diff --git a/build_scripts/Debian/README b/build_scripts/Debian/README new file mode 100644 index 000000000..b821c1d2e --- /dev/null +++ b/build_scripts/Debian/README @@ -0,0 +1,5 @@ +Packing building for Ubuntu 32bits and 64bits +============================================= + +Just type 'sudo ./make.sh', and follow the instructions from the script . + diff --git a/build_scripts/Debian/make.sh b/build_scripts/Debian/make.sh new file mode 100755 index 000000000..ce89ad94a --- /dev/null +++ b/build_scripts/Debian/make.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# @author Cyril Soler, Thomas Eimers + +###################### PARAMETERS #################### +version="0.5.1b" +arch=`dpkg --print-architecture` +packager="Thomas Eimers " +###################################################### + +echo attempting to get svn revision number... +svn=`svn info | grep 'Revision:' | cut -d\ -f2` +echo done. +version="$version"."$svn" +pkgname=RetroShare_"$version"_debian_"$arch".deb + +echo Building retroshare debian package version $version for Debian $arch. +echo Please check that: +echo " "- you have sudo access and that root has right to write in this directory and the subdirectories. +echo " "- you have compiled libretroshare and retroshare-gui in ../../libretroshare/src/ +echo " "and ../../retroshare-gui/src/ +echo " "- you have updated version numbers in ../../retroshare-gui/src/util/rsversion.cpp +echo " "and ../../retroshare-gui/src/retroshare.nsi +echo " "- version and name will be: $pkgname + +if ! test `whoami` = "root" ; then + echo Please run this script as root. + echo + exit ; +fi + +echo +echo Press [ENTER] when ok, else quit with Ctrl+C. +read tmp + +echo +echo Unzipping... +tar zxvf retroshare.tgz +echo Changing ownership... +chown -R root.root retroshare + +# setup version numbers and arch in DEBIAN/control + +echo Setting up version numbers... +cat retroshare/DEBIAN/control | sed -e s/XXXXXX/"$version"/g | sed -e s/YYYYYY/"$arch"/g | sed -e s/ZZZZZZ/"$packager"/g > retroshare/DEBIAN/control.tmp +mv retroshare/DEBIAN/control.tmp retroshare/DEBIAN/control + +# clean +find retroshare -name "*~" -exec \rm -f {} \; + +# copy executables at the right place +if ! test -f ../../retroshare-gui/src/RetroShare; then + echo Can not find executable ../../retroshare-gui/src/RetroShare. Please fix this. + echo + exit ; +fi +#if ! test -f ../../retroshare-nogui/src/retroshare-nogui; then +# echo Can not find executable ../../retroshare-nogui/src/retroshare-nogui. Please fix this. +# echo +# exit ; +#fi + +echo Stripping executables... +cp ../../retroshare-gui/src/RetroShare retroshare/usr/bin/ +strip retroshare/usr/bin/RetroShare +#cp ../../retroshare-nogui/src/retroshare-nogui retroshare/usr/bin/ +#strip retroshare/usr/bin/retroshare-nogui + +# compute md5 sums +echo Computing/setting md5 sums... +cd retroshare +find usr -type f -exec md5sum {} \; > DEBIAN/md5sums +cd .. +echo Creating package $pkgname +dpkg-deb -b retroshare $pkgname + +# cleaning +echo Cleaning up... +\rm -rf retroshare + +echo Done. diff --git a/build_scripts/Debian/retroshare.tgz b/build_scripts/Debian/retroshare.tgz new file mode 100644 index 000000000..dd80240f4 Binary files /dev/null and b/build_scripts/Debian/retroshare.tgz differ diff --git a/build_scripts/OSX/OSX_RS_Compilation_Instructions.txt b/build_scripts/OSX/OSX_RS_Compilation_Instructions.txt new file mode 100644 index 000000000..684c45f3e --- /dev/null +++ b/build_scripts/OSX/OSX_RS_Compilation_Instructions.txt @@ -0,0 +1,66 @@ + +Mac OSX Build Instructions. +------------------------------------------- + +There are several complications with building Retroshare under OSX. + 1) Support Libraries must be built and installed seperately. + 2) Universal and OSX 10.5 support is a little tricky, mainly due to the support libraries. + +Additional Libraries +--------------------- + + * GnuPG Package, that comes with Retroshare OSX install image. (GnuPG-1.4.9.dmg) + +GPG Development libraries + * libassuan (I'm using 2.0.1) + * libgpg-error (I'm using 1.9) + * libgpgme (I'm using 1.3.0) + +These libraries use standard UNIX installation systems: AUTOCONF/AUTOMAKE (configure, make, etc) +Unfortunately, this makes it difficult and a little manual to compile Universal and 10.5 libraries. + +UPNPC (for OSX and windows) + * miniupnpc (I'm using 1.0) + +You will also need to install + * XCode (available on the Apple Install CDs) + * Qt4 (from trolltech.com) + +First Compilation... +-------------------- + +The First challenge is to build Retroshare on your Mac. For this first compilation, +we only build for your specific machine, and not attempt a Generic / 10.5 / Univeral build. + + +1) Install / Compile all the packages listed above. + be sure to use a configure command like this where applicable to only create a static library. + ./configure --enable-static=yes --enable-shared=no CFLAGS="-arch i386" CPPFLAGS="-arch i386" + +2) Check out the Retroshare SVN. + +3) compile libbitdht: + cd libbitdht/src + qmake + + This recreates a xcodeproj file for compilation using XCode. + Open with Xcode, and build. + +4) compile libretroshare: same way. +5) compile retroshare-gui: same way. + + +Creating Retroshare OSX Distribution Packages. +----------------------------------------------- + TODO, once I've got feedback on First Compilation! + + + + + + + + + + + diff --git a/build_scripts/Ubuntu/README b/build_scripts/Ubuntu/README new file mode 100644 index 000000000..b821c1d2e --- /dev/null +++ b/build_scripts/Ubuntu/README @@ -0,0 +1,5 @@ +Packing building for Ubuntu 32bits and 64bits +============================================= + +Just type 'sudo ./make.sh', and follow the instructions from the script . + diff --git a/build_scripts/Ubuntu/make.sh b/build_scripts/Ubuntu/make.sh new file mode 100755 index 000000000..41a497058 --- /dev/null +++ b/build_scripts/Ubuntu/make.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +###################### PARAMETERS #################### +version="0.4.12" +arch=`dpkg --print-architecture` +packager="Cyril Soler " +###################################################### + +echo attempting to get svn revision number... +svn=`svn info | grep 'Revision:' | cut -d\ -f2` +echo done. +version="$version"."$svn" +pkgname=RetroShare_"$version"_ubuntu_"$arch".deb + +echo Building retroshare debian package version $version for Ubuntu $arch. +echo Please check that: +echo " "- you have sudo access and that root has right to write in this directory and the subdirectories. +echo " "- you have compiled libretroshare and retroshare-gui in ../../libretroshare/src/ +echo " "and ../../retroshare-gui/src/ +echo " "- you have updated version numbers in ../../retroshare-gui/src/util/rsversion.cpp +echo " "and ../../retroshare-gui/src/retroshare.nsi +echo " "- version and name will be: $pkgname + +if ! test `whoami` = "root" ; then + echo Please run this script as root. + echo + exit ; +fi + +echo +echo Press [ENTER] when ok, else quit with Ctrl+C. +read tmp + +echo +echo Unzipping... +tar zxvf retroshare.tgz +echo Changing ownership... +chown -R root.root retroshare + +# setup version numbers and arch in DEBIAN/control + +echo Setting up version numbers... +cat retroshare/DEBIAN/control | sed -e s/XXXXXX/"$version"/g | sed -e s/YYYYYY/"$arch"/g | sed -e s/ZZZZZZ/"$packager"/g > retroshare/DEBIAN/control.tmp +mv retroshare/DEBIAN/control.tmp retroshare/DEBIAN/control + +# clean +find retroshare -name "*~" -exec \rm -f {} \; + +# copy executables at the right place +if ! test -f ../../retroshare-gui/src/RetroShare; then + echo Can not find executable ../../retroshare-gui/src/RetroShare. Please fix this. + echo + exit ; +fi +if ! test -f ../../retroshare-nogui/src/retroshare-nogui; then + echo Can not find executable ../../retroshare-nogui/src/retroshare-nogui. Please fix this. + echo + exit ; +fi + +echo Stripping executables... +cp ../../retroshare-gui/src/RetroShare retroshare/usr/bin/ +strip retroshare/usr/bin/RetroShare +cp ../../retroshare-nogui/src/retroshare-nogui retroshare/usr/bin/ +strip retroshare/usr/bin/retroshare-nogui + +# compute md5 sums +echo Computing/setting md5 sums... +cd retroshare +find usr -type f -exec md5sum {} \; > DEBIAN/md5sums +cd .. +echo Creating package $pkgname +dpkg-deb -b retroshare $pkgname + +# cleaning +echo Cleaning up... +\rm -rf retroshare + +echo Done. diff --git a/build_scripts/Ubuntu/retroshare.tgz b/build_scripts/Ubuntu/retroshare.tgz new file mode 100644 index 000000000..48f29aa6f Binary files /dev/null and b/build_scripts/Ubuntu/retroshare.tgz differ diff --git a/build_scripts/Ubuntu_src/BaseRetroShareDirs.tgz b/build_scripts/Ubuntu_src/BaseRetroShareDirs.tgz new file mode 100644 index 000000000..1b15d92ad Binary files /dev/null and b/build_scripts/Ubuntu_src/BaseRetroShareDirs.tgz differ diff --git a/build_scripts/Ubuntu_src/README.txt b/build_scripts/Ubuntu_src/README.txt new file mode 100644 index 000000000..23846b595 --- /dev/null +++ b/build_scripts/Ubuntu_src/README.txt @@ -0,0 +1,9 @@ +This directory contains the material for buildign a debian/ubuntu source package from +the svn repository of RetroShare. The various files here are: + + BaseRetroShareDirs.tgz: basic directory structure. Does not contain any source file. + makeSourcePackage.sh : main script. Produces source binary debian package (.dsc+.tgz files) + from the base directory structure and the sources in the svn repository. + clean.sh : compiles the source package. Produce a binary pkg for a given ubuntu distribution + make_tgz.sh : rebuilds the basic directory structure if some config/debian files where modified + in the retroshare-0.5 directory diff --git a/build_scripts/Ubuntu_src/changelog b/build_scripts/Ubuntu_src/changelog new file mode 100644 index 000000000..f3179af13 --- /dev/null +++ b/build_scripts/Ubuntu_src/changelog @@ -0,0 +1,196 @@ +retroshare (0.5.1-0.XXXXXX~YYYYYY) YYYYYY; urgency=low + + * Improvements + - Updated tests for tcponudp. + + * Bug fixes + - fixed bug in search with size in MB. Caused crash due to deserialization error. + - Added Check for the existance of each Cache File before that are passed on the loader. + This should once and for-all remove the copy file warnings + + -- Cyril Soler Tue, 28 Jun 2011 19:35:46 +0100 + +retroshare (0.5.1-0.4337~lucid) lucid; urgency=low + + * Bug fixes + - Fixed the cache transfer killing bug (misplaced brackets) + - Fixed bug in pqissl wrongly casting a pointer to unsigned long, possibly impacting 64bit systems + - Fixed bug responsible for corrupting large packets. Solved the chat bug, + the errors in GetTlvString, the corrupted exchange of keys, location names, etc. + + -- Cyril Soler Sat, 25 Jun 2011 19:35:46 +0100 + +retroshare (0.5.1-0.4331~lucid) lucid; urgency=low + + * Improvements + - Started dev of plugin system. Works on linux, not yet on windows. + - Added gui for plugins in Settings + - Ported LinksCloud service as a plugin + - Improvement of the unit tests, and coverage calculations. + - Hash cache: missing root directories are not discarded anymore, but kept empty, + unless the user really removes them explicitely. + - Reworked settings dialog + - Automatic add the recommended friend(s) as CC in the MessageComposer. + - Send plain text message instead of html, when the text contains no html specifics. + This is a huge gain in forum posts size, up to a factor of 50 + - Enabled Spanish translation + - Moved the fill function of the ForumsDialog to a QThread. + - Made multiple keyword search use an AND instead of an OR. + + * Bug fixes + - Fixed display of upload transfers + - Fixed the Missing Cache File bug. + - Added Old Cache Storage... so these can be retrieved. + - Connected up the CancelCacheFile() -> FileCancel. + - Removed "ipaddr=1" bug + - Fixed uninitialized value in p3turtle + - Fixed html title bug in forum message when answering from news feed + - Fixed reaction of the checkbox "web of trust" + - Fixed calculation of the unread messages in MessagesDialog + - Corrected bug that would wipe out the hash cache file every other start + - Fixed crash in ForumsDialog + - Fixed memory leak of the fill thread of the history browser + - Fixed refill of the threads tree after receiving a new message. Now the new message is expanded. + + -- Cyril Soler Mon, 11 Apr 2010 21:35:46 +0100 + +retroshare (0.5.1-0.4239~lucid) lucid; urgency=low + + * Improvements + - Optimized the functions for the forum messages. + - added a star functionality to forums + - placed private message editing into a separate window + - added a tab to graphically display turtle router statistics + - added automatic handling of turtle requests/search conjestion cases + - patched for compilation on OpenSuze11.4 + - put links to peer and signers in certificate dialog + - updated french translation + - added copy/paste functionality of RS links to friends keys + - various GUI tweaks + - added to RetroShare Help page noew commands entry for "-r retroshare://..." + - added history cache optimisation to subscribed/client groups (functionality is now disabled) + - Added new RetroShare link format to write a message retroshare://message?id=...[&subject=...] + - Added new RetroShare link format to start a search retroshare://search?keywords=... + - Enabled on Private Chat to display for the status string smileys, when there is smiley codes used. + + * Bug fixes + - Channels: Fixed bug related to opening cache hist file in text mode for windows + - Chat: Sending large messages now works, thanks to RsChatMsgItem splitting (not 100% backward compatible, but avoids crashing) + - Chat: Removed crash due to dynamic_cast onto a deleted pointer. + - Dbase: Removed the difference of the separator for Linux and Windows. + - Dbase: Removed extra "/" of the filename (e.g. "E://") of the hashed file when sharing a whole drive. + - Forums: Fixed drag and drop of files to a forum message with utf8 chars. + - General: Fixed recommend friend. + - Search: Fixed sorting by date in search + + -- Cyril Soler Mon, 11 Apr 2010 21:35:46 +0100 + +retroshare (0.5.1-0.4179~lucid) lucid; urgency=low + + * Improvements + - updated packaging for ubuntu natty, removed dependency on qt4-opengl + - updated french/german translations + - updated icons + - enabled drag and drop of directories in share manager + + * Bug fixes + - suppred unwanted apparence of channel source id as channel source + - improved strategy for cleaning stalled cache transfers + - fixed leaking of sources in channel posts + + -- Cyril Soler Mon, 11 Apr 2010 21:35:46 +0100 + +retroshare (0.5.1-0.4166~lucid) lucid; urgency=low + + * Improvements + - made flat view for shared files less CPU demanding + - added automated treatment of RS links from web browser + + * Bug fixes + - removed potential segfault when decrypting cache file + + -- Cyril Soler Mon, 11 Apr 2010 21:35:46 +0100 + +retroshare (0.5.1-0.4154~lucid) lucid; urgency=low + + * Improvements + - added flat view for shared files, with search, sorting and temporised update + - enabled file preview for partially downloaded files, for non windows users + - removed display of directories from search + - added auto-download option to channels + - added random bias to turtle search and tunnels at maximum depth, to prevent security issues + - added biased rerouting of tunnels requests to statistically optimize tunnel length + - made sign GPG button disabled by default + - optimized lookups of/into FileEntry structures (faster, better memory coalescence) + - added tunning for auto-check of shared directories, in config + - updated french/german translations + - saved the visible state of the avatar picture in private chat for the friend. + - removed own settings for news feed + - added tooltip for systray to display nickname and location + - made lock file warning more explicit + + * Bug fixes + - channel download is now called only once for each channel post + - fixed cleaning issue of certificates. Added a button in cert dialog for cleaning. + - removed automatic cleaning of certs. + - fixed bug with utf8 chatacters in %appdata% paths on windows + - fixed crash on shutdown when the cache loading is running + - fixed some stylesheets to use gradients instead of a background images, + - fixed thread leak in file checking due to not calling pthread_join() on finished thread + - showing uploads by default, instead of current transfer + + -- Cyril Soler Mon, 11 Apr 2010 21:35:46 +0100 + +retroshare (0.5.1-0.4097~lucid) lucid; urgency=low + + * Improvements + - attempt to make GPG errors more verbose at cert exchange time + - translate QuickStartWizard, GenCertDialog and StartDialog into german + - fixed tab order of the upload and download settings in QuickStartWizard + - Added a basic description of the chat style + - Added share incoming directory to the QuickStartWizard, while keeping + the Download directory shared by default + + * Bug Fixes + - implemented a backward compatible fix for advance searching with size + larger than 2Gb + - implemented a better management of tunnel requests + + + -- Cyril Soler Thu, 07 Mar 2010 21:35:46 +0100 + +retroshare (0.5.1-0.4087~lucid) lucid; urgency=low + + * Improvements + - The working (hashing) thread FileIndexMonitor is now stopped when RetroShare is closed. + - Removed tab focus from the toolbar and image buttons. + - Fixed german translation. + + * Bug Fixes: + - Fixed a toolbar icon to display with a correct size on macosx + - Added missing return... which was causing crash at start during directory creation. + - Supressed memory leak due to not deleting a RsItem + - Suppressed potential SIGSEGV as exit time + + -- Cyril Soler Thu, 07 Mar 2010 21:35:46 +0100 + +retroshare (0.5.1-0.4069~lucid) lucid; urgency=low + + * Improvements: + - Added a confirm to the delete history action. + - Added the RetroShare icon to the password input window. + - Added display of number of intermediate tunnels, and limited the number of displayed tunnel requests + + * Bug Fixes: + - Fixed potential SIGSEGV because of not checking returned pointer in DHT code. + - Fixed memory leak in GUI responsible for high leaks in large networks. + - Fixed memory leak in p3distrib + + -- Cyril Soler Thu, 28 Feb 2010 21:35:46 +0100 + +retroshare (0.5.1-0.4059~lucid) lucid; urgency=low + + * Release 0.5.1: + New features (DHT, Channels, Network View), Improved stability w.r.t. previous version 0.5.0g + + -- Cyril Soler Thu, 24 Feb 2010 21:35:46 +0100 diff --git a/build_scripts/Ubuntu_src/clean.sh b/build_scripts/Ubuntu_src/clean.sh new file mode 100755 index 000000000..21993af4c --- /dev/null +++ b/build_scripts/Ubuntu_src/clean.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +rm ./retroshare_0.5.1-0.*_source.build +rm ./retroshare_0.5.1-0.*_source.changes +rm ./retroshare_0.5.1-0.*.tar.gz +rm ./retroshare_0.5.1-0.*.diff.gz +rm ./retroshare_0.5.1-0.*.dsc + +rm *~ +find . -name "*~" -exec rm {} \; + diff --git a/build_scripts/Ubuntu_src/cleanProFile.sh b/build_scripts/Ubuntu_src/cleanProFile.sh new file mode 100755 index 000000000..e6e03a907 --- /dev/null +++ b/build_scripts/Ubuntu_src/cleanProFile.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +tmpfile=/tmp/toto42314321 + +cat "$1" | grep -v "CONFIG += version_detail_bash_script" > $tmpfile +echo "INCLUDEPATH += ../libretroshare" > $1 +cat $tmpfile >> $1 + diff --git a/build_scripts/Ubuntu_src/make.sh b/build_scripts/Ubuntu_src/make.sh new file mode 100755 index 000000000..ec627df26 --- /dev/null +++ b/build_scripts/Ubuntu_src/make.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +echo This script will +echo - remove the directory retroshare-0.5/ +echo - remove existing sources packages in the current directory +echo - build a new source package from the svn +echo - rebuild the source package for the karmic i386 arch. +echo + +echo attempting to get svn revision number... +svn=`svn info | grep 'Revision:' | cut -d\ -f2` +echo Revision number is $svn. + +echo Type ^C to abort, or enter to continue +read tmp + +svn=4153 +rm -rf ./retroshare-0.5 +# ./makeSourcePackage.sh + +for dist in jaunty karmic lucid maverick natty; do + sudo PBUILDFOLDER=/var/cache/pbuilder pbuilder-dist "$dist" build retroshare_0.5.1-0."$svn"~"$dist".dsc + cp /var/cache/pbuilder/"$dist"_result/retroshare_0.5.1-0."$svn"~"$dist"_amd64.deb . + sudo PBUILDFOLDER=/var/cache/pbuilder pbuilder-dist "$dist" i386 build retroshare_0.5.1-0."$svn"~"$dist".dsc + cp /var/cache/pbuilder/"$dist"-i386_result/retroshare_0.5.1-0."$svn"~"$dist"_i386.deb . +done + diff --git a/build_scripts/Ubuntu_src/makeSourcePackage.sh b/build_scripts/Ubuntu_src/makeSourcePackage.sh new file mode 100755 index 000000000..15a036735 --- /dev/null +++ b/build_scripts/Ubuntu_src/makeSourcePackage.sh @@ -0,0 +1,114 @@ +#!/bin/sh + +echo This script is going to build the debian source package for RetroShare, from the svn. + +if test -d "RetroShare" ; then + echo Please remove the RetroShare/ directory first. + exit +fi + +svn update + +###################### PARAMETERS #################### +version="0.5.1" +###################################################### + +if test "$1" = "" ; then + echo attempting to get svn revision number... + svn=`svn info | grep 'Revision:' | cut -d\ -f2` +else + echo svn number has been provided. Forcing update. + svn="$1" +fi + +echo done. +version="$version"."$svn" +echo got version number $version. +echo Please check that the changelog is up to date. +echo Hit ENTER is this is this correct. Otherwise hit Ctrl+C +read tmp + +packages="." + +echo SVN number is $svn +echo version is $version + +echo Extracting base archive... +tar zxvf $packages/BaseRetroShareDirs.tgz 2> /dev/null + +echo Checking out latest snapshot in libbitdht... +cd retroshare-0.5/src/libbitdht/ +svn co -r$svn https://retroshare.svn.sourceforge.net/svnroot/retroshare/trunk/libbitdht/src . 2> /dev/null +cd ../../.. +# +echo Checking out latest snapshot in libretroshare... +cd retroshare-0.5/src/libretroshare/ +svn co -r$svn https://retroshare.svn.sourceforge.net/svnroot/retroshare/trunk/libretroshare/src . 2> /dev/null +cd ../../.. +# +echo Checking out latest snapshot in retroshare-gui... +cd retroshare-0.5/src/retroshare-gui/ +svn co -r$svn https://retroshare.svn.sourceforge.net/svnroot/retroshare/trunk/retroshare-gui/src . 2> /dev/null +cd ../../.. +# +echo Checking out latest snapshot in retroshare-nogui... +cd retroshare-0.5/src/retroshare-nogui/ +svn co -r$svn https://retroshare.svn.sourceforge.net/svnroot/retroshare/trunk/retroshare-nogui/src . 2> /dev/null +cd ../../.. + +echo Copying bdboot.txt file at installation place +cp retroshare-0.5/src/libbitdht/bitdht/bdboot.txt +echo Setting version numbers... + +# setup version numbers +cat retroshare-0.5/src/libretroshare/util/rsversion.h | grep -v SVN_REVISION > /tmp/toto2342 +echo \#define SVN_REVISION \"Revision: "$version" date : `date`\" >> /tmp/toto2342 +cp /tmp/toto2342 retroshare-0.5/src/libretroshare/util/rsversion.h + +cat retroshare-0.5/src/retroshare-gui/util/rsversion.h | grep -v GUI_REVISION > /tmp/toto4463 +echo \#define GUI_REVISION \"Revision: "$version" date : `date`\" >> /tmp/toto4463 +cp /tmp/toto4463 retroshare-0.5/src/retroshare-gui/util/rsversion.h + +# Various cleaning + +echo Cleaning... +find retroshare-0.5 -name ".svn" -exec rm -rf {} \; # remove all svn repositories + +echo Preparing package +mv retroshare-0.5/src/retroshare-gui/RetroShare.pro retroshare-0.5/src/retroshare-gui/retroshare-gui.pro + +./cleanProFile.sh retroshare-0.5/src/libretroshare/libretroshare.pro +./cleanProFile.sh retroshare-0.5/src/retroshare-gui/retroshare-gui.pro +./cleanProFile.sh retroshare-0.5/src/retroshare-nogui/retroshare-nogui.pro + +echo "DESTDIR = ../../libretroshare/src/lib/" > /tmp/toto75299 +cat retroshare-0.5/src/libretroshare/libretroshare.pro /tmp/toto75299 > /tmp/toto752992 +cp /tmp/toto752992 retroshare-0.5/src/libretroshare/libretroshare.pro + +echo "DESTDIR = ../../libbitdht/src/lib/" > /tmp/toto75299 +cat retroshare-0.5/src/libbitdht/libbitdht.pro /tmp/toto75299 > /tmp/toto752992 +cp /tmp/toto752992 retroshare-0.5/src/libbitdht/libbitdht.pro + +#cat retroshare-gui-ext.pro >> retroshare-0.5/src/retroshare-gui/retroshare-gui.pro + +#echo Building orig directory... +#mkdir retroshare-0.5.orig +#cp -r retroshare-0.5/src retroshare-0.5.orig + +# Call debuild to make the source debian package + +echo Calling debuild... +cat retroshare-0.5/debian/control | sed -e s/XXXXXX/"$version"/g > retroshare-0.5/debian/control.tmp +mv -f retroshare-0.5/debian/control.tmp retroshare-0.5/debian/control + +cd retroshare-0.5 + +for i in lucid karmic jaunty maverick natty; do + echo copying changelog for $i + cat ../changelog | sed -e s/XXXXXX/"$svn"/g | sed -e s/YYYYYY/"$i"/g > debian/changelog + + # This is the key for "Cyril Soler " + debuild -S -kC737CA98 +done + + diff --git a/build_scripts/Ubuntu_src/make_tgz.sh b/build_scripts/Ubuntu_src/make_tgz.sh new file mode 100755 index 000000000..37acdba19 --- /dev/null +++ b/build_scripts/Ubuntu_src/make_tgz.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +rm BaseRetroShareDirs.tgz + +rm -rf retroshare-0.5/libbitdht/ +rm -rf retroshare-0.5/libretroshare/ + +rm -rf retroshare-0.5/src/libbitdht/* +rm -rf retroshare-0.5/src/libbitdht/.svn/ +rm -rf retroshare-0.5/src/libretroshare/* +rm -rf retroshare-0.5/src/libretroshare/.svn/ +rm -rf retroshare-0.5/src/retroshare-gui/* +rm -rf retroshare-0.5/src/retroshare-gui/.svn/ +rm -rf retroshare-0.5/src/retroshare-nogui/* +rm -rf retroshare-0.5/src/retroshare-nogui/.svn/ + +find retroshare-0.5 -name "*~" -exec \rm {} \; + +tar zcvf BaseRetroShareDirs.tgz retroshare-0.5/ + +if ! test -f BaseRetroShareDirs.tgz; then + echo BaseRetroShareDirs.tgz could not be created + exit; +fi + +rm -rf retroshare-0.5/ + + diff --git a/build_scripts/Ubuntu_src/ppa_upload.sh b/build_scripts/Ubuntu_src/ppa_upload.sh new file mode 100644 index 000000000..db89c7a40 --- /dev/null +++ b/build_scripts/Ubuntu_src/ppa_upload.sh @@ -0,0 +1,2 @@ +#!/bin/sh +dput ppa:csoler-users/ppa retroshare_0.5-1_source.changes diff --git a/build_scripts/Ubuntu_src/retroshare_ppastatistics.py b/build_scripts/Ubuntu_src/retroshare_ppastatistics.py new file mode 100755 index 000000000..e6831d788 --- /dev/null +++ b/build_scripts/Ubuntu_src/retroshare_ppastatistics.py @@ -0,0 +1,32 @@ +#!/usr/bin/python + +# Requires packages +# python-launchpad-integration +# python-launchpadlib + +from launchpadlib.launchpad import Launchpad +PPAOWNER = "csoler-users" #the launchpad PPA owener. It's usually the first part of a PPA. Example: in "webupd8team/vlmc", the owener is "webupd8team". + +distribs = ['jaunty','karmic','lucid','maverick','natty'] +archs = ['i386','amd64'] +ppas = ['retroshare','retroshare-snapshots'] +total = 0 + + +for PPA in ppas: + for distrib in distribs: + for arch in archs: + desired_dist_and_arch = 'https://api.edge.launchpad.net/devel/ubuntu/' + distrib + '/' + arch + #here, edit "maverick" and "i386" with the Ubuntu version and desired arhitecture + + cachedir = "~/.launchpadlib/cache/" + lp_ = Launchpad.login_anonymously('ppastats', 'edge', cachedir, version='devel') + owner = lp_.people[PPAOWNER] + archive = owner.getPPAByName(name=PPA) + + for individualarchive in archive.getPublishedBinaries(status='Published',distro_arch_series=desired_dist_and_arch): + print PPA + "\t" + arch + "\t" + individualarchive.binary_package_version + "\t" + str(individualarchive.getDownloadCount()) + total += individualarchive.getDownloadCount() + +print "Total downloads: " + str(total) + diff --git a/build_scripts/Windows/compilingForWindows.txt b/build_scripts/Windows/compilingForWindows.txt new file mode 100644 index 000000000..963f24107 --- /dev/null +++ b/build_scripts/Windows/compilingForWindows.txt @@ -0,0 +1,224 @@ + +Compling for Windows. +----------------------------------- +For Version V0.5.0+ we are switching to GPGme libraries. +This documents a clean compilation of V0.5 for Windows. + +Tested on: WinXP July 2009. + +You will need: + * Qt4.5 Development Libraries (from TrollTech) + * MinGw/MinSys full installation (from sourceforge.net) + * Cygwin (for OpenSSL compilation / SVN / Unix Tools) + * OpenSSL standard libraries. + * GPG Windows Install (includes gpg.exe) + * MiniUpnp library + * gpgme Library. + * libgpg-error Library. + + +This compilation is a little tricky as different environments +are needed to compile different libraries. +a) Cygwin: libssl.a libcrypto.a +b) MinGW/MSYS: libgpg-error, libgpgme.a, libretroshare.a, libminiupnp.a +c) Qt/MinGW: Retroshare.exe + + +/***************** Installation of Development Tools **************/ +In this section we install: cygwin, mingw/msys and Qt4.5 + +1) Install Cygwin + a) download the installer and run. + b) be sure to select from the development packages: + * mingw + * svn + * gcc/gdb + * make + links: + http://www.cygwin.org/ + +2) install the MinGW/Msys package. + a) Download MinGW-5.1.4 installer and run. + b) Download MSYS-1.0.11 installer and run. + + links: + http://downloads.sourceforge.net/mingw/MinGW-5.1.4.exe + http://downloads.sourceforge.net/mingw/MSYS-1.0.11.exe + http://www.mingw.org/ + http://sourceforge.net/projects/mingw/files/ + +3) Install Qt4.5 LGPL Version. (Qt SDK 2009.03) + a) Download from website and run. + b) Select all options (including MinGW) + + links: + http://www.qtsoftware.com/downloads + +/***************** Installation of Development Tools **************/ +/******************* Compiling Support Libraries ******************/ + +1) Compile OpenSSL using Cygwin. + a) launch cygwin xterm + b) untar openssl source package. + c) Configure mingw + d) make. + +2) Compile gpg-error + a) Download from gpg + b) load up MinGW/MSYS Bash shell. + c) extract code. + d) configure + e) make + f) make install + + The library will end up in /local/lib + +3) Compile gpgme + a) Download from gpg + b) load up MinGW/MSYS Bash shell. + c) extract code. + d) configure + e) make + f) make install + + The library will end up in /local/lib + + +4) Compile MiniUPnP. + up to release v1.3 now. + links: + http://miniupnp.free.fr/ + http://miniupnp.free.fr/files/ + +5) Install pthreads + + links: + http://sourceware.org/pthreads-win32/ + ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.exe + +/******************* Compiling Support Libraries ******************/ +/*********************** Compiling Retroshare *********************/ + +1) Setup Source Code TAR (TODO: Update for windows). + This is useful as it provides a standard structure to work against, + we will update this with the required support libraries soon. + + a) Open MSYS Bash shell, and change to this location. + c:/msys/1.0/home/XXX/retroshare + b) create a working directory under this. + 1) c:/msys/1.0/home/XXX/miniupnpc-1.3 + 2) c:/msys/1.0/home/XXX/pthreads-w32-2-8-0-release + 3) c:/msys/1.0/home/XXX/zlib-1.2.3 + 4) c:/msys/1.0/home/XXX/gpgme-1.1.8 + 5) c:/msys/1.0/home/XXX/libgpg-error-1.7 + c) Install OpenSSL to this directory (get from http://www.slproweb.com/download/Win32OpenSSL-0_9_8k.exe) + 1) c:/msys/1.0/home/XXX/OpenSSL + d) get the latest svn trunk and unzip to (get from http://retroshare.svn.sourceforge.net/viewvc/retroshare/trunk.tar.gz) . + 1) c:/msys/1.0/home/XXX/retroshare + +2) Compile libretroshare + a) change to the libretroshare directory. + 1) cd c:/msys/1.0/home/XXX/retroshare/libretroshare/src + b) modify support directory paths to point at correct locations. + 1) open scripts/config.mk and enable OS = Win # MinGw. + 2) open scripts/config-mingw.mk + 3) disable lines (line 20-29) + 4) enable lines 34-42 and 118-119 + #### Enable this section for compiling with MSYS/MINGW compile + SRC_ROOT=/home/linux + + SSL_DIR=$(SRC_ROOT)/OpenSSL + GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 + GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 + + ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 + UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 + PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release + + ### Enable this for GPGME and GPG ERROR dirs + CFLAGS += -I$(GPGME_DIR)/src + CFLAGS += -I$(GPG_ERROR_DIR)/src + 5) Edit your SRC_ROOT to your /home/xxxx dir + + + c) compile libretroshare + 1) make + +3) Copy all the required support libraries into the library directory: + c:/msys/1.0/home/XXX/lib + + This should include: + + gpg-error / gpgme libraries: + libgpg-error.a + libgpg-error.dll.a + libgpg-error.la + libgpgme.dll.a + libgpgme.la + + openssl libraries: + libcrypto.a + libssl.a + + miniupnpc / pthreads / libz + + libminiupnpc.a + miniupnpc.dll + libpthreadGCE2.a + pthreadGCE2.dll + libz.a + + extra library from cygwin. (renamed from libcrypt32.a) + libcrypt32-cygwin.a + + libretroshare + libretroshare.a + + +4) Compile GUI. + +/*********************** Compiling Retroshare *********************/ +/************************ Running Retroshare **********************/ + +1) Collect Relevant DLL's with Application. + a) make retroshare application directory. + b) copy Retroshare.exe executable into directory. + c) Copy required DLL's into that directory. + These include: + + mingw runtime: + mingwm10.dll + + gpgme/gpg-error: + libgpg-error-0.dll + libgpgme-11.dll + + other support libraries: + miniupnpc.dll + pthreadGCE2.dll + + Qt DLLs: + QtCore4.dll, + QtGui4.dll,... + etc. + + d) You should be able to run Retroshare from this directory now! + +2) Install gpg4win package... for gpg.exe + +3) Create an OpenGPG identity using gpa or Enigmail or other PGP tool. + +4) You should be able to use Retroshare on your PC now. + +/************************ Running Retroshare **********************/ +/******************************** FAQs ****************************/ +Ask and it might be answered! +/******************************** FAQs ****************************/ + +This is obviously a work in progress - +drBob. + + + + + diff --git a/build_scripts/Windows/make_installer.sh b/build_scripts/Windows/make_installer.sh new file mode 100755 index 000000000..6b3b5766a --- /dev/null +++ b/build_scripts/Windows/make_installer.sh @@ -0,0 +1,46 @@ +#!/bin/sh +### +# +# +# + +QTGUI_DIR=../devel/retroshare-package-v0.4.09b/src/svn-retroshare/retroshare-gui/src +INST_DIR=../devel/retroshare-package-v0.4.09b/src/svn-retroshare/build_scripts/Windows/ +EXEC=release/Retroshare.exe + +BIN_DIR=./release +NSIS_EXE="/cygdrive/c/Program\ Files/NSIS/makensis.exe" + +cp $QTGUI_DIR/$EXEC $BIN_DIR +echo cp $QTGUI_DIR/$EXEC $BIN_DIR + +# copy skin files. +cp -r $QTGUI_DIR/qss/* $BIN_DIR/qss +echo 'cp -r $QTGUI_DIR/qss/* $BIN_DIR/qss' +# +cp -r $QTGUI_DIR/skin/* $BIN_DIR/skin +echo 'cp $QTGUI_DIR/skin/* $BIN_DIR/skin' +# +cp -r $QTGUI_DIR/emoticons/* $BIN_DIR/emoticons/ +echo cp -r $QTGUI_DIR/emoticons/* $BIN_DIR/emoticons/ + +cp -r $QTGUI_DIR/style/* $BIN_DIR/style +echo 'cp -r $QTGUI_DIR/style/* $BIN_DIR/style' + +./stripSVN.sh release +echo ./stripSVN.sh release + +cp $INST_DIR/retroshare.nsi ./ +echo cp $QTGUI_DIR/retroshare.nsi ./ + +cp $QTGUI_DIR/license/* ./license/ +echo cp $QTGUI_DIR/license/* ./license/ + +cp $QTGUI_DIR/gui/images/splash.bmp ./gui/images/ +echo cp $QTGUI_DIR/gui/images/splash.bmp ./gui/images/ + +#cp $QTGUI_DIR/release/changelog.txt ./release/changelog.txt +#echo cp $QTGUI_DIR/release/changelog.txt ./release/changelog.txt + +"/cygdrive/c/Program Files/NSIS/makensis.exe" retroshare.nsi +#$NSIS_EXE retroshare.nsi diff --git a/build_scripts/Windows/retroshare.nsi b/build_scripts/Windows/retroshare.nsi new file mode 100644 index 000000000..b1e4ffcb3 --- /dev/null +++ b/build_scripts/Windows/retroshare.nsi @@ -0,0 +1,390 @@ +; Script generated with the Venis Install Wizard & modified by defnax + +; Define your application name +!define APPNAME "RetroShare" +!define VERSION "0.4.13c" +!define APPNAMEANDVERSION "${APPNAME} ${VERSION}" + +; Main Install settings +Name "${APPNAMEANDVERSION}" +InstallDir "$PROGRAMFILES\RetroShare" +InstallDirRegKey HKLM "Software\${APPNAME}" "" +OutFile "RetroShare_${VERSION}_setup.exe" +BrandingText "${APPNAMEANDVERSION}" +; Use compression +SetCompressor LZMA + +; Modern interface settings +!include Sections.nsh +!include "MUI.nsh" + +;Interface Settings +!define MUI_ABORTWARNING +;!define MUI_HEADERIMAGE +;!define MUI_HEADERIMAGE_BITMAP "retroshare.bmp" ; optional + +# MUI defines +!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico" +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_LICENSEPAGE_RADIOBUTTONS +!define MUI_COMPONENTSPAGE_SMALLDESC +!define MUI_FINISHPAGE_LINK "Visit the RetroShare forum for the latest news and support" +!define MUI_FINISHPAGE_LINK_LOCATION "http://retroshare.sourceforge.net/forum/" +!define MUI_FINISHPAGE_RUN "$INSTDIR\RetroShare.exe" +!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_TEXT changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico" +!define MUI_UNFINISHPAGE_NOAUTOCLOSE +!define MUI_LANGDLL_REGISTRY_ROOT HKLM +!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY} +!define MUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage + +;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without havinf to reboot your computer. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + +;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + + +; Defines the un-/installer logo of RetroShare +!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp" +!insertmacro MUI_DEFAULT MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp" + +; Set languages (first is default language) +!insertmacro MUI_RESERVEFILE_LANGDLL +ReserveFile "${NSISDIR}\Plugins\AdvSplash.dll" + +;-------------------------------- +;Configuration + + + ;!insertmacro MUI_RESERVEFILE_SPECIALBITMAP + + LicenseLangString myLicenseData 1033 "license\license.txt" + LicenseLangString myLicenseData 1031 "license\license-GER.txt" + LicenseLangString myLicenseData 1036 "license\license-FR.txt" + LicenseLangString myLicenseData 1055 "license\license-TR.txt" + LicenseLangString myLicenseData 2052 "license\license.txt" + LicenseLangString myLicenseData 1045 "license\license.txt" + + LicenseData $(myLicenseData) + +# Installer pages +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +# Installer languages +!define MUI_LANGDLL_ALLLANGUAGES + +!insertmacro MUI_LANGUAGE English +!insertmacro MUI_LANGUAGE German +!insertmacro MUI_LANGUAGE French +!insertmacro MUI_LANGUAGE Turkish +!insertmacro MUI_LANGUAGE SimpChinese +!insertmacro MUI_LANGUAGE Polish + + + ;Component-selection page + ;Titles + + LangString sec_main ${LANG_ENGLISH} "Program Files" + LangString sec_data ${LANG_ENGLISH} "Program Skins" + LangString sec_shortcuts ${LANG_ENGLISH} "Shortcuts" + LangString sec_link ${LANG_ENGLISH} "File Association" + LangString sec_autostart ${LANG_ENGLISH} "Auto Startup" + LangString DESC_sec_main ${LANG_ENGLISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_ENGLISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_ENGLISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_ENGLISH} "Associate RetroShare with .pqi file extension" + LangString DESC_sec_autostart ${LANG_ENGLISH} "Auto-Run and Login at Startup" + LangString LANGUAGEID ${LANG_ENGLISH} "1033" + + + LangString sec_main ${LANG_FRENCH} "RetroShare" + LangString sec_data ${LANG_FRENCH} "Programme de Skins" + LangString sec_shortcuts ${LANG_FRENCH} "Raccourcis" + LangString sec_link ${LANG_FRENCH} "RetroShare fichiers Association" + LangString sec_startmenu ${LANG_FRENCH} "Raccourcis du menu Démarrer" + LangString sec_autostart ${LANG_FRENCH} "Démarrage automatique" + LangString DESC_sec_main ${LANG_FRENCH} "Installe les fichiers du programme." + LangString DESC_sec_data ${LANG_FRENCH} "Installe RetroShare Skins" + LangString DESC_sec_startmenu ${LANG_FRENCH} "Crée les raccourcis du menu Démarrer" + LangString DESC_sec_shortcuts ${LANG_FRENCH} "Crée une icône sur le bureau." + LangString DESC_sec_link ${LANG_FRENCH} "Associate RetroShare with .pqi file extension" + LangString DESC_sec_autostart ${LANG_FRENCH} "Run and Auto-connexion au démarrage" + LangString LANGUAGEID ${LANG_FRENCH} "1036" + + + LangString sec_main ${LANG_GERMAN} "Programmdateien" + LangString sec_data ${LANG_GERMAN} "Skins f�r das Programm" + LangString sec_shortcuts ${LANG_GERMAN} "Shortcuts" + LangString sec_link ${LANG_GERMAN} "Dateiverkn�pfungen" + LangString sec_autostart ${LANG_GERMAN} "Auto Startup" + LangString DESC_sec_main ${LANG_GERMAN} "Installiert die erforderlichen Programmdateien." + LangString DESC_sec_data ${LANG_GERMAN} "Installiert RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_GERMAN} "Erstellt eine RetroShare Verkn�pfung im Startmen�, Desktop oder im Schnellstarter." + LangString DESC_sec_link ${LANG_GERMAN} "RetroShare mit .pqi Dateien verkn�pfen" + LangString DESC_sec_autostart ${LANG_GERMAN} "Beim Neustart automatisch RetroShare starten und sich anmelden" + LangString LANGUAGEID ${LANG_GERMAN} "1031" + + LangString sec_main ${LANG_TURKISH} "Program Dosyalar�" + LangString sec_data ${LANG_TURKISH} "Program Skinleri" + LangString sec_shortcuts ${LANG_TURKISH} "Shortcut'lar" + LangString sec_link ${LANG_TURKISH} ".pqi Dosya Kaydet" + LangString sec_autostart ${LANG_TURKISH} "Otomatik calistir ve baglan" + LangString DESC_sec_main ${LANG_TURKISH} "Program dosyalar�n� kurar." + LangString DESC_sec_data ${LANG_TURKISH} "RetroShare Skin'leri kurar" + LangString DESC_sec_shortcuts ${TURKISH} "Shortcut yap Start menu , Desktop veya Quicklaunchbar icin." + LangString DESC_sec_link ${LANG_TURKISH} "RetroShare .pqi almas� i�in kaydettirir" + LangString DESC_sec_autostart ${LANG_TURKISH} "Isletim sistemi acildiginda Otomatik olarak calistir ve baglan" + LangString LANGUAGEID ${LANG_TURKISH} "1055" + + LangString sec_main ${LANG_SIMPCHINESE} "程序文件" + LangString sec_data ${LANG_SIMPCHINESE} "程序皮肤" + LangString sec_shortcuts ${LANG_SIMPCHINESE} "快捷方式" + LangString sec_link ${LANG_SIMPCHINESE} "RetroShare文件关联" + LangString sec_autostart ${LANG_SIMPCHINESE} "自动启动" + LangString DESC_sec_main ${LANG_SIMPCHINESE} "安装RetroShare程序" + LangString DESC_sec_data ${LANG_SIMPCHINESE} "安装RetroShare皮肤" + LangString DESC_sec_shortcuts ${LANG_SIMPCHINESE} "建RetroShare快捷方式" + LangString DESC_sec_link ${LANG_SIMPCHINESE} "关联.pqi扩展名" + LangString DESC_sec_autostart ${LANG_SIMPCHINESE} "启动时自动运行和登录" + LangString LANGUAGEID ${LANG_SIMPCHINESE} "2052" + + LangString sec_main ${LANG_POLISH} "Pliki programu" + LangString sec_data ${LANG_POLISH} "Skórki" + LangString sec_shortcuts ${LANG_POLISH} "Skróty" + LangString sec_link ${LANG_POLISH} "Skojarz pliki" + LangString sec_autostart ${LANG_POLISH} "Automatyczne uruchamianie" + LangString DESC_sec_main ${LANG_POLISH} "Instaluje pliki programu RetroShare" + LangString DESC_sec_data ${LANG_POLISH} "Instaluje skórki programu RetroShare" + LangString DESC_sec_shortcuts ${LANG_POLISH} "Utwórz ikony skrótów na pulpicie, w menu start oraz na pasku szybkiego uruchamiania." + LangString DESC_sec_link ${LANG_POLISH} "Skojarz pliki o rozszerzeniu .pqi z RetroShare" + LangString DESC_sec_autostart ${LANG_POLISH} "Uruchom i zaloguj podczas startu systemu" + LangString LANGUAGEID ${LANG_POLISH} "1045" + + + +!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +Section $(sec_main) sec_main + + ;Set Section required + SectionIn RO + + ; Set Section properties + SetOverwrite on + + ; Clears previous error logs + Delete "$INSTDIR\*.log" + + ; Set Section Files and Shortcuts + SetOutPath "$INSTDIR\" + File /r "release\RetroShare.exe" + File /r "D:\Qt\2009.02\mingw\bin\mingwm10.dll" + File /r "D:\Qt\2009.02\qt\bin\QtCore4.dll" + File /r "D:\Qt\2009.02\qt\bin\QtGui4.dll" + File /r "D:\Qt\2009.02\qt\bin\QtNetwork4.dll" + File /r "D:\Qt\2009.02\qt\bin\QtXml4.dll" + File /r "D:\Qt\2009.02\qt\bin\QtScript4.dll" + File /r "pthreadGCE2.dll" + File /r "pthreadGC2d.dll" + File /r "changelog.txt" + + + +SectionEnd + +Section $(sec_data) sec_data + + ; Set Section properties + SetOverwrite on + + ; Set Section Files and Shortcuts + SetOutPath "$APPDATA\RetroShare\" + ;File /r "data\*" + + ; We're not ready for external skins... + ; Set Section qss need to remove svn path + SetOutPath "$INSTDIR\qss\" + File /r qss\*.* + + ; Set Section skin + ; SetOutPath "$INSTDIR\skin\" + ; File /r release\skin\*.* + + ; Add emoticons + SetOutPath "$INSTDIR\emoticons\" + File /r emoticons\*.* + + ; Add Chat Style + SetOutPath "$INSTDIR\style\" + File /r style\*.* + +SectionEnd + +Section $(sec_link) sec_link + ; Delete any existing keys + + + ; Write the file association + WriteRegStr HKCR .pqi "" retroshare + WriteRegStr HKCR retroshare "" "PQI File" + WriteRegBin HKCR retroshare EditFlags 00000100 + WriteRegStr HKCR "retroshare\shell" "" open + WriteRegStr HKCR "retroshare\shell\open\command" "" `"$INSTDIR\RetroShare.exe" "%1"` + +SectionEnd + +SectionGroup $(sec_shortcuts) sec_shortcuts +Section StartMenu SEC0001 + + SetOutPath "$INSTDIR" + CreateDirectory "$SMPROGRAMS\${APPNAME}" + CreateShortCut "$SMPROGRAMS\${APPNAME}\$(^UninstallLink).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd + +Section Desktop SEC0002 + + + CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd + +Section Quicklaunchbar SEC0003 + + + CreateShortCut "$QUICKLAUNCH\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd +SectionGroupEnd + +;Section $(sec_autostart) sec_autostart + +; WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" "$INSTDIR\${APPNAME}.exe -a" + +;SectionEnd + +Section $(sec_autostart) sec_autostart + + CreateShortCut "$SMSTARTUP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 +SectionEnd + + +Section -FinishSection + + WriteRegStr HKLM "Software\${APPNAME}" "" "$INSTDIR" + WriteRegStr HKLM "Software\${APPNAME}" "Version" "${VERSION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe" + WriteUninstaller "$INSTDIR\uninstall.exe" + +SectionEnd + + + +;-------------------------------- +;Descriptions + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${sec_main} $(DESC_sec_main) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_data} $(DESC_sec_data) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_shortcuts} $(DESC_sec_shortcuts) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_link} $(DESC_sec_link) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_autostart} $(DESC_sec_autostart) +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +;Uninstall section +Section "Uninstall" + + ; Remove file association registry keys + DeleteRegKey HKCR .pqi + DeleteRegKey HKCR retroshare + + ; Remove program/uninstall regsitry keys + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" + DeleteRegKey HKLM SOFTWARE\${APPNAME} + + DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" + + ; Remove files and uninstaller + Delete $INSTDIR\RetroShare.exe + Delete $INSTDIR\*.dll + Delete $INSTDIR\*.dat + Delete $INSTDIR\*.txt + Delete $INSTDIR\*.ini + Delete $INSTDIR\*.log + + Delete $INSTDIR\uninstall.exe + + ; Remove the kadc.ini file. + ; Don't remove the directory, otherwise + ; we lose the XPGP keys. + ; Should make this an option though... + Delete "$APPDATA\${APPNAME}\kadc.ini" + Delete "$APPDATA\${APPNAME}\*.cfg" + Delete "$APPDATA\${APPNAME}\*.conf" + Delete "$APPDATA\${APPNAME}\*.log-save" + Delete "$APPDATA\${APPNAME}\*.log" + Delete "$APPDATA\${APPNAME}\*.failed" + + RMDir /r "$APPDATA\${APPNAME}\cache" + RMDir /r "$APPDATA\${APPNAME}\Partials" + + + ; Remove shortcuts, if any + Delete "$SMPROGRAMS\${APPNAME}\*.*" + + ; Remove desktop shortcut + Delete "$DESKTOP\${APPNAME}.lnk" + + ; Remove Quicklaunch shortcut + Delete "$QUICKLAUNCH\${APPNAME}.lnk" + + ; Remove Autstart + Delete "$SMSTARTUP\${APPNAME}.lnk" + + ; Remove directories used + RMDir "$SMPROGRAMS\${APPNAME}" + RMDir /r "$INSTDIR" + RMDir /r "$INSTDIR\qss" + RMDir /r "$INSTDIR\emoticons" + RMDir /r "$INSTDIR\style" + +SectionEnd + +Function .onInit + + InitPluginsDir + Push $R1 + File /oname=$PLUGINSDIR\spltmp.bmp "gui\images\splash.bmp" + advsplash::show 1200 1000 1000 -1 $PLUGINSDIR\spltmp + Pop $R1 + Pop $R1 + !insertmacro MUI_LANGDLL_DISPLAY + + + +FunctionEnd + + +# Installer Language Strings +# TODO Update the Language Strings with the appropriate translations. + +LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall" +LangString ^UninstallLink ${LANG_GERMAN} "Deinstallieren" +LangString ^UninstallLink ${LANG_TURKISH} "Kald�r" +LangString ^UninstallLink ${LANG_FRENCH} "Désinstaller" +LangString ^UninstallLink ${LANG_SIMPCHINESE} "卸载" +LangString ^UninstallLink ${LANG_POLISH} "Odinstaluj" + + + +; eof diff --git a/build_scripts/Windows/stripSVN.sh b/build_scripts/Windows/stripSVN.sh new file mode 100755 index 000000000..65a740cab --- /dev/null +++ b/build_scripts/Windows/stripSVN.sh @@ -0,0 +1,12 @@ +#!/bin/sh + + +if [ $# -le 0 ] +then + echo usage $0 directory + exit +fi + +echo find $1 -name .svn +rm -vrf `find $1 -name .svn` + diff --git a/libbitdht/src/README.txt b/libbitdht/src/README.txt new file mode 100644 index 000000000..8f4daabf2 --- /dev/null +++ b/libbitdht/src/README.txt @@ -0,0 +1,23 @@ + +What's in the Package +--------------------------------------------------------------- +bitdht - base BitDHT Code. +util - generic utils for networking and threading. +udp - UDP interfacing code. +lib - Where the library is created. +tests - basic unit tests. +example - example code of how to use libbitdht. +libbitdht.pro - build script for Qt's qmake. +README.txt - this file. + + +HOWTO libbitdht. +---------------------------------------------- +This version is build using Qt's qmake system. + +1) Install Qt's qmake system: libqt-dev +2) type ./qmake +3) type ./make +4) check out the example and tests to learn how to interface with libbitdht. + + diff --git a/libbitdht/src/bitdht/Makefile b/libbitdht/src/bitdht/Makefile new file mode 100644 index 000000000..60e7b510b --- /dev/null +++ b/libbitdht/src/bitdht/Makefile @@ -0,0 +1,44 @@ +CPPFLAGS += -g -Wall -D BE_DEBUG -lpthread +LDFLAGS += -g -Wall -D BE_DEBUG -lpthread +CFLAGS += -g -Wall -D BE_DEBUG +CC = g++ +LIB = -lpthread +CPPLIB = -lpthread + +EXEC = bdmsgs_test bdmetric_test bdquery_test bdspace_test bdspace_test2 bdnode_test bdnode_test2 bdstore_test +EXEC += bdnode_multitest1 bdmidids_test +EXEC += udpbitdht_nettest bencode_test +EXEC += bdmgr_multitest +#EXEC += bdudp_test + +all: $(EXEC) + +OBJ = bencode.o bdmsgs.o bdobj.o +OBJ += bdpeer.o bdquery.o bdnode.o bdstore.o bdhash.o +OBJ += bdmanager.o bdstddht.o + +# udp base objs +OBJ += bdthreads.o udplayer.o udpstack.o +OBJ += udpbitdht.o + +bdmsgs_test: $(OBJ) bdmsgs_test.o +bdmetric_test: $(OBJ) bdmetric_test.o +bdquery_test: $(OBJ) bdquery_test.o +bdspace_test: $(OBJ) bdspace_test.o +bdspace_test2: $(OBJ) bdspace_test2.o +bdnode_test: $(OBJ) bdnode_test.o +bdnode_test2: $(OBJ) bdnode_test2.o +bdmidids_test: $(OBJ) bdmidids_test.o + +bdnode_multitest1: $(OBJ) bdnode_multitest1.o +bdmgr_multitest: $(OBJ) bdmgr_multitest.o + +bdstore_test: $(OBJ) bdstore_test.o +bdudp_test: $(OBJ) bdudp_test.o +udpbitdht_nettest: $(OBJ) udpbitdht_nettest.o +bencode_test: $(OBJ) bencode_test.o + +clean: + rm -f *.o core $(EXEC) + +.PHONY: all clean diff --git a/libbitdht/src/bitdht/bdaccount.cc b/libbitdht/src/bitdht/bdaccount.cc new file mode 100644 index 000000000..232f586ea --- /dev/null +++ b/libbitdht/src/bitdht/bdaccount.cc @@ -0,0 +1,137 @@ +/* + * bitdht/bdaccount.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2011 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bitdht/bdaccount.h" + +#include +#include + +#include +#include +#include + + +#define LPF_FACTOR (0.90) + +bdAccount::bdAccount() + :mNoStats(BDACCOUNT_NUM_ENTRIES), + mCountersOut(BDACCOUNT_NUM_ENTRIES), mCountersRecv(BDACCOUNT_NUM_ENTRIES), + mLpfOut(BDACCOUNT_NUM_ENTRIES), mLpfRecv(BDACCOUNT_NUM_ENTRIES), + mLabel(BDACCOUNT_NUM_ENTRIES) +{ + + mLabel[BDACCOUNT_MSG_OUTOFDATEPING] = "OUTOFDATEPING "; + mLabel[BDACCOUNT_MSG_PING] = "PING "; + mLabel[BDACCOUNT_MSG_PONG] = "PONG "; + mLabel[BDACCOUNT_MSG_QUERYNODE] = "QUERYNODE "; + mLabel[BDACCOUNT_MSG_QUERYHASH] = "QUERYHASH "; + mLabel[BDACCOUNT_MSG_REPLYFINDNODE] = "REPLYFINDNODE "; + mLabel[BDACCOUNT_MSG_REPLYQUERYHASH] = "REPLYQUERYHASH "; + + mLabel[BDACCOUNT_MSG_POSTHASH] = "POSTHASH "; + mLabel[BDACCOUNT_MSG_REPLYPOSTHASH] = "REPLYPOSTHASH "; + + mLabel[BDACCOUNT_MSG_CONNECTREQUEST] = "CONNECTREQUEST "; + mLabel[BDACCOUNT_MSG_CONNECTREPLY] = "CONNECTREPLY "; + mLabel[BDACCOUNT_MSG_CONNECTSTART] = "CONNECTSTART "; + mLabel[BDACCOUNT_MSG_CONNECTACK] = "CONNECTACK "; + + resetStats(); +} + + +void bdAccount::incCounter(uint32_t idx, bool out) +{ + if (idx > mNoStats-1) + { + std::cerr << "bdAccount::incCounter() Invalid Index"; + std::cerr << std::endl; + } + + if (out) + { + mCountersOut[idx]++; + } + else + { + mCountersRecv[idx]++; + } + return; +} + + +void bdAccount::doStats() +{ + int i; + for(i = 0; i < mNoStats; i++) + { + mLpfOut[i] *= (LPF_FACTOR) ; + mLpfOut[i] += (1.0 - LPF_FACTOR) * mCountersOut[i]; + + mLpfRecv[i] *= (LPF_FACTOR) ; + mLpfRecv[i] += (1.0 - LPF_FACTOR) * mCountersRecv[i]; + } + resetCounters(); +} + +void bdAccount::printStats(std::ostream &out) +{ + int i; + out << " Send Recv: "; + out << std::endl; + for(i = 0; i < mNoStats; i++) + { + + out << "Send" << mLabel[i] << " : " << std::setw(10) << mLpfOut[i]; + out << " "; + out << "Recv" << mLabel[i] << " : " << std::setw(10) << mLpfRecv[i]; + out << std::endl; + } +} + +void bdAccount::resetCounters() +{ + int i; + for(i = 0; i < mNoStats; i++) + { + mCountersOut[i] = 0; + mCountersRecv[i] = 0; + } +} + +void bdAccount::resetStats() +{ + int i; + for(i = 0; i < mNoStats; i++) + { + mLpfOut[i] = 0; + mLpfRecv[i] = 0; + } + resetCounters(); +} + + + + diff --git a/libbitdht/src/bitdht/bdaccount.h b/libbitdht/src/bitdht/bdaccount.h new file mode 100644 index 000000000..5e9b6cc61 --- /dev/null +++ b/libbitdht/src/bitdht/bdaccount.h @@ -0,0 +1,79 @@ +#ifndef BITDHT_ACCOUNT_H +#define BITDHT_ACCOUNT_H + +/* + * bitdht/bdaccount.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2011 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include +#include +#include + +#define BDACCOUNT_MSG_OUTOFDATEPING 0 +#define BDACCOUNT_MSG_PING 1 +#define BDACCOUNT_MSG_PONG 2 +#define BDACCOUNT_MSG_QUERYNODE 3 +#define BDACCOUNT_MSG_QUERYHASH 4 +#define BDACCOUNT_MSG_REPLYFINDNODE 5 +#define BDACCOUNT_MSG_REPLYQUERYHASH 6 + +#define BDACCOUNT_MSG_POSTHASH 7 +#define BDACCOUNT_MSG_REPLYPOSTHASH 8 + +#define BDACCOUNT_MSG_CONNECTREQUEST 9 +#define BDACCOUNT_MSG_CONNECTREPLY 10 +#define BDACCOUNT_MSG_CONNECTSTART 11 +#define BDACCOUNT_MSG_CONNECTACK 12 + +#define BDACCOUNT_NUM_ENTRIES 13 + +class bdAccount +{ + public: + + bdAccount(); + + void incCounter(uint32_t idx, bool out); + void doStats(); + void printStats(std::ostream &out); + void resetCounters(); + void resetStats(); + + private: + + int mNoStats; + + std::vector mCountersOut; + std::vector mCountersRecv; + + std::vector mLpfOut; + std::vector mLpfRecv; + + std::vector mLabel; + // Statistics. +}; + + + +#endif // BITDHT_ACCOUNT_H diff --git a/libbitdht/src/bitdht/bdboot.txt b/libbitdht/src/bitdht/bdboot.txt new file mode 100644 index 000000000..498d472ff --- /dev/null +++ b/libbitdht/src/bitdht/bdboot.txt @@ -0,0 +1,500 @@ +108.36.64.33 58209 +89.160.187.217 16932 +84.124.224.199 56885 +94.237.72.30 42945 +85.201.229.3 11452 +201.173.120.93 23428 +76.127.178.159 14380 +92.247.199.243 19710 +95.58.126.146 64477 +174.94.94.69 43503 +95.79.65.220 8087 +78.90.64.148 10231 +24.193.122.202 11511 +216.97.218.167 40124 +70.69.163.9 23456 +67.185.18.229 52572 +210.251.181.85 55531 +82.137.120.244 34738 +61.52.66.122 42160 +61.61.233.108 21637 +111.255.1.79 11783 +110.182.101.142 10347 +70.69.188.108 22559 +81.153.223.47 46074 +77.220.132.130 44444 +213.177.119.61 6881 +75.126.69.83 29903 +85.186.138.51 20478 +46.147.163.175 33427 +77.81.147.93 7937 +216.183.139.145 6681 +203.122.227.234 18471 +94.182.158.89 18819 +61.62.57.67 27226 +84.31.247.193 14144 +84.2.188.109 23962 +91.145.86.134 62952 +41.228.217.33 37400 +78.30.225.207 80 +64.53.221.48 38759 +79.131.81.227 10361 +85.56.11.182 15327 +68.101.25.86 30415 +61.227.170.158 15549 +178.44.156.94 5001 +83.46.22.193 61631 +24.178.72.100 4417 +87.254.152.23 57402 +213.22.241.214 27873 +46.73.100.190 11594 +95.78.217.2 21760 +195.245.119.20 7625 +95.136.244.101 31640 +91.146.43.182 35691 +95.134.156.22 27409 +184.82.35.166 6821 +84.50.94.139 26929 +95.133.87.134 45486 +59.9.209.241 40451 +83.226.67.223 12241 +216.37.139.190 59646 +77.97.241.193 54359 +95.134.154.114 60010 +61.103.124.160 15674 +46.64.80.102 35895 +99.118.0.136 53622 +188.235.132.82 52580 +188.173.99.140 42754 +71.195.234.69 45976 +83.172.22.81 55552 +80.221.169.92 18891 +2.82.212.216 61972 +98.77.175.116 33627 +121.174.151.70 26581 +81.102.255.173 35470 +110.159.178.96 10214 +190.16.216.71 52982 +80.162.37.81 22080 +213.124.220.198 6881 +77.248.101.169 51413 +173.49.168.99 51735 +213.5.78.19 17590 +86.88.195.220 51979 +79.114.26.233 40236 +79.130.39.45 26676 +90.199.157.147 37872 +96.48.156.192 13393 +85.226.120.222 39272 +78.63.251.197 18248 +89.221.25.71 51000 +83.226.167.119 22644 +88.120.240.30 37760 +82.225.93.93 53862 +84.48.59.74 27223 +212.117.4.117 51413 +92.148.10.30 54848 +62.216.126.134 35621 +84.250.34.176 25812 +109.165.126.178 41845 +81.23.163.247 25809 +79.50.33.239 26631 +124.191.192.176 48362 +76.114.42.202 33582 +173.55.160.70 14566 +58.196.220.183 24681 +95.28.1.159 60240 +81.170.186.164 39044 +46.7.204.107 35529 +109.73.104.152 37534 +90.200.237.165 23711 +46.70.27.140 10719 +207.161.37.213 18690 +80.117.226.21 30443 +77.38.42.20 9715 +92.239.12.100 54721 +110.174.165.63 39500 +88.88.84.245 12345 +91.121.26.60 55124 +109.239.213.19 41255 +92.47.45.110 13189 +76.216.237.156 64405 +118.168.4.98 8014 +111.91.225.146 6881 +124.89.124.129 18563 +94.8.56.115 29333 +109.207.176.90 17931 +91.217.5.1 41930 +92.112.169.230 29038 +62.162.51.133 61656 +125.27.152.162 8007 +60.216.222.200 11640 +118.81.110.97 16001 +112.202.153.252 49354 +70.84.216.90 15007 +89.40.176.80 52201 +67.184.198.91 55290 +95.52.255.243 18914 +91.83.156.215 34982 +151.51.17.237 35268 +92.99.25.17 14092 +46.164.215.90 14014 +212.52.56.16 63696 +89.178.129.27 18456 +89.88.248.180 59786 +109.96.108.144 48019 +178.206.21.232 12086 +99.37.202.87 51092 +94.248.194.63 48559 +188.232.154.148 6881 +99.73.91.225 51413 +117.200.148.179 16442 +122.120.128.224 14850 +220.248.146.129 56019 +113.141.183.16 10910 +41.218.252.74 29060 +203.218.78.175 51413 +94.176.131.60 27185 +77.122.219.96 6881 +94.27.105.217 28094 +99.62.146.221 16880 +188.83.195.167 43090 +121.214.19.48 21179 +213.87.123.205 65503 +67.82.123.5 37156 +46.70.161.55 63742 +70.82.91.50 61288 +218.91.146.70 50791 +125.252.61.71 63002 +90.213.160.205 35913 +78.235.221.72 59553 +178.121.52.96 60579 +87.247.62.167 27816 +118.172.31.159 23100 +82.17.243.247 43682 +109.173.41.131 47434 +89.254.192.115 57300 +222.5.240.97 21494 +190.25.44.167 10459 +41.99.59.57 26955 +125.230.193.210 16001 +91.137.156.131 52773 +109.92.201.235 17434 +82.141.87.41 32786 +109.75.197.236 39742 +94.236.149.79 54983 +84.202.212.85 47459 +74.210.181.212 39137 +82.233.137.114 16390 +87.55.32.94 42788 +41.233.84.104 37902 +68.84.52.55 36773 +41.230.239.93 54167 +89.123.145.26 10029 +129.95.72.236 56091 +74.138.196.114 62934 +95.37.81.137 35567 +14.194.100.227 42436 +81.164.46.76 6881 +74.102.22.47 11336 +213.114.29.161 50888 +78.90.176.124 56017 +192.11.19.2 38614 +192.11.19.2 38603 +98.228.57.239 57855 +96.23.56.6 12860 +86.151.199.161 43280 +220.230.99.102 53175 +213.57.146.235 36661 +99.244.175.108 18892 +98.232.219.193 50555 +93.86.22.133 22942 +81.198.240.88 46581 +95.153.176.117 33309 +121.2.134.222 13597 +118.209.164.73 44759 +78.57.193.144 29742 +109.105.15.232 62929 +86.101.214.205 60200 +69.138.195.57 54191 +83.212.200.132 12132 +77.77.26.194 9171 +69.196.186.81 36734 +203.160.24.156 43016 +94.247.88.154 24234 +46.118.116.49 48599 +87.93.8.216 15147 +70.92.75.203 29092 +76.22.97.29 39847 +178.213.213.100 37592 +77.96.97.40 51413 +24.189.102.125 42007 +118.169.120.177 12350 +115.135.179.213 13726 +98.251.72.191 56125 +84.74.112.151 34936 +84.51.88.213 59826 +86.106.112.169 28453 +95.135.143.126 50860 +178.140.187.211 54465 +178.121.100.43 35693 +2.217.35.228 21568 +220.211.30.194 54587 +122.145.130.70 16881 +87.207.15.170 29646 +82.239.79.88 44207 +109.187.146.145 10124 +89.135.117.177 61182 +122.169.146.174 16519 +77.78.26.66 8338 +41.104.30.0 17325 +117.11.157.108 16611 +79.116.50.118 44770 +116.74.101.72 43363 +86.126.196.48 35650 +60.241.61.19 37797 +79.113.28.247 12658 +92.113.35.173 52525 +123.110.9.189 23814 +200.104.141.151 27144 +70.94.54.203 28093 +188.26.254.79 22577 +188.254.130.80 10722 +88.118.111.251 24290 +109.173.106.39 6881 +109.252.32.107 33633 +176.14.235.3 57996 +188.226.77.216 48959 +86.72.177.79 20211 +95.84.248.77 36474 +98.226.183.179 62538 +173.176.31.176 61480 +98.110.164.233 18738 +109.169.129.229 33204 +67.189.89.157 54418 +218.28.216.174 15334 +41.132.206.240 17260 +124.234.185.101 22990 +95.247.246.235 22300 +91.66.51.19 4636 +115.187.48.222 19949 +41.218.206.184 51078 +109.205.248.138 34794 +129.2.86.70 19788 +178.59.141.236 58319 +78.100.18.29 12094 +220.100.30.198 27290 +2.133.72.50 18676 +95.34.94.2 7227 +77.123.178.198 35691 +95.29.188.15 14653 +98.80.131.126 50703 +123.193.24.234 18099 +93.155.151.134 19304 +78.29.92.93 17481 +93.87.39.186 40929 +193.110.115.71 61728 +81.27.61.29 64090 +187.69.27.142 25996 +118.172.11.101 10343 +202.176.172.192 17288 +93.178.199.55 25690 +118.169.14.92 10308 +173.14.30.134 45196 +188.17.235.68 18143 +188.17.235.68 18152 +80.251.134.66 25101 +88.178.72.2 7812 +78.27.33.114 15136 +14.136.5.8 20249 +151.203.29.130 50096 +24.10.47.12 55203 +76.187.211.94 59425 +195.67.238.121 15000 +89.82.71.87 6881 +78.150.5.162 27729 +81.155.121.101 6881 +62.122.5.70 11473 +213.196.160.129 6881 +195.91.155.91 24234 +178.150.196.145 35691 +77.20.253.136 6881 +99.192.107.151 29420 +93.182.146.26 15210 +89.132.74.190 27071 +94.192.17.72 59453 +46.107.134.155 46382 +77.66.223.100 25012 +175.137.178.223 16001 +120.147.48.118 6881 +61.73.149.123 57527 +46.9.225.86 51337 +77.77.34.49 53250 +46.118.64.164 38555 +72.91.173.234 53989 +108.0.13.192 13395 +96.234.5.159 50601 +95.143.147.128 47163 +216.228.194.176 49234 +92.107.1.68 47053 +92.52.48.200 64153 +85.157.73.46 44039 +213.22.59.123 33547 +194.44.174.33 11653 +173.179.46.189 37498 +98.196.139.105 28085 +98.213.2.57 25910 +173.192.155.242 15009 +210.51.59.72 8921 +84.108.167.190 20819 +78.46.106.133 51420 +77.223.225.140 46881 +118.233.249.25 19661 +118.223.202.132 34704 +93.74.54.75 41632 +178.41.52.249 23388 +189.33.41.183 57777 +108.11.139.67 50063 +178.130.19.250 22912 +24.6.228.21 24104 +14.32.5.68 44972 +173.63.112.3 14618 +24.47.92.66 56734 +76.107.89.84 18354 +81.236.195.180 18203 +68.52.17.145 8280 +184.59.91.226 49545 +50.18.3.51 11079 +68.13.217.94 30656 +80.64.26.155 48649 +82.233.85.22 38594 +69.84.120.59 51580 +24.131.35.42 43079 +189.122.104.141 50099 +78.96.226.99 52701 +68.80.227.54 55421 +188.49.22.126 17110 +89.215.54.73 35995 +112.173.202.157 31786 +188.246.77.253 29604 +182.21.19.42 12348 +68.148.101.110 53676 +67.184.242.108 47636 +68.102.204.198 45538 +109.148.249.57 49722 +217.43.247.199 26578 +87.15.161.70 29772 +87.255.16.8 21689 +98.82.237.179 27374 +67.184.213.33 61087 +68.209.144.92 24424 +88.198.183.157 32257 +219.84.8.213 20509 +78.63.251.219 54049 +188.143.45.245 33207 +178.207.61.146 48127 +92.37.38.199 34094 +76.255.178.99 55241 +187.113.243.20 29024 +219.126.158.155 62647 +95.172.127.31 52302 +94.66.254.203 24543 +24.179.64.210 15228 +78.139.225.244 45682 +76.234.131.193 41917 +93.91.229.98 64578 +82.244.203.153 21428 +112.201.99.184 24555 +78.62.147.218 40756 +86.186.163.106 24725 +188.168.87.217 56926 +201.79.56.34 51002 +60.240.20.17 52324 +95.42.221.189 21048 +113.147.245.39 7015 +86.219.130.100 33634 +46.229.50.135 64546 +188.115.160.24 22829 +2.125.135.95 41031 +84.212.218.243 15778 +174.96.234.186 55204 +178.79.21.107 29953 +67.188.133.52 32812 +184.155.124.198 49383 +119.152.32.140 44814 +93.7.182.144 45874 +95.7.188.130 54914 +24.69.34.86 60863 +84.208.115.8 19878 +70.52.174.137 53161 +88.168.14.141 46232 +112.118.110.73 23523 +86.131.64.203 10961 +90.16.186.222 28963 +114.25.189.2 26371 +41.201.193.31 62478 +78.243.1.54 23096 +188.40.241.165 42860 +134.106.236.73 47676 +178.126.116.177 41191 +109.184.124.201 15949 +173.32.244.91 36480 +78.160.108.42 26516 +110.4.37.208 18405 +79.35.38.183 56065 +178.140.45.11 58773 +90.23.195.31 5980 +114.42.69.220 25934 +124.209.90.197 7143 +77.122.48.90 15241 +95.211.8.11 19632 +113.253.67.125 15806 +82.233.53.72 24504 +85.222.76.230 28749 +188.247.87.63 61053 +190.205.135.114 6558 +85.73.96.172 20157 +74.248.209.2 43507 +79.165.180.49 61839 +71.166.156.253 50056 +99.255.144.165 47227 +118.168.190.64 21716 +61.206.121.120 17377 +85.187.37.123 13017 +108.28.93.29 21491 +66.91.48.116 43960 +196.205.129.245 11972 +93.12.186.53 7448 +62.147.204.92 7812 +90.205.87.163 25878 +207.81.138.15 47037 +112.202.44.3 19127 +91.17.208.53 1253 +2.221.14.86 14144 +89.131.159.217 38402 +24.0.27.234 33531 +46.55.74.45 45370 +68.224.62.176 54916 +78.58.13.203 11641 +77.182.30.93 8812 +95.182.76.102 24521 +122.167.5.167 12542 +92.134.16.12 42932 +88.187.80.252 49180 +134.106.236.73 32092 +95.90.231.148 35420 +82.232.0.124 9156 +125.26.193.75 15782 +84.123.34.33 19467 +193.95.54.218 51240 +89.28.25.110 25077 +124.6.0.183 30001 +92.50.80.105 49232 +88.189.82.239 5666 +213.245.188.141 25551 +91.66.51.19 33548 +24.1.118.110 27704 +216.137.133.89 44376 +188.126.74.13 45416 +84.208.60.162 37692 +86.193.13.31 7812 diff --git a/libbitdht/src/bitdht/bdconnection.cc b/libbitdht/src/bitdht/bdconnection.cc new file mode 100644 index 000000000..36c5889fc --- /dev/null +++ b/libbitdht/src/bitdht/bdconnection.cc @@ -0,0 +1,2907 @@ +/* + * bitdht/bdconnection.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2011 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include +#include "bitdht/bdiface.h" + +#include "bitdht/bdnode.h" +#include "bitdht/bdquerymgr.h" +#include "bitdht/bdconnection.h" +#include "bitdht/bdmsgs.h" +#include "bitdht/bdstddht.h" +#include "util/bdnet.h" +#include "util/bdrandom.h" + +#define DEBUG_NODE_CONNECTION 1 + + + +#define BITDHT_CR_PAUSE_BASE_PERIOD 5 +#define BITDHT_CR_PAUSE_RND_PERIOD 15 + +#define MAX_NUM_RETRIES 3 + +uint32_t createConnectionErrorCode(uint32_t userProvided, uint32_t fallback, uint32_t point); + +/************************************************************************************************************ +******************************************** Connection Config ********************************************** +************************************************************************************************************/ + +bdConnectManager::bdConnectManager(bdNodeId *ownId, bdSpace *space, bdQueryManager *qmgr, bdDhtFunctions *fns, bdNodePublisher *pub) + :mOwnId(*ownId), mNodeSpace(space), mQueryMgr(qmgr), mFns(fns), mPub(pub) +{ + defaultConnectionOptions(); +} + + + + +void bdConnectManager::defaultConnectionOptions() +{ + /* by default we want to help people proxy connections. + * As this involves no interaction at higher levels, + * we want ALL BitDHT clients to support - unless explicitly disabled. + */ + + setConnectionOptions(BITDHT_CONNECT_MODE_PROXY, + BITDHT_CONNECT_OPTION_AUTOPROXY); +} + +void bdConnectManager::setConnectionOptions(uint32_t allowedModes, uint32_t flags) +{ + mConfigAllowedModes = allowedModes; + mConfigAutoProxy = false; + + if (flags & BITDHT_CONNECT_OPTION_AUTOPROXY) + { + mConfigAutoProxy = true; + } + +} + +void bdConnectManager::shutdownConnections() +{ + std::cerr << "bdConnectManager::shutdownConnections() Brutal Shutdown of the following connections: "; + std::cerr << std::endl; + + printConnections(); + + mConnectionRequests.clear(); + mConnections.clear(); + +} + +void bdConnectManager::printConnections() +{ + std::cerr << "bdConnectManager::printConnections()"; + std::cerr << std::endl; + + std::map::iterator it; + for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) + { + std::cerr << "bdConnectManager::printConnections() Connect Request:"; + std::cerr << std::endl; + std::cerr << it->second; + std::cerr << std::endl; + } + + std::map::iterator tit; + for(tit = mConnections.begin(); tit != mConnections.end(); tit++) + { + std::cerr << "bdConnectManager::printConnections() ConnectAttempt:"; + std::cerr << std::endl; + std::cerr << tit->second; + std::cerr << std::endl; + } +} + + + + + + +/************************************************************************************************************ +****************************************** Connection Initiation ******************************************** +************************************************************************************************************/ + + +/* This is called to initialise a connection. + * the callback could be with regard to: + * a Direct EndPoint. + * a Proxy Proxy, or an Proxy EndPoint. + * a Relay Proxy, or an Relay EndPoint. + * + * We have two alternatives: + * 1) Direct Endpoint. + * 2) Using a Proxy. + */ + +int bdConnectManager::requestConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t start) +{ + /* check if connection obj already exists */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::requestConnection() Mode: " << mode; + std::cerr << " Start: " << start; + std::cerr << " Target: "; + mFns->bdPrintNodeId(std::cerr, target); + std::cerr << " Local NetAddress: " << inet_ntoa(laddr->sin_addr); + std::cerr << ":" << ntohs(laddr->sin_port); + std::cerr << std::endl; +#endif + + if (!start) + { + return killConnectionRequest(laddr, target, mode); + } + + if (!(mConfigAllowedModes & mode)) + { + /* MODE not supported */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::requestConnection() Mode Not Supported"; + std::cerr << std::endl; +#endif + return 0; + } + + // Seems like a dumb one, but the testing picked it up. + if (*target == mOwnId) + { + /* MODE not supported */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::requestConnection() WARNING Not allowing connection to self"; + std::cerr << std::endl; +#endif + return 0; + } + + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { + return requestConnection_direct(laddr, target); + } + else + { + return requestConnection_proxy(laddr, target, mode); + } +} + +int bdConnectManager::checkExistingConnectionAttempt(bdNodeId *target) +{ + std::map::iterator it; + it = mConnectionRequests.find(*target); + if (it != mConnectionRequests.end()) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::checkExistingConnectAttempt() Found Existing Connection!"; + std::cerr << std::endl; +#endif + return 1; + } + return 0; +} + + +int bdConnectManager::killConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) +{ + /* check if connection obj already exists */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::killConnectionRequest() Mode: " << mode; + std::cerr << " Target: "; + mFns->bdPrintNodeId(std::cerr, target); + std::cerr << " Local NetAddress: " << inet_ntoa(laddr->sin_addr); + std::cerr << ":" << ntohs(laddr->sin_port); + std::cerr << std::endl; +#endif + + std::map::iterator it; + it = mConnectionRequests.find(*target); + if (it == mConnectionRequests.end()) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::killConnectionRequest() ERROR Request not there!"; + std::cerr << std::endl; +#endif + return 0; + } + + std::cerr << "bdConnectManager::killConnectionRequest() Flagging Connection Request as DONE"; + std::cerr << std::endl; + + time_t now = time(NULL); + it->second.mState = BITDHT_CONNREQUEST_DONE; + it->second.mStateTS = now; + it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | + BITDHT_CONNECT_ERROR_USER; + + + + return 1; +} + + + + +#define MIN_START_DIRECT_COUNT 1 +#define MIN_START_PROXY_COUNT 10 +#define CONNECT_NUM_PROXY_ATTEMPTS 10 + + +int bdConnectManager::requestConnection_direct(struct sockaddr_in *laddr, bdNodeId *target) +{ + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::requestConnection_direct()"; + std::cerr << std::endl; +#endif + /* create a bdConnect, and put into the queue */ + int mode = BITDHT_CONNECT_MODE_DIRECT; + bdConnectionRequest connreq; + + if (checkExistingConnectionAttempt(target)) + { + return 0; + } + + connreq.setupDirectConnection(laddr, target); + + mQueryMgr->result(target, connreq.mGoodProxies); + + /* now look in the bdSpace as well */ + if (connreq.mGoodProxies.size() < MIN_START_DIRECT_COUNT) + { + int number = CONNECT_NUM_PROXY_ATTEMPTS; + int with_flag = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; + std::list matchIds; + std::list::iterator it; + std::list::iterator pit; + mNodeSpace->find_node(target, number, matchIds, with_flag); + + /* merge lists (costly should use sets or something) */ + for(it = matchIds.begin(); it != matchIds.end(); it++) + { + pit = std::find(connreq.mGoodProxies.begin(), connreq.mGoodProxies.end(), *it); + if (pit != connreq.mGoodProxies.end()) + { + connreq.mGoodProxies.push_back(*it); + } + } + } + + /* Actually if we lots of ids at this point... its likely that something is wrong + */ + + if (connreq.mGoodProxies.size() > 1) + { + std::cerr << "bdConnectManager::requestConnection_direct() ERROR Multiple Peers for DIRECT connection"; + std::cerr << std::endl; + } + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::requestConnection_direct() CRINITSTATE Init Connection State"; + std::cerr << std::endl; + std::cerr << connreq; + std::cerr << std::endl; +#endif + + /* push connect onto queue, for later completion */ + + mConnectionRequests[*target] = connreq; + + /* connection continued via iterator */ + return 1; +} + + +int bdConnectManager::requestConnection_proxy(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) +{ + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::requestConnection_proxy()"; + std::cerr << std::endl; +#endif + + /* create a bdConnect, and put into the queue */ + + bdConnectionRequest connreq; + connreq.setupProxyConnection(laddr, target, mode); + + /* grab any peers from any existing query */ + std::list::iterator pit; + std::list potentialProxies; + mQueryMgr->proxies(target, connreq.mGoodProxies); + mQueryMgr->potentialProxies(target, potentialProxies); + + /* check any potential proxies, must be same DHT Type */ + for(pit = potentialProxies.begin(); pit != potentialProxies.end(); ) + { + /* check the type in bdSpace */ + if (checkPeerForFlag(&(*pit), BITDHT_PEER_STATUS_DHT_ENGINE_VERSION)) + { + connreq.mGoodProxies.push_back(*pit); + pit = potentialProxies.erase(pit); + } + else + { + pit++; + } + } + + + /* if we don't have enough proxies ... ping the potentials */ + if (connreq.mGoodProxies.size() < MIN_START_PROXY_COUNT) + { + /* unknown, add to potential list, and ping! */ + for(pit = potentialProxies.begin(); pit != potentialProxies.end(); pit++) + { + + connreq.mPotentialProxies.push_back(*pit); + + // If the pings come back will be handled by + // updatePotentialConnectionProxy() + + mPub->send_ping(&(*pit)); + + std::cerr << "bdConnectManager::requestConnection_proxy() Pinging Potential Proxy"; + mFns->bdPrintId(std::cerr, &(*pit)); + std::cerr << std::endl; + } + } + + // Final Desperate Measures! + if (connreq.mGoodProxies.size() < MIN_START_PROXY_COUNT) + { + /* now find closest acceptable peers, + * and trigger a search for target... + * this will hopefully find more suitable proxies. + */ + + std::list excluding; + std::multimap nearest; + + + int number = CONNECT_NUM_PROXY_ATTEMPTS; + + mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, + BITDHT_PEER_STATUS_DHT_FOF | + BITDHT_PEER_STATUS_DHT_FRIEND); + + number = CONNECT_NUM_PROXY_ATTEMPTS - number; + + mNodeSpace->find_nearest_nodes_with_flags(target, number, excluding, nearest, + BITDHT_PEER_STATUS_DHT_ENGINE_VERSION ); + + std::multimap::iterator it; + for(it = nearest.begin(); it != nearest.end(); it++) + { + bdNodeId midId; + mFns->bdRandomMidId(target, &(it->second.id), &midId); + /* trigger search */ + mPub->send_query(&(it->second), &midId); + } + } + + + if (connreq.mGoodProxies.size() < 1) + { + std::cerr << "bdConnectManager::requestConnection_proxy() ERROR initial proxyList.size() == 0"; + std::cerr << std::endl; + } + + if (connreq.mGoodProxies.size() < MIN_START_PROXY_COUNT) + { + std::cerr << "bdConnectManager::requestConnection_proxy() WARNING initial proxyList.size() == SMALL PAUSING"; + std::cerr << std::endl; + + time_t now = time(NULL); + /* PAUSE the connection Attempt, so we can wait for responses */ + connreq.mState = BITDHT_CONNREQUEST_PAUSED; + connreq.mPauseTS = now + BITDHT_CR_PAUSE_BASE_PERIOD + + (int) (bdRandom::random_f32() * BITDHT_CR_PAUSE_RND_PERIOD); + } + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::requestConnection_proxy() CRINITSTATE Init Connection State"; + std::cerr << std::endl; + std::cerr << connreq; + std::cerr << std::endl; +#endif + + + /* push connect onto queue, for later completion */ + mConnectionRequests[*target] = connreq; + + return 1; +} + +void bdConnectManager::addPotentialConnectionProxy(const bdId *srcId, const bdId *target) +{ +#ifdef DEBUG_NODE_CONNECTION + //std::cerr << "bdConnectManager::addPotentialConnectionProxy() "; + //std::cerr << " srcId: "; + //bdStdPrintId(std::cerr, srcId); + //std::cerr << " target: "; + //bdStdPrintId(std::cerr, target); + //std::cerr << std::endl; +#endif + + if (!srcId) + { + /* not one of our targets... drop it */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::addPotentialConnectionProxy() srcID = NULL, useless to us"; + std::cerr << std::endl; +#endif + return; + } + + std::map::iterator it; + it = mConnectionRequests.find(target->id); + if (it == mConnectionRequests.end()) + { + /* not one of our targets... drop it */ +#ifdef DEBUG_NODE_CONNECTION + //std::cerr << "bdConnectManager::addPotentialConnectionProxy() Dropping Not one of Our Targets"; + //std::cerr << std::endl; +#endif + return; + } + + if (it->second.mMode == BITDHT_CONNECT_MODE_DIRECT) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::addPotentialConnectionProxy() Dropping Target is DIRECT"; + std::cerr << std::endl; +#endif + return; + } + + /* This is one is strange elsewhere.... srcId = targetId. + * This means that peer is actually reachable! and we should be connecting directly. + * however there is not much we can do about it here. Really up to higher level logic. + */ + if (srcId->id == target->id) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::addPotentialConnectionProxy() ERROR srcId.id == target.id (more of a WARNING)"; + std::cerr << std::endl; + std::cerr << "bdConnectManager::addPotentialConnectionProxy() NB: This means peer is actually reachable...."; + std::cerr << std::endl; + std::cerr << "bdConnectManager::addPotentialConnectionProxy() and we should be connecting directly. Oh Well!"; + std::cerr << std::endl; +#endif + return; + } + + if (checkPeerForFlag(srcId, BITDHT_PEER_STATUS_DHT_ENGINE_VERSION)) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::addPotentialConnectionProxy() Src passes FLAG test"; + std::cerr << std::endl; +#endif + it->second.addGoodProxy(srcId); + } + else + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::addPotentialConnectionProxy() Dropping SrcId failed FLAG test"; + std::cerr << std::endl; +#endif + } +} + + +int bdConnectManager::checkPeerForFlag(const bdId *id, uint32_t with_flag) +{ + /* check the type in bdSpace */ + bdPeer peer; + if (mNodeSpace->find_exactnode(id, peer)) + { + if (peer.mPeerFlags & with_flag) + { + return 1; + } + } + /* XXX eventually we'll need to check against extra peer lists. + * with our friends, etc + * + * ideally we'll track this info in the query! + */ + + return 0; +} + + +void bdConnectManager::updatePotentialConnectionProxy(const bdId *id, uint32_t mode) +{ + if (mode & BITDHT_PEER_STATUS_DHT_ENGINE_VERSION) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::updatePotentialConnectionProxy() Peer is GOOD : "; + bdStdPrintId(std::cerr, id); + std::cerr << std::endl; + std::cerr << "bdConnectManager::updatePotentialConnectionProxy() checking Connection Requests"; + std::cerr << std::endl; +#endif + /* good peer, see if any of our connectionrequests can use it */ + std::map::iterator it; + for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) + { + it->second.checkGoodProxyPeer(id); + } + } +} + + +int bdConnectManager::tickConnections() +{ + iterateConnectionRequests(); + iterateConnections(); + + return 1; +} + + +void bdConnectManager::iterateConnectionRequests() +{ + time_t now = time(NULL); + + std::list eraseList; + std::list::iterator eit; + + std::map::iterator it; + for(it = mConnectionRequests.begin(); it != mConnectionRequests.end(); it++) + { + bool erase = false; + std::cerr << "bdConnectManager::iterateConnectionAttempt() Request is:"; + std::cerr << std::endl; + std::cerr << it->second; + std::cerr << std::endl; + + + /* check status of connection */ + if (it->second.mState == BITDHT_CONNREQUEST_READY) + { + std::cerr << "bdConnectManager::iterateConnectionAttempt() Request is READY, starting"; + std::cerr << std::endl; + + + + /* kick off the connection if possible */ + // goes to BITDHT_CONNREQUEST_INPROGRESS; + if (!startConnectionAttempt(&(it->second))) + { + // FAILS if proxy is bad / nonexistent + std::cerr << "bdConnectManager::iterateConnectionAttempt() Failed startup => PAUSED"; + std::cerr << std::endl; + std::cerr << it->second; + std::cerr << std::endl; + + /* timeout and restart */ + it->second.mState = BITDHT_CONNREQUEST_PAUSED; + it->second.mStateTS = now; + it->second.mPauseTS = now + BITDHT_CR_PAUSE_BASE_PERIOD + + (int) (bdRandom::random_f32() * BITDHT_CR_PAUSE_RND_PERIOD); + + } + } + else if (it->second.mState == BITDHT_CONNREQUEST_PAUSED) + { + /* forced pause, with period specified at PAUSE point */ + if (now > it->second.mPauseTS) + { + std::cerr << "bdConnectManager::iterateConnectionAttempt() PAUSED has reached timout -> READY"; + std::cerr << std::endl; + + /* if we have run out of proxies, or recycled too many times. kill it */ + if (it->second.mGoodProxies.size() == 0) + { + std::cerr << "bdConnectManager::iterateConnectionAttempt() no more proxies => DONE"; + std::cerr << std::endl; + + it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | + BITDHT_CONNECT_ERROR_OUTOFPROXY; + it->second.mState = BITDHT_CONNREQUEST_DONE; + it->second.mStateTS = now; + } + else if (it->second.mRecycled > it->second.mGoodProxies.size() * MAX_NUM_RETRIES) + { + std::cerr << "bdConnectManager::iterateConnectionAttempt() to many retries => DONE"; + std::cerr << std::endl; + + it->second.mErrCode = BITDHT_CONNECT_ERROR_SOURCE_START | + BITDHT_CONNECT_ERROR_TOOMANYRETRY; + it->second.mState = BITDHT_CONNREQUEST_DONE; + it->second.mStateTS = now; + } + else + { + /* timeout and restart */ + it->second.mState = BITDHT_CONNREQUEST_READY; + it->second.mStateTS = now; + } + } + } + else if (it->second.mState == BITDHT_CONNREQUEST_INPROGRESS) + { + /* single connection attempt */ + if (now - it->second.mStateTS > BITDHT_CONNREQUEST_TIMEOUT_INPROGRESS) + { + std::cerr << "bdConnectManager::iterateConnectionAttempt() INPROGRESS has reached timout -> READY"; + std::cerr << std::endl; + std::cerr << it->second; + std::cerr << std::endl; + + /* timeout and restart */ + it->second.mState = BITDHT_CONNREQUEST_PAUSED; + it->second.mStateTS = now; + it->second.mPauseTS = now + BITDHT_CR_PAUSE_BASE_PERIOD + + (int) (bdRandom::random_f32() * BITDHT_CR_PAUSE_RND_PERIOD); + } + } + else if (it->second.mState == BITDHT_CONNREQUEST_EXTCONNECT) + { + /* connection completed, doing UDP connection */ + if (now - it->second.mStateTS > BITDHT_CONNREQUEST_TIMEOUT_CONNECT) + { + std::cerr << "bdConnectManager::iterateConnectionAttempt() EXTCONNECT has reached timout ->????"; + std::cerr << std::endl; + std::cerr << it->second; + std::cerr << std::endl; + + /* timeout and restart */ + it->second.mState = BITDHT_CONNREQUEST_PAUSED; + it->second.mStateTS = now; + it->second.mPauseTS = now + BITDHT_CR_PAUSE_BASE_PERIOD + + (int) (bdRandom::random_f32() * BITDHT_CR_PAUSE_RND_PERIOD); + } + } + else if (it->second.mState == BITDHT_CONNREQUEST_DONE) + { + std::cerr << "bdConnectManager::iterateConnectionAttempt() DONE -> erase"; + std::cerr << std::endl; + std::cerr << it->second; + std::cerr << std::endl; + + erase = true; + + } + + // Cleanup + if (now - it->second.mStateTS > BITDHT_CONNREQUEST_MAX_AGE) + { + std::cerr << "bdConnectManager::iterateConnectionAttempt() Cleaning Old ConnReq: "; + std::cerr << std::endl; + std::cerr << it->second; + std::cerr << std::endl; + } + + if (erase) + { + /* do callback */ + bdId srcId; + bdId proxyId; + bdId destId; + + destId.id = it->second.mTarget; + callbackConnect(&srcId, &proxyId, &destId, it->second.mMode, + BD_PROXY_CONNECTION_START_POINT, + BITDHT_CONNECT_CB_REQUEST, it->second.mErrCode); + + /* cleanup */ + eraseList.push_back(it->first); + } + } + + for(eit = eraseList.begin(); eit != eraseList.end(); eit++) + { + it = mConnectionRequests.find(*eit); + if (it != mConnectionRequests.end()) + { + mConnectionRequests.erase(it); + } + } +} + + + +int bdConnectManager::startConnectionAttempt(bdConnectionRequest *req) +{ + std::cerr << "bdConnectManager::startConnectionAttempt() ConnReq: "; + std::cerr << std::endl; + std::cerr << *req; + std::cerr << std::endl; + + if (req->mGoodProxies.size() < 1) + { + std::cerr << "bdConnectManager::startConnectionAttempt() No Potential Proxies... delaying attempt"; + std::cerr << std::endl; + return 0; + } + + bdId proxyId; + bdId srcConnAddr; + bdId destConnAddr; + + int mode = req->mMode; + + destConnAddr.id = req->mTarget; + bdsockaddr_clear(&(destConnAddr.addr)); + + srcConnAddr.id = mOwnId; + srcConnAddr.addr = req->mLocalAddr; + + proxyId = req->mGoodProxies.front(); + req->mGoodProxies.pop_front(); + + req->mCurrentAttempt = proxyId; + //req->mPeersTried.push_back(proxyId); + + req->mState = BITDHT_CONNREQUEST_INPROGRESS; + req->mStateTS = time(NULL); + + bool failProxy = false; + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { + // ONE BUG I HAVE SEEN. + if (!(req->mTarget == proxyId.id)) + { + std::cerr << "bdConnectManager::startConnectionAttempt() ERROR Trying to use a Proxy for DIRECT"; + std::cerr << std::endl; + + return 0; + } + } + else + { + if (req->mTarget == proxyId.id) + { + std::cerr << "bdConnectManager::startConnectionAttempt() ERROR Trying connect direct for PROXY|RELAY"; + std::cerr << std::endl; + + return 0; + } + } + + + return startConnectionAttempt(&proxyId, &srcConnAddr, &destConnAddr, mode); +} + + + +/************************************************************************************************************ +****************************************** Outgoing Triggers ************************************************ +************************************************************************************************************/ + +/************************************************************************************************************ +****************************************** Outgoing Triggers ************************************************ +************************************************************************************************************/ + +/************************************************************************************************************ +*************************************** Connection Requests Callback **************************************** +************************************************************************************************************/ + +/* Lots of Callbacks come through here... The Connection Request gets flagged, and the message + * get passed on up if necessary. + */ + +void bdConnectManager::callbackConnectRequest(bdId *srcId, bdId *proxyId, bdId *destId, + int mode, int point, int cbtype, int errcode) +{ + /* Check if we are the originator of the Connect Request. If so, then we do stuff to the CR. + */ + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "mode: " << mode; + std::cerr << " point: " << point; + std::cerr << " cbtype: " << cbtype; + std::cerr << " errcode: " << errcode; + std::cerr << std::endl; + + std::cerr << "\tsrcId: "; + bdStdPrintId(std::cerr, srcId); + std::cerr << std::endl; + std::cerr << "\tproxyId: "; + bdStdPrintId(std::cerr, proxyId); + std::cerr << std::endl; + std::cerr << "\tdestId: "; + bdStdPrintId(std::cerr, destId); + std::cerr << std::endl; + + + if (point != BD_PROXY_CONNECTION_START_POINT) + { + /* ONLY ONE CASE THAT GOES HERE -> for sanity testing */ + if ((cbtype == BITDHT_CONNECT_CB_START) && (point == BD_PROXY_CONNECTION_END_POINT)) + { + std::cerr << "bdConnectManager::callbackConnectRequest() END & START checking ConnectRequest state"; + std::cerr << std::endl; + + // Reverse lookup (srcId). + std::map::iterator it = mConnectionRequests.find(srcId->id); + if (it != mConnectionRequests.end()) + { + if (it->second.mState == BITDHT_CONNREQUEST_INPROGRESS) + { + std::cerr << "bdConnectManager::callbackConnectRequest() ERROR alt CR also in progress!"; + std::cerr << std::endl; + } + } + callbackConnect(srcId, proxyId, destId, mode, point, cbtype, errcode); + return; + } + + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR point != START, should not be receiving this callback, ignoring"; + std::cerr << std::endl; + return; + } + + /* now find our peer in the map */ + std::map::iterator it = mConnectionRequests.find(destId->id); + if (it == mConnectionRequests.end()) + { + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR no associated Connection Request, ignoring"; + std::cerr << std::endl; + return; + } + bdConnectionRequest *cr = &(it->second); + time_t now = time(NULL); + + /* what types of cbtype can we get? + * BITDHT_CONNECT_CB_AUTH not as START + * BITDHT_CONNECT_CB_PENDING not as START + * BITDHT_CONNECT_CB_START YES important, change state to PAUSED and pass up + * BITDHT_CONNECT_CB_PROXY not as START + * BITDHT_CONNECT_CB_FAILED YES most important, trigger next one + */ + + switch(cbtype) + { + default: // all fallthrough. + case BITDHT_CONNECT_CB_AUTH: + case BITDHT_CONNECT_CB_PENDING: + case BITDHT_CONNECT_CB_PROXY: + { + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR unexpected CBTYPE: AUTH/PENDING/PROXY/other. ignoring"; + std::cerr << std::endl; + return; + } + + case BITDHT_CONNECT_CB_FAILED: + { + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "Connection FAILED.... determining if fatal/recycle/next"; + std::cerr << std::endl; + + // one more big switch statement, to decide: fatal/delay/or next + // default is move to next proxy/peer. + bool fatal = false; + bool recycle = false; + + int errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; + int errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; + + switch(errtype) + { + default: + // (These could be fatal or recycle cases... but really ERROR, try NEXT. + case BITDHT_CONNECT_ERROR_GENERIC: + case BITDHT_CONNECT_ERROR_PROTOCOL: + case BITDHT_CONNECT_ERROR_TIMEOUT: // SHould never receive. + { + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR unexpected errcode: " << errcode; + std::cerr << std::endl; + } + break; + + // FATAL ONES. + case BITDHT_CONNECT_ERROR_UNREACHABLE: // END has Unstable ExtAddr. ONLY(PROXYMODE,END) + { + if ((errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) && + (mode == BITDHT_CONNECT_MODE_PROXY)) + { + // fatal. + fatal = true; + + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "END says UNREACHABLE. FATAL ;("; + std::cerr << std::endl; + } + else + { + // error. + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR, UNREACHABLE, but !END"; + std::cerr << std::endl; + } + } + break; + case BITDHT_CONNECT_ERROR_AUTH_DENIED: // END won't accept conn END|PROXY, RELAY|PROXY + { + if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) + { + // fatal. + fatal = true; + + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "END says AUTH_DENIED, fatal"; + std::cerr << std::endl; + } + else if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) + { + // next. (unlikely). + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "WARNING MID says AUTH_DENIED"; + std::cerr << std::endl; + } + else + { + // error. + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR strange AUTH_DENIED"; + std::cerr << std::endl; + } + } + break; + case BITDHT_CONNECT_ERROR_UNSUPPORTED: // mode is unsupprted. fatal or next ANY/ANY + { + if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) + { + // fatal. + fatal = true; + + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "END says UNSUPPORTED, fatal"; + std::cerr << std::endl; + } + else if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) + { + // next. + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "MID says UNSUPPORTED"; + std::cerr << std::endl; + + } + else + { + // error. + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR strange UNSUPPORTED"; + std::cerr << std::endl; + + } + } + break; + + // RECYCLE PROXY + case BITDHT_CONNECT_ERROR_TEMPUNAVAIL: // only END | PROXY, no extAddress + { + if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_END) + { + recycle = true; + + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "END says TEMPUNAVAIL, recycle"; + std::cerr << std::endl; + } + else + { + // next. + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR strange TEMPUNAVAIL"; + std::cerr << std::endl; + + } + } + case BITDHT_CONNECT_ERROR_DUPLICATE: // similar attempt. delay/recycle (ANY/ANY) + { + + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << " DUPLICATE, recycle"; + std::cerr << std::endl; + + recycle = true; + } + break; + case BITDHT_CONNECT_ERROR_OVERLOADED: // not more space. PROXY in RELAY mode. + { + if ((errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) && + (mode == BITDHT_CONNECT_MODE_RELAY)) + { + recycle = true; + + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "MID says OVERLOADED, recycle"; + std::cerr << std::endl; + + } + else + { + //ERROR. + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR strange OVERLOADED"; + std::cerr << std::endl; + } + } + break; + + // NEXT PROXY. + case BITDHT_CONNECT_ERROR_NOADDRESS: //Proxy doesn't know peer MID/(RELAY|PROXY) + { + if (errsrc == BITDHT_CONNECT_ERROR_SOURCE_MID) + { + // could recycle? probably still won't work. + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "MID says NOADDRESS"; + std::cerr << std::endl; + } + else + { + //ERROR. + std::cerr << "bdConnectManager::callbackConnectRequest() "; + std::cerr << "ERROR strange NOADDRESS"; + std::cerr << std::endl; + } + } + break; + } // end of error code switch. + + // Now act on the decision. + int newerrcode = errcode; + if (fatal) + { + /* kill connection request, do callback */ + /* setup for next one */ + cr->mState = BITDHT_CONNREQUEST_DONE; + } + else + { + if (recycle) + { + /* rotate around */ + cr->mGoodProxies.push_back(cr->mCurrentAttempt); + cr->mRecycled++; + } + else + { + cr->mPeersTried.push_back(cr->mCurrentAttempt); + } + + /* setup for next one */ + cr->mState = BITDHT_CONNREQUEST_PAUSED; + cr->mPauseTS = now + BITDHT_CR_PAUSE_BASE_PERIOD + + (int) (bdRandom::random_f32() * BITDHT_CR_PAUSE_RND_PERIOD); + } + + cr->mStateTS = now; + cr->mErrCode = errcode; + + /* just pass on the callbackConnect() */ + callbackConnect(srcId, proxyId, destId, mode, point, cbtype, errcode); + + return; // CALLBACK FINISHED for FAILURE CODES. + + } + break; + case BITDHT_CONNECT_CB_START: + { + + cr->mState = BITDHT_CONNREQUEST_EXTCONNECT; + cr->mStateTS = now; + + callbackConnect(srcId, proxyId, destId, mode, point, cbtype, errcode); + + } + break; + } +} + + + +/************************************************************************************************************ +************************************** END of Connection Requests ******************************************* +************************************************************************************************************/ + +/************************************************************************************************************ +****************************************** Outgoing Triggers ************************************************ +************************************************************************************************************/ + +/*** Called by iterator. + * initiates the connection startup + * + * srcConnAddr must contain Own ID + Connection Port (DHT or TOU depending on Mode). + * + * For a DIRECT Connection: proxyId == destination Id, and mode == DIRECT. + * + * For RELAY | PROXY Connection: + * + * In all cases, destConnAddr doesn't need to contain a valid address. + */ + +int bdConnectManager::startConnectionAttempt(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode) +{ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::startConnectionAttempt()"; + std::cerr << std::endl; +#endif + + if (!(mConfigAllowedModes & mode)) + { + /* MODE not supported */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::startConnectionAttempt() ERROR Mode Not Supported"; + std::cerr << std::endl; +#endif + return 0; + } + + /* Check for existing Connection */ + bdConnection *conn = findExistingConnectionBySender(proxyId, srcConnAddr, destConnAddr); + if (conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::startConnectAttempt() ERROR EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return 0; + } + + { + // DO A CALLBACK to TELL higher levels, we are starting a connection attempt. + int point = BD_PROXY_CONNECTION_START_POINT; + int cbtype = BITDHT_CONNECT_CB_REQUEST; + int errcode = 0; + callbackConnect(srcConnAddr, proxyId, destConnAddr, mode, point, cbtype, errcode); + } + + /* INSTALL a NEW CONNECTION */ + // not offically playing by the rules, but it should work. + conn = newConnectionBySender(proxyId, srcConnAddr, destConnAddr); + + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { + /* proxy is the real peer address, destConnAddr has an invalid address */ + conn->ConnectionSetupDirect(proxyId, srcConnAddr); + } + else + { + conn->ConnectionSetup(proxyId, srcConnAddr, destConnAddr, mode); + } + + + int msgtype = BITDHT_MSG_TYPE_CONNECT_REQUEST; + int status = BITDHT_CONNECT_ANSWER_OKAY; + mPub->send_connect_msg(&(conn->mProxyId), msgtype, + &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, status); + + return 1; +} + +/* This will be called in response to a callback. + * the callback could be with regard to: + * a Direct EndPoint. + * a Proxy Proxy, or an Proxy EndPoint. + * a Relay Proxy, or an Relay EndPoint. + * + * If we are going to store the minimal amount in the bdNode about connections, + * then the parameters must contain all the information: + * + * case 1: + * + */ + +void bdConnectManager::AuthConnectionOk(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc) +{ + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionOk()"; + std::cerr << std::endl; +#endif + + /* Check for existing Connection */ + bdConnection *conn = findExistingConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionOk() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return; + } + + /* we need to continue the connection */ + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { + if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionOk() Direct Connection, in WAITING_AUTH state... Authorising Direct Connect"; + std::cerr << std::endl; +#endif + /* This pushes it into the START/ACK cycle, + * which handles messages elsewhere + */ + conn->AuthoriseDirectConnection(srcId, proxyId, destId, mode, loc); + } + else + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionOk() ERROR Direct Connection, !WAITING_AUTH state... Ignoring"; + std::cerr << std::endl; +#endif + + } + return; + } + + if (loc == BD_PROXY_CONNECTION_END_POINT) + { + if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionOk() Proxy End Connection, in WAITING_AUTH state... Authorising"; + std::cerr << std::endl; +#endif + /*** XXX MUST RECEIVE THE ADDRESS FROM DEST for connection */ + conn->AuthoriseEndConnection(srcId, proxyId, destId, mode, loc); + + /* we respond to the proxy which will finalise connection */ + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + int status = BITDHT_CONNECT_ANSWER_OKAY; + mPub->send_connect_msg(&(conn->mProxyId), msgtype, + &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, status); + + return; + } + else + { + + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionOk() ERROR Proxy End Connection, !WAITING_AUTH state... Ignoring"; + std::cerr << std::endl; +#endif + } + } + + if (conn->mState == BITDHT_CONNECTION_WAITING_AUTH) + { + /* otherwise we are the proxy (for either), pass on the request */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionOk() Proxy Mid Connection, in WAITING_AUTH state... Authorising"; + std::cerr << std::endl; +#endif + + /* SEARCH for IP:Port of destination is done before AUTH */ + + conn->AuthoriseProxyConnection(srcId, proxyId, destId, mode, loc); + + int msgtype = BITDHT_MSG_TYPE_CONNECT_REQUEST; + int status = BITDHT_CONNECT_ANSWER_OKAY; + mPub->send_connect_msg(&(conn->mDestId), msgtype, + &(conn->mSrcConnAddr), &(conn->mDestConnAddr), conn->mMode, status); + } + else + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionOk() ERROR Proxy Mid Connection, !WAITING_AUTH state... Ignoring"; + std::cerr << std::endl; +#endif + } + + return; +} + + + + +void bdConnectManager::AuthConnectionNo(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int errCode) +{ + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionNo()"; + std::cerr << std::endl; +#endif + + /* Check for existing Connection */ + bdConnection *conn = findExistingConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionNo() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return; + } + + /* we need indicate failure of the connection */ + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + uint32_t status = createConnectionErrorCode(errCode, BITDHT_CONNECT_ERROR_AUTH_DENIED, conn->mPoint); + + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { + /* we respond to the proxy which will finalise connection */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionNo() Direct End Connection Cleaning up"; + std::cerr << std::endl; +#endif + mPub->send_connect_msg(&(conn->mSrcId), msgtype, + &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, status); + + cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + return; + } + + if (loc == BD_PROXY_CONNECTION_END_POINT) + { + /* we respond to the proxy which will finalise connection */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionNo() Proxy End Connection Cleaning up"; + std::cerr << std::endl; +#endif + mPub->send_connect_msg(&(conn->mProxyId), msgtype, + &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, status); + + cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + + return; + } + + /* otherwise we are the proxy (for either), reply FAIL */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::AuthConnectionNo() Proxy Mid Connection Cleaning up"; + std::cerr << std::endl; +#endif + mPub->send_connect_msg(&(conn->mSrcId), msgtype, + &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, status); + + cleanConnection(&(srcId->id), &(proxyId->id), &(destId->id)); + + return; +} + + + + + +void bdConnectManager::iterateConnections() +{ + std::map::iterator it; + std::list eraseList; + time_t now = time(NULL); + + for(it = mConnections.begin(); it != mConnections.end(); it++) + { + if (now - it->second.mLastEvent > BD_CONNECTION_MAX_TIMEOUT) + { + /* cleanup event */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::iterateConnections() Connection Timed Out: " << (it->first); + std::cerr << std::endl; +#endif + eraseList.push_back(it->first); + continue; + } + + if ((it->second.mState == BITDHT_CONNECTION_WAITING_ACK) && + (now - it->second.mLastStart > BD_CONNECTION_START_RETRY_PERIOD)) + { + if (it->second.mRetryCount > BD_CONNECTION_START_MAX_RETRY) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle, Too many iterations: " << it->first; + std::cerr << std::endl; +#endif + /* connection failed! cleanup */ + if ((it->second.mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) + { + uint32_t errCode = createConnectionErrorCode(0, + BITDHT_CONNECT_ERROR_TIMEOUT,it->second.mPoint); + callbackConnect(&(it->second.mSrcId),&(it->second.mProxyId), + &(it->second.mDestId), it->second.mMode, it->second.mPoint, + BITDHT_CONNECT_CB_FAILED, errCode); + } + + /* add to erase list */ + eraseList.push_back(it->first); + } + else + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::iterateConnections() Start/ACK cycle, Retransmitting START: " << it->first; + std::cerr << std::endl; +#endif + it->second.mLastStart = now; + it->second.mRetryCount++; + if (!it->second.mSrcAck) + { + int msgtype = BITDHT_MSG_TYPE_CONNECT_START; + mPub->send_connect_msg(&(it->second.mSrcId), msgtype, + &(it->second.mSrcConnAddr), &(it->second.mDestConnAddr), + it->second.mMode, it->second.mBandwidth); + } + if (!it->second.mDestAck) + { + int msgtype = BITDHT_MSG_TYPE_CONNECT_START; + mPub->send_connect_msg(&(it->second.mDestId), msgtype, + &(it->second.mSrcConnAddr), &(it->second.mDestConnAddr), + it->second.mMode, it->second.mBandwidth); + } + } + } + } + + /* clean up */ + while(eraseList.size() > 0) + { + bdProxyTuple tuple = eraseList.front(); + eraseList.pop_front(); + + std::map::iterator eit = mConnections.find(tuple); + mConnections.erase(eit); + } +} + + + + +/************************************************************************************************************ +****************************************** Callback Functions ******************************************** +************************************************************************************************************/ + + +void bdConnectManager::callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, + int mode, int point, int cbtype, int errcode) +{ + /* This is overloaded at a higher level */ + mPub->callbackConnect(srcId, proxyId, destId, mode, point, cbtype, errcode); +} + + +/************************************************************************************************************ +************************************** ProxyTuple + Connection State **************************************** +************************************************************************************************************/ + +int operator<(const bdProxyTuple &a, const bdProxyTuple &b) +{ + if (a.srcId < b.srcId) + { + return 1; + } + + if (a.srcId == b.srcId) + { + if (a.proxyId < b.proxyId) + { + return 1; + } + else if (a.proxyId == b.proxyId) + { + if (a.destId < b.destId) + { + return 1; + } + } + } + return 0; +} + +int operator==(const bdProxyTuple &a, const bdProxyTuple &b) +{ + if ((a.srcId == b.srcId) && (a.proxyId == b.proxyId) && (a.destId == b.destId)) + { + return 1; + } + return 0; +} + +std::ostream &operator<<(std::ostream &out, const bdProxyTuple &t) +{ + out << "[---"; + bdStdPrintNodeId(out, &(t.srcId)); + out << "---"; + bdStdPrintNodeId(out, &(t.proxyId)); + out << "---"; + bdStdPrintNodeId(out, &(t.destId)); + out << "---]"; + + return out; +} + +bdConnection::bdConnection() +{ + /* DUMMY INITIALISATION FOR ALL DATA - DON"T THINK IT MATTERS + * But keeps Valgrind happy + */ + + /* Connection State, and TimeStamp of Update */ + int mState = 0; + time_t mLastEvent = 0; + // + ///* Addresses of Start/Proxy/End Nodes */ + //bdId mSrcId; + //bdId mDestId; + //bdId mProxyId; + // + ///* Where we are in the connection, + //* and what connection mode. + //*/ + int mPoint = 0; + int mMode = 0; + // + ///* must have ip:ports of connection ends (if proxied) */ + //bdId mSrcConnAddr; + //bdId mDestConnAddr; + // + int mBandwidth = 0; + // + ///* START/ACK Finishing ****/ + time_t mLastStart = 0; /* timer for retries */ + int mRetryCount = 0; /* retry counter */ + // + bool mSrcAck = false; + bool mDestAck = false; + // + //// Completion TS. + time_t mCompletedTS = 0; +} + + /* heavy check, used to check for alternative connections, coming from other direction + * Caller must switch src/dest to use it properly (otherwise it'll find your connection!) + */ +bdConnection *bdConnectManager::findSimilarConnection(bdNodeId *srcId, bdNodeId *destId) +{ + std::map::iterator it; + for(it = mConnections.begin(); it != mConnections.end(); it++) + { + if ((it->first.srcId == *srcId) && (it->first.destId == *destId)) + { + /* found similar connection */ + return &(it->second); + } + } + return NULL; +} + +bdConnection *bdConnectManager::findExistingConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) +{ + bdProxyTuple tuple(srcId, proxyId, destId); + + std::cerr << "bdConnectManager::findExistingConnection() Looking For: " << tuple << std::endl; + + std::map::iterator it = mConnections.find(tuple); + if (it == mConnections.end()) + { + std::cerr << "bdConnectManager::findExistingConnection() Failed to Find: " << tuple << std::endl; + return NULL; + } + + std::cerr << "bdConnectManager::findExistingConnection() Found: " << tuple << std::endl; + return &(it->second); +} + +bdConnection *bdConnectManager::newConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) +{ + bdProxyTuple tuple(srcId, proxyId, destId); + bdConnection conn; + + std::cerr << "bdConnectManager::newConnection() Installing: " << tuple << std::endl; + + mConnections[tuple] = conn; + std::map::iterator it = mConnections.find(tuple); + if (it == mConnections.end()) + { + std::cerr << "bdConnectManager::newConnection() ERROR Installing: " << tuple << std::endl; + return NULL; + } + return &(it->second); +} + +int bdConnectManager::cleanConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId) +{ + bdProxyTuple tuple(srcId, proxyId, destId); + bdConnection conn; + + std::cerr << "bdConnectManager::cleanConnection() Removing: " << tuple << std::endl; + + std::map::iterator it = mConnections.find(tuple); + if (it == mConnections.end()) + { + std::cerr << "bdConnectManager::cleanConnection() ERROR Removing: " << tuple << std::endl; + return 0; + } + mConnections.erase(it); + + return 1; +} + + +int bdConnectManager::determinePosition(bdNodeId *sender, bdNodeId *src, bdNodeId *dest) +{ + int pos = BD_PROXY_CONNECTION_UNKNOWN_POINT; + if (mOwnId == *src) + { + pos = BD_PROXY_CONNECTION_START_POINT; + } + else if (mOwnId == *dest) + { + pos = BD_PROXY_CONNECTION_END_POINT; + } + else + { + pos = BD_PROXY_CONNECTION_MID_POINT; + } + return pos; +} + +int bdConnectManager::determineProxyId(bdNodeId *sender, bdNodeId *src, bdNodeId *dest, bdNodeId *proxyId) +{ + int pos = determinePosition(sender, src, dest); + switch(pos) + { + case BD_PROXY_CONNECTION_START_POINT: + case BD_PROXY_CONNECTION_END_POINT: + *proxyId = *sender; + return 1; + break; + default: + case BD_PROXY_CONNECTION_MID_POINT: + *proxyId = mOwnId; + return 1; + break; + } + return 0; +} + + + +bdConnection *bdConnectManager::findExistingConnectionBySender(bdId *sender, bdId *src, bdId *dest) +{ + bdNodeId proxyId; + bdNodeId *senderId = &(sender->id); + bdNodeId *srcId = &(src->id); + bdNodeId *destId = &(dest->id); + determineProxyId(senderId, srcId, destId, &proxyId); + + return findExistingConnection(srcId, &proxyId, destId); +} + +bdConnection *bdConnectManager::newConnectionBySender(bdId *sender, bdId *src, bdId *dest) +{ + bdNodeId proxyId; + bdNodeId *senderId = &(sender->id); + bdNodeId *srcId = &(src->id); + bdNodeId *destId = &(dest->id); + determineProxyId(senderId, srcId, destId, &proxyId); + + return newConnection(srcId, &proxyId, destId); +} + + +int bdConnectManager::cleanConnectionBySender(bdId *sender, bdId *src, bdId *dest) +{ + bdNodeId proxyId; + bdNodeId *senderId = &(sender->id); + bdNodeId *srcId = &(src->id); + bdNodeId *destId = &(dest->id); + determineProxyId(senderId, srcId, destId, &proxyId); + + return cleanConnection(srcId, &proxyId, destId); +} + + +/************************************************************************************************************ +****************************************** Received Connect Msgs ******************************************** +************************************************************************************************************/ + + +/* This function is triggered by a CONNECT_REQUEST message. + * it will occur on both the Proxy/Dest in the case of a Proxy (PROXY | RELAY) and on the Dest (DIRECT) nodes. + * + * In all cases, we store the request and ask for authentication. + * + */ + + + +int bdConnectManager::recvedConnectionRequest(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode) +{ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::recvedConnectionRequest()"; + std::cerr << std::endl; +#endif + + if (!(mConfigAllowedModes & mode)) + { + /* MODE not supported */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Mode Not Supported"; + std::cerr << std::endl; +#endif + /* reply existing connection */ + int pos = determinePosition(&(id->id), &(srcConnAddr->id), &(destConnAddr->id)); + uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_UNSUPPORTED, pos); + + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, status); + + return 0; + } + + /* Check for existing Connection */ + bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); + if (conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::recvedConnectionRequest() ERROR EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + /* reply existing connection */ + uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_DUPLICATE, conn->mPoint); + + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, status); + + return 0; + } + + + /* Switch the order of peers around to test for "opposite connections" */ + if (NULL != findSimilarConnection(&(destConnAddr->id), &(srcConnAddr->id))) + { + std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Found Similar Connection. Replying NO"; + std::cerr << std::endl; + + /* reply existing connection */ + int pos = determinePosition(&(id->id), &(srcConnAddr->id), &(destConnAddr->id)); + uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_DUPLICATE, pos); + + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, status); + return 0; + } + + /* INSTALL a NEW CONNECTION */ + conn = bdConnectManager::newConnectionBySender(id, srcConnAddr, destConnAddr); + + int point = 0; + if (mode == BITDHT_CONNECT_MODE_DIRECT) + { +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::recvedConnectionRequest() Installing DIRECT CONNECTION"; + std::cerr << std::endl; +#endif + + /* we are actually the end node, store stuff, get auth and on with it! */ + point = BD_PROXY_CONNECTION_END_POINT; + + conn->ConnectionRequestDirect(id, srcConnAddr, destConnAddr); + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::recvedConnectionRequest() Connection State:"; + std::cerr << std::endl; + std::cerr << *conn; + std::cerr << std::endl; +#endif + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_AUTH, + BITDHT_CONNECT_ERROR_NONE); + } + else + { + /* check if we are proxy, or end point */ + bool areProxy = (srcConnAddr->id == id->id); + if (areProxy) + { + std::cerr << "bdConnectManager::recvedConnectionRequest() We are MID Point for Proxy / Relay Connection."; + std::cerr << std::endl; + + point = BD_PROXY_CONNECTION_MID_POINT; + + /* SEARCH for IP:Port of destination before AUTH */ + int numNodes = 10; + std::list matchingIds; + + std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING searching for \"VERSION\" flag... TO FIX LATER"; + std::cerr << std::endl; + + uint32_t with_flag = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; + //BITDHT_PEER_STATUS_DHT_APPL | BITDHT_PEER_STATUS_DHT_APPL_VERSION); + + bool proxyOk = false; + bdId destId; + + if (mNodeSpace->find_node(&(destConnAddr->id), numNodes, matchingIds, with_flag)) + { + std::cerr << "bdConnectManager::recvedConnectionRequest() Found Suitable Destination Addr"; + std::cerr << std::endl; + + if (matchingIds.size() > 1) + { + /* WARNING multiple matches */ + std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING Found Multiple Matching Destination Addr"; + std::cerr << std::endl; + } + + proxyOk = true; + destId = matchingIds.front(); + } + + if (proxyOk) + { + std::cerr << "bdConnectManager::recvedConnectionRequest() Proxy Addr Ok: "; + bdStdPrintId(std::cerr, destConnAddr); + std::cerr << "asking for AUTH to continue"; + std::cerr << std::endl; + + conn->ConnectionRequestProxy(id, srcConnAddr, &mOwnId, &destId, mode); + + /* ALLOW AUTO AUTH for MID Proxy Connections. */ + if (mConfigAutoProxy) + { + AuthConnectionOk(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint); + } + else + { + + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_AUTH, + BITDHT_CONNECT_ERROR_NONE); + } + } + else + { + /* clean up connection... its not going to work */ + std::cerr << "bdConnectManager::recvedConnectionRequest() WARNING No Proxy Addr, Shutting Connect Attempt"; + std::cerr << std::endl; + + + /* send FAIL message to SRC */ + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + uint32_t status = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_NOADDRESS, point); + mPub->send_connect_msg(id, msgtype, srcConnAddr, destConnAddr, mode, status); + + /* remove connection */ + bdConnectManager::cleanConnectionBySender(id, srcConnAddr, destConnAddr); + + } + } + else + { + std::cerr << "bdConnectManager::recvedConnectionRequest() END Proxy/Relay Connection, asking for AUTH to continue"; + std::cerr << std::endl; + + point = BD_PROXY_CONNECTION_END_POINT; + + conn->ConnectionRequestEnd(id, srcConnAddr, destConnAddr, mode); + + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_AUTH, + BITDHT_CONNECT_ERROR_NONE); + } + } + return 1; +} + + +/* This function is triggered by a CONNECT_REPLY message. + * it will occur on either the Proxy or Source. And indicates YES / NO to the connection, + * as well as supplying address info to the proxy. + * + */ + +int bdConnectManager::recvedConnectionReply(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int status) +{ + /* retrieve existing connection data */ + bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::recvedConnectionReply() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return 0; + } + + switch(conn->mPoint) + { + case BD_PROXY_CONNECTION_START_POINT: + case BD_PROXY_CONNECTION_END_POINT: /* NEVER EXPECT THIS */ + case BD_PROXY_CONNECTION_UNKNOWN_POINT: /* NEVER EXPECT THIS */ + default: /* NEVER EXPECT THIS */ + { + + + /* Only situation we expect this, is if the connection is not allowed. + * DEST has sent back an ERROR Message + */ + uint32_t errCode = BITDHT_CONNECT_ERROR_GENERIC; + if ((status != BITDHT_CONNECT_ANSWER_OKAY) && (conn->mPoint == BD_PROXY_CONNECTION_START_POINT)) + { + /* connection is killed */ + std::cerr << "bdConnectManager::recvedConnectionReply() WARNING Connection Rejected. Error: "; + std::cerr << decodeConnectionError(status); + std::cerr << ", Killing It: "; + std::cerr << std::endl; + std::cerr << *conn; + std::cerr << std::endl; + errCode = status; // Pass on the Error Message. + + } + else + { + /* ERROR in protocol */ + std::cerr << "bdConnectManager::recvedConnectionReply() ERROR Unexpected Message, Killing It: "; + std::cerr << std::endl; + std::cerr << *conn; + std::cerr << std::endl; + errCode = createConnectionErrorCode(0, BITDHT_CONNECT_ERROR_PROTOCOL, conn->mPoint ); + } + + /* do Callback for Failed Connection */ + if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) + { + /* As we started the connection, callback internally first! */ + callbackConnectRequest(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_FAILED, errCode); + } + else + { + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_FAILED, errCode); + } + + /* Kill Connection always */ + cleanConnectionBySender(id, srcConnAddr, destConnAddr); + + return 0; + } + break; + + case BD_PROXY_CONNECTION_MID_POINT: + { + /* We are proxy. and OK / NOK for connection proceed. + */ + + if ((status == BITDHT_CONNECT_ANSWER_OKAY) && (conn->mState == BITDHT_CONNECTION_WAITING_REPLY)) + { + /* OK, continue connection! */ + std::cerr << "bdConnectManager::recvedConnectionReply() @MIDPOINT. Reply + State OK, continuing connection"; + std::cerr << std::endl; + + /* Upgrade Connection to Finishing Mode */ + conn->upgradeProxyConnectionToFinish(id, srcConnAddr, destConnAddr, mode, status); + + /* do Callback for Pending Connection */ + /* DONT CALLBACK in AutoProxy Mode: (PROXY & mConfigAutoProxy) */ + if ((conn->mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) + { + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_PENDING, + BITDHT_CONNECT_ERROR_NONE); + } + + return 1; + } + else + { + + + std::cerr << "bdConnectManager::recvedConnectionReply() WARNING @MIDPOINT recved Error: "; + std::cerr << decodeConnectionError(status); + std::cerr << " Killing It: "; + std::cerr << std::endl; + std::cerr << *conn; + std::cerr << std::endl; + + uint32_t errCode = status; + if (errCode == BITDHT_CONNECT_ERROR_NONE) + { + errCode = createConnectionErrorCode(0, + BITDHT_CONNECT_ERROR_PROTOCOL, conn->mPoint ); + } + + /* do Callback for Failed Connection */ + /* DONT CALLBACK in AutoProxy Mode: (PROXY & mConfigAutoProxy) */ + if ((conn->mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) + { + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_FAILED, errCode); + } + + + /* send on message to SRC */ + int msgtype = BITDHT_MSG_TYPE_CONNECT_REPLY; + mPub->send_connect_msg(&(conn->mSrcId), msgtype, &(conn->mSrcConnAddr), &(conn->mDestConnAddr), mode, errCode); + + /* connection is killed */ + cleanConnectionBySender(id, srcConnAddr, destConnAddr); + } + return 0; + } + break; + } + return 0; +} + + +/* This function is triggered by a CONNECT_START message. + * it will occur on both the Src/Dest in the case of a Proxy (PROXY | RELAY) and on the Src (DIRECT) nodes. + * + * parameters are checked against pending connections. + * Acks are set, and connections completed if possible (including callback!). + */ + +int bdConnectManager::recvedConnectionStart(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int bandwidth) +{ + std::cerr << "bdConnectManager::recvedConnectionStart()"; + std::cerr << std::endl; + + /* retrieve existing connection data */ + bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::recvedConnectionStart() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return 0; + } + + + if (conn->mPoint == BD_PROXY_CONNECTION_MID_POINT) + { + std::cerr << "bdConnectManager::recvedConnectionStart() ERROR We Are Connection MID Point"; + std::cerr << std::endl; + /* ERROR */ + } + + /* check state */ + if ((conn->mState != BITDHT_CONNECTION_WAITING_START) && (conn->mState != BITDHT_CONNECTION_COMPLETED)) + { + /* ERROR */ + std::cerr << "bdConnectManager::recvedConnectionStart() ERROR State != WAITING_START && != COMPLETED"; + std::cerr << std::endl; + + return 0; + } + + /* ALL Okay, Send ACK */ + std::cerr << "bdConnectManager::recvedConnectionStart() Passed basic tests, Okay to send ACK"; + std::cerr << std::endl; + + int msgtype = BITDHT_MSG_TYPE_CONNECT_ACK; + int status = BITDHT_CONNECT_ANSWER_OKAY; + mPub->send_connect_msg(id, msgtype, &(conn->mSrcId), &(conn->mDestId), mode, status); + + /* do complete Callback */ + + /* flag as completed */ + if (conn->mState != BITDHT_CONNECTION_COMPLETED) + { + std::cerr << "bdConnectManager::recvedConnectionStart() Switching State to COMPLETED, doing callback"; + std::cerr << std::endl; + + conn->CompleteConnection(id, srcConnAddr, destConnAddr); + + std::cerr << "bdConnectManager::recvedConnectionStart() Connection State: "; + std::cerr << *conn; + std::cerr << std::endl; + + + if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) + { + /* internal callback first */ + callbackConnectRequest(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestConnAddr), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_START, + BITDHT_CONNECT_ERROR_NONE); + + } + else + { + /* internal callback first */ + callbackConnectRequest(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestConnAddr), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_START, + BITDHT_CONNECT_ERROR_NONE); + } + + } + else + { + std::cerr << "bdConnectManager::recvedConnectionStart() Just sent duplicate ACK"; + std::cerr << std::endl; + } + /* don't delete, if ACK is lost, we want to be able to re-respond */ + + return 1; +} + + +/* This function is triggered by a CONNECT_ACK message. + * it will occur on both the Proxy (PROXY | RELAY) and on the Dest (DIRECT) nodes. + * + * parameters are checked against pending connections. + * Acks are set, and connections completed if possible (including callback!). + */ + +int bdConnectManager::recvedConnectionAck(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode) +{ + /* retrieve existing connection data */ + bdConnection *conn = findExistingConnectionBySender(id, srcConnAddr, destConnAddr); + if (!conn) + { + /* ERROR */ +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdConnectManager::recvedConnectionAck() ERROR NO EXISTING CONNECTION"; + std::cerr << std::endl; +#endif + return 0; + } + + if (conn->mPoint == BD_PROXY_CONNECTION_START_POINT) + { + /* ERROR */ + std::cerr << "bdConnectManager::recvedConnectionAck() ERROR ACK received at START POINT"; + std::cerr << std::endl; + + return 0; + } + + /* check state */ + if (conn->mState != BITDHT_CONNECTION_WAITING_ACK) + { + /* ERROR */ + std::cerr << "bdConnectManager::recvedConnectionAck() conn->mState != WAITING_ACK, actual State: " << conn->mState; + std::cerr << std::endl; + + return 0; + } + + if (id->id == srcConnAddr->id) + { + std::cerr << "bdConnectManager::recvedConnectionAck() from Src, marking So"; + std::cerr << std::endl; + + /* recved Ack from source */ + conn->mSrcAck = true; + } + else if (id->id == destConnAddr->id) + { + std::cerr << "bdConnectManager::recvedConnectionAck() from Dest, marking So"; + std::cerr << std::endl; + /* recved Ack from dest */ + conn->mDestAck = true; + } + + if (conn->mSrcAck && conn->mDestAck) + { + std::cerr << "bdConnectManager::recvedConnectionAck() ACKs from Both Src & Dest, Connection Complete: callback & cleanup"; + std::cerr << std::endl; + + /* connection complete! cleanup */ + if (conn->mMode == BITDHT_CONNECT_MODE_DIRECT) + { + int mode = conn->mMode | BITDHT_CONNECT_ANSWER_OKAY; + /* callback to connect to Src address! */ + // Slightly different callback, use ConnAddr for start message! + // Also callback to ConnectionRequest first. + // ACTUALLY we are END, so shouldn't (AT This Point do this). + callbackConnect(&(conn->mSrcConnAddr),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_START, + BITDHT_CONNECT_ERROR_NONE); + + } + else + { + /* DONT CALLBACK in AutoProxy Mode: (PROXY & mConfigAutoProxy) */ + if ((conn->mMode != BITDHT_CONNECT_MODE_PROXY) || (!mConfigAutoProxy)) + { + callbackConnect(&(conn->mSrcId),&(conn->mProxyId),&(conn->mDestId), + conn->mMode, conn->mPoint, BITDHT_CONNECT_CB_PROXY, + BITDHT_CONNECT_ERROR_NONE); + } + + + } + + /* Finished Connection! */ + cleanConnectionBySender(id, srcConnAddr, destConnAddr); + } + return 1; +} + + + +/************************************************************************************************************ +********************************* Connection / ConnectionRequest Functions ********************************** +************************************************************************************************************/ + +// Initialise a new Connection (request by User) + +// Any Connection initialised at Source (START_POINT), prior to Auth. +int bdConnection::ConnectionSetup(bdId *proxyId, bdId *srcConnAddr, bdId *destId, int mode) +{ + mState = BITDHT_CONNECTION_WAITING_START; /* or REPLY, no AUTH required */ + mLastEvent = time(NULL); + mSrcId = *srcConnAddr; /* self, IP unknown */ + mDestId = *destId; /* dest, IP unknown */ + mProxyId = *proxyId; /* full proxy/dest address */ + + mPoint = BD_PROXY_CONNECTION_START_POINT; + mMode = mode; + + mSrcConnAddr = *srcConnAddr; /* self, full ID/IP */ + mDestConnAddr = *destId; /* IP unknown */ + + /* clear IP Addresses to enforce this */ + bdsockaddr_clear(&(mSrcId.addr)); + bdsockaddr_clear(&(mDestId.addr)); + bdsockaddr_clear(&(mDestConnAddr.addr)); + + /* don't bother with START/ACK parameters */ + + return 1; +} + +int bdConnection::ConnectionSetupDirect(bdId *destId, bdId *srcConnAddr) +{ + mState = BITDHT_CONNECTION_WAITING_START; /* or REPLY, no AUTH required */ + mLastEvent = time(NULL); + mSrcId = *srcConnAddr; /* self, IP unknown */ + mDestId = *destId; /* full proxy/dest address */ + mProxyId = *destId; /* full proxy/dest address */ + + mPoint = BD_PROXY_CONNECTION_START_POINT; + mMode = BITDHT_CONNECT_MODE_DIRECT; + + mSrcConnAddr = *srcConnAddr; /* self, full ID/IP */ + mDestConnAddr = *destId; /* IP unknown */ + + /* clear IP Addresses to enforce this */ + bdsockaddr_clear(&(mSrcId.addr)); + bdsockaddr_clear(&(mDestConnAddr.addr)); + + /* don't bother with START/ACK parameters */ + + return 1; +} + + + +// Initialise a new Connection. (receiving a Connection Request) +// Direct Connection initialised at Destination (END_POINT), prior to Auth. +int bdConnection::ConnectionRequestDirect(bdId *id, bdId *srcConnAddr, bdId *destId) +{ + mState = BITDHT_CONNECTION_WAITING_AUTH; + mLastEvent = time(NULL); + mSrcId = *id; /* peer ID/IP known */ + mDestId = *destId; /* self, IP unknown */ + mProxyId = *id; /* src ID/IP known */ + + mPoint = BD_PROXY_CONNECTION_END_POINT; + mMode = BITDHT_CONNECT_MODE_DIRECT; + + mSrcConnAddr = *srcConnAddr; /* connect address ID/IP known */ + mDestConnAddr = *destId; /* self IP unknown */ + + /* clear IP Addresses to enforce this */ + bdsockaddr_clear(&(mDestId.addr)); + bdsockaddr_clear(&(mDestConnAddr.addr)); + + /* don't bother with START/ACK parameters */ + + return 1; +} + + +// Proxy Connection initialised at Proxy (MID_POINT), prior to Auth. +int bdConnection::ConnectionRequestProxy(bdId *id, bdId *srcConnAddr, bdNodeId *ownId, bdId *destId, int mode) +{ + mState = BITDHT_CONNECTION_WAITING_AUTH; + mLastEvent = time(NULL); + mSrcId = *id; /* ID/IP Known */ + mDestId = *destId; /* destination, ID/IP known */ + mProxyId.id = *ownId; /* own id, must be set for callback, IP Unknown */ + + mPoint = BD_PROXY_CONNECTION_MID_POINT; + mMode = mode; + + mSrcConnAddr = *srcConnAddr; + mDestConnAddr = *destId; /* other peer, IP unknown */ + + /* clear IP Addresses to enforce this */ + bdsockaddr_clear(&(mProxyId.addr)); + bdsockaddr_clear(&(mDestConnAddr.addr)); + + /* don't bother with START/ACK parameters */ + + return 1; +} + + +// Proxy Connection initialised at Destination (END_POINT), prior to Auth. +int bdConnection::ConnectionRequestEnd(bdId *id, bdId *srcId, bdId *destId, int mode) +{ + mState = BITDHT_CONNECTION_WAITING_AUTH; + mLastEvent = time(NULL); + mSrcId = *srcId; /* src IP unknown */ + mDestId = *destId; /* self, IP unknown */ + mProxyId = *id; /* src of message, full ID/IP of proxy */ + + mPoint = BD_PROXY_CONNECTION_END_POINT; + mMode = mode; + + mSrcConnAddr = *srcId; /* ID, not IP */ + mDestConnAddr = *destId; /* ID, not IP */ + + /* clear IP Addresses to enforce this */ + bdsockaddr_clear(&(mSrcId.addr)); + bdsockaddr_clear(&(mDestId.addr)); + bdsockaddr_clear(&(mSrcConnAddr.addr)); + bdsockaddr_clear(&(mDestConnAddr.addr)); + + /* don't bother with START/ACK parameters */ + + return 1; +} + +// Received AUTH, step up to next stage. +// Search for dest ID/IP is done before AUTH. so actually nothing to do here, except set the state +int bdConnection::AuthoriseProxyConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc) +{ + mState = BITDHT_CONNECTION_WAITING_REPLY; + mLastEvent = time(NULL); + + //mSrcId, (peer) (ID/IP known) + //mDestId (other peer) (ID/IP known) + //mProxyId (self) (IP unknown) + + // mPoint, mMode should be okay. + + // mSrcConnAddr (ID/IP known) + // mDestConnAddr is still pending. + + /* clear IP Addresses to enforce this */ + bdsockaddr_clear(&(mProxyId.addr)); + bdsockaddr_clear(&(mDestConnAddr.addr)); + + /* don't bother with START/ACK parameters */ + + return 1; +} + + +/* we are end of a Proxy Connection */ +int bdConnection::AuthoriseEndConnection(bdId *srcId, bdId *proxyId, bdId *destConnAddr, int mode, int loc) +{ + mState = BITDHT_CONNECTION_WAITING_START; + mLastEvent = time(NULL); + + //mSrcId, (peer) should be okay. (IP unknown) + //mDestId (self) doesn't matter. (IP unknown) + //mProxyId (peer) should be okay. (ID/IP known) + + // mPoint, mMode should be okay. + + // mSrcConnAddr should be okay. (IP unknown) + // Install the correct destConnAddr. (just received) + mDestConnAddr = *destConnAddr; + + /* clear IP Addresses to enforce this */ + bdsockaddr_clear(&(mSrcId.addr)); + bdsockaddr_clear(&(mDestId.addr)); + bdsockaddr_clear(&(mSrcConnAddr.addr)); + + + // Initialise the START/ACK Parameters. + mRetryCount = 0; + mLastStart = 0; + mSrcAck = false; + mDestAck = true; // Automatic ACK, as it is from us. + mCompletedTS = 0; + + return 1; +} + + + + +// Auth of the Direct Connection, means we move straight to WAITING_ACK mode. +int bdConnection::AuthoriseDirectConnection(bdId *srcId, bdId *proxyId, bdId *destConnAddr, int mode, int loc) +{ + mState = BITDHT_CONNECTION_WAITING_ACK; + mLastEvent = time(NULL); + + //mSrcId, (peer) should be okay. (ID/IP known) + //mDestId (self) doesn't matter. (IP Unknown) + //mProxyId (peer) should be okay. (ID/IP known) + + // mPoint, mMode should be okay. + + // mSrcConnAddr should be okay. (ID/IP known) + // Install the correct destConnAddr. (just received) + mDestConnAddr = *destConnAddr; + + /* clear IP Addresses to enforce this */ + bdsockaddr_clear(&(mDestId.addr)); + + // Should we check for these? This will not help for the Dest address, as we just blanked it above! */ + checkForDefaultConnectAddress(); + + // Initialise the START/ACK Parameters. + mRetryCount = 0; + mLastStart = 0; + mSrcAck = false; + mDestAck = true; // Automatic ACK, as it is from us. + mCompletedTS = 0; + + return 1; +} + +// Proxy Connection => at Proxy, Ready to send out Start and get back ACKs!! +int bdConnection::upgradeProxyConnectionToFinish(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int status) +{ + mState = BITDHT_CONNECTION_WAITING_ACK; + mLastEvent = time(NULL); + + //mSrcId,mDestId should be okay. (ID/IP okay) + //mProxyId, not set, doesn't matter. (IP Unknown) + + // mPoint, mMode should be okay. + + // mSrcConnAddr should be okay. (ID/IP known) + // Install the correct destConnAddr. (just received) + mDestConnAddr = *destConnAddr; + + /* clear IP Addresses to enforce this */ + bdsockaddr_clear(&(mProxyId.addr)); + + checkForDefaultConnectAddress(); + + // Initialise the START/ACK Parameters. + mRetryCount = 0; + mLastStart = 0; + mSrcAck = false; + mDestAck = false; + mCompletedTS = 0; + + return 1; +} + + +// Final Sorting out of Addresses. +int bdConnection::CompleteConnection(bdId *id, bdId *srcConnAddr, bdId *destConnAddr) +{ + /* Store Final Addresses */ + time_t now = time(NULL); + + mState = BITDHT_CONNECTION_COMPLETED; + mCompletedTS = now; + mLastEvent = now; + + // Received Definitive Final Addresses from Proxy. + // These have to be done by proxy, as its the only one who know both our addresses. + + mSrcConnAddr = *srcConnAddr; + mDestConnAddr = *destConnAddr; + + checkForDefaultConnectAddress(); + + return 1; +} + + + +int bdConnection::checkForDefaultConnectAddress() +{ + // We can check if the DestConnAddr / SrcConnAddr are real. + // If there is nothing there, we assume that that want to connect on the + // same IP:Port as the DHT Node. + + if (mSrcConnAddr.addr.sin_addr.s_addr == 0) + { + std::cerr << "bdConnectManager::checkForDefaultConnectAddress() SrcConnAddr.addr is BLANK, installing Dht Node Address"; + std::cerr << std::endl; + + mSrcConnAddr.addr = mSrcId.addr; + } + + if (mDestConnAddr.addr.sin_addr.s_addr == 0) + { + std::cerr << "bdConnectManager::checkForDefaultConnectAddress() DestConnAddr.addr is BLANK, installing Dht Node Address"; + std::cerr << std::endl; + + mDestConnAddr.addr = mDestId.addr; + } + + return 1; + +} + + +int bdConnectionRequest::setupDirectConnection(struct sockaddr_in *laddr, bdNodeId *target) +{ + mState = BITDHT_CONNREQUEST_READY; + mStateTS = time(NULL); + mPauseTS = 0; + mTarget = *target; + mLocalAddr = *laddr; + mMode = BITDHT_CONNECT_MODE_DIRECT; + mRecycled = 0; + mErrCode = 0; + + return 1; +} + +int bdConnectionRequest::setupProxyConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode) +{ + mState = BITDHT_CONNREQUEST_READY; + mStateTS = time(NULL); + mPauseTS = 0; + mTarget = *target; + mLocalAddr = *laddr; + mMode = mode; + mRecycled = 0; + mErrCode = 0; + + return 1; +} + +/* this is a good proxy peer (with flags already checked). + * if it is in the potential proxy list, then we can add it into the good proxy list. + */ + +int bdConnectionRequest::checkGoodProxyPeer(const bdId *id) +{ + std::cerr << "bdConnectionRequest::checkProxyPeer() "; + bdStdPrintId(std::cerr, id); + std::cerr << std::endl; + + std::list::iterator it = std::find(mPotentialProxies.begin(), mPotentialProxies.end(), *id); + if (it != mPotentialProxies.end()) + { + std::cerr << "bdConnectionRequest::checkProxyPeer() Found in PotentialProxies List, adding in"; + std::cerr << std::endl; + + it = mPotentialProxies.erase(it); + + /* now add it in */ + addGoodProxy(id); + } + return 1; +} + + +int bdConnectionRequest::addGoodProxy(const bdId *srcId) +{ + std::cerr << "bdConnectionRequest::addGoodProxy() "; + bdStdPrintId(std::cerr, srcId); + std::cerr << std::endl; + + if (*srcId == mCurrentAttempt) + { + std::cerr << "bdConnectionRequest::addGoodProxy() Duplicate with CurrentAttempt"; + std::cerr << std::endl; + return 0; + } + + std::list::iterator it = std::find(mPeersTried.begin(), mPeersTried.end(), *srcId); + if (it == mPeersTried.end()) + { + it = std::find(mGoodProxies.begin(), mGoodProxies.end(), *srcId); + if (it == mGoodProxies.end()) + { + std::cerr << "bdConnectionRequest::addGoodProxy() CRINITSTATE Found New Proxy: "; + bdStdPrintId(std::cerr, srcId); + std::cerr << std::endl; + + mGoodProxies.push_back(*srcId); + + /* if it is potentialProxies then remove */ + it = std::find(mPotentialProxies.begin(), mPotentialProxies.end(), *srcId); + if (it != mPotentialProxies.end()) + { + std::cerr << "bdConnectionRequest::addGoodProxy() Removing from PotentialProxy List"; + std::cerr << std::endl; + + it = mPotentialProxies.erase(it); + } + return 1; + } + else + { + std::cerr << "bdConnectionRequest::addGoodProxy() Duplicate in mPotentialProxies List"; + std::cerr << std::endl; + } + } + else + { + std::cerr << "bdConnectionRequest::addGoodProxy() Already tried this peer"; + std::cerr << std::endl; + } + return 0; +} + + +std::ostream &operator<<(std::ostream &out, const bdConnectionRequest &req) +{ + time_t now = time(NULL); + out << "bdConnectionRequest: "; + out << "State: " << req.mState; + out << " StateTS: " << now - req.mStateTS; + out << " Recycled: " << req.mRecycled; + out << std::endl; + out << "\tTargetId: "; + bdStdPrintNodeId(out, &(req.mTarget)); + out << std::endl; + out << "\tMode: " << req.mMode; + out << std::endl; + + out << "CurrentAttempt:"; + bdStdPrintId(out, &(req.mCurrentAttempt)); + out << std::endl; + + out << "GoodProxies:"; + out << std::endl; + + std::list::const_iterator it; + for(it = req.mGoodProxies.begin(); it != req.mGoodProxies.end(); it++) + { + out << "\t"; + bdStdPrintId(out, &(*it)); + out << std::endl; + } + + out << "PotentialProxies:"; + out << std::endl; + + for(it = req.mPotentialProxies.begin(); it != req.mPotentialProxies.end(); it++) + { + out << "\t"; + bdStdPrintId(out, &(*it)); + out << std::endl; + } + + out << "PeersTried:"; + out << std::endl; + + for(it = req.mPeersTried.begin(); it != req.mPeersTried.end(); it++) + { + out << "\t"; + bdStdPrintId(out, &(*it)); + out << std::endl; + } + return out; +} + +std::ostream &operator<<(std::ostream &out, const bdConnection &conn) +{ + time_t now = time(NULL); + out << "bdConnection: "; + out << "State: " << conn.mState; + out << " LastEvent: " << now - conn.mLastEvent; + out << " Point: " << conn.mPoint; + out << " Mode: " << conn.mMode; + out << std::endl; + + out << "\tsrcId: "; + bdStdPrintId(out, &(conn.mSrcId)); + out << std::endl; + out << "\tproxyId: "; + bdStdPrintId(out, &(conn.mProxyId)); + out << std::endl; + out << "\tdestId: "; + bdStdPrintId(out, &(conn.mDestId)); + out << std::endl; + + out << "\tsrcConnAddr: "; + bdStdPrintId(out, &(conn.mSrcConnAddr)); + out << std::endl; + + out << "\tdestConnAddr: "; + bdStdPrintId(out, &(conn.mDestConnAddr)); + out << std::endl; + + out << "\tretryCount: " << conn.mRetryCount; + out << " retryCount: " << conn.mLastStart; + out << " srcAck: " << conn.mSrcAck; + out << " destAck: " << conn.mDestAck; + out << " completedTS: " << now - conn.mCompletedTS; + out << std::endl; + + return out; + +} + + +uint32_t createConnectionErrorCode(uint32_t userProvided, uint32_t fallback, uint32_t point) +{ + int status = userProvided & BITDHT_CONNECT_ERROR_MASK_TYPE; + if (status == BITDHT_CONNECT_ERROR_NONE) + { + status = fallback; + } + /* backup, backup. */ + if (status == BITDHT_CONNECT_ERROR_NONE) + { + status = BITDHT_CONNECT_ERROR_GENERIC; /* FALLBACK ERROR CODE */ + } + + switch(point) + { + case BD_PROXY_CONNECTION_START_POINT: + status |= BITDHT_CONNECT_ERROR_SOURCE_START; + break; + case BD_PROXY_CONNECTION_MID_POINT: + status |= BITDHT_CONNECT_ERROR_SOURCE_MID; + break; + case BD_PROXY_CONNECTION_END_POINT: + status |= BITDHT_CONNECT_ERROR_SOURCE_END; + break; + } + + return status; +} + + + +std::string decodeConnectionErrorType(uint32_t errcode) +{ + uint32_t errtype = errcode & BITDHT_CONNECT_ERROR_MASK_TYPE; + std::string namedtype = "UNKNOWN"; + switch(errtype) + { + default: + break; + case BITDHT_CONNECT_ERROR_GENERIC: + namedtype = "GENERIC"; + break; + case BITDHT_CONNECT_ERROR_PROTOCOL: + namedtype = "PROTOCOL"; + break; + case BITDHT_CONNECT_ERROR_TIMEOUT: + namedtype = "TIMEOUT"; + break; + case BITDHT_CONNECT_ERROR_TEMPUNAVAIL: + namedtype = "TEMPUNAVAIL"; + break; + case BITDHT_CONNECT_ERROR_NOADDRESS: + namedtype = "NOADDRESS"; + break; + case BITDHT_CONNECT_ERROR_UNREACHABLE: + namedtype = "UNREACHABLE"; + break; + case BITDHT_CONNECT_ERROR_UNSUPPORTED: + namedtype = "UNSUPPORTED"; + break; + case BITDHT_CONNECT_ERROR_OVERLOADED: + namedtype = "OVERLOADED"; + break; + case BITDHT_CONNECT_ERROR_AUTH_DENIED: + namedtype = "AUTH_DENIED"; + break; + case BITDHT_CONNECT_ERROR_DUPLICATE: + namedtype = "DUPLICATE"; + break; + case BITDHT_CONNECT_ERROR_TOOMANYRETRY: + namedtype = "TOOMANYRETRY"; + break; + case BITDHT_CONNECT_ERROR_OUTOFPROXY: + namedtype = "OUTOFPROXY"; + break; + case BITDHT_CONNECT_ERROR_USER: + namedtype = "USER DEFINED"; + break; + } + return namedtype; +} + + +std::string decodeConnectionErrorSource(uint32_t errcode) +{ + uint32_t errsrc = errcode & BITDHT_CONNECT_ERROR_MASK_SOURCE; + std::string namedtype = "UNKNOWN"; + switch(errsrc) + { + default: + break; + case BITDHT_CONNECT_ERROR_SOURCE_START: + namedtype = "START"; + break; + case BITDHT_CONNECT_ERROR_SOURCE_MID: + namedtype = "MID"; + break; + case BITDHT_CONNECT_ERROR_SOURCE_END: + namedtype = "END"; + break; + case BITDHT_CONNECT_ERROR_SOURCE_OTHER: + namedtype = "OTHER"; + break; + } + return namedtype; +} + + +#if 0 +std::string decodeConnectionErrorCRMove(uint32_t errcode) +{ + uint32_t errcr = errcode & BITDHT_CONNECT_ERROR_MASK_CRMOVE; + std::string namedtype = "UNKNOWN"; + switch(errcr) + { + default: + break; + case 0: + namedtype = "REMOTE"; + break; + case BITDHT_CONNECT_ERROR_CRMOVE_FATAL: + namedtype = "FATAL"; + break; + case BITDHT_CONNECT_ERROR_SOURCE_NOMOREIDS: + namedtype = "NOMOREIDS"; + break; + case BITDHT_CONNECT_ERROR_SOURCE_NEXTID: + namedtype = "NEXTID"; + break; + case BITDHT_CONNECT_ERROR_CRMOVE_PAUSED: + namedtype = "PAUSED"; + break; + } + return namedtype; +} +#endif + + + +std::string decodeConnectionError(uint32_t errcode) +{ + std::string totalerror; + if (!errcode) + { + totalerror = "NoError"; + } + else + { + //totalerror = decodeConnectionErrorCRMove(errcode); + //totalerror += ":"; + totalerror = decodeConnectionErrorSource(errcode); + totalerror += ":"; + totalerror += decodeConnectionErrorType(errcode); + } + + return totalerror; +} + diff --git a/libbitdht/src/bitdht/bdconnection.h b/libbitdht/src/bitdht/bdconnection.h new file mode 100644 index 000000000..3e3f1cbc3 --- /dev/null +++ b/libbitdht/src/bitdht/bdconnection.h @@ -0,0 +1,274 @@ +#ifndef BITDHT_CONNECTION_H +#define BITDHT_CONNECTION_H + +/* + * bitdht/bdconnection.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2011 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdiface.h" + +class bdQueryManager; +class bdNodePublisher; + +/************************************************************************************************************ +************************************** ProxyTuple + Connection State **************************************** +************************************************************************************************************/ + +#define BITDHT_CONNREQUEST_READY 1 +#define BITDHT_CONNREQUEST_PAUSED 2 +#define BITDHT_CONNREQUEST_INPROGRESS 3 +#define BITDHT_CONNREQUEST_EXTCONNECT 4 +#define BITDHT_CONNREQUEST_DONE 5 + +#define BITDHT_CONNREQUEST_TIMEOUT_CONNECT 30 +#define BITDHT_CONNREQUEST_TIMEOUT_INPROGRESS 30 +#define BITDHT_CONNREQUEST_MAX_AGE 60 + + +#define BITDHT_CONNECTION_WAITING_AUTH 1 +#define BITDHT_CONNECTION_WAITING_REPLY 2 +#define BITDHT_CONNECTION_WAITING_START 3 +#define BITDHT_CONNECTION_WAITING_ACK 4 +#define BITDHT_CONNECTION_COMPLETED 5 + + +#define BD_CONNECTION_START_RETRY_PERIOD 5 // Should only take a couple of seconds to get reply. +#define BD_CONNECTION_START_MAX_RETRY 3 +#define BD_CONNECTION_MAX_TIMEOUT 30 + + + +class bdProxyTuple +{ + public: + bdProxyTuple() { return; } + bdProxyTuple(bdNodeId *s, bdNodeId *p, bdNodeId *d) + :srcId(*s), proxyId(*p), destId(*d) { return; } + + bdNodeId srcId; + bdNodeId proxyId; + bdNodeId destId; +}; + +std::ostream &operator<<(std::ostream &out, const bdProxyTuple &t); +int operator<(const bdProxyTuple &a, const bdProxyTuple &b); +int operator==(const bdProxyTuple &a, const bdProxyTuple &b); + + +class bdConnection +{ + public: + bdConnection(); + + /** Functions to tweak the connection status */ + + // User initialised Connection. + int ConnectionSetup(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode); + int ConnectionSetupDirect(bdId *destId, bdId *srcConnAddr); + + // Initialise a new Connection. (receiving a Connection Request) + int ConnectionRequestDirect(bdId *id, bdId *srcConnAddr, bdId *destConnAddr); + int ConnectionRequestProxy(bdId *id, bdId *srcConnAddr, bdNodeId *ownId, bdId *destConnAddr, int mode); + int ConnectionRequestEnd(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); + + // Setup Finishing Stage, (receiving a Connection Reply). + int upgradeProxyConnectionToFinish(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int status); + + int AuthoriseDirectConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); + int AuthoriseProxyConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); + int AuthoriseEndConnection(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); + + int CompleteConnection(bdId *id, bdId *srcConnAddr, bdId *destConnAddr); + + int checkForDefaultConnectAddress(); + + /* Connection State, and TimeStamp of Update */ + int mState; + time_t mLastEvent; + + /* Addresses of Start/Proxy/End Nodes */ + bdId mSrcId; + bdId mDestId; + bdId mProxyId; + + /* Where we are in the connection, + * and what connection mode. + */ + int mPoint; + int mMode; + + /* must have ip:ports of connection ends (if proxied) */ + bdId mSrcConnAddr; + bdId mDestConnAddr; + + int mBandwidth; + + /* START/ACK Finishing ****/ + time_t mLastStart; /* timer for retries */ + int mRetryCount; /* retry counter */ + + bool mSrcAck; + bool mDestAck; + + // Completion TS. + time_t mCompletedTS; + + +}; + +class bdConnectionRequest +{ + public: + int setupDirectConnection(struct sockaddr_in *laddr, bdNodeId *target); + int setupProxyConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); + + int addGoodProxy(const bdId *srcId); + int checkGoodProxyPeer(const bdId *Id); + + bdNodeId mTarget; + struct sockaddr_in mLocalAddr; + int mMode; + + int mState; + time_t mStateTS; + + time_t mPauseTS; + uint32_t mErrCode; + + + std::list mGoodProxies; + std::list mPotentialProxies; + int mRecycled; + + bdId mCurrentAttempt; + std::list mPeersTried; +}; + +std::ostream &operator<<(std::ostream &out, const bdConnectionRequest &req); +std::ostream &operator<<(std::ostream &out, const bdConnection &conn); + + +/********* + * The Connection Management Class. + * this encapsulates all of the functionality.. + * except for a couple of message in/outs + callback. + */ + +class bdConnectManager +{ + public: + + bdConnectManager(bdNodeId *ownid, bdSpace *space, bdQueryManager *qmgr, bdDhtFunctions *fns, bdNodePublisher *pub); + + + /* connection functions */ + void requestConnection(bdNodeId *id, uint32_t modes); + void allowConnection(bdNodeId *id, uint32_t modes); + + + /* high level */ + + void shutdownConnections(); + void printConnections(); + + /* Connections: Configuration */ + void defaultConnectionOptions(); + virtual void setConnectionOptions(uint32_t allowedModes, uint32_t flags); + + /* Connections: Initiation */ + + int requestConnection(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t start); + int requestConnection_direct(struct sockaddr_in *laddr, bdNodeId *target); + int requestConnection_proxy(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); + + int killConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode); + + int checkExistingConnectionAttempt(bdNodeId *target); + void addPotentialConnectionProxy(const bdId *srcId, const bdId *target); + void updatePotentialConnectionProxy(const bdId *id, uint32_t mode); + + int checkPeerForFlag(const bdId *id, uint32_t with_flag); + + int tickConnections(); + void iterateConnectionRequests(); + int startConnectionAttempt(bdConnectionRequest *req); + + // internal Callback -> normally continues to callbackConnect(). + void callbackConnectRequest(bdId *srcId, bdId *proxyId, bdId *destId, + int mode, int point, int cbtype, int errcode); + + /* Connections: Outgoing */ + + int startConnectionAttempt(bdId *proxyId, bdId *srcConnAddr, bdId *destConnAddr, int mode); + void AuthConnectionOk(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc); + void AuthConnectionNo(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int loc, int errcode); + void iterateConnections(); + + + /* Connections: Utility State */ + + bdConnection *findExistingConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); + bdConnection *newConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); + int cleanConnection(bdNodeId *srcId, bdNodeId *proxyId, bdNodeId *destId); + + int determinePosition(bdNodeId *sender, bdNodeId *src, bdNodeId *dest); + int determineProxyId(bdNodeId *sender, bdNodeId *src, bdNodeId *dest, bdNodeId *proxyId); + + bdConnection *findSimilarConnection(bdNodeId *srcId, bdNodeId *destId); + bdConnection *findExistingConnectionBySender(bdId *sender, bdId *src, bdId *dest); + bdConnection *newConnectionBySender(bdId *sender, bdId *src, bdId *dest); + int cleanConnectionBySender(bdId *sender, bdId *src, bdId *dest); + + // Overloaded Generalised Connection Callback. + virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, + int mode, int point, int cbtype, int errcode); + + /* Connections: */ + int recvedConnectionRequest(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); + int recvedConnectionReply(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int status); + int recvedConnectionStart(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode, int bandwidth); + int recvedConnectionAck(bdId *id, bdId *srcConnAddr, bdId *destConnAddr, int mode); + + private: + + std::map mConnections; + std::map mConnectionRequests; + + uint32_t mConfigAllowedModes; + bool mConfigAutoProxy; + + /****************************** Connection Code (in bdconnection.cc) ****************************/ + + private: + + bdNodeId mOwnId; + bdSpace *mNodeSpace; + bdQueryManager *mQueryMgr; + bdDhtFunctions *mFns; + bdNodePublisher *mPub; +}; + + +#endif // BITDHT_CONNECTION_H diff --git a/libbitdht/src/bitdht/bdfilter.cc b/libbitdht/src/bitdht/bdfilter.cc new file mode 100644 index 000000000..597d3a6b5 --- /dev/null +++ b/libbitdht/src/bitdht/bdfilter.cc @@ -0,0 +1,175 @@ + +/* + * bitdht/bdfilter.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdfilter.h" + +#include +#include +#include +#include + +/** + * #define DEBUG_FILTER 1 +**/ + + +bdFilter::bdFilter(const bdNodeId *ownId, std::list &startList, + uint32_t filterFlags, bdDhtFunctions *fns) +{ + /* */ + mOwnId = *ownId; + mFns = fns; + + time_t now = time(NULL); + std::list::iterator it; + + for(it = startList.begin(); it != startList.end(); it++) + { + mFiltered.push_back(*it); + } + + mFilterFlags = filterFlags; +} + +bool bdFilter::filtered(std::list &answer) +{ + answer = mFiltered; + return (answer.size() > 0); +} + +bool bdFilter::filteredIPs(std::list &answer) +{ + std::list::iterator it; + for(it = mFiltered.begin(); it != mFiltered.end(); it++) + { + answer.push_back(it->mAddr); + } + return (answer.size() > 0); +} + +int bdFilter::checkPeer(const bdId *id, uint32_t mode) +{ + bool add = false; + uint32_t flags = 0; + if ((mFilterFlags & BITDHT_FILTER_REASON_OWNID) && + isOwnIdWithoutBitDhtFlags(id, mode)) + { + add = true; + flags |= BITDHT_FILTER_REASON_OWNID; + } + + if (add) + { + bool isNew = addPeerToFilter(id, flags); + if (isNew) + { + return 1; + } + } + + return 0; +} + +int bdFilter::addPeerToFilter(const bdId *id, uint32_t flags) +{ + std::list::iterator it; + bool found = false; + for(it = mFiltered.begin(); it != mFiltered.end(); it++) + { + if (id->addr.sin_addr.s_addr == it->mAddr.sin_addr.s_addr) + { + found = true; + it->mLastSeen = time(NULL); + it->mFilterFlags |= flags; + break; + } + } + + if (!found) + { + time_t now = time(NULL); + bdFilteredPeer fp; + + fp.mAddr = id->addr; + fp.mAddr.sin_port = 0; + fp.mFilterFlags = flags; + fp.mFilterTS = now; + fp.mLastSeen = now; + + mFiltered.push_back(fp); + + uint32_t saddr = id->addr.sin_addr.s_addr; + mIpsBanned.insert(saddr); + + std::cerr << "Adding New Banned Ip Address: " << inet_ntoa(id->addr.sin_addr); + std::cerr << std::endl; + + return true; + } + return false; +} + +/* fast check if the addr is in the structure */ +int bdFilter::addrOkay(struct sockaddr_in *addr) +{ + std::set::const_iterator it = mIpsBanned.find(addr->sin_addr.s_addr); + if (it == mIpsBanned.end()) + { + return 1; // Address is Okay! + } + std::cerr << "Detected Packet From Banned Ip Address: " << inet_ntoa(addr->sin_addr); + std::cerr << std::endl; + return 0; +} + + +bool bdFilter::isOwnIdWithoutBitDhtFlags(const bdId *id, uint32_t peerFlags) +{ + if (peerFlags & BITDHT_PEER_STATUS_RECV_PONG) + { + if (peerFlags & BITDHT_PEER_STATUS_DHT_ENGINE) + { + /* okay! */ + return false; + } + + /* now check distance */ + bdMetric dist; + mFns->bdDistance(&mOwnId, &(id->id), &dist); + int bucket = mFns->bdBucketDistance(&dist); + + /* if they match us... kill it */ + if (bucket == 0) + { + return true; + } + } + return false; +} + + + diff --git a/libbitdht/src/bitdht/bdfilter.h b/libbitdht/src/bitdht/bdfilter.h new file mode 100644 index 000000000..b18f64ad7 --- /dev/null +++ b/libbitdht/src/bitdht/bdfilter.h @@ -0,0 +1,82 @@ +#ifndef BITDHT_FILTER_H +#define BITDHT_FILTER_H + +/* + * bitdht/bdfilter.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +/* This class is used to detect bad and filter them peers + * + */ + + +#include "bitdht/bdiface.h" +#include + +/* Query result flags are in bdiface.h */ + +#define BITDHT_FILTER_REASON_OWNID 0x0001 + +class bdFilteredPeer +{ + public: + struct sockaddr_in mAddr; + uint32_t mFilterFlags; /* reasons why we are filtering */ + time_t mFilterTS; + time_t mLastSeen; +}; + +class bdFilter +{ + public: + bdFilter(const bdNodeId *ownid, std::list &initialFilters, + uint32_t filterFlags, bdDhtFunctions *fns); + + // get the answer. +bool filtered(std::list &answer); +bool filteredIPs(std::list &answer); + +int checkPeer(const bdId *id, uint32_t peerFlags); + +int addrOkay(struct sockaddr_in *addr); + + private: + +int addPeerToFilter(const bdId *id, uint32_t flags); +bool isOwnIdWithoutBitDhtFlags(const bdId *id, uint32_t peerFlags); + + // searching for + bdNodeId mOwnId; + uint32_t mFilterFlags; + + std::list mFiltered; + bdDhtFunctions *mFns; + + // = addr.sin_addr.s_addr (uint32_t) stored in network order. + std::set mIpsBanned; +}; + + +#endif + diff --git a/libbitdht/src/bitdht/bdhash.cc b/libbitdht/src/bitdht/bdhash.cc new file mode 100644 index 000000000..762ca5e1b --- /dev/null +++ b/libbitdht/src/bitdht/bdhash.cc @@ -0,0 +1,287 @@ +/* + * bitdht/bdhash.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdhash.h" +#include "bitdht/bdstddht.h" +#include + +bdHashEntry::bdHashEntry(std::string value, std::string secret, time_t lifetime, time_t store) + :mValue(value), mStoreTS(store), mSecret(secret), mLifetime(lifetime) +{ + return; +} + + +/**************************** class bdHashSet ********************************/ + +bdHashSet::bdHashSet(bdNodeId *id) + :mId(*id) +{ + return; +} + +int bdHashSet::search(std::string key, uint32_t maxAge, std::list &entries) +{ + std::multimap::iterator sit, eit, it; + sit = mEntries.lower_bound(key); + eit = mEntries.upper_bound(key); + + time_t now = time(NULL); + + for(it = sit; it != eit; it++) + { + time_t age = now - it->second.mStoreTS; + if (age < (int32_t) maxAge) + { + entries.push_back(it->second); + } + } + return (0 < entries.size()); +} + +/*** + * With modification. + * If there is no secret -> it cannot be deleted (must timeout), but can be extended. + * If there is a secret -> must include it to modify. + * + * Therefore if identical entry without secret comes along - what do I do? + * -> create duplicate? + */ + +int bdHashSet::modify(std::string key, bdHashEntry *entry, uint32_t modFlags) +{ + std::multimap::iterator sit, eit, it; + sit = mEntries.lower_bound(key); + eit = mEntries.upper_bound(key); + + time_t now = time(NULL); + + bool updated = false; + for(it = sit; it != eit; it++) + { + /* check it all */ + if (it->second.mValue == entry->mValue) + { + bool noSecret = (it->second.mSecret == ""); + bool sameSecret = (it->second.mSecret == entry->mSecret); + bool update = false; + + if (noSecret && sameSecret) + { + /* only allowed to increase lifetime */ + if (modFlags == BITDHT_HASH_ENTRY_ADD) + { + time_t existKillTime = it->second.mLifetime + it->second.mStoreTS; + time_t newKillTime = entry->mLifetime + now; + if (newKillTime > existKillTime) + { + update = true; + } + } + } + else if (sameSecret) + { + if (modFlags == BITDHT_HASH_ENTRY_ADD) + { + update = true; + } + else if (modFlags == BITDHT_HASH_ENTRY_DELETE) + { + /* do it here */ + mEntries.erase(it); + return 1; + } + } + + if (update) + { + it->second.mStoreTS = now; + it->second.mLifetime = entry->mLifetime; + updated = true; + } + } + } + + if ((!updated) && (modFlags == BITDHT_HASH_ENTRY_ADD)) + { + /* create a new entry */ + bdHashEntry newEntry(entry->mValue, entry->mSecret, entry->mLifetime, now); + mEntries.insert(std::pair(key, newEntry)); + updated = true; + } + return updated; +} + +int bdHashSet::printHashSet(std::ostream &out) +{ + time_t now = time(NULL); + std::multimap::iterator it; + out << "Hash: "; + bdStdPrintNodeId(out, &mId); // Allowing "Std" as we dont need dht functions everywhere. + out << std::endl; + + for(it = mEntries.begin(); it != mEntries.end();it++) + { + time_t age = now - it->second.mStoreTS; + out << "\tK:" << bdStdConvertToPrintable(it->first); + out << " V:" << bdStdConvertToPrintable(it->second.mValue); + out << " A:" << age << " L:" << it->second.mLifetime; + out << " S:" << bdStdConvertToPrintable(it->second.mSecret); + out << std::endl; + } + return 1; +} + + + + +int bdHashSet::cleanupHashSet(uint32_t maxAge) +{ + time_t now = time(NULL); + + /* this is nasty... but don't know how to effectively remove from multimaps + * * Must do full repeat for each removal. + */ + + std::multimap::iterator it; + for(it = mEntries.begin(); it != mEntries.end();) + { + time_t age = now - it->second.mStoreTS; + if ((age > (int32_t) maxAge) || (age > it->second.mLifetime)) + { + mEntries.erase(it); + it = mEntries.begin(); + } + else + { + it++; + } + } + return 1; +} + + + + + + +/******************************* class bdHashSpace ***************************/ + +bdHashSpace::bdHashSpace() +{ + return; +} + + /* accessors */ +int bdHashSpace::search(bdNodeId *id, std::string key, uint32_t maxAge, std::list &entries) +{ + std::map::iterator it; + it = mHashTable.find(*id); + if (it == mHashTable.end()) + { + /* no entry */ + return 1; + } + + return it->second.search(key, maxAge, entries); +} + +int bdHashSpace::modify(bdNodeId *id, std::string key, bdHashEntry *entry, uint32_t modFlags) +{ + std::map::iterator it; + it = mHashTable.find(*id); + if (it == mHashTable.end()) + { + if (modFlags == BITDHT_HASH_ENTRY_DELETE) + { + /* done already */ + return 1; + } + + //mHashTable[*id] = bdHashSet(id); + mHashTable.insert(std::pair(*id, bdHashSet(id))); + it = mHashTable.find(*id); + } + + return it->second.modify(key, entry, modFlags); +} + +int bdHashSpace::printHashSpace(std::ostream &out) +{ + std::map::iterator it; + out << "bdHashSpace::printHashSpace()" << std::endl; + out << "--------------------------------------------" << std::endl; + + for(it = mHashTable.begin(); it != mHashTable.end(); it++) + { + it->second.printHashSet(out); + } + out << "--------------------------------------------" << std::endl; + return 1; +} + +int bdHashSpace::cleanHashSpace(bdNodeId *min, bdNodeId *max, time_t maxAge) +{ + std::map::iterator it; + std::list eraseList; + std::list::iterator eit; + + for(it = mHashTable.begin(); it != mHashTable.end(); it++) + { + if ((it->first < *min) || + (*max < it->first)) + { + /* schedule for erasure */ + eraseList.push_back(it->first); + } + else + { + /* clean up Hash Set */ + it->second.cleanupHashSet(maxAge); + } + } + + /* cleanup */ + while(eraseList.size() > 0) + { + bdNodeId &eId = eraseList.front(); + it = mHashTable.find(eId); + if (it != mHashTable.end()) + { + mHashTable.erase(it); + } + } + return 1; +} + + +int bdHashSpace::clear() +{ + mHashTable.clear(); + return 1; +} + + diff --git a/libbitdht/src/bitdht/bdhash.h b/libbitdht/src/bitdht/bdhash.h new file mode 100644 index 000000000..10c8fd6e2 --- /dev/null +++ b/libbitdht/src/bitdht/bdhash.h @@ -0,0 +1,88 @@ +#ifndef BITDHT_HASH_SPACE_H +#define BITDHT_HASH_SPACE_H + +/* + * bitdht/bdhash.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bitdht/bdpeer.h" + +#include +#include +#include + +#define BITDHT_HASH_ENTRY_ADD 1 +#define BITDHT_HASH_ENTRY_DELETE 2 + +class bdHashEntry +{ + public: + + bdHashEntry(std::string value, std::string secret, time_t lifetime, time_t store); + std::string mValue; + time_t mStoreTS; + + /* These are nice features that OpenDHT had */ + std::string mSecret; + time_t mLifetime; +}; + + +class bdHashSet +{ + public: + + bdHashSet(bdNodeId *id); + +int search(std::string key, uint32_t maxAge, std::list &entries); +int modify(std::string key, bdHashEntry *entry, uint32_t modFlags); +int printHashSet(std::ostream &out); +int cleanupHashSet(uint32_t maxAge); + + bdNodeId mId; + std::multimap mEntries; +}; + +class bdHashSpace +{ + public: + + bdHashSpace(); + + /* accessors */ +int search(bdNodeId *id, std::string key, uint32_t maxAge, std::list &entries); +int modify(bdNodeId *id, std::string key, bdHashEntry *entry, uint32_t modFlags); + +int printHashSpace(std::ostream&); +int cleanHashSpace(bdNodeId *min, bdNodeId *max, time_t maxAge); +int clear(); + + private: + + std::map mHashTable; +}; + + +#endif + diff --git a/libbitdht/src/bitdht/bdhistory.cc b/libbitdht/src/bitdht/bdhistory.cc new file mode 100644 index 000000000..49a664e1c --- /dev/null +++ b/libbitdht/src/bitdht/bdhistory.cc @@ -0,0 +1,211 @@ + + +#include "bitdht/bdhistory.h" +#include "bitdht/bdstddht.h" + +#define MIN_RESEND_PERIOD 60 + +void bdMsgHistoryList::addMsg(time_t ts, uint32_t msgType, bool incoming) + +{ + uint32_t msg = msgType | (incoming ? MSG_DIRECTION_INCOMING : MSG_DIRECTION_OUTGOING); + msgHistory.insert(std::make_pair(ts, msg)); +} + +int bdMsgHistoryList::msgCount(time_t start_ts, time_t end_ts) +{ + std::multimap::iterator sit, eit, it; + sit = msgHistory.lower_bound(start_ts); + eit = msgHistory.upper_bound(end_ts); + int count = 0; + for (it = sit; it != eit; it++, count++) ; // empty loop. + + return count; +} + +void bdMsgHistoryList::msgClear() +{ + msgHistory.clear(); +} + + +void bdMsgHistoryList::printHistory(std::ostream &out, int mode, time_t start_ts, time_t end_ts) +{ + //out << "AGE: MSGS => incoming, <= outgoing" << std::endl; + std::multimap::iterator sit, eit, it; + sit = msgHistory.lower_bound(start_ts); + eit = msgHistory.upper_bound(end_ts); + time_t curr_ts = 0; + time_t old_ts = 0; + bool time_changed = false; + bool first_line = true; + + for(it = sit; it != eit; it++) + { + time_changed = false; + if (curr_ts != it->first) + { + old_ts = curr_ts; + curr_ts = it->first; + time_changed = true; + } + switch(mode) + { + default: + { + /* print one line per ts */ + if (time_changed) + { + if (!first_line) + { + /* finish existing line */ + out << " " << std::endl; + } + else + { + first_line = false; + } + out << "\tTS: " << time(NULL) - curr_ts << " "; + } + + if (MSG_DIRECTION_INCOMING & it->second) + { + out << " =>" << it->second - MSG_DIRECTION_INCOMING; + out << " "; + } + else + { + out << " "; + out << it->second - MSG_DIRECTION_OUTGOING << "=> "; + } + + } + break; + } // end of switch. + } + + /* finish up last line */ + if (!first_line) + { + out << " " << std::endl; + } +} + + +bool bdMsgHistoryList::canSend() +{ + std::cerr << "bdMsgHistoryList::canSend()"; + + std::multimap::reverse_iterator rit; + + rit = msgHistory.rbegin(); + if (rit != msgHistory.rend()) + { + time_t now = time(NULL); + if (now - rit->first > MIN_RESEND_PERIOD) + { + std::cerr << " OVER RESEND_PERIOD... true"; + std::cerr << std::endl; + + return true; + } + } + + if (msgHistory.size() % 2 == 0) + { + std::cerr << " SIZE: " << msgHistory.size() << " % 2 = 0 ... true"; + std::cerr << std::endl; + + return true; + } + + std::cerr << " false"; + std::cerr << std::endl; + + return false; +} + +bool bdMsgHistoryList::validPeer() +{ + std::cerr << "bdMsgHistoryList::validPeer()"; + + std::multimap::iterator it; + + for(it = msgHistory.begin(); it != msgHistory.end(); it++) + { + if (MSG_DIRECTION_INCOMING & it->second) + { + std::cerr << " Incoming Msg... so validPeer"; + std::cerr << std::endl; + + return true; + } + } + + std::cerr << " false"; + std::cerr << std::endl; + + return false; +} + +void bdHistory::addMsg(const bdId *id, bdToken * /*transId*/, uint32_t msgType, bool incoming) +{ + std::map::iterator it; + bdMsgHistoryList &histRef = mHistory[*id]; /* will instaniate empty */ + histRef.addMsg(time(NULL), msgType, incoming); +} + +void bdHistory::printMsgs() +{ + /* print and clear msgs */ + std::ostream &out = std::cerr; + + std::map ::iterator it; + for(it = mHistory.begin(); it != mHistory.end(); it++) + { + if (it->second.msgCount(0, time(NULL))) // all msg count. + { + /* print header */ + out << "Msgs for "; + bdStdPrintId(out, &(it->first)); + out << std::endl; + + it->second.printHistory(out, 0, 0, time(NULL)); + } + } +} + +void bdHistory::clearHistory() +{ + mHistory.clear(); +} + +bool bdHistory::canSend(const bdId *id) +{ + + std::map ::iterator it; + it = mHistory.find(*id); + if (it != mHistory.end()) + { + return (it->second.canSend()); + } + + /* if not found - then can send */ + return true; +} + + +bool bdHistory::validPeer(const bdId *id) +{ + std::map ::iterator it; + it = mHistory.find(*id); + if (it != mHistory.end()) + { + return (it->second.validPeer()); + } + + /* if not found - then can send */ + return false; +} + + diff --git a/libbitdht/src/bitdht/bdhistory.h b/libbitdht/src/bitdht/bdhistory.h new file mode 100644 index 000000000..cccbe2062 --- /dev/null +++ b/libbitdht/src/bitdht/bdhistory.h @@ -0,0 +1,50 @@ +#ifndef BITDHT_HISTORY_H +#define BITDHT_HISTORY_H + +#include "bitdht/bdpeer.h" +#include "bitdht/bdobj.h" +#include + +#define MSG_TYPE_DIRECTION_MASK 0x000f0000 + +#define MSG_DIRECTION_INCOMING 0x00010000 +#define MSG_DIRECTION_OUTGOING 0x00020000 + +/**** DEBUGGING HISTORY ****/ + +class bdMsgHistoryList +{ + public: + +void addMsg(time_t ts, uint32_t msgType, bool incoming); +int msgCount(time_t start_ts, time_t end_ts); +void msgClear(); +void printHistory(std::ostream &out, int mode, time_t start_ts, time_t end_ts); + +bool canSend(); +bool validPeer(); + + std::multimap msgHistory; +}; + + + +class bdHistory +{ + public: +void addMsg(const bdId *id, bdToken *transId, uint32_t msgType, bool incoming); +void printMsgs(); +void clearHistory(); + +bool canSend(const bdId *id); +bool validPeer(const bdId *id); + + /* recent history */ + //std::list lastMsgs; + std::map mHistory; +}; + + + +#endif + diff --git a/libbitdht/src/bitdht/bdiface.h b/libbitdht/src/bitdht/bdiface.h new file mode 100644 index 000000000..5c4c187af --- /dev/null +++ b/libbitdht/src/bitdht/bdiface.h @@ -0,0 +1,355 @@ +#ifndef BIT_DHT_INTERFACE_H +#define BIT_DHT_INTERFACE_H + +/* + * bitdht/bdiface.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include +#include +#include +#include +#include + +#include "util/bdnet.h" + +/* + * Functions and Classes required for Interfacing with the BitDht. + * This should be the sole header file required to talk to Dht. + * ... though setting it up will require including udpbitdht.h as well. + * + */ + +#define BITDHT_KEY_LEN 20 +#define BITDHT_KEY_INTLEN 5 +#define BITDHT_KEY_BITLEN 160 + + + + +#define BITDHT_MAX_PKTSIZE 1024 + +#define BITDHT_TTL 64 + +#define BITDHT_SEARCH_ONE_SHOT 1 +#define BITDHT_SEARCH_REPEATING 2 + +class bdNodeId +{ + public: + unsigned char data[BITDHT_KEY_LEN]; +}; + +class bdMetric: public bdNodeId {}; + +class bdId +{ + public: + + bdId(); + bdId(bdNodeId in_id, struct sockaddr_in in_addr); + + struct sockaddr_in addr; + bdNodeId id; +}; + +#define BITDHT_LIKELY_SAME_NO 0x00000000 +#define BITDHT_LIKELY_SAME_YES 0x00000001 +#define BITDHT_LIKELY_SAME_PORT_CHANGED 0x00000002 +#define BITDHT_LIKELY_SAME_LOC_CHANGED 0x00000004 +#define BITDHT_LIKELY_SAME_IDENTICAL 0x00000008 + + +class bdDhtFunctions +{ + public: + +// bdDhtFunctions(); + /* setup variables */ +virtual uint16_t bdNumBuckets() = 0; +virtual uint16_t bdNodesPerBucket() = 0; /* used for query + bdspace */ +virtual uint16_t bdBucketBitSize() = 0; + +virtual int bdDistance(const bdNodeId *n1, const bdNodeId *n2, bdMetric *metric) = 0; +virtual int bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2) = 0; +virtual int bdBucketDistance(const bdMetric *metric) = 0; + +virtual bool bdSimilarId(const bdId *id1, const bdId *id2) = 0; +virtual bool bdUpdateSimilarId(bdId *dest, const bdId *src) = 0; + +virtual void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid) = 0; + +virtual void bdPrintId(std::ostream &out, const bdId *a) = 0; +virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a) = 0; + +}; + + + +/* NODE OPTIONS */ +#define BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT 0x00000001 + + + +/* peer flags + * order is important! + * higher bits = more priority. + * BITDHT_PEER_STATUS_RECVPING + * BITDHT_PEER_STATUS_RECVPONG + * BITDHT_PEER_STATUS_RECVNODES + * BITDHT_PEER_STATUS_RECVHASHES + * BITDHT_PEER_STATUS_DHT_ENGINE (dbXXxx) + * BITDHT_PEER_STATUS_DHT_APPL (XXRSxx) + * BITDHT_PEER_STATUS_DHT_VERSION (XXxx50) + * + */ + +#define BITDHT_PEER_STATUS_MASK_RECVD 0x000000ff +#define BITDHT_PEER_STATUS_MASK_DHT 0x0000ff00 +#define BITDHT_PEER_STATUS_MASK_KNOWN 0x00ff0000 + +#define BITDHT_PEER_STATUS_RECV_PING 0x00000001 +#define BITDHT_PEER_STATUS_RECV_PONG 0x00000002 +#define BITDHT_PEER_STATUS_RECV_NODES 0x00000004 +#define BITDHT_PEER_STATUS_RECV_HASHES 0x00000008 +#define BITDHT_PEER_STATUS_RECV_CONNECT_MSG 0x00000010 + +#define BITDHT_PEER_STATUS_DHT_ENGINE 0x00000100 +#define BITDHT_PEER_STATUS_DHT_ENGINE_VERSION 0x00000200 +#define BITDHT_PEER_STATUS_DHT_APPL 0x00000400 +#define BITDHT_PEER_STATUS_DHT_APPL_VERSION 0x00000800 + +#define BITDHT_PEER_STATUS_DHT_WHITELIST 0x00010000 +#define BITDHT_PEER_STATUS_DHT_FOF 0x00020000 +#define BITDHT_PEER_STATUS_DHT_FRIEND 0x00040000 + + +// EXTRA FLAGS are our internal thoughts about the peer. +#define BITDHT_PEER_EXFLAG_MASK_BASIC 0x000000ff +#define BITDHT_PEER_EXFLAG_UNSTABLE 0x00000001 // Port changes. +#define BITDHT_PEER_EXFLAG_ATTACHED 0x00000002 // We will ping in heavily. (if unstable) + + + + + + +#define BITDHT_CONNECT_MODE_DIRECT 0x00000001 +#define BITDHT_CONNECT_MODE_PROXY 0x00000002 +#define BITDHT_CONNECT_MODE_RELAY 0x00000004 + +#define BITDHT_CONNECT_OPTION_AUTOPROXY 0x00000001 + +// STATUS CODES. == 0 is okay, != 0 is error. +#define BITDHT_CONNECT_ANSWER_OKAY 0x00000000 +#define BITDHT_CONNECT_ERROR_NONE (BITDHT_CONNECT_ANSWER_OKAY) + +#define BITDHT_CONNECT_ERROR_MASK_TYPE 0x0000ffff +#define BITDHT_CONNECT_ERROR_MASK_SOURCE 0x00ff0000 +#define BITDHT_CONNECT_ERROR_MASK_CRMOVE 0xff000000 + +#define BITDHT_CONNECT_ERROR_SOURCE_START 0x00010000 +#define BITDHT_CONNECT_ERROR_SOURCE_MID 0x00020000 +#define BITDHT_CONNECT_ERROR_SOURCE_END 0x00040000 +#define BITDHT_CONNECT_ERROR_SOURCE_OTHER 0x00080000 + +#define BITDHT_CONNECT_ERROR_CRMOVE_FATAL 0x01000000 +#define BITDHT_CONNECT_ERROR_CRMOVE_NOMOREIDS 0x02000000 +#define BITDHT_CONNECT_ERROR_CRMOVE_NEXTID 0x04000000 +#define BITDHT_CONNECT_ERROR_CRMOVE_PAUSED 0x08000000 + +// ERROR CODES. +#define BITDHT_CONNECT_ERROR_GENERIC 0x00000001 +#define BITDHT_CONNECT_ERROR_PROTOCOL 0x00000002 +#define BITDHT_CONNECT_ERROR_TIMEOUT 0x00000003 +#define BITDHT_CONNECT_ERROR_TEMPUNAVAIL 0x00000004 // Haven't got ext address yet. +#define BITDHT_CONNECT_ERROR_NOADDRESS 0x00000005 // Can't find the peer in tables. +#define BITDHT_CONNECT_ERROR_UNREACHABLE 0x00000006 // Symmetric NAT + +#define BITDHT_CONNECT_ERROR_UNSUPPORTED 0x00000007 +#define BITDHT_CONNECT_ERROR_OVERLOADED 0x00000008 +#define BITDHT_CONNECT_ERROR_AUTH_DENIED 0x00000009 +#define BITDHT_CONNECT_ERROR_DUPLICATE 0x0000000a + +// These are slightly special ones used for CB_REQUEST +#define BITDHT_CONNECT_ERROR_TOOMANYRETRY 0x0000000b +#define BITDHT_CONNECT_ERROR_OUTOFPROXY 0x0000000c +#define BITDHT_CONNECT_ERROR_USER 0x0000000d + + + + + + +/* Definitions of bdSpace Peer and Bucket are publically available, + * so we can expose the bucket entries for the gui. + */ + +class bdPeer +{ + public: + bdPeer():mPeerFlags(0), mLastSendTime(0), mLastRecvTime(0), mFoundTime(0), mExtraFlags(0) { return; } + + bdId mPeerId; + uint32_t mPeerFlags; + time_t mLastSendTime; + time_t mLastRecvTime; + time_t mFoundTime; /* time stamp that peer was found */ + + uint32_t mExtraFlags; +}; + +class bdBucket +{ + public: + + bdBucket(); + /* list so we can queue properly */ + std::list entries; +}; + +class bdQueryStatus +{ + public: + uint32_t mStatus; + uint32_t mQFlags; + std::list mResults; +}; + +class bdQuerySummary +{ + public: + + bdNodeId mId; + bdMetric mLimit; + uint32_t mState; + time_t mQueryTS; + uint32_t mQueryFlags; + int32_t mSearchTime; + + int32_t mQueryIdlePeerRetryPeriod; // seconds between retries. + + // closest peers + std::multimap mClosest; + std::multimap mPotentialPeers; + std::list mProxiesUnknown; + std::list mProxiesFlagged; +}; + + + + +/* Status options */ +#define BITDHT_QUERY_READY 1 +#define BITDHT_QUERY_QUERYING 2 +#define BITDHT_QUERY_FAILURE 3 +#define BITDHT_QUERY_FOUND_CLOSEST 4 +#define BITDHT_QUERY_PEER_UNREACHABLE 5 +#define BITDHT_QUERY_SUCCESS 6 + +/* Query Flags */ +#define BITDHT_QFLAGS_NONE 0x0000 +#define BITDHT_QFLAGS_DISGUISE 0x0001 +#define BITDHT_QFLAGS_DO_IDLE 0x0002 +#define BITDHT_QFLAGS_INTERNAL 0x0004 // means it runs through startup. +#define BITDHT_QFLAGS_QUICK 0x0008 // ONE Request per peer. +#define BITDHT_QFLAGS_UPDATES 0x0010 // Do regular updates. + +/* Connect Callback Flags */ +#define BITDHT_CONNECT_CB_AUTH 1 +#define BITDHT_CONNECT_CB_PENDING 2 +#define BITDHT_CONNECT_CB_START 3 +#define BITDHT_CONNECT_CB_PROXY 4 +#define BITDHT_CONNECT_CB_FAILED 5 +#define BITDHT_CONNECT_CB_REQUEST 6 + +#define BD_PROXY_CONNECTION_UNKNOWN_POINT 0 +#define BD_PROXY_CONNECTION_START_POINT 1 +#define BD_PROXY_CONNECTION_MID_POINT 2 +#define BD_PROXY_CONNECTION_END_POINT 3 + +class BitDhtCallback +{ + public: +// ~BitDhtCallback(); + + // dummy cos not needed for standard dht behaviour; +virtual int dhtNodeCallback(const bdId * /*id*/, uint32_t /*peerflags*/) { return 0; } + + // must be implemented. +virtual int dhtPeerCallback(const bdId *id, uint32_t status) = 0; +virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) = 0; + + // connection callback. Not required for basic behaviour, but forced for initial development. +virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, + uint32_t mode, uint32_t point, uint32_t cbtype, uint32_t errcode) = 0; /* { return 0; } */ + +}; + + +class BitDhtInterface +{ + public: + + /***** Request Lookup (DHT Peer & Keyword) *****/ +virtual void addFindNode(bdNodeId *id, uint32_t mode) = 0; +virtual void removeFindNode(bdNodeId *id) = 0; +virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode) = 0; + + /***** Connections Requests *****/ +virtual void ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t start) = 0; +virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t answer) = 0; +virtual void ConnectionOptions(uint32_t allowedModes, uint32_t flags) = 0; + + + /***** Add / Remove Callback Clients *****/ +virtual void addCallback(BitDhtCallback *cb) = 0; +virtual void removeCallback(BitDhtCallback *cb) = 0; + + /***** Get Results Details *****/ +virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) = 0; +virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value) = 0; +virtual int getDhtBucket(const int idx, bdBucket &bucket) = 0; + +virtual int getDhtQueries(std::map &queries) = 0; +virtual int getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query) = 0; + + /* stats and Dht state */ +virtual int startDht() = 0; +virtual int stopDht() = 0; +virtual int stateDht() = 0; /* STOPPED, STARTING, ACTIVE, FAILED */ +virtual uint32_t statsNetworkSize() = 0; +virtual uint32_t statsBDVersionSize() = 0; /* same version as us! */ +}; + + +// general helper functions for decoding error messages. +std::string decodeConnectionError(uint32_t errcode); +std::string decodeConnectionErrorCRMove(uint32_t errcode); +std::string decodeConnectionErrorSource(uint32_t errcode); +std::string decodeConnectionErrorType(uint32_t errcode); + + +#endif + diff --git a/libbitdht/src/bitdht/bdmanager.cc b/libbitdht/src/bitdht/bdmanager.cc new file mode 100644 index 000000000..439b6f769 --- /dev/null +++ b/libbitdht/src/bitdht/bdmanager.cc @@ -0,0 +1,1290 @@ +/* + * bitdht/bdmanager.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +/******* + * Node Manager. + ******/ + +/****************************************** + * 1) Maintains a list of ids to search for. + * 2) Sets up initial search for own node. + * 3) Checks on status of queries. + * 4) Callback on successful searches. + * + * This is pretty specific to RS requirements. + ****/ + +#include "bitdht/bdiface.h" +#include "bitdht/bdstddht.h" +#include "bitdht/bdmanager.h" +#include "bitdht/bdmsgs.h" +#include "bitdht/bencode.h" +#include "bitdht/bdquerymgr.h" + +#include +#include +#include + +#include "util/bdnet.h" +#include "util/bdrandom.h" + +/*** + * #define DEBUG_MGR 1 + * #define DEBUG_MGR_PKT 1 + ***/ + +//#define DEBUG_MGR 1 + +//#define LOCAL_NET_FLAG (BITDHT_PEER_STATUS_DHT_APPL) +#define LOCAL_NET_FLAG (BITDHT_PEER_STATUS_DHT_ENGINE) +// This is eventually what we want. +//#define LOCAL_NET_FLAG (BITDHT_PEER_STATUS_DHT_ENGINE_VERSION) + + +bdNodeManager::bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string bootfile, bdDhtFunctions *fns) + :bdNode(id, dhtVersion, bootfile, fns) +{ + mMode = BITDHT_MGR_STATE_OFF; + mFns = fns; + mModeTS = 0 ; + + mNetworkSize = 0; + mBdNetworkSize = 0; + + std::string bfilter = "15108044002028000000200040400081a20840001000010400070240220000020501196b2420105218204008000000201102802041000a000004000004002881001180068301458000180000040000010080820e0005811000220200040800210280582001118024041002200004000000c44400080485a50008011084040200"; + + mBloomFilter.setFilterBits(bfilter); + +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::bdNodeManager() ID: "; + mFns->bdPrintNodeId(std::cerr, id); + std::cerr << std::endl; +#endif +} + +int bdNodeManager::stopDht() +{ + time_t now = time(NULL); + + /* clean up node */ + shutdownNode(); + + /* flag queries as inactive */ + /* check if exists already */ + std::map::iterator it; + for(it = mActivePeers.begin(); it != mActivePeers.end(); it++) + { + it->second.mStatus = BITDHT_QUERY_READY; + } + + /* set state flag */ + mMode = BITDHT_MGR_STATE_OFF; + mModeTS = now; + + return 1; +} + +int bdNodeManager::startDht() +{ + time_t now = time(NULL); + + /* set startup mode */ + restartNode(); + + mMode = BITDHT_MGR_STATE_STARTUP; + mModeTS = now; + + mStartTS = now; + mSearchingDone = false; + mSearchTS = now; + + return 1; +} + + /* STOPPED, STARTING, ACTIVE, FAILED */ +int bdNodeManager::stateDht() +{ + return mMode; +} + +uint32_t bdNodeManager::statsNetworkSize() +{ + return mNetworkSize; +} + +/* same version as us! */ +uint32_t bdNodeManager::statsBDVersionSize() +{ + return mBdNetworkSize; +} + + +void bdNodeManager::addFindNode(bdNodeId *id, uint32_t qflags) +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::addFindNode() "; + mFns->bdPrintNodeId(std::cerr, id); + std::cerr << std::endl; +#endif + /* check if exists already */ + std::map::iterator it; + it = mActivePeers.find(*id); + if (it != mActivePeers.end()) + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::addFindNode() Found existing...."; + std::cerr << std::endl; +#endif + return; + } + + /* add to map */ + bdQueryPeer peer; + peer.mId.id = (*id); + peer.mStatus = BITDHT_QUERY_READY; //QUERYING; + peer.mQFlags = qflags; + + peer.mDhtAddr.sin_addr.s_addr = 0; + peer.mDhtAddr.sin_port = 0; + + mActivePeers[*id] = peer; +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::addFindNode() Added QueryPeer as READY...."; + std::cerr << std::endl; +#endif + //addQuery(id, qflags | BITDHT_QFLAGS_DISGUISE); + return; +} + + /* finds a queued query, and starts it */ +void bdNodeManager::startQueries() +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::startQueries() "; + std::cerr << std::endl; +#endif + /* check if exists already */ + std::map::iterator it; + for(it = mActivePeers.begin(); it != mActivePeers.end(); it++) + { + if (it->second.mStatus == BITDHT_QUERY_READY) + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::startQueries() Found READY Query."; + std::cerr << std::endl; +#endif + it->second.mStatus = BITDHT_QUERY_QUERYING; + + uint32_t qflags = it->second.mQFlags | BITDHT_QFLAGS_DISGUISE; + mQueryMgr->addQuery(&(it->first), qflags); + + // add all queries at the same time! + //return; + } + } + return; +} + + +void bdNodeManager::removeFindNode(bdNodeId *id) +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::removeFindNode() "; + mFns->bdPrintNodeId(std::cerr, id); + std::cerr << std::endl; +#endif + std::map::iterator it; + it = mActivePeers.find(*id); + if (it == mActivePeers.end()) + { + return; + } + + /* cleanup any actions */ + mQueryMgr->clearQuery(&(it->first)); + //clearPing(&(it->first)); + + /* remove from map */ + mActivePeers.erase(it); + return; +} + +void bdNodeManager::iteration() +{ + + time_t now = time(NULL); + time_t modeAge = now - mModeTS; + switch(mMode) + { + case BITDHT_MGR_STATE_OFF: + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration(): OFF"; + std::cerr << std::endl; +#endif + } + break; + + case BITDHT_MGR_STATE_STARTUP: + /* 10 seconds startup .... then switch to ACTIVE */ + + if (modeAge > MAX_STARTUP_TIME) + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration(): STARTUP -> REFRESH"; + std::cerr << std::endl; +#endif + bdNodeId id; + getOwnId(&id); + mQueryMgr->addQuery(&id, BITDHT_QFLAGS_DO_IDLE | BITDHT_QFLAGS_DISGUISE); + + mMode = BITDHT_MGR_STATE_FINDSELF; + mModeTS = now; + } + break; + + case BITDHT_MGR_STATE_FINDSELF: + /* 60 seconds further startup .... then switch to ACTIVE + * if we reach TRANSITION_OP_SPACE_SIZE before this time, transition immediately... + * if, after 60 secs, we haven't reached MIN_OP_SPACE_SIZE, restart.... + */ + +#define TRANSITION_OP_SPACE_SIZE 100 /* 1 query / sec, should take 12-15 secs */ +//#define MAX_FINDSELF_TIME 60 +//#define MIN_OP_SPACE_SIZE 20 +#define MAX_FINDSELF_TIME 10 +#define MIN_OP_SPACE_SIZE 2 // for testing. self + oneother. + + { + uint32_t nodeSpaceSize = mNodeSpace.calcSpaceSize(); + +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration() Finding Oneself: "; + std::cerr << "NodeSpace Size:" << nodeSpaceSize; + std::cerr << std::endl; +#endif + + if (nodeSpaceSize > TRANSITION_OP_SPACE_SIZE) + { + mMode = BITDHT_MGR_STATE_REFRESH; + mModeTS = now; + } + + if (modeAge > MAX_FINDSELF_TIME) + { + if (nodeSpaceSize >= MIN_OP_SPACE_SIZE) + { + mMode = BITDHT_MGR_STATE_REFRESH; + mModeTS = now; + } + else + { + mMode = BITDHT_MGR_STATE_FAILED; + mModeTS = now; + } + } + } + + break; + + case BITDHT_MGR_STATE_ACTIVE: + if (modeAge > MAX_REFRESH_TIME) + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration(): ACTIVE -> REFRESH"; + std::cerr << std::endl; +#endif + mMode = BITDHT_MGR_STATE_REFRESH; + mModeTS = now; + } + + break; + + case BITDHT_MGR_STATE_REFRESH: + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration(): REFRESH -> ACTIVE"; + std::cerr << std::endl; +#endif + /* select random ids, and perform searchs to refresh space */ + mMode = BITDHT_MGR_STATE_ACTIVE; + mModeTS = now; + +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration(): Starting Query"; + std::cerr << std::endl; +#endif + + startQueries(); + +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration(): Updating Stores"; + std::cerr << std::endl; +#endif + + updateStore(); + +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration(): Do App Search"; + std::cerr << std::endl; +#endif + + /* run a random search for ourselves, from own App DHT peer */ + QueryRandomLocalNet(); + +#define SEARCH_MAX_SIZE 10 + if (mBdNetworkSize < SEARCH_MAX_SIZE) + { + std::cerr << "Local Netsize: " << mBdNetworkSize << " to small...searching"; + std::cerr << std::endl; + + /* if the network size is very small */ + SearchForLocalNet(); + mSearchingDone = false; + } + else + { + if (!mSearchingDone) + { + mSearchingDone = true; + mSearchTS = now; + std::cerr << "Completed LocalNet Search in : " << mSearchTS-mStartTS; + std::cerr << std::endl; + } + } + +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration(): REFRESH "; + std::cerr << std::endl; +#endif + + status(); /* calculates mNetworkSize */ + +#ifdef DEBUG_MGR + mAccount.printStats(std::cerr); +#endif + + /* Finally, Fail, and restart if we lose all peers */ + uint32_t nodeSpaceSize = mNodeSpace.calcSpaceSize(); + if (nodeSpaceSize < MIN_OP_SPACE_SIZE) + { + std::cerr << "bdNodeManager::iteration(): SpaceSize to Small: " << nodeSpaceSize; + std::cerr << std::endl; + std::cerr << "bdNodeManager::iteration(): REFRESH ==> FAILED"; + std::cerr << std::endl; + + mMode = BITDHT_MGR_STATE_FAILED; + mModeTS = now; + } + } + break; + + case BITDHT_MGR_STATE_QUIET: + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::iteration(): QUIET"; + std::cerr << std::endl; +#endif + + + } + break; + + default: + case BITDHT_MGR_STATE_FAILED: + { + std::cerr << "bdNodeManager::iteration(): FAILED ==> STARTUP"; + std::cerr << std::endl; +#ifdef DEBUG_MGR +#endif + stopDht(); + startDht(); + } + break; + } + + if (mMode == BITDHT_MGR_STATE_OFF) + { + bdNode::iterationOff(); + } + else + { + /* tick parent */ + bdNode::iteration(); + } +} + + /* NB: This is a bit of a hack, the code is duplicated from bdnode & bdquery. + * should use fn calls into their functions for good generality + */ + +#define RANDOM_SEARCH_FRAC (0.1) + +int bdNodeManager::QueryRandomLocalNet() +{ + bdId id; + bdNodeId targetNodeId; + + uint32_t withFlag = LOCAL_NET_FLAG; + if (mNodeSpace.findRandomPeerWithFlag(id, withFlag)) + { + /* if we've got a very small network size... then ask them about a random peer. + * (so we get there 159/158 boxes! + */ + bool isRandom = false; + if ((mBdNetworkSize < SEARCH_MAX_SIZE) || (RANDOM_SEARCH_FRAC > bdRandom::random_f32())) + { + bdStdRandomNodeId(&targetNodeId); + isRandom = true; + } + else + { + /* calculate mid point */ + mFns->bdRandomMidId(&mOwnId, &(id.id), &targetNodeId); + } + + /* do standard find_peer message */ + + mQueryMgr->addWorthyPeerSource(&id); /* Tell BitDHT that we really want to ping their peers */ + send_query(&id, &targetNodeId); + +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNodeManager::QueryRandomLocalNet() Querying : "; + mFns->bdPrintId(std::cerr, &id); + std::cerr << " searching for : "; + mFns->bdPrintNodeId(std::cerr, &targetNodeId); + std::cerr << std::endl; +#endif + + if (isRandom) + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNodeManager::QueryRandomLocalNet() Search is Random!"; + std::cerr << std::endl; +#endif + } + + return 1; + } + else + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNodeManager::QueryRandomLocalNet() No LocalNet Peer Found"; + std::cerr << std::endl; +#endif + } + + return 0; +} + + + +void bdNodeManager::SearchForLocalNet() +{ + + +#ifdef DEBUG_MGR +#endif + std::cerr << "bdNodeManager::SearchForLocalNet()"; + std::cerr << std::endl; + + /* Check how many "Search Queries" we've got going. */ + + /* check queries */ + std::map::iterator it; + std::map queryStatus; + + + mQueryMgr->QueryStatus(queryStatus); + + int numSearchQueries = 0; + for(it = queryStatus.begin(); it != queryStatus.end(); it++) + { + if (it->second.mQFlags & BITDHT_QFLAGS_INTERNAL) + { + std::cerr << "bdNodeManager::SearchForLocalNet() Existing Internal Search: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; + + numSearchQueries++; + } + } + +#define MAX_SEARCH_QUERIES 5 + + for(;numSearchQueries < MAX_SEARCH_QUERIES; numSearchQueries++) + { + /* install a new query */ + bdNodeId targetNodeId; + + /* get something that filter approves of */ + bool filterOk = false; + int i; + +#define MAX_FILTER_ATTEMPTS 3000 + + for(i = 0; (!filterOk) && (i < MAX_FILTER_ATTEMPTS); i++) + { + bdStdRandomNodeId(&targetNodeId); + std::ostringstream tststr; + bdStdPrintNodeId(tststr, &targetNodeId); + + if (mBloomFilter.test(tststr.str())) + { + filterOk = true; + } + } + + if (filterOk) + { + std::cerr << "bdNodeManager::SearchForLocalNet() " << i << " Attempts to find OkNode: "; + mFns->bdPrintNodeId(std::cerr, &targetNodeId); + std::cerr << std::endl; + } + else + { + std::cerr << "bdNodeManager::SearchForLocalNet() Failed to Find FilterOk this time: "; + mFns->bdPrintNodeId(std::cerr, &targetNodeId); + std::cerr << std::endl; + } + + + uint32_t qflags = BITDHT_QFLAGS_INTERNAL | BITDHT_QFLAGS_DISGUISE; + mQueryMgr->addQuery(&targetNodeId, qflags); + +#ifdef DEBUG_NODE_MSGS +#endif + std::cerr << "bdNodeManager::SearchForLocalNet() Adding New Internal Search: "; + mFns->bdPrintNodeId(std::cerr, &(targetNodeId)); + std::cerr << std::endl; + } +} + + +int bdNodeManager::status() +{ + /* do status of bdNode */ +#ifdef DEBUG_MGR + printState(); +#endif + + checkStatus(); + + /* update the network numbers */ + mNetworkSize = mNodeSpace.calcNetworkSize(); + mBdNetworkSize = mNodeSpace.calcNetworkSizeWithFlag( + LOCAL_NET_FLAG); + +#ifdef DEBUG_MGR + std::cerr << "BitDHT NetworkSize: " << mNetworkSize << std::endl; + std::cerr << "BitDHT App NetworkSize: " << mBdNetworkSize << std::endl; +#endif + + return 1; +} + + +int bdNodeManager::checkStatus() +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus()"; + std::cerr << std::endl; +#endif + + /* check queries */ + std::map::iterator it; + std::map queryStatus; + + + mQueryMgr->QueryStatus(queryStatus); + + for(it = queryStatus.begin(); it != queryStatus.end(); it++) + { + bool doPing = false; + bool doRemove = false; + bool doCallback = false; + bool doSaveAddress = false; + uint32_t callbackStatus = 0; + + switch(it->second.mStatus) + { + default: + case BITDHT_QUERY_QUERYING: + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Query in Progress id: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; +#endif + } + break; + + case BITDHT_QUERY_FAILURE: + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Query Failed: id: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; +#endif + // BAD. + doRemove = true; + doCallback = true; + callbackStatus = BITDHT_MGR_QUERY_FAILURE; + } + break; + + case BITDHT_QUERY_FOUND_CLOSEST: + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Found Closest: id: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; +#endif + + doRemove = true; + doCallback = true; + callbackStatus = BITDHT_MGR_QUERY_PEER_OFFLINE; + } + break; + + case BITDHT_QUERY_PEER_UNREACHABLE: + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() the Peer Online but Unreachable: id: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; +#endif + + doRemove = true; + doCallback = true; + callbackStatus = BITDHT_MGR_QUERY_PEER_UNREACHABLE; + } + break; + + case BITDHT_QUERY_SUCCESS: + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Found Query: id: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; +#endif + //foundId = + doRemove = true; + doCallback = true; + doSaveAddress = true; + callbackStatus = BITDHT_MGR_QUERY_PEER_ONLINE; + } + break; + } + + /* remove done queries */ + if (doRemove) + { + if (it->second.mQFlags & BITDHT_QFLAGS_DO_IDLE) + { + doRemove = false; + } + } + + if (doRemove) + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Removing query: id: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; +#endif + mQueryMgr->clearQuery(&(it->first)); + } + + /* FIND in activePeers */ + std::map::iterator pit; + pit = mActivePeers.find(it->first); + + if (pit == mActivePeers.end()) + { + /* only internal! - disable Callback / Ping */ + doPing = false; + doCallback = false; +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Internal: no cb for id: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; +#endif + } + else + { + if (pit->second.mStatus == it->second.mStatus) + { + /* status is unchanged */ + doPing = false; + doCallback = false; +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Status unchanged for : "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << " status: " << it->second.mStatus; + std::cerr << std::endl; +#endif + } + else + { + +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Updating External Status for : "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << " to: " << it->second.mStatus; + std::cerr << std::endl; +#endif + /* update status */ + pit->second.mStatus = it->second.mStatus; + } + + if (doSaveAddress) + { + if (it->second.mResults.size() > 0) + { + pit->second.mDhtAddr = it->second.mResults.front().addr; + } + else + { + pit->second.mDhtAddr.sin_addr.s_addr = 0; + pit->second.mDhtAddr.sin_port = 0; + } + } + + /* add successful queries to ping list */ + if (doPing) + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Starting Ping (TODO): id: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; +#endif + /* add first matching peer */ + //addPeerPing(foundId); + } + + /* callback on new successful queries */ + if (doCallback) + { +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::checkStatus() Doing Callback: id: "; + mFns->bdPrintNodeId(std::cerr, &(it->first)); + std::cerr << std::endl; +#endif + bdId id(it->first,pit->second.mDhtAddr); + doPeerCallback(&id, callbackStatus); + } + } + } + return 1; +} + +#if 0 +bdNodeManager::checkPingStatus() +{ + + /* check queries */ + std::map::iterator it; + std::map pingStatus; + + PingStatus(pingStatus); + + for(it = pingStatus.begin(); it != pingStatus.end(); it++) + { + switch(it->second.mStatus) + { + case BITDHT_QUERY_QUERYING: + { + + } + break; + + case BITDHT_QUERY_FAILURE: + { + // BAD. + doRemove = true; + } + break; + + case BITDHT_QUERY_FOUND_CLOSEST: + { + + doRemove = true; + } + break; + + case BITDHT_QUERY_SUCCESS: + { + foundId = + doRemove = true; + } + break; + } + + /* remove done queries */ + if (doRemove) + { + clearQuery(it->first); + } + + /* add successful queries to ping list */ + if (doPing) + { + /* add first matching peer */ + addPeerPing(foundId); + } + + /* callback on new successful queries */ + if (doCallback) + { + + } + } +} +#endif + + +int bdNodeManager::SearchOutOfDate() +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::SearchOutOfDate()"; + std::cerr << std::endl; +#endif + + std::map::iterator it; + + /* search for out-of-date peers */ + for(it = mActivePeers.begin(); it != mActivePeers.end(); it++) + { +#if 0 + if (old) + { + addQuery(it->first); + } +#endif + } + + return 1; +} + + + + /***** Functions to Call down to bdNodeManager ****/ + /* Request DHT Peer Lookup */ + /* Request Keyword Lookup */ + +void bdNodeManager::findDhtValue(bdNodeId * /*id*/, std::string /*key*/, uint32_t /*mode*/) +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::findDhtValue() TODO"; + std::cerr << std::endl; +#endif +} + + + /***** Get Results Details *****/ +int bdNodeManager::getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::getDhtPeerAddress() Id: "; + mFns->bdPrintNodeId(std::cerr, id); + std::cerr << " ... ? TODO" << std::endl; +#else + (void) id; +#endif + + std::map::iterator pit; + pit = mActivePeers.find(*id); + + std::cerr << "bdNodeManager::getDhtPeerAddress() Id: "; + mFns->bdPrintNodeId(std::cerr, id); + std::cerr << std::endl; + + if (pit != mActivePeers.end()) + { + std::cerr << "bdNodeManager::getDhtPeerAddress() Found ActiveQuery"; + std::cerr << std::endl; + + if (pit->second.mStatus == BITDHT_QUERY_SUCCESS) + { + from = pit->second.mDhtAddr; + + std::cerr << "bdNodeManager::getDhtPeerAddress() Found Peer Address:"; + std::cerr << inet_ntoa(from.sin_addr) << ":" << htons(from.sin_port); + std::cerr << std::endl; + + return 1; + } + } + return 0; + +} + +int bdNodeManager::getDhtValue(const bdNodeId *id, std::string key, std::string & /*value*/) +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::getDhtValue() Id: "; + mFns->bdPrintNodeId(std::cerr, id); + std::cerr << " key: " << key; + std::cerr << " ... ? TODO" << std::endl; +#else + (void) id; + (void) key; +#endif + + return 1; +} + +int bdNodeManager::getDhtBucket(const int idx, bdBucket &bucket) +{ + return mNodeSpace.getDhtBucket(idx, bucket); +} + +int bdNodeManager::getDhtQueries(std::map &queries) +{ + mQueryMgr->QueryStatus(queries); + return 1; +} + +int bdNodeManager::getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query) +{ + return mQueryMgr->QuerySummary(id, query); +} + + + /***** Add / Remove Callback Clients *****/ +void bdNodeManager::addCallback(BitDhtCallback *cb) +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::addCallback()"; + std::cerr << std::endl; +#endif + /* search list */ + std::list::iterator it; + it = std::find(mCallbacks.begin(), mCallbacks.end(), cb); + if (it == mCallbacks.end()) + { + /* add it */ + mCallbacks.push_back(cb); + } +} + +void bdNodeManager::removeCallback(BitDhtCallback *cb) +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::removeCallback()"; + std::cerr << std::endl; +#endif + /* search list */ + std::list::iterator it; + it = std::find(mCallbacks.begin(), mCallbacks.end(), cb); + if (it == mCallbacks.end()) + { + /* not found! */ + return; + } + it = mCallbacks.erase(it); +} + + +void bdNodeManager::addPeer(const bdId *id, uint32_t peerflags) +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::addPeer() Overloaded (doing Callback)"; + std::cerr << std::endl; +#endif + doNodeCallback(id, peerflags); + + // call parent. + bdNode::addPeer(id, peerflags); + + return; +} + + + +void bdNodeManager::doNodeCallback(const bdId *id, uint32_t peerflags) +{ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::doNodeCallback() "; + mFns->bdPrintId(std::cerr, id); + std::cerr << "peerflags: " << peerflags; + std::cerr << std::endl; +#endif + + /* search list */ + std::list::iterator it; + for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) + { + (*it)->dhtNodeCallback(id, peerflags); + } + return; +} + +void bdNodeManager::doPeerCallback(const bdId *id, uint32_t status) +{ + +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::doPeerCallback()"; + mFns->bdPrintId(std::cerr, id); + std::cerr << "status: " << status; + std::cerr << std::endl; +#endif + + /* search list */ + std::list::iterator it; + for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) + { + (*it)->dhtPeerCallback(id, status); + } + return; +} + +void bdNodeManager::doValueCallback(const bdNodeId *id, std::string key, uint32_t status) +{ + std::cerr << "bdNodeManager::doValueCallback()"; + std::cerr << std::endl; + +#ifdef DEBUG_MGR +#endif + /* search list */ + std::list::iterator it; + for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) + { + (*it)->dhtValueCallback(id, key, status); + } + return; +} + + + + /******************* Internals *************************/ +int bdNodeManager::isBitDhtPacket(char *data, int size, struct sockaddr_in & from) + +{ +#ifdef DEBUG_MGR_PKT + std::cerr << "bdNodeManager::isBitDhtPacket() *******************************"; + std::cerr << " from " << inet_ntoa(from.sin_addr); + std::cerr << ":" << ntohs(from.sin_port); + std::cerr << std::endl; + { + /* print the fucker... only way to catch bad ones */ + std::ostringstream out; + for(int i = 0; i < size; i++) + { + if (isascii(data[i])) + { + out << data[i]; + } + else + { + out << "["; + out << std::setw(2) << std::setfill('0') + << std::hex << (uint32_t) data[i]; + out << "]"; + } + if ((i % 16 == 0) && (i != 0)) + { + out << std::endl; + } + } + std::cerr << out.str(); + } + std::cerr << "bdNodeManager::isBitDhtPacket() *******************************"; + std::cerr << std::endl; +#else + (void) from; +#endif + + /* try to parse it! */ + /* convert to a be_node */ + be_node *node = be_decoden(data, size); + if (!node) + { + /* invalid decode */ +#ifdef DEBUG_MGR + std::cerr << "bdNodeManager::isBitDhtPacket() be_decode failed. dropping"; + std::cerr << std::endl; + std::cerr << "bdNodeManager::BadPacket ******************************"; + std::cerr << " from " << inet_ntoa(from.sin_addr); + std::cerr << ":" << ntohs(from.sin_port); + std::cerr << std::endl; + { + /* print the fucker... only way to catch bad ones */ + std::ostringstream out; + for(int i = 0; i < size; i++) + { + if (isascii(data[i])) + { + out << data[i]; + } + else + { + out << "["; + out << std::setw(2) << std::setfill('0') + << std::hex << (uint32_t) data[i]; + out << "]"; + } + if ((i % 16 == 0) && (i != 0)) + { + out << std::endl; + } + } + std::cerr << out.str(); + } + std::cerr << "bdNodeManager::BadPacket ******************************"; + std::cerr << std::endl; +#endif + return 0; + } + + /* find message type */ + uint32_t beType = beMsgType(node); + int ans = (beType != BITDHT_MSG_TYPE_UNKNOWN); + be_free(node); + +#ifdef DEBUG_MGR_PKT + if (ans) + { + std::cerr << "bdNodeManager::isBitDhtPacket() YES"; + std::cerr << std::endl; + } + else + { + std::cerr << "bdNodeManager::isBitDhtPacket() NO: Unknown Type"; + std::cerr << std::endl; + } + +#endif + return ans; +} + + +bdDebugCallback::~bdDebugCallback() +{ +} + +int bdDebugCallback::dhtPeerCallback(const bdId *id, uint32_t status) +{ +#ifdef DEBUG_MGR + std::cerr << "bdDebugCallback::dhtPeerCallback() Id: "; +#endif + bdStdPrintId(std::cerr, id); +#ifdef DEBUG_MGR + std::cerr << " status: " << std::hex << status << std::dec << std::endl; +#endif + return 1; +} + +int bdDebugCallback::dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) +{ +#ifdef DEBUG_MGR + std::cerr << "bdDebugCallback::dhtValueCallback() Id: "; +#endif + bdStdPrintNodeId(std::cerr, id); +#ifdef DEBUG_MGR + std::cerr << " key: " << key; + std::cerr << " status: " << std::hex << status << std::dec << std::endl; +#endif + + return 1; +} + + + + + +/******************* Connection Stuff ********************/ + + + +void bdNodeManager::ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t start) +{ + std::cerr << "bdNodeManager::ConnectionRequest()"; + std::cerr << std::endl; + + mConnMgr->requestConnection(laddr, target, mode, start); +} + +void bdNodeManager::ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t answer) +{ + std::cerr << "bdNodeManager::ConnectionAuth()"; + std::cerr << std::endl; + + if (answer == BITDHT_CONNECT_ANSWER_OKAY) + { + mConnMgr->AuthConnectionOk(srcId, proxyId, destId, mode, loc); + } + else + { + mConnMgr->AuthConnectionNo(srcId, proxyId, destId, mode, loc, answer); + } +} + +void bdNodeManager::ConnectionOptions(uint32_t allowedModes, uint32_t flags) +{ + mConnMgr->setConnectionOptions(allowedModes, flags); +} + + + /***** Connections Requests *****/ + + // Overloaded from bdnode for external node callback. +void bdNodeManager::callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, int mode, int point, int cbtype, int errcode) +{ + std::cerr << "bdNodeManager::callbackConnect()"; + std::cerr << std::endl; + +#ifdef DEBUG_MGR +#endif + /* search list */ + std::list::iterator it; + for(it = mCallbacks.begin(); it != mCallbacks.end(); it++) + { + (*it)->dhtConnectCallback(srcId, proxyId, destId, mode, point, cbtype, errcode); + } + return; +} + +int bdDebugCallback::dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, + uint32_t mode, uint32_t point, uint32_t cbtype, uint32_t errcode) +{ +#ifdef DEBUG_MGR + std::cerr << "bdDebugCallback::dhtConnectCallback() Type: " << cbtype; + std::cerr << " errCode: " << errcode; + std::cerr << " srcId: "; + bdStdPrintId(std::cerr, srcId); + std::cerr << " proxyId: "; + bdStdPrintId(std::cerr, proxyId); + std::cerr << " destId: "; + bdStdPrintId(std::cerr, destId); + std::cerr << " mode: " << mode; + std::cerr << " point: " << point << std::endl; +#endif + + return 1; +} + diff --git a/libbitdht/src/bitdht/bdmanager.h b/libbitdht/src/bitdht/bdmanager.h new file mode 100644 index 000000000..4794fabe2 --- /dev/null +++ b/libbitdht/src/bitdht/bdmanager.h @@ -0,0 +1,195 @@ +#ifndef BITDHT_MANAGER_H +#define BITDHT_MANAGER_H + +/* + * bitdht/bdmanager.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + + +/******* + * Node Manager. + ******/ + +/****************************************** + * 1) Maintains a list of ids to search for. + * 2) Sets up initial search for own node. + * 3) Checks on status of queries. + * 4) Callback on successful searches. + * + * This is pretty specific to RS requirements. + ****/ + +#define BITDHT_PS_MASK_ACTIONS (0x000000ff) +#define BITDHT_PS_MASK_STATE (0x0000ff00) + +#define BITDHT_PS_ACTION_SEARCHING (0x00000001) +#define BITDHT_PS_ACTION_WAITING (0x00000002) +#define BITDHT_PS_ACTION_PINGING (0x00000004) + +#define BITDHT_PS_STATE_UNKNOWN (0x00000100) +#define BITDHT_PS_STATE_OFFLINE (0x00000200) +#define BITDHT_PS_STATE_ONLINE (0x00000400) +#define BITDHT_PS_STATE_CONNECTED (0x00000800) + +#include "bitdht/bdiface.h" +#include "bitdht/bdnode.h" +#include "util/bdbloom.h" + + + +class bdQueryPeer +{ + public: + bdId mId; + uint32_t mStatus; + uint32_t mQFlags; + time_t mLastQuery; + time_t mLastFound; + struct sockaddr_in mDhtAddr; +}; + + +#define BITDHT_MGR_STATE_OFF 0 +#define BITDHT_MGR_STATE_STARTUP 1 +#define BITDHT_MGR_STATE_FINDSELF 2 +#define BITDHT_MGR_STATE_ACTIVE 3 +#define BITDHT_MGR_STATE_REFRESH 4 +#define BITDHT_MGR_STATE_QUIET 5 +#define BITDHT_MGR_STATE_FAILED 6 + +#define MAX_STARTUP_TIME 10 +#define MAX_REFRESH_TIME 10 + +#define BITDHT_MGR_QUERY_FAILURE 1 +#define BITDHT_MGR_QUERY_PEER_OFFLINE 2 +#define BITDHT_MGR_QUERY_PEER_UNREACHABLE 3 +#define BITDHT_MGR_QUERY_PEER_ONLINE 4 + + +/*** NB: Nothing in here is protected by mutexes + * must be done at a higher level! + ***/ + +class bdNodeManager: public bdNode, public BitDhtInterface +{ + public: + bdNodeManager(bdNodeId *id, std::string dhtVersion, std::string bootfile, bdDhtFunctions *fns); + + +void iteration(); + + /***** Functions to Call down to bdNodeManager ****/ + /* Request DHT Peer Lookup */ + /* Request Keyword Lookup */ +virtual void addFindNode(bdNodeId *id, uint32_t mode); +virtual void removeFindNode(bdNodeId *id); +virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode); + + /***** Add / Remove Callback Clients *****/ +virtual void addCallback(BitDhtCallback *cb); +virtual void removeCallback(BitDhtCallback *cb); + + /***** Get Results Details *****/ +virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from); +virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value); +virtual int getDhtBucket(const int idx, bdBucket &bucket); + +virtual int getDhtQueries(std::map &queries); +virtual int getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query); + + /***** Connection Interface ****/ +virtual void ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t start); +virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, + uint32_t mode, uint32_t loc, uint32_t answer); +virtual void ConnectionOptions(uint32_t allowedModes, uint32_t flags); + + + /* stats and Dht state */ +virtual int startDht(); +virtual int stopDht(); +virtual int stateDht(); /* STOPPED, STARTING, ACTIVE, FAILED */ +virtual uint32_t statsNetworkSize(); +virtual uint32_t statsBDVersionSize(); /* same version as us! */ + /******************* Internals *************************/ + + // Overloaded from bdnode for external node callback. +virtual void addPeer(const bdId *id, uint32_t peerflags); + // Overloaded from bdnode for external node callback. +virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, + int mode, int point, int cbtype, int errcode); + +int isBitDhtPacket(char *data, int size, struct sockaddr_in &from); + private: + + +void doNodeCallback(const bdId *id, uint32_t peerflags); +void doPeerCallback(const bdId *id, uint32_t status); +void doValueCallback(const bdNodeId *id, std::string key, uint32_t status); + +int status(); +int checkStatus(); +int checkPingStatus(); +int SearchOutOfDate(); +void startQueries(); + +int QueryRandomLocalNet(); +void SearchForLocalNet(); + + std::map mActivePeers; + std::list mCallbacks; + + uint32_t mMode; + time_t mModeTS; + + time_t mStartTS; + time_t mSearchTS; + bool mSearchingDone; + + bdDhtFunctions *mFns; + + uint32_t mNetworkSize; + uint32_t mBdNetworkSize; + + bdBloom mBloomFilter; + + /* future node functions */ + //addPeerPing(foundId); + //clearPing(it->first); + //PingStatus(it->first); +}; + +class bdDebugCallback: public BitDhtCallback +{ + public: + ~bdDebugCallback(); +virtual int dhtPeerCallback(const bdId *id, uint32_t status); +virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status); +virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, + uint32_t mode, uint32_t point, uint32_t cbtype, uint32_t errcode); + +}; + + +#endif diff --git a/libbitdht/src/bitdht/bdmsgs.cc b/libbitdht/src/bitdht/bdmsgs.cc new file mode 100644 index 000000000..a11dead46 --- /dev/null +++ b/libbitdht/src/bitdht/bdmsgs.cc @@ -0,0 +1,1034 @@ +/* + * bitdht/bdmsgs.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include +#include +#include +#include "bitdht/bencode.h" +#include "bitdht/bdmsgs.h" + + +int create_ping_message(); +int response_ping_message(); + +int find_node_message(); +int response_node_message(); + +int get_peers_message(); +int response_peers_message(); +int response_closestnodes_message(); + + /* +ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}} +bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe + */ + +/**** + * #define DEBUG_MSG_DUMP 1 + * #define DEBUG_MSG_TYPE 1 + * #define DEBUG_MSGS 1 + ****/ + + +int bitdht_create_ping_msg(bdToken *tid, bdNodeId *id, char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_create_ping_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + be_node *iddict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + + be_add_keypair(iddict, "id", idnode); + + be_node *pingnode = be_create_str("ping"); + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *qynode = be_create_str("q"); + + be_add_keypair(dict, "a", iddict); + + be_add_keypair(dict, "q", pingnode); + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", qynode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; + + +} + + + /* +Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} +bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re + */ + +int bitdht_response_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, + char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_response_ping_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *iddict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *yqrnode = be_create_str("r"); + + be_node *vnode = be_create_str_wlen((char *) vid->data, vid->len); + + be_add_keypair(iddict, "id", idnode); + be_add_keypair(dict, "r", iddict); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "v", vnode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} + + + /* +find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}} +bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe + */ + + +int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, + char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_find_node_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *iddict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + be_node *targetnode = be_create_str_wlen((char *) target->data, BITDHT_KEY_LEN); + + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *yqrnode = be_create_str("q"); + be_node *findnode = be_create_str("find_node"); + + be_add_keypair(iddict, "id", idnode); + be_add_keypair(iddict, "target", targetnode); + be_add_keypair(dict, "a", iddict); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "q", findnode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} + + + + /* +Response = {"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}} +bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re + */ + +int bitdht_resp_node_msg(bdToken *tid, bdNodeId *id, std::list &nodes, + char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_resp_node_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *replydict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + + be_node *peersnode = makeCompactNodeIdString(nodes); + + be_node *yqrnode = be_create_str("r"); + + be_add_keypair(replydict, "id", idnode); + be_add_keypair(replydict, "nodes", peersnode); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "r", replydict); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + +#ifdef DEBUG_MSG_DUMP + fprintf(stderr, "bitdht_resp_node_msg() len = %d / %d\n", blen, avail); +#endif + + return blen; +} + + + /* +get_peers Query = {"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}} +bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe + */ + +int bitdht_get_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, + char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_get_peers_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *iddict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + be_node *hashnode = be_create_str_wlen((char *) info_hash->data, BITDHT_KEY_LEN); + + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *yqrnode = be_create_str("q"); + be_node *findnode = be_create_str("get_peers"); + + be_add_keypair(iddict, "id", idnode); + be_add_keypair(iddict, "info_hash", hashnode); + be_add_keypair(dict, "a", iddict); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "q", findnode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} + + + /* +Response with peers = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}} +bencoded = d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re + */ + +int bitdht_peers_reply_hash_msg(bdToken *tid, bdNodeId *id, + bdToken *token, std::list &values, + char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_peers_reply_hash_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *replydict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *tokennode = be_create_str_wlen((char *) token->data, token->len); + be_node *valuesnode = makeCompactPeerIds(values); + + be_node *yqrnode = be_create_str("r"); + + be_add_keypair(replydict, "id", idnode); + be_add_keypair(replydict, "token", tokennode); + be_add_keypair(replydict, "values", valuesnode); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "r", replydict); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} + + /** + +Response with closest nodes = {"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."}} +bencoded = d1:rd2:id20:abcdefghij01234567895:nodes9:def456...5:token8:aoeusnthe1:t2:aa1:y1:re + + **/ + + +int bitdht_peers_reply_closest_msg(bdToken *tid, bdNodeId *id, + bdToken *token, std::list &nodes, + char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_peers_reply_closest_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *replydict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *tokennode = be_create_str_wlen((char *) token->data, token->len); + + be_node *peersnode = makeCompactNodeIdString(nodes); + + be_node *yqrnode = be_create_str("r"); + + be_add_keypair(replydict, "id", idnode); + be_add_keypair(replydict, "token", tokennode); + be_add_keypair(replydict, "nodes", peersnode); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "r", replydict); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} + + + +/**** FINAL TWO MESSAGES! ***/ + +/**** +announce_peers Query = {"t":"aa", "y":"q", "q":"announce_peer", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456", "port": 6881, "token": "aoeusnth"}} +bencoded = d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe + +****/ + +int bitdht_announce_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, uint32_t port, bdToken *token, char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_announce_peers_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + be_node *iddict = be_create_dict(); + + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + + be_node *hashnode = be_create_str_wlen((char *) info_hash->data, BITDHT_KEY_LEN); + be_node *portnode = be_create_int(port); + be_node *tokennode = be_create_str_wlen((char *) token->data, token->len); + + be_add_keypair(iddict, "id", idnode); + be_add_keypair(iddict, "info_hash", hashnode); + be_add_keypair(iddict, "port", portnode); + be_add_keypair(iddict, "token", tokennode); + + be_node *announcenode = be_create_str("announce_peer"); + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *qynode = be_create_str("q"); + + be_add_keypair(dict, "a", iddict); + + be_add_keypair(dict, "q", announcenode); + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", qynode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; + +} + + +/***** +Response to Announce Peers = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} +bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re +****/ + +/**** + * NB: This is the same as a PONG msg! + ***/ + +int bitdht_reply_announce_msg(bdToken *tid, bdNodeId *id, + char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_response_ping_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *iddict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *yqrnode = be_create_str("r"); + + be_add_keypair(iddict, "id", idnode); + be_add_keypair(dict, "r", iddict); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} + + + +/************************ Parsing Messages ********************* + * + */ + +be_node *beMsgGetDictNode(be_node *node, const char *key) +{ + /* make sure its a dictionary */ + if (node->type != BE_DICT) + { + return NULL; + } + + /* get dictionary entry 'y' */ + int i; + for(i = 0; node->val.d[i].val; i++) + { + if (0 == strcmp(key, node->val.d[i].key)) + { + return node->val.d[i].val; + } + } + return NULL; +} + + + +int beMsgMatchString(be_node *n, const char *str, int len) +{ + if (n->type != BE_STR) + { + return 0; + } + if (len != be_str_len(n)) + { + return 0; + } + + int i; + for(i = 0; i < len; i++) + { + if (n->val.s[i] != str[i]) + return 0; + } + return 1; +} + + +uint32_t beMsgGetY(be_node *n) +{ + be_node *val = beMsgGetDictNode(n, "y"); + + if(val == NULL) + return BE_Y_UNKNOWN ; + + if (val->type != BE_STR) + { + return BE_Y_UNKNOWN; + } + + if (val->val.s[0] == 'q') + { + return BE_Y_Q; + } + else if (val->val.s[0] == 'r') + { + return BE_Y_R; + } + + return BE_Y_UNKNOWN; +} + + + +uint32_t beMsgType(be_node *n) +{ + /* check for + * y: q or r + */ + uint32_t beY = beMsgGetY(n); + +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() beY: " << beY << std::endl; +#endif + + if (beY == BE_Y_UNKNOWN) + { +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() UNKNOWN MSG TYPE" << std::endl; +#endif + + return BITDHT_MSG_TYPE_UNKNOWN; + } + + if (beY == BE_Y_Q) /* query */ + { +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() QUERY MSG TYPE" << std::endl; +#endif + be_node *query = beMsgGetDictNode(n, "q"); + + if(query == NULL) + return BITDHT_MSG_TYPE_UNKNOWN; + + if (beMsgMatchString(query, "ping", 4)) + { +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() QUERY:ping MSG TYPE" << std::endl; +#endif + return BITDHT_MSG_TYPE_PING; + } + else if (beMsgMatchString(query, "find_node", 9)) + { +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() QUERY:find_node MSG TYPE" << std::endl; +#endif + return BITDHT_MSG_TYPE_FIND_NODE; + } + else if (beMsgMatchString(query, "get_peers", 9)) + { +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() QUERY:get_peers MSG TYPE" << std::endl; +#endif + return BITDHT_MSG_TYPE_GET_HASH; + } + else if (beMsgMatchString(query, "announce_peer", 13)) + { +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() QUERY:announce_peer MSG TYPE" << std::endl; +#endif + return BITDHT_MSG_TYPE_POST_HASH; + } + else if (beMsgMatchString(query, "connect", 7)) + { +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() QUERY:connect MSG TYPE" << std::endl; +#endif + return BITDHT_MSG_TYPE_CONNECT; + } +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() QUERY:UNKNOWN MSG TYPE, dumping dict" << std::endl; + /* dump answer */ + be_dump(n); +#endif + return BITDHT_MSG_TYPE_UNKNOWN; + } + + if (beY != BE_Y_R) + { +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() UNKNOWN2 MSG TYPE" << std::endl; +#endif + return BITDHT_MSG_TYPE_UNKNOWN; + } + +#ifdef DEBUG_MSG_TYPE + std::cerr << "bsMsgType() REPLY MSG TYPE" << std::endl; +#endif + + /* otherwise a reply or - invalid + pong {"id":"mnopqrstuvwxyz123456"} + reply_neigh { "id":"0123456789abcdefghij", "nodes": "def456..."}} + reply_hash { "id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}} + reply_near { "id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."} + */ + + be_node *reply = beMsgGetDictNode(n, "r"); + if (!reply) + { + return BITDHT_MSG_TYPE_UNKNOWN; + } + + be_node *id = beMsgGetDictNode(reply, "id"); + be_node *token = beMsgGetDictNode(reply, "token"); + be_node *values = beMsgGetDictNode(reply, "values"); + be_node *nodes = beMsgGetDictNode(reply, "nodes"); + + if (!id) + { + return BITDHT_MSG_TYPE_UNKNOWN; + } + + if (token && values) + { + /* reply hash */ + return BITDHT_MSG_TYPE_REPLY_HASH; + } + else if (token && nodes) + { + /* reply near */ + return BITDHT_MSG_TYPE_REPLY_NEAR; + } + else if (nodes) + { + /* reply neigh */ + return BITDHT_MSG_TYPE_REPLY_NODE; + } + else + { + /* pong */ + return BITDHT_MSG_TYPE_PONG; + } + /* TODO reply_post */ + //return BITDHT_MSG_TYPE_REPLY_POST; + /* can't get here! */ + return BITDHT_MSG_TYPE_UNKNOWN; +} + +/* extract specific types here */ + +int beMsgGetToken(be_node *n, bdToken &token) +{ + if (n->type != BE_STR) + { + return 0; + } + int len = be_str_len(n); + + if(len > BITDHT_TOKEN_MAX_LEN) + return 0 ; + + for(int i = 0; i < len; i++) + { + token.data[i] = n->val.s[i]; + } + token.len = len; + return 1; +} + +int beMsgGetNodeId(be_node *n, bdNodeId &nodeId) +{ + if (n->type != BE_STR) + { + return 0; + } + int len = be_str_len(n); + if (len != BITDHT_KEY_LEN) + { + return 0; + } + for(int i = 0; i < len; i++) + { + nodeId.data[i] = n->val.s[i]; + } + return 1; +} + +be_node *makeCompactNodeIdString(std::list &nodes) +{ + int len = BITDHT_COMPACTNODEID_LEN * nodes.size(); + std::string cni; + std::list::iterator it; + for(it = nodes.begin(); it != nodes.end(); it++) + { + cni += encodeCompactNodeId(&(*it)); + } + + + be_node *cninode = be_create_str_wlen((char *) cni.c_str(), len); + return cninode; +} + +be_node *makeCompactPeerIds(std::list &values) +{ + be_node *valuesnode = be_create_list(); + std::list::iterator it; + for(it = values.begin(); it != values.end(); it++) + { + be_node *val1 = be_create_str_wlen((char *) it->c_str(), it->length()); + be_add_list(valuesnode, val1); + } + return valuesnode; +} + + +int beMsgGetListBdIds(be_node *n, std::list &nodes) +{ + /* extract the string pointer, and size */ + /* split into parts */ + + if (n->type != BE_STR) + { + return 0; + } + + int len = be_str_len(n); + int count = len / BITDHT_COMPACTNODEID_LEN; + for(int i = 0; i < count; i++) + { + bdId id; + if (decodeCompactNodeId(&id, &(n->val.s[i*BITDHT_COMPACTNODEID_LEN]), BITDHT_COMPACTNODEID_LEN)) + { + nodes.push_back(id); + } + } + return 1; +} + +int beMsgGetBdId(be_node *n, bdId &id) +{ + /* extract the string pointer, and size */ + /* split into parts */ + + if (n->type != BE_STR) + { + return 0; + } + + int len = be_str_len(n); + if (len < BITDHT_COMPACTNODEID_LEN) + { + return 0; + } + if (decodeCompactNodeId(&id, n->val.s, BITDHT_COMPACTNODEID_LEN)) + { + return 1; + } + return 0; +} + +std::string encodeCompactNodeId(bdId *id) +{ + std::string enc; + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + enc += id->id.data[i]; + } + /* convert ip address (already in network order) */ + enc += encodeCompactPeerId(&(id->addr)); + return enc; +} + +int decodeCompactNodeId(bdId *id, char *enc, int len) +{ + if (len < BITDHT_COMPACTNODEID_LEN) + { + return 0; + } + + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + id->id.data[i] = enc[i]; + } + + char *ipenc = &(enc[BITDHT_COMPACTNODEID_LEN - BITDHT_COMPACTPEERID_LEN]); + if (!decodeCompactPeerId(&(id->addr), ipenc, BITDHT_COMPACTPEERID_LEN)) + { + return 0; + } + + return 1; +} + +std::string encodeCompactPeerId(struct sockaddr_in *addr) +{ + std::string encstr; + char enc[BITDHT_COMPACTPEERID_LEN]; + uint32_t *ip = (uint32_t *) (enc); + uint16_t *port = (uint16_t *) (&enc[4]); + (*ip) = addr->sin_addr.s_addr; + (*port) = addr->sin_port; + + encstr.append(enc, BITDHT_COMPACTPEERID_LEN); + return encstr; +} + +int decodeCompactPeerId(struct sockaddr_in *addr, char *enc, int len) +{ + if (len < BITDHT_COMPACTPEERID_LEN) + return 0; + + memset(addr, 0, sizeof(struct sockaddr_in)); + + uint32_t *ip = (uint32_t *) (enc); + uint16_t *port = (uint16_t *) (&enc[4]); + addr->sin_addr.s_addr = (*ip); + addr->sin_port = (*port); + addr->sin_family = AF_INET; + + return 1; +} + + +int beMsgGetListStrings(be_node *n, std::list &values) +{ + if (n->type != BE_LIST) + { + return 0; + } + for(int i = 0; n->val.l[i] != NULL; i++) + { + be_node *val = n->val.l[i]; + + if (val == NULL || val->type != BE_STR) + return 0; + + int len = be_str_len(val); + std::string str; + str.append(val->val.s, len); + values.push_back(str); + } + return 1; +} + + +int beMsgGetUInt32(be_node *n, uint32_t *port) +{ + if (n->type != BE_INT) + { + return 0; + } + *port = n->val.i; + return 1; +} + + + + + + + +/******************************************************************************************************************** + * CONNECTION EXTENSIONS + * + */ + + /* +ping Query = {"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}} +bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe + */ + + /* +Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}} +bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re + */ + + /* +find_node Query = {"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}} +bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe + */ + +#if 0 +int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, + char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_find_node_msg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *iddict = be_create_dict(); + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + be_node *targetnode = be_create_str_wlen((char *) target->data, BITDHT_KEY_LEN); + + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *yqrnode = be_create_str("q"); + be_node *findnode = be_create_str("find_node"); + + be_add_keypair(iddict, "id", idnode); + be_add_keypair(iddict, "target", targetnode); + be_add_keypair(dict, "a", iddict); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "q", findnode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} +#endif + +/**** + * Thinking about the format of this message. + * id: ownId is stanard in all other messages, so should keep the same!. + * src: + * target: + * mode: d,p or r + * + * A -> B -> C + * direct: A ------> B + * ---> id:A src:A target:B mode:d + * <--- id:B src:A target:B mode:d a:OK + * + * proxy: A ------> B -------> C + * A->B id:A src:A target:C mode:p q + * + * a) + * B->A id:B src:A target:C mode:p r:NOK + * + * b) + * B->C id:B src:A target:C mode:p q + * C->B id:C src:A target:C mode:p r:NOK + * B->A id:B src:A target:C mode:p r:NOK + * + * c) + * B->C id:B src:A target:C mode:p q + * C->B id:C src:A target:C mode:p r:OK + * B->A id:B src:A target:C mode:p r:OK + * connect happens. + * Dropped packets will affect this! + * + * + * REQUIRED BITS FOR A MESSAGE + * 1) DIRECT + * -> REQUEST, ownId, targetId, transId, mode. + * -> RESPONSE, ownId, targetId, transId, mode, answer. + * + * 2) PROXY + */ + + +int bitdht_connect_genmsg(bdToken *tid, bdNodeId *id, int msgtype, bdId *src, bdId *dest, int mode, int status, char *msg, int avail) +{ +#ifdef DEBUG_MSGS + fprintf(stderr, "bitdht_connect_genmsg()\n"); +#endif + + be_node *dict = be_create_dict(); + + be_node *iddict = be_create_dict(); + + be_node *idnode = be_create_str_wlen((char *) id->data, BITDHT_KEY_LEN); + + std::string srcEnc = encodeCompactNodeId(src); + std::string destEnc = encodeCompactNodeId(dest); + + be_node *srcnode = be_create_str_wlen(srcEnc.c_str(), BITDHT_COMPACTNODEID_LEN); + be_node *destnode = be_create_str_wlen(destEnc.c_str(), BITDHT_COMPACTNODEID_LEN); + be_node *typenode = be_create_int(msgtype); + be_node *statusnode = be_create_int(status); + be_node *modenode = be_create_int(mode); + + be_node *tidnode = be_create_str_wlen((char *) tid->data, tid->len); + be_node *yqrnode = be_create_str("q"); + be_node *cmdnode = be_create_str("connect"); + +#if 0 + be_node *modenode = NULL; + switch(mode) + { + case BITDHT_CONNECT_MODE_DIRECT: + modenode = be_create_str("d"); + break; + case BITDHT_CONNECT_MODE_PROXY: + modenode = be_create_str("p"); + break; + case BITDHT_CONNECT_MODE_RELAY: + modenode = be_create_str("r"); + break; + default: + modenode = be_create_str("u"); + break; + } +#endif + + be_add_keypair(iddict, "id", idnode); + be_add_keypair(iddict, "src", srcnode); + be_add_keypair(iddict, "dest", destnode); + be_add_keypair(iddict, "mode", modenode); + be_add_keypair(iddict, "status", statusnode); + be_add_keypair(iddict, "type", typenode); + + be_add_keypair(dict, "a", iddict); + + be_add_keypair(dict, "t", tidnode); + be_add_keypair(dict, "y", yqrnode); + be_add_keypair(dict, "q", cmdnode); + +#ifdef DEBUG_MSG_DUMP + /* dump answer */ + be_dump(dict); +#endif + + int blen = be_encode(dict, msg, avail); + be_free(dict); + + return blen; +} + + diff --git a/libbitdht/src/bitdht/bdmsgs.h b/libbitdht/src/bitdht/bdmsgs.h new file mode 100644 index 000000000..738f0075d --- /dev/null +++ b/libbitdht/src/bitdht/bdmsgs.h @@ -0,0 +1,130 @@ +#ifndef BITDHT_MSGS_H +#define BITDHT_MSGS_H + +/* + * bitdht/bdmsgs.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include +#include +#include +#include "bitdht/bencode.h" +#include "bitdht/bdobj.h" +#include "bitdht/bdpeer.h" + +#define BITDHT_MSG_TYPE_UNKNOWN 0 +#define BITDHT_MSG_TYPE_PING 1 +#define BITDHT_MSG_TYPE_PONG 2 +#define BITDHT_MSG_TYPE_FIND_NODE 3 +#define BITDHT_MSG_TYPE_REPLY_NODE 4 +#define BITDHT_MSG_TYPE_GET_HASH 5 +#define BITDHT_MSG_TYPE_REPLY_HASH 6 +#define BITDHT_MSG_TYPE_REPLY_NEAR 7 +#define BITDHT_MSG_TYPE_POST_HASH 8 +#define BITDHT_MSG_TYPE_REPLY_POST 9 + + + +// THESE ARE EXTENSIONS +#define BITDHT_MSG_TYPE_CONNECT 20 + +// CONNECTIONS. +#define BITDHT_MSG_TYPE_CONNECT_REQUEST 101 +#define BITDHT_MSG_TYPE_CONNECT_REPLY 102 +#define BITDHT_MSG_TYPE_CONNECT_START 103 +#define BITDHT_MSG_TYPE_CONNECT_ACK 104 + +// FANCY HASHES. + + +#define BITDHT_COMPACTNODEID_LEN 26 +#define BITDHT_COMPACTPEERID_LEN 6 + +#define BE_Y_UNKNOWN 0 +#define BE_Y_R 1 +#define BE_Y_Q 2 + + +/****** Known BD Version Strings ******/ + +#define BITDHT_VID_RS1 1 +#define BITDHT_VID_UT 2 + + +int bitdht_create_ping_msg(bdToken *tid, bdNodeId *id, char *msg, int avail); +int bitdht_response_ping_msg(bdToken *tid, bdNodeId *id, bdToken *vid, char *msg, int avail); +int bitdht_find_node_msg(bdToken *tid, bdNodeId *id, bdNodeId *target, char *msg, int avail); +int bitdht_resp_node_msg(bdToken *tid, bdNodeId *id, std::list &nodes, + char *msg, int avail); +int bitdht_get_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, + char *msg, int avail); +int bitdht_peers_reply_hash_msg(bdToken *tid, bdNodeId *id, + bdToken *token, std::list &values, + char *msg, int avail); +int bitdht_peers_reply_closest_msg(bdToken *tid, bdNodeId *id, + bdToken *token, std::list &nodes, + char *msg, int avail); +int bitdht_announce_peers_msg(bdToken *tid, bdNodeId *id, bdNodeId *info_hash, + uint32_t port, bdToken *token, char *msg, int avail); +int bitdht_reply_announce_msg(bdToken *tid, bdNodeId *id, + char *msg, int avail); + + +// Extensions. +int bitdht_connect_genmsg(bdToken *tid, bdNodeId *id, int msgtype, bdId *src, bdId *dest, int mode, int status, char *msg, int avail); + + +//int response_peers_message() +//int response_closestnodes_message() + +be_node *beMsgGetDictNode(be_node *node, const char *key); +int beMsgMatchString(be_node *n, const char *str, int len); +uint32_t beMsgGetY(be_node *n); +uint32_t beMsgType(be_node *n); + + +uint32_t convertBdVersionToVID(bdVersion *version); + +be_node *makeCompactPeerIds(std::list &values); +be_node *makeCompactNodeIdString(std::list &nodes); + +int beMsgGetToken(be_node *n, bdToken &token); +int beMsgGetNodeId(be_node *n, bdNodeId &nodeId); +int beMsgGetBdId(be_node *n, bdId &id); +int beMsgGetListBdIds(be_node *n, std::list &nodes); + +int beMsgGetListStrings(be_node *n, std::list &values); +int beMsgGetUInt32(be_node *n, uint32_t *port); + +/* Low Level conversion functions */ +int decodeCompactPeerId(struct sockaddr_in *addr, char *enc, int len); +std::string encodeCompactPeerId(struct sockaddr_in *addr); + +int decodeCompactNodeId(bdId *id, char *enc, int len); +std::string encodeCompactNodeId(bdId *id); + + + +#endif diff --git a/libbitdht/src/bitdht/bdnode.cc b/libbitdht/src/bitdht/bdnode.cc new file mode 100644 index 000000000..d506fb71c --- /dev/null +++ b/libbitdht/src/bitdht/bdnode.cc @@ -0,0 +1,2064 @@ +/* + * bitdht/bdnode.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bitdht/bdnode.h" + +#include "bitdht/bencode.h" +#include "bitdht/bdmsgs.h" + +#include "bitdht/bdquerymgr.h" +#include "bitdht/bdfilter.h" + +#include "util/bdnet.h" +#include "util/bdrandom.h" + + +#include +#include + +#include +#include +#include + + +#define BITDHT_QUERY_START_PEERS 10 +#define BITDHT_QUERY_NEIGHBOUR_PEERS 8 +#define BITDHT_MAX_REMOTE_QUERY_AGE 10 + +/**** + * #define USE_HISTORY 1 + * + * #define DEBUG_NODE_MULTIPEER 1 + * #define DEBUG_NODE_PARSE 1 + + * #define DEBUG_NODE_MSGS 1 + * #define DEBUG_NODE_ACTIONS 1 + + * #define DEBUG_NODE_MSGIN 1 + * #define DEBUG_NODE_MSGOUT 1 + ***/ + +//#define DEBUG_NODE_MSGS 1 + + +bdNode::bdNode(bdNodeId *ownId, std::string dhtVersion, std::string bootfile, bdDhtFunctions *fns) + :mOwnId(*ownId), mNodeSpace(ownId, fns), mStore(bootfile, fns), mDhtVersion(dhtVersion), mFns(fns), + mQueryMgr(NULL), mConnMgr(NULL), mFilterPeers(NULL) +{ + + init(); /* (uses this pointers) stuff it - do it here! */ +} + +void bdNode::init() +{ + mQueryMgr = new bdQueryManager(&mNodeSpace, mFns, this); + mConnMgr = new bdConnectManager(&mOwnId, &mNodeSpace, mQueryMgr, mFns, this); + + std::list emptyList; + mFilterPeers = new bdFilter(&mOwnId, emptyList, BITDHT_FILTER_REASON_OWNID, mFns); + + setNodeOptions(BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT); + +} + +#define ATTACH_NUMBER 5 +void bdNode::setNodeOptions(uint32_t optFlags) +{ + mNodeOptionFlags = optFlags; + if (optFlags & BITDHT_OPTIONS_MAINTAIN_UNSTABLE_PORT) + { + mNodeSpace.setAttachedFlag(BITDHT_PEER_STATUS_DHT_ENGINE, ATTACH_NUMBER); + } + else + { + mNodeSpace.setAttachedFlag(BITDHT_PEER_STATUS_DHT_ENGINE, 0); + } +} + + +void bdNode::getOwnId(bdNodeId *id) +{ + *id = mOwnId; +} + +/***** Startup / Shutdown ******/ +void bdNode::restartNode() +{ + mAccount.resetStats(); + + mStore.reloadFromStore(); + + /* setup */ + bdPeer peer; + while(mStore.getPeer(&peer)) + { + addPotentialPeer(&(peer.mPeerId), NULL); + } +} + + +void bdNode::shutdownNode() +{ + /* clear the queries */ + mQueryMgr->shutdownQueries(); + mConnMgr->shutdownConnections(); + + mRemoteQueries.clear(); + + /* clear the space */ + mNodeSpace.clear(); + mHashSpace.clear(); + + /* clear other stuff */ + mPotentialPeers.clear(); + mStore.clear(); + + /* clean up any outgoing messages */ + while(mOutgoingMsgs.size() > 0) + { + bdNodeNetMsg *msg = mOutgoingMsgs.front(); + mOutgoingMsgs.pop_front(); + + /* cleanup message */ + delete msg; + } +} + + +/* Crappy initial store... use bdspace as answer */ +void bdNode::updateStore() +{ + mStore.writeStore(); +} + +void bdNode::printState() +{ + std::cerr << "bdNode::printState() for Peer: "; + mFns->bdPrintNodeId(std::cerr, &mOwnId); + std::cerr << std::endl; + + mNodeSpace.printDHT(); + + mQueryMgr->printQueries(); + mConnMgr->printConnections(); + +#ifdef USE_HISTORY + mHistory.printMsgs(); +#endif + + mAccount.printStats(std::cerr); +} + +void bdNode::iterationOff() +{ + /* clean up any incoming messages */ + while(mIncomingMsgs.size() > 0) + { + bdNodeNetMsg *msg = mIncomingMsgs.front(); + mIncomingMsgs.pop_front(); + + /* cleanup message */ + delete msg; + } +} + +void bdNode::iteration() +{ +#ifdef DEBUG_NODE_MULTIPEER + std::cerr << "bdNode::iteration() of Peer: "; + mFns->bdPrintNodeId(std::cerr, &mOwnId); + std::cerr << std::endl; +#endif + /* iterate through queries */ + + bdId id; + bdNodeId targetNodeId; + std::list::iterator it; + std::list::iterator bit; + + /* process incoming msgs */ + while(mIncomingMsgs.size() > 0) + { + bdNodeNetMsg *msg = mIncomingMsgs.front(); + mIncomingMsgs.pop_front(); + + recvPkt(msg->data, msg->mSize, msg->addr); + + /* cleanup message */ + delete msg; + } + + + /* assume that this is called once per second... limit the messages + * in theory, a query can generate up to 10 peers (which will all require a ping!). + * we want to handle all the pings we can... so we don't hold up the process. + * but we also want enough queries to keep things moving. + * so allow up to 90% of messages to be pings. + * + * ignore responses to other peers... as the number is very small generally + */ + +#define BDNODE_MESSAGE_RATE_HIGH 1 +#define BDNODE_MESSAGE_RATE_MED 2 +#define BDNODE_MESSAGE_RATE_LOW 3 +#define BDNODE_MESSAGE_RATE_TRICKLE 4 + +#define BDNODE_HIGH_MSG_RATE 100 +#define BDNODE_MED_MSG_RATE 50 +#define BDNODE_LOW_MSG_RATE 20 +#define BDNODE_TRICKLE_MSG_RATE 5 + + int maxMsgs = BDNODE_MED_MSG_RATE; + int mAllowedMsgRate = BDNODE_MESSAGE_RATE_MED; + + switch(mAllowedMsgRate) + { + case BDNODE_MESSAGE_RATE_HIGH: + maxMsgs = BDNODE_HIGH_MSG_RATE; + break; + + case BDNODE_MESSAGE_RATE_MED: + maxMsgs = BDNODE_MED_MSG_RATE; + break; + + case BDNODE_MESSAGE_RATE_LOW: + maxMsgs = BDNODE_LOW_MSG_RATE; + break; + + case BDNODE_MESSAGE_RATE_TRICKLE: + maxMsgs = BDNODE_TRICKLE_MSG_RATE; + break; + + default: + break; + + } + + + + int allowedPings = 0.9 * maxMsgs; + int sentMsgs = 0; + int sentPings = 0; + + while((mPotentialPeers.size() > 0) && (sentMsgs < allowedPings)) + { + /* check history ... is we have pinged them already... + * then simulate / pretend we have received a pong, + * and don't bother sending another ping. + */ + + bdId pid = mPotentialPeers.front(); + mPotentialPeers.pop_front(); + + + /* don't send too many queries ... check history first */ +#ifdef USE_HISTORY + if (mHistory.validPeer(&pid)) + { + /* just add as peer */ + +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::iteration() Pinging Known Potential Peer : "; + mFns->bdPrintId(std::cerr, &pid); + std::cerr << std::endl; +#endif + + } +#endif + + /**** TEMP ****/ + + { + send_ping(&pid); + + sentMsgs++; + sentPings++; + +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::iteration() Pinging Potential Peer : "; + mFns->bdPrintId(std::cerr, &pid); + std::cerr << std::endl; +#endif + + } + + } + + /* allow each query to send up to one query... until maxMsgs has been reached */ + int sentQueries = mQueryMgr->iterateQueries(maxMsgs-sentMsgs); + sentMsgs += sentQueries; + +#ifdef DEBUG_NODE_ACTIONS + std::cerr << "bdNode::iteration() maxMsgs: " << maxMsgs << " sentPings: " << sentPings; + std::cerr << " / " << allowedPings; + std::cerr << " sentQueries: " << sentQueries; + std::cerr << std::endl; +#endif + + /* process remote query too */ + processRemoteQuery(); + + std::list peerIds; + std::list::iterator oit; + mNodeSpace.scanOutOfDatePeers(peerIds); + + for(oit = peerIds.begin(); oit != peerIds.end(); oit++) + { + send_ping(&(*oit)); + mAccount.incCounter(BDACCOUNT_MSG_OUTOFDATEPING, true); + +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::iteration() Pinging Out-Of-Date Peer: "; + mFns->bdPrintId(std::cerr, *oit); + std::cerr << std::endl; +#endif + } + + // Handle Connection loops. + mConnMgr->tickConnections(); + + mAccount.doStats(); +} + + + +/*************************************************************************************** + *************************************************************************************** + ***************************************************************************************/ + +void bdNode::send_ping(bdId *id) +{ + bdToken transId; + genNewTransId(&transId); + //registerOutgoingMsg(&id, &transId, BITDHT_MSG_TYPE_PING); + + msgout_ping(id, &transId); +} + + +void bdNode::send_query(bdId *id, bdNodeId *targetNodeId) +{ + /* push out query */ + bdToken transId; + genNewTransId(&transId); + //registerOutgoingMsg(&id, &transId, BITDHT_MSG_TYPE_FIND_NODE); + + msgout_find_node(id, &transId, targetNodeId); + +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::send_query() Find Node Req for : "; + mFns->bdPrintId(std::cerr, &id); + std::cerr << " searching for : "; + mFns->bdPrintNodeId(std::cerr, &targetNodeId); + std::cerr << std::endl; +#endif +} + + +void bdNode::send_connect_msg(bdId *id, int msgtype, bdId *srcAddr, bdId *destAddr, int mode, int status) +{ + /* push out query */ + bdToken transId; + genNewTransId(&transId); + //registerOutgoingMsg(&id, &transId, BITDHT_MSG_TYPE_FIND_NODE); + + msgout_connect_genmsg(id, &transId, msgtype, srcAddr, destAddr, mode, status); + +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::send_connect_msg() to: "; + mFns->bdPrintId(std::cerr, &id); + std::cerr << std::endl; +#endif +} + + + + + +void bdNode::checkPotentialPeer(bdId *id, bdId *src) +{ + bool isWorthyPeer = mQueryMgr->checkPotentialPeer(id, src); + + if (isWorthyPeer) + { + addPotentialPeer(id, src); + + } + + if (src) // src can be NULL! + { + mConnMgr->addPotentialConnectionProxy(src, id); // CAUTION: Order switched! + } + +} + + +void bdNode::addPotentialPeer(bdId *id, bdId *src) +{ + mPotentialPeers.push_back(*id); +} + + + + // virtual so manager can do callback. + // peer flags defined in bdiface.h +void bdNode::addPeer(const bdId *id, uint32_t peerflags) +{ + +#ifdef DEBUG_NODE_ACTIONS + fprintf(stderr, "bdNode::addPeer("); + mFns->bdPrintId(std::cerr, id); + fprintf(stderr, ")\n"); +#endif + + /* first check the filters */ + if (mFilterPeers->checkPeer(id, peerflags)) + { + std::cerr << "bdNode::addPeer("; + mFns->bdPrintId(std::cerr, id); + std::cerr << ", " << std::hex << peerflags << std::dec; + std::cerr << ") FAILED the BAD PEER FILTER!!!! DISCARDING MSG"; + std::cerr << std::endl; + + std::list filteredIPs; + mFilterPeers->filteredIPs(filteredIPs); + mStore.filterIpList(filteredIPs); + + return; + } + + mQueryMgr->addPeer(id, peerflags); + mNodeSpace.add_peer(id, peerflags); + + bdPeer peer; + peer.mPeerId = *id; + peer.mPeerFlags = peerflags; + peer.mLastRecvTime = time(NULL); + mStore.addStore(&peer); + + // Finally we pass to connections for them to use. + mConnMgr->updatePotentialConnectionProxy(id, peerflags); + + +//#define DISPLAY_BITDHTNODES 1 +#ifdef DISPLAY_BITDHTNODES + /* TEMP to extract IDS for BloomFilter */ + if (peerflags & BITDHT_PEER_STATUS_DHT_ENGINE) + { + std::cerr << "bdNode::addPeer() FOUND BITDHT PEER"; + std::cerr << std::endl; + mFns->bdPrintNodeId(std::cerr, &(id->id)); + std::cerr << std::endl; + } +#endif +} + +/************************************ Process Remote Query *************************/ +void bdNode::processRemoteQuery() +{ + bool processed = false; + time_t oldTS = time(NULL) - BITDHT_MAX_REMOTE_QUERY_AGE; + while(!processed) + { + /* extra exit clause */ + if (mRemoteQueries.size() < 1) return; + + bdRemoteQuery &query = mRemoteQueries.front(); + + /* discard older ones (stops queue getting overloaded) */ + if (query.mQueryTS > oldTS) + { + /* recent enough to process! */ + processed = true; + + switch(query.mQueryType) + { + case BD_QUERY_NEIGHBOURS: + { + /* search bdSpace for neighbours */ + //std::list excludeList; + + std::list nearList; + std::multimap nearest; + std::multimap::iterator it; + + //mNodeSpace.find_nearest_nodes(&(query.mQuery), BITDHT_QUERY_NEIGHBOUR_PEERS, excludeList, nearest, 0); + + mNodeSpace.find_nearest_nodes(&(query.mQuery), BITDHT_QUERY_NEIGHBOUR_PEERS, nearest); + + for(it = nearest.begin(); it != nearest.end(); it++) + { + nearList.push_back(it->second); + } + msgout_reply_find_node(&(query.mId), &(query.mTransId), nearList); +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::processRemoteQuery() Reply to Find Node: "; + mFns->bdPrintId(std::cerr, &(query.mId)); + std::cerr << " searching for : "; + mFns->bdPrintNodeId(std::cerr, &(query.mQuery)); + std::cerr << ", found " << nearest.size() << " nodes "; + std::cerr << std::endl; +#endif + + break; + } + case BD_QUERY_HASH: + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::processRemoteQuery() Reply to Query Node: "; + mFns->bdPrintId(std::cerr, &(query.mId)); + std::cerr << " TODO"; + std::cerr << std::endl; +#endif + + /* TODO */ + break; + } + default: + { + /* drop */ + /* unprocess! */ + processed = false; + break; + } + } + + + + } + else + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::processRemoteQuery() Query Too Old: Discarding: "; + mFns->bdPrintId(std::cerr, &(query.mId)); + std::cerr << std::endl; +#endif + } + + + mRemoteQueries.pop_front(); + } +} + + + + + +/************************************ Message Buffering ****************************/ + + /* interaction with outside world */ +int bdNode::outgoingMsg(struct sockaddr_in *addr, char *msg, int *len) +{ + if (mOutgoingMsgs.size() > 0) + { + bdNodeNetMsg *bdmsg = mOutgoingMsgs.front(); + //bdmsg->print(std::cerr); + mOutgoingMsgs.pop_front(); + //bdmsg->print(std::cerr); + + /* truncate if necessary */ + if (bdmsg->mSize < *len) + { + //std::cerr << "bdNode::outgoingMsg space(" << *len << ") msgsize(" << bdmsg->mSize << ")"; + //std::cerr << std::endl; + *len = bdmsg->mSize; + } + else + { + //std::cerr << "bdNode::outgoingMsg space(" << *len << ") small - trunc from: " + //<< bdmsg->mSize; + //std::cerr << std::endl; + } + + + memcpy(msg, bdmsg->data, *len); + *addr = bdmsg->addr; + + //bdmsg->print(std::cerr); + + delete bdmsg; + return 1; + } + return 0; +} + +void bdNode::incomingMsg(struct sockaddr_in *addr, char *msg, int len) +{ + /* check against the filter */ + if (mFilterPeers->addrOkay(addr)) + { + bdNodeNetMsg *bdmsg = new bdNodeNetMsg(msg, len, addr); + mIncomingMsgs.push_back(bdmsg); + } + else + { + std::cerr << "bdNode::incomingMsg() Incoming Packet Filtered"; + std::cerr << std::endl; + } +} + +/************************************ Message Handling *****************************/ + +/* Outgoing Messages */ + +void bdNode::msgout_ping(bdId *id, bdToken *transId) +{ +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_ping() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << std::endl; +#endif + + registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_PING); + + + /* create string */ + char msg[10240]; + int avail = 10240; + + int blen = bitdht_create_ping_msg(transId, &(mOwnId), msg, avail-1); + sendPkt(msg, blen, id->addr); + + mAccount.incCounter(BDACCOUNT_MSG_PING, true); + +} + + +void bdNode::msgout_pong(bdId *id, bdToken *transId) +{ +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_pong() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " Version: " << version; + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << std::endl; +#endif + + registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_PONG); + + /* generate message, send to udp */ + bdToken vid; + uint32_t vlen = BITDHT_TOKEN_MAX_LEN; + if (mDhtVersion.size() < vlen) + { + vlen = mDhtVersion.size(); + } + memcpy(vid.data, mDhtVersion.c_str(), vlen); + vid.len = vlen; + + char msg[10240]; + int avail = 10240; + + int blen = bitdht_response_ping_msg(transId, &(mOwnId), &vid, msg, avail-1); + + sendPkt(msg, blen, id->addr); + + mAccount.incCounter(BDACCOUNT_MSG_PONG, true); + +} + + +void bdNode::msgout_find_node(bdId *id, bdToken *transId, bdNodeId *query) +{ +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_find_node() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Query: "; + mFns->bdPrintNodeId(std::cerr, query); + std::cerr << std::endl; +#endif + + registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_FIND_NODE); + + + + char msg[10240]; + int avail = 10240; + + int blen = bitdht_find_node_msg(transId, &(mOwnId), query, msg, avail-1); + + sendPkt(msg, blen, id->addr); + + mAccount.incCounter(BDACCOUNT_MSG_QUERYNODE, true); + +} + +void bdNode::msgout_reply_find_node(bdId *id, bdToken *transId, std::list &peers) +{ + char msg[10240]; + int avail = 10240; + + registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_NODE); + + mAccount.incCounter(BDACCOUNT_MSG_REPLYFINDNODE, true); + + int blen = bitdht_resp_node_msg(transId, &(mOwnId), peers, msg, avail-1); + + sendPkt(msg, blen, id->addr); + +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_reply_find_node() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Peers:"; + std::list::iterator it; + for(it = peers.begin(); it != peers.end(); it++) + { + std::cerr << " "; + mFns->bdPrintId(std::cerr, &(*it)); + } + std::cerr << std::endl; +#endif +} + +/***************** + * SECOND HALF + * + *****/ + +void bdNode::msgout_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash) +{ +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_get_hash() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " InfoHash: "; + mFns->bdPrintNodeId(std::cerr, info_hash); + std::cerr << std::endl; +#endif + + char msg[10240]; + int avail = 10240; + + registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_GET_HASH); + + + int blen = bitdht_get_peers_msg(transId, &(mOwnId), info_hash, msg, avail-1); + + sendPkt(msg, blen, id->addr); + + mAccount.incCounter(BDACCOUNT_MSG_QUERYHASH, true); + +} + +void bdNode::msgout_reply_hash(bdId *id, bdToken *transId, bdToken *token, std::list &values) +{ +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_reply_hash() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Token: "; + bdPrintToken(std::cerr, token); + + std::cerr << " Peers: "; + std::list::iterator it; + for(it = values.begin(); it != values.end(); it++) + { + std::cerr << " "; + bdPrintCompactPeerId(std::cerr, *it); + } + std::cerr << std::endl; +#endif + + char msg[10240]; + int avail = 10240; + + registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_HASH); + + int blen = bitdht_peers_reply_hash_msg(transId, &(mOwnId), token, values, msg, avail-1); + + sendPkt(msg, blen, id->addr); + + mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, true); + +} + +void bdNode::msgout_reply_nearest(bdId *id, bdToken *transId, bdToken *token, std::list &nodes) +{ +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_reply_nearest() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Token: "; + bdPrintToken(std::cerr, token); + std::cerr << " Nodes:"; + + std::list::iterator it; + for(it = nodes.begin(); it != nodes.end(); it++) + { + std::cerr << " "; + mFns->bdPrintId(std::cerr, &(*it)); + } + std::cerr << std::endl; +#endif + + char msg[10240]; + int avail = 10240; + + registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_NEAR); + + + + int blen = bitdht_peers_reply_closest_msg(transId, &(mOwnId), token, nodes, msg, avail-1); + + sendPkt(msg, blen, id->addr); + mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, true); + + +} + +void bdNode::msgout_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash, uint32_t port, bdToken *token) +{ +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_post_hash() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Info_Hash: "; + mFns->bdPrintNodeId(std::cerr, info_hash); + std::cerr << " Port: " << port; + std::cerr << " Token: "; + bdPrintToken(std::cerr, token); + std::cerr << std::endl; +#endif + + char msg[10240]; + int avail = 10240; + + registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_POST_HASH); + + + int blen = bitdht_announce_peers_msg(transId,&(mOwnId),info_hash,port,token,msg,avail-1); + + sendPkt(msg, blen, id->addr); + mAccount.incCounter(BDACCOUNT_MSG_POSTHASH, true); + + +} + +void bdNode::msgout_reply_post(bdId *id, bdToken *transId) +{ +#ifdef DEBUG_NODE_MSGOUT + std::cerr << "bdNode::msgout_reply_post() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << std::endl; +#endif + + /* generate message, send to udp */ + char msg[10240]; + int avail = 10240; + + registerOutgoingMsg(id, transId, BITDHT_MSG_TYPE_REPLY_POST); + + int blen = bitdht_reply_announce_msg(transId, &(mOwnId), msg, avail-1); + + sendPkt(msg, blen, id->addr); + mAccount.incCounter(BDACCOUNT_MSG_REPLYPOSTHASH, true); + +} + + +void bdNode::sendPkt(char *msg, int len, struct sockaddr_in addr) +{ + //fprintf(stderr, "bdNode::sendPkt(%d) to %s:%d\n", + // len, inet_ntoa(addr.sin_addr), htons(addr.sin_port)); + + /* filter outgoing packets */ + if (mFilterPeers->addrOkay(&addr)) + { + bdNodeNetMsg *bdmsg = new bdNodeNetMsg(msg, len, &addr); + //bdmsg->print(std::cerr); + mOutgoingMsgs.push_back(bdmsg); + //bdmsg->print(std::cerr); + } + else + { + std::cerr << "bdNode::sendPkt() Outgoing Packet Filtered"; + std::cerr << std::endl; + } + + return; +} + + +/********************* Incoming Messages *************************/ +/* + * These functions are holding up udp queue -> so quickly + * parse message, and get on with it! + */ + +void bdNode::recvPkt(char *msg, int len, struct sockaddr_in addr) +{ +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() msg[" << len << "] = "; + for(int i = 0; i < len; i++) + { + if ((msg[i] > 31) && (msg[i] < 127)) + { + std::cerr << msg[i]; + } + else + { + std::cerr << "[" << (int) msg[i] << "]"; + } + } + std::cerr << std::endl; +#endif + + /* convert to a be_node */ + be_node *node = be_decoden(msg, len); + if (!node) + { + /* invalid decode */ +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() Failure to decode. Dropping Msg"; + std::cerr << std::endl; + std::cerr << "message length: " << len; + std::cerr << std::endl; + std::cerr << "msg[] = "; + for(int i = 0; i < len; i++) + { + if ((msg[i] > 31) && (msg[i] < 127)) + { + std::cerr << msg[i]; + } + else + { + std::cerr << "[" << (int) msg[i] << "]"; + } + } + std::cerr << std::endl; +#endif + return; + } + + /* find message type */ + uint32_t beType = beMsgType(node); + bool beQuery = (BE_Y_Q == beMsgGetY(node)); + + if (!beType) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() Invalid Message Type. Dropping Msg"; + std::cerr << std::endl; +#endif + /* invalid message */ + be_free(node); + return; + } + + /************************* handle token (all) **************************/ + be_node *be_transId = beMsgGetDictNode(node, "t"); + bdToken transId; + if (be_transId) + { + beMsgGetToken(be_transId, transId); + } + else + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() TransId Failure. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + + /************************* handle data (all) **************************/ + + /* extract common features */ + char dictkey[2] = "r"; + if (beQuery) + { + dictkey[0] = 'a'; + } + + be_node *be_data = beMsgGetDictNode(node, dictkey); + if (!be_data) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() Missing Data Body. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + + /************************** handle id (all) ***************************/ + be_node *be_id = beMsgGetDictNode(be_data, "id"); + bdNodeId id; + if (be_id) + { + beMsgGetNodeId(be_id, id); + } + else + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() Missing Peer Id. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + + /************************ handle version (optional:pong) **************/ + be_node *be_version = NULL; + bdToken versionId; + if (beType == BITDHT_MSG_TYPE_PONG) + { + be_version = beMsgGetDictNode(node, "v"); + if (!be_version) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() NOTE: PONG missing Optional Version."; + std::cerr << std::endl; +#endif + } + } + + if (be_version) + { + beMsgGetToken(be_version, versionId); + } + + /*********** handle target (query) or info_hash (get_hash) ************/ + bdNodeId target_info_hash; + be_node *be_target = NULL; + if (beType == BITDHT_MSG_TYPE_FIND_NODE) + { + be_target = beMsgGetDictNode(be_data, "target"); + if (!be_target) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() Missing Target / Info_Hash. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + } + else if ((beType == BITDHT_MSG_TYPE_GET_HASH) || + (beType == BITDHT_MSG_TYPE_POST_HASH)) + { + be_target = beMsgGetDictNode(be_data, "info_hash"); + if (!be_target) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() Missing Target / Info_Hash. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + } + + if (be_target) + { + beMsgGetNodeId(be_target, target_info_hash); + } + + /*********** handle nodes (reply_query or reply_near) *****************/ + std::list nodes; + be_node *be_nodes = NULL; + if ((beType == BITDHT_MSG_TYPE_REPLY_NODE) || + (beType == BITDHT_MSG_TYPE_REPLY_NEAR)) + { + be_nodes = beMsgGetDictNode(be_data, "nodes"); + if (!be_nodes) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() Missing Nodes. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + } + + if (be_nodes) + { + beMsgGetListBdIds(be_nodes, nodes); + } + + /******************* handle values (reply_hash) ***********************/ + std::list values; + be_node *be_values = NULL; + if (beType == BITDHT_MSG_TYPE_REPLY_HASH) + { + be_values = beMsgGetDictNode(be_data, "values"); + if (!be_values) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() Missing Values. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + } + + if (be_values) + { + beMsgGetListStrings(be_values, values); + } + + /************ handle token (reply_hash, reply_near, post hash) ********/ + bdToken token; + be_node *be_token = NULL; + if ((beType == BITDHT_MSG_TYPE_REPLY_HASH) || + (beType == BITDHT_MSG_TYPE_REPLY_NEAR) || + (beType == BITDHT_MSG_TYPE_POST_HASH)) + { + be_token = beMsgGetDictNode(be_data, "token"); + if (!be_token) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() Missing Token. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + } + + if (be_token) + { + beMsgGetToken(be_transId, transId); + } + + /****************** handle port (post hash) ***************************/ + uint32_t port; + be_node *be_port = NULL; + if (beType == BITDHT_MSG_TYPE_POST_HASH) + { + be_port = beMsgGetDictNode(be_data, "port"); + if (!be_port) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() POST_HASH Missing Port. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + } + + if (be_port) + { + beMsgGetUInt32(be_port, &port); + } + + /****************** handle Connect (lots) ***************************/ + bdId connSrcAddr; + bdId connDestAddr; + uint32_t connMode; + uint32_t connStatus; + uint32_t connType; + + be_node *be_ConnSrcAddr = NULL; + be_node *be_ConnDestAddr = NULL; + be_node *be_ConnMode = NULL; + be_node *be_ConnStatus = NULL; + be_node *be_ConnType = NULL; + if (beType == BITDHT_MSG_TYPE_CONNECT) + { + /* SrcAddr */ + be_ConnSrcAddr = beMsgGetDictNode(be_data, "src"); + if (!be_ConnSrcAddr) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() CONNECT Missing SrcAddr. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + + /* DestAddr */ + be_ConnDestAddr = beMsgGetDictNode(be_data, "dest"); + if (!be_ConnDestAddr) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() CONNECT Missing DestAddr. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + + /* Mode */ + be_ConnMode = beMsgGetDictNode(be_data, "mode"); + if (!be_ConnMode) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() CONNECT Missing Mode. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + + /* Status */ + be_ConnStatus = beMsgGetDictNode(be_data, "status"); + if (!be_ConnStatus) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() CONNECT Missing Status. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + + /* Type */ + be_ConnType = beMsgGetDictNode(be_data, "type"); + if (!be_ConnType) + { +#ifdef DEBUG_NODE_PARSE + std::cerr << "bdNode::recvPkt() CONNECT Missing Type. Dropping Msg"; + std::cerr << std::endl; +#endif + be_free(node); + return; + } + } + + if (be_ConnSrcAddr) + { + beMsgGetBdId(be_ConnSrcAddr, connSrcAddr); + } + + if (be_ConnDestAddr) + { + beMsgGetBdId(be_ConnDestAddr, connDestAddr); + } + + if (be_ConnMode) + { + beMsgGetUInt32(be_ConnMode, &connMode); + } + + if (be_ConnStatus) + { + beMsgGetUInt32(be_ConnStatus, &connStatus); + } + + if (be_ConnType) + { + beMsgGetUInt32(be_ConnType, &connType); + } + + + + /****************** Bits Parsed Ok. Process Msg ***********************/ + /* Construct Source Id */ + bdId srcId(id, addr); + + checkIncomingMsg(&srcId, &transId, beType); + switch(beType) + { + case BITDHT_MSG_TYPE_PING: /* a: id, transId */ + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() Responding to Ping : "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << std::endl; +#endif + msgin_ping(&srcId, &transId); + break; + } + case BITDHT_MSG_TYPE_PONG: /* r: id, transId */ + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() Received Pong from : "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << std::endl; +#endif + if (be_version) + { + msgin_pong(&srcId, &transId, &versionId); + } + else + { + msgin_pong(&srcId, &transId, NULL); + } + + break; + } + case BITDHT_MSG_TYPE_FIND_NODE: /* a: id, transId, target */ + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() Req Find Node from : "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << " Looking for: "; + mFns->bdPrintNodeId(std::cerr, &target_info_hash); + std::cerr << std::endl; +#endif + msgin_find_node(&srcId, &transId, &target_info_hash); + break; + } + case BITDHT_MSG_TYPE_REPLY_NODE: /* r: id, transId, nodes */ + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() Received Reply Node from : "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << std::endl; +#endif + msgin_reply_find_node(&srcId, &transId, nodes); + break; + } + case BITDHT_MSG_TYPE_GET_HASH: /* a: id, transId, info_hash */ + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() Received SearchHash : "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << " for Hash: "; + mFns->bdPrintNodeId(std::cerr, &target_info_hash); + std::cerr << std::endl; +#endif + msgin_get_hash(&srcId, &transId, &target_info_hash); + break; + } + case BITDHT_MSG_TYPE_REPLY_HASH: /* r: id, transId, token, values */ + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() Received Reply Hash : "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << std::endl; +#endif + msgin_reply_hash(&srcId, &transId, &token, values); + break; + } + case BITDHT_MSG_TYPE_REPLY_NEAR: /* r: id, transId, token, nodes */ + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() Received Reply Near : "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << std::endl; +#endif + msgin_reply_nearest(&srcId, &transId, &token, nodes); + break; + } + case BITDHT_MSG_TYPE_POST_HASH: /* a: id, transId, info_hash, port, token */ + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() Post Hash from : "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << " to post: "; + mFns->bdPrintNodeId(std::cerr, &target_info_hash); + std::cerr << " with port: " << port; + std::cerr << std::endl; +#endif + msgin_post_hash(&srcId, &transId, &target_info_hash, port, &token); + break; + } + case BITDHT_MSG_TYPE_REPLY_POST: /* r: id, transId */ + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() Reply Post from: "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << std::endl; +#endif + msgin_reply_post(&srcId, &transId); + break; + } + case BITDHT_MSG_TYPE_CONNECT: /* a: id, src, dest, mode, status, type */ + { +//#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() ConnectMsg from: "; + mFns->bdPrintId(std::cerr, &srcId); + std::cerr << std::endl; +//#endif + msgin_connect_genmsg(&srcId, &transId, connType, + &connSrcAddr, &connDestAddr, + connMode, connStatus); + break; + } + default: + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::recvPkt() ERROR"; + std::cerr << std::endl; +#endif + /* ERROR */ + break; + } + } + + be_free(node); + return; +} + +/* Input: id, token. + * Response: pong(id, token) + */ + +void bdNode::msgin_ping(bdId *id, bdToken *transId) +{ +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_ping() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << std::endl; +#endif + + mAccount.incCounter(BDACCOUNT_MSG_PING, false); + + /* peer is alive */ + uint32_t peerflags = BITDHT_PEER_STATUS_RECV_PING; /* no id typically, so cant get version */ + addPeer(id, peerflags); + + /* reply */ + msgout_pong(id, transId); + +} + +/* Input: id, token, (+optional version) + * Response: store peer. + */ + +void bdNode::msgin_pong(bdId *id, bdToken *transId, bdToken *versionId) +{ +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_pong() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " Version: TODO!"; // << version; + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << std::endl; +#else + (void) transId; +#endif + + mAccount.incCounter(BDACCOUNT_MSG_PONG, false); + + /* recv pong, and peer is alive. add to DHT */ + //uint32_t vId = 0; // TODO XXX convertBdVersionToVID(versionId); + + /* calculate version match with peer */ + bool sameDhtEngine = false; + bool sameDhtVersion = false; + bool sameAppl = false; + bool sameApplVersion = false; + + if (versionId) + { + +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_pong() Peer Version: "; + for(int i = 0; i < versionId->len; i++) + { + std::cerr << versionId->data[i]; + } + std::cerr << std::endl; +#endif + + /* check two bytes */ + if ((versionId->len >= 2) && (mDhtVersion.size() >= 2) && + (versionId->data[0] == mDhtVersion[0]) && (versionId->data[1] == mDhtVersion[1])) + { + sameDhtEngine = true; + } + + /* check two bytes. + * Due to Old Versions not having this field, we need to check that they are numbers. + * We have a Major version, and minor version.... + * This flag is set if Major is same, and minor is greater or equal to our version. + */ + if ((versionId->len >= 4) && (mDhtVersion.size() >= 4)) + { + if ((isdigit(versionId->data[2]) && isdigit(versionId->data[3])) && + (versionId->data[2] == mDhtVersion[2]) && (versionId->data[3] >= mDhtVersion[3])) + { + sameDhtVersion = true; + } + } + + if ((sameDhtVersion) && (!sameDhtEngine)) + { + sameDhtVersion = false; + std::cerr << "bdNode::msgin_pong() STRANGE Peer Version: "; + for(int i = 0; i < versionId->len; i++) + { + std::cerr << versionId->data[i]; + } + std::cerr << std::endl; + } + + /* check two bytes */ + if ((versionId->len >= 6) && (mDhtVersion.size() >= 6) && + (versionId->data[4] == mDhtVersion[4]) && (versionId->data[5] == mDhtVersion[5])) + { + sameAppl = true; + } + + + /* check two bytes */ + if ((versionId->len >= 8) && (mDhtVersion.size() >= 8)) + { + if ((isdigit(versionId->data[6]) && isdigit(versionId->data[7])) && + (versionId->data[6] == mDhtVersion[6]) && (versionId->data[7] >= mDhtVersion[7])) + { + sameApplVersion = true; + } + } + } + else + { + +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_pong() No Version"; + std::cerr << std::endl; +#endif + } + + + uint32_t peerflags = BITDHT_PEER_STATUS_RECV_PONG; /* should have id too */ + if (sameDhtEngine) + { + peerflags |= BITDHT_PEER_STATUS_DHT_ENGINE; + } + if (sameDhtVersion) + { + peerflags |= BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; + } + if (sameAppl) + { + peerflags |= BITDHT_PEER_STATUS_DHT_APPL; + } + if (sameApplVersion) + { + peerflags |= BITDHT_PEER_STATUS_DHT_APPL_VERSION; + } + + addPeer(id, peerflags); +} + +/* Input: id, token, queryId */ + +void bdNode::msgin_find_node(bdId *id, bdToken *transId, bdNodeId *query) +{ +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_find_node() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Query: "; + mFns->bdPrintNodeId(std::cerr, query); + std::cerr << std::endl; +#endif + + mAccount.incCounter(BDACCOUNT_MSG_QUERYNODE, false); + + + /* store query... */ + queueQuery(id, query, transId, BD_QUERY_NEIGHBOURS); + + + uint32_t peerflags = 0; /* no id, and no help! */ + addPeer(id, peerflags); +} + +void bdNode::msgin_reply_find_node(bdId *id, bdToken *transId, std::list &nodes) +{ + std::list::iterator it; + +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdNode::msgin_reply_find_node() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Peers:"; + for(it = nodes.begin(); it != nodes.end(); it++) + { + std::cerr << " "; + mFns->bdPrintId(std::cerr, &(*it)); + } + std::cerr << std::endl; +#else + (void) transId; +#endif + + mAccount.incCounter(BDACCOUNT_MSG_REPLYFINDNODE, false); + + /* add neighbours to the potential list */ + for(it = nodes.begin(); it != nodes.end(); it++) + { + checkPotentialPeer(&(*it), id); + } + + /* received reply - so peer must be good */ + uint32_t peerflags = BITDHT_PEER_STATUS_RECV_NODES; /* no id ;( */ + addPeer(id, peerflags); +} + +/********* THIS IS THE SECOND STAGE + * + */ + +void bdNode::msgin_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash) +{ + + +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_get_hash() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " InfoHash: "; + mFns->bdPrintNodeId(std::cerr, info_hash); + std::cerr << std::endl; +#endif + + + mAccount.incCounter(BDACCOUNT_MSG_QUERYHASH, false); + + /* generate message, send to udp */ + queueQuery(id, info_hash, transId, BD_QUERY_HASH); + +} + +void bdNode::msgin_reply_hash(bdId *id, bdToken *transId, bdToken *token, std::list &values) +{ + mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, false); + +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_reply_hash() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Token: "; + bdPrintToken(std::cerr, token); + + std::cerr << " Peers: "; + std::list::iterator it; + for(it = values.begin(); it != values.end(); it++) + { + std::cerr << " "; + bdPrintCompactPeerId(std::cerr, *it); + } + std::cerr << std::endl; +#else + (void) id; + (void) transId; + (void) token; + (void) values; +#endif +} + +void bdNode::msgin_reply_nearest(bdId *id, bdToken *transId, bdToken *token, std::list &nodes) +{ + mAccount.incCounter(BDACCOUNT_MSG_REPLYQUERYHASH, false); + +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_reply_nearest() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Token: "; + bdPrintToken(std::cerr, token); + std::cerr << " Nodes:"; + + std::list::iterator it; + for(it = nodes.begin(); it != nodes.end(); it++) + { + std::cerr << " "; + mFns->bdPrintId(std::cerr, &(*it)); + } + std::cerr << std::endl; +#else + (void) id; + (void) transId; + (void) token; + (void) nodes; +#endif +} + + + +void bdNode::msgin_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash, uint32_t port, bdToken *token) +{ + + mAccount.incCounter(BDACCOUNT_MSG_POSTHASH, false); + +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_post_hash() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " Info_Hash: "; + mFns->bdPrintNodeId(std::cerr, info_hash); + std::cerr << " Port: " << port; + std::cerr << " Token: "; + bdPrintToken(std::cerr, token); + std::cerr << std::endl; +#else + (void) id; + (void) transId; + (void) info_hash; + (void) port; + (void) token; +#endif + +} + + +void bdNode::msgin_reply_post(bdId *id, bdToken *transId) +{ + /* generate message, send to udp */ + mAccount.incCounter(BDACCOUNT_MSG_REPLYPOSTHASH, false); + +#ifdef DEBUG_NODE_MSGIN + std::cerr << "bdNode::msgin_reply_post() TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << std::endl; +#else + (void) id; + (void) transId; +#endif +} + + + +/************************************************************************************************************ +******************************************** Message Interface ********************************************** +************************************************************************************************************/ + +/* Outgoing Messages */ +std::string getConnectMsgType(int msgtype) +{ + switch(msgtype) + { + case BITDHT_MSG_TYPE_CONNECT_REQUEST: + return "ConnectRequest"; + break; + case BITDHT_MSG_TYPE_CONNECT_REPLY: + return "ConnectReply"; + break; + case BITDHT_MSG_TYPE_CONNECT_START: + return "ConnectStart"; + break; + case BITDHT_MSG_TYPE_CONNECT_ACK: + return "ConnectAck"; + break; + default: + return "ConnectUnknown"; + break; + } +} + +void bdNode::msgout_connect_genmsg(bdId *id, bdToken *transId, int msgtype, bdId *srcAddr, bdId *destAddr, int mode, int status) +{ + std::cerr << "bdConnectManager::msgout_connect_genmsg() Type: " << getConnectMsgType(msgtype); + std::cerr << " TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " To: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " SrcAddr: "; + mFns->bdPrintId(std::cerr, srcAddr); + std::cerr << " DestAddr: "; + mFns->bdPrintId(std::cerr, destAddr); + std::cerr << " Mode: " << mode; + std::cerr << " Status: " << status; + std::cerr << std::endl; +#ifdef DEBUG_NODE_MSGOUT +#endif + + switch(msgtype) + { + default: + case BITDHT_MSG_TYPE_CONNECT_REQUEST: + mAccount.incCounter(BDACCOUNT_MSG_CONNECTREQUEST, true); + break; + case BITDHT_MSG_TYPE_CONNECT_REPLY: + mAccount.incCounter(BDACCOUNT_MSG_CONNECTREPLY, true); + break; + case BITDHT_MSG_TYPE_CONNECT_START: + mAccount.incCounter(BDACCOUNT_MSG_CONNECTSTART, true); + break; + case BITDHT_MSG_TYPE_CONNECT_ACK: + mAccount.incCounter(BDACCOUNT_MSG_CONNECTACK, true); + break; + } + + registerOutgoingMsg(id, transId, msgtype); + + /* create string */ + char msg[10240]; + int avail = 10240; + + int blen = bitdht_connect_genmsg(transId, &(mOwnId), msgtype, srcAddr, destAddr, mode, status, msg, avail-1); + sendPkt(msg, blen, id->addr); +} + + +void bdNode::msgin_connect_genmsg(bdId *id, bdToken *transId, int msgtype, + bdId *srcAddr, bdId *destAddr, int mode, int status) +{ + std::list::iterator it; + + std::cerr << "bdConnectManager::msgin_connect_genmsg() Type: " << getConnectMsgType(msgtype); + std::cerr << " TransId: "; + bdPrintTransId(std::cerr, transId); + std::cerr << " From: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << " SrcAddr: "; + mFns->bdPrintId(std::cerr, srcAddr); + std::cerr << " DestAddr: "; + mFns->bdPrintId(std::cerr, destAddr); + std::cerr << " Mode: " << mode; + std::cerr << " Status: " << status; + std::cerr << std::endl; +#ifdef DEBUG_NODE_MSGS +#else + (void) transId; +#endif + + /* switch to actual work functions */ + uint32_t peerflags = 0; + switch(msgtype) + { + case BITDHT_MSG_TYPE_CONNECT_REQUEST: + peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; + mAccount.incCounter(BDACCOUNT_MSG_CONNECTREQUEST, false); + + + mConnMgr->recvedConnectionRequest(id, srcAddr, destAddr, mode); + + break; + case BITDHT_MSG_TYPE_CONNECT_REPLY: + peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; + mAccount.incCounter(BDACCOUNT_MSG_CONNECTREPLY, false); + + mConnMgr->recvedConnectionReply(id, srcAddr, destAddr, mode, status); + + break; + case BITDHT_MSG_TYPE_CONNECT_START: + peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; + mAccount.incCounter(BDACCOUNT_MSG_CONNECTSTART, false); + + mConnMgr->recvedConnectionStart(id, srcAddr, destAddr, mode, status); + + break; + case BITDHT_MSG_TYPE_CONNECT_ACK: + peerflags = BITDHT_PEER_STATUS_RECV_CONNECT_MSG; + mAccount.incCounter(BDACCOUNT_MSG_CONNECTACK, false); + + mConnMgr->recvedConnectionAck(id, srcAddr, destAddr, mode); + + break; + default: + break; + } + + /* received message - so peer must be good */ + addPeer(id, peerflags); + +} + + + + + + + + + + + +/****************** Other Functions ******************/ + +void bdNode::genNewToken(bdToken *token) +{ +#ifdef DEBUG_NODE_ACTIONS + fprintf(stderr, "bdNode::genNewToken()"); + fprintf(stderr, ")\n"); +#endif + + // XXX is this a good way to do it? + // Variable length, from 4 chars up to lots... 10? + // leave for the moment, but fix. + std::ostringstream out; + out << std::setw(4) << std::setfill('0') << bdRandom::random_u32(); + + std::string num = out.str(); + int len = num.size(); + if (len > BITDHT_TOKEN_MAX_LEN) + len = BITDHT_TOKEN_MAX_LEN; + + for(int i = 0; i < len; i++) + { + token->data[i] = num[i]; + } + token->len = len; + +} + +uint32_t transIdCounter = 0; +void bdNode::genNewTransId(bdToken *token) +{ + /* generate message, send to udp */ +#ifdef DEBUG_NODE_ACTIONS + fprintf(stderr, "bdNode::genNewTransId()"); + fprintf(stderr, ")\n"); +#endif + + std::ostringstream out; + out << std::setw(2) << std::setfill('0') << transIdCounter++; + std::string num = out.str(); + int len = num.size(); + if (len > BITDHT_TOKEN_MAX_LEN) + len = BITDHT_TOKEN_MAX_LEN; + + for(int i = 0; i < len; i++) + { + token->data[i] = num[i]; + } + token->len = len; +} + + +/* Store Remote Query for processing */ +int bdNode::queueQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type) +{ +#ifdef DEBUG_NODE_ACTIONS + std::cerr << "bdnode::queueQuery()" << std::endl; +#endif + + mRemoteQueries.push_back(bdRemoteQuery(id, query, transId, query_type)); + + return 1; +} + +/*************** Register Transaction Ids *************/ + +void bdNode::registerOutgoingMsg(bdId *id, bdToken *transId, uint32_t msgType) +{ + +#ifdef DEBUG_MSG_CHECKS + std::cerr << "bdNode::registerOutgoingMsg("; + mFns->bdPrintId(std::cerr, id); + std::cerr << ", " << msgType << ")"; + std::cerr << std::endl; +#else + (void) id; + (void) msgType; +#endif + +#ifdef USE_HISTORY + mHistory.addMsg(id, transId, msgType, false); +#else + (void) transId; +#endif + + + +/**** +#define BITDHT_MSG_TYPE_UNKNOWN 0 +#define BITDHT_MSG_TYPE_PING 1 +#define BITDHT_MSG_TYPE_PONG 2 +#define BITDHT_MSG_TYPE_FIND_NODE 3 +#define BITDHT_MSG_TYPE_REPLY_NODE 4 +#define BITDHT_MSG_TYPE_GET_HASH 5 +#define BITDHT_MSG_TYPE_REPLY_HASH 6 +#define BITDHT_MSG_TYPE_REPLY_NEAR 7 +#define BITDHT_MSG_TYPE_POST_HASH 8 +#define BITDHT_MSG_TYPE_REPLY_POST 9 +***/ + +} + + + +uint32_t bdNode::checkIncomingMsg(bdId *id, bdToken *transId, uint32_t msgType) +{ + +#ifdef DEBUG_MSG_CHECKS + std::cerr << "bdNode::checkIncomingMsg("; + mFns->bdPrintId(std::cerr, id); + std::cerr << ", " << msgType << ")"; + std::cerr << std::endl; +#else + (void) id; + (void) msgType; +#endif + +#ifdef USE_HISTORY + mHistory.addMsg(id, transId, msgType, true); +#else + (void) transId; +#endif + + return 0; +} + +void bdNode::cleanupTransIdRegister() +{ + return; +} + + + +/*************** Internal Msg Storage *****************/ + +bdNodeNetMsg::bdNodeNetMsg(char *msg, int len, struct sockaddr_in *in_addr) + :data(NULL), mSize(len), addr(*in_addr) +{ + data = (char *) malloc(len); + memcpy(data, msg, len); + //print(std::cerr); +} + +void bdNodeNetMsg::print(std::ostream &out) +{ + out << "bdNodeNetMsg::print(" << mSize << ") to " + << inet_ntoa(addr.sin_addr) << ":" << htons(addr.sin_port); + out << std::endl; +} + + +bdNodeNetMsg::~bdNodeNetMsg() +{ + free(data); +} + + + + + diff --git a/libbitdht/src/bitdht/bdnode.h b/libbitdht/src/bitdht/bdnode.h new file mode 100644 index 000000000..3d43d1c5c --- /dev/null +++ b/libbitdht/src/bitdht/bdnode.h @@ -0,0 +1,260 @@ +#ifndef BITDHT_NODE_H +#define BITDHT_NODE_H + +/* + * bitdht/bdnode.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdpeer.h" +#include "bitdht/bdquery.h" +#include "bitdht/bdstore.h" +#include "bitdht/bdobj.h" +#include "bitdht/bdhash.h" +#include "bitdht/bdhistory.h" + +#include "bitdht/bdconnection.h" +#include "bitdht/bdaccount.h" + +class bdFilter; + + +#define BD_QUERY_NEIGHBOURS 1 +#define BD_QUERY_HASH 2 + +/********************************** + * Running a node.... + * + * run(). + * loops through and checks out of date peers. + * handles searches. + * prints out dht Table. + * + +The node handles the i/o traffic from peers. +It + + + +ping, return +peers, return +hash store, return +hash get, return + + + +respond queue. + +query queue. + + + + + +input -> call into recvFunction() +output -> call back to Udp(). + + + + + *********/ + +class bdNodeNetMsg +{ + + public: + bdNodeNetMsg(char *data, int size, struct sockaddr_in *addr); + ~bdNodeNetMsg(); + + void print(std::ostream &out); + + char *data; + int mSize; + struct sockaddr_in addr; + +}; + +class bdNodePublisher +{ + public: + /* simplified outgoing msg functions (for the managers) */ + virtual void send_ping(bdId *id) = 0; /* message out */ + virtual void send_query(bdId *id, bdNodeId *targetNodeId) = 0; /* message out */ + virtual void send_connect_msg(bdId *id, int msgtype, + bdId *srcAddr, bdId *destAddr, int mode, int status) = 0; + + // internal Callback -> normally continues to callbackConnect(). + virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, + int mode, int point, int cbtype, int errcode) = 0; + +}; + + +class bdNode: public bdNodePublisher +{ + public: + + bdNode(bdNodeId *id, std::string dhtVersion, std::string bootfile, + bdDhtFunctions *fns); + + void init(); /* sets up the self referential classes (mQueryMgr & mConnMgr) */ + + void setNodeOptions(uint32_t optFlags); + + /* startup / shutdown node */ + void restartNode(); + void shutdownNode(); + + void getOwnId(bdNodeId *id); + + // virtual so manager can do callback. + // peer flags defined in bdiface.h + virtual void addPeer(const bdId *id, uint32_t peerflags); + + void printState(); + void checkPotentialPeer(bdId *id, bdId *src); + void addPotentialPeer(bdId *id, bdId *src); + + void iterationOff(); + void iteration(); + void processRemoteQuery(); + void updateStore(); + + /* simplified outgoing msg functions (for the managers) */ + virtual void send_ping(bdId *id); /* message out */ + virtual void send_query(bdId *id, bdNodeId *targetNodeId); /* message out */ + virtual void send_connect_msg(bdId *id, int msgtype, + bdId *srcAddr, bdId *destAddr, int mode, int status); + +// This is implemented in bdManager. +// virtual void callbackConnect(bdId *srcId, bdId *proxyId, bdId *destId, +// int mode, int point, int cbtype, int errcode); + + /* interaction with outside world (Accessed by controller to deliver us msgs) */ +int outgoingMsg(struct sockaddr_in *addr, char *msg, int *len); +void incomingMsg(struct sockaddr_in *addr, char *msg, int len); + + + // Below is internal Management of incoming / outgoing messages. + private: + + /* internal interaction with network */ +void sendPkt(char *msg, int len, struct sockaddr_in addr); +void recvPkt(char *msg, int len, struct sockaddr_in addr); + + + /* output functions (send msg) */ + void msgout_ping(bdId *id, bdToken *transId); + void msgout_pong(bdId *id, bdToken *transId); + void msgout_find_node(bdId *id, bdToken *transId, bdNodeId *query); + void msgout_reply_find_node(bdId *id, bdToken *transId, + std::list &peers); + void msgout_get_hash(bdId *id, bdToken *transId, bdNodeId *info_hash); + void msgout_reply_hash(bdId *id, bdToken *transId, + bdToken *token, std::list &values); + void msgout_reply_nearest(bdId *id, bdToken *transId, + bdToken *token, std::list &peers); + + void msgout_post_hash(bdId *id, bdToken *transId, bdNodeId *info_hash, + uint32_t port, bdToken *token); + void msgout_reply_post(bdId *id, bdToken *transId); + + + /* input functions (once mesg is parsed) */ + void msgin_ping(bdId *id, bdToken *token); + void msgin_pong(bdId *id, bdToken *transId, bdToken *versionId); + + void msgin_find_node(bdId *id, bdToken *transId, bdNodeId *query); + void msgin_reply_find_node(bdId *id, bdToken *transId, + std::list &entries); + + void msgin_get_hash(bdId *id, bdToken *transId, bdNodeId *nodeid); + void msgin_reply_hash(bdId *id, bdToken *transId, + bdToken *token, std::list &values); + void msgin_reply_nearest(bdId *id, bdToken *transId, + bdToken *token, std::list &nodes); + + void msgin_post_hash(bdId *id, bdToken *transId, + bdNodeId *info_hash, uint32_t port, bdToken *token); + void msgin_reply_post(bdId *id, bdToken *transId); + + void msgout_connect_genmsg(bdId *id, bdToken *transId, int msgtype, + bdId *srcAddr, bdId *destAddr, int mode, int status); + void msgin_connect_genmsg(bdId *id, bdToken *transId, int msgtype, + bdId *srcAddr, bdId *destAddr, int mode, int status); + + + + /* token handling */ + void genNewToken(bdToken *token); + int queueQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type); + + /* transId handling */ + void genNewTransId(bdToken *token); + void registerOutgoingMsg(bdId *id, bdToken *transId, uint32_t msgType); + uint32_t checkIncomingMsg(bdId *id, bdToken *transId, uint32_t msgType); + void cleanupTransIdRegister(); + + + void doStats(); + + /********** Variables **********/ + private: + + /**** Some Variables are Protected to allow inherited classes to use *****/ + protected: + + bdSpace mNodeSpace; + + bdQueryManager *mQueryMgr; + bdConnectManager *mConnMgr; + bdFilter *mFilterPeers; + + bdNodeId mOwnId; + bdId mLikelyOwnId; // Try to workout own id address. + std::string mDhtVersion; + + bdAccount mAccount; + bdStore mStore; + + bdDhtFunctions *mFns; + bdHashSpace mHashSpace; + + private: + + uint32_t mNodeOptionFlags; + + bdHistory mHistory; /* for understanding the DHT */ + + std::list mRemoteQueries; + + std::list mPotentialPeers; + + std::list mOutgoingMsgs; + std::list mIncomingMsgs; +}; + + + +#endif // BITDHT_NODE_H diff --git a/libbitdht/src/bitdht/bdobj.cc b/libbitdht/src/bitdht/bdobj.cc new file mode 100644 index 000000000..df22686cc --- /dev/null +++ b/libbitdht/src/bitdht/bdobj.cc @@ -0,0 +1,52 @@ + +/* + * bitdht/bdobj.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bitdht/bdobj.h" + + +void bdPrintTransId(std::ostream &out, bdToken *transId) +{ + //out << transId->data; + bdPrintToken(out, transId); + return; +} + + +void bdPrintToken(std::ostream &out, bdToken *token) +{ + for(unsigned int i = 0; i < token->len; i++) + { + out << std::hex << (uint32_t) token->data[i]; + } + out << std::dec; +} + +void bdPrintCompactPeerId(std::ostream &out, std::string /*cpi*/ ) +{ + out << "DummyCompactPeerId"; +} + + diff --git a/libbitdht/src/bitdht/bdobj.h b/libbitdht/src/bitdht/bdobj.h new file mode 100644 index 000000000..dbc8b5385 --- /dev/null +++ b/libbitdht/src/bitdht/bdobj.h @@ -0,0 +1,64 @@ +#ifndef BITDHT_OBJECTS_H +#define BITDHT_OBJECTS_H + +/* + * bitdht/bdobj.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#define BITDHT_TOKEN_MAX_LEN 20 + +#include +#include + +class bdToken +{ + public: + bdToken() :len(0) { return; } + uint32_t len; + unsigned char data[BITDHT_TOKEN_MAX_LEN]; +}; + +class bdCompactIds +{ + public: + bdCompactIds() :len(0) { return; } + uint32_t len; + unsigned char data[BITDHT_TOKEN_MAX_LEN]; +}; + +class bdVersion +{ + public: + bdVersion() :len(0) { return; } + uint32_t len; + unsigned char data[BITDHT_TOKEN_MAX_LEN]; +}; + +void bdPrintTransId(std::ostream &out, bdToken *transId); +void bdPrintToken(std::ostream &out, bdToken *transId); +void bdPrintCompactPeerId(std::ostream &out, std::string cpi); + +#endif + diff --git a/libbitdht/src/bitdht/bdpeer.cc b/libbitdht/src/bitdht/bdpeer.cc new file mode 100644 index 000000000..31f450ae8 --- /dev/null +++ b/libbitdht/src/bitdht/bdpeer.cc @@ -0,0 +1,1262 @@ +/* + * bitdht/bdpeer.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdpeer.h" +#include "util/bdnet.h" +#include "util/bdrandom.h" +#include "bitdht/bdiface.h" + +#include +#include +#include + +#include +#include +#include + +/** + * #define BITDHT_DEBUG 1 +**/ + +void bdSockAddrInit(struct sockaddr_in *addr) +{ + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; +} + +bdId::bdId() +{ + /* blank everything */ + bdSockAddrInit(&addr); + memset(&id.data, 0, BITDHT_KEY_LEN); +} + + +bdId::bdId(bdNodeId in_id, struct sockaddr_in in_addr) +{ + /* this bit is to ensure the address is valid for windows / osx */ + bdSockAddrInit(&addr); + addr.sin_addr.s_addr = in_addr.sin_addr.s_addr; + addr.sin_port = in_addr.sin_port; + + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + id.data[i] = in_id.data[i]; + } +}; + + +void bdZeroNodeId(bdNodeId *id) +{ + uint32_t *a_data = (uint32_t *) id->data; + for(int i = 0; i < BITDHT_KEY_INTLEN; i++) + { + a_data[i] = 0; + } + return; +} + + +int operator<(const bdNodeId &a, const bdNodeId &b) +{ +#if 0 + std::cerr << "operator<("); + bdPrintNodeId(std::cerr, &a); + std::cerr << ","; + bdPrintNodeId(std::cerr, &b); + std::cerr << ")" << std::endl; +#endif + + uint8_t *a_data = (uint8_t *) a.data; + uint8_t *b_data = (uint8_t *) b.data; + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + if (*a_data < *b_data) + { + //fprintf(stderr, "Return 1, at i = %d\n", i); + return 1; + } + else if (*a_data > *b_data) + { + //fprintf(stderr, "Return 0, at i = %d\n", i); + return 0; + } + a_data++; + b_data++; + } + //fprintf(stderr, "Return 0, at i = KEYLEN\n"); + return 0; +} + +#if 0 +int operator<(const struct sockaddr_in &a, const struct sockaddr_in &b) +{ + /* else NodeIds the same - check id addresses */ + if (a.sin_addr.s_addr < b.sin_addr.s_addr) + return 1; + if (b.sin_addr.s_addr > a.sin_addr.s_addr) + return 0; + + if (a.sin_port < b.sin_port) + return 1; + + return 0; +} +#endif + +int operator<(const bdId &a, const bdId &b) +{ + if (a.id < b.id) + return 1; + if (b.id < a.id) + return 0; + + /* else NodeIds the same - check id addresses */ + if (a.addr.sin_addr.s_addr < b.addr.sin_addr.s_addr) + return 1; + if (b.addr.sin_addr.s_addr > a.addr.sin_addr.s_addr) + return 0; + + if (a.addr.sin_port < b.addr.sin_port) + return 1; + + return 0; +} + + +int operator==(const bdNodeId &a, const bdNodeId &b) +{ + uint8_t *a_data = (uint8_t *) a.data; + uint8_t *b_data = (uint8_t *) b.data; + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + if (*a_data < *b_data) + { + return 0; + } + else if (*a_data > *b_data) + { + return 0; + } + a_data++; + b_data++; + } + return 1; +} + +int operator==(const bdId &a, const bdId &b) +{ + if (!(a.id == b.id)) + return 0; + + if ((a.addr.sin_addr.s_addr == b.addr.sin_addr.s_addr) && + (a.addr.sin_port == b.addr.sin_port)) + { + return 1; + } + return 0; +} + + + +bdBucket::bdBucket() +{ + return; +} + +bdSpace::bdSpace(bdNodeId *ownId, bdDhtFunctions *fns) + :mOwnId(*ownId), mFns(fns) +{ + /* make some space for data */ + buckets.resize(mFns->bdNumBuckets()); + + mAttachTS = 0; + mAttachedFlags = 0; + mAttachedCount = 0; + + return; +} + + /* empty the buckets */ +int bdSpace::clear() +{ + std::vector::iterator it; + /* iterate through the buckets, and sort by distance */ + for(it = buckets.begin(); it != buckets.end(); it++) + { + it->entries.clear(); + } + return 1; +} + +int bdSpace::setAttachedFlag(uint32_t withflags, int count) +{ + mAttachedFlags = withflags; + mAttachedCount = count; + mAttachTS = 0; + return 1; +} + +int bdSpace::find_nearest_nodes_with_flags(const bdNodeId *id, int number, + std::list /* excluding */, + std::multimap &nearest, uint32_t with_flags) +{ + std::multimap closest; + std::multimap::iterator mit; + + bdMetric dist; + mFns->bdDistance(id, &(mOwnId), &dist); + +#ifdef DEBUG_BD_SPACE + int bucket = mFns->bdBucketDistance(&dist); + + std::cerr << "bdSpace::find_nearest_nodes(NodeId:"; + mFns->bdPrintNodeId(std::cerr, id); + + std::cerr << " Number: " << number; + std::cerr << " Query Bucket #: " << bucket; + std::cerr << std::endl; +#endif + + std::vector::iterator it; + std::list::iterator eit; + /* iterate through the buckets, and sort by distance */ + for(it = buckets.begin(); it != buckets.end(); it++) + { + for(eit = it->entries.begin(); eit != it->entries.end(); eit++) + { + if ((!with_flags) || ((with_flags & eit->mPeerFlags) == with_flags)) + { + mFns->bdDistance(id, &(eit->mPeerId.id), &dist); + closest.insert(std::pair(dist, eit->mPeerId)); + +#if 0 + std::cerr << "Added NodeId: "; + bdPrintNodeId(std::cerr, &(eit->mPeerId.id)); + std::cerr << " Metric: "; + bdPrintNodeId(std::cerr, &(dist)); + std::cerr << std::endl; +#endif + } + } + } + + /* take the first number of nodes */ + int i = 0; + for(mit = closest.begin(); (mit != closest.end()) && (i < number); mit++, i++) + { + mFns->bdDistance(&(mOwnId), &(mit->second.id), &dist); + +#ifdef DEBUG_BD_SPACE + int iBucket = mFns->bdBucketDistance(&(mit->first)); + + std::cerr << "Closest " << i << ": "; + mFns->bdPrintNodeId(std::cerr, &(mit->second.id)); + std::cerr << " Bucket: " << iBucket; + std::cerr << std::endl; +#endif + + +#if 0 + std::cerr << "\tNodeId: "; + mFns->bdPrintNodeId(std::cerr, &(mit->second.id)); + std::cerr << std::endl; + + std::cerr << "\tOwn Id: "; + mFns->bdPrintNodeId(std::cerr, &(mOwnId)); + std::cerr << std::endl; + + std::cerr << " Us Metric: "; + mFns->bdPrintNodeId(std::cerr, &dist); + std::cerr << " Bucket: " << oBucket; + std::cerr << std::endl; + + std::cerr << "\tFindId: "; + mFns->bdPrintNodeId(std::cerr, id); + std::cerr << std::endl; + + std::cerr << " Id Metric: "; + mFns->bdPrintNodeId(std::cerr, &(mit->first)); + std::cerr << " Bucket: " << iBucket; + std::cerr << std::endl; +#endif + + nearest.insert(*mit); + } + +#ifdef DEBUG_BD_SPACE + std::cerr << "#Nearest: " << (int) nearest.size(); + std::cerr << " #Closest: " << (int) closest.size(); + std::cerr << " #Requested: " << number; + std::cerr << std::endl << std::endl; +#endif + + return 1; +} + +int bdSpace::find_nearest_nodes(const bdNodeId *id, int number, + std::multimap &nearest) +{ + std::list excluding; + uint32_t with_flag = 0; + + return find_nearest_nodes_with_flags(id, number, excluding, nearest, with_flag); +} + + +/* This is much cheaper than find nearest... we only look in the one bucket + */ + +int bdSpace::find_node(const bdNodeId *id, int number, std::list &matchIds, uint32_t with_flags) +{ + bdMetric dist; + mFns->bdDistance(id, &(mOwnId), &dist); + int buckno = mFns->bdBucketDistance(&dist); + + std::cerr << "bdSpace::find_node(NodeId:"; + mFns->bdPrintNodeId(std::cerr, id); + std::cerr << ")"; + + std::cerr << " Number: " << number; + std::cerr << " Bucket #: " << buckno; + std::cerr << std::endl; +#ifdef DEBUG_BD_SPACE +#endif + + bdBucket &buck = buckets[buckno]; + + std::list::iterator eit; + int matchCount = 0; + for(eit = buck.entries.begin(); eit != buck.entries.end(); eit++) + { + std::cerr << "bdSpace::find_node() Checking Against Peer: "; + mFns->bdPrintId(std::cerr, &(eit->mPeerId)); + std::cerr << " withFlags: " << eit->mPeerFlags; + std::cerr << std::endl; + + if ((!with_flags) || ((with_flags & eit->mPeerFlags) == with_flags)) + { + if (*id == eit->mPeerId.id) + { + matchIds.push_back(eit->mPeerId); + matchCount++; + + std::cerr << "bdSpace::find_node() Found Matching Peer: "; + mFns->bdPrintId(std::cerr, &(eit->mPeerId)); + std::cerr << " withFlags: " << eit->mPeerFlags; + std::cerr << std::endl; + } + } + else + { + if (*id == eit->mPeerId.id) + { + //matchIds.push_back(eit->mPeerId); + //matchCount++; + + std::cerr << "bdSpace::find_node() Found (WITHOUT FLAGS) Matching Peer: "; + mFns->bdPrintId(std::cerr, &(eit->mPeerId)); + std::cerr << " withFlags: " << eit->mPeerFlags; + std::cerr << std::endl; + } + } + } + + std::cerr << "bdSpace::find_node() Found " << matchCount << " Matching Peers"; + std::cerr << std::endl << std::endl; +#ifdef DEBUG_BD_SPACE +#endif + + return matchCount; +} + +/* even cheaper again... no big lists */ +int bdSpace::find_exactnode(const bdId *id, bdPeer &peer) +{ + bdMetric dist; + mFns->bdDistance(&(id->id), &(mOwnId), &dist); + int buckno = mFns->bdBucketDistance(&dist); + + std::cerr << "bdSpace::find_exactnode(Id:"; + mFns->bdPrintId(std::cerr, id); + std::cerr << ")"; + + std::cerr << " Bucket #: " << buckno; + std::cerr << std::endl; + +#ifdef DEBUG_BD_SPACE +#endif + + bdBucket &buck = buckets[buckno]; + + std::list::iterator eit; + int matchCount = 0; + for(eit = buck.entries.begin(); eit != buck.entries.end(); eit++) + { + if (*id == eit->mPeerId) + { + std::cerr << "bdSpace::find_exactnode() Found Matching Peer: "; + mFns->bdPrintId(std::cerr, &(eit->mPeerId)); + std::cerr << " withFlags: " << eit->mPeerFlags; + std::cerr << std::endl; + + peer = (*eit); + return 1; + } + } + std::cerr << "bdSpace::find_exactnode() ERROR Failed to find Matching Peer: "; + std::cerr << std::endl; + + return 0; +} + + +#if 0 +int bdSpace::out_of_date_peer(bdId &id) +{ + /* + * + */ + + std::map closest; + std::map::iterator mit; + + std::vector::iterator it; + std::list::iterator eit; + time_t ts = time(NULL); + + /* iterate through the buckets, and sort by distance */ + for(it = buckets.begin(); it != buckets.end(); it++) + { + for(eit = it->entries.begin(); eit != it->entries.end(); ) + { + /* timeout on last send time! */ + if (ts - eit->mLastSendTime > BITDHT_MAX_SEND_PERIOD ) + { + /* We want to ping a peer iff: + * 1) They are out-of-date: mLastRecvTime is too old. + * 2) They don't have 0x0001 flag (we haven't received a PONG) and never sent. + */ + if ((ts - eit->mLastRecvTime > BITDHT_MAX_SEND_PERIOD ) || + !(eit->mPeerFlags & BITDHT_PEER_STATUS_RECV_PONG)) + { + id = eit->mPeerId; + eit->mLastSendTime = ts; + return 1; + } + } + + + /* we also want to remove very old entries (should it happen here?) + * which are not pushed out by newer entries (will happen in for closer buckets) + */ + + bool discard = false; + /* discard very old entries */ + if (ts - eit->mLastRecvTime > BITDHT_DISCARD_PERIOD) + { + discard = true; + } + + /* discard peers which have not responded to anything (ie have no flags set) */ + if ((ts - eit->mFoundTime > BITDHT_MAX_RESPONSE_PERIOD ) && + (eit->mPeerFlags == 0)) + { + discard = true; + } + + + /* INCREMENT */ + if (discard) + { + eit = it->entries.erase(eit); + } + else + { + eit++; + } + } + } + return 0; +} + +#endif + + + + +#define BITDHT_ATTACHED_SEND_PERIOD 17 + +int bdSpace::scanOutOfDatePeers(std::list &peerIds) +{ + /* + * + */ + bool doAttached = (mAttachedCount > 0); + int attachedCount = 0; + + std::map closest; + std::map::iterator mit; + + std::vector::iterator it; + std::list::iterator eit; + time_t ts = time(NULL); + + /* iterate through the buckets, and sort by distance */ + for(it = buckets.begin(); it != buckets.end(); it++) + { + for(eit = it->entries.begin(); eit != it->entries.end(); ) + { + bool added = false; + if (doAttached) + { + if (eit->mExtraFlags & BITDHT_PEER_EXFLAG_ATTACHED) + { + /* add to send list, if we haven't pinged recently */ + if ((ts - eit->mLastSendTime > BITDHT_ATTACHED_SEND_PERIOD ) && + (ts - eit->mLastRecvTime > BITDHT_ATTACHED_SEND_PERIOD )) + { + peerIds.push_back(eit->mPeerId); + eit->mLastSendTime = ts; + added = true; + } + attachedCount++; + } + } + + + /* timeout on last send time! */ + if ((!added) && (ts - eit->mLastSendTime > BITDHT_MAX_SEND_PERIOD )) + { + /* We want to ping a peer iff: + * 1) They are out-of-date: mLastRecvTime is too old. + * 2) They don't have 0x0001 flag (we haven't received a PONG) and never sent. + */ + if ((ts - eit->mLastRecvTime > BITDHT_MAX_SEND_PERIOD ) || + !(eit->mPeerFlags & BITDHT_PEER_STATUS_RECV_PONG)) + { + peerIds.push_back(eit->mPeerId); + eit->mLastSendTime = ts; + } + } + + + /* we also want to remove very old entries (should it happen here?) + * which are not pushed out by newer entries (will happen in for closer buckets) + */ + + bool discard = false; + /* discard very old entries */ + if (ts - eit->mLastRecvTime > BITDHT_DISCARD_PERIOD) + { + discard = true; + } + + /* discard peers which have not responded to anything (ie have no flags set) */ + /* changed into have not id'ed themselves, as we've added ping to list of flags. */ + if ((ts - eit->mFoundTime > BITDHT_MAX_RESPONSE_PERIOD ) && + !(eit->mPeerFlags & BITDHT_PEER_STATUS_RECV_PONG)) + { + discard = true; + } + + + /* INCREMENT */ + if (discard) + { + eit = it->entries.erase(eit); + } + else + { + eit++; + } + } + } + +#define ATTACH_UPDATE_PERIOD 600 + + if ((ts - mAttachTS > ATTACH_UPDATE_PERIOD) || (attachedCount != mAttachedCount)) + { + //std::cerr << "Updating ATTACH Stuff"; + //std::cerr << std::endl; + updateAttachedPeers(); /* XXX TEMP HACK to look at stability */ + mAttachTS = ts; + } + + return (peerIds.size()); +} + + +int bdSpace::updateAttachedPeers() +{ + /* + * + */ + bool doAttached = (mAttachedCount > 0); + int attachedCount = 0; + + if (!doAttached) + { + return 0; + } + + std::map closest; + std::map::iterator mit; + + std::vector::iterator it; + std::list::reverse_iterator eit; + + + /* skip the first bucket, as we don't want to ping ourselves! */ + it = buckets.begin(); + if (it != buckets.end()) + { + it++; + } + + /* iterate through the buckets (sorted by distance) */ + for(; it != buckets.end(); it++) + { + /* start from the back, as these are the most recently seen (and more likely to be the old ATTACHED) */ + for(eit = it->entries.rbegin(); eit != it->entries.rend(); eit++) + { + bool added = false; + if (doAttached) + { + if ((eit->mPeerFlags & mAttachedFlags) == mAttachedFlags) + { + /* flag as attached */ + eit->mExtraFlags |= BITDHT_PEER_EXFLAG_ATTACHED; + + /* inc count, and cancel search if we've found them */ + attachedCount++; + if (attachedCount >= mAttachedCount) + { + doAttached = false; + } + } + else + { + eit->mExtraFlags &= ~BITDHT_PEER_EXFLAG_ATTACHED; + } + } + else + { + eit->mExtraFlags &= ~BITDHT_PEER_EXFLAG_ATTACHED; + } + } + } + return 1; +} + + + + +/* Called to add or update peer. + * sorts bucket lists by lastRecvTime. + * updates requested node. + */ + +/* peer flags + * order is important! + * higher bits = more priority. + * BITDHT_PEER_STATUS_RECVPING + * BITDHT_PEER_STATUS_RECVPONG + * BITDHT_PEER_STATUS_RECVNODES + * BITDHT_PEER_STATUS_RECVHASHES + * BITDHT_PEER_STATUS_DHT_ENGINE (dbXXxx) + * BITDHT_PEER_STATUS_DHT_APPL (XXRSxx) + * BITDHT_PEER_STATUS_DHT_VERSION (XXxx50) + * + */ + +int bdSpace::add_peer(const bdId *id, uint32_t peerflags) +{ + /* find the peer */ + bool add = false; + time_t ts = time(NULL); + +#ifdef DEBUG_BD_SPACE + fprintf(stderr, "bdSpace::add_peer()\n"); +#endif + + /* calculate metric */ + bdMetric met; + mFns->bdDistance(&(mOwnId), &(id->id), &met); + int bucket = mFns->bdBucketDistance(&met); + +#ifdef DEBUG_BD_SPACE + fprintf(stderr, "peer:"); + mFns->bdPrintId(std::cerr, id); + fprintf(stderr, " bucket: %d", bucket); + fprintf(stderr, "\n"); +#endif + + /* select correct bucket */ + bdBucket &buck = buckets[bucket]; + + + std::list::iterator it; + + /* calculate the score for this new peer */ + uint32_t minScore = peerflags; + + /* loop through ids, to find it */ + for(it = buck.entries.begin(); it != buck.entries.end(); it++) + { + /* similar id check */ + if (mFns->bdSimilarId(id, &(it->mPeerId))) + { + bdPeer peer = *it; + it = buck.entries.erase(it); + + peer.mLastRecvTime = ts; + peer.mPeerFlags |= peerflags; /* must be cumulative ... so can do online, replynodes, etc */ + + /* also update port from incoming id, as we have definitely recved from it */ + if (mFns->bdUpdateSimilarId(&(peer.mPeerId), id)) + { + /* updated it... must be Unstable */ + peer.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; + } + + buck.entries.push_back(peer); + +#ifdef DEBUG_BD_SPACE + std::cerr << "Peer already in bucket: moving to back of the list" << std::endl; +#endif + + return 1; + } + + /* find lowest score */ + if (it->mPeerFlags < minScore) + { + minScore = it->mPeerFlags; + } + } + + /* not in the list! */ + + if (buck.entries.size() < mFns->bdNodesPerBucket()) + { +#ifdef DEBUG_BD_SPACE + std::cerr << "Bucket not full: allowing add" << std::endl; +#endif + add = true; + } + else + { + /* check head of list */ + bdPeer &peer = buck.entries.front(); + if (ts - peer.mLastRecvTime > BITDHT_MAX_RECV_PERIOD) + { +#ifdef DEBUG_BD_SPACE + std::cerr << "Dropping Out-of-Date peer in bucket" << std::endl; +#endif + buck.entries.pop_front(); + add = true; + } + else if (peerflags > minScore) + { + /* find one to drop */ + for(it = buck.entries.begin(); it != buck.entries.end(); it++) + { + if (it->mPeerFlags == minScore) + { + /* delete low priority peer */ + it = buck.entries.erase(it); + add = true; + break; + } + } + +#ifdef DEBUG_BD_SPACE + std::cerr << "Inserting due to Priority: minScore: " << minScore + << " new Peer Score: " << peerscore << << std::endl; +#endif + } + else + { +#ifdef DEBUG_BD_SPACE + std::cerr << "No Out-Of-Date peers in bucket... dropping new entry" << std::endl; +#endif + } + } + + if (add) + { + bdPeer newPeer; + + newPeer.mPeerId = *id; + newPeer.mLastRecvTime = ts; + newPeer.mLastSendTime = 0; // ts; //???? + newPeer.mFoundTime = ts; + newPeer.mPeerFlags = peerflags; + newPeer.mExtraFlags = 0; + + buck.entries.push_back(newPeer); + +#ifdef DEBUG_BD_SPACE + /* useful debug */ + std::cerr << "bdSpace::add_peer() Added Bucket["; + std::cerr << bucket << "] Entry: "; + mFns->bdPrintId(std::cerr, id); + std::cerr << std::endl; +#endif + } + return add; +} + + + +/* print tables. + */ + +int bdSpace::printDHT() +{ + std::map closest; + std::map::iterator mit; + + std::vector::iterator it; + std::list::iterator eit; + + /* iterate through the buckets, and sort by distance */ + int i = 0; + +#ifdef BITDHT_DEBUG + fprintf(stderr, "bdSpace::printDHT()\n"); + for(it = buckets.begin(); it != buckets.end(); it++, i++) + { + if (it->entries.size() > 0) + { + fprintf(stderr, "Bucket %d ----------------------------\n", i); + } + + for(eit = it->entries.begin(); eit != it->entries.end(); eit++) + { + bdMetric dist; + mFns->bdDistance(&(mOwnId), &(eit->mPeerId.id), &dist); + + fprintf(stderr, " Metric: "); + mFns->bdPrintNodeId(std::cerr, &(dist)); + fprintf(stderr, " Id: "); + mFns->bdPrintId(std::cerr, &(eit->mPeerId)); + fprintf(stderr, " PeerFlags: %08x", eit->mPeerFlags); + fprintf(stderr, "\n"); + } + } +#endif + + fprintf(stderr, "--------------------------------------\n"); + fprintf(stderr, "DHT Table Summary --------------------\n"); + fprintf(stderr, "--------------------------------------\n"); + + /* little summary */ + unsigned long long sum = 0; + unsigned long long no_peers = 0; + uint32_t count = 0; + bool doPrint = false; + bool doAvg = false; + + i = 0; + for(it = buckets.begin(); it != buckets.end(); it++, i++) + { + int size = it->entries.size(); + int shift = BITDHT_KEY_BITLEN - i; + bool toBig = false; + + if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1) + { + toBig = true; + shift = BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1; + } + unsigned long long no_nets = ((unsigned long long) 1 << shift); + + /* use doPrint so it acts as a single switch */ + if (size && !doAvg && !doPrint) + { + doAvg = true; + } + + if (size && !doPrint) + { + doPrint = true; + } + + if (size == 0) + { + /* reset counters - if empty slot - to discount outliers in average */ + sum = 0; + no_peers = 0; + count = 0; + } + + if (doPrint) + { + if (size) + fprintf(stderr, "Bucket %d: %d peers: ", i, size); +#ifdef BITDHT_DEBUG + else + fprintf(stderr, "Bucket %d: %d peers: ", i, size); +#endif + } + if (toBig) + { + if (size) + { + if (doPrint) + fprintf(stderr, "Estimated NetSize >> %llu\n", no_nets); + } + else + { +#ifdef BITDHT_DEBUG + if (doPrint) + fprintf(stderr, " Bucket = Net / >> %llu\n", no_nets); +#endif + } + } + else + { + no_peers = no_nets * size; + if (size) + { + if (doPrint) + fprintf(stderr, "Estimated NetSize = %llu\n", no_peers); + } + else + { + +#ifdef BITDHT_DEBUG + if (doPrint) + fprintf(stderr, " Bucket = Net / %llu\n", no_nets); +#endif + + } + } + if (doPrint && doAvg && !toBig) + { + if (size == mFns->bdNodesPerBucket()) + { + /* last average */ + doAvg = false; + } + if (no_peers != 0) + { + sum += no_peers; + count++; +#ifdef BITDHT_DEBUG + fprintf(stderr, "Est: %d: %llu => %llu / %d\n", + i, no_peers, sum, count); +#endif + } + } + + } + if (count == 0) + { + fprintf(stderr, "Zero Network Size (count = 0)\n"); + } + else + { + fprintf(stderr, "Estimated Network Size = (%llu / %d) = %llu\n", sum, count, sum / count); + } + + return 1; +} + + +int bdSpace::getDhtBucket(const int idx, bdBucket &bucket) +{ + if ((idx < 0) || (idx > (int) buckets.size() - 1 )) + { + return 0; + } + bucket = buckets[idx]; + return 1; +} + +uint32_t bdSpace::calcNetworkSize() +{ + std::vector::iterator it; + + /* little summary */ + unsigned long long sum = 0; + unsigned long long no_peers = 0; + uint32_t count = 0; + bool doPrint = false; + bool doAvg = false; + + int i = 0; + for(it = buckets.begin(); it != buckets.end(); it++, i++) + { + int size = it->entries.size(); + int shift = BITDHT_KEY_BITLEN - i; + bool toBig = false; + + if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1) + { + toBig = true; + shift = BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1; + } + unsigned long long no_nets = ((unsigned long long) 1 << shift); + + /* use doPrint so it acts as a single switch */ + if (size && !doAvg && !doPrint) + { + doAvg = true; + } + + if (size && !doPrint) + { + doPrint = true; + } + + if (size == 0) + { + /* reset counters - if empty slot - to discount outliers in average */ + sum = 0; + no_peers = 0; + count = 0; + } + + if (!toBig) + { + no_peers = no_nets * size; + } + + if (doPrint && doAvg && !toBig) + { + if (size == mFns->bdNodesPerBucket()) + { + /* last average */ + doAvg = false; + } + if (no_peers != 0) + { + sum += no_peers; + count++; + } + } + } + + + uint32_t NetSize = 0; + if (count != 0) + { + NetSize = sum / count; + } + + //std::cerr << "bdSpace::calcNetworkSize() : " << NetSize; + //std::cerr << std::endl; + + return NetSize; +} + +uint32_t bdSpace::calcNetworkSizeWithFlag(uint32_t withFlag) +{ + std::vector::iterator it; + + /* little summary */ + unsigned long long sum = 0; + unsigned long long no_peers = 0; + uint32_t count = 0; + uint32_t totalcount = 0; + bool doPrint = false; + bool doAvg = false; + + int i = 0; + for(it = buckets.begin(); it != buckets.end(); it++, i++) + { + int size = 0; + std::list::iterator lit; + for(lit = it->entries.begin(); lit != it->entries.end(); lit++) + { + if (withFlag & lit->mPeerFlags) + { + size++; + } + } + + totalcount += size; + + int shift = BITDHT_KEY_BITLEN - i; + bool toBig = false; + + if (shift > BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1) + { + toBig = true; + shift = BITDHT_ULLONG_BITS - mFns->bdBucketBitSize() - 1; + } + unsigned long long no_nets = ((unsigned long long) 1 << shift); + + + /* use doPrint so it acts as a single switch */ + if (size && !doAvg && !doPrint) + { + doAvg = true; + } + + if (size && !doPrint) + { + doPrint = true; + } + + if (size == 0) + { + /* reset counters - if empty slot - to discount outliers in average */ + sum = 0; + no_peers = 0; + count = 0; + } + + if (!toBig) + { + no_peers = no_nets * size; + } + + if (doPrint && doAvg && !toBig) + { + if (size == mFns->bdNodesPerBucket()) + { + /* last average */ + doAvg = false; + } + if (no_peers != 0) + { + sum += no_peers; + count++; + } + } + } + + + uint32_t NetSize = 0; + if (count != 0) + { + NetSize = sum / count; + } + + //std::cerr << "bdSpace::calcNetworkSize() : " << NetSize; + //std::cerr << std::endl; + + return NetSize; +} + + +uint32_t bdSpace::calcSpaceSize() +{ + std::vector::iterator it; + + /* little summary */ + uint32_t totalcount = 0; + for(it = buckets.begin(); it != buckets.end(); it++) + { + totalcount += it->entries.size(); + } + return totalcount; +} + +uint32_t bdSpace::calcSpaceSizeWithFlag(uint32_t withFlag) +{ + std::vector::iterator it; + + /* little summary */ + uint32_t totalcount = 0; + + it = buckets.begin(); + if (it != buckets.end()) + { + it++; /* skip own bucket! */ + } + for(; it != buckets.end(); it++) + { + int size = 0; + std::list::iterator lit; + for(lit = it->entries.begin(); lit != it->entries.end(); lit++) + { + if (withFlag & lit->mPeerFlags) + { + size++; + } + } + totalcount += size; + } + return totalcount; +} + + /* special function to enable DHT localisation (i.e find peers from own network) */ +bool bdSpace::findRandomPeerWithFlag(bdId &id, uint32_t withFlag) +{ + std::vector::iterator it; + uint32_t totalcount = calcSpaceSizeWithFlag(withFlag); + + if(totalcount == 0) + return false ; + + uint32_t rnd = bdRandom::random_u32() % totalcount; + uint32_t i = 0; + uint32_t buck = 0; + + //std::cerr << "bdSpace::findRandomPeerWithFlag()"; + //std::cerr << std::endl; + + it = buckets.begin(); + if (it != buckets.end()) + { + it++; /* skip own bucket! */ + buck++; + } + for(; it != buckets.end(); it++, buck++) + { + std::list::iterator lit; + for(lit = it->entries.begin(); lit != it->entries.end(); lit++) + { + if (withFlag & lit->mPeerFlags) + { + if (i == rnd) + { +#ifdef BITDHT_DEBUG + std::cerr << "bdSpace::findRandomPeerWithFlag() found #" << i; + std::cerr << " in bucket #" << buck; + std::cerr << std::endl; +#endif + /* found */ + id = lit->mPeerId; + return true; + } + i++; + } + } + } + std::cerr << "bdSpace::findRandomPeerWithFlag() failed to find " << rnd << " / " << totalcount; + std::cerr << std::endl; +#ifdef BITDHT_DEBUG +#endif + + return false; +} + diff --git a/libbitdht/src/bitdht/bdpeer.h b/libbitdht/src/bitdht/bdpeer.h new file mode 100644 index 000000000..65b931f3c --- /dev/null +++ b/libbitdht/src/bitdht/bdpeer.h @@ -0,0 +1,209 @@ +#ifndef BITDHT_PEER_H +#define BITDHT_PEER_H + +/* + * bitdht/bdpeer.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bitdht/bdiface.h" +#include + +/******* + * These type of parameters are now DHT Function dependent + * +#define BITDHT_BUCKET_SIZE 20 +#define BITDHT_BUCKET_SIZE_BITS 5 + +#define BITDHT_N_BUCKETS BITDHT_KEY_BITLEN + * + * + ***/ + +/*** + * DEFINED in bdiface.h + * #define BITDHT_KEY_LEN 20 + * #define BITDHT_KEY_INTLEN 5 + * #define BITDHT_KEY_BITLEN 160 + ***/ + +#define BITDHT_ULLONG_BITS 64 + +#define BITDHT_MAX_RESPONSE_PERIOD (15) +#define BITDHT_MAX_SEND_PERIOD 300 // 5 minutes. +#define BITDHT_MAX_RECV_PERIOD (BITDHT_MAX_SEND_PERIOD + BITDHT_MAX_RESPONSE_PERIOD) // didn't respond to a ping. + +// Properly out of date. +#define BITDHT_DISCARD_PERIOD (2 * BITDHT_MAX_SEND_PERIOD + BITDHT_MAX_RESPONSE_PERIOD) // didn't respond to two pings. + +// Must have a FLAG by this time. (Make it really quick - so we through away the rubbish). + + +#include +#include +#include +#include + +/**** + * DEFINED in bdiface.h + * + * class bdNodeId + * { + * public: + * unsigned char data[BITDHT_KEY_LEN]; + * }; + ****/ + + +/**** + * DEFINED in bdiface.h + * + +class bdMetric: public bdNodeId {}; + +class bdId +{ + public: + + bdId(); + bdId(bdNodeId in_id, struct sockaddr_in in_addr); + + struct sockaddr_in addr; + bdNodeId id; +}; + * + *********/ + + + +//void bdRandomNodeId(bdNodeId *id); + +// Only Functions that are common for all Dhts. +// zero, basic comparisons.. +void bdZeroNodeId(bdNodeId *id); + +//void bdRandomId(bdId *id); +//int bdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r); +//int bdBucketDistance(const bdMetric *m); +//int bdBucketDistance(const bdNodeId *a, const bdNodeId *b); +//int operator<(const bdMetric &a, const bdMetric &b); + +//int operator<(const struct sockaddr_in &a, const struct sockaddr_in &b); + +int operator<(const bdNodeId &a, const bdNodeId &b); +int operator<(const bdId &a, const bdId &b); +int operator==(const bdNodeId &a, const bdNodeId &b); +int operator==(const bdId &a, const bdId &b); + +//void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); + +//void bdPrintId(std::ostream &out, const bdId *a); +//void bdPrintNodeId(std::ostream &out, const bdNodeId *a); + +//std::string bdConvertToPrintable(std::string input); + +/**** + * DEFINED in bdiface.h + * + +class bdPeer +{ + public: + + bdId mPeerId; + uint32_t mPeerFlags; + time_t mLastSendTime; + time_t mLastRecvTime; + time_t mFoundTime; // time stamp that peer was found +}; + + +class bdBucket +{ + public: + + bdBucket(); + + // list so we can queue properly + std::list entries; +}; + * + * + *****/ + +class bdSpace +{ + public: + + bdSpace(bdNodeId *ownId, bdDhtFunctions *fns); + +int clear(); + +int setAttachedFlag(uint32_t withflags, int count); + + /* accessors */ +int find_nearest_nodes(const bdNodeId *id, int number, + std::multimap &nearest); + +int find_nearest_nodes_with_flags(const bdNodeId *id, int number, + std::list excluding, + std::multimap &nearest, uint32_t with_flag); + +int find_node(const bdNodeId *id, int number, + std::list &matchIds, uint32_t with_flag); +int find_exactnode(const bdId *id, bdPeer &peer); + +// switched to more efficient single sweep. +//int out_of_date_peer(bdId &id); // side-effect updates, send flag on peer. +int scanOutOfDatePeers(std::list &peerIds); +int updateAttachedPeers(); + +int add_peer(const bdId *id, uint32_t mode); +int printDHT(); +int getDhtBucket(const int idx, bdBucket &bucket); + +uint32_t calcNetworkSize(); +uint32_t calcNetworkSizeWithFlag(uint32_t withFlag); +uint32_t calcSpaceSize(); +uint32_t calcSpaceSizeWithFlag(uint32_t withFlag); + + /* special function to enable DHT localisation (i.e find peers from own network) */ +bool findRandomPeerWithFlag(bdId &id, uint32_t withFlag); + + /* to add later */ +int updateOwnId(bdNodeId *newOwnId); + + private: + + std::vector buckets; + bdNodeId mOwnId; + bdDhtFunctions *mFns; + + uint32_t mAttachedFlags; + uint32_t mAttachedCount; + time_t mAttachTS; +}; + + +#endif + diff --git a/libbitdht/src/bitdht/bdquery.cc b/libbitdht/src/bitdht/bdquery.cc new file mode 100644 index 000000000..a746b2cf3 --- /dev/null +++ b/libbitdht/src/bitdht/bdquery.cc @@ -0,0 +1,1021 @@ + +/* + * bitdht/bdquery.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdquery.h" +#include "util/bdnet.h" + +#include +#include +#include + +/** + * #define DEBUG_QUERY 1 +**/ + + +#define EXPECTED_REPLY 10 // Speed up queries +#define QUERY_IDLE_RETRY_PEER_PERIOD 300 // 5min = (mFns->bdNodesPerBucket() * 30) + + +/************************************************************ + * bdQuery logic: + * 1) as replies come in ... maintain list of M closest peers to ID. + * 2) select non-queried peer from list, and query. + * 3) halt when we have asked all M closest peers about the ID. + * + * Flags can be set to disguise the target of the search. + * This involves + */ + +bdQuery::bdQuery(const bdNodeId *id, std::list &startList, uint32_t queryFlags, + bdDhtFunctions *fns) +{ + /* */ + mId = *id; + mFns = fns; + + time_t now = time(NULL); + std::list::iterator it; + for(it = startList.begin(); it != startList.end(); it++) + { + bdPeer peer; + peer.mLastSendTime = 0; + peer.mLastRecvTime = 0; + peer.mPeerFlags = 0; + peer.mFoundTime = now; + peer.mPeerId = *it; + + bdMetric dist; + + mFns->bdDistance(&mId, &(peer.mPeerId.id), &dist); + + mClosest.insert(std::pair(dist, peer)); + + + } + + mState = BITDHT_QUERY_QUERYING; + mQueryFlags = queryFlags; + mQueryTS = now; + mSearchTime = 0; + mClosestListSize = (int) (1.5 * mFns->bdNodesPerBucket()); + + mQueryIdlePeerRetryPeriod = QUERY_IDLE_RETRY_PEER_PERIOD; + mRequiredPeerFlags = BITDHT_PEER_STATUS_DHT_ENGINE_VERSION; // XXX to update later. + + /* setup the limit of the search + * by default it is setup to 000000 = exact match + */ + bdZeroNodeId(&mLimit); +} + +bool bdQuery::result(std::list &answer) +{ + /* get all the matches to our query */ + std::multimap::iterator sit, eit; + sit = mClosest.begin(); + eit = mClosest.upper_bound(mLimit); + int i = 0; + for(; sit != eit; sit++, i++) + { + answer.push_back(sit->second.mPeerId); + } + return (i > 0); +} + + +int bdQuery::nextQuery(bdId &id, bdNodeId &targetNodeId) +{ + if ((mState != BITDHT_QUERY_QUERYING) && !(mQueryFlags & BITDHT_QFLAGS_DO_IDLE)) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "NextQuery() Query is done\n"); +#endif + return 0; + } + + /* search through through list, find closest not queried */ + time_t now = time(NULL); + + /* update IdlePeerRetry */ + if ((now - mQueryTS) / 2 > mQueryIdlePeerRetryPeriod) + { + mQueryIdlePeerRetryPeriod = (now-mQueryTS) / 2; + } + + bool notFinished = false; + std::multimap::iterator it; + int i = 0; + for(it = mClosest.begin(); it != mClosest.end(); it++, i++) + { + bool queryPeer = false; + + /* if never queried */ + if (it->second.mLastSendTime == 0) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "NextQuery() Found non-sent peer. queryPeer = true : "); + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + std::cerr << std::endl; +#endif + queryPeer = true; + } + + /* re-request every so often */ + if ((!queryPeer) && (mQueryFlags & BITDHT_QFLAGS_DO_IDLE) && + (now - it->second.mLastSendTime > mQueryIdlePeerRetryPeriod)) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "NextQuery() Found out-of-date. queryPeer = true : "); + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + std::cerr << std::endl; +#endif + queryPeer = true; + } + + /* expecting every peer to be up-to-date is too hard... + * enough just to have received lists from each + * - replacement policy will still work. + * + * Need to wait at least EXPECTED_REPLY, to make sure their answers are pinged + */ + + if (((it->second.mLastRecvTime == 0) || (now - it->second.mLastRecvTime < EXPECTED_REPLY)) && + (i < mFns->bdNodesPerBucket())) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "NextQuery() Never Received @Idx(%d) notFinished = true: ", i); + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + std::cerr << std::endl; +#endif + notFinished = true; + } + + if (queryPeer) + { + id = it->second.mPeerId; + it->second.mLastSendTime = now; + + if (mQueryFlags & BITDHT_QFLAGS_DISGUISE) + { + /* calc Id mid point between Target and Peer */ + bdNodeId midRndId; + mFns->bdRandomMidId(&mId, &(id.id), &midRndId); + + targetNodeId = midRndId; + } + else + { + targetNodeId = mId; + } +#ifdef DEBUG_QUERY + fprintf(stderr, "NextQuery() Querying Peer: "); + mFns->bdPrintId(std::cerr, &id); + std::cerr << std::endl; +#endif + return 1; + } + } + + /* allow query to run for a minimal amount of time + * This is important as startup - when we might not have any peers. + * Probably should be handled elsewhere. + */ + time_t age = now - mQueryTS; + + if (age < BITDHT_MIN_QUERY_AGE) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "NextQuery() under Min Time: Query not finished / No Query\n"); +#endif + return 0; + } + + if (age > BITDHT_MAX_QUERY_AGE) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "NextQuery() under Min Time: Query not finished / No Query\n"); +#endif + /* fall through and stop */ + } + else if ((mClosest.size() < mFns->bdNodesPerBucket()) || (notFinished)) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "NextQuery() notFinished | !size(): Query not finished / No Query\n"); +#endif + /* not full yet... */ + return 0; + } + +#ifdef DEBUG_QUERY + fprintf(stderr, "NextQuery() Finished\n"); +#endif + + /* if we get here - query finished */ + if (mState == BITDHT_QUERY_QUERYING) + { + /* store query time */ + mSearchTime = now - mQueryTS; + } + + /* check if we found the node */ + if (mClosest.size() > 0) + { + if ((mClosest.begin()->second).mPeerId.id == mId) + { + mState = BITDHT_QUERY_SUCCESS; + } + else if ((mPotentialPeers.begin()->second).mPeerId.id == mId) + { + mState = BITDHT_QUERY_PEER_UNREACHABLE; + } + else + { + mState = BITDHT_QUERY_FOUND_CLOSEST; + } + } + else + { + mState = BITDHT_QUERY_FAILURE; + } + return 0; +} + +int bdQuery::addClosestPeer(const bdId *id, uint32_t mode) +{ + bdMetric dist; + time_t ts = time(NULL); + + mFns->bdDistance(&mId, &(id->id), &dist); + +#ifdef DEBUG_QUERY + fprintf(stderr, "bdQuery::addPeer("); + mFns->bdPrintId(std::cerr, id); + fprintf(stderr, ", %u)\n", mode); +#endif + + std::multimap::iterator it, sit, eit; + sit = mClosest.lower_bound(dist); + eit = mClosest.upper_bound(dist); + int i = 0; + int actualCloser = 0; + int toDrop = 0; + // switched end condition to upper_bound to provide stability for NATTED peers. + // we will favour the older entries! + for(it = mClosest.begin(); it != eit; it++, i++, actualCloser++) + { + time_t sendts = ts - it->second.mLastSendTime; + bool hasSent = (it->second.mLastSendTime != 0); + bool hasReply = (it->second.mLastRecvTime >= it->second.mLastSendTime); + if ((hasSent) && (!hasReply) && (sendts > EXPECTED_REPLY)) + { + i--; /* dont count this one */ + toDrop++; + } + } + // Counts where we are. +#ifdef DEBUG_QUERY + fprintf(stderr, "Searching.... %di = %d - %d peers closer than this one\n", i, actualCloser, toDrop); +#endif + + + if (i > mClosestListSize - 1) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "Distance to far... dropping\n"); +#endif + /* drop it */ + return 0; + } + + for(it = sit; it != eit; it++, i++) + { + /* full id check */ + if (mFns->bdSimilarId(id, &(it->second.mPeerId))) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "Peer Already here!\n"); +#endif + if (mode) + { + /* also update port from incoming id, as we have definitely recved from it */ + if (mFns->bdUpdateSimilarId(&(it->second.mPeerId), id)) + { + /* updated it... must be Unstable */ + it->second.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; + } + } + if (mode & BITDHT_PEER_STATUS_RECV_NODES) + { + /* only update recvTime if sendTime > checkTime.... (then its our query) */ +#ifdef DEBUG_QUERY + fprintf(stderr, "Updating LastRecvTime\n"); +#endif + it->second.mLastRecvTime = ts; + it->second.mPeerFlags |= mode; + } + return 1; + } + } + +#ifdef DEBUG_QUERY + fprintf(stderr, "Peer not in Query\n"); +#endif + /* firstly drop unresponded (bit ugly - but hard structure to extract from) */ + int j; + for(j = 0; j < toDrop; j++) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "Dropping Peer that dont reply\n"); +#endif + bool removed = false; + for(it = mClosest.begin(); it != mClosest.end(); ++it) + { + time_t sendts = ts - it->second.mLastSendTime; + bool hasSent = (it->second.mLastSendTime != 0); + bool hasReply = (it->second.mLastRecvTime >= it->second.mLastSendTime); + + if ((hasSent) && (!hasReply) && (sendts > EXPECTED_REPLY)) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "Dropped: "); + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + fprintf(stderr, "\n"); +#endif + mClosest.erase(it); + removed = true; + break ; + } + } + } + + /* trim it back */ + while(mClosest.size() > (uint32_t) (mClosestListSize - 1)) + { + std::multimap::iterator it; + it = mClosest.end(); + if (!mClosest.empty()) + { + it--; +#ifdef DEBUG_QUERY + fprintf(stderr, "Removing Furthest Peer: "); + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + fprintf(stderr, "\n"); +#endif + + mClosest.erase(it); + } + } + +#ifdef DEBUG_QUERY + fprintf(stderr, "bdQuery::addPeer(): Closer Peer!: "); + mFns->bdPrintId(std::cerr, id); + fprintf(stderr, "\n"); +#endif + + /* add it in */ + bdPeer peer; + peer.mPeerId = *id; + peer.mPeerFlags = mode; + peer.mLastSendTime = 0; + peer.mLastRecvTime = 0; + peer.mFoundTime = ts; + + if (mode & BITDHT_PEER_STATUS_RECV_NODES) + { + peer.mLastRecvTime = ts; + } + + mClosest.insert(std::pair(dist, peer)); + return 1; +} + + +/******************************************************************************************* + ********************************* Add Peer Interface ************************************* + *******************************************************************************************/ + +/**** These functions are called by bdNode to add peers to the query + * They add/update the three sets of lists. + * + * int bdQuery::addPeer(const bdId *id, uint32_t mode) + * Proper message from a peer. + * + * int bdQuery::addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode) + * This returns 1 if worthy of pinging, 0 if to ignore. + */ + +#define PEER_MESSAGE 0 +#define FIND_NODE_RESPONSE 1 + +int bdQuery::addPeer(const bdId *id, uint32_t mode) +{ + addClosestPeer(id, mode); + updatePotentialPeer(id, mode, PEER_MESSAGE); + updateProxy(id, mode); + return 1; +} + +int bdQuery::addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode) +{ + // is it a Potential Proxy? Always Check This. + addProxy(id, src, srcmode); + + int worthy = worthyPotentialPeer(id); + int shouldPing = 0; + if (worthy) + { + shouldPing = updatePotentialPeer(id, 0, FIND_NODE_RESPONSE); + } + return shouldPing; +} + + +/******************************************************************************************* + ********************************* Closest Peer ******************************************** + *******************************************************************************************/ + + +/******************************************************************************************* + ******************************** Potential Peer ******************************************* + *******************************************************************************************/ + + + + +/******* + * Potential Peers are a list of the closest answers to our queries. + * Lots of these peers will not be reachable.... so will only exist in this list. + * They will also never have there PeerFlags set ;( + * + */ + + +/*** utility functions ***/ + +int bdQuery::worthyPotentialPeer(const bdId *id) +{ + bdMetric dist; + mFns->bdDistance(&mId, &(id->id), &dist); + +#ifdef DEBUG_QUERY + fprintf(stderr, "bdQuery::addPotentialPeer("); + mFns->bdPrintId(std::cerr, id); + fprintf(stderr, ", %u)\n", mode); +#endif + + /* we check if this is a worthy potential peer.... + * if it is already in mClosest -> false. old peer. + * if it is > mClosest.rbegin() -> false. too far way. + */ + int retval = 1; + + std::multimap::iterator it, sit, eit; + sit = mClosest.lower_bound(dist); + eit = mClosest.upper_bound(dist); + + /* check if outside range, & bucket is full */ + if ((sit == mClosest.end()) && (mClosest.size() >= mFns->bdNodesPerBucket())) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "Peer to far away for Potential\n"); +#endif + return 0; /* too far way */ + } + + + for(it = sit; it != eit; it++) + { + if (mFns->bdSimilarId(id, &(it->second.mPeerId))) + { + // Not updating Full Peer Id here... as inspection function. +#ifdef DEBUG_QUERY + fprintf(stderr, "Peer already in mClosest\n"); +#endif + return 0; + } + } + + return 1; /* either within mClosest Range (but not there!), or there aren't enough peers */ +} + + +/***** + * + * mLastSendTime ... is the last FIND_NODE_RESPONSE that we returned 1. (indicating to PING). + * mLastRecvTime ... is the last time we received an updatei about/from them + * + * The update is dependent on the flags passed in the function call. (saves duplicate code). + * + * + * XXX IMPORTANT TO DECIDE WHAT IS RETURNED HERE. + * original algorithm return 0 if exists in potential peers, 1 if unknown. + * This is used to limit the number of pings to non-responding potentials. + * + * MUST think about this. Need to install HISTORY tracking again. to look at the statistics. + * + * It is important that the potential Peers list extends all the way back to == mClosest().end(). + * Otherwise we end up with [TARGET] .... [ POTENTIAL ] ..... [ CLOSEST ] ...... + * and the gap between POT and CLOSEST will get hammered with pings. + * + */ + +#define MIN_PING_POTENTIAL_PERIOD 300 + +int bdQuery::updatePotentialPeer(const bdId *id, uint32_t mode, uint32_t addType) +{ + bdMetric dist; + time_t now = time(NULL); + + mFns->bdDistance(&mId, &(id->id), &dist); + + std::multimap::iterator it, sit, eit; + sit = mPotentialPeers.lower_bound(dist); + eit = mPotentialPeers.upper_bound(dist); + + bool found = false; + for(it = sit; it != eit; it++) + { + if (mFns->bdSimilarId(id, &(it->second.mPeerId))) + { + found = true; + + it->second.mPeerFlags |= mode; + it->second.mLastRecvTime = now; + if (addType == FIND_NODE_RESPONSE) + { + // We could lose peers here by not updating port... but should be okay. + if (now - it->second.mLastSendTime > MIN_PING_POTENTIAL_PERIOD) + { + it->second.mLastSendTime = now; + return 1; + } + } + else if (mode) + { + /* also update port from incoming id, as we have definitely recved from it */ + if (mFns->bdUpdateSimilarId(&(it->second.mPeerId), id)) + { + /* updated it... must be Unstable */ + it->second.mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; + } + } + return 0; + } + } + +// Removing this check - so that we can have varying length PotentialPeers. +// Peer will always be added, then probably removed straight away. + +#if 0 + /* check if outside range, & bucket is full */ + if ((sit == mPotentialPeers.end()) && (mPotentialPeers.size() >= mFns->bdNodesPerBucket())) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "Peer to far away for Potential\n"); +#endif + return 0; + } +#endif + + /* add it in */ + bdPeer peer; + peer.mPeerId = *id; + peer.mPeerFlags = mode; + peer.mFoundTime = now; + peer.mLastRecvTime = now; + peer.mLastSendTime = 0; + if (addType == FIND_NODE_RESPONSE) + { + peer.mLastSendTime = now; + } + + mPotentialPeers.insert(std::pair(dist, peer)); + +#ifdef DEBUG_QUERY + fprintf(stderr, "Flagging as Potential Peer!\n"); +#endif + + trimPotentialPeers_toClosest(); + + return 1; +} + + +int bdQuery::trimPotentialPeers_FixedLength() +{ + /* trim it back */ + while(mPotentialPeers.size() > (uint32_t) (mFns->bdNodesPerBucket())) + { + std::multimap::iterator it; + it = mPotentialPeers.end(); + it--; // must be more than 1 peer here? +#ifdef DEBUG_QUERY + fprintf(stderr, "Removing Furthest Peer: "); + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + fprintf(stderr, "\n"); +#endif + mPotentialPeers.erase(it); + } + return 1; +} + + +int bdQuery::trimPotentialPeers_toClosest() +{ + if (mPotentialPeers.size() <= (uint32_t) (mFns->bdNodesPerBucket())) + return 1; + + std::multimap::reverse_iterator it; + it = mClosest.rbegin(); + bdMetric lastClosest = it->first; + + /* trim it back */ + while(mPotentialPeers.size() > (uint32_t) (mFns->bdNodesPerBucket())) + { + std::multimap::iterator it; + it = mPotentialPeers.end(); + it--; // must be more than 1 peer here? + if (lastClosest < it->first) + { +#ifdef DEBUG_QUERY + fprintf(stderr, "Removing Furthest Peer: "); + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + fprintf(stderr, "\n"); +#endif + mPotentialPeers.erase(it); + } + else + { + return 1; + } + } + return 1; +} + + + +/******************************************************************************************* + ******************************** Potential Proxies **************************************** + *******************************************************************************************/ + +/******** + * Potential Proxies. a list of peers that have returned our target in response to a query. + * + * We are particularly interested in peers with specific flags... + * But all the peers have been pinged already by the time they reach this list. + * So there are two options: + * 1) Track everythings mode history - which is a waste of resources. + * 2) Store the list, and ping later. + * + * We will store these in two lists: Flags & Unknown. + * we keep the most recent of each, and move around as required. + * + * we could also check the Closest/PotentialPeer lists to grab the flags, + * for an unknown peer? + * + * All Functions manipulating PotentialProxies are here. + * We need several functions: + * + * For Extracting Proxies. +bool bdQuery::proxies(std::list &answer) +bool bdQuery::potentialProxies(std::list &answer) + * + * For Adding/Updating Proxies. +int bdQuery::addProxy(const bdId *id, const bdId *src, uint32_t srcmode) +int bdQuery::updateProxy(const bdId *id, uint32_t mode) + * + */ + +/*** Two Functions to extract Proxies... ***/ +bool bdQuery::proxies(std::list &answer) +{ + /* get all the matches to our query */ + std::list::iterator it; + int i = 0; + for(it = mProxiesFlagged.begin(); it != mProxiesFlagged.end(); it++, i++) + { + answer.push_back(it->mPeerId); + } + return (i > 0); +} + +bool bdQuery::potentialProxies(std::list &answer) +{ + /* get all the matches to our query */ + std::list::iterator it; + int i = 0; + for(it = mProxiesUnknown.begin(); it != mProxiesUnknown.end(); it++, i++) + { + answer.push_back(it->mPeerId); + } + return (i > 0); +} + + + +int bdQuery::addProxy(const bdId *id, const bdId *src, uint32_t srcmode) +{ + bdMetric dist; + time_t now = time(NULL); + + mFns->bdDistance(&mId, &(id->id), &dist); + + /* finally if it is an exact match, add as potential proxy */ + int bucket = mFns->bdBucketDistance(&dist); + if ((bucket != 0) || (src == NULL)) + { + /* not a potential proxy */ + return 0; + } + +#ifdef DEBUG_QUERY + fprintf(stderr, "Bucket = 0, Have Potential Proxy!\n"); +#endif + + bool found = false; + if (updateProxyList(src, srcmode, mProxiesUnknown)) + { + found = true; + } + + if (!found) + { + if (updateProxyList(src, srcmode, mProxiesFlagged)) + { + found = true; + } + } + + if (!found) + { + /* if we get here. its not in the list */ +#ifdef DEBUG_QUERY + fprintf(stderr, "Adding Source to Proxy List:\n"); +#endif + bdPeer peer; + peer.mPeerId = *src; + peer.mPeerFlags = srcmode; + peer.mLastSendTime = 0; + peer.mLastRecvTime = now; + peer.mFoundTime = now; + + /* add it in */ + if ((srcmode & mRequiredPeerFlags) == mRequiredPeerFlags) + { + mProxiesFlagged.push_front(peer); + } + else + { + mProxiesUnknown.push_front(peer); + } + } + + + trimProxies(); + + return 1; +} + + +int bdQuery::updateProxy(const bdId *id, uint32_t mode) +{ + if (!updateProxyList(id, mode, mProxiesUnknown)) + { + updateProxyList(id, mode, mProxiesFlagged); + } + + trimProxies(); + return 1; +} + + +/**** Utility functions that do all the work! ****/ + +int bdQuery::updateProxyList(const bdId *id, uint32_t mode, std::list &searchProxyList) +{ + std::list::iterator it; + for(it = searchProxyList.begin(); it != searchProxyList.end(); it++) + { + if (mFns->bdSimilarId(id, &(it->mPeerId))) + { + /* found it ;( */ +#ifdef DEBUG_QUERY + std::cerr << "bdQuery::updateProxyList() Found peer, updating"; + std::cerr << std::endl; +#endif + + time_t now = time(NULL); + if (mode) + { + /* also update port from incoming id, as we have definitely recved from it */ + if (mFns->bdUpdateSimilarId(&(it->mPeerId), id)) + { + /* updated it... must be Unstable */ + it->mExtraFlags |= BITDHT_PEER_EXFLAG_UNSTABLE; + } + } + it->mPeerFlags |= mode; + it->mLastRecvTime = now; + + /* now move it to the front of required list... + * note this could be exactly the same list as &searchProxyList, or a different one! + */ + + bdPeer peer = *it; + it = searchProxyList.erase(it); + + if ((peer.mPeerFlags & mRequiredPeerFlags) == mRequiredPeerFlags) + { + mProxiesFlagged.push_front(peer); + } + else + { + mProxiesUnknown.push_front(peer); + } + + return 1; + break; + } + } + + return 0; +} + +#define MAX_POTENTIAL_PROXIES 10 + +int bdQuery::trimProxies() +{ + + /* drop excess Potential Proxies */ + while(mProxiesUnknown.size() > MAX_POTENTIAL_PROXIES) + { + mProxiesUnknown.pop_back(); + } + + while(mProxiesFlagged.size() > MAX_POTENTIAL_PROXIES) + { + mProxiesFlagged.pop_back(); + } + return 1; +} + + +/******************************************************************************************* + ******************************** Potential Proxies **************************************** + *******************************************************************************************/ + + + +/* print query. + */ + +int bdQuery::printQuery() +{ +#ifdef DEBUG_QUERY + fprintf(stderr, "bdQuery::printQuery()\n"); +#endif + + time_t ts = time(NULL); + fprintf(stderr, "Query for: "); + mFns->bdPrintNodeId(std::cerr, &mId); + fprintf(stderr, " Query State: %d", mState); + fprintf(stderr, " Query Age %ld secs", ts-mQueryTS); + if (mState >= BITDHT_QUERY_FAILURE) + { + fprintf(stderr, " Search Time: %d secs", mSearchTime); + } + fprintf(stderr, "\n"); + +#ifdef DEBUG_QUERY + fprintf(stderr, "Closest Available Peers:\n"); + std::multimap::iterator it; + for(it = mClosest.begin(); it != mClosest.end(); it++) + { + fprintf(stderr, "Id: "); + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); + fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); + fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); + fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); + fprintf(stderr, "\n"); + } + + fprintf(stderr, "\nClosest Potential Peers:\n"); + for(it = mPotentialClosest.begin(); it != mPotentialClosest.end(); it++) + { + fprintf(stderr, "Id: "); + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); + fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); + fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); + fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); + fprintf(stderr, "\n"); + } + + std::list::iterator lit; + fprintf(stderr, "\nPotential Proxies:\n"); + for(lit = mPotentialProxies.begin(); lit != mPotentialProxies.end(); lit++) + { + fprintf(stderr, "ProxyId: "); + mFns->bdPrintId(std::cerr, &(lit->mPeerId)); + fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime); + fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime); + fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime); + fprintf(stderr, "\n"); + } +#else + // shortened version. + fprintf(stderr, "Closest Available Peer: "); + std::multimap::iterator it = mClosest.begin(); + if (it != mClosest.end()) + { + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); + fprintf(stderr," Flags: %x", it->second.mPeerFlags); + fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); + fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); + fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); + } + fprintf(stderr, "\n"); + + fprintf(stderr, "Closest Potential Peer: "); + it = mPotentialPeers.begin(); + if (it != mPotentialPeers.end()) + { + mFns->bdPrintId(std::cerr, &(it->second.mPeerId)); + fprintf(stderr, " Bucket: %d ", mFns->bdBucketDistance(&(it->first))); + fprintf(stderr," Flags: %x", it->second.mPeerFlags); + fprintf(stderr," Found: %ld ago", ts-it->second.mFoundTime); + fprintf(stderr," LastSent: %ld ago", ts-it->second.mLastSendTime); + fprintf(stderr," LastRecv: %ld ago", ts-it->second.mLastRecvTime); + } + fprintf(stderr, "\n"); + + std::list::iterator lit; + fprintf(stderr, "Flagged Proxies:\n"); + for(lit = mProxiesFlagged.begin(); lit != mProxiesFlagged.end(); lit++) + { + fprintf(stderr, "ProxyId: "); + mFns->bdPrintId(std::cerr, &(lit->mPeerId)); + fprintf(stderr," Flags: %x", it->second.mPeerFlags); + fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime); + fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime); + fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime); + fprintf(stderr, "\n"); + } + + fprintf(stderr, "Potential Proxies:\n"); + for(lit = mProxiesUnknown.begin(); lit != mProxiesUnknown.end(); lit++) + { + fprintf(stderr, "ProxyId: "); + mFns->bdPrintId(std::cerr, &(lit->mPeerId)); + fprintf(stderr," Flags: %x", it->second.mPeerFlags); + fprintf(stderr," Found: %ld ago", ts-lit->mFoundTime); + fprintf(stderr," LastSent: %ld ago", ts-lit->mLastSendTime); + fprintf(stderr," LastRecv: %ld ago", ts-lit->mLastRecvTime); + fprintf(stderr, "\n"); + } +#endif + + return 1; +} + + + + +/********************************* Remote Query **************************************/ +bdRemoteQuery::bdRemoteQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type) + :mId(*id), mQuery(*query), mTransId(*transId), mQueryType(query_type) +{ + mQueryTS = time(NULL); +} + + + + + diff --git a/libbitdht/src/bitdht/bdquery.h b/libbitdht/src/bitdht/bdquery.h new file mode 100644 index 000000000..e2d2a3069 --- /dev/null +++ b/libbitdht/src/bitdht/bdquery.h @@ -0,0 +1,128 @@ +#ifndef BITDHT_QUERY_H +#define BITDHT_QUERY_H + +/* + * bitdht/bdquery.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdiface.h" +#include "bitdht/bdpeer.h" +#include "bitdht/bdobj.h" + +/* Query result flags are in bdiface.h */ + +#define BITDHT_MIN_QUERY_AGE 10 +#define BITDHT_MAX_QUERY_AGE 1800 /* 30 minutes */ + +class bdQuery +{ + public: + bdQuery(const bdNodeId *id, std::list &startList, uint32_t queryFlags, + bdDhtFunctions *fns); + + // get the answer. +bool result(std::list &answer); +bool proxies(std::list &answer); +bool potentialProxies(std::list &answer); + + // returning results get passed to all queries. +//void addNode(const bdId *id, int mode); +int nextQuery(bdId &id, bdNodeId &targetId); +int addPeer(const bdId *id, uint32_t mode); +int addPotentialPeer(const bdId *id, const bdId *src, uint32_t srcmode); +int printQuery(); + + // searching for + bdNodeId mId; + bdMetric mLimit; + uint32_t mState; + time_t mQueryTS; + uint32_t mQueryFlags; + int32_t mSearchTime; + + int32_t mQueryIdlePeerRetryPeriod; // seconds between retries. + + //private: + + // Closest Handling Fns. +int addClosestPeer(const bdId *id, uint32_t mode); + + // Potential Handling Fns. +int worthyPotentialPeer(const bdId *id); +int updatePotentialPeer(const bdId *id, uint32_t mode, uint32_t addType); +int trimPotentialPeers_FixedLength(); +int trimPotentialPeers_toClosest(); + + // Proxy Handling Fns. +int addProxy(const bdId *id, const bdId *src, uint32_t srcmode); +int updateProxy(const bdId *id, uint32_t mode); +int updateProxyList(const bdId *id, uint32_t mode, std::list &searchProxyList); +int trimProxies(); + + + // closest peers. + std::multimap mClosest; + std::multimap mPotentialPeers; + + uint32_t mRequiredPeerFlags; + std::list mProxiesUnknown; + std::list mProxiesFlagged; + + int mClosestListSize; + bdDhtFunctions *mFns; +}; + +#if 0 + +class bdQueryStatus +{ + public: + uint32_t mStatus; + uint32_t mQFlags; + std::list mResults; +}; + +#endif + + + +/* this is just a container class. + * we locally seach for this, once then discard. + */ +class bdRemoteQuery +{ + public: + bdRemoteQuery(bdId *id, bdNodeId *query, bdToken *transId, uint32_t query_type); + + bdId mId; + bdNodeId mQuery; + bdToken mTransId; + uint32_t mQueryType; + + time_t mQueryTS; +}; + +#endif + diff --git a/libbitdht/src/bitdht/bdquerymgr.cc b/libbitdht/src/bitdht/bdquerymgr.cc new file mode 100644 index 000000000..fb78261f3 --- /dev/null +++ b/libbitdht/src/bitdht/bdquerymgr.cc @@ -0,0 +1,380 @@ +/* + * bitdht/bdnode.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bitdht/bdquerymgr.h" +#include "bitdht/bdnode.h" + +#include +#include +#include + +#include +#include +#include + + +#define BITDHT_QUERY_START_PEERS 10 +#define BITDHT_QUERY_NEIGHBOUR_PEERS 8 +#define BITDHT_MAX_REMOTE_QUERY_AGE 10 + +/**** + * #define DEBUG_NODE_MULTIPEER 1 + * #define DEBUG_NODE_MSGS 1 + * #define DEBUG_NODE_ACTIONS 1 + + * #define DEBUG_NODE_MSGIN 1 + * #define DEBUG_NODE_MSGOUT 1 + ***/ + +//#define DEBUG_NODE_MSGS 1 + + +bdQueryManager::bdQueryManager(bdSpace *space, bdDhtFunctions *fns, bdNodePublisher *pub) + :mNodeSpace(space), mFns(fns), mPub(pub) +{ +} + +/***** Startup / Shutdown ******/ +void bdQueryManager::shutdownQueries() +{ + /* clear the queries */ + std::list::iterator it; + for(it = mLocalQueries.begin(); it != mLocalQueries.end();it++) + { + delete (*it); + } + + mLocalQueries.clear(); +} + + +void bdQueryManager::printQueries() +{ + std::cerr << "bdQueryManager::printQueries()"; + std::cerr << std::endl; + + int i = 0; + std::list::iterator it; + for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++, i++) + { + fprintf(stderr, "Query #%d:\n", i); + (*it)->printQuery(); + fprintf(stderr, "\n"); + } +} + + +int bdQueryManager::iterateQueries(int maxQueries) +{ +#ifdef DEBUG_NODE_MULTIPEER + std::cerr << "bdQueryManager::iterateQueries() of Peer: "; + mFns->bdPrintNodeId(std::cerr, &mOwnId); + std::cerr << std::endl; +#endif + + /* allow each query to send up to one query... until maxMsgs has been reached */ + int numQueries = mLocalQueries.size(); + int sentQueries = 0; + int i = 0; + + bdId id; + bdNodeId targetNodeId; + + while((i < numQueries) && (sentQueries < maxQueries)) + { + bdQuery *query = mLocalQueries.front(); + mLocalQueries.pop_front(); + mLocalQueries.push_back(query); + + /* go through the possible queries */ + if (query->nextQuery(id, targetNodeId)) + { +#ifdef DEBUG_NODE_MSGS + std::cerr << "bdQueryManager::iteration() send_query("; + mFns->bdPrintId(std::cerr, &id); + std::cerr << ","; + mFns->bdPrintNodeId(std::cerr, &targetNodeId); + std::cerr << ")"; + std::cerr << std::endl; +#endif + mPub->send_query(&id, &targetNodeId); + sentQueries++; + } + i++; + } + +#ifdef DEBUG_NODE_ACTIONS + std::cerr << "bdQueryManager::iteration() maxMsgs: " << maxMsgs << " sentPings: " << sentPings; + std::cerr << " / " << allowedPings; + std::cerr << " sentQueries: " << sentQueries; + std::cerr << " / " << numQueries; + std::cerr << std::endl; +#endif + + //printQueries(); + + return sentQueries; +} + + +bool bdQueryManager::checkPotentialPeer(bdId *id, bdId *src) +{ + bool isWorthyPeer = false; + /* also push to queries */ + std::list::iterator it; + for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) + { + if ((*it)->addPotentialPeer(id, src, 0)) + { + isWorthyPeer = true; + } + } + + if (!isWorthyPeer) + { + isWorthyPeer = checkWorthyPeerSources(src); + } + + return isWorthyPeer; +} + + +void bdQueryManager::addPeer(const bdId *id, uint32_t peerflags) +{ + +#ifdef DEBUG_NODE_ACTIONS + fprintf(stderr, "bdQueryManager::addPeer("); + mFns->bdPrintId(std::cerr, id); + fprintf(stderr, ")\n"); +#endif + + /* iterate through queries */ + std::list::iterator it; + for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) + { + (*it)->addPeer(id, peerflags); + } +} + + +/************************************ Query Details *************************/ +void bdQueryManager::addQuery(const bdNodeId *id, uint32_t qflags) +{ + + std::list startList; + std::multimap nearest; + std::multimap::iterator it; + + mNodeSpace->find_nearest_nodes(id, BITDHT_QUERY_START_PEERS, nearest); + + fprintf(stderr, "bdQueryManager::addQuery("); + mFns->bdPrintNodeId(std::cerr, id); + fprintf(stderr, ")\n"); + + for(it = nearest.begin(); it != nearest.end(); it++) + { + startList.push_back(it->second); + } + + bdQuery *query = new bdQuery(id, startList, qflags, mFns); + mLocalQueries.push_back(query); +} + + +void bdQueryManager::clearQuery(const bdNodeId *rmId) +{ + std::list::iterator it; + for(it = mLocalQueries.begin(); it != mLocalQueries.end();) + { + if ((*it)->mId == *rmId) + { + bdQuery *query = (*it); + it = mLocalQueries.erase(it); + delete query; + } + else + { + it++; + } + } +} + +void bdQueryManager::QueryStatus(std::map &statusMap) +{ + std::list::iterator it; + for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) + { + bdQueryStatus status; + status.mStatus = (*it)->mState; + status.mQFlags = (*it)->mQueryFlags; + (*it)->result(status.mResults); + statusMap[(*it)->mId] = status; + } +} + +int bdQueryManager::QuerySummary(const bdNodeId *id, bdQuerySummary &query) +{ + std::list::iterator it; + for(it = mLocalQueries.begin(); it != mLocalQueries.end(); it++) + { + if ((*it)->mId == *id) + { + query.mId = (*it)->mId; + query.mLimit = (*it)->mLimit; + query.mState = (*it)->mState; + query.mQueryTS = (*it)->mQueryTS; + query.mQueryFlags = (*it)->mQueryFlags; + query.mSearchTime = (*it)->mSearchTime; + query.mClosest = (*it)->mClosest; + query.mPotentialPeers = (*it)->mPotentialPeers; + query.mProxiesUnknown = (*it)->mProxiesUnknown; + query.mProxiesFlagged = (*it)->mProxiesFlagged; + query.mQueryIdlePeerRetryPeriod = (*it)->mQueryIdlePeerRetryPeriod; + + return 1; + } + } + return 0; +} + +/* Extract Results from Peer Queries */ + +#define BDQRYMGR_RESULTS 1 +#define BDQRYMGR_PROXIES 2 +#define BDQRYMGR_POTPROXIES 3 + +int bdQueryManager::getResults(bdNodeId *target, std::list &answer, int querytype) +{ + + /* grab any peers from any existing query */ + int results = 0; + std::list::iterator qit; + for(qit = mLocalQueries.begin(); qit != mLocalQueries.end(); qit++) + { + if (!((*qit)->mId == (*target))) + { + continue; + } + +#ifdef DEBUG_NODE_CONNECTION + std::cerr << "bdQueryManager::getResults() Found Matching Query"; + std::cerr << std::endl; +#endif + switch(querytype) + { + default: + case BDQRYMGR_RESULTS: + results = (*qit)->result(answer); + break; + case BDQRYMGR_PROXIES: + results = (*qit)->proxies(answer); + break; + case BDQRYMGR_POTPROXIES: + results = (*qit)->potentialProxies(answer); + break; + } + /* will only be one matching query.. so end loop */ + return results; + } + return 0; +} + + +int bdQueryManager::result(bdNodeId *target, std::list &answer) +{ + return getResults(target, answer, BDQRYMGR_RESULTS); +} + +int bdQueryManager::proxies(bdNodeId *target, std::list &answer) +{ + return getResults(target, answer, BDQRYMGR_PROXIES); +} + +int bdQueryManager::potentialProxies(bdNodeId *target, std::list &answer) +{ + return getResults(target, answer, BDQRYMGR_POTPROXIES); +} + + +/************ WORTHY PEERS **********/ + +#define MAX_WORTHY_PEER_AGE 15 + +void bdQueryManager::addWorthyPeerSource(bdId *src) +{ + time_t now = time(NULL); + + bdPeer peer; + peer.mPeerId = *src; + peer.mFoundTime = now; + +#ifdef DEBUG_NODE_ACTIONS + std::cerr << "bdQueryManager::addWorthyPeerSource("; + mFns->bdPrintId(std::cerr, src); + std::cerr << ")" << std::endl; +#endif + + mWorthyPeerSources.push_back(peer); +} + +bool bdQueryManager::checkWorthyPeerSources(bdId *src) +{ + if (!src) + return false; + + time_t now = time(NULL); + std::list::iterator it; + for(it = mWorthyPeerSources.begin(); it != mWorthyPeerSources.end(); ) + { + if (now - it->mFoundTime > MAX_WORTHY_PEER_AGE) + { +#ifdef DEBUG_NODE_ACTIONS + std::cerr << "bdQueryManager::checkWorthyPeerSource() Discard old Source: "; + mFns->bdPrintId(std::cerr, &(it->mPeerId)); + std::cerr << std::endl; +#endif + + it = mWorthyPeerSources.erase(it); + } + else + { + if (it->mPeerId == *src) + { +#ifdef DEBUG_NODE_ACTIONS + std::cerr << "bdQueryManager::checkWorthyPeerSource("; + mFns->bdPrintId(std::cerr, src); + std::cerr << ") = true" << std::endl; +#endif + + return true; + } + it++; + } + } + return false; +} + + + diff --git a/libbitdht/src/bitdht/bdquerymgr.h b/libbitdht/src/bitdht/bdquerymgr.h new file mode 100644 index 000000000..042fbec41 --- /dev/null +++ b/libbitdht/src/bitdht/bdquerymgr.h @@ -0,0 +1,78 @@ +#ifndef BITDHT_QUERY_MANAGER_H +#define BITDHT_QUERY_MANAGER_H + +/* + * bitdht/bdquerymgr.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2011 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdquery.h" +class bdNodePublisher; + + +class bdQueryManager +{ + public: + + bdQueryManager(bdSpace *space, bdDhtFunctions *fns, bdNodePublisher *pub); + + void shutdownQueries(); + void printQueries(); + + int iterateQueries(int maxqueries); + + bool checkPotentialPeer(bdId *id, bdId *src); + void addPeer(const bdId *id, uint32_t peerflags); + + void addQuery(const bdNodeId *id, uint32_t qflags); + void clearQuery(const bdNodeId *id); + void QueryStatus(std::map &statusMap); + int QuerySummary(const bdNodeId *id, bdQuerySummary &query); + + int result(bdNodeId *target, std::list &answer); + int proxies(bdNodeId *target, std::list &answer); + int potentialProxies(bdNodeId *target, std::list &answer); + + // extra "Worthy Peers" we will want to ping. + void addWorthyPeerSource(bdId *src); + bool checkWorthyPeerSources(bdId *src); + + private: + + int getResults(bdNodeId *target, std::list &answer, int querytype); + + /* NB: No Mutex Protection... Single threaded, Mutex at higher level! + */ + + bdSpace *mNodeSpace; + bdDhtFunctions *mFns; + bdNodePublisher *mPub; + + std::list mLocalQueries; + std::list mWorthyPeerSources; +}; + + + +#endif // BITDHT_QUERY_MANAGER_H diff --git a/libbitdht/src/bitdht/bdstddht.cc b/libbitdht/src/bitdht/bdstddht.cc new file mode 100644 index 000000000..a8872bcde --- /dev/null +++ b/libbitdht/src/bitdht/bdstddht.cc @@ -0,0 +1,313 @@ +/* + * bitdht/bdstddht.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdstddht.h" +#include "bitdht/bdpeer.h" +#include "util/bdrandom.h" + +#include +#include +#include +#include + +#include +#include +#include + +/** + * #define BITDHT_DEBUG 1 +**/ + +void bdStdRandomId(bdId *id) +{ + bdStdRandomNodeId(&(id->id)); + id->addr.sin_addr.s_addr = bdRandom::random_u32(); + id->addr.sin_port = (bdRandom::random_u32() % USHRT_MAX); + + return; +} + +void bdStdRandomNodeId(bdNodeId *id) +{ + uint32_t *a_data = (uint32_t *) id->data; + for(int i = 0; i < BITDHT_KEY_INTLEN; i++) + { + a_data[i] = bdRandom::random_u32(); + } + return; +} + +void bdStdZeroNodeId(bdNodeId *id) +{ + uint32_t *a_data = (uint32_t *) id->data; + for(int i = 0; i < BITDHT_KEY_INTLEN; i++) + { + a_data[i] = 0; + } + return; +} + +// Ignore differences in port.... +// must be careful which one we accept after this. +// can could end-up with the wrong port. +// However this only matters with firewalled peers anyway. +// So not too serious. +bool bdStdSimilarId(const bdId *n1, const bdId *n2) +{ + if (n1->id == n2->id) + { + if (n1->addr.sin_addr.s_addr == n2->addr.sin_addr.s_addr) + { + return true; + } + } + return false; +} + +bool bdStdUpdateSimilarId(bdId *dest, const bdId *src) +{ + /* only difference that's currently allowed */ + if (dest->addr.sin_port == src->addr.sin_port) + { + /* no update required */ + return false; + } + + dest->addr.sin_port = src->addr.sin_port; + return true; +} + + +/* fills in bdNodeId r, with XOR of a and b */ +int bdStdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r) +{ + uint8_t *a_data = (uint8_t *) a->data; + uint8_t *b_data = (uint8_t *) b->data; + uint8_t *ans = (uint8_t *) r->data; + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + *(ans++) = *(a_data++) ^ *(b_data++); + } + return 1; +} + +void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *midId) +{ + bdMetric dist; + + /* get distance between a & c */ + bdStdDistance(target, other, &dist); + + /* generate Random Id */ + bdStdRandomNodeId(midId); + + /* zero bits of Random Id until under 1/2 of distance + * done in bytes for ease... matches one extra byte than distance = 0 + * -> hence wierd order of operations + */ + //bool done = false; + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + midId->data[i] = target->data[i]; + + if (dist.data[i] != 0) + break; + } +} + +int bdStdLoadNodeId(bdNodeId *id, std::string input) +{ + uint8_t *a_data = (uint8_t *) id->data; + int reqlen = BITDHT_KEY_LEN * 2; + if (input.size() < reqlen) + { + return 0; + } + + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + char ch1 = input[2 * i]; + char ch2 = input[2 * i + 1]; + uint8_t value1 = 0; + uint8_t value2 = 0; + + /* do char1 */ + if (ch1 >= '0' && ch1 <= '9') + value1 = (ch1 - '0'); + else if (ch1 >= 'A' && ch1 <= 'F') + value1 = (ch1 - 'A' + 10); + else if (ch1 >= 'a' && ch1 <= 'f') + value1 = (ch1 - 'a' + 10); + + /* do char2 */ + if (ch2 >= '0' && ch2 <= '9') + value2 = (ch2 - '0'); + else if (ch2 >= 'A' && ch2 <= 'F') + value2 = (ch2 - 'A' + 10); + else if (ch2 >= 'a' && ch2 <= 'f') + value2 = (ch2 - 'a' + 10); + + a_data[i] = (value1 << 4) + value2; + } + return 1; +} + +std::string bdStdConvertToPrintable(std::string input) +{ + std::ostringstream out; + for(uint32_t i = 0; i < input.length(); i++) + { + /* sensible chars */ + if ((input[i] > 31) && (input[i] < 127)) + { + out << input[i]; + } + else + { + out << "[0x" << std::hex << (uint32_t) input[i] << "]"; + out << std::dec; + } + } + return out.str(); +} + +void bdStdPrintNodeId(std::ostream &out, const bdNodeId *a) +{ + for(int i = 0; i < BITDHT_KEY_LEN; i++) + { + out << std::setw(2) << std::setfill('0') << std::hex << (uint32_t) (a->data)[i]; + } + out << std::dec; + + return; +} + + +void bdStdPrintId(std::ostream &out, const bdId *a) +{ + bdStdPrintNodeId(out, &(a->id)); + out << " ip:" << inet_ntoa(a->addr.sin_addr); + out << ":" << ntohs(a->addr.sin_port); + return; +} + +/* returns 0-160 depending on bucket */ +int bdStdBucketDistance(const bdNodeId *a, const bdNodeId *b) +{ + bdMetric m; + bdStdDistance(a, b, &m); + return bdStdBucketDistance(&m); +} + +/* returns 0-160 depending on bucket */ +int bdStdBucketDistance(const bdMetric *m) +{ + for(int i = 0; i < BITDHT_KEY_BITLEN; i++) + { + int bit = BITDHT_KEY_BITLEN - i - 1; + int byte = i / 8; + int bbit = 7 - (i % 8); + unsigned char comp = (1 << bbit); + +#ifdef BITDHT_DEBUG + fprintf(stderr, "bdStdBucketDistance: bit:%d byte:%d bbit:%d comp:%x, data:%x\n", bit, byte, bbit, comp, m->data[byte]); +#endif + + if (comp & m->data[byte]) + { + return bit; + } + } + return 0; +} + + +bdStdDht::bdStdDht() +{ + return; +} + /* setup variables */ +uint16_t bdStdDht::bdNumBuckets() +{ + + return BITDHT_STANDARD_N_BUCKETS; +} + +uint16_t bdStdDht::bdNodesPerBucket() /* used for query + bdspace */ +{ + return BITDHT_STANDARD_BUCKET_SIZE; +} +uint16_t bdStdDht::bdBucketBitSize() +{ + return BITDHT_STANDARD_BUCKET_SIZE_BITS; +} + +int bdStdDht::bdDistance(const bdNodeId *n1, const bdNodeId *n2, class bdMetric *metric) +{ + return bdStdDistance(n1, n2, metric); +} + +int bdStdDht::bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2) +{ + return bdStdBucketDistance(n1, n2); +} + +int bdStdDht::bdBucketDistance(const bdMetric *metric) +{ + return bdStdBucketDistance(metric); +} + + +bool bdStdDht::bdSimilarId(const bdId *id1, const bdId *id2) +{ + return bdStdSimilarId(id1, id2); +} + + +bool bdStdDht::bdUpdateSimilarId(bdId *dest, const bdId *src) +{ + return bdStdUpdateSimilarId(dest, src); +} + + +void bdStdDht::bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid) +{ + return bdStdRandomMidId(target, other, mid); +} + + +void bdStdDht::bdPrintId(std::ostream &out, const bdId *a) +{ + return bdStdPrintId(out, a); +} + +void bdStdDht::bdPrintNodeId(std::ostream &out, const bdNodeId *a) +{ + return bdStdPrintNodeId(out, a); +} + + + diff --git a/libbitdht/src/bitdht/bdstddht.h b/libbitdht/src/bitdht/bdstddht.h new file mode 100644 index 000000000..71e1b44ce --- /dev/null +++ b/libbitdht/src/bitdht/bdstddht.h @@ -0,0 +1,91 @@ +#ifndef BITDHT_STANDARD_DHT_H +#define BITDHT_STANDARD_DHT_H + +/* + * bitdht/bdstddht.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdiface.h" + +#define BITDHT_STANDARD_BUCKET_SIZE 10 // 20 too many per query? +#define BITDHT_STANDARD_BUCKET_SIZE_BITS 5 + +#define BITDHT_STANDARD_N_BUCKETS BITDHT_KEY_BITLEN + +#include +#include +#include +#include + + + + +void bdStdRandomNodeId(bdNodeId *id); +void bdStdZeroNodeId(bdNodeId *id); + +void bdStdRandomId(bdId *id); +int bdStdDistance(const bdNodeId *a, const bdNodeId *b, bdMetric *r); +int bdStdBucketDistance(const bdMetric *m); +int bdStdBucketDistance(const bdNodeId *a, const bdNodeId *b); + +void bdStdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); + +int bdStdLoadNodeId(bdNodeId *id, std::string input); + +void bdStdPrintId(std::ostream &out, const bdId *a); +void bdStdPrintNodeId(std::ostream &out, const bdNodeId *a); + +std::string bdStdConvertToPrintable(std::string input); + +//uint32_t bdStdSimilarNode(const bdId*, const bdId*); + + +class bdStdDht: public bdDhtFunctions +{ + public: + + bdStdDht(); + /* setup variables */ +virtual uint16_t bdNumBuckets(); +virtual uint16_t bdNodesPerBucket(); /* used for query + bdspace */ +virtual uint16_t bdBucketBitSize(); + +virtual int bdDistance(const bdNodeId *n1, const bdNodeId *n2, bdMetric *metric); +virtual int bdBucketDistance(const bdNodeId *n1, const bdNodeId *n2); +virtual int bdBucketDistance(const bdMetric *metric); + +virtual bool bdSimilarId(const bdId *id1, const bdId *id2); +virtual bool bdUpdateSimilarId(bdId *dest, const bdId *src); /* returns true if update was necessary */ + +virtual void bdRandomMidId(const bdNodeId *target, const bdNodeId *other, bdNodeId *mid); + +virtual void bdPrintId(std::ostream &out, const bdId *a); +virtual void bdPrintNodeId(std::ostream &out, const bdNodeId *a); + +}; + + +#endif + diff --git a/libbitdht/src/bitdht/bdstore.cc b/libbitdht/src/bitdht/bdstore.cc new file mode 100644 index 000000000..10046ba2e --- /dev/null +++ b/libbitdht/src/bitdht/bdstore.cc @@ -0,0 +1,253 @@ +/* + * bitdht/bdstore.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdstore.h" +#include "util/bdnet.h" + +#include +#include + +//#define DEBUG_STORE 1 + +bdStore::bdStore(std::string file, bdDhtFunctions *fns) + :mFns(fns) +{ +#ifdef DEBUG_STORE + std::cerr << "bdStore::bdStore(" << file << ")"; + std::cerr << std::endl; +#endif + + /* read data from file */ + mStoreFile = file; + + reloadFromStore(); +} + +int bdStore::clear() +{ + mIndex = 0; + store.clear(); + return 1; +} + +int bdStore::reloadFromStore() +{ + clear(); + + FILE *fd = fopen(mStoreFile.c_str(), "r"); + if (!fd) + { + fprintf(stderr, "Failed to Open File: %s ... No Peers\n", mStoreFile.c_str()); + return 0; + } + + + char line[10240]; + char addr_str[10240]; + struct sockaddr_in addr; + addr.sin_family = PF_INET; + unsigned short port; + + while(line == fgets(line, 10240, fd)) + { + if (2 == sscanf(line, "%s %hd", addr_str, &port)) + { + if (bdnet_inet_aton(addr_str, &(addr.sin_addr))) + { + addr.sin_port = htons(port); + bdPeer peer; + //bdZeroNodeId(&(peer.mPeerId.id)); + peer.mPeerId.addr = addr; + peer.mLastSendTime = 0; + peer.mLastRecvTime = 0; + store.push_back(peer); +#ifdef DEBUG_STORE + fprintf(stderr, "Read: %s %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); +#endif + } + } + } + + fclose(fd); + +#ifdef DEBUG_STORE + fprintf(stderr, "Read %ld Peers\n", (long) store.size()); +#endif + + return 1; + +} + +// This is a very ugly function! +int bdStore::getPeer(bdPeer *peer) +{ +#ifdef DEBUG_STORE + fprintf(stderr, "bdStore::getPeer() %ld Peers left\n", (long) store.size()); +#endif + + std::list::iterator it; + int i = 0; + for(it = store.begin(); (it != store.end()) && (i < mIndex); it++, i++) ; /* empty loop */ + if (it != store.end()) + { + *peer = *it; + mIndex++; + return 1; + } + return 0; +} + +int bdStore::filterIpList(const std::list &filteredIPs) +{ + // Nasty O(n^2) iteration over 500 entries!!!. + // hope its not used to often. + + std::list::const_iterator it; + for(it = filteredIPs.begin(); it != filteredIPs.end(); it++) + { + std::list::iterator sit; + for(sit = store.begin(); sit != store.end();) + { + if (it->sin_addr.s_addr == sit->mPeerId.addr.sin_addr.s_addr) + { + std::cerr << "bdStore::filterIpList() Found Bad entry in Store. Erasing!"; + std::cerr << std::endl; + + sit = store.erase(sit); + } + else + { + sit++; + } + } + } + return 1; +} + + + +#define MAX_ENTRIES 500 + + /* maintain a sorted list */ +void bdStore::addStore(bdPeer *peer) +{ +#ifdef DEBUG_STORE + std::cerr << "bdStore::addStore() "; + mFns->bdPrintId(std::cerr, &(peer->mPeerId)); + std::cerr << std::endl; +#endif + + /* remove old entry */ + bool removed = false; + + std::list::iterator it; + for(it = store.begin(); it != store.end(); ) + { + if ((it->mPeerId.addr.sin_addr.s_addr == peer->mPeerId.addr.sin_addr.s_addr) && + (it->mPeerId.addr.sin_port == peer->mPeerId.addr.sin_port)) + { + removed = true; +#ifdef DEBUG_STORE + std::cerr << "bdStore::addStore() Removed Existing Entry: "; + mFns->bdPrintId(std::cerr, &(it->mPeerId)); + std::cerr << std::endl; +#endif + it = store.erase(it); + } + else + { + it++; + } + } + +#ifdef DEBUG_STORE + std::cerr << "bdStore::addStore() Push_back"; + std::cerr << std::endl; +#endif + store.push_back(*peer); + + while(store.size() > MAX_ENTRIES) + { +#ifdef DEBUG_STORE + std::cerr << "bdStore::addStore() pop_front()"; + std::cerr << std::endl; +#endif + store.pop_front(); + } +} + +void bdStore::writeStore(std::string file) +{ + /* write out store */ +#ifdef DEBUG_STORE + fprintf(stderr, "bdStore::writeStore(%s) = %d entries\n", file.c_str(), store.size()); +#endif + + if (store.size() < 0.9 * MAX_ENTRIES) + { + /* don't save yet! */ +#ifdef DEBUG_STORE + fprintf(stderr, "bdStore::writeStore() Delaying until more entries\n"); +#endif + return; + } + + + FILE *fd = fopen(file.c_str(), "w"); + + if (!fd) + { +#ifdef DEBUG_STORE +#endif + fprintf(stderr, "bdStore::writeStore() FAILED to Open File\n"); + return; + } + + std::list::iterator it; + for(it = store.begin(); it != store.end(); it++) + { + fprintf(fd, "%s %d\n", inet_ntoa(it->mPeerId.addr.sin_addr), ntohs(it->mPeerId.addr.sin_port)); +#ifdef DEBUG_STORE + fprintf(stderr, "Storing Peer Address: %s %d\n", inet_ntoa(it->mPeerId.addr.sin_addr), ntohs(it->mPeerId.addr.sin_port)); +#endif + + } + fclose(fd); +} + +void bdStore::writeStore() +{ +#if 0 + if (mStoreFile == "") + { + return; + } +#endif + return writeStore(mStoreFile); +} + + + diff --git a/libbitdht/src/bitdht/bdstore.h b/libbitdht/src/bitdht/bdstore.h new file mode 100644 index 000000000..c1b0f7b03 --- /dev/null +++ b/libbitdht/src/bitdht/bdstore.h @@ -0,0 +1,57 @@ +#ifndef BITDHT_STORE_H +#define BITDHT_STORE_H + +/* + * bitdht/bdstore.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include +#include "bitdht/bdiface.h" +#include "bitdht/bdpeer.h" + +class bdStore +{ + public: + + bdStore(std::string file, bdDhtFunctions *fns); + +int reloadFromStore(); /* for restarts */ +int filterIpList(const std::list &filteredIPs); +int clear(); + +int getPeer(bdPeer *peer); +void addStore(bdPeer *peer); +void writeStore(std::string file); +void writeStore(); + + private: + std::string mStoreFile; + std::list store; + int mIndex; + bdDhtFunctions *mFns; +}; + + +#endif diff --git a/libbitdht/src/bitdht/bencode.c b/libbitdht/src/bitdht/bencode.c new file mode 100644 index 000000000..60bc75660 --- /dev/null +++ b/libbitdht/src/bitdht/bencode.c @@ -0,0 +1,602 @@ +/* + * C implementation of a bencode decoder. + * This is the format defined by BitTorrent: + * http://wiki.theory.org/BitTorrentSpecification#bencoding + * + * The only external requirements are a few [standard] function calls and + * the long long type. Any sane system should provide all of these things. + * + * See the bencode.h header file for usage information. + * + * This is released into the public domain. + * Written by Mike Frysinger . + */ + +/* + * This implementation isn't optimized at all as I wrote it to support + * a bogus system. I have no real interest in this format. Feel free + * to send me patches (so long as you don't copyright them and you release + * your changes into the public domain as well). + */ + +#include +#include /* malloc() realloc() free() strtoll() */ +#include /* memset() */ + +#include "bitdht/bencode.h" + +/*** + * #define BE_DEBUG_DECODE 1 + * #define BE_DEBUG 1 // controlled from Makefile too. + ***/ + +#ifdef BE_DEBUG_DECODE + #include /* debug */ +#endif + +static be_node *be_alloc(be_type type) +{ + be_node *ret = (be_node *) malloc(sizeof(*ret)); + if (ret) { + memset(ret, 0x00, sizeof(*ret)); + ret->type = type; + } + return ret; +} + +static long long _be_decode_int(const char **data, long long *data_len) +{ + char *endp; + long long ret = strtoll(*data, &endp, 10); + *data_len -= (endp - *data); + *data = endp; + +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode_int(pnt: %p, rem: %lld) = %lld\n", *data, *data_len, ret); +#endif + return ret; +} + +long long be_str_len(be_node *node) +{ + long long ret = 0; + if (node->val.s) + memcpy(&ret, node->val.s - sizeof(ret), sizeof(ret)); + return ret; +} + +static char *_be_decode_str(const char **data, long long *data_len) +{ +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode_str(pnt: %p, rem: %lld)\n", *data, *data_len); +#endif + long long sllen = _be_decode_int(data, data_len); + long slen = sllen; + unsigned long len; + char *ret = NULL; + + /* slen is signed, so negative values get rejected */ + if (sllen < 0) + { +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode_str() reject bad length\n"); +#endif + return ret; + } + + /* reject attempts to allocate large values that overflow the + * size_t type which is used with malloc() + */ + if (sizeof(long long) != sizeof(long)) + if (sllen != slen) + { +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode_str() reject large_values\n"); +#endif + return ret; + } + + /* make sure we have enough data left */ + if (sllen > *data_len - 1) + { +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode_str() reject large_values\n"); +#endif + return ret; + } + + /* switch from signed to unsigned so we don't overflow below */ + len = slen; + + if (**data == ':') { + char *_ret = (char *) malloc(sizeof(sllen) + len + 1); + memcpy(_ret, &sllen, sizeof(sllen)); + ret = _ret + sizeof(sllen); + memcpy(ret, *data + 1, len); + ret[len] = '\0'; + *data += len + 1; + *data_len -= len + 1; + +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode_str() read %ld bytes\n", len+1); +#endif + } + else + { +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode_str() reject missing :\n"); +#endif + } + return ret; +} + +static be_node *_be_decode(const char **data, long long *data_len) +{ +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode(pnt: %p, rem: %lld)\n", *data, *data_len); +#endif + be_node *ret = NULL; + + if (!*data_len) + { +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() reject invalid datalen\n"); +#endif + return ret; + } + + switch (**data) { + /* lists */ + case 'l': { + unsigned int i = 0; +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() found list\n"); +#endif + + ret = be_alloc(BE_LIST); + + --(*data_len); + ++(*data); + while (**data != 'e') { +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() list get item (%d)\n", i); +#endif + ret->val.l = (be_node **) realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l)); + ret->val.l[i] = _be_decode(data, data_len); + if (ret->val.l[i] == NULL) + { + /* failed decode - kill decode */ +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() failed list decode - kill\n"); +#endif + be_free(ret); + return NULL; + } + ++i; + } + --(*data_len); + ++(*data); + + /* empty list case. */ + if (i == 0) + { + ret->val.l = (be_node **) realloc(ret->val.l, 1 * sizeof(*ret->val.l)); + } + + ret->val.l[i] = NULL; + + return ret; + } + + /* dictionaries */ + case 'd': { + unsigned int i = 0; +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() found dictionary\n"); +#endif + + ret = be_alloc(BE_DICT); + + --(*data_len); + ++(*data); + while (**data != 'e') { +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() dictionary get key (%d)\n", i); +#endif + ret->val.d = (be_dict *) realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d)); + ret->val.d[i].key = _be_decode_str(data, data_len); +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() dictionary get val\n"); +#endif + ret->val.d[i].val = _be_decode(data, data_len); + + if ((ret->val.d[i].key == NULL) || (ret->val.d[i].val == NULL)) + { + /* failed decode - kill decode */ +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() failed dict decode - kill\n"); +#endif + be_free(ret); + return NULL; + } + ++i; + } + --(*data_len); + ++(*data); + + /* empty dictionary case. */ + if (i == 0) + { + ret->val.d = (be_dict *) realloc(ret->val.d, 1 * sizeof(*ret->val.d)); + } + + + ret->val.d[i].val = NULL; + return ret; + } + + /* integers */ + case 'i': { + ret = be_alloc(BE_INT); +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() found int\n"); +#endif + + --(*data_len); + ++(*data); + ret->val.i = _be_decode_int(data, data_len); + if (**data != 'e') + { +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() reject data != e - kill\n"); +#endif + be_free(ret); + return NULL; + } + --(*data_len); + ++(*data); + + return ret; + } + + /* byte strings */ + case '0'...'9': { + ret = be_alloc(BE_STR); +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() found string\n"); +#endif + + ret->val.s = _be_decode_str(data, data_len); + + return ret; + } + + /* invalid */ + default: +#ifdef BE_DEBUG_DECODE + fprintf(stderr, "bencode::_be_decode() found invalid - kill\n"); +#endif + return NULL; + break; + } + + return ret; +} + +be_node *be_decoden(const char *data, long long len) +{ + return _be_decode(&data, &len); +} + +be_node *be_decode(const char *data) +{ + return be_decoden(data, strlen(data)); +} + +static inline void _be_free_str(char *str) +{ + if (str) + free(str - sizeof(long long)); +} +void be_free(be_node *node) +{ + switch (node->type) { + case BE_STR: + _be_free_str(node->val.s); + break; + + case BE_INT: + break; + + case BE_LIST: { + unsigned int i; + for (i = 0; node->val.l[i]; ++i) + be_free(node->val.l[i]); + free(node->val.l); + break; + } + + case BE_DICT: { + unsigned int i; + for (i = 0; node->val.d[i].val; ++i) { + _be_free_str(node->val.d[i].key); + be_free(node->val.d[i].val); + } + free(node->val.d); + break; + } + } + free(node); +} + +#ifdef BE_DEBUG +#include +#include + +static void _be_dump_indent(ssize_t indent) +{ + while (indent-- > 0) + printf(" "); +} +static void _be_dump(be_node *node, ssize_t indent) +{ + size_t i; + + _be_dump_indent(indent); + indent = abs(indent); + + switch (node->type) { + case BE_STR: + be_dump_str(node); + //printf("str = %s (len = %lli)\n", node->val.s, be_str_len(node)); + break; + + case BE_INT: + printf("int = %lli\n", node->val.i); + break; + + case BE_LIST: + puts("list ["); + + for (i = 0; node->val.l[i]; ++i) + _be_dump(node->val.l[i], indent + 1); + + _be_dump_indent(indent); + puts("]"); + break; + + case BE_DICT: + puts("dict {"); + + for (i = 0; node->val.d[i].val; ++i) { + _be_dump_indent(indent + 1); + printf("%s => ", node->val.d[i].key); + _be_dump(node->val.d[i].val, -(indent + 1)); + } + + _be_dump_indent(indent); + puts("}"); + break; + } +} +void be_dump(be_node *node) +{ + _be_dump(node, 0); +} + +void be_dump_str(be_node *node) +{ + if (node->type != BE_STR) + { + printf("be_dump_str(): error not a string\n"); + return; + } + + int len = be_str_len(node); + int i = 0; + printf("str[%d] = ", len); + for(i = 0; i < len; i++) + { + /* sensible chars */ + if ((node->val.s[i] > 31) && (node->val.s[i] < 127)) + { + printf("%c", node->val.s[i]); + } + else + { + printf("[%d]", node->val.s[i]); + } + } + printf("\n"); +} + + +#endif + +/******************** New Functions added by drBob ************* + * Output bencode + * + */ + +int be_encode(be_node *node, char *str, int len) +{ + size_t i; + int loc = 0; + + switch (node->type) { + case BE_STR: + snprintf(str, len, "%lli:", be_str_len(node)); + loc += strlen(&(str[loc])); + + memcpy(&(str[loc]), node->val.s, be_str_len(node)); + loc += be_str_len(node); + break; + + case BE_INT: + snprintf(str, len, "i%llie", node->val.i); + loc += strlen(&(str[loc])); + break; + + case BE_LIST: + + snprintf(str, len, "l"); + loc += 1; + + for (i = 0; node->val.l[i]; ++i) + { + loc += be_encode(node->val.l[i], &(str[loc]), len-loc); + } + + snprintf(&(str[loc]), len - loc, "e"); + loc += 1; + + break; + + case BE_DICT: + snprintf(str, len, "d"); + loc += 1; + + for (i = 0; node->val.d[i].val; ++i) { + + /* assumption that key must be ascii! */ + snprintf(&(str[loc]), len-loc, "%i:%s", + (int) strlen(node->val.d[i].key), + node->val.d[i].key); + loc += strlen(&(str[loc])); + loc += be_encode(node->val.d[i].val, &(str[loc]), len-loc); + } + + snprintf(&(str[loc]), len - loc, "e"); + loc += 1; + + break; + } + return loc; +} + +/* hackish way to create nodes! */ +be_node *be_create_dict() +{ + be_node *n = be_decode("de"); + return n; +} + + +be_node *be_create_list() +{ + be_node *n = be_decode("le"); + return n; +} + +be_node *be_create_str(const char *str) +{ + + /* must */ + be_node *n = be_alloc(BE_STR); + int len = strlen(str); + long long int sllen = len; + char *_ret = (char *) malloc(sizeof(sllen) + len + 1); + char *ret = NULL; + + memcpy(_ret, &sllen, sizeof(sllen)); + ret = _ret + sizeof(sllen); + memcpy(ret, str, len); + ret[len] = '\0'; + + n->val.s = ret; + + return n; +} + +be_node *be_create_str_wlen(const char *str, int len) /* not including \0 */ +{ + + /* must */ + be_node *n = be_alloc(BE_STR); + long long int sllen = len; + char *_ret = (char *) malloc(sizeof(sllen) + len + 1); + char *ret = NULL; + + memcpy(_ret, &sllen, sizeof(sllen)); + ret = _ret + sizeof(sllen); + memcpy(ret, str, len); + ret[len] = '\0'; + + n->val.s = ret; + + return n; +} + +be_node *be_create_int(long long int num) +{ + /* must */ + be_node *n = be_alloc(BE_INT); + n->val.i = num; + return n; +} + +int be_add_keypair(be_node *dict, const char *str, be_node *node) +{ + int i = 0; + + /* only if dict type */ + if (dict->type != BE_DICT) + { + return 0; + } + + // get to end of dict. + for(i = 0; dict->val.d[i].val; i++); + + //fprintf(stderr, "be_add_keypair() i = %d\n",i); + + /* realloc space */ + dict->val.d = (be_dict *) realloc(dict->val.d, (i + 2) * sizeof(*dict->val.d)); + + /* stupid key storage system */ + int len = strlen(str); + long long int sllen = len; + char *_ret = (char *) malloc(sizeof(sllen) + len + 1); + char *ret = NULL; + + //fprintf(stderr, "be_add_keypair() key len = %d\n",len); + + memcpy(_ret, &sllen, sizeof(sllen)); + ret = _ret + sizeof(sllen); + memcpy(ret, str, len); + ret[len] = '\0'; + + dict->val.d[i].key = ret; + dict->val.d[i].val = node; + i++; + dict->val.d[i].val = NULL; + + return 1; +} + + +int be_add_list(be_node *list, be_node *node) +{ + int i = 0; + + /* only if dict type */ + if (list->type != BE_LIST) + { + return 0; + } + + // get to end of dict. + for(i = 0; list->val.l[i]; i++); + + /* realloc space */ + list->val.l = (be_node **) realloc(list->val.l, (i + 2) * sizeof(*list->val.l)); + list->val.l[i] = node; + ++i; + list->val.l[i] = NULL; + + return 1; +} + + + + diff --git a/libbitdht/src/bitdht/bencode.h b/libbitdht/src/bitdht/bencode.h new file mode 100644 index 000000000..211c96542 --- /dev/null +++ b/libbitdht/src/bitdht/bencode.h @@ -0,0 +1,82 @@ +/* + * C implementation of a bencode decoder. + * This is the format defined by BitTorrent: + * http://wiki.theory.org/BitTorrentSpecification#bencoding + * + * The only external requirements are a few [standard] function calls and + * the long long type. Any sane system should provide all of these things. + * + * This is released into the public domain. + * Written by Mike Frysinger . + */ + +/* USAGE: + * - pass the string full of the bencoded data to be_decode() + * - parse the resulting tree however you like + * - call be_free() on the tree to release resources + */ + +#ifndef _BENCODE_H +#define _BENCODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + BE_STR, + BE_INT, + BE_LIST, + BE_DICT, +} be_type; + +struct be_dict; +struct be_node; + +/* + * XXX: the "val" field of be_dict and be_node can be confusing ... + */ + +typedef struct be_dict { + char *key; + struct be_node *val; +} be_dict; + +typedef struct be_node { + be_type type; + union { + char *s; + long long i; + struct be_node **l; + struct be_dict *d; + } val; +} be_node; + +extern long long be_str_len(be_node *node); +// This function uses strlen, so is unreliable. +//extern be_node *be_decode(const char *bencode); +extern be_node *be_decoden(const char *bencode, long long bencode_len); +extern void be_free(be_node *node); +extern void be_dump(be_node *node); +extern void be_dump_str(be_node *node); + +// New Functions for the other half of the work - encoding */ + +extern int be_encode(be_node *node, char *str, int len); + + +// Creating the data structure. +extern int be_add_list(be_node *list, be_node *node); +extern int be_add_keypair(be_node *dict, const char *str, be_node *node); +extern be_node *be_create_int(long long int num); +extern be_node *be_create_list(); +extern be_node *be_create_str(const char *str); +extern be_node *be_create_str_wlen(const char *str, int len); /* not including \0 */ +extern be_node *be_create_dict(); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libbitdht/src/example/Makefile b/libbitdht/src/example/Makefile new file mode 100644 index 000000000..b71d1f898 --- /dev/null +++ b/libbitdht/src/example/Makefile @@ -0,0 +1,16 @@ + +CXXFLAGS = -Wall -g -I.. +#CXXFLAGS += -arch i386 # OSX + +LIBS = -L../lib -lbitdht + + + +EXEC : bdexample + +EGOBJ = bdhandler.o bdexample.o + +bdexample: $(EGOBJ) + $(CXX) $(CXXFLAGS) -o bdexample $(EGOBJ) $(LIBS) + + diff --git a/libbitdht/src/example/bdboot.txt b/libbitdht/src/example/bdboot.txt new file mode 100644 index 000000000..89f27a247 --- /dev/null +++ b/libbitdht/src/example/bdboot.txt @@ -0,0 +1,500 @@ +64.121.80.63 45642 +84.82.225.139 52002 +200.104.218.244 24447 +116.81.147.106 10014 +76.238.231.136 37770 +68.148.109.134 32815 +78.43.60.243 18973 +62.33.209.243 20600 +84.40.115.5 49669 +93.11.108.82 45078 +90.157.139.222 28487 +79.83.184.114 40139 +109.104.187.16 30000 +87.101.162.223 21364 +99.251.104.111 60382 +130.63.133.216 47451 +64.216.32.37 6881 +75.137.149.242 19860 +208.102.25.182 50675 +75.72.144.15 54485 +68.148.20.202 22025 +69.148.177.153 26961 +121.222.5.240 51932 +88.161.156.9 48251 +88.200.104.216 27784 +109.160.52.2 36630 +74.12.101.58 61864 +174.71.75.121 48749 +186.66.255.5 37580 +24.116.239.194 59147 +95.65.178.164 23715 +220.70.175.83 43726 +182.169.110.245 64684 +119.247.164.154 22132 +77.202.227.150 15621 +79.129.217.171 17248 +98.117.197.195 53478 +71.72.3.201 40665 +72.88.206.217 57170 +95.29.8.61 59559 +142.163.161.23 60957 +70.27.27.105 23047 +90.42.104.194 10595 +114.36.7.29 26051 +78.26.164.132 59437 +70.126.197.41 14207 +187.14.3.249 8753 +62.166.34.78 62133 +82.45.213.218 24740 +213.123.71.145 56050 +93.12.188.2 22070 +203.184.0.161 10295 +69.156.209.139 19165 +83.81.119.121 34439 +109.208.211.98 36278 +84.3.208.199 50001 +85.87.98.187 53911 +93.127.107.157 35691 +188.195.145.172 21827 +184.56.151.190 11951 +98.168.190.247 61279 +83.237.221.242 16613 +75.30.79.175 57107 +90.24.61.26 57262 +125.27.132.48 10018 +94.98.122.161 62266 +81.25.50.209 44962 +94.24.137.191 35691 +74.119.191.181 62498 +46.33.237.37 21135 +183.83.30.78 15822 +109.75.207.23 14085 +92.147.163.123 36706 +110.3.132.18 10149 +90.38.163.86 61080 +77.50.87.114 11399 +76.106.47.230 6881 +24.47.46.185 59822 +118.150.145.87 16553 +98.121.178.252 31353 +95.62.64.40 12174 +85.91.17.78 8644 +98.148.37.251 55774 +122.117.82.108 16293 +200.26.143.117 14013 +187.37.80.22 25095 +95.19.224.225 25446 +79.132.4.131 36094 +109.86.136.248 44281 +85.54.187.59 28890 +99.225.92.6 38080 +178.40.89.75 10018 +189.237.151.135 17643 +189.114.233.119 12308 +93.13.211.51 59788 +80.56.69.253 25685 +83.131.224.235 62622 +201.229.9.69 28159 +201.223.65.4 43804 +77.167.196.115 64788 +71.72.158.196 37961 +86.132.129.242 23071 +93.103.167.242 35298 +212.37.169.128 31631 +74.105.104.186 23922 +173.176.243.27 31393 +86.13.110.77 47020 +76.181.24.116 35553 +94.158.107.234 32516 +99.242.143.80 19034 +201.209.54.201 26726 +109.87.52.11 20186 +98.121.161.117 54068 +75.69.6.91 6881 +98.223.44.215 35998 +123.193.220.215 54157 +95.130.12.23 61546 +84.215.125.229 51413 +77.203.179.13 23145 +217.172.179.78 18692 +85.170.52.161 12310 +98.244.158.38 40311 +71.201.200.183 41435 +99.111.202.61 10341 +84.252.27.201 17253 +210.6.173.193 6887 +74.67.142.125 17874 +94.23.212.70 57174 +77.99.18.29 63852 +91.100.81.198 49999 +82.74.117.94 25000 +78.83.127.162 53345 +95.84.255.201 17122 +85.228.78.9 47500 +217.77.60.189 58847 +67.174.74.95 35000 +95.105.198.233 80 +85.238.105.154 40000 +70.114.173.8 26375 +71.100.182.81 21724 +24.9.187.250 29985 +72.204.16.239 50200 +78.94.104.125 63580 +67.83.132.220 51515 +96.52.145.135 12607 +85.187.24.45 14111 +91.148.128.36 24464 +24.186.53.139 61726 +109.110.3.135 57756 +78.159.108.124 63982 +82.244.72.113 10620 +24.16.216.224 45546 +24.60.118.120 60005 +89.135.149.47 52055 +88.191.117.198 46881 +79.108.19.172 52750 +84.24.37.138 15678 +213.93.83.121 51413 +87.50.207.134 60361 +77.120.182.144 30585 +80.109.42.12 29168 +188.230.38.94 32525 +109.86.246.11 11400 +93.72.108.237 39272 +109.160.201.32 27495 +90.214.93.249 25238 +2.106.159.182 28860 +24.49.43.222 26917 +67.215.242.139 6881 +83.83.52.92 10000 +89.161.85.250 27553 +76.20.230.30 58335 +60.62.38.145 22101 +62.148.159.55 52603 +69.123.52.81 64701 +67.215.242.138 6881 +99.225.194.114 45586 +79.124.27.117 26472 +86.10.209.139 12001 +95.181.30.110 37075 +65.5.225.206 6881 +66.110.140.217 6881 +99.112.96.188 35979 +87.120.113.236 18301 +67.162.118.20 9820 +173.51.87.191 37950 +58.69.218.34 38072 +87.120.78.253 25118 +69.137.192.214 6881 +81.57.50.221 11095 +89.212.93.62 32590 +93.152.176.62 6881 +96.250.206.111 20965 +93.72.132.238 47860 +96.20.161.32 44893 +24.235.41.231 11181 +88.80.49.238 35857 +89.215.103.145 16242 +142.162.65.171 30537 +178.162.184.203 6821 +93.182.0.249 32217 +217.208.59.201 46227 +79.132.182.136 30129 +77.70.96.3 11949 +174.59.144.37 5895 +24.206.168.152 22102 +24.64.233.94 17962 +109.168.162.23 32195 +71.53.119.62 23108 +60.241.156.191 24064 +18.242.7.242 65435 +216.113.97.150 29801 +89.133.173.35 37855 +78.82.124.105 20047 +78.128.57.15 22034 +99.54.50.211 64189 +174.118.36.27 60010 +189.120.102.167 63495 +187.1.109.123 20546 +123.193.205.49 22248 +87.48.15.175 52767 +195.145.124.15 33639 +189.34.175.133 1142 +188.16.249.8 10428 +78.96.153.123 10943 +209.188.19.242 61204 +94.208.99.166 13733 +77.70.32.188 9459 +69.134.71.56 10713 +74.213.69.68 17477 +175.137.140.31 18987 +219.79.191.108 35982 +86.129.7.137 21672 +78.225.25.249 10323 +216.195.251.137 41238 +201.6.19.10 64067 +76.101.164.51 20673 +196.221.130.175 18290 +80.192.63.126 59768 +80.177.109.9 34474 +77.243.211.17 40330 +99.179.5.68 55337 +206.63.116.47 47092 +2.83.53.144 14926 +188.25.174.202 26218 +86.28.149.67 39274 +92.133.136.242 41243 +95.28.8.196 39167 +213.231.136.129 13219 +98.237.145.195 46637 +58.165.71.127 25006 +111.252.45.153 25943 +89.29.15.90 56736 +86.171.44.134 57592 +94.59.26.121 36725 +81.191.88.223 54799 +75.81.195.23 22056 +81.109.38.132 31233 +109.121.220.16 10301 +212.92.246.213 22544 +95.158.10.130 13941 +112.118.166.151 45684 +202.154.59.140 43442 +93.181.215.55 46157 +76.217.106.151 62033 +61.227.125.97 13874 +78.58.201.174 28778 +81.231.229.41 19130 +186.10.23.230 37769 +83.254.77.75 17232 +84.110.59.219 62065 +81.98.22.127 47800 +85.17.5.132 51413 +83.55.120.23 42521 +195.18.28.147 35691 +61.202.78.247 22221 +93.80.153.76 48878 +95.29.196.251 61629 +94.75.148.194 24796 +109.194.167.19 47193 +207.216.26.166 36202 +76.186.158.107 56213 +79.118.112.122 26181 +93.115.48.2 16132 +84.32.80.26 6881 +72.198.44.72 31231 +70.162.57.125 48027 +216.162.201.192 17384 +77.49.95.176 45619 +77.47.185.248 15245 +80.185.186.95 10318 +82.200.130.249 58389 +67.162.140.62 29974 +118.168.172.177 27161 +114.51.38.178 23793 +125.175.146.71 17014 +80.66.213.182 64219 +77.50.234.5 25866 +78.90.218.100 49844 +46.118.135.250 58667 +92.80.58.143 14569 +99.253.186.136 43003 +71.60.40.75 41590 +151.11.145.100 18163 +123.237.49.221 17321 +201.130.198.7 56378 +64.219.119.229 53546 +121.118.219.211 6880 +114.32.171.238 6881 +110.33.112.22 7336 +85.58.8.57 59138 +77.70.70.8 19445 +178.140.72.96 33178 +78.166.69.33 40531 +211.24.149.162 39719 +62.16.162.73 50001 +95.84.244.177 33076 +46.118.71.243 57944 +91.139.194.92 24902 +77.248.205.101 58849 +83.152.236.85 46613 +41.236.189.5 11493 +94.26.63.5 29973 +189.100.145.169 45441 +84.202.146.45 32122 +183.179.108.42 15833 +78.247.112.51 48465 +95.102.42.122 6881 +89.185.199.69 49879 +74.129.254.238 21830 +99.181.161.222 27636 +96.235.14.144 40928 +189.71.180.71 18172 +96.54.129.2 26085 +222.141.53.49 16006 +121.184.217.130 21563 +84.3.111.252 51111 +79.103.174.69 40190 +89.139.35.26 45625 +62.215.144.191 33078 +75.27.19.0 42707 +83.192.127.87 10785 +99.174.215.236 51128 +78.36.180.6 33016 +92.101.222.111 42441 +85.91.17.59 14091 +24.14.120.77 11682 +188.26.55.161 13650 +77.37.133.138 63572 +117.199.5.229 28835 +66.231.126.16 53509 +151.68.147.67 38146 +86.28.168.196 52549 +95.208.206.96 24833 +99.36.177.82 57416 +82.19.43.141 50274 +88.243.226.34 31952 +89.117.4.177 9026 +92.62.81.2 11369 +124.103.179.186 15356 +62.182.72.252 56899 +195.174.137.55 10152 +220.77.252.33 64170 +84.28.164.197 38804 +92.247.230.190 56889 +77.255.188.154 50182 +188.52.90.206 62502 +58.99.68.183 16001 +81.166.131.74 49856 +84.72.160.67 21783 +61.58.164.40 61726 +121.3.76.229 24859 +119.188.12.17 16003 +109.194.148.235 35691 +89.152.22.150 54895 +79.169.181.30 15368 +71.229.7.56 63792 +85.152.185.205 37976 +72.179.54.146 62040 +188.168.19.251 33178 +62.42.136.67 14957 +95.104.224.245 55165 +68.148.68.46 61984 +122.3.9.39 62546 +121.222.50.109 33067 +212.7.27.71 59005 +41.233.123.170 57369 +85.69.170.120 44386 +83.209.26.106 57404 +79.114.213.111 41823 +72.139.120.43 64593 +220.235.102.85 40329 +189.114.35.172 9884 +213.89.205.22 51413 +206.45.53.201 6881 +95.93.140.179 58457 +86.212.236.62 41939 +64.120.217.48 6821 +24.192.141.196 43444 +98.111.205.18 38107 +72.70.248.25 50824 +93.80.95.102 6882 +78.161.215.48 1024 +92.46.27.57 32582 +109.185.14.134 10020 +76.10.184.99 48754 +59.129.24.10 12345 +79.167.72.16 24971 +76.69.58.83 33258 +212.75.11.116 18431 +91.111.73.116 60521 +188.177.32.124 25573 +70.119.124.175 32302 +93.141.74.98 25058 +24.113.236.144 28024 +76.22.33.148 47355 +84.38.176.176 59787 +90.3.48.40 52585 +89.72.89.197 19610 +204.191.41.127 23927 +221.217.45.24 47709 +74.137.200.28 6112 +84.1.255.253 39168 +90.230.207.166 64697 +109.195.179.25 49034 +213.7.173.150 27444 +113.190.35.133 26298 +219.71.14.70 20000 +188.26.238.55 12082 +188.126.90.189 42521 +92.152.222.207 60086 +94.41.126.183 35691 +92.124.18.175 7691 +121.84.53.235 36421 +114.181.232.144 14859 +87.126.166.37 23145 +79.136.38.51 61193 +79.136.29.76 64123 +91.203.188.89 31780 +173.70.56.200 34107 +69.112.65.152 26394 +122.168.6.130 36327 +124.24.226.162 8640 +178.164.171.162 38624 +92.241.245.68 47765 +99.99.66.212 23188 +211.38.161.183 41794 +95.153.168.28 8033 +114.77.55.185 14890 +114.41.140.117 11675 +66.41.250.122 26560 +66.131.96.98 9090 +95.42.148.127 21982 +217.172.183.163 6881 +78.56.249.219 11699 +82.209.126.232 49180 +74.129.176.196 18957 +119.246.185.40 25295 +87.207.245.56 14132 +86.205.109.156 9739 +92.239.247.56 39166 +24.9.173.223 61423 +80.54.16.78 14221 +173.58.23.148 56221 +174.93.222.175 58944 +83.188.251.214 37857 +96.242.15.74 31666 +71.56.126.209 50316 +178.46.224.6 61397 +203.121.129.35 48913 +78.107.255.16 6884 +178.30.150.171 49763 +97.118.36.234 28186 +58.179.125.192 62734 +92.28.78.203 14274 +80.219.210.106 56365 +89.38.197.172 27077 +201.226.156.70 16668 +183.191.171.160 4041 +95.233.192.118 52630 +94.253.81.217 52858 +189.98.226.168 54960 +93.103.210.87 35228 +109.86.255.184 6881 +200.120.232.126 42476 +80.56.123.123 15541 +81.234.102.107 18764 +89.253.109.172 31844 +122.166.49.234 16842 +188.27.102.215 33333 +212.233.236.87 1041 +79.165.176.206 39053 +109.171.12.85 51441 +178.94.111.98 59615 +94.112.39.248 7289 +125.134.85.142 21707 +46.33.245.141 45822 +217.23.176.216 58252 +154.5.172.67 23127 +126.12.49.142 23120 diff --git a/libbitdht/src/example/bdexample.cc b/libbitdht/src/example/bdexample.cc new file mode 100644 index 000000000..0c965eabd --- /dev/null +++ b/libbitdht/src/example/bdexample.cc @@ -0,0 +1,42 @@ + + +#include "bitdht/bdiface.h" +#include "bitdht/bdstddht.h" +#include "bdhandler.h" + +int main(int argc, char **argv) +{ + + /* startup dht : with a random id! */ + bdNodeId ownId; + bdStdRandomNodeId(&ownId); + + uint16_t port = 6775; + std::string appId = "exId"; + std::string bootstrapfile = "bdboot.txt"; + + BitDhtHandler dht(&ownId, port, appId, bootstrapfile); + + /* run your program */ + while(1) + { + bdNodeId searchId; + bdStdRandomNodeId(&searchId); + + dht.FindNode(&searchId); + + sleep(180); + + dht.DropNode(&searchId); + } + + return 1; +} + + + + + + + + diff --git a/libbitdht/src/example/bdhandler.cc b/libbitdht/src/example/bdhandler.cc new file mode 100644 index 000000000..5b3e9b788 --- /dev/null +++ b/libbitdht/src/example/bdhandler.cc @@ -0,0 +1,251 @@ +/* + * libretroshare/src/dht: bdhandler.h + * + * BitDht example interface + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include +#include +#include + +#include "bdhandler.h" + +/* This is a conversion callback class + */ + +class BdCallback: public BitDhtCallback +{ + public: + + BdCallback(BitDhtHandler *parent) + :mParent(parent) { return; } + +virtual int dhtNodeCallback(const bdId *id, uint32_t peerflags) +{ + return mParent->NodeCallback(id, peerflags); +} + +virtual int dhtPeerCallback(const bdNodeId *id, uint32_t status) +{ + return mParent->PeerCallback(id, status); +} + +virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) +{ + return mParent->ValueCallback(id, key, status); +} + + private: + + BitDhtHandler *mParent; +}; + + +BitDhtHandler::BitDhtHandler(bdNodeId *ownId, uint16_t port, std::string appId, std::string bootstrapfile) +{ + std::cerr << "BitDhtHandler::BitDhtHandler()" << std::endl; + std::cerr << "Using Id: "; + bdStdPrintNodeId(std::cerr, ownId); + std::cerr << std::endl; + + std::cerr << "Using Bootstrap File: " << bootstrapfile; + std::cerr << std::endl; + std::cerr << "Converting OwnId to bdNodeId...."; + std::cerr << std::endl; + + /* standard dht behaviour */ + bdDhtFunctions *stdfns = new bdStdDht(); + + std::cerr << "BitDhtHandler() startup ... creating UdpBitDht"; + std::cerr << std::endl; + + /* create dht */ + struct sockaddr_in local; + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_addr.s_addr = 0; + local.sin_port = htons(port); + + mStack = new UdpStack(local); + + mUdpBitDht = new UdpBitDht(mStack, ownId, appId, bootstrapfile, stdfns); + mStack->addReceiver(mUdpBitDht); + + /* setup callback to here */ + BdCallback *bdcb = new BdCallback(this); + mUdpBitDht->addCallback(bdcb); + + std::cerr << "BitDhtHandler() starting threads and dht"; + std::cerr << std::endl; + + mUdpBitDht->start(); /* starts up the bitdht thread */ + + /* switch on the dht too */ + mUdpBitDht->startDht(); +} + + /* pqiNetAssist - external interface functions */ +void BitDhtHandler::enable(bool on) +{ + std::cerr << "p3BitDht::enable(" << on << ")"; + std::cerr << std::endl; + if (on) + { + mUdpBitDht->startDht(); + } + else + { + mUdpBitDht->stopDht(); + } +} + +void BitDhtHandler::shutdown() /* blocking call */ +{ + mUdpBitDht->stopDht(); +} + + +void BitDhtHandler::restart() +{ + mUdpBitDht->stopDht(); + mUdpBitDht->startDht(); +} + +bool BitDhtHandler::getEnabled() +{ + return (mUdpBitDht->stateDht() != 0); +} + +bool BitDhtHandler::getActive() +{ + return (mUdpBitDht->stateDht() >= BITDHT_MGR_STATE_ACTIVE); +} + + + + + /* pqiNetAssistConnect - external interface functions */ + /* add / remove peers */ +bool BitDhtHandler::FindNode(bdNodeId *peerId) +{ + std::cerr << "BitDhtHandler::FindNode("; + bdStdPrintNodeId(std::cerr, peerId); + std::cerr << ")" << std::endl; + + /* add in peer */ + mUdpBitDht->addFindNode(peerId, BITDHT_QFLAGS_DO_IDLE); + + return true ; +} + +bool BitDhtHandler::DropNode(bdNodeId *peerId) +{ + std::cerr << "BitDhtHandler::DropNode("; + bdStdPrintNodeId(std::cerr, peerId); + std::cerr << ")" << std::endl; + std::cerr << std::endl; + + /* remove in peer */ + mUdpBitDht->removeFindNode(peerId); + + return true ; +} + + + +/********************** Callback Functions **************************/ + +int BitDhtHandler::NodeCallback(const bdId *id, uint32_t peerflags) +{ +#ifdef DEBUG_BITDHT + std::cerr << "BitDhtHandler::NodeCallback()"; + bdStdPrintNodeId(std::cerr, &(id->id)); + std::cerr << " flags: " << peerflags; + std::cerr << std::endl; +#endif + + return 0; +} + +int BitDhtHandler::PeerCallback(const bdNodeId *id, uint32_t status) +{ + std::cerr << "BitDhtHandler::PeerCallback() NodeId: "; + bdStdPrintNodeId(std::cerr, id); + std::cerr << std::endl; + + bool connect = false; + switch(status) + { + case BITDHT_MGR_QUERY_FAILURE: + /* do nothing */ + std::cerr << "BitDhtHandler::PeerCallback() QUERY FAILURE ... do nothin "; + std::cerr << std::endl; + + break; + + case BITDHT_MGR_QUERY_PEER_OFFLINE: + /* do nothing */ + + std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER OFFLINE ... do nothin "; + std::cerr << std::endl; + + break; + + case BITDHT_MGR_QUERY_PEER_UNREACHABLE: + /* do nothing */ + + std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER UNREACHABLE ... flag? / do nothin "; + std::cerr << std::endl; + + + break; + + case BITDHT_MGR_QUERY_PEER_ONLINE: + /* do something */ + + std::cerr << "BitDhtHandler::PeerCallback() QUERY PEER ONLINE ... try udp connection"; + std::cerr << std::endl; + + connect = true; + break; + } + return 1; +} + + + +int BitDhtHandler::ValueCallback(const bdNodeId *id, std::string key, uint32_t status) +{ + std::cerr << "BitDhtHandler::ValueCallback() NOOP for NOW"; + std::cerr << std::endl; + + std::cerr << "BitDhtHandler::ValueCallback()"; + bdStdPrintNodeId(std::cerr, id); + std::cerr << " key: " << key; + std::cerr << " status: " << status; + std::cerr << std::endl; + + /* ignore for now */ + return 0; +} + diff --git a/libbitdht/src/example/bdhandler.h b/libbitdht/src/example/bdhandler.h new file mode 100644 index 000000000..88ef8bbee --- /dev/null +++ b/libbitdht/src/example/bdhandler.h @@ -0,0 +1,71 @@ +/* + * libbitdht/src/example/bdhandler.h + * + * BitDht interface example + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#ifndef BITDHT_HANDLER_H +#define BITDHT_HANDLER_H + +#include +#include + +#include "udp/udpstack.h" +#include "udp/udpbitdht.h" +#include "bitdht/bdiface.h" + +/*** This class can be overloaded to use the XXXXCallback() Functions *****/ +class BitDhtIntCallback; + +class BitDhtHandler +{ + + public: + + BitDhtHandler(bdNodeId *ownId, uint16_t port, std::string appId, std::string bootstrapfile); + +void enable(bool on); +void shutdown(); /* blocking call */ +void restart(); + +bool getEnabled(); +bool getActive(); + +bool FindNode(bdNodeId *peerId); +bool DropNode(bdNodeId *peerId); + +virtual int NodeCallback(const bdId *id, uint32_t peerflags); +virtual int PeerCallback(const bdNodeId *id, uint32_t status); +virtual int ValueCallback(const bdNodeId *id, std::string key, uint32_t status); + + private: + + /* real DHT classes */ + UdpStack *mStack; + UdpBitDht *mUdpBitDht; + +}; + + +#endif /* BITDHT_HANDLER_H */ + diff --git a/libbitdht/src/libbitdht.pro b/libbitdht/src/libbitdht.pro new file mode 100644 index 000000000..a260a592f --- /dev/null +++ b/libbitdht/src/libbitdht.pro @@ -0,0 +1,137 @@ +TEMPLATE = lib +CONFIG += staticlib +CONFIG -= qt +TARGET = bitdht +QMAKE_CXXFLAGS *= -Wall -DBE_DEBUG + +profiling { + QMAKE_CXXFLAGS -= -fomit-frame-pointer + QMAKE_CXXFLAGS *= -pg -g -fno-omit-frame-pointer +} + +release { + # not much here yet. +} + +#CONFIG += debug +debug { + QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer + QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer +} + +################################# Linux ########################################## +linux-* { + DESTDIR = lib + QMAKE_CC = g++ +} + +linux-g++ { + OBJECTS_DIR = temp/linux-g++/obj +} + +linux-g++-64 { + OBJECTS_DIR = temp/linux-g++-64/obj +} + +#################### Cross compilation for windows under Linux #################### + +win32-x-g++ { + OBJECTS_DIR = temp/win32xgcc/obj + DESTDIR = lib.win32xgcc + # These have been replaced by _WIN32 && __MINGW32__ + # DEFINES *= WINDOWS_SYS WIN32 WIN_CROSS_UBUNTU + QMAKE_CXXFLAGS *= -Wmissing-include-dirs + QMAKE_CC = i586-mingw32msvc-g++ + QMAKE_LIB = i586-mingw32msvc-ar + QMAKE_AR = i586-mingw32msvc-ar + DEFINES *= STATICLIB WIN32 + + INCLUDEPATH *= /usr/i586-mingw32msvc/include ${HOME}/.wine/drive_c/pthreads/include/ +} +################################# Windows ########################################## + +win32 { + QMAKE_CC = g++ + OBJECTS_DIR = temp/obj + MOC_DIR = temp/moc + DEFINES *= STATICLIB + # These have been replaced by _WIN32 && __MINGW32__ + #DEFINES *= WINDOWS_SYS WIN32 STATICLIB MINGW + DESTDIR = lib + + # Switch off optimization for release version + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE += -O0 + QMAKE_CFLAGS_RELEASE -= -O2 + QMAKE_CFLAGS_RELEASE += -O0 + + # Switch on optimization for debug version + #QMAKE_CXXFLAGS_DEBUG += -O2 + #QMAKE_CFLAGS_DEBUG += -O2 +} + +################################# MacOSX ########################################## + +mac { + QMAKE_CC = g++ + OBJECTS_DIR = temp/obj + MOC_DIR = temp/moc + DESTDIR = lib +} + +################################### COMMON stuff ################################## +################################### COMMON stuff ################################## + +#DEPENDPATH += . \ +INCLUDEPATH += . \ + +HEADERS += \ + bitdht/bdiface.h \ + bitdht/bencode.h \ + bitdht/bdobj.h \ + bitdht/bdmsgs.h \ + bitdht/bdpeer.h \ + bitdht/bdquery.h \ + bitdht/bdhash.h \ + bitdht/bdstore.h \ + bitdht/bdnode.h \ + bitdht/bdmanager.h \ + bitdht/bdstddht.h \ + bitdht/bdhistory.h \ + util/bdnet.h \ + util/bdthreads.h \ + util/bdrandom.h \ + udp/udplayer.h \ + udp/udpstack.h \ + udp/udpbitdht.h \ + bitdht/bdconnection.h \ + bitdht/bdfilter.h \ + bitdht/bdaccount.h \ + bitdht/bdquerymgr.h \ + util/bdbloom.h \ + +SOURCES += \ + bitdht/bencode.c \ + bitdht/bdobj.cc \ + bitdht/bdmsgs.cc \ + bitdht/bdpeer.cc \ + bitdht/bdquery.cc \ + bitdht/bdhash.cc \ + bitdht/bdstore.cc \ + bitdht/bdnode.cc \ + bitdht/bdmanager.cc \ + bitdht/bdstddht.cc \ + bitdht/bdhistory.cc \ + util/bdnet.cc \ + util/bdthreads.cc \ + util/bdrandom.cc \ + udp/udplayer.cc \ + udp/udpstack.cc \ + udp/udpbitdht.cc \ + bitdht/bdconnection.cc \ + bitdht/bdfilter.cc \ + bitdht/bdaccount.cc \ + bitdht/bdquerymgr.cc \ + util/bdbloom.cc \ + + diff --git a/libbitdht/src/mingw32make.bat b/libbitdht/src/mingw32make.bat new file mode 100644 index 000000000..358dbdb5e --- /dev/null +++ b/libbitdht/src/mingw32make.bat @@ -0,0 +1,13 @@ +set QTDIR=d:\qt\2010.01 +set MINGW=%QTDIR%\mingw + +set PATH=%QTDIR%\qt\bin;%QTDIR%\bin;%MINGW%\bin;%PATH% + +mingw32-make clean + +qmake libbitdht.pro + +mingw32-make + +pause + diff --git a/libbitdht/src/tests/Makefile b/libbitdht/src/tests/Makefile new file mode 100644 index 000000000..5d6cc7f5c --- /dev/null +++ b/libbitdht/src/tests/Makefile @@ -0,0 +1,91 @@ + +LIB_TOP_DIR = .. +TEST_TOP_DIR = $(LIB_TOP_DIR)/tests + +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(TEST_TOP_DIR)/scripts/config.mk +############################################################### + +# Generic Test Harnesses. +TESTOBJ = bdmetric_test.o bdmsgs_test.o bdnode_test.o bdspace_test.o +TESTOBJ += bdmgr_multitest.o bdquery_test.o bdstore_test.o +TESTOBJ += bdmidids_test.o bdspace_test2.o udpbitdht_nettest.o +TESTOBJ += bdbloom_test.o bdbloom_makefilter.o +#TESTOBJ += bencode_test.o bdudp_test.o +#TESTOBJ = bdnode_test.o bdnode_multitest1.o bdnode_test2.o + +TESTS = bdmetric_test bdmsgs_test bdspace_test +TESTS += bdmgr_multitest bdquery_test bdstore_test +TESTS += bdmidids_test bdspace_test2 udpbitdht_nettest +TESTS += bdbloom_test +#TESTS += bencode_test bdudp_test +#Tests to Fix. +#TESTS = bdnode_test bdnode_multitest1 bdnode_test2 + +MANUAL_TESTS = + +all: tests $(MANUAL_TESTS) + +bdmsgs_test: bdmsgs_test.o + $(CC) $(CFLAGS) -o bdmsgs_test bdmsgs_test.o $(LIBS) + +bdmetric_test: bdmetric_test.o + $(CC) $(CFLAGS) -o bdmetric_test bdmetric_test.o $(LIBS) + +bdquery_test: bdquery_test.o + $(CC) $(CFLAGS) -o bdquery_test bdquery_test.o $(LIBS) + +bdspace_test: bdspace_test.o + $(CC) $(CFLAGS) -o bdspace_test bdspace_test.o $(LIBS) + +bdspace_test2: bdspace_test2.o + $(CC) $(CFLAGS) -o bdspace_test2 bdspace_test2.o $(LIBS) + +bdnode_test: bdnode_test.o + $(CC) $(CFLAGS) -o bdnode_test bdnode_test.o $(LIBS) + +bdnode_test2: bdnode_test2.o + $(CC) $(CFLAGS) -o bdnode_test2 bdnode_test2.o $(LIBS) + +bdmidids_test: bdmidids_test.o + $(CC) $(CFLAGS) -o bdmidids_test bdmidids_test.o $(LIBS) + + +bdnode_multitest1: bdnode_multitest1.o + $(CC) $(CFLAGS) -o bdnode_multitest1 bdnode_multitest1.o $(LIBS) + +bdmgr_multitest: bdmgr_multitest.o + $(CC) $(CFLAGS) -o bdmgr_multitest bdmgr_multitest.o $(LIBS) + + +bdstore_test: bdstore_test.o + $(CC) $(CFLAGS) -o bdstore_test bdstore_test.o $(LIBS) + +bdudp_test: bdudp_test.o + $(CC) $(CFLAGS) -o bdudp_test bdudp_test.o $(LIBS) + +udpbitdht_nettest: udpbitdht_nettest.o + $(CC) $(CFLAGS) -o udpbitdht_nettest udpbitdht_nettest.o $(LIBS) + +bencode_test: bencode_test.o + $(CC) $(CFLAGS) -o bencode_test bencode_test.o $(LIBS) + +bdbloom_test: bdbloom_test.o + $(CC) $(CFLAGS) -o bdbloom_test bdbloom_test.o $(LIBS) + +bdbloom_makefilter: bdbloom_makefilter.o + $(CC) $(CFLAGS) -o bdbloom_makefilter bdbloom_makefilter.o $(LIBS) + + +clobber: remove_extra_files + +remove_extra_files: + -$(RM) $(MANUAL_TESTS) + +############################################################### +include $(TEST_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libbitdht/src/tests/bdbloom_makefilter.cc b/libbitdht/src/tests/bdbloom_makefilter.cc new file mode 100644 index 000000000..ceb95c7c3 --- /dev/null +++ b/libbitdht/src/tests/bdbloom_makefilter.cc @@ -0,0 +1,91 @@ +/* + * bitdht/bdbloom_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "util/bdbloom.h" +#include "bitdht/bdstddht.h" +#include +#include + +#define N_TESTS 100 + +int main(int argc, char **argv) +{ + /* read from the file */ + if (argc < 2) + { + std::cerr << "Missing Hash File"; + std::cerr << std::endl; + } + + FILE *fd = fopen(argv[1], "r"); + if (!fd) + { + std::cerr << "Failed to Open File: " << argv[1]; + std::cerr << std::endl; + return 1; + } + + char line[1000]; + + bdBloom filter; + + int nHashes = 0; + while(fgets(line, 1000-1, fd)) + { + std::string hash = line; + std::cerr << "Read Hash: " << hash; + std::cerr << std::endl; + + filter.add(hash); + nHashes++; + } + fclose(fd); + + filter.printFilter(std::cerr); + + int bits = filter.countBits(); + int filterBits = filter.filterBits(); + std::cerr << "Filter Bits Set: " << bits; + std::cerr << std::endl; + + double possible = ((double) bits) * bits; + double max = ((double) filterBits) * filterBits; + std::cerr << "Therefore Possible Finds: " << possible << "/" << max << " = %" << 100 * possible / max; + std::cerr << std::endl; + std::cerr << "With Insertions: " << nHashes; + std::cerr << std::endl; + + std::cerr << std::endl; + std::cerr << std::endl; + + std::cerr << "Filter String: " << filter.getFilter() << std::endl; + std::cerr << std::endl; + std::cerr << std::endl; + + return 1; +} + + diff --git a/libbitdht/src/tests/bdbloom_test.cc b/libbitdht/src/tests/bdbloom_test.cc new file mode 100644 index 000000000..aacb70395 --- /dev/null +++ b/libbitdht/src/tests/bdbloom_test.cc @@ -0,0 +1,165 @@ +/* + * bitdht/bdbloom_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "util/bdbloom.h" +#include "bitdht/bdstddht.h" +#include +#include + +#define N_TESTS 100 + +int main(int argc, char **argv) +{ + + /* Do this multiple times */ + int i; + + + bdBloom filter; + + std::list testIds; + std::list::iterator it; + + for(i = 0; i < N_TESTS; i++) + { + bdNodeId targetId; + bdStdRandomNodeId(&targetId); + testIds.push_back(targetId); + } + + std::cerr << "Test bdBloom Filter...." << std::endl; + for(it = testIds.begin(); it != testIds.end(); it++) + { + bdNodeId targetId = *it; + + std::cerr << "-------------------------------------------------" << std::endl; + std::cerr << "Inserting : "; + std::ostringstream str; + bdStdPrintNodeId(str, &targetId); + std::cerr << str.str(); + std::cerr << std::endl; + + filter.add(str.str()); + + filter.printFilter(std::cerr); + } + + std::string fs1 = filter.getFilter(); + /* now extract, and reinsert filter */ + bdBloom filter2; + filter2.setFilterBits(fs1); + + std::string fs2 = filter2.getFilter(); + filter2.printFilter(std::cerr); + + if (fs1 == fs2) + { + std::cerr << "SUCCESS: Filter Correctly Transferred!"; + std::cerr << std::endl; + } + else + { + std::cerr << "FAILURE: Filter Not Transferred!"; + std::cerr << std::endl; + } + + + for(it = testIds.begin(); it != testIds.end(); it++) + { + bdNodeId targetId = *it; + + std::cerr << "-------------------------------------------------" << std::endl; + std::cerr << "Testing : "; + std::cerr << std::endl; + + std::ostringstream str; + bdStdPrintNodeId(str, &targetId); + std::cerr << str.str() << std::endl; + + if (filter2.test(str.str())) + { + std::cerr << "SUCCESS: Filter Found Entry"; + std::cerr << std::endl; + } + else + { + std::cerr << "FAILURE: Filter Didn't Found Entry"; + std::cerr << std::endl; + } + } + + int bits = filter.countBits(); + int filterBits = filter.filterBits(); + std::cerr << "Filter Bits Set: " << bits; + std::cerr << std::endl; + + double possible = ((double) bits) * bits; + double max = ((double) filterBits) * filterBits; + std::cerr << "Therefore Possible Finds: " << possible << "/" << max << " = %" << 100 * possible / max; + std::cerr << std::endl; + std::cerr << "With Insertions: " << N_TESTS; + std::cerr << std::endl; + +#define FINAL_TESTS (1000000) + int found = 0; + int didnt = 0; + for(i = 0; i < FINAL_TESTS; i++) + { + if ((i != 0) && (i % 100000 == 0)) + { + std::cerr << "Run " << i << " Checks" << std::endl; + } + + bdNodeId targetId; + bdStdRandomNodeId(&targetId); + std::ostringstream str; + bdStdPrintNodeId(str, &targetId); + + if (filter2.test(str.str())) + { + found++; + } + else + { + didnt++; + } + } + + std::cerr << "Final Stats: " << FINAL_TESTS << " random checks done"; + std::cerr << std::endl; + std::cerr << "\t" << found << " " << 100.0 * ((double) found) / FINAL_TESTS << "% found"; + std::cerr << std::endl; + std::cerr << "\t" << didnt << " " << 100.0 * ((double) didnt) / FINAL_TESTS << "% didnt"; + std::cerr << std::endl; + + + + + + return 1; +} + + diff --git a/libbitdht/src/tests/bdboot.txt b/libbitdht/src/tests/bdboot.txt new file mode 100644 index 000000000..8869d39f6 --- /dev/null +++ b/libbitdht/src/tests/bdboot.txt @@ -0,0 +1,500 @@ +93.113.253.235 10351 +109.195.26.63 35691 +78.84.189.238 16105 +93.149.194.159 10006 +142.165.155.66 54333 +87.2.252.141 32523 +86.28.119.162 65393 +75.141.203.120 9269 +61.219.92.157 26309 +113.197.131.184 39390 +61.202.78.247 22221 +99.192.87.181 63645 +186.14.24.166 53495 +90.191.162.101 56943 +75.9.79.58 49173 +189.79.164.180 51916 +188.2.188.200 15904 +216.137.107.5 42096 +119.82.197.117 14165 +93.142.184.229 30804 +81.230.155.227 49912 +78.3.22.204 12176 +70.53.218.176 48079 +99.138.101.252 45682 +109.96.227.190 17059 +71.72.158.196 37961 +92.80.210.120 10000 +91.146.132.224 12566 +81.182.99.86 58659 +83.217.46.30 59184 +118.173.96.14 15000 +41.107.83.159 10000 +80.189.136.230 51692 +212.142.83.32 48265 +194.220.84.244 22464 +79.219.206.130 57803 +94.179.29.137 9371 +86.132.129.242 23071 +92.101.129.144 59039 +113.77.164.93 31872 +114.149.135.219 7128 +178.90.5.139 14054 +85.67.83.55 18671 +77.121.45.122 26731 +84.202.51.66 52591 +80.9.93.215 16504 +83.82.128.46 62372 +178.167.21.234 6881 +82.243.15.108 64162 +89.241.183.88 11887 +187.1.109.123 20546 +76.104.157.104 13313 +121.190.21.7 23585 +111.184.60.209 8473 +175.137.141.17 4841 +114.47.124.155 16001 +190.9.80.109 60921 +78.53.157.19 61597 +82.22.73.207 39714 +94.227.124.236 51413 +93.86.121.17 23491 +78.8.127.204 49158 +173.21.246.1 28175 +74.105.104.186 23922 +93.106.78.26 62241 +95.52.220.221 46873 +46.41.99.164 41403 +90.3.189.132 27532 +95.24.191.34 37686 +94.158.206.37 47733 +24.192.141.196 43444 +88.114.60.226 14701 +190.233.28.216 10035 +187.59.104.184 38406 +88.241.54.177 6881 +75.169.41.44 23921 +212.231.219.123 30749 +95.111.59.146 31360 +117.20.185.249 34787 +184.15.43.192 25872 +41.236.143.104 18254 +212.37.169.128 31631 +93.103.167.242 35298 +95.208.34.13 28134 +81.184.29.241 60338 +173.176.243.27 31393 +200.30.215.247 53196 +95.27.138.236 32373 +78.181.51.1 56672 +69.113.118.17 43710 +118.15.159.47 14924 +219.78.37.4 17323 +79.179.35.221 8080 +41.233.232.153 28027 +2.40.81.5 39425 +76.181.24.116 35553 +183.37.193.84 21819 +188.2.108.62 62838 +188.2.182.88 12877 +93.150.26.240 19076 +78.60.165.96 46785 +99.242.143.80 19034 +190.166.108.145 57967 +90.15.142.10 20380 +212.139.216.168 28287 +79.173.18.85 16234 +109.122.6.119 35077 +95.70.76.28 39132 +178.206.42.99 35691 +189.110.158.105 52423 +112.195.15.4 1083 +219.79.127.226 20579 +194.102.155.85 30332 +94.158.107.234 32516 +144.85.198.132 55745 +220.132.140.86 16001 +92.14.78.83 15294 +92.147.31.42 14099 +86.13.110.77 47020 +95.8.170.249 34481 +178.166.138.75 33347 +117.195.196.154 53480 +189.159.45.177 27778 +99.228.167.174 18537 +60.34.32.239 64398 +71.103.193.176 50913 +213.156.101.150 47078 +95.72.233.199 13299 +70.70.161.4 37542 +89.252.11.169 39924 +94.21.150.86 20004 +90.206.166.236 30055 +92.45.198.23 56969 +71.190.128.27 8181 +201.209.54.201 26726 +201.254.175.141 1052 +86.22.154.1 34153 +202.212.230.225 62582 +217.210.126.55 6881 +92.242.118.12 59741 +195.18.28.147 35691 +77.105.61.152 10003 +90.157.174.67 64061 +109.184.242.18 19268 +97.95.66.89 37027 +109.212.41.127 46365 +204.182.12.51 56654 +186.205.50.126 54325 +119.247.252.118 13277 +118.20.246.94 7113 +116.3.57.205 19699 +189.101.77.13 52448 +89.178.80.137 40431 +75.69.6.91 6881 +98.121.161.117 54068 +69.153.56.74 13496 +78.62.118.16 47252 +79.46.255.126 26751 +122.169.170.101 10028 +123.193.220.215 54157 +218.218.128.104 49963 +219.106.122.171 55959 +112.210.235.218 27157 +90.60.172.96 6881 +92.17.64.55 10008 +98.223.44.215 35998 +190.28.95.226 41411 +186.206.12.110 9037 +90.218.16.149 40972 +109.87.52.11 20186 +77.101.143.17 37570 +82.34.77.180 41818 +94.41.21.214 36939 +85.127.34.173 10085 +83.4.7.35 19276 +91.200.254.202 12737 +87.121.66.246 12420 +81.198.26.183 39568 +92.132.93.148 23722 +91.77.94.227 14372 +206.45.53.201 6881 +74.95.222.53 60733 +72.19.62.187 21338 +71.201.200.183 41435 +24.98.172.105 61382 +78.92.152.60 12365 +93.87.252.82 21564 +61.228.64.67 38444 +219.79.74.97 43357 +118.173.119.134 10993 +123.254.183.208 36587 +99.111.202.61 10341 +94.194.87.1 31169 +93.23.174.188 39415 +78.70.152.38 30356 +94.251.17.152 35691 +67.175.189.15 16703 +109.242.224.50 45107 +86.196.29.237 28767 +84.252.27.201 17253 +70.162.57.125 48027 +210.6.173.193 6886 +210.6.173.193 6887 +110.132.207.153 29959 +94.25.171.229 40703 +178.53.139.9 13328 +85.170.52.161 12310 +85.17.5.132 51413 +95.130.12.23 61546 +87.106.18.80 21060 +85.69.170.120 44386 +77.203.179.13 23145 +86.125.150.25 59847 +82.130.251.32 54834 +83.139.173.200 56953 +87.11.51.210 8500 +85.70.116.131 19860 +98.244.158.38 40311 +98.143.96.103 21711 +84.215.125.229 51413 +217.172.179.78 18692 +74.67.142.125 17874 +98.195.197.177 32346 +207.216.26.166 36202 +76.29.22.154 37778 +114.220.155.188 7576 +109.8.31.209 16726 +71.100.182.81 21724 +58.85.55.238 14725 +67.174.74.95 35000 +99.194.168.253 29358 +85.228.78.9 47500 +71.187.90.32 50260 +216.113.97.150 29801 +85.49.133.208 27989 +94.208.99.166 13733 +78.83.127.162 53345 +91.121.174.148 55690 +94.3.214.214 56319 +94.23.212.70 57174 +85.217.136.179 47053 +78.94.104.125 63580 +95.105.198.233 80 +95.84.255.201 17122 +91.100.81.198 49999 +78.90.128.10 52518 +95.26.156.134 19486 +82.232.104.187 16807 +79.101.213.250 13121 +75.118.101.142 30141 +93.89.209.227 19280 +82.7.214.190 21876 +217.168.214.39 19766 +70.114.173.8 26375 +72.204.16.239 50200 +24.9.187.250 29985 +76.16.32.242 16278 +74.79.89.24 11697 +200.158.63.125 39637 +82.74.116.4 17223 +96.52.145.135 12607 +77.99.18.29 63852 +217.77.60.189 58847 +82.74.117.94 25000 +85.238.105.154 40000 +67.83.132.220 51515 +82.237.186.158 6881 +188.187.172.48 63699 +90.192.99.87 19903 +74.162.128.111 65432 +109.184.8.183 64619 +77.198.210.34 58320 +89.90.170.230 23442 +97.100.136.205 25942 +98.119.32.149 13434 +68.51.90.191 16878 +142.167.52.20 42904 +118.5.144.222 45043 +98.149.14.52 26659 +79.108.19.172 52750 +79.115.9.172 63866 +79.168.88.72 12883 +91.148.128.36 24464 +85.187.24.45 14111 +82.240.100.118 19906 +89.135.149.47 52055 +71.185.134.201 50771 +77.78.178.156 60852 +24.186.53.139 61726 +74.140.96.199 19420 +109.110.3.135 57756 +24.16.216.224 45546 +85.132.109.108 21838 +118.101.115.37 10395 +24.102.8.251 34774 +85.247.82.191 6882 +59.113.66.184 8473 +220.61.29.35 32776 +82.244.72.113 10620 +124.144.11.76 26144 +59.100.97.236 421 +115.166.24.156 21109 +188.36.71.13 45750 +95.37.35.103 6881 +78.159.108.124 63982 +81.166.43.192 48429 +85.222.55.113 51409 +62.80.183.225 26033 +84.85.23.152 56471 +86.165.244.171 6881 +90.157.165.36 1046 +84.61.147.98 6889 +81.154.201.146 45682 +24.60.118.120 60005 +24.61.141.82 60919 +2.106.159.182 28860 +78.57.176.166 33061 +87.1.182.97 48031 +84.3.249.76 11353 +87.120.64.46 25428 +88.181.152.48 44330 +109.160.201.32 27495 +188.230.38.94 32525 +90.214.93.249 25238 +84.249.175.45 34904 +114.45.181.114 61860 +69.176.179.196 53579 +220.210.178.105 37492 +213.93.83.121 51413 +88.191.117.198 46881 +212.233.241.25 20164 +96.38.226.139 47850 +77.120.182.144 30585 +82.228.54.32 32492 +92.138.66.102 17105 +95.158.179.229 13684 +77.70.20.90 17610 +87.203.114.107 39136 +85.113.48.19 6881 +174.51.65.149 46912 +67.215.242.139 6881 +99.111.240.83 54548 +24.54.1.238 60738 +65.13.127.70 56958 +83.83.52.92 10000 +60.62.38.145 22101 +61.22.93.23 35048 +58.152.160.161 51954 +121.7.94.125 23766 +89.161.85.250 27553 +84.24.37.138 15678 +80.109.42.12 29168 +87.50.207.134 60361 +93.72.108.237 39272 +91.117.209.44 17063 +109.86.246.11 11400 +24.49.43.222 26917 +64.121.80.63 45642 +76.20.230.30 58335 +86.10.209.139 12001 +67.215.242.138 6881 +87.120.78.253 25118 +84.82.225.139 52002 +200.104.218.244 24447 +116.81.147.106 10014 +76.238.231.136 37770 +68.148.109.134 32815 +78.43.60.243 18973 +62.33.209.243 20600 +84.40.115.5 49669 +93.11.108.82 45078 +90.157.139.222 28487 +79.124.27.117 26472 +99.225.194.114 45586 +79.83.184.114 40139 +109.104.187.16 30000 +87.101.162.223 21364 +99.251.104.111 60382 +130.63.133.216 47451 +66.110.140.217 6881 +87.120.113.236 18301 +64.216.32.37 6881 +75.137.149.242 19860 +69.137.192.214 6881 +208.102.25.182 50675 +173.51.87.191 37950 +75.72.144.15 54485 +68.148.20.202 22025 +99.112.96.188 35979 +67.162.118.20 9820 +69.148.177.153 26961 +58.69.218.34 38072 +121.222.5.240 51932 +88.161.156.9 48251 +88.200.104.216 27784 +62.148.159.55 52603 +109.160.52.2 36630 +69.123.52.81 64701 +95.181.30.110 37075 +65.5.225.206 6881 +74.12.101.58 61864 +174.71.75.121 48749 +186.66.255.5 37580 +24.116.239.194 59147 +95.65.178.164 23715 +220.70.175.83 43726 +182.169.110.245 64684 +122.166.49.234 16842 +119.247.164.154 22132 +77.202.227.150 15621 +79.129.217.171 17248 +88.80.49.238 35857 +96.250.206.111 20965 +98.117.197.195 53478 +81.57.50.221 11095 +71.72.3.201 40665 +72.88.206.217 57170 +95.29.8.61 59559 +24.235.41.231 11181 +142.163.161.23 60957 +70.27.27.105 23047 +90.42.104.194 10595 +114.36.7.29 26051 +78.26.164.132 59437 +70.126.197.41 14207 +142.162.65.171 30537 +187.14.3.249 8753 +62.166.34.78 62133 +82.45.213.218 24740 +213.123.71.145 56050 +93.12.188.2 22070 +203.184.0.161 10295 +93.152.176.62 6881 +69.156.209.139 19165 +96.20.161.32 44893 +83.81.119.121 34439 +109.208.211.98 36278 +154.5.172.67 23127 +93.72.132.238 47860 +89.215.103.145 16242 +89.212.93.62 32590 +84.3.208.199 50001 +85.87.98.187 53911 +93.127.107.157 35691 +188.195.145.172 21827 +184.56.151.190 11951 +98.168.190.247 61279 +83.237.221.242 16613 +75.30.79.175 57107 +90.24.61.26 57262 +125.27.132.48 10018 +94.98.122.161 62266 +178.162.184.203 6821 +93.182.0.249 32217 +81.25.50.209 44962 +94.24.137.191 35691 +78.82.124.105 20047 +71.53.119.62 23108 +74.119.191.181 62498 +46.33.237.37 21135 +183.83.30.78 15822 +109.75.207.23 14085 +92.147.163.123 36706 +110.3.132.18 10149 +90.38.163.86 61080 +89.133.173.35 37855 +77.50.87.114 11399 +76.106.47.230 6881 +24.206.168.152 22102 +24.47.46.185 59822 +60.241.156.191 24064 +118.150.145.87 16553 +98.121.178.252 31353 +24.64.233.94 17962 +95.62.64.40 12174 +85.91.17.78 8644 +98.148.37.251 55774 +122.117.82.108 16293 +200.26.143.117 14013 +187.37.80.22 25095 +95.19.224.225 25446 +79.132.4.131 36094 +217.208.59.201 46227 +109.86.136.248 44281 +85.54.187.59 28890 +99.225.92.6 38080 +178.40.89.75 10018 +79.132.182.136 30129 +174.59.144.37 5895 +189.237.151.135 17643 +189.114.233.119 12308 +109.168.162.23 32195 +93.13.211.51 59788 +80.56.69.253 25685 +77.70.96.3 11949 +18.242.7.242 65435 +83.131.224.235 62622 +201.229.9.69 28159 +201.223.65.4 43804 +77.167.196.115 64788 diff --git a/libbitdht/src/tests/bdmetric_test.cc b/libbitdht/src/tests/bdmetric_test.cc new file mode 100644 index 000000000..d0865794e --- /dev/null +++ b/libbitdht/src/tests/bdmetric_test.cc @@ -0,0 +1,264 @@ +/* + * bitdht/bdmetric_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdpeer.h" +#include "bitdht/bdstddht.h" +#include +#include + + +#include "utest.h" + +bool test_metric_explicit(); +bool test_metric_random(); + +INITTEST(); + +int main(int argc, char **argv) +{ + std::cerr << "libbitdht: " << argv[0] << std::endl; + + test_metric_explicit(); + + FINALREPORT("libbitdht: Metric Tests"); + return TESTRESULT(); +} + +bool test_metric_explicit() +{ + std::cerr << "test_metric_explicit:" << std::endl; + +#define NUM_IDS 6 + + /* create some ids */ + bdId id[NUM_IDS]; + int i, j; + + /* create a set of known ids ... and + * check the metrics are what we expect. + */ + + for(i = 0; i < NUM_IDS; i++) + { + bdZeroNodeId(&(id[i].id)); + } + + /* test the zero node works */ + for(i = 0; i < NUM_IDS; i++) + { + for(j = 0; j < BITDHT_KEY_LEN; j++) + { + CHECK(id[i].id.data[j] == 0); + } + } + + for(i = 0; i < NUM_IDS; i++) + { + for(j = i; j < NUM_IDS; j++) + { + id[j].id.data[BITDHT_KEY_LEN - i - 1] = 1; + } + } + + for(i = 0; i < NUM_IDS; i++) + { + fprintf(stderr, "id[%d]:", i+1); + bdStdPrintId(std::cerr,&(id[i])); + fprintf(stderr, "\n"); + } + + /* now do the sums */ + bdMetric met; + bdMetric met2; + int bdist = 0; + + for(i = 0; i < 6; i++) + { + for(j = i+1; j < 6; j++) + { + bdStdDistance(&(id[i].id), &(id[j].id), &met); + + fprintf(stderr, "%d^%d:", i, j); + bdStdPrintNodeId(std::cerr,&met); + fprintf(stderr, "\n"); + + bdist = bdStdBucketDistance(&met); + fprintf(stderr, " bucket: %d\n", bdist); + } + } + +#if 0 + int c1 = met < met2; + int c2 = met2 < met; + + fprintf(stderr, "1^2<1^3? : %d 1^3<1^2?: %d\n", c1, c2); +#endif + + + REPORT("Test Byte Manipulation"); + //FAILED("Couldn't Bind to socket"); + + return 1; +} + + + +bool test_metric_random() +{ + std::cerr << "test_metric_random:" << std::endl; + + /* create some ids */ + bdId id1; + bdId id2; + bdId id3; + bdId id4; + bdId id5; + bdId id6; + + bdStdRandomId(&id1); + bdStdRandomId(&id2); + bdStdRandomId(&id3); + bdStdRandomId(&id4); + bdStdRandomId(&id5); + bdStdRandomId(&id6); + + fprintf(stderr, "id1:"); + bdStdPrintId(std::cerr,&id1); + fprintf(stderr, "\n"); + + fprintf(stderr, "id2:"); + bdStdPrintId(std::cerr,&id2); + fprintf(stderr, "\n"); + + fprintf(stderr, "id3:"); + bdStdPrintId(std::cerr,&id3); + fprintf(stderr, "\n"); + + fprintf(stderr, "id4:"); + bdStdPrintId(std::cerr,&id4); + fprintf(stderr, "\n"); + + fprintf(stderr, "id5:"); + bdStdPrintId(std::cerr,&id5); + fprintf(stderr, "\n"); + + fprintf(stderr, "id6:"); + bdStdPrintId(std::cerr,&id6); + fprintf(stderr, "\n"); + + /* now do the sums */ + bdMetric met; + bdMetric met2; + int bdist = 0; + bdStdDistance(&(id1.id), &(id2.id), &met); + + fprintf(stderr, "1^2:"); + bdStdPrintNodeId(std::cerr,&met); + fprintf(stderr, "\n"); + bdist = bdStdBucketDistance(&met); + fprintf(stderr, " bucket: %d\n", bdist); + + bdStdDistance(&(id1.id), &(id3.id), &met2); + bdist = bdStdBucketDistance(&met2); + + fprintf(stderr, "1^3:"); + bdStdPrintNodeId(std::cerr,&met2); + fprintf(stderr, "\n"); + fprintf(stderr, " bucket: %d\n", bdist); + + int c1 = met < met2; + int c2 = met2 < met; + + fprintf(stderr, "1^2<1^3? : %d 1^3<1^2?: %d\n", c1, c2); + + + bdStdDistance(&(id1.id), &(id4.id), &met2); + bdist = bdStdBucketDistance(&met2); + + fprintf(stderr, "1^4:"); + bdStdPrintNodeId(std::cerr,&met2); + fprintf(stderr, "\n"); + fprintf(stderr, " bucket: %d\n", bdist); + + c1 = met < met2; + c2 = met2 < met; + + fprintf(stderr, "1^2<1^4? : %d 1^4<1^2?: %d\n", c1, c2); + + bdStdDistance(&(id1.id), &(id5.id), &met); + bdist = bdStdBucketDistance(&met); + + fprintf(stderr, "1^5:"); + bdStdPrintNodeId(std::cerr,&met); + fprintf(stderr, "\n"); + fprintf(stderr, " bucket: %d\n", bdist); + + bdStdDistance(&(id1.id), &(id6.id), &met); + bdist = bdStdBucketDistance(&met); + + fprintf(stderr, "1^6:"); + bdStdPrintNodeId(std::cerr,&met); + fprintf(stderr, "\n"); + fprintf(stderr, " bucket: %d\n", bdist); + + bdStdDistance(&(id2.id), &(id3.id), &met); + bdist = bdStdBucketDistance(&met); + + fprintf(stderr, "2^3:"); + bdStdPrintNodeId(std::cerr,&met); + fprintf(stderr, "\n"); + fprintf(stderr, " bucket: %d\n", bdist); + + + fprintf(stderr, "id1:"); + bdStdPrintId(std::cerr,&id1); + fprintf(stderr, "\n"); + + fprintf(stderr, "id2:"); + bdStdPrintId(std::cerr,&id2); + fprintf(stderr, "\n"); + + fprintf(stderr, "id3:"); + bdStdPrintId(std::cerr,&id3); + fprintf(stderr, "\n"); + + fprintf(stderr, "id4:"); + bdStdPrintId(std::cerr,&id4); + fprintf(stderr, "\n"); + + fprintf(stderr, "id5:"); + bdStdPrintId(std::cerr,&id5); + fprintf(stderr, "\n"); + + fprintf(stderr, "id6:"); + bdStdPrintId(std::cerr,&id6); + fprintf(stderr, "\n"); + + + return 1; +} + + diff --git a/libbitdht/src/tests/bdmgr_multitest.cc b/libbitdht/src/tests/bdmgr_multitest.cc new file mode 100644 index 000000000..cfed76862 --- /dev/null +++ b/libbitdht/src/tests/bdmgr_multitest.cc @@ -0,0 +1,186 @@ +/* + * bitdht/bdmgr_multitest.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdmanager.h" +#include "bitdht/bdstddht.h" +#include "udp/udplayer.h" +#include "util/bdrandom.h" + +#include + +/********************************************************************************** + * tests of multi bdnodes all connected together. + * in these cases, the networking step is shortcut and the ip addresses ignored. + * instead the port number is used as an index to peers. + * + * test1() + * Small cross seeding, and static list of peers. + * Set it going - and see what happens. + */ + +std::map nodes; +std::map addrIdx; + +int main(int argc, char **argv) +{ + time_t sim_time = 600; + time_t starttime = time(NULL); + int n_nodes = 1000; + std::map::iterator it; + std::map::iterator nit; + std::map::iterator ait; + + int i, j; + + bdDhtFunctions *fns = new bdStdDht(); + + std::cerr << "bdmgr_multitest() Setting up Nodes" << std::endl; + /* setup nodes */ + for(i = 0; i < n_nodes; i++) + { + bdId id; + + bdStdRandomId(&id); + + //id.addr.sin_port = htons(i); + //((uint32_t *) (id.id.data))[0] = i * 16 * 16; /* force this so the sort order is maintained! */ + std::cerr << "bdmgr_multitest() Id: "; + fns->bdPrintId(std::cerr, &id); + std::cerr << std::endl; + + bdNodeManager *mgr = new bdNodeManager(&(id.id), "bdTEST", "", fns); + + /* Store in nodes */ + nodes[id] = mgr; + /* Store in indices */ + addrIdx[id.addr] = id; + + } + + std::cerr << "bdmgr_multitest() Cross Seeding" << std::endl; + /* do a little cross seeding */ + for(nit = nodes.begin(); nit != nodes.end(); nit++) + { + for(j = 0; j < 2; j++) + { + int peeridx = bdRandom::random_u32() % n_nodes; + for(i = 0, it = nodes.begin(); + (i < peeridx) && (it != nodes.end()); i++, it++) + { + /* empty */ + } + if (it != nodes.end()) + { + nit->second->addPotentialPeer((bdId *) &(it->first), NULL); + } + } + } + + /* ready to run */ + + std::cerr << "bdmgr_multitest() Simulation Time....." << std::endl; + i = 0; + while(time(NULL) < starttime + sim_time) + { + i++; + std::cerr << "bdmgr_multitest() Iteration: " << i << std::endl; + + for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) + { + /* extract messages to go -> and deliver */ +#define MAX_MSG_SIZE 10240 + struct sockaddr_in addr; + char data[MAX_MSG_SIZE]; + int len = MAX_MSG_SIZE; + + while(it->second->outgoingMsg(&addr, data, &len)) + { + std::cerr << "bdmgr_multitest() Msg from Peer: " << j; + + /* find the peer */ + ait = addrIdx.find(addr); + nit = nodes.end(); + if (ait != addrIdx.end()) + { + nit = nodes.find(ait->second); + std::cerr << " For: "; + fns->bdPrintId(std::cerr, &(nit->first)); + std::cerr << std::endl; + } + else + { + std::cerr << " For Unknown Destination"; + std::cerr << std::endl; + + } + + if (nit != nodes.end()) + { + /* set from address */ + nit->second->incomingMsg( (sockaddr_in *) &(it->first.addr), data, len); + } + /* reset message size */ + len = MAX_MSG_SIZE; + } + } + + for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) + { + /* tick */ + std::cerr << "bdmgr_multitest() Ticking peer: " << j << std::endl; + it->second->iteration(); + } + + + /* have a rest */ + sleep(1); + } + + std::cerr << "bdmgr_multitest() Displying States"<< std::endl; + for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) + { + /* tick */ + std::cerr << "bdmgr_multitest() Peer State: " << j << std::endl; + it->second->printState(); + } + +} + + + + + + + + + + + + + + + + diff --git a/libbitdht/src/tests/bdmidids_test.cc b/libbitdht/src/tests/bdmidids_test.cc new file mode 100644 index 000000000..de52975cb --- /dev/null +++ b/libbitdht/src/tests/bdmidids_test.cc @@ -0,0 +1,96 @@ +/* + * bitdht/bdmidids_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdpeer.h" +#include "bitdht/bdstddht.h" +#include + +int main(int argc, char **argv) +{ + + /* Do this multiple times */ + int i, j; + + std::cerr << "Test Mid Peer Intersection....." << std::endl; + for(i = 0; i < 10; i++) + { + bdNodeId targetId; + bdNodeId peerId; + + bdStdRandomNodeId(&targetId); + bdStdRandomNodeId(&peerId); + + std::cerr << "-------------------------------------------------" << std::endl; + + for(j = 0; j < 10; j++) + { + + bdNodeId midId; + + bdStdRandomMidId(&targetId, &peerId, &midId); + + bdMetric TPmetric; + bdMetric TMmetric; + bdMetric PMmetric; + + bdStdDistance(&targetId, &peerId, &TPmetric); + bdStdDistance(&targetId, &midId, &TMmetric); + bdStdDistance(&peerId, &midId, &PMmetric); + + int TPdist = bdStdBucketDistance(&TPmetric); + int TMdist = bdStdBucketDistance(&TMmetric); + int PMdist = bdStdBucketDistance(&PMmetric); + + std::cerr << "Target: "; + bdStdPrintNodeId(std::cerr,&targetId); + std::cerr << " Peer: "; + bdStdPrintNodeId(std::cerr,&peerId); + std::cerr << std::endl; + + std::cerr << "\tTarget ^ Peer: "; + bdStdPrintNodeId(std::cerr,&TPmetric); + std::cerr << " Bucket: " << TPdist; + std::cerr << std::endl; + + std::cerr << "\tTarget ^ Mid: "; + bdStdPrintNodeId(std::cerr,&TMmetric); + std::cerr << " Bucket: " << TMdist; + std::cerr << std::endl; + + std::cerr << "\tPeer ^ Mid: "; + bdStdPrintNodeId(std::cerr,&PMmetric); + std::cerr << " Bucket: " << PMdist; + std::cerr << std::endl; + + /* now save mid to peer... and repeat */ + peerId = midId; + } + } + + return 1; +} + + diff --git a/libbitdht/src/tests/bdmsgs_test.cc b/libbitdht/src/tests/bdmsgs_test.cc new file mode 100644 index 000000000..cdfaed7d2 --- /dev/null +++ b/libbitdht/src/tests/bdmsgs_test.cc @@ -0,0 +1,102 @@ + +/* + * bitdht/bdmsgs_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdmsgs.h" +#include "bitdht/bdstddht.h" +#include + +/******************************************************************* + * Test of bencode message creation functions in bdmsgs.cc + * + * Create a couple of each type. + */ + +#define MAX_MESSAGE_LEN 10240 + +int main(int argc, char **argv) +{ + /***** create messages *****/ + char msg[MAX_MESSAGE_LEN]; + int avail = MAX_MESSAGE_LEN -1; + + bdToken tid; + bdToken vid; + bdToken token; + + + bdNodeId ownId; + bdNodeId peerId; + bdNodeId target; + bdNodeId info_hash; + + bdStdRandomNodeId(&ownId); + bdStdRandomNodeId(&peerId); + bdStdRandomNodeId(&target); + bdStdRandomNodeId(&info_hash); + + std::list nodes; + std::list values; + + /* setup tokens */ + strncpy((char*)tid.data, "tid", 4); + strncpy((char*)vid.data, "RS50", 5); + strncpy((char*)token.data, "ToKEn", 6); + + tid.len = 3; + vid.len = 4; + token.len = 5; + + /* setup lists */ + for(int i = 0; i < 8; i++) + { + bdId rndId; + bdStdRandomId(&rndId); + + nodes.push_back(rndId); + values.push_back("values"); + } + + uint32_t port = 1234; + + bitdht_create_ping_msg(&tid, &ownId, msg, avail); + bitdht_response_ping_msg(&tid, &ownId, &vid, msg, avail); + + bitdht_find_node_msg(&tid, &ownId, &target, msg, avail); + bitdht_resp_node_msg(&tid, &ownId, nodes, msg, avail); + + bitdht_get_peers_msg(&tid, &ownId, &info_hash, msg, avail); + bitdht_peers_reply_hash_msg(&tid, &ownId, &token, values, msg, avail); + bitdht_peers_reply_closest_msg(&tid, &ownId, &token, nodes, msg, avail); + + bitdht_announce_peers_msg(&tid, &ownId, &info_hash, port, &token, msg, avail); + bitdht_reply_announce_msg(&tid, &ownId, msg, avail); + + + return 1; +} + + diff --git a/libbitdht/src/tests/bdnode_multitest1.cc b/libbitdht/src/tests/bdnode_multitest1.cc new file mode 100644 index 000000000..5e1a6ebca --- /dev/null +++ b/libbitdht/src/tests/bdnode_multitest1.cc @@ -0,0 +1,185 @@ +/* + * bitdht/bdnode_multitest1.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdnode.h" +#include "bitdht/bdstddht.h" +#include "util/bdrandom.h" + +#include + +/********************************************************************************** + * tests of multi bdnodes all connected together. + * in these cases, the networking step is shortcut and the ip addresses ignored. + * instead the port number is used as an index to peers. + * + * test1() + * Small cross seeding, and static list of peers. + * Set it going - and see what happens. + */ + +std::map nodes; +std::map portIdx; + +int main(int argc, char **argv) +{ + time_t sim_time = 60; + time_t starttime = time(NULL); + int n_nodes = 10; + std::map::iterator it; + std::map::iterator nit; + std::map::iterator pit; + + int i, j; + + bdDhtFunctions *fns = new bdStdDht(); + + std::cerr << "bdnode_multitest1() Setting up Nodes" << std::endl; + /* setup nodes */ + for(i = 0; i < n_nodes; i++) + { + bdId id; + + bdStdRandomId(&id); + + id.addr.sin_port = htons(i); + ((uint32_t *) (id.id.data))[0] = i * 16 * 16; /* force this so the sort order is maintained! */ + std::cerr << "bdnode_multitest1() Id: "; + fns->bdPrintId(std::cerr, &id); + std::cerr << std::endl; + + bdNode *node = new bdNode(&(id.id), "bdTEST", "", fns); + + /* Store in nodes */ + nodes[id] = node; + /* Store in indices */ + portIdx[i] = id; + + } + + std::cerr << "bdnode_multitest1() Cross Seeding" << std::endl; + /* do a little cross seeding */ + for(i = 0; i < n_nodes; i++) + { + bdId nid = portIdx[i]; + bdNode *node = nodes[nid]; + + for(j = 0; j < 5; j++) + { + int peeridx = bdRandom::random_u32() % n_nodes; + + bdId pid = portIdx[peeridx]; + node->addPotentialPeer(&pid, NULL); + } + } + + /* ready to run */ + + std::cerr << "bdnode_multitest1() Simulation Time....." << std::endl; + i = 0; + while(time(NULL) < starttime + sim_time) + { + i++; + std::cerr << "bdnode_multitest1() Iteration: " << i << std::endl; + + for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) + { + /* extract messages to go -> and deliver */ +#define MAX_MSG_SIZE 10240 + struct sockaddr_in addr; + char data[MAX_MSG_SIZE]; + int len = MAX_MSG_SIZE; + + while(it->second->outgoingMsg(&addr, data, &len)) + { + std::cerr << "bdnode_multitest1() Msg from Peer: " << j; + + /* find the peer */ + int peeridx = htons(addr.sin_port); + pit = portIdx.find(peeridx); + nit = nodes.end(); + if (pit != portIdx.end()) + { + nit = nodes.find(pit->second); + std::cerr << " For: "; + fns->bdPrintId(std::cerr, &(nit->first)); + std::cerr << std::endl; + } + else + { + std::cerr << " For Unknown Destination"; + std::cerr << std::endl; + + } + + if (nit != nodes.end()) + { + /* set from address */ + nit->second->incomingMsg( (sockaddr_in *) &(it->first.addr), data, len); + } + /* reset message size */ + len = MAX_MSG_SIZE; + } + } + + for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) + { + /* tick */ + std::cerr << "bdnode_multitest1() Ticking peer: " << j << std::endl; + it->second->iteration(); + } + + if (i % 5 == 0) + { + std::cerr << "bdnode_multitest1() Displying States"<< std::endl; + for(it = nodes.begin(), j = 0; it != nodes.end(); it++, j++) + { + /* tick */ + std::cerr << "bdnode_multitest1() Peer State: " << j << std::endl; + it->second->printState(); + } + } + + + /* have a rest */ + sleep(1); + } +} + + + + + + + + + + + + + + + + diff --git a/libbitdht/src/tests/bdnode_test.cc b/libbitdht/src/tests/bdnode_test.cc new file mode 100644 index 000000000..848a27e7c --- /dev/null +++ b/libbitdht/src/tests/bdnode_test.cc @@ -0,0 +1,90 @@ +/* + * bitdht/bdnode_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bitdht/bdpeer.h" +#include "bitdht/bdstddht.h" +#include "bitdht/bdquery.h" +#include "bitdht/bdnode.h" + +#define N_PEERS_TO_ADD_INIT 10 +#define N_PEERS_TO_ADD 11 +#define N_PEERS_TO_START 10 +#define N_PEERS_TO_PRINT 1 +#define N_QUERIES 2 + +int main(int argc, char **argv) +{ + + /* create some ids */ + bdDhtFunctions *fns = new bdStdDht(); + + bdNodeId ownId; + bdStdRandomNodeId(&ownId); + + bdNode node(&ownId, "bdTEST","./dht.log", fns); + + int i = 0; + for (i = 0; i < N_PEERS_TO_ADD_INIT; i++) + { + bdId tmpId; + bdStdRandomId(&tmpId); + + node.addPeer(&tmpId, 0); + } + + node.printState(); + +#if 0 + for(i = 0; i < N_QUERIES; i++) + { + /* create a query */ + bdNodeId queryId; + bdStdRandomNodeId(&queryId); + + node.addQuery(&queryId, 0); + } +#endif + + node.printState(); + + for (i = 0; i < N_PEERS_TO_ADD; i++) + { + bdId tmpId; + bdStdRandomId(&tmpId); + + node.addPeer(&tmpId, 0); + + if (i % N_PEERS_TO_PRINT == 0) + { + node.printState(); + node.iteration(); + sleep(5); + } + } + + return 1; +} + + diff --git a/libbitdht/src/tests/bdnode_test2.cc b/libbitdht/src/tests/bdnode_test2.cc new file mode 100644 index 000000000..1e4b16b68 --- /dev/null +++ b/libbitdht/src/tests/bdnode_test2.cc @@ -0,0 +1,56 @@ +/* + * bitdht/bdnode_test2.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bitdht/bdpeer.h" +#include "bitdht/bdstddht.h" +#include "bitdht/bdquery.h" +#include "bitdht/bdnode.h" + +#define N_PEERS_TO_ADD_INIT 10 +#define N_PEERS_TO_ADD 11 +#define N_PEERS_TO_START 10 +#define N_PEERS_TO_PRINT 1 +#define N_QUERIES 2 + +int main(int argc, char **argv) +{ + + /* create some ids */ + bdNodeId ownId; + bdStdRandomNodeId(&ownId); + bdDhtFunctions *fns = new bdStdDht(); + + bdNode node(&ownId, "bdTEST", "./dht.log", fns); + + while(1) + { + node.iteration(); + sleep(1); + } + + return 1; +} + + diff --git a/libbitdht/src/tests/bdquery_test.cc b/libbitdht/src/tests/bdquery_test.cc new file mode 100644 index 000000000..b4c8e980b --- /dev/null +++ b/libbitdht/src/tests/bdquery_test.cc @@ -0,0 +1,83 @@ +/* + * bitdht/bdquery_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdpeer.h" +#include "bitdht/bdstddht.h" +#include "bitdht/bdquery.h" + +#define N_PEERS_TO_ADD 10000 +#define N_PEERS_TO_PRINT 1000 +#define N_PEERS_TO_START 10 + +int main(int argc, char **argv) +{ + + /* create some ids */ + bdNodeId ownId; + bdStdRandomNodeId(&ownId); + + bdDhtFunctions *fns = new bdStdDht(); + + bdSpace space(&ownId, fns); + int i = 0; + for (i = 0; i < N_PEERS_TO_ADD; i++) + { + bdId tmpId; + bdStdRandomId(&tmpId); + + space.add_peer(&tmpId, 0); + } + + space.printDHT(); + + /* create a query */ + bdId queryId; + bdStdRandomId(&queryId); + + + + std::list startList; + std::multimap nearest; + std::multimap::iterator it; + + space.find_nearest_nodes(&(queryId.id), N_PEERS_TO_START, nearest); + + for(it = nearest.begin(); it != nearest.end(); it++) + { + startList.push_back(it->second); + } + + bdQuery query(&(queryId.id), startList, BITDHT_QFLAGS_DISGUISE, fns); + + /* */ + + query.printQuery(); + + + return 1; +} + + diff --git a/libbitdht/src/tests/bdspace_test.cc b/libbitdht/src/tests/bdspace_test.cc new file mode 100644 index 000000000..ead78c683 --- /dev/null +++ b/libbitdht/src/tests/bdspace_test.cc @@ -0,0 +1,60 @@ +/* + * bitdht/bdspace_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdpeer.h" +#include "bitdht/bdstddht.h" + +#define N_PEERS_TO_ADD 10000 +#define N_PEERS_TO_PRINT 1000 + +int main(int argc, char **argv) +{ + + /* create some ids */ + bdNodeId ownId; + bdStdRandomNodeId(&ownId); + bdDhtFunctions *fns = new bdStdDht(); + + bdSpace space(&ownId, fns); + int i = 0; + for (i = 0; i < N_PEERS_TO_ADD; i++) + { + bdId tmpId; + bdStdRandomId(&tmpId); + + space.add_peer(&tmpId, 0); + + if (i % N_PEERS_TO_PRINT == 0) + { + space.printDHT(); + } + } + space.printDHT(); + + return 1; +} + + diff --git a/libbitdht/src/tests/bdspace_test2.cc b/libbitdht/src/tests/bdspace_test2.cc new file mode 100644 index 000000000..ca9e7f024 --- /dev/null +++ b/libbitdht/src/tests/bdspace_test2.cc @@ -0,0 +1,67 @@ +/* + * bitdht/bdspace_test2.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdpeer.h" +#include "bitdht/bdstddht.h" + +#define N_PEERS_TO_ADD 10000 +#define N_PEERS_TO_TEST 100 +#define N_PEERS_TO_FIND 10 + +int main(int argc, char **argv) +{ + + /* create some ids */ + bdNodeId ownId; + bdStdRandomNodeId(&ownId); + bdDhtFunctions *fns = new bdStdDht(); + + bdSpace space(&ownId, fns); + int i = 0; + for (i = 0; i < N_PEERS_TO_ADD; i++) + { + bdId tmpId; + bdStdRandomId(&tmpId); + space.add_peer(&tmpId, 0); + } + + space.printDHT(); + + + /* now generate random id's and test closeness */ + for(i = 0; i < N_PEERS_TO_TEST; i++) + { + bdId tmpId; + bdStdRandomId(&tmpId); + std::multimap list2; + + space.find_nearest_nodes(&(tmpId.id), N_PEERS_TO_FIND, list2); + } + + return 1; +} + + diff --git a/libbitdht/src/tests/bdstore_test.cc b/libbitdht/src/tests/bdstore_test.cc new file mode 100644 index 000000000..c1207def5 --- /dev/null +++ b/libbitdht/src/tests/bdstore_test.cc @@ -0,0 +1,47 @@ +/* + * bitdht/bdstore_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdstore.h" +#include "bitdht/bdstddht.h" + +#include +#include + +int main(int argc, char **argv) +{ + /* load store */ + if (argc < 2) + { + fprintf(stderr, "Missing Store File\n"); + exit(1); + } + + bdDhtFunctions *fns = new bdStdDht(); + bdStore store(argv[1], fns); + return 1; +} + + diff --git a/libbitdht/src/tests/bdudp_test.cc b/libbitdht/src/tests/bdudp_test.cc new file mode 100644 index 000000000..4b9d581bd --- /dev/null +++ b/libbitdht/src/tests/bdudp_test.cc @@ -0,0 +1,66 @@ +/* + * bitdht/bdudp_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bdpeer.h" +#include "bitdht/bdquery.h" +#include "udp/udpbitdht.h" + +#define N_PEERS_TO_ADD 10000 +#define N_PEERS_TO_PRINT 1000 +#define N_PEERS_TO_START 10 + +int main(int argc, char **argv) +{ + + /* create some ids */ + bdId ownId; + bdRandomId(&ownId); + + + struct sockaddr_in local; + local.sin_addr.s_addr = 0; + local.sin_port = htons(7812); + std::string bootstrapfile = "dht.log"; + + bdId bid; + + bid.addr = local; + bid.id = ownId.id; + + UdpBitDht ubd(local, 0, &bid, bootstrapfile); + + + + while(1) + { + ubd.tick(); + sleep(1); + } + + return 1; +} + + diff --git a/libbitdht/src/tests/bencode_test.cc b/libbitdht/src/tests/bencode_test.cc new file mode 100644 index 000000000..8d35c0678 --- /dev/null +++ b/libbitdht/src/tests/bencode_test.cc @@ -0,0 +1,182 @@ +/* + * bitdht/bencode_test.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "bitdht/bencode.h" +#include + +int main(int argc, char **argv) +{ + + char msg[100]; + + msg[0] = 'd'; + msg[1] = '1'; + msg[2] = ':'; + msg[3] = 't'; + msg[4] = 'L'; + msg[5] = 'b'; + msg[6] = 'U'; + msg[7] = 0xd9; + msg[8] = 0xfa; + msg[9] = 0xff; + msg[10] = 0xff; + msg[11] = 0xff; + msg[12] = 0xff; + msg[13] = '\n'; + msg[14] = 'H'; + msg[15] = '#'; + msg[16] = '#'; + msg[17] = '#'; + msg[18] = '#'; + msg[19] = '#'; + msg[20] = '#'; + msg[21] = '#'; + + be_node *n = be_decoden(msg, 16); + + if (n) + { + be_dump(n); + be_free(n); + } + else + { + fprintf(stderr, "didn't crash!\n"); + } + + msg[0] = 'd'; + msg[1] = '1'; + msg[2] = ':'; + msg[3] = 'a'; + msg[4] = 'L'; + msg[5] = 0x8d; + msg[6] = 0xd6; + msg[7] = '\r'; + msg[8] = 0x9d; + msg[9] = ';'; + msg[10] = 0xff; + msg[11] = 0xff; + msg[12] = 0xff; + msg[13] = 0xff; + msg[14] = 'H'; + msg[15] = '#'; + msg[16] = '#'; + msg[17] = '#'; + msg[18] = '#'; + msg[19] = '#'; + msg[20] = '#'; + msg[21] = '#'; + + n = be_decoden(msg, 14); + + if (n) + { + be_dump(n); + be_free(n); + } + else + { + fprintf(stderr, "didn't crash!\n"); + } + + msg[0] = 'd'; + msg[1] = '1'; + msg[2] = ':'; + msg[3] = 't'; + msg[4] = '4'; + msg[5] = ':'; + msg[6] = 'a'; + msg[7] = 'b'; + msg[8] = 'c'; + msg[9] = 'd'; + msg[10] = '1'; + msg[11] = ':'; + msg[12] = 'y'; + msg[13] = '1'; + msg[14] = ':'; + msg[15] = 'r'; + msg[16] = '1'; + msg[17] = ':'; + msg[18] = 'r'; + msg[19] = 'd'; + msg[20] = '2'; + msg[21] = ':'; + msg[22] = 'i'; + msg[23] = 'd'; + msg[24] = '2'; + msg[25] = '0'; + msg[26] = ':'; + msg[27] = '1'; + msg[28] = '2'; + msg[29] = '3'; + msg[30] = '4'; + msg[31] = '5'; + msg[32] = '6'; + msg[33] = '7'; + msg[34] = '8'; + msg[35] = '9'; + msg[36] = '0'; + msg[37] = 'a'; + msg[38] = 'b'; + msg[39] = 'c'; + msg[40] = 'd'; + msg[41] = 'e'; + msg[42] = 'f'; + msg[43] = 'g'; + msg[44] = 'h'; + msg[45] = 'i'; + msg[46] = '.'; + msg[47] = '5'; + msg[48] = ':'; + msg[49] = 'n'; + msg[50] = 'o'; + msg[51] = 'd'; + msg[52] = 'e'; + msg[53] = 's'; + msg[54] = '2'; + msg[55] = '0'; + msg[56] = '8'; + msg[57] = ':'; + msg[58] = '\0'; + msg[59] = '\0'; + msg[60] = '\0'; + + n = be_decoden(msg, 58); + + if (n) + { + be_dump(n); + be_free(n); + } + else + { + fprintf(stderr, "didn't crash!\n"); + } + + return 1; +} + + diff --git a/libbitdht/src/tests/scripts/checks.mk b/libbitdht/src/tests/scripts/checks.mk new file mode 100644 index 000000000..dfccbdedf --- /dev/null +++ b/libbitdht/src/tests/scripts/checks.mk @@ -0,0 +1,19 @@ +#Basic checks + +ifndef TEST_TOP_DIR +dummy: + echo "TEST_TOP_DIR is not defined in your makefile" +endif + +ifneq ($(OS),Linux) + ifneq ($(OS),MacOSX) + ifndef PTHREADS_DIR +dummy: + echo "you must define PTHREADS_DIR before you can compile" + + endif + endif +endif + + + diff --git a/libbitdht/src/tests/scripts/config-cygwin.mk b/libbitdht/src/tests/scripts/config-cygwin.mk new file mode 100644 index 000000000..ec4518f68 --- /dev/null +++ b/libbitdht/src/tests/scripts/config-cygwin.mk @@ -0,0 +1,118 @@ +ifneq ($(OS),Cygwin) +dummy: + echo "ERROR Cygwin configuration file included, but (OS != Cygwin) + +endif + +############ LINUX CONFIGURATION ######################## + +# flags for components.... +PQI_USE_XPGP = 1 +#PQI_USE_PROXY = 1 +#PQI_USE_CHANNELS = 1 +#USE_FILELOOK = 1 + +########################################################################### + +#### DrBobs Versions.... Please Don't Delete. +### Comment out if needed. +ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW +SRC_ROOT=../../../.. + +PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2 + +################### + +#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src +#SRC_ROOT=/cygdrive/c/RetroShareBuild/src + +#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release + +################### + +ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3 + +SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c +UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 + +include $(RS_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ######################## + +CC = g++ +RM = /bin/rm +RANLIB = ranlib +LIBDIR = $(RS_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +# Unix: Linux/Cygwin +INCLUDE = -I $(RS_TOP_DIR) + +ifdef PQI_DEBUG + CFLAGS = -Wall -g $(INCLUDE) +else + CFLAGS = -Wall -O2 $(INCLUDE) +endif + +ifdef PQI_USE_XPGP + INCLUDE += -I $(SSL_DIR)/include +endif + +ifdef PQI_USE_XPGP + CFLAGS += -DPQI_USE_XPGP +endif + +ifdef PQI_USE_PROXY + CFLAGS += -DPQI_USE_PROXY +endif + +ifdef PQI_USE_CHANNELS + CFLAGS += -DPQI_USE_CHANNELS +endif + +ifdef USE_FILELOOK + CFLAGS += -DUSE_FILELOOK +endif + + +RSCFLAGS = -Wall -g $(INCLUDE) + +######################################################################### +# OS Compile Options +######################################################################### + +# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) +BIOCC = gcc + +# Cygwin - ?same? as Linux flags +BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM + +######################################################################### +# OS specific Linking. +######################################################################### + +# for static pthread libs.... +WININC += -DPTW32_STATIC_LIB +WININC += -mno-cygwin -mwindows -fno-exceptions +WININC += -DWINDOWS_SYS + +WINLIB = -lws2_32 -luuid -lole32 -liphlpapi +WINLIB += -lcrypt32 -lwinmm + +CFLAGS += -I$(PTHREADS_DIR) $(WININC) +CFLAGS += -I$(ZLIB_DIR) + +LIBS = -L$(LIBDIR) -lretroshare +ifdef PQI_USE_XPGP + LIBS += -L$(SSL_DIR) +endif + +LIBS += -lssl -lcrypto +LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += -L$(ZLIB_DIR) -lz +LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d +LIBS += $(WINLIB) + +RSCFLAGS += $(WININC) + + diff --git a/libbitdht/src/tests/scripts/config-linux.mk b/libbitdht/src/tests/scripts/config-linux.mk new file mode 100644 index 000000000..182f9c39a --- /dev/null +++ b/libbitdht/src/tests/scripts/config-linux.mk @@ -0,0 +1,41 @@ + +ifneq ($(OS),Linux) +dummy: + echo "ERROR Linux configuration file included, but (OS != Linux) + +endif + +############ LINUX CONFIGURATION ######################## + +include $(TEST_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ######################## + +CC = g++ +RM = /bin/rm +RANLIB = ranlib +LIBDIR = $(LIB_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +# Unix: Linux/Cygwin +INCLUDE = -I $(LIB_TOP_DIR) +CFLAGS = -Wall -g $(INCLUDE) +CFLAGS += ${DEFINES} -D BE_DEBUG + +######################################################################### +# OS Compile Options +######################################################################### + +######################################################################### +# OS specific Linking. +######################################################################### + +LIBS = -L$(LIBDIR) -lbitdht +LIBS += -lpthread +#LIBS += $(XLIB) -ldl -lz +#LIBS += -lupnp +#LIBS += -lgpgme +# +#RSLIBS = $(LIBS) + + diff --git a/libbitdht/src/tests/scripts/config-macosx.mk b/libbitdht/src/tests/scripts/config-macosx.mk new file mode 100644 index 000000000..ecf95733d --- /dev/null +++ b/libbitdht/src/tests/scripts/config-macosx.mk @@ -0,0 +1,81 @@ + +ifneq ($(OS),MacOSX) +dummy: + echo "ERROR MacOSX configuration file included, but (OS != MacOSX) + +endif + +############ MACOSX CONFIGURATION ######################## + + +# FLAGS to decide if we want i386 Build or ppc Build +# +# + +# MAC_I386_BUILD = 1 +# MAC_PPC_BUILD = 1 + +MAC_I386_BUILD = 1 +#MAC_PPC_BUILD = 1 + +ifndef MAC_I386_BUILD + MAC_PPC_BUILD = 1 +endif + +include $(TEST_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ######################## + +CC = g++ +RM = /bin/rm + +RANLIB = ranlib + +# Dummy ranlib -> can't do it until afterwards with universal binaries. +# RANLIB = ls -l + +LIBDIR = $(LIB_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +OPT_DIR = /opt/local +OPT_INCLUDE = $(OPT_DIR)/include +OPT_LIBS = $(OPT_DIR)/lib + +INCLUDE = -I $(LIB_TOP_DIR) +#-I $(OPT_INCLUDE) +#CFLAGS = -Wall -O3 +CFLAGS = -Wall -g + +# Flags for architecture builds. +ifdef MAC_I386_BUILD + CFLAGS += -arch i386 +endif + +ifdef MAC_PPC_BUILD + CFLAGS += -arch ppc +endif + +CFLAGS += $(INCLUDE) + +# This Line is for Universal BUILD for 10.4 + 10.5 +# (but unlikely to work unless Qt Libraries are build properly) +#CFLAGS += -isysroot /Developer/SDKs/MacOSX10.5.sdk + +######################################################################### +# OS Compile Options +######################################################################### + +######################################################################### +# OS specific Linking. +######################################################################### + +#LIBS = -Wl,-search_paths_first + +# for Univeral BUILD +# LIBS += -arch ppc -arch i386 +# LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 + +#LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk +LIBS += -L$(LIBDIR) -lbitdht + + diff --git a/libbitdht/src/tests/scripts/config-mingw.mk b/libbitdht/src/tests/scripts/config-mingw.mk new file mode 100644 index 000000000..c0040ac4e --- /dev/null +++ b/libbitdht/src/tests/scripts/config-mingw.mk @@ -0,0 +1,138 @@ +#ifneq ($(OS),"Win ") +#dummy: +# echo "ERROR OS = $(OS)" +# echo "ERROR MinGW configuration file included, but (OS != Win) +# +#endif + +############ LINUX CONFIGURATION ######################## + +# flags for components.... +#PQI_USE_XPGP = 1 +#PQI_USE_PROXY = 1 +#PQI_USE_CHANNELS = 1 +#USE_FILELOOK = 1 + +########################################################################### + +#### DrBobs Versions.... Please Don't Delete. +### Comment out if needed. +SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src +SRC_ROOT_GPG=/local + +#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW +#SRC_ROOT=../../../.. + +PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2 +ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3 +SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp +UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3 + +########################################################################### + +#### Enable this section for compiling with MSYS/MINGW compile +#SRC_ROOT=/home/linux + +#SSL_DIR=$(SRC_ROOT)/OpenSSL +#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 +#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 + +#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 +#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 +#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release + +include $(RS_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ####################################### + +CC = g++ +RM = /bin/rm +RANLIB = ranlib +LIBDIR = $(RS_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +# Unix: Linux/Cygwin +INCLUDE = -I $(RS_TOP_DIR) + +ifdef PQI_DEBUG + CFLAGS = -Wall -g $(INCLUDE) +else + CFLAGS = -Wall -O2 $(INCLUDE) +endif + +# These aren't used anymore.... really. +ifdef PQI_USE_XPGP + CFLAGS += -DPQI_USE_XPGP +endif + +ifdef PQI_USE_PROXY + CFLAGS += -DPQI_USE_PROXY +endif + +ifdef PQI_USE_CHANNELS + CFLAGS += -DPQI_USE_CHANNELS +endif + +ifdef USE_FILELOOK + CFLAGS += -DUSE_FILELOOK +endif + + +# SSL / pthreads / Zlib +# included by default for Windows compilation. +INCLUDE += -I $(SSL_DIR)/include +INCLUDE += -I$(PTHREADS_DIR) +INCLUDE += -I$(ZLIB_DIR) + + +######################################################################### +# OS Compile Options +######################################################################### + +# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) +BIOCC = gcc + +# Cygwin - ?same? as Linux flags +BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM +BIOCFLAGS += -DWINDOWS_SYS + +######################################################################### +# OS specific Linking. +######################################################################### + +# for static pthread libs.... +#WININC += -DPTW32_STATIC_LIB +#WININC += -mno-cygwin -mwindows -fno-exceptions + +WININC += -DWINDOWS_SYS + +WINLIB = -lws2_32 -luuid -lole32 -liphlpapi +WINLIB += -lcrypt32 -lwinmm + +CFLAGS += -I$(SSL_DIR)/include +CFLAGS += -I$(PTHREADS_DIR)/include +CFLAGS += -I$(ZLIB_DIR) +CFLAGS += -I$(SRC_ROOT_GPG)/include + +### Enable this for GPGME and GPG ERROR dirs +#CFLAGS += -I$(GPGME_DIR)/src +#CFLAGS += -I$(GPG_ERROR_DIR)/src + +CFLAGS += $(WININC) + + + +LIBS = -L$(LIBDIR) -lretroshare + +LIBS += -L$(SSL_DIR) + +LIBS += -lssl -lcrypto +LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += -L$(ZLIB_DIR) -lz +LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d +LIBS += $(WINLIB) + +#RSCFLAGS = -Wall -g $(INCLUDE) +#RSCFLAGS += $(WININC) + + diff --git a/libbitdht/src/tests/scripts/config.mk b/libbitdht/src/tests/scripts/config.mk new file mode 100644 index 000000000..0859a4799 --- /dev/null +++ b/libbitdht/src/tests/scripts/config.mk @@ -0,0 +1,27 @@ + +# determine which operating system +# +########################################################################### +#Define OS. +# +OS = Linux +#OS = MacOSX +#OS = Cygwin +#OS = Win # MinGw. +########################################################################### + +ifeq ($(OS),Linux) + include $(TEST_TOP_DIR)/scripts/config-linux.mk +else + ifeq ($(OS),MacOSX) + include $(TEST_TOP_DIR)/scripts/config-macosx.mk + else + ifeq ($(OS),Cygwin) + include $(TEST_TOP_DIR)/scripts/config-cygwin.mk + else + include $(TEST_TOP_DIR)/scripts/config-mingw.mk + endif + endif +endif + +########################################################################### diff --git a/libbitdht/src/tests/scripts/regress.mk b/libbitdht/src/tests/scripts/regress.mk new file mode 100644 index 000000000..f80b48451 --- /dev/null +++ b/libbitdht/src/tests/scripts/regress.mk @@ -0,0 +1,25 @@ + +testoutputfiles = $(foreach tt,$(1),$(tt).tstout) + +%.tstout : %.sh + -sh ./$< > $@ 2>&1 + +%.tstout : % + -./$< > $@ 2>&1 + +TESTOUT = $(call testoutputfiles,$(TESTS)) + +.phony : tests regress retest clobber + +tests: $(TESTS) + +regress: $(TESTOUT) + @-echo "--------------- SUCCESS (count):" + @-grep -c SUCCESS $(TESTOUT) + @-echo "--------------- FAILURE REPORTS:" + @-grep FAILURE $(TESTOUT) || echo no failures + @-echo "--------------- end" + +retest: + -/bin/rm $(TESTOUT) + diff --git a/libbitdht/src/tests/scripts/rules.mk b/libbitdht/src/tests/scripts/rules.mk new file mode 100644 index 000000000..9166e80a4 --- /dev/null +++ b/libbitdht/src/tests/scripts/rules.mk @@ -0,0 +1,19 @@ + +# defines required / used. +# +# CFLAGS +# +# + +.cc.o: + $(CC) $(CFLAGS) -c $< + +clean: + -/bin/rm $(EXECOBJ) $(TESTOBJ) + +clobber: clean retest + -/bin/rm $(EXEC) $(TESTS) + + +include $(TEST_TOP_DIR)/scripts/regress.mk + diff --git a/libbitdht/src/tests/udpbitdht_nettest.cc b/libbitdht/src/tests/udpbitdht_nettest.cc new file mode 100644 index 000000000..0dbb634b2 --- /dev/null +++ b/libbitdht/src/tests/udpbitdht_nettest.cc @@ -0,0 +1,278 @@ +/* + * bitdht/udpbitdht_nettest.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "udp/udpbitdht.h" +#include "udp/udpstack.h" +#include "bitdht/bdstddht.h" + +#include +#include + +/******************************************************************* + * DHT test program. + * + * + * Create a couple of each type. + */ + +#define MAX_MESSAGE_LEN 10240 + +int args(char *name) +{ + std::cerr << "Usage: " << name; + std::cerr << " -p "; + std::cerr << " -b "; + std::cerr << " -u "; + std::cerr << " -q "; + std::cerr << " -r (do dht restarts) "; + std::cerr << " -j (do join test) "; + std::cerr << std::endl; + return 1; +} + +#define DEF_PORT 7500 + +#define MIN_DEF_PORT 1001 +#define MAX_DEF_PORT 16000 + +#define DEF_BOOTFILE "bdboot.txt" + +int main(int argc, char **argv) +{ + int c; + int port = DEF_PORT; + std::string bootfile = DEF_BOOTFILE; + std::string uid; + bool setUid = false; + bool doRandomQueries = false; + bool doRestart = false; + bool doThreadJoin = false; + int noQueries = 0; + + while((c = getopt(argc, argv,"rjp:b:u:q:")) != -1) + { + switch (c) + { + case 'r': + doRestart = true; + break; + case 'j': + doThreadJoin = true; + break; + case 'p': + { + int tmp_port = atoi(optarg); + if ((tmp_port > MIN_DEF_PORT) && (tmp_port < MAX_DEF_PORT)) + { + port = tmp_port; + std::cerr << "Port: " << port; + std::cerr << std::endl; + } + else + { + std::cerr << "Invalid Port"; + std::cerr << std::endl; + args(argv[0]); + return 1; + } + + } + break; + case 'b': + { + bootfile = optarg; + std::cerr << "Bootfile: " << bootfile; + std::cerr << std::endl; + } + break; + case 'u': + { + setUid = true; + uid = optarg; + std::cerr << "UID: " << uid; + std::cerr << std::endl; + } + break; + case 'q': + { + doRandomQueries = true; + noQueries = atoi(optarg); + std::cerr << "Doing Random Queries"; + std::cerr << std::endl; + } + break; + + default: + { + args(argv[0]); + return 1; + } + break; + } + } + + + bdDhtFunctions *fns = new bdStdDht(); + + bdNodeId id; + + /* start off with a random id! */ + bdStdRandomNodeId(&id); + + if (setUid) + { + int len = uid.size(); + if (len > 20) + { + len = 20; + } + + for(int i = 0; i < len; i++) + { + id.data[i] = uid[i]; + } + } + + std::cerr << "Using NodeId: "; + fns->bdPrintNodeId(std::cerr, &id); + std::cerr << std::endl; + + /* setup the udp port */ + struct sockaddr_in local; + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_addr.s_addr = 0; + local.sin_port = htons(port); + UdpStack *udpstack = new UdpStack(local); + + /* create bitdht component */ + std::string dhtVersion = "dbTEST"; + UdpBitDht *bitdht = new UdpBitDht(udpstack, &id, dhtVersion, bootfile, fns); + + /* add in the stack */ + udpstack->addReceiver(bitdht); + + /* register callback display */ + bdDebugCallback *cb = new bdDebugCallback(); + bitdht->addCallback(cb); + + /* startup threads */ + //udpstack->start(); + bitdht->start(); + + + + + /* do a couple of random continuous searchs. */ + + uint32_t mode = BITDHT_QFLAGS_DO_IDLE; + + int count = 0; + int running = 1; + + std::cerr << "Starting Dht: "; + std::cerr << std::endl; + bitdht->startDht(); + + + if (doRandomQueries) + { + for(int i = 0; i < noQueries; i++) + { + bdNodeId rndId; + bdStdRandomNodeId(&rndId); + + std::cerr << "BitDht Launching Random Search: "; + bdStdPrintNodeId(std::cerr, &rndId); + std::cerr << std::endl; + + bitdht->addFindNode(&rndId, mode); + + } + } + + while(1) + { + sleep(60); + + std::cerr << "BitDht State: "; + std::cerr << bitdht->stateDht(); + std::cerr << std::endl; + + std::cerr << "Dht Network Size: "; + std::cerr << bitdht->statsNetworkSize(); + std::cerr << std::endl; + + std::cerr << "BitDht Network Size: "; + std::cerr << bitdht->statsBDVersionSize(); + std::cerr << std::endl; + + if (++count == 2) + { + /* switch to one-shot searchs */ + mode = 0; + } + + if (doThreadJoin) + { + /* change address */ + if (count % 2 == 0) + { + + std::cerr << "Resetting UdpStack: "; + std::cerr << std::endl; + + udpstack->resetAddress(local); + } + } + if (doRestart) + { + if (count % 2 == 1) + { + if (running) + { + + std::cerr << "Stopping Dht: "; + std::cerr << std::endl; + + bitdht->stopDht(); + running = 0; + } + else + { + std::cerr << "Starting Dht: "; + std::cerr << std::endl; + + bitdht->startDht(); + running = 1; + } + } + } + } + return 1; +} + + diff --git a/libbitdht/src/tests/utest.h b/libbitdht/src/tests/utest.h new file mode 100644 index 000000000..1ebd9875a --- /dev/null +++ b/libbitdht/src/tests/utest.h @@ -0,0 +1,23 @@ +#ifndef _UNIT_TEST_MACROS_H__ +#define _UNIT_TEST_MACROS_H__ + +#include + +#define TFAILURE( s ) printf( "FAILURE: " __FILE__ ":%-4d %s\n", __LINE__, s ) +#define TSUCCESS( s ) printf( "SUCCESS: " __FILE__ ":%-4d %s\n", __LINE__, s ) + +/* careful with this line (no protection) */ +#define INITTEST() int ok = 1; int gok = 1; + +/* declare the variables */ +extern int ok; +extern int gok; + +#define CHECK( b ) do { if ( ! (b) ) { ok = 0; TFAILURE( #b ); } } while(0) +#define FAILED( s ) do { ok = 0; TFAILURE( s ); } while(0) +#define REPORT( s ) do { if ( ! (ok) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) +#define REPORT2( b, s ) do { if ( ! (b) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) +#define FINALREPORT( s ) do { gok &= ok; ok = 1; if ( ! (gok) ) { TFAILURE( s ); } else { TSUCCESS( s );} } while(0) +#define TESTRESULT() (!gok) + +#endif diff --git a/libbitdht/src/udp/udpbitdht.cc b/libbitdht/src/udp/udpbitdht.cc new file mode 100644 index 000000000..addcd98e3 --- /dev/null +++ b/libbitdht/src/udp/udpbitdht.cc @@ -0,0 +1,306 @@ +/* + * bitdht/udpbitdht.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "udp/udpbitdht.h" +#include "bitdht/bdpeer.h" +#include "bitdht/bdstore.h" +#include "bitdht/bdmsgs.h" +#include "bitdht/bencode.h" + +#include +#include +#include +#include + +#include + +#include "util/bdnet.h" + +/* + * #define DEBUG_UDP_BITDHT 1 + * + * #define BITDHT_VERSION_ANONYMOUS 1 + */ + +//#define DEBUG_UDP_BITDHT 1 + +#define BITDHT_VERSION_IDENTIFER 1 + +// Original RS 0.5.0/0.5.1 version, is un-numbered. +#define BITDHT_VERSION "00" // First Release of BitDHT with Connections (Proxy Support + Dht Stun) +//#define BITDHT_VERSION "01" // Potentially... Connections + Full DHT implementation. (TBD) +/*************************************/ + +UdpBitDht::UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string appVersion, std::string bootstrapfile, bdDhtFunctions *fns) + :UdpSubReceiver(pub), dhtMtx(true), mFns(fns) +{ + std::string usedVersion; + +#ifdef BITDHT_VERSION_IDENTIFER + usedVersion = "BD"; + usedVersion += BITDHT_VERSION; +#endif + usedVersion += appVersion; + +#ifdef BITDHT_VERSION_ANONYMOUS + usedVersion = ""; /* blank it */ +#endif + + /* setup nodeManager */ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + mBitDhtManager = new bdNodeManager(id, usedVersion, bootstrapfile, fns); + +} + + +UdpBitDht::~UdpBitDht() +{ + return; +} + + + /*********** External Interface to the World ************/ + + /***** Functions to Call down to bdNodeManager ****/ + /* Request DHT Peer Lookup */ + /* Request Keyword Lookup */ +void UdpBitDht::addFindNode(bdNodeId *id, uint32_t mode) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->addFindNode(id, mode); +} + +void UdpBitDht::removeFindNode(bdNodeId *id) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->removeFindNode(id); +} + +void UdpBitDht::findDhtValue(bdNodeId *id, std::string key, uint32_t mode) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->findDhtValue(id, key, mode); +} + + /***** Add / Remove Callback Clients *****/ +void UdpBitDht::addCallback(BitDhtCallback *cb) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->addCallback(cb); +} + +void UdpBitDht::removeCallback(BitDhtCallback *cb) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->removeCallback(cb); +} + +void UdpBitDht::ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t start) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->ConnectionRequest(laddr, target, mode, start); +} + + + +void UdpBitDht::ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t answer) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->ConnectionAuth(srcId, proxyId, destId, mode, loc, answer); +} + +void UdpBitDht::ConnectionOptions(uint32_t allowedModes, uint32_t flags) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + mBitDhtManager->ConnectionOptions(allowedModes, flags); +} + + +int UdpBitDht::getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->getDhtPeerAddress(id, from); +} + +int UdpBitDht::getDhtValue(const bdNodeId *id, std::string key, std::string &value) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->getDhtValue(id, key, value); +} + +int UdpBitDht::getDhtBucket(const int idx, bdBucket &bucket) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->getDhtBucket(idx, bucket); +} + + + +int UdpBitDht::getDhtQueries(std::map &queries) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->getDhtQueries(queries); +} + +int UdpBitDht::getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query) +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->getDhtQueryStatus(id, query); +} + + + + /* stats and Dht state */ +int UdpBitDht:: startDht() +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->startDht(); +} + +int UdpBitDht:: stopDht() +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->stopDht(); +} + +int UdpBitDht::stateDht() +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->stateDht(); +} + +uint32_t UdpBitDht::statsNetworkSize() +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->statsNetworkSize(); +} + +uint32_t UdpBitDht::statsBDVersionSize() +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + return mBitDhtManager->statsBDVersionSize(); +} + + /******************* Internals *************************/ + + /***** Iteration / Loop Management *****/ + + /*** Overloaded from UdpSubReceiver ***/ +int UdpBitDht::recvPkt(void *data, int size, struct sockaddr_in &from) +{ + /* pass onto bitdht */ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + /* check packet suitability */ + if (mBitDhtManager->isBitDhtPacket((char *) data, size, from)) + { + + mBitDhtManager->incomingMsg(&from, (char *) data, size); + return 1; + } + return 0; +} + +int UdpBitDht::status(std::ostream &out) +{ + out << "UdpBitDht::status()" << std::endl; + + return 1; +} + + /*** Overloaded from iThread ***/ +#define MAX_MSG_PER_TICK 100 +#define TICK_PAUSE_USEC 20000 /* 20ms secs .. max messages = 50 x 100 = 5000 */ + +void UdpBitDht::run() +{ + while(1) + { + while(tick()) + { + usleep(TICK_PAUSE_USEC); + } + + { + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + mBitDhtManager->iteration(); + } + sleep(1); + } +} + + +int UdpBitDht::tick() +{ + bdStackMutex stack(dhtMtx); /********** MUTEX LOCKED *************/ + + /* pass on messages from the node */ + int i = 0; + char data[BITDHT_MAX_PKTSIZE]; + struct sockaddr_in toAddr; + int size = BITDHT_MAX_PKTSIZE; + + while((i < MAX_MSG_PER_TICK) && (mBitDhtManager->outgoingMsg(&toAddr, data, &size))) + { +#ifdef DEBUG_UDP_BITDHT + std::cerr << "UdpBitDht::tick() outgoing msg(" << size << ") to " << toAddr; + std::cerr << std::endl; +#endif + + sendPkt(data, size, toAddr, BITDHT_TTL); + + // iterate + i++; + size = BITDHT_MAX_PKTSIZE; // reset msg size! + } + + if (i == MAX_MSG_PER_TICK) + { + return 1; /* keep on ticking */ + } + return 0; +} + + + diff --git a/libbitdht/src/udp/udpbitdht.h b/libbitdht/src/udp/udpbitdht.h new file mode 100644 index 000000000..fd330471e --- /dev/null +++ b/libbitdht/src/udp/udpbitdht.h @@ -0,0 +1,112 @@ +#ifndef UDP_BIT_DHT_CLASS_H +#define UDP_BIT_DHT_CLASS_H + +/* + * bitdht/udpbitdht.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include +#include +#include + +#include "udp/udpstack.h" +#include "bitdht/bdiface.h" +#include "bitdht/bdmanager.h" + +/* + * This implements a UdpSubReceiver class to allow the DHT to talk to the network. + * The parser is very strict - and will try to not pick up anyone else's messages. + * + * Mutexes are implemented at this level protecting the whole of the DHT code. + * This class is also a thread - enabling it to do callback etc. + */ + +// class BitDhtCallback defined in bdiface.h + + +class UdpBitDht: public UdpSubReceiver, public bdThread, public BitDhtInterface +{ + public: + + UdpBitDht(UdpPublisher *pub, bdNodeId *id, std::string dhtVersion, std::string bootstrapfile, bdDhtFunctions *fns); +virtual ~UdpBitDht(); + + + /*********** External Interface to the World (BitDhtInterface) ************/ + + /***** Functions to Call down to bdNodeManager ****/ + /* Request DHT Peer Lookup */ + /* Request Keyword Lookup */ +virtual void addFindNode(bdNodeId *id, uint32_t mode); +virtual void removeFindNode(bdNodeId *id); +virtual void findDhtValue(bdNodeId *id, std::string key, uint32_t mode); + + /***** Add / Remove Callback Clients *****/ +virtual void addCallback(BitDhtCallback *cb); +virtual void removeCallback(BitDhtCallback *cb); + + /***** Connections Requests *****/ +virtual void ConnectionRequest(struct sockaddr_in *laddr, bdNodeId *target, uint32_t mode, uint32_t start); +virtual void ConnectionAuth(bdId *srcId, bdId *proxyId, bdId *destId, uint32_t mode, uint32_t loc, uint32_t answer); +virtual void ConnectionOptions(uint32_t allowedModes, uint32_t flags); + + /***** Get Results Details *****/ +virtual int getDhtPeerAddress(const bdNodeId *id, struct sockaddr_in &from); +virtual int getDhtValue(const bdNodeId *id, std::string key, std::string &value); +virtual int getDhtBucket(const int idx, bdBucket &bucket); + +virtual int getDhtQueries(std::map &queries); +virtual int getDhtQueryStatus(const bdNodeId *id, bdQuerySummary &query); + + /* stats and Dht state */ +virtual int startDht(); +virtual int stopDht(); +virtual int stateDht(); +virtual uint32_t statsNetworkSize(); +virtual uint32_t statsBDVersionSize(); + + /******************* Internals *************************/ + /***** Iteration / Loop Management *****/ + + /*** Overloaded from UdpSubReceiver ***/ +virtual int recvPkt(void *data, int size, struct sockaddr_in &from); +virtual int status(std::ostream &out); + + + /*** Overloaded from iThread ***/ +virtual void run(); + + /**** do whats to be done ***/ + int tick(); + + private: + + bdMutex dhtMtx; /* for all class data (below) */ + bdNodeManager *mBitDhtManager; + bdDhtFunctions *mFns; +}; + + +#endif diff --git a/libbitdht/src/udp/udplayer.cc b/libbitdht/src/udp/udplayer.cc new file mode 100644 index 000000000..9dd467a2c --- /dev/null +++ b/libbitdht/src/udp/udplayer.cc @@ -0,0 +1,668 @@ +/* + * udp/udplayer.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2004-2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "udp/udplayer.h" +#include "util/bdrandom.h" + +#include +#include +#include +#include +#include + +/*** + * #define UDP_ENABLE_BROADCAST 1 + * #define UDP_LOOPBACK_TESTING 1 + * #define DEBUG_UDP_LAYER 1 + ***/ + +//#define DEBUG_UDP_LAYER 1 + +static const int UDP_DEF_TTL = 64; + +/* NB: This #define makes the listener open 0.0.0.0:X port instead + * of a specific port - this helps library communicate on systems + * with multiple interfaces or unique network setups. + * + * - It should always be used! + * + * #define OPEN_UNIVERSAL_PORT 1 + * + */ + +#define OPEN_UNIVERSAL_PORT 1 + + +class udpPacket +{ + public: + udpPacket(struct sockaddr_in *addr, void *dta, int dlen) + :raddr(*addr), len(dlen) + { + data = malloc(len); + memcpy(data, dta, len); + } + + ~udpPacket() + { + if (data) + { + free(data); + data = NULL; + len = 0; + } + } + + struct sockaddr_in raddr; + void *data; + int len; +}; + +//std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr) +std::ostream &operator<<(std::ostream &out, struct sockaddr_in &addr) +{ + out << "[" << inet_ntoa(addr.sin_addr) << ":"; + out << htons(addr.sin_port) << "]"; + return out; +} + +bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2) +{ + if (addr.sin_family != addr2.sin_family) + return false; + if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr) + return false; + if (addr.sin_port != addr2.sin_port) + return false; + return true; +} + + +bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2) +{ + if (addr.sin_family != addr2.sin_family) + return (addr.sin_family < addr2.sin_family); + if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr) + return (addr.sin_addr.s_addr < addr2.sin_addr.s_addr); + if (addr.sin_port != addr2.sin_port) + return (addr.sin_port < addr2.sin_port); + return false; +} + +std::string printPkt(void *d, int size) +{ + std::ostringstream out; + out << "Packet:" << "**********************"; + for(int i = 0; i < size; i++) + { + if (i % 16 == 0) + out << std::endl; + out << std::hex << std::setw(2) << (unsigned int) ((unsigned char *) d)[i] << " "; + } + out << std::endl << "**********************"; + out << std::endl; + return out.str(); +} + + +std::string printPktOffset(unsigned int offset, void *d, unsigned int size) +{ + std::ostringstream out; + out << "Packet:" << "**********************"; + out << std::endl; + out << "Offset: " << std::hex << offset << " -> " << offset + size; + out << std::endl; + out << "Packet:" << "**********************"; + + unsigned int j = offset % 16; + if (j != 0) + { + out << std::endl; + out << std::hex << std::setw(6) << (unsigned int) offset - j; + out << ": "; + for(unsigned int i = 0; i < j; i++) + { + out << "xx "; + } + } + for(unsigned int i = offset; i < offset + size; i++) + { + if (i % 16 == 0) + { + out << std::endl; + out << std::hex << std::setw(6) << (unsigned int) i; + out << ": "; + } + out << std::hex << std::setw(2) << (unsigned int) ((unsigned char *) d)[i-offset] << " "; + } + out << std::endl << "**********************"; + out << std::endl; + return out.str(); +} + + + +UdpLayer::UdpLayer(UdpReceiver *udpr, struct sockaddr_in &local) + :recv(udpr), laddr(local), errorState(0), ttl(UDP_DEF_TTL) +{ + openSocket(); + return; +} + +int UdpLayer::status(std::ostream &out) +{ + out << "UdpLayer::status()" << std::endl; + out << "localaddr: " << laddr << std::endl; + out << "sockfd: " << sockfd << std::endl; + out << std::endl; + return 1; +} + +int UdpLayer::reset(struct sockaddr_in &local) +{ +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::reset()" << std::endl; +#endif + + /* stop the old thread */ + { + bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/ +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::reset() setting stopThread flag" << std::endl; +#endif + stopThread = true; + } +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::reset() joining" << std::endl; +#endif + + join(); + +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::reset() closing socket" << std::endl; +#endif + closeSocket(); + +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::reset() resetting variables" << std::endl; +#endif + laddr = local; + errorState = 0; + ttl = UDP_DEF_TTL; + +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::reset() opening socket" << std::endl; +#endif + openSocket(); + + return 1 ; +} + + +int UdpLayer::closeSocket() +{ + /* close socket if open */ + sockMtx.lock(); /********** LOCK MUTEX *********/ + + if (sockfd > 0) + { + bdnet_close(sockfd); + } + + sockMtx.unlock(); /******** UNLOCK MUTEX *********/ + return 1; +} + +void UdpLayer::run() +{ + return recv_loop(); +} + +/* higher level interface */ +void UdpLayer::recv_loop() +{ + int maxsize = 16000; + void *inbuf = malloc(maxsize); + + int status; + struct timeval timeout; + + while(1) + { + fd_set rset; + for(;;) + { + /* check if we need to stop */ + bool toStop = false; + { + bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/ + toStop = stopThread; + } + + if (toStop) + { +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::recv_loop() stopping thread" << std::endl; +#endif + stop(); + } + + FD_ZERO(&rset); + FD_SET(sockfd, &rset); + timeout.tv_sec = 0; + timeout.tv_usec = 500000; /* 500 ms timeout */ + status = select(sockfd+1, &rset, NULL, NULL, &timeout); + if (status > 0) + { + break; /* data available, go read it */ + } + else if (status < 0) + { +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::recv_loop() Error: " << bdnet_errno() << std::endl; +#endif + } + }; + + int nsize = maxsize; + struct sockaddr_in from; + if (0 < receiveUdpPacket(inbuf, &nsize, from)) + { +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::readPkt() from : " << from << std::endl; + std::cerr << printPkt(inbuf, nsize); +#endif + // send to reciever. + recv -> recvPkt(inbuf, nsize, from); + } + else + { +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::readPkt() not ready" << from; + std::cerr << std::endl; +#endif + } + } + + free(inbuf) ; + return; +} + + +int UdpLayer::sendPkt(const void *data, int size, const sockaddr_in &to, int ttl) +{ + /* if ttl is different -> set it */ + if (ttl != getTTL()) + { + setTTL(ttl); + } + + /* and send! */ +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::sendPkt() to: " << to << std::endl; + std::cerr << printPkt((void *) data, size); +#endif + sendUdpPacket(data, size, to); + return size; +} + +/* setup connections */ +int UdpLayer::openSocket() +{ + sockMtx.lock(); /********** LOCK MUTEX *********/ + + /* make a socket */ + sockfd = bdnet_socket(PF_INET, SOCK_DGRAM, 0); +#ifdef DEBUG_UDP_LAYER + std::cerr << "UpdStreamer::openSocket()" << std::endl; +#endif + /* bind to address */ + + +#ifdef UDP_LOOPBACK_TESTING + bdnet_inet_aton("127.0.0.1", &(laddr.sin_addr)); +#endif + +#ifdef OPEN_UNIVERSAL_PORT + struct sockaddr_in tmpaddr = laddr; + tmpaddr.sin_addr.s_addr = 0; + if (0 != bdnet_bind(sockfd, (struct sockaddr *) (&tmpaddr), sizeof(tmpaddr))) +#else + if (0 != bdnet_bind(sockfd, (struct sockaddr *) (&laddr), sizeof(laddr))) +#endif + { +#ifdef DEBUG_UDP_LAYER + std::cerr << "Socket Failed to Bind to : " << laddr << std::endl; + std::cerr << "Error: " << bdnet_errno() << std::endl; +#endif + errorState = EADDRINUSE; + //exit(1); + + sockMtx.unlock(); /******** UNLOCK MUTEX *********/ + return -1; + } + + if (-1 == bdnet_fcntl(sockfd, F_SETFL, O_NONBLOCK)) + { +#ifdef DEBUG_UDP_LAYER + std::cerr << "Failed to Make Non-Blocking" << std::endl; +#endif + } + +#ifdef UDP_ENABLE_BROADCAST + /* Setup socket for broadcast. */ + int val = 1; + if (-1 == setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(int))) + { +#ifdef DEBUG_UDP_LAYER + std::cerr << "Failed to Make Socket Broadcast" << std::endl; +#endif + } +#endif + + errorState = 0; + +#ifdef DEBUG_UDP_LAYER + std::cerr << "Socket Bound to : " << laddr << std::endl; +#endif + + sockMtx.unlock(); /******** UNLOCK MUTEX *********/ + +#ifdef DEBUG_UDP_LAYER + std::cerr << "Setting TTL to " << UDP_DEF_TTL << std::endl; +#endif + setTTL(UDP_DEF_TTL); + + // start up our thread. + { + bdStackMutex stack(sockMtx); /********** LOCK MUTEX *********/ + stopThread = false; + } + start(); + + return 1; + +} + +int UdpLayer::setTTL(int t) +{ + sockMtx.lock(); /********** LOCK MUTEX *********/ + + int err = bdnet_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &t, sizeof(int)); + ttl = t; + + sockMtx.unlock(); /******** UNLOCK MUTEX *********/ + +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::setTTL(" << t << ") returned: " << err; + std::cerr << std::endl; +#endif + + return err; +} + +int UdpLayer::getTTL() +{ + sockMtx.lock(); /********** LOCK MUTEX *********/ + + int t = ttl; + + sockMtx.unlock(); /******** UNLOCK MUTEX *********/ + + return t; +} + +/* monitoring / updates */ +int UdpLayer::okay() +{ + sockMtx.lock(); /********** LOCK MUTEX *********/ + + bool nonFatalError = ((errorState == 0) || + (errorState == EAGAIN) || + (errorState == EINPROGRESS)); + + sockMtx.unlock(); /******** UNLOCK MUTEX *********/ + +#ifdef DEBUG_UDP_LAYER + if (!nonFatalError) + { + std::cerr << "UdpLayer::NOT okay(): Error: " << errorState << std::endl; + } + +#endif + + return nonFatalError; +} + +int UdpLayer::tick() +{ +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::tick()" << std::endl; +#endif + return 1; +} + +/******************* Internals *************************************/ + +int UdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) +{ + struct sockaddr_in fromaddr; + socklen_t fromsize = sizeof(fromaddr); + int insize = *size; + + sockMtx.lock(); /********** LOCK MUTEX *********/ + + insize = bdnet_recvfrom(sockfd,data,insize,0, + (struct sockaddr*)&fromaddr,&fromsize); + + sockMtx.unlock(); /******** UNLOCK MUTEX *********/ + + if (0 < insize) + { +#ifdef DEBUG_UDP_LAYER + std::cerr << "receiveUdpPacket() from: " << fromaddr; + std::cerr << " Size: " << insize; + std::cerr << std::endl; +#endif + *size = insize; + from = fromaddr; + return insize; + } + return -1; +} + +int UdpLayer::sendUdpPacket(const void *data, int size, const struct sockaddr_in &to) +{ + /* send out */ +#ifdef DEBUG_UDP_LAYER + std::cerr << "UdpLayer::sendUdpPacket(): size: " << size; + std::cerr << " To: " << to << std::endl; +#endif + struct sockaddr_in toaddr = to; + + sockMtx.lock(); /********** LOCK MUTEX *********/ + + bdnet_sendto(sockfd, data, size, 0, + (struct sockaddr *) &(toaddr), + sizeof(toaddr)); + + sockMtx.unlock(); /******** UNLOCK MUTEX *********/ + return 1; +} + + +/**************************** LossyUdpLayer - for Testing **************/ + + +LossyUdpLayer::LossyUdpLayer(UdpReceiver *udpr, + struct sockaddr_in &local, double frac) + :UdpLayer(udpr, local), lossFraction(frac) +{ + return; +} +LossyUdpLayer::~LossyUdpLayer() { return; } + +int LossyUdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) +{ + if (0 < UdpLayer::receiveUdpPacket(data, size, from)) + { + float prob = bdRandom::random_f32(); + if (prob < lossFraction) + { + /* discard */ + std::cerr << "LossyUdpLayer::receiveUdpPacket() Dropping packet!"; + std::cerr << std::endl; + std::cerr << printPkt(data, *size); + std::cerr << std::endl; + std::cerr << "LossyUdpLayer::receiveUdpPacket() Packet Dropped!"; + std::cerr << std::endl; + + size = 0; + return -1; + } + + return *size; + } + return -1; +} + +int LossyUdpLayer::sendUdpPacket(const void *data, int size, struct sockaddr_in &to) +{ + double prob = (1.0 * (rand() / (RAND_MAX + 1.0))); + + if (prob < lossFraction) + { + /* discard */ + + std::cerr << "LossyUdpLayer::sendUdpPacket() Dropping packet!"; + std::cerr << std::endl; + std::cerr << printPkt((void *) data, size); + std::cerr << std::endl; + std::cerr << "LossyUdpLayer::sendUdpPacket() Packet Dropped!"; + std::cerr << std::endl; + + return size; + } + + // otherwise read normally; + return UdpLayer::sendUdpPacket(data, size, to); +} + +/**************************** LossyUdpLayer - for Testing **************/ + +PortRange::PortRange() :lport(0), uport(0) { return; } +PortRange::PortRange(uint16_t lp, uint16_t up) :lport(lp), uport(up) { return; } + +bool PortRange::inRange(uint16_t port) +{ + if (port < lport) + { + return false; + } + + if (port > uport) + { + return false; + } + return true; +} + + + +RestrictedUdpLayer::RestrictedUdpLayer(UdpReceiver *udpr, + struct sockaddr_in &local) + :UdpLayer(udpr, local) +{ + return; +} +RestrictedUdpLayer::~RestrictedUdpLayer() { return; } + +void RestrictedUdpLayer::addRestrictedPortRange(int lp, int up) +{ + PortRange pr(lp, up); + mLostPorts.push_back(pr); +} + +int RestrictedUdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from) +{ + if (0 < UdpLayer::receiveUdpPacket(data, size, from)) + { + /* check the port against list */ + uint16_t inPort = ntohs(from.sin_port); + + std::list::iterator it; + for(it = mLostPorts.begin(); it != mLostPorts.end(); it++) + { + if (it->inRange(inPort)) + { +#ifdef DEBUG_UDP_LAYER + std::cerr << "RestrictedUdpLayer::receiveUdpPacket() Dropping packet"; + std::cerr << ", Port(" << inPort << ") in restricted range!"; + std::cerr << std::endl; + //std::cerr << printPkt(data, *size); + //std::cerr << std::endl; +#endif + + size = 0; + return -1; + + } + + } + /* acceptable port */ + return *size; + } + return -1; +} + +int RestrictedUdpLayer::sendUdpPacket(const void *data, int size, struct sockaddr_in &to) +{ + /* check the port against list */ + uint16_t outPort = ntohs(to.sin_port); + + std::list::iterator it; + for(it = mLostPorts.begin(); it != mLostPorts.end(); it++) + { + if (it->inRange(outPort)) + { + /* drop */ +#ifdef DEBUG_UDP_LAYER + std::cerr << "RestrictedUdpLayer::sendUdpPacket() Dropping packet"; + std::cerr << ", Port(" << outPort << ") in restricted range!"; + std::cerr << std::endl; + //std::cerr << printPkt(data, *size); + //std::cerr << std::endl; +#endif + + return size; + } + + + } + + // otherwise read normally; + return UdpLayer::sendUdpPacket(data, size, to); +} + diff --git a/libbitdht/src/udp/udplayer.h b/libbitdht/src/udp/udplayer.h new file mode 100644 index 000000000..b82513d43 --- /dev/null +++ b/libbitdht/src/udp/udplayer.h @@ -0,0 +1,168 @@ +#ifndef BITDHT_UDP_LAYER_H +#define BITDHT_UDP_LAYER_H + +/* + * udp/udplayer.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2004-2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "util/bdthreads.h" +#include "util/bdnet.h" + +#include +#include +#include + +/* careful - duplicate definitions */ +//std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr); +std::ostream &operator<<(std::ostream &out, struct sockaddr_in &addr); + +bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); +bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2); + +std::string printPkt(void *d, int size); +std::string printPktOffset(unsigned int offset, void *d, unsigned int size); + + +/* UdpLayer ..... is the bottom layer which + * just sends and receives Udp packets. + */ + +class UdpReceiver +{ + public: +virtual ~UdpReceiver() {} +virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0; +virtual int status(std::ostream &out) = 0; +}; + +class UdpPublisher +{ + public: +virtual ~UdpPublisher() {} +virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) = 0; +}; + + +class UdpLayer: public bdThread +{ + public: + + UdpLayer(UdpReceiver *recv, struct sockaddr_in &local); +virtual ~UdpLayer() { return; } + +int reset(struct sockaddr_in &local); /* calls join, close, openSocket */ + +int status(std::ostream &out); + + /* setup connections */ + int closeSocket(); + int openSocket(); + + /* RsThread functions */ +virtual void run(); /* called once the thread is started */ + +void recv_loop(); /* uses callback to UdpReceiver */ + + /* Higher Level Interface */ + //int readPkt(void *data, int *size, struct sockaddr_in &from); + int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); + + /* monitoring / updates */ + int okay(); + int tick(); + + + /* data */ + /* internals */ + protected: + +virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); +virtual int sendUdpPacket(const void *data, int size, const struct sockaddr_in &to); + + int setTTL(int t); + int getTTL(); + + /* low level */ + private: + + UdpReceiver *recv; + + struct sockaddr_in laddr; /* local addr */ + + int errorState; + int sockfd; + int ttl; + bool stopThread; + + bdMutex sockMtx; +}; + + +/* For Testing - drops packets */ +class LossyUdpLayer: public UdpLayer +{ + public: + LossyUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local, double frac); +virtual ~LossyUdpLayer(); + + protected: + +virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); +virtual int sendUdpPacket(const void *data, int size, struct sockaddr_in &to); + + double lossFraction; +}; + +class PortRange +{ + public: + PortRange(); + PortRange(uint16_t lp, uint16_t up); + + bool inRange(uint16_t port); + + uint16_t lport; + uint16_t uport; +}; + + +/* For Testing - drops packets */ +class RestrictedUdpLayer: public UdpLayer +{ + public: + RestrictedUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local); +virtual ~RestrictedUdpLayer(); + +void addRestrictedPortRange(int lp, int up); + + protected: + +virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from); +virtual int sendUdpPacket(const void *data, int size, struct sockaddr_in &to); + + std::list mLostPorts; +}; + + +#endif diff --git a/libbitdht/src/udp/udpstack.cc b/libbitdht/src/udp/udpstack.cc new file mode 100644 index 000000000..b3ca88e75 --- /dev/null +++ b/libbitdht/src/udp/udpstack.cc @@ -0,0 +1,242 @@ +/* + * udp/udpstack.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "udp/udpstack.h" + +#include +#include +#include +#include +#include + +#include + +/*** + * #define DEBUG_UDP_RECV 1 + ***/ + +//#define DEBUG_UDP_RECV 1 + + +UdpStack::UdpStack(struct sockaddr_in &local) + :udpLayer(NULL), laddr(local) +{ + openSocket(); + return; +} + +UdpStack::UdpStack(int testmode, struct sockaddr_in &local) + :udpLayer(NULL), laddr(local) +{ + std::cerr << "UdpStack::UdpStack() Evoked in TestMode" << std::endl; + if (testmode == UDP_TEST_LOSSY_LAYER) + { + std::cerr << "UdpStack::UdpStack() Installing LossyUdpLayer" << std::endl; + udpLayer = new LossyUdpLayer(this, laddr, UDP_TEST_LOSSY_FRAC); + } + else if (testmode == UDP_TEST_RESTRICTED_LAYER) + { + std::cerr << "UdpStack::UdpStack() Installing RestrictedUdpLayer" << std::endl; + udpLayer = new RestrictedUdpLayer(this, laddr); + } + else + { + std::cerr << "UdpStack::UdpStack() Installing Standard UdpLayer" << std::endl; + // standard layer + openSocket(); + } + return; +} + +UdpLayer *UdpStack::getUdpLayer() /* for testing only */ +{ + return udpLayer; +} + +bool UdpStack::resetAddress(struct sockaddr_in &local) +{ + std::cerr << "UdpStack::resetAddress(" << local << ")"; + std::cerr << std::endl; + + return udpLayer->reset(local); +} + + + +/* higher level interface */ +int UdpStack::recvPkt(void *data, int size, struct sockaddr_in &from) +{ + /* print packet information */ +#ifdef DEBUG_UDP_RECV + std::cerr << "UdpStack::recvPkt(" << size << ") from: " << from; + std::cerr << std::endl; +#endif + + bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ + + std::list::iterator it; + for(it = mReceivers.begin(); it != mReceivers.end(); it++) + { + // See if they want the packet. + if ((*it)->recvPkt(data, size, from)) + { +#ifdef DEBUG_UDP_RECV + std::cerr << "UdpStack::recvPkt(" << size << ") from: " << from; + std::cerr << std::endl; +#endif + break; + } + } + return 1; +} + +int UdpStack::sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) +{ + /* print packet information */ +#ifdef DEBUG_UDP_RECV + std::cerr << "UdpStack::sendPkt(" << size << ") ttl: " << ttl; + std::cerr << " to: " << to; + std::cerr << std::endl; +#endif + + /* send to udpLayer */ + return udpLayer->sendPkt(data, size, to, ttl); +} + +int UdpStack::status(std::ostream &out) +{ + { + bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ + + out << "UdpStack::status()" << std::endl; + out << "localaddr: " << laddr << std::endl; + out << "UdpStack::SubReceivers:" << std::endl; + std::list::iterator it; + int i = 0; + for(it = mReceivers.begin(); it != mReceivers.end(); it++, i++) + { + out << "\tReceiver " << i << " --------------------" << std::endl; + (*it)->status(out); + } + out << "--------------------" << std::endl; + out << std::endl; + } + + udpLayer->status(out); + + return 1; +} + +/* setup connections */ +int UdpStack::openSocket() +{ + udpLayer = new UdpLayer(this, laddr); + return 1; +} + +/* monitoring / updates */ +int UdpStack::okay() +{ + return udpLayer->okay(); +} + +int UdpStack::close() +{ + /* TODO */ + return 1; +} + + + /* add a TCPonUDP stream */ +int UdpStack::addReceiver(UdpReceiver *recv) +{ + bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ + + /* check for duplicate */ + std::list::iterator it; + it = std::find(mReceivers.begin(), mReceivers.end(), recv); + if (it == mReceivers.end()) + { + mReceivers.push_back(recv); + return 1; + } + + /* otherwise its already there! */ + +#ifdef DEBUG_UDP_RECV + std::cerr << "UdpStack::addReceiver() Recv already exists!" << std::endl; + std::cerr << "UdpStack::addReceiver() ERROR" << std::endl; +#endif + + return 0; +} + +int UdpStack::removeReceiver(UdpReceiver *recv) +{ + bdStackMutex stack(stackMtx); /********** LOCK MUTEX *********/ + + /* check for duplicate */ + std::list::iterator it; + it = std::find(mReceivers.begin(), mReceivers.end(), recv); + if (it != mReceivers.end()) + { + mReceivers.erase(it); + return 1; + } + + /* otherwise its not there! */ + +#ifdef DEBUG_UDP_RECV + std::cerr << "UdpStack::removeReceiver() Recv dont exist!" << std::endl; + std::cerr << "UdpStack::removeReceiver() ERROR" << std::endl; +#endif + + return 0; +} + + + +/*****************************************************************************************/ + +UdpSubReceiver::UdpSubReceiver(UdpPublisher *pub) + :mPublisher(pub) +{ + return; +} + +int UdpSubReceiver::sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) +{ + /* print packet information */ +#ifdef DEBUG_UDP_RECV + std::cerr << "UdpSubReceiver::sendPkt(" << size << ") ttl: " << ttl; + std::cerr << " to: " << to; + std::cerr << std::endl; +#endif + + /* send to udpLayer */ + return mPublisher->sendPkt(data, size, to, ttl); +} + + diff --git a/libbitdht/src/udp/udpstack.h b/libbitdht/src/udp/udpstack.h new file mode 100644 index 000000000..9aeeed3a1 --- /dev/null +++ b/libbitdht/src/udp/udpstack.h @@ -0,0 +1,117 @@ +#ifndef BITDHT_UDP_STACK_RECEIVER_H +#define BITDHT_UDP_STACK_RECEIVER_H + +/* + * udp/udpstack.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include "util/bdthreads.h" +#include "util/bdnet.h" + +#include +#include +#include + +#include +#include + +#include "udp/udplayer.h" + +/* UdpStackReceiver is a Generic Receiver of info from a UdpLayer class. + * it provides a UdpReceiver class, and accepts a stack of UdpReceivers, + * which will be iterated through (in-order) until someone accepts the packet. + * + * It is important to order these Receivers correctly! + * + * This infact becomes the holder of the UdpLayer, and all controls + * go through the StackReceiver. + */ + +class UdpSubReceiver: public UdpReceiver +{ + public: + UdpSubReceiver(UdpPublisher *pub); + + /* calls mPublisher->sendPkt */ +virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); + /* callback for recved data (overloaded from UdpReceiver) */ +//virtual int recvPkt(void *data, int size, struct sockaddr_in &from) = 0; + + UdpPublisher *mPublisher; +}; + + +#define UDP_TEST_LOSSY_LAYER 1 +#define UDP_TEST_RESTRICTED_LAYER 2 + +#define UDP_TEST_LOSSY_FRAC (0.10) + +class UdpStack: public UdpReceiver, public UdpPublisher +{ + public: + + UdpStack(struct sockaddr_in &local); + UdpStack(int testmode, struct sockaddr_in &local); +virtual ~UdpStack() { return; } + +UdpLayer *getUdpLayer(); /* for testing only */ + +bool resetAddress(struct sockaddr_in &local); + + + /* add in a receiver */ +int addReceiver(UdpReceiver *recv); +int removeReceiver(UdpReceiver *recv); + + /* Packet IO */ + /* pass-through send packets */ +virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); + /* callback for recved data (overloaded from UdpReceiver) */ + +virtual int recvPkt(void *data, int size, struct sockaddr_in &from); + +int status(std::ostream &out); + + /* setup connections */ + int openSocket(); + + /* monitoring / updates */ + int okay(); +// int tick(); + + int close(); + + private: + + UdpLayer *udpLayer; + + bdMutex stackMtx; /* for all class data (below) */ + + struct sockaddr_in laddr; /* local addr */ + + std::list mReceivers; +}; + +#endif diff --git a/libbitdht/src/util/bdbloom.cc b/libbitdht/src/util/bdbloom.cc new file mode 100644 index 000000000..e6dbe3a58 --- /dev/null +++ b/libbitdht/src/util/bdbloom.cc @@ -0,0 +1,383 @@ +/* + * bitdht/bdbloom.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2011 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "util/bdbloom.h" + +#include +#include +#include + +/* Bloom Filter implementation */ + + +bloomFilter::bloomFilter(int m, int k) +{ + mBits.resize(m); + mHashFns.resize(k); + + mFilterBits = m; + mNoHashs = k; + mNoElements = 0; + + int i; + for(i = 0; i < m; i++) + { + mBits[i] = 0; + } + + for(i = 0; i < k; i++) + { + mHashFns[i] = NULL; + } + +} + +uint8_t convertCharToUint8(char ch1, char ch2) +{ + uint8_t value1 = 0; + uint8_t value2 = 0; + + /* do char1 */ + if (ch1 >= '0' && ch1 <= '9') + value1 = (ch1 - '0'); + else if (ch1 >= 'A' && ch1 <= 'F') + value1 = (ch1 - 'A' + 10); + else if (ch1 >= 'a' && ch1 <= 'f') + value1 = (ch1 - 'a' + 10); + + /* do char2 */ + if (ch2 >= '0' && ch2 <= '9') + value2 = (ch2 - '0'); + else if (ch2 >= 'A' && ch2 <= 'F') + value2 = (ch2 - 'A' + 10); + else if (ch2 >= 'a' && ch2 <= 'f') + value2 = (ch2 - 'a' + 10); + + uint8_t output = (value1 << 4) + value2; + return output; +} + +#define BITS_PER_BYTE (8) + +int bloomFilter::setFilterBits(const std::string &hex) +{ + int bytes = (mFilterBits / BITS_PER_BYTE); + if (mFilterBits % BITS_PER_BYTE) + { + bytes++; + } + + if (hex.size() < bytes * 2) + { + return 0; + } + + // convert to binary array. + uint8_t *tmparray = (uint8_t *) malloc(bytes); + int i = 0; + + for(i = 0; i < bytes; i++) + { + tmparray[i] = convertCharToUint8(hex[2 * i], hex[2 * i + 1]); + } + + + for(i = 0; i < mFilterBits; i++) + { + int byte = i / BITS_PER_BYTE; + int bit = i % BITS_PER_BYTE; + uint8_t value = (tmparray[byte] & (1 << bit)); + + if (value) + { + mBits[i] = 1; + } + else + { + mBits[i] = 0; + } + } + + free(tmparray); + return 1; +} + +std::string bloomFilter::getFilter() +{ + /* extract filter as a hex string */ + std::string output; + int bytes = (mFilterBits / BITS_PER_BYTE); + if (mFilterBits % BITS_PER_BYTE) + { + bytes++; + } + + // convert to binary array. + uint8_t *tmparray = (uint8_t *) malloc(bytes); + int i,j; + + for(i = 0; i < bytes; i++) + { + tmparray[i] = 0; + for(j = 0; j < BITS_PER_BYTE; j++) + { + int bit = i * BITS_PER_BYTE + j; + if (mBits[bit]) + { + tmparray[i] |= (1 << j); + } + } + } + + std::ostringstream out; + for(int i = 0; i < bytes; i++) + { + out << std::setw(2) << std::setfill('0') << std::hex << (uint32_t) (tmparray)[i]; + } + + free(tmparray); + + return out.str(); +} + +void bloomFilter::setBit(int bit) +{ + mBits[bit] = 1; + +} + + +bool bloomFilter::isBitSet(int bit) +{ + return (mBits[bit] == 1); +} + +uint32_t bloomFilter::filterBits() +{ + return mFilterBits; +} + +uint32_t bloomFilter::countBits() +{ + int count = 0; + int i; + for(i = 0; i < mFilterBits; i++) + { + if (mBits[i]) + { + count++; + } + } + return count; +} + + +void bloomFilter::printFilter(std::ostream &out) +{ + out << "bloomFilter: m = " << mFilterBits; + out << " k = " << mNoHashs; + out << " n = " << mNoElements; + out << std::endl; + + out << "BITS: "; + int i; + for(i = 0; i < mFilterBits; i++) + { + if ((i > 0) && (i % 32 == 0)) + { + out << std::endl; + out << "BITS: "; + } + if (mBits[i]) + { + out << "1"; + } + else + { + out << "0"; + } + } + out << std::endl; + out << "STR: " << getFilter(); + out << std::endl; +} + +void bloomFilter::setHashFunction(int idx, uint32_t (*hashfn)(const std::string &)) +{ + mHashFns[idx] = hashfn; +} + +void bloomFilter::add(const std::string &hex) +{ + uint32_t (*hashfn)(const std::string &); + int i; + for(i = 0; i < mNoHashs; i++) + { + hashfn = mHashFns[i]; + + int bit = hashfn(hex); + + setBit(bit); + } + + mNoElements++; + +} + +bool bloomFilter::test(const std::string &hex) +{ + uint32_t (*hashfn)(const std::string &); + int i; + for(i = 0; i < mNoHashs; i++) + { + hashfn = mHashFns[i]; + + int bit = hashfn(hex); + + if (!isBitSet(bit)) + { + return false; + } + } + return true; +} + +uint32_t getFirst10BitsAsNumber(const std::string &input) +{ + if (input.size() < 8) + { + std::cerr << "getFirst10BitsAsNumber() ERROR Size too small!"; + std::cerr << std::endl; + return 0; + } + + uint8_t data[4]; + + data[0] = convertCharToUint8(input[0], input[1]); + data[1] = convertCharToUint8(input[2], input[3]); + data[2] = convertCharToUint8(input[4], input[5]); + data[3] = convertCharToUint8(input[6], input[7]); + + uint32_t val = ((data[0] & 0xff) << 2) + ((data[1] & 0xc0) >> 6); + +#ifdef DEBUG_BLOOM + std::cerr << "getFirst10BitsAsNumber() input: " << input; + std::cerr << std::endl; + std::cerr << "getFirst10BitsAsNumber() "; + std::cerr << " data[0]: " << std::hex << (uint32_t) data[0]; + std::cerr << " data[1]: " << (uint32_t) data[1]; + std::cerr << " data[2]: " << (uint32_t) data[2]; + std::cerr << " data[3]: " << (uint32_t) data[3]; + std::cerr << " val: " << std::dec << (uint32_t) val; + std::cerr << std::endl; +#endif + + return val; +} + +uint32_t getSecond10BitsAsNumber(const std::string &input) +{ + if (input.size() < 8) + { + std::cerr << "getSecond10BitsAsNumber() ERROR Size too small!"; + std::cerr << std::endl; + return 0; + } + + uint8_t data[4]; + + data[0] = convertCharToUint8(input[0], input[1]); + data[1] = convertCharToUint8(input[2], input[3]); + data[2] = convertCharToUint8(input[4], input[5]); + data[3] = convertCharToUint8(input[6], input[7]); + + uint32_t val = ((data[1] & 0x3f) << 4) + ((data[2] & 0xf0) >> 4); + +#ifdef DEBUG_BLOOM + std::cerr << "getSecond10BitsAsNumber() input: " << input; + std::cerr << std::endl; + std::cerr << "getSecond10BitsAsNumber() "; + std::cerr << " data[0]: " << std::hex << (uint32_t) data[0]; + std::cerr << " data[1]: " << (uint32_t) data[1]; + std::cerr << " data[2]: " << (uint32_t) data[2]; + std::cerr << " data[3]: " << (uint32_t) data[3]; + std::cerr << " val: " << std::dec << (uint32_t) val; + std::cerr << std::endl; +#endif + + return val; +} + + +uint32_t getMid10BitsAsNumber(const std::string &input) +{ + if (input.size() < 8) + { + std::cerr << "getMid10BitsAsNumber() ERROR Size too small!"; + std::cerr << std::endl; + return 0; + } + + uint8_t data[4]; + + data[0] = convertCharToUint8(input[0], input[1]); + data[1] = convertCharToUint8(input[2], input[3]); + data[2] = convertCharToUint8(input[4], input[5]); + data[3] = convertCharToUint8(input[6], input[7]); + + uint32_t val = ((data[0] & 0x07) << 7) + ((data[1] & 0x7f) >> 1); + +#ifdef DEBUG_BLOOM + std::cerr << "getMid10BitsAsNumber() input: " << input; + std::cerr << std::endl; + std::cerr << "getMid10BitsAsNumber() "; + std::cerr << " data[0]: " << std::hex << (uint32_t) data[0]; + std::cerr << " data[1]: " << (uint32_t) data[1]; + std::cerr << " data[2]: " << (uint32_t) data[2]; + std::cerr << " data[3]: " << (uint32_t) data[3]; + std::cerr << " val: " << std::dec << (uint32_t) val; + std::cerr << std::endl; +#endif + + return val; +} + + +#define BDFILTER_M 1024 +#define BDFILTER_K 3 + +bdBloom::bdBloom() + :bloomFilter(BDFILTER_M, BDFILTER_K) +{ + /* set the fns. */ + setHashFunction(0, getFirst10BitsAsNumber); + setHashFunction(1, getSecond10BitsAsNumber); + setHashFunction(2, getMid10BitsAsNumber); +} + + + + + diff --git a/libbitdht/src/util/bdbloom.h b/libbitdht/src/util/bdbloom.h new file mode 100644 index 000000000..91257514e --- /dev/null +++ b/libbitdht/src/util/bdbloom.h @@ -0,0 +1,79 @@ +#ifndef BITDHT_BLOOM_H +#define BITDHT_BLOOM_H + +/* + * bitdht/bdbloom.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2011 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include +#include + +#include +#include + + +class bloomFilter +{ + public: + + bloomFilter(int m, int k); + +int setFilterBits(const std::string &hex); +std::string getFilter(); + +void printFilter(std::ostream &out); + +bool test(const std::string &hex); // takes first m bits. +void add(const std::string &hex); +uint32_t countBits(); +uint32_t filterBits(); + + protected: +void setHashFunction(int idx, uint32_t (*hashfn)(const std::string &)); + + private: +void setBit(int bit); +bool isBitSet(int bit); + + std::vector mBits; + std::vector mHashFns; + + uint32_t mFilterBits; + uint32_t mNoHashs; + uint32_t mNoElements; +}; + + +/* our specific implementation */ +class bdBloom: public bloomFilter +{ + public: + + bdBloom(); +}; + + +#endif + diff --git a/libbitdht/src/util/bdnet.cc b/libbitdht/src/util/bdnet.cc new file mode 100644 index 000000000..887230a2c --- /dev/null +++ b/libbitdht/src/util/bdnet.cc @@ -0,0 +1,359 @@ + +/* + * util/bdnet.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include "bdnet.h" + +#include +#include +#include + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#if defined(_WIN32) || defined(__MINGW32__) + + +/* error handling */ +int bdnet_int_errno; + +int bdnet_errno() +{ + return bdnet_int_errno; +} + +int bdnet_init() +{ + std::cerr << "bdnet_init()" << std::endl; + bdnet_int_errno = 0; + + // Windows Networking Init. + WORD wVerReq = MAKEWORD(2,2); + WSADATA wsaData; + + if (0 != WSAStartup(wVerReq, &wsaData)) + { + std::cerr << "Failed to Startup Windows Networking"; + std::cerr << std::endl; + } + else + { + std::cerr << "Started Windows Networking"; + std::cerr << std::endl; + } + + return 0; +} + +/* check if we can modify the TTL on a UDP packet */ +int bdnet_checkTTL(int fd) +{ + std::cerr << "bdnet_checkTTL()" << std::endl; + int optlen = 4; + char optval[optlen]; + + int ret = getsockopt(fd, IPPROTO_IP, IP_TTL, optval, &optlen); + //int ret = getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, optval, &optlen); + if (ret == SOCKET_ERROR) + { + ret = -1; + bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); + std::cerr << "bdnet_checkTTL() Failed!"; + std::cerr << std::endl; + } + else + { + std::cerr << "bdnet_checkTTL() :"; + std::cerr << (int) optval[0] << ":"; + std::cerr << (int) optval[1] << ":"; + std::cerr << (int) optval[2] << ":"; + std::cerr << (int) optval[3] << ": RET: "; + std::cerr << ret << ":"; + std::cerr << std::endl; + } + return ret; +} + +int bdnet_close(int fd) +{ + std::cerr << "bdnet_close()" << std::endl; + return closesocket(fd); +} + +int bdnet_socket(int domain, int type, int protocol) +{ + int osock = socket(domain, type, protocol); + std::cerr << "bdnet_socket()" << std::endl; + + if ((unsigned) osock == INVALID_SOCKET) + { + // Invalidate socket Unix style. + osock = -1; + bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); + } + bdnet_checkTTL(osock); + return osock; +} + +int bdnet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) +{ + std::cerr << "bdnet_bind()" << std::endl; + int ret = bind(sockfd,my_addr,addrlen); + if (ret != 0) + { + /* store unix-style error + */ + + ret = -1; + bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); + } + return ret; +} + +int bdnet_fcntl(int fd, int cmd, long arg) +{ + int ret; + + unsigned long int on = 1; + std::cerr << "bdnet_fcntl()" << std::endl; + + /* can only do NONBLOCK at the moment */ + if ((cmd != F_SETFL) || (arg != O_NONBLOCK)) + { + std::cerr << "bdnet_fcntl() limited to fcntl(fd, F_SETFL, O_NONBLOCK)"; + std::cerr << std::endl; + bdnet_int_errno = EOPNOTSUPP; + return -1; + } + + ret = ioctlsocket(fd, FIONBIO, &on); + + if (ret != 0) + { + /* store unix-style error + */ + + ret = -1; + bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); + } + return ret; +} + +int bdnet_setsockopt(int s, int level, int optname, + const void *optval, socklen_t optlen) +{ + std::cerr << "bdnet_setsockopt() val:" << *((int *) optval) << std::endl; + std::cerr << "bdnet_setsockopt() len:" << optlen << std::endl; + if ((level != IPPROTO_IP) || (optname != IP_TTL)) + { + std::cerr << "bdnet_setsockopt() limited to "; + std::cerr << "setsockopt(fd, IPPROTO_IP, IP_TTL, ....)"; + std::cerr << std::endl; + bdnet_int_errno = EOPNOTSUPP; + return -1; + } + + int ret = setsockopt(s, level, optname, (const char *) optval, optlen); + //int ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *) optval, optlen); + if (ret == SOCKET_ERROR) + { + ret = -1; + bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); + } + bdnet_checkTTL(s); + return ret; +} + +ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + std::cerr << "bdnet_recvfrom()" << std::endl; + int ret = recvfrom(s, (char *) buf, len, flags, from, fromlen); + if (ret == SOCKET_ERROR) + { + ret = -1; + bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); + } + return ret; +} + +ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + std::cerr << "bdnet_sendto()" << std::endl; + int ret = sendto(s, (const char *) buf, len, flags, to, tolen); + if (ret == SOCKET_ERROR) + { + ret = -1; + bdnet_int_errno = bdnet_w2u_errno(WSAGetLastError()); + } + return ret; +} + +int bdnet_w2u_errno(int err) +{ + /* switch */ + std::cerr << "tou_net_w2u_errno(" << err << ")" << std::endl; + switch(err) + { + case WSAEINPROGRESS: + return EINPROGRESS; + break; + case WSAEWOULDBLOCK: + return EINPROGRESS; + break; + case WSAENETUNREACH: + return ENETUNREACH; + break; + case WSAETIMEDOUT: + return ETIMEDOUT; + break; + case WSAEHOSTDOWN: + return EHOSTDOWN; + break; + case WSAECONNREFUSED: + return ECONNREFUSED; + break; + case WSAEADDRINUSE: + return EADDRINUSE; + break; + case WSAEUSERS: + return EUSERS; + break; + /* This one is returned for UDP recvfrom, when nothing there + * but not a real error... translate into EINPROGRESS + */ + case WSAECONNRESET: + std::cerr << "tou_net_w2u_errno(" << err << ")"; + std::cerr << " = WSAECONNRESET ---> EINPROGRESS"; + std::cerr << std::endl; + return EINPROGRESS; + break; + /*** + * + case WSAECONNRESET: + return ECONNRESET; + break; + * + ***/ + + case WSANOTINITIALISED: + std::cerr << "tou_net_w2u_errno(" << err << ") WSANOTINITIALISED. Fix Your Code!"; + std::cerr << std::endl; + break; + default: + std::cerr << "tou_net_w2u_errno(" << err << ") Unknown"; + std::cerr << std::endl; + break; + } + + return ECONNREFUSED; /* sensible default? */ +} + +int bdnet_inet_aton(const char *name, struct in_addr *addr) +{ + return (((*addr).s_addr = inet_addr(name)) != INADDR_NONE); +} + + + +int sleep(unsigned int sec) +{ + Sleep(sec * 1000); + return 0; +} + +int usleep(unsigned int usec) +{ + Sleep(usec / 1000); + return 0; +} + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else // UNIX + +/* Unix Version is easy -> just call the unix fn + */ + +#include /* for close definition */ + +/* the universal interface */ +int bdnet_init() { return 0; } +int bdnet_errno() { return errno; } + + +/* check if we can modify the TTL on a UDP packet */ +int bdnet_checkTTL(int /*fd*/) { return 1;} + + +int bdnet_inet_aton(const char *name, struct in_addr *addr) +{ + return inet_aton(name, addr); +} + +int bdnet_close(int fd) { return close(fd); } + +int bdnet_socket(int domain, int type, int protocol) +{ + return socket(domain, type, protocol); +} + +int bdnet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) +{ + return bind(sockfd,my_addr,addrlen); +} + +int bdnet_fcntl(int fd, int cmd, long arg) +{ + return fcntl(fd, cmd, arg); +} + +int bdnet_setsockopt(int s, int level, int optname, + const void *optval, socklen_t optlen) +{ + return setsockopt(s, level, optname, optval, optlen); +} + +ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + return recvfrom(s, buf, len, flags, from, fromlen); +} + +ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + return sendto(s, buf, len, flags, to, tolen); +} + + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + +void bdsockaddr_clear(struct sockaddr_in *addr) +{ + memset(addr, 0, sizeof(*addr)); +} + + diff --git a/libbitdht/src/util/bdnet.h b/libbitdht/src/util/bdnet.h new file mode 100644 index 000000000..2fc5f4a50 --- /dev/null +++ b/libbitdht/src/util/bdnet.h @@ -0,0 +1,171 @@ +#ifndef BITDHT_UNIVERSAL_NETWORK_HEADER +#define BITDHT_UNIVERSAL_NETWORK_HEADER +/* + * + * util/bdnet.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2004-2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + +#include + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#if defined(_WIN32) || defined(__MINGW32__) + +#include +#include +#include + +#include /* for ssize_t */ +typedef uint32_t in_addr_t; + +#else // UNIX + +#include +#include +#include +#include + +#include +#include + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + + +/* C Interface */ +#ifdef __cplusplus +extern "C" { +#endif + +/******* + * This defines a (unix-like) universal networking layer + * that should function on both windows and unix. (C - interface) + * + * This is of course only a subset of the full interface. + * functions required are: + * + * int bdnet_close(int fd); + * int bdnet_socket(int domain, int type, int protocol); + * int bdnet_bind(int sockfd, const struct sockaddr *my_addr, + * socklen_t addrlen); + * int bdnet_fcntl(int fd, int cmd, long arg); + * int bdnet_setsockopt(int s, int level, int optname, + * const void *optval, socklen_t optlen); + * ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, + * struct sockaddr *from, socklen_t *fromlen); + * ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, + * const struct sockaddr *to, socklen_t tolen); + * + * There are some non-standard ones as well: + * int bdnet_errno(); for internal networking errors + * int bdnet_init(); required for windows + * int bdnet_checkTTL(); a check if we can modify the ttl + */ + + +/* the universal interface */ +int bdnet_errno(); /* for internal networking errors */ +int bdnet_init(); /* required for windows */ +int bdnet_close(int fd); +int bdnet_socket(int domain, int type, int protocol); +int bdnet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen); +int bdnet_fcntl(int fd, int cmd, long arg); +int bdnet_setsockopt(int s, int level, int optname, + const void *optval, socklen_t optlen); +ssize_t bdnet_recvfrom(int s, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +ssize_t bdnet_sendto(int s, const void *buf, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen); + +/* address filling */ +int bdnet_inet_aton(const char *name, struct in_addr *addr); +/* check if we can modify the TTL on a UDP packet */ +int bdnet_checkTTL(int fd); + +void bdsockaddr_clear(struct sockaddr_in *addr); + +/* Extra stuff to declare for windows error handling (mimics unix errno) + */ + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#if defined(_WIN32) || defined(__MINGW32__) + +// Some Network functions that are missing from windows. +//in_addr_t inet_netof(struct in_addr addr); +//in_addr_t inet_network(char *inet_name); +//int inet_aton(const char *name, struct in_addr *addr); + + +// definitions for fcntl (NON_BLOCK) (random?) +#define F_SETFL 0x1010 +#define O_NONBLOCK 0x0100 + +// definitions for setsockopt (TTL) (random?) +//#define IPPROTO_IP 0x0011 +//#define IP_TTL 0x0110 + +/* define the Unix Error Codes that we use... + * NB. we should make the same, but not necessary + */ + +#define EAGAIN 11 +#define EWOULDBLOCK EAGAIN + +#define EUSERS 87 +#define ENOTSOCK 88 + +#define EOPNOTSUPP 95 + +#define EADDRINUSE 98 +#define EADDRNOTAVAIL 99 +#define ENETDOWN 100 +#define ENETUNREACH 101 + +#define ECONNRESET 104 + +#define ETIMEDOUT 10060 // value from pthread.h +#define ECONNREFUSED 111 +#define EHOSTDOWN 112 +#define EHOSTUNREACH 113 +#define EALREADY 114 +#define EINPROGRESS 115 + +int bdnet_w2u_errno(int error); + +/* also put the sleep commands in here (where else to go) + * ms uses millisecs. + * void Sleep(int ms); + */ +int sleep(unsigned int sec); +int usleep(unsigned int usec); + +#endif // END of WINDOWS defines. +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + +#ifdef __cplusplus +} /* C Interface */ +#endif + +#endif /* BITDHT_UNIVERSAL_NETWORK_HEADER */ diff --git a/libbitdht/src/util/bdrandom.cc b/libbitdht/src/util/bdrandom.cc new file mode 100644 index 000000000..b2d7ee2b8 --- /dev/null +++ b/libbitdht/src/util/bdrandom.cc @@ -0,0 +1,93 @@ +#include +#include +#include +#include "util/bdrandom.h" + +uint32_t bdRandom::index = 0 ; +std::vector bdRandom::MT(bdRandom::N,0u) ; +bdMutex bdRandom::rndMtx ; + +#if defined(_WIN32) || defined(__MINGW32__) +static bool auto_seed = bdRandom::seed( (time(NULL) + ((uint32_t) pthread_self().p)*0x1293fe)^0x18e34a12 ) ; +#else + #ifdef __APPLE__ + static bool auto_seed = bdRandom::seed( (time(NULL) + pthread_mach_thread_np(pthread_self())*0x1293fe + (getpid()^0x113ef76b))^0x18e34a12 ) ; + #else + static bool auto_seed = bdRandom::seed( (time(NULL) + pthread_self()*0x1293fe + (getpid()^0x113ef76b))^0x18e34a12 ) ; + #endif +#endif +bool bdRandom::seed(uint32_t s) +{ + bdStackMutex mtx(rndMtx) ; + + MT.resize(N,0) ; // because MT might not be already resized + + uint32_t j ; + MT[0]= s & 0xffffffffUL; + for (j=1; j> 30)) + j) & 0xffffffffUL ; + + return true ; +} + +void bdRandom::locked_next_state() +{ + for(uint32_t i=0;i> 1) ; + + if((y & 1) == 1) + MT[i] = MT[i] ^ 0x9908b0df ; + } + index = 0 ; +} + +uint32_t bdRandom::random_u32() +{ + uint32_t y; + + { + bdStackMutex mtx(rndMtx) ; + + y = MT[index++] ; + + if(index == N) + locked_next_state(); + } + + // Tempering + y ^= (y >> 11); + y ^= (y << 7 ) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + return y; +} + +uint64_t bdRandom::random_u64() +{ + return ((uint64_t)random_u32() << 32ul) + random_u32() ; +} + +float bdRandom::random_f32() +{ + return random_u32() / (float)(~(uint32_t)0) ; +} + +double bdRandom::random_f64() +{ + return random_u64() / (double)(~(uint64_t)0) ; +} + +std::string bdRandom::random_alphaNumericString(uint32_t len) +{ + std::string s = "" ; + + for(uint32_t i=0;i + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* This Source Code is basically a direct copy of libretroshare's RsRandom. + * the function names have just been renamed. drbob + */ + + +// bdRandom contains a random number generator that is +// - thread safe +// - system independant +// - fast +// - cryptographically safe +// +// The implementation is adapted from the Mersenne Twister page of Wikipedia. +// +// http://en.wikipedia.org/wiki/Mersenne_twister + +#include +#include "util/bdthreads.h" + +class bdRandom +{ + public: + static uint32_t random_u32() ; + static uint64_t random_u64() ; + static float random_f32() ; + static double random_f64() ; + + static bool seed(uint32_t s) ; + + static std::string random_alphaNumericString(uint32_t length) ; + + private: + static bdMutex rndMtx ; + + static const uint32_t N = 624; + static const uint32_t M = 397; + + static const uint32_t MATRIX_A = 0x9908b0dfUL; + static const uint32_t UMASK = 0x80000000UL; + static const uint32_t LMASK = 0x7fffffffUL; + + static void locked_next_state() ; + static uint32_t index ; + static std::vector MT ; +}; + +#endif \ No newline at end of file diff --git a/libbitdht/src/util/bdthreads.cc b/libbitdht/src/util/bdthreads.cc new file mode 100644 index 000000000..2d70e7f31 --- /dev/null +++ b/libbitdht/src/util/bdthreads.cc @@ -0,0 +1,172 @@ +/* + * util/bdthreads.cc + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2004-2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + + +#include "bdthreads.h" +#include /* for usleep() */ + +/******* + * #define DEBUG_THREADS 1 + *******/ + +#define DEBUG_THREADS 1 + +#ifdef DEBUG_THREADS + #include +#endif + +extern "C" void* bdthread_init(void* p) +{ +#ifdef DEBUG_THREADS + std::cerr << "bdthread_init()"; + std::cerr << std::endl; +#endif + + bdThread *thread = (bdThread *) p; + if (!thread) + { +#ifdef DEBUG_THREADS + std::cerr << "bdthread_init() Error Invalid thread pointer."; + std::cerr << std::endl; +#endif + return 0; + } + thread -> run(); + return 0; +} + + +pthread_t createThread(bdThread &thread) +{ + pthread_t tid; + void *data = (void *) (&thread); + +#ifdef DEBUG_THREADS + std::cerr << "createThread() creating a bdThread"; + std::cerr << std::endl; +#endif + + thread.mMutex.lock(); + { + pthread_create(&tid, 0, &bdthread_init, data); + thread.mTid = tid; + } + +#ifdef DEBUG_THREADS + std::cerr << "createThread() created Thread.mTid: "; + +#if defined(_WIN32) || defined(__MINGW32__) + std::cerr << "WIN32: Cannot print mTid "; +#else + std::cerr << thread.mTid; +#endif + std::cerr << std::endl; + +#endif + + thread.mMutex.unlock(); + + + + return tid; + +} + +bdThread::bdThread() +{ + +#ifdef DEBUG_THREADS + std::cerr << "bdThread::bdThread()"; + std::cerr << std::endl; +#endif + +#if defined(_WIN32) || defined(__MINGW32__) + memset (&mTid, 0, sizeof(mTid)); +#else + mTid = 0; +#endif +} + +void bdThread::join() /* waits for the the mTid thread to stop */ +{ +#ifdef DEBUG_THREADS + std::cerr << "bdThread::join() Called! Waiting for Thread.mTid: "; + +#if defined(_WIN32) || defined(__MINGW32__) + std::cerr << "WIN32: Cannot print mTid "; +#else + std::cerr << mTid; +#endif + + std::cerr << std::endl; +#endif + + mMutex.lock(); + { +#if defined(_WIN32) || defined(__MINGW32__) + /* Its a struct in Windows compile and the member .p ist checked in the pthreads library */ +#else + if(mTid > 0) +#endif + pthread_join(mTid, NULL); + +#ifdef DEBUG_THREADS + std::cerr << "bdThread::join() Joined Thread.mTid: "; + +#if defined(_WIN32) || defined(__MINGW32__) + std::cerr << "WIN32: Cannot print mTid "; +#else + std::cerr << mTid; +#endif + + std::cerr << std::endl; + std::cerr << "bdThread::join() Setting mTid = 0"; + std::cerr << std::endl; +#endif + +#if defined(_WIN32) || defined(__MINGW32__) + memset (&mTid, 0, sizeof(mTid)); +#else + mTid = 0; +#endif + + } + mMutex.unlock(); + +} + +void bdThread::stop() +{ +#ifdef DEBUG_THREADS + std::cerr << "bdThread::stop() Called!"; + std::cerr << std::endl; +#endif + + pthread_exit(NULL); +} + + + diff --git a/libbitdht/src/util/bdthreads.h b/libbitdht/src/util/bdthreads.h new file mode 100644 index 000000000..d44ff947d --- /dev/null +++ b/libbitdht/src/util/bdthreads.h @@ -0,0 +1,99 @@ +#ifndef BITDHT_THREADS_H +#define BITDHT_THREADS_H + +/* + * util/bdthreads.h + * + * BitDHT: An Flexible DHT library. + * + * Copyright 2004-2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "bitdht@lunamutt.com". + * + */ + + +#include +#include +#include + +/* Thread Wrappers */ + +class bdMutex +{ + public: + + bdMutex(bool recursive = false) + { +#if 0 // TESTING WITHOUT RECURSIVE + if(recursive) + { + pthread_mutexattr_t att ; + pthread_mutexattr_init(&att) ; + pthread_mutexattr_settype(&att,PTHREAD_MUTEX_RECURSIVE) ; + + if( pthread_mutex_init(&realMutex, &att)) + std::cerr << "ERROR: Could not initialize mutex !" << std::endl ; + } + else +#endif + if( pthread_mutex_init(&realMutex, NULL)) + std::cerr << "ERROR: Could not initialize mutex !" << std::endl ; + } + + ~bdMutex() { pthread_mutex_destroy(&realMutex); } + void lock() { pthread_mutex_lock(&realMutex); } + void unlock() { pthread_mutex_unlock(&realMutex); } + bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); } + + private: + pthread_mutex_t realMutex; +}; + +class bdStackMutex +{ + public: + + bdStackMutex(bdMutex &mtx): mMtx(mtx) { mMtx.lock(); } + ~bdStackMutex() { mMtx.unlock(); } + + private: + bdMutex &mMtx; +}; + +class bdThread; + +/* to create a thread! */ +pthread_t createThread(bdThread &thread); + +class bdThread +{ + public: + bdThread(); +virtual ~bdThread() { return; } + +virtual void start() { createThread(*this); } +virtual void run() = 0; /* called once the thread is started */ +virtual void join(); /* waits for the mTid thread to stop */ +virtual void stop(); /* calls pthread_exit() */ + + pthread_t mTid; + bdMutex mMutex; +}; + + +#endif diff --git a/libretroshare/src/BUGS b/libretroshare/src/BUGS new file mode 100644 index 000000000..a169439d1 --- /dev/null +++ b/libretroshare/src/BUGS @@ -0,0 +1,11 @@ + +This is the list of known BUGS: +------------------------------- + * None! + + + + + + + diff --git a/libretroshare/src/Doxyfile b/libretroshare/src/Doxyfile new file mode 100644 index 000000000..174c7743f --- /dev/null +++ b/libretroshare/src/Doxyfile @@ -0,0 +1,246 @@ +# Doxyfile 1.5.6 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = +PROJECT_NUMBER = +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = YES +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +HTML_DYNAMIC_SECTIONS = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NONE +TREEVIEW_WIDTH = 250 +FORMULA_FONTSIZE = 10 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +DOT_FONTNAME = FreeSans +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +CALLER_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = YES +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = YES diff --git a/libretroshare/src/Readme.txt b/libretroshare/src/Readme.txt new file mode 100644 index 000000000..e4c645361 --- /dev/null +++ b/libretroshare/src/Readme.txt @@ -0,0 +1,65 @@ +======================================================================================= +README for RetroShare +======================================================================================= + +RetroShare web site . . . . http://retroshare.sourceforge.net/ +Documentation . . . . . . . http://retroshare.sourceforge.net/doc.html +Support . . . . . . . . . . http://retroshare.sourceforge.net/support.html +Forums . . . . . . . . . . http://retroshare.sourceforge.net/forum/ +Wiki . . . . . . . . . . . http://retroshare.sourceforge.net/wiki/ +The Developers site . . . . http://retroshare.sourceforge.net/developers.html +Project site . . . . . . . https://sourceforge.net/projects/retroshare + +Contact: . . . . . . . . . retroshare@lunamutt.com ,defnax@users.sourceforge.net + + +Compiling + Running RetroShare (V0.5.xxx) +========================================================================================= +REQUIREMENTS +========================================================================================= + +Libraries/Tools: + * C/C++ Compiler. (standard on Linux/cygwin) + * Qt >= 4.5.x http://qt.nokia.com/downloads/downloads#lgpl + * OpenSSL http://www.openssl.org/source/openssl-0.9.8k.tar.gz + * MiniUPnP http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.3.tar.gz + * gpgme ftp://ftp.gnupg.org/gcrypt/gpgme/gpgme-1.1.8.tar.bz2 + * libgpg-error ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.7.tar.bz2 + +Windows only: + * Cygwin http://www.cygwin.com/cygwin/setup.exe (for openssl compile) + * MinGW/Msys package http://sourceforge.net/projects/mingw/files/ (for compile gpgme,libgpg-error) + * Pthreads http://sourceware.org/pthreads-win32/ + * Zlib http://www.zlib.net/ + + Latest RetroShare sources from (SVN) sourceforge.net: + svn co https://retroshare.svn.sourceforge.net/svnroot/retroshare retroshare + +========================================================================================= + +Build Scripts are avaible on SVN for Debian and Ubuntu: +http://retroshare.svn.sourceforge.net/viewvc/retroshare/trunk/build_scripts/ + +Latest stable OpenSSL is available at: +http://www.openssl.org + +Latest miniupnpc-1.3 is avaible at: +http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.3.tar.gz + +Latest gpgme Library is avaible at: +ftp://ftp.gnupg.org/gcrypt/gpgme/gpgme-1.1.8.tar.bz2 + +Latest libgpg-error Library is avaible at: +ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.7.tar.bz2 + +Windows only: + pthreads: ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz + zlib: http://www.zlib.net/zlib-1.2.3.tar.gz +========================================================================================= +You can find here instrustions howto compile libretroshare and gui: +http://retroshare.sourceforge.net/wiki/index.php/Developers_Corner + +========================================================================================= +You can go on over to our forum when you have trouble with compiling: +http://retroshare.sourceforge.net/forum/ +--------------------------------------------- diff --git a/libretroshare/src/TODO b/libretroshare/src/TODO new file mode 100644 index 000000000..0e5e4f51b --- /dev/null +++ b/libretroshare/src/TODO @@ -0,0 +1,7 @@ + +TODO +--------------- + +Too much to list... + +test SVN \ No newline at end of file diff --git a/libretroshare/src/dbase/cachestrapper.cc b/libretroshare/src/dbase/cachestrapper.cc new file mode 100644 index 000000000..729f62fd4 --- /dev/null +++ b/libretroshare/src/dbase/cachestrapper.cc @@ -0,0 +1,1220 @@ +/* + * RetroShare FileCache Module: cachestrapper.cc + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "dbase/cachestrapper.h" +#include "serialiser/rsconfigitems.h" +#include "pqi/p3connmgr.h" +#include "util/rsdir.h" + +#include +#include +#include + +/**** + * #define CS_DEBUG 1 + ***/ + +bool operator<(const CacheId &a, const CacheId &b) +{ + if (a.type == b.type) + return (a.subid < b.subid); + return (a.type < b.type); +} + +bool operator<(const CachePair &a, const CachePair &b) +{ + return (a.id < b.id); +} + + +std::ostream &operator<<(std::ostream &out, const CacheData &d) +{ + out << "[ p: " << d.pid << " id: <" << d.cid.type << "," << d.cid.subid; + out << "> #" << d.hash << " size: " << d.size; + out << " \"" << d.name << "\"@\"" << d.path; + out << "\" ]"; + return out; +} + +/********************************* Cache Store / Source ************************** + * This is a generic interface which interacts with the FileTransfer Unit + * to collect Data to be Cached. + * + ********************************* Cache Store / Source *************************/ + +CacheSource::CacheSource(uint16_t t, bool m, CacheStrapper *cs, std::string cachedir) + :cacheType(t), multiCache(m), mStrapper(cs), cacheDir(cachedir) + { + return; + } + + /* Mutex Stuff -> to be done... */ +void CacheSource::lockData() const +{ +#ifdef CS_DEBUG + std::cerr << "CacheSource::lockData()" << std::endl; +#endif + cMutex.lock(); +} + +void CacheSource::unlockData() const +{ +#ifdef CS_DEBUG + std::cerr << "CacheSource::unlockData()" << std::endl; +#endif + cMutex.unlock(); +} + + /* to be overloaded for inherited Classes */ +bool CacheSource::loadLocalCache(const CacheData &data) +{ + return refreshCache(data); +} + + /* control Caches available */ +bool CacheSource::refreshCache(const CacheData &data) +{ + lockData(); /* LOCK MUTEX */ + + bool ret = false; + if (data.cid.type == getCacheType()) + { + int subid = 0; + if (isMultiCache()) + { + subid = data.cid.subid; + } + + /* Backup the old Caches */ + CacheSet::const_iterator it; + if (caches.end() != (it = caches.find(subid))) + { + mOldCaches[it->second.hash] = it->second; + } + + /* store new cache */ + caches[subid] = data; + ret = true; + } + + unlockData(); /* UNLOCK MUTEX */ + + if (mStrapper) /* allow testing without full feedback */ + mStrapper->refreshCache(data); + return ret; +} + +bool CacheSource::clearCache(CacheId id) +{ + lockData(); /* LOCK MUTEX */ + + bool ret = false; + if (id.type == getCacheType()) + { + CacheSet::iterator it; + if (caches.end() != (it = caches.find(id.subid))) + { + /* Backup the old Caches */ + mOldCaches[it->second.hash] = it->second; + caches.erase(it); + ret = true; + } + } + + unlockData(); /* UNLOCK MUTEX */ + return ret; +} + +bool CacheSource::cachesAvailable(RsPeerId /* pid */, std::map &ids) +{ + lockData(); /* LOCK MUTEX */ + + /* can overwrite for more control! */ + CacheSet::iterator it; + for(it = caches.begin(); it != caches.end(); it++) + { + ids[(it->second).cid] = it->second; + } + bool ret = (caches.size() > 0); + + unlockData(); /* UNLOCK MUTEX */ + return ret; + +} + + +bool CacheSource::findCache(std::string hash, CacheData &data) const +{ + lockData(); /* LOCK MUTEX */ + + bool found = false; + CacheSet::const_iterator it; + for(it = caches.begin(); it != caches.end(); it++) + { + if (hash == (it->second).hash) + { + data = it->second; + found = true; + break; + } + } + + if (!found) + { + std::map::const_iterator oit; + oit = mOldCaches.find(hash); + if (oit != mOldCaches.end()) + { + data = oit->second; + found = true; + } + } + + unlockData(); /* UNLOCK MUTEX */ + + return found; +} + + +void CacheSource::listCaches(std::ostream &out) +{ + lockData(); /* LOCK MUTEX */ + + /* can overwrite for more control! */ + CacheSet::iterator it; + out << "CacheSource::listCaches() [" << getCacheType(); + out << "] Total: " << caches.size() << std::endl; + int i; + for(i = 0, it = caches.begin(); it != caches.end(); it++, i++) + { + out << "\tC[" << i << "] : " << it->second << std::endl; + } + + unlockData(); /* UNLOCK MUTEX */ + return; +} + + +CacheStore::CacheStore(uint16_t t, bool m, + CacheStrapper *cs, CacheTransfer *cft, std::string cachedir) + :cacheType(t), multiCache(m), mStrapper(cs), + cacheTransfer(cft), cacheDir(cachedir) + { + /* not much */ + return; + } + + /* Mutex Stuff -> to be done... */ +void CacheStore::lockData() const +{ +#ifdef CS_DEBUG +// std::cerr << "CacheStore::lockData()" << std::endl; +#endif + cMutex.lock(); +} + +void CacheStore::unlockData() const +{ +#ifdef CS_DEBUG +// std::cerr << "CacheStore::unlockData()" << std::endl; +#endif + cMutex.unlock(); +} + +void CacheStore::listCaches(std::ostream &out) +{ + lockData(); /* LOCK MUTEX */ + + /* can overwrite for more control! */ + std::map::iterator pit; + out << "CacheStore::listCaches() [" << getCacheType(); + out << "] Total People: " << caches.size(); + out << std::endl; + for(pit = caches.begin(); pit != caches.end(); pit++) + { + CacheSet::iterator it; + out << "\tTotal for [" << pit->first << "] : " << (pit->second).size(); + out << std::endl; + for(it = (pit->second).begin(); it != (pit->second).end(); it++) + { + out << "\t\t" << it->second; + out << std::endl; + } + } + + unlockData(); /* UNLOCK MUTEX */ + return; +} + + + /* look for stored data. using pic/cid in CacheData + */ +bool CacheStore::getStoredCache(CacheData &data) +{ + lockData(); /* LOCK MUTEX */ + + bool ok = locked_getStoredCache(data); + + unlockData(); /* UNLOCK MUTEX */ + return ok; +} + +bool CacheStore::cached(const std::string cacheId) +{ + + return false; +} + +void CacheStore::updateCacheDocument(pugi::xml_document& cacheDoc) +{ + return; +} + +void CacheStore::updateCacheTable() +{ + return; +} + +bool CacheStore::locked_getStoredCache(CacheData &data) +{ + if (data.cid.type != getCacheType()) + { + return false; + } + + std::map::iterator pit; + if (caches.end() == (pit = caches.find(data.pid))) + { + return false; + } + + CacheSet::iterator cit; + if (isMultiCache()) + { + /* look for subid */ + if ((pit->second).end() == + (cit = (pit->second).find(data.cid.subid))) + { + return false; + } + } + else + { + if ((pit->second).end() == + (cit = (pit->second).find(0))) + { + return false; + } + } + + /* we found it! (cit) */ + data = cit->second; + + return true; +} + + + +bool CacheStore::getAllStoredCaches(std::list &data) +{ + lockData(); /* LOCK MUTEX */ + + std::map::iterator pit; + for(pit = caches.begin(); pit != caches.end(); pit++) + { + CacheSet::iterator cit; + /* look for subid */ + for(cit = (pit->second).begin(); + cit != (pit->second).end(); cit++) + { + data.push_back(cit->second); + } + } + + unlockData(); /* UNLOCK MUTEX */ + + return true; +} + + + /* input from CacheStrapper. + * check if we want to download it... + * determine the new name/path + * then request it. + */ +void CacheStore::availableCache(const CacheData &data) +{ +#ifdef CS_DEBUG + std::cerr << "CacheStore::availableCache() :" << data << std::endl; +#endif + + /* basic checks */ + lockData(); /* LOCK MUTEX */ + + bool rightCache = (data.cid.type == getCacheType()); + + unlockData(); /* UNLOCK MUTEX */ + + if (!rightCache) + { + return; /* bad id */ + } + + /* These Functions lock the Mutex themselves + */ + + if (!fetchCache(data)) + { + return; /* ignore it */ + } + + CacheData rData = data; + + /* get new name */ + if (!nameCache(rData)) + { + return; /* error naming */ + } + + /* request it */ + cacheTransfer -> RequestCache(rData, this); + + /* will get callback when it is complete */ + return; +} + + + + /* called when the download is completed ... updates internal data */ +void CacheStore::downloadedCache(const CacheData &data) +{ +#ifdef CS_DEBUG + std::cerr << "CacheStore::downloadedCache() :" << data << std::endl; +#endif + + /* updates data */ + if (!loadCache(data)) + { + return; + } +} + /* called when the download is completed ... updates internal data */ +void CacheStore::failedCache(const CacheData &data) +{ + (void) data; +#ifdef CS_DEBUG + std::cerr << "CacheStore::failedCache() :" << data << std::endl; +#endif + + return; +} + + + /* virtual function overloaded by cache implementor */ +bool CacheStore::fetchCache(const CacheData &data) +{ + /* should we fetch it? */ +#ifdef CS_DEBUG + std::cerr << "CacheStore::fetchCache() tofetch?:" << data << std::endl; +#endif + + CacheData incache = data; + + lockData(); /* LOCK MUTEX */ + + bool haveCache = ((locked_getStoredCache(incache)) && (data.hash == incache.hash)); + + unlockData(); /* UNLOCK MUTEX */ + + + if (haveCache) + { +#ifdef CS_DEBUG + std::cerr << "CacheStore::fetchCache() Already have it: false" << std::endl; +#endif + return false; + } + +#ifdef CS_DEBUG + std::cerr << "CacheStore::fetchCache() Missing this cache: true" << std::endl; +#endif + return true; +} + + +int CacheStore::nameCache(CacheData &data) +{ + /* name it... */ + lockData(); /* LOCK MUTEX */ + +#ifdef CS_DEBUG + std::cerr << "CacheStore::nameCache() for:" << data << std::endl; +#endif + + data.name = data.hash; + data.path = getCacheDir(); + +#ifdef CS_DEBUG + std::cerr << "CacheStore::nameCache() done:" << data << std::endl; +#endif + + unlockData(); /* UNLOCK MUTEX */ + + return 1; +} + + +int CacheStore::loadCache(const CacheData &data) +{ + /* attempt to load -> dummy function */ +#ifdef CS_DEBUG + std::cerr << "CacheStore::loadCache() Dummy Load for:" << data << std::endl; +#endif + + lockData(); /* LOCK MUTEX */ + + locked_storeCacheEntry(data); + + unlockData(); /* UNLOCK MUTEX */ + + return 1; +} + +/* This function is called to store Cache Entry in the CacheStore Table. + * it must be called from within a Mutex Lock.... + * + * It doesn't lock itself -> to avoid race conditions + */ + +void CacheStore::locked_storeCacheEntry(const CacheData &data) +{ + /* store what we loaded - overwriting if necessary */ + std::map::iterator pit; + if (caches.end() == (pit = caches.find(data.pid))) + { + /* add in a new CacheSet */ + CacheSet emptySet; + caches[data.pid] = emptySet; + + pit = caches.find(data.pid); + } + + if (isMultiCache()) + { + (pit->second)[data.cid.subid] = data; + } + else + { + (pit->second)[0] = data; + } + + /* tell the strapper we've loaded one */ + if (mStrapper) + { + mStrapper->refreshCacheStore(data); + } + return; +} + + +/********************************* CacheStrapper ********************************* + * This is the bit which handles queries + * + ********************************* CacheStrapper ********************************/ + +CacheStrapper::CacheStrapper(p3ConnectMgr *cm) + :p3Config(CONFIG_TYPE_CACHE), mConnMgr(cm) +{ + return; +} + + +void CacheStrapper::addCachePair(CachePair set) +{ + caches[set.id.type] = set; +} + + + /**************** from pqimonclient ********************/ + +void CacheStrapper::statusChange(const std::list &plist) +{ + std::list::const_iterator it; + for(it = plist.begin(); it != plist.end(); it++) + { + if (it->actions & RS_PEER_CONNECTED) + { + /* grab all the cache ids and add */ + + std::map hashs; + std::map::iterator cit; + + handleCacheQuery(it->id, hashs); + + RsStackMutex stack(csMtx); /******* LOCK STACK MUTEX *********/ + for(cit = hashs.begin(); cit != hashs.end(); cit++) + { + mCacheUpdates.push_back(std::make_pair(it->id, cit->second)); + } + } + } +} + + /**************** from pqimonclient ********************/ + + +void CacheStrapper::refreshCache(const CacheData &data) +{ + /* we've received an update + * send to all online peers + self + */ +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::refreshCache() : " << data << std::endl; +#endif + + std::list ids; + std::list::iterator it; + + mConnMgr->getOnlineList(ids); + + RsStackMutex stack(csMtx); /******* LOCK STACK MUTEX *********/ + for(it = ids.begin(); it != ids.end(); it++) + { +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::refreshCache() Send To: " << *it << std::endl; +#endif + + mCacheUpdates.push_back(std::make_pair(*it, data)); + } + + mCacheUpdates.push_back(std::make_pair(mConnMgr->getOwnId(), data)); + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ +} + + +void CacheStrapper::refreshCacheStore(const CacheData & /* data */ ) +{ + /* indicate to save data */ + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + +} + +bool CacheStrapper::getCacheUpdates(std::list > &updates) +{ + RsStackMutex stack(csMtx); /******* LOCK STACK MUTEX *********/ + updates = mCacheUpdates; + mCacheUpdates.clear(); + + return true; +} + + + + /* pass to correct CacheSet */ +void CacheStrapper::recvCacheResponse(CacheData &data, time_t /* ts */) +{ + /* find cache store */ + std::map::iterator it2; + if (caches.end() == (it2 = caches.find(data.cid.type))) + { + /* error - don't have this type of cache */ + return; + } + + /* notify the CacheStore */ + (it2 -> second).store -> availableCache(data); + +} + + + /* generate periodically or at a change */ +#if 0 +bool CacheStrapper::sendCacheQuery(std::list &id, time_t ts) +{ + /* iterate through peers, and see who we haven't got an answer from recently */ + std::map::iterator it; + for(it = status.begin(); it != status.end(); it++) + { + if ((ts - (it->second).query) > queryPeriod) + { + /* query this one */ + id.push_back(it->first); + (it->second).query = ts; + } + } + return (id.size() > 0); +} +#endif + + +void CacheStrapper::handleCacheQuery(RsPeerId id, std::map &hashs) +{ + /* basic version just iterates through .... + * more complex could decide who gets what! + * + * or that can be handled on a cache by cache basis. + */ + + std::map::iterator it; + for(it = caches.begin(); it != caches.end(); it++) + { + (it->second).source -> cachesAvailable(id, hashs); + } + return; +} + +void CacheStrapper::listCaches(std::ostream &out) +{ + /* can overwrite for more control! */ + std::map::iterator it; + out << "CacheStrapper::listCaches() [" << mConnMgr->getOwnId(); + out << "] " << " Total Caches: " << caches.size(); + out << std::endl; + for(it = caches.begin(); it != caches.end(); it++) + { + out << "CacheType: " << it->first; + out << std::endl; + + (it->second).source->listCaches(out); + (it->second).store->listCaches(out); + out << std::endl; + } + return; +} + +void CacheStrapper::listPeerStatus(std::ostream & /* out */) +{ +#if 0 + std::map::iterator it; + out << "CacheStrapper::listPeerStatus() [" << ownId; + out << "] Total Peers: " << status.size() << " Total Caches: " << caches.size(); + out << std::endl; + for(it = status.begin(); it != status.end(); it++) + { + out << "Peer: " << it->first; + out << " Query: " << (it->second).query; + out << " Answer: " << (it->second).answer; + out << std::endl; + } + return; +#endif +} + + +bool CacheStrapper::findCache(std::string hash, CacheData &data) const +{ + /* can overwrite for more control! */ + std::map::const_iterator it; + for(it = caches.begin(); it != caches.end(); it++) + { + if ((it->second).source->findCache(hash, data)) + { + return true; + } + } + return false; +} + +bool CacheStrapper::CacheExist(CacheData& data){ + + std::string filename = data.path + "/" + data.name; + FILE* file = NULL; + file = RsDirUtil::rs_fopen(filename.c_str(), "r"); + + if(file == NULL) + return false; + + fclose(file); + return true; +} + +/***************************************************************************/ +/****************************** CONFIGURATION HANDLING *********************/ +/***************************************************************************/ + +/**** OVERLOADED FROM p3Config ****/ + +RsSerialiser *CacheStrapper::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + + /* add in the types we need! */ + rss->addSerialType(new RsCacheConfigSerialiser()); + + return rss; +} + + +bool CacheStrapper::saveList(bool &cleanup, std::list& saveData) +{ + + /* it can delete them! */ + cleanup = true; + +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::saveList()" << std::endl; +#endif + + /* iterate through the Caches (local first) */ + + std::list::iterator cit; + std::list ownCaches; + std::list remoteCaches; + std::string ownId = mConnMgr->getOwnId(); + + std::map::iterator it; + for(it = caches.begin(); it != caches.end(); it++) + { + std::map::iterator tit; + std::map ownTmp; + (it->second).source -> cachesAvailable(ownId, ownTmp); + (it->second).store -> getAllStoredCaches(remoteCaches); + + for(tit = ownTmp.begin(); tit != ownTmp.end(); tit++) + { + if(CacheExist(tit->second)) + ownCaches.push_back(tit->second); + } + } + + for(cit = ownCaches.begin(); cit != ownCaches.end(); cit++) + { + RsCacheConfig *rscc = new RsCacheConfig(); + + // Fixup lazy behaviour in clients... + // This ensures correct loading later. + // (used to be: rscc->pid = cit->pid;) + rscc->pid = ownId; + + //rscc->pname = cit->pname; + rscc->cachetypeid = cit->cid.type; + rscc->cachesubid = cit->cid.subid; + rscc->path = cit->path; + rscc->name = cit->name; + rscc->hash = cit->hash; + rscc->size = cit->size; + rscc->recvd = cit->recvd; + + saveData.push_back(rscc); + } + + for(cit = remoteCaches.begin(); cit != remoteCaches.end(); cit++) + { + if (cit->pid == ownId) + { +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() discarding Own Remote Cache"; + std::cerr << std::endl; +#endif + continue; /* skip own caches -> will get transferred anyway */ + } + + RsCacheConfig *rscc = new RsCacheConfig(); + + rscc->pid = cit->pid; + //rscc->pname = cit->pname; + rscc->cachetypeid = cit->cid.type; + rscc->cachesubid = cit->cid.subid; + rscc->path = cit->path; + rscc->name = cit->name; + rscc->hash = cit->hash; + rscc->size = cit->size; + rscc->recvd = cit->recvd; + + saveData.push_back(rscc); + } + + /* list completed! */ + return true; +} + + +bool CacheStrapper::loadList(std::list& load) +{ + std::list::iterator it; + RsCacheConfig *rscc; + +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() Item Count: " << load.size(); + std::cerr << std::endl; +#endif + std::list ownCaches; + std::list remoteCaches; + std::string ownId = mConnMgr->getOwnId(); + + peerConnectState ownState; + mConnMgr->getOwnNetStatus(ownState); + std::string ownName = ownState.name+" ("+ownState.location+")"; + + std::map > saveFiles; + std::map >::iterator sit; + + for(it = load.begin(); it != load.end(); it++) + { + /* switch on type */ + if (NULL != (rscc = dynamic_cast(*it))) + { +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() Item: "; + std::cerr << std::endl; + rscc->print(std::cerr, 10); + std::cerr << std::endl; +#endif + CacheData cd; + + cd.pid = rscc->pid; + + if(cd.pid == ownId) + { + cd.pname = ownName; + } + else + { + peerConnectState pca; + mConnMgr->getFriendNetStatus(rscc->pid, pca); + cd.pname = pca.name+" ("+pca.location+")"; + } + + cd.cid.type = rscc->cachetypeid; + cd.cid.subid = rscc->cachesubid; + cd.path = RsDirUtil::convertPathToUnix(rscc->path); + cd.name = rscc->name; + cd.hash = rscc->hash; + cd.size = rscc->size; + cd.recvd = rscc->recvd; + + /* store files that we want to keep */ + (saveFiles[cd.path]).push_back(cd.name); + + std::map::iterator it2; + if (caches.end() == (it2 = caches.find(cd.cid.type))) + { + /* error - don't have this type of cache */ +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() Can't Find Cache discarding"; + std::cerr << std::endl; +#endif + } + else + { + /* check that the file exists first.... */ + std::string filename = cd.path; + filename += "/"; + filename += cd.name; +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() Checking File: " << filename; + std::cerr << std::endl; +#endif + + bool fileExists = RsDirUtil::checkFile(filename); + if (fileExists) + { +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() Exists ... continuing"; + std::cerr << std::endl; +#endif + if (cd.pid == ownId) + { + + /* load local */ + (it2 -> second).source -> loadLocalCache(cd); +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() loaded Local"; + std::cerr << std::endl; +#endif + } + else + { + /* load remote */ + (it2 -> second).store -> loadCache(cd); +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() loaded Remote"; + std::cerr << std::endl; +#endif + } + } + else + { + std::cerr << "CacheStrapper::loadList() Doesn't Exist dropping: " << filename; + std::cerr << std::endl; + } + + } + + /* cleanup */ + delete (*it); + + } + else + { + /* cleanup */ + delete (*it); + } + } + + /* assemble a list of dirs to clean (union of cache dirs) */ + std::list cacheDirs; + std::list::iterator dit; +#ifdef CS_DEBUG + std::list::iterator fit; +#endif + std::map::iterator cit; + for(cit = caches.begin(); cit != caches.end(); cit++) + { + std::string lcdir = (cit->second).source->getCacheDir(); + std::string rcdir = (cit->second).store->getCacheDir(); + + if (cacheDirs.end() == std::find(cacheDirs.begin(), cacheDirs.end(), lcdir)) + { + cacheDirs.push_back(lcdir); + } + + if (cacheDirs.end() == std::find(cacheDirs.begin(), cacheDirs.end(), rcdir)) + { + cacheDirs.push_back(rcdir); + } + } + +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() Files To Save:" << std::endl; +#endif + +#ifdef CS_DEBUG + for(sit = saveFiles.begin(); sit != saveFiles.end(); sit++) + { + std::cerr << "CacheStrapper::loadList() Files To Save in dir: <" << sit->first << ">" << std::endl; + for(fit = (sit->second).begin(); fit != (sit->second).end(); fit++) + { + std::cerr << "\tFile: " << *fit << std::endl; + } + } +#endif + + std::list emptyList; + for(dit = cacheDirs.begin(); dit != cacheDirs.end(); dit++) + { +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() Cleaning cache dir: <" << *dit << ">" << std::endl; +#endif + sit = saveFiles.find(*dit); + if (sit != saveFiles.end()) + { +#ifdef CS_DEBUG + for(fit = (sit->second).begin(); fit != (sit->second).end(); fit++) + { + std::cerr << "CacheStrapper::loadList() Keeping File: " << *fit << std::endl; + } +#endif + RsDirUtil::cleanupDirectory(*dit, sit->second); + } + else + { +#ifdef CS_DEBUG + std::cerr << "CacheStrapper::loadList() No Files to save here!" << std::endl; +#endif + RsDirUtil::cleanupDirectory(*dit, emptyList); + } + } + + return true; + +} + + +/********************************* CacheStrapper ********************************* + * This is the bit which handles queries + * + ********************************* CacheStrapper ********************************/ + + +/* request from CacheStore */ +bool CacheTransfer::RequestCache(CacheData &data, CacheStore *cbStore) +{ + /* check for a previous request -> and cancel + * + * - if duplicate pid, cid -> cancel old transfer + * - if duplicate hash -> Fail Transfer + */ + + std::map::iterator dit; + std::map::iterator sit; + + for(dit = cbData.begin(); dit != cbData.end(); dit++) + { + if (((dit->second).pid == data.pid) && + ((dit->second).cid.type == data.cid.type) && + ((dit->second).cid.subid == data.cid.subid)) + { + /* cancel old transfer */ + CancelCacheFile(dit->second.pid, dit->second.path, + dit->second.hash, dit->second.size); + + sit = cbStores.find(dit->second.hash); + cbData.erase(dit); + cbStores.erase(sit); + + break; + } + } + + /* find in store.... */ + sit = cbStores.find(data.hash); + if (sit != cbStores.end()) + { + /* Duplicate Current Request */ + cbStore -> failedCache(data); + return false; + } + + + /* store request */ + cbData[data.hash] = data; + cbStores[data.hash] = cbStore; + + /* request data */ + RequestCacheFile(data.pid, data.path, data.hash, data.size); + + /* wait for answer */ + return true; +} + + +/* to be overloaded */ +bool CacheTransfer::RequestCacheFile(RsPeerId id, std::string path, std::string hash, uint64_t size) +{ + (void) id; + (void) path; + (void) size; +#ifdef CS_DEBUG + std::cerr << "CacheTransfer::RequestCacheFile() : from:" << id << " #"; + std::cerr << hash << " size: " << size; + std::cerr << " savepath: " << path << std::endl; + std::cerr << "CacheTransfer::RequestCacheFile() Dummy... saying completed"; + std::cerr << std::endl; +#endif + + /* just tell them we've completed! */ + CompletedCache(hash); + return true; +} + +/* to be overloaded */ +bool CacheTransfer::CancelCacheFile(RsPeerId id, std::string path, std::string hash, uint64_t size) +{ + (void) id; + (void) path; + (void) hash; + (void) size; +#ifdef CS_DEBUG + std::cerr << "CacheTransfer::CancelCacheFile() : from:" << id << " #"; + std::cerr << hash << " size: " << size; + std::cerr << " savepath: " << path << std::endl; + std::cerr << "CacheTransfer::CancelCacheFile() Dummy fn"; + std::cerr << std::endl; +#endif + + return true; +} + + +/* internal completion -> does cb */ +bool CacheTransfer::CompletedCache(std::string hash) +{ + std::map::iterator dit; + std::map::iterator sit; + +#ifdef CS_DEBUG + std::cerr << "CacheTransfer::CompletedCache(" << hash << ")"; + std::cerr << std::endl; +#endif + + /* find in store.... */ + sit = cbStores.find(hash); + dit = cbData.find(hash); + + if ((sit == cbStores.end()) || (dit == cbData.end())) + { +#ifdef CS_DEBUG + std::cerr << "CacheTransfer::CompletedCache() Failed to find it"; + std::cerr << std::endl; +#endif + + return false; + } + +#ifdef CS_DEBUG + std::cerr << "CacheTransfer::CompletedCache() callback to store"; + std::cerr << std::endl; +#endif + /* callback */ + (sit -> second) -> downloadedCache(dit->second); + + /* clean up store */ + cbStores.erase(sit); + cbData.erase(dit); + + return true; +} + +/* internal completion -> does cb */ +bool CacheTransfer::FailedCache(std::string hash) +{ + std::map::iterator dit; + std::map::iterator sit; + + /* find in store.... */ + sit = cbStores.find(hash); + dit = cbData.find(hash); + + if ((sit == cbStores.end()) || (dit == cbData.end())) + { + return false; + } + + /* callback */ + (sit -> second) -> failedCache(dit->second); + + /* clean up store */ + cbStores.erase(sit); + cbData.erase(dit); + + return true; +} + + +bool CacheTransfer::FindCacheFile(std::string hash, std::string &path, uint64_t &size) +{ + CacheData data; + if (strapper->findCache(hash, data)) + { + path = data.path + "/" + data.name; + size = data.size; + return true; + } + + return false; +} + + + diff --git a/libretroshare/src/dbase/cachestrapper.h b/libretroshare/src/dbase/cachestrapper.h new file mode 100644 index 000000000..c11107ec1 --- /dev/null +++ b/libretroshare/src/dbase/cachestrapper.h @@ -0,0 +1,502 @@ +/* + * RetroShare FileCache Module: cachestrapper.h + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_CACHE_STRAPPER_H +#define MRK_CACHE_STRAPPER_H + +#include "pqi/p3cfgmgr.h" +#include "pqi/pqimonitor.h" +#include "util/rsthreads.h" +#include "util/pugixml.h" + +#include +#include +#include +#include + +/******************* CacheStrapper and Related Classes ******************* + * A generic Cache Update system. + * + * CacheStrapper: maintains a set of CacheSources, and CacheStores, + * queries and updates as new information arrives. + * + * CacheTransfer: Interface for FileTransfer Class to support. + * + * CacheSource: Base Class for cache data provider. eg. FileIndexMonitor. + * CacheStore: Base Class for data cache. eg. FileCache/Store. + * + * Still TODO: + * (1) Design and Implement the Upload side of CacheTransfer/CacheStrapper. + * (2) CacheStrapper:: Save / Load Cache lists.... + * (3) Clean up lists, maps on shutdown etc. + * (4) Consider Mutexes for multithreaded operations. + * (5) Test the MultiSource/Store capabilities. + * + ******************* CacheStrapper and Related Classes *******************/ + + +class CacheTransfer; /* Interface for File Transfer */ +class CacheSource; /* Interface for local File Index/Monitor */ +class CacheStore; /* Interface for the actual Cache */ +class CacheStrapper; /* Controlling Class */ + +/**** +typedef uint32_t RsPeerId; +*****/ +typedef std::string RsPeerId; + +/******************************** CacheId ********************************/ + +/*! + * Use this to identify the type of cache source, strapper, + */ +class CacheId +{ + public: + CacheId() :type(0), subid(0) { return; } + CacheId(uint16_t a, uint16_t b) :type(a), subid(b) { return; } + uint16_t type; /// cache types, this should be set to services type + uint16_t subid; /// should be initialised when using multicache feature of cachestrapper +}; + + +bool operator<(const CacheId &a, const CacheId &b); + +/*! + * Use for identifying physical files that have been chosen as cache data + * note: this does not actual store the data but serves to locate on network (via hash attribute, + * and on file via path) + */ +class CacheData +{ + public: + + RsPeerId pid; /// peer id + std::string pname; /// peer name (can be used by cachestore) + CacheId cid; /// cache id + std::string path; /// file system path where physical cache data is located + std::string name; + std::string hash; + uint64_t size; + time_t recvd; /// received timestamp +}; + + +std::ostream &operator<<(std::ostream &out, const CacheData &d); + +/***************************** CacheTransfer *****************************/ + +/** + * Interface for FileTransfer Class to support cache + */ +class CacheTransfer +{ + public: + + CacheTransfer(CacheStrapper *cs) :strapper(cs) { return; } + virtual ~CacheTransfer() {} + + /*! + * upload side of things .... searches through CacheStrapper. + */ + bool FindCacheFile(std::string hash, std::string &path, uint64_t &size); + + /*! + * At the download side RequestCache() => overloaded RequestCacheFile() + * the class should then call CompletedCache() or FailedCache() + */ + bool RequestCache(CacheData &data, CacheStore *cbStore); /* request from CacheStore */ + + protected: + + /*! + * to be overloaded + */ + virtual bool RequestCacheFile(RsPeerId id, std::string path, std::string hash, uint64_t size); + virtual bool CancelCacheFile(RsPeerId id, std::string path, std::string hash, uint64_t size); + + bool CompletedCache(std::string hash); /* internal completion -> does cb */ + bool FailedCache(std::string hash); /* internal completion -> does cb */ + + private: + + CacheStrapper *strapper; + + std::map cbData; + std::map cbStores; +}; + + + +/************************ CacheSource/CacheStore *************************/ + +typedef std::map CacheSet; + +/*! + * Implements features needed for a service to act as a cachesource and allow pushing a of cache data from service to strapper + * Service is able to use this class for refresh its cache (push cache data) + * and interface to load and check cache availablility among peers (source of cache data) + * Architecturally Cachestrapper maintains the cachesource (which is passed as a pointer handle) while the cachesource-inheriting + * service can update cachesource as to new cache sources (cache data) created. Equivalently it enquiries through cache source for + * new cache data from peers + * @see p3Distrib + */ +class CacheSource +{ + public: + + CacheSource(uint16_t t, bool m, CacheStrapper *cs, std::string cachedir); + virtual ~CacheSource() {} + + /*! + * called to determine available cache for peer - + * default acceptable (returns all) + */ + virtual bool cachesAvailable(RsPeerId pid, std::map &ids); + + /*! + * function called at startup to load from + * configuration file.... + * to be overloaded by inherited class + */ + virtual bool loadLocalCache(const CacheData &data); + + /* control Caches available */ + bool refreshCache(const CacheData &data); + bool clearCache(CacheId id); + + /* get private data */ + std::string getCacheDir() { return cacheDir; } + bool isMultiCache() { return multiCache; } + uint16_t getCacheType() { return cacheType; } + + /* display */ + void listCaches(std::ostream &out); + + /* search */ + bool findCache(std::string hash, CacheData &data) const; + + protected: + + uint16_t cacheType; /// for checking of cache type (usually of child class of source) + bool multiCache; /// whether multisource is in use or not. + CacheStrapper *mStrapper; + + /*** MUTEX LOCKING */ + void lockData() const; + void unlockData() const; + + CacheSet caches; /// all local cache data stored here + std::map mOldCaches; /// replaced/cleared caches are pushed here (in case requested) + + private: + + std::string cacheDir; + mutable RsMutex cMutex; + +}; + + +/*! + * Base Class for data cache. eg. FileCache/Store. + * This is best used to deal with external caches from other peers + * @see p3Distrib. pqiMonitor + */ +class CacheStore +{ + public: + + /*! + * + * @param t set to particular rs_service id. see rsserviceids.h + * @param m whether this is multicache service (true) or not(false) + * @param cs cache strapper instance responsible for maintaining the cache service + * @param cft cache transfer instance responsible for rquestiing and tranfering caches + * @param cachedir directory used to store cache related info for cachestore client + * @return + */ + CacheStore(uint16_t t, bool m, CacheStrapper *cs, CacheTransfer *cft, std::string cachedir); + virtual ~CacheStore() {} + + /* current stored data */ + + /*! + * + * @param data returns cache data for pid/cid set in data itself + * @return false is unsuccessful and vice versa + */ + bool getStoredCache(CacheData &data); /* use pid/cid in data */ + + /*! + * + * @param data all cache store by cachestore is store here + * @return false not returned, only true at the moment + */ + bool getAllStoredCaches(std::list &data); /* use pid/cid in data */ + + /*! + * input from CacheStrapper -> store can then download new data + */ + void availableCache(const CacheData &data); + + /*! + * should be called when the download is completed ... cache data is loaded + */ + void downloadedCache(const CacheData &data); + + /*! + * called if the download fails, TODO: nothing done yet + */ + void failedCache(const CacheData &data); + + /* virtual functions overloaded by cache implementor */ + + /*! + * @param data cache data is stored here + * @return false is failed (cache does not exist), otherwise true + */ + virtual bool fetchCache(const CacheData &data); /* a question? */ + virtual int nameCache(CacheData &data); /* fill in the name/path */ + virtual int loadCache(const CacheData &data); /* actual load, once data available */ + + /* get private data */ + + std::string getCacheDir() { return cacheDir; } + bool isMultiCache() { return multiCache; } + uint16_t getCacheType() { return cacheType; } + + /*! + * display, e.g. can pass std::out, cerr, ofstream, etc + */ + void listCaches(std::ostream &out); + + protected: + + /*! + * ** MUTEX LOCKING + */ + void lockData() const; + + /*! + * ** MUTEX LOCKING + */ + void unlockData() const; + + /*! This function is called to store Cache Entry in the CacheStore Table. + * it must be called from within a Mutex Lock.... + * + * It doesn't lock itself -> to avoid race conditions + */ + void locked_storeCacheEntry(const CacheData &data); + + /*! This function is called to store Cache Entry in the CacheStore Table. + * it must be called from within a Mutex Lock.... + * + * It doesn't lock itself -> to avoid race conditions + */ + bool locked_getStoredCache(CacheData &data); + + + //////////////// Cache Optimisation ////////////////// + + /** + *@param id the key for determing whether this data has been cached or not + *@return true if data referenced by key has been cached false otherwise + */ + bool cached(const std::string cacheId); + + /** + * TODO: will be abstract + * The deriving class should return a document which accurately reflects its data + * structure + * @param cacheDoc document reflecting derving class's cache data structure + */ + virtual void updateCacheDocument(pugi::xml_document& cacheDoc); + + + + + //////////////// Cache Optimisation ////////////////// + private: + /** + * This updates the cache table with information from the xml document + * + */ + void updateCacheTable(); + + uint16_t cacheType; /* for checking */ + bool multiCache; /* do we care about subid's */ + + CacheStrapper *mStrapper; + CacheTransfer *cacheTransfer; + + std::string cacheDir; + + mutable RsMutex cMutex; + std::map caches; + + ////////////// cache optimisation //////////////// + + /// whether to run in cache optimisation mode + bool cacheOptMode; + + /// stores whether given instance of cache data has been loaded already or not + std::map cacheTable; + +}; + + + +/***************************** CacheStrapper *****************************/ + + +/*! + * a convenient to pass cache handles to cachestrapper to maintain the cache service + * Make Sure you get the Ids right! see rsservicesids.h. + * When creating a cache service this data structure is + * source, usually the child class of store and source also serves as both handles + * @see CacheStrapper + */ +class CachePair +{ + public: + + /*! + * Default constructor, all variables set to NULL + */ + CachePair() + :source(NULL), store(NULL), id(0, 0) { return; } + + /*! + * + * @param a cache source for service + * @param b cache store for service + * @param c the cache service id, c.type should be set to service id service-child class of store and source + */ + CachePair(CacheSource *a, CacheStore *b, CacheId c) + :source(a), store(b), id(c) { return; } + + CacheSource *source; + CacheStore *store; + CacheId id; /// should be set id type to service types of store and source service-child class, and subid for multicache use +}; + + +bool operator<(const CachePair &a, const CachePair &b); + +/*! + * CacheStrapper: maintains a set of CacheSources, and CacheStores, + * queries and updates as new information arrives. + */ +class CacheStrapper: public pqiMonitor, public p3Config +{ + public: + + /*! + * @param cm handle used by strapper for getting peer connection information (online peers, sslids...) + * @return + */ + CacheStrapper(p3ConnectMgr *cm); +virtual ~CacheStrapper() { return; } + + /************* from pqiMonitor *******************/ +virtual void statusChange(const std::list &plist); + /************* from pqiMonitor *******************/ + + /* Feedback from CacheSources */ + +/*! + * send data to peers online and selfe + * @param data + * + */ +void refreshCache(const CacheData &data); + +/*! + * forces config savelist + * @param data + * @see saveList() + */ +void refreshCacheStore(const CacheData &data); + +/*! + * list of Caches to send out + */ +bool getCacheUpdates(std::list > &updates); + +/*! + * add to strapper's cachepair set so a related service's store and source can be maintained + * @param pair the source and store handle for a service + */ +void addCachePair(CachePair pair); + + /*** I/O (2) ***/ +void recvCacheResponse(CacheData &data, time_t ts); +void handleCacheQuery(RsPeerId id, std::map &data); + + +/*! + * search through CacheSources. + * @return false if cachedate mapping to hash not found + */ +bool findCache(std::string hash, CacheData &data) const; + + /* display */ +void listCaches(std::ostream &out); + +/*! + * does not do anything + * @param out + * @deprecated + */ +void listPeerStatus(std::ostream &out); + +/** + * Checks if the cache physically exist at path given + * @param data + * @return whether it exists or not + */ +bool CacheExist(CacheData& data); + + /* Config */ + protected: + + /* Key Functions to be overloaded for Full Configuration */ +virtual RsSerialiser *setupSerialiser(); +virtual bool saveList(bool &cleanup, std::list&); +virtual bool loadList(std::list& load); + + private: + + /* these are static - so shouldn't need mutex */ + p3ConnectMgr *mConnMgr; + + std::map caches; + + RsMutex csMtx; /* protect below */ + + std::list > mCacheUpdates; +}; + + +#endif diff --git a/libretroshare/src/dbase/cachetest.h b/libretroshare/src/dbase/cachetest.h new file mode 100644 index 000000000..59d55b5be --- /dev/null +++ b/libretroshare/src/dbase/cachetest.h @@ -0,0 +1,63 @@ +/* + * RetroShare FileCache Module: cachetest.h + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_TEST_CACHE_H +#define MRK_TEST_CACHE_H + +#include "cachestrapper.h" + +#define TESTID 0xffff +#define TESTID2 0xffee + +class CacheTestSource: public CacheSource +{ + public: + CacheTestSource(CacheStrapper *cs, std::string dir) + :CacheSource(cs, TESTID, false, dir) { return; } +}; + +class CacheTestStore: public CacheStore +{ + public: + CacheTestStore(CacheTransfer *cft, std::string dir) + :CacheStore(TESTID, false, cft, dir) { return; } +}; + + +class CacheTestMultiSource: public CacheSource +{ + public: + CacheTestMultiSource(CacheStrapper *cs, std::string dir) + :CacheSource(cs, TESTID2, true, dir) { return; } +}; + +class CacheTestMultiStore: public CacheStore +{ + public: + CacheTestMultiStore(CacheTransfer *cft, std::string dir) + :CacheStore(TESTID2, true, cft, dir) { return; } +}; + + +#endif + diff --git a/libretroshare/src/dbase/fimonitor.cc b/libretroshare/src/dbase/fimonitor.cc new file mode 100644 index 000000000..a186020f5 --- /dev/null +++ b/libretroshare/src/dbase/fimonitor.cc @@ -0,0 +1,1358 @@ +/* + * RetroShare FileCache Module: fimonitor.cc + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#endif + +#include "dbase/fimonitor.h" +#include "util/rsdir.h" +#include "serialiser/rsserviceids.h" +#include "retroshare/rsiface.h" +#include "retroshare/rsnotify.h" +#include "util/folderiterator.h" +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//*********** +//#define FIM_DEBUG 1 +// ***********/ + +FileIndexMonitor::FileIndexMonitor(CacheStrapper *cs, NotifyBase *cb_in,std::string cachedir, std::string pid,const std::string& config_dir) + :CacheSource(RS_SERVICE_TYPE_FILE_INDEX, false, cs, cachedir), fi(pid), + pendingDirs(false), pendingForceCacheWrite(false), + mForceCheck(false), mInCheck(false),cb(cb_in), hashCache(config_dir+"/" + "file_cache.lst"),useHashCache(true) + +{ + updatePeriod = 60; +} + +bool FileIndexMonitor::autoCheckEnabled() const +{ + RsStackMutex mtx(fiMutex) ; /* LOCKED DIRS */ + return updatePeriod > 0 ; +} + +bool FileIndexMonitor::rememberHashFiles() +{ + RsStackMutex mtx(fiMutex) ; /* LOCKED DIRS */ + return useHashCache ; +} +void FileIndexMonitor::setRememberHashFiles(bool b) +{ + RsStackMutex mtx(fiMutex) ; /* LOCKED DIRS */ +#ifdef FIM_DEBUG + std::cerr << "Setting useHashCache to " << b << std::endl; +#endif + useHashCache = b ; +} +void FileIndexMonitor::setRememberHashFilesDuration(uint32_t days) +{ + RsStackMutex mtx(fiMutex) ; /* LOCKED DIRS */ + +#ifdef FIM_DEBUG + std::cerr << "Setting HashCache duration to " << days << std::endl; +#endif + hashCache.setRememberHashFilesDuration(days) ; + hashCache.clean() ; +} + +uint32_t FileIndexMonitor::rememberHashFilesDuration() const +{ + RsStackMutex mtx(fiMutex) ; /* LOCKED DIRS */ + + return hashCache.rememberHashFilesDuration() ; +} + +// Remove any memory of formerly hashed files that are not shared anymore +void FileIndexMonitor::clearHashFiles() +{ + RsStackMutex mtx(fiMutex) ; /* LOCKED DIRS */ + + hashCache.clear() ; + hashCache.save() ; +} + +HashCache::HashCache(const std::string& path) + : _path(path) +{ + _max_cache_duration_days = 10 ; // 10 days is the default value. + _files.clear() ; + _changed = false ; + std::ifstream f(_path.c_str()) ; + + std::streamsize max_line_size = 2000 ; // should be enough. Anyway, if we + // miss one entry, we just lose some + // cache itemsn but this is not too + // much of a problem. + char *buff = new char[max_line_size] ; + +#ifdef FIM_DEBUG + std::cerr << "Loading HashCache from file " << path << std::endl ; + int n=0 ; +#endif + + while(!f.eof()) + { + HashCacheInfo info ; + + f.getline(buff,max_line_size,'\n') ; + std::string name(buff) ; + + f.getline(buff,max_line_size,'\n') ; if(sscanf(buff,"%lld",&info.size) != 1) break ; + f.getline(buff,max_line_size,'\n') ; if(sscanf(buff,"%ld",&info.time_stamp) != 1) break ; + f.getline(buff,max_line_size,'\n') ; if(sscanf(buff,"%ld",&info.modf_stamp) != 1) break ; + f.getline(buff,max_line_size,'\n') ; info.hash = std::string(buff) ; + +#ifdef FIM_DEBUG + std::cerr << " (" << name << ", " << info.size << ", " << info.time_stamp << ", " << info.modf_stamp << ", " << info.hash << std::endl ; + ++n ; +#endif + _files[name] = info ; + } + f.close() ; + + delete[] buff ; +#ifdef FIM_DEBUG + std::cerr << n << " entries loaded." << std::endl ; +#endif +} + +void HashCache::save() +{ + if(_changed) + { +#ifdef FIM_DEBUG + std::cerr << "Saving Hash Cache to file " << _path << "..." << std::endl ; +#endif + std::ofstream f( (_path+".tmp").c_str() ) ; + + for(std::map::const_iterator it(_files.begin());it!=_files.end();++it) + { + f << it->first << std::endl ; + f << it->second.size << std::endl; + f << it->second.time_stamp << std::endl; + f << it->second.modf_stamp << std::endl; + f << it->second.hash << std::endl; + } + f.close() ; + + RsDirUtil::renameFile(_path+".tmp",_path) ; +#ifdef FIM_DEBUG + std::cerr << "done." << std::endl ; +#endif + + _changed = false ; + } +#ifdef FIM_DEBUG + else + std::cerr << "Hash cache not changed. Not saving." << std::endl ; +#endif +} + +bool HashCache::find(const std::string& full_path,uint64_t size,time_t time_stamp,std::string& hash) +{ +#ifdef FIM_DEBUG + std::cerr << "HashCache: looking for " << full_path << std::endl ; +#endif + time_t now = time(NULL) ; + std::map::iterator it(_files.find(full_path)) ; + + if(it != _files.end() && time_stamp == it->second.modf_stamp && size == it->second.size) + { + hash = it->second.hash ; + it->second.time_stamp = now ; +#ifdef FIM_DEBUG + std::cerr << "Found in cache." << std::endl ; +#endif + return true ; + } + else + { +#ifdef FIM_DEBUG + std::cerr << "not found in cache." << std::endl ; +#endif + return false ; + } +} +void HashCache::insert(const std::string& full_path,uint64_t size,time_t time_stamp,const std::string& hash) +{ + HashCacheInfo info ; + info.size = size ; + info.modf_stamp = time_stamp ; + info.time_stamp = time(NULL) ; + info.hash = hash ; + + _files[full_path] = info ; + _changed = true ; + +#ifdef FIM_DEBUG + std::cerr << "Entry inserted in cache: " << full_path << ", " << size << ", " << time_stamp << std::endl ; +#endif +} +void HashCache::clean() +{ +#ifdef FIM_DEBUG + std::cerr << "Cleaning HashCache..." << std::endl ; +#endif + time_t now = time(NULL) ; + time_t duration = _max_cache_duration_days * 24 * 3600 ; // seconds + +#ifdef FIM_DEBUG + std::cerr << "cleaning hash cache." << std::endl ; +#endif + + for(std::map::iterator it(_files.begin());it!=_files.end();) + if(it->second.time_stamp + duration < now) + { +#ifdef FIM_DEBUG + std::cerr << " Entry too old: " << it->first << ", ts=" << it->second.time_stamp << std::endl ; +#endif + std::map::iterator tmp(it) ; + ++tmp ; + _files.erase(it) ; + it=tmp ; + } + else + ++it ; + +#ifdef FIM_DEBUG + std::cerr << "Done." << std::endl; +#endif +} + +FileIndexMonitor::~FileIndexMonitor() +{ + /* Data cleanup - TODO */ +} + +int FileIndexMonitor::SearchKeywords(std::list keywords, std::list &results,uint32_t flags) +{ + results.clear(); + std::list firesults; + + { + RsStackMutex stackM(fiMutex) ;/* LOCKED DIRS */ + fi.searchTerms(keywords, firesults); + } + + return filterResults(firesults,results,flags) ; +} + +int FileIndexMonitor::SearchBoolExp(Expression *exp, std::list& results,uint32_t flags) const +{ + results.clear(); + std::list firesults; + + { + RsStackMutex stackM(fiMutex) ;/* LOCKED DIRS */ + fi.searchBoolExp(exp, firesults); + } + + return filterResults(firesults,results,flags) ; +} + +int FileIndexMonitor::filterResults(std::list& firesults,std::list& results,uint32_t flags) const +{ + /* translate/filter results */ + + for(std::list::const_iterator rit(firesults.begin()); rit != firesults.end(); ++rit) + { + DirDetails cdetails ; + RequestDirDetails (*rit,cdetails,0); +#ifdef FIM_DEBUG + std::cerr << "Filtering candidate " << (*rit)->name << ", flags=" << cdetails.flags ; +#endif + + if (cdetails.type == DIR_TYPE_FILE && ( cdetails.flags & flags & (DIR_FLAGS_BROWSABLE | DIR_FLAGS_NETWORK_WIDE)) > 0) + { + cdetails.id = "Local"; + results.push_back(cdetails); +#ifdef FIM_DEBUG + std::cerr << ": kept" << std::endl ; +#endif + } +#ifdef FIM_DEBUG + else + std::cerr << ": discarded" << std::endl ; +#endif + } + return !results.empty() ; +} + +bool FileIndexMonitor::findLocalFile(std::string hash,uint32_t hint_flags, std::string &fullpath, uint64_t &size) const +{ + std::list results; + bool ok = false; + + { + RsStackMutex stackM(fiMutex) ;/* LOCKED DIRS */ + +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::findLocalFile() Hash: " << hash << std::endl; +#endif + /* search through the fileIndex */ + fi.searchHash(hash, results); + + if (results.size() > 0) + { + /* find the full path for the first entry */ + FileEntry *fe = results.front(); + DirEntry *de = fe->parent; /* all files must have a valid parent! */ + + uint32_t share_flags = locked_findShareFlags(fe) ; +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::findLocalFile: Filtering candidate " << fe->name << ", flags=" << share_flags << ", hint_flags=" << hint_flags << std::endl ; +#endif + + if((share_flags & hint_flags & (RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE)) > 0) + { +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::findLocalFile() Found Name: " << fe->name << std::endl; +#endif + std::string shpath = RsDirUtil::removeRootDir(de->path); + std::string basedir = RsDirUtil::getRootDir(de->path); + std::string realroot = locked_findRealRoot(basedir); + + /* construct full name */ + if (realroot.length() > 0) + { + fullpath = realroot + "/"; + if (shpath != "") + { + fullpath += shpath + "/"; + } + fullpath += fe->name; + + size = fe->size; + ok = true; + } +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::findLocalFile() Found Path: " << fullpath << std::endl; + std::cerr << "FileIndexMonitor::findLocalFile() Found Size: " << size << std::endl; +#endif + } +#ifdef FIM_DEBUG + else + std::cerr << "FileIndexMonitor::findLocalFile() discarded" << std::endl ; +#endif + } + } /* UNLOCKED DIRS */ + + return ok; +} + +bool FileIndexMonitor::convertSharedFilePath(std::string path, std::string &fullpath) +{ + bool ok = false; + + { + RsStackMutex stackM(fiMutex) ;/* LOCKED DIRS */ + +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::convertSharedFilePath() path: " << path << std::endl; +#endif + + std::string shpath = RsDirUtil::removeRootDir(path); + std::string basedir = RsDirUtil::getRootDir(path); + std::string realroot = locked_findRealRoot(basedir); + + /* construct full name */ + if (realroot.length() > 0) + { + fullpath = realroot + "/"; + fullpath += shpath; +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::convertSharedFilePath() Found Path: " << fullpath << std::endl; +#endif + ok = true; + } + + } /* UNLOCKED DIRS */ + + return ok; +} + + +bool FileIndexMonitor::loadLocalCache(const CacheData &data) /* called with stored data */ +{ + bool ok = false; + + { + RsStackMutex mtx(fiMutex) ; /* LOCKED DIRS */ + + /* More error checking needed here! */ + + std::string name = data.name ; // this trick allows to load the complete file. Not the one being shared. + name[name.length()-1] = 'c' ; + + if ((ok = fi.loadIndex(data.path + '/' + name, "", data.size))) + { +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::loadCache() Success!"; + std::cerr << std::endl; +#endif + fi.root->row = 0; + fi.root->name = data.pname ; + } + else + { +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::loadCache() Failed!"; + std::cerr << std::endl; +#endif + } + + fi.updateMaxModTime() ; + } + + if (ok) + { + return updateCache(data); + } + return false; +} + +bool FileIndexMonitor::updateCache(const CacheData &data) /* we call this one */ +{ + return refreshCache(data); +} + + +int FileIndexMonitor::getPeriod() const +{ +//#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::setPeriod() getting watch period" << std::endl; +//#endif + RsStackMutex mtx(fiMutex) ; /* LOCKED DIRS */ + return updatePeriod ; +} + +void FileIndexMonitor::setPeriod(int period) +{ + RsStackMutex mtx(fiMutex) ; /* LOCKED DIRS */ + updatePeriod = period; +//#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::setPeriod() Setting watch period to " << updatePeriod << std::endl; +//#endif +} + +void FileIndexMonitor::run() +{ + if(autoCheckEnabled()) + updateCycle(); + + while(isRunning()) + { + int i=0 ; + for(;;i++) + { + if(!isRunning()) + return; + + /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + sleep(1); +#else + Sleep(1000); +#endif + /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + /* check dirs if they've changed */ + if (internal_setSharedDirectories()) + break; + + { + RsStackMutex mtx(fiMutex) ; + + if(i >= abs(updatePeriod)) + break ; + } + } + + if(i < abs(updatePeriod) || autoCheckEnabled()) + updateCycle(); + +#ifdef FIM_DEBUG + { + RsStackMutex mtx(fiMutex) ; + std::cerr <<"*********** FileIndex **************" << std::endl ; + fi.printFileIndex(std::cerr) ; + std::cerr <<"************** END *****************" << std::endl ; + std::cerr << std::endl ; + } +#endif + } +} + +//void FileIndexMonitor::updateCycle(std::string& current_job) +void FileIndexMonitor::updateCycle() +{ + time_t startstamp = time(NULL); + + /* iterate through all out-of-date directories */ + bool moretodo = true; + bool fiMods = false; + + { + RsStackMutex stack(fiMutex); /**** LOCKED DIRS ****/ + mInCheck = true; + } + + cb->notifyHashingInfo(NOTIFY_HASHTYPE_EXAMINING_FILES, "") ; + + std::vector to_hash ; + + bool cache_is_new ; + { + RsStackMutex mtx(fiMutex) ; + cache_is_new = useHashCache && hashCache.empty() ; + } + + while(isRunning() && moretodo) + { + /* sleep a bit for each loop */ +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + usleep(100000); /* 1/10 sec */ +#else + Sleep(100); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + /* check if directories have been updated */ + if (internal_setSharedDirectories()) /* reset start time */ + startstamp = time(NULL); + + /* Handle a Single out-of-date directory */ + + time_t stamp = time(NULL); + + /* lock dirs from now on */ + RsStackMutex mtx(fiMutex) ; + + DirEntry *olddir = fi.findOldDirectory(startstamp); + + if (!olddir) + { + /* finished */ + moretodo = false; + continue; + } + +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::updateCycle()"; + std::cerr << " Checking: " << olddir->path << std::endl; +#endif + + FileEntry fe; + /* entries that need to be checked properly */ + std::list::iterator hit; + + /* determine the full root path */ + std::string dirpath = olddir->path; + std::string rootdir = RsDirUtil::getRootDir(olddir->path); + std::string remdir = RsDirUtil::removeRootDir(olddir->path); + std::string realroot = locked_findRealRoot(rootdir); + std::string realpath = realroot; + + if (remdir != "") + realpath += "/" + remdir; + +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::updateCycle()"; + std::cerr << " RealPath: " << realpath << std::endl; +#endif + + /* check for the dir existance */ + librs::util::FolderIterator dirIt(realpath); + if (!dirIt.isValid()) + { +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::updateCycle()"; + std::cerr << " Missing Dir: " << realpath << std::endl; + std::cerr << " Root Dir: " << rootdir << std::endl; + std::cerr << " remdir: " << remdir << std::endl; +#endif + if(directoryMap.end() != directoryMap.find(rootdir) && remdir=="") + { +#ifdef FIM_DEBUG + std::cerr << " This is a root directory. Keeping it empty." << std::endl; +#endif + } + else + { + if (!fi.removeOldDirectory(olddir->parent->path, olddir->name, stamp))/* bad directory - delete */ + { + /* bad... drop out of updateCycle() - hopefully the initial cleanup + * will deal with it next time! - otherwise we're in a continual loop + */ + std::cerr << "FileIndexMonitor::updateCycle()"; + std::cerr << "ERROR Failed to Remove: " << olddir->path << std::endl; + } + continue; + } + } + + /* update this dir - as its valid */ + fe.name = olddir->name; + fi.updateDirEntry(olddir->parent->path, fe, stamp); + + /* update the directories and files here */ + std::map::iterator dit; + std::map::iterator fit; + + /* flag existing subdirs as old */ + for(dit = olddir->subdirs.begin(); dit != olddir->subdirs.end(); dit++) + { + fe.name = (dit->second)->name; + /* set the age as out-of-date so that it gets checked */ + fi.updateDirEntry(olddir->path, fe, 0); + } + + /* now iterate through the directory... + * directories - flags as old, + * files checked to see if they have changed. (rehashed) + */ + + struct stat64 buf; + + to_hash.push_back(DirContentToHash()) ; + to_hash.back().realpath = realpath ; + to_hash.back().dirpath = dirpath ; + + while(isRunning() && dirIt.readdir()) + { + /* check entry type */ + std::string fname; + dirIt.d_name(fname); + std::string fullname = realpath + "/" + fname; +#ifdef FIM_DEBUG + std::cerr << "calling stats on " << fullname <path, fe, 0); + } + else if (S_ISREG(buf.st_mode)) + { + /* is file */ + bool toadd = false; +#ifdef FIM_DEBUG + std::cerr << "Is File: " << fullname << std::endl; +#endif + + fe.name = fname; + fe.size = buf.st_size; + fe.modtime = buf.st_mtime; + + /* check if it exists already */ + fit = olddir->files.find(fname); + if (fit == olddir->files.end()) + { + /* needs to be added */ +#ifdef FIM_DEBUG + std::cerr << "File Missing from List:" << fname << std::endl; +#endif + toadd = true; + } + else + { + /* check size / modtime are the same */ + if ((fe.size != (fit->second)->size) || (fe.modtime != (fit->second)->modtime)) + { +#ifdef FIM_DEBUG + std::cerr << "File ModTime/Size changed:" << fname << std::endl; + std::cerr << "fe.modtime = " << fe.modtime << std::endl; + std::cerr << "fit.mdtime = " << fit->second->modtime << std::endl; +#endif + toadd = true; + } + else + fe.hash = (fit->second)->hash; /* keep old info */ + } + if (toadd) + { + /* push onto Hash List */ +#ifdef FIM_DEBUG + std::cerr << "Adding to Update List: "; + std::cerr << olddir->path; + std::cerr << fname << std::endl; +#endif + to_hash.back().fentries.push_back(fe); + fiMods = true ; + } + else /* update with new time */ + { +#ifdef FIM_DEBUG + std::cerr << "File Hasn't Changed:" << fname << std::endl; +#endif + fi.updateFileEntry(olddir->path, fe, stamp); + + if(cache_is_new) + hashCache.insert(realpath+"/"+fe.name,fe.size,fe.modtime,fe.hash) ; + } + } + } +#ifdef FIM_DEBUG + else + std::cout << "stat error " << errno << std::endl ; +#endif + } + + if(to_hash.back().fentries.empty()) + to_hash.pop_back() ; + + /* now we unlock the lock, and iterate through the + * next files - hashing them, before adding into the system. + */ + /* for safety - blank out data we cannot use (TODO) */ + olddir = NULL; + + /* close directory */ + dirIt.closedir(); + } + + // Now, hash all files at once. + // + if(isRunning() && !to_hash.empty()) + hashFiles(to_hash) ; + + cb->notifyHashingInfo(NOTIFY_HASHTYPE_FINISH, "") ; + + { /* LOCKED DIRS */ + RsStackMutex stack(fiMutex); /**** LOCKED DIRS ****/ + + /* finished update cycle - cleanup extra dirs/files that + * have not had their timestamps updated. + */ + + fi.cleanOldEntries(startstamp) ; + +#ifdef FIM_DEBUG + /* print out the new directory structure */ + fi.printFileIndex(std::cerr); +#endif + /* now if we have changed things -> restore file/hash it/and + * tell the CacheSource + */ + + if (pendingForceCacheWrite) + { + pendingForceCacheWrite = false; + fiMods = true; + } + + if (fiMods) + locked_saveFileIndexes() ; + + fi.updateMaxModTime() ; // Update modification times for proper display. + + mInCheck = false; + + if(useHashCache) + hashCache.save() ; + } +} + +static std::string friendlyUnit(uint64_t val) +{ + const std::string units[5] = {"B","KB","MB","GB","TB"}; + char buf[50] ; + + double fact = 1.0 ; + + for(unsigned int i=0; i<5; ++i) + if(double(val)/fact < 1024.0) + { + sprintf(buf,"%2.2f",double(val)/fact) ; + return std::string(buf) + " " + units[i]; + } + else + fact *= 1024.0f ; + + sprintf(buf,"%2.2f",double(val)/fact*1024.0f) ; + return std::string(buf) + " TB"; +} + + +void FileIndexMonitor::hashFiles(const std::vector& to_hash) +{ + // Size interval at which we save the file lists + static const uint64_t MAX_SIZE_WITHOUT_SAVING = 10737418240ull ; // 10 GB + + cb->notifyListPreChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); + + time_t stamp = time(NULL); + + // compute total size of files to hash + uint64_t total_size = 0 ; + uint32_t n_files = 0 ; + + for(uint32_t i=0;inotifyHashingInfo(NOTIFY_HASHTYPE_HASH_FILE, tmpout.str()) ; + + std::string real_path = RsDirUtil::makePath(to_hash[i].realpath, fe.name); + + // 1st look into the hash cache if this file already exists. + // + if(useHashCache && hashCache.find(real_path,fe.size,fe.modtime,fe.hash)) + fi.updateFileEntry(to_hash[i].dirpath,fe,stamp); + else if(RsDirUtil::getFileHash(real_path, fe.hash,fe.size, this)) // not found, then hash it. + { + RsStackMutex stack(fiMutex); /**** LOCKED DIRS ****/ + + /* update fileIndex with new time */ + /* update with new time */ + + fi.updateFileEntry(to_hash[i].dirpath,fe,stamp); + + hashed_size += to_hash[i].fentries[j].size ; + + // Update the hash cache + if(useHashCache) + hashCache.insert(real_path,fe.size,fe.modtime,fe.hash) ; + } + else + std::cerr << "Failed to Hash File " << fe.name << std::endl; + + size += to_hash[i].fentries[j].size ; + + /* don't hit the disk too hard! */ +#ifndef WINDOWS_SYS + /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + usleep(40000); /* 40 msec */ +#else + + Sleep(40); +#endif + + // Save the hashing result every 60 seconds, so has to save what is already hashed. + std::cerr << "size - last_save_size = " << hashed_size - last_save_size << ", max=" << MAX_SIZE_WITHOUT_SAVING << std::endl ; + + if(hashed_size > last_save_size + MAX_SIZE_WITHOUT_SAVING) + { + cb->notifyHashingInfo(NOTIFY_HASHTYPE_SAVE_FILE_INDEX, "") ; +#ifdef WINDOWS_SYS + Sleep(1000) ; +#else + sleep(1) ; +#endif + RsStackMutex stack(fiMutex); /**** LOCKED DIRS ****/ + FileIndexMonitor::locked_saveFileIndexes() ; + last_save_size = hashed_size ; + + if(useHashCache) + hashCache.save() ; + } + + // check if thread is running + running = isRunning(); + } + + cb->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); +} + + +void FileIndexMonitor::locked_saveFileIndexes() +{ + /* store to the cacheDirectory */ + + std::string path = getCacheDir(); + + // Two files are saved: one with only browsable dirs, which will be shared by the cache system, + // and one with the complete file collection. + // + std::ostringstream out; + out << "fc-own-" << time(NULL) << ".rsfb"; + std::string tmpname_browsable = out.str(); + std::string fname_browsable = path + "/" + tmpname_browsable; + + std::ostringstream out2; + out2 << "fc-own-" << time(NULL) << ".rsfc"; + std::string tmpname_total = out2.str(); + std::string fname_total = path + "/" + tmpname_total; + +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::updateCycle() FileIndex modified ... updating"; + std::cerr << std::endl; + std::cerr << "FileIndexMonitor::updateCycle() saving browsable file list to: " << fname_browsable << std::endl ; + std::cerr << "FileIndexMonitor::updateCycle() saving total file list to to: " << fname_total << std::endl ; +#endif + + std::string calchash; + uint64_t size; + + std::cerr << "About to save, with the following restrictions:" << std::endl ; + std::set forbidden_dirs ; + for(std::map::const_iterator it(directoryMap.begin());it!=directoryMap.end();++it) + { + std::cerr << " dir=" << it->first << " : " ; + if((it->second.shareflags & RS_FILE_HINTS_BROWSABLE) == 0) + { + std::cerr << "forbidden" << std::endl; + forbidden_dirs.insert(it->first) ; + } + else + std::cerr << "autorized" << std::endl; + } + + uint64_t sizetmp ; + + fi.saveIndex(fname_total, calchash, sizetmp,std::set()); // save all files + fi.saveIndex(fname_browsable, calchash, size,forbidden_dirs); // save only browsable files + + if(size > 0) + { +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::updateCycle() saved with hash:" << calchash; + std::cerr << std::endl; +#endif + + /* should clean up the previous cache.... */ + + /* flag as new info */ + CacheData data; + data.pid = fi.root->id; + data.cid.type = getCacheType(); + data.cid.subid = 0; + data.path = path; + data.name = tmpname_browsable; + data.hash = calchash; + data.size = size; + data.recvd = time(NULL); + + updateCache(data); + } + +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::updateCycle() called updateCache()"; + std::cerr << std::endl; +#endif +} + +void FileIndexMonitor::updateShareFlags(const SharedDirInfo& dir) +{ + cb->notifyListPreChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); + + bool fimods = false ; +#ifdef FIM_DEBUG + std::cerr << "*** FileIndexMonitor: Updating flags for " << dir.filename << " to " << dir.shareflags << std::endl ; +#endif + { + RsStackMutex stack(fiMutex) ; /* LOCKED DIRS */ + + for(std::list::iterator it(pendingDirList.begin());it!=pendingDirList.end();++it) + { + std::cerr << "** testing pending dir " << (*it).filename << std::endl ; + if((*it).filename == dir.filename) + { + std::cerr << "** Updating to " << (*it).shareflags << "!!" << std::endl ; + (*it).shareflags = dir.shareflags ; + break ; + } + } + + for(std::map::iterator it(directoryMap.begin());it!=directoryMap.end();++it) + { + std::cerr << "** testing " << (*it).second.filename << std::endl ; + if((*it).second.filename == dir.filename) + { + std::cerr << "** Updating from " << it->second.shareflags << "!!" << std::endl ; + (*it).second.shareflags = dir.shareflags ; + fimods = true ; + break ; + } + } + } + if(fimods) + { + RsStackMutex stack(fiMutex) ; /* LOCKED DIRS */ + locked_saveFileIndexes() ; + } + cb->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); +} + /* interface */ +void FileIndexMonitor::setSharedDirectories(const std::list& dirs) +{ + cb->notifyListPreChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); + + std::list checkeddirs; + + std::list::const_iterator it; +#ifdef FIM_DEBUG + std::cerr << "FileIndexMonitor::setSharedDirectories() :\n"; +#endif + + for(it = dirs.begin(); it != dirs.end(); it++) + { + +#ifdef FIM_DEBUG + std::cerr << "\t" << (*it).filename; + std::cerr << std::endl; +#endif + + checkeddirs.push_back(*it); + +#ifdef REMOVED_CODE + // this code has been removed because it prevents unmounted shared directories to stay in the list of shared files. It's better + // to keep them showing empty than removing them completely. + // + /* check if dir exists before adding in */ +// std::string path = (*it).filename; +// if (!RsDirUtil::checkDirectory(path)) +// { +//#ifdef FIM_DEBUG +// std::cerr << "FileIndexMonitor::setSharedDirectories()"; +// std::cerr << " Ignoring NonExistant SharedDir: " << path << std::endl; +//#endif +// } +// else +// { +// checkeddirs.push_back(*it); +// } +#endif + } + + { + RsStackMutex stack(fiMutex) ;/* LOCKED DIRS */ + + pendingDirs = true; + pendingDirList = checkeddirs; + } + + cb->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0); +} + + /* interface */ +void FileIndexMonitor::getSharedDirectories(std::list &dirs) +{ + RsStackMutex stack(fiMutex) ; /* LOCKED DIRS */ + + /* must provide pendingDirs, as other parts depend on instanteous response */ + if (pendingDirs) + dirs = pendingDirList; + else + { + /* get actual list (not pending stuff) */ + std::map::const_iterator it; + + for(it = directoryMap.begin(); it != directoryMap.end(); it++) + dirs.push_back(it->second) ; + } +} + + + /* interface */ +void FileIndexMonitor::forceDirectoryCheck() +{ + RsStackMutex stack(fiMutex) ; /* LOCKED DIRS */ + + if (!mInCheck) + mForceCheck = true; +} + + + /* interface */ +bool FileIndexMonitor::inDirectoryCheck() +{ + RsStackMutex stack(fiMutex); /**** LOCKED DIRS ****/ + + return mInCheck; +} + + +bool FileIndexMonitor::internal_setSharedDirectories() +{ + int i; + RsStackMutex stack(fiMutex) ; /* LOCKED DIRS */ + + if (!pendingDirs) + { + if (mForceCheck) + { + mForceCheck = false; + return true; + } + + return false; + } + + mForceCheck = false; + pendingDirs = false; + pendingForceCacheWrite = true; + + /* clear old directories */ + directoryMap.clear(); + + /* iterate through the directories */ + std::list::iterator it; + std::map::const_iterator cit; + for(it = pendingDirList.begin(); it != pendingDirList.end(); it++) + { + /* get the head directory */ + std::string root_dir = (*it).filename; + std::string top_dir = it->virtualname; + if (top_dir.empty()) { + top_dir = RsDirUtil::getTopDir(root_dir); + } + + /* if unique -> add, else add modifier */ + bool unique = false; + for(i = 0; !unique; i++) + { + std::string tst_dir = top_dir; + if (i > 0) + { + std::ostringstream out; + out << "-" << i; + tst_dir += out.str(); + } + if (directoryMap.end()== (cit=directoryMap.find(tst_dir))) + { + unique = true; + /* store calculated name */ + it->virtualname = tst_dir; + /* add it! */ + directoryMap[tst_dir.c_str()] = *it; +#ifdef FIM_DEBUG + std::cerr << "Added [" << tst_dir << "] => " << root_dir << std::endl; +#endif + } + } + } + + pendingDirList.clear(); + + /* now we've decided on the 'root' dirs set them to the + * fileIndex + */ + std::list topdirs; + for(cit = directoryMap.begin(); cit != directoryMap.end(); cit++) + { + topdirs.push_back(cit->first); + } + + fi.setRootDirectories(topdirs, 0); + + locked_saveFileIndexes() ; + + return true; +} + +/* lookup directory function */ +std::string FileIndexMonitor::locked_findRealRoot(std::string rootdir) const +{ + /**** MUST ALREADY BE LOCKED ****/ + std::string realroot = ""; + + std::map::const_iterator cit; + if (directoryMap.end()== (cit=directoryMap.find(rootdir))) + { + std::cerr << "FileIndexMonitor::locked_findRealRoot() Invalid RootDir: "; + std::cerr << rootdir << std::endl; + } + else + { + realroot = cit->second.filename; + } + + return realroot; +} + +int FileIndexMonitor::RequestDirDetails(std::string uid, std::string path, DirDetails &details) const +{ + /* lock it up */ + RsStackMutex mutex(fiMutex) ; + + return (uid == fi.root->id) ; +} + +uint32_t FileIndexMonitor::getType(void *ref) const +{ + RsStackMutex mutex(fiMutex) ; + + return fi.getType(ref) ; +} +int FileIndexMonitor::RequestDirDetails(void *ref, DirDetails &details, uint32_t flags) const +{ + RsStackMutex mutex(fiMutex) ; + +#ifdef FIM_DEBUG2 + std::cerr << "FileIndexMonitor::RequestDirDetails() ref=" << ref << " flags: " << flags << std::endl; +#endif + + /* root case */ + +#ifdef FIM_DEBUG2 + fi.root->checkParentPointers(); +#endif + + // If ref is NULL, we build a root node + + if (ref == NULL) + { +#ifdef FI_DEBUG2 + std::cerr << "FileIndex::RequestDirDetails() ref=NULL (root)" << std::endl; +#endif + /* local only */ + DirStub stub; + stub.type = DIR_TYPE_PERSON; + stub.name = fi.root->name; + stub.ref = fi.root; + details.children.push_back(stub); + details.count = 1; + + details.parent = NULL; + details.prow = -1; + details.ref = NULL; + details.type = DIR_TYPE_ROOT; + details.name = "root"; + details.hash = ""; + details.path = "root"; + details.age = 0; + details.flags = 0; + details.min_age = 0 ; + + return true ; + } + + bool b = FileIndex::extractData(ref,details) ; + + if(!b) + return false ; + + // look for the top level and setup flags accordingly + // The top level directory is the first dir in parents for which + // dir->parent->parent == NULL + + if(ref != NULL) + { + FileEntry *file = (FileEntry *) ref; + + uint32_t share_flags = locked_findShareFlags(file) ; + + details.flags |= (( (share_flags & RS_FILE_HINTS_BROWSABLE )>0)?DIR_FLAGS_BROWSABLE :0) ; + details.flags |= (( (share_flags & RS_FILE_HINTS_NETWORK_WIDE)>0)?DIR_FLAGS_NETWORK_WIDE:0) ; + } + return true ; +} + +uint32_t FileIndexMonitor::locked_findShareFlags(FileEntry *file) const +{ + uint32_t flags = 0 ; + + DirEntry *dir = dynamic_cast(file) ; + if(dir == NULL) + dir = dynamic_cast(file->parent) ; + + if(dir != NULL && dir->parent != NULL) + while(dir->parent->parent != NULL) + dir = dir->parent ; + + if(dir != NULL && dir->parent != NULL) + { +#ifdef FIM_DEBUG2 + std::cerr << "FileIndexMonitor::RequestDirDetails: top parent name=" << dir->name << std::endl ; +#endif + std::map::const_iterator it = directoryMap.find(dir->name) ; + + if(it == directoryMap.end()) + std::cerr << "*********** ERROR *********** In " << __PRETTY_FUNCTION__ << std::endl ; + else + flags = it->second.shareflags & (RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE) ; +#ifdef FIM_DEBUG2 + std::cerr << "flags = " << flags << std::endl ; +#endif + } + + return flags ; +} + + diff --git a/libretroshare/src/dbase/fimonitor.h b/libretroshare/src/dbase/fimonitor.h new file mode 100644 index 000000000..8c859e725 --- /dev/null +++ b/libretroshare/src/dbase/fimonitor.h @@ -0,0 +1,208 @@ +/* + * RetroShare FileCache Module: fimonitor.h + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FILE_INDEX_MONITOR_H +#define FILE_INDEX_MONITOR_H + +#include "dbase/cachestrapper.h" +#include "dbase/findex.h" +#include "util/rsthreads.h" +#include "retroshare/rsfiles.h" + +/****************************************************************************************** + * The Local Monitoring Class: FileIndexMonitor. + * + * This periodically scans the directory tree, and updates any modified directories/files. + * + *****************************************************************************************/ + +/****************************************************************************************** + STILL TODO: + + (1) Implement Hash function. + +bool FileIndexMonitor::hashFile(std::string path, FileEntry &fi); + + (2) Add Shared directory controls to Monitor. + +int FileIndexMonitor::addSharedDirectory(std::path); +int FileIndexMonitor::removeSharedDirectory(std::path); +std::string FileIndexMonitor::findRealRoot(std::string base); + + These must be split into / and the mapping saved. + eg: addSharedDirectory("c:/home/stuff/dir1") --> "c:/home/stuff" <-> "dir1" + This code has been written already, and can just be moved over. + + FOR LATER: + (2) Port File/Directory lookup code to windoze. (or compile dirent.c under windoze) + (3) Add Load/Store interface to FileIndexMonitor. (later) + (4) Integrate with real Thread/Mutex code (last thing to do) + +******************************************************************************************/ + +class NotifyBase ; + +class DirContentToHash +{ + public: + std::vector fentries ; + + std::string realpath ; + std::string dirpath ; +}; + +class HashCache +{ + public: + HashCache(const std::string& save_file_name) ; + + void save() ; + void insert(const std::string& full_path,uint64_t size,time_t time_stamp,const std::string& hash) ; + bool find(const std::string& full_path,uint64_t size,time_t time_stamp,std::string& hash) ; + void clean() ; + + typedef struct + { + uint64_t size ; + time_t time_stamp ; + time_t modf_stamp ; + std::string hash ; + } HashCacheInfo ; + + void setRememberHashFilesDuration(uint32_t days) { _max_cache_duration_days = days ; } + uint32_t rememberHashFilesDuration() const { return _max_cache_duration_days ; } + void clear() { _files.clear(); } + bool empty() const { return _files.empty() ; } + private: + uint32_t _max_cache_duration_days ; // maximum duration of un-requested cache entries + std::map _files ; + std::string _path ; + bool _changed ; +}; + +/****************************************************************************************** + * FileIndexMonitor + *****************************************************************************************/ + +class FileIndexMonitor: public CacheSource, public RsThread +{ + public: + FileIndexMonitor(CacheStrapper *cs, NotifyBase *cb_in, std::string cachedir, std::string pid, const std::string& config_dir); + virtual ~FileIndexMonitor(); + + /* external interface for filetransfer */ + bool findLocalFile(std::string hash,uint32_t f, std::string &fullpath, uint64_t &size) const; + int SearchKeywords(std::list keywords, std::list &results,uint32_t flags) ; + int SearchBoolExp(Expression *exp, std::list &results,uint32_t flags) const ; + int filterResults(std::list& firesults,std::list& results,uint32_t flags) const ; + + + /* external interface for local access to files */ + bool convertSharedFilePath(std::string path, std::string &fullpath); + + + /* Interacting with CacheSource */ + /* overloaded from CacheSource */ + virtual bool loadLocalCache(const CacheData &data); /* called with stored data */ + bool updateCache(const CacheData &data); /* we call when we have a new cache for others */ + + + /* the FileIndexMonitor inner workings */ + //virtual void run(std::string& currentJob); /* overloaded from RsThread */ + //void updateCycle(std::string& currentJob); + virtual void run(); /* overloaded from RsThread */ + void updateCycle(); + + // Interface for browsing dir hirarchy + int RequestDirDetails(void*, DirDetails&, uint32_t) const ; + uint32_t getType(void*) const ; + int RequestDirDetails(std::string uid, std::string path, DirDetails &details) const ; + + // set/update shared directories + virtual void setSharedDirectories(const std::list& dirs); + void getSharedDirectories(std::list& dirs); + void updateShareFlags(const SharedDirInfo& info) ; + + void forceDirectoryCheck(); + bool inDirectoryCheck(); + + /* util fns */ + + protected: + // Sets/gets the duration period within which already hashed files are remembered. + // + void setRememberHashFilesDuration(uint32_t days) ; + uint32_t rememberHashFilesDuration() const ; + void setRememberHashFiles(bool) ; + bool rememberHashFiles() ; + // Remove any memory of formerly hashed files that are not shared anymore + void clearHashFiles() ; + void setPeriod(int insecs); + int getPeriod() const; + + bool autoCheckEnabled() const ; + + private: + /* the mutex should be locked before calling these 3. */ + + // saves file indexs and update the cache. + void locked_saveFileIndexes() ; + + // Finds the share flags associated with this file entry. + uint32_t locked_findShareFlags(FileEntry *fe) const ; + + std::string locked_findRealRoot(std::string base) const; + + void hashFiles(const std::vector& to_hash) ; + bool hashFile(std::string path, FileEntry &fi); /* To Implement */ + + /* data */ + + mutable RsMutex fiMutex; + + FileIndex fi; + + int updatePeriod; + std::map directoryMap; /* used by findRealRoot */ + + /* flags to kick - if we were busy or sleeping */ + bool pendingDirs; + bool pendingForceCacheWrite; + + /* flags to force Check, to tell if we're in check */ + bool mForceCheck; + bool mInCheck; + + std::list pendingDirList; + bool internal_setSharedDirectories(); + + NotifyBase *cb ; + + HashCache hashCache ; + bool useHashCache ; +}; + + +#endif + + diff --git a/libretroshare/src/dbase/findex.cc b/libretroshare/src/dbase/findex.cc new file mode 100644 index 000000000..d925cbadc --- /dev/null +++ b/libretroshare/src/dbase/findex.cc @@ -0,0 +1,1330 @@ +/* + * RetroShare FileCache Module: findex.cc + * + * Copyright 2004-2007 by Robert Fernie, Kefei Zhou. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include "dbase/findex.h" +#include "retroshare/rsexpr.h" +#include "util/rsdir.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// This char is used to separate fields in the file list cache. It is supposed to be +// sufficiently safe on all systems. +// +static const char FILE_CACHE_SEPARATOR_CHAR = '|' ; + +/**** +#define FI_DEBUG 1 + * #define FI_DEBUG_ALL 1 + ****/ + +static RsMutex FIndexPtrMtx ; +std::tr1::unordered_set FileIndex::_pointers ; + +void FileIndex::registerEntry(void*p) +{ + RsStackMutex m(FIndexPtrMtx) ; + _pointers.insert(p) ; +} +void FileIndex::unregisterEntry(void*p) +{ + RsStackMutex m(FIndexPtrMtx) ; + _pointers.erase(p) ; +} +bool FileIndex::isValid(void*p) +{ + RsStackMutex m(FIndexPtrMtx) ; + return _pointers.find(p) != _pointers.end() ; +} + +DirEntry::~DirEntry() +{ + /* cleanup */ + std::map::iterator dit; + std::map::iterator fit; + + for(dit = subdirs.begin(); dit != subdirs.end(); dit++) + { + FileIndex::unregisterEntry((void*)dit->second) ; + delete (dit->second); + } + subdirs.clear(); + + for(fit = files.begin(); fit != files.end(); fit++) + { + FileIndex::unregisterEntry((void*)fit->second) ; + delete (fit->second); + } + files.clear(); +} + + +int DirEntry::checkParentPointers() +{ +#ifdef FI_DEBUG + updateChildRows(); + std::map::iterator dit; + for(dit = subdirs.begin(); dit != subdirs.end(); dit++) + { + /* debug check */ + (dit->second)->checkParentPointers(); + } +#endif + return 1; +} + + + +int DirEntry::updateChildRows() +{ + /* iterate through children and set row (parent should be good) */ + std::map::iterator dit; + std::map::iterator fit; + int i = 0; + for(dit = subdirs.begin(); dit != subdirs.end(); dit++) + { +#ifdef FI_DEBUG + /* debug check */ + if ((dit->second)->parent != this) + { + std::cerr << "DirEntry::updateChildRows()"; + std::cerr << "****WARNING subdir Parent pointer invalid!"; + std::cerr << std::endl; + (dit->second)->parent = this; + } +#endif + (dit->second)->row = i++; + } + + for(fit = files.begin(); fit != files.end(); fit++) + { +#ifdef FI_DEBUG + /* debug check */ + if ((fit->second)->parent != this) + { + std::cerr << "DirEntry::updateChildRows()"; + std::cerr << "****WARNING file Parent pointer invalid!"; + std::cerr << std::endl; + (fit->second)->parent = this; + } +#endif + (fit->second)->row = i++; + } + return 1; +} + + +int DirEntry::removeDir(const std::string& name) +{ + /* if it doesn't exist - add */ + std::map::iterator it; + DirEntry *ndir = NULL; + if (subdirs.end() != (it = subdirs.find(name))) + { +#ifdef FI_DEBUG_ALL + std::cerr << "DirEntry::removeDir() Cleaning up dir: " << name; + std::cerr << std::endl; +#endif + ndir = (it->second); + + subdirs.erase(it); + FileIndex::unregisterEntry((void*)ndir) ; + delete ndir; + /* update row counters */ + updateChildRows(); + return 1; + } + +#ifdef FI_DEBUG + std::cerr << "DirEntry::removeDir() missing Entry: " << name; + std::cerr << std::endl; +#endif + return 0; +} + + +int DirEntry::removeFile(const std::string& name) +{ + /* if it doesn't exist - add */ + std::map::iterator it; + FileEntry *nfile = NULL; + + if (files.end() != (it = files.find(name))) + { +#ifdef FI_DEBUG_ALL + std::cerr << "DirEntry::removeFile() removing File: " << name; + std::cerr << std::endl; +#endif + nfile = (it->second); + + files.erase(it); + FileIndex::unregisterEntry((void*)nfile) ; + delete nfile; + /* update row counters */ + updateChildRows(); + return 1; + } + +#ifdef FI_DEBUG + std::cerr << "DirEntry::removeFile() missing Entry: " << name; + std::cerr << std::endl; +#endif + return 0; +} + + + + +int DirEntry::removeOldDir(const std::string& name, time_t old) +{ + std::map::iterator it; + DirEntry *ndir = NULL; + if (subdirs.end() != (it = subdirs.find(name))) + { + ndir = (it->second); + if (ndir->updtime < old) + { +#ifdef FI_DEBUG_ALL + std::cerr << "DirEntry::removeOldDir() Removing Old dir: " << name; + std::cerr << std::endl; +#endif + subdirs.erase(it); + FileIndex::unregisterEntry((void*)ndir) ; + delete ndir; + + /* update row counters */ + updateChildRows(); + return 1; + } +#ifdef FI_DEBUG_ALL + std::cerr << "DirEntry::removeOldDir() Keeping UptoDate dir: " << name; + std::cerr << std::endl; +#endif + return 0; + } + +#ifdef FI_DEBUG + std::cerr << "DirEntry::removeDir() missing Entry: " << name; + std::cerr << std::endl; +#endif + return 0; +} + + + + +int DirEntry::removeOldEntries(time_t old, bool recursive) +{ + /* remove old dirs from our lists -> then do children and files */ + + /* get all dirs with old time */ + std::list removeList; + std::map::iterator it; + for(it = subdirs.begin(); it != subdirs.end(); it++) + { + if ((it->second)->updtime < old) + { + removeList.push_back(it->second); + } + } + + /* now remove the old entries */ + std::list::iterator rit; + for(rit = removeList.begin(); rit != removeList.end(); rit++) + { + removeDir((*rit)->name); + } + + if (recursive) + { + /* now handle children */ + for(it = subdirs.begin(); it != subdirs.end(); it++) + { + (it->second)->removeOldEntries(old, recursive); + } + } + + /* now handle files similarly */ + std::list removeFileList; + std::map::iterator fit; + for(fit = files.begin(); fit != files.end(); fit++) + { + if ((fit->second)->updtime < old) + { + removeFileList.push_back(fit->second); + } + } + + /* now remove the old entries */ + std::list::iterator rfit; + for(rfit = removeFileList.begin(); rfit != removeFileList.end(); rfit++) + { + removeFile((*rfit)->name); + } + + return 1; +} + + +DirEntry *DirEntry::findOldDirectory(time_t old) +{ + /* check if one of our directories is old ... + */ + + /* get all dirs with old time */ + std::map::iterator it; + for(it = subdirs.begin(); it != subdirs.end(); it++) + { + if ((it->second)->updtime < old) + { + return (it->second); + } + } + + /* + * else check chlidren. + */ + + for(it = subdirs.begin(); it != subdirs.end(); it++) + { + DirEntry *olddir = (it->second)->findOldDirectory(old); + if (olddir) + { + return olddir; + } + } + + return NULL; +} + + +DirEntry *DirEntry::findDirectory(const std::string& fpath) +{ + std::string nextdir = RsDirUtil::getRootDir(fpath); + std::map::iterator it; + if (subdirs.end() == (it = subdirs.find(nextdir))) + { +#ifdef FI_DEBUG + std::cerr << "DirEntry::findDirectory() Missing subdir:"; + std::cerr << "\"" << nextdir << "\""; + std::cerr << std::endl; +#endif + return NULL; + } + + std::string rempath = RsDirUtil::removeRootDir(fpath); + if (rempath == "") + { + return it->second; + } + + return (it->second)->findDirectory(rempath); +} + + +int DirEntry::updateDirectories(const std::string& fpath, int new_pop, int new_modtime) +{ + int ret = 1; + if (path != "") /* if not there -> continue down tree */ + { + std::string nextdir = RsDirUtil::getRootDir(fpath); + std::map::iterator it; + if (subdirs.end() == (it = subdirs.find(nextdir))) + { + return 0; + } + + std::string rempath = RsDirUtil::removeRootDir(fpath); + ret = (it->second)->updateDirectories(rempath, new_pop, new_modtime); + } + + if (ret) /* if full path is okay -> update and return ok */ + { + /* this is assumes that pop always increases! */ + if (new_pop > pop) + { + pop = new_pop; + } + if (new_modtime > modtime) + { + modtime = new_modtime; + } + } + return ret; +} + +DirEntry *DirEntry::updateDir(const FileEntry& fe, time_t utime) +{ + /* if it doesn't exist - add */ + std::map::iterator it; + DirEntry *ndir = NULL; + if (subdirs.end() == (it = subdirs.find(fe.name))) + { +#ifdef FI_DEBUG_ALL + std::cerr << "DirEntry::updateDir() Adding Entry"; + std::cerr << std::endl; +#endif + ndir = new DirEntry(); + FileIndex::registerEntry((void*)ndir) ; + ndir -> parent = this; + ndir -> path = path + "/" + fe.name; + ndir -> name = fe.name; + ndir -> pop = 0; + ndir -> modtime = 0; + ndir -> updtime = utime; + + subdirs[fe.name] = ndir; + + /* update row counters */ + updateChildRows(); + return ndir; + } + +#ifdef FI_DEBUG_ALL + std::cerr << "DirEntry::updateDir() Updating Entry"; + std::cerr << std::endl; +#endif + + /* update utime */ + ndir = (it->second); + ndir->updtime = utime; + + return ndir; +} + + +FileEntry *DirEntry::updateFile(const FileEntry& fe, time_t utime) +{ + /* if it doesn't exist - add */ + std::map::iterator it; + FileEntry *nfile = NULL; + if (files.end() == (it = files.find(fe.name))) + { + +#ifdef FI_DEBUG_ALL + std::cerr << "DirEntry::updateFile() Adding Entry"; + std::cerr << std::endl; +#endif + + nfile = new FileEntry(); + FileIndex::registerEntry((void*)nfile) ; + nfile -> parent = this; + nfile -> name = fe.name; + nfile -> hash = fe.hash; + nfile -> size = fe.size; + nfile -> pop = 0; + nfile -> modtime = fe.modtime; + nfile -> updtime = utime; + + files[fe.name] = nfile; + + /* update row counters */ + updateChildRows(); + return nfile; + } + + +#ifdef FI_DEBUG_ALL + std::cerr << "DirEntry::updateFile() Updating Entry"; + std::cerr << std::endl; +#endif + + + /* update utime */ + nfile = (it->second); + nfile -> parent = this; + nfile -> name = fe.name; + nfile -> hash = fe.hash; + nfile -> size = fe.size; + nfile -> modtime = fe.modtime; + nfile -> updtime = utime; + //nfile -> pop = 0; // not handled here. + + return nfile; +} + + +int FileEntry::print(std::ostream &out) +{ + /* print this dir, then subdirs, then files */ + + out << "file "; + out << std::setw(3) << std::setfill('0') << row; + out << " [" << updtime << "/" << modtime << "] : "; + + if (parent) + out << parent->path; + else + out << "[MISSING PARENT]"; + + out << " " << name; + out << " [ s: " << size << " ] ==> "; + out << " [ " << hash << " ]"; + out << std::endl; + return 1; +} + + +int DirEntry::print(std::ostream &out) +{ + /* print this dir, then subdirs, then files */ + out << "dir "; + out << std::setw(3) << std::setfill('0') << row; + out << " [" << updtime << "] : " << path; + out << std::endl; + + std::map::iterator it; + for(it = subdirs.begin(); it != subdirs.end(); it++) + { + (it->second)->print(out); + } + std::map::iterator fit; + for(fit = files.begin(); fit != files.end(); fit++) + { + (fit->second)->print(out); + } + return 1; +} + +FileIndex::FileIndex(const std::string& pid) +{ + root = new PersonEntry(pid); + registerEntry(root) ; +} + +FileIndex::~FileIndex() +{ + FileIndex::unregisterEntry((void*)root) ; + delete root; +} + +int FileIndex::setRootDirectories(const std::list &inlist, time_t updtime) +{ + /* set update time to zero */ + std::map::iterator it; + for(it = root->subdirs.begin(); it != root->subdirs.end(); it++) + { + (it->second)->updtime = 0; + } + + std::list::const_iterator ait; + FileEntry fe; + time_t utime = 1; + for(ait = inlist.begin(); ait != inlist.end(); ait++) + { + fe.name = (*ait); + + /* see if it exists */ + root->updateDir(fe, utime); + } + + /* remove all dirs with zero time (non recursive) */ + root->removeOldEntries(utime, false); + + /* now flag remaining directories with correct update time */ + for(it = root->subdirs.begin(); it != root->subdirs.end(); it++) + { + (it->second)->updtime = updtime; + } + + return 1; +} + +void FileIndex::updateMaxModTime() +{ + RecursUpdateMaxModTime(root) ; +} +void FileIndex::RecursUpdateMaxModTime(DirEntry *dir) +{ + time_t max_mod_t = 0 ; + + for(std::map::iterator it(dir->subdirs.begin());it!=dir->subdirs.end();++it) + { + RecursUpdateMaxModTime(it->second) ; + max_mod_t = std::max(max_mod_t, it->second->most_recent_time) ; + } + for(std::map::iterator it(dir->files.begin());it!=dir->files.end();++it) + max_mod_t = std::max(max_mod_t, it->second->modtime) ; + + dir->most_recent_time = max_mod_t ; +} + +int FileIndex::getRootDirectories(std::list &outlist) +{ + /* set update time to zero */ + std::map::iterator it; + for(it = root->subdirs.begin(); it != root->subdirs.end(); it++) + { + outlist.push_back(it->first); + } + return 1; +} + +/* update (index building) */ +DirEntry *FileIndex::updateDirEntry(const std::string& fpath, const FileEntry& fe, time_t utime) +{ + /* path is to parent */ +#ifdef FI_DEBUG_ALL + std::cerr << "FileIndex::updateDirEntry() Path: \""; + std::cerr << fpath << "\"" << " + \"" << fe.name << "\""; + std::cerr << std::endl; +#endif + DirEntry *parent = NULL; + if (fpath == "") + { + parent = root; + } + else + { + parent = root->findDirectory(fpath); + } + + if (!parent) { +#ifdef FI_DEBUG + std::cerr << "FileIndex::updateDirEntry() NULL parent"; + std::cerr << std::endl; +#endif + return NULL; + } + return parent -> updateDir(fe, utime); +} + + +FileEntry *FileIndex::updateFileEntry(const std::string& fpath, const FileEntry& fe, time_t utime) +{ + /* path is to parent */ +#ifdef FI_DEBUG_ALL + std::cerr << "FileIndex::updateFileEntry() Path: \""; + std::cerr << fpath << "\"" << " + \"" << fe.name << "\""; + std::cerr << std::endl; +#endif + DirEntry *parent = root->findDirectory(fpath); + + if (!parent) { +#ifdef FI_DEBUG + std::cerr << "FileIndex::updateFileEntry() NULL parent"; + std::cerr << std::endl; +#endif + return NULL; + } + return parent -> updateFile(fe, utime); +} + + +DirEntry *FileIndex::findOldDirectory(time_t old) /* finds directories older than old */ +{ + DirEntry *olddir = root->findOldDirectory(old); +#ifdef FI_DEBUG + + std::cerr << "FileIndex::findOldDirectory(" << old << ") -> "; + if (olddir) + { + std::cerr << olddir->path; + } + else + { + std::cerr << "NONE"; + } + std::cerr << std::endl; + +#endif + return olddir; +} + +int FileIndex::removeOldDirectory(const std::string& fpath, const std::string& name, time_t old) +{ + /* path is to parent */ +#ifdef FI_DEBUG_ALL + std::cerr << "FileIndex::removeOldDirectory() Path: \""; + std::cerr << fpath << "\"" << " + \"" << name << "\""; + std::cerr << std::endl; +#endif + + /* because of this find - we cannot get a child of + * root (which is what we want!) + */ + + DirEntry *parent = root->findDirectory(fpath); + /* for root directory case ... no subdir. */ + if (fpath == "") + { +#ifdef FI_DEBUG + std::cerr << "FileIndex::removeOldDirectory() removing a root dir"; + std::cerr << std::endl; +#endif + parent = root; + } + + if (!parent) { +#ifdef FI_DEBUG + std::cerr << "FileIndex::removeOldDirectory() NULL parent"; + std::cerr << std::endl; +#endif + return 0; + } + return parent -> removeOldDir(name, old); +} + + +int FileIndex::cleanOldEntries(time_t old) /* removes entries older than old */ +{ + std::map::iterator it; + for(it = root->subdirs.begin(); it != root->subdirs.end(); it++) + { + (it->second)->removeOldEntries(old, true); + } + return 1; +} + + + +int FileIndex::printFileIndex(std::ostream &out) +{ + out << "FileIndex::printFileIndex()" << std::endl; + root->print(out); + return 1; +} + +int FileIndex::loadIndex(const std::string& filename, const std::string& expectedHash, uint64_t size) +{ + std::ifstream file (filename.c_str(), std::ifstream::binary); + if (!file) + { +#ifdef FI_DEBUG + std::cerr << "FileIndex::loadIndex error opening file: " << filename; + std::cerr << std::endl; +#endif + return 0; + } + + /* load file into memory, close file */ + char ibuf[512]; + std::stringstream ss; + while(!file.eof()) + { + file.read(ibuf, 512); + ss.write(ibuf, file.gcount()); + } + file.close(); + + /* calculate hash */ + unsigned char sha_buf[SHA_DIGEST_LENGTH]; + SHA_CTX *sha_ctx = new SHA_CTX; + SHA1_Init(sha_ctx); + SHA1_Update(sha_ctx, ss.str().c_str(), ss.str().length()); + SHA1_Final(&sha_buf[0], sha_ctx); + delete sha_ctx; + + std::ostringstream tmpout; + for(int i = 0; i < SHA_DIGEST_LENGTH; i++) + { + tmpout << std::setw(2) << std::setfill('0') << std::hex << (unsigned int) (sha_buf[i]); + } + + if (expectedHash != "" && expectedHash != tmpout.str()) + { +#ifdef FI_DEBUG + std::cerr << "FileIndex::loadIndex expected hash does not match" << std::endl; + std::cerr << "Expected hash: " << expectedHash << std::endl; + std::cerr << "Hash found: " << tmpout.str() << std::endl; +#endif + return 0; + } + + DirEntry *ndir = NULL; + FileEntry *nfile = NULL; + std::list dirlist; + std::string word; + char ch; + + while(ss.get(ch)) + { + if (ch == '-') + { + ss.ignore(256, '\n'); + switch(dirlist.size()) + { + /* parse error: out of directory */ + case 0: + { +#ifdef FI_DEBUG + std::cerr << "loadIndex error parsing saved file: " << filename; + std::cerr << " Ran out of dirs"; + std::cerr << std::endl; +#endif + goto error; + } + /* finished parse, last dir is root */ + case 1: + { + std::string pid = root -> id; + FileIndex::unregisterEntry((void*)root) ; + delete root; /* to clean up old entries */ + root = new PersonEntry(pid); + registerEntry((void*)root) ; + + /* shallow copy of all except id */ + ndir = dirlist.back(); + dirlist.pop_back(); /* empty list */ + (*root) = (*ndir); + + /* now cleanup (can't call standard delete) */ + ndir->subdirs.clear(); + ndir->files.clear(); + FileIndex::unregisterEntry((void*)ndir) ; + delete ndir; + ndir = NULL; + + /* must reset parent pointers now */ + std::map::iterator it; + for(it = root->subdirs.begin(); + it != root->subdirs.end(); it++) + { + (it->second)->parent = root; + } + + break; + } + /* pop stack */ + default: dirlist.pop_back(); ndir = dirlist.back(); + } + continue; + } + + // Ignore comments + else if (ch == '#') + { + ss.ignore(256, '\n'); + } + + else { + std::vector tokens; + /* parse line */ + while(1) + { + getline(ss, word, FILE_CACHE_SEPARATOR_CHAR); + if (ss.eof()) + goto error; + tokens.push_back(word); + if (ss.peek() == '\n') + { + ss.ignore(256, '\n'); + break; + } + + } + /* create new file and add it to last directory*/ + if (ch == 'f') + { + if (tokens.size() != 6) + { +#ifdef FI_DEBUG + std::cerr << "loadIndex error parsing saved file: " << filename; + std::cerr << " File token count wrong: " << tokens.size(); + std::cerr << std::endl; + for(unsigned int i = 0; i < tokens.size(); i++) + { + std::cerr << "\tToken[" << i << "]:" << tokens[i]; + std::cerr << std::endl; + } + +#endif + goto error; + } + nfile = new FileEntry(); + registerEntry((void*)nfile) ; + nfile->name = tokens[0]; + nfile->hash = tokens[1]; + nfile->size = atoll(tokens[2].c_str()); + nfile->modtime = atoi(tokens[3].c_str()); + nfile->pop = atoi(tokens[4].c_str()); + nfile->updtime = atoi(tokens[5].c_str()); + nfile->parent = ndir; + nfile->row = ndir->subdirs.size() + ndir->files.size(); + ndir->files[nfile->name] = nfile; + + } + /* create new dir and add to stack */ + else if (ch == 'd') + { + if (tokens.size() != 6) + { +#ifdef FI_DEBUG + std::cerr << "loadIndex error parsing saved file: " << filename; + std::cerr << " Dir token count wrong: " << tokens.size(); + std::cerr << std::endl; +#endif + goto error; + } + ndir = new DirEntry(); + registerEntry((void*)ndir) ; + ndir->name = tokens[0]; + ndir->path = tokens[1]; + ndir->size = atoi(tokens[2].c_str()); + ndir->modtime = atoi(tokens[3].c_str()); + ndir->pop = atoi(tokens[4].c_str()); + ndir->updtime = atoi(tokens[5].c_str()); + if (!dirlist.empty()) + { + ndir->parent = (dirlist.back()); + ndir->row = dirlist.back()->subdirs.size(); + dirlist.back()->subdirs[ndir->name] = ndir; + } + dirlist.push_back(ndir); + } + } + } + + return 1; + + /* parse error encountered */ +error: +#ifdef FI_DEBUG + std::cerr << "loadIndex error parsing saved file: " << filename; + std::cerr << std::endl; +#endif + return 0; +} + + +int FileIndex::saveIndex(const std::string& filename, std::string &fileHash, uint64_t &size,const std::set& forbidden_dirs) +{ + unsigned char sha_buf[SHA_DIGEST_LENGTH]; + std::string filenametmp = filename + ".tmp" ; + std::ostringstream oss; + + size = 0 ; + fileHash = "" ; + + /* print version and header */ + oss << "# FileIndex version 0.1" << std::endl; + oss << "# Dir: d name, path, parent, size, modtime, pop, updtime;" << std::endl; + oss << "# File: f name, hash, size, modtime, pop, updtime;" << std::endl; + oss << "#" << std::endl; + + /* begin recusion */ + root->writeDirInfo(oss) ; + + std::map::iterator it; + for(it = root->subdirs.begin(); it != root->subdirs.end(); it++) + { +#ifdef FI_DEBUG + std::cout << "writting root directory: name=" << it->second->name << ", path=" << it->second->path << std::endl ; +#endif + if(forbidden_dirs.find(it->second->name) != forbidden_dirs.end()) + { +#ifdef FI_DEBUG + std::cerr << " will be suppressed." << std::endl ; +#endif + } + else + { +#ifdef FI_DEBUG + std::cerr << " will be saved." << std::endl ; +#endif + (it->second)->saveEntry(oss); + } + } + + root->writeFileInfo(oss) ; // this should never do anything + + /* signal to pop directory from stack in loadIndex() */ + oss << "-" << std::endl; + + /* calculate sha1 hash */ + SHA_CTX *sha_ctx = new SHA_CTX; + SHA1_Init(sha_ctx); + SHA1_Update(sha_ctx, oss.str().c_str(), oss.str().length()); + SHA1_Final(&sha_buf[0], sha_ctx); + delete sha_ctx; + + std::ostringstream tmpout; + for(int i = 0; i < SHA_DIGEST_LENGTH; i++) + { + tmpout << std::setw(2) << std::setfill('0') << std::hex << (unsigned int) (sha_buf[i]); + } + fileHash = tmpout.str(); + + /* finally, save to file */ + + FILE *file = RsDirUtil::rs_fopen(filenametmp.c_str(), "wb"); + if (file == NULL) + { + std::cerr << "FileIndex::saveIndex error opening file for writting: " << filename << ". Giving up." << std::endl; + return 0; + } + fprintf(file,"%s",oss.str().c_str()) ; + + fclose(file); + + // Use a temp file name so that the file is never half saved. + // + if(!RsDirUtil::renameFile(filenametmp,filename)) + return false ; + + /* get the size out */ + struct stat64 buf; + + if(-1 == stat64(filename.c_str(), &buf)) + { + std::cerr << "Can't determine size of file " << filename << ": errno = " << errno << std::endl ; + return false ; + } + + size=buf.st_size; + + return true; +} + + +std::string FixName(const std::string& _in) +{ + /* replace any , with _ */ + std::string in(_in) ; + for(unsigned int i = 0; i < in.length(); i++) + { + if (in[i] == FILE_CACHE_SEPARATOR_CHAR) + { + in[i] = '_'; + } + } + return in; +} + +void DirEntry::writeDirInfo(std::ostringstream& oss) +{ + /* print node info */ + oss << "d"; + oss << FixName(name) << FILE_CACHE_SEPARATOR_CHAR ; + oss << FixName(path) << FILE_CACHE_SEPARATOR_CHAR ; + oss << size << FILE_CACHE_SEPARATOR_CHAR ; + oss << modtime << FILE_CACHE_SEPARATOR_CHAR ; + oss << pop << FILE_CACHE_SEPARATOR_CHAR ; + oss << updtime << FILE_CACHE_SEPARATOR_CHAR << std::endl; +} + +void DirEntry::writeFileInfo(std::ostringstream& oss) +{ + /* print file info */ + std::map::iterator fit; + for(fit = files.begin(); fit != files.end(); fit++) + { + oss << "f"; + oss << FixName((fit->second)->name) << FILE_CACHE_SEPARATOR_CHAR ; + oss << (fit->second)->hash << FILE_CACHE_SEPARATOR_CHAR ; + oss << (fit->second)->size << FILE_CACHE_SEPARATOR_CHAR ; + oss << (fit->second)->modtime << FILE_CACHE_SEPARATOR_CHAR ; + oss << (fit->second)->pop << FILE_CACHE_SEPARATOR_CHAR ; + oss << (fit->second)->updtime << FILE_CACHE_SEPARATOR_CHAR << std::endl; + } +} + +/* recusive function for traversing the dir tree in preorder */ +int DirEntry::saveEntry(std::ostringstream &oss) +{ + writeDirInfo(oss) ; + + std::map::iterator it; + for(it = subdirs.begin(); it != subdirs.end(); it++) + { + (it->second)->saveEntry(oss); + } + + writeFileInfo(oss) ; + + /* signal to pop directory from stack in loadIndex() */ + oss << "-" << std::endl; + return 1; +} + + +int FileIndex::searchHash(const std::string& hash, std::list &results) const +{ +#ifdef FI_DEBUG + std::cerr << "FileIndex::searchHash(" << hash << ")"; + std::cerr << std::endl; +#endif + DirEntry *ndir = NULL; + std::list dirlist; + dirlist.push_back(root); + + while(!dirlist.empty()) + { + ndir = dirlist.back(); + dirlist.pop_back(); + /* add subdirs to stack */ + std::map::iterator it; + for(it = ndir->subdirs.begin(); it != ndir->subdirs.end(); it++) + { + dirlist.push_back(it->second); + } + + std::map::iterator fit; + /* search in current dir */ + for(fit = ndir->files.begin(); fit != ndir->files.end(); fit++) + { + if (hash == (fit->second)->hash) + { + results.push_back(fit->second); +#ifdef FI_DEBUG + std::cerr << "FileIndex::searchHash(" << hash << ")"; + std::cerr << " found: " << fit->second->name; + std::cerr << std::endl; +#endif + } + } + } + + return 0; +} + + +int FileIndex::searchTerms(const std::list& terms, std::list &results) const +{ + DirEntry *ndir = NULL; + std::list dirlist; + dirlist.push_back(root); + + /* iterators */ + std::map::iterator it; + std::map::iterator fit; + std::list::const_iterator iter; + + while(!dirlist.empty()) + { + ndir = dirlist.back(); + dirlist.pop_back(); + for(it = ndir->subdirs.begin(); it != ndir->subdirs.end(); it++) + { + dirlist.push_back(it->second); + } + + for (iter = terms.begin(); iter != terms.end(); iter ++) { + std::string::const_iterator it2; + const std::string &str1 = ndir->name; + const std::string &str2 = *iter; + it2 = std::search(str1.begin(), str1.end(), str2.begin(), str2.end(), CompareCharIC()); + if (it2 != str1.end()) { + /* first search to see if its parent is in the results list */ + bool addDir = true; + for (std::list::iterator rit(results.begin()); rit != results.end() && addDir; rit ++) { + DirEntry *de = dynamic_cast(*rit); + if (de && (de == root)) + continue; + if (de && (de == ndir->parent)) + addDir = false; + } + if (addDir) { + results.push_back((FileEntry *) ndir); + break; + } + } + } + + for(fit = ndir->files.begin(); fit != ndir->files.end(); fit++) + { + /* cycle through terms */ + for(iter = terms.begin(); iter != terms.end(); iter++) + { + /* always ignore case */ + std::string::const_iterator it2 ; + const std::string &str1 = fit->second->name; + const std::string &str2 = (*iter); + + it2 = std::search( str1.begin(), str1.end(), + str2.begin(), str2.end(), CompareCharIC() ); + if (it2 != str1.end()) + { + results.push_back(fit->second); + break; + } + /* original case specific term search ****** + if (fit->second->name.find(*iter) != std::string::npos) + { + results.push_back(fit->second); + break; + } + ************/ + } + } + } //while + + return 0; +} + +int FileIndex::searchBoolExp(Expression * exp, std::list &results) const +{ + DirEntry *ndir = NULL; + std::list dirlist; + dirlist.push_back(root); + + /* iterators */ + std::map::iterator it; + std::map::iterator fit; + std::list::const_iterator iter; + + while(!dirlist.empty()) + { + ndir = dirlist.back(); + dirlist.pop_back(); + for(it = ndir->subdirs.begin(); it != ndir->subdirs.end(); it++) + { + dirlist.push_back(it->second); + } + + for(fit = ndir->files.begin(); fit != ndir->files.end(); fit++) + { + /*Evaluate the boolean expression and add it to the results if its true*/ + bool ret = exp->eval(fit->second); + if (ret == true){ + results.push_back(fit->second); + } + } + } //while + + return 0; +} + +uint32_t FileIndex::getType(void *ref) +{ + if(ref == NULL) + return DIR_TYPE_ROOT ; + + if(!isValid(ref)) + return DIR_TYPE_ROOT ; + + return static_cast(ref)->type() ; +} +bool FileIndex::extractData(void *ref,DirDetails& details) +{ + if(!isValid(ref)) + { +#ifdef FI_DEBUG + std::cerr << "FileIndex::extractData() asked for an invalid pointer " << (void*)ref << std::endl; +#endif + return false ; + } + + FileEntry *file = static_cast(ref); + DirEntry *dir = (file->hash.empty())?static_cast(file):NULL ; // This is a hack to avoid doing a dynamic_cast + + details.children = std::list() ; + time_t now = time(NULL) ; + + if (dir!=NULL) /* has children --- fill */ + { +#ifdef FI_DEBUG + std::cerr << "FileIndex::extractData() ref=dir" << std::endl; +#endif + /* extract all the entries */ + for(std::map::const_iterator dit(dir->subdirs.begin()); dit != dir->subdirs.end(); ++dit) + { + DirStub stub; + stub.type = DIR_TYPE_DIR; + stub.name = (dit->second) -> name; + stub.ref = (dit->second); + + details.children.push_back(stub); + } + + for(std::map::const_iterator fit(dir->files.begin()); fit != dir->files.end(); ++fit) + { + DirStub stub; + stub.type = DIR_TYPE_FILE; + stub.name = (fit->second) -> name; + stub.ref = (fit->second); + + details.children.push_back(stub); + } + + if(dir->parent == NULL) + details.type = DIR_TYPE_PERSON ; + else + details.type = DIR_TYPE_DIR; + details.hash = ""; + details.count = dir->subdirs.size() + dir->files.size(); + details.min_age = now - dir->most_recent_time ; + } + else + { +#ifdef FI_DEBUG + std::cerr << "FileIndexStore::extractData() ref=file" << std::endl; +#endif + details.type = DIR_TYPE_FILE; + details.count = file->size; + details.min_age = now - file->modtime ; + } + +#ifdef FI_DEBUG + std::cerr << "FileIndexStore::extractData() name: " << file->name << std::endl; +#endif + details.ref = file; + details.hash = file->hash; + details.age = now - file->modtime; + details.flags = 0;//file->pop; + + /* find parent pointer, and row */ + details.parent = file->parent ; + + details.prow = (file->parent==NULL)?0:file->parent->row ; + + if(details.type == DIR_TYPE_DIR) + { + details.name = file->name; + details.path = dir->path; + } + else + { + details.name = file->name; + details.path = (file->parent==NULL)?"":file->parent->path; + } + + /* find peer id */ + FileEntry *f ; + for(f=file;f->parent!=NULL;f=f->parent) ; + + details.id = static_cast(f)->id; // The topmost parent is necessarily a personEntrY, so we can avoid a dynamic_cast. + +#ifdef FI_DEBUG + assert(details.parent != details.ref) ; + std::cout << "details: ref=" << (void*)ref << ", prow=" << details.prow << ", parent=" << (void*)details.parent << ", children=" ; + for(std::list::iterator it(details.children.begin());it!=details.children.end();++it) + std::cout << " " << (void*)it->ref ; + std::cout << std::endl ; +#endif + + return true; +} + diff --git a/libretroshare/src/dbase/findex.h b/libretroshare/src/dbase/findex.h new file mode 100644 index 000000000..29c4089d4 --- /dev/null +++ b/libretroshare/src/dbase/findex.h @@ -0,0 +1,262 @@ +/* + * RetroShare FileCache Module: findex.h + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FILE_INDEX_H +#define FILE_INDEX_H + +#include +#include +#include +#include +#include +#include +#include +#include "retroshare/rstypes.h" + +class ostream; + +/****************************************************************************************** + * The Key Data Types for the File Index: + + FileEntry : Information about a single file. + DirEntry : Information about a directory and its children + PersonEntry : Information the root of a FileIndex. + + FileIndex : A Collection of root directories, with a set of functions to manipulate them. + In terms of retroshare, There will be a single 'Local' FileIndex used to store + the shared files, and a set of 'Remote' FileIndices which are used to store + the available files of all the peers. + +******************************************************************************************/ +/****************************************************************************************** + STILL TODO: + + (1) Load/Store a FileIndex to file... + int FileIndex::loadIndex(FILE *input); + int FileIndex::saveIndex(FILE *input); + + This can be done in a recursive manner, or handled completely within FileIndex. + + (2) Search Functions for Partial File Names and Hashes. + + int FileIndex::searchHash(std::string hash, std::list &results); + int FileIndex::searchTerms(std::list terms, std::list &results); + + This is probably best done in a recursive manner. + + The search could also be extended to handle complex Boolean searches such as : + match (size > 100K) && (name contains 'Blue') .... if anyone is interested. + But this can get quite complicated, and can be left to a later date. + +******************************************************************************************/ + + +/****************************************************************************************** + * FileEntry + *****************************************************************************************/ + +#include + +class DirEntry; + +class FileEntry: public RsMemoryManagement::SmallObject +{ + public: + FileEntry() + : size(0), modtime(0), pop(0), updtime(0), parent(NULL), row(0) + { return; } + + virtual ~FileEntry() { return; } + virtual uint32_t type() const { return DIR_TYPE_FILE ; } + +virtual int print(std::ostream &out); + + /* Data */ + std::string name; + std::string hash; + uint64_t size; /* file size */ + time_t modtime; /* modification time - most recent mod time for a sub entry for dirs */ + int pop; /* popularity rating */ + + time_t updtime; /* last updated */ + + /* References for easy manipulation */ + DirEntry *parent; + int row; +}; + +/****************************************************************************************** + * DirEntry + *****************************************************************************************/ + +class DirEntry: public FileEntry +{ + public: + + DirEntry() : most_recent_time(0) {} + /* cleanup */ +virtual ~DirEntry(); + + /* update local entries */ +DirEntry * updateDir(const FileEntry& fe, time_t updtime); +FileEntry * updateFile(const FileEntry& fe, time_t updtime); + + + virtual uint32_t type() const { return DIR_TYPE_DIR ; } +int checkParentPointers(); +int updateChildRows(); + + /* remove local entries */ +int removeFile(const std::string& name); +int removeDir(const std::string& name); +int removeOldDir(const std::string& name, time_t old); /* checks ts first */ + + /* recursive cleanup */ +int removeOldEntries(time_t old, bool recursive); + + /* recursive searches */ +DirEntry * findOldDirectory(time_t old); +DirEntry * findDirectory(const std::string& path); + + /* recursive update directory mod/pop values */ +int updateDirectories(const std::string& path, int pop, int modtime); + + /* output */ +int print(std::ostream &out); + +int saveEntry(std::ostringstream &out); +void writeDirInfo(std::ostringstream&); +void writeFileInfo(std::ostringstream&); + + /* Data */ + std::string path; /* full path (includes name) */ + std::map subdirs; + std::map files; + + time_t most_recent_time; /* last updated */ + + /* Inherited members from FileEntry: + int size - count for dirs + std::string name; - directory name + std::string hash; - not used + int size; - not used + int modtime; - most recent modication time of any child file (recursive) + int pop; - most popular child file (recursive) + int updtime; - last updated + */ + +}; + +/****************************************************************************************** + * PersonEntry + *****************************************************************************************/ + +class PersonEntry: public DirEntry +{ + public: + /* cleanup */ + PersonEntry(const std::string& pid) : id(pid) { return; } +virtual ~PersonEntry() { return; } + +DirEntry &operator=(DirEntry &src) +{ + DirEntry *pdest = this; + (*pdest) = src; + return *this; +} + virtual uint32_t type() const { return DIR_TYPE_PERSON ; } + + /* Data */ + std::string id; + + /* Inherited members from FileEntry: + int size - count for dirs + std::string name; - directory name + std::string hash; - not used + int size; - not used + int modtime; - most recent modication time of any child file (recursive) + int pop; - most popular child file (recursive) + int updtime; - last updated + */ + +}; + +/****************************************************************************************** + * FileIndex + *****************************************************************************************/ + +class Expression; + +class FileIndex +{ + public: + FileIndex(const std::string& pid); + ~FileIndex(); + + /* control root entries */ + int setRootDirectories(const std::list &inlist, time_t utime); + int getRootDirectories(std::list &outlist); + + /* update (index building) */ + DirEntry * updateDirEntry(const std::string& path, const FileEntry& fe, time_t utime); + FileEntry * updateFileEntry(const std::string& path, const FileEntry& fe, time_t utime); + + DirEntry * findOldDirectory(time_t old); /* finds directories older than old */ + int removeOldDirectory(const std::string& fpath, const std::string& name, time_t old); + + int cleanOldEntries(time_t old); /* removes entries older than old */ + + /* debug */ + int printFileIndex(std::ostream &out); + + /* load/save to file */ + int loadIndex(const std::string& filename, const std::string& expectedHash, uint64_t size); + int saveIndex(const std::string& filename, std::string &fileHash, uint64_t &size, const std::set& forbidden_roots); + + /* search through this index */ + int searchTerms(const std::list& terms, std::list &results) const; + int searchHash(const std::string& hash, std::list &results) const; + int searchBoolExp(Expression * exp, std::list &results) const; + + /// Recursively compute the maximum modification time of children. + /// Used to easily retrieve mose recent files. + // + void updateMaxModTime() ; + void RecursUpdateMaxModTime(DirEntry *) ; + + PersonEntry *root; + + static std::tr1::unordered_set _pointers ; + static void registerEntry(void*p) ; + static void unregisterEntry(void*p) ; + static bool isValid(void*p) ; + + /// Fills up details from the data contained in ref. + // + static bool extractData(void *ref,DirDetails& details) ; + static uint32_t getType(void *ref) ; +}; + + +#endif + diff --git a/libretroshare/src/dbase/fistore.cc b/libretroshare/src/dbase/fistore.cc new file mode 100644 index 000000000..7b2d1de1d --- /dev/null +++ b/libretroshare/src/dbase/fistore.cc @@ -0,0 +1,431 @@ +/* + * RetroShare FileCache Module: fistore.cc + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "dbase/fistore.h" +#include "retroshare/rsexpr.h" +#include "serialiser/rsserviceids.h" +#include "pqi/p3connmgr.h" + +FileIndexStore::FileIndexStore(CacheStrapper *cs, CacheTransfer *cft, + NotifyBase *cb_in,p3ConnectMgr *cnmgr, RsPeerId ownid, std::string cachedir) + :CacheStore(RS_SERVICE_TYPE_FILE_INDEX, false, cs, cft, cachedir), + localId(ownid), localindex(NULL), cb(cb_in),mConnMgr(cnmgr) +{ + return; +} + +FileIndexStore::~FileIndexStore() +{ + /* clean up the Index */ + return; +} + +/*** + * #define FIS_DEBUG2 1 + * #define FIS_DEBUG 1 + **/ + + /* actual load, once data available */ +int FileIndexStore::loadCache(const CacheData &data) +{ + +#ifdef FIS_DEBUG2 + std::cerr << "FileIndexStore::loadCache() hash: " << data.hash << std::endl; + std::cerr << "FileIndexStore::loadCache() path: " << data.path << std::endl; + std::cerr << "FileIndexStore::loadCache() name: " << data.name << std::endl; + std::cerr << "FileIndexStore::loadCache() size: " << data.size << std::endl; +#endif + + /* do Callback */ + AboutToModify(); + + /* lock it up */ + lockData(); + + FileIndex *fiold = NULL; + bool local = (data.pid == localId); + + std::map::iterator it; + /* remove old cache */ + if (local) + { + fiold = localindex; + localindex = NULL; + } + else if (indices.end() != (it = indices.find(data.pid))) + { + fiold = it->second; + indices.erase(it); + //delete fi; + } + + /* load Cache */ + + FileIndex *finew = new FileIndex(data.pid); + + if(mConnMgr->isFriend(data.pid)) + { + // We discard file lists from non friends. This is the place to remove file lists of deleted friends + // from the cache. Doing this, the file list still shows in a session where we deleted a friend, but will be removed + // at next restart. + // + if (finew->loadIndex(data.path + '/' + data.name, data.hash, data.size)) + { +#ifdef FIS_DEBUG2 + std::cerr << "FileIndexStore::loadCache() Succeeded!" << std::endl; +#endif + /* set the name */ + finew->root->name = data.pname; + + if (local) + { + localindex = finew; + } + else + { + indices[data.pid] = finew; + } + delete fiold; + + /* store in tale */ + locked_storeCacheEntry(data); + } + else + { +#ifdef FIS_DEBUG2 + std::cerr << "FileIndexStore::loadCache() Failed!" << std::endl; +#endif + /* reinstall the old one! */ + delete finew; + if (fiold) + { + if (local) + { + localindex = fiold; + } + else + { + indices[data.pid] = fiold; + } + } + } + } +#ifdef FIS_DEBUG + else + std::cerr << "Discarding file list from deleted peer " << data.pid << std::endl ; +#endif + + /* need to correct indices(row) for the roots of the FileIndex */ + int i = 0; + for(it = indices.begin(); it != indices.end(); it++) + { + (it->second)->root->row = i++; + it->second->FileIndex::updateMaxModTime() ; + } + if (localindex) + { + localindex->root->row = 0; + localindex->updateMaxModTime() ; + } + + unlockData(); + + ModCompleted(); + bool ret = false; + return ret; +} + + + /* Search Interface - For Directory Access */ +int FileIndexStore::RequestDirDetails(std::string uid, std::string path, DirDetails &details) const +{ + /* lock it up */ + lockData(); + + std::map::const_iterator it; + it = indices.find(uid); + bool found = true; + if (it == indices.end()) + { + //DirEntry *fdir = (it->second).lookupDirectory(path); + /* translate it + */ + found = false; + } + else + { + found = false; + } + + unlockData(); + return found; +} + +int FileIndexStore::RequestDirDetails(void *ref, DirDetails &details, uint32_t flags) const +{ +#ifdef FIS_DEBUG + std::cerr << "FileIndexStore::RequestDirDetails() ref=" << ref << " flags: " << flags << std::endl; +#endif + + std::map::const_iterator pit; + + lockData(); + +// checked by FileIndex::extractData +// if(ref != NULL && !FileIndex::isValid(ref)) +// { +// unlockData() ; +// return false ; +// } + + /* so cast *ref to a DirEntry */ + /* root case */ + +#ifdef FIS_DEBUG + std::cerr << "FileIndexStore::RequestDirDetails() CHKS" << std::endl; + for(pit = indices.begin(); pit != indices.end(); pit++) + { + (pit->second)->root->checkParentPointers(); + } +#endif + + if (ref == NULL) + { +#ifdef FIS_DEBUG + std::cerr << "FileIndexStore::RequestDirDetails() ref=NULL (root)" << std::endl; +#endif + + /* get remote root entries */ + for(pit = indices.begin(); pit != indices.end(); pit++) + { + /* + */ + DirStub stub; + stub.type = DIR_TYPE_PERSON; + stub.name = (pit->second)->root->name; + stub.ref = (pit->second)->root; + + details.children.push_back(stub); + } + details.parent = NULL; + details.prow = -1; + details.ref = NULL; + details.type = DIR_TYPE_ROOT; + details.name = ""; + details.hash = ""; + details.path = ""; + details.count = indices.size(); + details.age = 0; + details.flags = 0; + details.min_age = 0; + + unlockData(); + return true ; + } + + bool b = FileIndex::extractData(ref,details) ; + + unlockData(); + return b; +} +uint32_t FileIndexStore::getType(void *ref) const +{ + lockData() ; + uint32_t b = FileIndex::getType(ref) ; + unlockData(); + + return b; +} + +int FileIndexStore::SearchHash(std::string hash, std::list &results) const +{ + lockData(); + results.clear() ; + std::map::const_iterator pit; + std::list::iterator rit; + std::list firesults; + + time_t now = time(NULL); + +#ifdef FIS_DEBUG + std::cerr << "FileIndexStore::SearchHash()" << std::endl; +#endif + for(pit = indices.begin(); pit != indices.end(); pit++) + { +#ifdef FIS_DEBUG + std::cerr << "FileIndexStore::SearchHash() Searching: Peer "; + std::cerr << pit->first << std::endl; +#endif + firesults.clear(); + + (pit->second)->searchHash(hash, firesults); + /* translate results */ + for(rit = firesults.begin(); rit != firesults.end(); rit++) + { + FileDetail fd; + fd.id = pit->first; + fd.name = (*rit)->name; + fd.hash = (*rit)->hash; + fd.path = ""; /* TODO */ + fd.size = (*rit)->size; + fd.age = now - (*rit)->modtime; + fd.rank = (*rit)->pop; + + results.push_back(fd); + } + + } + + +#ifdef FIS_DEBUG + std::cerr << "FileIndexStore::SearchHash() Found " << results.size(); + std::cerr << " Results from " << indices.size() << " Peers" << std::endl; +#endif + + unlockData(); + return results.size(); +} + + +int FileIndexStore::SearchKeywords(std::list keywords, std::list &results,uint32_t flags) const +{ + lockData(); + std::map::const_iterator pit; + std::list::iterator rit; + std::list firesults; + + results.clear() ; + +#ifdef FIS_DEBUG + std::cerr << "FileIndexStore::SearchKeywords()" << std::endl; +#endif + if(flags & DIR_FLAGS_REMOTE) + for(pit = indices.begin(); pit != indices.end(); pit++) + { + firesults.clear(); + + (pit->second)->searchTerms(keywords, firesults); + /* translate results */ + for(rit = firesults.begin(); rit != firesults.end(); rit++) + { + DirDetails dd; + + if(!FileIndex::extractData(*rit, dd)) + continue ; + + results.push_back(dd); + } + } + + if(flags & DIR_FLAGS_LOCAL) + if (localindex) + { + firesults.clear(); + + localindex->searchTerms(keywords, firesults); + /* translate results */ + for(rit = firesults.begin(); rit != firesults.end(); rit++) + { + DirDetails dd; + + if(!FileIndex::extractData(*rit, dd)) + continue ; + + dd.id = "Local"; + results.push_back(dd); + } + + } + + unlockData(); + return results.size(); +} + + +int FileIndexStore::searchBoolExp(Expression * exp, std::list &results) const +{ + lockData(); + std::map::const_iterator pit; + std::list::iterator rit; + std::list firesults; + +#ifdef FIS_DEBUG + std::cerr << "FileIndexStore::searchBoolExp()" << std::endl; +#endif + for(pit = indices.begin(); pit != indices.end(); pit++) + { + firesults.clear(); + + (pit->second)->searchBoolExp(exp, firesults); + + /* translate results */ + for(rit = firesults.begin(); rit != firesults.end(); rit++) + { + DirDetails dd; + FileIndex::extractData(*rit, dd); + results.push_back(dd); + } + + } + + /* finally search local files */ + if (localindex) + { + firesults.clear(); + + localindex->searchBoolExp(exp, firesults); + + /* translate results */ + for(rit = firesults.begin(); rit != firesults.end(); rit++) + { + DirDetails dd; + FileIndex::extractData(*rit, dd); + dd.id = "Local"; + results.push_back(dd); + } + + } + + + unlockData(); + return results.size(); +} + +int FileIndexStore::AboutToModify() +{ + if (cb) + cb->notifyListPreChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0); + + return 1; +} + + +int FileIndexStore::ModCompleted() +{ + if (cb) + cb->notifyListChange(NOTIFY_LIST_DIRLIST_FRIENDS, 0); + + return 1; +} + + diff --git a/libretroshare/src/dbase/fistore.h b/libretroshare/src/dbase/fistore.h new file mode 100644 index 000000000..f42ae7f65 --- /dev/null +++ b/libretroshare/src/dbase/fistore.h @@ -0,0 +1,103 @@ +/* + * RetroShare FileCache Module: fistore.h + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_FILE_INDEX_STORE_H +#define MRK_FILE_INDEX_STORE_H + + +/********** + * Stores the FileCaches of the Peers + * must implement 'loadCache' to + * + * This class is also accessed by the GUI.... + * and the FileTransfer class. + * + */ + +class p3ConnectMgr ; + +#include "dbase/findex.h" +#include "dbase/cachestrapper.h" +#include "retroshare/rsiface.h" + +class FileStoreResult +{ + public: + std::string id; + std::string path; + std::string hash; + std::string name; +}; + +class NotifyCallback +{ + public: + NotifyCallback() { return; } +virtual ~NotifyCallback() { return; } +virtual void AboutToModify() { return; } +virtual void ModCompleted() { return; } +}; + + +class Expression; + +class FileIndexStore: public CacheStore +{ + public: + + FileIndexStore(CacheStrapper *cs, CacheTransfer *cft, NotifyBase *cb_in,p3ConnectMgr *cmgr, RsPeerId ownid, std::string cachedir); +virtual ~FileIndexStore(); + + /* virtual functions overloaded by cache implementor */ +virtual int loadCache(const CacheData &data); /* actual load, once data available */ + + /* Search Interface - For FileTransfer Lookup */ + int SearchHash(std::string hash, std::list &results) const; + + /* Search Interface - For Search Interface */ + int SearchKeywords(std::list terms, std::list &results,uint32_t flags) const; + + /* Search Interface - for Adv Search Interface */ + int searchBoolExp(Expression * exp, std::list &results) const; + + + /* Search Interface - For Directory Access */ + int RequestDirDetails(std::string uid, std::string path, DirDetails &details) const; + int RequestDirDetails(void *ref, DirDetails &details, uint32_t flags) const; + uint32_t getType(void *ref) const ; + + private: + int AboutToModify(); + int ModCompleted(); + + std::map indices; + + RsPeerId localId; + FileIndex *localindex; + + NotifyBase *cb; + p3ConnectMgr *mConnMgr ; +}; + + +#endif diff --git a/libretroshare/src/dbase/rsexpr.cc b/libretroshare/src/dbase/rsexpr.cc new file mode 100644 index 000000000..8cd781d1c --- /dev/null +++ b/libretroshare/src/dbase/rsexpr.cc @@ -0,0 +1,289 @@ +/* + * rs-core/src/dbase: rsexpr.cc + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Kashif Kaleem. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "dbase/findex.h" +#include "retroshare/rsexpr.h" +#include +#include + +/****************************************************************************************** +eval functions of relational expressions. + +******************************************************************************************/ + +template<> +void RelExpression::linearize(LinearizedExpression& e) const +{ + e._ints.push_back(Op) ; + e._ints.push_back(LowerValue) ; + e._ints.push_back(HigherValue) ; +} + + +bool DateExpression::eval(FileEntry *file) +{ + return evalRel(file->modtime); +} + +bool SizeExpressionMB::eval(FileEntry *file) +{ + return evalRel((int)(file->size/(uint64_t)(1024*1024))); +} + +bool SizeExpression::eval(FileEntry *file) +{ + return evalRel(file->size); +} + +bool PopExpression::eval(FileEntry *file) +{ + return evalRel(file->pop); +} + +/****************************************************************************************** +Code for evaluating string expressions + +******************************************************************************************/ + +bool NameExpression::eval(FileEntry *file) +{ + return evalStr(file->name); +} + +bool PathExpression::eval(FileEntry *file){ + std::string path; + /*Construct the path of this file*/ + DirEntry * curr = file->parent; + while ( curr != NULL ){ + path = curr->name+"/"+ path; + curr = curr->parent; + } + return evalStr(path); +} + +bool ExtExpression::eval(FileEntry *file){ + std::string ext; + /*Get the part of the string after the last instance of . in the filename */ + size_t index = file->name.find_last_of('.'); + if (index != std::string::npos) { + ext = file->name.substr(index+1); + if (ext != "" ){ + return evalStr(ext); + } + } + return false; +} + +bool HashExpression::eval(FileEntry *file){ + return evalStr(file->hash); +} + +/*Check whether two strings are 'equal' to each other*/ +static bool StrEquals(const std::string & str1, const std::string & str2, + bool IgnoreCase ){ + if ( str1.size() != str2.size() ){ + return false; + } else if (IgnoreCase) { + std::equal( str1.begin(), str1.end(), + str2.begin(), CompareCharIC() ); + } + return std::equal( str1.begin(), str1.end(), + str2.begin()); +} + +/*Check whether one string contains the other*/ +static bool StrContains( std::string & str1, std::string & str2, + bool IgnoreCase){ + + std::string::const_iterator iter ; + if (IgnoreCase) { + iter = std::search( str1.begin(), str1.end(), + str2.begin(), str2.end(), CompareCharIC() ); + } else { + iter = std::search( str1.begin(), str1.end(), + str2.begin(), str2.end()); + } + + return ( iter != str1.end() ); +} + + +bool StringExpression :: evalStr ( std::string &str ){ + std::list::iterator iter; + switch (Op) { + case ContainsAllStrings: + for ( iter = terms.begin(); iter != terms.end(); iter++ ) { + if ( StrContains (str, *iter, IgnoreCase) == false ){ + return false; + } + } + return true; + break; + case ContainsAnyStrings: + for ( iter = terms.begin(); iter != terms.end(); iter++ ) { + if ( StrContains (str,*iter, IgnoreCase) == true ) { + return true; + } + } + break; + case EqualsString: + for ( iter = terms.begin(); iter != terms.end(); iter++ ) { + if ( StrEquals (str,*iter, IgnoreCase) == true ) { + return true; + } + } + break; + default: + return false; + } + return false; +} + +/************************************************************************* + * linearization code + *************************************************************************/ + +void CompoundExpression::linearize(LinearizedExpression& e) const +{ + e._tokens.push_back(LinearizedExpression::EXPR_COMP) ; + e._ints.push_back(Op) ; + + Lexp->linearize(e) ; + Rexp->linearize(e) ; +} + +void StringExpression::linearize(LinearizedExpression& e) const +{ + e._ints.push_back(Op) ; + e._ints.push_back(IgnoreCase) ; + e._ints.push_back(terms.size()) ; + + for(std::list::const_iterator it(terms.begin());it!=terms.end();++it) + e._strings.push_back(*it) ; +} + +Expression *LinearizedExpression::toExpr(const LinearizedExpression& e) +{ + int i=0,j=0,k=0 ; + return toExpr(e,i,j,k) ; +} + +void LinearizedExpression::readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list& strings,bool& b,StringOperator& op) +{ + op = static_cast(e._ints[n_ints++]) ; + b = e._ints[n_ints++] ; + int n = e._ints[n_ints++] ; + + strings.clear() ; + for(int i=0;i(e._tokens[n_tok++]) ; + + switch(tok) + { + case EXPR_DATE: { + RelOperator op = static_cast(e._ints[n_ints++]) ; + int lv = e._ints[n_ints++] ; + int hv = e._ints[n_ints++] ; + + return new DateExpression(op,lv,hv) ; + } + + case EXPR_POP: { + RelOperator op = static_cast(e._ints[n_ints++]) ; + int lv = e._ints[n_ints++] ; + int hv = e._ints[n_ints++] ; + + return new PopExpression(op,lv,hv) ; + } + case EXPR_SIZE: { + RelOperator op = static_cast(e._ints[n_ints++]) ; + int lv = e._ints[n_ints++] ; + int hv = e._ints[n_ints++] ; + + return new SizeExpression(op,lv,hv) ; + } + case EXPR_HASH: { + std::list strings ; + StringOperator op ; + bool b ; + + readStringExpr(e,n_ints,n_strings,strings,b,op) ; + return new HashExpression(op,strings) ; + } + case EXPR_NAME: { + std::list strings ; + StringOperator op ; + bool b ; + + readStringExpr(e,n_ints,n_strings,strings,b,op) ; + + return new NameExpression(op,strings,b) ; + } + case EXPR_PATH: { + std::list strings ; + StringOperator op ; + bool b ; + + readStringExpr(e,n_ints,n_strings,strings,b,op) ; + + return new ExtExpression(op,strings,b) ; + } + case EXPR_EXT: { + std::list strings ; + StringOperator op ; + bool b ; + + readStringExpr(e,n_ints,n_strings,strings,b,op) ; + + return new ExtExpression(op,strings,b) ; + } + case EXPR_COMP: { + LogicalOperator op = static_cast(e._ints[n_ints++]) ; + + Expression *e1 = toExpr(e,n_tok,n_ints,n_strings) ; + Expression *e2 = toExpr(e,n_tok,n_ints,n_strings) ; + + return new CompoundExpression(op,e1,e2) ; + } + case EXPR_SIZE_MB: { + RelOperator op = static_cast(e._ints[n_ints++]) ; + int lv = e._ints[n_ints++] ; + int hv = e._ints[n_ints++] ; + + return new SizeExpressionMB(op,lv,hv) ; + } + default: + std::cerr << "No expression match the current value " << tok << std::endl ; + return NULL ; + } +} + + diff --git a/libretroshare/src/dht/p3bitdht.cc b/libretroshare/src/dht/p3bitdht.cc new file mode 100644 index 000000000..82e14a663 --- /dev/null +++ b/libretroshare/src/dht/p3bitdht.cc @@ -0,0 +1,685 @@ +/* + * libretroshare/src/dht: p3bitdht.h + * + * BitDht interface for RetroShare. + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "dht/p3bitdht.h" + +#include "bitdht/bdstddht.h" +#include "pqi/p3connmgr.h" + +#include + + +/* This is a conversion callback class between pqi interface + * and the BitDht Interface. + * + */ + +class p3BdCallback: public BitDhtCallback +{ + public: + + p3BdCallback(p3BitDht *parent) + :mParent(parent) { return; } + +virtual int dhtNodeCallback(const bdId *id, uint32_t peerflags) +{ + return mParent->NodeCallback(id, peerflags); +} + +virtual int dhtPeerCallback(const bdId *id, uint32_t status) +{ + return mParent->PeerCallback(id, status); +} + +virtual int dhtValueCallback(const bdNodeId *id, std::string key, uint32_t status) +{ + return mParent->ValueCallback(id, key, status); +} + +virtual int dhtConnectCallback(const bdId *srcId, const bdId *proxyId, const bdId *destId, + uint32_t mode, uint32_t point, uint32_t cbtype, uint32_t errcode) +{ + return 0; +} + + private: + + p3BitDht *mParent; +}; + + +p3BitDht::p3BitDht(std::string id, pqiConnectCb *cb, UdpStack *udpstack, std::string bootstrapfile) + :pqiNetAssistConnect(id, cb) +{ + std::string dhtVersion = "RS51"; // should come from elsewhere! + bdNodeId ownId; + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::p3BitDht()" << std::endl; + std::cerr << "Using Id: " << id; + std::cerr << std::endl; + std::cerr << "Using Bootstrap File: " << bootstrapfile; + std::cerr << std::endl; + std::cerr << "Converting OwnId to bdNodeId...."; + std::cerr << std::endl; +#endif + + /* setup ownId */ + storeTranslation(id); + lookupNodeId(id, &ownId); + + +#ifdef DEBUG_BITDHT + std::cerr << "Own NodeId: "; + bdStdPrintNodeId(std::cerr, &ownId); + std::cerr << std::endl; +#endif + + /* standard dht behaviour */ + bdDhtFunctions *stdfns = new bdStdDht(); + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht() startup ... creating UdpBitDht"; + std::cerr << std::endl; +#endif + + /* create dht */ + mUdpBitDht = new UdpBitDht(udpstack, &ownId, dhtVersion, bootstrapfile, stdfns); + udpstack->addReceiver(mUdpBitDht); + + /* setup callback to here */ + p3BdCallback *bdcb = new p3BdCallback(this); + mUdpBitDht->addCallback(bdcb); + +} + +p3BitDht::~p3BitDht() +{ + //udpstack->removeReceiver(mUdpBitDht); + delete mUdpBitDht; +} + +void p3BitDht::start() +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::start()"; + std::cerr << std::endl; +#endif + + mUdpBitDht->start(); /* starts up the bitdht thread */ + + /* dht switched on by config later. */ +} + + /* pqiNetAssist - external interface functions */ +void p3BitDht::enable(bool on) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::enable(" << on << ")"; + std::cerr << std::endl; +#endif + + if (on) + { + mUdpBitDht->startDht(); + } + else + { + mUdpBitDht->stopDht(); + } +} + +void p3BitDht::shutdown() /* blocking call */ +{ + mUdpBitDht->stopDht(); +} + + +void p3BitDht::restart() +{ + mUdpBitDht->stopDht(); + mUdpBitDht->startDht(); +} + +bool p3BitDht::getEnabled() +{ + return (mUdpBitDht->stateDht() != 0); +} + +bool p3BitDht::getActive() +{ + return (mUdpBitDht->stateDht() >= BITDHT_MGR_STATE_ACTIVE); +} + +bool p3BitDht::getNetworkStats(uint32_t &netsize, uint32_t &localnetsize) +{ + netsize = mUdpBitDht->statsNetworkSize(); + localnetsize = mUdpBitDht->statsBDVersionSize(); + return true; +} + + /* pqiNetAssistConnect - external interface functions */ + /* add / remove peers */ +bool p3BitDht::findPeer(std::string pid) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::findPeer(" << pid << ")"; + std::cerr << std::endl; +#endif + + /* convert id -> NodeId */ + if (!storeTranslation(pid)) + { + std::cerr << "p3BitDht::findPeer() Failed to storeTranslation"; + std::cerr << std::endl; + + /* error */ + return false; + } + + bdNodeId nid; + if (!lookupNodeId(pid, &nid)) + { + std::cerr << "p3BitDht::findPeer() Failed to lookupNodeId"; + std::cerr << std::endl; + + /* error */ + return false; + } + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::findPeer() calling AddFindNode() with pid => NodeId: "; + bdStdPrintNodeId(std::cerr, &nid); + std::cerr << std::endl; +#endif + + /* add in peer */ + mUdpBitDht->addFindNode(&nid, BITDHT_QFLAGS_DO_IDLE); + + return true ; +} + +bool p3BitDht::dropPeer(std::string pid) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::dropPeer(" << pid << ")"; + std::cerr << std::endl; +#endif + + /* convert id -> NodeId */ + bdNodeId nid; + if (!lookupNodeId(pid, &nid)) + { + std::cerr << "p3BitDht::dropPeer() Failed to lookup NodeId"; + std::cerr << std::endl; + + /* error */ + return false; + } + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::dropPeer() Translated to NodeId: "; + bdStdPrintNodeId(std::cerr, &nid); + std::cerr << std::endl; +#endif + + /* remove in peer */ + mUdpBitDht->removeFindNode(&nid); + + /* remove from translation */ + if (!removeTranslation(pid)) + { + std::cerr << "p3BitDht::dropPeer() Failed to removeTranslation"; + std::cerr << std::endl; + + /* error */ + return false; + } + + return true ; +} + + /* extract current peer status */ +bool p3BitDht::getPeerStatus(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t &type, uint32_t &mode) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::getPeerStatus(" << id << ")"; + std::cerr << std::endl; +#endif + + + return false; +} + +bool p3BitDht::getExternalInterface(struct sockaddr_in &raddr, + uint32_t &mode) +{ + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::getExternalInterface()"; + std::cerr << std::endl; +#endif + + + return false; +} + + +/* Adding a little bit of fixed test... + * This allows us to ensure that only compatible peers will find each other + */ + +const uint8_t RS_DHT_VERSION_LEN = 17; +const uint8_t rs_dht_version_data[RS_DHT_VERSION_LEN] = "RS_VERSION_0.5.1"; + +/******************** Conversion Functions **************************/ +int p3BitDht::calculateNodeId(const std::string pid, bdNodeId *id) +{ + /* generate node id from pid */ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::calculateNodeId() " << pid; +#endif + + /* use a hash to make it impossible to reverse */ + + uint8_t sha_hash[SHA_DIGEST_LENGTH]; + memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ; + SHA_CTX *sha_ctx = new SHA_CTX; + SHA1_Init(sha_ctx); + + SHA1_Update(sha_ctx, rs_dht_version_data, RS_DHT_VERSION_LEN); + SHA1_Update(sha_ctx, pid.c_str(), pid.length()); + SHA1_Final(sha_hash, sha_ctx); + + for(int i = 0; i < SHA_DIGEST_LENGTH && (i < BITDHT_KEY_LEN); i++) + { + id->data[i] = sha_hash[i]; + } + delete sha_ctx; + +#ifdef DEBUG_BITDHT + std::cerr << " => "; + bdStdPrintNodeId(std::cerr, id); + std::cerr << std::endl; +#endif + + return 1; +} + +int p3BitDht::lookupNodeId(const std::string pid, bdNodeId *id) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::lookupNodeId() for : " << pid; + std::cerr << std::endl; +#endif + + RsStackMutex stack(dhtMtx); + + std::map::iterator it; + it = mTransToNodeId.find(pid); + if (it == mTransToNodeId.end()) + { +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::lookupNodeId() failed"; + std::cerr << std::endl; +#endif + + return 0; + } + *id = it->second; + + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::lookupNodeId() Found NodeId: "; + bdStdPrintNodeId(std::cerr, id); + std::cerr << std::endl; +#endif + + return 1; +} + + +int p3BitDht::lookupRsId(const bdNodeId *id, std::string &pid) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::lookupRsId() for : "; + bdStdPrintNodeId(std::cerr, id); + std::cerr << std::endl; +#endif + + RsStackMutex stack(dhtMtx); + + std::map::iterator nit; + nit = mTransToRsId.find(*id); + if (nit == mTransToRsId.end()) + { +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::lookupRsId() failed"; + std::cerr << std::endl; +#endif + + return 0; + } + pid = nit->second; + + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::lookupRsId() Found Matching RsId: " << pid; + std::cerr << std::endl; +#endif + + return 1; +} + +int p3BitDht::storeTranslation(const std::string pid) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::storeTranslation(" << pid << ")"; + std::cerr << std::endl; +#endif + + bdNodeId nid; + calculateNodeId(pid, &nid); + + RsStackMutex stack(dhtMtx); + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::storeTranslation() Converts to NodeId: "; + bdStdPrintNodeId(std::cerr, &(nid)); + std::cerr << std::endl; +#endif + + mTransToNodeId[pid] = nid; + mTransToRsId[nid] = pid; + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::storeTranslation() Success"; + std::cerr << std::endl; +#endif + + return 1; +} + +int p3BitDht::removeTranslation(const std::string pid) +{ + RsStackMutex stack(dhtMtx); + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::removeTranslation(" << pid << ")"; + std::cerr << std::endl; +#endif + + std::map::iterator it = mTransToNodeId.find(pid); + it = mTransToNodeId.find(pid); + if (it == mTransToNodeId.end()) + { + std::cerr << "p3BitDht::removeTranslation() ERROR MISSING TransToNodeId"; + std::cerr << std::endl; + /* missing */ + return 0; + } + + bdNodeId nid = it->second; + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::removeTranslation() Found Translation: NodeId: "; + bdStdPrintNodeId(std::cerr, &(nid)); + std::cerr << std::endl; +#endif + + + std::map::iterator nit; + nit = mTransToRsId.find(nid); + if (nit == mTransToRsId.end()) + { + std::cerr << "p3BitDht::removeTranslation() ERROR MISSING TransToRsId"; + std::cerr << std::endl; + /* inconsistent!!! */ + return 0; + } + + mTransToNodeId.erase(it); + mTransToRsId.erase(nit); + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::removeTranslation() SUCCESS"; + std::cerr << std::endl; +#endif + + return 1; +} + + +/********************** Callback Functions **************************/ +uint32_t translatebdcbflgs(uint32_t peerflags); + +int p3BitDht::NodeCallback(const bdId *id, uint32_t peerflags) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::NodeCallback()"; + std::cerr << std::endl; +#endif + + // XXX THIS IS A BAD HACK TO PREVENT connection attempt to MEDIASENTRY (dht spies) + // peers... These peers appear to masquerade as your OwnNodeId!!!! + // which means peers could attempt to connect too?? not sure about this? + // Anyway they don't appear to REPLY to FIND_NODE requests... + // So if we ignore these peers, we'll only get the true RS peers! + + // This should be fixed by a collaborative IP filter system, + // EACH peer identifies dodgey IP (ones spoofing yourself), and shares them + // This are distributed around RS via a service, and the UDP ignores + // all comms from these sources. (AT a low level). + + if (peerflags != BITDHT_PEER_STATUS_RECV_NODES) + { + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::NodeCallback() Ignoring !FIND_NODE callback from:"; + bdStdPrintNodeId(std::cerr, &(id->id)); + std::cerr << " flags: " << peerflags; + std::cerr << std::endl; +#endif + + return 0; + } + + /* is it one that we are interested in? */ + std::string pid; + /* check for translation */ + if (lookupRsId(&(id->id), pid)) + { +#ifdef DEBUG_BITDHT + /* we found it ... do callback to p3connmgr */ + std::cerr << "p3BitDht::NodeCallback() FOUND NODE!!!: "; + bdStdPrintNodeId(std::cerr, &(id->id)); + std::cerr << "-> " << pid << " flags: " << peerflags; + std::cerr << std::endl; +#endif + /* send status info to p3connmgr */ + + + + pqiIpAddress dhtpeer; + dhtpeer.mSrc = RS_CB_DHT; + dhtpeer.mSeenTime = time(NULL); + dhtpeer.mAddr = id->addr; + + pqiIpAddrSet addrs; + addrs.updateExtAddrs(dhtpeer); + + uint32_t type = RS_NET_CONN_UDP_DHT_SYNC; + uint32_t flags = translatebdcbflgs(peerflags); + uint32_t source = RS_CB_DHT; + + mConnCb->peerStatus(pid, addrs, type, flags, source); + + return 1; + } + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::NodeCallback() FAILED TO FIND NODE: "; + bdStdPrintNodeId(std::cerr, &(id->id)); + std::cerr << std::endl; +#endif + + return 0; +} +uint32_t translatebdcbflgs(uint32_t peerflags) +{ + uint32_t outflags = 0; + outflags |= RS_NET_FLAGS_ONLINE; + return outflags; +#if 0 + + // The input flags. +#define BITDHT_PEER_STATUS_RECV_PONG 0x00000001 +#define BITDHT_PEER_STATUS_RECV_NODES 0x00000002 +#define BITDHT_PEER_STATUS_RECV_HASHES 0x00000004 + +#define BITDHT_PEER_STATUS_DHT_ENGINE 0x00000100 +#define BITDHT_PEER_STATUS_DHT_APPL 0x00000200 +#define BITDHT_PEER_STATUS_DHT_VERSION 0x00000400 + + if (peerflags & ONLINE) + { + outflags |= RS_NET_FLAGS_ONLINE; + } + if (peerflags & ONLINE) + { + outflags |= RS_NET_FLAGS_EXTERNAL_ADDR | RS_NET_FLAGS_STABLE_UDP; + } +#endif +} + + +int p3BitDht::PeerCallback(const bdId *id, uint32_t status) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::PeerCallback() bdId: "; + bdStdPrintId(std::cerr, id); + std::cerr << std::endl; +#endif + + /* is it one that we are interested in? */ + std::string pid; + /* check for translation */ + if (lookupRsId(&(id->id), pid)) + { +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::PeerCallback() => RsId: "; + std::cerr << pid << " status: " << status; + std::cerr << " NOOP for NOW"; + std::cerr << std::endl; +#endif + + bool connect = false; + switch(status) + { + case BITDHT_MGR_QUERY_FAILURE: + /* do nothing */ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::PeerCallback() QUERY FAILURE ... do nothin "; + std::cerr << std::endl; +#endif + + break; + + case BITDHT_MGR_QUERY_PEER_OFFLINE: + /* do nothing */ + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::PeerCallback() QUERY PEER OFFLINE ... do nothin "; + std::cerr << std::endl; +#endif + + break; + + case BITDHT_MGR_QUERY_PEER_UNREACHABLE: + /* do nothing */ + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::PeerCallback() QUERY PEER UNREACHABLE ... flag? / do nothin "; + std::cerr << std::endl; +#endif + + + break; + + case BITDHT_MGR_QUERY_PEER_ONLINE: + /* do something */ + +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::PeerCallback() QUERY PEER ONLINE ... try udp connection"; + std::cerr << std::endl; +#endif + + connect = true; + break; + } + + if (connect) + { +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::PeerCallback() mConnCb->peerConnectRequest()"; + std::cerr << std::endl; +#endif + + mConnCb->peerConnectRequest(pid, id->addr, RS_CB_DHT); + return 1; + } + else + { + return 0; + } + } + else + { +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::PeerCallback()"; + std::cerr << " FAILED TO TRANSLATE ID "; + std::cerr << " status: " << status; + std::cerr << " NOOP for NOW"; + std::cerr << std::endl; +#endif + } + + return 0; +} + +int p3BitDht::ValueCallback(const bdNodeId *id, std::string key, uint32_t status) +{ +#ifdef DEBUG_BITDHT + std::cerr << "p3BitDht::ValueCallback() NOOP for NOW"; + std::cerr << std::endl; +#endif + + /* ignore for now */ + return 0; +} + diff --git a/libretroshare/src/dht/p3bitdht.h b/libretroshare/src/dht/p3bitdht.h new file mode 100644 index 000000000..869a7a621 --- /dev/null +++ b/libretroshare/src/dht/p3bitdht.h @@ -0,0 +1,106 @@ +/* + * libretroshare/src/dht: p3bitdht.h + * + * BitDht interface for RetroShare. + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef MRK_P3_BITDHT_H +#define MRK_P3_BITDHT_H + +#include "pqi/pqiassist.h" + +#include +#include +#include "pqi/pqinetwork.h" +#include "pqi/pqimonitor.h" +#include "util/rsthreads.h" + +#include "udp/udpstack.h" +#include "udp/udpbitdht.h" +#include "bitdht/bdiface.h" + +class p3BitDht: public pqiNetAssistConnect +{ + public: + p3BitDht(std::string id, pqiConnectCb *cb, + UdpStack *udpstack, std::string bootstrapfile); + +virtual ~p3BitDht(); + +void start(); /* starts up the bitdht thread */ + + /* pqiNetAssist - external interface functions */ +virtual void enable(bool on); +virtual void shutdown(); /* blocking call */ +virtual void restart(); + +virtual bool getEnabled(); +virtual bool getActive(); +virtual bool getNetworkStats(uint32_t &netsize, uint32_t &localnetsize); + + /* pqiNetAssistConnect - external interface functions */ + + /* add / remove peers */ +virtual bool findPeer(std::string id); +virtual bool dropPeer(std::string id); + + /* extract current peer status */ +virtual bool getPeerStatus(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t &type, uint32_t &mode); + +virtual bool getExternalInterface(struct sockaddr_in &raddr, + uint32_t &mode); + + /* notifyPeer/setExtInterface/Bootstrap/Stun + * hould all be removed from NetAssist? + */ + + /* pqiNetAssistConnect - external interface functions */ + + + /* Callback functions - from bitdht */ +int NodeCallback(const bdId *id, uint32_t peerflags); +int PeerCallback(const bdId *id, uint32_t status); +int ValueCallback(const bdNodeId *id, std::string key, uint32_t status); + + private: + /* translation stuff */ + int calculateNodeId(const std::string pid, bdNodeId *id); + + int lookupNodeId(const std::string pid, bdNodeId *id); + int lookupRsId(const bdNodeId *id, std::string &pid); + int storeTranslation(const std::string pid); + int removeTranslation(const std::string pid); + + UdpBitDht *mUdpBitDht; /* has own mutex, is static except for creation/destruction */ + + RsMutex dhtMtx; + /* translation maps */ + std::map mTransToNodeId; + std::map mTransToRsId; + +}; + +#endif /* MRK_P3_BITDHT_H */ + diff --git a/libretroshare/src/ft/ftchunkmap.cc b/libretroshare/src/ft/ftchunkmap.cc new file mode 100644 index 000000000..459a9575a --- /dev/null +++ b/libretroshare/src/ft/ftchunkmap.cc @@ -0,0 +1,497 @@ +/* + * libretroshare/src/ft: ftdata.cc + * + * File Transfer for RetroShare. + * + * Copyright 2010 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "csoler@users.sourceforge.net". + * + */ + +/******** + * #define DEBUG_FTCHUNK 1 + *********/ + +#ifdef DEBUG_FTCHUNK +#include +#endif +#include +#include +#include "retroshare/rspeers.h" +#include "ftchunkmap.h" +#include + +static const uint32_t SOURCE_CHUNK_MAP_UPDATE_PERIOD = 60 ; //! TTL for chunkmap info +static const uint32_t INACTIVE_CHUNK_TIME_LAPSE = 60 ; //! TTL for an inactive chunk + +std::ostream& operator<<(std::ostream& o,const ftChunk& c) +{ + return o << "\tChunk [" << c.offset << "] size: " << c.size << " ChunkId: " << c.id << " Age: " << time(NULL) - c.ts << ", owner: " << c.peer_id ; +} + +// Chunk: very bold implementation for now. We should compress the bits to have +// 32 of them per uint32_t value, of course! +// +Chunk::Chunk(uint64_t start,uint32_t size) + : _start(start),_offset(start),_end( (uint64_t)size + start ) +{ +} + +void Chunk::getSlice(uint32_t size_hint,ftChunk& chunk) +{ + // Take the current offset + chunk.offset = _offset ; + chunk.size = std::min(size_hint,(uint32_t)(_end-_offset)) ; + chunk.id = _offset ; + chunk.ts = time(NULL) ; + + // push the slice marker into currently handled slices. + _offset += chunk.size ; +} + +ChunkMap::ChunkMap(uint64_t s,bool availability) + : _file_size(s), + _chunk_size(CHUNKMAP_FIXED_CHUNK_SIZE), // 1MB chunks + _assume_availability(availability) +{ + uint64_t n = s/(uint64_t)_chunk_size ; + if(s% (uint64_t)_chunk_size != 0) + ++n ; + + _map.resize(n,FileChunksInfo::CHUNK_OUTSTANDING) ; + _strategy = FileChunksInfo::CHUNK_STRATEGY_RANDOM ; + _total_downloaded = 0 ; + _file_is_complete = false ; +#ifdef DEBUG_FTCHUNK + std::cerr << "*** ChunkMap::ChunkMap: starting new chunkmap:" << std::endl ; + std::cerr << " File size: " << s << std::endl ; + std::cerr << " Strategy: " << _strategy << std::endl ; + std::cerr << " ChunkSize: " << _chunk_size << std::endl ; + std::cerr << " Number of Chunks: " << n << std::endl ; + std::cerr << " Data: " ; + for(int i=0;i<_map.size();++i) + std::cerr << _map[i] ; + std::cerr << std::endl ; +#endif +} + +void ChunkMap::setAvailabilityMap(const CompressedChunkMap& map) +{ + _file_is_complete = true ; + _total_downloaded = 0 ; + + for(uint32_t i=0;i<_map.size();++i) + if(map[i] > 0) + { + _map[i] = FileChunksInfo::CHUNK_DONE ; + _total_downloaded += sizeOfChunk(i) ; + } + else + { + _map[i] = FileChunksInfo::CHUNK_OUTSTANDING ; + _file_is_complete = false ; + } +} + +void ChunkMap::dataReceived(const ftChunk::ChunkId& cid) +{ + // 1 - find which chunk contains the received data. + // + + // trick: cid is the chunk offset. So we use it to get the chunk number. + int n = (uint64_t)cid/_chunk_size ; + + std::map::iterator itc(_slices_to_download.find(n)) ; + + if(itc == _slices_to_download.end()) + { + std::cerr << "!!! ChunkMap::dataReceived: error: ChunkId " << cid << " corresponds to chunk number " << n << ", which is not being downloaded!" << std::endl ; +#ifdef DEBUG_FTCHUNK + assert(false) ; +#endif + return ; + } + + std::map::iterator it(itc->second._slices.find(cid)) ; + + if(it == itc->second._slices.end()) + { + std::cerr << "!!! ChunkMap::dataReceived: chunk " << cid << " is not found in slice lst of chunk number " << n << std::endl ; +#ifdef DEBUG_FTCHUNK + assert(false) ; +#endif + return ; + } + + _total_downloaded += it->second ; + itc->second._remains -= it->second ; + itc->second._slices.erase(it) ; + itc->second._last_data_received = time(NULL) ; // update time stamp + +#ifdef DEBUG_FTCHUNK + std::cerr << "*** ChunkMap::dataReceived: received data chunk " << cid << " for chunk number " << n << ", local remains=" << itc->second._remains << ", total downloaded=" << _total_downloaded << ", remains=" << _file_size - _total_downloaded << std::endl ; +#endif + if(itc->second._remains == 0) // the chunk was completely downloaded + { +#ifdef DEBUG_FTCHUNK + std::cerr << "*** ChunkMap::dataReceived: Chunk is complete. Removing it." << std::endl ; +#endif + _map[n] = FileChunksInfo::CHUNK_DONE ; + _slices_to_download.erase(itc) ; + + // We also check whether the file is complete or not. + + _file_is_complete = true ; + + for(uint32_t i=0;i<_map.size();++i) + if(_map[i] != FileChunksInfo::CHUNK_DONE) + { + _file_is_complete = false ; + break ; + } + } +} + +// Warning: a chunk may be empty, but still being downloaded, so asking new slices from it +// will produce slices of size 0. This happens at the end of each chunk. +// --> I need to get slices from the next chunk, in such a case. +// --> solution: +// - have too chunks maps: +// 1 indexed by peer id to feed the getChunk method +// - chunks pushed when new chunks are needed +// - chunks removed when empty +// 1 indexed by chunk id to account for chunks being downloaded +// - chunks pushed when new chunks are needed +// - chunks removed when completely downloaded +// +bool ChunkMap::getDataChunk(const std::string& peer_id,uint32_t size_hint,ftChunk& chunk,bool& source_chunk_map_needed) +{ +#ifdef DEBUG_FTCHUNK + std::cerr << "*** ChunkMap::getDataChunk: size_hint = " << size_hint << std::endl ; +#endif + // 1 - find if this peer already has an active chunk. + // + std::map::iterator it = _active_chunks_feed.find(peer_id) ; + + if(it == _active_chunks_feed.end()) + { + // 1 - select an available chunk id for this peer. + // + uint32_t c = getAvailableChunk(peer_id,source_chunk_map_needed) ; + + if(c >= _map.size()) + return false ; + + // 2 - add the chunk in the list of active chunks, and mark it as being downloaded + // + uint32_t soc = sizeOfChunk(c) ; + _active_chunks_feed[peer_id] = Chunk( c*(uint64_t)_chunk_size, soc ) ; + _map[c] = FileChunksInfo::CHUNK_ACTIVE ; + _slices_to_download[c]._remains = soc ; // init the list of slices to download +#ifdef DEBUG_FTCHUNK + std::cout << "*** ChunkMap::getDataChunk: Allocating new chunk " << c << " for peer " << peer_id << std::endl ; +#endif + } +#ifdef DEBUG_FTCHUNK + else + std::cout << "*** ChunkMap::getDataChunk: Re-using chunk " << it->second._start/_chunk_size << " for peer " << peer_id << std::endl ; +#endif + + // Get the first slice of the chunk, that is at most of length size + // + _active_chunks_feed[peer_id].getSlice(size_hint,chunk) ; + _slices_to_download[chunk.offset/_chunk_size]._slices[chunk.id] = chunk.size ; + _slices_to_download[chunk.offset/_chunk_size]._last_data_received = time(NULL) ; + + if(_active_chunks_feed[peer_id].empty()) + _active_chunks_feed.erase(_active_chunks_feed.find(peer_id)) ; + + chunk.peer_id = peer_id ; +#ifdef DEBUG_FTCHUNK + std::cout << "*** ChunkMap::getDataChunk: returning slice " << chunk << " for peer " << peer_id << std::endl ; +#endif + return true ; +} + +void ChunkMap::removeInactiveChunks(std::vector& to_remove) +{ + to_remove.clear() ; + time_t now = time(NULL) ; + + for(std::map::iterator it(_slices_to_download.begin());it!=_slices_to_download.end();) + if(now - it->second._last_data_received > (int)INACTIVE_CHUNK_TIME_LAPSE) + { +#ifdef DEBUG_FTCHUNK + std::cerr << "ChunkMap::removeInactiveChunks(): removing inactive chunk " << it->first << ", time lapse=" << now - it->second._last_data_received << std::endl ; +#endif + // First, remove all slices from this chunk + // + std::map::iterator tmp(it) ; + + for(std::map::const_iterator it2(it->second._slices.begin());it2!=it->second._slices.end();++it2) + to_remove.push_back(it2->first) ; + + _map[it->first] = FileChunksInfo::CHUNK_OUTSTANDING ; // reset the chunk + + _total_downloaded -= (sizeOfChunk(it->first) - it->second._remains) ; // restore completion. + + // Also remove the chunk from the chunk feed, to free the associated peer. + // + for(std::map::iterator it3=_active_chunks_feed.begin();it3!=_active_chunks_feed.end();) + if(it3->second._start == _chunk_size*uint64_t(it->first)) + { + std::map::iterator tmp3 = it3 ; + ++it3 ; + _active_chunks_feed.erase(tmp3) ; + } + else + ++it3 ; + + ++it ; + _slices_to_download.erase(tmp) ; + } + else + ++it ; +} + +bool ChunkMap::isChunkAvailable(uint64_t offset, uint32_t chunk_size) const +{ + uint32_t chunk_number_start = offset/(uint64_t)_chunk_size ; + uint32_t chunk_number_end = (offset+(uint64_t)chunk_size)/(uint64_t)_chunk_size ; + + if((offset+(uint64_t)chunk_size) % (uint64_t)_chunk_size != 0) + ++chunk_number_end ; + + // It's possible that chunk_number_start==chunk_number_end+1, but for this we need to have + // chunk_size=0, and offset%_chunk_size=0, so the response "true" is still valid. + // + for(uint32_t i=chunk_number_start;i::iterator it(_peers_chunks_availability.find(peer_id)) ; + SourceChunksInfo *peer_chunks = NULL; + + // Do we have a chunk map for this file source ? + // - if yes, we use it + // - if no, + // - if availability is assumed, let's build a plain chunkmap for it + // - otherwise, refuse the transfer, but still ask for the chunkmap + // + // We first test whether the source has a record of not. If not, we fill a new record. + // For availability sources we fill it plain, otherwise, we fill it blank. + // + if(it == _peers_chunks_availability.end()) + { + SourceChunksInfo& pchunks(_peers_chunks_availability[peer_id]) ; + + // Ok, we don't have the info, so two cases: + // - peer_id is a not a turtle peer, so he is considered having the full file source, so we init with a plain chunkmap + // - otherwise, a source map needs to be obtained, so we init with a blank chunkmap + // + if(_assume_availability) + { + pchunks.cmap._map.resize( CompressedChunkMap::getCompressedSize(_map.size()),~(uint32_t)0 ) ; + pchunks.TS = 0 ; + pchunks.is_full = true ; + } + else + { + pchunks.cmap._map.resize( CompressedChunkMap::getCompressedSize(_map.size()),0 ) ; + pchunks.TS = 0 ; + pchunks.is_full = false ; + } + + it = _peers_chunks_availability.find(peer_id) ; + } + peer_chunks = &(it->second) ; + + // If the info is too old, we ask for a new one. When the map is full, we ask 10 times less, as it's probably not + // useful to get a new map that will also be full, but because we need to be careful not to mislead information, + // we still keep asking. + // + time_t now = time(NULL) ; + + if((!peer_chunks->is_full) && ((int)now - (int)peer_chunks->TS > (int)SOURCE_CHUNK_MAP_UPDATE_PERIOD)) + { + map_is_too_old = true ;// We will re-ask but not before some seconds. + peer_chunks->TS = now ; + } + else + map_is_too_old = false ;// the map is not too old + + uint32_t available_chunks = 0 ; + + for(unsigned int i=0;i<_map.size();++i) + if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING && (peer_chunks->is_full || peer_chunks->cmap[i])) + { + if(_strategy == FileChunksInfo::CHUNK_STRATEGY_STREAMING) + { +#ifdef DEBUG_FTCHUNK + std::cerr << "ChunkMap::getAvailableChunk: returning chunk " << i << " for peer " << peer_id << std::endl; +#endif + return i ; + } + else + ++available_chunks ; + } + + if(available_chunks > 0) + { + uint32_t chosen_chunk_number = rand() % available_chunks ; + uint32_t j=0 ; + + for(uint32_t i=0;i<_map.size();++i) + if(_map[i] == FileChunksInfo::CHUNK_OUTSTANDING && (peer_chunks->is_full || peer_chunks->cmap[i])) + { + if(j == chosen_chunk_number) + { +#ifdef DEBUG_FTCHUNK + std::cerr << "ChunkMap::getAvailableChunk: returning chunk " << i << " for peer " << peer_id << std::endl; +#endif + return i ; + } + else + ++j ; + } + } + +#ifdef DEBUG_FTCHUNK + std::cout << "!!! ChunkMap::getAvailableChunk: No available chunk from peer " << peer_id << ": returning false" << std::endl ; +#endif + return _map.size() ; +} + +void ChunkMap::getChunksInfo(FileChunksInfo& info) const +{ + info.file_size = _file_size ; + info.chunk_size = _chunk_size ; + info.chunks = _map ; + info.strategy = _strategy ; + + info.active_chunks.clear() ; + + for(std::map::const_iterator it(_slices_to_download.begin());it!=_slices_to_download.end();++it) + info.active_chunks.push_back(std::pair(it->first,it->second._remains)) ; + + info.compressed_peer_availability_maps.clear() ; + + for(std::map::const_iterator it(_peers_chunks_availability.begin());it!=_peers_chunks_availability.end();++it) + info.compressed_peer_availability_maps[it->first] = it->second.cmap ; +} + +void ChunkMap::removeFileSource(const std::string& peer_id) +{ + std::map::iterator it(_peers_chunks_availability.find(peer_id)) ; + + if(it == _peers_chunks_availability.end()) + return ; + + _peers_chunks_availability.erase(it) ; +} + +void ChunkMap::getAvailabilityMap(CompressedChunkMap& compressed_map) const +{ + compressed_map = CompressedChunkMap(_map) ; + +#ifdef DEBUG_FTCHUNK + std::cerr << "ChunkMap:: retrieved availability map of size " << _map.size() << ", chunk_size=" << _chunk_size << std::endl ; +#endif +} + +uint32_t ChunkMap::getNumberOfChunks(uint64_t size) +{ + uint64_t n = size/(uint64_t)CHUNKMAP_FIXED_CHUNK_SIZE ; + + if(size % (uint64_t)CHUNKMAP_FIXED_CHUNK_SIZE != 0) + ++n ; + + uint32_t value = n & 0xffffffffull ; + + if((uint64_t)value != n) + { + std::cerr << "ERROR: number of chunks is a totally absurd value. File size is " << size << ", chunks are " << n << "!!" << std::endl ; + return 0 ; + } + return value ; +} + +void ChunkMap::buildPlainMap(uint64_t size, CompressedChunkMap& map) +{ + uint32_t n = getNumberOfChunks(size) ; + + map = CompressedChunkMap(n,~uint32_t(0)) ; +} + + diff --git a/libretroshare/src/ft/ftchunkmap.h b/libretroshare/src/ft/ftchunkmap.h new file mode 100644 index 000000000..1f60b6fcc --- /dev/null +++ b/libretroshare/src/ft/ftchunkmap.h @@ -0,0 +1,188 @@ +#pragma once + +#include +#include "retroshare/rstypes.h" + +// ftChunkMap: +// - handles chunk map over a complete file +// - mark down which chunk is being downloaded by which peer +// - allocate data ranges of any requested size for a given peer +// - continuing an existing chunk +// - allocating a new chunk +// +// Download mecanism: +// - ftFileCreator handles a list of active slices, and periodically resends requests every 20 sec. +// Slices have arbitrary size (less than a chunk), depending on the transfer rate. +// When receiving data, ftFileCreator shrinks its slices until they get complete. When a slice is finished, it +// notifies ftChunkMap that this slice is done. +// +// - ftChunkMap maintains two levels: +// - the chunk level (Chunks a 1MB long) with a map of who has which chunk and what locally is the state of +// each chunk +// - the slice level: each active chunk is cut into slices (basically a list of intervalls) being downloaded, and +// a remaining slice to cut off new candidates. When notified for a complete slice, ftChunkMap removed the +// corresponding acive slice. When asked a slice, ftChunkMap cuts out a slice from the remaining part of the chunk +// to download, sends the slice's coordinates and gives a unique slice id (such as the slice offset). + + +// This class handles a slice of a chunk of arbitrary uint32_t size, at the level of ftFileCreator + +class ftController ; + +class ftChunk +{ + public: + typedef uint64_t ChunkId ; + + ftChunk():offset(0), size(0), ts(0) {} + + friend std::ostream& operator<<(std::ostream& o,const ftChunk& f) ; + + uint64_t offset; // current offset of the slice + uint64_t size; // size remaining to download + ChunkId id ; // id of the chunk. Equal to the starting offset of the chunk + time_t ts; // time of last data received + std::string peer_id ; +}; + +// This class handles a single fixed-sized chunk. Although each chunk is requested at once, +// it may be sent back into sub-chunks because of file transfer rate constraints. +// So the dataReceived function should be called to progressively complete the chunk, +// and the getChunk method should ask for a sub-chunk of a given size. +// +class Chunk +{ + public: + Chunk(): _start(0),_offset(0),_end(0) {} // only used in default std::map fillers + + Chunk(uint64_t start,uint32_t size) ; + + void getSlice(uint32_t size_hint,ftChunk& chunk) ; + + // Returns true when the chunk is complete + bool empty() const { return _offset == _end ; } + + // Array of intervalls of bytes to download. + // + uint64_t _start ; // const + uint64_t _offset ; // not const: handles the current offset within the chunk. + uint64_t _end ; // const +}; + +class ChunkDownloadInfo +{ + public: + std::map _slices ; + uint32_t _remains ; + time_t _last_data_received ; +}; + +class SourceChunksInfo +{ + public: + CompressedChunkMap cmap ; //! map of what the peer has/doens't have + time_t TS ; //! last update time for this info + bool is_full ; //! is the map full ? In such a case, re-asking for it is unnecessary. +}; + +class ChunkMap +{ + public: + static const uint32_t CHUNKMAP_FIXED_CHUNK_SIZE = 1024*1024 ; // 1 MB chunk + typedef uint32_t ChunkNumber ; + + /// Constructor. Decides what will be the size of chunks and how many there will be. + + ChunkMap(uint64_t file_size,bool assume_availability) ; + + /// destructor + virtual ~ChunkMap() {} + + /// Returns an slice of data to be asked to the peer within a chunk. + /// If a chunk is already been downloaded by this peer, take a slice at + /// the beginning of this chunk, or at least where it starts. + /// If not, randomly/streamly select a new chunk depending on the strategy. + /// adds an entry in the chunk_ids map, and sets up 1 interval for it. + /// the chunk should be available from the designated peer. + /// On return: + /// - source_chunk_map_needed = true if the source map should be asked + + virtual bool getDataChunk(const std::string& peer_id,uint32_t size_hint,ftChunk& chunk,bool& source_chunk_map_needed) ; + + /// Notify received a slice of data. This needs to + /// - carve in the map of chunks what is received, what is not. + /// - tell which chunks are finished. For this, each interval must know what chunk number it has been attributed + /// when the interval is split in the middle, the number of intervals for the chunk is increased. If the interval is + /// completely covered by the data, the interval number is decreased. + + virtual void dataReceived(const ftChunk::ChunkId& c_id) ; + + /// Decides how chunks are selected. + /// STREAMING: the 1st chunk is always returned + /// RANDOM: a uniformly random chunk is selected among available chunks for the current source. + /// + + void setStrategy(FileChunksInfo::ChunkStrategy s) { _strategy = s ; } + FileChunksInfo::ChunkStrategy getStrategy() const { return _strategy ; } + + /// Properly fills an vector of fixed size chunks with availability or download state. + /// chunks is given with the proper number of chunks and we have to adapt to it. This can be used + /// to display square chunks in the gui or display a blue bar of availability by collapsing info from all peers. + /// The set method is not virtual because it has no reason to exist in the parent ftFileProvider + + virtual void getAvailabilityMap(CompressedChunkMap& cmap) const ; + void setAvailabilityMap(const CompressedChunkMap& cmap) ; + + /// Removes the source availability map. The map + void removeFileSource(const std::string& peer_id) ; + + /// This function fills in a plain map for a file of the given size. This + /// is used to ensure that the chunk size will be consistent with the rest + /// of the code. + // + static void buildPlainMap(uint64_t size,CompressedChunkMap& map) ; + + /// Computes the number of chunks for the given file size. + static uint32_t getNumberOfChunks(uint64_t size) ; + + /// This function is used by the parent ftFileProvider to know whether the chunk can be sent or not. + bool isChunkAvailable(uint64_t offset, uint32_t chunk_size) const ; + + /// Remove active chunks that have not received any data for the last 60 seconds, and return + /// the list of slice numbers that should be canceled. + void removeInactiveChunks(std::vector& to_remove) ; + + /// Updates the peer's availablility map + // + void setPeerAvailabilityMap(const std::string& peer_id,const CompressedChunkMap& peer_map) ; + + /// Returns the total size of downloaded data in the file. + uint64_t getTotalReceived() const { return _total_downloaded ; } + + /// returns true is the file is complete + bool isComplete() const { return _file_is_complete ; } + + void getChunksInfo(FileChunksInfo& info) const ; + + protected: + /// handles what size the last chunk has. + uint32_t sizeOfChunk(uint32_t chunk_number) const ; + + /// Returns a chunk available for this peer_id, depending on the chunk strategy. + // + uint32_t getAvailableChunk(const std::string& peer_id,bool& chunk_map_too_old) ; + + private: + uint64_t _file_size ; //! total size of the file in bytes. + uint32_t _chunk_size ; //! Size of chunks. Common to all chunks. + FileChunksInfo::ChunkStrategy _strategy ; //! how do we allocate new chunks + std::map _active_chunks_feed ; //! vector of chunks being downloaded. Exactly 1 chunk per peer. + std::map _slices_to_download ; //! list of (slice id,slice size) + std::vector _map ; //! vector of chunk state over the whole file + std::map _peers_chunks_availability ; //! what does each source peer have + uint64_t _total_downloaded ; //! completion for the file + bool _file_is_complete ; //! set to true when the file is complete. + bool _assume_availability ; //! true if all sources always have the complete file. +}; + + diff --git a/libretroshare/src/ft/ftcontroller.cc b/libretroshare/src/ft/ftcontroller.cc new file mode 100644 index 000000000..541eec664 --- /dev/null +++ b/libretroshare/src/ft/ftcontroller.cc @@ -0,0 +1,2130 @@ +/* + * libretroshare/src/ft: ftcontroller.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* + * ftController + * + * Top level download controller. + * + * inherits configuration (save downloading files) + * inherits pqiMonitor (knows which peers are online). + * inherits CacheTransfer (transfers cache files too) + * inherits RsThread (to control transfers) + * + */ + +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#endif +#include "util/rsdiscspace.h" + +#include "ft/ftcontroller.h" + +#include "ft/ftfilecreator.h" +#include "ft/fttransfermodule.h" +#include "ft/ftsearch.h" +#include "ft/ftdatamultiplex.h" +#include "ft/ftextralist.h" + +#include "turtle/p3turtle.h" + +#include "util/rsdir.h" + +#include "pqi/p3connmgr.h" +#include "pqi/pqinotify.h" + +#include "retroshare/rsiface.h" + +#include "serialiser/rsconfigitems.h" +#include +#include + +/****** + * #define CONTROL_DEBUG 1 + * #define DEBUG_DWLQUEUE 1 + *****/ + +static const uint32_t SAVE_TRANSFERS_DELAY = 61 ; // save transfer progress every 61 seconds. +static const uint32_t INACTIVE_CHUNKS_CHECK_DELAY = 60 ; // time after which an inactive chunk is released +static const uint32_t MAX_TIME_INACTIVE_REQUEUED = 60 ; // time after which an inactive ftFileControl is bt-queued +static const uint32_t TIMOUT_CACHE_FILE_TRANSFER = 800 ; // time after which cache transfer gets cancelled if inactive. + +static const uint32_t FT_FILECONTROL_QUEUE_ADD_END = 0 ; +static const uint32_t FT_FILECONTROL_QUEUE_ADD_AFTER_CACHE = 1 ; + +ftFileControl::ftFileControl() + :mTransfer(NULL), mCreator(NULL), + mState(DOWNLOADING), mSize(0), mFlags(0), + mPriority(SPEED_NORMAL) +{ + return; +} + +ftFileControl::ftFileControl(std::string fname, + std::string tmppath, std::string dest, + uint64_t size, std::string hash, uint32_t flags, + ftFileCreator *fc, ftTransferModule *tm) + :mName(fname), mCurrentPath(tmppath), mDestination(dest), + mTransfer(tm), mCreator(fc), mState(DOWNLOADING), mHash(hash), + mSize(size), mFlags(flags), + mPriority(SPEED_NORMAL) // default priority to normal +{ + return; +} + +ftController::ftController(CacheStrapper *cs, ftDataMultiplex *dm, std::string configDir) + :CacheTransfer(cs), p3Config(CONFIG_TYPE_FT_CONTROL), + last_save_time(0), + last_clean_time(0), + mDataplex(dm), + mTurtle(NULL), + mFtActive(false), + mDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) +{ + _max_active_downloads = 5 ; // default queue size + /* TODO */ +} + +void ftController::setTurtleRouter(p3turtle *pt) +{ + mTurtle = pt ; +} +void ftController::setFtSearchNExtra(ftSearch *search, ftExtraList *list) +{ + mSearch = search; + mExtraList = list; +} + +bool ftController::getFileDownloadChunksDetails(const std::string& hash,FileChunksInfo& info) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + std::map::iterator it = mDownloads.find(hash) ; + + if(it != mDownloads.end()) + { + it->second->mCreator->getChunkMap(info) ; + info.flags = it->second->mFlags ; + + return true ; + } + + it = mCompleted.find(hash) ; + + if(it != mCompleted.end()) + { + // This should rather be done as a static method of ChunkMap. + // + // We do this manually, because the file creator has already been destroyed. + // + info.file_size = it->second->mSize ; + info.strategy = mDefaultChunkStrategy ; + info.chunk_size = ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE ; + info.flags = it->second->mFlags ; + uint32_t nb_chunks = it->second->mSize/ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE ; + if(it->second->mSize % ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE != 0) + ++nb_chunks ; + info.chunks.resize(nb_chunks,FileChunksInfo::CHUNK_DONE) ; + + return true ; + } + + return false ; +} + +void ftController::addFileSource(const std::string& hash,const std::string& peer_id) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + std::map::iterator it; + std::map currentDownloads = *(&mDownloads); + +#ifdef CONTROL_DEBUG + std::cerr << "ftController: Adding source " << peer_id << " to current download hash=" << hash ; +#endif + for(it = currentDownloads.begin(); it != currentDownloads.end(); it++) + if(it->first == hash) + { + it->second->mTransfer->addFileSource(peer_id); + +#ifdef CONTROL_DEBUG + std::cerr << "... added." << std::endl ; +#endif + return ; + } +#ifdef CONTROL_DEBUG + std::cerr << "... not added: hash not found." << std::endl ; +#endif +} +void ftController::removeFileSource(const std::string& hash,const std::string& peer_id) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + std::map::iterator it; + std::map currentDownloads = *(&mDownloads); + +#ifdef CONTROL_DEBUG + std::cerr << "ftController: Adding source " << peer_id << " to current download hash=" << hash ; +#endif + for(it = currentDownloads.begin(); it != currentDownloads.end(); it++) + if(it->first == hash) + { + it->second->mTransfer->removeFileSource(peer_id); + it->second->mCreator->removeFileSource(peer_id); + +#ifdef CONTROL_DEBUG + std::cerr << "... added." << std::endl ; +#endif + return ; + } +#ifdef CONTROL_DEBUG + std::cerr << "... not added: hash not found." << std::endl ; +#endif +} +void ftController::run() +{ + + /* check the queues */ + uint32_t cnt = 0 ; + + while(isRunning()) + { +#ifdef WIN32 + Sleep(1000); +#else + sleep(1); +#endif + +#ifdef CONTROL_DEBUG + std::cerr << "ftController::run()"; + std::cerr << std::endl; +#endif + bool doPending = false; + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + doPending = (mFtActive) && (!mFtPendingDone); + } + + time_t now = time(NULL) ; + if((int)now - (int)last_save_time > (int)SAVE_TRANSFERS_DELAY) + { + cleanCacheDownloads() ; + + IndicateConfigChanged() ; + last_save_time = now ; + } + + if((int)now - (int)last_clean_time > (int)INACTIVE_CHUNKS_CHECK_DELAY) + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + for(std::map::iterator it(mDownloads.begin());it!=mDownloads.end();++it) + it->second->mCreator->removeInactiveChunks() ; + + last_clean_time = now ; + } + + if (doPending) + { + if (!handleAPendingRequest()) + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + mFtPendingDone = true; + } + } + + tickTransfers() ; + + { + std::list files_to_complete ; + + { + RsStackMutex stack2(doneMutex); + files_to_complete = mDone ; + mDone.clear(); + } + + for(std::list::iterator it(files_to_complete.begin()); it != files_to_complete.end(); ++it) + completeFile(*it); + } + + if(cnt++ % 10 == 0) + checkDownloadQueue() ; + } + +} + +void ftController::tickTransfers() +{ + // 1 - sort modules into arrays according to priority + + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + +#ifdef CONTROL_DEBUG + std::cerr << "ticking transfers." << std::endl ; +#endif + std::vector >priority_tab (3,std::vector()) ; + + // Collect all non queued files. + // + for(std::map::iterator it(mDownloads.begin()); it != mDownloads.end(); it++) + if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED) + priority_tab[it->second->mPriority].push_back(it->second->mTransfer) ; + + // 2 - tick arrays with a probability proportional to priority + + // 2.1 - decide based on probability, which category of files we handle. + +#ifdef CONTROL_DEBUG + std::cerr << "Priority tabs: " ; + std::cerr << "Low (" << priority_tab[SPEED_LOW ].size() << ") " ; + std::cerr << "Normal (" << priority_tab[SPEED_NORMAL].size() << ") " ; + std::cerr << "High (" << priority_tab[SPEED_HIGH ].size() << ") " ; + std::cerr << std::endl ; +#endif + + /* tick the transferModules */ + + // start anywhere in the chosen list of transfers, so that not to favor any special transfer + // + + for(int chosen=2;chosen>=0;--chosen) + if(!priority_tab[chosen].empty()) + { + int start = rand() % priority_tab[chosen].size() ; + + for(int i=0;i<(int)priority_tab[chosen].size();++i) + priority_tab[chosen][(i+start)%(int)priority_tab[chosen].size()]->tick() ; + } +} + +bool ftController::getPriority(const std::string& hash,DwlSpeed& p) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + std::map::iterator it(mDownloads.find(hash)) ; + + if(it != mDownloads.end()) + { + p = it->second->mPriority ; + return true ; + } + else + return false ; +} +void ftController::setPriority(const std::string& hash,DwlSpeed p) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + std::map::iterator it(mDownloads.find(hash)) ; + + if(it != mDownloads.end()) + it->second->mPriority = p ; +} + +void ftController::cleanCacheDownloads() +{ + std::vector toCancel ; + time_t now = time(NULL) ; + + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + for(std::map::iterator it(mDownloads.begin());it!=mDownloads.end();++it) + if (((it->second)->mFlags & RS_FILE_HINTS_CACHE) && it->second->mState != ftFileControl::DOWNLOADING) + // check if a cache file is downloaded, if the case, timeout the transfer after TIMOUT_CACHE_FILE_TRANSFER + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::run() cache transfer found. age of this tranfer is :" << (int)(time(NULL) - (it->second)->mCreateTime); + std::cerr << std::endl; +#endif + if (now > (it->second)->mCreator->creationTimeStamp() + TIMOUT_CACHE_FILE_TRANSFER) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::run() cache transfer to old. Cancelling transfer. Hash :" << (it->second)->mHash << ", time=" << (it->second)->mCreateTime << ", now = " << time(NULL) ; + std::cerr << std::endl; +#endif + toCancel.push_back((it->second)->mHash); + } + } + } + + for(uint32_t i=0;i + // - sort the ftFileControl* into a std::vector + // - store the queue position of each ftFileControl* into its own structure (mQueuePosition member) + // + // We don't want the turtle router to keep openning tunnels for queued files, so we only base + // the notion of inactive on the fact that no traffic happens for the file within 5 mins. + // + // How do we detect inactive files? + // For a downld file: - no traffic for 5 min. + + RsStackMutex mtx(ctrlMutex) ; + +#ifdef DEBUG_DWLQUEUE + std::cerr << "Checking download queue." << std::endl ; +#endif + if(mDownloads.size() <= _max_active_downloads) + return ; + + // Check for inactive transfers. + // + time_t now = time(NULL) ; + uint32_t nb_moved = 0 ; // don't move more files than the size of the queue. + + for(std::map::const_iterator it(mDownloads.begin());it!=mDownloads.end() && nb_moved <= _max_active_downloads;++it) + if( it->second->mState != ftFileControl::QUEUED + && it->second->mState != ftFileControl::PAUSED + && now > it->second->mCreator->lastRecvTimeStamp() + (time_t)MAX_TIME_INACTIVE_REQUEUED) + { +#ifdef DEBUG_DWLQUEUE + std::cerr << " - Inactive file " << it->second->mName << " at position " << it->second->mQueuePosition << " moved to end of the queue. mState=" << it->second->mState << ", time lapse=" << now - it->second->mCreator->lastRecvTimeStamp() << std::endl ; +#endif + locked_bottomQueue(it->second->mQueuePosition) ; +#ifdef DEBUG_DWLQUEUE + std::cerr << " new position: " << it->second->mQueuePosition << std::endl ; + std::cerr << " new state: " << it->second->mState << std::endl ; +#endif + it->second->mCreator->resetRecvTimeStamp() ; // very important! + ++nb_moved ; + } +} + +void ftController::locked_addToQueue(ftFileControl* ftfc,int add_strategy) +{ +#ifdef DEBUG_DWLQUEUE + std::cerr << "Queueing ftfileControl " << (void*)ftfc << ", name=" << ftfc->mName << std::endl ; +#endif + + switch(add_strategy) + { + case FT_FILECONTROL_QUEUE_ADD_END: _queue.push_back(ftfc) ; + locked_checkQueueElement(_queue.size()-1) ; + break ; + case FT_FILECONTROL_QUEUE_ADD_AFTER_CACHE: + { + // We add the transfer just before the first non cache transfer. + // + uint32_t pos =0; + while(pos < _queue.size() && (_queue[pos]->mFlags & RS_FILE_HINTS_CACHE)>0) + ++pos ; + + _queue.push_back(NULL) ; + + for(int i=int(_queue.size())-1;i>(int)pos;--i) + { + _queue[i] = _queue[i-1] ; + locked_checkQueueElement(i) ; + } + + _queue[pos] = ftfc ; + locked_checkQueueElement(pos) ; + } + break ; + } +} + +void ftController::locked_queueRemove(uint32_t pos) +{ + for(uint32_t p=pos;p<_queue.size()-1;++p) + { + _queue[p]=_queue[p+1] ; + locked_checkQueueElement(p) ; + } + _queue.pop_back(); +} + +void ftController::setQueueSize(uint32_t s) +{ + RsStackMutex mtx(ctrlMutex) ; + + if(s > 0) + { + uint32_t old_s = _max_active_downloads ; + _max_active_downloads = s ; +#ifdef DEBUG_DWLQUEUE + std::cerr << "Settign new queue size to " << s << std::endl ; +#endif + for(uint32_t p=std::min(s,old_s);p<=std::max(s,old_s);++p) + if(p < _queue.size()) + locked_checkQueueElement(p); + } + else + std::cerr << "ftController::setQueueSize(): cannot set queue to size " << s << std::endl ; +} +uint32_t ftController::getQueueSize() +{ + RsStackMutex mtx(ctrlMutex) ; + return _max_active_downloads ; +} + +void ftController::moveInQueue(const std::string& hash,QueueMove mv) +{ + RsStackMutex mtx(ctrlMutex) ; + + std::map::iterator it(mDownloads.find(hash)) ; + + if(it == mDownloads.end()) + { + std::cerr << "ftController::moveInQueue: can't find hash " << hash << " in the download list." << std::endl ; + return ; + } + uint32_t pos = it->second->mQueuePosition ; + +#ifdef DEBUG_DWLQUEUE + std::cerr << "Moving file " << hash << ", pos=" << pos << " to new pos." << std::endl ; +#endif + switch(mv) + { + case QUEUE_TOP: locked_topQueue(pos) ; + break ; + + case QUEUE_BOTTOM: locked_bottomQueue(pos) ; + break ; + + case QUEUE_UP: if(pos > 0) + locked_swapQueue(pos,pos-1) ; + break ; + + case QUEUE_DOWN: if(pos < _queue.size()-1) + locked_swapQueue(pos,pos+1) ; + break ; + default: + std::cerr << "ftController::moveInQueue: unknown move " << mv << std::endl ; + } +} + +void ftController::locked_topQueue(uint32_t pos) +{ + ftFileControl *tmp=_queue[pos] ; + + for(int p=pos;p>0;--p) + { + _queue[p]=_queue[p-1] ; + locked_checkQueueElement(p) ; + } + _queue[0]=tmp ; + + locked_checkQueueElement(0) ; +} +void ftController::locked_bottomQueue(uint32_t pos) +{ + ftFileControl *tmp=_queue[pos] ; + + for(uint32_t p=pos;p<_queue.size()-1;++p) + { + _queue[p]=_queue[p+1] ; + locked_checkQueueElement(p) ; + } + _queue[_queue.size()-1]=tmp ; + locked_checkQueueElement(_queue.size()-1) ; +} +void ftController::locked_swapQueue(uint32_t pos1,uint32_t pos2) +{ + // Swap the element at position pos with the last element of the queue + + if(pos1==pos2) + return ; + + ftFileControl *tmp = _queue[pos1] ; + _queue[pos1] = _queue[pos2] ; + _queue[pos2] = tmp; + + locked_checkQueueElement(pos1) ; + locked_checkQueueElement(pos2) ; +} + +void ftController::locked_checkQueueElement(uint32_t pos) +{ + _queue[pos]->mQueuePosition = pos ; + + if(pos < _max_active_downloads && _queue[pos]->mState != ftFileControl::PAUSED) + { + if(_queue[pos]->mState == ftFileControl::QUEUED) + _queue[pos]->mCreator->resetRecvTimeStamp() ; + + _queue[pos]->mState = ftFileControl::DOWNLOADING ; + + if(_queue[pos]->mFlags & RS_FILE_HINTS_NETWORK_WIDE) + mTurtle->monitorFileTunnels(_queue[pos]->mName,_queue[pos]->mHash,_queue[pos]->mSize) ; + } + + if(pos >= _max_active_downloads && _queue[pos]->mState != ftFileControl::QUEUED && _queue[pos]->mState != ftFileControl::PAUSED) + { + _queue[pos]->mState = ftFileControl::QUEUED ; + _queue[pos]->mCreator->closeFile() ; + + if(_queue[pos]->mFlags & RS_FILE_HINTS_NETWORK_WIDE) + mTurtle->stopMonitoringFileTunnels(_queue[pos]->mHash) ; + } +} + +bool ftController::FlagFileComplete(std::string hash) +{ + RsStackMutex stack2(doneMutex); + mDone.push_back(hash); + +#ifdef CONTROL_DEBUG + std::cerr << "ftController:FlagFileComplete(" << hash << ")"; + std::cerr << std::endl; +#endif + + return true; +} + +bool ftController::moveFile(const std::string& source,const std::string& dest) +{ + // First try a rename + // + +#ifdef WINDOWS_SYS + std::wstring sourceW; + std::wstring destW; + librs::util::ConvertUtf8ToUtf16(source,sourceW); + librs::util::ConvertUtf8ToUtf16(dest,destW); + + if( 0 != MoveFileW(sourceW.c_str(), destW.c_str())) +#else + if (0 == rename(source.c_str(), dest.c_str())) +#endif + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::completeFile() renaming to: "; + std::cerr << dest; + std::cerr << std::endl; +#endif + + return true ; + } +#ifdef CONTROL_DEBUG + std::cerr << "ftController::completeFile() FAILED mv to: "; + std::cerr << dest; + std::cerr << std::endl; + std::cerr << "trying copy" << std::endl ; +#endif + // We could not rename, probably because we're dealing with different file systems. + // Let's copy then. + +#ifdef WINDOWS_SYS + if(CopyFileW(sourceW.c_str(), destW.c_str(), FALSE) == 0) +#else + if(!copyFile(source,dest)) +#endif + return false ; + + // copy was successfull, let's delete the original + std::cerr << "deleting original file " << source << std::endl ; + +#ifdef WINDOWS_SYS + if(0 != DeleteFileW(sourceW.c_str())) +#else + if(0 == remove(source.c_str())) +#endif + return true ; + else + { + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "File erase error", "Error while removing hash file " + dest + "\nRead-only file system ?"); + return false ; + } +} + +bool ftController::copyFile(const std::string& source,const std::string& dest) +{ + FILE *in = RsDirUtil::rs_fopen(source.c_str(),"rb") ; + + if(in == NULL) + { + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "File copy error", "Error while copying file " + dest + "\nCannot open input file "+source); + return false ; + } + + FILE *out = RsDirUtil::rs_fopen(dest.c_str(),"wb") ; + + if(out == NULL) + { + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "File copy error", "Error while copying file " + dest + "\nCheck for disk full, or write permission ?\nOriginal file kept under the name "+source); + fclose (in); + return false ; + } + + size_t s=0; + size_t T=0; + + static const int BUFF_SIZE = 10485760 ; // 10 MB buffer to speed things up. + void *buffer = malloc(BUFF_SIZE) ; + + bool bRet = true; + + while( (s = fread(buffer,1,BUFF_SIZE,in)) > 0) + { + size_t t = fwrite(buffer,1,s,out) ; + T += t ; + + if(t != s) + { + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "File copy error", "Error while copying file " + dest + "\nIs your disc full ?\nOriginal file kept under the name "+source); + bRet = false ; + break; + } + } + + fclose(in) ; + fclose(out) ; + + free(buffer) ; + + return true ; +} + + + +bool ftController::completeFile(std::string hash) +{ + /* variables... so we can drop mutex later */ + std::string path; + std::string name; + uint64_t size = 0; + uint32_t state = 0; + uint32_t period = 0; + uint32_t flags = 0; + uint32_t extraflags = 0; + uint32_t completeCount = 0; + + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + +#ifdef CONTROL_DEBUG + std::cerr << "ftController:completeFile(" << hash << ")"; + std::cerr << std::endl; +#endif + std::map::iterator it(mDownloads.find(hash)); + + if (it == mDownloads.end()) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController:completeFile(" << hash << ")"; + std::cerr << " Not Found!"; + std::cerr << std::endl; +#endif + return false; + } + + /* check if finished */ + if (!(it->second)->mCreator->finished()) + { + /* not done! */ +#ifdef CONTROL_DEBUG + std::cerr << "ftController:completeFile(" << hash << ")"; + std::cerr << " Transfer Not Done"; + std::cerr << std::endl; + + std::cerr << "FileSize: "; + std::cerr << (it->second)->mCreator->getFileSize(); + std::cerr << " and Recvd: "; + std::cerr << (it->second)->mCreator->getRecvd(); +#endif + return false; + } + + + ftFileControl *fc = it->second; + + // (csoler) I've postponed this to the end of the block because deleting the + // element from the map calls the destructor of fc->mTransfer, which + // makes fc to point to nothing and causes random behavior/crashes. + // + // mDataplex->removeTransferModule(fc->mTransfer->hash()); + // + /* done - cleanup */ + + // (csoler) I'm copying this because "delete fc->mTransfer" deletes the hash string! + std::string hash_to_suppress(fc->mTransfer->hash()); + + if (fc->mTransfer) + { + delete fc->mTransfer; + fc->mTransfer = NULL; + } + + if (fc->mCreator) + { + fc->mCreator->closeFile() ; + delete fc->mCreator; + fc->mCreator = NULL; + } + + fc->mState = ftFileControl::COMPLETED; + + // I don't know how the size can be zero, but believe me, this happens, + // and it causes an error on linux because then the file may not even exist. + // + if( fc->mSize > 0 && moveFile(fc->mCurrentPath,fc->mDestination) ) + fc->mCurrentPath = fc->mDestination; + else + fc->mState = ftFileControl::ERROR_COMPLETION; + + /* for extralist additions */ + path = fc->mDestination; + name = fc->mName; + //hash = fc->mHash; + size = fc->mSize; + state = fc->mState; + period = 30 * 24 * 3600; /* 30 days */ + extraflags = 0; + +#ifdef CONTROL_DEBUG + std::cerr << "CompleteFile(): size = " << size << std::endl ; +#endif + + mDataplex->removeTransferModule(hash_to_suppress) ; + flags = fc->mFlags ; + + locked_queueRemove(it->second->mQueuePosition) ; + + /* switch map */ + if (!(fc->mFlags & RS_FILE_HINTS_CACHE)) /* clean up completed cache files automatically */ + { + mCompleted[fc->mHash] = fc; + completeCount = mCompleted.size(); + } else + delete fc ; + + mDownloads.erase(it); + + if(flags & RS_FILE_HINTS_NETWORK_WIDE) + mTurtle->stopMonitoringFileTunnels(hash_to_suppress) ; + + } /******* UNLOCKED ********/ + + + /******************** NO Mutex from Now ******************** + * cos Callback can end up back in this class. + ***********************************************************/ + + /* If it has a callback - do it now */ + + if(flags & ( RS_FILE_HINTS_CACHE | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_MEDIA)) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::completeFile() doing Callback, callbackflags:" << (flags & ( RS_FILE_HINTS_CACHE | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_MEDIA)) ; + std::cerr << std::endl; +#endif + if(flags & RS_FILE_HINTS_CACHE) + { + /* callback */ + if (state == ftFileControl::COMPLETED) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::completeFile() doing Callback : Success"; + std::cerr << std::endl; +#endif + + CompletedCache(hash); + } + else + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::completeFile() Cache Callback : Failed"; + std::cerr << std::endl; +#endif + FailedCache(hash); + } + } + + if(flags & RS_FILE_HINTS_EXTRA) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::completeFile() adding to ExtraList"; + std::cerr << std::endl; +#endif + + mExtraList->addExtraFile(path, hash, size, period, extraflags); + } + + if(flags & RS_FILE_HINTS_MEDIA) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::completeFile() NULL MEDIA callback"; + std::cerr << std::endl; +#endif + } + } + else + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::completeFile() No callback"; + std::cerr << std::endl; +#endif + } + + /* Notify GUI */ + if ((flags & RS_FILE_HINTS_CACHE) == 0) { + pqiNotify *notify = getPqiNotify(); + if (notify) { + notify->AddPopupMessage(RS_POPUP_DOWNLOAD, hash, name, ""); + } + rsicontrol->getNotify().notifyDownloadComplete(hash); + rsicontrol->getNotify().notifyDownloadCompleteCount(completeCount); + } + + IndicateConfigChanged(); /* completed transfer -> save */ + return true; + +} + + /***************************************************************/ + /********************** Controller Access **********************/ + /***************************************************************/ + +const uint32_t FT_CNTRL_STANDARD_RATE = 1024 * 1024; +const uint32_t FT_CNTRL_SLOW_RATE = 10 * 1024; + +bool ftController::activate() +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + mFtActive = true; + mFtPendingDone = false; + return true; +} + +bool ftController::isActiveAndNoPending() +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + return (mFtActive && mFtPendingDone); +} + +bool ftController::handleAPendingRequest() +{ + ftPendingRequest req; + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + if (mPendingRequests.size() < 1) + { + return false; + } + req = mPendingRequests.front(); + mPendingRequests.pop_front(); + } +#ifdef CONTROL_DEBUG + std::cerr << "Requesting pending hash " << req.mHash << std::endl ; +#endif + + FileRequest(req.mName, req.mHash, req.mSize, req.mDest, req.mFlags, req.mSrcIds); + + { + // See whether there is a pendign chunk map recorded for this hash. + // + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + std::map::iterator it(mPendingChunkMaps.find(req.mHash)) ; + + if(it != mPendingChunkMaps.end()) + { + RsFileTransfer *rsft = it->second ; + std::map::iterator fit = mDownloads.find(rsft->file.hash); + + if((fit==mDownloads.end() || (fit->second)->mCreator == NULL)) + { + // This should never happen, because the last call to FileRequest must have created the fileCreator!! + // + std::cerr << "ftController::loadList(): Error: could not find hash " << rsft->file.hash << " in mDownloads list !" << std::endl ; + } + else + { +#ifdef CONTROL_DEBUG + std::cerr << "Hash " << req.mHash << " is in downloads" << std::endl ; + std::cerr << " setting chunk strategy to " << rsft->chunk_strategy << std::endl; +#endif + (fit->second)->mCreator->setAvailabilityMap(rsft->compressed_chunk_map) ; + (fit->second)->mCreator->setChunkStrategy((FileChunksInfo::ChunkStrategy)(rsft->chunk_strategy)) ; + } + + delete rsft ; + mPendingChunkMaps.erase(it) ; + } +#ifdef CONTROL_DEBUG + else + std::cerr << "No pending chunkmap for hash " << req.mHash << std::endl ; +#endif + } + + return true ; +} + +bool ftController::alreadyHaveFile(const std::string& hash, FileInfo &info) +{ + // check for downloads + if (FileDetails(hash, info) && (info.downloadStatus == FT_STATE_COMPLETE)) + return true ; + + // check for file lists + if (mSearch->search(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info)) + return true ; + + return false ; +} + +bool ftController::FileRequest(const std::string& fname, const std::string& hash, + uint64_t size, const std::string& dest, uint32_t flags, + const std::list &_srcIds) +{ + std::list srcIds(_srcIds) ; + + /* check if we have the file */ + + FileInfo info; + if(alreadyHaveFile(hash, info)) + return false ; + + if(size == 0) // we treat this special case because + { + /* if no destpath - send to download directory */ + std::string destination ; + + if (dest == "") + destination = mDownloadPath + "/" + fname; + else + destination = dest + "/" + fname; + + // create void file with the target name. + FILE *f = RsDirUtil::rs_fopen(destination.c_str(),"w") ; + if(f == NULL) + std::cerr << "Could not open file " << destination << " for writting." << std::endl ; + else + fclose(f) ; + + return true ; + } + + // Bugs in the cache system can cause files with arbitrary size to be + // requested, causing a division by zero in ftChunkMap when size > 1MB * + // (2^32-1). I thus conservatively check for large size values. + // + if(size >= 1024ull*1024ull*((1ull << 32) - 1)) + { + std::cerr << "FileRequest Error: unexpected size. This is probably a bug." << std::endl; + std::cerr << " name = " << fname << std::endl ; + std::cerr << " flags = " << flags << std::endl ; + std::cerr << " dest = " << dest << std::endl ; + std::cerr << " size = " << size << std::endl ; + return false ; + } + + /* If file transfer is not enabled .... + * save request for later. This will also + * mean that we will have to copy local files, + * or have a callback which says: local file. + */ + + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + if (!mFtActive) + { + /* store in pending queue */ + ftPendingRequest req(fname, hash, size, dest, flags, srcIds); + mPendingRequests.push_back(req); + return true; + } + } + + std::list::const_iterator it; + std::list::const_iterator pit; + +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileRequest(" << fname << ","; + std::cerr << hash << "," << size << "," << dest << ","; + std::cerr << flags << ",<"; + + for(it = srcIds.begin(); it != srcIds.end(); it++) + { + std::cerr << *it << ","; + } + std::cerr << ">)"; + std::cerr << std::endl; +#endif + + uint32_t rate = 0; + if (flags & RS_FILE_HINTS_BACKGROUND) + rate = FT_CNTRL_SLOW_RATE; + else + rate = FT_CNTRL_STANDARD_RATE; + + /* First check if the file is already being downloaded.... + * This is important as some guis request duplicate files regularly. + */ + + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + std::map::const_iterator dit = mDownloads.find(hash); + + if (dit != mDownloads.end()) + { + /* we already have it! */ + +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileRequest() Already Downloading File"; + std::cerr << std::endl; + std::cerr << "\tNo need to download"; + std::cerr << std::endl; +#endif + /* but we should add this peer - if they don't exist! + * (needed for channels). + */ + + for(it = srcIds.begin(); it != srcIds.end(); it++) + { + uint32_t i, j; + if ((dit->second)->mTransfer->getPeerState(*it, i, j)) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileRequest() Peer Existing"; + std::cerr << std::endl; +#endif + continue; /* already added peer */ + } + +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileRequest() Adding Peer: " << *it; + std::cerr << std::endl; +#endif + (dit->second)->mTransfer->addFileSource(*it); + setPeerState(dit->second->mTransfer, *it, rate, mConnMgr->isOnline(*it)); + + IndicateConfigChanged(); /* new peer for transfer -> save */ + } + + if (srcIds.size() == 0) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileRequest() WARNING: No Src Peers"; + std::cerr << std::endl; +#endif + } + + return true; + } + } /******* UNLOCKED ********/ + + if(!(flags & RS_FILE_HINTS_NO_SEARCH)) + { + /* do a source search - for any extra sources */ + // add sources only in direct mode + // + if ((!(flags & RS_FILE_HINTS_NETWORK_WIDE)) && mSearch->search(hash, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info)) + { + /* do something with results */ +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileRequest() Found Other Sources"; + std::cerr << std::endl; +#endif + + /* if the sources don't exist already - add in */ + for(pit = info.peers.begin(); pit != info.peers.end(); pit++) + { +#ifdef CONTROL_DEBUG + std::cerr << "\tSource: " << pit->peerId; + std::cerr << std::endl; +#endif + + if (srcIds.end() == std::find( srcIds.begin(), srcIds.end(), pit->peerId)) + { + srcIds.push_back(pit->peerId); + +#ifdef CONTROL_DEBUG + std::cerr << "\tAdding in: " << pit->peerId; + std::cerr << std::endl; +#endif + } + } + } + } + + /* add in new item for download */ + std::string savepath; + std::string destination; + + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + savepath = mPartialsPath + "/" + hash; + destination = dest + "/" + fname; + + /* if no destpath - send to download directory */ + if (dest == "") + destination = mDownloadPath + "/" + fname; + } /******* UNLOCKED ********/ + + // We check that flags are consistent. + + if(flags & RS_FILE_HINTS_NETWORK_WIDE) + mTurtle->monitorFileTunnels(fname,hash,size) ; + + bool assume_availability = flags & RS_FILE_HINTS_CACHE ; // assume availability for cache files + + ftFileCreator *fc = new ftFileCreator(savepath, size, hash,assume_availability); + ftTransferModule *tm = new ftTransferModule(fc, mDataplex,this); + +#ifdef CONTROL_DEBUG + std::cerr << "Note: setting chunk strategy to " << mDefaultChunkStrategy <setChunkStrategy(mDefaultChunkStrategy) ; + + /* add into maps */ + ftFileControl *ftfc = new ftFileControl(fname, savepath, destination, size, hash, flags, fc, tm); + ftfc->mCreateTime = time(NULL); + + /* now add source peers (and their current state) */ + tm->setFileSources(srcIds); + + /* get current state for transfer module */ + for(it = srcIds.begin(); it != srcIds.end(); it++) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileRequest() adding peer: " << *it; + std::cerr << std::endl; +#endif + setPeerState(tm, *it, rate, mConnMgr->isOnline(*it)); + } + + /* add structures into the accessible data. Needs to be locked */ + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + locked_addToQueue(ftfc, (flags & RS_FILE_HINTS_CACHE)?FT_FILECONTROL_QUEUE_ADD_AFTER_CACHE : FT_FILECONTROL_QUEUE_ADD_END ) ; + +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileRequest() Created ftFileCreator @: " << fc; + std::cerr << std::endl; + std::cerr << "ftController::FileRequest() Created ftTransModule @: " << tm; + std::cerr << std::endl; + std::cerr << "ftController::FileRequest() Created ftFileControl." ; + std::cerr << std::endl; +#endif + + /* add to ClientModule */ + mDataplex->addTransferModule(tm, fc); + mDownloads[hash] = ftfc; + } + + IndicateConfigChanged(); /* completed transfer -> save */ + return true; +} + +bool ftController::setPeerState(ftTransferModule *tm, std::string id, uint32_t maxrate, bool online) +{ + if (id == mConnMgr->getOwnId()) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::setPeerState() is Self"; + std::cerr << std::endl; +#endif + tm->setPeerState(id, PQIPEER_IDLE, maxrate); + } + else if (online || mTurtle->isOnline(id)) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::setPeerState()"; + std::cerr << " Peer is Online"; + std::cerr << std::endl; +#endif + tm->setPeerState(id, PQIPEER_IDLE, maxrate); + } + else + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::setPeerState()"; + std::cerr << " Peer is Offline"; + std::cerr << std::endl; +#endif + tm->setPeerState(id, PQIPEER_NOT_ONLINE, maxrate); + } + return true; +} + + +bool ftController::setChunkStrategy(const std::string& hash,FileChunksInfo::ChunkStrategy s) +{ + std::map::iterator mit=mDownloads.find(hash); + if (mit==mDownloads.end()) + { +#ifdef CONTROL_DEBUG + std::cerr<<"ftController::setChunkStrategy file is not found in mDownloads"<second->mCreator->setChunkStrategy(s) ; + return true ; +} + +bool ftController::FileCancel(const std::string& hash) +{ + rsTurtle->stopMonitoringFileTunnels(hash) ; + +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileCancel" << std::endl; +#endif + /*check if the file in the download map*/ + + { + RsStackMutex mtx(ctrlMutex) ; + + std::map::iterator mit=mDownloads.find(hash); + if (mit==mDownloads.end()) + { +#ifdef CONTROL_DEBUG + std::cerr<<"ftController::FileCancel file is not found in mDownloads"<second)->mCreator->finished()) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController:FileCancel(" << hash << ")"; + std::cerr << " Transfer Already finished"; + std::cerr << std::endl; + + std::cerr << "FileSize: "; + std::cerr << (mit->second)->mCreator->getFileSize(); + std::cerr << " and Recvd: "; + std::cerr << (mit->second)->mCreator->getRecvd(); +#endif + return false; + } + + /*find the point to transfer module*/ + ftTransferModule* ft=(mit->second)->mTransfer; + ft->cancelTransfer(); + + ftFileControl *fc = mit->second; + mDataplex->removeTransferModule(fc->mTransfer->hash()); + + if (fc->mTransfer) + { + delete fc->mTransfer; + fc->mTransfer = NULL; + } + + if (fc->mCreator) + { + delete fc->mCreator; + fc->mCreator = NULL; + } + + /* delete the temporary file */ + if (0 == remove(fc->mCurrentPath.c_str())) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileCancel() remove temporary file "; + std::cerr << fc->mCurrentPath; + std::cerr << std::endl; +#endif + } + else + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileCancel() fail to remove file "; + std::cerr << fc->mCurrentPath; + std::cerr << std::endl; +#endif + } + + locked_queueRemove(fc->mQueuePosition) ; + delete fc ; + mDownloads.erase(mit); + } + + IndicateConfigChanged(); /* completed transfer -> save */ + return true; +} + +bool ftController::FileControl(const std::string& hash, uint32_t flags) +{ +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileControl(" << hash << ","; + std::cerr << flags << ")"<::iterator mit=mDownloads.find(hash); + if (mit==mDownloads.end()) + { +#ifdef CONTROL_DEBUG + std::cerr<<"ftController::FileControl file is not found in mDownloads"<second->mState = ftFileControl::PAUSED ; + std::cerr << "setting state to " << ftFileControl::PAUSED << std::endl ; + break; + + case RS_FILE_CTRL_START: + mit->second->mState = ftFileControl::DOWNLOADING ; + std::cerr << "setting state to " << ftFileControl::DOWNLOADING << std::endl ; + break; + + case RS_FILE_CTRL_FORCE_CHECK: + mit->second->mTransfer->forceCheck(); + std::cerr << "setting state to " << ftFileControl::CHECKING_HASH << std::endl ; + break; + + default: + return false; + } + return true; +} + +bool ftController::FileClearCompleted() +{ +#ifdef CONTROL_DEBUG + std::cerr << "ftController::FileClearCompleted()" <::iterator it(mCompleted.begin());it!=mCompleted.end();++it) + delete it->second ; + + mCompleted.clear(); + + IndicateConfigChanged(); + } /******* UNLOCKED ********/ + + rsicontrol->getNotify().notifyDownloadCompleteCount(0); + + return false; +} + + /* get Details of File Transfers */ +bool ftController::FileDownloads(std::list &hashs) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + std::map::iterator it; + for(it = mDownloads.begin(); it != mDownloads.end(); it++) + { + hashs.push_back(it->second->mHash); + } + for(it = mCompleted.begin(); it != mCompleted.end(); it++) + { + hashs.push_back(it->second->mHash); + } + return true; +} + + + /* Directory Handling */ +bool ftController::setDownloadDirectory(std::string path) +{ +#ifdef CONTROL_DEBUG + std::cerr << "ftController::setDownloadDirectory(" << path << ")"; + std::cerr << std::endl; +#endif + /* check if it exists */ + if (RsDirUtil::checkCreateDirectory(path)) + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + mDownloadPath = RsDirUtil::convertPathToUnix(path); +#ifdef CONTROL_DEBUG + std::cerr << "ftController::setDownloadDirectory() Okay!"; + std::cerr << std::endl; +#endif + IndicateConfigChanged(); + return true; + } + +#ifdef CONTROL_DEBUG + std::cerr << "ftController::setDownloadDirectory() Failed"; + std::cerr << std::endl; +#endif + return false; +} + +bool ftController::setPartialsDirectory(std::string path) +{ + + /* check it is not a subdir of download / shared directories (BAD) - TODO */ + { + RsStackMutex stack(ctrlMutex); + + path = RsDirUtil::convertPathToUnix(path); + + if (!path.find(mDownloadPath)) { + return false; + } + + if (rsFiles) { + std::list::iterator it; + std::list dirs; + rsFiles->getSharedDirectories(dirs); + for (it = dirs.begin(); it != dirs.end(); it++) { + if (!path.find((*it).filename)) { + return false; + } + } + } + } + + /* check if it exists */ + + if (RsDirUtil::checkCreateDirectory(path)) + { + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + mPartialsPath = path; + +#if 0 /*** FIX ME !!!**************/ + /* move all existing files! */ + std::map::iterator it; + for(it = mDownloads.begin(); it != mDownloads.end(); it++) + { + (it->second).mCreator->changePartialDirectory(mPartialPath); + } +#endif + IndicateConfigChanged(); + return true; + } + + return false; +} + +std::string ftController::getDownloadDirectory() +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + return mDownloadPath; +} + +std::string ftController::getPartialsDirectory() +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + return mPartialsPath; +} + +bool ftController::FileDetails(const std::string &hash, FileInfo &info) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + bool completed = false; + std::map::iterator it = mDownloads.find(hash); + if (it == mDownloads.end()) + { + /* search completed files too */ + it = mCompleted.find(hash); + if (it == mCompleted.end()) + { + /* Note: mTransfer & mCreator + * are both NULL + */ + return false; + } + completed = true; + } + + /* extract details */ + info.hash = hash; + info.fname = it->second->mName; + info.flags = it->second->mFlags; + info.path = RsDirUtil::removeTopDir(it->second->mDestination); /* remove fname */ + info.priority = it->second->mPriority ; + info.queue_position = it->second->mQueuePosition ; + + /* get list of sources from transferModule */ + std::list peerIds; + std::list::iterator pit; + + if (!completed) + it->second->mTransfer->getFileSources(peerIds); + + double totalRate = 0; + uint32_t tfRate = 0; + uint32_t state = 0; + + bool isDownloading = false; + bool isSuspended = false; + + for(pit = peerIds.begin(); pit != peerIds.end(); pit++) + { + if (it->second->mTransfer->getPeerState(*pit, state, tfRate)) + { + TransferInfo ti; + switch(state) + { + case PQIPEER_INIT: + ti.status = FT_STATE_OKAY; + break; + case PQIPEER_NOT_ONLINE: + ti.status = FT_STATE_WAITING; + break; + case PQIPEER_DOWNLOADING: + isDownloading = true; + ti.status = FT_STATE_DOWNLOADING; + break; + case PQIPEER_IDLE: + ti.status = FT_STATE_OKAY; + break; + default: + case PQIPEER_SUSPEND: + isSuspended = true; + ti.status = FT_STATE_FAILED; + break; + } + + ti.tfRate = tfRate / 1024.0; + ti.peerId = *pit; + info.peers.push_back(ti); + totalRate += tfRate / 1024.0; + } + } + + if ((completed) || ((it->second)->mCreator->finished())) + { + info.downloadStatus = FT_STATE_COMPLETE; + } + else if (isDownloading) + { + info.downloadStatus = FT_STATE_DOWNLOADING; + } + else if (isSuspended) + { + info.downloadStatus = FT_STATE_FAILED; + } + else + { + info.downloadStatus = FT_STATE_WAITING; + } + + if(it->second->mState == ftFileControl::QUEUED) + info.downloadStatus = FT_STATE_QUEUED ; + + if(it->second->mState == ftFileControl::PAUSED) + info.downloadStatus = FT_STATE_PAUSED ; + + if((!completed) && it->second->mTransfer->isCheckingHash()) + info.downloadStatus = FT_STATE_CHECKING_HASH ; + + info.tfRate = totalRate; + info.size = (it->second)->mSize; + + if (completed) + { + info.transfered = info.size; + info.avail = info.transfered; + } + else + { + info.transfered = (it->second)->mCreator->getRecvd(); + info.avail = info.transfered; + } + + return true; + + + +} + + + /***************************************************************/ + /********************** Controller Access **********************/ + /***************************************************************/ + + /* pqiMonitor callback: + * Used to tell TransferModules new available peers + */ +void ftController::statusChange(const std::list &plist) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + uint32_t rate = FT_CNTRL_STANDARD_RATE; + + /* add online to all downloads */ + std::map::iterator it; + std::list::const_iterator pit; + + std::list vlist ; + mTurtle->getVirtualPeersList(vlist) ; + +#ifdef CONTROL_DEBUG + std::cerr << "ftController::statusChange()"; + std::cerr << std::endl; +#endif + + for(it = mDownloads.begin(); it != mDownloads.end(); it++) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftController::statusChange() Updating Hash:"; + std::cerr << it->first; + std::cerr << std::endl; +#endif + for(pit = plist.begin(); pit != plist.end(); pit++) + { +#ifdef CONTROL_DEBUG + std::cerr << "Peer: " << pit->id; +#endif + if (pit->actions & RS_PEER_CONNECTED) + { +#ifdef CONTROL_DEBUG + std::cerr << " is Newly Connected!"; + std::cerr << std::endl; +#endif + setPeerState(it->second->mTransfer, pit->id, rate, true); + } + else if (pit->actions & RS_PEER_DISCONNECTED) + { +#ifdef CONTROL_DEBUG + std::cerr << " is Just disconnected!"; + std::cerr << std::endl; +#endif + setPeerState(it->second->mTransfer, pit->id, rate, false); + } + else + { +#ifdef CONTROL_DEBUG + std::cerr << " had something happen to it: "; + std::cerr << pit-> actions; + std::cerr << std::endl; +#endif + setPeerState(it->second->mTransfer, pit->id, rate, false); + } + } + + // Now also look at turtle virtual peers. + // + for(pit = vlist.begin(); pit != vlist.end(); pit++) + { +#ifdef CONTROL_DEBUG + std::cerr << "Peer: " << pit->id; +#endif + if (pit->actions & RS_PEER_CONNECTED) + { +#ifdef CONTROL_DEBUG + std::cerr << " is Newly Connected!"; + std::cerr << std::endl; +#endif + setPeerState(it->second->mTransfer, pit->id, rate, true); + } + else if (pit->actions & RS_PEER_DISCONNECTED) + { +#ifdef CONTROL_DEBUG + std::cerr << " is Just disconnected!"; + std::cerr << std::endl; +#endif + setPeerState(it->second->mTransfer, pit->id, rate, false); + } + else + { +#ifdef CONTROL_DEBUG + std::cerr << " had something happen to it: "; + std::cerr << pit-> actions; + std::cerr << std::endl; +#endif + setPeerState(it->second->mTransfer, pit->id, rate, false); + } + } + } +} + + /* Cache Interface */ +bool ftController::RequestCacheFile(RsPeerId id, std::string path, std::string hash, uint64_t size) +{ +#ifdef CONTROL_DEBUG + std::cerr << "ftController::RequestCacheFile(" << id << ","; + std::cerr << path << "," << hash << "," << size << ")"; + std::cerr << std::endl; +#endif + + /* Request File */ + std::list ids; + ids.push_back(id); + + FileInfo info ; + if(mSearch->search(hash, RS_FILE_HINTS_CACHE, info)) + { +#ifdef CONTROL_DEBUG + std::cerr << "I already have this file:" << std::endl ; + std::cerr << " path: " << info.path << std::endl ; + std::cerr << " fname: " << info.fname << std::endl ; + std::cerr << " hash: " << info.hash << std::endl ; + + std::cerr << "Copying it !!" << std::endl ; +#endif + + if(info.size > 0 && copyFile(info.path,path+"/"+hash)) + { + CompletedCache(hash); + return true ; + } + else + return false ; + } + + FileRequest(hash, hash, size, path, RS_FILE_HINTS_CACHE | RS_FILE_HINTS_NO_SEARCH, ids); + + return true; +} + + +bool ftController::CancelCacheFile(RsPeerId id, std::string path, std::string hash, uint64_t size) +{ + std::cerr << "ftController::CancelCacheFile(" << id << ","; + std::cerr << path << "," << hash << "," << size << ")"; + std::cerr << std::endl; +#ifdef CONTROL_DEBUG +#endif + + return FileCancel(hash); + +} + +const std::string active_downloads_size_ss("MAX_ACTIVE_DOWNLOADS"); +const std::string download_dir_ss("DOWN_DIR"); +const std::string partial_dir_ss("PART_DIR"); +const std::string default_chunk_strategy_ss("DEFAULT_CHUNK_STRATEGY"); +const std::string free_space_limit_ss("FREE_SPACE_LIMIT"); + + + /* p3Config Interface */ +RsSerialiser *ftController::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + + /* add in the types we need! */ + rss->addSerialType(new RsFileConfigSerialiser()); + rss->addSerialType(new RsGeneralConfigSerialiser()); + + return rss; +} + +bool ftController::saveList(bool &cleanup, std::list& saveData) +{ + + + /* it can delete them! */ + cleanup = true; + + /* create a key/value set for most of the parameters */ + std::map configMap; + std::map::iterator mit; + std::list::iterator it; + + /* basic control parameters */ + std::ostringstream strm ; + strm << getQueueSize() ; + configMap[active_downloads_size_ss] = strm.str() ; + configMap[download_dir_ss] = getDownloadDirectory(); + configMap[partial_dir_ss] = getPartialsDirectory(); + configMap[default_chunk_strategy_ss] = (mDefaultChunkStrategy==FileChunksInfo::CHUNK_STRATEGY_STREAMING) ? "STREAMING" : "RANDOM"; + + std::ostringstream s ; + s << RsDiscSpace::freeSpaceLimit(); + + configMap[free_space_limit_ss] = s.str() ; + + RsConfigKeyValueSet *rskv = new RsConfigKeyValueSet(); + + /* Convert to TLV */ + for(mit = configMap.begin(); mit != configMap.end(); mit++) + { + RsTlvKeyValue kv; + kv.key = mit->first; + kv.value = mit->second; + + rskv->tlvkvs.pairs.push_back(kv); + } + + /* Add KeyValue to saveList */ + saveData.push_back(rskv); + + /* get list of Downloads .... + * strip out Caches / ExtraList / Channels???? + * (anything with a callback?) + * - most systems will restart missing files. + */ + + + /* get Details of File Transfers */ + std::list hashs; + FileDownloads(hashs); + + for(it = hashs.begin(); it != hashs.end(); it++) + { + /* stack mutex released each loop */ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + + std::map::iterator fit = mDownloads.find(*it); + if (fit == mDownloads.end()) + continue; + + /* ignore cache files. As this is small files, better download them again from scratch at restart.*/ + + if (fit->second->mFlags & RS_FILE_HINTS_CACHE) + { +#ifdef CONTROL_DEBUG + std::cerr << "ftcontroller::saveList(): Not saving (callback) file entry " << fit->second->mName << ", " << fit->second->mHash << ", " << fit->second->mSize << std::endl ; +#endif + continue; + } + + if ((fit->second)->mCreator->finished()) + continue; + + /* make RsFileTransfer item for save list */ + RsFileTransfer *rft = new RsFileTransfer(); + + /* what data is important? */ + + rft->file.name = fit->second->mName; + rft->file.hash = fit->second->mHash; + rft->file.filesize = fit->second->mSize; + rft->file.path = RsDirUtil::removeTopDir(fit->second->mDestination); /* remove fname */ + rft->flags = fit->second->mFlags; + rft->state = fit->second->mState; + fit->second->mTransfer->getFileSources(rft->allPeerIds.ids); + + // just avoid uninitialised memory reads + rft->in = 0 ; + rft->cPeerId = "" ; + rft->transferred = fit->second->mCreator->getRecvd(); + rft->crate = 0 ; + rft->lrate = 0 ; + rft->trate = 0 ; + rft->ltransfer = 0 ; + + // Remove turtle peers from sources, as they are not supposed to survive a reboot of RS, since they are dynamic sources. + // Otherwize, such sources are unknown from the turtle router, at restart, and never get removed. + // + for(std::list::iterator sit(rft->allPeerIds.ids.begin());sit!=rft->allPeerIds.ids.end();) + if(mTurtle->isTurtlePeer(*sit)) + { + std::list::iterator sittmp(sit) ; + ++sittmp ; + rft->allPeerIds.ids.erase(sit) ; + sit = sittmp ; + } + else + ++sit ; + + fit->second->mCreator->getAvailabilityMap(rft->compressed_chunk_map) ; + rft->chunk_strategy = fit->second->mCreator->getChunkStrategy() ; + + saveData.push_back(rft); + } + + /* list completed! */ + return true; +} + + +bool ftController::loadList(std::list& load) +{ + std::list::iterator it; + std::list::iterator kit; + RsConfigKeyValueSet *rskv; + RsFileTransfer *rsft; + +#ifdef CONTROL_DEBUG + std::cerr << "ftController::loadList() Item Count: " << load.size(); + std::cerr << std::endl; +#endif + + for(it = load.begin(); it != load.end(); it++) + { + /* switch on type */ + if (NULL != (rskv = dynamic_cast(*it))) + { + /* make into map */ + std::map configMap; + for(kit = rskv->tlvkvs.pairs.begin(); + kit != rskv->tlvkvs.pairs.end(); kit++) + { + configMap[kit->key] = kit->value; + } + + loadConfigMap(configMap); + + } + else if (NULL != (rsft = dynamic_cast(*it))) + { + /* This will get stored on a waiting list - until the + * config files are fully loaded + */ +#ifdef CONTROL_DEBUG + std::cerr << "ftController::loadList(): requesting " << rsft->file.name << ", " << rsft->file.hash << ", " << rsft->file.filesize << std::endl ; +#endif + FileRequest(rsft->file.name, rsft->file.hash, rsft->file.filesize, rsft->file.path, rsft->flags, rsft->allPeerIds.ids); + + { + RsStackMutex mtx(ctrlMutex) ; + + std::map::iterator fit = mDownloads.find(rsft->file.hash); + + if((fit==mDownloads.end() || (fit->second)->mCreator == NULL)) + { + std::cerr << "ftController::loadList(): Error: could not find hash " << rsft->file.hash << " in mDownloads list !" << std::endl ; + std::cerr << "Storing the map in a wait list." << std::endl ; + + mPendingChunkMaps[rsft->file.hash] = rsft ; + continue ; // i.e. don't delete the item! + } + else + { + (fit->second)->mCreator->setAvailabilityMap(rsft->compressed_chunk_map) ; + (fit->second)->mCreator->setChunkStrategy((FileChunksInfo::ChunkStrategy)(rsft->chunk_strategy)) ; + } + } + } + + /* cleanup */ + delete (*it); + } + return true; + +} + +bool ftController::loadConfigMap(std::map &configMap) +{ + std::map::iterator mit; + + std::string str_true("true"); + std::string empty(""); + std::string dir = "notempty"; + + if (configMap.end() != (mit = configMap.find(download_dir_ss))) + setDownloadDirectory(mit->second); + + if (configMap.end() != (mit = configMap.find(active_downloads_size_ss))) + { + std::istringstream i(mit->second) ; + int n=5 ; + i >> n ; + std::cerr << "Note: loading active max downloads: " << n << std::endl; + setQueueSize(n); + } + + if (configMap.end() != (mit = configMap.find(partial_dir_ss))) + { + setPartialsDirectory(mit->second); + } + + if (configMap.end() != (mit = configMap.find(default_chunk_strategy_ss))) + { + if(mit->second == "STREAMING") + { + setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_STREAMING) ; + std::cerr << "Note: loading default value for chunk strategy: streaming" << std::endl; + } + else if(mit->second == "RANDOM") + { + setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; + std::cerr << "Note: loading default value for chunk strategy: random" << std::endl; + } + else + std::cerr << "**** ERROR ***: Unknown value for default chunk strategy in keymap." << std::endl ; + } + + if (configMap.end() != (mit = configMap.find(free_space_limit_ss))) + { + std::istringstream in(mit->second) ; + uint32_t size ; + + in >> size ; + + std::cerr << "have read a size limit of " << size <<" MB" << std::endl ; + + RsDiscSpace::setFreeSpaceLimit(size) ; + } + return true; +} + +void ftController::setFreeDiskSpaceLimit(uint32_t size_in_mb) +{ + RsDiscSpace::setFreeSpaceLimit(size_in_mb) ; + + IndicateConfigChanged() ; +} + + +uint32_t ftController::freeDiskSpaceLimit() const +{ + return RsDiscSpace::freeSpaceLimit() ; +} + +FileChunksInfo::ChunkStrategy ftController::defaultChunkStrategy() +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + return mDefaultChunkStrategy ; +} +void ftController::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy S) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ +#ifdef CONTROL_DEBUG + std::cerr << "Note: in frController: setting chunk strategy to " << S << std::endl ; +#endif + mDefaultChunkStrategy = S ; + IndicateConfigChanged() ; +} diff --git a/libretroshare/src/ft/ftcontroller.h b/libretroshare/src/ft/ftcontroller.h new file mode 100644 index 000000000..cfeb6ea47 --- /dev/null +++ b/libretroshare/src/ft/ftcontroller.h @@ -0,0 +1,261 @@ +/* + * libretroshare/src/ft: ftcontroller.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_CONTROLLER_HEADER +#define FT_CONTROLLER_HEADER + +/* + * ftController + * + * Top level download controller. + * + * inherits configuration (save downloading files) + * inherits pqiMonitor (knows which peers are online). + * inherits CacheTransfer (transfers cache files too) + * inherits RsThread (to control transfers) + * + */ + +class ftFileCreator; +class ftTransferModule; +class ftFileProvider; +class ftSearch; +class ftExtraList; +class ftDataMultiplex; +class p3turtle ; + +#include "dbase/cachestrapper.h" +#include "util/rsthreads.h" +#include "pqi/pqimonitor.h" +#include "pqi/p3cfgmgr.h" + +#include "retroshare/rsfiles.h" +#include "serialiser/rsconfigitems.h" + +#include + + +const uint32_t FC_TRANSFER_COMPLETE = 0x0001; + +class ftFileControl +{ + public: + + enum { DOWNLOADING = 0, + COMPLETED = 1, + ERROR_COMPLETION = 2, + QUEUED = 3, + PAUSED = 4, + CHECKING_HASH = 5 + }; + + ftFileControl(); + ftFileControl(std::string fname, std::string tmppath, std::string dest, + uint64_t size, std::string hash, uint32_t flags, + ftFileCreator *fc, ftTransferModule *tm); + + std::string mName; + std::string mCurrentPath; /* current full path (including name) */ + std::string mDestination; /* final full path (including name) */ + ftTransferModule * mTransfer; + ftFileCreator * mCreator; + uint32_t mState; + std::string mHash; + uint64_t mSize; + uint32_t mFlags; + time_t mCreateTime; + DwlSpeed mPriority ; + uint32_t mQueuePriority ; + uint32_t mQueuePosition ; +}; + +class ftPendingRequest +{ + public: + ftPendingRequest(const std::string& fname, const std::string& hash, + uint64_t size, const std::string& dest, uint32_t flags, + const std::list &srcIds) + : mName(fname), mHash(hash), mSize(size), + mDest(dest), mFlags(flags),mSrcIds(srcIds) { return; } + + ftPendingRequest() : mSize(0), mFlags(0) { return; } + + std::string mName; + std::string mHash; + uint64_t mSize; + std::string mDest; + uint32_t mFlags; + std::list mSrcIds; +}; + + +class ftController: public CacheTransfer, public RsThread, public pqiMonitor, public p3Config +{ + public: + + /* Setup */ + ftController(CacheStrapper *cs, ftDataMultiplex *dm, std::string configDir); + + void setFtSearchNExtra(ftSearch *, ftExtraList *); + void setTurtleRouter(p3turtle *) ; + bool activate(); + bool isActiveAndNoPending(); + + virtual void run(); + + /***************************************************************/ + /********************** Controller Access **********************/ + /***************************************************************/ + + bool FileRequest(const std::string& fname, const std::string& hash, + uint64_t size, const std::string& dest, uint32_t flags, + const std::list &sourceIds); + + /// Do we already have this file, either in download or in file lists ? + bool alreadyHaveFile(const std::string& hash, FileInfo &info); + + bool setChunkStrategy(const std::string& hash,FileChunksInfo::ChunkStrategy s); + void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s); + FileChunksInfo::ChunkStrategy defaultChunkStrategy(); + uint32_t freeDiskSpaceLimit() const ; + void setFreeDiskSpaceLimit(uint32_t size_in_mb) ; + + bool FileCancel(const std::string& hash); + bool FileControl(const std::string& hash, uint32_t flags); + bool FileClearCompleted(); + bool FlagFileComplete(std::string hash); + bool getFileDownloadChunksDetails(const std::string& hash,FileChunksInfo& info); + + // Download speed + bool getPriority(const std::string& hash,DwlSpeed& p); + void setPriority(const std::string& hash,DwlSpeed p); + + // Action on queue position + // + void moveInQueue(const std::string& hash,QueueMove mv) ; + void clearQueue() ; + void setQueueSize(uint32_t size) ; + uint32_t getQueueSize() ; + + /* get Details of File Transfers */ + bool FileDownloads(std::list &hashs); + + /* Directory Handling */ + bool setDownloadDirectory(std::string path); + bool setPartialsDirectory(std::string path); + std::string getDownloadDirectory(); + std::string getPartialsDirectory(); + bool FileDetails(const std::string &hash, FileInfo &info); + + bool moveFile(const std::string& source,const std::string& dest) ; + bool copyFile(const std::string& source,const std::string& dest) ; + + /***************************************************************/ + /********************** Cache Transfer *************************/ + /***************************************************************/ + + /// Returns true is full source availability can be assumed for this peer. + /// + bool assumeAvailability(const std::string& peer_id) const ; + + /* pqiMonitor callback (also provided mConnMgr pointer!) */ + virtual void statusChange(const std::list &plist); + void addFileSource(const std::string& hash,const std::string& peer_id) ; + void removeFileSource(const std::string& hash,const std::string& peer_id) ; + + protected: + + virtual bool RequestCacheFile(RsPeerId id, std::string path, std::string hash, uint64_t size); + virtual bool CancelCacheFile(RsPeerId id, std::string path, std::string hash, uint64_t size); + + void cleanCacheDownloads() ; + void tickTransfers() ; + + /***************************************************************/ + /********************** Controller Access **********************/ + /***************************************************************/ + + + /* p3Config Interface */ + virtual RsSerialiser *setupSerialiser(); + virtual bool saveList(bool &cleanup, std::list&); + virtual bool loadList(std::list& load); + bool loadConfigMap(std::map &configMap); + + private: + + /* RunTime Functions */ + void checkDownloadQueue(); // check the whole queue for inactive files + + void locked_addToQueue(ftFileControl*,int strategy) ;// insert this one into the queue + void locked_bottomQueue(uint32_t pos) ; // bottom queue file which is at this position + void locked_topQueue(uint32_t pos) ; // top queue file which is at this position + void locked_checkQueueElement(uint32_t pos) ; // check the state of this element in the queue + void locked_queueRemove(uint32_t pos) ; // delete this element from the queue + void locked_swapQueue(uint32_t pos1,uint32_t pos2) ; // swap position of the two elements + + bool completeFile(std::string hash); + bool handleAPendingRequest(); + + bool setPeerState(ftTransferModule *tm, std::string id, + uint32_t maxrate, bool online); + + time_t last_save_time ; + time_t last_clean_time ; + /* pointers to other components */ + + ftSearch *mSearch; + ftDataMultiplex *mDataplex; + ftExtraList *mExtraList; + p3turtle *mTurtle ; + + RsMutex ctrlMutex; + + std::map mCompleted; + std::map mDownloads; + std::vector _queue ; + + std::string mConfigPath; + std::string mDownloadPath; + std::string mPartialsPath; + + /**** SPEED QUEUES ****/ + + /* callback list (for File Completion) */ + RsMutex doneMutex; + std::list mDone; + + /* List to Pause File transfers until Caches are properly loaded */ + bool mFtActive; + bool mFtPendingDone; + std::list mPendingRequests; + std::map mPendingChunkMaps ; + + FileChunksInfo::ChunkStrategy mDefaultChunkStrategy ; + + uint32_t _max_active_downloads ; // maximum number of simultaneous downloads +}; + +#endif diff --git a/libretroshare/src/ft/ftdata.cc b/libretroshare/src/ft/ftdata.cc new file mode 100644 index 000000000..46c2a0c02 --- /dev/null +++ b/libretroshare/src/ft/ftdata.cc @@ -0,0 +1,146 @@ +/* + * libretroshare/src/ft: ftdata.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "ft/ftdata.h" + +/******* Pair of Send/Recv (Only need to handle Send side) ******/ +ftDataSendPair::ftDataSendPair(ftDataRecv *recv) + :mDataRecv(recv) +{ + return; +} + + /* Client Send */ +bool ftDataSendPair::sendDataRequest(const std::string &peerId, const std::string &hash, + uint64_t size, uint64_t offset, uint32_t chunksize) +{ + return mDataRecv->recvDataRequest(peerId,hash,size,offset,chunksize); +} + + /* Server Send */ +bool ftDataSendPair::sendData(const std::string &peerId, const std::string &hash, + uint64_t size, uint64_t offset, uint32_t chunksize, void *data) +{ + return mDataRecv->recvData(peerId, hash,size,offset,chunksize,data); +} + + /* Send a request for a chunk map */ +bool ftDataSendPair::sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) +{ + return mDataRecv->recvChunkMapRequest(peer_id,hash,is_client); +} + + /* Send a chunk map */ +bool ftDataSendPair::sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client) +{ + return mDataRecv->recvChunkMap(peer_id,hash,cmap, is_client); +} + /* Send a request for a chunk map */ +bool ftDataSendPair::sendCRC32MapRequest(const std::string& peer_id,const std::string& hash) +{ + return mDataRecv->recvCRC32MapRequest(peer_id,hash); +} + + /* Send a chunk map */ +bool ftDataSendPair::sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& crcmap) +{ + return mDataRecv->recvCRC32Map(peer_id,hash,crcmap) ; +} + /* Client Send */ +bool ftDataSendDummy::sendDataRequest(const std::string &peerId, const std::string &hash, + uint64_t size, uint64_t offset, uint32_t chunksize) +{ + return true; +} + + /* Server Send */ +bool ftDataSendDummy::sendData(const std::string &peerId, const std::string &hash, + uint64_t size, uint64_t offset, uint32_t chunksize, void *data) +{ + return true; +} + + + /* Send a request for a chunk map */ +bool ftDataSendDummy::sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) +{ + return true; +} + + /* Send a chunk map */ +bool ftDataSendDummy::sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client) +{ + return true; +} +bool ftDataSendDummy::sendCRC32MapRequest(const std::string& peer_id,const std::string& hash) +{ + return true; +} + + /* Send a chunk map */ +bool ftDataSendDummy::sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& cmap) +{ + return true; +} + + /* Client Recv */ +bool ftDataRecvDummy::recvData(const std::string &peerId, const std::string &hash, + uint64_t size, uint64_t offset, uint32_t chunksize, void *data) +{ + return true; +} + + + /* Server Recv */ +bool ftDataRecvDummy::recvDataRequest(const std::string &peerId, const std::string &hash, + uint64_t size, uint64_t offset, uint32_t chunksize) +{ + return true; +} + + /* Send a request for a chunk map */ +bool ftDataRecvDummy::recvChunkMapRequest(const std::string& peer_id,const std::string& hash, + bool is_client) +{ + return true; +} + + /* Send a chunk map */ +bool ftDataRecvDummy::recvChunkMap(const std::string& peer_id,const std::string& hash, + const CompressedChunkMap& cmap,bool is_client) +{ + return true; +} + +bool ftDataRecvDummy::sendCRC32MapRequest(const std::string& peer_id,const std::string& hash) +{ + return true ; +} + + /* Send a chunk map */ +bool ftDataRecvDummy::sendCRC32Map(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap) +{ + return true ; +} diff --git a/libretroshare/src/ft/ftdata.h b/libretroshare/src/ft/ftdata.h new file mode 100644 index 000000000..9097bd9a3 --- /dev/null +++ b/libretroshare/src/ft/ftdata.h @@ -0,0 +1,186 @@ +/* + * libretroshare/src/ft: ftdata.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_DATA_INTERFACE_HEADER +#define FT_DATA_INTERFACE_HEADER + +/* + * ftData. + * + * Internal Interfaces for sending and receiving data. + * Most likely to be implemented by ftServer. + * Provided as an independent interface for testing purposes. + * + */ + +#include +#include + + /*************** SEND INTERFACE *******************/ + +class CompressedChunkMap ; +class CRC32Map ; + +class ftDataSend +{ + public: + virtual ~ftDataSend() { return; } + + /* Client Send */ + virtual bool sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) = 0; + + /* Server Send */ + virtual bool sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) = 0; + + /// Send a chunkmap[request]. Because requests/chunkmaps can go both + //directions, but for different usages, we have this "is_client" flags, + //that gives the ultimate goal of the data. "is_client==true" means that + //the message is for a client (download) instead of a server. + // + virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) = 0; + virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap,bool is_client) = 0; + + /// Send a request for a chunk crc map + virtual bool sendCRC32MapRequest(const std::string& peer_id,const std::string& hash) = 0; + /// Send a chunk crc map + virtual bool sendCRC32Map(const std::string& peer_id,const std::string& hash,const CRC32Map& crc_map) = 0; +}; + + + + /*************** RECV INTERFACE *******************/ + +class ftDataRecv +{ + public: + virtual ~ftDataRecv() { return; } + + /* Client Recv */ + virtual bool recvData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) = 0; + + /* Server Recv */ + virtual bool recvDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) = 0; + + /// Send a request for a chunk map + virtual bool recvChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) = 0; + + /// Send a chunk map + virtual bool recvChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap,bool is_client) = 0; + /// Send a request for a chunk map + virtual bool recvCRC32MapRequest(const std::string& peer_id,const std::string& hash) = 0; + + /// Send a chunk map + virtual bool recvCRC32Map(const std::string& peer_id,const std::string& hash,const CRC32Map& crcmap) = 0; +}; + + /**************** FOR TESTING ***********************/ + +/******* Pair of Send/Recv (Only need to handle Send side) ******/ +class ftDataSendPair: public ftDataSend +{ + public: + + ftDataSendPair(ftDataRecv *recv); +virtual ~ftDataSendPair() { return; } + + /* Client Send */ +virtual bool sendDataRequest(const std::string &peerId, const std::string &hash, + uint64_t size, uint64_t offset, uint32_t chunksize); + + /* Server Send */ +virtual bool sendData(const std::string &peerId, const std::string &hash, uint64_t size, + uint64_t offset, uint32_t chunksize, void *data); + + /* Send a request for a chunk map */ +virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client); + + /* Send a chunk map */ +virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client); + + /* Send a request for a chunk map */ +virtual bool sendCRC32MapRequest(const std::string& peer_id,const std::string& hash); + + /* Send a chunk map */ +virtual bool sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& cmap); + ftDataRecv *mDataRecv; +}; + + +class ftDataSendDummy: public ftDataSend +{ + public: +virtual ~ftDataSendDummy() { return; } + + /* Client Send */ +virtual bool sendDataRequest(const std::string &peerId, const std::string &hash, + uint64_t size, uint64_t offset, uint32_t chunksize); + + /* Server Send */ +virtual bool sendData(const std::string &peerId, const std::string &hash, uint64_t size, + uint64_t offset, uint32_t chunksize, void *data); + + /* Send a request for a chunk map */ +virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client); + + /* Send a chunk map */ +virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap,bool is_client); + + /* Send a request for a chunk map */ +virtual bool sendCRC32MapRequest(const std::string& peer_id,const std::string& hash); + + /* Send a chunk map */ +virtual bool sendCRC32Map(const std::string& peer_id,const std::string& hash, const CRC32Map& cmap); +}; + +class ftDataRecvDummy: public ftDataRecv +{ + public: + +virtual ~ftDataRecvDummy() { return; } + + /* Client Recv */ +virtual bool recvData(const std::string& peerId, const std::string& hash, + uint64_t size, uint64_t offset, uint32_t chunksize, void *data); + + /* Server Recv */ +virtual bool recvDataRequest(const std::string& peerId, const std::string& hash, + uint64_t size, uint64_t offset, uint32_t chunksize); + + /* Send a request for a chunk map */ +virtual bool recvChunkMapRequest(const std::string& peer_id,const std::string& hash, + bool is_client); + + /* Send a chunk map */ +virtual bool recvChunkMap(const std::string& peer_id,const std::string& hash, + const CompressedChunkMap& cmap,bool is_client); + + /* Send a request for a chunk map */ +virtual bool sendCRC32MapRequest(const std::string& peer_id,const std::string& hash); + + /* Send a chunk map */ +virtual bool sendCRC32Map(const std::string& peer_id,const std::string& hash, const CompressedChunkMap& cmap); +}; + +#endif diff --git a/libretroshare/src/ft/ftdatamultiplex.cc b/libretroshare/src/ft/ftdatamultiplex.cc new file mode 100644 index 000000000..7f688b391 --- /dev/null +++ b/libretroshare/src/ft/ftdatamultiplex.cc @@ -0,0 +1,891 @@ +/* + * libretroshare/src/ft: ftdatamultiplex.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* + * ftDataMultiplexModule. + * + * This multiplexes the data from PQInterface to the ftTransferModules. + */ + +#include "ft/ftdatamultiplex.h" +#include "ft/fttransfermodule.h" +#include "ft/ftfilecreator.h" +#include "ft/ftfileprovider.h" +#include "ft/ftsearch.h" + +/* For Thread Behaviour */ +const uint32_t DMULTIPLEX_MIN = 10; /* 1ms sleep */ +const uint32_t DMULTIPLEX_MAX = 1000; /* 1 sec sleep */ +const double DMULTIPLEX_RELAX = 0.5; /* ??? */ + +/****** + * #define MPLEX_DEBUG 1 + *****/ + +ftClient::ftClient(ftTransferModule *module, ftFileCreator *creator) + :mModule(module), mCreator(creator) +{ + return; +} + +const uint32_t FT_DATA = 0x0001; // data cuhnk to be stored +const uint32_t FT_DATA_REQ = 0x0002; // data request to be treated +const uint32_t FT_CLIENT_CHUNK_MAP_REQ = 0x0003; // chunk map request to be treated by client +const uint32_t FT_SERVER_CHUNK_MAP_REQ = 0x0004; // chunk map request to be treated by server +const uint32_t FT_CRC32MAP_REQ = 0x0005; // crc32 map request to be treated by server + +ftRequest::ftRequest(uint32_t type, std::string peerId, std::string hash, uint64_t size, uint64_t offset, uint32_t chunk, void *data) + :mType(type), mPeerId(peerId), mHash(hash), mSize(size), + mOffset(offset), mChunk(chunk), mData(data) +{ + return; +} + +ftDataMultiplex::ftDataMultiplex(std::string ownId, ftDataSend *server, ftSearch *search) + :RsQueueThread(DMULTIPLEX_MIN, DMULTIPLEX_MAX, DMULTIPLEX_RELAX), + mDataSend(server), mSearch(search), mOwnId(ownId) +{ + return; +} + +bool ftDataMultiplex::addTransferModule(ftTransferModule *mod, ftFileCreator *f) +{ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + std::map::iterator it; + if (mClients.end() != (it = mClients.find(mod->hash()))) + { + /* error */ + return false; + } + mClients[mod->hash()] = ftClient(mod, f); + + return true; +} + +bool ftDataMultiplex::removeTransferModule(std::string hash) +{ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + std::map::iterator it; + if (mClients.end() == (it = mClients.find(hash))) + { + /* error */ + return false; + } + mClients.erase(it); + + // This is very important to delete the hash from servers as well, because + // after removing the transfer module, ftController will delete the fileCreator. + // If the file creator is also a server in use, then it will cause a crash + // at the next server request. + // + // With the current action, the next server request will re-create the server as + // a ftFileProvider. + // + std::map::iterator sit = mServers.find(hash) ; + + if(sit != mServers.end()) + mServers.erase(sit); + + return true; +} + + +bool ftDataMultiplex::FileUploads(std::list &hashs) +{ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + std::map::iterator sit; + for(sit = mServers.begin(); sit != mServers.end(); sit++) + { + hashs.push_back(sit->first); + } + return true; +} + +bool ftDataMultiplex::FileDownloads(std::list &hashs) +{ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + std::map::iterator cit; + for(cit = mClients.begin(); cit != mClients.end(); cit++) + { + hashs.push_back(cit->first); + } + return true; +} + + +bool ftDataMultiplex::FileDetails(const std::string &hash, uint32_t hintsflag, FileInfo &info) +{ +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::FileDetails("; + std::cerr << hash << ", " << hintsflag << ")"; + std::cerr << std::endl; +#endif + + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + if(hintsflag & RS_FILE_HINTS_DOWNLOAD) + { + std::map::iterator cit; + if (mClients.end() != (cit = mClients.find(hash))) + { + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::FileDetails()"; + std::cerr << " Found ftFileCreator!"; + std::cerr << std::endl; +#endif + + //(cit->second).mModule->FileDetails(info); + (cit->second).mCreator->FileDetails(info); + return true; + } + } + + if(hintsflag & RS_FILE_HINTS_UPLOAD) + { + std::map::iterator sit; + sit = mServers.find(hash); + if (sit != mServers.end()) + { + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::FileDetails()"; + std::cerr << " Found ftFileProvider!"; + std::cerr << std::endl; +#endif + + (sit->second)->FileDetails(info); + return true; + } + } + + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::FileDetails()"; + std::cerr << " Found nothing"; + std::cerr << std::endl; +#endif + + return false; +} + + /* data interface */ + + /*************** SEND INTERFACE (calls ftDataSend) *******************/ + + /* Client Send */ +bool ftDataMultiplex::sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) +{ +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::sendDataRequest() Client Send"; + std::cerr << std::endl; +#endif + return mDataSend->sendDataRequest(peerId,hash,size,offset,chunksize); +} + + /* Server Send */ +bool ftDataMultiplex::sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) +{ +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::sendData() Server Send"; + std::cerr << std::endl; +#endif + return mDataSend->sendData(peerId,hash,size,offset,chunksize,data); +} + + + /*************** RECV INTERFACE (provides ftDataRecv) ****************/ + + /* Client Recv */ +bool ftDataMultiplex::recvData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) +{ +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::recvData() Client Recv"; + std::cerr << std::endl; +#endif + /* Store in Queue */ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + mRequestQueue.push_back(ftRequest(FT_DATA,peerId,hash,size,offset,chunksize,data)); + + return true; +} + + + /* Server Recv */ +bool ftDataMultiplex::recvDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) +{ +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::recvDataRequest() Server Recv"; + std::cerr << std::endl; +#endif + /* Store in Queue */ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + mRequestQueue.push_back( + ftRequest(FT_DATA_REQ,peerId,hash,size,offset,chunksize,NULL)); + + return true; +} + +bool ftDataMultiplex::recvChunkMapRequest(const std::string& peerId, const std::string& hash,bool is_client) +{ +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::recvChunkMapRequest() Server Recv"; + std::cerr << std::endl; +#endif + /* Store in Queue */ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + if(is_client) + mRequestQueue.push_back(ftRequest(FT_CLIENT_CHUNK_MAP_REQ,peerId,hash,0,0,0,NULL)); + else + mRequestQueue.push_back(ftRequest(FT_SERVER_CHUNK_MAP_REQ,peerId,hash,0,0,0,NULL)); + + return true; +} + +bool ftDataMultiplex::recvCRC32MapRequest(const std::string& peerId, const std::string& hash) +{ +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::recvChunkMapRequest() Server Recv"; + std::cerr << std::endl; +#endif + /* Store in Queue */ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + mRequestQueue.push_back(ftRequest(FT_CRC32MAP_REQ,peerId,hash,0,0,0,NULL)); + + return true; +} + +/*********** BACKGROUND THREAD OPERATIONS ***********/ +bool ftDataMultiplex::workQueued() +{ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + if (mRequestQueue.size() > 0) + { + return true; + } + + if (mSearchQueue.size() > 0) + { + return true; + } + + return false; +} + +bool ftDataMultiplex::doWork() +{ + bool doRequests = true; + + /* Handle All the current Requests */ + while(doRequests) + { + ftRequest req; + + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + if (mRequestQueue.size() == 0) + { + doRequests = false; + continue; + } + + req = mRequestQueue.front(); + mRequestQueue.pop_front(); + } + + /* MUTEX FREE */ + + switch(req.mType) + { + case FT_DATA: +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::doWork() Handling FT_DATA"; + std::cerr << std::endl; +#endif + handleRecvData(req.mPeerId, req.mHash, req.mSize, req.mOffset, req.mChunk, req.mData); + break; + + case FT_DATA_REQ: +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::doWork() Handling FT_DATA_REQ"; + std::cerr << std::endl; +#endif + handleRecvDataRequest(req.mPeerId, req.mHash, req.mSize, req.mOffset, req.mChunk); + break; + + case FT_CLIENT_CHUNK_MAP_REQ: +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::doWork() Handling FT_CLIENT_CHUNK_MAP_REQ"; + std::cerr << std::endl; +#endif + handleRecvClientChunkMapRequest(req.mPeerId,req.mHash) ; + break ; + + case FT_SERVER_CHUNK_MAP_REQ: +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::doWork() Handling FT_CLIENT_CHUNK_MAP_REQ"; + std::cerr << std::endl; +#endif + handleRecvServerChunkMapRequest(req.mPeerId,req.mHash) ; + break ; + + case FT_CRC32MAP_REQ: +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::doWork() Handling FT_CLIENT_CRC32_MAP_REQ"; + std::cerr << std::endl; +#endif + handleRecvCRC32MapRequest(req.mPeerId,req.mHash) ; + break ; + + default: +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::doWork() Ignoring UNKNOWN"; + std::cerr << std::endl; +#endif + break; + } + } + + /* Only Handle One Search Per Period.... + * Lower Priority + */ + ftRequest req; + + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + if (mSearchQueue.size() == 0) + { + /* Finished */ + return true; + } + + req = mSearchQueue.front(); + mSearchQueue.pop_front(); + } + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::doWork() Handling Search Request"; + std::cerr << std::endl; +#endif + if(handleSearchRequest(req.mPeerId, req.mHash)) + handleRecvDataRequest(req.mPeerId, req.mHash, req.mSize, req.mOffset, req.mChunk) ; + + return true; +} + +bool ftDataMultiplex::recvCRC32Map(const std::string& peerId, const std::string& hash,const CRC32Map& crc_map) +{ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + std::map::iterator it = mClients.find(hash); + + if(it == mClients.end()) + { + std::cerr << "ftDataMultiplex::recvCRCMap() ERROR: No matching Client for CRC32map. This is an error. " << hash << " !" << std::endl; + /* error */ + return false; + } + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::recvCRCMap() Passing crc map of file " << hash << ", to FT Module" << std::endl; +#endif + + (it->second).mModule->addCRC32Map(crc_map); + return true ; +} + +// A chunk map has arrived. It can be two different situations: +// - an uploader has sent his chunk map, so we need to store it in the corresponding ftFileProvider +// - a source for a download has sent his chunk map, so we need to send it to the corresponding ftFileCreator. +// +bool ftDataMultiplex::recvChunkMap(const std::string& peerId, const std::string& hash,const CompressedChunkMap& compressed_map,bool client) +{ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + if(client) // is the chunk map for a client, or for a server ? + { + std::map::iterator it = mClients.find(hash); + + if(it == mClients.end()) + { +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::recvChunkMap() ERROR: No matching Client for hash " << hash << " !"; + std::cerr << std::endl; +#endif + /* error */ + return false; + } + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::recvChunkMap() Passing map of file " << hash << ", to FT Module"; + std::cerr << std::endl; +#endif + + (it->second).mCreator->setSourceMap(peerId, compressed_map); + return true ; + } + else + { + std::map::iterator it = mServers.find(hash) ; + + if(it == mServers.end()) + { +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvChunkMap() ERROR: No matching file Provider for hash " << hash ; + std::cerr << std::endl; +#endif + return false; + } + + it->second->setClientMap(peerId, compressed_map); + return true ; + } + + return false; +} + +bool ftDataMultiplex::handleRecvCRC32MapRequest(const std::string& peerId, const std::string& hash) +{ + std::map::iterator it ; + bool found = true ; + + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + it = mServers.find(hash) ; + + if(it == mServers.end()) + found = false ; + } + + if(!found) + { +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() ERROR: No matching file Provider for hash " << hash ; + std::cerr << std::endl; +#endif + if(!handleSearchRequest(peerId,hash)) + return false ; + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() A new file Provider has been made up for hash " << hash ; + std::cerr << std::endl; +#endif + } + + CRC32Map cmap ; + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + it = mServers.find(hash) ; + + if(it == mServers.end()) // handleSearchRequest should have filled mServers[hash], but we have been off-mutex since, + return false ; // so it's safer to check again. + else if(!it->second->getCRC32Map(cmap)) + return false ; + } + + std::cerr << "File CRC32 map was successfully computed. Sending it." << std::endl ; + + mDataSend->sendCRC32Map(peerId,hash,cmap); + return true ; +} + +bool ftDataMultiplex::handleRecvClientChunkMapRequest(const std::string& peerId, const std::string& hash) +{ + CompressedChunkMap cmap ; + + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + std::map::iterator it = mClients.find(hash); + + if(it == mClients.end()) + { + // If we can't find the client, it's not a problem. Chunk maps from + // clients are not essential, as they are only used for display. +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvServerChunkMapRequest() ERROR: No matching Client for hash " << hash ; + std::cerr << ". Performing local search." << std::endl; +#endif + return false; + } + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvServerChunkMapRequest() Sending map of file " << hash << ", to peer " << peerId << std::endl; +#endif + + (it->second).mCreator->getAvailabilityMap(cmap); + } + + mDataSend->sendChunkMap(peerId,hash,cmap,false); + + return true ; +} + +bool ftDataMultiplex::handleRecvServerChunkMapRequest(const std::string& peerId, const std::string& hash) +{ + CompressedChunkMap cmap ; + std::map::iterator it ; + bool found = true ; + + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + it = mServers.find(hash) ; + + if(it == mServers.end()) + found = false ; + } + + if(!found) + { +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() ERROR: No matching file Provider for hash " << hash ; + std::cerr << std::endl; +#endif + if(!handleSearchRequest(peerId,hash)) + return false ; + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvChunkMapReq() A new file Provider has been made up for hash " << hash ; + std::cerr << std::endl; +#endif + } + + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + it = mServers.find(hash) ; + + if(it == mServers.end()) // handleSearchRequest should have filled mServers[hash], but we have been off-mutex since, + return false ; // so it's safer to check again. + else + it->second->getAvailabilityMap(cmap); + } + + mDataSend->sendChunkMap(peerId,hash,cmap,true); + + return true; +} + +bool ftDataMultiplex::handleRecvData(const std::string& peerId, + const std::string& hash, uint64_t size, + uint64_t offset, uint32_t chunksize, void *data) +{ + ftTransferModule *transfer_module = NULL ; + + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + std::map::iterator it; + if (mClients.end() == (it = mClients.find(hash))) + { +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvData() ERROR: No matching Client!"; + std::cerr << std::endl; +#endif + /* error */ + return false; + } + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvData() Passing to Module"; + std::cerr << std::endl; +#endif + + transfer_module = (it->second).mModule ; + } + transfer_module->recvFileData(peerId, offset, chunksize, data); + + return true; +} + + + /* called by ftTransferModule */ +bool ftDataMultiplex::handleRecvDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) +{ + /**** Find Files *****/ + + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + std::map::iterator cit; + if (mOwnId == peerId) + { + /* own requests must be passed to Servers */ +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvData() OwnId, so skip Clients..."; + std::cerr << std::endl; +#endif + } + else if (mClients.end() != (cit = mClients.find(hash))) + { +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvData() Matched to a Client."; + std::cerr << std::endl; +#endif + locked_handleServerRequest((cit->second).mCreator, peerId, hash, size, offset, chunksize); + return true; + } + + std::map::iterator sit; + if (mServers.end() != (sit = mServers.find(hash))) + { +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvData() Matched to a Provider."; + std::cerr << std::endl; +#endif + locked_handleServerRequest(sit->second, peerId, hash, size, offset, chunksize); + return true; + } + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleRecvData() No Match... adding to Search Queue."; + std::cerr << std::endl; +#endif + + /* Add to Search Queue */ + mSearchQueue.push_back( ftRequest(FT_DATA_REQ, peerId, hash, size, offset, chunksize, NULL)); + + return true; +} + +bool ftDataMultiplex::locked_handleServerRequest(ftFileProvider *provider, + std::string peerId, std::string hash, uint64_t size, + uint64_t offset, uint32_t chunksize) +{ + if(chunksize > std::min(size,uint64_t(10*1024*1024))) + { + std::cerr << "Warning: peer " << peerId << " is asking a large chunk (s=" << chunksize << ") for hash " << hash << ", filesize=" << size << ". This is unexpected." << std::endl ; + return false ; + } + void *data = malloc(chunksize); + + if(data == NULL) + { + std::cerr << "WARNING: Could not allocate data for a chunksize of " << chunksize << std::endl ; + return false ; + } +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::locked_handleServerRequest()"; + std::cerr << "\t peer: " << peerId << " hash: " << hash; + std::cerr << " size: " << size; + std::cerr << std::endl; + std::cerr << "\t offset: " << offset; + std::cerr << " chunksize: " << chunksize << " data: " << data; + std::cerr << std::endl; +#endif + + if (provider->getFileData(peerId,offset, chunksize, data)) + { + /* send data out */ + sendData(peerId, hash, size, offset, chunksize, data); + return true; + } +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::locked_handleServerRequest()"; + std::cerr << " FAILED"; + std::cerr << std::endl; +#endif + free(data); + + return false; +} + +bool ftDataMultiplex::getClientChunkMap(const std::string& upload_hash,const std::string& peerId,CompressedChunkMap& cmap) +{ + bool too_old = false; + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + std::map::iterator sit = mServers.find(upload_hash); + + if(mServers.end() == sit) + return false ; + + sit->second->getClientMap(peerId,cmap,too_old) ; + } + + // If the map is too old then we should ask an other map to the peer. + // + if(too_old) + sendChunkMapRequest(peerId,upload_hash,true); + + return true ; +} + +bool ftDataMultiplex::sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) +{ + return mDataSend->sendChunkMapRequest(peer_id,hash,is_client); +} +bool ftDataMultiplex::sendCRC32MapRequest(const std::string& peer_id,const std::string& hash) +{ + return mDataSend->sendCRC32MapRequest(peer_id,hash); +} +void ftDataMultiplex::deleteUnusedServers() +{ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + //scan the uploads list in ftdatamultiplex and delete the items which time out + time_t now = time(NULL); + + for(std::map::iterator sit(mServers.begin());sit != mServers.end();) + if(sit->second->purgeOldPeers(now,10)) + { +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::deleteUnusedServers(): provider " << (void*)sit->second << " has no active peers. Removing. Now=" << now << std::endl ; +#endif + // We don't delete servers that are clients at the same time ! + if(dynamic_cast(sit->second) == NULL) + { +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::deleteUnusedServers(): deleting file provider " << (void*)sit->second << std::endl ; +#endif + delete sit->second; + } +#ifdef MPLEX_DEBUG + else + std::cerr << "ftDataMultiplex::deleteUnusedServers(): " << (void*)sit->second << " was not deleted because it's also a file creator." << std::endl ; +#endif + + std::map::iterator tmp(sit); + ++tmp ; + + mServers.erase(sit); + + sit = tmp ; + } + else + ++sit ; +} + +bool ftDataMultiplex::handleSearchRequest(const std::string& peerId, const std::string& hash) +{ +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleSearchRequest("; + std::cerr << peerId << ", " << hash << "...)"; + std::cerr << std::endl; +#endif + +// { +// RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ +// +// /* Check for bad requests */ +// std::map::iterator bit; +// if (mUnknownHashs.end() != (bit = mUnknownHashs.find(hash))) +// { +// +//#ifdef MPLEX_DEBUG +// std::cerr << "ftDataMultiplex::handleSearchRequest("; +// std::cerr << " Found Ignore Hash ... done"; +// std::cerr << std::endl; +//#endif +// +// /* We've previously rejected this one, so ignore */ +// return false; +// } +// } + + + /* + * Do Actual search + * Could be Cache File, Local or Extra + * (anywhere but remote really) + * + * the network wide and browsable flags are needed, otherwise results get filtered. + * For tunnel creation, the check of browsable/network wide flag is already done, so + * if we get a file download packet here, the source is already allowed to download it. + * + */ + + FileInfo info; + uint32_t hintflags = ( RS_FILE_HINTS_NETWORK_WIDE + | RS_FILE_HINTS_BROWSABLE + | RS_FILE_HINTS_CACHE + | RS_FILE_HINTS_EXTRA + | RS_FILE_HINTS_LOCAL + | RS_FILE_HINTS_SPEC_ONLY); + + if (mSearch->search(hash, hintflags, info)) + { + + /* setup a new provider */ + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + // We might already have a file provider, if two requests have got stacked in the request queue. So let's + // check that before. + +#ifdef MPLEX_DEBUG + std::cerr << "ftDataMultiplex::handleSearchRequest("; + std::cerr << " Found Local File, sharing..."; +#endif + std::map::const_iterator it = mServers.find(hash) ; + ftFileProvider *provider ; + + if(it == mServers.end()) + { + provider = new ftFileProvider(info.path, info.size, hash); + mServers[hash] = provider; +#ifdef MPLEX_DEBUG + std::cerr << " created new file provider " << (void*)provider << std::endl; +#endif + } + else + { +#ifdef MPLEX_DEBUG + std::cerr << " re-using existing file provider " << (void*)it->second << std::endl; +#endif + } + + return true; + } + // Now check wether the required file is actually being downloaded. In such a case, + // setup the file provider to be the file creator itself. Warning: this server should not + // be deleted when not used anymore. We need to restrict this to client peers that are + // not ourself, since the file transfer also handles the local cache traffic (this + // is something to be changed soon!!) + // + + if(peerId != mOwnId) + { + RsStackMutex stack(dataMtx); /******* LOCK MUTEX ******/ + + std::map::const_iterator it(mClients.find(hash)) ; + + if(it != mClients.end()) + { + mServers[hash] = it->second.mCreator ; + return true; + } + } + + return false; +} + + + + + diff --git a/libretroshare/src/ft/ftdatamultiplex.h b/libretroshare/src/ft/ftdatamultiplex.h new file mode 100644 index 000000000..021ef4914 --- /dev/null +++ b/libretroshare/src/ft/ftdatamultiplex.h @@ -0,0 +1,172 @@ +/* + * libretroshare/src/ft: ftdatamultiplex.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_DATA_MULTIPLEX_HEADER +#define FT_DATA_MULTIPLEX_HEADER + +/* + * ftDataMultiplexModule. + * + * This multiplexes the data from PQInterface to the ftTransferModules. + */ + +class ftTransferModule; +class ftFileProvider; +class ftFileCreator; +class ftSearch; + +#include +#include +#include +#include + +#include "util/rsthreads.h" + +#include "ft/ftdata.h" +#include "retroshare/rsfiles.h" + + +class ftClient +{ + public: + + ftClient() :mModule(NULL), mCreator(NULL) { return; } + ftClient(ftTransferModule *module, ftFileCreator *creator); + + ftTransferModule *mModule; + ftFileCreator *mCreator; +}; + +class ftRequest +{ + public: + + ftRequest(uint32_t type, std::string peerId, std::string hash, uint64_t size, uint64_t offset, uint32_t chunk, void *data); + + ftRequest() + :mType(0), mSize(0), mOffset(0), mChunk(0), mData(NULL) { return; } + + uint32_t mType; + std::string mPeerId; + std::string mHash; + uint64_t mSize; + uint64_t mOffset; + uint32_t mChunk; + void *mData; +}; + + + +class ftDataMultiplex: public ftDataRecv, public RsQueueThread +{ + + public: + + ftDataMultiplex(std::string ownId, ftDataSend *server, ftSearch *search); + + /* ftController Interface */ + bool addTransferModule(ftTransferModule *mod, ftFileCreator *f); + bool removeTransferModule(std::string hash); + + /* data interface */ + /* get Details of File Transfers */ + bool FileUploads(std::list &hashs); + bool FileDownloads(std::list &hashs); + bool FileDetails(const std::string &hash, uint32_t hintsflag, FileInfo &info); + + void deleteUnusedServers() ; + + + /*************** SEND INTERFACE (calls ftDataSend) *******************/ + + /* Client Send */ + bool sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize); + + /* Server Send */ + bool sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); + + /* Server/client Send */ + bool sendChunkMapRequest(const std::string& peerId, const std::string& hash,bool is_client) ; + + /* Client Send */ + bool sendCRC32MapRequest(const std::string& peerId, const std::string& hash) ; + + /*************** RECV INTERFACE (provides ftDataRecv) ****************/ + + /* Client Recv */ + virtual bool recvData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); + /* Server Recv */ + virtual bool recvDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize); + + /// Receive a request for a chunk map + virtual bool recvChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) ; + /// Receive a chunk map + virtual bool recvChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap,bool is_client) ; + /// Receive a CRC map + virtual bool recvCRC32Map(const std::string& peer_id,const std::string& hash,const CRC32Map& crc_map) ; + /// Receive a CRC map request + virtual bool recvCRC32MapRequest(const std::string& peer_id,const std::string& hash) ; + + // Returns the chunk map from the file uploading client. Also initiates a chunk map request if this + // map is too old. This supposes that the caller will ask again in a few seconds. + // + bool getClientChunkMap(const std::string& upload_hash,const std::string& peer_id,CompressedChunkMap& map) ; + + protected: + + /* Overloaded from RsQueueThread */ + virtual bool workQueued(); + virtual bool doWork(); + + private: + + /* Handling Job Queues */ + bool handleRecvData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); + bool handleRecvDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize); + bool handleSearchRequest(const std::string& peerId, const std::string& hash); + bool handleRecvClientChunkMapRequest(const std::string& peerId, const std::string& hash) ; + bool handleRecvServerChunkMapRequest(const std::string& peerId, const std::string& hash) ; + bool handleRecvCRC32MapRequest(const std::string& peerId, const std::string& hash) ; + + /* We end up doing the actual server job here */ + bool locked_handleServerRequest(ftFileProvider *provider, std::string peerId, std::string hash, uint64_t size, uint64_t offset, uint32_t chunksize); + + RsMutex dataMtx; + + std::map mClients; + std::map mServers; + + std::list mRequestQueue; + std::list mSearchQueue; +// std::map mUnknownHashs; + + ftDataSend *mDataSend; + ftSearch *mSearch; + std::string mOwnId; + + friend class ftServer; +}; + +#endif diff --git a/libretroshare/src/ft/ftdbase.cc b/libretroshare/src/ft/ftdbase.cc new file mode 100644 index 000000000..3651ca06f --- /dev/null +++ b/libretroshare/src/ft/ftdbase.cc @@ -0,0 +1,403 @@ +/* + * libretroshare/src/ft: ftdbase.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "ft/ftdbase.h" +#include "util/rsdir.h" + +#include "serialiser/rsconfigitems.h" + +//#define DB_DEBUG 1 + +ftFiStore::ftFiStore(CacheStrapper *cs, CacheTransfer *cft, NotifyBase *cb_in,p3ConnectMgr *cnmgr, + RsPeerId ownid, std::string cachedir) + :FileIndexStore(cs, cft, cb_in,cnmgr, ownid, cachedir) +{ + return; +} + +bool ftFiStore::search(const std::string &hash, uint32_t hintflags, FileInfo &info) const +{ + /* could use hintflags to specify which bits of fileinfo to use additionally. + eg. hintflags & FT_SEARCH_PEER_ID, then only return matching peers + hash. + eg. hintflags & FT_SEARCH_NAME, then only return matching name + hash. + * + * Still to see if concept is worthwhle + */ + +#ifdef DB_DEBUG + std::cerr << "ftFiStore::search(" << hash << "," << hintflags; + std::cerr << ")"; + std::cerr << std::endl; +#endif + + std::list results; + std::list::iterator it; + + if (SearchHash(hash, results)) + { + bool first = true; + for(it = results.begin(); it != results.end(); it++) + { +#ifdef DB_DEBUG + std::cerr << "ftFiStore::search() found: "; + std::cerr << it->name << " (" << it->size; + std::cerr << ") @ " << it->id << " = " << hash; + std::cerr << std::endl; +#endif + bool fullmatch = true; + +// if (it->size != size) +// fullmatch = false; + + +#if 0 + if (hintflags & FT_SEARCH_PEER_ID) + { + pit = std::find(info.srcIds.begin(), + info.srcId.end(). it->id); + if (pit == info.srcIds.end()) + { + fullmatch = false; + } + } +#endif + + + if (fullmatch) + { + if (first) + { + first = false; + info.fname = it->name; + info.size = it->size; + info.hash = it->hash; + + } + + TransferInfo ti; + ti.peerId = it->id; + ti.name = it->name; + ti.tfRate = 0; + info.peers.push_back(ti); + } + } + + /**** DEPENDS ON SOURCES! + info.downloadStatus = FT_STATE_COMPLETE: + ****/ + + /* if the first flag is cleared, we've definitely + * had a full match!. + */ + + if (!first) + return true; + } + return false; +} + + +ftFiMonitor::ftFiMonitor(CacheStrapper *cs,NotifyBase *cb_in, std::string cachedir, std::string pid,const std::string& config_dir) + :FileIndexMonitor(cs,cb_in, cachedir, pid,config_dir), p3Config(CONFIG_TYPE_FT_SHARED) +{ + return; +} + +bool ftFiMonitor::search(const std::string &hash, uint32_t hintflags, FileInfo &info) const +{ + uint64_t fsize; + std::string path; + +#ifdef DB_DEBUG + std::cerr << "ftFiMonitor::search(" << hash << "," << hintflags; + std::cerr << ")"; + std::cerr << std::endl; +#endif + + // Setup search flags according to hintflags. Originally flags was 0. I (cyril) don't know + // why we don't just pass hintflags there, so I tried to keep the idea. + // + uint32_t flags = hintflags & (RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE); + + if(findLocalFile(hash, flags, path, fsize)) + { + /* fill in details */ +#ifdef DB_DEBUG + std::cerr << "ftFiMonitor::search() found: "; + std::cerr << path; + std::cerr << " = " << hash << "," << fsize; + std::cerr << std::endl; +#endif + + info.size = fsize; + info.fname = RsDirUtil::getTopDir(path); + info.path = path; + + return true; + } + + return false; +}; + +int ftFiMonitor::watchPeriod() const +{ + return getPeriod() ; +} +void ftFiMonitor::setWatchPeriod(int seconds) +{ + setPeriod(seconds) ;// call FileIndexMonitor + IndicateConfigChanged() ; +} + +void ftFiMonitor::setRememberHashCacheDuration(uint32_t days) +{ + setRememberHashFilesDuration(days) ; // calls FileIndexMonitor + IndicateConfigChanged() ; +} +uint32_t ftFiMonitor::rememberHashCacheDuration() const +{ + return rememberHashFilesDuration() ; // calls FileIndexMonitor +} +void ftFiMonitor::setRememberHashCache(bool b) +{ + setRememberHashFiles(b) ; // calls FileIndexMonitor + IndicateConfigChanged() ; +} +bool ftFiMonitor::rememberHashCache() +{ + return rememberHashFiles() ; // calls FileIndexMonitor +} +void ftFiMonitor::clearHashCache() +{ + clearHashFiles() ; +} + +/******* LOAD / SAVE CONFIG List. + * + * + * + * + */ + +RsSerialiser *ftFiMonitor::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + + /* add in the types we need! */ + rss->addSerialType(new RsFileConfigSerialiser()); + rss->addSerialType(new RsGeneralConfigSerialiser()); + + return rss; +} + +const std::string hash_cache_duration_ss("HASH_CACHE_DURATION"); +const std::string hash_cache_ss("HASH_CACHE"); +const std::string watch_file_duration_ss("WATCH_FILES_DELAY"); + +bool ftFiMonitor::saveList(bool &cleanup, std::list& sList) +{ + + + cleanup = true; + +#ifdef DB_DEBUG + std::cerr << "ftFiMonitor::saveList()"; + std::cerr << std::endl; +#endif + + /* get list of directories */ + std::list dirList; + std::list::iterator it; + + getSharedDirectories(dirList); + + for(it = dirList.begin(); it != dirList.end(); it++) + { + RsFileConfigItem *fi = new RsFileConfigItem(); + fi->file.path = (*it).filename ; + fi->file.name = (*it).virtualname ; + fi->flags = (*it).shareflags ; + + sList.push_back(fi); + } + + std::map configMap; + + /* basic control parameters */ + { + std::ostringstream s ; + s << rememberHashFilesDuration() ; + + configMap[hash_cache_duration_ss] = s.str() ; + } + configMap[hash_cache_ss] = rememberHashFiles()?"YES":"NO" ; + + { + std::ostringstream s ; + s << watchPeriod() ; + + configMap[watch_file_duration_ss] = s.str() ; + } + + RsConfigKeyValueSet *rskv = new RsConfigKeyValueSet(); + + /* Convert to TLV */ + for(std::map::const_iterator mit = configMap.begin(); mit != configMap.end(); mit++) + { + RsTlvKeyValue kv; + kv.key = mit->first; + kv.value = mit->second; + + rskv->tlvkvs.pairs.push_back(kv); + } + + /* Add KeyValue to saveList */ + sList.push_back(rskv); + + return true; +} + + +bool ftFiMonitor::loadList(std::list& load) +{ + /* for each item, check it exists .... + * - remove any that are dead (or flag?) + */ + +#ifdef DEBUG_ELIST + std::cerr << "ftFiMonitor::loadList()"; + std::cerr << std::endl; +#endif + + std::list dirList; + + std::list::iterator it; + for(it = load.begin(); it != load.end(); it++) + { + RsConfigKeyValueSet *rskv ; + /* switch on type */ + if (NULL != (rskv = dynamic_cast(*it))) + { + /* make into map */ + std::map configMap; + std::map::const_iterator mit ; + + for(std::list::const_iterator kit = rskv->tlvkvs.pairs.begin(); kit != rskv->tlvkvs.pairs.end(); kit++) + { + configMap[kit->key] = kit->value; + } + + if (configMap.end() != (mit = configMap.find(hash_cache_duration_ss))) + { + uint32_t t=0 ; + if(sscanf(mit->second.c_str(),"%d",&t) == 1) + setRememberHashFilesDuration(t); + } + if(configMap.end() != (mit = configMap.find(hash_cache_ss))) + setRememberHashFiles( mit->second == "YES") ; + + if(configMap.end() != (mit = configMap.find(watch_file_duration_ss))) + { + int t=0 ; + if(sscanf(mit->second.c_str(),"%d",&t) == 1) + setWatchPeriod(t); + } + } + + RsFileConfigItem *fi = dynamic_cast(*it); + if (!fi) + { + delete (*it); + continue; + } + + /* ensure that it exists? */ + + SharedDirInfo info ; + info.filename = RsDirUtil::convertPathToUnix(fi->file.path); + info.virtualname = fi->file.name; + info.shareflags = fi->flags & (RS_FILE_HINTS_BROWSABLE | RS_FILE_HINTS_NETWORK_WIDE) ; + + dirList.push_back(info) ; + } + + /* set directories */ + setSharedDirectories(dirList); + return true; +} + +void ftFiMonitor::updateShareFlags(const SharedDirInfo& info) +{ + FileIndexMonitor::updateShareFlags(info); + + /* flag for config */ + IndicateConfigChanged(); +} + +void ftFiMonitor::setSharedDirectories(const std::list& dirList) +{ + FileIndexMonitor::setSharedDirectories(dirList); + + /* flag for config */ + IndicateConfigChanged(); +} + + + +ftCacheStrapper::ftCacheStrapper(p3ConnectMgr *cm) + :CacheStrapper(cm) +{ + return; +} + + /* overloaded search function */ +bool ftCacheStrapper::search(const std::string &hash, uint32_t hintflags, FileInfo &info) const +{ +#ifdef DB_DEBUG + std::cerr << "ftCacheStrapper::search(" << hash << "," << hintflags; + std::cerr << ")"; + std::cerr << std::endl; +#endif + + CacheData data; + if (findCache(hash, data)) + { +#ifdef DB_DEBUG + std::cerr << "ftCacheStrapper::search() found: "; + std::cerr << data.path << "/" << data.name; + std::cerr << " = " << data.hash << "," << data.size; + std::cerr << std::endl; +#endif + + /* ... */ + info.size = data.size; + info.fname = data.name; + info.path = data.path + "/" + data.name; + + return true; + } + return false; +} + diff --git a/libretroshare/src/ft/ftdbase.h b/libretroshare/src/ft/ftdbase.h new file mode 100644 index 000000000..715824e91 --- /dev/null +++ b/libretroshare/src/ft/ftdbase.h @@ -0,0 +1,101 @@ +/* + * libretroshare/src/ft: ftdbase.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_DBASE_INTERFACE_HEADER +#define FT_DBASE_INTERFACE_HEADER + +/* + * ftdbase. + * + * Wrappers for the Cache/FiStore/FiMonitor classes. + * So they work in the ft world. + */ + +class p3ConnectMgr ; + +#include "ft/ftsearch.h" +#include "pqi/p3cfgmgr.h" + +#include "dbase/fistore.h" +#include "dbase/fimonitor.h" +#include "dbase/cachestrapper.h" + + +class ftFiStore: public FileIndexStore, public ftSearch +{ + public: + ftFiStore(CacheStrapper *cs, CacheTransfer *cft, NotifyBase *cb_in, + p3ConnectMgr *, + RsPeerId ownid, std::string cachedir); + + /* overloaded search function */ +virtual bool search(const std::string &hash, uint32_t hintflags, FileInfo &info) const; +}; + +class ftFiMonitor: public FileIndexMonitor, public ftSearch, public p3Config +{ + public: + ftFiMonitor(CacheStrapper *cs,NotifyBase *cb_in, std::string cachedir, std::string pid,const std::string& config_dir); + + /* overloaded search function */ + virtual bool search(const std::string &hash, uint32_t hintflags, FileInfo &info) const; + + /* overloaded set dirs enables config indication */ + virtual void setSharedDirectories(const std::list& dirList); + virtual void updateShareFlags(const SharedDirInfo& info) ; + + void setRememberHashCacheDuration(uint32_t days) ; + uint32_t rememberHashCacheDuration() const ; + void setRememberHashCache(bool) ; + bool rememberHashCache() ; + void clearHashCache() ; + void setWatchPeriod(int seconds) ; // can be negative, which means auto-check disabled. + int watchPeriod() const ; + + /*** + * Configuration - store shared directories + */ + protected: + +virtual RsSerialiser *setupSerialiser(); +virtual bool saveList(bool &cleanup, std::list&); +virtual bool loadList(std::list& load); + + +}; + +class ftCacheStrapper: public CacheStrapper, public ftSearch +{ + public: + ftCacheStrapper(p3ConnectMgr *cm); + + /* overloaded search function */ +virtual bool search(const std::string &hash, uint32_t hintflags, FileInfo &info) const; + +}; + + +#endif + diff --git a/libretroshare/src/ft/ftextralist.cc b/libretroshare/src/ft/ftextralist.cc new file mode 100644 index 000000000..145e312dd --- /dev/null +++ b/libretroshare/src/ft/ftextralist.cc @@ -0,0 +1,480 @@ +/* + * libretroshare/src/ft: ftextralist.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#endif + +#include "ft/ftextralist.h" +#include "serialiser/rsconfigitems.h" +#include "util/rsdir.h" +#include + +/****** + * #define DEBUG_ELIST 1 + *****/ + +ftExtraList::ftExtraList() + :p3Config(CONFIG_TYPE_FT_EXTRA_LIST) +{ + return; +} + + +void ftExtraList::run() +{ + bool todo = false; + time_t cleanup = 0; + time_t now = 0; + + while (isRunning()) + { +#ifdef DEBUG_ELIST + //std::cerr << "ftExtraList::run() Iteration"; + //std::cerr << std::endl; +#endif + + now = time(NULL); + + { + RsStackMutex stack(extMutex); + + todo = (mToHash.size() > 0); + } + + if (todo) + { + /* Hash a file */ + hashAFile(); + +#ifdef WIN32 + Sleep(1); +#else + /* microsleep */ + usleep(10); +#endif + } + else + { + /* cleanup */ + if (cleanup < now) + { + cleanupOldFiles(); + cleanup = now + CLEANUP_PERIOD; + } + + /* sleep */ +#ifdef WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + } +} + + + +void ftExtraList::hashAFile() +{ +#ifdef DEBUG_ELIST + std::cerr << "ftExtraList::hashAFile()"; + std::cerr << std::endl; +#endif + + /* extract entry from the queue */ + FileDetails details; + + { + RsStackMutex stack(extMutex); + + if (mToHash.size() == 0) + return; + + details = mToHash.front(); + mToHash.pop_front(); + } + +#ifdef DEBUG_ELIST + std::cerr << "Hashing: " << details.info.path; + std::cerr << std::endl; +#endif + + /* hash it! */ + std::string name, hash; + //uint64_t size; + if (RsDirUtil::hashFile(details.info.path, details.info.fname, + details.info.hash, details.info.size)) + { + RsStackMutex stack(extMutex); + + /* stick it in the available queue */ + mFiles[details.info.hash] = details; + + /* add to the path->hash map */ + mHashedList[details.info.path] = details.info.hash; + + IndicateConfigChanged(); + } +} + + /*** + * If the File is alreay Hashed, then just add it in. + **/ + +bool ftExtraList::addExtraFile(std::string path, std::string hash, + uint64_t size, uint32_t period, uint32_t flags) +{ +#ifdef DEBUG_ELIST + std::cerr << "ftExtraList::addExtraFile() path: " << path; + std::cerr << " hash: " << hash; + std::cerr << " size: " << size; + std::cerr << " period: " << period; + std::cerr << " flags: " << flags; + + std::cerr << std::endl; +#endif + + RsStackMutex stack(extMutex); + + FileDetails details; + + details.info.path = path; + details.info.fname = RsDirUtil::getTopDir(path); + details.info.hash = hash; + details.info.size = size; + details.info.age = time(NULL) + period; /* if time > this... cleanup */ + details.flags = flags; + + /* stick it in the available queue */ + mFiles[details.info.hash] = details; + + IndicateConfigChanged(); + + return true; +} + +bool ftExtraList::removeExtraFile(std::string hash, uint32_t flags) +{ +#ifdef DEBUG_ELIST + std::cerr << "ftExtraList::removeExtraFile()"; + std::cerr << " hash: " << hash; + std::cerr << " flags: " << flags; + + std::cerr << std::endl; +#endif + + RsStackMutex stack(extMutex); + + std::map::iterator it; + it = mFiles.find(hash); + if (it == mFiles.end()) + { + return false; + } + + mFiles.erase(it); + + IndicateConfigChanged(); + + return true; +} + +bool ftExtraList::moveExtraFile(std::string fname, std::string hash, uint64_t size, + std::string destpath) +{ + RsStackMutex stack(extMutex); + + std::map::iterator it; + it = mFiles.find(hash); + if (it == mFiles.end()) + { + return false; + } + + std::string path = destpath + '/' + fname; + if (RsDirUtil::renameFile(it->second.info.path, path)) + { + /* rename */ + it->second.info.path = path; + it->second.info.fname = fname; + IndicateConfigChanged(); + } + + return true; +} + + + +bool ftExtraList::cleanupOldFiles() +{ +#ifdef DEBUG_ELIST + std::cerr << "ftExtraList::cleanupOldFiles()"; + std::cerr << std::endl; +#endif + + RsStackMutex stack(extMutex); + + time_t now = time(NULL); + + std::list toRemove; + std::list::iterator rit; + + std::map::iterator it; + for(it = mFiles.begin(); it != mFiles.end(); it++) + { + /* check timestamps */ + if ((time_t)it->second.info.age < now) + { + toRemove.push_back(it->first); + } + } + + if (toRemove.size() > 0) + { + /* remove items */ + for(rit = toRemove.begin(); rit != toRemove.end(); rit++) + { + if (mFiles.end() != (it = mFiles.find(*rit))) + { + cleanupEntry(it->second.info.path, it->second.flags); + mFiles.erase(it); + } + } + IndicateConfigChanged(); + } + return true; +} + + +bool ftExtraList::cleanupEntry(std::string path, uint32_t flags) +{ + if (flags & RS_FILE_CONFIG_CLEANUP_DELETE) + { + /* Delete the file? - not yet! */ + } + return true; +} + + /*** + * Hash file, and add to the files, + * file is removed after period. + **/ + +bool ftExtraList::hashExtraFile(std::string path, uint32_t period, uint32_t flags) +{ +#ifdef DEBUG_ELIST + std::cerr << "ftExtraList::hashExtraFile() path: " << path; + std::cerr << " period: " << period; + std::cerr << " flags: " << flags; + + std::cerr << std::endl; +#endif + + /* add into queue */ + RsStackMutex stack(extMutex); + + FileDetails details(path, period, flags); + details.info.age = time(NULL) + period; + mToHash.push_back(details); + + return true; +} + +bool ftExtraList::hashExtraFileDone(std::string path, FileInfo &info) +{ +#ifdef DEBUG_ELIST + std::cerr << "ftExtraList::hashExtraFileDone()"; + std::cerr << std::endl; +#endif + + std::string hash; + { + /* Find in the path->hash map */ + RsStackMutex stack(extMutex); + + std::map::iterator it; + if (mHashedList.end() == (it = mHashedList.find(path))) + { + return false; + } + hash = it->second; + } + return search(hash, 0, info); +} + + /*** + * Search Function - used by File Transfer + * + **/ +bool ftExtraList::search(const std::string &hash, uint32_t hintflags, FileInfo &info) const +{ + +#ifdef DEBUG_ELIST + std::cerr << "ftExtraList::search()"; + std::cerr << std::endl; +#endif + + /* find hash */ + std::map::const_iterator fit; + if (mFiles.end() == (fit = mFiles.find(hash))) + { + return false; + } + + info = fit->second.info; + return true; +} + + + /*** + * Configuration - store extra files. + * + **/ + +RsSerialiser *ftExtraList::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + + /* add in the types we need! */ + rss->addSerialType(new RsFileConfigSerialiser()); + return rss; +} + +bool ftExtraList::saveList(bool &cleanup, std::list& sList) +{ + + + cleanup = true; + + /* called after each item is added */ + + /* create a list of fileitems with + * age used to specify its timeout. + */ + +#ifdef DEBUG_ELIST + std::cerr << "ftExtraList::saveList()"; + std::cerr << std::endl; +#endif + + RsStackMutex stack(extMutex); + + + std::map::const_iterator it; + for(it = mFiles.begin(); it != mFiles.end(); it++) + { + RsFileConfigItem *fi = new RsFileConfigItem(); + fi->file.path = (it->second).info.path; + fi->file.name = (it->second).info.fname; + fi->file.hash = (it->second).info.hash; + fi->file.filesize = (it->second).info.size; + fi->file.age = (it->second).info.age; + fi->flags = (it->second).flags; + + sList.push_back(fi); + } + + return true; +} + + +bool ftExtraList::loadList(std::list& load) +{ + /* for each item, check it exists .... + * - remove any that are dead (or flag?) + */ + +#ifdef DEBUG_ELIST + std::cerr << "ftExtraList::loadList()"; + std::cerr << std::endl; +#endif + + time_t ts = time(NULL); + + + std::list::iterator it; + for(it = load.begin(); it != load.end(); it++) + { + + RsFileConfigItem *fi = dynamic_cast(*it); + if (!fi) + { + delete (*it); + continue; + } + + /* open file */ + FILE *fd = RsDirUtil::rs_fopen(fi->file.path.c_str(), "rb"); + if (fd == NULL) + { + delete (*it); + continue; + } + + fclose(fd); + fd = NULL ; + + if (ts > (time_t)fi->file.age) + { + /* to old */ + cleanupEntry(fi->file.path, fi->flags); + delete (*it); + continue ; + } + + /* add into system */ + FileDetails file; + + RsStackMutex stack(extMutex); + + FileDetails details; + + details.info.path = fi->file.path; + details.info.fname = fi->file.name; + details.info.hash = fi->file.hash; + details.info.size = fi->file.filesize; + details.info.age = fi->file.age; /* time that we remove it. */ + details.flags = fi->flags; + + /* stick it in the available queue */ + mFiles[details.info.hash] = details; + delete (*it); + + /* short sleep */ +#ifndef WINDOWS_SYS +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + usleep(1000); /* 1000 per second */ + +#else +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + Sleep(1); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + } + return true; +} + diff --git a/libretroshare/src/ft/ftextralist.h b/libretroshare/src/ft/ftextralist.h new file mode 100644 index 000000000..afdc3e685 --- /dev/null +++ b/libretroshare/src/ft/ftextralist.h @@ -0,0 +1,175 @@ +/* + * libretroshare/src/ft: ftextralist.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_FILE_EXTRA_LIST_HEADER +#define FT_FILE_EXTRA_LIST_HEADER + +/* + * ftFileExtraList + * + * This maintains a list of 'Extra Files' to share with peers. + * + * Files are added via: + * 1) For Files which have been hashed already: + * addExtraFile(std::string path, std::string hash, uint64_t size, uint32_t period, uint32_t flags); + * + * 2) For Files to be hashed: + * hashExtraFile(std::string path, uint32_t period, uint32_t flags); + * + * Results of Hashing can be retrieved via: + * hashExtraFileDone(std::string path, std::string &hash, uint64_t &size); + * + * Files can be searched for via: + * searchExtraFiles(std::string hash, ftFileDetail file); + * + * This Class is Mutexed protected, and has a thread in it which checks the files periodically. + * If a file is found to have changed... It is discarded from the list - and not updated. + * + * this thread is also used to hash added files. + * + * The list of extra files is stored using the configuration system. + * + */ + +#include +#include +#include + +#include "ft/ftsearch.h" +#include "util/rsthreads.h" +#include "retroshare/rsfiles.h" +#include "pqi/p3cfgmgr.h" + +class FileDetails +{ + public: + FileDetails() +{ + return; +} + + FileDetails(std::string path, uint32_t p, uint32_t f) +{ + info.path = path; + period = p; + flags = f; +} + + FileDetails(FileInfo &i, uint32_t p, uint32_t f) +{ + info = i; + period = p; + flags = f; +} + + FileInfo info; + +#if 0 /*** WHAT IS NEEDED ***/ + std::list sources; + std::string path; + std::string fname; + std::string hash; + uint64_t size; +#endif + + uint32_t start; + uint32_t period; + uint32_t flags; +}; + +const uint32_t FT_DETAILS_CLEANUP = 0x0100; /* remove when it expires */ +const uint32_t FT_DETAILS_LOCAL = 0x0001; +const uint32_t FT_DETAILS_REMOTE = 0x0002; + +const uint32_t CLEANUP_PERIOD = 600; /* 10 minutes */ + + +class ftExtraList: public RsThread, public p3Config, public ftSearch +{ + + public: + + ftExtraList(); + + /*** + * If the File is alreay Hashed, then just add it in. + **/ + +bool addExtraFile(std::string path, std::string hash, + uint64_t size, uint32_t period, uint32_t flags); + +bool removeExtraFile(std::string hash, uint32_t flags); +bool moveExtraFile(std::string fname, std::string hash, uint64_t size, + std::string destpath); + + + /*** + * Hash file, and add to the files, + * file is removed after period. + **/ + +bool hashExtraFile(std::string path, uint32_t period, uint32_t flags); +bool hashExtraFileDone(std::string path, FileInfo &info); + + /*** + * Search Function - used by File Transfer + * implementation of ftSearch. + * + **/ +virtual bool search(const std::string &hash, uint32_t hintflags, FileInfo &info) const; + + /*** + * Thread Main Loop + **/ +virtual void run(); + + /*** + * Configuration - store extra files. + * + **/ + protected: +virtual RsSerialiser *setupSerialiser(); +virtual bool saveList(bool &cleanup, std::list&); +virtual bool loadList(std::list& load); + + private: + + /* Worker Functions */ +void hashAFile(); +bool cleanupOldFiles(); +bool cleanupEntry(std::string path, uint32_t flags); + + mutable RsMutex extMutex; + + std::list mToHash; + + std::map mHashedList; /* path -> hash ( not saved ) */ + std::map mFiles; +}; + + + + +#endif diff --git a/libretroshare/src/ft/ftfilecreator.cc b/libretroshare/src/ft/ftfilecreator.cc new file mode 100644 index 000000000..abbc22311 --- /dev/null +++ b/libretroshare/src/ft/ftfilecreator.cc @@ -0,0 +1,589 @@ +#include "ftfilecreator.h" +#include +#include +#include +#include + +/******* + * #define FILE_DEBUG 1 + ******/ + +#define CHUNK_MAX_AGE 40 +#define MAX_FTCHUNKS_PER_PEER 5 + +/*********************************************************** +* +* ftFileCreator methods +* +***********************************************************/ + +ftFileCreator::ftFileCreator(const std::string& path, uint64_t size, const std::string& hash,bool assume_availability) + : ftFileProvider(path,size,hash), chunkMap(size,assume_availability) +{ + /* + * FIXME any inits to do? + */ + +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator()"; + std::cerr << std::endl; + std::cerr << "\tpath: " << path; + std::cerr << std::endl; + std::cerr << "\tsize: " << size; + std::cerr << std::endl; + std::cerr << "\thash: " << hash; + std::cerr << std::endl; +#endif + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + time_t now = time(NULL) ; + _last_recv_time_t = now ; + _creation_time = now ; +} + +bool ftFileCreator::getFileData(const std::string& peer_id,uint64_t offset, uint32_t &chunk_size, void *data) +{ + // Only send the data if we actually have it. + // +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::getFileData(). Asked for offset=" << offset << ", size=" << chunk_size << std::endl ; +#endif + bool have_it = false ; + { + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + have_it = chunkMap.isChunkAvailable(offset, chunk_size) ; + } +#ifdef FILE_DEBUG + if(have_it) + std::cerr << "ftFileCreator::getFileData(). Have it" << std::endl ; + else + std::cerr << "ftFileCreator::getFileData(). Don't have it" << std::endl ; +#endif + + if(have_it) + return ftFileProvider::getFileData(peer_id,offset, chunk_size, data); + else + return false ; +} + +time_t ftFileCreator::creationTimeStamp() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + return _creation_time ; +} +time_t ftFileCreator::lastRecvTimeStamp() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + return _last_recv_time_t ; +} +void ftFileCreator::resetRecvTimeStamp() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + _last_recv_time_t = time(NULL) ; +} + +void ftFileCreator::closeFile() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + if(fd != NULL) + { +#ifdef FILE_DEBUG + std::cerr << "CLOSED FILE " << (void*)fd << " (" << file_name << ")." << std::endl ; +#endif + fclose(fd) ; + } + + fd = NULL ; +} + +uint64_t ftFileCreator::getRecvd() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + return chunkMap.getTotalReceived() ; +} + +bool ftFileCreator::addFileData(uint64_t offset, uint32_t chunk_size, void *data) +{ +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::addFileData("; + std::cerr << offset; + std::cerr << ", " << chunk_size; + std::cerr << ", " << data << ")"; + std::cerr << " this: " << this; + std::cerr << std::endl; +#endif + /* dodgey checking outside of mutex... much check again inside FileAttrs(). */ + /* Check File is open */ + + if(!RsDiscSpace::checkForDiscSpace(RS_PARTIALS_DIRECTORY)) + return false ; + + bool complete = false ; + { + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + if (fd == NULL) + if (!locked_initializeFileAttrs()) + return false; + + /* + * check its at the correct location + */ + if (offset + chunk_size > mSize) + { + chunk_size = mSize - offset; + std::cerr <<"Chunk Size greater than total file size, adjusting chunk " << "size " << chunk_size << std::endl; + + } + + /* + * go to the offset of the file + */ + if (0 != fseeko64(this->fd, offset, SEEK_SET)) + { + std::cerr << "ftFileCreator::addFileData() Bad fseek at offset " << offset << ", fd=" << (void*)(this->fd) << ", size=" << mSize << ", errno=" << errno << std::endl; + return 0; + } + + if (1 != fwrite(data, chunk_size, 1, this->fd)) + { + std::cerr << "ftFileCreator::addFileData() Bad fwrite." << std::endl; + std::cerr << "ERRNO: " << errno << std::endl; + + return 0; + } + +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::addFileData() added Data..."; + std::cerr << std::endl; + std::cerr << " pos: " << offset; + std::cerr << std::endl; +#endif + /* + * Notify ftFileChunker about chunks received + */ + locked_notifyReceived(offset,chunk_size); + + complete = chunkMap.isComplete(); + } + if(complete) + { +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::addFileData() File is complete: closing" << std::endl ; +#endif + closeFile(); + } + + /* + * FIXME HANDLE COMPLETION HERE - Any better way? + */ + + return 1; +} + +void ftFileCreator::removeInactiveChunks() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::removeInactiveChunks(): looking for old chunks." << std::endl ; +#endif + std::vector to_remove ; + + chunkMap.removeInactiveChunks(to_remove) ; + +#ifdef FILE_DEBUG + if(!to_remove.empty()) + std::cerr << "ftFileCreator::removeInactiveChunks(): removing slice ids: " ; +#endif + // This double loop looks costly, but it's called on very few chunks, and not often, so it's ok. + // + for(uint32_t i=0;i::iterator it(mChunks.begin());it!=mChunks.end();) + if(it->second.id == to_remove[i]) + { + std::map::iterator tmp(it) ; + ++it ; + --mChunksPerPeer[tmp->second.peer_id].cnt ; + mChunks.erase(tmp) ; + } + else + ++it ; + } +#ifdef FILE_DEBUG + if(!to_remove.empty()) + std::cerr << std::endl ; +#endif +} + +void ftFileCreator::removeFileSource(const std::string& peer_id) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator:: removign file source " << peer_id << " from chunkmap." << std::endl ; +#endif + chunkMap.removeFileSource(peer_id) ; +} + +int ftFileCreator::locked_initializeFileAttrs() +{ +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::initializeFileAttrs() Filename: " << file_name << " this: " << this << std::endl; +#endif + + /* + * check if the file exists + * cant use FileProviders verion because that opens readonly. + */ + + if (fd) + return 1; + + /* + * check if the file exists + */ + + { +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::initializeFileAttrs() trying (r+b) " << file_name << " this: " << this << std::endl; +#endif + } + + /* + * attempt to open file + */ + + fd = RsDirUtil::rs_fopen(file_name.c_str(), "r+b"); + + if (!fd) + { + std::cerr << "ftFileCreator::initializeFileAttrs() Failed to open (r+b): "; + std::cerr << file_name << ", errno = " << errno << std::endl; + + std::cerr << "ftFileCreator::initializeFileAttrs() opening w+b"; + std::cerr << std::endl; + + /* try opening for write */ + fd = RsDirUtil::rs_fopen(file_name.c_str(), "w+b"); + if (!fd) + { + std::cerr << "ftFileCreator::initializeFileAttrs()"; + std::cerr << " Failed to open (w+b): "<< file_name << ", errno = " << errno << std::endl; + return 0; + } + } +#ifdef FILE_DEBUG + std::cerr << "OPENNED FILE " << (void*)fd << " (" << file_name << "), for r/w." << std::endl ; +#endif + + return 1; +} +ftFileCreator::~ftFileCreator() +{ + std::cerr << "Deleting file creator for " << file_name << std::endl; + + // Note: The file is actually closed in the parent, that is always a ftFileProvider. + // + /* + * FIXME Any cleanups specific to filecreator? + */ +} + + +int ftFileCreator::locked_notifyReceived(uint64_t offset, uint32_t chunk_size) +{ + /* ALREADY LOCKED */ +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::locked_notifyReceived( " << offset; + std::cerr << ", " << chunk_size << " )"; + std::cerr << " this: " << this; + std::cerr << std::endl; +#endif + + /* find the chunk */ + std::map::iterator it = mChunks.find(offset); + + if (it == mChunks.end()) + { +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::locked_notifyReceived() "; + std::cerr << " Failed to match to existing chunk - ignoring"; + std::cerr << std::endl; + + locked_printChunkMap(); +#endif + return 0; /* ignoring */ + } + + ftChunk chunk = it->second; + mChunks.erase(it); + + if (chunk.size != chunk_size) + { + /* partial : shrink chunk */ + chunk.size -= chunk_size; + chunk.offset += chunk_size; + mChunks[chunk.offset] = chunk; + } + else // notify the chunkmap that the slice is finished, and decrement the number of chunks for this peer. + { + chunkMap.dataReceived(chunk.id) ; + --mChunksPerPeer[chunk.peer_id].cnt ; + } + + _last_recv_time_t = time(NULL) ; + + /* otherwise there is another earlier block to go + */ + + return 1; +} + +FileChunksInfo::ChunkStrategy ftFileCreator::getChunkStrategy() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + return chunkMap.getStrategy() ; +} +void ftFileCreator::setChunkStrategy(FileChunksInfo::ChunkStrategy s) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + // Let's check, for safety. + if(s != FileChunksInfo::CHUNK_STRATEGY_STREAMING && s != FileChunksInfo::CHUNK_STRATEGY_RANDOM) + { + std::cerr << "ftFileCreator::ERROR: invalid chunk strategy " << s << "!" << " setting default value " << FileChunksInfo::CHUNK_STRATEGY_STREAMING << std::endl ; + s = FileChunksInfo::CHUNK_STRATEGY_STREAMING ; + } + +#ifdef FILE_DEBUG + std::cerr << "ftFileCtreator: setting chunk strategy to " << s << std::endl ; +#endif + chunkMap.setStrategy(s) ; +} + +/* Returns true if more to get + * But can return size = 0, if we are still waiting for the data. + */ + +bool ftFileCreator::getMissingChunk(const std::string& peer_id,uint32_t size_hint,uint64_t &offset, uint32_t& size,bool& source_chunk_map_needed) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ +#ifdef FILE_DEBUG + std::cerr << "ffc::getMissingChunk(...,"<< size_hint << ")"; + std::cerr << " this: " << this; + std::cerr << std::endl; + locked_printChunkMap(); +#endif + source_chunk_map_needed = false ; + + uint32_t& chunks_for_this_peer(mChunksPerPeer[peer_id].cnt) ; + + if(chunks_for_this_peer >= MAX_FTCHUNKS_PER_PEER) + { +#ifdef FILE_DEBUG + std::cerr << "ffc::getMissingChunk() too many chunks for peer " << peer_id << std::endl ; +#endif + return false ; + } + + /* else allocate a new chunk */ + + ftChunk chunk ; + + if(!chunkMap.getDataChunk(peer_id,size_hint,chunk,source_chunk_map_needed)) + return false ; + +#ifdef FILE_DEBUG + std::cerr << "ffc::getMissingChunk() Retrieved new chunk: " << chunk << std::endl ; +#endif + + mChunks[chunk.offset] = chunk ; + + offset = chunk.offset ; + size = chunk.size ; + + ++chunks_for_this_peer ; // increase number of chunks for this peer. + + return true; /* cos more data to get */ +} + +void ftFileCreator::getChunkMap(FileChunksInfo& info) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + chunkMap.getChunksInfo(info) ; + + // add info pending requests, handled by ftFileCreator + // + info.pending_slices.clear(); + + for(std::map::iterator it = mChunks.begin();it!=mChunks.end();++it) + { + int n = it->second.id / info.chunk_size ; + + FileChunksInfo::SliceInfo si ; + si.start = it->second.offset - n*info.chunk_size ; + si.size = it->second.size ; + si.peer_id = it->second.peer_id ; + + info.pending_slices[n].push_back(si) ; + } +} + +bool ftFileCreator::locked_printChunkMap() +{ +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator::locked_printChunkMap()"; + std::cerr << " this: " << this; + std::cerr << std::endl; +#endif + + /* check start point */ + std::cerr << "\tOutstanding Chunks:"; + std::cerr << std::endl; + + std::map::iterator it; + + for(it = mChunks.begin(); it != mChunks.end(); it++) + std::cerr << " " << it->second << std::endl ; + + std::cerr << "Active chunks per peer:" << std::endl ; + for(std::map::const_iterator it(mChunksPerPeer.begin());it!=mChunksPerPeer.end();++it) + std::cerr << " " << it->first << "\t: " << it->second.cnt << std::endl; + + return true; +} + +void ftFileCreator::setAvailabilityMap(const CompressedChunkMap& cmap) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + chunkMap.setAvailabilityMap(cmap) ; +#ifdef FILE_DEBUG + std::cerr << "ftFileCreator: setting chunkmap for hash " << hash << ": " ; + + for(uint32_t i=0;i 0) + { + uint32_t crc = RsDirUtil::rs_CRC32(buff,len) ; + + printf(" crc: %08x, ref: %08x : ",crc,ref[i]) ; + + if(crc != ref[i]) + { + printf(" CRC ERROR!!\n") ; + ++bad_chunks ; + ++incomplete_chunks ; + map.reset(i) ; + } + else + printf(" matched\n") ; + } + else + { + printf(" cannot fseek!\n") ; + ++bad_chunks ; + ++incomplete_chunks ; + map.reset(i) ; + } + } + else + { + printf(" incomplete.\n") ; + ++incomplete_chunks ; + } + } + + delete[] buff ; + + if(bad_chunks > 0) + chunkMap.setAvailabilityMap(map) ; + } + closeFile() ; + return true ; +} + + diff --git a/libretroshare/src/ft/ftfilecreator.h b/libretroshare/src/ft/ftfilecreator.h new file mode 100644 index 000000000..228321e89 --- /dev/null +++ b/libretroshare/src/ft/ftfilecreator.h @@ -0,0 +1,150 @@ +/* + * libretroshare/src/ft/ ftfilecreator.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_FILE_CREATOR_HEADER +#define FT_FILE_CREATOR_HEADER + +/* + * ftFileCreator + * + * TODO: Serialiser Load / Save. + * + */ +#include "ftfileprovider.h" +#include "ftchunkmap.h" +#include + +class ZeroInitCounter +{ + public: + ZeroInitCounter(): cnt(0) {} + uint32_t cnt ; +}; + +class ftFileCreator: public ftFileProvider +{ + public: + + ftFileCreator(const std::string& savepath, uint64_t size, const std::string& hash,bool assume_availability); + + ~ftFileCreator(); + + /* overloaded from FileProvider */ + virtual bool getFileData(const std::string& peer_id,uint64_t offset, uint32_t &chunk_size, void *data); + bool finished() ; + uint64_t getRecvd(); + + /// (temporarily) close the file, to save file descriptors. + void closeFile() ; + + void getChunkMap(FileChunksInfo& info) ; + + void setChunkStrategy(FileChunksInfo::ChunkStrategy s) ; + FileChunksInfo::ChunkStrategy getChunkStrategy() ; + + // Computes a sha1sum of the partial file, to check that the data is overall consistent. + // This function is not mutexed. This is a bit dangerous, but otherwise we might stuck the GUI for a + // long time. Therefore, we must pay attention not to call this function + // at a time file_name nor hash can be modified, which is quite easy. + + bool hashReceivedData(std::string& hash) ; + + // Checks the CRC32 of all chunks against the given CRC32 map. Re-flag the bad chunks as being void. + // bad_chunks: count of achieved chunks that don't match the CRC + // incomplete_chunks: count of any bad or not yet downloaded chunk + // + bool crossCheckChunkMap(const CRC32Map& ref,uint32_t& bad_chunks,uint32_t& incomplete_chunks) ; + /* + * creation functions for FileCreator + */ + + // Gets a new variable-sized chunk of size "size_hint" from the given peer id. The returned size, "size" is + // at most equal to size_hint. chunk_map_needed is set if + // - no chunkmap info is available. In such a case, the chunk info is irrelevant and false is returned. + // - the chunk info is too old. In tis case, true is returned, and the chunks info can be used. + // + bool getMissingChunk(const std::string& peer_id,uint32_t size_hint,uint64_t& offset, uint32_t& size,bool& is_chunk_map_too_old); + + // Takes care of purging any inactive chunks. This should be called regularly, because some peers may disconnect + // and let inactive chunks not finished. + // + void removeInactiveChunks() ; + + // removes the designated file source from the chunkmap. + void removeFileSource(const std::string& peer_id) ; + + // Returns resets the time stamp of the last data receive. + time_t lastRecvTimeStamp() ; + void resetRecvTimeStamp() ; + time_t creationTimeStamp() ; + + // actually store data in the file, and update chunks info + // + bool addFileData(uint64_t offset, uint32_t chunk_size, void *data); + + // Load/save the availability map for the file being downloaded, in a compact/compressed form. + // This is used for + // - loading and saving info about the current transfers + // - getting info about current chunks for the GUI + // - sending availability info to the peers for which we also are a source + // + virtual void getAvailabilityMap(CompressedChunkMap& cmap) ; + void setAvailabilityMap(const CompressedChunkMap& cmap) ; + + // Provides a complete per-chunk CRC32 map to client who want to check their data. + // This is overloads ftFileProvider, but returns false, because we can't ensure that unchecked chunks + // will provide a CRC32 that is faithful to the original hash. + // + virtual bool getCRC32Map(CRC32Map& crc_map) { return false ; } + + // This is called when receiving the availability map from a source peer, for the file being handled. + // + void setSourceMap(const std::string& peer_id,const CompressedChunkMap& map) ; + + protected: + + virtual int locked_initializeFileAttrs(); + + private: + + bool locked_printChunkMap(); + int locked_notifyReceived(uint64_t offset, uint32_t chunk_size); + /* + * structure to track missing chunks + */ + + uint64_t mStart; + uint64_t mEnd; + + std::map mChunks; + std::map mChunksPerPeer ; + + ChunkMap chunkMap ; + + time_t _last_recv_time_t ; /// last time stamp when data was received. Used for queue control. + time_t _creation_time ; /// time at which the file creator was created. Used to spot long-inactive transfers. +}; + +#endif // FT_FILE_CREATOR_HEADER diff --git a/libretroshare/src/ft/ftfileprovider.cc b/libretroshare/src/ft/ftfileprovider.cc new file mode 100644 index 000000000..c8c3329ee --- /dev/null +++ b/libretroshare/src/ft/ftfileprovider.cc @@ -0,0 +1,343 @@ +#include "ftfileprovider.h" +#include "ftchunkmap.h" + +#include "util/rsdir.h" +#include +#include + +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#endif // WINDOWS_SYS + +/******** +* #define DEBUG_FT_FILE_PROVIDER 1 +* #define DEBUG_TRANSFERS 1 // TO GET TIMESTAMPS of DATA READING +********/ + +#ifdef DEBUG_TRANSFERS + #include "util/rsprint.h" + #include +#endif + + + +static const time_t UPLOAD_CHUNK_MAPS_TIME = 20 ; // time to ask for a new chunkmap from uploaders in seconds. + +ftFileProvider::ftFileProvider(const std::string& path, uint64_t size, const std::string& hash) + : mSize(size), hash(hash), file_name(path), fd(NULL) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + +#ifdef DEBUG_FT_FILE_PROVIDER + std::cout << "Creating file provider for " << hash << std::endl ; +#endif +} + +ftFileProvider::~ftFileProvider() +{ +#ifdef DEBUG_FT_FILE_PROVIDER + std::cout << "ftFileProvider::~ftFileProvider(): Destroying file provider for " << hash << std::endl ; +#endif + if (fd!=NULL) { + fclose(fd); + fd = NULL ; +#ifdef DEBUG_FT_FILE_PROVIDER + std::cout << "ftFileProvider::~ftFileProvider(): closed file: " << hash << std::endl ; +#endif + } +} + +bool ftFileProvider::fileOk() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + return (fd != NULL); +} + +std::string ftFileProvider::getHash() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + return hash; +} + +uint64_t ftFileProvider::getFileSize() +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + return mSize; +} + +bool ftFileProvider::FileDetails(FileInfo &info) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + info.hash = hash; + info.size = mSize; + info.path = file_name; + info.fname = RsDirUtil::getTopDir(file_name); + + info.transfered = 0 ; // unused + info.lastTS = 0; + info.status = FT_STATE_DOWNLOADING ; + + info.peers.clear() ; + float total_transfer_rate = 0.0f ; + + for(std::map::const_iterator it(uploading_peers.begin());it!=uploading_peers.end();++it) + { + TransferInfo inf ; + inf.peerId = it->first ; + inf.status = FT_STATE_DOWNLOADING ; + inf.name = info.fname ; + inf.transfered = it->second.req_loc ; + + inf.tfRate = it->second.transfer_rate/1024.0 ; + total_transfer_rate += it->second.transfer_rate ; + info.lastTS = std::max(info.lastTS,it->second.lastTS); + + info.peers.push_back(inf) ; + } + info.tfRate = total_transfer_rate/1024.0 ; + + /* Use req_loc / req_size to estimate data rate */ + + return true; +} + +bool ftFileProvider::purgeOldPeers(time_t now,uint32_t max_duration) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + +#ifdef DEBUG_FT_FILE_PROVIDER + std::cerr << "ftFileProvider::purgeOldPeers(): " << (void*)this << ": examining peers." << std::endl ; +#endif + bool ret = true ; + for(std::map::iterator it(uploading_peers.begin());it!=uploading_peers.end();) + if( (*it).second.lastTS+max_duration < (uint32_t)now) + { +#ifdef DEBUG_FT_FILE_PROVIDER + std::cerr << "ftFileProvider::purgeOldPeers(): " << (void*)this << ": peer " << it->first << " is too old. Removing." << std::endl ; +#endif + std::map::iterator tmp = it ; + ++tmp ; + uploading_peers.erase(it) ; + it=tmp ; + } + else + { +#ifdef DEBUG_FT_FILE_PROVIDER + std::cerr << "ftFileProvider::purgeOldPeers(): " << (void*)this << ": peer " << it->first << " will be kept." << std::endl ; +#endif + ret = false ; + ++it ; + } + return ret ; +} + +void ftFileProvider::getAvailabilityMap(CompressedChunkMap& cmap) +{ + // We are here because the file we deal with is complete. So we return a plain map. + // + ChunkMap::buildPlainMap(mSize,cmap) ; +} + + +bool ftFileProvider::getFileData(const std::string& peer_id,uint64_t offset, uint32_t &chunk_size, void *data) +{ + /* dodgey checking outside of mutex... + * much check again inside FileAttrs(). + */ + if (fd == NULL) + if (!initializeFileAttrs()) + return false; + + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + /* + * FIXME: Warning of comparison between unsigned and signed int? + */ + + uint32_t data_size = chunk_size; + uint64_t base_loc = offset; + + if (base_loc + data_size > mSize) + { + data_size = mSize - base_loc; + chunk_size = mSize - base_loc; + std::cerr <<"Chunk Size greater than total file size, adjusting chunk size " << data_size << std::endl; + } + + if (data_size > 0) + { + if(data == NULL) + { + std::cerr << "ftFileProvider: Warning ! Re-allocating data, which probably could not be allocated because of weird chunk size." << std::endl ; + if(NULL == (data = malloc(data_size))) + { + std::cerr << "ftFileProvider: Could not malloc a size of " << data_size << std::endl ; + return false; + } + } + /* + * seek for base_loc + */ + fseeko64(fd, base_loc, SEEK_SET); + + // Data space allocated by caller. + //void *data = malloc(chunk_size); + + /* + * read the data + */ + + if (1 != fread(data, data_size, 1, fd)) + { + #ifdef DEBUG_FT_FILE_PROVIDER + std::cerr << "ftFileProvider::getFileData() Failed to get data. Data_size=" << data_size << ", base_loc=" << base_loc << " !" << std::endl; + #endif + //free(data); No!! It's already freed upwards in ftDataMultiplex::locked_handleServerRequest() + return 0; + } + + /* + * Update status of ftFileStatus to reflect last usage (for GUI display) + * We need to store. + * (a) Id, + * (b) Offset, + * (c) Size, + * (d) timestamp + */ + + // This creates the peer info, and updates it. + // + time_t now = time(NULL) ; + uploading_peers[peer_id].updateStatus(offset,data_size,now) ; + +#ifdef DEBUG_TRANSFERS + std::cerr << "ftFileProvider::getFileData() "; + std::cerr << " at " << RsUtil::AccurateTimeString(); + std::cerr << " hash: " << hash; + std::cerr << " for peerId: " << peer_id; + std::cerr << " offset: " << offset; + std::cerr << " chunkSize: " << chunk_size; + std::cerr << std::endl; +#endif + + } + else + { + std::cerr << "No data to read" << std::endl; + return 0; + } + return 1; +} + +void ftFileProvider::PeerUploadInfo::updateStatus(uint64_t offset,uint32_t data_size,time_t now) +{ + lastTS = now ; + long int diff = (long int)now - (long int)lastTS_t ; // in bytes/s. Average over multiple samples + +#ifdef DEBUG_FT_FILE_PROVIDER + std::cout << "diff = " << diff << std::endl ; +#endif + + if(diff > 3) + { + transfer_rate = total_size / (float)diff ; +#ifdef DEBUG_FT_FILE_PROVIDER + std::cout << "updated TR = " << transfer_rate << ", total_size=" << total_size << std::endl ; +#endif + lastTS_t = now ; + total_size = 0 ; + } + + req_loc = offset; + req_size = data_size; + total_size += req_size ; +} + +void ftFileProvider::setClientMap(const std::string& peer_id,const CompressedChunkMap& cmap) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + // Create by default. + uploading_peers[peer_id].client_chunk_map = cmap ; + uploading_peers[peer_id].client_chunk_map_stamp = time(NULL) ; +} + +void ftFileProvider::getClientMap(const std::string& peer_id,CompressedChunkMap& cmap,bool& map_is_too_old) +{ + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + + PeerUploadInfo& pui(uploading_peers[peer_id]) ; + + time_t now = time(NULL) ; + + if(now - pui.client_chunk_map_stamp > UPLOAD_CHUNK_MAPS_TIME) + { + map_is_too_old = true ; + pui.client_chunk_map_stamp = now ; // to avoid re-asking before the TTL + } + else + map_is_too_old = false ; + + cmap = pui.client_chunk_map; +} + +int ftFileProvider::initializeFileAttrs() +{ +#ifdef DEBUG_FT_FILE_PROVIDER + std::cerr << "ftFileProvider::initializeFileAttrs() Filename: " << file_name << std::endl; +#endif + + RsStackMutex stack(ftcMutex); /********** STACK LOCKED MTX ******/ + if (fd) + return 1; + + /* + * check if the file exists + */ + + { +#ifdef DEBUG_FT_FILE_PROVIDER + std::cerr << "ftFileProvider::initializeFileAttrs() trying (r+b) " << std::endl; +#endif + } + + /* + * attempt to open file + */ + + fd = RsDirUtil::rs_fopen(file_name.c_str(), "r+b"); + if (!fd) + { + std::cerr << "ftFileProvider::initializeFileAttrs() Failed to open (r+b): "; + std::cerr << file_name << std::endl; + + /* try opening read only */ + fd = RsDirUtil::rs_fopen(file_name.c_str(), "rb"); + if (!fd) + { + std::cerr << "ftFileProvider::initializeFileAttrs() Failed to open (rb): "; + std::cerr << file_name << std::endl; + + /* try opening read only */ + return 0; + } + } +#ifdef DEBUG_FT_FILE_PROVIDER + std::cerr << "ftFileProvider:: openned file " << file_name << std::endl ; +#endif + + return 1; +} + +bool ftFileProvider::getCRC32Map(CRC32Map& crc_map) +{ + if(!initializeFileAttrs()) + { + std::cerr << "ftFileProvider::getCRC32Map(...): ERROR: can't initialize file !" << std::endl ; + return false ; + } + + std::cerr << "ftFileProvider::getClientMap(): computing CRC32 map for file " << file_name << " (" << hash << ")" << std::endl ; + return RsDirUtil::crc32File(fd,mSize,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE,crc_map) ; +} + diff --git a/libretroshare/src/ft/ftfileprovider.h b/libretroshare/src/ft/ftfileprovider.h new file mode 100644 index 000000000..cd3bf7393 --- /dev/null +++ b/libretroshare/src/ft/ftfileprovider.h @@ -0,0 +1,114 @@ +/* + * libretroshare/src/ft ftFileProvider.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_FILE_PROVIDER_HEADER +#define FT_FILE_PROVIDER_HEADER + +/* + * ftFileProvider. + * + */ +#include +#include +#include "util/rsthreads.h" +#include "retroshare/rsfiles.h" + +class ftFileProvider +{ + public: + ftFileProvider(const std::string& path, uint64_t size, const std::string& hash); + virtual ~ftFileProvider(); + + virtual bool getFileData(const std::string& peer_id,uint64_t offset, uint32_t &chunk_size, void *data); + virtual bool FileDetails(FileInfo &info); + std::string getHash(); + uint64_t getFileSize(); + bool fileOk(); + + // Provides a client for the map of chunks actually present in the file. If the provider is also + // a file creator, because the file is actually being downloaded, then the map may be partially complete. + // Otherwize, a plain map is returned. + // + virtual void getAvailabilityMap(CompressedChunkMap& cmap) ; + + // Provides a complete per-chunk CRC32 map to client who want to check their data. + // This is derived in ftFileCreator, but returns false, because we can't ensure that unchecked chunks + // will provide a CRC32 that is faithful to the original hash. + // + virtual bool getCRC32Map(CRC32Map& crc_map) ; + + // a ftFileProvider feeds a distant peer. To display what the peers already has, we need to store/read this info. + void getClientMap(const std::string& peer_id,CompressedChunkMap& cmap,bool& map_is_too_old) ; + void setClientMap(const std::string& peer_id,const CompressedChunkMap& cmap) ; + + // Removes inactive peers from the client list. Returns true if all peers have been removed. + // + bool purgeOldPeers(time_t now,uint32_t max_duration) ; + protected: + virtual int initializeFileAttrs(); /* does for both */ + + uint64_t mSize; + std::string hash; + std::string file_name; + FILE *fd; + + /* + * Structure to gather statistics FIXME: lastRequestor - figure out a + * way to get last requestor (peerID) + */ + class PeerUploadInfo + { + public: + PeerUploadInfo() + : req_loc(0),req_size(1), lastTS_t(0), transfer_rate(0), total_size(0), client_chunk_map_stamp(0) {} + + void updateStatus(uint64_t offset,uint32_t data_size,time_t now) ; + + uint64_t req_loc; + uint32_t req_size; + time_t lastTS_t; // used for estimating transfer rate. + time_t lastTS; // last update time (for purging) + + // these two are used for speed estimation + float transfer_rate ; + uint32_t total_size ; + + // Info about what the downloading peer already has + CompressedChunkMap client_chunk_map ; + time_t client_chunk_map_stamp ; + }; + + // Contains statistics (speed, peer name, etc.) of all uploading peers for that file. + // + std::map uploading_peers ; + + /* + * Mutex Required for stuff below + */ + RsMutex ftcMutex; +}; + + +#endif // FT_FILE_PROVIDER_HEADER diff --git a/libretroshare/src/ft/ftfilesearch.cc b/libretroshare/src/ft/ftfilesearch.cc new file mode 100644 index 000000000..966b88f48 --- /dev/null +++ b/libretroshare/src/ft/ftfilesearch.cc @@ -0,0 +1,193 @@ +/* + * libretroshare/src/ft: ftfilesearch.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "ft/ftfilesearch.h" + +const uint32_t MAX_SEARCHS = 24; /* lower 24 bits of hint */ + +//#define DEBUG_SEARCH 1 + +ftFileSearch::ftFileSearch() + :mSearchs(MAX_SEARCHS) +{ + uint32_t i; + for(i = 0; i < MAX_SEARCHS; i++) + { + mSearchs[i] = NULL; + } +} + +bool ftFileSearch::addSearchMode(ftSearch *search, uint32_t hintflags) +{ + hintflags &= 0x00ffffff; + +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::addSearchMode() : " << hintflags; + std::cerr << std::endl; +#endif + + uint32_t i; + for (i = 0; i < MAX_SEARCHS; i++) + { + uint32_t hints = hintflags >> i; + if (hints & 0x0001) + { + /* has the flag */ + mSearchs[i] = search; + +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::addSearchMode() to slot "; + std::cerr << i; + std::cerr << std::endl; +#endif + + return true; + } + } + +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::addSearchMode() Failed"; + std::cerr << std::endl; +#endif + + return false; +} + +bool ftFileSearch::search(const std::string &hash, uint32_t hintflags, FileInfo &info) const +{ + uint32_t hints, i; + +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::search(" << hash ; + std::cerr << ", " << hintflags << ");"; + std::cerr << std::endl; +#endif + + for (i = 0; i < MAX_SEARCHS; i++) + { + hints = hintflags >> i; + if (hints & 0x0001) + { + /* has the flag */ + ftSearch *search = mSearchs[i]; + if (search) + { +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::search() SLOT: "; + std::cerr << i; + std::cerr << std::endl; +#endif + if (search->search(hash, hintflags, info)) + { +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::search() SLOT: "; + std::cerr << i << " success!"; + std::cerr << std::endl; +#endif + return true; + } + else + { +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::search() SLOT: "; + std::cerr << i << " no luck"; + std::cerr << std::endl; +#endif + } + } + } + } + + /* if we haven't found it by now! - check if SPEC_ONLY flag is set */ + if (hintflags & RS_FILE_HINTS_SPEC_ONLY) + { +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::search() SPEC_ONLY: Failed"; + std::cerr << std::endl; +#endif + return false; + } + +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::search() Searching Others (no SPEC ONLY):"; + std::cerr << std::endl; +#endif + + /* if we don't have the SPEC_ONLY flag, + * we check through all the others + */ + for (i = 0; i < MAX_SEARCHS; i++) + { + hints = hintflags >> i; + if (hints & 0x0001) + { + continue; + } + + /* has the flag */ + ftSearch *search = mSearchs[i]; + if (search) + { + +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::search() SLOT: " << i; + std::cerr << std::endl; +#endif + if (search->search(hash, hintflags, info)) + { +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::search() SLOT: "; + std::cerr << i << " success!"; + std::cerr << std::endl; +#endif + return true; + } + else + { +#ifdef DEBUG_SEARCH + std::cerr << "ftFileSearch::search() SLOT: "; + std::cerr << i << " no luck"; + std::cerr << std::endl; +#endif + } + + } + } + /* found nothing */ + return false; +} + + +bool ftSearchDummy::search(std::string hash, uint32_t hintflags, FileInfo &info) const +{ +#ifdef DEBUG_SEARCH + std::cerr << "ftSearchDummy::search(" << hash ; + std::cerr << ", " << hintflags << ");"; + std::cerr << std::endl; +#endif + return false; +} + + diff --git a/libretroshare/src/ft/ftfilesearch.h b/libretroshare/src/ft/ftfilesearch.h new file mode 100644 index 000000000..eaf5db2cd --- /dev/null +++ b/libretroshare/src/ft/ftfilesearch.h @@ -0,0 +1,59 @@ +/* + * libretroshare/src/ft: ftfilesearch.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_FILE_SEARCH_HEADER +#define FT_FILE_SEARCH_HEADER + +/* + * ftFileSearch + * + * This is implements an array of ftSearch Interfaces. + * + */ + +#include + +#include "ft/ftsearch.h" + +class ftFileSearch: public ftSearch +{ + + public: + + ftFileSearch(); + +bool addSearchMode(ftSearch *search, uint32_t hintflags); +virtual bool search(const std::string &hash, uint32_t hintflags, FileInfo &info) const; + + private: + + // should have a mutex to protect vector.... + // but not really necessary as it is const most of the time. + + std::vector mSearchs; +}; + + +#endif diff --git a/libretroshare/src/ft/ftsearch.h b/libretroshare/src/ft/ftsearch.h new file mode 100644 index 000000000..670d78630 --- /dev/null +++ b/libretroshare/src/ft/ftsearch.h @@ -0,0 +1,60 @@ +/* + * libretroshare/src/ft: ftsearch.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_SEARCH_HEADER +#define FT_SEARCH_HEADER + +/* + * ftSearch + * + * This is a generic search interface - used by ft* to find files. + * The derived class will search for Caches/Local/ExtraList/Remote entries. + * + */ + +#include "retroshare/rsfiles.h" // includes retroshare/rstypes.h too! + +class ftSearch +{ + + public: + + ftSearch() { return; } +virtual ~ftSearch() { return; } +virtual bool search(const std::string &hash, uint32_t hintflags, FileInfo &info) const = 0; + +}; + + +class ftSearchDummy: public ftSearch +{ + public: + + ftSearchDummy() { return; } +virtual ~ftSearchDummy() { return; } +virtual bool search(std::string hash, uint32_t hintflags, FileInfo &info) const; +}; + +#endif diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc new file mode 100644 index 000000000..9321df954 --- /dev/null +++ b/libretroshare/src/ft/ftserver.cc @@ -0,0 +1,1306 @@ +/* + * libretroshare/src/ft: ftserver.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include "util/rsdebug.h" +#include "util/rsdir.h" +#include "retroshare/rstypes.h" +const int ftserverzone = 29539; + +#include "ft/ftserver.h" +#include "ft/ftextralist.h" +#include "ft/ftfilesearch.h" +#include "ft/ftcontroller.h" +#include "ft/ftfileprovider.h" +#include "ft/ftdatamultiplex.h" +//#include "ft/ftdwlqueue.h" +#include "turtle/p3turtle.h" + + +// Includes CacheStrapper / FiMonitor / FiStore for us. + +#include "ft/ftdbase.h" + +#include "pqi/pqi.h" +#include "pqi/p3connmgr.h" + +#include "serialiser/rsserviceids.h" + +#include +#include + +/*** + * #define SERVER_DEBUG 1 + * #define DEBUG_TICK 1 + ***/ + + /* Setup */ +ftServer::ftServer(p3ConnectMgr *connMgr) + : mP3iface(NULL), + mConnMgr(connMgr), + mCacheStrapper(NULL), + mFiStore(NULL), mFiMon(NULL), + mFtController(NULL), mFtExtra(NULL), + mFtDataplex(NULL), mFtSearch(NULL) +{ + mCacheStrapper = new ftCacheStrapper(connMgr); +} + +void ftServer::setConfigDirectory(std::string path) +{ + mConfigPath = path; + + /* Must update the sub classes ... if they exist + * TODO. + */ + + std::string basecachedir = mConfigPath + "/cache"; + std::string localcachedir = mConfigPath + "/cache/local"; + std::string remotecachedir = mConfigPath + "/cache/remote"; + + RsDirUtil::checkCreateDirectory(basecachedir) ; + RsDirUtil::checkCreateDirectory(localcachedir) ; + RsDirUtil::checkCreateDirectory(remotecachedir) ; +} + +void ftServer::setP3Interface(P3Interface *pqi) +{ + mP3iface = pqi; +} + + /* Control Interface */ + + /* add Config Items (Extra, Controller) */ +void ftServer::addConfigComponents(p3ConfigMgr *mgr) +{ + /* NOT SURE ABOUT THIS ONE */ +} + +std::string ftServer::OwnId() +{ + std::string ownId; + if (mConnMgr) + ownId = mConnMgr->getOwnId(); + return ownId; +} + + /* Final Setup (once everything is assigned) */ +void ftServer::SetupFtServer(NotifyBase *cb) +{ + + /* setup FiStore/Monitor */ + std::string localcachedir = mConfigPath + "/cache/local"; + std::string remotecachedir = mConfigPath + "/cache/remote"; + std::string ownId = mConnMgr->getOwnId(); + + /* search/extras List */ + mFtExtra = new ftExtraList(); + mFtSearch = new ftFileSearch(); + + /* Transport */ + mFtDataplex = new ftDataMultiplex(ownId, this, mFtSearch); + + /* make Controller */ + mFtController = new ftController(mCacheStrapper, mFtDataplex, mConfigPath); + mFtController -> setFtSearchNExtra(mFtSearch, mFtExtra); + std::string tmppath = "."; + mFtController->setPartialsDirectory(tmppath); + mFtController->setDownloadDirectory(tmppath); + + + /* Make Cache Source/Store */ + mFiStore = new ftFiStore(mCacheStrapper, mFtController, cb,mConnMgr, ownId, remotecachedir); + mFiMon = new ftFiMonitor(mCacheStrapper,cb, localcachedir, ownId,mConfigPath); + + /* now add the set to the cachestrapper */ + CachePair cp(mFiMon, mFiStore, CacheId(RS_SERVICE_TYPE_FILE_INDEX, 0)); + mCacheStrapper -> addCachePair(cp); + + /* complete search setup */ + mFtSearch->addSearchMode(mCacheStrapper, RS_FILE_HINTS_CACHE); + mFtSearch->addSearchMode(mFtExtra, RS_FILE_HINTS_EXTRA); + mFtSearch->addSearchMode(mFiMon, RS_FILE_HINTS_LOCAL); + mFtSearch->addSearchMode(mFiStore, RS_FILE_HINTS_REMOTE); + + mConnMgr->addMonitor(mFtController); + mConnMgr->addMonitor(mCacheStrapper); + + return; +} + +void ftServer::connectToTurtleRouter(p3turtle *fts) +{ + mTurtleRouter = fts ; + + mFtController->setTurtleRouter(fts) ; +} + +void ftServer::StartupThreads() +{ + /* start up order - important for dependencies */ + + /* self contained threads */ + /* startup ExtraList Thread */ + mFtExtra->start(); + + /* startup Monitor Thread */ + /* startup the FileMonitor (after cache load) */ + /* start it up */ + + mFiMon->start(); + + /* Controller thread */ + mFtController->start(); + + /* Dataplex */ + mFtDataplex->start(); + + /* start own thread */ + start(); +} + +void ftServer::StopThreads() +{ + /* stop own thread */ + join(); + + /* stop Dataplex */ + mFtDataplex->join(); + + /* stop Controller thread */ + mFtController->join(); + + /* stop Monitor Thread */ + mFiMon->join(); + + /* self contained threads */ + /* stop ExtraList Thread */ + mFtExtra->join(); + + delete (mFtDataplex); + mFtDataplex = NULL; + + delete (mFtController); + mFtController = NULL; + + delete (mFiMon); + mFiMon = NULL; + + delete (mFtExtra); + mFtExtra = NULL; +} + +CacheStrapper *ftServer::getCacheStrapper() +{ + return mCacheStrapper; +} + +CacheTransfer *ftServer::getCacheTransfer() +{ + return mFtController; +} + +void ftServer::run() +{ + while(isRunning()) + { + mFtDataplex->deleteUnusedServers() ; +#ifdef WIN32 + Sleep(5000); +#else + sleep(5); +#endif + } +} + + + /***************************************************************/ + /********************** RsFiles Interface **********************/ + /***************************************************************/ + + + /***************************************************************/ + /********************** Controller Access **********************/ + /***************************************************************/ + +bool ftServer::checkHash(const std::string& hash,std::string& error_string) +{ + static const uint32_t HASH_LENGTH = 40 ; + + if(hash.length() != HASH_LENGTH) + { + std::ostringstream is ; + is << "Line too long : " << hash.length() << " chars, " << HASH_LENGTH << " expected." ; + is.flush() ; + error_string = is.str() ; + return false ; + } + + for(uint32_t i=0;i 47 && hash[i] < 58) || (hash[i] > 96 && hash[i] < 103))) + { + std::ostringstream is; + is << "unexpected char code=" << (int)hash[i] << " '" << hash[i] << "'" ; + is.flush() ; + error_string = is.str() ; + return false ; + } + + return true ; +} + +bool ftServer::alreadyHaveFile(const std::string& hash, FileInfo &info) +{ + return mFtController->alreadyHaveFile(hash, info); +} + +bool ftServer::FileRequest(const std::string& fname, const std::string& hash, uint64_t size, const std::string& dest, uint32_t flags, const std::list& srcIds) +{ + std::string error_string ; + + if(!checkHash(hash,error_string)) + { + rsicontrol->getNotify().notifyErrorMsg(0,0,"Error handling hash \""+hash+"\". This hash appears to be invalid(Error string=\""+error_string+"\"). This is probably due an bad handling of strings.") ; + return false ; + } + + std::cerr << "Requesting " << fname << std::endl ; + + if(!mFtController->FileRequest(fname, hash, size, dest, flags, srcIds)) + return false ; + + return true ; +} + +bool ftServer::setChunkStrategy(const std::string& hash,FileChunksInfo::ChunkStrategy s) +{ + return mFtController->setChunkStrategy(hash,s); +} +uint32_t ftServer::freeDiskSpaceLimit()const +{ + return mFtController->freeDiskSpaceLimit() ; +} +void ftServer::setFreeDiskSpaceLimit(uint32_t s) +{ + mFtController->setFreeDiskSpaceLimit(s) ; +} +void ftServer::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s) +{ + mFtController->setDefaultChunkStrategy(s) ; +} +FileChunksInfo::ChunkStrategy ftServer::defaultChunkStrategy() +{ + return mFtController->defaultChunkStrategy() ; +} +bool ftServer::FileCancel(const std::string& hash) +{ + // Remove from both queue and ftController, by default. + // + mFtController->FileCancel(hash); + + return true ; +} + +bool ftServer::FileControl(const std::string& hash, uint32_t flags) +{ + return mFtController->FileControl(hash, flags); +} + +bool ftServer::FileClearCompleted() +{ + return mFtController->FileClearCompleted(); +} + +void ftServer::setQueueSize(uint32_t s) +{ + mFtController->setQueueSize(s) ; +} +uint32_t ftServer::getQueueSize() +{ + return mFtController->getQueueSize() ; +} + /* Control of Downloads Priority. */ +bool ftServer::changeQueuePosition(const std::string hash, QueueMove mv) +{ + mFtController->moveInQueue(hash,mv) ; + return true ; +} +bool ftServer::changeDownloadSpeed(const std::string hash, int speed) +{ + mFtController->setPriority(hash, (DwlSpeed)speed); + return true ; +} +bool ftServer::getDownloadSpeed(const std::string hash, int & speed) +{ + DwlSpeed _speed; + int ret = mFtController->getPriority(hash, _speed); + if (ret) + speed = _speed; + + return ret; +} +bool ftServer::clearDownload(const std::string hash) +{ + return true ; +} + +bool ftServer::FileDownloadChunksDetails(const std::string& hash,FileChunksInfo& info) +{ + return mFtController->getFileDownloadChunksDetails(hash,info); +} + + /* Directory Handling */ +void ftServer::setDownloadDirectory(std::string path) +{ + mFtController->setDownloadDirectory(path); +} + +std::string ftServer::getDownloadDirectory() +{ + return mFtController->getDownloadDirectory(); +} + +void ftServer::setPartialsDirectory(std::string path) +{ + mFtController->setPartialsDirectory(path); +} + +std::string ftServer::getPartialsDirectory() +{ + return mFtController->getPartialsDirectory(); +} + + + /***************************************************************/ + /************************* Other Access ************************/ + /***************************************************************/ + +bool ftServer::FileDownloads(std::list &hashs) +{ + return mFtController->FileDownloads(hashs); + /* this only contains downloads.... not completed */ + //return mFtDataplex->FileDownloads(hashs); +} + +bool ftServer::FileUploadChunksDetails(const std::string& hash,const std::string& peer_id,CompressedChunkMap& cmap) +{ + return mFtDataplex->getClientChunkMap(hash,peer_id,cmap); +} + +bool ftServer::FileUploads(std::list &hashs) +{ + return mFtDataplex->FileUploads(hashs); +} + +bool ftServer::FileDetails(const std::string &hash, uint32_t hintflags, FileInfo &info) +{ + if (hintflags & RS_FILE_HINTS_DOWNLOAD) + if(mFtController->FileDetails(hash, info)) + return true ; + + if(hintflags & RS_FILE_HINTS_UPLOAD) + if(mFtDataplex->FileDetails(hash, hintflags, info)) + return true ; + + if(hintflags & ~(RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_DOWNLOAD)) + if(mFtSearch->search(hash, hintflags, info)) + return true ; + + return false; +} + + /***************************************************************/ + /******************* ExtraFileList Access **********************/ + /***************************************************************/ + +bool ftServer::ExtraFileAdd(std::string fname, std::string hash, uint64_t size, + uint32_t period, uint32_t flags) +{ + return mFtExtra->addExtraFile(fname, hash, size, period, flags); +} + +bool ftServer::ExtraFileRemove(std::string hash, uint32_t flags) +{ + return mFtExtra->removeExtraFile(hash, flags); +} + +bool ftServer::ExtraFileHash(std::string localpath, uint32_t period, uint32_t flags) +{ + return mFtExtra->hashExtraFile(localpath, period, flags); +} + +bool ftServer::ExtraFileStatus(std::string localpath, FileInfo &info) +{ + return mFtExtra->hashExtraFileDone(localpath, info); +} + +bool ftServer::ExtraFileMove(std::string fname, std::string hash, uint64_t size, + std::string destpath) +{ + return mFtExtra->moveExtraFile(fname, hash, size, destpath); +} + + + /***************************************************************/ + /******************** Directory Listing ************************/ + /***************************************************************/ + +int ftServer::RequestDirDetails(std::string uid, std::string path, DirDetails &details) +{ +#ifdef SERVER_DEBUG + std::cerr << "ftServer::RequestDirDetails(uid:" << uid; + std::cerr << ", path:" << path << ", ...) -> mFiStore"; + std::cerr << std::endl; + + if (!mFiStore) + { + std::cerr << "mFiStore not SET yet = FAIL"; + std::cerr << std::endl; + } +#endif + return mFiStore->RequestDirDetails(uid, path, details); +} + +int ftServer::RequestDirDetails(void *ref, DirDetails &details, uint32_t flags) +{ +#ifdef SERVER_DEBUG + std::cerr << "ftServer::RequestDirDetails(ref:" << ref; + std::cerr << ", flags:" << flags << ", ...) -> mFiStore"; + std::cerr << std::endl; + + if (!mFiStore) + { + std::cerr << "mFiStore not SET yet = FAIL"; + std::cerr << std::endl; + } + +#endif + if(flags & DIR_FLAGS_LOCAL) + return mFiMon->RequestDirDetails(ref, details, flags); + else + return mFiStore->RequestDirDetails(ref, details, flags); +} +uint32_t ftServer::getType(void *ref, uint32_t flags) +{ +#ifdef SERVER_DEBUG + std::cerr << "ftServer::RequestDirDetails(ref:" << ref; + std::cerr << ", flags:" << flags << ", ...) -> mFiStore"; + std::cerr << std::endl; + + if (!mFiStore) + { + std::cerr << "mFiStore not SET yet = FAIL"; + std::cerr << std::endl; + } + +#endif + if(flags & DIR_FLAGS_LOCAL) + return mFiMon->getType(ref); + else + return mFiStore->getType(ref); +} + /***************************************************************/ + /******************** Search Interface *************************/ + /***************************************************************/ + + +int ftServer::SearchKeywords(std::list keywords, std::list &results,uint32_t flags) +{ +#ifdef SERVER_DEBUG + std::cerr << "ftServer::SearchKeywords()"; + std::cerr << std::endl; + + if (!mFiStore) + { + std::cerr << "mFiStore not SET yet = FAIL"; + std::cerr << std::endl; + } + +#endif + if(flags & DIR_FLAGS_LOCAL) + return mFiMon->SearchKeywords(keywords, results,flags); + else + return mFiStore->SearchKeywords(keywords, results,flags); +} + +int ftServer::SearchBoolExp(Expression * exp, std::list &results,uint32_t flags) +{ + if(flags & DIR_FLAGS_LOCAL) + return mFiMon->SearchBoolExp(exp,results,flags) ; + else + return mFiStore->searchBoolExp(exp, results); +} + + + /***************************************************************/ + /*************** Local Shared Dir Interface ********************/ + /***************************************************************/ + +bool ftServer::ConvertSharedFilePath(std::string path, std::string &fullpath) +{ + return mFiMon->convertSharedFilePath(path, fullpath); +} + +void ftServer::ForceDirectoryCheck() +{ + mFiMon->forceDirectoryCheck(); + return; +} + +bool ftServer::InDirectoryCheck() +{ + return mFiMon->inDirectoryCheck(); +} + +bool ftServer::CopyFile(const std::string& source, const std::string& dest) +{ + return mFtController->copyFile(source, dest); +} + +bool ftServer::getSharedDirectories(std::list &dirs) +{ + mFiMon->getSharedDirectories(dirs); + return true; +} + +bool ftServer::setSharedDirectories(std::list &dirs) +{ + mFiMon->setSharedDirectories(dirs); + return true; +} + +bool ftServer::addSharedDirectory(const SharedDirInfo& dir) +{ + SharedDirInfo _dir = dir; + _dir.filename = RsDirUtil::convertPathToUnix(_dir.filename); + + std::list dirList; + mFiMon->getSharedDirectories(dirList); + + // check that the directory is not already in the list. + for(std::list::const_iterator it(dirList.begin());it!=dirList.end();++it) + if((*it).filename == _dir.filename) + return false ; + + // ok then, add the shared directory. + dirList.push_back(_dir); + + mFiMon->setSharedDirectories(dirList); + return true; +} + +bool ftServer::updateShareFlags(const SharedDirInfo& info) +{ + mFiMon->updateShareFlags(info); + + return true ; +} + +bool ftServer::removeSharedDirectory(std::string dir) +{ + dir = RsDirUtil::convertPathToUnix(dir); + + std::list dirList; + std::list::iterator it; + +#ifdef SERVER_DEBUG + std::cerr << "ftServer::removeSharedDirectory(" << dir << ")"; + std::cerr << std::endl; +#endif + + mFiMon->getSharedDirectories(dirList); + +#ifdef SERVER_DEBUG + for(it = dirList.begin(); it != dirList.end(); it++) + { + std::cerr << "ftServer::removeSharedDirectory()"; + std::cerr << " existing: " << (*it).filename; + std::cerr << std::endl; + } +#endif + + for(it = dirList.begin();it!=dirList.end() && (*it).filename != dir;++it) ; + + if(it == dirList.end()) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::removeSharedDirectory()"; + std::cerr << " Cannot Find Directory... Fail"; + std::cerr << std::endl; +#endif + + return false; + } + + +#ifdef SERVER_DEBUG + std::cerr << "ftServer::removeSharedDirectory()"; + std::cerr << " Updating Directories"; + std::cerr << std::endl; +#endif + + dirList.erase(it); + mFiMon->setSharedDirectories(dirList); + + return true; +} +void ftServer::setWatchPeriod(int minutes) +{ + mFiMon->setWatchPeriod(minutes*60) ; +} +int ftServer::watchPeriod() const +{ + return mFiMon->watchPeriod()/60 ; +} + +void ftServer::setRememberHashFiles(bool b) +{ + mFiMon->setRememberHashCache(b) ; +} +bool ftServer::rememberHashFiles() const +{ + return mFiMon->rememberHashCache() ; +} +void ftServer::setRememberHashFilesDuration(uint32_t days) +{ + mFiMon->setRememberHashCacheDuration(days) ; +} +uint32_t ftServer::rememberHashFilesDuration() const +{ + return mFiMon->rememberHashCacheDuration() ; +} +void ftServer::clearHashCache() +{ + mFiMon->clearHashCache() ; +} + +bool ftServer::getShareDownloadDirectory() +{ + std::list dirList; + mFiMon->getSharedDirectories(dirList); + + std::string dir = mFtController->getDownloadDirectory(); + + // check if the download directory is in the list. + for (std::list::const_iterator it(dirList.begin()); it != dirList.end(); ++it) + if ((*it).filename == dir) + return true; + + return false; +} + +bool ftServer::shareDownloadDirectory(bool share) +{ + if (share) { + /* Share */ + SharedDirInfo inf ; + inf.filename = mFtController->getDownloadDirectory(); + inf.shareflags = RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE ; + + return addSharedDirectory(inf); + } + + /* Unshare */ + std::string dir = mFtController->getDownloadDirectory(); + return removeSharedDirectory(dir); +} + + /***************************************************************/ + /****************** End of RsFiles Interface *******************/ + /***************************************************************/ + + + /***************************************************************/ + /**************** Config Interface *****************************/ + /***************************************************************/ + + /* Key Functions to be overloaded for Full Configuration */ +RsSerialiser *ftServer::setupSerialiser() +{ + return NULL; +} + +bool ftServer::saveList(bool &cleanup, std::list& list) +{ + + return true; +} + +bool ftServer::loadList(std::list& load) +{ + return true; +} + +bool ftServer::loadConfigMap(std::map &configMap) +{ + return true; +} + + + /***************************************************************/ + /********************** Data Flow **********************/ + /***************************************************************/ + + /* Client Send */ +bool ftServer::sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) +{ + if(mTurtleRouter->isTurtlePeer(peerId)) + mTurtleRouter->sendDataRequest(peerId,hash,size,offset,chunksize) ; + else + { + /* create a packet */ + /* push to networking part */ + RsFileRequest *rfi = new RsFileRequest(); + + /* id */ + rfi->PeerId(peerId); + + /* file info */ + rfi->file.filesize = size; + rfi->file.hash = hash; /* ftr->hash; */ + + /* offsets */ + rfi->fileoffset = offset; /* ftr->offset; */ + rfi->chunksize = chunksize; /* ftr->chunk; */ + + mP3iface->SendFileRequest(rfi); + } + + return true; +} + +bool ftServer::sendChunkMapRequest(const std::string& peerId,const std::string& hash,bool is_client) +{ + if(mTurtleRouter->isTurtlePeer(peerId)) + mTurtleRouter->sendChunkMapRequest(peerId,hash,is_client) ; + else + { + /* create a packet */ + /* push to networking part */ + RsFileChunkMapRequest *rfi = new RsFileChunkMapRequest(); + + /* id */ + rfi->PeerId(peerId); + + /* file info */ + rfi->hash = hash; /* ftr->hash; */ + rfi->is_client = is_client ; + + mP3iface->SendFileChunkMapRequest(rfi); + } + + return true ; +} + +bool ftServer::sendChunkMap(const std::string& peerId,const std::string& hash,const CompressedChunkMap& map,bool is_client) +{ + if(mTurtleRouter->isTurtlePeer(peerId)) + mTurtleRouter->sendChunkMap(peerId,hash,map,is_client) ; + else + { + /* create a packet */ + /* push to networking part */ + RsFileChunkMap *rfi = new RsFileChunkMap(); + + /* id */ + rfi->PeerId(peerId); + + /* file info */ + rfi->hash = hash; /* ftr->hash; */ + rfi->is_client = is_client; /* ftr->hash; */ + rfi->compressed_map = map; /* ftr->hash; */ + + mP3iface->SendFileChunkMap(rfi); + } + + return true ; +} +bool ftServer::sendCRC32MapRequest(const std::string& peerId,const std::string& hash) +{ + if(mTurtleRouter->isTurtlePeer(peerId)) + mTurtleRouter->sendCRC32MapRequest(peerId,hash) ; + else + { + /* create a packet */ + /* push to networking part */ + RsFileCRC32MapRequest *rfi = new RsFileCRC32MapRequest(); + + /* id */ + rfi->PeerId(peerId); + + /* file info */ + rfi->hash = hash; /* ftr->hash; */ + + mP3iface->SendFileCRC32MapRequest(rfi); + } + + // We only send chunkmap requests to turtle peers. This will be a problem at display time for + // direct friends, so I'll see later whether I code it or not. + return true ; +} + +bool ftServer::sendCRC32Map(const std::string& peerId,const std::string& hash,const CRC32Map& crcmap) +{ + if(mTurtleRouter->isTurtlePeer(peerId)) + mTurtleRouter->sendCRC32Map(peerId,hash,crcmap) ; + else + { + /* create a packet */ + /* push to networking part */ + RsFileCRC32Map *rfi = new RsFileCRC32Map(); + + /* id */ + rfi->PeerId(peerId); + + /* file info */ + rfi->hash = hash; /* ftr->hash; */ + rfi->crc_map = crcmap; /* ftr->hash; */ + + mP3iface->SendFileCRC32Map(rfi); + } + + // We only send chunkmap requests to turtle peers. This will be a problem at display time for + // direct friends, so I'll see later whether I code it or not. + return true ; +} + +//const uint32_t MAX_FT_CHUNK = 32 * 1024; /* 32K */ +//const uint32_t MAX_FT_CHUNK = 16 * 1024; /* 16K */ +const uint32_t MAX_FT_CHUNK = 8 * 1024; /* 16K */ + + /* Server Send */ +bool ftServer::sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t baseoffset, uint32_t chunksize, void *data) +{ + /* create a packet */ + /* push to networking part */ + uint32_t tosend = chunksize; + uint64_t offset = 0; + uint32_t chunk; + +#ifdef SERVER_DEBUG + std::cerr << "ftServer::sendData() to " << peerId << std::endl; + std::cerr << "hash: " << hash; + std::cerr << " offset: " << baseoffset; + std::cerr << " chunk: " << chunksize; + std::cerr << " data: " << data; + std::cerr << std::endl; +#endif + + while(tosend > 0) + { + /* workout size */ + chunk = MAX_FT_CHUNK; + if (chunk > tosend) + { + chunk = tosend; + } + + /******** New Serialiser Type *******/ + + if(mTurtleRouter->isTurtlePeer(peerId)) + mTurtleRouter->sendFileData(peerId,hash,size,baseoffset+offset,chunk,&(((uint8_t *) data)[offset])) ; + else + { + RsFileData *rfd = new RsFileData(); + + /* set id */ + rfd->PeerId(peerId); + + /* file info */ + rfd->fd.file.filesize = size; + rfd->fd.file.hash = hash; + rfd->fd.file.name = ""; /* blank other data */ + rfd->fd.file.path = ""; + rfd->fd.file.pop = 0; + rfd->fd.file.age = 0; + + rfd->fd.file_offset = baseoffset + offset; + + /* file data */ + rfd->fd.binData.setBinData( &(((uint8_t *) data)[offset]), chunk); + + mP3iface->SendFileData(rfd); + + /* print the data pointer */ +#ifdef SERVER_DEBUG + std::cerr << "ftServer::sendData() Packet: " << std::endl; + std::cerr << " offset: " << rfd->fd.file_offset; + std::cerr << " chunk: " << chunk; + std::cerr << " len: " << rfd->fd.binData.bin_len; + std::cerr << " data: " << rfd->fd.binData.bin_data; + std::cerr << std::endl; +#endif + } + + offset += chunk; + tosend -= chunk; + } + + /* clean up data */ + free(data); + + return true; +} + + +/* NB: The rsCore lock must be activated before calling this. + * This Lock should be moved lower into the system... + * most likely destination is in ftServer. + */ +int ftServer::tick() +{ + rslog(RSL_DEBUG_BASIC, ftserverzone, + "filedexserver::tick()"); + + if (mP3iface == NULL) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::tick() ERROR: mP3iface == NULL"; +#endif + + std::ostringstream out; + rslog(RSL_DEBUG_BASIC, ftserverzone, + "filedexserver::tick() Invalid Interface()"); + + return 1; + } + + int moreToTick = 0; + + if (0 < mP3iface -> tick()) + { + moreToTick = 1; +#ifdef DEBUG_TICK + std::cerr << "filedexserver::tick() moreToTick from mP3iface" << std::endl; +#endif + } + + if (0 < handleInputQueues()) + { + moreToTick = 1; +#ifdef DEBUG_TICK + std::cerr << "filedexserver::tick() moreToTick from InputQueues" << std::endl; +#endif + } + return moreToTick; +} + + +// This function needs to be divided up. +bool ftServer::handleInputQueues() +{ + bool moreToTick = false; + + if (handleCacheData()) + moreToTick = true; + + if (handleFileData()) + moreToTick = true; + + return moreToTick; +} + +bool ftServer::handleCacheData() +{ + // get all the incoming results.. and print to the screen. + RsCacheRequest *cr; + RsCacheItem *ci; + + // Loop through Search Results. + int i = 0; + int i_init = 0; + +#ifdef SERVER_DEBUG + //std::cerr << "ftServer::handleCacheData()" << std::endl; +#endif + while((ci = mP3iface -> GetSearchResult()) != NULL) + { + +#ifdef SERVER_DEBUG + std::cerr << "ftServer::handleCacheData() Recvd SearchResult (CacheResponse!)" << std::endl; + std::ostringstream out; + if (i++ == i_init) + { + out << "Recieved Search Results:" << std::endl; + } + ci -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + + /* these go to the CacheStrapper! */ + CacheData data; + data.pid = ci->PeerId(); + peerConnectState pca; + mConnMgr->getFriendNetStatus(ci->PeerId(), pca); + data.pname = pca.name; + data.cid = CacheId(ci->cacheType, ci->cacheSubId); + data.path = ci->file.path; + data.name = ci->file.name; + data.hash = ci->file.hash; + data.size = ci->file.filesize; + data.recvd = time(NULL) ; + + mCacheStrapper->recvCacheResponse(data, time(NULL)); + + delete ci; + } + + // now requested Searches. + i_init = i; + while((cr = mP3iface -> RequestedSearch()) != NULL) + { +#ifdef SERVER_DEBUG + /* just delete these */ + std::ostringstream out; + out << "Requested Search:" << std::endl; + cr -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + delete cr; + } + + + // Now handle it replacement (pushed cache results) + { + std::list > cacheUpdates; + std::list >::iterator it; + + mCacheStrapper->getCacheUpdates(cacheUpdates); + for(it = cacheUpdates.begin(); it != cacheUpdates.end(); it++) + { + /* construct reply */ + RsCacheItem *ci = new RsCacheItem(); + + /* id from incoming */ + ci -> PeerId(it->first); + + ci -> file.hash = (it->second).hash; + ci -> file.name = (it->second).name; + ci -> file.path = ""; // (it->second).path; + ci -> file.filesize = (it->second).size; + ci -> cacheType = (it->second).cid.type; + ci -> cacheSubId = (it->second).cid.subid; + +#ifdef SERVER_DEBUG + std::ostringstream out2; + out2 << "Outgoing CacheStrapper Update -> RsCacheItem:" << std::endl; + ci -> print(out2); + std::cerr << out2.str() << std::endl; +#endif + + //rslog(RSL_DEBUG_BASIC, ftserverzone, out2.str()); + mP3iface -> SendSearchResult(ci); + + i++; + } + } + return (i > 0); +} + + +bool ftServer::handleFileData() +{ + // now File Input. + RsFileRequest *fr; + RsFileData *fd; + RsFileChunkMapRequest *fcmr; + RsFileChunkMap *fcm; + RsFileCRC32MapRequest *fccrcmr; + RsFileCRC32Map *fccrcm; + + int i_init = 0; + int i = 0; + + i_init = i; + while((fr = mP3iface -> GetFileRequest()) != NULL ) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::handleFileData() Recvd ftFiler Request" << std::endl; + std::ostringstream out; + if (i == i_init) + { + out << "Incoming(Net) File Item:" << std::endl; + } + fr -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + + i++; /* count */ + mFtDataplex->recvDataRequest(fr->PeerId(), + fr->file.hash, fr->file.filesize, + fr->fileoffset, fr->chunksize); + +FileInfo(ffr); + delete fr; + } + + // now File Data. + i_init = i; + while((fd = mP3iface -> GetFileData()) != NULL ) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::handleFileData() Recvd ftFiler Data" << std::endl; + std::cerr << "hash: " << fd->fd.file.hash; + std::cerr << " length: " << fd->fd.binData.bin_len; + std::cerr << " data: " << fd->fd.binData.bin_data; + std::cerr << std::endl; + + std::ostringstream out; + if (i == i_init) + { + out << "Incoming(Net) File Data:" << std::endl; + } + fd -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + i++; /* count */ + + /* incoming data */ + mFtDataplex->recvData(fd->PeerId(), + fd->fd.file.hash, fd->fd.file.filesize, + fd->fd.file_offset, + fd->fd.binData.bin_len, + fd->fd.binData.bin_data); + + /* we've stolen the data part -> so blank before delete + */ + fd->fd.binData.TlvShallowClear(); + delete fd; + } + // now file chunkmap requests + i_init = i; + while((fcmr = mP3iface -> GetFileChunkMapRequest()) != NULL ) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::handleFileData() Recvd ChunkMap request" << std::endl; + std::ostringstream out; + if (i == i_init) + { + out << "Incoming(Net) File Data:" << std::endl; + } + fcmr -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + i++; /* count */ + + /* incoming data */ + mFtDataplex->recvChunkMapRequest(fcmr->PeerId(), fcmr->hash,fcmr->is_client) ; + + delete fcmr; + } + // now file chunkmaps + i_init = i; + while((fcm = mP3iface -> GetFileChunkMap()) != NULL ) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::handleFileData() Recvd ChunkMap request" << std::endl; + std::ostringstream out; + if (i == i_init) + { + out << "Incoming(Net) File Data:" << std::endl; + } + fcm -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + i++; /* count */ + + /* incoming data */ + mFtDataplex->recvChunkMap(fcm->PeerId(), fcm->hash,fcm->compressed_map,fcm->is_client) ; + + delete fcm; + } + // now file chunkmap requests + i_init = i; + while((fccrcmr = mP3iface -> GetFileCRC32MapRequest()) != NULL ) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::handleFileData() Recvd ChunkMap request" << std::endl; + std::ostringstream out; + if (i == i_init) + { + out << "Incoming(Net) File Data:" << std::endl; + } + fccrcmr -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + i++; /* count */ + + /* incoming data */ + mFtDataplex->recvCRC32MapRequest(fccrcmr->PeerId(), fccrcmr->hash) ; + + delete fccrcmr; + } + // now file chunkmaps + i_init = i; + while((fccrcm = mP3iface -> GetFileCRC32Map()) != NULL ) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::handleFileData() Recvd ChunkMap request" << std::endl; + std::ostringstream out; + if (i == i_init) + { + out << "Incoming(Net) File Data:" << std::endl; + } + fccrcm -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + i++; /* count */ + + /* incoming data */ + mFtDataplex->recvCRC32Map(fccrcm->PeerId(), fccrcm->hash,fccrcm->crc_map); + + delete fccrcm; + } + if (i > 0) + { + return 1; + } + return 0; +} + +/********************************** + ********************************** + ********************************** + *********************************/ + + /***************************** CONFIG ****************************/ + +bool ftServer::addConfiguration(p3ConfigMgr *cfgmgr) +{ + /* add all the subbits to config mgr */ + cfgmgr->addConfiguration("ft_shared.cfg", mFiMon); + cfgmgr->addConfiguration("ft_extra.cfg", mFtExtra); + cfgmgr->addConfiguration("ft_transfers.cfg", mFtController); + + return true; +} + +bool ftServer::ResumeTransfers() +{ + mFtController->activate(); + + return true; +} + diff --git a/libretroshare/src/ft/ftserver.h b/libretroshare/src/ft/ftserver.h new file mode 100644 index 000000000..12ee36caf --- /dev/null +++ b/libretroshare/src/ft/ftserver.h @@ -0,0 +1,294 @@ +/* + * libretroshare/src/ft: ftserver.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_SERVER_HEADER +#define FT_SERVER_HEADER + +/* + * ftServer. + * + * Top level File Transfer interface. + * (replaces old filedexserver) + * + * sets up the whole File Transfer class structure. + * sets up the File Indexing side of cache system too. + * + * provides rsFiles interface for external control. + * + */ + +#include +#include +#include + +#include "ft/ftdata.h" +#include "retroshare/rsfiles.h" +//#include "dbase/cachestrapper.h" + +#include "pqi/pqi.h" +#include "pqi/p3cfgmgr.h" + +class p3ConnectMgr; + +class CacheStrapper; +class CacheTransfer; + +class NotifyBase; /* needed by FiStore */ +class ftCacheStrapper; +class ftFiStore; +class ftFiMonitor; + +class ftController; +class ftExtraList; +class ftFileSearch; + +class ftDataMultiplex; +class p3turtle; + +class ftDwlQueue; + +class ftServer: public RsFiles, public ftDataSend, public RsThread +{ + + public: + + /***************************************************************/ + /******************** Setup ************************************/ + /***************************************************************/ + + ftServer(p3ConnectMgr *connMgr); + + /* Assign important variables */ +void setConfigDirectory(std::string path); + +void setP3Interface(P3Interface *pqi); + + /* add Config Items (Extra, Controller) */ +void addConfigComponents(p3ConfigMgr *mgr); + +virtual CacheStrapper *getCacheStrapper(); +virtual CacheTransfer *getCacheTransfer(); + +std::string OwnId(); + + /* Final Setup (once everything is assigned) */ +//void SetupFtServer(); +void SetupFtServer(NotifyBase *cb); +void connectToTurtleRouter(p3turtle *p) ; + +void StartupThreads(); +void StopThreads(); + + /* own thread */ +virtual void run(); + +// Checks that the given hash is well formed. Used to chase +// string bugs. +static bool checkHash(const std::string& hash,std::string& error_string) ; + + /***************************************************************/ + /*************** Control Interface *****************************/ + /************** (Implements RsFiles) ***************************/ + /***************************************************************/ + +// member access + +ftDataMultiplex *getMultiplexer() const { return mFtDataplex ; } +ftController *getController() const { return mFtController ; } + +/*** + * Control of Downloads + ***/ +virtual bool alreadyHaveFile(const std::string& hash, FileInfo &info); +virtual bool FileRequest(const std::string& fname, const std::string& hash, uint64_t size, const std::string& dest, uint32_t flags, const std::list& srcIds); +virtual bool FileCancel(const std::string& hash); +virtual bool FileControl(const std::string& hash, uint32_t flags); +virtual bool FileClearCompleted(); +virtual bool setChunkStrategy(const std::string& hash,FileChunksInfo::ChunkStrategy s) ; +virtual void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy) ; +virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() ; +virtual uint32_t freeDiskSpaceLimit() const ; +virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) ; + + +/*** + * Control of Downloads Priority. + ***/ +virtual uint32_t getQueueSize() ; +virtual void setQueueSize(uint32_t s) ; +virtual bool changeQueuePosition(const std::string hash, QueueMove queue_mv); +virtual bool changeDownloadSpeed(const std::string hash, int speed); +virtual bool getDownloadSpeed(const std::string hash, int & speed); +virtual bool clearDownload(const std::string hash); +//virtual void getDwlDetails(std::list & details); + +/*** + * Download/Upload Details + ***/ +virtual bool FileDownloads(std::list &hashs); +virtual bool FileUploads(std::list &hashs); +virtual bool FileDetails(const std::string &hash, uint32_t hintflags, FileInfo &info); +virtual bool FileDownloadChunksDetails(const std::string& hash,FileChunksInfo& info) ; +virtual bool FileUploadChunksDetails(const std::string& hash,const std::string& peer_id,CompressedChunkMap& map) ; + + +/*** + * Extra List Access + ***/ +virtual bool ExtraFileAdd(std::string fname, std::string hash, uint64_t size, + uint32_t period, uint32_t flags); +virtual bool ExtraFileRemove(std::string hash, uint32_t flags); +virtual bool ExtraFileHash(std::string localpath, + uint32_t period, uint32_t flags); +virtual bool ExtraFileStatus(std::string localpath, FileInfo &info); +virtual bool ExtraFileMove(std::string fname, std::string hash, uint64_t size, + std::string destpath); + + +/*** + * Directory Listing / Search Interface + ***/ +virtual int RequestDirDetails(std::string uid, std::string path, DirDetails &details); +virtual int RequestDirDetails(void *ref, DirDetails &details, uint32_t flags); +virtual uint32_t getType(void *ref,uint32_t flags) ; + +virtual int SearchKeywords(std::list keywords, std::list &results,uint32_t flags); +virtual int SearchBoolExp(Expression * exp, std::list &results,uint32_t flags); + +/*** + * Utility Functions + ***/ +virtual bool ConvertSharedFilePath(std::string path, std::string &fullpath); +virtual void ForceDirectoryCheck(); +virtual bool InDirectoryCheck(); +virtual bool CopyFile(const std::string& source, const std::string& dest); + +/*** + * Directory Handling + ***/ +virtual void setDownloadDirectory(std::string path); +virtual void setPartialsDirectory(std::string path); +virtual std::string getDownloadDirectory(); +virtual std::string getPartialsDirectory(); + +virtual bool getSharedDirectories(std::list &dirs); +virtual bool setSharedDirectories(std::list &dirs); +virtual bool addSharedDirectory(const SharedDirInfo& dir); +virtual bool updateShareFlags(const SharedDirInfo& dir); // updates the flags. The directory should already exist ! +virtual bool removeSharedDirectory(std::string dir); + +virtual bool getShareDownloadDirectory(); +virtual bool shareDownloadDirectory(bool share); + + virtual void setRememberHashFilesDuration(uint32_t days) ; + virtual uint32_t rememberHashFilesDuration() const ; + virtual bool rememberHashFiles() const ; + virtual void setRememberHashFiles(bool) ; + virtual void clearHashCache() ; + virtual void setWatchPeriod(int minutes) ; + virtual int watchPeriod() const ; + + /***************************************************************/ + /*************** Control Interface *****************************/ + /***************************************************************/ + + /***************************************************************/ + /*************** Data Transfer Interface ***********************/ + /***************************************************************/ +public: +virtual bool sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); +virtual bool sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize); +virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) ; +virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap,bool is_client) ; +virtual bool sendCRC32MapRequest(const std::string&, const std::string&) ; +virtual bool sendCRC32Map(const std::string&, const std::string&, const CRC32Map&) ; + + + + /*************** Internal Transfer Fns *************************/ +virtual int tick(); + + /* Configuration */ +bool addConfiguration(p3ConfigMgr *cfgmgr); +bool ResumeTransfers(); + +private: +bool handleInputQueues(); +bool handleCacheData(); +bool handleFileData(); + + /******************* p3 Config Overload ************************/ + protected: + /* Key Functions to be overloaded for Full Configuration */ +virtual RsSerialiser *setupSerialiser(); +virtual bool saveList(bool &cleanup, std::list&); +virtual bool loadList(std::list& load); + + private: +bool loadConfigMap(std::map &configMap); + /******************* p3 Config Overload ************************/ + +/*************************** p3 Config Overload ********************/ + + private: + + /**** INTERNAL FUNCTIONS ***/ +//virtual int reScanDirs(); +//virtual int check_dBUpdate(); + + private: + + /* no need for Mutex protection - + * as each component is protected independently. + */ + + P3Interface *mP3iface; /* XXX THIS NEEDS PROTECTION */ + p3ConnectMgr *mConnMgr; + + ftCacheStrapper *mCacheStrapper; + ftFiStore *mFiStore; + ftFiMonitor *mFiMon; + + ftController *mFtController; + ftExtraList *mFtExtra; + + ftDataMultiplex *mFtDataplex; + p3turtle *mTurtleRouter ; + + + ftFileSearch *mFtSearch; + + ftDwlQueue *mFtDwlQueue; + + RsMutex srvMutex; + std::string mConfigPath; + std::string mDownloadPath; + std::string mPartialsPath; + +}; + + + +#endif diff --git a/libretroshare/src/ft/fttransfermodule.cc b/libretroshare/src/ft/fttransfermodule.cc new file mode 100644 index 000000000..651c87b1d --- /dev/null +++ b/libretroshare/src/ft/fttransfermodule.cc @@ -0,0 +1,1036 @@ +/* + * libretroshare/src/ft: fttransfermodule.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * #define FT_DEBUG 1 + *****/ + +#include "retroshare/rsturtle.h" +#include "fttransfermodule.h" + +/************************************************************************* + * Notes on file transfer strategy. + * Care must be taken not to overload pipe. best way is to time requests. + * and according adjust data rate. + * + * each peer gets a 'max_rate' which is decided on the type of transfer. + * - trickle ... + * - stream ... + * - max ... + * + * Each peer is independently managed. + * + * via the functions: + * + */ + +const double FT_TM_MAX_PEER_RATE = 10 * 1024 * 1024; /* 10MB/s */ +const uint32_t FT_TM_MAX_RESETS = 5; + +const uint32_t FT_TM_MINIMUM_CHUNK = 1024; /* ie 1Kb / sec */ +const uint32_t FT_TM_RESTART_DOWNLOAD = 20; /* 20 seconds */ +const uint32_t FT_TM_DOWNLOAD_TIMEOUT = 10; /* 10 seconds */ +const uint32_t FT_TM_CRC_MAP_MAX_WAIT_PER_GIG = 20; /* 20 seconds per gigabyte */ + +const double FT_TM_MAX_INCREASE = 1.00; +const double FT_TM_MIN_INCREASE = -0.10; +const int32_t FT_TM_FAST_RTT = 1.0; +const int32_t FT_TM_STD_RTT = 5.0; +const int32_t FT_TM_SLOW_RTT = 9.0; + +const uint32_t FT_TM_CRC_MAP_STATE_NOCHECK = 0 ; +const uint32_t FT_TM_CRC_MAP_STATE_DONT_HAVE = 1 ; +const uint32_t FT_TM_CRC_MAP_STATE_HAVE = 2 ; + +#define FT_TM_FLAG_DOWNLOADING 0 +#define FT_TM_FLAG_CANCELED 1 +#define FT_TM_FLAG_COMPLETE 2 +#define FT_TM_FLAG_CHECKING 3 +#define FT_TM_FLAG_CHUNK_CRC 4 + +ftTransferModule::ftTransferModule(ftFileCreator *fc, ftDataMultiplex *dm, ftController *c) + :mFileCreator(fc), mMultiplexor(dm), mFtController(c), mFlag(FT_TM_FLAG_DOWNLOADING) +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + + mHash = mFileCreator->getHash(); + mSize = mFileCreator->getFileSize(); + mFileStatus.hash = mHash; + + _hash_thread = NULL ; + + // Dummy for Testing (should be handled independantly for + // each peer. + //mChunkSize = 10000; + desiredRate = FT_TM_MAX_PEER_RATE; /* 1MB/s ??? */ + actualRate = 0; + _crcmap_state = FT_TM_CRC_MAP_STATE_NOCHECK ; + _crcmap_last_asked_time = 0 ; +} + +ftTransferModule::~ftTransferModule() +{} + + +bool ftTransferModule::setFileSources(const std::list& peerIds) +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + + mFileSources.clear(); + +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::setFileSources()"; + std::cerr << " List of peers: " ; +#endif + + std::list::const_iterator it; + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + +#ifdef FT_DEBUG + std::cerr << " \t" << *it; +#endif + + peerInfo pInfo(*it); + mFileSources.insert(std::pair(*it,pInfo)); + } + +#ifdef FT_DEBUG + std::cerr << std::endl; +#endif + + return true; +} + +bool ftTransferModule::getFileSources(std::list &peerIds) +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + std::map::iterator it; + for(it = mFileSources.begin(); it != mFileSources.end(); it++) + { + peerIds.push_back(it->first); + } + return true; +} + +bool ftTransferModule::addFileSource(const std::string& peerId) +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + std::map::iterator mit; + mit = mFileSources.find(peerId); + + if (mit == mFileSources.end()) + { + /* add in new source */ + peerInfo pInfo(peerId); + mFileSources.insert(std::pair(peerId,pInfo)); + mit = mFileSources.find(peerId); + +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::addFileSource()"; + std::cerr << " adding peer: " << peerId << " to sourceList"; + std::cerr << std::endl; +#endif + + } + else + { +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::addFileSource()"; + std::cerr << " peer: " << peerId << " already there"; + std::cerr << std::endl; +#endif + } + return true; +} + +bool ftTransferModule::removeFileSource(const std::string& peerId) +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + std::map::iterator mit; + mit = mFileSources.find(peerId); + + if (mit != mFileSources.end()) + { + /* add in new source */ + mFileSources.erase(mit) ; +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::addFileSource(): removing peer: " << peerId << " from sourceList" << std::cerr << std::endl; +#endif + } +#ifdef FT_DEBUG + else + std::cerr << "ftTransferModule::addFileSource(): Should remove peer: " << peerId << ", but it's not in the source list. " << std::cerr << std::endl; +#endif + + return true; +} + +bool ftTransferModule::setPeerState(const std::string& peerId,uint32_t state,uint32_t maxRate) +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::setPeerState()"; + std::cerr << " peerId: " << peerId; + std::cerr << " state: " << state; + std::cerr << " maxRate: " << maxRate << std::endl; +#endif + + std::map::iterator mit; + mit = mFileSources.find(peerId); + + if (mit == mFileSources.end()) + { + /* add in new source */ + +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::setPeerState()"; + std::cerr << " adding new peer to sourceList"; + std::cerr << std::endl; +#endif + return false; + } + + (mit->second).state=state; + (mit->second).desiredRate=maxRate; + // Start it off at zero.... + // (mit->second).actualRate=maxRate; /* should give big kick in right direction */ + + std::list::iterator it; + it = std::find(mOnlinePeers.begin(), mOnlinePeers.end(), peerId); + + if (state!=PQIPEER_NOT_ONLINE) + { + //change to online, add peerId in online peer list + if (it==mOnlinePeers.end()) mOnlinePeers.push_back(peerId); + } + else + { + //change to offline, remove peerId in online peer list + if (it!=mOnlinePeers.end()) mOnlinePeers.erase(it); + } + + return true; +} + + +bool ftTransferModule::getPeerState(const std::string& peerId,uint32_t &state,uint32_t &tfRate) +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + std::map::iterator mit; + mit = mFileSources.find(peerId); + + if (mit == mFileSources.end()) return false; + + state = (mit->second).state; + tfRate = (uint32_t) (mit->second).actualRate; + +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::getPeerState()"; + std::cerr << " peerId: " << peerId; + std::cerr << " state: " << state; + std::cerr << " tfRate: " << tfRate << std::endl; +#endif + return true; +} + +uint32_t ftTransferModule::getDataRate(const std::string& peerId) +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + std::map::iterator mit; + mit = mFileSources.find(peerId); + if (mit == mFileSources.end()) + { +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::getDataRate()"; + std::cerr << " peerId: " << peerId; + std::cerr << " peer not exist in file sources " << std::endl; +#endif + return 0; + } + else + return (uint32_t) (mit->second).actualRate; +} + + + //interface to client module +bool ftTransferModule::recvFileData(const std::string& peerId, uint64_t offset, uint32_t chunk_size, void *data) +{ +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::recvFileData()"; + std::cerr << " peerId: " << peerId; + std::cerr << " offset: " << offset; + std::cerr << " chunksize: " << chunk_size; + std::cerr << " data: " << data; + std::cerr << std::endl; +#endif + + bool ok = false; + + { + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + + std::map::iterator mit; + mit = mFileSources.find(peerId); + + if (mit == mFileSources.end()) + { +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::recvFileData()"; + std::cerr << " peer not found in sources"; + std::cerr << std::endl; +#endif + return false; + } + ok = locked_recvPeerData(mit->second, offset, chunk_size, data); + + } /***** STACK MUTEX END ****/ + + if (ok) + storeData(offset, chunk_size, data); + + free(data) ; + return ok; +} + +void ftTransferModule::requestData(const std::string& peerId, uint64_t offset, uint32_t chunk_size) +{ +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::requestData()"; + std::cerr << " peerId: " << peerId; + std::cerr << " hash: " << mHash; + std::cerr << " size: " << mSize; + std::cerr << " offset: " << offset; + std::cerr << " chunk_size: " << chunk_size; + std::cerr << std::endl; +#endif + + mMultiplexor->sendDataRequest(peerId, mHash, mSize, offset,chunk_size); +} + +bool ftTransferModule::getChunk(const std::string& peer_id,uint32_t size_hint,uint64_t &offset, uint32_t &chunk_size) +{ +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::getChunk()"; + std::cerr << " hash: " << mHash; + std::cerr << " size: " << mSize; + std::cerr << " offset: " << offset; + std::cerr << " size_hint: " << size_hint; + std::cerr << " chunk_size: " << chunk_size; + std::cerr << std::endl; +#endif + + bool source_peer_map_needed ; + + bool val = mFileCreator->getMissingChunk(peer_id,size_hint,offset, chunk_size,source_peer_map_needed); + + if(source_peer_map_needed) + mMultiplexor->sendChunkMapRequest(peer_id, mHash,false) ; + +#ifdef FT_DEBUG + if (val) + { + std::cerr << "ftTransferModule::getChunk()"; + std::cerr << " Answer: Chunk Available"; + std::cerr << " hash: " << mHash; + std::cerr << " size: " << mSize; + std::cerr << " offset: " << offset; + std::cerr << " chunk_size: " << chunk_size; + std::cerr << " peer map needed = " << source_peer_map_needed << std::endl ; + std::cerr << std::endl; + } + else + { + std::cerr << "ftTransferModule::getChunk()"; + std::cerr << " Answer: No Chunk Available"; + std::cerr << " peer map needed = " << source_peer_map_needed << std::endl ; + std::cerr << std::endl; + } +#endif + + return val; +} + +bool ftTransferModule::storeData(uint64_t offset, uint32_t chunk_size,void *data) +{ +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::storeData()"; + std::cerr << " hash: " << mHash; + std::cerr << " size: " << mSize; + std::cerr << " offset: " << offset; + std::cerr << " chunk_size: " << chunk_size; + std::cerr << std::endl; +#endif + + return mFileCreator -> addFileData(offset, chunk_size, data); +} + +bool ftTransferModule::queryInactive() +{ + /* NB: Not sure about this lock... might cause deadlock. + */ + { + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::queryInactive()" << std::endl; +#endif + + if (mFileStatus.stat == ftFileStatus::PQIFILE_INIT) + mFileStatus.stat = ftFileStatus::PQIFILE_DOWNLOADING; + + if (mFileStatus.stat != ftFileStatus::PQIFILE_DOWNLOADING) + { + if (mFileStatus.stat == ftFileStatus::PQIFILE_FAIL_CANCEL) + mFlag = FT_TM_FLAG_COMPLETE; //file canceled by user + return false; + } + + if (mFileStatus.stat == ftFileStatus::PQIFILE_CHECKING) + return false ; + + std::map::iterator mit; + for(mit = mFileSources.begin(); mit != mFileSources.end(); mit++) + { + locked_tickPeerTransfer(mit->second); + } + if(mFileCreator->finished()) // transfer is complete + { + mFileStatus.stat = ftFileStatus::PQIFILE_CHECKING ; + mFlag = FT_TM_FLAG_CHECKING; + } + } + + return true; +} + +bool ftTransferModule::cancelTransfer() +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + mFileStatus.stat=ftFileStatus::PQIFILE_FAIL_CANCEL; + + return 1; +} + +bool ftTransferModule::cancelFileTransferUpward() +{ + if (mFtController) + mFtController->FileCancel(mHash); + return true; +} +bool ftTransferModule::completeFileTransfer() +{ +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::completeFileTransfer()"; + std::cerr << std::endl; +#endif + if (mFtController) + mFtController->FlagFileComplete(mHash); + return true; +} + +int ftTransferModule::tick() +{ + queryInactive(); +#ifdef FT_DEBUG + { + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + + std::cerr << "ftTransferModule::tick()"; + std::cerr << " mFlag: " << mFlag; + std::cerr << " mHash: " << mHash; + std::cerr << " mSize: " << mSize; + std::cerr << std::endl; + + std::cerr << "Peers: "; + std::map::iterator it; + for(it = mFileSources.begin(); it != mFileSources.end(); it++) + { + std::cerr << " " << it->first; + } + std::cerr << std::endl; + + + } +#endif + + uint32_t flags = 0; + { + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + flags = mFlag; + } + + switch (flags) + { + case FT_TM_FLAG_DOWNLOADING: //file transfer not complete + adjustSpeed(); + break; + case FT_TM_FLAG_COMPLETE: //file transfer complete + completeFileTransfer(); + break; + case FT_TM_FLAG_CANCELED: //file transfer canceled + break; + case FT_TM_FLAG_CHECKING: // Check if file hash matches the hashed data + checkFile() ; + break ; + case FT_TM_FLAG_CHUNK_CRC: // File is waiting for CRC32 map. Check if received, and re-set matched chunks + checkCRC() ; + break ; + default: + break; + } + + return 0; +} + +bool ftTransferModule::isCheckingHash() +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ +#ifdef FT_DEBUG + std::cerr << "isCheckingHash(): mFlag=" << mFlag << std::endl; +#endif + return mFlag == FT_TM_FLAG_CHECKING || mFlag == FT_TM_FLAG_CHUNK_CRC; +} + +class HashThread: public RsThread +{ + public: + HashThread(ftFileCreator *m) + : _m(m),_finished(false),_hash("") {} + + virtual void run() + { +#ifdef FT_DEBUG + std::cerr << "hash thread is running for file " << std::endl; +#endif + std::string tmphash ; + _m->hashReceivedData(tmphash) ; + + RsStackMutex stack(_hashThreadMtx) ; + _hash = tmphash ; + _finished = true ; + } + std::string hash() + { + RsStackMutex stack(_hashThreadMtx) ; + return _hash ; + } + bool finished() + { + RsStackMutex stack(_hashThreadMtx) ; + return _finished ; + } + private: + RsMutex _hashThreadMtx ; + ftFileCreator *_m ; + bool _finished ; + std::string _hash ; +}; + +bool ftTransferModule::checkFile() +{ + { + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkFile(): checking File " << mHash << std::endl ; +#endif + + // if we don't have a hashing thread, create one. + + if(_hash_thread == NULL) + { + // Note: using new is really important to avoid copy and write errors in the thread. + // + _hash_thread = new HashThread(mFileCreator) ; + _hash_thread->start() ; +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkFile(): launched hashing thread for file " << mHash << std::endl ; +#endif + return false ; + } + + if(!_hash_thread->finished()) + { +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkFile(): file " << mHash << " is being hashed.?" << std::endl ; +#endif + return false ; + } + + std::string check_hash( _hash_thread->hash() ) ; + + _hash_thread->join(); // allow releasing of resources when finished. + + delete _hash_thread ; + _hash_thread = NULL ; + + if(check_hash == mHash) + { + mFlag = FT_TM_FLAG_COMPLETE ; // Transfer is complete. +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkFile(): hash finished. File verification complete ! Setting mFlag to 1" << std::endl ; +#endif + return true ; + } + } + forceCheck() ; + return false ; +} + +void ftTransferModule::forceCheck() +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::forceCheck(): setting flags to force check." << std::endl ; +#endif + mFlag = FT_TM_FLAG_CHUNK_CRC ; // Ask for CRC map. + + // setup flags for CRC state machine to work properly + _crcmap_state = FT_TM_CRC_MAP_STATE_DONT_HAVE ; + _crcmap_last_asked_time = 0 ; +} + +bool ftTransferModule::checkCRC() +{ + // We have a finite state machine here. + // + // The states are, for each chunk, and what should be done: + // DONT_HAVE + // -> ask for the chunk CRC + // ASKED + // -> do nothing + // RECEIVED + // -> check the chunk + // CHECKED + // -> do nothing + // + // CRCs are asked by group of CRC_REQUEST_MAX_SIZE chunks at a time. The response may contain a different + // number of CRCs, depending on the availability. + // + // Server side: + // - Only complete files can compute CRCs, as the CRCs of downloaded chunks in an unchecked file are un-verified. + // - CRCs of files are cached, so that they don't get computed twice. + // +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkCRC(): looking for CRC32 map." << std::endl ; +#endif + + // Loop over chunks. Collect the ones to ask for, and hash the ones received. + // If we have + // + time_t now = time(NULL) ; + + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + + switch(_crcmap_state) + { + case FT_TM_CRC_MAP_STATE_NOCHECK: +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkCRC(): state is NOCHECK. Doing nothing." << std::endl ; +#endif + break ; + + case FT_TM_CRC_MAP_STATE_DONT_HAVE: + { + // Check wether we have a CRC map or not. + // + std::cerr << "FT_TM_CRC_MAP_STATE_ASKED: last time is " << _crcmap_last_asked_time << std::endl ; + std::cerr << "FT_TM_CRC_MAP_STATE_ASKED: now is " << now << std::endl ; + + uint64_t threshold = (uint64_t)(FT_TM_CRC_MAP_MAX_WAIT_PER_GIG * (1+mSize/float(1024ull*1024ull*1024ull))) ; + + std::cerr << "Threshold is " << threshold << std::endl; + std::cerr << "Limit is " << (uint64_t)_crcmap_last_asked_time + threshold << std::endl ; + + if( (uint64_t)_crcmap_last_asked_time + threshold > (uint64_t)now) + { +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkCRC(): state is NOCHECK. Doing nothing." << std::endl ; +#endif + break ; + } + // Ask the ones we should ask for. We use a very coarse strategy now: we + // send the request to a random source. We'll make this more sensible + // later. + +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkCRC(): state is DONT_HAVE or last request is too old. Selecting a source for asking a CRC map." << std::endl ; +#endif + if(mFileSources.empty()) + { + std::cerr << "ftTransferModule::checkCRC(): No sources available for checking file " << mHash << ": waiting 3 additional sec." <::const_iterator mit ; + for(mit = mFileSources.begin();mit != mFileSources.end() && pfirst << std::endl ; +#endif + _crcmap_last_asked_time = now ; + mMultiplexor->sendCRC32MapRequest(mit->first,mHash); + } + break ; + + case FT_TM_CRC_MAP_STATE_HAVE: + { +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkCRC(): got a CRC32 map. Matching chunks..." << std::endl ; +#endif + // The CRCmap is complete. Let's cross check it with existing chunks in ftFileCreator ! + // + uint32_t bad_chunks ; + uint32_t incomplete_chunks ; + + if(!mFileCreator->crossCheckChunkMap(_crcmap,bad_chunks,incomplete_chunks)) + { + std::cerr << "ftTransferModule::checkCRC(): could not check CRC chunks!" << std::endl ; + return false; + } + + // go back to download stage, if not all chunks are correct. + // + if(bad_chunks > 0) + { + mFlag = FT_TM_FLAG_DOWNLOADING ; + mFileStatus.stat = ftFileStatus::PQIFILE_DOWNLOADING; + std::cerr << "ftTransferModule::checkCRC(): Done. File has errors: " << bad_chunks << " bad chunks found. Restarting download for these chunks only." << std::endl ; + } + else if(incomplete_chunks > 0) + { + mFlag = FT_TM_FLAG_DOWNLOADING ; + mFileStatus.stat = ftFileStatus::PQIFILE_DOWNLOADING; +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkCRC(): Done. all chunks ok. Continuing download for remaining chunks." << std::endl ; +#endif + } + else + { + mFlag = FT_TM_FLAG_COMPLETE ; +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::checkCRC(): Done. CRC check is ok, file is complete." << std::endl ; +#endif + } + + _crcmap_state = FT_TM_CRC_MAP_STATE_NOCHECK ; + } + } + + return true ; +} + +void ftTransferModule::addCRC32Map(const CRC32Map& crc_map) +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + + // Note: for now, we only send complete CRC32 maps, so the crc_map is always complete. When we + // send partial CRC maps, we will have to check them for completness. + // + _crcmap_state = FT_TM_CRC_MAP_STATE_HAVE ; + _crcmap = crc_map ; +} + +void ftTransferModule::adjustSpeed() +{ + RsStackMutex stack(tfMtx); /******* STACK LOCKED ******/ + + std::map::iterator mit; + + + actualRate = 0; + for(mit = mFileSources.begin(); mit != mFileSources.end(); mit++) + { +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::adjustSpeed()"; + std::cerr << "Peer: " << mit->first; + std::cerr << " Desired Rate: " << (mit->second).desiredRate; + std::cerr << " Actual Rate: " << (mit->second).actualRate; + std::cerr << std::endl; +#endif + actualRate += mit->second.actualRate; + } + +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::adjustSpeed() Totals:"; + std::cerr << "Desired Rate: " << desiredRate << " Actual Rate: " << actualRate; + std::cerr << std::endl; +#endif + + return; +} + + +/******************************************************************************* + * Actual Peer Transfer Management Code. + * + * request very tick, at rate + * + * + **/ + + +/* NOTEs on this function... + * 1) This is the critical function for deciding the rate at which ft takes place. + * 2) Some of the peers might not have the file... care must be taken avoid deadlock. + * + * Eg. A edge case which fails badly. + * Small 1K file (one chunk), with 3 sources (A,B,C). A doesn't have file. + * (a) request data from A. B & C pause cos no more data needed. + * (b) all timeout, chunk reset... then back to request again (a) and repeat. + * (c) all timeout x 5 and are disabled.... no transfer, while B&C had it all the time. + * + * To solve this we might need random waiting periods, so each peer can + * be tried. + * + * + */ + +bool ftTransferModule::locked_tickPeerTransfer(peerInfo &info) +{ + /* how long has it been? */ + time_t ts = time(NULL); + + int ageRecv = ts - info.recvTS; + int ageReq = ts - info.lastTS; + + /* if offline - ignore */ + if ((info.state == PQIPEER_SUSPEND) || + (info.state == PQIPEER_NOT_ONLINE)) + { + + return false; + } + + if (ageReq > (int) (FT_TM_RESTART_DOWNLOAD * (info.nResets + 1))) + { + if (info.nResets > 1) /* 3rd timeout */ + { + /* 90% chance of return false... + * will mean variations in which peer + * starts first. hopefully stop deadlocks. + */ + if (rand() % 10 != 0) + { + return false; + } + } + + info.state = PQIPEER_DOWNLOADING; + info.recvTS = ts; /* reset to activate */ + info.nResets++; + ageRecv = 0; + + if (info.nResets >= FT_TM_MAX_RESETS) + { + /* for this file anyway */ + info.state = PQIPEER_NOT_ONLINE; + return false; + } + } + + if (ageRecv > (int) FT_TM_DOWNLOAD_TIMEOUT) + { + info.state = PQIPEER_IDLE; + return false; + } +#ifdef FT_DEBUG + std::cerr << "locked_tickPeerTransfer() actual rate (before): " << info.actualRate << ", lastTransfers=" << info.lastTransfers << std::endl ; +#endif + /* update rate */ + info.actualRate = info.actualRate * 0.75 + 0.25 * info.lastTransfers; + info.lastTransfers = 0; + + /**************** + * NOTE: If we continually increase the request rate thus: ... + * uint32_t next_req = info.actualRate * 1.25; + * + * then we will achieve max data rate, but we will fill up + * peers out queue and/or network buffers..... + * + * we must therefore monitor the RTT to tell us if this is happening. + */ + + /* emergency shutdown if we are stuck in x 1.25 mode + * probably not needed + */ + +// csoler: I commented this out because that tends to make some sources +// get stuck into minimal 128 B/s rate, when multiple sources are competiting into the +// same limited bandwidth. I don't think this emergency shutdown is necessary anyway. +// +// if ((info.rttActive) && (ts - info.rttStart > FT_TM_SLOW_RTT)) +// { +// if (info.mRateIncrease > 0) +// { +//#ifdef FT_DEBUG +// std::cerr << "!!! - Emergency shutdown because rttActive is true, and age is " << ts - info.rttStart << std::endl ; +//#endif +// info.mRateIncrease = 0; +// info.rttActive = false ; // I've added this to avoid being stuck when rttActive is true +// } +// } + + /* request at more than current rate */ + uint32_t next_req = info.actualRate * (1.0 + info.mRateIncrease); +#ifdef FT_DEBUG + std::cerr << "locked_tickPeerTransfer() actual rate (after): " << actualRate + << " increase factor=" << 1.0 + info.mRateIncrease + << " info.desiredRate=" << info.desiredRate + << " info.actualRate=" << info.actualRate + << ", next_req=" << next_req ; + + std::cerr << std::endl; +#endif + + if (next_req > info.desiredRate * 1.1) + { + next_req = info.desiredRate * 1.1; +#ifdef FT_DEBUG + std::cerr << "locked_tickPeerTransfer() Reached MaxRate: next_req: " << next_req; + std::cerr << std::endl; +#endif + } + + + if (next_req > FT_TM_MAX_PEER_RATE) + { + next_req = FT_TM_MAX_PEER_RATE; +#ifdef FT_DEBUG + std::cerr << "locked_tickPeerTransfer() Reached AbsMaxRate: next_req: " << next_req; + std::cerr << std::endl; +#endif + } + + + if (next_req < FT_TM_MINIMUM_CHUNK) + { + next_req = FT_TM_MINIMUM_CHUNK; +#ifdef FT_DEBUG + std::cerr << "locked_tickPeerTransfer() small chunk: next_req: " << next_req; + std::cerr << std::endl; +#endif + } + + info.lastTS = ts; + +#ifdef FT_DEBUG + std::cerr << "locked_tickPeerTransfer() desired next_req: " << next_req; + std::cerr << std::endl; +#endif + + /* do request */ + uint64_t req_offset = 0; + uint32_t req_size =0 ; + + if (getChunk(info.peerId,next_req,req_offset,req_size)) + { + if (req_size > 0) + { + info.state = PQIPEER_DOWNLOADING; + requestData(info.peerId,req_offset,req_size); + + /* start next rtt measurement */ + if (!info.rttActive) + { + info.rttStart = ts; + info.rttActive = true; + info.rttOffset = req_offset + req_size; + } + } + else + { + std::cerr << "transfermodule::Waiting for available data"; + std::cerr << std::endl; + } + } + + return true; +} + + + + //interface to client module +bool ftTransferModule::locked_recvPeerData(peerInfo &info, uint64_t offset, + uint32_t chunk_size, void *data) +{ +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::locked_recvPeerData()"; + std::cerr << " peerId: " << info.peerId; + std::cerr << " rttOffset: " << info.rttOffset; + std::cerr << " lastTransfers: " << info.lastTransfers; + std::cerr << " offset: " << offset; + std::cerr << " chunksize: " << chunk_size; + std::cerr << " data: " << data; + std::cerr << std::endl; +#endif + + time_t ts = time(NULL); + info.recvTS = ts; + info.nResets = 0; + info.state = PQIPEER_DOWNLOADING; + info.lastTransfers += chunk_size; + + if ((info.rttActive) && (info.rttOffset == offset + chunk_size)) + { + /* update tip */ + int32_t rtt = time(NULL) - info.rttStart; + + /* + * FT_TM_FAST_RTT = 1 sec. mRateIncrease = 1.00 + * FT_TM_SLOW_RTT = 9 sec. mRateIncrease = 0 + * 11 sec. mRateIncrease = -0.25 + * if it is slower than this allow fast data increase. + * initial guess - linear with rtt. + * change if this leads to wild oscillations + * + */ + + info.mRateIncrease = (FT_TM_SLOW_RTT - rtt) * + (FT_TM_MAX_INCREASE / (FT_TM_SLOW_RTT - FT_TM_FAST_RTT)); + + if (info.mRateIncrease > FT_TM_MAX_INCREASE) + info.mRateIncrease = FT_TM_MAX_INCREASE; + + if (info.mRateIncrease < FT_TM_MIN_INCREASE) + info.mRateIncrease = FT_TM_MIN_INCREASE; + + info.rtt = rtt; + info.rttActive = false; + +#ifdef FT_DEBUG + std::cerr << "ftTransferModule::locked_recvPeerData()"; + std::cerr << "Updated Rate based on RTT: " << rtt; + std::cerr << " Rate: " << info.mRateIncrease; + std::cerr << std::endl; +#endif + + } + return true; +} + diff --git a/libretroshare/src/ft/fttransfermodule.h b/libretroshare/src/ft/fttransfermodule.h new file mode 100644 index 000000000..efb03fe06 --- /dev/null +++ b/libretroshare/src/ft/fttransfermodule.h @@ -0,0 +1,203 @@ +/* + * Retroshare file transfer module: ftTransferModule.h + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef FT_TRANSFER_MODULE_HEADER +#define FT_TRANSFER_MODULE_HEADER + +/* + * FUNCTION DESCRIPTION + * + * Each Transfer Module is paired up with a single File Creator, and responsible for the transfer of one file. + * The Transfer Module is responsible for sending requests to peers at the correct data rates, and storing the returned data + * in a FileCreator. + * There are multiple Transfer Modules in the File Transfer system. Their requests are multiplexed through the Client Module. * The Transfer Module contains all the algorithms for sensible Data Requests. + * It must be able to cope with varying data rates and dropped peers without flooding the system with too many requests. + * + */ + +#include +#include +#include + +#include "ft/ftfilecreator.h" +#include "ft/ftdatamultiplex.h" +#include "ft/ftcontroller.h" + +#include "util/rsthreads.h" + +const uint32_t PQIPEER_INIT = 0x0000; +const uint32_t PQIPEER_NOT_ONLINE = 0x0001; +const uint32_t PQIPEER_DOWNLOADING = 0x0002; +const uint32_t PQIPEER_IDLE = 0x0004; +const uint32_t PQIPEER_SUSPEND = 0x0010; + +class HashThread ; + +class peerInfo +{ +public: + peerInfo(std::string peerId_in):peerId(peerId_in),state(PQIPEER_NOT_ONLINE),desiredRate(0),actualRate(0), +// offset(0),chunkSize(0),receivedSize(0), + lastTS(0), + recvTS(0), lastTransfers(0), nResets(0), + rtt(0), rttActive(false), rttStart(0), rttOffset(0), + mRateIncrease(1) + { + return; + } + peerInfo(std::string peerId_in,uint32_t state_in,uint32_t maxRate_in): + peerId(peerId_in),state(state_in),desiredRate(maxRate_in),actualRate(0), +// offset(0),chunkSize(0),receivedSize(0), + lastTS(0), + recvTS(0), lastTransfers(0), nResets(0), + rtt(0), rttActive(false), rttStart(0), rttOffset(0), + mRateIncrease(1) + { + return; + } + std::string peerId; + uint32_t state; + double desiredRate; + double actualRate; + + //current file data request +// uint64_t offset; +// uint32_t chunkSize; + + //already received data size for current request +// uint32_t receivedSize; + + time_t lastTS; /* last Request */ + time_t recvTS; /* last Recv */ + uint32_t lastTransfers; /* data recvd in last second */ + uint32_t nResets; /* count to disable non-existant files */ + + /* rrt rate control */ + uint32_t rtt; /* last rtt */ + bool rttActive; /* have we initialised an rtt measurement */ + time_t rttStart; /* ts of request */ + uint64_t rttOffset; /* end of request */ + float mRateIncrease; /* current rate */ +}; + +class ftFileStatus +{ +public: + enum Status { + PQIFILE_INIT, + PQIFILE_NOT_ONLINE, + PQIFILE_DOWNLOADING, + PQIFILE_COMPLETE, + PQIFILE_CHECKING, + PQIFILE_FAIL, + PQIFILE_FAIL_CANCEL, + PQIFILE_FAIL_NOT_AVAIL, + PQIFILE_FAIL_NOT_OPEN, + PQIFILE_FAIL_NOT_SEEK, + PQIFILE_FAIL_NOT_WRITE, + PQIFILE_FAIL_NOT_READ, + PQIFILE_FAIL_BAD_PATH + }; + + ftFileStatus():hash(""),stat(PQIFILE_INIT) {} + ftFileStatus(std::string hash_in):hash(hash_in),stat(PQIFILE_INIT) {} + + std::string hash; + Status stat; +}; + +class ftTransferModule +{ +public: + ftTransferModule(ftFileCreator *fc, ftDataMultiplex *dm, ftController *c); + ~ftTransferModule(); + + //interface to download controller + bool setFileSources(const std::list& peerIds); + bool addFileSource(const std::string& peerId); + bool removeFileSource(const std::string& peerId); + bool setPeerState(const std::string& peerId,uint32_t state,uint32_t maxRate); //state = ONLINE/OFFLINE + bool getFileSources(std::list &peerIds); + bool getPeerState(const std::string& peerId,uint32_t &state,uint32_t &tfRate); + uint32_t getDataRate(const std::string& peerId); + bool cancelTransfer(); + bool cancelFileTransferUpward(); + bool completeFileTransfer(); + bool isCheckingHash() ; + void forceCheck() ; + void addCRC32Map(const CRC32Map& map) ; + + //interface to multiplex module + bool recvFileData(const std::string& peerId, uint64_t offset, + uint32_t chunk_size, void *data); + void requestData(const std::string& peerId, uint64_t offset, uint32_t chunk_size); + + //interface to file creator + bool getChunk(const std::string& peer_id,uint32_t size_hint,uint64_t &offset, uint32_t &chunk_size); + bool storeData(uint64_t offset, uint32_t chunk_size, void *data); + + int tick(); + + std::string hash() { return mHash; } + uint64_t size() { return mSize; } + + //internal used functions + bool queryInactive(); + void adjustSpeed(); + +private: + + bool locked_tickPeerTransfer(peerInfo &info); + bool locked_recvPeerData(peerInfo &info, uint64_t offset, + uint32_t chunk_size, void *data); + + bool checkFile() ; + bool checkCRC() ; + + /* These have independent Mutexes / are const locally (no Mutex protection)*/ + ftFileCreator *mFileCreator; + ftDataMultiplex *mMultiplexor; + ftController *mFtController; + + std::string mHash; + uint64_t mSize; + + RsMutex tfMtx; /* below is mutex protected */ + + std::list mOnlinePeers; + std::map mFileSources; + + uint16_t mFlag; //2:file canceled, 1:transfer complete, 0: not complete, 3: checking hash, 4: checking chunks + double desiredRate; + double actualRate; + + CRC32Map _crcmap ; + uint32_t _crcmap_state ; + time_t _crcmap_last_asked_time ; + + ftFileStatus mFileStatus; //used for pause/resume file transfer + + HashThread *_hash_thread ; +}; + +#endif //FT_TRANSFER_MODULE_HEADER diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro new file mode 100644 index 000000000..a5e44b380 --- /dev/null +++ b/libretroshare/src/libretroshare.pro @@ -0,0 +1,569 @@ +TEMPLATE = lib +#CONFIG += staticlib release +#CONFIG += staticlib testnetwork +CONFIG += staticlib bitdht +CONFIG -= qt +TARGET = retroshare + +# Beware: All data of the stripped services are lost +#CONFIG += minimal +DEFINES *= PQI_DISABLE_TUNNEL +#ENABLE_CACHE_OPT + +minimal { + CONFIG -= use_blogs + + DEFINES += MINIMAL_LIBRS +} + +profiling { + QMAKE_CXXFLAGS -= -fomit-frame-pointer + QMAKE_CXXFLAGS *= -pg -g -fno-omit-frame-pointer +} + +release { + # UDP and TUNNEL dont work anymore. + #DEFINES *= PQI_DISABLE_UDP +} + + + +testnetwork { + #DEFINES *= PQI_DISABLE_UDP + DEFINES *= PQI_DISABLE_TUNNEL + + # DEFINES *= AUTHSSL_DEBUG GPG_DEBUG + # DEFINES *= CONN_DEBUG + # DEFINES *= P3DISC_DEBUG + + # DEFINES *= PGRP_DEBUG + # DEFINES *= PERSON_DEBUG + + #DEFINES *= DEBUG_UDP_SORTER DEBUG_UDP_LAYER EXTADDRSEARCH_DEBUG + + QMAKE_CXXFLAGS -= -fomit-frame-pointer + QMAKE_CXXFLAGS -= -O2 + QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer +} + + +#CONFIG += debug +debug { +# DEFINES *= DEBUG +# DEFINES *= OPENDHT_DEBUG DHT_DEBUG CONN_DEBUG DEBUG_UDP_SORTER P3DISC_DEBUG DEBUG_UDP_LAYER FT_DEBUG EXTADDRSEARCH_DEBUG +# DEFINES *= CONTROL_DEBUG FT_DEBUG DEBUG_FTCHUNK P3TURTLE_DEBUG +# DEFINES *= P3TURTLE_DEBUG +# DEFINES *= NET_DEBUG +# DEFINES *= DISTRIB_DEBUG +# DEFINES *= P3TURTLE_DEBUG FT_DEBUG DEBUG_FTCHUNK MPLEX_DEBUG +# DEFINES *= STATUS_DEBUG SERV_DEBUG RSSERIAL_DEBUG #CONN_DEBUG + + QMAKE_CXXFLAGS -= -O2 -fomit-frame-pointer + QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer +} + +bitdht { + +HEADERS += dht/p3bitdht.h +SOURCES += dht/p3bitdht.cc + + +HEADERS += tcponudp/udppeer.h \ + tcponudp/bio_tou.h \ + tcponudp/tcppacket.h \ + tcponudp/tcpstream.h \ + tcponudp/tou.h \ + tcponudp/udpstunner.h \ + tcponudp/udprelay.h \ + +SOURCES += tcponudp/udppeer.cc \ + tcponudp/tcppacket.cc \ + tcponudp/tcpstream.cc \ + tcponudp/tou.cc \ + tcponudp/bss_tou.c \ + tcponudp/udpstunner.cc \ + tcponudp/udprelay.cc \ + +# These two aren't actually used (and don't compile) .... +# but could be useful later +# +# tcponudp/udpstunner.h \ +# tcponudp/udpstunner.cc \ +# + + + BITDHT_DIR = ../../libbitdht/src + INCLUDEPATH += . $${BITDHT_DIR} + # The next line if for compliance with debian packages. Keep it! + INCLUDEPATH += ../libbitdht + DEFINES *= RS_USE_BITDHT +} + + +test_bitdht { + # DISABLE TCP CONNECTIONS... + DEFINES *= P3CONNMGR_NO_TCP_CONNECTIONS + + # NO AUTO CONNECTIONS??? FOR TESTING DHT STATUS. + DEFINES *= P3CONNMGR_NO_AUTO_CONNECTION + + # ENABLED UDP NOW. +} + + + + + +use_blogs { + + HEADERS += services/p3blogs.h + SOURCES += services/p3blogs.cc + + DEFINES *= RS_USE_BLOGS +} + +PUBLIC_HEADERS = retroshare/rsblogs.h \ + retroshare/rschannels.h \ + retroshare/rsdisc.h \ + retroshare/rsdistrib.h \ + retroshare/rsexpr.h \ + retroshare/rsfiles.h \ + retroshare/rsforums.h \ + retroshare/rsiface.h \ + retroshare/rsinit.h \ + retroshare/rsplugin.h \ + retroshare/rsloginhandler.h \ + retroshare/rsmsgs.h \ + retroshare/rsnotify.h \ + retroshare/rspeers.h \ + retroshare/rsrank.h \ + retroshare/rsstatus.h \ + retroshare/rsturtle.h \ + retroshare/rstypes.h + +HEADERS += plugins/pluginmanager.h \ + plugins/dlfcn_win32.h + +HEADERS += $$PUBLIC_HEADERS + +# public headers to be... +HEADERS += retroshare/rsgame.h \ + retroshare/rsphoto.h + +################################# Linux ########################################## +linux-* { + isEmpty(PREFIX) { PREFIX = /usr } + isEmpty(INC_DIR) { INC_DIR = $${PREFIX}/include/retroshare/ } + isEmpty(LIB_DIR) { LIB_DIR = $${PREFIX}/lib/ } + + # These two lines fixe compilation on ubuntu natty. Probably a ubuntu packaging error. + INCLUDEPATH *= /usr/lib/x86_64-linux-gnu/glib-2.0/include/ + INCLUDEPATH *= /usr/lib/i386-linux-gnu/glib-2.0/include/ + + DESTDIR = lib + QMAKE_CXXFLAGS *= -Wall -D_FILE_OFFSET_BITS=64 + QMAKE_CC = g++ + + SSL_DIR = /usr/include/openssl + UPNP_DIR = /usr/include/upnp + INCLUDEPATH += . $${SSL_DIR} $${UPNP_DIR} + + #gpg files + system(which gpg-error-config >/dev/null 2>&1) { + INCLUDEPATH += $$system(gpg-error-config --cflags | sed -e "s/-I//g") + } else { + message(Could not find gpg-error-config on your system, assuming gpg-error.h is in /usr/include) + } + system(which gpgme-config >/dev/null 2>&1) { + INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") + } else { + message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) + } + + #libupnp implementation files + HEADERS += upnp/UPnPBase.h + SOURCES += upnp/UPnPBase.cpp + + # where to put the shared library itself + target.path = $$LIB_DIR + INSTALLS *= target + + # where to put the library's interface + include_rsiface.path = $${INC_DIR} + include_rsiface.files = $$PUBLIC_HEADERS + INSTALLS += include_rsiface + + #CONFIG += version_detail_bash_script + + DEFINES *= UBUNTU + INCLUDEPATH += /usr/include/glib-2.0/ /usr/lib/glib-2.0/include + LIBS *= -lgnome-keyring +} + +linux-g++ { + OBJECTS_DIR = temp/linux-g++/obj +} + +linux-g++-64 { + OBJECTS_DIR = temp/linux-g++-64/obj +} + +version_detail_bash_script { + QMAKE_EXTRA_TARGETS += write_version_detail + PRE_TARGETDEPS = write_version_detail + write_version_detail.commands = ./version_detail.sh +} + +#################### Cross compilation for windows under Linux #################### + +win32-x-g++ { + OBJECTS_DIR = temp/win32xgcc/obj + DESTDIR = lib.win32xgcc + DEFINES *= WINDOWS_SYS WIN32 WIN_CROSS_UBUNTU + QMAKE_CXXFLAGS *= -Wmissing-include-dirs + QMAKE_CC = i586-mingw32msvc-g++ + QMAKE_LIB = i586-mingw32msvc-ar + QMAKE_AR = i586-mingw32msvc-ar + DEFINES *= STATICLIB WIN32 + + #miniupnp implementation files + HEADERS += upnp/upnputil.h + SOURCES += upnp/upnputil.c + + SSL_DIR=../../../../openssl + UPNPC_DIR = ../../../../miniupnpc-1.3 + GPG_ERROR_DIR = ../../../../libgpg-error-1.7 + GPGME_DIR = ../../../../gpgme-1.1.8 + + INCLUDEPATH *= /usr/i586-mingw32msvc/include ${HOME}/.wine/drive_c/pthreads/include/ +} +################################# Windows ########################################## + + +win32 { + QMAKE_CC = g++ + OBJECTS_DIR = temp/obj + MOC_DIR = temp/moc + DEFINES *= WINDOWS_SYS WIN32 STATICLIB MINGW + DEFINES *= MINIUPNPC_VERSION=13 + DESTDIR = lib + + # Switch off optimization for release version + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE += -O0 + QMAKE_CFLAGS_RELEASE -= -O2 + QMAKE_CFLAGS_RELEASE += -O0 + + # Switch on optimization for debug version + #QMAKE_CXXFLAGS_DEBUG += -O2 + #QMAKE_CFLAGS_DEBUG += -O2 + + DEFINES += USE_CMD_ARGS + + #miniupnp implementation files + HEADERS += upnp/upnputil.h + SOURCES += upnp/upnputil.c + + + UPNPC_DIR = ../../../../miniupnpc-1.3 + GPG_ERROR_DIR = ../../../../libgpg-error-1.7 + GPGME_DIR = ../../../../gpgme-1.1.8 + + PTHREADS_DIR = ../../../../pthreads-w32-2-8-0-release + ZLIB_DIR = ../../../../zlib-1.2.3 + SSL_DIR = ../../../../OpenSSL + + + INCLUDEPATH += . $${SSL_DIR}/include $${UPNPC_DIR} $${PTHREADS_DIR} $${ZLIB_DIR} $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src +} + + +################################# MacOSX ########################################## + +mac { + QMAKE_CC = g++ + OBJECTS_DIR = temp/obj + MOC_DIR = temp/moc + #DEFINES = WINDOWS_SYS WIN32 STATICLIB MINGW + #DEFINES *= MINIUPNPC_VERSION=13 + DESTDIR = lib + + #miniupnp implementation files + HEADERS += upnp/upnputil.h + SOURCES += upnp/upnputil.c + + # Beautiful Hack to fix 64bit file access. + QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dfopen64=fopen -Dvstatfs64=vstatfs + + UPNPC_DIR = ../../../miniupnpc-1.0 + GPG_ERROR_DIR = ../../../../libgpg-error-1.7 + GPGME_DIR = ../../../../gpgme-1.1.8 + + INCLUDEPATH += . $${UPNPC_DIR} + #INCLUDEPATH += . $${UPNPC_DIR} $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src +} + +################################### COMMON stuff ################################## + +HEADERS += dbase/cachestrapper.h \ + dbase/fimonitor.h \ + dbase/findex.h \ + dbase/fistore.h + +#HEADERS += dht/p3bitdht.h \ + +HEADERS += ft/ftchunkmap.h \ + ft/ftcontroller.h \ + ft/ftdata.h \ + ft/ftdatamultiplex.h \ + ft/ftdbase.h \ + ft/ftextralist.h \ + ft/ftfilecreator.h \ + ft/ftfileprovider.h \ + ft/ftfilesearch.h \ + ft/ftsearch.h \ + ft/ftserver.h \ + ft/fttransfermodule.h + +HEADERS += pqi/authssl.h \ + pqi/authgpg.h \ + pqi/cleanupxpgp.h \ + pqi/p3cfgmgr.h \ + pqi/p3connmgr.h \ + pqi/p3dhtmgr.h \ + pqi/p3notify.h \ + pqi/p3upnpmgr.h \ + pqi/pqi.h \ + pqi/pqi_base.h \ + pqi/pqiarchive.h \ + pqi/pqiassist.h \ + pqi/pqibin.h \ + pqi/pqihandler.h \ + pqi/pqihash.h \ + pqi/pqiindic.h \ + pqi/pqiipset.h \ + pqi/pqilistener.h \ + pqi/pqiloopback.h \ + pqi/pqimonitor.h \ + pqi/pqinetwork.h \ + pqi/pqinotify.h \ + pqi/pqiperson.h \ + pqi/pqipersongrp.h \ + pqi/pqisecurity.h \ + pqi/pqiservice.h \ + pqi/pqissl.h \ + pqi/pqissllistener.h \ + pqi/pqisslpersongrp.h \ + pqi/pqissltunnel.h \ + pqi/pqissludp.h \ + pqi/pqistore.h \ + pqi/pqistreamer.h \ + pqi/sslfns.h + +HEADERS += rsserver/p3discovery.h \ + rsserver/p3face.h \ + rsserver/p3msgs.h \ + rsserver/p3peers.h \ + rsserver/p3photo.h \ + rsserver/p3status.h + +HEADERS += serialiser/rsbaseitems.h \ + serialiser/rsbaseserial.h \ + serialiser/rsblogitems.h \ + serialiser/rschannelitems.h \ + serialiser/rsconfigitems.h \ + serialiser/rsdiscitems.h \ + serialiser/rsdistribitems.h \ + serialiser/rsforumitems.h \ + serialiser/rsgameitems.h \ + serialiser/rsmsgitems.h \ + serialiser/rsphotoitems.h \ + serialiser/rsserial.h \ + serialiser/rsserviceids.h \ + serialiser/rsserviceitems.h \ + serialiser/rsstatusitems.h \ + serialiser/rstlvaddrs.h \ + serialiser/rstlvbase.h \ + serialiser/rstlvkeys.h \ + serialiser/rstlvkvwide.h \ + serialiser/rstlvtypes.h \ + serialiser/rstlvutil.h \ + serialiser/rstunnelitems.h + +HEADERS += services/p3channels.h \ + services/p3chatservice.h \ + services/p3disc.h \ + services/p3distrib.h \ + services/p3forums.h \ + services/p3gamelauncher.h \ + services/p3gameservice.h \ + services/p3msgservice.h \ + services/p3photoservice.h \ + services/p3portservice.h \ + services/p3service.h \ + services/p3statusservice.h \ + services/p3tunnel.h +# services/p3blogs.h \ + +HEADERS += turtle/p3turtle.h \ + turtle/rsturtleitem.h \ + turtle/turtletypes.h + +HEADERS += upnp/upnphandler.h + +HEADERS += util/folderiterator.h \ + util/rsdebug.h \ + util/smallobject.h \ + util/rsdir.h \ + util/rsdiscspace.h \ + util/rsnet.h \ + util/extaddrfinder.h \ + util/dnsresolver.h \ + util/rsprint.h \ + util/rsthreads.h \ + util/rsversion.h \ + util/rswin.h \ + util/rsrandom.h \ + util/pugiconfig.h \ + util/pugixml.h + +SOURCES += dbase/cachestrapper.cc \ + dbase/fimonitor.cc \ + dbase/findex.cc \ + dbase/fistore.cc \ + dbase/rsexpr.cc + + +SOURCES += ft/ftchunkmap.cc \ + ft/ftcontroller.cc \ + ft/ftdata.cc \ + ft/ftdatamultiplex.cc \ + ft/ftdbase.cc \ + ft/ftextralist.cc \ + ft/ftfilecreator.cc \ + ft/ftfileprovider.cc \ + ft/ftfilesearch.cc \ + ft/ftserver.cc \ + ft/fttransfermodule.cc \ + +SOURCES += pqi/authgpg.cc \ + pqi/authssl.cc \ + pqi/cleanupxpgp.cc \ + pqi/p3cfgmgr.cc \ + pqi/p3connmgr.cc \ + pqi/p3dhtmgr.cc \ + pqi/p3notify.cc \ + pqi/pqiarchive.cc \ + pqi/pqibin.cc \ + pqi/pqihandler.cc \ + pqi/pqiipset.cc \ + pqi/pqiloopback.cc \ + pqi/pqimonitor.cc \ + pqi/pqinetwork.cc \ + pqi/pqiperson.cc \ + pqi/pqipersongrp.cc \ + pqi/pqisecurity.cc \ + pqi/pqiservice.cc \ + pqi/pqissl.cc \ + pqi/pqissllistener.cc \ + pqi/pqisslpersongrp.cc \ + pqi/pqissltunnel.cc \ + pqi/pqissludp.cc \ + pqi/pqistore.cc \ + pqi/pqistreamer.cc \ + pqi/sslfns.cc + +SOURCES += rsserver/p3discovery.cc \ + rsserver/p3face-config.cc \ + rsserver/p3face-msgs.cc \ + rsserver/p3face-server.cc \ + rsserver/p3msgs.cc \ + rsserver/p3peers.cc \ + rsserver/p3photo.cc \ + rsserver/p3status.cc \ + rsserver/rsiface.cc \ + rsserver/rsinit.cc \ + rsserver/rsloginhandler.cc \ + rsserver/rstypes.cc + +SOURCES += plugins/pluginmanager.cc \ + plugins/dlfcn_win32.cc + +SOURCES += serialiser/rsbaseitems.cc \ + serialiser/rsbaseserial.cc \ + serialiser/rsblogitems.cc \ + serialiser/rschannelitems.cc \ + serialiser/rsconfigitems.cc \ + serialiser/rsdiscitems.cc \ + serialiser/rsdistribitems.cc \ + serialiser/rsforumitems.cc \ + serialiser/rsgameitems.cc \ + serialiser/rsmsgitems.cc \ + serialiser/rsphotoitems.cc \ + serialiser/rsserial.cc \ + serialiser/rsstatusitems.cc \ + serialiser/rstlvaddrs.cc \ + serialiser/rstlvbase.cc \ + serialiser/rstlvfileitem.cc \ + serialiser/rstlvimage.cc \ + serialiser/rstlvkeys.cc \ + serialiser/rstlvkvwide.cc \ + serialiser/rstlvtypes.cc \ + serialiser/rstlvutil.cc \ + serialiser/rstunnelitems.cc + +SOURCES += services/p3channels.cc \ + services/p3chatservice.cc \ + services/p3disc.cc \ + services/p3distrib.cc \ + services/p3forums.cc \ + services/p3gamelauncher.cc \ + services/p3msgservice.cc \ + services/p3photoservice.cc \ + services/p3portservice.cc \ + services/p3service.cc \ + services/p3statusservice.cc +# removed because getPeer() doesn t exist services/p3tunnel.cc + + +SOURCES += turtle/p3turtle.cc \ + turtle/rsturtleitem.cc +# turtle/turtlerouting.cc \ +# turtle/turtlesearch.cc \ +# turtle/turtletunnels.cc + +SOURCES += upnp/upnphandler.cc + +SOURCES += util/folderiterator.cc \ + util/rsdebug.cc \ + util/smallobject.cc \ + util/rsdir.cc \ + util/rsdiscspace.cc \ + util/rsnet.cc \ + util/extaddrfinder.cc \ + util/dnsresolver.cc \ + util/rsprint.cc \ + util/rsthreads.cc \ + util/rsversion.cc \ + util/rswin.cc \ + util/rsrandom.cc \ + util/pugixml.cc + +minimal { + SOURCES -= rsserver/p3msgs.cc \ + rsserver/p3status.cc \ + rsserver/p3photo.cc + + SOURCES -= serialiser/rsforumitems.cc \ + serialiser/rsstatusitems.cc \ + serialiser/rschannelitems.cc \ + serialiser/rsgameitems.cc \ + serialiser/rsphotoitems.cc + + SOURCES -= services/p3forums.cc \ + services/p3msgservice.cc \ + services/p3statusservice.cc \ + services/p3channels.cc \ + services/p3gamelauncher.cc \ + services/p3photoservice.cc +} diff --git a/libretroshare/src/licence b/libretroshare/src/licence new file mode 100644 index 000000000..0f1320391 --- /dev/null +++ b/libretroshare/src/licence @@ -0,0 +1,27 @@ +/* + * "$Id: licence,v 1.1 2007-02-18 21:46:42 rmf24 Exp $" + * + * TOU + 3P/PQI + RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + diff --git a/libretroshare/src/mingw32make.bat b/libretroshare/src/mingw32make.bat new file mode 100644 index 000000000..b9c84ebf5 --- /dev/null +++ b/libretroshare/src/mingw32make.bat @@ -0,0 +1,15 @@ +set QTDIR=d:\qt\2010.01 +set MINGW=%QTDIR%\mingw + +set PATH=%QTDIR%\qt\bin;%QTDIR%\bin;%MINGW%\bin;%PATH% + +"D:\Programme\TortoiseSVN\bin\SubWCRev" . util\rsversion.in util\rsversion.h + +mingw32-make clean + +qmake libretroshare.pro + +mingw32-make + +pause + diff --git a/libretroshare/src/plugins/dlfcn_win32.cc b/libretroshare/src/plugins/dlfcn_win32.cc new file mode 100644 index 000000000..58aa8ffb1 --- /dev/null +++ b/libretroshare/src/plugins/dlfcn_win32.cc @@ -0,0 +1,318 @@ +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef WINDOWS_SYS + +#include +#include + +#include "dlfcn_win32.h" + +/* Note: + * MSDN says these functions are not thread-safe. We make no efforts to have + * any kind of thread safety. + */ + +typedef struct global_object { + HMODULE hModule; + struct global_object *previous; + struct global_object *next; +} global_object; + +static global_object first_object; + +/* These functions implement a double linked list for the global objects. */ +static global_object *global_search( HMODULE hModule ) +{ + global_object *pobject; + + if( hModule == NULL ) + return NULL; + + for( pobject = &first_object; pobject ; pobject = pobject->next ) + if( pobject->hModule == hModule ) + return pobject; + + return NULL; +} + +static void global_add( HMODULE hModule ) +{ + global_object *pobject; + global_object *nobject; + + if( hModule == NULL ) + return; + + pobject = global_search( hModule ); + + /* Do not add object again if it's already on the list */ + if( pobject ) + return; + + for( pobject = &first_object; pobject->next ; pobject = pobject->next ); + + nobject = (global_object*) malloc( sizeof(global_object) ); + + /* Should this be enough to fail global_add, and therefore also fail + * dlopen? + */ + if( !nobject ) + return; + + pobject->next = nobject; + nobject->next = NULL; + nobject->previous = pobject; + nobject->hModule = hModule; +} + +static void global_rem( HMODULE hModule ) +{ + global_object *pobject; + + if( hModule == NULL ) + return; + + pobject = global_search( hModule ); + + if( !pobject ) + return; + + if( pobject->next ) + pobject->next->previous = pobject->previous; + if( pobject->previous ) + pobject->previous->next = pobject->next; + + free( pobject ); +} + +/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one + * static buffer. + * MSDN says the buffer cannot be larger than 64K bytes, so we set it to + * the limit. + */ +static char error_buffer[65535]; +static char *current_error; + +static int copy_string( char *dest, int dest_size, const char *src ) +{ + int i = 0; + + /* gcc should optimize this out */ + if( !src && !dest ) + return 0; + + for( i = 0 ; i < dest_size-1 ; i++ ) + { + if( !src[i] ) + break; + else + dest[i] = src[i]; + } + dest[i] = '\0'; + + return i; +} + +static void save_err_str( const char *str ) +{ + DWORD dwMessageId; + DWORD pos; + + dwMessageId = GetLastError( ); + + if( dwMessageId == 0 ) + return; + + /* Format error message to: + * "": + */ + pos = copy_string( error_buffer, sizeof(error_buffer), "\"" ); + pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, str ); + pos += copy_string( error_buffer+pos, sizeof(error_buffer)-pos, "\": " ); + pos += FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), + error_buffer+pos, sizeof(error_buffer)-pos, NULL ); + + if( pos > 1 ) + { + /* POSIX says the string must not have trailing */ + if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' ) + error_buffer[pos-2] = '\0'; + } + + current_error = error_buffer; +} + +static void save_err_ptr_str( const void *ptr ) +{ + char ptr_buf[19]; /* 0x up to 64 bits. */ + + sprintf( ptr_buf, "0x%p", ptr ); + + save_err_str( ptr_buf ); +} + +void *dlopen( const char *file, int mode ) +{ + HMODULE hModule; + UINT uMode; + + current_error = NULL; + + /* Do not let Windows display the critical-error-handler message box */ + uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); + + if( file == 0 ) + { + /* POSIX says that if the value of file is 0, a handle on a global + * symbol object must be provided. That object must be able to access + * all symbols from the original program file, and any objects loaded + * with the RTLD_GLOBAL flag. + * The return value from GetModuleHandle( ) allows us to retrieve + * symbols only from the original program file. For objects loaded with + * the RTLD_GLOBAL flag, we create our own list later on. + */ + hModule = GetModuleHandle( NULL ); + + if( !hModule ) + save_err_ptr_str( file ); + } + else + { + char lpFileName[MAX_PATH]; + int i; + + /* MSDN says backslashes *must* be used instead of forward slashes. */ + for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) + { + if( !file[i] ) + break; + else if( file[i] == '/' ) + lpFileName[i] = '\\'; + else + lpFileName[i] = file[i]; + } + lpFileName[i] = '\0'; + + /* POSIX says the search path is implementation-defined. + * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely + * to UNIX's search paths (start with system folders instead of current + * folder). + */ + hModule = LoadLibraryExA( (LPSTR) lpFileName, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH ); + + /* If the object was loaded with RTLD_GLOBAL, add it to list of global + * objects, so that its symbols may be retrieved even if the handle for + * the original program file is passed. POSIX says that if the same + * file is specified in multiple invocations, and any of them are + * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the + * symbols will remain global. + */ + if( !hModule ) + save_err_str( lpFileName ); + else if( (mode & RTLD_GLOBAL) ) + global_add( hModule ); + } + + /* Return to previous state of the error-mode bit flags. */ + SetErrorMode( uMode ); + + return (void *) hModule; +} + +int dlclose( void *handle ) +{ + HMODULE hModule = (HMODULE) handle; + BOOL ret; + + current_error = NULL; + + ret = FreeLibrary( hModule ); + + /* If the object was loaded with RTLD_GLOBAL, remove it from list of global + * objects. + */ + if( ret ) + global_rem( hModule ); + else + save_err_ptr_str( handle ); + + /* dlclose's return value in inverted in relation to FreeLibrary's. */ + ret = !ret; + + return (int) ret; +} + +void *dlsym( void *handle, const char *name ) +{ + FARPROC symbol; + + current_error = NULL; + + symbol = GetProcAddress( (HINSTANCE) handle, name ); + + if( symbol == NULL ) + { + HMODULE hModule; + + /* If the handle for the original program file is passed, also search + * in all globally loaded objects. + */ + + hModule = GetModuleHandle( NULL ); + + if( hModule == handle ) + { + global_object *pobject; + + for( pobject = &first_object; pobject ; pobject = pobject->next ) + { + if( pobject->hModule ) + { + symbol = GetProcAddress( pobject->hModule, name ); + if( symbol != NULL ) + break; + } + } + } + + // Do not close the handle of the calling process +// CloseHandle( hModule ); + } + + if( symbol == NULL ) + save_err_str( name ); + + return (void*) symbol; +} + +char *dlerror( void ) +{ + char *error_pointer = current_error; + + /* POSIX says that invoking dlerror( ) a second time, immediately following + * a prior invocation, shall result in NULL being returned. + */ + current_error = NULL; + + return error_pointer; +} +#endif diff --git a/libretroshare/src/plugins/dlfcn_win32.h b/libretroshare/src/plugins/dlfcn_win32.h new file mode 100644 index 000000000..af33af443 --- /dev/null +++ b/libretroshare/src/plugins/dlfcn_win32.h @@ -0,0 +1,47 @@ +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef WINDOWS_SYS +#ifndef DLFCN_H +#define DLFCN_H + +/* POSIX says these are implementation-defined. + * To simplify use with Windows API, we treat them the same way. + */ + +#define RTLD_LAZY 0 +#define RTLD_NOW 0 + +#define RTLD_GLOBAL (1 << 1) +#define RTLD_LOCAL (1 << 2) + +/* These two were added in The Open Group Base Specifications Issue 6. + * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. + */ + +#define RTLD_DEFAULT 0 +#define RTLD_NEXT 0 + +void *dlopen ( const char *file, int mode ); +int dlclose( void *handle ); +void *dlsym ( void *handle, const char *name ); +char *dlerror( void ); + +#endif /* DLFCN_H */ +#endif /* WINDOWS_SYS */ diff --git a/libretroshare/src/plugins/pluginclasses.h b/libretroshare/src/plugins/pluginclasses.h new file mode 100644 index 000000000..889d49abe --- /dev/null +++ b/libretroshare/src/plugins/pluginclasses.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +// The following class abstracts the construction of a cache service. The user only has to +// supply RS with a type ID. If the ID is already in use, RS will complain. +// +class RsCacheService: public CacheSource, public CacheStore, public p3Config +{ + public: + RsCacheService(uint16_t type,uint32_t config_type,uint32_t tick_delay_in_seconds) ; + + uint32_t tickDelay() const { return _tick_delay_in_seconds ; } + virtual void tick() {} + + // Functions from p3config + // + virtual RsSerialiser *setupSerialiser() { return NULL ; } + virtual bool saveList(bool&, std::list&) { return false ;} + virtual bool loadList(std::list&) { return false ;} + + private: + uint32_t _tick_delay_in_seconds ; +}; + diff --git a/libretroshare/src/plugins/pluginmanager.cc b/libretroshare/src/plugins/pluginmanager.cc new file mode 100644 index 000000000..932329337 --- /dev/null +++ b/libretroshare/src/plugins/pluginmanager.cc @@ -0,0 +1,206 @@ +#include + +#include "pluginmanager.h" +#include +#include +#include +#include +#include +#include +#include +#include + +// lets disable the plugin system for now, as it's unfinished. +#ifdef WINDOWS_SYS +#include "dlfcn_win32.h" +#else +#include +#endif + +std::string RsPluginManager::_plugin_entry_symbol ; +std::string RsPluginManager::_local_cache_dir ; +std::string RsPluginManager::_remote_cache_dir ; +std::vector RsPluginManager::_plugin_directories ; + +ftServer *RsPluginManager::_ftserver = NULL ; +p3ConnectMgr *RsPluginManager::_connectmgr = NULL ; + +typedef RsPlugin *(*RetroSharePluginEntry)(void) ; +RsPluginHandler *rsPlugins ; + +void RsPluginManager::setCacheDirectories(const std::string& local_cache, const std::string& remote_cache) +{ + _local_cache_dir = local_cache ; + _remote_cache_dir = remote_cache ; +} + +bool RsPluginManager::acceptablePluginName(const std::string& name) +{ + // Needs some windows specific code here + // +#ifdef WINDOWS_SYS + return name.size() > 4 && name.substr(name.size() - 4) == ".dll"; +#else + return name.size() > 3 && !strcmp(name.c_str()+name.size()-3,".so") ; +#endif +} + +void RsPluginManager::loadPlugins(const std::vector& plugin_directories) +{ + _plugin_directories = plugin_directories ; + _plugin_entry_symbol = "RETROSHARE_PLUGIN_provide" ; + + // 0 - get the list of files to read + + for(uint32_t i=0;irs_cache_service() != NULL && (seconds % _plugins[i]->rs_cache_service()->tickDelay() )) + { + std::cerr << " ticking plugin " << _plugins[i]->getPluginName() << std::endl; + _plugins[i]->rs_cache_service()->tick() ; + } +} + +void RsPluginManager::registerCacheServices() +{ + std::cerr << " Registering cache services." << std::endl; + + for(uint32_t i=0;i<_plugins.size();++i) + if(_plugins[i]->rs_cache_service() != NULL) + { + rsFiles->getCacheStrapper()->addCachePair(CachePair(_plugins[i]->rs_cache_service(),_plugins[i]->rs_cache_service(),CacheId(_plugins[i]->rs_service_id(), 0))) ; + std::cerr << " adding new cache pair for plugin " << _plugins[i]->getPluginName() << ", with RS_ID " << _plugins[i]->rs_service_id() << std::endl ; + } +} + +void RsPluginManager::registerClientServices(p3ServiceServer *pqih) +{ + std::cerr << " Registering pqi services." << std::endl; + + for(uint32_t i=0;i<_plugins.size();++i) + if(_plugins[i]->rs_pqi_service() != NULL) + { + pqih->addService(_plugins[i]->rs_pqi_service()) ; + std::cerr << " Added pqi service for plugin " << _plugins[i]->getPluginName() << std::endl; + } +} + +void RsPluginManager::addConfigurations(p3ConfigMgr *ConfigMgr) +{ + std::cerr << " Registering configuration files." << std::endl; + + for(uint32_t i=0;i<_plugins.size();++i) + if(_plugins[i]->configurationFileName().length() > 0) + { + ConfigMgr->addConfiguration(_plugins[i]->configurationFileName(), _plugins[i]->rs_cache_service()); + std::cerr << " Added configuration for plugin " << _plugins[i]->getPluginName() << ", with file " << _plugins[i]->configurationFileName() << std::endl; + } +} + +RsCacheService::RsCacheService(uint16_t service_type,uint32_t config_type,uint32_t tick_delay) + : CacheSource(service_type, true, rsPlugins->getFileServer()->getCacheStrapper(), rsPlugins->getLocalCacheDir()), + CacheStore (service_type, true, rsPlugins->getFileServer()->getCacheStrapper(), rsPlugins->getFileServer()->getCacheTransfer(), rsPlugins->getRemoteCacheDir()), + p3Config(config_type), // CONFIG_TYPE_RANK_LINK + _tick_delay_in_seconds(tick_delay) +{ +} + diff --git a/libretroshare/src/plugins/pluginmanager.h b/libretroshare/src/plugins/pluginmanager.h new file mode 100644 index 000000000..fdb2096b9 --- /dev/null +++ b/libretroshare/src/plugins/pluginmanager.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include + +class p3ConfigMgr ; +class p3ServiceServer ; +class p3ConnectMgr ; + +class RsPluginManager: public RsPluginHandler +{ + public: + RsPluginManager() {} + virtual ~RsPluginManager() {} + + virtual int nbPlugins() const { return _plugins.size() ; } + virtual RsPlugin *plugin(int i) { return _plugins[i] ; } + virtual const std::vector& getPluginDirectories() const { return _plugin_directories ; } + + + virtual void slowTickPlugins(time_t sec) ; + virtual void addConfigurations(p3ConfigMgr *cfgMgr) ; + virtual const std::string& getLocalCacheDir() const ; + virtual const std::string& getRemoteCacheDir() const ; + virtual ftServer *getFileServer() const ; + virtual p3ConnectMgr *getConnectMgr() const ; + + static void setPluginEntrySymbol(const std::string& s) { _plugin_entry_symbol = s ; } + static bool acceptablePluginName(const std::string& s) ; + static void setCacheDirectories(const std::string& local,const std::string& remote) ; + static void setFileServer(ftServer *ft) { _ftserver = ft ; } + static void setConnectMgr(p3ConnectMgr *cm) { _connectmgr = cm ; } + + void loadPlugins(const std::vector& plugin_directories) ; + + void registerCacheServices() ; + void registerClientServices(p3ServiceServer *pqih) ; + private: + bool loadPlugin(const std::string& shared_library_name) ; + + std::vector _plugins ; + + static std::string _plugin_entry_symbol ; + static std::string _remote_cache_dir ; + static std::string _local_cache_dir ; + static ftServer *_ftserver ; + static p3ConnectMgr *_connectmgr ; + + static std::vector _plugin_directories ; +}; + diff --git a/libretroshare/src/pqi/Makefile b/libretroshare/src/pqi/Makefile new file mode 100644 index 000000000..dc41bfa16 --- /dev/null +++ b/libretroshare/src/pqi/Makefile @@ -0,0 +1,77 @@ + +RS_TOP_DIR = .. +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/scripts/config.mk +############################################################### + +BASE_OBJ = pqisecurity.o pqinetwork.o +#pqi_base.o + +LOOP_OBJ = pqiloopback.o +STREAM_OBJ = pqistreamer.o pqiarchive.o pqistore.o pqibin.o +MGR_OBJ = pqimonitor.o p3dhtmgr.o p3connmgr.o p3cfgmgr.o p3authmgr.o +GRP_OBJ = pqiperson.o pqihandler.o pqiservice.o pqipersongrp.o +SSL_OBJ = pqissl.o pqissllistener.o pqisslpersongrp.o cleanupxpgp.o +UDP_OBJ = pqissludp.o + +OTHER_OBJ = p3notify.o + + +TESTOBJ = net_test.o dht_test.o net_test1.o netiface_test.o +#conn_test.o + +TESTS = net_test dht_test net_test1 netiface_test +#conn_test + +ifdef PQI_USE_XPGP + SSL_OBJ += authxpgp.o + TESTOBJ += xpgp_id.o + TESTS += xpgp_id +else + ifdef PQI_USE_SSLONLY + SSL_OBJ += authssl.o + else + SSL_OBJ += authssl.o authgpg.o + TESTOBJ += gpgme_tst.o + TESTS += gpgme_tst + endif +endif + +RSOBJ = $(BASE_OBJ) $(LOOP_OBJ) \ + $(STREAM_OBJ) \ + $(MGR_OBJ) \ + $(SSL_OBJ) \ + $(UDP_OBJ) \ + $(GRP_OBJ) \ + $(OTHER_OBJ) + +all: librs tests + +gpgme_tst: gpgme_tst.o + $(CC) $(CFLAGS) -o gpgme_tst gpgme_tst.o $(LIBS) + +xpgp_id: xpgp_id.o + $(CC) $(CFLAGS) -o xpgp_id xpgp_id.o $(LIBS) + +dht_test: dht_test.o + $(CC) $(CFLAGS) -o dht_test dht_test.o $(LIBS) + +conn_test: conn_test.o + $(CC) $(CFLAGS) -o conn_test conn_test.o $(LIBS) + +net_test: net_test.o + $(CC) $(CFLAGS) -o net_test net_test.o $(LIBS) + +net_test1: net_test1.o + $(CC) $(CFLAGS) -o net_test1 net_test1.o $(LIBS) + +netiface_test: netiface_test.o + $(CC) $(CFLAGS) -o netiface_test netiface_test.o $(LIBS) + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/pqi/authgpg.cc b/libretroshare/src/pqi/authgpg.cc new file mode 100644 index 000000000..f1c846fb8 --- /dev/null +++ b/libretroshare/src/pqi/authgpg.cc @@ -0,0 +1,2469 @@ +/* + * libretroshare/src AuthGPG.cc + * + * GnuPG/GPGme interface for RetroShare. + * + * Copyright 2008-2009 by Robert Fernie, Retroshare Team. + * + * This library is free software; you can redistribute it and/or + * modify it under the termsf the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + * + */ + +#include "authgpg.h" +#include "retroshare/rsiface.h" +#include "retroshare/rsinit.h" +#include +#include +#include +#include +#include "serialiser/rsconfigitems.h" +#include "cleanupxpgp.h" + +const time_t STORE_KEY_TIMEOUT = 1 * 60 * 60; //store key is call around every hour + +void cleanupZombies(int numkill); // function to cleanup zombies under OSX. + +//#define GPG_DEBUG 1 + +static AuthGPG *instance_gpg = NULL; + +void AuthGPGInit() +{ + instance_gpg = new AuthGPGimpl(); +} + + + +void AuthGPGExit() +{ + if (instance_gpg) { + instance_gpg->join(); + delete(instance_gpg); + instance_gpg = NULL; + } +} + +AuthGPG *AuthGPG::getAuthGPG() +{ + return instance_gpg; +} + +/* Turn a set of parameters into a string */ +#if 0 +static std::string setKeyPairParams(bool useRsa, unsigned int blen, + std::string name, std::string comment, std::string email); +#endif +static std::string setKeyPairParams(bool useRsa, unsigned int blen, + std::string name, std::string comment, std::string email, + std::string inPassphrase); + +#ifdef UNUSED_CODE +static gpgme_key_t getKey(gpgme_ctx_t, std::string, std::string, std::string); +#endif + +static gpg_error_t keySignCallback(void *, gpgme_status_code_t, \ + const char *, int); + +static gpg_error_t trustCallback(void *, gpgme_status_code_t, \ + const char *, int); + +static std::string ProcessPGPmeError(gpgme_error_t ERR); + +/* Function to sign X509_REQ via GPGme. + */ + +gpgcert::gpgcert() + :key(NULL) +{ + return; +} + +gpgcert::~gpgcert() +{ + if (key) + { + gpgme_key_unref(key); + } +} + +#define GPG_DEBUG2 +gpg_error_t pgp_pwd_callback(void *hook, const char *uid_hint, const char *passphrase_info, int prev_was_bad, int fd) +{ +#ifdef GPG_DEBUG2 + fprintf(stderr, "pgp_pwd_callback() called.\n"); +#endif + std::string text = rsicontrol->getNotify().askForPassword(uid_hint,prev_was_bad); + +#ifdef GPG_DEBUG2 + std::cerr << "pgp_pwd_callback() got GPG passwd from gui." << std::endl; +#endif + + if((void*)fd != NULL) + { +#ifndef WINDOWS_SYS + write(fd, text.c_str(), text.size()); + write(fd, "\n", 1); /* needs a new line? */ +#else + DWORD written = 0; + HANDLE winFd = (HANDLE) fd; + WriteFile(winFd, text.c_str(), text.size(), &written, NULL); + WriteFile(winFd, "\n", 1, &written, NULL); +#endif + } + +#ifdef GPG_DEBUG2 + fprintf(stderr, "pgp_pwd_callback() password setted\n"); +#endif + + return 0; +} + +AuthGPGimpl::AuthGPGimpl() + :p3Config(CONFIG_TYPE_AUTHGPG),gpgmeInit(false),gpgmeKeySelected(false) +{ + { + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + + CTX = NULL; + + setlocale(LC_ALL, ""); + gpgme_check_version(NULL); + gpgme_set_locale(NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); + + #ifdef LC_MESSAGES + gpgme_set_locale(NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); + #endif + + #ifndef WINDOWS_SYS + /* setup the engine (gpg2) */ + // if (GPG_ERR_NO_ERROR != gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, "/usr/bin/gpg2", NULL)) + // { + // std::cerr << "Error creating Setting engine" << std::endl; + // return; + // } + #endif + + if (GPG_ERR_NO_ERROR != gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP)) + { + std::cerr << "Error check engine version" << std::endl; + return; + } + + if (GPG_ERR_NO_ERROR != gpgme_get_engine_info(&INFO)) + { + std::cerr << "Error getting engine info" << std::endl; + while (INFO && INFO->protocol != GPGME_PROTOCOL_OpenPGP) { + INFO = INFO->next; + } + if (!INFO) { + fprintf (stderr, "GPGME compiled without support for protocol %s", + gpgme_get_protocol_name (INFO->protocol)); + } else if (INFO->file_name && !INFO->version) { + fprintf (stderr, "Engine %s not installed properly", + INFO->file_name); + } else if (INFO->file_name && INFO->version && INFO->req_version) { + fprintf (stderr, "Engine %s version %s installed, " + "but at least version %s required", INFO->file_name, + INFO->version, INFO->req_version); + } else { + fprintf (stderr, "Unknown problem with engine for protocol %s", + gpgme_get_protocol_name (INFO->protocol)); + } + return; + } + + /* Create New Contexts */ + if (GPG_ERR_NO_ERROR != gpgme_new(&CTX)) + { + std::cerr << "Error creating GPGME Context" << std::endl; + return; + } + + gpgme_set_passphrase_cb(CTX, pgp_pwd_callback, (void *) NULL); + } +} + +/* Initialize */ +bool AuthGPGimpl::InitAuth () +{ + std::string HomeDir; + + if (!CTX) { + std::cerr << "Error with gpg initialization. Is gpg missing ?" << std::endl; + return false; + } + +#ifdef WINDOWS_SYS + if (RsInit::isPortable ()) { + // set home dir of gpg to configdir\gnupg + HomeDir = RsInit::RsConfigDirectory() + "/" + "gnupg"; + + if (!RsDirUtil::checkCreateDirectory(HomeDir)) { + std::cerr << "Error creating gnupg directory" << std::endl; + return false; + } + } +#endif + + /* setup protocol and homedir */ + if (GPG_ERR_NO_ERROR != gpgme_ctx_set_engine_info(CTX, GPGME_PROTOCOL_OpenPGP, NULL, HomeDir.empty () ? NULL : HomeDir.c_str ())) + { + std::cerr << "Error creating Setting Protocol" << std::endl; + return false; + } + + gpgmeInit = true; + + storeAllKeys(); + #ifdef GPG_DEBUG + printAllKeys_locked(); + #endif + //updateTrustAllKeys_locked(); + + /* start thread */ + start(); + + return true; +} + +/* This function is called when retroshare is first started + * to get the list of available GPG certificates. + * This function should only return certs for which + * the private(secret) keys are available. + * + * returns false if GnuPG is not available. + */ +bool AuthGPGimpl::availableGPGCertificatesWithPrivateKeys(std::list &ids) +{ + int i = 0; + gpgme_key_t KEY = NULL; + gpg_error_t ERR; + + { + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + + if (!gpgmeInit) + { + return false; + } + } /******* UNLOCKED ******/ + + /* XXX should check that CTX is valid */ + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + + /* Initiates a key listing */ + if (GPG_ERR_NO_ERROR != gpgme_op_keylist_start (CTX, "", 1)) + { + std::cerr << "Error iterating through KeyList" << std::endl; + return false; + + } + + /* Loop until end of key */ + for(i = 0;(GPG_ERR_NO_ERROR == (ERR = gpgme_op_keylist_next (CTX, &KEY))); i++) + { + if (KEY->subkeys) + { + ids.push_back(KEY->subkeys->keyid); +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::availablePGPCertificates() Added: " << KEY->subkeys->keyid << std::endl; +#endif + } + else + { +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::availablePGPCertificates() Missing subkey" << std::endl; +#endif + } + } + + if (GPG_ERR_NO_ERROR != gpgme_op_keylist_end(CTX)) + { + std::cerr << "Error ending KeyList" << std::endl; + return false; + } + + std::cerr << "AuthGPGimpl::availablePGPCertificates() Secret Key Count: " << i << std::endl; + + /* return false if there are no private keys */ + return (i > 0); +} + +/* You can initialise Retroshare with + * (a) load existing certificate. + * (b) a new certificate. + * + * This function must be called successfully (return == 1) + * before anything else can be done. (except above fn). + */ +int AuthGPGimpl::GPGInit(const std::string &ownId) +{ + + std::cerr << "AuthGPGimpl::GPGInit() called with own gpg id : " << ownId << std::endl; + + { + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + + if (!gpgmeInit) { + return 0; + } + + mOwnGpgId = ownId; + } + + storeAllKeys(); + + int lvl = 0; + + { + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + if (mOwnGpgCert.id != mOwnGpgId) { + std::cerr << "AuthGPGimpl::GPGInit() failed to find your id." << std::endl; + return 0; + } + + gpgmeKeySelected = true; + + lvl = mOwnGpgCert.validLvl; + } + + //force the validity of the private key. When set to unknown, it caused signature and text encryptions bugs + privateTrustCertificate(mOwnGpgId, 5); + + //printAllKeys_locked(); + + std::cerr << "AuthGPGimpl::GPGInit finished." << std::endl; + + return 1; +} + + AuthGPGimpl::~AuthGPGimpl() +{ +} + +void AuthGPGimpl::run() +{ + int count = 0; + + while (isRunning()) + { +#ifdef WIN32 + Sleep(100); +#else + usleep(100000); +#endif + + /* every 100 milliseconds */ + processServices(); + + /* every minute */ + if (++count >= 600) { + storeAllKeys_tick(); + count = 0; + } + } +} + +void AuthGPGimpl::processServices() +{ + AuthGPGOperation *operation = NULL; + AuthGPGService *service = NULL; + + { + RsStackMutex stack(gpgMtxService); /******* LOCKED ******/ + + std::list::iterator serviceIt; + for (serviceIt = services.begin(); serviceIt != services.end(); serviceIt++) { + operation = (*serviceIt)->getGPGOperation(); + if (operation) { + service = *serviceIt; + break; + } + } + } /******* UNLOCKED ******/ + + if (operation == NULL) { + /* nothing to do */ + return; + } + + if (service == NULL) { + /* huh ? */ + delete operation; + return; + } + + AuthGPGOperationLoadOrSave *loadOrSave = dynamic_cast(operation); + if (loadOrSave) { + if (loadOrSave->m_load) { + /* process load operation */ + +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::processServices() Process load operation" << std::endl; +#endif + + /* load the certificate */ + std::string error_string ; + LoadCertificateFromString(loadOrSave->m_certGpg, loadOrSave->m_certGpgId,error_string); + } else { + /* process save operation */ + +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::processServices() Process save operation" << std::endl; +#endif + + /* save the certificate to string */ + loadOrSave->m_certGpg = SaveCertificateToString(loadOrSave->m_certGpgId); + } + + service->setGPGOperation(loadOrSave); + } else { +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::processServices() Unknown operation" << std::endl; +#endif + } + + delete operation; +} + +bool AuthGPGimpl::storeAllKeys_tick() { +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::storeAllKeys_tick() called." << std::endl; +#endif + time_t timeSinceStore = 0; + { + RsStackMutex stack(gpgMtxData); + timeSinceStore = time(NULL) - mStoreKeyTime; + } + + if (timeSinceStore > STORE_KEY_TIMEOUT) + { + storeAllKeys(); + } + return true ; +} + +// store all keys in map mKeyList to avoid callin gpgme exe repeatedly +bool AuthGPGimpl::storeAllKeys() +{ +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::storeAllKeys()" << std::endl; +#endif + + std::string ownGpgId; + + /* store member variables locally */ + { + RsStackMutex stack(gpgMtxData); + + if (!gpgmeInit) + { + std::cerr << "AuthGPGimpl::storeAllKeys() Error since GPG is not initialised" << std::endl; + return false; + } + + mStoreKeyTime = time(NULL); + ownGpgId = mOwnGpgId; + } + + /* read keys from gpg to local list */ + std::list keyList; + + { +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::storeAllKeys() clearing existing ones" << std::endl; +#endif + + gpg_error_t ERR; + + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + + /* enable SIG mode */ + gpgme_keylist_mode_t origmode = gpgme_get_keylist_mode(CTX); + gpgme_keylist_mode_t mode = origmode | GPGME_KEYLIST_MODE_SIGS; + + gpgme_set_keylist_mode(CTX, mode); + + /* store keys */ + gpgme_key_t KEY = NULL; + + /* Initiates a key listing 0 = All Keys */ + if (GPG_ERR_NO_ERROR != gpgme_op_keylist_start (CTX, "", 0)) + { + std::cerr << "AuthGPGimpl::storeAllKeys() Error iterating through KeyList" << std::endl; + // if (rsicontrol != NULL) { + // rsicontrol->getNotify().notifyErrorMsg(0,0,"Error reading gpg keyring, cannot acess key list."); + // } + gpgme_set_keylist_mode(CTX, origmode); + return false; + } + + /* Loop until end of key */ + ERR = gpgme_op_keylist_next (CTX, &KEY); + if (GPG_ERR_NO_ERROR != ERR) { + std::cerr << "AuthGPGimpl::storeAllKeys() didn't find any gpg key in the keyring" << std::endl; + // if (rsicontrol != NULL) { + // rsicontrol->getNotify().notifyErrorMsg(0,0,"Error reading gpg keyring, cannot find any key in the list."); + // } + gpgme_set_keylist_mode(CTX, origmode); + return false; + } + + for(int i = 0;GPG_ERR_NO_ERROR == ERR; i++) + { + /* store in pqiAuthDetails */ + gpgcert nu; + + /* NB subkeys is a linked list and can contain multiple keys. + * first key is primary. + */ + + if ((!KEY->subkeys) || (!KEY->uids)) + { + std::cerr << "AuthGPGimpl::storeAllKeys() Invalid Key in List... skipping" << std::endl; + continue; + } + + /* In general MainSubKey is used to sign all others! + * Don't really need to worry about other ids either. + */ + gpgme_subkey_t mainsubkey = KEY->subkeys; + nu.id = mainsubkey->keyid; + nu.fpr = mainsubkey->fpr; + +#ifdef GPG_DEBUG + std::cerr << "MAIN KEYID: " << nu.id << " FPR: " << nu.fpr << std::endl; + + gpgme_subkey_t subkeylist = KEY->subkeys; + while(subkeylist != NULL) + { + std::cerr << "\tKEYID: " << subkeylist->keyid << " FPR: " << subkeylist->fpr << std::endl; + + subkeylist = subkeylist->next; + } +#endif + + + /* NB uids is a linked list and can contain multiple ids. + * first id is primary. + */ + gpgme_user_id_t mainuid = KEY->uids; + nu.name = mainuid->name; + nu.email = mainuid->email; + gpgme_key_sig_t mainsiglist = mainuid->signatures; + + nu.ownsign = false; + while(mainsiglist != NULL) + { + if (mainsiglist->status == GPG_ERR_NO_ERROR) + { + /* add as a signature ... even if the + * we haven't go the peer yet. + * (might be yet to come). + */ + std::string keyid = mainsiglist->keyid; + if (nu.signers.end() == std::find( + nu.signers.begin(), + nu.signers.end(),keyid)) + { + nu.signers.push_back(keyid); + } + if (keyid == ownGpgId) { + nu.ownsign = true; + } + } + mainsiglist = mainsiglist->next; + } + +#ifdef GPG_DEBUG + gpgme_user_id_t uidlist = KEY->uids; + while(uidlist != NULL) + { + std::cerr << "\tUID: " << uidlist->uid; + std::cerr << " NAME: " << uidlist->name; + std::cerr << " EMAIL: " << uidlist->email; + std::cerr << " VALIDITY: " << uidlist->validity; + std::cerr << std::endl; + gpgme_key_sig_t usiglist = uidlist->signatures; + while(usiglist != NULL) + { + std::cerr << "\t\tSIG KEYID: " << usiglist->keyid; + std::cerr << " UID: " << usiglist->uid; + std::cerr << " NAME: " << usiglist->name; + std::cerr << " EMAIL: " << usiglist->email; + std::cerr << " VALIDITY: " << (usiglist->status == GPG_ERR_NO_ERROR); + std::cerr << std::endl; + + usiglist = usiglist->next; + } + + uidlist = uidlist->next; + } +#endif + + /* signatures are attached to uids... but only supplied + * if GPGME_KEYLIST_MODE_SIGS is on. + * signature notation supplied is GPGME_KEYLIST_MODE_SIG_NOTATION is on + */ + nu.trustLvl = KEY->owner_trust; + nu.validLvl = mainuid->validity; + + /* grab a reference, so the key remains */ + gpgme_key_ref(KEY); + nu.key = KEY; + + /* store in map */ + keyList.push_back(nu); +#ifdef GPG_DEBUG + std::cerr << "nu.name" << nu.name << std::endl; + std::cerr << "nu.trustLvl" << nu.trustLvl << std::endl; + std::cerr << "nu.accept_connection" << nu.accept_connection << std::endl; +#endif + + ERR = gpgme_op_keylist_next (CTX, &KEY); + } + + if (GPG_ERR_NO_ERROR != gpgme_op_keylist_end(CTX)) + { + std::cerr << "Error ending KeyList" << std::endl; + gpgme_set_keylist_mode(CTX, origmode); + return false; + } + + gpgme_set_keylist_mode(CTX, origmode); + } + + /* process read gpg keys and store it in member */ + std::list gpg_change_trust_list; + + { + RsStackMutex stack(gpgMtxData); + + //let's start a new list + mKeyList.clear(); + + for (std::list::iterator it = keyList.begin(); it != keyList.end(); it++) { + gpgcert &nu = *it; + + std::map::iterator itAccept; + if (mAcceptToConnectMap.end() != (itAccept = mAcceptToConnectMap.find(nu.id))) { + nu.accept_connection = itAccept->second; + } else { + nu.accept_connection = false; + mAcceptToConnectMap[nu.id] = false; + } + + if (nu.trustLvl < 2 && nu.accept_connection) { + //add it to the list of key that we will force the trust to 2 + gpg_change_trust_list.push_back(nu.id); + } + + /* grab a reference, so the key remains */ + gpgme_key_ref(nu.key); + + mKeyList[nu.id] = nu; + + //store own key + if (nu.id == mOwnGpgId) { + /* grab a reference, so the key remains */ + gpgme_key_ref(nu.key); + + gpgme_key_unref(mOwnGpgCert.key); + mOwnGpgCert = nu; + } + } + } + + std::list::iterator it; + for(it = gpg_change_trust_list.begin(); it != gpg_change_trust_list.end(); it++) + { + privateTrustCertificate(*it, 3); + } + + return true; + +} + +// update trust on all available keys. Not used anymore +//bool AuthGPGimpl::updateTrustAllKeys_locked() +//{ +// gpg_error_t ERR; +// if (!gpgmeInit) +// { +// std::cerr << "Error since GPG is not initialised" << std::endl; +// return false; +// } +// +// +// /* have to do this the hard way! */ +// std::map::iterator it; +// +// for(it = mKeyList.begin(); it != mKeyList.end(); it++) +// { +// /* check for trust items associated with key */ +// std::string peerid = it->second.email; +//#ifdef GPG_DEBUG +// std::cerr << "Searching GPGme for TrustInfo on: " << peerid << std::endl; +//#endif +// +// /* Initiates a key listing. NB: maxlevel is ignored!*/ +// if (GPG_ERR_NO_ERROR != (ERR = gpgme_op_trustlist_start (CTX, peerid.c_str(), 0))) +// { +// std::cerr << "Error Starting Trust List" << std::endl; +// ProcessPGPmeError(ERR); +// continue; +// } +// +// +// /* Loop until end of key */ +//#ifdef GPG_DEBUG +// gpgme_trust_item_t ti = NULL; +// +// for(int i = 0;(GPG_ERR_NO_ERROR == (ERR = gpgme_op_trustlist_next (CTX, &ti))); i++) +// { +// std::string keyid = ti->keyid; +// int type = ti->type; +// int level = ti->level; +// +// /* identify the peers, and add trust level */ +// std::cerr << "GPGme Trust Item for: " << keyid; +// std::cerr << std::endl; +// +// std::cerr << "\t Type: " << type; +// std::cerr << " Level: " << level; +// std::cerr << std::endl; +// +// std::cerr << "\t Owner Trust: " << ti->owner_trust; +// std::cerr << " Validity: " << ti->validity; +// std::cerr << " Name: " << ti->name; +// std::cerr << std::endl; +// } +// std::cerr << "End of TrustList Iteration." << std::endl; +//#endif +// ProcessPGPmeError(ERR); +// +// if (GPG_ERR_NO_ERROR != gpgme_op_trustlist_end(CTX)) +// { +// std::cerr << "Error ending TrustList" << std::endl; +// +// ProcessPGPmeError(ERR); +// } +// } +// +// return true; +// +//} + +bool AuthGPGimpl::printAllKeys_locked() +{ + certmap::const_iterator it; + for(it = mKeyList.begin(); it != mKeyList.end(); it++) + { + std::cerr << "PGP Key: " << it->second.id << std::endl; + + std::cerr << "\tName: " << it->second.name << std::endl; + std::cerr << "\tEmail: " << it->second.email << std::endl; + + std::cerr << "\townsign: " << it->second.ownsign << std::endl; + std::cerr << "\ttrustLvl: " << it->second.trustLvl << std::endl; + std::cerr << "\tvalidLvl: " << it->second.validLvl << std::endl; + std::cerr << "\tEmail: " << it->second.email << std::endl; + + std::list::const_iterator sit; + for(sit = it->second.signers.begin(); + sit != it->second.signers.end(); sit++) + { + std::cerr << "\t\tSigner ID:" << *sit; + + /* do a naughty second search.. should be ok + * as we aren't modifying list. + */ + certmap::const_iterator kit = mKeyList.find(*sit); + if (kit != mKeyList.end()) + { + std::cerr << " Name:" << kit->second.name << std::endl; + } + } + } + return true; +} + +bool AuthGPGimpl::printOwnKeys_locked() +{ + certmap::iterator it; + for(it = mKeyList.begin(); it != mKeyList.end(); it++) + { + if (it->second.ownsign) + { + std::cerr << "Own PGP Key: " << it->second.id << std::endl; + + std::cerr << "\tName: " << it->second.name << std::endl; + std::cerr << "\tEmail: " << it->second.email << std::endl; + } + } + return true; +} + +bool AuthGPGimpl::printKeys() +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + printAllKeys_locked(); + return printOwnKeys_locked(); +} + +std::string ProcessPGPmeError(gpgme_error_t ERR) +{ + gpgme_err_code_t code = gpgme_err_code(ERR); + gpgme_err_source_t src = gpgme_err_source(ERR); + + std::ostringstream ss ; + + if(code > 0) + { + ss << "GPGme ERROR: Code: " << code << " Source: " << src << std::endl; + ss << "GPGme ERROR: " << gpgme_strerror(ERR) << std::endl; + } + else + return std::string("Unknown error") ; + + return ss.str() ; +} + +void print_pgpme_verify_summary(unsigned int summary) +{ + std::cerr << "\tFLAGS:"; + if (summary & GPGME_SIGSUM_VALID) + std::cerr << " VALID "; + if (summary & GPGME_SIGSUM_GREEN) + std::cerr << " GREEN "; + if (summary & GPGME_SIGSUM_RED) + std::cerr << " RED "; + if (summary & GPGME_SIGSUM_KEY_REVOKED) + std::cerr << " KEY_REVOKED "; + if (summary & GPGME_SIGSUM_KEY_EXPIRED) + std::cerr << " KEY_EXPIRED "; + if (summary & GPGME_SIGSUM_SIG_EXPIRED) + std::cerr << " SIG_EXPIRED "; + if (summary & GPGME_SIGSUM_KEY_MISSING) + std::cerr << " KEY_MISSING "; + if (summary & GPGME_SIGSUM_CRL_MISSING) + std::cerr << " CRL_MISSING "; + if (summary & GPGME_SIGSUM_CRL_TOO_OLD) + std::cerr << " CRL_TOO_OLD "; + if (summary & GPGME_SIGSUM_BAD_POLICY) + std::cerr << " BAD_POLICY "; + if (summary & GPGME_SIGSUM_SYS_ERROR) + std::cerr << " SYS_ERROR "; + std::cerr << std::endl; +} + + +bool AuthGPGimpl::DoOwnSignature(const void *data, unsigned int datalen, void *buf_sigout, unsigned int *outl) +{ + gpgcert ownGpgCert; + { + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + + /* grab a reference, so the key remains */ + gpgme_key_ref(mOwnGpgCert.key); + + ownGpgCert = mOwnGpgCert; + } /******* UNLOCKED ******/ + + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + /* setup signers */ + gpgme_signers_clear(CTX); + if (GPG_ERR_NO_ERROR != gpgme_signers_add(CTX, ownGpgCert.key)) + { + std::cerr << "AuthGPGimpl::DoOwnSignature() Error Adding Signer" << std::endl; + } + + gpgme_data_t gpgmeData; + gpgme_data_t gpgmeSig; + if (GPG_ERR_NO_ERROR != gpgme_data_new_from_mem(&gpgmeData, (const char *) data, datalen, 1)) + { + std::cerr << "Error create Data" << std::endl; + } + + if (GPG_ERR_NO_ERROR != gpgme_data_new(&gpgmeSig)) + { + std::cerr << "Error create Sig" << std::endl; + } + + cleanupZombies(2); // cleanup zombies under OSX. (Called before gpgme operation) + + /* move string data to gpgmeData */ + gpgme_set_armor (CTX, 0); + + gpgme_sig_mode_t mode = GPGME_SIG_MODE_DETACH; + gpg_error_t ERR; + if (GPG_ERR_NO_ERROR != (ERR = gpgme_op_sign(CTX,gpgmeData, gpgmeSig, mode))) + { + ProcessPGPmeError(ERR); + std::cerr << "AuthGPGimpl::Sign FAILED ERR: " << ERR << std::endl; + gpgme_data_release(gpgmeSig); + gpgme_data_release(gpgmeData); + gpgme_signers_clear(CTX); + return false; + } + + gpgme_sign_result_t res = gpgme_op_sign_result(CTX); + + if (res) + { +#ifdef GPG_DEBUG + fprintf(stderr, "Sign Got Result\n"); +#endif + } + else + { + fprintf(stderr, "Sign Failed to get Result\n"); + } + +#ifdef GPG_DEBUG + gpgme_invalid_key_t ik = res->invalid_signers; + gpgme_new_signature_t sg = res->signatures; + + while(ik != NULL) + { + fprintf(stderr, "AuthGPGimpl::Sign, Invalid by: %s\n", ik->fpr); + ik = ik->next; + } + + while(sg != NULL) + { + fprintf(stderr, "AuthGPGimpl::Signed by: %s\n", sg->fpr); + sg = sg->next; + } +#endif + + /* now extract the data from gpgmeSig */ + size_t len = 0; +// gpgme_data_write (gpgmeSig, "", 1); // to be able to convert it into a string + char *export_sig = gpgme_data_release_and_get_mem(gpgmeSig, &len); +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::Signature len: " << len << std::endl; +#endif + + if (len < *outl) // -1 because we added a 0 at the end. + { + std::cerr << "Length is smaller. Reducing to " << len << std::endl; + *outl = len; + } + memmove(buf_sigout, export_sig, *outl); + gpgme_free(export_sig); + gpgme_data_release (gpgmeData); + gpgme_signers_clear(CTX); + + /* extract id(s)! */ + return true; +} + + +/* import to GnuPG and other Certificates */ +bool AuthGPGimpl::VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const std::string &withfingerprint) +{ + gpgme_data_t gpgmeSig; + gpgme_data_t gpgmeData; + +#ifdef GPG_DEBUG + std::cerr << "VerifySignature: datalen: " << datalen << " siglen: " << siglen << std::endl; +#endif + + if (!active()) + { + return false ; + } + + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + +// if(siglen==73) +// { +// //std::cerr << "Reducing to 72 to overcome an old bug." << std::endl ; +// siglen=72 ; +// } + + if (GPG_ERR_NO_ERROR != gpgme_data_new_from_mem(&gpgmeData, (const char *) data, datalen, 1)) + { + std::cerr << "Error create Data" << std::endl; + } + + if (siglen != 0 && GPG_ERR_NO_ERROR != gpgme_data_new_from_mem(&gpgmeSig, (const char *) sig, siglen, 1)) + { + std::cerr << "Error create Sig" << std::endl; + } + + cleanupZombies(2); // cleanup zombies under OSX. (Called before gpgme operation) + + gpgme_set_armor (CTX, 0); + + gpgme_error_t ERR; + if (GPG_ERR_NO_ERROR != (ERR = gpgme_op_verify(CTX,gpgmeSig, gpgmeData, NULL))) + { + ProcessPGPmeError(ERR); + std::cerr << "AuthGPGimpl::Verify FAILED" << std::endl; + } + + gpgme_verify_result_t res = gpgme_op_verify_result(CTX); + + if (res) + { +#ifdef GPG_DEBUG + fprintf(stderr, "VerifySignature Got Result\n"); +#endif + } + else + { +#ifdef GPG_DEBUG + fprintf(stderr, "VerifySignature Failed to get Result\n"); +#endif + gpgme_data_release(gpgmeData); + gpgme_data_release(gpgmeSig); + return false ; + } + + gpgme_signature_t sg = res->signatures; + bool valid = false; + + while(sg != NULL) + { +#ifdef GPG_DEBUG + fprintf(stderr, "AuthGPGimpl::Verify Sig by: %s, status: %d\n", sg->fpr, sg->status); + print_pgpme_verify_summary(sg->summary); +#endif + + if (sg->status == GPG_ERR_NO_ERROR) + { +#ifdef GPG_DEBUG + fprintf(stderr, "AuthGPGimpl::VerifySignature() OK\n"); +#endif + if (withfingerprint.empty() == false && withfingerprint == sg->fpr) { +#ifdef GPG_DEBUG + fprintf(stderr, "AuthGPGimpl::VerifySignature() for the fingerprint key : "); + std::cerr << withfingerprint; + fprintf(stderr, "\n"); +#endif + valid = true; + break; + } + } + + sg = sg->next; + } + + gpgme_data_release (gpgmeData); + gpgme_data_release (gpgmeSig); + + /* extract id(s)! */ + if (!valid) + { + fprintf(stderr, "AuthGPGimpl::VerifySignature() FAILED\n"); + } + + return valid; +} + + + + +bool AuthGPGimpl::active() +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + + return ((gpgmeInit) && (gpgmeKeySelected)); +} + +bool AuthGPGimpl::GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString) { + + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + + gpgme_key_t newKey; + gpgme_genkey_result_t result; + gpg_error_t ERR; + + cleanupZombies(2); // cleanup zombies under OSX. (Called before gpgme operation) + + if(GPG_ERR_NO_ERROR != (ERR = gpgme_op_genkey(CTX, setKeyPairParams(true, 2048, name, "generated by Retroshare", email, \ + passwd).c_str(), NULL, NULL))) { + ProcessPGPmeError(ERR); + std::cerr << "Error generating the key" << std::endl; + return 0; + } + + if((result = gpgme_op_genkey_result(CTX)) == NULL) + return 0; + + + if(GPG_ERR_NO_ERROR != (ERR = gpgme_get_key(CTX, result->fpr, &newKey, 1))) { + std::cerr << "Error reading own key" << std::endl; + return 0; + } + pgpId = newKey->subkeys->keyid; + + return true; +} + +bool AuthGPGimpl::CloseAuth() +{ + return true; +} + +/**** These Two are common */ +std::string AuthGPGimpl::getGPGName(const std::string &id) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + + certmap::iterator it; + if (mKeyList.end() != (it = mKeyList.find(id))) + return it->second.name; + + return std::string(); +} + +/**** These Two are common */ +std::string AuthGPGimpl::getGPGEmail(const std::string &id) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + + certmap::iterator it; + if (mKeyList.end() != (it = mKeyList.find(id))) + return it->second.email; + + return std::string(); +} + +/**** GPG versions ***/ + +std::string AuthGPGimpl::getGPGOwnId() +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + return mOwnGpgId; +} + +std::string AuthGPGimpl::getGPGOwnName() +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + return mOwnGpgCert.name; +} + +bool AuthGPGimpl::getGPGAllList(std::list &ids) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + + /* add an id for each pgp certificate */ + certmap::iterator it; + for(it = mKeyList.begin(); it != mKeyList.end(); it++) + { + ids.push_back(it->first); + } + return true; +} + +bool AuthGPGimpl::getGPGDetails(const std::string &id, RsPeerDetails &d) +{ +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::getPGPDetails() called for : " << id << std::endl; +#endif + + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + + /* add an id for each pgp certificate */ + certmap::iterator it; + if (mKeyList.end() != (it = mKeyList.find(id))) + { + gpgcert &cert = it->second; + + d.id = cert.id; //keep, it but can be bug gen + d.gpg_id = cert.id; + d.name = cert.name; + d.email = cert.email; + d.trustLvl = cert.trustLvl; + d.validLvl = cert.validLvl; + d.ownsign = cert.ownsign; + d.gpgSigners = cert.signers; + d.fpr = cert.fpr; + + d.accept_connection = cert.accept_connection; + + //did the peer signed me ? + d.hasSignedMe = false; + std::list::iterator signersIt; + for(signersIt = mOwnGpgCert.signers.begin(); signersIt != mOwnGpgCert.signers.end() ; ++signersIt) + if (*signersIt == d.id) + { + d.hasSignedMe = true; + break; + } + +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::getPGPDetails() Name : " << cert.name << std::endl; +#endif + return true; + } + return false; +} + +bool AuthGPGimpl::decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN) { + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + gpgme_set_armor (CTX, 1); + gpg_error_t ERR; + + cleanupZombies(2); // cleanup zombies under OSX. (Called before gpgme operation) + + if (GPG_ERR_NO_ERROR != (ERR = gpgme_op_decrypt (CTX, CIPHER, PLAIN))) + { + ProcessPGPmeError(ERR); + std::cerr << "AuthGPGimpl::decryptText() Error decrypting text." << std::endl; + return false; + } + + return true; +} + +bool AuthGPGimpl::encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER) { + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + gpgme_encrypt_flags_t* flags = new gpgme_encrypt_flags_t(); + gpgme_key_t keys[2] = {mOwnGpgCert.key, NULL}; + gpgme_set_armor (CTX, 1); + gpg_error_t ERR; + + cleanupZombies(2); // cleanup zombies under OSX. (Called before gpgme operation) + + + if (GPG_ERR_NO_ERROR != (ERR = gpgme_op_encrypt(CTX, keys, *flags, PLAIN, CIPHER))) + { + ProcessPGPmeError(ERR); + std::cerr << "AuthGPGimpl::encryptText() Error encrypting text." << std::endl; + return false; + } + + return true; +} + +bool AuthGPGimpl::getGPGValidList(std::list &ids) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + /* add an id for each pgp certificate */ + certmap::iterator it; + for(it = mKeyList.begin(); it != mKeyList.end(); it++) + { + if (it->second.validLvl >= GPGME_VALIDITY_MARGINAL) { + ids.push_back(it->first); + } + } + return true; +} + +bool AuthGPGimpl::getGPGAcceptedList(std::list &ids) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + certmap::iterator it; + for(it = mKeyList.begin(); it != mKeyList.end(); it++) + { + if (it->second.accept_connection) + { + ids.push_back(it->first); + } + } + return true; +} + +bool AuthGPGimpl::getGPGSignedList(std::list &ids) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + certmap::iterator it; + for(it = mKeyList.begin(); it != mKeyList.end(); it++) + { + if (it->second.ownsign) + { + ids.push_back(it->first); + } + } + return true; +} + +bool AuthGPGimpl::isGPGValid(const std::string &id) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + certmap::iterator it; + if (mKeyList.end() != (it = mKeyList.find(id))) { + return (it->second.validLvl >= GPGME_VALIDITY_MARGINAL); + } else { + return false; + } + +} + +bool AuthGPGimpl::isGPGId(const std::string &id) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + certmap::iterator it; + if (mKeyList.end() != (it = mKeyList.find(id))) { + return true; + } else { + return false; + } +} + + +bool AuthGPGimpl::isGPGSigned(const std::string &id) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + certmap::iterator it; + if (mKeyList.end() != (it = mKeyList.find(id))) + { + return (it->second.ownsign); + } + return false; +} + +bool AuthGPGimpl::isGPGAccepted(const std::string &id) +{ + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + certmap::iterator it; + if (mKeyList.end() != (it = mKeyList.find(id))) + { + return (it->second.accept_connection); + } + return false; +} + +/***************************************************************** + * Loading and Saving Certificates - this has to + * be able to handle both openpgp and X509 certificates. + * + * X509 are passed onto AuthSSL, OpenPGP are passed to gpgme. + * + */ + + +/* SKTAN : do not know how to use std::string id */ +std::string AuthGPGimpl::SaveCertificateToString(const std::string &id) +{ + + if (!isGPGId(id)) { + std::cerr << "AuthGPGimpl::SaveCertificateToString() unknown ID" << std::endl; + return ""; + } + + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + + std::string tmp; + const char *pattern[] = { NULL, NULL }; + pattern[0] = id.c_str(); + gpgme_data_t gpgmeData; + + if (GPG_ERR_NO_ERROR != gpgme_data_new (&gpgmeData)) + { + std::cerr << "Error create Data" << std::endl; + } + gpgme_set_armor (CTX, 1); + + if (GPG_ERR_NO_ERROR != gpgme_op_export_ext (CTX, pattern, 0, gpgmeData)) + { + std::cerr << "Error export Data" << std::endl; + } + + fflush (NULL); + //showData (gpgmeData); + + size_t len = 0; + char *export_txt = gpgme_data_release_and_get_mem(gpgmeData, &len); + + char *str = new char[len+1] ; + memcpy(str,export_txt,len) ; + str[len]=0 ; + + tmp = std::string(str); + + delete[] str ; + +#ifdef GPG_DEBUG + std::cerr << "Exported Certificate: " << std::endl << tmp << std::endl; +#endif + + gpgme_free(export_txt); + + return tmp; +} + +/* import to GnuPG and other Certificates */ +bool AuthGPGimpl::LoadCertificateFromString(const std::string &str, std::string &gpg_id,std::string& error_string) +{ + if (str == "") { + error_string = "Certificate is an empty string." ; + return false; + } + int imported = 0; + std::string fingerprint; + + { + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + //std::string cleancert = cleanUpCertificate(str); disable for p3disc message on windows system. Move the clean cert in p3peers + std::string cleancert = str; + + #ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::LoadCertificateFromString() cleancert : " << cleancert; + #endif + + gpgme_data_t gpgmeData; + gpg_error_t ERR ; + + if (GPG_ERR_NO_ERROR != (ERR = gpgme_data_new_from_mem(&gpgmeData, cleancert.c_str(), cleancert.length(), 1))) + { + error_string = ProcessPGPmeError(ERR) ; + std::cerr << "Error create Data" << std::endl; + return false; + } + + /* move string data to gpgmeData */ + + gpgme_set_armor (CTX, 1); + if (GPG_ERR_NO_ERROR != (ERR = gpgme_op_import (CTX,gpgmeData))) + { + std::cerr << "AuthGPGimpl::LoadCertificateFromString() Error Importing Certificate" << std::endl; + error_string = ProcessPGPmeError(ERR) ; + gpgme_data_release (gpgmeData); + return false ; + } + + + gpgme_import_result_t res = gpgme_op_import_result(CTX); + + if(res == NULL || res->imports == NULL) { + gpgme_data_release (gpgmeData); + error_string = "Certificate is corrupted." ; + return false ; + } + + fingerprint = std::string(res->imports->fpr); + #ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::LoadCertificateFromString() Importing considered folowing fpr : " << fingerprint << std::endl; + #endif + imported = res->imported || res->new_signatures; + + #ifdef GPG_DEBUG + fprintf(stderr, "ImportCertificate(Considered: %d Imported: %d)\n", + res->considered, res->imported); + #endif + + /* do we need to delete res??? */ + gpgme_data_release (gpgmeData); + } + + /* extract id(s)! (only if we actually imported one) */ + if (imported) { + storeAllKeys(); + } + //retrieve the id of the key + certmap::iterator it; + gpg_id = "" ; + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + for(it = mKeyList.begin(); it != mKeyList.end(); it++) + { + if (it->second.fpr == fingerprint) + { + gpg_id = it->second.id; + break; + } + } +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::LoadCertificateFromString() returning with gpg_id : " << gpg_id << std::endl; +#endif + if (gpg_id == "") { + return false; + } else { + return true; + } +} + +/***************************************************************** + * Auth...? Signing, Revoke, Trust are all done at + * the PGP level.... + * + * Only Signing of SSL is done at setup. + * Auth should be done... ?? not sure + * maybe + * + */ + + +/*************************************/ + +/* These take PGP Ids */ +bool AuthGPGimpl::setAcceptToConnectGPGCertificate(const std::string &gpg_id, bool acceptance) +{ + +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::markGPGCertificateAsFriends(" << gpg_id << ")" << std::endl; +#endif + + /* reload stuff now ... */ + storeAllKeys(); + { + RsStackMutex stack(gpgMtxData); + certmap::iterator it; + if (mKeyList.end() == (it = mKeyList.find(gpg_id))) { + return false; + } + it->second.accept_connection = acceptance; + mAcceptToConnectMap[gpg_id] = acceptance; + } + storeAllKeys(); + + IndicateConfigChanged(); + + return true; +} + +/* These take PGP Ids */ +bool AuthGPGimpl::SignCertificateLevel0(const std::string &id) +{ + +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::SignCertificat(" << id << ")" << std::endl; +#endif + + if (1 != privateSignCertificate(id)) + { + storeAllKeys(); + return false; + } + + /* reload stuff now ... */ + storeAllKeys(); + return true; +} + +bool AuthGPGimpl::RevokeCertificate(const std::string &id) +{ + //RsStackMutex stack(gpgMtx); /******* LOCKED ******/ + +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::RevokeCertificate(" << id << ") not implemented yet" << std::endl; +#endif + + return false; +} + +bool AuthGPGimpl::TrustCertificate(const std::string &id, int trustlvl) +{ +#ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::TrustCertificate(" << id << ", " << trustlvl << ")" << std::endl; +#endif + if (1 != privateTrustCertificate(id, trustlvl)) + { + storeAllKeys(); + return false; + } + + /* Keys are reloaded by privateTrustCertificate */ + return true; +} + +#if 0 +/* remove otherwise will cause bugs */ +bool AuthGPGimpl::SignData(std::string input, std::string &sign) +{ + return false; +} + +bool AuthGPGimpl::SignData(const void *data, const uint32_t len, std::string &sign) +{ + return false; +} + + +bool AuthGPGimpl::SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen) +{ + return false; +} +#endif + +bool AuthGPGimpl::SignDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) { + return DoOwnSignature(data, datalen, + sign, signlen); +} + +bool AuthGPGimpl::VerifySignBin(const void *data, uint32_t datalen, unsigned char *sign, unsigned int signlen, const std::string &withfingerprint) { + return VerifySignature(data, datalen, + sign, signlen, withfingerprint); +} + + + /* Sign/Trust stuff */ + +int AuthGPGimpl::privateSignCertificate(const std::string &id) +{ + /* The key should be in Others list and not in Peers list ?? + * Once the key is signed, it moves from Others to Peers list ??? + */ + + gpgcert signKey; + gpgcert ownKey; + + { + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + certmap::iterator it; + + if (mKeyList.end() == (it = mKeyList.find(id))) + { + return false; + } + + /* grab a reference, so the key remains */ + gpgme_key_ref(it->second.key); + + signKey = it->second; + + /* grab a reference, so the key remains */ + gpgme_key_ref(mOwnGpgCert.key); + + ownKey = mOwnGpgCert; + } /******* UNLOCKED ******/ + + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + + class SignParams sparams("0"); + class EditParams params(SIGN_START, &sparams); + gpgme_data_t out; + gpg_error_t ERR; + + if(GPG_ERR_NO_ERROR != (ERR = gpgme_data_new(&out))) { + return 0; + } + + gpgme_signers_clear(CTX); + if(GPG_ERR_NO_ERROR != (ERR = gpgme_signers_add(CTX, ownKey.key))) { + gpgme_data_release(out); + return 0; + } + + if(GPG_ERR_NO_ERROR != (ERR = gpgme_op_edit(CTX, signKey.key, keySignCallback, ¶ms, out))) { + gpgme_data_release(out); + gpgme_signers_clear(CTX); + return 0; + } + + gpgme_data_release(out); + gpgme_signers_clear(CTX); + + return 1; +} + +/* revoke the signature on Certificate */ +int AuthGPGimpl::privateRevokeCertificate(const std::string &id) +{ + //RsStackMutex stack(gpgMtx); /******* LOCKED ******/ + + return 0; +} + +int AuthGPGimpl::privateTrustCertificate(const std::string &id, int trustlvl) +{ + /* The certificate should be in Peers list ??? */ + if(!isGPGAccepted(id)) { + std::cerr << "Invalid Certificate" << std::endl; + return 0; + } + + { + gpgcert trustCert; + { + RsStackMutex stack(gpgMtxData); + + trustCert = mKeyList.find(id)->second; + } /******* UNLOCKED ******/ + + RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ + + gpgme_key_t trustKey = trustCert.key; + std::string trustString; + std::ostringstream trustStrOut; + trustStrOut << trustlvl; + class TrustParams sparams(trustStrOut.str()); + class EditParams params(TRUST_START, &sparams); + gpgme_data_t out; + gpg_error_t ERR; + + if(GPG_ERR_NO_ERROR != (ERR = gpgme_data_new(&out))) { + return 0; + } + + if(GPG_ERR_NO_ERROR != (ERR = gpgme_op_edit(CTX, trustKey, trustCallback, ¶ms, out))) { + gpgme_data_release(out); + return 0; + } + + gpgme_data_release(out); + + //the key ref has changed, we got to get rid of the old reference. + trustCert.key = NULL; + } + + storeAllKeys(); + + return 1; +} + + +/* This function to print Data */ +#if 0 +void showData(gpgme_data_t dh) +{ + #define BUF_SIZE 512 + char buf[BUF_SIZE + 1]; + int ret; + + ret = gpgme_data_seek (dh, 0, SEEK_SET); + if (ret) + { + std::cerr << "Fail data seek" << std::endl; + // fail_if_err (gpgme_err_code_from_errno (errno)); + } + + while ((ret = gpgme_data_read (dh, buf, BUF_SIZE)) > 0) + fwrite (buf, ret, 1, stdout); + + if (ret < 0) + { + std::cerr << "Fail data seek" << std::endl; + //fail_if_err (gpgme_err_code_from_errno (errno)); + } +} +#endif + +#if 0 +static std::string setKeyPairParams(bool useRsa, unsigned int blen, + std::string name, std::string comment, std::string email) +{ + std::ostringstream params; + params << ""<< std::endl; + if (useRsa) + { + params << "Key-Type: RSA"<< std::endl; + if (blen < 1024) + { +#ifdef GPG_DEBUG + std::cerr << "Weak Key... strengthing..."<< std::endl; +#endif + blen = 1024; + } + blen = ((blen / 512) * 512); /* make multiple of 512 */ + params << "Key-Length: "<< blen << std::endl; + } + else + { + params << "Key-Type: DSA"<< std::endl; + params << "Key-Length: 1024"<< std::endl; + params << "Subkey-Type: ELG-E"<< std::endl; + params << "Subkey-Length: 1024"<< std::endl; + } + params << "Name-Real: "<< name << std::endl; + params << "Name-Comment: "<< comment << std::endl; + params << "Name-Email: "<< email << std::endl; + params << "Expire-Date: 0"<< std::endl; + params << ""<< std::endl; + + return params.str(); +} +#endif + +static std::string setKeyPairParams(bool useRsa, unsigned int blen, + std::string name, std::string comment, std::string email, + std::string inPassphrase) +{ + std::ostringstream params; + params << ""<< std::endl; + if (useRsa) + { + params << "Key-Type: RSA"<< std::endl; + if (blen < 1024) + { +#ifdef GPG_DEBUG + std::cerr << "Weak Key... strengthing..."<< std::endl; +#endif + blen = 1024; + } + blen = ((blen / 512) * 512); /* make multiple of 512 */ + params << "Key-Length: "<< blen << std::endl; + } + else + { + params << "Key-Type: DSA"<< std::endl; + params << "Key-Length: 1024"<< std::endl; + params << "Subkey-Type: ELG-E"<< std::endl; + params << "Subkey-Length: 1024"<< std::endl; + } + params << "Name-Real: "<< name << std::endl; + params << "Name-Comment: "<< comment << std::endl; + params << "Name-Email: "<< email << std::endl; + params << "Expire-Date: 0"<< std::endl; + params << "Passphrase: "<< inPassphrase << std::endl; + params << ""<< std::endl; + + return params.str(); +} + + +/* Author: Shiva + * This function returns the key macthing the user parameters + * from the keyring + */ + +#ifdef UNUSED_CODE +static gpgme_key_t getKey(gpgme_ctx_t CTX, std::string name, std::string comment, std::string email) { + + gpgme_key_t key; + gpgme_user_id_t user; + + /* Initiates a key listing */ + if (GPG_ERR_NO_ERROR != gpgme_op_keylist_start (CTX, "", 0)) + { + std::cerr << "Error iterating through KeyList"; + std::cerr << std::endl; + return false; + + } + + /* Loop until end of key */ + for(int i = 0;(GPG_ERR_NO_ERROR == gpgme_op_keylist_next (CTX, &key)); i++) + { + user = key->uids; + + while(user != NULL) { + if((name.size() && name == user->name) && (comment.size() && comment == user->comment) && \ + (email.size() && email == user->email)) + { + /* grab a reference to the key */ + gpgme_op_keylist_end(CTX); + if (GPG_ERR_NO_ERROR != gpgme_op_keylist_end(CTX)) + { + std::cerr << "Error ending KeyList"; + std::cerr << std::endl; + } + gpgme_key_ref(key); + return key; + } + user = user->next; + } + } + + if (GPG_ERR_NO_ERROR != gpgme_op_keylist_end(CTX)) + { + std::cerr << "Error ending KeyList" << std::endl; + } + return NULL; +} +#endif + + +/* Callback function for key signing */ + +static gpg_error_t keySignCallback(void *opaque, gpgme_status_code_t status, \ + const char *args, int fd) { + + class EditParams *params = (class EditParams *)opaque; + class SignParams *sparams = (class SignParams *)params->oParams; + const char *result = NULL; +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback status: %d args: %s, params->state: %d\n", status, args, params->state); + + /* printf stuff out */ + if (status == GPGME_STATUS_EOF) + fprintf(stderr,"keySignCallback GPGME_STATUS_EOF\n"); + if (status == GPGME_STATUS_GOT_IT) + fprintf(stderr,"keySignCallback GPGME_STATUS_GOT_IT\n"); + if (status == GPGME_STATUS_USERID_HINT) + fprintf(stderr,"keySignCallback GPGME_STATUS_USERID_HINT\n"); + if (status == GPGME_STATUS_NEED_PASSPHRASE) + fprintf(stderr,"keySignCallback GPGME_STATUS_NEED_PASSPHRASE\n"); + if (status == GPGME_STATUS_GOOD_PASSPHRASE) + fprintf(stderr,"keySignCallback GPGME_STATUS_GOOD_PASSPHRASE\n"); + if (status == GPGME_STATUS_BAD_PASSPHRASE) + fprintf(stderr,"keySignCallback GPGME_STATUS_BAD_PASSPHRASE\n"); + if (status == GPGME_STATUS_GET_LINE) + fprintf(stderr,"keySignCallback GPGME_STATUS_GET_LINE\n"); + if (status == GPGME_STATUS_GET_BOOL) + fprintf(stderr,"keySignCallback GPGME_STATUS_GET_BOOL\n"); + if (status == GPGME_STATUS_ALREADY_SIGNED) + fprintf(stderr,"keySignCallback GPGME_STATUS_ALREADY_SIGNED\n"); + + /* printf stuff out */ + if (params->state == SIGN_START) + fprintf(stderr,"keySignCallback params->state SIGN_START\n"); + if (params->state == SIGN_COMMAND) + fprintf(stderr,"keySignCallback params->state SIGN_COMMAND\n"); + if (params->state == SIGN_UIDS) + fprintf(stderr,"keySignCallback params->state SIGN_UIDS\n"); + if (params->state == SIGN_SET_EXPIRE) + fprintf(stderr,"keySignCallback params->state SIGN_SET_EXPIRE\n"); + if (params->state == SIGN_SET_CHECK_LEVEL) + fprintf(stderr,"keySignCallback params->state SIGN_SET_CHECK_LEVEL\n"); + if (params->state == SIGN_CONFIRM) + fprintf(stderr,"keySignCallback params->state SIGN_CONFIRM\n"); + if (params->state == SIGN_QUIT) + fprintf(stderr,"keySignCallback params->state SIGN_QUIT\n"); + if (params->state == SIGN_ENTER_PASSPHRASE) + fprintf(stderr,"keySignCallback params->state SIGN_ENTER_PASSPHRASE\n"); + if (params->state == SIGN_ERROR) + fprintf(stderr,"keySignCallback params->state SIGN_ERROR"); +#endif + + + if(status == GPGME_STATUS_EOF || + status == GPGME_STATUS_GOT_IT || + status == GPGME_STATUS_USERID_HINT || + status == GPGME_STATUS_NEED_PASSPHRASE || + // status == GPGME_STATUS_GOOD_PASSPHRASE || + status == GPGME_STATUS_BAD_PASSPHRASE) { + + + fprintf(stderr,"keySignCallback Error status\n"); + ProcessPGPmeError(params->err); + + return params->err; + } + + switch (params->state) + { + case SIGN_START: +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback SIGN_START\n"); +#endif + + if (status == GPGME_STATUS_GET_LINE && + (!std::string("keyedit.prompt").compare(args))) + { + params->state = SIGN_COMMAND; + result = "sign"; + } + else + { + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case SIGN_COMMAND: +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback SIGN_COMMAND\n"); +#endif + + if (status == GPGME_STATUS_GET_BOOL && + (!std::string("keyedit.sign_all.okay").compare(args))) + { + params->state = SIGN_UIDS; + result = "Y"; + } + else if (status == GPGME_STATUS_GET_BOOL && + (!std::string("sign_uid.okay").compare(args))) + { + params->state = SIGN_ENTER_PASSPHRASE; + result = "Y"; + } + else if (status == GPGME_STATUS_GET_LINE && + (!std::string("sign_uid.expire").compare(args))) + { + params->state = SIGN_SET_EXPIRE; + result = "Y"; + } + else if (status == GPGME_STATUS_GET_LINE && + (!std::string("sign_uid.class").compare(args))) + { + params->state = SIGN_SET_CHECK_LEVEL; + result = sparams->checkLvl.c_str(); + } + else if (status == GPGME_STATUS_ALREADY_SIGNED) + { + /* The key has already been signed with this key */ + params->state = SIGN_QUIT; + result = "quit"; + } + else if (status == GPGME_STATUS_GET_LINE && + (!std::string("keyedit.prompt").compare(args))) + { + /* Failed sign: expired key */ + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_UNUSABLE_PUBKEY); + } + else + { + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case SIGN_UIDS: +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback SIGN_UIDS\n"); +#endif + + if (status == GPGME_STATUS_GET_LINE && + (!std::string("sign_uid.expire").compare(args))) + { + params->state = SIGN_SET_EXPIRE; + result = "Y"; + } + else if (status == GPGME_STATUS_GET_LINE && + (!std::string("sign_uid.class").compare(args))) + { + params->state = SIGN_SET_CHECK_LEVEL; + result = sparams->checkLvl.c_str(); + } + else if (status == GPGME_STATUS_GET_BOOL && + (!std::string("sign_uid.okay").compare(args))) + { + params->state = SIGN_ENTER_PASSPHRASE; + result = "Y"; + } + else if (status == GPGME_STATUS_GET_LINE && + (!std::string("keyedit.prompt").compare(args))) + { + /* Failed sign: expired key */ + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_UNUSABLE_PUBKEY); + } + else + { + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case SIGN_SET_EXPIRE: +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback SIGN_SET_EXPIRE\n"); +#endif + + if (status == GPGME_STATUS_GET_LINE && + (!std::string("sign_uid.class").compare(args))) + { + params->state = SIGN_SET_CHECK_LEVEL; + result = sparams->checkLvl.c_str(); + } + else + { + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case SIGN_SET_CHECK_LEVEL: +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback SIGN_SET_CHECK_LEVEL\n"); +#endif + + if (status == GPGME_STATUS_GET_BOOL && + (!std::string("sign_uid.okay").compare(args))) + { + params->state = SIGN_ENTER_PASSPHRASE; + result = "Y"; + } + else + { + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case SIGN_ENTER_PASSPHRASE: +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback SIGN_ENTER_PASSPHRASE\n"); +#endif + + if (status == GPGME_STATUS_GOOD_PASSPHRASE) + { + params->state = SIGN_CONFIRM; + } + else + { + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case SIGN_CONFIRM: +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback SIGN_CONFIRM\n"); +#endif + + if (status == GPGME_STATUS_GET_LINE && + (!std::string("keyedit.prompt").compare(args))) + { + params->state = SIGN_QUIT; + result = "quit"; + } + else + { + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case SIGN_QUIT: +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback SIGN_QUIT\n"); +#endif + + if (status == GPGME_STATUS_GET_BOOL && + (!std::string("keyedit.save.okay").compare(args))) + { + params->state = SIGN_SAVE; + result = "Y"; + } + else + { + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case SIGN_ERROR: +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback SIGN_ERROR\n"); +#endif + + if (status == GPGME_STATUS_GET_LINE && + (!std::string("keyedit.prompt").compare(args))) + { + /* Go to quit operation state */ + params->state = SIGN_QUIT; + result = "quit"; + } + else + { + params->state = SIGN_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + default: + fprintf(stderr,"keySignCallback UNKNOWN state\n"); + break; + } + + if (result) + { +#ifdef GPG_DEBUG + fprintf(stderr,"keySignCallback result:%s\n", result); +#endif +#ifndef WINDOWS_SYS + if (*result) + { + write (fd, result, strlen (result)); + write (fd, "\n", 1); + } +#else + DWORD written = 0; + HANDLE winFd = (HANDLE) fd; + if (*result) + { + WriteFile(winFd, result, strlen(result), &written, NULL); + WriteFile(winFd, "\n", 1, &written, NULL); + } +#endif + + } + + fprintf(stderr,"keySignCallback Error status\n"); + ProcessPGPmeError(params->err); + + return params->err; +} + + + +/* Callback function for assigning trust level */ + +static gpgme_error_t trustCallback(void *opaque, gpgme_status_code_t status, \ + const char *args, int fd) { + + class EditParams *params = (class EditParams *)opaque; + class TrustParams *tparams = (class TrustParams *)params->oParams; + const char *result = NULL; + + /* printf stuff out */ +#ifdef GPG_DEBUG + if (status == GPGME_STATUS_EOF) + fprintf(stderr,"keySignCallback GPGME_STATUS_EOF\n"); + if (status == GPGME_STATUS_GOT_IT) + fprintf(stderr,"keySignCallback GPGME_STATUS_GOT_IT\n"); + if (status == GPGME_STATUS_USERID_HINT) + fprintf(stderr,"keySignCallback GPGME_STATUS_USERID_HINT\n"); + if (status == GPGME_STATUS_NEED_PASSPHRASE) + fprintf(stderr,"keySignCallback GPGME_STATUS_NEED_PASSPHRASE\n"); + if (status == GPGME_STATUS_GOOD_PASSPHRASE) + fprintf(stderr,"keySignCallback GPGME_STATUS_GOOD_PASSPHRASE\n"); + if (status == GPGME_STATUS_BAD_PASSPHRASE) + fprintf(stderr,"keySignCallback GPGME_STATUS_BAD_PASSPHRASE\n"); + if (status == GPGME_STATUS_GET_LINE) + fprintf(stderr,"keySignCallback GPGME_STATUS_GET_LINE\n"); + if (status == GPGME_STATUS_GET_BOOL) + fprintf(stderr,"keySignCallback GPGME_STATUS_GET_BOOL \n"); + if (status == GPGME_STATUS_ALREADY_SIGNED) + fprintf(stderr,"keySignCallback GPGME_STATUS_ALREADY_SIGNED\n"); + + /* printf stuff out */ + if (params->state == TRUST_START) + fprintf(stderr,"keySignCallback params->state TRUST_START\n"); + if (params->state == TRUST_COMMAND) + fprintf(stderr,"keySignCallback params->state TRUST_COMMAND\n"); + if (params->state == TRUST_VALUE) + fprintf(stderr,"keySignCallback params->state TRUST_VALUE\n"); + if (params->state == TRUST_REALLY_ULTIMATE) + fprintf(stderr,"keySignCallback params->state TRUST_REALLY_ULTIMATE\n"); + if (params->state == TRUST_QUIT) + fprintf(stderr,"keySignCallback params->state TRUST_QUIT\n"); + if (params->state == TRUST_ERROR) + fprintf(stderr,"keySignCallback params->state TRUST_ERROR\n"); +#endif + + + if(status == GPGME_STATUS_EOF || + status == GPGME_STATUS_GOT_IT) { + return params->err; + } + + + switch (params->state) + { + case TRUST_START: + if (status == GPGME_STATUS_GET_LINE && + (!std::string("keyedit.prompt").compare(args))) { + params->state = TRUST_COMMAND; + result = "trust"; + } else { + params->state = TRUST_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + + case TRUST_COMMAND: + if (status == GPGME_STATUS_GET_LINE && + (!std::string("edit_ownertrust.value").compare(args))) { + params->state = TRUST_VALUE; + result = tparams->trustLvl.c_str();; + } else { + params->state = TRUST_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case TRUST_VALUE: + if (status == GPGME_STATUS_GET_LINE && + (!std::string("keyedit.prompt").compare(args))) { + params->state = TRUST_QUIT; + result = "quit"; + } + else if (status == GPGME_STATUS_GET_BOOL && + (!std::string("edit_ownertrust.set_ultimate.okay").compare(args))) { + params->state = TRUST_REALLY_ULTIMATE; + result = "Y"; + } + else { + params->state = TRUST_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case TRUST_REALLY_ULTIMATE: + if (status == GPGME_STATUS_GET_LINE && + (!std::string("keyedit.prompt").compare(args))) { + params->state = TRUST_QUIT; + result = "quit"; + } else { + params->state = TRUST_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case TRUST_QUIT: + if (status == GPGME_STATUS_GET_BOOL && + (!std::string("keyedit.save.okay").compare(args))) { + params->state = TRUST_SAVE; + result = "Y"; + } else { + params->state = TRUST_ERROR; + params->err = gpg_error (GPG_ERR_GENERAL); + } + break; + case TRUST_ERROR: + if (status == GPGME_STATUS_GET_LINE && + (!std::string("keyedit.prompt").compare(args))) { + /* Go to quit operation state */ + params->state = TRUST_QUIT; + result = "quit"; + } else { + params->state = TRUST_ERROR; + } + break; + } + + if (result) + { +#ifndef WINDOWS_SYS + if (*result) + write (fd, result, strlen (result)); + write (fd, "\n", 1); +#else + DWORD written = 0; + HANDLE winFd = (HANDLE) fd; + if (*result) + WriteFile(winFd, result, strlen (result), &written, NULL); + WriteFile(winFd, "\n", 1, &written, NULL); +#endif +#ifdef GPG_DEBUG + std::cerr << "trustCallback() result : " << result << std::endl; +#endif + } + + return params->err; +} + +// -----------------------------------------------------------------------------------// +// -------------------------------- Config functions ------------------------------ // +// -----------------------------------------------------------------------------------// +// +RsSerialiser *AuthGPGimpl::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser ; + rss->addSerialType(new RsGeneralConfigSerialiser()); + return rss ; +} + +bool AuthGPGimpl::saveList(bool& cleanup, std::list& lst) +{ + #ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::saveList() called" << std::endl ; + #endif + + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + + cleanup = true ; + + // Now save config for network digging strategies + RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; + std::map::iterator mapIt; + for (mapIt = mAcceptToConnectMap.begin(); mapIt != mAcceptToConnectMap.end(); mapIt++) { + if (mapIt->first == mOwnGpgId) { + continue; + } + RsTlvKeyValue kv; + kv.key = mapIt->first; + #ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::saveList() called (mapIt->second) : " << (mapIt->second) << std::endl ; + #endif + kv.value = (mapIt->second)?"TRUE":"FALSE" ; + vitem->tlvkvs.pairs.push_back(kv) ; + } + lst.push_back(vitem); + + return true ; +} + +bool AuthGPGimpl::loadList(std::list& load) +{ + #ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::loadList() Item Count: " << load.size() << std::endl; + #endif + + storeAllKeys(); + + RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ + /* load the list of accepted gpg keys */ + std::list::iterator it; + for(it = load.begin(); it != load.end(); it++) { + RsConfigKeyValueSet *vitem = dynamic_cast(*it); + + if(vitem) { + #ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::loadList() General Variable Config Item:" << std::endl; + vitem->print(std::cerr, 10); + std::cerr << std::endl; + #endif + + std::list::iterator kit; + for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); kit++) { + if (kit->key == mOwnGpgId) { + continue; + } + mAcceptToConnectMap[kit->key] = (kit->value == "TRUE"); + //set the gpg key + certmap::iterator it; + if (mKeyList.end() != (it = mKeyList.find(kit->key))) { + #ifdef GPG_DEBUG + std::cerr << "AuthGPGimpl::loadList() setting accept to : " << (kit->value == "TRUE"); + std::cerr << " for gpg key id : " << kit->key << std::endl; + #endif + it->second.accept_connection = (kit->value == "TRUE"); + } + } + } + delete (*it); + } + return true; +} + +bool AuthGPGimpl::addService(AuthGPGService *service) +{ + RsStackMutex stack(gpgMtxService); /********* LOCKED *********/ + + if (std::find(services.begin(), services.end(), service) != services.end()) { + /* it exists already! */ + return false; + } + + services.push_back(service); + return true; +} + + +/***************************** HACK to Cleanup OSX Zombies *****************************/ + + +#ifdef __APPLE__ +#include +#endif + +void cleanupZombies(int numkill) +{ + +#ifdef __APPLE__ + + pid_t wpid = -1; // any child. + int stat_loc = 0; + int options = WNOHANG ; + + //std::cerr << "cleanupZombies() checking for dead children"; + //std::cerr << std::endl; + + int i; + for(i = 0; i < numkill; i++) + { + pid_t childpid = waitpid(wpid, &stat_loc, options); + + if (childpid > 0) + { + std::cerr << "cleanupZombies() Found stopped child with pid: " << childpid; + std::cerr << std::endl; + } + else + { + //std::cerr << "cleanupZombies() No Zombies around!"; + //std::cerr << std::endl; + break; + } + } + + //std::cerr << "cleanupZombies() Killed " << i << " zombies"; + //std::cerr << std::endl; + +#endif + + return; +} + diff --git a/libretroshare/src/pqi/authgpg.h b/libretroshare/src/pqi/authgpg.h new file mode 100644 index 000000000..f45190a65 --- /dev/null +++ b/libretroshare/src/pqi/authgpg.h @@ -0,0 +1,543 @@ +/* + * libretroshare/src/ : gpgauthmgr.h + * + * GPG interface for RetroShare. + * + * Copyright 2008-2009 by Raghu Dev R. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + * This is *THE* auth manager. It provides the web-of-trust via + * gpgme, and authenticates the certificates that are managed + * by the sublayer AuthSSL. + * + */ + +/**** + * Here's GPG policy : + * By default, all pgpg keys imported via a RS user (make friend and accept friend action) are signed at level 0. + * All signed keys by RS are set to be trusted marginally. You can change it to full or no trust in the friend profile + * For a key to be marginaly valid, it has to be signed by one fully trusted key, or at least by 3 marginally trusted keys. + * All keys that have at least marginal validity are designed as valid in RS. They are shown in the RS gui in order to be signed. + * If there is no validity then the key is not shown. + */ + +#ifndef RS_GPG_AUTH_HEADER +#define RS_GPG_AUTH_HEADER + +#include +#include +#include +#include "util/rsthreads.h" +#include "retroshare/rspeers.h" +#include +#include +#include +#include +#include "pqi/p3cfgmgr.h" + +#define MAX_GPG_SIGNATURE_SIZE 4096 + +/*! + * gpgcert is the identifier for a person. + * It is a wrapper class for a GPGme OpenPGP certificate. + */ +class AuthGPG; + +class gpgcert +{ + public: + gpgcert(); + ~gpgcert(); + + std::string id; + std::string name; + std::string email; + + std::string fpr; /* fingerprint */ + std::list signers; + + uint32_t trustLvl; + uint32_t validLvl; + + bool ownsign; + + //This is not gpg, but RS data. A gpg peer can be accepted for connecting but not signed. + bool accept_connection; + + gpgme_key_t key; +}; + +class AuthGPGOperation +{ +public: + AuthGPGOperation(void *userdata) + { + m_userdata = userdata; + } + virtual ~AuthGPGOperation() {} + +public: + void *m_userdata; +}; + +class AuthGPGOperationLoadOrSave : public AuthGPGOperation +{ +public: + AuthGPGOperationLoadOrSave(bool load, const std::string &certGpgOrId, void *userdata) : AuthGPGOperation(userdata) + { + m_load = load; + if (m_load) { + m_certGpg = certGpgOrId; + } else { + m_certGpgId = certGpgOrId; + } + } + +public: + bool m_load; + std::string m_certGpgId; // set for save + std::string m_certGpg; // set for load +}; + +class AuthGPGService +{ +public: + AuthGPGService() {}; + ~AuthGPGService() {}; + + virtual AuthGPGOperation *getGPGOperation() = 0; + virtual void setGPGOperation(AuthGPGOperation *operation) = 0; +}; + +/*! + * The certificate map type + */ +typedef std::map certmap; + +//! provides basic gpg functionality +/*! + * + * This provides retroshare basic gpg functionality and + * key/web-of-trust management, also handle cert intialisation for retroshare + */ + +extern void AuthGPGInit(); +extern void AuthGPGExit(); + +class AuthGPG : public RsThread +{ + + public: + //AuthGPG(); + +static AuthGPG *getAuthGPG(); + + /** + * @param ids list of gpg certificate ids (note, not the actual certificates) + */ +virtual bool availableGPGCertificatesWithPrivateKeys(std::list &ids) = 0; +virtual bool printKeys() = 0; + +/*********************************************************************************/ +/************************* STAGE 1 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 1: Initialisation.... As we are switching to OpenPGP the init functions + * will be different. Just move the initialisation functions over.... + * + * As GPGMe requires external calls to the GPG executable, which could potentially + * be expensive, We'll want to cache the GPG keys in this class. + * This should be done at initialisation, and saved in a map. + * (see storage at the end of the class) + * + ****/ +virtual bool active() = 0; + + /* Initialize */ +virtual bool InitAuth () = 0; + + /* Init by generating new Own PGP Cert, or selecting existing PGP Cert */ +virtual int GPGInit(const std::string &ownId) = 0; +virtual bool CloseAuth() = 0; +virtual bool GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString) = 0; + +/*********************************************************************************/ +/************************* STAGE 3 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 3: These are some of the most commonly used functions in Retroshare. + * + * More commonly used functions. + * + * provide access to details in cache list. + * + ****/ +virtual std::string getGPGName(const std::string &pgp_id) = 0; +virtual std::string getGPGEmail(const std::string &pgp_id) = 0; + + /* PGP web of trust management */ +virtual std::string getGPGOwnId() = 0; +virtual std::string getGPGOwnName() = 0; + +//virtual std::string getGPGOwnEmail() = 0; +virtual bool getGPGDetails(const std::string &id, RsPeerDetails &d) = 0; +virtual bool getGPGAllList(std::list &ids) = 0; +virtual bool getGPGValidList(std::list &ids) = 0; +virtual bool getGPGAcceptedList(std::list &ids) = 0; +virtual bool getGPGSignedList(std::list &ids) = 0; +virtual bool isGPGValid(const std::string &id) = 0; +virtual bool isGPGSigned(const std::string &id) = 0; +virtual bool isGPGAccepted(const std::string &id) = 0; +virtual bool isGPGId(const std::string &id) = 0; + +/*********************************************************************************/ +/************************* STAGE 4 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 4: Loading and Saving Certificates. (Strings and Files) + * + ****/ +virtual bool LoadCertificateFromString(const std::string &pem, std::string &gpg_id,std::string& error_string) = 0; +virtual std::string SaveCertificateToString(const std::string &id) = 0; + +/*********************************************************************************/ +/************************* STAGE 6 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 6: Authentication, Trust and Signing. + * + * This is some of the harder functions, but they should have been + * done in gpgroot already. + * + ****/ +virtual bool setAcceptToConnectGPGCertificate(const std::string &gpg_id, bool acceptance) = 0; //don't act on the gpg key, use a seperate set +virtual bool SignCertificateLevel0(const std::string &id) = 0; +virtual bool RevokeCertificate(const std::string &id) = 0; /* Particularly hard - leave for later */ +//virtual bool TrustCertificateNone(std::string id) = 0; +//virtual bool TrustCertificateMarginally(std::string id) = 0; +//virtual bool TrustCertificateFully(std::string id) = 0; +virtual bool TrustCertificate(const std::string &id, int trustlvl) = 0; //trustlvl is 2 for none, 3 for marginal and 4 for full trust + +/*********************************************************************************/ +/************************* STAGE 7 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 7: Signing Data. + * + * There should also be Encryption Functions... (do later). + * + ****/ +//virtual bool SignData(std::string input, std::string &sign) = 0; +//virtual bool SignData(const void *data, const uint32_t len, std::string &sign) = 0; +//virtual bool SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen) = 0; +virtual bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen) = 0; +virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const std::string &withfingerprint) = 0; +virtual bool decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN) = 0; +virtual bool encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER) = 0; +//END of PGP public functions + +/* GPG service */ +virtual bool addService(AuthGPGService *service) = 0; + +}; + +/* The real implementation! */ + + +class AuthGPGimpl : public AuthGPG, public p3Config +{ + public: + + AuthGPGimpl(); + ~AuthGPGimpl(); + + /** + * @param ids list of gpg certificate ids (note, not the actual certificates) + */ +virtual bool availableGPGCertificatesWithPrivateKeys(std::list &ids); + +virtual bool printKeys(); + +/*********************************************************************************/ +/************************* STAGE 1 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 1: Initialisation.... As we are switching to OpenPGP the init functions + * will be different. Just move the initialisation functions over.... + * + * As GPGMe requires external calls to the GPG executable, which could potentially + * be expensive, We'll want to cache the GPG keys in this class. + * This should be done at initialisation, and saved in a map. + * (see storage at the end of the class) + * + ****/ +virtual bool active(); + + /* Initialize */ +virtual bool InitAuth (); + + /* Init by generating new Own PGP Cert, or selecting existing PGP Cert */ +virtual int GPGInit(const std::string &ownId); +virtual bool CloseAuth(); +virtual bool GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString); + +/*********************************************************************************/ +/************************* STAGE 3 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 3: These are some of the most commonly used functions in Retroshare. + * + * More commonly used functions. + * + * provide access to details in cache list. + * + ****/ +virtual std::string getGPGName(const std::string &pgp_id); +virtual std::string getGPGEmail(const std::string &pgp_id); + + /* PGP web of trust management */ +virtual std::string getGPGOwnId(); +virtual std::string getGPGOwnName(); + +//virtual std::string getGPGOwnEmail(); +virtual bool getGPGDetails(const std::string &id, RsPeerDetails &d); +virtual bool getGPGAllList(std::list &ids); +virtual bool getGPGValidList(std::list &ids); +virtual bool getGPGAcceptedList(std::list &ids); +virtual bool getGPGSignedList(std::list &ids); +virtual bool isGPGValid(const std::string &id); +virtual bool isGPGSigned(const std::string &id); +virtual bool isGPGAccepted(const std::string &id); +virtual bool isGPGId(const std::string &id); + +/*********************************************************************************/ +/************************* STAGE 4 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 4: Loading and Saving Certificates. (Strings and Files) + * + ****/ +virtual bool LoadCertificateFromString(const std::string &pem, std::string &gpg_id,std::string& error_string); +virtual std::string SaveCertificateToString(const std::string &id); + +/*********************************************************************************/ +/************************* STAGE 6 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 6: Authentication, Trust and Signing. + * + * This is some of the harder functions, but they should have been + * done in gpgroot already. + * + ****/ +virtual bool setAcceptToConnectGPGCertificate(const std::string &gpg_id, bool acceptance); //don't act on the gpg key, use a seperate set +virtual bool SignCertificateLevel0(const std::string &id); +virtual bool RevokeCertificate(const std::string &id); /* Particularly hard - leave for later */ + +//virtual bool TrustCertificateNone(std::string id); +//virtual bool TrustCertificateMarginally(std::string id); +//virtual bool TrustCertificateFully(std::string id); +virtual bool TrustCertificate(const std::string &id, int trustlvl); //trustlvl is 2 for none, 3 for marginal and 4 for full trust + +/*********************************************************************************/ +/************************* STAGE 7 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 7: Signing Data. + * + * There should also be Encryption Functions... (do later). + * + ****/ +//virtual bool SignData(std::string input, std::string &sign); +//virtual bool SignData(const void *data, const uint32_t len, std::string &sign); +//virtual bool SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen); +virtual bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen); +virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const std::string &withfingerprint); +virtual bool decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN); +virtual bool encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER); +//END of PGP public functions + +/* GPG service */ +virtual bool addService(AuthGPGService *service); + + protected: +/*****************************************************************/ +/*********************** p3config ******************************/ + /* Key Functions to be overloaded for Full Configuration */ + virtual RsSerialiser *setupSerialiser(); + virtual bool saveList(bool &cleanup, std::list&); + virtual bool loadList(std::list& load); +/*****************************************************************/ + + private: + + /* SKTAN */ + //void showData(gpgme_data_t dh); + //void createDummyFriends(void); //NYI + + + /* Internal functions */ + bool DoOwnSignature(const void *, unsigned int, void *, unsigned int *); + bool VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const std::string &withfingerprint); + + /* Sign/Trust stuff */ + int privateSignCertificate(const std::string &id); + int privateRevokeCertificate(const std::string &id); /* revoke the signature on Certificate */ + int privateTrustCertificate(const std::string &id, int trustlvl); + + // store all keys in map mKeyList to avoid calling gpgme exe repeatedly + bool storeAllKeys(); + bool storeAllKeys_tick(); + +// Not used anymore +// bool updateTrustAllKeys_locked(); + + /* GPG service */ + void processServices(); + + bool printAllKeys_locked(); + bool printOwnKeys_locked(); + + /* own thread */ + virtual void run(); + +private: + + static AuthGPG *instance_gpg; // pointeur vers le singleton + + RsMutex gpgMtxEngine; + /* Below is protected via the mutex */ + + gpgme_engine_info_t INFO; + gpgme_ctx_t CTX; + + RsMutex gpgMtxData; + /* Below is protected via the mutex */ + + certmap mKeyList; + time_t mStoreKeyTime; + + bool gpgmeInit; + + bool gpgmeKeySelected; + + std::string mOwnGpgId; + gpgcert mOwnGpgCert; + + std::map mAcceptToConnectMap; + + RsMutex gpgMtxService; + /* Below is protected via the mutex */ + + std::list services; +}; + +/*! + * Sign a key + **/ +typedef enum +{ + SIGN_START, + SIGN_COMMAND, + SIGN_UIDS, + SIGN_SET_EXPIRE, + SIGN_SET_CHECK_LEVEL, + SIGN_ENTER_PASSPHRASE, + SIGN_CONFIRM, + SIGN_QUIT, + SIGN_SAVE, + SIGN_ERROR +} SignState; + + +/*! + * Change the key ownertrust + **/ +typedef enum +{ + TRUST_START, + TRUST_COMMAND, + TRUST_VALUE, + TRUST_REALLY_ULTIMATE, + TRUST_QUIT, + TRUST_SAVE, + TRUST_ERROR +} TrustState; + + + +/*! + * This is the generic data object passed to the + * callback function in a gpgme_op_edit operation. + * The contents of this object are modified during + * each callback, to keep track of states, errors + * and other data. + */ +class EditParams +{ + public: + int state; + + /*! + * The return code of gpgme_op_edit() is the return value of + * the last invocation of the callback. But returning an error + * from the callback does not abort the edit operation, so we + * must remember any error. + */ + gpg_error_t err; + + /// Parameters specific to the key operation + void *oParams; + + EditParams(int state, void *oParams) { + this->state = state; + this->err = gpgme_error(GPG_ERR_NO_ERROR); + this->oParams = oParams; + } + +}; + +/*! + * Data specific to key signing + **/ +class SignParams +{ + public: + + std::string checkLvl; + + SignParams(std::string checkLvl) { + this->checkLvl = checkLvl; + } +}; + +/*! + * Data specific to key signing + **/ +class TrustParams +{ + public: + + std::string trustLvl; + + TrustParams(std::string trustLvl) { + this->trustLvl = trustLvl; + } +}; + +#endif diff --git a/libretroshare/src/pqi/authgpgtest.cc b/libretroshare/src/pqi/authgpgtest.cc new file mode 100644 index 000000000..36193fa26 --- /dev/null +++ b/libretroshare/src/pqi/authgpgtest.cc @@ -0,0 +1,408 @@ +/* + * libretroshare/src/ : authgpgtest.cc + * + * GPG interface for RetroShare. + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + * This is *THE* auth manager. It provides the web-of-trust via + * gpgme, and authenticates the certificates that are managed + * by the sublayer AuthSSL. + * + */ + +#include "pqi/authgpgtest.h" + +AuthGPGtest::AuthGPGtest() +{ + mOwnGPGId = "TEST_DUMMY_OWN_GPG_ID"; + return; +} + + /** + * @param ids list of gpg certificate ids (note, not the actual certificates) + */ +bool AuthGPGtest::availableGPGCertificatesWithPrivateKeys(std::list &ids) +{ + std::cerr << "AuthGPGtest::availableGPGCertificatesWithPrivateKeys()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::printKeys() +{ + std::cerr << "AuthGPGtest::printKeys()"; + std::cerr << std::endl; + return true; +} + + +/*********************************************************************************/ +/************************* STAGE 1 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 1: Initialisation.... As we are switching to OpenPGP the init functions + * will be different. Just move the initialisation functions over.... + * + * As GPGMe requires external calls to the GPG executable, which could potentially + * be expensive, We'll want to cache the GPG keys in this class. + * This should be done at initialisation, and saved in a map. + * (see storage at the end of the class) + * + ****/ +bool AuthGPGtest::active() +{ + std::cerr << "AuthGPGtest::active()"; + std::cerr << std::endl; + return true; +} + + + /* Initialize */ +bool AuthGPGtest::InitAuth() +{ + std::cerr << "AuthGPGtest::InitAuth()"; + std::cerr << std::endl; + return true; +} + + + /* Init by generating new Own PGP Cert, or selecting existing PGP Cert */ +int AuthGPGtest::GPGInit(const std::string& ownId) +{ + std::cerr << "AuthGPGtest::GPGInit(): new OwnId: " << ownId; + std::cerr << std::endl; + mOwnGPGId = ownId; + return true; +} + +bool AuthGPGtest::CloseAuth() +{ + std::cerr << "AuthGPGtest::CloseAuth()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString) +{ + std::cerr << "AuthGPGtest::GeneratePGPCertificate()"; + std::cerr << std::endl; + return true; +} + + +/*********************************************************************************/ +/************************* STAGE 3 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 3: These are some of the most commonly used functions in Retroshare. + * + * More commonly used functions. + * + * provide access to details in cache list. + * + ****/ +std::string getGPGName(const std::string &pgp_id) +{ + std::cerr << "AuthGPGtest::getGPGName()"; + std::cerr << std::endl; + return "DUMMY_NAME"; +} + +std::string getGPGEmail(const std::string &pgp_id) +{ + std::cerr << "AuthGPGtest::getGPGEmail()"; + std::cerr << std::endl; + return "DUMMY_EMAIL"; +} + + + /* PGP web of trust management */ +std::string AuthGPGtest::getGPGOwnId() +{ + std::cerr << "AuthGPGtest::getGPGOwnId()"; + std::cerr << std::endl; + return mOwnGPGId; +} + +std::string AuthGPGtest::getGPGOwnName() +{ + std::cerr << "AuthGPGtest::getGPGOwnName()"; + std::cerr << std::endl; + return "DUMMY_OWN_NAME"; +} + + +#if 0 +std::string AuthGPGtest::getGPGOwnEmail() +{ + std::cerr << "AuthGPGtest::getGPGOwnEmail()"; + std::cerr << std::endl; + return "DUMMY_OWN_EMAIL"; +} +#endif + +bool AuthGPGtest::getGPGDetails(const std::string& id, RsPeerDetails &d) +{ + std::cerr << "AuthGPGtest::getGPGDetails()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::getGPGAllList(std::list &ids) +{ + std::cerr << "AuthGPGtest::getGPGAllList()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::getGPGValidList(std::list &ids) +{ + std::cerr << "AuthGPGtest::getGPGValidList()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::getGPGAcceptedList(std::list &ids) +{ + std::cerr << "AuthGPGtest::getGPGAcceptedList()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::getGPGSignedList(std::list &ids) +{ + std::cerr << "AuthGPGtest::getGPGSignedList()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::isGPGValid(const std::string& id) +{ + std::cerr << "AuthGPGtest::isGPGValid()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::isGPGSigned(const std::string& id) +{ + std::cerr << "AuthGPGtest::isGPGSigned()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::isGPGAccepted(const std::string& id) +{ + std::cerr << "AuthGPGtest::isGPGAccepted()"; + std::cerr << std::endl; + return true; +} + +bool isGPGId(const std::string &id) +{ + std::cerr << "AuthGPGtest::isGPGId()"; + std::cerr << std::endl; + return true; +} + + +/*********************************************************************************/ +/************************* STAGE 4 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 4: Loading and Saving Certificates. (Strings and Files) + * + ****/ +bool AuthGPGtest::LoadCertificateFromString(const std::string& pem, std::string &gpg_id, + std::string& error_string) +{ + std::cerr << "AuthGPGtest::LoadCertificateFromString()"; + std::cerr << std::endl; + return true; +} + +std::string AuthGPGtest::SaveCertificateToString(const std::string& id) +{ + std::cerr << "AuthGPGtest::SaveCertificateToString()"; + std::cerr << std::endl; + return "NOT_A_CERTIFICATE"; +} + + +/*********************************************************************************/ +/************************* STAGE 6 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 6: Authentication, Trust and Signing. + * + * This is some of the harder functions, but they should have been + * done in gpgroot already. + * + ****/ +bool AuthGPGtest::setAcceptToConnectGPGCertificate(const std::string& gpg_id, + bool acceptance) +{ + std::cerr << "AuthGPGtest::setAcceptToConnectGPGCertificate()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::SignCertificateLevel0(const std::string& id) +{ + std::cerr << "AuthGPGtest::SignCertificateLevel0()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::RevokeCertificate(const std::string& id) +{ + std::cerr << "AuthGPGtest::RevokeCertificate()"; + std::cerr << std::endl; + return true; +} + +virtual bool TrustCertificate(const std::string &id, int trustlvl) +{ + std::cerr << "AuthGPGtest::TrustCertificate()"; + std::cerr << std::endl; + return true; +} +void AuthGPGtest::run() +{ + +} + +#if 0 +bool AuthGPGtest::TrustCertificateNone(std::string id) +{ + std::cerr << "AuthGPGtest::TrustCertificateNone()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::TrustCertificateMarginally(std::string id) +{ + std::cerr << "AuthGPGtest::TrustCertificateMarginally()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::TrustCertificateFully(std::string id) +{ + std::cerr << "AuthGPGtest::TrustCertificateFully()"; + std::cerr << std::endl; + return true; +} + +#endif + +bool AuthGPGtest::TrustCertificate(std::string id, int trustlvl) +{ + std::cerr << "AuthGPGtest::TrustCertificate()"; + std::cerr << std::endl; + return true; +} + + +/*********************************************************************************/ +/************************* STAGE 7 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 7: Signing Data. + * + * There should also be Encryption Functions... (do later). + * + ****/ +#if 0 +bool AuthGPGtest::SignData(std::string input, std::string &sign) +{ + std::cerr << "AuthGPGtest::SignData()"; + std::cerr << std::endl; + return false; +} + +bool AuthGPGtest::SignData(const void *data, const uint32_t len, std::string &sign) +{ + std::cerr << "AuthGPGtest::SignData()"; + std::cerr << std::endl; + return false; +} + +bool AuthGPGtest::SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen) +{ + std::cerr << "AuthGPGtest::SignDataBin()"; + std::cerr << std::endl; + return false; +} +#endif + +bool AuthGPGtest::SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen) +{ + std::cerr << "AuthGPGtest::SignDataBin()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const std::string& withfingerprint) +{ + std::cerr << "AuthGPGtest::VerifySignBin()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGtest::decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN) +{ + std::cerr << "AuthGPGtest::decryptText()"; + std::cerr << std::endl; + return true; +} + +bool AuthGPGimpl::addService(AuthGPGService *service) +{ + std::cerr << "AuthGPGtest::addService()"; + std::cerr << std::endl; + return true; +} + +std::string AuthGPGtest::getGPGName(const std::string & pgp_id) +{ + std::cerr << "AuthGPGtest::getGPGName()"; + std::cerr << std::endl; + return std::string(""); +} + +bool AuthGPGtest::TrustCertificate(const std::string & id, int trustlvl) +{ +} + +bool AuthGPGtest::isGPGId(const std::string & id) +{ +} + +std::string AuthGPGtest::getGPGEmail(const std::string & pgp_id) +{ +} + +bool AuthGPGtest::encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER) +{ + std::cerr << "AuthGPGtest::encryptText()"; + std::cerr << std::endl; + return false; +} + diff --git a/libretroshare/src/pqi/authgpgtest.h b/libretroshare/src/pqi/authgpgtest.h new file mode 100644 index 000000000..dacb0f745 --- /dev/null +++ b/libretroshare/src/pqi/authgpgtest.h @@ -0,0 +1,160 @@ +/* + * libretroshare/src/ : authgpgtest.h + * + * GPG interface for RetroShare. + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + * This is *THE* auth manager. It provides the web-of-trust via + * gpgme, and authenticates the certificates that are managed + * by the sublayer AuthSSL. + * + */ + +#ifndef RS_GPG_AUTH_TEST_HEADER +#define RS_GPG_AUTH_TEST_HEADER + +#include "pqi/authgpg.h" + +/* override the default AuthGPG */ +void setAuthGPG(AuthGPG *newgpg); + +class AuthGPGtest: public AuthGPG +{ + + public: + AuthGPGtest(); + + /** + * @param ids list of gpg certificate ids (note, not the actual certificates) + */ +virtual bool availableGPGCertificatesWithPrivateKeys(std::list &ids); +virtual bool printKeys(); + +/*********************************************************************************/ +/************************* STAGE 1 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 1: Initialisation.... As we are switching to OpenPGP the init functions + * will be different. Just move the initialisation functions over.... + * + * As GPGMe requires external calls to the GPG executable, which could potentially + * be expensive, We'll want to cache the GPG keys in this class. + * This should be done at initialisation, and saved in a map. + * (see storage at the end of the class) + * + ****/ +virtual bool active(); + + /* Initialize */ +virtual bool InitAuth (); +virtual void run(); + + /* Init by generating new Own PGP Cert, or selecting existing PGP Cert */ +virtual int GPGInit(const std::string& ownId); +virtual bool CloseAuth(); +virtual bool GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString); + +/*********************************************************************************/ +/************************* STAGE 3 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 3: These are some of the most commonly used functions in Retroshare. + * + * More commonly used functions. + * + * provide access to details in cache list. + * + ****/ +virtual std::string getGPGName(const std::string &pgp_id); +virtual std::string getGPGEmail(const std::string &pgp_id); + + /* PGP web of trust management */ +virtual std::string getGPGOwnId(); +virtual std::string getGPGOwnName(); + +//virtual std::string getGPGOwnEmail(); +virtual bool getGPGDetails(const std::string& id, RsPeerDetails &d); +virtual bool getGPGAllList(std::list &ids); +virtual bool getGPGValidList(std::list &ids); +virtual bool getGPGAcceptedList(std::list &ids); +virtual bool getGPGSignedList(std::list &ids); +virtual bool isGPGValid(const std::string& id); +virtual bool isGPGSigned(const std::string& id); +virtual bool isGPGAccepted(const std::string& id); +virtual bool isGPGId(const std::string &id); + +/*********************************************************************************/ +/************************* STAGE 4 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 4: Loading and Saving Certificates. (Strings and Files) + * + ****/ +virtual bool LoadCertificateFromString(const std::string& pem, std::string &gpg_id, + std::string& error_string); +virtual std::string SaveCertificateToString(const std::string& id); + +/*********************************************************************************/ +/************************* STAGE 6 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 6: Authentication, Trust and Signing. + * + * This is some of the harder functions, but they should have been + * done in gpgroot already. + * + ****/ +virtual bool setAcceptToConnectGPGCertificate(const std::string& gpg_id, + bool acceptance); //don't act on the gpg key, use a seperate set +virtual bool SignCertificateLevel0(const std::string& id); +virtual bool RevokeCertificate(const std::string& id); /* Particularly hard - leave for later */ +//virtual bool TrustCertificateNone(std::string id); +//virtual bool TrustCertificateMarginally(std::string id); +//virtual bool TrustCertificateFully(std::string id); +virtual bool TrustCertificate(const std::string &id, int trustlvl); //trustlvl is 2 for none, 3 for marginal and 4 for full trust + +/*********************************************************************************/ +/************************* STAGE 7 ***********************************************/ +/*********************************************************************************/ +/***** + * STAGE 7: Signing Data. + * + * There should also be Encryption Functions... (do later). + * + ****/ +//virtual bool SignData(std::string input, std::string &sign); +//virtual bool SignData(const void *data, const uint32_t len, std::string &sign); +//virtual bool SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen); +virtual bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen); +virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const std::string& withfingerprint); +virtual bool decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN); +virtual bool encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER); +//END of PGP public functions + +virtual bool addService(AuthGPGService *service); + private: + + std::string mOwnGPGId; +}; + + + + +#endif diff --git a/libretroshare/src/pqi/authssl.cc b/libretroshare/src/pqi/authssl.cc new file mode 100644 index 000000000..95865de07 --- /dev/null +++ b/libretroshare/src/pqi/authssl.cc @@ -0,0 +1,1344 @@ +/* + * libretroshare/src/pqi: authssl.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + * + * This class is designed to provide authentication using ssl certificates + * only. It is intended to be wrapped by an gpgauthmgr to provide + * pgp + ssl web-of-trust authentication. + * + */ + +#include "authssl.h" +#include "sslfns.h" +#include "cleanupxpgp.h" + +#include "pqinetwork.h" +#include "authgpg.h" +#include "pqi/p3connmgr.h" +#include "serialiser/rsconfigitems.h" +#include "util/rsdir.h" + +/******************** notify of new Cert **************************/ +#include "pqinotify.h" + +#include +//#include +//#include +#include +#include + +#include +#include + +/**** + * #define AUTHSSL_DEBUG 1 + ***/ + +// initialisation du pointeur de singleton � z�ro +static AuthSSL *instance_ssl = NULL; + +/* hidden function - for testing purposes() */ +void setAuthSSL(AuthSSL *newssl) +{ + instance_ssl = newssl; +} + +void AuthSSLInit() +{ + instance_ssl = new AuthSSLimpl(); +} + +AuthSSL *AuthSSL::getAuthSSL() +{ + return instance_ssl; +} + +AuthSSL::AuthSSL() +{ + return; +} + + +/********************************************************************************/ +/********************************************************************************/ +/********************* Cert Search / Add / Remove **************************/ +/********************************************************************************/ +/********************************************************************************/ + +static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx); + + +sslcert::sslcert(X509 *x509, std::string pid) +{ + certificate = x509; + id = pid; + name = getX509CNString(x509->cert_info->subject); + org = getX509OrgString(x509->cert_info->subject); + location = getX509LocString(x509->cert_info->subject); + email = ""; + + issuer = getX509CNString(x509->cert_info->issuer); + + authed = false; +} + +/************************************************************************ + * + * + * CODE IS DIVIDED INTO + * + * 1) SSL Setup. + * 3) Cert Access. + * 4) Cert Sign / Verify. + * 5) Cert Authentication + * 2) Cert Add / Remove + * 6) Cert Storage + */ + +/********************************************************************************/ +/********************************************************************************/ +/********************* Cert Search / Add / Remove **************************/ +/********************************************************************************/ +/********************************************************************************/ + + +AuthSSLimpl::AuthSSLimpl() + : p3Config(CONFIG_TYPE_AUTHSSL), sslctx(NULL), + mOwnCert(NULL), mOwnPrivateKey(NULL), mOwnPublicKey(NULL), init(0) +{ +} + +bool AuthSSLimpl::active() +{ + return init; +} + + +int AuthSSLimpl::InitAuth(const char *cert_file, const char *priv_key_file, + const char *passwd) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::InitAuth()"; + std::cerr << std::endl; +#endif + + /* single call here si don't need to invoke mutex yet */ +static int initLib = 0; + if (!initLib) + { + initLib = 1; + SSL_load_error_strings(); + SSL_library_init(); + } + + + if (init == 1) + { + std::cerr << "AuthSSLimpl::InitAuth already initialized." << std::endl; + return 1; + } + + if ((cert_file == NULL) || + (priv_key_file == NULL) || + (passwd == NULL)) + { + //fprintf(stderr, "sslroot::initssl() missing parameters!\n"); + return 0; + } + + + // actions_to_seed_PRNG(); + RAND_seed(passwd, strlen(passwd)); + + std::cerr << "SSL Library Init!" << std::endl; + + // setup connection method + sslctx = SSL_CTX_new(TLSv1_method()); + + // setup cipher lists. + SSL_CTX_set_cipher_list(sslctx, "DEFAULT"); + + // certificates (Set Local Server Certificate). + FILE *ownfp = RsDirUtil::rs_fopen(cert_file, "r"); + if (ownfp == NULL) + { + std::cerr << "Couldn't open Own Certificate!" << std::endl; + return -1; + } + + + + // get xPGP certificate. + X509 *x509 = PEM_read_X509(ownfp, NULL, NULL, NULL); + fclose(ownfp); + + if (x509 == NULL) + { + std::cerr << "AuthSSLimpl::InitAuth() PEM_read_X509() Failed"; + std::cerr << std::endl; + return -1; + } + SSL_CTX_use_certificate(sslctx, x509); + mOwnPublicKey = X509_get_pubkey(x509); + + // get private key + FILE *pkfp = RsDirUtil::rs_fopen(priv_key_file, "rb"); + if (pkfp == NULL) + { + std::cerr << "Couldn't Open PrivKey File!" << std::endl; + CloseAuth(); + return -1; + } + + mOwnPrivateKey = PEM_read_PrivateKey(pkfp, NULL, NULL, (void *) passwd); + fclose(pkfp); + + if (mOwnPrivateKey == NULL) + { + std::cerr << "AuthSSLimpl::InitAuth() PEM_read_PrivateKey() Failed"; + std::cerr << std::endl; + return -1; + } + SSL_CTX_use_PrivateKey(sslctx, mOwnPrivateKey); + + if (1 != SSL_CTX_check_private_key(sslctx)) + { + std::cerr << "Issues With Private Key! - Doesn't match your Cert" << std::endl; + std::cerr << "Check your input key/certificate:" << std::endl; + std::cerr << priv_key_file << " & " << cert_file; + std::cerr << std::endl; + CloseAuth(); + return -1; + } + + if (!getX509id(x509, mOwnId)) + { + std::cerr << "AuthSSLimpl::InitAuth() getX509id() Failed"; + std::cerr << std::endl; + + /* bad certificate */ + CloseAuth(); + return -1; + } + + /* Check that Certificate is Ok ( virtual function ) + * for gpg/pgp or CA verification + */ + + if (!validateOwnCertificate(x509, mOwnPrivateKey)) + { + std::cerr << "AuthSSLimpl::InitAuth() validateOwnCertificate() Failed"; + std::cerr << std::endl; + + /* bad certificate */ + CloseAuth(); + exit(1); + return -1; + } + + + // enable verification of certificates (PEER) + // and install verify callback. + SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + verify_x509_callback); + + std::cerr << "SSL Verification Set" << std::endl; + + mOwnCert = new sslcert(x509, mOwnId); + + init = 1; + return 1; +} + +/* Dummy function to be overloaded by real implementation */ +bool AuthSSLimpl::validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) +{ + (void) pkey; /* remove unused parameter warning */ + + /* standard authentication */ + if (!AuthX509WithGPG(x509)) + { + return false; + } + return true; +} + +bool AuthSSLimpl::CloseAuth() +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::CloseAuth()"; + std::cerr << std::endl; +#endif + SSL_CTX_free(sslctx); + + // clean up private key.... + // remove certificates etc -> opposite of initssl. + init = 0; + return 1; +} + +/* Context handling */ +SSL_CTX *AuthSSLimpl::getCTX() +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::getCTX()"; + std::cerr << std::endl; +#endif + return sslctx; +} + +std::string AuthSSLimpl::OwnId() +{ +#ifdef AUTHSSL_DEBUG +// std::cerr << "AuthSSLimpl::OwnId()" << std::endl; +#endif + return mOwnId; +} + +std::string AuthSSLimpl::getOwnLocation() +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::OwnId()" << std::endl; +#endif + return mOwnCert->location; +} + +std::string AuthSSLimpl::SaveOwnCertificateToString() +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::SaveOwnCertificateToString() " << std::endl; +#endif + return saveX509ToPEM(mOwnCert->certificate); +} + +/********************************************************************************/ +/********************************************************************************/ +/********************* Cert Search / Add / Remove **************************/ +/********************************************************************************/ +/********************************************************************************/ + +bool AuthSSLimpl::SignData(std::string input, std::string &sign) +{ + return SignData(input.c_str(), input.length(), sign); +} + +bool AuthSSLimpl::SignData(const void *data, const uint32_t len, std::string &sign) +{ + + RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + unsigned int signlen = EVP_PKEY_size(mOwnPrivateKey); + unsigned char signature[signlen]; + + if (0 == EVP_SignInit(mdctx, EVP_sha1())) + { + std::cerr << "EVP_SignInit Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if (0 == EVP_SignUpdate(mdctx, data, len)) + { + std::cerr << "EVP_SignUpdate Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if (0 == EVP_SignFinal(mdctx, signature, &signlen, mOwnPrivateKey)) + { + std::cerr << "EVP_SignFinal Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + EVP_MD_CTX_destroy(mdctx); + + sign.clear(); + std::ostringstream out; + out << std::hex; + for(uint32_t i = 0; i < signlen; i++) + { + out << std::setw(2) << std::setfill('0'); + out << (uint32_t) (signature[i]); + } + + sign = out.str(); + + return true; +} + +bool AuthSSLimpl::SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen) +{ + return SignDataBin(input.c_str(), input.length(), sign, signlen); +} + +bool AuthSSLimpl::SignDataBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int *signlen) +{ + RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ + return SSL_SignDataBin(data, len, sign, signlen, mOwnPrivateKey); +} + + +bool AuthSSLimpl::VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, SSL_id sslId) +{ + /* find certificate. + * if we don't have - fail. + */ + + RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ + + /* find the peer */ + sslcert *peer; + if (sslId == mOwnId) + { + peer = mOwnCert; + } + else if (!locked_FindCert(sslId, &peer)) + { + std::cerr << "VerifySignBin() no peer" << std::endl; + return false; + } + + return SSL_VerifySignBin(data, len, sign, signlen, peer->certificate); +} + +bool AuthSSLimpl::VerifyOwnSignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen) +{ + return SSL_VerifySignBin(data, len, sign, signlen, mOwnCert->certificate); +} + + +/********************************************************************************/ +/********************************************************************************/ +/********************* Sign and Auth with GPG **************************/ +/********************************************************************************/ +/********************************************************************************/ + +/* Note these functions don't need Mutexes - + * only using GPG functions - which lock themselves + */ + +X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long days) +{ + /* Transform the X509_REQ into a suitable format to + * generate DIGEST hash. (for SSL to do grunt work) + */ + +#define SERIAL_RAND_BITS 64 + + //const EVP_MD *digest = EVP_sha1(); + ASN1_INTEGER *serial = ASN1_INTEGER_new(); + EVP_PKEY *tmppkey; + X509 *x509 = X509_new(); + if (x509 == NULL) + { + std::cerr << "AuthSSLimpl::SignX509Req() FAIL" << std::endl; + return NULL; + } + + //long version = 0x00; + unsigned long chtype = MBSTRING_ASC; + X509_NAME *issuer_name = X509_NAME_new(); + X509_NAME_add_entry_by_txt(issuer_name, "CN", chtype, + (unsigned char *) AuthGPG::getAuthGPG()->getGPGOwnId().c_str(), -1, -1, 0); +/**** + X509_NAME_add_entry_by_NID(issuer_name, 48, 0, + (unsigned char *) "email@email.com", -1, -1, 0); + X509_NAME_add_entry_by_txt(issuer_name, "O", chtype, + (unsigned char *) "org", -1, -1, 0); + X509_NAME_add_entry_by_txt(x509_name, "L", chtype, + (unsigned char *) "loc", -1, -1, 0); +****/ + + std::cerr << "AuthSSLimpl::SignX509Req() Issuer name: " << AuthGPG::getAuthGPG()->getGPGOwnId() << std::endl; + + BIGNUM *btmp = BN_new(); + if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) + { + std::cerr << "AuthSSLimpl::SignX509Req() rand FAIL" << std::endl; + return NULL; + } + if (!BN_to_ASN1_INTEGER(btmp, serial)) + { + std::cerr << "AuthSSLimpl::SignX509Req() asn1 FAIL" << std::endl; + return NULL; + } + BN_free(btmp); + + if (!X509_set_serialNumber(x509, serial)) + { + std::cerr << "AuthSSLimpl::SignX509Req() serial FAIL" << std::endl; + return NULL; + } + ASN1_INTEGER_free(serial); + + /* Generate SUITABLE issuer name. + * Must reference OpenPGP key, that is used to verify it + */ + + if (!X509_set_issuer_name(x509, issuer_name)) + { + std::cerr << "AuthSSLimpl::SignX509Req() issue FAIL" << std::endl; + return NULL; + } + X509_NAME_free(issuer_name); + + + if (!X509_gmtime_adj(X509_get_notBefore(x509),0)) + { + std::cerr << "AuthSSLimpl::SignX509Req() notbefore FAIL" << std::endl; + return NULL; + } + + if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*days)) + { + std::cerr << "AuthSSLimpl::SignX509Req() notafter FAIL" << std::endl; + return NULL; + } + + if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req))) + { + std::cerr << "AuthSSLimpl::SignX509Req() sub FAIL" << std::endl; + return NULL; + } + + tmppkey = X509_REQ_get_pubkey(req); + if (!tmppkey || !X509_set_pubkey(x509,tmppkey)) + { + std::cerr << "AuthSSLimpl::SignX509Req() pub FAIL" << std::endl; + return NULL; + } + + std::cerr << "X509 Cert, prepared for signing" << std::endl; + + /*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/ + int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF; + X509_ALGOR *algor1 = x509->cert_info->signature; + X509_ALGOR *algor2 = x509->sig_alg; + ASN1_BIT_STRING *signature = x509->signature; + X509_CINF *data = x509->cert_info; + //EVP_PKEY *pkey = NULL; + const EVP_MD *type = EVP_sha1(); + + EVP_MD_CTX ctx; + unsigned char *p,*buf_in=NULL; + unsigned char *buf_hashout=NULL,*buf_sigout=NULL; + int inl=0,hashoutl=0,hashoutll=0; + int sigoutl=0,sigoutll=0; + X509_ALGOR *a; + + EVP_MD_CTX_init(&ctx); + + /* FIX ALGORITHMS */ + + a = algor1; + ASN1_TYPE_free(a->parameter); + a->parameter=ASN1_TYPE_new(); + a->parameter->type=V_ASN1_NULL; + + ASN1_OBJECT_free(a->algorithm); + a->algorithm=OBJ_nid2obj(type->pkey_type); + + a = algor2; + ASN1_TYPE_free(a->parameter); + a->parameter=ASN1_TYPE_new(); + a->parameter->type=V_ASN1_NULL; + + ASN1_OBJECT_free(a->algorithm); + a->algorithm=OBJ_nid2obj(type->pkey_type); + + + std::cerr << "Algorithms Fixed" << std::endl; + + /* input buffer */ + inl=i2d(data,NULL); + buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl); + + hashoutll=hashoutl=EVP_MD_size(type); + buf_hashout=(unsigned char *)OPENSSL_malloc((unsigned int)hashoutl); + + sigoutll=sigoutl=2048; // hashoutl; //EVP_PKEY_size(pkey); + buf_sigout=(unsigned char *)OPENSSL_malloc((unsigned int)sigoutl); + + if ((buf_in == NULL) || (buf_hashout == NULL) || (buf_sigout == NULL)) + { + hashoutl=0; + sigoutl=0; + fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); + goto err; + } + p=buf_in; + + std::cerr << "Buffers Allocated" << std::endl; + + i2d(data,&p); + /* data in buf_in, ready to be hashed */ + EVP_DigestInit_ex(&ctx,type, NULL); + EVP_DigestUpdate(&ctx,(unsigned char *)buf_in,inl); + if (!EVP_DigestFinal(&ctx,(unsigned char *)buf_hashout, + (unsigned int *)&hashoutl)) + { + hashoutl=0; + fprintf(stderr, "AuthSSLimpl::SignX509Req: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB)\n"); + goto err; + } + + std::cerr << "Digest Applied: len: " << hashoutl << std::endl; + + /* NOW Sign via GPG Functions */ + if (!AuthGPG::getAuthGPG()->SignDataBin(buf_hashout, hashoutl, buf_sigout, (unsigned int *) &sigoutl)) + { + sigoutl = 0; + goto err; + } + + std::cerr << "Buffer Sizes: in: " << inl; + std::cerr << " HashOut: " << hashoutl; + std::cerr << " SigOut: " << sigoutl; + std::cerr << std::endl; + + //passphrase = "NULL"; + + std::cerr << "Signature done: len:" << sigoutl << std::endl; + + /* ADD Signature back into Cert... Signed!. */ + + if (signature->data != NULL) OPENSSL_free(signature->data); + signature->data=buf_sigout; + buf_sigout=NULL; + signature->length=sigoutl; + /* In the interests of compatibility, I'll make sure that + * the bit string has a 'not-used bits' value of 0 + */ + signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); + signature->flags|=ASN1_STRING_FLAG_BITS_LEFT; + + std::cerr << "Certificate Complete" << std::endl; + + return x509; + + /* XXX CLEANUP */ + err: + /* cleanup */ + std::cerr << "GPGAuthMgr::SignX509Req() err: FAIL" << std::endl; + + return NULL; +} + + +/* This function, checks that the X509 is signed by a known GPG key, + * NB: we do not have to have approved this person as a friend. + * this is important - as it allows non-friends messages to be validated. + */ + +bool AuthSSLimpl::AuthX509WithGPG(X509 *x509) +{ + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "AuthSSLimpl::AuthX509WithGPG() called\n"); + #endif + + if (!CheckX509Certificate(x509)) + { + std::cerr << "AuthSSLimpl::AuthX509() X509 NOT authenticated : Certificate failed basic checks" << std::endl; + return false; + } + + /* extract CN for peer Id */ + std::string issuer = getX509CNString(x509->cert_info->issuer); + RsPeerDetails pd; + #ifdef AUTHSSL_DEBUG + std::cerr << "Checking GPG issuer : " << issuer << std::endl ; + #endif + if (!AuthGPG::getAuthGPG()->getGPGDetails(issuer, pd)) { + std::cerr << "AuthSSLimpl::AuthX509() X509 NOT authenticated : AuthGPG::getAuthGPG()->getGPGDetails() returned false." << std::endl; + return false; + } + + /* verify GPG signature */ + + /*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/ + int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF; + ASN1_BIT_STRING *signature = x509->signature; + X509_CINF *data = x509->cert_info; + const EVP_MD *type = EVP_sha1(); + + EVP_MD_CTX ctx; + unsigned char *p,*buf_in=NULL; + unsigned char *buf_hashout=NULL,*buf_sigout=NULL; + int inl=0,hashoutl=0,hashoutll=0; + int sigoutl=0,sigoutll=0; + //X509_ALGOR *a; + + EVP_MD_CTX_init(&ctx); + + /* input buffer */ + inl=i2d(data,NULL); + buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl); + + hashoutll=hashoutl=EVP_MD_size(type); + buf_hashout=(unsigned char *)OPENSSL_malloc((unsigned int)hashoutl); + + sigoutll=sigoutl=2048; //hashoutl; //EVP_PKEY_size(pkey); + buf_sigout=(unsigned char *)OPENSSL_malloc((unsigned int)sigoutl); + + #ifdef AUTHSSL_DEBUG + std::cerr << "Buffer Sizes: in: " << inl; + std::cerr << " HashOut: " << hashoutl; + std::cerr << " SigOut: " << sigoutl; + std::cerr << std::endl; + #endif + + if ((buf_in == NULL) || (buf_hashout == NULL) || (buf_sigout == NULL)) { + hashoutl=0; + sigoutl=0; + fprintf(stderr, "AuthSSLimpl::AuthX509: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n"); + goto err; + } + p=buf_in; + + #ifdef AUTHSSL_DEBUG + std::cerr << "Buffers Allocated" << std::endl; + #endif + + i2d(data,&p); + /* data in buf_in, ready to be hashed */ + EVP_DigestInit_ex(&ctx,type, NULL); + EVP_DigestUpdate(&ctx,(unsigned char *)buf_in,inl); + if (!EVP_DigestFinal(&ctx,(unsigned char *)buf_hashout, + (unsigned int *)&hashoutl)) + { + hashoutl=0; + fprintf(stderr, "AuthSSLimpl::AuthX509: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB)\n"); + goto err; + } + + #ifdef AUTHSSL_DEBUG + std::cerr << "Digest Applied: len: " << hashoutl << std::endl; + #endif + + /* copy data into signature */ + sigoutl = signature->length; + memmove(buf_sigout, signature->data, sigoutl); + + /* NOW check sign via GPG Functions */ + //get the fingerprint of the key that is supposed to sign + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::AuthX509() verifying the gpg sig with keyprint : " << pd.fpr << std::endl; + std::cerr << "Sigoutl = " << sigoutl << std::endl ; + std::cerr << "pd.fpr = " << pd.fpr << std::endl ; + std::cerr << "hashoutl = " << hashoutl << std::endl ; + #endif + + if (!AuthGPG::getAuthGPG()->VerifySignBin(buf_hashout, hashoutl, buf_sigout, (unsigned int) sigoutl, pd.fpr)) { + sigoutl = 0; + goto err; + } + + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::AuthX509() X509 authenticated" << std::endl; + #endif + + OPENSSL_free(buf_in) ; + OPENSSL_free(buf_hashout) ; + return true; + + err: + std::cerr << "AuthSSLimpl::AuthX509() X509 NOT authenticated" << std::endl; + + if(buf_in != NULL) + OPENSSL_free(buf_in) ; + if(buf_hashout != NULL) + OPENSSL_free(buf_hashout) ; + return false; +} + + + + /* validate + get id */ +bool AuthSSLimpl::ValidateCertificate(X509 *x509, std::string &peerId) +{ + /* check self signed */ + if (!AuthX509WithGPG(x509)) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::ValidateCertificate() bad certificate."; + std::cerr << std::endl; +#endif + return false; + } + if(!getX509id(x509, peerId)) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::ValidateCertificate() Cannot retrieve peer id from certificate.."; + std::cerr << std::endl; +#endif + return false; + } + +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::ValidateCertificate() good certificate."; + std::cerr << std::endl; +#endif + + return true; +} + + +/********************************************************************************/ +/********************************************************************************/ +/**************************** encrypt / decrypt fns ****************************/ +/********************************************************************************/ +/********************************************************************************/ + +static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "static verify_x509_callback called."; + std::cerr << std::endl; +#endif + return AuthSSL::getAuthSSL()->VerifyX509Callback(preverify_ok, ctx); + +} + +int AuthSSLimpl::VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx) +{ + char buf[256]; + X509 *err_cert; + int err, depth; + + err_cert = X509_STORE_CTX_get_current_cert(ctx); + err = X509_STORE_CTX_get_error(ctx); + depth = X509_STORE_CTX_get_error_depth(ctx); + + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::VerifyX509Callback(preverify_ok: " << preverify_ok + << " Err: " << err << " Depth: " << depth << std::endl; + #endif + + /* + * Retrieve the pointer to the SSL of the connection currently treated + * and the application specific data stored into the SSL object. + */ + + X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); + + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::VerifyX509Callback: depth: " << depth << ":" << buf << std::endl; + #endif + + + if (!preverify_ok) { + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "Verify error:num=%d:%s:depth=%d:%s\n", err, + X509_verify_cert_error_string(err), depth, buf); + #endif + } + + /* + * At this point, err contains the last verification error. We can use + * it for something special + */ + + if (!preverify_ok) + { + + X509_NAME_oneline(X509_get_issuer_name(X509_STORE_CTX_get_current_cert(ctx)), buf, 256); + #ifdef AUTHSSL_DEBUG + printf("issuer= %s\n", buf); + #endif + + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "Doing REAL PGP Certificates\n"); + #endif + /* do the REAL Authentication */ + if (!AuthX509WithGPG(X509_STORE_CTX_get_current_cert(ctx))) + { + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "AuthSSLimpl::VerifyX509Callback() X509 not authenticated.\n"); + #endif + return false; + } + std::string pgpid = getX509CNString(X509_STORE_CTX_get_current_cert(ctx)->cert_info->issuer); + + if (pgpid != AuthGPG::getAuthGPG()->getGPGOwnId() && !AuthGPG::getAuthGPG()->isGPGAccepted(pgpid)) + { + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "AuthSSLimpl::VerifyX509Callback() pgp key not accepted : \n"); + fprintf(stderr, "issuer pgpid : "); + fprintf(stderr, "%s\n",pgpid.c_str()); + fprintf(stderr, "\n AuthGPG::getAuthGPG()->getGPGOwnId() : "); + fprintf(stderr, "%s\n",AuthGPG::getAuthGPG()->getGPGOwnId().c_str()); + fprintf(stderr, "\n"); + #endif + return false; + } + + preverify_ok = true; + + } else { + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "A normal certificate is probably a security breach attempt. We sould fail it !!!\n"); + #endif + preverify_ok = false; + } + + if (preverify_ok) { + + //sslcert *cert = NULL; + std::string certId; + getX509id(X509_STORE_CTX_get_current_cert(ctx), certId); + + } + + #ifdef AUTHSSL_DEBUG + if (preverify_ok) { + fprintf(stderr, "AuthSSLimpl::VerifyX509Callback returned true.\n"); + } else { + fprintf(stderr, "AuthSSLimpl::VerifyX509Callback returned false.\n"); + } + #endif + + return preverify_ok; +} + + +/********************************************************************************/ +/********************************************************************************/ +/**************************** encrypt / decrypt fns ****************************/ +/********************************************************************************/ +/********************************************************************************/ + + +bool AuthSSLimpl::encrypt(void *&out, int &outlen, const void *in, int inlen, std::string peerId) +{ + RsStackMutex stack(sslMtx); /******* LOCKED ******/ + +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::encrypt() called for peerId : " << peerId << " with inlen : " << inlen << std::endl; +#endif + //TODO : use ssl to crypt the binary input buffer +// out = malloc(inlen); +// memcpy(out, in, inlen); +// outlen = inlen; + + EVP_PKEY *public_key; + if (peerId == mOwnId) { + public_key = mOwnPublicKey; + } else { + if (!mCerts[peerId]) { + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::encrypt() public key not found." << std::endl; + #endif + return false; + } else { + public_key = mCerts[peerId]->certificate->cert_info->key->pkey; + } + } + + EVP_CIPHER_CTX ctx; + int eklen, net_ekl; + unsigned char *ek; + unsigned char iv[EVP_MAX_IV_LENGTH]; + EVP_CIPHER_CTX_init(&ctx); + int out_currOffset = 0; + int out_offset = 0; + + int max_evp_key_size = EVP_PKEY_size(public_key); + ek = (unsigned char*)malloc(max_evp_key_size); + const EVP_CIPHER *cipher = EVP_aes_128_cbc(); + int cipher_block_size = EVP_CIPHER_block_size(cipher); + int size_net_ekl = sizeof(net_ekl); + + int max_outlen = inlen + cipher_block_size + EVP_MAX_IV_LENGTH + max_evp_key_size + size_net_ekl; + + // intialize context and send store encrypted cipher in ek + if(!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &public_key, 1)) { + free(ek); + return false; + } + + // now assign memory to out accounting for data, and cipher block size, key length, and key length val + out = new unsigned char[inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH]; + + net_ekl = htonl(eklen); + memcpy((unsigned char*)out + out_offset, &net_ekl, size_net_ekl); + out_offset += size_net_ekl; + + memcpy((unsigned char*)out + out_offset, ek, eklen); + out_offset += eklen; + + memcpy((unsigned char*)out + out_offset, iv, EVP_MAX_IV_LENGTH); + out_offset += EVP_MAX_IV_LENGTH; + + // now encrypt actual data + if(!EVP_SealUpdate(&ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen)) { + free(ek); + delete[] (unsigned char*) out; + out = NULL; + return false; + } + + // move along to partial block space + out_offset += out_currOffset; + + // add padding + if(!EVP_SealFinal(&ctx, (unsigned char*) out + out_offset, &out_currOffset)) { + free(ek); + delete[] (unsigned char*) out; + out = NULL; + return false; + } + + // move to end + out_offset += out_currOffset; + + // make sure offset has not gone passed valid memory bounds + if(out_offset > max_outlen) return false; + + // free encrypted key data + free(ek); + + EVP_CIPHER_CTX_cleanup(&ctx); + + outlen = out_offset; + + #ifdef DISTRIB_DEBUG + std::cerr << "Authssl::encrypt() finished with outlen : " << outlen << std::endl; + #endif + + return true; +} + +bool AuthSSLimpl::decrypt(void *&out, int &outlen, const void *in, int inlen) +{ + RsStackMutex stack(sslMtx); /******* LOCKED ******/ + + + +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::decrypt() called with inlen : " << inlen << std::endl; +#endif + //TODO : use ssl to decrypt the binary input buffer +// out = malloc(inlen); +// memcpy(out, in, inlen); +// outlen = inlen; + EVP_CIPHER_CTX ctx; + int eklen = 0, net_ekl = 0; + unsigned char *ek = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + int ek_mkl = EVP_PKEY_size(mOwnPrivateKey); + ek = (unsigned char*)malloc(ek_mkl); + EVP_CIPHER_CTX_init(&ctx); + + int in_offset = 0, out_currOffset = 0; + int size_net_ekl = sizeof(net_ekl); + + if(size_net_ekl > inlen) { + free(ek); + return false; + } + + memcpy(&net_ekl, (unsigned char*)in, size_net_ekl); + eklen = ntohl(net_ekl); + in_offset += size_net_ekl; + + if(eklen > (inlen-in_offset)) { + free(ek); + return false; + } + + memcpy(ek, (unsigned char*)in + in_offset, eklen); + in_offset += eklen; + + if(EVP_MAX_IV_LENGTH > (inlen-in_offset)) { + free(ek); + return false; + } + + memcpy(iv, (unsigned char*)in + in_offset, EVP_MAX_IV_LENGTH); + in_offset += EVP_MAX_IV_LENGTH; + + const EVP_CIPHER* cipher = EVP_aes_128_cbc(); + + if(0 == EVP_OpenInit(&ctx, cipher, ek, eklen, iv, mOwnPrivateKey)) { + free(ek); + return false; + } + + out = new unsigned char[inlen - in_offset]; + + if(!EVP_OpenUpdate(&ctx, (unsigned char*) out, &out_currOffset, (unsigned char*)in + in_offset, inlen - in_offset)) { + free(ek); + delete[] (unsigned char*) out; + out = NULL; + return false; + } + + in_offset += out_currOffset; + outlen += out_currOffset; + + if(!EVP_OpenFinal(&ctx, (unsigned char*)out + out_currOffset, &out_currOffset)) { + free(ek); + delete[] (unsigned char*) out; + out = NULL; + return false; + } + + outlen += out_currOffset; + + if(ek != NULL) + free(ek); + + EVP_CIPHER_CTX_cleanup(&ctx); + + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::decrypt() finished with outlen : " << outlen << std::endl; + #endif + + return true; +} + + +/********************************************************************************/ +/********************************************************************************/ +/********************* Cert Search / Add / Remove **************************/ +/********************************************************************************/ +/********************************************************************************/ + +/* store for discovery */ +bool AuthSSLimpl::FailedCertificate(X509 *x509, bool incoming) +{ + (void) incoming; /* remove unused parameter warning */ + + /* if auths -> store */ + if (AuthX509WithGPG(x509)) + { + LocalStoreCert(x509); + return true; + } + return false; +} + +bool AuthSSLimpl::CheckCertificate(std::string id, X509 *x509) +{ + (void) id; /* remove unused parameter warning */ + + /* if auths -> store */ + if (AuthX509WithGPG(x509)) + { + LocalStoreCert(x509); + return true; + } + return false; +} + + + +/* Locked search -> internal help function */ +bool AuthSSLimpl::locked_FindCert(std::string id, sslcert **cert) +{ + std::map::iterator it; + + if (mCerts.end() != (it = mCerts.find(id))) + { + *cert = it->second; + return true; + } + return false; +} + + +/* Remove Certificate */ + +bool AuthSSLimpl::RemoveX509(std::string id) +{ + std::map::iterator it; + + RsStackMutex stack(sslMtx); /******* LOCKED ******/ + + if (mCerts.end() != (it = mCerts.find(id))) + { + sslcert *cert = it->second; + + /* clean up */ + X509_free(cert->certificate); + cert->certificate = NULL; + delete cert; + + mCerts.erase(it); + + return true; + } + return false; +} + + +bool AuthSSLimpl::LocalStoreCert(X509* x509) +{ + //store the certificate in the local cert list + std::string peerId; + if(!getX509id(x509, peerId)) + { + std::cerr << "AuthSSLimpl::LocalStoreCert() Cannot retrieve peer id from certificate." << std::endl; +#ifdef AUTHSSL_DEBUG +#endif + return false; + } + + + RsStackMutex stack(sslMtx); /******* LOCKED ******/ + + if (peerId == mOwnId) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::LocalStoreCert() not storing own certificate" << std::endl; +#endif + return false; + } + + /* do a search */ + std::map::iterator it; + + if (mCerts.end() != (it = mCerts.find(peerId))) + { + sslcert *cert = it->second; + + /* found something */ + /* check that they are exact */ + if (0 != X509_cmp(cert->certificate, x509)) + { + /* MAJOR ERROR */ + std::cerr << "ERROR : AuthSSLimpl::LocalStoreCert() got two ssl certificates with identical ids -> dropping second"; + std::cerr << std::endl; + return false; + } + /* otherwise - we have it already */ + return false; + } + +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::LocalStoreCert() storing certificate for " << peerId << std::endl; +#endif + mCerts[peerId] = new sslcert(X509_dup(x509), peerId); + + /* flag for saving config */ + IndicateConfigChanged(); + return true ; +} + + +/********************************************************************************/ +/********************************************************************************/ +/************************ Config Functions **********************************/ +/********************************************************************************/ +/********************************************************************************/ + + +RsSerialiser *AuthSSLimpl::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsGeneralConfigSerialiser()); + return rss ; +} + +bool AuthSSLimpl::saveList(bool& cleanup, std::list& lst) +{ + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::saveList() called" << std::endl ; + #endif + + RsStackMutex stack(sslMtx); /******* LOCKED ******/ + + cleanup = true ; + + // Now save config for network digging strategies + RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; + std::map::iterator mapIt; + for (mapIt = mCerts.begin(); mapIt != mCerts.end(); mapIt++) { + if (mapIt->first == mOwnId) { + continue; + } + RsTlvKeyValue kv; + kv.key = mapIt->first; + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::saveList() called (mapIt->first) : " << (mapIt->first) << std::endl ; + #endif + kv.value = saveX509ToPEM(mapIt->second->certificate); + vitem->tlvkvs.pairs.push_back(kv) ; + } + lst.push_back(vitem); + + return true ; +} + +bool AuthSSLimpl::loadList(std::list& load) +{ + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::loadList() Item Count: " << load.size() << std::endl; + #endif + + /* load the list of accepted gpg keys */ + std::list::iterator it; + for(it = load.begin(); it != load.end(); it++) { + RsConfigKeyValueSet *vitem = dynamic_cast(*it); + + if(vitem) { + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSLimpl::loadList() General Variable Config Item:" << std::endl; + vitem->print(std::cerr, 10); + std::cerr << std::endl; + #endif + + std::list::iterator kit; + for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); kit++) { + if (kit->key == mOwnId) { + continue; + } + + X509 *peer = loadX509FromPEM(kit->value); + /* authenticate it */ + if (AuthX509WithGPG(peer)) + { + LocalStoreCert(peer); + } + } + } + delete (*it); + } + return true; +} + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + diff --git a/libretroshare/src/pqi/authssl.h b/libretroshare/src/pqi/authssl.h new file mode 100644 index 000000000..390042ce7 --- /dev/null +++ b/libretroshare/src/pqi/authssl.h @@ -0,0 +1,261 @@ +/* + * libretroshare/src/pqi: authssl.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_AUTH_SSL_HEADER +#define MRK_AUTH_SSL_HEADER + +/* + * This is an implementation of SSL certificate authentication, which is + * overloaded with pgp style signatures, and web-of-trust authentication. + * + * only the owner ssl cert is store, the rest is jeus callback verification + * + * To use as an SSL authentication system, you must use a common CA certificate. + * * The pqissl stuff doesn't need to differentiate between SSL, SSL + PGP, + * as its X509 certs. + * * The rsserver stuff has to distinguish between all three types ;( + * + */ + +#include +#include + +#include +#include + +#include "util/rsthreads.h" + +#include "pqi/pqi_base.h" +#include "pqi/pqinetwork.h" +//#include "rsiface/rspeers.h" +#include "pqi/p3cfgmgr.h" + +typedef std::string SSL_id; + +/* This #define removes Connection Manager references in AuthSSL. + * They should not be here. What about Objects and orthogonality? + * This code is also stopping immediate reconnections from working. + */ + +class AuthSSL; + +class sslcert +{ + public: + sslcert(X509* x509, std::string id); + sslcert(); + + /* certificate parameters */ + std::string id; + std::string name; + std::string location; + std::string org; + std::string email; + + std::string issuer; + + std::string fpr; + //std::list signers; + + /* Auth settings */ + bool authed; + + /* INTERNAL Parameters */ + X509* certificate; +}; + +/* required to install instance */ +extern void AuthSSLInit(); + +class AuthSSL +{ + public: + AuthSSL(); + +static AuthSSL *getAuthSSL(); + + /* Initialisation Functions (Unique) */ +virtual bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) = 0; + +virtual bool active() = 0; +virtual int InitAuth(const char *srvr_cert, const char *priv_key, + const char *passwd) = 0; +virtual bool CloseAuth() = 0; + + /*********** Overloaded Functions from p3AuthMgr **********/ + + /* get Certificate Id */ +virtual std::string OwnId() = 0; +virtual std::string getOwnLocation() = 0; +//virtual bool getAllList(std::list &ids); +//virtual bool getAuthenticatedList(std::list &ids); +//virtual bool getUnknownList(std::list &ids); +//virtual bool getSSLChildListOfGPGId(std::string gpg_id, std::list &ids); + + /* get Details from the Certificates */ +//virtual bool isAuthenticated(std::string id); +//virtual std::string getName(std::string id); +//virtual std::string getIssuerName(std::string id); +//virtual std::string getGPGId(SSL_id id); +//virtual bool getCertDetails(std::string id, sslcert &cert); + + /* Load/Save certificates */ +virtual std::string SaveOwnCertificateToString() = 0; + + /* Sign / Encrypt / Verify Data */ +virtual bool SignData(std::string input, std::string &sign) = 0; +virtual bool SignData(const void *data, const uint32_t len, std::string &sign) = 0; + +virtual bool SignDataBin(std::string, unsigned char*, unsigned int*) = 0; +virtual bool SignDataBin(const void*, uint32_t, unsigned char*, unsigned int*) = 0; +virtual bool VerifyOwnSignBin(const void*, uint32_t, unsigned char*, unsigned int) = 0; +virtual bool VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, SSL_id sslId) = 0; + +// return : false if encrypt failed +virtual bool encrypt(void *&out, int &outlen, const void *in, int inlen, std::string peerId) = 0; +// return : false if decrypt fails +virtual bool decrypt(void *&out, int &outlen, const void *in, int inlen) = 0; + + +virtual X509* SignX509ReqWithGPG(X509_REQ *req, long days) = 0; +virtual bool AuthX509WithGPG(X509 *x509) = 0; + + +virtual int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx) = 0; +virtual bool ValidateCertificate(X509 *x509, std::string &peerId) = 0; /* validate + get id */ + + public: /* SSL specific functions used in pqissl/pqissllistener */ +virtual SSL_CTX *getCTX() = 0; + +/* Restored these functions: */ +virtual bool FailedCertificate(X509 *x509, bool incoming) = 0; /* store for discovery */ +virtual bool CheckCertificate(std::string peerId, X509 *x509) = 0; /* check that they are exact match */ +}; + + +class AuthSSLimpl : public AuthSSL, public p3Config +{ + public: + + /* Initialisation Functions (Unique) */ + AuthSSLimpl(); +bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey); + +virtual bool active(); +virtual int InitAuth(const char *srvr_cert, const char *priv_key, + const char *passwd); +virtual bool CloseAuth(); + + /*********** Overloaded Functions from p3AuthMgr **********/ + + /* get Certificate Id */ +virtual std::string OwnId(); +virtual std::string getOwnLocation(); +//virtual bool getAllList(std::list &ids); +//virtual bool getAuthenticatedList(std::list &ids); +//virtual bool getUnknownList(std::list &ids); +//virtual bool getSSLChildListOfGPGId(std::string gpg_id, std::list &ids); + + /* get Details from the Certificates */ +//virtual bool isAuthenticated(std::string id); +//virtual std::string getName(std::string id); +//virtual std::string getIssuerName(std::string id); +//virtual std::string getGPGId(SSL_id id); +//virtual bool getCertDetails(std::string id, sslcert &cert); + + /* Load/Save certificates */ +virtual std::string SaveOwnCertificateToString(); + + /* Sign / Encrypt / Verify Data */ +virtual bool SignData(std::string input, std::string &sign); +virtual bool SignData(const void *data, const uint32_t len, std::string &sign); + +virtual bool SignDataBin(std::string, unsigned char*, unsigned int*); +virtual bool SignDataBin(const void*, uint32_t, unsigned char*, unsigned int*); +virtual bool VerifyOwnSignBin(const void*, uint32_t, unsigned char*, unsigned int); +virtual bool VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, SSL_id sslId); + +// return : false if encrypt failed +virtual bool encrypt(void *&out, int &outlen, const void *in, int inlen, std::string peerId); +// return : false if decrypt fails +virtual bool decrypt(void *&out, int &outlen, const void *in, int inlen); + + +virtual X509* SignX509ReqWithGPG(X509_REQ *req, long days); +virtual bool AuthX509WithGPG(X509 *x509); + + +virtual int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx); +virtual bool ValidateCertificate(X509 *x509, std::string &peerId); /* validate + get id */ + + +/*****************************************************************/ +/*********************** p3config ******************************/ + /* Key Functions to be overloaded for Full Configuration */ + virtual RsSerialiser *setupSerialiser(); + virtual bool saveList(bool &cleanup, std::list& ); + virtual bool loadList(std::list& load); +/*****************************************************************/ + + public: /* SSL specific functions used in pqissl/pqissllistener */ +virtual SSL_CTX *getCTX(); + +/* Restored these functions: */ +virtual bool FailedCertificate(X509 *x509, bool incoming); /* store for discovery */ +virtual bool CheckCertificate(std::string peerId, X509 *x509); /* check that they are exact match */ + + + private: + + // the single instance of this + static AuthSSL *instance_ssl; + +bool LocalStoreCert(X509* x509); +bool RemoveX509(std::string id); + + /*********** LOCKED Functions ******/ +bool locked_FindCert(std::string id, sslcert **cert); + + /* Data */ + /* these variables are constants -> don't need to protect */ + SSL_CTX *sslctx; + std::string mOwnId; + sslcert *mOwnCert; + + RsMutex sslMtx; /* protects all below */ + + + EVP_PKEY *mOwnPrivateKey; + EVP_PKEY *mOwnPublicKey; + + int init; + + std::map mCerts; + +}; + +#endif // MRK_AUTH_SSL_HEADER diff --git a/libretroshare/src/pqi/authssltest.cc b/libretroshare/src/pqi/authssltest.cc new file mode 100644 index 000000000..a4a3d6a5e --- /dev/null +++ b/libretroshare/src/pqi/authssltest.cc @@ -0,0 +1,223 @@ +/* + * libretroshare/src/pqi: authssltest.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/authssltest.h" + +AuthSSLtest::AuthSSLtest() +{ + mOwnId = "abcdtestid12345678"; +} + + + /* Initialisation Functions (Unique) */ +bool AuthSSLtest::validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) +{ + std::cerr << "AuthSSLtest::validateOwnCertificate()"; + std::cerr << std::endl; + return false; +} + + +bool AuthSSLtest::active() +{ + std::cerr << "AuthSSLtest::active()"; + std::cerr << std::endl; + return true; +} + +int AuthSSLtest::InitAuth(const char *srvr_cert, const char *priv_key, + const char *passwd) +{ + std::cerr << "AuthSSLtest::InitAuth()"; + std::cerr << std::endl; + return 1; +} + +bool AuthSSLtest::CloseAuth() +{ + std::cerr << "AuthSSLtest::AuthSSLtest::CloseAuth()"; + std::cerr << std::endl; + return 1; +} + + + /*********** Overloaded Functions from p3AuthMgr **********/ + + /* get Certificate Id */ +std::string AuthSSLtest::OwnId() +{ + std::cerr << "AuthSSLtest::OwnId"; + std::cerr << std::endl; + return mOwnId; +} + +std::string AuthSSLtest::getOwnLocation() +{ + std::cerr << "AuthSSLtest::getOwnLocation"; + std::cerr << std::endl; + return "TestVersion"; +} + +//bool getAllList(std::list &ids); +//bool getAuthenticatedList(std::list &ids); +//bool getUnknownList(std::list &ids); +//bool getSSLChildListOfGPGId(std::string gpg_id, std::list &ids); + + /* get Details from the Certificates */ +//bool isAuthenticated(std::string id); +//virtual std::string getName(std::string id); +//std::string getIssuerName(std::string id); +//std::string getGPGId(SSL_id id); +//bool getCertDetails(std::string id, sslcert &cert); + + /* Load/Save certificates */ +std::string AuthSSLtest::SaveOwnCertificateToString() +{ + std::cerr << "AuthSSLtest::SaveOwnCertificateToString()"; + std::cerr << std::endl; + return std::string(); +} + + + /* Sign / Encrypt / Verify Data */ +bool AuthSSLtest::SignData(std::string input, std::string &sign) +{ + std::cerr << "AuthSSLtest::SignData()"; + std::cerr << std::endl; + return false; +} + +bool AuthSSLtest::SignData(const void *data, const uint32_t len, std::string &sign) +{ + std::cerr << "AuthSSLtest::SignData()"; + std::cerr << std::endl; + return false; +} + + +bool AuthSSLtest::SignDataBin(std::string, unsigned char*, unsigned int*) +{ + std::cerr << "AuthSSLtest::SignDataBin()"; + std::cerr << std::endl; + return false; +} + +bool AuthSSLtest::SignDataBin(const void*, uint32_t, unsigned char*, unsigned int*) +{ + std::cerr << "AuthSSLtest::SignDataBin()"; + std::cerr << std::endl; + return false; +} + +bool AuthSSLtest::VerifyOwnSignBin(const void*, uint32_t, unsigned char*, unsigned int) +{ + std::cerr << "AuthSSLtest::VerifyOwnSignBin()"; + std::cerr << std::endl; + return false; +} + +bool AuthSSLtest::VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, SSL_id sslId) +{ + std::cerr << "AuthSSLtest::VerifySignBin()"; + std::cerr << std::endl; + return false; +} + + + +// return : false if encrypt failed +bool AuthSSLtest::encrypt(void *&out, int &outlen, const void *in, int inlen, std::string peerId) +{ + std::cerr << "AuthSSLtest::encrypt()"; + std::cerr << std::endl; + return false; +} + +// return : false if decrypt fails +bool AuthSSLtest::decrypt(void *&out, int &outlen, const void *in, int inlen) +{ + std::cerr << "AuthSSLtest::decrypt()"; + std::cerr << std::endl; + return false; +} + + + +X509* AuthSSLtest::SignX509ReqWithGPG(X509_REQ *req, long days) +{ + std::cerr << "AuthSSLtest::SignX509ReqWithGPG"; + std::cerr << std::endl; + return NULL; +} + +bool AuthSSLtest::AuthX509WithGPG(X509 *x509) +{ + std::cerr << "AuthSSLtest::AuthX509WithGPG()"; + std::cerr << std::endl; + return false; +} + + + +int AuthSSLtest::VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx) +{ + std::cerr << "AuthSSLtest::VerifyX509Callback()"; + std::cerr << std::endl; + return 0; +} + +bool AuthSSLtest::ValidateCertificate(X509 *x509, std::string &peerId) +{ + std::cerr << "AuthSSLtest::ValidateCertificate()"; + std::cerr << std::endl; + return false; +} + + + +SSL_CTX *AuthSSLtest::getCTX() +{ + std::cerr << "AuthSSLtest::getCTX()"; + std::cerr << std::endl; + return NULL; +} + + +/* Restored these functions: */ +bool AuthSSLtest::FailedCertificate(X509 *x509, bool incoming) +{ + std::cerr << "AuthSSLtest::FailedCertificate()"; + std::cerr << std::endl; + return false; +} + +bool AuthSSLtest::CheckCertificate(std::string peerId, X509 *x509) +{ + std::cerr << "AuthSSLtest::CheckCertificate()"; + std::cerr << std::endl; + return false; +} + diff --git a/libretroshare/src/pqi/authssltest.h b/libretroshare/src/pqi/authssltest.h new file mode 100644 index 000000000..b395babe1 --- /dev/null +++ b/libretroshare/src/pqi/authssltest.h @@ -0,0 +1,101 @@ +/* + * libretroshare/src/pqi: authssltest.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_AUTH_SSL_TEST_HEADER +#define MRK_AUTH_SSL_TEST_HEADER + +#include "pqi/authssl.h" + +void setAuthSSL(AuthSSL *newssl); + +class AuthSSLtest: public AuthSSL +{ + public: + + AuthSSLtest(); + /* Initialisation Functions (Unique) */ +virtual bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey); + +virtual bool active(); +virtual int InitAuth(const char *srvr_cert, const char *priv_key, + const char *passwd); +virtual bool CloseAuth(); + + /*********** Overloaded Functions from p3AuthMgr **********/ + + /* get Certificate Id */ +virtual std::string OwnId(); +virtual std::string getOwnLocation(); +//virtual bool getAllList(std::list &ids); +//virtual bool getAuthenticatedList(std::list &ids); +//virtual bool getUnknownList(std::list &ids); +//virtual bool getSSLChildListOfGPGId(std::string gpg_id, std::list &ids); + + /* get Details from the Certificates */ +//virtual bool isAuthenticated(std::string id); +//virtual std::string getName(std::string id); +//virtual std::string getIssuerName(std::string id); +//virtual std::string getGPGId(SSL_id id); +//virtual bool getCertDetails(std::string id, sslcert &cert); + + /* Load/Save certificates */ +virtual std::string SaveOwnCertificateToString(); + + /* Sign / Encrypt / Verify Data */ +virtual bool SignData(std::string input, std::string &sign); +virtual bool SignData(const void *data, const uint32_t len, std::string &sign); + +virtual bool SignDataBin(std::string, unsigned char*, unsigned int*); +virtual bool SignDataBin(const void*, uint32_t, unsigned char*, unsigned int*); +virtual bool VerifyOwnSignBin(const void*, uint32_t, unsigned char*, unsigned int); +virtual bool VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, SSL_id sslId); + +// return : false if encrypt failed +virtual bool encrypt(void *&out, int &outlen, const void *in, int inlen, std::string peerId); +// return : false if decrypt fails +virtual bool decrypt(void *&out, int &outlen, const void *in, int inlen); + + +virtual X509* SignX509ReqWithGPG(X509_REQ *req, long days); +virtual bool AuthX509WithGPG(X509 *x509); + + +virtual int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx); +virtual bool ValidateCertificate(X509 *x509, std::string &peerId); /* validate + get id */ + + public: /* SSL specific functions used in pqissl/pqissllistener */ +virtual SSL_CTX *getCTX(); + +/* Restored these functions: */ +virtual bool FailedCertificate(X509 *x509, bool incoming); /* store for discovery */ +virtual bool CheckCertificate(std::string peerId, X509 *x509); /* check that they are exact match */ + + private: + + std::string mOwnId; +}; + +#endif // MRK_AUTH_SSL_TEST_HEADER diff --git a/libretroshare/src/pqi/cleanupxpgp.cc b/libretroshare/src/pqi/cleanupxpgp.cc new file mode 100644 index 000000000..8e74ba4f0 --- /dev/null +++ b/libretroshare/src/pqi/cleanupxpgp.cc @@ -0,0 +1,385 @@ +/* + * libretroshare/src/pqi: cleanupxpgp.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2008 by Sourashis Roy + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "cleanupxpgp.h" +#include +#include //strlen +#include + +/* +Method for cleaning up the certificate. This method removes any unnecessay white spaces and unnecessary +new line characters in the certificate. Also it makes sure that there are 64 characters per line in +the certificate. This function removes white spaces and new line characters in the entire segment +-----BEGIN XPGP CERTIFICATE----- + +-----END XPGP CERTIFICATE----- +We also take care of correcting cases like ----- BEGIN. Here extra empty spaces +have been introduced between ----- and BEGIN. Similarly for the +end tag we take care of cases like ----- END XPGP . Here extra empty spaces have been +introduced and the actual tag should have been -----END XPGP +*/ + +std::string cleanUpCertificate(const std::string& badCertificate) +{ + /* + Buffer for storing the cleaned certificate. In certain cases the + cleanCertificate can be larger than the badCertificate + */ + std::string cleanCertificate; + //The entire certificate begin tag + const char * beginCertTag="-----BEGIN"; + //The entire certificate end tag + const char * endCertTag="-----END"; + //Tag containing dots. The common part of both start and end tags + const char * commonTag="-----"; + //Only BEGIN part of the begin tag + const char * beginTag="BEGIN"; + //Only END part of the end tag + const char * endTag="END"; + //The start index of the ----- part of the certificate begin tag + size_t beginCertStartIdx1=0; + //The start index of the BEGIN part of the certificate begin tag + size_t beginCertStartIdx2=0; + //The start index of the end part(-----) of the certificate begin tag. The begin tag ends with -----. Example -----BEGIN XPGP CERTIFICATE----- + size_t beginCertEndIdx=0; + //The start index of the ----- part of the certificate end tag + size_t endCertStartIdx1=0; + //The start index of the END part of the certificate end tag + size_t endCertStartIdx2=0; + //The start index of the end part(-----) of the certificate end tag. The begin tag ends with -----. Example -----BEGIN XPGP CERTIFICATE----- + size_t endCertEndIdx=0; + //The length of the bad certificate. + size_t lengthOfCert=badCertificate.length(); + //The current index value in the bad certificate + size_t currBadCertIdx=0; + //Temporary index value + size_t tmpIdx=0; + //Boolean flag showing if the begin tag or the end tag has been found + bool found=false; + /* + Calculating the value of the beginCertStartIdx1 and beginCertStartIdx2. Here we first locate the occurance of ----- and then + the location of BEGIN. Next we check if there are any non space or non new-line characters between their occureance. If there are any other + characters between the two(----- and BEGIN), other than space and new line then it means that it is the certificate begin tag. + Here we take care of the fact that we may have introduced some spaces and newlines in the begin tag by mistake. This + takes care of the spaces and newlines between ----- and BEGIN. + */ + + while(found==false && (beginCertStartIdx1=badCertificate.find(commonTag,tmpIdx))!=std::string::npos) + { + beginCertStartIdx2=badCertificate.find(beginTag,beginCertStartIdx1+strlen(commonTag)); + tmpIdx=beginCertStartIdx1+strlen(commonTag); + if(beginCertStartIdx2!=std::string::npos) + { + found=true; + for(size_t i=beginCertStartIdx1+strlen(commonTag);i tag"< tag"< tag"<=lengthOfCert) + { + std::cerr<<"Certificate corrupted beyond repair: No <------END > tag"< header; + header.push_back("Version"); + header.push_back("Comment"); + header.push_back("MessageID"); + header.push_back("Hash"); + header.push_back("Charset"); + + for (std::list::iterator headerIt = header.begin (); headerIt != header.end(); headerIt++) + { + if (badCertificate.substr(currBadCertIdx, (*headerIt).length()) == *headerIt) + { + cleanCertificate += badCertificate.substr(currBadCertIdx, (*headerIt).length()); + currBadCertIdx += (*headerIt).length(); + while(badCertificate[currBadCertIdx]!='\n') + { + cleanCertificate += badCertificate[currBadCertIdx]; + currBadCertIdx++; + } + cleanCertificate += "\n"; + } + } + + //add empty line after armor header + cleanCertificate += "\n"; + + //Start of the actual certificate. Remove spaces in the certificate + //and make sure there are 64 characters per line in the + //new cleaned certificate + int cntPerLine=0; + while(currBadCertIdx + +//! Converts invitation to clean XPGP certificate + +//! This function was used for extracting XPGP certificates from invitation +//!letters. Typical input was something like +//! You have been invited to join the retroshare community by: beardog-unstable-02 +//! +//! Retroshare is a Friend-2-Friend network that enables you to communicate securely and privately .... +//! ... text stuff ..... +//! +//!-----BEGIN XPGP CERTIFICATE----- +//!Version: ... +//! +//!MIICxQIBADCCAUkCAQAwHhcNMDkwMjI4MTgzODIyWhcNMTQwMjI3MTgzODIyWjCC +//! ...more ines here... +//!mEuhG8UmDIzC1jeTu8rTMnO+DO3FH/cek1vlfFl4t9g/xktG9U4SPLg= +//!=checksum +//!-----END XPGP CERTIFICATE----- +//! +//! In the newer gui version, users send each other almost clean certificates, +//! so this functon is used only to avoid possible bugs with line endings +std::string cleanUpCertificate(const std::string& badCertificate); + +#endif diff --git a/libretroshare/src/pqi/p3cfgmgr.cc b/libretroshare/src/pqi/p3cfgmgr.cc new file mode 100644 index 000000000..255c6e86d --- /dev/null +++ b/libretroshare/src/pqi/p3cfgmgr.cc @@ -0,0 +1,1349 @@ +/* + * libretroshare/src/pqi: p3cfgmgr.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "util/rsdir.h" +#include "retroshare/rspeers.h" +#include "pqi/p3cfgmgr.h" +#include "pqi/authssl.h" +#include "pqi/pqibin.h" +#include "pqi/pqistore.h" +#include "pqi/pqiarchive.h" +#include "pqi/pqinotify.h" +#include +#include + +#include "serialiser/rsconfigitems.h" + +/* +#define CONFIG_DEBUG 1 +*/ +#define BACKEDUP_SAVE + + +p3ConfigMgr::p3ConfigMgr(std::string dir, std::string fname, std::string signame) + :basedir(dir), metafname(fname), metasigfname(signame), + mConfigSaveActive(true) +{ + oldConfigType = checkForGlobalSigConfig(); + + // configuration to load correct global types + pqiConfig::globalConfigType = oldConfigType; + +} + +void p3ConfigMgr::tick() +{ + bool toSave = false; + + { + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + + /* iterate through and check if any have changed */ + std::map::iterator it; + for(it = configs.begin(); it != configs.end(); it++) + { + if (it->second->HasConfigChanged(0)) + { + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::tick() Config Changed - Element: "; + std::cerr << it->first; + std::cerr << std::endl; +#endif + + toSave = true; + } + } + + /* disable saving before exit */ + if (!mConfigSaveActive) + { + toSave = false; + } + } + + if (toSave) + { + saveConfiguration(); + } +} + + +void p3ConfigMgr::saveConfiguration() +{ + if(!RsDiscSpace::checkForDiscSpace(RS_CONFIG_DIRECTORY)) + return ; + + saveConfig(); + + +} + +void p3ConfigMgr::saveConfig() +{ + + bool ok= true; + + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + + std::map::iterator it; + for(it = configs.begin(); it != configs.end(); it++) + { + if (it->second->HasConfigChanged(1)) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::globalSaveConfig() Saving Element: "; + std::cerr << it->first; + std::cerr << std::endl; +#endif + ok &= it->second->saveConfiguration(); + } + /* save metaconfig */ + } + + if(ok && oldConfigType) + removeOldConfigType(); + return; +} + + +void p3ConfigMgr::removeOldConfigType() +{ + std::string fName = basedir + "/" + metafname; + std::string sigfName = basedir + "/" + metasigfname; + + remove(fName.c_str()); + remove(sigfName.c_str()); + + //now set globalconfig type to false so mgr saves + oldConfigType = false; + pqiConfig::globalConfigType = oldConfigType; + +} +void p3ConfigMgr::globalSaveConfig() +{ + + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::globalSaveConfig()"; + std::cerr << std::endl; +#endif + + RsConfigKeyValueSet *item = new RsConfigKeyValueSet(); + + std::map::iterator it; + for(it = configs.begin(); it != configs.end(); it++) + { + if (it->second->HasConfigChanged(1)) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::globalSaveConfig() Saving Element: "; + std::cerr << it->first; + std::cerr << std::endl; +#endif + it->second->saveConfiguration(); + } + /* save metaconfig */ + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::globalSaveConfig() Element: "; + std::cerr << it->first << " Hash: " << it->second->Hash(); + std::cerr << std::endl; +#endif + if (it->second->Hash() == "") + { + /* skip if no hash */ + continue; + } + + RsTlvKeyValue kv; + { + std::ostringstream out; + out << it->first; + kv.key = out.str(); + } + kv.value = it->second->Hash(); + item->tlvkvs.pairs.push_back(kv); + } + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::globalSaveConfig() Complete MetaConfigItem: "; + std::cerr << std::endl; + item->print(std::cerr, 20); + +#endif + /* construct filename */ + std::string fname = basedir; + std::string sign_fname = basedir; + std::string fname_backup, sign_fname_backup; // back up files + + if (basedir != "") + { + fname += "/"; + sign_fname += "/"; + } + + fname += metafname; + sign_fname += metasigfname; + fname_backup = fname + ".tmp"; + sign_fname_backup = sign_fname + ".tmp"; + + /* Write the data to a stream */ + uint32_t bioflags = BIN_FLAGS_WRITEABLE; + BinMemInterface *configbio = new BinMemInterface(1000, bioflags); + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsGeneralConfigSerialiser()); + pqistore store(rss, "CONFIG", configbio, BIN_FLAGS_WRITEABLE); + + store.SendItem(item); + + /* sign data */ + std::string signature; + AuthSSL::getAuthSSL()->SignData(configbio->memptr(), configbio->memsize(), signature); + + /* write signature to configuration */ + BinMemInterface *signbio = new BinMemInterface(signature.c_str(), + signature.length(), BIN_FLAGS_READABLE); + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::globalSaveConfig() MetaFile Signature:"; + std::cerr << std::endl; + std::cerr << signature; + std::cerr << std::endl; +#endif + + // begin two pass save + backedUpFileSave(fname, fname_backup, sign_fname, sign_fname_backup, configbio, signbio); + + delete signbio; + +} + +bool p3ConfigMgr::backedUpFileSave(const std::string& fname, const std::string& fname_backup, const std::string& sign_fname, + const std::string& sign_fname_backup, BinMemInterface* configbio, BinMemInterface* signbio){ + + FILE *file = NULL, *sign = NULL; + char *config_buff=NULL, *sign_buff=NULL; + int size_file=0, size_sign=0; + + // begin two pass saving by writing to back up file instead + if (!configbio->writetofile(fname_backup.c_str()) || !signbio->writetofile(sign_fname_backup.c_str())) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::backedupFileSave() Failed write to Backup MetaFiles " << fname_backup + << " and " << sign_fname_backup; + std::cerr << std::endl; +#endif + return false; + } + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() Save file and keeps a back up " << std::endl; +#endif + + // open file from which to collect buffer + file = RsDirUtil::rs_fopen(fname.c_str(), "rb"); + sign = RsDirUtil::rs_fopen(sign_fname.c_str(), "rb"); + + // if failed then create files + if((file == NULL) || (sign == NULL)){ +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() failed to open meta files " << fname << std::endl; +#endif + + file = RsDirUtil::rs_fopen(fname.c_str(), "wb"); + sign = RsDirUtil::rs_fopen(sign_fname.c_str(), "wb"); + + if((file == NULL) || (sign == NULL)){ + std::cerr << "p3Config::backedUpFileSave() failed to open backup meta files" << fname_backup << std::endl; + return false; + } + } + + + //determine file size + fseek(file, 0L, SEEK_END); + size_file = ftell(file); + fseek(file, 0L, SEEK_SET); + + fseek(sign, 0L, SEEK_END); + size_sign = ftell(sign); + fseek(sign, 0L, SEEK_SET); + + if((size_file) > 0 && (size_sign > 0)){ + //read this into a buffer + config_buff = new char[size_file]; + fread(config_buff, 1, size_file, file); + + //read this into a buffer + sign_buff = new char[size_sign]; + fread(sign_buff, 1, size_sign, sign); + } + + fclose(file); + fclose(sign); + + // rename back-up to current file + if(!RsDirUtil::renameFile(fname_backup, fname) || !RsDirUtil::renameFile(sign_fname_backup, sign_fname)){ +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() Failed to rename backup meta files: " << std::endl + << fname_backup << " to " << fname << std::endl + << sign_fname_backup << " to " << sign_fname << std::endl; +#endif + return true; + } + + if((size_file) > 0 && (size_sign > 0)){ + + // now write actual back-up file + file = RsDirUtil::rs_fopen(fname_backup.c_str(), "wb"); + sign = RsDirUtil::rs_fopen(sign_fname_backup.c_str(), "wb"); + + if((file == NULL) || (sign == NULL)){ +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() fopen failed for file: " << fname_backup << std::endl; +#endif + return true; + } + + if(size_file != fwrite(config_buff,1, size_file, file)) + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "Write error", "Error while writing backup configuration file " + fname_backup + "\nIs your disc full or out of quota ?"); + + if(size_sign != fwrite(sign_buff, 1, size_sign, sign)) + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "Write error", "Error while writing main signature file " + sign_fname_backup + "\nIs your disc full or out of quota ?"); + + fclose(file); + fclose(sign); + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() finished backed up save. " << std::endl; +#endif + + delete[] config_buff; + delete[] sign_buff; + } + return true; +} + +void p3ConfigMgr::loadConfiguration() +{ + if(oldConfigType) + globalLoadConfig(); + else + loadConfig(); + + return; +} + +void p3ConfigMgr::loadConfig() +{ + std::map::iterator cit; + std::string dummyHash = "dummyHash"; + for (cit = configs.begin(); cit != configs.end(); cit++) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfig() Element: "; + std::cerr << cit->first <<"Dummy Hash: " << dummyHash; + std::cerr << std::endl; +#endif + + cit->second->loadConfiguration(dummyHash); + + /* force config to NOT CHANGED */ + cit->second->HasConfigChanged(0); + cit->second->HasConfigChanged(1); + } + + return; +} + +void p3ConfigMgr::globalLoadConfig() +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfiguration()"; + std::cerr << std::endl; +#endif + + /* construct filename */ + std::string fname = basedir; + std::string sign_fname = basedir; + std::string fname_backup, sign_fname_backup; + + if (basedir != "") + { + fname += "/"; + sign_fname += "/"; + } + + fname += metafname; + sign_fname += metasigfname; + + // temporary files + fname_backup = fname + ".tmp"; + sign_fname_backup = sign_fname + ".tmp"; + + BinMemInterface* membio = new BinMemInterface(1000, BIN_FLAGS_READABLE); + + // Will attempt to get signature first from meta file then if that fails try temporary meta files, these will correspond to temp configs + bool pass = getSignAttempt(fname, sign_fname, membio); + + // if first attempt fails then try and temporary files + if(!pass){ + + #ifdef CONFIG_DEBUG + std::cerr << "\np3ConfigMgr::loadConfiguration(): Trying to load METACONFIG item and METASIGN with temporary files"; + std::cerr << std::endl; + #endif + + pass = getSignAttempt(fname_backup, sign_fname_backup , membio); + + if(!pass){ + #ifdef CONFIG_DEBUG + std::cerr << "\np3ConfigMgr::loadConfiguration(): failed to load METACONFIG item and METASIGN"; + std::cerr << std::endl; + #endif + + return; + } + } + + membio->fseek(0); /* go back to start of file */ + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsGeneralConfigSerialiser()); + pqistore stream(rss, "CONFIG", membio, BIN_FLAGS_READABLE); + + RsItem *rsitem = stream.GetItem(); + + RsConfigKeyValueSet *item = dynamic_cast(rsitem); + if (!item) + { + delete rsitem; + return; + } + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfiguration() Loaded MetaConfigItem: "; + std::cerr << std::endl; + item->print(std::cerr, 20); + +#endif + + /* extract info from KeyValueSet */ + std::list::iterator it; + for(it = item->tlvkvs.pairs.begin(); it != item->tlvkvs.pairs.end(); it++) + { + /* find the configuration */ + uint32_t confId = atoi(it->key.c_str()); + std::string hashin = it->value; + + /*********************** HACK TO CHANGE CACHE CONFIG ID ********* + * REMOVE IN A MONTH OR TWO + */ + + if (confId == CONFIG_TYPE_CACHE_OLDID) + { + confId = CONFIG_TYPE_CACHE; + } + + /*********************** HACK TO CHANGE CACHE CONFIG ID *********/ + + std::map::iterator cit; + cit = configs.find(confId); + if (cit != configs.end()) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfiguration() Element: "; + std::cerr << confId << " Hash: " << hashin; + std::cerr << std::endl; +#endif + (cit->second)->loadConfiguration(hashin); + + /* force config to CHANGED to force saving into new non-global sig format */ + cit->second->IndicateConfigChanged(); + // cit->second->HasConfigChanged(0); + // cit->second->HasConfigChanged(1); + } + } + + delete item; + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfiguration() Done!"; + std::cerr << std::endl; +#endif + +} + + +bool p3ConfigMgr::getSignAttempt(std::string& metaConfigFname, std::string& metaSignFname, BinMemInterface* membio){ + + + #ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::getSignAttempt() metaConfigFname : " << metaConfigFname; + std::cerr << std::endl; + std::cerr << "p3ConfigMgr::getSignAttempt() metaSignFname : " << metaSignFname; + std::cerr << std::endl; + #endif + + /* read signature */ + BinMemInterface *signbio = new BinMemInterface(1000, BIN_FLAGS_READABLE); + + if (!signbio->readfromfile(metaSignFname.c_str())) + { + #ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::getSignAttempt() Failed to Load MetaSignFile"; + std::cerr << std::endl; + #endif + + /* HACK to load the old one (with the wrong directory) + * THIS SHOULD BE REMOVED IN A COUPLE OF VERSIONS.... + * ONLY HERE TO CORRECT BAD MISTAKE IN EARLIER VERSIONS. + */ + + metaSignFname = metasigfname; + metaConfigFname = metafname; + + if (!signbio->readfromfile(metaSignFname.c_str())) + { + #ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::getSignAttempt() HACK: Failed to Load ALT MetaSignFile"; + std::cerr << std::endl; + #endif + } + else + { + #ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::getSignAttempt() HACK: Loaded ALT MetaSignFile"; + std::cerr << std::endl; + #endif + } + } + + std::string oldsignature((char *) signbio->memptr(), signbio->memsize()); + delete signbio; + + + + if (!membio->readfromfile(metaConfigFname.c_str())) + { + #ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::getSignAttempt() Failed to Load MetaFile"; + std::cerr << std::endl; + #endif + // delete membio; + // return ; + } + + /* get signature */ + std::string signature; + AuthSSL::getAuthSSL()->SignData(membio->memptr(), membio->memsize(), signature); + + #ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::getSignAttempt() New MetaFile Signature:"; + std::cerr << std::endl; + std::cerr << signature; + std::cerr << std::endl; + #endif + + #ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::getSignAttempt() Orig MetaFile Signature:"; + std::cerr << std::endl; + std::cerr << oldsignature; + std::cerr << std::endl; + #endif + + if (signature != oldsignature) + { + /* Failed */ + #ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::getSignAttempt() Signature Check Failed"; + std::cerr << std::endl; + #endif + return false; + } + +#ifdef CONFIG_DEBUG +std::cerr << "p3ConfigMgr::getSignAttempt() Signature Check Passed!"; +std::cerr << std::endl; +#endif + + return true; + +} + +void p3ConfigMgr::addConfiguration(std::string file, pqiConfig *conf) +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + + /* construct filename */ + std::string filename = basedir; + if (basedir != "") + { + filename += "/"; + } + filename += file; + + conf->setFilename(filename); + configs[conf->Type()] = conf; +} + + +void p3ConfigMgr::completeConfiguration() +{ + saveConfiguration(); + + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + mConfigSaveActive = false; +} + +bool p3ConfigMgr::checkForGlobalSigConfig() +{ + bool oldTypeExists; + FILE *metaFile = NULL, *metaSig = NULL; + std::string fName = basedir + "/" + metafname; + std::string sigName = basedir + "/" + metasigfname; + + metaFile = RsDirUtil::rs_fopen(fName.c_str(), "r"); + metaSig = RsDirUtil::rs_fopen(sigName.c_str(), "r"); + + // check if files exist + if((metaFile != NULL) && (metaSig != NULL)) + { + oldTypeExists = true; + fclose(metaFile); + fclose(metaSig); + } + else + oldTypeExists = false; + + + + return oldTypeExists; + + +} + +p3Config::p3Config(uint32_t t) + :pqiConfig(t) +{ + return; +} + + +bool p3Config::loadConfiguration(std::string &loadHash) +{ + if(globalConfigType) + return loadGlobalConfig(loadHash); + else + return loadConfig(); +} + +bool p3Config::loadConfig() +{ + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadConfig() loading Configuration\n File: " << Filename() << std::endl; +#endif + + bool pass = true; + std::string cfgFname = Filename(); + std::string cfgFnameBackup = cfgFname + ".tmp"; + + std::string signFname = Filename() +".sgn"; + std::string signFnameBackup = signFname + ".tmp"; + + std::list load; + std::list::iterator it; + + // try 1st attempt + if(!loadAttempt(cfgFname, signFname, load)) + { + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadConfig() Failed to Load" << std::endl; +#endif + + /* bad load */ + for(it = load.begin(); it != load.end(); it++) + { + delete (*it); + } + pass = false; + + load.clear(); + } + + // try 2nd attempt with backup files if first failed + if(!pass) + { + if(!loadAttempt(cfgFnameBackup, signFnameBackup, load)) + { + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadConfig() Failed on 2nd Pass" << std::endl; +#endif + + /* bad load */ + for(it = load.begin(); it != load.end(); it++) + { + delete (*it); + } + pass = false; + } + pass = true; + } + + + + if(pass) + loadList(load); + else + return false; + + return pass; +} + +bool p3Config::loadAttempt(const std::string& cfgFname,const std::string& signFname, std::list& load) +{ + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadAttempt() \nFilename: " << cfgFname << std::endl; +#endif + + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_READABLE; + uint32_t stream_flags = BIN_FLAGS_READABLE; + + BinEncryptedFileInterface *bio = new BinEncryptedFileInterface(cfgFname.c_str(), bioflags); + pqiSSLstore stream(setupSerialiser(), "CONFIG", bio, stream_flags); + + if(!stream.getEncryptedItems(load)) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadAttempt() Error occurred trying to load Item" << std::endl; +#endif + return false; + } + + /* set hash */ + setHash(bio->gethash()); + + BinMemInterface *signbio = new BinMemInterface(1000, BIN_FLAGS_READABLE); + + if(!signbio->readfromfile(signFname.c_str())) + return false; + + std::string signatureStored((char *) signbio->memptr(), signbio->memsize()); + + std::string signatureRead; + std::string strHash(Hash()); + AuthSSL::getAuthSSL()->SignData(strHash.c_str(), strHash.length(), signatureRead); + + if(signatureRead != signatureStored) + return false; + + delete signbio; + + return true; +} + +bool p3Config::loadGlobalConfig(std::string &loadHash) +{ + bool pass = false; + std::string cfg_fname = Filename(); + std::string cfg_fname_backup = cfg_fname + ".tmp"; + std::string hashstr; + std::list load; + +#ifdef CONFIG_DEBUG + std::string success_fname = cfg_fname; + std::cerr << "p3Config::loadConfiguration(): Attempting to load configuration file" << cfg_fname << std::endl; +#endif + + pass = getHashAttempt(loadHash, hashstr, cfg_fname, load); + + if(!pass){ + load.clear(); + pass = getHashAttempt(loadHash, hashstr, cfg_fname_backup, load); +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadConfiguration() ERROR: Failed to get Hash from " << success_fname << std::endl; + success_fname = cfg_fname_backup; +#endif + + if(!pass){ +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadConfiguration() ERROR: Failed to get Hash from " << success_fname << std::endl; +#endif + return false; + } + } + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadConfiguration(): SUCCESS: configuration file loaded" << success_fname << std::endl; +#endif + + setHash(hashstr); + return loadList(load); +} + + + + +bool p3Config::getHashAttempt(const std::string& loadHash, std::string& hashstr,const std::string& cfg_fname, + std::list& load){ + + std::list::iterator it; + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_READABLE; + uint32_t stream_flags = BIN_FLAGS_READABLE; + + BinInterface *bio = new BinFileInterface(cfg_fname.c_str(), bioflags); + PQInterface *stream = NULL; + + std::string tempString, msgConfigFileName; + std::string filename = Filename() ; + std::string::reverse_iterator rit = filename.rbegin(); + + + // get the msgconfig file name + for(int i =0; (i <= 7) && (rit != filename.rend()); i++) + { + tempString.push_back(*rit); + rit++; + } + + rit = tempString.rbegin(); + + for(; rit !=tempString.rend(); rit++) + msgConfigFileName.push_back(*rit); + + if(msgConfigFileName == "msgs.cfg") + stream = new pqiarchive(setupSerialiser(), bio, bioflags); + else + stream = new pqistore(setupSerialiser(), "CONFIG", bio, bioflags); + + RsItem *item = NULL; + + while(NULL != (item = stream->GetItem())) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadConfiguration() loaded item:"; + std::cerr << std::endl; + item->print(std::cerr, 0); + std::cerr << std::endl; +#endif + load.push_back(item); + } + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadConfiguration() loaded " << load.size(); + std::cerr << " Elements from File: " << cfg_fname; + std::cerr << std::endl; +#endif + + /* check hash */ + hashstr = bio->gethash(); + + // if hash then atmpt load with temporary file + if (hashstr != loadHash) + { + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::loadConfiguration() ERROR: Hash != MATCHloaded"; + std::cerr << std::endl; +#endif + + /* bad load */ + for(it = load.begin(); it != load.end(); it++) + { + delete (*it); + } + + setHash(""); + + return false; + } + + delete stream; + return true; +} + + +bool p3Config::saveConfiguration() +{ + return saveConfig(); +} + +bool p3Config::saveConfig() +{ + + bool cleanup = true; + std::list toSave; + saveList(cleanup, toSave); + + // temporarily append new to files as these will replace current configuration + std::string newCfgFname = Filename() + "_new"; + std::string newSignFname = Filename() + ".sgn" + "_new"; + + std::string tmpCfgFname = Filename() + ".tmp"; + std::string tmpSignFname = Filename() + ".sgn" + ".tmp"; + + std::string cfgFname = Filename(); + std::string signFname = Filename() + ".sgn"; + + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_WRITEABLE; + uint32_t stream_flags = BIN_FLAGS_WRITEABLE; + bool written = true; + + if (!cleanup) + stream_flags |= BIN_FLAGS_NO_DELETE; + + BinEncryptedFileInterface *cfg_bio = new BinEncryptedFileInterface(newCfgFname.c_str(), bioflags); + pqiSSLstore *stream = new pqiSSLstore(setupSerialiser(), "CONFIG", cfg_bio, stream_flags); + + written = written && stream->encryptedSendItems(toSave); + + /* store the hash */ + setHash(cfg_bio->gethash()); + + // bio is taken care of in stream's destructor, also forces file to close + delete stream; + + /* sign data */ + std::string signature; + std::string strHash(Hash()); + AuthSSL::getAuthSSL()->SignData(strHash.c_str(),strHash.length(), signature); + + /* write signature to configuration */ + BinMemInterface *signbio = new BinMemInterface(signature.c_str(), + signature.length(), BIN_FLAGS_READABLE); + + signbio->writetofile(newSignFname.c_str()); + + delete signbio; + + // now rewrite current files to temp files + // rename back-up to current file + if(!RsDirUtil::renameFile(cfgFname, tmpCfgFname) || !RsDirUtil::renameFile(signFname, tmpSignFname)){ +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() Failed to rename backup meta files: " << std::endl + << cfgFname << " to " << tmpCfgFname << std::endl + << signFname << " to " << tmpSignFname << std::endl; +#endif + written = false; + } + + + + // now rewrite current files to temp files + // rename back-up to current file + if(!RsDirUtil::renameFile(newCfgFname, cfgFname) || !RsDirUtil::renameFile(newSignFname, signFname)){ + #ifdef CONFIG_DEBUG + std::cerr << "p3Config::() Failed to rename meta files: " << std::endl + << newCfgFname << " to " << cfgFname << std::endl + << newSignFname << " to " << signFname << std::endl; + #endif + + written = false; + } + + + + saveDone(); // callback to inherited class to unlock any Mutexes protecting saveList() data + + return written; + +} + + +bool p3Config::saveGlobalConfig() +{ + + bool cleanup = true; + std::list toSave; + saveList(cleanup, toSave); + + + std::string cfg_fname = Filename(); // get configuration file name + std::string cfg_fname_backup = Filename()+".tmp"; // backup file for two pass save + +#ifdef CONFIG_DEBUG + std::cerr << "Writting p3config file " << cfg_fname << std::endl ; + std::cerr << "p3Config::saveConfiguration() toSave " << toSave.size(); + std::cerr << " Elements to File: " << cfg_fname; + std::cerr << std::endl; +#endif + + // saves current config and keeps back-up (old configuration) + if(!backedUpFileSave(cfg_fname, cfg_fname_backup, toSave, cleanup)){ +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::saveConfiguration(): Failed to save file" << std::endl; +#endif + return false; + } + + saveDone(); // callback to inherited class to unlock any Mutexes protecting saveList() data + + return true; +} + + +bool p3Config::backedUpFileSave(const std::string& cfg_fname, const std::string& cfg_fname_backup, std::list& itemList, + bool cleanup){ + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_WRITEABLE; + uint32_t stream_flags = BIN_FLAGS_WRITEABLE; + bool written = true; + FILE* cfg_file = NULL; + char* buff=NULL; + int size_file = 0; + + if (!cleanup) + stream_flags |= BIN_FLAGS_NO_DELETE; + + BinInterface *bio = new BinFileInterface(cfg_fname_backup.c_str(), bioflags); + pqistore *stream = new pqistore(setupSerialiser(), "CONFIG", bio, stream_flags); + + std::list::iterator it; + + for(it = itemList.begin(); it != itemList.end(); it++) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() save item:"; + std::cerr << std::endl; + (*it)->print(std::cerr, 0); + std::cerr << std::endl; +#endif + written = written && stream->SendItem(*it); + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() saved "; +#endif + + } + + /* store the hash */ + setHash(bio->gethash()); + + // bio is taken care of in stream's destructor + delete stream; + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() Save file and keeps a back up " << std::endl; +#endif + + // open file from which to collect buffer + cfg_file = RsDirUtil::rs_fopen(cfg_fname.c_str(), "rb"); + + // if it fails to open, create file,but back-up file will now be empty + if(cfg_file == NULL){ + #ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() fopen failed for file: " << cfg_fname << std::endl; + #endif + + cfg_file = RsDirUtil::rs_fopen(cfg_fname.c_str(), "wb"); + + if(cfg_file == NULL) + { + std::cerr << "p3Config::backedUpFileSave() fopen failed for file:" << cfg_fname << std::endl; + return false ; + } + } + + //determine file size + fseek(cfg_file, 0L, SEEK_END); + size_file = ftell(cfg_file); + + if(size_file < 0) // ftell returns -1 when fails + { + fclose(cfg_file); + size_file = 0 ; + } + + fseek(cfg_file, 0L, SEEK_SET); + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave(): Size of file: " << size_file << std::endl; +#endif + + // no point continuing, empty files all have same hash + if(size_file > 0){ + + //read this into a data buffer + buff = new char[size_file]; + fread(buff, 1, size_file, cfg_file); + } + + fclose(cfg_file); + + // rename back-up to current file, if this fails should return false hash's will not match at startup + if(!RsDirUtil::renameFile(cfg_fname_backup, cfg_fname)){ +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() Failed to rename file" << cfg_fname_backup << " to " + << cfg_fname << std::endl; +#endif + written &= false; // at least one file save should be successful + } + + if(size_file > 0) + { + + // now write actual back-up file + cfg_file = RsDirUtil::rs_fopen(cfg_fname_backup.c_str(), "wb"); + + if(cfg_file == NULL){ +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() fopen failed for file: " << cfg_fname_backup << std::endl; +#endif + } + + if(size_file != fwrite(buff, 1, size_file, cfg_file)) + { + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "Write error", "Error while writing backup configuration file " + cfg_fname_backup + "\nIs your disc full or out of quota ?"); + fclose(cfg_file); + return false ; + } + + + fclose(cfg_file); + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() finished backed up save. " << std::endl; +#endif + + + delete[] buff; + written |= true; // either backup or current file should have been saved + } + + +#ifdef CONFIG_DEBUG + std::cerr << "p3Config::backedUpFileSave() finished backed up save. " << std::endl; +#endif + + return written; +} + + +/**************************** CONFIGURATION CLASSES ********************/ + +p3GeneralConfig::p3GeneralConfig() + :p3Config(CONFIG_TYPE_GENERAL) +{ + return; +} + + // General Configuration System +std::string p3GeneralConfig::getSetting(std::string opt) +{ +#ifdef CONFIG_DEBUG + std::cerr << "p3GeneralConfig::getSetting(" << opt << ")"; + std::cerr << std::endl; +#endif + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + + /* extract from config */ + std::map::iterator it; + if (settings.end() == (it = settings.find(opt))) + { + std::string nullstring; + return nullstring; + } + return it->second; +} + +void p3GeneralConfig::setSetting(std::string opt, std::string val) +{ +#ifdef CONFIG_DEBUG + std::cerr << "p3GeneralConfig::setSetting(" << opt << " = " << val << ")"; + std::cerr << std::endl; +#endif + { + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + + /* extract from config */ + std::map::iterator it; + if (settings.end() != (it = settings.find(opt))) + { + if (it->second == val) + { + /* no change */ + return; + } + } + + settings[opt] = val; + } + /* outside mutex */ + IndicateConfigChanged(); + + return; +} + +RsSerialiser *p3GeneralConfig::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsGeneralConfigSerialiser()); + return rss; +} + +bool p3GeneralConfig::saveList(bool &cleanup, std::list& savelist) +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + +#ifdef CONFIG_DEBUG + std::cerr << "p3GeneralConfig::saveList() KV sets: " << settings.size(); + std::cerr << std::endl; +#endif + + cleanup = true; + + + RsConfigKeyValueSet *item = new RsConfigKeyValueSet(); + std::map::iterator it; + for(it = settings.begin(); it != settings.end(); it++) + { + RsTlvKeyValue kv; + kv.key = it->first; + kv.value = it->second; + item->tlvkvs.pairs.push_back(kv); + + /* make sure we don't overload it */ + if (item->tlvkvs.TlvSize() > 4000) + { + savelist.push_back(item); + item = new RsConfigKeyValueSet(); + } + } + + if (item->tlvkvs.pairs.size() > 0) + { + savelist.push_back(item); + } + + return true; +} + + +bool p3GeneralConfig::loadList(std::list& load) +{ +#ifdef CONFIG_DEBUG + std::cerr << "p3GeneralConfig::loadList() count: " << load.size(); + std::cerr << std::endl; +#endif + + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + + /* add into settings */ + RsConfigKeyValueSet *item = NULL; + std::list::iterator it; + std::list::iterator kit; + + for(it = load.begin(); it != load.end();) + { + item = dynamic_cast(*it); + if (item) + { + for(kit = item->tlvkvs.pairs.begin(); + kit != item->tlvkvs.pairs.end(); kit++) + { + settings[kit->key] = kit->value; + } + } + + /* cleanup */ + delete (*it); + it = load.erase(it); + } + + return true; +} + + +/**** MUTEX NOTE: + * have protected all, but think that + * only the Indication and hash really need it + */ + +bool pqiConfig::globalConfigType = false; + +pqiConfig::pqiConfig(uint32_t t) + :ConfInd(2), type(t) +{ + return; +} + +pqiConfig::~pqiConfig() +{ + return; +} + +uint32_t pqiConfig::Type() +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + return type; +} + +const std::string& pqiConfig::Filename() +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + return filename; +} + +const std::string& pqiConfig::Hash() +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + return hash; +} + +void pqiConfig::IndicateConfigChanged() +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + ConfInd.IndicateChanged(); +} + +bool pqiConfig::HasConfigChanged(uint16_t idx) +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + return ConfInd.Changed(idx); +} + +void pqiConfig::setFilename(std::string name) +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + filename = name; +} + +void pqiConfig::setHash(std::string h) +{ + RsStackMutex stack(cfgMtx); /***** LOCK STACK MUTEX ****/ + hash = h; +} + diff --git a/libretroshare/src/pqi/p3cfgmgr.h b/libretroshare/src/pqi/p3cfgmgr.h new file mode 100644 index 000000000..5ddcf7f9b --- /dev/null +++ b/libretroshare/src/pqi/p3cfgmgr.h @@ -0,0 +1,403 @@ +/* + * libretroshare/src/pqi: p3cfgmgr.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef P3_CONFIG_MGR_HEADER +#define P3_CONFIG_MGR_HEADER + +#include +#include + +#include "pqi/pqi_base.h" +#include "pqi/pqiindic.h" +#include "pqi/pqinetwork.h" +#include "util/rsthreads.h" +#include "pqi/pqibin.h" + +/***** Configuration Management ***** + * + * we need to store: + * (1) Certificates. + * (2) List of Friends / Net Configuration + * (3) Stun List. / DHT peers. + * (4) general config. + * + * + * At top level we need: + * + * - type / filename / size / hash - + * and the file signed... + * + * + */ + +/**** THESE are STORED in CONFIGURATION FILES.... + * Cannot be changed + * + *********************/ + +const uint32_t CONFIG_TYPE_GENERAL = 0x0001; +const uint32_t CONFIG_TYPE_PEERS = 0x0002; +const uint32_t CONFIG_TYPE_FSERVER = 0x0003; +const uint32_t CONFIG_TYPE_MSGS = 0x0004; +const uint32_t CONFIG_TYPE_CACHE_OLDID = 0x0005; +const uint32_t CONFIG_TYPE_AUTHGPG = 0x006; + +const uint32_t CONFIG_TYPE_P3DISC = 0x00B; +const uint32_t CONFIG_TYPE_AUTHSSL = 0x00C; + + +/* new FileTransfer */ +const uint32_t CONFIG_TYPE_FT_SHARED = 0x0007; +const uint32_t CONFIG_TYPE_FT_EXTRA_LIST= 0x0008; +const uint32_t CONFIG_TYPE_FT_CONTROL = 0x0009; +const uint32_t CONFIG_TYPE_FT_DWLQUEUE = 0x000A; + +/// turtle router +const uint32_t CONFIG_TYPE_TURTLE = 0x0020; + +/* wish these ids where higher... + * may move when switch to v0.5 + */ +const uint32_t CONFIG_TYPE_CHAT = 0x0012; +const uint32_t CONFIG_TYPE_STATUS = 0x0013; + +/* standard services */ +const uint32_t CONFIG_TYPE_QBLOG = 0x0101; +const uint32_t CONFIG_TYPE_FORUMS = 0x0102; +const uint32_t CONFIG_TYPE_CHANNELS = 0x0103; + +/* CACHE ID Must be at the END so that other configurations + * are loaded First (Cache Config --> Cache Loading) + */ +const uint32_t CONFIG_TYPE_CACHE = 0xff01; + +class p3ConfigMgr; + + + +//! abstract class for configuration saving +/*! + * Aim is that active objects in retroshare can dervie from this class + * and implement their method of saving and loading their configuration + */ +class pqiConfig +{ + public: + pqiConfig(uint32_t t); +virtual ~pqiConfig(); + +/** + * loads configuration of object + * @param loadHash This is the hash that will be compared to confirm saved configuration has not + * been tampered with + */ +virtual bool loadConfiguration(std::string &loadHash) = 0; + +/** + * save configuration of object + */ +virtual bool saveConfiguration() = 0; + +/** + * The type of configuration, see ids where this class is declared + * @see p3cfgmgr.h + */ +uint32_t Type(); + +/** + * The name of the configuration file + */ +const std::string& Filename(); + +/** + * The hash computed for this configuration, can use this to compare to externally stored hash + * for validation checking + */ +const std::string& Hash(); + + protected: + +/** + * Checks if configuration has changed + */ +void IndicateConfigChanged(); +void setHash(std::string h); + + RsMutex cfgMtx; + + static bool globalConfigType; + + private: + + /** + * This sets the name of the pqi configuation file + */ + void setFilename(std::string name); + + /** + * @param an index for the Confind which contains list of configuarations that can be tracked + */ + bool HasConfigChanged(uint16_t idx); + + Indicator ConfInd; + + uint32_t type; + std::string filename; + std::string hash; + + + friend class p3ConfigMgr; + /* so it can access: + * setFilename() and HasConfigChanged() + */ + + +}; + + + +/***********************************************************************************************/ + +/*! + * MUTEX NOTE + * Class data is protected by mutex's so that anyone can call these + * functions, at any time. + */ + +class p3ConfigMgr +{ + public: + + /** + * @param bdir base directory: where config files will be saved + * @param fname file name for global configuration + * @param signame file name for global signature + */ + p3ConfigMgr(std::string bdir, std::string fname, std::string signame); + + /** + * checks and update all added configurations + * @see rsserver + */ + void tick(); + + /** + * save all added configuation including configuration files + * creates global signature file + */ + void saveConfiguration(); + + /** + * loads all configurations + */ + void loadConfiguration(); + + /** + * @param file The name for new configuration + * @param conf to the configuration to use + */ + void addConfiguration(std::string file, pqiConfig *conf); + + /* saves config, and disables further saving + * used for exiting the system + */ + void completeConfiguration(); + + + + private: + + /** + * this checks for the global config file and signature and determines class's mode of operation + * @return global file rs-v0.#.cfg and rs-v0.#.sgn are present + * @deprecated + */ + bool checkForGlobalSigConfig(); + + /** + * removes theoldconfiguration type + * @deprecated + */ + void removeOldConfigType(); + + /** + * to save old style global-signature configuration files + * @deprecated + */ + void globalSaveConfig(); + + /** + * to load up old style global-signature config files + * @deprecated + */ + void globalLoadConfig(); + + /** + * saves configuration of pqiconfigs in object configs + */ + void saveConfig(); + + /** + * + */ + void loadConfig(); + + /** + * checks if signature and configuration file's signature matches + * @return false if signature file does not match configuration file's signature + */ + bool getSignAttempt(std::string& metaConfigFname, std::string& metaSignFname, BinMemInterface* membio); + + /** + * takes current configuration which is stored in back-up file, and moves it to actual config file + * then stores data that was in actual config file into back-up, Corresponding signatures and handled + * simlarly in parallel + *@param fname the name of the first configuration file checked + *@param fname_backup the seconf file, backup, checked if first file does not exist or is corrupted + *@param sign file name in which signature is kept + *@param sign_backup file name in which signature which correspond to backup config is kept + *@param configbio to write config to file + *@param signbio to write signature config to file + */ + bool backedUpFileSave(const std::string& fname, const std::string& fname_backup,const std::string& sign, + const std::string& sign_backup, BinMemInterface* configbio, BinMemInterface* signbio); + +const std::string basedir; +const std::string metafname; +const std::string metasigfname; + + RsMutex cfgMtx; /* below is protected */ + +bool oldConfigType; +bool mConfigSaveActive; +std::map configs; +}; + + + +/***************************************************************************************************/ + + +//! abstract class for configuration saving, aimed at rs services that uses RsItem config data +/*! + * The aim of this class is to provide a way for rs services and object to save particular + * configurations an items (and load them up as well). + */ +class p3Config: public pqiConfig +{ + public: + + p3Config(uint32_t t); + +virtual bool loadConfiguration(std::string &loadHash); +virtual bool saveConfiguration(); + + + protected: + + /* Key Functions to be overloaded for Full Configuration */ +virtual RsSerialiser *setupSerialiser() = 0; + +/** + * saves list of derived object + * @param cleanup this inform you if you need to call saveDone() to unlock/allow + * access to resources pointed to by handles (list) returned by function: thus false, call saveDone after returned list finished with + * and vice versa + * @return list of config items derived object wants to saves + */ +virtual bool saveList(bool &cleanup, std::list&) = 0; + +/** + * loads up list of configs items for derived object + * @param load list of config items to load up + */ +virtual bool loadList(std::list& load) = 0; + +/** + * callback for mutex unlocking + * in derived classes (should only be needed if cleanup = false) + */ +virtual void saveDone() { return; } + +private: + +/** + * takes current configuration which is stored in back-up file, and moves it to actual config file + * then stores data that was in actual config file into back-up, This is an rs specific solution + * @param fname the name of the first configuration file checked + * @param fname_backup the seconf file, backup, checked if first file does not exist or is corrupted + */ +bool backedUpFileSave(const std::string& fname, const std::string& fname_backup, std::list& toSave, + bool cleanup); + +/* + * for retrieving hash files + */ +bool getHashAttempt(const std::string& loadHash, std::string& hashstr, const std::string& fname, std::list& load); + +bool loadConfig(); +bool saveConfig(); + +bool loadGlobalConfig(std::string& hash); +bool saveGlobalConfig(); + +bool loadAttempt(const std::string&,const std::string&, std::list& load); + +}; /* end of p3Config */ + + +class p3GeneralConfig: public p3Config +{ + public: + p3GeneralConfig(); + +// General Configuration System +std::string getSetting(std::string opt); +void setSetting(std::string opt, std::string val); + + protected: + + /* Key Functions to be overloaded for Full Configuration */ +virtual RsSerialiser *setupSerialiser(); +virtual bool saveList(bool &cleanup, std::list&); +virtual bool loadList(std::list& ); + + private: + + /* protected by pqiConfig mutex as well! */ +std::map settings; + + +}; + + + + + + + +#endif // P3_CONFIG_MGR_HEADER diff --git a/libretroshare/src/pqi/p3connmgr.cc b/libretroshare/src/pqi/p3connmgr.cc new file mode 100644 index 000000000..54435079a --- /dev/null +++ b/libretroshare/src/pqi/p3connmgr.cc @@ -0,0 +1,4180 @@ +/* + * libretroshare/src/pqi: p3connmgr.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/authssl.h" +#include "pqi/p3connmgr.h" +#include "pqi/p3dhtmgr.h" // Only need it for constants. +#include "tcponudp/tou.h" +#include "util/extaddrfinder.h" +#include "util/dnsresolver.h" +#include "util/rsnet.h" +#include "pqi/authgpg.h" + + +#include "util/rsprint.h" +#include "util/rsdebug.h" +const int p3connectzone = 3431; + +#include "serialiser/rsconfigitems.h" +#include "pqi/pqinotify.h" +#include "retroshare/rsiface.h" + +#include + +/* Network setup States */ + +const uint32_t RS_NET_NEEDS_RESET = 0x0000; +const uint32_t RS_NET_UNKNOWN = 0x0001; +const uint32_t RS_NET_UPNP_INIT = 0x0002; +const uint32_t RS_NET_UPNP_SETUP = 0x0003; +const uint32_t RS_NET_EXT_SETUP = 0x0004; +const uint32_t RS_NET_DONE = 0x0005; +const uint32_t RS_NET_LOOPBACK = 0x0006; +const uint32_t RS_NET_DOWN = 0x0007; + +/* Stun modes (TODO) */ +const uint32_t RS_STUN_DHT = 0x0001; +const uint32_t RS_STUN_DONE = 0x0002; +const uint32_t RS_STUN_LIST_MIN = 100; +const uint32_t RS_STUN_FOUND_MIN = 10; + +const uint32_t MAX_UPNP_INIT = 60; /* seconds UPnP timeout */ +const uint32_t MAX_UPNP_COMPLETE = 600; /* 10 min... seems to take a while */ +const uint32_t MAX_NETWORK_INIT = 70; /* timeout before network reset */ + +const uint32_t MIN_TIME_BETWEEN_NET_RESET = 5; + +const uint32_t PEER_IP_CONNECT_STATE_MAX_LIST_SIZE = 4; + +/**** + * #define CONN_DEBUG 1 + * #define CONN_DEBUG_RESET 1 + * #define CONN_DEBUG_TICK 1 + ***/ + +/**** + * #define P3CONNMGR_NO_TCP_CONNECTIONS 1 + ***/ +/**** + * #define P3CONNMGR_NO_AUTO_CONNECTION 1 + ***/ + +const uint32_t P3CONNMGR_TCP_DEFAULT_DELAY = 3; /* 2 Seconds? is it be enough! */ +const uint32_t P3CONNMGR_UDP_DEFAULT_DELAY = 3; /* 2 Seconds? is it be enough! */ + +const uint32_t P3CONNMGR_TCP_DEFAULT_PERIOD = 10; +const uint32_t P3CONNMGR_UDP_DEFAULT_PERIOD = 40; + +#define MAX_AVAIL_PERIOD 230 //times a peer stay in available state when not connected +#define MIN_RETRY_PERIOD 140 + +#define MAX_RANDOM_ATTEMPT_OFFSET 6 // seconds. + +void printConnectState(std::ostream &out, peerConnectState &peer); + +peerConnectAddress::peerConnectAddress() + :delay(0), period(0), type(0), ts(0) +{ + sockaddr_clear(&addr); +} + + +peerAddrInfo::peerAddrInfo() + :found(false), type(0), ts(0) +{ +} + +peerConnectState::peerConnectState() + :id("unknown"), + gpg_id("unknown"), + netMode(RS_NET_MODE_UNKNOWN), visState(RS_VIS_STATE_STD), + lastcontact(0), + connecttype(0), + lastavailable(0), + lastattempt(0), + name(""), location(""), + state(0), actions(0), + source(0), + inConnAttempt(0) +{ + sockaddr_clear(¤tlocaladdr); + sockaddr_clear(¤tserveraddr); + + return; +} + +std::string textPeerConnectState(peerConnectState &state) +{ + std::ostringstream out; + out << "Id: " << state.id << std::endl; + out << "NetMode: " << state.netMode << std::endl; + out << "VisState: " << state.visState << std::endl; + out << "laddr: " << rs_inet_ntoa(state.currentlocaladdr.sin_addr) + << ":" << ntohs(state.currentlocaladdr.sin_port) << std::endl; + out << "eaddr: " << rs_inet_ntoa(state.currentserveraddr.sin_addr) + << ":" << ntohs(state.currentserveraddr.sin_port) << std::endl; + + std::string output = out.str(); + return output; +} + + +pqiNetStatus::pqiNetStatus() + :mLocalAddrOk(false), mExtAddrOk(false), mExtAddrStableOk(false), + mUpnpOk(false), mDhtOk(false), mResetReq(false) +{ + mDhtNetworkSize = 0; + mDhtRsNetworkSize = 0; + + sockaddr_clear(&mLocalAddr); + sockaddr_clear(&mExtAddr); + return; +} + + + +void pqiNetStatus::print(std::ostream &out) +{ + out << "pqiNetStatus: "; + out << "mLocalAddrOk: " << mLocalAddrOk; + out << " mExtAddrOk: " << mExtAddrOk; + out << " mExtAddrStableOk: " << mExtAddrStableOk; + out << std::endl; + out << " mUpnpOk: " << mUpnpOk; + out << " mDhtOk: " << mDhtOk; + out << " mResetReq: " << mResetReq; + out << std::endl; + out << "mDhtNetworkSize: " << mDhtNetworkSize << " mDhtRsNetworkSize: " << mDhtRsNetworkSize; + out << std::endl; + out << "mLocalAddr: " << rs_inet_ntoa(mLocalAddr.sin_addr) << ":" << ntohs(mLocalAddr.sin_port) << " "; + out << "mExtAddr: " << rs_inet_ntoa(mExtAddr.sin_addr) << ":" << ntohs(mExtAddr.sin_port) << " "; + out << " NetOk: " << NetOk(); + out << std::endl; +} + + +p3ConnectMgr::p3ConnectMgr() + :p3Config(CONFIG_TYPE_PEERS), + mNetStatus(RS_NET_UNKNOWN), + mStatusChanged(false) +{ + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* setup basics of own state */ + mOwnState.id = AuthSSL::getAuthSSL()->OwnId(); + mOwnState.gpg_id = AuthGPG::getAuthGPG()->getGPGOwnId(); + mOwnState.name = AuthGPG::getAuthGPG()->getGPGOwnName(); + mOwnState.location = AuthSSL::getAuthSSL()->getOwnLocation(); + mOwnState.netMode = RS_NET_MODE_UDP; + // user decided. + //mOwnState.netMode |= RS_NET_MODE_TRY_UPNP; + + mUseExtAddrFinder = true; + mAllowTunnelConnection = false; + mExtAddrFinder = new ExtAddrFinder; + mDNSResolver = new DNSResolver; + mNetInitTS = 0; + mRetryPeriod = MIN_RETRY_PERIOD; + + mNetFlags = pqiNetStatus(); + mOldNetFlags = pqiNetStatus(); + + lastGroupId = 1; + + /* setup Banned Ip Address - static for now + */ + + struct in_addr bip; + memset(&bip, 0, sizeof(bip)); + bip.s_addr = 1; + + mBannedIpList.push_back(bip); + } + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr() Startup" << std::endl; +#endif + + netReset(); + + return; +} + +bool p3ConnectMgr::getIPServersEnabled() +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + return mUseExtAddrFinder; +} + +void p3ConnectMgr::getIPServersList(std::list& ip_servers) +{ + mExtAddrFinder->getIPServersList(ip_servers); +} + +void p3ConnectMgr::setIPServersEnabled(bool b) +{ + bool changed = false; + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + if (mUseExtAddrFinder != b) + changed = true; + mUseExtAddrFinder = b; + } + + if (changed) + { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr: setIPServers to " << b << std::endl ; +#endif +} + +void p3ConnectMgr::setTunnelConnection(bool b) +{ + bool changed = false; + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + if (mAllowTunnelConnection != b) + changed = true; + + mAllowTunnelConnection = b; + } + + if (changed) + { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } +} + +bool p3ConnectMgr::getTunnelConnection() +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + return mAllowTunnelConnection; +} + +void p3ConnectMgr::setOwnNetConfig(uint32_t netMode, uint32_t visState) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + /* only change TRY flags */ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::setOwnNetConfig()" << std::endl; + std::cerr << "Existing netMode: " << mOwnState.netMode << " vis: " << mOwnState.visState; + std::cerr << std::endl; + std::cerr << "Input netMode: " << netMode << " vis: " << visState; + std::cerr << std::endl; +#endif + mOwnState.netMode &= ~(RS_NET_MODE_TRYMODE); + +#ifdef CONN_DEBUG + std::cerr << "After Clear netMode: " << mOwnState.netMode << " vis: " << mOwnState.visState; + std::cerr << std::endl; +#endif + + switch(netMode & RS_NET_MODE_ACTUAL) + { + case RS_NET_MODE_EXT: + mOwnState.netMode |= RS_NET_MODE_TRY_EXT; + break; + case RS_NET_MODE_UPNP: + mOwnState.netMode |= RS_NET_MODE_TRY_UPNP; + break; + default: + case RS_NET_MODE_UDP: + mOwnState.netMode |= RS_NET_MODE_TRY_UDP; + break; + } + + mOwnState.visState = visState; + +#ifdef CONN_DEBUG + std::cerr << "Final netMode: " << mOwnState.netMode << " vis: " << mOwnState.visState; + std::cerr << std::endl; +#endif + + /* if we've started up - then tweak Dht On/Off */ + if (mNetStatus != RS_NET_UNKNOWN) + { + enableNetAssistConnect(!(mOwnState.visState & RS_VIS_STATE_NODHT)); + } + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ +} + + +/***** Framework / initial implementation for a connection manager. + * + * This needs a state machine for Initialisation. + * + * Network state: + * RS_NET_UNKNOWN + * RS_NET_EXT_UNKNOWN * forwarded port (but Unknown Ext IP) * + * RS_NET_EXT_KNOWN * forwarded port with known IP/Port. * + * + * RS_NET_UPNP_CHECK * checking for UPnP * + * RS_NET_UPNP_KNOWN * confirmed UPnP ext Ip/port * + * + * RS_NET_UDP_UNKNOWN * not Ext/UPnP - to determine Ext IP/Port * + * RS_NET_UDP_KNOWN * have Stunned for Ext Addr * + * + * Transitions: + * + * RS_NET_UNKNOWN -(config)-> RS_NET_EXT_UNKNOWN + * RS_NET_UNKNOWN -(config)-> RS_NET_UPNP_UNKNOWN + * RS_NET_UNKNOWN -(config)-> RS_NET_UDP_UNKNOWN + * + * RS_NET_EXT_UNKNOWN -(DHT(ip)/Stun)-> RS_NET_EXT_KNOWN + * + * RS_NET_UPNP_UNKNOWN -(Upnp)-> RS_NET_UPNP_KNOWN + * RS_NET_UPNP_UNKNOWN -(timout/Upnp)-> RS_NET_UDP_UNKNOWN + * + * RS_NET_UDP_UNKNOWN -(stun)-> RS_NET_UDP_KNOWN + * + * + * STUN state: + * RS_STUN_INIT * done nothing * + * RS_STUN_DHT * looking up peers * + * RS_STUN_DONE * found active peer and stunned * + * + * + * Steps. + ******************************************************************* + * (1) Startup. + * - UDP port setup. + * - DHT setup. + * - Get Stun Keys -> add to DHT. + * - Feedback from DHT -> ask UDP to stun. + * + * (1) determine Network mode. + * If external Port.... Done: + * (2) + ******************************************************************* + * Stable operation: + * (1) tick and check peers. + * (2) handle callback. + * (3) notify of new/failed connections. + * + * + */ + +/* Called to reseet the whole network stack. this call is + * triggered by udp stun address tracking. + * + * must: + * - reset UPnP and DHT. + * - + */ + +void p3ConnectMgr::netReset() +{ + //don't do a net reset if the MIN_TIME_BETWEEN_NET_RESET is not reached +#if 0 + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + time_t delta = time(NULL) - mNetInitTS; + #ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr time since last reset : " << delta << std::endl; + #endif + if (delta < (time_t)MIN_TIME_BETWEEN_NET_RESET) + { + mNetStatus = RS_NET_NEEDS_RESET; + #ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netStartup() don't do a net reset if the MIN_TIME_BETWEEN_NET_RESET is not reached" << std::endl; + #endif + return; + } + } +#endif + +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netReset() Called" << std::endl; +#endif + + shutdown(); /* blocking shutdown call */ + + // Will initiate a new call for determining the external ip. + if (mUseExtAddrFinder) + { +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netReset() restarting AddrFinder" << std::endl; +#endif + mExtAddrFinder->reset() ; + } + else + { +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netReset() ExtAddrFinder Disabled" << std::endl; +#endif + } + +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netReset() resetting NetStatus" << std::endl; +#endif + + /* reset udp network - handled by tou_init! */ + /* reset tcp network - if necessary */ + { + /* NOTE: nNetListeners should be protected via the Mutex. + * HOWEVER, as we NEVER change this list - once its setup + * we can get away without it - and assume its constant. + * + * NB: (*it)->reset_listener must be out of the mutex, + * as it calls back to p3ConnMgr. + */ + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + struct sockaddr_in iaddr = mOwnState.currentlocaladdr; + +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netReset() resetting listeners" << std::endl; +#endif + std::list::const_iterator it; + for(it = mNetListeners.begin(); it != mNetListeners.end(); it++) + { + (*it)->resetListener(iaddr); +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netReset() reset listener" << std::endl; +#endif + } + } + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + mNetStatus = RS_NET_UNKNOWN; + netStatusReset_locked(); + } + + /* check Network Address. This happens later */ + //checkNetAddress(); + +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netReset() done" << std::endl; +#endif +} + + +/* to allow resets of network stuff */ +void p3ConnectMgr::addNetListener(pqiNetListener *listener) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + mNetListeners.push_back(listener); +} + +void p3ConnectMgr::netStatusReset_locked() +{ + //std::cerr << "p3ConnectMgr::netStatusReset()" << std::endl;; + + mNetFlags = pqiNetStatus(); + //oldNetFlags = pqiNetStatus(); + //IndicateConfigChanged(); +} + +void p3ConnectMgr::netStartup() +{ + /* startup stuff */ + + /* StunInit gets a list of peers, and asks the DHT to find them... + * This is needed for all systems so startup straight away + */ +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netStartup()" << std::endl; +#endif + + netDhtInit(); + netUdpInit(); + + /* decide which net setup mode we're going into + */ + + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + mNetInitTS = time(NULL); + netStatusReset_locked(); + +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netStartup() resetting mNetInitTS / Status" << std::endl; +#endif + mOwnState.netMode &= ~(RS_NET_MODE_ACTUAL); + + switch(mOwnState.netMode & RS_NET_MODE_TRYMODE) + { + + case RS_NET_MODE_TRY_EXT: /* v similar to UDP */ +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netStartup() TRY_EXT mode"; + std::cerr << std::endl; +#endif + mOwnState.netMode |= RS_NET_MODE_EXT; + mNetStatus = RS_NET_EXT_SETUP; + break; + + case RS_NET_MODE_TRY_UDP: +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netStartup() TRY_UDP mode"; + std::cerr << std::endl; +#endif + mOwnState.netMode |= RS_NET_MODE_UDP; + mNetStatus = RS_NET_EXT_SETUP; + break; + + default: // Fall through. + +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netStartup() UNKNOWN mode"; + std::cerr << std::endl; +#endif + + case RS_NET_MODE_TRY_UPNP: +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::netStartup() TRY_UPNP mode"; + std::cerr << std::endl; +#endif + /* Force it here (could be default!) */ + mOwnState.netMode |= RS_NET_MODE_TRY_UPNP; + mOwnState.netMode |= RS_NET_MODE_UDP; /* set to UDP, upgraded is UPnP is Okay */ + mNetStatus = RS_NET_UPNP_INIT; + break; + } +} + + +void p3ConnectMgr::tick() +{ + netTick(); + statusTick(); + tickMonitors(); + + static time_t last_friends_check = time(NULL) ; + static const time_t INTERVAL_BETWEEN_LOCATION_CLEANING = 600 ; // Remove unused locations every 10 minutes. + + time_t now = time(NULL) ; + + if(now > last_friends_check + INTERVAL_BETWEEN_LOCATION_CLEANING && rsPeers != NULL) + { + std::cerr << "p3ConnectMgr::tick(): cleaning unused locations." << std::endl ; + + rsPeers->cleanUnusedLocations() ; + last_friends_check = now ; + } +} + +bool p3ConnectMgr::shutdown() /* blocking shutdown call */ +{ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::shutdown()"; + std::cerr << std::endl; +#endif + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + mNetStatus = RS_NET_UNKNOWN; + mNetInitTS = time(NULL); + netStatusReset_locked(); + } + netAssistFirewallShutdown(); + netAssistConnectShutdown(); + + return true; +} + + +void p3ConnectMgr::statusTick() +{ + /* iterate through peers ... + * if been available for long time ... remove flag + * if last attempt a while - retryConnect. + * etc. + */ + +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::statusTick()" << std::endl; +#endif + std::list retryIds; + std::list::iterator it2; + //std::list dummyToRemove; + + { + time_t now = time(NULL); + time_t oldavail = now - MAX_AVAIL_PERIOD; + time_t retry = now - mRetryPeriod; + + RsStackMutex stack(connMtx); /****** LOCK MUTEX ******/ + std::map::iterator it; + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + if (it->second.state & RS_PEER_S_CONNECTED) + { + continue; + } + + if ((it->second.state & RS_PEER_S_ONLINE) && + (it->second.lastavailable < oldavail)) + { +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::statusTick() ONLINE TIMEOUT for: "; + std::cerr << it->first; + std::cerr << std::endl; +#endif + it->second.state &= (~RS_PEER_S_ONLINE); + } + + if (it->second.lastattempt < retry) + { + retryIds.push_back(it->first); + } + } + } + +#ifndef P3CONNMGR_NO_AUTO_CONNECTION + + for(it2 = retryIds.begin(); it2 != retryIds.end(); it2++) + { +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::statusTick() RETRY TIMEOUT for: "; + std::cerr << *it2; + std::cerr << std::endl; +#endif + /* retry it! */ + retryConnect(*it2); + } + +#endif + +} + + +void p3ConnectMgr::netTick() +{ + +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::netTick()" << std::endl; +#endif + + // Check whether we are stuck on loopback. This happens if RS starts when + // the computer is not yet connected to the internet. In such a case we + // periodically check for a local net address. + // + checkNetAddress() ; + networkConsistencyCheck(); /* check consistency. If not consistent, do a reset inside networkConsistencyCheck() */ + + connMtx.lock(); /* LOCK MUTEX */ + + uint32_t netStatus = mNetStatus; + time_t age = time(NULL) - mNetInitTS; + + connMtx.unlock(); /* UNLOCK MUTEX */ + /* start tcp network - if necessary */ + + switch(netStatus) + { + case RS_NET_NEEDS_RESET: + +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netTick() STATUS: NEEDS_RESET" << std::endl; +#endif + netReset(); + break; + + case RS_NET_UNKNOWN: +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netTick() STATUS: UNKNOWN" << std::endl; +#endif + + /* add a small delay to stop restarting straight after a RESET + * This is so can we shutdown cleanly + */ +#define STARTUP_DELAY 5 + if (age < STARTUP_DELAY) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netTick() Delaying Startup" << std::endl; +#endif + } + else + { + netStartup(); + } + + break; + + case RS_NET_UPNP_INIT: +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netTick() STATUS: UPNP_INIT" << std::endl; +#endif + netUpnpInit(); + break; + + case RS_NET_UPNP_SETUP: +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netTick() STATUS: UPNP_SETUP" << std::endl; +#endif + netUpnpCheck(); + break; + + + case RS_NET_EXT_SETUP: +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netTick() STATUS: EXT_SETUP" << std::endl; +#endif + netExtCheck(); + //netDhtInit(); + break; + + case RS_NET_DONE: +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::netTick() STATUS: DONE" << std::endl; +#endif + + break; + + case RS_NET_LOOPBACK: + //don't do a shutdown because a client in a computer without local network might be usefull for debug. + //shutdown(); +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netTick() STATUS: RS_NET_LOOPBACK" << std::endl; +#endif + default: + break; + } + + return; +} + + +void p3ConnectMgr::netUdpInit() +{ + // All functionality has been moved elsewhere (pqiNetListener interface) +#if 0 +#if defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netUdpInit() Does nothing!" << std::endl; +#endif + connMtx.lock(); /* LOCK MUTEX */ + + struct sockaddr_in iaddr = mOwnState.currentlocaladdr; + + connMtx.unlock(); /* UNLOCK MUTEX */ + + /* udp port now controlled by udpstack (from libbitdht) */ + mUdpStack->resetAddress(iaddr); + /* open our udp port */ + tou_init((struct sockaddr *) &iaddr, sizeof(iaddr)); +#endif + +} + + +void p3ConnectMgr::netDhtInit() +{ +#if defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netDhtInit()" << std::endl; +#endif + connMtx.lock(); /* LOCK MUTEX */ + + uint32_t vs = mOwnState.visState; + + connMtx.unlock(); /* UNLOCK MUTEX */ + + enableNetAssistConnect(!(vs & RS_VIS_STATE_NODHT)); +} + + +void p3ConnectMgr::netUpnpInit() +{ +#if defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netUpnpInit()" << std::endl; +#endif + uint16_t eport, iport; + + connMtx.lock(); /* LOCK MUTEX */ + + /* get the ports from the configuration */ + + mNetStatus = RS_NET_UPNP_SETUP; + iport = ntohs(mOwnState.currentlocaladdr.sin_port); + eport = ntohs(mOwnState.currentserveraddr.sin_port); + if ((eport < 1000) || (eport > 30000)) + { + eport = iport; + } + + connMtx.unlock(); /* UNLOCK MUTEX */ + + netAssistFirewallPorts(iport, eport); + enableNetAssistFirewall(true); +} + +void p3ConnectMgr::netUpnpCheck() +{ + /* grab timestamp */ + connMtx.lock(); /* LOCK MUTEX */ + + time_t delta = time(NULL) - mNetInitTS; + +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netUpnpCheck() age: " << delta << std::endl; +#endif + + connMtx.unlock(); /* UNLOCK MUTEX */ + + struct sockaddr_in extAddr; + int upnpState = netAssistFirewallActive(); + + if (((upnpState == 0) && (delta > (time_t)MAX_UPNP_INIT)) || + ((upnpState > 0) && (delta > (time_t)MAX_UPNP_COMPLETE))) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netUpnpCheck() "; + std::cerr << "Upnp Check failed." << std::endl; +#endif + /* fallback to UDP startup */ + connMtx.lock(); /* LOCK MUTEX */ + + /* UPnP Failed us! */ + mNetStatus = RS_NET_EXT_SETUP; + mNetFlags.mUpnpOk = false; + + connMtx.unlock(); /* UNLOCK MUTEX */ + } + else if ((upnpState > 0) && netAssistExtAddress(extAddr)) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netUpnpCheck() "; + std::cerr << "Upnp Check success state: " << upnpState << std::endl; +#endif + /* switch to UDP startup */ + connMtx.lock(); /* LOCK MUTEX */ + + /* Set Net Status flags .... + * we now have external upnp address. Golden! + * don't set netOk flag until have seen some traffic. + */ + if (isValidNet(&(extAddr.sin_addr))) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netUpnpCheck() "; + std::cerr << "UpnpAddr: " << rs_inet_ntoa(extAddr.sin_addr); + std::cerr << ":" << ntohs(extAddr.sin_port); + std::cerr << std::endl; +#endif + mNetFlags.mUpnpOk = true; + mNetFlags.mExtAddr = extAddr; + mNetFlags.mExtAddrOk = true; + mNetFlags.mExtAddrStableOk = true; + + mNetStatus = RS_NET_EXT_SETUP; + /* Fix netMode & Clear others! */ + mOwnState.netMode = RS_NET_MODE_TRY_UPNP | RS_NET_MODE_UPNP; + } + connMtx.unlock(); /* UNLOCK MUTEX */ + } + else + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netUpnpCheck() "; + std::cerr << "Upnp Check Continues: status: " << upnpState << std::endl; +#endif + } + +} + + +void p3ConnectMgr::netExtCheck() +{ +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck()" << std::endl; +#endif + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + bool isStable = false; + struct sockaddr_in tmpip ; + + /* check for External Address */ + /* in order of importance */ + /* (1) UPnP -> which handles itself */ + if (!mNetFlags.mExtAddrOk) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() Ext Not Ok" << std::endl; +#endif + + /* net Assist */ + if (netAssistExtAddress(tmpip)) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() Ext supplied from netAssistExternalAddress()" << std::endl; +#endif + if (isValidNet(&(tmpip.sin_addr))) + { + // must be stable??? + isStable = true; + mNetFlags.mExtAddr = tmpip; + mNetFlags.mExtAddrOk = true; + mNetFlags.mExtAddrStableOk = isStable; + } + else + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() Bad Address supplied from netAssistExternalAddress()" << std::endl; +#endif + } + } + + } + + /* otherwise ask ExtAddrFinder */ + if (!mNetFlags.mExtAddrOk) + { + /* ExtAddrFinder */ + if (mUseExtAddrFinder) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() checking ExtAddrFinder" << std::endl; +#endif + bool extFinderOk = mExtAddrFinder->hasValidIP(&(tmpip.sin_addr)); + if (extFinderOk) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() Ext supplied by ExtAddrFinder" << std::endl; +#endif + /* best guess at port */ + tmpip.sin_port = mNetFlags.mLocalAddr.sin_port; +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() "; + std::cerr << "ExtAddr: " << rs_inet_ntoa(tmpip.sin_addr); + std::cerr << ":" << ntohs(tmpip.sin_port); + std::cerr << std::endl; +#endif + + mNetFlags.mExtAddr = tmpip; + mNetFlags.mExtAddrOk = true; + mNetFlags.mExtAddrStableOk = isStable; + + /* XXX HACK TO FIX */ +#warning "ALLOWING ExtAddrFinder -> ExtAddrStableOk = true (which it is not normally)" + mNetFlags.mExtAddrStableOk = true; + + } + } + } + + /* any other sources ??? */ + + /* finalise address */ + if (mNetFlags.mExtAddrOk) + { + +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() "; + std::cerr << "ExtAddr: " << rs_inet_ntoa(mNetFlags.mExtAddr.sin_addr); + std::cerr << ":" << ntohs(mNetFlags.mExtAddr.sin_port); + std::cerr << std::endl; +#endif + //update ip address list + mOwnState.currentserveraddr = mNetFlags.mExtAddr; + + pqiIpAddress addrInfo; + addrInfo.mAddr = mNetFlags.mExtAddr; + addrInfo.mSeenTime = time(NULL); + addrInfo.mSrc = 0; + mOwnState.ipAddrs.mExt.updateIpAddressList(addrInfo); + + mNetStatus = RS_NET_DONE; +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() Ext Ok: RS_NET_DONE" << std::endl; +#endif + + if (!mNetFlags.mExtAddrStableOk) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netUdpCheck() UDP Unstable :( "; + std::cerr << std::endl; + std::cerr << "p3ConnectMgr::netUdpCheck() We are unreachable"; + std::cerr << std::endl; + std::cerr << "netMode => RS_NET_MODE_UNREACHABLE"; + std::cerr << std::endl; +#endif + mOwnState.netMode &= ~(RS_NET_MODE_ACTUAL); + mOwnState.netMode |= RS_NET_MODE_UNREACHABLE; + + /* send a system warning message */ + pqiNotify *notify = getPqiNotify(); + if (notify) + { + std::string title = + "Warning: Bad Firewall Configuration"; + + std::string msg; + msg += " **** WARNING **** \n"; + msg += "Retroshare has detected that you are behind"; + msg += " a restrictive Firewall\n"; + msg += "\n"; + msg += "You cannot connect to other firewalled peers\n"; + msg += "\n"; + msg += "You can fix this by:\n"; + msg += " (1) opening an External Port\n"; + msg += " (2) enabling UPnP, or\n"; + msg += " (3) get a new (approved) Firewall/Router\n"; + + notify->AddSysMessage(0, RS_SYS_WARNING, title, msg); + } + + } + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } + + if (mNetFlags.mExtAddrOk) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() setting netAssistSetAddress()" << std::endl; +#endif + netAssistSetAddress(mNetFlags.mLocalAddr, mNetFlags.mExtAddr, mOwnState.netMode); + } +#if 0 + else + { + std::cerr << "p3ConnectMgr::netExtCheck() setting ERR netAssistSetAddress(0)" << std::endl; + /* mode = 0 for error */ + netAssistSetAddress(mNetFlags.mLocalAddr, mNetFlags.mExtAddr, mOwnState.netMode); + } +#endif + + /* flag unreachables! */ + if ((mNetFlags.mExtAddrOk) && (!mNetFlags.mExtAddrStableOk)) + { +#if defined(CONN_DEBUG_TICK) || defined(CONN_DEBUG_RESET) + std::cerr << "p3ConnectMgr::netExtCheck() Ext Unstable - Unreachable Check" << std::endl; +#endif + connMtx.unlock(); /* UNLOCK MUTEX */ + netUnreachableCheck(); + } + } +} + + +void p3ConnectMgr::networkConsistencyCheck() +{ + return; +} + +#if 0 + +void p3ConnectMgr::networkConsistencyCheck() +{ + time_t delta; +#ifdef CONN_DEBUG_TICK + delta = time(NULL) - mNetInitTS; + std::cerr << "p3ConnectMgr::networkConsistencyCheck() time since last reset : " << delta << std::endl; +#endif + + bool doNetReset = false; + //if one of the flag is degrated from true to false during last tick, let's do a reset +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::networkConsistencyCheck() net flags : " << std::endl; + std::cerr << " oldnetFlagLocalOk : " << oldnetFlagLocalOk << ". netFlagLocalOk : " << netFlagLocalOk << "." << std::endl; + std::cerr << " oldnetFlagUpnpOk : " << oldnetFlagUpnpOk << ". netFlagUpnpOk : " << netFlagUpnpOk << "." << std::endl; + std::cerr << " oldnetFlagDhtOk : " << oldnetFlagDhtOk << ". netFlagDhtOk : " << netFlagDhtOk << "." << std::endl; + std::cerr << " oldnetFlagStunOk : " << oldnetFlagStunOk << ". netFlagStunOk : " << netFlagStunOk << "." << std::endl; + std::cerr << " oldnetFlagExtraAddressCheckOk : " << oldnetFlagExtraAddressCheckOk << ". netFlagExtraAddressCheckOk : " << netFlagExtraAddressCheckOk << "." << std::endl; +#endif + if ( !netFlagLocalOk + || (!netFlagUpnpOk && oldnetFlagUpnpOk) + || (!netFlagDhtOk && oldnetFlagDhtOk) + || (!netFlagStunOk && oldnetFlagStunOk) + || (!netFlagExtraAddressCheckOk && oldnetFlagExtraAddressCheckOk) + ) { +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::networkConsistencyCheck() A net flag went down." << std::endl; +#endif + + //don't do a normal shutdown for upnp as it might hang up. + //With a 0 port it will just dereference and not attemps to communicate for shutting down upnp session. + netAssistFirewallPorts(0, 0); + + doNetReset = true; + } + + bool haveReliableIP = false ; + + { + RsStackMutex stck(connMtx) ; + + //storing old flags + mOldNetFlags = mNetFlags; + + if (!doNetReset) + { // Set an external address. if ip adresses are different, let's use the stun address, then + // the extaddrfinder and then the upnp address. + // + struct sockaddr_in extAddr; + + if (!mOwnState.dyndns.empty () && getIPAddressFromString (mOwnState.dyndns.c_str (), &extAddr.sin_addr)) + { +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::networkConsistencyCheck() using getIPAddressFromString for mOwnState.serveraddr." << std::endl; +#endif + extAddr.sin_port = mOwnState.currentserveraddr.sin_port; + mOwnState.currentserveraddr = extAddr; + haveReliableIP = true ; + } + else if (getExtFinderExtAddress(extAddr)) + { + netExtFinderAddressCheck(); //so we put the extra address flag ok. +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::networkConsistencyCheck() using getExtFinderExtAddress for mOwnState.serveraddr." << std::endl; +#endif + mOwnState.currentserveraddr = extAddr; + haveReliableIP = true ; + } + else if (getUpnpExtAddress(extAddr)) + { +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::networkConsistencyCheck() using getUpnpExtAddress for mOwnState.serveraddr." << std::endl; +#endif + mOwnState.currentserveraddr = extAddr; + haveReliableIP = true ; + } + else + { + //try to extract ext address from our own ip address list + IpAddressTimed extractedAddress; + + if (peerConnectState::extractExtAddress(mOwnState.getIpAddressList(), extractedAddress)) + mOwnState.currentserveraddr = extractedAddress.ipAddr; + + //check if a peer is connected, if yes don't do a net reset + bool is_connected = false; + std::map::iterator it; + for(it = mFriendList.begin(); it != mFriendList.end() && !is_connected; it++) + { + /* get last contact detail */ + is_connected = it->second.state & RS_PEER_S_CONNECTED; + } +#ifdef CONN_DEBUG_TICK + if (is_connected) + std::cerr << "p3ConnectMgr::networkConsistencyCheck() not doing a net reset because a peer is connected." << std::endl; + else + std::cerr << "p3ConnectMgr::networkConsistencyCheck() no peer is connected." << std::endl; +#endif + doNetReset = !is_connected; + } + } + } /* UNLOCK MUTEX */ + + if (haveReliableIP) + { + //extAddr found,update ip address A list + pqiIpAddress addr; + addr.mAddr = mOwnState.currentserveraddr; + addr.mSeenTime = time(NULL); + addr.mSrc = OWN_ADDRESS; + + mOwnState.ipAddrs.updateExtAddrs(addr); + } + + //let's do a net reset + if (doNetReset) + { + //don't do a reset it if the network init is not finished + delta = time(NULL) - mNetInitTS; + if (delta > MAX_NETWORK_INIT) { +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::networkConsistencyCheck() doing a net reset." << std::endl; +#endif +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::networkConsistencyCheck() Calling NetReset" << std::endl; +#endif + netReset(); + } + else + { +#ifdef CONN_DEBUG_TICK + std::cerr << "p3ConnectMgr::networkConsistencyCheck() reset delayed : p3ConnectMgr time since last reset : " << delta; + std::cerr << ". Cannot reset before : " << MAX_NETWORK_INIT << " sec" << std::endl; +#endif + +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::networkConsistencyCheck() Reset PENDING" << std::endl; +#endif + } + } +} + +#endif + +void p3ConnectMgr::netUnreachableCheck() +{ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netUnreachableCheck()" << std::endl; +#endif + std::map::iterator it; + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + /* get last contact detail */ + if (it->second.state & RS_PEER_S_CONNECTED) + { +#ifdef CONN_DEBUG + std::cerr << "NUC() Ignoring Connected Peer" << std::endl; +#endif + continue; + } + + peerAddrInfo details; + switch(it->second.source) + { + case RS_CB_DHT: + details = it->second.dht; +#ifdef CONN_DEBUG + std::cerr << "NUC() Using DHT data" << std::endl; +#endif + break; + case RS_CB_DISC: + details = it->second.disc; +#ifdef CONN_DEBUG + std::cerr << "NUC() Using DISC data" << std::endl; +#endif + break; + case RS_CB_PERSON: + details = it->second.peer; +#ifdef CONN_DEBUG + std::cerr << "NUC() Using PEER data" << std::endl; +#endif + break; + default: + continue; + break; + } + + std::cerr << "NUC() Peer: " << it->first << std::endl; + + /* Determine Reachability (only advisory) */ + // if (mOwnState.netMode == RS_NET_MODE_UNREACHABLE) // MUST BE TRUE! + { + if (details.type & RS_NET_CONN_TCP_EXTERNAL) + { + /* reachable! */ + it->second.state &= (~RS_PEER_S_UNREACHABLE); +#ifdef CONN_DEBUG + std::cerr << "NUC() Peer EXT TCP - reachable" << std::endl; +#endif + } + else + { + /* unreachable */ + it->second.state |= RS_PEER_S_UNREACHABLE; +#ifdef CONN_DEBUG + std::cerr << "NUC() Peer !EXT TCP - unreachable" << std::endl; +#endif + } + } + } + +} + + +/******************************** Network Status ********************************* + * Configuration Loading / Saving. + */ + +void p3ConnectMgr::addMonitor(pqiMonitor *mon) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::list::iterator it; + it = std::find(clients.begin(), clients.end(), mon); + if (it != clients.end()) + { + return; + } + + mon->setConnectionMgr(this); + clients.push_back(mon); + return; +} + +void p3ConnectMgr::removeMonitor(pqiMonitor *mon) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::list::iterator it; + it = std::find(clients.begin(), clients.end(), mon); + if (it == clients.end()) + { + return; + } + (*it)->setConnectionMgr(NULL); + clients.erase(it); + + return; +} + +void p3ConnectMgr::tickMonitors() +{ + bool doStatusChange = false; + std::list actionList; + std::map::iterator it; + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + if (mStatusChanged) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::tickMonitors() StatusChanged! List:" << std::endl; +#endif + /* assemble list */ + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + if (it->second.actions) + { + /* add in */ + pqipeer peer; + peer.id = it->second.id; + peer.name = it->second.name; + peer.state = it->second.state; + peer.actions = it->second.actions; + + /* reset action */ + it->second.actions = 0; + + actionList.push_back(peer); + +#ifdef CONN_DEBUG + std::cerr << "Friend: " << peer.name << " Id: " << peer.id << " State: " << peer.state; + if (peer.state & RS_PEER_S_FRIEND) + std::cerr << " S:RS_PEER_S_FRIEND"; + if (peer.state & RS_PEER_S_ONLINE) + std::cerr << " S:RS_PEER_S_ONLINE"; + if (peer.state & RS_PEER_S_CONNECTED) + std::cerr << " S:RS_PEER_S_CONNECTED"; + std::cerr << " Actions: " << peer.actions; + if (peer.actions & RS_PEER_NEW) + std::cerr << " A:RS_PEER_NEW"; + if (peer.actions & RS_PEER_MOVED) + std::cerr << " A:RS_PEER_MOVED"; + if (peer.actions & RS_PEER_CONNECTED) + std::cerr << " A:RS_PEER_CONNECTED"; + if (peer.actions & RS_PEER_DISCONNECTED) + std::cerr << " A:RS_PEER_DISCONNECTED"; + if (peer.actions & RS_PEER_CONNECT_REQ) + std::cerr << " A:RS_PEER_CONNECT_REQ"; + + std::cerr << std::endl; +#endif + + /* notify GUI */ + if (peer.actions & RS_PEER_CONNECTED) + { + pqiNotify *notify = getPqiNotify(); + if (notify) + { + notify->AddPopupMessage(RS_POPUP_CONNECT, peer.id,"", "Online: "); + notify->AddFeedItem(RS_FEED_ITEM_PEER_CONNECT, peer.id, "", ""); + } + } + } + } + /* do the Others as well! */ + for(it = mOthersList.begin(); it != mOthersList.end(); it++) + { + if (it->second.actions) + { + /* add in */ + pqipeer peer; + peer.id = it->second.id; + peer.name = it->second.name; + peer.state = it->second.state; + peer.actions = it->second.actions; + + /* reset action */ + it->second.actions = 0; + +#ifdef CONN_DEBUG + std::cerr << "Other: " << peer.name << " Id: " << peer.id << " State: " << peer.state; + if (peer.state & RS_PEER_S_FRIEND) + std::cerr << " S:RS_PEER_S_FRIEND"; + if (peer.state & RS_PEER_S_ONLINE) + std::cerr << " S:RS_PEER_S_ONLINE"; + if (peer.state & RS_PEER_S_CONNECTED) + std::cerr << " S:RS_PEER_S_CONNECTED"; + std::cerr << " Actions: " << peer.actions; + if (peer.actions & RS_PEER_NEW) + std::cerr << " A:RS_PEER_NEW"; + if (peer.actions & RS_PEER_MOVED) + std::cerr << " A:RS_PEER_MOVED"; + if (peer.actions & RS_PEER_CONNECTED) + std::cerr << " A:RS_PEER_CONNECTED"; + if (peer.actions & RS_PEER_DISCONNECTED) + std::cerr << " A:RS_PEER_DISCONNECTED"; + if (peer.actions & RS_PEER_CONNECT_REQ) + std::cerr << " A:RS_PEER_CONNECT_REQ"; + + std::cerr << std::endl; +#endif + + actionList.push_back(peer); + } + } + mStatusChanged = false; + doStatusChange = true; + + } + } /****** UNLOCK STACK MUTEX ******/ + + + + + /* NOTE - clients is accessed without mutex protection!!!! + * At the moment this is okay - as they are only added at the start. + * IF this changes ---- must fix with second Mutex. + */ + + if (doStatusChange) + { +#ifdef CONN_DEBUG + std::cerr << "Sending to " << clients.size() << " monitorClients" << std::endl; +#endif + + /* send to all monitors */ + std::list::iterator mit; + for(mit = clients.begin(); mit != clients.end(); mit++) + { + (*mit)->statusChange(actionList); + } + } + +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections + + /* notify all monitors */ + std::list::iterator mit; + for(mit = clients.begin(); mit != clients.end(); mit++) { + (*mit)->statusChanged(); + } + +/////////////////////////////////////////////////////////// +#endif +} + + +const std::string p3ConnectMgr::getOwnId() +{ + return AuthSSL::getAuthSSL()->OwnId(); +} + + +bool p3ConnectMgr::getOwnNetStatus(peerConnectState &state) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + state = mOwnState; + return true; +} + +bool p3ConnectMgr::isFriend(const std::string &id) +{ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::isFriend(" << id << ") called" << std::endl; +#endif + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + bool ret = (mFriendList.end() != mFriendList.find(id)); +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::isFriend(" << id << ") returning : " << ret << std::endl; +#endif + return ret; +} + +bool p3ConnectMgr::isOnline(const std::string &id) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::map::iterator it; + if (mFriendList.end() != (it = mFriendList.find(id))) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::isOnline(" << id << ") is Friend, Online: " << (it->second.state & RS_PEER_S_CONNECTED) << std::endl; +#endif + return (it->second.state & RS_PEER_S_CONNECTED); + } + else + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::isOnline(" << id << ") is Not Friend" << std::endl << "p3ConnectMgr::isOnline() OwnId: " << AuthSSL::getAuthSSL()->OwnId() << std::endl; +#endif + /* not a friend */ + } + + return false; +} + +bool p3ConnectMgr::getFriendNetStatus(const std::string &id, peerConnectState &state) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* check for existing */ + std::map::iterator it; + it = mFriendList.find(id); + if (it == mFriendList.end()) + { + return false; + } + + state = it->second; + return true; +} + + +bool p3ConnectMgr::getOthersNetStatus(const std::string &id, peerConnectState &state) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* check for existing */ + std::map::iterator it; + it = mOthersList.find(id); + if (it == mOthersList.end()) + { + return false; + } + + state = it->second; + return true; +} + + +void p3ConnectMgr::getOnlineList(std::list &peers) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* check for existing */ + std::map::iterator it; + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + if (it->second.state & RS_PEER_S_CONNECTED) + { + peers.push_back(it->first); + } + } + return; +} + +void p3ConnectMgr::getFriendList(std::list &peers) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* check for existing */ + std::map::iterator it; + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + peers.push_back(it->first); + } + return; +} + + +#if 0 +void p3ConnectMgr::getOthersList(std::list &peers) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* check for existing */ + std::map::iterator it; + for(it = mOthersList.begin(); it != mOthersList.end(); it++) + { + peers.push_back(it->first); + } + return; +} +#endif + + +bool p3ConnectMgr::getPeerCount (unsigned int *pnFriendCount, unsigned int *pnOnlineCount, bool ssl) +{ + if (ssl) { + /* count ssl id's */ + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + if (pnFriendCount) *pnFriendCount = mFriendList.size(); + if (pnOnlineCount) { + *pnOnlineCount = 0; + + std::map::iterator it; + for (it = mFriendList.begin(); it != mFriendList.end(); it++) { + if (it->second.state & RS_PEER_S_CONNECTED) { + (*pnOnlineCount)++; + } + } + } + } else { + /* count gpg id's */ + + if (pnFriendCount) *pnFriendCount = 0; + if (pnOnlineCount) *pnOnlineCount = 0; + + if (pnFriendCount || pnOnlineCount) { + std::list gpgIds; + if (AuthGPG::getAuthGPG()->getGPGAcceptedList(gpgIds) == false) { + return false; + } + + /* add own id */ + gpgIds.push_back(AuthGPG::getAuthGPG()->getGPGOwnId()); + + std::list gpgOnlineIds = gpgIds; + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::list::iterator gpgIt; + + /* check ssl id's */ + std::map::iterator it; + for (it = mFriendList.begin(); it != mFriendList.end(); it++) { + if (pnFriendCount && gpgIds.size()) { + gpgIt = std::find(gpgIds.begin(), gpgIds.end(), it->second.gpg_id); + if (gpgIt != gpgIds.end()) { + (*pnFriendCount)++; + gpgIds.erase(gpgIt); + } + } + + if (pnOnlineCount && gpgOnlineIds.size()) { + if (it->second.state & RS_PEER_S_CONNECTED) { + gpgIt = std::find(gpgOnlineIds.begin(), gpgOnlineIds.end(), it->second.gpg_id); + if (gpgIt != gpgOnlineIds.end()) { + (*pnOnlineCount)++; + gpgOnlineIds.erase(gpgIt); + } + } + } + } + } + } + + return true; +} + + +bool p3ConnectMgr::connectAttempt(const std::string &id, struct sockaddr_in &addr, + uint32_t &delay, uint32_t &period, uint32_t &type) + +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* check for existing */ + std::map::iterator it; + it = mFriendList.find(id); + if (it == mFriendList.end()) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::connectAttempt() FAILED Not in FriendList! id: " << id << std::endl; +#endif + + return false; + } + + if (it->second.connAddrs.size() < 1) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::connectAttempt() FAILED No ConnectAddresses id: " << id << std::endl; +#endif + return false; + } + + + if (it->second.state & RS_PEER_S_CONNECTED) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::connectAttempt() Already FLAGGED as connected!!!!" << std::endl; + std::cerr << "p3ConnectMgr::connectAttempt() But allowing anyway!!!" << std::endl; +#endif + } + + it->second.lastattempt = time(NULL); + it->second.inConnAttempt = true; + it->second.currentConnAddrAttempt = it->second.connAddrs.front(); + it->second.connAddrs.pop_front(); + + addr = it->second.currentConnAddrAttempt.addr; + delay = it->second.currentConnAddrAttempt.delay; + period = it->second.currentConnAddrAttempt.period; + type = it->second.currentConnAddrAttempt.type; + + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::connectAttempt() found an address: id: " << id << std::endl; + std::cerr << " laddr: " << rs_inet_ntoa(addr.sin_addr) << " lport: " << ntohs(addr.sin_port) << " delay: " << delay << " period: " << period; + std::cerr << " type: " << type << std::endl; +#endif + if (addr.sin_addr.s_addr == 0 || addr.sin_port == 0) { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::connectAttempt() WARNING: address or port is null" << std::endl; + std::cerr << " type: " << type << std::endl; +#endif + } + + return true; +} + + +/**************************** + * Update state, + * trigger retry if necessary, + * + * remove from DHT? + * + */ + +bool p3ConnectMgr::connectResult(const std::string &id, bool success, uint32_t flags, struct sockaddr_in remote_peer_address) +{ + bool should_netAssistFriend_false = false ; + bool should_netAssistFriend_true = false ; + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::connectResult() called Connect!: id: " + id); + if (success) { + rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::connectResult() called with SUCCESS."); + } else { + rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::connectResult() called with FAILED."); + } + + if (id == getOwnId()) { +#ifdef CONN_DEBUG + rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::connectResult() Failed, connecting to own id: "); +#endif + return false; + } + /* check for existing */ + std::map::iterator it; + it = mFriendList.find(id); + if (it == mFriendList.end()) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::connectResult() Failed, missing Friend " << " id: " << id << std::endl; +#endif + return false; + } + + if (success) + { + /* update address (should also come through from DISC) */ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::connectResult() Connect!: id: " << id << std::endl; + std::cerr << " Success: " << success << " flags: " << flags << std::endl; +#endif + + rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::connectResult() Success"); + + /* change state */ + it->second.state |= RS_PEER_S_CONNECTED; + it->second.actions |= RS_PEER_CONNECTED; + it->second.lastcontact = time(NULL); /* time of connect */ + it->second.connecttype = flags; + + + /* only update the peer's address if we were in a connect attempt. + * Otherwise, they connected to us, and the address will be a + * random port of their outgoing TCP socket + * + * NB even if we received the connection, the IP address is likely to okay. + */ + + //used to send back to the peer it's own ext address + //it->second.currentserveraddr = remote_peer_address; + + if ((it->second.inConnAttempt) && + (it->second.currentConnAddrAttempt.addr.sin_addr.s_addr + == remote_peer_address.sin_addr.s_addr) && + (it->second.currentConnAddrAttempt.addr.sin_port + == remote_peer_address.sin_port)) + { + pqiIpAddress raddr; + raddr.mAddr = remote_peer_address; + raddr.mSeenTime = time(NULL); + raddr.mSrc = 0; + if (isPrivateNet(&(remote_peer_address.sin_addr))) + { + it->second.ipAddrs.updateLocalAddrs(raddr); + it->second.currentlocaladdr = remote_peer_address; + } + else + { + it->second.ipAddrs.updateExtAddrs(raddr); + it->second.currentserveraddr = remote_peer_address; + } +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::connectResult() adding current peer address in list." << std::endl; + it->second.ipAddrs.printAddrs(std::cerr); +#endif + } + + /* remove other attempts */ + it->second.inConnAttempt = false; + it->second.connAddrs.clear(); + should_netAssistFriend_false = true ; + mStatusChanged = true; + return true; + } + else + { + it->second.inConnAttempt = false; + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::connectResult() Disconnect/Fail: id: " << id << std::endl; + std::cerr << " Success: " << success << " flags: " << flags << std::endl; +#endif + + /* if currently connected -> flag as failed */ + if (it->second.state & RS_PEER_S_CONNECTED) + { + it->second.state &= (~RS_PEER_S_CONNECTED); + it->second.actions |= RS_PEER_DISCONNECTED; + mStatusChanged = true; + + it->second.lastcontact = time(NULL); /* time of disconnect */ + + should_netAssistFriend_true = true ; + } + + if (it->second.connAddrs.size() >= 1) + { + it->second.actions |= RS_PEER_CONNECT_REQ; + mStatusChanged = true; + } + } + } + if(should_netAssistFriend_true) + netAssistFriend(id,true) ; + if(should_netAssistFriend_false) + netAssistFriend(id,false) ; + + return true; +} + +/******************************** Feedback ...... ********************************* + * From various sources + */ + + +void p3ConnectMgr::peerStatus(std::string id, const pqiIpAddrSet &addrs, + uint32_t type, uint32_t flags, uint32_t source) +{ + /* HACKED UP FIX ****/ + + std::map::iterator it; + bool isFriend = true; + bool newAddrs; + + time_t now = time(NULL); + + peerAddrInfo details; + details.type = type; + details.found = true; + details.addrs = addrs; + details.ts = now; + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + { + /* Log */ + std::ostringstream out; + out << "p3ConnectMgr::peerStatus()" << " id: " << id; + out << " type: " << type << " flags: " << flags; + out << " source: " << source; + out << std::endl; + addrs.printAddrs(out); + + rslog(RSL_WARNING, p3connectzone, out.str()); +#ifdef CONN_DEBUG + std::cerr << out.str(); +#endif + } + + /* look up the id */ + it = mFriendList.find(id); + if (it == mFriendList.end()) + { + /* check Others list */ + isFriend = false; + it = mOthersList.find(id); + if (it == mOthersList.end()) + { + /* not found - ignore */ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::peerStatus() Peer Not Found - Ignore" << std::endl; +#endif + return; + } +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::peerStatus() Peer is in mOthersList" << std::endl; +#endif + } + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::peerStatus() Current Peer State:" << std::endl; + printConnectState(std::cerr, it->second); + std::cerr << std::endl; +#endif + + /* update the status */ + + /* if source is DHT */ + if (source == RS_CB_DHT) + { + /* DHT can tell us about + * 1) connect type (UDP/TCP/etc) + * 2) local/external address + */ + it->second.source = RS_CB_DHT; + it->second.dht = details; + + /* If we get a info -> then they are online */ + it->second.state |= RS_PEER_S_ONLINE; + it->second.lastavailable = now; + + /* if we are recieving these - the dht is definitely up. + */ + mNetFlags.mDhtOk = true; + } + else if (source == RS_CB_DISC) + { + /* DISC can tell us about + * 1) connect type (UDP/TCP/etc) + * 2) local/external addresses + */ + it->second.source = RS_CB_DISC; + it->second.disc = details; + + + if (flags & RS_NET_FLAGS_ONLINE) + { + it->second.actions |= RS_PEER_ONLINE; + it->second.state |= RS_PEER_S_ONLINE; + it->second.lastavailable = now; + mStatusChanged = true; + } + + /* not updating VIS status??? */ + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } + else if (source == RS_CB_PERSON) + { + /* PERSON can tell us about + * 1) online / offline + * 2) connect address + * -> update all! + */ + + it->second.source = RS_CB_PERSON; + it->second.peer = details; + + it->second.state |= RS_PEER_S_ONLINE; + it->second.lastavailable = now; + + /* must be online to recv info (should be connected too!) + * but no need for action as should be connected already + */ + + it->second.netMode &= (~RS_NET_MODE_ACTUAL); /* clear actual flags */ + if (flags & RS_NET_FLAGS_EXTERNAL_ADDR) + { + it->second.netMode = RS_NET_MODE_EXT; + } + else if (flags & RS_NET_FLAGS_STABLE_UDP) + { + it->second.netMode = RS_NET_MODE_UDP; + } + else + { + it->second.netMode = RS_NET_MODE_UNREACHABLE; + } + + + /* always update VIS status */ + if (flags & RS_NET_FLAGS_USE_DISC) + { + it->second.visState &= (~RS_VIS_STATE_NODISC); + } + else + { + it->second.visState |= RS_VIS_STATE_NODISC; + } + + if (flags & RS_NET_FLAGS_USE_DHT) + { + it->second.visState &= (~RS_VIS_STATE_NODHT); + } + else + { + it->second.visState |= RS_VIS_STATE_NODHT; + } + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } + + /* Determine Reachability (only advisory) */ + if (mOwnState.netMode & RS_NET_MODE_UDP) + { + if ((details.type & RS_NET_CONN_UDP_DHT_SYNC) || + (details.type & RS_NET_CONN_TCP_EXTERNAL)) + { + /* reachable! */ + it->second.state &= (~RS_PEER_S_UNREACHABLE); + } + else + { + /* unreachable */ + it->second.state |= RS_PEER_S_UNREACHABLE; + } + } + else if (mOwnState.netMode & RS_NET_MODE_UNREACHABLE) + { + if (details.type & RS_NET_CONN_TCP_EXTERNAL) + { + /* reachable! */ + it->second.state &= (~RS_PEER_S_UNREACHABLE); + } + else + { + /* unreachable */ + it->second.state |= RS_PEER_S_UNREACHABLE; + } + } + else + { + it->second.state &= (~RS_PEER_S_UNREACHABLE); + } + + if (!isFriend) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::peerStatus() NOT FRIEND " << " id: " << id << std::endl; +#endif + + { + rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::peerStatus() NO CONNECT (not friend)"); + } + return; + } + + /* if already connected -> done */ + if (it->second.state & RS_PEER_S_CONNECTED) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::peerStatus() PEER ONLINE ALREADY " << " id: " << id << std::endl; +#endif + { + /* Log */ + rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::peerStatus() NO CONNECT (already connected!)"); + } + + return; + } + + newAddrs = it->second.ipAddrs.updateAddrs(addrs); + } /****** STACK UNLOCK MUTEX *******/ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::peerStatus()" << " id: " << id; + std::cerr << " type: " << type << " flags: " << flags; + std::cerr << " source: " << source << std::endl; + std::cerr << " addrs: " << std::endl; + addrs.printAddrs(std::cerr); + std::cerr << std::endl; + +#endif + +#ifndef P3CONNMGR_NO_AUTO_CONNECTION + +#ifndef P3CONNMGR_NO_TCP_CONNECTIONS + if (newAddrs) + { + retryConnectTCP(id); + } + +#endif // P3CONNMGR_NO_TCP_CONNECTIONS + + +#else +#endif // P3CONNMGR_NO_AUTO_CONNECTION + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::peerStatus() Resulting Peer State:" << std::endl; + printConnectState(std::cerr, it->second); + std::cerr << std::endl; +#endif + +} + +void p3ConnectMgr::peerConnectRequest(std::string id, struct sockaddr_in raddr, + uint32_t source) +{ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::peerConnectRequest() id: " << id << " raddr: " << rs_inet_ntoa(raddr.sin_addr) << ":" << ntohs(raddr.sin_port); + std::cerr << " source: " << source << std::endl; +#endif + { + /* Log */ + std::ostringstream out; + out << "p3ConnectMgr::peerConnectRequest() id: " << id << " raddr: " << rs_inet_ntoa(raddr.sin_addr); + out << ":" << ntohs(raddr.sin_port) << " source: " << source; + rslog(RSL_WARNING, p3connectzone, out.str()); + } + + /******************** TCP PART *****************************/ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::peerConnectRequest() Try TCP first" << std::endl; +#endif + + if (source == RS_CB_DHT) + { + std::cerr << "p3ConnectMgr::peerConnectRequest() source DHT ==> retryConnectUDP()" << std::endl; + retryConnectUDP(id, raddr); + return; + } + else + { // IS THIS USED??? + std::cerr << "p3ConnectMgr::peerConnectRequest() source OTHER ==> retryConnect()" << std::endl; + + retryConnect(id); + return; + } +} + + +/*******************************************************************/ +/*******************************************************************/ + +bool p3ConnectMgr::addFriend(const std::string &id, const std::string &gpg_id, uint32_t netMode, uint32_t visState, time_t lastContact) +{ + bool should_netAssistFriend_true = false ; + bool should_netAssistFriend_false = false ; + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + //set a new retry period, so the more frinds we have the less we launch conection attempts + mRetryPeriod = MIN_RETRY_PERIOD + (mFriendList.size() * 2); + + if (id == AuthSSL::getAuthSSL()->OwnId()) { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() cannot add own id as a friend." << std::endl; +#endif + /* (1) already exists */ + return false; + } + /* so four possibilities + * (1) already exists as friend -> do nothing. + * (2) is in others list -> move over. + * (3) is non-existant -> create new one. + */ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() " << id << "; gpg_id : " << gpg_id << std::endl; +#endif + + std::map::iterator it; + if (mFriendList.end() != mFriendList.find(id)) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() Already Exists" << std::endl; +#endif + /* (1) already exists */ + return true; + } + + //Authentication is now tested at connection time, we don't store the ssl cert anymore + // + if (!AuthGPG::getAuthGPG()->isGPGAccepted(gpg_id) && gpg_id != AuthGPG::getAuthGPG()->getGPGOwnId()) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() gpg is not accepted" << std::endl; +#endif + /* no auth */ + return false; + } + + + /* check if it is in others */ + if (mOthersList.end() != (it = mOthersList.find(id))) + { + /* (2) in mOthersList -> move over */ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() Move from Others" << std::endl; +#endif + + mFriendList[id] = it->second; + mOthersList.erase(it); + + it = mFriendList.find(id); + + /* setup state */ + it->second.state = RS_PEER_S_FRIEND; + it->second.actions = RS_PEER_NEW; + + /* setup connectivity parameters */ + it->second.visState = visState; + it->second.netMode = netMode; + it->second.lastcontact = lastContact; + + mStatusChanged = true; + + /* add peer to DHT (if not dark) */ + if (it->second.visState & RS_VIS_STATE_NODHT) + { + /* hidden from DHT world */ + should_netAssistFriend_false = true ; + } + else + { + should_netAssistFriend_true = true ; + } + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } + else + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addFriend() Creating New Entry" << std::endl; +#endif + + /* create a new entry */ + peerConnectState pstate; + + pstate.id = id; + pstate.gpg_id = gpg_id; + pstate.name = AuthGPG::getAuthGPG()->getGPGName(gpg_id); + + pstate.state = RS_PEER_S_FRIEND; + pstate.actions = RS_PEER_NEW; + pstate.visState = visState; + pstate.netMode = netMode; + pstate.lastcontact = lastContact; + + /* addr & timestamps -> auto cleared */ + + mFriendList[id] = pstate; + + mStatusChanged = true; + + /* expect it to be a standard DHT */ + should_netAssistFriend_true = true ; + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } + } + if(should_netAssistFriend_true) + netAssistFriend(id,true) ; + if(should_netAssistFriend_false) + netAssistFriend(id,false) ; + + return true; +} + + +bool p3ConnectMgr::removeFriend(const std::string &id) +{ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::removeFriend() for id : " << id << std::endl; + std::cerr << "p3ConnectMgr::removeFriend() mFriendList.size() : " << mFriendList.size() << std::endl; +#endif + + netAssistFriend(id, false); + + std::list toRemove; + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* move to othersList */ + bool success = false; + std::map::iterator it; + //remove ssl and gpg_ids + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + if (it->second.id == id || it->second.gpg_id == id) { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::removeFriend() friend found in the list." << id << std::endl; +#endif + peerConnectState peer = it->second; + + toRemove.push_back(it->second.id); + + peer.state &= (~RS_PEER_S_FRIEND); + peer.state &= (~RS_PEER_S_CONNECTED); + peer.state &= (~RS_PEER_S_ONLINE); + peer.actions = RS_PEER_MOVED; + peer.inConnAttempt = false; + mOthersList[id] = peer; + mStatusChanged = true; + + success = true; + } + } + + std::list::iterator toRemoveIt; + for(toRemoveIt = toRemove.begin(); toRemoveIt != toRemove.end(); toRemoveIt++) { + if (mFriendList.end() != (it = mFriendList.find(*toRemoveIt))) { + mFriendList.erase(it); + } + } + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::removeFriend() new mFriendList.size() : " << mFriendList.size() << std::endl; +#endif + } + + /* remove id from all groups */ + std::list peerIds; + peerIds.push_back(id); + + assignPeersToGroup("", peerIds, false); + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + return !toRemove.empty(); +} + + + +#if 0 +bool p3ConnectMgr::addNeighbour(std::string id) +{ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::addNeighbour() not implemented anymore." << id << std::endl; +#endif + + /* so three possibilities + * (1) already exists as friend -> do nothing. + * (2) already in others list -> do nothing. + * (3) is non-existant -> create new one. + */ + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::map::iterator it; + if (mFriendList.end() == mFriendList.find(id)) + { + /* (1) already exists */ + return false; + } + + if (mOthersList.end() == mOthersList.find(id)) + { + /* (2) already exists */ + return true; + } + + /* check with the AuthMgr if its valid */ + if (!AuthSSL::getAuthSSL()->isAuthenticated(id)) + { + /* no auth */ + return false; + } + + /* get details from AuthMgr */ + sslcert detail; + if (!AuthSSL::getAuthSSL()->getCertDetails(id, detail)) + { + /* no details */ + return false; + } + + /* create a new entry */ + peerConnectState pstate; + + pstate.id = id; + pstate.name = detail.name; + + pstate.state = 0; + pstate.actions = 0; //RS_PEER_NEW; + pstate.visState = RS_VIS_STATE_STD; + pstate.netMode = RS_NET_MODE_UNKNOWN; + + /* addr & timestamps -> auto cleared */ + mOthersList[id] = pstate; + + return false; +} + +#endif + +/*******************************************************************/ +/*******************************************************************/ + /*************** External Control ****************/ +bool p3ConnectMgr::retryConnect(const std::string &id) +{ + /* push all available addresses onto the connect addr stack */ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnect() id: " << id << std::endl; +#endif + +#ifndef P3CONNMGR_NO_TCP_CONNECTIONS + + retryConnectTCP(id); + +#endif // P3CONNMGR_NO_TCP_CONNECTIONS + + return true; +} + + + +bool p3ConnectMgr::retryConnectUDP(const std::string &id, struct sockaddr_in &rUdpAddr) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* push all available addresses onto the connect addr stack */ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectTCP() id: " << id << std::endl; +#endif + + if (id == getOwnId()) { + #ifdef CONN_DEBUG + rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::retryConnectUDP() Failed, connecting to own id: "); + #endif + return false; + } + + /* look up the id */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectUDP() Peer is not Friend" << std::endl; +#endif + return false; + } + + /* if already connected -> done */ + if (it->second.state & RS_PEER_S_CONNECTED) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectUDP() Peer Already Connected" << std::endl; +#endif + if (it->second.connecttype & RS_NET_CONN_TUNNEL) { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectUDP() Peer Connected through a tunnel connection, let's try a normal connection." << std::endl; +#endif + } else { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectUDP() Peer Connected no more connection attempts" << std::endl; +#endif + return false; + } + } + + /* Explicit Request to start the UDP connection */ + if (isValidNet(&(rUdpAddr.sin_addr))) + { +#ifdef CONN_DEBUG + std::cerr << "Adding udp connection attempt: "; + std::cerr << "Addr: " << rs_inet_ntoa(rUdpAddr.sin_addr); + std::cerr << ":" << ntohs(rUdpAddr.sin_port); + std::cerr << std::endl; +#endif + peerConnectAddress pca; + pca.addr = rUdpAddr; + pca.type = RS_NET_CONN_UDP_PEER_SYNC; + pca.delay = P3CONNMGR_UDP_DEFAULT_DELAY; + pca.ts = time(NULL); + pca.period = P3CONNMGR_UDP_DEFAULT_PERIOD; + + addAddressIfUnique(it->second.connAddrs, pca); + } + + /* finish it off */ + return locked_ConnectAttempt_Complete(&(it->second)); +} + + + + + +bool p3ConnectMgr::retryConnectTCP(const std::string &id) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* push all available addresses onto the connect addr stack... + * with the following exceptions: + * - check local address, see if it is the same network as us + - check address age. don't add old ones + */ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectTCP() id: " << id << std::endl; +#endif + + if (id == getOwnId()) { + #ifdef CONN_DEBUG + rslog(RSL_WARNING, p3connectzone, "p3ConnectMgr::retryConnectTCP() Failed, connecting to own id: "); + #endif + return false; + } + + /* look up the id */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectTCP() Peer is not Friend" << std::endl; +#endif + return false; + } + + /* if already connected -> done */ + if (it->second.state & RS_PEER_S_CONNECTED) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectTCP() Peer Already Connected" << std::endl; +#endif + if (it->second.connecttype & RS_NET_CONN_TUNNEL) { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectTCP() Peer Connected through a tunnel connection, let's try a normal connection." << std::endl; +#endif + } else { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::retryConnectTCP() Peer Connected no more connection attempts" << std::endl; +#endif + return false; + } + } + + /* UDP automatically searches -> no need to push start */ + + locked_ConnectAttempt_CurrentAddresses(&(it->second)); + locked_ConnectAttempt_HistoricalAddresses(&(it->second)); + locked_ConnectAttempt_AddDynDNS(&(it->second)); + locked_ConnectAttempt_AddTunnel(&(it->second)); + + /* finish it off */ + return locked_ConnectAttempt_Complete(&(it->second)); +} + + +#define MAX_TCP_ADDR_AGE (3600 * 24 * 14) // two weeks in seconds. + +bool p3ConnectMgr::locked_CheckPotentialAddr(struct sockaddr_in *addr, time_t age) +{ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::locked_CheckPotentialAddr("; + std::cerr << rs_inet_ntoa(addr->sin_addr); + std::cerr << ":" << ntohs(addr->sin_port); + std::cerr << ", " << age << ")"; + std::cerr << std::endl; +#endif + + /* + * if it is old - quick rejection + */ + if (age > MAX_TCP_ADDR_AGE) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::locked_CheckPotentialAddr() REJECTING - TOO OLD"; + std::cerr << std::endl; +#endif + return false; + } + + bool isValid = isValidNet(&(addr->sin_addr)); + // bool isLoopback = isLoopbackNet(&(addr->sin_addr)); + // bool isPrivate = isPrivateNet(&(addr->sin_addr)); + bool isExternal = isExternalNet(&(addr->sin_addr)); + + /* if invalid - quick rejection */ + if (!isValid) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::locked_CheckPotentialAddr() REJECTING - INVALID"; + std::cerr << std::endl; +#endif + return false; + } + + /* if it is on the ban list - ignore */ + /* checks - is it the dreaded 1.0.0.0 */ + + std::list::const_iterator it; + for(it = mBannedIpList.begin(); it != mBannedIpList.end(); it++) + { + if (it->s_addr == addr->sin_addr.s_addr) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::locked_CheckPotentialAddr() REJECTING - ON BANNED IPLIST"; + std::cerr << std::endl; +#endif + return false; + } + } + + + /* if it is an external address, we'll accept it. + * - even it is meant to be a local address. + */ + if (isExternal) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::locked_CheckPotentialAddr() ACCEPTING - EXTERNAL"; + std::cerr << std::endl; +#endif + return true; + } + + + /* get here, it is private or loopback + * - can only connect to these addresses if we are on the same subnet. + - check net against our local address. + */ + + std::cerr << "p3ConnectMgr::locked_CheckPotentialAddr() Checking sameNet against: "; + std::cerr << rs_inet_ntoa(mOwnState.currentlocaladdr.sin_addr); + std::cerr << ")"; + std::cerr << std::endl; + + if (sameNet(&(mOwnState.currentlocaladdr.sin_addr), &(addr->sin_addr))) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::locked_CheckPotentialAddr() ACCEPTING - PRIVATE & sameNET"; + std::cerr << std::endl; +#endif + return true; + } + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::locked_CheckPotentialAddr() REJECTING - PRIVATE & !sameNET"; + std::cerr << std::endl; +#endif + + /* else it fails */ + return false; + +} + + +void p3ConnectMgr::locked_ConnectAttempt_CurrentAddresses(peerConnectState *peer) +{ + // Just push all the addresses onto the stack. + /* try "current addresses" first */ + if (locked_CheckPotentialAddr(&(peer->currentlocaladdr), 0)) + { +#ifdef CONN_DEBUG + std::cerr << "Adding tcp connection attempt: "; + std::cerr << "Current Local Addr: " << rs_inet_ntoa(peer->currentlocaladdr.sin_addr); + std::cerr << ":" << ntohs(peer->currentlocaladdr.sin_port); + std::cerr << std::endl; +#endif + peerConnectAddress pca; + pca.addr = peer->currentlocaladdr; + pca.type = RS_NET_CONN_TCP_LOCAL; + pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; + pca.ts = time(NULL); + pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; + + addAddressIfUnique(peer->connAddrs, pca); + } + + if (locked_CheckPotentialAddr(&(peer->currentserveraddr), 0)) + { +#ifdef CONN_DEBUG + std::cerr << "Adding tcp connection attempt: "; + std::cerr << "Current Ext Addr: " << rs_inet_ntoa(peer->currentserveraddr.sin_addr); + std::cerr << ":" << ntohs(peer->currentserveraddr.sin_port); + std::cerr << std::endl; +#endif + peerConnectAddress pca; + pca.addr = peer->currentserveraddr; + pca.type = RS_NET_CONN_TCP_EXTERNAL; + pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; + pca.ts = time(NULL); + pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; + + addAddressIfUnique(peer->connAddrs, pca); + } +} + + +void p3ConnectMgr::locked_ConnectAttempt_HistoricalAddresses(peerConnectState *peer) +{ + /* now try historical addresses */ + /* try local addresses first */ + std::list::iterator ait; + time_t now = time(NULL); + + for(ait = peer->ipAddrs.mLocal.mAddrs.begin(); + ait != peer->ipAddrs.mLocal.mAddrs.end(); ait++) + { + if (locked_CheckPotentialAddr(&(ait->mAddr), now - ait->mSeenTime)) + { + +#ifdef CONN_DEBUG + std::cerr << "Adding tcp connection attempt: "; + std::cerr << "Local Addr: " << rs_inet_ntoa(ait->mAddr.sin_addr); + std::cerr << ":" << ntohs(ait->mAddr.sin_port); + std::cerr << std::endl; +#endif + + peerConnectAddress pca; + pca.addr = ait->mAddr; + pca.type = RS_NET_CONN_TCP_LOCAL; + pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; + pca.ts = time(NULL); + pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; + + addAddressIfUnique(peer->connAddrs, pca); + } + } + + for(ait = peer->ipAddrs.mExt.mAddrs.begin(); + ait != peer->ipAddrs.mExt.mAddrs.end(); ait++) + { + if (locked_CheckPotentialAddr(&(ait->mAddr), now - ait->mSeenTime)) + { + +#ifdef CONN_DEBUG + std::cerr << "Adding tcp connection attempt: "; + std::cerr << "Ext Addr: " << rs_inet_ntoa(ait->mAddr.sin_addr); + std::cerr << ":" << ntohs(ait->mAddr.sin_port); + std::cerr << std::endl; +#endif + peerConnectAddress pca; + pca.addr = ait->mAddr; + pca.type = RS_NET_CONN_TCP_EXTERNAL; + pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; + pca.ts = time(NULL); + pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; + + addAddressIfUnique(peer->connAddrs, pca); + } + } +} + + +void p3ConnectMgr::locked_ConnectAttempt_AddDynDNS(peerConnectState *peer) +{ + /* try dyndns address too */ + if (!peer->dyndns.empty()) + { + struct in_addr addr; + u_short port = peer->currentserveraddr.sin_port ? peer->currentserveraddr.sin_port : peer->currentlocaladdr.sin_port; +#ifdef CONN_DEBUG + std::cerr << "Looking up DynDNS address" << std::endl; +#endif + if (port) + { + if(mDNSResolver->getIPAddressFromString (std::string(peer->dyndns.c_str()), addr)) + { +#ifdef CONN_DEBUG + std::cerr << "Adding tcp connection attempt: "; + std::cerr << "DynDNS Addr: " << rs_inet_ntoa(addr); + std::cerr << ":" << ntohs(port); + std::cerr << std::endl; +#endif + peerConnectAddress pca; + pca.addr.sin_family = AF_INET; + pca.addr.sin_addr.s_addr = addr.s_addr; + pca.addr.sin_port = port; + pca.type = RS_NET_CONN_TCP_EXTERNAL; + //for the delay, we add a random time and some more time when the friend list is big + pca.delay = P3CONNMGR_TCP_DEFAULT_DELAY; + pca.ts = time(NULL); + pca.period = P3CONNMGR_TCP_DEFAULT_PERIOD; + + /* check address validity */ + if (locked_CheckPotentialAddr(&(pca.addr), 0)) + { + addAddressIfUnique(peer->connAddrs, pca); + } + } + } + } +} + + +void p3ConnectMgr::locked_ConnectAttempt_AddTunnel(peerConnectState *peer) +{ + if (!(peer->state & RS_PEER_S_CONNECTED) && mAllowTunnelConnection) + { +#ifdef CONN_DEBUG + std::cerr << "Adding TUNNEL Connection Attempt"; + std::cerr << std::endl; +#endif + peerConnectAddress pca; + pca.type = RS_NET_CONN_TUNNEL; + pca.ts = time(NULL); + pca.period = 0; + + sockaddr_clear(&pca.addr); + + addAddressIfUnique(peer->connAddrs, pca); + } +} + + +bool p3ConnectMgr::addAddressIfUnique(std::list &addrList, peerConnectAddress &pca) +{ + /* iterate through the list, and make sure it isn't already + * in the list + */ + + std::list::iterator it; + for(it = addrList.begin(); it != addrList.end(); it++) + { + if ((pca.addr.sin_addr.s_addr == it->addr.sin_addr.s_addr) && + (pca.addr.sin_port == it->addr.sin_port) && + (pca.type == it->type)) + { + /* already */ + return false; + } + } + + addrList.push_back(pca); + + return true; +} + + + +bool p3ConnectMgr::locked_ConnectAttempt_Complete(peerConnectState *peer) +{ + + /* flag as last attempt to prevent loop */ + //add a random perturbation between 0 and 2 sec. + peer->lastattempt = time(NULL) + rand() % MAX_RANDOM_ATTEMPT_OFFSET; + + if (peer->inConnAttempt) { + /* -> it'll automatically use the addresses we added */ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::locked_ConnectAttempt_Complete() Already in CONNECT ATTEMPT"; + std::cerr << std::endl; + std::cerr << "p3ConnectMgr::locked_ConnectAttempt_Complete() Remaining ConnAddr Count: " << peer->connAddrs.size(); + std::cerr << std::endl; +#endif + return true; + } + + /* start a connection attempt */ + if (peer->connAddrs.size() > 0) + { + #ifdef CONN_DEBUG + std::ostringstream out; + out << "p3ConnectMgr::locked_ConnectAttempt_Complete() Started CONNECT ATTEMPT! " ; + out << std::endl; + out << "p3ConnectMgr::locked_ConnectAttempt_Complete() ConnAddr Count: " << peer->connAddrs.size(); + rslog(RSL_DEBUG_ALERT, p3connectzone, out.str()); + std::cerr << out.str() << std::endl; + + #endif + + peer->actions |= RS_PEER_CONNECT_REQ; + mStatusChanged = true; + return true; + } + else + { + #ifdef CONN_DEBUG + std::ostringstream out; + out << "p3ConnectMgr::locked_ConnectAttempt_Complete() No addr in the connect attempt list. Not suitable for CONNECT ATTEMPT! "; + rslog(RSL_DEBUG_ALERT, p3connectzone, out.str()); + std::cerr << out.str() << std::endl; + #endif + return false; + } + return false; +} + +/********************************************************************** + ********************************************************************** + ******************** External Setup ********************************** + ********************************************************************** + **********************************************************************/ + + +bool p3ConnectMgr::setLocalAddress(const std::string &id, struct sockaddr_in addr) +{ + if (id == AuthSSL::getAuthSSL()->OwnId()) + { + bool changed = false; + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + if (mOwnState.currentlocaladdr.sin_addr.s_addr != addr.sin_addr.s_addr || + mOwnState.currentlocaladdr.sin_port != addr.sin_port) + { + changed = true; + } + + mOwnState.currentlocaladdr = addr; + } + + if (changed) + { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + netReset(); + #ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::setLocalAddress() Calling NetReset" << std::endl; + #endif + } + return true; + } + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + /* check if it is a friend */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { + if (mOthersList.end() == (it = mOthersList.find(id))) + { + #ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::setLocalAddress() cannot add addres info : peer id not found in friend list id: " << id << std::endl; + #endif + return false; + } + } + + /* "it" points to peer */ + it->second.currentlocaladdr = addr; + +#if 0 + //update ip address list + IpAddressTimed ipAddressTimed; + ipAddressTimed.ipAddr = addr; + ipAddressTimed.seenTime = time(NULL); + it->second.updateIpAddressList(ipAddressTimed); +#endif + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + return true; +} + +bool p3ConnectMgr::setExtAddress(const std::string &id, struct sockaddr_in addr) +{ + if (id == AuthSSL::getAuthSSL()->OwnId()) + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + mOwnState.currentserveraddr = addr; + return true; + } + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + /* check if it is a friend */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { + if (mOthersList.end() == (it = mOthersList.find(id))) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::setLocalAddress() cannot add addres info : peer id not found in friend list id: " << id << std::endl; +#endif + return false; + } + } + + /* "it" points to peer */ + it->second.currentserveraddr = addr; + +#if 0 + //update ip address list + IpAddressTimed ipAddressTimed; + ipAddressTimed.ipAddr = addr; + ipAddressTimed.seenTime = time(NULL); + it->second.updateIpAddressList(ipAddressTimed); +#endif + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + return true; +} + + +bool p3ConnectMgr::setDynDNS(const std::string &id, const std::string &dyndns) +{ + if (id == AuthSSL::getAuthSSL()->OwnId()) + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + mOwnState.dyndns = dyndns; + return true; + } + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + /* check if it is a friend */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { + if (mOthersList.end() == (it = mOthersList.find(id))) + { + #ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::setDynDNS() cannot add dyn dns info : peer id not found in friend list id: " << id << std::endl; + #endif + return false; + } + } + + /* "it" points to peer */ + it->second.dyndns = dyndns; + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + return true; +} + +bool p3ConnectMgr::updateAddressList(const std::string& id, const pqiIpAddrSet &addrs) +{ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::setAddressList() called for id : " << id << std::endl; +#endif + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* check if it is our own ip */ + if (id == getOwnId()) + { + mOwnState.ipAddrs.updateAddrs(addrs); + return true; + } + + /* check if it is a friend */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { + if (mOthersList.end() == (it = mOthersList.find(id))) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::setLocalAddress() cannot add addres info : peer id not found in friend list. id: " << id << std::endl; +#endif + return false; + } + } + + /* "it" points to peer */ + it->second.ipAddrs.updateAddrs(addrs); +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::setLocalAddress() Updated Address for: " << id; + std::cerr << std::endl; + it->second.ipAddrs.printAddrs(std::cerr); + std::cerr << std::endl; +#endif + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + return true; +} + +bool p3ConnectMgr::setNetworkMode(const std::string &id, uint32_t netMode) +{ + if (id == AuthSSL::getAuthSSL()->OwnId()) + { + uint32_t visState; + uint32_t oldNetMode; + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + visState = mOwnState.visState; + oldNetMode = mOwnState.netMode; + } + + setOwnNetConfig(netMode, visState); + + if ((netMode & RS_NET_MODE_ACTUAL) != (oldNetMode & RS_NET_MODE_ACTUAL)) { + #ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::setNetworkMode() Calling NetReset" << std::endl; + #endif + netReset(); + } + return true; + } + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + /* check if it is a friend */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { + if (mOthersList.end() == (it = mOthersList.find(id))) + { + return false; + } + } + + /* "it" points to peer */ + it->second.netMode = netMode; + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + return false; +} + +bool p3ConnectMgr::setLocation(const std::string &id, const std::string &location) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::setLocation() called for id : " << id << "; with location " << location << std::endl; +#endif + if (id == AuthSSL::getAuthSSL()->OwnId()) + { + mOwnState.location = location; + return true; + } + + /* check if it is a friend */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) { + return false; + } else { + it->second.location = location; + return true; + } +} + +bool p3ConnectMgr::setVisState(const std::string &id, uint32_t visState) +{ + if (id == AuthSSL::getAuthSSL()->OwnId()) + { + uint32_t netMode; + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + netMode = mOwnState.netMode; + } + setOwnNetConfig(netMode, visState); + return true; + } + + bool dht_state ; + bool isFriend = false; + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* check if it is a friend */ + std::map::iterator it; + if (mFriendList.end() == (it = mFriendList.find(id))) + { + if (mOthersList.end() == (it = mOthersList.find(id))) + { + return false; + } + } + else + { + isFriend = true; + } + + /* "it" points to peer */ + it->second.visState = visState; + dht_state = it->second.visState & RS_VIS_STATE_NODHT ; + } + if(isFriend) + { + /* toggle DHT state */ + if(dht_state) + { + /* hidden from DHT world */ + netAssistFriend(id, false); + } + else + { + netAssistFriend(id, true); + } + } + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + return false; +} + + + + +/*******************************************************************/ + +bool p3ConnectMgr::checkNetAddress() +{ + bool addrChanged = false; + bool validAddr = false; + + struct in_addr prefAddr; + struct sockaddr_in oldAddr; + + validAddr = getPreferredInterface(prefAddr); + + /* if we don't have a valid address - reset */ + if (!validAddr) + { +#ifdef CONN_DEBUG_RESET + std::cerr << "p3ConnectMgr::checkNetAddress() no Valid Network Address, resetting network." << std::endl; + std::cerr << std::endl; +#endif + netReset(); + IndicateConfigChanged(); + return false; + } + + + /* check addresses */ + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + oldAddr = mOwnState.currentlocaladdr; + addrChanged = (prefAddr.s_addr != mOwnState.currentlocaladdr.sin_addr.s_addr); + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::checkNetAddress()"; + std::cerr << std::endl; + std::cerr << "Current Local: " << rs_inet_ntoa(mOwnState.currentlocaladdr.sin_addr); + std::cerr << ":" << ntohs(mOwnState.currentlocaladdr.sin_port); + std::cerr << std::endl; + std::cerr << "Current Preferred: " << rs_inet_ntoa(prefAddr); + std::cerr << std::endl; +#endif + +#ifdef CONN_DEBUG_RESET + if (addrChanged) + { + std::cerr << "p3ConnectMgr::checkNetAddress() Address Changed!"; + std::cerr << std::endl; + std::cerr << "Current Local: " << rs_inet_ntoa(mOwnState.currentlocaladdr.sin_addr); + std::cerr << ":" << ntohs(mOwnState.currentlocaladdr.sin_port); + std::cerr << std::endl; + std::cerr << "Current Preferred: " << rs_inet_ntoa(prefAddr); + std::cerr << std::endl; + } +#endif + + // update address. + mOwnState.currentlocaladdr.sin_addr = prefAddr; + + + mNetFlags.mLocalAddr = mOwnState.currentlocaladdr; + + if(isLoopbackNet(&(mOwnState.currentlocaladdr.sin_addr))) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::checkNetAddress() laddr: Loopback" << std::endl; +#endif + mNetFlags.mLocalAddrOk = false; + mNetStatus = RS_NET_LOOPBACK; + } + else if (!isValidNet(&mOwnState.currentlocaladdr.sin_addr)) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::checkNetAddress() laddr: invalid" << std::endl; +#endif + mNetFlags.mLocalAddrOk = false; + } + else + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::checkNetAddress() laddr okay" << std::endl; +#endif + mNetFlags.mLocalAddrOk = true; + } + + + int port = ntohs(mOwnState.currentlocaladdr.sin_port); + if ((port < PQI_MIN_PORT) || (port > PQI_MAX_PORT)) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::checkNetAddress() Correcting Port to DEFAULT" << std::endl; +#endif + // Generate a default port from SSL id. The port will always be the + // same, but appear random from peer to peer. + // Random port avoids clashes, improves anonymity. + // + uint32_t default_port_seed = 0 ; + for(std::string::size_type i=0;iaddSerialType(new RsPeerConfigSerialiser()); + rss->addSerialType(new RsGeneralConfigSerialiser()) ; + + return rss; +} + + +bool p3ConnectMgr::saveList(bool &cleanup, std::list& saveData) +{ + /* create a list of current peers */ + cleanup = false; + + connMtx.lock(); /****** MUTEX LOCKED *******/ + + RsPeerNetItem *item = new RsPeerNetItem(); + item->clear(); + + item->pid = getOwnId(); + item->gpg_id = mOwnState.gpg_id; + item->location = mOwnState.location; + if (mOwnState.netMode & RS_NET_MODE_TRY_EXT) + { + item->netMode = RS_NET_MODE_EXT; + } + else if (mOwnState.netMode & RS_NET_MODE_TRY_UPNP) + { + item->netMode = RS_NET_MODE_UPNP; + } + else + { + item->netMode = RS_NET_MODE_UDP; + } + + item->visState = mOwnState.visState; + item->lastContact = mOwnState.lastcontact; + + item->currentlocaladdr = mOwnState.currentlocaladdr; + item->currentremoteaddr = mOwnState.currentserveraddr; + item->dyndns = mOwnState.dyndns; + mOwnState.ipAddrs.mLocal.loadTlv(item->localAddrList); + mOwnState.ipAddrs.mExt.loadTlv(item->extAddrList); + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::saveList() Own Config Item:" << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + saveData.push_back(item); + saveCleanupList.push_back(item); + + /* iterate through all friends and save */ + std::map::iterator it; + for(it = mFriendList.begin(); it != mFriendList.end(); it++) + { + item = new RsPeerNetItem(); + item->clear(); + + item->pid = it->first; + item->gpg_id = (it->second).gpg_id; + item->location = (it->second).location; + item->netMode = (it->second).netMode; + item->visState = (it->second).visState; + item->lastContact = (it->second).lastcontact; + item->currentlocaladdr = (it->second).currentlocaladdr; + item->currentremoteaddr = (it->second).currentserveraddr; + item->dyndns = (it->second).dyndns; + (it->second).ipAddrs.mLocal.loadTlv(item->localAddrList); + (it->second).ipAddrs.mExt.loadTlv(item->extAddrList); + + saveData.push_back(item); + saveCleanupList.push_back(item); +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::saveList() Peer Config Item:" << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + } + + // Now save config for network digging strategies + + RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; + + RsTlvKeyValue kv; + kv.key = "USE_EXTR_IP_FINDER" ; + kv.value = (mUseExtAddrFinder)?"TRUE":"FALSE" ; + vitem->tlvkvs.pairs.push_back(kv) ; + + #ifdef CONN_DEBUG + std::cout << "Pushing item for use_extr_addr_finder = " << mUseExtAddrFinder << std::endl ; + #endif + saveData.push_back(vitem); + saveCleanupList.push_back(vitem); + + // Now save config for network digging strategies + + RsConfigKeyValueSet *vitem2 = new RsConfigKeyValueSet ; + + RsTlvKeyValue kv2; + kv2.key = "ALLOW_TUNNEL_CONNECTION" ; + kv2.value = (mAllowTunnelConnection)?"TRUE":"FALSE" ; + vitem2->tlvkvs.pairs.push_back(kv2) ; + + #ifdef CONN_DEBUG + std::cout << "Pushing item for allow_tunnel_connection = " << mAllowTunnelConnection << std::endl ; + #endif + saveData.push_back(vitem2); + saveCleanupList.push_back(vitem2); + + /* save groups */ + + std::list::iterator groupIt; + for (groupIt = groupList.begin(); groupIt != groupList.end(); groupIt++) { + saveData.push_back(*groupIt); // no delete + } + + return true; +} + +void p3ConnectMgr::saveDone() +{ + /* clean up the save List */ + std::list::iterator it; + for(it = saveCleanupList.begin(); it != saveCleanupList.end(); it++) + { + delete (*it); + } + + saveCleanupList.clear(); + + /* unlock mutex */ + connMtx.unlock(); /****** MUTEX UNLOCKED *******/ +} + +bool p3ConnectMgr::loadList(std::list& load) +{ + + if (load.size() == 0) { + std::cerr << "p3ConnectMgr::loadList() list is empty, it may be a configuration problem." << std::endl; + return false; + } + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::loadList() Item Count: " << load.size() << std::endl; +#endif + + std::string ownId = getOwnId(); + + /* load the list of peers */ + std::list::iterator it; + for(it = load.begin(); it != load.end(); it++) + { + RsPeerNetItem *pitem = dynamic_cast(*it); + if (pitem) + { + if (pitem->pid == ownId) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::loadList() Own Config Item:" << std::endl; + pitem->print(std::cerr, 10); + std::cerr << std::endl; +#endif + /* add ownConfig */ + setOwnNetConfig(pitem->netMode, pitem->visState); + mOwnState.gpg_id = AuthGPG::getAuthGPG()->getGPGOwnId(); + mOwnState.location = AuthSSL::getAuthSSL()->getOwnLocation(); + } + else + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::loadList() Peer Config Item:" << std::endl; + pitem->print(std::cerr, 10); + std::cerr << std::endl; +#endif + /* ************* */ + addFriend(pitem->pid, pitem->gpg_id, pitem->netMode, pitem->visState, pitem->lastContact); + setLocation(pitem->pid, pitem->location); + } + setLocalAddress(pitem->pid, pitem->currentlocaladdr); + setExtAddress(pitem->pid, pitem->currentremoteaddr); + setDynDNS (pitem->pid, pitem->dyndns); + + /* convert addresses */ + pqiIpAddrSet addrs; + addrs.mLocal.extractFromTlv(pitem->localAddrList); + addrs.mExt.extractFromTlv(pitem->extAddrList); + updateAddressList(pitem->pid, addrs); + + delete(*it); + + continue; + } + + RsConfigKeyValueSet *vitem = dynamic_cast(*it) ; + if (vitem) + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::loadList() General Variable Config Item:" << std::endl; + vitem->print(std::cerr, 10); + std::cerr << std::endl; +#endif + std::list::iterator kit; + for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); kit++) { + if(kit->key == "USE_EXTR_IP_FINDER") { + mUseExtAddrFinder = (kit->value == "TRUE"); + std::cerr << "setting use_extr_addr_finder to " << mUseExtAddrFinder << std::endl ; + } else if (kit->key == "ALLOW_TUNNEL_CONNECTION") { + mAllowTunnelConnection = (kit->value == "TRUE"); + std::cerr << "setting allow_tunnel_connection to " << mAllowTunnelConnection << std::endl ; + } + } + + delete(*it); + + continue; + } + + RsPeerGroupItem *gitem = dynamic_cast(*it) ; + if (gitem) + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::loadList() Peer group item:" << std::endl; + gitem->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + groupList.push_back(gitem); // don't delete + + if ((gitem->flag & RS_GROUP_FLAG_STANDARD) == 0) { + /* calculate group id */ + uint32_t groupId = atoi(gitem->id.c_str()); + if (groupId > lastGroupId) { + lastGroupId = groupId; + } + } + + continue; + } + + delete (*it); + } + + { + /* set missing groupIds */ + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* Standard groups */ + const int standardGroupCount = 5; + const char *standardGroup[standardGroupCount] = { RS_GROUP_ID_FRIENDS, RS_GROUP_ID_FAMILY, RS_GROUP_ID_COWORKERS, RS_GROUP_ID_OTHERS, RS_GROUP_ID_FAVORITES }; + bool foundStandardGroup[standardGroupCount] = { false, false, false, false, false }; + + std::list::iterator groupIt; + for (groupIt = groupList.begin(); groupIt != groupList.end(); groupIt++) { + if ((*groupIt)->flag & RS_GROUP_FLAG_STANDARD) { + int i; + for (i = 0; i < standardGroupCount; i++) { + if ((*groupIt)->id == standardGroup[i]) { + foundStandardGroup[i] = true; + break; + } + } + + if (i >= standardGroupCount) { + /* No more a standard group, remove the flag standard */ + (*groupIt)->flag &= ~RS_GROUP_FLAG_STANDARD; + } + } else { + uint32_t groupId = atoi((*groupIt)->id.c_str()); + if (groupId == 0) { + std::ostringstream out; + out << (lastGroupId++); + (*groupIt)->id = out.str(); + } + } + } + + /* Initialize standard groups */ + for (int i = 0; i < standardGroupCount; i++) { + if (foundStandardGroup[i] == false) { + RsPeerGroupItem *gitem = new RsPeerGroupItem; + gitem->id = standardGroup[i]; + gitem->name = standardGroup[i]; + gitem->flag |= RS_GROUP_FLAG_STANDARD; + groupList.push_back(gitem); + } + } + } + + return true; +} + + + +void printConnectState(std::ostream &out, peerConnectState &peer) +{ + + out << "Friend: " << peer.name << " Id: " << peer.id << " State: " << peer.state; + if (peer.state & RS_PEER_S_FRIEND) + out << " S:RS_PEER_S_FRIEND"; + if (peer.state & RS_PEER_S_ONLINE) + out << " S:RS_PEER_S_ONLINE"; + if (peer.state & RS_PEER_S_CONNECTED) + out << " S:RS_PEER_S_CONNECTED"; + out << " Actions: " << peer.actions; + if (peer.actions & RS_PEER_NEW) + out << " A:RS_PEER_NEW"; + if (peer.actions & RS_PEER_MOVED) + out << " A:RS_PEER_MOVED"; + if (peer.actions & RS_PEER_CONNECTED) + out << " A:RS_PEER_CONNECTED"; + if (peer.actions & RS_PEER_DISCONNECTED) + out << " A:RS_PEER_DISCONNECTED"; + if (peer.actions & RS_PEER_CONNECT_REQ) + out << " A:RS_PEER_CONNECT_REQ"; + + out << std::endl; + return; +} + + + + +/********************************************************************** + ********************************************************************** + ******************** Interfaces *********************************** + ********************************************************************** + **********************************************************************/ + + + +void p3ConnectMgr::addNetAssistFirewall(uint32_t id, pqiNetAssistFirewall *fwAgent) +{ + mFwAgents[id] = fwAgent; +} + + +bool p3ConnectMgr::enableNetAssistFirewall(bool on) +{ + std::map::iterator it; + for(it = mFwAgents.begin(); it != mFwAgents.end(); it++) + { + (it->second)->enable(on); + } + return true; +} + + +bool p3ConnectMgr::netAssistFirewallEnabled() +{ + std::map::iterator it; + for(it = mFwAgents.begin(); it != mFwAgents.end(); it++) + { + if ((it->second)->getEnabled()) + { + return true; + } + } + return false; +} + +bool p3ConnectMgr::netAssistFirewallActive() +{ + std::map::iterator it; + for(it = mFwAgents.begin(); it != mFwAgents.end(); it++) + { + if ((it->second)->getActive()) + { + return true; + } + } + return false; +} + +bool p3ConnectMgr::netAssistFirewallShutdown() +{ + std::map::iterator it; + for(it = mFwAgents.begin(); it != mFwAgents.end(); it++) + { + (it->second)->shutdown(); + } + return true; +} + +bool p3ConnectMgr::netAssistFirewallPorts(uint16_t iport, uint16_t eport) +{ + std::map::iterator it; + for(it = mFwAgents.begin(); it != mFwAgents.end(); it++) + { + (it->second)->setInternalPort(iport); + (it->second)->setExternalPort(eport); + } + return true; +} + + +bool p3ConnectMgr::netAssistExtAddress(struct sockaddr_in &extAddr) +{ + std::map::iterator it; + for(it = mFwAgents.begin(); it != mFwAgents.end(); it++) + { + if ((it->second)->getActive()) + { + if ((it->second)->getExternalAddress(extAddr)) + { + return true; + } + } + } + return false; +} + + +void p3ConnectMgr::addNetAssistConnect(uint32_t id, pqiNetAssistConnect *dht) +{ + mDhts[id] = dht; +} + +bool p3ConnectMgr::enableNetAssistConnect(bool on) +{ + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::enableNetAssistConnect(" << on << ")"; + std::cerr << std::endl; +#endif + + std::map::iterator it; + for(it = mDhts.begin(); it != mDhts.end(); it++) + { + (it->second)->enable(on); + } + return true; +} + +bool p3ConnectMgr::netAssistConnectEnabled() +{ + std::map::iterator it; + for(it = mDhts.begin(); it != mDhts.end(); it++) + { + if ((it->second)->getEnabled()) + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netAssistConnectEnabled() YES"; + std::cerr << std::endl; +#endif + + return true; + } + } + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netAssistConnectEnabled() NO"; + std::cerr << std::endl; +#endif + + return false; +} + +bool p3ConnectMgr::netAssistConnectActive() +{ + std::map::iterator it; + for(it = mDhts.begin(); it != mDhts.end(); it++) + { + if ((it->second)->getActive()) + + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netAssistConnectActive() ACTIVE"; + std::cerr << std::endl; +#endif + + return true; + } + } + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netAssistConnectActive() INACTIVE"; + std::cerr << std::endl; +#endif + + return false; +} + +bool p3ConnectMgr::netAssistConnectStats(uint32_t &netsize, uint32_t &localnetsize) +{ + std::map::iterator it; + for(it = mDhts.begin(); it != mDhts.end(); it++) + { + if (((it->second)->getActive()) && ((it->second)->getNetworkStats(netsize, localnetsize))) + + { +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netAssistConnectStats("; + std::cerr << netsize << ", " << localnetsize << ")"; + std::cerr << std::endl; +#endif + + return true; + } + } + +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netAssistConnectStats() INACTIVE"; + std::cerr << std::endl; +#endif + + return false; +} + +bool p3ConnectMgr::netAssistConnectShutdown() +{ +#ifdef CONN_DEBUG + std::cerr << "p3ConnectMgr::netAssistConnectShutdown()"; + std::cerr << std::endl; +#endif + + std::map::iterator it; + for(it = mDhts.begin(); it != mDhts.end(); it++) + { + (it->second)->shutdown(); + } + return true; +} + +bool p3ConnectMgr::netAssistFriend(std::string id, bool on) +{ + std::map::iterator it; + std::list toFind ; + std::list toDrop ; + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + for(it = mDhts.begin(); it != mDhts.end(); it++) + { + if (on) + toFind.push_back(it->second) ; + else + toDrop.push_back(it->second) ; + } + } + + for(std::list::const_iterator it(toFind.begin());it!=toFind.end();++it) + (*it)->findPeer(id) ; + for(std::list::const_iterator it(toDrop.begin());it!=toDrop.end();++it) + (*it)->dropPeer(id) ; + + return true; +} + + +bool p3ConnectMgr::netAssistSetAddress( struct sockaddr_in &laddr, + struct sockaddr_in &eaddr, + uint32_t mode) +{ +#if 0 + std::map::iterator it; + for(it = mDhts.begin(); it != mDhts.end(); it++) + { + (it->second)->setExternalInterface(laddr, eaddr, mode); + } +#endif + return true; +} + +/********************************************************************** + ********************************************************************** + ******************** Network State *********************************** + ********************************************************************** + **********************************************************************/ + +bool p3ConnectMgr::getUPnPState() +{ + return netAssistFirewallActive(); +} + +bool p3ConnectMgr::getUPnPEnabled() +{ + return netAssistFirewallEnabled(); +} + +bool p3ConnectMgr::getDHTEnabled() +{ + return netAssistConnectEnabled(); +} + + +void p3ConnectMgr::getNetStatus(pqiNetStatus &status) +{ + /* cannot lock local stack, then call DHT... as this can cause lock up */ + /* must extract data... then update mNetFlags */ + + bool dhtOk = netAssistConnectActive(); + uint32_t netsize, rsnetsize; + netAssistConnectStats(netsize, rsnetsize); + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + /* quick update of the stuff that can change! */ + mNetFlags.mDhtOk = dhtOk; + mNetFlags.mDhtNetworkSize = netsize; + mNetFlags.mDhtRsNetworkSize = rsnetsize; + + status = mNetFlags; +} + +/********************************************************************** + ********************************************************************** + ************************** Groups ************************************ + ********************************************************************** + **********************************************************************/ + +bool p3ConnectMgr::addGroup(RsGroupInfo &groupInfo) +{ + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + RsPeerGroupItem *groupItem = new RsPeerGroupItem; + groupItem->set(groupInfo); + + std::ostringstream out; + out << (++lastGroupId); + groupItem->id = out.str(); + + // remove standard flag + groupItem->flag &= ~RS_GROUP_FLAG_STANDARD; + + groupItem->PeerId(getOwnId()); + + groupList.push_back(groupItem); + } + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_ADD); + + IndicateConfigChanged(); + + return true; +} + +bool p3ConnectMgr::editGroup(const std::string &groupId, RsGroupInfo &groupInfo) +{ + if (groupId.empty()) { + return false; + } + + bool changed = false; + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::list::iterator groupIt; + for (groupIt = groupList.begin(); groupIt != groupList.end(); groupIt++) { + if ((*groupIt)->id == groupId) { + break; + } + } + + if (groupIt != groupList.end()) { + if ((*groupIt)->flag & RS_GROUP_FLAG_STANDARD) { + // can't edit standard groups + } else { + changed = true; + (*groupIt)->set(groupInfo); + } + } + } + + if (changed) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_MOD); + + IndicateConfigChanged(); + } + + return changed; +} + +bool p3ConnectMgr::removeGroup(const std::string &groupId) +{ + if (groupId.empty()) { + return false; + } + + bool changed = false; + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::list::iterator groupIt; + for (groupIt = groupList.begin(); groupIt != groupList.end(); groupIt++) { + if ((*groupIt)->id == groupId) { + break; + } + } + + if (groupIt != groupList.end()) { + if ((*groupIt)->flag & RS_GROUP_FLAG_STANDARD) { + // can't remove standard groups + } else { + changed = true; + delete(*groupIt); + groupList.erase(groupIt); + } + } + } + + if (changed) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_DEL); + + IndicateConfigChanged(); + } + + return changed; +} + +bool p3ConnectMgr::getGroupInfo(const std::string &groupId, RsGroupInfo &groupInfo) +{ + if (groupId.empty()) { + return false; + } + + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::list::iterator groupIt; + for (groupIt = groupList.begin(); groupIt != groupList.end(); groupIt++) { + if ((*groupIt)->id == groupId) { + (*groupIt)->get(groupInfo); + + return true; + } + } + + return false; +} + +bool p3ConnectMgr::getGroupInfoList(std::list &groupInfoList) +{ + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::list::iterator groupIt; + for (groupIt = groupList.begin(); groupIt != groupList.end(); groupIt++) { + RsGroupInfo groupInfo; + (*groupIt)->get(groupInfo); + groupInfoList.push_back(groupInfo); + } + + return true; +} + +// groupId == "" && assign == false -> remove from all groups +bool p3ConnectMgr::assignPeersToGroup(const std::string &groupId, const std::list &peerIds, bool assign) +{ + if (groupId.empty() && assign == true) { + return false; + } + + if (peerIds.empty()) { + return false; + } + + bool changed = false; + + { + RsStackMutex stack(connMtx); /****** STACK LOCK MUTEX *******/ + + std::list::iterator groupIt; + for (groupIt = groupList.begin(); groupIt != groupList.end(); groupIt++) { + if (groupId.empty() || (*groupIt)->id == groupId) { + RsPeerGroupItem *groupItem = *groupIt; + + std::list::const_iterator peerIt; + for (peerIt = peerIds.begin(); peerIt != peerIds.end(); peerIt++) { + std::list::iterator peerIt1 = std::find(groupItem->peerIds.begin(), groupItem->peerIds.end(), *peerIt); + if (assign) { + if (peerIt1 == groupItem->peerIds.end()) { + groupItem->peerIds.push_back(*peerIt); + changed = true; + } + } else { + if (peerIt1 != groupItem->peerIds.end()) { + groupItem->peerIds.erase(peerIt1); + changed = true; + } + } + } + + if (groupId.empty() == false) { + break; + } + } + } + } + + if (changed) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_GROUPLIST, NOTIFY_TYPE_MOD); + + IndicateConfigChanged(); + } + + return changed; +} diff --git a/libretroshare/src/pqi/p3connmgr.h b/libretroshare/src/pqi/p3connmgr.h new file mode 100644 index 000000000..082b0dc0d --- /dev/null +++ b/libretroshare/src/pqi/p3connmgr.h @@ -0,0 +1,454 @@ +/* + * libretroshare/src/pqi: p3connmgr.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_PQI_CONNECTION_MANAGER_HEADER +#define MRK_PQI_CONNECTION_MANAGER_HEADER + +#include "pqi/pqimonitor.h" +#include "pqi/pqiipset.h" + +//#include "pqi/p3dhtmgr.h" +//#include "pqi/p3upnpmgr.h" +#include "pqi/pqiassist.h" + +#include "pqi/p3cfgmgr.h" + +#include "util/rsthreads.h" + +class ExtAddrFinder ; +class DNSResolver ; + + /* RS_VIS_STATE_XXXX + * determines how public this peer wants to be... + * + * STD = advertise to Peers / DHT checking etc + * GRAY = share with friends / but not DHT + * DARK = hidden from all + * BROWN? = hidden from friends / but on DHT + */ + +const uint32_t RS_VIS_STATE_NODISC = 0x0001; +const uint32_t RS_VIS_STATE_NODHT = 0x0002; + +const uint32_t RS_VIS_STATE_STD = 0x0000; +const uint32_t RS_VIS_STATE_GRAY = RS_VIS_STATE_NODHT; +const uint32_t RS_VIS_STATE_DARK = RS_VIS_STATE_NODISC | RS_VIS_STATE_NODHT; +const uint32_t RS_VIS_STATE_BROWN = RS_VIS_STATE_NODISC; + + + + + /* Startup Modes (confirmed later) */ +const uint32_t RS_NET_MODE_TRYMODE = 0x00f0; + +const uint32_t RS_NET_MODE_TRY_EXT = 0x0010; +const uint32_t RS_NET_MODE_TRY_UPNP = 0x0020; +const uint32_t RS_NET_MODE_TRY_UDP = 0x0040; + + /* Actual State */ +const uint32_t RS_NET_MODE_ACTUAL = 0x000f; + +const uint32_t RS_NET_MODE_UNKNOWN = 0x0000; +const uint32_t RS_NET_MODE_EXT = 0x0001; +const uint32_t RS_NET_MODE_UPNP = 0x0002; +const uint32_t RS_NET_MODE_UDP = 0x0004; +const uint32_t RS_NET_MODE_UNREACHABLE = 0x0008; + + +/* order of attempts ... */ +const uint32_t RS_NET_CONN_TCP_ALL = 0x000f; +const uint32_t RS_NET_CONN_UDP_ALL = 0x00f0; +const uint32_t RS_NET_CONN_TUNNEL = 0x0f00; + +const uint32_t RS_NET_CONN_TCP_LOCAL = 0x0001; +const uint32_t RS_NET_CONN_TCP_EXTERNAL = 0x0002; +const uint32_t RS_NET_CONN_TCP_UNKNOW_TOPOLOGY = 0x0004; +const uint32_t RS_NET_CONN_UDP_DHT_SYNC = 0x0010; +const uint32_t RS_NET_CONN_UDP_PEER_SYNC = 0x0020; /* coming soon */ + +/* extra flags */ +// not sure if needed yet. +//const uint32_t RS_NET_CONN_PEERAGE = 0x0f00; +//const uint32_t RS_NET_CONN_SERVER = 0x0100; /* TCP only */ +//const uint32_t RS_NET_CONN_PEER = 0x0200; /* all UDP */ + + +/* flags of peerStatus */ +const uint32_t RS_NET_FLAGS_USE_DISC = 0x0001; +const uint32_t RS_NET_FLAGS_USE_DHT = 0x0002; +const uint32_t RS_NET_FLAGS_ONLINE = 0x0004; +const uint32_t RS_NET_FLAGS_EXTERNAL_ADDR = 0x0008; +const uint32_t RS_NET_FLAGS_STABLE_UDP = 0x0010; +const uint32_t RS_NET_FLAGS_TRUSTS_ME = 0x0020; + +const uint32_t RS_TCP_STD_TIMEOUT_PERIOD = 5; /* 5 seconds! */ + +class peerAddrInfo +{ + public: + peerAddrInfo(); /* init */ + + bool found; + uint32_t type; + pqiIpAddrSet addrs; + time_t ts; +}; + +class peerConnectAddress +{ + public: + peerConnectAddress(); /* init */ + + struct sockaddr_in addr; + uint32_t delay; /* to stop simultaneous connects */ + uint32_t period; /* UDP only */ + uint32_t type; + time_t ts; +}; + +class peerConnectState +{ + public: + peerConnectState(); /* init */ + + std::string id; + std::string gpg_id; + + uint32_t netMode; /* EXT / UPNP / UDP / INVALID */ + uint32_t visState; /* STD, GRAY, DARK */ + + struct sockaddr_in localaddr, serveraddr; + + //used to store current ip (for config and connection management) + struct sockaddr_in currentlocaladdr; /* Mandatory */ + struct sockaddr_in currentserveraddr; /* Mandatory */ + std::string dyndns; + + time_t lastcontact; + + /* list of addresses from various sources */ + pqiIpAddrSet ipAddrs; + + /***** Below here not stored permanently *****/ + + uint32_t connecttype; // RS_NET_CONN_TCP_ALL / RS_NET_CONN_UDP_ALL + time_t lastavailable; + time_t lastattempt; + + std::string name; + std::string location; + + uint32_t state; + uint32_t actions; + + uint32_t source; /* most current source */ + peerAddrInfo dht; + peerAddrInfo disc; + peerAddrInfo peer; + + /* a list of connect attempts to make (in order) */ + bool inConnAttempt; + peerConnectAddress currentConnAddrAttempt; + std::list connAddrs; + + +}; + +class pqiNetStatus +{ + public: + + pqiNetStatus(); + + bool mLocalAddrOk; // Local address is not loopback. + bool mExtAddrOk; // have external address. + bool mExtAddrStableOk; // stable external address. + bool mUpnpOk; // upnp is ok. + bool mDhtOk; // dht is ok. + + uint32_t mDhtNetworkSize; + uint32_t mDhtRsNetworkSize; + + struct sockaddr_in mLocalAddr; // percieved ext addr. + struct sockaddr_in mExtAddr; // percieved ext addr. + + bool mResetReq; // Not Used yet!. + + void print(std::ostream &out); + + bool NetOk() // minimum to believe network is okay.` + { + return (mLocalAddrOk && mExtAddrOk); + } +}; + +class p3tunnel; +class RsPeerGroupItem; +class RsGroupInfo; + +std::string textPeerConnectState(peerConnectState &state); + + +class p3ConnectMgr: public pqiConnectCb, public p3Config +{ + public: + + p3ConnectMgr(); + +void tick(); + + /*************** Setup ***************************/ +void addNetAssistConnect(uint32_t type, pqiNetAssistConnect *); +void addNetAssistFirewall(uint32_t type, pqiNetAssistFirewall *); + +void addNetListener(pqiNetListener *listener); + +bool checkNetAddress(); /* check our address is sensible */ + + /*************** External Control ****************/ +bool shutdown(); /* blocking shutdown call */ + +bool retryConnect(const std::string &id); + +bool getUPnPState(); +bool getUPnPEnabled(); +bool getDHTEnabled(); +bool getDHTStats(uint32_t &netsize, uint32_t &localnetsize); + +bool getIPServersEnabled(); +void setIPServersEnabled(bool b) ; +void getIPServersList(std::list& ip_servers) ; + +void setTunnelConnection(bool b); +bool getTunnelConnection(); + +bool getNetStatusLocalOk(); +bool getNetStatusUpnpOk(); +bool getNetStatusDhtOk(); +bool getNetStatusStunOk(); +bool getNetStatusExtraAddressCheckOk(); + +bool getUpnpExtAddress(struct sockaddr_in &addr); +bool getExtFinderAddress(struct sockaddr_in &addr); +void getNetStatus(pqiNetStatus &status); + +void setOwnNetConfig(uint32_t netMode, uint32_t visState); +bool setLocalAddress(const std::string &id, struct sockaddr_in addr); +bool setExtAddress(const std::string &id, struct sockaddr_in addr); +bool setDynDNS(const std::string &id, const std::string &dyndns); +bool updateAddressList(const std::string& id, const pqiIpAddrSet &addrs); + +bool setNetworkMode(const std::string &id, uint32_t netMode); +bool setVisState(const std::string &id, uint32_t visState); + +bool setLocation(const std::string &pid, const std::string &location);//location is shown in the gui to differentiate ssl certs + + /* add/remove friends */ +bool addFriend(const std::string &ssl_id, const std::string &gpg_id, uint32_t netMode = RS_NET_MODE_UDP, + uint32_t visState = RS_VIS_STATE_STD , time_t lastContact = 0); + +bool removeFriend(const std::string &ssl_id); +bool addNeighbour(const std::string&); + + /*************** External Control ****************/ + + /* access to network details (called through Monitor) */ +const std::string getOwnId(); +bool getOwnNetStatus(peerConnectState &state); + +bool isFriend(const std::string &ssl_id); +bool isOnline(const std::string &ssl_id); +bool getFriendNetStatus(const std::string &id, peerConnectState &state); +bool getOthersNetStatus(const std::string &id, peerConnectState &state); + +void getOnlineList(std::list &ssl_peers); +void getFriendList(std::list &ssl_peers); +//void getOthersList(std::list &peers); /deprecated +bool getPeerCount (unsigned int *pnFriendCount, unsigned int *pnOnlineCount, bool ssl); + + + /**************** handle monitors *****************/ +void addMonitor(pqiMonitor *mon); +void removeMonitor(pqiMonitor *mon); + + /******* overloaded from pqiConnectCb *************/ +virtual void peerStatus(std::string id, const pqiIpAddrSet &addrs, + uint32_t type, uint32_t flags, uint32_t source); +virtual void peerConnectRequest(std::string id, + struct sockaddr_in raddr, uint32_t source); +//virtual void stunStatus(std::string id, struct sockaddr_in raddr, uint32_t type, uint32_t flags); + + /****************** Connections *******************/ +bool connectAttempt(const std::string &id, struct sockaddr_in &addr, + uint32_t &delay, uint32_t &period, uint32_t &type); +bool connectResult(const std::string &id, bool success, uint32_t flags, struct sockaddr_in remote_peer_address); + + /******************** Groups **********************/ +bool addGroup(RsGroupInfo &groupInfo); +bool editGroup(const std::string &groupId, RsGroupInfo &groupInfo); +bool removeGroup(const std::string &groupId); +bool getGroupInfo(const std::string &groupId, RsGroupInfo &groupInfo); +bool getGroupInfoList(std::list &groupInfoList); +bool assignPeersToGroup(const std::string &groupId, const std::list &peerIds, bool assign); + + +protected: + /****************** Internal Interface *******************/ +virtual bool enableNetAssistFirewall(bool on); +virtual bool netAssistFirewallEnabled(); +virtual bool netAssistFirewallActive(); +virtual bool netAssistFirewallShutdown(); + +virtual bool enableNetAssistConnect(bool on); +virtual bool netAssistConnectEnabled(); +virtual bool netAssistConnectActive(); +virtual bool netAssistConnectShutdown(); +virtual bool netAssistConnectStats(uint32_t &netsize, uint32_t &localnetsize); + + +/* Assist Firewall */ +bool netAssistExtAddress(struct sockaddr_in &extAddr); +bool netAssistFirewallPorts(uint16_t iport, uint16_t eport); + + /* Assist Connect */ +virtual bool netAssistFriend(std::string id, bool on); +virtual bool netAssistSetAddress( struct sockaddr_in &laddr, + struct sockaddr_in &eaddr, + uint32_t mode); + + + /* Internal Functions */ +void netReset(); + +void statusTick(); +void netTick(); +void netStartup(); + + /* startup the bits */ +void netDhtInit(); +void netUdpInit(); +void netStunInit(); + + + +void netInit(); + +void netExtInit(); +void netExtCheck(); + +void netUpnpInit(); +void netUpnpCheck(); + +void netUnreachableCheck(); + +void networkConsistencyCheck(); + + /* monitor control */ +void tickMonitors(); + + /* connect attempts UDP */ +bool retryConnectUDP(const std::string &id, struct sockaddr_in &rUdpAddr); + + /* connect attempts TCP */ +bool retryConnectTCP(const std::string &id); + +void locked_ConnectAttempt_CurrentAddresses(peerConnectState *peer); +void locked_ConnectAttempt_HistoricalAddresses(peerConnectState *peer); +void locked_ConnectAttempt_AddDynDNS(peerConnectState *peer); +void locked_ConnectAttempt_AddTunnel(peerConnectState *peer); + +bool locked_ConnectAttempt_Complete(peerConnectState *peer); + +bool locked_CheckPotentialAddr(struct sockaddr_in *addr, time_t age); +bool addAddressIfUnique(std::list &addrList, + peerConnectAddress &pca); + + + protected: +/*****************************************************************/ +/*********************** p3config ******************************/ + /* Key Functions to be overloaded for Full Configuration */ + virtual RsSerialiser *setupSerialiser(); + virtual bool saveList(bool &cleanup, std::list&); + virtual void saveDone(); + virtual bool loadList(std::list& load); +/*****************************************************************/ + +//void setupOwnNetConfig(RsPeerConfigItem *item); +//void addPeer(RsPeerConfigItem *item); + +private: + // These should have there own Mutex Protection, + //p3tunnel *mP3tunnel; + ExtAddrFinder *mExtAddrFinder ; + DNSResolver *mDNSResolver ; + + /* These are considered static from a MUTEX perspective */ + std::map mFwAgents; + std::map mDhts; + + std::list mNetListeners; + + + RsMutex connMtx; /* protects below */ + +void netStatusReset_locked(); + + uint32_t mRetryPeriod; + + time_t mNetInitTS; + uint32_t mNetStatus; + + bool mStatusChanged; + + std::list clients; + + bool mUseExtAddrFinder; + bool mAllowTunnelConnection; + + /* external Address determination */ + //bool mUpnpAddrValid, mStunAddrValid; + //struct sockaddr_in mUpnpExtAddr; + + /* network status flags (read by rsiface) */ + pqiNetStatus mNetFlags; + pqiNetStatus mOldNetFlags; + + peerConnectState mOwnState; + + std::map mFriendList; + std::map mOthersList; + + std::list groupList; + uint32_t lastGroupId; + + std::list saveCleanupList; /* TEMPORARY LIST WHEN SAVING */ + + + /* relatively static list of banned ip addresses */ + std::list mBannedIpList; +}; + +#endif // MRK_PQI_CONNECTION_MANAGER_HEADER diff --git a/libretroshare/src/pqi/p3dhtmgr.cc b/libretroshare/src/pqi/p3dhtmgr.cc new file mode 100644 index 000000000..f6b0f9236 --- /dev/null +++ b/libretroshare/src/pqi/p3dhtmgr.cc @@ -0,0 +1,1812 @@ +/* + * libretroshare/src/pqi: p3dhtmgr.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include +#include + +#include "pqi/p3dhtmgr.h" +#include "pqi/p3connmgr.h" + +#include "util/rsprint.h" +#include "util/rsdebug.h" +const int p3dhtzone = 3892; + +/***** + * #define DHT_DEBUG 1 + * #define P3DHTMGR_USE_LOCAL_UDP_CONN 1 // For Testing only + ****/ + +/**** DHT State Variables **** + * TODO: + * (1) notify call in. + * (2) publish/search parameters. + * (3) callback. + * (4) example + * + */ + +/**** DHT State Variables ****/ + +#define DHT_STATE_OFF 0 +#define DHT_STATE_INIT 1 +#define DHT_STATE_CHECK_PEERS 2 +#define DHT_STATE_FIND_STUN 3 +#define DHT_STATE_ACTIVE 4 + +/* TIMEOUTS (Key ones in .h) */ +#define DHT_RESTART_PERIOD 300 /* 5 min */ +#define DHT_DEFAULT_PERIOD 300 /* Default period if no work to do */ +#define DHT_MIN_PERIOD 1 /* to ensure we don't get too many requests */ +#define DHT_SHORT_PERIOD 10 /* a short period */ + +#define DHT_DEFAULT_WAITTIME 1 /* Std sleep break period */ + +#define DHT_NUM_BOOTSTRAP_BINS 8 +#define DHT_MIN_BOOTSTRAP_REQ_PERIOD 5 + +void printDhtPeerEntry(dhtPeerEntry *ent, std::ostream &out); + +/* Interface class for DHT data */ + +dhtPeerEntry::dhtPeerEntry() + :state(DHT_PEER_INIT), lastTS(0), + notifyPending(0), notifyTS(0), + type(DHT_ADDR_INVALID) +{ + laddr.sin_addr.s_addr = 0; + laddr.sin_port = 0; + laddr.sin_family = 0; + + raddr.sin_addr.s_addr = 0; + raddr.sin_port = 0; + raddr.sin_family = 0; + + return; +} + +p3DhtMgr::p3DhtMgr(std::string id, pqiConnectCb *cb) + :pqiNetAssistConnect(id, cb), mStunRequired(true) +{ + /* setup own entry */ + dhtMtx.lock(); /* LOCK MUTEX */ + + ownEntry.id = id; + ownEntry.state = DHT_PEER_INIT; + ownEntry.type = DHT_ADDR_INVALID; + ownEntry.lastTS = 0; + + ownEntry.notifyPending = 0; + ownEntry.notifyTS = 0; + + ownEntry.hash1 = RsUtil::HashId(id, false); + ownEntry.hash2 = RsUtil::HashId(id, true); + + mDhtModifications = true; + mDhtOn = false; + mDhtState = DHT_STATE_OFF; + + mBootstrapAllowed = true; + mLastBootstrapListTS = 0; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return; +} + + /* OVERLOADED from pqiNetAssistConnect + */ + +void p3DhtMgr::shutdown() +{ + /* ??? */ + +} + +void p3DhtMgr::restart() +{ + /* ??? */ +} + +void p3DhtMgr::enable(bool on) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + mDhtOn = on; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ +} + +bool p3DhtMgr::getEnabled() +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + bool on = mDhtOn; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return on; +} + +bool p3DhtMgr::getActive() +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + bool act = dhtActive(); + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return act; +} + +void p3DhtMgr::setBootstrapAllowed(bool on) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mBootstrapAllowed = on; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ +} + +bool p3DhtMgr::getBootstrapAllowed() +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + bool on = mBootstrapAllowed; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return on; +} + +/******************************** PEER MANAGEMENT ********************************** + * + */ + /* set key data */ +bool p3DhtMgr::setExternalInterface( + struct sockaddr_in laddr, + struct sockaddr_in raddr, + uint32_t type) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + ownEntry.laddr = laddr; + ownEntry.raddr = raddr; + ownEntry.type = type; + ownEntry.state = DHT_PEER_ADDR_KNOWN; /* will force republish */ + ownEntry.lastTS = 0; /* will force republish */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::setExternalInterface()"; + std::cerr << " laddr: " << rs_inet_ntoa(ownEntry.laddr.sin_addr); + std::cerr << " lport: " << ntohs(ownEntry.laddr.sin_port); + std::cerr << " raddr: " << rs_inet_ntoa(ownEntry.raddr.sin_addr); + std::cerr << " rport: " << ntohs(ownEntry.raddr.sin_port); + std::cerr << " type: " << ownEntry.type; + std::cerr << " state: " << ownEntry.state; + std::cerr << std::endl; +#endif + + /* Log External Interface too */ + std::ostringstream out; + out << "p3DhtMgr::setExternalInterface()"; + out << " laddr: " << rs_inet_ntoa(ownEntry.laddr.sin_addr); + out << " lport: " << ntohs(ownEntry.laddr.sin_port); + out << " raddr: " << rs_inet_ntoa(ownEntry.raddr.sin_addr); + out << " rport: " << ntohs(ownEntry.raddr.sin_port); + out << " type: " << ownEntry.type; + out << " state: " << ownEntry.state; + + rslog(RSL_WARNING, p3dhtzone, out.str()); + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + checkOwnDHTKeys(); + return true; +} + + + /* add / remove peers */ +bool p3DhtMgr::findPeer(std::string id) +{ + RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ + + mDhtModifications = true; + + std::map::iterator it; + it = peers.find(id); + if (it != peers.end()) + { + /* reset some of it */ + it->second.state = DHT_PEER_INIT; + + // No point destroying a valid address!. + //it->second.type = DHT_ADDR_INVALID; + + // Reset notify + it->second.notifyPending = 0; + it->second.notifyTS = 0; + + return true; + } + + /* if they are not in the list -> add */ + dhtPeerEntry ent; + ent.id = id; + ent.state = DHT_PEER_INIT; + ent.type = DHT_ADDR_INVALID; + ent.lastTS = 0; + + ent.notifyPending = 0; + ent.notifyTS = 0; + + /* fill in hashes */ + ent.hash1 = RsUtil::HashId(id, false); + ent.hash2 = RsUtil::HashId(id, true); + + /* other fields don't matter */ + + peers[id] = ent; + + return true; +} + +bool p3DhtMgr::dropPeer(std::string id) +{ + RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ + + mDhtModifications = true; + + /* once we are connected ... don't worry about them anymore */ + std::map::iterator it; + it = peers.find(id); + if (it == peers.end()) + { + return false; + } + + /* leave it in there - just switch to off */ + it->second.state = DHT_PEER_OFF; + + return true; +} + + /* post DHT key saying we should connect */ +bool p3DhtMgr::notifyPeer(std::string id) +{ + RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::notifyPeer() " << id << std::endl; +#endif + + std::map::iterator it; + it = peers.find(id); + if (it == peers.end()) + { + return false; + } + /* ignore OFF peers */ + if (it->second.state == DHT_PEER_OFF) + { + return false; + } + + + time_t now = time(NULL); + + if (now - it->second.notifyTS < 2 * DHT_NOTIFY_PERIOD) + { + /* drop the notify (too soon) */ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::notifyPeer() TO SOON - DROPPING" << std::endl; +#endif + { + /* Log */ + std::ostringstream out; + out << "p3DhtMgr::notifyPeer() Id: " << id; + out << " TO SOON - DROPPING"; + rslog(RSL_WARNING, p3dhtzone, out.str()); + } + return false; + } + + it->second.notifyPending = RS_CONNECT_ACTIVE; + it->second.notifyTS = time(NULL); + + /* Trigger search if not found! */ + if (it->second.state != DHT_PEER_FOUND) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::notifyPeer() PEER NOT FOUND - Trigger search" << std::endl; +#endif + { + /* Log */ + std::ostringstream out; + out << "p3DhtMgr::notifyPeer() Id: " << id; + out << " PEER NOT FOUND - Trigger Search"; + rslog(RSL_WARNING, p3dhtzone, out.str()); + } + it->second.lastTS = 0; + } + + mDhtModifications = true; /* no wait! */ + + return true; +} + + /* extract current peer status */ +bool p3DhtMgr::getPeerStatus(std::string id, + struct sockaddr_in &laddr, + struct sockaddr_in &raddr, + uint32_t &type, uint32_t &state) +{ + RsStackMutex stack(dhtMtx); /* LOCK MUTEX */ + + std::map::iterator it; + it = peers.find(id); + + /* ignore OFF peers */ + if ((it == peers.end()) || (it->second.state == DHT_PEER_OFF)) + { + return false; + } + + laddr = it->second.laddr; + raddr = it->second.raddr; + type = it->second.type; + state = it->second.type; + + return true; +} + +/********************************* STUN HANDLING ********************************** + * add / cleanup / stun. + * + */ + + /* stun */ +bool p3DhtMgr::addStun(std::string id) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + + std::list::iterator it; + it = std::find(stunIds.begin(), stunIds.end(), id); + if (it != stunIds.end()) + { + dhtMtx.unlock(); /* UNLOCK MUTEX */ + return false; + } + stunIds.push_back(id); + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return true; +} + +bool p3DhtMgr::enableStun(bool on) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtModifications = true; + + if (!on) + { + /* clear up */ + stunIds.clear(); + } + + mStunRequired = on; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return true; +} + + +void p3DhtMgr::run() +{ + /* + * + */ + + while(1) + { + checkDHTStatus(); + + +#ifdef DHT_DEBUG + status(std::cerr); +#endif + + dhtMtx.lock(); /* LOCK MUTEX */ + + uint32_t dhtState = mDhtState; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + int period = 60; /* default wait */ + switch(dhtState) + { + case DHT_STATE_INIT: +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = INIT -> wait" << std::endl; +#endif + period = 10; + break; + case DHT_STATE_CHECK_PEERS: +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = CHECK_PEERS -> do stuff" << std::endl; +#endif + checkPeerDHTKeys(); + checkStunState(); + period = DHT_MIN_PERIOD; + break; + case DHT_STATE_FIND_STUN: +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = FIND_STUN -> do stuff" << std::endl; +#endif + doStun(); + checkPeerDHTKeys(); /* keep on going - as we could be in this state for a while */ + checkStunState(); + period = DHT_MIN_PERIOD; + break; + case DHT_STATE_ACTIVE: + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = ACTIVE -> do stuff" << std::endl; +#endif + + period = checkOwnDHTKeys(); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() checkOwnDHTKeys() period: " << period << std::endl; +#endif + int tmpperiod = checkNotifyDHT(); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() checkNotifyDHT() period: " << tmpperiod << std::endl; +#endif + int tmpperiod2 = checkPeerDHTKeys(); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() checkPeerDHTKeys() period: " << tmpperiod2 << std::endl; +#endif + if (tmpperiod < period) + period = tmpperiod; + if (tmpperiod2 < period) + period = tmpperiod2; + + /* finally we need to keep stun going */ + if (checkStunState_Active()) + { + /* still more stun to do */ + period = DHT_SHORT_PERIOD; + doStun(); + } + + } + break; + default: + case DHT_STATE_OFF: +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() state = OFF -> wait" << std::endl; +#endif + period = 60; + break; + } + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() sleeping for: " << period << std::endl; +#endif + + /* Breakable sleep loop */ + + bool toBreak = false; + int waittime = 1; + int i; + for(i = 0; i < period; i += waittime) + { + if (period-i > DHT_DEFAULT_WAITTIME) + { + waittime = DHT_DEFAULT_WAITTIME; + } + else + { + waittime = period-i; + } + + dhtMtx.lock(); /* LOCK MUTEX */ + + if (mDhtModifications) + { + mDhtModifications = false; + toBreak = true; + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + if (toBreak) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::run() breaking sleep" << std::endl; +#endif + + break; /* speed up config modifications */ + } + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + sleep(waittime); +#else + Sleep(1000 * waittime); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + } + } +} + + +int p3DhtMgr::checkOwnDHTKeys() +{ + int repubPeriod = 10000; + time_t now = time(NULL); + + /* in order of importance: + * (1) Check for Own Key publish. + * (2) Check for notification requests + * (3) Check for Peers + */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys()" << std::endl; +#endif + + dhtMtx.lock(); /* LOCK MUTEX */ + + dhtPeerEntry peer = ownEntry; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + /* publish ourselves if necessary */ + if (peer.state >= DHT_PEER_ADDR_KNOWN) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() OWN ADDR KNOWN" << std::endl; +#endif + if ((peer.state < DHT_PEER_PUBLISHED) || + (now - peer.lastTS > DHT_PUBLISH_PERIOD)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() OWN ADDR REPUB" << std::endl; +#endif + +#ifdef DHT_DEBUG + std::cerr << "PUBLISH: "; + std::cerr << " hash1: " << RsUtil::BinToHex(peer.hash1); + std::cerr << " laddr: " << rs_inet_ntoa(peer.laddr.sin_addr); + std::cerr << ":" << ntohs(peer.laddr.sin_port); + std::cerr << " raddr: " << rs_inet_ntoa(peer.raddr.sin_addr); + std::cerr << ":" << ntohs(peer.raddr.sin_port); + std::cerr << " type: " << peer.type; + std::cerr << std::endl; +#endif + + { + /* Log */ + std::ostringstream out; + out << "p3DhtMgr::checkOwnDHTKeys() PUBLISH OWN ADDR:"; + out << " hash1: " << RsUtil::BinToHex(peer.hash1); + out << " laddr: " << rs_inet_ntoa(peer.laddr.sin_addr); + out << " :" << ntohs(peer.laddr.sin_port); + out << " raddr: " << rs_inet_ntoa(peer.raddr.sin_addr); + out << ":" << ntohs(peer.raddr.sin_port); + out << " type: " << peer.type; + + rslog(RSL_WARNING, p3dhtzone, out.str()); + } + + /* publish own key */ + if (dhtPublish(peer.hash1, peer.laddr, peer.raddr, peer.type, "")) + { + dhtMtx.lock(); /* LOCK MUTEX */ + + ownEntry.lastTS = now; + ownEntry.state = DHT_PEER_PUBLISHED; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + } + + /* dhtBootstrap -> if allowed and EXT port */ + if (peer.type & RS_NET_CONN_TCP_EXTERNAL) + { + dhtMtx.lock(); /* LOCK MUTEX */ + + bool doBootstrapPub = mBootstrapAllowed; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + if (doBootstrapPub) + { + dhtBootstrap(randomBootstrapId(), peer.hash1, ""); + } + } + + /* restart immediately */ + repubPeriod = DHT_MIN_PERIOD; + return repubPeriod; + } + else + { + if (now - peer.lastTS < DHT_PUBLISH_PERIOD) + { + repubPeriod = DHT_PUBLISH_PERIOD - + (now - peer.lastTS); + } + else + { + repubPeriod = 10; + } +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() repub in: "; + std::cerr << repubPeriod << std::endl; +#endif + } + + + /* check for connect requests */ + //if ((peer.state == DHT_PEER_PUBLISHED) && + // (!(peer.type & RS_NET_CONN_TCP_EXTERNAL))) + if (peer.state == DHT_PEER_PUBLISHED) + { + if (now - peer.notifyTS >= DHT_NOTIFY_PERIOD) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() check for Notify (rep=0)"; + std::cerr << std::endl; +#endif + { + /* Log */ + std::ostringstream out; + out << "p3DhtMgr::checkOwnDHTKeys() Checking for NOTIFY"; + rslog(RSL_WARNING, p3dhtzone, out.str()); + } + + if (dhtSearch(peer.hash1, DHT_MODE_NOTIFY)) + { + dhtMtx.lock(); /* LOCK MUTEX */ + + ownEntry.notifyTS = now; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + } + + /* restart immediately */ + repubPeriod = DHT_MIN_PERIOD; + return repubPeriod; + } + else + { + repubPeriod = DHT_NOTIFY_PERIOD - + (now - peer.notifyTS); + if (repubPeriod < DHT_MIN_PERIOD) + { + repubPeriod = DHT_MIN_PERIOD; + } +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() check Notify in: "; + std::cerr << repubPeriod << std::endl; +#endif + } + } + else + { + if (peer.state != DHT_PEER_PUBLISHED) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() No Notify until Published"; + std::cerr << std::endl; +#endif + } + else if (peer.type & RS_NET_CONN_TCP_EXTERNAL) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() No Notify because have Ext Addr"; + std::cerr << std::endl; +#endif + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() No Notify: Unknown Reason"; + std::cerr << std::endl; +#endif + } + } + + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkOwnDHTKeys() PEER ADDR UNKNOWN" << std::endl; +#endif + repubPeriod = 10; + } + return repubPeriod; +} + + +int p3DhtMgr::checkPeerDHTKeys() +{ + /* now loop through the peers */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkPeerDHTKeys()" << std::endl; +#endif + + dhtMtx.lock(); /* LOCK MUTEX */ + + /* iterate through and find min time and suitable candidate */ + std::map::iterator it,pit; + time_t now = time(NULL); + uint32_t period = 0; + uint32_t repeatPeriod = 6000; + + pit = peers.end(); + time_t pTS = now; + + for(it = peers.begin(); it != peers.end(); it++) + { + /* ignore OFF peers */ + if (it->second.state == DHT_PEER_OFF) + { + continue; + } + + time_t delta = now - it->second.lastTS; + if (it->second.state < DHT_PEER_FOUND) + { + period = DHT_SEARCH_PERIOD; + } + else /* (it->second.state == DHT_PEER_FOUND) */ + { + period = DHT_CHECK_PERIOD; + } +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkPeerDHTKeys() Peer: " << it->second.id; + std::cerr << " Period: " << period; + std::cerr << " Delta: " << delta; + std::cerr << std::endl; +#endif + + + if ((unsigned) delta >= period) + { + if (it->second.lastTS < pTS) + { + pit = it; + pTS = it->second.lastTS; + } + repeatPeriod = DHT_MIN_PERIOD; + } + else if (period - delta < repeatPeriod) + { + repeatPeriod = period - delta; + } + } + + /* now have - peer to handle, and period to next call */ + + if (pit == peers.end()) + { + dhtMtx.unlock(); /* UNLOCK MUTEX */ + return repeatPeriod; + } + + /* update timestamp + * clear FOUND or INIT state. + * */ + + pit->second.lastTS = now; + pit->second.state = DHT_PEER_SEARCH; + + dhtPeerEntry peer = (pit->second); + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + /* now search for the peer */ + dhtSearch(peer.hash1, DHT_MODE_SEARCH); + + /* results come through callback */ + return repeatPeriod; +} + + +int p3DhtMgr::checkNotifyDHT() +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkNotifyDHT()" << std::endl; +#endif + /* now loop through the peers */ + uint32_t notifyType = 0; + dhtPeerEntry peer; + dhtPeerEntry own; + + { + RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ + + /* iterate through and find min time and suitable candidate */ + std::map::iterator it; + time_t now = time(NULL); + int repeatPeriod = DHT_DEFAULT_PERIOD; + + /* find the first with a notify flag */ + for(it = peers.begin(); it != peers.end(); it++) + { + /* ignore OFF peers */ + if (it->second.state == DHT_PEER_OFF) + { + continue; + } + + if (it->second.notifyPending) + { + /* if very old drop it */ + if (now - it->second.notifyTS > DHT_NOTIFY_PERIOD) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkNotifyDHT() Dropping OLD Notify: "; + std::cerr << it->first << std::endl; +#endif + it->second.notifyPending = 0; + } + + if (it->second.state == DHT_PEER_FOUND) + { + notifyType = it->second.notifyPending; + break; + } + } + } + + /* now have - peer to handle */ + if (it == peers.end()) + { + return repeatPeriod; + } + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkNotifyDHT() Notify From: "; + std::cerr << it->first << std::endl; +#endif + { + /* Log */ + std::ostringstream out; + out << "p3DhtMgr::checkNotifyDHT() Notify Request for Known Peer: " << it->first; + rslog(RSL_WARNING, p3dhtzone, out.str()); + } + + /* update timestamp */ + it->second.notifyTS = now; + it->second.notifyPending = 0; + + peer = (it->second); + own = ownEntry; + + } /******* UNLOCK ******/ + + if (notifyType == RS_CONNECT_ACTIVE) + { + /* publish notification (publish Our Id) + * We publish the connection attempt on peers hash, + * using our alternative hash.. + * */ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkNotifyDHT() Posting Active Notify"; + std::cerr << std::endl; +#endif + { + /* Log */ + std::ostringstream out; + out << "p3DhtMgr::checkNotifyDHT() POST DHT (Active Notify) for Peer: " << peer.id; + rslog(RSL_WARNING, p3dhtzone, out.str()); + } + + dhtNotify(peer.hash1, own.hash2, ""); + } + + /* feedback to say we started it! */ +#ifdef P3DHTMGR_USE_LOCAL_UDP_CONN + mConnCb->peerConnectRequest(peer.id, peer.laddr, RS_CB_DHT); +#else + mConnCb->peerConnectRequest(peer.id, peer.raddr, RS_CB_DHT); +#endif + + return DHT_MIN_PERIOD; +} + + + +int p3DhtMgr::doStun() +{ + if (stunIds.size() < 1) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::doStun() Failed -> no Ids left" << std::endl; +#endif + return 0; + } + + dhtMtx.lock(); /* LOCK MUTEX */ + + bool stunRequired = mStunRequired; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + /* now loop through the peers */ + if (!stunRequired) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::doStun() not Required" << std::endl; +#endif + return 0; + } + + /* pop the front one */ + std::string activeStunId = stunIds.front(); + + stunIds.pop_front(); + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::doStun() STUN: " << RsUtil::BinToHex(activeStunId); + std::cerr << std::endl; +#endif + + /* look it up! */ + dhtSearch(activeStunId, DHT_MODE_SEARCH); + + return 1; +} + + + +int p3DhtMgr::checkStunState() +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkStunState()" << std::endl; +#endif + dhtMtx.lock(); /* LOCK MUTEX */ + + /* now loop through the peers */ + if (!mStunRequired) + { + mDhtState = DHT_STATE_ACTIVE; + } + + if (mDhtState == DHT_STATE_CHECK_PEERS) + { + /* check that they have all be searched for */ + std::map::iterator it; + for(it = peers.begin(); it != peers.end(); it++) + { + if (it->second.state == DHT_PEER_INIT) + { + break; + } + } + + if (it == peers.end()) + { + /* we've checked all peers */ + mDhtState = DHT_STATE_FIND_STUN; + } + } + else if (mDhtState == DHT_STATE_FIND_STUN) + { + } + + /* if we run out of stun peers -> get some more */ + if (stunIds.size() < 1) + { +#ifdef DHT_DEBUG + std::cerr << "WARNING: out of Stun Peers - Fetching some more" << std::endl; +#endif + mDhtState = DHT_STATE_ACTIVE; + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + /* this is a locked function */ + getDhtBootstrapList(); + + dhtMtx.lock(); /* LOCK MUTEX */ + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + return 1; +} + +int p3DhtMgr::checkStunState_Active() +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkStunState_Active()" << std::endl; +#endif + dhtMtx.lock(); /* LOCK MUTEX */ + + bool stunReq = mStunRequired; + bool moreIds = ((mStunRequired) && (stunIds.size() < 1)); + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + if (moreIds) + /* if we run out of stun peers -> get some more */ + { +#ifdef DHT_DEBUG + std::cerr << "WARNING: out of Stun Peers - getting more" << std::endl; +#endif + getDhtBootstrapList(); + } + + return stunReq; +} + +bool p3DhtMgr::getDhtBootstrapList() +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::getDHTBootstrapList()" << std::endl; +#endif + dhtMtx.lock(); /* LOCK MUTEX */ + + time_t now = time(NULL); + if (now - mLastBootstrapListTS < DHT_MIN_BOOTSTRAP_REQ_PERIOD) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::getDHTBootstrapList() Waiting: "; + std::cerr << DHT_MIN_BOOTSTRAP_REQ_PERIOD-(now-mLastBootstrapListTS); + std::cerr << " secs" << std::endl; +#endif + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return false; + } + + mLastBootstrapListTS = now; + std::string bootId = randomBootstrapId(); + + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::getDHTBootstrapList() bootId: 0x"; + std::cerr << RsUtil::BinToHex(bootId) << std::endl; +#endif + + dhtSearch(bootId, DHT_MODE_SEARCH); + + return true; +} + + +std::string p3DhtMgr::BootstrapId(uint32_t bin) +{ + /* generate these from an equation! (makes it easy) + * Make sure that NUM_BOOTSTRAP_BINS doesn't affect ids + */ + + std::ostringstream genId; + genId << "BootstrapId"; + + uint32_t id = (bin % DHT_NUM_BOOTSTRAP_BINS) * 1234; + + genId << id; + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::BootstrapId() generatedId: "; + std::cerr << genId.str() << std::endl; +#endif + + /* now hash this to create a bootstrap Bin Id */ + std::string bootId = RsUtil::HashId(genId.str(), false); + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::BootstrapId() bootId: 0x"; + std::cerr << RsUtil::BinToHex(bootId) << std::endl; +#endif + + return bootId; +} + +std::string p3DhtMgr::randomBootstrapId() +{ + uint32_t rnd = DHT_NUM_BOOTSTRAP_BINS * (rand() / (RAND_MAX + 1.0)); + + return BootstrapId(rnd); +} + + + +void p3DhtMgr::checkDHTStatus() +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + bool isActive = (mDhtState != DHT_STATE_OFF); + + bool toShutdown = false; + bool toStartup = false; + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() mDhtState: " << mDhtState << std::endl; + std::cerr << "p3DhtMgr::checkDhtStatus() mDhtOn : " << mDhtOn << std::endl; +#endif + + if ((isActive) && (!mDhtOn)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() Active & !mDhtOn -> toShutdown" << std::endl; +#endif + toShutdown = true; + } + + if ((!isActive) && (mDhtOn)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() !Active & mDhtOn -> toStartup" << std::endl; +#endif + toStartup = true; + } + + /* restart if it has shutdown */ + if (isActive && mDhtOn) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() Active & mDhtOn" << std::endl; +#endif + if (dhtActive()) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() dhtActive() = true" << std::endl; +#endif + if (mDhtState == DHT_STATE_INIT) + { + mDhtState = DHT_STATE_CHECK_PEERS; +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() Switching to CHECK PEERS" << std::endl; +#endif + } + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() dhtActive() = false" << std::endl; +#endif + if (mDhtActiveTS - time(NULL) > DHT_RESTART_PERIOD) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() restart Period..." << std::endl; +#endif + toShutdown = true; + toStartup = true; + } + } + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + if (toShutdown) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() toShutdown = true -> shutdown()" << std::endl; +#endif + if (dhtShutdown()) + { + clearDhtData(); + + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtState = DHT_STATE_OFF; +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() mDhtState -> OFF" << std::endl; +#endif + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + } + } + + if (toStartup) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() toStartup = true -> dhtInit()" << std::endl; +#endif + if (dhtInit()) + { + + dhtMtx.lock(); /* LOCK MUTEX */ + + mDhtState = DHT_STATE_INIT; + mDhtActiveTS = time(NULL); + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::checkDhtStatus() mDhtState -> INIT" << std::endl; +#endif + + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + } + } +} + +void p3DhtMgr::clearDhtData() +{ + std::cerr << "p3DhtMgr::clearDhtData() DUMMY FN" << std::endl; +} + + +/****************************** REAL DHT INTERFACE ********************************* + * publish/search/result. + * + * dummy implementation for testing. + */ + +int p3DhtMgr::status(std::ostream &out) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + + out << "p3DhtMgr::status() ************************************" << std::endl; + out << "mDhtState: " << mDhtState << std::endl; + out << "mDhtOn : " << mDhtOn << std::endl; + out << "dhtActive: " << dhtActive() << std::endl; + + /* now own state */ + out << "OWN DETAILS -------------------------------------------" << std::endl; + printDhtPeerEntry(&ownEntry, out); + out << "OWN DETAILS END----------------------------------------" << std::endl; + + /* now peers states */ + std::map::iterator it; + out << "PEER DETAILS ------------------------------------------" << std::endl; + for(it = peers.begin(); it != peers.end(); it++) + { + printDhtPeerEntry(&(it->second), out); + } + out << "PEER DETAILS END---------------------------------------" << std::endl; + + /* now stun states */ + out << "STUN DETAILS ------------------------------------------" << std::endl; + out << "Available Stun Ids: " << stunIds.size() << std::endl; + out << "STUN DETAILS END---------------------------------------" << std::endl; + + + out << "p3DhtMgr::status() END ********************************" << std::endl; + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + return 0; +} + + + + + +bool p3DhtMgr::dhtInit() +{ + std::cerr << "p3DhtMgr::dhtInit() DUMMY FN" << std::endl; + return true; +} + +bool p3DhtMgr::dhtShutdown() +{ + std::cerr << "p3DhtMgr::dhtShutdown() DUMMY FN" << std::endl; + return true; +} + +bool p3DhtMgr::dhtActive() +{ + std::cerr << "p3DhtMgr::dhtActive() DUMMY FN" << std::endl; + return true; +} + +bool p3DhtMgr::publishDHT(std::string key, std::string value, uint32_t ttl) +{ + std::cerr << "p3DhtMgr::publishDHT() DUMMY FN" << std::endl; + return false; +} + +bool p3DhtMgr::searchDHT(std::string idhash) +{ + std::cerr << "p3DhtMgr::searchDHT() DUMMY FN" << std::endl; + return false; +} + + + + +/****************************** INTERMEDIATE DHT INTERFACE ********************************* + * publish/search/result. + * + * Take the 'real' parameters and create the key/value parameters for the real dht. + */ + + +bool p3DhtMgr::dhtPublish(std::string idhash, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign) +{ + /* ... goes and searches */ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtPublish()" << std::endl; + + std::cerr << "PUBLISHing: idhash: " << RsUtil::BinToHex(idhash); + std::cerr << " laddr: " << rs_inet_ntoa(laddr.sin_addr); + std::cerr << ":" << ntohs(laddr.sin_port); + std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr); + std::cerr << ":" << ntohs(raddr.sin_port); + std::cerr << " type: " << type; + std::cerr << " sign: " << sign; + std::cerr << std::endl; +#endif + + /* Create a Value from addresses and type */ + /* to store the ip address and flags */ + + std::ostringstream out; + out << "RSDHT:" << std::setw(2) << std::setfill('0') << DHT_MODE_SEARCH << ": "; + out << "IPL=" << rs_inet_ntoa(laddr.sin_addr) << ":" << ntohs(laddr.sin_port) << ", "; + out << "IPE=" << rs_inet_ntoa(raddr.sin_addr) << ":" << ntohs(raddr.sin_port) << ", "; + out << "type=" << std::setw(4) << std::setfill('0') << std::hex << type << ", "; + +/******* + char valuearray[1024]; + snprintf(valuearray, 1024, "RSDHT:%02d: IPL=%s:%d, IPE=%s:%d, type=%04X,", + DHT_MODE_SEARCH, + rs_inet_ntoa(laddr.sin_addr), + ntohs(laddr.sin_port), + rs_inet_ntoa(raddr.sin_addr), + ntohs(raddr.sin_port), + type); + + std::string value = valuearray; +******/ + + std::string value = out.str(); + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtPublish()" << std::endl; + + std::cerr << "PUBLISH: key: " << RsUtil::BinToHex(idhash); + std::cerr << " value: " << value; + std::cerr << std::endl; +#endif + + /* call to the real DHT */ + return publishDHT(idhash, value, DHT_TTL_PUBLISH); +} + +bool p3DhtMgr::dhtNotify(std::string idhash, std::string ownIdHash, std::string sign) +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtNotify()" << std::endl; +#endif + + std::ostringstream value; + value << "RSDHT:" << std::setw(2) << std::setfill('0') << DHT_MODE_NOTIFY << ":"; + value << ownIdHash; + + /* call to the real DHT */ + return publishDHT(idhash, value.str(), DHT_TTL_NOTIFY); +} + +bool p3DhtMgr::dhtSearch(std::string idhash, uint32_t mode) +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtSearch()" << std::endl; +#endif + + /* call to the real DHT */ + return searchDHT(idhash); +} + + +bool p3DhtMgr::dhtBootstrap(std::string storehash, std::string ownIdHash, std::string sign) +{ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtBootstrap()" << std::endl; +#endif + + std::ostringstream value; + value << "RSDHT:" << std::setw(2) << std::setfill('0') << DHT_MODE_BOOTSTRAP << ":"; + value << ownIdHash; + + /* call to the real DHT */ + return publishDHT(storehash, value.str(), DHT_TTL_BOOTSTRAP); +} + + +/****************************** DHT FEEDBACK INTERFACE ********************************* + * Two functions... + * (1) The interpretation function. + * (2) callback handling. + * + */ + +bool p3DhtMgr::resultDHT(std::string key, std::string value) +{ + /* so .... two possibilities. + * + * RSDHT:01: IPL ... IPE ... TYPE ... (advertising) + * RSDHT:02: HASH (connect request) + * + */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() key: 0x" << RsUtil::BinToHex(key); + std::cerr << " value: 0x" << RsUtil::BinToHex(value) << std::endl; +#endif + + /* variables for dhtResult() call */ + struct sockaddr_in laddr; + struct sockaddr_in raddr; + std::string sign; + + + int32_t reqType; + uint32_t loc; + if (1 > sscanf(value.c_str(), "RSDHT:%d: %n", &reqType, &loc)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() Not RSDHT msg -> discarding" << std::endl; +#endif + /* failed */ + return false; + } + + + dhtMtx.lock(); /* LOCK MUTEX */ + std::string ownhash = ownEntry.hash1; + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + switch(reqType) + { + case DHT_MODE_NOTIFY: + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() NOTIFY msg" << std::endl; +#endif + + if (ownhash != key) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() NOTIFY msg not for us -> discarding" << std::endl; +#endif + return false; + } + + /* get the hash */ + std::string notifyHash = value.substr(loc); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() NOTIFY msg HASH:-> 0x" << RsUtil::BinToHex(notifyHash) << "<-" << std::endl; +#endif + /* call out */ + dhtResultNotify(notifyHash); + + break; + } + + case DHT_MODE_SEARCH: + { + + if (ownhash == key) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() SEARCH msg is OWN PUBLISH -> discarding" << std::endl; +#endif + return false; + } + + uint32_t a1,b1,c1,d1,e1; + uint32_t a2,b2,c2,d2,e2; + uint32_t flags; + + if (sscanf(&((value.c_str())[loc]), " IPL=%d.%d.%d.%d:%d, IPE=%d.%d.%d.%d:%d, type=%x", + &a1, &b1, &c1, &d1, &e1, &a2, &b2, &c2, &d2, &e2, &flags) != 11) + { + /* failed to scan */ +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() SEARCH parse failed of:" << (&((value.c_str())[loc])); + std::cerr << std::endl; +#endif + return false; + } + + std::ostringstream out1; + out1 << a1 << "." << b1 << "." << c1 << "." << d1; + inet_aton(out1.str().c_str(), &(laddr.sin_addr)); + laddr.sin_port = htons(e1); + laddr.sin_family = AF_INET; + + std::ostringstream out2; + out2 << a2 << "." << b2 << "." << c2 << "." << d2; + inet_aton(out2.str().c_str(), &(raddr.sin_addr)); + raddr.sin_port = htons(e2); + raddr.sin_family = AF_INET; + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() SEARCH laddr: " << out1.str() << ":" << e1; + std::cerr << " raddr: " << out2.str() << ":" << e2; + std::cerr << " flags: " << flags; + std::cerr << std::endl; +#endif + + return dhtResultSearch(key, laddr, raddr, flags, sign); + + break; + } + + case DHT_MODE_BOOTSTRAP: + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() BOOTSTRAP msg" << std::endl; +#endif + + /* get the hash */ + std::string bootId = value.substr(loc); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::resultDHT() BOOTSTRAP msg, IdHash:->" << RsUtil::BinToHex(bootId) << "<-" << std::endl; +#endif + /* call out */ + dhtResultBootstrap(bootId); + + break; + } + + default: + + return false; + break; + } + + return false; +} + + + + +bool p3DhtMgr::dhtResultBootstrap(std::string idhash) +{ + RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResultBootstrap() from idhash: "; + std::cerr << RsUtil::BinToHex(idhash) << std::endl; +#endif + + /* Temp - to avoid duplication during testing */ + if (stunIds.end() == std::find(stunIds.begin(), stunIds.end(), idhash)) + { + stunIds.push_back(idhash); +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResultBootstrap() adding to StunList"; + std::cerr << std::endl; +#endif + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResultBootstrap() DUPLICATE not adding to List"; + std::cerr << std::endl; +#endif + } + + + return true; +} + + + + +bool p3DhtMgr::dhtResultNotify(std::string idhash) +{ + RsStackMutex stack(dhtMtx); /***** LOCK MUTEX *****/ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResultNotify() from idhash: "; + std::cerr << RsUtil::BinToHex(idhash) << std::endl; +#endif + std::map::iterator it; + time_t now = time(NULL); + + /* if notify - we must match on the second hash */ + for(it = peers.begin(); (it != peers.end()) && ((it->second).hash2 != idhash); it++) ; + + /* update data */ + std::string peerid; + + /* ignore OFF peers */ + if ((it != peers.end()) && (it->second.state != DHT_PEER_OFF)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResult() NOTIFY for id: " << it->first << std::endl; +#endif + { + /* Log */ + std::ostringstream out; + out << "p3DhtMgr::dhtResultNotify() NOTIFY from Id: " << it->first; + rslog(RSL_WARNING, p3dhtzone, out.str()); + } + + /* delay callback -> if they are not found */ + it->second.notifyTS = now; + it->second.notifyPending = RS_CONNECT_PASSIVE; + mDhtModifications = true; /* no wait! */ + + if (it->second.state != DHT_PEER_FOUND) + { + /* flag for immediate search */ + it->second.lastTS = 0; + } + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResult() unknown NOTIFY "; + std::cerr << RsUtil::BinToHex(idhash) << std::endl; +#endif + } + + return true; +} + + +bool p3DhtMgr::dhtResultSearch(std::string idhash, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign) +{ + dhtMtx.lock(); /* LOCK MUTEX */ + +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResultSearch() for idhash: "; + std::cerr << RsUtil::BinToHex(idhash) << std::endl; +#endif + std::map::iterator it; + bool doCb = false; + bool doStun = false; + uint32_t stunFlags = 0; + time_t now = time(NULL); + + dhtPeerEntry ent; + + /* if search - we must match on the second hash */ + for(it = peers.begin(); (it != peers.end()) && ((it->second).hash1 != idhash); it++) ; + + /* update data */ + /* ignore OFF peers */ + if ((it != peers.end()) && (it->second.state != DHT_PEER_OFF)) + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResult() SEARCH for id: " << it->first << std::endl; +#endif + it->second.lastTS = now; + + { + /* Log */ + std::ostringstream out; + out << "p3DhtMgr::dhtSearchResult() for Id: " << it->first; + out << " laddr: " << rs_inet_ntoa(laddr.sin_addr); + out << ":" << ntohs(laddr.sin_port); + out << " raddr: " << rs_inet_ntoa(raddr.sin_addr); + out << ":" << ntohs(raddr.sin_port); + out << " type: " << ownEntry.type; + + rslog(RSL_WARNING, p3dhtzone, out.str()); + } + + /* update info .... always */ + it->second.state = DHT_PEER_FOUND; + it->second.laddr = laddr; + it->second.raddr = raddr; + it->second.type = type; + + /* Do callback all the time */ + ent = it->second; + doCb = true; + + if (it->second.notifyPending) + { + /* no wait if we have pendingNotification */ + mDhtModifications = true; + } + + /* do Stun always */ + doStun = true; + stunFlags = RS_STUN_FRIEND | RS_STUN_ONLINE; + } + else + { +#ifdef DHT_DEBUG + std::cerr << "p3DhtMgr::dhtResult() SEARCH(stun) for idhash: "; + std::cerr << RsUtil::BinToHex(idhash) << std::endl; +#endif + /* stun result? */ + doStun = true; + stunFlags = RS_STUN_ONLINE; + } + + dhtMtx.unlock(); /* UNLOCK MUTEX */ + + if (doCb) + { + pqiIpAddrSet addrs; + + pqiIpAddress laddr; + laddr.mAddr = ent.laddr; + laddr.mSeenTime = time(NULL); + laddr.mSrc = RS_CB_DHT; + + addrs.updateLocalAddrs(laddr); + + pqiIpAddress eaddr; + eaddr.mAddr = ent.raddr; + eaddr.mSeenTime = time(NULL); + eaddr.mSrc = RS_CB_DHT; + + addrs.updateExtAddrs(eaddr); + + mConnCb->peerStatus(ent.id, addrs, ent.type, 0, RS_CB_DHT); + } + + if (doStun) + { + //mConnCb->stunStatus(idhash, raddr, type, stunFlags); + } + + return true; +} + + + +/******************************** AUX FUNCTIONS ********************************** + * + */ + +void printDhtPeerEntry(dhtPeerEntry *ent, std::ostream &out) +{ + + out << "DhtEntry: ID: " << ent->id; + out << " State: " << ent->state; + out << " lastTS: " << ent->lastTS; + out << " notifyPending: " << ent->notifyPending; + out << " notifyTS: " << ent->notifyTS; + out << std::endl; + out << " laddr: " << rs_inet_ntoa(ent->laddr.sin_addr) << ":" << ntohs(ent->laddr.sin_port); + out << " raddr: " << rs_inet_ntoa(ent->raddr.sin_addr) << ":" << ntohs(ent->raddr.sin_port); + out << " type: " << ent->type; + out << std::endl; + out << " hash1: " << RsUtil::BinToHex(ent->hash1); + out << std::endl; + out << " hash2: " << RsUtil::BinToHex(ent->hash2); + out << std::endl; + return; +} + + diff --git a/libretroshare/src/pqi/p3dhtmgr.h b/libretroshare/src/pqi/p3dhtmgr.h new file mode 100644 index 000000000..f08c2bc96 --- /dev/null +++ b/libretroshare/src/pqi/p3dhtmgr.h @@ -0,0 +1,250 @@ +/* + * libretroshare/src/pqi: p3dhtmgr.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef MRK_P3_DHT_MANAGER_HEADER +#define MRK_P3_DHT_MANAGER_HEADER + +/* Interface class for DHT data */ + +#include +#include +#include "pqi/pqinetwork.h" + +#include "util/rsthreads.h" +#include "pqi/pqimonitor.h" + +#include "pqi/pqiassist.h" + +/* All other #defs are in .cc */ +#define DHT_ADDR_INVALID 0xff +#define DHT_ADDR_TCP 0x01 +#define DHT_ADDR_UDP 0x02 + + +/* for DHT peer STATE */ +#define DHT_PEER_OFF 0 +#define DHT_PEER_INIT 1 +#define DHT_PEER_SEARCH 2 +#define DHT_PEER_FOUND 3 + +/* for DHT peer STATE (ownEntry) */ +#define DHT_PEER_ADDR_KNOWN 4 +#define DHT_PEER_PUBLISHED 5 + +/* Interface with Real DHT Implementation */ +#define DHT_MODE_SEARCH 1 +#define DHT_MODE_PUBLISH 1 +#define DHT_MODE_NOTIFY 2 +#define DHT_MODE_BOOTSTRAP 3 + + +/* TIMEOUTS: Reference Values are set here... */ + +#define DHT_SEARCH_PERIOD 1800 /* PeerKeys: if we haven't found them: 30 min */ +#define DHT_CHECK_PERIOD 1800 /* PeerKeys: re-lookup peer: 30 min */ +#define DHT_PUBLISH_PERIOD 1800 /* OwnKey: 30 min */ +#define DHT_NOTIFY_PERIOD 300 /* 5 min - Notify Check period */ + +/* TTLs for DHTs posts */ +#define DHT_TTL_PUBLISH (DHT_PUBLISH_PERIOD + 120) // for a little overlap. +#define DHT_TTL_NOTIFY (DHT_NOTIFY_PERIOD + 60) // for time to find it... +#define DHT_TTL_BOOTSTRAP (DHT_PUBLISH_PERIOD) // To start with. + +class dhtPeerEntry +{ + public: + dhtPeerEntry(); + + std::string id; + uint32_t state; + time_t lastTS; + + uint32_t notifyPending; + time_t notifyTS; + + struct sockaddr_in laddr, raddr; + uint32_t type; /* ADDR_TYPE as defined above */ + + std::string hash1; /* SHA1 Hash of id */ + std::string hash2; /* SHA1 Hash of reverse Id */ +}; + +class p3DhtMgr: public pqiNetAssistConnect, public RsThread +{ + /* + */ + public: + p3DhtMgr(std::string id, pqiConnectCb *cb); + + /********** External DHT Interface ************************ + * These Functions are the external interface + * for the DHT, and must be non-blocking and return quickly + */ + + /* OVERLOADED From pqiNetAssistConnect. */ + +virtual void enable(bool on); +virtual void shutdown(); +virtual void restart(); + +virtual bool getEnabled(); /* on */ +virtual bool getActive(); /* actually working */ + +virtual void setBootstrapAllowed(bool on); +virtual bool getBootstrapAllowed(); + + /* set key data */ +virtual bool setExternalInterface(struct sockaddr_in laddr, + struct sockaddr_in raddr, uint32_t type); + + /* add / remove peers */ +virtual bool findPeer(std::string id); +virtual bool dropPeer(std::string id); + + /* post DHT key saying we should connect (callback when done) */ +virtual bool notifyPeer(std::string id); + + /* extract current peer status */ +virtual bool getPeerStatus(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t &type, uint32_t &mode); + + /* stun */ +virtual bool enableStun(bool on); +virtual bool addStun(std::string id); + //doneStun(); + + /********** Higher Level DHT Work Functions ************************ + * These functions translate from the strings/addresss to + * key/value pairs. + */ + public: + + /* results from DHT proper */ +virtual bool dhtResultNotify(std::string id); +virtual bool dhtResultSearch(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign); + +virtual bool dhtResultBootstrap(std::string idhash); + + protected: + + /* can block briefly (called only from thread) */ +virtual bool dhtPublish(std::string id, + struct sockaddr_in &laddr, + struct sockaddr_in &raddr, + uint32_t type, std::string sign); + +virtual bool dhtNotify(std::string peerid, std::string ownId, + std::string sign); + +virtual bool dhtSearch(std::string id, uint32_t mode); + +virtual bool dhtBootstrap(std::string storehash, std::string ownIdHash, + std::string sign); /* to publish bootstrap */ + + + + /********** Actual DHT Work Functions ************************ + * These involve a very simple LOW-LEVEL interface ... + * + * publish + * search + * result + * + */ + + public: + + /* Feedback callback (handled here) */ +virtual bool resultDHT(std::string key, std::string value); + + protected: + +virtual bool dhtInit(); +virtual bool dhtShutdown(); +virtual bool dhtActive(); +virtual int status(std::ostream &out); + +virtual bool publishDHT(std::string key, std::string value, uint32_t ttl); +virtual bool searchDHT(std::string key); + + + + /********** Internal DHT Threading ************************ + * + */ + + public: + +virtual void run(); + + private: + + /* search scheduling */ +void checkDHTStatus(); +int checkStunState(); +int checkStunState_Active(); /* when in active state */ +int doStun(); +int checkPeerDHTKeys(); +int checkOwnDHTKeys(); +int checkNotifyDHT(); + +void clearDhtData(); + + /* IP Bootstrap */ +bool getDhtBootstrapList(); +std::string BootstrapId(uint32_t bin); +std::string randomBootstrapId(); + + /* other feedback through callback */ + // use pqiNetAssistConnect.. version pqiConnectCb *connCb; + + /* protected by Mutex */ + RsMutex dhtMtx; + + bool mDhtOn; /* User desired state */ + bool mDhtModifications; /* any user requests? */ + + dhtPeerEntry ownEntry; + time_t ownNotifyTS; + std::map peers; + + std::list stunIds; + bool mStunRequired; + + uint32_t mDhtState; + time_t mDhtActiveTS; + + bool mBootstrapAllowed; + time_t mLastBootstrapListTS; +}; + + +#endif // MRK_P3_DHT_MANAGER_HEADER + + diff --git a/libretroshare/src/pqi/p3notify.cc b/libretroshare/src/pqi/p3notify.cc new file mode 100644 index 000000000..e7e3a01a5 --- /dev/null +++ b/libretroshare/src/pqi/p3notify.cc @@ -0,0 +1,222 @@ +/* + * libretroshare/src/rsserver: p3notify.cc + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "pqi/p3notify.h" +#include + +/* external reference point */ +RsNotify *rsNotify = NULL; + +pqiNotify *getPqiNotify() +{ + return ((p3Notify *) rsNotify); +} + + /* Output for retroshare-gui */ +bool p3Notify::NotifySysMessage(uint32_t &sysid, uint32_t &type, + std::string &title, std::string &msg) +{ + RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ + if (pendingSysMsgs.size() > 0) + { + p3NotifySysMsg smsg = pendingSysMsgs.front(); + pendingSysMsgs.pop_front(); + + sysid = smsg.sysid; + type = smsg.type; + title = smsg.title; + msg = smsg.msg; + + return true; + } + + return false; +} + + /* Output for retroshare-gui */ +bool p3Notify::NotifyLogMessage(uint32_t &sysid, uint32_t &type, + std::string &title, std::string &msg) +{ + RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ + if (pendingLogMsgs.size() > 0) + { + p3NotifyLogMsg smsg = pendingLogMsgs.front(); + pendingLogMsgs.pop_front(); + + sysid = smsg.sysid; + type = smsg.type; + title = smsg.title; + msg = smsg.msg; + + return true; + } + + return false; +} + + +bool p3Notify::NotifyPopupMessage(uint32_t &ptype, std::string &name, std::string &title, std::string &msg) +{ + RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ + if (pendingPopupMsgs.size() > 0) + { + p3NotifyPopupMsg pmsg = pendingPopupMsgs.front(); + pendingPopupMsgs.pop_front(); + + ptype = pmsg.type; + name = pmsg.name; + title = pmsg.title; + msg = pmsg.msg; + + return true; + } + + return false; +} + + + /* Control over Messages */ +bool p3Notify::GetSysMessageList(std::map &list) +{ + (void) list; /* suppress unused parameter warning */ + return false; +} + +bool p3Notify::GetPopupMessageList(std::map &list) +{ + (void) list; /* suppress unused parameter warning */ + return false; +} + + +bool p3Notify::SetSysMessageMode(uint32_t sysid, uint32_t mode) +{ + (void) sysid; /* suppress unused parameter warning */ + (void) mode; /* suppress unused parameter warning */ + return false; +} + +bool p3Notify::SetPopupMessageMode(uint32_t ptype, uint32_t mode) +{ + (void) ptype; /* suppress unused parameter warning */ + (void) mode; /* suppress unused parameter warning */ + return false; +} + + + /* Input from libretroshare */ +bool p3Notify::AddPopupMessage(uint32_t ptype, const std::string& name, const std::string& title, const std::string& msg) +{ + RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ + + p3NotifyPopupMsg pmsg; + + pmsg.type = ptype; + pmsg.name = name; + pmsg.title = title; + pmsg.msg = msg; + + pendingPopupMsgs.push_back(pmsg); + + return true; +} + + +bool p3Notify::AddSysMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg) +{ + RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ + + p3NotifySysMsg smsg; + + smsg.sysid = sysid; + smsg.type = type; + smsg.title = title; + smsg.msg = msg; + + pendingSysMsgs.push_back(smsg); + + return true; +} + +bool p3Notify::AddLogMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg) +{ + RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ + + p3NotifyLogMsg smsg; + + smsg.sysid = sysid; + smsg.type = type; + smsg.title = title; + smsg.msg = msg; + + pendingLogMsgs.push_back(smsg); + + return true; +} + + +bool p3Notify::GetFeedItem(RsFeedItem &item) +{ + RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ + if (pendingNewsFeed.size() > 0) + { + item = pendingNewsFeed.front(); + pendingNewsFeed.pop_front(); + + return true; + } + + return false; +} + + +bool p3Notify::AddFeedItem(uint32_t type, const std::string& id1, const std::string& id2, const std::string& id3) +{ + RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ + pendingNewsFeed.push_back(RsFeedItem(type, id1, id2, id3)); + + return true; +} + + +bool p3Notify::ClearFeedItems(uint32_t type) +{ + RsStackMutex stack(noteMtx); /************* LOCK MUTEX ************/ + + std::list::iterator it; + for(it = pendingNewsFeed.begin(); it != pendingNewsFeed.end(); ) + { + if (it->mType == type) + { + it = pendingNewsFeed.erase(it); + } + else + { + it++; + } + } + return true; +} diff --git a/libretroshare/src/pqi/p3notify.h b/libretroshare/src/pqi/p3notify.h new file mode 100644 index 000000000..52ad94502 --- /dev/null +++ b/libretroshare/src/pqi/p3notify.h @@ -0,0 +1,104 @@ +#ifndef RS_P3_NOTIFY_INTERFACE_H +#define RS_P3_NOTIFY_INTERFACE_H + +/* + * libretroshare/src/rsserver: p3notify.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rsnotify.h" +#include "pqi/pqinotify.h" + +#include "util/rsthreads.h" + +class p3NotifySysMsg +{ + public: + + uint32_t sysid; + uint32_t type; + std::string title; + std::string msg; +}; + +class p3NotifyLogMsg +{ + public: + + uint32_t sysid; + uint32_t type; + std::string title; + std::string msg; +}; + +class p3NotifyPopupMsg +{ + public: + + uint32_t type; + std::string name; + std::string title; + std::string msg; +}; + + +class p3Notify: public RsNotify, public pqiNotify +{ + public: + + p3Notify() { return; } +virtual ~p3Notify() { return; } + + /* Output for retroshare-gui */ +virtual bool NotifySysMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg); +virtual bool NotifyPopupMessage(uint32_t &ptype, std::string &name, std::string &title, std::string &msg); +virtual bool NotifyLogMessage(uint32_t &sysid, uint32_t &type, std::string &title, std::string &msg); + + /* Control over Messages */ +virtual bool GetSysMessageList(std::map &list); +virtual bool GetPopupMessageList(std::map &list); + +virtual bool SetSysMessageMode(uint32_t sysid, uint32_t mode); +virtual bool SetPopupMessageMode(uint32_t ptype, uint32_t mode); + +virtual bool GetFeedItem(RsFeedItem &item); + + /* Overloaded from pqiNotify */ +virtual bool AddPopupMessage(uint32_t ptype, const std::string& name, const std::string& title, const std::string& msg); +virtual bool AddSysMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg); +virtual bool AddLogMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg); +virtual bool AddFeedItem(uint32_t type, const std::string& id1, const std::string& id2, const std::string& id3); +virtual bool ClearFeedItems(uint32_t type); + + private: + + RsMutex noteMtx; + + std::list pendingSysMsgs; + std::list pendingLogMsgs; + std::list pendingPopupMsgs; + std::list pendingNewsFeed; +}; + + +#endif diff --git a/libretroshare/src/pqi/p3upnpmgr.h b/libretroshare/src/pqi/p3upnpmgr.h new file mode 100644 index 000000000..99640d4f0 --- /dev/null +++ b/libretroshare/src/pqi/p3upnpmgr.h @@ -0,0 +1,59 @@ +/* + * libretroshare/src/pqi: p3upnpmgr.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef MRK_P3_UPNP_MANAGER_H +#define MRK_P3_UPNP_MANAGER_H + +/* platform independent networking... */ +#include "util/rsthreads.h" +#include "pqi/pqinetwork.h" + +class p3UpnpMgr: public pqiNetAssistFirewall +{ + public: + +virtual ~p3UpnpMgr() { return; } + + /* External Interface */ +virtual void enable(bool on) = 0; /* launches thread to start it up */ +virtual void shutdown() = 0; /* blocking shutdown call */ +virtual void restart() = 0; /* must be called if ports change */ + +virtual bool getEnabled() = 0; +virtual bool getActive() = 0; + + /* the address that the listening port is on */ +virtual void setInternalPort(unsigned short iport_in) = 0; +virtual void setExternalPort(unsigned short eport_in) = 0; + + /* as determined by uPnP */ +virtual bool getInternalAddress(struct sockaddr_in &addr) = 0; +virtual bool getExternalAddress(struct sockaddr_in &addr) = 0; + +}; + +#endif /* MRK_P3_UPNP_MANAGER_H */ + diff --git a/libretroshare/src/pqi/pqi.h b/libretroshare/src/pqi/pqi.h new file mode 100644 index 000000000..7800a0420 --- /dev/null +++ b/libretroshare/src/pqi/pqi.h @@ -0,0 +1,98 @@ +/* + * libretroshare/src/pqi pqi.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef PQI_TOP_HEADER +#define PQI_TOP_HEADER + +/* This just includes the standard headers required. + */ + + +#include "pqi/pqi_base.h" +#include "pqi/pqinetwork.h" +#include "serialiser/rsserial.h" +#include "serialiser/rsbaseitems.h" + +#include +#include +#include + +/********************** SEARCH INTERFACE ***************************/ +// this is an interface.... so should be +// classified as virtual = 0; + +class SearchInterface +{ +public: + SearchInterface() { return; } + +virtual ~SearchInterface() { return; } + + // Cache Requests +virtual int SearchSpecific(RsCacheRequest *) = 0; +virtual RsCacheRequest *RequestedSearch() = 0; + + // Cache Results +virtual int SendSearchResult(RsCacheItem *item) = 0; +virtual RsCacheItem *GetSearchResult() = 0; + + // FileTransfer. +virtual RsFileRequest *GetFileRequest() = 0; +virtual int SendFileRequest(RsFileRequest *) = 0; + +virtual RsFileData *GetFileData() = 0; +virtual int SendFileData(RsFileData *) = 0; + +virtual RsFileChunkMapRequest *GetFileChunkMapRequest() = 0; +virtual int SendFileChunkMapRequest(RsFileChunkMapRequest *) = 0; + +virtual RsFileChunkMap *GetFileChunkMap() = 0; +virtual int SendFileChunkMap(RsFileChunkMap *) = 0; + +virtual RsFileCRC32MapRequest *GetFileCRC32MapRequest() = 0; +virtual int SendFileCRC32MapRequest(RsFileCRC32MapRequest *) = 0; + +virtual RsFileCRC32Map *GetFileCRC32Map() = 0; +virtual int SendFileCRC32Map(RsFileCRC32Map *) = 0; + +}; + +class P3Interface: public SearchInterface +{ +public: + P3Interface() {return; } +virtual ~P3Interface() {return; } + +virtual int tick() { return 1; } +virtual int status() { return 1; } + +virtual int SendRsRawItem(RsRawItem *) = 0; +virtual RsRawItem *GetRsRawItem() = 0; + +}; + +#endif // PQI_TOP_HEADER + diff --git a/libretroshare/src/pqi/pqi_base.h b/libretroshare/src/pqi/pqi_base.h new file mode 100644 index 000000000..21b21f1b6 --- /dev/null +++ b/libretroshare/src/pqi/pqi_base.h @@ -0,0 +1,301 @@ +/* + * "$Id: pqi_base.h,v 1.18 2007-05-05 16:10:05 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef PQI_BASE_ITEM_HEADER +#define PQI_BASE_ITEM_HEADER + +#include +#include +#include +#include +#include +#include + +#include "pqi/pqinetwork.h" + +/*** Base DataTypes: ****/ +#include "serialiser/rsserial.h" + + +#define PQI_MIN_PORT 1024 +#define PQI_MAX_PORT 50000 +#define PQI_DEFAULT_PORT 7812 + +int getPQIsearchId(); +int fixme(char *str, int n); + +//! controlling data rates +/*! + * For controlling data rates. + */ +class RateInterface +{ + +public: + + RateInterface() + :bw_in(0), bw_out(0), bwMax_in(0), bwMax_out(0) { return; } +virtual ~RateInterface() { return; } + +virtual float getRate(bool in) + { + if (in) + return bw_in; + return bw_out; + } + +virtual float getMaxRate(bool in) + { + if (in) + return bwMax_in; + return bwMax_out; + } + +virtual void setMaxRate(bool in, float val) + { + if (in) + bwMax_in = val; + else + bwMax_out = val; + return; + } + +protected: + +void setRate(bool in, float val) + { + if (in) + bw_in = val; + else + bw_out = val; + return; + } + + private: +float bw_in, bw_out, bwMax_in, bwMax_out; +}; + + +class NetInterface; + +//! The basic exchange interface. +/*! + * + * This inherits the RateInterface, as Bandwidth control + * is critical to a networked application. + **/ +class PQInterface: public RateInterface +{ +public: + PQInterface(const std::string &id) :peerId(id) { return; } +virtual ~PQInterface() { return; } + +/*! + * allows user to send RsItems to a particular facility (file, network) + */ +virtual int SendItem(RsItem *) = 0; + +/*! + * Retrieve RsItem from a facility + */ +virtual RsItem *GetItem() = 0; + +/** + * also there are tick + person id functions. + */ +virtual int tick() { return 0; } +virtual int status() { return 0; } +virtual std::string PeerId() { return peerId; } + + // the callback from NetInterface Connection Events. +virtual int notifyEvent(NetInterface *ni, int event) + { + (void) ni; /* remove unused parameter warnings */ + (void) event; /* remove unused parameter warnings */ + return 0; + } + + private: + + std::string peerId; +}; + + + +/**** Consts for pqiperson -> placed here for NetBinDummy usage() */ + +const uint32_t PQI_CONNECT_TCP = 0x0001; +const uint32_t PQI_CONNECT_UDP = 0x0002; +const uint32_t PQI_CONNECT_TUNNEL = 0x0003; + + +#define BIN_FLAGS_NO_CLOSE 0x0001 +#define BIN_FLAGS_READABLE 0x0002 +#define BIN_FLAGS_WRITEABLE 0x0004 +#define BIN_FLAGS_NO_DELETE 0x0008 +#define BIN_FLAGS_HASH_DATA 0x0010 + +/*! + * This defines the binary interface used by Network/loopback/file + * interfaces + * e.g. sending binary data to file or to memory or even through a socket + */ +class BinInterface +{ +public: + BinInterface() { return; } +virtual ~BinInterface() { return; } + +/** + * To be called loop, for updating state + */ +virtual int tick() = 0; + +/** + * Sends data to a prescribed location (implementation dependent) + *@param data what will be sent + *@param len the size of data pointed to in memory + */ +virtual int senddata(void *data, int len) = 0; + +/** + * reads data from a prescribed location (implementation dependent) + *@param data what will be sent + *@param len the size of data pointed to in memory + */ +virtual int readdata(void *data, int len) = 0; + +/** + * Is more particular the case of the sending data through a socket (internet) + */ +virtual int netstatus() = 0; +virtual int isactive() = 0; +virtual bool moretoread() = 0; +virtual bool cansend() = 0; + +/** + * method for streamer to shutdown bininterface + **/ +virtual int close() = 0; + +/** + * If hashing data + **/ +virtual std::string gethash() = 0; + +/** + * Number of bytes read/sent + */ +virtual uint64_t bytecount() { return 0; } + +/** + * used by pqistreamer to limit transfers + **/ +virtual bool bandwidthLimited() { return true; } +}; + + + +static const int NET_CONNECT_RECEIVED = 1; +static const int NET_CONNECT_SUCCESS = 2; +static const int NET_CONNECT_UNREACHABLE = 3; +static const int NET_CONNECT_FIREWALLED = 4; +static const int NET_CONNECT_FAILED = 5; + +static const uint32_t NET_PARAM_CONNECT_DELAY = 1; +static const uint32_t NET_PARAM_CONNECT_PERIOD = 2; +static const uint32_t NET_PARAM_CONNECT_TIMEOUT = 3; + + +/*! + * ******************** Network INTERFACE *************************** + * This defines the Network interface used by sockets/SSL/XPGP + * interfaces + * + * NetInterface: very pure interface, so no tick.... + * + * It is passed a pointer to a PQInterface *parent, + * this is used to notify the system of Connect/Disconnect Events. + * + * Below are the Events for callback. + **/ +class NetInterface +{ +public: + + /** + * @param p_in used to notify system of connect/disconnect events + */ + NetInterface(PQInterface *p_in, std::string id) + :p(p_in), peerId(id) { return; } + +virtual ~NetInterface() + { return; } + +virtual int connect(struct sockaddr_in raddr) = 0; +virtual int listen() = 0; +virtual int stoplistening() = 0; +virtual int disconnect() = 0; +virtual int reset() = 0; +virtual std::string PeerId() { return peerId; } +virtual int getConnectAddress(struct sockaddr_in &raddr) = 0; + +virtual bool connect_parameter(uint32_t type, uint32_t value) = 0; + +protected: +PQInterface *parent() { return p; } + +private: + PQInterface *p; + std::string peerId; +}; + +//! network binary interface (abstract) +/** + * Should be used for networking and connecting to addresses + * + * @see pqissl + * @see NetInterface + * @see BinInterface + **/ +class NetBinInterface: public NetInterface, public BinInterface +{ +public: + NetBinInterface(PQInterface *parent, std::string id) + :NetInterface(parent, id) + { return; } +virtual ~NetBinInterface() { return; } +}; + +#define CHAN_SIGN_SIZE 16 +#define CERTSIGNLEN 16 /* actual byte length of signature */ +#define PQI_PEERID_LENGTH 32 /* When expanded into a string */ + + + +#endif // PQI_BASE_ITEM_HEADER + diff --git a/libretroshare/src/pqi/pqiarchive.cc b/libretroshare/src/pqi/pqiarchive.cc new file mode 100644 index 000000000..71deff4bf --- /dev/null +++ b/libretroshare/src/pqi/pqiarchive.cc @@ -0,0 +1,488 @@ +/* + * "$Id: pqiarchive.cc,v 1.5 2007-03-21 18:45:41 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +/* This is dependent on the sslroot at the moment. + * -> as we need to create/restore references to the Person. + * -> and store the signatures to do this. + */ + +/******************************************************************* + * pqiarchive provides an archive stream. + * This stores RsItem + Person Reference + Timestamp, + * + * and allows Objects to be replayed or restored, + * independently of the rest of the pqi system. + * + */ + +#include "pqi/pqiarchive.h" +#include "serialiser/rsserial.h" +#include +#include + +#include +#include "util/rsdebug.h" +#include + +const int pqiarchivezone = 9326; + +struct pqiarchive_header +{ + uint32_t type; + uint32_t length; + uint32_t ts; + uint8_t personSig[PQI_PEERID_LENGTH]; +}; + +const int PQIARCHIVE_TYPE_PQITEM = 0x0001; + +/* PeerId of PQInterface is not important ... as we are archiving + * packets from other people... + */ + +pqiarchive::pqiarchive(RsSerialiser *rss, BinInterface *bio_in, int bio_flags_in) + :PQInterface(""), rsSerialiser(rss), bio(bio_in), bio_flags(bio_flags_in), + nextPkt(NULL), nextPktTS(0), firstPktTS(0), initTS(0),realTime(false) +{ + { + std::ostringstream out; + out << "pqiarchive::pqiarchive()"; + out << " Initialisation!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqiarchivezone, out.str()); + } + + if (!bio_in) + { + std::ostringstream out; + out << "pqiarchive::pqiarchive()"; + out << " NULL bio, FATAL ERROR!" << std::endl; + pqioutput(PQL_ALERT, pqiarchivezone, out.str()); + exit(1); + } + + return; +} + +pqiarchive::~pqiarchive() +{ + { + std::ostringstream out; + out << "pqiarchive::~pqiarchive()"; + out << " Destruction!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqiarchivezone, out.str()); + } + + if (bio_flags & BIN_FLAGS_NO_CLOSE) + { + std::ostringstream out; + out << "pqiarchive::~pqiarchive()"; + out << " Not Closing BinInterface!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqiarchivezone, out.str()); + } + else if (bio) + { + std::ostringstream out; + out << "pqiarchive::~pqiarchive()"; + out << " Deleting BinInterface!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqiarchivezone, out.str()); + + delete bio; + } + + if (rsSerialiser) + delete rsSerialiser; + + if (nextPkt) + { + delete nextPkt; + } + return; +} + + +// Get/Send Items. +int pqiarchive::SendItem(RsItem *si) +{ + { + std::ostringstream out; + out << "pqiarchive::SendItem()" << std::endl; + si -> print(out); + pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out.str()); + } + + // check if this is a writing bio. + + if (!(bio_flags & BIN_FLAGS_WRITEABLE)) + { + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete si; + return -1; + } + +// std::cerr << "SendItem: si->PeerId()=" << si->PeerId() << std::endl ; + + int ret = writePkt(si); + return ret; /* 0 - failure, 1 - success*/ +} + +RsItem *pqiarchive::GetItem() +{ + { + std::ostringstream out; + out << "pqiarchive::GetItem()"; + pqioutput(PQL_DEBUG_ALL, pqiarchivezone, out.str()); + } + + // check if this is a reading bio. + if (!(bio_flags & BIN_FLAGS_READABLE)) + { + std::ostringstream out; + out << "pqiarchive::GetItem()"; + out << "Error Not Readable" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out.str()); + return NULL; + } + + // load if we dont have a packet. + if (!nextPkt) + { + if (!readPkt(&nextPkt, &nextPktTS)) + { + std::ostringstream out; + out << "pqiarchive::GetItem()"; + out << "Failed to ReadPkt" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out.str()); + return NULL; + } + } + + if (!nextPkt) return NULL; + + + /* if realtime - check delta */ + bool rtnPkt = true; + if ((realTime) && (initTS)) + { + int delta = time(NULL) - initTS; + int delta2 = nextPktTS - firstPktTS; + if (delta >= delta2) + { + rtnPkt = true; + } + else + { + rtnPkt = false; + } + } + + if (rtnPkt) + { + if (!initTS) + { + /* first read! */ + initTS = time(NULL); + firstPktTS = nextPktTS; + } + RsItem *outPkt = nextPkt; + nextPkt = NULL; + + if (outPkt != NULL) + { + std::ostringstream out; + out << "pqiarchive::GetItem() Returning:" << std::endl; + outPkt -> print(out); + pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out.str()); + } + return outPkt; + } + return NULL; +} + +// // PQInterface +int pqiarchive::tick() +{ + { + std::ostringstream out; + out << "pqiarchive::tick()"; + out << std::endl; + } + return 0; +} + +int pqiarchive::status() +{ + { + std::ostringstream out; + out << "pqiarchive::status()"; + pqioutput(PQL_DEBUG_ALL, pqiarchivezone, out.str()); + } + return 0; +} + +// +/**************** HANDLE OUTGOING TRANSLATION + TRANSMISSION ******/ + +int pqiarchive::writePkt(RsItem *pqi) +{ +// std::cerr << "writePkt, pqi->peerId()=" << pqi->PeerId() << std::endl ; + { + std::ostringstream out; + out << "pqiarchive::writePkt()"; + pqioutput(PQL_DEBUG_ALL, pqiarchivezone, out.str()); + } + + uint32_t pktsize = rsSerialiser->size(pqi); + void *ptr = malloc(pktsize); + if (!(rsSerialiser->serialise(pqi, ptr, &pktsize))) + { + std::ostringstream out; + out << "pqiarchive::writePkt() Null Pkt generated!"; + out << std::endl; + out << "Caused By: " << std::endl; + pqi -> print(out); + pqioutput(PQL_ALERT, pqiarchivezone, out.str()); + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + return 0; + } + + /* extract the extra details */ + uint32_t len = getRsItemSize(ptr); + if (len != pktsize) + { + std::ostringstream out; + out << "pqiarchive::writePkt() Length MisMatch: len: " << len; + out << " != pktsize: " << pktsize; + out << std::endl; + out << "Caused By: " << std::endl; + pqi -> print(out); + pqioutput(PQL_ALERT, pqiarchivezone, out.str()); + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + return 0; + } + + + if (!(bio->cansend())) + { + std::ostringstream out; + out << "pqiarchive::writePkt() BIO cannot write!"; + out << std::endl; + out << "Discarding: " << std::endl; + pqi -> print(out); + pqioutput(PQL_ALERT, pqiarchivezone, out.str()); + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + + return 0; + } + + // using the peerid from the item. + if (pqi->PeerId().length() != PQI_PEERID_LENGTH) + { + std::ostringstream out; + out << "pqiarchive::writePkt() Invalid peerId Length!"; + out << std::endl; + out << "Found " << pqi->PeerId().length() << " instead of " << PQI_PEERID_LENGTH << std::endl ; + out << "pqi->PeerId() = " << pqi->PeerId() << std::endl ; + out << "Caused By: " << std::endl; + pqi -> print(out); + pqioutput(PQL_ALERT, pqiarchivezone, out.str()); + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + return 0; + } + + std::ostringstream out; + out << "Writing Pkt Header" << std::endl; + struct pqiarchive_header hdr; + hdr.type = PQIARCHIVE_TYPE_PQITEM; + hdr.length = len; + hdr.ts = time(NULL); + memcpy(hdr.personSig, pqi->PeerId().c_str(), PQI_PEERID_LENGTH); + + // write packet header. + if (sizeof(hdr) != bio->senddata(&hdr, sizeof(hdr))) + { + out << "Trouble writing header!"; + out << std::endl; + pqioutput(PQL_ALERT, pqiarchivezone, out.str()); + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + + return 0; + } + + out << "Writing Pkt Body" << std::endl; + + // write packet. + if (len != bio->senddata(ptr, len)) + { + out << "Problems with Send Data!"; + out << std::endl; + pqioutput(PQL_ALERT, pqiarchivezone, out.str()); + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + + return 0; + } + + out << " Success!" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqiarchivezone, out.str()); + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + + return 1; +} + +/* Reads a single packet from the input stream + * gets the timestamp as well. + * + */ + +int pqiarchive::readPkt(RsItem **item_out, long *ts_out) +{ + { + std::ostringstream out; + out << "pqiarchive::readPkt()"; + pqioutput(PQL_DEBUG_ALL, pqiarchivezone, out.str()); + } + + if ((!(bio->isactive())) || (!(bio->moretoread()))) + { + return 0; + } + + // header + struct pqiarchive_header hdr; + + // enough space to read any packet. + int maxlen = getRsPktMaxSize(); + void *block = malloc(maxlen); + + // initial read size: basic packet. + int blen = getRsPktBaseSize(); + + int tmplen; + + /* read in the header */ + if (sizeof(hdr) != bio->readdata(&hdr, sizeof(hdr))) + { + /* error */ + pqioutput(PQL_WARNING, pqiarchivezone, + "pqiarchive::readPkt() bad read(1)"); + + free(block); + return 0; + } + + /* we have the header */ + + // read the basic block (minimum packet size) + if (blen != (tmplen = bio->readdata(block, blen))) + { + pqioutput(PQL_WARNING, pqiarchivezone, + "pqiarchive::readPkt() bad read(2)"); + + free(block); + return 0; + } + + // workout how much more to read. + int extralen = getRsItemSize(block) - blen; + if (extralen > 0) + { + void *extradata = (void *) (((char *) block) + blen); + if (extralen != (tmplen = bio->readdata(extradata, extralen))) + { + + std::ostringstream out; + out << "pqiarchive::readPkt() "; + out << "Error Completing Read (read "; + out << tmplen << "/" << extralen << ")" << std::endl; + pqioutput(PQL_ALERT, pqiarchivezone, out.str()); + + free(block); + return 0; + } + } + + // create packet, based on header. + //std::cerr << "Read Data Block -> Incoming Pkt("; + //std::cerr << blen + extralen << ")" << std::endl; + uint32_t readbytes = extralen + blen; + + RsItem *item = rsSerialiser->deserialise(block, &readbytes); + free(block); + + if (item == NULL) + { + pqioutput(PQL_ALERT, pqiarchivezone, + "pqiarchive::readPkt() Failed to create Item from archive!"); + return 0; + } + + /* Cannot detect bad ids here anymore.... + * but removed dependancy on the sslroot! + */ + + std::string peerId = ""; + for(int i = 0; i < PQI_PEERID_LENGTH; i++) + { + peerId += hdr.personSig[i]; + } + item->PeerId(peerId); + + *item_out = item; + *ts_out = hdr.ts; + + return 1; +} + +/**** Hashing Functions ****/ +std::string pqiarchive::gethash() +{ + return bio->gethash(); +} + + + diff --git a/libretroshare/src/pqi/pqiarchive.h b/libretroshare/src/pqi/pqiarchive.h new file mode 100644 index 000000000..1c329bd33 --- /dev/null +++ b/libretroshare/src/pqi/pqiarchive.h @@ -0,0 +1,81 @@ +/* + * "$Id: pqiarchive.h,v 1.3 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_ARCHIVE_STREAMER_HEADER +#define MRK_PQI_ARCHIVE_STREAMER_HEADER + +#include "pqi/pqi.h" + +#include + +/******************************************************************* + * pqiarchive provides an archive stream. + * This stores RsItem + Person Reference + Timestamp, + * + * and allows Objects to be replayed or restored, + * independently of the rest of the pqi system. + * + */ + +class pqiarchive: public PQInterface +{ +public: + pqiarchive(RsSerialiser *rss, BinInterface *bio_in, int bio_flagsin); +virtual ~pqiarchive(); + +// PQInterface +virtual int SendItem(RsItem *); +virtual RsItem *GetItem(); + +virtual int tick(); +virtual int status(); + +virtual void setRealTime(bool r) { realTime = r; } + +std::string gethash(); + + private: +int writePkt(RsItem *item); +int readPkt(RsItem **item_out, long *ts); + + // Serialiser + RsSerialiser *rsSerialiser; + // Binary Interface for IO, initialisated at startup. + BinInterface *bio; + unsigned int bio_flags; // only BIN_NO_CLOSE at the moment. + + // Temp Storage for transient data..... + RsItem *nextPkt; + long nextPktTS; /* timestamp associated with nextPkt */ + long firstPktTS; /* timestamp associated with first read Pkt */ + long initTS; /* clock timestamp at first read */ + + bool realTime; +}; + + +#endif //MRK_PQI_ARCHIVE_STREAMER_HEADER diff --git a/libretroshare/src/pqi/pqiassist.h b/libretroshare/src/pqi/pqiassist.h new file mode 100644 index 000000000..5aaee6581 --- /dev/null +++ b/libretroshare/src/pqi/pqiassist.h @@ -0,0 +1,119 @@ +/* + * libretroshare/src/pqi: pqiassist.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef MRK_PQI_ASSIST_H +#define MRK_PQI_ASSIST_H + +#include +#include +#include "pqi/pqinetwork.h" +#include "pqi/pqimonitor.h" + +/********** + * This header file provides two interfaces for assisting + * the connections to friends. + * + * pqiNetAssistFirewall - which will provides interfaces + * to functionality like upnp and apple's equivalent. + * + * pqiNetAssistConnect - which will provides interfaces + * to other networks (DHT) etc that can provide information. + * These classes would be expected to use the pqiMonitor + * callback system to notify the connectionMgr. + * + ***/ + +class pqiNetAssist +{ + public: + +virtual ~pqiNetAssist() { return; } + + /* External Interface */ +virtual void enable(bool on) = 0; +virtual void shutdown() = 0; /* blocking call */ +virtual void restart() = 0; + +virtual bool getEnabled() = 0; +virtual bool getActive() = 0; + +}; + +class pqiNetAssistFirewall: public pqiNetAssist +{ + public: + +virtual ~pqiNetAssistFirewall() { return; } + + /* the address that the listening port is on */ +virtual void setInternalPort(unsigned short iport_in) = 0; +virtual void setExternalPort(unsigned short eport_in) = 0; + + /* as determined by uPnP */ +virtual bool getInternalAddress(struct sockaddr_in &addr) = 0; +virtual bool getExternalAddress(struct sockaddr_in &addr) = 0; + +}; + + + + +class pqiNetAssistConnect: public pqiNetAssist +{ + /* + */ + public: + pqiNetAssistConnect(std::string id, pqiConnectCb *cb) + :mPeerId(id), mConnCb(cb) { return; } + + /********** External DHT Interface ************************ + * These Functions are the external interface + * for the DHT, and must be non-blocking and return quickly + */ + + /* add / remove peers */ +virtual bool findPeer(std::string id) = 0; +virtual bool dropPeer(std::string id) = 0; + + /* extract current peer status */ +virtual bool getPeerStatus(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t &type, uint32_t &mode) = 0; + +//virtual bool getExternalInterface(struct sockaddr_in &raddr, +// uint32_t &mode) = 0; + + /***** Stats for Network / DHT *****/ +virtual bool getNetworkStats(uint32_t &netsize, uint32_t &localnetsize) = 0; + + protected: + std::string mPeerId; + pqiConnectCb *mConnCb; +}; + + +#endif /* MRK_PQI_ASSIST_H */ + diff --git a/libretroshare/src/pqi/pqibin.cc b/libretroshare/src/pqi/pqibin.cc new file mode 100644 index 000000000..bf39c87e6 --- /dev/null +++ b/libretroshare/src/pqi/pqibin.cc @@ -0,0 +1,711 @@ +/* + * "$Id: pqibin.cc,v 1.4 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqibin.h" +#include "pqi/authssl.h" +#include "util/rsnet.h" +#include "util/rsdir.h" + +// #define DEBUG_PQIBIN + +BinFileInterface::BinFileInterface(const char *fname, int flags) + :bin_flags(flags), buf(NULL), hash(NULL), bcount(0) +{ + /* if read + write - open r+ */ + if ((bin_flags & BIN_FLAGS_READABLE) && + (bin_flags & BIN_FLAGS_WRITEABLE)) + { + buf = RsDirUtil::rs_fopen(fname, "rb+"); + /* if the file don't exist */ + if (!buf) + { + buf = RsDirUtil::rs_fopen(fname, "wb+"); + } + + } + else if (bin_flags & BIN_FLAGS_READABLE) + { + buf = RsDirUtil::rs_fopen(fname, "rb"); + } + else if (bin_flags & BIN_FLAGS_WRITEABLE) + { + // This is enough to remove old file in Linux... + // but not in windows.... (what to do) + buf = RsDirUtil::rs_fopen(fname, "wb"); + fflush(buf); /* this might help windows! */ + } + else + { + /* not read or write! */ + } + + if (buf) + { +#ifdef DEBUG_PQIBIN + std::cerr << "BinFileInterface: " << (void*)this << ": openned file " << fname << std::endl; +#endif + /* no problem */ + + /* go to the end */ + fseek(buf, 0L, SEEK_END); + /* get size */ + size = ftell(buf); + /* back to the start */ + fseek(buf, 0L, SEEK_SET); + } + else + { + size = 0; + } + + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash = new pqihash(); + } +} + + +BinFileInterface::~BinFileInterface() +{ + if (buf) + { + fclose(buf); +#ifdef DEBUG_PQIBIN + std::cerr << "BinFileInterface: " << (void*)this << ": closed file " << std::endl; +#endif + } + + if (hash) + { + delete hash; + } +} + +int BinFileInterface::close() +{ + if (buf) + { + fclose(buf); +#ifdef DISTRIB_DEBUG + std::cerr << "BinFileInterface: " << (void*)this << ": closed file " << std::endl; +#endif + buf = NULL; + } + return 1; +} + +int BinFileInterface::senddata(void *data, int len) +{ + if (!buf) + return -1; + + if (1 != fwrite(data, len, 1, buf)) + { + return -1; + } + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->addData(data, len); + bcount += len; + } + return len; +} + +int BinFileInterface::readdata(void *data, int len) +{ + if (!buf) + return -1; + + if (1 != fread(data, len, 1, buf)) + { + return -1; + } + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->addData(data, len); + bcount += len; + } + return len; +} + +std::string BinFileInterface::gethash() +{ + std::string hashstr; + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->Complete(hashstr); + } + return hashstr; +} + +uint64_t BinFileInterface::bytecount() +{ + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + return bcount; + } + return 0; +} + +int BinFileInterface::getFileSize() +{ + return size; +} + + + +BinEncryptedFileInterface::BinEncryptedFileInterface(const char* fname, int flags) + : BinFileInterface(fname, flags), data(NULL), haveData(false), sizeData(0), cpyCount(0) +{ +} + +BinEncryptedFileInterface::~BinEncryptedFileInterface() +{ + if((sizeData > 0) && data != NULL) + { + delete[] data; + } + +} + +int BinEncryptedFileInterface::senddata(void* data, int len) +{ + + char* encrytedData = NULL; + int encDataLen = 0; + + // encrypt using own ssl public key + if(len > 0) + AuthSSL::getAuthSSL()->encrypt((void*&)encrytedData, encDataLen, data, len, AuthSSL::getAuthSSL()->OwnId()); + else + return -1; + + + if((encDataLen > 0) && (encrytedData != NULL)) + { + BinFileInterface::senddata(encrytedData, encDataLen); + delete[] encrytedData; + } + else + { + return -1; + } + + return len; +} + + +int BinEncryptedFileInterface::readdata(void* data, int len) +{ + // to respect the inherited behavior of BinInterface + // the whole file is read and decryped and store to be read by subsequent calls + char* encryptedData = NULL; + int encrypDataLen = 0; + + + if(!haveData) // read whole data for first call, or first call after close() + { + + encrypDataLen = BinFileInterface::getFileSize(); + encryptedData = new char[encrypDataLen]; + + // make sure assign was successful + if(encryptedData == NULL) + return -1; + + + if(-1 == BinFileInterface::readdata(encryptedData, encrypDataLen)) + return -1; + + if((encrypDataLen > 0) && (encryptedData != NULL)) + { + + if(!AuthSSL::getAuthSSL()->decrypt((void*&)(this->data), sizeData, encryptedData, encrypDataLen)) + return -1; + + haveData = true; + delete[] encryptedData; + } + + + if(len <= sizeData) + { + memcpy(data, this->data, len); + cpyCount += len; + } + else + { + std::cerr << "BinEncryptedFileInterface::readData(): Error, Asking for more data than present" << std::endl; + return -1; + } + } + else + { + + if((cpyCount + len) <= sizeData) + { + memcpy(data, (void *) ((this->data) + cpyCount), len); + cpyCount += len; + } + else + { + std::cerr << "BinEncryptedFileInterface::readData(): Error, Asking for more data than present" << std::endl; + return -1; + } + } + + return len; +} + +int BinEncryptedFileInterface::close() +{ + if(data != NULL) + { + delete[] data; + sizeData = 0; + haveData = false; + cpyCount = 0; + } + + return BinFileInterface::close(); +} + +uint64_t BinEncryptedFileInterface::bytecount() +{ + return cpyCount; +} + +bool BinEncryptedFileInterface::moretoread() +{ + if(haveData) + return (cpyCount < sizeData); + else + return cpyCount < getFileSize(); +} + +BinMemInterface::BinMemInterface(int defsize, int flags) + :bin_flags(flags), buf(NULL), size(defsize), + recvsize(0), readloc(0), hash(NULL), bcount(0) + { + buf = malloc(defsize); + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash = new pqihash(); + } + } + + +BinMemInterface::BinMemInterface(const void *data, const int defsize, int flags) + :bin_flags(flags), buf(NULL), size(defsize), + recvsize(0), readloc(0), hash(NULL), bcount(0) + { + buf = malloc(defsize); + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash = new pqihash(); + } + + /* just remove the const + * *BAD* but senddata don't change it anyway + */ + senddata((void *) data, defsize); + } + +BinMemInterface::~BinMemInterface() +{ + if (buf) + free(buf); + + if (hash) + delete hash; + return; +} + +int BinMemInterface::close() +{ + if (buf) + { + free(buf); + buf = NULL; + } + size = 0; + recvsize = 0; + readloc = 0; + return 1; +} + + /* some fns to mess with the memory */ +int BinMemInterface::fseek(int loc) + { + if (loc <= recvsize) + { + readloc = loc; + return 1; + } + return 0; + } + + +int BinMemInterface::senddata(void *data, const int len) + { + if(recvsize + len > size) + { + /* resize? */ + return -1; + } + memcpy((char *) buf + recvsize, data, len); + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->addData(data, len); + bcount += len; + } + recvsize += len; + return len; + } + + +int BinMemInterface::readdata(void *data, int len) + { + if(readloc + len > recvsize) + { + /* no more stuff? */ + return -1; + } + memcpy(data, (char *) buf + readloc, len); + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->addData(data, len); + bcount += len; + } + readloc += len; + return len; + } + + + +std::string BinMemInterface::gethash() + { + std::string hashstr; + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash->Complete(hashstr); + } + return hashstr; + } + + +uint64_t BinMemInterface::bytecount() +{ + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + return bcount; + } + return 0; +} + +bool BinMemInterface::writetofile(const char *fname) +{ + FILE *fd = RsDirUtil::rs_fopen(fname, "wb"); + if (!fd) + { + return false; + } + + if (1 != fwrite(buf, recvsize, 1, fd)) + { + fclose(fd); + return false; + } + + fclose(fd); + + return true; +} + +bool BinMemInterface::readfromfile(const char *fname) +{ + FILE *fd = RsDirUtil::rs_fopen(fname, "rb"); + if (!fd) + { + return false; + } + + /* get size */ + ::fseek(fd, 0L, SEEK_END); + int fsize = ftell(fd); + + if (fsize > size) + { + /* not enough room */ + std::cerr << "BinMemInterface::readfromfile() not enough room"; + std::cerr << std::endl; + + fclose(fd); + return false; + } + + ::fseek(fd, 0L, SEEK_SET); + if (1 != fread(buf, fsize, 1, fd)) + { + /* not enough room */ + std::cerr << "BinMemInterface::readfromfile() failed fread"; + std::cerr << std::endl; + + fclose(fd); + return false; + } + + recvsize = fsize; + readloc = 0; + fclose(fd); + + return true; +} + + +/**************************************************************************/ + + +void printNetBinID(std::ostream &out, std::string id, uint32_t t) +{ + out << "NetBinId(" << id << ","; + if (t == PQI_CONNECT_TCP) + { + out << "TCP)"; + } + else + { + out << "UDP)"; + } +} + + +/************************** NetBinDummy ****************************** + * A test framework, + * + */ + +#include "pqi/pqiperson.h" + +const uint32_t DEFAULT_DUMMY_DELTA = 5; + +NetBinDummy::NetBinDummy(PQInterface *parent, std::string id, uint32_t t) + :NetBinInterface(parent, id), type(t), dummyConnected(false), + toConnect(false), connectDelta(DEFAULT_DUMMY_DELTA) +{ + return; +} + + // Net Interface +int NetBinDummy::connect(struct sockaddr_in raddr) +{ + std::cerr << "NetBinDummy::connect("; + std::cerr << rs_inet_ntoa(raddr.sin_addr) << ":"; + std::cerr << htons(raddr.sin_port); + std::cerr << ") "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + std::cerr << "NetBinDummy::dummyConnect = true!"; + std::cerr << std::endl; + + if (type == PQI_CONNECT_TCP) + { + std::cerr << "NetBinDummy:: Not connecting TCP"; + std::cerr << std::endl; + if (parent()) + { + parent()->notifyEvent(this, CONNECT_FAILED); + } + } + else if (!dummyConnected) + { + toConnect = true; + connectTS = time(NULL) + connectDelta; + std::cerr << "NetBinDummy::toConnect = true, connect in: "; + std::cerr << connectDelta << " secs"; + std::cerr << std::endl; + } + else + { + std::cerr << "NetBinDummy:: Already Connected!"; + std::cerr << std::endl; + } + + return 1; +} + +int NetBinDummy::listen() +{ + std::cerr << "NetBinDummy::connect() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return 1; +} + +int NetBinDummy::stoplistening() +{ + std::cerr << "NetBinDummy::stoplistening() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return 1; +} + +int NetBinDummy::disconnect() +{ + std::cerr << "NetBinDummy::disconnect() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + std::cerr << "NetBinDummy::dummyConnect = false!"; + std::cerr << std::endl; + dummyConnected = false; + + if (parent()) + { + parent()->notifyEvent(this, CONNECT_FAILED); + } + + return 1; +} + +int NetBinDummy::reset() +{ + std::cerr << "NetBinDummy::reset() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + disconnect(); + + return 1; +} + + + // Bin Interface. +int NetBinDummy::tick() +{ + + if (toConnect) + { + if (connectTS < time(NULL)) + { + std::cerr << "NetBinDummy::tick() dummyConnected = true "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + dummyConnected = true; + toConnect = false; + if (parent()) + parent()->notifyEvent(this, CONNECT_SUCCESS); + } + else + { + std::cerr << "NetBinDummy::tick() toConnect "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + } + } + return 0; +} + +int NetBinDummy::senddata(void *data, int len) +{ + std::cerr << "NetBinDummy::senddata() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + if (dummyConnected) + return len; + return 0; +} + +int NetBinDummy::readdata(void *data, int len) +{ + std::cerr << "NetBinDummy::readdata() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return 0; +} + +int NetBinDummy::netstatus() +{ + std::cerr << "NetBinDummy::netstatus() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return 1; +} + +int NetBinDummy::isactive() +{ + std::cerr << "NetBinDummy::isactive() "; + printNetBinID(std::cerr, PeerId(), type); + if (dummyConnected) + std::cerr << " true "; + else + std::cerr << " false "; + std::cerr << std::endl; + + return dummyConnected; +} + +bool NetBinDummy::moretoread() +{ + std::cerr << "NetBinDummy::moretoread() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return false; +} + +bool NetBinDummy::cansend() +{ + std::cerr << "NetBinDummy::cansend() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return dummyConnected; +} + +int NetBinDummy::close() +{ + std::cerr << "NetBinDummy::close() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return 1; +} + +std::string NetBinDummy::gethash() +{ + std::cerr << "NetBinDummy::gethash() "; + printNetBinID(std::cerr, PeerId(), type); + std::cerr << std::endl; + + return std::string(""); +} + diff --git a/libretroshare/src/pqi/pqibin.h b/libretroshare/src/pqi/pqibin.h new file mode 100644 index 000000000..55479e297 --- /dev/null +++ b/libretroshare/src/pqi/pqibin.h @@ -0,0 +1,236 @@ +/* + * "$Id: pqibin.h,v 1.2 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef PQI_BIN_INTERFACE_HEADER +#define PQI_BIN_INTERFACE_HEADER + + +#include "pqi/pqi_base.h" +#include "pqi/pqihash.h" + +#include + + +//! handles writing to binary files +/*! + * This allows for handling of binary file within Rs, In particular writing + * binary data to file declared in constructor + */ +class BinFileInterface: public BinInterface +{ +public: + BinFileInterface(const char *fname, int flags); +virtual ~BinFileInterface(); + +virtual int tick() { return 1; } + +virtual int senddata(void *data, int len); +virtual int readdata(void *data, int len); +virtual int netstatus() { return 1;} +virtual int isactive() { return (buf != NULL);} +virtual bool moretoread() + { + if ((buf) && (bin_flags | BIN_FLAGS_READABLE)) + { + if ((size - ftell(buf)) > 0) + { + return true; + } + } + return false; + } + +virtual int close(); +virtual bool cansend() { return (bin_flags | BIN_FLAGS_WRITEABLE); } +virtual bool bandwidthLimited() { return false; } + +//! if HASHing is switched on +virtual std::string gethash(); +virtual uint64_t bytecount(); + +protected: + virtual int getFileSize(); + +private: + int bin_flags; + FILE *buf; + int size; + pqihash *hash; + uint64_t bcount; +}; + +/*! + * use this for writing encrypted data to file using user's (ownid) ssl key + * hash for encrypted data is calculated, not the unencrypted data + */ +class BinEncryptedFileInterface : public BinFileInterface +{ +public: + + BinEncryptedFileInterface(const char *fname, int flags); + virtual ~BinEncryptedFileInterface(); + + /*! + * pls note if hashing is on, it is the hash of the encrypted data that is calculated + * also note, sif data is sent more than once, in a single instance of this object, then you will need to store the + * encrypted file size for each send externally as they are encrypted with different random keys. + * @param data data to be sent + * @param len length of data in bytes + * @return -1 if failed to write data, if not number bytes sent to file is returned + */ + int senddata(void *data, int len); + + /*! + * uses the hash of the encrypted data + * @param location to place data + * @param the length of data to be read + * @return -1 if failed to write data, if not number of bytes read is returned + */ + int readdata(void *data, int len); + + /*! + * this releases resources held by an instance + */ + int close(); + + uint64_t bytecount(); + bool moretoread(); + +private: + + char* data; + bool haveData; + int sizeData; + uint64_t cpyCount; + +}; + +//! handles writing to reading/writing to memory +/*! + * This provide a memory interface for storing/retrieving information in memory + * to be read/sent elsewhere + */ +class BinMemInterface: public BinInterface +{ +public: + BinMemInterface(int defsize, int flags); + BinMemInterface(const void *data, const int size, int flags); +virtual ~BinMemInterface(); + + /* Extra Interfaces */ +int fseek(int loc); +int memsize() { return recvsize; } +void *memptr() { return buf; } + + /* file interface */ +bool writetofile(const char *fname); +bool readfromfile(const char *fname); + +virtual int tick() { return 1; } + +virtual int senddata(void *data, int len); +virtual int readdata(void *data, int len); +virtual int netstatus() { return 1; } +virtual int isactive() { return 1; } +virtual bool moretoread() + { + if ((buf) && (bin_flags | BIN_FLAGS_READABLE )) + { + if (readloc < recvsize) + { + return true; + } + } + return false; + } + +virtual int close(); +virtual bool cansend() { return (bin_flags | BIN_FLAGS_WRITEABLE); } +virtual bool bandwidthLimited() { return false; } + +virtual std::string gethash(); +virtual uint64_t bytecount(); + + private: + int bin_flags; + void *buf; + int size; + int recvsize; + int readloc; + pqihash *hash; + uint64_t bcount; +}; + + +class NetBinDummy: public NetBinInterface +{ +public: + NetBinDummy(PQInterface *parent, std::string id, uint32_t t); +virtual ~NetBinDummy() { return; } + + // Net Interface +virtual int connect(struct sockaddr_in raddr); +virtual int listen(); +virtual int stoplistening(); +virtual int disconnect(); +virtual int reset(); +virtual bool connect_parameter(uint32_t type, uint32_t value) + { + (void) type; /* suppress unused parameter warning */ + (void) value; /* suppress unused parameter warning */ + return false; + } +virtual int getConnectAddress(struct sockaddr_in &raddr) + { + (void) raddr; /* suppress unused parameter warning */ + return 0; + } + + // Bin Interface. +virtual int tick(); + +virtual int senddata(void *data, int len); +virtual int readdata(void *data, int len); +virtual int netstatus(); +virtual int isactive(); +virtual bool moretoread(); +virtual bool cansend(); +virtual int close(); + +virtual std::string gethash(); + + private: + uint32_t type; + bool dummyConnected; + bool toConnect; + uint32_t connectDelta; + time_t connectTS; +}; + + +#endif // PQI_BINARY_INTERFACES_HEADER + diff --git a/libretroshare/src/pqi/pqihandler.cc b/libretroshare/src/pqi/pqihandler.cc new file mode 100644 index 000000000..cefbf865b --- /dev/null +++ b/libretroshare/src/pqi/pqihandler.cc @@ -0,0 +1,782 @@ +/* + * "$Id: pqihandler.cc,v 1.12 2007-03-31 09:41:32 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +#include "pqi/pqihandler.h" + +#include +#include "util/rsdebug.h" +#include +const int pqihandlerzone = 34283; + +/**** +#define DEBUG_TICK 1 +#define RSITEM_DEBUG 1 +****/ + +pqihandler::pqihandler(SecurityPolicy *Global) +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + // The global security.... + // if something is disabled here... + // cannot be enabled by module. + globsec = Global; + + { + std::ostringstream out; + out << "New pqihandler()" << std::endl; + out << "Security Policy: " << secpolicy_print(globsec); + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out.str()); + } + + // setup minimal total+individual rates. + rateIndiv_out = 0.01; + rateIndiv_in = 0.01; + rateMax_out = 0.01; + rateMax_in = 0.01; + return; +} + +int pqihandler::tick() +{ + int moreToTick = 0; + + { RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + // tick all interfaces... + std::map::iterator it; + for(it = mods.begin(); it != mods.end(); it++) + { + if (0 < ((it -> second) -> pqi) -> tick()) + { +#ifdef DEBUG_TICK + std::cerr << "pqihandler::tick() moreToTick from mod()" << std::endl; +#endif + moreToTick = 1; + } + } + // get the items, and queue them correctly + if (0 < locked_GetItems()) + { +#ifdef DEBUG_TICK + std::cerr << "pqihandler::tick() moreToTick from GetItems()" << std::endl; +#endif + moreToTick = 1; + } + } /****** UNLOCK ******/ + + UpdateRates(); + return moreToTick; +} + + +int pqihandler::status() +{ + std::map::iterator it; + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + { // for output + std::ostringstream out; + out << "pqihandler::status() Active Modules:" << std::endl; + + // display all interfaces... + for(it = mods.begin(); it != mods.end(); it++) + { + out << "\tModule [" << it -> first << "] Pointer <"; + out << (void *) ((it -> second) -> pqi) << ">" << std::endl; + } + + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out.str()); + + } // end of output. + + + // status all interfaces... + for(it = mods.begin(); it != mods.end(); it++) + { + ((it -> second) -> pqi) -> status(); + } + return 1; +} + + + +bool pqihandler::AddSearchModule(SearchModule *mod) +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + // if peerid used -> error. + std::map::iterator it; + if (mod->peerid != mod->pqi->PeerId()) + { + // ERROR! + std::ostringstream out; + out << "ERROR peerid != PeerId!" << std::endl; + pqioutput(PQL_ALERT, pqihandlerzone, out.str()); + return false; + } + + if (mod->peerid == "") + { + // ERROR! + std::ostringstream out; + out << "ERROR peerid == NULL" << std::endl; + pqioutput(PQL_ALERT, pqihandlerzone, out.str()); + return false; + } + + if (mods.find(mod->peerid) != mods.end()) + { + // ERROR! + std::ostringstream out; + out << "ERROR PeerId Module already exists!" << std::endl; + pqioutput(PQL_ALERT, pqihandlerzone, out.str()); + return false; + } + + // check security. + if (mod -> sp == NULL) + { + // create policy. + mod -> sp = secpolicy_create(); + } + + // limit to what global security allows. + secpolicy_limit(globsec, mod -> sp); + + // store. + mods[mod->peerid] = mod; + return true; +} + +bool pqihandler::RemoveSearchModule(SearchModule *mod) +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + std::map::iterator it; + for(it = mods.begin(); it != mods.end(); it++) + { + if (mod == it -> second) + { + mods.erase(it); + return true; + } + } + return false; +} + +// dummy output check +int pqihandler::locked_checkOutgoingRsItem(RsItem *item, int global) +{ + pqioutput(PQL_WARNING, pqihandlerzone, + "pqihandler::checkOutgoingPQItem() NULL fn"); + return 1; +} + + + +// generalised output +int pqihandler::HandleRsItem(RsItem *item, int allowglobal) +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + std::map::iterator it; + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "pqihandler::HandleRsItem()"); + + /* simplified to no global! */ + if (allowglobal) + { + /* error */ + std::ostringstream out; + out << "pqihandler::HandleSearchItem()"; + out << " Cannot send out Global RsItem"; + pqioutput(PQL_ALERT, pqihandlerzone, out.str()); +#ifdef DEBUG_TICK + std::cerr << out.str(); +#endif + delete item; + return -1; + } + + if (!locked_checkOutgoingRsItem(item, allowglobal)) + { + std::ostringstream out; + out << "pqihandler::HandleRsItem() checkOutgoingPQItem"; + out << " Failed on item: " << std::endl; +#ifdef DEBUG_TICK + std::cerr << out.str(); +#endif + item -> print(out); + + pqioutput(PQL_ALERT, pqihandlerzone, out.str()); + delete item; + return -1; + } + + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "pqihandler::HandleRsItem() Sending to One Channel"); +#ifdef DEBUG_TICK + std::cerr << "pqihandler::HandleRsItem() Sending to One Channel" << std::endl; +#endif + + + // find module. + if ((it = mods.find(item->PeerId())) == mods.end()) + { + std::ostringstream out; + out << "pqihandler::HandleRsItem() Invalid chan!"; + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out.str()); +#ifdef DEBUG_TICK + std::cerr << out.str(); +#endif + + delete item; + return -1; + } + + // check security... is output allowed. + if(0 < secpolicy_check((it -> second) -> sp, 0, PQI_OUTGOING)) + { + std::ostringstream out; + out << "pqihandler::HandleRsItem() sending to chan:"; + out << it -> first << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out.str()); +#ifdef DEBUG_TICK + std::cerr << out.str(); +#endif + + // if yes send on item. + ((it -> second) -> pqi) -> SendItem(item); + return 1; + } + else + { + std::ostringstream out; + out << "pqihandler::HandleRsItem()"; + out << " Sec not approved"; + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, out.str()); +#ifdef DEBUG_TICK + std::cerr << out.str(); +#endif + + delete item; + return -1; + } + + // if successfully sent to at least one. + return 1; +} + +int pqihandler::SearchSpecific(RsCacheRequest *ns) +{ + return HandleRsItem(ns, 0); +} + +int pqihandler::SendSearchResult(RsCacheItem *ns) +{ + return HandleRsItem(ns, 0); +} + +int pqihandler::SendFileRequest(RsFileRequest *ns) +{ + return HandleRsItem(ns, 0); +} + +int pqihandler::SendFileData(RsFileData *ns) +{ + return HandleRsItem(ns, 0); +} +int pqihandler::SendFileChunkMapRequest(RsFileChunkMapRequest *ns) +{ + return HandleRsItem(ns, 0); +} +int pqihandler::SendFileChunkMap(RsFileChunkMap *ns) +{ + return HandleRsItem(ns, 0); +} +int pqihandler::SendFileCRC32MapRequest(RsFileCRC32MapRequest *ns) +{ + return HandleRsItem(ns, 0); +} +int pqihandler::SendFileCRC32Map(RsFileCRC32Map *ns) +{ + return HandleRsItem(ns, 0); +} +int pqihandler::SendRsRawItem(RsRawItem *ns) +{ + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "pqihandler::SendRsRawItem()"); +#ifdef DEBUG_TICK + std::cerr << "pqihandler::SendRsRawItem()" << std ::endl; +#endif + return HandleRsItem(ns, 0); +} + + +// inputs. This is a very basic +// system that is completely biased and slow... +// someone please fix. + +int pqihandler::locked_GetItems() +{ + std::map::iterator it; + + RsItem *item; + int count = 0; + + // loop through modules.... + for(it = mods.begin(); it != mods.end(); it++) + { + SearchModule *mod = (it -> second); + + // check security... is output allowed. + if(0 < secpolicy_check((it -> second) -> sp, + 0, PQI_INCOMING)) // PQI_ITEM_TYPE_ITEM, PQI_INCOMING)) + { + // if yes... attempt to read. + while((item = (mod -> pqi) -> GetItem()) != NULL) + { +#ifdef RSITEM_DEBUG + std::ostringstream out; + out << "pqihandler::GetItems() Incoming Item "; + out << " from: " << mod -> pqi << std::endl; + item -> print(out); + + pqioutput(PQL_DEBUG_BASIC, + pqihandlerzone, out.str()); +#endif + + if (item->PeerId() != (mod->pqi)->PeerId()) + { + /* ERROR */ + pqioutput(PQL_ALERT, + pqihandlerzone, "ERROR PeerIds dont match!"); + item->PeerId(mod->pqi->PeerId()); + } + + locked_SortnStoreItem(item); + count++; + } + } + else + { + // not allowed to recieve from here.... + while((item = (mod -> pqi) -> GetItem()) != NULL) + { + std::ostringstream out; + out << "pqihandler::GetItems() Incoming Item "; + out << " from: " << mod -> pqi << std::endl; + item -> print(out); + out << std::endl; + out << "Item Not Allowed (Sec Pol). deleting!"; + out << std::endl; + + pqioutput(PQL_DEBUG_BASIC, + pqihandlerzone, out.str()); + + delete item; + } + } + } + return count; +} + + + + +void pqihandler::locked_SortnStoreItem(RsItem *item) +{ + /* get class type / subtype out of the item */ + uint8_t vers = item -> PacketVersion(); + uint8_t cls = item -> PacketClass(); + uint8_t type = item -> PacketType(); + uint8_t subtype = item -> PacketSubType(); + + /* whole Version reserved for SERVICES/CACHES */ + if (vers == RS_PKT_VERSION_SERVICE) + { + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "SortnStore -> Service"); + in_service.push_back(item); + item = NULL; + return; + } + + if (vers != RS_PKT_VERSION1) + { + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "SortnStore -> Invalid VERSION! Deleting!"); + delete item; + item = NULL; + return; + } + + switch(cls) + { + case RS_PKT_CLASS_BASE: + switch(type) + { + case RS_PKT_TYPE_CACHE: + switch(subtype) + { + case RS_PKT_SUBTYPE_CACHE_REQUEST: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "SortnStore -> Cache Request"); + in_search.push_back(item); + item = NULL; + break; + + case RS_PKT_SUBTYPE_CACHE_ITEM: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "SortnStore -> Cache Result"); + in_result.push_back(item); + item = NULL; + break; + + default: + break; /* no match! */ + } + break; + + case RS_PKT_TYPE_FILE: + switch(subtype) + { + case RS_PKT_SUBTYPE_FI_REQUEST: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "SortnStore -> File Request"); + in_request.push_back(item); + item = NULL; + break; + + case RS_PKT_SUBTYPE_FI_DATA: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "SortnStore -> File Data"); + in_data.push_back(item); + item = NULL; + break; + + case RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "SortnStore -> File ChunkMap Request"); + in_chunkmap_request.push_back(item); + item = NULL; + break; + + case RS_PKT_SUBTYPE_FI_CHUNK_MAP: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "SortnStore -> File ChunkMap"); + in_chunkmap.push_back(item); + item = NULL; + break; + + case RS_PKT_SUBTYPE_FI_CRC32_MAP_REQUEST: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "SortnStore -> File Crc32Map Request"); + in_crc32map_request.push_back(item); + item = NULL; + break; + + case RS_PKT_SUBTYPE_FI_CRC32_MAP: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "SortnStore -> File CRC32Map"); + in_crc32map.push_back(item); + item = NULL; + break; + + + default: + break; /* no match! */ + } + break; + + default: + break; /* no match! */ + } + break; + + default: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "SortnStore -> Unknown"); + break; + + } + + if (item) + { + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "SortnStore -> Deleting Unsorted Item"); + delete item; + } + + return; +} + + +// much like the input stuff. +RsCacheItem *pqihandler::GetSearchResult() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_result.size() != 0) + { + RsCacheItem *fi = dynamic_cast(in_result.front()); + if (!fi) { delete in_result.front(); } + in_result.pop_front(); + return fi; + } + return NULL; +} + +RsCacheRequest *pqihandler::RequestedSearch() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_search.size() != 0) + { + RsCacheRequest *fi = dynamic_cast(in_search.front()); + if (!fi) { delete in_search.front(); } + in_search.pop_front(); + return fi; + } + return NULL; +} + +RsFileRequest *pqihandler::GetFileRequest() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_request.size() != 0) + { + RsFileRequest *fi = dynamic_cast(in_request.front()); + if (!fi) { delete in_request.front(); } + in_request.pop_front(); + return fi; + } + return NULL; +} + +RsFileData *pqihandler::GetFileData() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_data.size() != 0) + { + RsFileData *fi = dynamic_cast(in_data.front()); + if (!fi) { delete in_data.front(); } + in_data.pop_front(); + return fi; + } + return NULL; +} +RsFileChunkMapRequest *pqihandler::GetFileChunkMapRequest() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_chunkmap_request.size() != 0) + { + RsFileChunkMapRequest *fi = dynamic_cast(in_chunkmap_request.front()); + if (!fi) { delete in_chunkmap_request.front(); } + in_chunkmap_request.pop_front(); + return fi; + } + return NULL; +} +RsFileChunkMap *pqihandler::GetFileChunkMap() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_chunkmap.size() != 0) + { + RsFileChunkMap *fi = dynamic_cast(in_chunkmap.front()); + if (!fi) { delete in_chunkmap.front(); } + in_chunkmap.pop_front(); + return fi; + } + return NULL; +} +RsFileCRC32MapRequest *pqihandler::GetFileCRC32MapRequest() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_crc32map_request.size() != 0) + { + RsFileCRC32MapRequest *fi = dynamic_cast(in_crc32map_request.front()); + if (!fi) { delete in_crc32map_request.front(); } + in_crc32map_request.pop_front(); + return fi; + } + return NULL; +} +RsFileCRC32Map *pqihandler::GetFileCRC32Map() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_crc32map.size() != 0) + { + RsFileCRC32Map *fi = dynamic_cast(in_crc32map.front()); + if (!fi) { delete in_crc32map.front(); } + in_crc32map.pop_front(); + return fi; + } + return NULL; +} + + +RsRawItem *pqihandler::GetRsRawItem() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_service.size() != 0) + { + RsRawItem *fi = dynamic_cast(in_service.front()); + if (!fi) { delete in_service.front(); } + in_service.pop_front(); + return fi; + } + return NULL; +} + +static const float MIN_RATE = 0.01; // 10 B/s + +// internal fn to send updates +int pqihandler::UpdateRates() +{ + std::map::iterator it; + int num_sm = mods.size(); + + float avail_in = getMaxRate(true); + float avail_out = getMaxRate(false); + + float used_bw_in = 0; + float used_bw_out = 0; + + /* Lock once rates have been retrieved */ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + int effectiveUploadsSm = 0; + int effectiveDownloadsSm = 0; + // loop through modules to get the used bandwith and the number of modules that are affectively transfering + //std::cerr << " Looping through modules" << std::endl; + for(it = mods.begin(); it != mods.end(); it++) + { + SearchModule *mod = (it -> second); + float crate_in = mod -> pqi -> getRate(true); + if (crate_in > 0.01 * avail_in || crate_in > 0.1) + { + effectiveDownloadsSm ++; + } + + float crate_out = mod -> pqi -> getRate(false); + if (crate_out > 0.01 * avail_out || crate_out > 0.1) + { + effectiveUploadsSm ++; + } + + used_bw_in += crate_in; + used_bw_out += crate_out; + } +// std::cerr << "Totals (In) Used B/W " << used_bw_in; +// std::cerr << " Available B/W " << avail_in; +// std::cerr << " Effective transfers " << effectiveDownloadsSm << std::endl; +// std::cerr << "Totals (Out) Used B/W " << used_bw_out; +// std::cerr << " Available B/W " << avail_out; +// std::cerr << " Effective transfers " << effectiveUploadsSm << std::endl; + + locked_StoreCurrentRates(used_bw_in, used_bw_out); + + //computing average rates for effective transfers + float max_in_effective = avail_in / num_sm; + if (effectiveDownloadsSm != 0) { + max_in_effective = avail_in / effectiveDownloadsSm; + } + float max_out_effective = avail_out / num_sm; + if (effectiveUploadsSm != 0) { + max_out_effective = avail_out / effectiveUploadsSm; + } + + //modify the outgoing rates if bandwith is not used well + float rate_out_modifier = 0; + if (used_bw_out / avail_out < 0.95) { + rate_out_modifier = 0.001 * avail_out; + } else if (used_bw_out / avail_out > 1.05) { + rate_out_modifier = - 0.001 * avail_out; + } + if (rate_out_modifier != 0) { + for(it = mods.begin(); it != mods.end(); it++) + { + SearchModule *mod = (it -> second); + mod -> pqi -> setMaxRate(false, mod -> pqi -> getMaxRate(false) + rate_out_modifier); + } + } + + //modify the incoming rates if bandwith is not used well + float rate_in_modifier = 0; + if (used_bw_in / avail_in < 0.95) { + rate_in_modifier = 0.001 * avail_in; + } else if (used_bw_in / avail_in > 1.05) { + rate_in_modifier = - 0.001 * avail_in; + } + if (rate_in_modifier != 0) { + for(it = mods.begin(); it != mods.end(); it++) + { + SearchModule *mod = (it -> second); + mod -> pqi -> setMaxRate(true, mod -> pqi -> getMaxRate(true) + rate_in_modifier); + } + } + + //cap the rates + for(it = mods.begin(); it != mods.end(); it++) + { + SearchModule *mod = (it -> second); + if (mod -> pqi -> getMaxRate(false) < max_out_effective) { + mod -> pqi -> setMaxRate(false, max_out_effective); + } + if (mod -> pqi -> getMaxRate(false) > avail_out) { + mod -> pqi -> setMaxRate(false, avail_out); + } + if (mod -> pqi -> getMaxRate(true) < max_in_effective) { + mod -> pqi -> setMaxRate(true, max_in_effective); + } + if (mod -> pqi -> getMaxRate(true) > avail_in) { + mod -> pqi -> setMaxRate(true, avail_in); + } + } + + return 1; +} + +void pqihandler::getCurrentRates(float &in, float &out) +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + in = rateTotal_in; + out = rateTotal_out; +} + +void pqihandler::locked_StoreCurrentRates(float in, float out) +{ + rateTotal_in = in; + rateTotal_out = out; +} + + diff --git a/libretroshare/src/pqi/pqihandler.h b/libretroshare/src/pqi/pqihandler.h new file mode 100644 index 000000000..f03a9c2c9 --- /dev/null +++ b/libretroshare/src/pqi/pqihandler.h @@ -0,0 +1,167 @@ +/* + * "$Id: pqihandler.h,v 1.10 2007-03-31 09:41:32 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_PQI_HANDLER_HEADER +#define MRK_PQI_HANDLER_HEADER + +#include "pqi/pqi.h" +#include "pqi/pqisecurity.h" + +#include "util/rsthreads.h" + +#include +#include + +class SearchModule +{ + public: + std::string peerid; + PQInterface *pqi; + SecurityPolicy *sp; +}; + +// Presents a P3 Face to the world! +// and funnels data through to a PQInterface. +// +class pqihandler: public P3Interface +{ + public: + pqihandler(SecurityPolicy *Global); +bool AddSearchModule(SearchModule *mod); +bool RemoveSearchModule(SearchModule *mod); + +// P3Interface. +virtual int SearchSpecific(RsCacheRequest *ns); +virtual int SendSearchResult(RsCacheItem *); + +// inputs. +virtual RsCacheRequest * RequestedSearch(); +virtual RsCacheItem * GetSearchResult(); + +// file i/o +virtual int SendFileRequest(RsFileRequest *ns); +virtual int SendFileData(RsFileData *ns); +virtual int SendFileChunkMapRequest(RsFileChunkMapRequest *ns); +virtual int SendFileChunkMap(RsFileChunkMap *ns); +virtual int SendFileCRC32MapRequest(RsFileCRC32MapRequest *ns); +virtual int SendFileCRC32Map(RsFileCRC32Map *ns); +virtual RsFileRequest *GetFileRequest(); +virtual RsFileData *GetFileData(); +virtual RsFileChunkMapRequest *GetFileChunkMapRequest(); +virtual RsFileChunkMap *GetFileChunkMap(); +virtual RsFileCRC32MapRequest *GetFileCRC32MapRequest(); +virtual RsFileCRC32Map *GetFileCRC32Map(); + +// Rest of P3Interface +virtual int tick(); +virtual int status(); + +// Service Data Interface +virtual int SendRsRawItem(RsRawItem *); +virtual RsRawItem *GetRsRawItem(); + + // rate control. +//indiv rate is deprecated +//void setMaxIndivRate(bool in, float val); +//float getMaxIndivRate(bool in); +void setMaxRate(bool in, float val); +float getMaxRate(bool in); + +void getCurrentRates(float &in, float &out); + + + protected: + /* check to be overloaded by those that can + * generates warnings otherwise + */ + +int HandleRsItem(RsItem *ns, int allowglobal); + +virtual int locked_checkOutgoingRsItem(RsItem *item, int global); +int locked_GetItems(); +void locked_SortnStoreItem(RsItem *item); + + RsMutex coreMtx; /* MUTEX */ + + std::map mods; + SecurityPolicy *globsec; + + // Temporary storage... + std::list in_result, in_search, in_request, in_data, in_service,in_chunkmap,in_chunkmap_request,in_crc32map_request,in_crc32map; + + private: + + // rate control. +int UpdateRates(); +void locked_StoreCurrentRates(float in, float out); + + float rateIndiv_in; + float rateIndiv_out; + float rateMax_in; + float rateMax_out; + + float rateTotal_in; + float rateTotal_out; +}; + +//inline void pqihandler::setMaxIndivRate(bool in, float val) +//{ +// RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ +// if (in) +// rateIndiv_in = val; +// else +// rateIndiv_out = val; +// return; +//} +// +//inline float pqihandler::getMaxIndivRate(bool in) +//{ +// RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ +// if (in) +// return rateIndiv_in; +// else +// return rateIndiv_out; +//} + +inline void pqihandler::setMaxRate(bool in, float val) +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + if (in) + rateMax_in = val; + else + rateMax_out = val; + return; +} + +inline float pqihandler::getMaxRate(bool in) +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + if (in) + return rateMax_in; + else + return rateMax_out; +} + +#endif // MRK_PQI_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqihash.h b/libretroshare/src/pqi/pqihash.h new file mode 100644 index 000000000..4794ff30e --- /dev/null +++ b/libretroshare/src/pqi/pqihash.h @@ -0,0 +1,90 @@ +/* + * libretroshare/src/pqi: pqihash.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include +#include + +class pqihash +{ + public: + pqihash() +{ + + sha_hash = new uint8_t[SHA_DIGEST_LENGTH]; + memset(sha_hash,0,SHA_DIGEST_LENGTH*sizeof(uint8_t)) ; + sha_ctx = new SHA_CTX; + SHA1_Init(sha_ctx); + doHash = true; +} + + ~pqihash() +{ + delete[] sha_hash; + delete sha_ctx; +} + + +void addData(void *data, uint32_t len) +{ + if (doHash) + { + SHA1_Update(sha_ctx, data, len); + } +} + +void Complete(std::string &hash) +{ + if (!doHash) + { + hash = endHash; + return; + } + + SHA1_Final(sha_hash, sha_ctx); + + std::ostringstream out; + for(int i = 0; i < SHA_DIGEST_LENGTH; i++) + { + out << std::setw(2) << std::setfill('0') << std::hex; + out << (unsigned int) (sha_hash[i]); + } + endHash = out.str(); + hash = endHash; + doHash = false; + + return; +} + + private: + + bool doHash; + std::string endHash; + uint8_t *sha_hash; + SHA_CTX *sha_ctx; +}; + + diff --git a/libretroshare/src/pqi/pqiindic.h b/libretroshare/src/pqi/pqiindic.h new file mode 100644 index 000000000..b75130265 --- /dev/null +++ b/libretroshare/src/pqi/pqiindic.h @@ -0,0 +1,65 @@ +/* + * "$Id: pqiindic.h,v 1.3 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_INDICATOR_HEADER +#define MRK_PQI_INDICATOR_HEADER + +#include + +// This will indicate to num different sources +// when the event has occured. + +class Indicator +{ + public: + Indicator(uint16_t n = 1) + :num(n), changeFlags(n) {IndicateChanged();} +void IndicateChanged() + { + for(uint16_t i = 0; i < num; i++) + changeFlags[i]=true; + } + +bool Changed(uint16_t idx = 0) + { + /* catch overflow */ + if (idx > num - 1) + return false; + + bool ans = changeFlags[idx]; + changeFlags[idx] = false; + return ans; + } + + private: + uint16_t num; + std::vector changeFlags; +}; + + + +#endif diff --git a/libretroshare/src/pqi/pqiipset.cc b/libretroshare/src/pqi/pqiipset.cc new file mode 100644 index 000000000..a1d481f76 --- /dev/null +++ b/libretroshare/src/pqi/pqiipset.cc @@ -0,0 +1,269 @@ +/* + * libretroshare/src/pqi: pqiipset.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include "pqi/pqiipset.h" + +bool pqiIpAddress::sameAddress(const pqiIpAddress &a) const +{ + return ((mAddr.sin_addr.s_addr == a.mAddr.sin_addr.s_addr) && + (mAddr.sin_port == a.mAddr.sin_port)); +} + + +bool pqiIpAddress::validAddress() const +{ + /* filter for unlikely addresses */ + if(isLoopbackNet(&(mAddr.sin_addr))) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddress::validAddress() ip parameter is loopback: disgarding." << std::endl ; +#endif + return false; + } + + if(mAddr.sin_addr.s_addr == 0 || mAddr.sin_addr.s_addr == 1 || mAddr.sin_port == 0) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddress::validAddress() ip parameter is 0.0.0.0/1, or port is 0, ignoring." << std::endl; +#endif + return false; + } + + return true; + +} + + +bool pqiIpAddrList::updateIpAddressList(const pqiIpAddress &addr) +{ + std::list::iterator it; + bool add = false; + bool newAddr = true; + +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList()"; + std::cerr << std::endl; +#endif + + if (mAddrs.size() < MAX_ADDRESS_LIST_SIZE) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList() small list: Add"; + std::cerr << std::endl; +#endif + add = true; + } + else if (mAddrs.back().mSeenTime < addr.mSeenTime) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList() oldAddr: Add"; + std::cerr << std::endl; +#endif + add = true; + } + + if ((!add) || (!addr.validAddress())) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList() not Add or !valid.. fail"; + std::cerr << std::endl; +#endif + return false; + } + + for(it = mAddrs.begin(); it != mAddrs.end(); it++) + { + if (it->sameAddress(addr)) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList() found duplicate"; + std::cerr << std::endl; +#endif + if (it->mSeenTime > addr.mSeenTime) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList() orig better, returning"; + std::cerr << std::endl; +#endif + /* already better -> quit */ + return false; + } + +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList() deleting orig"; + std::cerr << std::endl; +#endif + it = mAddrs.erase(it); + newAddr = false; + break; + } + } + + // ordered by decreaseing time. (newest at front) + bool added = false; + for(it = mAddrs.begin(); it != mAddrs.end(); it++) + { + if (it->mSeenTime < addr.mSeenTime) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList() added orig SeenTime: " << it->mSeenTime << " new SeenTime: " << addr.mSeenTime; + std::cerr << std::endl; +#endif + + added = true; + mAddrs.insert(it, addr); + break; + } + } + if (!added) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList() pushing to back"; + std::cerr << std::endl; +#endif + mAddrs.push_back(addr); + } + + /* pop if necessary */ + while (mAddrs.size() > MAX_ADDRESS_LIST_SIZE) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrList::updateIpAddressList() popping back"; + std::cerr << std::endl; +#endif + mAddrs.pop_back(); + } + + return newAddr; +} + +void pqiIpAddrList::extractFromTlv(const RsTlvIpAddrSet &tlvAddrs) +{ + std::list::const_iterator it; + + for(it = tlvAddrs.addrs.begin(); it != tlvAddrs.addrs.end() ; ++it) + { + pqiIpAddress addr; + addr.mAddr = it->addr; + addr.mSeenTime = it->seenTime; + addr.mSrc = it->source; + + mAddrs.push_back(addr); + } +} + +void pqiIpAddrList::loadTlv(RsTlvIpAddrSet &tlvAddrs) +{ + std::list::iterator it; + + for(it = mAddrs.begin(); it != mAddrs.end() ; ++it) + { + RsTlvIpAddressInfo addr; + addr.addr = it->mAddr; + addr.seenTime = it->mSeenTime; + addr.source = it->mSrc; + + tlvAddrs.addrs.push_back(addr); + } +} + + + +void pqiIpAddrList::printIpAddressList(std::ostream &out) const +{ + std::list::const_iterator it; + time_t now = time(NULL); + for(it = mAddrs.begin(); it != mAddrs.end(); it++) + { + out << rs_inet_ntoa(it->mAddr.sin_addr) << ":" + << ntohs(it->mAddr.sin_port) << " ( " + << now - it->mSeenTime << " old) " << std::endl; + + } + return; +} + + +bool pqiIpAddrSet::updateLocalAddrs(const pqiIpAddress &addr) +{ + return mLocal.updateIpAddressList(addr); +} + +bool pqiIpAddrSet::updateExtAddrs(const pqiIpAddress &addr) +{ + return mExt.updateIpAddressList(addr); +} + +bool pqiIpAddrSet::updateAddrs(const pqiIpAddrSet &addrs) +{ +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrSet::updateAddrs()"; + std::cerr << std::endl; +#endif + + bool newAddrs = false; + std::list::const_iterator it; + for(it = addrs.mLocal.mAddrs.begin(); it != addrs.mLocal.mAddrs.end(); it++) + { + if (mLocal.updateIpAddressList(*it)) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrSet::updateAddrs() Updated Local Addr"; + std::cerr << std::endl; +#endif + newAddrs = true; + } + } + + for(it = addrs.mExt.mAddrs.begin(); it != addrs.mExt.mAddrs.end(); it++) + { + if (mExt.updateIpAddressList(*it)) + { +#ifdef IPADDR_DEBUG + std::cerr << "pqiIpAddrSet::updateAddrs() Updated Ext Addr"; + std::cerr << std::endl; +#endif + newAddrs = true; + } + } + return newAddrs; +} + + + +void pqiIpAddrSet::printAddrs(std::ostream &out) const +{ + out << "Local Addresses: "; + mLocal.printIpAddressList(out); + out << std::endl; + out << "Ext Addresses: "; + mExt.printIpAddressList(out); + out << std::endl; +} + + + + diff --git a/libretroshare/src/pqi/pqiipset.h b/libretroshare/src/pqi/pqiipset.h new file mode 100644 index 000000000..54a50ea1f --- /dev/null +++ b/libretroshare/src/pqi/pqiipset.h @@ -0,0 +1,74 @@ +#ifndef PQI_IP_SET_H +#define PQI_IP_SET_H + +/* + * libretroshare/src/pqi: pqiipset.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "util/rsnet.h" +#include "serialiser/rstlvaddrs.h" + +#define MAX_ADDRESS_LIST_SIZE 4 + +class pqiIpAddress +{ + public: + bool sameAddress(const pqiIpAddress &a) const; + bool validAddress() const; + + struct sockaddr_in mAddr; + time_t mSeenTime; + uint32_t mSrc; +}; + + +class pqiIpAddrList +{ + public: + + // returns true if new address added. + bool updateIpAddressList(const pqiIpAddress &addr); + void printIpAddressList(std::ostream &out) const; + void extractFromTlv(const RsTlvIpAddrSet &tlvAddrs); + void loadTlv(RsTlvIpAddrSet &tlvAddrs); + + // sorted list... based on seen time. + std::list mAddrs; +}; + + +class pqiIpAddrSet +{ + public: + + bool updateLocalAddrs(const pqiIpAddress &addr); + bool updateExtAddrs(const pqiIpAddress &addr); + bool updateAddrs(const pqiIpAddrSet &addrs); + void printAddrs(std::ostream &out) const; + pqiIpAddrList mLocal; + pqiIpAddrList mExt; +}; + + +#endif diff --git a/libretroshare/src/pqi/pqilistener.h b/libretroshare/src/pqi/pqilistener.h new file mode 100644 index 000000000..0e0b980ee --- /dev/null +++ b/libretroshare/src/pqi/pqilistener.h @@ -0,0 +1,52 @@ +/* + * libretroshare/src/pqi: pqilistener.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_PQI_GENERIC_LISTEN_HEADER +#define MRK_PQI_GENERIC_LISTEN_HEADER + +// operating system specific network header. +#include "pqi/pqinetwork.h" + +class pqilistener +{ + public: + + pqilistener() { return; } +virtual ~pqilistener() { return; } + +virtual int tick() { return 1; } +virtual int status() { return 1; } +virtual int setListenAddr(struct sockaddr_in addr) + { + (void) addr; /* suppress unused parameter warning */ + return 1; + } +virtual int setuplisten() { return 1; } +virtual int resetlisten() { return 1; } + +}; + + +#endif // MRK_PQI_GENERIC_LISTEN_HEADER diff --git a/libretroshare/src/pqi/pqiloopback.cc b/libretroshare/src/pqi/pqiloopback.cc new file mode 100644 index 000000000..457548d33 --- /dev/null +++ b/libretroshare/src/pqi/pqiloopback.cc @@ -0,0 +1,90 @@ +/* + * libretroshare/src/pqi: pqiloopback.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqi.h" +#include "pqi/pqiloopback.h" + +/*** +#define LOOPBACK_DEBUG 1 +***/ + +pqiloopback::pqiloopback(std::string id) + :PQInterface(id) +{ + setMaxRate(true, 0); + setMaxRate(false, 0); + setRate(true, 0); + setRate(false, 0); + + return; +} + +pqiloopback::~pqiloopback() +{ + return; +} + +int pqiloopback::SendItem(RsItem *i) +{ + +#ifdef LOOPBACK_DEBUG + std::cerr << "pqiloopback::SendItem()"; + std::cerr << std::endl; + i->print(std::cerr); + std::cerr << std::endl; +#endif + objs.push_back(i); + return 1; +} + +RsItem * pqiloopback::GetItem() +{ + if (objs.size() > 0) + { + RsItem *pqi = objs.front(); + objs.pop_front(); +#ifdef LOOPBACK_DEBUG + std::cerr << "pqiloopback::GetItem()"; + std::cerr << std::endl; + pqi->print(std::cerr); + std::cerr << std::endl; +#endif + return pqi; + } + return NULL; +} + +// PQI interface. +int pqiloopback::tick() +{ + return 0; +} + +int pqiloopback::status() +{ + return 0; +} + + diff --git a/libretroshare/src/pqi/pqiloopback.h b/libretroshare/src/pqi/pqiloopback.h new file mode 100644 index 000000000..f79403609 --- /dev/null +++ b/libretroshare/src/pqi/pqiloopback.h @@ -0,0 +1,55 @@ +/* + * libretroshare/src/pqi: pqiloopback.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_PQI_LOOPBACK_HEADER +#define MRK_PQI_LOOPBACK_HEADER + +// The standard data types and the search interface. +#include "pqi/pqi.h" + +#include +#include +#include + +class pqiloopback: public PQInterface +{ +public: + pqiloopback(std::string id); +virtual ~pqiloopback(); + +// search Interface. +virtual int SendItem(RsItem *item); +virtual RsItem *GetItem(); + +// PQI interface. +virtual int tick(); +virtual int status(); + +virtual int notifyEvent(NetInterface *ni, int event) { return 0; } /* Not used */ + private: + std::list objs; +}; + +#endif //MRK_PQI_LOOPBACK_HEADER diff --git a/libretroshare/src/pqi/pqimonitor.cc b/libretroshare/src/pqi/pqimonitor.cc new file mode 100644 index 000000000..879a72871 --- /dev/null +++ b/libretroshare/src/pqi/pqimonitor.cc @@ -0,0 +1,87 @@ +/* + * libretroshare/src/pqi: pqimonitor.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqimonitor.h" +#include "pqi/pqinetwork.h" +#include "pqi/pqiipset.h" +#include "util/rsprint.h" + +/***** DUMMY Connect CB for testing *****/ + +#include + + +pqiConnectCbDummy::pqiConnectCbDummy() +{ + std::cerr << "pqiConnectCbDummy()" << std::endl; + return; +} + +pqiConnectCbDummy::~pqiConnectCbDummy() +{ + return; +} + +void pqiConnectCbDummy::peerStatus(std::string id, const pqiIpAddrSet &addrs, + uint32_t type, uint32_t mode, uint32_t source) +{ + std::cerr << "pqiConnectCbDummy::peerStatus()"; + std::cerr << " id: " << id; + std::cerr << " type: " << type; + std::cerr << " mode: " << mode; + std::cerr << " source: " << source; + std::cerr << std::endl; + + std::cerr << " addrs: "; + std::cerr << std::endl; + addrs.printAddrs(std::cerr); + std::cerr << std::endl; +} + +void pqiConnectCbDummy::peerConnectRequest(std::string id, + struct sockaddr_in raddr, uint32_t source) +{ + std::cerr << "pqiConnectCbDummy::peerConnectRequest()"; + std::cerr << " id: " << id; + std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr); + std::cerr << ":" << ntohs(raddr.sin_port); + std::cerr << " source: " << source; + std::cerr << std::endl; +} + +#if 0 +void pqiConnectCbDummy::stunStatus(std::string id, struct sockaddr_in raddr, + uint32_t type, uint32_t flags) +{ + std::cerr << "pqiConnectCbDummy::stunStatus()"; + std::cerr << " idhash: " << RsUtil::BinToHex(id) << " raddr: " << rs_inet_ntoa(raddr.sin_addr); + std::cerr << ":" << ntohs(raddr.sin_port); + std::cerr << " type: " << type; + std::cerr << " flags: " << flags; + std::cerr << std::endl; +} +#endif + + diff --git a/libretroshare/src/pqi/pqimonitor.h b/libretroshare/src/pqi/pqimonitor.h new file mode 100644 index 000000000..f82244f89 --- /dev/null +++ b/libretroshare/src/pqi/pqimonitor.h @@ -0,0 +1,173 @@ +/* + * libretroshare/src/pqi: pqimonitor.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef PQI_MONITOR_H +#define PQI_MONITOR_H + +/**** Rough sketch of a Monitor class + * expect it to change significantly + * + */ + +#include +#include +#include +#include "pqi/pqiipset.h" + +/************** Define Type/Mode/Source ***************/ + + +/* STATE MASK */ +const uint32_t RS_PEER_STATE_MASK = 0x00ff; +const uint32_t RS_PEER_ACTION_MASK = 0xff00; + +/* STATE */ +const uint32_t RS_PEER_S_FRIEND = 0x0001; +const uint32_t RS_PEER_S_ONLINE = 0x0002; /* heard from recently..*/ +const uint32_t RS_PEER_S_CONNECTED = 0x0004; +const uint32_t RS_PEER_S_UNREACHABLE = 0x0008; + +/* ACTIONS */ +const uint32_t RS_PEER_NEW = 0x0001; /* new Peer */ +const uint32_t RS_PEER_ONLINE = 0x0002; +const uint32_t RS_PEER_CONNECTED = 0x0004; +const uint32_t RS_PEER_MOVED = 0x0008; /* moved from F->O or O->F */ +const uint32_t RS_PEER_DISCONNECTED = 0x0010; +const uint32_t RS_PEER_CONNECT_REQ = 0x0020; + +/* Stun Status Flags */ +//const uint32_t RS_STUN_SRC_DHT = 0x0001; +//const uint32_t RS_STUN_SRC_PEER = 0x0002; +const uint32_t RS_STUN_ONLINE = 0x0010; +const uint32_t RS_STUN_FRIEND = 0x0020; +const uint32_t RS_STUN_FRIEND_OF_FRIEND = 0x0040; + + + +#define RS_CONNECT_PASSIVE 1 +#define RS_CONNECT_ACTIVE 2 + +#define RS_CB_DHT 1 /* from dht */ +#define RS_CB_DISC 2 /* from peers */ +#define RS_CB_PERSON 3 /* from connection */ +#define RS_CB_PROXY 4 /* via proxy */ + + +class pqipeer +{ + public: +std::string id; +std::string name; +uint32_t state; +uint32_t actions; +}; + +class p3ConnectMgr; + +/*! + * This class should be implemented + * to use the information that is passed to it via + * from the p3ConnectMngr + * Useful information is sent via ticks such as a peer's + * state and a peer's action + */ +class pqiMonitor +{ + public: + pqiMonitor() :mConnMgr(NULL) { return; } +virtual ~pqiMonitor() { return; } + + /*! + * passes a handle the retroshare connection manager + */ + void setConnectionMgr(p3ConnectMgr *cm) { mConnMgr = cm; } + + /*! + * this serves as a call back function for server which has + * a handle on the subclass and updates this subclass on the + * action of peer's of the client (state and action information) + * + *@param plist contains list of states and actions of the client's peers + */ +virtual void statusChange(const std::list &plist) = 0; + +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections +virtual void statusChanged() {}; +/////////////////////////////////////////////////////////// +#endif + +//virtual void ownStatusChange(pqipeer &) { return; } // SIGNAL reset or similar. +//virtual void peerStatus(std::string id, uint32_t mode) = 0; + + protected: + p3ConnectMgr *mConnMgr; +}; + + + + +class pqiConnectCb +{ + public: +virtual ~pqiConnectCb() { return; } +virtual void peerStatus(std::string id, const pqiIpAddrSet &addrs, + uint32_t type, uint32_t flags, uint32_t source) = 0; + +virtual void peerConnectRequest(std::string id, + struct sockaddr_in raddr, uint32_t source) = 0; + +//virtual void stunStatus(std::string id, struct sockaddr_in raddr, uint32_t type, uint32_t flags) = 0; +}; + + +/**** DUMMY CB FOR TESTING (just prints) ****/ +class pqiConnectCbDummy: public pqiConnectCb +{ + public: + pqiConnectCbDummy(); +virtual ~pqiConnectCbDummy(); +virtual void peerStatus(std::string id, const pqiIpAddrSet &addrs, + uint32_t type, uint32_t mode, uint32_t source); + +virtual void peerConnectRequest(std::string id, + struct sockaddr_in raddr, uint32_t source); + +//virtual void stunStatus(std::string id, struct sockaddr_in raddr, uint32_t type, uint32_t flags); +}; + + +/* network listener interface - used to reset network addresses */ +class pqiNetListener +{ + public: +virtual bool resetListener(struct sockaddr_in &local) = 0; + +}; + + +#endif // PQI_MONITOR_H + diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc new file mode 100644 index 000000000..1b004b08e --- /dev/null +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -0,0 +1,933 @@ +/* + * "$Id: pqinetwork.cc,v 1.18 2007-04-15 18:45:18 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +#include "pqi/pqinetwork.h" +#include "util/rsnet.h" + +#include +#include +#include + +#include "util/rsdebug.h" +#include +#include +static const int pqinetzone = 96184; + +/***** + * #define NET_DEBUG 1 + ****/ + +#ifdef WINDOWS_SYS /* Windows - define errno */ + +int errno; + +#else /* Windows - define errno */ + +#include + +#endif + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + +std::ostream &showSocketError(std::ostream &out) +{ + int err = errno; + out << "\tSocket Error(" << err << ") : "; + out << socket_errorType(err) << std::endl; + return out; +} + +std::string socket_errorType(int err) +{ + if (err == EBADF) + { + return std::string("EBADF"); + } + else if (err == EINVAL) + { + return std::string("EINVAL"); + } + else if (err == EFAULT) + { + return std::string("EFAULT"); + } + else if (err == ENOTSOCK) + { + return std::string("ENOTSOCK"); + } + else if (err == EISCONN) + { + return std::string("EISCONN"); + } + else if (err == ECONNREFUSED) + { + return std::string("ECONNREFUSED"); + } + else if (err == ETIMEDOUT) + { + return std::string("ETIMEDOUT"); + } + else if (err == ENETUNREACH) + { + return std::string("ENETUNREACH"); + } + else if (err == EADDRINUSE) + { + return std::string("EADDRINUSE"); + } + else if (err == EINPROGRESS) + { + return std::string("EINPROGRESS"); + } + else if (err == EALREADY) + { + return std::string("EALREADY"); + } + else if (err == EAGAIN) + { + return std::string("EAGAIN"); + } + else if (err == EISCONN) + { + return std::string("EISCONN"); + } + else if (err == ENOTCONN) + { + return std::string("ENOTCONN"); + } + + return std::string("UNKNOWN ERROR CODE"); +} + +#include +#include + +bool getLocalInterfaces(std::list &addrs) +{ + int sock = 0; + struct ifreq ifreq; + + struct if_nameindex *iflist = if_nameindex(); + struct if_nameindex *ifptr = iflist; + + //need a socket for ioctl() + if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + pqioutput(PQL_ALERT, pqinetzone, + "Cannot Determine Local Addresses!"); + return false; + } + + if (!ifptr) + { + pqioutput(PQL_ALERT, pqinetzone, + "getLocalInterfaces(): ERROR if_nameindex == NULL"); + return false; + } + + // loop through the interfaces. + for(; ifptr->if_index != 0; ifptr++) + { + //copy in the interface name to look up address of + strncpy(ifreq.ifr_name, ifptr->if_name, IF_NAMESIZE); + + if(ioctl(sock, SIOCGIFADDR, &ifreq) != 0) + { + std::ostringstream out; + out << "Cannot Determine Address for Iface: "; + out << ifptr -> if_name << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqinetzone, out.str()); + } + else + { + struct sockaddr_in *aptr = + (struct sockaddr_in *) &ifreq.ifr_addr; + std::string astr =rs_inet_ntoa(aptr -> sin_addr); + + std::ostringstream out; + out << "Iface: "; + out << ifptr -> if_name << std::endl; + out << " Address: " << astr; + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqinetzone, out.str()); + + // Now check wether the interface is up and running. If not, we don't use it!! + // + if(ioctl(sock,SIOCGIFFLAGS,&ifreq) != 0) + { + std::cerr << "Could not get flags from interface " << ifptr -> if_name << std::endl ; + continue ; + } +#ifdef NET_DEBUG + std::cout << out.str() ; + std::cout << "flags = " << ifreq.ifr_flags << std::endl ; +#endif + if((ifreq.ifr_flags & IFF_UP) == 0) continue ; + if((ifreq.ifr_flags & IFF_RUNNING) == 0) continue ; + + addrs.push_back(aptr->sin_addr); + } + } + // free socket -> or else run out of fds. + close(sock); + + if_freenameindex(iflist); + return (addrs.size() > 0); +} + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else + +std::ostream &showSocketError(std::ostream &out) +{ + int err = WSAGetLastError(); + out << "\tSocket Error(" << err << ") : "; + out << socket_errorType(err) << std::endl; + return out; +} + + +std::string socket_errorType(int err) +{ + if (err == WSAEBADF) + { + return std::string("WSABADF"); + } + + + else if (err == WSAEINTR) + { + return std::string("WSAEINTR"); + } + else if (err == WSAEACCES) + { + return std::string("WSAEACCES"); + } + else if (err == WSAEFAULT) + { + return std::string("WSAEFAULT"); + } + else if (err == WSAEINVAL) + { + return std::string("WSAEINVAL"); + } + else if (err == WSAEMFILE) + { + return std::string("WSAEMFILE"); + } + else if (err == WSAEWOULDBLOCK) + { + return std::string("WSAEWOULDBLOCK"); + } + else if (err == WSAEINPROGRESS) + { + return std::string("WSAEINPROGRESS"); + } + else if (err == WSAEALREADY) + { + return std::string("WSAEALREADY"); + } + else if (err == WSAENOTSOCK) + { + return std::string("WSAENOTSOCK"); + } + else if (err == WSAEDESTADDRREQ) + { + return std::string("WSAEDESTADDRREQ"); + } + else if (err == WSAEMSGSIZE) + { + return std::string("WSAEMSGSIZE"); + } + else if (err == WSAEPROTOTYPE) + { + return std::string("WSAEPROTOTYPE"); + } + else if (err == WSAENOPROTOOPT) + { + return std::string("WSAENOPROTOOPT"); + } + else if (err == WSAENOTSOCK) + { + return std::string("WSAENOTSOCK"); + } + else if (err == WSAEISCONN) + { + return std::string("WSAISCONN"); + } + else if (err == WSAECONNREFUSED) + { + return std::string("WSACONNREFUSED"); + } + else if (err == WSAECONNRESET) + { + return std::string("WSACONNRESET"); + } + else if (err == WSAETIMEDOUT) + { + return std::string("WSATIMEDOUT"); + } + else if (err == WSAENETUNREACH) + { + return std::string("WSANETUNREACH"); + } + else if (err == WSAEADDRINUSE) + { + return std::string("WSAADDRINUSE"); + } + else if (err == WSAEAFNOSUPPORT) + { + return std::string("WSAEAFNOSUPPORT (normally UDP related!)"); + } + + return std::string("----WINDOWS OPERATING SYSTEM FAILURE----"); +} + +#include +//#include + +// A function to determine the interfaces on your computer.... +// No idea of how to do this in windows.... +// see if it compiles. +bool getLocalInterfaces(std::list &addrs) +{ + + /* USE MIB IPADDR Interface */ + PMIB_IPADDRTABLE iptable = NULL; + DWORD dwSize = 0; + + if (GetIpAddrTable(iptable, &dwSize, 0) != + ERROR_INSUFFICIENT_BUFFER) + { + pqioutput(PQL_ALERT, pqinetzone, + "Cannot Find Windoze Interfaces!"); + exit(0); + } + + iptable = (MIB_IPADDRTABLE *) malloc(dwSize); + GetIpAddrTable(iptable, &dwSize, 0); + + struct in_addr addr; + + for(unsigned int i = 0; i < iptable -> dwNumEntries; i++) + { + std::ostringstream out; + + out << "Iface(" << iptable->table[i].dwIndex << ") "; + addr.s_addr = iptable->table[i].dwAddr; + out << " => " << rs_inet_ntoa(addr); + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqinetzone, out.str()); + + addrs.push_back(addr); + } + + free (iptable); + + return (addrs.size() > 0); +} + +// implement the improved unix inet address fn. +// using old one. +int inet_aton(const char *name, struct in_addr *addr) +{ + return (((*addr).s_addr = inet_addr(name)) != INADDR_NONE); +} + + +// This returns in Net Byte Order. +// NB: Linux man page claims it is in Host Byte order, but +// this is blatantly wrong!..... (for Debian anyway) +// Making this consistent with the Actual behavior (rather than documented). +in_addr_t inet_netof(struct in_addr addr) +{ + return pqi_inet_netof(addr); +} + +// This returns in Host Byte Order. (as the man page says) +// Again, to be consistent with Linux. +in_addr_t inet_network(const char *inet_name) +{ + struct in_addr addr; + if (inet_aton(inet_name, &addr)) + { +#ifdef NET_DEBUG +// std::cerr << "inet_network(" << inet_name << ") : "; +// std::cerr << rs_inet_ntoa(addr) << std::endl; +#endif + return ntohl(inet_netof(addr)); + } + return 0xffffffff; + //return -1; +} + + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + +#include + + +// This returns in Net Byte Order. +// NB: Linux man page claims it is in Host Byte order, but +// this is blatantly wrong!..... (for Debian anyway) +// Making this consistent with the Actual behavior (rather than documented). +in_addr_t pqi_inet_netof(struct in_addr addr) +{ + // decide if A class address. + unsigned long haddr = ntohl(addr.s_addr); + unsigned long abit = haddr & 0xff000000UL; + unsigned long bbit = haddr & 0xffff0000UL; + unsigned long cbit = haddr & 0xffffff00UL; + +#ifdef NET_DEBUG + std::cerr << "inet_netof(" << rs_inet_ntoa(addr) << ") "; +#endif + + if (!((haddr >> 31) | 0x0UL)) // MSB = 0 + { +#ifdef NET_DEBUG + std::cerr << " Type A " << std::endl; + std::cerr << "\tShifted(31): " << (haddr >> 31); + std::cerr << " Xord(0x0UL): " << + !((haddr >> 31) | 0x0UL) << std::endl; +#endif + + return htonl(abit); + } + else if (!((haddr >> 30) ^ 0x2UL)) // 2MSBs = 10 + { +#ifdef NET_DEBUG + std::cerr << " Type B " << std::endl; + std::cerr << "\tShifted(30): " << (haddr >> 30); + std::cerr << " Xord(0x2UL): " << + !((haddr >> 30) | 0x2UL) << std::endl; +#endif + + return htonl(bbit); + } + else if (!((haddr >> 29) ^ 0x6UL)) // 3MSBs = 110 + { +#ifdef NET_DEBUG + std::cerr << " Type C " << std::endl; + std::cerr << "\tShifted(29): " << (haddr >> 29); + std::cerr << " Xord(0x6UL): " << + !((haddr >> 29) | 0x6UL) << std::endl; +#endif + + return htonl(cbit); + } + else if (!((haddr >> 28) ^ 0xeUL)) // 4MSBs = 1110 + { +#ifdef NET_DEBUG + std::cerr << " Type Multicast " << std::endl; + std::cerr << "\tShifted(28): " << (haddr >> 28); + std::cerr << " Xord(0xeUL): " << + !((haddr >> 29) | 0xeUL) << std::endl; +#endif + + return addr.s_addr; // return full address. + } + else if (!((haddr >> 27) ^ 0x1eUL)) // 5MSBs = 11110 + { +#ifdef NET_DEBUG + std::cerr << " Type Reserved " << std::endl; + std::cerr << "\tShifted(27): " << (haddr >> 27); + std::cerr << " Xord(0x1eUL): " << + !((haddr >> 27) | 0x1eUL) << std::endl; +#endif + + return addr.s_addr; // return full address. + } + return htonl(abit); +} + +int sockaddr_cmp(struct sockaddr_in &addr1, struct sockaddr_in &addr2 ) +{ + if (addr1.sin_family != addr2.sin_family) + return addr1.sin_family - addr2.sin_family; + if (addr1.sin_addr.s_addr != addr2.sin_addr.s_addr) + return (addr1.sin_addr.s_addr - addr2.sin_addr.s_addr); + if (addr1.sin_port != addr2.sin_port) + return (addr1.sin_port - addr2.sin_port); + return 0; +} + +int inaddr_cmp(struct sockaddr_in addr1, struct sockaddr_in addr2 ) +{ +#ifdef NET_DEBUG + std::ostringstream out; + out << "inaddr_cmp(" << rs_inet_ntoa(addr1.sin_addr); + out << "-" << addr1.sin_addr.s_addr; + out << "," << rs_inet_ntoa(addr2.sin_addr); + out << "-" << addr2.sin_addr.s_addr << ")" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqinetzone, out.str()); +#endif + + + if (addr1.sin_addr.s_addr == addr2.sin_addr.s_addr) + { + return 0; + } + if (addr1.sin_addr.s_addr < addr2.sin_addr.s_addr) + return -1; + return 1; +} + +int inaddr_cmp(struct sockaddr_in addr1, unsigned long addr2) +{ +#ifdef NET_DEBUG + struct in_addr inaddr_tmp; + inaddr_tmp.s_addr = addr2; + + std::ostringstream out; + out << "inaddr_cmp2(" << rs_inet_ntoa(addr1.sin_addr); + out << " vs " << rs_inet_ntoa(inaddr_tmp); + out << " /or/ "; + out << std::hex << std::setw(10) << addr1.sin_addr.s_addr; + out << " vs " << std::setw(10) << addr2 << ")" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqinetzone, out.str()); +#endif + + if (addr1.sin_addr.s_addr == addr2) + { + return 0; + } + if (addr1.sin_addr.s_addr < addr2) + return -1; + return 1; +} + + +bool getPreferredInterface(struct in_addr &prefAddr) // returns best addr. +{ + std::list addrs; + std::list::iterator it; + struct in_addr addr_zero, addr_loop, addr_priv, addr_ext; + +#ifdef NET_DEBUG + struct in_addr addr; +#endif + + bool found_zero = false; + bool found_loopback = false; + bool found_priv = false; + bool found_ext = false; + + if (!getLocalInterfaces(addrs)) + { + return false; + } + + memset(&addr_zero, 0, sizeof(addr_zero)); + memset(&addr_loop, 0, sizeof(addr_loop)); + memset(&addr_priv, 0, sizeof(addr_priv)); + memset(&addr_ext, 0, sizeof(addr_ext)); + +#ifdef NET_DEBUG + memset(&addr, 0, sizeof(addr)); +#endif + + // find the first of each of these. + // if ext - take first. + // if no ext -> first priv + // if no priv -> first loopback. + +#ifdef NET_DEBUG + std::cerr << "getPreferredInterface() " << addrs.size() << " interfaces." << std::endl; +#endif + + for(it = addrs.begin(); it != addrs.end(); it++) + { + struct in_addr addr = *it; + +#ifdef NET_DEBUG + std::cerr << "Examining addr: " << rs_inet_ntoa(addr); + std::cerr << " => " << (uint32_t) addr.s_addr << std::endl ; +#endif + + // for windows silliness (returning 0.0.0.0 as valid addr!). + if (addr.s_addr == 0) + { + if (!found_zero) + { +#ifdef NET_DEBUG + std::cerr << "\tFound Zero Address" << std::endl ; +#endif + + found_zero = true; + addr_zero = addr; + } + } + else if (isLoopbackNet(&addr)) + { + if (!found_loopback) + { +#ifdef NET_DEBUG + std::cerr << "\tFound Loopback Address" << std::endl ; +#endif + + found_loopback = true; + addr_loop = addr; + } + } + else if (isPrivateNet(&addr)) + { + if (!found_priv) + { +#ifdef NET_DEBUG + std::cerr << "\tFound Private Address" << std::endl ; +#endif + + found_priv = true; + addr_priv = addr; + } + } + else + { + if (!found_ext) + { +#ifdef NET_DEBUG + std::cerr << "\tFound Other Address (Ext?) " << std::endl ; +#endif + found_ext = true; + addr_ext = addr; + } + } + } + + if(found_ext) // external address is best. + { + prefAddr = addr_ext; + return true; + } + + if (found_priv) + { + prefAddr = addr_priv; + return true; + } + + // next bit can happen under windows, + // a general address is still + // preferable to a loopback device. + if (found_zero) + { + prefAddr = addr_zero; + return true; + } + + if (found_loopback) + { + prefAddr = addr_loop; + return true; + } + + // shound be 255.255.255.255 (error). + prefAddr.s_addr = 0xffffffff; + return false; +} + +bool sameNet(struct in_addr *addr, struct in_addr *addr2) +{ +#ifdef NET_DEBUG + std::cerr << "sameNet: " << rs_inet_ntoa(*addr); + std::cerr << " VS " << rs_inet_ntoa(*addr2); + std::cerr << std::endl; +#endif + struct in_addr addrnet, addrnet2; + + addrnet.s_addr = inet_netof(*addr); + addrnet2.s_addr = inet_netof(*addr2); + +#ifdef NET_DEBUG + std::cerr << " (" << rs_inet_ntoa(addrnet); + std::cerr << " =?= " << rs_inet_ntoa(addrnet2); + std::cerr << ")" << std::endl; +#endif + + in_addr_t address1 = htonl(addr->s_addr); + in_addr_t address2 = htonl(addr2->s_addr); + + // handle case for private net: 172.16.0.0/12 + if (address1>>20 == (172<<4 | 16>>4)) + { + return (address1>>20 == address2>>20); + } + + return (inet_netof(*addr) == inet_netof(*addr2)); +} + + +bool isSameSubnet(struct in_addr *addr1, struct in_addr *addr2) +{ + /* + * check that the (addr1 & 255.255.255.0) == (addr2 & 255.255.255.0) + */ + + unsigned long a1 = ntohl(addr1->s_addr); + unsigned long a2 = ntohl(addr2->s_addr); + + return ((a1 & 0xffffff00) == (a2 & 0xffffff00)); +} + +/* This just might be portable!!! will see!!! + * Unfortunately this is usable on winXP+, determined by: (_WIN32_WINNT >= 0x0501) + * but not older platforms.... which must use gethostbyname. + * + * include it for now..... + */ + +bool LookupDNSAddr(std::string name, struct sockaddr_in &addr) +{ + +#if 1 + char service[100]; + struct addrinfo hints_st; + struct addrinfo *hints = &hints_st; + struct addrinfo *res; + + hints -> ai_flags = 0; // (cygwin don;t like these) AI_ADDRCONFIG | AI_NUMERICSERV; + hints -> ai_family = AF_INET; + hints -> ai_socktype = 0; + hints -> ai_protocol = 0; + hints -> ai_addrlen = 0; + hints -> ai_addr = NULL; + hints -> ai_canonname = NULL; + hints -> ai_next = NULL; + + /* get the port number */ + sprintf(service, "%d", ntohs(addr.sin_port)); + + /* set it to IPV4 */ +#ifdef NET_DEBUG + std::cerr << "LookupDNSAddr() name: " << name << " service: " << service << std::endl; +#endif + + int err = 0; + if (0 != (err = getaddrinfo(name.c_str(), service, hints, &res))) + { +#ifdef NET_DEBUG + std::cerr << "LookupDNSAddr() getaddrinfo failed!" << std::endl; + std::cerr << "Error: " << gai_strerror(err) << std::endl; +#endif + return false; + } + + if ((res) && (res->ai_family == AF_INET)) + { + addr = *((struct sockaddr_in *) res->ai_addr); + freeaddrinfo(res); + +#ifdef NET_DEBUG + std::cerr << "LookupDNSAddr() getaddrinfo found address" << std::endl; + std::cerr << "addr: " << rs_inet_ntoa(addr.sin_addr) << std::endl; + std::cerr << "port: " << ntohs(addr.sin_port) << std::endl; +#endif + return true; + } + +#ifdef NET_DEBUG + std::cerr << "getaddrinfo failed - no address" << std::endl; +#endif + +#endif +#ifdef NET_DEBUG + //std::cerr << "getaddrinfo disabled" << std::endl; +#endif + return false; +} + +/************************************************************* + * Socket Library Wrapper Functions + * to get over the crapness of the windows. + * + */ + +int unix_close(int fd) +{ + int ret; +/******************* WINDOWS SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + ret = close(fd); +#else + +#ifdef NET_DEBUG + std::cerr << "unix_close()" << std::endl; +#endif + ret = closesocket(fd); + /* translate error */ +#endif +/******************* WINDOWS SPECIFIC PART ******************/ + return ret; +} + +int unix_socket(int domain, int type, int protocol) +{ + int osock = socket(PF_INET, SOCK_STREAM, 0); + +/******************* WINDOWS SPECIFIC PART ******************/ +#ifdef WINDOWS_SYS // WINDOWS + +#ifdef NET_DEBUG + std::cerr << "unix_socket()" << std::endl; +#endif + + if ((unsigned) osock == INVALID_SOCKET) + { + // Invalidate socket Unix style. + osock = -1; + errno = WinToUnixError(WSAGetLastError()); + } +#endif +/******************* WINDOWS SPECIFIC PART ******************/ + return osock; +} + + +int unix_fcntl_nonblock(int fd) +{ + int ret; + +/******************* WINDOWS SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + ret = fcntl(fd, F_SETFL, O_NONBLOCK); + +#ifdef NET_DEBUG + std::cerr << "unix_fcntl_nonblock():" << ret << " errno:" << errno << std::endl; +#endif + +#else + unsigned long int on = 1; + ret = ioctlsocket(fd, FIONBIO, &on); + +#ifdef NET_DEBUG + std::cerr << "unix_fcntl_nonblock()" << std::endl; +#endif + if (ret != 0) + { + /* store unix-style error + */ + ret = -1; + errno = WinToUnixError(WSAGetLastError()); + } +#endif +/******************* WINDOWS SPECIFIC PART ******************/ + return ret; +} + + +int unix_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + int ret = connect(fd, serv_addr, addrlen); + +/******************* WINDOWS SPECIFIC PART ******************/ +#ifdef WINDOWS_SYS // WINDOWS + +#ifdef NET_DEBUG + std::cerr << "unix_connect()" << std::endl; +#endif + if (ret != 0) + { + errno = WinToUnixError(WSAGetLastError()); + ret = -1; + } +#endif +/******************* WINDOWS SPECIFIC PART ******************/ + return ret; +} + + +int unix_getsockopt_error(int sockfd, int *err) +{ + int ret; + *err = 1; +/******************* WINDOWS SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + socklen_t optlen = 4; + ret=getsockopt(sockfd, SOL_SOCKET, SO_ERROR, err, &optlen); +#else // WINDOWS_SYS + int optlen = 4; + ret=getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *) err, &optlen); + /* translate */ +#ifdef NET_DEBUG + std::cerr << "unix_getsockopt_error() returned: " << (int) err << std::endl; +#endif + if (*err != 0) + { + *err = WinToUnixError(*err); + } +#endif +/******************* WINDOWS SPECIFIC PART ******************/ + return ret; +} + +/******************* WINDOWS SPECIFIC PART ******************/ +#ifdef WINDOWS_SYS // ie WINDOWS. + +int WinToUnixError(int error) +{ +#ifdef NET_DEBUG + std::cerr << "WinToUnixError(" << error << ")" << std::endl; +#endif + switch(error) + { + case WSAEINPROGRESS: + return EINPROGRESS; + break; + case WSAEWOULDBLOCK: + return EINPROGRESS; + break; + case WSAENETUNREACH: + return ENETUNREACH; + break; + case WSAETIMEDOUT: + return ETIMEDOUT; + break; + case WSAEHOSTDOWN: + return EHOSTDOWN; + break; + case WSAECONNREFUSED: + return ECONNREFUSED; + break; + case WSAECONNRESET: + return ECONNRESET; + break; + default: +#ifdef NET_DEBUG + std::cerr << "WinToUnixError(" << error << ") Code Unknown!"; + std::cerr << std::endl; +#endif + break; + } + return ECONNREFUSED; /* sensible default? */ +} + +#endif +/******************* WINDOWS SPECIFIC PART ******************/ diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h new file mode 100644 index 000000000..fb2f8596b --- /dev/null +++ b/libretroshare/src/pqi/pqinetwork.h @@ -0,0 +1,133 @@ +/* + * "$Id: pqinetwork.h,v 1.15 2007-04-15 18:45:18 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_NETWORKING_HEADER +#define MRK_PQI_NETWORKING_HEADER + + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + +#include +#include +#include +#include + +#include + +//socket blocking/options. +#include +#include + +#else + +#include "util/rswin.h" + +#include "util/rsnet.h" /* more generic networking header */ + +#include +#include +typedef int socklen_t; +//typedef unsigned long in_addr_t; + +// Some Network functions that are missing from windows. + +in_addr_t inet_netof(struct in_addr addr); +in_addr_t inet_network(const char *inet_name); +int inet_aton(const char *name, struct in_addr *addr); + +extern int errno; /* Define extern errno, to duplicate unix behaviour */ + +/* define the Unix Error Codes that we use... + * NB. we should make the same, but not necessary + */ +#define EAGAIN 11 +#define EWOULDBLOCK EAGAIN + +#define EUSERS 87 +#define ENOTSOCK 88 + +#define EOPNOTSUPP 95 + +#define EADDRINUSE 98 +#define EADDRNOTAVAIL 99 +#define ENETDOWN 100 +#define ENETUNREACH 101 + +#define ECONNRESET 104 + +#define ETIMEDOUT 10060 // value from pthread.h +#define ECONNREFUSED 111 +#define EHOSTDOWN 112 +#define EHOSTUNREACH 113 +#define EALREADY 114 +#define EINPROGRESS 115 + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + +#include +#include +#include + +// Same def - different functions... + +std::ostream &showSocketError(std::ostream &out); + +std::string socket_errorType(int err); +int sockaddr_cmp(struct sockaddr_in &addr1, struct sockaddr_in &addr2 ); +int inaddr_cmp(struct sockaddr_in addr1, struct sockaddr_in addr2 ); +int inaddr_cmp(struct sockaddr_in addr1, unsigned long); + +bool getPreferredInterface(struct in_addr &prefAddr); // returns best addr. +bool getLocalInterfaces(std::list &addrs); // returns all possible addrs. + + // checks (addr1 & 255.255.255.0) == (addr2 & 255.255.255.0) +bool isSameSubnet(struct in_addr *addr1, struct in_addr *addr2); +bool sameNet(struct in_addr *addr, struct in_addr *addr2); + +in_addr_t pqi_inet_netof(struct in_addr addr); // our implementation. + +bool LookupDNSAddr(std::string name, struct sockaddr_in &addr); + +/* universal socket interface */ + +int unix_close(int sockfd); +int unix_socket(int domain, int type, int protocol); +int unix_fcntl_nonblock(int sockfd); +int unix_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); +int unix_getsockopt_error(int sockfd, int *err); + +#ifdef WINDOWS_SYS // WINDOWS +/******************* WINDOWS SPECIFIC PART ******************/ +int WinToUnixError(int error); +#endif + + + +#endif + diff --git a/libretroshare/src/pqi/pqinotify.h b/libretroshare/src/pqi/pqinotify.h new file mode 100644 index 000000000..12db382c7 --- /dev/null +++ b/libretroshare/src/pqi/pqinotify.h @@ -0,0 +1,52 @@ +#ifndef PQI_NOTIFY_INTERFACE_H +#define PQI_NOTIFY_INTERFACE_H + +/* + * libretroshare/src/rsserver: pqinotify.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rsnotify.h" /* for ids */ + + /* Interface for System Notification: Implemented in rsserver */ + /* Global Access -> so we don't need everyone to have a pointer to this! */ + + +class pqiNotify +{ + public: + + pqiNotify() { return; } +virtual ~pqiNotify() { return; } + + /* Input from libretroshare */ +virtual bool AddPopupMessage(uint32_t ptype, const std::string& name, const std::string& title, const std::string& msg) = 0; +virtual bool AddSysMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg) = 0; +virtual bool AddLogMessage(uint32_t sysid, uint32_t type, const std::string& title, const std::string& msg) = 0; +virtual bool AddFeedItem(uint32_t type, const std::string& id1, const std::string& id2, const std::string& id3) = 0; +virtual bool ClearFeedItems(uint32_t type) = 0; +}; + +extern pqiNotify *getPqiNotify(); + +#endif diff --git a/libretroshare/src/pqi/pqiperson.cc b/libretroshare/src/pqi/pqiperson.cc new file mode 100644 index 000000000..4d9ce7a24 --- /dev/null +++ b/libretroshare/src/pqi/pqiperson.cc @@ -0,0 +1,473 @@ +/* + * libretroshare/src/pqi pqiperson.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqi.h" +#include "pqi/pqiperson.h" +#include "pqi/pqipersongrp.h" +#include "services/p3disc.h" + +const int pqipersonzone = 82371; +#include "util/rsdebug.h" +#include + +/**** + * #define PERSON_DEBUG + ****/ + +pqiperson::pqiperson(std::string id, pqipersongrp *pg) + :PQInterface(id), active(false), activepqi(NULL), + inConnectAttempt(false), waittimes(0), + pqipg(pg) +{ + + /* must check id! */ + + return; +} + +pqiperson::~pqiperson() +{ + // clean up the children. + std::map::iterator it; + for(it = kids.begin(); it != kids.end(); it++) + { + pqiconnect *pc = (it->second); + delete pc; + } + kids.clear(); +} + + + // The PQInterface interface. +int pqiperson::SendItem(RsItem *i) +{ + std::ostringstream out; + out << "pqiperson::SendItem()"; + if (active) + { + out << " Active: Sending On" << std::endl; + i->print(out, 5); +#ifdef PERSON_DEBUG + std::cerr << out.str() << std::endl; +#endif + return activepqi -> SendItem(i); + } + else + { + out << " Not Active: Used to put in ToGo Store"; + out << std::endl; + out << " Now deleting..."; + delete i; + } + pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + return 0; // queued. +} + +RsItem *pqiperson::GetItem() +{ + if (active) + return activepqi -> GetItem(); + // else not possible. + return NULL; +} + +int pqiperson::status() +{ + if (active) + return activepqi -> status(); + return -1; +} + +int pqiperson::receiveHeartbeat() +{ + pqioutput(PQL_DEBUG_ALERT, pqipersonzone, "pqiperson::receiveHeartbeat() from peer : " + PeerId()); + lastHeartbeatReceived = time(NULL); + + return true ; +} + + // tick...... +int pqiperson::tick() +{ + //if lastHeartbeatReceived is 0, it might be not activated so don't do a net reset. + if (active && + lastHeartbeatReceived != 0 && + (time(NULL) - lastHeartbeatReceived) > HEARTBEAT_REPEAT_TIME * 5) { + pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::tick() No heartbeat from the peer, assume connection is dead."); + this->reset(); + } + + int activeTick = 0; + + { + std::ostringstream out; + out << "pqiperson::tick() Id: " << PeerId() << " "; + if (active) + out << "***Active***"; + else + out << ">>InActive<<"; + + out << std::endl; + out << "Activepqi: " << activepqi << " inConnectAttempt: "; + + if (inConnectAttempt) + out << "In Connection Attempt"; + else + out << " Not Connecting "; + out << std::endl; + + + // tick the children. + std::map::iterator it; + for(it = kids.begin(); it != kids.end(); it++) + { + if (0 < (it->second) -> tick()) + { + activeTick = 1; + } + out << "\tTicking Child: " << (it->first) << std::endl; + } + + pqioutput(PQL_DEBUG_ALL, pqipersonzone, out.str()); + } // end of pqioutput. + + return activeTick; +} + +// callback function for the child - notify of a change. +// This is only used for out-of-band info.... +// otherwise could get dangerous loops. +int pqiperson::notifyEvent(NetInterface *ni, int newState) +{ + { + std::ostringstream out; + out << "pqiperson::notifyEvent() Id: " << PeerId(); + out << std::endl; + out << "Message: " << newState << " from: " << ni << std::endl; + out << "Active pqi : " << activepqi; + + pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + } + + /* find the pqi, */ + pqiconnect *pqi = NULL; + uint32_t type = 0; + std::map::iterator it; + + /* start again */ + int i = 0; + for(it = kids.begin(); it != kids.end(); it++) + { + std::ostringstream out; + out << "pqiperson::connectattempt() Kid# "; + out << i << " of " << kids.size(); + out << std::endl; + out << " type: " << (it->first); + out << " ni: " << (it->second)->ni; + out << " in_ni: " << ni; + pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + i++; + + if ((it->second)->thisNetInterface(ni)) + { + pqi = (it->second); + type = (it->first); + } + } + + if (!pqi) + { + pqioutput(PQL_WARNING, pqipersonzone, "Unknown notfyEvent Source!"); + return -1; + } + + + switch(newState) + { + case CONNECT_RECEIVED: + case CONNECT_SUCCESS: + + /* notify */ + if (pqipg) { + struct sockaddr_in remote_peer_address; + pqi->getConnectAddress(remote_peer_address); + pqipg->notifyConnect(PeerId(), type, true, remote_peer_address); + } + + if ((active) && (activepqi != pqi)) // already connected - trouble + { + pqioutput(PQL_WARNING, pqipersonzone, + "CONNECT_SUCCESS+active-> activing new connection, shutting others"); + + // This is the RESET that's killing the connections..... + //activepqi -> reset(); + // this causes a recursive call back into this fn. + // which cleans up state. + // we only do this if its not going to mess with new conn. + } + + /* now install a new one. */ + { + + pqioutput(PQL_WARNING, pqipersonzone, + "CONNECT_SUCCESS->marking so! (resetting others)"); + // mark as active. + active = true; + lastHeartbeatReceived = 0; + activepqi = pqi; + inConnectAttempt = false; + + /* reset all other children? (clear up long UDP attempt) */ + for(it = kids.begin(); it != kids.end(); it++) + { + if (!(it->second)->thisNetInterface(ni)) + { + std::ostringstream out; + out << "Resetting pqi ref : " << &(it->second) << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + it->second->reset(); + } else { + //std::cerr << "Active pqi : not resetting." << std::endl; + } + } + return 1; + } + break; + case CONNECT_UNREACHABLE: + case CONNECT_FIREWALLED: + case CONNECT_FAILED: + + + if (active) + { + if (activepqi == pqi) + { + pqioutput(PQL_WARNING, pqipersonzone, + "CONNECT_FAILED->marking so!"); + active = false; + activepqi = NULL; + } else { + pqioutput(PQL_WARNING, pqipersonzone, + "CONNECT_FAILED-> from an unactive connection, don't flag the peer as not connected, just try next attempt !"); + } + } + else + { + pqioutput(PQL_WARNING, pqipersonzone, + "CONNECT_FAILED+NOT active -> try connect again"); + } + + /* notify up (But not if we are actually active: rtn -1 case above) */ + if (pqipg) + { + struct sockaddr_in raddr; + sockaddr_clear(&raddr); + pqipg->notifyConnect(PeerId(), type, false, raddr); + } + + return 1; + + break; + default: + break; + } + return -1; +} + +/***************** Not PQInterface Fns ***********************/ + +int pqiperson::reset() +{ + { + std::ostringstream out; + out << "pqiperson::reset() Id: " << PeerId(); + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + } + + std::map::iterator it; + for(it = kids.begin(); it != kids.end(); it++) + { + (it->second) -> reset(); + } + + activepqi = NULL; + active = false; + lastHeartbeatReceived = 0; + + return 1; +} + +int pqiperson::addChildInterface(uint32_t type, pqiconnect *pqi) +{ + { + std::ostringstream out; + out << "pqiperson::addChildInterface() : Id " << PeerId() << " " << type; + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + } + + kids[type] = pqi; + return 1; +} + +/***************** PRIVATE FUNCTIONS ***********************/ +// functions to iterate over the connects and change state. + + +int pqiperson::listen() +{ + { + std::ostringstream out; + out << "pqiperson::listen() Id: " << PeerId(); + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + } + + if (!active) + { + std::map::iterator it; + for(it = kids.begin(); it != kids.end(); it++) + { + // set them all listening. + (it->second) -> listen(); + } + } + return 1; +} + + +int pqiperson::stoplistening() +{ + { + std::ostringstream out; + out << "pqiperson::stoplistening() Id: " << PeerId(); + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + } + + std::map::iterator it; + for(it = kids.begin(); it != kids.end(); it++) + { + // set them all listening. + (it->second) -> stoplistening(); + } + return 1; +} + +int pqiperson::connect(uint32_t type, struct sockaddr_in raddr, uint32_t delay, uint32_t period, uint32_t timeout) +{ +#ifdef PERSON_DEBUG + { + std::ostringstream out; + out << "pqiperson::connect() Id: " << PeerId(); + out << " type: " << type; + out << " addr: " << rs_inet_ntoa(raddr.sin_addr); + out << ":" << ntohs(raddr.sin_port); + out << " delay: " << delay; + out << " period: " << period; + out << " timeout: " << timeout; + out << std::endl; + std::cerr << out.str(); + //pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); + } +#endif + + std::map::iterator it; + + it = kids.find(type); + if (it == kids.end()) + { +#ifdef PERSON_DEBUG + std::ostringstream out; + out << "pqiperson::connect()"; + out << " missing pqiconnect"; + out << std::endl; + std::cerr << out.str(); + //pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out.str()); +#endif + /* notify of fail! */ + + pqipg->notifyConnect(PeerId(), type, false, raddr); + + return 0; + } + + /* set the parameters */ + (it->second)->reset(); + +#ifdef PERSON_DEBUG + std::cerr << "pqiperson::connect() setting connect_parameters" << std::endl; +#endif + (it->second)->connect_parameter(NET_PARAM_CONNECT_DELAY, delay); + (it->second)->connect_parameter(NET_PARAM_CONNECT_PERIOD, period); + (it->second)->connect_parameter(NET_PARAM_CONNECT_TIMEOUT, timeout); + + (it->second)->connect(raddr); + + // flag if we started a new connectionAttempt. + inConnectAttempt = true; + + return 1; +} + + +pqiconnect *pqiperson::getKid(uint32_t type) +{ + std::map::iterator it; + + if (kids.empty()) { + return NULL; + } + + it = kids.find(type); + if (it == kids.end()) + { + return NULL; + } else { + return it->second; + } +} + +float pqiperson::getRate(bool in) +{ + // get the rate from the active one. + if ((!active) || (activepqi == NULL)) + return 0; + return activepqi -> getRate(in); +} + +void pqiperson::setMaxRate(bool in, float val) +{ + // set to all of them. (and us) + PQInterface::setMaxRate(in, val); + // clean up the children. + std::map::iterator it; + for(it = kids.begin(); it != kids.end(); it++) + { + (it->second) -> setMaxRate(in, val); + } +} + diff --git a/libretroshare/src/pqi/pqiperson.h b/libretroshare/src/pqi/pqiperson.h new file mode 100644 index 000000000..3e6478c33 --- /dev/null +++ b/libretroshare/src/pqi/pqiperson.h @@ -0,0 +1,148 @@ +/* + * libretroshare/src/pqi pqiperson.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_PERSON_HEADER +#define MRK_PQI_PERSON_HEADER + + +#include "pqi/pqi.h" + +#include + +class pqiperson; + +static const int CONNECT_RECEIVED = 1; +static const int CONNECT_SUCCESS = 2; +static const int CONNECT_UNREACHABLE = 3; +static const int CONNECT_FIREWALLED = 4; +static const int CONNECT_FAILED = 5; + +static const int HEARTBEAT_REPEAT_TIME = 5; + +#include "pqi/pqistreamer.h" + +class pqiconnect: public pqistreamer, public NetInterface +{ +public: + pqiconnect(RsSerialiser *rss, NetBinInterface *ni_in) + :pqistreamer(rss, ni_in->PeerId(), ni_in, 0), // pqistreamer will cleanup NetInterface. + NetInterface(NULL, ni_in->PeerId()), // No need for callback + ni(ni_in) + { + if (!ni_in) + { + std::cerr << "pqiconnect::pqiconnect() NetInterface == NULL, FATAL!"; + std::cerr << std::endl; + exit(1); + } + return; + } + +virtual ~pqiconnect() { return; } + + // presents a virtual NetInterface -> passes to ni. +virtual int connect(struct sockaddr_in raddr) { return ni->connect(raddr); } +virtual int listen() { return ni -> listen(); } +virtual int stoplistening() { return ni -> stoplistening(); } +virtual int reset() { return ni -> reset(); } +virtual int disconnect() { return ni -> reset(); } +virtual bool connect_parameter(uint32_t type, uint32_t value) { return ni -> connect_parameter(type, value);} +virtual int getConnectAddress(struct sockaddr_in &raddr){ return ni->getConnectAddress(raddr); } + + // get the contact from the net side! +virtual std::string PeerId() +{ + if (ni) + { + return ni->PeerId(); + } + else + { + return PQInterface::PeerId(); + } +} + + // to check if our interface. +virtual bool thisNetInterface(NetInterface *ni_in) { return (ni_in == ni); } +//protected: + NetBinInterface *ni; +protected: +}; + + +class pqipersongrp; + +class pqiperson: public PQInterface +{ +public: + pqiperson(std::string id, pqipersongrp *ppg); +virtual ~pqiperson(); // must clean up children. + + // control of the connection. +int reset(); +int listen(); +int stoplistening(); +int connect(uint32_t type, struct sockaddr_in raddr, uint32_t delay, uint32_t period, uint32_t timeout); +int receiveHeartbeat(); + // add in connection method. +int addChildInterface(uint32_t type, pqiconnect *pqi); + + // The PQInterface interface. +virtual int SendItem(RsItem *); +virtual RsItem *GetItem(); + +virtual int status(); +virtual int tick(); + +// overloaded callback function for the child - notify of a change. +int notifyEvent(NetInterface *ni, int event); + +// PQInterface for rate control overloaded.... +virtual float getRate(bool in); +virtual void setMaxRate(bool in, float val); + +pqiconnect *getKid(uint32_t type); + + private: + + std::map kids; + bool active; + pqiconnect *activepqi; + bool inConnectAttempt; + int waittimes; + time_t lastHeartbeatReceived;//use to track connection failure + +private: /* Helper functions */ + + + pqipersongrp *pqipg; /* parent for callback */ +}; + + + +#endif + diff --git a/libretroshare/src/pqi/pqipersongrp.cc b/libretroshare/src/pqi/pqipersongrp.cc new file mode 100644 index 000000000..16be14343 --- /dev/null +++ b/libretroshare/src/pqi/pqipersongrp.cc @@ -0,0 +1,679 @@ +/* + * libretroshare/src/pqi: pqipersongrp.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqipersongrp.h" +#include "pqi/p3connmgr.h" +#include "util/rsdebug.h" + +#include +#include + +const int pqipersongrpzone = 354; + +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections +#include "retroshare/rsinit.h" +static std::list waitingIds; +#define MAX_CONNECT_COUNT 5 +/////////////////////////////////////////////////////////// +#endif + +/**** + *#define PGRP_DEBUG 1 + ****/ +//#define PGRP_DEBUG 1 + +/* MUTEX NOTES: + * Functions like GetRsRawItem() lock itself (pqihandler) and + * likewise ServiceServer and ConfigMgr mutex themselves. + * This means the only things we need to worry about are: + * pqilistener and when accessing pqihandlers data. + */ + +// handle the tunnel services. +int pqipersongrp::tickServiceRecv() +{ + RsRawItem *pqi = NULL; + int i = 0; + { + std::ostringstream out; + out << "pqipersongrp::tickTunnelServer()"; + pqioutput(PQL_DEBUG_ALL, pqipersongrpzone, out.str()); + } + + //p3ServiceServer::tick(); + + while(NULL != (pqi = GetRsRawItem())) + { + ++i; + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, + "pqipersongrp::tickTunnelServer() Incoming TunnelItem"); + incoming(pqi); + } + + if (0 < i) + { + return 1; + } + return 0; +} + +// handle the tunnel services. +int pqipersongrp::tickServiceSend() +{ + RsRawItem *pqi = NULL; + int i = 0; + { + std::ostringstream out; + out << "pqipersongrp::tickServiceSend()"; + pqioutput(PQL_DEBUG_ALL, pqipersongrpzone, out.str()); + } + + p3ServiceServer::tick(); + + while(NULL != (pqi = outgoing())) /* outgoing has own locking */ + { + ++i; + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, + "pqipersongrp::tickTunnelServer() OutGoing RsItem"); + + SendRsRawItem(pqi); /* Locked by pqihandler */ + } + if (0 < i) + { + return 1; + } + return 0; +} + + + // init +pqipersongrp::pqipersongrp(SecurityPolicy *glob, unsigned long flags) + :pqihandler(glob), pqil(NULL), config(NULL), initFlags(flags) +{ +} + + +int pqipersongrp::tick() +{ + /* could limit the ticking of listener / tunnels to 1/sec... + * but not to important. + */ + + { RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + if (pqil) + { + pqil -> tick(); + } + } /* UNLOCKED */ + + int i = 0; + + if (tickServiceSend()) + { + i = 1; +#ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::tick() moreToTick from tickServiceSend()" << std::endl; +#endif + } + + if (pqihandler::tick()) /* does actual Send/Recv */ + { + i = 1; +#ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::tick() moreToTick from pqihandler::tick()" << std::endl; +#endif + } + + + if (tickServiceRecv()) + { + i = 1; +#ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::tick() moreToTick from tickServiceRecv()" << std::endl; +#endif + } + + return i; +} + +int pqipersongrp::status() +{ + { RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + if (pqil) + { + pqil -> status(); + } + } /* UNLOCKED */ + + return pqihandler::status(); +} + + +/* Initialise pqilistener */ +int pqipersongrp::init_listener() +{ + /* extract our information from the p3ConnectMgr */ + if (initFlags & PQIPERSON_NO_LISTENER) + { + pqil = NULL; + } + else + { + /* extract details from + */ + peerConnectState state; + mConnMgr->getOwnNetStatus(state); + + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + pqil = createListener(state.currentlocaladdr); + } + return 1; +} + +bool pqipersongrp::resetListener(struct sockaddr_in &local) +{ + #ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::resetListener()" << std::endl; + #endif + + // stop it, + // change the address. + // restart. + + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (pqil != NULL) + { + #ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::resetListener() haveListener" << std::endl; + #endif + + pqil -> resetlisten(); + pqil -> setListenAddr(local); + pqil -> setuplisten(); + + #ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::resetListener() done!" << std::endl; + #endif + + } + return 1; +} + +/* NOT bothering to protect Config with a mutex.... it is not going to change + * and has its own internal mutexs. + */ +int pqipersongrp::setConfig(p3GeneralConfig *cfg) +{ + config = cfg; + return 1; +} + +static const std::string pqih_ftr("PQIH_FTR"); + +int pqipersongrp::save_config() +{ + char line[512]; + sprintf(line, "%f %f", getMaxRate(true), getMaxRate(false)); + if (config) + { + config -> setSetting(pqih_ftr, std::string(line)); + } + return 1; +} + +int pqipersongrp::load_config() +{ + std::string line; + if (config) + { + line = config -> getSetting(pqih_ftr); + } + + float mri, mro; + + if (2 == sscanf(line.c_str(), "%f %f", &mri, &mro)) + { + setMaxRate(true, mri); + setMaxRate(false, mro); + } + else + { + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, + "pqipersongrp::load_config() Loading Default Rates!"); + + setMaxRate(true, 500.0); + setMaxRate(false, 500.0); + } + + return 1; +} + + +void pqipersongrp::statusChange(const std::list &plist) +{ + + /* iterate through, only worry about the friends */ + std::list::const_iterator it; + for(it = plist.begin(); it != plist.end(); it++) + { + if (it->state & RS_PEER_S_FRIEND) + { + /* now handle add/remove */ + if ((it->actions & RS_PEER_NEW) + || (it->actions & RS_PEER_MOVED)) + { + addPeer(it->id); + } + + if (it->actions & RS_PEER_CONNECT_REQ) + { + connectPeer(it->id); + } + } + else /* Not Friend */ + { + if (it->actions & RS_PEER_MOVED) + { + removePeer(it->id); + } + } + } +} + +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections +void pqipersongrp::statusChanged() +{ +#warning "Windows connection limited hacked together - please fix" + + if (RsInit::isWindowsXP() == false) { + /* the problem only exist in Windows XP */ + waitingIds.clear(); + return; + } + + /* check for active connections and start waiting id's */ + long connect_count = 0; + + { + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + /* get address from p3connmgr */ + if (!mConnMgr) { + return; + } + + /* check for active connections and start waiting id's */ + std::list peers; + mConnMgr->getFriendList(peers); + + /* count connection attempts */ + std::list::iterator peer; + for (peer = peers.begin(); peer != peers.end(); peer++) { + peerConnectState state; + if (mConnMgr->getFriendNetStatus(*peer, state) == false) { + continue; + } + + if (state.inConnAttempt) { + connect_count++; + if (connect_count >= MAX_CONNECT_COUNT) { +#ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::connectPeer() Too many connections due to windows limitations. There are " << waitingIds.size() << " waiting connections." << std::endl; +#endif + return; + } + } + } + + } /* UNLOCKED */ + +#ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::connectPeer() There are " << connect_count << " connection attempts and " << waitingIds.size() << " waiting connections. Can start " << (MAX_CONNECT_COUNT - connect_count) << " connection attempts." << std::endl; +#endif + + /* there is no need for a mutex for waitingIds */ + + /* start some waiting id's */ + for (int i = connect_count; i < MAX_CONNECT_COUNT; i++) { + if (waitingIds.empty()) { + break; + } + std::string waitingId = waitingIds.front(); + waitingIds.pop_front(); + connectPeer(waitingId, true); + } +} +/////////////////////////////////////////////////////////// +#endif + + +int pqipersongrp::addPeer(std::string id) +{ + { + std::ostringstream out; + out << "pqipersongrp::addPeer() PeerId: " << id; + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, out.str()); + } + +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::addPeer() id: " << id; + std::cerr << std::endl; +#endif + + SearchModule *sm = NULL; + { RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + std::map::iterator it; + it = mods.find(id); + if (it != mods.end()) + { + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, + "pqipersongrp::addPeer() Peer already in Use!"); + return -1; + } + + pqiperson *pqip = createPerson(id, pqil); + + // attach to pqihandler + sm = new SearchModule(); + sm -> peerid = id; + sm -> pqi = pqip; + sm -> sp = secpolicy_create(); + + // reset it to start it working. + pqip -> reset(); + pqip -> listen(); + } /* UNLOCKED */ + + return AddSearchModule(sm); +} + + +int pqipersongrp::removePeer(std::string id) +{ + std::map::iterator it; + +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::removePeer() id: " << id; + std::cerr << std::endl; +#endif + + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + it = mods.find(id); + if (it != mods.end()) + { + SearchModule *mod = it->second; + // Don't duplicate remove!!! + //RemoveSearchModule(mod); + secpolicy_delete(mod -> sp); + pqiperson *p = (pqiperson *) mod -> pqi; + p -> stoplistening(); + p -> reset(); + delete p; + mods.erase(it); + } + return 1; +} + +int pqipersongrp::tagHeartbeatRecvd(std::string id) +{ + std::map::iterator it; + +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::tagHeartbeatRecvd() id: " << id; + std::cerr << std::endl; +#endif + + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + it = mods.find(id); + if (it != mods.end()) + { + SearchModule *mod = it->second; + pqiperson *p = (pqiperson *) mod -> pqi; + p->receiveHeartbeat(); + return 1; + } + return 0; +} + + + + + + +int pqipersongrp::connectPeer(std::string id +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections + , bool bConnect /*= false*/ +/////////////////////////////////////////////////////////// +#endif + ) +{ + /* get status from p3connectMgr */ +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::connectPeer() id: " << id << " does nothing yet! "; + std::cerr << std::endl; +#endif + + { RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + if (id == mConnMgr->getOwnId()) { + #ifdef PGRP_DEBUG + std::cerr << "pqipersongrp::connectPeer() Failed, connecting to own id." << std::endl; + #endif + return 0; + } + std::map::iterator it; + it = mods.find(id); + if (it == mods.end()) + { + return 0; + } + /* get the connect attempt details from the p3connmgr... */ + SearchModule *mod = it->second; + pqiperson *p = (pqiperson *) mod -> pqi; + + + /* get address from p3connmgr */ + if (!mConnMgr) + return 0; + +#ifdef WINDOWS_SYS + /////////////////////////////////////////////////////////// + // hack for too many connections + + if (RsInit::isWindowsXP()) { + /* the problem only exist in Windows XP */ + if (bConnect == false) { + /* check for id is waiting */ + if (std::find(waitingIds.begin(), waitingIds.end(), id) != waitingIds.end()) { + /* id is waiting for a connection */ + return 0; + } + + /* add id to waiting */ + waitingIds.push_back(id); + + /* wait for call to connectPeer with empty id */ + return 0; + } + + /* remove id from waiting */ + waitingIds.remove(id); + } + + /////////////////////////////////////////////////////////// +#endif + + struct sockaddr_in addr; + uint32_t delay; + uint32_t period; + uint32_t timeout; + uint32_t type; + + if (!mConnMgr->connectAttempt(id, addr, delay, period, type)) + { +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::connectPeer() No Net Address"; + std::cerr << std::endl; +#endif + return 0; + } + +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::connectPeer() connectAttempt data id: " << id; + std::cerr << " addr: " << rs_inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port); + std::cerr << " delay: " << delay; + std::cerr << " period: " << period; + std::cerr << " type: " << type; + std::cerr << std::endl; +#endif + + + uint32_t ptype; + if (type & RS_NET_CONN_TCP_ALL) + { + ptype = PQI_CONNECT_TCP; + timeout = RS_TCP_STD_TIMEOUT_PERIOD; +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::connectPeer() connecting with TCP: Timeout :" << timeout; + std::cerr << std::endl; +#endif + } + else if (type & RS_NET_CONN_UDP_ALL) + { + ptype = PQI_CONNECT_UDP; + timeout = period * 2; +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::connectPeer() connecting with UDP: Timeout :" << timeout; + std::cerr << std::endl; +#endif + } + else if (type & RS_NET_CONN_TUNNEL) + { + ptype = PQI_CONNECT_TUNNEL; + timeout = period * 2; +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::connectPeer() connecting with Tunnel: Timeout :" << timeout; + std::cerr << std::endl; +#endif + } + else + { +#ifdef PGRP_DEBUG + std::cerr << " pqipersongrp::connectPeer() Ignoring Unknown Type:" << type; + std::cerr << std::endl; +#endif + return 0; + } + + p->connect(ptype, addr, delay, period, timeout); + + } /* UNLOCKED */ + + + /* */ + return 1; +} + +bool pqipersongrp::notifyConnect(std::string id, uint32_t ptype, bool success, struct sockaddr_in raddr) +{ + uint32_t type = 0; + if (ptype == PQI_CONNECT_TCP) + { + type = RS_NET_CONN_TCP_ALL; + } + else if (ptype == PQI_CONNECT_UDP) + { + type = RS_NET_CONN_UDP_ALL; + } + else if (ptype == PQI_CONNECT_TUNNEL) + { + type = RS_NET_CONN_TUNNEL; + } + + + if (mConnMgr) + mConnMgr->connectResult(id, success, type, raddr); + + return (NULL != mConnMgr); +} + +/******************************** DUMMY Specific features ***************************/ + +#include "pqi/pqibin.h" + +pqilistener * pqipersongrpDummy::createListener(struct sockaddr_in laddr) +{ + pqilistener *listener = new pqilistener(); + return listener; +} + + +pqiperson * pqipersongrpDummy::createPerson(std::string id, pqilistener *listener) +{ + { + std::ostringstream out; + out << "pqipersongrpDummy::createPerson() PeerId: " << id; + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, out.str()); + } + + pqiperson *pqip = new pqiperson(id, this); + + // TCP + NetBinDummy *d1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + rss->addSerialType(new RsCacheItemSerialiser()); + rss->addSerialType(new RsServiceSerialiser()); + + pqiconnect *pqic = new pqiconnect(rss, d1); + + pqip -> addChildInterface(PQI_CONNECT_TCP, pqic); + + // UDP. + NetBinDummy *d2 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); + + RsSerialiser *rss2 = new RsSerialiser(); + rss2->addSerialType(new RsFileItemSerialiser()); + rss2->addSerialType(new RsCacheItemSerialiser()); + rss2->addSerialType(new RsServiceSerialiser()); + + pqiconnect *pqic2 = new pqiconnect(rss2, d2); + + pqip -> addChildInterface(PQI_CONNECT_UDP, pqic2); + + return pqip; +} + +/******************************** DUMMY Specific features ***************************/ + diff --git a/libretroshare/src/pqi/pqipersongrp.h b/libretroshare/src/pqi/pqipersongrp.h new file mode 100644 index 000000000..7243d46bd --- /dev/null +++ b/libretroshare/src/pqi/pqipersongrp.h @@ -0,0 +1,141 @@ +/* + * libretroshare/src/pqi: pqipersongrp.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef MRK_PQI_PERSON_HANDLER_HEADER +#define MRK_PQI_PERSON_HANDLER_HEADER + +#include "pqi/pqihandler.h" +#include "pqi/pqiperson.h" +#include "pqi/pqilistener.h" +#include "pqi/pqiservice.h" +#include "pqi/pqimonitor.h" +#include "pqi/p3cfgmgr.h" + + +// So this is a specific implementation +// +// it is designed to have one pqilistensocket + a series of pqisockets +// +// as an added bonus, we are going to +// make this a pqitunnelserver, to which services can be attached. + +const unsigned long PQIPERSON_NO_LISTENER = 0x0001; + +const unsigned long PQIPERSON_ALL_BW_LIMITED = 0x0010; + +class pqipersongrp: public pqihandler, public pqiMonitor, public p3ServiceServer, public pqiNetListener +{ + public: + pqipersongrp(SecurityPolicy *, unsigned long flags); + + /*************************** Setup *************************/ + /* pqilistener */ + +virtual bool resetListener(struct sockaddr_in &local); // overloaded from pqiNetListener +int init_listener(); + +int setConfig(p3GeneralConfig *cfg); +int save_config(); +int load_config(); + + /*************** pqiMonitor callback ***********************/ +virtual void statusChange(const std::list &plist); + +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections +virtual void statusChanged(); +/////////////////////////////////////////////////////////// +#endif + + /******************* Peer Control **************************/ +virtual int addPeer(std::string id); /* can be overloaded for testing */ +int removePeer(std::string id); +int connectPeer(std::string id +#ifdef WINDOWS_SYS +/////////////////////////////////////////////////////////// +// hack for too many connections + , bool bConnect = false +/////////////////////////////////////////////////////////// +#endif + ); + + /* Work-around to dodgy pointer stuff */ +int tagHeartbeatRecvd(std::string id); + + /*** callback from children ****/ +bool notifyConnect(std::string id, uint32_t type, bool success, struct sockaddr_in remote_peer_address); +//bool notifyConnect(std::string id, uint32_t type, bool success); + + // tick interfaces. +virtual int tick(); +virtual int status(); + + protected: + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +virtual pqilistener *createListener(struct sockaddr_in laddr) = 0; +virtual pqiperson *createPerson(std::string id, pqilistener *listener) = 0; + /********* FUNCTIONS to OVERLOAD for specialisation ********/ + + /* Overloaded RsItem Check + * checks item->cid vs Person + */ +virtual int checkOutgoingRsItem(RsItem *item, int global) + { + (void) item; /* suppress unused parameter warning */ + (void) global; /* suppress unused parameter warning */ + return 1; + } + + private: + + // The tunnelserver operation. + int tickServiceRecv(); + int tickServiceSend(); + + pqilistener *pqil; + p3GeneralConfig *config; + unsigned long initFlags; +}; + +class pqipersongrpDummy: public pqipersongrp +{ + public: + pqipersongrpDummy(SecurityPolicy *pol, unsigned long flags) + :pqipersongrp(pol, flags) { return; } + + protected: + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +virtual pqilistener *createListener(struct sockaddr_in laddr); +virtual pqiperson *createPerson(std::string id, pqilistener *listener); + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +}; + + + +#endif // MRK_PQI_PERSON_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqisecurity.cc b/libretroshare/src/pqi/pqisecurity.cc new file mode 100644 index 000000000..5303af138 --- /dev/null +++ b/libretroshare/src/pqi/pqisecurity.cc @@ -0,0 +1,70 @@ +/* + * "$Id: pqisecurity.cc,v 1.3 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +#include "pqi/pqisecurity.h" +#include // malloc + + +// Can keep the structure hidden.... +// but won't at the moment. + +// functions for checking what is allowed... +// currently these are all dummies. + + +std::string secpolicy_print(SecurityPolicy *) +{ + return std::string("secpolicy_print() Implement Me Please!"); +} + +SecurityPolicy * secpolicy_create() +{ + return (SecurityPolicy *) malloc(sizeof(SecurityPolicy)); +} + +int secpolicy_delete(SecurityPolicy *p) +{ + free(p); + return 1; +} + + +int secpolicy_limit(SecurityPolicy *limiter, + SecurityPolicy *alter) +{ + return 1; +} + +int secpolicy_check(SecurityPolicy *, int type_transaction, + int direction) +{ + return 1; +} + + + diff --git a/libretroshare/src/pqi/pqisecurity.h b/libretroshare/src/pqi/pqisecurity.h new file mode 100644 index 000000000..7656927ad --- /dev/null +++ b/libretroshare/src/pqi/pqisecurity.h @@ -0,0 +1,55 @@ +/* + * "$Id: pqisecurity.h,v 1.3 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_SECURITY_HEADER +#define MRK_PQI_SECURITY_HEADER + +#define PQI_INCOMING 2 +#define PQI_OUTGOING 5 + +#include + +//structure. +typedef struct sec_policy +{ + int searchable; // flags indicate how searchable we are.. +} SecurityPolicy; + +// functions for checking what is allowed... +// + +std::string secpolicy_print(SecurityPolicy *); +SecurityPolicy * secpolicy_create(); +int secpolicy_delete(SecurityPolicy *); +int secpolicy_limit(SecurityPolicy *limiter, + SecurityPolicy *alter); +int secpolicy_check(SecurityPolicy *, int type_transaction, + int direction); + + +#endif + diff --git a/libretroshare/src/pqi/pqiservice.cc b/libretroshare/src/pqi/pqiservice.cc new file mode 100644 index 000000000..ec9d6d754 --- /dev/null +++ b/libretroshare/src/pqi/pqiservice.cc @@ -0,0 +1,225 @@ +/* + * libretroshare/src/pqi pqiservice.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqiservice.h" +#include "util/rsdebug.h" +#include + +const int pqiservicezone = 60478; + +/**** + * #define SERVICE_DEBUG 1 + ****/ + +p3ServiceServer::p3ServiceServer() +{ + RsStackMutex stack(srvMtx); /********* LOCKED *********/ + +#ifdef SERVICE_DEBUG + pqioutput(PQL_DEBUG_BASIC, pqiservicezone, + "p3ServiceServer::p3ServiceServer()"); +#endif + + rrit = services.begin(); + return; +} + +int p3ServiceServer::addService(pqiService *ts) +{ + RsStackMutex stack(srvMtx); /********* LOCKED *********/ + +#ifdef SERVICE_DEBUG + pqioutput(PQL_DEBUG_BASIC, pqiservicezone, + "p3ServiceServer::addService()"); +#endif + + std::map::iterator it; + it = services.find(ts -> getType()); + if (it != services.end()) + { + // it exists already! + return -1; + } + + services[ts -> getType()] = ts; + rrit = services.begin(); + return 1; +} + +int p3ServiceServer::incoming(RsRawItem *item) +{ + RsStackMutex stack(srvMtx); /********* LOCKED *********/ + +#ifdef SERVICE_DEBUG + pqioutput(PQL_DEBUG_BASIC, pqiservicezone, + "p3ServiceServer::incoming()"); + + { + std::ostringstream out; + out << "p3ServiceServer::incoming() PacketId: "; + out << std::hex << item -> PacketId() << std::endl; + out << "Looking for Service: "; + out << (item -> PacketId() & 0xffffff00) << std::dec << std::endl; + + out << "Item:" << std::endl; + item -> print(out); + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqiservicezone, out.str()); + } +#endif + + std::map::iterator it; + it = services.find(item -> PacketId() & 0xffffff00); + if (it == services.end()) + { +#ifdef SERVICE_DEBUG + pqioutput(PQL_DEBUG_BASIC, pqiservicezone, + "p3ServiceServer::incoming() Service: No Service - deleting"); +#endif + + // delete it. + delete item; + + // it exists already! + return -1; + } + + { +#ifdef SERVICE_DEBUG + std::ostringstream out; + out << "p3ServiceServer::incoming() Sending to"; + out << it -> second << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqiservicezone, out.str()); +#endif + + return (it->second) -> receive(item); + } + + delete item; + return -1; +} + + + +RsRawItem *p3ServiceServer::outgoing() +{ + RsStackMutex stack(srvMtx); /********* LOCKED *********/ + +#ifdef SERVICE_DEBUG + pqioutput(PQL_DEBUG_ALL, pqiservicezone, + "p3ServiceServer::outgoing()"); +#endif + + if (rrit != services.end()) + { + rrit++; + } + else + { + rrit = services.begin(); + } + + std::map::iterator sit = rrit; + // run to the end. + RsRawItem *item; + + // run through to the end, + for(;rrit != services.end();rrit++) + { + if (NULL != (item = (rrit -> second) -> send())) + { + +#ifdef SERVICE_DEBUG + std::ostringstream out; + out << "p3ServiceServer::outgoing() Got Item From:"; + out << rrit -> second << std::endl; + + item -> print(out); + out << std::endl; + std::cerr << out.str(); + pqioutput(PQL_DEBUG_BASIC, pqiservicezone, out.str()); +#endif + + return item; + } + } + + // from the beginning to where we started. + for(rrit = services.begin();rrit != sit; rrit++) + { + if (NULL != (item = (rrit -> second) -> send())) + { + +#ifdef SERVICE_DEBUG + std::ostringstream out; + out << "p3ServiceServer::outgoing() Got Item From:"; + out << rrit -> second << std::endl; + + item -> print(out); + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqiservicezone, out.str()); + std::cerr << out.str(); +#endif + + return item; + } + } + return NULL; +} + + + +int p3ServiceServer::tick() +{ + + RsStackMutex stack(srvMtx); /********* LOCKED *********/ + +#ifdef SERVICE_DEBUG + pqioutput(PQL_DEBUG_ALL, pqiservicezone, + "p3ServiceServer::tick()"); +#endif + + std::map::iterator it; + + // from the beginning to where we started. + for(it = services.begin();it != services.end(); it++) + { + +#ifdef SERVICE_DEBUG + std::ostringstream out; + out << "p3ServiceServer::service id:" << it -> first; + out << " -> Service: " << it -> second; + out << std::endl; + pqioutput(PQL_DEBUG_ALL, pqiservicezone, out.str()); +#endif + + // now we should actually tick the service. + (it -> second) -> tick(); + } + return 1; +} + + + diff --git a/libretroshare/src/pqi/pqiservice.h b/libretroshare/src/pqi/pqiservice.h new file mode 100644 index 000000000..5286d2013 --- /dev/null +++ b/libretroshare/src/pqi/pqiservice.h @@ -0,0 +1,101 @@ +/* + * libretroshare/src/pqi pqiservice.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef PQI_SERVICE_HEADER +#define PQI_SERVICE_HEADER + +#include "pqi/pqi_base.h" +#include "util/rsthreads.h" + +// PQI Service, is a generic lower layer on which services can run on. +// +// these packets get passed through the +// server, to a service that is registered. +// +// example services: +// proxytunnel. -> p3proxy. +// sockettunnel +// -> either broadcast (attach to +// open socket instead +// of broadcast address) +// -> or requested/signon. +// +// games, +// voice +// video +// +// +// DataType is defined in the serialiser directory. + +class RsRawItem; + +class pqiService +{ + protected: + + pqiService(uint32_t t) // our type of packets. + :type(t) { return; } + +virtual ~pqiService() { return; } + + public: + // +virtual int receive(RsRawItem *) = 0; +virtual RsRawItem * send() = 0; + +uint32_t getType() { return type; } + +virtual int tick() { return 0; } + + private: + uint32_t type; +}; + +#include + + +class p3ServiceServer +{ +public: + p3ServiceServer(); + +int addService(pqiService *); + +int incoming(RsRawItem *); +RsRawItem *outgoing(); + +int tick(); + +private: + + RsMutex srvMtx; +std::map services; +std::map::iterator rrit; + +}; + + +#endif // PQI_SERVICE_HEADER diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc new file mode 100644 index 000000000..7795c40bc --- /dev/null +++ b/libretroshare/src/pqi/pqissl.cc @@ -0,0 +1,1782 @@ +/* + * "$Id: pqissl.cc,v 1.28 2007-03-17 19:32:59 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + + +#include "pqi/pqissl.h" +#include "pqi/pqinetwork.h" +#include "pqi/sslfns.h" + +#include "util/rsnet.h" +#include "util/rsdebug.h" + +#include +#include +#include + +#include + +#include "pqi/pqissllistener.h" + +const int pqisslzone = 37714; + +/********* +#define WAITING_NOT 0 +#define WAITING_LOCAL_ADDR 1 +#define WAITING_REMOTE_ADDR 2 +#define WAITING_SOCK_CONNECT 3 +#define WAITING_SSL_CONNECTION 4 +#define WAITING_SSL_AUTHORISE 5 +#define WAITING_FAIL_INTERFACE 6 + +#define PQISSL_PASSIVE 0x00 +#define PQISSL_ACTIVE 0x01 + +#define PQISSL_DEBUG 1 + +const int PQISSL_LOCAL_FLAG = 0x01; +const int PQISSL_REMOTE_FLAG = 0x02; +const int PQISSL_UDP_FLAG = 0x02; +***********/ + +static const int PQISSL_MAX_READ_ZERO_COUNT = 20; +static const time_t PQISSL_MAX_READ_ZERO_TIME = 15; // 15 seconds of no data => reset. (atm HeartBeat pkt sent 5 secs) + +static const int PQISSL_SSL_CONNECT_TIMEOUT = 30; + +/********** PQI SSL STUFF ****************************************** + * + * A little note on the notifyEvent(FAILED).... + * + * this is called from + * (1) reset if needed! + * (2) Determine_Remote_Address (when all options have failed). + * + * reset() is only called when a TCP/SSL connection has been + * established, and there is an error. If there is a failed TCP + * connection, then an alternative address can be attempted. + * + * reset() is called from + * (1) destruction. + * (2) disconnect() + * (3) bad waiting state. + * + * // TCP/or SSL connection already established.... + * (5) pqissl::SSL_Connection_Complete() <- okay -> cos we made a TCP connection already. + * (6) pqissl::accept() <- okay cos something went wrong. + * (7) moretoread()/cansend() <- okay cos + * + */ + +pqissl::pqissl(pqissllistener *l, PQInterface *parent, p3ConnectMgr *cm) + :NetBinInterface(parent, parent->PeerId()), + waiting(WAITING_NOT), active(false), certvalid(false), + sslmode(PQISSL_ACTIVE), ssl_connection(NULL), sockfd(-1), + pqil(l), // no init for remote_addr. + readpkt(NULL), pktlen(0), + attempt_ts(0), + net_attempt(0), net_failure(0), net_unreachable(0), + sameLAN(false), n_read_zero(0), mReadZeroTS(0), + mConnectDelay(0), mConnectTS(0), + mConnectTimeout(0), mTimeoutTS(0), mConnMgr(cm) + +{ + /* set address to zero */ + sockaddr_clear(&remote_addr); + + { + std::ostringstream out; + out << "pqissl for PeerId: " << PeerId(); + rslog(RSL_ALERT, pqisslzone, out.str()); + } + +#if 0 + if (!(AuthSSL::getAuthSSL()->isAuthenticated(PeerId()))) + { + rslog(RSL_ALERT, pqisslzone, + "pqissl::Warning Certificate Not Approved!"); + + rslog(RSL_ALERT, pqisslzone, + "\t pqissl will not initialise...."); + + } +#else + rslog(RSL_ALERT, pqisslzone, + "pqissl::Warning SSL Certificate Approval Not CHECKED??"); +#endif + + return; +} + + pqissl::~pqissl() +{ + rslog(RSL_ALERT, pqisslzone, + "pqissl::~pqissl -> destroying pqissl"); + stoplistening(); /* remove from pqissllistener only */ + reset(); + return; +} + + +/********** Implementation of NetInterface *************************/ + +int pqissl::connect(struct sockaddr_in raddr) +{ + // reset failures + net_failure = 0; + remote_addr = raddr; + remote_addr.sin_family = AF_INET; + + return ConnectAttempt(); +} + +// tells pqilistener to listen for us. +int pqissl::listen() +{ + if (pqil) + { + return pqil -> addlistenaddr(PeerId(), this); + } + return 0; +} + +int pqissl::stoplistening() +{ + if (pqil) + { + pqil -> removeListenPort(PeerId()); + } + return 1; +} + +int pqissl::disconnect() +{ + return reset(); +} + +int pqissl::getConnectAddress(struct sockaddr_in &raddr) { + raddr = remote_addr; + return (remote_addr.sin_addr.s_addr == 0); +} + +/* BinInterface version of reset() for pqistreamer */ +int pqissl::close() +{ + return reset(); +} + +// put back on the listening queue. +int pqissl::reset() +{ + std::ostringstream out; + std::ostringstream outAlert; + + /* a reset shouldn't cause us to stop listening + * only reasons for stoplistening() are; + * + * (1) destruction. + * (2) connection. + * (3) WillListen state change + * + */ + + outAlert << "pqissl::reset():" << PeerId(); + rslog(RSL_ALERT, pqisslzone, outAlert.str()); + + + out << "pqissl::reset() State Before Reset:" << std::endl; + out << "\tActive: " << (int) active << std::endl; + out << "\tsockfd: " << sockfd << std::endl; + out << "\twaiting: " << waiting << std::endl; + out << "\tssl_con: " << ssl_connection << std::endl; + out << std::endl; + + bool neededReset = false; + + if (ssl_connection != NULL) + { + out << "pqissl::reset() Shutting down SSL Connection"; + out << std::endl; + SSL_shutdown(ssl_connection); + SSL_free (ssl_connection); + + neededReset = true; + } + + if (sockfd > 0) + { + out << "pqissl::reset() Shutting down (active) socket"; + out << std::endl; + net_internal_close(sockfd); + sockfd = -1; + neededReset = true; + } + active = false; + sockfd = -1; + waiting = WAITING_NOT; + ssl_connection = NULL; + sameLAN = false; + n_read_zero = 0; + mReadZeroTS = 0; + total_len = 0 ; + mTimeoutTS = 0; + + if (neededReset) + { + out << "pqissl::reset() Reset Required!" << std::endl; + out << "pqissl::reset() Will Attempt notifyEvent(FAILED)"; + out << std::endl; + } + + out << "pqissl::reset() Complete!" << std::endl; + rslog(RSL_DEBUG_BASIC, pqisslzone, out.str()); + + // notify people of problem! + // but only if we really shut something down. + if (neededReset) + { + // clean up the streamer + if (parent()) + { + parent() -> notifyEvent(this, NET_CONNECT_FAILED); + } + } + return 1; +} + +bool pqissl::connect_parameter(uint32_t type, uint32_t value) +{ + { + std::ostringstream out; + out << "pqissl::connect_parameter() Peer: " << PeerId(); + out << " type: " << type << "value: " << value; + rslog(RSL_DEBUG_ALL, pqisslzone, out.str()); + } + + if (type == NET_PARAM_CONNECT_DELAY) + { + std::ostringstream out; + out << "pqissl::connect_parameter() Peer: " << PeerId(); + out << " DELAY: " << value; + rslog(RSL_WARNING, pqisslzone, out.str()); + + + mConnectDelay = value; + return true; + } + else if (type == NET_PARAM_CONNECT_TIMEOUT) + { + std::ostringstream out; + out << "pqissl::connect_parameter() Peer: " << PeerId(); + out << " TIMEOUT: " << value; + rslog(RSL_WARNING, pqisslzone, out.str()); + + mConnectTimeout = value; + return true; + } + return false; + //return NetInterface::connect_parameter(type, value); +} + + +/********** End of Implementation of NetInterface ******************/ +/********** Implementation of BinInterface ************************** + * Only status() + tick() are here ... as they are really related + * to the NetInterface, and not the BinInterface, + * + */ + +/* returns ... + * -1 if inactive. + * 0 if connecting. + * 1 if connected. + */ + +int pqissl::status() +{ + int alg; + + std::ostringstream out; + out << "pqissl::status()"; + + if (active) + { + out << " active: " << std::endl; + // print out connection. + out << "Connected TO : " << PeerId(); + out << std::endl; + // print out cipher. + out << "\t\tSSL Cipher:" << SSL_get_cipher(ssl_connection); + out << " (" << SSL_get_cipher_bits(ssl_connection, &alg); + out << ":" << alg << ") "; + out << "Vers:" << SSL_get_cipher_version(ssl_connection); + out << std::endl; + out << std::endl; + + } + else + { + out << " Waiting for connection!" << std::endl; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, out.str()); + + if (active) + { + return 1; + } + else if (waiting > 0) + { + return 0; + } + return -1; +} + + // tick...... +int pqissl::tick() +{ + //pqistreamer::tick(); + + // continue existing connection attempt. + if (!active) + { + // if we are waiting.. continue the connection (only) + if (waiting > 0) + { + std::ostringstream out; + out << "pqissl::tick() "; + out << "Continuing Connection Attempt!"; + rslog(RSL_DEBUG_BASIC, pqisslzone, out.str()); + + ConnectAttempt(); + return 1; + } + } + return 1; +} + +/********** End of Implementation of BinInterface ******************/ +/********** Internals of SSL Connection ****************************/ + + +int pqissl::ConnectAttempt() +{ + switch(waiting) + { + case WAITING_NOT: + + sslmode = PQISSL_ACTIVE; /* we're starting this one */ + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::ConnectAttempt() STATE = Not Waiting, starting connection"); + + case WAITING_DELAY: + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::ConnectAttempt() STATE = Waiting Delay, starting connection"); + + return Delay_Connection(); + //return Initiate_Connection(); /* now called by Delay_Connection() */ + + break; + + case WAITING_SOCK_CONNECT: + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::ConnectAttempt() STATE = Waiting Sock Connect"); + + return Initiate_SSL_Connection(); + break; + + case WAITING_SSL_CONNECTION: + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::ConnectAttempt() STATE = Waiting SSL Connection"); + + return Authorise_SSL_Connection(); + break; + + case WAITING_SSL_AUTHORISE: + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::ConnectAttempt() STATE = Waiting SSL Authorise"); + + return Authorise_SSL_Connection(); + break; + case WAITING_FAIL_INTERFACE: + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::ConnectAttempt() Failed - Retrying"); + + return Failed_Connection(); + break; + + + default: + rslog(RSL_ALERT, pqisslzone, + "pqissl::ConnectAttempt() STATE = Unknown - Reset"); + + reset(); + break; + } + rslog(RSL_ALERT, pqisslzone, "pqissl::ConnectAttempt() Unknown"); + + return -1; +} + + +/****************************** FAILED ATTEMPT ****************************** + * Determine the Remote Address. + * + * Specifics: + * TCP / UDP + * TCP - check for which interface to use. + * UDP - check for request proxies.... + * + * X509 / XPGP - Same. + * + */ + +int pqissl::Failed_Connection() +{ + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::ConnectAttempt() Failed - Notifying"); + + if (parent()) + { + parent() -> notifyEvent(this, NET_CONNECT_UNREACHABLE); + } + waiting = WAITING_NOT; + + return 1; +} + +/****************************** MAKE CONNECTION ***************************** + * Open Socket and Initiate Connection. + * + * Specifics: + * TCP / UDP + * TCP - socket()/connect() + * UDP - tou_socket()/tou_connect() + * + * X509 / XPGP - Same. + * + */ + +int pqissl::Delay_Connection() +{ + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Delay_Connection() Attempting Outgoing Connection...."); + + if (waiting == WAITING_NOT) + { + waiting = WAITING_DELAY; + + /* set delay */ + if (mConnectDelay == 0) + { + return Initiate_Connection(); + } + + /* set Connection TS. + */ + { + std::ostringstream out; + out << "pqissl::Delay_Connection() "; + out << " Delaying Connection to "; + out << PeerId() << " for "; + out << mConnectDelay; + out << " seconds"; + rslog(RSL_DEBUG_BASIC, pqisslzone, out.str()); + } + + + mConnectTS = time(NULL) + mConnectDelay; + return 0; + } + else if (waiting == WAITING_DELAY) + { + { + std::ostringstream out; + out << "pqissl::Delay_Connection() "; + out << " Connection to "; + out << PeerId() << " starting in "; + out << mConnectTS - time(NULL); + out << " seconds"; + rslog(RSL_DEBUG_BASIC, pqisslzone, out.str()); + } + + if (time(NULL) > mConnectTS) + { + return Initiate_Connection(); + } + return 0; + } + + rslog(RSL_WARNING, pqisslzone, + "pqissl::Initiate_Connection() Already Attempt in Progress!"); + return -1; +} + + +int pqissl::Initiate_Connection() +{ + int err; + struct sockaddr_in addr = remote_addr; + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Initiate_Connection() Attempting Outgoing Connection...."); + + if (waiting != WAITING_DELAY) + { + rslog(RSL_WARNING, pqisslzone, + "pqissl::Initiate_Connection() Already Attempt in Progress!"); + return -1; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Initiate_Connection() Opening Socket"); + + // open socket connection to addr. + int osock = unix_socket(PF_INET, SOCK_STREAM, 0); + + { + std::ostringstream out; + out << "pqissl::Initiate_Connection() osock = " << osock; + rslog(RSL_DEBUG_BASIC, pqisslzone, out.str()); + } + + if (osock < 0) + { + std::ostringstream out; + out << "pqissl::Initiate_Connection()"; + out << "Failed to open socket!" << std::endl; + out << "Socket Error:" << socket_errorType(errno) << std::endl; + rslog(RSL_WARNING, pqisslzone, out.str()); + + net_internal_close(osock); + waiting = WAITING_FAIL_INTERFACE; + return -1; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Initiate_Connection() Making Non-Blocking"); + + err = unix_fcntl_nonblock(osock); + if (err < 0) + { + std::ostringstream out; + out << "pqissl::Initiate_Connection()"; + out << "Error: Cannot make socket NON-Blocking: "; + out << err << std::endl; + rslog(RSL_WARNING, pqisslzone, out.str()); + + waiting = WAITING_FAIL_INTERFACE; + net_internal_close(osock); + return -1; + } + + { + std::ostringstream out; + out << "pqissl::Initiate_Connection() "; + out << "Connecting To: "; + out << PeerId() << " via: "; + out << rs_inet_ntoa(addr.sin_addr); + out << ":" << ntohs(addr.sin_port); + rslog(RSL_WARNING, pqisslzone, out.str()); + } + + if (addr.sin_addr.s_addr == 0) + { + std::ostringstream out; + out << "pqissl::Initiate_Connection() "; + out << "Invalid (0.0.0.0) Remote Address,"; + out << " Aborting Connect."; + out << std::endl; + rslog(RSL_WARNING, pqisslzone, out.str()); + waiting = WAITING_FAIL_INTERFACE; + net_internal_close(osock); + return -1; + } + +#ifdef WINDOWS_SYS + /* Set TCP buffer size for Windows systems */ + + int sockbufsize = 0; + int size = sizeof(int); + + err = getsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size); +#ifdef PQISSL_DEBUG + if (err == 0) { + std::cerr << "pqissl::Initiate_Connection: Current TCP receive buffer size " << sockbufsize << std::endl; + } else { + std::cerr << "pqissl::Initiate_Connection: Error getting TCP receive buffer size. Error " << err << std::endl; + } +#endif + + sockbufsize = 0; + + err = getsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size); +#ifdef PQISSL_DEBUG + if (err == 0) { + std::cerr << "pqissl::Initiate_Connection: Current TCP send buffer size " << sockbufsize << std::endl; + } else { + std::cerr << "pqissl::Initiate_Connection: Error getting TCP send buffer size. Error " << err << std::endl; + } +#endif + + sockbufsize = WINDOWS_TCP_BUFFER_SIZE; + + err = setsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, sizeof(sockbufsize)); +#ifdef PQISSL_DEBUG + if (err == 0) { + std::cerr << "pqissl::Initiate_Connection: TCP receive buffer size set to " << sockbufsize << std::endl; + } else { + std::cerr << "pqissl::Initiate_Connection: Error setting TCP receive buffer size. Error " << err << std::endl; + } +#endif + + err = setsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, sizeof(sockbufsize)); +#ifdef PQISSL_DEBUG + if (err == 0) { + std::cerr << "pqissl::Initiate_Connection: TCP send buffer size set to " << sockbufsize << std::endl; + } else { + std::cerr << "pqissl::Initiate_Connection: Error setting TCP send buffer size. Error " << err << std::endl; + } +#endif +#endif // WINDOWS_SYS + + mTimeoutTS = time(NULL) + mConnectTimeout; + //std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl; + + if (0 != (err = unix_connect(osock, (struct sockaddr *) &addr, sizeof(addr)))) + { + std::ostringstream out; + out << "pqissl::Initiate_Connection() connect returns:"; + out << err << " -> errno: " << errno << " error: "; + out << socket_errorType(errno) << std::endl; + + if (errno == EINPROGRESS) + { + // set state to waiting..... + waiting = WAITING_SOCK_CONNECT; + sockfd = osock; + + out << " EINPROGRESS Waiting for Socket Connection"; + rslog(RSL_DEBUG_BASIC, pqisslzone, out.str()); + + return 0; + } + else if ((errno == ENETUNREACH) || (errno == ETIMEDOUT)) + { + out << "ENETUNREACHABLE: cert: " << PeerId(); + rslog(RSL_WARNING, pqisslzone, out.str()); + + // Then send unreachable message. + net_internal_close(osock); + osock=-1; + //reset(); + + waiting = WAITING_FAIL_INTERFACE; + // removing unreachables... + //net_unreachable |= net_attempt; + + return -1; + } + + /* IF we get here ---- we Failed for some other reason. + * Should abandon this interface + * Known reasons to get here: EINVAL (bad address) + */ + + out << "Error: Connection Failed: " << errno; + out << " - " << socket_errorType(errno) << std::endl; + + net_internal_close(osock); + osock=-1; + waiting = WAITING_FAIL_INTERFACE; + + rslog(RSL_WARNING, pqisslzone, out.str()); + // extra output for the moment. + //std::cerr << out.str(); + + return -1; + } + else + { + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Init_Connection() connect returned 0"); + } + + waiting = WAITING_SOCK_CONNECT; + sockfd = osock; + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Initiate_Connection() Waiting for Socket Connect"); + + return 1; +} + + +/****************************** CHECK SOCKET ***************************** + * Check the Socket. + * + * select() and getsockopt(). + * + * Specifics: + * TCP / UDP + * TCP - select()/getsockopt() + * UDP - tou_error() + * + * X509 / XPGP - Same. + * + */ + +int pqissl::Basic_Connection_Complete() +{ + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Basic_Connection_Complete()..."); + + /* new TimeOut code. */ + if (time(NULL) > mTimeoutTS) + { + std::ostringstream out; + out << "pqissl::Basic_Connection_Complete() Connection Timed Out. "; + out << "Peer: " << PeerId() << " Period: "; + out << mConnectTimeout; + + rslog(RSL_WARNING, pqisslzone, out.str()); + /* as sockfd is valid, this should close it all up */ + + reset(); + return -1; + } + + + if (waiting != WAITING_SOCK_CONNECT) + { + rslog(RSL_ALERT, pqisslzone, + "pqissl::Basic_Connection_Complete() Wrong Mode"); + return -1; + } + + if (sockfd == -1) + { + rslog(RSL_ALERT, pqisslzone, + "pqissl::Basic_Connection_Complete() problem with the socket descriptor. Aborting"); + reset(); + return -1; + } + + // use select on the opened socket. + // Interestingly - This code might be portable.... + + fd_set ReadFDs, WriteFDs, ExceptFDs; + FD_ZERO(&ReadFDs); + FD_ZERO(&WriteFDs); + FD_ZERO(&ExceptFDs); + + FD_SET(sockfd, &ReadFDs); + FD_SET(sockfd, &WriteFDs); + FD_SET(sockfd, &ExceptFDs); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Basic_Connection_Complete() Selecting ...."); + + int sr = 0; + if (0 > (sr = select(sockfd + 1, + &ReadFDs, &WriteFDs, &ExceptFDs, &timeout))) + { + // select error. + rslog(RSL_WARNING, pqisslzone, + "pqissl::Basic_Connection_Complete() Select ERROR(1)"); + + net_internal_close(sockfd); + sockfd=-1; + //reset(); + waiting = WAITING_FAIL_INTERFACE; + return -1; + } + + { + std::ostringstream out; + out << "pqissl::Basic_Connection_Complete() Select "; + out << " returned " << sr; + rslog(RSL_DEBUG_BASIC, pqisslzone, out.str()); + } + + + if (FD_ISSET(sockfd, &ExceptFDs)) + { + // error - reset socket. + // this is a definite bad socket!. + + rslog(RSL_WARNING, pqisslzone, + "pqissl::Basic_Connection_Complete() Select ERROR(2)"); + + net_internal_close(sockfd); + sockfd=-1; + //reset(); + waiting = WAITING_FAIL_INTERFACE; + return -1; + } + + if (FD_ISSET(sockfd, &WriteFDs)) + { + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Basic_Connection_Complete() Can Write!"); + } + else + { + // happens frequently so switched to debug msg. + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Basic_Connection_Complete() Not Yet Ready!"); + return 0; + } + + if (FD_ISSET(sockfd, &ReadFDs)) + { + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Basic_Connection_Complete() Can Read!"); + } + else + { + // not ready return -1; + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Basic_Connection_Complete() Cannot Read!"); + } + + int err = 1; + if (0==unix_getsockopt_error(sockfd, &err)) + { + if (err == 0) + { + + { + std::ostringstream out; + out << "pqissl::Basic_Connection_Complete()"; + out << " TCP Connection Complete: cert: "; + out << PeerId(); + out << " on osock: " << sockfd; + rslog(RSL_WARNING, pqisslzone, out.str()); + } + return 1; + } + else if (err == EINPROGRESS) + { + + std::ostringstream out; + out << "pqissl::Basic_Connection_Complete()"; + out << " EINPROGRESS: cert: " << PeerId(); + rslog(RSL_WARNING, pqisslzone, out.str()); + + return 0; + } + else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) + { + std::ostringstream out; + out << "pqissl::Basic_Connection_Complete()"; + out << " ENETUNREACH/ETIMEDOUT: cert: "; + out << PeerId(); + rslog(RSL_WARNING, pqisslzone, out.str()); + + // Then send unreachable message. + net_internal_close(sockfd); + sockfd=-1; + //reset(); + + waiting = WAITING_FAIL_INTERFACE; + // removing unreachables... + //net_unreachable |= net_attempt; + + return -1; + } + else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN)) + { + std::ostringstream out; + out << "pqissl::Basic_Connection_Complete()"; + out << " EHOSTUNREACH/EHOSTDOWN: cert: "; + out << PeerId(); + rslog(RSL_WARNING, pqisslzone, out.str()); + + // Then send unreachable message. + net_internal_close(sockfd); + sockfd=-1; + //reset(); + waiting = WAITING_FAIL_INTERFACE; + + return -1; + } + else if ((err == ECONNREFUSED)) + { + std::ostringstream out; + out << "pqissl::Basic_Connection_Complete()"; + out << " ECONNREFUSED: cert: "; + out << PeerId(); + rslog(RSL_WARNING, pqisslzone, out.str()); + + // Then send unreachable message. + net_internal_close(sockfd); + sockfd=-1; + //reset(); + waiting = WAITING_FAIL_INTERFACE; + + return -1; + } + + std::ostringstream out; + out << "Error: Connection Failed UNKNOWN ERROR: " << err; + out << " - " << socket_errorType(err); + rslog(RSL_WARNING, pqisslzone, out.str()); + + net_internal_close(sockfd); + sockfd=-1; + //reset(); // which will send Connect Failed, + return -1; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Basic_Connection_Complete() BAD GETSOCKOPT!"); + waiting = WAITING_FAIL_INTERFACE; + + return -1; +} + + +int pqissl::Initiate_SSL_Connection() +{ + int err; + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Initiate_SSL_Connection() Checking Basic Connection"); + + if (0 >= (err = Basic_Connection_Complete())) + { + return err; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Initiate_SSL_Connection() Basic Connection Okay"); + + // setup timeout value. + ssl_connect_timeout = time(NULL) + PQISSL_SSL_CONNECT_TIMEOUT; + + // Perform SSL magic. + // library already inited by sslroot(). + SSL *ssl = SSL_new(AuthSSL::getAuthSSL()->getCTX()); + if (ssl == NULL) + { + rslog(RSL_ALERT, pqisslzone, + "pqissl::Initiate_SSL_Connection() SSL_new failed!"); + + exit(1); + return -1; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Initiate_SSL_Connection() SSL Connection Okay"); + + ssl_connection = ssl; + + net_internal_SSL_set_fd(ssl, sockfd); + if (err < 1) + { + std::ostringstream out; + out << "pqissl::Initiate_SSL_Connection() SSL_set_fd failed!"; + out << std::endl; + printSSLError(ssl, err, SSL_get_error(ssl, err), + ERR_get_error(), out); + + rslog(RSL_ALERT, pqisslzone, out.str()); + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Initiate_SSL_Connection() Waiting for SSL Connection"); + + waiting = WAITING_SSL_CONNECTION; + return 1; +} + +int pqissl::SSL_Connection_Complete() +{ + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::SSL_Connection_Complete()??? ... Checking"); + + if (waiting == WAITING_SSL_AUTHORISE) + { + rslog(RSL_ALERT, pqisslzone, + "pqissl::SSL_Connection_Complete() Waiting = W_SSL_AUTH"); + + return 1; + } + if (waiting != WAITING_SSL_CONNECTION) + { + rslog(RSL_ALERT, pqisslzone, + "pqissl::SSL_Connection_Complete() Still Waiting.."); + + return -1; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::SSL_Connection_Complete() Attempting SSL_connect"); + + /* if we are passive - then accept! */ + int err; + + if (sslmode) + { + rslog(RSL_DEBUG_BASIC, pqisslzone, "--------> Active Connect!"); + err = SSL_connect(ssl_connection); + } + else + { + rslog(RSL_DEBUG_BASIC, pqisslzone, "--------> Passive Accept!"); + err = SSL_accept(ssl_connection); + } + + if (err != 1) + { + int serr = SSL_get_error(ssl_connection, err); + if ((serr == SSL_ERROR_WANT_READ) + || (serr == SSL_ERROR_WANT_WRITE)) + { + rslog(RSL_DEBUG_BASIC, pqisslzone, + "Waiting for SSL handshake!"); + + waiting = WAITING_SSL_CONNECTION; + return 0; + } + + + std::ostringstream out; + out << "pqissl::SSL_Connection_Complete()" << std::endl; + out << "Issues with SSL Connect(" << err << ")!" << std::endl; + printSSLError(ssl_connection, err, serr, + ERR_get_error(), out); + + rslog(RSL_WARNING, pqisslzone, + out.str()); + + // attempt real error. + Extract_Failed_SSL_Certificate(); + + reset(); + waiting = WAITING_FAIL_INTERFACE; + + return -1; + } + // if we get here... success v quickly. + + { + std::ostringstream out; + out << "pqissl::SSL_Connection_Complete() Success!: Peer: " << PeerId(); + rslog(RSL_WARNING, pqisslzone, out.str()); + } + + waiting = WAITING_SSL_AUTHORISE; + return 1; +} + +int pqissl::Extract_Failed_SSL_Certificate() +{ + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Extract_Failed_SSL_Certificate()"); + + // Get the Peer Certificate.... + X509 *peercert = SSL_get_peer_certificate(ssl_connection); + + if (peercert == NULL) + { + rslog(RSL_WARNING, pqisslzone, + "pqissl::Extract_Failed_SSL_Certificate() Peer Didnt Give Cert"); + return -1; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Extract_Failed_SSL_Certificate() Have Peer Cert - Registering"); + + // save certificate... (and ip locations) + // false for outgoing.... + // we actually connected to remote_addr, + // which could be + // (pqissl's case) sslcert->serveraddr or sslcert->localaddr. + AuthSSL::getAuthSSL()->FailedCertificate(peercert, false); + + return 1; +} + + + + +int pqissl::Authorise_SSL_Connection() +{ + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Authorise_SSL_Connection()"); + + if (time(NULL) > ssl_connect_timeout) + { + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Authorise_SSL_Connection() Connection Timed Out!"); + /* as sockfd is valid, this should close it all up */ + reset(); + } + + int err; + if (0 >= (err = SSL_Connection_Complete())) + { + return err; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Authorise_SSL_Connection() SSL_Connection_Complete"); + + // reset switch. + waiting = WAITING_NOT; + + X509 *peercert = SSL_get_peer_certificate(ssl_connection); + + if (peercert == NULL) + { + rslog(RSL_WARNING, pqisslzone, + "pqissl::Authorise_SSL_Connection() Peer Didnt Give Cert"); + + // Failed completely + reset(); + return -1; + } + + std::string certPeerId; + getX509id(peercert, certPeerId); + if (certPeerId != PeerId()) { + rslog(RSL_WARNING, pqisslzone, + "pqissl::Authorise_SSL_Connection() the cert Id doesn't match the Peer id we're trying to connect to."); + + // Failed completely + reset(); + return -1; + } + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::Authorise_SSL_Connection() Have Peer Cert"); + + // save certificate... (and ip locations) + // false for outgoing.... + // we actually connected to remote_addr, + // which could be + // (pqissl's case) sslcert->serveraddr or sslcert->localaddr. + + AuthSSL::getAuthSSL()->CheckCertificate(PeerId(), peercert); + bool certCorrect = true; /* WE know it okay already! */ + + // check it's the right one. + if (certCorrect) + { + // then okay... + std::ostringstream out; + out << "pqissl::Authorise_SSL_Connection() Accepting Conn. Peer: " << PeerId(); + rslog(RSL_WARNING, pqisslzone, out.str()); + + accept(ssl_connection, sockfd, remote_addr); + return 1; + } + + { + std::ostringstream out; + out << "pqissl::Authorise_SSL_Connection() Something Wrong ... "; + out << " Shutdown. Peer: " << PeerId(); + rslog(RSL_WARNING, pqisslzone, out.str()); + } + + // else shutdown ssl connection. + + reset(); + return 0; +} + +int pqissl::accept(SSL *ssl, int fd, struct sockaddr_in foreign_addr) // initiate incoming connection. +{ + if (waiting != WAITING_NOT) + { + rslog(RSL_WARNING, pqisslzone, + "pqissl::accept() - Two connections in progress - Shut 1 down!"); + + // outgoing connection in progress. + // shut this baby down. + // + // Thought I should shut down one in progress, and continue existing one! + // But the existing one might be broke.... take second. + // all we need is to never stop listening. + + switch(waiting) + { + + case WAITING_SOCK_CONNECT: + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::accept() STATE = Waiting Sock Connect - close the socket"); + + break; + + case WAITING_SSL_CONNECTION: + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::accept() STATE = Waiting SSL Connection - close sockfd + ssl_conn"); + + break; + + case WAITING_SSL_AUTHORISE: + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::accept() STATE = Waiting SSL Authorise - close sockfd + ssl_conn"); + + break; + + case WAITING_FAIL_INTERFACE: + + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::accept() STATE = Failed, ignore?"); + + break; + + + default: + rslog(RSL_ALERT, pqisslzone, + "pqissl::accept() STATE = Unknown - ignore?"); + + reset(); + break; + } + + //waiting = WAITING_FAIL_INTERFACE; + //return -1; + } + + /* shutdown existing - in all cases use the new one */ + if ((ssl_connection) && (ssl_connection != ssl)) + { + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::accept() closing Previous/Existing ssl_connection"); + SSL_shutdown(ssl_connection); + } + + if ((sockfd > -1) && (sockfd != fd)) + { + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::accept() closing Previous/Existing sockfd"); + net_internal_close(sockfd); + } + + + // save ssl + sock. + + ssl_connection = ssl; + sockfd = fd; + + /* if we connected - then just writing the same over, + * but if from ssllistener then we need to save the address. + */ + remote_addr = foreign_addr; + + /* check whether it is on the same LAN */ + + peerConnectState details; + mConnMgr->getOwnNetStatus(details); + sameLAN = isSameSubnet(&(remote_addr.sin_addr), &(details.currentlocaladdr.sin_addr)); + + { + std::ostringstream out; + out << "pqissl::accept() Successful connection with: " << PeerId(); + out << std::endl; + out << "\t\tchecking for same LAN"; + out << std::endl; + out << "\t localaddr: " << rs_inet_ntoa(details.currentlocaladdr.sin_addr); + out << std::endl; + out << "\t remoteaddr: " << rs_inet_ntoa(remote_addr.sin_addr); + out << std::endl; +// if (sameLAN) +// { +// out << "\tSAME LAN - no bandwidth restrictions!"; +// } +// else +// { +// out << "\tDifferent LANs - bandwidth restrictions!"; +// } +// out << std::endl; + + rslog(RSL_WARNING, pqisslzone, out.str()); + } + + // establish the ssl details. + // cipher name. + int alg; + int err; + + { + std::ostringstream out; + out << "SSL Cipher:" << SSL_get_cipher(ssl) << std::endl; + out << "SSL Cipher Bits:" << SSL_get_cipher_bits(ssl, &alg); + out << " - " << alg << std::endl; + out << "SSL Cipher Version:" << SSL_get_cipher_version(ssl) << std::endl; + rslog(RSL_DEBUG_BASIC, pqisslzone, out.str()); + } + + // make non-blocking / or check..... + if ((err = net_internal_fcntl_nonblock(sockfd)) < 0) + { + rslog(RSL_ALERT, pqisslzone, "Error: Cannot make socket NON-Blocking: "); + + active = false; + waiting = WAITING_FAIL_INTERFACE; + // failed completely. + reset(); + return -1; + } + else + { + rslog(RSL_DEBUG_BASIC, pqisslzone, "pqissl::accept() Socket Made Non-Blocking!"); + } + + // we want to continue listening - incase this socket is crap, and they try again. + //stoplistening(); + + active = true; + waiting = WAITING_NOT; + + // Notify the pqiperson.... (Both Connect/Receive) + if (parent()) + { + parent() -> notifyEvent(this, NET_CONNECT_SUCCESS); + } + return 1; +} + +/********** Implementation of BinInterface ************************** + * All the rest of the BinInterface. + * + */ + +int pqissl::senddata(void *data, int len) +{ + int tmppktlen ; + +#ifdef PQISSL_DEBUG + std::cout << "Sending data thread=" << pthread_self() << ", ssl=" << (void*)this << ", size=" << len << std::endl ; +#endif + tmppktlen = SSL_write(ssl_connection, data, len) ; + + if (len != tmppktlen) + { + std::ostringstream out; + out << "pqissl::senddata()"; + out << " Full Packet Not Sent!" << std::endl; + out << " -> Expected len(" << len << ") actually sent("; + out << tmppktlen << ")" << std::endl; + + int err = SSL_get_error(ssl_connection, tmppktlen); + // incomplete operations - to repeat.... + // handled by the pqistreamer... + if (err == SSL_ERROR_SYSCALL) + { + out << "SSL_write() SSL_ERROR_SYSCALL"; + out << std::endl; + out << "Socket Closed Abruptly.... Resetting PQIssl"; + out << std::endl; + std::cerr << out.str() ; + rslog(RSL_ALERT, pqisslzone, out.str()); + + /* extra debugging - based on SSL_get_error() man page */ + { + int errsys = errno; + int sslerr = 0; + std::ostringstream out2; + out2 << "SSL_ERROR_SYSCALL, ret == " << tmppktlen; + out2 << " errno: " << errsys << std::endl; + + while(0 != (sslerr = ERR_get_error())) + { + out2 << "SSLERR:" << sslerr << " : "; + + char sslbuf[256] = {0}; + out2 << ERR_error_string(sslerr, sslbuf); + out2 << std::endl; + } + rslog(RSL_ALERT, pqisslzone, out2.str()); + } + + reset(); + return -1; + } + else if (err == SSL_ERROR_WANT_WRITE) + { + out << "SSL_write() SSL_ERROR_WANT_WRITE"; + out << std::endl; + rslog(RSL_ALERT, pqisslzone, out.str()); +// std::cerr << out.str() ; + return -1; + } + else if (err == SSL_ERROR_WANT_READ) + { + out << "SSL_write() SSL_ERROR_WANT_READ"; + out << std::endl; + rslog(RSL_ALERT, pqisslzone, out.str()); + std::cerr << out.str() ; + return -1; + } + else + { + out << "SSL_write() UNKNOWN ERROR: " << err; + out << std::endl; + printSSLError(ssl_connection, tmppktlen, err, ERR_get_error(), out); + out << std::endl; + out << "\tResetting!"; + out << std::endl; + std::cerr << out.str() ; + rslog(RSL_ALERT, pqisslzone, out.str()); + + reset(); + return -1; + } + } + return tmppktlen; +} + +int pqissl::readdata(void *data, int len) +{ +#ifdef PQISSL_DEBUG + std::cout << "Reading data thread=" << pthread_self() << ", ssl=" << (void*)this << std::endl ; +#endif + + // There is a do, because packets can be splitted into multiple ssl buffers + // when they are larger than 16384 bytes. Such packets have to be read in + // multiple slices. + do + { + int tmppktlen ; + +#ifdef PQISSL_DEBUG + std::cerr << "calling SSL_read. len=" << len << ", total_len=" << total_len << std::endl ; +#endif + tmppktlen = SSL_read(ssl_connection, (void*)( &(((uint8_t*)data)[total_len])), len-total_len) ; +#ifdef PQISSL_DEBUG + std::cerr << "have read " << tmppktlen << " bytes" << std::endl ; + std::cerr << "data[0] = " + << (int)((uint8_t*)data)[total_len+0] << " " + << (int)((uint8_t*)data)[total_len+1] << " " + << (int)((uint8_t*)data)[total_len+2] << " " + << (int)((uint8_t*)data)[total_len+3] << " " + << (int)((uint8_t*)data)[total_len+4] << " " + << (int)((uint8_t*)data)[total_len+5] << " " + << (int)((uint8_t*)data)[total_len+6] << " " + << (int)((uint8_t*)data)[total_len+7] << std::endl ; +#endif + + // Need to catch errors..... + // + if (tmppktlen <= 0) // probably needs a reset. + { + std::ostringstream out; + + int error = SSL_get_error(ssl_connection, tmppktlen); + unsigned long err2 = ERR_get_error(); + + //printSSLError(ssl_connection, tmppktlen, error, err2, out); + + if ((error == SSL_ERROR_ZERO_RETURN) && (err2 == 0)) + { + /* this code will be called when + * (1) moretoread -> returns true. + + * (2) SSL_read fails. + * + * There are two ways this can happen: + * (1) there is a little data on the socket, but not enough + * for a full SSL record, so there legimitately is no error, and the moretoread() + * was correct, but the read fails. + * + * (2) the socket has been closed correctly. this leads to moretoread() -> true, + * and ZERO error.... we catch this case by counting how many times + * it occurs in a row (cos the other one will not). + */ + if (n_read_zero == 0) + { + /* first read_zero */ + mReadZeroTS = time(NULL); + } + + ++n_read_zero; + out << "ssl read : SSL_ERROR_ZERO_RETURN : nReadZero: " << n_read_zero; + out << std::endl; + + if ((PQISSL_MAX_READ_ZERO_COUNT < n_read_zero) + && (time(NULL) - mReadZeroTS > PQISSL_MAX_READ_ZERO_TIME)) + { + out << "Count passed Limit, shutting down!"; + out << " ReadZero Age: " << time(NULL) - mReadZeroTS; + reset(); + } + + rslog(RSL_ALERT, pqisslzone, out.str()); + std::cerr << out.str() << std::endl ; + return -1; + } + + /* the only real error we expect */ + if (error == SSL_ERROR_SYSCALL) + { + out << "SSL_read() SSL_ERROR_SYSCALL"; + out << std::endl; + out << "Socket Closed Abruptly.... Resetting PQIssl"; + out << std::endl; + rslog(RSL_ALERT, pqisslzone, out.str()); + + /* extra debugging - based on SSL_get_error() man page */ + { + int syserr = errno; + int sslerr = 0; + std::ostringstream out2; + out2 << "SSL_ERROR_SYSCALL, ret == " << tmppktlen; + out2 << " errno: " << syserr << std::endl; + + while(0 != (sslerr = ERR_get_error())) + { + out2 << "SSLERR:" << sslerr << " : "; + + char sslbuf[256] = {0}; + out2 << ERR_error_string(sslerr, sslbuf); + out2 << std::endl; + } + rslog(RSL_ALERT, pqisslzone, out2.str()); + } + + reset(); + std::cerr << out.str() << std::endl ; + return -1; + } + else if (error == SSL_ERROR_WANT_WRITE) + { + out << "SSL_read() SSL_ERROR_WANT_WRITE"; + out << std::endl; + rslog(RSL_ALERT, pqisslzone, out.str()); + std::cerr << out.str() << std::endl ; + return -1; + } + else if (error == SSL_ERROR_WANT_READ) // SSL_WANT_READ is not a crittical error. It's just a sign that + { // the internal SSL buffer is not ready to accept more data. So -1 +// out << "SSL_read() SSL_ERROR_WANT_READ"; // is returned, and the connexion will be retried as is on next +// out << std::endl; // call of readdata(). +// rslog(RSL_ALERT, pqisslzone, out.str()); + return -1; + } + else + { + out << "SSL_read() UNKNOWN ERROR: " << error; + out << std::endl; + out << "\tResetting!"; + rslog(RSL_ALERT, pqisslzone, out.str()); + std::cerr << out.str() << std::endl ; + reset(); + return -1; + } + + rslog(RSL_ALERT, pqisslzone, out.str()); + //exit(1); + } + else + total_len+=tmppktlen ; + } while(total_len < len) ; + +#ifdef PQISSL_DEBUG + std::cerr << "pqissl: have read data of length " << total_len << ", expected is " << len << std::endl ; +#endif + + if (len != total_len) + { + std::ostringstream out; + out << "pqissl::readdata()"; + out << " Full Packet Not read!" << std::endl; + out << " -> Expected len(" << len << ") actually read("; + out << total_len << ")" << std::endl; + std::cerr << out.str() ; + rslog(RSL_WARNING, pqisslzone, out.str()); + } + total_len = 0 ; // reset the packet pointer as we have finished a packet. + n_read_zero = 0; + return len;//tmppktlen; +} + + +// dummy function currently. +int pqissl::netstatus() +{ + return 1; +} + +int pqissl::isactive() +{ + return active; +} + +bool pqissl::moretoread() +{ + { + std::ostringstream out; + out << "pqissl::moretoread()"; + out << " polling socket (" << sockfd << ")"; + rslog(RSL_DEBUG_ALL, pqisslzone, out.str()); + } + + fd_set ReadFDs, WriteFDs, ExceptFDs; + FD_ZERO(&ReadFDs); + FD_ZERO(&WriteFDs); + FD_ZERO(&ExceptFDs); + + FD_SET(sockfd, &ReadFDs); + FD_SET(sockfd, &WriteFDs); + FD_SET(sockfd, &ExceptFDs); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + if (select(sockfd + 1, &ReadFDs, &WriteFDs, &ExceptFDs, &timeout) < 0) + { + rslog(RSL_ALERT, pqisslzone, + "pqissl::moretoread() Select ERROR!"); + return 0; + } + + if (FD_ISSET(sockfd, &ExceptFDs)) + { + // error - reset socket. + rslog(RSL_ALERT, pqisslzone, + "pqissl::moretoread() Select Exception ERROR!"); + + // this is a definite bad socket!. + // reset. + reset(); + return 0; + } + + if (FD_ISSET(sockfd, &WriteFDs)) + { + // write can work. + rslog(RSL_DEBUG_ALL, pqisslzone, + "pqissl::moretoread() Can Write!"); + } + else + { + // write can work. + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::moretoread() Can *NOT* Write!"); + } + + if (FD_ISSET(sockfd, &ReadFDs)) + { + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::moretoread() Data to Read!"); + return 1; + } + else + { + rslog(RSL_DEBUG_ALL, pqisslzone, + "pqissl::moretoread() No Data to Read!"); + return 0; + } + +} + +bool pqissl::cansend() +{ + rslog(RSL_DEBUG_ALL, pqisslzone, + "pqissl::cansend() polling socket!"); + + // Interestingly - This code might be portable.... + + fd_set ReadFDs, WriteFDs, ExceptFDs; + FD_ZERO(&ReadFDs); + FD_ZERO(&WriteFDs); + FD_ZERO(&ExceptFDs); + + FD_SET(sockfd, &ReadFDs); + FD_SET(sockfd, &WriteFDs); + FD_SET(sockfd, &ExceptFDs); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + if (select(sockfd + 1, &ReadFDs, &WriteFDs, &ExceptFDs, &timeout) < 0) + { + // select error. + rslog(RSL_ALERT, pqisslzone, + "pqissl::cansend() Select Error!"); + + return 0; + } + + if (FD_ISSET(sockfd, &ExceptFDs)) + { + // error - reset socket. + rslog(RSL_ALERT, pqisslzone, + "pqissl::cansend() Select Exception!"); + + // this is a definite bad socket!. + // reset. + reset(); + return 0; + } + + if (FD_ISSET(sockfd, &WriteFDs)) + { + // write can work. + rslog(RSL_DEBUG_ALL, pqisslzone, + "pqissl::cansend() Can Write!"); + return 1; + } + else + { + // write can work. + rslog(RSL_DEBUG_BASIC, pqisslzone, + "pqissl::cansend() Can *NOT* Write!"); + + return 0; + } + +} + +std::string pqissl::gethash() +{ + std::string dummyhash; + return dummyhash; +} + +/********** End of Implementation of BinInterface ******************/ + + diff --git a/libretroshare/src/pqi/pqissl.h b/libretroshare/src/pqi/pqissl.h new file mode 100644 index 000000000..5a7756c36 --- /dev/null +++ b/libretroshare/src/pqi/pqissl.h @@ -0,0 +1,214 @@ +/* + * "$Id: pqissl.h,v 1.18 2007-03-11 14:54:22 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_SSL_HEADER +#define MRK_PQI_SSL_HEADER + +#include + +// operating system specific network header. +#include "pqi/pqinetwork.h" + +#include +#include + +#include "pqi/pqi_base.h" + +#include "pqi/p3connmgr.h" + +#include "pqi/authssl.h" + +#define WAITING_NOT 0 +#define WAITING_DELAY 1 +#define WAITING_SOCK_CONNECT 2 +#define WAITING_SSL_CONNECTION 3 +#define WAITING_SSL_AUTHORISE 4 +#define WAITING_FAIL_INTERFACE 5 + +#define PQISSL_PASSIVE 0x00 +#define PQISSL_ACTIVE 0x01 + +const int PQISSL_LOCAL_FLAG = 0x01; +const int PQISSL_REMOTE_FLAG = 0x02; +const int PQISSL_DNS_FLAG = 0x04; + +/* not sure about the value? */ +const int PQISSL_UDP_FLAG = 0x02; + +/* TCP buffer size for Windows systems */ +const int WINDOWS_TCP_BUFFER_SIZE = 128 * 1024; // 128 KB + +/***************************** pqi Net SSL Interface ********************************* + * This provides the base SSL interface class, + * and handles most of the required functionality. + * + * there are a series of small fn's that can be overloaded + * to provide alternative behaviour.... + * + * Classes expected to inherit from this are: + * + * pqissllistener -> pqissllistener (tcp only) + * -> pqixpgplistener (tcp only) + * + * pqissl -> pqissltcp + * -> pqissludp + * -> pqixpgptcp + * -> pqixpgpudp + * + */ + +class pqissl; +class cert; + +class pqissllistener; + +class pqissl: public NetBinInterface +{ +public: + pqissl(pqissllistener *l, PQInterface *parent, + p3ConnectMgr *cm); +virtual ~pqissl(); + + // NetInterface +virtual int connect(struct sockaddr_in raddr); +virtual int listen(); +virtual int stoplistening(); +virtual int reset(); +virtual int disconnect(); +virtual int getConnectAddress(struct sockaddr_in &raddr); + +virtual bool connect_parameter(uint32_t type, uint32_t value); + + // BinInterface +virtual int tick(); +virtual int status(); + +virtual int senddata(void*, int); +virtual int readdata(void*, int); +virtual int netstatus(); +virtual int isactive(); +virtual bool moretoread(); +virtual bool cansend(); + +virtual int close(); /* BinInterface version of reset() */ +virtual std::string gethash(); /* not used here */ +virtual bool bandwidthLimited() { return true ; } // replace by !sameLAN to avoid bandwidth limiting on lAN + +protected: + // A little bit of information to describe + // the SSL state, this is needed + // to allow full Non-Blocking Connect behaviour. + // This fn loops through the following fns. + // to complete an SSL. + +int ConnectAttempt(); +int waiting; + +virtual int Failed_Connection(); + + // Start up connection with delay... +virtual int Delay_Connection(); + + // These two fns are overloaded for udp/etc connections. +virtual int Initiate_Connection(); +virtual int Basic_Connection_Complete(); + + // These should be identical for all cases, + // differences are achieved via the net_internal_* fns. +int Initiate_SSL_Connection(); +int SSL_Connection_Complete(); +int Authorise_SSL_Connection(); + +int Extract_Failed_SSL_Certificate(); // try to get cert anyway. + +public: + +/* Completion of the SSL connection, + * this is public, so it can be called by + * the listener (should make friends??) + */ + +int accept(SSL *ssl, int fd, struct sockaddr_in foreign_addr); + +protected: + + //protected internal fns that are overloaded for udp case. +virtual int net_internal_close(int fd) { return unix_close(fd); } +virtual int net_internal_SSL_set_fd(SSL *ssl, int fd) { return SSL_set_fd(ssl, fd); } +virtual int net_internal_fcntl_nonblock(int fd) { return unix_fcntl_nonblock(fd);} + + + /* data */ + bool active; + bool certvalid; + + // addition for udp (tcp version == ACTIVE). + int sslmode; + + SSL *ssl_connection; + int sockfd; + + pqissllistener *pqil; + struct sockaddr_in remote_addr; + + void *readpkt; + int pktlen; + int total_len ; // saves the reading state accross successive calls. + + int attempt_ts; + + // Some flags to indicate + // the status of the various interfaces + // (local), (server) + unsigned int net_attempt; + unsigned int net_failure; + unsigned int net_unreachable; + + bool sameLAN; /* flag use to allow high-speed transfers */ + + int n_read_zero; /* a counter to determine if the connection is really dead */ + time_t mReadZeroTS; /* timestamp of first READ_ZERO occurance */ + + int ssl_connect_timeout; /* timeout to ensure that we don't get stuck (can happen on udp!) */ + + uint32_t mConnectDelay; + time_t mConnectTS; + uint32_t mConnectTimeout; + time_t mTimeoutTS; + + p3ConnectMgr *mConnMgr; + +private: + // ssl only fns. +int connectInterface(sockaddr_in&); + +}; + + + + +#endif // MRK_PQI_SSL_HEADER diff --git a/libretroshare/src/pqi/pqissllistener.cc b/libretroshare/src/pqi/pqissllistener.cc new file mode 100644 index 000000000..22e3978a0 --- /dev/null +++ b/libretroshare/src/pqi/pqissllistener.cc @@ -0,0 +1,755 @@ +/* + * "$Id: pqissllistener.cc,v 1.3 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + + +#include "pqi/pqissl.h" +#include "pqi/pqissllistener.h" +#include "pqi/pqinetwork.h" +#include "pqi/sslfns.h" + +#include +#include + +#include "util/rsdebug.h" +#include + +const int pqissllistenzone = 49787; + +/* NB: This #define makes the listener open 0.0.0.0:X port instead + * of a specific port - this might help retroshare work on PCs with + * multiple interfaces or unique network setups. + * #define OPEN_UNIVERSAL_PORT 1 + */ + +#define OPEN_UNIVERSAL_PORT 1 + +/************************ PQI SSL LISTEN BASE **************************** + * + * This provides all of the basic connection stuff, + * and calls completeConnection afterwards... + * + */ + + +pqissllistenbase::pqissllistenbase(struct sockaddr_in addr, p3ConnectMgr *cm) + :laddr(addr), active(false), mConnMgr(cm) + +{ + if (!(AuthSSL::getAuthSSL()-> active())) { + pqioutput(PQL_ALERT, pqissllistenzone, + "SSL-CTX-CERT-ROOT not initialised!"); + + exit(1); + } + + setuplisten(); + return; +} + +pqissllistenbase::~pqissllistenbase() +{ + return; +} + +int pqissllistenbase::tick() +{ + status(); + // check listen port. + acceptconnection(); + return continueaccepts(); +} + +int pqissllistenbase::status() +{ + std::ostringstream out; + out << "pqissllistenbase::status(): "; + out << " Listening on port: " << ntohs(laddr.sin_port) << std::endl; + pqioutput(PQL_DEBUG_ALL, pqissllistenzone, out.str()); + return 1; +} + + + +int pqissllistenbase::setuplisten() +{ + int err; + if (active) + return -1; + + lsock = socket(PF_INET, SOCK_STREAM, 0); +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + if (lsock < 0) + { + pqioutput(PQL_ALERT, pqissllistenzone, + "pqissllistenbase::setuplisten() Cannot Open Socket!"); + + return -1; + } + + err = fcntl(lsock, F_SETFL, O_NONBLOCK); + if (err < 0) + { + std::ostringstream out; + out << "Error: Cannot make socket NON-Blocking: "; + out << err << std::endl; + pqioutput(PQL_ERROR, pqissllistenzone, out.str()); + + return -1; + } + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else //WINDOWS_SYS + if ((unsigned) lsock == INVALID_SOCKET) + { + std::ostringstream out; + out << "pqissllistenbase::setuplisten()"; + out << " Cannot Open Socket!" << std::endl; + out << "Socket Error:"; + out << socket_errorType(WSAGetLastError()) << std::endl; + pqioutput(PQL_ALERT, pqissllistenzone, out.str()); + + return -1; + } + + // Make nonblocking. + unsigned long int on = 1; + if (0 != (err = ioctlsocket(lsock, FIONBIO, &on))) + { + std::ostringstream out; + out << "pqissllistenbase::setuplisten()"; + out << "Error: Cannot make socket NON-Blocking: "; + out << err << std::endl; + out << "Socket Error:"; + out << socket_errorType(WSAGetLastError()) << std::endl; + pqioutput(PQL_ALERT, pqissllistenzone, out.str()); + + return -1; + } +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + // setup listening address. + + // fill in fconstant bits. + + laddr.sin_family = AF_INET; + + { + std::ostringstream out; + out << "pqissllistenbase::setuplisten()"; + out << "\tAddress Family: " << (int) laddr.sin_family; + out << std::endl; + out << "\tSetup Address: " << rs_inet_ntoa(laddr.sin_addr); + out << std::endl; + out << "\tSetup Port: " << ntohs(laddr.sin_port); + + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out.str()); + //std::cerr << out.str() << std::endl; + } + + /* added a call to REUSEADDR, so that we can re-open an existing socket + * when we restart_listener. + */ + + { + int on = 1; + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + if (setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) +#else //WINDOWS_SYS + if (setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)) < 0) +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + { + std::ostringstream out; + out << "pqissllistenbase::setuplisten()"; + out << " Cannot setsockopt SO_REUSEADDR!" << std::endl; + showSocketError(out); + pqioutput(PQL_ALERT, pqissllistenzone, out.str()); + std::cerr << out.str() << std::endl; + + exit(1); + } + } + +#ifdef OPEN_UNIVERSAL_PORT + struct sockaddr_in tmpaddr = laddr; + tmpaddr.sin_addr.s_addr = 0; + if (0 != (err = bind(lsock, (struct sockaddr *) &tmpaddr, sizeof(tmpaddr)))) +#else + if (0 != (err = bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr)))) +#endif + { + std::ostringstream out; + out << "pqissllistenbase::setuplisten()"; + out << " Cannot Bind to Local Address!" << std::endl; + showSocketError(out); + pqioutput(PQL_ALERT, pqissllistenzone, out.str()); + std::cerr << out.str() << std::endl; + + exit(1); + return -1; + } + else + { + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, + "pqissllistenbase::setuplisten() Bound to Address."); + } + +#ifdef WINDOWS_SYS + /* Set TCP buffer size for Windows systems */ + + int sockbufsize = 0; + int size = sizeof(int); + + err = getsockopt(lsock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size); + if (err == 0) { + std::cerr << "pqissllistenbase::setuplisten: Current TCP receive buffer size " << sockbufsize << std::endl; + } else { + std::cerr << "pqissllistenbase::setuplisten: Error getting TCP receive buffer size. Error " << err << std::endl; + } + + sockbufsize = 0; + + err = getsockopt(lsock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size); + + if (err == 0) { + std::cerr << "pqissllistenbase::setuplisten: Current TCP send buffer size " << sockbufsize << std::endl; + } else { + std::cerr << "pqissllistenbase::setuplisten: Error getting TCP send buffer size. Error " << err << std::endl; + } + + sockbufsize = WINDOWS_TCP_BUFFER_SIZE; + + err = setsockopt(lsock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, sizeof(sockbufsize)); + + if (err == 0) { + std::cerr << "pqissllistenbase::setuplisten: TCP receive buffer size set to " << sockbufsize << std::endl; + } else { + std::cerr << "pqissllistenbase::setuplisten: Error setting TCP receive buffer size. Error " << err << std::endl; + } + + err = setsockopt(lsock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, sizeof(sockbufsize)); + + if (err == 0) { + std::cerr << "pqissllistenbase::setuplisten: TCP send buffer size set to " << sockbufsize << std::endl; + } else { + std::cerr << "pqissllistenbase::setuplisten: Error setting TCP send buffer size. Error " << err << std::endl; + } +#endif + + if (0 != (err = listen(lsock, 100))) + { + std::ostringstream out; + out << "pqissllistenbase::setuplisten()"; + out << "Error: Cannot Listen to Socket: "; + out << err << std::endl; + showSocketError(out); + pqioutput(PQL_ALERT, pqissllistenzone, out.str()); + std::cerr << out.str() << std::endl; + + exit(1); + return -1; + } + else + { + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, + "pqissllistenbase::setuplisten() Listening to Socket"); + } + active = true; + return 1; +} + +int pqissllistenbase::setListenAddr(struct sockaddr_in addr) +{ + laddr = addr; + return 1; +} + +int pqissllistenbase::resetlisten() +{ + if (active) + { + // close ports etc. +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + shutdown(lsock, SHUT_RDWR); + close(lsock); +#else //WINDOWS_SYS + closesocket(lsock); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + active = false; + return 1; + } + + return 0; +} + + +int pqissllistenbase::acceptconnection() +{ + if (!active) + return 0; + // check port for any socets... + pqioutput(PQL_DEBUG_ALL, pqissllistenzone, "pqissllistenbase::accepting()"); + + // These are local but temp variables... + // can't be arsed making them all the time. + struct sockaddr_in remote_addr; + socklen_t addrlen = sizeof(remote_addr); + int fd = accept(lsock, (struct sockaddr *) &remote_addr, &addrlen); + int err = 0; + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + if (fd < 0) + { + pqioutput(PQL_DEBUG_ALL, pqissllistenzone, + "pqissllistenbase::acceptconnnection() Nothing to Accept!"); + return 0; + } + + err = fcntl(fd, F_SETFL, O_NONBLOCK); + if (err < 0) + { + std::ostringstream out; + out << "pqissllistenbase::acceptconnection()"; + out << "Error: Cannot make socket NON-Blocking: "; + out << err << std::endl; + pqioutput(PQL_ERROR, pqissllistenzone, out.str()); + + close(fd); + return -1; + } + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else //WINDOWS_SYS + if ((unsigned) fd == INVALID_SOCKET) + { + pqioutput(PQL_DEBUG_ALL, pqissllistenzone, + "pqissllistenbase::acceptconnnection() Nothing to Accept!"); + return 0; + } + + // Make nonblocking. + unsigned long int on = 1; + if (0 != (err = ioctlsocket(fd, FIONBIO, &on))) + { + std::ostringstream out; + out << "pqissllistenbase::acceptconnection()"; + out << "Error: Cannot make socket NON-Blocking: "; + out << err << std::endl; + out << "Socket Error:"; + out << socket_errorType(WSAGetLastError()) << std::endl; + pqioutput(PQL_ALERT, pqissllistenzone, out.str()); + + closesocket(fd); + return 0; + } +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + { + std::ostringstream out; + out << "Accepted Connection from "; + out << rs_inet_ntoa(remote_addr.sin_addr) << ":" << ntohs(remote_addr.sin_port); + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out.str()); + } + + // Negotiate certificates. SSL stylee. + // Allow negotiations for secure transaction. + + SSL *ssl = SSL_new(AuthSSL::getAuthSSL() -> getCTX()); + SSL_set_fd(ssl, fd); + + return continueSSL(ssl, remote_addr, true); // continue and save if incomplete. +} + +int pqissllistenbase::continueSSL(SSL *ssl, struct sockaddr_in remote_addr, bool addin) +{ + // attempt the accept again. + int fd = SSL_get_fd(ssl); + int err = SSL_accept(ssl); + if (err <= 0) + { + int ssl_err = SSL_get_error(ssl, err); + int err_err = ERR_get_error(); + + { + std::ostringstream out; + out << "pqissllistenbase::continueSSL() "; + out << "Issues with SSL Accept(" << err << ")!" << std::endl; + printSSLError(ssl, err, ssl_err, err_err, out); + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out.str()); + } + + if ((ssl_err == SSL_ERROR_WANT_READ) || + (ssl_err == SSL_ERROR_WANT_WRITE)) + { + std::ostringstream out; + out << "pqissllistenbase::continueSSL() "; + out << " Connection Not Complete!"; + out << std::endl; + + if (addin) + { + out << "pqissllistenbase::continueSSL() "; + out << "Adding SSL to incoming!"; + + // add to incomingqueue. + incoming_ssl[ssl] = remote_addr; + } + + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out.str()); + + // zero means still continuing.... + return 0; + } + + /* we have failed -> get certificate if possible */ + Extract_Failed_SSL_Certificate(ssl, &remote_addr); + + // other wise delete ssl connection. + // kill connection.... + // so it will be removed from cache. + SSL_shutdown(ssl); + + // close socket??? +/************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + shutdown(fd, SHUT_RDWR); + close(fd); +#else //WINDOWS_SYS + closesocket(fd); +#endif +/************************** WINDOWS/UNIX SPECIFIC PART ******************/ + // free connection. + SSL_free(ssl); + + std::ostringstream out; + out << "Read Error on the SSL Socket"; + out << std::endl; + out << "Shutting it down!" << std::endl; + pqioutput(PQL_WARNING, pqissllistenzone, out.str()); + + // failure -1, pending 0, sucess 1. + return -1; + } + + // if it succeeds + if (0 < completeConnection(fd, ssl, remote_addr)) + { + return 1; + } + + /* else we shut it down! */ + pqioutput(PQL_WARNING, pqissllistenzone, + "pqissllistenbase::completeConnection() Failed!"); + + // delete ssl connection. + SSL_shutdown(ssl); + + // close socket??? +/************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + shutdown(fd, SHUT_RDWR); + close(fd); +#else //WINDOWS_SYS + closesocket(fd); +#endif +/************************** WINDOWS/UNIX SPECIFIC PART ******************/ + // free connection. + SSL_free(ssl); + + std::ostringstream out; + out << "Shutting it down!" << std::endl; + pqioutput(PQL_WARNING, pqissllistenzone, out.str()); + + // failure -1, pending 0, sucess 1. + return -1; +} + + +int pqissllistenbase::Extract_Failed_SSL_Certificate(SSL *ssl, struct sockaddr_in *inaddr) +{ + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, + "pqissllistenbase::Extract_Failed_SSL_Certificate()"); + + // Get the Peer Certificate.... + X509 *peercert = SSL_get_peer_certificate(ssl); + + if (peercert == NULL) + { + pqioutput(PQL_WARNING, pqissllistenzone, + "pqissllistenbase::Extract_Failed_SSL_Certificate() Peer Didnt Give Cert"); + return -1; + } + + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, + "pqissllistenbase::Extract_Failed_SSL_Certificate() Have Peer Cert - Registering"); + + // save certificate... (and ip locations) + // false for outgoing.... + AuthSSL::getAuthSSL()->FailedCertificate(peercert, true); + + return 1; +} + + +int pqissllistenbase::continueaccepts() +{ + + // for each of the incoming sockets.... call continue. + std::map::iterator it, itd; + + for(it = incoming_ssl.begin(); it != incoming_ssl.end();) + { + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, + "pqissllistenbase::continueaccepts() Continuing SSL"); + if (0 != continueSSL(it->first, it->second, false)) + { + pqioutput(PQL_DEBUG_ALERT, pqissllistenzone, + "pqissllistenbase::continueaccepts() SSL Complete/Dead!"); + + /* save and increment -> so we can delete */ + itd = it++; + incoming_ssl.erase(itd); + } + else + { + it++; + } + } + return 1; +} + + +/************************ PQI SSL LISTENER **************************** + * + * This is the standard pqissl listener interface.... + * + * this class only allows connections from + * specific certificates, which are pre specified. + * + */ + +pqissllistener::pqissllistener(struct sockaddr_in addr, p3ConnectMgr *cm) + :pqissllistenbase(addr, cm) +{ + return; +} + +pqissllistener::~pqissllistener() +{ + return; +} + +int pqissllistener::addlistenaddr(std::string id, pqissl *acc) +{ + std::map::iterator it; + + std::ostringstream out; + + out << "Adding to Cert Listening Addresses Id: " << id << std::endl; + out << "Current Certs:" << std::endl; + for(it = listenaddr.begin(); it != listenaddr.end(); it++) + { + out << id << std::endl; + if (it -> first == id) + { + out << "pqissllistener::addlistenaddr()"; + out << "Already listening for Certificate!"; + out << std::endl; + + pqioutput(PQL_DEBUG_ALERT, pqissllistenzone, out.str()); + return -1; + + } + } + + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out.str()); + + // not there can accept it! + listenaddr[id] = acc; + return 1; +} + +int pqissllistener::removeListenPort(std::string id) +{ + // check where the connection is coming from. + // if in list of acceptable addresses, + // + // check if in list. + std::map::iterator it; + for(it = listenaddr.begin();it!=listenaddr.end();it++) + { + if (it->first == id) + { + listenaddr.erase(it); + + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, + "pqissllisten::removeListenPort() Success!"); + return 1; + } + } + + pqioutput(PQL_WARNING, pqissllistenzone, + "pqissllistener::removeListenPort() Failed to Find a Match"); + + return -1; +} + + +int pqissllistener::status() +{ + pqissllistenbase::status(); + // print certificates we are listening for. + std::map::iterator it; + + std::ostringstream out; + out << "pqissllistener::status(): "; + out << " Listening (" << ntohs(laddr.sin_port) << ") for Certs:" << std::endl; + for(it = listenaddr.begin(); it != listenaddr.end(); it++) + { + out << it -> first << std::endl; + } + pqioutput(PQL_DEBUG_ALL, pqissllistenzone, out.str()); + + return 1; +} + +int pqissllistener::completeConnection(int fd, SSL *ssl, struct sockaddr_in &remote_addr) +{ + + // Get the Peer Certificate.... + X509 *peercert = SSL_get_peer_certificate(ssl); + + if (peercert == NULL) + { + pqioutput(PQL_WARNING, pqissllistenzone, + "pqissllistener::completeConnection() Peer Did Not Provide Cert!"); + + // failure -1, pending 0, sucess 1. + // pqissllistenbase will shutdown! + return -1; + } + + // Check cert. + std::string newPeerId; + + + /**** + * As the validation is actually done before this... + * we should only need to call CheckCertificate here! + ****/ + + bool certOk = AuthSSL::getAuthSSL()->ValidateCertificate(peercert, newPeerId); + + bool found = false; + std::map::iterator it; + + // Let connected one through as well! if ((npc == NULL) || (npc -> Connected())) + if (!certOk) + { + pqioutput(PQL_WARNING, pqissllistenzone, + "pqissllistener::completeConnection() registerCertificate Failed!"); + + // bad - shutdown. + // pqissllistenbase will shutdown! + X509_free(peercert); + + return -1; + } + else + { + std::ostringstream out; + + out << "pqissllistener::continueSSL()" << std::endl; + out << "checking: " << newPeerId << std::endl; + // check if cert is in our list..... + for(it = listenaddr.begin();(found!=true) && (it!=listenaddr.end());) + { + out << "\tagainst: " << it->first << std::endl; + if (it -> first == newPeerId) + { + // accept even if already connected. + out << "\t\tMatch!"; + found = true; + } + else + { + it++; + } + } + + pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out.str()); + } + + if (found == false) + { + std::ostringstream out; + out << "No Matching Certificate"; + out << " for Connection:" << rs_inet_ntoa(remote_addr.sin_addr); + out << std::endl; + out << "pqissllistenbase: Will shut it down!" << std::endl; + pqioutput(PQL_WARNING, pqissllistenzone, out.str()); + + // but as it passed the authentication step, + // we can add it into the AuthSSL, and mConnMgr. + + AuthSSL::getAuthSSL()->CheckCertificate(newPeerId, peercert); + + /* now need to get GPG id too */ + std::string pgpid = getX509CNString(peercert->cert_info->issuer); + mConnMgr->addFriend(newPeerId, pgpid); + + X509_free(peercert); + return -1; + } + + pqissl *pqis = it -> second; + + // dont remove from the list of certificates. + // want to allow a new connection to replace a faulty one! + // listenaddr.erase(it); + + // timestamp + // done in sslroot... npc -> lr_timestamp = time(NULL); + + // hand off ssl conection. + pqis -> accept(ssl, fd, remote_addr); + return 1; +} + + + + diff --git a/libretroshare/src/pqi/pqissllistener.h b/libretroshare/src/pqi/pqissllistener.h new file mode 100644 index 000000000..59edc8522 --- /dev/null +++ b/libretroshare/src/pqi/pqissllistener.h @@ -0,0 +1,117 @@ +/* + * "$Id: pqissllistener.h,v 1.2 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_SSL_LISTEN_HEADER +#define MRK_PQI_SSL_LISTEN_HEADER + +#include + +// operating system specific network header. +#include "pqi/pqinetwork.h" + +#include +#include + +#include "pqi/pqi_base.h" +#include "pqi/pqilistener.h" + +#include "pqi/authssl.h" + +/***************************** pqi Net SSL Interface ********************************* + */ + +class pqissl; + +class pqissllistenbase: public pqilistener +{ + public: + + + pqissllistenbase(struct sockaddr_in addr, p3ConnectMgr *cm); +virtual ~pqissllistenbase(); + +/*************************************/ +/* LISTENER INTERFACE **/ + +virtual int tick(); +virtual int status(); +virtual int setListenAddr(struct sockaddr_in addr); +virtual int setuplisten(); +virtual int resetlisten(); + +/*************************************/ + +int acceptconnection(); +int continueaccepts(); +int continueSSL(SSL *ssl, struct sockaddr_in remote_addr, bool); + + +virtual int completeConnection(int sockfd, SSL *in_connection, struct sockaddr_in &raddr) = 0; + + protected: + + struct sockaddr_in laddr; + + private: + + // fn to get cert, anyway +int Extract_Failed_SSL_Certificate(SSL *ssl, struct sockaddr_in *inaddr); + + bool active; + int lsock; + + std::map incoming_ssl; + + protected: + + p3ConnectMgr *mConnMgr; + +}; + + +class pqissllistener: public pqissllistenbase +{ + public: + + pqissllistener(struct sockaddr_in addr, p3ConnectMgr *cm); +virtual ~pqissllistener(); + +int addlistenaddr(std::string id, pqissl *acc); +int removeListenPort(std::string id); + +//virtual int tick(); +virtual int status(); + +virtual int completeConnection(int sockfd, SSL *in_connection, struct sockaddr_in &raddr); + + private: + + std::map listenaddr; +}; + + +#endif // MRK_PQI_SSL_LISTEN_HEADER diff --git a/libretroshare/src/pqi/pqisslpersongrp.cc b/libretroshare/src/pqi/pqisslpersongrp.cc new file mode 100644 index 000000000..01753dcda --- /dev/null +++ b/libretroshare/src/pqi/pqisslpersongrp.cc @@ -0,0 +1,119 @@ +/* + * libretroshare/src/pqi: pqisslpersongrp.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "util/rsdebug.h" + +#include "pqi/pqisslpersongrp.h" +#include "pqi/authssl.h" + + +const int pqipersongrpzone = 354; + +/**** + * #define PQI_DISABLE_UDP 1 + ***/ + +/********************************** SSL Specific features ***************************/ + +#include "pqi/pqissl.h" +#include "pqi/pqissllistener.h" + +#ifndef PQI_DISABLE_TUNNEL +#include "pqi/pqissltunnel.h" +#endif + +#ifndef PQI_DISABLE_UDP + #include "pqi/pqissludp.h" +#endif + + +pqilistener * pqisslpersongrp::createListener(struct sockaddr_in laddr) +{ + pqilistener *listener = new pqissllistener(laddr, mConnMgr); + return listener; +} + +pqiperson * pqisslpersongrp::createPerson(std::string id, pqilistener *listener) +{ + { + std::ostringstream out; + out << "pqipersongrp::createPerson() PeerId: " << id; + pqioutput(PQL_DEBUG_BASIC, pqipersongrpzone, out.str()); + } + + pqiperson *pqip = new pqiperson(id, this); + pqissl *pqis = new pqissl((pqissllistener *) listener, pqip, mConnMgr); + + /* construct the serialiser .... + * Needs: + * * FileItem + * * FileData + * * ServiceGeneric + */ + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + rss->addSerialType(new RsCacheItemSerialiser()); + rss->addSerialType(new RsServiceSerialiser()); + + pqiconnect *pqisc = new pqiconnect(rss, pqis); + + pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); + +#ifndef PQI_DISABLE_TUNNEL + pqissltunnel *pqitun = new pqissltunnel(pqip, mConnMgr); + + RsSerialiser *rss3 = new RsSerialiser(); + rss3->addSerialType(new RsFileItemSerialiser()); + rss3->addSerialType(new RsCacheItemSerialiser()); + rss3->addSerialType(new RsServiceSerialiser()); + pqiconnect *pqicontun = new pqiconnect(rss3, pqitun); + pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); +#endif + +#ifndef PQI_DISABLE_UDP + pqissludp *pqius = new pqissludp(pqip, mConnMgr); + + RsSerialiser *rss2 = new RsSerialiser(); + rss2->addSerialType(new RsFileItemSerialiser()); + rss2->addSerialType(new RsCacheItemSerialiser()); + rss2->addSerialType(new RsServiceSerialiser()); + + pqiconnect *pqiusc = new pqiconnect(rss2, pqius); + + // add a ssl + proxy interface. + // Add Proxy First. + pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); +#endif + + return pqip; +} + + +/********************************** SSL Specific features ***************************/ + + diff --git a/libretroshare/src/pqi/pqisslpersongrp.h b/libretroshare/src/pqi/pqisslpersongrp.h new file mode 100644 index 000000000..7cff11621 --- /dev/null +++ b/libretroshare/src/pqi/pqisslpersongrp.h @@ -0,0 +1,48 @@ +/* + * libretroshare/src/pqi: pqisslpersongrp.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_SSL_PERSON_HANDLER_HEADER +#define MRK_PQI_SSL_PERSON_HANDLER_HEADER + +#include "pqi/pqipersongrp.h" + +class pqisslpersongrp: public pqipersongrp +{ + public: + pqisslpersongrp(SecurityPolicy *pol, unsigned long flags) + :pqipersongrp(pol, flags) { return; } + + protected: + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +virtual pqilistener *createListener(struct sockaddr_in laddr); +virtual pqiperson *createPerson(std::string id, pqilistener *listener); + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +}; + + +#endif // MRK_PQI_SSL_PERSON_HANDLER_HEADER diff --git a/libretroshare/src/pqi/pqissltunnel.cc b/libretroshare/src/pqi/pqissltunnel.cc new file mode 100644 index 000000000..720cf6c7d --- /dev/null +++ b/libretroshare/src/pqi/pqissltunnel.cc @@ -0,0 +1,565 @@ +/* + * "$Id: pqissl.cc,v 1.28 2007-03-17 19:32:59 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + + +#include "pqi/pqissltunnel.h" +#include "pqi/pqinetwork.h" + +//#include "services/p3tunnel.h" + +#include "util/rsnet.h" +#include "util/rsdebug.h" + +#include +#include +#include + +#include + +const int pqisslzone = 37714; + +#define TUNNEL_WAITING_NOT 0 +#define TUNNEL_WAITING_DELAY 1 +#define TUNNEL_WAITING_SPAM_HANDSHAKE 2 +#define TUNNEL_WAITING_RETURN_HANDSHAKE 3 + + +#define TUNNEL_PASSIVE 0x00 +#define TUNNEL_ACTIVE 0x01 + +#define TUNNEL_START_CONNECTION_DELAY 1 +#define TUNNEL_PING_TIMEOUT 6 +#define TUNNEL_REPEAT_PING_TIME 2 +#define TUNNEL_TIMEOUT_AFTER_RESET 30 + +#define TUNNEL_TRY_OTHER_CONNECTION_INTERVAL 190 //let's try a normal tcp or udp connection every 190 sec + +//const int TUNNEL_LOCAL_FLAG = 0x01; +//const int TUNNEL_REMOTE_FLAG = 0x02; +//const int TUNNEL_UDP_FLAG = 0x02; +// +//static const int PQISSL_MAX_READ_ZERO_COUNT = 20; +//static const int PQISSL_SSL_CONNECT_TIMEOUT = 30; + +/********** PQI SSL STUFF ****************************************** + * + * A little note on the notifyEvent(FAILED).... + * + * this is called from + * (1) reset if needed! + * (2) Determine_Remote_Address (when all options have failed). + * + * reset() is only called when a TCP/SSL connection has been + * established, and there is an error. If there is a failed TCP + * connection, then an alternative address can be attempted. + * + * reset() is called from + * (1) destruction. + * (2) disconnect() + * (3) bad waiting state. + * + * // TCP/or SSL connection already established.... + * (5) pqissltunnel::SSL_Connection_Complete() <- okay -> cos we made a TCP connection already. + * (6) pqissltunnel::accept() <- okay cos something went wrong. + * (7) moretoread()/cansend() <- okay cos + * + */ + +pqissltunnel::pqissltunnel(PQInterface *parent, p3ConnectMgr *cm, p3tunnel *p3t) + :NetBinInterface(parent, parent->PeerId()), mConnMgr(cm) +{ + active = false; + waiting = TUNNEL_WAITING_NOT; + + { + std::ostringstream out; + out << "pqissltunnel for PeerId: " << PeerId(); + rslog(RSL_ALERT, pqisslzone, out.str()); + } + +// if (!(AuthSSL::getAuthSSL()->isAuthenticated(PeerId()))) { +// rslog(RSL_ALERT, pqisslzone, +// "pqissltunnel::Warning Certificate Not Approved!"); +// rslog(RSL_ALERT, pqisslzone, +// "\t pqissltunnel will not initialise...."); +// } + mP3tunnel = p3t; + current_data_offset = 0; + curent_data_packet.length = 0; + + return; +} + +pqissltunnel::~pqissltunnel() { + rslog(RSL_ALERT, pqisslzone, + "pqissltunnel::~pqissltunnel -> destroying pqissl"); + //stoplistening(); + reset(); + return; +} + + +/********** Implementation of NetInterface *************************/ + +int pqissltunnel::connect(struct sockaddr_in raddr) { +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::connect() called : " << PeerId() << std::endl; +#endif + last_normal_connection_attempt_time = time(NULL); + mConnectTS = time(NULL); + resetTime = time(NULL) - TUNNEL_TIMEOUT_AFTER_RESET; + waiting = TUNNEL_WAITING_DELAY; + return 0; +} + +// tells pqilistener to listen for us. +int pqissltunnel::listen() +{ + //no use + return 0; +} + +int pqissltunnel::stoplistening() +{ + //no use + return 1; +} + +int pqissltunnel::disconnect() +{ +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::disconnect() called : " << PeerId() << std::endl; +#endif + return reset(); +} + +/* BinInterface version of reset() for pqistreamer */ +int pqissltunnel::close() +{ + return reset(); +} + +// put back on the listening queue. +int pqissltunnel::reset() +{ +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::reset() called : " << PeerId() << std::endl; +#endif + + if (active) + { +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::reset() Reset Required because tunnel was activated !" << std::endl; + std::cerr << "pqissltunnel::reset() Will Attempt notifyEvent(FAILED)" << std::endl; +#endif + waiting = TUNNEL_WAITING_NOT; + active = false; + resetTime = time(NULL); + // clean up the streamer + if (parent()) { +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::reset() notifyEvent(FAILED)" << std::endl; +#endif + parent() -> notifyEvent(this, NET_CONNECT_FAILED); + } + } else { +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::reset() Reset not required because tunnel was not activated !" << std::endl; +#endif + } + return 1; +} + +int pqissltunnel::getConnectAddress(struct sockaddr_in &raddr) { + sockaddr_clear(&raddr); + return 0; +} + +bool pqissltunnel::connect_parameter(uint32_t type, uint32_t value) +{ + { + std::ostringstream out; + out << "pqissltunnel::connect_parameter() (not used) Peer: " << PeerId(); + out << " type: " << type << "value: " << value; + rslog(RSL_DEBUG_ALL, pqisslzone, out.str()); + } + + if (type == NET_PARAM_CONNECT_DELAY) + { + std::ostringstream out; + out << "pqissltunnel::connect_parameter() (not used) Peer: " << PeerId(); + out << " DELAY: " << value; + rslog(RSL_WARNING, pqisslzone, out.str()); + + return true; + } + else if (type == NET_PARAM_CONNECT_TIMEOUT) + { + std::ostringstream out; + out << "pqissltunnel::connect_parameter() (not used) Peer: " << PeerId(); + out << " TIMEOUT: " << value; + rslog(RSL_WARNING, pqisslzone, out.str()); + + return true; + } + return false; +} + + +/********** End of Implementation of NetInterface ******************/ +/********** Implementation of BinInterface ************************** + * Only status() + tick() are here ... as they are really related + * to the NetInterface, and not the BinInterface, + * + */ + +/* returns ... + * -1 if inactive. + * 0 if connecting. + * 1 if connected. + */ + +int pqissltunnel::status() +{ +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::status() called." << std::endl; +#endif + + if (active) { + std::cerr << " active: " << std::endl; + // print out connection. + std::cerr << "dest : " << PeerId(); + std::cerr << "relay : " << relayPeerId; + std::cerr << std::endl; + } + else { + std::cerr << " Waiting for connection!" << std::endl; + } + + if (active) { + return 1; + } else if (waiting > 0) { + return 0; + } + return -1; +} + + +int pqissltunnel::tick() +{ + if (active && ((time(NULL) - last_normal_connection_attempt_time) > TUNNEL_TRY_OTHER_CONNECTION_INTERVAL)) { + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::tick() attempt to connect through a normal tcp or udp connection." << std::endl; + #endif + last_normal_connection_attempt_time = time(NULL); + mConnMgr->retryConnect(parent()->PeerId()); + } + + if (active && ((time(NULL) - last_ping_send_time) > TUNNEL_REPEAT_PING_TIME)) { + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::tick() sending a ping." << std::endl; + #endif + last_ping_send_time = time(NULL);; + mP3tunnel->pingTunnelConnection(relayPeerId, parent()->PeerId()); + } + + if (active && ((time(NULL) - last_packet_time) > TUNNEL_PING_TIMEOUT)) { + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::tick() no packet received since PING_RECEIVE_TIME_OUT. Connection is broken." << std::endl; + #endif + reset(); + } + // continue existing connection attempt. + if (!active) + { + // if we are waiting.. continue the connection (only) + if (waiting > 0) + { + #ifdef DEBUG_PQISSL_TUNNEL + //std::cerr << "pqissltunnel::tick() Continuing Connection Attempt!" << std::endl; + #endif + ConnectAttempt(); + return 1; + } + } + return 1; +} + +/********** End of Implementation of BinInterface ******************/ +/********** Internals of Tunnel Connection ****************************/ +int pqissltunnel::ConnectAttempt() +{ + #ifdef DEBUG_PQISSL_TUNNEL + //std::cerr << "pqissltunnel::ConnectAttempt() called." << std::endl; + #endif + switch(waiting) + { + case TUNNEL_WAITING_NOT: + active = true; /* we're starting this one */ + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::ConnectAttempt() STATE = Not Waiting." << std::endl; + #endif + + case TUNNEL_WAITING_DELAY: + if ((time(NULL) - mConnectTS) > TUNNEL_START_CONNECTION_DELAY) { + waiting = TUNNEL_WAITING_SPAM_HANDSHAKE; + } + + break; + + case TUNNEL_WAITING_SPAM_HANDSHAKE: + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::ConnectAttempt() STATE = Waiting for spamming handshake." << std::endl; + #endif + + spam_handshake(); + waiting = TUNNEL_WAITING_RETURN_HANDSHAKE; + break; + + case TUNNEL_WAITING_RETURN_HANDSHAKE: + if ((time(NULL) - mConnectTS) < TUNNEL_PING_TIMEOUT) { + #ifdef DEBUG_PQISSL_TUNNEL + //std::cerr << "pqissltunnel::ConnectAttempt() STATE = Waiting for handshake reply." << std::endl; + #endif + } else { + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::ConnectAttempt() no handshake reply during imparing time. Connection failed." << std::endl; + #endif + waiting = TUNNEL_WAITING_NOT; + active = false; + // clean up the streamer + if (parent()) { +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::reset() Reset not required because tunnel was not activated !" << std::endl; +#endif + parent() -> notifyEvent(this, NET_CONNECT_FAILED); + } + } + break; + + + default: + std::cerr << "pqissltunnel::ConnectAttempt() STATE = Unknown - Reset" << std::endl; + + reset(); + break; + } + return -1; +} + +void pqissltunnel::spam_handshake() +{ +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::spam_handshake() starting to spam handshake tunnel packet." << std::endl; +#endif + std::list peers; + mConnMgr->getOnlineList(peers); + std::list::iterator it = peers.begin(); + while (it != peers.end()) { + //send a handshake to the destination through the relay + if (*it != parent()->PeerId()) { + mP3tunnel->initiateHandshake(*it, parent()->PeerId()); + } + ++it; + } +} + +void pqissltunnel::addIncomingPacket(void* encoded_data, int encoded_data_length) { + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::addIncomingPacket() called." << std::endl; + #endif + last_packet_time = time(NULL); + + data_with_length data_w_l; + data_w_l.data = (void*)malloc(encoded_data_length) ; + memcpy(data_w_l.data, encoded_data, encoded_data_length); + data_w_l.length = encoded_data_length; + data_packet_queue.push_front(data_w_l); +} + +void pqissltunnel::IncommingPingPacket() { + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::IncommingPingPacket() called" << std::endl; + #endif + + last_packet_time = time(NULL); +} + +void pqissltunnel::IncommingHanshakePacket(std::string incRelayPeerId) { + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::IncommingHanshakePacket() called with incRelayPeerId : " << incRelayPeerId << std::endl; + #endif + + if ((time(NULL) - resetTime) <= TUNNEL_TIMEOUT_AFTER_RESET) { +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::IncommingHanshakePacket() a reset occured, don't activate the connection." << std::endl; +#endif + return; + } + last_packet_time = time(NULL); + + std::string message = "pqissltunnel::IncommingHanshakePacket() mConnMgr->isOnline(parent()->PeerId() : "; + if (mConnMgr->isOnline(parent()->PeerId())) { + message += "true"; + } else { + message += "false"; + } + rslog(RSL_DEBUG_BASIC, pqisslzone, message); + + if (active || mConnMgr->isOnline(parent()->PeerId())) { + //connection is already active, or peer is already online don't do nothing + return; + } + //TODO : check if cert is in order before accepting + + //activate connection + waiting = TUNNEL_WAITING_NOT; + active = true; + relayPeerId = incRelayPeerId; + + if (parent()) + { + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::IncommingHanshakePacket() Notify the pqiperson.... (Both Connect/Receive)" << parent()->PeerId() < notifyEvent(this, NET_CONNECT_SUCCESS); + } +} +/********** Implementation of BinInterface ************************** + * All the rest of the BinInterface. + * + */ + +int pqissltunnel::senddata(void *data, int len) +{ +#ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::senddata() called" << std::endl ; +#endif + if (!active) { + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::senddata() connection is not active" << std::endl ; + #endif + return -1; + } + + int outlen = 0; + void * out; + if (!AuthSSL::getAuthSSL()->encrypt(out, outlen, data, len, parent()->PeerId())) { + std::cerr << "pqissltunnel::senddata() problem while crypting packet, ignoring it." << std::endl; + return -1; + } + + #ifdef DEBUG_PQISSL_TUNNEL + std::cerr << "pqissltunnel::senddata() sending item via p3tunnel" << std::endl ; + #endif + mP3tunnel->sendTunnelData(parent()->PeerId(), relayPeerId, out, outlen); + + return len; +} + +int pqissltunnel::readdata(void *data, int len) +{ +#ifdef DEBUG_PQISSL_TUNNEL + std::cout << "pqissltunnel::readdata() called" << std::endl ; +#endif + //let's see if we got a new packet to read + if (current_data_offset >= curent_data_packet.length) { + //current packet has finished reading, let's pop out a new packet if available + if (data_packet_queue.size() ==0) { + //no more to read + return -1; + } else { + //let's read a new packet + current_data_offset = 0; + //decrypt one packet from the queue and put it into the current data packet. + if (!AuthSSL::getAuthSSL()->decrypt(curent_data_packet.data, curent_data_packet.length, data_packet_queue.back().data, data_packet_queue.back().length)) { + std::cerr << "pqissltunnel::readdata() problem while decrypting packet, ignoring it." << std::endl; + curent_data_packet.length = 0; + return -1; + } + data_packet_queue.pop_back(); + } + } + + if (current_data_offset < curent_data_packet.length) { +#ifdef DEBUG_PQISSL_TUNNEL + std::cout << "pqissltunnel::readdata() reading..." << std::endl ; + std::cout << "pqissltunnel::readdata() len : " << len << std::endl ; + std::cout << "pqissltunnel::readdata() current_data_offset : " << current_data_offset << std::endl ; + std::cout << "pqissltunnel::readdata() curent_data_packet.length : " << curent_data_packet.length << std::endl ; + std::cerr << "pqissltunnel::readdata() getRsItemSize(curent_data_packet.data) : " << getRsItemSize(curent_data_packet.data) << std::endl; +#endif + + //read from packet + memcpy(data, (void*)((unsigned long int)curent_data_packet.data+(unsigned long int)current_data_offset), len); + current_data_offset += len; + + return len; + } + + return -1; +} + +// dummy function currently. +int pqissltunnel::netstatus() +{ + return 1; +} + +int pqissltunnel::isactive() +{ + return active; +} + +bool pqissltunnel::moretoread() +{ + //let's see if we got an old packet or a new packet to read + if (current_data_offset >= curent_data_packet.length && data_packet_queue.size() ==0) { + return false; + } else { + return true; + } +} + +bool pqissltunnel::cansend() +{ + if (!mConnMgr->isOnline(relayPeerId)) { + reset(); + return false; + } + return true; +} + +std::string pqissltunnel::gethash() +{ + std::string dummyhash; + return dummyhash; +} + +/********** End of Implementation of BinInterface ******************/ diff --git a/libretroshare/src/pqi/pqissltunnel.h b/libretroshare/src/pqi/pqissltunnel.h new file mode 100644 index 000000000..ef3ae6987 --- /dev/null +++ b/libretroshare/src/pqi/pqissltunnel.h @@ -0,0 +1,145 @@ +/* + * "$Id: pqissl.h,v 1.18 2007-03-11 14:54:22 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_SSL_TUNNEL_HEADER +#define MRK_PQI_SSL_TUNNEL_HEADER + + +#include + +// operating system specific network header. +//#include "pqi/pqinetwork.h" + +#include "pqi/pqi_base.h" + +#include "pqi/p3connmgr.h" + +#include "services/p3tunnel.h" + +#include "pqi/authssl.h" + +/***************************** pqi Net SSL Interface ********************************* + * This provides the base SSL interface class, + * and handles most of the required functionality. + * + * there are a series of small fn's that can be overloaded + * to provide alternative behaviour.... + * + * Classes expected to inherit from this are: + * + * pqissllistener -> pqissllistener (tcp only) + * -> pqixpgplistener (tcp only) + * + * pqissl -> pqissltcp + * -> pqissludp + * -> pqixpgptcp + * -> pqixpgpudp + * + */ + +class pqissl; +class cert; + +class pqissltunnellistener; + +struct data_with_length { + int length; + void *data; +}; + +class pqissltunnel: public NetBinInterface +{ +public: + pqissltunnel(PQInterface *parent, p3ConnectMgr *cm, p3tunnel *p3t); +virtual ~pqissltunnel(); + + // NetInterface + +//the addr is not used for the tunnel +virtual int connect(struct sockaddr_in raddr); +virtual int listen(); +virtual int stoplistening(); +virtual int reset(); +virtual int disconnect(); +virtual int getConnectAddress(struct sockaddr_in &raddr); + +virtual bool connect_parameter(uint32_t type, uint32_t value); + + // BinInterface +virtual int tick(); +virtual int status(); + +virtual int senddata(void*, int); +virtual int readdata(void*, int); +virtual int netstatus(); +virtual int isactive(); +virtual bool moretoread(); +virtual bool cansend(); + +virtual int close(); /* BinInterface version of reset() */ +virtual std::string gethash(); /* not used here */ +virtual bool bandwidthLimited() { return true ; } // replace by !sameLAN to avoid bandwidth limiting on lAN + +//called by the p3tunnel service to add incoming packets that will be read by the read data function. +void addIncomingPacket(void* encoded_data, int data_length); +void IncommingPingPacket(); +void IncommingHanshakePacket(std::string incRelayPeerId); + +private: + //if no packet (last_time_packet_time) is received since PING_RECEIVE_TIME_OUT, let's assume the connection is broken + int last_normal_connection_attempt_time; + + //if no packet (last_time_packet_time) is received since PING_RECEIVE_TIME_OUT, let's assume the connection is broken + int last_packet_time; + + //send a ping on a regular basis + int last_ping_send_time; + + int ConnectAttempt(); + void spam_handshake(); + int waiting; + bool active; + time_t resetTime; + pqissltunnellistener *pqil; + + /* Need Certificate specific functions here! */ + time_t mConnectTS; + + p3ConnectMgr *mConnMgr; + + p3tunnel *mP3tunnel; + + std::list data_packet_queue; + data_with_length curent_data_packet; + int current_data_offset; + + //tunneling details + std::string relayPeerId; + +}; + +#endif // MRK_PQI_SSL_HEADER diff --git a/libretroshare/src/pqi/pqissludp.cc b/libretroshare/src/pqi/pqissludp.cc new file mode 100644 index 000000000..5f9030dd6 --- /dev/null +++ b/libretroshare/src/pqi/pqissludp.cc @@ -0,0 +1,515 @@ +/* + * "$Id: pqissludp.cc,v 1.16 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + + +#include "pqi/pqissludp.h" +#include "pqi/pqinetwork.h" + +#include "tcponudp/tou.h" +#include "tcponudp/bio_tou.h" + +#include +#include + +#include + +#include "util/rsdebug.h" +#include "util/rsnet.h" + +const int pqissludpzone = 3144; + + /* a final timeout, to ensure this never blocks completely + * 300 secs to complete udp/tcp/ssl connection. + * This is long as the udp connect can take some time. + */ + +static const uint32_t PQI_SSLUDP_DEF_CONN_PERIOD = 300; /* 5 minutes? */ + +/********** PQI SSL UDP STUFF **************************************/ + +pqissludp::pqissludp(PQInterface *parent, p3ConnectMgr *cm) + :pqissl(NULL, parent, cm), tou_bio(NULL), + listen_checktime(0), mConnectPeriod(PQI_SSLUDP_DEF_CONN_PERIOD) +{ + sockaddr_clear(&remote_addr); + return; +} + + +pqissludp::~pqissludp() +{ + rslog(RSL_ALERT, pqissludpzone, + "pqissludp::~pqissludp -> destroying pqissludp"); + + /* must call reset from here, so that the + * virtual functions will still work. + * -> as they stop working in base class destructor. + * + * This means that reset() will be called twice, but this should + * be harmless. + */ + stoplistening(); /* remove from p3proxy listenqueue */ + reset(); + + if (tou_bio) // this should be in the reset? + { + BIO_free(tou_bio); + } + return; +} + +int pqissludp::reset() +{ + /* reset for next time.*/ + return pqissl::reset(); +} + + + /* <===================== UDP Difference *******************/ + // The Proxy Version takes a few more step + // + // connectInterface is sent via message from the proxy. + // and is set here. + /* <===================== UDP Difference *******************/ + +int pqissludp::attach() +{ + // IN THE IMPROVED TOU LIBRARY, we need to be careful with the tou_socket PARAMETERS. + // For now, this should do! + sockfd = tou_socket(0,TOU_RECEIVER_TYPE_UDPPEER,0); + if (0 > sockfd) + { + rslog(RSL_WARNING, pqissludpzone, + "pqissludp::attach() failed to create a socket"); + return -1; + } + + // setup remote address + rslog(RSL_WARNING, pqissludpzone, + "pqissludp::attach() Opened Local Udp Socket"); + + return 1; +} + + +// The Address determination is done centrally +int pqissludp::Initiate_Connection() +{ + int err; + + attach(); /* open socket */ + remote_addr.sin_family = AF_INET; + + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::Initiate_Connection() Attempting Outgoing Connection...."); + + /* decide if we're active or passive */ + if (PeerId() < mConnMgr->getOwnId()) + { + sslmode = PQISSL_ACTIVE; + } + else + { + sslmode = PQISSL_PASSIVE; + } + + if (waiting != WAITING_DELAY) + { + rslog(RSL_WARNING, pqissludpzone, + "pqissludp::Initiate_Connection() Already Attempt in Progress!"); + return -1; + } + + if (sockfd < 0) + { + rslog(RSL_ALERT, pqissludpzone, + "pqissludp::Initiate_Connection() Socket Creation Failed!"); + waiting = WAITING_FAIL_INTERFACE; + return -1; + } + + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::Initiate_Connection() Opening Socket"); + + { + std::ostringstream out; + out << "pqissludp::Initiate_Connection() "; + out << "Connecting To: " << PeerId(); + out << " via: " << rs_inet_ntoa(remote_addr.sin_addr) << ":"; + out << ntohs(remote_addr.sin_port) << " "; + if (sslmode) + { + out << "ACTIVE Connect (SSL_Connect)"; + } + else + { + out << "PASSIVE Connect (SSL_Accept)"; + } + rslog(RSL_WARNING, pqissludpzone, out.str()); + } + + if (remote_addr.sin_addr.s_addr == 0) + { + std::ostringstream out; + out << "pqissludp::Initiate_Connection() "; + out << "Invalid (0.0.0.0) Remote Address,"; + out << " Aborting Connect."; + out << std::endl; + rslog(RSL_WARNING, pqissludpzone, out.str()); + waiting = WAITING_FAIL_INTERFACE; + + reset(); + return -1; + } + + mTimeoutTS = time(NULL) + mConnectTimeout; + //std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl; + //std::cerr << " Connect Period is:" << mConnectPeriod << std::endl; + + /* <===================== UDP Difference *******************/ + if (0 != (err = tou_connect(sockfd, (struct sockaddr *) &remote_addr, + sizeof(remote_addr), mConnectPeriod))) + /* <===================== UDP Difference *******************/ + { + int tou_err = tou_errno(sockfd); + + std::ostringstream out; + out << "pqissludp::Initiate_Connection()"; + + if ((tou_err == EINPROGRESS) || (tou_err == EAGAIN)) + { + // set state to waiting..... + waiting = WAITING_SOCK_CONNECT; + + out << " EINPROGRESS Waiting for Socket Connection"; + rslog(RSL_WARNING, pqissludpzone, out.str()); + + return 0; + } + else if ((tou_err == ENETUNREACH) || (tou_err == ETIMEDOUT)) + { + out << "ENETUNREACHABLE: cert: " << PeerId(); + out << std::endl; + + // Then send unreachable message. + waiting = WAITING_FAIL_INTERFACE; + net_unreachable |= net_attempt; + } + + out << "Error: Connection Failed: " << tou_err; + out << " - " << socket_errorType(tou_err) << std::endl; + + rslog(RSL_WARNING, pqissludpzone, out.str()); + + reset(); + + return -1; + } + else + { + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::Init_Connection() connect returned 0"); + } + + waiting = WAITING_SOCK_CONNECT; + + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::Initiate_Connection() Waiting for Socket Connect"); + + return 1; +} + +/********* VERY DIFFERENT **********/ +int pqissludp::Basic_Connection_Complete() +{ + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::Basic_Connection_Complete()..."); + + + if (time(NULL) > mTimeoutTS) + { + std::ostringstream out; + out << "pqissludp::Basic_Connection_Complete() Connection Timed Out. "; + out << "Peer: " << PeerId() << " Period: "; + out << mConnectTimeout; + + rslog(RSL_WARNING, pqissludpzone, out.str()); + + /* as sockfd is valid, this should close it all up */ + + reset(); + return -1; + } + + + if (waiting != WAITING_SOCK_CONNECT) + { + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::Basic_Connection_Complete() Wrong Mode"); + return -1; + } + + + /* new approach is to check for an error */ + /* check for an error */ + int err; + if (0 != (err = tou_errno(sockfd))) + { + if (err == EINPROGRESS) + { + + std::ostringstream out; + out << "pqissludp::Basic_Connection_Complete() "; + out << "EINPROGRESS: cert: " << PeerId(); + rslog(RSL_DEBUG_BASIC, pqissludpzone, out.str()); + + } + else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) + { + std::ostringstream out; + out << "pqissludp::Basic_Connection_Complete() "; + out << "ENETUNREACH/ETIMEDOUT: cert: "; + out << PeerId(); + rslog(RSL_WARNING, pqissludpzone, out.str()); + + /* is the second one needed? */ + std::ostringstream out2; + out2 << "pqissludp::Basic_Connection_Complete() "; + out2 << "Error: Connection Failed: " << err; + out2 << " - " << socket_errorType(err); + rslog(RSL_DEBUG_BASIC, pqissludpzone, out2.str()); + + net_unreachable |= net_attempt; + + reset(); + + // Then send unreachable message. + waiting = WAITING_FAIL_INTERFACE; + + return -1; + } + } + + /* <===================== UDP Difference *******************/ + if (tou_connected(sockfd)) + /* <===================== UDP Difference *******************/ + { + std::ostringstream out; + out << "pqissludp::Basic_Connection_Complete() "; + out << "Connection Complete: cert: "; + out << PeerId(); + rslog(RSL_WARNING, pqissludpzone, out.str()); + + return 1; + } + else + { + // not ready return -1; + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::Basic_Connection_Complete() Not Yet Ready!"); + return 0; + } + + return -1; +} + + +/* New Internal Functions required to generalise tcp/udp version + * of the programs + */ + +// used everywhere +int pqissludp::net_internal_close(int fd) +{ + rslog(RSL_ALERT, pqissludpzone, + "pqissludp::net_internal_close() -> tou_close()"); + return tou_close(fd); +} + +// install udp BIO. +int pqissludp::net_internal_SSL_set_fd(SSL *ssl, int fd) +{ + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::net_internal_SSL_set_fd()"); + + /* create the bio's */ + tou_bio =BIO_new(BIO_s_tou_socket()); + + /* attach the fd's to the BIO's */ + BIO_set_fd(tou_bio, fd, BIO_NOCLOSE); + SSL_set_bio(ssl, tou_bio, tou_bio); + return 1; +} + +int pqissludp::net_internal_fcntl_nonblock(int fd) +{ + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::net_internal_fcntl_nonblock()"); + return 0; +} + + +/* These are identical to pqinetssl version */ +//int pqissludp::status() + +int pqissludp::tick() +{ + pqissl::tick(); + return 1; +} + + // listen fns call the udpproxy. +int pqissludp::listen() +{ + { + std::ostringstream out; + out << "pqissludp::listen() (NULLOP)"; + rslog(RSL_DEBUG_BASIC, pqissludpzone, out.str()); + } + return 1; //udpproxy->listen(); +} + +int pqissludp::stoplistening() +{ + { + std::ostringstream out; + out << "pqissludp::stoplistening() (NULLOP)"; + rslog(RSL_DEBUG_BASIC, pqissludpzone, out.str()); + } + return 1; //udpproxy->stoplistening(); +} + + +bool pqissludp::connect_parameter(uint32_t type, uint32_t value) +{ + //std::cerr << "pqissludp::connect_parameter() type: " << type << "value: " << value << std::endl; + if (type == NET_PARAM_CONNECT_PERIOD) + { + std::ostringstream out; + out << "pqissludp::connect_parameter() Peer: " << PeerId() << " PERIOD: " << value; + rslog(RSL_WARNING, pqissludpzone, out.str()); + + mConnectPeriod = value; + return true; + } + return pqissl::connect_parameter(type, value); +} + +/********** PQI STREAMER OVERLOADING *********************************/ + +bool pqissludp::moretoread() +{ + { + std::ostringstream out; + out << "pqissludp::moretoread()"; + out << " polling socket (" << sockfd << ")"; + rslog(RSL_DEBUG_ALL, pqissludpzone, out.str()); + } + + /* check for more to read first ... if nothing... check error + */ + /* <===================== UDP Difference *******************/ + if (tou_maxread(sockfd)) + /* <===================== UDP Difference *******************/ + { + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::moretoread() Data to Read!"); + return 1; + } + + /* else check the error */ + rslog(RSL_DEBUG_ALL, pqissludpzone, + "pqissludp::moretoread() No Data to Read!"); + + int err; + if (0 != (err = tou_errno(sockfd))) + { + if ((err == EAGAIN) || (err == EINPROGRESS)) + { + + std::ostringstream out; + out << "pqissludp::moretoread() "; + out << "EAGAIN/EINPROGRESS: cert " << PeerId(); + rslog(RSL_DEBUG_BASIC, pqissludpzone, out.str()); + return 0; + + } + else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) + { + std::ostringstream out; + out << "pqissludp::moretoread() "; + out << "ENETUNREACH/ETIMEDOUT: cert "; + out << PeerId(); + rslog(RSL_WARNING, pqissludpzone, out.str()); + + } + else if (err == EBADF) + { + std::ostringstream out; + out << "pqissludp::moretoread() "; + out << "EBADF: cert "; + out << PeerId(); + rslog(RSL_WARNING, pqissludpzone, out.str()); + + } + else + { + std::ostringstream out; + out << "pqissludp::moretoread() "; + out << " Unknown ERROR: " << err << ": cert "; + out << PeerId(); + rslog(RSL_WARNING, pqissludpzone, out.str()); + + } + + reset(); + return 0; + } + + /* otherwise - not error - strange! */ + rslog(RSL_DEBUG_BASIC, pqissludpzone, + "pqissludp::moretoread() No Data + No Error (really nothing)"); + + return 0; + + +} + +bool pqissludp::cansend() +{ + rslog(RSL_DEBUG_ALL, pqissludpzone, + "pqissludp::cansend() polling socket!"); + + /* <===================== UDP Difference *******************/ + return (0 < tou_maxwrite(sockfd)); + /* <===================== UDP Difference *******************/ + +} + + + diff --git a/libretroshare/src/pqi/pqissludp.h b/libretroshare/src/pqi/pqissludp.h new file mode 100644 index 000000000..1ee2966ed --- /dev/null +++ b/libretroshare/src/pqi/pqissludp.h @@ -0,0 +1,104 @@ +/* + * "$Id: pqissludp.h,v 1.8 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_SSL_UDP_HEADER +#define MRK_PQI_SSL_UDP_HEADER + +#include + +// operating system specific network header. +#include "pqi/pqinetwork.h" + +#include +#include + +#include "pqi/pqissl.h" + + /* So pqissludp is the special firewall breaking protocol. + * This class will implement the basics of streaming + * ssl over udp using a tcponudp library.... + * and a small extension to ssl. + */ + +class pqissludp; +class cert; + +/* This provides a NetBinInterface, which is + * primarily inherited from pqissl. + * fns declared here are different -> all others are identical. + */ + +class pqissludp: public pqissl +{ +public: + pqissludp(PQInterface *parent, p3ConnectMgr *cm); + +virtual ~pqissludp(); + + // NetInterface. + // listen fns call the udpproxy. +virtual int listen(); +virtual int stoplistening(); +virtual int tick(); +virtual int reset(); + +virtual bool connect_parameter(uint32_t type, uint32_t value); + + // BinInterface. + // These are reimplemented. +virtual bool moretoread(); +virtual bool cansend(); + /* UDP always through firewalls -> always bandwidth Limited */ +virtual bool bandwidthLimited() { return true; } + + // pqissludp specific. + // called to initiate a connection; +int attach(); + +protected: + +virtual int Initiate_Connection(); +virtual int Basic_Connection_Complete(); + +//protected internal fns that are overloaded for udp case. +virtual int net_internal_close(int fd); +virtual int net_internal_SSL_set_fd(SSL *ssl, int fd); +virtual int net_internal_fcntl_nonblock(int fd); + +private: + + BIO *tou_bio; // specific to ssludp. + + //int remote_timeout; + //int proxy_timeout; + + long listen_checktime; + + uint32_t mConnectPeriod; +}; + +#endif // MRK_PQI_SSL_UDP_HEADER diff --git a/libretroshare/src/pqi/pqistore.cc b/libretroshare/src/pqi/pqistore.cc new file mode 100644 index 000000000..3871d58a6 --- /dev/null +++ b/libretroshare/src/pqi/pqistore.cc @@ -0,0 +1,617 @@ +/* + * "$Id: pqistore.cc,v 1.5 2007-03-21 18:45:41 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +/* This is dependent on the sslroot at the moment. + * -> as we need to create/restore references to the Person. + * -> and store the signatures to do this. + */ + +/******************************************************************* + * pqistore provides an store stream. + * This stores RsItem + Person Reference + Timestamp, + * + * and allows Objects to be replayed or restored, + * independently of the rest of the pqi system. + * + */ + +#include "pqi/pqistore.h" +#include "serialiser/rsserial.h" +#include +#include + +#include +#include "util/rsdebug.h" + +// +// #define PQISTORE_DEBUG +// + +const int pqistorezone = 9511; + +pqistore::pqistore(RsSerialiser *rss, const std::string &srcId, BinInterface *bio_in, int bio_flags_in) + :PQInterface(""), rsSerialiser(rss), bio(bio_in), bio_flags(bio_flags_in), + nextPkt(NULL), mSrcId(srcId) +{ + { + std::ostringstream out; + out << "pqistore::pqistore()"; + out << " Initialisation!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + } + + if (!bio_in) + { + std::ostringstream out; + out << "pqistore::pqistore()"; + out << " NULL bio, FATAL ERROR!" << std::endl; + pqioutput(PQL_ALERT, pqistorezone, out.str()); + exit(1); + } + + return; +} + +pqistore::~pqistore() +{ + { + std::ostringstream out; + out << "pqistore::~pqistore()"; + out << " Destruction!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + } + + if (bio_flags & BIN_FLAGS_NO_CLOSE) + { + std::ostringstream out; + out << "pqistore::~pqistore()"; + out << " Not Closing BinInterface!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + } + else if (bio) + { + std::ostringstream out; + out << "pqistore::~pqistore()"; + out << " Deleting BinInterface!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + + delete bio; + } + + if (rsSerialiser) + delete rsSerialiser; + + if (nextPkt) + { + delete nextPkt; + } + return; +} + + +// Get/Send Items. +int pqistore::SendItem(RsItem *si) +{ +#ifdef PQISTORE_DEBUG + { + std::ostringstream out; + out << "pqistore::SendItem()" << std::endl; + si -> print(out); + pqioutput(PQL_DEBUG_BASIC, pqistorezone, out.str()); + } +#endif + + // check if this is a writing bio. + + if (!(bio_flags & BIN_FLAGS_WRITEABLE)) + { + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete si; + return -1; + } + +// std::cerr << "SendItem: si->PeerId()=" << si->PeerId() << std::endl ; + + int ret = writePkt(si); + return ret; /* 0 - failure, 1 - success*/ +} + +RsItem *pqistore::GetItem() +{ +#ifdef PQISTORE_DEBUG + { + std::ostringstream out; + out << "pqistore::GetItem()"; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + } +#endif + + // check if this is a reading bio. + if (!(bio_flags & BIN_FLAGS_READABLE)) + { +#ifdef PQISTORE_DEBUG + std::ostringstream out; + out << "pqistore::GetItem()"; + out << "Error Not Readable" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqistorezone, out.str()); +#endif + return NULL; + } + + // load if we dont have a packet. + if (!nextPkt) + { + if (!readPkt(&nextPkt)) + { + std::ostringstream out; + out << "pqistore::GetItem()"; + out << "Failed to ReadPkt" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqistorezone, out.str()); + return NULL; + } + } + + if (!nextPkt) return NULL; + + RsItem *outPkt = nextPkt; + nextPkt = NULL; + +#ifdef PQISTORE_DEBUG + if (outPkt != NULL) + { + std::ostringstream out; + out << "pqistore::GetItem() Returning:" << std::endl; + outPkt -> print(out); + pqioutput(PQL_DEBUG_BASIC, pqistorezone, out.str()); + } +#endif + return outPkt; +} + + + + +// // PQInterface +int pqistore::tick() +{ +#ifdef PQISTORE_DEBUG + { + std::ostringstream out; + out << "pqistore::tick()"; + out << std::endl; + } +#endif + return 0; +} + +int pqistore::status() +{ +#ifdef PQISTORE_DEBUG + { + std::ostringstream out; + out << "pqistore::status()"; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + } +#endif + return 0; +} + +// +/**************** HANDLE OUTGOING TRANSLATION + TRANSMISSION ******/ + +int pqistore::writePkt(RsItem *pqi) +{ +// std::cerr << "writePkt, pqi->peerId()=" << pqi->PeerId() << std::endl ; +#ifdef PQISTORE_DEBUG + { + std::ostringstream out; + out << "pqistore::writePkt()"; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + } +#endif + + uint32_t pktsize = rsSerialiser->size(pqi); + void *ptr = malloc(pktsize); + if (!(rsSerialiser->serialise(pqi, ptr, &pktsize))) + { +#ifdef PQISTORE_DEBUG + std::ostringstream out; + out << "pqistore::writePkt() Null Pkt generated!"; + out << std::endl; + out << "Caused By: " << std::endl; + pqi -> print(out); + pqioutput(PQL_ALERT, pqistorezone, out.str()); +#endif + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + return 0; + } + + /* extract the extra details */ + uint32_t len = getRsItemSize(ptr); + if (len != pktsize) + { + std::ostringstream out; + out << "pqistore::writePkt() Length MisMatch: len: " << len; + out << " != pktsize: " << pktsize; + out << std::endl; + out << "Caused By: " << std::endl; + pqi -> print(out); + pqioutput(PQL_ALERT, pqistorezone, out.str()); + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + return 0; + } + + + if (!(bio->cansend())) + { + std::ostringstream out; + out << "pqistore::writePkt() BIO cannot write!"; + out << std::endl; + out << "Discarding: " << std::endl; + pqi -> print(out); + pqioutput(PQL_ALERT, pqistorezone, out.str()); + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + + return 0; + } + +#ifdef PQISTORE_DEBUG + std::ostringstream out; + out << "Writing Pkt Body" << std::endl; +#endif + // write packet. + if (len != bio->senddata(ptr, len)) + { +#ifdef PQISTORE_DEBUG + out << "Problems with Send Data!"; + out << std::endl; + pqioutput(PQL_ALERT, pqistorezone, out.str()); +#endif + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + + return 0; + } + +#ifdef PQISTORE_DEBUG + out << " Success!" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqistorezone, out.str()); +#endif + + free(ptr); + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete pqi; + + return 1; +} + +/* Reads a single packet from the input stream + * gets the timestamp as well. + */ + +int pqistore::readPkt(RsItem **item_out) +{ +#ifdef PQISTORE_DEBUG + { + std::ostringstream out; + out << "pqistore::readPkt()"; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + } +#endif + + if ((!(bio->isactive())) || (!(bio->moretoread()))) + { + return 0; + } + + // enough space to read any packet. + int maxlen = getRsPktMaxSize(); + void *block = malloc(maxlen); + + // initial read size: basic packet. + int blen = getRsPktBaseSize(); + + int tmplen; + /* we have the header */ + + // read the basic block (minimum packet size) + if (blen != (tmplen = bio->readdata(block, blen))) + { + pqioutput(PQL_WARNING, pqistorezone, + "pqistore::readPkt() bad read(2)"); + + free(block); + return 0; + } + + // workout how much more to read. + int extralen = getRsItemSize(block) - blen; + + if(extralen+blen > maxlen) + std::cerr << "***** ERROR: trying to read a packet of length " << extralen+blen << ", while the maximum length is " << maxlen << std::endl ; + + if (extralen > 0) + { + if(extralen > blen + maxlen) + { + std::cerr << "pqistore: ERROR: Inconsistency in packet format (extralen=" << extralen << ", maxlen=" << maxlen << "). Wasting the whole file." << std::endl ; + free(block) ; + return 0 ; + } + + void *extradata = (void *) (((char *) block) + blen); + + if (extralen != (tmplen = bio->readdata(extradata, extralen))) + { + + std::ostringstream out; + out << "pqistore::readPkt() "; + out << "Error Completing Read (read "; + out << tmplen << "/" << extralen << ")" << std::endl; + pqioutput(PQL_ALERT, pqistorezone, out.str()); + + free(block); + return 0; + } + } + + // create packet, based on header. + //std::cerr << "Read Data Block -> Incoming Pkt("; + //std::cerr << blen + extralen << ")" << std::endl; + uint32_t readbytes = extralen + blen; + + RsItem *item = rsSerialiser->deserialise(block, &readbytes); + free(block); + + if (item == NULL) + { + pqioutput(PQL_ALERT, pqistorezone, + "pqistore::readPkt() Failed to create Item from store!"); + return 0; + } + + item->PeerId(mSrcId); + *item_out = item; + return 1; +} + +/**** Hashing Functions ****/ +std::string pqistore::gethash() +{ + return bio->gethash(); +} + +pqiSSLstore::pqiSSLstore(RsSerialiser *rss, std::string srcId, BinEncryptedFileInterface* bio_in, int bio_flagsin) +: pqistore(rss, srcId, bio_in, bio_flagsin), enc_bio(bio_in) +{ + return; +} + +pqiSSLstore::~pqiSSLstore() +{ + // no need to delete member enc_bio, as it is deleted by the parent class. + return; +} + +bool pqiSSLstore::encryptedSendItems(const std::list& rsItemList) +{ + + std::list::const_iterator it; + uint32_t sizeItems = 0, sizeItem = 0; + uint32_t offset = 0; + char* data = NULL; + + for(it = rsItemList.begin(); it != rsItemList.end(); it++) + sizeItems += rsSerialiser->size(*it); + + data = new char[sizeItems]; + + for(it = rsItemList.begin(); it != rsItemList.end(); it++) + { + sizeItem = rsSerialiser->size(*it); + if(!rsSerialiser->serialise(*it, (data+offset),&sizeItem)) + return false; + offset += sizeItem; + + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + delete *it; + } + + if(sizeItems == offset) + enc_bio->senddata(data, sizeItems); + else + return false; + + if(data != NULL) + delete[] data; + + return true; +} + +bool pqiSSLstore::getEncryptedItems(std::list& rsItemList) +{ + RsItem* item; + + while(NULL != (item = GetItem())) + { + rsItemList.push_back(item); + } + + return true; +} + + +RsItem *pqiSSLstore::GetItem() +{ +#ifdef PQISTORE_DEBUG + { + std::ostringstream out; + out << "pqistore::GetItem()"; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + } +#endif + + // check if this is a reading bio. + if (!(bio_flags & BIN_FLAGS_READABLE)) + { + std::ostringstream out; + out << "pqistore::GetItem()"; + out << "Error Not Readable" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqistorezone, out.str()); + return NULL; + } + + // load if we dont have a packet. + if (!nextPkt) + { + if (!readPkt(&nextPkt)) + { + std::ostringstream out; + out << "pqistore::GetItem()"; + out << "Failed to ReadPkt" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqistorezone, out.str()); + return NULL; + } + } + + if (!nextPkt) return NULL; + + RsItem *outPkt = nextPkt; + nextPkt = NULL; + +#ifdef PQISTORE_DEBUG + if (outPkt != NULL) + { + std::ostringstream out; + out << "pqistore::GetItem() Returning:" << std::endl; + outPkt -> print(out); + pqioutput(PQL_DEBUG_BASIC, pqistorezone, out.str()); + } +#endif + return outPkt; +} + + +int pqiSSLstore::readPkt(RsItem **item_out) +{ +#ifdef PQISTORE_DEBUG + { + std::ostringstream out; + out << "pqistore::readPkt()"; + pqioutput(PQL_DEBUG_ALL, pqistorezone, out.str()); + } +#endif + + if ((!(enc_bio->isactive())) || (!(enc_bio->moretoread()))) + { + return 0; + } + + // enough space to read any packet. + int maxlen = getRsPktMaxSize(); + void *block = malloc(maxlen); + + // initial read size: basic packet. + int blen = getRsPktBaseSize(); + + int tmplen; + /* we have the header */ + + // read the basic block (minimum packet size) + if (blen != (tmplen = enc_bio->readdata(block, blen))) + { + pqioutput(PQL_WARNING, pqistorezone, + "pqistore::readPkt() bad read(2)"); + + free(block); + return 0; + } + + // workout how much more to read. + int extralen = getRsItemSize(block) - blen; + + if(extralen+blen > maxlen) + std::cerr << "***** ERROR: trying to read a packet of length " << extralen+blen << ", while the maximum length is " << maxlen << std::endl ; + + if (extralen > 0) + { + if(extralen > blen + maxlen) + { + std::cerr << "pqistore: ERROR: Inconsistency in packet format (extralen=" << extralen << ", maxlen=" << maxlen << "). Wasting the whole file." << std::endl ; + free(block) ; + return 0 ; + } + + void *extradata = (void *) (((char *) block) + blen); + + if (extralen != (tmplen = enc_bio->readdata(extradata, extralen))) + { + + std::ostringstream out; + out << "pqistore::readPkt() "; + out << "Error Completing Read (read "; + out << tmplen << "/" << extralen << ")" << std::endl; + pqioutput(PQL_ALERT, pqistorezone, out.str()); + + free(block); + return 0; + } + } + + // create packet, based on header. + //std::cerr << "Read Data Block -> Incoming Pkt("; + //std::cerr << blen + extralen << ")" << std::endl; + uint32_t readbytes = extralen + blen; + + RsItem *item = rsSerialiser->deserialise(block, &readbytes); + free(block); + +#ifdef PQISTORE_DEBUG + if (item == NULL) + { + pqioutput(PQL_ALERT, pqistorezone, + "pqistore::readPkt() Failed to create Item from store!"); + return 0; + } +#endif + + item->PeerId(mSrcId); + *item_out = item; + return 1; +} diff --git a/libretroshare/src/pqi/pqistore.h b/libretroshare/src/pqi/pqistore.h new file mode 100644 index 000000000..0e1bc400c --- /dev/null +++ b/libretroshare/src/pqi/pqistore.h @@ -0,0 +1,112 @@ +/* + * pqistore.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef MRK_PQI_STORE_STREAMER_HEADER +#define MRK_PQI_STORE_STREAMER_HEADER + +#include "pqi/pqibin.h" + +#include + +/******************************************************************* + * pqistore provides a stream to file. + * objects only - like pqistreamer as opposed to pqiarchive. + * + */ + +class pqistore: public PQInterface +{ +public: + pqistore(RsSerialiser *rss, const std::string &srcId, BinInterface *bio_in, int bio_flagsin); +virtual ~pqistore(); + +// PQInterface +virtual int SendItem(RsItem *); +virtual RsItem *GetItem(); + +virtual int tick(); +virtual int status(); + +std::string gethash(); + +protected: + +// Serialiser +RsSerialiser *rsSerialiser; +unsigned int bio_flags; // only BIN_NO_CLOSE at the moment. + +// Temp Storage for transient data..... +RsItem *nextPkt; +std::string mSrcId; + +private: + + int writePkt(RsItem *item); + int readPkt(RsItem **item_out); + + + + // Binary Interface for IO, initialisated at startup. + BinInterface *bio; + +}; + + +/*! + * provdes an ssl encrypted stream to file storage + */ +class pqiSSLstore: public pqistore +{ + +public: + + pqiSSLstore(RsSerialiser *rss, std::string srcId, BinEncryptedFileInterface *bio_in, int bio_flagsin); + + virtual ~pqiSSLstore(); + + /*! + * send items encrypted to file using client's ssl key + */ + bool encryptedSendItems(const std::list&); + + /*! + * retrieve encrypted file using client's ssl key + */ + bool getEncryptedItems(std::list&); + +private: + + RsItem *GetItem(); + int readPkt(RsItem **item_out); + + BinEncryptedFileInterface* enc_bio; + + +}; + + +#endif //MRK_PQI_STORE_STREAMER_HEADER diff --git a/libretroshare/src/pqi/pqistreamer.cc b/libretroshare/src/pqi/pqistreamer.cc new file mode 100644 index 000000000..12120914f --- /dev/null +++ b/libretroshare/src/pqi/pqistreamer.cc @@ -0,0 +1,1006 @@ +/* + * "$Id: pqistreamer.cc,v 1.19 2007-02-18 21:46:50 rmf24 Exp $" + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include +#include "util/rsdebug.h" + +#include "pqi/pqistreamer.h" +#include "pqi/pqinotify.h" + +#include "serialiser/rsserial.h" +#include "serialiser/rsbaseitems.h" /***** For RsFileData *****/ + + +const int pqistreamerzone = 8221; + +const int PQISTREAM_ABS_MAX = 100000000; /* 100 MB/sec (actually per loop) */ + +/* This removes the print statements (which hammer pqidebug) */ +/*** +#define RSITEM_DEBUG 1 +#define DEBUG_TRANSFERS 1 +#define DEBUG_PQISTREAMER 1 + ***/ + + +#ifdef DEBUG_TRANSFERS + #include "util/rsprint.h" +#endif + + +pqistreamer::pqistreamer(RsSerialiser *rss, std::string id, BinInterface *bio_in, int bio_flags_in) + :PQInterface(id), rsSerialiser(rss), bio(bio_in), bio_flags(bio_flags_in), + pkt_wpending(NULL), + totalRead(0), totalSent(0), + currRead(0), currSent(0), + avgReadCount(0), avgSentCount(0) +{ + avgLastUpdate = currReadTS = currSentTS = time(NULL); + + /* allocated once */ + pkt_rpend_size = getRsPktMaxSize(); + pkt_rpending = malloc(pkt_rpend_size); + reading_state = reading_state_initial ; + +// thread_id = pthread_self() ; + // avoid uninitialized (and random) memory read. + memset(pkt_rpending,0,pkt_rpend_size) ; + + // 100 B/s (minimal) + setMaxRate(true, 0.1); + setMaxRate(false, 0.1); + setRate(true, 0); + setRate(false, 0); + + { + std::ostringstream out; + out << "pqistreamer::pqistreamer()"; + out << " Initialisation!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + if (!bio_in) + { + std::ostringstream out; + out << "pqistreamer::pqistreamer()"; + out << " NULL bio, FATAL ERROR!" << std::endl; + pqioutput(PQL_ALERT, pqistreamerzone, out.str()); + exit(1); + } + + failed_read_attempts = 0 ; // reset failed read, as no packet is still read. + + return; +} + +pqistreamer::~pqistreamer() +{ + RsStackMutex stack(streamerMtx) ; // lock out_pkt and out_data + + { + std::ostringstream out; + out << "pqistreamer::~pqistreamer()"; + out << " Destruction!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + if (bio_flags & BIN_FLAGS_NO_CLOSE) + { + std::ostringstream out; + out << "pqistreamer::~pqistreamer()"; + out << " Not Closing BinInterface!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + else if (bio) + { + std::ostringstream out; + out << "pqistreamer::~pqistreamer()"; + out << " Deleting BinInterface!" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + + delete bio; + } + + /* clean up serialiser */ + if (rsSerialiser) + delete rsSerialiser; + + // clean up outgoing. (cntrl packets) + while(out_pkt.size() > 0) + { + void *pkt = out_pkt.front(); + out_pkt.pop_front(); + free(pkt); + } + + // clean up outgoing (data packets) + while(out_data.size() > 0) + { + void *pkt = out_data.front(); + out_data.pop_front(); + free(pkt); + } + + if (pkt_wpending) + { + free(pkt_wpending); + pkt_wpending = NULL; + } + + free(pkt_rpending); + + // clean up outgoing. + while(incoming.size() > 0) + { + RsItem *i = incoming.front(); + incoming.pop_front(); + delete i; + } + return; +} + + +// Get/Send Items. +int pqistreamer::SendItem(RsItem *si) +{ +#ifdef RSITEM_DEBUG + { + std::ostringstream out; + out << "pqistreamer::SendItem():" << std::endl; + si -> print(out); + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + std::cerr << out.str(); + } +#endif + + return queue_outpqi(si); +} + +RsItem *pqistreamer::GetItem() +{ + { + std::ostringstream out; + out << "pqistreamer::GetItem()"; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + if(incoming.empty()) + return NULL; + + RsItem *osr = incoming.front() ; + incoming.pop_front() ; + + return osr; +} + +// // PQInterface +int pqistreamer::tick() +{ + { + std::ostringstream out; + out << "pqistreamer::tick()"; + out << std::endl; + out << PeerId() << ": currRead/Sent: " << currRead << "/" << currSent; + out << std::endl; + + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + bio->tick(); + + /* short circuit everything is bio isn't active */ + if (!(bio->isactive())) + { + return 0; + } + + + /* must do both, as outgoing will catch some bad sockets, + * that incoming will not + */ + + handleincoming(); + handleoutgoing(); + + /* give details of the packets */ + { + std::list::iterator it; + + std::ostringstream out; + out << "pqistreamer::tick() Queued Data:"; + out << " for " << PeerId(); + + if (bio->isactive()) + { + out << " (active)"; + } + else + { + out << " (waiting)"; + } + out << std::endl; + + { + RsStackMutex stack(streamerMtx) ; // lock out_pkt and out_data + int total = 0; + + for(it = out_pkt.begin(); it != out_pkt.end(); it++) + { + total += getRsItemSize(*it); + } + + out << "\t Out Packets [" << out_pkt.size() << "] => " << total; + out << " bytes" << std::endl; + + total = 0; + for(it = out_data.begin(); it != out_data.end(); it++) + { + total += getRsItemSize(*it); + } + + out << "\t Out Data [" << out_data.size() << "] => " << total; + out << " bytes" << std::endl; + + out << "\t Incoming [" << incoming.size() << "]"; + out << std::endl; + } + + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out.str()); + } + + /* if there is more stuff in the queues */ + if ((incoming.size() > 0) || (out_pkt.size() > 0) || (out_data.size() > 0)) + { + return 1; + } + return 0; +} + +int pqistreamer::status() +{ + { + std::ostringstream out; + out << "pqistreamer::status()"; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + if (bio->isactive()) + { + std::ostringstream out; + out << "Data in:" << totalRead << " out:" << totalSent; + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out.str()); + } + + return 0; +} + +// +/**************** HANDLE OUTGOING TRANSLATION + TRANSMISSION ******/ + +int pqistreamer::queue_outpqi(RsItem *pqi) +{ +#ifdef DEBUG_PQISTREAMER + std::cerr << "pqistreamer::queue_outpqi() called." << std::endl; +#endif + RsStackMutex stack(streamerMtx) ; // lock out_pkt and out_data + + // This is called by different threads, and by threads that are not the handleoutgoing thread, + // so it should be protected by a mutex !! + +#ifdef DEBUG_PQISTREAMER + if(dynamic_cast(pqi)!=NULL && (bio_flags & BIN_FLAGS_NO_DELETE)) + { + std::cerr << "Having file data with flags = " << bio_flags << std::endl ; + *(int*)0x0=1 ; + } +#endif + + { + std::ostringstream out; + out << "pqistreamer::queue_outpqi()"; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + /* decide which type of packet it is */ + RsFileData *dta = dynamic_cast(pqi); // This is the old test method + bool isCntrl = (dta == NULL); + + if(pqi->queueType() == RsItem::DATA_QUEUE) // this is the new test method. More general. + { +#ifdef DEBUG_PQISTREAMER + std::cerr << "PQISTREAMER:: got a data queue packet !!" << std::endl ; +#endif + isCntrl = false ; + } + + uint32_t pktsize = rsSerialiser->size(pqi); + void *ptr = malloc(pktsize); + +#ifdef DEBUG_PQISTREAMER + std::cerr << "pqistreamer::queue_outpqi() serializing packet with packet size : " << pktsize << std::endl; +#endif + if (rsSerialiser->serialise(pqi, ptr, &pktsize)) + { + if (isCntrl) + { + out_pkt.push_back(ptr); + } + else + { + out_data.push_back(ptr); + } + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + { + delete pqi; + } + return 1; + } + else + { + /* cleanup serialiser */ + free(ptr); + } + + std::ostringstream out; + out << "pqistreamer::queue_outpqi() Null Pkt generated!"; + out << std::endl; + out << "Caused By: " << std::endl; + pqi -> print(out); + pqioutput(PQL_ALERT, pqistreamerzone, out.str()); + + if (!(bio_flags & BIN_FLAGS_NO_DELETE)) + { + delete pqi; + } + return 1; // keep error internal. +} + +int pqistreamer::handleincomingitem(RsItem *pqi) +{ + { + std::ostringstream out; + out << "pqistreamer::handleincomingitem()"; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + // Use overloaded Contact function + pqi -> PeerId(PeerId()); + incoming.push_back(pqi); + return 1; +} + +int pqistreamer::handleoutgoing() +{ + RsStackMutex stack(streamerMtx) ; // lock out_pkt and out_data + + { + std::ostringstream out; + out << "pqistreamer::handleoutgoing()"; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + int maxbytes = outAllowedBytes(); + int sentbytes = 0; + int len; + int ss; + // std::cerr << "pqistreamer: maxbytes=" << maxbytes<< std::endl ; + + std::list::iterator it; + + // if not connection, or cannot send anything... pause. + if (!(bio->isactive())) + { + /* if we are not active - clear anything in the queues. */ + for(it = out_pkt.begin(); it != out_pkt.end(); ) + { + free(*it); + it = out_pkt.erase(it); + + std::ostringstream out; + out << "pqistreamer::handleoutgoing() Not active -> Clearing Pkt!"; + // std::cerr << out.str() ; + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out.str()); + } + for(it = out_data.begin(); it != out_data.end(); ) + { + free(*it); + it = out_data.erase(it); + + std::ostringstream out; + out << "pqistreamer::handleoutgoing() Not active -> Clearing DPkt!"; + // std::cerr << out.str() ; + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out.str()); + } + + /* also remove the pending packets */ + if (pkt_wpending) + { + free(pkt_wpending); + pkt_wpending = NULL; + } + + outSentBytes(sentbytes); + return 0; + } + + // a very simple round robin + + bool sent = true; + while(sent) // catch if all items sent. + { + sent = false; + + if ((!(bio->cansend())) || (maxbytes < sentbytes)) + { + +#ifdef DEBUG_TRANSFERS + if (maxbytes < sentbytes) + { + std::cerr << "pqistreamer::handleoutgoing() Stopped sending sentbytes > maxbytes. Sent " << sentbytes << " bytes "; + std::cerr << std::endl; + } + else + { + std::cerr << "pqistreamer::handleoutgoing() Stopped sending at cansend() is false"; + std::cerr << std::endl; + } +#endif + + outSentBytes(sentbytes); + return 0; + } + + // send a out_pkt., else send out_data. unless + // there is a pending packet. + if (!pkt_wpending) + { + if (out_pkt.size() > 0) + { + pkt_wpending = *(out_pkt.begin()); + out_pkt.pop_front(); +#ifdef DEBUG_TRANSFERS + std::cerr << "pqistreamer::handleoutgoing() getting next pkt from out_pkt queue"; + std::cerr << std::endl; +#endif + + } + else if (out_data.size() > 0) + { + pkt_wpending = *(out_data.begin()); + out_data.pop_front(); +#ifdef DEBUG_TRANSFERS + std::cerr << "pqistreamer::handleoutgoing() getting next pkt from out_data queue"; + std::cerr << std::endl; +#endif + } + } + + if (pkt_wpending) + { + std::ostringstream out; + // write packet. + len = getRsItemSize(pkt_wpending); + +#ifdef DEBUG_PQISTREAMER + std::cout << "Sending Out Pkt of size " << len << " !" << std::endl; +#endif + + if (len != (ss = bio->senddata(pkt_wpending, len))) + { + out << "Problems with Send Data! (only " << ss << " bytes sent" << ", total pkt size=" << len ; + out << std::endl; +// std::cerr << out.str() ; + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out.str()); + + outSentBytes(sentbytes); + // pkt_wpending will kept til next time. + // ensuring exactly the same data is written (openSSL requirement). + return -1; + } + +#ifdef DEBUG_TRANSFERS + std::cerr << "pqistreamer::handleoutgoing() Sent Packet len: " << len << " @ " << RsUtil::AccurateTimeString(); + std::cerr << std::endl; +#endif + +// out << " Success!" << ", sent " << len << " bytes" << std::endl; + // std::cerr << out.str() ; + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out.str()); + + free(pkt_wpending); + pkt_wpending = NULL; + + sentbytes += len; + sent = true; + } + } + outSentBytes(sentbytes); + return 1; +} + + +/* Handles reading from input stream. + */ +int pqistreamer::handleincoming() +{ + int readbytes = 0; + static const int max_failed_read_attempts = 2000 ; + + { + std::ostringstream out; + out << "pqistreamer::handleincoming()"; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + if(!(bio->isactive())) + { + reading_state = reading_state_initial ; + inReadBytes(readbytes); + return 0; + } + + // enough space to read any packet. + int maxlen = pkt_rpend_size; + void *block = pkt_rpending; + + // initial read size: basic packet. + int blen = getRsPktBaseSize(); + + int maxin = inAllowedBytes(); + +#ifdef DEBUG_PQISTREAMER + std::cerr << "[" << (void*)pthread_self() << "] " << "reading state = " << reading_state << std::endl ; +#endif + switch(reading_state) + { + case reading_state_initial: /*std::cerr << "jumping to start" << std::endl; */ goto start_packet_read ; + case reading_state_packet_started: /*std::cerr << "jumping to middle" << std::endl;*/ goto continue_packet ; + } + +start_packet_read: + { // scope to ensure variable visibility + // read the basic block (minimum packet size) + int tmplen; +#ifdef DEBUG_PQISTREAMER + std::cerr << "[" << (void*)pthread_self() << "] " << "starting packet" << std::endl ; +#endif + memset(block,0,blen) ; // reset the block, to avoid uninitialized memory reads. + + if (blen != (tmplen = bio->readdata(block, blen))) + { + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "pqistreamer::handleincoming() Didn't read BasePkt!"); + + inReadBytes(readbytes); + + // error.... (either blocked or failure) + if (tmplen == 0) + { + // most likely blocked! + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "pqistreamer::handleincoming() read blocked"); +#ifdef DEBUG_PQISTREAMER + std::cerr << "[" << (void*)pthread_self() << "] " << "given up 1" << std::endl ; +#endif + return 0; + } + else if (tmplen < 0) + { + // Most likely it is that the packet is pending but could not be read by pqissl because of stream flow. + // So we return without an error, and leave the machine state in 'start_read'. + // + //pqioutput(PQL_WARNING, pqistreamerzone, "pqistreamer::handleincoming() Error in bio read"); +#ifdef DEBUG_PQISTREAMER + std::cerr << "[" << (void*)pthread_self() << "] " << "given up 2, state = " << reading_state << std::endl ; +#endif + return 0; + } + else // tmplen > 0 + { + // strange case....This should never happen as partial reads are handled by pqissl below. + std::ostringstream out; + out << "pqistreamer::handleincoming() Incomplete "; + out << "(Strange) read of " << tmplen << " bytes"; + pqioutput(PQL_ALERT, pqistreamerzone, out.str()); +#ifdef DEBUG_PQISTREAMER + std::cerr << "[" << (void*)pthread_self() << "] " << "given up 3" << std::endl ; +#endif + return -1; + } + } +#ifdef DEBUG_PQISTREAMER + std::cerr << "[" << (void*)pthread_self() << "] " << "block 0 : " << (int)(((unsigned char*)block)[0]) << " " << (int)(((unsigned char*)block)[1]) << " " << (int)(((unsigned char*)block)[2]) << " " + << (int)(((unsigned char*)block)[3]) << " " + << (int)(((unsigned char*)block)[4]) << " " + << (int)(((unsigned char*)block)[5]) << " " + << (int)(((unsigned char*)block)[6]) << " " + << (int)(((unsigned char*)block)[7]) << " " << std::endl ; +#endif + + readbytes += blen; + reading_state = reading_state_packet_started ; + failed_read_attempts = 0 ; // reset failed read, as the packet has been totally read. + } +continue_packet: + { + // workout how much more to read. + int extralen = getRsItemSize(block) - blen; + +#ifdef DEBUG_PQISTREAMER + std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet getRsItemSize(block) = " << getRsItemSize(block) << std::endl ; + std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet extralen = " << extralen << std::endl ; + + std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet state=" << reading_state << std::endl ; + std::cerr << "[" << (void*)pthread_self() << "] " << "block 1 : " << (int)(((unsigned char*)block)[0]) << " " << (int)(((unsigned char*)block)[1]) << " " << (int)(((unsigned char*)block)[2]) << " " << (int)(((unsigned char*)block)[3]) << " " + << (int)(((unsigned char*)block)[4]) << " " + << (int)(((unsigned char*)block)[5]) << " " + << (int)(((unsigned char*)block)[6]) << " " + << (int)(((unsigned char*)block)[7]) << " " << std::endl ; +#endif + if (extralen > maxlen - blen) + { + pqioutput(PQL_ALERT, pqistreamerzone, "ERROR: Read Packet too Big!"); + + pqiNotify *notify = getPqiNotify(); + if (notify) + { + std::string title = + "Warning: Bad Packet Read"; + + std::ostringstream msgout; + msgout << " **** WARNING **** \n"; + msgout << "Retroshare has caught a BAD Packet Read"; + msgout << "\n"; + msgout << "This is normally caused by connecting to an"; + msgout << " OLD version of Retroshare"; + msgout << "\n"; + msgout << "(M:" << maxlen << " B:" << blen << " E:" << extralen << ")\n"; + msgout << "\n"; + msgout << "block = " + << (int)(((unsigned char*)block)[0]) << " " + << (int)(((unsigned char*)block)[1]) << " " + << (int)(((unsigned char*)block)[2]) << " " + << (int)(((unsigned char*)block)[3]) << "\n" ; + msgout << "\n"; + msgout << "Please get your friends to upgrade to the latest version"; + msgout << "\n"; + msgout << "\n"; + msgout << "If you are sure the error was not caused by an old version"; + msgout << "\n"; + msgout << "Please report the problem to Retroshare's developers"; + msgout << "\n"; + + std::string msg = msgout.str(); + notify->AddLogMessage(0, RS_SYS_WARNING, title, msg); + } + bio->close(); + reading_state = reading_state_initial ; // restart at state 1. + failed_read_attempts = 0 ; + return -1; + + // Used to exit now! exit(1); + } + + if (extralen > 0) + { + void *extradata = (void *) (((char *) block) + blen); + int tmplen ; + + // Don't reset the block now! If pqissl is in the middle of a multiple-chunk + // packet (larger than 16384 bytes), and pqistreamer jumped directly yo + // continue_packet:, then readdata is going to write after the beginning of + // extradata, yet not exactly at start -> the start of the packet would be wiped out. + // + // so, don't do that: + // memset( extradata,0,extralen ) ; + + if (extralen != (tmplen = bio->readdata(extradata, extralen))) + { +#ifdef DEBUG_PQISTREAMER + if(tmplen > 0) + std::cerr << "[" << (void*)pthread_self() << "] " << "Incomplete packet read ! This is a real problem ;-)" << std::endl ; +#endif + + if(++failed_read_attempts > max_failed_read_attempts) + { + std::ostringstream out; + out << "Error Completing Read (read "; + out << tmplen << "/" << extralen << ")" << std::endl; + std::cerr << out.str() ; + pqioutput(PQL_ALERT, pqistreamerzone, out.str()); + + pqiNotify *notify = getPqiNotify(); + if (notify) + { + std::string title = "Warning: Error Completing Read"; + + std::ostringstream msgout; + msgout << " **** WARNING **** \n"; + msgout << "Retroshare has experienced an unexpected Read ERROR"; + msgout << "\n"; + msgout << "(M:" << maxlen << " B:" << blen; + msgout << " E:" << extralen << " R:" << tmplen << ")\n"; + msgout << "\n"; + msgout << "Note: this error might as well happen (rarely) when a peer disconnects in between a transmission of a large packet." << std::endl; + msgout << "If it happens manny time, please contact the developers, and send them these numbers:"; + msgout << "\n"; + + msgout << "block = " + << (int)(((unsigned char*)block)[0]) << " " + << (int)(((unsigned char*)block)[1]) << " " + << (int)(((unsigned char*)block)[2]) << " " + << (int)(((unsigned char*)block)[3]) << " " + << (int)(((unsigned char*)block)[4]) << " " + << (int)(((unsigned char*)block)[5]) << " " + << (int)(((unsigned char*)block)[6]) << " " + << (int)(((unsigned char*)block)[7]) << " " + << std::endl ; + + + //notify->AddSysMessage(0, RS_SYS_WARNING, title, msgout.str()); + + std::cerr << msgout.str() << std::endl; + } + + bio->close(); + reading_state = reading_state_initial ; // restart at state 1. + failed_read_attempts = 0 ; + return -1; + } + else + { +#ifdef DEBUG_PQISTREAMER + std::cerr << "[" << (void*)pthread_self() << "] " << "given up 5, state = " << reading_state << std::endl ; +#endif + return 0 ; // this is just a SSL_WANT_READ error. Don't panic, we'll re-try the read soon. + // we assume readdata() returned either -1 or the complete read size. + } + } +#ifdef DEBUG_PQISTREAMER + std::cerr << "[" << (void*)pthread_self() << "] " << "continuing packet state=" << reading_state << std::endl ; + std::cerr << "[" << (void*)pthread_self() << "] " << "block 2 : " << (int)(((unsigned char*)extradata)[0]) << " " << (int)(((unsigned char*)extradata)[1]) << " " << (int)(((unsigned char*)extradata)[2]) << " " << (int)(((unsigned char*)extradata)[3]) << " " + << (int)(((unsigned char*)extradata)[4]) << " " + << (int)(((unsigned char*)extradata)[5]) << " " + << (int)(((unsigned char*)extradata)[6]) << " " + << (int)(((unsigned char*)extradata)[7]) << " " << std::endl ; +#endif + + failed_read_attempts = 0 ; + readbytes += extralen; + } + + // create packet, based on header. + { + std::ostringstream out; + out << "Read Data Block -> Incoming Pkt("; + out << blen + extralen << ")" << std::endl; + //std::cerr << out.str() ; + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out.str()); + } + + // std::cerr << "Deserializing packet of size " << pktlen <deserialise(block, &pktlen); + + if ((pkt != NULL) && (0 < handleincomingitem(pkt))) + pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, "Successfully Read a Packet!"); + else + pqioutput(PQL_ALERT, pqistreamerzone, "Failed to handle Packet!"); + + reading_state = reading_state_initial ; // restart at state 1. + failed_read_attempts = 0 ; // reset failed read, as the packet has been totally read. + } + + if(maxin > readbytes && bio->moretoread()) + goto start_packet_read ; + +#ifdef DEBUG_TRANSFERS + if (readbytes >= maxin) + { + std::cerr << "pqistreamer::handleincoming() Stopped reading as readbytes >= maxin. Read " << readbytes << " bytes "; + std::cerr << std::endl; + } +#endif + + inReadBytes(readbytes); + return 0; +} + + +/* BandWidth Management Assistance */ + +float pqistreamer::outTimeSlice() +{ + { + std::ostringstream out; + out << "pqistreamer::outTimeSlice()"; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + //fixme("pqistreamer::outTimeSlice()", 1); + return 1; +} + +// very simple..... +int pqistreamer::outAllowedBytes() +{ + int t = time(NULL); // get current timestep. + + /* allow a lot if not bandwidthLimited */ + if (!bio->bandwidthLimited()) + { + currSent = 0; + currSentTS = t; + return PQISTREAM_ABS_MAX; + } + + int dt = t - currSentTS; + // limiter -> for when currSentTs -> 0. + if (dt > 5) + dt = 5; + + int maxout = (int) (getMaxRate(false) * 1000.0); + currSent -= dt * maxout; + if (currSent < 0) + { + currSent = 0; + } + + currSentTS = t; + + { + std::ostringstream out; + out << "pqistreamer::outAllowedBytes() is "; + out << maxout - currSent << "/"; + out << maxout; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + + return maxout - currSent; +} + +int pqistreamer::inAllowedBytes() +{ + int t = time(NULL); // get current timestep. + + /* allow a lot if not bandwidthLimited */ + if (!bio->bandwidthLimited()) + { + currReadTS = t; + currRead = 0; + return PQISTREAM_ABS_MAX; + } + + int dt = t - currReadTS; + // limiter -> for when currReadTs -> 0. + if (dt > 5) + dt = 5; + + int maxin = (int) (getMaxRate(true) * 1000.0); + currRead -= dt * maxin; + if (currRead < 0) + { + currRead = 0; + } + + currReadTS = t; + + { + std::ostringstream out; + out << "pqistreamer::inAllowedBytes() is "; + out << maxin - currRead << "/"; + out << maxin; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + + return maxin - currRead; +} + + +static const float AVG_PERIOD = 5; // sec +static const float AVG_FRAC = 0.8; // for low pass filter. + +void pqistreamer::outSentBytes(int outb) +{ + { + std::ostringstream out; + out << "pqistreamer::outSentBytes(): "; + out << outb << "@" << getRate(false) << "kB/s" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + + totalSent += outb; + currSent += outb; + avgSentCount += outb; + + int t = time(NULL); // get current timestep. + if (t - avgLastUpdate > AVG_PERIOD) + { + float avgReadpSec = getRate(true); + float avgSentpSec = getRate(false); + + avgReadpSec *= AVG_FRAC; + avgReadpSec += (1.0 - AVG_FRAC) * avgReadCount / + (1000.0 * (t - avgLastUpdate)); + + avgSentpSec *= AVG_FRAC; + avgSentpSec += (1.0 - AVG_FRAC) * avgSentCount / + (1000.0 * (t - avgLastUpdate)); + + + /* pretend our rate is zero if we are + * not bandwidthLimited(). + */ + if (bio->bandwidthLimited()) + { + setRate(true, avgReadpSec); + setRate(false, avgSentpSec); + } + else + { + setRate(true, 0); + setRate(false, 0); + } + + + avgLastUpdate = t; + avgReadCount = 0; + avgSentCount = 0; + } + return; +} + +void pqistreamer::inReadBytes(int inb) +{ + { + std::ostringstream out; + out << "pqistreamer::inReadBytes(): "; + out << inb << "@" << getRate(true) << "kB/s" << std::endl; + pqioutput(PQL_DEBUG_ALL, pqistreamerzone, out.str()); + } + + totalRead += inb; + currRead += inb; + avgReadCount += inb; + + return; +} + diff --git a/libretroshare/src/pqi/pqistreamer.h b/libretroshare/src/pqi/pqistreamer.h new file mode 100644 index 000000000..74b99c1b5 --- /dev/null +++ b/libretroshare/src/pqi/pqistreamer.h @@ -0,0 +1,116 @@ +/* + * libretroshare/src/pqi pqistreamer.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef MRK_PQI_STREAMER_HEADER +#define MRK_PQI_STREAMER_HEADER + +// Only dependent on the base stuff. +#include "pqi/pqi_base.h" +#include "util/rsthreads.h" + +#include + +// Fully implements the PQInterface. +// and communicates with peer etc via the BinInterface. +// +// The interface does not handle connection, just communication. +// possible bioflags: BIN_FLAGS_NO_CLOSE | BIN_FLAGS_NO_DELETE + +class pqistreamer: public PQInterface +{ +public: + pqistreamer(RsSerialiser *rss, std::string peerid, BinInterface *bio_in, int bio_flagsin); +virtual ~pqistreamer(); + +// PQInterface +virtual int SendItem(RsItem *); +virtual RsItem *GetItem(); + +virtual int tick(); +virtual int status(); + + private: + /* Implementation */ + + // to filter functions - detect filecancel/data and act! +int queue_outpqi( RsItem *i); +int handleincomingitem(RsItem *i); + + // ticked regularly (manages out queues and sending + // via above interfaces. +int handleoutgoing(); +int handleincoming(); + + // Bandwidth/Streaming Management. +float outTimeSlice(); + +int outAllowedBytes(); +void outSentBytes(int ); + +int inAllowedBytes(); +void inReadBytes(int ); + + // RsSerialiser - determines which packets can be serialised. + RsSerialiser *rsSerialiser; + // Binary Interface for IO, initialisated at startup. + BinInterface *bio; + unsigned int bio_flags; // BIN_FLAGS_NO_CLOSE | BIN_FLAGS_NO_DELETE + + void *pkt_wpending; // storage for pending packet to write. + int pkt_rpend_size; // size of pkt_rpending. + void *pkt_rpending; // storage for read in pending packets. + + enum {reading_state_packet_started=1, + reading_state_initial=0 } ; + + int reading_state ; + int failed_read_attempts ; + + // Temp Storage for transient data..... + std::list out_pkt; // Cntrl / Search / Results queue + std::list out_data; // FileData - secondary queue. + std::list incoming; + + // data for network stats. + int totalRead; + int totalSent; + + // these are representative (but not exact) + int currRead; + int currSent; + int currReadTS; // TS from which these are measured. + int currSentTS; + + int avgLastUpdate; // TS from which these are measured. + float avgReadCount; + float avgSentCount; + + RsMutex streamerMtx ; +// pthread_t thread_id; +}; + + +#endif //MRK_PQI_STREAMER_HEADER diff --git a/libretroshare/src/pqi/sslfns.cc b/libretroshare/src/pqi/sslfns.cc new file mode 100644 index 000000000..9e6c194be --- /dev/null +++ b/libretroshare/src/pqi/sslfns.cc @@ -0,0 +1,927 @@ +/* + * libretroshare/src/pqi: sslfns.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* Functions in this file are SSL only, + * and have no dependence on SSLRoot() etc. + * might need SSL_Init() to be called - thats it! + */ + +/******************** notify of new Cert **************************/ + +#include "pqi/sslfns.h" +#include "pqi/pqi_base.h" +#include "util/rsdir.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +/**** + * #define AUTHSSL_DEBUG 1 + ***/ + +/********************************************************************************/ + +#if defined(SSLFNS_ADD_CIPHER_CTX_RAND_KEY) + +int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) +{ + //if (ctx->cipher->flags & EVP_CIPH_RAND_KEY) + // return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key); + if (RAND_bytes(key, ctx->key_len) <= 0) + return 0; + return 1; +} + +#endif + +/********************************************************************************/ +/********************************************************************************/ + +X509_REQ *GenerateX509Req( + std::string pkey_file, std::string passwd, + std::string name, std::string email, std::string org, + std::string loc, std::string state, std::string country, + int nbits_in, std::string &errString) +{ + /* generate request */ + X509_REQ *req=X509_REQ_new(); + + // setup output. + BIO *bio_out = NULL; + bio_out = BIO_new(BIO_s_file()); + BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); + + EVP_PKEY *pkey = NULL; + + // first generate a key.... + if ((pkey=EVP_PKEY_new()) == NULL) + { + fprintf(stderr,"GenerateX509Req: Couldn't Create Key\n"); + errString = "Couldn't Create Key"; + return 0; + } + + int nbits = 2048; + unsigned long e = 0x10001; + + if ((nbits_in >= 512) && (nbits_in <= 4096)) + { + nbits = nbits_in; + } + else + { + fprintf(stderr,"GenerateX509Req: strange num of nbits: %d\n", nbits_in); + fprintf(stderr,"GenerateX509Req: reverting to %d\n", nbits); + } + + + RSA *rsa = RSA_generate_key(nbits, e, NULL, NULL); + if ((rsa == NULL) || !EVP_PKEY_assign_RSA(pkey, rsa)) + { + if(rsa) RSA_free(rsa); + fprintf(stderr,"GenerateX509Req: Couldn't Generate RSA Key!\n"); + errString = "Couldn't generate RSA Key"; + return 0; + } + + + // open the file. + FILE *out; + if (NULL == (out = RsDirUtil::rs_fopen(pkey_file.c_str(), "w"))) + { + fprintf(stderr,"GenerateX509Req: Couldn't Create Key File!"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + errString = "Couldn't Create Key File"; + return 0; + } + + const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); + + if (!PEM_write_PrivateKey(out,pkey,cipher, + NULL,0,NULL,(void *) passwd.c_str())) + { + fprintf(stderr,"GenerateX509Req() Couldn't Save Private Key"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + errString = "Couldn't Save Private Key File"; + return 0; + } + fclose(out); + + // We have now created a private key.... + fprintf(stderr,"GenerateX509Req() Saved Private Key"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + /********** Test Loading the private Key.... ************/ + FILE *tst_in = NULL; + EVP_PKEY *tst_pkey = NULL; + if (NULL == (tst_in = RsDirUtil::rs_fopen(pkey_file.c_str(), "rb"))) + { + fprintf(stderr,"GenerateX509Req() Couldn't Open Private Key"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + errString = "Couldn't Open Private Key"; + return 0; + } + + if (NULL == (tst_pkey = + PEM_read_PrivateKey(tst_in,NULL,NULL,(void *) passwd.c_str()))) + { + fprintf(stderr,"GenerateX509Req() Couldn't Read Private Key"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + errString = "Couldn't Read Private Key"; + return 0; + } + fclose(tst_in); + EVP_PKEY_free(tst_pkey); + /********** Test Loading the private Key.... ************/ + + /* Fill in details: fields. + req->req_info; + req->req_info->enc; + req->req_info->version; + req->req_info->subject; + req->req_info->pubkey; + ****************************/ + + long version = 0x00; + unsigned long chtype = MBSTRING_ASC; + X509_NAME *x509_name = X509_NAME_new(); + + // fill in the request. + + /**** X509_REQ -> Version ********************************/ + if (!X509_REQ_set_version(req,version)) /* version 1 */ + { + fprintf(stderr,"GenerateX509Req(): Couldn't Set Version!\n"); + + errString = "Couldn't Set Version"; + return 0; + } + /**** X509_REQ -> Version ********************************/ + /**** X509_REQ -> Key ********************************/ + + if (!X509_REQ_set_pubkey(req,pkey)) + { + fprintf(stderr,"GenerateX509Req() Couldn't Set PUBKEY !\n"); + + errString = "Couldn't Set PubKey"; + return 0; + } + + /**** SUBJECT ********************************/ + // create the name. + + // fields to add. + // commonName CN + // emailAddress (none) + // organizationName O + // localityName L + // stateOrProvinceName ST + // countryName C + + if (0 < strlen(name.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "CN", chtype, + (unsigned char *) name.c_str(), -1, -1, 0); + } + else + { + fprintf(stderr,"GenerateX509Req(): No Name -> Not creating X509 Cert Req\n"); + errString = "No Name, Aborting"; + return 0; + } + + if (0 < strlen(email.c_str())) + { + //X509_NAME_add_entry_by_txt(x509_name, "Email", 0, + // (unsigned char *) ui -> gen_email -> value(), -1, -1, 0); + X509_NAME_add_entry_by_NID(x509_name, 48, 0, + (unsigned char *) email.c_str(), -1, -1, 0); + } + + if (0 < strlen(org.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "O", chtype, + (unsigned char *) org.c_str(), -1, -1, 0); + } + + if (0 < strlen(loc.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "L", chtype, + (unsigned char *) loc.c_str(), -1, -1, 0); + } + + if (0 < strlen(state.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "ST", chtype, + (unsigned char *) state.c_str(), -1, -1, 0); + } + + if (0 < strlen(country.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "C", chtype, + (unsigned char *) country.c_str(), -1, -1, 0); + } + + if (!X509_REQ_set_subject_name(req,x509_name)) + { + fprintf(stderr,"GenerateX509Req() Couldn't Set Name to Request!\n"); + X509_NAME_free(x509_name); + + errString = "Couldn't Set Name"; + return 0; + } + + X509_NAME_free(x509_name); + /**** SUBJECT ********************************/ + + if (!X509_REQ_sign(req,pkey,EVP_sha1())) + { + fprintf(stderr,"GenerateX509Req() Failed to Sign REQ\n"); + + errString = "Couldn't Sign Req"; + return 0; + } + + errString = "No Error"; + return req; +} + +#define SERIAL_RAND_BITS 64 + +X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days) +{ + const EVP_MD *digest = EVP_sha1(); + ASN1_INTEGER *serial = ASN1_INTEGER_new(); + EVP_PKEY *tmppkey; + X509 *x509 = X509_new(); + if (x509 == NULL) + return NULL; + + BIGNUM *btmp = BN_new(); + if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," pseudo_rand\n"); + + return NULL; + } + if (!BN_to_ASN1_INTEGER(btmp, serial)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," int\n"); + + return NULL; + } + BN_free(btmp); + + if (!X509_set_serialNumber(x509, serial)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," serialNumber\n"); + + return NULL; + } + ASN1_INTEGER_free(serial); + + if (!X509_set_issuer_name(x509, issuer)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," issuer\n"); + + return NULL; + } + + if (!X509_gmtime_adj(x509->cert_info->validity->notBefore, 0)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," notBefore\n"); + + return NULL; + } + + //x509->cert_info->validity->notAfter + //if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*days)) + if (!X509_gmtime_adj(x509->cert_info->validity->notAfter, (long)60*60*24*days)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," notAfter\n"); + + return NULL; + } + + if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req))) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," subject_name\n"); + + return NULL; + } + + + tmppkey = X509_REQ_get_pubkey(req); + if (!tmppkey || !X509_set_pubkey(x509,tmppkey)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," pubkey\n"); + + return NULL; + } + + + /* Cleanup Algorithm part */ + + X509_ALGOR *algor1 = x509->cert_info->signature; + X509_ALGOR *algor2 = x509->sig_alg; + + X509_ALGOR *a; + + a = algor1; + ASN1_TYPE_free(a->parameter); + a->parameter=ASN1_TYPE_new(); + a->parameter->type=V_ASN1_NULL; + + ASN1_OBJECT_free(a->algorithm); + a->algorithm=OBJ_nid2obj(digest->pkey_type); + + a = algor2; + ASN1_TYPE_free(a->parameter); + a->parameter=ASN1_TYPE_new(); + a->parameter->type=V_ASN1_NULL; + + ASN1_OBJECT_free(a->algorithm); + a->algorithm=OBJ_nid2obj(digest->pkey_type); + + + if (!X509_sign(x509,privkey,digest)) + { + long e = ERR_get_error(); + + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," signing Error: %ld\n", e); + + fprintf(stderr,"ERR: %s, %s, %s\n", + ERR_lib_error_string(e), + ERR_func_error_string(e), + ERR_reason_error_string(e)); + + int inl=i2d_X509(x509,NULL); + int outl=EVP_PKEY_size(privkey); + fprintf(stderr,"Size Check: inl: %d, outl: %d\n", inl, outl); + + return NULL; + } + + fprintf(stderr,"SignX509Certificate() Success\n"); + + return x509; +} + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + + + /* Sign / Encrypt / Verify Data */ +bool SSL_SignDataBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int *signlen, EVP_PKEY *pkey) +{ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + unsigned int req_signlen = EVP_PKEY_size(pkey); + if (req_signlen > *signlen) + { + /* not enough space */ + std::cerr << "SignDataBin() Not Enough Sign SpacegnInit Failure!" << std::endl; + return false; + } + + if (0 == EVP_SignInit(mdctx, EVP_sha1())) + { + std::cerr << "EVP_SignInit Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if (0 == EVP_SignUpdate(mdctx, data, len)) + { + std::cerr << "EVP_SignUpdate Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if (0 == EVP_SignFinal(mdctx, sign, signlen, pkey)) + { + std::cerr << "EVP_SignFinal Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + EVP_MD_CTX_destroy(mdctx); + return true; +} + +bool SSL_VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, X509 *cert) +{ + + /* cert->cert_info->key->pkey is NULL.... + * but is instantiated when we call X509_get_pubkey() + */ + + EVP_PKEY *peerkey = X509_get_pubkey(cert); + + /* must free this key afterwards */ + bool ret = SSL_VerifySignBin(data, len, sign, signlen, peerkey); + + EVP_PKEY_free(peerkey); + + return ret; +} + +/* Correct form of this function ... Internal for AuthSSL's usage + */ + +bool SSL_VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, EVP_PKEY *peerkey) +{ + if(peerkey == NULL) + { + std::cerr << "VerifySignBin: no public key available !!" << std::endl ; + return false ; + } + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + if (0 == EVP_VerifyInit(mdctx, EVP_sha1())) + { + std::cerr << "EVP_VerifyInit Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if (0 == EVP_VerifyUpdate(mdctx, data, len)) + { + std::cerr << "EVP_VerifyUpdate Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if(signlen == 0 || sign == NULL) + { + std::cerr << "AuthSSL::VerifySignBin: signlen=" << signlen << ", sign=" << (void*)sign << "!!" << std::endl ; + EVP_MD_CTX_destroy(mdctx); + return false ; + } + + if (0 == EVP_VerifyFinal(mdctx, sign, signlen, peerkey)) + { + std::cerr << "EVP_VerifyFinal Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + EVP_MD_CTX_destroy(mdctx); + return true; +} + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +X509 *loadX509FromPEM(std::string pem) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "loadX509FromPEM()"; + std::cerr << std::endl; +#endif + + /* Put the data into a mem BIO */ + char *certstr = strdup(pem.c_str()); + + BIO *bp = BIO_new_mem_buf(certstr, -1); + + X509 *pc = PEM_read_bio_X509(bp, NULL, NULL, NULL); + + BIO_free(bp); + free(certstr); + + return pc; +} + +std::string saveX509ToPEM(X509* x509) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "saveX509ToPEM() " << std::endl; +#endif + + /* get the cert first */ + std::string certstr; + BIO *bp = BIO_new(BIO_s_mem()); + + PEM_write_bio_X509(bp, x509); + + /* translate the bp data to a string */ + char *data; + int len = BIO_get_mem_data(bp, &data); + for(int i = 0; i < len; i++) + { + certstr += data[i]; + } + + BIO_free(bp); + + return certstr; +} + + +X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::LoadX509FromDER()"; + std::cerr << std::endl; +#endif + + X509 *tmp = NULL; +#ifdef __APPLE__ + // This depends on which version you are compiling for... OSX10.5 doesn't have consts (old OpenSSL!) + unsigned char **certptr = (unsigned char **) &ptr; + //const unsigned char **certptr = (const unsigned char **) &ptr; +#else + const unsigned char **certptr = (const unsigned char **) &ptr; +#endif + + X509 *x509 = d2i_X509(&tmp, certptr, len); + + return x509; +} + +bool saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::saveX509ToDER()"; + std::cerr << std::endl; +#endif + + int certlen = i2d_X509(x509, (unsigned char **) ptr); + if (certlen > 0) + { + *len = certlen; + return true; + } + else + { + *len = 0; + return false; + } + return false; +} + + +bool getX509id(X509 *x509, std::string &xid) { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::getX509id()"; + std::cerr << std::endl; +#endif + + xid = ""; + if (x509 == NULL) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::getX509id() NULL pointer"; + std::cerr << std::endl; +#endif + return false; + } + + // get the signature from the cert, and copy to the array. + ASN1_BIT_STRING *signature = x509->signature; + int signlen = ASN1_STRING_length(signature); + if (signlen < CERTSIGNLEN) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::getX509id() ERROR: Short Signature"; + std::cerr << std::endl; +#endif + return false; + } + + // else copy in the first CERTSIGNLEN. + unsigned char *signdata = ASN1_STRING_data(signature); + + std::ostringstream id; + /* switched to the other end of the signature. for + * more randomness + */ + for(int i = signlen - CERTSIGNLEN; i < signlen; i++) + { + id << std::hex << std::setw(2) << std::setfill('0') + << (uint16_t) (((uint8_t *) (signdata))[i]); + } + xid = id.str(); + return true; +} + + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +int pem_passwd_cb(char *buf, int size, int rwflag, void *password) +{ + /* remove unused parameter warnings */ + (void) rwflag; + + strncpy(buf, (char *)(password), size); + buf[size - 1] = '\0'; + return(strlen(buf)); +} + +/* XXX FIX */ +bool CheckX509Certificate(X509 *x509) +{ + + return true; +} + + +// Not dependent on sslroot. load, and detroys the X509 memory. +int LoadCheckX509(const char *cert_file, std::string &issuerName, std::string &location, std::string &userId) +{ + /* This function loads the X509 certificate from the file, + * and checks the certificate + */ + + FILE *tmpfp = RsDirUtil::rs_fopen(cert_file, "r"); + if (tmpfp == NULL) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "sslroot::LoadCheckAndGetX509Name()"; + std::cerr << " Failed to open Certificate File:" << cert_file; + std::cerr << std::endl; +#endif + return 0; + } + + // get xPGP certificate. + X509 *x509 = PEM_read_X509(tmpfp, NULL, NULL, NULL); + fclose(tmpfp); + + // check the certificate. + bool valid = false; + if (x509) + { + valid = CheckX509Certificate(x509); + if (valid) + { + valid = getX509id(x509, userId); + } + } + + if (valid) + { + // extract the name. + issuerName = getX509CNString(x509->cert_info->issuer); + location = getX509LocString(x509->cert_info->subject); + } + + #ifdef AUTHSSL_DEBUG + std::cout << getX509Info(x509) << std::endl ; + #endif + // clean up. + X509_free(x509); + + if (valid) + { + // happy! + return 1; + } + else + { + // something went wrong! + return 0; + } +} + + + + +std::string getX509NameString(X509_NAME *name) +{ + std::string namestr; + for(int i = 0; i < X509_NAME_entry_count(name); i++) + { + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); + ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); + + namestr += "\t"; + namestr += OBJ_nid2ln(OBJ_obj2nid(entry_obj)); + namestr += " : "; + + //namestr += entry_obj -> flags; + //namestr += entry_data -> length; + //namestr += entry_data -> type; + + //namestr += entry_data -> flags; + //entry -> set; + + if (entry_data -> data != NULL) + { + namestr += (char *) entry_data -> data; + } + else + { + namestr += "NULL"; + } + + if (i + 1 < X509_NAME_entry_count(name)) + { + namestr += "\n"; + } + + } + return namestr; +} + + +std::string getX509CNString(X509_NAME *name) +{ + std::string namestr; + for(int i = 0; i < X509_NAME_entry_count(name); i++) + { + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); + ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); + + if (0 == strncmp("CN", OBJ_nid2sn(OBJ_obj2nid(entry_obj)), 2)) + { + if (entry_data -> data != NULL) + { + namestr += (char *) entry_data -> data; + } + else + { + namestr += "Unknown"; + } + return namestr; + } + } + return namestr; +} + + +std::string getX509TypeString(X509_NAME *name, const char *type, int len) +{ + std::string namestr; + for(int i = 0; i < X509_NAME_entry_count(name); i++) + { + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); + ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); + + if (0 == strncmp(type, OBJ_nid2sn(OBJ_obj2nid(entry_obj)), len)) + { + if (entry_data -> data != NULL) + { + namestr += (char *) entry_data -> data; + } + else + { + namestr += "Unknown"; + } + return namestr; + } + } + return namestr; +} + + +std::string getX509LocString(X509_NAME *name) +{ + return getX509TypeString(name, "L", 2); +} + +std::string getX509OrgString(X509_NAME *name) +{ + return getX509TypeString(name, "O", 2); +} + + +std::string getX509CountryString(X509_NAME *name) +{ + return getX509TypeString(name, "C", 2); +} + + +std::string getX509Info(X509 *cert) +{ + std::stringstream out; + long l; + + out << "X509 Certificate:" << std::endl; + l=X509_get_version(cert); + out << " Version: " << l+1 << "(0x" << l << ")" << std::endl; + out << " Subject: " << std::endl; + out << " " << getX509NameString(cert->cert_info->subject); + out << std::endl; + out << std::endl; + out << " Signatures:" << std::endl; + return out.str(); +} + +/********** SSL ERROR STUFF ******************************************/ + +int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, + std::ostream &out) +{ + (void) ssl; /* remove unused parameter warnings */ + + std::string reason; + + std::string mainreason = std::string("UNKNOWN ERROR CODE"); + if (err == SSL_ERROR_NONE) + { + mainreason = std::string("SSL_ERROR_NONE"); + } + else if (err == SSL_ERROR_ZERO_RETURN) + { + mainreason = std::string("SSL_ERROR_ZERO_RETURN"); + } + else if (err == SSL_ERROR_WANT_READ) + { + mainreason = std::string("SSL_ERROR_WANT_READ"); + } + else if (err == SSL_ERROR_WANT_WRITE) + { + mainreason = std::string("SSL_ERROR_WANT_WRITE"); + } + else if (err == SSL_ERROR_WANT_CONNECT) + { + mainreason = std::string("SSL_ERROR_WANT_CONNECT"); + } + else if (err == SSL_ERROR_WANT_ACCEPT) + { + mainreason = std::string("SSL_ERROR_WANT_ACCEPT"); + } + else if (err == SSL_ERROR_WANT_X509_LOOKUP) + { + mainreason = std::string("SSL_ERROR_WANT_X509_LOOKUP"); + } + else if (err == SSL_ERROR_SYSCALL) + { + mainreason = std::string("SSL_ERROR_SYSCALL"); + } + else if (err == SSL_ERROR_SSL) + { + mainreason = std::string("SSL_ERROR_SSL"); + } + out << "RetVal(" << retval; + out << ") -> SSL Error: " << mainreason << std::endl; + out << "\t + ERR Error: " << ERR_error_string(err2, NULL) << std::endl; + return 1; +} + diff --git a/libretroshare/src/pqi/sslfns.h b/libretroshare/src/pqi/sslfns.h new file mode 100644 index 000000000..e1c61ea43 --- /dev/null +++ b/libretroshare/src/pqi/sslfns.h @@ -0,0 +1,131 @@ +#ifndef RS_PQI_SSL_HELPER_H +#define RS_PQI_SSL_HELPER_H + +/* + * libretroshare/src/pqi: sslfns.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* Functions in this file are SSL only, + * and have no dependence on SSLRoot() etc. + * might need SSL_Init() to be called - thats it! + */ + +/******************** notify of new Cert **************************/ + +#include +#include +#include + +#include +#include + +/**** + * #define AUTHSSL_DEBUG 1 + ***/ + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + + +// IF we are compiling against ssl0.9.7 - these functions don't exist. + +#if (OPENSSL_VERSION_NUMBER & 0xfffff000) < 0x00908000 + #define SSLFNS_ADD_CIPHER_CTX_RAND_KEY 1 +#endif + +#if defined(SSLFNS_ADD_CIPHER_CTX_RAND_KEY) + +int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key); + +#endif + + + +X509_REQ *GenerateX509Req( + std::string pkey_file, std::string passwd, + std::string name, std::string email, std::string org, + std::string loc, std::string state, std::string country, + int nbits_in, std::string &errString); + +X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days); + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + + + /* Sign / Encrypt / Verify Data */ +bool SSL_SignDataBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int *signlen, EVP_PKEY *pkey); + +bool SSL_VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, X509 *cert); + +bool SSL_VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, EVP_PKEY *peerkey); + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +X509 *loadX509FromPEM(std::string pem); +std::string saveX509ToPEM(X509* x509); +X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len); +bool saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len); + +bool getX509id(X509 *x509, std::string &xid); + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +int pem_passwd_cb(char *buf, int size, int rwflag, void *password); + +bool CheckX509Certificate(X509 *x509); +// Not dependent on sslroot. load, and detroys the X509 memory. +int LoadCheckX509(const char *cert_file, std::string &issuerName, std::string &location, std::string &userId); + + +std::string getX509NameString(X509_NAME *name); +std::string getX509CNString(X509_NAME *name); +std::string getX509TypeString(X509_NAME *name, const char *type, int len); +std::string getX509LocString(X509_NAME *name); +std::string getX509OrgString(X509_NAME *name); +std::string getX509CountryString(X509_NAME *name); +std::string getX509Info(X509 *cert); + +/********** SSL ERROR STUFF ******************************************/ + +int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, + std::ostream &out); + +#endif /* RS_PQI_SSL_HELPER_H */ + diff --git a/libretroshare/src/retroshare/Makefile b/libretroshare/src/retroshare/Makefile new file mode 100644 index 000000000..0b4646b09 --- /dev/null +++ b/libretroshare/src/retroshare/Makefile @@ -0,0 +1,25 @@ + +RS_TOP_DIR = .. +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/scripts/config.mk +############################################################### + +OBJ = notifytxt.o retroshare.o + +#TESTOBJ = + +TESTS = retroshare-nogui + +all: tests + +retroshare-nogui: $(OBJ) + $(CC) $(CFLAGS) -o retroshare-nogui $(OBJ) $(LIBS) + + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/retroshare/rsblogs.h b/libretroshare/src/retroshare/rsblogs.h new file mode 100644 index 000000000..35586c3b4 --- /dev/null +++ b/libretroshare/src/retroshare/rsblogs.h @@ -0,0 +1,154 @@ +#ifndef RS_BLOG_GUI_INTERFACE_H +#define RS_BLOG_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsblogs.h + * + * RetroShare C++ Interface. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include + +#include "rstypes.h" +#include "rsdistrib.h" /* For FLAGS */ + +class BlogInfo +{ + public: + BlogInfo() {} + std::string blogId; + std::wstring blogName; + std::wstring blogDesc; + + uint32_t blogFlags; + uint32_t pop; + + unsigned char* pngChanImage; + uint32_t pngImageLen; + + time_t lastPost; +}; + +class BlogMsgInfo +{ + public: + BlogMsgInfo() {} + std::string blogId; + std::string msgId; + /// this has a value if replying to another msg + std::string msgIdReply; + + unsigned int msgflags; + + std::wstring subject; + std::wstring msg; + time_t ts; + + std::list files; + uint32_t count; + uint64_t size; +}; + + +class BlogMsgSummary +{ + public: + BlogMsgSummary() {} + std::string blogId; + std::string msgId; + + uint32_t msgflags; + + std::wstring subject; + std::wstring msg; + std::string msgIdReply; + uint32_t count; /* file count */ + time_t ts; + +}; + +std::ostream &operator<<(std::ostream &out, const BlogInfo &info); +std::ostream &operator<<(std::ostream &out, const BlogMsgSummary &info); +std::ostream &operator<<(std::ostream &out, const BlogMsgInfo &info); + +class RsBlogs; +extern RsBlogs *rsBlogs; + +class RsBlogs +{ + public: + + RsBlogs() { return; } +virtual ~RsBlogs() { return; } + +/****************************************/ + +/*! + * Checks if the group a blod id belongs to has changed + */ +virtual bool blogsChanged(std::list &blogIds) = 0; + + +virtual std::string createBlog(std::wstring blogName, std::wstring blogDesc, uint32_t blogFlags, + unsigned char* pngImageData, uint32_t imageSize) = 0; + +virtual bool getBlogInfo(std::string cId, BlogInfo &ci) = 0; +virtual bool getBlogList(std::list &chanList) = 0; +virtual bool getBlogMsgList(std::string cId, std::list &msgs) = 0; + +/*! + * Retrieves a specific blog Msg based on group Id and message Id + */ +virtual bool getBlogMessage(std::string cId, std::string mId, BlogMsgInfo &msg) = 0; + +/*! + * Can send blog message to user + * @param info the message + */ +virtual bool BlogMessageSend(BlogMsgInfo &info) = 0; + +/*! + * Allows user to subscribe to a blog via group ID + * @param cId group id + * @param subscribe determine subscription based on value + */ +virtual bool blogSubscribe(std::string cId, bool subscribe) = 0; + +/*! + * Commenting on other user's blogs, ensure field info has a valid info.msgIdReply has valid msg id, this + * points to which message the blog reply is replying to + */ +virtual bool BlogMessageReply(BlogMsgInfo &info) = 0; + +/*! + * + */ +virtual bool isReply(BlogMsgInfo &info) = 0; +/****************************************/ + +}; + + +#endif diff --git a/libretroshare/src/retroshare/rschannels.h b/libretroshare/src/retroshare/rschannels.h new file mode 100644 index 000000000..8c98283cc --- /dev/null +++ b/libretroshare/src/retroshare/rschannels.h @@ -0,0 +1,278 @@ +#ifndef RS_CHANNEL_GUI_INTERFACE_H +#define RS_CHANNEL_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rschannels.h + * + * RetroShare C++ Interface. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include + +#include "rstypes.h" +#include "rsdistrib.h" /* For FLAGS */ + +#define CHANNEL_MSG_STATUS_MASK 0x000f +#define CHANNEL_MSG_STATUS_READ 0x0001 +#define CHANNEL_MSG_STATUS_UNREAD_BY_USER 0x0002 +#define CHANNEL_MSG_STATUS_DOWLOADED 0x0004 + + +//! Stores information for a give channel id +/*! + * Stores all information for a given channel id + */ +class ChannelInfo +{ + public: + ChannelInfo() : autoDownload(false), pngChanImage(NULL), pngImageLen(0) + {} + std::string channelId; + std::wstring channelName; + std::wstring channelDesc; + + uint32_t channelFlags; + uint32_t pop; /// popularity + bool autoDownload; + + unsigned char* pngChanImage; + uint32_t pngImageLen; + + time_t lastPost; +}; + +//! for storing a channel msgs thumbnail picture +class ChannelMsgThumbnail +{ +public: + ChannelMsgThumbnail() : image_thumbnail(NULL), im_thumbnail_size(0) {} + + unsigned char* image_thumbnail; + int im_thumbnail_size; +}; + +//! Stores information on a message within a channel +class ChannelMsgInfo +{ + public: + ChannelMsgInfo () : count(0), size(0) {} + std::string channelId; + std::string msgId; + + unsigned int msgflags; + + std::wstring subject; + std::wstring msg; + time_t ts; /// time stamp + + std::list files; + uint32_t count; /// file count + uint64_t size; /// size of all files + + ChannelMsgThumbnail thumbnail; + +}; + + +//! gives a more brief account of a channel message than channelMsgInfo +class ChannelMsgSummary +{ + public: + ChannelMsgSummary() : count(0) {} + std::string channelId; + std::string msgId; + + uint32_t msgflags; + + std::wstring subject; + std::wstring msg; + uint32_t count; /// file count + time_t ts; /// time stamp + +}; + +std::ostream &operator<<(std::ostream &out, const ChannelInfo &info); +std::ostream &operator<<(std::ostream &out, const ChannelMsgSummary &info); +std::ostream &operator<<(std::ostream &out, const ChannelMsgInfo &info); + +class RsChannels; +extern RsChannels *rsChannels; + +/*! + * retroshare interface to the channels distributed group service + * Channels user to create feeds similar to RSS feed where you can share files + * with other users, when you subscribe to a channel you immediately begin downloading + * the file shared on that channel. Channel feeds are shared anonymously + */ +class RsChannels +{ + public: + + RsChannels() { return; } +virtual ~RsChannels() { return; } + +/****************************************/ + +/*! + * returns a list of channel id that have changed (i.e. received new message, chan descr update) + * @param chanIds this is populated with channel ids that have changed + */ +virtual bool channelsChanged(std::list &chanIds) = 0; + +/*! + * @param chanName name of the channel + * @param chanDesc a short description for the created channel + * @param chanFlags admin details on created channel group see rsdistrib.h for flags types + * @param pngImageData point at image data in PNG format + * @param imageSize size of the image data + */ +virtual std::string createChannel(std::wstring chanName, std::wstring chanDesc, uint32_t chanFlags, + unsigned char* pngImageData, uint32_t imageSize) = 0; + +/*! + * retrieve channel information + * @param cId channel id + * @param ci channel info is store here + */ +virtual bool getChannelInfo(std::string cId, ChannelInfo &ci) = 0; + +/*! + * @param chanList populated channelinfo for all channels + */ +virtual bool getChannelList(std::list &chanList) = 0; + +/*! + * get a message summary list for a given channel id + * @param cId channel id user wants messages for + * @param msgs summary of messages for the given cId + */ +virtual bool getChannelMsgList(std::string cId, std::list &msgs) = 0; + +/*! + * retrieve more comprehensive message info given channel id and message id + */ +virtual bool getChannelMessage(std::string cId, std::string mId, ChannelMsgInfo &msg) = 0; + +/*! + * set message status + * @param cId channel id + * @param mId message id + * @param status status to set + * @param statusMask bitmask to modify + */ +virtual bool setMessageStatus(const std::string& cId,const std::string& mId, const uint32_t status, const uint32_t statusMask) = 0; + +/*! + * set message status + * @param cId channel id + * @param mId message id + * @param status status + */ +virtual bool getMessageStatus(const std::string& cId, const std::string& mId, uint32_t& status) = 0; + +/*! + * count the new and unread messages + * @param cId channel id + * @param newCount count of new messages + * @param unreadCount count of unread messages + */ +virtual bool getMessageCount(const std::string cId, unsigned int &newCount, unsigned int &unreadCount) = 0; + +/*! + * send message contain in message info to the id indicated within it (make sure you set the channel id of the message info) + * @param info message to be sent + */ +virtual bool ChannelMessageSend(ChannelMsgInfo &info) = 0; + +/*! + * @param cId the channel id + * @param subscribe set to true if you want to subscribe and to false to unsubscribe + * @param set true to allow autodownload of new content and false otherwise, ignored when second param is false + */ +virtual bool channelSubscribe(std::string cId, bool subscribe, bool autoDl) = 0; + +/*! + * This hashes a file which is not already shared by client or his peers, + * The file is copied into the channels directory if its not too large (> 100mb) + * @param path This is full path to file + * @param channel Id + */ +virtual bool channelExtraFileHash(std::string path, std::string chId, FileInfo& fInfo) = 0; + +/*! + * This removes hashed extra files, and also removes channels directory copy if it exists + * @param chId channel id + */ +virtual bool channelExtraFileRemove(std::string hash, std::string chId) = 0; + +/*! + * Restores channel private keys for channel in the event keys stored in configuration files are lost + * @param chId channel id to restore keys for + */ +virtual bool channelRestoreKeys(std::string chId) = 0; + +/*! + * shares keys with peers + *@param chId the channel for which private publish keys will be shared + *@param peers peers in this list will be sent keys + * + */ +virtual bool channelShareKeys(std::string chId, std::list& peers) = 0; +/****************************************/ + +/*! + * allows peers to change information for the channel: + * can only change channel image, descriptions and name + * + */ +virtual bool channelEditInfo(std::string chId, ChannelInfo &ci) = 0; + + +/*! + * get list of channels for which private publish key is available + * @param grpIds list of channels for which private publish key is available + */ +virtual void getPubKeysAvailableGrpIds(std::list& chanIds) = 0; + +/*! + * set the channel so that it does not auto download any more + * @param chId the channel id to set for + * @param set to true to enable auto dl and false to disable + */ +virtual bool channelSetAutoDl(const std::string& chId, bool autoDl) = 0; + + +/*! + * get what autoDl is set to for the given channel id + * @param chId id of channel to get autoDl status for + * @param autoDl + * @return false if channel cannot be found + */ +virtual bool channelGetAutoDl(const std::string& chId, bool& autoDl) = 0; + +}; + + +#endif diff --git a/libretroshare/src/retroshare/rsdisc.h b/libretroshare/src/retroshare/rsdisc.h new file mode 100644 index 000000000..c1f25cc15 --- /dev/null +++ b/libretroshare/src/retroshare/rsdisc.h @@ -0,0 +1,52 @@ +#ifndef RETROSHARE_DISC_GUI_INTERFACE_H +#define RETROSHARE_DISC_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsdisc.h + * + * RetroShare C++ Interface. + * + * Copyright 2008-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include +#include + +/* The Main Interface Class - for information about your Peers */ +class RsDisc; +extern RsDisc *rsDisc; + +class RsDisc +{ + public: + + RsDisc() { return; } +virtual ~RsDisc() { return; } + +virtual bool getDiscFriends(std::string id, std::list& friends) = 0; +virtual bool getDiscGPGFriends(std::string id, std::list& gpg_friends) = 0; +virtual bool getDiscVersions(std::map &versions) = 0; +virtual bool getWaitingDiscCount(unsigned int *sendCount, unsigned int *recvCount) = 0; + +}; + +#endif diff --git a/libretroshare/src/retroshare/rsdistrib.h b/libretroshare/src/retroshare/rsdistrib.h new file mode 100644 index 000000000..9faee45ff --- /dev/null +++ b/libretroshare/src/retroshare/rsdistrib.h @@ -0,0 +1,56 @@ +#ifndef RS_DISTRIB_GUI_INTERFACE_H +#define RS_DISTRIB_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsdistrib.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#define RS_DISTRIB_PRIVACY_MASK 0x0000000f /* who can publish & view */ +#define RS_DISTRIB_AUTHEN_MASK 0x000000f0 /* how to publish */ +#define RS_DISTRIB_LISTEN_MASK 0x00000f00 /* distribution flags */ +#define RS_DISTRIB_UPDATE_MASK 0x0000f000 /* if sending a group info update */ +#define RS_DISTRIB_MISC_MASK 0x00ff0000 /* if sending a group info update */ + +#define RS_DISTRIB_PUBLIC 0x00000001 /* anyone can publish */ +#define RS_DISTRIB_PRIVATE 0x00000002 /* anyone with key can publish */ +#define RS_DISTRIB_ENCRYPTED 0x00000004 /* need publish key to view */ + +#define RS_DISTRIB_AUTHEN_REQ 0x00000010 /* you must sign messages */ +#define RS_DISTRIB_AUTHEN_ANON 0x00000020 /* you can send anonymous messages */ + +#define RS_DISTRIB_ADMIN 0x00000100 +#define RS_DISTRIB_PUBLISH 0x00000200 +#define RS_DISTRIB_SUBSCRIBED 0x00000400 + +#define RS_DISTRIB_UPDATE 0x00001000 + +/* don't know if this should go with the above flags, as it message specific, and not a group settings. + * As it is currently not stored any configuration, it can be changed. + */ + +#define RS_DISTRIB_MISSING_MSG 0x00010000 + + +#endif diff --git a/libretroshare/src/retroshare/rsexpr.h b/libretroshare/src/retroshare/rsexpr.h new file mode 100755 index 000000000..eaeb4c864 --- /dev/null +++ b/libretroshare/src/retroshare/rsexpr.h @@ -0,0 +1,347 @@ +#ifndef RS_EXPRESSIONS_H +#define RS_EXPRESSIONS_H + +/* + * rs-core/src/rsiface: rsexpr.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Kashif Kaleem. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include + +/****************************************************************************************** +Enumerations defining the Operators usable in the Boolean search expressions +******************************************************************************************/ + + +enum LogicalOperator{ + AndOp=0, /* exp AND exp */ + OrOp=1, /* exp OR exp */ + XorOp=2 /* exp XOR exp */ +}; + + +/*Operators for String Queries*/ +enum StringOperator{ + ContainsAnyStrings = 0, /* e.g. name contains any of 'conference' 'meeting' 'presentation' */ + ContainsAllStrings = 1, /* same as above except that it contains ALL of the strings */ + EqualsString = 2 /* exactly equal*/ +}; + +/*Relational operators ( >, <, >=, <=, == and InRange )*/ +enum RelOperator{ + Equals = 0, + GreaterEquals = 1, + Greater = 2, + SmallerEquals = 3, + Smaller = 4, + InRange = 5 /* lower limit <= value <= upper limit*/ +}; + +/******************************************************************************************** + * Helper class for further serialisation + ********************************************************************************************/ + +class StringExpression ; +class Expression ; + +class LinearizedExpression +{ + public: + std::vector _tokens ; + std::vector _ints ; + std::vector _strings ; + + typedef enum { EXPR_DATE= 0, + EXPR_POP = 1, + EXPR_SIZE= 2, + EXPR_HASH= 3, + EXPR_NAME= 4, + EXPR_PATH= 5, + EXPR_EXT = 6, + EXPR_COMP= 7, + EXPR_SIZE_MB=8 } token ; + + static Expression *toExpr(const LinearizedExpression& e) ; + + private: + static Expression *toExpr(const LinearizedExpression& e,int&,int&,int&) ; + static void readStringExpr(const LinearizedExpression& e,int& n_ints,int& n_strings,std::list& strings,bool& b,StringOperator& op) ; +}; + + +/****************************************************************************************** +Boolean Search Expression +classes: + + Expression: The base class of all expression typest + CompoundExpression: The expression which uses a logical operator to combine + the results of two expressions + StringExpression: An expression which uses some sort of string comparison. + RelExpression: A Relational Expression where > < >= <= == make sense. + e.g. size date etc + +******************************************************************************************/ + +class FileEntry; + +class Expression +{ + public: + virtual bool eval (FileEntry *file) = 0; + virtual ~Expression() {}; + + virtual void linearize(LinearizedExpression& e) const = 0 ; +}; + + +class CompoundExpression : public Expression +{ + public: + CompoundExpression( enum LogicalOperator op, Expression * exp1, Expression *exp2) + : Lexp(exp1), Rexp(exp2), Op(op){ } + + bool eval (FileEntry *file) { + if (Lexp == NULL or Rexp == NULL) { + return false; + } + switch (Op){ + case AndOp: + return Lexp->eval(file) && Rexp->eval(file); + case OrOp: + return Lexp->eval(file) || Rexp->eval(file); + case XorOp: + return Lexp->eval(file) ^ Rexp->eval(file); + default: + return false; + } + } + virtual ~CompoundExpression(){ + delete Lexp; + delete Rexp; + } + + virtual void linearize(LinearizedExpression& e) const ; + private: + Expression *Lexp; + Expression *Rexp; + enum LogicalOperator Op; + +}; + +class StringExpression: public Expression +{ + public: + StringExpression(enum StringOperator op, std::list &t, bool ic): Op(op),terms(t), IgnoreCase(ic){} + + virtual void linearize(LinearizedExpression& e) const ; + protected: + bool evalStr(std::string &str); + + enum StringOperator Op; + std::list terms; + bool IgnoreCase; +}; + +template +class RelExpression: public Expression +{ + public: + RelExpression(enum RelOperator op, T lv, T hv): Op(op), LowerValue(lv), HigherValue(hv) {} + + virtual void linearize(LinearizedExpression& e) const ; + protected: + bool evalRel(T val); + + enum RelOperator Op; + T LowerValue; + T HigherValue; +}; + +template<> void RelExpression::linearize(LinearizedExpression& e) const ; + +template +bool RelExpression::evalRel(T val) { + switch (Op) { + case Equals: + return LowerValue == val; + case GreaterEquals: + return LowerValue >= val; + case Greater: + return LowerValue > val; + case SmallerEquals: + return LowerValue <= val; + case Smaller: + return LowerValue < val; + case InRange: + return (LowerValue <= val) && (val <= HigherValue); + default: + return false; + } +} + + +/****************************************************************************************** +Binary Predicate for Case Insensitive search + +******************************************************************************************/ +/*Binary predicate for case insensitive character comparison.*/ +/*TODOS: + *Factor locales in the comparison + */ +struct CompareCharIC : + public std::binary_function< char , char , bool> { + + bool operator () ( char ch1 , char ch2 ) const { + return tolower( static_cast < unsigned char > (ch1) ) + == tolower( static_cast < unsigned char > (ch2) ); + } + +}; + +/****************************************************************************************** +Some implementations of StringExpressions. + +******************************************************************************************/ + +class NameExpression: public StringExpression +{ + public: + NameExpression(enum StringOperator op, std::list &t, bool ic): + StringExpression(op,t,ic) {} + bool eval(FileEntry *file); + + virtual void linearize(LinearizedExpression& e) const + { + e._tokens.push_back(LinearizedExpression::EXPR_NAME) ; + StringExpression::linearize(e) ; + } +}; + +class PathExpression: public StringExpression { +public: + PathExpression(enum StringOperator op, std::list &t, bool ic): + StringExpression(op,t,ic) {} + bool eval(FileEntry *file); + + virtual void linearize(LinearizedExpression& e) const + { + e._tokens.push_back(LinearizedExpression::EXPR_PATH) ; + StringExpression::linearize(e) ; + } +}; + +class ExtExpression: public StringExpression { +public: + ExtExpression(enum StringOperator op, std::list &t, bool ic): + StringExpression(op,t,ic) {} + bool eval(FileEntry *file); + + virtual void linearize(LinearizedExpression& e) const + { + e._tokens.push_back(LinearizedExpression::EXPR_EXT) ; + StringExpression::linearize(e) ; + } +}; + +class HashExpression: public StringExpression { +public: + HashExpression(enum StringOperator op, std::list &t): + StringExpression(op,t, true) {} + bool eval(FileEntry *file); + + virtual void linearize(LinearizedExpression& e) const + { + e._tokens.push_back(LinearizedExpression::EXPR_HASH) ; + StringExpression::linearize(e) ; + } +}; + +/****************************************************************************************** +Some implementations of Relational Expressions. + +******************************************************************************************/ + +class DateExpression: public RelExpression +{ + public: + DateExpression(enum RelOperator op, int v): RelExpression(op,v,v){} + DateExpression(enum RelOperator op, int lv, int hv): + RelExpression(op,lv,hv) {} + bool eval(FileEntry *file); + + virtual void linearize(LinearizedExpression& e) const + { + e._tokens.push_back(LinearizedExpression::EXPR_DATE) ; + RelExpression::linearize(e) ; + } +}; + +class SizeExpression: public RelExpression +{ + public: + SizeExpression(enum RelOperator op, int v): RelExpression(op,v,v){} + SizeExpression(enum RelOperator op, int lv, int hv): + RelExpression(op,lv,hv) {} + bool eval(FileEntry *file); + + virtual void linearize(LinearizedExpression& e) const + { + e._tokens.push_back(LinearizedExpression::EXPR_SIZE) ; + RelExpression::linearize(e) ; + } +}; + +class SizeExpressionMB: public RelExpression +{ + public: + SizeExpressionMB(enum RelOperator op, int v): RelExpression(op,v,v){} + SizeExpressionMB(enum RelOperator op, int lv, int hv): + RelExpression(op,lv,hv) {} + bool eval(FileEntry *file); + + virtual void linearize(LinearizedExpression& e) const + { + e._tokens.push_back(LinearizedExpression::EXPR_SIZE_MB) ; + RelExpression::linearize(e) ; + } +}; +class PopExpression: public RelExpression +{ + public: + PopExpression(enum RelOperator op, int v): RelExpression(op,v,v){} + PopExpression(enum RelOperator op, int lv, int hv): RelExpression(op,lv,hv) {} + PopExpression(const LinearizedExpression& e) ; + bool eval(FileEntry *file); + + virtual void linearize(LinearizedExpression& e) const + { + e._tokens.push_back(LinearizedExpression::EXPR_POP) ; + RelExpression::linearize(e) ; + } +}; + +#endif /* RS_EXPRESSIONS_H */ + diff --git a/libretroshare/src/retroshare/rsfiles.h b/libretroshare/src/retroshare/rsfiles.h new file mode 100644 index 000000000..9f3a7e362 --- /dev/null +++ b/libretroshare/src/retroshare/rsfiles.h @@ -0,0 +1,208 @@ +#ifndef RS_FILES_GUI_INTERFACE_H +#define RS_FILES_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsfiles.h + * + * RetroShare C++ Interface. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include + +#include "rstypes.h" + +class RsFiles; +extern RsFiles *rsFiles; + +class Expression; +class CacheStrapper ; +class CacheTransfer; + +/* These are used mainly by ftController at the moment */ +const uint32_t RS_FILE_CTRL_PAUSE = 0x00000100; +const uint32_t RS_FILE_CTRL_START = 0x00000200; +const uint32_t RS_FILE_CTRL_FORCE_CHECK = 0x00000400; + +const uint32_t RS_FILE_RATE_TRICKLE = 0x00000001; +const uint32_t RS_FILE_RATE_SLOW = 0x00000002; +const uint32_t RS_FILE_RATE_STANDARD = 0x00000003; +const uint32_t RS_FILE_RATE_FAST = 0x00000004; +const uint32_t RS_FILE_RATE_STREAM_AUDIO = 0x00000005; +const uint32_t RS_FILE_RATE_STREAM_VIDEO = 0x00000006; + +const uint32_t RS_FILE_PEER_ONLINE = 0x00001000; +const uint32_t RS_FILE_PEER_OFFLINE = 0x00002000; + +/************************************ + * Used To indicate where to search. + * + * The Order of these is very important, + * it specifies the search order too. + * + */ + +const uint32_t RS_FILE_HINTS_MASK = 0x00ffffff; + +const uint32_t RS_FILE_HINTS_CACHE = 0x00000001; +const uint32_t RS_FILE_HINTS_EXTRA = 0x00000002; +const uint32_t RS_FILE_HINTS_LOCAL = 0x00000004; +const uint32_t RS_FILE_HINTS_REMOTE = 0x00000008; +const uint32_t RS_FILE_HINTS_DOWNLOAD = 0x00000010; +const uint32_t RS_FILE_HINTS_UPLOAD = 0x00000020; + +const uint32_t RS_FILE_HINTS_NETWORK_WIDE = 0x00000080; // anonymously shared over network +const uint32_t RS_FILE_HINTS_BROWSABLE = 0x00000100; // browsable by friends +const uint32_t RS_FILE_HINTS_ASSUME_AVAILABILITY = 0x00000200; // Assume full source availability. Used for cache files. +const uint32_t RS_FILE_HINTS_MEDIA = 0x00001000; +const uint32_t RS_FILE_HINTS_BACKGROUND = 0x00002000; // To download slowly. + +const uint32_t RS_FILE_HINTS_SPEC_ONLY = 0x01000000; +const uint32_t RS_FILE_HINTS_NO_SEARCH = 0x02000000; + +/* Callback Codes */ + +const uint32_t RS_FILE_EXTRA_DELETE = 0x0010; + +struct SharedDirInfo +{ + std::string filename ; + std::string virtualname ; + uint32_t shareflags ; // RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE +}; + +class RsFiles +{ + public: + + RsFiles() { return; } + virtual ~RsFiles() { return; } + + /****************************************/ + /* download */ + + + /*** + * Control of Downloads. + ***/ + + virtual bool alreadyHaveFile(const std::string& hash, FileInfo &info) = 0; + /// Returns false is we already have the file. Otherwise, initiates the dl and returns true. + virtual bool FileRequest(const std::string& fname, const std::string& hash, uint64_t size, const std::string& dest, uint32_t flags, const std::list& srcIds) = 0; + virtual bool FileCancel(const std::string& hash) = 0; + virtual bool setChunkStrategy(const std::string& hash,FileChunksInfo::ChunkStrategy) = 0; + virtual void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy) = 0; + virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() = 0; + virtual uint32_t freeDiskSpaceLimit() const =0; + virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) =0; + virtual bool FileControl(const std::string& hash, uint32_t flags) = 0; + virtual bool FileClearCompleted() = 0; + + /*** + * Control of Downloads Priority. + ***/ + virtual uint32_t getQueueSize() = 0 ; + virtual void setQueueSize(uint32_t s) = 0 ; + virtual bool changeQueuePosition(const std::string hash, QueueMove mv) = 0; + virtual bool changeDownloadSpeed(const std::string hash, int speed) = 0; + virtual bool getDownloadSpeed(const std::string hash, int & speed) = 0; + virtual bool clearDownload(const std::string hash) = 0; +// virtual void getDwlDetails(std::list & details) = 0; + + /*** + * Download / Upload Details. + ***/ + virtual bool FileDownloads(std::list &hashs) = 0; + virtual bool FileUploads(std::list &hashs) = 0; + virtual bool FileDetails(const std::string &hash, uint32_t hintflags, FileInfo &info) = 0; + + /// Gives chunk details about the downloaded file with given hash. + virtual bool FileDownloadChunksDetails(const std::string& hash,FileChunksInfo& info) = 0 ; + + /// details about the upload with given hash + virtual bool FileUploadChunksDetails(const std::string& hash,const std::string& peer_id,CompressedChunkMap& map) = 0 ; + + /*** + * Extra List Access + ***/ + virtual bool ExtraFileAdd(std::string fname, std::string hash, uint64_t size, + uint32_t period, uint32_t flags) = 0; + virtual bool ExtraFileRemove(std::string hash, uint32_t flags) = 0; + virtual bool ExtraFileHash(std::string localpath, + uint32_t period, uint32_t flags) = 0; + virtual bool ExtraFileStatus(std::string localpath, FileInfo &info) = 0; + virtual bool ExtraFileMove(std::string fname, std::string hash, uint64_t size, + std::string destpath) = 0; + + + + /*** + * Directory Listing / Search Interface + */ + virtual int RequestDirDetails(std::string uid, std::string path, DirDetails &details) = 0; + + virtual int RequestDirDetails(void *ref, DirDetails &details, uint32_t flags) = 0; + virtual uint32_t getType(void *ref,uint32_t flags) = 0; + + virtual int SearchKeywords(std::list keywords, std::list &results,uint32_t flags) = 0; + virtual int SearchBoolExp(Expression * exp, std::list &results,uint32_t flags) = 0; + + /*** + * Utility Functions. + ***/ + virtual bool ConvertSharedFilePath(std::string path, std::string &fullpath) = 0; + virtual void ForceDirectoryCheck() = 0; + virtual bool InDirectoryCheck() = 0; + virtual bool CopyFile(const std::string& source,const std::string& dest) = 0; + + /*** + * Directory Control + ***/ + virtual void setDownloadDirectory(std::string path) = 0; + virtual void setPartialsDirectory(std::string path) = 0; + virtual std::string getDownloadDirectory() = 0; + virtual std::string getPartialsDirectory() = 0; + + virtual bool getSharedDirectories(std::list &dirs) = 0; + virtual bool addSharedDirectory(const SharedDirInfo& dir) = 0; + virtual bool updateShareFlags(const SharedDirInfo& dir) = 0; // updates the flags. The directory should already exist ! + virtual bool removeSharedDirectory(std::string dir) = 0; + virtual void setRememberHashFilesDuration(uint32_t days) = 0 ; + virtual uint32_t rememberHashFilesDuration() const = 0 ; + virtual void clearHashCache() = 0 ; + virtual bool rememberHashFiles() const =0; + virtual void setRememberHashFiles(bool) =0; + virtual void setWatchPeriod(int minutes) =0; + virtual int watchPeriod() const =0; + + virtual CacheStrapper *getCacheStrapper() =0; + virtual CacheTransfer *getCacheTransfer() =0; + + virtual bool getShareDownloadDirectory() = 0; + virtual bool shareDownloadDirectory(bool share) = 0; + +}; + + +#endif diff --git a/libretroshare/src/retroshare/rsforums.h b/libretroshare/src/retroshare/rsforums.h new file mode 100644 index 000000000..634dcc267 --- /dev/null +++ b/libretroshare/src/retroshare/rsforums.h @@ -0,0 +1,158 @@ +#ifndef RS_FORUM_GUI_INTERFACE_H +#define RS_FORUM_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsforums.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include + +#include "rstypes.h" +#include "rsdistrib.h" /* For FLAGS */ + +#define FORUM_MSG_STATUS_MASK 0x000f +#define FORUM_MSG_STATUS_READ 0x0001 +#define FORUM_MSG_STATUS_UNREAD_BY_USER 0x0002 + +class ForumInfo +{ + public: + ForumInfo() + { + forumFlags = 0 ; + subscribeFlags = 0 ; + pop = 0 ; + lastPost = 0 ; + } + std::string forumId; + std::wstring forumName; + std::wstring forumDesc; + + uint32_t forumFlags; + uint32_t subscribeFlags; + + uint32_t pop; + + time_t lastPost; +}; + +class ForumMsgInfo +{ + public: + ForumMsgInfo() + { + msgflags = 0 ; + ts = childTS = status = 0 ; + } + std::string forumId; + std::string threadId; + std::string parentId; + std::string msgId; + + std::string srcId; /* if Authenticated -> signed here */ + + unsigned int msgflags; + + std::wstring title; + std::wstring msg; + time_t ts; + time_t childTS; + uint32_t status; +}; + + +class ThreadInfoSummary +{ + public: + ThreadInfoSummary() + { + msgflags = 0 ; + count = 0 ; + ts = childTS = 0 ; + } + std::string forumId; + std::string threadId; + std::string parentId; + std::string msgId; + + uint32_t msgflags; + + std::wstring title; + std::wstring msg; + int count; /* file count */ + time_t ts; + time_t childTS; +}; + +std::ostream &operator<<(std::ostream &out, const ForumInfo &info); +std::ostream &operator<<(std::ostream &out, const ThreadInfoSummary &info); +std::ostream &operator<<(std::ostream &out, const ForumMsgInfo &info); + +class RsForums; +extern RsForums *rsForums; + +class RsForums +{ + public: + + RsForums() { return; } +virtual ~RsForums() { return; } + +/****************************************/ + +virtual bool forumsChanged(std::list &forumIds) = 0; + + +virtual std::string createForum(const std::wstring &forumName, const std::wstring &forumDesc, uint32_t forumFlags) = 0; + +virtual bool getForumInfo(const std::string &fId, ForumInfo &fi) = 0; + +/*! + * allows peers to change information for the forum: + * can only change name and descriptions + * + */ +virtual bool setForumInfo(const std::string &fId, ForumInfo &fi) = 0; + +virtual bool getForumList(std::list &forumList) = 0; +virtual bool getForumThreadList(const std::string &fId, std::list &msgs) = 0; +virtual bool getForumThreadMsgList(const std::string &fId, const std::string &pId, std::list &msgs) = 0; +virtual bool getForumMessage(const std::string &fId, const std::string &mId, ForumMsgInfo &msg) = 0; +virtual bool setMessageStatus(const std::string& fId,const std::string& mId, const uint32_t status, const uint32_t statusMask) = 0; +virtual bool getMessageStatus(const std::string& fId, const std::string& mId, uint32_t& status) = 0; +virtual bool ForumMessageSend(ForumMsgInfo &info) = 0; +virtual bool forumRestoreKeys(const std::string& fId) = 0; +virtual bool forumSubscribe(const std::string &fId, bool subscribe) = 0; + +virtual bool getMessageCount(const std::string &fId, unsigned int &newCount, unsigned int &unreadCount) = 0; + +/****************************************/ + +}; + + +#endif diff --git a/libretroshare/src/retroshare/rsgame.h b/libretroshare/src/retroshare/rsgame.h new file mode 100644 index 000000000..553bb477b --- /dev/null +++ b/libretroshare/src/retroshare/rsgame.h @@ -0,0 +1,113 @@ +#ifndef RS_GAME_GUI_INTERFACE_H +#define RS_GAME_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsgame.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "rstypes.h" + + +class RsGameLauncher; + +/* declare single RsIface for everyone to use! */ + +extern RsGameLauncher *rsGameLauncher; + +#include +#include +#include + +class RsGameInfo +{ + public: + + std::string gameId; + std::string serverId; + + std::string gameType; + std::wstring gameName; + std::string serverName; + std::string status; + uint16_t numPlayers; + +}; + +class RsGamePeer +{ + public: + std::string id; + bool invite; + bool interested; + bool play; +}; + +class RsGameDetail +{ + public: + std::string gameId; + std::string gameType; + std::wstring gameName; + + bool areServer; /* are we the server? */ + std::string serverId; /* if not, who is? */ + std::string serverName; + + std::string status; + + uint16_t numPlayers; + std::map gamers; + +}; + +class RsGameLauncher +{ + public: + +/* server commands */ +virtual std::string createGame(uint32_t gameType, std::wstring name) = 0; +virtual bool deleteGame(std::string gameId) = 0; +virtual bool inviteGame(std::string gameId) = 0; +virtual bool playGame(std::string gameId) = 0; +//virtual bool quitGame(std::string gameId) = 0; + +virtual bool invitePeer(std::string gameId, std::string peerId) = 0; +virtual bool uninvitePeer(std::string gameId, std::string peerId) = 0; +virtual bool confirmPeer(std::string gameId, std::string peerId, + int16_t pos = -1) = 0; +virtual bool unconfirmPeer(std::string gameId, std::string peerId) = 0; + +/* client commands */ +virtual bool interestedPeer(std::string gameId) = 0; +virtual bool uninterestedPeer(std::string gameId) = 0; + +/* get details */ +virtual bool getGameList(std::list &gameList) = 0; +virtual bool getGameDetail(std::string gameId, RsGameDetail &detail) = 0; + +}; + + +#endif diff --git a/libretroshare/src/retroshare/rsiface.h b/libretroshare/src/retroshare/rsiface.h new file mode 100644 index 000000000..1ef3be308 --- /dev/null +++ b/libretroshare/src/retroshare/rsiface.h @@ -0,0 +1,236 @@ +#ifndef RETROSHARE_GUI_INTERFACE_H +#define RETROSHARE_GUI_INTERFACE_H + +/* + * "$Id: rsiface.h,v 1.9 2007-04-21 19:08:51 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "rstypes.h" + +#include + +class NotifyBase; +class RsIface; +class RsControl; +class RsInit; +struct TurtleFileInfo ; + +/* declare single RsIface for everyone to use! */ + +extern RsIface *rsiface; +extern RsControl *rsicontrol; + +/* RsInit -> Configuration Parameters for RetroShare Startup + */ + +RsInit *InitRsConfig(); +/* extract various options for GUI */ +const char *RsConfigDirectory(RsInit *config); +bool RsConfigStartMinimised(RsInit *config); +void CleanupRsConfig(RsInit *); + + +// Called First... (handles comandline options) +int InitRetroShare(int argc, char **argv, RsInit *config); + +// This Functions are used for Login. +bool ValidateCertificate(RsInit *config, std::string &userName); +bool ValidateTrustedUser(RsInit *config, std::string fname, std::string &userName); +bool LoadPassword(RsInit *config, std::string passwd); +bool RsGenerateCertificate(RsInit *config, std::string name, std::string org, + std::string loc, std::string country, std::string passwd, std::string &errString); + +/* Auto Login Fns */ +bool RsTryAutoLogin(RsInit *config); +bool RsStoreAutoLogin(RsInit *config); +bool RsClearAutoLogin(std::string basedir); + +// Handle actual Login. +int LoadCertificates(RsInit *config, bool autoLoginNT); + +RsIface *createRsIface (NotifyBase ¬ify); +RsControl *createRsControl(RsIface &iface, NotifyBase ¬ify); + + +class RsIface /* The Main Interface Class - create a single one! */ +{ +public: + RsIface(NotifyBase &callback) + :cb(callback) { return; } + virtual ~RsIface() { return; } + +/****************************************/ + + /* Stubs for Very Important Fns -> Locking Functions */ +virtual void lockData() = 0; +virtual void unlockData() = 0; + + const RsConfig &getConfig() + { return mConfig; } +/****************************************/ + + + /* Flags to indicate used or not */ + enum DataFlags + { + Neighbour = 0, + Friend = 1, + DirLocal = 2, /* Not Used - QModel instead */ + DirRemote = 3, /* Not Used - QModel instead */ + Transfer = 4, + Message = 5, + Channel = 6, + Chat = 7, + Recommend = 8, + Config = 9, + NumOfFlags = 10 + }; + + + /* + * Operations for flags + */ + +bool setChanged(DataFlags set); /* set to true */ +bool getChanged(DataFlags set); /* leaves it */ +bool hasChanged(DataFlags set); /* resets it */ + + private: + +void fillLists(); /* create some dummy data to display */ + + /* Internals */ + bool mChanged[NumOfFlags]; + + RsConfig mConfig; + + NotifyBase &cb; + + /* Classes which can update the Lists! */ + friend class RsControl; + friend class RsServer; +}; + + +class RsControl /* The Main Interface Class - for controlling the server */ +{ + public: + + RsControl(RsIface &i, NotifyBase &callback) + :cb(callback), rsIface(i) { return; } + + virtual ~RsControl() { return; } + + /* Real Startup Fn */ + virtual int StartupRetroShare() = 0; + + /****************************************/ + + /* Flagging Persons / Channels / Files in or out of a set (CheckLists) */ + virtual int SetInBroadcast(std::string id, bool in) = 0; /* channel : channel broadcast */ + virtual int SetInSubscribe(std::string id, bool in) = 0; /* channel : subscribed channels */ + virtual int ClearInBroadcast() = 0; + virtual int ClearInSubscribe() = 0; + + /****************************************/ + /* Config */ + + virtual int ConfigSetDataRates( int totalDownload, int totalUpload ) = 0; + virtual int ConfigGetDataRates( float &inKb, float &outKb) = 0; + virtual int ConfigSetBootPrompt( bool on ) = 0; + virtual void ConfigFinalSave( ) = 0; + virtual void rsGlobalShutDown( ) = 0; + + /****************************************/ + + NotifyBase &getNotify() { return cb; } + RsIface &getIface() { return rsIface; } + + private: + NotifyBase &cb; + RsIface &rsIface; +}; + + +/********************** Overload this Class for callback *****************/ + + +class NotifyBase +{ + public: + NotifyBase() { return; } + virtual ~NotifyBase() { return; } + virtual void notifyListPreChange(int list, int type) { (void) list; (void) type; return; } + virtual void notifyListChange(int list, int type) { (void) list; (void) type; return; } + virtual void notifyErrorMsg(int list, int sev, std::string msg) { (void) list; (void) sev; (void) msg; return; } + virtual void notifyChat() { return; } + virtual void notifyChatStatus(const std::string& /* peer_id */, const std::string& /* status_string */ ,bool /* is_private */) {} + virtual void notifyCustomState(const std::string& /* peer_id */, const std::string& /* status_string */) {} + virtual void notifyHashingInfo(uint32_t type, const std::string& fileinfo) { (void) type; (void)fileinfo; } + virtual void notifyTurtleSearchResult(uint32_t /* search_id */ ,const std::list& files) { (void)files; } + virtual void notifyPeerHasNewAvatar(std::string peer_id) { (void)peer_id; } + virtual void notifyOwnAvatarChanged() {} + virtual void notifyOwnStatusMessageChanged() {} + virtual void notifyDiskFull(uint32_t /* location */,uint32_t /* size limit in MB */) {} + /* peer has changed the status */ + virtual void notifyPeerStatusChanged(const std::string& /* peer_id */, uint32_t /* status */) {} + /* one or more peers has changed the states */ + virtual void notifyPeerStatusChangedSummary() {} + virtual void notifyChannelMsgReadSatusChanged(const std::string& /* channelId */, const std::string& /* msgId */, uint32_t /* status */) {} + virtual void notifyDiscInfoChanged() {} + virtual void notifyDownloadComplete(const std::string& /* fileHash */) {}; + virtual void notifyDownloadCompleteCount(uint32_t /* count */) {}; + + virtual std::string askForPassword(const std::string& /* key_details */ ,bool /* prev_is_bad */ ) { return "" ;} +}; + +const int NOTIFY_LIST_NEIGHBOURS = 1; +const int NOTIFY_LIST_FRIENDS = 2; +const int NOTIFY_LIST_SEARCHLIST = 4; +const int NOTIFY_LIST_MESSAGELIST = 5; +const int NOTIFY_LIST_CHANNELLIST = 6; +const int NOTIFY_LIST_TRANSFERLIST = 7; +const int NOTIFY_LIST_CONFIG = 8; +const int NOTIFY_LIST_DIRLIST_LOCAL = 9; +const int NOTIFY_LIST_DIRLIST_FRIENDS = 10; +const int NOTIFY_LIST_FORUMLIST_LOCKED = 11; // use connect with Qt::QueuedConnection +const int NOTIFY_LIST_MESSAGE_TAGS = 12; +const int NOTIFY_LIST_PUBLIC_CHAT = 13; +const int NOTIFY_LIST_PRIVATE_INCOMING_CHAT = 14; +const int NOTIFY_LIST_PRIVATE_OUTGOING_CHAT = 15; +const int NOTIFY_LIST_GROUPLIST = 16; +const int NOTIFY_LIST_CHANNELLIST_LOCKED = 17; // use connect with Qt::QueuedConnection + +const int NOTIFY_TYPE_SAME = 0x01; +const int NOTIFY_TYPE_MOD = 0x02; /* general purpose, check all */ +const int NOTIFY_TYPE_ADD = 0x04; /* flagged additions */ +const int NOTIFY_TYPE_DEL = 0x08; /* flagged deletions */ + +const uint32_t NOTIFY_HASHTYPE_EXAMINING_FILES = 1; /* Examining shared files */ +const uint32_t NOTIFY_HASHTYPE_FINISH = 2; /* Finish */ +const uint32_t NOTIFY_HASHTYPE_HASH_FILE = 3; /* Hashing file */ +const uint32_t NOTIFY_HASHTYPE_SAVE_FILE_INDEX = 4; /* Hashing file */ + +#endif diff --git a/libretroshare/src/retroshare/rsinit.h b/libretroshare/src/retroshare/rsinit.h new file mode 100644 index 000000000..be6a24e98 --- /dev/null +++ b/libretroshare/src/retroshare/rsinit.h @@ -0,0 +1,163 @@ +#ifndef RETROSHARE_INIT_INTERFACE_H +#define RETROSHARE_INIT_INTERFACE_H + +/* + * "$Id: rsiface.h,v 1.9 2007-04-21 19:08:51 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +// Initialize ok, result >= 0 +#define RS_INIT_OK 0 // Initialize ok +#define RS_INIT_HAVE_ACCOUNT 1 // Initialize ok, have account +// Initialize failed, result < 0 +#define RS_INIT_AUTH_FAILED -1 // AuthGPG::InitAuth failed + + +/**** + * #define RS_USE_PGPSSL 1 + ***/ + +#define RS_USE_PGPSSL 1 + +#include + +/*! + * Initialisation Class (not publicly disclosed to RsIFace) + */ +class RsInit +{ + public: + /* reorganised RsInit system */ + + /*! + * PreLogin + * Call before init retroshare, initialises rsinitconfig's public attributes + */ + static void InitRsConfig() ; + + /*! + * Should be called to load up ssl cert and private key, and intialises gpg + * this must be called before accessing rsserver (e.g. ::startupretroshare) + * @param argc passed from executable + * @param argv commandline arguments passed to executable + * @param strictCheck set to true if you want rs to continue executing if invalid argument passed and vice versa + * @return RS_INIT_... + */ + static int InitRetroShare(int argc, char **argv, bool strictCheck=true); + + static bool isPortable(); + static bool isWindowsXP(); + + /*! + * Account Details (Combined GPG+SSL Setup) + */ + static bool getPreferedAccountId(std::string &id); + static bool getPGPEngineFileName(std::string &fileName); + static bool getAccountIds(std::list &ids); + static bool getAccountDetails(std::string id, + std::string &gpgId, std::string &gpgName, + std::string &gpgEmail, std::string &sslName); + + static bool ValidateCertificate(std::string &userName) ; + + + /*! + * Generating GPGme Account + */ + static int GetPGPLogins(std::list &pgpIds); + static int GetPGPLoginDetails(std::string id, std::string &name, std::string &email); + static bool GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString); + + /*! + * Login GGP + */ + static bool SelectGPGAccount(const std::string& gpgId); + static bool LoadGPGPassword(std::string passwd); + + /*! + * Create SSL Certificates + */ + static bool GenerateSSLCertificate(std::string name, std::string org, std::string loc, std::string country, std::string passwd, std::string &sslId, std::string &errString); + + /*! + * intialises directories for passwords and ssl keys + */ + static bool LoadPassword(std::string id, std::string passwd) ; + + /*! + * Final Certificate load. This can be called if: + * a) InitRetroshare() returns RS_INIT_HAVE_ACCOUNT -> autoLoad/password Set. + * b) SelectGPGAccount() && LoadPassword() + * + * This wrapper is used to lock the profile first before + * finalising the login + */ + static int LockAndLoadCertificates(bool autoLoginNT, std::string& lockFilePath); + + + /*! + * Post Login Options + */ + static std::string RsConfigDirectory(); + static std::string RsConfigKeysDirectory(); + + static std::string RsProfileConfigDirectory(); + static bool getStartMinimised() ; + static std::string getRetroShareLink(); + + static int getSslPwdLen(); + static bool getAutoLogin(); + static void setAutoLogin(bool autoLogin); + static bool RsClearAutoLogin() ; + + /* used for static install data */ + static std::string getRetroshareDataDirectory(); + + private: + + /* PreLogin */ + static std::string getHomePath() ; + static void setupBaseDir(); + + /* Account Details */ + static bool get_configinit(std::string dir, std::string &id); + static bool create_configinit(std::string dir, std::string id); + + static bool setupAccount(std::string accountdir); + + /* Auto Login */ + static bool RsStoreAutoLogin() ; + static bool RsTryAutoLogin() ; + + /* Lock/unlock profile directory */ + static int LockConfigDirectory(const std::string& accountDir, std::string& lockFilePath); + static void UnlockConfigDirectory(); + + /* The true LoadCertificates() method */ + static int LoadCertificates(bool autoLoginNT) ; + +}; + + + +#endif diff --git a/libretroshare/src/retroshare/rsmsgs.h b/libretroshare/src/retroshare/rsmsgs.h new file mode 100644 index 000000000..57843088f --- /dev/null +++ b/libretroshare/src/retroshare/rsmsgs.h @@ -0,0 +1,212 @@ +#ifndef RS_MSG_GUI_INTERFACE_H +#define RS_MSG_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsmsgs.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include + +#include "rstypes.h" + +/********************** For Messages and Channels *****************/ + +#define RS_MSG_BOXMASK 0x000f /* Mask for determining Box */ + +#define RS_MSG_OUTGOING 0x0001 /* !Inbox */ +#define RS_MSG_PENDING 0x0002 /* OutBox */ +#define RS_MSG_DRAFT 0x0004 /* Draft */ + +/* ORs of above */ +#define RS_MSG_INBOX 0x00 /* Inbox */ +#define RS_MSG_SENTBOX 0x01 /* Sentbox */ +#define RS_MSG_OUTBOX 0x03 /* Outbox */ +#define RS_MSG_DRAFTBOX 0x05 /* Draftbox */ + +#define RS_MSG_NEW 0x0010 /* New */ +#define RS_MSG_TRASH 0x0020 /* Trash */ +#define RS_MSG_UNREAD_BY_USER 0x0040 /* Unread by user */ +#define RS_MSG_REPLIED 0x0080 /* Message is replied */ +#define RS_MSG_FORWARDED 0x0100 /* Message is forwarded */ +#define RS_MSG_STAR 0x0200 /* Message is marked with a star */ + +#define RS_MSGTAGTYPE_IMPORTANT 1 +#define RS_MSGTAGTYPE_WORK 2 +#define RS_MSGTAGTYPE_PERSONAL 3 +#define RS_MSGTAGTYPE_TODO 4 +#define RS_MSGTAGTYPE_LATER 5 +#define RS_MSGTAGTYPE_USER 100 + +class MessageInfo +{ + public: + MessageInfo() {} + std::string msgId; + std::string srcId; + + unsigned int msgflags; + + std::list msgto; + std::list msgcc; + std::list msgbcc; + + std::wstring title; + std::wstring msg; + + std::wstring attach_title; + std::wstring attach_comment; + std::list files; + int size; /* total of files */ + int count; /* file count */ + + int ts; +}; + +class MsgInfoSummary +{ + public: + MsgInfoSummary() {} + + std::string msgId; + std::string srcId; + + uint32_t msgflags; + + std::wstring title; + int count; /* file count */ + time_t ts; + +}; + +class MsgTagInfo +{ +public: + MsgTagInfo() {} + + std::string msgId; + std::list tagIds; +}; + +class MsgTagType +{ +public: + MsgTagType() {} + + /* map containing tagId -> pair (text, rgb color) */ + std::map > types; + +}; + +#define RS_CHAT_PUBLIC 0x0001 +#define RS_CHAT_PRIVATE 0x0002 +#define RS_CHAT_AVATAR_AVAILABLE 0x0004 + +class ChatInfo +{ + public: + std::string rsid; + unsigned int chatflags; + uint32_t sendTime; + uint32_t recvTime; + std::wstring msg; +}; + +std::ostream &operator<<(std::ostream &out, const MessageInfo &info); +std::ostream &operator<<(std::ostream &out, const ChatInfo &info); +//std::ostream &operator<<(std::ostream &out, const MsgTagInfo); +//std::ostream &operator<<(std::ostream &out, const MsgTagType); + + +class RsMsgs; +extern RsMsgs *rsMsgs; + +class RsMsgs +{ + public: + + RsMsgs() { return; } +virtual ~RsMsgs() { return; } + +/****************************************/ + /* Message Items */ + +virtual bool getMessageSummaries(std::list &msgList) = 0; +virtual bool getMessage(const std::string &mId, MessageInfo &msg) = 0; +virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox) = 0; + +virtual bool MessageSend(MessageInfo &info) = 0; +virtual bool MessageToDraft(MessageInfo &info, const std::string &msgParentId) = 0; +virtual bool MessageToTrash(const std::string &mid, bool bTrash) = 0; +virtual bool getMsgParentId(const std::string &msgId, std::string &msgParentId) = 0; + +virtual bool MessageDelete(const std::string &mid) = 0; +virtual bool MessageRead(const std::string &mid, bool unreadByUser) = 0; +virtual bool MessageReplied(const std::string &mid, bool replied) = 0; +virtual bool MessageForwarded(const std::string &mid, bool forwarded) = 0; +virtual bool MessageStar(const std::string &mid, bool mark) = 0; + +/* message tagging */ + +virtual bool getMessageTagTypes(MsgTagType& tags) = 0; +/* set == false && tagId == 0 --> remove all */ +virtual bool setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color) = 0; +virtual bool removeMessageTagType(uint32_t tagId) = 0; + +virtual bool getMessageTag(const std::string &msgId, MsgTagInfo& info) = 0; +virtual bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set) = 0; + +virtual bool resetMessageStandardTagTypes(MsgTagType& tags) = 0; + +/****************************************/ + /* Chat */ +virtual bool sendPublicChat(std::wstring msg) = 0; +virtual bool sendPrivateChat(std::string id, std::wstring msg) = 0; +virtual int getPublicChatQueueCount() = 0; +virtual bool getPublicChatQueue(std::list &chats) = 0; +virtual int getPrivateChatQueueCount(bool incoming) = 0; +virtual bool getPrivateChatQueueIds(bool incoming, std::list &ids) = 0; +virtual bool getPrivateChatQueue(bool incoming, std::string id, std::list &chats) = 0; +virtual bool clearPrivateChatQueue(bool incoming, std::string id) = 0; +virtual void sendStatusString(const std::string& id,const std::string& status_string) = 0 ; +virtual void sendGroupChatStatusString(const std::string& status_string) = 0 ; + +virtual void setCustomStateString(const std::string& status_string) = 0 ; +virtual std::string getCustomStateString() = 0 ; +virtual std::string getCustomStateString(const std::string& peer_id) = 0 ; + +// get avatar data for peer pid +virtual void getAvatarData(std::string pid,unsigned char *& data,int& size) = 0 ; +// set own avatar data +virtual void setOwnAvatarData(const unsigned char *data,int size) = 0 ; +virtual void getOwnAvatarData(unsigned char *& data,int& size) = 0 ; + +/****************************************/ + +}; + + +#endif diff --git a/libretroshare/src/retroshare/rsnotify.h b/libretroshare/src/retroshare/rsnotify.h new file mode 100644 index 000000000..31ae6c83b --- /dev/null +++ b/libretroshare/src/retroshare/rsnotify.h @@ -0,0 +1,131 @@ +#ifndef RS_NOTIFY_GUI_INTERFACE_H +#define RS_NOTIFY_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsnotify.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include +#include +#include + +class RsNotify; +extern RsNotify *rsNotify; + +const uint32_t RS_SYS_ERROR = 0x0001; +const uint32_t RS_SYS_WARNING = 0x0002; +const uint32_t RS_SYS_INFO = 0x0004; + +const uint32_t RS_POPUP_MSG = 0x0001; +//const uint32_t RS_POPUP_CHAT = 0x0002; +//const uint32_t RS_POPUP_CALL = 0x0004; +const uint32_t RS_POPUP_CONNECT = 0x0008; +const uint32_t RS_SYSTRAY_GROUP_MSG = 0x0010; +const uint32_t RS_POPUP_DOWNLOAD = 0x0020; + +/* CHAT flags are here - so they are in the same place as + * other Notify flags... not used by libretroshare though + */ +const uint32_t RS_CHAT_OPEN = 0x0001; +//const uint32_t free = 0x0002; +const uint32_t RS_CHAT_FOCUS = 0x0004; +const uint32_t RS_CHAT_TABBED_WINDOW = 0x0008; + +const uint32_t RS_FEED_TYPE_PEER = 0x0010; +const uint32_t RS_FEED_TYPE_CHAN = 0x0020; +const uint32_t RS_FEED_TYPE_FORUM = 0x0040; +const uint32_t RS_FEED_TYPE_BLOG = 0x0080; +const uint32_t RS_FEED_TYPE_CHAT = 0x0100; +const uint32_t RS_FEED_TYPE_MSG = 0x0200; +const uint32_t RS_FEED_TYPE_FILES = 0x0400; + +const uint32_t RS_FEED_ITEM_PEER_CONNECT = RS_FEED_TYPE_PEER | 0x0001; +const uint32_t RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x0002; +const uint32_t RS_FEED_ITEM_PEER_NEW = RS_FEED_TYPE_PEER | 0x0003; +const uint32_t RS_FEED_ITEM_PEER_HELLO = RS_FEED_TYPE_PEER | 0x0004; + +const uint32_t RS_FEED_ITEM_CHAN_NEW = RS_FEED_TYPE_CHAN | 0x0001; +const uint32_t RS_FEED_ITEM_CHAN_UPDATE = RS_FEED_TYPE_CHAN | 0x0002; +const uint32_t RS_FEED_ITEM_CHAN_MSG = RS_FEED_TYPE_CHAN | 0x0003; + +const uint32_t RS_FEED_ITEM_FORUM_NEW = RS_FEED_TYPE_FORUM | 0x0001; +const uint32_t RS_FEED_ITEM_FORUM_UPDATE = RS_FEED_TYPE_FORUM | 0x0002; +const uint32_t RS_FEED_ITEM_FORUM_MSG = RS_FEED_TYPE_FORUM | 0x0003; + +const uint32_t RS_FEED_ITEM_BLOG_NEW = RS_FEED_TYPE_BLOG | 0x0001; +const uint32_t RS_FEED_ITEM_BLOG_UPDATE = RS_FEED_TYPE_BLOG | 0x0002; +const uint32_t RS_FEED_ITEM_BLOG_MSG = RS_FEED_TYPE_BLOG | 0x0003; + +const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001; +const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001; +const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001; + + +class RsFeedItem +{ +public: + RsFeedItem(uint32_t type, std::string id1, std::string id2, std::string id3) + :mType(type), mId1(id1), mId2(id2), mId3(id3) + { + return; + } + + RsFeedItem() :mType(0) { return; } + + uint32_t mType; + std::string mId1, mId2, mId3; +}; + + +class RsNotify +{ + public: + + RsNotify() { return; } +virtual ~RsNotify() { return; } + + /* Output for retroshare-gui */ +virtual bool NotifySysMessage(uint32_t &sysid, uint32_t &type, + std::string &title, std::string &msg) = 0; +virtual bool NotifyPopupMessage(uint32_t &ptype, std::string &name, std::string &title, std::string &msg) = 0; +virtual bool NotifyLogMessage(uint32_t &sysid, uint32_t &type, + std::string &title, std::string &msg) = 0; + + /* Control over Messages */ +virtual bool GetSysMessageList(std::map &list) = 0; +virtual bool GetPopupMessageList(std::map &list) = 0; + +virtual bool SetSysMessageMode(uint32_t sysid, uint32_t mode) = 0; +virtual bool SetPopupMessageMode(uint32_t ptype, uint32_t mode) = 0; + + /* Feed Output */ +virtual bool GetFeedItem(RsFeedItem &item) = 0; + +}; + + +#endif diff --git a/libretroshare/src/retroshare/rspeers.h b/libretroshare/src/retroshare/rspeers.h new file mode 100644 index 000000000..47436556b --- /dev/null +++ b/libretroshare/src/retroshare/rspeers.h @@ -0,0 +1,239 @@ +#ifndef RETROSHARE_PEER_GUI_INTERFACE_H +#define RETROSHARE_PEER_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rspeer.h + * + * RetroShare C++ Interface. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include + +/* The Main Interface Class - for information about your Peers +* A peer is another RS instance, means associated with an SSL certificate +* A same GPG person can have multiple peer running with different SSL certs signed by the same GPG key +* Thus a peer have SSL cert details, and also the parent GPG details +*/ +class RsPeers; +extern RsPeers *rsPeers; + +/* Trust Levels */ +const uint32_t RS_TRUST_LVL_NONE = 2; +const uint32_t RS_TRUST_LVL_MARGINAL = 3; +const uint32_t RS_TRUST_LVL_FULL = 4; +const uint32_t RS_TRUST_LVL_ULTIMATE = 5; + + +/* Net Mode */ +const uint32_t RS_NETMODE_UDP = 0x0001; +const uint32_t RS_NETMODE_UPNP = 0x0002; +const uint32_t RS_NETMODE_EXT = 0x0003; +const uint32_t RS_NETMODE_UNREACHABLE = 0x0004; + +/* Visibility */ +const uint32_t RS_VS_DHT_ON = 0x0001; +const uint32_t RS_VS_DISC_ON = 0x0002; + +/* State */ +const uint32_t RS_PEER_STATE_FRIEND = 0x0001; +const uint32_t RS_PEER_STATE_ONLINE = 0x0002; +const uint32_t RS_PEER_STATE_CONNECTED = 0x0004; +const uint32_t RS_PEER_STATE_UNREACHABLE= 0x0008; + +/* Connect state */ +const uint32_t RS_PEER_CONNECTSTATE_TRYING_TUNNEL = 1; +const uint32_t RS_PEER_CONNECTSTATE_TRYING_TCP = 2; +const uint32_t RS_PEER_CONNECTSTATE_TRYING_UDP = 3; +const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_TCP = 4; +const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_UDP = 5; +const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_TUNNEL = 6; +const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN = 7; + +/* Groups */ +#define RS_GROUP_ID_FRIENDS "Friends" +#define RS_GROUP_ID_FAMILY "Family" +#define RS_GROUP_ID_COWORKERS "Co-Workers" +#define RS_GROUP_ID_OTHERS "Other Contacts" +#define RS_GROUP_ID_FAVORITES "Favorites" + +const uint32_t RS_GROUP_FLAG_STANDARD = 0x0001; + +/* A couple of helper functions for translating the numbers games */ + +std::string RsPeerTrustString(uint32_t trustLvl); +std::string RsPeerNetModeString(uint32_t netModel); +std::string RsPeerLastConnectString(uint32_t lastConnect); + + +/* Details class */ +class RsPeerDetails +{ + public: + + RsPeerDetails(); + + /* Auth details */ + bool isOnlyGPGdetail; + std::string id; + std::string gpg_id; + std::string name; + std::string email; + std::string location; + std::string org; + + std::string issuer; + + std::string fpr; /* pgp fingerprint */ + std::string authcode; + std::list gpgSigners; + + uint32_t trustLvl; + uint32_t validLvl; + + bool ownsign; /* we have signed the remote peer GPG key */ + bool hasSignedMe; /* the remote peer has signed my GPG key */ + + bool accept_connection; + + /* Network details (only valid if friend) */ + uint32_t state; + + std::string localAddr; + uint16_t localPort; + std::string extAddr; + uint16_t extPort; + std::string dyndns; + std::list ipAddressList; + + uint32_t netMode; + uint32_t tryNetMode; /* only for ownState */ + uint32_t visState; + + /* basic stats */ + uint32_t lastConnect; /* how long ago */ + uint32_t connectState; /* RS_PEER_CONNECTSTATE_... */ + std::string connectStateString; /* Additional string like ip address */ + uint32_t connectPeriod; + bool foundDHT; +}; + +class RsGroupInfo +{ +public: + RsGroupInfo(); + + std::string id; + std::string name; + uint32_t flag; + + std::list peerIds; +}; + +std::ostream &operator<<(std::ostream &out, const RsPeerDetails &detail); + +class RsPeers +{ + public: + + RsPeers() { return; } +virtual ~RsPeers() { return; } + + /* Updates ... */ +virtual bool FriendsChanged() = 0; +virtual bool OthersChanged() = 0; + + /* Peer Details (Net & Auth) */ +virtual std::string getOwnId() = 0; + +virtual bool getOnlineList(std::list &ssl_ids) = 0; +virtual bool getFriendList(std::list &ssl_ids) = 0; +//virtual bool getOthersList(std::list &ssl_ids) = 0; +virtual bool getPeerCount (unsigned int *pnFriendCount, unsigned int *pnnOnlineCount, bool ssl) = 0; + +virtual bool isOnline(const std::string &ssl_id) = 0; +virtual bool isFriend(const std::string &ssl_id) = 0; +virtual bool isGPGAccepted(const std::string &gpg_id_is_friend) = 0; // +virtual std::string getPeerName(const std::string &ssl_or_gpg_id) = 0; +virtual std::string getGPGName(const std::string &gpg_id) = 0; +virtual bool getPeerDetails(const std::string &ssl_or_gpg_id, RsPeerDetails &d) = 0; //get Peer detail accept SSL and PGP certs + + /* Using PGP Ids */ +virtual std::string getGPGOwnId() = 0; +virtual std::string getGPGId(const std::string &sslid_or_gpgid) = 0; //return the gpg id of the given gpg or ssl id +virtual bool getGPGAcceptedList(std::list &gpg_ids) = 0; +virtual bool getGPGSignedList(std::list &gpg_ids) = 0;//friends that we accpet to connect with but we don't want to sign their gpg key +virtual bool getGPGValidList(std::list &gpg_ids) = 0; +virtual bool getGPGAllList(std::list &gpg_ids) = 0; +virtual bool getGPGDetails(const std::string &gpg_id, RsPeerDetails &d) = 0; +virtual bool getSSLChildListOfGPGId(const std::string &gpg_id, std::list &ssl_ids) = 0; + + /* Add/Remove Friends */ +virtual bool addFriend(const std::string &ssl_id, const std::string &gpg_id) = 0; +virtual bool addDummyFriend(const std::string &gpg_id) = 0; //we want to add a empty ssl friend for this gpg id +virtual bool isDummyFriend(const std::string &ssl_id) = 0; +virtual bool removeFriend(const std::string &ssl_or_gpg_id) = 0; +virtual bool cleanUnusedLocations() = 0 ; + + /* Network Stuff */ +virtual bool connectAttempt(const std::string &ssl_id) = 0; +virtual bool setLocation(const std::string &ssl_id, const std::string &location) = 0;//location is shown in the gui to differentiate ssl certs +virtual bool setLocalAddress(const std::string &ssl_id, const std::string &addr, uint16_t port) = 0; +virtual bool setExtAddress( const std::string &ssl_id, const std::string &addr, uint16_t port) = 0; +virtual bool setDynDNS(const std::string &id, const std::string &addr) = 0; +virtual bool setNetworkMode(const std::string &ssl_id, uint32_t netMode) = 0; +virtual bool setVisState(const std::string &ssl_id, uint32_t vis) = 0; + +virtual void getIPServersList(std::list& ip_servers) = 0; +virtual void allowServerIPDetermination(bool) = 0; +virtual void allowTunnelConnection(bool) = 0; +virtual bool getAllowServerIPDetermination() = 0 ; +virtual bool getAllowTunnelConnection() = 0 ; + + /* Auth Stuff */ +virtual std::string GetRetroshareInvite(const std::string& ssl_id) = 0; +virtual std::string GetRetroshareInvite() = 0; + +virtual bool loadCertificateFromFile(const std::string &fname, std::string &ssl_id, std::string &gpg_id) = 0; +virtual bool loadDetailsFromStringCert(const std::string &certGPG, RsPeerDetails &pd,std::string& error_string) = 0; +virtual bool cleanCertificate(const std::string &certstr, std::string &cleanCert) = 0; +virtual bool saveCertificateToFile(const std::string &id, const std::string &fname) = 0; +virtual std::string saveCertificateToString(const std::string &id) = 0; + +virtual bool setAcceptToConnectGPGCertificate(const std::string &gpg_id, bool acceptance) = 0; +virtual bool signGPGCertificate(const std::string &gpg_id) = 0; +virtual bool trustGPGCertificate(const std::string &gpg_id, uint32_t trustlvl) = 0; + + /* Group Stuff */ +virtual bool addGroup(RsGroupInfo &groupInfo) = 0; +virtual bool editGroup(const std::string &groupId, RsGroupInfo &groupInfo) = 0; +virtual bool removeGroup(const std::string &groupId) = 0; +virtual bool getGroupInfo(const std::string &groupId, RsGroupInfo &groupInfo) = 0; +virtual bool getGroupInfoList(std::list &groupInfoList) = 0; +// groupId == "" && assign == false -> remove from all groups +virtual bool assignPeerToGroup(const std::string &groupId, const std::string &peerId, bool assign) = 0; +virtual bool assignPeersToGroup(const std::string &groupId, const std::list &peerIds, bool assign) = 0; + +}; + +#endif diff --git a/libretroshare/src/retroshare/rsphoto.h b/libretroshare/src/retroshare/rsphoto.h new file mode 100644 index 000000000..9a16cce4f --- /dev/null +++ b/libretroshare/src/retroshare/rsphoto.h @@ -0,0 +1,127 @@ +#ifndef RETROSHARE_PHOTO_GUI_INTERFACE_H +#define RETROSHARE_PHOTO_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsphoto.h + * + * RetroShare C++ Interface. + * + * Copyright 2008-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include + +/* The Main Interface Class - for information about your Peers */ +class RsPhoto; +extern RsPhoto *rsPhoto; + +class RsPhotoDetails; +class RsPhotoShowDetails; + +class RsPhotoShowInfo +{ + public: + + std::string photoId; + std::wstring altComment; + uint32_t deltaT; /* in 100ths of sec? */ +}; + +class RsPhotoShowDetails +{ + public: + + RsPhotoShowDetails(); + + std::string id; + std::string showid; + + std::string name; + std::wstring location; + std::wstring comment; + std::string date; + std::list photos; +}; + +/* Details class */ +class RsPhotoDetails +{ + public: + + RsPhotoDetails(); + + std::string id; + std::string srcid; + + std::string hash; + uint64_t size; + + std::string name; + std::wstring comment; + + std::string location; + std::string date; + + uint32_t format; + + bool isAvailable; + std::string path; +}; + +std::ostream &operator<<(std::ostream &out, const RsPhotoShowDetails &detail); +std::ostream &operator<<(std::ostream &out, const RsPhotoDetails &detail); + +class RsPhoto +{ + public: + + RsPhoto() { return; } +virtual ~RsPhoto() { return; } + + /* changed? */ +virtual bool updated() = 0; + + /* access data */ +virtual bool getPhotoList(std::string id, std::list &hashs) = 0; +virtual bool getShowList(std::string id, std::list &showIds) = 0; +virtual bool getShowDetails(std::string id, std::string showId, RsPhotoShowDetails &detail) = 0; +virtual bool getPhotoDetails(std::string id, std::string photoId, RsPhotoDetails &detail) = 0; + + /* add / delete */ +virtual std::string createShow(std::string name) = 0; +virtual bool deleteShow(std::string showId) = 0; +virtual bool addPhotoToShow(std::string showId, std::string photoId, int16_t index) = 0; +virtual bool movePhotoInShow(std::string showId, std::string photoId, int16_t index) = 0; +virtual bool removePhotoFromShow(std::string showId, std::string photoId) = 0; + +virtual std::string addPhoto(std::string path) = 0; /* add from file */ +virtual bool addPhoto(std::string srcId, std::string photoId) = 0; /* add from peers photos */ +virtual bool deletePhoto(std::string photoId) = 0; + + /* modify properties (TODO) */ +virtual bool modifyShow(std::string showId, std::wstring name, std::wstring comment) = 0; +virtual bool modifyPhoto(std::string photoId, std::wstring name, std::wstring comment) = 0; +virtual bool modifyShowComment(std::string showId, std::string photoId, std::wstring comment) = 0; + +}; + +#endif diff --git a/libretroshare/src/retroshare/rsplugin.h b/libretroshare/src/retroshare/rsplugin.h new file mode 100644 index 000000000..e35ef5329 --- /dev/null +++ b/libretroshare/src/retroshare/rsplugin.h @@ -0,0 +1,76 @@ +/* + * "$Id: rsiface.h,v 1.9 2007-04-21 19:08:51 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2011-2011 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#pragma once + +#include +#include +#include +#include + +class RsPluginHandler ; +extern RsPluginHandler *rsPlugins ; + +class p3Service ; +class p3ConnectMgr ; +class MainPage ; +class QIcon ; +class RsCacheService ; +class ftServer ; +class pqiService ; + +class RsPlugin +{ + public: + virtual RsCacheService *rs_cache_service() const { return NULL ; } + virtual pqiService *rs_pqi_service() const { return NULL ; } + virtual uint16_t rs_service_id() const { return 0 ; } + virtual MainPage *qt_page() const { return NULL ; } + virtual QIcon *qt_icon() const { return NULL ; } + + virtual std::string configurationFileName() const { return std::string() ; } + virtual std::string getShortPluginDescription() const = 0 ; + virtual std::string getPluginName() const = 0 ; +}; + +class RsPluginHandler +{ + public: + // Returns the number of loaded plugins. + // + virtual int nbPlugins() const = 0 ; + virtual RsPlugin *plugin(int i) = 0 ; + virtual const std::vector& getPluginDirectories() const = 0; + + virtual void slowTickPlugins(time_t sec) = 0 ; + + virtual const std::string& getLocalCacheDir() const =0; + virtual const std::string& getRemoteCacheDir() const =0; + virtual ftServer *getFileServer() const = 0; + virtual p3ConnectMgr *getConnectMgr() const = 0; +}; + + + diff --git a/libretroshare/src/retroshare/rsrank.h b/libretroshare/src/retroshare/rsrank.h new file mode 100644 index 000000000..a69425c91 --- /dev/null +++ b/libretroshare/src/retroshare/rsrank.h @@ -0,0 +1,96 @@ +#ifndef RETROSHARE_RANKING_GUI_INTERFACE_H +#define RETROSHARE_RANKING_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsrank.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include + +/* The Main Interface Class - for information about your Peers */ +class RsRanks; +extern RsRanks *rsRanks; + +class RsRankComment +{ + public: + + std::string id; + std::wstring comment; + int32_t score; + time_t timestamp; +}; + +class RsRankDetails +{ + public: + + std::string rid; + std::wstring link; + std::wstring title; + float rank; + bool ownTag; + + std::list comments; +}; + +const uint32_t RS_RANK_SCORE = 0x0001; +const uint32_t RS_RANK_TIME = 0x0002; +const uint32_t RS_RANK_ALG = 0x0003; + +std::ostream &operator<<(std::ostream &out, const RsRankDetails &detail); + +class RsRanks +{ + public: + + RsRanks() { return; } +virtual ~RsRanks() { return; } + + /* needs update? */ +virtual bool updated() = 0; + + /* Set Sort Methods */ +virtual bool setSortPeriod(uint32_t period) = 0; +virtual bool setSortMethod(uint32_t type) = 0; +virtual bool clearPeerFilter() = 0; +virtual bool setPeerFilter(std::list peers) = 0; + + /* get Ids */ +virtual uint32_t getRankingsCount() = 0; +virtual float getMaxRank() = 0; +virtual bool getRankings(uint32_t first, uint32_t count, std::list &rids) = 0; +virtual bool getRankDetails(std::string rid, RsRankDetails &details) = 0; + + /* Add New Comment / Msg */ +virtual std::string newRankMsg(std::wstring link, std::wstring title, std::wstring comment, int32_t score) = 0; +virtual bool updateComment(std::string rid, std::wstring comment, int32_t score) = 0; + +virtual std::string anonRankMsg(std::string rid, std::wstring link, std::wstring title) = 0; + +}; + +#endif diff --git a/libretroshare/src/retroshare/rsstatus.h b/libretroshare/src/retroshare/rsstatus.h new file mode 100644 index 000000000..1ab703e52 --- /dev/null +++ b/libretroshare/src/retroshare/rsstatus.h @@ -0,0 +1,103 @@ +#ifndef RS_STATUS_INTERFACE_H +#define RS_STATUS_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsstatus.h + * + * RetroShare C++ . + * + * Copyright 2007-2008 by Vinny Do, Chris Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +class RsStatus; + +extern RsStatus *rsStatus; + +#include +#include +#include +#include + + +const uint32_t RS_STATUS_OFFLINE = 0x0000; +const uint32_t RS_STATUS_AWAY = 0x0001; +const uint32_t RS_STATUS_BUSY = 0x0002; +const uint32_t RS_STATUS_ONLINE = 0x0003; +const uint32_t RS_STATUS_INACTIVE = 0x0004; + +const uint32_t RS_STATUS_COUNT = 0x0005; // count of status + +//! data object for peer status information +/*! + * data object used for peer status information + */ +class StatusInfo +{ + public: + StatusInfo() + { + status = 0; + time_stamp = 0; + } + + public: + std::string id; + uint32_t status; + time_t time_stamp; /// for owner time set, and for their peers time sent +}; + + +//! Interface to retroshare for Rs status +/*! + * Provides an interface for retroshare's status functionality + */ +class RsStatus +{ + public: + + /** + * This retrieves the own status info + * @param statusInfo is populated with own status + */ + virtual bool getOwnStatus(StatusInfo& statusInfo) = 0; + + /** + * This retrieves the status info on the client's peers + * @param statusInfo is populated with client's peer's status + */ + virtual bool getStatusList(std::list& statusInfo) = 0; + + /** + * This retrieves the status info one peer + * @param statusInfo is populated with client's peer's status + */ + virtual bool getStatus(std::string &id, StatusInfo &statusInfo) = 0; + + /** + * send the client's status to his/her peers + * @param id the peer to send the status (empty, send to all) + * @param status the status of the peers + * @return will return false if status info does not belong to client + */ + virtual bool sendStatus(std::string id, uint32_t status) = 0; +}; + + +#endif diff --git a/libretroshare/src/retroshare/rsturtle.h b/libretroshare/src/retroshare/rsturtle.h new file mode 100644 index 000000000..aaec76851 --- /dev/null +++ b/libretroshare/src/retroshare/rsturtle.h @@ -0,0 +1,130 @@ +#ifndef RETROSHARE_TURTLE_GUI_INTERFACE_H +#define RETROSHARE_TURTLE_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsturtle.h + * + * RetroShare C++ Interface. + * + * Copyright 2009 by Cyril Soler. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "csoler@users.sourceforge.net" + * + */ + +#pragma once + +#include +#include +#include +#include + +class LinearizedExpression ; + +class RsTurtle; +extern RsTurtle *rsTurtle ; + +typedef uint32_t TurtleRequestId ; + +// This is the structure used to send back results of the turtle search +// to the notifyBase class, or send info to the GUI. + +struct TurtleFileInfo +{ + std::string hash ; + std::string name ; + uint64_t size ; +}; + +struct TurtleRequestDisplayInfo +{ + uint32_t request_id ; // Id of the request + std::string source_peer_id ; // Peer that relayed the request + uint32_t age ; // Age in seconds + uint32_t depth ; // Depth of the request. Might be altered. +}; + +class TurtleTrafficStatisticsInfo +{ + public: + float unknown_updn_Bps ; // unknown data transit bitrate (in Bytes per sec.) + float data_up_Bps ; // upload (in Bytes per sec.) + float data_dn_Bps ; // download (in Bytes per sec.) + float tr_up_Bps ; // tunnel requests upload bitrate (in Bytes per sec.) + float tr_dn_Bps ; // tunnel requests dnload bitrate (in Bytes per sec.) + float total_up_Bps ; // turtle network management bitrate (in Bytes per sec.) + float total_dn_Bps ; // turtle network management bitrate (in Bytes per sec.) +}; + +// Interface class for turtle hopping. +// +// This class mainly interacts with the turtle router, that is responsible +// for routing turtle packets between peers, accepting/forwarding search +// requests and dowloading files. +// +// As seen from here, the interface is really simple. +// +class RsTurtle +{ + public: + enum FileSharingStrategy { SHARE_ENTIRE_NETWORK, SHARE_FRIENDS_ONLY } ; + + RsTurtle() {} + virtual ~RsTurtle() {} + + // Lauches a search request through the pipes, and immediately returns + // the request id, which will be further used by the gui to store results + // as they come back. + // + virtual TurtleRequestId turtleSearch(const std::string& match_string) = 0 ; + virtual TurtleRequestId turtleSearch(const LinearizedExpression& expr) = 0 ; + + // Sets the file sharing strategy. It concerns all local files. It would + // be better to handle this for each file, of course. + + void setFileSharingStrategy(FileSharingStrategy f) { _sharing_strategy = f ; } + + // Initiates tunnel handling for the given file hash. tunnels. Launches + // an exception if an error occurs during the initialization process. The + // turtle router itself does not initiate downloads, it only maintains + // tunnels for the given hash. The download should be driven by the file + // transfer module by calling ftServer::FileRequest(). + // + virtual void monitorFileTunnels(const std::string& name,const std::string& file_hash,uint64_t size) = 0 ; + + // Tells the turtle router to stop handling tunnels for the given file hash. Traditionally this should + // be called after calling ftServer::fileCancel(). + // + virtual void stopMonitoringFileTunnels(const std::string& file_hash) = 0 ; + + // Get info from the turtle router. I use std strings to hide the internal structs. + // + virtual void getInfo(std::vector >&,std::vector >&, + std::vector&,std::vector&) const = 0; + + // Get info about turtle traffic. See TurtleTrafficStatisticsInfo members for details. + // + virtual void getTrafficStatistics(TurtleTrafficStatisticsInfo& info) const = 0; + + // Convenience function. + virtual bool isTurtlePeer(const std::string& peer_id) const = 0 ; + + protected: + FileSharingStrategy _sharing_strategy ; +}; + +#endif diff --git a/libretroshare/src/retroshare/rstypes.h b/libretroshare/src/retroshare/rstypes.h new file mode 100644 index 000000000..c53f3ac22 --- /dev/null +++ b/libretroshare/src/retroshare/rstypes.h @@ -0,0 +1,408 @@ +#ifndef RS_TYPES_GUI_INTERFACE_H +#define RS_TYPES_GUI_INTERFACE_H + +/* + * "$Id: rstypes.h,v 1.7 2007-05-05 16:10:05 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include +#include +#include +#include + +typedef std::string RsCertId; +typedef std::string RsChanId; +typedef std::string RsMsgId; +typedef std::string RsAuthId; + +const uint32_t FT_STATE_FAILED = 0x0000 ; +const uint32_t FT_STATE_OKAY = 0x0001 ; +const uint32_t FT_STATE_WAITING = 0x0002 ; +const uint32_t FT_STATE_DOWNLOADING = 0x0003 ; +const uint32_t FT_STATE_COMPLETE = 0x0004 ; +const uint32_t FT_STATE_QUEUED = 0x0005 ; +const uint32_t FT_STATE_PAUSED = 0x0006 ; +const uint32_t FT_STATE_CHECKING_HASH = 0x0007 ; + +// These constants are used by RsDiscSpace +// +const uint32_t RS_PARTIALS_DIRECTORY = 0x0000 ; +const uint32_t RS_DOWNLOAD_DIRECTORY = 0x0001 ; +const uint32_t RS_CONFIG_DIRECTORY = 0x0002 ; + +class TransferInfo +{ + public: + /**** Need Some of these Fields ****/ + std::string peerId; + std::string name; /* if has alternative name? */ + double tfRate; /* kbytes */ + int status; /* FT_STATE_... */ + uint64_t transfered ; // used when no chunkmap data is available +}; + +enum QueueMove { QUEUE_TOP = 0x00, + QUEUE_UP = 0x01, + QUEUE_DOWN = 0x02, + QUEUE_BOTTOM = 0x03 +}; + +enum DwlSpeed { SPEED_LOW = 0x00, + SPEED_NORMAL = 0x01, + SPEED_HIGH = 0x02 +}; + + + +class FileInfo +{ + /* old BaseInfo Entries */ + public: + + FileInfo() :flags(0), mId(0) { return; } + RsCertId id; /* key for matching everything */ + int flags; /* INFO_TAG above */ + + /* allow this to be tweaked by the GUI Model */ + mutable unsigned int mId; /* (GUI) Model Id -> unique number */ + + /* Old FileInfo Entries */ + public: + + static const int kRsFiStatusNone = 0; + static const int kRsFiStatusStall = 1; + static const int kRsFiStatusProgress = 2; + static const int kRsFiStatusDone = 2; + + /* FileInfo(); */ + + int searchId; /* 0 if none */ + std::string path; + std::string fname; + std::string hash; + std::string ext; + + uint64_t size; + uint64_t avail; /* how much we have */ + int status; + + double rank; + int age; + uint32_t queue_position ; + + /* Transfer Stuff */ + uint64_t transfered; + double tfRate; /* in kbytes */ + uint32_t downloadStatus; /* 0 = Err, 1 = Ok, 2 = Done */ + std::list peers; + + DwlSpeed priority ; + time_t lastTS; +}; + +std::ostream &operator<<(std::ostream &out, const FileInfo &info); + + +/* matched to the uPnP states */ +#define UPNP_STATE_UNINITIALISED 0 +#define UPNP_STATE_UNAVAILABILE 1 +#define UPNP_STATE_READY 2 +#define UPNP_STATE_FAILED_TCP 3 +#define UPNP_STATE_FAILED_UDP 4 +#define UPNP_STATE_ACTIVE 5 + +class RsConfig +{ + public: + RsConfig() + { + localPort = extPort = 0 ; + firewalled = forwardPort = false ; + maxDownloadDataRate = maxUploadDataRate = maxIndivDataRate = 0 ; + promptAtBoot = 0 ; + DHTActive = uPnPActive = netLocalOk = netUpnpOk = netDhtOk = netStunOk = netExtraAddressOk = false ; + uPnPState = DHTPeers = 0 ; + } + std::string ownId; + std::string ownName; + + std::string localAddr; + int localPort; + std::string extAddr; + int extPort; + std::string extName; + + bool firewalled; + bool forwardPort; + + int maxDownloadDataRate; /* kb */ + int maxUploadDataRate; /* kb */ + int maxIndivDataRate; /* kb */ + + int promptAtBoot; /* popup the password prompt */ + + /* older data types */ + bool DHTActive; + bool uPnPActive; + + int uPnPState; + int DHTPeers; + + /* Flags for Network Status */ + bool netLocalOk; /* That we've talked to someone! */ + bool netUpnpOk; /* upnp is enabled and active */ + bool netDhtOk; /* response from dht */ + bool netStunOk; /* recvd stun / udp packets */ + bool netExtraAddressOk; /* recvd ip address with external finder*/ + + uint32_t netDhtNetSize; /* response from dht */ + uint32_t netDhtRsNetSize; /* response from dht */ + +}; + +/********************** For Search Interface *****************/ + +/* This is still rough, implement later! */ + + /* text based ones */ +const std::string TypeExt = "ext"; +const std::string TypeName = "name"; +const std::string TypeHash = "hash"; +const std::string TypeSize = "size"; + +const int OpContains = 0x001; +const int OpExactMatch = 0x002; +const int OpLessThan = 0x003; +const int OpGreaterThan = 0x004; + +class Condition +{ + public: + + std::string type; + int op; + double value; + std::string name; +}; + +class SearchRequest +{ + public: + int searchId; + RsCertId toId; /* all zeros for everyone! */ + std::list tests; +}; + + +/********************** For FileCache Interface *****************/ + +#define DIR_TYPE_ROOT 0x01 +#define DIR_TYPE_PERSON 0x02 +#define DIR_TYPE_DIR 0x04 +#define DIR_TYPE_FILE 0x08 + +/* flags for Directry request - + * two types; + * (1) Local / Remote (top byte) + * (2) Request type: Parent / Child - allows reduction in workload. + * (TODO) + */ + +#define DIR_FLAGS_LOCAL 0x1000 +#define DIR_FLAGS_REMOTE 0x2000 + +#define DIR_FLAGS_PARENT 0x0001 +#define DIR_FLAGS_DETAILS 0x0002 +#define DIR_FLAGS_CHILDREN 0x0004 +#define DIR_FLAGS_NETWORK_WIDE 0x0008 +#define DIR_FLAGS_BROWSABLE 0x0010 + +class DirStub +{ + public: + uint8_t type; + std::string name; + void *ref; +}; + +class DirDetails +{ + public: + void *parent; + int prow; /* parent row */ + + void *ref; + uint8_t type; + std::string id; + std::string name; + std::string hash; + std::string path; + uint64_t count; + uint32_t age; + uint32_t flags; + uint32_t min_age ; // minimum age of files in this subtree + + std::list children; +}; + +class FileDetail +{ + public: + std::string id; + std::string name; + std::string hash; + std::string path; + uint64_t size; + uint32_t age; + uint32_t rank; +}; + +class CompressedChunkMap ; + +class FileChunksInfo +{ + public: + enum ChunkState { CHUNK_DONE=2, CHUNK_ACTIVE=1, CHUNK_OUTSTANDING=0 } ; + enum ChunkStrategy { CHUNK_STRATEGY_STREAMING, CHUNK_STRATEGY_RANDOM } ; + + struct SliceInfo + { + uint32_t start ; + uint32_t size ; + std::string peer_id ; + }; + + uint64_t file_size ; // real size of the file + uint32_t chunk_size ; // size of chunks + uint32_t flags ; + uint32_t strategy ; + + // dl state of chunks. Only the last chunk may have size < chunk_size + std::vector chunks ; + + // For each source peer, gives the compressed bit map of have/don't have sate + std::map compressed_peer_availability_maps ; + + // For each chunk (by chunk number), gives the completion of the chunk. + // + std::vector > active_chunks ; + + // The list of pending requests, chunk per chunk (by chunk id) + // + std::map > pending_slices ; +}; + +class CompressedChunkMap +{ + public: + CompressedChunkMap() {} + + CompressedChunkMap(const std::vector& uncompressed_data) + { + _map.resize( getCompressedSize(uncompressed_data.size()),0 ) ; + + for(uint32_t i=0;i>5) + !!(size&31) ; } + + uint32_t filledChunks(uint32_t nbchks) + { + uint32_t res = 0 ; + for(uint32_t i=0;i> 5] & (1 << (i & 31))) > 0 ; } + + inline void set(uint32_t j) { _map[j >> 5] |= (1 << (j & 31)) ; } + inline void reset(uint32_t j) { _map[j >> 5] &= ~(1 << (j & 31)) ; } + + /// compressed map, one bit per chunk + std::vector _map ; +}; + +class CRC32Map +{ + public: + // Build from a file. + // + CRC32Map(uint64_t file_size,uint32_t chunk_size) + : _crcs( file_size/chunk_size + ( (file_size%chunk_size)>0)), _ccmap(file_size/chunk_size + ( (file_size%chunk_size)>0),0) + { + } + CRC32Map() {} + + // Compares two maps and returns the valid chunks in a compressed chunk map. + // + friend CompressedChunkMap compare(const CRC32Map& crc1,const CRC32Map& crc2) ; + + inline void set(uint32_t i,uint32_t val) { _crcs[i] = val ; _ccmap.set(i) ; } + + inline uint32_t operator[](int i) const { return _crcs[i] ; } + inline uint32_t size() const { return _crcs.size() ; } + private: + std::vector _crcs; + CompressedChunkMap _ccmap ; + + friend class RsTurtleFileCrcItem ; + friend class RsFileItemSerialiser ; + friend class RsFileCRC32Map ; +}; + +/* class which encapsulates download details */ +class DwlDetails { +public: + DwlDetails() { return; } + DwlDetails(std::string fname, std::string hash, int count, std::string dest, + uint32_t flags, std::list srcIds, uint32_t queue_pos) + : fname(fname), hash(hash), count(count), dest(dest), flags(flags), + srcIds(srcIds), queue_position(queue_pos), retries(0) { return; } + + /* download details */ + std::string fname; + std::string hash; + int count; + std::string dest; + uint32_t flags; + std::list srcIds; + + /* internally used in download queue */ + uint32_t queue_position; + + /* how many times a failed dwl will be requeued */ + unsigned int retries; +}; + +#endif diff --git a/libretroshare/src/rsserver/Makefile b/libretroshare/src/rsserver/Makefile new file mode 100644 index 000000000..fae412965 --- /dev/null +++ b/libretroshare/src/rsserver/Makefile @@ -0,0 +1,35 @@ + +RS_TOP_DIR = .. +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/scripts/config.mk +############################################################### + +RSOBJ = rsinit.o \ + p3peers.o \ + p3rank.o \ + p3photo.o \ + p3msgs.o \ + p3blog.o \ + p3discovery.o \ + p3face-server.o \ + p3face-config.o \ + p3face-msgs.o \ + rsiface.o \ + rstypes.o + +#TESTOBJ = + +#TESTS = + +all: librs tests + +#tlvbase_test : tlvbase_test.o +# $(CC) $(CFLAGS) -o tlvbase_test tlvbase_test.o $(OBJ) $(LIBS) + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/rsserver/p3discovery.cc b/libretroshare/src/rsserver/p3discovery.cc new file mode 100644 index 000000000..bd58e11a5 --- /dev/null +++ b/libretroshare/src/rsserver/p3discovery.cc @@ -0,0 +1,68 @@ +/* + * libretroshare/src/rsserver: p3discovery.cc + * + * RetroShare C++ Interface. + * + * Copyright 2008-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rsserver/p3discovery.h" +#include +#include + +RsDisc *rsDisc = NULL; + +bool p3Discovery::getDiscGPGFriends(std::string id, std::list& gpg_friends) +{ + if (mDisc) + { + return mDisc->potentialGPGproxies(id, gpg_friends); + } + return false; +} + +bool p3Discovery::getDiscFriends(std::string id, std::list &friends) +{ + if (mDisc) + { + return mDisc->potentialproxies(id, friends); + } + return false; +} + +bool p3Discovery::getDiscVersions(std::map &versions) +{ + if (mDisc) + { + mDisc->getversions(versions); + return true; + } + return false; +} + +bool p3Discovery::getWaitingDiscCount(unsigned int *sendCount, unsigned int *recvCount) +{ + if (mDisc) + { + mDisc->getWaitingDiscCount(sendCount, recvCount); + return true; + } + return false; +} diff --git a/libretroshare/src/rsserver/p3discovery.h b/libretroshare/src/rsserver/p3discovery.h new file mode 100644 index 000000000..c1d70584f --- /dev/null +++ b/libretroshare/src/rsserver/p3discovery.h @@ -0,0 +1,51 @@ +#ifndef RETROSHARE_P3_DISC_INTERFACE_H +#define RETROSHARE_P3_DISC_INTERFACE_H + +/* + * libretroshare/src/rsserver: p3discovery.h + * + * RetroShare C++ Interface. + * + * Copyright 2008-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rsdisc.h" +#include "services/p3disc.h" + +class p3Discovery: public RsDisc +{ + public: + + p3Discovery(p3disc *disc) + :mDisc(disc) { return; } +virtual ~p3Discovery() { return; } + +virtual bool getDiscFriends(std::string id, std::list &friends); +virtual bool getDiscGPGFriends(std::string id, std::list &gpg_friends); +virtual bool getDiscVersions(std::map &versions); +virtual bool getWaitingDiscCount(unsigned int *sendCount, unsigned int *recvCount); + + private: + + p3disc *mDisc; +}; + +#endif + diff --git a/libretroshare/src/rsserver/p3face-config.cc b/libretroshare/src/rsserver/p3face-config.cc new file mode 100644 index 000000000..d2eab9e45 --- /dev/null +++ b/libretroshare/src/rsserver/p3face-config.cc @@ -0,0 +1,194 @@ + +/* + * "$Id: p3face-config.cc,v 1.4 2007-05-05 16:10:05 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "rsserver/p3face.h" + +#include +#include +#include "pqi/authssl.h" +#include "pqi/authgpg.h" +#include "retroshare/rsinit.h" +#include "util/rsdebug.h" +const int p3facemsgzone = 11453; + +#include +#include + + +/****************************************/ +/* RsIface Config */ +/* Config */ + +int RsServer::ConfigSetDataRates( int totalDownload, int totalUpload ) /* in kbrates */ +{ + /* fill the rsiface class */ + RsIface &iface = getIface(); + + /* lock Mutexes */ + lockRsCore(); /* LOCK */ + iface.lockData(); /* LOCK */ + + pqih -> setMaxRate(true, totalDownload); + pqih -> setMaxRate(false, totalUpload); + + pqih -> save_config(); + + /* unlock Mutexes */ + iface.unlockData(); /* UNLOCK */ + unlockRsCore(); /* UNLOCK */ + + /* does its own locking */ + UpdateAllConfig(); + return 1; +} + + +int RsServer::ConfigGetDataRates( float &inKb, float &outKb ) /* in kbrates */ +{ + /* fill the rsiface class */ + RsIface &iface = getIface(); + + /* lock Mutexes */ + lockRsCore(); /* LOCK */ + iface.lockData(); /* LOCK */ + + pqih -> getCurrentRates(inKb, outKb); + + /* unlock Mutexes */ + iface.unlockData(); /* UNLOCK */ + unlockRsCore(); /* UNLOCK */ + + return 1; +} + + +int RsServer::ConfigSetBootPrompt( bool on ) +{ + + return 1; +} + + +int RsServer::UpdateAllConfig() +{ + /* fill the rsiface class */ + RsIface &iface = getIface(); + + /* lock Mutexes */ + lockRsCore(); /* LOCK */ + iface.lockData(); /* LOCK */ + + RsConfig &config = iface.mConfig; + + config.ownId = AuthSSL::getAuthSSL()->OwnId(); + config.ownName = AuthGPG::getAuthGPG()->getGPGOwnName(); + peerConnectState pstate; + mConnMgr->getOwnNetStatus(pstate); + + /* ports */ + config.localAddr = rs_inet_ntoa(pstate.currentlocaladdr.sin_addr); + config.localPort = ntohs(pstate.currentlocaladdr.sin_port); + + config.firewalled = true; + config.forwardPort = true; + + config.extAddr = rs_inet_ntoa(pstate.currentserveraddr.sin_addr); + config.extPort = ntohs(pstate.currentserveraddr.sin_port); + + /* data rates */ + config.maxDownloadDataRate = (int) pqih -> getMaxRate(true); /* kb */ + config.maxUploadDataRate = (int) pqih -> getMaxRate(false); /* kb */ + + config.promptAtBoot = true; /* popup the password prompt */ + + /* update network configuration */ + + pqiNetStatus status; + mConnMgr->getNetStatus(status); + + config.netLocalOk = status.mLocalAddrOk; + config.netUpnpOk = status.mUpnpOk; + config.netStunOk = false; + config.netExtraAddressOk = status.mExtAddrOk; + + config.netDhtOk = status.mDhtOk; + config.netDhtNetSize = status.mDhtNetworkSize; + config.netDhtRsNetSize = status.mDhtRsNetworkSize; + + /* update DHT/UPnP config */ + + config.uPnPState = mConnMgr->getUPnPState(); + config.uPnPActive = mConnMgr->getUPnPEnabled(); + config.DHTPeers = 20; + config.DHTActive = mConnMgr->getDHTEnabled(); + + /* Notify of Changes */ +// iface.setChanged(RsIface::Config); + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_CONFIG, NOTIFY_TYPE_MOD); + + /* unlock Mutexes */ + iface.unlockData(); /* UNLOCK */ + unlockRsCore(); /* UNLOCK */ + + return 1; + + +} + +void RsServer::ConfigFinalSave() +{ + /* force saving of transfers TODO */ + //ftserver->saveFileTransferStatus(); + if(!RsInit::getAutoLogin()) + RsInit::RsClearAutoLogin(); + + //AuthSSL::getAuthSSL()->FinalSaveCertificates(); + mConfigMgr->completeConfiguration(); +} + +void RsServer::rsGlobalShutDown() +{ + // TODO: cache should also clean up old files + + ConfigFinalSave(); // save configuration before exit + mConnMgr->shutdown(); /* Handles UPnP */ + + join(); + ftserver->StopThreads(); + + // stop the p3distrib threads +#ifndef MINIMAL_LIBRS + mForums->join(); + mChannels->join(); + +#ifdef RS_USE_BLOGS + mBlogs->join(); +#endif +#endif // MINIMAL_LIBRS + + AuthGPGExit(); +} diff --git a/libretroshare/src/rsserver/p3face-msgs.cc b/libretroshare/src/rsserver/p3face-msgs.cc new file mode 100644 index 000000000..359246f0e --- /dev/null +++ b/libretroshare/src/rsserver/p3face-msgs.cc @@ -0,0 +1,61 @@ + +/* + * "$Id: p3face-msgs.cc,v 1.7 2007-05-05 16:10:06 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "rsserver/p3face.h" +#include "util/rsdir.h" + +#include +#include + +#include "util/rsdebug.h" +const int p3facemsgzone = 11453; + +#include +#include + + + /* Flagging Persons / Channels / Files in or out of a set (CheckLists) */ + +int RsServer::ClearInBroadcast() +{ + return 1; +} + +int RsServer::ClearInSubscribe() +{ + return 1; +} + +int RsServer::SetInBroadcast(std::string id, bool in) /* channel : channel broadcast */ +{ + return 1; +} + +int RsServer::SetInSubscribe(std::string id, bool in) /* channel : subscribed channels */ +{ + return 1; +} diff --git a/libretroshare/src/rsserver/p3face-server.cc b/libretroshare/src/rsserver/p3face-server.cc new file mode 100644 index 000000000..a856a87e0 --- /dev/null +++ b/libretroshare/src/rsserver/p3face-server.cc @@ -0,0 +1,243 @@ + +/* + * "$Id: p3face-server.cc,v 1.5 2007-04-15 18:45:23 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "rsserver/p3face.h" +#include "retroshare/rsplugin.h" + +#include "tcponudp/tou.h" +#include + +#include "pqi/authssl.h" +#include +#include + +/**** +#define DEBUG_TICK 1 +****/ + +RsServer::RsServer(RsIface &i, NotifyBase &callback) + :RsControl(i, callback) +{ + ftserver = NULL; + + mConnMgr = NULL; + + pqih = NULL; + + /* services */ + ad = NULL; + msgSrv = NULL; + chatSrv = NULL; + mStatusSrv = NULL; + mChannels = NULL; + mForums = NULL; + /* caches (that need ticking) */ + + /* Config */ + mConfigMgr = NULL; + mGeneralConfig = NULL; +} + +RsServer::~RsServer() +{ + return; +} + + /* General Internal Helper Functions + ----> MUST BE LOCKED! + */ + +#ifdef WINDOWS_SYS +#include +#include +#endif + +static double getCurrentTS() +{ + +#ifndef WINDOWS_SYS + struct timeval cts_tmp; + gettimeofday(&cts_tmp, NULL); + double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; +#else + struct _timeb timebuf; + _ftime( &timebuf); + double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; +#endif + return cts; +} + + + /* Thread Fn: Run the Core */ +void RsServer::run() +{ + + double timeDelta = 0.25; + double minTimeDelta = 0.1; // 25; + double maxTimeDelta = 0.5; + double kickLimit = 0.15; + + double avgTickRate = timeDelta; + + double lastts, ts; + lastts = ts = getCurrentTS(); + + long lastSec = 0; /* for the slower ticked stuff */ + + int min = 0; + int loop = 0; + + while(isRunning()) + { +#ifndef WINDOWS_SYS + usleep((int) (timeDelta * 1000000)); +#else + Sleep((int) (timeDelta * 1000)); +#endif + + ts = getCurrentTS(); + double delta = ts - lastts; + + /* for the fast ticked stuff */ + if (delta > timeDelta) + { +#ifdef DEBUG_TICK + std::cerr << "Delta: " << delta << std::endl; + std::cerr << "Time Delta: " << timeDelta << std::endl; + std::cerr << "Avg Tick Rate: " << avgTickRate << std::endl; +#endif + + lastts = ts; + + /******************************** RUN SERVER *****************/ + lockRsCore(); + + int moreToTick = ftserver -> tick(); + +#ifdef DEBUG_TICK + std::cerr << "RsServer::run() ftserver->tick(): moreToTick: " << moreToTick << std::endl; +#endif + + unlockRsCore(); + + /* tick the connection Manager */ + mConnMgr->tick(); + /******************************** RUN SERVER *****************/ + + /* adjust tick rate depending on whether there is more. + */ + + avgTickRate = 0.2 * timeDelta + 0.8 * avgTickRate; + + if (1 == moreToTick) + { + timeDelta = 0.9 * avgTickRate; + if (timeDelta > kickLimit) + { + /* force next tick in one sec + * if we are reading data. + */ + timeDelta = kickLimit; + avgTickRate = kickLimit; + } + } + else + { + timeDelta = 1.1 * avgTickRate; + } + + /* limiter */ + if (timeDelta < minTimeDelta) + { + timeDelta = minTimeDelta; + } + else if (timeDelta > maxTimeDelta) + { + timeDelta = maxTimeDelta; + } + + /* Fast Updates */ + + + /* now we have the slow ticking stuff */ + /* stuff ticked once a second (but can be slowed down) */ + if ((int) ts > lastSec) + { + lastSec = (int) ts; + + // Every second! (UDP keepalive). + //tou_tick_stunkeepalive(); + + // every five loops (> 5 secs) + if (loop % 5 == 0) + { + // update_quick_stats(); + + // Update All Every 5 Seconds. + // These Update Functions do the locking themselves. +#ifdef DEBUG_TICK + std::cerr << "RsServer::run() Updates()" << std::endl; +#endif + UpdateAllConfig(); + + + mConfigMgr->tick(); /* saves stuff */ + + } + + // every 60 loops (> 1 min) + if (++loop >= 60) + { + loop = 0; + + /* force saving FileTransferStatus TODO */ + //ftserver->saveFileTransferStatus(); + + /* see if we need to resave certs */ + //AuthSSL::getAuthSSL()->CheckSaveCertificates(); + + /* hour loop */ + if (++min >= 60) + { + min = 0; + } + } + + /* Tick slow services */ + if(rsPlugins) + rsPlugins->slowTickPlugins((time_t)ts); + + // slow update tick as well. + // update(); + } // end of slow tick. + + } // end of only once a second. + } + return; +} + + diff --git a/libretroshare/src/rsserver/p3face.h b/libretroshare/src/rsserver/p3face.h new file mode 100644 index 000000000..c01a6e182 --- /dev/null +++ b/libretroshare/src/rsserver/p3face.h @@ -0,0 +1,182 @@ +#ifndef MRK_P3RS_INTERFACE_H +#define MRK_P3RS_INTERFACE_H + +/* + * "$Id: p3face.h,v 1.9 2007-05-05 16:10:06 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +//#include "server/filedexserver.h" +#include "ft/ftserver.h" +//#include "pqi/pqissl.h" + +#include "pqi/p3cfgmgr.h" +#include "pqi/p3connmgr.h" +#include "pqi/pqipersongrp.h" + +#include "retroshare/rsiface.h" +#include "retroshare/rstypes.h" +#include "util/rsthreads.h" + +#include "services/p3disc.h" +#include "services/p3msgservice.h" +#include "services/p3chatservice.h" +#include "services/p3blogs.h" +#include "services/p3statusservice.h" +#include "services/p3channels.h" +#include "services/p3forums.h" + +/* The Main Interface Class - for controlling the server */ + +/* The init functions are actually Defined in p3face-startup.cc + */ +//RsInit *InitRsConfig(); +//void CleanupRsConfig(RsInit *); +//int InitRetroShare(int argc, char **argv, RsInit *config); +//int LoadCertificates(RsInit *config); + +RsControl *createRsControl(RsIface &iface, NotifyBase ¬ify); + + +class RsServer: public RsControl, public RsThread +{ + public: + /****************************************/ + /* p3face-startup.cc: init... */ + virtual int StartupRetroShare(); + + public: + /****************************************/ + /* p3face.cc: main loop / util fns / locking. */ + + RsServer(RsIface &i, NotifyBase &callback); + virtual ~RsServer(); + + /* Thread Fn: Run the Core */ + virtual void run(); + + public: // no longer private:!!! + /* locking stuff */ + void lockRsCore() + { + // std::cerr << "RsServer::lockRsCore()" << std::endl; + coreMutex.lock(); + } + + void unlockRsCore() + { + // std::cerr << "RsServer::unlockRsCore()" << std::endl; + coreMutex.unlock(); + } + + private: + + /* mutex */ + RsMutex coreMutex; + + /* General Internal Helper Functions + (Must be Locked) + */ +#if 0 + cert *intFindCert(RsCertId id); + RsCertId intGetCertId(cert *c); +#endif + + /****************************************/ + /****************************************/ + /* p3face-msg Operations */ + + public: + /* Flagging Persons / Channels / Files in or out of a set (CheckLists) */ + virtual int SetInBroadcast(std::string id, bool in); /* channel : channel broadcast */ + virtual int SetInSubscribe(std::string id, bool in); /* channel : subscribed channels */ + virtual int ClearInBroadcast(); + virtual int ClearInSubscribe(); + + private: + + void initRsMI(RsMsgItem *msg, MessageInfo &mi); + + /****************************************/ + /****************************************/ + /****************************************/ + /****************************************/ + public: + /* Config */ + + virtual int ConfigGetDataRates(float &inKb, float &outKb); + virtual int ConfigSetDataRates( int totalDownload, int totalUpload ); + virtual int ConfigSetBootPrompt( bool on ); + + virtual void ConfigFinalSave( ); + + /************* Rs shut down function: in upnp 'port lease time' bug *****************/ + + /** + * This function is responsible for ensuring Retroshare exits in a legal state: + * i.e. releases all held resources and saves current configuration + */ + virtual void rsGlobalShutDown( ); + private: + int UpdateAllConfig(); + + /****************************************/ + + + private: + + // The real Server Parts. + + //filedexserver *server; + ftServer *ftserver; + + p3ConnectMgr *mConnMgr; + + pqipersongrp *pqih; + + //sslroot *sslr; + + /* services */ + p3disc *ad; + p3MsgService *msgSrv; + p3ChatService *chatSrv; + p3StatusService *mStatusSrv; + p3Channels *mChannels; + p3Forums *mForums; + /* caches (that need ticking) */ + + /* Config */ + p3ConfigMgr *mConfigMgr; + p3GeneralConfig *mGeneralConfig; + + // Worker Data..... + +}; + +/* Helper function to convert windows paths + * into unix (ie switch \ to /) for FLTK's file chooser + */ + +std::string make_path_unix(std::string winpath); + +#endif diff --git a/libretroshare/src/rsserver/p3msgs.cc b/libretroshare/src/rsserver/p3msgs.cc new file mode 100644 index 000000000..a259fd1d7 --- /dev/null +++ b/libretroshare/src/rsserver/p3msgs.cc @@ -0,0 +1,239 @@ + +/* + * "$Id: p3face-msgs.cc,v 1.7 2007-05-05 16:10:06 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#include +#include + +#include "util/rsdir.h" +#include "util/rsdebug.h" +const int p3facemsgzone = 11453; + +#include +#include + +#include "retroshare/rstypes.h" +#include "rsserver/p3msgs.h" + +#include "services/p3msgservice.h" +#include "services/p3chatservice.h" + +#include "pqi/authgpg.h" + +/* external reference point */ +RsMsgs *rsMsgs = NULL; + +/****************************************/ +/****************************************/ + +bool p3Msgs::getMessageSummaries(std::list &msgList) +{ + return mMsgSrv->getMessageSummaries(msgList); +} + + + +bool p3Msgs::getMessage(const std::string &mid, MessageInfo &msg) +{ + return mMsgSrv->getMessage(mid, msg); +} + +void p3Msgs::getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox) +{ + mMsgSrv->getMessageCount(pnInbox, pnInboxNew, pnOutbox, pnDraftbox, pnSentbox, pnTrashbox); +} + +/****************************************/ +/****************************************/ + /* Message Items */ +bool p3Msgs::MessageSend(MessageInfo &info) +{ + return mMsgSrv->MessageSend(info); +} + +bool p3Msgs::MessageToDraft(MessageInfo &info, const std::string &msgParentId) +{ + return mMsgSrv->MessageToDraft(info, msgParentId); +} + +bool p3Msgs::MessageToTrash(const std::string &mid, bool bTrash) +{ + return mMsgSrv->MessageToTrash(mid, bTrash); +} + +bool p3Msgs::getMsgParentId(const std::string &msgId, std::string &msgParentId) +{ + return mMsgSrv->getMsgParentId(msgId, msgParentId); +} + +/****************************************/ +/****************************************/ +bool p3Msgs::MessageDelete(const std::string &mid) +{ + //std::cerr << "p3Msgs::MessageDelete() "; + //std::cerr << "mid: " << mid << std::endl; + + return mMsgSrv -> removeMsgId(mid); +} + +bool p3Msgs::MessageRead(const std::string &mid, bool unreadByUser) +{ + //std::cerr << "p3Msgs::MessageRead() "; + //std::cerr << "mid: " << mid << std::endl; + + return mMsgSrv -> markMsgIdRead(mid, unreadByUser); +} + +bool p3Msgs::MessageReplied(const std::string &mid, bool replied) +{ + return mMsgSrv->setMsgFlag(mid, replied ? RS_MSG_FLAGS_REPLIED : 0, RS_MSG_FLAGS_REPLIED); +} + +bool p3Msgs::MessageForwarded(const std::string &mid, bool forwarded) +{ + return mMsgSrv->setMsgFlag(mid, forwarded ? RS_MSG_FLAGS_FORWARDED : 0, RS_MSG_FLAGS_FORWARDED); +} + +bool p3Msgs::getMessageTagTypes(MsgTagType& tags) +{ + return mMsgSrv->getMessageTagTypes(tags); +} + +bool p3Msgs::MessageStar(const std::string &mid, bool star) + +{ + return mMsgSrv->setMsgFlag(mid, star ? RS_MSG_FLAGS_STAR : 0, RS_MSG_FLAGS_STAR); +} + +bool p3Msgs::setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color) +{ + return mMsgSrv->setMessageTagType(tagId, text, rgb_color); +} + +bool p3Msgs::removeMessageTagType(uint32_t tagId) +{ + return mMsgSrv->removeMessageTagType(tagId); +} + +bool p3Msgs::getMessageTag(const std::string &msgId, MsgTagInfo& info) +{ + return mMsgSrv->getMessageTag(msgId, info); +} + +bool p3Msgs::setMessageTag(const std::string &msgId, uint32_t tagId, bool set) +{ + return mMsgSrv->setMessageTag(msgId, tagId, set); +} + +bool p3Msgs::resetMessageStandardTagTypes(MsgTagType& tags) +{ + return mMsgSrv->resetMessageStandardTagTypes(tags); +} + +/****************************************/ +/****************************************/ +bool p3Msgs::sendPublicChat(std::wstring msg) +{ + /* send a message to all for now */ + return mChatSrv -> sendPublicChat(msg); +} + +bool p3Msgs::sendPrivateChat(std::string id, std::wstring msg) +{ + /* send a message to peer */ + return mChatSrv -> sendPrivateChat(id, msg); +} + +void p3Msgs::sendGroupChatStatusString(const std::string& status_string) +{ + mChatSrv->sendGroupChatStatusString(status_string); +} +void p3Msgs::sendStatusString(const std::string& peer_id,const std::string& status_string) +{ + mChatSrv->sendStatusString(peer_id,status_string); +} + +int p3Msgs::getPublicChatQueueCount() +{ + return mChatSrv->getPublicChatQueueCount(); +} + +bool p3Msgs::getPublicChatQueue(std::list &chats) +{ + return mChatSrv->getPublicChatQueue(chats); +} + +int p3Msgs::getPrivateChatQueueCount(bool incoming) +{ + return mChatSrv->getPrivateChatQueueCount(incoming); +} + +bool p3Msgs::getPrivateChatQueueIds(bool incoming, std::list &ids) +{ + return mChatSrv->getPrivateChatQueueIds(incoming, ids); +} + +bool p3Msgs::getPrivateChatQueue(bool incoming, std::string id, std::list &chats) +{ + return mChatSrv->getPrivateChatQueue(incoming, id, chats); +} + +bool p3Msgs::clearPrivateChatQueue(bool incoming, std::string id) +{ + return mChatSrv->clearPrivateChatQueue(incoming, id); +} + +void p3Msgs::getOwnAvatarData(unsigned char *& data,int& size) +{ + mChatSrv->getOwnAvatarJpegData(data,size) ; +} + +void p3Msgs::setOwnAvatarData(const unsigned char *data,int size) +{ + mChatSrv->setOwnAvatarJpegData(data,size) ; +} + +void p3Msgs::getAvatarData(std::string pid,unsigned char *& data,int& size) +{ + mChatSrv->getAvatarJpegData(pid,data,size) ; +} + +std::string p3Msgs::getCustomStateString(const std::string& peer_id) +{ + return mChatSrv->getCustomStateString(peer_id) ; +} + +std::string p3Msgs::getCustomStateString() +{ + return mChatSrv->getOwnCustomStateString() ; +} + +void p3Msgs::setCustomStateString(const std::string& state_string) +{ + mChatSrv->setOwnCustomStateString(state_string) ; +} + diff --git a/libretroshare/src/rsserver/p3msgs.h b/libretroshare/src/rsserver/p3msgs.h new file mode 100644 index 000000000..9440de2c5 --- /dev/null +++ b/libretroshare/src/rsserver/p3msgs.h @@ -0,0 +1,178 @@ +#ifndef RS_P3MSG_INTERFACE_H +#define RS_P3MSG_INTERFACE_H + +/* + * libretroshare/src/rsserver: p3msgs.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rsmsgs.h" + +class p3MsgService; +class p3ChatService; + +class RsChatMsgItem; + +//! provides retroshares chatservice and messaging service +/*! + * Provides rs with the ability to send/receive messages, immediate status, + * custom status, avatar and + * chats (public(group) and private) to peers + */ +class p3Msgs: public RsMsgs +{ + public: + + p3Msgs(p3MsgService *p3m, p3ChatService *p3c) + :mMsgSrv(p3m), mChatSrv(p3c) { return; } + virtual ~p3Msgs() { return; } + + /****************************************/ + /* Message Items */ + + /*! + * @param msgList ref to list summarising client's msgs + */ + virtual bool getMessageSummaries(std::list &msgList); + virtual bool getMessage(const std::string &mId, MessageInfo &msg); + virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox); + + virtual bool MessageSend(MessageInfo &info); + virtual bool MessageToDraft(MessageInfo &info, const std::string &msgParentId); + virtual bool MessageToTrash(const std::string &mid, bool bTrash); + virtual bool MessageDelete(const std::string &mid); + virtual bool MessageRead(const std::string &mid, bool unreadByUser); + virtual bool MessageReplied(const std::string &mid, bool replied); + virtual bool MessageForwarded(const std::string &mid, bool forwarded); + virtual bool MessageStar(const std::string &mid, bool star); + virtual bool getMsgParentId(const std::string &msgId, std::string &msgParentId); + + virtual bool getMessageTagTypes(MsgTagType& tags); + virtual bool setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color); + virtual bool removeMessageTagType(uint32_t tagId); + + virtual bool getMessageTag(const std::string &msgId, MsgTagInfo& info); + /* set == false && tagId == 0 --> remove all */ + virtual bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set); + + virtual bool resetMessageStandardTagTypes(MsgTagType& tags); + + /*! + * gets avatar from peer, image data in jpeg format + */ + virtual void getAvatarData(std::string pid,unsigned char *& data,int& size); + + /*! + * sets clients avatar, image data should be in jpeg format + */ + virtual void setOwnAvatarData(const unsigned char *data,int size); + + /*! + * retrieve clients avatar, image data in jpeg format + */ + virtual void getOwnAvatarData(unsigned char *& data,int& size); + + /*! + * sets clients custom status (e.g. "i'm tired") + */ + virtual void setCustomStateString(const std::string& status_string) ; + + /*! + * retrieves client's custom status + */ + virtual std::string getCustomStateString() ; + + /*! + * retrieves peer's custom status + */ + virtual std::string getCustomStateString(const std::string& peer_id) ; + + + /*! + * public chat sent to all peers + */ + virtual bool sendPublicChat(std::wstring msg); + + /*! + * chat is sent to specifc peer + * @param id peer to send chat msg to + */ + virtual bool sendPrivateChat(std::string id, std::wstring msg); + + /*! + * returns the count of messages in public or private queue + * @param public or private queue + */ + virtual int getPublicChatQueueCount(); + + /*! + * @param chats ref to list of received public chats is stored here + */ + virtual bool getPublicChatQueue(std::list &chats); + + /*! + * returns the count of messages in private queue + * @param public or private queue + */ + virtual int getPrivateChatQueueCount(bool incoming); + + /*! + * @param id's of available private chat messages + */ + virtual bool getPrivateChatQueueIds(bool incoming, std::list &ids); + + + /*! + * @param chats ref to list of received private chats is stored here + */ + virtual bool getPrivateChatQueue(bool incoming, std::string id, std::list &chats); + + /*! + * @param clear private chat queue + */ + virtual bool clearPrivateChatQueue(bool incoming, std::string id); + + /*! + * sends immediate status string to a specific peer, e.g. in a private chat + * @param peer_id peer to send status string to + * @param status_string immediate status to send + */ + virtual void sendStatusString(const std::string& peer_id,const std::string& status_string) ; + + /*! + * sends immediate status to all peers + * @param status_string immediate status to send + */ + virtual void sendGroupChatStatusString(const std::string& status_string) ; + + /****************************************/ + + + private: + + p3MsgService *mMsgSrv; + p3ChatService *mChatSrv; +}; + + +#endif diff --git a/libretroshare/src/rsserver/p3peers.cc b/libretroshare/src/rsserver/p3peers.cc new file mode 100644 index 000000000..16b3c3b98 --- /dev/null +++ b/libretroshare/src/rsserver/p3peers.cc @@ -0,0 +1,1368 @@ +/* + * libretroshare/src/rsserver: p3peers.cc + * + * RetroShare C++ Interface. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rsserver/p3peers.h" +#include "rsserver/p3face.h" +#include "pqi/p3connmgr.h" +#include "pqi/authssl.h" +#include "pqi/authgpg.h" +#include "retroshare/rsinit.h" +#include "pqi/cleanupxpgp.h" + + +#include +#include +#include + +#include + +const std::string CERT_SSL_ID = "--SSLID--"; +const std::string CERT_LOCATION = "--LOCATION--"; +const std::string CERT_LOCAL_IP = "--LOCAL--"; +const std::string CERT_EXT_IP = "--EXT--"; +const std::string CERT_DYNDNS = "--DYNDNS--"; + +static const int MAX_TIME_KEEP_LOCATION_WITHOUT_CONTACT = 30*24*3600 ; // 30 days. + + +#include "pqi/authssl.h" + + +RsPeers *rsPeers = NULL; + +/******* + * #define P3PEERS_DEBUG 1 + *******/ + +int ensureExtension(std::string &name, std::string def_ext); + +std::string RsPeerTrustString(uint32_t trustLvl) +{ + + std::string str; + + switch(trustLvl) + { + default: + case GPGME_VALIDITY_UNKNOWN: + str = "GPGME_VALIDITY_UNKNOWN"; + break; + case GPGME_VALIDITY_UNDEFINED: + str = "GPGME_VALIDITY_UNDEFINED"; + break; + case GPGME_VALIDITY_NEVER: + str = "GPGME_VALIDITY_NEVER"; + break; + case GPGME_VALIDITY_MARGINAL: + str = "GPGME_VALIDITY_MARGINAL"; + break; + case GPGME_VALIDITY_FULL: + str = "GPGME_VALIDITY_FULL"; + break; + case GPGME_VALIDITY_ULTIMATE: + str = "GPGME_VALIDITY_ULTIMATE"; + break; + } + return str; +} + +std::string RsPeerNetModeString(uint32_t netModel) +{ + std::string str; + if (netModel == RS_NETMODE_EXT) + { + str = "External Port"; + } + else if (netModel == RS_NETMODE_UPNP) + { + str = "Ext (UPnP)"; + } + else if (netModel == RS_NETMODE_UDP) + { + str = "UDP Mode"; + } + else if (netModel == RS_NETMODE_UNREACHABLE) + { + str = "UDP Mode (Unreachable)"; + } + else + { + str = "Unknown NetMode"; + } + return str; +} + + +std::string RsPeerLastConnectString(uint32_t lastConnect) +{ + std::ostringstream out; + out << lastConnect << " secs ago"; + return out.str(); +} + + +p3Peers::p3Peers(p3ConnectMgr *cm) + :mConnMgr(cm) +{ + return; +} + + /* Updates ... */ +bool p3Peers::FriendsChanged() +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::FriendsChanged()" << std::endl; +#endif + + /* TODO */ + return false; +} + +bool p3Peers::OthersChanged() +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::OthersChanged()" << std::endl; +#endif + + /* TODO */ + return false; +} + + /* Peer Details (Net & Auth) */ +std::string p3Peers::getOwnId() +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getOwnId()" << std::endl; +#endif + + return AuthSSL::getAuthSSL()->OwnId(); +} + +bool p3Peers::getOnlineList(std::list &ids) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getOnlineList()" << std::endl; +#endif + + /* get from mConnectMgr */ + mConnMgr->getOnlineList(ids); + return true; +} + +bool p3Peers::getFriendList(std::list &ids) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getFriendList()" << std::endl; +#endif + + /* get from mConnectMgr */ + mConnMgr->getFriendList(ids); + return true; +} + +//bool p3Peers::getOthersList(std::list &ids) +//{ +//#ifdef P3PEERS_DEBUG +// std::cerr << "p3Peers::getOthersList()"; +// std::cerr << std::endl; +//#endif +// +// /* get from mAuthMgr */ +// AuthSSL::getAuthSSL()->getAllList(ids); +// return true; +//} + +bool p3Peers::getPeerCount (unsigned int *pnFriendCount, unsigned int *pnOnlineCount, bool ssl) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPeerCount()" << std::endl; +#endif + + /* get from mConnectMgr */ + return mConnMgr->getPeerCount(pnFriendCount, pnOnlineCount, ssl); +} + +bool p3Peers::isOnline(const std::string &id) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::isOnline() " << id << std::endl; +#endif + + /* get from mConnectMgr */ + peerConnectState state; + if (mConnMgr->getFriendNetStatus(id, state) && + (state.state & RS_PEER_S_CONNECTED)) + { + return true; + } + return false; +} + +bool p3Peers::isFriend(const std::string &ssl_id) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::isFriend() " << ssl_id << std::endl; +#endif + + /* get from mConnectMgr */ + return mConnMgr->isFriend(ssl_id); +} + +#if 0 +static struct sockaddr_in getPreferredAddress( const struct sockaddr_in& addr1,time_t ts1, + const struct sockaddr_in& addr2,time_t ts2, + const struct sockaddr_in& addr3,time_t ts3) +{ + time_t ts = ts1 ; + struct sockaddr_in addr = addr1 ; + + if(ts2 > ts && strcmp(rs_inet_ntoa(addr2.sin_addr),"0.0.0.0")) { ts = ts2 ; addr = addr2 ; } + if(ts3 > ts && strcmp(rs_inet_ntoa(addr3.sin_addr),"0.0.0.0")) { ts = ts3 ; addr = addr3 ; } + + return addr ; +} +#endif + +bool p3Peers::getPeerDetails(const std::string &id, RsPeerDetails &d) +{ + #ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPeerDetails() called for id : " << id << std::endl; + #endif + //first, check if it's a gpg or a ssl id. + std::string sOwnId = AuthSSL::getAuthSSL()->OwnId(); + peerConnectState pcs; + if (id != sOwnId && !mConnMgr->getFriendNetStatus(id, pcs)) { + //assume is not SSL, because every ssl_id has got a friend correspondance in mConnMgr + #ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPeerDetails() got a gpg id and is returning GPG details only for id : " << id << std::endl; + #endif + d.isOnlyGPGdetail = true; + return this->getGPGDetails(id, d); + } + #ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPeerDetails() got a SSL id and is returning SSL and GPG details for id : " << id << std::endl; + #endif + + if (id == sOwnId) { + mConnMgr->getOwnNetStatus(pcs); + pcs.gpg_id = AuthGPG::getAuthGPG()->getGPGOwnId(); + } + + /* get from gpg (first), to fill in the sign and trust details */ + /* don't retrun now, we've got fill in the ssl and connection info */ + this->getGPGDetails(pcs.gpg_id, d); + d.isOnlyGPGdetail = false; + + //get the ssl details + d.id = id; + d.location = pcs.location; + + /* generate */ + d.authcode = "AUTHCODE"; + + /* fill from pcs */ + + d.localAddr = rs_inet_ntoa(pcs.currentlocaladdr.sin_addr); + d.localPort = ntohs(pcs.currentlocaladdr.sin_port); + d.extAddr = rs_inet_ntoa(pcs.currentserveraddr.sin_addr); + d.extPort = ntohs(pcs.currentserveraddr.sin_port); + d.dyndns = pcs.dyndns; + d.lastConnect = pcs.lastcontact; + d.connectPeriod = 0; + + + std::list::iterator it; + for(it = pcs.ipAddrs.mLocal.mAddrs.begin(); + it != pcs.ipAddrs.mLocal.mAddrs.end(); it++) + { + std::ostringstream toto; + toto << ntohs(it->mAddr.sin_port) << " " << (time(NULL) - it->mSeenTime) << " sec"; + d.ipAddressList.push_back("L:" + std::string(rs_inet_ntoa(it->mAddr.sin_addr)) + ":" + toto.str()); + } + for(it = pcs.ipAddrs.mExt.mAddrs.begin(); + it != pcs.ipAddrs.mExt.mAddrs.end(); it++) + { + std::ostringstream toto; + toto << ntohs(it->mAddr.sin_port) << " " << (time(NULL) - it->mSeenTime) << " sec"; + d.ipAddressList.push_back("E:" + std::string(rs_inet_ntoa(it->mAddr.sin_addr)) + ":" + toto.str()); + } + + /* Translate */ + + d.state = 0; + if (pcs.state & RS_PEER_S_FRIEND) + d.state |= RS_PEER_STATE_FRIEND; + if (pcs.state & RS_PEER_S_ONLINE) + d.state |= RS_PEER_STATE_ONLINE; + if (pcs.state & RS_PEER_S_CONNECTED) + d.state |= RS_PEER_STATE_CONNECTED; + if (pcs.state & RS_PEER_S_UNREACHABLE) + d.state |= RS_PEER_STATE_UNREACHABLE; + + switch(pcs.netMode & RS_NET_MODE_ACTUAL) + { + case RS_NET_MODE_EXT: + d.netMode = RS_NETMODE_EXT; + break; + case RS_NET_MODE_UPNP: + d.netMode = RS_NETMODE_UPNP; + break; + case RS_NET_MODE_UDP: + d.netMode = RS_NETMODE_UDP; + break; + case RS_NET_MODE_UNREACHABLE: + case RS_NET_MODE_UNKNOWN: + default: + d.netMode = RS_NETMODE_UNREACHABLE; + break; + } + + if (pcs.netMode & RS_NET_MODE_TRY_EXT) + { + d.tryNetMode = RS_NETMODE_EXT; + } + else if (pcs.netMode & RS_NET_MODE_TRY_UPNP) + { + d.tryNetMode = RS_NETMODE_UPNP; + } + else + { + d.tryNetMode = RS_NETMODE_UDP; + } + + d.visState = 0; + if (!(pcs.visState & RS_VIS_STATE_NODISC)) + { + d.visState |= RS_VS_DISC_ON; + } + + if (!(pcs.visState & RS_VIS_STATE_NODHT)) + { + d.visState |= RS_VS_DHT_ON; + } + + + /* Finally determine AutoConnect Status */ + d.foundDHT = pcs.dht.found; + + d.connectState = 0; + d.connectStateString.clear(); + + + if (pcs.inConnAttempt) + { + if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_TUNNEL) { + d.connectState = RS_PEER_CONNECTSTATE_TRYING_TUNNEL; + } else if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_TCP_ALL) { + d.connectState = RS_PEER_CONNECTSTATE_TRYING_TCP; + + std::ostringstream str; + str << rs_inet_ntoa(pcs.currentConnAddrAttempt.addr.sin_addr) << ":" << ntohs(pcs.currentConnAddrAttempt.addr.sin_port); + d.connectStateString = str.str(); + } else if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_UDP_ALL) { + d.connectState = RS_PEER_CONNECTSTATE_TRYING_UDP; + + std::ostringstream str; + str << rs_inet_ntoa(pcs.currentConnAddrAttempt.addr.sin_addr) << ":" << ntohs(pcs.currentConnAddrAttempt.addr.sin_port); + d.connectStateString = str.str(); + } + } + else if (pcs.state & RS_PEER_S_CONNECTED) + { + if (pcs.connecttype == RS_NET_CONN_TCP_ALL) + { + d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TCP; + } + else if (pcs.connecttype == RS_NET_CONN_UDP_ALL) + { + d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UDP; + } + else if (pcs.connecttype == RS_NET_CONN_TUNNEL) + { + d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TUNNEL; + } + else + { + d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN; + } + } + + return true; +} + + +std::string p3Peers::getGPGName(const std::string &gpg_id) +{ + /* get from mAuthMgr as it should have more peers? */ + return AuthGPG::getAuthGPG()->getGPGName(gpg_id); +} + +bool p3Peers::isGPGAccepted(const std::string &gpg_id_is_friend) +{ + /* get from mAuthMgr as it should have more peers? */ + return AuthGPG::getAuthGPG()->isGPGAccepted(gpg_id_is_friend); +} + +std::string p3Peers::getPeerName(const std::string &ssl_or_gpg_id) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPeerName() " << ssl_or_gpg_id << std::endl; +#endif + std::string name; + if (ssl_or_gpg_id == AuthSSL::getAuthSSL()->OwnId()) { + return AuthGPG::getAuthGPG()->getGPGOwnName(); + } + peerConnectState pcs; + if (mConnMgr->getFriendNetStatus(ssl_or_gpg_id, pcs)) { + #ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPeerName() got a ssl id. Name is : " << pcs.name << std::endl; + #endif + return pcs.name; + } + + return AuthGPG::getAuthGPG()->getGPGName(ssl_or_gpg_id); +} + +bool p3Peers::getGPGAllList(std::list &ids) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getGPGAllList()" << std::endl; +#endif + + /* get from mAuthMgr */ + AuthGPG::getAuthGPG()->getGPGAllList(ids); + return true; +} + +bool p3Peers::getGPGValidList(std::list &ids) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPGPOthersList()" << std::endl; +#endif + + /* get from mAuthMgr */ + AuthGPG::getAuthGPG()->getGPGValidList(ids); + return true; +} + +bool p3Peers::getGPGSignedList(std::list &ids) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPGPOthersList()" << std::endl; +#endif + + /* get from mAuthMgr */ + AuthGPG::getAuthGPG()->getGPGSignedList(ids); + return true; +} + +bool p3Peers::getGPGAcceptedList(std::list &ids) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getGPGAcceptedList()" << std::endl; +#endif + AuthGPG::getAuthGPG()->getGPGAcceptedList(ids); + return true; +} + +bool p3Peers::getSSLChildListOfGPGId(const std::string &gpg_id, std::list &ids) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getSSLChildListOfGPGId() for id : " << gpg_id << std::endl; +#endif + ids.clear(); + if (gpg_id == "" ) { + return false; + } + //let's roll throush the friends + std::list friendsIds; + mConnMgr->getFriendList(friendsIds); + peerConnectState pcs; + for (std::list::iterator it = friendsIds.begin(); it != friendsIds.end(); it++) + { +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getSSLChildListOfGPGId() iterating over friends id : " << *it << std::endl; +#endif + if (mConnMgr->getFriendNetStatus(*it, pcs) && pcs.gpg_id == gpg_id) { +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getSSLChildListOfGPGId() adding ssl id : " << pcs.id << std::endl; +#endif + ids.push_back(pcs.id); + } + } + return true; +} + +bool p3Peers::cleanUnusedLocations() +{ + // Obtain all current locations of each GPG friend. + // + std::map > friends_info ; + std::list friendSSLIds ; + + mConnMgr->getFriendList(friendSSLIds); + + for(std::list::const_iterator it(friendSSLIds.begin());it!=friendSSLIds.end();++it) + { + peerConnectState pcs; + + if(mConnMgr->getFriendNetStatus(*it, pcs)) + friends_info[pcs.gpg_id].push_back(pcs) ; + } + + // Now sort them out + // + + std::cerr << "Examining Old/Unused locations." << std::endl ; + time_t now = time(NULL) ; + + std::list locations_to_remove ; + + for(std::map >::iterator it(friends_info.begin());it!=friends_info.end();++it) + { + std::list& locations_list(it->second) ; + + int size = locations_list.size() ; + + std::cerr << " GPG id: " << it->first << std::endl ; + + for(std::list::const_iterator itloc(locations_list.begin());itloc!=locations_list.end();++itloc) + std::cerr << " Location " << (*itloc).id << ", last contact " << now - (*itloc).lastcontact << " seconds ago" << std::endl ; + + // Remove any location that is dummy. Update the list, such that we only look into non dummy friends later. + // + for(std::list::iterator itloc(locations_list.begin());itloc!=locations_list.end();) + if(size > 1 && isDummyFriend((*itloc).id)) + { + locations_to_remove.push_back((*itloc).id) ; + --size ; + + std::cerr << " Removing dummy location: " << (*itloc).id << std::endl ; + + std::list::iterator tmp(itloc) ; + ++tmp ; + locations_list.erase(itloc) ; + itloc=tmp ; + } + else + ++itloc ; + + for(std::list::const_iterator itloc(locations_list.begin());itloc!=locations_list.end();++itloc) + if(size > 1 && now > (*itloc).lastcontact + MAX_TIME_KEEP_LOCATION_WITHOUT_CONTACT) + { + locations_to_remove.push_back((*itloc).id) ; + --size ; + std::cerr << " Removing unused location: " << (*itloc).id << std::endl ; + } + } + + std::cerr << "Now removing unused locations:" << std::endl ; + + for(std::list::const_iterator it(locations_to_remove.begin());it!=locations_to_remove.end();++it) + { + std::cerr << " Removing unused friend location " << *it << std::endl ; + removeFriend(*it) ; + } + + return true ; +} + +bool p3Peers::getGPGDetails(const std::string &id, RsPeerDetails &d) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPgpDetails() called for id : " << id << std::endl; +#endif + + /* get from mAuthMgr */ + return AuthGPG::getAuthGPG()->getGPGDetails(id, d); +} + +std::string p3Peers::getGPGOwnId() +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPGPOwnId()" << std::endl; +#endif + + /* get from mAuthMgr */ + return AuthGPG::getAuthGPG()->getGPGOwnId(); +} + +std::string p3Peers::getGPGId(const std::string &sslid_or_gpgid) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPGPId()" << std::endl; +#endif + + /* get from mAuthMgr */ + if (sslid_or_gpgid == AuthSSL::getAuthSSL()->OwnId()) { + return AuthGPG::getAuthGPG()->getGPGOwnId(); + } + peerConnectState pcs; + if (mConnMgr->getFriendNetStatus(sslid_or_gpgid, pcs) || mConnMgr->getOthersNetStatus(sslid_or_gpgid, pcs)) { + return pcs.gpg_id; + } else { + if ( AuthGPG::getAuthGPG()->isGPGId(sslid_or_gpgid)) { + #ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getPGPId() given id is already an gpg id : " << sslid_or_gpgid << std::endl; + #endif + return sslid_or_gpgid; + } + } + return ""; +} + + + + /* Add/Remove Friends */ +bool p3Peers::addFriend(const std::string &id, const std::string &gpg_id) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::addFriend() with : id : " << id << "; gpg_id : " << gpg_id << std::endl; +#endif + if (id == gpg_id || id == "") { + return addDummyFriend(gpg_id); + } else { + return mConnMgr->addFriend(id, gpg_id); + } +} + +bool p3Peers::addDummyFriend(const std::string &gpg_id) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::addDummyFriend() called" << std::endl; +#endif + std::string dummy_ssl_id = "dummy"+ gpg_id; + //check if this gpg_id already got a dummy friend + if (!mConnMgr->isFriend(dummy_ssl_id)) { + return mConnMgr->addFriend(dummy_ssl_id, gpg_id); + } else { +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::addDummyFriend() dummy friend already exists for gpg_id : " << gpg_id << std::endl; +#endif + return false; + } +} + +bool p3Peers::isDummyFriend(const std::string &ssl_id) { +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::isDummyFriend() called" << std::endl; +#endif + RsPeerDetails details; + bool ret = false; + if (getPeerDetails(ssl_id, details)) { + ret = (details.id == ("dummy" + details.gpg_id)); + } else { + ret = (ssl_id.substr(0,5) == "dummy"); + } +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::isDummyFriend() return : " << ret << std::endl; +#endif + return ret; + } + +bool p3Peers::removeFriend(const std::string &ssl_or_gpgid) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::removeFriend() " << ssl_or_gpgid << std::endl; +#endif + if (ssl_or_gpgid == AuthGPG::getAuthGPG()->getGPGOwnId()) { +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::removeFriend() fail : we're not going to remove our own GPG id." << std::endl; +#endif + return false; + } + //will remove if it's a gpg id + AuthGPG::getAuthGPG()->setAcceptToConnectGPGCertificate(ssl_or_gpgid, false); + + //will remove if it's a ssl id + mConnMgr->removeFriend(ssl_or_gpgid); + return true; + +} + + /* Network Stuff */ +bool p3Peers::connectAttempt(const std::string &id) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::connectAttempt() " << id << std::endl; +#endif + + return mConnMgr->retryConnect(id); +} + +void p3Peers::getIPServersList(std::list& ip_servers) +{ + mConnMgr->getIPServersList(ip_servers) ; +} +void p3Peers::allowServerIPDetermination(bool b) +{ + mConnMgr->setIPServersEnabled(b) ; +} + +void p3Peers::allowTunnelConnection(bool b) +{ + #ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::allowTunnelConnection() set tunnel to : " << b << std::endl; + #endif + mConnMgr->setTunnelConnection(b) ; +} + +bool p3Peers::getAllowServerIPDetermination() +{ + return mConnMgr->getIPServersEnabled() ; +} + +bool p3Peers::getAllowTunnelConnection() +{ + #ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getAllowTunnelConnection() tunnel is : " << mConnMgr->getTunnelConnection() << std::endl; + #endif + return mConnMgr->getTunnelConnection() ; +} + +bool p3Peers::setLocalAddress(const std::string &id, const std::string &addr_str, uint16_t port) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::setLocalAddress() " << id << std::endl; +#endif + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + int ret = 1; +/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ +#ifndef WINDOWS_SYS + if (ret && (0 != inet_aton(addr_str.c_str(), &(addr.sin_addr)))) +#else + addr.sin_addr.s_addr = inet_addr(addr_str.c_str()); + if (ret) +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ + { + return mConnMgr->setLocalAddress(id, addr); + } + return false; +} + +bool p3Peers::setLocation(const std::string &ssl_id, const std::string &location) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::setLocation() " << ssl_id << std::endl; +#endif + + return mConnMgr->setLocation(ssl_id, location); +} +bool p3Peers::setExtAddress(const std::string &id, const std::string &addr_str, uint16_t port) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::setExtAddress() " << id << std::endl; +#endif + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + int ret = 1; +/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ +#ifndef WINDOWS_SYS + if (ret && (0 != inet_aton(addr_str.c_str(), &(addr.sin_addr)))) +#else + addr.sin_addr.s_addr = inet_addr(addr_str.c_str()); + if (ret) +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART *******************/ + { + return mConnMgr->setExtAddress(id, addr); + } + return false; +} + +bool p3Peers::setDynDNS(const std::string &id, const std::string &dyndns) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::setDynDNS() called with id: " << id << " dyndns: " << dyndns <setDynDNS(id, dyndns); +} + +bool p3Peers::setNetworkMode(const std::string &id, uint32_t extNetMode) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::setNetworkMode() " << id << std::endl; +#endif + + /* translate */ + uint32_t netMode = 0; + switch(extNetMode) + { + case RS_NETMODE_EXT: + netMode = RS_NET_MODE_EXT; + break; + case RS_NETMODE_UPNP: + netMode = RS_NET_MODE_UPNP; + break; + case RS_NETMODE_UDP: + netMode = RS_NET_MODE_UDP; + break; + case RS_NETMODE_UNREACHABLE: + netMode = RS_NET_MODE_UNREACHABLE; + break; + default: + break; + } + + return mConnMgr->setNetworkMode(id, netMode); +} + + +bool +p3Peers::setVisState(const std::string &id, uint32_t extVisState) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::setVisState() " << id << std::endl; +#endif + std::cerr << "p3Peers::setVisState() " << id << " " << extVisState << std::endl; + + uint32_t visState = 0; + if (!(extVisState & RS_VS_DHT_ON)) + visState |= RS_VIS_STATE_NODHT; + if (!(extVisState & RS_VS_DISC_ON)) + visState |= RS_VIS_STATE_NODISC; + + return mConnMgr->setVisState(id, visState); +} + +//=========================================================================== + /* Auth Stuff */ +std::string +p3Peers::GetRetroshareInvite() +{ + return GetRetroshareInvite(getOwnId()); +} + +std::string +p3Peers::GetRetroshareInvite(const std::string& ssl_id) +{ + #ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::GetRetroshareInvite()" << std::endl; + #endif + + //add the sslid, location, ip local and external address after the signature + RsPeerDetails Detail; + std::string invite ; + + if (getPeerDetails(ssl_id, Detail)) + { + invite = AuthGPG::getAuthGPG()->SaveCertificateToString(Detail.gpg_id); + + if(!Detail.isOnlyGPGdetail) + { + invite += CERT_SSL_ID + Detail.id + ";"; + invite += CERT_LOCATION + Detail.location + ";\n"; + invite += CERT_LOCAL_IP + Detail.localAddr + ":"; + std::ostringstream out; + out << Detail.localPort; + invite += out.str() + ";"; + invite += CERT_EXT_IP + Detail.extAddr + ":"; + std::ostringstream out2; + out2 << Detail.extPort; + invite += out2.str() + ";"; + if (!Detail.dyndns.empty()) { + invite += "\n" + CERT_DYNDNS + Detail.dyndns + ";"; + } + } + } + + #ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::GetRetroshareInvite() returns : \n" << invite << std::endl; + #endif + return invite; +} + +//=========================================================================== + +bool p3Peers::loadCertificateFromFile(const std::string &fname, std::string &id, std::string &gpg_id) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::LoadCertificateFromFile() not implemented yet"; + std::cerr << std::endl; +#endif + + return false; +} + + +//bool splitCerts(std::string in, std::string &sslcert, std::string &pgpcert) +//{ +// std::cerr << "splitCerts():" << in; +// std::cerr << std::endl; +// +// /* search for -----END CERTIFICATE----- */ +// std::string sslend("-----END CERTIFICATE-----"); +// std::string pgpend("-----END PGP PUBLIC KEY BLOCK-----"); +// size_t pos = in.find(sslend); +// size_t pos2 = in.find(pgpend); +// size_t ssllen, pgplen; +// +// if (pos != std::string::npos) +// { +// std::cerr << "splitCerts(): Found SSL Cert"; +// std::cerr << std::endl; +// +// ssllen = pos + sslend.length(); +// sslcert = in.substr(0, ssllen); +// +// if (pos2 != std::string::npos) +// { +// std::cerr << "splitCerts(): Found SSL + PGP Cert"; +// std::cerr << std::endl; +// +// pgplen = pos2 + pgpend.length() - ssllen; +// pgpcert = in.substr(ssllen, pgplen); +// } +// return true; +// } +// else if (pos2 != std::string::npos) +// { +// std::cerr << "splitCerts(): Found PGP Cert Only"; +// std::cerr << std::endl; +// +// pgplen = pos2 + pgpend.length(); +// pgpcert = in.substr(0, pgplen); +// return true; +// } +// return false; +//} + +static bool splitCert(const std::string &certstr, std::string &cert, std::string &peerInfo) +{ + cert.erase(); + peerInfo.erase(); + + /* search for -----END CERTIFICATE----- */ + std::string pgpend("-----END PGP PUBLIC KEY BLOCK-----"); + + size_t pos = certstr.find(pgpend); + + if (pos != std::string::npos) { + pos += pgpend.length(); + cert = certstr.substr(0, pos); + peerInfo = certstr.substr(pos + 1); + } + + return !cert.empty(); +} + +bool p3Peers::loadDetailsFromStringCert(const std::string &certstr, RsPeerDetails &pd,std::string& error_string) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::LoadCertificateFromString() "; + std::cerr << std::endl; +#endif + + //parse the text to get ip address + try { + + std::string cert; + std::string peerInfo; + + if (splitCert(certstr, cert, peerInfo)) { + std::string gpg_id; + AuthGPG::getAuthGPG()->LoadCertificateFromString(cert, gpg_id,error_string); + AuthGPG::getAuthGPG()->getGPGDetails(gpg_id, pd); + if (gpg_id.empty()) { + return false; + } + } else { + return false; + } + + #ifdef P3PEERS_DEBUG + std::cerr << "Parsing cert for sslid, location, ext and local address details. : " << certstr << std::endl; + #endif + + //let's parse the ssl id + size_t parsePosition = peerInfo.find(CERT_SSL_ID); + std::cerr << "sslid position : " << parsePosition << std::endl; + if (parsePosition != std::string::npos) { + parsePosition += CERT_SSL_ID.length(); + std::string subCert = peerInfo.substr(parsePosition); + parsePosition = subCert.find(";"); + if (parsePosition != std::string::npos) { + std::string ssl_id = subCert.substr(0, parsePosition); + std::cerr << "SSL id : " << ssl_id << std::endl; + pd.id = ssl_id; + pd.isOnlyGPGdetail = false; + } + } + + //let's parse the location + parsePosition = peerInfo.find(CERT_LOCATION); + std::cerr << "location position : " << parsePosition << std::endl; + if (parsePosition != std::string::npos) { + parsePosition += CERT_LOCATION.length(); + std::string subCert = peerInfo.substr(parsePosition); + parsePosition = subCert.find(";"); + if (parsePosition != std::string::npos) { + std::string location = subCert.substr(0, parsePosition); + std::cerr << "location : " << location << std::endl; + pd.location = location; + } + } + + //let's parse ip local address + parsePosition = peerInfo.find(CERT_LOCAL_IP); + std::cerr << "local ip position : " << parsePosition << std::endl; + if (parsePosition != std::string::npos) { + parsePosition += CERT_LOCAL_IP.length(); + std::string subCert = peerInfo.substr(parsePosition); + parsePosition = subCert.find(":"); + if (parsePosition != std::string::npos) { + std::string local_ip = subCert.substr(0, parsePosition); + std::cerr << "Local Ip : " << local_ip << std::endl; + pd.localAddr = local_ip; + + //let's parse local port + subCert = subCert.substr(parsePosition + 1); + parsePosition = subCert.find(";"); + if (parsePosition != std::string::npos) { + std::string local_port = subCert.substr(0, parsePosition); + std::cerr << "Local port : " << local_port << std::endl; + std::istringstream instream(local_port); + uint16_t local_port_int; + instream >> local_port_int; + pd.localPort = (local_port_int); + } + } + } + + //let's parse ip ext address + parsePosition = peerInfo.find(CERT_EXT_IP); + std::cerr << "Ext ip position : " << parsePosition << std::endl; + if (parsePosition != std::string::npos) { + parsePosition = parsePosition + CERT_EXT_IP.length(); + std::string subCert = peerInfo.substr(parsePosition); + parsePosition = subCert.find(":"); + if (parsePosition != std::string::npos) { + std::string ext_ip = subCert.substr(0, parsePosition); + std::cerr << "Ext Ip : " << ext_ip << std::endl; + pd.extAddr = ext_ip; + + //let's parse ext port + subCert = subCert.substr(parsePosition + 1); + parsePosition = subCert.find(";"); + if (parsePosition != std::string::npos) { + std::string ext_port = subCert.substr(0, parsePosition); + std::cerr << "Ext port : " << ext_port << std::endl; + std::istringstream instream(ext_port); + uint16_t ext_port_int; + instream >> ext_port_int; + pd.extPort = (ext_port_int); + } + } + } + + //let's parse DynDNS + parsePosition = peerInfo.find(CERT_DYNDNS); + std::cerr << "location DynDNS : " << parsePosition << std::endl; + if (parsePosition != std::string::npos) { + parsePosition += CERT_DYNDNS.length(); + std::string subCert = peerInfo.substr(parsePosition); + parsePosition = subCert.find(";"); + if (parsePosition != std::string::npos) { + std::string DynDNS = subCert.substr(0, parsePosition); + std::cerr << "DynDNS : " << DynDNS << std::endl; + pd.dyndns = DynDNS; + } + } + + } catch (...) { + std::cerr << "ConnectFriendWizard : Parse ip address error." << std::endl; + } + + if (pd.gpg_id == "") { + return false; + } else { + return true; + } +} + +bool p3Peers::cleanCertificate(const std::string &certstr, std::string &cleanCert) +{ + std::string cert; + std::string peerInfo; + + if (splitCert(certstr, cert, peerInfo)) { + cleanCert = cleanUpCertificate(cert); + if (!cleanCert.empty()) { + if (!peerInfo.empty()) { + if (*cleanCert.rbegin() != '\n') { + cleanCert += "\n"; + } + cleanCert += peerInfo; + } + return true; + } + } + + return false; +} + +bool p3Peers::saveCertificateToFile(const std::string &id, const std::string &fname) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::SaveCertificateToFile() not implemented yet " << id; + std::cerr << std::endl; +#endif + +// ensureExtension(fname, "pqi"); +// +// return AuthSSL::getAuthSSL()->SaveCertificateToFile(id, fname); + return false; +} + +std::string p3Peers::saveCertificateToString(const std::string &id) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::SaveCertificateToString() " << id; + std::cerr << std::endl; +#endif + if (id == AuthSSL::getAuthSSL()->OwnId()) { + return AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); + } else { + return ""; + } +} + +bool p3Peers::signGPGCertificate(const std::string &id) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::SignCertificate() " << id; + std::cerr << std::endl; +#endif + + + AuthGPG::getAuthGPG()->setAcceptToConnectGPGCertificate(id, true); + return AuthGPG::getAuthGPG()->SignCertificateLevel0(id); +} + +bool p3Peers::setAcceptToConnectGPGCertificate(const std::string &gpg_id, bool acceptance) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::setAcceptToConnectGPGCertificate() called with gpg_id : " << gpg_id << ", acceptance : " << acceptance << std::endl; +#endif + + if (gpg_id != "" && acceptance == false) { + //remove the friends from the connect manager + std::list sslFriends; + this->getSSLChildListOfGPGId(gpg_id, sslFriends); + for (std::list::iterator it = sslFriends.begin(); it != sslFriends.end(); it++) { + mConnMgr->removeFriend(*it); + } + return AuthGPG::getAuthGPG()->setAcceptToConnectGPGCertificate(gpg_id, acceptance); + } + return AuthGPG::getAuthGPG()->setAcceptToConnectGPGCertificate(gpg_id, acceptance); +} + +bool p3Peers::trustGPGCertificate(const std::string &id, uint32_t trustlvl) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::TrustCertificate() " << id; + std::cerr << std::endl; +#endif + //check if we've got a ssl or gpg id + std::string gpgId = getGPGId(id); + if (gpgId.empty()) { + //if no result then it must be a gpg id + return AuthGPG::getAuthGPG()->TrustCertificate(id, trustlvl); + } else { + return AuthGPG::getAuthGPG()->TrustCertificate(gpgId, trustlvl); + } +} + + +int ensureExtension(std::string &name, std::string def_ext) +{ + /* if it has an extension, don't change */ + int len = name.length(); + int extpos = name.find_last_of('.'); + + std::ostringstream out; + out << "ensureExtension() name: " << name << std::endl; + out << "\t\t extpos: " << extpos; + out << " len: " << len << std::endl; + + /* check that the '.' has between 1 and 4 char after it (an extension) */ + if ((extpos > 0) && (extpos < len - 1) && (extpos + 6 > len)) + { + /* extension there */ + std::string curext = name.substr(extpos, len); + out << "ensureExtension() curext: " << curext << std::endl; + std::cerr << out.str(); + return 0; + } + + if (extpos != len - 1) + { + name += "."; + } + name += def_ext; + + out << "ensureExtension() added ext: " << name << std::endl; + + std::cerr << out.str(); + return 1; +} + + /* Group Stuff */ +bool p3Peers::addGroup(RsGroupInfo &groupInfo) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::addGroup()" << std::endl; +#endif + + return mConnMgr->addGroup(groupInfo); +} + +bool p3Peers::editGroup(const std::string &groupId, RsGroupInfo &groupInfo) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::editGroup()" << std::endl; +#endif + + return mConnMgr->editGroup(groupId, groupInfo); +} + +bool p3Peers::removeGroup(const std::string &groupId) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::removeGroup()" << std::endl; +#endif + + return mConnMgr->removeGroup(groupId); +} + +bool p3Peers::getGroupInfo(const std::string &groupId, RsGroupInfo &groupInfo) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getGroupInfo()" << std::endl; +#endif + + return mConnMgr->getGroupInfo(groupId, groupInfo); +} + +bool p3Peers::getGroupInfoList(std::list &groupInfoList) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::getGroupInfoList()" << std::endl; +#endif + + return mConnMgr->getGroupInfoList(groupInfoList); +} + +bool p3Peers::assignPeerToGroup(const std::string &groupId, const std::string &peerId, bool assign) +{ + std::list peerIds; + peerIds.push_back(peerId); + + return assignPeersToGroup(groupId, peerIds, assign); +} + +bool p3Peers::assignPeersToGroup(const std::string &groupId, const std::list &peerIds, bool assign) +{ +#ifdef P3PEERS_DEBUG + std::cerr << "p3Peers::assignPeersToGroup()" << std::endl; +#endif + + return mConnMgr->assignPeersToGroup(groupId, peerIds, assign); +} + + +RsPeerDetails::RsPeerDetails() + :isOnlyGPGdetail(false), + id(""),gpg_id(""), + name(""),email(""),location(""), + org(""),issuer(""),fpr(""),authcode(""), + trustLvl(0), validLvl(0),ownsign(false), + hasSignedMe(false),accept_connection(false), + state(0),localAddr(""),localPort(0),extAddr(""),extPort(0),netMode(0),visState(0), + lastConnect(0),connectState(0),connectStateString(""),connectPeriod(0) +{ +} + +std::ostream &operator<<(std::ostream &out, const RsPeerDetails &detail) +{ + out << "RsPeerDetail: " << detail.name << " <" << detail.id << ">"; + out << std::endl; + + out << " email: " << detail.email; + out << " location:" << detail.location; + out << " org: " << detail.org; + out << std::endl; + + out << " fpr: " << detail.fpr; + out << " authcode:" << detail.authcode; + out << std::endl; + + out << " signers:"; + out << std::endl; + + std::list::const_iterator it; + for(it = detail.gpgSigners.begin(); + it != detail.gpgSigners.end(); it++) + { + out << "\t" << *it; + out << std::endl; + } + out << std::endl; + + out << " trustLvl: " << detail.trustLvl; + out << " ownSign: " << detail.ownsign; + out << std::endl; + + out << " state: " << detail.state; + out << " netMode: " << detail.netMode; + out << std::endl; + + out << " localAddr: " << detail.localAddr; + out << ":" << detail.localPort; + out << std::endl; + out << " extAddr: " << detail.extAddr; + out << ":" << detail.extPort; + out << std::endl; + + + out << " lastConnect: " << detail.lastConnect; + out << " connectPeriod: " << detail.connectPeriod; + out << std::endl; + + return out; +} + +RsGroupInfo::RsGroupInfo() +{ + flag = 0; +} diff --git a/libretroshare/src/rsserver/p3peers.h b/libretroshare/src/rsserver/p3peers.h new file mode 100644 index 000000000..435b58d79 --- /dev/null +++ b/libretroshare/src/rsserver/p3peers.h @@ -0,0 +1,120 @@ +#ifndef RETROSHARE_P3_PEER_INTERFACE_H +#define RETROSHARE_P3_PEER_INTERFACE_H + +/* + * libretroshare/src/rsserver: p3peers.h + * + * RetroShare C++ Interface. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rspeers.h" +#include "pqi/p3connmgr.h" + +class p3Peers: public RsPeers +{ + public: + + p3Peers(p3ConnectMgr *cm); +virtual ~p3Peers() { return; } + + /* Updates ... */ +virtual bool FriendsChanged(); +virtual bool OthersChanged(); + + /* Peer Details (Net & Auth) */ +virtual std::string getOwnId(); + +virtual bool getOnlineList(std::list &ids); +virtual bool getFriendList(std::list &ids); +//virtual bool getOthersList(std::list &ids); +virtual bool getPeerCount (unsigned int *pnFriendCount, unsigned int *pnOnlineCount, bool ssl); + +virtual bool isOnline(const std::string &id); +virtual bool isFriend(const std::string &id); +virtual bool isGPGAccepted(const std::string &gpg_id_is_friend); // +virtual std::string getGPGName(const std::string &gpg_id); +virtual std::string getPeerName(const std::string &ssl_or_gpg_id); +virtual bool getPeerDetails(const std::string &id, RsPeerDetails &d); + + /* Using PGP Ids */ +virtual std::string getGPGOwnId(); +virtual std::string getGPGId(const std::string &ssl_id); +virtual bool getGPGAcceptedList(std::list &ids); +virtual bool getGPGSignedList(std::list &ids); +virtual bool getGPGValidList(std::list &ids); +virtual bool getGPGAllList(std::list &ids); +virtual bool getGPGDetails(const std::string &id, RsPeerDetails &d); +virtual bool getSSLChildListOfGPGId(const std::string &gpg_id, std::list &ids); + + /* Add/Remove Friends */ +virtual bool addFriend(const std::string &ssl_id, const std::string &gpg_id); +virtual bool addDummyFriend(const std::string &gpg_id); //we want to add a empty ssl friend for this gpg id +virtual bool isDummyFriend(const std::string &ssl_id); +virtual bool removeFriend(const std::string &ssl_id); +virtual bool cleanUnusedLocations() ; + + /* Network Stuff */ +virtual bool connectAttempt(const std::string &id); +virtual bool setLocation(const std::string &ssl_id, const std::string &location);//location is shown in the gui to differentiate ssl certs +virtual bool setLocalAddress(const std::string &id, const std::string &addr, uint16_t port); +virtual bool setExtAddress(const std::string &id, const std::string &addr, uint16_t port); +virtual bool setDynDNS(const std::string &id, const std::string &dyndns); +virtual bool setNetworkMode(const std::string &id, uint32_t netMode); +virtual bool setVisState(const std::string &id, uint32_t mode); + +virtual void getIPServersList(std::list& ip_servers) ; +virtual void allowServerIPDetermination(bool) ; +virtual void allowTunnelConnection(bool) ; +virtual bool getAllowServerIPDetermination() ; +virtual bool getAllowTunnelConnection() ; + + /* Auth Stuff */ +// Get the invitation (GPG cert + local/ext address + SSL id for the given peer) +virtual std::string GetRetroshareInvite(const std::string& ssl_id); +// same but for own id +virtual std::string GetRetroshareInvite(); + +virtual bool loadCertificateFromFile(const std::string &fname, std::string &id, std::string &gpg_id); +virtual bool loadDetailsFromStringCert(const std::string &cert, RsPeerDetails &pd, std::string& error_string); +virtual bool cleanCertificate(const std::string &certstr, std::string &cleanCert); +virtual bool saveCertificateToFile(const std::string &id, const std::string &fname); +virtual std::string saveCertificateToString(const std::string &id); + +virtual bool setAcceptToConnectGPGCertificate(const std::string &gpg_id, bool acceptance); +virtual bool signGPGCertificate(const std::string &id); +virtual bool trustGPGCertificate(const std::string &id, uint32_t trustlvl); + + /* Group Stuff */ +virtual bool addGroup(RsGroupInfo &groupInfo); +virtual bool editGroup(const std::string &groupId, RsGroupInfo &groupInfo); +virtual bool removeGroup(const std::string &groupId); +virtual bool getGroupInfo(const std::string &groupId, RsGroupInfo &groupInfo); +virtual bool getGroupInfoList(std::list &groupInfoList); +virtual bool assignPeerToGroup(const std::string &groupId, const std::string &peerId, bool assign); +virtual bool assignPeersToGroup(const std::string &groupId, const std::list &peerIds, bool assign); + + private: + + p3ConnectMgr *mConnMgr; +}; + +#endif diff --git a/libretroshare/src/rsserver/p3photo.cc b/libretroshare/src/rsserver/p3photo.cc new file mode 100644 index 000000000..788163257 --- /dev/null +++ b/libretroshare/src/rsserver/p3photo.cc @@ -0,0 +1,143 @@ +/* + * libretroshare/src/rsserver: p3photo.cc + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rsserver/p3photo.h" +#include "services/p3photoservice.h" + +RsPhoto *rsPhoto = NULL; + + +RsPhotoDetails::RsPhotoDetails() +{ + return; +} + +RsPhotoShowDetails::RsPhotoShowDetails() +{ + return; +} + +p3Photo::p3Photo(p3PhotoService *p3ps) + :mPhoto(p3ps) +{ + return; +} + +p3Photo::~p3Photo() +{ + return; +} + + /* needs update? */ +bool p3Photo::updated() +{ + return mPhoto->updated(); +} + + /* access data */ +bool p3Photo::getPhotoList(std::string id, std::list &hashs) +{ + return mPhoto->getPhotoList(id, hashs); +} + +bool p3Photo::getShowList(std::string id, std::list &showIds) +{ + return mPhoto -> getShowList(id, showIds); +} + + +bool p3Photo::getShowDetails(std::string id, std::string showId, RsPhotoShowDetails &detail) +{ + return mPhoto -> getShowDetails(id, showId, detail); +} + + +bool p3Photo::getPhotoDetails(std::string id, std::string photoId, RsPhotoDetails &detail) +{ + return mPhoto -> getPhotoDetails(id, photoId, detail); +} + + + /* add / delete */ +std::string p3Photo::createShow(std::string name) +{ + return mPhoto -> createShow(name); +} + +bool p3Photo::deleteShow(std::string showId) +{ + return mPhoto -> deleteShow(showId); +} + +bool p3Photo::addPhotoToShow(std::string showId, std::string photoId, int16_t index) +{ + return mPhoto -> addPhotoToShow(showId, photoId, index); +} + +bool p3Photo::movePhotoInShow(std::string showId, std::string photoId, int16_t index) +{ + return mPhoto -> movePhotoInShow(showId, photoId, index); +} + +bool p3Photo::removePhotoFromShow(std::string showId, std::string photoId) +{ + return mPhoto -> removePhotoFromShow(showId, photoId); +} + + +std::string p3Photo::addPhoto(std::string path) /* add from file */ +{ + return mPhoto -> addPhoto(path); /* add from file */ +} + +bool p3Photo::addPhoto(std::string srcId, std::string photoId) /* add from peers photos */ +{ + return mPhoto -> addPhoto(srcId, photoId); /* add from peers photos */ + +} + +bool p3Photo::deletePhoto(std::string photoId) +{ + return mPhoto -> deletePhoto(photoId); +} + + + /* modify properties (TODO) */ +bool p3Photo::modifyShow(std::string showId, std::wstring name, std::wstring comment) +{ + return mPhoto -> modifyShow(showId, name, comment); +} + +bool p3Photo::modifyPhoto(std::string photoId, std::wstring name, std::wstring comment) +{ + return mPhoto -> modifyPhoto(photoId, name, comment); +} + +bool p3Photo::modifyShowComment(std::string showId, std::string photoId, std::wstring comment) +{ + return mPhoto -> modifyShowComment(showId, photoId, comment); +} + + diff --git a/libretroshare/src/rsserver/p3photo.h b/libretroshare/src/rsserver/p3photo.h new file mode 100644 index 000000000..897af193b --- /dev/null +++ b/libretroshare/src/rsserver/p3photo.h @@ -0,0 +1,69 @@ +#ifndef RETROSHARE_P3_PHOTO_INTERFACE_H +#define RETROSHARE_P3_PHOTO_INTERFACE_H + +/* + * libretroshare/src/rsserver: p3photo.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rsphoto.h" +#include "services/p3photoservice.h" + +class p3Photo: public RsPhoto +{ + public: + + p3Photo(p3PhotoService *p3ps); +virtual ~p3Photo(); + + /* changed? */ +virtual bool updated(); + + /* access data */ +virtual bool getPhotoList(std::string id, std::list &hashs); +virtual bool getShowList(std::string id, std::list &showIds); +virtual bool getShowDetails(std::string id, std::string showId, RsPhotoShowDetails &detail); +virtual bool getPhotoDetails(std::string id, std::string photoId, RsPhotoDetails &detail); + + /* add / delete */ +virtual std::string createShow(std::string name); +virtual bool deleteShow(std::string showId); +virtual bool addPhotoToShow(std::string showId, std::string photoId, int16_t index); +virtual bool movePhotoInShow(std::string showId, std::string photoId, int16_t index); +virtual bool removePhotoFromShow(std::string showId, std::string photoId); + +virtual std::string addPhoto(std::string path); /* add from file */ +virtual bool addPhoto(std::string srcId, std::string photoId); /* add from peers photos */ +virtual bool deletePhoto(std::string photoId); + + /* modify properties (TODO) */ +virtual bool modifyShow(std::string showId, std::wstring name, std::wstring comment); +virtual bool modifyPhoto(std::string photoId, std::wstring name, std::wstring comment); +virtual bool modifyShowComment(std::string showId, std::string photoId, std::wstring comment); + + private: + + p3PhotoService *mPhoto; +}; + +#endif diff --git a/libretroshare/src/rsserver/p3rank.cc b/libretroshare/src/rsserver/p3rank.cc new file mode 100644 index 000000000..8dc613cff --- /dev/null +++ b/libretroshare/src/rsserver/p3rank.cc @@ -0,0 +1,104 @@ +/* + * libretroshare/src/rsserver: p3rank.cc + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rsserver/p3rank.h" + +RsRanks *rsRanks = NULL; + +p3Rank::p3Rank(p3Ranking *ranking) + :mRank(ranking) +{ + return; +} + +p3Rank::~p3Rank() +{ + return; +} + /* needs update? */ +bool p3Rank::updated() +{ + return mRank->updated(); +} + + /* Set Sort Methods */ +bool p3Rank::setSortPeriod(uint32_t period) +{ + return mRank->setSortPeriod(period); +} + +bool p3Rank::setSortMethod(uint32_t type) +{ + return mRank->setSortMethod(type); +} + +bool p3Rank::clearPeerFilter() +{ + return mRank->clearPeerFilter(); +} + +bool p3Rank::setPeerFilter(std::list peers) +{ + return mRank->setPeerFilter(peers); +} + + /* get Ids */ +uint32_t p3Rank::getRankingsCount() +{ + return mRank->getRankingsCount(); +} + +float p3Rank::getMaxRank() +{ + return mRank->getMaxRank(); +} + +bool p3Rank::getRankings(uint32_t first, uint32_t count, std::list &rids) +{ + return mRank->getRankings(first, count, rids); +} + +bool p3Rank::getRankDetails(std::string rid, RsRankDetails &details) +{ + return mRank->getRankDetails(rid, details); +} + + + /* Add New Comment / Msg */ +std::string p3Rank::newRankMsg(std::wstring link, std::wstring title, std::wstring comment, int32_t score) +{ + return mRank->newRankMsg(link, title, comment, score); +} + +bool p3Rank::updateComment(std::string rid, std::wstring comment, int32_t score) +{ + return mRank->updateComment(rid, comment, score); +} + +std::string p3Rank::anonRankMsg(std::string rid, std::wstring link, std::wstring title) +{ + return mRank->anonRankMsg(rid, link, title); +} + diff --git a/libretroshare/src/rsserver/p3rank.h b/libretroshare/src/rsserver/p3rank.h new file mode 100644 index 000000000..cdf9bbfd5 --- /dev/null +++ b/libretroshare/src/rsserver/p3rank.h @@ -0,0 +1,64 @@ +#ifndef RETROSHARE_P3_RANKING_INTERFACE_H +#define RETROSHARE_P3_RANKING_INTERFACE_H + +/* + * libretroshare/src/rsserver: p3rank.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rsrank.h" +#include "services/p3ranking.h" + +class p3Rank: public RsRanks +{ + public: + + p3Rank(p3Ranking *ranking); +virtual ~p3Rank(); + + /* needs update? */ +virtual bool updated(); + + /* Set Sort Methods */ +virtual bool setSortPeriod(uint32_t period); +virtual bool setSortMethod(uint32_t type); +virtual bool clearPeerFilter(); +virtual bool setPeerFilter(std::list peers); + + /* get Ids */ +virtual uint32_t getRankingsCount(); +virtual float getMaxRank(); +virtual bool getRankings(uint32_t first, uint32_t count, std::list &rids); +virtual bool getRankDetails(std::string rid, RsRankDetails &details); + + /* Add New Comment / Msg */ +virtual std::string newRankMsg(std::wstring link, std::wstring title, std::wstring comment, int32_t score); +virtual bool updateComment(std::string rid, std::wstring comment, int32_t score); +virtual std::string anonRankMsg(std::string rid, std::wstring link, std::wstring title); + + private: + + p3Ranking *mRank; +}; + +#endif diff --git a/libretroshare/src/rsserver/p3status.cc b/libretroshare/src/rsserver/p3status.cc new file mode 100644 index 000000000..150854c2c --- /dev/null +++ b/libretroshare/src/rsserver/p3status.cc @@ -0,0 +1,58 @@ +/* + * libretroshare/src/rsserver: p3msgs.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "p3status.h" +#include "services/p3statusservice.h" + +p3Status::p3Status(p3StatusService* statusSrv) + : mStatusSrv(statusSrv) { + + +} + +p3Status::~p3Status(){ + return; +} + +bool p3Status::getOwnStatus(StatusInfo& statusInfo){ + + return mStatusSrv->getOwnStatus(statusInfo); +} + +bool p3Status::getStatusList(std::list& statusInfo){ + + return mStatusSrv->getStatusList(statusInfo); +} + +bool p3Status::getStatus(std::string &id, StatusInfo &statusInfo) +{ + return mStatusSrv->getStatus(id, statusInfo); +} + +bool p3Status::sendStatus(std::string id, uint32_t status){ + + return mStatusSrv->sendStatus(id, status); +} diff --git a/libretroshare/src/rsserver/p3status.h b/libretroshare/src/rsserver/p3status.h new file mode 100644 index 000000000..3a65e44a4 --- /dev/null +++ b/libretroshare/src/rsserver/p3status.h @@ -0,0 +1,57 @@ +#ifndef RS_P3STATUS_INTERFACE_H +#define RS_P3STATUS_INTERFACE_H + +/* + * libretroshare/src/rsserver: p3status.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Chris Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rsstatus.h" + + +class p3StatusService; + +//! Implements abstract interface rsStatus +/*! + * Interfaces with p3StatusService + */ +class p3Status : public RsStatus +{ +public: + + p3Status(p3StatusService* statusSrv); + virtual ~p3Status(); + + + virtual bool getOwnStatus(StatusInfo& statusInfo); + virtual bool getStatusList(std::list& statusInfo); + virtual bool getStatus(std::string &id, StatusInfo &statusInfo); + virtual bool sendStatus(std::string id, uint32_t status); + +private: + + p3StatusService* mStatusSrv; + +}; + +#endif /* RS_P3STATUS_INTERFACE_H */ diff --git a/libretroshare/src/rsserver/rsiface.cc b/libretroshare/src/rsserver/rsiface.cc new file mode 100644 index 000000000..f2e5ba071 --- /dev/null +++ b/libretroshare/src/rsserver/rsiface.cc @@ -0,0 +1,109 @@ + +/* + * "$Id: rsiface.cc,v 1.6 2007-04-15 18:45:23 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#include "retroshare/rsiface.h" +#include "util/rsdir.h" + +/* global variable */ +RsIface *rsiface = NULL; + + +/* set to true */ +bool RsIface::setChanged(DataFlags set) +{ + if ((int) set < (int) NumOfFlags) + { + /* go for it */ + mChanged[(int) set ] = true; + return true; + } + return false; +} + + +/* leaves it */ +bool RsIface::getChanged(DataFlags set) +{ + if ((int) set < (int) NumOfFlags) + { + /* go for it */ + return mChanged[(int) set ]; + } + return false; +} + +/* resets it */ +bool RsIface::hasChanged(DataFlags set) +{ + if ((int) set < (int) NumOfFlags) + { + /* go for it */ + if (mChanged[(int) set ]) + { + mChanged[(int) set ] = false; + return true; + } + } + return false; +} + +/*************************** THE REAL RSIFACE (with MUTEXES) *******/ + +#include "util/rsthreads.h" + +class RsIfaceReal: public RsIface +{ +public: + RsIfaceReal(NotifyBase &callback) + :RsIface(callback) + { return; } + + virtual void lockData() + { +// std::cerr << "RsIfaceReal::lockData()" << std::endl; + return rsIfaceMutex.lock(); + } + + virtual void unlockData() + { +// std::cerr << "RsIfaceReal::unlockData()" << std::endl; + return rsIfaceMutex.unlock(); + } + +private: + RsMutex rsIfaceMutex; +}; + +RsIface *createRsIface(NotifyBase &cb) +{ + rsiface = new RsIfaceReal(cb); + return rsiface; +} + + + diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc new file mode 100644 index 000000000..9bbded580 --- /dev/null +++ b/libretroshare/src/rsserver/rsinit.cc @@ -0,0 +1,2312 @@ +/* + * libretroshare/src/reserver rsinit.cc + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* This is an updated startup class. Class variables are hidden from + * the GUI / External via a hidden class */ + +#include + +// for locking instances +#ifndef WINDOWS_SYS +#include +#endif + +#include "util/rsdebug.h" +#include "util/rsdir.h" +#include "util/rsrandom.h" +#include "util/folderiterator.h" +#include "retroshare/rsinit.h" +#include "plugins/pluginmanager.h" +#include "rsserver/rsloginhandler.h" + +#include +#include +#include + +#include +#include +#include +#include + +// for blocking signals +#include + +#include "pqi/authssl.h" +#include "pqi/sslfns.h" +#include "pqi/authgpg.h" + +#include "tcponudp/udpstunner.h" + +class accountId +{ + public: + std::string pgpId; + std::string pgpName; + std::string pgpEmail; + + std::string sslId; + std::string location; +}; + + +class RsInitConfig +{ + public: + /* Directories (SetupBaseDir) */ + static std::string basedir; + static std::string homePath; +#ifdef WINDOWS_SYS + static bool portable; + static bool isWindowsXP; +#endif + + static std::list accountIds; + static std::string preferedId; + + /* for certificate creation */ + //static std::string gpgPasswd; + +#ifndef WINDOWS_SYS + static int lockHandle; +#else + static HANDLE lockHandle; +#endif + + /* These fields are needed for login */ + static std::string loginId; + static std::string configDir; + static std::string load_cert; + static std::string load_key; + + static std::string passwd; + + static bool autoLogin; /* autoLogin allowed */ + static bool startMinimised; /* Icon or Full Window */ + + /* Key Parameters that must be set before + * RetroShare will start up: + */ + + /* Listening Port */ + static bool forceExtPort; + static bool forceLocalAddr; + static unsigned short port; + static char inet[256]; + + /* Logging */ + static bool haveLogFile; + static bool outStderr; + static bool haveDebugLevel; + static int debugLevel; + static std::string logfname; + + static bool firsttime_run; + static bool load_trustedpeer; + static std::string load_trustedpeer_file; + + static bool udpListenerOnly; + + static std::string RetroShareLink; +}; + + +const int p3facestartupzone = 47238; + +// initial configuration bootstrapping... +static const std::string configInitFile = "default_cert.txt"; +static const std::string configConfFile = "config.rs"; +static const std::string configCertDir = "friends"; +static const std::string configKeyDir = "keys"; +static const std::string configCaFile = "cacerts.pem"; +static const std::string configLogFileName = "retro.log"; +static const std::string configHelpName = "retro.htm"; +static const int SSLPWD_LEN = 64; + +std::list RsInitConfig::accountIds; +std::string RsInitConfig::preferedId; + +#ifndef WINDOWS_SYS + int RsInitConfig::lockHandle; +#else + HANDLE RsInitConfig::lockHandle; +#endif + +std::string RsInitConfig::configDir; +std::string RsInitConfig::load_cert; +std::string RsInitConfig::load_key; + +std::string RsInitConfig::passwd; +//std::string RsInitConfig::gpgPasswd; + +bool RsInitConfig::autoLogin; /* autoLogin allowed */ +bool RsInitConfig::startMinimised; /* Icon or Full Window */ +std::string RsInitConfig::RetroShareLink; + +/* Directories */ +std::string RsInitConfig::basedir; +std::string RsInitConfig::homePath; +#ifdef WINDOWS_SYS +bool RsInitConfig::portable = false; +bool RsInitConfig::isWindowsXP = false; +#endif + +/* Listening Port */ +bool RsInitConfig::forceExtPort; +bool RsInitConfig::forceLocalAddr; +unsigned short RsInitConfig::port; +char RsInitConfig::inet[256]; + +/* Logging */ +bool RsInitConfig::haveLogFile; +bool RsInitConfig::outStderr; +bool RsInitConfig::haveDebugLevel; +int RsInitConfig::debugLevel; +std::string RsInitConfig::logfname; + +bool RsInitConfig::firsttime_run; +bool RsInitConfig::load_trustedpeer; +std::string RsInitConfig::load_trustedpeer_file; + +bool RsInitConfig::udpListenerOnly; + + +/* Uses private class - so must be hidden */ +static bool getAvailableAccounts(std::list &ids); +static bool checkAccount(std::string accountdir, accountId &id); + +static std::string toUpperCase(const std::string& s) +{ + std::string res(s) ; + + for(uint32_t i=0;i 96 && res[i] < 123) + res[i] -= 97-65 ; + + return res ; +} + +static std::string toLowerCase(const std::string& s) +{ + std::string res(s) ; + + for(uint32_t i=0;i 64 && res[i] < 91) + res[i] += 97-65 ; + + return res ; +} + +void RsInit::InitRsConfig() +{ +#ifndef WINDOWS_SYS + RsInitConfig::lockHandle = -1; +#else + RsInitConfig::lockHandle = NULL; +#endif + + + RsInitConfig::load_trustedpeer = false; + RsInitConfig::firsttime_run = false; + RsInitConfig::port = 0 ; + RsInitConfig::forceLocalAddr = false; + RsInitConfig::haveLogFile = false; + RsInitConfig::outStderr = false; + RsInitConfig::forceExtPort = false; + + strcpy(RsInitConfig::inet, "127.0.0.1"); + + RsInitConfig::autoLogin = false; // . + RsInitConfig::startMinimised = false; + RsInitConfig::passwd = ""; + RsInitConfig::haveDebugLevel = false; + RsInitConfig::debugLevel = PQL_WARNING; + RsInitConfig::udpListenerOnly = false; + + /* setup the homePath (default save location) */ + RsInitConfig::homePath = getHomePath(); + +#ifdef WINDOWS_SYS + // test for portable version + if (GetFileAttributes (L"gpg.exe") != (DWORD) -1 && GetFileAttributes (L"gpgme-w32spawn.exe") != (DWORD) -1) { + // use portable version + RsInitConfig::portable = true; + } + + // test for Windows XP + OSVERSIONINFOEX osvi; + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + if (GetVersionEx((OSVERSIONINFO*) &osvi)) { + if (osvi.dwMajorVersion == 5) { + if (osvi.dwMinorVersion == 1) { + /* Windows XP */ + RsInitConfig::isWindowsXP = true; + } else if (osvi.dwMinorVersion == 2) { + SYSTEM_INFO si; + memset(&si, 0, sizeof(si)); + GetSystemInfo(&si); + if (osvi.wProductType == VER_NT_WORKSTATION && si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) { + /* Windows XP Professional x64 Edition */ + RsInitConfig::isWindowsXP = true; + } + } + } + } + + if (RsInitConfig::isWindowsXP) { + std::cerr << "Running Windows XP" << std::endl; + } else { + std::cerr << "Not running Windows XP" << std::endl; + } +#endif + + /* Setup the Debugging */ + // setup debugging for desired zones. + setOutputLevel(PQL_WARNING); // default to Warnings. + + // For Testing purposes. + // We can adjust everything under Linux. + //setZoneLevel(PQL_DEBUG_BASIC, 38422); // pqipacket. + //setZoneLevel(PQL_DEBUG_BASIC, 96184); // pqinetwork; + //setZoneLevel(PQL_DEBUG_BASIC, 82371); // pqiperson. + //setZoneLevel(PQL_DEBUG_BASIC, 60478); // pqitunnel. + //setZoneLevel(PQL_DEBUG_BASIC, 34283); // pqihandler. + //setZoneLevel(PQL_DEBUG_BASIC, 44863); // discItems. + //setZoneLevel(PQL_DEBUG_BASIC, 2482); // p3disc + //setZoneLevel(PQL_DEBUG_BASIC, 1728); // pqi/p3proxy + //setZoneLevel(PQL_DEBUG_BASIC, 1211); // sslroot. + //setZoneLevel(PQL_DEBUG_BASIC, 37714); // pqissl. + //setZoneLevel(PQL_DEBUG_BASIC, 8221); // pqistreamer. + //setZoneLevel(PQL_DEBUG_BASIC, 9326); // pqiarchive + //setZoneLevel(PQL_DEBUG_BASIC, 3334); // p3channel. + //setZoneLevel(PQL_DEBUG_BASIC, 354); // pqipersongrp. + //setZoneLevel(PQL_DEBUG_BASIC, 6846); // pqiudpproxy + //setZoneLevel(PQL_DEBUG_BASIC, 3144); // pqissludp; + //setZoneLevel(PQL_DEBUG_BASIC, 86539); // pqifiler. + //setZoneLevel(PQL_DEBUG_BASIC, 91393); // Funky_Browser. + //setZoneLevel(PQL_DEBUG_BASIC, 25915); // fltkserver + //setZoneLevel(PQL_DEBUG_BASIC, 47659); // fldxsrvr + //setZoneLevel(PQL_DEBUG_BASIC, 49787); // pqissllistener +} + + +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS +int RsInit::InitRetroShare(int argc, char **argv, bool strictCheck) +{ +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else + + /* for static PThreads under windows... we need to init the library... + */ + #ifdef PTW32_STATIC_LIB + #include + #endif + +int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck) +{ + + /* THIS IS A HACK TO ALLOW WINDOWS TO ACCEPT COMMANDLINE ARGUMENTS */ + + + + + int argc; + int i; +#ifdef USE_CMD_ARGS + char** argv = argvIgnored; + argc = argcIgnored; + + +#else + + const int MAX_ARGS = 32; + int j; + char *argv[MAX_ARGS]; + char *wholeline = (char*)GetCommandLine(); + int cmdlen = strlen(wholeline); + // duplicate line, so we can put in spaces.. + char dupline[cmdlen+1]; + strcpy(dupline, wholeline); + + /* break wholeline down .... + * NB. This is very simplistic, and will not + * handle multiple spaces, or quotations etc, only for debugging purposes + */ + argv[0] = dupline; + for(i = 1, j = 0; (j + 1 < cmdlen) && (i < MAX_ARGS);) + { + /* find next space. */ + for(;(j + 1 < cmdlen) && (dupline[j] != ' ');j++); + if (j + 1 < cmdlen) + { + dupline[j] = '\0'; + argv[i++] = &(dupline[j+1]); + } + } + argc = i; + +#endif + + for( i=0; i 0) && + (RsInitConfig::debugLevel <= PQL_DEBUG_ALL)) + { + std::cerr << "Setting Debug Level to: "; + std::cerr << RsInitConfig::debugLevel; + std::cerr << std::endl; + setOutputLevel(RsInitConfig::debugLevel); + } + else + { + std::cerr << "Ignoring Invalid Debug Level: "; + std::cerr << RsInitConfig::debugLevel; + std::cerr << std::endl; + } + } + + // set the debug file. + if (RsInitConfig::haveLogFile) + { + setDebugFile(RsInitConfig::logfname.c_str()); + } + +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else + // Windows Networking Init. + WORD wVerReq = MAKEWORD(2,2); + WSADATA wsaData; + + if (0 != WSAStartup(wVerReq, &wsaData)) + { + std::cerr << "Failed to Startup Windows Networking"; + std::cerr << std::endl; + } + else + { + std::cerr << "Started Windows Networking"; + std::cerr << std::endl; + } + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + // SWITCH off the SIGPIPE - kills process on Linux. +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + struct sigaction sigact; + sigact.sa_handler = SIG_IGN; + sigact.sa_flags = 0; + + sigset_t set; + sigemptyset(&set); + //sigaddset(&set, SIGINT); // or whatever other signal + sigact.sa_mask = set; + + if (0 == sigaction(SIGPIPE, &sigact, NULL)) + { + std::cerr << "RetroShare:: Successfully Installed"; + std::cerr << "the SIGPIPE Block" << std::endl; + } + else + { + std::cerr << "RetroShare:: Failed to Install"; + std::cerr << "the SIGPIPE Block" << std::endl; + } +#endif +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + + /* At this point we want to. + * 1) Load up Dase Directory. + * 3) Get Prefered Id. + * 2) Get List of Available Accounts. + * 4) Get List of GPG Accounts. + */ + /* create singletons */ + AuthSSLInit(); + AuthGPGInit(); + + AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL); + + // first check config directories, and set bootstrap values. + setupBaseDir(); + get_configinit(RsInitConfig::basedir, RsInitConfig::preferedId); + + /* Initialize AuthGPG */ + if (AuthGPG::getAuthGPG()->InitAuth() == false) { + std::cerr << "AuthGPG::InitAuth failed" << std::endl; + return RS_INIT_AUTH_FAILED; + } + + //std::list ids; + std::list::iterator it; + getAvailableAccounts(RsInitConfig::accountIds); + + // if a different user id has been passed to cmd line check for that instead + + std::string lower_case_user_string = toLowerCase(prefUserString) ; + std::string upper_case_user_string = toUpperCase(prefUserString) ; + + bool pgpNameFound = false; + if(prefUserString != "") + { + + for(it = RsInitConfig::accountIds.begin() ; it!= RsInitConfig::accountIds.end() ; it++) + { + std::cerr << "Checking account (gpgid = " << it->pgpId << ", name=" << it->pgpName << ", sslId=" << it->sslId << ")" << std::endl ; + + if(prefUserString == it->pgpName || upper_case_user_string == it->pgpId || lower_case_user_string == it->sslId) + { + RsInitConfig::preferedId = it->sslId; + pgpNameFound = true; + } + } + if(!pgpNameFound){ + std::cerr << "Invalid User name/GPG id/SSL id: not found in list" << std::endl; + exit(1); + } + } + + + + /* check that preferedId */ + std::string userName; + std::string userId; + bool existingUser = false; + for(it = RsInitConfig::accountIds.begin(); it != RsInitConfig::accountIds.end(); it++) + { + std::cerr << "Checking Account Id: " << it->sslId << std::endl; + if (RsInitConfig::preferedId == it->sslId) + { + std::cerr << " * Preferred * " << std::endl; + userId = it->sslId; + userName = it->pgpName; + existingUser = true; + } + } + if (!existingUser) + { + std::cerr << "No Existing User" << std::endl; + RsInitConfig::preferedId == ""; + + } + + /* if existing user, and havePasswd .... we can skip the login prompt */ + if (existingUser) + { + if (RsInitConfig::passwd != "") + { + return RS_INIT_HAVE_ACCOUNT; + } + + RsInit::LoadPassword(RsInitConfig::preferedId, ""); + + if(RsLoginHandler::getSSLPassword(RsInitConfig::preferedId,false,RsInitConfig::passwd)) + { + RsInit::setAutoLogin(true); + std::cerr << "Autologin has succeeded" << std::endl; + return RS_INIT_HAVE_ACCOUNT; + } + } + return RS_INIT_OK; +} + +/**************************** Access Functions for Init Data **************************/ + +bool RsInit::getPreferedAccountId(std::string &id) +{ + id = RsInitConfig::preferedId; + return (RsInitConfig::preferedId != ""); +} + +bool RsInit::getAccountIds(std::list &ids) +{ + std::list::iterator it; + #ifdef AUTHSSL_DEBUG + std::cerr << "getAccountIds:" << std::endl; + #endif + + for(it = RsInitConfig::accountIds.begin(); it != RsInitConfig::accountIds.end(); it++) + { + #ifdef AUTHSSL_DEBUG + std::cerr << "SSL Id: " << it->sslId << " PGP Id " << it->pgpId; + std::cerr << " PGP Name: " << it->pgpName; + std::cerr << " PGP Email: " << it->pgpEmail; + std::cerr << " Location: " << it->location; + std::cerr << std::endl; + #endif + + ids.push_back(it->sslId); + } + return true; +} + + +bool RsInit::getAccountDetails(std::string id, + std::string &gpgId, std::string &gpgName, + std::string &gpgEmail, std::string &location) +{ + std::list::iterator it; + for(it = RsInitConfig::accountIds.begin(); it != RsInitConfig::accountIds.end(); it++) + { + if (id == it->sslId) + { + gpgId = it->pgpId; + gpgName = it->pgpName; + gpgEmail = it->pgpEmail; + location = it->location; + return true; + } + } + return false; +} + +/**************************** Access Functions for Init Data **************************/ +/**************************** Private Functions for InitRetroshare ********************/ +/**************************** Private Functions for InitRetroshare ********************/ + + +void RsInit::setupBaseDir() +{ + // get the default configuration location. + + if (RsInitConfig::basedir == "") + { + // v0.4.x if unix. homedir + /.pqiPGPrc + // v0.5.x if unix. homedir + /.retroshare + +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + char *h = getenv("HOME"); + std::cerr << "retroShare::basedir() -> $HOME = "; + std::cerr << h << std::endl; + if (h == NULL) + { + std::cerr << "load_check_basedir() Fatal Error --"; + std::cerr << std::endl; + std::cerr << "\tcannot determine $HOME dir" < $APPDATA = "; + std::cerr << h << std::endl; + char *h2 = getenv("HOMEDRIVE"); + std::cerr << "retroShare::basedir() -> $HOMEDRIVE = "; + std::cerr << h2 << std::endl; + wchar_t *wh3 = _wgetenv(L"HOMEPATH"); + std::string h3; + librs::util::ConvertUtf16ToUtf8(std::wstring(wh3), h3); + std::cerr << "retroShare::basedir() -> $HOMEPATH = "; + std::cerr << h3 << std::endl; + if (h.empty()) + { + // generating default + std::cerr << "load_check_basedir() getEnv Error --Win95/98?"; + std::cerr << std::endl; + + RsInitConfig::basedir="C:\\Retro"; + + } + else + { + RsInitConfig::basedir = h; + } + + if (!RsDirUtil::checkCreateDirectory(RsInitConfig::basedir)) + { + std::cerr << "Cannot Create BaseConfig Dir" << std::endl; + exit(1); + } + RsInitConfig::basedir += "\\RetroShare"; + } +#endif +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + } + + // fatal if cannot find/create. + std::cerr << "Creating Root Retroshare Config Directories" << std::endl; + if (!RsDirUtil::checkCreateDirectory(RsInitConfig::basedir)) + { + std::cerr << "Cannot Create BaseConfig Dir:" << RsInitConfig::basedir << std::endl; + exit(1); + } +} + + +/*********************************************************** + * This Directory is used to store data and "template" file that Retroshare requires. + * These files will either be copied into Retroshare's configuration directory, + * if they are to be modified. Or used directly, if read-only. + * + * This will initially be used for the DHT bootstrap file. + * + * Please modify the code below to suit your platform! + * + * WINDOWS: + * WINDOWS PORTABLE: + * Linux: + * OSX: + + ***********/ + +#ifdef __APPLE__ + /* needs CoreFoundation Framework */ + #include + //#include + //#include +#endif + +std::string RsInit::getRetroshareDataDirectory() +{ + std::string dataDirectory; + +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + + #ifdef __APPLE__ + /* For OSX, applications are Bundled in a directory... + * need to get the path to the executable Bundle. + * + * Code nicely supplied by Qt! + */ + + CFURLRef pluginRef = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, + kCFURLPOSIXPathStyle); + const char *pathPtr = CFStringGetCStringPtr(macPath, + CFStringGetSystemEncoding()); + dataDirectory = pathPtr; + CFRelease(pluginRef); + CFRelease(macPath); + + dataDirectory += "/Contents/Resources"; + std::cerr << "getRetroshareDataDirectory() OSX: " << dataDirectory; + + #else + /* For Linux, we have a fixed standard data directory */ + dataDirectory = "/usr/share/RetroShare"; + std::cerr << "getRetroshareDataDirectory() Linux: " << dataDirectory; + + #endif +#else +// if (RsInitConfig::portable) +// { +// /* For Windows Portable, files must be in the data directory */ +// dataDirectory = "Data"; +// std::cerr << "getRetroshareDataDirectory() WINDOWS PORTABLE: " << dataDirectory; +// std::cerr << std::endl; +// } +// else +// { +// /* For Windows: environment variable APPDATA should be suitable */ +// dataDirectory = getenv("APPDATA"); +// dataDirectory += "\\RetroShare"; +// +// std::cerr << "getRetroshareDataDirectory() WINDOWS: " << dataDirectory; +// std::cerr << std::endl; +// } + + /* Use RetroShare's exe dir */ + dataDirectory = "."; +#endif +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + /* Make sure the directory exists, else return emptyString */ + if (!RsDirUtil::checkDirectory(dataDirectory)) + { + std::cerr << "Data Directory not Found: " << dataDirectory << std::endl; + dataDirectory = ""; + } + else + { + std::cerr << "Data Directory Found: " << dataDirectory << std::endl; + } + + return dataDirectory; +} + + + + +/* directories with valid certificates in the expected location */ +bool getAvailableAccounts(std::list &ids) +{ + /* get the directories */ + std::list directories; + std::list::iterator it; + + std::cerr << "getAvailableAccounts()"; + std::cerr << std::endl; + + /* now iterate through the directory... + * directories - flags as old, + * files checked to see if they have changed. (rehashed) + */ + + /* check for the dir existance */ + librs::util::FolderIterator dirIt(RsInitConfig::basedir); + if (!dirIt.isValid()) + { + std::cerr << "Cannot Open Base Dir - No Available Accounts" << std::endl; + exit(1); + } + + struct stat64 buf; + + while (dirIt.readdir()) + { + /* check entry type */ + std::string fname; + dirIt.d_name(fname); + std::string fullname = RsInitConfig::basedir + "/" + fname; +#ifdef FIM_DEBUG + std::cerr << "calling stats on " << fullname < &pgpIds) { + AuthGPG::getAuthGPG()->availableGPGCertificatesWithPrivateKeys(pgpIds); + return 1; +} + +int RsInit::GetPGPLoginDetails(std::string id, std::string &name, std::string &email) +{ + #ifdef GPG_DEBUG + std::cerr << "RsInit::GetPGPLoginDetails for \"" << id << "\"" << std::endl; + #endif + + name = AuthGPG::getAuthGPG()->getGPGName(id); + email = AuthGPG::getAuthGPG()->getGPGEmail(id); + if (name != "") { + return 1; + } else { + return 0; + } +} + +/* + * To prevent several running instances from using the same directory + * simultaneously we have to use a global lock. + * We use a lock file on Unix systems. + * + * Return value: + * 0 : Success + * 1 : Another instance already has the lock + * 2 : Unexpected error + */ +int RsInit::LockConfigDirectory(const std::string& accountDir, std::string& lockFilePath) +{ + const std::string lockFile = accountDir + "/" + "lock"; + + lockFilePath = lockFile; +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + if(RsInitConfig::lockHandle != -1) + close(RsInitConfig::lockHandle); + + // open the file in write mode, create it if necessary, truncate it (it should be empty) + RsInitConfig::lockHandle = open(lockFile.c_str(), O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + if(RsInitConfig::lockHandle == -1) + { + std::cerr << "Could not open lock file " << lockFile.c_str() << std::flush; + perror(NULL); + return 2; + } + + // see "man fcntl" for the details, in short: non blocking lock creation on the whole file contents + struct flock lockDetails; + lockDetails.l_type = F_WRLCK; + lockDetails.l_whence = SEEK_SET; + lockDetails.l_start = 0; + lockDetails.l_len = 0; + + if(fcntl(RsInitConfig::lockHandle, F_SETLK, &lockDetails) == -1) + { + int fcntlErr = errno; + std::cerr << "Could not request lock on file " << lockFile.c_str() << std::flush; + perror(NULL); + + // there's no lock so let's release the file handle immediately + close(RsInitConfig::lockHandle); + RsInitConfig::lockHandle = -1; + + if(fcntlErr == EACCES || fcntlErr == EAGAIN) + return 1; + else + return 2; + } + + return 0; +#else + if (RsInitConfig::lockHandle) { + CloseHandle(RsInitConfig::lockHandle); + } + + std::wstring wlockFile; + librs::util::ConvertUtf8ToUtf16(lockFile, wlockFile); + + // open the file in write mode, create it if necessary + RsInitConfig::lockHandle = CreateFile(wlockFile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + + if (RsInitConfig::lockHandle == INVALID_HANDLE_VALUE) { + DWORD lasterror = GetLastError(); + + std::cerr << "Could not open lock file " << lockFile.c_str() << std::endl; + std::cerr << "Last error: " << lasterror << std::endl << std::flush; + perror(NULL); + + if (lasterror == ERROR_SHARING_VIOLATION || lasterror == ERROR_ACCESS_DENIED) { + return 1; + } + return 2; + } + + return 0; +#endif +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +} + +/* + * Unlock the currently locked profile, if there is one. + * For Unix systems we simply close the handle of the lock file. + */ +void RsInit::UnlockConfigDirectory() +{ +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + if(RsInitConfig::lockHandle != -1) + { + close(RsInitConfig::lockHandle); + RsInitConfig::lockHandle = -1; + } +#else + if(RsInitConfig::lockHandle) + { + CloseHandle(RsInitConfig::lockHandle); + RsInitConfig::lockHandle = NULL; + } +#endif +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +} + + +/* Before any SSL stuff can be loaded, the correct PGP must be selected / generated: + **/ + +bool RsInit::SelectGPGAccount(const std::string& gpgId) +{ + bool retVal = false; + + if (0 < AuthGPG::getAuthGPG() -> GPGInit(gpgId)) + { + retVal = true; + std::cerr << "PGP Auth Success!"; + } + else + std::cerr << "PGP Auth Failed!"; + + std::cerr << " ID: " << gpgId << std::endl; + + return retVal; +} + + +bool RsInit::GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString) { + return AuthGPG::getAuthGPG()->GeneratePGPCertificate(name, email, passwd, pgpId, errString); +} + + + /* Create SSL Certificates */ +bool RsInit::GenerateSSLCertificate(std::string gpg_id, std::string org, std::string loc, std::string country, std::string passwd, std::string &sslId, std::string &errString) +{ + // generate the private_key / certificate. + // save to file. + // + // then load as if they had entered a passwd. + + // check password. + if (passwd.length() < 4) + { + errString = "Password is Unsatisfactory (must be 4+ chars)"; + return false; + } + + int nbits = 2048; + + std::string name = AuthGPG::getAuthGPG()->getGPGName(gpg_id); + + // Create the filename ..... + // Temporary Directory for creating files.... + std::string tmpdir = "TMPCFG"; + + std::string tmpbase = RsInitConfig::basedir + "/" + tmpdir + "/"; + RsInit::setupAccount(tmpbase); + + /* create directory structure */ + + std::string basename = tmpbase + configKeyDir + "/"; + basename += "user"; + + std::string key_name = basename + "_pk.pem"; + std::string cert_name = basename + "_cert.pem"; + + bool gen_ok = false; + + /* Extra step required for SSL + PGP, user must have selected + * or generated a suitable key so the signing can happen. + */ + + X509_REQ *req = GenerateX509Req( + key_name.c_str(), + passwd.c_str(), + name.c_str(), + "", //ui -> gen_email -> value(), + org.c_str(), + loc.c_str(), + "", //ui -> gen_state -> value(), + country.c_str(), + nbits, errString); + + long days = 3000; + X509 *x509 = AuthSSL::getAuthSSL()->SignX509ReqWithGPG(req, days); + + X509_REQ_free(req); + if (x509 == NULL) { + fprintf(stderr,"RsGenerateCert() Couldn't sign ssl certificate. Probably PGP password is wrong.\n"); + return false; + } + + /* save to file */ + if (x509) + { + gen_ok = true; + + /* Print the signed Certificate! */ + BIO *bio_out = NULL; + bio_out = BIO_new(BIO_s_file()); + BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); + + /* Print it out */ + int nmflag = 0; + int reqflag = 0; + + X509_print_ex(bio_out, x509, nmflag, reqflag); + + BIO_flush(bio_out); + BIO_free(bio_out); + + } + else + { + gen_ok = false; + } + + if (gen_ok) + { + /* Save cert to file */ + // open the file. + FILE *out = NULL; + if (NULL == (out = RsDirUtil::rs_fopen(cert_name.c_str(), "w"))) + { + fprintf(stderr,"RsGenerateCert() Couldn't create Cert File"); + fprintf(stderr," : %s\n", cert_name.c_str()); + gen_ok = false; + } + + if (!PEM_write_X509(out,x509)) + { + fprintf(stderr,"RsGenerateCert() Couldn't Save Cert"); + fprintf(stderr," : %s\n", cert_name.c_str()); + gen_ok = false; + } + + fclose(out); + X509_free(x509); + } + + if (!gen_ok) + { + errString = "Generation of Certificate Failed"; + return false; + } + + /* try to load it, and get Id */ + + std::string location; + std::string gpgid; + if (LoadCheckX509(cert_name.c_str(), gpgid, location, sslId) == 0) { + std::cerr << "RsInit::GenerateSSLCertificate() Cannot check own signature, maybe the files are corrupted." << std::endl; + return false; + } + + /* Move directory to correct id */ + std::string finalbase = RsInitConfig::basedir + "/" + sslId + "/"; + /* Rename Directory */ + + std::cerr << "Mv Config Dir from: " << tmpbase << " to: " << finalbase; + std::cerr << std::endl; + + if (!RsDirUtil::renameFile(tmpbase, finalbase)) + { + std::cerr << "rename FAILED" << std::endl; + } + + /* Flag as first time run */ + RsInitConfig::firsttime_run = true; + + { + std::ostringstream out; + out << "RetroShare has Successfully generated"; + out << "a Certficate/Key" << std::endl; + out << "\tCert Located: " << cert_name << std::endl; + out << "\tLocated: " << key_name << std::endl; + std::cerr << out.str(); + } + return true; +} + + +/******************* PRIVATE FNS TO HELP with GEN **************/ +bool RsInit::setupAccount(std::string accountdir) +{ + /* actual config directory isd */ + + std::string subdir1 = accountdir + "/"; + std::string subdir2 = subdir1; + subdir1 += configKeyDir; + subdir2 += configCertDir; + + std::string subdir3 = accountdir + "/"; + subdir3 += "cache"; + + std::string subdir4 = subdir3 + "/"; + std::string subdir5 = subdir3 + "/"; + subdir4 += "local"; + subdir5 += "remote"; + + // fatal if cannot find/create. + std::cerr << "Checking For Directories" << std::endl; + if (!RsDirUtil::checkCreateDirectory(accountdir)) + { + std::cerr << "Cannot Create BaseConfig Dir" << std::endl; + exit(1); + } + if (!RsDirUtil::checkCreateDirectory(subdir1)) + { + std::cerr << "Cannot Create Config/Key Dir" << std::endl; + exit(1); + } + if (!RsDirUtil::checkCreateDirectory(subdir2)) + { + std::cerr << "Cannot Create Config/Cert Dir" << std::endl; + exit(1); + } + if (!RsDirUtil::checkCreateDirectory(subdir3)) + { + std::cerr << "Cannot Create Config/Cache Dir" << std::endl; + exit(1); + } + if (!RsDirUtil::checkCreateDirectory(subdir4)) + { + std::cerr << "Cannot Create Config/Cache/local Dir" << std::endl; + exit(1); + } + if (!RsDirUtil::checkCreateDirectory(subdir5)) + { + std::cerr << "Cannot Create Config/Cache/remote Dir" << std::endl; + exit(1); + } + + return true; +} + + + + + + +/***************************** FINAL LOADING OF SETUP *************************/ + /* Login SSL */ +bool RsInit::LoadPassword(std::string id, std::string inPwd) +{ + /* select configDir */ + + RsInitConfig::preferedId = id; + RsInitConfig::configDir = RsInitConfig::basedir + "/" + id; + RsInitConfig::passwd = inPwd; + + // if(inPwd != "") + // RsInitConfig::havePasswd = true; + + // Create the filename. + std::string basename = RsInitConfig::configDir + "/"; + basename += configKeyDir + "/"; + basename += "user"; + + RsInitConfig::load_key = basename + "_pk.pem"; + RsInitConfig::load_cert = basename + "_cert.pem"; + + return true; +} + + +/** + * Locks the profile directory and tries to finalize the login procedure + * + * Return value: + * 0 : success + * 1 : another instance is already running + * 2 : unexpected error while locking + * 3 : unexpected error while loading certificates + */ +int RsInit::LockAndLoadCertificates(bool autoLoginNT, std::string& lockFilePath) +{ + int retVal = LockConfigDirectory(RsInitConfig::configDir, lockFilePath); + if(retVal != 0) + return retVal; + + retVal = LoadCertificates(autoLoginNT); + if(retVal != 1) { + UnlockConfigDirectory(); + return 3; + } + + return 0; +} + + +/** *************************** FINAL LOADING OF SETUP ************************* + * Requires: + * PGPid to be selected (Password not required). + * CertId to be selected (Password Required). + * + * Return value: + * 0 : unexpected error + * 1 : success + */ +int RsInit::LoadCertificates(bool autoLoginNT) +{ + + if (RsInitConfig::load_cert == "") + { + std::cerr << "RetroShare needs a certificate" << std::endl; + return 0; + } + + if (RsInitConfig::load_key == "") + { + std::cerr << "RetroShare needs a key" << std::endl; + return 0; + } + + //check if password is already in memory + + if(RsInitConfig::passwd == "") + RsLoginHandler::getSSLPassword(RsInitConfig::preferedId,true,RsInitConfig::passwd) ; + else + RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile(RsInitConfig::preferedId,RsInitConfig::passwd) ; + + std::cerr << "RsInitConfig::load_key.c_str() : " << RsInitConfig::load_key.c_str() << std::endl; + + if(0 == AuthSSL::getAuthSSL() -> InitAuth(RsInitConfig::load_cert.c_str(), RsInitConfig::load_key.c_str(), RsInitConfig::passwd.c_str())) + { + std::cerr << "SSL Auth Failed!"; + return 0 ; + } + + if(autoLoginNT) + { + std::cerr << "RetroShare will AutoLogin next time"; + std::cerr << std::endl; + + RsLoginHandler::enableAutoLogin(RsInitConfig::preferedId,RsInitConfig::passwd); + RsInitConfig::autoLogin = true ; + } + + /* wipe out password */ + RsInitConfig::passwd = ""; + create_configinit(RsInitConfig::basedir, RsInitConfig::preferedId); + + return 1; +} +bool RsInit::RsClearAutoLogin() +{ + return RsLoginHandler::clearAutoLogin(RsInitConfig::preferedId); +} +bool RsInit::get_configinit(std::string dir, std::string &id) +{ + // have a config directories. + + // Check for config file. + std::string initfile = dir + "/"; + initfile += configInitFile; + + // open and read in the lines. + FILE *ifd = RsDirUtil::rs_fopen(initfile.c_str(), "r"); + char path[1024]; + int i; + + if (ifd != NULL) + { + if (NULL != fgets(path, 1024, ifd)) + { + for(i = 0; (path[i] != '\0') && (path[i] != '\n'); i++) {} + path[i] = '\0'; + id = path; + } + fclose(ifd); + return true; + } + + // we have now + // 1) checked or created the config dirs. + // 2) loaded the config_init file - if possible. + return false; +} + + +bool RsInit::create_configinit(std::string dir, std::string id) +{ + // Check for config file. + std::string initfile = dir + "/"; + initfile += configInitFile; + + // open and read in the lines. + FILE *ifd = RsDirUtil::rs_fopen(initfile.c_str(), "w"); + + if (ifd != NULL) + { + fprintf(ifd, "%s\n", id.c_str()); + fclose(ifd); + + std::cerr << "Creating Init File: " << initfile << std::endl; + std::cerr << "\tId: " << id << std::endl; + + return true; + } + std::cerr << "Failed To Create Init File: " << initfile << std::endl; + return false; +} + +std::string RsInit::getHomePath() +{ + std::string home; +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS /* UNIX */ + + home = getenv("HOME"); + +#else /* Windows */ + + std::ostringstream out; + char *h2 = getenv("HOMEDRIVE"); + out << "getHomePath() -> $HOMEDRIVE = "; + out << h2 << std::endl; + char *h3 = getenv("HOMEPATH"); + out << "getHomePath() -> $HOMEPATH = "; + out << h3 << std::endl; + + if (h2 == NULL) + { + // Might be Win95/98 + // generate default. + home = "C:\\Retro"; + } + else + { + home = h2; + home += h3; + home += "\\Desktop"; + } + + out << "fltkserver::getHomePath() -> " << home << std::endl; + std::cerr << out.str(); + + // convert to FLTK desired format. + home = RsDirUtil::convertPathToUnix(home); +#endif +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + return home; +} + +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + +bool RsInit::isPortable() +{ +#ifdef WINDOWS_SYS + return RsInitConfig::portable; +#else + return false; +#endif +} + +bool RsInit::isWindowsXP() +{ +#ifdef WINDOWS_SYS + return RsInitConfig::isWindowsXP; +#else + return false; +#endif +} +std::string RsInit::RsConfigKeysDirectory() +{ + return RsInitConfig::basedir + "/" + RsInitConfig::preferedId + "/" + configKeyDir ; +} +std::string RsInit::RsConfigDirectory() +{ + return RsInitConfig::basedir; +} + +std::string RsInit::RsProfileConfigDirectory() +{ + std::string dir = RsInitConfig::basedir + "/" + RsInitConfig::preferedId; + //std::cerr << "RsInit::RsProfileConfigDirectory() returning : " << dir << std::endl; + return dir; +} + +bool RsInit::getStartMinimised() +{ + return RsInitConfig::startMinimised; +} + +std::string RsInit::getRetroShareLink() +{ + return RsInitConfig::RetroShareLink; +} + +int RsInit::getSslPwdLen(){ + return SSLPWD_LEN; +} + +bool RsInit::getAutoLogin(){ + return RsInitConfig::autoLogin; +} + +void RsInit::setAutoLogin(bool autoLogin){ + RsInitConfig::autoLogin = autoLogin; +} + +/* + * + * Init Part of RsServer... needs the private + * variables so in the same file. + * + */ + +#include +//#include + +#include "dbase/cachestrapper.h" +#include "ft/ftserver.h" +#include "ft/ftcontroller.h" + +#include "retroshare/rsiface.h" +#include "retroshare/rsturtle.h" + +/* global variable now points straight to + * ft/ code so variable defined here. + */ + +RsControl *rsicontrol = NULL; +RsFiles *rsFiles = NULL; +RsTurtle *rsTurtle = NULL ; + +#include "pqi/pqipersongrp.h" +#include "pqi/pqisslpersongrp.h" +#include "pqi/pqiloopback.h" +#include "pqi/p3cfgmgr.h" + +#include "util/rsdebug.h" +#include "util/rsdir.h" + +#include "upnp/upnphandler.h" +//#include "dht/opendhtmgr.h" + +#include "services/p3disc.h" +#include "services/p3msgservice.h" +#include "services/p3chatservice.h" +#include "services/p3gamelauncher.h" +#include "services/p3photoservice.h" +#include "services/p3forums.h" +#include "services/p3channels.h" +#include "services/p3statusservice.h" +#include "services/p3blogs.h" +#include "turtle/p3turtle.h" + +#ifndef PQI_DISABLE_TUNNEL +#include "services/p3tunnel.h" +#endif + +#include +#include +#include + +// for blocking signals +#include + +/* Implemented Rs Interfaces */ +#include "rsserver/p3face.h" +#include "rsserver/p3peers.h" +#include "rsserver/p3msgs.h" +#include "rsserver/p3discovery.h" +#include "rsserver/p3photo.h" +#include "rsserver/p3status.h" +#include "retroshare/rsgame.h" + +#include "pqi/p3notify.h" // HACK - moved to pqi for compilation order. + +#include "tcponudp/tou.h" +#include "tcponudp/rsudpstack.h" + +#ifdef RS_USE_BITDHT +#include "dht/p3bitdht.h" +#include "udp/udpstack.h" +#include "tcponudp/udppeer.h" +#include "tcponudp/udprelay.h" +#endif + +/**** +#define RS_RELEASE 1 +****/ + +#define RS_RELEASE 1 + + +RsControl *createRsControl(RsIface &iface, NotifyBase ¬ify) +{ + RsServer *srv = new RsServer(iface, notify); + rsicontrol = srv; + return srv; +} + +/* + * The Real RetroShare Startup Function. + */ + +int RsServer::StartupRetroShare() +{ + /**************************************************************************/ + /* STARTUP procedure */ + /**************************************************************************/ + /**************************************************************************/ + /* (1) Load up own certificate (DONE ALREADY) - just CHECK */ + /**************************************************************************/ + + if (1 != AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL)) + { + std::cerr << "main() - Fatal Error....." << std::endl; + std::cerr << "Invalid Certificate configuration!" << std::endl; + std::cerr << std::endl; + exit(1); + } + + std::string ownId = AuthSSL::getAuthSSL()->OwnId(); + + /**************************************************************************/ + /* Any Initial Configuration (Commandline Options) */ + /**************************************************************************/ + + /* set the debugging to crashMode */ + std::cerr << "set the debugging to crashMode." << std::endl; + if ((!RsInitConfig::haveLogFile) && (!RsInitConfig::outStderr)) + { + std::string crashfile = RsInitConfig::basedir + "/"; + crashfile += ownId + "/" + configLogFileName; + setDebugCrashMode(crashfile.c_str()); + } + + unsigned long flags = 0; + if (RsInitConfig::udpListenerOnly) + { + flags |= PQIPERSON_NO_LISTENER; + } + + /**************************************************************************/ + // Load up Certificates, and Old Configuration (if present) + std::cerr << "Load up Certificates, and Old Configuration (if present)." << std::endl; + + std::string emergencySaveDir = RsInitConfig::configDir.c_str(); + std::string emergencyPartialsDir = RsInitConfig::configDir.c_str(); + if (emergencySaveDir != "") + { + emergencySaveDir += "/"; + emergencyPartialsDir += "/"; + } + emergencySaveDir += "Downloads"; + emergencyPartialsDir += "Partials"; + + /**************************************************************************/ + /* setup classes / structures */ + /**************************************************************************/ + std::cerr << "setup classes / structures" << std::endl; + + /* Setup Notify Early - So we can use it. */ + rsNotify = new p3Notify(); + + mConnMgr = new p3ConnectMgr(); + + //load all the SSL certs as friends +// std::list sslIds; +// AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds); +// for (std::list::iterator sslIdsIt = sslIds.begin(); sslIdsIt != sslIds.end(); sslIdsIt++) { +// mConnMgr->addFriend(*sslIdsIt); +// } + pqiNetAssistFirewall *mUpnpMgr = new upnphandler(); + //p3DhtMgr *mDhtMgr = new OpenDHTMgr(ownId, mConnMgr, RsInitConfig::configDir); +/**************************** BITDHT ***********************************/ + + // Make up an address. XXX + + struct sockaddr_in tmpladdr; + sockaddr_clear(&tmpladdr); + tmpladdr.sin_port = htons(RsInitConfig::port); + rsUdpStack *mUdpStack = new rsUdpStack(tmpladdr); + +#ifdef RS_USE_BITDHT + +#define BITDHT_BOOTSTRAP_FILENAME "bdboot.txt" + + + std::string bootstrapfile = RsInitConfig::configDir.c_str(); + if (bootstrapfile != "") + { + bootstrapfile += "/"; + } + bootstrapfile += BITDHT_BOOTSTRAP_FILENAME; + + std::cerr << "Checking for DHT bootstrap file: " << bootstrapfile << std::endl; + + /* check if bootstrap file exists... + * if not... copy from dataDirectory + */ + + if (!RsDirUtil::checkFile(bootstrapfile)) + { + std::cerr << "DHT bootstrap file not in ConfigDir: " << bootstrapfile << std::endl; + std::string installfile = RsInit::getRetroshareDataDirectory(); + installfile += "/"; + installfile += BITDHT_BOOTSTRAP_FILENAME; + + std::cerr << "Checking for Installation DHT bootstrap file " << installfile << std::endl; + if ((installfile != "") && (RsDirUtil::checkFile(installfile))) + { + std::cerr << "Copying Installation DHT bootstrap file..." << std::endl; + if (RsDirUtil::copyFile(installfile, bootstrapfile)) + { + std::cerr << "Installed DHT bootstrap file in configDir" << std::endl; + } + else + { + std::cerr << "Failed Installation DHT bootstrap file..." << std::endl; + } + } + else + { + std::cerr << "No Installation DHT bootstrap file to copy" << std::endl; + } + } + + /* construct the rest of the stack, important to build them in the correct order! */ + /* MOST OF THIS IS COMMENTED OUT UNTIL THE REST OF libretroshare IS READY FOR IT! */ + + UdpSubReceiver *udpReceivers[3]; + int udpTypes[3]; + + // FIRST DHT STUNNER. + UdpStunner *mDhtStunner = new UdpStunner(mUdpStack); + mDhtStunner->setTargetStunPeriod(0); /* passive */ + //mDhtStunner->setTargetStunPeriod(300); /* slow (5mins) */ + mUdpStack->addReceiver(mDhtStunner); + + // NEXT BITDHT. + p3BitDht *mBitDht = new p3BitDht(ownId, mConnMgr, mUdpStack, bootstrapfile); + + // NEXT THE RELAY (NEED to keep a reference for installing RELAYS) + //UdpRelayReceiver *mRelayRecver = new UdpRelayReceiver(mUdpStack); + //udpReceivers[2] = mRelayRecver; /* RELAY Connections (DHT Port) */ + //udpTypes[2] = TOU_RECEIVER_TYPE_UDPRELAY; + //mUdpStack->addReceiver(udpReceivers[2]); + + // LAST ON THIS STACK IS STANDARD DIRECT TOU + udpReceivers[0] = new UdpPeerReceiver(mUdpStack); /* standard DIRECT Connections (DHT Port) */ + udpTypes[0] = TOU_RECEIVER_TYPE_UDPPEER; + mUdpStack->addReceiver(udpReceivers[0]); + + // NOW WE BUILD THE SECOND STACK. + // Create the Second UdpStack... Port should be random (but openable!). + //struct sockaddr_in sndladdr; + //sockaddr_clear(&sndladdr); + //sndladdr.sin_port = htons(RsInitConfig::port + 1111); + //rsUdpStack *mUdpProxyStack = new rsUdpStack(sndladdr); + + // FIRSTLY THE PROXY STUNNER. + //UdpStunner *mProxyStunner = new UdpStunner(mUdpProxyStack); + // USE DEFAULT PERIOD... mDhtStunner->setTargetStunPeriod(300); /* slow (5mins) */ + //mUdpStack->addReceiver(mDhtStunner); + + + // FINALLY THE PROXY UDP CONNECTIONS + //udpReceivers[1] = new UdpPeerReceiver(mUdpProxyStack); /* PROXY Connections (Alt UDP Port) */ + //udpTypes[1] = TOU_RECEIVER_TYPE_UDPPEER; + //mUdpProxyStack->addReceiver(udpReceivers[1]); + + + // NOW WE CAN PASS THE RECEIVERS TO TOU. + // temp initialisation of only the DIRECT TOU. + tou_init((void **) udpReceivers, udpTypes, 1); + + // REAL INITIALISATION - WITH THREE MODES - FOR LATER. + //tou_init((void **) udpReceivers, udpTypes, 3); + +#endif + + +/**************************** BITDHT ***********************************/ + + + SecurityPolicy *none = secpolicy_create(); + pqih = new pqisslpersongrp(none, flags); + //pqih = new pqipersongrpDummy(none, flags); + + /****** New Ft Server **** !!! */ + ftserver = new ftServer(mConnMgr); + ftserver->setP3Interface(pqih); + ftserver->setConfigDirectory(RsInitConfig::configDir); + + ftserver->SetupFtServer(&(getNotify())); + CacheStrapper *mCacheStrapper = ftserver->getCacheStrapper(); + CacheTransfer *mCacheTransfer = ftserver->getCacheTransfer(); + + /* setup any extra bits (Default Paths) */ + ftserver->setPartialsDirectory(emergencyPartialsDir); + ftserver->setDownloadDirectory(emergencySaveDir); + + /* This should be set by config ... there is no default */ + //ftserver->setSharedDirectories(fileList); + rsFiles = ftserver; + + + mConfigMgr = new p3ConfigMgr(RsInitConfig::configDir, "rs-v0.5.cfg", "rs-v0.5.sgn"); + mGeneralConfig = new p3GeneralConfig(); + + /* create Cache Services */ + std::string config_dir = RsInitConfig::configDir; + std::string localcachedir = config_dir + "/cache/local"; + std::string remotecachedir = config_dir + "/cache/remote"; + std::string channelsdir = config_dir + "/channels"; + std::string blogsdir = config_dir + "/blogs"; + std::string forumdir = config_dir + "/forums"; + + std::vector plugins_directories ; + +#ifndef WINDOWS_SYS + plugins_directories.push_back(std::string("/usr/lib/retroshare/extensions/")) ; +#endif + plugins_directories.push_back(RsInitConfig::basedir + "/extensions/") ; +#ifdef DEBUG_PLUGIN_SYSTEM + plugins_directories.push_back(".") ; // this list should be saved/set to some correct value. + // possible entries include: /usr/lib/retroshare, ~/.retroshare/extensions/, etc. +#endif + + RsPluginManager *mPluginsManager = new RsPluginManager ; + rsPlugins = mPluginsManager ; + + // These are needed to load plugins: plugin devs might want to know the place of + // cache directories, get pointers to cache strapper, or access ownId() + // + mPluginsManager->setCacheDirectories(localcachedir,remotecachedir) ; + mPluginsManager->setFileServer(ftserver) ; + mPluginsManager->setConnectMgr(mConnMgr) ; + + // Now load the plugins. This parses the available SO/DLL files for known symbols. + // + mPluginsManager->loadPlugins(plugins_directories) ; + + /* create Services */ + ad = new p3disc(mConnMgr, pqih); +#ifndef MINIMAL_LIBRS + msgSrv = new p3MsgService(mConnMgr); + chatSrv = new p3ChatService(mConnMgr); + mStatusSrv = new p3StatusService(mConnMgr); +#endif // MINIMAL_LIBRS + +#ifndef PQI_DISABLE_TUNNEL + p3tunnel *tn = new p3tunnel(mConnMgr, pqih); + pqih -> addService(tn); + mConnMgr->setP3tunnel(tn); +#endif + + p3turtle *tr = new p3turtle(mConnMgr,ftserver) ; + rsTurtle = tr ; + pqih -> addService(tr); + ftserver->connectToTurtleRouter(tr) ; + + pqih -> addService(ad); +#ifndef MINIMAL_LIBRS + pqih -> addService(msgSrv); + pqih -> addService(chatSrv); + pqih ->addService(mStatusSrv); + +#endif // MINIMAL_LIBRS +#ifndef MINIMAL_LIBRS + + mForums = new p3Forums(RS_SERVICE_TYPE_FORUM, mCacheStrapper, mCacheTransfer, localcachedir, remotecachedir, forumdir); + + mCacheStrapper -> addCachePair( CachePair(mForums, mForums, CacheId(RS_SERVICE_TYPE_FORUM, 0))); + pqih -> addService(mForums); /* This must be also ticked as a service */ + + mChannels = new p3Channels(RS_SERVICE_TYPE_CHANNEL, mCacheStrapper, mCacheTransfer, rsFiles, localcachedir, remotecachedir, channelsdir); + + mCacheStrapper -> addCachePair(CachePair(mChannels, mChannels, CacheId(RS_SERVICE_TYPE_CHANNEL, 0))); + pqih -> addService(mChannels); /* This must be also ticked as a service */ +#ifdef RS_USE_BLOGS + p3Blogs *mBlogs = new p3Blogs(RS_SERVICE_TYPE_QBLOG, mCacheStrapper, mCacheTransfer, rsFiles, localcachedir, remotecachedir, blogsdir); + + mCacheStrapper -> addCachePair(CachePair(mBlogs, mBlogs, CacheId(RS_SERVICE_TYPE_QBLOG, 0))); + pqih -> addService(mBlogs); /* This must be also ticked as a service */ + +#endif + // now add plugin objects inside the loop: + // - client services provided by plugins. + // - cache services provided by plugins. + // + mPluginsManager->registerClientServices(pqih) ; + mPluginsManager->registerCacheServices() ; + +#ifndef RS_RELEASE + p3GameLauncher *gameLauncher = new p3GameLauncher(mConnMgr); + pqih -> addService(gameLauncher); + + p3PhotoService *photoService = new p3PhotoService(RS_SERVICE_TYPE_PHOTO, /* .... for photo service */ + mCacheStrapper, mCacheTransfer, + localcachedir, remotecachedir); + + CachePair cp2(photoService, photoService, CacheId(RS_SERVICE_TYPE_PHOTO, 0)); + mCacheStrapper -> addCachePair(cp2); +#endif +#endif // MINIMAL_LIBRS + + /**************************************************************************/ + +#ifdef RS_USE_BITDHT + mConnMgr->addNetAssistConnect(1, mBitDht); + mConnMgr->addNetListener(mUdpStack); +#endif + mConnMgr->addNetAssistFirewall(1, mUpnpMgr); + + /**************************************************************************/ + /* need to Monitor too! */ + mConnMgr->addMonitor(pqih); + mConnMgr->addMonitor(mCacheStrapper); + mConnMgr->addMonitor(ad); +#ifndef MINIMAL_LIBRS + mConnMgr->addMonitor(msgSrv); + mConnMgr->addMonitor(mStatusSrv); + mConnMgr->addMonitor(chatSrv); +#endif // MINIMAL_LIBRS + + /* must also add the controller as a Monitor... + * a little hack to get it to work. + */ + mConnMgr->addMonitor(((ftController *) mCacheTransfer)); + + + /**************************************************************************/ + + //mConfigMgr->addConfiguration("ftserver.cfg", ftserver); + // + mConfigMgr->addConfiguration("gpg_prefs.cfg", (AuthGPGimpl *) AuthGPG::getAuthGPG()); + mConfigMgr->loadConfiguration(); + + //mConfigMgr->addConfiguration("sslcerts.cfg", AuthSSL::getAuthSSL()); + mConfigMgr->addConfiguration("peers.cfg", mConnMgr); + mConfigMgr->addConfiguration("general.cfg", mGeneralConfig); + mConfigMgr->addConfiguration("cache.cfg", mCacheStrapper); +#ifndef MINIMAL_LIBRS + mConfigMgr->addConfiguration("msgs.cfg", msgSrv); + mConfigMgr->addConfiguration("chat.cfg", chatSrv); +#ifdef RS_USE_BLOGS + mConfigMgr->addConfiguration("blogs.cfg", mBlogs); +#endif + mConfigMgr->addConfiguration("forums.cfg", mForums); + mConfigMgr->addConfiguration("channels.cfg", mChannels); + mConfigMgr->addConfiguration("p3Status.cfg", mStatusSrv); +#endif // MINIMAL_LIBRS + mConfigMgr->addConfiguration("turtle.cfg", tr); + mConfigMgr->addConfiguration("p3disc.cfg", ad); + + mPluginsManager->addConfigurations(mConfigMgr) ; + + ftserver->addConfiguration(mConfigMgr); + + /**************************************************************************/ + /* (2) Load configuration files */ + /**************************************************************************/ + std::cerr << "(2) Load configuration files" << std::endl; + + mConfigMgr->loadConfiguration(); + + /* NOTE: CacheStrapper's load causes Cache Files to be + * loaded into all the CacheStores/Sources. This happens + * after all the other configurations have happened. + */ + + /**************************************************************************/ + /* trigger generalConfig loading for classes that require it */ + /**************************************************************************/ + pqih->setConfig(mGeneralConfig); + + pqih->load_config(); + + /**************************************************************************/ + /* Force Any Configuration before Startup (After Load) */ + /**************************************************************************/ + std::cerr << "Force Any Configuration before Startup (After Load)" << std::endl; + + if (RsInitConfig::forceLocalAddr) + { + struct sockaddr_in laddr; + + /* clean sockaddr before setting values (MaxOSX) */ + sockaddr_clear(&laddr); + + laddr.sin_family = AF_INET; + laddr.sin_port = htons(RsInitConfig::port); + + // universal + laddr.sin_addr.s_addr = inet_addr(RsInitConfig::inet); + + mConnMgr->setLocalAddress(ownId, laddr); + } + + if (RsInitConfig::forceExtPort) + { + mConnMgr->setOwnNetConfig(RS_NET_MODE_EXT, RS_VIS_STATE_STD); + } + +#if 0 + /* must load the trusted_peer before setting up the pqipersongrp */ + if (firsttime_run) + { + /* at this point we want to load and start the trusted peer -> if selected */ + if (load_trustedpeer) + { + /* sslroot does further checks */ + sslr -> loadInitialTrustedPeer(load_trustedpeer_file); + } + } +#endif + + mConnMgr -> checkNetAddress(); + + /**************************************************************************/ + /* startup (stuff dependent on Ids/peers is after this point) */ + /**************************************************************************/ + + pqih->init_listener(); + mConnMgr->addNetListener(pqih); /* add listener so we can reset all sockets later */ + + + + /**************************************************************************/ + /* load caches and secondary data */ + /**************************************************************************/ + + // Clear the News Feeds that are generated by Initial Cache Loading. + + /* Peer stuff is up to date */ + + /* Channel/Forum/Blog stuff will all come from Caches */ + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_CHAN_NEW); + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_CHAN_UPDATE); + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_CHAN_MSG); + + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_FORUM_NEW); + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_FORUM_UPDATE); + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_FORUM_MSG); + + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_BLOG_NEW); + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_BLOG_UPDATE); + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_BLOG_MSG); + + //getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_CHAT_NEW); + getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_MESSAGE); + //getPqiNotify()->ClearFeedItems(RS_FEED_ITEM_FILES_NEW); + + /* flag that the basic Caches are now in the pending Queues */ +#ifndef MINIMAL_LIBRS + mForums->HistoricalCachesDone(); + mChannels->HistoricalCachesDone(); + +#ifdef RS_USE_BLOGS + mBlogs->HistoricalCachesDone(); +#endif +#endif // MINIMAL_LIBRS + + + /**************************************************************************/ + /* Add AuthGPG services */ + /**************************************************************************/ + + AuthGPG::getAuthGPG()->addService(ad); + + /**************************************************************************/ + /* Force Any Last Configuration Options */ + /**************************************************************************/ + + /**************************************************************************/ + /* Start up Threads */ + /**************************************************************************/ + + ftserver->StartupThreads(); + ftserver->ResumeTransfers(); + + //mDhtMgr->start(); +#ifdef RS_USE_BITDHT + mBitDht->start(); +#endif + + // startup the p3distrib threads (for cache loading). +#ifndef MINIMAL_LIBRS + mForums->start(); + mChannels->start(); + +#ifdef RS_USE_BLOGS + mBlogs->start(); +#endif +#endif // MINIMAL_LIBRS + + /**************************************************************************/ + + // create loopback device, and add to pqisslgrp. + + SearchModule *mod = new SearchModule(); + pqiloopback *ploop = new pqiloopback(ownId); + + mod -> peerid = ownId; + mod -> pqi = ploop; + mod -> sp = secpolicy_create(); + + pqih->AddSearchModule(mod); + + /* Setup GUI Interfaces. */ + + rsPeers = new p3Peers(mConnMgr); + rsDisc = new p3Discovery(ad); + +#ifndef MINIMAL_LIBRS + rsMsgs = new p3Msgs(msgSrv, chatSrv); + rsForums = mForums; + rsChannels = mChannels; +#ifdef RS_USE_BLOGS + rsBlogs = mBlogs; +#endif + rsStatus = new p3Status(mStatusSrv); + +#ifndef RS_RELEASE + rsGameLauncher = gameLauncher; + rsPhoto = new p3Photo(photoService); +#else + rsGameLauncher = NULL; + rsPhoto = NULL; +#endif +#endif // MINIMAL_LIBRS + +#ifndef MINIMAL_LIBRS + /* put a welcome message in! */ + if (RsInitConfig::firsttime_run) + { + msgSrv->loadWelcomeMsg(); + ftserver->shareDownloadDirectory(true); + } +#endif // MINIMAL_LIBRS + + // load up the help page + std::string helppage = RsInitConfig::basedir + "/"; + helppage += configHelpName; + + /* Startup this thread! */ + createThread(*this); + + return 1; +} diff --git a/libretroshare/src/rsserver/rsloginhandler.cc b/libretroshare/src/rsserver/rsloginhandler.cc new file mode 100644 index 000000000..5e64999eb --- /dev/null +++ b/libretroshare/src/rsserver/rsloginhandler.cc @@ -0,0 +1,730 @@ +#include +#include +#include +#include +#include "rsloginhandler.h" +#include "util/rsdir.h" + +#ifdef UBUNTU +#include + + GnomeKeyringPasswordSchema my_schema = { + GNOME_KEYRING_ITEM_ENCRYPTION_KEY_PASSWORD, + { + { "RetroShare SSL Id", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { NULL, (GnomeKeyringAttributeType)0 } + } + }; +#endif + + +#ifdef __APPLE__ + /* OSX Headers */ + +#include +#include + +#endif + +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +/* WINDOWS STRUCTURES FOR DPAPI */ + +#ifndef WINDOWS_SYS /* UNIX */ + +#include + +#else +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + +#include +#include +#include + +/* +class CRYPTPROTECT_PROMPTSTRUCT; +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WINDOWS_SYS +#if defined(__CYGWIN__) + +typedef struct _CRYPTPROTECT_PROMPTSTRUCT { + DWORD cbSize; + DWORD dwPromptFlags; + HWND hwndApp; + LPCWSTR szPrompt; +} CRYPTPROTECT_PROMPTSTRUCT, + *PCRYPTPROTECT_PROMPTSTRUCT; + +#endif +#endif + +/* definitions for the two functions */ +__declspec (dllimport) +extern BOOL WINAPI CryptProtectData( + DATA_BLOB* pDataIn, + LPCWSTR szDataDescr, + DATA_BLOB* pOptionalEntropy, + PVOID pvReserved, + /* PVOID prompt, */ + /* CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, */ + CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, + DWORD dwFlags, + DATA_BLOB* pDataOut +); + +__declspec (dllimport) +extern BOOL WINAPI CryptUnprotectData( + DATA_BLOB* pDataIn, + LPWSTR* ppszDataDescr, + DATA_BLOB* pOptionalEntropy, + PVOID pvReserved, + /* PVOID prompt, */ + /* CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, */ + CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, + DWORD dwFlags, + DATA_BLOB* pDataOut +); + +#ifdef __cplusplus +} +#endif + +#endif + + +bool RsLoginHandler::getSSLPassword(const std::string& ssl_id,bool enable_gpg_ask_passwd,std::string& ssl_passwd) +{ + // First, see if autologin is available + // + if(tryAutoLogin(ssl_id,ssl_passwd)) + return true ; + + // If we're not expecting to enter a passwd (e.g. test for autologin before + // display of the login window), safely respond false. + // + if(!enable_gpg_ask_passwd) + return false ; + + return getSSLPasswdFromGPGFile(ssl_id,ssl_passwd) ; +} + +bool RsLoginHandler::tryAutoLogin(const std::string& ssl_id,std::string& ssl_passwd) +{ + std::cerr << "RsTryAutoLogin()" << std::endl; + + /******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS /* UNIX */ +#ifdef UBUNTU + + gchar *passwd = NULL; + + std::cerr << "Using attribute: " << ssl_id << std::endl; + if( gnome_keyring_find_password_sync(&my_schema, &passwd,"RetroShare SSL Id",ssl_id.c_str(),NULL) == GNOME_KEYRING_RESULT_OK ) + { + std::cerr << "Got SSL passwd ********************" /*<< passwd*/ << " from gnome keyring" << std::endl; + ssl_passwd = std::string(passwd); + return true ; + } + else + { + std::cerr << "Could not get passwd from gnome keyring" << std::endl; + return false ; + } + +#else + /******************** OSX KeyChain stuff *****************************/ +#ifdef __APPLE__ + + std::cerr << "RsTryAutoLogin() OSX Version" << std::endl; + //Call SecKeychainFindGenericPassword to get a password from the keychain: + + void *passwordData = NULL; + UInt32 passwordLength = 0; + const char *userId = ssl_id.c_str(); + UInt32 uidLength = strlen(ssl_id.c_str()); + SecKeychainItemRef itemRef = NULL; + + OSStatus status = SecKeychainFindGenericPassword ( + NULL, // default keychain + 10, // length of service name + "Retroshare", // service name + uidLength, // length of account name + userId, // account name + &passwordLength, // length of password + &passwordData, // pointer to password data + &itemRef // the item reference + ); + + std::cerr << "RsTryAutoLogin() SecKeychainFindGenericPassword returned: " << status << std::endl; + + if (status != 0) + { + std::cerr << "RsTryAutoLogin() Error " << std::endl; + + /* error */ + if (status == errSecItemNotFound) + { + //Is password on keychain? + std::cerr << "RsTryAutoLogin() Error - Looks like password is not in KeyChain " << std::endl; + } + } + else + { + std::cerr << "RsTryAutoLogin() Password found on KeyChain! " << std::endl; + + /* load up password to correct location */ + ssl_passwd.clear(); + ssl_passwd.insert(0, (char*)passwordData, passwordLength); + } + + //Free the data allocated by SecKeychainFindGenericPassword: + + SecKeychainItemFreeContent ( + NULL, //No attribute data to release + passwordData //Release data buffer allocated by SecKeychainFindGenericPassword + ); + + if (itemRef) CFRelease(itemRef); + + return (status == 0); + + /******************** OSX KeyChain stuff *****************************/ +#else /* UNIX, but not UBUNTU or APPLE */ + + FILE* helpFile = RsDirUtil::rs_fopen(getAutologinFileName.c_str(), "r"); + + if(helpFile == NULL){ + std::cerr << "\nFailed to open help file\n" << std::endl; + return false; + } + + /* decrypt help */ + + int c ; + std::string passwd ; + while( (c = getc(helpFile)) != EOF ) + passwd += (char)c ; + + const int DAT_LEN = passwd.length(); + const int KEY_DAT_LEN = RsInitConfig::load_cert.length(); + unsigned char* key_data = (unsigned char*)RsInitConfig::load_cert.c_str(); + unsigned char* indata = new unsigned char[DAT_LEN]; + unsigned char* outdata = new unsigned char[DAT_LEN]; + + for(int i=0;iencryptText(plain, cipher)) + { + std::cerr << "Encrypting went ok !" << std::endl; + ok= true ; + } + else + { + std::cerr << "Encrypting went wrong !" << std::endl; + ok= false ; + } + + gpgme_data_release (cipher); + gpgme_data_release (plain); + + fclose(sslPassphraseFile); + + return ok ; +} + +bool RsLoginHandler::getSSLPasswdFromGPGFile(const std::string& ssl_id,std::string& sslPassword) +{ + // Let's read the password from an encrypted file + // Let's check if there's a ssl_passpharese_file that we can decrypt with PGP + // + FILE *sslPassphraseFile = RsDirUtil::rs_fopen(getSSLPasswdFileName(ssl_id).c_str(), "r"); + + if (sslPassphraseFile == NULL) + { + std::cerr << "No password provided, and no sslPassphraseFile : " << getSSLPasswdFileName(ssl_id).c_str() << std::endl; + return 0; + } + + std::cerr << "opening sslPassphraseFile : " << getSSLPasswdFileName(ssl_id).c_str() << std::endl; + + gpgme_data_t cipher; + gpgme_data_t plain; + gpgme_data_new (&plain); + + if( gpgme_data_new_from_stream (&cipher, sslPassphraseFile) != GPG_ERR_NO_ERROR) + { + std::cerr << "Error while creating stream from ssl passwd file." << std::endl ; + return 0 ; + } + if (0 < AuthGPG::getAuthGPG()->decryptText(cipher, plain)) + { + std::cerr << "Decrypting went ok !" << std::endl; + gpgme_data_write (plain, "", 1); + sslPassword = std::string(gpgme_data_release_and_get_mem(plain, NULL)); + std::cerr << "sslpassword: " << "********************" << std::endl; + gpgme_data_release (cipher); + fclose(sslPassphraseFile); + + return true ; + } + else + { + gpgme_data_release (plain); + gpgme_data_release (cipher); + fclose(sslPassphraseFile); + sslPassword = "" ; + std::cerr << "Error : decrypting went wrong !" << std::endl; + + return false; + } +} + + +std::string RsLoginHandler::getSSLPasswdFileName(const std::string& ssl_id) +{ + return RsInit::RsConfigKeysDirectory() + "/" + "ssl_passphrase.pgp"; +} + +std::string RsLoginHandler::getAutologinFileName(const std::string& ssl_id) +{ + return RsInit::RsConfigKeysDirectory() + "/" + "help.dta" ; +} + diff --git a/libretroshare/src/rsserver/rsloginhandler.h b/libretroshare/src/rsserver/rsloginhandler.h new file mode 100644 index 000000000..022100010 --- /dev/null +++ b/libretroshare/src/rsserver/rsloginhandler.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +// This class handles login, meaning that it retrieves the SSL password from either +// the keyring or help.dta file, if autologin is enabled, or from the ssl_passphrase.pgp +// file, asking for the GPG password to decrypt it. +// +// This class should handle the following scenario: +// +// Normal login: +// - SSL key is stored -> do autologin +// - SSL key is not stored +// - if we're actually in the login process, ask for the gpg passwd, and decrypt the key file +// - if we're just trying for autologin, don't ask for the gpg passwd and return null +// +// Key creation: +// - the key should be stored in the gpg file. +// +class RsLoginHandler +{ + public: + // Gets the SSL passwd by any means: try autologin, and look into gpg file if enable_gpg_key_callback==true + // + static bool getSSLPassword(const std::string& ssl_id,bool enable_gpg_key_callback,std::string& ssl_password) ; + + // Checks whether the ssl passwd is already in the gpg file. If the file's not here, the passwd is stored there, + // encrypted with the current GPG key. + // + static bool checkAndStoreSSLPasswdIntoGPGFile(const std::string& ssl_id,const std::string& ssl_passwd) ; + + // Stores the given ssl_id/passwd pair into the keyring, or by default into a file in /[ssl_id]/keys/help.dta + // + static bool enableAutoLogin(const std::string& ssl_id,const std::string& passwd) ; + + // Clears autologin entry. + // + static bool clearAutoLogin(const std::string& ssl_id) ; + + private: + static bool tryAutoLogin(const std::string& ssl_id,std::string& ssl_passwd) ; + static bool getSSLPasswdFromGPGFile(const std::string& ssl_id,std::string& sslPassword) ; + + static std::string getSSLPasswdFileName(const std::string& ssl_id) ; + static std::string getAutologinFileName(const std::string& ssl_id) ; +}; + diff --git a/libretroshare/src/rsserver/rstypes.cc b/libretroshare/src/rsserver/rstypes.cc new file mode 100644 index 000000000..dbfcf531c --- /dev/null +++ b/libretroshare/src/rsserver/rstypes.cc @@ -0,0 +1,60 @@ + +/* + * "$Id: rstypes.cc,v 1.2 2007-04-07 08:41:00 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +/* Insides of RetroShare interface. + * only prints stuff out at the moment + */ + +#include "retroshare/rstypes.h" +#include +#include +#include + + +/********************************************************************** + * NOTE NOTE NOTE ...... XXX + * BUG in MinGW .... %hhx in sscanf overwrites 32bits, instead of 8bits. + * this means that scanf(.... &(data[15])) is running off the + * end of the buffer, and hitting data[15-18]... + * To work around this bug we are reading into proper int32s + * and then copying the data over... + * +**********************************************************************/ + + +std::ostream &operator<<(std::ostream &out, const FileInfo &info) +{ + out << "FileInfo: path: " << info.path; + out << std::endl; + out << "File: " << info.fname; + out << " Size: " << info.size; + out << std::endl; + out << "Hash: " << info.hash; + return out; +} + + diff --git a/libretroshare/src/scripts/checks.mk b/libretroshare/src/scripts/checks.mk new file mode 100644 index 000000000..61d242ef0 --- /dev/null +++ b/libretroshare/src/scripts/checks.mk @@ -0,0 +1,25 @@ +#Basic checks + +ifndef RS_TOP_DIR +dummy: + echo "RS_TOP_DIR is not defined in your makefile" +endif + +ifndef SSL_DIR +dummy: + echo "you must define SSL_DIR before you can compile" + +endif + +ifneq ($(OS),Linux) + ifneq ($(OS),MacOSX) + ifndef PTHREADS_DIR +dummy: + echo "you must define PTHREADS_DIR before you can compile" + + endif + endif +endif + + + diff --git a/libretroshare/src/scripts/config-cygwin.mk b/libretroshare/src/scripts/config-cygwin.mk new file mode 100644 index 000000000..ec4518f68 --- /dev/null +++ b/libretroshare/src/scripts/config-cygwin.mk @@ -0,0 +1,118 @@ +ifneq ($(OS),Cygwin) +dummy: + echo "ERROR Cygwin configuration file included, but (OS != Cygwin) + +endif + +############ LINUX CONFIGURATION ######################## + +# flags for components.... +PQI_USE_XPGP = 1 +#PQI_USE_PROXY = 1 +#PQI_USE_CHANNELS = 1 +#USE_FILELOOK = 1 + +########################################################################### + +#### DrBobs Versions.... Please Don't Delete. +### Comment out if needed. +ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW +SRC_ROOT=../../../.. + +PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2 + +################### + +#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src +#SRC_ROOT=/cygdrive/c/RetroShareBuild/src + +#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release + +################### + +ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3 + +SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c +UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 + +include $(RS_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ######################## + +CC = g++ +RM = /bin/rm +RANLIB = ranlib +LIBDIR = $(RS_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +# Unix: Linux/Cygwin +INCLUDE = -I $(RS_TOP_DIR) + +ifdef PQI_DEBUG + CFLAGS = -Wall -g $(INCLUDE) +else + CFLAGS = -Wall -O2 $(INCLUDE) +endif + +ifdef PQI_USE_XPGP + INCLUDE += -I $(SSL_DIR)/include +endif + +ifdef PQI_USE_XPGP + CFLAGS += -DPQI_USE_XPGP +endif + +ifdef PQI_USE_PROXY + CFLAGS += -DPQI_USE_PROXY +endif + +ifdef PQI_USE_CHANNELS + CFLAGS += -DPQI_USE_CHANNELS +endif + +ifdef USE_FILELOOK + CFLAGS += -DUSE_FILELOOK +endif + + +RSCFLAGS = -Wall -g $(INCLUDE) + +######################################################################### +# OS Compile Options +######################################################################### + +# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) +BIOCC = gcc + +# Cygwin - ?same? as Linux flags +BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM + +######################################################################### +# OS specific Linking. +######################################################################### + +# for static pthread libs.... +WININC += -DPTW32_STATIC_LIB +WININC += -mno-cygwin -mwindows -fno-exceptions +WININC += -DWINDOWS_SYS + +WINLIB = -lws2_32 -luuid -lole32 -liphlpapi +WINLIB += -lcrypt32 -lwinmm + +CFLAGS += -I$(PTHREADS_DIR) $(WININC) +CFLAGS += -I$(ZLIB_DIR) + +LIBS = -L$(LIBDIR) -lretroshare +ifdef PQI_USE_XPGP + LIBS += -L$(SSL_DIR) +endif + +LIBS += -lssl -lcrypto +LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += -L$(ZLIB_DIR) -lz +LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d +LIBS += $(WINLIB) + +RSCFLAGS += $(WININC) + + diff --git a/libretroshare/src/scripts/config-linux.mk b/libretroshare/src/scripts/config-linux.mk new file mode 100644 index 000000000..e82e903c2 --- /dev/null +++ b/libretroshare/src/scripts/config-linux.mk @@ -0,0 +1,98 @@ + +ifneq ($(OS),Linux) +dummy: + echo "ERROR Linux configuration file included, but (OS != Linux) + +endif + +############ LINUX CONFIGURATION ######################## + +# flags for components.... +#PQI_USE_SSLONLY = 1 +#PQI_USE_XPGP = 1 + + +#PQI_USE_PROXY = 1 +#PQI_USE_CHANNELS = 1 +#USE_FILELOOK = 1 + +SSL_DIR=../../../../openssl-0.9.7g-xpgp-0.1c +UPNPC_DIR=../../../../miniupnpc-1.0 + +# Need to define miniupnpc version because API changed a little between v1.0 and 1.2 +# put 10 for 1.0 and 12 for 1.2 +DEFINES += -DMINIUPNPC_VERSION=10 + +include $(RS_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ######################## + +CC = g++ +RM = /bin/rm +RANLIB = ranlib +LIBDIR = $(RS_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +# Unix: Linux/Cygwin +INCLUDE = -I $(RS_TOP_DIR) +#-I$(KADC_DIR) +CFLAGS = -Wall -g $(INCLUDE) +CFLAGS += ${DEFINES} + +ifdef PQI_USE_XPGP + INCLUDE += -I $(SSL_DIR)/include +endif + +ifdef PQI_USE_XPGP + CFLAGS += -DPQI_USE_XPGP +endif + +ifdef PQI_USE_SSLONLY + CFLAGS += -DPQI_USE_SSLONLY +endif + +ifdef PQI_USE_PROXY + CFLAGS += -DPQI_USE_PROXY +endif + +ifdef PQI_USE_CHANNELS + CFLAGS += -DPQI_USE_CHANNELS +endif + +ifdef USE_FILELOOK + CFLAGS += -DUSE_FILELOOK +endif + + +RSCFLAGS = -Wall -g $(INCLUDE) +######################################################################### +# OS Compile Options +######################################################################### + +# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) +BIOCC = gcc + +# march=i686 causes problems while 64Bit compiling, GCC tries to generate Output for a m64 machine, but the marchi686 +# doesnt allow the instructionfs for that. +# +# gcc docu: http://gcc.gnu.org/onlinedocs/gcc-4.0.3/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options + +# Linux flags +BIOCFLAGS = -I $(SSL_DIR)/include ${DEFINES} -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM + +######################################################################### +# OS specific Linking. +######################################################################### + +LIBS = -L$(LIBDIR) -lretroshare +ifdef PQI_USE_XPGP + LIBS += -L$(SSL_DIR) + endif +LIBS += -lssl -lcrypto -lpthread +LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += $(XLIB) -ldl -lz +LIBS += -lgpgme + +RSLIBS = $(LIBS) + + diff --git a/libretroshare/src/scripts/config-macosx.mk b/libretroshare/src/scripts/config-macosx.mk new file mode 100644 index 000000000..7aa56d361 --- /dev/null +++ b/libretroshare/src/scripts/config-macosx.mk @@ -0,0 +1,152 @@ + +ifneq ($(OS),MacOSX) +dummy: + echo "ERROR MacOSX configuration file included, but (OS != MacOSX) + +endif + +############ LINUX CONFIGURATION ######################## + + +# FLAGS to decide if we want i386 Build or ppc Build +# +# + +# PPC is default +# Could define both for combined compilation... +# except might not work for bio_tou.c file! +# +# MAC_I386_BUILD = 1 +# MAC_PPC_BUILD = 1 + +#MAC_I386_BUILD = 1 +#MAC_PPC_BUILD = 1 + +ifndef MAC_I386_BUILD + MAC_PPC_BUILD = 1 +endif + +# flags for components.... +#PQI_USE_SSLONLY = 1 +#PQI_USE_XPGP = 1 + +#PQI_USE_PROXY = 1 +#PQI_USE_CHANNELS = 1 +#USE_FILELOOK = 1 + +SSL_DIR=../../../../../src/openssl-0.9.7g-xpgp-0.1c +UPNPC_DIR=../../../../../src/miniupnpc-1.0 + +include $(RS_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ######################## + +CC = g++ +RM = /bin/rm + +RANLIB = ranlib + +# Dummy ranlib -> can't do it until afterwards with universal binaries. +# RANLIB = ls -l + +LIBDIR = $(RS_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +OPT_DIR = /opt/local +OPT_INCLUDE = $(OPT_DIR)/include +OPT_LIBS = $(OPT_DIR)/lib + +INCLUDE = -I $(RS_TOP_DIR) -I $(OPT_INCLUDE) +#CFLAGS = -Wall -O3 +CFLAGS = -Wall -g + +# Flags for architecture builds. +ifdef MAC_I386_BUILD + CFLAGS += -arch i386 +endif + +ifdef MAC_PPC_BUILD + CFLAGS += -arch ppc +endif + +CFLAGS += $(INCLUDE) + +# This Line is for Universal BUILD for 10.4 + 10.5 +# (but unlikely to work unless Qt Libraries are build properly) +# CFLAGS += -isysroot /Developer/SDKs/MacOSX10.4u.sdk + +ifdef PQI_USE_XPGP + INCLUDE += -I $(SSL_DIR)/include + CFLAGS += -DPQI_USE_XPGP +endif + +ifdef PQI_USE_SSLONLY + CFLAGS += -DPQI_USE_SSLONLY +endif + +ifdef PQI_USE_PROXY + CFLAGS += -DPQI_USE_PROXY +endif + +ifdef PQI_USE_CHANNELS + CFLAGS += -DPQI_USE_CHANNELS +endif + +ifdef USE_FILELOOK + CFLAGS += -DUSE_FILELOOK +endif + + +# RSCFLAGS = -Wall -O3 $(INCLUDE) + +######################################################################### +# OS Compile Options +######################################################################### + +# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) +BIOCC = gcc + + +# Flags for architecture builds. +ifdef MAC_I386_BUILD + BIOCFLAGS = -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common +endif + +ifdef MAC_PPC_BUILD + BIOCFLAGS = -arch ppc -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN +endif + + + +# MacOSX flags +# BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN + +# This is for the Universal Build... +# but is unlikely to work... as options are PPC specific.... +# +# BIOCFLAGS = -arch ppc -arch i386 -I $(SSL_DIR)/include -DOPENSSL_SYSNAME_MACOSX -DOPENSSL_THREADS -D_REENTRANT -DOPENSSL_NO_KRB5 -O3 -fomit-frame-pointer -fno-common -DB_ENDIAN + + +######################################################################### +# OS specific Linking. +######################################################################### + +LIBS = -Wl,-search_paths_first + +# for Univeral BUILD +# LIBS += -arch ppc -arch i386 +# LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 + +LIBS += -L$(LIBDIR) -lretroshare +ifdef PQI_USE_XPGP + LIBS += -L$(SSL_DIR) + endif +LIBS += -lssl -lcrypto -lpthread +LIBS += -L$(OPT_LIBS) +LIBS += -lgpgme -lgpg-error +LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += $(XLIB) -ldl -lz + +RSLIBS = $(LIBS) + + diff --git a/libretroshare/src/scripts/config-mingw.mk b/libretroshare/src/scripts/config-mingw.mk new file mode 100644 index 000000000..c0040ac4e --- /dev/null +++ b/libretroshare/src/scripts/config-mingw.mk @@ -0,0 +1,138 @@ +#ifneq ($(OS),"Win ") +#dummy: +# echo "ERROR OS = $(OS)" +# echo "ERROR MinGW configuration file included, but (OS != Win) +# +#endif + +############ LINUX CONFIGURATION ######################## + +# flags for components.... +#PQI_USE_XPGP = 1 +#PQI_USE_PROXY = 1 +#PQI_USE_CHANNELS = 1 +#USE_FILELOOK = 1 + +########################################################################### + +#### DrBobs Versions.... Please Don't Delete. +### Comment out if needed. +SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src +SRC_ROOT_GPG=/local + +#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW +#SRC_ROOT=../../../.. + +PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2 +ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3 +SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp +UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3 + +########################################################################### + +#### Enable this section for compiling with MSYS/MINGW compile +#SRC_ROOT=/home/linux + +#SSL_DIR=$(SRC_ROOT)/OpenSSL +#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 +#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 + +#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 +#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 +#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release + +include $(RS_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ####################################### + +CC = g++ +RM = /bin/rm +RANLIB = ranlib +LIBDIR = $(RS_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +# Unix: Linux/Cygwin +INCLUDE = -I $(RS_TOP_DIR) + +ifdef PQI_DEBUG + CFLAGS = -Wall -g $(INCLUDE) +else + CFLAGS = -Wall -O2 $(INCLUDE) +endif + +# These aren't used anymore.... really. +ifdef PQI_USE_XPGP + CFLAGS += -DPQI_USE_XPGP +endif + +ifdef PQI_USE_PROXY + CFLAGS += -DPQI_USE_PROXY +endif + +ifdef PQI_USE_CHANNELS + CFLAGS += -DPQI_USE_CHANNELS +endif + +ifdef USE_FILELOOK + CFLAGS += -DUSE_FILELOOK +endif + + +# SSL / pthreads / Zlib +# included by default for Windows compilation. +INCLUDE += -I $(SSL_DIR)/include +INCLUDE += -I$(PTHREADS_DIR) +INCLUDE += -I$(ZLIB_DIR) + + +######################################################################### +# OS Compile Options +######################################################################### + +# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) +BIOCC = gcc + +# Cygwin - ?same? as Linux flags +BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM +BIOCFLAGS += -DWINDOWS_SYS + +######################################################################### +# OS specific Linking. +######################################################################### + +# for static pthread libs.... +#WININC += -DPTW32_STATIC_LIB +#WININC += -mno-cygwin -mwindows -fno-exceptions + +WININC += -DWINDOWS_SYS + +WINLIB = -lws2_32 -luuid -lole32 -liphlpapi +WINLIB += -lcrypt32 -lwinmm + +CFLAGS += -I$(SSL_DIR)/include +CFLAGS += -I$(PTHREADS_DIR)/include +CFLAGS += -I$(ZLIB_DIR) +CFLAGS += -I$(SRC_ROOT_GPG)/include + +### Enable this for GPGME and GPG ERROR dirs +#CFLAGS += -I$(GPGME_DIR)/src +#CFLAGS += -I$(GPG_ERROR_DIR)/src + +CFLAGS += $(WININC) + + + +LIBS = -L$(LIBDIR) -lretroshare + +LIBS += -L$(SSL_DIR) + +LIBS += -lssl -lcrypto +LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += -L$(ZLIB_DIR) -lz +LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d +LIBS += $(WINLIB) + +#RSCFLAGS = -Wall -g $(INCLUDE) +#RSCFLAGS += $(WININC) + + diff --git a/libretroshare/src/scripts/config.mk b/libretroshare/src/scripts/config.mk new file mode 100644 index 000000000..9f22fa363 --- /dev/null +++ b/libretroshare/src/scripts/config.mk @@ -0,0 +1,27 @@ + +# determine which operating system +# +########################################################################### +#Define OS. +# +OS = Linux +#OS = MacOSX +#OS = Cygwin +#OS = Win # MinGw. +########################################################################### + +ifeq ($(OS),Linux) + include $(RS_TOP_DIR)/scripts/config-linux.mk +else + ifeq ($(OS),MacOSX) + include $(RS_TOP_DIR)/scripts/config-macosx.mk + else + ifeq ($(OS),Cygwin) + include $(RS_TOP_DIR)/scripts/config-cygwin.mk + else + include $(RS_TOP_DIR)/scripts/config-mingw.mk + endif + endif +endif + +########################################################################### diff --git a/libretroshare/src/scripts/documentation-script b/libretroshare/src/scripts/documentation-script new file mode 100755 index 000000000..0d47217bc --- /dev/null +++ b/libretroshare/src/scripts/documentation-script @@ -0,0 +1,16 @@ + +#!/bin/bash +# This script creates a doxygen documentation of retroshare +# you need to install doxygen and graph-viz(dot tool) for script to work + + +echo "doxygen and graph viz must be installed" + +# create documentation +doxygen rsDocumentation || exit + +#indicate finshed +echo "complete" + + + diff --git a/libretroshare/src/scripts/makeMacUniversalLibrary.sh b/libretroshare/src/scripts/makeMacUniversalLibrary.sh new file mode 100755 index 000000000..b1222d049 --- /dev/null +++ b/libretroshare/src/scripts/makeMacUniversalLibrary.sh @@ -0,0 +1,35 @@ +# +## clean up all bits of libretroshare +echo make clobber +make clobber +# +## make the standard version (PPC) +echo make librs +make librs +# +LIB=libretroshare.a +LIB_PPC=libretroshare_ppc.a +LIB_X86=libretroshare_x86.a + +MAC_SCRIPT="./scripts/config-macosx.mk" + +echo cp lib/$LIB lib/$LIB_PPC +cp lib/$LIB lib/$LIB_PPC + +echo make clobber +make clobber + +echo make "MAC_I386_BUILD=1" librs +make "MAC_I386_BUILD=1" librs + +echo cp lib/$LIB lib/$LIB_X86 +cp lib/$LIB lib/$LIB_X86 + +# magic combine trick. +echo cd lib +cd lib + +echo lipo -create libretroshare_*.a -output $LIB +lipo -create libretroshare_*.a -output $LIB + + diff --git a/libretroshare/src/scripts/regress.mk b/libretroshare/src/scripts/regress.mk new file mode 100644 index 000000000..f80b48451 --- /dev/null +++ b/libretroshare/src/scripts/regress.mk @@ -0,0 +1,25 @@ + +testoutputfiles = $(foreach tt,$(1),$(tt).tstout) + +%.tstout : %.sh + -sh ./$< > $@ 2>&1 + +%.tstout : % + -./$< > $@ 2>&1 + +TESTOUT = $(call testoutputfiles,$(TESTS)) + +.phony : tests regress retest clobber + +tests: $(TESTS) + +regress: $(TESTOUT) + @-echo "--------------- SUCCESS (count):" + @-grep -c SUCCESS $(TESTOUT) + @-echo "--------------- FAILURE REPORTS:" + @-grep FAILURE $(TESTOUT) || echo no failures + @-echo "--------------- end" + +retest: + -/bin/rm $(TESTOUT) + diff --git a/libretroshare/src/scripts/rsDocumentation b/libretroshare/src/scripts/rsDocumentation new file mode 100644 index 000000000..d21dfaa1c --- /dev/null +++ b/libretroshare/src/scripts/rsDocumentation @@ -0,0 +1,281 @@ +# Doxyfile 1.5.3 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = retroshare +PROJECT_NUMBER = 1.0 +OUTPUT_DIRECTORY = ../ +CREATE_SUBDIRS = YES +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class " \ + "The $name widget " \ + "The $name file " \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = ../ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text " +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../ +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.PY +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +HTML_DYNAMIC_SECTIONS = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/libretroshare/src/scripts/rules.mk b/libretroshare/src/scripts/rules.mk new file mode 100644 index 000000000..f8d75c21f --- /dev/null +++ b/libretroshare/src/scripts/rules.mk @@ -0,0 +1,23 @@ + +# defines required / used. +# +# CFLAGS +# +# + +librs: $(RSOBJ) + $(AR) r $(LIBRS) $(RSOBJ) + $(RANLIB) $(LIBRS) + +.cc.o: + $(CC) $(CFLAGS) -c $< + +clean: + -/bin/rm $(RSOBJ) $(EXECOBJ) $(TESTOBJ) + +clobber: clean retest + -/bin/rm $(EXEC) $(TESTS) + + +include $(RS_TOP_DIR)/scripts/regress.mk + diff --git a/libretroshare/src/serialiser/rsbaseitems.cc b/libretroshare/src/serialiser/rsbaseitems.cc new file mode 100644 index 000000000..d98a0fba4 --- /dev/null +++ b/libretroshare/src/serialiser/rsbaseitems.cc @@ -0,0 +1,1278 @@ + +/* + * libretroshare/src/serialiser: rsbaseitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsbaseitems.h" +#include "serialiser/rstlvbase.h" + +/*** + * #define RSSERIAL_DEBUG 1 + * #define DEBUG_TRANSFERS 1 +***/ + + +#ifdef DEBUG_TRANSFERS + #include "util/rsprint.h" +#endif + +#include + +/*************************************************************************/ + +uint32_t RsFileItemSerialiser::size(RsItem *i) +{ + RsFileRequest *rfr; + RsFileData *rfd; + RsFileChunkMapRequest *rfcmr; + RsFileChunkMap *rfcm; + RsFileCRC32MapRequest *rfcrcr; + RsFileCRC32Map *rfcrc; + + if (NULL != (rfr = dynamic_cast(i))) + { + return sizeReq(rfr); + } + else if (NULL != (rfd = dynamic_cast(i))) + { + return sizeData(rfd); + } + else if (NULL != (rfcmr = dynamic_cast(i))) + { + return sizeChunkMapReq(rfcmr); + } + else if (NULL != (rfcm = dynamic_cast(i))) + { + return sizeChunkMap(rfcm); + } + else if (NULL != (rfcrcr = dynamic_cast(i))) + { + return sizeCRC32MapReq(rfcrcr); + } + else if (NULL != (rfcrc = dynamic_cast(i))) + { + return sizeCRC32Map(rfcrc); + } + + return 0; +} + +/* serialise the data to the buffer */ +bool RsFileItemSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ + RsFileRequest *rfr; + RsFileData *rfd; + RsFileChunkMapRequest *rfcmr; + RsFileChunkMap *rfcm; + RsFileCRC32MapRequest *rfcrcr; + RsFileCRC32Map *rfcrc; + + if (NULL != (rfr = dynamic_cast(i))) + { + return serialiseReq(rfr, data, pktsize); + } + else if (NULL != (rfd = dynamic_cast(i))) + { + return serialiseData(rfd, data, pktsize); + } + else if (NULL != (rfcmr = dynamic_cast(i))) + { + return serialiseChunkMapReq(rfcmr,data,pktsize); + } + else if (NULL != (rfcm = dynamic_cast(i))) + { + return serialiseChunkMap(rfcm,data,pktsize); + } + else if (NULL != (rfcrcr = dynamic_cast(i))) + { + return serialiseCRC32MapReq(rfcrcr,data,pktsize); + } + else if (NULL != (rfcrc = dynamic_cast(i))) + { + return serialiseCRC32Map(rfcrc,data,pktsize); + } + return false; +} + +RsItem *RsFileItemSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE != getRsItemType(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_FI_REQUEST: + return deserialiseReq(data, pktsize); + break; + case RS_PKT_SUBTYPE_FI_DATA: + return deserialiseData(data, pktsize); + break; + case RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST: + return deserialiseChunkMapReq(data, pktsize); + break; + case RS_PKT_SUBTYPE_FI_CHUNK_MAP: + return deserialiseChunkMap(data, pktsize); + break; + case RS_PKT_SUBTYPE_FI_CRC32_MAP_REQUEST: + return deserialiseCRC32MapReq(data, pktsize); + break; + case RS_PKT_SUBTYPE_FI_CRC32_MAP: + return deserialiseCRC32Map(data, pktsize); + break; + default: + return NULL; + break; + } + return NULL; +} + +/*************************************************************************/ + +RsFileRequest::~RsFileRequest() +{ + return; +} + +void RsFileRequest::clear() +{ + file.TlvClear(); + fileoffset = 0; + chunksize = 0; +} + +std::ostream &RsFileRequest::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileRequest", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "FileOffset: " << fileoffset; + out << " ChunkSize: " << chunksize << std::endl; + file.print(out, int_Indent); + printRsItemEnd(out, "RsFileRequest", indent); + return out; +} + + +uint32_t RsFileItemSerialiser::sizeReq(RsFileRequest *item) +{ + uint32_t s = 8; /* header */ + s += 8; /* offset */ + s += 4; /* chunksize */ + s += item->file.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsFileItemSerialiser::serialiseReq(RsFileRequest *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeReq(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseReq() Header: " << ok << std::endl; + std::cerr << "RsFileItemSerialiser::serialiseReq() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt64(data, tlvsize, &offset, item->fileoffset); + ok &= setRawUInt32(data, tlvsize, &offset, item->chunksize); + ok &= item->file.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseReq() Size Error! " << std::endl; +#endif + } + + /*** Debugging Transfer rates. + * print timestamp, and file details so we can workout packet lags. + ***/ + +#ifdef DEBUG_TRANSFERS + std::cerr << "RsFileItemSerialiser::serialiseReq() at: " << RsUtil::AccurateTimeString() << std::endl; + item->print(std::cerr, 10); +#endif + + return ok; +} + +RsFileRequest *RsFileItemSerialiser::deserialiseReq(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FI_REQUEST != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileRequest *item = new RsFileRequest(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= getRawUInt64(data, rssize, &offset, &(item->fileoffset)); + ok &= getRawUInt32(data, rssize, &offset, &(item->chunksize)); + ok &= item->file.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + + /*** Debugging Transfer rates. + * print timestamp, and file details so we can workout packet lags. + ***/ + +#ifdef DEBUG_TRANSFERS + std::cerr << "RsFileItemSerialiser::deserialiseReq() at: " << RsUtil::AccurateTimeString() << std::endl; + item->print(std::cerr, 10); +#endif + + return item; +} + + +/*************************************************************************/ + +RsFileData::~RsFileData() +{ + return; +} + +void RsFileData::clear() +{ + fd.TlvClear(); +} +std::ostream &RsFileChunkMap::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileChunkMap", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); out << "PeerId: " << PeerId() << std::endl ; + printIndent(out, int_Indent); out << " hash: " << hash << std::endl ; + printIndent(out, int_Indent); out << "chunks: " << (void*)(compressed_map._map[0]) << "..." << std::endl ; + printRsItemEnd(out, "RsFileChunkMap", indent); + return out; +} +std::ostream &RsFileChunkMapRequest::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileChunkMapRequest", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); out << "PeerId: " << PeerId() << std::endl ; + printIndent(out, int_Indent); out << " hash: " << hash << std::endl ; + printRsItemEnd(out, "RsFileChunkMapRequest", indent); + return out; +} +std::ostream& RsFileCRC32Map::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileCRC32Map", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); out << "PeerId: " << PeerId() << std::endl ; + printIndent(out, int_Indent); out << " hash: " << hash << std::endl ; + printIndent(out, int_Indent); out << "chunks: " << (void*)(crc_map._ccmap._map[0]) << "..." << std::endl ; + printRsItemEnd(out, "RsFileCRC32Map", indent); + return out; +} +std::ostream& RsFileCRC32MapRequest::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileCRC32MapRequest", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); out << "PeerId: " << PeerId() << std::endl ; + printIndent(out, int_Indent); out << " hash: " << hash << std::endl ; + printRsItemEnd(out, "RsFileCRC32MapRequest", indent); + return out; +} +std::ostream &RsFileData::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileData", indent); + uint16_t int_Indent = indent + 2; + fd.print(out, int_Indent); + printRsItemEnd(out, "RsFileData", indent); + return out; +} + + +uint32_t RsFileItemSerialiser::sizeData(RsFileData *item) +{ + uint32_t s = 8; /* header */ + s += item->fd.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsFileItemSerialiser::serialiseData(RsFileData *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeData(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= item->fd.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Size Error! " << std::endl; +#endif + } + +#ifdef DEBUG_TRANSFERS + std::cerr << "RsFileItemSerialiser::serialiseData() at: " << RsUtil::AccurateTimeString() << std::endl; + item->print(std::cerr, 10); +#endif + + + return ok; +} + +RsFileData *RsFileItemSerialiser::deserialiseData(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FI_DATA != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileData *item = new RsFileData(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= item->fd.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + +#ifdef DEBUG_TRANSFERS + std::cerr << "RsFileItemSerialiser::deserialiseData() at: " << RsUtil::AccurateTimeString() << std::endl; + item->print(std::cerr, 10); +#endif + + + return item; +} + +uint32_t RsFileItemSerialiser::sizeChunkMapReq(RsFileChunkMapRequest *item) +{ + uint32_t s = 8; /* header */ + s += 1 ; // is_client + s += GetTlvStringSize(item->hash) ; // hash + + return s; +} +uint32_t RsFileItemSerialiser::sizeChunkMap(RsFileChunkMap *item) +{ + uint32_t s = 8; /* header */ + s += 1 ; // is_client + s += GetTlvStringSize(item->hash) ; // hash + s += 4 ; // compressed map size + s += 4 * item->compressed_map._map.size() ; // compressed chunk map + + return s; +} +uint32_t RsFileItemSerialiser::sizeCRC32MapReq(RsFileCRC32MapRequest *item) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(item->hash) ; // hash + + return s; +} +uint32_t RsFileItemSerialiser::sizeCRC32Map(RsFileCRC32Map *item) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(item->hash) ; // hash + s += 4 ; // crc32 map size + s += 4 * item->crc_map._ccmap._map.size() ; // compressed chunk map + s += 4 ; // crc32 map size + s += 4 * item->crc_map._crcs.size() ; // compressed chunk map + + return s; +} +/* serialise the data to the buffer */ +bool RsFileItemSerialiser::serialiseCRC32MapReq(RsFileCRC32MapRequest *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeCRC32MapReq(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->hash); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Size Error! " << std::endl; +#endif + } + + return ok; +} +bool RsFileItemSerialiser::serialiseCRC32Map(RsFileCRC32Map *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeCRC32Map(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->hash); + ok &= setRawUInt32(data, tlvsize, &offset, item->crc_map._ccmap._map.size()); + + for(uint32_t i=0;icrc_map._ccmap._map.size();++i) + ok &= setRawUInt32(data, tlvsize, &offset, item->crc_map._ccmap._map[i]); + + ok &= setRawUInt32(data, tlvsize, &offset, item->crc_map._crcs.size()); + + for(uint32_t i=0;icrc_map._crcs.size();++i) + ok &= setRawUInt32(data, tlvsize, &offset, item->crc_map._crcs[i]); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Size Error! " << std::endl; +#endif + } + + return ok; +} +RsFileCRC32MapRequest *RsFileItemSerialiser::deserialiseCRC32MapReq(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FI_CRC32_MAP_REQUEST != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileCRC32MapRequest *item = new RsFileCRC32MapRequest(); + item->clear(); + + /* skip the header */ + offset += 8; + ok &= GetTlvString(data, *pktsize, &offset, TLV_TYPE_STR_VALUE, item->hash); // file hash + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} +RsFileCRC32Map *RsFileItemSerialiser::deserialiseCRC32Map(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FI_CRC32_MAP != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileCRC32Map *item = new RsFileCRC32Map(); + item->clear(); + + /* skip the header */ + offset += 8; + ok &= GetTlvString(data, *pktsize, &offset, TLV_TYPE_STR_VALUE, item->hash); // file hash + uint32_t size =0; + ok &= getRawUInt32(data, *pktsize, &offset, &size); + + if(ok) + { + item->crc_map._ccmap._map.resize(size) ; + + for(uint32_t i=0;icrc_map._ccmap._map[i])); + } + + uint32_t size2 =0; + ok &= getRawUInt32(data, *pktsize, &offset, &size2); + + if(ok) + { + item->crc_map._crcs.resize(size2) ; + + for(uint32_t i=0;icrc_map._crcs[i])); + } + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/* serialise the data to the buffer */ +bool RsFileItemSerialiser::serialiseChunkMapReq(RsFileChunkMapRequest *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeChunkMapReq(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt8(data, tlvsize, &offset, item->is_client); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->hash); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Size Error! " << std::endl; +#endif + } + + return ok; +} +bool RsFileItemSerialiser::serialiseChunkMap(RsFileChunkMap *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeChunkMap(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt8(data, tlvsize, &offset, item->is_client); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->hash); + ok &= setRawUInt32(data, tlvsize, &offset, item->compressed_map._map.size()); + + for(uint32_t i=0;icompressed_map._map.size();++i) + ok &= setRawUInt32(data, tlvsize, &offset, item->compressed_map._map[i]); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Size Error! " << std::endl; +#endif + } + + return ok; +} +RsFileChunkMapRequest *RsFileItemSerialiser::deserialiseChunkMapReq(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileChunkMapRequest *item = new RsFileChunkMapRequest(); + item->clear(); + + /* skip the header */ + offset += 8; + uint8_t tmp ; + ok &= getRawUInt8(data, *pktsize, &offset, &tmp); item->is_client = tmp; + ok &= GetTlvString(data, *pktsize, &offset, TLV_TYPE_STR_VALUE, item->hash); // file hash + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} +RsFileChunkMap *RsFileItemSerialiser::deserialiseChunkMap(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FI_CHUNK_MAP != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileChunkMap *item = new RsFileChunkMap(); + item->clear(); + + /* skip the header */ + offset += 8; + uint8_t tmp ; + ok &= getRawUInt8(data, *pktsize, &offset, &tmp); item->is_client = tmp; + ok &= GetTlvString(data, *pktsize, &offset, TLV_TYPE_STR_VALUE, item->hash); // file hash + uint32_t size =0; + ok &= getRawUInt32(data, *pktsize, &offset, &size); + + if(ok) + { + item->compressed_map._map.resize(size) ; + + for(uint32_t i=0;icompressed_map._map[i])); + } + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} +/*************************************************************************/ +/*************************************************************************/ + +uint32_t RsCacheItemSerialiser::size(RsItem *i) +{ + RsCacheRequest *rfr; + RsCacheItem *rfi; + + if (NULL != (rfr = dynamic_cast(i))) + { + return sizeReq(rfr); + } + else if (NULL != (rfi = dynamic_cast(i))) + { + return sizeItem(rfi); + } + + return 0; +} + +/* serialise the data to the buffer */ +bool RsCacheItemSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ + RsCacheRequest *rfr; + RsCacheItem *rfi; + + if (NULL != (rfr = dynamic_cast(i))) + { + return serialiseReq(rfr, data, pktsize); + } + else if (NULL != (rfi = dynamic_cast(i))) + { + return serialiseItem(rfi, data, pktsize); + } + + return false; +} + +RsItem *RsCacheItemSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_CACHE != getRsItemType(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_CACHE_REQUEST: + return deserialiseReq(data, pktsize); + break; + case RS_PKT_SUBTYPE_CACHE_ITEM: + return deserialiseItem(data, pktsize); + break; + default: + return NULL; + break; + } + return NULL; +} + +/*************************************************************************/ + +RsCacheRequest::~RsCacheRequest() +{ + return; +} + +void RsCacheRequest::clear() +{ + cacheType = 0; + cacheSubId = 0; + file.TlvClear(); +} + +std::ostream &RsCacheRequest::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsCacheRequest", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "CacheId: " << cacheType << "/" << cacheSubId << std::endl; + file.print(out, int_Indent); + printRsItemEnd(out, "RsCacheRequest", indent); + return out; +} + + +uint32_t RsCacheItemSerialiser::sizeReq(RsCacheRequest *item) +{ + uint32_t s = 8; /* header */ + s += 4; /* type/subid */ + s += item->file.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsCacheItemSerialiser::serialiseReq(RsCacheRequest *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeReq(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsCacheItemSerialiser::serialiseReq() Header: " << ok << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt16(data, tlvsize, &offset, item->cacheType); + ok &= setRawUInt16(data, tlvsize, &offset, item->cacheSubId); + ok &= item->file.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseReq() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsCacheRequest *RsCacheItemSerialiser::deserialiseReq(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_CACHE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_CACHE_REQUEST != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsCacheRequest *item = new RsCacheRequest(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= getRawUInt16(data, rssize, &offset, &(item->cacheType)); + ok &= getRawUInt16(data, rssize, &offset, &(item->cacheSubId)); + ok &= item->file.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +/*************************************************************************/ + + +RsCacheItem::~RsCacheItem() +{ + return; +} + +void RsCacheItem::clear() +{ + cacheType = 0; + cacheSubId = 0; + file.TlvClear(); +} + +std::ostream &RsCacheItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsCacheItem", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "CacheId: " << cacheType << "/" << cacheSubId << std::endl; + file.print(out, int_Indent); + printRsItemEnd(out, "RsCacheItem", indent); + return out; +} + + +uint32_t RsCacheItemSerialiser::sizeItem(RsCacheItem *item) +{ + uint32_t s = 8; /* header */ + s += 4; /* type/subid */ + s += item->file.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsCacheItemSerialiser::serialiseItem(RsCacheItem *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeItem(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsCacheItemSerialiser::serialiseItem() Header: " << ok << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt16(data, tlvsize, &offset, item->cacheType); + ok &= setRawUInt16(data, tlvsize, &offset, item->cacheSubId); + ok &= item->file.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsCacheItem *RsCacheItemSerialiser::deserialiseItem(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_CACHE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_CACHE_ITEM != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsCacheItem *item = new RsCacheItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= getRawUInt16(data, rssize, &offset, &(item->cacheType)); + ok &= getRawUInt16(data, rssize, &offset, &(item->cacheSubId)); + ok &= item->file.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +/*************************************************************************/ +/*************************************************************************/ + +uint32_t RsServiceSerialiser::size(RsItem *i) +{ + RsRawItem *item = dynamic_cast(i); + + if (item) + { + return item->getRawLength(); + } + return 0; +} + +/* serialise the data to the buffer */ +bool RsServiceSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ + RsRawItem *item = dynamic_cast(i); + if (!item) + { + return false; + } + + #ifdef RSSERIAL_DEBUG + std::cerr << "RsServiceSerialiser::serialise() serializing raw item. pktsize : " << *pktsize; + #endif + + uint32_t tlvsize = item->getRawLength(); + #ifdef RSSERIAL_DEBUG + std::cerr << "tlvsize : " << tlvsize << std::endl; + #endif + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + if (tlvsize > getRsPktMaxSize()) + return false; /* packet too big */ + + *pktsize = tlvsize; + + /* its serialised already!!! */ + memcpy(data, item->getRawData(), tlvsize); + + return true; +} + +RsItem *RsServiceSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + if (RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + if (rssize > getRsPktMaxSize()) + return NULL; /* packet too big */ + + /* set the packet length */ + *pktsize = rssize; + + RsRawItem *item = new RsRawItem(rstype, rssize); + void *item_data = item->getRawData(); + + memcpy(item_data, data, rssize); + + return item; +} + + diff --git a/libretroshare/src/serialiser/rsbaseitems.h b/libretroshare/src/serialiser/rsbaseitems.h new file mode 100644 index 000000000..89cd21107 --- /dev/null +++ b/libretroshare/src/serialiser/rsbaseitems.h @@ -0,0 +1,270 @@ +#ifndef RS_BASE_ITEMS_H +#define RS_BASE_ITEMS_H + +/* + * libretroshare/src/serialiser: rsbaseitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "retroshare/rstypes.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +const uint8_t RS_PKT_TYPE_FILE = 0x01; +const uint8_t RS_PKT_TYPE_CACHE = 0x02; + +const uint8_t RS_PKT_SUBTYPE_FI_REQUEST = 0x01; +const uint8_t RS_PKT_SUBTYPE_FI_DATA = 0x02; +const uint8_t RS_PKT_SUBTYPE_FI_TRANSFER = 0x03; +const uint8_t RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST = 0x04; +const uint8_t RS_PKT_SUBTYPE_FI_CHUNK_MAP = 0x05; +const uint8_t RS_PKT_SUBTYPE_FI_CRC32_MAP_REQUEST = 0x06; +const uint8_t RS_PKT_SUBTYPE_FI_CRC32_MAP = 0x07; + +const uint8_t RS_PKT_SUBTYPE_CACHE_ITEM = 0x01; +const uint8_t RS_PKT_SUBTYPE_CACHE_REQUEST = 0x02; + +/**************************************************************************/ + +class RsFileRequest: public RsItem +{ + public: + RsFileRequest() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, + RS_PKT_TYPE_FILE, + RS_PKT_SUBTYPE_FI_REQUEST) + { return; } +virtual ~RsFileRequest(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + uint64_t fileoffset; /* start of data requested */ + uint32_t chunksize; /* size of data requested */ + RsTlvFileItem file; /* file information */ +}; + +/**************************************************************************/ + +class RsFileData: public RsItem +{ + public: + RsFileData() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, + RS_PKT_TYPE_FILE, + RS_PKT_SUBTYPE_FI_DATA) + { return; } +virtual ~RsFileData(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsTlvFileData fd; +}; + +class RsFileChunkMapRequest: public RsItem +{ + public: + RsFileChunkMapRequest() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, RS_PKT_TYPE_FILE, RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST) + {} + virtual ~RsFileChunkMapRequest() {} + virtual void clear() {} + + bool is_client ; // is the request for a client, or a server ? + std::string hash ; // hash of the file for which we request the chunk map + + std::ostream &print(std::ostream &out, uint16_t indent = 0); +}; + +class RsFileChunkMap: public RsItem +{ + public: + RsFileChunkMap() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, RS_PKT_TYPE_FILE, RS_PKT_SUBTYPE_FI_CHUNK_MAP) + {} + virtual ~RsFileChunkMap() {} + virtual void clear() {} + + bool is_client ; // is the request for a client, or a server ? + std::string hash ; // hash of the file for which we request the chunk map + CompressedChunkMap compressed_map ; // Chunk map of the file. + + std::ostream &print(std::ostream &out, uint16_t indent = 0); +}; + +class RsFileCRC32MapRequest: public RsItem +{ + public: + RsFileCRC32MapRequest() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, RS_PKT_TYPE_FILE, RS_PKT_SUBTYPE_FI_CRC32_MAP_REQUEST) + {} + virtual ~RsFileCRC32MapRequest() {} + virtual void clear() {} + + std::string hash ; // hash of the file for which we request the chunk map + + std::ostream &print(std::ostream &out, uint16_t indent = 0); +}; + +class RsFileCRC32Map: public RsItem +{ + public: + RsFileCRC32Map() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, RS_PKT_TYPE_FILE, RS_PKT_SUBTYPE_FI_CRC32_MAP) + {} + virtual ~RsFileCRC32Map() {} + virtual void clear() {} + + std::string hash ; // hash of the file for which we request the chunk map + CRC32Map crc_map ; // CRC32 map of the file. + + std::ostream &print(std::ostream &out, uint16_t indent = 0); +}; +/**************************************************************************/ + +class RsFileItemSerialiser: public RsSerialType +{ + public: + RsFileItemSerialiser() + :RsSerialType(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, + RS_PKT_TYPE_FILE) + { return; } + virtual ~RsFileItemSerialiser() { return; } + + virtual uint32_t size(RsItem *); + virtual bool serialise (RsItem *item, void *data, uint32_t *size); + virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + + /* sub types */ + virtual uint32_t sizeReq(RsFileRequest *); + virtual uint32_t sizeData(RsFileData *); + virtual uint32_t sizeChunkMapReq(RsFileChunkMapRequest *); + virtual uint32_t sizeChunkMap(RsFileChunkMap *); + virtual uint32_t sizeCRC32MapReq(RsFileCRC32MapRequest *); + virtual uint32_t sizeCRC32Map(RsFileCRC32Map *); + + virtual bool serialiseReq (RsFileRequest *item, void *data, uint32_t *size); + virtual bool serialiseData (RsFileData *item, void *data, uint32_t *size); + virtual bool serialiseChunkMapReq(RsFileChunkMapRequest *item, void *data, uint32_t *size); + virtual bool serialiseChunkMap(RsFileChunkMap *item, void *data, uint32_t *size); + virtual bool serialiseCRC32MapReq(RsFileCRC32MapRequest *item, void *data, uint32_t *size); + virtual bool serialiseCRC32Map(RsFileCRC32Map *item, void *data, uint32_t *size); + + virtual RsFileRequest *deserialiseReq(void *data, uint32_t *size); + virtual RsFileData *deserialiseData(void *data, uint32_t *size); + virtual RsFileChunkMapRequest *deserialiseChunkMapReq(void *data, uint32_t *size); + virtual RsFileChunkMap *deserialiseChunkMap(void *data, uint32_t *size); + virtual RsFileCRC32MapRequest *deserialiseCRC32MapReq(void *data, uint32_t *size); + virtual RsFileCRC32Map *deserialiseCRC32Map(void *data, uint32_t *size); +}; + +/**************************************************************************/ + +class RsCacheRequest: public RsItem +{ + public: + RsCacheRequest() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, + RS_PKT_TYPE_CACHE, + RS_PKT_SUBTYPE_CACHE_REQUEST) + { return; } +virtual ~RsCacheRequest(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + uint16_t cacheType; + uint16_t cacheSubId; + RsTlvFileItem file; /* file information */ +}; + +/**************************************************************************/ + +class RsCacheItem: public RsItem +{ + public: + RsCacheItem() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, + RS_PKT_TYPE_CACHE, + RS_PKT_SUBTYPE_CACHE_ITEM) + { return; } +virtual ~RsCacheItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + uint16_t cacheType; + uint16_t cacheSubId; + RsTlvFileItem file; /* file information */ +}; + +/**************************************************************************/ + +class RsCacheItemSerialiser: public RsSerialType +{ + public: + RsCacheItemSerialiser() + :RsSerialType(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, + RS_PKT_TYPE_CACHE) + { return; } +virtual ~RsCacheItemSerialiser() { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + + /* sub types */ +virtual uint32_t sizeReq(RsCacheRequest *); +virtual bool serialiseReq (RsCacheRequest *item, void *data, uint32_t *size); +virtual RsCacheRequest * deserialiseReq(void *data, uint32_t *size); + +virtual uint32_t sizeItem(RsCacheItem *); +virtual bool serialiseItem (RsCacheItem *item, void *data, uint32_t *size); +virtual RsCacheItem * deserialiseItem(void *data, uint32_t *size); + +}; + +/**************************************************************************/ + +class RsServiceSerialiser: public RsSerialType +{ + public: + RsServiceSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, 0, 0) + { return; } +virtual ~RsServiceSerialiser() + { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + +}; + +/**************************************************************************/ + +#endif + diff --git a/libretroshare/src/serialiser/rsbaseserial.cc b/libretroshare/src/serialiser/rsbaseserial.cc new file mode 100644 index 000000000..1218c325d --- /dev/null +++ b/libretroshare/src/serialiser/rsbaseserial.cc @@ -0,0 +1,242 @@ + +/* + * libretroshare/src/serialiser: rsbaseserial.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include /* Included because GCC4.4 wants it */ +#include /* Included because GCC4.4 wants it */ + +#include "serialiser/rsbaseserial.h" +#include "util/rsnet.h" + +#include + +/* UInt8 get/set */ + +bool getRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t *out) +{ + /* first check there is space */ + if (size < *offset + 1) + { + return false; + } + void *buf = (void *) &(((uint8_t *) data)[*offset]); + + /* extract the data */ + memcpy(out, buf, sizeof(uint8_t)); + (*offset) += 1; + + return true; +} + +bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in) +{ + /* first check there is space */ + if (size < *offset + 1) + { + return false; + } + + void *buf = (void *) &(((uint8_t *) data)[*offset]); + + /* pack it in */ + memcpy(buf, &in, sizeof(uint8_t)); + + (*offset) += 1; + return true; +} +/* UInt16 get/set */ + +bool getRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t *out) +{ + /* first check there is space */ + if (size < *offset + 2) + { + return false; + } + void *buf = (void *) &(((uint8_t *) data)[*offset]); + + /* extract the data */ + uint16_t netorder_num; + memcpy(&netorder_num, buf, sizeof(uint16_t)); + + (*out) = ntohs(netorder_num); + (*offset) += 2; + return true; +} + +bool setRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t in) +{ + /* first check there is space */ + if (size < *offset + 2) + { + return false; + } + + void *buf = (void *) &(((uint8_t *) data)[*offset]); + + /* convert the data to the right format */ + uint16_t netorder_num = htons(in); + + /* pack it in */ + memcpy(buf, &netorder_num, sizeof(uint16_t)); + + (*offset) += 2; + return true; +} + +/* UInt32 get/set */ + +bool getRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t *out) +{ + /* first check there is space */ + if (size < *offset + 4) + { + return false; + } + void *buf = (void *) &(((uint8_t *) data)[*offset]); + + /* extract the data */ + uint32_t netorder_num; + memcpy(&netorder_num, buf, sizeof(uint32_t)); + + (*out) = ntohl(netorder_num); + (*offset) += 4; + return true; +} + +bool setRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t in) +{ + /* first check there is space */ + if (size < *offset + 4) + { + return false; + } + + void *buf = (void *) &(((uint8_t *) data)[*offset]); + + /* convert the data to the right format */ + uint32_t netorder_num = htonl(in); + + /* pack it in */ + memcpy(buf, &netorder_num, sizeof(uint32_t)); + + (*offset) += 4; + return true; +} + +/* UInt64 get/set */ + +bool getRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t *out) +{ + /* first check there is space */ + if (size < *offset + 8) + { + return false; + } + void *buf = (void *) &(((uint8_t *) data)[*offset]); + + /* extract the data */ + uint64_t netorder_num; + memcpy(&netorder_num, buf, sizeof(uint64_t)); + + (*out) = ntohll(netorder_num); + (*offset) += 8; + return true; +} + +bool setRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t in) +{ + /* first check there is space */ + if (size < *offset + 8) + { + return false; + } + + void *buf = (void *) &(((uint8_t *) data)[*offset]); + + /* convert the data to the right format */ + uint64_t netorder_num = htonll(in); + + /* pack it in */ + memcpy(buf, &netorder_num, sizeof(uint64_t)); + + (*offset) += 8; + return true; +} + + + +bool getRawString(void *data, uint32_t size, uint32_t *offset, std::string &outStr) +{ + uint32_t len = 0; + if (!getRawUInt32(data, size, offset, &len)) + { + std::cerr << "getRawString() get size failed" << std::endl; + return false; + } + + /* check there is space for string */ + if (size < *offset + len) + { + std::cerr << "getRawString() not enough size" << std::endl; + return false; + } + uint8_t *buf = &(((uint8_t *) data)[*offset]); + for (uint32_t i = 0; i < len; i++) + { + outStr += buf[i]; + } + + (*offset) += len; + return true; +} + +bool setRawString(void *data, uint32_t size, uint32_t *offset, std::string &inStr) +{ + uint32_t len = inStr.length(); + /* first check there is space */ + if (size < *offset + 4 + len) + { +//#ifdef RSSERIAL_DEBUG + std::cerr << "setRawString() Not enough size" << std::endl; +//#endif + return false; + } + + if (!setRawUInt32(data, size, offset, len)) + { + std::cerr << "setRawString() set size failed" << std::endl; + return false; + } + + void *buf = (void *) &(((uint8_t *) data)[*offset]); + + /* pack it in */ + memcpy(buf, inStr.c_str(), len); + + (*offset) += len; + return true; +} + diff --git a/libretroshare/src/serialiser/rsbaseserial.h b/libretroshare/src/serialiser/rsbaseserial.h new file mode 100644 index 000000000..50070c205 --- /dev/null +++ b/libretroshare/src/serialiser/rsbaseserial.h @@ -0,0 +1,67 @@ +#ifndef RS_BASE_PACKING_H +#define RS_BASE_PACKING_H + +/* + * libretroshare/src/serialiser: rsbaseserial.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include + +/******************************************************************* + * This is at the lowlevel packing routines. They are usually + * created in pairs - one to pack the data, the other to unpack. + * + * getRawXXX(void *data, uint32_t size, uint32_t *offset, XXX *out); + * setRawXXX(void *data, uint32_t size, uint32_t *offset, XXX *in); + * + * + * data - the base pointer to the serialised data. + * size - size of the memory pointed to by data. + * *offset - where we want to (un)pack the data. + * This is incremented by the datasize. + * + * *in / *out - the data to (un)pack. + * + ******************************************************************/ + + +bool getRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t *out); +bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in); + +bool getRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t *out); +bool setRawUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t in); + +bool getRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t *out); +bool setRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t in); + +bool getRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t *out); +bool setRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t in); + +bool getRawString(void *data, uint32_t size, uint32_t *offset, std::string &outStr); +bool setRawString(void *data, uint32_t size, uint32_t *offset, std::string &inStr); + +#endif + diff --git a/libretroshare/src/serialiser/rsblogitems.cc b/libretroshare/src/serialiser/rsblogitems.cc new file mode 100644 index 000000000..1ad80c4c6 --- /dev/null +++ b/libretroshare/src/serialiser/rsblogitems.cc @@ -0,0 +1,255 @@ + +/* + * libretroshare/src/serialiser: rsblogitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2010 by Cyril, Chris Parker . + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsblogitems.h" + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rstlvbase.h" + +#define RSSERIAL_DEBUG 1 +#include + +/*************************************************************************/ + +void RsBlogMsg::clear() +{ + RsDistribMsg::clear(); + + subject.clear(); + message.clear(); + + std::list::iterator it = graphic_set.begin(); + + for(; it != graphic_set.end(); it++) + { + it->TlvClear(); + } + + graphic_set.clear(); +} + +std::ostream &RsBlogMsg::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsBlogMsg", indent); + uint16_t int_Indent = indent + 2; + + RsDistribMsg::print(out, int_Indent); + + printIndent(out, int_Indent); + + std::string cnv_subject(subject.begin(), subject.end()); + out << "subject: " << cnv_subject << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_message(message.begin(), message.end()); + out << "message: " << cnv_message << std::endl; + + std::list::iterator it = graphic_set.begin(); + + for(; it != graphic_set.end(); it++) + { + it->print(out, int_Indent); + } + + + printRsItemEnd(out, "RsBlogMsg", indent); + return out; +} + + +/*************************************************************************/ +/*************************************************************************/ + +uint32_t RsBlogSerialiser::sizeMsg(RsBlogMsg *item) +{ + uint32_t s = 8; /* header */ + /* RsDistribMsg stuff */ + s += GetTlvStringSize(item->grpId); + s += GetTlvStringSize(item->parentId); + s += GetTlvStringSize(item->threadId); + s += 4; /* timestamp */ + + /* RsBlogMsg stuff */ + s += GetTlvWideStringSize(item->subject); + s += GetTlvWideStringSize(item->message); + + std::list::iterator it = item->graphic_set.begin(); + + for(; it != item->graphic_set.end(); it++) + { + s += it->TlvSize(); + } + + return s; +} + +/* serialise the data to the buffer */ +bool RsBlogSerialiser::serialiseMsg(RsBlogMsg *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeMsg(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + std::cerr << "RsBlogSerialiser::serialiseMsg() Header: " << ok << std::endl; + std::cerr << "RsBlogSerialiser::serialiseMsg() Size: " << tlvsize << std::endl; + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + std::cerr << "RsBlogSerialiser::serialiseMsg() grpId: " << ok << std::endl; + + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PARENTID, item->parentId); + std::cerr << "RsBlogSerialiser::serialiseMsg() parentId: " << ok << std::endl; + + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_THREADID, item->threadId); + std::cerr << "RsBlogSerialiser::serialiseMsg() threadpId: " << ok << std::endl; + + ok &= setRawUInt32(data, tlvsize, &offset, item->timestamp); + std::cerr << "RsBlogSerialiser::serialiseMsg() timestamp: " << ok << std::endl; + + /* RsBlogMsg */ + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_SUBJECT, item->subject); + std::cerr << "RsBlogSerialiser::serialiseMsg() subject: " << ok << std::endl; + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, item->message); + std::cerr << "RsBlogSerialiser::serialiseMsg() msg: " << ok << std::endl; + + std::list::iterator it = item->graphic_set.begin(); + + for(; it != item->graphic_set.end(); it++) + { + ok &= it->SetTlv(data, tlvsize, &offset); + } + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsBlogSerialiser::serialiseMsg() Size Error! " << std::endl; + } + + return ok; +} + + + +RsBlogMsg *RsBlogSerialiser::deserialiseMsg(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_QBLOG != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_BLOG_MSG != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsBlogMsg *item = new RsBlogMsg(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PARENTID, item->parentId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_THREADID, item->threadId); + ok &= getRawUInt32(data, rssize, &offset, &(item->timestamp)); + + /* RsBlogMsg */ + + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_SUBJECT, item->subject); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_MSG, item->message); + + RsTlvImage image; + image.TlvClear(); + + while(offset != rssize) + { + image.GetTlv(data, rssize, &offset); + item->graphic_set.push_back(image); + image.TlvClear(); + } + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +uint32_t RsBlogSerialiser::size(RsItem *item) +{ + return sizeMsg((RsBlogMsg *) item); +} + +bool RsBlogSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +{ + return serialiseMsg((RsBlogMsg *) item, data, pktsize); +} + +RsItem *RsBlogSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + return deserialiseMsg(data, pktsize); +} + + + +/*************************************************************************/ + diff --git a/libretroshare/src/serialiser/rsblogitems.h b/libretroshare/src/serialiser/rsblogitems.h new file mode 100644 index 000000000..14412d762 --- /dev/null +++ b/libretroshare/src/serialiser/rsblogitems.h @@ -0,0 +1,91 @@ +#ifndef RS_BLOG_ITEMS_H +#define RS_BLOG_ITEMS_H + +/* + * libretroshare/src/serialiser: rsblogitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Cyril, Chris Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvkeys.h" + +#include "serialiser/rsdistribitems.h" + +const uint8_t RS_PKT_SUBTYPE_BLOG_MSG = 0x01; + +/**************************************************************************/ + +class RsBlogMsg: public RsDistribMsg +{ + public: + RsBlogMsg() + :RsDistribMsg(RS_SERVICE_TYPE_QBLOG, RS_PKT_SUBTYPE_BLOG_MSG) { return; } +virtual ~RsBlogMsg() { return; } + +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + /* + * RsDistribMsg has: + * grpId, timestamp. + * Not Used: parentId, threadId + */ + std::wstring subject; + std::wstring message; + + /// for adding images to graphics + std::list graphic_set; + +}; + +class RsBlogSerialiser: public RsSerialType +{ + public: + RsBlogSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_QBLOG) + { return; } +virtual ~RsBlogSerialiser() + { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + + /* For RS_PKT_SUBTYPE_CHANNEL_MSG */ +virtual uint32_t sizeMsg(RsBlogMsg *); +virtual bool serialiseMsg(RsBlogMsg *item, void *data, uint32_t *size); +virtual RsBlogMsg *deserialiseMsg(void *data, uint32_t *size); + +}; + +/**************************************************************************/ + +#endif /* RS_BLOG_ITEMS_H */ + + diff --git a/libretroshare/src/serialiser/rschannelitems.cc b/libretroshare/src/serialiser/rschannelitems.cc new file mode 100644 index 000000000..3c3e94a57 --- /dev/null +++ b/libretroshare/src/serialiser/rschannelitems.cc @@ -0,0 +1,452 @@ + +/* + * libretroshare/src/serialiser: rschannelitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rschannelitems.h" + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rstlvbase.h" + +#define RSSERIAL_DEBUG 1 +#include + +/*************************************************************************/ + +void RsChannelMsg::clear() +{ + RsDistribMsg::clear(); + + subject.clear(); + message.clear(); + + attachment.TlvClear(); + thumbnail.TlvClear(); +} + +std::ostream &RsChannelMsg::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsChannelMsg", indent); + uint16_t int_Indent = indent + 2; + + RsDistribMsg::print(out, int_Indent); + + printIndent(out, int_Indent); + + std::string cnv_subject(subject.begin(), subject.end()); + out << "subject: " << cnv_subject << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_message(message.begin(), message.end()); + out << "message: " << cnv_message << std::endl; + + printIndent(out, int_Indent); + out << "Attachment: " << std::endl; + attachment.print(out, int_Indent); + + printIndent(out, int_Indent); + out << "Thumbnail: " << std::endl; + thumbnail.print(out, int_Indent); + + printRsItemEnd(out, "RsChannelMsg", indent); + return out; +} + +void RsChannelReadStatus::clear() +{ + + RsDistribChildConfig::clear(); + + channelId.clear(); + msgReadStatus.clear(); + + return; + +} + +std::ostream& RsChannelReadStatus::print(std::ostream &out, uint16_t indent = 0) +{ + + printRsItemBase(out, "RsChannelMsg", indent); + uint16_t int_Indent = indent + 2; + + RsDistribChildConfig::print(out, int_Indent); + + printIndent(out, int_Indent); + out << "ChannelId: " << channelId << std::endl; + + std::map::iterator mit = msgReadStatus.begin(); + + for(; mit != msgReadStatus.end(); mit++) + { + + printIndent(out, int_Indent); + out << "msgId : " << mit->first << std::endl; + + printIndent(out, int_Indent); + out << " status : " << mit->second << std::endl; + + } + + printRsItemEnd(out, "RsChannelMsg", indent); + return out; +} + +/*************************************************************************/ +/*************************************************************************/ + +uint32_t RsChannelSerialiser::sizeMsg(RsChannelMsg *item) +{ + uint32_t s = 8; /* header */ + /* RsDistribMsg stuff */ + s += GetTlvStringSize(item->grpId); + s += 4; /* timestamp */ + + /* RsChannelMsg stuff */ + s += GetTlvWideStringSize(item->subject); + s += GetTlvWideStringSize(item->message); + s += item->attachment.TlvSize(); + s += item->thumbnail.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsChannelSerialiser::serialiseMsg(RsChannelMsg *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeMsg(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + std::cerr << "RsChannelSerialiser::serialiseMsg() Header: " << ok << std::endl; + std::cerr << "RsChannelSerialiser::serialiseMsg() Size: " << tlvsize << std::endl; + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + std::cerr << "RsChannelSerialiser::serialiseMsg() grpId: " << ok << std::endl; + + ok &= setRawUInt32(data, tlvsize, &offset, item->timestamp); + std::cerr << "RsChannelSerialiser::serialiseMsg() timestamp: " << ok << std::endl; + + /* RsChannelMsg */ + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_SUBJECT, item->subject); + std::cerr << "RsChannelSerialiser::serialiseMsg() Title: " << ok << std::endl; + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, item->message); + std::cerr << "RsChannelSerialiser::serialiseMsg() Msg: " << ok << std::endl; + + ok &= item->attachment.SetTlv(data, tlvsize, &offset); + std::cerr << "RsChannelSerialiser::serialiseMsg() Attachment: " << ok << std::endl; + + ok &= item->thumbnail.SetTlv(data, tlvsize, &offset); + std::cerr << "RsChannelSerialiser::serialiseMsg() thumbnail: " << ok << std::endl; + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsChannelSerialiser::serialiseMsg() Size Error! " << std::endl; + } + + return ok; +} + + + +RsChannelMsg *RsChannelSerialiser::deserialiseMsg(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_CHANNEL != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_CHANNEL_MSG != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsChannelMsg *item = new RsChannelMsg(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + ok &= getRawUInt32(data, rssize, &offset, &(item->timestamp)); + + /* RsChannelMsg */ + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_SUBJECT, item->subject); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_MSG, item->message); + ok &= item->attachment.GetTlv(data, rssize, &offset); + ok &= item->thumbnail.GetTlv(data, rssize, &offset); + + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +uint32_t RsChannelSerialiser::sizeReadStatus(RsChannelReadStatus *item) +{ + uint32_t s = 8; /* header */ + /* RsDistribChildConfig stuff */ + + s += 4; /* save_type */ + + /* RsChannelReadStatus stuff */ + + s += GetTlvStringSize(item->channelId); + + std::map::iterator mit = item->msgReadStatus.begin(); + + for(; mit != item->msgReadStatus.end(); mit++) + { + s += GetTlvStringSize(mit->first); /* key */ + s += 4; /* value */ + } + + return s; +} + +/* serialise the data to the buffer */ +bool RsChannelSerialiser::serialiseReadStatus(RsChannelReadStatus *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeReadStatus(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + std::cerr << "RsChannelSerialiser::serialiseReadStatus() Header: " << ok << std::endl; + std::cerr << "RsChannelSerialiser::serialiseReadStatus() Size: " << tlvsize << std::endl; + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + + ok &= setRawUInt32(data, tlvsize, &offset, item->save_type); + std::cerr << "RsChannelSerialiser::serialiseReadStatus() save_type: " << ok << std::endl; + + + + /* RsChannelMsg */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GROUPID, item->channelId); + std::cerr << "RsChannelSerialiser::serialiseReadStatus() channelId: " << ok << std::endl; + + std::map::iterator mit = item->msgReadStatus.begin(); + + for(; mit != item->msgReadStatus.end(); mit++) + { + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_MSGID, mit->first); /* key */ + ok &= setRawUInt32(data, tlvsize, &offset, mit->second); /* value */ + } + + std::cerr << "RsChannelSerialiser::serialiseReadStatus() msgReadStatus: " << ok << std::endl; + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsChannelSerialiser::serialiseReadStatus() Size Error! " << std::endl; + } + + return ok; +} + + + +RsChannelReadStatus *RsChannelSerialiser::deserialiseReadStatus(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_CHANNEL != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_CHANNEL_READ_STATUS != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsChannelReadStatus *item = new RsChannelReadStatus(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + ok &= getRawUInt32(data, rssize, &offset, &(item->save_type)); + + /* RschannelMsg */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GROUPID, item->channelId); + + std::string key; + uint32_t value; + + while(offset != rssize) + { + key.clear(); + value = 0; + + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_MSGID, key); /* key */ + + /* incomplete key value pair? then fail*/ + if(offset == rssize) + { + delete item; + return NULL; + } + + ok &= getRawUInt32(data, rssize, &offset, &value); /* value */ + + item->msgReadStatus.insert(std::pair(key, value)); + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/************************************************************/ + +uint32_t RsChannelSerialiser::size(RsItem *item) +{ + RsChannelMsg* dcm; + RsChannelReadStatus* drs; + + if( NULL != ( dcm = dynamic_cast(item))) + { + return sizeMsg(dcm); + } + else if(NULL != (drs = dynamic_cast(item))) + { + return sizeReadStatus(drs); + } + + return false; +} + +bool RsChannelSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +{ + RsChannelMsg* dcm; + RsChannelReadStatus* drs; + + if( NULL != ( dcm = dynamic_cast(item))) + { + return serialiseMsg(dcm, data, pktsize); + } + else if(NULL != (drs = dynamic_cast(item))) + { + return serialiseReadStatus(drs, data, pktsize); + } + + return false; +} + +RsItem *RsChannelSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_CHANNEL != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_CHANNEL_MSG: + return deserialiseMsg(data, pktsize); + case RS_PKT_SUBTYPE_CHANNEL_READ_STATUS: + return deserialiseReadStatus(data, pktsize); + default: + return NULL; + } + + return NULL; +} + + + +/*************************************************************************/ + diff --git a/libretroshare/src/serialiser/rschannelitems.h b/libretroshare/src/serialiser/rschannelitems.h new file mode 100644 index 000000000..726fed7a0 --- /dev/null +++ b/libretroshare/src/serialiser/rschannelitems.h @@ -0,0 +1,120 @@ +#ifndef RS_CHANNEL_ITEMS_H +#define RS_CHANNEL_ITEMS_H + +/* + * libretroshare/src/serialiser: rschannelitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvkeys.h" + +#include "serialiser/rsdistribitems.h" + +const uint8_t RS_PKT_SUBTYPE_CHANNEL_MSG = 0x01; +const uint8_t RS_PKT_SUBTYPE_CHANNEL_READ_STATUS = 0x02; + +/**************************************************************************/ + +class RsChannelMsg: public RsDistribMsg +{ + public: + RsChannelMsg() + :RsDistribMsg(RS_SERVICE_TYPE_CHANNEL, RS_PKT_SUBTYPE_CHANNEL_MSG) { return; } +virtual ~RsChannelMsg() { return; } + +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + /* + * RsDistribMsg has: + * grpId, timestamp. + * Not Used: parentId, threadId + */ + + std::wstring subject; + std::wstring message; + + RsTlvFileSet attachment; + RsTlvImage thumbnail; + +}; + +/*! + * This is used to keep track of whether a message has been read + * by client + */ +class RsChannelReadStatus : public RsDistribChildConfig +{ +public: + RsChannelReadStatus() + : RsDistribChildConfig(RS_SERVICE_TYPE_CHANNEL, RS_PKT_SUBTYPE_CHANNEL_READ_STATUS) + { return; } + + virtual ~RsChannelReadStatus() {return; } + + virtual void clear(); + virtual std::ostream& print(std::ostream &out, uint16_t indent); + + std::string channelId; + + /// a map which contains the read for messages within a forum + std::map msgReadStatus; + +}; + +class RsChannelSerialiser: public RsSerialType +{ + public: + RsChannelSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_CHANNEL) + { return; } +virtual ~RsChannelSerialiser() + { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + + /* For RS_PKT_SUBTYPE_CHANNEL_MSG */ +virtual uint32_t sizeMsg(RsChannelMsg *); +virtual bool serialiseMsg(RsChannelMsg *item, void *data, uint32_t *size); +virtual RsChannelMsg *deserialiseMsg(void *data, uint32_t *size); + +virtual uint32_t sizeReadStatus(RsChannelReadStatus* ); +virtual bool serialiseReadStatus(RsChannelReadStatus* item, void* data, uint32_t *size); +virtual RsChannelReadStatus *deserialiseReadStatus(void* data, uint32_t *size); + +}; + +/**************************************************************************/ + +#endif /* RS_CHANNEL_ITEMS_H */ + + diff --git a/libretroshare/src/serialiser/rsconfigitems.cc b/libretroshare/src/serialiser/rsconfigitems.cc new file mode 100644 index 000000000..16ae68fc6 --- /dev/null +++ b/libretroshare/src/serialiser/rsconfigitems.cc @@ -0,0 +1,1675 @@ + +/* + * libretroshare/src/serialiser: rsconfigitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie, Chris Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsconfigitems.h" +#include "retroshare/rspeers.h" + +/*** +#define RSSERIAL_DEBUG 1 +***/ + +#include + +// For transition. +RsPeerNetItem *convertToNetItem(RsPeerOldNetItem *old); + +/*************************************************************************/ + +uint32_t RsFileConfigSerialiser::size(RsItem *i) +{ + RsFileTransfer *rft; + RsFileConfigItem *rfi; + + if (NULL != (rft = dynamic_cast(i))) + { + return sizeTransfer(rft); + } + if (NULL != (rfi = dynamic_cast(i))) + { + return sizeFileItem(rfi); + } + return 0; +} + +/* serialise the data to the buffer */ +bool RsFileConfigSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ + RsFileTransfer *rft; + RsFileConfigItem *rfi; + + if (NULL != (rft = dynamic_cast(i))) + { + return serialiseTransfer(rft, data, pktsize); + } + if (NULL != (rfi = dynamic_cast(i))) + { + return serialiseFileItem(rfi, data, pktsize); + } + return false; +} + +RsItem *RsFileConfigSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE_CONFIG != getRsItemType(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_FILE_TRANSFER: + return deserialiseTransfer(data, pktsize); + break; + case RS_PKT_SUBTYPE_FILE_ITEM: + return deserialiseFileItem(data, pktsize); + break; + default: + return NULL; + break; + } + return NULL; +} + +/*************************************************************************/ + +RsFileTransfer::~RsFileTransfer() +{ + return; +} + +void RsFileTransfer::clear() +{ + + file.TlvClear(); + allPeerIds.TlvClear(); + cPeerId = ""; + state = 0; + in = false; + transferred = 0; + crate = 0; + trate = 0; + lrate = 0; + ltransfer = 0; + +} + +std::ostream &RsFileTransfer::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileTransfer", indent); + uint16_t int_Indent = indent + 2; + file.print(out, int_Indent); + allPeerIds.print(out, int_Indent); + + printIndent(out, int_Indent); + out << "cPeerId: " << cPeerId << std::endl; + + printIndent(out, int_Indent); + out << "State: " << state << std::endl; + printIndent(out, int_Indent); + out << "In/Out: " << in << std::endl; + + printIndent(out, int_Indent); + out << "Transferred: " << transferred << std::endl; + + printIndent(out, int_Indent); + out << "crate: " << crate << std::endl; + printIndent(out, int_Indent); + out << "trate: " << trate << std::endl; + printIndent(out, int_Indent); + out << "lrate: " << lrate << std::endl; + printIndent(out, int_Indent); + out << "ltransfer: " << ltransfer << std::endl; + + printRsItemEnd(out, "RsFileTransfer", indent); + return out; + +} + +/*************************************************************************/ +/*************************************************************************/ + +RsFileConfigItem::~RsFileConfigItem() +{ + return; +} + +void RsFileConfigItem::clear() +{ + + file.TlvClear(); + flags = 0; +} + +std::ostream &RsFileConfigItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileConfigItem", indent); + uint16_t int_Indent = indent + 2; + file.print(out, int_Indent); + + printIndent(out, int_Indent); + out << "flags: " << flags << std::endl; + + printRsItemEnd(out, "RsFileConfigItem", indent); + return out; + +} + +/*************************************************************************/ +/*************************************************************************/ + + +uint32_t RsFileConfigSerialiser::sizeTransfer(RsFileTransfer *item) +{ + uint32_t s = 8; /* header */ + s += item->file.TlvSize(); + s += item->allPeerIds.TlvSize(); + s += GetTlvStringSize(item->cPeerId); + s += 2; /* state */ + s += 2; /* in/out */ + s += 8; /* transferred */ + s += 4; /* crate */ + s += 4; /* trate */ + s += 4; /* lrate */ + s += 4; /* ltransfer */ + s += 4; // chunk_strategy + s += 4; // flags + s += 4; // chunk map size + s += 4*item->compressed_chunk_map._map.size(); // compressed_chunk_map + + return s; +} + +bool RsFileConfigSerialiser::serialiseTransfer(RsFileTransfer *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeTransfer(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Header: " << ok << std::endl; + std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= item->file.SetTlv(data, tlvsize, &offset); + ok &= item->allPeerIds.SetTlv(data, tlvsize, &offset); + + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->cPeerId); + + ok &= setRawUInt16(data, tlvsize, &offset, item->state); + ok &= setRawUInt16(data, tlvsize, &offset, item->in); + + ok &= setRawUInt64(data, tlvsize, &offset, item->transferred); + + ok &= setRawUInt32(data, tlvsize, &offset, item->crate); + ok &= setRawUInt32(data, tlvsize, &offset, item->trate); + ok &= setRawUInt32(data, tlvsize, &offset, item->lrate); + ok &= setRawUInt32(data, tlvsize, &offset, item->ltransfer); + + ok &= setRawUInt32(data, tlvsize, &offset, item->flags); + ok &= setRawUInt32(data, tlvsize, &offset, item->chunk_strategy); + ok &= setRawUInt32(data, tlvsize, &offset, item->compressed_chunk_map._map.size()); + + for(uint32_t i=0;icompressed_chunk_map._map.size();++i) + ok &= setRawUInt32(data, tlvsize, &offset, item->compressed_chunk_map._map[i]); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsFileTransfer *RsFileConfigSerialiser::deserialiseTransfer(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE_CONFIG != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FILE_TRANSFER != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileTransfer *item = new RsFileTransfer(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= item->file.GetTlv(data, rssize, &offset); + ok &= item->allPeerIds.GetTlv(data, rssize, &offset); + + /* string */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->cPeerId); + + /* data */ + ok &= getRawUInt16(data, rssize, &offset, &(item->state)); + ok &= getRawUInt16(data, rssize, &offset, &(item->in)); + ok &= getRawUInt64(data, rssize, &offset, &(item->transferred)); + ok &= getRawUInt32(data, rssize, &offset, &(item->crate)); + ok &= getRawUInt32(data, rssize, &offset, &(item->trate)); + ok &= getRawUInt32(data, rssize, &offset, &(item->lrate)); + ok &= getRawUInt32(data, rssize, &offset, &(item->ltransfer)); + + ok &= getRawUInt32(data, rssize, &offset, &(item->flags)); + ok &= getRawUInt32(data, rssize, &offset, &(item->chunk_strategy)); + uint32_t map_size = 0 ; + ok &= getRawUInt32(data, rssize, &offset, &map_size); + + item->compressed_chunk_map._map.resize(map_size) ; + for(uint32_t i=0;icompressed_chunk_map._map[i])); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ +/*************************************************************************/ + + +uint32_t RsFileConfigSerialiser::sizeFileItem(RsFileConfigItem *item) +{ + uint32_t s = 8; /* header */ + s += item->file.TlvSize(); + s += 4; + + return s; +} + +bool RsFileConfigSerialiser::serialiseFileItem(RsFileConfigItem *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeFileItem(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileConfigSerialiser::serialiseFileItem() Header: " << ok << std::endl; + std::cerr << "RsFileConfigSerialiser::serialiseFileItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= item->file.SetTlv(data, tlvsize, &offset); + + ok &= setRawUInt32(data, tlvsize, &offset, item->flags); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileConfigSerialiser::serialiseFileItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsFileConfigItem *RsFileConfigSerialiser::deserialiseFileItem(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE_CONFIG != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FILE_ITEM != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileConfigItem *item = new RsFileConfigItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= item->file.GetTlv(data, rssize, &offset); + ok &= getRawUInt32(data, rssize, &offset, &(item->flags)); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + + + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + +RsGeneralConfigSerialiser::~RsGeneralConfigSerialiser() +{ + return; +} + +uint32_t RsGeneralConfigSerialiser::size(RsItem *i) +{ + RsConfigKeyValueSet *kvs; + + if (NULL != (kvs = dynamic_cast(i))) + { + return sizeKeyValueSet(kvs); + } + else if (NULL != (kvs = dynamic_cast(i))) + { + return sizeKeyValueSet(kvs); + } + + return 0; +} + +/* serialise the data to the buffer */ +bool RsGeneralConfigSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ + RsConfigKeyValueSet *kvs; + + /* do reply first - as it is derived from Item */ + if (NULL != (kvs = dynamic_cast(i))) + { + return serialiseKeyValueSet(kvs, data, pktsize); + } + else if (NULL != (kvs = dynamic_cast(i))) + { + return serialiseKeyValueSet(kvs, data, pktsize); + } + + return false; +} + +RsItem *RsGeneralConfigSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_GENERAL_CONFIG != getRsItemType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGeneralConfigSerialiser::deserialise() Wrong Type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_KEY_VALUE: + return deserialiseKeyValueSet(data, pktsize); + break; + default: + return NULL; + break; + } + return NULL; +} + +/*************************************************************************/ + +RsConfigKeyValueSet::~RsConfigKeyValueSet() +{ + return; +} + +void RsConfigKeyValueSet::clear() +{ + tlvkvs.pairs.clear(); +} + +std::ostream &RsConfigKeyValueSet::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsConfigKeyValueSet", indent); + uint16_t int_Indent = indent + 2; + + tlvkvs.print(out, int_Indent); + + printRsItemEnd(out, "RsConfigKeyValueSet", indent); + return out; +} + + +uint32_t RsGeneralConfigSerialiser::sizeKeyValueSet(RsConfigKeyValueSet *item) +{ + uint32_t s = 8; /* header */ + s += item->tlvkvs.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsGeneralConfigSerialiser::serialiseKeyValueSet(RsConfigKeyValueSet *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeKeyValueSet(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGeneralConfigSerialiser::serialiseKeyValueSet() Header: " << ok << std::endl; + std::cerr << "RsGeneralConfigSerialiser::serialiseKeyValueSet() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= item->tlvkvs.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGeneralConfigSerialiser::serialiseKeyValueSet() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsConfigKeyValueSet *RsGeneralConfigSerialiser::deserialiseKeyValueSet(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_GENERAL_CONFIG != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_KEY_VALUE != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGeneralConfigSerialiser::deserialiseKeyValueSet() Wrong Type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGeneralConfigSerialiser::deserialiseKeyValueSet() Not Enough Space" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsConfigKeyValueSet *item = new RsConfigKeyValueSet(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= item->tlvkvs.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGeneralConfigSerialiser::deserialiseKeyValueSet() offset != rssize" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGeneralConfigSerialiser::deserialiseKeyValueSet() ok = false" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + +RsPeerConfigSerialiser::~RsPeerConfigSerialiser() +{ + return; +} + +uint32_t RsPeerConfigSerialiser::size(RsItem *i) +{ + RsPeerOldNetItem *oldpni; + RsPeerStunItem *psi; + RsPeerNetItem *pni; + RsPeerGroupItem *pgi; + + if (NULL != (oldpni = dynamic_cast(i))) + { + return sizeOldNet(oldpni); + } + if (NULL != (pni = dynamic_cast(i))) + { + return sizeNet(pni); + } + else if (NULL != (psi = dynamic_cast(i))) + { + return sizeStun(psi); + } + else if (NULL != (pgi = dynamic_cast(i))) + { + return sizeGroup(pgi); + } + + return 0; +} + +/* serialise the data to the buffer */ +bool RsPeerConfigSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ + RsPeerOldNetItem *oldpni; + RsPeerNetItem *pni; + RsPeerStunItem *psi; + RsPeerGroupItem *pgi; + + if (NULL != (oldpni = dynamic_cast(i))) + { + return serialiseOldNet(oldpni, data, pktsize); + } + if (NULL != (pni = dynamic_cast(i))) + { + return serialiseNet(pni, data, pktsize); + } + else if (NULL != (psi = dynamic_cast(i))) + { + return serialiseStun(psi, data, pktsize); + } + else if (NULL != (pgi = dynamic_cast(i))) + { + return serialiseGroup(pgi, data, pktsize); + } + + return false; +} + +RsItem *RsPeerConfigSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_PEER_CONFIG != getRsItemType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::deserialise() Wrong Type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + RsPeerOldNetItem *old = NULL; + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_PEER_OLD_NET: + old = deserialiseOldNet(data, pktsize); + /* upgrade mechanism */ + return convertToNetItem(old); + case RS_PKT_SUBTYPE_PEER_NET: + return deserialiseNet(data, pktsize); + case RS_PKT_SUBTYPE_PEER_STUN: + return deserialiseStun(data, pktsize); + case RS_PKT_SUBTYPE_PEER_GROUP: + return deserialiseGroup(data, pktsize); + default: + return NULL; + } + return NULL; +} + + +/*************************************************************************/ + +RsPeerOldNetItem::~RsPeerOldNetItem() +{ + return; +} + +void RsPeerOldNetItem::clear() +{ + pid.clear(); + gpg_id.clear(); + location.clear(); + netMode = 0; + visState = 0; + lastContact = 0; + + sockaddr_clear(¤tlocaladdr); + sockaddr_clear(¤tremoteaddr); + dyndns.clear(); +} + +std::ostream &RsPeerOldNetItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsPeerOldNetItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "PeerId: " << pid << std::endl; + + printIndent(out, int_Indent); + out << "GPGid: " << gpg_id << std::endl; + + printIndent(out, int_Indent); + out << "location: " << location << std::endl; + + printIndent(out, int_Indent); + out << "netMode: " << netMode << std::endl; + + printIndent(out, int_Indent); + out << "visState: " << visState << std::endl; + + printIndent(out, int_Indent); + out << "lastContact: " << lastContact << std::endl; + + printIndent(out, int_Indent); + out << "currentlocaladdr: " << rs_inet_ntoa(currentlocaladdr.sin_addr); + out << ":" << htons(currentlocaladdr.sin_port) << std::endl; + + printIndent(out, int_Indent); + out << "currentremoteaddr: " << rs_inet_ntoa(currentremoteaddr.sin_addr); + out << ":" << htons(currentremoteaddr.sin_port) << std::endl; + + printIndent(out, int_Indent); + out << "DynDNS: " << dyndns << std::endl; + + printIndent(out, int_Indent); + out << "ipAdressList: size : " << ipAddressList.size() << ", adresses : " << std::endl; + for (std::list::iterator ipListIt = ipAddressList.begin(); ipListIt!=(ipAddressList.end()); ipListIt++) { + printIndent(out, int_Indent); + out << rs_inet_ntoa(ipListIt->ipAddr.sin_addr) << ":" << ntohs(ipListIt->ipAddr.sin_port) << " seenTime : " << ipListIt->seenTime << std::endl; + } + + printRsItemEnd(out, "RsPeerOldNetItem", indent); + return out; +} + +/*************************************************************************/ + +uint32_t RsPeerConfigSerialiser::sizeOldNet(RsPeerOldNetItem *i) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(i->pid); /* peerid */ + s += GetTlvStringSize(i->gpg_id); + s += GetTlvStringSize(i->location); + s += 4; /* netMode */ + s += 4; /* visState */ + s += 4; /* lastContact */ + s += GetTlvIpAddrPortV4Size(); /* localaddr */ + s += GetTlvIpAddrPortV4Size(); /* remoteaddr */ + s += GetTlvStringSize(i->dyndns); + + //add the size of the ip list + int ipListSize = i->ipAddressList.size(); + s += ipListSize * GetTlvIpAddrPortV4Size(); + s += ipListSize * 8; //size of an uint64 + + return s; + +} + +bool RsPeerConfigSerialiser::serialiseOldNet(RsPeerOldNetItem *item, void *data, uint32_t *size) +{ + uint32_t tlvsize = RsPeerConfigSerialiser::sizeOldNet(item); + uint32_t offset = 0; + + if(*size < tlvsize) + return false; /* not enough space */ + + *size = tlvsize; + + bool ok = true; + + // serialise header + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialiseNet() Header: " << ok << std::endl; + std::cerr << "RsPeerConfigSerialiser::serialiseNet() Header test: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->pid); /* Mandatory */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GPGID, item->gpg_id); /* Mandatory */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LOCATION, item->location); /* Mandatory */ + ok &= setRawUInt32(data, tlvsize, &offset, item->netMode); /* Mandatory */ + ok &= setRawUInt32(data, tlvsize, &offset, item->visState); /* Mandatory */ + ok &= setRawUInt32(data, tlvsize, &offset, item->lastContact); /* Mandatory */ + ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_LOCAL, &(item->currentlocaladdr)); + ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_REMOTE, &(item->currentremoteaddr)); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); + + //store the ip list + std::list::iterator ipListIt; + for (ipListIt = item->ipAddressList.begin(); ipListIt!=(item->ipAddressList.end()); ipListIt++) { + ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_REMOTE, &(ipListIt->ipAddr)); + ok &= setRawUInt64(data, tlvsize, &offset, ipListIt->seenTime); + } + + if(offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialise() Size Error! " << std::endl; +#endif + } + + return ok; + +} + +RsPeerOldNetItem *RsPeerConfigSerialiser::deserialiseOldNet(void *data, uint32_t *size) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_PEER_CONFIG != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_PEER_OLD_NET != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsPeerOldNetItem *item = new RsPeerOldNetItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->pid); /* Mandatory */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GPGID, item->gpg_id); /* Mandatory */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LOCATION, item->location); /* Mandatory */ + ok &= getRawUInt32(data, rssize, &offset, &(item->netMode)); /* Mandatory */ + ok &= getRawUInt32(data, rssize, &offset, &(item->visState)); /* Mandatory */ + ok &= getRawUInt32(data, rssize, &offset, &(item->lastContact)); /* Mandatory */ + ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_LOCAL, &(item->currentlocaladdr)); + ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_REMOTE, &(item->currentremoteaddr)); + //ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); + GetTlvString(data, rssize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); //use this line for backward compatibility + + //get the ip adress list + std::list ipTimedList; + while (offset < rssize) { + IpAddressTimed ipTimed; + sockaddr_clear(&ipTimed.ipAddr); + ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_REMOTE, &ipTimed.ipAddr); + if (!ok) { break;} + uint64_t time = 0; + ok &= getRawUInt64(data, rssize, &offset, &time); + if (!ok) { break;} + ipTimed.seenTime = time; + ipTimedList.push_back(ipTimed); + } + item->ipAddressList = ipTimedList; + + //if (offset != rssize) + if (false) //use this line for backward compatibility + { + + /* error */ + delete item; + return NULL; + } + + return item; +} + +/****************************************************************************/ +RsPeerNetItem *convertToNetItem(RsPeerOldNetItem *old) +{ + RsPeerNetItem *item = new RsPeerNetItem(); + + /* copy over data */ + item->pid = old->pid; + item->gpg_id = old->gpg_id; + item->location = old->location; + item->netMode = old->netMode; + item->visState = old->visState; + item->lastContact = old->lastContact; + + item->currentlocaladdr = old->currentlocaladdr; + item->currentremoteaddr = old->currentremoteaddr; + item->dyndns = old->dyndns; + + std::list::iterator it; + for(it = old->ipAddressList.begin(); it != old->ipAddressList.end(); it++) + { + RsTlvIpAddressInfo info; + info.addr = it->ipAddr; + info.seenTime = it->seenTime; + info.source = 0; + + item->extAddrList.addrs.push_back(info); + } + + /* delete old data */ + delete old; + + return item; +} + +/****************************************************************************/ + +RsPeerNetItem::~RsPeerNetItem() +{ + return; +} + +void RsPeerNetItem::clear() +{ + pid.clear(); + gpg_id.clear(); + location.clear(); + netMode = 0; + visState = 0; + lastContact = 0; + + sockaddr_clear(¤tlocaladdr); + sockaddr_clear(¤tremoteaddr); + dyndns.clear(); + + localAddrList.TlvClear(); + extAddrList.TlvClear(); +} + +std::ostream &RsPeerNetItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsPeerNetItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "PeerId: " << pid << std::endl; + + printIndent(out, int_Indent); + out << "GPGid: " << gpg_id << std::endl; + + printIndent(out, int_Indent); + out << "location: " << location << std::endl; + + printIndent(out, int_Indent); + out << "netMode: " << netMode << std::endl; + + printIndent(out, int_Indent); + out << "visState: " << visState << std::endl; + + printIndent(out, int_Indent); + out << "lastContact: " << lastContact << std::endl; + + printIndent(out, int_Indent); + out << "currentlocaladdr: " << rs_inet_ntoa(currentlocaladdr.sin_addr); + out << ":" << htons(currentlocaladdr.sin_port) << std::endl; + + printIndent(out, int_Indent); + out << "currentremoteaddr: " << rs_inet_ntoa(currentremoteaddr.sin_addr); + out << ":" << htons(currentremoteaddr.sin_port) << std::endl; + + printIndent(out, int_Indent); + out << "DynDNS: " << dyndns << std::endl; + + localAddrList.print(out, int_Indent); + extAddrList.print(out, int_Indent); + + printRsItemEnd(out, "RsPeerNetItem", indent); + return out; +} + +/*************************************************************************/ + +uint32_t RsPeerConfigSerialiser::sizeNet(RsPeerNetItem *i) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(i->pid); /* peerid */ + s += GetTlvStringSize(i->gpg_id); + s += GetTlvStringSize(i->location); + s += 4; /* netMode */ + s += 4; /* visState */ + s += 4; /* lastContact */ + s += GetTlvIpAddrPortV4Size(); /* localaddr */ + s += GetTlvIpAddrPortV4Size(); /* remoteaddr */ + s += GetTlvStringSize(i->dyndns); + + //add the size of the ip list + s += i->localAddrList.TlvSize(); + s += i->extAddrList.TlvSize(); + + return s; + +} + +bool RsPeerConfigSerialiser::serialiseNet(RsPeerNetItem *item, void *data, uint32_t *size) +{ + uint32_t tlvsize = RsPeerConfigSerialiser::sizeNet(item); + uint32_t offset = 0; + + if(*size < tlvsize) + return false; /* not enough space */ + + *size = tlvsize; + + bool ok = true; + + // serialise header + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialiseNet() Header: " << ok << std::endl; + std::cerr << "RsPeerConfigSerialiser::serialiseNet() Header test: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->pid); /* Mandatory */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GPGID, item->gpg_id); /* Mandatory */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LOCATION, item->location); /* Mandatory */ + ok &= setRawUInt32(data, tlvsize, &offset, item->netMode); /* Mandatory */ + ok &= setRawUInt32(data, tlvsize, &offset, item->visState); /* Mandatory */ + ok &= setRawUInt32(data, tlvsize, &offset, item->lastContact); /* Mandatory */ + ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_LOCAL, &(item->currentlocaladdr)); + ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_REMOTE, &(item->currentremoteaddr)); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); + + ok &= item->localAddrList.SetTlv(data, tlvsize, &offset); + ok &= item->extAddrList.SetTlv(data, tlvsize, &offset); + + if(offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialise() Size Error! " << std::endl; +#endif + } + + return ok; + +} + +RsPeerNetItem *RsPeerConfigSerialiser::deserialiseNet(void *data, uint32_t *size) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_PEER_CONFIG != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_PEER_NET != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsPeerNetItem *item = new RsPeerNetItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->pid); /* Mandatory */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GPGID, item->gpg_id); /* Mandatory */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LOCATION, item->location); /* Mandatory */ + ok &= getRawUInt32(data, rssize, &offset, &(item->netMode)); /* Mandatory */ + ok &= getRawUInt32(data, rssize, &offset, &(item->visState)); /* Mandatory */ + ok &= getRawUInt32(data, rssize, &offset, &(item->lastContact)); /* Mandatory */ + ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_LOCAL, &(item->currentlocaladdr)); + ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_REMOTE, &(item->currentremoteaddr)); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); + ok &= item->localAddrList.GetTlv(data, rssize, &offset); + ok &= item->extAddrList.GetTlv(data, rssize, &offset); + + + //if (offset != rssize) + if (false) //use this line for backward compatibility + { + + /* error */ + delete item; + return NULL; + } + + return item; +} + +/****************************************************************************/ + +RsPeerStunItem::~RsPeerStunItem() +{ + return; +} + +void RsPeerStunItem::clear() +{ + stunList.TlvClear(); +} + +std::ostream &RsPeerStunItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsPeerStunItem", indent); + uint16_t int_Indent = indent + 2; + + stunList.printHex(out, int_Indent); + + printRsItemEnd(out, "RsPeerStunItem", indent); + return out; +} + +/*************************************************************************/ + +uint32_t RsPeerConfigSerialiser::sizeStun(RsPeerStunItem *i) +{ + uint32_t s = 8; /* header */ + s += i->stunList.TlvSize(); /* stunList */ + + return s; + +} + +bool RsPeerConfigSerialiser::serialiseStun(RsPeerStunItem *item, void *data, uint32_t *size) +{ + uint32_t tlvsize = RsPeerConfigSerialiser::sizeStun(item); + uint32_t offset = 0; + + if(*size < tlvsize) + return false; /* not enough space */ + + *size = tlvsize; + + bool ok = true; + + // serialise header + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialiseStun() Header: " << ok << std::endl; + std::cerr << "RsPeerConfigSerialiser::serialiseStun() Header: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= item->stunList.SetTlv(data, tlvsize, &offset); /* Mandatory */ + + if(offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialiseStun() Size Error! " << std::endl; +#endif + } + + return ok; + +} + +RsPeerStunItem *RsPeerConfigSerialiser::deserialiseStun(void *data, uint32_t *size) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_PEER_CONFIG != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_PEER_STUN != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsPeerStunItem *item = new RsPeerStunItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= item->stunList.GetTlv(data, rssize, &offset); /* Mandatory */ + + if (offset != rssize) + { + + /* error */ + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ + +RsPeerGroupItem::RsPeerGroupItem() : RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_PEER_CONFIG, RS_PKT_SUBTYPE_PEER_GROUP) +{ +} + +RsPeerGroupItem::~RsPeerGroupItem() +{ +} + +void RsPeerGroupItem::clear() +{ + id.clear(); + name.clear(); + flag = 0; + peerIds.clear(); +} + +std::ostream &RsPeerGroupItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsPeerGroupItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "groupId: " << id << std::endl; + + printIndent(out, int_Indent); + out << "groupName: " << name << std::endl; + + printIndent(out, int_Indent); + out << "groupFlag: " << flag << std::endl; + + std::list::iterator it; + for (it = peerIds.begin(); it != peerIds.end(); it++) { + printIndent(out, int_Indent); + out << "peerId: " << *it << std::endl; + } + + printRsItemEnd(out, "RsPeerGroupItem", indent); + return out; +} + +/* set data from RsGroupInfo to RsPeerGroupItem */ +void RsPeerGroupItem::set(RsGroupInfo &groupInfo) +{ + id = groupInfo.id; + name = groupInfo.name; + flag = groupInfo.flag; + peerIds = groupInfo.peerIds; +} + +/* get data from RsGroupInfo to RsPeerGroupItem */ +void RsPeerGroupItem::get(RsGroupInfo &groupInfo) +{ + groupInfo.id = id; + groupInfo.name = name; + groupInfo.flag = flag; + groupInfo.peerIds = peerIds; +} + +/*************************************************************************/ + +uint32_t RsPeerConfigSerialiser::sizeGroup(RsPeerGroupItem *i) +{ + uint32_t s = 8; /* header */ + s += 4; /* version */ + s += GetTlvStringSize(i->id); + s += GetTlvStringSize(i->name); + s += 4; /* flag */ + + std::list::iterator it; + for (it = i->peerIds.begin(); it != i->peerIds.end(); it++) { + s += GetTlvStringSize(*it); + } + + return s; +} + +bool RsPeerConfigSerialiser::serialiseGroup(RsPeerGroupItem *item, void *data, uint32_t *size) +{ + uint32_t tlvsize = RsPeerConfigSerialiser::sizeGroup(item); + uint32_t offset = 0; + + if(*size < tlvsize) + return false; /* not enough space */ + + *size = tlvsize; + + bool ok = true; + + // serialise header + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialiseGroup() Header: " << ok << std::endl; + std::cerr << "RsPeerConfigSerialiser::serialiseGroup() Header: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt32(data, tlvsize, &offset, 0); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_KEY, item->id); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, item->name); + ok &= setRawUInt32(data, tlvsize, &offset, item->flag); + + std::list::iterator it; + for (it = item->peerIds.begin(); it != item->peerIds.end(); it++) { + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, *it); + } + + if(offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialiseGroup() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsPeerGroupItem *RsPeerConfigSerialiser::deserialiseGroup(void *data, uint32_t *size) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_PEER_CONFIG != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_PEER_GROUP != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsPeerGroupItem *item = new RsPeerGroupItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + uint32_t version; + ok &= getRawUInt32(data, rssize, &offset, &version); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_KEY, item->id); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_NAME, item->name); + ok &= getRawUInt32(data, rssize, &offset, &(item->flag)); + + std::string peerId; + while (offset != rssize) { + peerId.erase(); + + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, peerId); + + item->peerIds.push_back(peerId); + } + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + return item; +} + + +/****************************************************************************/ + + +RsCacheConfig::~RsCacheConfig() +{ + return; +} + +void RsCacheConfig::clear() +{ + pid.clear(); + cachetypeid = 0; + cachesubid = 0; + path = ""; + name = ""; + hash = ""; + size = 0; + recvd = 0; + +} + +std::ostream &RsCacheConfig::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsCacheConfig", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); //indent + out << "pid: " << pid << std::endl; // display value of peerid + + printIndent(out, int_Indent); //indent + out << "cacheid: " << cachetypeid << ":" << cachesubid << std::endl; // display value of cacheid + + printIndent(out, int_Indent); + out << "path: " << path << std::endl; // display value of path + + printIndent(out, int_Indent); + out << "name: " << name << std::endl; // display value of name + + printIndent(out, int_Indent); + out << "hash: " << hash << std::endl; // display value of hash + + printIndent(out, int_Indent); + out << "size: " << size << std::endl; // display value of size + + printIndent(out, int_Indent); + out << "recvd: " << recvd << std::endl; // display value of recvd + + printRsItemEnd(out, "RsCacheConfig", indent); // end of 'WRITE' check + return out; +} + +/**************************************************************************/ + + +RsCacheConfigSerialiser::~RsCacheConfigSerialiser() +{ + return; +} + +uint32_t RsCacheConfigSerialiser::size(RsItem *i) +{ + RsCacheConfig *item = (RsCacheConfig *) i; + + uint32_t s = 8; // to store calculated size, initiailize with size of header + + + s += GetTlvStringSize(item->pid); + s += 2; /* cachetypeid */ + s += 2; /* cachesubid */ + s += GetTlvStringSize(item->path); + s += GetTlvStringSize(item->name); + s += GetTlvStringSize(item->hash); + s += 8; /* size */ + s += 4; /* recvd */ + + return s; +} + +bool RsCacheConfigSerialiser::serialise(RsItem *i, void *data, uint32_t *size) +{ + RsCacheConfig *item = (RsCacheConfig *) i; + uint32_t tlvsize = RsCacheConfigSerialiser::size(item); + uint32_t offset = 0; + + if(*size < tlvsize) + return false; /* not enough space */ + + *size = tlvsize; + + bool ok = true; + + ok &=setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsCacheConfigSerialiser::serialise() Header: " << ok << std::endl; + std::cerr << "RsCacheConfigSerialiser::serialise() Size: " << size << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add the mandatory parts first */ + + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->pid); + ok &= setRawUInt16(data, tlvsize, &offset, item->cachetypeid); + ok &= setRawUInt16(data, tlvsize, &offset, item->cachesubid); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PATH, item->path); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, item->name); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_HASH_SHA1, item->hash); + ok &= setRawUInt64(data, tlvsize, &offset, item->size); + ok &= setRawUInt32(data, tlvsize, &offset, item->recvd); + + if (offset !=tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsConfigSerialiser::serialisertransfer() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsItem *RsCacheConfigSerialiser::deserialise(void *data, uint32_t *size) +{/* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset; + offset = 0; + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_CACHE_CONFIG != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_DEFAULT != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + /* ready to load */ + RsCacheConfig *item = new RsCacheConfig(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->pid); + ok &= getRawUInt16(data, rssize, &offset, &(item->cachetypeid)); + ok &= getRawUInt16(data, rssize, &offset, &(item->cachesubid)); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PATH, item->path); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_NAME, item->name); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_HASH_SHA1, item->hash); + ok &= getRawUInt64(data, rssize, &offset, &(item->size)); + ok &= getRawUInt32(data, rssize, &offset, &(item->recvd)); + + + if (offset != rssize) + { + + /* error */ + delete item; + return NULL; + } + + return item; +} + + + + + diff --git a/libretroshare/src/serialiser/rsconfigitems.h b/libretroshare/src/serialiser/rsconfigitems.h new file mode 100644 index 000000000..f932602f1 --- /dev/null +++ b/libretroshare/src/serialiser/rsconfigitems.h @@ -0,0 +1,363 @@ +#ifndef RS_CONFIG_ITEMS_SERIALISER_H +#define RS_CONFIG_ITEMS_SERIALISER_H + +/* + * libretroshare/src/serialiser: rsconfigitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include + +#include "retroshare/rstypes.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvaddrs.h" + +class RsGroupInfo; + +const uint8_t RS_PKT_TYPE_GENERAL_CONFIG = 0x01; +const uint8_t RS_PKT_TYPE_PEER_CONFIG = 0x02; +const uint8_t RS_PKT_TYPE_CACHE_CONFIG = 0x03; +const uint8_t RS_PKT_TYPE_FILE_CONFIG = 0x04; + + /* GENERAL CONFIG SUBTYPES */ +const uint8_t RS_PKT_SUBTYPE_KEY_VALUE = 0x01; + + /* PEER CONFIG SUBTYPES */ +const uint8_t RS_PKT_SUBTYPE_PEER_OLD_NET = 0x01; +const uint8_t RS_PKT_SUBTYPE_PEER_STUN = 0x02; +const uint8_t RS_PKT_SUBTYPE_PEER_NET = 0x03; /* replacement for OLD_NET */ +const uint8_t RS_PKT_SUBTYPE_PEER_GROUP = 0x04; + + /* FILE CONFIG SUBTYPES */ +const uint8_t RS_PKT_SUBTYPE_FILE_TRANSFER = 0x01; +const uint8_t RS_PKT_SUBTYPE_FILE_ITEM = 0x02; + +/**************************************************************************/ + +struct IpAddressTimed { + struct sockaddr_in ipAddr; + time_t seenTime; +}; + +class RsPeerOldNetItem: public RsItem +{ + public: + RsPeerOldNetItem() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_PEER_CONFIG, + RS_PKT_SUBTYPE_PEER_OLD_NET) + { return; } +virtual ~RsPeerOldNetItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + /* networking information */ + std::string pid; /* Mandatory */ + std::string gpg_id; /* Mandatory */ + std::string location; /* not Mandatory */ + uint32_t netMode; /* Mandatory */ + uint32_t visState; /* Mandatory */ + uint32_t lastContact; /* Mandatory */ + + struct sockaddr_in currentlocaladdr; /* Mandatory */ + struct sockaddr_in currentremoteaddr; /* Mandatory */ + std::string dyndns; + + std::list ipAddressList; +}; + +class RsPeerNetItem: public RsItem +{ + public: + RsPeerNetItem() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_PEER_CONFIG, + RS_PKT_SUBTYPE_PEER_NET) + { return; } +virtual ~RsPeerNetItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + /* networking information */ + std::string pid; /* Mandatory */ + std::string gpg_id; /* Mandatory */ + std::string location; /* not Mandatory */ + uint32_t netMode; /* Mandatory */ + uint32_t visState; /* Mandatory */ + uint32_t lastContact; /* Mandatory */ + + struct sockaddr_in currentlocaladdr; /* Mandatory */ + struct sockaddr_in currentremoteaddr; /* Mandatory */ + std::string dyndns; + + RsTlvIpAddrSet localAddrList; + RsTlvIpAddrSet extAddrList; +}; + +class RsPeerGroupItem : public RsItem +{ +public: + RsPeerGroupItem(); + virtual ~RsPeerGroupItem(); + + virtual void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + /* set data from RsGroupInfo to RsPeerGroupItem */ + void set(RsGroupInfo &groupInfo); + /* get data from RsGroupInfo to RsPeerGroupItem */ + void get(RsGroupInfo &groupInfo); + + /* Mandatory */ + std::string id; + std::string name; + uint32_t flag; + + std::list peerIds; +}; + + +class RsPeerStunItem: public RsItem +{ + public: + RsPeerStunItem() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_PEER_CONFIG, + RS_PKT_SUBTYPE_PEER_STUN) + { return; } +virtual ~RsPeerStunItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsTlvPeerIdSet stunList; /* Mandatory */ +}; + +class RsPeerConfigSerialiser: public RsSerialType +{ + public: + RsPeerConfigSerialiser() + :RsSerialType(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_PEER_CONFIG) + { return; } + +virtual ~RsPeerConfigSerialiser(); + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + +/* These are depreciated ... conversion functions used to seemlessly ungrade. + */ +virtual uint32_t sizeOldNet(RsPeerOldNetItem *); +virtual bool serialiseOldNet (RsPeerOldNetItem *item, void *data, uint32_t *size); +virtual RsPeerOldNetItem *deserialiseOldNet(void *data, uint32_t *size); + +virtual uint32_t sizeNet(RsPeerNetItem *); +virtual bool serialiseNet (RsPeerNetItem *item, void *data, uint32_t *size); +virtual RsPeerNetItem *deserialiseNet(void *data, uint32_t *size); + +virtual uint32_t sizeStun(RsPeerStunItem *); +virtual bool serialiseStun (RsPeerStunItem *item, void *data, uint32_t *size); +virtual RsPeerStunItem * deserialiseStun(void *data, uint32_t *size); + +virtual uint32_t sizeGroup(RsPeerGroupItem *); +virtual bool serialiseGroup (RsPeerGroupItem *item, void *data, uint32_t *size); +virtual RsPeerGroupItem * deserialiseGroup(void *data, uint32_t *size); + +}; + +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ + +class RsCacheConfig: public RsItem +{ + public: + RsCacheConfig() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_CACHE_CONFIG, + RS_PKT_SUBTYPE_DEFAULT) + { return; } +virtual ~RsCacheConfig(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + std::string pid; /* Mandatory */ + uint16_t cachetypeid; /* Mandatory */ + uint16_t cachesubid; /* Mandatory */ + + std::string path; /* Mandatory */ + std::string name; /* Mandatory */ + std::string hash; /* Mandatory */ + uint64_t size; /* Mandatory */ + + uint32_t recvd; /* Mandatory */ +}; + + +class RsCacheConfigSerialiser: public RsSerialType +{ + public: + RsCacheConfigSerialiser() + :RsSerialType(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_CACHE_CONFIG) + { return; } + +virtual ~RsCacheConfigSerialiser(); + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + +}; + +/**************************************************************************/ + +class RsFileTransfer: public RsItem +{ + public: + RsFileTransfer() :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, RS_PKT_TYPE_FILE_CONFIG, RS_PKT_SUBTYPE_FILE_TRANSFER) + { + return; + } + virtual ~RsFileTransfer(); + virtual void clear(); + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsTlvFileItem file; + RsTlvPeerIdSet allPeerIds; + + std::string cPeerId; + + uint16_t state; + uint16_t in; + + uint64_t transferred; + uint32_t crate; + uint32_t trate; + + uint32_t lrate; + uint32_t ltransfer; + + // chunk information + uint32_t flags ; + uint32_t chunk_strategy ; // strategy flags for chunks + CompressedChunkMap compressed_chunk_map ; // chunk availability (bitwise) +}; + +/**************************************************************************/ + +const uint32_t RS_FILE_CONFIG_CLEANUP_DELETE = 0x0001; + +/* Used by ft / extralist / configdirs / anyone who wants a basic file */ +class RsFileConfigItem: public RsItem +{ + public: + RsFileConfigItem() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_FILE_CONFIG, + RS_PKT_SUBTYPE_FILE_ITEM) + { return; } +virtual ~RsFileConfigItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsTlvFileItem file; + uint32_t flags; +}; + +/**************************************************************************/ + +class RsFileConfigSerialiser: public RsSerialType +{ + public: + RsFileConfigSerialiser() + :RsSerialType(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_FILE_CONFIG) + { return; } +virtual ~RsFileConfigSerialiser() { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + +virtual uint32_t sizeTransfer(RsFileTransfer *); +virtual bool serialiseTransfer(RsFileTransfer *item, void *data, uint32_t *size); +virtual RsFileTransfer * deserialiseTransfer(void *data, uint32_t *size); + +virtual uint32_t sizeFileItem(RsFileConfigItem *); +virtual bool serialiseFileItem(RsFileConfigItem *item, void *data, uint32_t *size); +virtual RsFileConfigItem * deserialiseFileItem(void *data, uint32_t *size); + +}; + +/**************************************************************************/ + +/* Config items that are used generally */ + +class RsConfigKeyValueSet: public RsItem +{ + public: + RsConfigKeyValueSet() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_GENERAL_CONFIG, + RS_PKT_SUBTYPE_KEY_VALUE) + { return; } +virtual ~RsConfigKeyValueSet(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsTlvKeyValueSet tlvkvs; +}; + + +class RsGeneralConfigSerialiser: public RsSerialType +{ + public: + RsGeneralConfigSerialiser() + :RsSerialType(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_GENERAL_CONFIG) + { return; } + +virtual ~RsGeneralConfigSerialiser(); + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: +uint32_t sizeKeyValueSet(RsConfigKeyValueSet *item); +bool serialiseKeyValueSet(RsConfigKeyValueSet *item, void *data, uint32_t *pktsize); +RsConfigKeyValueSet *deserialiseKeyValueSet(void *data, uint32_t *pktsize); + +}; + +#endif /* RS_CONFIG_ITEMS_SERIALISER_H */ diff --git a/libretroshare/src/serialiser/rsdiscitems.cc b/libretroshare/src/serialiser/rsdiscitems.cc new file mode 100644 index 000000000..5e76c5306 --- /dev/null +++ b/libretroshare/src/serialiser/rsdiscitems.cc @@ -0,0 +1,707 @@ + +/* + * libretroshare/src/serialiser: rsdiscitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsbaseserial.h" + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsdiscitems.h" + +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" + +/*** +#define RSSERIAL_DEBUG 1 +***/ + +#include + +/*************************************************************************/ + +uint32_t RsDiscSerialiser::size(RsItem *i) +{ + RsDiscAskInfo *inf; + RsDiscReply *rdr; + RsDiscVersion *rdv; + RsDiscHeartbeat *rdt; + + /* do reply first - as it is derived from Item */ + if (NULL != (rdr = dynamic_cast(i))) + { + return sizeReply(rdr); + } + else if (NULL != (inf = dynamic_cast(i))) + { + return sizeAskInfo(inf); + } + else if (NULL != (rdv = dynamic_cast(i))) + { + return sizeVersion(rdv); + } + else if (NULL != (rdt = dynamic_cast(i))) + { + return sizeHeartbeat(rdt); + } + + return 0; +} + +/* serialise the data to the buffer */ +bool RsDiscSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ + RsDiscAskInfo *inf; + RsDiscReply *rdr; + RsDiscVersion *rdv; + RsDiscHeartbeat *rdt; + + /* do reply first - as it is derived from Item */ + if (NULL != (rdr = dynamic_cast(i))) + { + return serialiseReply(rdr, data, pktsize); + } + else if (NULL != (inf = dynamic_cast(i))) + { + return serialiseAskInfo(inf, data, pktsize); + } + else if (NULL != (rdv = dynamic_cast(i))) + { + return serialiseVersion(rdv, data, pktsize); + } + else if (NULL != (rdt = dynamic_cast(i))) + { + return serialiseHeartbeat(rdt, data, pktsize); + } + + return false; +} + +RsItem *RsDiscSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DISC != getRsItemService(rstype))) + { + std::cerr << "RsDiscSerialiser::deserialise() Wrong Type" << std::endl; + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_DISC_REPLY: + return deserialiseReply(data, pktsize); + break; + case RS_PKT_SUBTYPE_DISC_ASK_INFO: + return deserialiseAskInfo(data, pktsize); + break; + case RS_PKT_SUBTYPE_DISC_VERSION: + return deserialiseVersion(data, pktsize); + break; + case RS_PKT_SUBTYPE_DISC_HEARTBEAT: + return deserialiseHeartbeat(data, pktsize); + break; + default: + return NULL; + break; + } + return NULL; +} + +/*************************************************************************/ + +RsDiscAskInfo::~RsDiscAskInfo() +{ + return; +} + +void RsDiscAskInfo::clear() +{ + gpg_id.clear(); +} + +std::ostream &RsDiscAskInfo::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDiscAskInfo", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "gpg_id: " << gpg_id << std::endl; + + printRsItemEnd(out, "RsDiscAskInfo", indent); + return out; +} + + +uint32_t RsDiscSerialiser::sizeAskInfo(RsDiscAskInfo *item) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(item->gpg_id); + return s; +} + +/* serialise the data to the buffer */ +bool RsDiscSerialiser::serialiseAskInfo(RsDiscAskInfo *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeAskInfo(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::serialiseAskInfo() Header: " << ok << std::endl; + std::cerr << "RsDiscSerialiser::serialiseAskInfo() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->gpg_id); + + if (offset != tlvsize) { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::serialiseAskInfo() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsDiscAskInfo *RsDiscSerialiser::deserialiseAskInfo(void *data, uint32_t *pktsize) { + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DISC != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DISC_ASK_INFO != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseAskInfo() Wrong Type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseAskInfo() Not Enough Space" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsDiscAskInfo *item = new RsDiscAskInfo(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->gpg_id); + + if (offset != rssize) { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseAskInfo() offset != rssize" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseAskInfo() ok = false" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*************************************************************************/ + + +RsDiscReply::~RsDiscReply() +{ + return; +} + +void RsDiscReply::clear() +{ + aboutId.clear(); + certGPG.clear(); + rsPeerList.clear(); +} + +std::ostream &RsDiscReply::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDiscReply", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "AboutId: " << aboutId << std::endl; + + printIndent(out, int_Indent); + out << "certGPG: " << certGPG << std::endl; + + printIndent(out, int_Indent); + out << "RsDiscReply::print() RsPeerNetItem list : " << std::endl; + for (std::list::iterator pitemIt = rsPeerList.begin(); pitemIt!=(rsPeerList.end()); pitemIt++) { + printIndent(out, int_Indent); + pitemIt->print(std::cerr, indent); + } + + printRsItemEnd(out, "RsDiscReply", indent); + return out; +} + + +uint32_t RsDiscSerialiser::sizeReply(RsDiscReply *item) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(item->aboutId); + s += GetTlvStringSize(item->certGPG); + + RsPeerConfigSerialiser rss ; + + for (std::list::iterator it = item->rsPeerList.begin(); it != item->rsPeerList.end(); it++) + s += rss.size(&(*it)) ; + + return s; +} + +/* serialise the data to the buffer */ +bool RsDiscSerialiser::serialiseReply(RsDiscReply *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeReply(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::serialiseReply() Header: " << ok << std::endl; + std::cerr << "RsDiscSerialiser::serialiseReply() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->aboutId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_CERT_GPG, item->certGPG); + + //store the ip list + RsPeerConfigSerialiser rss ; + std::list::iterator pitemIt; + + for (pitemIt = item->rsPeerList.begin(); pitemIt!=(item->rsPeerList.end()) && ok; ++pitemIt) + { + uint32_t size = *pktsize - offset ;//~(uint32_t)0; // we must be conservative otherwise the serialiser returns false !! + + ok &= rss.serialise(&(*pitemIt), (void *) (((char *) data) + offset), &size); + + // The size has been updated to its exact value. + offset += size; + } + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::serialiseReply() Size Error: " << tlvsize << " != " << offset << std::endl; +#endif + } + + return ok; +} + +RsDiscReply *RsDiscSerialiser::deserialiseReply(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DISC != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DISC_REPLY != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseReply() Wrong Type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseReply() pktsize != rssize" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsDiscReply *item = new RsDiscReply(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->aboutId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_CERT_GPG, item->certGPG); + + //get the peernet address list + RsPeerConfigSerialiser rss ; + + while (offset < rssize) + { + uint32_t peerNetSize = rssize - offset ; + + RsPeerNetItem *rsPeerNetItem = (RsPeerNetItem*)rss.deserialise((void *) (((char *) data) + offset), &peerNetSize); + offset += peerNetSize; + + if(rsPeerNetItem == NULL) + break ; + + item->rsPeerList.push_back(*rsPeerNetItem); + delete rsPeerNetItem ; + } + + if (offset != rssize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseReply() offset != rssize" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseReply() ok = false" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ + + +RsDiscVersion::~RsDiscVersion() +{ + return; +} +void RsDiscVersion::clear() +{ + version = ""; +} + +std::ostream &RsDiscVersion::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDiscVersion", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Version String: " << version << std::endl; + + printRsItemEnd(out, "RsDiscVersion", indent); + return out; +} + +uint32_t RsDiscSerialiser::sizeVersion(RsDiscVersion *item) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(item->version); + + return s; +} + +/* serialise the data to the buffer */ +bool RsDiscSerialiser::serialiseVersion(RsDiscVersion *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeVersion(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, *pktsize, item->PacketId(), *pktsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::serialiseVersion() Header: " << ok << std::endl; + std::cerr << "RsDiscSerialiser::serialiseVersion() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->version); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::serialiseVersion() Size Error! " << std::endl; + std::cerr << "Offset: " << offset << " tlvsize: " << tlvsize << std::endl; +#endif + } + + return ok; +} + +RsDiscVersion *RsDiscSerialiser::deserialiseVersion(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DISC != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DISC_VERSION != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseVersion() Wrong Type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseVersion() pktsize != rssize" << std::endl; + std::cerr << "Pktsize: " << *pktsize << " Rssize: " << rssize << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsDiscVersion *item = new RsDiscVersion(); + item->clear(); + + /* skip the header */ + offset += 8; + + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_VALUE, item->version); + + if (offset != rssize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseVersion() offset != rssize" << std::endl; + std::cerr << "Offset: " << offset << " Rssize: " << rssize << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseVersion() ok = false" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*************************************************************************/ + + +RsDiscHeartbeat::~RsDiscHeartbeat() +{ + return; +} +void RsDiscHeartbeat::clear() +{ +} + +std::ostream &RsDiscHeartbeat::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDiscHeartbeat", indent); + printRsItemEnd(out, "RsDiscHeartbeat", indent); + return out; +} + +uint32_t RsDiscSerialiser::sizeHeartbeat(RsDiscHeartbeat *item) +{ + uint32_t s = 8; /* header */ + + return s; +} + +/* serialise the data to the buffer */ +bool RsDiscSerialiser::serialiseHeartbeat(RsDiscHeartbeat *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeHeartbeat(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, *pktsize, item->PacketId(), *pktsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::serialiseHeartbeat() Header: " << ok << std::endl; + std::cerr << "RsDiscSerialiser::serialiseHeartbeat() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::serialiseHeartbeat() Size Error! " << std::endl; + std::cerr << "Offset: " << offset << " tlvsize: " << tlvsize << std::endl; +#endif + } + + return ok; +} + +RsDiscHeartbeat *RsDiscSerialiser::deserialiseHeartbeat(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DISC != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DISC_HEARTBEAT != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseHeartbeat() Wrong Type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseHeartbeat() pktsize != rssize" << std::endl; + std::cerr << "Pktsize: " << *pktsize << " Rssize: " << rssize << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsDiscHeartbeat *item = new RsDiscHeartbeat(); + item->clear(); + + /* skip the header */ + offset += 8; + + if (offset != rssize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseHeartbeat() offset != rssize" << std::endl; + std::cerr << "Offset: " << offset << " Rssize: " << rssize << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDiscSerialiser::deserialiseHeartbeat() ok = false" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + +/*************************************************************************/ diff --git a/libretroshare/src/serialiser/rsdiscitems.h b/libretroshare/src/serialiser/rsdiscitems.h new file mode 100644 index 000000000..fa7234c73 --- /dev/null +++ b/libretroshare/src/serialiser/rsdiscitems.h @@ -0,0 +1,185 @@ +/* + * libretroshare/src/serialiser: rsdiscitems.h + * + * Serialiser for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef RS_DISC_ITEMS_H +#define RS_DISC_ITEMS_H + +#include "serialiser/rsserial.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rsserviceids.h" +#include "serialiser/rsconfigitems.h" + +//const uint8_t RS_PKT_SUBTYPE_DISC_OWN = 0x01; +const uint8_t RS_PKT_SUBTYPE_DISC_REPLY = 0x02; +const uint8_t RS_PKT_SUBTYPE_DISC_ASK_INFO = 0x03; +const uint8_t RS_PKT_SUBTYPE_DISC_VERSION = 0x05; +const uint8_t RS_PKT_SUBTYPE_DISC_HEARTBEAT = 0x06; + +class RsDiscItem: public RsItem +{ + protected: + RsDiscItem(uint8_t subtype) :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DISC, subtype) {} +}; + + +//class RsDiscOwnItem: public RsDiscItem +//{ +// public: +// +// RsDiscOwnItem() :RsDiscItem(RS_PKT_SUBTYPE_DISC_OWN ) {} +// +// +// virtual ~RsDiscOwnItem(); +// +// virtual void clear(); +// virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); +// +// //use for transmitting ip address list +// std::list ipAddressList; +// +// //use for transmitting my own adress list +// struct sockaddr_in laddr; +// struct sockaddr_in saddr; +// +// // time frame of recent connections. +// uint16_t contact_tf; +// // flags... +// uint32_t discFlags; +//}; + +class RsDiscReply: public RsDiscItem +{ + public: + + RsDiscReply() + :RsDiscItem(RS_PKT_SUBTYPE_DISC_REPLY) + { return; } + +virtual ~RsDiscReply(); + +virtual void clear(); +virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); + + //use for transmitting ip address list + std::list rsPeerList; + + //use for transmitting my own adress list +// struct sockaddr_in currentladdr; +// struct sockaddr_in currentsaddr; + + // time frame of recent connections. + //uint16_t contact_tf; + // flags... + //uint32_t discFlags; + + std::string aboutId; + std::string certGPG; +}; + +class RsDiscAskInfo: public RsDiscItem +{ + public: + + RsDiscAskInfo() + :RsDiscItem(RS_PKT_SUBTYPE_DISC_ASK_INFO) + { return; } + +virtual ~RsDiscAskInfo(); + +virtual void clear(); +virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); + + std::string gpg_id; +}; + +class RsDiscVersion: public RsDiscItem +{ +public: + RsDiscVersion() :RsDiscItem(RS_PKT_SUBTYPE_DISC_VERSION) + { return; } + + virtual ~RsDiscVersion(); + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); + + std::string version; +}; + +class RsDiscHeartbeat: public RsDiscItem +{ +public: + RsDiscHeartbeat() :RsDiscItem(RS_PKT_SUBTYPE_DISC_HEARTBEAT) + { return; } + + virtual ~RsDiscHeartbeat(); + + virtual void clear(); + virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); +}; + +class RsDiscSerialiser: public RsSerialType +{ + public: + RsDiscSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DISC) + { return; } + +virtual ~RsDiscSerialiser() { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + +virtual uint32_t sizeAskInfo(RsDiscAskInfo *); +virtual bool serialiseAskInfo(RsDiscAskInfo *item, void *data, uint32_t *size); +virtual RsDiscAskInfo *deserialiseAskInfo(void *data, uint32_t *size); + +virtual uint32_t sizeReply(RsDiscReply *); +virtual bool serialiseReply (RsDiscReply *item, void *data, uint32_t *size); +virtual RsDiscReply *deserialiseReply(void *data, uint32_t *size); + +//virtual uint32_t sizeIssuer(RsDiscIssuer *); +//virtual bool serialiseIssuer (RsDiscIssuer *item, void *data, uint32_t *size); +//virtual RsDiscIssuer *deserialiseIssuer(void *data, uint32_t *size); + +virtual uint32_t sizeVersion(RsDiscVersion *); +virtual bool serialiseVersion(RsDiscVersion *item, void *data, uint32_t *size); +virtual RsDiscVersion *deserialiseVersion(void *data, uint32_t *size); + +virtual uint32_t sizeHeartbeat(RsDiscHeartbeat *); +virtual bool serialiseHeartbeat(RsDiscHeartbeat *item, void *data, uint32_t *size); +virtual RsDiscHeartbeat *deserialiseHeartbeat(void *data, uint32_t *size); + +}; + + +#endif // RS_DISC_ITEMS_H + diff --git a/libretroshare/src/serialiser/rsdistribitems.cc b/libretroshare/src/serialiser/rsdistribitems.cc new file mode 100644 index 000000000..5a4396c5d --- /dev/null +++ b/libretroshare/src/serialiser/rsdistribitems.cc @@ -0,0 +1,958 @@ + +/* + * libretroshare/src/serialiser: rsforumitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsdistribitems.h" + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rstlvbase.h" + +//#define RSSERIAL_DEBUG 1 +#include + +/*************************************************************************/ + +void RsDistribMsg::clear() +{ + grpId.clear(); + parentId.clear(); + threadId.clear(); + timestamp = 0; + childTS = 0; + + msgId.clear(); + publishSignature.TlvClear(); + personalSignature.TlvClear(); +} + +std::ostream &RsDistribMsg::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDistribMsg", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "grpId: " << grpId << std::endl; + printIndent(out, int_Indent); + out << "parentId: " << parentId << std::endl; + printIndent(out, int_Indent); + out << "threadId: " << threadId << std::endl; + + printIndent(out, int_Indent); + out << "timestamp: " << timestamp << std::endl; + + printIndent(out, int_Indent); + out << "<<<<<<<< Not Serialised >>>>>>>>" << std::endl; + + printIndent(out, int_Indent); + out << "msgId: " << msgId << std::endl; + publishSignature.print(out, int_Indent); + personalSignature.print(out, int_Indent); + + out << "<<<<<<<< Not Serialised >>>>>>>>" << std::endl; + + printRsItemEnd(out, "RsDistribMsg", indent); + return out; +} + +void RsDistribChildConfig::clear() +{ + save_type = 0; +} + +std::ostream& RsDistribChildConfig::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDistribChildConfig", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "save_type: " << save_type << std::endl; + + printRsItemEnd(out, "RsDistribChildConfig", indent); + return out; +} + +void RsDistribConfigData::clear() +{ + service_data.TlvClear(); +} + +std::ostream& RsDistribConfigData::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDistribConfigData", indent); + uint16_t int_Indent = indent + 2; + + service_data.print(out, int_Indent); + + printRsItemEnd(out, "RsDistribChildConfig", indent); + return out; +} + +void RsDistribSignedMsg::clear() +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSignedMsg::clear()" << std::endl; +#endif + + grpId.clear(); + msgId.clear(); + flags = 0; + timestamp = 0; + packet.TlvClear(); + publishSignature.TlvClear(); + personalSignature.TlvClear(); + + return; +} + +std::ostream &RsDistribSignedMsg::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDistribSignedMsg", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "grpId: " << grpId << std::endl; + printIndent(out, int_Indent); + out << "msgId: " << msgId << std::endl; + printIndent(out, int_Indent); + out << "flags: " << flags << std::endl; + printIndent(out, int_Indent); + out << "timestamp: " << timestamp << std::endl; + packet.print(out, 10); + publishSignature.print(out, 10); + personalSignature.print(out, 10); + + printRsItemEnd(out, "RsDistribSignedMsg", indent); + return out; +} + +/*************************************************************************/ + +void RsDistribGrp::clear() +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribGrp::clear()" << std::endl; +#endif + + grpId.clear(); + timestamp = 0; + grpFlags = 0; + grpName.clear(); + grpDesc.clear(); + grpCategory.clear(); + + grpControlFlags = 0; + grpControlList.TlvClear(); + + grpPixmap.TlvClear(); + + adminKey.TlvClear(); + publishKeys.TlvClear(); + + adminSignature.TlvClear(); +} + +std::ostream &RsDistribGrp::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDistribGrp", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "grpId: " << grpId << std::endl; + printIndent(out, int_Indent); + out << "timestamp: " << timestamp << std::endl; + printIndent(out, int_Indent); + out << "grpFlags: " << grpFlags << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_name(grpName.begin(), grpName.end()); + out << "grpName: " << cnv_name << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_desc(grpDesc.begin(), grpDesc.end()); + out << "grpDesc: " << cnv_desc << std::endl; + + printIndent(out, int_Indent); + std::string cnv_category(grpCategory.begin(), grpCategory.end()); + out << "grpCategory: " << cnv_category << std::endl; + + printIndent(out, int_Indent); + out << "grpControlFlags: " << grpControlFlags << std::endl; + + grpControlList.print(out, int_Indent); + + grpPixmap.print(out, int_Indent); + + adminKey.print(out, int_Indent); + publishKeys.print(out, int_Indent); + adminSignature.print(out, int_Indent); + + printRsItemEnd(out, "RsDistribGrp", indent); + return out; +} + +/*************************************************************************/ + +void RsDistribGrpKey::clear() +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribGrpKey::clear()" << std::endl; +#endif + + grpId.clear(); + key.TlvClear(); +} + +std::ostream &RsDistribGrpKey::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDistribGrpKey", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "grpId: " << grpId << std::endl; + + key.print(out, int_Indent); + + printRsItemEnd(out, "RsDistribGrpKey", indent); + return out; +} + +/*************************************************************************/ +/*************************************************************************/ + +uint32_t RsDistribSerialiser::sizeGrp(RsDistribGrp *item) +{ + uint32_t s = 8; /* header */ + /* RsDistribMsg stuff */ + s += GetTlvStringSize(item->grpId); + s += 4; /* timestamp */ + s += 4; /* grpFlags */ + s += GetTlvWideStringSize(item->grpName); + s += GetTlvWideStringSize(item->grpDesc); + s += GetTlvWideStringSize(item->grpCategory); + + s += 4; /* grpControlFlags */ + s += item->grpControlList.TlvSize(); + + s += item->grpPixmap.TlvSize(); + + s += item->adminKey.TlvSize(); + s += item->publishKeys.TlvSize(); + s += item->adminSignature.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsDistribSerialiser::serialiseGrp(RsDistribGrp *item, void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseGrp()" << std::endl; +#endif + + uint32_t tlvsize = sizeGrp(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseGrp() FAIL no space" << std::endl; +#endif + + return false; /* not enough space */ + } + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* RsDistribGrp */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + ok &= setRawUInt32(data, tlvsize, &offset, item->timestamp); + ok &= setRawUInt32(data, tlvsize, &offset, item->grpFlags); + +#ifdef RSSERIAL_DEBUG + if (!ok) + std::cerr << "RsDistribSerialiser::serialiseGrp() Id/Flags NOK" << std::endl; +#endif + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_NAME, item->grpName); + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_COMMENT, item->grpDesc); + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_CATEGORY, item->grpCategory); + +#ifdef RSSERIAL_DEBUG + if (!ok) + std::cerr << "RsDistribSerialiser::serialiseGrp() Strings NOK" << std::endl; +#endif + ok &= setRawUInt32(data, tlvsize, &offset, item->grpControlFlags); + ok &= item->grpControlList.SetTlv(data, tlvsize, &offset); + + ok &= item->grpPixmap.SetTlv(data, tlvsize, &offset); +#ifdef RSSERIAL_DEBUG + if (!ok) + std::cerr << "RsDistribSerialiser::serialiseGrp() List/Pix NOK" << std::endl; +#endif + + ok &= item->adminKey.SetTlv(data, tlvsize, &offset); +#ifdef RSSERIAL_DEBUG + if (!ok) + std::cerr << "RsDistribSerialiser::serialiseGrp() AdminKey NOK" << std::endl; +#endif + ok &= item->publishKeys.SetTlv(data, tlvsize, &offset); +#ifdef RSSERIAL_DEBUG + if (!ok) + std::cerr << "RsDistribSerialiser::serialiseGrp() PubKey NOK" << std::endl; +#endif + ok &= item->adminSignature.SetTlv(data, tlvsize, &offset); +#ifdef RSSERIAL_DEBUG + if (!ok) + std::cerr << "RsDistribSerialiser::serialiseGrp() AdminSign NOK" << std::endl; +#endif + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsDistribSerialiser::serialiseGrp() Size Error! " << std::endl; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsDistribSerialiser::serialiseGrp() NOK" << std::endl; + } +#endif + + return ok; +} + + +RsDistribGrp *RsDistribSerialiser::deserialiseGrp(void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrp()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (SERVICE_TYPE != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DISTRIB_GRP != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrp() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrp() FAIL wrong size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsDistribGrp *item = new RsDistribGrp(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* RsDistribGrp */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + ok &= getRawUInt32(data, rssize, &offset, &(item->timestamp)); + ok &= getRawUInt32(data, rssize, &offset, &(item->grpFlags)); + + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_NAME, item->grpName); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_COMMENT, item->grpDesc); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_CATEGORY, item->grpCategory); + + ok &= getRawUInt32(data, rssize, &offset, &(item->grpControlFlags)); + ok &= item->grpControlList.GetTlv(data, rssize, &offset); + + ok &= item->grpPixmap.GetTlv(data, rssize, &offset); + + ok &= item->adminKey.GetTlv(data, rssize, &offset); + ok &= item->publishKeys.GetTlv(data, rssize, &offset); + ok &= item->adminSignature.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrp() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrp() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ + +uint32_t RsDistribSerialiser::sizeGrpKey(RsDistribGrpKey *item) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(item->grpId); + s += item->key.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsDistribSerialiser::serialiseGrpKey(RsDistribGrpKey *item, void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseGrpKey()" << std::endl; +#endif + /* error */ + uint32_t tlvsize = sizeGrpKey(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseGrpKey() FAIL no space" << std::endl; +#endif + return false; /* not enough space */ + } + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsDistribSerialiser::serialiseGrpKey() HEADER FAILED" << std::endl; + } +#endif + + /* skip the header */ + offset += 8; + + /* RsDistribGrp */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsDistribSerialiser::serialiseGrpKey() GROUPID FAILED" << std::endl; + } +#endif + + ok &= item->key.SetTlv(data, tlvsize, &offset); +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsDistribSerialiser::serialiseGrpKey() KEY FAILED" << std::endl; + } +#endif + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsDistribSerialiser::serialiseGrpKey() Size Error! " << std::endl; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsDistribSerialiser::serialiseGrpKey() NOK" << std::endl; + } +#endif + + return ok; +} + + +RsDistribGrpKey *RsDistribSerialiser::deserialiseGrpKey(void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrpKey()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (SERVICE_TYPE != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DISTRIB_GRP_KEY != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrpKey() FAIL wrong type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrpKey() FAIL no space" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsDistribGrpKey *item = new RsDistribGrpKey(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* RsDistribGrp */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + ok &= item->key.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrpKey() FAIL size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseGrpKey() FAIL not Okay" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ + +uint32_t RsDistribSerialiser::sizeSignedMsg(RsDistribSignedMsg *item) +{ + uint32_t s = 8; /* header */ + /* RsDistribSignedMsg stuff */ + s += GetTlvStringSize(item->grpId); + s += GetTlvStringSize(item->msgId); + s += 4; /* flags */ + s += 4; /* timestamp */ + s += item->packet.TlvSize(); + s += item->publishSignature.TlvSize(); + s += item->personalSignature.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsDistribSerialiser::serialiseSignedMsg(RsDistribSignedMsg *item, void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseSignedMsg()" << std::endl; +#endif + uint32_t tlvsize = sizeSignedMsg(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseSignedMsg() FAIL no space" << std::endl; +#endif + return false; /* not enough space */ + } + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* RsDistribSignedMsg */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_MSGID, item->msgId); + + ok &= setRawUInt32(data, tlvsize, &offset, item->flags); + ok &= setRawUInt32(data, tlvsize, &offset, item->timestamp); + + ok &= item->packet.SetTlv(data, tlvsize, &offset); + + ok &= item->publishSignature.SetTlv(data, tlvsize, &offset); + ok &= item->personalSignature.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseSignedMsg() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsDistribSerialiser::serialiseSignedMsg() NOK" << std::endl; + } +#endif + + return ok; +} + + +RsDistribSignedMsg *RsDistribSerialiser::deserialiseSignedMsg(void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseSignedMsg()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (SERVICE_TYPE != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DISTRIB_SIGNED_MSG != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseSignedMsg() Wrong Type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseSignedMsg() Wrong Size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsDistribSignedMsg *item = new RsDistribSignedMsg(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* RsDistribGrp */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_MSGID, item->msgId); + ok &= getRawUInt32(data, rssize, &offset, &(item->flags)); + ok &= getRawUInt32(data, rssize, &offset, &(item->timestamp)); + + ok &= item->packet.GetTlv(data, rssize, &offset); + + ok &= item->publishSignature.GetTlv(data, rssize, &offset); + ok &= item->personalSignature.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseSignedMsg() size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseSignedMsg() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + +/*********************** save data *******************************/ + + +uint32_t RsDistribSerialiser::sizeConfigData(RsDistribConfigData *item) +{ + uint32_t s = 8; /* header */ + + /* RsDistribSignedMsg stuff */ + s += item->service_data.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsDistribSerialiser::serialiseConfigData(RsDistribConfigData *item, void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseConfigData()" << std::endl; +#endif + uint32_t tlvsize = sizeConfigData(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseConfigData() FAIL no space" << std::endl; +#endif + return false; /* not enough space */ + } + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* RsDistribSignedMsg */ + ok &= item->service_data.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialiseConfigData() FAIL Size Error! " << std::endl; +#endif + ok = false; + } + +#ifdef RSSERIAL_DEBUG + if (!ok) + { + std::cerr << "RsDistribSerialiser::serialiseConfigData() NOK" << std::endl; + } +#endif + + return ok; +} + + +RsDistribConfigData *RsDistribSerialiser::deserialiseConfigData(void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseConfigData()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (SERVICE_TYPE != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DISTRIB_CONFIG_DATA != getRsItemSubType(rstype))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseSignedMsg() Wrong Type" << std::endl; +#endif + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseSignedMsg() Wrong Size" << std::endl; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsDistribConfigData *item = new RsDistribConfigData(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* RsDistribGrp */ + ok &= item->service_data.GetTlv(data, rssize, &offset); + + if (offset != rssize) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseSignedMsg() size mismatch" << std::endl; +#endif + /* error */ + delete item; + return NULL; + } + + if (!ok) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialiseSignedMsg() NOK" << std::endl; +#endif + delete item; + return NULL; + } + + return item; +} + + + + + +uint32_t RsDistribSerialiser::size(RsItem *i) +{ + RsDistribGrp *dg; + RsDistribGrpKey *dgk; + RsDistribSignedMsg *dsm; + RsDistribConfigData *dsd; + + /* in order of frequency */ + if (NULL != (dsm = dynamic_cast(i))) + { + return sizeSignedMsg(dsm); + } + else if (NULL != (dg = dynamic_cast(i))) + { + return sizeGrp(dg); + } + else if (NULL != (dgk = dynamic_cast(i))) + { + return sizeGrpKey(dgk); + } + else if(NULL != (dsd = dynamic_cast(i))) + { + return sizeConfigData(dsd); + } + + return 0; +} + +bool RsDistribSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::serialise()" << std::endl; +#endif + RsDistribGrp *dg; + RsDistribGrpKey *dgk; + RsDistribSignedMsg *dsm; + RsDistribConfigData *dsd; + + if (NULL != (dsm = dynamic_cast(i))) + { + return serialiseSignedMsg(dsm, data, pktsize); + } + else if (NULL != (dg = dynamic_cast(i))) + { + return serialiseGrp(dg, data, pktsize); + } + else if (NULL != (dgk = dynamic_cast(i))) + { + return serialiseGrpKey(dgk, data, pktsize); + } + else if(NULL != (dsd = dynamic_cast(i))) + { + return serialiseConfigData(dsd, data, pktsize); + } + return false; +} + +RsItem *RsDistribSerialiser::deserialise(void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDistribSerialiser::deserialise()" << std::endl; +#endif + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (SERVICE_TYPE != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_DISTRIB_GRP: + return deserialiseGrp(data, pktsize); + break; + case RS_PKT_SUBTYPE_DISTRIB_GRP_KEY: + return deserialiseGrpKey(data, pktsize); + break; + case RS_PKT_SUBTYPE_DISTRIB_SIGNED_MSG: + return deserialiseSignedMsg(data, pktsize); + break; + case RS_PKT_SUBTYPE_DISTRIB_CONFIG_DATA: + return deserialiseConfigData(data, pktsize); + break; + default: + return NULL; + break; + } + return NULL; +} + +/*************************************************************************/ +/*************************************************************************/ + diff --git a/libretroshare/src/serialiser/rsdistribitems.h b/libretroshare/src/serialiser/rsdistribitems.h new file mode 100644 index 000000000..33681de10 --- /dev/null +++ b/libretroshare/src/serialiser/rsdistribitems.h @@ -0,0 +1,260 @@ +#ifndef RS_DISTRIB_ITEMS_H +#define RS_DISTRIB_ITEMS_H + +/* + * libretroshare/src/serialiser: rsdistribitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvkeys.h" + +const uint8_t RS_PKT_SUBTYPE_DISTRIB_GRP = 0x01; +const uint8_t RS_PKT_SUBTYPE_DISTRIB_GRP_KEY = 0x02; +const uint8_t RS_PKT_SUBTYPE_DISTRIB_SIGNED_MSG = 0x03; +const uint8_t RS_PKT_SUBTYPE_DISTRIB_CONFIG_DATA = 0x04; + +/**************************************************************************/ + +/*! + * This should be subclassed by p3distrib subclass's to store their data + * save data + */ +class RsDistribChildConfig: public RsItem +{ +public: + RsDistribChildConfig(uint16_t servtype, uint8_t subtype) + : RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype),save_type(0) {return;} + + virtual ~RsDistribChildConfig() { return; } + + virtual void clear(); + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + /// use this to id the type of data you want to save + uint32_t save_type; +}; + + +/*! + * This should be used to save the service data such as settings + */ +class RsDistribConfigData: public RsItem +{ +public: + RsDistribConfigData() + : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DISTRIB, RS_PKT_SUBTYPE_DISTRIB_CONFIG_DATA), service_data(TLV_TYPE_BIN_SERIALISE) + {return;} + + virtual ~RsDistribConfigData() { return; } + + virtual void clear(); + + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + // this is where a derived distrib service saves its data + RsTlvBinaryData service_data; + +}; + + +/*! + * This is used by p3Distrib for storing messages + * of derived services, attributes are given for writing + * personal signatures (confirms user) and publish signatures (to + * confirm consistency source) + */ +class RsDistribMsg: public RsItem +{ + public: + RsDistribMsg(uint16_t servtype, uint8_t subtype) + :RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype) { return; } + +virtual ~RsDistribMsg() { return; } + +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string grpId; /* Grp Id */ + + /// Parent Msg Id, msgs above a thread + std::string parentId; + + /// Thread Msg Id: useful identifyingfor responses + ///to a forum msg and replies in general + std::string threadId; + uint32_t timestamp; + + /* Not Serialised */ + + std::string msgId; /* Msg Id */ + time_t childTS; /* timestamp of most recent child */ + + /// used to confirm the message is from a group author, or someone with valid publish key + RsTlvKeySignature publishSignature; + + /// used to confirm message is from a particular peer + RsTlvKeySignature personalSignature; +}; + + +/*! + * This is used as a storage container for messages from a service + * via the binary data container (packet) + */ +class RsDistribSignedMsg: public RsItem +{ + public: + RsDistribSignedMsg() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DISTRIB, RS_PKT_SUBTYPE_DISTRIB_SIGNED_MSG), + packet(TLV_TYPE_BIN_SERIALISE) + { return; } + +virtual ~RsDistribSignedMsg() { return; } + +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string grpId; + + /// should be taken publishSignature + std::string msgId; + uint32_t flags; + uint32_t timestamp; + + /// in order to tranfer messages from service level to distrib level + RsTlvBinaryData packet; + RsTlvKeySignature publishSignature; + RsTlvKeySignature personalSignature; +}; + + +class RsDistribGrp: public RsItem +{ + public: +// RsDistribGrp(uint16_t servtype, uint8_t subtype) +// :RsItem(RS_PKT_VERSION_SERVICE, servtype, subtype) { return; } + + RsDistribGrp() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DISTRIB, RS_PKT_SUBTYPE_DISTRIB_GRP) + { return; } + +virtual ~RsDistribGrp() { return; } + +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string grpId; /* Grp Id */ + uint32_t timestamp; + uint32_t grpFlags; + std::wstring grpName; + std::wstring grpDesc; + std::wstring grpCategory; + + RsTlvImage grpPixmap; + + uint32_t grpControlFlags; + RsTlvPeerIdSet grpControlList; + + RsTlvSecurityKey adminKey; + RsTlvSecurityKeySet publishKeys; + + RsTlvKeySignature adminSignature; +}; + + +class RsDistribGrpKey: public RsItem +{ + public: + + RsDistribGrpKey(uint16_t service_type) + :RsItem(RS_PKT_VERSION_SERVICE, service_type, RS_PKT_SUBTYPE_DISTRIB_GRP_KEY) + { return; } + + RsDistribGrpKey() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DISTRIB, RS_PKT_SUBTYPE_DISTRIB_GRP_KEY) + { return; } + +virtual ~RsDistribGrpKey() { return; } + +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string grpId; /* Grp Id */ + RsTlvSecurityKey key; +}; + + +class RsDistribSerialiser: public RsSerialType +{ + public: + + // optional to allow use in p3service/sockets + RsDistribSerialiser(uint16_t service_type = RS_SERVICE_TYPE_DISTRIB) + : RsSerialType(RS_PKT_VERSION_SERVICE, service_type), SERVICE_TYPE(service_type) + { return; } + +virtual ~RsDistribSerialiser() + { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + + /* For RS_PKT_SUBTYPE_DISTRIB_GRP */ +virtual uint32_t sizeGrp(RsDistribGrp *); +virtual bool serialiseGrp (RsDistribGrp *item, void *data, uint32_t *size); +virtual RsDistribGrp *deserialiseGrp(void *data, uint32_t *size); + + /* For RS_PKT_SUBTYPE_DISTRIB_GRP_KEY */ +virtual uint32_t sizeGrpKey(RsDistribGrpKey *); +virtual bool serialiseGrpKey (RsDistribGrpKey *item, void *data, uint32_t *size); +virtual RsDistribGrpKey *deserialiseGrpKey(void *data, uint32_t *size); + + /* For RS_PKT_SUBTYPE_DISTRIB_SIGNED_MSG */ +virtual uint32_t sizeSignedMsg(RsDistribSignedMsg *); +virtual bool serialiseSignedMsg (RsDistribSignedMsg *item, void *data, uint32_t *size); +virtual RsDistribSignedMsg *deserialiseSignedMsg(void *data, uint32_t *size); + + /* For RS_PKT_SUBTYPE_DISTRIB_SAVE_DATA */ +virtual uint32_t sizeConfigData(RsDistribConfigData *); +virtual bool serialiseConfigData(RsDistribConfigData *item, void *data, uint32_t *size); +virtual RsDistribConfigData *deserialiseConfigData(void* data, uint32_t *size); + + +const uint16_t SERVICE_TYPE; + +}; + +/**************************************************************************/ + +#endif /* RS_FORUM_ITEMS_H */ + + diff --git a/libretroshare/src/serialiser/rsforumitems.cc b/libretroshare/src/serialiser/rsforumitems.cc new file mode 100644 index 000000000..91c9ac47d --- /dev/null +++ b/libretroshare/src/serialiser/rsforumitems.cc @@ -0,0 +1,493 @@ + +/* + * libretroshare/src/serialiser: rsforumitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsforumitems.h" + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rstlvbase.h" + +// #define RSSERIAL_DEBUG 1 +#include + +/*************************************************************************/ + +void RsForumMsg::clear() +{ + RsDistribMsg::clear(); + + srcId.clear(); + title.clear(); + msg.clear(); +} + +std::ostream &RsForumMsg::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsForumMsg", indent); + uint16_t int_Indent = indent + 2; + + RsDistribMsg::print(out, int_Indent); + + printIndent(out, int_Indent); + out << "srcId: " << srcId << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_title(title.begin(), title.end()); + out << "title: " << cnv_title << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_msg(msg.begin(), msg.end()); + out << "msg: " << cnv_msg << std::endl; + + printRsItemEnd(out, "RsForumMsg", indent); + return out; +} + +void RsForumReadStatus::clear() +{ + + RsDistribChildConfig::clear(); + + forumId.clear(); + msgReadStatus.clear(); + + return; + +} + +std::ostream& RsForumReadStatus::print(std::ostream &out, uint16_t indent = 0) +{ + + printRsItemBase(out, "RsForumMsg", indent); + uint16_t int_Indent = indent + 2; + + RsDistribChildConfig::print(out, int_Indent); + + printIndent(out, int_Indent); + out << "ForumId: " << forumId << std::endl; + + printIndent(out, int_Indent); + out << "ForumId: " << forumId << std::endl; + + std::map::iterator mit = msgReadStatus.begin(); + + for(; mit != msgReadStatus.end(); mit++) + { + + printIndent(out, int_Indent); + out << "msgId : " << mit->first << std::endl; + + printIndent(out, int_Indent); + out << " status : " << mit->second << std::endl; + + } + + printRsItemEnd(out, "RsForumMsg", indent); + return out; +} + +/*************************************************************************/ +/*************************************************************************/ + +uint32_t RsForumSerialiser::sizeMsg(RsForumMsg *item) +{ + uint32_t s = 8; /* header */ + /* RsDistribMsg stuff */ + s += GetTlvStringSize(item->grpId); + s += GetTlvStringSize(item->parentId); + s += GetTlvStringSize(item->threadId); + s += 4; /* timestamp */ + + /* RsForumMsg stuff */ + s += GetTlvStringSize(item->srcId); + s += GetTlvWideStringSize(item->title); + s += GetTlvWideStringSize(item->msg); + + return s; +} + + +/* serialise the data to the buffer */ +bool RsForumSerialiser::serialiseMsg(RsForumMsg *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeMsg(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseMsg() Header: " << ok << std::endl; + std::cerr << "RsForumSerialiser::serialiseMsg() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseMsg() grpId: " << ok << std::endl; +#endif + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PARENTID, item->parentId); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseMsg() parentId: " << ok << std::endl; +#endif + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_THREADID, item->threadId); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseMsg() threadId: " << ok << std::endl; +#endif + + ok &= setRawUInt32(data, tlvsize, &offset, item->timestamp); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseMsg() timestamp: " << ok << std::endl; +#endif + + /* RsForumMsg */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->srcId); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseMsg() srcId: " << ok << std::endl; +#endif + + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_TITLE, item->title); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseMsg() Title: " << ok << std::endl; +#endif + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, item->msg); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseMsg() Msg: " << ok << std::endl; +#endif + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsForumSerialiser::serialiseMsg() Size Error! " << std::endl; + } + + return ok; +} + + + +RsForumMsg *RsForumSerialiser::deserialiseMsg(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_FORUM != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_FORUM_MSG != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsForumMsg *item = new RsForumMsg(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GROUPID, item->grpId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PARENTID, item->parentId); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_THREADID, item->threadId); + ok &= getRawUInt32(data, rssize, &offset, &(item->timestamp)); + + /* RsForumMsg */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->srcId); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_TITLE, item->title); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_MSG, item->msg); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +/*************************************************************************/ +/*************************************************************************/ + +uint32_t RsForumSerialiser::sizeReadStatus(RsForumReadStatus *item) +{ + uint32_t s = 8; /* header */ + /* RsDistribChildConfig stuff */ + + s += 4; /* save_type */ + + /* RsForumReadStatus stuff */ + + s += GetTlvStringSize(item->forumId); + + std::map::iterator mit = item->msgReadStatus.begin(); + + for(; mit != item->msgReadStatus.end(); mit++) + { + s += GetTlvStringSize(mit->first); /* key */ + s += 4; /* value */ + } + + return s; +} + +/* serialise the data to the buffer */ +bool RsForumSerialiser::serialiseReadStatus(RsForumReadStatus *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeReadStatus(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseReadStatus() Header: " << ok << std::endl; + std::cerr << "RsForumSerialiser::serialiseReadStatus() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + + ok &= setRawUInt32(data, tlvsize, &offset, item->save_type); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseReadStatus() save_type: " << ok << std::endl; +#endif + + + + /* RsForumMsg */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GROUPID, item->forumId); +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseReadStatus() forumId: " << ok << std::endl; +#endif + + std::map::iterator mit = item->msgReadStatus.begin(); + + for(; mit != item->msgReadStatus.end(); mit++) + { + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_MSGID, mit->first); /* key */ + ok &= setRawUInt32(data, tlvsize, &offset, mit->second); /* value */ + } + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseReadStatus() msgReadStatus: " << ok << std::endl; +#endif + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialiseReadStatus() Size Error! " << std::endl; +#endif + } + + return ok; +} + + + +RsForumReadStatus *RsForumSerialiser::deserialiseReadStatus(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_FORUM != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_FORUM_READ_STATUS != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsForumReadStatus *item = new RsForumReadStatus(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* RsDistribMsg first */ + ok &= getRawUInt32(data, rssize, &offset, &(item->save_type)); + + /* RsForumMsg */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GROUPID, item->forumId); + + std::string key; + uint32_t value; + + while(offset != rssize) + { + key.clear(); + value = 0; + + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_MSGID, key); /* key */ + + /* incomplete key value pair? then fail*/ + if(offset == rssize) + { + delete item; + return NULL; + } + + ok &= getRawUInt32(data, rssize, &offset, &value); /* value */ + + item->msgReadStatus.insert(std::pair(key, value)); + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/************************************************************/ + +uint32_t RsForumSerialiser::size(RsItem *item) +{ + RsForumMsg* dfm; + RsForumReadStatus* drs; + + if( NULL != ( dfm = dynamic_cast(item))) + { + return sizeMsg(dfm); + } + else if(NULL != (drs = dynamic_cast(item))) + { + return sizeReadStatus(drs); + } + + return false; +} + + +bool RsForumSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +{ + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::serialise()" << std::endl; +#endif + + RsForumMsg* dfm; + RsForumReadStatus* drs; + + if( NULL != ( dfm = dynamic_cast(item))) + { + return serialiseMsg(dfm, data, pktsize); + } + else if(NULL != (drs = dynamic_cast(item))) + { + return serialiseReadStatus(drs, data, pktsize); + } + + return NULL; +} + +RsItem *RsForumSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsForumSerialiser::deserialise()" << std::endl; +#endif + + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_FORUM != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_FORUM_MSG: + return deserialiseMsg(data, pktsize); + break; + case RS_PKT_SUBTYPE_FORUM_READ_STATUS: + return deserialiseReadStatus(data, pktsize); + break; + default: + return NULL; + break; + } + + return NULL; +} + + + +/*************************************************************************/ + diff --git a/libretroshare/src/serialiser/rsforumitems.h b/libretroshare/src/serialiser/rsforumitems.h new file mode 100644 index 000000000..f83148f78 --- /dev/null +++ b/libretroshare/src/serialiser/rsforumitems.h @@ -0,0 +1,124 @@ +#ifndef RS_FORUM_ITEMS_H +#define RS_FORUM_ITEMS_H + +/* + * libretroshare/src/serialiser: rsforumitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvkeys.h" + +#include "serialiser/rsdistribitems.h" + +const uint8_t RS_PKT_SUBTYPE_FORUM_GRP = 0x01; +const uint8_t RS_PKT_SUBTYPE_FORUM_MSG = 0x02; +const uint8_t RS_PKT_SUBTYPE_FORUM_READ_STATUS = 0x03; + +/**************************************************************************/ + +class RsForumMsg: public RsDistribMsg +{ + public: + RsForumMsg() + :RsDistribMsg(RS_SERVICE_TYPE_FORUM, RS_PKT_SUBTYPE_FORUM_MSG) { return; } +virtual ~RsForumMsg() { return; } + +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + /* + * RsDistribMsg has: + * grpId, parentId, threadId & timestamp. + */ + + std::string srcId; + + std::wstring title; + std::wstring msg; + +}; + +/*! + * This is used to keep track of whether a message has been read + * by client + */ +class RsForumReadStatus : public RsDistribChildConfig +{ +public: + RsForumReadStatus() + : RsDistribChildConfig(RS_SERVICE_TYPE_FORUM, RS_PKT_SUBTYPE_FORUM_READ_STATUS) + { return; } + + virtual ~RsForumReadStatus() {return; } + + virtual void clear(); + virtual std::ostream& print(std::ostream &out, uint16_t indent); + + std::string forumId; + + /// a map which contains the read for messages within a forum + std::map msgReadStatus; + +}; + +class RsForumSerialiser: public RsSerialType +{ + public: + RsForumSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_FORUM) + { return; } +virtual ~RsForumSerialiser() + { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + + /* For RS_PKT_SUBTYPE_FORUM_GRP */ +//virtual uint32_t sizeGrp(RsForumGrp *); +//virtual bool serialiseGrp (RsForumGrp *item, void *data, uint32_t *size); +//virtual RsForumGrp *deserialiseGrp(void *data, uint32_t *size); + + /* For RS_PKT_SUBTYPE_FORUM_MSG */ +virtual uint32_t sizeMsg(RsForumMsg *); +virtual bool serialiseMsg(RsForumMsg *item, void *data, uint32_t *size); +virtual RsForumMsg *deserialiseMsg(void *data, uint32_t *size); + +virtual uint32_t sizeReadStatus(RsForumReadStatus* ); +virtual bool serialiseReadStatus(RsForumReadStatus* item, void* data, uint32_t *size); +virtual RsForumReadStatus *deserialiseReadStatus(void* data, uint32_t *size); + +}; + +/**************************************************************************/ + +#endif /* RS_FORUM_ITEMS_H */ + + diff --git a/libretroshare/src/serialiser/rsgameitems.cc b/libretroshare/src/serialiser/rsgameitems.cc new file mode 100644 index 000000000..87fe6d0d5 --- /dev/null +++ b/libretroshare/src/serialiser/rsgameitems.cc @@ -0,0 +1,212 @@ +/* + * libretroshare/src/serialiser: rsgameitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsgameitems.h" +#include "serialiser/rstlvbase.h" + +/*** +#define RSSERIAL_DEBUG 1 +***/ + +#include + +/*************************************************************************/ + +RsGameItem::~RsGameItem() +{ + return; +} + +void RsGameItem::clear() +{ + serviceId = 0; + numPlayers = 0; + msg = 0; + + gameId.clear(); + gameComment.clear(); + players.TlvClear(); +} + +std::ostream &RsGameItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsGameItem", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "serviceId: " << serviceId << std::endl; + printIndent(out, int_Indent); + out << "numPlayers: " << numPlayers << std::endl; + printIndent(out, int_Indent); + out << "msg: " << msg << std::endl; + + printIndent(out, int_Indent); + out << "gameId: " << gameId << std::endl; + + printIndent(out, int_Indent); + std::string cnv_comment(gameComment.begin(), gameComment.end()); + out << "msg: " << cnv_comment << std::endl; + + printIndent(out, int_Indent); + out << "Players Ids: " << std::endl; + players.print(out, int_Indent); + + printRsItemEnd(out, "RsGameItem", indent); + return out; +} + + +uint32_t RsGameSerialiser::sizeItem(RsGameItem *item) +{ + uint32_t s = 8; /* header */ + s += 4; /* serviceId */ + s += 4; /* numPlayers */ + s += 4; /* msg */ + s += GetTlvStringSize(item->gameId); + s += GetTlvWideStringSize(item->gameComment); + s += item->players.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsGameSerialiser::serialiseItem(RsGameItem *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeItem(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGameSerialiser::serialiseItem() Header: " << ok << std::endl; + std::cerr << "RsGameSerialiser::serialiseItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt32(data, tlvsize, &offset, item->serviceId); + ok &= setRawUInt32(data, tlvsize, &offset, item->numPlayers); + ok &= setRawUInt32(data, tlvsize, &offset, item->msg); + + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->gameId); + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_COMMENT, item->gameComment); + ok &= item->players.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGameSerialiser::serialiseItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsGameItem *RsGameSerialiser::deserialiseItem(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t tlvsize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_GAME_LAUNCHER != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DEFAULT != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < tlvsize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = tlvsize; + + bool ok = true; + + /* ready to load */ + RsGameItem *item = new RsGameItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= getRawUInt32(data, tlvsize, &offset, &(item->serviceId)); + ok &= getRawUInt32(data, tlvsize, &offset, &(item->numPlayers)); + ok &= getRawUInt32(data, tlvsize, &offset, &(item->msg)); + + ok &= GetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->gameId); + ok &= GetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_COMMENT, item->gameComment); + ok &= item->players.GetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +uint32_t RsGameSerialiser::size(RsItem *item) +{ + return sizeItem((RsGameItem *) item); +} + +bool RsGameSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +{ + return serialiseItem((RsGameItem *) item, data, pktsize); +} + +RsItem *RsGameSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + return deserialiseItem(data, pktsize); +} + +/*************************************************************************/ + + + diff --git a/libretroshare/src/serialiser/rsgameitems.h b/libretroshare/src/serialiser/rsgameitems.h new file mode 100644 index 000000000..4b183f82d --- /dev/null +++ b/libretroshare/src/serialiser/rsgameitems.h @@ -0,0 +1,84 @@ +#ifndef RS_GAME_ITEMS_H +#define RS_GAME_ITEMS_H + +/* + * libretroshare/src/serialiser: rsgameitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +/**************************************************************************/ + +class RsGameItem: public RsItem +{ + public: + RsGameItem() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GAME_LAUNCHER, + RS_PKT_SUBTYPE_DEFAULT) + { return; } +virtual ~RsGameItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + uint32_t serviceId; + uint32_t numPlayers; + uint32_t msg; /* RS_GAME_MSG_XXX */ + + std::string gameId; + std::wstring gameComment; + + RsTlvPeerIdSet players; +}; + +class RsGameSerialiser: public RsSerialType +{ + public: + RsGameSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GAME_LAUNCHER) + { return; } +virtual ~RsGameSerialiser() + { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + +virtual uint32_t sizeItem(RsGameItem *); +virtual bool serialiseItem (RsGameItem *item, void *data, uint32_t *size); +virtual RsGameItem *deserialiseItem(void *data, uint32_t *size); + + +}; + +/**************************************************************************/ + +#endif /* RS_GAME_ITEMS_H */ + + diff --git a/libretroshare/src/serialiser/rsmsgitems.cc b/libretroshare/src/serialiser/rsmsgitems.cc new file mode 100644 index 000000000..8f8653e49 --- /dev/null +++ b/libretroshare/src/serialiser/rsmsgitems.cc @@ -0,0 +1,1359 @@ + +/* + * libretroshare/src/serialiser: rsbaseitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsmsgitems.h" +#include "serialiser/rstlvbase.h" + +/*** +#define RSSERIAL_DEBUG 1 +#define CHAT_DEBUG 1 +***/ + +#include + +/*************************************************************************/ + +std::ostream& RsChatMsgItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsChatMsgItem", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "QblogMs " << chatFlags << std::endl; + + printIndent(out, int_Indent); + out << "sendTime: " << sendTime << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_message(message.begin(), message.end()); + out << "msg: " << cnv_message << std::endl; + + printRsItemEnd(out, "RsChatMsgItem", indent); + return out; +} + +std::ostream& RsPrivateChatMsgConfigItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsPrivateChatMsgConfigItem", indent); + uint16_t int_Indent = indent + 2; + + out << "peerId: " << configPeerId << std::endl; + + printIndent(out, int_Indent); + out << "QblogMs " << chatFlags << std::endl; + + printIndent(out, int_Indent); + out << "QblogMs " << configFlags << std::endl; + + printIndent(out, int_Indent); + out << "sendTime: " << sendTime << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_message(message.begin(), message.end()); + out << "msg: " << cnv_message << std::endl; + + printRsItemEnd(out, "RsPrivateChatMsgConfigItem", indent); + return out; +} + +std::ostream& RsChatStatusItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsChatStatusItem", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "Status string: " << status_string << std::endl; + out << "Flags : " << (void*)flags << std::endl; + + printRsItemEnd(out, "RsChatStatusItem", indent); + return out; +} + +std::ostream& RsChatAvatarItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsChatAvatarItem", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "Image size: " << image_size << std::endl; + printRsItemEnd(out, "RsChatStatusItem", indent); + + return out; +} +RsItem *RsChatSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + +#ifdef CHAT_DEBUG + std::cerr << "deserializing packet..."<< std::endl ; +#endif + // look what we have... + if (*pktsize < rssize) /* check size */ + { +#ifdef CHAT_DEBUG + std::cerr << "chat deserialisation: not enough size: pktsize=" << *pktsize << ", rssize=" << rssize << std::endl ; +#endif + return NULL; /* not enough data */ + } + + /* set the packet length */ + *pktsize = rssize; + + /* ready to load */ + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_CHAT != getRsItemService(rstype))) + { +#ifdef CHAT_DEBUG + std::cerr << "chat deserialisation: wrong type !" << std::endl ; +#endif + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_DEFAULT: return new RsChatMsgItem(data,*pktsize) ; + case RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG: return new RsPrivateChatMsgConfigItem(data,*pktsize) ; + case RS_PKT_SUBTYPE_CHAT_STATUS: return new RsChatStatusItem(data,*pktsize) ; + case RS_PKT_SUBTYPE_CHAT_AVATAR: return new RsChatAvatarItem(data,*pktsize) ; + default: + std::cerr << "Unknown packet type in chat!" << std::endl ; + return NULL ; + } +} + +uint32_t RsChatMsgItem::serial_size() +{ + uint32_t s = 8; /* header */ + s += 4; /* chatFlags */ + s += 4; /* sendTime */ + s += GetTlvWideStringSize(message); + + return s; +} + +uint32_t RsPrivateChatMsgConfigItem::serial_size() +{ + uint32_t s = 8; /* header */ + s += 4; /* version */ + s += GetTlvStringSize(configPeerId); + s += 4; /* chatFlags */ + s += 4; /* configFlags */ + s += 4; /* sendTime */ + s += GetTlvWideStringSize(message); + s += 4; /* recvTime */ + + return s; +} + +uint32_t RsChatStatusItem::serial_size() +{ + uint32_t s = 8; /* header */ + s += 4 ; // flags + s += GetTlvStringSize(status_string); /* status */ + + return s; +} + +uint32_t RsChatAvatarItem::serial_size() +{ + uint32_t s = 8; /* header */ + s += 4 ; // size + s += image_size ; // data + + return s; +} + +RsChatAvatarItem::~RsChatAvatarItem() +{ + if(image_data != NULL) + { + delete[] image_data ; + image_data = NULL ; + } +} + +/* serialise the data to the buffer */ +bool RsChatMsgItem::serialise(void *data, uint32_t& pktsize) +{ + uint32_t tlvsize = serial_size() ; + uint32_t offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize); + +#ifdef CHAT_DEBUG + std::cerr << "RsChatSerialiser::serialiseItem() Header: " << ok << std::endl; + std::cerr << "RsChatSerialiser::serialiseItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt32(data, tlvsize, &offset, chatFlags); + ok &= setRawUInt32(data, tlvsize, &offset, sendTime); + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, message); +#ifdef CHAT_DEBUG + std::cerr << "Serialized the following message:" << std::endl; + std::cerr << "========== BEGIN MESSAGE =========" << std::endl; + for(int i=0;iPeerId()); + configPeerId = ci->PeerId(); + chatFlags = ci->chatFlags; + configFlags = confFlags; + sendTime = ci->sendTime; + message = ci->message; + recvTime = ci->recvTime; +} + +/* get data from RsPrivateChatMsgConfigItem to RsChatMsgItem */ +void RsPrivateChatMsgConfigItem::get(RsChatMsgItem *ci) +{ + ci->PeerId(configPeerId); + ci->chatFlags = chatFlags; + //configFlags not used + ci->sendTime = sendTime; + ci->message = message; + ci->recvTime = recvTime; +} + +RsChatStatusItem::RsChatStatusItem(void *data,uint32_t size) + : RsChatItem(RS_PKT_SUBTYPE_CHAT_STATUS) +{ + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + +#ifdef CHAT_DEBUG + std::cerr << "Building new chat status item." << std::endl ; +#endif + /* get mandatory parts first */ + ok &= getRawUInt32(data, rssize, &offset, &flags); + ok &= GetTlvString(data, rssize, &offset,TLV_TYPE_STR_MSG, status_string); + + if (offset != rssize) + std::cerr << "Size error while deserializing." << std::endl ; + if (!ok) + std::cerr << "Unknown error while deserializing." << std::endl ; +} + +RsChatAvatarItem::RsChatAvatarItem(void *data,uint32_t size) + : RsChatItem(RS_PKT_SUBTYPE_CHAT_STATUS) +{ + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + +#ifdef CHAT_DEBUG + std::cerr << "Building new chat status item." << std::endl ; +#endif + /* get mandatory parts first */ + ok &= getRawUInt32(data, rssize, &offset,&image_size); + + image_data = new unsigned char[image_size] ; + memcpy(image_data,(void*)((unsigned char*)data+offset),image_size) ; + offset += image_size ; + + if (offset != rssize) + std::cerr << "Size error while deserializing." << std::endl ; + if (!ok) + std::cerr << "Unknown error while deserializing." << std::endl ; +} + + +/*************************************************************************/ + + +RsMsgItem::~RsMsgItem() +{ + return; +} + +void RsMsgItem::clear() +{ + msgId = 0; + msgFlags = 0; + sendTime = 0; + recvTime = 0; + subject.clear(); + message.clear(); + + msgto.TlvClear(); + msgcc.TlvClear(); + msgbcc.TlvClear(); + + attachment.TlvClear(); +} + +std::ostream &RsMsgItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsMsgItem", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "msgId (not serialised): " << msgId << std::endl; + printIndent(out, int_Indent); + out << "msgFlags: " << msgFlags << std::endl; + + printIndent(out, int_Indent); + out << "sendTime: " << sendTime << std::endl; + printIndent(out, int_Indent); + out << "recvTime: " << recvTime << std::endl; + + printIndent(out, int_Indent); + out << "Message To: " << std::endl; + msgto.print(out, int_Indent); + + printIndent(out, int_Indent); + out << "Message CC: " << std::endl; + msgcc.print(out, int_Indent); + + printIndent(out, int_Indent); + out << "Message BCC: " << std::endl; + msgbcc.print(out, int_Indent); + + printIndent(out, int_Indent); + std::string cnv_subject(subject.begin(), subject.end()); + out << "subject: " << cnv_subject << std::endl; + + printIndent(out, int_Indent); + std::string cnv_message(message.begin(), message.end()); + out << "msg: " << cnv_message << std::endl; + + printIndent(out, int_Indent); + out << "Attachment: " << std::endl; + attachment.print(out, int_Indent); + + printRsItemEnd(out, "RsMsgItem", indent); + return out; +} + +void RsMsgTagType::clear() +{ + text.clear(); + tagId = 0; + rgb_color = 0; +} + + +void RsMsgTags::clear() +{ + msgId = 0; + tagIds.clear(); +} + +std::ostream& RsMsgTagType::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsMsgTagType", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "rgb_color : " << rgb_color << std::endl; + + + printIndent(out, int_Indent); + out << "text: " << text << std::endl; + + printIndent(out, int_Indent); + out << "tagId: " << tagId << std::endl; + + printRsItemEnd(out, "RsMsgTagTypeItem", indent); + + return out; +} + +std::ostream& RsMsgTags::print(std::ostream &out, uint16_t indent) +{ + + printRsItemBase(out, "RsMsgTagsItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "msgId : " << msgId << std::endl; + + std::list::iterator it; + + for(it=tagIds.begin(); it != tagIds.end(); it++) + { + printIndent(out, int_Indent); + out << "tagId : " << *it << std::endl; + } + + printRsItemEnd(out, "RsMsgTags", indent); + + return out; +} + +RsMsgTagType::~RsMsgTagType() +{ + return; +} + +RsMsgTags::~RsMsgTags() +{ + return; +} + +uint32_t RsMsgSerialiser::sizeMsgItem(RsMsgItem *item) +{ + uint32_t s = 8; /* header */ + s += 4; /* msgFlags */ + s += 4; /* sendTime */ + s += 4; /* recvTime */ + + s += GetTlvWideStringSize(item->subject); + s += GetTlvWideStringSize(item->message); + + s += item->msgto.TlvSize(); + s += item->msgcc.TlvSize(); + s += item->msgbcc.TlvSize(); + s += item->attachment.TlvSize(); + + if (m_bConfiguration) { + // serialise msgId too + s += 4; + } + + return s; +} + +/* serialise the data to the buffer */ +bool RsMsgSerialiser::serialiseMsgItem(RsMsgItem *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeMsgItem(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseItem() Header: " << ok << std::endl; + std::cerr << "RsMsgSerialiser::serialiseItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt32(data, tlvsize, &offset, item->msgFlags); + ok &= setRawUInt32(data, tlvsize, &offset, item->sendTime); + ok &= setRawUInt32(data, tlvsize, &offset, item->recvTime); + + ok &= SetTlvWideString(data,tlvsize,&offset,TLV_TYPE_WSTR_SUBJECT,item->subject); + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_MSG, item->message); + + ok &= item->msgto.SetTlv(data, tlvsize, &offset); + ok &= item->msgcc.SetTlv(data, tlvsize, &offset); + ok &= item->msgbcc.SetTlv(data, tlvsize, &offset); + + ok &= item->attachment.SetTlv(data, tlvsize, &offset); + + if (m_bConfiguration) { + // serialise msgId too + ok &= setRawUInt32(data, tlvsize, &offset, item->msgId); + } + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsMsgItem *RsMsgSerialiser::deserialiseMsgItem(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_MSG != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DEFAULT != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsMsgItem *item = new RsMsgItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= getRawUInt32(data, rssize, &offset, &(item->msgFlags)); + ok &= getRawUInt32(data, rssize, &offset, &(item->sendTime)); + ok &= getRawUInt32(data, rssize, &offset, &(item->recvTime)); + + ok &= GetTlvWideString(data,rssize,&offset,TLV_TYPE_WSTR_SUBJECT,item->subject); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_MSG, item->message); + ok &= item->msgto.GetTlv(data, rssize, &offset); + ok &= item->msgcc.GetTlv(data, rssize, &offset); + ok &= item->msgbcc.GetTlv(data, rssize, &offset); + ok &= item->attachment.GetTlv(data, rssize, &offset); + + if (m_bConfiguration) { + // deserialise msgId too + // ok &= getRawUInt32(data, rssize, &offset, &(item->msgId)); + getRawUInt32(data, rssize, &offset, &(item->msgId)); //use this line for backward compatibility + } + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +uint32_t RsMsgSerialiser::sizeTagItem(RsMsgTagType* item) +{ + uint32_t s = 8; /* header */ + + s += GetTlvStringSize(item->text); + s += 4; /* color */ + s += 4; /* tag id */ + + return s; +} + + +bool RsMsgSerialiser::serialiseTagItem(RsMsgTagType *item, void *data, uint32_t* pktsize) +{ + uint32_t tlvsize = sizeTagItem(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseMsgTagItem() Header: " << ok << std::endl; + std::cerr << "RsMsgSerialiser::serialiseMsgTagItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + + ok &= SetTlvString(data,tlvsize,&offset, TLV_TYPE_STR_NAME, item->text); + ok &= setRawUInt32(data, tlvsize, &offset, item->rgb_color); + ok &= setRawUInt32(data, tlvsize, &offset, item->tagId); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseMsgTagItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsMsgTagType* RsMsgSerialiser::deserialiseTagItem(void *data,uint32_t* pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_MSG != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_MSG_TAG_TYPE != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsMsgTagType *item = new RsMsgTagType(); + item->clear(); + + /* skip the header */ + offset += 8; + + + /* get mandatory parts first */ + ok &= GetTlvString(data,rssize,&offset,TLV_TYPE_STR_NAME,item->text); + ok &= getRawUInt32(data, rssize, &offset, &(item->rgb_color)); + ok &= getRawUInt32(data, rssize, &offset, &(item->tagId)); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +uint32_t RsMsgSerialiser::sizeMsgTagItem(RsMsgTags* item) +{ + uint32_t s = 8; /* header */ + + s += 4; /* msgId */ + s += item->tagIds.size() * 4; /* tagIds */ + + return s; +} + +bool RsMsgSerialiser::serialiseMsgTagItem(RsMsgTags *item, void *data, uint32_t* pktsize) +{ + uint32_t tlvsize = sizeMsgTagItem(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseMsgTagItem() Header: " << ok << std::endl; + std::cerr << "RsMsgSerialiser::serialiseMsgTagItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + ok &= setRawUInt32(data,tlvsize,&offset, item->msgId); + + std::list::iterator mit = item->tagIds.begin(); + for(;mit != item->tagIds.end(); mit++) + { + ok &= setRawUInt32(data, tlvsize, &offset, *mit); + } + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseMsgTagItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsMsgTags* RsMsgSerialiser::deserialiseMsgTagItem(void* data, uint32_t* pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_MSG != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_MSG_TAGS != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsMsgTags *item = new RsMsgTags(); + item->clear(); + + /* skip the header */ + offset += 8; + + + /* get mandatory parts first */ + ok &= getRawUInt32(data, rssize, &offset, &item->msgId); + + uint32_t tagId; + while (offset != rssize) + { + tagId = 0; + + ok &= getRawUInt32(data, rssize, &offset, &tagId); + + item->tagIds.push_back(tagId); + } + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +/************************************** Message SrcId **********************/ + + + +RsMsgSrcId::~RsMsgSrcId() +{ + return; +} + +std::ostream& RsMsgSrcId::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsMsgSrcIdItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "msgId : " << msgId << std::endl; + + printIndent(out, int_Indent); + out << "SrcId: " << srcId << std::endl; + + + printRsItemEnd(out, "RsMsgItem", indent); + + return out; +} + +void RsMsgSrcId::clear() +{ + msgId = 0; + srcId.clear(); + + return; +} + +uint32_t RsMsgSerialiser::sizeMsgSrcIdItem(RsMsgSrcId* item) +{ + uint32_t s = 8; /* header */ + + s += 4; + s += GetTlvStringSize(item->srcId); + + return s; +} + + +bool RsMsgSerialiser::serialiseMsgSrcIdItem(RsMsgSrcId *item, void *data, uint32_t* pktsize) +{ + uint32_t tlvsize = sizeMsgSrcIdItem(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseMsgSrcIdItem() Header: " << ok << std::endl; + std::cerr << "RsMsgSerialiser::serialiseMsgSrcIdItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + ok &= setRawUInt32(data, tlvsize, &offset, item->msgId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, (item->srcId)); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseMsgSrcIdItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsMsgSrcId* RsMsgSerialiser::deserialiseMsgSrcIdItem(void* data, uint32_t* pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_MSG != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_MSG_SRC_TAG != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsMsgSrcId *item = new RsMsgSrcId(); + item->clear(); + + /* skip the header */ + offset += 8; + + + /* get mandatory parts first */ + ok &= getRawUInt32(data, rssize, &offset, &(item->msgId)); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->srcId); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/************************* end of definition of msgSrcId serialisation functions ************************/ + +/************************************** Message ParentId **********************/ + +RsMsgParentId::~RsMsgParentId() +{ + return; +} + +std::ostream& RsMsgParentId::print(std::ostream& out, uint16_t indent) +{ + printRsItemBase(out, "RsMsgParentIdItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "msgId : " << msgId << std::endl; + + printIndent(out, int_Indent); + out << "msgParentId: " << msgParentId << std::endl; + + + printRsItemEnd(out, "RsMsgParentId", indent); + + return out; +} + +void RsMsgParentId::clear() +{ + msgId = 0; + msgParentId = 0; + + return; +} + +uint32_t RsMsgSerialiser::sizeMsgParentIdItem(RsMsgParentId* item) +{ + uint32_t s = 8; /* header */ + + s += 4; // srcId + s += 4; // msgParentId + + return s; +} + +bool RsMsgSerialiser::serialiseMsgParentIdItem(RsMsgParentId *item, void *data, uint32_t* pktsize) +{ + uint32_t tlvsize = sizeMsgParentIdItem(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseMsgParentIdItem() Header: " << ok << std::endl; + std::cerr << "RsMsgSerialiser::serialiseMsgParentIdItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + ok &= setRawUInt32(data, tlvsize, &offset, item->msgId); + ok &= setRawUInt32(data, tlvsize, &offset, item->msgParentId); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialiseMsgParentIdItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsMsgParentId* RsMsgSerialiser::deserialiseMsgParentIdItem(void* data, uint32_t* pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_MSG != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_MSG_PARENT_TAG != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsMsgParentId *item = new RsMsgParentId(); + item->clear(); + + /* skip the header */ + offset += 8; + + + /* get mandatory parts first */ + ok &= getRawUInt32(data, rssize, &offset, &(item->msgId)); + ok &= getRawUInt32(data, rssize, &offset, &(item->msgParentId)); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/************************* end of definition of msgParentId serialisation functions ************************/ + +uint32_t RsMsgSerialiser::size(RsItem *i) +{ + RsMsgItem *mi; + RsMsgTagType *mtt; + RsMsgTags *mts; + RsMsgSrcId *msi; + RsMsgParentId *msp; + + /* in order of frequency */ + if (NULL != (mi = dynamic_cast(i))) + { + return sizeMsgItem(mi); + } + else if (NULL != (msi = dynamic_cast(i))) + { + return sizeMsgSrcIdItem(msi); + } + else if (NULL != (msp = dynamic_cast(i))) + { + return sizeMsgParentIdItem(msp); + } + else if (NULL != (mtt = dynamic_cast(i))) + { + return sizeTagItem(mtt); + } + else if (NULL != (mts = dynamic_cast(i))) + { + return sizeMsgTagItem(mts); + } + + return 0; +} + +bool RsMsgSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::serialise()" << std::endl; +#endif + + RsMsgItem *mi; + RsMsgSrcId* msi; + RsMsgParentId* msp; + RsMsgTagType *mtt; + RsMsgTags *mts; + + + if (NULL != (mi = dynamic_cast(i))) + { + return serialiseMsgItem(mi, data, pktsize); + } + else if (NULL != (msi = dynamic_cast(i))) + { + return serialiseMsgSrcIdItem(msi, data, pktsize); + } + else if (NULL != (msp = dynamic_cast(i))) + { + return serialiseMsgParentIdItem(msp, data, pktsize); + } + else if (NULL != (mtt = dynamic_cast(i))) + { + return serialiseTagItem(mtt, data, pktsize); + } + else if (NULL != (mts = dynamic_cast(i))) + { + return serialiseMsgTagItem(mts, data, pktsize); + } + + return false; +} + +RsItem* RsMsgSerialiser::deserialise(void *data, uint32_t *pktsize) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsMsgSerialiser::deserialise()" << std::endl; +#endif + + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_MSG != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_DEFAULT: + return deserialiseMsgItem(data, pktsize); + break; + case RS_PKT_SUBTYPE_MSG_SRC_TAG: + return deserialiseMsgSrcIdItem(data, pktsize); + break; + case RS_PKT_SUBTYPE_MSG_PARENT_TAG: + return deserialiseMsgParentIdItem(data, pktsize); + break; + case RS_PKT_SUBTYPE_MSG_TAG_TYPE: + return deserialiseTagItem(data, pktsize); + break; + case RS_PKT_SUBTYPE_MSG_TAGS: + return deserialiseMsgTagItem(data, pktsize); + break; + default: + return NULL; + break; + } + + return NULL; +} + + +/*************************************************************************/ + diff --git a/libretroshare/src/serialiser/rsmsgitems.h b/libretroshare/src/serialiser/rsmsgitems.h new file mode 100644 index 000000000..9e8eb3455 --- /dev/null +++ b/libretroshare/src/serialiser/rsmsgitems.h @@ -0,0 +1,351 @@ +#ifndef RS_MSG_ITEMS_H +#define RS_MSG_ITEMS_H + +/* + * libretroshare/src/serialiser: rsmsgitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +/**************************************************************************/ + +/* chat Flags */ +const uint32_t RS_CHAT_FLAG_PRIVATE = 0x0001; +const uint32_t RS_CHAT_FLAG_REQUESTS_AVATAR = 0x0002; +const uint32_t RS_CHAT_FLAG_CONTAINS_AVATAR = 0x0004; +const uint32_t RS_CHAT_FLAG_AVATAR_AVAILABLE = 0x0008; +const uint32_t RS_CHAT_FLAG_CUSTOM_STATE = 0x0010; // used for transmitting peer status string +const uint32_t RS_CHAT_FLAG_PUBLIC = 0x0020; +const uint32_t RS_CHAT_FLAG_REQUEST_CUSTOM_STATE = 0x0040; +const uint32_t RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE = 0x0080; +const uint32_t RS_CHAT_FLAG_PARTIAL_MESSAGE = 0x0100; + +const uint32_t RS_CHATMSG_CONFIGFLAG_INCOMING = 0x0001; + +const uint8_t RS_PKT_SUBTYPE_CHAT_AVATAR = 0x03 ; // default is 0x01 +const uint8_t RS_PKT_SUBTYPE_CHAT_STATUS = 0x04 ; // default is 0x01 +const uint8_t RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG = 0x05 ; // default is 0x01 + +// for defining tags themselves and msg tags +const uint8_t RS_PKT_SUBTYPE_MSG_TAG_TYPE = 0x03; +const uint8_t RS_PKT_SUBTYPE_MSG_TAGS = 0x04; +const uint8_t RS_PKT_SUBTYPE_MSG_SRC_TAG = 0x05; +const uint8_t RS_PKT_SUBTYPE_MSG_PARENT_TAG = 0x06; + + +class RsChatItem: public RsItem +{ + public: + RsChatItem(uint8_t chat_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_CHAT,chat_subtype) {} + + virtual ~RsChatItem() {} + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) = 0 ; + + virtual bool serialise(void *data,uint32_t& size) = 0 ; // Isn't it better that items can serialize themselves ? + virtual uint32_t serial_size() = 0 ; // deserialise is handled using a constructor +}; + +/*! + * For sending chat msgs + * @see p3ChatService + */ +class RsChatMsgItem: public RsChatItem +{ + public: + RsChatMsgItem() :RsChatItem(RS_PKT_SUBTYPE_DEFAULT) {} + RsChatMsgItem(void *data,uint32_t size) ; // deserialization + + virtual ~RsChatMsgItem() {} + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ? + virtual uint32_t serial_size() ; // deserialise is handled using a constructor + + uint32_t chatFlags; + uint32_t sendTime; + std::wstring message; + /* not serialised */ + uint32_t recvTime; +}; + +/*! + * For saving incoming and outgoing chat msgs + * @see p3ChatService + */ +class RsPrivateChatMsgConfigItem: public RsChatItem +{ + public: + RsPrivateChatMsgConfigItem() :RsChatItem(RS_PKT_SUBTYPE_PRIVATECHATMSG_CONFIG) {} + RsPrivateChatMsgConfigItem(void *data,uint32_t size) ; // deserialization + + virtual ~RsPrivateChatMsgConfigItem() {} + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ? + virtual uint32_t serial_size() ; // deserialise is handled using a constructor + + /* set data from RsChatMsgItem to RsPrivateChatMsgConfigItem */ + void set(RsChatMsgItem *ci, const std::string &peerId, uint32_t confFlags); + /* get data from RsPrivateChatMsgConfigItem to RsChatMsgItem */ + void get(RsChatMsgItem *ci); + + std::string configPeerId; + uint32_t chatFlags; + uint32_t configFlags; + uint32_t sendTime; + std::wstring message; + uint32_t recvTime; +}; + +// This class contains activity info for the sending peer: active, idle, typing, etc. +// +class RsChatStatusItem: public RsChatItem +{ + public: + RsChatStatusItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_STATUS) {} + RsChatStatusItem(void *data,uint32_t size) ; // deserialization + + virtual ~RsChatStatusItem() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ? + virtual uint32_t serial_size() ; // deserialise is handled using a constructor + + uint32_t flags ; + std::string status_string; +}; + +// This class contains avatar images in Qt format. +// +class RsChatAvatarItem: public RsChatItem +{ + public: + RsChatAvatarItem() :RsChatItem(RS_PKT_SUBTYPE_CHAT_AVATAR) {} + RsChatAvatarItem(void *data,uint32_t size) ; // deserialization + + virtual ~RsChatAvatarItem() ; + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ? + virtual uint32_t serial_size() ; // deserialise is handled using a constructor + + uint32_t image_size ; // size of data in bytes + unsigned char *image_data ; // image +}; + + +class RsChatSerialiser: public RsSerialType +{ + public: + RsChatSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_CHAT) {} + + virtual uint32_t size (RsItem *item) + { + return static_cast(item)->serial_size() ; + } + virtual bool serialise(RsItem *item, void *data, uint32_t *size) + { + return static_cast(item)->serialise(data,*size) ; + } + virtual RsItem *deserialise (void *data, uint32_t *size) ; +}; + +/**************************************************************************/ + +const uint32_t RS_MSG_FLAGS_OUTGOING = 0x0001; +const uint32_t RS_MSG_FLAGS_PENDING = 0x0002; +const uint32_t RS_MSG_FLAGS_DRAFT = 0x0004; +const uint32_t RS_MSG_FLAGS_NEW = 0x0010; +const uint32_t RS_MSG_FLAGS_TRASH = 0x0020; +const uint32_t RS_MSG_FLAGS_UNREAD_BY_USER = 0x0040; +const uint32_t RS_MSG_FLAGS_REPLIED = 0x0080; +const uint32_t RS_MSG_FLAGS_FORWARDED = 0x0100; +const uint32_t RS_MSG_FLAGS_STAR = 0x0200; + +class RsMsgItem: public RsItem +{ + public: + RsMsgItem() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_MSG, + RS_PKT_SUBTYPE_DEFAULT) + { return; } + + RsMsgItem(uint16_t type) + :RsItem(RS_PKT_VERSION_SERVICE, type, + RS_PKT_SUBTYPE_DEFAULT) + { return; } + +virtual ~RsMsgItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + uint32_t msgFlags; + uint32_t msgId; + + uint32_t sendTime; + uint32_t recvTime; + + std::wstring subject; + std::wstring message; + + RsTlvPeerIdSet msgto; + RsTlvPeerIdSet msgcc; + RsTlvPeerIdSet msgbcc; + + RsTlvFileSet attachment; +}; + +class RsMsgTagType : public RsItem +{ +public: + RsMsgTagType() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_MSG, + RS_PKT_SUBTYPE_MSG_TAG_TYPE) + { return; } + + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + + virtual ~RsMsgTagType(); + virtual void clear(); + + std::string text; + uint32_t rgb_color; + uint32_t tagId; + +}; + +class RsMsgTags : public RsItem +{ +public: + RsMsgTags() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_MSG, + RS_PKT_SUBTYPE_MSG_TAGS) + { return; } + + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + virtual ~RsMsgTags(); + virtual void clear(); + + uint32_t msgId; + std::list tagIds; +}; + +class RsMsgSrcId : public RsItem +{ + +public: + RsMsgSrcId() + : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_MSG, + RS_PKT_SUBTYPE_MSG_SRC_TAG) + { return;} + + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + virtual ~RsMsgSrcId(); + virtual void clear(); + + + uint32_t msgId; + std::string srcId; + +}; + +class RsMsgParentId : public RsItem +{ + +public: + RsMsgParentId() + : RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_MSG, + RS_PKT_SUBTYPE_MSG_PARENT_TAG) + { return;} + + std::ostream &print(std::ostream &out, uint16_t indent = 0); + + virtual ~RsMsgParentId(); + virtual void clear(); + + + uint32_t msgId; + uint32_t msgParentId; + +}; + +class RsMsgSerialiser: public RsSerialType +{ + public: + RsMsgSerialiser(bool bConfiguration = false) + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_MSG), m_bConfiguration (bConfiguration) + { return; } + + RsMsgSerialiser(uint16_t type) + :RsSerialType(RS_PKT_VERSION_SERVICE, type), m_bConfiguration (false) + { return; } + +virtual ~RsMsgSerialiser() { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + + private: + +virtual uint32_t sizeMsgItem(RsMsgItem *); +virtual bool serialiseMsgItem (RsMsgItem *item, void *data, uint32_t *size); +virtual RsMsgItem *deserialiseMsgItem(void *data, uint32_t *size); + +virtual uint32_t sizeTagItem(RsMsgTagType *); +virtual bool serialiseTagItem (RsMsgTagType *item, void *data, uint32_t *size); +virtual RsMsgTagType *deserialiseTagItem(void *data, uint32_t *size); + +virtual uint32_t sizeMsgTagItem(RsMsgTags *); +virtual bool serialiseMsgTagItem (RsMsgTags *item, void *data, uint32_t *size); +virtual RsMsgTags *deserialiseMsgTagItem(void *data, uint32_t *size); + +virtual uint32_t sizeMsgSrcIdItem(RsMsgSrcId *); +virtual bool serialiseMsgSrcIdItem (RsMsgSrcId *item, void *data, uint32_t *size); +virtual RsMsgSrcId *deserialiseMsgSrcIdItem(void *data, uint32_t *size); + +virtual uint32_t sizeMsgParentIdItem(RsMsgParentId *); +virtual bool serialiseMsgParentIdItem (RsMsgParentId *item, void *data, uint32_t *size); +virtual RsMsgParentId *deserialiseMsgParentIdItem(void *data, uint32_t *size); + + + bool m_bConfiguration; // is set to true for saving configuration (enables serialising msgId) +}; + +/**************************************************************************/ + +#endif /* RS_MSG_ITEMS_H */ + + diff --git a/libretroshare/src/serialiser/rsphotoitems.cc b/libretroshare/src/serialiser/rsphotoitems.cc new file mode 100644 index 000000000..7216f95b4 --- /dev/null +++ b/libretroshare/src/serialiser/rsphotoitems.cc @@ -0,0 +1,290 @@ + +/* + * libretroshare/src/serialiser: rsphotoitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsphotoitems.h" +#include "serialiser/rstlvbase.h" + +#define RSSERIAL_DEBUG 1 +#include + +/*************************************************************************/ + +void RsPhotoItem::clear() +{ + srcId.clear(); + photoId.clear(); + size = 0; + + name.clear(); + comment.clear(); + + location.clear(); + date.clear(); + + /* not serialised */ + isAvailable = false; + path.clear(); +} + +std::ostream &RsPhotoItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsPhotoItem", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "srcId: " << srcId << std::endl; + printIndent(out, int_Indent); + out << "photoId: " << photoId << std::endl; + printIndent(out, int_Indent); + out << "size: " << size << std::endl; + + printIndent(out, int_Indent); + out << "name: " << name << std::endl; + + printIndent(out, int_Indent); + std::string cnv_comment(comment.begin(), comment.end()); + out << "msg: " << cnv_comment << std::endl; + + printIndent(out, int_Indent); + out << "location: " << location << std::endl; + printIndent(out, int_Indent); + out << "date: " << date << std::endl; + + printIndent(out, int_Indent); + out << "(NS) isAvailable: " << isAvailable << std::endl; + printIndent(out, int_Indent); + out << "(NS) path: " << path << std::endl; + + printRsItemEnd(out, "RsPhotoItem", indent); + return out; +} + +/*************************************************************************/ +/*************************************************************************/ + +void RsPhotoShowItem::clear() +{ + showId.clear(); + name.clear(); + comment.clear(); + + location.clear(); + date.clear(); + + photos.clear(); +} + +std::ostream &RsPhotoShowItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsPhotoShowItem", indent); + uint16_t int_Indent = indent + 2; + uint16_t int_Indent2 = int_Indent + 2; + + printIndent(out, int_Indent); + out << "showId: " << showId << std::endl; + printIndent(out, int_Indent); + out << "name: " << name << std::endl; + + printIndent(out, int_Indent); + std::string cnv_comment(comment.begin(), comment.end()); + out << "msg: " << cnv_comment << std::endl; + + printIndent(out, int_Indent); + out << "location: " << location << std::endl; + printIndent(out, int_Indent); + out << "date: " << date << std::endl; + + printIndent(out, int_Indent); + out << "Photos in Show: " << photos.size() << std::endl; + + std::list::iterator it; + for(it = photos.begin(); it != photos.end(); it++) + { + printIndent(out, int_Indent2); + out << "PhotoId: " << it->photoId << std::endl; + printIndent(out, int_Indent2 + 2); + std::string cnv_comment2(it->altComment.begin(), it->altComment.end()); + out << "AltComment: " << cnv_comment2 << std::endl; + printIndent(out, int_Indent2 + 2); + out << "Delta T: " << it->deltaT << std::endl; + } + + printRsItemEnd(out, "RsPhotoShowItem", indent); + return out; +} + +RsPhotoRefItem::RsPhotoRefItem() + :deltaT(0) +{ + return; +} + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + +/* TODO serialiser */ + +#if 0 + +uint32_t RsPhotoSerialiser::sizeLink(RsPhotoLinkMsg *item) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(item->rid); + s += 4; /* timestamp */ + s += GetTlvWideStringSize(item->title); + s += GetTlvWideStringSize(item->comment); + s += 4; /* linktype */ + s += GetTlvWideStringSize(item->link); + + return s; +} + +/* serialise the data to the buffer */ +bool RsPhotoSerialiser::serialiseLink(RsPhotoLinkMsg *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeLink(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Header: " << ok << std::endl; + std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Size: " << tlvsize << std::endl; + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->rid); + std::cerr << "RsPhotoLinkSerialiser::serialiseLink() rid: " << ok << std::endl; + + ok &= setRawUInt32(data, tlvsize, &offset, item->timestamp); + std::cerr << "RsPhotoLinkSerialiser::serialiseLink() timestamp: " << ok << std::endl; + + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_TITLE, item->title); + std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Title: " << ok << std::endl; + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_COMMENT, item->comment); + std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Comment: " << ok << std::endl; + + ok &= setRawUInt32(data, tlvsize, &offset, item->linktype); + std::cerr << "RsPhotoLinkSerialiser::serialiseLink() linktype: " << ok << std::endl; + + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_LINK, item->link); + std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Link: " << ok << std::endl; + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsPhotoLinkSerialiser::serialiseLink() Size Error! " << std::endl; + } + + return ok; +} + +RsPhotoLinkMsg *RsPhotoSerialiser::deserialiseLink(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_RANK != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_RANK_LINK != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsPhotoLinkMsg *item = new RsPhotoLinkMsg(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GENID, item->rid); + ok &= getRawUInt32(data, rssize, &offset, &(item->timestamp)); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_TITLE, item->title); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_COMMENT, item->comment); + ok &= getRawUInt32(data, rssize, &offset, &(item->linktype)); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_LINK, item->link); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +uint32_t RsPhotoSerialiser::size(RsItem *item) +{ + return sizeLink((RsPhotoLinkMsg *) item); +} + +bool RsPhotoSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +{ + return serialiseLink((RsPhotoLinkMsg *) item, data, pktsize); +} + +RsItem *RsPhotoSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + return deserialiseLink(data, pktsize); +} + + +#endif + + +/*************************************************************************/ + diff --git a/libretroshare/src/serialiser/rsphotoitems.h b/libretroshare/src/serialiser/rsphotoitems.h new file mode 100644 index 000000000..43a65d1f4 --- /dev/null +++ b/libretroshare/src/serialiser/rsphotoitems.h @@ -0,0 +1,138 @@ +#ifndef P3_PHOTO_ITEMS_H +#define P3_PHOTO_ITEMS_H + +/* + * libretroshare/src/serialiser: rsphotoitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +const uint8_t RS_PKT_SUBTYPE_PHOTO_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM = 0x03; +const uint8_t RS_PKT_SUBTYPE_PHOTO_COMMENT_ITEM = 0x04; + +/**************************************************************************/ + +class RsPhotoItem; +class RsPhotoShowItem; +class RsPhotoCommentItem; + +class RsPhotoItem: public RsItem +{ + public: + + RsPhotoItem() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PHOTO, + RS_PKT_SUBTYPE_PHOTO_ITEM) { return; } +virtual ~RsPhotoItem() { return; } +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string srcId; + std::string photoId; /* same as hash */ + uint64_t size; /* file size */ + + std::string name; + std::wstring comment; + + std::string location; /* TODO: change to TLV */ + std::string date; /* TODO: change to TLV */ + + /* not serialised */ + bool isAvailable; + std::string path; +}; + +/* THIS must be turned into a TLV type + set (TOD) */ +class RsPhotoRefItem +{ + public: + RsPhotoRefItem(); + + std::string photoId; + std::wstring altComment; + uint32_t deltaT; /* in 100ths of sec? */ +}; + +class RsPhotoShowItem: public RsItem +{ + public: + RsPhotoShowItem() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PHOTO, + RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM) { return; } + +virtual ~RsPhotoShowItem() { return; } +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string showId; + + std::string name; + std::wstring comment; + + std::string location; /* TODO -> TLV */ + std::string date; /* TODO -> TLV */ + std::list photos; /* list as ordered */ +}; + +class RsPhotoSerialiser: public RsSerialType +{ + public: + RsPhotoSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_PHOTO) + { return; } +virtual ~RsPhotoSerialiser() + { return; } + +virtual uint32_t size(RsItem *) { return 0; } +virtual bool serialise (RsItem *item, void *data, uint32_t *size) { return false; } +virtual RsItem * deserialise(void *data, uint32_t *size) { return NULL; } + + private: + + /* For RS_PKT_SUBTYPE_PHOTO_ITEM */ +//virtual uint32_t sizeLink(RsPhotoItem *); +//virtual bool serialiseLink (RsPhotoItem *item, void *data, uint32_t *size); +//virtual RsPhotoItem *deserialiseLink(void *data, uint32_t *size); + + /* For RS_PKT_SUBTYPE_PHOTO_SHOW_ITEM */ +//virtual uint32_t sizeLink(RsPhotoShowItem *); +//virtual bool serialiseLink (RsPhotoShowItem *item, void *data, uint32_t *size); +//virtual RsPhotoShowItem *deserialiseLink(void *data, uint32_t *size); + + /* For RS_PKT_SUBTYPE_PHOTO_COMMENT_ITEM */ +//virtual uint32_t sizeLink(RsPhotoCommentItem *); +//virtual bool serialiseLink (RsPhotoCommentItem *item, void *data, uint32_t *size); +//virtual RsPhotoCommentItem *deserialiseLink(void *data, uint32_t *size); + +}; + +/**************************************************************************/ + +#endif /* RS_PHOTO_ITEMS_H */ + diff --git a/libretroshare/src/serialiser/rsrankitems.cc b/libretroshare/src/serialiser/rsrankitems.cc new file mode 100644 index 000000000..a476dbb1c --- /dev/null +++ b/libretroshare/src/serialiser/rsrankitems.cc @@ -0,0 +1,253 @@ + +/* + * libretroshare/src/serialiser: rsbaseitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsrankitems.h" +#include "serialiser/rstlvbase.h" + +#define RSSERIAL_DEBUG 1 +#include + +/*************************************************************************/ + +void RsRankMsg::clear() +{ + rid.clear(); + timestamp = 0; + title.clear(); + comment.clear(); +} + +std::ostream &RsRankMsg::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsRankMsg", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "rid: " << rid << std::endl; + + printIndent(out, int_Indent); + out << "timestamp: " << timestamp << std::endl; + + + printIndent(out, int_Indent); + + std::string cnv_title(title.begin(), title.end()); + out << "msg: " << cnv_title << std::endl; + + printIndent(out, int_Indent); + std::string cnv_comment(comment.begin(), comment.end()); + out << "comment: " << cnv_comment << std::endl; + + printIndent(out, int_Indent); + out << "score: " << score << std::endl; + + printRsItemEnd(out, "RsRankMsg", indent); + return out; +} + +/*************************************************************************/ + +void RsRankLinkMsg::clear() +{ + rid.clear(); + pid.clear(); + timestamp = 0; + title.clear(); + comment.clear(); + score = 0; + linktype = 0; + link.clear(); +} + +std::ostream &RsRankLinkMsg::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsRankLinkMsg", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "rid: " << rid << std::endl; + printIndent(out, int_Indent); + out << "pid: " << pid << std::endl; + + printIndent(out, int_Indent); + out << "timestamp: " << timestamp << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_title(title.begin(), title.end()); + out << "msg: " << cnv_title << std::endl; + + printIndent(out, int_Indent); + std::string cnv_comment(comment.begin(), comment.end()); + out << "comment: " << cnv_comment << std::endl; + + printIndent(out, int_Indent); + out << "score: " << score << std::endl; + + printIndent(out, int_Indent); + out << "linktype: " << linktype << std::endl; + printIndent(out, int_Indent); + std::string cnv_link(link.begin(), link.end()); + out << "link: " << cnv_link << std::endl; + + printRsItemEnd(out, "RsRankLinkMsg", indent); + return out; +} + + +uint32_t RsRankSerialiser::sizeLink(RsRankLinkMsg *item) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(item->rid); + s += GetTlvStringSize(item->pid); + s += 4; /* timestamp */ + s += GetTlvWideStringSize(item->title); + s += GetTlvWideStringSize(item->comment); + s += 4; /* score */ + s += 4; /* linktype */ + s += GetTlvWideStringSize(item->link); + + return s; +} + +/* serialise the data to the buffer */ +bool RsRankSerialiser::serialiseLink(RsRankLinkMsg *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeLink(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->rid); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->pid); + + ok &= setRawUInt32(data, tlvsize, &offset, item->timestamp); + + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_TITLE, item->title); + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_COMMENT, item->comment); + + ok &= setRawUInt32(data, tlvsize, &offset, *((uint32_t *) &(item->score))); + + ok &= setRawUInt32(data, tlvsize, &offset, item->linktype); + + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_LINK, item->link); + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsRankLinkSerialiser::serialiseLink() Size Error! " << std::endl; + } + + return ok; +} + +RsRankLinkMsg *RsRankSerialiser::deserialiseLink(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_RANK != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_RANK_LINK3 != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsRankLinkMsg *item = new RsRankLinkMsg(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GENID, item->rid); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->pid); + ok &= getRawUInt32(data, rssize, &offset, &(item->timestamp)); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_TITLE, item->title); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_COMMENT, item->comment); + ok &= getRawUInt32(data, rssize, &offset, (uint32_t *) &(item->score)); + ok &= getRawUInt32(data, rssize, &offset, &(item->linktype)); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_LINK, item->link); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +uint32_t RsRankSerialiser::size(RsItem *item) +{ + return sizeLink((RsRankLinkMsg *) item); +} + +bool RsRankSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +{ + return serialiseLink((RsRankLinkMsg *) item, data, pktsize); +} + +RsItem *RsRankSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + return deserialiseLink(data, pktsize); +} + + + +/*************************************************************************/ + diff --git a/libretroshare/src/serialiser/rsrankitems.h b/libretroshare/src/serialiser/rsrankitems.h new file mode 100644 index 000000000..22dbdfa0b --- /dev/null +++ b/libretroshare/src/serialiser/rsrankitems.h @@ -0,0 +1,115 @@ +#ifndef RS_RANK_ITEMS_H +#define RS_RANK_ITEMS_H + +/* + * libretroshare/src/serialiser: rsrankitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +const uint8_t RS_PKT_SUBTYPE_RANK_OLD_LINK = 0x02; /* defunct - don't use! */ +const uint8_t RS_PKT_SUBTYPE_RANK_OLD_LINK2 = 0x03; +const uint8_t RS_PKT_SUBTYPE_RANK_LINK3 = 0x04; + +const uint8_t RS_PKT_SUBTYPE_RANK_PHOTO = 0x05; + +/**************************************************************************/ + + +class RsRankMsg: public RsItem +{ + public: + RsRankMsg(uint8_t subtype) + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_RANK, + subtype) { return; } +virtual ~RsRankMsg() { return; } +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string rid; /* Random Id */ + std::string pid; /* Peer Id (cannot use RsItem::PeerId - as FoF transport!) */ + uint32_t timestamp; + std::wstring title; + std::wstring comment; + int32_t score; +}; + + +/* Flags */ +const uint32_t RS_LINK_TYPE_WEB = 0x0001; +const uint32_t RS_LINK_TYPE_OFF = 0x0002; + +class RsRankLinkMsg: public RsRankMsg +{ + public: + RsRankLinkMsg() + :RsRankMsg(RS_PKT_SUBTYPE_RANK_LINK3) { return; } +virtual ~RsRankLinkMsg() { return; } +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + /**** SAME as RsRankMsg **** + std::string rid; + uint32_t timestamp; + std::wstring title; + std::wstring comment; + int32_t score; + ***************************/ + + /* Link specific Fields */ + uint32_t linktype; /* to be used later! */ + std::wstring link; +}; + +class RsRankSerialiser: public RsSerialType +{ + public: + RsRankSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_RANK) + { return; } +virtual ~RsRankSerialiser() + { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + + /* For RS_PKT_SUBTYPE_RANK_LINK */ +virtual uint32_t sizeLink(RsRankLinkMsg *); +virtual bool serialiseLink (RsRankLinkMsg *item, void *data, uint32_t *size); +virtual RsRankLinkMsg *deserialiseLink(void *data, uint32_t *size); + +}; + +/**************************************************************************/ + +#endif /* RS_RANK_ITEMS_H */ + + diff --git a/libretroshare/src/serialiser/rsserial.cc b/libretroshare/src/serialiser/rsserial.cc new file mode 100644 index 000000000..063b46741 --- /dev/null +++ b/libretroshare/src/serialiser/rsserial.cc @@ -0,0 +1,521 @@ + +/* + * libretroshare/src/serialiser: rsserial.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsserial.h" +#include "util/rsthreads.h" + +#include +#include +#include +#include + +/*** +#define RSSERIAL_DEBUG 1 +***/ + +#ifdef RSSERIAL_DEBUG + #include +#endif + +RsItem::RsItem(uint32_t t) +:type(t) +{ + return; +} + +#ifdef DO_STATISTICS +class Counter +{ + public: + Counter(int i): _i(i) {} + Counter(): _i(0) {} + + int v() const { return _i ; } + int& v() { return _i ; } + private: + int _i ; +}; + + static RsMutex smtx ; + static std::map size_hits ; + static int nb_rsitem_creations = 0 ; + static int total_rsitem_mallocs = 0 ; + static int total_rsitem_frees = 0 ; + static int total_rsitem_freed = 0 ; + static time_t last_time = 0 ; + +void *RsItem::operator new(size_t s) +{ +// std::cerr << "New RsItem: s=" << s << std::endl; + + RsStackMutex m(smtx) ; + + ++size_hits[ s ].v() ; + + time_t now = time(NULL); + ++nb_rsitem_creations ; + total_rsitem_mallocs += s ; + + if(last_time + 20 < now) + { + std::cerr << "Memory statistics:" << std::endl; + std::cerr << " Total RsItem memory: " << total_rsitem_mallocs << std::endl; + std::cerr << " Total RsItem creations: " << nb_rsitem_creations << std::endl; + std::cerr << " Total RsItem freed memory: " << total_rsitem_freed << std::endl; + std::cerr << " Total RsItem deletions: " << total_rsitem_frees << std::endl; + std::cerr << "Now printing histogram:" << std::endl; + + for(std::map::const_iterator it(size_hits.begin());it!=size_hits.end();++it) + std::cerr << it->first << " " << it->second.v() << std::endl; + last_time = now ; + } + + RsItem *a = static_cast(::operator new(s)) ; + return a ; +} +void RsItem::operator delete(void *p,size_t s) +{ +// std::cerr << "Delete RsItem: s=" << s << std::endl; + + RsStackMutex m(smtx) ; + total_rsitem_freed += s ; + ++total_rsitem_frees ; + + ::operator delete(p) ; +} +#endif + +RsItem::RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype) +{ + type = (ver << 24) + (cls << 16) + (t << 8) + subtype; + return; +} + +RsItem::~RsItem() +{ + return; +} + + +uint32_t RsItem::PacketId() +{ + return type; +} + +uint8_t RsItem::PacketVersion() +{ + return (type >> 24); +} + + +uint8_t RsItem::PacketClass() +{ + return (type >> 16) & 0xFF; +} + + +uint8_t RsItem::PacketType() +{ + return (type >> 8) & 0xFF; +} + + +uint8_t RsItem::PacketSubType() +{ + return (type & 0xFF); +} + + + /* For Service Packets */ +RsItem::RsItem(uint8_t ver, uint16_t service, uint8_t subtype) +{ + type = (ver << 24) + (service << 8) + subtype; + return; +} + +uint16_t RsItem::PacketService() +{ + return (type >> 8) & 0xFFFF; +} + + + +RsSerialType::RsSerialType(uint32_t t) + :type(t & 0xFFFFFF00) +{ + return; +} + +RsSerialType::RsSerialType(uint8_t ver, uint8_t cls, uint8_t t) +{ + type = (ver << 24) + (cls << 16) + (t << 8); + return; +} + +RsSerialType::RsSerialType(uint8_t ver, uint16_t service) +{ + type = (ver << 24) + (service << 8); + return; +} + +RsSerialType::~RsSerialType() +{ + return; +} + +uint32_t RsSerialType::size(RsItem *) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialType::size()" << std::endl; +#endif + + /* base size: type + length */ + return 8; +} + +bool RsSerialType::serialise(RsItem *item, void *data, uint32_t *size) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialType::serialise()" << std::endl; +#endif + return false; +} + +RsItem * RsSerialType::deserialise(void *data, uint32_t *size) +{ +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialType::deserialise()" << std::endl; +#endif + return NULL; +} + +uint32_t RsSerialType::PacketId() +{ + return type; +} + + + + +RsSerialiser::RsSerialiser() +{ + return; +} + + +RsSerialiser::~RsSerialiser() +{ + /* clean up the map */ + std::map::iterator it; + for(it = serialisers.begin(); it != serialisers.end(); it++) + { + delete (it->second); + } + serialisers.clear(); + return; +} + + + +bool RsSerialiser::addSerialType(RsSerialType *serialiser) +{ + uint32_t type = (serialiser->PacketId() & 0xFFFFFF00); + std::map::iterator it; + if (serialisers.end() != (it = serialisers.find(type))) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialiser::addSerialType() Error Serialiser already exists!"; + std::cerr << std::endl; +#endif + return false; + } + + serialisers[type] = serialiser; + return true; +} + + + +uint32_t RsSerialiser::size(RsItem *item) +{ + /* find the type */ + uint32_t type = (item->PacketId() & 0xFFFFFF00); + std::map::iterator it; + + if (serialisers.end() == (it = serialisers.find(type))) + { + /* remove 8 more bits -> try again */ + type &= 0xFFFF0000; + if (serialisers.end() == (it = serialisers.find(type))) + { + /* one more try */ + type &= 0xFF000000; + if (serialisers.end() == (it = serialisers.find(type))) + { + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialiser::size() serialiser missing!"; + + std::ostringstream out; + out << std::hex << item->PacketId(); + + std::cerr << "RsSerialiser::size() PacketId: "; + std::cerr << out.str(); + std::cerr << std::endl; +#endif + return 0; + } + } + } + +#ifdef RSSERIAL_DEBUG + std::ostringstream out; + out << std::hex << "RsSerialiser::size() Item->PacketId(): " << item->PacketId(); + out << " matched to Serialiser Type: " << type; + std::cerr << out.str() << std::endl; +#endif + + return (it->second)->size(item); +} + +bool RsSerialiser::serialise (RsItem *item, void *data, uint32_t *size) +{ + /* find the type */ + uint32_t type = (item->PacketId() & 0xFFFFFF00); + std::map::iterator it; + + if (serialisers.end() == (it = serialisers.find(type))) + { + /* remove 8 more bits -> try again */ + type &= 0xFFFF0000; + if (serialisers.end() == (it = serialisers.find(type))) + { + /* one more try */ + type &= 0xFF000000; + if (serialisers.end() == (it = serialisers.find(type))) + { + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialiser::serialise() serialiser missing!"; + std::ostringstream out; + out << std::hex << item->PacketId(); + + std::cerr << "RsSerialiser::serialise() PacketId: "; + std::cerr << out.str(); + std::cerr << std::endl; +#endif + return false; + } + } + } + +#ifdef RSSERIAL_DEBUG + std::ostringstream out; + out << std::hex << "RsSerialiser::serialise() Item->PacketId(): " << item->PacketId(); + out << " matched to Serialiser Type: " << type; + std::cerr << out.str() << std::endl; +#endif + + return (it->second)->serialise(item, data, size); +} + + + +RsItem * RsSerialiser::deserialise(void *data, uint32_t *size) +{ + /* find the type */ + if (*size < 8) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialiser::deserialise() Not Enough Data(1)"; + std::cerr << std::endl; +#endif + return NULL; + } + + uint32_t type = (getRsItemId(data) & 0xFFFFFF00); + uint32_t pkt_size = getRsItemSize(data); + + if (pkt_size < *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialiser::deserialise() Not Enough Data(2)"; + std::cerr << std::endl; +#endif + return NULL; + } + + /* store the packet size to return the amount we should use up */ + *size = pkt_size; + + std::map::iterator it; + if (serialisers.end() == (it = serialisers.find(type))) + { + /* remove 8 more bits -> try again */ + type &= 0xFFFF0000; + if (serialisers.end() == (it = serialisers.find(type))) + { + /* one more try */ + type &= 0xFF000000; + if (serialisers.end() == (it = serialisers.find(type))) + { + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialiser::deserialise() deserialiser missing!"; + std::ostringstream out; + out << std::hex << getRsItemId(data); + + std::cerr << "RsSerialiser::deserialise() PacketId: "; + std::cerr << out.str(); + std::cerr << std::endl; +#endif + return NULL; + } + } + } + + RsItem *item = (it->second)->deserialise(data, &pkt_size); + if (!item) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialiser::deserialise() Failed!"; + std::cerr << std::endl; +#endif + return NULL; + } + + if (pkt_size != *size) + { +#ifdef RSSERIAL_DEBUG + std::cerr << "RsSerialiser::deserialise() Warning: size mismatch!"; + std::cerr << std::endl; +#endif + } + return item; +} + + +bool setRsItemHeader(void *data, uint32_t size, uint32_t type, uint32_t pktsize) +{ + if (size < 8) + return false; + + uint32_t offset = 0; + bool ok = true; + ok &= setRawUInt32(data, 8, &offset, type); + ok &= setRawUInt32(data, 8, &offset, pktsize); + + return ok; +} + + + +uint32_t getRsItemId(void *data) +{ + uint32_t type = 0; + uint32_t offset = 0; + getRawUInt32(data, 4, &offset, &type); + return type; +} + + +uint32_t getRsItemSize(void *data) +{ + uint32_t size = 0; + uint32_t offset = 4; + getRawUInt32(data, 8, &offset, &size); + return size; +} + +uint8_t getRsItemVersion(uint32_t type) +{ + return (type >> 24); +} + +uint8_t getRsItemClass(uint32_t type) +{ + return (type >> 16) & 0xFF; +} + +uint8_t getRsItemType(uint32_t type) +{ + return (type >> 8) & 0xFF; +} + +uint8_t getRsItemSubType(uint32_t type) +{ + return (type & 0xFF); +} + +uint16_t getRsItemService(uint32_t type) +{ + return (type >> 8) & 0xFFFF; +} + + +std::ostream &printRsItemBase(std::ostream &out, std::string clsName, uint16_t indent) +{ + printIndent(out, indent); + out << "RsItem: " << clsName << " ####################################"; + out << std::endl; + return out; +} + +std::ostream &printRsItemEnd(std::ostream &out, std::string clsName, uint16_t indent) +{ + printIndent(out, indent); + out << "###################### " << clsName << " #####################"; + out << std::endl; + return out; +} + +std::ostream &RsRawItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsRawItem", indent); + printIndent(out, indent); + out << "Size: " << len << std::endl; + printRsItemEnd(out, "RsRawItem", indent); + return out; +} + + +uint32_t getRsPktMaxSize() +{ + //return 65535; /* 2^16 (old artifical low size) */ + //return 1048575; /* 2^20 -1 (Too Big! - must remove fixed static buffers first) */ + /* Remember that every pqistreamer allocates an input buffer of this size! + * So don't make it too big! + */ + return 262143; /* 2^18 -1 */ +} + + +uint32_t getRsPktBaseSize() +{ + return 8; /* 4 + 4 */ +} + diff --git a/libretroshare/src/serialiser/rsserial.h b/libretroshare/src/serialiser/rsserial.h new file mode 100644 index 000000000..05ca80eb8 --- /dev/null +++ b/libretroshare/src/serialiser/rsserial.h @@ -0,0 +1,204 @@ +#ifndef RS_BASE_SERIALISER_H +#define RS_BASE_SERIALISER_H + +/* + * libretroshare/src/serialiser: rsserial.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************* + * This is the Top-Level serialiser/deserialise, + * + * Data is Serialised into the following format + * + * ----------------------------------------- + * | TYPE (4 bytes) | Size (4 bytes) | + * ----------------------------------------- + * | | + * | Data .... | + * | | + * ----------------------------------------- + * + * Size is the total size of the packet (including the 8 byte header) + * Type is composed of: + * + * 8 bits: Version (0x01) + * 8 bits: Class + * 8 bits: Type + * 8 bits: SubType + ******************************************************************/ + +#include + +const uint8_t RS_PKT_VERSION1 = 0x01; +const uint8_t RS_PKT_VERSION_SERVICE = 0x02; + +const uint8_t RS_PKT_CLASS_BASE = 0x01; +const uint8_t RS_PKT_CLASS_CONFIG = 0x02; + +const uint8_t RS_PKT_SUBTYPE_DEFAULT = 0x01; /* if only one subtype */ + + +class RsItem: public RsMemoryManagement::SmallObject +{ + public: + RsItem(uint32_t t); + RsItem(uint8_t ver, uint8_t cls, uint8_t t, uint8_t subtype); +#ifdef DO_STATISTICS + void *operator new(size_t s) ; + void operator delete(void *,size_t s) ; +#endif + +virtual ~RsItem(); +virtual void clear() = 0; +virtual std::ostream &print(std::ostream &out, uint16_t indent = 0) = 0; + + /* source / destination id */ +const std::string& PeerId() const { return peerId; } +void PeerId(const std::string& id) { peerId = id; } + + /* complete id */ +uint32_t PacketId(); + + /* id parts */ +uint8_t PacketVersion(); +uint8_t PacketClass(); +uint8_t PacketType(); +uint8_t PacketSubType(); + + /* For Service Packets */ + RsItem(uint8_t ver, uint16_t service, uint8_t subtype); +uint16_t PacketService(); /* combined Packet class/type (mid 16bits) */ + +typedef enum { CONTROL_QUEUE, DATA_QUEUE } QueueType ; +virtual QueueType queueType() const { return CONTROL_QUEUE ; } + + private: +uint32_t type; +std::string peerId; +}; + + +class RsSerialType +{ + public: + RsSerialType(uint32_t t); /* only uses top 24bits */ + RsSerialType(uint8_t ver, uint8_t cls, uint8_t t); + RsSerialType(uint8_t ver, uint16_t service); + +virtual ~RsSerialType(); + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + +uint32_t PacketId(); + private: +uint32_t type; +}; + + +class RsSerialiser +{ + public: + RsSerialiser(); + ~RsSerialiser(); + bool addSerialType(RsSerialType *type); + + uint32_t size(RsItem *); + bool serialise (RsItem *item, void *data, uint32_t *size); + RsItem * deserialise(void *data, uint32_t *size); + + + private: + std::map serialisers; +}; + +bool setRsItemHeader(void *data, uint32_t size, uint32_t type, uint32_t pktsize); + +/* Extract Header Information from Packet */ +uint32_t getRsItemId(void *data); +uint32_t getRsItemSize(void *data); + +uint8_t getRsItemVersion(uint32_t type); +uint8_t getRsItemClass(uint32_t type); +uint8_t getRsItemType(uint32_t type); +uint8_t getRsItemSubType(uint32_t type); + +uint16_t getRsItemService(uint32_t type); + +/* size constants */ +uint32_t getRsPktBaseSize(); +uint32_t getRsPktMaxSize(); + + + +/* helper fns for printing */ +std::ostream &printRsItemBase(std::ostream &o, std::string n, uint16_t i); +std::ostream &printRsItemEnd(std::ostream &o, std::string n, uint16_t i); + +/* defined in rstlvtypes.cc - redeclared here for ease */ +std::ostream &printIndent(std::ostream &out, uint16_t indent); +/* Wrapper class for data that is serialised somewhere else */ + +class RsRawItem: public RsItem +{ + public: + RsRawItem(uint32_t t, uint32_t size) + :RsItem(t), len(size), _queue_type(RsItem::CONTROL_QUEUE) + { data = malloc(len);} + +virtual ~RsRawItem() + { + if (data) + free(data); + data = NULL; + len = 0; + } + +uint32_t getRawLength() { return len; } +void * getRawData() { return data; } + +virtual void clear() { return; } /* what can it do? */ +virtual std::ostream &print(std::ostream &out, uint16_t indent = 0); + +virtual RsItem::QueueType queueType() const { return _queue_type ;} +void setQueueType(const RsItem::QueueType& t) { _queue_type = t ;} + + private: + void *data; + uint32_t len; + RsItem::QueueType _queue_type ; +}; + + + +#endif /* RS_BASE_SERIALISER_H */ diff --git a/libretroshare/src/serialiser/rsserviceids.h b/libretroshare/src/serialiser/rsserviceids.h new file mode 100644 index 000000000..afcad1de8 --- /dev/null +++ b/libretroshare/src/serialiser/rsserviceids.h @@ -0,0 +1,111 @@ +#ifndef RS_SERVICE_IDS_H +#define RS_SERVICE_IDS_H + +/* + * libretroshare/src/serialiser: rsserviceids.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +/* Single place for Cache/Service Ids (uint16_t) + * to 64K of them.... + * + * Some Services/Caches are only msgs or caches... + * but they need to be combined so that the messages/caches + * can easily be aligned. + * + */ + +/* These are Cache Only */ +const uint16_t RS_SERVICE_TYPE_FILE_INDEX = 0x0001; + +/* These are Services only */ +const uint16_t RS_SERVICE_TYPE_DISC = 0x0011; +const uint16_t RS_SERVICE_TYPE_CHAT = 0x0012; +const uint16_t RS_SERVICE_TYPE_MSG = 0x0013; +const uint16_t RS_SERVICE_TYPE_TURTLE = 0x0014; +const uint16_t RS_SERVICE_TYPE_TUNNEL = 0x0015; + +/* Combined Cache/Service ids */ + +/****************** BELOW ARE ONLY THEORETICAL (CAN BE CHANGED) *****/ +/* + * If you are planning on making a new service.... + * Test it out with an ID in the range from 0xf000 - 0xffff + * And Change the ID everytime you make significant changes to the + * data structures... + * + * eg. + * const uint16_t RS_SERVICE_TYPE_DISTRIB_O1 = 0xf110; // First Revision. + * const uint16_t RS_SERVICE_TYPE_DISTRIB_O2 = 0xf111; // Second Revision. + * const uint16_t RS_SERVICE_TYPE_DISTRIB = 0xf112; // Final Revision. + * + * This minimises the chances of your new serialisers messing with + * other existing, older, or proposed services. + * + * ONLY MOVE your Id once the service has been finalised. + * + */ + + /*! for Qblog service (Cache Only) */ +const uint16_t RS_SERVICE_TYPE_QBLOG = 0xf010; + + /* Status - Service only */ +const uint16_t RS_SERVICE_TYPE_STATUS = 0xf020; + + /* Proxy - Service only */ +const uint16_t RS_SERVICE_TYPE_PROXY = 0xf030; + + /* Photo - Cache Only */ +const uint16_t RS_SERVICE_TYPE_PHOTO = 0xf040; + +/* Caches based on p3distrib (Cache Only) + * DUMMY IDS until testing is finished + */ +const uint16_t RS_SERVICE_TYPE_DISTRIB = 0xf110; +const uint16_t RS_SERVICE_TYPE_FORUM = 0xf120; +const uint16_t RS_SERVICE_TYPE_CHANNEL = 0xf130; +const uint16_t RS_SERVICE_TYPE_CHANNEL_SOCKET = 0xf140; + +/* Games/External Apps - Service Only */ +const uint16_t RS_SERVICE_TYPE_GAME_LAUNCHER = 0xf200; +const uint16_t RS_SERVICE_TYPE_PORT = 0xf201; + +/* Example Games (NOT USED YET!) */ +/* Board Games */ +const uint16_t RS_SERVICE_TYPE_GAME_QTCHESS = 0xf211; +const uint16_t RS_SERVICE_TYPE_GAME_QGO = 0xf212; + +/* Card Games */ +const uint16_t RS_SERVICE_TYPE_GAME_BIGTWO = 0xf213; +const uint16_t RS_SERVICE_TYPE_GAME_POKER = 0xf214; + + + + + + +#endif /* RS_SERVICE_IDS_H */ + + diff --git a/libretroshare/src/serialiser/rsstatusitems.cc b/libretroshare/src/serialiser/rsstatusitems.cc new file mode 100644 index 000000000..7ba7d5a29 --- /dev/null +++ b/libretroshare/src/serialiser/rsstatusitems.cc @@ -0,0 +1,175 @@ +/* + * libretroshare/src/serialiser: rsstatusitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Vinny Do. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsstatusitems.h" +#include "serialiser/rsbaseserial.h" + +/*** +#define RSSERIAL_DEBUG 1 +***/ + +#include + +/*************************************************************************/ + +RsStatusItem::~RsStatusItem() +{ + return; +} + +void RsStatusItem::clear() +{ + sendTime = 0; + status = 0; +} + +std::ostream &RsStatusItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsStatusItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "sendTime: " << sendTime << std::endl; + + printIndent(out, int_Indent); + out << "status: " << status << std::endl; + + printRsItemEnd(out, "RsStatusItem", indent); + return out; +} + +uint32_t RsStatusSerialiser::sizeItem(RsStatusItem *item) +{ + uint32_t s = 8; /* header */ + s += 4; /* sendTime */ + s += 4; /* status */ + + return s; +} + +/* serialise the data to the buffer */ +bool RsStatusSerialiser::serialiseItem(RsStatusItem *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeItem(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsStatusSerialiser::serialiseItem() Header: " << ok << std::endl; + std::cerr << "RsStatusSerialiser::serialiseItem() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt32(data, tlvsize, &offset, item->sendTime); + ok &= setRawUInt32(data, tlvsize, &offset, item->status); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsStatusSerialiser::serialiseItem() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsStatusItem *RsStatusSerialiser::deserialiseItem(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_STATUS != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DEFAULT != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsStatusItem *item = new RsStatusItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= getRawUInt32(data, rssize, &offset, &(item->sendTime)); + ok &= getRawUInt32(data, rssize, &offset, &(item->status)); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +uint32_t RsStatusSerialiser::size(RsItem *item) +{ + return sizeItem((RsStatusItem *) item); +} + +bool RsStatusSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +{ + return serialiseItem((RsStatusItem *) item, data, pktsize); +} + +RsItem *RsStatusSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + return deserialiseItem(data, pktsize); +} + +/*************************************************************************/ diff --git a/libretroshare/src/serialiser/rsstatusitems.h b/libretroshare/src/serialiser/rsstatusitems.h new file mode 100644 index 000000000..688be6a3c --- /dev/null +++ b/libretroshare/src/serialiser/rsstatusitems.h @@ -0,0 +1,79 @@ +#ifndef RS_STATUS_ITEMS_H +#define RS_STATUS_ITEMS_H + +/* + * libretroshare/src/serialiser: rsstatusitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Vinny Do. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" + +/**************************************************************************/ + +class RsStatusItem: public RsItem +{ + public: + RsStatusItem() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_STATUS, + RS_PKT_SUBTYPE_DEFAULT) + { return; } +virtual ~RsStatusItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + uint32_t sendTime; + + uint32_t status; + + /* not serialised */ + uint32_t recvTime; +}; + +class RsStatusSerialiser: public RsSerialType +{ + public: + RsStatusSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_STATUS) + { return; } +virtual ~RsStatusSerialiser() + { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + +virtual uint32_t sizeItem(RsStatusItem *); +virtual bool serialiseItem (RsStatusItem *item, void *data, uint32_t *size); +virtual RsStatusItem *deserialiseItem(void *data, uint32_t *size); + + +}; + +/**************************************************************************/ + +#endif /* RS_STATUS_ITEMS_H */ + + diff --git a/libretroshare/src/serialiser/rstlvaddrs.cc b/libretroshare/src/serialiser/rstlvaddrs.cc new file mode 100644 index 000000000..c3f504e83 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvaddrs.cc @@ -0,0 +1,305 @@ + +/* + * libretroshare/src/serialiser: rstlvtypes.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie, Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rstlvaddrs.h" + +#include "rstlvbase.h" +#include "rstlvtypes.h" +#include "rsbaseserial.h" +#include "util/rsprint.h" +#include +#include +#include +#include + + +/************************************* RsTlvIpAddressInfo ************************************/ + +RsTlvIpAddressInfo::RsTlvIpAddressInfo() + :RsTlvItem(), seenTime(0), source(0) +{ + sockaddr_clear(&addr); + return; +} + +void RsTlvIpAddressInfo::TlvClear() +{ + sockaddr_clear(&addr); + seenTime = 0; + source = 0; +} + +uint32_t RsTlvIpAddressInfo::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header + IpAddr + 8 for time & 4 for size */ + + s += GetTlvIpAddrPortV4Size(); + s += 8; // seenTime + s += 4; // source + + return s; + +} + +bool RsTlvIpAddressInfo::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + /* add mandatory parts first */ + + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS_INFO, tlvsize); + + ok &= SetTlvIpAddrPortV4(data, tlvend, offset, TLV_TYPE_IPV4_LAST, &addr); + ok &= setRawUInt64(data, tlvend, offset, seenTime); + ok &= setRawUInt32(data, tlvend, offset, source); + + return ok; + +} + + +bool RsTlvIpAddressInfo::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_ADDRESS_INFO) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + ok &= GetTlvIpAddrPortV4(data, tlvend, offset, TLV_TYPE_IPV4_LAST, &addr); + ok &= getRawUInt64(data, tlvend, offset, &(seenTime)); + ok &= getRawUInt32(data, tlvend, offset, &(source)); + + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvIpAddressInfo::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; + +} + + +std::ostream &RsTlvIpAddressInfo::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvIpAddressInfo", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Address:" << rs_inet_ntoa(addr.sin_addr); + out << ":" << htons(addr.sin_port) << std::endl; + + printIndent(out, int_Indent); + out << "SeenTime:" << seenTime; + out << std::endl; + + printIndent(out, int_Indent); + out << "Source:" << source; + out << std::endl; + + printEnd(out, "RsTlvIpAddressInfo", indent); + return out; +} + + + + +/************************************* RsTlvIpAddrSet ************************************/ + +void RsTlvIpAddrSet::TlvClear() +{ + addrs.clear(); +} + +uint32_t RsTlvIpAddrSet::TlvSize() +{ + + uint32_t s = TLV_HEADER_SIZE; /* header */ + + std::list::iterator it; + + + if(!addrs.empty()) + { + + for(it = addrs.begin(); it != addrs.end() ; ++it) + s += it->TlvSize(); + + } + + return s; +} + +bool RsTlvIpAddrSet::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS_SET , tlvsize); + + if(!addrs.empty()) + { + std::list::iterator it; + + for(it = addrs.begin(); it != addrs.end() ; ++it) + ok &= it->SetTlv(data, size, offset); + } + + +return ok; + +} + + +bool RsTlvIpAddrSet::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_ADDRESS_SET) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + switch(tlvsubtype) + { + case TLV_TYPE_ADDRESS_INFO: + { + RsTlvIpAddressInfo addr; + ok &= addr.GetTlv(data, size, offset); + if (ok) + { + addrs.push_back(addr); + } + } + break; + default: + ok &= SkipUnknownTlv(data, tlvend, offset); + break; + + } + + if (!ok) + break; + } + + + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvIpAddrSet::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +// prints out contents of RsTlvIpAddrSet +std::ostream &RsTlvIpAddrSet::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvIpAddrSet", indent); + uint16_t int_Indent = indent + 2; + + std::list::iterator it; + for(it = addrs.begin(); it != addrs.end() ; ++it) + it->print(out, int_Indent); + + printEnd(out, "RsTlvIpAddrSet", indent); + return out; +} + + +/************************************* RsTlvIpAddressInfo ************************************/ + diff --git a/libretroshare/src/serialiser/rstlvaddrs.h b/libretroshare/src/serialiser/rstlvaddrs.h new file mode 100644 index 000000000..3de93ad66 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvaddrs.h @@ -0,0 +1,70 @@ +#ifndef RS_TLV_ADDRS_TYPES_H +#define RS_TLV_ADDRS_TYPES_H + +/* + * libretroshare/src/serialiser: rstlvaddrs.h + * + * RetroShare Serialiser. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/******************************************************************* + * These are the Compound TLV structures that must be (un)packed. + ******************************************************************/ + +#include +#include "serialiser/rstlvtypes.h" +#include "util/rsnet.h" + + +class RsTlvIpAddressInfo: public RsTlvItem +{ + public: + RsTlvIpAddressInfo(); +virtual ~RsTlvIpAddressInfo() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + struct sockaddr_in addr; // Mandatory : + uint64_t seenTime; // Mandatory : + uint32_t source; // Mandatory : +}; + +class RsTlvIpAddrSet: public RsTlvItem +{ + public: + RsTlvIpAddrSet() { return; } +virtual ~RsTlvIpAddrSet() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + std::list addrs; // Mandatory : +}; + + +#endif + diff --git a/libretroshare/src/serialiser/rstlvbase.cc b/libretroshare/src/serialiser/rstlvbase.cc new file mode 100644 index 000000000..b672c089b --- /dev/null +++ b/libretroshare/src/serialiser/rstlvbase.cc @@ -0,0 +1,678 @@ + +/* + * libretroshare/src/serialiser: rstlvbase.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie, Horatio, Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rstlvbase.h" +#include "serialiser/rsbaseserial.h" + +//********************* + +// A facility func +inline void* right_shift_void_pointer(void* p, uint32_t len) { + + return (void*)( (uint8_t*)p + len); +} +//********************* + +#define TLV_BASE_DEBUG 1 + +/**** Basic TLV Functions ****/ +uint32_t GetTlvSize(void *data) { + if (!data) + return 0; + + uint32_t len; + + void * from =right_shift_void_pointer(data, TLV_HEADER_TYPE_SIZE); + + memcpy((void *)&len, from , TLV_HEADER_LEN_SIZE); + + len = ntohl(len); + + return len; +} + +uint16_t GetTlvType(void *data) { + if (!data) + return 0; + + uint16_t type; + + memcpy((void*)&type, data, TLV_HEADER_TYPE_SIZE); + + type = ntohs(type); + + return type; + +} + +//tested +bool SetTlvBase(void *data, uint32_t size, uint32_t *offset, uint16_t type, + uint32_t len) { + if (!data) + return false; + if (!offset) + return false; + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t type_n = htons(type); + + //copy type_n to (data+*offset) + void* to = right_shift_void_pointer(data, *offset); + memcpy(to , (void*)&type_n, TLV_HEADER_TYPE_SIZE); + + uint32_t len_n =htonl(len); + //copy len_n to (data + *offset +2) + to = right_shift_void_pointer(to, TLV_HEADER_TYPE_SIZE); + memcpy((void *)to, (void*)&len_n, TLV_HEADER_LEN_SIZE); + + *offset += TLV_HEADER_SIZE; + + return true; +} + +bool SetTlvType(void *data, uint32_t size, uint16_t type) +{ + if (!data) + return false; + + if(size < TLV_HEADER_SIZE ) + return false; + + uint16_t type_n = htons(type); + memcpy(data , (void*)&type_n, TLV_HEADER_TYPE_SIZE); + return true; +} + +//tested +bool SetTlvSize(void *data, uint32_t size, uint32_t len) { + if (!data) + return false; + + if(size < TLV_HEADER_SIZE ) + return false; + + uint32_t len_n = htonl(len); + + void * to = (void*)((uint8_t *) data + TLV_HEADER_TYPE_SIZE); + + memcpy(to, (void*) &len_n, TLV_HEADER_LEN_SIZE); + + return true; + +} + +/* Step past unknown TLV TYPE */ +bool SkipUnknownTlv(void *data, uint32_t size, uint32_t *offset) +{ + if (!data) + return false; + + if (size < *offset + TLV_HEADER_SIZE) + return false; + + /* extract the type and size */ + void *tlvstart = right_shift_void_pointer(data, *offset); + //uint16_t tlvtype = GetTlvType(tlvstart); + uint32_t tlvsize = GetTlvSize(tlvstart); + + /* check that there is size */ + uint32_t tlvend = *offset + tlvsize; + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "SkipUnknownTlv() FAILED - not enough space." << std::endl; + std::cerr << "SkipUnknownTlv() size: " << size << std::endl; + std::cerr << "SkipUnknownTlv() tlvsize: " << tlvsize << std::endl; + std::cerr << "SkipUnknownTlv() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + bool ok = true; + /* step past this tlv item */ + *offset = tlvend; + return ok; +} + + +/**** Generic TLV Functions **** + * This have the same data (int or string for example), + * but they can have different types eg. a string could represent a name or a path, + * so we include a type parameter in the arguments + */ +//tested +bool SetTlvUInt32(void *data, uint32_t size, uint32_t *offset, uint16_t type, + uint32_t out) +{ + if (!data) + return false; + uint32_t tlvsize = GetTlvUInt32Size(); /* this will always be 8 bytes */ + uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "SetTlvUInt32() FAILED - not enough space. (or earlier)" << std::endl; + std::cerr << "SetTlvUInt32() size: " << size << std::endl; + std::cerr << "SetTlvUInt32() tlvsize: " << tlvsize << std::endl; + std::cerr << "SetTlvUInt32() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + bool ok = true; + + /* Now use the function we got to set the TlvHeader */ + /* function shifts offset to the new start for the next data */ + ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); + +#ifdef TLV_BASE_DEBUG + if (!ok) + { + std::cerr << "SetTlvUInt32() SetTlvBase FAILED (or earlier)" << std::endl; + } +#endif + + /* now set the UInt32 ( in rsbaseserial.h???) */ + ok &= setRawUInt32(data, tlvend, offset, out); + +#ifdef TLV_BASE_DEBUG + if (!ok) + { + std::cerr << "SetTlvUInt32() setRawUInt32 FAILED (or earlier)" << std::endl; + } +#endif + + + return ok; + +} + +//tested +bool GetTlvUInt32(void *data, uint32_t size, uint32_t *offset, + uint16_t type, uint32_t *in) +{ + if (!data) + return false; + + if (size < *offset + TLV_HEADER_SIZE) + return false; + + /* extract the type and size */ + void *tlvstart = right_shift_void_pointer(data, *offset); + uint16_t tlvtype = GetTlvType(tlvstart); + uint32_t tlvsize = GetTlvSize(tlvstart); + + /* check that there is size */ + uint32_t tlvend = *offset + tlvsize; + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvUInt32() FAILED - not enough space." << std::endl; + std::cerr << "GetTlvUInt32() size: " << size << std::endl; + std::cerr << "GetTlvUInt32() tlvsize: " << tlvsize << std::endl; + std::cerr << "GetTlvUInt32() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + if (type != tlvtype) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvUInt32() FAILED - Type mismatch" << std::endl; + std::cerr << "GetTlvUInt32() type: " << type << std::endl; + std::cerr << "GetTlvUInt32() tlvtype: " << tlvtype << std::endl; +#endif + return false; + } + + *offset += TLV_HEADER_SIZE; /* step past header */ + + bool ok = true; + ok &= getRawUInt32(data, tlvend, offset, in); + + return ok; +} + + +uint32_t GetTlvUInt64Size() { + return TLV_HEADER_SIZE + 8; +} + +uint32_t GetTlvUInt32Size() { + return TLV_HEADER_SIZE + 4; +} + +uint32_t GetTlvUInt16Size() { + return TLV_HEADER_SIZE + sizeof(uint16_t); + +} + +uint32_t GetTlvUInt8Size() { + return TLV_HEADER_SIZE + sizeof(uint8_t); + +} + + +bool SetTlvUInt64(void *data, uint32_t size, uint32_t *offset, uint16_t type, + uint64_t out) +{ + if (!data) + return false; + uint32_t tlvsize = GetTlvUInt64Size(); + uint32_t tlvend = *offset + tlvsize; + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "SetTlvUInt64() FAILED - not enough space. (or earlier)" << std::endl; + std::cerr << "SetTlvUInt64() size: " << size << std::endl; + std::cerr << "SetTlvUInt64() tlvsize: " << tlvsize << std::endl; + std::cerr << "SetTlvUInt64() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + bool ok = true; + + /* Now use the function we got to set the TlvHeader */ + /* function shifts offset to the new start for the next data */ + ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); + +#ifdef TLV_BASE_DEBUG + if (!ok) + { + std::cerr << "SetTlvUInt64() SetTlvBase FAILED (or earlier)" << std::endl; + } +#endif + + /* now set the UInt64 ( in rsbaseserial.h???) */ + ok &= setRawUInt64(data, tlvend, offset, out); + +#ifdef TLV_BASE_DEBUG + if (!ok) + { + std::cerr << "SetTlvUInt64() setRawUInt64 FAILED (or earlier)" << std::endl; + } +#endif + + return ok; + +} + +bool GetTlvUInt64(void *data, uint32_t size, uint32_t *offset, + uint16_t type, uint64_t *in) +{ + if (!data) + return false; + + if (size < *offset + TLV_HEADER_SIZE) + return false; + + /* extract the type and size */ + void *tlvstart = right_shift_void_pointer(data, *offset); + uint16_t tlvtype = GetTlvType(tlvstart); + uint32_t tlvsize = GetTlvSize(tlvstart); + + /* check that there is size */ + uint32_t tlvend = *offset + tlvsize; + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvUInt64() FAILED - not enough space." << std::endl; + std::cerr << "GetTlvUInt64() size: " << size << std::endl; + std::cerr << "GetTlvUInt64() tlvsize: " << tlvsize << std::endl; + std::cerr << "GetTlvUInt64() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + if (type != tlvtype) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvUInt64() FAILED - Type mismatch" << std::endl; + std::cerr << "GetTlvUInt64() type: " << type << std::endl; + std::cerr << "GetTlvUInt64() tlvtype: " << tlvtype << std::endl; +#endif + return false; + } + + *offset += TLV_HEADER_SIZE; /* step past header */ + + bool ok = true; + ok &= getRawUInt64(data, tlvend, offset, in); + + return ok; +} + + +bool SetTlvString(void *data, uint32_t size, uint32_t *offset, + uint16_t type, std::string out) +{ + if (!data) + return false; + uint32_t tlvsize = GetTlvStringSize(out); + uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ + + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "SetTlvString() FAILED - not enough space" << std::endl; + std::cerr << "SetTlvString() size: " << size << std::endl; + std::cerr << "SetTlvString() tlvsize: " << tlvsize << std::endl; + std::cerr << "SetTlvString() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + bool ok = true; + ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); + + void * to = right_shift_void_pointer(data, *offset); + + uint32_t strlen = tlvsize - TLV_HEADER_SIZE; + memcpy(to, out.c_str(), strlen); + + *offset += strlen; + + return ok; +} + +//tested +bool GetTlvString(void *data, uint32_t size, uint32_t *offset, + uint16_t type, std::string &in) +{ + if (!data) + return false; + + // Check if we have a null string (this happens with certs) + // + if (size == *offset) + { + in = "" ; + return true ; + } + + if (size < *offset) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvString() FAILED - not enough space" << std::endl; + std::cerr << "GetTlvString() size: " << size << std::endl; + std::cerr << "GetTlvString() *offset: " << *offset << std::endl; +#endif + return false; + } + + /* extract the type and size */ + void *tlvstart = right_shift_void_pointer(data, *offset); + uint16_t tlvtype = GetTlvType(tlvstart); + uint32_t tlvsize = GetTlvSize(tlvstart); + + /* check that there is size */ + uint32_t tlvend = *offset + tlvsize; + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvString() FAILED - not enough space" << std::endl; + std::cerr << "GetTlvString() size: " << size << std::endl; + std::cerr << "GetTlvString() tlvsize: " << tlvsize << std::endl; + std::cerr << "GetTlvString() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + if (type != tlvtype) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvString() FAILED - invalid type" << std::endl; + std::cerr << "GetTlvString() type: " << type << std::endl; + std::cerr << "GetTlvString() tlvtype: " << tlvtype << std::endl; +#endif + return false; + } + + char *strdata = (char *) right_shift_void_pointer(tlvstart, TLV_HEADER_SIZE); + uint32_t strsize = tlvsize - TLV_HEADER_SIZE; /* remove the header */ + if (strsize <= 0) { + in = ""; + } else { + in = std::string(strdata, strsize); + } + + *offset += tlvsize; /* step along */ + return true; +} + +uint32_t GetTlvStringSize(const std::string &in) { + return TLV_HEADER_SIZE + in.size(); +} + + +/* We must use a consistent wchar size for cross platform ness. + * As unix uses 4bytes, and windows 2bytes? we'll go with 4bytes for maximum flexibility + */ + +const uint32_t RS_WCHAR_SIZE = 4; + +bool SetTlvWideString(void *data, uint32_t size, uint32_t *offset, + uint16_t type, std::wstring out) +{ + if (!data) + return false; + uint32_t tlvsize = GetTlvWideStringSize(out); + uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ + + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "SetTlvWideString() FAILED - not enough space" << std::endl; + std::cerr << "SetTlvWideString() size: " << size << std::endl; + std::cerr << "SetTlvWideString() tlvsize: " << tlvsize << std::endl; + std::cerr << "SetTlvWideString() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + bool ok = true; + ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); + + uint32_t strlen = out.length(); + + /* Must convert manually to ensure its always the same! */ + for(uint32_t i = 0; i < strlen; i++) + { + uint32_t widechar = out[i]; + ok &= setRawUInt32(data, tlvend, offset, widechar); + } + return ok; +} + +//tested +bool GetTlvWideString(void *data, uint32_t size, uint32_t *offset, + uint16_t type, std::wstring &in) +{ + if (!data) + return false; + + if (size < *offset + TLV_HEADER_SIZE) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvWideString() FAILED - not enough space" << std::endl; + std::cerr << "GetTlvWideString() size: " << size << std::endl; + std::cerr << "GetTlvWideString() *offset: " << *offset << std::endl; +#endif + return false; + } + + /* extract the type and size */ + void *tlvstart = right_shift_void_pointer(data, *offset); + uint16_t tlvtype = GetTlvType(tlvstart); + uint32_t tlvsize = GetTlvSize(tlvstart); + + /* check that there is size */ + uint32_t tlvend = *offset + tlvsize; + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvWideString() FAILED - not enough space" << std::endl; + std::cerr << "GetTlvWideString() size: " << size << std::endl; + std::cerr << "GetTlvWideString() tlvsize: " << tlvsize << std::endl; + std::cerr << "GetTlvWideString() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + if (type != tlvtype) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetTlvWideString() FAILED - invalid type" << std::endl; + std::cerr << "GetTlvWideString() type: " << type << std::endl; + std::cerr << "GetTlvWideString() tlvtype: " << tlvtype << std::endl; +#endif + return false; + } + + + bool ok = true; + /* remove the header, calc string length */ + *offset += TLV_HEADER_SIZE; + uint32_t strlen = (tlvsize - TLV_HEADER_SIZE) / RS_WCHAR_SIZE; + + /* Must convert manually to ensure its always the same! */ + for(uint32_t i = 0; i < strlen; i++) + { + uint32_t widechar; + ok &= getRawUInt32(data, tlvend, offset, &widechar); + in += widechar; + } + return ok; +} + +uint32_t GetTlvWideStringSize(std::wstring &in) { + return TLV_HEADER_SIZE + in.size() * RS_WCHAR_SIZE; +} + + +bool SetTlvIpAddrPortV4(void *data, uint32_t size, uint32_t *offset, + uint16_t type, struct sockaddr_in *out) { + if (!data) + return false; + + uint32_t tlvsize = GetTlvIpAddrPortV4Size(); + uint32_t tlvend = *offset + tlvsize; /* where the data will extend to */ + + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "SetTlvIpAddrPortV4() FAILED - not enough space" << std::endl; + std::cerr << "SetTlvIpAddrPortV4() size: " << size << std::endl; + std::cerr << "SetTlvIpAddrPortV4() tlvsize: " << tlvsize << std::endl; + std::cerr << "SetTlvIpAddrPortV4() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + bool ok = true; + ok &= SetTlvBase(data, tlvend, offset, type, tlvsize); + + sockaddr_in addr = *out; + + /* now add the data .... (its already in network order) - so flip */ + uint32_t ipaddr = addr.sin_addr.s_addr; + ok &= setRawUInt32(data, tlvend, offset, ntohl(ipaddr)); + + uint16_t port = addr.sin_port; + ok &= setRawUInt16(data, tlvend, offset, ntohs(port)); + + return ok; +} + +bool GetTlvIpAddrPortV4(void *data, uint32_t size, uint32_t *offset, + uint16_t type, struct sockaddr_in *in) { + if (!data) + return false; + + if (size < *offset + TLV_HEADER_SIZE) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetIpAddrPortV4() FAILED - not enough space" << std::endl; + std::cerr << "GetIpAddrPortV4() size: " << size << std::endl; + std::cerr << "GetIpAddrPortV4() *offset: " << *offset << std::endl; +#endif + return false; + } + + /* extract the type and size */ + void *tlvstart = right_shift_void_pointer(data, *offset); + uint16_t tlvtype = GetTlvType(tlvstart); + uint32_t tlvsize = GetTlvSize(tlvstart); + + /* check that there is size */ + uint32_t tlvend = *offset + tlvsize; + if (size < tlvend) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetIpAddrPortV4() FAILED - not enough space" << std::endl; + std::cerr << "GetIpAddrPortV4() size: " << size << std::endl; + std::cerr << "GetIpAddrPortV4() tlvsize: " << tlvsize << std::endl; + std::cerr << "GetIpAddrPortV4() tlvend: " << tlvend << std::endl; +#endif + return false; + } + + if (type != tlvtype) + { +#ifdef TLV_BASE_DEBUG + std::cerr << "GetIpAddrPortV4() FAILED - invalid type" << std::endl; + std::cerr << "GetIpAddrPortV4() type: " << type << std::endl; + std::cerr << "GetIpAddrPortV4() tlvtype: " << tlvtype << std::endl; +#endif + return false; + } + + *offset += TLV_HEADER_SIZE; /* skip header */ + + bool ok = true; + + /* now get the data .... (its already in network order) - so flip */ + + uint32_t ipaddr; + ok &= getRawUInt32(data, tlvend, offset, &ipaddr); + in->sin_family = AF_INET; /* set FAMILY */ + in->sin_addr.s_addr = htonl(ipaddr); + + uint16_t port; + ok &= getRawUInt16(data, tlvend, offset, &port); + in->sin_port = htons(port); + + return ok; +} + +uint32_t GetTlvIpAddrPortV4Size() { + return TLV_HEADER_SIZE + 4 + 2; /* header + 4 (IP) + 2 (Port) */ +} + diff --git a/libretroshare/src/serialiser/rstlvbase.h b/libretroshare/src/serialiser/rstlvbase.h new file mode 100644 index 000000000..40865aa61 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvbase.h @@ -0,0 +1,276 @@ +#ifndef RS_TLV_BASE_H +#define RS_TLV_BASE_H + +/* + * libretroshare/src/serialiser: rstlvbase.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie, Horatio, Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +/******************************************************************* + * These are the general TLV (un)packing routines. + * + * Data is Serialised into the following format + * + * ----------------------------------------- + * | TLV TYPE (2 bytes) | TLV LEN (4 bytes)| + * ----------------------------------------- + * | | + * | Data .... | + * | | + * ----------------------------------------- + * + * Originally TLV TYPE = 2 bytes, and TLV LEN = 2 bytes. + * However with HTML and WSTRINGS the 64K Limit becomes limiting. + * The TLV LEN = 4 bytes now! + * + * Size is the total size of the TLV Field (including the 4 byte header) + * + * Like the lowlevel packing routines. They are usually + * created in pairs - one to pack the data, the other to unpack. + * + * GetTlvXXX(void *data, uint32_t size, uint32_t *offset, XXX *out); + * SetTlvXXX(void *data, uint32_t size, uint32_t *offset, XXX *in); + * + * + * data - the base pointer to the serialised data. + * size - size of the memory pointed to by data. + * *offset - where we want to (un)pack the data. + * This is incremented by the datasize. + * + * *in / *out - the data to (un)pack. + * + ******************************************************************/ + +#include +#include +#include +#include "util/rsnet.h" + +/* 0b 0000 0000 0001 XXXX UInt8 */ +/* 0b 0000 0000 0010 XXXX UInt16 */ +/* 0b 0000 0000 0011 XXXX UInt32 */ +/* 0b 0000 0000 0100 XXXX UInt64 */ +/* 0b 0000 0000 0101 XXXX String */ +/* 0b 0000 0000 0110 XXXX Wide String */ +/* 0b 0000 0000 0111 XXXX Hashes */ +/* 0b 0000 0000 1000 XXXX IP:Port V4 */ + +/******* BINARY TYPES *****************/ +/* 0b 0000 0001 0000 XXXX CERT */ +/* 0b 0000 0001 0001 XXXX Priv Key */ +/* 0b 0000 0001 0010 XXXX Pub Key */ +/* 0b 0000 0001 0011 XXXX Signature */ + +/******* COMPOUND TYPES ***************/ +/* 0b 0001 XXXX XXXX XXXX Compound */ +/* 0b 0001 0000 0000 XXXX FILE */ +/* 0b 0001 0000 0001 XXXX KEY VALUE */ +/* 0b 0001 0000 0010 XXXX PEERS */ +/* 0b 0001 0000 0011 XXXX SERVICES */ + +/******* BIG LEN TYPES ***************/ + +/* 0b 1000 XXXX XXXX XXXX BIG LEN */ +/* 0b 1000 0000 0001 XXXX STRINGS */ +/* 0b 1000 0000 0010 XXXX WSTRINGS */ +/* 0b 1000 0000 0011 XXXX BINARY */ + +/* 0b 1001 XXXX XXXX XXXX Compound */ + + +/* TLV HEADER SIZE (Reference) *******************************/ +const uint32_t TLV_HEADER_TYPE_SIZE = 2; +const uint32_t TLV_HEADER_LEN_SIZE = 4; +const uint32_t TLV_HEADER_SIZE = TLV_HEADER_TYPE_SIZE + TLV_HEADER_LEN_SIZE; +/* TLV HEADER SIZE (Reference) *******************************/ + + +const uint16_t TLV_TYPE_UINT8_SERID = 0x0010; + +const uint16_t TLV_TYPE_UINT16_SERID = 0x0020; + +const uint16_t TLV_TYPE_UINT32_SIZE = 0x0030; +const uint16_t TLV_TYPE_UINT32_POP = 0x0031; +const uint16_t TLV_TYPE_UINT32_AGE = 0x0032; +const uint16_t TLV_TYPE_UINT32_OFFSET = 0x0033; +const uint16_t TLV_TYPE_UINT32_SERID = 0x0034; + +const uint16_t TLV_TYPE_UINT64_SIZE = 0x0040; +const uint16_t TLV_TYPE_UINT64_OFFSET = 0x0041; + +const uint16_t TLV_TYPE_STR_PEERID = 0x0050; +const uint16_t TLV_TYPE_STR_NAME = 0x0051; +const uint16_t TLV_TYPE_STR_PATH = 0x0052; +const uint16_t TLV_TYPE_STR_KEY = 0x0053; +const uint16_t TLV_TYPE_STR_VALUE = 0x0054; +const uint16_t TLV_TYPE_STR_COMMENT = 0x0055; +const uint16_t TLV_TYPE_STR_TITLE = 0x0056; +const uint16_t TLV_TYPE_STR_MSG = 0x0057; +const uint16_t TLV_TYPE_STR_SUBJECT = 0x0058; +const uint16_t TLV_TYPE_STR_LINK = 0x0059; +const uint16_t TLV_TYPE_STR_GENID = 0x005a; +const uint16_t TLV_TYPE_STR_GPGID = 0x005b; +const uint16_t TLV_TYPE_STR_LOCATION = 0x005c; +const uint16_t TLV_TYPE_STR_CERT_GPG = 0x005d; +const uint16_t TLV_TYPE_STR_CERT_SSL = 0x005e; + +/* Wide Chars (4 bytes per char) for internationalisation */ +const uint16_t TLV_TYPE_WSTR_PEERID = 0x0060; +const uint16_t TLV_TYPE_WSTR_NAME = 0x0061; +const uint16_t TLV_TYPE_WSTR_PATH = 0x0062; +const uint16_t TLV_TYPE_WSTR_KEY = 0x0063; +const uint16_t TLV_TYPE_WSTR_VALUE = 0x0064; +const uint16_t TLV_TYPE_WSTR_COMMENT = 0x0065; +const uint16_t TLV_TYPE_WSTR_TITLE = 0x0066; +const uint16_t TLV_TYPE_WSTR_MSG = 0x0067; +const uint16_t TLV_TYPE_WSTR_SUBJECT = 0x0068; +const uint16_t TLV_TYPE_WSTR_LINK = 0x0069; +const uint16_t TLV_TYPE_WSTR_GENID = 0x006a; + +/* Hashs are always strings */ +const uint16_t TLV_TYPE_STR_HASH_SHA1 = 0x0070; +const uint16_t TLV_TYPE_STR_HASH_ED2K = 0x0071; + +const uint16_t TLV_TYPE_IPV4_LOCAL = 0x0080; +const uint16_t TLV_TYPE_IPV4_REMOTE = 0x0081; +const uint16_t TLV_TYPE_IPV4_LAST = 0x0082; +const uint16_t TLV_TYPE_STR_DYNDNS = 0x0083; + +/*** MORE STRING IDS ****/ +const uint16_t TLV_TYPE_STR_GROUPID = 0x00a0; +const uint16_t TLV_TYPE_STR_MSGID = 0x00a1; +const uint16_t TLV_TYPE_STR_PARENTID = 0x00a2; +const uint16_t TLV_TYPE_STR_THREADID = 0x00a3; +const uint16_t TLV_TYPE_STR_KEYID = 0x00a4; + +const uint16_t TLV_TYPE_WSTR_CATEGORY = 0x00b0; + + + /**** Binary Types ****/ +const uint16_t TLV_TYPE_CERT_XPGP_DER = 0x0100; +const uint16_t TLV_TYPE_CERT_X509 = 0x0101; +const uint16_t TLV_TYPE_CERT_OPENPGP = 0x0102; + +const uint16_t TLV_TYPE_KEY_EVP_PKEY = 0x0110; /* Used (Generic - Distrib) */ +const uint16_t TLV_TYPE_KEY_PRIV_RSA = 0x0111; /* not used yet */ +const uint16_t TLV_TYPE_KEY_PUB_RSA = 0x0112; /* not used yet */ + +const uint16_t TLV_TYPE_SIGN_RSA_SHA1 = 0x0120; /* Used (Distrib/Forums) */ + +const uint16_t TLV_TYPE_BIN_IMAGE = 0x0130; /* Used (Generic - Forums) */ + +const uint16_t TLV_TYPE_BIN_FILEDATA = 0x0140; /* Used - ACTIVE! */ + +const uint16_t TLV_TYPE_BIN_SERIALISE = 0x0150; /* Used (Generic - Distrib) */ + + + /**** Compound Types ****/ +const uint16_t TLV_TYPE_FILEITEM = 0x1000; +const uint16_t TLV_TYPE_FILESET = 0x1001; +const uint16_t TLV_TYPE_FILEDATA = 0x1002; + +const uint16_t TLV_TYPE_KEYVALUE = 0x1010; +const uint16_t TLV_TYPE_WKEYVALUE = 0x1012; +const uint16_t TLV_TYPE_KEYVALUESET = 0x1011; +const uint16_t TLV_TYPE_WKEYVALUESET = 0x1013; + +const uint16_t TLV_TYPE_STRINGSET = 0x1020; /* dummy non-existant */ +const uint16_t TLV_TYPE_PEERSET = 0x1021; +const uint16_t TLV_TYPE_HASHSET = 0x1022; +const uint16_t TLV_TYPE_SERVICESET = 0x1030; + +const uint16_t TLV_TYPE_SECURITYKEY = 0x1040; +const uint16_t TLV_TYPE_SECURITYKEYSET= 0x1041; + +const uint16_t TLV_TYPE_KEYSIGNATURE = 0x1050; + +const uint16_t TLV_TYPE_IMAGE = 0x1060; + +const uint16_t TLV_TYPE_ADDRESS_INFO = 0x1070; +const uint16_t TLV_TYPE_ADDRESS_SET = 0x1071; + + + + + + +const uint32_t RSTLV_IMAGE_TYPE_PNG = 0x0001; +const uint32_t RSTLV_IMAGE_TYPE_JPG = 0x0002; + +/**** Basic TLV Functions ****/ +uint32_t GetTlvSize(void *data); +uint16_t GetTlvType(void *data); +bool SetTlvBase(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint32_t len); +bool SetTlvSize(void *data, uint32_t size, uint32_t len); +bool SetTlvType(void *data, uint32_t size, uint16_t type); + +/* skip past the unknown tlv elements */ +bool SkipUnknownTlv(void *data, uint32_t size, uint32_t *offset); + +/**** Generic TLV Functions **** + * This have the same data (int or string for example), + * but they can have different types eg. a string could represent a name or a path, + * so we include a type parameter in the arguments + */ + +bool SetTlvUInt8(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint8_t out); +bool GetTlvUInt8(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint8_t *in); + +bool SetTlvUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint16_t out); +bool GetTlvUInt16(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint16_t *in); + +bool SetTlvUInt32(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint32_t out); +bool GetTlvUInt32(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint32_t *in); + +bool SetTlvUInt64(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint64_t out); +bool GetTlvUInt64(void *data, uint32_t size, uint32_t *offset, uint16_t type, uint64_t *in); + +uint32_t GetTlvUInt8Size(); +uint32_t GetTlvUInt16Size(); +uint32_t GetTlvUInt32Size(); +uint32_t GetTlvUInt64Size(); + + +bool SetTlvString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::string out); +bool GetTlvString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::string &in); +uint32_t GetTlvStringSize(const std::string &in); + +bool SetTlvWideString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::wstring out); +bool GetTlvWideString(void *data, uint32_t size, uint32_t *offset, uint16_t type, std::wstring &in); +uint32_t GetTlvWideStringSize(std::wstring &in); + +bool SetTlvIpAddrPortV4(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in *out); +bool GetTlvIpAddrPortV4(void *data, uint32_t size, uint32_t *offset, uint16_t type, struct sockaddr_in *in); +uint32_t GetTlvIpAddrPortV4Size(); + +/* additional function to be added + +bool SetTlvBinData(void* data, uint32_t size, uint32_t* offset, uint16_t type, void* data_bin, uint32_t len_tlv) + +above(SetTlvbinData) is partially implemented + +bool GetTlvBinData(void* data, uint32_t size, uint32_t* offset, uint16_t type, void* data_bin, uint32_t len_tlv) + +*************************************/ +#endif diff --git a/libretroshare/src/serialiser/rstlvfileitem.cc b/libretroshare/src/serialiser/rstlvfileitem.cc new file mode 100644 index 000000000..644bdb856 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvfileitem.cc @@ -0,0 +1,704 @@ + +/* + * libretroshare/src/serialiser: rstlvfileitem.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rsbaseserial.h" + +/*** + * #define TLV_FI_DEBUG 1 + **/ + + +RsTlvFileItem::RsTlvFileItem() +{ + TlvClear(); +} + +void RsTlvFileItem::TlvClear() +{ + filesize = 0; + hash = ""; + name.clear(); + path.clear(); + pop = 0; + age = 0; + piecesize = 0; + hashset.TlvClear(); +} + +uint32_t RsTlvFileItem::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header */ + s += 8; /* filesize */ + s += GetTlvStringSize(hash); +#ifdef TLV_FI_DEBUG + std::cerr << "RsTlvFileItem::TlvSize() 8 + Hash: " << s << std::endl; +#endif + + + /* now optional ones */ + if (name.length() > 0) + { + s += GetTlvStringSize(name); +#ifdef TLV_FI_DEBUG + std::cerr << "RsTlvFileItem::TlvSize() + Name: " << s << std::endl; +#endif + } + + if (path.length() > 0) + { + s += GetTlvStringSize(path); +#ifdef TLV_FI_DEBUG + std::cerr << "RsTlvFileItem::TlvSize() + Path: " << s << std::endl; +#endif + } + + if (pop != 0) + { + s += GetTlvUInt32Size(); +#ifdef TLV_FI_DEBUG + std::cerr << "RsTlvFileItem::TlvSize() + Pop: " << s << std::endl; +#endif + } + + if (age != 0) + { + s += GetTlvUInt32Size(); +#ifdef TLV_FI_DEBUG + std::cerr << "RsTlvFileItem::TlvSize() 4 + Age: " << s << std::endl; +#endif + } + + if (piecesize != 0) + { + s += GetTlvUInt32Size(); +#ifdef TLV_FI_DEBUG + std::cerr << "RsTlvFileItem::TlvSize() 4 + PieceSize: " << s << std::endl; +#endif + } + + if (hashset.ids.size() != 0) + { + s += hashset.TlvSize(); +#ifdef TLV_FI_DEBUG + std::cerr << "RsTlvFileItem::TlvSize() 4 + HashSet: " << s << std::endl; +#endif + } + +#ifdef TLV_FI_DEBUG + std::cerr << "RsTlvFileItem::TlvSize() Total: " << s << std::endl; +#endif + + return s; +} + +/* serialise the data to the buffer */ +bool RsTlvFileItem::SetTlv(void *data, uint32_t size, uint32_t *offset) +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + { +#ifdef TLV_FI_DEBUG + std::cerr << "RsTlvFileItem::SetTlv() Failed size (" << size; + std::cerr << ") < tlvend (" << tlvend << ")" << std::endl; +#endif + return false; /* not enough space */ + } + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_FILEITEM, tlvsize); + +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() SetTlvBase Failed (or earlier)" << std::endl; + } + std::cerr << "RsTlvFileItem::SetTlv() PostBase:" << std::endl; + std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; + std::cerr << std::endl; +#endif + + + /* add mandatory parts first */ + ok &= setRawUInt64(data, tlvend, offset, filesize); + +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() SetRawUInt32(FILESIZE) Failed (or earlier)" << std::endl; + } + std::cerr << "RsTlvFileItem::SetTlv() PostSize:" << std::endl; + std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; + std::cerr << std::endl; +#endif + + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, hash); + + +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() SetTlvString(HASH) Failed (or earlier)" << std::endl; + } + std::cerr << "RsTlvFileItem::SetTlv() PostHash:" << std::endl; + std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; + std::cerr << std::endl; +#endif + + /* now optional ones */ + if (name.length() > 0) + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_NAME, name); +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Name Failed (or earlier)" << std::endl; + } + std::cerr << "RsTlvFileItem::SetTlv() PostName:" << std::endl; + std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; + std::cerr << std::endl; +#endif + + if (path.length() > 0) + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_PATH, path); +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Path Failed (or earlier)" << std::endl; + } + std::cerr << "RsTlvFileItem::SetTlv() Pre Pop:" << std::endl; + std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; + std::cerr << " type: " << TLV_TYPE_UINT32_POP << " value: " << pop; + std::cerr << std::endl; +#endif + + if (pop != 0) + ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_POP, pop); +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Pop Failed (or earlier)" << std::endl; + } + std::cerr << "RsTlvFileItem::SetTlv() Post Pop/Pre Age:" << std::endl; + std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; + std::cerr << " type: " << TLV_TYPE_UINT32_AGE << " value: " << age; + std::cerr << std::endl; +#endif + + if (age != 0) + ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_AGE, age); +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() Setting Option:Age Failed (or earlier)" << std::endl; + } + std::cerr << "RsTlvFileItem::SetTlv() Post Age:" << std::endl; + std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; + std::cerr << std::endl; +#endif + + if (piecesize != 0) + ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SIZE, piecesize); +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() Setting Option:piecesize Failed (or earlier)" << std::endl; + } + std::cerr << "RsTlvFileItem::SetTlv() Post PieceSize:" << std::endl; + std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; + std::cerr << std::endl; +#endif + + if (hashset.ids.size() != 0) + ok &= hashset.SetTlv(data, tlvend, offset); +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() Setting Option:hashset Failed (or earlier)" << std::endl; + } + std::cerr << "RsTlvFileItem::SetTlv() Post HashSet:" << std::endl; + std::cerr << "RsTlvFileItem::SetTlv() Data: " << data << " size: " << size << " offset: " << *offset; + std::cerr << std::endl; +#endif + + + +#ifdef TLV_FI_DEBUG + if (!ok) + { + std::cerr << "RsTlvFileItem::SetTlv() Setting Options Failed (or earlier)" << std::endl; + } +#endif + + return ok; +} + +bool RsTlvFileItem::GetTlv(void *data, uint32_t size, uint32_t *offset) +{ + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_FILEITEM) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* get mandatory parts first */ + ok &= getRawUInt64(data, tlvend, offset, &filesize); + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, hash); + + /* while there is more TLV (optional part) */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + switch(tlvsubtype) + { + case TLV_TYPE_STR_NAME: + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_NAME, name); + break; + case TLV_TYPE_STR_PATH: + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_PATH, path); + break; + case TLV_TYPE_UINT32_POP: + ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_POP, &pop); + break; + case TLV_TYPE_UINT32_AGE: + ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_AGE, &age); + break; + case TLV_TYPE_UINT32_SIZE: + ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SIZE, &piecesize); + break; + case TLV_TYPE_HASHSET: + ok &= hashset.GetTlv(data, tlvend, offset); + break; + default: + ok &= SkipUnknownTlv(data, tlvend, offset); + break; + } + if (!ok) + { + break; + } + } + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvFileItem::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + + +/* print it out */ +std::ostream &RsTlvFileItem::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvFileItem", indent); + uint16_t int_Indent = indent + 2; + + + printIndent(out, int_Indent); + out << "Mandatory: FileSize: " << filesize << " Hash: " << hash; + out << std::endl; + + printIndent(out, int_Indent); + out << "Optional:" << std::endl; + + /* now optional ones */ + if (name.length() > 0) + { + printIndent(out, int_Indent); + out << "Name : " << name << std::endl; + } + if (path.length() > 0) + { + printIndent(out, int_Indent); + out << "Path : " << path << std::endl; + } + if (pop != 0) + { + printIndent(out, int_Indent); + out << "Pop: " << pop << std::endl; + } + if (age != 0) + { + printIndent(out, int_Indent); + out << "Age: " << age << std::endl; + } + if (piecesize != 0) + { + printIndent(out, int_Indent); + out << "PieceSize: " << piecesize << std::endl; + } + if (hashset.ids.size() != 0) + { + hashset.print(out, int_Indent); + } + + printEnd(out, "RsTlvFileItem", indent); + + return out; +} + + +/************************************* RsTlvFileSet ************************************/ + +void RsTlvFileSet::TlvClear() +{ + title.clear(); + comment.clear(); + items.clear(); +} + +uint32_t RsTlvFileSet::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header */ + + /* first determine the total size of RstlvFileItems in list */ + + std::list::iterator it; + + for(it = items.begin(); it != items.end() ; ++it) + { + s += (*it).TlvSize(); + } + + /* now add comment and title length of this tlv object */ + + if (title.length() > 0) + s += GetTlvWideStringSize(title); + if (comment.length() > 0) + s += GetTlvWideStringSize(comment); + + return s; +} + + +/* serialize data to the buffer */ + +bool RsTlvFileSet::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_FILESET, tlvsize); + + /* add mandatory parts first */ + std::list::iterator it; + + for(it = items.begin(); it != items.end() ; ++it) + { + ok &= (*it).SetTlv(data, size, offset); + /* drop out if fails */ + if (!ok) + return false; + } + + /* now optional ones */ + if (title.length() > 0) + ok &= SetTlvWideString(data, tlvend, offset, TLV_TYPE_WSTR_TITLE, title); + if (comment.length() > 0) + ok &= SetTlvWideString(data, tlvend, offset, TLV_TYPE_WSTR_COMMENT, comment); + + return ok; + +} + + +bool RsTlvFileSet::GetTlv(void *data, uint32_t size, uint32_t *offset) +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint16_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_FILESET) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* while there is more TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + if (tlvsubtype == TLV_TYPE_FILEITEM) + { + RsTlvFileItem newitem; + ok &= newitem.GetTlv(data, size, offset); + if (ok) + { + items.push_back(newitem); + } + } + else if (tlvsubtype == TLV_TYPE_WSTR_TITLE) + { + ok &= GetTlvWideString(data, tlvend, offset, + TLV_TYPE_WSTR_TITLE, title); + } + else if (tlvsubtype == TLV_TYPE_WSTR_COMMENT) + { + ok &= GetTlvWideString(data, tlvend, offset, + TLV_TYPE_WSTR_COMMENT, comment); + } + else + { + /* unknown subtype -> error */ + ok &= SkipUnknownTlv(data, tlvend, offset); + } + + if (!ok) + { + break; + } + } + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvFileSet::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +/* print it out */ + +std::ostream &RsTlvFileSet::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvFileSet", indent); + uint16_t int_Indent = indent + 2; + + + printIndent(out, int_Indent); + out << "Mandatory:" << std::endl; + std::list::iterator it; + + for(it = items.begin(); it != items.end() ; ++it) + { + it->print(out, int_Indent); + } + printIndent(out, int_Indent); + out << "Optional:" << std::endl; + + /* now optional ones */ + if (title.length() > 0) + { + printIndent(out, int_Indent); + std::string cnv_title(title.begin(), title.end()); + out << "Title: " << cnv_title << std::endl; + } + if (comment.length() > 0) + { + printIndent(out, int_Indent); + std::string cnv_comment(comment.begin(), comment.end()); + out << "Comment: " << cnv_comment << std::endl; + } + + printEnd(out, "RsTlvFileSet", indent); + + return out; +} + + +/************************************* RsTlvFileData ************************************/ + +RsTlvFileData::RsTlvFileData() + :RsTlvItem(), file_offset(0), binData(TLV_TYPE_BIN_FILEDATA) +{ + return; +} + +void RsTlvFileData::TlvClear() +{ + file.TlvClear(); + binData.TlvClear(); + file_offset = 0; +} + + +uint32_t RsTlvFileData::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header */ + + /* collect sizes for both uInts and data length */ + s+= file.TlvSize(); + s+= GetTlvUInt64Size(); + s+= binData.TlvSize(); + + return s; +} + + +bool RsTlvFileData::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_FILEDATA , tlvsize); + + /* add mandatory part */ + ok &= file.SetTlv(data, size, offset); + ok &= SetTlvUInt64(data,size,offset, + TLV_TYPE_UINT64_OFFSET,file_offset); + ok &= binData.SetTlv(data, size, offset); + + return ok; + + +} + +bool RsTlvFileData::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + { + return false; + } + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint16_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_FILEDATA) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + ok &= file.GetTlv(data, size, offset); + ok &= GetTlvUInt64(data,size,offset, + TLV_TYPE_UINT64_OFFSET,&file_offset); + ok &= binData.GetTlv(data, size, offset); + + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvFileData::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; + +} + +/* print it out */ +std::ostream &RsTlvFileData::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvFileData", indent); + uint16_t int_Indent = indent + 2; + + file.print(out, int_Indent); + + printIndent(out, int_Indent); + out << "FileOffset: " << file_offset; + out << std::endl; + + binData.print(out, int_Indent); + + printEnd(out, "RsTlvFileData", indent); + return out; + +} + diff --git a/libretroshare/src/serialiser/rstlvimage.cc b/libretroshare/src/serialiser/rstlvimage.cc new file mode 100644 index 000000000..33d76465b --- /dev/null +++ b/libretroshare/src/serialiser/rstlvimage.cc @@ -0,0 +1,200 @@ + +/* + * libretroshare/src/serialiser: rstlvfileitem.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rsbaseserial.h" + +/*** + * #define TLV_IMG_DEBUG 1 + **/ + +/************************************* RsTlvImage ************************************/ + +RsTlvImage::RsTlvImage() + :RsTlvItem(), image_type(0), binData(TLV_TYPE_BIN_IMAGE) +{ + return; +} + +void RsTlvImage::TlvClear() +{ + image_type = 0; + binData.TlvClear(); +} + + +uint32_t RsTlvImage::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header */ + + /* collect sizes for both uInts and data length */ + s+= 4; + s+= binData.TlvSize(); + + return s; +} + + +bool RsTlvImage::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ +#ifdef TLV_IMG_DEBUG + std::cerr << "RsTlvImage::SetTlv()" << std::endl; +#endif + + + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + { +#ifdef TLV_IMG_DEBUG + std::cerr << "RsTlvImage::SetTlv() no space" << std::endl; +#endif + return false; /* not enough space */ + } + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_IMAGE , tlvsize); +#ifdef TLV_IMG_DEBUG + if (!ok) + std::cerr << "RsTlvImage::SetTlv() NOK base" << std::endl; +#endif + + /* add mandatory part */ + ok &= setRawUInt32(data, tlvend, offset, image_type); +#ifdef TLV_IMG_DEBUG + if (!ok) + std::cerr << "RsTlvImage::SetTlv() NOK image" << std::endl; +#endif + + ok &= binData.SetTlv(data, size, offset); +#ifdef TLV_IMG_DEBUG + if (!ok) + std::cerr << "RsTlvImage::SetTlv() NOK binData" << std::endl; +#endif + + + return ok; + + +} + +bool RsTlvImage::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ +#ifdef TLV_IMG_DEBUG + std::cerr << "RsTlvImage::GetTlv()" << std::endl; +#endif + if (size < *offset + TLV_HEADER_SIZE) + { + return false; + } + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint16_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + { +#ifdef TLV_IMG_DEBUG + std::cerr << "RsTlvImage::GetTlv() FAIL no space" << std::endl; +#endif + return false; /* not enough space */ + } + + if (tlvtype != TLV_TYPE_IMAGE) /* check type */ + { +#ifdef TLV_IMG_DEBUG + std::cerr << "RsTlvImage::GetTlv() FAIL wrong type" << std::endl; +#endif + return false; + } + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* add mandatory parts first */ + ok &= getRawUInt32(data, tlvend, offset, &(image_type)); + ok &= binData.GetTlv(data, size, offset); + +#ifdef TLV_IMG_DEBUG + if (!ok) + std::cerr << "RsTlvImage::GetTlv() NOK" << std::endl; +#endif + + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvImage::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; + +} + +/* print it out */ +std::ostream &RsTlvImage::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvImage", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Image_Type: " << image_type; + out << std::endl; + + binData.print(out, int_Indent); + + printEnd(out, "RsTlvImage", indent); + return out; + +} + +RsTlvImage::RsTlvImage(const RsTlvImage& rightOp) +:RsTlvItem(), image_type(0), binData(TLV_TYPE_BIN_IMAGE) +{ + this->image_type = rightOp.image_type; + this->binData.setBinData(rightOp.binData.bin_data, rightOp.binData.bin_len); +} diff --git a/libretroshare/src/serialiser/rstlvkeys.cc b/libretroshare/src/serialiser/rstlvkeys.cc new file mode 100644 index 000000000..9ccc20a53 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvkeys.cc @@ -0,0 +1,523 @@ + +/* + * libretroshare/src/serialiser: rstlvtypes.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie, Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rstlvkeys.h" + +#include "rstlvbase.h" +#include "rstlvtypes.h" +#include "rsbaseserial.h" +#include "util/rsprint.h" +#include +#include +#include +#include + +//#define TLV_DEBUG 1 + +/************************************* RsTlvSecurityKey ************************************/ + +RsTlvSecurityKey::RsTlvSecurityKey() + :RsTlvItem(), keyFlags(0), startTS(0), endTS(0), keyData(TLV_TYPE_KEY_EVP_PKEY) +{ + return; +} + +void RsTlvSecurityKey::TlvClear() +{ + keyId.clear(); + keyFlags = 0; + startTS = 0; + endTS = 0; + keyData.TlvClear(); +} + +/* clears keyData - but doesn't delete */ +void RsTlvSecurityKey::ShallowClear() +{ + keyId.clear(); + keyFlags = 0; + startTS = 0; + endTS = 0; + keyData.bin_data = 0; + keyData.bin_len = 0; +} + + +uint32_t RsTlvSecurityKey::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header + 4 for size */ + + /* now add comment and title length of this tlv object */ + + s += GetTlvStringSize(keyId); + s += 4; + s += 4; + s += 4; + s += keyData.TlvSize(); + + return s; + +} + +bool RsTlvSecurityKey::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvSecurityKey::SetTlv() Failed not enough space"; + std::cerr << std::endl; +#endif + return false; /* not enough space */ + } + + bool ok = true; + + /* start at data[offset] */ + /* add mandatory parts first */ + + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SECURITYKEY, tlvsize); + + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId); + ok &= setRawUInt32(data, tlvend, offset, keyFlags); + ok &= setRawUInt32(data, tlvend, offset, startTS); + ok &= setRawUInt32(data, tlvend, offset, endTS); + ok &= keyData.SetTlv(data, tlvend, offset); + + return ok; + +} + + +bool RsTlvSecurityKey::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvSecurityKey::GetTlv() Fail, not enough space"; + std::cerr << std::endl; +#endif + return false; /* not enough space */ + } + + if (tlvtype != TLV_TYPE_SECURITYKEY) /* check type */ + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvSecurityKey::GetTlv() Fail, wrong type"; + std::cerr << std::endl; +#endif + return false; + } + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId); + ok &= getRawUInt32(data, tlvend, offset, &(keyFlags)); + ok &= getRawUInt32(data, tlvend, offset, &(startTS)); + ok &= getRawUInt32(data, tlvend, offset, &(endTS)); + ok &= keyData.GetTlv(data, tlvend, offset); + + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvSecurityKey::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + if (!ok) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvSecurityKey::GetTlv() Failed somewhere ok == false"; + std::cerr << std::endl; +#endif + } + + return ok; + +} + + +std::ostream &RsTlvSecurityKey::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvSecurityKey", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "KeyId:" << keyId; + out << std::endl; + + printIndent(out, int_Indent); + out << "KeyFlags:" << keyFlags; + out << std::endl; + + printIndent(out, int_Indent); + out << "StartTS:" << startTS; + out << std::endl; + + printIndent(out, int_Indent); + out << "EndTS:" << endTS; + out << std::endl; + + keyData.print(out, int_Indent); + + out << std::endl; + + printEnd(out, "RsTlvSecurityKey", indent); + return out; +} + + + + +/************************************* RsTlvSecurityKeySet ************************************/ + +void RsTlvSecurityKeySet::TlvClear() +{ + groupId.clear(); + keys.clear(); //empty list +} + +uint32_t RsTlvSecurityKeySet::TlvSize() +{ + + uint32_t s = TLV_HEADER_SIZE; /* header */ + + std::map::iterator it; + + s += GetTlvStringSize(groupId); + + if(!keys.empty()) + { + + for(it = keys.begin(); it != keys.end() ; ++it) + s += (it->second).TlvSize(); + + } + + return s; +} + +bool RsTlvSecurityKeySet::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvSecurityKeySet::SetTlv() Failed not enough space"; + std::cerr << std::endl; +#endif + return false; /* not enough space */ + } + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SECURITYKEYSET , tlvsize); + + /* groupId */ + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GROUPID, groupId); + + if(!keys.empty()) + { + std::map::iterator it; + + for(it = keys.begin(); it != keys.end() ; ++it) + ok &= (it->second).SetTlv(data, size, offset); + } + + +return ok; + +} + + +bool RsTlvSecurityKeySet::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_SECURITYKEYSET) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* groupId */ + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GROUPID, groupId); + + /* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + switch(tlvsubtype) + { + case TLV_TYPE_SECURITYKEY: + { + RsTlvSecurityKey key; + ok &= key.GetTlv(data, size, offset); + if (ok) + { + keys[key.keyId] = key; + key.ShallowClear(); /* so that the Map can get control - should be ref counted*/ + } + } + break; + default: + ok &= SkipUnknownTlv(data, tlvend, offset); + break; + + } + + if (!ok) + break; + } + + + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvSecurityKeySet::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +// prints out contents of RsTlvSecurityKeySet +std::ostream &RsTlvSecurityKeySet::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvSecurityKeySet", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "GroupId: " << groupId; + out << std::endl; + + std::map::iterator it; + for(it = keys.begin(); it != keys.end() ; ++it) + (it->second).print(out, int_Indent); + + printEnd(out, "RsTlvSecurityKeySet", indent); + return out; +} + + +/************************************* RsTlvSecurityKey ************************************/ + +RsTlvKeySignature::RsTlvKeySignature() + :RsTlvItem(), signData(TLV_TYPE_SIGN_RSA_SHA1) +{ + return; +} + +void RsTlvKeySignature::TlvClear() +{ + keyId.clear(); + signData.TlvClear(); +} + +/* clears signData - but doesn't delete */ +void RsTlvKeySignature::ShallowClear() +{ + keyId.clear(); + signData.bin_data = 0; + signData.bin_len = 0; +} + +uint32_t RsTlvKeySignature::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header + 4 for size */ + + s += GetTlvStringSize(keyId); + s += signData.TlvSize(); + return s; + +} + +bool RsTlvKeySignature::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeySignature::SetTlv() Fail, not enough space"; + std::cerr << std::endl; +#endif + return false; /* not enough space */ + } + + bool ok = true; + + /* start at data[offset] */ + /* add mandatory parts first */ + + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYSIGNATURE, tlvsize); + + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId); + ok &= signData.SetTlv(data, tlvend, offset); + + if (!ok) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeySignature::SetTlv() Failed somewhere"; + std::cerr << std::endl; +#endif + } + + return ok; + +} + + +bool RsTlvKeySignature::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint16_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeySignature::GetTlv() Not Enough Space"; + std::cerr << std::endl; +#endif + return false; /* not enough space */ + } + + if (tlvtype != TLV_TYPE_KEYSIGNATURE) /* check type */ + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeySignature::GetTlv() Type Fail"; + std::cerr << std::endl; +#endif + return false; + } + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId); + ok &= signData.GetTlv(data, tlvend, offset); + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeySignature::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; + +} + + +std::ostream &RsTlvKeySignature::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvKeySignature", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "KeyId:" << keyId; + out << std::endl; + + signData.print(out, int_Indent); + + out << std::endl; + + printEnd(out, "RsTlvKeySignature", indent); + return out; +} + diff --git a/libretroshare/src/serialiser/rstlvkeys.h b/libretroshare/src/serialiser/rstlvkeys.h new file mode 100644 index 000000000..35caca20c --- /dev/null +++ b/libretroshare/src/serialiser/rstlvkeys.h @@ -0,0 +1,104 @@ +#ifndef RS_TLV_KEY_TYPES_H +#define RS_TLV_KEY_TYPES_H + +/* + * libretroshare/src/serialiser: rstlvkeys.h + * + * RetroShare Serialiser. + * + * Copyright 2008 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/******************************************************************* + * These are the Compound TLV structures that must be (un)packed. + ******************************************************************/ + +#include +#include "serialiser/rstlvtypes.h" + +const uint32_t RSTLV_KEY_TYPE_MASK = 0x000f; +const uint32_t RSTLV_KEY_DISTRIB_MASK = 0x00f0; +const uint32_t RSTLV_KEY_TYPE_PUBLIC_ONLY = 0x0001; +const uint32_t RSTLV_KEY_TYPE_FULL = 0x0002; +const uint32_t RSTLV_KEY_TYPE_SHARED = 0x0004; +const uint32_t RSTLV_KEY_DISTRIB_PUBLIC = 0x0010; +const uint32_t RSTLV_KEY_DISTRIB_PRIVATE = 0x0020; +const uint32_t RSTLV_KEY_DISTRIB_ADMIN = 0x0040; + + +class RsTlvSecurityKey: public RsTlvItem +{ + public: + RsTlvSecurityKey(); +virtual ~RsTlvSecurityKey() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + /* clears KeyData - but doesn't delete - to transfer ownership */ + void ShallowClear(); + + std::string keyId; // Mandatory : + uint32_t keyFlags; // Mandatory ; + uint32_t startTS; // Mandatory : + uint32_t endTS; // Mandatory : + RsTlvBinaryData keyData; // Mandatory : +}; + +class RsTlvSecurityKeySet: public RsTlvItem +{ + public: + RsTlvSecurityKeySet() { return; } +virtual ~RsTlvSecurityKeySet() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + std::string groupId; // Mandatory : + std::map keys; // Mandatory : +}; + + +class RsTlvKeySignature: public RsTlvItem +{ + public: + RsTlvKeySignature(); +virtual ~RsTlvKeySignature() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + void ShallowClear(); /* clears signData - but doesn't delete */ + + std::string keyId; // Mandatory : + RsTlvBinaryData signData; // Mandatory : + // NO Certificates in Signatures... add as separate data type. +}; + + + +#endif + diff --git a/libretroshare/src/serialiser/rstlvkvwide.cc b/libretroshare/src/serialiser/rstlvkvwide.cc new file mode 100644 index 000000000..570f3d45b --- /dev/null +++ b/libretroshare/src/serialiser/rstlvkvwide.cc @@ -0,0 +1,292 @@ +/* + * libretroshare/src/serialiser: rstlvkvwide.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rstlvbase.h" +#include "rstlvkvwide.h" +#include "rsbaseserial.h" +#include "util/rsprint.h" +#include +#include +#include +#include + + +void RsTlvKeyValueWide::TlvClear() +{ + wKey.clear(); + wValue.clear(); +} + +uint32_t RsTlvKeyValueWide::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header size */ + s += GetTlvWideStringSize(wKey); + s += GetTlvWideStringSize(wValue); + + return s; +} + +std::ostream &RsTlvKeyValueWide::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvKeyValueWide", indent); + uint16_t int_Indent = indent + 2; + std::string cnv_str(wKey.begin(), wKey.end()); // to convert to string + + printIndent(out, int_Indent); + out << "wKey:" << cnv_str; + cnv_str.clear(); + cnv_str.assign(wValue.begin(), wValue.end()); + printIndent(out, int_Indent); + out << "wValue:" << cnv_str; + out << std::endl; + + printEnd(out, "RsTlvKeyValuewide", indent); + return out; +} + +bool RsTlvKeyValueWide::SetTlv(void *data, uint32_t size, uint32_t *offset) +{ + + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_WKEYVALUE, tlvsize); + + + + /* now optional ones */ + if (wKey.length() > 0) + ok &= SetTlvWideString(data, tlvend, offset, TLV_TYPE_WSTR_KEY, wKey); // no base tlv type for title? + if (wValue.length() > 0) + ok &= SetTlvWideString(data, tlvend, offset, TLV_TYPE_WSTR_VALUE, wValue); // no base tlv type for comment? + + return ok; +} + +bool RsTlvKeyValueWide::GetTlv(void *data, uint32_t size, uint32_t *offset) +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint16_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_WKEYVALUE ) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + switch(tlvsubtype) + { + case TLV_TYPE_WSTR_KEY: + ok &= GetTlvWideString(data, tlvend, offset, TLV_TYPE_WSTR_KEY, wKey); + break; + case TLV_TYPE_WSTR_VALUE: + ok &= GetTlvWideString(data, tlvend, offset, TLV_TYPE_WSTR_VALUE, wValue); + break; + default: + ok &= SkipUnknownTlv(data, tlvend, offset); + break; + + } + + if (!ok) + { + break; + } + } + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeyValueWide::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +/******************************************* Wide Key Value set *************************************/ + + +void RsTlvKeyValueWideSet::TlvClear() +{ + wPairs.clear(); +} + +uint32_t RsTlvKeyValueWideSet::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header size */ + + std::list::iterator it; + + for(it = wPairs.begin(); it != wPairs.end(); it++) + { + s += it->TlvSize(); + } + + return s; +} + +std::ostream &RsTlvKeyValueWideSet::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvKeyValueWide", indent); + uint16_t int_Indent = indent + 2; + + std::list::iterator it; + + for(it = wPairs.begin(); it != wPairs.end(); it++) + { + it->print(out, int_Indent); + } + + printEnd(out, "RsTlvKeyValuewide", indent); + return out; +} + +bool RsTlvKeyValueWideSet::SetTlv(void *data, uint32_t size, uint32_t* offset) +{ + + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_WKEYVALUESET, tlvsize); + std::list::iterator it; + + for(it = wPairs.begin(); it != wPairs.end(); it++) + { + ok &= it->SetTlv(data, size, offset); + } + + return ok; +} + +bool RsTlvKeyValueWideSet::GetTlv(void *data, uint32_t size, uint32_t* offset) +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint16_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_WKEYVALUESET) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + switch(tlvsubtype) + { + case TLV_TYPE_WKEYVALUE: + { + RsTlvKeyValueWide kv; + ok &= kv.GetTlv(data, size, offset); + if (ok) + { + wPairs.push_back(kv); + } + } + break; + default: + ok &= SkipUnknownTlv(data, tlvend, offset); + break; + + } + + if (!ok) + break; + } + + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvBinaryData::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} diff --git a/libretroshare/src/serialiser/rstlvkvwide.h b/libretroshare/src/serialiser/rstlvkvwide.h new file mode 100644 index 000000000..3476c0863 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvkvwide.h @@ -0,0 +1,66 @@ +#ifndef RSTLVKVWIDE_H_ +#define RSTLVKVWIDE_H_ + +/* + * libretroshare/src/serialiser: rstlvkvwide.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rstlvtypes.h" + +class RsTlvKeyValueWide: public RsTlvItem +{ + public: + + RsTlvKeyValueWide() { return;} + virtual ~RsTlvKeyValueWide() { return;} + +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + std::wstring wKey; + std::wstring wValue; +}; + + +class RsTlvKeyValueWideSet : public RsTlvItem +{ + public: + + RsTlvKeyValueWideSet() { return;} + virtual ~RsTlvKeyValueWideSet() { return; } + +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + std::list wPairs; +}; + + +#endif /*RSTLVKVWIDE_H_*/ diff --git a/libretroshare/src/serialiser/rstlvtypes.cc b/libretroshare/src/serialiser/rstlvtypes.cc new file mode 100644 index 000000000..c1fe805e5 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvtypes.cc @@ -0,0 +1,830 @@ + +/* + * libretroshare/src/serialiser: rstlvtypes.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie, Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rstlvbase.h" +#include "rstlvtypes.h" +#include "rsbaseserial.h" +#include "util/rsprint.h" +#include +#include +#include +#include + +#define TLV_DEBUG 1 + +void RsTlvItem::TlvShallowClear() +{ + TlvClear(); /* unless overloaded! */ +} + +std::ostream &RsTlvItem::printBase(std::ostream &out, std::string clsName, uint16_t indent) +{ + printIndent(out, indent); + out << "RsTlvItem: " << clsName << " Size: " << TlvSize() << " ***********************"; + out << std::endl; + return out; +} + +std::ostream &RsTlvItem::printEnd(std::ostream &out, std::string clsName, uint16_t indent) +{ + printIndent(out, indent); + out << "********************** " << clsName << " *********************"; + out << std::endl; + return out; +} + +std::ostream &printIndent(std::ostream &out, uint16_t indent) +{ + for(int i = 0; i < indent; i++) + { + out << " "; + } + return out; +} + + + +/*!********************************** RsTlvFileBinaryData **********************************/ + + +RsTlvBinaryData::RsTlvBinaryData(uint16_t t) + :tlvtype(t), bin_len(0), bin_data(NULL) +{ + return; +} + +RsTlvBinaryData::~RsTlvBinaryData() +{ + TlvClear(); +} + + +/// used to allocate memory andinitialize binary data member +bool RsTlvBinaryData::setBinData(const void *data, uint32_t size) +{ + /* ready to load */ + TlvClear(); + + /* get mandatory */ + /* the rest of the TLV size binary data */ + bin_len = size; + if (bin_len == 0) + { + bin_data = NULL; + return true; + } + + bin_data = malloc(bin_len); + memcpy(bin_data, data, bin_len); + return true; +} + +void RsTlvBinaryData::TlvClear() +{ + if (bin_data) + { + free(bin_data); + } + TlvShallowClear(); +} + +void RsTlvBinaryData::TlvShallowClear() +{ + bin_data = NULL; + bin_len = 0; +} + +uint32_t RsTlvBinaryData::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header */ + + if (bin_data != NULL) + s += bin_len; // len is the size of data + + return s; +} + + +bool RsTlvBinaryData::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, tlvtype, tlvsize); + + /* add mandatory data */ + + // Warning: this is actually not an error if bin_len=0, as it does not + // corrupt the packet structure. We thus still return true in this case. + // + if (bin_data != NULL && bin_len > 0) + { + memcpy(&(((uint8_t *) data)[*offset]), bin_data, bin_len); + *offset += bin_len; + } + return ok; +} + + + +bool RsTlvBinaryData::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + { + return false; /* not enough space to get the header */ + } + + uint16_t tlvtype_in = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvsize < TLV_HEADER_SIZE) + { + return false; /* bad tlv size */ + } + + if (tlvtype != tlvtype_in) /* check type */ + return false; + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + bool ok = setBinData(&(((uint8_t *) data)[*offset]), tlvsize - TLV_HEADER_SIZE); + (*offset) += bin_len; + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvBinaryData::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +std::ostream &RsTlvBinaryData::print(std::ostream &out, uint16_t indent) +{ + uint16_t int_Indent = indent + 2; + + uint32_t i; + std::ostringstream sout; + printIndent(sout, indent); + sout << "RsTlvBinaryData: Type: " << tlvtype << " Size: " << bin_len; + sout << std::hex; + + for(i = 0; i < bin_len; i++) + { + if (i % 16 == 0) + { + sout << std::endl; + printIndent(sout, int_Indent); + } + sout << std::setw(2) << std::setfill('0') + << (int) (((unsigned char *) bin_data)[i]) << ":"; + } + + sout << std::endl; + out << sout.str(); + + printEnd(out, "RsTlvBinaryData", indent); + return out; + +} + +/************************************* Peer Id Set ************************************/ + +RsTlvPeerIdSet::RsTlvPeerIdSet(): RsTlvStringSet(TLV_TYPE_PEERSET) {} +RsTlvHashSet::RsTlvHashSet(): RsTlvStringSet(TLV_TYPE_HASHSET) {} + + +RsTlvStringSet::RsTlvStringSet(uint16_t type) :mType(type) +{ +} + +void RsTlvStringSet::TlvClear() +{ + ids.clear(); + +} + +uint32_t RsTlvStringSet::TlvSize() +{ + + uint32_t s = TLV_HEADER_SIZE; /* header */ + + /* determine the total size of ids strings in list */ + + std::list::iterator it; + + for(it = ids.begin(); it != ids.end() ; ++it) + { + if (it->length() > 0) + s += GetTlvStringSize(*it); + } + + return s; +} + + +bool RsTlvStringSet::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, mType , tlvsize); + + /* determine the total size of ids strings in list */ + + std::list::iterator it; + + for(it = ids.begin(); it != ids.end() ; ++it) + { + if (it->length() > 0) + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, *it); + } + + return ok; + +} + + +bool RsTlvStringSet::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != mType) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + + +/* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + if (tlvsubtype == TLV_TYPE_STR_GENID) + { + std::string newIds; + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, newIds); + if(ok) + { + ids.push_back(newIds); + + } + } + else + { + /* Step past unknown TLV TYPE */ + ok &= SkipUnknownTlv(data, tlvend, offset); + } + + if (!ok) + { + break; + } + } + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvPeerIdSet::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +/// print to screen RsTlvStringSet contents +std::ostream &RsTlvStringSet::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvStringSet", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "type:" << mType; + out << std::endl; + + std::list::iterator it; + for(it = ids.begin(); it != ids.end() ; ++it) + { + printIndent(out, int_Indent); + out << "id:" << *it; + out << std::endl; + } + + printEnd(out, "RsTlvStringSet", indent); + return out; + +} + +/// print to screen RsTlvStringSet contents +std::ostream &RsTlvStringSet::printHex(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvStringSet", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "type:" << mType; + out << std::endl; + + std::list::iterator it; + for(it = ids.begin(); it != ids.end() ; ++it) + { + printIndent(out, int_Indent); + out << "id: 0x" << RsUtil::BinToHex(*it); + out << std::endl; + } + + printEnd(out, "RsTlvStringSet", indent); + return out; + +} + + +/************************************* Service Id Set ************************************/ + +void RsTlvServiceIdSet::TlvClear() +{ + ids.clear(); + +} + +uint32_t RsTlvServiceIdSet::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header */ + + /* determine the total size of ids strings in list */ + std::list::iterator it; + for(it = ids.begin(); it != ids.end() ; ++it) + { + if (*it > 0) + s += GetTlvUInt32Size(); + } + + return s; +} + +bool RsTlvServiceIdSet::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_SERVICESET , tlvsize); + + /* determine the total size of ids strings in list */ + std::list::iterator it; + for(it = ids.begin(); it != ids.end() ; ++it) + { + if (*it > 0) + ok &= SetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SERID, *it); + } + + return ok; + +} + +bool RsTlvServiceIdSet::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_SERVICESET) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + +/* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + if (tlvsubtype == TLV_TYPE_UINT32_SERID) + { + uint32_t newIds; + ok &= GetTlvUInt32(data, tlvend, offset, TLV_TYPE_UINT32_SERID, &newIds); + if(ok) + { + ids.push_back(newIds); + + } + } + else + { + /* Step past unknown TLV TYPE */ + ok &= SkipUnknownTlv(data, tlvend, offset); + } + + if (!ok) + { + break; + } + } + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvServiceIdSet::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + + return ok; +} + +/// print to screen RsTlvServiceSet contents +std::ostream &RsTlvServiceIdSet::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvServiceIdSet", indent); + uint16_t int_Indent = indent + 2; + + std::list::iterator it; + for(it = ids.begin(); it != ids.end() ; ++it) + { + printIndent(out, int_Indent); + out << "id:" << *it; + out << std::endl; + } + + printEnd(out, "RsTlvServiceIdSet", indent); + return out; + +} + +/************************************* RsTlvKeyValue ************************************/ + +void RsTlvKeyValue::TlvClear() +{ + key = ""; + value = ""; +} + +uint32_t RsTlvKeyValue::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header */ + + /* now add comment and title length of this tlv object */ + + if (key.length() > 0) + s += GetTlvStringSize(key); + if (value.length() > 0) + s += GetTlvStringSize(value); + + return s; + +} + +bool RsTlvKeyValue::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYVALUE, tlvsize); + + + + /* now optional ones */ + if (key.length() > 0) + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEY, key); // no base tlv type for title? + if (value.length() > 0) + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_VALUE, value); // no base tlv type for comment? + +return ok; + +} + +bool RsTlvKeyValue::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_KEYVALUE) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + switch(tlvsubtype) + { + case TLV_TYPE_STR_KEY: + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEY, key); + break; + case TLV_TYPE_STR_VALUE: + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_VALUE, value); + break; + default: + ok &= SkipUnknownTlv(data, tlvend, offset); + break; + + } + + if (!ok) + { + break; + } + } + + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeyValue::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; + +} + +std::ostream &RsTlvKeyValue::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvKeyValue", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Key:" << key; + printIndent(out, int_Indent); + out << "Value:" << value; + out << std::endl; + + + printEnd(out, "RsTlvKeyValue", indent); + return out; +} + +/************************************* RsTlvKeyValueSet ************************************/ + +void RsTlvKeyValueSet::TlvClear() +{ + pairs.clear(); //empty list +} + +uint32_t RsTlvKeyValueSet::TlvSize() +{ + + uint32_t s = TLV_HEADER_SIZE; /* header */ + + std::list::iterator it; + + if(!pairs.empty()) + { + + for(it = pairs.begin(); it != pairs.end() ; ++it) + s += it->TlvSize(); + + } + + return s; +} + +bool RsTlvKeyValueSet::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_KEYVALUESET , tlvsize); + + + if(!pairs.empty()) + { + std::list::iterator it; + + for(it = pairs.begin(); it != pairs.end() ; ++it) + ok &= it->SetTlv(data, size, offset); + } + + +return ok; + +} + + +bool RsTlvKeyValueSet::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_KEYVALUESET) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + switch(tlvsubtype) + { + case TLV_TYPE_KEYVALUE: + { + RsTlvKeyValue kv; + ok &= kv.GetTlv(data, size, offset); + if (ok) + { + pairs.push_back(kv); + } + } + break; + default: + ok &= SkipUnknownTlv(data, tlvend, offset); + break; + + } + + if (!ok) + break; + } + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvKeyValueSet::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +/// prints out contents of RsTlvKeyValueSet +std::ostream &RsTlvKeyValueSet::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvKeyValue", indent); + uint16_t int_Indent = indent + 2; + + std::list::iterator it; + + for(it = pairs.begin(); it != pairs.end() ; ++it) + it->print(out, indent); + + printEnd(out, "RsTlvKeyValue", indent); + return out; +} + diff --git a/libretroshare/src/serialiser/rstlvtypes.h b/libretroshare/src/serialiser/rstlvtypes.h new file mode 100644 index 000000000..d45980635 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvtypes.h @@ -0,0 +1,258 @@ +#ifndef RS_TLV_COMPOUND_TYPES_H +#define RS_TLV_COMPOUND_TYPES_H + +/* + * libretroshare/src/serialiser: rstlvtypes.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie, Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/******************************************************************* + * These are the Compound TLV structures that must be (un)packed. + * + ******************************************************************/ + +#include +#include +#include +#include + + +//! A base class for all tlv items +/*! This class is provided to allow the serialisation and deserialization of compund +tlv items +*/ +class RsTlvItem +{ + public: + RsTlvItem() { return; } +virtual ~RsTlvItem() { return; } +virtual uint32_t TlvSize() = 0; +virtual void TlvClear() = 0; +virtual void TlvShallowClear(); /*! Don't delete allocated data */ +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) = 0; /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset) = 0; /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent) = 0; +std::ostream &printBase(std::ostream &out, std::string clsName, uint16_t indent); +std::ostream &printEnd(std::ostream &out, std::string clsName, uint16_t indent); +}; + +std::ostream &printIndent(std::ostream &out, uint16_t indent); + +//! GENERIC Binary Data TLV +/*! Use to serialise and deserialise binary data, usually included in other compound tlvs +*/ +class RsTlvBinaryData: public RsTlvItem +{ + public: + RsTlvBinaryData(uint16_t t); +virtual ~RsTlvBinaryData(); +virtual uint32_t TlvSize(); +virtual void TlvClear(); /*! Initialize fields to empty legal values ( "0", "", etc) */ +virtual void TlvShallowClear(); /*! Don't delete the binary data */ + + /// Serialise. +/*! Serialise Tlv to buffer(*data) of 'size' bytes starting at *offset */ +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); + +/// Deserialise. +/*! Deserialise Tlv buffer(*data) of 'size' bytes starting at *offset */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); +virtual std::ostream &print(std::ostream &out, uint16_t indent); /*! Error/Debug util function */ + +bool setBinData(const void *data, uint32_t size); + + uint16_t tlvtype; /// set/checked against TLV input + uint32_t bin_len; /// size of malloc'ed data (not serialised) + void *bin_data; /// mandatory +}; + + +/**** MORE TLV ***** + * + * + */ + +class RsTlvStringSet: public RsTlvItem +{ + public: + RsTlvStringSet(uint16_t type); +virtual ~RsTlvStringSet() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); +virtual std::ostream &printHex(std::ostream &out, uint16_t indent); /* SPECIAL One */ + + uint16_t mType; + std::list ids; /* Mandatory */ +}; + +class RsTlvPeerIdSet: public RsTlvStringSet +{ + public: + RsTlvPeerIdSet(); +}; + +class RsTlvHashSet: public RsTlvStringSet +{ + public: + RsTlvHashSet(); +}; + +class RsTlvServiceIdSet: public RsTlvItem +{ + public: + RsTlvServiceIdSet() { return; } +virtual ~RsTlvServiceIdSet() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + std::list ids; /* Mandatory */ +}; + + +/**** MORE TLV ***** + * + * File Items/Data. + * + */ + + +class RsTlvFileItem: public RsTlvItem +{ + public: + RsTlvFileItem(); +virtual ~RsTlvFileItem() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + uint64_t filesize; /// Mandatory: size of file to be downloaded + std::string hash; /// Mandatory: to find file + std::string name; /// Optional: name of file + std::string path; /// Optional: path on host computer + uint32_t pop; /// Optional: Popularity of file + uint32_t age; /// Optional: age of file + // For chunk hashing. + uint32_t piecesize; /// Optional: bytes/piece for hashset. + RsTlvHashSet hashset; /// Optional: chunk hashes. + +}; + +class RsTlvFileSet: public RsTlvItem +{ + public: + RsTlvFileSet() { return; } +virtual ~RsTlvFileSet() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + std::list items; /// Mandatory + std::wstring title; /// Optional: title of file set + std::wstring comment; /// Optional: comments for file +}; + + +class RsTlvFileData: public RsTlvItem +{ + public: + RsTlvFileData(); + virtual ~RsTlvFileData() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + RsTlvFileItem file; /// Mandatory: file information + uint64_t file_offset; /// Mandatory: where to start in bin data + RsTlvBinaryData binData; /// Mandatory: serialised file info +}; + + + + +/**** MORE TLV ***** + * Key/Value + Set used for Generic Configuration Parameters. + * + */ + + +class RsTlvKeyValue: public RsTlvItem +{ + public: + RsTlvKeyValue() { return; } +virtual ~RsTlvKeyValue() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + std::string key; /// Mandatory : For use in hash tables + std::string value; /// Mandatory : For use in hash tables +}; + +class RsTlvKeyValueSet: public RsTlvItem +{ + public: + RsTlvKeyValueSet() { return; } +virtual ~RsTlvKeyValueSet() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + std::list pairs; /// For use in hash tables +}; + + +class RsTlvImage: public RsTlvItem +{ + public: + RsTlvImage(); + RsTlvImage(const RsTlvImage& ); + virtual ~RsTlvImage() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ + +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + uint32_t image_type; // Mandatory: + RsTlvBinaryData binData; // Mandatory: serialised file info +}; + +#endif + diff --git a/libretroshare/src/serialiser/rstlvutil.cc b/libretroshare/src/serialiser/rstlvutil.cc new file mode 100644 index 000000000..c808b237e --- /dev/null +++ b/libretroshare/src/serialiser/rstlvutil.cc @@ -0,0 +1,182 @@ + +/* + * libretroshare/src/serialiser: rstlvutil.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +/* some utility functions mainly for debugging + * + * + * + */ + +/* print out a packet */ +#include +#include +#include +#include +#include + +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" +#include "util/utest.h" + +void displayRawPacket(std::ostream &out, void *data, uint32_t size) +{ + uint32_t i; + std::ostringstream sout; + sout << "DisplayRawPacket: Size: " << size; + sout << std::hex; + for(i = 0; i < size; i++) + { + if (i % 16 == 0) + { + sout << std::endl; + } + sout << std::setw(2) << std::setfill('0') + << (int) (((unsigned char *) data)[i]) << ":"; + } + sout << std::endl; + + out << sout.str(); +} + + +#define WHOLE_64K_SIZE 65536 + +int test_SerialiseTlvItem(std::ostream &str, RsTlvItem *in, RsTlvItem *out) +{ + uint16_t initsize = in->TlvSize(); + uint32_t serialOffset = 0; + uint32_t deserialOffset = 0; + + str << "test_SerialiseTlvItem() Testing ... Print/Serialise/Deserialise"; + str << std::endl; + + + /* some space to serialise into */ + unsigned char serbuffer[WHOLE_64K_SIZE]; + + CHECK(in->SetTlv(serbuffer, WHOLE_64K_SIZE, &serialOffset)); + + CHECK(serialOffset == initsize); /* check that the offset matches the size */ + CHECK(in->TlvSize() == initsize); /* check size hasn't changed */ + + REPORT("Serialise RsTlvItem"); + + /* now we try to read it back in! */ + CHECK(out->GetTlv(serbuffer, serialOffset, &deserialOffset)); + + /* again check sizes */ + CHECK(serialOffset == deserialOffset); + CHECK(deserialOffset == initsize); + CHECK(out->TlvSize() == initsize); + + str << "Class In/Serialised/Out!" << std::endl; + in->print(str, 0); + displayRawPacket(str, serbuffer, serialOffset); + out->print(str, 0); + + /* Can't check the actual data -> should add function */ + REPORT("DeSerialise RsTlvFileItem"); + + /* print it out */ + + + return 1; +} + +/* This function checks the TLV header, and steps on to the next one + */ + +bool test_StepThroughTlvStack(std::ostream &str, void *data, int size) +{ + uint32_t offset = 0; + uint32_t index = 0; + while (offset + 4 <= size) + { + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[offset]) ); + uint16_t tlvsize = GetTlvSize( &(((uint8_t *) data)[offset]) ); + str << "Tlv Entry[" << index << "] => Offset: " << offset; + str << " Type: " << tlvtype; + str << " Size: " << tlvsize; + str << std::endl; + + offset += tlvsize; + } + CHECK(offset == size); /* we match up exactly */ + + REPORT("Step Through RsTlvStack"); + return 1; +} + + +int test_CreateTlvStack(std::ostream &str, + std::vector items, void *data, uint32_t *totalsize) +{ + /* (1) select a random item + * (2) check size -> if okay serialise onto the end + * (3) loop!. + */ + uint32_t offset = 0; + uint32_t count = 0; + + while(1) + { + int idx = (int) (items.size() * (rand() / (RAND_MAX + 1.0))); + uint32_t tlvsize = items[idx] -> TlvSize(); + + if (offset + tlvsize > *totalsize) + { + *totalsize = offset; + return count; + } + + str << "Stack[" << count << "]"; + str << " Offset: " << offset; + str << " TlvSize: " << tlvsize; + str << std::endl; + + /* serialise it */ + items[idx] -> SetTlv(data, *totalsize, &offset); + items[idx] -> print(str, 10); + count++; + } + *totalsize = offset; + return 0; +} + +int test_TlvSet(std::vector items, int maxsize) +{ + int totalsize = maxsize; + void *data = malloc(totalsize); + uint32_t size = totalsize; + + int bytes = test_CreateTlvStack(std::cerr, items, data, &size); + test_StepThroughTlvStack(std::cerr, data, size); + + return 1; +} + + diff --git a/libretroshare/src/serialiser/rstlvutil.h b/libretroshare/src/serialiser/rstlvutil.h new file mode 100644 index 000000000..87a8280ba --- /dev/null +++ b/libretroshare/src/serialiser/rstlvutil.h @@ -0,0 +1,47 @@ +#ifndef RS_TLV_UTIL_H +#define RS_TLV_UTIL_H + +/* + * libretroshare/src/serialiser: rstlvutil.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* some utility functions mainly for debugging + */ + +#include + +class RsTlvItem; + +/* print out a packet */ +void displayRawPacket(std::ostream &out, void *data, uint32_t size); +int test_SerialiseTlvItem(std::ostream &str, RsTlvItem *in, RsTlvItem *out); + +#include + +bool test_StepThroughTlvStack(std::ostream &str, void *data, int size); +int test_CreateTlvStack(std::ostream &str, + std::vector items, void *data, int totalsize); +int test_TlvSet(std::vector items, int maxsize); + +#endif diff --git a/libretroshare/src/serialiser/rstunnelitems.cc b/libretroshare/src/serialiser/rstunnelitems.cc new file mode 100644 index 000000000..a0b405682 --- /dev/null +++ b/libretroshare/src/serialiser/rstunnelitems.cc @@ -0,0 +1,306 @@ +#include +#include +#include +#include "rstunnelitems.h" + +// -----------------------------------------------------------------------------------// +// -------------------------------- Serialization. --------------------------------- // +// -----------------------------------------------------------------------------------// +// + +// +// ---------------------------------- Packet sizes -----------------------------------// +// + +uint32_t RsTunnelDataItem::serial_size() +{ +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelDataItem::serial_size() called." << std::endl ; +#endif + uint32_t s = 0 ; + + s += 8 ; // header + s += GetTlvStringSize(sourcePeerId) ; + s += GetTlvStringSize(relayPeerId) ; + s += GetTlvStringSize(destPeerId) ; + + s += 4 ; //encoded_data_len + s += encoded_data_len; + + return s ; +} + +uint32_t RsTunnelHandshakeItem::serial_size() +{ +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelHandshakeItem::serial_size() called." << std::endl ; +#endif + uint32_t s = 0 ; + + s += 8 ; // header + s += GetTlvStringSize(sourcePeerId) ; + s += GetTlvStringSize(relayPeerId) ; + s += GetTlvStringSize(destPeerId) ; + s += GetTlvStringSize(sslCertPEM) ; + s += 4 ; //connection_accept + + + return s ; +} + +// +// ---------------------------------- Serialization ----------------------------------// +// +RsItem *RsTunnelSerialiser::deserialise(void *data, uint32_t *size) +{ +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelSerialiser::deserialise() called." << std::endl ; +#endif + // look what we have... + + /* get the type */ + uint32_t rstype = getRsItemId(data); +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel: deserialising packet: " << std::endl ; +#endif + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_TUNNEL != getRsItemService(rstype))) + { +#ifdef P3TUNNEL_DEBUG + std::cerr << " Wrong type !!" << std::endl ; +#endif + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_TUNNEL_SUBTYPE_DATA : return RsTunnelDataItem::deserialise(data,*size) ; + case RS_TUNNEL_SUBTYPE_HANDSHAKE : return RsTunnelHandshakeItem::deserialise(data,*size) ; + + default: + std::cerr << "Unknown packet type in Rstunnel!" << std::endl ; + return NULL ; + } +} + +RsTunnelDataItem::~RsTunnelDataItem() +{ + if(encoded_data != NULL) + free(encoded_data) ; +} + +bool RsTunnelDataItem::serialize(void *data,uint32_t& pktsize) +{ +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelDataItem::serialize() called." << std::endl ; +#endif + uint32_t tlvsize = serial_size(); + uint32_t offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + bool ok = true; + +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelDataItem::serialize() tlvsize : " << tlvsize << std::endl ; +#endif + + ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, sourcePeerId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, relayPeerId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, destPeerId); + + ok &= setRawUInt32(data, tlvsize, &offset, encoded_data_len) ; + + if(encoded_data != NULL) + memcpy((void*)((unsigned char*)data+offset),encoded_data,encoded_data_len) ; + +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelDataItem::serialise() (offset + encoded_data_len) " << (offset + encoded_data_len) << std::endl; + std::cerr << "RsTunnelDataItem::serialise() tlvsize " << tlvsize << std::endl; +#endif + + if ((offset + encoded_data_len) != tlvsize ) + { + ok = false; + std::cerr << "RsTunnelDataItem::serialiseTransfer() Size Error! " << std::endl; + } + +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelDataItem::serialize() packet size inside serialised data : " << getRsItemSize(data) << std::endl ; +#endif + + return ok; +} + +bool RsTunnelHandshakeItem::serialize(void *data,uint32_t& pktsize) +{ +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelHandshakeItem::serialize() called." << std::endl ; +#endif + uint32_t tlvsize = serial_size(); + uint32_t offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + bool ok = true; + +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelHandshakeItem::serialize() tlvsize : " << tlvsize << std::endl ; +#endif + + ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, sourcePeerId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, relayPeerId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, destPeerId); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_CERT_SSL, sslCertPEM); + ok &= setRawUInt32(data, tlvsize, &offset, connection_accepted); + + if (offset != tlvsize ) + { + ok = false; + std::cerr << "RsTunnelHandshakeItem::serialiseTransfer() Size Error! " << std::endl; + } + + return ok; +} + +#ifdef P3TUNNEL_DEBUG +void displayRawPacket(std::ostream &out, void *data, uint32_t size) +{ + uint32_t i; + std::ostringstream sout; + sout << "DisplayRawPacket: Size: " << size; + sout << std::hex; + for(i = 0; i < size; i++) + { + if (i % 16 == 0) + { + sout << std::endl; + } + sout << std::setw(2) << std::setfill('0') + << (int) (((unsigned char *) data)[i]) << ":"; + } + sout << std::endl; + + out << sout.str(); +} +#endif + +//deserialize in constructor +RsTunnelDataItem *RsTunnelDataItem::deserialise(void *data,uint32_t pktsize) +{ + RsTunnelDataItem *item = new RsTunnelDataItem ; +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelDataItem constructor called : deserializing packet." << std::endl ; +#endif + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelDataItem constructor rssize : " << rssize << std::endl ; +#endif + + ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE, item->sourcePeerId); + ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE, item->relayPeerId); + ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE, item->destPeerId); + + ok &= getRawUInt32(data, pktsize, &offset, &item->encoded_data_len) ; + + if(!ok) // return early to avoid calling malloc with invalid size + return NULL ; + + if(item->encoded_data_len > 0) + { + item->encoded_data = (void*)malloc(item->encoded_data_len) ; + memcpy(item->encoded_data, (void*)((unsigned char*)data+offset), item->encoded_data_len); + } + else + item->encoded_data = NULL ; + + if ((offset + item->encoded_data_len) != rssize) + { + std::cerr << "Size error while deserializing a RsTunnelHandshakeItem." << std::endl; +#ifdef P3TUNNEL_DEBUG + displayRawPacket(std::cerr,data,rssize) ; +#endif + return NULL ; + } + if (!ok) + { + std::cerr << "Error while deserializing a RstunnelDataItem." << std::endl ; + return NULL ; + } + return item ; +} + +//deserialize in constructor +RsTunnelHandshakeItem *RsTunnelHandshakeItem::deserialise(void *data,uint32_t pktsize) +{ + RsTunnelHandshakeItem *item = new RsTunnelHandshakeItem ; +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelHandshakeItem constructor called : deserializing packet." << std::endl ; +#endif + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + +#ifdef P3TUNNEL_DEBUG + std::cerr << "RsTunnelHandshakeItem constructor rssize : " << rssize << std::endl ; +#endif + + ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE, item->sourcePeerId); + ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE, item->relayPeerId); + ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE, item->destPeerId); + ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_CERT_SSL, item->sslCertPEM); + ok &= getRawUInt32(data, pktsize, &offset, &item->connection_accepted); + + if (offset != rssize) + { + std::cerr << "Size error while deserializing a RsTunnelHandshakeItem." << std::endl; + return NULL ; + } + if (!ok) + { + std::cerr << "Unknown error while deserializing a RsTunnelHandshakeItem." << std::endl ; + return NULL ; + } + return item ; +} + +std::ostream& RsTunnelDataItem::print(std::ostream& o, uint16_t) +{ + o << "RsTunnelDataItem :" << std::endl ; + o << " sourcePeerId : " << sourcePeerId << std::endl ; + o << " relayPeerId : " << relayPeerId << std::endl ; + o << " destPeerId : " << destPeerId << std::endl ; + o << " encoded_data_len : " << encoded_data_len << std::endl ; + return o ; +} + +std::ostream& RsTunnelHandshakeItem::print(std::ostream& o, uint16_t) +{ + o << "RsTunnelHandshakeItem :" << std::endl ; + o << " sourcePeerId : " << sourcePeerId << std::endl ; + o << " relayPeerId : " << relayPeerId << std::endl ; + o << " destPeerId : " << destPeerId << std::endl ; + o << " sslCertPEM : " << sslCertPEM << std::endl ; + o << " connection_accepted : " << connection_accepted << std::endl ; + return o ; +} diff --git a/libretroshare/src/serialiser/rstunnelitems.h b/libretroshare/src/serialiser/rstunnelitems.h new file mode 100644 index 000000000..f50a79345 --- /dev/null +++ b/libretroshare/src/serialiser/rstunnelitems.h @@ -0,0 +1,132 @@ +#ifndef RS_TUNNEL_ITEMS_H +#define RS_TUNNEL_ITEMS_H + +/* + * libretroshare/src/serialiser: rschannelitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rstlvbase.h" +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvkeys.h" + +const uint8_t RS_TUNNEL_SUBTYPE_DATA = 0x01 ; +const uint8_t RS_TUNNEL_SUBTYPE_HANDSHAKE = 0x02 ; + +/***********************************************************************************/ +/* Basic Tunnel Item Class */ +/***********************************************************************************/ + +class RsTunnelItem: public RsItem +{ + public: + RsTunnelItem(uint8_t tunnel_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_TUNNEL,tunnel_subtype) {} + + virtual ~RsTunnelItem() {} + + virtual bool serialize(void *data,uint32_t& size) = 0 ; // Isn't it better that items can serialize themselves ? + virtual uint32_t serial_size() { return 0;} + + virtual void clear() {} +}; + +class RsTunnelDataItem: public RsTunnelItem +{ + public: + RsTunnelDataItem() : RsTunnelItem(RS_TUNNEL_SUBTYPE_DATA) + { + encoded_data = NULL ; // To comply with the destructor below. + } + virtual ~RsTunnelDataItem() ; + + static RsTunnelDataItem *deserialise(void *data,uint32_t size) ; // deserialization + + uint32_t encoded_data_len; + void *encoded_data; + + std::string sourcePeerId ; + std::string relayPeerId ; + std::string destPeerId ; + + std::ostream& print(std::ostream& o, uint16_t) ; + + bool serialize(void *data,uint32_t& size) ; + uint32_t serial_size() ; +}; + +class RsTunnelHandshakeItem: public RsTunnelItem +{ + public: + RsTunnelHandshakeItem() : RsTunnelItem(RS_TUNNEL_SUBTYPE_HANDSHAKE) {} + virtual ~RsTunnelHandshakeItem() {} + + static RsTunnelHandshakeItem *deserialise(void *data,uint32_t size) ; // deserialization + + std::string sourcePeerId ; + std::string relayPeerId ; + std::string destPeerId ; + std::string sslCertPEM ; + uint32_t connection_accepted; + + std::ostream& print(std::ostream& o, uint16_t) ; + + bool serialize(void *data,uint32_t& size) ; + uint32_t serial_size() ; +}; + +class RsTunnelSerialiser: public RsSerialType +{ + public: + RsTunnelSerialiser() : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_TUNNEL) {} + + virtual uint32_t size(RsItem *item) + { + RsTunnelItem * rst; + if (NULL != (rst = dynamic_cast(item))) + { + return rst->serial_size() ; + } else { + std::cerr << "RsTunnelSerialiser::size() problem, not a RsTunnelItem." << std::endl; + } + return 0; + } + virtual bool serialise(RsItem *item, void *data, uint32_t *size) + { + RsTunnelItem * rst; + if (NULL != (rst = dynamic_cast(item))) + { + return rst->serialize(data,*size) ; + } else { + std::cerr << "RsTunnelSerialiser::serialise() problem, not a RsTunnelItem." << std::endl; + } + return false; + } + virtual RsItem *deserialise (void *data, uint32_t *size) ; +}; + +#endif /* RS_TUNNEL_ITEMS_H */ diff --git a/libretroshare/src/services/Makefile b/libretroshare/src/services/Makefile new file mode 100644 index 000000000..c85837f32 --- /dev/null +++ b/libretroshare/src/services/Makefile @@ -0,0 +1,36 @@ + +RS_TOP_DIR = .. +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/scripts/config.mk +############################################################### + +RSOBJ = p3service.o p3chatservice.o p3msgservice.o \ + p3gamelauncher.o p3ranking.o p3disc.o \ + p3photoservice.o \ + p3distrib.o \ + p3status.o \ + p3Qblog.o \ + p3forums.o \ + p3channels.o \ + p3portservice.o + +# dummy forums interface. +# p3forums-dummy.o \ + +TESTOBJ = forum_test.o + +TESTS = forum_test + +all: librs tests + +forum_test : forum_test.o + $(CC) $(CFLAGS) -o forum_test forum_test.o $(OBJ) $(LIBS) + + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/services/p3blogs.cc b/libretroshare/src/services/p3blogs.cc new file mode 100644 index 000000000..c865282f2 --- /dev/null +++ b/libretroshare/src/services/p3blogs.cc @@ -0,0 +1,406 @@ +/* + * libretroshare/src/services: p3Blogs.cc + * + * RetroShare C++ Interface. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3blogs.h" +#include "util/rsdir.h" + +std::ostream &operator<<(std::ostream &out, const BlogInfo &info) +{ + std::string name(info.blogName.begin(), info.blogName.end()); + std::string desc(info.blogDesc.begin(), info.blogDesc.end()); + + out << "BlogInfo:"; + out << std::endl; + out << "BlogId: " << info.blogId << std::endl; + out << "BlogName: " << name << std::endl; + out << "BlogDesc: " << desc << std::endl; + out << "BlogFlags: " << info.blogFlags << std::endl; + out << "Pop: " << info.pop << std::endl; + out << "LastPost: " << info.lastPost << std::endl; + + return out; +} + +std::ostream &operator<<(std::ostream &out, const BlogMsgSummary &info) +{ + out << "BlogMsgSummary:"; + out << std::endl; + out << "BlogId: " << info.blogId << std::endl; + + return out; +} + +std::ostream &operator<<(std::ostream &out, const BlogMsgInfo &info) +{ + out << "BlogMsgInfo:"; + out << std::endl; + out << "BlogId: " << info.blogId << std::endl; + + return out; +} + + +RsBlogs *rsBlogs = NULL; + + +/* Blogs will be initially stored for 1 year + * remember 2^16 = 64K max units in store period. + * PUBPERIOD * 2^16 = max STORE PERIOD */ +#define BLOG_STOREPERIOD (90*24*3600) /* 30 * 24 * 3600 - secs in a year */ +#define BLOG_PUBPERIOD 600 /* 10 minutes ... (max = 455 days) */ + +p3Blogs::p3Blogs(uint16_t type, CacheStrapper *cs, + CacheTransfer *cft, + std::string srcdir, std::string storedir) + :p3GroupDistrib(type, cs, cft, srcdir, storedir, "", + CONFIG_TYPE_QBLOG, BLOG_STOREPERIOD, BLOG_PUBPERIOD) +{ + return; +} + +p3Blogs::~p3Blogs() +{ + return; +} + +/****************************************/ + +bool p3Blogs::blogsChanged(std::list &blogIds) +{ + return groupsChanged(blogIds); +} + + +bool p3Blogs::getBlogInfo(std::string cId, BlogInfo &ci) +{ + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + /* extract details */ + GroupInfo *gi = locked_getGroupInfo(cId); + + if (!gi) + return false; + + ci.blogId = gi->grpId; + ci.blogName = gi->grpName; + ci.blogDesc = gi->grpDesc; + + ci.blogFlags = gi->flags; + + ci.pop = gi->sources.size(); + ci.lastPost = gi->lastPost; + + ci.pngChanImage = gi->grpIcon.pngImageData; + + if(ci.pngChanImage != NULL) + ci.pngImageLen = gi->grpIcon.imageSize; + else + ci.pngImageLen = 0; + + return true; +} + + +bool p3Blogs::getBlogList(std::list &blogList) +{ + std::list grpIds; + std::list::iterator it; + + getAllGroupList(grpIds); + + for(it = grpIds.begin(); it != grpIds.end(); it++) + { + BlogInfo ci; + if (getBlogInfo(*it, ci)) + { + blogList.push_back(ci); + } + } + return true; +} + + +bool p3Blogs::getBlogMsgList(std::string cId, std::list &msgs) +{ + std::list msgIds; + std::list::iterator it; + + getAllMsgList(cId, msgIds); + + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + for(it = msgIds.begin(); it != msgIds.end(); it++) + { + /* get details */ + RsDistribMsg *msg = locked_getGroupMsg(cId, *it); + RsBlogMsg *cmsg = dynamic_cast(msg); + if (!cmsg) + continue; + + BlogMsgSummary tis; + + tis.blogId = msg->grpId; + tis.msgId = msg->msgId; + tis.ts = msg->timestamp; + + /* the rest must be gotten from the derived Msg */ + + tis.subject = cmsg->subject; + tis.msg = cmsg->message; + + msgs.push_back(tis); + } + return true; +} + +bool p3Blogs::getBlogMessage(std::string fId, std::string mId, BlogMsgInfo &info) +{ + std::list msgIds; + std::list::iterator it; + + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + RsDistribMsg *msg = locked_getGroupMsg(fId, mId); + RsBlogMsg *cmsg = dynamic_cast(msg); + if (!cmsg) + return false; + + + info.blogId = msg->grpId; + info.msgId = msg->msgId; + info.ts = msg->timestamp; + + /* the rest must be gotten from the derived Msg */ + + info.subject = cmsg->subject; + info.msg = cmsg->message; + + return true; +} + +bool p3Blogs::BlogMessageSend(BlogMsgInfo &info) +{ + + RsBlogMsg *cmsg = new RsBlogMsg(); + cmsg->grpId = info.blogId; + + cmsg->subject = info.subject; + cmsg->message = info.msg; + cmsg->timestamp = time(NULL); + + std::string msgId = publishMsg(cmsg, true); + + return true; +} + +bool p3Blogs::BlogMessageReply(BlogMsgInfo& reply){ + + // ensure it has a value + if(isReply(reply)){ + std::cerr << "p3Blogs::BlogMessageReply()" << " This is not a reply " << std::endl; + return false; + } + + + // also check that msgId exists for group + + return BlogMessageSend(reply); +} + +bool p3Blogs::isReply(BlogMsgInfo& info){ + + // if replies list is empty then this is not a reply to a blog + return !info.msgIdReply.empty(); +} + +std::string p3Blogs::createBlog(std::wstring blogName, std::wstring blogDesc, uint32_t blogFlags, + unsigned char* pngImageData, uint32_t imageSize) +{ + + std::string id = createGroup(blogName, blogDesc, blogFlags, pngImageData, imageSize); + + return id; +} + +RsSerialType *p3Blogs::createSerialiser() +{ + return new RsBlogSerialiser(); +} + +bool p3Blogs::locked_checkDistribMsg(RsDistribMsg *msg) +{ + return true; +} + + +RsDistribGrp *p3Blogs::locked_createPublicDistribGrp(GroupInfo &info) +{ + RsDistribGrp *grp = NULL; //new RsChannelGrp(); + + return grp; +} + +RsDistribGrp *p3Blogs::locked_createPrivateDistribGrp(GroupInfo &info) +{ + RsDistribGrp *grp = NULL; //new RsChannelGrp(); + + return grp; +} + + +bool p3Blogs::blogSubscribe(std::string cId, bool subscribe) +{ + std::cerr << "p3Blogs::channelSubscribe() "; + std::cerr << cId; + std::cerr << std::endl; + + return subscribeToGroup(cId, subscribe); +} + + +/***************************************************************************************/ +/****************** Event Feedback (Overloaded form p3distrib) *************************/ +/***************************************************************************************/ +/* only download in the first week of channel + * older stuff can be manually downloaded. + */ + +const uint32_t DOWNLOAD_PERIOD = 7 * 24 * 3600; + +/* This is called when we receive a msg, and also recalled + * + */ + +bool p3Blogs::locked_eventDuplicateMsg(GroupInfo *grp, RsDistribMsg *msg, const std::string& id, bool historical) +{ + return true; +} + +#include "pqi/pqinotify.h" + +bool p3Blogs::locked_eventNewMsg(GroupInfo *grp, RsDistribMsg *msg, const std::string& id, bool historical) +{ + std::string grpId = msg->grpId; + std::string msgId = msg->msgId; + std::string nullId; + + std::cerr << "p3Blogs::locked_eventNewMsg() "; + std::cerr << " grpId: " << grpId; + std::cerr << " msgId: " << msgId; + std::cerr << " peerId: " << id; + std::cerr << std::endl; + + if (!historical) + { + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_BLOG_MSG, grpId, msgId, nullId); + } + + /* request the files + * NB: This could result in duplicates. + * which must be handled by ft side. + * + * this is exactly what DuplicateMsg does. + * */ + return locked_eventDuplicateMsg(grp, msg, id, historical); +} + + + + +void p3Blogs::locked_notifyGroupChanged(GroupInfo &grp, uint32_t flags, bool historical) +{ + std::string grpId = grp.grpId; + std::string msgId; + std::string nullId; + + std::cerr << "p3Blogs::locked_notifyGroupChanged() "; + std::cerr << grpId; + std::cerr << " flags:" << flags; + std::cerr << std::endl; + + switch(flags) + { + case GRP_NEW_UPDATE: + std::cerr << "p3Blogs::locked_notifyGroupChanged() NEW UPDATE"; + std::cerr << std::endl; + if (!historical) + { + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_BLOG_NEW, grpId, msgId, nullId); + } + break; + case GRP_UPDATE: + std::cerr << "p3Blogs::locked_notifyGroupChanged() UPDATE"; + std::cerr << std::endl; + if (!historical) + { + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_BLOG_UPDATE, grpId, msgId, nullId); + } + break; + case GRP_LOAD_KEY: + std::cerr << "p3Blogs::locked_notifyGroupChanged() LOAD_KEY"; + std::cerr << std::endl; + break; + case GRP_NEW_MSG: + std::cerr << "p3Blogs::locked_notifyGroupChanged() NEW MSG"; + std::cerr << std::endl; + break; + case GRP_SUBSCRIBED: + std::cerr << "p3Blogs::locked_notifyGroupChanged() SUBSCRIBED"; + std::cerr << std::endl; + break; + case GRP_UNSUBSCRIBED: + std::cerr << "p3Blogs::locked_notifyGroupChanged() UNSUBSCRIBED"; + std::cerr << std::endl; + + /* won't stop downloads... */ + + break; + + default: + std::cerr << "p3Blogs::locked_notifyGroupChanged() Unknown DEFAULT"; + std::cerr << std::endl; + break; + } + + return p3GroupDistrib::locked_notifyGroupChanged(grp, flags); +} + +//TODO: if you want to enable config saving and loading implement this +bool p3Blogs::childLoadList(std::list& configSaves) +{ + return true; +} + +//TODO: +std::list p3Blogs::childSaveList() +{ + std::list saveL; + + return saveL; +} + +/****************************************/ + + + diff --git a/libretroshare/src/services/p3blogs.h b/libretroshare/src/services/p3blogs.h new file mode 100644 index 000000000..e6bfc5aa1 --- /dev/null +++ b/libretroshare/src/services/p3blogs.h @@ -0,0 +1,137 @@ +#ifndef RS_P3_BLOGS_INTERFACE_H +#define RS_P3_BLOGS_INTERFACE_H + +/* + * libretroshare/src/services: p3blogs.h + * + * RetroShare C++ Interface. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rsblogs.h" +#include "retroshare/rsfiles.h" +#include "services/p3distrib.h" + +#include "serialiser/rstlvtypes.h" +#include "serialiser/rsblogitems.h" + +/*! + * implements the blog interface using the distrib service. it allows users to send blogs using + * retroshare's cache service. its use + */ +class p3Blogs: public p3GroupDistrib, public RsBlogs +{ + public: + + /*! + * @param CacheStrapper needed to push blogs onto the cache service + * @param CacheTransfer maintains distrib servi + * @param srcdir + * @param storedir + */ + p3Blogs(uint16_t type, CacheStrapper *cs, CacheTransfer *cft, + std::string srcdir, std::string storedir); +virtual ~p3Blogs(); + +/****************************************/ +/********* rsBlogs Interface ***********/ + + +/** + * check if any of the blogs has been changed + * @param blogIds list blogs by ids to be checked + * @return false if changed and vice versa + */ +virtual bool blogsChanged(std::list &blogIds); + +/** + * creates a new blog + */ +virtual std::string createBlog(std::wstring blogName, std::wstring blogDesc, uint32_t blogFlags, + unsigned char* pngImageData, uint32_t imageSize); + +/** + * @param cId the id for the blog + * @param BloogInfo blog information is stored here + */ +virtual bool getBlogInfo(std::string cId, BlogInfo &ci); + +/** + * get list of blogs from the group peer belongs to + */ +virtual bool getBlogList(std::list &blogList); + +/** + * Returns a list of all the messages sent + * @param cId group id + * @param msgs + */ +virtual bool getBlogMsgList(std::string cId, std::list &msgs); +virtual bool getBlogMessage(std::string cId, std::string mId, BlogMsgInfo &msg); + +virtual bool BlogMessageSend(BlogMsgInfo &info); + +/** + * subscribes or unsubscribes peer to a blog message + * @param cId the id of the blog message peer wants to subscribe + * @param subscribe set to true to subscribe, false otherwise + */ +virtual bool blogSubscribe(std::string cId, bool subscribe); + + +/** + * send a reply to a blog msg, ensure msgIdReply has valid id to a message + */ +virtual bool BlogMessageReply(BlogMsgInfo &info); + +/** + * check if a particular blog is a reply + * @return false if not a reply, true otherwise + */ +virtual bool isReply(BlogMsgInfo& info); + + +/***************************************************************************************/ +/****************** Event Feedback (Overloaded form p3distrib) *************************/ +/***************************************************************************************/ + + protected: +virtual void locked_notifyGroupChanged(GroupInfo &info, uint32_t flags, bool historical); +virtual bool locked_eventNewMsg(GroupInfo *, RsDistribMsg *, const std::string&, bool historical); +virtual bool locked_eventDuplicateMsg(GroupInfo *, RsDistribMsg *, const std::string&, bool historical); + + +/****************************************/ +/********* Overloaded Functions *********/ + +virtual RsSerialType *createSerialiser(); + +virtual bool locked_checkDistribMsg(RsDistribMsg *msg); +virtual RsDistribGrp *locked_createPublicDistribGrp(GroupInfo &info); +virtual RsDistribGrp *locked_createPrivateDistribGrp(GroupInfo &info); +virtual bool childLoadList(std::list& configSaves); +virtual std::list childSaveList(); +/****************************************/ + +}; + + +#endif diff --git a/libretroshare/src/services/p3channels.cc b/libretroshare/src/services/p3channels.cc new file mode 100644 index 000000000..3ec1e4d6e --- /dev/null +++ b/libretroshare/src/services/p3channels.cc @@ -0,0 +1,1060 @@ +/* + * libretroshare/src/services: p3channels.cc + * + * RetroShare C++ Interface. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3channels.h" +#include "util/rsdir.h" +#include "retroshare/rsiface.h" + +std::ostream &operator<<(std::ostream &out, const ChannelInfo &info) +{ + std::string name(info.channelName.begin(), info.channelName.end()); + std::string desc(info.channelDesc.begin(), info.channelDesc.end()); + + out << "ChannelInfo:"; + out << std::endl; + out << "ChannelId: " << info.channelId << std::endl; + out << "ChannelName: " << name << std::endl; + out << "ChannelDesc: " << desc << std::endl; + out << "ChannelFlags: " << info.channelFlags << std::endl; + out << "Pop: " << info.pop << std::endl; + out << "LastPost: " << info.lastPost << std::endl; + + return out; +} + +std::ostream &operator<<(std::ostream &out, const ChannelMsgSummary &info) +{ + out << "ChannelMsgSummary: ChannelId: " << info.channelId << std::endl; + + return out; +} + +std::ostream &operator<<(std::ostream &out, const ChannelMsgInfo &info) +{ + out << "ChannelMsgInfo: ChannelId: " << info.channelId << std::endl; + + return out; +} + + +RsChannels *rsChannels = NULL; + + +/* remember 2^16 = 64K max units in store period. + * PUBPERIOD * 2^16 = max STORE PERIOD */ +#define CHANNEL_STOREPERIOD (30*24*3600) /* 30 * 24 * 3600 - secs in a 30 day month */ +#define CHANNEL_PUBPERIOD 120 /* 2 minutes ... (max = 455 days) */ +#define MAX_AUTO_DL 1E9 /* auto download of attachment limit; 1 GIG */ + +p3Channels::p3Channels(uint16_t type, CacheStrapper *cs, + CacheTransfer *cft, RsFiles *files, + std::string srcdir, std::string storedir, std::string chanDir) + :p3GroupDistrib(type, cs, cft, srcdir, storedir, chanDir, + CONFIG_TYPE_CHANNELS, CHANNEL_STOREPERIOD, CHANNEL_PUBPERIOD), + mRsFiles(files), + mChannelsDir(chanDir) +{ + + /* create chanDir */ + if (!RsDirUtil::checkCreateDirectory(mChannelsDir)) { + std::cerr << "p3Channels() Failed to create Channels Directory: " << mChannelsDir << std::endl; + } + + + return; +} + +p3Channels::~p3Channels() +{ + return; +} + +/****************************************/ + +bool p3Channels::channelsChanged(std::list &chanIds) +{ + return groupsChanged(chanIds); +} + + +bool p3Channels::getChannelInfo(std::string cId, ChannelInfo &ci) +{ + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + /* extract details */ + GroupInfo *gi = locked_getGroupInfo(cId); + + if (!gi) + return false; + + ci.channelId = gi->grpId; + ci.channelName = gi->grpName; + ci.channelDesc = gi->grpDesc; + + ci.channelFlags = gi->flags; + + ci.pop = gi->sources.size(); + ci.lastPost = gi->lastPost; + + ci.pngChanImage = gi->grpIcon.pngImageData; + + if(ci.pngChanImage != NULL) + ci.pngImageLen = gi->grpIcon.imageSize; + else + ci.pngImageLen = 0; + + return true; +} + + +bool p3Channels::getChannelList(std::list &channelList) +{ + std::list grpIds; + std::list::iterator it; + + getAllGroupList(grpIds); + + for(it = grpIds.begin(); it != grpIds.end(); it++) + { + ChannelInfo ci; + if (getChannelInfo(*it, ci)) + { + channelList.push_back(ci); + } + } + return true; +} + + +bool p3Channels::getChannelMsgList(std::string cId, std::list &msgs) +{ + std::list msgIds; + std::list::iterator it; + + getAllMsgList(cId, msgIds); + + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + for(it = msgIds.begin(); it != msgIds.end(); it++) + { + /* get details */ + RsDistribMsg *msg = locked_getGroupMsg(cId, *it); + RsChannelMsg *cmsg = dynamic_cast(msg); + if (!cmsg) + continue; + + ChannelMsgSummary tis; + + tis.channelId = msg->grpId; + tis.msgId = msg->msgId; + tis.ts = msg->timestamp; + + /* the rest must be gotten from the derived Msg */ + + tis.subject = cmsg->subject; + tis.msg = cmsg->message; + tis.count = cmsg->attachment.items.size(); + + msgs.push_back(tis); + } + return true; +} + +bool p3Channels::getChannelMessage(std::string cId, std::string mId, ChannelMsgInfo &info) +{ + std::list msgIds; + std::list::iterator it; + + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + RsDistribMsg *msg = locked_getGroupMsg(cId, mId); + RsChannelMsg *cmsg = dynamic_cast(msg); + if (!cmsg) + return false; + + + info.channelId = msg->grpId; + info.msgId = msg->msgId; + info.ts = msg->timestamp; + + /* the rest must be gotten from the derived Msg */ + + info.subject = cmsg->subject; + info.msg = cmsg->message; + info.count = 0; + info.size = 0; + + std::list::iterator fit; + for(fit = cmsg->attachment.items.begin(); + fit != cmsg->attachment.items.end(); fit++) + { + FileInfo fi; + fi.fname = RsDirUtil::getTopDir(fit->name); + fi.size = fit->filesize; + fi.hash = fit->hash; + fi.path = fit->path; + + info.files.push_back(fi); + info.count++; + info.size += fi.size; + } + + if((cmsg->thumbnail.binData.bin_data != NULL) && (cmsg->thumbnail.image_type == RSTLV_IMAGE_TYPE_PNG)) + { + info.thumbnail.image_thumbnail = + (unsigned char*) cmsg->thumbnail.binData.bin_data; + + info.thumbnail.im_thumbnail_size = + cmsg->thumbnail.binData.bin_len; + } + + return true; +} + +bool p3Channels::channelRestoreKeys(std::string chId){ + + return p3GroupDistrib::restoreGrpKeys(chId); +} + +bool p3Channels::ChannelMessageSend(ChannelMsgInfo &info) +{ + + RsChannelMsg *cmsg = new RsChannelMsg(); + cmsg->grpId = info.channelId; + + cmsg->subject = info.subject; + cmsg->message = info.msg; + cmsg->timestamp = time(NULL); + + std::list::iterator it; + for(it = info.files.begin(); it != info.files.end(); it++) + { + + RsTlvFileItem mfi; + mfi.hash = it -> hash; + mfi.name = it -> fname; + mfi.filesize = it -> size; + cmsg -> attachment.items.push_back(mfi); + } + + // explicit member wise copy for grp image + if((info.thumbnail.image_thumbnail != NULL) && + (info.thumbnail.im_thumbnail_size > 0)){ + + cmsg->thumbnail.binData.bin_data = + new unsigned char[info.thumbnail.im_thumbnail_size]; + + memcpy(cmsg->thumbnail.binData.bin_data, info.thumbnail.image_thumbnail, + info.thumbnail.im_thumbnail_size*sizeof(unsigned char)); + cmsg->thumbnail.binData.bin_len = info.thumbnail.im_thumbnail_size; + cmsg->thumbnail.image_type = RSTLV_IMAGE_TYPE_PNG; + + }else{ + + cmsg->thumbnail.binData.bin_data = NULL; + cmsg->thumbnail.binData.bin_len = 0; + cmsg->thumbnail.image_type = 0; + } + + bool toSign = false; + // Channels are not personally signed yet... (certainly not by default!). + // This functionality can easily be added once its available in the gui + API. + // should check the GroupFlags for default. + + std::string msgId = publishMsg(cmsg, toSign); + + if (msgId.empty()) { + return false; + } + + return setMessageStatus(info.channelId, msgId, CHANNEL_MSG_STATUS_READ, CHANNEL_MSG_STATUS_MASK); +} + +bool p3Channels::setMessageStatus(const std::string& cId,const std::string& mId,const uint32_t status, const uint32_t statusMask) +{ + bool changed = false; + uint32_t newStatus = 0; + + { + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + std::list::iterator lit = mReadStatus.begin(); + + for(; lit != mReadStatus.end(); lit++) + { + + if((*lit)->channelId == cId) + { + RsChannelReadStatus* rsi = *lit; + uint32_t oldStatus = rsi->msgReadStatus[mId]; + rsi->msgReadStatus[mId] &= ~statusMask; + rsi->msgReadStatus[mId] |= (status & statusMask); + + newStatus = rsi->msgReadStatus[mId]; + if (oldStatus != newStatus) { + changed = true; + } + break; + } + + } + + // if channel id does not exist create one + if(lit == mReadStatus.end()) + { + RsChannelReadStatus* rsi = new RsChannelReadStatus(); + rsi->channelId = cId; + rsi->msgReadStatus[mId] = status & statusMask; + mReadStatus.push_back(rsi); + saveList.push_back(rsi); + + newStatus = rsi->msgReadStatus[mId]; + changed = true; + } + + if (changed) { + IndicateConfigChanged(); + } + } /******* UNLOCKED ********/ + + if (changed) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_CHANNELLIST_LOCKED, NOTIFY_TYPE_MOD); + rsicontrol->getNotify().notifyChannelMsgReadSatusChanged(cId, mId, newStatus); + } + + return true; +} + +bool p3Channels::getMessageStatus(const std::string& cId, const std::string& mId, uint32_t& status) +{ + + status = 0; + + RsStackMutex stack(distribMtx); + + std::list::iterator lit = mReadStatus.begin(); + + for(; lit != mReadStatus.end(); lit++) + { + + if((*lit)->channelId == cId) + { + break; + } + + } + + if(lit == mReadStatus.end()) + { + return false; + } + + std::map::iterator mit = (*lit)->msgReadStatus.find(mId); + + if(mit != (*lit)->msgReadStatus.end()) + { + status = mit->second; + return true; + } + + return false; +} + +bool p3Channels::getMessageCount(const std::string cId, unsigned int &newCount, unsigned int &unreadCount) +{ + newCount = 0; + unreadCount = 0; + + std::list grpIds; + + if (cId.empty()) { + // count all messages of all subscribed channels + getAllGroupList(grpIds); + } else { + // count all messages of one channels + grpIds.push_back(cId); + } + + std::list::iterator git; + for (git = grpIds.begin(); git != grpIds.end(); git++) { + std::string cId = *git; + uint32_t grpFlags; + + { + // only flag is needed + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + GroupInfo *gi = locked_getGroupInfo(cId); + if (gi == NULL) { + return false; + } + grpFlags = gi->flags; + } /******* UNLOCKED ********/ + + if (grpFlags & (RS_DISTRIB_ADMIN | RS_DISTRIB_SUBSCRIBED)) { + std::list msgIds; + if (getAllMsgList(cId, msgIds)) { + std::list::iterator mit; + + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + std::list::iterator lit; + for(lit = mReadStatus.begin(); lit != mReadStatus.end(); lit++) { + if ((*lit)->channelId == cId) { + break; + } + } + + if (lit == mReadStatus.end()) { + // no status available -> all messages are new + newCount += msgIds.size(); + unreadCount += msgIds.size(); + continue; + } + + for (mit = msgIds.begin(); mit != msgIds.end(); mit++) { + std::map::iterator rit = (*lit)->msgReadStatus.find(*mit); + + if (rit == (*lit)->msgReadStatus.end()) { + // no status available -> message is new + newCount++; + unreadCount++; + continue; + } + + if (rit->second & CHANNEL_MSG_STATUS_READ) { + // message is not new + if (rit->second & CHANNEL_MSG_STATUS_UNREAD_BY_USER) { + // message is unread + unreadCount++; + } + } else { + newCount++; + unreadCount++; + } + } + } /******* UNLOCKED ********/ + } + } + + return true; +} + +bool p3Channels::channelExtraFileHash(std::string path, std::string chId, FileInfo& fInfo){ + + // get file name + std::string fname, fnameBuff; + std::string::reverse_iterator rit; + + for(rit = path.rbegin(); *rit != '/' ; rit++){ + fnameBuff.push_back(*rit); + } + + // reverse string buff for correct file name + fname.append(fnameBuff.rbegin(), fnameBuff.rend()); + + + uint32_t flags = RS_FILE_HINTS_NETWORK_WIDE; + + // then hash file and get file info too + + if(!mRsFiles->ExtraFileHash(path, CHANNEL_STOREPERIOD, flags)) + return false; + + fInfo.path = path; + fInfo.fname = fname; + + return true; +} + + +bool p3Channels::channelExtraFileRemove(std::string hash, std::string chId){ + + uint32_t flags = RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_EXTRA; + + /* remove copy from channels directory */ + + FileInfo fInfo; + mRsFiles->FileDetails(hash, flags, fInfo); + std::string chPath = mChannelsDir + "/" + chId + "/" + fInfo.fname; + + if(remove(chPath.c_str()) == 0){ + std::cerr << "p3Channel::channelExtraFileRemove() Removed file :" + << chPath.c_str() << std::endl; + + }else{ + std::cerr << "p3Channel::channelExtraFileRemove() Failed to remove file :" + << chPath.c_str() << std::endl; + } + + return mRsFiles->ExtraFileRemove(hash, flags); + +} + + +std::string p3Channels::createChannel(std::wstring channelName, std::wstring channelDesc, uint32_t channelFlags, + unsigned char* pngImageData, uint32_t imageSize) +{ + + std::string grpId = createGroup(channelName, channelDesc, channelFlags, pngImageData, imageSize); + + // create channel directory + std::string channelDir = mChannelsDir + "/" + grpId; + + if(RsDirUtil::checkCreateDirectory(channelDir)) + std::cerr << "p3Channels::createChannel(): Failed to create channel directory " + << channelDir << std::endl; + + return grpId; +} + +RsSerialType *p3Channels::createSerialiser() +{ + return new RsChannelSerialiser(); +} + +bool p3Channels::locked_checkDistribMsg(RsDistribMsg *msg) +{ + return true; +} + + + + +bool p3Channels::channelSubscribe(std::string cId, bool subscribe, bool autoDl) +{ +#ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::channelSubscribe() " << cId << std::endl; +#endif + + { + RsStackMutex stack(distribMtx); + + if(subscribe) + mChannelStatus[cId] |= autoDl ? + (RS_CHAN_STATUS_AUTO_DL & RS_CHAN_STATUS_MASK) : ~RS_CHAN_STATUS_MASK; + } + + bool ok = subscribeToGroup(cId, subscribe); + + + // if subscribing set channel status bit field on whether + // or not to auto download + { + RsStackMutex stack(distribMtx); + + if(!ok || !subscribe){ + mChannelStatus.erase(cId); + removeChannelReadStatusEntry(cId); + } + else{ + addChannelReadStatusEntry(cId); + } + + IndicateConfigChanged(); + } + return ok; +} + +void p3Channels::addChannelReadStatusEntry(const std::string& cId) +{ + std::list::iterator lit = mReadStatus.begin(); + RsChannelReadStatus* rds = NULL; + + // check to ensure an entry does not exist + for(; lit != mReadStatus.end(); lit++){ + + if((*lit)->channelId == cId) + { + break; + } + } + + if(lit == mReadStatus.end()){ + rds = new RsChannelReadStatus(); + rds->channelId = cId; + mReadStatus.push_back(rds); + saveList.push_back(rds); + } + + return; +} + +//TODO: delete unsubscribed channels from entry +void p3Channels::removeChannelReadStatusEntry(const std::string& cId) +{ + std::list::iterator lit = mReadStatus.begin(); + statMap::iterator mit; + // check to ensure an entry does not exist + for(; lit != mReadStatus.end(); lit++){ + + if((*lit)->channelId == cId) + { + if((mit = (*lit)->msgReadStatus.find(cId)) != + (*lit)->msgReadStatus.end()){ + (*lit)->msgReadStatus.erase(mit); + break; + } + } + } + +} +bool p3Channels::channelShareKeys(std::string chId, std::list& peers){ + +#ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::channelShareKeys() " << chId << std::endl; +#endif + + return sharePubKey(chId, peers); + +} + +bool p3Channels::channelEditInfo(std::string chId, ChannelInfo& info){ + +#ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::channelUdateInfo() " << chId << std::endl; +#endif + + GroupInfo gi; + + RsStackMutex stack(distribMtx); + + gi.grpName = info.channelName; + gi.grpDesc = info.channelDesc; + + + if((info.pngChanImage != NULL) && (info.pngImageLen != 0)){ + gi.grpIcon.imageSize = info.pngImageLen; + gi.grpIcon.pngImageData = info.pngChanImage; + } + else{ + gi.grpIcon.imageSize = 0; + gi.grpIcon.pngImageData = NULL; + } + + return locked_editGroup(chId, gi); + +} + + +void p3Channels::getPubKeysAvailableGrpIds(std::list& grpIds) +{ + + getGrpListPubKeyAvailable(grpIds); + return; + +} + +bool p3Channels::channelSetAutoDl(const std::string& chId, bool autoDl) +{ + + RsStackMutex stack(distribMtx); + + statMap::iterator it = mChannelStatus.find(chId); + bool changed = false; + + if(it != mChannelStatus.end()){ + + if(autoDl) + it->second |= RS_CHAN_STATUS_AUTO_DL; + else + it->second &= ~(RS_CHAN_STATUS_AUTO_DL & RS_CHAN_STATUS_MASK); + + changed = true; + } + else + { +#ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::channelSetAutoDl(): " << "Channel does not exist" + << std::endl; +#endif + return false; + } + + // save configuration + if(changed) + IndicateConfigChanged(); + + return true; +} + + +bool p3Channels::channelGetAutoDl(const std::string& chId, bool& autoDl) +{ + RsStackMutex stack(distribMtx); + + statMap::iterator it = mChannelStatus.find(chId); + + if(it != mChannelStatus.end()) + { + autoDl = it->second & RS_CHAN_STATUS_AUTO_DL; + return true; + } + + return false; +} + +/***************************************************************************************/ +/****************** Event Feedback (Overloaded form p3distrib) *************************/ +/***************************************************************************************/ +/* only download in the first week of channel + * older stuff can be manually downloaded. + */ + +const uint32_t DOWNLOAD_PERIOD = 7 * 24 * 3600; + +/* This is called when we receive a msg, and also recalled + * on a subscription to a channel.. + */ + +bool p3Channels::locked_eventDuplicateMsg(GroupInfo *grp, RsDistribMsg *msg, const std::string& id, bool historical) +{ + std::string grpId = msg->grpId; + std::string msgId = msg->msgId; + std::string nullId; + + + RsChannelMsg *chanMsg = dynamic_cast(msg); + if (!chanMsg) + { + return true; + } + + // return if msg has d download already + + statMap MsgMap; + statMap::iterator mit1, mit2; + std::list::iterator lit = mReadStatus.begin(); + + for(;lit != mReadStatus.end();lit++){ + + if((*lit)->channelId == grpId) + break; + } + + mit2 = mChannelStatus.find(grpId); + + if(mit2 != mChannelStatus.end()) + { + if(!(mit2->second & RS_CHAN_STATUS_AUTO_DL)){ + + if(lit != mReadStatus.end()){ + + if(( mit1=(*lit)->msgReadStatus.find(msgId)) != (*lit)->msgReadStatus.end()) + (*lit)->msgReadStatus[msgId] |= (CHANNEL_MSG_STATUS_MASK & CHANNEL_MSG_STATUS_DOWLOADED); + + } + return false; + } + } + + if(lit != mReadStatus.end()){ + + if(( mit1=(*lit)->msgReadStatus.find(msgId)) != (*lit)->msgReadStatus.end()){ + if(mit1->second & CHANNEL_MSG_STATUS_DOWLOADED) + return false; + }else{ + // create an entry for msg id + (*lit)->msgReadStatus[msgId] = ~CHANNEL_MSG_STATUS_MASK; + } + } + + + + /* request the files + * NB: This will result in duplicates. + * it is upto ftserver/ftcontroller/ftextralist to handle this! + * */ + + bool download = (grp->flags & RS_DISTRIB_SUBSCRIBED); + + if (id == mOwnId) + { + download = false; +#ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::locked_eventDuplicateMsg() msg from self - not downloading"; + std::cerr << std::endl; +#endif + } + + /* check subscribed */ + if (!download) + { + return true; + } + + /* check age */ + time_t age = time(NULL) - msg->timestamp; + + if (age > (time_t)DOWNLOAD_PERIOD ) + { + return true; + } + + // get channel info to determine if channel is private or not + ChannelInfo cInfo; + bool chanPrivate = false; + + // tho if empty don't bother + if(!chanMsg->attachment.items.empty()){ + + + if(grp->flags & RS_DISTRIB_PRIVATE) + chanPrivate = true; + } + + /* Iterate through files */ + std::list::iterator fit; + for(fit = chanMsg->attachment.items.begin(); + fit != chanMsg->attachment.items.end(); fit++) + { + std::string fname = fit->name; + std::string hash = fit->hash; + uint64_t size = fit->filesize; + std::string channelname = grpId; + + std::string localpath; + uint32_t flags; + + // send to download directory if file is private + if(chanPrivate){ + localpath = mChannelsDir; + flags = RS_FILE_HINTS_BACKGROUND | RS_FILE_HINTS_EXTRA; + + }else{ + + localpath = ""; // forces dl to default directory + flags = RS_FILE_HINTS_BACKGROUND | + RS_FILE_HINTS_NETWORK_WIDE; + + } + + std::list srcIds; + srcIds.push_back(id); + + /* download it ... and flag for ExtraList + * don't do pre-search check as FileRequest does it better + * + * FileRequest will ignore request if file is already indexed. + */ + +#ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::locked_eventDuplicateMsg() " << " Downloading: " << fname; + std::cerr << " to: " << localpath << " from: " << id << std::endl; +#endif + + if(size < MAX_AUTO_DL) + mRsFiles->FileRequest(fname, hash, size, + localpath, flags, srcIds); + } + + if(lit != mReadStatus.end()){ + + (*lit)->msgReadStatus[msgId] |= (CHANNEL_MSG_STATUS_MASK & + CHANNEL_MSG_STATUS_DOWLOADED); + + } + + IndicateConfigChanged(); + + return true; +} + +#include "pqi/pqinotify.h" + +bool p3Channels::locked_eventNewMsg(GroupInfo *grp, RsDistribMsg *msg, const std::string& id, bool historical) +{ + std::string grpId = msg->grpId; + std::string msgId = msg->msgId; + std::string nullId; + + if (!historical) + { + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_CHAN_MSG, grpId, msgId, nullId); + } + + /* request the files + * NB: This could result in duplicates. + * which must be handled by ft side. + * + * this is exactly what DuplicateMsg does. + * */ + return locked_eventDuplicateMsg(grp, msg, id, historical); +} + +void p3Channels::locked_notifyGroupChanged(GroupInfo &grp, uint32_t flags, bool historical) +{ + std::string grpId = grp.grpId; + std::string msgId; + std::string nullId; + + + switch(flags) + { + case GRP_NEW_UPDATE: + #ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::locked_notifyGroupChanged() NEW UPDATE" << std::endl; + #endif + if (!historical) + { + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_CHAN_NEW, grpId, msgId, nullId); + } + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_CHANNELLIST_LOCKED, NOTIFY_TYPE_ADD); + break; + case GRP_UPDATE: + #ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::locked_notifyGroupChanged() UPDATE" << std::endl; + #endif + if (!historical) + { + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_CHAN_UPDATE, grpId, msgId, nullId); + } + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_CHANNELLIST_LOCKED, NOTIFY_TYPE_MOD); + break; + case GRP_LOAD_KEY: + #ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::locked_notifyGroupChanged() LOAD_KEY" << std::endl; + #endif + break; + case GRP_NEW_MSG: + #ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::locked_notifyGroupChanged() NEW MSG" << std::endl; + #endif + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_CHANNELLIST_LOCKED, NOTIFY_TYPE_ADD); + break; + case GRP_SUBSCRIBED: + #ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::locked_notifyGroupChanged() SUBSCRIBED" << std::endl; + #endif + { + std::string channeldir = mChannelsDir + "/" + grpId; + #ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::locked_notifyGroupChanged() creating directory: " << channeldir << std::endl; + #endif + + /* create chanDir */ + if (!RsDirUtil::checkCreateDirectory(channeldir)) { + std::cerr << "p3Channels::locked_notifyGroupChanged() Failed to create Channels Directory: " << channeldir << std::endl; + } + + /* check if downloads need to be started? */ + } + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_CHANNELLIST_LOCKED, NOTIFY_TYPE_ADD); + break; + case GRP_UNSUBSCRIBED: + #ifdef CHANNEL_DEBUG + std::cerr << "p3Channels::locked_notifyGroupChanged() UNSUBSCRIBED" << std::endl; + #endif + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_CHANNELLIST_LOCKED, NOTIFY_TYPE_DEL); + + /* won't stop downloads... */ + + break; + + default: + std::cerr << "p3Channels::locked_notifyGroupChanged() Unknown DEFAULT" << std::endl; + break; + } + + return p3GroupDistrib::locked_notifyGroupChanged(grp, flags, historical); +} + + +//TODO: if you want to config saving and loading for channel distrib service implement this method further +bool p3Channels::childLoadList(std::list& configSaves) +{ + RsChannelReadStatus* drs = NULL; + std::list::iterator it; + + for(it = configSaves.begin(); it != configSaves.end(); it++) + { + if(NULL != (drs = dynamic_cast(*it))) + { + processChanReadStatus(drs); + } + else + { + std::cerr << "p3Channels::childLoadList(): Configs items loaded were incorrect!" + << std::endl; + + if(*it != NULL) + delete *it; + } + } + + return true; +} + +void p3Channels::processChanReadStatus(RsChannelReadStatus* drs) +{ + + + mReadStatus.push_back(drs); + std::string chId = drs->channelId; + + statMap::iterator sit = drs->msgReadStatus.find(chId); + + if(sit != drs->msgReadStatus.end()){ + mChannelStatus[chId] = sit->second; + mChanReadStatus.insert(std::make_pair + (chId, drs)); + } + + // first pull out the channel id status + + mMsgReadStatus[drs->channelId] = drs->msgReadStatus; + mReadStatus.push_back(drs); + + saveList.push_back(drs); + + +} + +std::list p3Channels::childSaveList() +{ + + std::list::iterator lit = mReadStatus.begin(); + statMap::iterator sit, mit; + + // update or add current channel id status + for(; lit != mReadStatus.end(); lit++) + { + if((sit = mChannelStatus.find((*lit)->channelId)) != mChannelStatus.end()) + { + mit = (*lit)->msgReadStatus.find((*lit)->channelId); + if(mit != (*lit)->msgReadStatus.end()) + { + mit->second = sit->second; + } + else + { + (*lit)->msgReadStatus[(*lit)->channelId] = sit->second; + } + } + } + + return saveList; +} + +/****************************************/ diff --git a/libretroshare/src/services/p3channels.h b/libretroshare/src/services/p3channels.h new file mode 100644 index 000000000..89b4ad326 --- /dev/null +++ b/libretroshare/src/services/p3channels.h @@ -0,0 +1,129 @@ +#ifndef RS_P3_CHANNELS_INTERFACE_H +#define RS_P3_CHANNELS_INTERFACE_H + +/* + * libretroshare/src/services: p3channels.h + * + * RetroShare C++ Interface. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rschannels.h" +#include "retroshare/rsfiles.h" +#include "services/p3distrib.h" + +#include "serialiser/rstlvtypes.h" +#include "serialiser/rschannelitems.h" + +#define RS_CHAN_STATUS_MASK 0x000f +#define RS_CHAN_STATUS_AUTO_DL 0x0002 + +typedef std::map statMap; +typedef std::map chanStatMap; + +//! Channels is a distributed 'feed' service +/*! + * Implementations of rschannels interface + * @see RsChannels for definition of implemented interface + */ +class p3Channels: public p3GroupDistrib, public RsChannels +{ + public: + + p3Channels(uint16_t type, CacheStrapper *cs, CacheTransfer *cft, RsFiles *files, + std::string srcdir, std::string storedir, std::string channelsdir); +virtual ~p3Channels(); + +/*! + * cleans up dowloaded files older than one month, + * should be called during shutdown of rs + */ +void cleanUpOldFiles(); + +/****************************************/ +/********* rsChannels Interface ***********/ + +virtual bool channelsChanged(std::list &chanIds); + +virtual std::string createChannel(std::wstring chanName, std::wstring chanDesc, uint32_t chanFlags, + unsigned char* pngImageData, uint32_t size); + +virtual bool getChannelInfo(std::string cId, ChannelInfo &ci); +virtual bool getChannelList(std::list &chanList); +virtual bool getChannelMsgList(std::string cId, std::list &msgs); +virtual bool getChannelMessage(std::string cId, std::string mId, ChannelMsgInfo &msg); + +virtual bool ChannelMessageSend(ChannelMsgInfo &info); +virtual bool setMessageStatus(const std::string& cId, const std::string& mId, const uint32_t status, const uint32_t statusMask); +virtual bool getMessageStatus(const std::string& cId, const std::string& mId, uint32_t& status); + +virtual bool getMessageCount(const std::string cId, unsigned int &newCount, unsigned int &unreadCount); +virtual bool channelSubscribe(std::string cId, bool subscribe, bool autoDl); +virtual bool channelExtraFileHash(std::string path, std::string chId, FileInfo& fInfo); +virtual bool channelExtraFileRemove(std::string hash, std::string chId); +virtual bool channelRestoreKeys(std::string chId); +virtual bool channelShareKeys(std::string chId, std::list& peers); +virtual bool channelEditInfo(std::string chId, ChannelInfo &ci); +virtual void getPubKeysAvailableGrpIds(std::list& grpIds); +virtual bool channelSetAutoDl(const std::string& chId, bool autoDl); +virtual bool channelGetAutoDl(const std::string& chId, bool& autoDl); + +/***************************************************************************************/ +/****************** Event Feedback (Overloaded form p3distrib) *************************/ +/***************************************************************************************/ + + protected: +virtual void locked_notifyGroupChanged(GroupInfo &info, uint32_t flags, bool historical); +virtual bool locked_eventNewMsg(GroupInfo *, RsDistribMsg *, const std::string&, bool historical); +virtual bool locked_eventDuplicateMsg(GroupInfo *, RsDistribMsg *, const std::string&, bool historical); + + +/****************************************/ +/********* Overloaded Functions *********/ + +virtual RsSerialType *createSerialiser(); + +virtual bool locked_checkDistribMsg(RsDistribMsg *msg); + +virtual bool childLoadList(std::list& configSaves); +virtual std::list childSaveList(); + + +/****************************************/ + + private: + +void processChanReadStatus(RsChannelReadStatus* drs); +void addChannelReadStatusEntry(const std::string& cId); +void removeChannelReadStatusEntry(const std::string& cId); + RsFiles *mRsFiles; + std::string mChannelsDir; + std::list saveList; + + std::list mReadStatus; + std::map mChanReadStatus; + + chanStatMap mMsgReadStatus; + statMap mChannelStatus; +}; + + +#endif diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc new file mode 100644 index 000000000..1ea5e4206 --- /dev/null +++ b/libretroshare/src/services/p3chatservice.cc @@ -0,0 +1,1116 @@ +/* + * "$Id: p3ChatService.cc,v 1.24 2007-05-05 16:10:06 rmf24 Exp $" + * + * Other Bits for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "util/rsdir.h" +#include "retroshare/rsiface.h" +#include "pqi/pqibin.h" +#include "pqi/pqinotify.h" +#include "pqi/pqistore.h" + +#include "services/p3chatservice.h" + +/**** + * #define CHAT_DEBUG 1 + ****/ + +/************ NOTE ********************************* + * This Service is so simple that there is no + * mutex protection required! + * + */ + +p3ChatService::p3ChatService(p3ConnectMgr *cm) + :p3Service(RS_SERVICE_TYPE_CHAT), p3Config(CONFIG_TYPE_CHAT), mConnMgr(cm) +{ + addSerialType(new RsChatSerialiser()); + + _own_avatar = NULL ; + _custom_status_string = "" ; +} + +int p3ChatService::tick() +{ + if (receivedItems()) { + receiveChatQueue(); + } + + return 0; +} + +int p3ChatService::status() +{ + return 1; +} + +/***************** Chat Stuff **********************/ + +int p3ChatService::sendPublicChat(std::wstring &msg) +{ + /* go through all the peers */ + + std::list ids; + std::list::iterator it; + mConnMgr->getOnlineList(ids); + + /* add in own id -> so get reflection */ + ids.push_back(mConnMgr->getOwnId()); + +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::sendChat()"; + std::cerr << std::endl; +#endif + + for(it = ids.begin(); it != ids.end(); it++) + { + RsChatMsgItem *ci = new RsChatMsgItem(); + + ci->PeerId(*it); + ci->chatFlags = 0; + ci->sendTime = time(NULL); + ci->recvTime = ci->sendTime; + ci->message = msg; + +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::sendChat() Item:"; + std::cerr << std::endl; + ci->print(std::cerr); + std::cerr << std::endl; +#endif + + sendItem(ci); + } + + return 1; +} + + +class p3ChatService::AvatarInfo +{ + public: + AvatarInfo() + { + _image_size = 0 ; + _image_data = NULL ; + _peer_is_new = false ; // true when the peer has a new avatar + _own_is_new = false ; // true when I myself a new avatar to send to this peer. + } + + ~AvatarInfo() + { + delete[] _image_data ; + _image_data = NULL ; + _image_size = 0 ; + } + + AvatarInfo(const AvatarInfo& ai) + { + init(ai._image_data,ai._image_size) ; + } + + void init(const unsigned char *jpeg_data,int size) + { + _image_size = size ; + _image_data = new unsigned char[size] ; + memcpy(_image_data,jpeg_data,size) ; + } + AvatarInfo(const unsigned char *jpeg_data,int size) + { + init(jpeg_data,size) ; + } + + void toUnsignedChar(unsigned char *& data,uint32_t& size) const + { + data = new unsigned char[_image_size] ; + size = _image_size ; + memcpy(data,_image_data,size*sizeof(unsigned char)) ; + } + + uint32_t _image_size ; + unsigned char *_image_data ; + int _peer_is_new ; // true when the peer has a new avatar + int _own_is_new ; // true when I myself a new avatar to send to this peer. +}; + +void p3ChatService::sendGroupChatStatusString(const std::string& status_string) +{ + std::list ids; + mConnMgr->getOnlineList(ids); + +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::sendChat(): sending group chat status string: " << status_string << std::endl ; + std::cerr << std::endl; +#endif + + for(std::list::iterator it = ids.begin(); it != ids.end(); ++it) + { + RsChatStatusItem *cs = new RsChatStatusItem ; + + cs->status_string = status_string ; + cs->flags = RS_CHAT_FLAG_PUBLIC ; + + cs->PeerId(*it); + + sendItem(cs); + } +} + +void p3ChatService::sendStatusString( const std::string& id , const std::string& status_string) +{ + RsChatStatusItem *cs = new RsChatStatusItem ; + + cs->status_string = status_string ; + cs->flags = RS_CHAT_FLAG_PRIVATE ; + cs->PeerId(id); + +#ifdef CHAT_DEBUG + std::cerr << "sending chat status packet:" << std::endl ; + cs->print(std::cerr) ; +#endif + sendItem(cs); +} + +void p3ChatService::checkSizeAndSendMessage(RsChatMsgItem *msg) +{ + // We check the message item, and possibly split it into multiple messages, if the message is too big. + + static const uint32_t MAX_STRING_SIZE = 15000 ; + + while(msg->message.size() > MAX_STRING_SIZE) + { + // chop off the first 15000 wchars + + RsChatMsgItem *item = new RsChatMsgItem(*msg) ; + + item->message = item->message.substr(0,MAX_STRING_SIZE) ; + msg->message = msg->message.substr(MAX_STRING_SIZE,msg->message.size()-MAX_STRING_SIZE) ; + + // Clear out any one time flags that should not be copied into multiple objects. This is + // a precaution, in case the receivign peer does not yet handle split messages transparently. + // + item->chatFlags &= (RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_PUBLIC) ; + + // Indicate that the message is to be continued. + // + item->chatFlags |= RS_CHAT_FLAG_PARTIAL_MESSAGE ; + sendItem(item) ; + } + sendItem(msg) ; +} + +bool p3ChatService::sendPrivateChat(std::string &id, std::wstring &msg) +{ + // make chat item.... +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::sendPrivateChat()"; + std::cerr << std::endl; +#endif + + RsChatMsgItem *ci = new RsChatMsgItem(); + + ci->PeerId(id); + ci->chatFlags = RS_CHAT_FLAG_PRIVATE; + ci->sendTime = time(NULL); + ci->recvTime = ci->sendTime; + ci->message = msg; + + if (!mConnMgr->isOnline(id)) { + /* peer is offline, add to outgoing list */ + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + privateOutgoingList.push_back(ci); + } + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_ADD); + + IndicateConfigChanged(); + + return false; + } + + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + std::map::iterator it = _avatars.find(id) ; + + if(it == _avatars.end()) + { + _avatars[id] = new AvatarInfo ; + it = _avatars.find(id) ; + } + if(it->second->_own_is_new) + { +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::sendPrivateChat: new avatar never sent to peer " << id << ". Setting flag to packet." << std::endl; +#endif + + ci->chatFlags |= RS_CHAT_FLAG_AVATAR_AVAILABLE ; + it->second->_own_is_new = false ; + } + } + +#ifdef CHAT_DEBUG + std::cerr << "Sending msg to peer " << id << ", flags = " << ci->chatFlags << std::endl ; + std::cerr << "p3ChatService::sendPrivateChat() Item:"; + std::cerr << std::endl; + ci->print(std::cerr); + std::cerr << std::endl; +#endif + + checkSizeAndSendMessage(ci); + + // Check if custom state string has changed, in which case it should be sent to the peer. + bool should_send_state_string = false ; + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it = _state_strings.find(id) ; + + if(it == _state_strings.end()) + { + _state_strings[id] = StateStringInfo() ; + it = _state_strings.find(id) ; + it->second._own_is_new = true ; + } + if(it->second._own_is_new) + { + should_send_state_string = true ; + it->second._own_is_new = false ; + } + } + + if(should_send_state_string) + { +#ifdef CHAT_DEBUG + std::cerr << "own status string is new for peer " << id << ": sending it." << std::endl ; +#endif + RsChatStatusItem *cs = makeOwnCustomStateStringItem() ; + cs->PeerId(id) ; + sendItem(cs) ; + } + + return true; +} + +bool p3ChatService::checkAndRebuildPartialMessage(RsChatMsgItem *ci) +{ + // Check is the item is ending an incomplete item. + // + std::map::iterator it = _pendingPartialMessages.find(ci->PeerId()) ; + + bool ci_is_partial = ci->chatFlags & RS_CHAT_FLAG_PARTIAL_MESSAGE ; + + if(it != _pendingPartialMessages.end()) + { +#ifdef CHAT_DEBUG + std::cerr << "Pending messahe found. Happending it." << std::endl; +#endif + // Yes, there is. Append the item to ci. + + ci->message = it->second->message + ci->message ; + ci->chatFlags |= it->second->chatFlags ; + + delete it->second ; + + if(!ci_is_partial) + _pendingPartialMessages.erase(it) ; + } + + if(ci_is_partial) + { +#ifdef CHAT_DEBUG + std::cerr << "Message is partial, storing for later." << std::endl; +#endif + // The item is a partial message. Push it, and wait for the rest. + // + _pendingPartialMessages[ci->PeerId()] = ci ; + return false ; + } + else + { +#ifdef CHAT_DEBUG + std::cerr << "Message is complete, using it now." << std::endl; +#endif + return true ; + } +} + + +void p3ChatService::receiveChatQueue() +{ + bool publicChanged = false; + bool privateChanged = false; + + time_t now = time(NULL); + RsItem *item ; + + while(NULL != (item=recvItem())) + { +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::receiveChatQueue() Item:" << (void*)item << std::endl ; +#endif + RsChatMsgItem *ci = dynamic_cast(item) ; + + if(ci != NULL) // real chat message + { +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::receiveChatQueue() Item:"; + std::cerr << std::endl; + ci->print(std::cerr); + std::cerr << std::endl; + std::cerr << "Got msg. Flags = " << ci->chatFlags << std::endl ; +#endif + if(!checkAndRebuildPartialMessage(ci)) + continue ; + + if(ci->chatFlags & RS_CHAT_FLAG_REQUESTS_AVATAR) // no msg here. Just an avatar request. + { + sendAvatarJpegData(ci->PeerId()) ; + delete item ; + continue ; + } + else // normal msg. Return it normally. + { + // Check if new avatar is available at peer's. If so, send a request to get the avatar. + if(ci->chatFlags & RS_CHAT_FLAG_AVATAR_AVAILABLE) + { + std::cerr << "New avatar is available for peer " << ci->PeerId() << ", sending request" << std::endl ; + sendAvatarRequest(ci->PeerId()) ; + ci->chatFlags &= ~RS_CHAT_FLAG_AVATAR_AVAILABLE ; + } + + std::map::const_iterator it = _avatars.find(ci->PeerId()) ; + +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice:: avatar requested from above. " << std::endl ; +#endif + // has avatar. Return it strait away. + // + if(it!=_avatars.end() && it->second->_peer_is_new) + { + std::cerr << "Avatar is new for peer. ending info above" << std::endl ; + ci->chatFlags |= RS_CHAT_FLAG_AVATAR_AVAILABLE ; + } + + if ((ci->chatFlags & RS_CHAT_FLAG_PRIVATE) == 0) { + /* notify public chat message */ + std::string message; + message.assign(ci->message.begin(), ci->message.end()); + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_CHAT_NEW, ci->PeerId(), message, ""); + } + + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + ci->recvTime = now; + + if (ci->chatFlags & RS_CHAT_FLAG_PRIVATE) { + privateChanged = true; + privateIncomingList.push_back(ci); // don't delete the item !! + } else { + publicChanged = true; + publicList.push_back(ci); // don't delete the item !! + } + } /* UNLOCK */ + } + } + + RsChatStatusItem *cs = dynamic_cast(item) ; + + if(cs != NULL) + { +#ifdef CHAT_DEBUG + std::cerr << "Received status string \"" << cs->status_string << "\"" << std::endl ; +#endif + + if(cs->flags & RS_CHAT_FLAG_REQUEST_CUSTOM_STATE){ // no state here just a request. + sendCustomState(cs->PeerId()) ; + + } + else // Check if new custom string is available at peer's. If so, send a request to get the custom string. + if(cs->flags & RS_CHAT_FLAG_CUSTOM_STATE) + { + receiveStateString(cs->PeerId(),cs->status_string) ; // store it + rsicontrol->getNotify().notifyCustomState(cs->PeerId(), cs->status_string) ; + }else + if(cs->flags & RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE){ + + std::cerr << "New custom state is available for peer " << cs->PeerId() << ", sending request" << std::endl ; + sendCustomStateRequest(cs->PeerId()) ; + }else + if(cs->flags & RS_CHAT_FLAG_PRIVATE) + rsicontrol->getNotify().notifyChatStatus(cs->PeerId(),cs->status_string,true) ; + else + if(cs->flags & RS_CHAT_FLAG_PUBLIC) + rsicontrol->getNotify().notifyChatStatus(cs->PeerId(),cs->status_string,false) ; + + delete item; + continue ; + } + + RsChatAvatarItem *ca = dynamic_cast(item) ; + + if(ca != NULL) + { + receiveAvatarJpegData(ca) ; + +#ifdef CHAT_DEBUG + std::cerr << "Received avatar data for peer " << ca->PeerId() << ". Notifying." << std::endl ; +#endif + rsicontrol->getNotify().notifyPeerHasNewAvatar(ca->PeerId()) ; + + delete item ; + continue ; + } + } + + if (publicChanged) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PUBLIC_CHAT, NOTIFY_TYPE_ADD); + } + if (privateChanged) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); + + IndicateConfigChanged(); // only private chat messages are saved + } +} + +int p3ChatService::getPublicChatQueueCount() +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + return publicList.size(); +} + +bool p3ChatService::getPublicChatQueue(std::list &chats) +{ + bool changed = false; + + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + // get the items from the public list. + if (publicList.size() == 0) { + return false; + } + + std::list::iterator it; + while (publicList.size()) { + RsChatMsgItem *c = publicList.front(); + publicList.pop_front(); + + ChatInfo ci; + initRsChatInfo(c, ci); + chats.push_back(ci); + + changed = true; + + delete c; + } + } /* UNLOCKED */ + + if (changed) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PUBLIC_CHAT, NOTIFY_TYPE_DEL); + } + + return true; +} + +int p3ChatService::getPrivateChatQueueCount(bool incoming) +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + if (incoming) { + return privateIncomingList.size(); + } + + return privateOutgoingList.size(); +} + +bool p3ChatService::getPrivateChatQueueIds(bool incoming, std::list &ids) +{ + ids.clear(); + + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::list *list; + + if (incoming) { + list = &privateIncomingList; + } else { + list = &privateOutgoingList; + } + + // get the items from the private list. + if (list->size() == 0) { + return false; + } + + std::list::iterator it; + for (it = list->begin(); it != list->end(); it++) { + RsChatMsgItem *c = *it; + + if (std::find(ids.begin(), ids.end(), c->PeerId()) == ids.end()) { + ids.push_back(c->PeerId()); + } + } + + return true; +} + +bool p3ChatService::getPrivateChatQueue(bool incoming, const std::string &id, std::list &chats) +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::list *list; + + if (incoming) { + list = &privateIncomingList; + } else { + list = &privateOutgoingList; + } + + // get the items from the private list. + if (list->size() == 0) { + return false; + } + + std::list::iterator it; + for (it = list->begin(); it != list->end(); it++) { + RsChatMsgItem *c = *it; + + if (c->PeerId() == id) { + ChatInfo ci; + initRsChatInfo(c, ci); + chats.push_back(ci); + } + } + + return (chats.size() > 0); +} + +bool p3ChatService::clearPrivateChatQueue(bool incoming, const std::string &id) +{ + bool changed = false; + + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::list *list; + + if (incoming) { + list = &privateIncomingList; + } else { + list = &privateOutgoingList; + } + + // get the items from the private list. + if (list->size() == 0) { + return false; + } + + std::list::iterator it = list->begin(); + while (it != list->end()) { + RsChatMsgItem *c = *it; + + if (c->PeerId() == id) { + delete c; + changed = true; + + std::list::iterator it1 = it; + it++; + list->erase(it1); + + continue; + } + + it++; + } + } /* UNLOCKED */ + + if (changed) { + rsicontrol->getNotify().notifyListChange(incoming ? NOTIFY_LIST_PRIVATE_INCOMING_CHAT : NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_DEL); + + IndicateConfigChanged(); + } + + return true; +} + +void p3ChatService::initRsChatInfo(RsChatMsgItem *c, ChatInfo &i) +{ + i.rsid = c->PeerId(); + i.chatflags = 0; + i.sendTime = c->sendTime; + i.recvTime = c->recvTime; + i.msg = c->message; + + if (c -> chatFlags & RS_CHAT_FLAG_PRIVATE) + { + i.chatflags |= RS_CHAT_PRIVATE; + //std::cerr << "RsServer::initRsChatInfo() Chat Private!!!"; + } + else + { + i.chatflags |= RS_CHAT_PUBLIC; + //std::cerr << "RsServer::initRsChatInfo() Chat Public!!!"; + } +} + +void p3ChatService::setOwnCustomStateString(const std::string& s) +{ + std::list onlineList; + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice: Setting own state string to new value : " << s << std::endl ; +#endif + _custom_status_string = s ; + + for(std::map::iterator it(_state_strings.begin());it!=_state_strings.end();++it) + it->second._own_is_new = true ; + + mConnMgr->getOnlineList(onlineList); + } + + rsicontrol->getNotify().notifyOwnStatusMessageChanged() ; + + // alert your online peers to your newly set status + std::list::iterator it(onlineList.begin()); + for(; it != onlineList.end(); it++){ + + RsChatStatusItem *cs = new RsChatStatusItem(); + cs->flags = RS_CHAT_FLAG_CUSTOM_STATE_AVAILABLE; + cs->status_string = ""; + cs->PeerId(*it); + sendItem(cs); + } + + IndicateConfigChanged(); +} + +void p3ChatService::setOwnAvatarJpegData(const unsigned char *data,int size) +{ + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice: Setting own avatar to new image." << std::endl ; +#endif + + if(_own_avatar != NULL) + delete _own_avatar ; + + _own_avatar = new AvatarInfo(data,size) ; + + // set the info that our avatar is new, for all peers + for(std::map::iterator it(_avatars.begin());it!=_avatars.end();++it) + it->second->_own_is_new = true ; + } + IndicateConfigChanged(); + + rsicontrol->getNotify().notifyOwnAvatarChanged() ; + +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice:setOwnAvatarJpegData() done." << std::endl ; +#endif + +} + +void p3ChatService::receiveStateString(const std::string& id,const std::string& s) +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice: received custom state string for peer " << id << ". Storing it." << std::endl ; +#endif + + bool new_peer = (_state_strings.find(id) == _state_strings.end()) ; + + _state_strings[id]._custom_status_string = s ; + _state_strings[id]._peer_is_new = true ; + _state_strings[id]._own_is_new = new_peer ; +} + +void p3ChatService::receiveAvatarJpegData(RsChatAvatarItem *ci) +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice: received avatar jpeg data for peer " << ci->PeerId() << ". Storing it." << std::endl ; +#endif + + bool new_peer = (_avatars.find(ci->PeerId()) == _avatars.end()) ; + + if (new_peer == false && _avatars[ci->PeerId()]) { + delete _avatars[ci->PeerId()]; + } + _avatars[ci->PeerId()] = new AvatarInfo(ci->image_data,ci->image_size) ; + _avatars[ci->PeerId()]->_peer_is_new = true ; + _avatars[ci->PeerId()]->_own_is_new = new_peer ; +} + +std::string p3ChatService::getOwnCustomStateString() +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + return _custom_status_string ; +} +void p3ChatService::getOwnAvatarJpegData(unsigned char *& data,int& size) +{ + // should be a Mutex here. + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + uint32_t s = 0 ; +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice:: own avatar requested from above. " << std::endl ; +#endif + // has avatar. Return it strait away. + // + if(_own_avatar != NULL) + { + _own_avatar->toUnsignedChar(data,s) ; + size = s ; + } + else + { + data=NULL ; + size=0 ; + } +} + +std::string p3ChatService::getCustomStateString(const std::string& peer_id) +{ + // should be a Mutex here. + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it = _state_strings.find(peer_id) ; + +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice:: status string for peer " << peer_id << " requested from above. " << std::endl ; +#endif + // has it. Return it strait away. + // + if(it!=_state_strings.end()) + { + it->second._peer_is_new = false ; +#ifdef CHAT_DEBUG + std::cerr << "Already has status string. Returning it" << std::endl ; +#endif + return it->second._custom_status_string ; + } + + +#ifdef CHAT_DEBUG + std::cerr << "No status string for this peer. requesting it." << std::endl ; +#endif + + + sendCustomStateRequest(peer_id); + return std::string() ; +} + +void p3ChatService::getAvatarJpegData(const std::string& peer_id,unsigned char *& data,int& size) +{ + // should be a Mutex here. + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::map::const_iterator it = _avatars.find(peer_id) ; + +#ifdef CHAT_DEBUG + std::cerr << "p3chatservice:: avatar for peer " << peer_id << " requested from above. " << std::endl ; +#endif + // has avatar. Return it straight away. + // + if(it!=_avatars.end()) + { + uint32_t s=0 ; + it->second->toUnsignedChar(data,s) ; + size = s ; + it->second->_peer_is_new = false ; +#ifdef CHAT_DEBUG + std::cerr << "Already has avatar. Returning it" << std::endl ; +#endif + return ; + } else { + #ifdef CHAT_DEBUG + std::cerr << "No avatar for this peer. Requesting it by sending request packet." << std::endl ; + #endif + } + + sendAvatarRequest(peer_id); +} + +void p3ChatService::sendAvatarRequest(const std::string& peer_id) +{ + // Doesn't have avatar. Request it. + // + RsChatMsgItem *ci = new RsChatMsgItem(); + + ci->PeerId(peer_id); + ci->chatFlags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_REQUESTS_AVATAR ; + ci->sendTime = time(NULL); + ci->message.erase(); + +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::sending request for avatar, to peer " << peer_id << std::endl ; + std::cerr << std::endl; +#endif + + sendItem(ci); +} + +void p3ChatService::sendCustomStateRequest(const std::string& peer_id){ + + RsChatStatusItem* cs = new RsChatStatusItem; + + cs->PeerId(peer_id); + cs->flags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_REQUEST_CUSTOM_STATE ; + cs->status_string.erase(); + +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::sending request for status, to peer " << peer_id << std::endl ; + std::cerr << std::endl; +#endif + + sendItem(cs); +} + +RsChatStatusItem *p3ChatService::makeOwnCustomStateStringItem() +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + RsChatStatusItem *ci = new RsChatStatusItem(); + + ci->flags = RS_CHAT_FLAG_CUSTOM_STATE ; + ci->status_string = _custom_status_string ; + + return ci ; +} +RsChatAvatarItem *p3ChatService::makeOwnAvatarItem() +{ + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + RsChatAvatarItem *ci = new RsChatAvatarItem(); + + _own_avatar->toUnsignedChar(ci->image_data,ci->image_size) ; + + return ci ; +} + + +void p3ChatService::sendAvatarJpegData(const std::string& peer_id) +{ + #ifdef CHAT_DEBUG + std::cerr << "p3chatservice: sending requested for peer " << peer_id << ", data=" << (void*)_own_avatar << std::endl ; + #endif + + if(_own_avatar != NULL) + { + RsChatAvatarItem *ci = makeOwnAvatarItem(); + ci->PeerId(peer_id); + + // take avatar, and embed it into a std::wstring. + // +#ifdef CHAT_DEBUG + std::cerr << "p3ChatService::sending avatar image to peer" << peer_id << ", image size = " << ci->image_size << std::endl ; + std::cerr << std::endl; +#endif + + sendItem(ci) ; + } + else { +#ifdef CHAT_DEBUG + std::cerr << "We have no avatar yet: Doing nothing" << std::endl ; +#endif + } +} + +void p3ChatService::sendCustomState(const std::string& peer_id){ + +#ifdef CHAT_DEBUG +std::cerr << "p3chatservice: sending requested status string for peer " << peer_id << std::endl ; +#endif + + RsChatStatusItem *cs = makeOwnCustomStateStringItem(); + cs->PeerId(peer_id); + + sendItem(cs); +} + +bool p3ChatService::loadList(std::list& load) +{ + for(std::list::const_iterator it(load.begin());it!=load.end();++it) + { + RsChatAvatarItem *ai = NULL ; + + if(NULL != (ai = dynamic_cast(*it))) + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + _own_avatar = new AvatarInfo(ai->image_data,ai->image_size) ; + + delete *it; + + continue; + } + + RsChatStatusItem *mitem = NULL ; + + if(NULL != (mitem = dynamic_cast(*it))) + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + _custom_status_string = mitem->status_string ; + + delete *it; + + continue; + } + + RsPrivateChatMsgConfigItem *citem = NULL ; + + if(NULL != (citem = dynamic_cast(*it))) + { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + if (citem->chatFlags & RS_CHAT_FLAG_PRIVATE) { + RsChatMsgItem *ci = new RsChatMsgItem(); + citem->get(ci); + + if (citem->configFlags & RS_CHATMSG_CONFIGFLAG_INCOMING) { + privateIncomingList.push_back(ci); + } else { + privateOutgoingList.push_back(ci); + } + } else { + // ignore all other items + } + + + delete *it; + + continue; + } + + // delete unknown items + delete *it; + } + return true; +} + +bool p3ChatService::saveList(bool& cleanup, std::list& list) +{ + cleanup = true; + + /* now we create a pqistore, and stream all the msgs into it */ + + if(_own_avatar != NULL) + { + RsChatAvatarItem *ci = makeOwnAvatarItem() ; + ci->PeerId(mConnMgr->getOwnId()); + + list.push_back(ci) ; + } + + mChatMtx.lock(); /****** MUTEX LOCKED *******/ + + RsChatStatusItem *di = new RsChatStatusItem ; + di->status_string = _custom_status_string ; + di->flags = RS_CHAT_FLAG_CUSTOM_STATE ; + + list.push_back(di) ; + + /* save incoming private chat messages */ + + std::list::iterator it; + for (it = privateIncomingList.begin(); it != privateIncomingList.end(); it++) { + RsPrivateChatMsgConfigItem *ci = new RsPrivateChatMsgConfigItem; + + ci->set(*it, (*it)->PeerId(), RS_CHATMSG_CONFIGFLAG_INCOMING); + + list.push_back(ci); + } + + /* save outgoing private chat messages */ + + for (it = privateOutgoingList.begin(); it != privateOutgoingList.end(); it++) { + RsPrivateChatMsgConfigItem *ci = new RsPrivateChatMsgConfigItem; + + ci->set(*it, (*it)->PeerId(), 0); + + list.push_back(ci); + } + + return true; +} + +void p3ChatService::saveDone() +{ + /* unlock mutex */ + mChatMtx.unlock(); /****** MUTEX UNLOCKED *******/ +} + +RsSerialiser *p3ChatService::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser ; + rss->addSerialType(new RsChatSerialiser) ; + + return rss ; +} + +/*************** pqiMonitor callback ***********************/ + +void p3ChatService::statusChange(const std::list &plist) +{ + std::list::const_iterator it; + for (it = plist.begin(); it != plist.end(); it++) { + if (it->state & RS_PEER_S_FRIEND) { + if (it->actions & RS_PEER_CONNECTED) { + /* send the saved outgoing messages */ + bool changed = false; + + if (privateOutgoingList.size()) { + RsStackMutex stack(mChatMtx); /********** STACK LOCKED MTX ******/ + + std::list::iterator cit = privateOutgoingList.begin(); + while (cit != privateOutgoingList.end()) { + RsChatMsgItem *c = *cit; + + if (c->PeerId() == it->id) { + sendItem(c); // delete item + + changed = true; + + cit = privateOutgoingList.erase(cit); + + continue; + } + + cit++; + } + } /* UNLOCKED */ + + if (changed) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_DEL); + + IndicateConfigChanged(); + } + } + } + } +} diff --git a/libretroshare/src/services/p3chatservice.h b/libretroshare/src/services/p3chatservice.h new file mode 100644 index 000000000..c75ac67a1 --- /dev/null +++ b/libretroshare/src/services/p3chatservice.h @@ -0,0 +1,232 @@ +/* + * libretroshare/src/services chatservice.h + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef SERVICE_CHAT_HEADER +#define SERVICE_CHAT_HEADER + +#include +#include + +#include "serialiser/rsmsgitems.h" +#include "services/p3service.h" +#include "pqi/p3connmgr.h" +#include "retroshare/rsmsgs.h" + +//!The basic Chat service. + /** + * + * Can be used to send and receive chats, immediate status (using notify), avatars, and custom status + * This service uses rsnotify (callbacks librs clients (e.g. rs-gui)) + * @see NotifyBase + */ +class p3ChatService: public p3Service, public p3Config, public pqiMonitor +{ + public: + p3ChatService(p3ConnectMgr *cm); + + /***** overloaded from p3Service *****/ + /*! + * This retrieves all chat msg items and also (important!) + * processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned + * (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status + * : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar + * @see NotifyBase + */ + virtual int tick(); + virtual int status(); + + /*************** pqiMonitor callback ***********************/ + virtual void statusChange(const std::list &plist); + + /*! + * public chat sent to all peers + */ + int sendPublicChat(std::wstring &msg); + + /********* RsMsgs ***********/ + /*! + * chat is sent to specifc peer + * @param id peer to send chat msg to + */ + bool sendPrivateChat(std::string &id, std::wstring &msg); + + /*! + * can be used to send 'immediate' status msgs, these status updates are meant for immediate use by peer (not saved by rs) + * e.g currently used to update user when a peer 'is typing' during a chat + */ + void sendStatusString(const std::string& peer_id,const std::string& status_str) ; + + /*! + * send to all peers online + *@see sendStatusString() + */ + void sendGroupChatStatusString(const std::string& status_str) ; + + /*! + * this retrieves custom status for a peers, generate a requests to the peer + * @param peer_id the id of the peer you want status string for + */ + std::string getCustomStateString(const std::string& peer_id) ; + + /*! + * sets the client's custom status, generates 'status available' item sent to all online peers + */ + void setOwnCustomStateString(const std::string&) ; + + /*! + * @return client's custom string + */ + std::string getOwnCustomStateString() ; + + /*! gets the peer's avatar in jpeg format, if available. Null otherwise. Also asks the peer to send + * its avatar, if not already available. Creates a new unsigned char array. It's the caller's + * responsibility to delete this ones used. + */ + void getAvatarJpegData(const std::string& peer_id,unsigned char *& data,int& size) ; + + /*! + * Sets the avatar data and size for client's account + * @param data is copied, so should be destroyed by the caller + */ + void setOwnAvatarJpegData(const unsigned char *data,int size) ; + + /*! + * Gets the avatar data for clients account + * data is in jpeg format + */ + void getOwnAvatarJpegData(unsigned char *& data,int& size) ; + + /*! + * returns the count of messages in public queue + * @param public or private queue + */ + int getPublicChatQueueCount(); + + /*! + * This retrieves all public chat msg items + */ + bool getPublicChatQueue(std::list &chats); + + /*! + * returns the count of messages in private queue + * @param public or private queue + */ + int getPrivateChatQueueCount(bool incoming); + + /*! + * @param id's of available private chat messages + */ + bool getPrivateChatQueueIds(bool incoming, std::list &ids); + + /*! + * This retrieves all private chat msg items for peer + */ + bool getPrivateChatQueue(bool incoming, const std::string &id, std::list &chats); + + /*! + * @param clear private chat queue + */ + bool clearPrivateChatQueue(bool incoming, const std::string &id); + + protected: + /************* from p3Config *******************/ + virtual RsSerialiser *setupSerialiser() ; + + /*! + * chat msg items and custom status are saved + */ + virtual bool saveList(bool& cleanup, std::list&) ; + virtual void saveDone(); + virtual bool loadList(std::list& load) ; + + private: + RsMutex mChatMtx; + + class AvatarInfo ; + class StateStringInfo ; + + // Receive chat queue + void receiveChatQueue(); + + void initRsChatInfo(RsChatMsgItem *c, ChatInfo &i); + + + /// Send avatar info to peer in jpeg format. + void sendAvatarJpegData(const std::string& peer_id) ; + + /// Send custom state info to peer + void sendCustomState(const std::string& peer_id); + + /// Receive the avatar in a chat item, with RS_CHAT_RECEIVE_AVATAR flag. + void receiveAvatarJpegData(RsChatAvatarItem *ci) ; // new method + void receiveStateString(const std::string& id,const std::string& s) ; + + /// Sends a request for an avatar to the peer of given id + void sendAvatarRequest(const std::string& peer_id) ; + + /// Send a request for custom status string + void sendCustomStateRequest(const std::string& peer_id); + + /// called as a proxy to sendItem(). Possibly splits item into multiple items of size lower than the maximum item size. + void checkSizeAndSendMessage(RsChatMsgItem *item) ; + + /// Called when a RsChatMsgItem is received. The item may be collapsed with any waiting partial chat item from the same peer. + bool checkAndRebuildPartialMessage(RsChatMsgItem*) ; + + RsChatAvatarItem *makeOwnAvatarItem() ; + RsChatStatusItem *makeOwnCustomStateStringItem() ; + + p3ConnectMgr *mConnMgr; + + std::list publicList; + std::list privateIncomingList; + std::list privateOutgoingList; + + AvatarInfo *_own_avatar ; + std::map _avatars ; + std::map _pendingPartialMessages ; + + std::string _custom_status_string ; + std::map _state_strings ; +}; + +class p3ChatService::StateStringInfo +{ + public: + StateStringInfo() + { + _custom_status_string = "" ; // the custom status string of the peer + _peer_is_new = false ; // true when the peer has a new avatar + _own_is_new = false ; // true when I myself a new avatar to send to this peer. + } + + std::string _custom_status_string ; + int _peer_is_new ; // true when the peer has a new avatar + int _own_is_new ; // true when I myself a new avatar to send to this peer. +}; + +#endif // SERVICE_CHAT_HEADER + diff --git a/libretroshare/src/services/p3disc.cc b/libretroshare/src/services/p3disc.cc new file mode 100644 index 000000000..57a1a30b9 --- /dev/null +++ b/libretroshare/src/services/p3disc.cc @@ -0,0 +1,1207 @@ +/* + * libretroshare/src/services: p3disc.cc + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "retroshare/rsiface.h" +#include "retroshare/rsinit.h" /* for PGPSSL flag */ +#include "retroshare/rspeers.h" +#include "services/p3disc.h" + +#include "pqi/authssl.h" +#include "pqi/authgpg.h" +#include "pqi/p3connmgr.h" + +#include +#include +#include + +const uint32_t AUTODISC_LDI_SUBTYPE_PING = 0x01; +const uint32_t AUTODISC_LDI_SUBTYPE_RPLY = 0x02; + +#include + +#include "util/rsdebug.h" +#include "util/rsprint.h" +#include "util/rsversion.h" + +const int pqidisczone = 2482; + +//static int convertTDeltaToTRange(double tdelta); +//static int convertTRangeToTDelta(int trange); + +// Operating System specific includes. +#include "pqi/pqinetwork.h" + +/* DISC FLAGS */ + +const uint32_t P3DISC_FLAGS_USE_DISC = 0x0001; +const uint32_t P3DISC_FLAGS_USE_DHT = 0x0002; +const uint32_t P3DISC_FLAGS_EXTERNAL_ADDR = 0x0004; +const uint32_t P3DISC_FLAGS_STABLE_UDP = 0x0008; +const uint32_t P3DISC_FLAGS_PEER_ONLINE = 0x0010; +const uint32_t P3DISC_FLAGS_OWN_DETAILS = 0x0020; +const uint32_t P3DISC_FLAGS_PEER_TRUSTS_ME= 0x0040; +const uint32_t P3DISC_FLAGS_ASK_VERSION = 0x0080; + + +/***** + * #define P3DISC_DEBUG 1 + ****/ + +//#define P3DISC_DEBUG 1 + +/*********** NOTE *************** + * + * Only need Mutexs for neighbours information + */ + +/****************************************************************************************** + ****************************** NEW DISCOVERY ******************************************* + ****************************************************************************************** + *****************************************************************************************/ + +p3disc::p3disc(p3ConnectMgr *cm, pqipersongrp *pqih) + :p3Service(RS_SERVICE_TYPE_DISC), + p3Config(CONFIG_TYPE_P3DISC), + mConnMgr(cm), + mPqiPersonGrp(pqih) +{ + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + addSerialType(new RsDiscSerialiser()); + + lastSentHeartbeatTime = time(NULL); + + //add own version to versions map + versions[AuthSSL::getAuthSSL()->OwnId()] = RsUtil::retroshareVersion(); +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::p3disc() setup"; + std::cerr << std::endl; +#endif + + return; +} + +int p3disc::tick() +{ + //send a heartbeat to all connected peers + if (time(NULL) - lastSentHeartbeatTime > HEARTBEAT_REPEAT_TIME) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::tick() sending heartbeat to all peers" << std::endl; +#endif + lastSentHeartbeatTime = time(NULL); + std::list peers; + mConnMgr->getOnlineList(peers); + for (std::list::const_iterator pit = peers.begin(); pit != peers.end(); ++pit) { + sendHeartbeat(*pit); + } + } + + return handleIncoming(); +} + +int p3disc::handleIncoming() +{ + RsItem *item = NULL; + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::handleIncoming()" << std::endl; +#endif + + // if off discard item. + peerConnectState detail; + if (!mConnMgr->getOwnNetStatus(detail) || (detail.visState & RS_VIS_STATE_NODISC)) + { + while(NULL != (item = recvItem())) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::handleIncoming() Deleting - Cos RemoteDisc Off!" << std::endl; + item -> print(std::cerr); + std::cerr << std::endl; +#endif + + delete item; + } + return 0; + } + + int nhandled = 0; + // While messages read + while(NULL != (item = recvItem())) + { + RsDiscAskInfo *inf = NULL; + RsDiscReply *dri = NULL; + RsDiscVersion *dvi = NULL; + RsDiscHeartbeat *dta = NULL; + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::handleIncoming() Received Message!" << std::endl; + item -> print(std::cerr); + std::cerr << std::endl; +#endif + + + // if discovery reply then respond if haven't already. + if (NULL != (dri = dynamic_cast (item))) { + + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + /* search pending item and remove it, when already exist */ + std::list::iterator it; + for (it = pendingDiscReplyInList.begin(); it != pendingDiscReplyInList.end(); it++) { + if ((*it)->PeerId() == dri->PeerId() && (*it)->aboutId == dri->aboutId) { + delete (*it); + pendingDiscReplyInList.erase(it); + break; + } + } + + // add item to list for later process + pendingDiscReplyInList.push_back(dri); // no delete + } + else if (NULL != (dvi = dynamic_cast (item))) { + recvPeerVersionMsg(dvi); + nhandled++; + delete item; + } + else if (NULL != (inf = dynamic_cast (item))) /* Ping */ { + recvAskInfo(inf); + nhandled++; + delete item; + } + else if (NULL != (dta = dynamic_cast (item))) { + recvHeartbeatMsg(dta); + nhandled++ ; + delete item; + } + else + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::handleIncoming() Unknown Received Message!" << std::endl; + item -> print(std::cerr); + std::cerr << std::endl; +#endif + delete item; + } + } + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::handleIncoming() finished." << std::endl; +#endif + + return nhandled; +} + + + + /************* from pqiMonitor *******************/ +void p3disc::statusChange(const std::list &plist) +{ +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::statusChange()" << std::endl; +#endif + + std::list::const_iterator pit; + /* if any have switched to 'connected' then we notify */ + for(pit = plist.begin(); pit != plist.end(); pit++) + { + if ((pit->state & RS_PEER_S_FRIEND) && (pit->actions & RS_PEER_CONNECTED)) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::statusChange() Starting Disc with: " << pit->id << std::endl; +#endif + sendOwnVersion(pit->id); + sendAllInfoToJustConnectedPeer(pit->id); + sendJustConnectedPeerInfoToAllPeer(pit->id); + } + else if (!(pit->state & RS_PEER_S_FRIEND) && (pit->actions & RS_PEER_MOVED)) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::statusChange() Removing Friend: " << pit->id << std::endl; +#endif + removeFriend(pit->id); + } + else if ((pit->state & RS_PEER_S_FRIEND) && (pit->actions & RS_PEER_NEW)) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::statusChange() Adding Friend: " << pit->id << std::endl; +#endif + askInfoToAllPeers(pit->id); + } + } +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::statusChange() finished." << std::endl; +#endif + return; +} + +void p3disc::sendAllInfoToJustConnectedPeer(const std::string &id) +{ + /* get a peer lists */ + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::sendAllInfoToJustConnectedPeer() id: " << id << std::endl; +#endif + + RsPeerDetails pd; + rsPeers->getPeerDetails(id, pd); + + if (pd.gpg_id != rsPeers->getGPGOwnId() && (!pd.accept_connection || !pd.ownsign) ) + { + //only send info when connection is accepted and gpg key is signed or our own key +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::sendAllInfoToJustConnectedPeer() we're not sending the info because the destination gpg key is not signed or not accepted." << std::cerr << std::endl; +#endif + return; + } + + + std::list friendIds; + std::list::iterator friendIdsIt; + std::set gpgIds; + + rsPeers->getFriendList(friendIds); + + /* send them a list of all friend's details */ + for(friendIdsIt = friendIds.begin(); friendIdsIt != friendIds.end(); friendIdsIt++) { + /* get details */ + peerConnectState detail; + if (!mConnMgr->getFriendNetStatus(*friendIdsIt, detail)) { + /* major error! */ + continue; + } + + if (!(detail.visState & RS_VIS_STATE_NODISC)) { + gpgIds.insert(detail.gpg_id); + } + } + + //add own info + gpgIds.insert(rsPeers->getGPGOwnId()); + + { + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + /* append gpg id's to the sending list for the id */ + + std::list &idList = sendIdList[id]; + + std::set::iterator gpgIdsIt; + for (gpgIdsIt = gpgIds.begin(); gpgIdsIt != gpgIds.end(); gpgIdsIt++) { + if (std::find(idList.begin(), idList.end(), *gpgIdsIt) == idList.end()) { + idList.push_back(*gpgIdsIt); + } + } + } + + #ifdef P3DISC_DEBUG + std::cerr << "p3disc::sendAllInfoToJustConnectedPeer() finished." << std::endl; + #endif +} + +void p3disc::sendJustConnectedPeerInfoToAllPeer(const std::string &connectedPeerId) +{ + /* get a peer lists */ + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::sendJustConnectedPeerInfoToAllPeer() connectedPeerId : " << connectedPeerId << std::endl; +#endif + std::string gpg_connectedPeerId = rsPeers->getGPGId(connectedPeerId); + std::list onlineIds; + + rsPeers->getOnlineList(onlineIds); + + { + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + /* append gpg id's of all friend's to the sending list */ + + std::list::iterator onlineIdsIt; + for (onlineIdsIt = onlineIds.begin(); onlineIdsIt != onlineIds.end(); onlineIdsIt++) { + std::list &idList = sendIdList[*onlineIdsIt]; + if (std::find(idList.begin(), idList.end(), gpg_connectedPeerId) == idList.end()) { + idList.push_back(gpg_connectedPeerId); + } + } + } +} + + /* (dest (to), source (cert)) */ +RsDiscReply *p3disc::createDiscReply(const std::string &to, const std::string &about) +{ +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::createDiscReply() called. Sending details of: " << about << " to: " << to << std::endl; +#endif + + RsPeerDetails pd; + rsPeers->getPeerDetails(to, pd); + if (pd.gpg_id != rsPeers->getGPGOwnId() && (!pd.accept_connection || !pd.ownsign) ) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::createDiscReply() we're not sending the info because the destination gpg key is not signed or not accepted." << std::cerr << std::endl; +#endif + return NULL; + } + + + // if off discard item. + peerConnectState detail; + if (!mConnMgr->getOwnNetStatus(detail) || (detail.visState & RS_VIS_STATE_NODISC)) { + return NULL; + } + + std::string aboutGpgId = rsPeers->getGPGId(about); + if (aboutGpgId.empty()) { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::createDiscReply() no info about this id" << std::endl; +#endif + return NULL; + } + + // Construct a message + RsDiscReply *di = new RsDiscReply(); + + // Fill the message + // Set Target as input cert. + di -> PeerId(to); + di -> aboutId = aboutGpgId; + + // set the ip addresse list. + std::list sslChilds; + rsPeers->getSSLChildListOfGPGId(aboutGpgId, sslChilds); + bool shouldWeSendGPGKey = false;//the GPG key is send only if we've got a valid friend with DISC enabled + + std::list::iterator sslChildIt; + for (sslChildIt = sslChilds.begin(); sslChildIt != sslChilds.end(); sslChildIt++) + if(!rsPeers->isDummyFriend(*sslChildIt)) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::createDiscReply() Found Child SSL Id:" << *sslChildIt; + std::cerr << std::endl; +#endif + if(sslChilds.size() == 1 || to != *sslChildIt) // We don't send info to a peer about itself, when there are more than one ssl children, + { // but we allow sending info about peers with the same GPG id. When there is only one ssl child, + // we must send it to transfer the signers of the gpg key. The receiver is skipping the own id. + peerConnectState detail; + if (!mConnMgr->getFriendNetStatus(*sslChildIt, detail) + || detail.visState & RS_VIS_STATE_NODISC) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::createDiscReply() Skipping cos No Details or NODISC flag"; + std::cerr << std::endl; +#endif + continue; + } + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::createDiscReply() Adding Child SSL Id Details"; + std::cerr << std::endl; +#endif + shouldWeSendGPGKey = true; + RsPeerNetItem rsPeerNetItem ; + rsPeerNetItem.clear(); + + rsPeerNetItem.pid = detail.id; + rsPeerNetItem.gpg_id = detail.gpg_id; + rsPeerNetItem.location = detail.location; + rsPeerNetItem.netMode = detail.netMode; + rsPeerNetItem.visState = detail.visState; + rsPeerNetItem.lastContact = detail.lastcontact; + rsPeerNetItem.currentlocaladdr = detail.currentlocaladdr; + rsPeerNetItem.currentremoteaddr = detail.currentserveraddr; + rsPeerNetItem.dyndns = detail.dyndns; + detail.ipAddrs.mLocal.loadTlv(rsPeerNetItem.localAddrList); + detail.ipAddrs.mExt.loadTlv(rsPeerNetItem.extAddrList); + + + di->rsPeerList.push_back(rsPeerNetItem); + } + else + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::createDiscReply() Skipping cos \"to == sslChildId\""; + std::cerr << std::endl; +#endif + } + } + + + //send own details + if (about == rsPeers->getGPGOwnId()) + { + peerConnectState detail; + if (mConnMgr->getOwnNetStatus(detail)) + { + shouldWeSendGPGKey = true; + RsPeerNetItem rsPeerNetItem ; + rsPeerNetItem.clear(); + rsPeerNetItem.pid = detail.id; + rsPeerNetItem.gpg_id = detail.gpg_id; + rsPeerNetItem.location = detail.location; + rsPeerNetItem.netMode = detail.netMode; + rsPeerNetItem.visState = detail.visState; + rsPeerNetItem.lastContact = time(NULL); + rsPeerNetItem.currentlocaladdr = detail.currentlocaladdr; + rsPeerNetItem.currentremoteaddr = detail.currentserveraddr; + rsPeerNetItem.dyndns = detail.dyndns; + detail.ipAddrs.mLocal.loadTlv(rsPeerNetItem.localAddrList); + detail.ipAddrs.mExt.loadTlv(rsPeerNetItem.extAddrList); + + di->rsPeerList.push_back(rsPeerNetItem); + } + } + + if (!shouldWeSendGPGKey) { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::createDiscReply() GPG key should not be send, no friend with disc on found about it." << std::endl; +#endif + // cleanup! + delete di; + return NULL; + } + + return di; +} + +void p3disc::sendOwnVersion(std::string to) +{ +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::sendOwnVersion() Sending rs version to: " << to << std::endl; +#endif + + RsDiscVersion *di = new RsDiscVersion(); + di->PeerId(to); + di->version = RsUtil::retroshareVersion(); + + /* send the message */ + sendItem(di); + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::sendOwnVersion() finished." << std::endl; +#endif +} + +void p3disc::sendHeartbeat(std::string to) +{ + { +#ifdef P3DISC_DEBUG + std::ostringstream out; + out << "p3disc::sendHeartbeat()"; + out << " Sending tick to : " << to << std::endl; + std::cerr << out.str() << std::endl; +#endif + } + + RsDiscHeartbeat *di = new RsDiscHeartbeat(); + di->PeerId(to); + + /* send the message */ + sendItem(di); + +#ifdef P3DISC_DEBUG + std::cerr << "Sent tick Message" << std::endl; +#endif +} + +void p3disc::askInfoToAllPeers(std::string about) +{ + +#ifdef P3DISC_DEBUG + std::cerr <<"p3disc::askInfoToAllPeers() about " << about << std::endl; +#endif + + + peerConnectState connectState; + if (!mConnMgr->getFriendNetStatus(about, connectState)) // || (connectState.visState & RS_VIS_STATE_NODISC)) { + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::askInfoToAllPeers() friend disc is off, don't send the request." << std::endl; +#endif + return; + } + + std::string aboutGpgId = rsPeers->getGPGId(about); + if (aboutGpgId == "") { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::askInfoToAllPeers() no gpg id found" << std::endl; +#endif + } + + // if off discard item. + if (!mConnMgr->getOwnNetStatus(connectState) || (connectState.visState & RS_VIS_STATE_NODISC)) { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::askInfoToAllPeers() no gpg id found" << std::endl; +#endif + return; + } + + std::list onlineIds; + std::list::iterator onlineIdsIt; + + rsPeers->getOnlineList(onlineIds); + + /* ask info to trusted friends */ + for(onlineIdsIt = onlineIds.begin(); onlineIdsIt != onlineIds.end(); onlineIdsIt++) + { + RsPeerDetails details; + rsPeers->getPeerDetails(*onlineIdsIt, details); + if (!details.accept_connection || !details.ownsign) + { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::askInfoToAllPeers() don't ask info message to untrusted peer." << std::endl; +#endif + continue; + } + RsDiscAskInfo *di = new RsDiscAskInfo(); + di->PeerId(*onlineIdsIt); + di->gpg_id = about; + sendItem(di); +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::askInfoToAllPeers() question sent to : " << *onlineIdsIt << std::endl; +#endif + } +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::askInfoToAllPeers() finished." << std::endl; +#endif +} + +void p3disc::recvPeerDetails(RsDiscReply *item, const std::string &certGpgId) +{ + // discovery is only disabled for sending, not for receiving. +// // if off discard item. +// peerConnectState detail; +// if (!mConnMgr->getOwnNetStatus(detail) || (detail.visState & RS_VIS_STATE_NODISC)) { +// return; +// } + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::recvPeerFriendMsg() From: " << item->PeerId() << " About " << item->aboutId << std::endl; +#endif + + if (certGpgId.empty()) { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::recvPeerFriendMsg() gpg cert is not good, aborting" << std::endl; +#endif + return; + } + if (item->aboutId == "" || item->aboutId != certGpgId) { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::recvPeerFriendMsg() Error : about id is not the same as gpg id." << std::endl; +#endif + return; + } + + bool should_notify_discovery = false ; + + for (std::list::iterator pitem = item->rsPeerList.begin(); pitem != item->rsPeerList.end(); pitem++) + if(!rsPeers->isDummyFriend(pitem->pid)) + { + bool new_info ; + addDiscoveryData(item->PeerId(), pitem->pid,rsPeers->getGPGId(item->PeerId()),item->aboutId, pitem->currentlocaladdr, pitem->currentremoteaddr, 0, time(NULL),new_info); + + if(new_info) + should_notify_discovery = true ; + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::recvPeerFriendMsg() Peer Config Item:" << std::endl; + + pitem->print(std::cerr, 10); + std::cerr << std::endl; +#endif + if (pitem->pid != rsPeers->getOwnId()) + { + // Apparently, the connect manager won't add a friend if the gpg id is not + // trusted. However, this should be tested here for consistency and security + // in case of modifications in mConnMgr. + // + if(AuthGPG::getAuthGPG()->isGPGAccepted(pitem->gpg_id) || pitem->gpg_id == AuthGPG::getAuthGPG()->getGPGOwnId()) + { + // Add with no disc by default. If friend already exists, it will do nothing + // +#ifdef P3DISC_DEBUG + std::cerr << "--> Adding to friends list " << pitem->pid << " - " << pitem->gpg_id << std::endl; +#endif + mConnMgr->addFriend(pitem->pid, pitem->gpg_id, pitem->netMode, 0, 0); + RsPeerDetails storedDetails; + + // Update if know this peer + if(rsPeers->getPeerDetails(pitem->pid, storedDetails)) + { + // Update if it's fresh info or if it's from the peer itself + // their info is fresher than ours, update ours + // + if(!(storedDetails.state & RS_PEER_CONNECTED)) + { +#ifdef P3DISC_DEBUG + std::cerr << "Friend is not connected -> updating info" << std::endl; + std::cerr << " -> network mode: " << pitem->netMode << std::endl; + std::cerr << " -> location: " << pitem->location << std::endl; +#endif + mConnMgr->setNetworkMode(pitem->pid, pitem->netMode); + } + mConnMgr->setLocation(pitem->pid, pitem->location); + + // The info from the peer itself is ultimately trustable, so we can override some info, + // such as: + // - local and global addresses + // - address list + // + // If we enter here, we're necessarily connected to this peer. + // + if (item->PeerId() == pitem->pid) + { +#ifdef P3DISC_DEBUG + std::cerr << "Info sent by the peer itself -> updating self info:" << std::endl; + std::cerr << " -> current local addr = " << pitem->currentlocaladdr << std::endl; + std::cerr << " -> current remote addr = " << pitem->currentremoteaddr << std::endl; + std::cerr << " -> clearing NODISC flag " << std::endl; +#endif + + // When the peer sends his own list of IPs, the info replaces the existing info, because the + // peer is the primary source of his own IPs. + + mConnMgr->setLocalAddress(pitem->pid, pitem->currentlocaladdr); + mConnMgr->setExtAddress(pitem->pid, pitem->currentremoteaddr); + pitem->visState &= ~RS_VIS_STATE_NODISC ; + mConnMgr->setVisState(pitem->pid, pitem->visState); + } + } + else + { + std::cerr << "p3disc:: ERROR HOW DID WE GET HERE?" << std::endl; + } + + pqiIpAddrSet addrsFromPeer; + addrsFromPeer.mLocal.extractFromTlv(pitem->localAddrList); + addrsFromPeer.mExt.extractFromTlv(pitem->extAddrList); + +#ifdef P3DISC_DEBUG + std::cerr << "Setting address list to peer " << pitem->pid << ", to be:" << std::endl ; + + addrsFromPeer.printAddrs(std::cerr); + std::cerr << std::endl; +#endif + // allways update address list and dns, except if it's ours + if (pitem->dyndns != "") + mConnMgr->setDynDNS(pitem->pid, pitem->dyndns); + + mConnMgr->updateAddressList(pitem->pid, addrsFromPeer); + } +#ifdef P3DISC_DEBUG + else + { + std::cerr << " skipping unknown gpg id " << pitem->gpg_id << std::endl ; + } +#endif + } +#ifdef P3DISC_DEBUG + else + { + std::cerr << "Skipping info about own id " << pitem->pid << std::endl ; + } +#endif + + } + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_NEIGHBOURS, NOTIFY_TYPE_MOD); + + if(should_notify_discovery) + rsicontrol->getNotify().notifyDiscInfoChanged(); + + /* cleanup (handled by caller) */ +} + +void p3disc::recvPeerVersionMsg(RsDiscVersion *item) +{ +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::recvPeerVersionMsg() From: " << item->PeerId(); + std::cerr << std::endl; +#endif + + // dont need protection + versions[item->PeerId()] = item->version; + + return; +} + +void p3disc::recvHeartbeatMsg(RsDiscHeartbeat *item) +{ +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::recvHeartbeatMsg() From: " << item->PeerId(); + std::cerr << std::endl; +#endif + + mPqiPersonGrp->tagHeartbeatRecvd(item->PeerId()); + + return; +} + +void p3disc::recvAskInfo(RsDiscAskInfo *item) { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::recvAskInfo() From: " << item->PeerId(); + std::cerr << std::endl; +#endif + + std::list &idList = sendIdList[item->PeerId()]; + + if (std::find(idList.begin(), idList.end(), item->gpg_id) == idList.end()) { + idList.push_back(item->gpg_id); + } +} + +void p3disc::removeFriend(std::string ssl_id) { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::removeFriend() called for : " << ssl_id << std::endl; +#endif + //if we deleted the gpg_id, don't store the friend deletion as if we add back the gpg_id, we won't have the ssl friends back + std::string gpg_id = rsPeers->getGPGId(ssl_id); +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::removeFriend() gpg_id : " << gpg_id << std::endl; +#endif + if (gpg_id == AuthGPG::getAuthGPG()->getGPGOwnId() || rsPeers->isGPGAccepted(rsPeers->getGPGId(ssl_id))) { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::removeFriend() storing the friend deletion." << ssl_id << std::endl; +#endif + deletedSSLFriendsIds[ssl_id] = time(NULL);//just keep track of the deleted time + IndicateConfigChanged(); + } +} + +/*************************************************************************************/ +/* AuthGPGService */ +/*************************************************************************************/ +AuthGPGOperation *p3disc::getGPGOperation() +{ + { + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + /* process disc reply in list */ + if (pendingDiscReplyInList.empty() == false) { + RsDiscReply *item = pendingDiscReplyInList.front(); + + return new AuthGPGOperationLoadOrSave(true, item->certGPG, item); + } + } + + /* process disc reply out list */ + + std::string destId; + std::string srcId; + + { + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + while (!sendIdList.empty()) { + std::map >::iterator sendIdIt = sendIdList.begin(); + + if (!sendIdIt->second.empty() && mConnMgr->isOnline(sendIdIt->first)) { + std::string gpgId = sendIdIt->second.front(); + sendIdIt->second.pop_front(); + + destId = sendIdIt->first; + srcId = gpgId; + + break; + } else { + /* peer is not online anymore ... try next */ + sendIdList.erase(sendIdIt); + } + } + } + + if (!destId.empty() && !srcId.empty()) { + RsDiscReply *item = createDiscReply(destId, srcId); + if (item) { + return new AuthGPGOperationLoadOrSave(false, item->aboutId, item); + } + } + + return NULL; +} + +void p3disc::setGPGOperation(AuthGPGOperation *operation) +{ + AuthGPGOperationLoadOrSave *loadOrSave = dynamic_cast(operation); + if (loadOrSave) { + if (loadOrSave->m_load) { + /* search in pending in list */ + RsDiscReply *item = NULL; + + { + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + std::list::iterator it = std::find(pendingDiscReplyInList.begin(), pendingDiscReplyInList.end(), loadOrSave->m_userdata); + if (it != pendingDiscReplyInList.end()) { + item = *it; + pendingDiscReplyInList.erase(it); + } + } + + if (item) { + recvPeerDetails(item, loadOrSave->m_certGpgId); + delete item; + } + } else { + RsDiscReply *item = (RsDiscReply*) loadOrSave->m_userdata; + + if (item) { + if (loadOrSave->m_certGpg.empty()) { +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::setGPGOperation() don't send details because the gpg cert is not good" << std::endl; +#endif + delete item; + return; + } + + // Send off message + item->certGPG = loadOrSave->m_certGpg; + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::setGPGOperation() About to Send Message:" << std::endl; + item->print(std::cerr, 5); +#endif + + sendItem(item); + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::cbkGPGOperationSave() discovery reply sent." << std::endl; +#endif + } + } + return; + } + + /* ignore other operations */ +} + +/*************************************************************************************/ +/* Storing Network Graph */ +/*************************************************************************************/ +int p3disc::addDiscoveryData(const std::string& fromId, const std::string& aboutId,const std::string& from_gpg_id,const std::string& about_gpg_id, const struct sockaddr_in& laddr, const struct sockaddr_in& raddr, uint32_t flags, time_t ts,bool& new_info) +{ + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + new_info = false ; + + gpg_neighbors[from_gpg_id].insert(about_gpg_id) ; + +#ifdef P3DISC_DEBUG + std::cerr << "Adding discovery data " << fromId << " - " << aboutId << std::endl ; +#endif + /* Store Network information */ + std::map::iterator it; + if (neighbours.end() == (it = neighbours.find(aboutId))) + { + /* doesn't exist */ + autoneighbour an; + + /* an data */ + an.id = aboutId; + an.validAddrs = false; + an.discFlags = 0; + an.ts = 0; + + neighbours[aboutId] = an; + + it = neighbours.find(aboutId); + new_info = true ; + } + + /* it always valid */ + + /* just update packet */ + + autoserver as; + + as.id = fromId; + as.localAddr = laddr; + as.remoteAddr = raddr; + as.discFlags = flags; + as.ts = ts; + + bool authDetails = (as.id == it->second.id); + + /* KEY decision about address */ + if ((authDetails) || + ((!(it->second.authoritative)) && (as.ts > it->second.ts))) + { + /* copy details to an */ + it->second.authoritative = authDetails; + it->second.ts = as.ts; + it->second.validAddrs = true; + it->second.localAddr = as.localAddr; + it->second.remoteAddr = as.remoteAddr; + it->second.discFlags = as.discFlags; + } + + if(it->second.neighbour_of.find(fromId) == it->second.neighbour_of.end()) + { + (it->second).neighbour_of[fromId] = as; + new_info =true ; + } + + /* do we update network address info??? */ + return 1; + +} + + + +/*************************************************************************************/ +/* Extracting Network Graph Details */ +/*************************************************************************************/ +bool p3disc::potentialproxies(const std::string& id, std::list &proxyIds) +{ + /* find id -> and extract the neighbour_of ids */ + + if(id == rsPeers->getOwnId()) // SSL id // This is treated appart, because otherwise we don't receive any disc info about us + return rsPeers->getFriendList(proxyIds) ; + + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it; + std::map::iterator sit; + if (neighbours.end() == (it = neighbours.find(id))) + { + return false; + } + + for(sit = it->second.neighbour_of.begin(); sit != it->second.neighbour_of.end(); sit++) + { + proxyIds.push_back(sit->first); + } + return true; +} +bool p3disc::potentialGPGproxies(const std::string& gpg_id, std::list &proxyGPGIds) +{ + /* find id -> and extract the neighbour_of ids */ + + if(gpg_id == rsPeers->getGPGOwnId()) // SSL id // This is treated appart, because otherwise we don't receive any disc info about us + return rsPeers->getGPGAcceptedList(proxyGPGIds) ; + + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + std::map >::iterator it = gpg_neighbors.find(gpg_id) ; + + if(it == gpg_neighbors.end()) + return false; + + for(std::set::const_iterator sit(it->second.begin()); sit != it->second.end(); ++sit) + proxyGPGIds.push_back(*sit); + + return true; +} + +void p3disc::getversions(std::map &versions) +{ + versions = this->versions; +} + +void p3disc::getWaitingDiscCount(unsigned int *sendCount, unsigned int *recvCount) +{ + if (sendCount == NULL && recvCount == NULL) { + /* Nothing to do */ + return; + } + + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + if (sendCount) { + *sendCount = 0; + + std::map >::iterator it; + for (it = sendIdList.begin(); it != sendIdList.end(); it++) { + *sendCount += it->second.size(); + } + } + + if (recvCount) { + *recvCount = pendingDiscReplyInList.size(); + } +} + +int p3disc::idServers() +{ + RsStackMutex stack(mDiscMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator nit; + std::map::iterator sit; + int cts = time(NULL); + + std::ostringstream out; + out << "::::AutoDiscovery Neighbours::::" << std::endl; + for(nit = neighbours.begin(); nit != neighbours.end(); nit++) + { + out << "Neighbour: " << (nit->second).id; + out << std::endl; + out << "-> LocalAddr: "; + out << rs_inet_ntoa(nit->second.localAddr.sin_addr); + out << ":" << ntohs(nit->second.localAddr.sin_port) << std::endl; + out << "-> RemoteAddr: "; + out << rs_inet_ntoa(nit->second.remoteAddr.sin_addr); + out << ":" << ntohs(nit->second.remoteAddr.sin_port) << std::endl; + out << " Last Contact: "; + out << cts - (nit->second.ts) << " sec ago"; + out << std::endl; + + out << " -->DiscFlags: 0x" << std::hex << nit->second.discFlags; + out << std::dec << std::endl; + + for(sit = (nit->second.neighbour_of).begin(); + sit != (nit->second.neighbour_of).end(); sit++) + { + out << "\tConnected via: " << (sit->first); + out << std::endl; + out << "\t\tLocalAddr: "; + out << rs_inet_ntoa(sit->second.localAddr.sin_addr); + out <<":"<< ntohs(sit->second.localAddr.sin_port); + out << std::endl; + out << "\t\tRemoteAddr: "; + out << rs_inet_ntoa(sit->second.remoteAddr.sin_addr); + out <<":"<< ntohs(sit->second.remoteAddr.sin_port); + + out << std::endl; + out << "\t\tLast Contact:"; + out << cts - (sit->second.ts) << " sec ago"; + out << std::endl; + out << "\t\tDiscFlags: 0x" << std::hex << (sit->second.discFlags); + out << std::dec << std::endl; + } + } + +#ifdef P3DISC_DEBUG + std::cerr << "p3disc::idServers()" << std::endl; + std::cerr << out.str(); + std::cerr << std::endl; +#endif + + return 1; +} + + +// tdelta -> trange. +// -inf...<0 0 (invalid) +// 0.. <9 1 +// 9...<99 2 +// 99...<999 3 +// 999...<9999 4 +// etc... + +//int convertTDeltaToTRange(double tdelta) +//{ +// if (tdelta < 0) +// return 0; +// int trange = 1 + (int) log10(tdelta + 1.0); +// return trange; +// +//} + +// trange -> tdelta +// -inf...0 -1 (invalid) +// 1 8 +// 2 98 +// 3 998 +// 4 9998 +// etc... + +//int convertTRangeToTDelta(int trange) +//{ +// if (trange <= 0) +// return -1; +// +// return (int) (pow(10.0, trange) - 1.5); // (int) xxx98.5 -> xxx98 +//} + +// -----------------------------------------------------------------------------------// +// -------------------------------- Config functions ------------------------------ // +// -----------------------------------------------------------------------------------// +// +RsSerialiser *p3disc::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser ; + rss->addSerialType(new RsGeneralConfigSerialiser()); + return rss ; +} + +bool p3disc::saveList(bool& cleanup, std::list& lst) +{ + #ifdef P3DISC_DEBUG + std::cerr << "p3disc::saveList() called" << std::endl; + #endif + cleanup = true ; + + + // Now save config for network digging strategies + RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; + std::map::iterator mapIt; + for (mapIt = deletedSSLFriendsIds.begin(); mapIt != deletedSSLFriendsIds.end(); mapIt++) { + RsTlvKeyValue kv; + kv.key = mapIt->first; + std::ostringstream time_string; + time_string << mapIt->second; + kv.value = time_string.str(); + vitem->tlvkvs.pairs.push_back(kv) ; + #ifdef P3DISC_DEBUG + std::cerr << "p3disc::saveList() saving : " << mapIt->first << " ; " << mapIt->second << std::endl ; + #endif + } + lst.push_back(vitem); + + return true ; +} + +bool p3disc::loadList(std::list& load) +{ + #ifdef P3DISC_DEBUG + std::cerr << "p3disc::loadList() Item Count: " << load.size() << std::endl; + #endif + + RsStackMutex stack(mDiscMtx); /****** STACK LOCK MUTEX *******/ + + /* load the list of accepted gpg keys */ + std::list::iterator it; + for(it = load.begin(); it != load.end(); it++) { + RsConfigKeyValueSet *vitem = dynamic_cast(*it); + + if(vitem) { + #ifdef P3DISC_DEBUG + std::cerr << "p3disc::loadList() General Variable Config Item:" << std::endl; + vitem->print(std::cerr, 10); + std::cerr << std::endl; + #endif + + std::list::iterator kit; + for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); kit++) { + std::istringstream instream(kit->value); + time_t deleted_time_t; + instream >> deleted_time_t; + deletedSSLFriendsIds[kit->key] = deleted_time_t; + } + } + delete (*it); + } + return true; +} diff --git a/libretroshare/src/services/p3disc.h b/libretroshare/src/services/p3disc.h new file mode 100644 index 000000000..defda57ce --- /dev/null +++ b/libretroshare/src/services/p3disc.h @@ -0,0 +1,167 @@ +/* + * libretroshare/src/services: p3disc.h + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_PQI_AUTODISC_H +#define MRK_PQI_AUTODISC_H + +// The AutoDiscovery Class + +#include +#include + +// system specific network headers +#include "pqi/pqinetwork.h" + +#include "pqi/pqi.h" +#include "pqi/pqipersongrp.h" + +class p3ConnectMgr; + +#include "pqi/pqimonitor.h" +#include "serialiser/rsdiscitems.h" +#include "services/p3service.h" +#include "pqi/authgpg.h" + +class autoserver +{ + public: + autoserver() + :ts(0), discFlags(0) { return;} + + std::string id; + struct sockaddr_in localAddr; + struct sockaddr_in remoteAddr; + + time_t ts; + uint32_t discFlags; +}; + + +class autoneighbour: public autoserver +{ + public: + autoneighbour() + :autoserver(), authoritative(false) {} + + bool authoritative; + bool validAddrs; + + std::map neighbour_of; + +}; + +class p3ConnectMgr; + + +class p3disc: public p3Service, public pqiMonitor, public p3Config, public AuthGPGService +{ + public: + + + p3disc(p3ConnectMgr *cm, pqipersongrp *persGrp); + + /************* from pqiMonitor *******************/ +virtual void statusChange(const std::list &plist); + /************* from pqiMonitor *******************/ + +int tick(); + + /* GUI requires access */ +bool potentialGPGproxies(const std::string& id, std::list &proxyGPGIds); +bool potentialproxies(const std::string& id, std::list &proxyIds); +void getversions(std::map &versions); +void getWaitingDiscCount(unsigned int *sendCount, unsigned int *recvCount); + + /************* from AuthGPService ****************/ +virtual AuthGPGOperation *getGPGOperation(); +virtual void setGPGOperation(AuthGPGOperation *operation); + + protected: +/*****************************************************************/ +/*********************** p3config ******************************/ +/* Key Functions to be overloaded for Full Configuration */ +virtual RsSerialiser *setupSerialiser(); +virtual bool saveList(bool &cleanup, std::list&); +virtual bool loadList(std::list& load); +/*****************************************************************/ + + private: + + +void sendAllInfoToJustConnectedPeer(const std::string &id); +void sendJustConnectedPeerInfoToAllPeer(const std::string &id); + + /* Network Output */ +//void sendOwnDetails(std::string to); +void sendOwnVersion(std::string to); +RsDiscReply *createDiscReply(const std::string &to, const std::string &about); +//void sendPeerIssuer(std::string to, std::string about); +void sendHeartbeat(std::string to); +void askInfoToAllPeers(std::string about); + + /* Network Input */ +int handleIncoming(); +void recvAskInfo(RsDiscAskInfo *item); +void recvPeerDetails(RsDiscReply *item, const std::string &certGpgId); +//void recvPeerIssuerMsg(RsDiscIssuer *item); +void recvPeerVersionMsg(RsDiscVersion *item); +void recvHeartbeatMsg(RsDiscHeartbeat *item); + +void removeFriend(std::string ssl_id); //keep tracks of removed friend so we're not gonna add them again immediately + +/* handle network shape */ +int addDiscoveryData(const std::string& fromId, const std::string& aboutId, + const std::string& fromGPGId,const std::string& aboutGPGId, + const struct sockaddr_in& laddr, const struct sockaddr_in& raddr, + uint32_t flags, time_t ts,bool& new_info); + +int idServers(); + + private: + + p3ConnectMgr *mConnMgr; + pqipersongrp *mPqiPersonGrp; + time_t lastSentHeartbeatTime; + + /* data */ + RsMutex mDiscMtx; + + std::map deletedSSLFriendsIds; + + std::map neighbours; + std::map versions; + + std::map > sendIdList; + std::list pendingDiscReplyInList; + + // Neighbors at the gpg level. + // + std::map > gpg_neighbors ; +}; + + + + +#endif // MRK_PQI_AUTODISC_H diff --git a/libretroshare/src/services/p3distrib.cc b/libretroshare/src/services/p3distrib.cc new file mode 100644 index 000000000..16877ecf1 --- /dev/null +++ b/libretroshare/src/services/p3distrib.cc @@ -0,0 +1,5168 @@ +/* + * libretroshare/src/services: p3distrib.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "retroshare/rsdistrib.h" +#include "services/p3distrib.h" +#include "serialiser/rsdistribitems.h" +#include "serialiser/rstlvkeys.h" + +#include "util/rsdir.h" +#include "pqi/pqinotify.h" +#include "pqi/pqibin.h" +#include "pqi/sslfns.h" +#include "pqi/authssl.h" +#include "pqi/authgpg.h" + +#define FAILED_CACHE_CONT "failedcachegrp" // cache id which have failed are stored under a node of this name/grpid +#define HIST_CACHE_FNAME "grp_history.xml" + +/*** + * #define ENABLE_CACHE_OPT 1 + ***/ + +/***** + * #define DISTRIB_DEBUG 1 + * #define DISTRIB_THREAD_DEBUG 1 + * #define DISTRIB_DUMMYMSG_DEBUG 1 + ****/ + +//#define DISTRIB_DEBUG 1 +//#define DISTRIB_THREAD_DEBUG 1 +//#define DISTRIB_DUMMYMSG_DEBUG 1 + + +RSA *extractPublicKey(RsTlvSecurityKey &key); +RSA *extractPrivateKey(RsTlvSecurityKey &key); +void setRSAPublicKey(RsTlvSecurityKey &key, RSA *rsa_pub); +void setRSAPrivateKey(RsTlvSecurityKey &key, RSA *rsa_priv); + +// add one set to another while not replacing elements unique to left operand +void operator+=(std::set& left, const std::set& right){ + + std::set::const_iterator sit = right.begin(); + + for(; sit != right.end(); sit++) + left.insert(*sit); + + return; +} + + +GroupInfo::~GroupInfo() +{ + delete distribGroup ; + + for(std::map::const_iterator it(msgs.begin());it!=msgs.end();++it) + delete it->second ; + + for(std::map::const_iterator it(decrypted_msg_cache.begin());it!=decrypted_msg_cache.end();++it) + delete it->second ; +} + +p3GroupDistrib::p3GroupDistrib(uint16_t subtype, + CacheStrapper *cs, CacheTransfer *cft, + std::string sourcedir, std::string storedir, + std::string keyBackUpDir, uint32_t configId, + uint32_t storePeriod, uint32_t pubPeriod) + + :CacheSource(subtype, true, cs, sourcedir), + CacheStore(subtype, true, cs, cft, storedir), + p3Config(configId), p3ThreadedService(subtype), + mHistoricalCaches(true), + mStorePeriod(storePeriod), + mPubPeriod(pubPeriod), + mLastPublishTime(0), + mMaxCacheSubId(1), + mKeyBackUpDir(keyBackUpDir), BACKUP_KEY_FILE("key.log"), mLastKeyPublishTime(0), mLastRecvdKeyTime(0) +{ + /* force publication of groups (cleared if local cache file found) */ + mGroupsRepublish = true; + mGroupsChanged = true; + mCount = 0; + mLastCacheDocUpdate = time(NULL); + mHistoricalCachesLoaded = false; + + mOwnId = AuthSSL::getAuthSSL()->OwnId(); + + addSerialType(new RsDistribSerialiser(getRsItemService(getType()))); + return; +} + +p3GroupDistrib::~p3GroupDistrib() +{ + for(std::map::iterator it(mRecvdPubKeys.begin());it!=mRecvdPubKeys.end();++it) + delete it->second ; + + for(std::list::iterator it(mPendingPublish.begin());it!=mPendingPublish.end();++it) + delete *it ; +} + +int p3GroupDistrib::tick() +{ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::tick()"; + std::cerr << std::endl; +#endif + + time_t now = time(NULL); + bool toPublish; + + { + RsStackMutex stack(distribMtx); /**** STACK LOCKED MUTEX ****/ + + toPublish = ((mPendingPublish.size() > 0) || (mPendingPubKeyRecipients.size() > 0)) && (now > (time_t) (mPubPeriod + mLastPublishTime)); + } + + if (toPublish) + { + RsStackMutex stack(distribMtx); /**** STACK LOCKED MUTEX ****/ + + locked_publishPendingMsgs(); /* flags taken care of in here */ + } + + bool toPublishGroups; + { + RsStackMutex stack(distribMtx); /**** STACK LOCKED MUTEX ****/ + toPublishGroups = mGroupsRepublish; + } + + if (toPublishGroups) + { + publishDistribGroups(); + + IndicateConfigChanged(); /**** INDICATE CONFIG CHANGED! *****/ + + RsStackMutex stack(distribMtx); /**** STACK LOCKED MUTEX ****/ + mGroupsRepublish = false; + } + + bool attemptRecv = false; + + { + RsStackMutex stack(distribMtx); + toPublish = (mPendingPubKeyRecipients.size() > 0) && (now > (time_t) (mPubPeriod + mLastKeyPublishTime)); + attemptRecv = (mRecvdPubKeys.size() > 0); // attempt to load stored keys in case user has subscribed + } + + if(toPublish){ + RsStackMutex stack(distribMtx); + locked_sharePubKey(); + } + + + if(attemptRecv) + { + attemptPublishKeysRecvd(); + } + + bool toReceive = receivedItems(); + + if(toReceive){ + + receivePubKeys(); + } + + // update cache document every 1 minute (5 mins in production) + // after historical files have loaded and there is reason to + bool updateCacheDoc = false; + { + RsStackMutex stack(distribMtx); + updateCacheDoc = (now > (time_t) (mLastCacheDocUpdate + 30)); + updateCacheDoc &= !mHistoricalCaches && mUpdateCacheDoc && mHistoricalCachesLoaded; +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "num pending grps: " << mGrpHistPending.size() << std::endl; + std::cerr << "num pending msgs: " << mMsgHistPending.size() << std::endl; + std::cerr << "num unique cache ids in table: " << mCachePairsInTable.size() << std::endl; +#endif + } + +#ifdef ENABLE_CACHE_OPT + if(updateCacheDoc){ + std::cerr << "count: " << mCount << std::endl; + updateCacheDocument(); + + } +#endif + + return 0; +} + + +/***************************************************************************************/ +/***************************************************************************************/ + /********************** overloaded functions from Cache Store ******************/ +/***************************************************************************************/ +/***************************************************************************************/ + +int p3GroupDistrib::loadCache(const CacheData &data) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadCache()"; + std::cerr << std::endl; +#endif + + if(mHistoricalCaches) + { + RsStackMutex stack(distribMtx); +#ifdef DISTRIB_THREAD_DEBUG + std::cerr << "p3GroupDistrib::loadCache() Storing historical PendingRemoteCache"; + std::cerr << std::endl; +#endif + /* store the cache file for later processing */ + mPendingHistCaches.push_back(CacheDataPending(data, false, true)); + }else + { +#ifdef DISTRIB_THREAD_DEBUG + std::cerr << "p3GroupDistrib::loadCache() Storing non historical PendingRemoteCache"; + std::cerr << std::endl; +#endif + mPendingCaches.push_back(CacheDataPending(data, false, false)); + } + + if (data.size > 0) + { + CacheStore::lockData(); /***** LOCK ****/ + locked_storeCacheEntry(data); + CacheStore::unlockData(); /***** UNLOCK ****/ + } + + return 1; +} + +bool p3GroupDistrib::loadLocalCache(const CacheData &data) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadLocalCache()"; + std::cerr << std::endl; +#endif + + if(mHistoricalCaches) + { + RsStackMutex stack(distribMtx); + mPendingHistCaches.push_back(CacheDataPending(data, true, true)); + + } + else + { + RsStackMutex stack(distribMtx); + +#ifdef DISTRIB_THREAD_DEBUG + std::cerr << "p3GroupDistrib::loadCache() Storing PendingLocalCache"; + std::cerr << std::endl; +#endif + + /* store the cache file for later processing */ + mPendingCaches.push_back(CacheDataPending(data, true, false)); + } + + if (data.size > 0) + { + refreshCache(data); + } + + return true; +} + + + +void p3GroupDistrib::updateCacheDocument() +{ + + RsStackMutex stack(distribMtx); + +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::updateCacheDocument() " + << mGrpHistPending.size() << " Grps" + << std::endl; +#endif + + std::vector grpNodes; + std::string failedCacheId = FAILED_CACHE_CONT; + + // failed cache content node is has not been created add to doc + if(mCacheTable.find(failedCacheId) == mCacheTable.end()){ + + mCacheDoc.append_child("group"); + mCacheDoc.last_child().append_child("grpId").append_child( + pugi::node_pcdata).set_value(failedCacheId.c_str()); + + grpNodes.push_back(grpNodePair(failedCacheId, mCacheDoc.last_child())); + } + + std::map::iterator nodeCache_iter; + + // for transforming int to string + std::string subId; + char subIdBuffer[6]; + + std::vector::iterator grpIt = + mGrpHistPending.begin(), msgIt = mMsgHistPending.begin(); + + /* + * add pending recvd msgs and grps to cache table + */ + + for(; grpIt != mGrpHistPending.end(); grpIt++){ + + + // make sure grp does not exist + nodeCache_iter = mCacheTable.find(grpIt->first); + + if(nodeCache_iter == mCacheTable.end()){ + + // add group node + mCacheDoc.append_child("group"); + + /*** adding grp id ***/ + + mCacheDoc.last_child().append_child("grpId").append_child( + pugi::node_pcdata).set_value(grpIt->first.c_str()); + + /*** adding cache id ***/ + + // add pid + mCacheDoc.last_child().append_child("pId").append_child( + pugi::node_pcdata).set_value(grpIt->second.first + .c_str()); + + // apparently portable int to string method + sprintf(subIdBuffer, "%d", grpIt->second.second); + subId = subIdBuffer; + mCacheDoc.last_child().append_child("subId").append_child( + pugi::node_pcdata).set_value(subId.c_str()); + + grpNodes.push_back(grpNodePair(grpIt->first, mCacheDoc.last_child())); + + } + else + { +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::updateCacheDocument()" + << "\nGrp already Exists in Document!"; +#endif + } + } + + mGrpHistPending.clear(); + + // add groups to cache table + locked_updateCacheTableGrp(grpNodes, false); + //grpNodeIter.clear(); + + std::map > msgCacheMap; + pugi::xml_node nodeIter; + + // create entry for all grps with empty sets + for(; msgIt != mMsgHistPending.end(); msgIt++) + { + msgCacheMap.insert(std::make_pair(msgIt->first, std::set())); + } + + // now update document with new msg cache info + msgIt = mMsgHistPending.begin(); + std::vector msgHistRestart; + pugi::xml_node messages_node; + pCacheId pCid; + + int count = 0; +// int count2 = 0, count3 = 0; + + for(; msgIt != mMsgHistPending.end(); msgIt++) + { + + // find grp in cache document + nodeCache_iter = mCacheTable.find(msgIt->first); + + if(nodeCache_iter != mCacheTable.end()){ + + pCid = pCacheId(msgIt->second.first, + msgIt->second.second); + + // ensure you don't add cache ids twice to same group +// // by checking cache table and current msg additions +// if(nodeCache_iter->second.cIdSet.find(pCid) != +// nodeCache_iter->second.cIdSet.end()) +// count2++; +// +// if(msgCacheMap[msgIt->first].find(pCid) != msgCacheMap[msgIt->first].end()) +// count3++; + + + + nodeIter = nodeCache_iter->second.node; + messages_node = nodeIter.child("messages"); + + // if messages child does not exist, add one + if(!messages_node) + messages_node = nodeIter.append_child("messages"); + + messages_node.append_child("msg"); + + // add cache id + messages_node.last_child().append_child("pId").append_child( + pugi::node_pcdata).set_value(msgIt->second.first + .c_str()); + sprintf(subIdBuffer, "%d", msgIt->second.second); + subId = subIdBuffer; + messages_node.last_child().append_child("subId").append_child( + pugi::node_pcdata).set_value(subId.c_str()); + + // add msg to grp set + msgCacheMap[msgIt->first].insert(pCid); + count++; + + } + else{ +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::updateCacheDocument()" + << "\nUpdating Cache with Msgs" + << "\nBut Parent group does not exists in cache table!" + << std::endl; +#endif + // remove from map but keep for later in case historical grp loads aren't done yet + msgCacheMap.erase(msgIt->first); + msgHistRestart.push_back(*msgIt); + } + } + + + + // now update cache table by tagging msg cache ids to their + // respective groups + locked_updateCacheTableMsg(msgCacheMap); + + // clear msg pending if all pending historical grps have been loaded + if(mHistoricalCachesLoaded && (mGrpHistPending.size() == 0)){ + +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "mMsgHistRestart() " << msgHistRestart.size() << std::endl; + std::cerr << "mMsgHistPending() " << mMsgHistPending.size() << std::endl; + std::cerr << "count: " << count << " " << count2 << " " << count3 << std::endl; +#endif + + mMsgHistPending.clear(); + } + else // if not keep the messages for next round of loads + { + mMsgHistPending.clear(); + mMsgHistPending = msgHistRestart; + } + + // indicate latest update to reset tick observer + mLastCacheDocUpdate = time(NULL); + mUpdateCacheDoc = false; + IndicateConfigChanged(); + + return; +} + +void p3GroupDistrib::locked_updateCacheTableGrp(const std::vector& grpNodes, bool historical) +{ + +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::locked_updateCacheTableGrp " + << std::endl; +#endif + + std::vector::const_iterator gnpIter = grpNodes.begin(); + nodeCache nCache; + + for(; gnpIter != grpNodes.end(); gnpIter++) + { + nCache.cached = !historical; + nCache.node = gnpIter->second; + mCacheTable.insert(std::make_pair(gnpIter->first, nCache)); + } + + return; +} + +void p3GroupDistrib::locked_updateCacheTableMsg(const std::map >& msgCacheMap) +{ + +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::locked_updateCacheTableMsg() " + << "loading " << msgCacheMap.size() << " messages" + << std::endl; +#endif + + if(msgCacheMap.empty()){ +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::locked_updateCacheTableMsg() " + << "\nMsg map is empty." << std::endl; +#endif + return; + } + + std::map >::const_iterator mit = msgCacheMap.begin(); + std::map::iterator cit; + + for(; mit != msgCacheMap.end(); mit++) + { + cit = mCacheTable.find(mit->first); + +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::locked_updateCacheTableMsg() " + << "\nAdding." << mit->second.size() << "to grp " + << mit->first << std::endl; +#endif + // add new cache ids to grp + if(cit != mCacheTable.end()){ + cit->second.cIdSet += mit->second; + + // don't add failed caches to cache pairs in table + if(mit->first != FAILED_CACHE_CONT) + mCachePairsInTable += mit->second; + else + mCacheFailedTable += mit->second; + + }else{ +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::locked_updateCacheTableMsg() " + << "\nMsg Grp does not Exist." << std::endl; +#endif + } + } + + return; +} + +bool p3GroupDistrib::locked_historyCached(const std::string& grpId, bool& cached) +{ + + std::map::iterator cit; + if(mCacheTable.end() != (cit = mCacheTable.find(grpId))) + { + cached = cit->second.cached; + return true; + } + + cached = false; + return false; +} + +bool p3GroupDistrib::locked_historyCached(const pCacheId& cId) +{ + + if(mCachePairsInTable.find(cId) != mCachePairsInTable.end()) + return true; + + if(mCacheFailedTable.find(cId) != mCacheFailedTable.end()) + return true; + + return false; +} + +bool p3GroupDistrib::locked_buildCacheTable(){ + +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::buildCacheTable()" + << std::endl; +#endif + + if(mCacheDoc.empty()){ +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::buildCacheTable()" + << "\nCache Doc empty" << std::endl; +#endif + return false; + } + + pugi::xml_node_iterator grpIt = mCacheDoc.begin(), msgIt; + pugi::xml_node messages_node; + std::map > msgCacheMap; + + std::vector grpNodes; + + + uint16_t subId = 0; + std::string pId, grpId, subId_str; + + for(; grpIt != mCacheDoc.end(); grpIt++) + { + + grpId = grpIt->child_value("grpId"); + // add grps to grp node list + grpNodes.push_back(grpNodePair(grpId, *grpIt)); + messages_node = grpIt->child("messages"); + + if(messages_node){ + + msgIt = messages_node.begin(); + + // add grp messages to message list + for(; msgIt != messages_node.end(); msgIt++){ + + pId = msgIt->child_value("pId"); + subId_str = msgIt->child_value("subId"); + subId = atoi(subId_str.c_str()); + + if(msgCacheMap.find(grpId) == msgCacheMap.end()){ + + msgCacheMap.insert(std::make_pair(grpId, std::set())); + msgCacheMap[grpId].insert(pCacheId(pId, subId)); + + }else{ + msgCacheMap[grpId].insert(pCacheId(pId, subId)); + } + } + } + else{ +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::buildCacheTable()" + << "\nNo messages for grp " << grpId + << std::endl; +#endif + } + } + + // now create cache table, marking these grp as not hist cache loaded + locked_updateCacheTableGrp(grpNodes, true); + + // add grp messages to table + locked_updateCacheTableMsg(msgCacheMap); + + return true; +} + +void p3GroupDistrib::locked_processHistoryCached(const std::string& grpId) +{ + + // no processing should be done until cache locations have been stored in memory + if(mHistoricalCaches) + return; + +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::locked_processHistoryCached() " + << std::endl; +#endif + + bool cached = true; + locked_historyCached(grpId, cached); + + std::list cDataList; + std::list::iterator cit; + std::string file; + CacheData cDataTemp; + uint16_t cacheType = CacheSource::getCacheType(); + + // if not history cached then load it + if(!cached) + { + // get list of cache id belonging to grp + locked_getHistoryCacheData(grpId, cDataList); + cit = cDataList.begin(); + + for(; cit != cDataList.end(); cit++){ + + cit->cid.type = cacheType; + locked_getStoredCache(*cit); + file = cit->path; + file += "/"; + file += cit->name; + + // note: you could load msgs for a cache historied group that is not loaded, + // but any request for info of affected grp will consequently load + // all its msgs through this function anyways + locked_loadFileMsgs(file, cit->cid.subid, cit->pid, cit->recvd, false, true); + + } + + } + + locked_updateCacheTableEntry(grpId, true); + return; +} + +void p3GroupDistrib::locked_updateCacheTableEntry(const std::string& grpId, bool cached) +{ + + std::map::iterator nit; + nit = mCacheTable.find(grpId); + + if(nit != mCacheTable.end()){ + nit->second.cached = cached; + } + else + { +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::locked_updateCacheTableEntry " + << "\nCannot find Grp " + << grpId + << std::endl; +#endif + return; + } + + return; +} + +void p3GroupDistrib::locked_getHistoryCacheData(const std::string& grpId, std::list& cDataSet) +{ + +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::locked_getHistoryCacheData() " + << std::endl; +#endif + + std::map::iterator nit; + std::set::iterator pit, pitEnd; + CacheData cDataTemp; + + GroupInfo* grpInfo = locked_getGroupInfo(grpId); + std::map::iterator mit; + bool subscribed = grpInfo->flags & RS_DISTRIB_SUBSCRIBED; + + nit = mCacheTable.find(grpId); + + if(nit != mCacheTable.end()){ + + pit = nit->second.cIdSet.begin(); + pitEnd = nit->second.cIdSet.end(); + + for(; pit != pitEnd; pit++){ + + cDataTemp.cid.subid = pit->second; + cDataTemp.pid = pit->first; + + if(subscribed){ + mit = mLocalHistCachesAvail.find(CacheId(CacheSource::getCacheType(), cDataTemp.cid.subid)); + if(mit != mLocalHistCachesAvail.end()) cDataTemp = mit->second; + } + else + locked_getStoredCache(cDataTemp); + + cDataSet.push_back(cDataTemp); + } + } + else + { +#ifdef DISTRIB_HISTORY_DEBUG + std::cerr << "p3GroupDistrib::getHistoryCacheData() " + << "\nCannot find any history cache data for " + << grpId + << std::endl; +#endif + return; + } + + return; +} + + +bool p3GroupDistrib::locked_loadHistoryCacheFile() +{ + std::string hFileName = mKeyBackUpDir + "/" + HIST_CACHE_FNAME; + std::ifstream hFile(hFileName.c_str(), std::ios::binary | std::ios::in); + int fileLength; + char* fileLoadBuffer = NULL; + char* decryptedCacheFile = NULL; + int outlen = 0; + bool ok = false; + hFile.seekg(0, std::ios::end); + fileLength = hFile.tellg(); + hFile.seekg(0, std::ios::beg); + + if(fileLength <= 0) + return false; + + fileLoadBuffer = new char[fileLength]; + hFile.read(fileLoadBuffer, fileLength); + hFile.close(); + + ok = AuthSSL::getAuthSSL()->decrypt((void*&)decryptedCacheFile, outlen, + fileLoadBuffer, fileLength); + + if(fileLoadBuffer != NULL) + delete[] fileLoadBuffer; + + char* buffer = static_cast(pugi::get_memory_allocation_function()(outlen)); + + if(ok){ + + memcpy(buffer, decryptedCacheFile, outlen); + + if(decryptedCacheFile != NULL) + delete[] decryptedCacheFile; + + ok &= mCacheDoc.load_buffer_inplace_own(buffer, outlen); + }else{ + if(buffer !=NULL) + delete[] buffer; + } + + return ok; +} + +bool p3GroupDistrib::locked_saveHistoryCacheFile() +{ + + std::cout << mCacheDoc.last_child().value(); + if(mCacheDoc.empty()) + return false; + + std::string hFileName = mKeyBackUpDir + "/" + HIST_CACHE_FNAME; + std::ofstream hFile(hFileName.c_str(), std::ios::binary | std::ios::out); + std::ostringstream cacheStream; + char* fileBuffer = NULL; + int streamLength; + char* encryptedFileBuffer = NULL; + int outlen = 0; + bool ok = false; + + mCacheDoc.save(cacheStream); + streamLength = cacheStream.str().length(); + std::string cacheContent = cacheStream.str(); + fileBuffer = new char[cacheContent.size()]; + cacheContent.copy(fileBuffer, cacheContent.size(), 0); + + ok = AuthSSL::getAuthSSL()->encrypt((void*&)encryptedFileBuffer, outlen, + (void*&)fileBuffer, streamLength, mOwnId); + + if(ok){ + hFile.write(encryptedFileBuffer, outlen); + hFile.close(); + } + + if(fileBuffer != NULL) + delete[] fileBuffer; + + if(encryptedFileBuffer != NULL) + delete[] encryptedFileBuffer; + + return ok; +} + +/* Handle the Cache Pending Setup */ +CacheDataPending::CacheDataPending(const CacheData &data, bool local, bool historical) + :mData(data), mLocal(local), mHistorical(historical) +{ + return; +} + +void p3GroupDistrib::HistoricalCachesDone() +{ + RsStackMutex stack(distribMtx); + std::string id; + cachesAvailable(id, mLocalHistCachesAvail); + mHistoricalCaches = false; // called when Stored Caches have been added to Pending List. +} + +void p3GroupDistrib::HistoricalCachesLoaded() +{ + RsStackMutex stack(distribMtx); + mHistoricalCachesLoaded = true; +} + + /* From RsThread */ +void p3GroupDistrib::run() /* called once the thread is started */ +{ + +#ifdef DISTRIB_THREAD_DEBUG + std::cerr << "p3GroupDistrib::run()"; + std::cerr << std::endl; +#endif + +#ifdef DISTRIB_DUMMYMSG_DEBUG + int printed = 0; +#endif + CacheData cache; + while(isRunning()) + { + /* */ + + bool validCache = false; + bool isLocal = false; + bool isHistorical = false; + { + RsStackMutex stack(distribMtx); + if(!mHistoricalCaches){ + + + if(mPendingHistCaches.size() > 0){ + +// std::cerr << "loaded pending caches: " << mPendingHistCaches.size() << std::endl; + CacheDataPending &pendingCache = mPendingHistCaches.front(); + cache = pendingCache.mData; + isLocal = pendingCache.mLocal; + isHistorical = pendingCache.mHistorical; + + validCache = true; + mPendingHistCaches.pop_front(); + } + else if (mPendingCaches.size() > 0) + { + CacheDataPending &pendingCache = mPendingCaches.front(); + cache = pendingCache.mData; + isLocal = pendingCache.mLocal; + isHistorical = pendingCache.mHistorical; + + validCache = true; + mPendingCaches.pop_front(); + +#ifdef DISTRIB_THREAD_DEBUG + std::cerr << "p3GroupDistrib::run() found pendingCache"; + std::cerr << std::endl; +#endif + + } + } + } + if (validCache) + { + loadAnyCache(cache, isLocal, isHistorical); + + if(!mHistoricalCachesLoaded){ + if(mPendingHistCaches.size() == 0) + HistoricalCachesLoaded(); + } + +#ifndef WINDOWS_SYS + usleep(1000); +#else + Sleep(1); +#endif + } + else + { +#ifndef WINDOWS_SYS + sleep(1); +#else + Sleep(1000); +#endif + +#ifdef DISTRIB_DUMMYMSG_DEBUG + /* HACK for debugging */ + if (printed < 10) + { + RsStackMutex stack(distribMtx); + locked_printAllDummyMsgs(); + + printed++; + } +#endif + + } + } +} + + + +int p3GroupDistrib::loadAnyCache(const CacheData &data, bool local, bool historical) +{ + /* if subtype = 1 -> FileGroup, else -> FileMsgs */ + + std::string file = data.path; + file += "/"; + file += data.name; + std::pair cidPair; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadAnyCache() file: " << file << std::endl; + std::cerr << "PeerId: " << data.pid << std::endl; + std::cerr << "Cid: " << data.cid.type << ":" << data.cid.subid << std::endl; +#endif + + if (data.cid.subid == 1) + { + cidPair = std::make_pair(data.pid, data.cid.subid); + loadFileGroups(file, data.pid, local, historical, cidPair); + } + else + { + loadFileMsgs(file, data.cid.subid, data.pid, data.recvd, local, historical); + } + + return true; +} + +/***************************************************************************************/ +/***************************************************************************************/ + /********************** load Cache Files ***************************************/ +/***************************************************************************************/ +/***************************************************************************************/ + + +/* No need for special treatment for 'own' groups. + * configuration should be loaded before cache files. + */ +void p3GroupDistrib::loadFileGroups(const std::string &filename, const std::string &src, bool local, bool historical, const pCacheId& cId) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileGroups()"; + std::cerr << std::endl; +#endif + + /* create the serialiser to load info */ + BinInterface *bio = new BinFileInterface(filename.c_str(), BIN_FLAGS_READABLE); + pqistore *store = createStore(bio, src, BIN_FLAGS_READABLE); + grpCachePair gcPair; + +#ifdef DISTRIB_DEBUG + std::cerr << "loading file " << filename << std::endl ; +#endif + + RsItem *item; + RsDistribGrp *newGrp; + RsDistribGrpKey *newKey; + + while(NULL != (item = store->GetItem())) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileGroups() Got Item:"; + std::cerr << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + newKey = dynamic_cast(item); + if ((newGrp = dynamic_cast(item))) + { + + bool cached = false; + if(loadGroup(newGrp, historical)){ + + // if not present in history cache table + // then add to document and update table + RsStackMutex stack(distribMtx); + + if(!locked_historyCached(newGrp->grpId, cached)){ + + gcPair = std::make_pair(newGrp->grpId, cId); + mGrpHistPending.push_back(gcPair); + mUpdateCacheDoc = true; + } + } + } + else if ((newKey = dynamic_cast(item))) + { + loadGroupKey(newKey, historical); + } + else + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileGroups() Unexpected Item - deleting"; + std::cerr << std::endl; +#endif + delete item; + } + } + + delete store; + + + /* clear publication of groups if local cache file found */ + RsStackMutex stack(distribMtx); /******* STACK LOCKED MUTEX ***********/ + if (local) + { + mGroupsRepublish = false; + } + + return; +} + +void p3GroupDistrib::loadFileMsgs(const std::string &filename, uint16_t cacheSubId, const std::string &src, uint32_t ts, bool local, bool historical) +{ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs()"; + std::cerr << std::endl; +#endif + + time_t now = time(NULL); + bool cache = false; + +#ifdef ENABLE_CACHE_OPT + // if cache id exists in cache table exit + { + RsStackMutex stack(distribMtx); + + if(locked_historyCached(pCacheId(src, cacheSubId))){ + return; + } + else + { + cache = true; + } + } +#endif + + // link grp to cache id (only one cache id, so doesn't matter if one grp comes out twice + // with same cache id) + std::map msgCacheMap; + pCacheId failedCache = pCacheId(src, cacheSubId); + /* create the serialiser to load msgs */ + BinInterface *bio = new BinFileInterface(filename.c_str(), BIN_FLAGS_READABLE); + pqistore *store = createStore(bio, src, BIN_FLAGS_READABLE); + +#ifdef DISTRIB_DEBUG + std::cerr << "loading file " << filename << std::endl ; +#endif + + RsItem *item; + RsDistribSignedMsg *newMsg; + std::string grpId; + + while(isRunning() && (NULL != (item = store->GetItem()))) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() Got Item:"; + std::cerr << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + if ((newMsg = dynamic_cast(item))) + { + grpId = newMsg->grpId; + if(loadMsg(newMsg, src, local, historical)) + { + if(cache) + { + msgCacheMap.insert(grpCachePair(grpId, pCacheId(src, cacheSubId))); + } + } + } + else + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() Unexpected Item - deleting"; + std::cerr << std::endl; +#endif + /* wrong message type */ + delete item; + } + } + + std::map::iterator mit; + + if(cache){ + + RsStackMutex stack(distribMtx); + + mit = msgCacheMap.begin(); + for(;mit != msgCacheMap.end(); mit++) + { + mMsgHistPending.push_back(grpCachePair(mit->first, mit->second)); + } + mUpdateCacheDoc = true; + if(!msgCacheMap.empty()) + mCount++; + + std::string failedCacheId = FAILED_CACHE_CONT; + + // if msg cache map is empty then cache id failed + if(msgCacheMap.empty()) + mMsgHistPending.push_back(grpCachePair(failedCacheId, failedCache)); + } + + if (local) + { + /* now we create a map of time -> subid + * This is used to determine the newest and the oldest items + */ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() Updating Local TimeStamps"; + std::cerr << std::endl; + std::cerr << "p3GroupDistrib::loadFileMsgs() CacheSubId: " << cacheSubId << " recvd: " << ts; + std::cerr << std::endl; +#endif + + mLocalCacheTs[ts] = cacheSubId; + if (cacheSubId > mMaxCacheSubId) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() New Max CacheSubId"; + std::cerr << std::endl; +#endif + mMaxCacheSubId = cacheSubId; + } + + if (((time_t) ts < now) && ((time_t) ts > mLastPublishTime)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() New LastPublishTime"; + std::cerr << std::endl; +#endif + mLastPublishTime = ts; + } + } + + delete store; + return; +} + +//TODO make carbon copy of sister +void p3GroupDistrib::locked_loadFileMsgs(const std::string &filename, uint16_t cacheSubId, const std::string &src, uint32_t ts, bool local, bool historical) +{ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs()"; + std::cerr << std::endl; +#endif + + time_t now = time(NULL); + bool cache = false; + +#ifdef ENABLE_CACHE_OPT + // if cache id exists in cache table exit + if(!historical){ + if(locked_historyCached(pCacheId(src, cacheSubId))){ + return; + } + else + { + cache = true; + } + } +#endif + + // link grp to cache id (only one cache id, so doesn't matter if one grp comes out twice + // with same cache id) + std::map msgCacheMap; + pCacheId failedCache = pCacheId(src, cacheSubId); + /* create the serialiser to load msgs */ + BinInterface *bio = new BinFileInterface(filename.c_str(), BIN_FLAGS_READABLE); + pqistore *store = createStore(bio, src, BIN_FLAGS_READABLE); + +#ifdef DISTRIB_DEBUG + std::cerr << "loading file " << filename << std::endl ; +#endif + + RsItem *item; + RsDistribSignedMsg *newMsg; + std::string grpId; + + while(NULL != (item = store->GetItem())) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() Got Item:"; + std::cerr << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + if ((newMsg = dynamic_cast(item))) + { + grpId = newMsg->grpId; + if(locked_loadMsg(newMsg, src, local, historical)) + { + if(cache) + { + msgCacheMap.insert(grpCachePair(grpId, pCacheId(src, cacheSubId))); + } + } + } + else + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() Unexpected Item - deleting"; + std::cerr << std::endl; +#endif + /* wrong message type */ + delete item; + } + } + + std::map::iterator mit; + + if(cache){ + + mit = msgCacheMap.begin(); + for(;mit != msgCacheMap.end(); mit++) + { + mMsgHistPending.push_back(grpCachePair(mit->first, mit->second)); + } + mUpdateCacheDoc = true; + if(!msgCacheMap.empty()) + mCount++; + + std::string failedCacheId = FAILED_CACHE_CONT; + + // if msg cache map is empty then cache id failed + if(msgCacheMap.empty()) + mMsgHistPending.push_back(grpCachePair(failedCacheId, failedCache)); + } + + if (local) + { + /* now we create a map of time -> subid + * This is used to determine the newest and the oldest items + */ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() Updating Local TimeStamps"; + std::cerr << std::endl; + std::cerr << "p3GroupDistrib::loadFileMsgs() CacheSubId: " << cacheSubId << " recvd: " << ts; + std::cerr << std::endl; +#endif + + mLocalCacheTs[ts] = cacheSubId; + if (cacheSubId > mMaxCacheSubId) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() New Max CacheSubId"; + std::cerr << std::endl; +#endif + mMaxCacheSubId = cacheSubId; + } + + if (((time_t) ts < now) && ((time_t) ts > mLastPublishTime)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadFileMsgs() New LastPublishTime"; + std::cerr << std::endl; +#endif + mLastPublishTime = ts; + } + } + + delete store; + return; +} +/***************************************************************************************/ +/***************************************************************************************/ + /********************** load Cache Msgs ***************************************/ +/***************************************************************************************/ +/***************************************************************************************/ + + +bool p3GroupDistrib::loadGroup(RsDistribGrp *newGrp, bool historical) +{ + /* load groupInfo */ + const std::string &gid = newGrp -> grpId; + const std::string &pid = newGrp -> PeerId(); + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroup()" << std::endl; + std::cerr << "groupId: " << gid << std::endl; + std::cerr << "PeerId: " << pid << std::endl; + std::cerr << "Group:" << std::endl; + newGrp -> print(std::cerr, 10); + std::cerr << "----------------------" << std::endl; +#endif + + RsStackMutex stack(distribMtx); /******* STACK LOCKED MUTEX ***********/ + + /* look for duplicate */ + bool checked = false; + bool isNew = false; + bool ok = false; + std::map::iterator it; + it = mGroups.find(gid); + + if (it == mGroups.end()) + { + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroup() Group Not Found"; + std::cerr << std::endl; +#endif + + if (!validateDistribGrp(newGrp)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroup() Invalid Group "; + std::cerr << std::endl; +#endif + /* fails test */ + delete newGrp; + return false; + } + + checked = true; + + GroupInfo gi; + gi.grpId = gid; + mGroups[gid] = gi; + + it = mGroups.find(gid); + + isNew = true; + } + + /* at this point - always in the map */ + + /* add as source ... don't need to validate for this! */ + std::list::iterator pit; + pit = std::find(it->second.sources.begin(), it->second.sources.end(), pid); + if (pit == it->second.sources.end()) + { + it->second.sources.push_back(pid); + it->second.pop = it->second.sources.size(); + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroup() New Source, pop = "; + std::cerr << it->second.pop; + std::cerr << std::endl; +#endif + } + + if (!checked) + { + if (!locked_checkGroupInfo(it->second, newGrp)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroup() Fails Check"; + std::cerr << std::endl; +#endif + /* either fails check or old/same data */ + delete newGrp; + return false; + } + } + + /* useful info/update */ + if(!locked_updateGroupInfo(it->second, newGrp)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroup() Fails Update"; + std::cerr << std::endl; +#endif + /* cleanup on false */ + delete newGrp; + } + else + { + /* Callback for any derived classes */ + + if (isNew) + locked_notifyGroupChanged(it->second, GRP_NEW_UPDATE, historical); + else + locked_notifyGroupChanged(it->second, GRP_UPDATE, historical); + + ok = true; + } + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroup() Done"; + std::cerr << std::endl; + std::cerr << "ok: " << ok << std::endl; +#endif + return ok; + +} + + +bool p3GroupDistrib::loadGroupKey(RsDistribGrpKey *newKey, bool historical) +{ + /* load Key */ + const std::string &gid = newKey -> grpId; + +#ifdef DISTRIB_DEBUG + const std::string &pid = newKey -> PeerId(); + std::cerr << "p3GroupDistrib::loadGroupKey()" << std::endl; + std::cerr << "PeerId: " << pid << std::endl; + std::cerr << "groupId: " << gid << std::endl; + std::cerr << "Key:" << std::endl; + newKey -> print(std::cerr, 10); + std::cerr << "----------------------" << std::endl; +#endif + + RsStackMutex stack(distribMtx); /******* STACK LOCKED MUTEX ***********/ + + /* Find the Group */ + std::map::iterator it; + it = mGroups.find(gid); + + // + if (it == mGroups.end()) + { + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroupKey() Group for key not found: discarding"; + std::cerr << std::endl; +#endif + + delete newKey; + newKey = NULL; + return false; + } + + /* have the group -> add in the key */ + bool updateOk = false; + if (newKey->key.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) + { + if(!locked_updateGroupAdminKey(it->second, newKey)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroupKey() Failed Admin Key Update"; + std::cerr << std::endl; +#endif + } + else + { + updateOk = true; + } + } + else + { + if(!locked_updateGroupPublishKey(it->second, newKey)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroupKey() Failed Publish Key Update"; + std::cerr << std::endl; +#endif + } + else + { + updateOk = true; + } + } + + if (updateOk) + locked_notifyGroupChanged(it->second, GRP_LOAD_KEY, historical); + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadGroupKey() Done - Cleaning up."; + std::cerr << std::endl; +#endif + +// if(!updateOk) + delete newKey; + + newKey = NULL; + return updateOk; +} + + +bool p3GroupDistrib::loadMsg(RsDistribSignedMsg *newMsg, const std::string &src, bool local, bool historical) +{ + /****************** check the msg ******************/ + /* Do the most likely checks to fail first.... + * + * timestamp (too old) + * group (non existant) + * msg (already have it) + * + * -> then do the expensive Hash / signature checks. + */ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg()" << std::endl; + std::cerr << "Source:" << src << std::endl; + std::cerr << "Local:" << local << std::endl; + newMsg -> print(std::cerr, 10); + std::cerr << "----------------------" << std::endl; +#endif + + RsStackMutex stack(distribMtx); /******* STACK LOCKED MUTEX ***********/ + + /* Check if it exists already */ + + /* find group */ + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(newMsg->grpId))) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Group Dont Exist" << std::endl; + std::cerr << std::endl; +#endif + /* if not there -> remove */ + delete newMsg; + return false; + } + + /****************** check the msg ******************/ + /* check for duplicate message, do this first to ensure minimal signature validations. + * therefore, duplicateMsg... could potentially be called on a dodgey msg (not a big problem!) + */ + + std::map::iterator mit; + mit = (git->second).msgs.find(newMsg->msgId); + if (mit != (git->second).msgs.end()) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Msg already exists" << std::endl; + std::cerr << std::endl; +#endif + /* if already there -> remove */ + locked_eventDuplicateMsg(&(git->second), mit->second, src, historical); + delete newMsg; + return false; + } + + /* if unique (new) msg - do validation */ + if (!locked_validateDistribSignedMsg(git->second, newMsg)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() validate failed" << std::endl; + std::cerr << std::endl; +#endif + delete newMsg; + return false; + } + + void *temp_ptr = newMsg->packet.bin_data; + int temp_len = newMsg->packet.bin_len; + + if(git->second.grpFlags & RS_DISTRIB_ENCRYPTED){ + void *out_data = NULL; + int out_len = 0; + + if(decrypt(out_data, out_len, newMsg->packet.bin_data, newMsg->packet.bin_len, newMsg->grpId)){ + newMsg->packet.TlvShallowClear(); + newMsg->packet.setBinData(out_data, out_len); + delete[] (unsigned char*) out_data; + }else{ + if((out_data != NULL) && (out_len != 0)) + delete[] (unsigned char*) out_data; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Failed to decrypt" << std::endl; + std::cerr << std::endl; +#endif + return false; + } + } + + /* convert Msg */ + RsDistribMsg *msg = unpackDistribSignedMsg(newMsg); + + if (!msg) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() unpack failed" << std::endl; + std::cerr << std::endl; +#endif + delete newMsg; + return false; + } + + if (!locked_checkDistribMsg(git->second, msg)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() check failed" << std::endl; + std::cerr << std::endl; +#endif + delete newMsg; + delete msg; + return false; + } + + /* accept message */ + (git->second).msgs[msg->msgId] = msg; + + // update the time stamp of group for last post + if((git->second.lastPost < (time_t)msg->timestamp)) + git->second.lastPost = msg->timestamp; + + // Interface to handle Dummy Msgs. + locked_CheckNewMsgDummies(git->second, msg, src, historical); + + /* now update parents TS */ + locked_updateChildTS(git->second, msg); + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Msg Loaded Successfully" << std::endl; + std::cerr << std::endl; +#endif + + /* Callback for any derived classes to play with */ + locked_eventNewMsg(&(git->second), msg, src, historical); + + /* else if group = subscribed | listener -> publish */ + /* if it has come from us... then it has been published already */ + if ((!local) && (git->second.flags & (RS_DISTRIB_SUBSCRIBED))) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() To be Published!"; + std::cerr << std::endl; +#endif + + if(git->second.grpFlags & RS_DISTRIB_ENCRYPTED){ + newMsg->packet.TlvClear(); + newMsg->packet.setBinData(temp_ptr, temp_len); + } + + locked_toPublishMsg(newMsg); + } + else + { + /* Note it makes it very difficult to republish msg - if we have + * deleted the signed version... The load of old messages will occur + * at next startup. And publication will happen then too. + */ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Deleted Original Msg (No Publish)"; + std::cerr << std::endl; +#endif + delete newMsg; + + } + + if(!historical) + locked_notifyGroupChanged(git->second, GRP_NEW_MSG, historical); + + return true; +} + +bool p3GroupDistrib::locked_loadMsg(RsDistribSignedMsg *newMsg, const std::string &src, bool local, bool historical) +{ + /****************** check the msg ******************/ + /* Do the most likely checks to fail first.... + * + * timestamp (too old) + * group (non existant) + * msg (already have it) + * + * -> then do the expensive Hash / signature checks. + */ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg()" << std::endl; + std::cerr << "Source:" << src << std::endl; + std::cerr << "Local:" << local << std::endl; + newMsg -> print(std::cerr, 10); + std::cerr << "----------------------" << std::endl; +#endif + + + /* Check if it exists already */ + + /* find group */ + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(newMsg->grpId))) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Group Dont Exist" << std::endl; + std::cerr << std::endl; +#endif + /* if not there -> remove */ + delete newMsg; + return false; + } + + + /****************** check the msg ******************/ + /* check for duplicate message, do this first to ensure minimal signature validations. + * therefore, duplicateMsg... could potentially be called on a dodgey msg (not a big problem!) + */ + + std::map::iterator mit; + mit = (git->second).msgs.find(newMsg->msgId); + if (mit != (git->second).msgs.end()) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Msg already exists" << std::endl; + std::cerr << std::endl; +#endif + /* if already there -> remove */ + locked_eventDuplicateMsg(&(git->second), mit->second, src, historical); + delete newMsg; + return false; + } + + /* if unique (new) msg - do validation */ + if (!locked_validateDistribSignedMsg(git->second, newMsg)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() validate failed" << std::endl; + std::cerr << std::endl; +#endif + delete newMsg; + return false; + } + + void *temp_ptr = newMsg->packet.bin_data; + int temp_len = newMsg->packet.bin_len; + + if(git->second.grpFlags & RS_DISTRIB_ENCRYPTED){ + + void *out_data = NULL; + int out_len = 0; + + if(decrypt(out_data, out_len, newMsg->packet.bin_data, newMsg->packet.bin_len, newMsg->grpId)){ + newMsg->packet.TlvShallowClear(); + newMsg->packet.setBinData(out_data, out_len); + delete[] (unsigned char*) out_data; + + }else{ + + if((out_data != NULL) && (out_len != 0)) + delete[] (unsigned char*) out_data; +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Failed to decrypt" << std::endl; + std::cerr << std::endl; +#endif + return false; + } + } + + /* convert Msg */ + RsDistribMsg *msg = unpackDistribSignedMsg(newMsg); + + if (!msg) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() unpack failed" << std::endl; + std::cerr << std::endl; +#endif + delete newMsg; + return false; + } + + if (!locked_checkDistribMsg(git->second, msg)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() check failed" << std::endl; + std::cerr << std::endl; +#endif + delete newMsg; + delete msg; + return false; + } + + /* accept message */ + (git->second).msgs[msg->msgId] = msg; + + // update the time stamp of group for last post + if((git->second.lastPost < (time_t)msg->timestamp)) + git->second.lastPost = msg->timestamp; + + // Interface to handle Dummy Msgs. + locked_CheckNewMsgDummies(git->second, msg, src, historical); + + /* now update parents TS */ + locked_updateChildTS(git->second, msg); + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Msg Loaded Successfully" << std::endl; + std::cerr << std::endl; +#endif + + + /* Callback for any derived classes to play with */ + locked_eventNewMsg(&(git->second), msg, src, historical); + + /* else if group = subscribed | listener -> publish */ + /* if it has come from us... then it has been published already */ + if ((!local) && (git->second.flags & (RS_DISTRIB_SUBSCRIBED))) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() To be Published!"; + std::cerr << std::endl; +#endif + + if(git->second.grpFlags & RS_DISTRIB_ENCRYPTED){ + newMsg->packet.TlvClear(); + newMsg->packet.setBinData(temp_ptr, temp_len); + } + + locked_toPublishMsg(newMsg); + } + else + { + /* Note it makes it very difficult to republish msg - if we have + * deleted the signed version... The load of old messages will occur + * at next startup. And publication will happen then too. + */ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::loadMsg() Deleted Original Msg (No Publish)"; + std::cerr << std::endl; +#endif + delete newMsg; + + } + + if(!historical) + locked_notifyGroupChanged(git->second, GRP_NEW_MSG, historical); + + return true; +} + +/***************************************************************************************/ +/***************************************************************************************/ + /****************** create/mod Cache Content **********************************/ +/***************************************************************************************/ +/***************************************************************************************/ + +void p3GroupDistrib::locked_toPublishMsg(RsDistribSignedMsg *msg) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_toPublishMsg() Adding to PendingPublish List"; + std::cerr << std::endl; +#endif + mPendingPublish.push_back(msg); + if (msg->PeerId() == mOwnId) + { + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_toPublishMsg() Local -> ConfigSave Requested"; + std::cerr << std::endl; +#endif + /* we need to trigger Configuration save */ + IndicateConfigChanged(); /**** INDICATE CONFIG CHANGED! *****/ + } +} + + +uint16_t p3GroupDistrib::locked_determineCacheSubId() +{ + /* if oldest cache is previous to StorePeriod - use that */ + time_t now = time(NULL); + uint16_t id = 1; + + uint32_t oldest = now; + if (mLocalCacheTs.size() > 0) + { + oldest = mLocalCacheTs.begin()->first; + } + + if (oldest < now - mStorePeriod) + { + /* clear it out, return id */ + id = mLocalCacheTs.begin()->second; + mLocalCacheTs.erase(mLocalCacheTs.begin()); + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_determineCacheSubId() Replacing Old CacheId: " << id; + std::cerr << std::endl; +#endif + return id; + } + + mMaxCacheSubId++; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_determineCacheSubId() Returning new Id: " << mMaxCacheSubId; + std::cerr << std::endl; +#endif + /* else return maximum */ + return mMaxCacheSubId; +} + + +void p3GroupDistrib::locked_publishPendingMsgs() +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_publishPendingMsgs()"; + std::cerr << std::endl; +#endif + /* get the next message id */ + CacheData newCache; + time_t now = time(NULL); + + bool ok = true; // hass msg/cache file been written successfully + + newCache.pid = mOwnId; + newCache.cid.type = CacheSource::getCacheType(); + newCache.cid.subid = locked_determineCacheSubId(); + + /* create filename */ + std::string path = CacheSource::getCacheDir(); + std::ostringstream out; + out << "grpdist-t" << CacheSource::getCacheType() << "-msgs-" << time(NULL) << ".dist"; + + std::string tmpname = out.str(); + std::string filename = path + "/" + tmpname ; + std::string filenametmp = path + "/" + tmpname + ".tmp"; + + BinInterface *bio = new BinFileInterface(filenametmp.c_str(), BIN_FLAGS_WRITEABLE | BIN_FLAGS_HASH_DATA); + pqistore *store = createStore(bio, mOwnId, BIN_FLAGS_WRITEABLE); /* messages are deleted! */ + + bool resave = false; + std::list::iterator it; + for(it = mPendingPublish.begin(); it != mPendingPublish.end(); it++) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_publishPendingMsgs() Publishing:"; + std::cerr << std::endl; + (*it)->print(std::cerr, 10); + std::cerr << std::endl; +#endif + if ((*it)->PeerId() == mOwnId) + { + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_publishPendingMsgs() Own Publish"; + std::cerr << std::endl; +#endif + resave = true; + } + + // prevent sending original source of message to peers + (*it)->PeerId(mOwnId); + + if(!store->SendItem(*it)) /* deletes it */ + { + ok &= false; + } + } + + /* Extract File Information from pqistore */ + newCache.path = path; + newCache.name = tmpname; + + newCache.hash = bio->gethash(); + newCache.size = bio->bytecount(); + newCache.recvd = now; + + /* cleanup */ + mPendingPublish.clear(); + delete store; + + if(!RsDirUtil::renameFile(filenametmp,filename)) + { + std::ostringstream errlog; + ok &= false; +#ifdef WIN32 + errlog << "Error " << GetLastError() ; +#else + errlog << "Error " << errno ; +#endif + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + filename + ": got error "+errlog.str()); + } + + /* indicate not to save for a while */ + mLastPublishTime = now; + + /* push file to CacheSource */ + + if(ok) + refreshCache(newCache); + + + if (ok && resave) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_publishPendingMsgs() Indicate Save Data Changed"; + std::cerr << std::endl; +#endif + /* flag to store config (saying we've published messages) */ + IndicateConfigChanged(); /**** INDICATE CONFIG CHANGED! *****/ + } +} + + +void p3GroupDistrib::publishDistribGroups() +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishDistribGroups()"; + std::cerr << std::endl; +#endif + + /* set subid = 1 */ + CacheData newCache; + + newCache.pid = mOwnId; + newCache.cid.type = CacheSource::getCacheType(); + newCache.cid.subid = 1; + + /* create filename */ + std::string path = CacheSource::getCacheDir(); + std::ostringstream out; + out << "grpdist-t" << CacheSource::getCacheType() << "-grps-" << time(NULL) << ".dist"; + + std::string tmpname = out.str(); + std::string filename = path + "/" + tmpname; + std::string filenametmp = path + "/" + tmpname + ".tmp"; + std::string tempPeerId; // to store actual id temporarily + + BinInterface *bio = new BinFileInterface(filenametmp.c_str(), BIN_FLAGS_WRITEABLE | BIN_FLAGS_HASH_DATA); + pqistore *store = createStore(bio, mOwnId, BIN_FLAGS_NO_DELETE | BIN_FLAGS_WRITEABLE); + + RsStackMutex stack(distribMtx); /****** STACK MUTEX LOCKED *******/ + + + /* Iterate through all the Groups */ + std::map::iterator it; + for(it = mGroups.begin(); it != mGroups.end(); it++) + { + /* if subscribed or listener or admin -> then send it to be published by cache */ + if ((it->second.flags & RS_DISTRIB_SUBSCRIBED) || (it->second.flags & RS_DISTRIB_ADMIN)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishDistribGroups() Saving Group: " << it->first; + std::cerr << std::endl; +#endif + + /* extract public info to RsDistribGrp */ + RsDistribGrp *grp = it->second.distribGroup; + + if (grp) + { + /* store in Cache File */ + tempPeerId = grp->PeerId(); + grp->PeerId(mOwnId); // prevent sending original source to users + store->SendItem(grp); /* no delete */ + grp->PeerId(tempPeerId); + + grp->grpFlags &= (~RS_DISTRIB_UPDATE); // if this is an update, ensure flag is removed after publication + } + + /* if they have public keys, publish these too */ + std::map::iterator kit; + for(kit = it->second.publishKeys.begin(); + kit != it->second.publishKeys.end(); kit++) + { + if ((kit->second.type & RSTLV_KEY_DISTRIB_PUBLIC) && + (kit->second.type & RSTLV_KEY_TYPE_FULL)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishDistribGroups() Saving Key: " << kit->first; + std::cerr << std::endl; +#endif + /* create Key for sharing */ + + RsDistribGrpKey *pubKey = new RsDistribGrpKey(); + pubKey->grpId = it->first; + + RSA *rsa_priv = EVP_PKEY_get1_RSA(kit->second.key); + setRSAPrivateKey(pubKey->key, rsa_priv); + RSA_free(rsa_priv); + + pubKey->key.keyFlags = RSTLV_KEY_TYPE_FULL; + pubKey->key.keyFlags |= RSTLV_KEY_DISTRIB_PUBLIC; + pubKey->key.startTS = kit->second.startTS; + pubKey->key.endTS = kit->second.endTS; + + store->SendItem(pubKey); + delete pubKey; + } + else + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishDistribGroups() Ignoring Key: " << kit->first; + std::cerr << std::endl; + std::cerr << "p3GroupDistrib::publishDistribGroups() Key Type: " << kit->second.type; + std::cerr << std::endl; +#endif + } + + } + } + else + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishDistribGroups() Ignoring Group: " << it->first; + std::cerr << std::endl; +#endif + } + + } + + /* Extract File Information from pqistore */ + newCache.path = path; + newCache.name = tmpname; + + newCache.hash = bio->gethash(); + newCache.size = bio->bytecount(); + newCache.recvd = time(NULL); + + /* cleanup */ + delete store; + + if(!RsDirUtil::renameFile(filenametmp,filename)) + { + std::ostringstream errlog; +#ifdef WIN32 + errlog << "Error " << GetLastError() ; +#else + errlog << "Error " << errno ; +#endif + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + filename + ": got error "+errlog.str()); + } + + /* push file to CacheSource */ + refreshCache(newCache); +} + + + /* clearing old data */ +void p3GroupDistrib::clear_local_caches(time_t now) +{ + RsStackMutex stack(distribMtx); /****** STACK MUTEX LOCKED *******/ + + time_t cutoff = now - mStorePeriod; + std::list::iterator it; + for(it = mLocalCaches.begin(); it != mLocalCaches.end();) + { + if (it->end < cutoff) + { + /* Call to CacheSource Function */ + CacheId cid(CacheSource::getCacheType(), it->cacheSubId); + clearCache(cid); + it = mLocalCaches.erase(it); + } + else + { + it++; + } + } +} + + + +/***************************************************************************************/ +/***************************************************************************************/ + /********************** Access Content ***************************************/ +/***************************************************************************************/ +/***************************************************************************************/ + + +/* get Group Lists */ +bool p3GroupDistrib::getAllGroupList(std::list &grpids) +{ + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + std::map::iterator git; + for(git = mGroups.begin(); git != mGroups.end(); git++) + { + grpids.push_back(git->first); + } + return true; +} + +bool p3GroupDistrib::getSubscribedGroupList(std::list &grpids) +{ + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + std::map::iterator git; + for(git = mGroups.begin(); git != mGroups.end(); git++) + { + if (git->second.flags & RS_DISTRIB_SUBSCRIBED) + { + grpids.push_back(git->first); + } + } + return true; +} + +bool p3GroupDistrib::getPublishGroupList(std::list &grpids) +{ + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + std::map::iterator git; + for(git = mGroups.begin(); git != mGroups.end(); git++) + { + if (git->second.flags & (RS_DISTRIB_ADMIN | RS_DISTRIB_PUBLISH)) + { + grpids.push_back(git->first); + } + } + return true; +} + +void p3GroupDistrib::getPopularGroupList(uint32_t popMin, uint32_t popMax, std::list &grpids) +{ + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + std::map::iterator git; + for(git = mGroups.begin(); git != mGroups.end(); git++) + { + if ((git->second.pop >= popMin) && + (git->second.pop <= popMax)) + { + grpids.push_back(git->first); + } + } + return; +} + + +/* get Msg Lists */ +bool p3GroupDistrib::getAllMsgList(const std::string& grpId, std::list &msgIds) +{ + + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + +#ifdef ENABLE_CACHE_OPT + locked_processHistoryCached(grpId); +#endif + + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { + return false; + } + + std::map::iterator mit; + std::map msgs; + + for(mit = git->second.msgs.begin(); mit != git->second.msgs.end(); mit++) + { + msgIds.push_back(mit->first); + } + return true; +} + +bool p3GroupDistrib::getParentMsgList(const std::string& grpId, const std::string& pId, + std::list &msgIds) +{ + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + +#ifdef ENABLE_CACHE_OPT + locked_processHistoryCached(grpId); +#endif + + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { + return false; + } + + std::map::iterator mit; + + for(mit = git->second.msgs.begin(); mit != git->second.msgs.end(); mit++) + { + if (mit->second->parentId == pId) + { + msgIds.push_back(mit->first); + } + } + return true; +} + +bool p3GroupDistrib::getTimePeriodMsgList(const std::string& grpId, uint32_t timeMin, + uint32_t timeMax, std::list &msgIds) +{ + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { + return false; + } + + std::map::iterator mit; + + for(mit = git->second.msgs.begin(); mit != git->second.msgs.end(); mit++) + { + if ((mit->second->timestamp >= timeMin) && + (mit->second->timestamp <= timeMax)) + { + msgIds.push_back(mit->first); + } + } + return true; +} + + +GroupInfo *p3GroupDistrib::locked_getGroupInfo(const std::string& grpId) +{ + /************* ALREADY LOCKED ************/ + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { + return NULL; + } + return &(git->second); +} + + +RsDistribMsg *p3GroupDistrib::locked_getGroupMsg(const std::string& grpId, const std::string& msgId) +{ + + /************* ALREADY LOCKED ************/ + + locked_processHistoryCached(grpId); + + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { + return NULL; + } + + std::map::iterator mit; + if (git->second.msgs.end() == (mit = git->second.msgs.find(msgId))) + { + return NULL; + } + + return mit->second; +} + +bool p3GroupDistrib::subscribeToGroup(const std::string &grpId, bool subscribe) +{ + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { + return false; + } + + if (subscribe) + { + if (!(git->second.flags & RS_DISTRIB_SUBSCRIBED)) + { + git->second.flags |= RS_DISTRIB_SUBSCRIBED; + + locked_notifyGroupChanged(git->second, GRP_SUBSCRIBED, false); + mGroupsRepublish = true; + + /* reprocess groups messages .... so actions can be taken (by inherited) + * This could be an very expensive operation! .... but they asked for it. + * + * Hopefully a LoadList call will have on existing messages! + */ + + std::map::iterator mit; + std::list::iterator pit; + + /* assume that each peer can provide all of them */ + for(mit = git->second.msgs.begin(); + mit != git->second.msgs.end(); mit++) + { + for(pit = git->second.sources.begin(); + pit != git->second.sources.end(); pit++) + { + if(*pit != mOwnId) + locked_eventDuplicateMsg(&(git->second), mit->second, *pit, false); + } + } + } + } + else + { + if (git->second.flags & RS_DISTRIB_SUBSCRIBED) + { + git->second.flags &= (~RS_DISTRIB_SUBSCRIBED); + + locked_notifyGroupChanged(git->second, GRP_UNSUBSCRIBED, false); + mGroupsRepublish = true; + } + } + + return true; +} + + +bool p3GroupDistrib::attemptPublishKeysRecvd() +{ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::attemptPublishKeysRecvd() " << std::endl; +#endif + + RsStackMutex stack(distribMtx); + + std::list toDelete; + std::list::iterator sit; + std::map::iterator it; + + std::map::iterator mit; + mit = mRecvdPubKeys.begin(); + + // add received keys for groups that are present + for(; mit != mRecvdPubKeys.end(); mit++){ + + it = mGroups.find(mit->first); + + // group has not arrived yet don't attempt to add + if(it == mGroups.end()){ + + continue; + + }else{ + + + + if(locked_updateGroupPublishKey(it->second, mit->second)){ + + locked_notifyGroupChanged(it->second, GRP_LOAD_KEY, false); + } + + if(it->second.flags & RS_DISTRIB_SUBSCRIBED){ + // remove key shared flag so key is not loaded back into mrecvdpubkeys + mit->second->key.keyFlags &= (~RSTLV_KEY_TYPE_SHARED); + + delete (mit->second); + toDelete.push_back(mit->first); + } + + } + } + + sit = toDelete.begin(); + + for(; sit != toDelete.end(); sit++) + mRecvdPubKeys.erase(*sit); + + + + + return true; +} + +/************************************* p3Config *************************************/ + +RsSerialiser *p3GroupDistrib::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsDistribSerialiser()); + + return rss; +} + +bool p3GroupDistrib::saveList(bool &cleanup, std::list& saveData) +{ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::saveList()"; + std::cerr << std::endl; +#endif + + cleanup = false; + + distribMtx.lock(); /****** MUTEX LOCKED *******/ + + /* Iterate through all the Groups */ + std::map::iterator it; + for(it = mGroups.begin(); it != mGroups.end(); it++) + { + /* if subscribed or listener -> do stuff */ + if (it->second.flags & (RS_DISTRIB_SUBSCRIBED)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::saveList() Saving Group: " << it->first; + std::cerr << std::endl; +#endif + + /* extract public info to RsDistribGrp */ + RsDistribGrp *grp = it->second.distribGroup; + + if (grp) + { + /* store in Cache File */ + saveData.push_back(grp); /* no delete */ + } + + /* if they have public keys, publish these too */ + std::map::iterator kit; + for(kit = it->second.publishKeys.begin(); + kit != it->second.publishKeys.end(); kit++) + { + if (kit->second.type & RSTLV_KEY_TYPE_FULL) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::saveList() Saving Key: " << kit->first; + std::cerr << std::endl; +#endif + /* create Key for sharing */ + + RsDistribGrpKey *pubKey = new RsDistribGrpKey(); + pubKey->grpId = it->first; + + RSA *rsa_priv = EVP_PKEY_get1_RSA(kit->second.key); + setRSAPrivateKey(pubKey->key, rsa_priv); + RSA_free(rsa_priv); + + pubKey->key.keyFlags = kit->second.type; + pubKey->key.startTS = kit->second.startTS; + pubKey->key.endTS = kit->second.endTS; + + saveData.push_back(pubKey); + saveCleanupList.push_back(pubKey); + } + else + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::saveList() Ignoring Key: " << kit->first; + std::cerr << std::endl; + std::cerr << "p3GroupDistrib::saveList() Key Type: " << kit->second.type; + std::cerr << std::endl; +#endif + } + + } + + if (it->second.adminKey.type & RSTLV_KEY_TYPE_FULL) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::saveList() Saving Admin Key"; + std::cerr << std::endl; +#endif + /* create Key for sharing */ + + RsDistribGrpKey *pubKey = new RsDistribGrpKey(); + pubKey->grpId = it->first; + + RSA *rsa_priv = EVP_PKEY_get1_RSA(kit->second.key); + setRSAPrivateKey(pubKey->key, rsa_priv); + RSA_free(rsa_priv); + + pubKey->key.keyFlags = RSTLV_KEY_TYPE_FULL; + pubKey->key.keyFlags |= RSTLV_KEY_DISTRIB_ADMIN; + pubKey->key.startTS = kit->second.startTS; + pubKey->key.endTS = kit->second.endTS; + + saveData.push_back(pubKey); + saveCleanupList.push_back(pubKey); + } + else + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::saveList() Ignoring Admin Key: " << it->second.adminKey.keyId; + std::cerr << std::endl; + std::cerr << "p3GroupDistrib::saveList() Admin Key Type: " << it->second.adminKey.type; + std::cerr << std::endl; +#endif + } + } + else + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::saveList() Ignoring Group: " << it->first; + std::cerr << std::endl; +#endif + } + + } + + std::list::iterator mit; + for(mit = mPendingPublish.begin(); mit != mPendingPublish.end(); mit++) + { + if ((*mit)->PeerId() == mOwnId) + { + saveData.push_back(*mit); + } + } + + // also save pending private publish keys you may have + std::map::iterator pendKeyIt; + + for(pendKeyIt = mRecvdPubKeys.begin(); pendKeyIt != mRecvdPubKeys.end(); pendKeyIt++) + { + + RsDistribGrpKey *pubKey = new RsDistribGrpKey(); + pubKey->grpId = pendKeyIt->first; + const unsigned char *keyptr = (const unsigned char *) + pendKeyIt->second->key.keyData.bin_data; + long keylen = pendKeyIt->second->key.keyData.bin_len; + + RSA *rsa_priv = d2i_RSAPrivateKey(NULL, &(keyptr), keylen); + + setRSAPrivateKey(pubKey->key, rsa_priv); + RSA_free(rsa_priv); + + pubKey->key.keyFlags = pendKeyIt->second->key.keyFlags; + pubKey->key.startTS = pendKeyIt->second->key.startTS; + pubKey->key.endTS = pendKeyIt->second->key.endTS; + + saveData.push_back(pubKey); + saveCleanupList.push_back(pubKey); + + } + + std::list childSaveL = childSaveList(); + std::list::iterator cit = childSaveL.begin(); + RsSerialType *childSer = createSerialiser(); + uint32_t pktSize = 0; + unsigned char *data = NULL; + + for(; cit != childSaveL.end() ; cit++) + { + RsDistribConfigData* childConfig = new RsDistribConfigData(); + + pktSize = childSer->size(*cit); + data = new unsigned char[pktSize]; + childSer->serialise(*cit, data, &pktSize); + childConfig->service_data.setBinData(data, pktSize); + delete[] data; + saveData.push_back(childConfig); + saveCleanupList.push_back(childConfig); + } + + delete childSer; + + // now save hostory doc +#ifdef ENABLE_CACHE_OPT + locked_saveHistoryCacheFile(); +#endif + + return true; +} + +void p3GroupDistrib::saveDone() +{ + /* clean up the save List */ + std::list::iterator it; + for(it = saveCleanupList.begin(); it != saveCleanupList.end(); it++) + { + delete (*it); + } + + saveCleanupList.clear(); + + /* unlock mutex */ + distribMtx.unlock(); /****** MUTEX UNLOCKED *******/ +} + +bool p3GroupDistrib::loadList(std::list& load) +{ + std::list::iterator lit; + +#ifdef ENABLE_CACHE_OPT + { + RsStackMutex stack(distribMtx); + + if(locked_loadHistoryCacheFile()) + locked_buildCacheTable(); + } +#endif + + /* for child config data */ + std::list childLoadL; + RsSerialType* childSer = createSerialiser(); + grpCachePair gcPair; + pCacheId cId; + for(lit = load.begin(); lit != load.end(); lit++) + { + /* decide what type it is */ + + RsDistribGrp *newGrp = NULL; + RsDistribGrpKey *newKey = NULL; + RsDistribSignedMsg *newMsg = NULL; + RsDistribConfigData* newChildConfig = NULL; + + + if ((newGrp = dynamic_cast(*lit))) + { + const std::string &gid = newGrp -> grpId; + if(loadGroup(newGrp, false)){ + +#ifdef ENABLE_CACHE_OPT + bool cached = false; + RsStackMutex stack(distribMtx); + + if(!locked_historyCached(newGrp->grpId, cached)){ + cId = pCacheId(mOwnId, 1); + gcPair = std::make_pair(newGrp->grpId, cId); + mGrpHistPending.push_back(gcPair); + mUpdateCacheDoc = true; + } +#endif + } + subscribeToGroup(gid, true); + } + else if ((newKey = dynamic_cast(*lit))) + { + + // for shared keys keep + if(newKey->key.keyFlags & RSTLV_KEY_TYPE_SHARED){ + + mRecvdPubKeys.insert(std::pair( + newKey->grpId, newKey)); + mPubKeyAvailableGrpId.insert(newKey->grpId); + continue; + } + + loadGroupKey(newKey, false); + + + } + else if ((newMsg = dynamic_cast(*lit))) + { + newMsg->PeerId(mOwnId); + loadMsg(newMsg, mOwnId, false, false); /* false so it'll pushed to PendingPublish list */ + } + else if ((newChildConfig = dynamic_cast(*lit))) + { + RsItem* childConfigItem = childSer->deserialise(newChildConfig->service_data.bin_data, + &newChildConfig->service_data.bin_len); + + childLoadL.push_back(childConfigItem); + + } + } + + /* no need to republish until something new comes in */ + RsStackMutex stack(distribMtx); /******* STACK LOCKED MUTEX ***********/ + + childLoadList(childLoadL); // send configurations down to child + + mGroupsRepublish = false; + delete childSer; + + return true; +} + +/************************************* p3Config *************************************/ + +/* This Streamer is used for Reading and Writing Cache Files.... + * As All the child packets are Packed, we should only need RsSerialDistrib() in it. + */ + +pqistore *p3GroupDistrib::createStore(BinInterface *bio, const std::string &src, uint32_t bioflags) +{ + RsSerialiser *rsSerialiser = new RsSerialiser(); + RsSerialType *serialType = new RsDistribSerialiser(); + rsSerialiser->addSerialType(serialType); + + pqistore *store = new pqistore(rsSerialiser, src, bio, bioflags); + + return store; +} + + +/***************************************************************************************/ +/***************************************************************************************/ + /********************** Create Content ***************************************/ +/***************************************************************************************/ +/***************************************************************************************/ + +std::string getRsaKeySign(RSA *pubkey) +{ + int len = BN_num_bytes(pubkey -> n); + unsigned char tmp[len]; + BN_bn2bin(pubkey -> n, tmp); + + // copy first CERTSIGNLEN bytes... + if (len > CERTSIGNLEN) + { + len = CERTSIGNLEN; + } + + std::ostringstream id; + for(uint32_t i = 0; i < CERTSIGNLEN; i++) + { + id << std::hex << std::setw(2) << std::setfill('0') + << (uint16_t) (((uint8_t *) (tmp))[i]); + } + std::string rsaId = id.str(); + + return rsaId; +} + +std::string getBinDataSign(void *data, int len) +{ + unsigned char *tmp = (unsigned char *) data; + + // copy first CERTSIGNLEN bytes... + if (len > CERTSIGNLEN) + { + len = CERTSIGNLEN; + } + + std::ostringstream id; + for(uint32_t i = 0; i < CERTSIGNLEN; i++) + { + id << std::hex << std::setw(2) << std::setfill('0') + << (uint16_t) (((uint8_t *) (tmp))[i]); + } + std::string Id = id.str(); + + return Id; +} + + +void setRSAPublicKey(RsTlvSecurityKey &key, RSA *rsa_pub) +{ + unsigned char data[10240]; /* more than enough space */ + unsigned char *ptr = data; + int reqspace = i2d_RSAPublicKey(rsa_pub, &ptr); + + key.keyData.setBinData(data, reqspace); + + std::string keyId = getRsaKeySign(rsa_pub); + key.keyId = keyId; +} + +void setRSAPrivateKey(RsTlvSecurityKey &key, RSA *rsa_priv) +{ + unsigned char data[10240]; /* more than enough space */ + unsigned char *ptr = data; + int reqspace = i2d_RSAPrivateKey(rsa_priv, &ptr); + + key.keyData.setBinData(data, reqspace); + + std::string keyId = getRsaKeySign(rsa_priv); + key.keyId = keyId; +} + + +RSA *extractPublicKey(RsTlvSecurityKey &key) +{ + const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; + long keylen = key.keyData.bin_len; + + /* extract admin key */ + RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); + + return rsakey; +} + + +RSA *extractPrivateKey(RsTlvSecurityKey &key) +{ + const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data; + long keylen = key.keyData.bin_len; + + /* extract admin key */ + RSA *rsakey = d2i_RSAPrivateKey(NULL, &(keyptr), keylen); + + return rsakey; +} + + +std::string p3GroupDistrib::createGroup(std::wstring name, std::wstring desc, uint32_t flags, + unsigned char* pngImageData, uint32_t imageSize) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::createGroup()" << std::endl; + std::cerr << std::endl; +#endif + /* Create a Group */ + std::string grpId; + time_t now = time(NULL); + + /* for backup */ + std::list grpKeySet; + + /* create Keys */ + RSA *rsa_admin = RSA_generate_key(2048, 65537, NULL, NULL); + RSA *rsa_admin_pub = RSAPublicKey_dup(rsa_admin); + + RSA *rsa_publish = RSA_generate_key(2048, 65537, NULL, NULL); + RSA *rsa_publish_pub = RSAPublicKey_dup(rsa_publish); + + /* Create Group Description */ + + RsDistribGrp *newGrp = new RsDistribGrp(); + + newGrp->grpName = name; + newGrp->grpDesc = desc; + newGrp->timestamp = now; + newGrp->grpFlags = flags & (RS_DISTRIB_PRIVACY_MASK | RS_DISTRIB_AUTHEN_MASK); + newGrp->grpControlFlags = 0; + + // explicit member wise copy for grp image + if((pngImageData != NULL) && (imageSize > 0)){ + newGrp->grpPixmap.binData.bin_data = new unsigned char[imageSize]; + + memcpy(newGrp->grpPixmap.binData.bin_data, pngImageData, + imageSize*sizeof(unsigned char)); + newGrp->grpPixmap.binData.bin_len = imageSize; + newGrp->grpPixmap.image_type = RSTLV_IMAGE_TYPE_PNG; + + }else{ + newGrp->grpPixmap.binData.bin_data = NULL; + newGrp->grpPixmap.binData.bin_len = 0; + newGrp->grpPixmap.image_type = 0; + } + + + + + /* set keys */ + setRSAPublicKey(newGrp->adminKey, rsa_admin_pub); + newGrp->adminKey.keyFlags = RSTLV_KEY_TYPE_PUBLIC_ONLY | RSTLV_KEY_DISTRIB_ADMIN; + newGrp->adminKey.startTS = now; + newGrp->adminKey.endTS = 0; /* no end */ + grpId = newGrp->adminKey.keyId; + + + RsTlvSecurityKey publish_key; + + setRSAPublicKey(publish_key, rsa_publish_pub); + + publish_key.keyFlags = RSTLV_KEY_TYPE_PUBLIC_ONLY; + if (flags & RS_DISTRIB_PUBLIC) + { + publish_key.keyFlags |= RSTLV_KEY_DISTRIB_PUBLIC; + } + else + { + publish_key.keyFlags |= RSTLV_KEY_DISTRIB_PRIVATE; + } + + publish_key.startTS = now; + publish_key.endTS = now + 60 * 60 * 24 * 365 * 5; /* approx 5 years */ + + newGrp->publishKeys.keys[publish_key.keyId] = publish_key; + newGrp->publishKeys.groupId = newGrp->adminKey.keyId; + + + /************* create Key Messages (to Add Later) *********************/ + RsDistribGrpKey *adKey = new RsDistribGrpKey(); + adKey->grpId = grpId; + + setRSAPrivateKey(adKey->key, rsa_admin); + adKey->key.keyFlags = RSTLV_KEY_TYPE_FULL | RSTLV_KEY_DISTRIB_ADMIN; + adKey->key.startTS = newGrp->adminKey.startTS; + adKey->key.endTS = newGrp->adminKey.endTS; + + + RsDistribGrpKey *pubKey = new RsDistribGrpKey(); + pubKey->grpId = grpId; + + setRSAPrivateKey(pubKey->key, rsa_publish); + pubKey->key.keyFlags = RSTLV_KEY_TYPE_FULL; + if (flags & RS_DISTRIB_PUBLIC) + { + pubKey->key.keyFlags |= RSTLV_KEY_DISTRIB_PUBLIC; + } + else + { + pubKey->key.keyFlags |= RSTLV_KEY_DISTRIB_PRIVATE; + } + pubKey->key.startTS = publish_key.startTS; + pubKey->key.endTS = publish_key.endTS; + /************* create Key Messages (to Add Later) *********************/ + + + /* clean up publish_key manually -> else + * the data will get deleted... + */ + + publish_key.keyData.bin_data = NULL; + publish_key.keyData.bin_len = 0; + + newGrp->grpId = grpId; + + /************* Back up Keys *********************/ + + grpKeySet.push_back(adKey); + grpKeySet.push_back(pubKey); + + backUpKeys(grpKeySet, grpId); + + /************** Serialise and sign **************************************/ + EVP_PKEY *key_admin = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(key_admin, rsa_admin); + + newGrp->adminSignature.TlvClear(); + + RsSerialType *serialType = new RsDistribSerialiser(); + + uint32_t size = serialType->size(newGrp); + char* data = new char[size]; + + serialType->serialise(newGrp, data, &size); + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_SignInit(mdctx, EVP_sha1()); + EVP_SignUpdate(mdctx, data, size); + + unsigned int siglen = EVP_PKEY_size(key_admin); + unsigned char sigbuf[siglen]; + EVP_SignFinal(mdctx, sigbuf, &siglen, key_admin); + + /* save signature */ + newGrp->adminSignature.signData.setBinData(sigbuf, siglen); + newGrp->adminSignature.keyId = grpId; + + /* clean up */ + delete serialType; + EVP_MD_CTX_destroy(mdctx); + + + /******************* clean up all Keys *******************/ + + RSA_free(rsa_admin_pub); + RSA_free(rsa_publish_pub); + RSA_free(rsa_publish); + EVP_PKEY_free(key_admin); + + /******************* load up new Group *********************/ + loadGroup(newGrp, false); + + /* add Keys to GroupInfo */ + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + GroupInfo *gi = locked_getGroupInfo(grpId); + if (!gi) + { + return grpId; + } + + gi->flags |= RS_DISTRIB_SUBSCRIBED; + mGroupsRepublish = true; + + /* replace the public keys */ + locked_updateGroupAdminKey(*gi, adKey); + locked_updateGroupPublishKey(*gi, pubKey); + + delete adKey; + delete pubKey; + delete[] data; + return grpId; +} + + +bool p3GroupDistrib::backUpKeys(const std::list& keysToBackUp, std::string grpId){ + +#ifdef DISTRIB_DEBUG + std::cerr << "P3Distrib::backUpKeys() Backing up keys for grpId: " << grpId << std::endl; +#endif + + std::string filename = mKeyBackUpDir + "/" + grpId + "_" + BACKUP_KEY_FILE; + std::string filenametmp = filename + ".tmp"; + + BinInterface *bio = new BinFileInterface(filenametmp.c_str(), BIN_FLAGS_WRITEABLE); + pqistore *store = createStore(bio, mOwnId, BIN_FLAGS_NO_DELETE | BIN_FLAGS_WRITEABLE); + + std::list::const_iterator it; + bool ok = true; + + for(it=keysToBackUp.begin(); it != keysToBackUp.end(); it++){ + + ok &= store->SendItem(*it); + + } + + delete store; + + if(!RsDirUtil::renameFile(filenametmp,filename)) + { + std::ostringstream errlog; +#ifdef WIN32 + errlog << "Error " << GetLastError() ; +#else + errlog << "Error " << errno ; +#endif + getPqiNotify()->AddSysMessage(0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + filename + ": got error "+errlog.str()); + return false; + } + + return ok; +} + +bool p3GroupDistrib::restoreGrpKeys(const std::string& grpId){ + + +#ifdef DISTRIB_DEBUG + std::cerr << "p3Distrib::restoreGrpKeys() Attempting to restore private keys for grp: " + << grpId << std::endl; +#endif + + // build key directory name + std::string filename = mKeyBackUpDir + "/"+ grpId + "_" + BACKUP_KEY_FILE; + + + /* create the serialiser to load keys */ + BinInterface *bio = new BinFileInterface(filename.c_str(), BIN_FLAGS_READABLE); + pqistore *store = createStore(bio, mOwnId, BIN_FLAGS_READABLE); + + RsItem* item; + bool ok = true; + bool itemAttempted = false; + RsDistribGrpKey* key = NULL; + + RsStackMutex stack(distribMtx); + + GroupInfo* gi = locked_getGroupInfo(grpId); + + //retrieve keys from file and load to appropriate grp + while(NULL != (item = store->GetItem())){ + + itemAttempted = true; + key = dynamic_cast(item); + + if(key == NULL){ +#ifdef DISTRIB_DEBUG + std::cerr << "p3groupDistrib::restoreGrpKey() Key file / grp key item not Valid, grp: " + "\ngrpId: " << grpId << std::endl; +#endif + delete store ; + return false; + } + + if(key->key.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) + ok &= locked_updateGroupAdminKey(*gi, key); + else if((key->key.keyFlags & RSTLV_KEY_DISTRIB_PRIVATE) || + (key->key.keyFlags & RSTLV_KEY_DISTRIB_PUBLIC)) + ok &= locked_updateGroupPublishKey(*gi, key); + else + ok &= false; + + } + + + + ok &= itemAttempted; + + if(ok){ + gi->flags |= RS_DISTRIB_SUBSCRIBED; + locked_notifyGroupChanged(*gi, GRP_SUBSCRIBED, false); + IndicateConfigChanged(); + mGroupsRepublish = true; + } + +#ifdef DISTRIB_DEBUG + if(!ok){ + std::cerr << "p3Distrib::restoreGrpKeys() Failed to restore private keys for grp " + << "\ngrpId: " << grpId << std::endl; + } +#endif + + delete store; + + return ok; +} + + +bool p3GroupDistrib::sharePubKey(std::string grpId, std::list& peers){ + + RsStackMutex stack(distribMtx); + + // first check that group actually exists + if(mGroups.find(grpId) == mGroups.end()){ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::sharePubKey(): Group does not exist" << std::endl; +#endif + return false; + } + + // add to pending list to be sent + mPendingPubKeyRecipients[grpId] = peers; + + return true; +} + +void p3GroupDistrib::locked_sharePubKey(){ + + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_sharePubKey() " << std::endl; +#endif + + std::map >::iterator mit; + std::list::iterator lit; + + // get list of peers that are online + std::list peersOnline; + rsPeers->getOnlineList(peersOnline); + std::list toDelete; + + /* send public key to peers online */ + + for(mit = mPendingPubKeyRecipients.begin(); mit != mPendingPubKeyRecipients.end(); mit++){ + + GroupInfo *gi = locked_getGroupInfo(mit->first); + + if(gi == NULL){ + toDelete.push_back(mit->first); // grp does not exist, stop attempting to share key for dead group + continue; + } + + // find full public key, and send to given peers + std::map::iterator kit; + for(kit = gi->publishKeys.begin(); + kit != gi->publishKeys.end(); kit++) + { + if (kit->second.type & RSTLV_KEY_TYPE_FULL) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_sharePubKey() Sharing Key: " << kit->first; + std::cerr << std::endl; +#endif + + // send keys to peers who are online + for(lit = mit->second.begin() ; lit != mit->second.end(); lit++){ + + if(std::find(peersOnline.begin(), peersOnline.end(), *lit) != peersOnline.end()){ + + /* create Key for sharing */ + RsDistribGrpKey* pubKey = new RsDistribGrpKey(getRsItemService(getType())); + + + pubKey->clear(); + pubKey->grpId = mit->first; + + RSA *rsa_priv = EVP_PKEY_get1_RSA(kit->second.key); + setRSAPrivateKey(pubKey->key, rsa_priv); + RSA_free(rsa_priv); + + pubKey->key.keyFlags = kit->second.type; + pubKey->key.startTS = kit->second.startTS; + pubKey->key.endTS = kit->second.endTS; + pubKey->PeerId(*lit); + std::cout << *lit << std::endl; + sendItem(pubKey); + + // remove peer from list + lit = mit->second.erase(lit); // no need to send to peer anymore + lit--; + } + } + } + } + + // if given peers have all received key(s) then stop sending for group + if(mit->second.empty()) + toDelete.push_back(mit->first); + } + + // delete pending peer list which are done with + for(lit = toDelete.begin(); lit != toDelete.end(); lit++) + mPendingPubKeyRecipients.erase(*lit); + + mLastKeyPublishTime = time(NULL); + + return; +} + + +void p3GroupDistrib::receivePubKeys(){ + + + RsItem* item; + std::string gid; + + std::map::iterator it; + std::list toDelete; + std::list::iterator sit; + + + // load received keys + while(NULL != (item = recvItem())){ + + RsDistribGrpKey* key_item = dynamic_cast(item); + + if(key_item != NULL){ + + it = mGroups.find(key_item->grpId); + + // if group does not exist keep to see if it arrives later + if(it == mGroups.end()){ + + // make sure key is in date + if(((time_t)(key_item->key.startTS + mStorePeriod) > time(NULL)) && + (key_item->key.keyFlags & RSTLV_KEY_TYPE_FULL)){ + + // make sure keys does not exist in recieved list, then delete + if(mRecvdPubKeys.find(gid) == mRecvdPubKeys.end()){ + + // id key as shared so on loadlist sends back mRecvdPubKeys + key_item->key.keyFlags |= RSTLV_KEY_TYPE_SHARED; + mRecvdPubKeys.insert(std::pair(key_item->grpId, key_item)); + + mPubKeyAvailableGrpId.insert(key_item->grpId); + } + + }else{ + delete key_item; + } + + continue; + } + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_receiveKeys()" << std::endl; + std::cerr << "PeerId : " << key_item->PeerId() << std::endl; + std::cerr << "GrpId: " << key_item->grpId << std::endl; + std::cerr << "Got key Item" << std::endl; +#endif + if(key_item->key.keyFlags & RSTLV_KEY_TYPE_FULL){ + + gid = key_item->grpId; + + // add key if user is subscribed if not store it until user subscribes + + if(locked_updateGroupPublishKey(it->second, key_item)){ + + mPubKeyAvailableGrpId.insert(key_item->grpId); + locked_notifyGroupChanged(it->second, GRP_LOAD_KEY, false); + + // keep key if user not subscribed + if(it->second.flags & RS_DISTRIB_SUBSCRIBED){ + + delete key_item; + + }else{ + + // make sure keys does not exist in recieved list + if(mRecvdPubKeys.find(gid) == mRecvdPubKeys.end()){ + + // id key as shared so on loadlist sends back to mRecvdPubKeys + key_item->key.keyFlags |= RSTLV_KEY_TYPE_SHARED; + mRecvdPubKeys.insert(std::pair(key_item->grpId, key_item)); + + } + } + + } + } + else{ + std::cerr << "p3GroupDistrib::locked_receiveKeys():" << "Not full public key" + << "Deleting item"<< std::endl; + + delete key_item; + } + } + else{ + delete item; + } + } + + + + + RsStackMutex stack(distribMtx); + + // indicate config changed and also record the groups keys received for + if(!mRecvdPubKeys.empty()) + IndicateConfigChanged(); + + return; + + + } + + +std::string p3GroupDistrib::publishMsg(RsDistribMsg *msg, bool personalSign) +{ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishMsg()" << std::endl; + msg->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + /* extract grpId */ + std::string grpId = msg->grpId; + std::string msgId; + + RsDistribSignedMsg *signedMsg = NULL; + + /* ensure Group exists */ + { /* STACK MUTEX */ + + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + GroupInfo *gi = locked_getGroupInfo(grpId); + if (!gi) + { + #ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishMsg() No Group"; + std::cerr << std::endl; + #endif + return msgId; + } + + /******************* FIND KEY ******************************/ + if (!locked_choosePublishKey(*gi)) + { + #ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishMsg() No Publish Key(1)"; + std::cerr << std::endl; + #endif + return msgId; + } + + /* find valid publish_key */ + EVP_PKEY *publishKey = NULL; + std::map::iterator kit; + kit = gi->publishKeys.find(gi->publishKeyId); + if (kit != gi->publishKeys.end()) + { + publishKey = kit->second.key; + } + + if (!publishKey) + { + #ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishMsg() No Publish Key"; + std::cerr << std::endl; + #endif + /* no publish Key */ + return msgId; + } + + /******************* FIND KEY ******************************/ + + signedMsg = new RsDistribSignedMsg(); + + RsSerialType *serialType = createSerialiser(); + uint32_t size = serialType->size(msg); + char *data = new char[size]; + serialType->serialise(msg, data, &size); + + char *out_data = NULL; + uint32_t out_size = 0; + + // encrypt data if group is private + + if(gi->grpFlags & RS_DISTRIB_ENCRYPTED){ + + if(encrypt((void*&)out_data, (int&)out_size, (void*&)data, (int)size, grpId)){ + + delete[] data; + }else{ + delete[] data; + delete signedMsg; + delete serialType; + return msgId; + } + + }else + { + out_data = data; + out_size = size; + } + + signedMsg->packet.setBinData(out_data, out_size); + + /* sign Packet */ + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_SignInit(mdctx, EVP_sha1()); + EVP_SignUpdate(mdctx, out_data, out_size); + + unsigned int siglen = EVP_PKEY_size(publishKey); + unsigned char sigbuf[siglen]; + EVP_SignFinal(mdctx, sigbuf, &siglen, publishKey); + + /* save signature */ + signedMsg->publishSignature.signData.setBinData(sigbuf, siglen); + signedMsg->publishSignature.keyId = gi->publishKeyId; + + bool ok = true; + + if (personalSign) + { + unsigned int siglen = MAX_GPG_SIGNATURE_SIZE; + unsigned char sigbuf[siglen]; + if (AuthGPG::getAuthGPG()->SignDataBin(out_data, out_size, sigbuf, &siglen)) + { + signedMsg->personalSignature.signData.setBinData(sigbuf, siglen); + signedMsg->personalSignature.keyId = AuthGPG::getAuthGPG()->getGPGOwnId(); + } else { + ok = false; + } + } + + /* clean up */ + delete serialType; + EVP_MD_CTX_destroy(mdctx); + delete[] out_data; + + if (ok == false) { + delete signedMsg; + return msgId; + } + + } /* END STACK MUTEX */ + + /* extract Ids from publishSignature */ + signedMsg->msgId = getBinDataSign( + signedMsg->publishSignature.signData.bin_data, + signedMsg->publishSignature.signData.bin_len); + signedMsg->grpId = grpId; + signedMsg->timestamp = msg->timestamp; + + msgId = signedMsg->msgId; + + /* delete original msg */ + delete msg; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::publishMsg() Created SignedMsg:"; + std::cerr << std::endl; + signedMsg->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + /* load proper - + * If we pretend it is coming from an alternative source + * it'll automatically get published with other msgs + */ + + signedMsg->PeerId(mOwnId); + loadMsg(signedMsg, mOwnId, false, false); + + /* done */ + return msgId; +} + + + + +/********************* Overloaded Functions **************************/ + +bool p3GroupDistrib::validateDistribGrp(RsDistribGrp *newGrp) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::validateDistribGrp()"; + std::cerr << std::endl; +#endif + + /* check signature */ + RsSerialType *serialType = new RsDistribSerialiser(); + + + + /* copy out signature (shallow copy) */ + RsTlvKeySignature tmpSign = newGrp->adminSignature; + unsigned char *sigbuf = (unsigned char *) tmpSign.signData.bin_data; + unsigned int siglen = tmpSign.signData.bin_len; + + /* clear signature */ + newGrp->adminSignature.ShallowClear(); + + uint32_t size = serialType->size(newGrp); + char* data = new char[size]; + + serialType->serialise(newGrp, data, &size); + + + const unsigned char *keyptr = (const unsigned char *) newGrp->adminKey.keyData.bin_data; + long keylen = newGrp->adminKey.keyData.bin_len; + + /* extract admin key */ + RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); + + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(key, rsakey); + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_VerifyInit(mdctx, EVP_sha1()); + EVP_VerifyUpdate(mdctx, data, size); + int ans = EVP_VerifyFinal(mdctx, sigbuf, siglen, key); + + + /* restore signature */ + newGrp->adminSignature = tmpSign; + tmpSign.ShallowClear(); + + /* clean up */ + EVP_PKEY_free(key); + delete serialType; + EVP_MD_CTX_destroy(mdctx); + delete[] data; + + if (ans == 1) + return true; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::validateDistribGrp() Signature invalid"; + std::cerr << std::endl; +#endif + return false; +} + + +bool p3GroupDistrib::locked_checkGroupInfo(GroupInfo &info, RsDistribGrp *newGrp) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupInfo()"; + std::cerr << std::endl; +#endif + /* groupInfo */ + + /* If adminKey is the same and + * timestamp is <= timestamp, or not an update (info edit) + * then just discard it. + */ + + if (info.grpId != newGrp->grpId) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupInfo() Failed GrpId Wrong"; + std::cerr << std::endl; +#endif + return false; + } + + if ((info.distribGroup) && + ((info.distribGroup->timestamp <= newGrp->timestamp) && !(newGrp->grpFlags & RS_DISTRIB_UPDATE))) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupInfo() Group Data Old/Same"; + std::cerr << std::endl; +#endif + /* old or same info -> drop it */ + return false; + } + + /* otherwise validate it */ + return validateDistribGrp(newGrp); +} + + +/* return false - to cleanup (delete group) afterwards, + * true - we've kept the data + */ +bool p3GroupDistrib::locked_updateGroupInfo(GroupInfo &info, RsDistribGrp *newGrp) +{ + /* new group has been validated already + * update information. + */ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupInfo()"; + std::cerr << std::endl; +#endif + + if (info.distribGroup) + { + delete info.distribGroup; + } + + if (info.grpIcon.pngImageData != NULL){ + delete[] info.grpIcon.pngImageData; + info.grpIcon.imageSize = 0; + } + + info.distribGroup = newGrp; + + /* copy details */ + info.grpName = newGrp->grpName; + info.grpDesc = newGrp->grpDesc; + info.grpCategory = newGrp->grpCategory; + info.grpFlags = newGrp->grpFlags; + + if((newGrp->grpPixmap.binData.bin_data != NULL) && (newGrp->grpPixmap.binData.bin_len > 0)){ + info.grpIcon.pngImageData = new unsigned char[newGrp->grpPixmap.binData.bin_len]; + + memcpy(info.grpIcon.pngImageData, newGrp->grpPixmap.binData.bin_data, + newGrp->grpPixmap.binData.bin_len*sizeof(unsigned char)); + + info.grpIcon.imageSize = newGrp->grpPixmap.binData.bin_len; + }else{ + info.grpIcon.pngImageData = NULL; + info.grpIcon.imageSize = 0; + } + + /* pop already calculated */ + /* last post handled seperately */ + + locked_checkGroupKeys(info); + + /* if we are subscribed to the group -> then we need to republish */ + if (info.flags & RS_DISTRIB_SUBSCRIBED) + { + mGroupsRepublish = true; + } + + return true; +} + + +bool p3GroupDistrib::locked_editGroup(std::string grpId, GroupInfo& gi){ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_editGroup() " << grpId << std::endl; +#endif + + GroupInfo* gi_curr = locked_getGroupInfo(grpId); + + if(gi_curr == NULL){ + + std::cerr << "p3GroupDistrib::locked_editGroup() Failed, group does not exist " << grpId + << std::endl; + return false; + } + + if(!(gi_curr->flags & RS_DISTRIB_ADMIN)) + return false; + + + gi_curr->grpName = gi.grpName; + gi_curr->distribGroup->grpName = gi_curr->grpName; + gi_curr->grpDesc = gi.grpDesc; + gi_curr->distribGroup->grpDesc = gi_curr->grpDesc; + + if((gi.grpIcon.imageSize != 0) && gi.grpIcon.pngImageData != NULL){ + + if((gi_curr->distribGroup->grpPixmap.binData.bin_data != NULL) && + (gi_curr->distribGroup->grpPixmap.binData.bin_len != 0)) + gi_curr->distribGroup->grpPixmap.binData.TlvClear(); + + gi_curr->distribGroup->grpPixmap.binData.bin_data = gi_curr->grpIcon.pngImageData; + gi_curr->distribGroup->grpPixmap.binData.bin_len = gi_curr->grpIcon.imageSize; + + gi_curr->grpIcon.imageSize = gi.grpIcon.imageSize; + gi_curr->grpIcon.pngImageData = gi.grpIcon.pngImageData; + + + } + + // set new timestamp for grp + gi_curr->distribGroup->timestamp = time(NULL); + + // create new signature for group + + EVP_PKEY *key_admin = gi_curr->adminKey.key; + gi_curr->distribGroup->adminSignature.TlvClear(); + RsSerialType *serialType = new RsDistribSerialiser(); + uint32_t size = serialType->size(gi_curr->distribGroup); + char* data = new char[size]; + serialType->serialise(gi_curr->distribGroup, data, &size); + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + EVP_SignInit(mdctx, EVP_sha1()); + EVP_SignUpdate(mdctx, data, size); + + unsigned int siglen = EVP_PKEY_size(key_admin); + unsigned char sigbuf[siglen]; + EVP_SignFinal(mdctx, sigbuf, &siglen, key_admin); + + /* save signature */ + gi_curr->distribGroup->adminSignature.signData.setBinData(sigbuf, siglen); + gi_curr->distribGroup->adminSignature.keyId = grpId; + + mGroupsChanged = true; + gi_curr->grpChanged = true; + mGroupsRepublish = true; + + // this is removed afterwards + gi_curr->distribGroup->grpFlags |= RS_DISTRIB_UPDATE; + + delete[] data; + + return true; +} + +bool p3GroupDistrib::locked_checkGroupKeys(GroupInfo &info) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys()"; + std::cerr << "GrpId: " << info.grpId; + std::cerr << std::endl; +#endif + + /* iterate through publish keys - check that they exist in distribGrp, or delete */ + RsDistribGrp *grp = info.distribGroup; + + std::list removeKeys; + std::map::iterator it; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() Checking if Expanded Keys still Exist"; + std::cerr << std::endl; +#endif + + for(it = info.publishKeys.begin(); it != info.publishKeys.end(); it++) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() Publish Key: " << it->first; +#endif + /* check for key in distribGrp */ + if (grp->publishKeys.keys.end() == grp->publishKeys.keys.find(it->first)) + { + /* remove publishKey */ + removeKeys.push_back(it->first); +#ifdef DISTRIB_DEBUG + std::cerr << " Old -> to Remove" << std::endl; +#endif + + } + +#ifdef DISTRIB_DEBUG + std::cerr << " Ok" << std::endl; +#endif + + } + + while(removeKeys.size() > 0) + { + std::string rkey = removeKeys.front(); + removeKeys.pop_front(); +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() Removing Key: " << rkey; + std::cerr << std::endl; +#endif + + it = info.publishKeys.find(rkey); + EVP_PKEY_free(it->second.key); + info.publishKeys.erase(it); + } + + /* iterate through distribGrp list - expanding any missing keys */ + std::map::iterator dit; + for(dit = grp->publishKeys.keys.begin(); dit != grp->publishKeys.keys.end(); dit++) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() Checking for New Keys: KeyId: " << dit->first; + std::cerr << std::endl; +#endif + + it = info.publishKeys.find(dit->first); + if (it == info.publishKeys.end()) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() Key Missing - Expand"; + std::cerr << std::endl; +#endif + + /* create a new expanded public key */ + RSA *rsa_pub = extractPublicKey(dit->second); + if (!rsa_pub) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() Failed to Expand Key"; + std::cerr << std::endl; +#endif + continue; + } + + GroupKey newKey; + newKey.keyId = dit->first; + newKey.type = RSTLV_KEY_TYPE_PUBLIC_ONLY | (dit->second.keyFlags & RSTLV_KEY_DISTRIB_MASK); + newKey.startTS = dit->second.startTS; + newKey.endTS = dit->second.endTS; + + newKey.key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(newKey.key, rsa_pub); + + info.publishKeys[newKey.keyId] = newKey; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() Expanded Key: " << dit->first; + std::cerr << "Key Type: " << newKey.type; + std::cerr << std::endl; + std::cerr << "Start: " << newKey.startTS; + std::cerr << std::endl; + std::cerr << "End: " << newKey.endTS; + std::cerr << std::endl; +#endif + } + } + + /* now check admin key */ + if ((info.adminKey.keyId == "") || (!info.adminKey.key)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() Must Expand AdminKey Too"; + std::cerr << std::endl; +#endif + + /* must expand admin key too */ + RSA *rsa_pub = extractPublicKey(grp->adminKey); + if (rsa_pub) + { + info.adminKey.keyId = grp->adminKey.keyId; + info.adminKey.type = RSTLV_KEY_TYPE_PUBLIC_ONLY & RSTLV_KEY_DISTRIB_ADMIN; + info.adminKey.startTS = grp->adminKey.startTS; + info.adminKey.endTS = grp->adminKey.endTS; + + info.adminKey.key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(info.adminKey.key, rsa_pub); +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() AdminKey Expanded"; + std::cerr << std::endl; +#endif + } + else + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkGroupKeys() ERROR Expandng AdminKey"; + std::cerr << std::endl; +#endif + } + } + + return true; +} + + + + +bool p3GroupDistrib::locked_updateGroupAdminKey(GroupInfo &info, RsDistribGrpKey *newKey) +{ + /* so firstly - check that the KeyId matches something in the group */ + const std::string &keyId = newKey->key.keyId; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupAdminKey() grpId: " << keyId; + std::cerr << std::endl; +#endif + + + if (keyId != info.grpId) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupAdminKey() Id mismatch - ERROR"; + std::cerr << std::endl; +#endif + + return false; + } + + if (!(newKey->key.keyFlags & RSTLV_KEY_TYPE_FULL)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupAdminKey() Key not Full - Ignore"; + std::cerr << std::endl; +#endif + + /* not a full key -> ignore */ + return false; + } + + if (info.adminKey.type & RSTLV_KEY_TYPE_FULL) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupAdminKey() Already have Full Key - Ignore"; + std::cerr << std::endl; +#endif + + /* if we have full key already - ignore */ + return true; + } + + /* need to update key */ + RSA *rsa_priv = extractPrivateKey(newKey->key); + + if (!rsa_priv) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupAdminKey() Extract Key failed - ERROR"; + std::cerr << std::endl; +#endif + + return false; + } + + /* validate they are a matching pair */ + std::string realkeyId = getRsaKeySign(rsa_priv); + if ((1 != RSA_check_key(rsa_priv)) || (realkeyId != keyId)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupAdminKey() Validate Key Failed - ERROR"; + std::cerr << std::endl; +#endif + + /* clean up */ + RSA_free(rsa_priv); + return false; + } + + /* add it in */ + EVP_PKEY *evp_pkey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(evp_pkey, rsa_priv); + + EVP_PKEY_free(info.adminKey.key); + info.adminKey.key = evp_pkey; + info.adminKey.type = RSTLV_KEY_TYPE_FULL | RSTLV_KEY_DISTRIB_ADMIN; + + info.flags |= RS_DISTRIB_ADMIN; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupAdminKey() Success"; + std::cerr << std::endl; +#endif + + return true; +} + + +bool p3GroupDistrib::locked_updateGroupPublishKey(GroupInfo &info, RsDistribGrpKey *newKey) +{ + /* so firstly - check that the KeyId matches something in the group */ + const std::string &keyId = newKey->key.keyId; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupPublishKey() grpId: " << info.grpId << " keyId: " << keyId; + std::cerr << std::endl; +#endif + + + std::map::iterator it; + it = info.publishKeys.find(keyId); + if (it == info.publishKeys.end()) + { + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupPublishKey() key not Found - Ignore"; + std::cerr << std::endl; +#endif + + /* no key -> ignore */ + return false; + } + + if (!(newKey->key.keyFlags & RSTLV_KEY_TYPE_FULL)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupPublishKey() not FullKey - Ignore"; + std::cerr << std::endl; +#endif + + /* not a full key -> ignore */ + return false; + } + + if (it->second.type & RSTLV_KEY_TYPE_FULL) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupPublishKey() already have FullKey - Ignore"; + std::cerr << std::endl; +#endif + + /* if we have full key already - ignore */ + return true; + } + + /* need to update key */ + RSA *rsa_priv = extractPrivateKey(newKey->key); + + if (!rsa_priv) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupPublishKey() Private Extract Failed - ERROR"; + std::cerr << std::endl; +#endif + + return false; + } + + /* validate they are a matching pair */ + std::string realkeyId = getRsaKeySign(rsa_priv); + if ((1 != RSA_check_key(rsa_priv)) || (realkeyId != keyId)) + { + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupPublishKey() Validate Private Key failed - ERROR"; + std::cerr << std::endl; +#endif + + /* clean up */ + RSA_free(rsa_priv); + return false; + } + + /* add it in */ + EVP_PKEY *evp_pkey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(evp_pkey, rsa_priv); + + EVP_PKEY_free(it->second.key); + it->second.key = evp_pkey; + it->second.type &= (~RSTLV_KEY_TYPE_PUBLIC_ONLY); + it->second.type |= RSTLV_KEY_TYPE_FULL; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_updateGroupPublishKey() Success"; + std::cerr << std::endl; + std::cerr << "Key ID: " << it->first; + std::cerr << std::endl; + std::cerr << "Key Type: " << it->second.type; + std::cerr << std::endl; + std::cerr << "Start: " << it->second.startTS; + std::cerr << std::endl; + std::cerr << "End: " << it->second.endTS; + std::cerr << std::endl; +#endif + + info.flags |= RS_DISTRIB_PUBLISH; + + /* if we have updated, we are subscribed, and it is a public key */ + if ((info.flags & RS_DISTRIB_SUBSCRIBED) && + (it->second.type & RSTLV_KEY_DISTRIB_PUBLIC)) + { + mGroupsRepublish = true; + } + + return true; +} + + +bool p3GroupDistrib::locked_choosePublishKey(GroupInfo &info) +{ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_choosePublishKey()"; + std::cerr << std::endl; +#endif + time_t now = time(NULL); + + /******************* CHECK CURRENT KEY ******************************/ + /* if current key is valid -> okay */ + + std::map::iterator kit; + kit = info.publishKeys.find(info.publishKeyId); + if (kit != info.publishKeys.end()) + { + if ((kit->second.type & RSTLV_KEY_TYPE_FULL) && + (now < kit->second.endTS) && (now > kit->second.startTS)) + { + /* key is okay */ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_choosePublishKey() Current Key is Okay"; + std::cerr << std::endl; +#endif + return true; + } + } + + /******************* FIND KEY ******************************/ + std::string bestKey = ""; + time_t bestEndTime = 0; + + for(kit = info.publishKeys.begin(); kit != info.publishKeys.end(); kit++) + { + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_choosePublishKey() Found Key: "; + std::cerr << kit->first << " type: " << kit->second.type; + std::cerr << std::endl; +#endif + + if (kit->second.type & RSTLV_KEY_TYPE_FULL) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_choosePublishKey() Found FULL Key: "; + std::cerr << kit->first << " startTS: " << kit->second.startTS; + std::cerr << " endTS: " << kit->second.startTS; + std::cerr << " now: " << now; + std::cerr << std::endl; +#endif + if ((now < kit->second.endTS) && (now >= kit->second.startTS)) + { + if (kit->second.endTS > bestEndTime) + { + bestKey = kit->first; + bestEndTime = kit->second.endTS; +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_choosePublishKey() Better Key: "; + std::cerr << kit->first; + std::cerr << std::endl; +#endif + } + } + } + } + + if (bestEndTime == 0) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_choosePublishKey() No Valid Key"; + std::cerr << std::endl; +#endif + return false; + } + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_choosePublishKey() Best Key is: " << bestKey; + std::cerr << std::endl; +#endif + + info.publishKeyId = bestKey; + return true; +} + + +/********************/ + +bool p3GroupDistrib::locked_validateDistribSignedMsg(GroupInfo &info, RsDistribSignedMsg *newMsg) +{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg()"; + std::cerr << std::endl; + std::cerr << "GroupInfo -> distribGrp:"; + std::cerr << std::endl; + info.distribGroup->print(std::cerr, 10); + std::cerr << std::endl; + std::cerr << "RsDistribSignedMsg: "; + std::cerr << std::endl; + newMsg->print(std::cerr, 10); + std::cerr << std::endl; +#endif + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() publish KeyId: " << newMsg->publishSignature.keyId << std::endl; + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() personal KeyId: " << newMsg->personalSignature.keyId << std::endl; +#endif + + /********************* check signature *******************/ + + /* find the right key */ + RsTlvSecurityKeySet &keyset = info.distribGroup->publishKeys; + + std::map::iterator kit; + kit = keyset.keys.find(newMsg->publishSignature.keyId); + + if (kit == keyset.keys.end()) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Missing Publish Key"; + std::cerr << std::endl; +#endif + return false; + } + + /* check signature timeperiod */ + if ((newMsg->timestamp < kit->second.startTS) || + (newMsg->timestamp > kit->second.endTS)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() TS out of range"; + std::cerr << std::endl; +#endif + return false; + } + + /* decode key */ + const unsigned char *keyptr = (const unsigned char *) kit->second.keyData.bin_data; + long keylen = kit->second.keyData.bin_len; + unsigned int siglen = newMsg->publishSignature.signData.bin_len; + unsigned char *sigbuf = (unsigned char *) newMsg->publishSignature.signData.bin_data; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Decode Key"; + std::cerr << " keylen: " << keylen << " siglen: " << siglen; + std::cerr << std::endl; +#endif + + /* extract admin key */ + RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); + + if (!rsakey) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg()"; + std::cerr << " Invalid RSA Key"; + std::cerr << std::endl; + + unsigned long err = ERR_get_error(); + std::cerr << "RSA Load Failed .... CODE(" << err << ")" << std::endl; + std::cerr << ERR_error_string(err, NULL) << std::endl; + + kit->second.print(std::cerr, 10); +#endif + } + + + EVP_PKEY *signKey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(signKey, rsakey); + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_VerifyInit(mdctx, EVP_sha1()); + EVP_VerifyUpdate(mdctx, newMsg->packet.bin_data, newMsg->packet.bin_len); + int signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); + + /* clean up */ + EVP_PKEY_free(signKey); + EVP_MD_CTX_destroy(mdctx); + + /* now verify Personal signature */ + if ((signOk == 1) && ((info.grpFlags & RS_DISTRIB_AUTHEN_MASK) & RS_DISTRIB_AUTHEN_REQ)) + { + unsigned int personalsiglen = + newMsg->personalSignature.signData.bin_len; + unsigned char *personalsigbuf = (unsigned char *) + newMsg->personalSignature.signData.bin_data; + + RsPeerDetails signerDetails; + std::string gpg_fpr; + if (AuthGPG::getAuthGPG()->getGPGDetails(newMsg->personalSignature.keyId, signerDetails)) + { + gpg_fpr = signerDetails.fpr; + } + + bool gpgSign = AuthGPG::getAuthGPG()->VerifySignBin( + newMsg->packet.bin_data, newMsg->packet.bin_len, + personalsigbuf, personalsiglen, gpg_fpr); + if (gpgSign) { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Success for gpg signature." << std::endl; +#endif + signOk = 1; + } else { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Fail for gpg signature." << std::endl; +#endif + signOk = 0; + } + } + + if (signOk == 1) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Signature OK"; + std::cerr << std::endl; +#endif + return true; + } + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Signature invalid"; + std::cerr << std::endl; +#endif + + return false; +} + + /* deserialise RsDistribSignedMsg */ +RsDistribMsg *p3GroupDistrib::unpackDistribSignedMsg(RsDistribSignedMsg *newMsg) +{ + RsSerialType *serialType = createSerialiser(); + uint32_t size = newMsg->packet.bin_len; + RsDistribMsg *distribMsg = (RsDistribMsg *) + serialType->deserialise(newMsg->packet.bin_data, &size); + + if (distribMsg) + { + + /* transfer data that is not in the serialiser */ + distribMsg->msgId = newMsg->msgId; + + /* Full copies required ? */ + + distribMsg->publishSignature.keyId = newMsg->publishSignature.keyId; + distribMsg->publishSignature.signData.setBinData( + newMsg->publishSignature.signData.bin_data, + newMsg->publishSignature.signData.bin_len); + + distribMsg->personalSignature.keyId = newMsg->personalSignature.keyId; + distribMsg->personalSignature.signData.setBinData( + newMsg->personalSignature.signData.bin_data, + newMsg->personalSignature.signData.bin_len); + } + + delete serialType; + + return distribMsg; +} + +void p3GroupDistrib::getGrpListPubKeyAvailable(std::list& grpList) +{ + RsStackMutex stack(distribMtx); + std::set::const_iterator cit = mPubKeyAvailableGrpId.begin(); + + for(; cit != mPubKeyAvailableGrpId.end(); cit++) + grpList.push_back(*cit); + + return; +} + +bool p3GroupDistrib::locked_checkDistribMsg( + GroupInfo &gi, RsDistribMsg *msg) +{ + + /* check timestamp */ + time_t now = time(NULL); + uint32_t min = now - mStorePeriod; + uint32_t max = now + GROUP_MAX_FWD_OFFSET; + + if ((msg->timestamp < min) || (msg->timestamp > max)) + { +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::locked_checkDistribMsg() TS out of range"; + std::cerr << std::endl; + std::cerr << "p3GroupDistrib::locked_checkDistribMsg() msg->timestamp: " << msg->timestamp; + std::cerr << std::endl; + std::cerr << "p3GroupDistrib::locked_checkDistribMsg() = " << now - msg->timestamp << " secs ago"; + std::cerr << std::endl; + std::cerr << "p3GroupDistrib::locked_checkDistribMsg() max TS: " << max; + std::cerr << std::endl; + std::cerr << "p3GroupDistrib::locked_checkDistribMsg() min TS: " << min; + std::cerr << std::endl; +#endif + /* if outside range -> remove */ + return false; + } + + /* check filters */ + + return true; +} + + + /* now update parents TS */ +bool p3GroupDistrib::locked_updateChildTS(GroupInfo &gi, RsDistribMsg *msg) +{ + /* find all parents - update timestamp */ + time_t updateTS = msg->timestamp; + msg->childTS = updateTS; + + while("" != msg->parentId) + { + std::string parentId = msg->parentId; + + std::map::iterator mit; + if (gi.msgs.end() == (mit = gi.msgs.find(parentId))) + { + /* not found - abandon (check for dummyMsgs first) */ + return locked_updateDummyChildTS(gi, parentId, updateTS); + + } + RsDistribMsg *parent = mit->second; + if ((!parent) || (parent->childTS > updateTS)) + { + /* we're too old - give up! */ + return true; + } + + /* update timestamp */ + parent->childTS = updateTS; + msg = parent; + } + return false ; +} + + + + + + + +/***** DEBUG *****/ + +void p3GroupDistrib::printGroups(std::ostream &out) +{ + /* iterate through all the groups */ + std::map::iterator git; + for(git = mGroups.begin(); git != mGroups.end(); git++) + { + out << "GroupId: " << git->first << std::endl; + out << "Group Details: " << std::endl; + out << git->second; + out << std::endl; + + std::map::iterator mit; + for(mit = git->second.msgs.begin(); + mit != git->second.msgs.end(); mit++) + { + out << "MsgId: " << mit->first << std::endl; + out << "Message Details: " << std::endl; + mit->second->print(out, 10); + out << std::endl; + } + } +} + +bool p3GroupDistrib::encrypt(void *& out, int& outlen, const void *in, int inlen, std::string grpId) +{ + + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::decrypt() " << std::endl; +#endif + + GroupInfo* gi = locked_getGroupInfo(grpId); + RSA *rsa_publish_pub = NULL; + EVP_PKEY *public_key = NULL, *private_key = NULL; + + if(gi == NULL){ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::decrypt(): Cannot find group, grpId " << grpId + << std::endl; +#endif + return false; + + } + + /* generate public key */ + + std::map::iterator kit; + + for(kit = gi->publishKeys.begin(); kit != gi->publishKeys.end(); kit++ ){ + + // Does not allow for possibility of different keys + + if((kit->second.type & RSTLV_KEY_TYPE_FULL) && (kit->second.key->type == EVP_PKEY_RSA)){ + private_key = kit->second.key; + break; + } + + } + + if(kit == gi->publishKeys.end()){ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::encrypt(): Cannot find full key, grpId " << grpId + << std::endl; +#endif + return false; + } + + + RSA* rsa_publish = EVP_PKEY_get1_RSA(private_key); + rsa_publish_pub = RSAPublicKey_dup(rsa_publish); + + + if(rsa_publish_pub != NULL){ + public_key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(public_key, rsa_publish_pub); + }else{ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::encrypt(): Could not generate publish key " << grpId + << std::endl; +#endif + return false; + } + + EVP_CIPHER_CTX ctx; + int eklen, net_ekl; + unsigned char *ek; + unsigned char iv[EVP_MAX_IV_LENGTH]; + EVP_CIPHER_CTX_init(&ctx); + int out_currOffset = 0; + int out_offset = 0; + + int max_evp_key_size = EVP_PKEY_size(public_key); + ek = (unsigned char*)malloc(max_evp_key_size); + const EVP_CIPHER *cipher = EVP_aes_128_cbc(); + int cipher_block_size = EVP_CIPHER_block_size(cipher); + int size_net_ekl = sizeof(net_ekl); + + int max_outlen = inlen + cipher_block_size + EVP_MAX_IV_LENGTH + max_evp_key_size + size_net_ekl; + + // intialize context and send store encrypted cipher in ek + if(!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &public_key, 1)) return false; + + // now assign memory to out accounting for data, and cipher block size, key length, and key length val + out = new unsigned char[inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH]; + + net_ekl = htonl(eklen); + memcpy((unsigned char*)out + out_offset, &net_ekl, size_net_ekl); + out_offset += size_net_ekl; + + memcpy((unsigned char*)out + out_offset, ek, eklen); + out_offset += eklen; + + memcpy((unsigned char*)out + out_offset, iv, EVP_MAX_IV_LENGTH); + out_offset += EVP_MAX_IV_LENGTH; + + // now encrypt actual data + if(!EVP_SealUpdate(&ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen)) return false; + + // move along to partial block space + out_offset += out_currOffset; + + // add padding + if(!EVP_SealFinal(&ctx, (unsigned char*) out + out_offset, &out_currOffset)) return false; + + // move to end + out_offset += out_currOffset; + + // make sure offset has not gone passed valid memory bounds + if(out_offset > max_outlen) return false; + + // free encrypted key data + free(ek); + + outlen = out_offset; + return true; + + delete[] ek; + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::encrypt() finished with outlen : " << outlen << std::endl; +#endif + + return true; +} + +bool p3GroupDistrib::decrypt(void *& out, int& outlen, const void *in, int inlen, std::string grpId) +{ + +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::decrypt() " << std::endl; +#endif + + GroupInfo* gi = locked_getGroupInfo(grpId); + EVP_PKEY *private_key; + + if(gi == NULL){ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::decrypt(): Cannot find group, grpId " << grpId + << std::endl; +#endif + return false; + } + + std::map::iterator kit; + + for(kit = gi->publishKeys.begin(); kit != gi->publishKeys.end(); kit++ ){ + + + if((kit->second.type & RSTLV_KEY_TYPE_FULL) && (kit->second.key->type == EVP_PKEY_RSA)){ + private_key = kit->second.key; + break; + } + } + + if(kit == gi->publishKeys.end()){ +#ifdef DISTRIB_DEBUG + std::cerr << "p3GroupDistrib::decrypt(): Cannot find full key, grpId " << grpId + << std::endl; +#endif + return false; + } + + EVP_CIPHER_CTX ctx; + int eklen = 0, net_ekl = 0; + unsigned char *ek = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + ek = (unsigned char*)malloc(EVP_PKEY_size(private_key)); + EVP_CIPHER_CTX_init(&ctx); + + int in_offset = 0, out_currOffset = 0; + int size_net_ekl = sizeof(net_ekl); + + memcpy(&net_ekl, (unsigned char*)in, size_net_ekl); + eklen = ntohl(net_ekl); + in_offset += size_net_ekl; + + memcpy(ek, (unsigned char*)in + in_offset, eklen); + in_offset += eklen; + + memcpy(iv, (unsigned char*)in + in_offset, EVP_MAX_IV_LENGTH); + in_offset += EVP_MAX_IV_LENGTH; + + const EVP_CIPHER* cipher = EVP_aes_128_cbc(); + + if(!EVP_OpenInit(&ctx, cipher, ek, eklen, iv, private_key)) return false; + + out = new unsigned char[inlen - in_offset]; + + if(!EVP_OpenUpdate(&ctx, (unsigned char*) out, &out_currOffset, (unsigned char*)in + in_offset, inlen - in_offset)) return false; + + in_offset += out_currOffset; + outlen += out_currOffset; + + if(!EVP_OpenFinal(&ctx, (unsigned char*)out + out_currOffset, &out_currOffset)) return false; + + outlen += out_currOffset; + + free(ek); + + return true; +} + + +std::ostream &operator<<(std::ostream &out, const GroupInfo &info) +{ + /* print Group Info */ + out << "GroupInfo: " << info.grpId << std::endl; + out << "sources [" << info.sources.size() << "]: "; + + std::list::const_iterator sit; + for(sit = info.sources.begin(); sit != info.sources.end(); sit++) + { + out << " " << *sit; + } + out << std::endl; + + out << " Message Count: " << info.msgs.size() << std::endl; + + std::string grpName(info.grpName.begin(), info.grpName.end()); + std::string grpDesc(info.grpDesc.begin(), info.grpDesc.end()); + + out << "Group Name: " << grpName << std::endl; + out << "Group Desc: " << grpDesc << std::endl; + out << "Group Flags: " << info.flags << std::endl; + out << "Group Pop: " << info.pop << std::endl; + out << "Last Post: " << info.lastPost << std::endl; + + out << "PublishKeyId:" << info.publishKeyId << std::endl; + + out << "Published RsDistribGrp: " << std::endl; + if (info.distribGroup) + { + info.distribGroup->print(out, 10); + } + else + { + out << "No RsDistribGroup Object" << std::endl; + } + + return out; +} + +void p3GroupDistrib::locked_notifyGroupChanged(GroupInfo &info, uint32_t flags, bool historical) +{ + mGroupsChanged = true; + info.grpChanged = true; +} + + +bool p3GroupDistrib::groupsChanged(std::list &groupIds) +{ + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + + /* iterate through all groups and get changed list */ + if (!mGroupsChanged) + return false; + + std::map::iterator it; + for(it = mGroups.begin(); it != mGroups.end(); it++) + { + if (it->second.grpChanged) + { + groupIds.push_back(it->first); + it->second.grpChanged = false; + } + } + + mGroupsChanged = false; + return true; +} + + + +/***************************************************************************************/ +/***************************************************************************************/ + /******************* Handle Missing Messages ***********************************/ +/***************************************************************************************/ +/***************************************************************************************/ + +/* Find missing messages */ + + + +/* LOGIC: + * + * dummy(grpId, threadId, parentId, msgId); + * + * add new msg.... + * - search for threadId. + * - if missing add thread head: dummy(grpId, threadId, NULL, threadId). + * + * - search for parentId + * - if = threadId, we just added it (ok). + * - if missing add dummy(grpId, threadId, threadId, parentId). + * + * - check for matching dummy msgId. + * - if yes, delete. + * + */ + +RsDistribDummyMsg::RsDistribDummyMsg( std::string tId, std::string pId, std::string mId, uint32_t ts) +:threadId(tId), parentId(pId), msgId(mId), timestamp(ts), childTS(ts) +{ + return; +} + +std::ostream &operator<<(std::ostream &out, const RsDistribDummyMsg &msg) +{ + out << "DummyMsg(" << msg.threadId << "," << msg.parentId << "," << msg.msgId << ")"; + return out; +} + + + +bool p3GroupDistrib::locked_CheckNewMsgDummies(GroupInfo &grp, RsDistribMsg *msg, std::string id, bool historical) +{ + std::string threadId = msg->threadId; + std::string parentId = msg->parentId; + std::string msgId = msg->msgId; + +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies(grpId:" << grp.grpId << ", threadId: " << threadId; + std::cerr << ", parentId:" << parentId << ", msgId: " << msgId << ")"; + std::cerr << std::endl; +#endif + +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies() Pre Printout"; + std::cerr << std::endl; + locked_printDummyMsgs(grp); +#endif + + + /* search for threadId */ + if (threadId != "") + { + std::map::iterator tit = grp.msgs.find(threadId); + + if (tit == grp.msgs.end()) // not there! + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies() No ThreadId Msg, Adding DummyMsg"; + std::cerr << std::endl; +#endif + locked_addDummyMsg(grp, threadId, "", threadId, msg->timestamp); + } + else + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies() Found ThreadId Msg"; + std::cerr << std::endl; +#endif + } + } + + if (parentId != "") + { + /* search for parentId */ + std::map::iterator pit = grp.msgs.find(parentId); + + if (pit == grp.msgs.end()) // not there! + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies() No ParentId Msg, Adding DummyMsg"; + std::cerr << std::endl; +#endif + locked_addDummyMsg(grp, threadId, threadId, parentId, msg->timestamp); + } + else + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies() Found ParentId Msg"; + std::cerr << std::endl; +#endif + } + } + +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies() Checking for DummyMsg"; + std::cerr << std::endl; +#endif + + /* remove existing dummy */ + locked_clearDummyMsg(grp, msgId); + + +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_CheckNewMsgDummies() Post Printout"; + std::cerr << std::endl; + locked_printDummyMsgs(grp); +#endif + + return true; +} + +bool p3GroupDistrib::locked_addDummyMsg(GroupInfo &grp, std::string threadId, std::string parentId, std::string msgId, uint32_t ts) +{ +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_addDummyMsg(grpId:" << grp.grpId << ", threadId: " << threadId; + std::cerr << ", parentId:" << parentId << ", msgId: " << msgId << ")"; + std::cerr << std::endl; +#endif + + if (msgId == "") + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_addDummyMsg() ERROR not adding empty MsgId"; + std::cerr << std::endl; +#endif + return false; + } + + /* search for the msg Id */ + std::map::iterator dit = grp.dummyMsgs.find(msgId); + + if (dit == grp.dummyMsgs.end()) // not there! + { + grp.dummyMsgs[msgId] = RsDistribDummyMsg(threadId, parentId, msgId, ts); + + +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_addDummyMsg() Adding Dummy Msg"; + std::cerr << std::endl; +#endif + } + else + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_addDummyMsg() Dummy Msg already there: " << dit->second; + std::cerr << std::endl; +#endif + } + + locked_updateDummyChildTS(grp, parentId, ts); // NOTE both ChildTS functions should be merged. + return true; +} + +bool p3GroupDistrib::locked_clearDummyMsg(GroupInfo &grp, std::string msgId) +{ +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_clearDummyMsg(grpId:" << grp.grpId << ", msgId: " << msgId << ")"; + std::cerr << std::endl; +#endif + + /* search for the msg Id */ + std::map::iterator dit = grp.dummyMsgs.find(msgId); + if (dit != grp.dummyMsgs.end()) + { + +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_clearDummyMsg() Erasing Dummy Msg: " << dit->second; + std::cerr << std::endl; +#endif + + grp.dummyMsgs.erase(dit); + } + else + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_clearDummyMsg() Msg not found"; + std::cerr << std::endl; +#endif + } + return true; +} + + + + /* now update parents TS */ +/* NB: it is a hack to have seperate updateChildTS functions for msgs and dummyMsgs, + * this need to be combined (do when we add a parentId index.) + */ + +bool p3GroupDistrib::locked_updateDummyChildTS(GroupInfo &gi, std::string parentId, time_t updateTS) +{ + while("" != parentId) + { + std::map::iterator mit; + if (gi.dummyMsgs.end() == (mit = gi.dummyMsgs.find(parentId))) + { + /* not found - abandon */ + return true; + } + RsDistribDummyMsg *parent = &(mit->second); + if (parent->childTS > updateTS) + { + /* we're too old - give up! */ + return true; + } + + /* update timestamp */ + parent->childTS = updateTS; + parentId = parent->parentId; + } + return false ; +} + + +bool p3GroupDistrib::locked_printAllDummyMsgs() +{ +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_printAllDummyMsg()"; + std::cerr << std::endl; +#endif + std::map::iterator it; + for(it = mGroups.begin(); it != mGroups.end(); it++) + { + locked_printDummyMsgs(it->second); + } + return true ; +} + + + +bool p3GroupDistrib::locked_printDummyMsgs(GroupInfo &grp) +{ +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_printDummyMsg(grpId:" << grp.grpId << ")"; + std::cerr << std::endl; +#endif + + /* search for the msg Id */ + std::map::iterator dit; + for(dit = grp.dummyMsgs.begin(); dit != grp.dummyMsgs.end(); dit++) + { + std::cerr << dit->second; + std::cerr << std::endl; + } + return true; +} + + +/***** These Functions are used by the children classes to access the dummyData + ****/ + +bool p3GroupDistrib::getDummyParentMsgList(const std::string& grpId, const std::string& pId, std::list &msgIds) +{ + +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::getDummyParentMsgList(grpId:" << grpId << "," << pId << ")"; + std::cerr << std::endl; +#endif + RsStackMutex stack(distribMtx); /************* STACK MUTEX ************/ + + // load grp from history cache if not already loaded +#ifdef ENABLE_CACHE_OPT + locked_processHistoryCached(grpId); +#endif + + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::getDummyParentMsgList() Group Not Found"; + std::cerr << std::endl; +#endif + return false; + } + + std::map::iterator mit; + + for(mit = git->second.dummyMsgs.begin(); mit != git->second.dummyMsgs.end(); mit++) + { + if (mit->second.parentId == pId) + { + msgIds.push_back(mit->first); + } + } + +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::getDummyParentMsgList() found " << msgIds.size() << " msgs"; + std::cerr << std::endl; +#endif + return true; +} + + +RsDistribDummyMsg *p3GroupDistrib::locked_getGroupDummyMsg(const std::string& grpId, const std::string& msgId) +{ + locked_processHistoryCached(grpId); +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_getGroupDummyMsg(grpId:" << grpId << "," << msgId << ")"; + std::cerr << std::endl; +#endif + /************* ALREADY LOCKED ************/ + std::map::iterator git; + if (mGroups.end() == (git = mGroups.find(grpId))) + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_getGroupDummyMsg() Group not found"; + std::cerr << std::endl; +#endif + return NULL; + } + + std::map::iterator dit; + if (git->second.dummyMsgs.end() == (dit = git->second.dummyMsgs.find(msgId))) + { +#ifdef DISTRIB_DUMMYMSG_DEBUG + std::cerr << "p3GroupDistrib::locked_getGroupDummyMsg() Msg not found"; + std::cerr << std::endl; +#endif + return NULL; + } + + return &(dit->second); +} + + + + + diff --git a/libretroshare/src/services/p3distrib.h b/libretroshare/src/services/p3distrib.h new file mode 100644 index 000000000..738fd1c74 --- /dev/null +++ b/libretroshare/src/services/p3distrib.h @@ -0,0 +1,902 @@ +/* + * libretroshare/src/services: p3distrib.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_GENERIC_DISTRIB_HEADER +#define P3_GENERIC_DISTRIB_HEADER + +#include "pqi/pqi.h" +#include "pqi/pqistore.h" +#include "pqi/p3cfgmgr.h" +#include "services/p3service.h" +#include "dbase/cachestrapper.h" +#include "serialiser/rsdistribitems.h" + +#include +#include + +#include +#include + +/* + * Group Messages.... + * + * Forums / Channels / Blogs... + * + * + * Plan. + * + * (1) First create basic structures .... algorithms. + * + * (2) integrate with Cache Source/Store for data transmission. + * (3) integrate with Serialiser for messages + * (4) bring over the final key parts from existing p3channel. + */ + +const uint32_t GROUP_MAX_FWD_OFFSET = (60 * 60 * 24 * 2); /* 2 Days */ + +/************* The Messages that are serialised ****************/ + +#if 0 + +class RsConfigDistrib: public RsSerialType +{ + public: + + RsConfigDistrib(); + +}; + +class RsSerialDistrib: public RsSerialType +{ + public: + + RsSerialDistrib(); + +}; + +#endif + + +/************* The Messages that are serialised ****************/ + +#if 0 +const uint32_t GROUP_KEY_TYPE_MASK = 0x000f; +const uint32_t GROUP_KEY_DISTRIB_MASK = 0x00f0; + +const uint32_t GROUP_KEY_TYPE_PUBLIC_ONLY = 0x0001; +const uint32_t GROUP_KEY_TYPE_FULL = 0x0002; +const uint32_t GROUP_KEY_DISTRIB_PUBLIC = 0x0010; +const uint32_t GROUP_KEY_DISTRIB_PRIVATE = 0x0020; +const uint32_t GROUP_KEY_DISTRIB_ADMIN = 0x0040; +#endif + + +/* + * A data structure to store dummy (missing) msgs. + * They are added to the GroupInfo if there is a missing parent Msg of thread Msg + * Basic Logic is: + * + */ + +class RsDistribDummyMsg +{ + public: + RsDistribDummyMsg( std::string tId, std::string pId, std::string mId, uint32_t ts); + RsDistribDummyMsg() { return; } + std::string threadId; + std::string parentId; + std::string msgId; + + uint32_t timestamp; + time_t childTS; /* timestamp of most recent child */ +}; + + +//! for storing group keys to members of a group +/*! + * This key but be of many types, including private/public publish key, or admin prite key for group + * @see p3GroupDistrib + */ +class GroupKey +{ + public: + + GroupKey() + :type(0), startTS(0), endTS(0), key(NULL) { return; } + + uint32_t type; /// whether key is full or public + std::string keyId; + time_t startTS, endTS; + EVP_PKEY *key; /// actual group key in evp format +}; + +//! used to store group picture +/*! + * ensures use of png image format + * @see p3GroupDistrib + */ +class GroupIcon{ +public: + GroupIcon(): pngImageData(NULL), imageSize(0) { + return; + } + + ~GroupIcon(){ + + if((pngImageData != NULL) && (imageSize > 0)) + delete[] pngImageData; + + return; + } + + unsigned char* pngImageData; /// pointer to image data in png format + int imageSize; +}; + +//! used by p3groupDistrib to store mirror info found in rsDistribGroup (i.e. messages, posts, etc) +/*! + * used by p3Groudistrib to store group info, also used to communicate group information + * to p3groupdistrib inherited classes. contain + * @see rsDistribGroup + */ +class GroupInfo +{ + public: + + GroupInfo() + :distribGroup(NULL), grpFlags(0), pop(0), lastPost(0), flags(0), grpChanged(false) + { + return; + } + virtual ~GroupInfo() ; + + std::string grpId; /// the group id + RsDistribGrp *distribGroup; /// item which contains further information on group + + std::list sources; + std::map msgs; + std::map dummyMsgs; // dummyMsgs. + + /***********************************/ + + /* Copied from DistribGrp */ + std::wstring grpName; + std::wstring grpDesc; /// group description + std::wstring grpCategory; + uint32_t grpFlags; /// PRIVACY & AUTHENTICATION + + + uint32_t pop; /// popularity sources.size() + time_t lastPost; /// modded as msgs added + + /***********************************/ + + uint32_t flags; /// PUBLISH, SUBSCRIBE, ADMIN + + + std::string publishKeyId; /// current active Publish Key + std::map publishKeys; + + GroupKey adminKey; + + + GroupIcon grpIcon; + /* NOT USED YET */ + + std::map decrypted_msg_cache; /// stores a cache of messages that have been decrypted + + bool publisher, allowAnon, allowUnknown; + bool subscribed, listener; + + uint32_t type; + + /// FLAG for Client - set if changed + bool grpChanged; +}; + + + +std::ostream &operator<<(std::ostream &out, const GroupInfo &info); + +//! information on what cache stores group info +/*! + * This can refer to idividual cache message, data etc + */ +class GroupCache +{ + public: + + std::string filename; + time_t start, end; + uint16_t cacheSubId; /// used to resolve complete cache id +}; + + /* Flags for locked_notifyGroupChanged() ***/ + +const uint32_t GRP_NEW_UPDATE = 0x0001; +const uint32_t GRP_UPDATE = 0x0002; +const uint32_t GRP_LOAD_KEY = 0x0003; +const uint32_t GRP_NEW_MSG = 0x0004; +const uint32_t GRP_SUBSCRIBED = 0x0005; +const uint32_t GRP_UNSUBSCRIBED = 0x0006; + + + + +typedef std::pair grpNodePair; // (is loaded, iterator pointing to node) + +// these make up a cache list +typedef std::pair pCacheId; //(pid, subid) +typedef std::pair grpCachePair; // (grpid, cid) + +/*! + * grp node content for faster access + */ +struct nodeCache +{ + bool cached; + pugi::xml_node_iterator it; + pCacheId cid; + std::set cIdSet; + pugi::xml_node node; +}; + +//! Cache based service to implement group messaging +/*! + * + * Group Description: + * + * Master Public/Private Key: (Admin Key) used to control + * Group Name/Description/Icon. + * Filter Lists. + * Publish Keys. + * + * Publish Keys. + * TimeStore Length determined by inheriting class + * + * Everyone gets: + * Master Public Key. + * Publish Public Keys. + * blacklist, or whitelist filter. (Only useful for Non-Anonymous groups) + * Name, Desc, + * etc. + * + * Admins get Master Private Key. + * Publishers get Publish Private Key. + * - Channels only some get publish key. + * - Forums everyone gets publish private key. + * + * Group id is the public admin keys id + * + */ + +/* + * To Handle Cache Data Loading.... we want to be able to seperate Historical + * from new data (primarily for the gui's benefit). + * to do this we have a mHistoricalCaches flag, which is automatically raised at startup, + * and a function is called to cancel it (HistoricalCachesDone()). + */ + +class CacheDataPending +{ + public: + + CacheDataPending(const CacheData &data, bool local, bool historical); + CacheData mData; + bool mLocal; + bool mHistorical; +}; + +class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, public p3ThreadedService +{ + public: + + p3GroupDistrib(uint16_t subtype, + CacheStrapper *cs, CacheTransfer *cft, + std::string sourcedir, std::string storedir, std::string keyBackUpDir, + uint32_t configId, + uint32_t storePeriod, uint32_t pubPeriod); + + virtual ~p3GroupDistrib() ; + +/***************************************************************************************/ +/******************************* CACHE SOURCE / STORE Interface ************************/ +/***************************************************************************************/ +/* TO FINISH */ + + public: + + virtual bool loadLocalCache(const CacheData &data); /// overloaded from Cache Source + virtual int loadCache(const CacheData &data); /// overloaded from Cache Store + + + /* From RsThread */ + virtual void run(); /* called once the thread is started */ + + void HistoricalCachesDone(); // called when Stored Caches have been added to Pending List. + + + + private: + + /*! + * called when all historical caches have been loaded + */ + void HistoricalCachesLoaded(); + + /*! + * This updates the cache document with pending msg and grp cache data + */ + void updateCacheDocument(); + + /*! + * @param grpIter this is a list of iterators point to newly added grp nodes + */ + void locked_updateCacheTableGrp(const std::vector& grpNodes, bool historical); + + /*! + * @param msgCacheMap each entry a set of cache ids that are to be loaded if grpId(entry) is requested to be cached + */ + void locked_updateCacheTableMsg(const std::map >& msgCacheMap); + + /*! + * @param grpId indicates which grp entry to update + * @param cached pass as true to update entry as true and vice versa + */ + void locked_updateCacheTableEntry(const std::string& grpId, bool cached); + + + /*! + * TODO: will be used to unpack cache doc from config load + * @param cacheBinDoc contains cache document as binary + */ + bool loadCacheDoc(RsDistribConfigData& cacheBinDoc); + + + /*! + * to find if grps messages have been loaded (assumes grps have been loaded first) + * @param cached true if grp has been loaded, false if not + * @return true is grp entry does not exist in table, false if not + */ + bool locked_historyCached(const std::string& grpId, bool& cached); + + /*! + * @param cache cache data id + * @return false if cache entry does not exist in table + */ + bool locked_historyCached(const pCacheId& cId); + + /*! + * builds cache table from loaded cached document + * @return false if cache document is empty + */ + bool locked_buildCacheTable(void); + + /*! + * if grp's message is not loaded, load it, and update cache table + * @param grpId group whose messages to load if not cached + */ + void locked_processHistoryCached(const std::string& grpId); + + + /*! + * loads cache data which contains location of cache files belonging + * to group + * @param grpId grp for which to get list of cache data + * @param cDataSet cache data belonging to grp is loaded into this list + */ + void locked_getHistoryCacheData(const std::string& grpId, std::list& cDataSet); + + /*! + * encrypts and saves cache file + */ + bool locked_saveHistoryCacheFile(); + + /*! + * decrypte and save cache file + */ + bool locked_loadHistoryCacheFile(); + + private: + + /* these lists are filled by the overloaded fns... then cleared by the thread */ + bool mHistoricalCaches; // initially true.... falsified by HistoricalCachesDone() + std::list mPendingCaches; + + /* top level load */ + int loadAnyCache(const CacheData &data, bool local, bool historical); + + /* load cache files */ + void loadFileGroups(const std::string &filename, const std::string &src, bool local, bool historical, const pCacheId& cid); + void loadFileMsgs(const std::string &filename, uint16_t cacheSubId, const std::string &src, uint32_t ts, bool local, bool historical); + void locked_loadFileMsgs(const std::string &filename, uint16_t cacheSubId, const std::string &src, uint32_t ts, bool local, bool historical); + bool backUpKeys(const std::list &keysToBackUp, std::string grpId); + void locked_sharePubKey(); + + /*! + * Attempt to load public key from recvd list if it exists for grpId + * @param grpId the id for the group for which private publish key is wanted + */ + bool attemptPublishKeysRecvd(); + + protected: + + /* load cache msgs */ + + /*! + * msg is loaded to its group and republished, + * msg decrypted if grp is private + * @param msg msg to loaded + * @param src src of msg (peer id) + * @param local is this a local cache msg (your msg) + */ + bool loadMsg(RsDistribSignedMsg *msg, const std::string &src, bool local, bool historical); + + /*! + * msg is loaded to its group and republished, + * msg decrypted if grp is private + * @param msg msg to loaded + * @param src src of msg (peer id) + * @param local is this a local cache msg (your msg) + */ + bool locked_loadMsg(RsDistribSignedMsg *newMsg, const std::string &src, bool local, bool historical); + + /*! + * adds newgrp to grp set, GroupInfo type created and stored + * @param newGrp grp to be added + */ + bool loadGroup(RsDistribGrp *newGrp, bool historical); + + /*! + * Adds new keys dependent on whether it is an admin or publish key + * on return resource pointed to by newKey should be considered invalid + * @param newKey key to be added + * @return if key is loaded to group or stored return true + */ + bool loadGroupKey(RsDistribGrpKey *newKey, bool historical); + + + +/***************************************************************************************/ +/***************************************************************************************/ + +/***************************************************************************************/ +/**************************** Create Content *******************************************/ +/***************************************************************************************/ +/* TO FINISH */ + + public: + + /*! + * This create a distributed grp which is sent via cache system to connected peers + * @param name name of the group created + * @param desc description of the group + * @param flags privacy flag + * @param pngImageData pointer to image data, data is copied + * @param imageSize size of the image passed + * @return id of the group + */ + std::string createGroup(std::wstring name, std::wstring desc, uint32_t flags, unsigned char *pngImageData, uint32_t imageSize); + + /*! + * msg is packed into a signed message (and encrypted msg grp is private) and then sent via cache system to connnected peers + * @param msg + * @param personalSign whether to personal to sign image (this is done using gpg cert) + * @return the msg id + */ + std::string publishMsg(RsDistribMsg *msg, bool personalSign); + + /*! + * note: call back to locked_eventDuplicateMSg is made on execution + * @param grpId id of group to subscribe to + * @param subscribe true to subscribe and vice versa + * @return + */ + bool subscribeToGroup(const std::string &grpId, bool subscribe); + + + + /***************************************************************************************/ + /***************************************************************************************/ + + /***************************************************************************************/ + /****************************** Access Content ***************************************/ + /***************************************************************************************/ + + public: + + /*! + * get Group Lists + */ + bool getAllGroupList(std::list &grpids); + bool getSubscribedGroupList(std::list &grpids); + bool getPublishGroupList(std::list &grpids); + + /*! + * + * @param popMin lower limit for a grp's populairty in grpids + * @param popMax upper limit for a grp's popularity in grpids + * @param grpids grpids of grps which adhere to upper and lower limit of popularity + * @return nothing returned + */ + void getPopularGroupList(uint32_t popMin, uint32_t popMax, std::list &grpids); + + + /* get Msg Lists */ + bool getAllMsgList(const std::string& grpId, std::list &msgIds); + bool getParentMsgList(const std::string& grpId, const std::string& pId, std::list &msgIds); + bool getTimePeriodMsgList(const std::string& grpId, uint32_t timeMin, + uint32_t timeMax, std::list &msgIds); + + + GroupInfo *locked_getGroupInfo(const std::string& grpId); + RsDistribMsg *locked_getGroupMsg(const std::string& grpId, const std::string& msgId); + + /*! + * for retrieving the grpList for which public keys are available + */ + void getGrpListPubKeyAvailable(std::list& grpList); + + /* Filter Messages */ + +/***************************************************************************************/ +/***************************** Event Feedback ******************************************/ +/***************************************************************************************/ + + protected: + /*! + * root version (p3Distrib::) of this function must be called + */ + virtual void locked_notifyGroupChanged(GroupInfo &info, uint32_t flags, bool historical); + + /*! + * client (inheriting class) should use this to determing behaviour of + * their service when a duplicate msg is found + * @param group should be called when duplicate message loaded + * @param the duplicate message + * @param id + * @param historical: is this msg from an historical cache + * @return successfully executed or not + */ + virtual bool locked_eventDuplicateMsg(GroupInfo *, RsDistribMsg *, const std::string& id, bool historical) = 0; + + /*! + * Inheriting class should implement this as a response to a new msg arriving + * @param + * @param + * @param id src of msg (peer id) + * @param historical: is this msg from an historical cache + * @return + */ + virtual bool locked_eventNewMsg(GroupInfo *, RsDistribMsg *, const std::string& id, bool historical) = 0; + +/***************************************************************************************/ +/********************************* p3Config ********************************************/ +/***************************************************************************************/ +/* TO FINISH */ + + protected: + + virtual RsSerialiser *setupSerialiser(); + virtual bool saveList(bool &cleanup, std::list& saveList); + virtual void saveDone(); + virtual bool loadList(std::list& load); + + /*! + * called by top class, child can use to save configs + */ + virtual std::list childSaveList() = 0; + + /*! + * called by top class, child can use to load configs + */ + virtual bool childLoadList(std::list& configSaves) = 0; + +/***************************************************************************************/ +/***************************************************************************************/ + + public: + + virtual int tick(); /* overloaded form pqiService */ + +/***************************************************************************************/ +/**************************** Publish Content ******************************************/ +/***************************************************************************************/ +/* TO FINISH */ + protected: + + /* create/mod cache content */ + + /*! + * adds msg to pending msg map + * @param msg a signed message by peer + */ + void locked_toPublishMsg(RsDistribSignedMsg *msg); + + /*! + * adds pending msg + */ + void publishPendingMsgs(); + + /*! + * sends created groups to cache, to be passed to cache listeners + */ + void publishDistribGroups(); + + /*! + * removes old caches based on store period (anything that has been in local cache longer + * than the store period is deleted + * @param now the current time when method is called + */ + void clear_local_caches(time_t now); + + /*! + * assumes RsDistribMtx is locked when call is made + */ + void locked_publishPendingMsgs(); + + /*! + * @return cache sub id + */ + uint16_t locked_determineCacheSubId(); + + /** + * grp keys are backed up when a grp is created this allows user to retrieve lost keys in case config saving fails + * @param grpId the grpId id for which backup keys should be restored + * @return false if failed and vice versa + */ + virtual bool restoreGrpKeys(const std::string& grpId); /// restores a group keys from backup + + /** + * Allows user to send keys to a list of peers + * @param grpId the group for which to share public keys + * @param peers The peers to which public keys should be sent + */ + virtual bool sharePubKey(std::string grpId, std::list& peers); + + /** + * Attempt to receive publication keys + */ + virtual void receivePubKeys(); + + /** + * Allows group admin(s) to change group icon, description and name + *@param grpId group id + *@param gi the changes to grp name, icon, and description should be reflected here + */ + virtual bool locked_editGroup(std::string grpId, GroupInfo& gi); + + /*! + * Encrypts data using envelope encryption (taken from open ssl's evp_sealinit ) + * only full publish key holders can encrypt data for given group + *@param out + *@param outlen + *@param in + *@param inlen + */ + virtual bool encrypt(void *&out, int &outlen, const void *in, int inlen, std::string grpId); + + + /** + * Decrypts data using evelope decryption (taken from open ssl's evp_sealinit ) + * only full publish key holders can decrypt data for a group + *@param out where decrypted data is written to + *@param outlen + *@param in + *@param inlen + */ + virtual bool decrypt(void *&out, int &outlen, const void *in, int inlen, std::string grpId); + + /***************************************************************************************/ + /***************************************************************************************/ + + /***************************************************************************************/ + /*************************** Overloaded Functions **************************************/ + /***************************************************************************************/ + + /*! + * Overloaded by inherited classes to Pack/UnPack their messages + * @return inherited class's serialiser + */ + virtual RsSerialType *createSerialiser() = 0; + + /*! Used to Create/Load Cache Files only + * @param bio binary i/o + * @param src peer id from which write/read content originates + * @param bioflags read write permision for bio + * @return pointer to pqistore instance + */ + virtual pqistore *createStore(BinInterface *bio, const std::string &src, uint32_t bioflags); + + /*! + * checks to see if admin signature is valid + * @param newGrp grp to validate + * @return true if group's signature is valid + */ + virtual bool validateDistribGrp(RsDistribGrp *newGrp); + virtual bool locked_checkGroupInfo(GroupInfo &info, RsDistribGrp *newGrp); + virtual bool locked_updateGroupInfo(GroupInfo &info, RsDistribGrp *newGrp); + virtual bool locked_checkGroupKeys(GroupInfo &info); + + /*! + * @param info group for which admin key will be added to + * @param newKey admin key + * @return true if key successfully added + */ + virtual bool locked_updateGroupAdminKey(GroupInfo &info, RsDistribGrpKey *newKey); + + + /*! + * @param info group for which publish key will be added to + * @param newKey publish key + * @return true if publish key successfully added + */ + virtual bool locked_updateGroupPublishKey(GroupInfo &info, RsDistribGrpKey *newKey); + + + /*! + * uses groupinfo public key to verify signature of signed message + * @param info groupinfo for which msg is meant for + * @param msg + * @return false if verfication of signature is not passed + */ + virtual bool locked_validateDistribSignedMsg(GroupInfo &info, RsDistribSignedMsg *msg); + + /*! + * Use this to retrieve packed message from a signed message + * @param newMsg signed message + * @return pointer to unpacked msg + */ + virtual RsDistribMsg* unpackDistribSignedMsg(RsDistribSignedMsg *newMsg); + + + /*! + * message is checked to see if it is in a valid time range + * @param info + * @param msg message to be checked + * @return false if msg is outside correct time range + */ + virtual bool locked_checkDistribMsg(GroupInfo &info, RsDistribMsg *msg); + + /*! + * chooses the best publish key based on it being full and latest + * @param info group to choose publish key + * @return true if a publish key could be found + */ + virtual bool locked_choosePublishKey(GroupInfo &info); + + +//virtual RsDistribGrp *locked_createPublicDistribGrp(GroupInfo &info); +//virtual RsDistribGrp *locked_createPrivateDistribGrp(GroupInfo &info); + + +/***************************************************************************************/ +/***************************** Utility Functions ***************************************/ +/***************************************************************************************/ +/* TO FINISH */ + + /* utilities */ + std::string HashRsItem(const RsItem *item); + bool locked_updateChildTS(GroupInfo &gi, RsDistribMsg *msg); + +/***************************************************************************************/ +/***************************************************************************************/ + +/***************************************************************************************/ +/***************************** Utility Functions ***************************************/ +/***************************************************************************************/ + public: + + void printGroups(std::ostream &out); + + /*! + * returns list of ids for group caches that have changed + */ + bool groupsChanged(std::list &groupIds); + +/***************************************************************************************/ +/***************************************************************************************/ + + +/***************************************************************************************/ +/**************************** DummyMsgs Functions **************************************/ +/***************************************************************************************/ + public: + +bool locked_CheckNewMsgDummies(GroupInfo &info, RsDistribMsg *msg, std::string id, bool historical); +bool locked_addDummyMsg(GroupInfo &info, std::string threadId, std::string parentId, std::string msgId, uint32_t ts); +bool locked_clearDummyMsg(GroupInfo &info, std::string msgId); +bool locked_updateDummyChildTS(GroupInfo &gi, std::string parentId, time_t updateTS); // NOTE MUST BE MERGED WITH nromal version. + +bool locked_printAllDummyMsgs(); +bool locked_printDummyMsgs(GroupInfo &info); + + /* access the dummy msgs */ +bool getDummyParentMsgList(const std::string& grpId, const std::string& pId, std::list &msgIds); +RsDistribDummyMsg *locked_getGroupDummyMsg(const std::string& grpId, const std::string& msgId); + + + /* key cache functions - we use .... (not overloaded) + */ + + /* storage */ + protected: + + RsMutex distribMtx; /// Protects all class atrributes + std::string mOwnId; /// rs peer id + + private: + + std::list mLocalCaches; + std::map mGroups; + uint32_t mStorePeriod, mPubPeriod; + + /* Message Publishing */ + std::list mPendingPublish; + time_t mLastPublishTime; + std::map mLocalCacheTs; + uint16_t mMaxCacheSubId; + + bool mGroupsChanged; + bool mGroupsRepublish; + + std::list saveCleanupList; /* TEMPORARY LIST WHEN SAVING */ + std::string mKeyBackUpDir; + const std::string BACKUP_KEY_FILE; + + std::map mRecvdPubKeys; /// full publishing keys received from users + std::map > mPendingPubKeyRecipients; /// peers to receive publics key for a given grp + std::set mPubKeyAvailableGrpId; // groups id for which public keys are available + time_t mLastKeyPublishTime, mLastRecvdKeyTime; + + ////////////// cache optimisation //////////////// + int mCount; + /// table containing new msg cache data to be added to xml doc ( grpid, (cid,pid) ) + std::vector mGrpHistPending; + + /// table containing new grp cache data to be added to xml doc (grpid, (cid,pid) ) + std::vector mMsgHistPending; + + std::set mCachePairsInTable, mCacheFailedTable; + + std::list mPendingHistCaches; + + std::map mLocalHistCachesAvail; + + time_t mLastCacheDocUpdate; + bool mUpdateCacheDoc, mHistoricalCachesLoaded; + + std::map mCacheTable; // (cid, node) + + /// contains information on cached data + pugi::xml_document mCacheDoc; + +}; + + +/***************************************************************************************/ +/***************************************************************************************/ + +#endif // P3_GENERIC_DISTRIB_HEADER diff --git a/libretroshare/src/services/p3forums.cc b/libretroshare/src/services/p3forums.cc new file mode 100644 index 000000000..45d3c9b2a --- /dev/null +++ b/libretroshare/src/services/p3forums.cc @@ -0,0 +1,790 @@ +/* + * libretroshare/src/services: rsforums.cc + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3forums.h" +#include "pqi/authssl.h" +#include "util/rsdir.h" +#include "retroshare/rsiface.h" + +uint32_t convertToInternalFlags(uint32_t extFlags); +uint32_t convertToExternalFlags(uint32_t intFlags); + +std::ostream &operator<<(std::ostream &out, const ForumInfo &info) +{ + std::string name(info.forumName.begin(), info.forumName.end()); + std::string desc(info.forumDesc.begin(), info.forumDesc.end()); + + out << "ForumInfo:"; + out << std::endl; + out << "ForumId: " << info.forumId << std::endl; + out << "ForumName: " << name << std::endl; + out << "ForumDesc: " << desc << std::endl; + out << "ForumFlags: " << info.forumFlags << std::endl; + out << "Pop: " << info.pop << std::endl; + out << "LastPost: " << info.lastPost << std::endl; + + return out; +} + +std::ostream &operator<<(std::ostream &out, const ThreadInfoSummary &info) +{ + out << "ThreadInfoSummary:"; + out << std::endl; + //out << "ForumId: " << forumId << std::endl; + //out << "ThreadId: " << threadId << std::endl; + + return out; +} + +std::ostream &operator<<(std::ostream &out, const ForumMsgInfo &info) +{ + out << "ForumMsgInfo:"; + out << std::endl; + //out << "ForumId: " << forumId << std::endl; + //out << "ThreadId: " << threadId << std::endl; + + return out; +} + + +RsForums *rsForums = NULL; + + +/* Forums will be initially stored for 1 year + * remember 2^16 = 64K max units in store period. + * PUBPERIOD * 2^16 = max STORE PERIOD */ +#define FORUM_STOREPERIOD (365*24*3600) /* 365 * 24 * 3600 - secs in a year */ +#define FORUM_PUBPERIOD 600 /* 10 minutes ... (max = 455 days) */ + +p3Forums::p3Forums(uint16_t type, CacheStrapper *cs, CacheTransfer *cft, + std::string srcdir, std::string storedir, std::string forumDir) + :p3GroupDistrib(type, cs, cft, srcdir, storedir, forumDir, + CONFIG_TYPE_FORUMS, FORUM_STOREPERIOD, FORUM_PUBPERIOD), + mForumsDir(forumDir) +{ + + /* create chanDir */ + if (!RsDirUtil::checkCreateDirectory(mForumsDir)) { + std::cerr << "p3Channels() Failed to create forums Directory: " << mForumsDir << std::endl; + } + + return; +} + +p3Forums::~p3Forums() +{ + return; +} + +/****************************************/ + +bool p3Forums::forumsChanged(std::list &forumIds) +{ + return groupsChanged(forumIds); +} + +bool p3Forums::getForumInfo(const std::string &fId, ForumInfo &fi) +{ + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + /* extract details */ + GroupInfo *gi = locked_getGroupInfo(fId); + + if (!gi) + return false; + + fi.forumId = gi->grpId; + fi.forumName = gi->grpName; + fi.forumDesc = gi->grpDesc; + fi.forumFlags = gi->grpFlags; + + fi.subscribeFlags = gi->flags; + + fi.pop = gi->sources.size(); + fi.lastPost = gi->lastPost; + + return true; +} + +/*! + * allows peers to change information for the forum: + * can only change name and descriptions + * + */ +bool p3Forums::setForumInfo(const std::string &fId, ForumInfo &fi) +{ + GroupInfo gi; + + RsStackMutex stack(distribMtx); + + gi.grpName = fi.forumName; + gi.grpDesc = fi.forumDesc; + + return locked_editGroup(fId, gi); + } + +bool p3Forums::getForumList(std::list &forumList) +{ + std::list grpIds; + std::list::iterator it; + + getAllGroupList(grpIds); + + for(it = grpIds.begin(); it != grpIds.end(); it++) + { + ForumInfo fi; + if (getForumInfo(*it, fi)) + { + forumList.push_back(fi); + } + } + return true; +} + +bool p3Forums::getForumThreadList(const std::string &fId, std::list &msgs) +{ + std::list msgIds; + std::list::iterator it; + + getParentMsgList(fId, "", msgIds); + + std::list msgDummyIds; + getDummyParentMsgList(fId, "", msgDummyIds); + + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + for(it = msgIds.begin(); it != msgIds.end(); it++) + { + /* get details */ + RsDistribMsg *msg = locked_getGroupMsg(fId, *it); + RsForumMsg *fmsg = dynamic_cast(msg); + if (!fmsg) + continue; + + ThreadInfoSummary tis; + + tis.forumId = msg->grpId; + tis.msgId = msg->msgId; + tis.parentId = ""; // always NULL (see request) + tis.threadId = msg->msgId; // these are the thread heads! + + tis.ts = msg->timestamp; + tis.childTS = msg->childTS; + + /* the rest must be gotten from the derived Msg */ + + tis.title = fmsg->title; + tis.msg = fmsg->msg; + + msgs.push_back(tis); + } + + // now add dummy msgs. + for(it = msgDummyIds.begin(); it != msgDummyIds.end(); it++) + { + /* get details */ + RsDistribDummyMsg *msg = locked_getGroupDummyMsg(fId, *it); + ThreadInfoSummary tis; + + tis.forumId = fId; + tis.msgId = msg->msgId; + tis.parentId = ""; // always NULL (see request) + tis.threadId = msg->msgId; // these are the thread heads! + + tis.ts = msg->timestamp; + tis.childTS = msg->childTS; + + /* dummy msg */ + tis.title = L"[ ... Missing Message ... ]"; + tis.msg = L"Placeholder for missing Message"; + tis.msgflags |= RS_DISTRIB_MISSING_MSG; + + msgs.push_back(tis); + } + + return true; +} + +bool p3Forums::getForumThreadMsgList(const std::string &fId, const std::string &pId, std::list &msgs) +{ + std::list msgIds; + std::list::iterator it; + + getParentMsgList(fId, pId, msgIds); + + std::list msgDummyIds; + getDummyParentMsgList(fId, pId, msgDummyIds); + + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + for(it = msgIds.begin(); it != msgIds.end(); it++) + { + /* get details */ + RsDistribMsg *msg = locked_getGroupMsg(fId, *it); + RsForumMsg *fmsg = dynamic_cast(msg); + if (!fmsg) + continue; + + ThreadInfoSummary tis; + + tis.forumId = msg->grpId; + tis.msgId = msg->msgId; + tis.parentId = msg->parentId; + tis.threadId = msg->threadId; + + tis.ts = msg->timestamp; + tis.childTS = msg->childTS; + + /* the rest must be gotten from the derived Msg */ + + tis.title = fmsg->title; + tis.msg = fmsg->msg; + + if (fmsg->personalSignature.keyId.empty() == false) { + tis.msgflags |= RS_DISTRIB_AUTHEN_REQ; + } + + msgs.push_back(tis); + } + + // now add dummy msgs. + for(it = msgDummyIds.begin(); it != msgDummyIds.end(); it++) + { + /* get details */ + RsDistribDummyMsg *msg = locked_getGroupDummyMsg(fId, *it); + ThreadInfoSummary tis; + + tis.forumId = fId; + tis.msgId = msg->msgId; + tis.parentId = msg->parentId; + tis.threadId = msg->threadId; + + tis.ts = msg->timestamp; + tis.childTS = msg->childTS; + + /* dummy msg */ + tis.title = L"[ ... Missing Message ... ]"; + tis.msg = L"Placeholder for missing Message"; + tis.msgflags |= RS_DISTRIB_MISSING_MSG; + + msgs.push_back(tis); + } + return true; +} + +bool p3Forums::getForumMessage(const std::string &fId, const std::string &mId, ForumMsgInfo &info) +{ + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + RsDistribMsg *msg = locked_getGroupMsg(fId, mId); + RsForumMsg *fmsg = dynamic_cast(msg); + if (!fmsg) + { + /* try for a dummy msg */ + RsDistribDummyMsg *dmsg = locked_getGroupDummyMsg(fId, mId); + if (!dmsg) + return false; + + /* fill in the dummy msg */ + info.forumId = fId; + info.msgId = dmsg->msgId; + info.parentId = dmsg->parentId; + info.threadId = dmsg->threadId; + + info.ts = dmsg->timestamp; + info.childTS = dmsg->childTS; + + info.title = L"[ ... Missing Message ... ]"; + info.msg = L"Placeholder for missing Message"; + info.msgflags |= RS_DISTRIB_MISSING_MSG; + + info.srcId = ""; + + return true; + } + + info.forumId = msg->grpId; + info.msgId = msg->msgId; + info.parentId = msg->parentId; + info.threadId = msg->threadId; + + info.ts = msg->timestamp; + info.childTS = msg->childTS; + + /* the rest must be gotten from the derived Msg */ + + info.title = fmsg->title; + info.msg = fmsg->msg; + // should only use actual signature .... + //info.srcId = fmsg->srcId; + info.srcId = fmsg->personalSignature.keyId; + + if (fmsg->personalSignature.keyId.empty() == false) { + info.msgflags |= RS_DISTRIB_AUTHEN_REQ; + } + + return true; +} + +bool p3Forums::ForumMessageSend(ForumMsgInfo &info) +{ + bool signIt = (info.msgflags == RS_DISTRIB_AUTHEN_REQ); + + std::string mId = createForumMsg(info.forumId, info.parentId, + info.title, info.msg, signIt); + + if (mId.empty()) { + return false; + } + + // return id + info.msgId = mId; + + return setMessageStatus(info.forumId, mId, FORUM_MSG_STATUS_READ, FORUM_MSG_STATUS_MASK); +} + +bool p3Forums::setMessageStatus(const std::string& fId,const std::string& mId,const uint32_t status, const uint32_t statusMask) +{ + { + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + std::map::iterator mit = mReadStatus.find(fId); + if (mit != mReadStatus.end()) + { + RsForumReadStatus* rsi = mit->second; + rsi->msgReadStatus[mId] &= ~statusMask; + rsi->msgReadStatus[mId] |= (status & statusMask); + } else { + // if forum id does not exist create one + RsForumReadStatus* rsi = new RsForumReadStatus(); + rsi->forumId = fId; + rsi->msgReadStatus[mId] = status & statusMask; + mReadStatus[fId] = rsi; + mSaveList.push_back(rsi); + } + + IndicateConfigChanged(); + } /******* UNLOCKED ********/ + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_FORUMLIST_LOCKED, NOTIFY_TYPE_MOD); + + return true; +} + +bool p3Forums::getMessageStatus(const std::string& fId, const std::string& mId, uint32_t& status) +{ + status = 0; + + RsStackMutex stack(distribMtx); + + std::map::iterator fit = mReadStatus.find(fId); + + if (fit == mReadStatus.end()) + { + return false; + } + + std::map::iterator rit = fit->second->msgReadStatus.find(mId); + + if(rit != fit->second->msgReadStatus.end()) + { + status = rit->second; + return true; + } + + return false; +} + +bool p3Forums::forumRestoreKeys(const std::string& fIds) +{ + return p3GroupDistrib::restoreGrpKeys(fIds); +} + + +std::string p3Forums::createForum(const std::wstring &forumName, const std::wstring &forumDesc, uint32_t forumFlags) +{ + + std::string id = createGroup(forumName, forumDesc, + convertToInternalFlags(forumFlags), NULL, 0); + + return id; +} + +std::string p3Forums::createForumMsg(std::string fId, std::string pId, + std::wstring title, std::wstring msg, bool signIt) +{ + + RsForumMsg *fmsg = new RsForumMsg(); + fmsg->grpId = fId; + fmsg->parentId = pId; + + { + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + RsDistribMsg *msg = locked_getGroupMsg(fId, pId); + if (!msg) + { + fmsg->parentId = ""; + fmsg->threadId = ""; + } + else + { + if (msg->parentId == "") + { + fmsg->threadId = fmsg->parentId; + } + else + { + fmsg->threadId = msg->threadId; + } + } + } + + fmsg->title = title; + fmsg->msg = msg; + if (signIt) + { + fmsg->srcId = AuthSSL::getAuthSSL()->OwnId(); + } + fmsg->timestamp = time(NULL); + + std::string msgId = publishMsg(fmsg, signIt); + + if (msgId.empty()) { + delete(fmsg); + } + + return msgId; +} + +RsSerialType *p3Forums::createSerialiser() +{ + return new RsForumSerialiser(); +} + +bool p3Forums::locked_checkDistribMsg(RsDistribMsg *msg) +{ + return true; +} + + +RsDistribGrp *p3Forums::locked_createPublicDistribGrp(GroupInfo &info) +{ + RsDistribGrp *grp = NULL; //new RsForumGrp(); + + return grp; +} + +RsDistribGrp *p3Forums::locked_createPrivateDistribGrp(GroupInfo &info) +{ + RsDistribGrp *grp = NULL; //new RsForumGrp(); + + return grp; +} + + +uint32_t convertToInternalFlags(uint32_t extFlags) +{ + return extFlags; +} + +uint32_t convertToExternalFlags(uint32_t intFlags) +{ + return intFlags; +} + +bool p3Forums::forumSubscribe(const std::string &fId, bool subscribe) +{ + return subscribeToGroup(fId, subscribe); +} + +bool p3Forums::getMessageCount(const std::string &fId, unsigned int &newCount, unsigned int &unreadCount) +{ + newCount = 0; + unreadCount = 0; + + std::list grpIds; + + if (fId.empty()) { + // count all messages of all subscribed forums + getAllGroupList(grpIds); + } else { + // count all messages of one forum + grpIds.push_back(fId); + } + + std::list::iterator git; + for (git = grpIds.begin(); git != grpIds.end(); git++) { + std::string fId = *git; + uint32_t grpFlags; + + { + // only flag is needed + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + GroupInfo *gi = locked_getGroupInfo(fId); + if (gi == NULL) { + return false; + } + grpFlags = gi->flags; + } /******* UNLOCKED ********/ + + if (grpFlags & (RS_DISTRIB_ADMIN | RS_DISTRIB_SUBSCRIBED)) { + std::list msgIds; + if (getAllMsgList(fId, msgIds)) { + + RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/ + + std::map::iterator fit = mReadStatus.find(fId); + if (fit == mReadStatus.end()) { + // no status available -> all messages are new + newCount += msgIds.size(); + unreadCount += msgIds.size(); + continue; + } + + std::list::iterator mit; + for (mit = msgIds.begin(); mit != msgIds.end(); mit++) { + std::map::iterator rit = fit->second->msgReadStatus.find(*mit); + + if (rit == fit->second->msgReadStatus.end()) { + // no status available -> message is new + newCount++; + unreadCount++; + continue; + } + + if (rit->second & FORUM_MSG_STATUS_READ) { + // message is not new + if (rit->second & FORUM_MSG_STATUS_UNREAD_BY_USER) { + // message is unread + unreadCount++; + } + } else { + newCount++; + unreadCount++; + } + } + } /******* UNLOCKED ********/ + } + } + + return true; +} + +/***************************************************************************************/ +/****************** Event Feedback (Overloaded form p3distrib) *************************/ +/***************************************************************************************/ + +#include "pqi/pqinotify.h" + +void p3Forums::locked_notifyGroupChanged(GroupInfo &grp, uint32_t flags, bool historical) +{ + const std::string &grpId = grp.grpId; + std::string msgId; + std::string nullId; + + switch(flags) + { + case GRP_NEW_UPDATE: + if (!historical) + { + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_FORUM_NEW, grpId, msgId, nullId); + } + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_FORUMLIST_LOCKED, NOTIFY_TYPE_ADD); + break; + case GRP_UPDATE: + if (!historical) + { + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_FORUM_UPDATE, grpId, msgId, nullId); + } + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_FORUMLIST_LOCKED, NOTIFY_TYPE_MOD); + break; + case GRP_LOAD_KEY: + break; + case GRP_NEW_MSG: + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_FORUMLIST_LOCKED, NOTIFY_TYPE_ADD); + break; + case GRP_SUBSCRIBED: + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_FORUMLIST_LOCKED, NOTIFY_TYPE_ADD); + break; + case GRP_UNSUBSCRIBED: + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_FORUMLIST_LOCKED, NOTIFY_TYPE_DEL); + break; + } + return p3GroupDistrib::locked_notifyGroupChanged(grp, flags, historical); +} + +bool p3Forums::locked_eventDuplicateMsg(GroupInfo *grp, RsDistribMsg *msg, const std::string& id, bool historical) +{ + return true; +} + +bool p3Forums::locked_eventNewMsg(GroupInfo *grp, RsDistribMsg *msg, const std::string& id, bool historical) +{ + std::string grpId = msg->grpId; + std::string msgId = msg->msgId; + std::string nullId; + + if (!historical) + { + getPqiNotify()->AddFeedItem(RS_FEED_ITEM_FORUM_MSG, grpId, msgId, nullId); + } + + return true; +} + + + +/****************************************/ + +void p3Forums::loadDummyData() +{ + ForumInfo fi; + std::string forumId; + std::string msgId; + time_t now = time(NULL); + + fi.forumId = "FID1234"; + fi.forumName = L"Forum 1"; + fi.forumDesc = L"Forum 1"; + fi.forumFlags = RS_DISTRIB_ADMIN; + fi.pop = 2; + fi.lastPost = now - 123; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); + + fi.forumId = "FID2345"; + fi.forumName = L"Forum 2"; + fi.forumDesc = L"Forum 2"; + fi.forumFlags = RS_DISTRIB_SUBSCRIBED; + fi.pop = 3; + fi.lastPost = now - 1234; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); + msgId = createForumMsg(forumId, "", L"WELCOME TO Forum1", L"Hello!", true); + msgId = createForumMsg(forumId, msgId, L"Love this forum", L"Hello2!", true); + + return; + + /* ignore this */ + + fi.forumId = "FID3456"; + fi.forumName = L"Forum 3"; + fi.forumDesc = L"Forum 3"; + fi.forumFlags = 0; + fi.pop = 3; + fi.lastPost = now - 1234; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); + + fi.forumId = "FID4567"; + fi.forumName = L"Forum 4"; + fi.forumDesc = L"Forum 4"; + fi.forumFlags = 0; + fi.pop = 5; + fi.lastPost = now - 1234; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); + + fi.forumId = "FID5678"; + fi.forumName = L"Forum 5"; + fi.forumDesc = L"Forum 5"; + fi.forumFlags = 0; + fi.pop = 1; + fi.lastPost = now - 1234; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); + + fi.forumId = "FID6789"; + fi.forumName = L"Forum 6"; + fi.forumDesc = L"Forum 6"; + fi.forumFlags = 0; + fi.pop = 2; + fi.lastPost = now - 1234; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); + + fi.forumId = "FID7890"; + fi.forumName = L"Forum 7"; + fi.forumDesc = L"Forum 7"; + fi.forumFlags = 0; + fi.pop = 4; + fi.lastPost = now - 1234; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); + + fi.forumId = "FID8901"; + fi.forumName = L"Forum 8"; + fi.forumDesc = L"Forum 8"; + fi.forumFlags = 0; + fi.pop = 3; + fi.lastPost = now - 1234; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); + + fi.forumId = "FID9012"; + fi.forumName = L"Forum 9"; + fi.forumDesc = L"Forum 9"; + fi.forumFlags = 0; + fi.pop = 2; + fi.lastPost = now - 1234; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); + + fi.forumId = "FID9123"; + fi.forumName = L"Forum 10"; + fi.forumDesc = L"Forum 10"; + fi.forumFlags = 0; + fi.pop = 1; + fi.lastPost = now - 1234; + + forumId = createForum(fi.forumName, fi.forumDesc, fi.forumFlags); +} + +std::list p3Forums::childSaveList() +{ + return mSaveList; +} + +bool p3Forums::childLoadList(std::list& configSaves) +{ + RsForumReadStatus* drs = NULL; + std::list::iterator it; + + for(it = configSaves.begin(); it != configSaves.end(); it++) + { + if(NULL != (drs = dynamic_cast(*it))) + { + mReadStatus[drs->forumId] = drs; + mSaveList.push_back(drs); + } + else + { + std::cerr << "p3Forums::childLoadList(): Configs items loaded were incorrect!" + << std::endl; + return false; + } + } + + return true; +} diff --git a/libretroshare/src/services/p3forums.h b/libretroshare/src/services/p3forums.h new file mode 100644 index 000000000..b68b0dd24 --- /dev/null +++ b/libretroshare/src/services/p3forums.h @@ -0,0 +1,105 @@ +#ifndef RS_P3_FORUMS_INTERFACE_H +#define RS_P3_FORUMS_INTERFACE_H + +/* + * libretroshare/src/services: p3forums.h + * + * RetroShare C++ Interface. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "retroshare/rsforums.h" +#include "services/p3distrib.h" +#include "serialiser/rsforumitems.h" + + + +class p3Forums: public p3GroupDistrib, public RsForums +{ + public: + + p3Forums(uint16_t type, CacheStrapper *cs, CacheTransfer *cft, + std::string srcdir, std::string storedir, std::string forumdir); +virtual ~p3Forums(); + +void loadDummyData(); + +/****************************************/ +/********* rsForums Interface ***********/ + +virtual bool forumsChanged(std::list &forumIds); + +virtual std::string createForum(const std::wstring &forumName, const std::wstring &forumDesc, uint32_t forumFlags); + +virtual bool getForumInfo(const std::string &fId, ForumInfo &fi); +virtual bool setForumInfo(const std::string &fId, ForumInfo &fi); +virtual bool getForumList(std::list &forumList); +virtual bool getForumThreadList(const std::string &fId, std::list &msgs); +virtual bool getForumThreadMsgList(const std::string &fId, const std::string &tId, std::list &msgs); +virtual bool getForumMessage(const std::string &fId, const std::string &mId, ForumMsgInfo &msg); +virtual bool ForumMessageSend(ForumMsgInfo &info); +virtual bool setMessageStatus(const std::string& fId, const std::string& mId, const uint32_t status, const uint32_t statusMask); +virtual bool getMessageStatus(const std::string& fId, const std::string& mId, uint32_t& status); +virtual bool forumRestoreKeys(const std::string& fId); + +virtual bool forumSubscribe(const std::string &fId, bool subscribe); + +virtual bool getMessageCount(const std::string &fId, unsigned int &newCount, unsigned int &unreadCount); + +/***************************************************************************************/ +/****************** Event Feedback (Overloaded form p3distrib) *************************/ +/***************************************************************************************/ + +virtual void locked_notifyGroupChanged(GroupInfo &grp, uint32_t flags, bool historical); +virtual bool locked_eventDuplicateMsg(GroupInfo *, RsDistribMsg *, const std::string&, bool historical); +virtual bool locked_eventNewMsg(GroupInfo *, RsDistribMsg *, const std::string&, bool historical); + + +/****************************************/ +/********* Overloaded Functions *********/ + +//virtual RsSerialiser *setupSerialiser(); +//virtual pqistreamer *createStreamer(BinInterface *bio, std::string src, uint32_t bioflags); +virtual RsSerialType *createSerialiser(); + +virtual bool locked_checkDistribMsg(RsDistribMsg *msg); +virtual RsDistribGrp *locked_createPublicDistribGrp(GroupInfo &info); +virtual RsDistribGrp *locked_createPrivateDistribGrp(GroupInfo &info); +virtual bool childLoadList(std::list& ); +virtual std::list childSaveList(); + + +/****************************************/ + +std::string createForumMsg(std::string fId, std::string pId, + std::wstring title, std::wstring msg, bool signIt); + + private: + +std::string mForumsDir; +std::list mSaveList; // store save data + +std::map mReadStatus; + +}; + + +#endif diff --git a/libretroshare/src/services/p3gamelauncher.cc b/libretroshare/src/services/p3gamelauncher.cc new file mode 100644 index 000000000..355b656b4 --- /dev/null +++ b/libretroshare/src/services/p3gamelauncher.cc @@ -0,0 +1,1341 @@ +/* + * libretroshare/src/services: p3gamelauncher.cc + * + * Other Bits for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3gamelauncher.h" +#include "services/p3gameservice.h" +#include "util/rsdebug.h" +#include "pqi/p3connmgr.h" +#include +#include + +/* global variable for GUI */ +RsGameLauncher *rsGameLauncher = NULL; + +/***** + * #define GAME_DEBUG 1 + *****/ + +#define TEST_NO_GAMES 1 + +/* So STATEs is always the best way to do things.... + * + * CLIENT: + * ------- + * state: message result + * NULL + * <------- START ----- to INVITED state + * <------- RESUME ----- to INVITED(resume) etc... + * + * INVITED + * ------ INTERESTED -----> to READY state + * ------ REJECT -----> to NULL state + * + * READY + * <------- CONFIRMED ----- to/stay READY (update) + * <------- REJECTED ----- to NULL (abort) + * <------- PLAY ----- to ACTIVE + * + * ---- + * below here the game s setup (game / players / order / etc is defined) + * + * ACTIVE (game play happens). + * <------ PAUSE -----> to NULL + * <------ disconnect ----> to NULL + * <------ QUIT -----> to NULL + * + ******************************************************** + * + * SERVER: + * ------- + * state: message result + * NULL + * ------ START -----> to SETUP state + * + * SETUP + * <----- INTERESTED ------ to SETUP state + * <----- REJECT ------ to SETUP state + * ------ CONFIRMED -----> to SETUP state + * ------ REJECTED -----> to SETUP state + * ------ PLAY -----> to ACTIVE state + * + * ---- + * below here the game s setup (game / players / order / etc is defined) + * + * ACTIVE (game play happens). + * <------- PAUSE ----- to NULL + * ------- disconnect ----- to NULL + * <------- QUIT ----- to NULL + */ + +/* Game Setup States ****/ +const uint32_t RS_GAME_INIT_INVITED = 1; /* Client */ +const uint32_t RS_GAME_INIT_READY = 2; /* Client */ +const uint32_t RS_GAME_INIT_SETUP = 3; /* Server */ +const uint32_t RS_GAME_INIT_CONFIRM = 4; /* Server */ +const uint32_t RS_GAME_INIT_ACTIVE = 5; /* Client/Server */ + + +/* Game Setup Messages ****/ +const uint32_t RS_GAME_MSG_START = 0; /* SERVER->CLIENT */ +const uint32_t RS_GAME_MSG_RESUME = 1; /* SERVER->CLIENT * TODO later */ +const uint32_t RS_GAME_MSG_INTERESTED = 2; /* CLIENT->SERVER */ +const uint32_t RS_GAME_MSG_CONFIRM = 3; /* SERVER->CLIENT */ +const uint32_t RS_GAME_MSG_PLAY = 4; /* SERVER->CLIENT */ +const uint32_t RS_GAME_MSG_PAUSE = 5; /* ANY -> ANY */ +const uint32_t RS_GAME_MSG_QUIT = 6; /* ANY -> ANY */ +const uint32_t RS_GAME_MSG_REJECT = 6; /* ANY -> ANY */ + +const int p3gamezone = 1745; + +p3GameLauncher::p3GameLauncher(p3ConnectMgr *connMgr) + :p3Service(RS_SERVICE_TYPE_GAME_LAUNCHER), + mConnMgr(connMgr) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::p3GameLauncher()"; + std::cerr << std::endl; +#endif + + addSerialType(new RsGameSerialiser()); + mOwnId = mConnMgr->getOwnId(); +} + +int p3GameLauncher::tick() +{ + pqioutput(PQL_DEBUG_BASIC, p3gamezone, + "p3GameLauncher::tick()"); + checkIncoming(); + return 0; +} + +int p3GameLauncher::status() +{ + pqioutput(PQL_DEBUG_BASIC, p3gamezone, + "p3GameLauncher::status()"); + return 1; +} + + +/**** Interface to GUI Game Launcher ****/ + + +std::string generateRandomGameId() +{ + std::ostringstream out; + out << std::hex; +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + /* 4 bytes per random number: 4 x 4 = 16 bytes */ + for(int i = 0; i < 4; i++) + { + out << std::setw(8) << std::setfill('0'); + uint32_t rint = random(); + out << rint; + } +#else + srand(time(NULL)); + /* 2 bytes per random number: 8 x 2 = 16 bytes */ + for(int i = 0; i < 8; i++) + { + out << std::setw(4) << std::setfill('0'); + uint16_t rint = rand(); /* only gives 16 bits */ + out << rint; + } +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + return out.str(); +} + +/**** GUI Interface ****/ + + +bool p3GameLauncher::resumeGame(std::string) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::resumeGame()"; + std::cerr << std::endl; +#endif + + /* get game details from p3gameService */ + /* add to status reports */ + /* send resume invites to peers in list */ + + return ""; /* TODO */ +} + + +/******************************************************************/ +/******************************************************************/ + /***** EXTERNAL RsGameLauncher Interface *******/ +/******************************************************************/ +/******************************************************************/ + + /* Server commands */ + +std::string p3GameLauncher::createGame(uint32_t gameType, std::wstring name) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::createGame()"; + std::cerr << std::endl; +#endif + + /* translate Id */ + uint16_t srvId = gameType; + + return newGame(srvId, name); +} + +std::string p3GameLauncher::newGame(uint16_t srvId, std::wstring name) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::newGame()"; + std::string tmpname(name.begin(), name.end()); + std::cerr << "srvId: " << srvId << " name: " << tmpname; + std::cerr << std::endl; +#endif + + /* generate GameId (random string) */ + std::string gameId = generateRandomGameId(); + + gameStatus newGame; + newGame.gameId = gameId; + newGame.serviceId = srvId; + newGame.numPlayers = 0; + newGame.gameName = name; + + newGame.interestedPeers.clear(); + newGame.peerIds.clear(); + newGame.state = RS_GAME_INIT_SETUP; /* Server Only */ + + newGame.areServer = true; + newGame.serverId = mOwnId; + newGame.allowedPeers.push_back(mOwnId); + newGame.interestedPeers.push_back(mOwnId); + newGame.peerIds.push_back(mOwnId); + + /* send messages to peers inviting to game */ + std::list::const_iterator it; + + /* store gameStatus in list */ + gamesCurrent[gameId] = newGame; + + /* return new game Id */ + return gameId; +} + +void p3GameLauncher::cleanupGame(std::string gameId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::cleanupGame()"; + std::cerr << " gameId: " << gameId; + std::cerr << std::endl; +#endif + + deleteGame(gameId); +} + +bool p3GameLauncher::deleteGame(std::string gameId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::deleteGame()"; + std::cerr << " gameId: " << gameId; + std::cerr << std::endl; +#endif + + std::map::iterator git; + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return false; + } + + if (git->second.state != RS_GAME_INIT_SETUP) + { + /* send off quit messages */ + quitGame(gameId); + } + + gamesCurrent.erase(git); + + return true; +} + +bool p3GameLauncher::inviteGame(std::string gameId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::inviteGame()"; + std::cerr << " gameId: " << gameId; + std::cerr << std::endl; +#endif + + std::map::iterator git; + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return false; + } + + if (git->second.state != RS_GAME_INIT_SETUP) + { + return false; + } + + /* send messages to peers inviting to game */ + std::list::const_iterator it; + + for(it = git->second.allowedPeers.begin(); + it != git->second.allowedPeers.end(); it++) + { + /* for an invite we need: + * serviceId, gameId, numPlayers.... + */ + if (*it == mOwnId) + { + continue; + } + + RsGameItem *rgi = new RsGameItem(); + rgi->serviceId = git->second.serviceId; + rgi->gameId = git->second.gameId; + rgi->gameComment = git->second.gameName; + rgi->numPlayers = git->second.numPlayers; + rgi->players.ids = git->second.allowedPeers; + + rgi->msg = RS_GAME_MSG_START; + /* destination */ + rgi->PeerId(*it); + + /* send Msg */ + sendItem(rgi); + } + + git->second.state = RS_GAME_INIT_CONFIRM; + + return true; +} + + +/* support Game */ +bool p3GameLauncher::confirmGame(std::string gameId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::confirmGame()"; + std::cerr << " gameId: " << gameId; + std::cerr << std::endl; +#endif + + + std::map::iterator git; + + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return false; + } + + /* send messages to peers inviting to game */ + std::list::const_iterator it; + + for(it = git->second.peerIds.begin(); + it != git->second.peerIds.end(); it++) + { + /* for an invite we need: + * serviceId, gameId, numPlayers.... + */ + + if (*it == mOwnId) + { + continue; + } + + RsGameItem *rgi = new RsGameItem(); + rgi->serviceId = git->second.serviceId; + rgi->gameId = git->second.gameId; + rgi->gameComment = git->second.gameName; + rgi->numPlayers = git->second.numPlayers; + rgi->players.ids = git->second.peerIds; + + rgi->msg = RS_GAME_MSG_CONFIRM; + + /* destination */ + rgi->PeerId(*it); + + /* send Msg */ + sendItem(rgi); + } + + return true; +} + + +bool p3GameLauncher::playGame(std::string gameId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::playGame()"; + std::cerr << " gameId: " << gameId; + std::cerr << std::endl; +#endif + + std::map::iterator git; + + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return false; + } + + if (git->second.state != RS_GAME_INIT_CONFIRM) + { + return false; + } + + /* send messages to peers inviting to game */ + std::list::const_iterator it; + + for(it = git->second.peerIds.begin(); + it != git->second.peerIds.end(); it++) + { + /* for an invite we need: + * serviceId, gameId, numPlayers.... + */ + + if (*it == mOwnId) + { + continue; + } + + RsGameItem *rgi = new RsGameItem(); + rgi->serviceId = git->second.serviceId; + rgi->gameId = git->second.gameId; + rgi->gameComment = git->second.gameName; + rgi->numPlayers = git->second.numPlayers; + rgi->players.ids = git->second.peerIds; + + rgi->msg = RS_GAME_MSG_PLAY; + + /* destination */ + rgi->PeerId(*it); + + /* send Msg */ + sendItem(rgi); + } + + /* inform all the other peers that we've started the game */ + for(it = git->second.interestedPeers.begin(); + it != git->second.interestedPeers.end(); it++) + { + if (git->second.peerIds.end() == (std::find(git->second.peerIds.begin(), + git->second.peerIds.end(), *it))) + { + /* tell the them they're not needed */ + + RsGameItem *rgi = new RsGameItem(); + rgi->serviceId = git->second.serviceId; + rgi->gameId = git->second.gameId; + rgi->gameComment= git->second.gameName; + rgi->numPlayers = 0; + rgi->players.ids.clear(); + + rgi->msg = RS_GAME_MSG_REJECT; + + /* destination */ + rgi->PeerId(*it); + + /* send Msg */ + sendItem(rgi); + } + } + + /* Finally start the actual Game */ + + /* TODO */ + + + return true; + +} + +bool p3GameLauncher::quitGame(std::string gameId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::checkGameProperties()"; + std::cerr << " gameId: " << gameId; + std::cerr << std::endl; +#endif + + /* TODO */ + + return false; +} + + + +bool p3GameLauncher::invitePeer(std::string gameId, std::string peerId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::invitePeer()"; + std::cerr << " gameId: " << gameId << " peerId: " << peerId; + std::cerr << std::endl; +#endif + + std::map::iterator git; + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return false; + } + + if (git->second.state != RS_GAME_INIT_SETUP) + { + return false; + } + + if (peerId == mOwnId) + { + return false; + } + + /* send messages to peers inviting to game */ + std::list::const_iterator it; + if (git->second.allowedPeers.end() != + (it = std::find(git->second.allowedPeers.begin(), + git->second.allowedPeers.end(), peerId))) + { + return true; + } + + git->second.allowedPeers.push_back(peerId); + return true; +} + + +/* Server GUI commands */ +bool p3GameLauncher::uninvitePeer(std::string gameId, std::string peerId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::uninvitePeer()"; + std::cerr << " gameId: " << gameId << " peerId: " << peerId; + std::cerr << std::endl; +#endif + + std::map::iterator git; + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return false; + } + + if (git->second.state != RS_GAME_INIT_SETUP) + { + return false; + } + + if (peerId == mOwnId) + { + return false; + } + + /* send messages to peers inviting to game */ + std::list::iterator it; + if (git->second.allowedPeers.end() == + (it = std::find(git->second.allowedPeers.begin(), + git->second.allowedPeers.end(), peerId))) + { + return true; + } + + git->second.allowedPeers.erase(it); + return true; +} + + +bool p3GameLauncher::confirmPeer(std::string gameId, std::string peerId, + int16_t pos) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::confirmPeer()"; + std::cerr << " gameId: " << gameId << " peerId: " << peerId; + std::cerr << std::endl; +#endif + + std::map::iterator git; + + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return false; + } + + if (git->second.state != RS_GAME_INIT_CONFIRM) + { + return false; + } + + std::list::iterator it; + if (git->second.interestedPeers.end() == + (it = std::find(git->second.interestedPeers.begin(), + git->second.interestedPeers.end(), peerId))) + { + return false; + } + + it = std::find(git->second.peerIds.begin(), + git->second.peerIds.end(), peerId); + if (it != git->second.peerIds.end()) + { + git->second.peerIds.erase(it); + } + + int32_t i = 0; + for(it = git->second.peerIds.begin(); (i < pos) && + (it != git->second.peerIds.end()); it++, i++) ; + + if ((pos < 0) || (it == git->second.peerIds.end())) + { + /* */ + git->second.peerIds.push_back(peerId); + } + + git->second.peerIds.insert(it, peerId); + return confirmGame(gameId); +} + + +bool p3GameLauncher::unconfirmPeer(std::string gameId, std::string peerId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::unconfirmPeer()"; + std::cerr << " gameId: " << gameId << " peerId: " << peerId; + std::cerr << std::endl; +#endif + + std::map::iterator git; + + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return false; + } + + if (git->second.state != RS_GAME_INIT_CONFIRM) + { + return false; + } + + std::list::iterator it; + + it = std::find(git->second.peerIds.begin(), + git->second.peerIds.end(), peerId); + if (it != git->second.peerIds.end()) + { + git->second.peerIds.erase(it); + } + return confirmGame(gameId); +} + + +/* Client GUI Commands */ +bool p3GameLauncher::interestedPeer(std::string gameId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::interestedPeer()"; + std::cerr << " gameId: " << gameId; + std::cerr << std::endl; +#endif + + return inviteResponse(gameId, true); +} + +bool p3GameLauncher::uninterestedPeer(std::string gameId) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::uninterestedPeer()"; + std::cerr << " gameId: " << gameId; + std::cerr << std::endl; +#endif + + return inviteResponse(gameId, false); +} + +bool p3GameLauncher::inviteResponse(std::string gameId, bool interested) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::inviteResponse()"; + std::cerr << " gameId: " << gameId << "interested: " << interested; + std::cerr << std::endl; +#endif + + std::map::iterator git; + + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return 0; + } + + /* TODO */ + + RsGameItem *rgi = new RsGameItem(); + rgi->serviceId = git->second.serviceId; + rgi->gameId = git->second.gameId; + rgi->gameComment= git->second.gameName; + rgi->numPlayers = 0; + rgi->players.ids.clear(); + + if (interested) + { + rgi->msg = RS_GAME_MSG_INTERESTED; + git->second.state = RS_GAME_INIT_READY; + } + else + { + rgi->msg = RS_GAME_MSG_REJECT; + git->second.state = RS_GAME_INIT_INVITED; + } + + /* destination */ + rgi->PeerId(git->second.serverId); + + /* send Msg */ + sendItem(rgi); + + return 1; +} + + +/***** Details ****/ + +/* get details */ +bool p3GameLauncher::getGameList(std::list &gameList) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::getGameList()"; + std::cerr << std::endl; +#endif + + std::map::iterator git; + for(git = gamesCurrent.begin(); git != gamesCurrent.end(); git++) + { + RsGameInfo info; + + info.gameId = git->first; + info.serverId = git->second.serverId; + + std::ostringstream out; + out << "GameType: " << git->second.serviceId; + info.gameType = out.str(); + + info.serverName = "ServerName"; + info.numPlayers = git->second.numPlayers; + info.gameName = git->second.gameName; + + if (git->second.state == RS_GAME_INIT_SETUP) + { + info.status = "Setup"; + } + else if (git->second.state == RS_GAME_INIT_INVITED) + { + info.status = "Invite"; + } + else if (git->second.state == RS_GAME_INIT_CONFIRM) + { + info.status = "Confirm"; + } + else if (git->second.state == RS_GAME_INIT_READY) + { + info.status = "Ready"; + } + else if (git->second.state == RS_GAME_INIT_ACTIVE) + { + info.status = "Playing"; + } + else + { + info.status = "Unknown"; + } + + gameList.push_back(info); + } + return true; +} + +bool p3GameLauncher::getGameDetail(std::string gameId, RsGameDetail &detail) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::getGameDetail()"; + std::cerr << " gameId: " << gameId; + std::cerr << std::endl; +#endif + + std::map::iterator git; + std::list::iterator it; + git = gamesCurrent.find(gameId); + if (git == gamesCurrent.end()) + { + return false; + } + + /* fill in the details */ + detail.gameId = gameId; + detail.gameType = git->second.serviceId; + detail.gameName = git->second.gameName; + detail.areServer = git->second.areServer; + detail.serverId = git->second.serverId; + detail.serverName = "Server???"; + detail.numPlayers = git->second.numPlayers; + + if ((git->second.state == RS_GAME_INIT_SETUP) || + (git->second.state == RS_GAME_INIT_INVITED)) + { + if (git->second.state == RS_GAME_INIT_SETUP) + detail.status = "Setup"; + else + detail.status = "Invite"; + + /* copy from invited List */ + for(it = git->second.allowedPeers.begin(); + it != git->second.allowedPeers.end(); it++) + { + RsGamePeer rgp; + rgp.id = *it; + rgp.invite = true; + rgp.interested = false; + rgp.play = false; + + detail.gamers[*it] = rgp; + } + } + else if ((git->second.state == RS_GAME_INIT_CONFIRM) || + (git->second.state == RS_GAME_INIT_READY)) + { + if (git->second.state == RS_GAME_INIT_CONFIRM) + detail.status = "Confirm"; + else + detail.status = "Ready"; + + /* copy from invited List */ + for(it = git->second.allowedPeers.begin(); + it != git->second.allowedPeers.end(); it++) + { + RsGamePeer rgp; + rgp.id = *it; + rgp.invite = true; + + if (git->second.interestedPeers.end() != + std::find(git->second.interestedPeers.begin(), + git->second.interestedPeers.end(), + *it)) + { + rgp.interested = true; + } + else + { + rgp.interested = false; + } + /* if in peerIds */ + if (git->second.peerIds.end() != + std::find(git->second.peerIds.begin(), + git->second.peerIds.end(), + *it)) + { + rgp.play = true; + } + else + { + rgp.play = false; + } + detail.gamers[*it] = rgp; + } + + + } + else if (git->second.state == RS_GAME_INIT_ACTIVE) + { + detail.status = "Playing"; + + /* copy from invited List */ + for(it = git->second.peerIds.begin(); + it != git->second.peerIds.end(); it++) + { + RsGamePeer rgp; + rgp.id = *it; + rgp.invite = true; + rgp.interested = true; + rgp.play = true; + + detail.gamers[*it] = rgp; + } + } + else + { + return false; + } + return true; +} + + +/**** Network interface ****/ + +int p3GameLauncher::checkIncoming() +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::checkIncoming()"; + std::cerr << std::endl; +#endif + + /* check for incoming items */ + + RsGameItem *gi = NULL; + + while(NULL != (gi = (RsGameItem *) recvItem())) + { + handleIncoming(gi); + delete gi; + } + return 1; +} + + +int p3GameLauncher::handleIncoming(RsGameItem *gi) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << std::endl; +#endif + + /* check that its a valid packet... + * and that there is a gameStatus. + */ + + /* Always check the Properties */ + if (!checkGameProperties(gi->serviceId, gi->numPlayers)) + { +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << std::endl; +#endif + sendRejectMsg(gi); + return 0; + } + + /* check if there is an existing game? */ + std::map::iterator it; + bool haveStatus = (gamesCurrent.end() != + (it = gamesCurrent.find(gi->gameId))); + + /* handle startup first */ + if (!haveStatus) + { + if (gi->msg == RS_GAME_MSG_START) + { + /***** CLIENT HANDLING ****/ + /* we are the client -> start it up! */ + return handleClientStart(gi); + } +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << std::endl; +#endif + sendRejectMsg(gi); + return 0; + } + + /* have a current status - if we get here + * switch on + * 1) server/client. + * 2) state, + * 3) msg. + */ + + if (it->second.areServer) + { +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming() AreServer for Game"; + std::cerr << std::endl; +#endif + /***** SERVER HANDLING ****/ + switch(it->second.state) + { + case RS_GAME_INIT_CONFIRM: + /* only accept INTERESTED | REJECT */ + if ((gi->msg == RS_GAME_MSG_INTERESTED) || + (gi->msg == RS_GAME_MSG_REJECT)) + { + handleServerSetup(gi); + return 1; + } + else + { +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << " INIT_CONFIRM & msg != INT | REJ - reject"; + std::cerr << std::endl; +#endif + sendRejectMsg(gi); + return 0; + } + break; + + case RS_GAME_INIT_ACTIVE: + if ((gi->msg == RS_GAME_MSG_PAUSE) || + (gi->msg == RS_GAME_MSG_QUIT)) + { + handleServerActive(gi); + return 1; + } + else + { +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << " INIT_ACTIVE & msg != PAU | QUIT - reject "; + std::cerr << std::endl; +#endif + sendRejectMsg(gi); + return 0; + } + break; + + case RS_GAME_INIT_SETUP: /* invalid state */ + case RS_GAME_INIT_INVITED: /* invalid state */ + case RS_GAME_INIT_READY: /* invalid state */ + default: +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << " INIT_SETUP | INIT_INVITED | INIT_READY | default - reject "; + std::cerr << std::endl; +#endif + sendRejectMsg(gi); + return 0; + break; + } + } + else + { +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming() AreClient for Game"; + std::cerr << std::endl; +#endif + /***** CLIENT HANDLING ****/ + switch(it->second.state) + { + case RS_GAME_INIT_INVITED: + /* only accept REJECT */ + if (gi->msg == RS_GAME_MSG_REJECT) + { + handleClientInvited(gi); + return 1; + } + else + { +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << " INIT_INVITED & msg != REJ - reject "; + std::cerr << std::endl; +#endif + sendRejectMsg(gi); + return 0; + } + break; + + case RS_GAME_INIT_READY: + + if ((gi->msg == RS_GAME_MSG_CONFIRM) || + (gi->msg == RS_GAME_MSG_REJECT) || + (gi->msg == RS_GAME_MSG_PLAY)) + { + handleClientReady(gi); + return 1; + } + else + { +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << " INIT_READY & msg != CFM, REJ, PLY - reject "; + std::cerr << std::endl; +#endif + sendRejectMsg(gi); + return 0; + } + break; + + case RS_GAME_INIT_ACTIVE: + if ((gi->msg == RS_GAME_MSG_PAUSE) || + (gi->msg == RS_GAME_MSG_QUIT)) + { + handleClientActive(gi); + return 1; + } + else + { +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << " INIT_ACTIVE & msg != PAU, QUIT - reject "; + std::cerr << std::endl; +#endif + sendRejectMsg(gi); + return 0; + } + break; + + + case RS_GAME_INIT_SETUP: /* invalid state */ + default: +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming()"; + std::cerr << " INIT_SETUP - invalid state - reject "; + std::cerr << std::endl; +#endif + sendRejectMsg(gi); + return 0; + break; + } + } + +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleIncoming() Never Get Here - reject"; + std::cerr << std::endl; +#endif + + /* should never get here */ + sendRejectMsg(gi); + return 0; +} + + + +/***** Network Msg Functions ***** + * + * + * + handleClientStart(gi) * START msg * + handleClientInvited(gi); * REJECT msg * + handleClientReady(gi); * CONFIRM / REJECT / PLAY msg * + handleClientActive(gi); * PAUSE / QUIT msg * + + handleServerSetup(gi); * INTERESTED / REJECT msg * + handleServerActive(gi); * PAUSE / QUIT msg * + sendRejectMsg(gi); + * + * + * + */ + + /* START msg */ +int p3GameLauncher::handleClientStart(RsGameItem *gi) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleClientStart()"; + std::cerr << std::endl; +#endif + + /* Already checked existance / Properties */ + + /* else -> add into the list of games */ + gameStatus gs; + gs.serviceId = gi->serviceId; + gs.gameId = gi->gameId; + gs.gameName = gi->gameComment; + gs.areServer = false; + gs.serverId = gi->PeerId(); + gs.state = RS_GAME_INIT_INVITED; /* Client */ + gs.numPlayers = gi->numPlayers; + gs.allowedPeers = gi->players.ids; + //gs.interestedPeers = gi->players.ids; + //gs.peerIds = gi->players.ids; + + gamesCurrent[gi->gameId] = gs; + + return 1; +} + + /* REJECT msg */ +int p3GameLauncher::handleClientInvited(RsGameItem *gi) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleClientInvited()"; + std::cerr << std::endl; +#endif + + /* cleanup game */ + cleanupGame(gi->gameId); + return 1; +} + + /* CONFIRM / REJECT / PLAY msg */ +int p3GameLauncher::handleClientReady(RsGameItem *gi) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleClientReady()"; + std::cerr << std::endl; +#endif + + /* get game */ + std::map::iterator it; + if (gamesCurrent.end() == (it = gamesCurrent.find(gi->gameId))) + { + /* no game exists */ + return 0; + } + + switch(gi->msg) + { + case RS_GAME_MSG_CONFIRM: + + /* update the information + * (other info should be the same) + */ + it->second.numPlayers = gi->numPlayers; + // Which one? + it->second.interestedPeers = gi->players.ids; + //it->second.peerIds = gi->players.ids; + + return 1; + break; + + case RS_GAME_MSG_REJECT: + cleanupGame(gi->gameId); + return 1; + break; + + case RS_GAME_MSG_PLAY: + /* TODO */ + return 1; + break; + default: + break; + } + return 0; +} + + /* PAUSE / QUIT msg */ +int p3GameLauncher::handleClientActive(RsGameItem *gi) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleClientActive()"; + std::cerr << std::endl; +#endif + + + + return 1; +} + + + /* INTERESTED / REJECT msg */ +int p3GameLauncher::handleServerSetup(RsGameItem *gi) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleServerSetup()"; + std::cerr << std::endl; +#endif + + /* check if there is an existing game? */ + std::map::iterator it; + if (gamesCurrent.end() == (it = gamesCurrent.find(gi->gameId))) + { + /* no game exists */ + return 0; + } + + /* we only care about this notice -> if we're the server */ + if (it->second.areServer) + { + std::list::iterator it2, it3; + it2 = std::find(it->second.allowedPeers.begin(), + it->second.allowedPeers.end(), gi->PeerId()); + it3 = std::find(it->second.interestedPeers.begin(), + it->second.interestedPeers.end(), gi->PeerId()); + + if ((it2 != it->second.allowedPeers.end()) && + (it3 == it->second.interestedPeers.end())) + { + it->second.interestedPeers.push_back(gi->PeerId()); + return 1; + } + } + return 0; +} + +/* This is a setup update from server + * only updates the players... + */ +int p3GameLauncher::handleServerActive(RsGameItem *gi) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::handleServerActive()"; + std::cerr << std::endl; +#endif + + + return 1; +} + +int p3GameLauncher::sendRejectMsg(RsGameItem *gi) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::sendRejectMsg()"; + std::cerr << std::endl; +#endif + + /* all should be okay ... except msg */ + + RsGameItem *response = new RsGameItem(); + response->serviceId = gi->serviceId; + response->numPlayers = gi->numPlayers; + response->msg = RS_GAME_MSG_REJECT; + response->gameId = gi->gameId; + response->gameComment = gi->gameComment; + response->players.ids = gi->players.ids; + + sendItem(response); + return 1; +} + +bool p3GameLauncher::checkGameProperties(uint16_t serviceId, uint16_t players) +{ +#ifdef GAME_DEBUG + std::cerr << "p3GameLauncher::checkGameProperties()"; + std::cerr << std::endl; +#endif + +#ifdef TEST_NO_GAMES + return true; +#endif + + std::map::iterator it; + if (gameList.end() == (it = gameList.find(serviceId))) + { + return false; /* we don't support the game */ + } + + if ((players <= it->second->getMaxPlayers()) && + (players >= it->second->getMinPlayers())) + { + return true; + } + return false; +} + diff --git a/libretroshare/src/services/p3gamelauncher.h b/libretroshare/src/services/p3gamelauncher.h new file mode 100644 index 000000000..70e55a191 --- /dev/null +++ b/libretroshare/src/services/p3gamelauncher.h @@ -0,0 +1,151 @@ +/* + * libretroshare/src/services: p3gamelauncher.h + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef SERVICE_GAME_LAUNCHER_HEADER +#define SERVICE_GAME_LAUNCHER_HEADER + +/* + * A central point to setup games between peers. + * + */ + +#include +#include + +#include "services/p3service.h" +#include "serialiser/rsgameitems.h" +#include "retroshare/rsgame.h" + +class p3ConnectMgr; + + +class gameAvail +{ + uint32_t serviceId; + std::string gameName; + uint16_t minPlayers; + uint16_t maxPlayers; +}; + +class gameStatus +{ + public: + + uint32_t serviceId; + std::string gameId; + std::wstring gameName; + + bool areServer; /* are we the server? */ + std::string serverId; /* if not, who is? */ + + uint16_t numPlayers; + std::list allowedPeers; /* who can play ( controlled by server) */ + std::list interestedPeers; /* who wants to play ( controlled by server) */ + std::list peerIds; /* in order of turns */ + + uint32_t state; +}; + +class p3GameService; + +/* We're going to add the external Interface - directly on here! */ + +class p3GameLauncher: public p3Service, public RsGameLauncher +{ + public: + p3GameLauncher(p3ConnectMgr *connMgr); + + /***** EXTERNAL RsGameLauncher Interface *******/ +/* server commands */ +virtual std::string createGame(uint32_t gameType, std::wstring name); +virtual bool deleteGame(std::string gameId); +virtual bool inviteGame(std::string gameId); +virtual bool playGame(std::string gameId); +//virtual bool quitGame(std::string gameId); + +virtual bool invitePeer(std::string gameId, std::string peerId); +virtual bool uninvitePeer(std::string gameId, std::string peerId); +virtual bool confirmPeer(std::string gameId, std::string peerId, + int16_t pos = -1); +virtual bool unconfirmPeer(std::string gameId, std::string peerId); + +/* client commands */ +virtual bool interestedPeer(std::string gameId); +virtual bool uninterestedPeer(std::string gameId); + +/* get details */ +virtual bool getGameList(std::list &gameList); +virtual bool getGameDetail(std::string gameId, RsGameDetail &detail); + /***** EXTERNAL RsGameLauncher Interface *******/ + + /* support functions */ + private: +std::string newGame(uint16_t srvId, std::wstring name); +bool confirmGame(std::string gameId); +bool quitGame(std::string gameId); +bool inviteResponse(std::string gameId, bool interested); + + + /* p3Service Overloaded */ +virtual int tick(); +virtual int status(); + + /* add in the Game */ +int addGameService(p3GameService *game); + /* notify gameService/peers */ + +//int getGameList(std::list &games); +//int getGamesCurrent(std::list &games); +//int getGameDetails(std::string gid, gameStatus &status); + + /**** GUI Interface ****/ + +bool resumeGame(std::string gameId); + + /**** Network Interface ****/ +int checkIncoming(); +int handleIncoming(RsGameItem *gi); + +int handleClientStart(RsGameItem *gi); /* START msg */ +int handleClientInvited(RsGameItem *gi); /* REJECT msg */ +int handleClientReady(RsGameItem *gi); /* CONFIRM / REJECT / PLAY msg */ +int handleClientActive(RsGameItem *gi); /* PAUSE / QUIT msg */ + +int handleServerSetup(RsGameItem *gi); /* INTERESTED / REJECT msg */ +int handleServerActive(RsGameItem *gi); /* PAUSE / QUIT msg */ + +int sendRejectMsg(RsGameItem *gi); /* --- error msg */ +void cleanupGame(std::string gameId); /* remove from list */ +bool checkGameProperties(uint16_t serviceId, uint16_t players); + +std::map gameList; +std::map gamesCurrent; + + p3ConnectMgr *mConnMgr; + std::string mOwnId; +}; + +#endif // SERVICE_GAME_LAUNCHER_HEADER diff --git a/libretroshare/src/services/p3gameservice.h b/libretroshare/src/services/p3gameservice.h new file mode 100644 index 000000000..c2bf348a2 --- /dev/null +++ b/libretroshare/src/services/p3gameservice.h @@ -0,0 +1,90 @@ +/* + * libretroshare/src/services: p3gameservice.h + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef P3_SERVICE_GAME_HEADER +#define P3_SERVICE_GAME_HEADER + +/* + * A central point to setup games between peers. + * + */ + +#include +#include + +#include "services/p3service.h" + +class StoredGame +{ + public: + std::string gameId; + time_t startTime; + std::list peerIds; /* in order of turns */ +}; + +class p3GameLauncher; +class p3Service; + +class p3GameService +{ + public: + + p3GameService(uint16_t sId, std::string name, uint16_t min, uint16_t max, p3GameLauncher *l) + :serviceId(sId), gameName(name), minPlayers(min), maxPlayers(max), + service(NULL), launcher(l) + { return; } + +virtual ~p3GameService() + { return; } + + /*************** Game Interface ******************/ + /* saved games */ +virtual void getSavedGames(std::list &gList); + + /* start a game */ +virtual void startGame(StoredGame &newGame, bool resume); +virtual void quitGame(std::string gameId); +virtual void deleteGame(std::string gameId); + /*************** Game Interface ******************/ + + /* details for the Launcher */ + uint16_t getServiceId() { return serviceId; } + std::string getGameName() { return gameName; } + uint16_t getMinPlayers() { return minPlayers; } + uint16_t getMaxPlayers() { return maxPlayers; } + p3GameLauncher *getLauncher() { return launcher; } + + private: + + uint16_t serviceId; + std::string gameName; + uint16_t minPlayers, maxPlayers; + + p3Service *service; + p3GameLauncher *launcher; +}; + +#endif // P3_SERVICE_GAME_HEADER diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc new file mode 100644 index 000000000..2b0cb109b --- /dev/null +++ b/libretroshare/src/services/p3msgservice.cc @@ -0,0 +1,1481 @@ +/* + * libretroshare/src/services msgservice.cc + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "retroshare/rsiface.h" + +#include "pqi/pqibin.h" +#include "pqi/pqiarchive.h" +#include "pqi/p3connmgr.h" + +#include "services/p3msgservice.h" +#include "pqi/pqinotify.h" + +#include "util/rsdebug.h" +#include "util/rsdir.h" + +#include +#include +#include + +const int msgservicezone = 54319; + +/* Another little hack ..... unique message Ids + * will be handled in this class..... + * These are unique within this run of the server, + * and are not stored long term.... + * + * Only 3 entry points: + * (1) from network.... + * (2) from local send + * (3) from storage... + */ + + +p3MsgService::p3MsgService(p3ConnectMgr *cm) + :p3Service(RS_SERVICE_TYPE_MSG), p3Config(CONFIG_TYPE_MSGS), + mConnMgr(cm), msgChanged(1), mMsgUniqueId(1) +{ + addSerialType(new RsMsgSerialiser()); + + /* Initialize standard tag types */ + if(cm) + initStandardTagTypes(); +} + +uint32_t p3MsgService::getNewUniqueMsgId() +{ + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + return mMsgUniqueId++; +} + +/****** Mods/Notifications ****/ + +bool p3MsgService::MsgsChanged() +{ + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + bool m1 = msgChanged.Changed(); + + return (m1); +} + +bool p3MsgService::MsgNotifications() +{ + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + return (msgNotifications.size() > 0); +} + +bool p3MsgService::getMessageNotifications(std::list ¬eList) +{ + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + noteList = msgNotifications; + msgNotifications.clear(); + + return (noteList.size() > 0); +} + + + +int p3MsgService::tick() +{ + pqioutput(PQL_DEBUG_BASIC, msgservicezone, + "p3MsgService::tick()"); + + /* don't worry about increasing tick rate! + * (handled by p3service) + */ + + incomingMsgs(); + //checkOutgoingMessages(); + + return 0; +} + + +int p3MsgService::status() +{ + pqioutput(PQL_DEBUG_BASIC, msgservicezone, + "p3MsgService::status()"); + + return 1; +} + +void p3MsgService::processMsg(RsMsgItem *mi) +{ + mi -> recvTime = time(NULL); + mi -> msgId = getNewUniqueMsgId(); + + std::string mesg; + + RsStackMutex stack(mMsgMtx); /*** STACK LOCKED MTX ***/ + + if (mi -> PeerId() == mConnMgr->getOwnId()) + { + /* from the loopback device */ + mi -> msgFlags |= RS_MSG_FLAGS_OUTGOING; + } + else + { + mi -> msgFlags = RS_MSG_FLAGS_NEW; + + /* from a peer */ + MsgInfoSummary mis; + initRsMIS(mi, mis); + + // msgNotifications.push_back(mis); + pqiNotify *notify = getPqiNotify(); + if (notify) + { + std::string message , title; + notify->AddPopupMessage(RS_POPUP_MSG, mi->PeerId(), + title.assign(mi->subject.begin(), mi->subject.end()), + message.assign(mi->message.begin(),mi->message.end())); + + std::ostringstream out; + out << mi->msgId; + notify->AddFeedItem(RS_FEED_ITEM_MESSAGE, out.str(), "", ""); + } + } + + imsg[mi->msgId] = mi; + RsMsgSrcId* msi = new RsMsgSrcId(); + msi->msgId = mi->msgId; + msi->srcId = mi->PeerId(); + mSrcIds.insert(std::pair(msi->msgId, msi)); + msgChanged.IndicateChanged(); + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + /**** STACK UNLOCKED ***/ +} + +int p3MsgService::incomingMsgs() +{ + RsMsgItem *mi; + int i = 0; + bool changed = false ; + + while((mi = (RsMsgItem *) recvItem()) != NULL) + { + changed = true ; + ++i; + + processMsg(mi); + } + if(changed) + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); + + return 1; +} + +void p3MsgService::statusChange(const std::list &plist) +{ + /* should do it properly! */ + checkOutgoingMessages(); +} + +int p3MsgService::checkOutgoingMessages() +{ + /* iterate through the outgoing queue + * + * if online, send + */ + + bool changed = false ; + + { + const std::string ownId = mConnMgr->getOwnId(); + + std::list::iterator it; + std::list toErase; + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator mit; + for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); mit++) + { + if (mit->second->msgFlags & RS_MSG_FLAGS_TRASH) { + continue; + } + + /* find the certificate */ + std::string pid = mit->second->PeerId(); + peerConnectState pstate; + bool toSend = false; + + if (mConnMgr->getFriendNetStatus(pid, pstate)) + { + if (pstate.state & RS_PEER_S_CONNECTED) + { + toSend = true; + } + } + else if (pid == ownId) /* FEEDBACK Msg to Ourselves */ + { + toSend = true; + } + + if (toSend) + { + /* send msg */ + pqioutput(PQL_DEBUG_BASIC, msgservicezone, + "p3MsgService::checkOutGoingMessages() Sending out message"); + /* remove the pending flag */ + (mit->second)->msgFlags &= ~RS_MSG_FLAGS_PENDING; + + sendItem(mit->second); + toErase.push_back(mit->first); + + changed = true ; + } + else + { + pqioutput(PQL_DEBUG_BASIC, msgservicezone, + "p3MsgService::checkOutGoingMessages() Delaying until available..."); + } + } + + /* clean up */ + for(it = toErase.begin(); it != toErase.end(); it++) + { + mit = msgOutgoing.find(*it); + if (mit != msgOutgoing.end()) + { + msgOutgoing.erase(mit); + } + + std::map::iterator srcIt = mSrcIds.find(*it); + if (srcIt != mSrcIds.end()) { + delete (srcIt->second); + mSrcIds.erase(srcIt); + } + } + + if (toErase.size() > 0) + { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } + } + + if(changed) + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); + + return 0; +} + + + + +bool p3MsgService::saveList(bool& cleanup, std::list& itemList) +{ + + std::map::iterator mit; + std::map::iterator mit2; + std::map::iterator mit3; + std::map::iterator lit; + std::map::iterator mit4; + + MsgTagType stdTags; + + cleanup = false; + + mMsgMtx.lock(); + + for(mit = imsg.begin(); mit != imsg.end(); mit++) + itemList.push_back(mit->second); + + for(lit = mSrcIds.begin(); lit != mSrcIds.end(); lit++) + itemList.push_back(lit->second); + + + for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); mit++) + itemList.push_back(mit->second) ; + + for(mit2 = mTags.begin(); mit2 != mTags.end(); mit2++) + itemList.push_back(mit2->second); + + for(mit3 = mMsgTags.begin(); mit3 != mMsgTags.end(); mit3++) + itemList.push_back(mit3->second); + + for(mit4 = mParentId.begin(); mit4 != mParentId.end(); mit4++) + itemList.push_back(mit4->second); + + return true; +} + +void p3MsgService::saveDone() +{ + // unlocks mutex which has been locked by savelist + mMsgMtx.unlock(); +} + +RsSerialiser* p3MsgService::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser ; + rss->addSerialType(new RsMsgSerialiser(true)); + return rss; +} + +// build list of standard tag types +static void getStandardTagTypes(MsgTagType &tags) +{ + /* create standard tag types, the text must be translated in the GUI */ + tags.types [RS_MSGTAGTYPE_IMPORTANT] = std::pair ("Important", 0xFF0000); + tags.types [RS_MSGTAGTYPE_WORK] = std::pair ("Work", 0xFF9900); + tags.types [RS_MSGTAGTYPE_PERSONAL] = std::pair ("Personal", 0x009900); + tags.types [RS_MSGTAGTYPE_TODO] = std::pair ("Todo", 0x3333FF); + tags.types [RS_MSGTAGTYPE_LATER] = std::pair ("Later", 0x993399); +} + +// Initialize the standard tag types after load +void p3MsgService::initStandardTagTypes() +{ + bool bChanged = false; + std::string ownId = mConnMgr->getOwnId(); + + MsgTagType tags; + getStandardTagTypes(tags); + + std::map >::iterator tit; + for (tit = tags.types.begin(); tit != tags.types.end(); tit++) { + std::map::iterator mit = mTags.find(tit->first); + if (mit == mTags.end()) { + RsMsgTagType* tagType = new RsMsgTagType(); + tagType->PeerId (ownId); + tagType->tagId = tit->first; + tagType->text = tit->second.first; + tagType->rgb_color = tit->second.second; + + mTags.insert(std::pair(tit->first, tagType)); + + bChanged = true; + } + } + + if (bChanged) { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } +} + +bool p3MsgService::loadList(std::list& load) +{ + RsMsgItem *mitem; + RsMsgTagType* mtt; + RsMsgTags* mti; + RsMsgSrcId* msi; + RsMsgParentId* msp; + + std::list items; + std::list::iterator it; + std::map::iterator tagIt; + std::map srcIdMsgMap; + std::map::iterator srcIt; + + + // load items and calculate next unique msgId + for(it = load.begin(); it != load.end(); it++) + { + + if (NULL != (mitem = dynamic_cast(*it))) + { + /* STORE MsgID */ + if (mitem->msgId >= mMsgUniqueId) { + mMsgUniqueId = mitem->msgId + 1; + } + items.push_back(mitem); + } + else if(NULL != (mtt = dynamic_cast(*it))) + { + // delete standard tags as they are now save in config + if(mTags.end() == (tagIt = mTags.find(mtt->tagId))) + { + mTags.insert(std::pair(mtt->tagId, mtt)); + } + else + { + delete mTags[mtt->tagId]; + mTags.erase(tagIt); + mTags.insert(std::pair(mtt->tagId, mtt)); + } + + } + else if(NULL != (mti = dynamic_cast(*it))) + { + mMsgTags.insert(std::pair(mti->msgId, mti)); + } + else if(NULL != (msi = dynamic_cast(*it))) + { + srcIdMsgMap.insert(std::pair(msi->msgId, msi->srcId)); + mSrcIds.insert(std::pair(msi->msgId, msi)); // does not need to be kept + } + else if(NULL != (msp = dynamic_cast(*it))) + { + mParentId.insert(std::pair(msp->msgId, msp)); + } + } + + // sort items into lists + std::list::iterator msgIt; + for (msgIt = items.begin(); msgIt != items.end(); msgIt++) + { + mitem = *msgIt; + + /* STORE MsgID */ + if (mitem->msgId == 0) { + mitem->msgId = getNewUniqueMsgId(); + } + + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + srcIt = srcIdMsgMap.find(mitem->msgId); + if(srcIt != srcIdMsgMap.end()) { + mitem->PeerId(srcIt->second); + srcIdMsgMap.erase(srcIt); + } + + /* switch depending on the PENDING + * flags + */ + if (mitem -> msgFlags & RS_MSG_FLAGS_PENDING) + { + + //std::cerr << "MSG_PENDING"; + //std::cerr << std::endl; + //mitem->print(std::cerr); + + msgOutgoing[mitem->msgId] = mitem; + } + else + { + imsg[mitem->msgId] = mitem; + } + } + + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + /* remove missing msgId in mSrcIds */ + for (srcIt = srcIdMsgMap.begin(); srcIt != srcIdMsgMap.end(); srcIt++) { + std::map::iterator it = mSrcIds.find(srcIt->first); + if (it != mSrcIds.end()) { + delete(it->second); + mSrcIds.erase(it); + } + } + + /* remove missing msgId in mParentId */ + std::map::iterator mit = mParentId.begin(); + while (mit != mParentId.end()) { + if (imsg.find(mit->first) == imsg.end()) { + if (msgOutgoing.find(mit->first) == msgOutgoing.end()) { + /* not found */ + mParentId.erase(mit++); + continue; + } + } + + mit++; + } + + return true; +} + + +void p3MsgService::loadWelcomeMsg() +{ + /* Load Welcome Message */ + RsMsgItem *msg = new RsMsgItem(); + + //msg -> PeerId(mConnMgr->getOwnId()); + + msg -> sendTime = time(NULL); + msg -> recvTime = time(NULL); + msg -> msgFlags = RS_MSG_FLAGS_NEW; + + msg -> subject = L"Welcome to Retroshare"; + + msg -> message = L"Send and receive messages with your friends...\n"; + msg -> message += L"These can hold recommendations from your local shared files.\n\n"; + msg -> message += L"Add recommendations through the Local Files Dialog.\n\n"; + msg -> message += L"Enjoy."; + + msg -> msgId = getNewUniqueMsgId(); + + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + imsg[msg->msgId] = msg; + + IndicateConfigChanged(); +} + + +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ + + +/****************************************/ +/****************************************/ + +bool p3MsgService::getMessageSummaries(std::list &msgList) +{ + /* do stuff */ + msgList.clear(); + + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator mit; + for(mit = imsg.begin(); mit != imsg.end(); mit++) + { + MsgInfoSummary mis; + initRsMIS(mit->second, mis); + msgList.push_back(mis); + } + + for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); mit++) + { + MsgInfoSummary mis; + initRsMIS(mit->second, mis); + msgList.push_back(mis); + } + return true; +} + + +bool p3MsgService::getMessage(const std::string &mId, MessageInfo &msg) +{ + std::map::iterator mit; + uint32_t msgId = atoi(mId.c_str()); + + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + mit = imsg.find(msgId); + if (mit == imsg.end()) + { + mit = msgOutgoing.find(msgId); + if (mit == msgOutgoing.end()) + { + return false; + } + } + + /* mit valid */ + initRsMI(mit->second, msg); + return true; +} + +void p3MsgService::getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox) +{ + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + if (pnInbox) *pnInbox = 0; + if (pnInboxNew) *pnInboxNew = 0; + if (pnOutbox) *pnOutbox = 0; + if (pnDraftbox) *pnDraftbox = 0; + if (pnSentbox) *pnSentbox = 0; + if (pnTrashbox) *pnTrashbox = 0; + + std::map::iterator mit; + std::map *apMsg [2] = { &imsg, &msgOutgoing }; + + for (int i = 0; i < 2; i++) { + for (mit = apMsg [i]->begin(); mit != apMsg [i]->end(); mit++) { + MsgInfoSummary mis; + initRsMIS(mit->second, mis); + + if (mis.msgflags & RS_MSG_TRASH) { + if (pnTrashbox) (*pnTrashbox)++; + continue; + } + switch (mis.msgflags & RS_MSG_BOXMASK) { + case RS_MSG_INBOX: + if (pnInbox) (*pnInbox)++; + if ((mis.msgflags & RS_MSG_NEW) == RS_MSG_NEW) { + if (pnInboxNew) (*pnInboxNew)++; + } + break; + case RS_MSG_OUTBOX: + if (pnOutbox) (*pnOutbox)++; + break; + case RS_MSG_DRAFTBOX: + if (pnDraftbox) (*pnDraftbox)++; + break; + case RS_MSG_SENTBOX: + if (pnSentbox) (*pnSentbox)++; + break; + } + } + } +} + +/* remove based on the unique mid (stored in sid) */ +bool p3MsgService::removeMsgId(const std::string &mid) +{ + std::map::iterator mit; + uint32_t msgId = atoi(mid.c_str()); + if (msgId == 0) { + std::cerr << "p3MsgService::removeMsgId: Unknown msgId " << msgId << std::endl; + return false; + } + + bool changed = false; + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + mit = imsg.find(msgId); + if (mit != imsg.end()) + { + changed = true; + RsMsgItem *mi = mit->second; + imsg.erase(mit); + delete mi; + } + + mit = msgOutgoing.find(msgId); + if (mit != msgOutgoing.end()) + { + changed = true ; + RsMsgItem *mi = mit->second; + msgOutgoing.erase(mit); + delete mi; + } + + std::map::iterator srcIt = mSrcIds.find(msgId); + if (srcIt != mSrcIds.end()) { + changed = true; + delete (srcIt->second); + mSrcIds.erase(srcIt); + } + } + + if(changed) { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + setMessageTag(mid, 0, false); + setMsgParentId(msgId, 0); + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); + } + + return changed; +} + +bool p3MsgService::markMsgIdRead(const std::string &mid, bool unreadByUser) +{ + std::map::iterator mit; + uint32_t msgId = atoi(mid.c_str()); + bool changed = false; + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + mit = imsg.find(msgId); + if (mit != imsg.end()) + { + RsMsgItem *mi = mit->second; + + uint32_t msgFlags = mi->msgFlags; + + /* remove new state */ + mi->msgFlags &= ~(RS_MSG_FLAGS_NEW); + + /* set state from user */ + if (unreadByUser) { + mi->msgFlags |= RS_MSG_FLAGS_UNREAD_BY_USER; + } else { + mi->msgFlags &= ~RS_MSG_FLAGS_UNREAD_BY_USER; + } + + if (mi->msgFlags != msgFlags) + { + changed = true; + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } + } else { + return false; + } + } /* UNLOCKED */ + + if (changed) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); + } + + return true; +} + +bool p3MsgService::setMsgFlag(const std::string &mid, uint32_t flag, uint32_t mask) +{ + std::map::iterator mit; + uint32_t msgId = atoi(mid.c_str()); + + bool changed = false; + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + mit = imsg.find(msgId); + if (mit == imsg.end()) + { + mit = msgOutgoing.find(msgId); + if (mit == msgOutgoing.end()) + { + return false; + } + } + + uint32_t oldFlag = mit->second->msgFlags; + + mit->second->msgFlags &= ~mask; + mit->second->msgFlags |= flag; + + if (mit->second->msgFlags != oldFlag) { + changed = true; + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } + } /* UNLOCKED */ + + if (changed) { + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); + } + + return true; +} + +bool p3MsgService::getMsgParentId(const std::string &msgId, std::string &msgParentId) +{ + msgParentId.clear(); + + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator mit = mParentId.find(atoi(msgId.c_str())); + if (mit == mParentId.end()) { + return false; + } + + std::ostringstream out; + out << mit->second->msgParentId; + msgParentId = out.str(); + + return true; +} + +bool p3MsgService::setMsgParentId(uint32_t msgId, uint32_t msgParentId) +{ + std::map::iterator mit; + + bool changed = false; + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + mit = mParentId.find(msgId); + if (mit == mParentId.end()) + { + if (msgParentId) { + RsMsgParentId* msp = new RsMsgParentId(); + msp->PeerId (mConnMgr->getOwnId()); + msp->msgId = msgId; + msp->msgParentId = msgParentId; + mParentId.insert(std::pair(msgId, msp)); + + changed = true; + } + } else { + if (msgParentId) { + if (mit->second->msgParentId != msgParentId) { + mit->second->msgParentId = msgParentId; + changed = true; + } + } else { + delete mit->second; + mParentId.erase(mit); + changed = true; + } + } + } /* UNLOCKED */ + + if (changed) { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + } + + return true; +} + +/****************************************/ +/****************************************/ + /* Message Items */ +int p3MsgService::sendMessage(RsMsgItem *item) +{ + pqioutput(PQL_DEBUG_BASIC, msgservicezone, + "p3MsgService::sendMessage()"); + + item -> msgId = getNewUniqueMsgId(); /* grabs Mtx as well */ + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + /* add pending flag */ + item->msgFlags |= (RS_MSG_FLAGS_OUTGOING | RS_MSG_FLAGS_PENDING); + /* STORE MsgID */ + msgOutgoing[item->msgId] = item; + + if (item->PeerId() != mConnMgr->getOwnId()) { + /* not to the loopback device */ + RsMsgSrcId* msi = new RsMsgSrcId(); + msi->msgId = item->msgId; + msi->srcId = item->PeerId(); + mSrcIds.insert(std::pair(msi->msgId, msi)); + } + } + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + checkOutgoingMessages(); + + return 1; +} + +bool p3MsgService::MessageSend(MessageInfo &info) +{ + std::list::const_iterator pit; + for(pit = info.msgto.begin(); pit != info.msgto.end(); pit++) + { + RsMsgItem *msg = initMIRsMsg(info, *pit); + if (msg) + { + sendMessage(msg); + } + } + + for(pit = info.msgcc.begin(); pit != info.msgcc.end(); pit++) + { + RsMsgItem *msg = initMIRsMsg(info, *pit); + if (msg) + { + sendMessage(msg); + } + } + + for(pit = info.msgbcc.begin(); pit != info.msgbcc.end(); pit++) + { + RsMsgItem *msg = initMIRsMsg(info, *pit); + if (msg) + { + sendMessage(msg); + } + } + + /* send to ourselves as well */ + RsMsgItem *msg = initMIRsMsg(info, mConnMgr->getOwnId()); + if (msg) + { + /* use processMsg to get the new msgId */ +// sendMessage(msg); + processMsg(msg); + + // return new message id + std::ostringstream out; + out << msg->msgId; + info.msgId = out.str(); + } + + return true; +} + +bool p3MsgService::MessageToDraft(MessageInfo &info, const std::string &msgParentId) +{ + RsMsgItem *msg = initMIRsMsg(info, mConnMgr->getOwnId()); + if (msg) + { + uint32_t msgId = 0; + if (info.msgId.empty() == false) { + msgId = atoi(info.msgId.c_str()); + } + + if (msgId) { + msg->msgId = msgId; + } else { + msg->msgId = getNewUniqueMsgId(); /* grabs Mtx as well */ + } + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + /* add pending flag */ + msg->msgFlags |= (RS_MSG_OUTGOING | RS_MSG_FLAGS_DRAFT); + + if (msgId) { + // remove existing message + std::map::iterator mit; + mit = imsg.find(msgId); + if (mit != imsg.end()) { + RsMsgItem *mi = mit->second; + imsg.erase(mit); + delete mi; + } + } + /* STORE MsgID */ + imsg[msg->msgId] = msg; + + // return new message id + std::ostringstream out; + out << msg->msgId; + info.msgId = out.str(); + } + + setMsgParentId(msg->msgId, atoi(msgParentId.c_str())); + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); + + return true; + } + + return false; +} + +bool p3MsgService::getMessageTagTypes(MsgTagType& tags) +{ + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator mit; + + for(mit = mTags.begin(); mit != mTags.end(); mit++) { + std::pair p(mit->second->text, mit->second->rgb_color); + tags.types.insert(std::pair >(mit->first, p)); + } + + return true; +} + +bool p3MsgService::setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color) +{ + int nNotifyType = 0; + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator mit; + mit = mTags.find(tagId); + + if (mit == mTags.end()) { + if (tagId < RS_MSGTAGTYPE_USER) { + std::cerr << "p3MsgService::MessageSetTagType: Standard tag type " << tagId << " cannot be inserted" << std::endl; + return false; + } + + /* new tag */ + RsMsgTagType* tagType = new RsMsgTagType(); + tagType->PeerId (mConnMgr->getOwnId()); + tagType->rgb_color = rgb_color; + tagType->tagId = tagId; + tagType->text = text; + + mTags.insert(std::pair(tagId, tagType)); + + nNotifyType = NOTIFY_TYPE_ADD; + } else { + if (mit->second->text != text || mit->second->rgb_color != rgb_color) { + /* modify existing tag */ + if (tagId >= RS_MSGTAGTYPE_USER) { + mit->second->text = text; + } else { + /* don't change text for standard tag types */ + if (mit->second->text != text) { + std::cerr << "p3MsgService::MessageSetTagType: Text " << text << " for standard tag type " << tagId << " cannot be changed" << std::endl; + } + } + mit->second->rgb_color = rgb_color; + + nNotifyType = NOTIFY_TYPE_MOD; + } + } + + } /* UNLOCKED */ + + if (nNotifyType) { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGE_TAGS, nNotifyType); + + return true; + } + + return false; +} + +bool p3MsgService::removeMessageTagType(uint32_t tagId) +{ + if (tagId < RS_MSGTAGTYPE_USER) { + std::cerr << "p3MsgService::MessageRemoveTagType: Can't delete standard tag type " << tagId << std::endl; + return false; + } + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator mit; + mit = mTags.find(tagId); + + if (mit == mTags.end()) { + /* tag id not found */ + std::cerr << "p3MsgService::MessageRemoveTagType: Tag Id not found " << tagId << std::endl; + return false; + } + + /* search for messages with this tag type */ + std::map::iterator mit1; + for (mit1 = mMsgTags.begin(); mit1 != mMsgTags.end(); ) { + RsMsgTags* tag = mit1->second; + + std::list::iterator lit; + lit = std::find(tag->tagIds.begin(), tag->tagIds.end(), tagId); + if (lit != tag->tagIds.end()) { + tag->tagIds.erase(lit); + + if (tag->tagIds.size() == 0) { + /* remove empty tag */ + delete(tag); + + mMsgTags.erase(mit1++); + continue; + } + } + mit1++; + } + + /* remove tag type */ + delete(mit->second); + mTags.erase(mit); + + } /* UNLOCKED */ + + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGE_TAGS, NOTIFY_TYPE_DEL); + + return true; +} + +bool p3MsgService::getMessageTag(const std::string &msgId, MsgTagInfo& info) +{ + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + uint32_t mid = atoi(msgId.c_str()); + if (mid == 0) { + std::cerr << "p3MsgService::MessageGetMsgTag: Unknown msgId " << msgId << std::endl; + return false; + } + + std::map::iterator mit; + + if(mMsgTags.end() != (mit = mMsgTags.find(mid))) { + std::ostringstream out; + out << mit->second->msgId; + + info.msgId = out.str(); + info.tagIds = mit->second->tagIds; + + return true; + } + + return false; +} + +/* set == false && tagId == 0 --> remove all */ +bool p3MsgService::setMessageTag(const std::string &msgId, uint32_t tagId, bool set) +{ + uint32_t mid = atoi(msgId.c_str()); + if (mid == 0) { + std::cerr << "p3MsgService::MessageSetMsgTag: Unknown msgId " << msgId << std::endl; + return false; + } + + if (tagId == 0) { + if (set == true) { + std::cerr << "p3MsgService::MessageSetMsgTag: No valid tagId given " << tagId << std::endl; + return false; + } + } + + int nNotifyType = 0; + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator mit; + mit = mMsgTags.find(mid); + + if (mit == mMsgTags.end()) { + if (set) { + /* new msg */ + RsMsgTags* tag = new RsMsgTags(); + tag->PeerId (mConnMgr->getOwnId()); + + tag->msgId = mid; + tag->tagIds.push_back(tagId); + + mMsgTags.insert(std::pair(tag->msgId, tag)); + + nNotifyType = NOTIFY_TYPE_ADD; + } + } else { + RsMsgTags* tag = mit->second; + + /* search existing tagId */ + std::list::iterator lit; + if (tagId) { + lit = std::find(tag->tagIds.begin(), tag->tagIds.end(), tagId); + } else { + lit = tag->tagIds.end(); + } + + if (set) { + if (lit == tag->tagIds.end()) { + tag->tagIds.push_back(tagId); + /* keep the list sorted */ + tag->tagIds.sort(); + nNotifyType = NOTIFY_TYPE_ADD; + } + } else { + if (tagId == 0) { + /* remove all */ + delete(tag); + mMsgTags.erase(mit); + nNotifyType = NOTIFY_TYPE_DEL; + } else { + if (lit != tag->tagIds.end()) { + tag->tagIds.erase(lit); + nNotifyType = NOTIFY_TYPE_DEL; + + if (tag->tagIds.size() == 0) { + /* remove empty tag */ + delete(tag); + mMsgTags.erase(mit); + } + } + } + } + } + + } /* UNLOCKED */ + + if (nNotifyType) { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGE_TAGS, nNotifyType); + + return true; + } + + return false; +} + +bool p3MsgService::resetMessageStandardTagTypes(MsgTagType& tags) +{ + MsgTagType standardTags; + getStandardTagTypes(standardTags); + + std::map >::iterator mit; + for (mit = standardTags.types.begin(); mit != standardTags.types.end(); mit++) { + tags.types[mit->first] = mit->second; + } + + return true; +} + +/* move message to trash based on the unique mid */ +bool p3MsgService::MessageToTrash(const std::string &mid, bool bTrash) +{ + std::map::iterator mit; + uint32_t msgId = atoi(mid.c_str()); + + bool bChanged = false; + bool bFound = false; + + { + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + RsMsgItem *mi = NULL; + + mit = imsg.find(msgId); + if (mit != imsg.end()) { + mi = mit->second; + } else { + mit = msgOutgoing.find(msgId); + if (mit != msgOutgoing.end()) { + mi = mit->second; + } + } + + if (mi) { + bFound = true; + + if (bTrash) { + if ((mi->msgFlags & RS_MSG_FLAGS_TRASH) == 0) { + mi->msgFlags |= RS_MSG_FLAGS_TRASH; + bChanged = true; + } + } else { + if (mi->msgFlags & RS_MSG_FLAGS_TRASH) { + mi->msgFlags &= ~RS_MSG_FLAGS_TRASH; + bChanged = true; + } + } + } + } + + if (bChanged) { + IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ + + checkOutgoingMessages(); + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); + } + + return bFound; +} + +/****************************************/ +/****************************************/ + + +/****************************************/ + +/**** HELPER FNS For Chat/Msg/Channel Lists ************ + * These aren't required to be locked, unless + * the data used is from internal stores -> then they should be. + */ + +void p3MsgService::initRsMI(RsMsgItem *msg, MessageInfo &mi) +{ + + mi.msgflags = 0; + + /* translate flags, if we sent it... outgoing */ + if ((msg->msgFlags & RS_MSG_FLAGS_OUTGOING) + || (msg->PeerId() == mConnMgr->getOwnId())) + { + mi.msgflags |= RS_MSG_OUTGOING; + } + /* if it has a pending flag, then its in the outbox */ + if (msg->msgFlags & RS_MSG_FLAGS_PENDING) + { + mi.msgflags |= RS_MSG_PENDING; + } + if (msg->msgFlags & RS_MSG_FLAGS_DRAFT) + { + mi.msgflags |= RS_MSG_DRAFT; + } + if (msg->msgFlags & RS_MSG_FLAGS_NEW) + { + mi.msgflags |= RS_MSG_NEW; + } + if (msg->msgFlags & RS_MSG_FLAGS_TRASH) + { + mi.msgflags |= RS_MSG_TRASH; + } + if (msg->msgFlags & RS_MSG_FLAGS_UNREAD_BY_USER) + { + mi.msgflags |= RS_MSG_UNREAD_BY_USER; + } + if (msg->msgFlags & RS_MSG_FLAGS_REPLIED) + { + mi.msgflags |= RS_MSG_REPLIED; + } + if (msg->msgFlags & RS_MSG_FLAGS_FORWARDED) + { + mi.msgflags |= RS_MSG_FORWARDED; + } + if (msg->msgFlags & RS_MSG_FLAGS_STAR) + { + mi.msgflags |= RS_MSG_STAR; + } + + mi.ts = msg->sendTime; + mi.srcId = msg->PeerId(); + { + //msg->msgId; + std::ostringstream out; + out << msg->msgId; + mi.msgId = out.str(); + } + + std::list::iterator pit; + + for(pit = msg->msgto.ids.begin(); + pit != msg->msgto.ids.end(); pit++) + { + mi.msgto.push_back(*pit); + } + + for(pit = msg->msgcc.ids.begin(); + pit != msg->msgcc.ids.end(); pit++) + { + mi.msgcc.push_back(*pit); + } + + for(pit = msg->msgbcc.ids.begin(); + pit != msg->msgbcc.ids.end(); pit++) + { + mi.msgbcc.push_back(*pit); + } + + mi.title = msg->subject; + mi.msg = msg->message; + + mi.attach_title = msg->attachment.title; + mi.attach_comment = msg->attachment.comment; + + mi.count = 0; + mi.size = 0; + + std::list::iterator it; + for(it = msg->attachment.items.begin(); + it != msg->attachment.items.end(); it++) + { + FileInfo fi; + fi.fname = RsDirUtil::getTopDir(it->name); + fi.size = it->filesize; + fi.hash = it->hash; + fi.path = it->path; + mi.files.push_back(fi); + mi.count++; + mi.size += fi.size; + } + +} + + +void p3MsgService::initRsMIS(RsMsgItem *msg, MsgInfoSummary &mis) +{ + mis.msgflags = 0; + + /* translate flags, if we sent it... outgoing */ + if ((msg->msgFlags & RS_MSG_FLAGS_OUTGOING) + || (msg->PeerId() == mConnMgr->getOwnId())) + { + mis.msgflags |= RS_MSG_OUTGOING; + } + /* if it has a pending flag, then its in the outbox */ + if (msg->msgFlags & RS_MSG_FLAGS_PENDING) + { + mis.msgflags |= RS_MSG_PENDING; + } + if (msg->msgFlags & RS_MSG_FLAGS_DRAFT) + { + mis.msgflags |= RS_MSG_DRAFT; + } + if (msg->msgFlags & RS_MSG_FLAGS_NEW) + { + mis.msgflags |= RS_MSG_NEW; + } + if (msg->msgFlags & RS_MSG_FLAGS_TRASH) + { + mis.msgflags |= RS_MSG_TRASH; + } + if (msg->msgFlags & RS_MSG_FLAGS_UNREAD_BY_USER) + { + mis.msgflags |= RS_MSG_UNREAD_BY_USER; + } + if (msg->msgFlags & RS_MSG_FLAGS_REPLIED) + { + mis.msgflags |= RS_MSG_REPLIED; + } + if (msg->msgFlags & RS_MSG_FLAGS_FORWARDED) + { + mis.msgflags |= RS_MSG_FORWARDED; + } + if (msg->msgFlags & RS_MSG_FLAGS_STAR) + { + mis.msgflags |= RS_MSG_STAR; + } + + mis.srcId = msg->PeerId(); + { + //msg->msgId; + std::ostringstream out; + out << msg->msgId; + mis.msgId = out.str(); + } + + mis.title = msg->subject; + mis.count = msg->attachment.items.size(); + mis.ts = msg->sendTime; +} + +RsMsgItem *p3MsgService::initMIRsMsg(MessageInfo &info, std::string to) +{ + RsMsgItem *msg = new RsMsgItem(); + + msg -> PeerId(to); + + msg -> msgFlags = 0; + msg -> msgId = 0; + msg -> sendTime = time(NULL); + msg -> recvTime = 0; + + msg -> subject = info.title; + msg -> message = info.msg; + + std::list::iterator pit; + for(pit = info.msgto.begin(); pit != info.msgto.end(); pit++) + { + msg -> msgto.ids.push_back(*pit); + } + + for(pit = info.msgcc.begin(); pit != info.msgcc.end(); pit++) + { + msg -> msgcc.ids.push_back(*pit); + } + + /* We don't fill in bcc (unless to ourselves) */ + if (to == mConnMgr->getOwnId()) + { + for(pit = info.msgbcc.begin(); pit != info.msgbcc.end(); pit++) + { + msg -> msgbcc.ids.push_back(*pit); + } + } + + msg -> attachment.title = info.attach_title; + msg -> attachment.comment = info.attach_comment; + + std::list::iterator it; + for(it = info.files.begin(); it != info.files.end(); it++) + { + RsTlvFileItem mfi; + mfi.hash = it -> hash; + mfi.name = it -> fname; + mfi.filesize = it -> size; + msg -> attachment.items.push_back(mfi); + } + + //std::cerr << "p3MsgService::initMIRsMsg()" << std::endl; + //msg->print(std::cerr); + return msg; +} diff --git a/libretroshare/src/services/p3msgservice.h b/libretroshare/src/services/p3msgservice.h new file mode 100644 index 000000000..aa92ebb63 --- /dev/null +++ b/libretroshare/src/services/p3msgservice.h @@ -0,0 +1,148 @@ +/* + * libretroshare/src/services msgservice.h + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef MESSAGE_SERVICE_HEADER +#define MESSAGE_SERVICE_HEADER + +#include +#include +#include + +#include "retroshare/rsmsgs.h" + +#include "pqi/pqi.h" +#include "pqi/pqiindic.h" + +#include "pqi/pqimonitor.h" +#include "pqi/p3cfgmgr.h" + +#include "services/p3service.h" +#include "serialiser/rsmsgitems.h" +#include "util/rsthreads.h" + +class p3ConnectMgr; + +class p3MsgService: public p3Service, public p3Config, public pqiMonitor +{ + public: + p3MsgService(p3ConnectMgr *cm); + + /* External Interface */ +bool MsgsChanged(); /* should update display */ +bool MsgNotifications(); /* popup - messages */ +bool getMessageNotifications(std::list ¬eList); + +bool getMessageSummaries(std::list &msgList); +bool getMessage(const std::string &mid, MessageInfo &msg); +void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox); + +bool removeMsgId(const std::string &mid); +bool markMsgIdRead(const std::string &mid, bool bUnreadByUser); +bool setMsgFlag(const std::string &mid, uint32_t flag, uint32_t mask); +bool getMsgParentId(const std::string &msgId, std::string &msgParentId); +// msgParentId == 0 --> remove +bool setMsgParentId(uint32_t msgId, uint32_t msgParentId); + +bool MessageSend(MessageInfo &info); +bool MessageToDraft(MessageInfo &info, const std::string &msgParentId); +bool MessageToTrash(const std::string &mid, bool bTrash); + +bool getMessageTagTypes(MsgTagType& tags); +bool setMessageTagType(uint32_t tagId, std::string& text, uint32_t rgb_color); +bool removeMessageTagType(uint32_t tagId); + +bool getMessageTag(const std::string &msgId, MsgTagInfo& info); +/* set == false && tagId == 0 --> remove all */ +bool setMessageTag(const std::string &msgId, uint32_t tagId, bool set); + +bool resetMessageStandardTagTypes(MsgTagType& tags); + +void loadWelcomeMsg(); /* startup message */ + +//std::list &getMsgList(); +//std::list &getMsgOutList(); + +int tick(); +int status(); + + /*** Overloaded from p3Config ****/ +virtual RsSerialiser *setupSerialiser(); +virtual bool saveList(bool& cleanup, std::list&); +virtual bool loadList(std::list& load); +virtual void saveDone(); + /*** Overloaded from p3Config ****/ + + /*** Overloaded from pqiMonitor ***/ +virtual void statusChange(const std::list &plist); +int checkOutgoingMessages(); + /*** Overloaded from pqiMonitor ***/ + + private: + +uint32_t getNewUniqueMsgId(); +int sendMessage(RsMsgItem *item); +int incomingMsgs(); +void processMsg(RsMsgItem *mi); + +void initRsMI(RsMsgItem *msg, MessageInfo &mi); +void initRsMIS(RsMsgItem *msg, MsgInfoSummary &mis); +RsMsgItem *initMIRsMsg(MessageInfo &info, std::string to); + +void initStandardTagTypes(); + + p3ConnectMgr *mConnMgr; + + /* Mutex Required for stuff below */ + + RsMutex mMsgMtx; + + /* stored list of messages */ + std::map imsg; + /* ones that haven't made it out yet! */ + std::map msgOutgoing; + + /* List of notifications to post via Toaster */ + std::list msgNotifications; + + /* maps for tags types and msg tags */ + + std::map mTags; + std::map mMsgTags; + + + Indicator msgChanged; + uint32_t mMsgUniqueId; + + // used delete msgSrcIds after config save + std::map mSrcIds; + + // save the parent of the messages in draft for replied and forwarded + std::map mParentId; + + std::string config_dir; +}; + +#endif // MESSAGE_SERVICE_HEADER diff --git a/libretroshare/src/services/p3photoservice.cc b/libretroshare/src/services/p3photoservice.cc new file mode 100644 index 000000000..ceeb58cd0 --- /dev/null +++ b/libretroshare/src/services/p3photoservice.cc @@ -0,0 +1,879 @@ +/* + * libretroshare/src/services p3ranking.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3photoservice.h" + +#include "pqi/pqibin.h" +#include "pqi/authssl.h" + +#include "util/rsdir.h" + +std::string generateRandomShowId(); + +/**** + * #define PHOTO_DEBUG 1 + ****/ + + +PhotoSet::PhotoSet() +{ + return; +} + +/********************************************************************************/ +/******************* Startup / Tick ******************************************/ +/********************************************************************************/ + +p3PhotoService::p3PhotoService(uint16_t type, CacheStrapper *cs, CacheTransfer *cft, + std::string sourcedir, std::string storedir) + :CacheSource(type, true, cs, sourcedir), + CacheStore(type, true, cs, cft, storedir), + mUpdated(true) +{ + + { RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + mOwnId = AuthSSL::getAuthSSL()->OwnId(); + } + +// createDummyData(); + return; +} + + +void p3PhotoService::tick() +{ + bool repub = false; + { + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + repub = mRepublish; + } + + if (repub) + { + //publishPhotos(); + + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + mRepublish = false; + } +} + + +/********************************************************************************/ +/******************* Cache Interaction ******************************************/ +/********************************************************************************/ + +bool p3PhotoService::loadLocalCache(const CacheData &data) +{ + std::string filename = data.path + '/' + data.name; + std::string hash = data.hash; + //uint64_t size = data.size; + std::string source = data.pid; + +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::loadLocalCache()"; + std::cerr << std::endl; + std::cerr << "\tSource: " << source; + std::cerr << std::endl; + std::cerr << "\tFilename: " << filename; + std::cerr << std::endl; + std::cerr << "\tHash: " << hash; + std::cerr << std::endl; + std::cerr << "\tSize: " << data.size; + std::cerr << std::endl; +#endif + + if (data.cid.subid == 0) + { + loadPhotoIndex(filename, hash, source); + } + else + { + availablePhoto(filename, hash, source); + } + + { + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + mRepublish = false; + mUpdated = true; + } + + if (data.size > 0) /* don't refresh zero sized caches */ + { + refreshCache(data); + } + return true; +} + +int p3PhotoService::loadCache(const CacheData &data) +{ + std::string filename = data.path + '/' + data.name; + std::string hash = data.hash; + //uint64_t size = data.size; + std::string source = data.pid; + +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::loadCache()"; + std::cerr << std::endl; + std::cerr << "\tSource: " << source; + std::cerr << std::endl; + std::cerr << "\tFilename: " << filename; + std::cerr << std::endl; + std::cerr << "\tHash: " << hash; + std::cerr << std::endl; + std::cerr << "\tSize: " << data.size; + std::cerr << std::endl; +#endif + + if (data.cid.subid == 0) + { + loadPhotoIndex(filename, hash, source); + } + else + { + availablePhoto(filename, hash, source); + } + + CacheStore::lockData(); /***** LOCK ****/ + locked_storeCacheEntry(data); + CacheStore::unlockData(); /***** UNLOCK ****/ + + return 1; +} + + +void p3PhotoService::loadPhotoIndex(std::string filename, std::string hash, std::string src) +{ + /* create the serialiser to load info */ + RsSerialiser *rsSerialiser = new RsSerialiser(); + rsSerialiser->addSerialType(new RsPhotoSerialiser()); + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_READABLE; + BinInterface *bio = new BinFileInterface(filename.c_str(), bioflags); + pqistreamer *stream = new pqistreamer(rsSerialiser, src, bio, 0); + +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::loadPhotoIndex()"; + std::cerr << std::endl; + std::cerr << "\tSource: " << src; + std::cerr << std::endl; + std::cerr << "\tHash: " << hash; + std::cerr << std::endl; + std::cerr << "\tFilename: " << filename; + std::cerr << std::endl; +#endif + + RsItem *item; + RsPhotoItem *pitem; + RsPhotoShowItem *sitem; + + stream->tick(); /* Tick to read! */ + while(NULL != (item = stream->GetItem())) + { + +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::loadPhotoIndex() Got Item:"; + std::cerr << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + pitem = dynamic_cast(item); + sitem = dynamic_cast(item); + + if (pitem) + { + /* photo item */ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::loadPhotoIndex() Loading Photo Item"; + std::cerr << std::endl; +#endif + loadPhotoItem(pitem); + + } + else if (sitem) + { + /* show item */ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::loadPhotoIndex() Loading Show Item"; + std::cerr << std::endl; +#endif + loadPhotoShowItem(sitem); + } + else + { + /* unknown */ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::loadRankFile() Unknown Item (deleting):"; + std::cerr << std::endl; +#endif + + } + delete item; + stream->tick(); /* Tick to read! */ + } + + delete stream; +} + + +bool p3PhotoService::loadPhotoItem(RsPhotoItem *item) +{ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::loadPhotoItem()"; + std::cerr << std::endl; + item->print(std::cerr); + std::cerr << std::endl; +#endif + + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + PhotoSet &pset = locked_getPhotoSet(item->PeerId()); + pset.photos[item->photoId] = item; + + mUpdated = true; + + return true; + + +} + + +bool p3PhotoService::loadPhotoShowItem(RsPhotoShowItem *item) +{ + +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::loadPhotoShowItem()"; + std::cerr << std::endl; + item->print(std::cerr); + std::cerr << std::endl; +#endif + + /* add to set */ + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + PhotoSet &pset = locked_getPhotoSet(item->PeerId()); + pset.shows[item->showId] = item; + + //mRepublish = true; + mUpdated = true; + + return true; +} + +void p3PhotoService::availablePhoto(std::string filename, std::string hash, std::string src) +{ + /* TODO */ + return; +} + + +void p3PhotoService::publishPhotos() +{ + +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::publishPhotos()"; + std::cerr << std::endl; +#endif + + /* determine filename */ + + std::string path = CacheSource::getCacheDir(); + std::ostringstream out; + out << "photo-index-" << time(NULL) << ".pdx"; + + std::string tmpname = out.str(); + std::string fname = path + "/" + tmpname; + +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::publishPhotos() Storing to: " << fname; + std::cerr << std::endl; +#endif + + + RsSerialiser *rsSerialiser = new RsSerialiser(); + rsSerialiser->addSerialType(new RsPhotoSerialiser()); + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_WRITEABLE; + BinInterface *bio = new BinFileInterface(fname.c_str(), bioflags); + pqistreamer *stream = new pqistreamer(rsSerialiser, mOwnId, bio, + BIN_FLAGS_NO_DELETE); + + + { RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + PhotoSet &pset = locked_getPhotoSet(mOwnId); + + std::map::iterator pit; + for(pit = pset.photos.begin(); pit != pset.photos.end(); pit++) + { + RsPhotoItem *pitem = pit->second; +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::publishPhotos() Storing Photo Item:"; + std::cerr << std::endl; + pitem->print(std::cerr, 10); + std::cerr << std::endl; +#endif + stream->SendItem(pitem); + stream->tick(); /* Tick to write! */ + + } + + std::map::iterator sit; + for(sit = pset.shows.begin(); sit != pset.shows.end(); sit++) + { + RsPhotoShowItem *sitem = sit->second; +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::publishPhotos() Storing PhotoShow Item:"; + std::cerr << std::endl; + sitem->print(std::cerr, 10); + std::cerr << std::endl; +#endif + stream->SendItem(sitem); + stream->tick(); /* Tick to write! */ + + } + } /********** STACK LOCKED MTX ******/ + stream->tick(); /* Tick for final write! */ + + /* flag as new info */ + CacheData data; + + { RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + data.pid = mOwnId; + } /********** STACK LOCKED MTX ******/ + + data.cid = CacheId(CacheSource::getCacheType(), 1); + + data.path = path; + data.name = tmpname; + + data.hash = bio->gethash(); + data.size = bio->bytecount(); + data.recvd = time(NULL); + +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::publishPhotos() refreshing Cache"; + std::cerr << std::endl; + std::cerr << "\tCache Path: " << data.path; + std::cerr << std::endl; + std::cerr << "\tCache Name: " << data.name; + std::cerr << std::endl; + std::cerr << "\tCache Hash: " << data.hash; + std::cerr << std::endl; + std::cerr << "\tCache Size: " << data.size; + std::cerr << std::endl; +#endif + if (data.size > 0) /* don't refresh zero sized caches */ + { + refreshCache(data); + } + + delete stream; + + /* TO HERE + * update Cache (new Photos (all Photos?)) + * */ + +} + + +/********************************************************************************/ +/******************* External Interface *****************************************/ +/********************************************************************************/ + +bool p3PhotoService::updated() +{ + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + if (mUpdated) + { + mUpdated = false; + return true; + } + return false; +} + +bool p3PhotoService::getPhotoList(std::string id, std::list &photoIds) +{ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::getPhotoList() pid: " << id; + std::cerr << std::endl; +#endif + + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + PhotoSet &pset = locked_getPhotoSet(id); + + /* get the list of photoids */ + std::map::iterator pit; + for(pit = pset.photos.begin(); pit != pset.photos.end(); pit++) + { +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::getPhotoList() PhotoId: " << pit->first; + std::cerr << std::endl; +#endif + photoIds.push_back(pit->first); + } + + return true; +} + + +bool p3PhotoService::getShowList(std::string id, std::list &showIds) +{ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::getShowList() pid: " << id; + std::cerr << std::endl; +#endif + + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + PhotoSet &pset = locked_getPhotoSet(id); + + /* get the list of showIds */ + std::map::iterator sit; + for(sit = pset.shows.begin(); sit != pset.shows.end(); sit++) + { +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::getShowList() ShowId: " << sit->first; + std::cerr << std::endl; +#endif + showIds.push_back(sit->first); + } + + return true; +} + +bool p3PhotoService::getShowDetails(std::string id, std::string showId, RsPhotoShowDetails &detail) +{ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::getShowDetails() pid: " << id; + std::cerr << "showId: " << showId; + std::cerr << std::endl; +#endif + + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + RsPhotoShowItem *item = locked_getShow(id, showId); + if (!item) + { + return false; + } + + /* extract Show details */ + + return true; +} + + +bool p3PhotoService::getPhotoDetails(std::string id, std::string photoId, RsPhotoDetails &detail) +{ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::getPhotoDetails() pid: " << id; + std::cerr << " photoId: " << photoId; + std::cerr << std::endl; +#endif + + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + RsPhotoItem *item = locked_getPhoto(id, photoId); + if (!item) + { + return false; + } + + /* extract Photo details */ + detail.id = item->PeerId(); + detail.srcid = item->srcId; + detail.hash = item->photoId; + detail.size = item->size; + detail.name = item->name; + detail.location = item->location; + detail.comment = item->comment; + detail.date = item->date; + detail.format = 0; + detail.isAvailable = item->isAvailable; + detail.path = item->path; + + return true; +} + +/* add / delete */ +std::string p3PhotoService::createShow(std::string name) +{ + std::string showId = generateRandomShowId(); + RsPhotoShowItem *newShow = new RsPhotoShowItem(); + + + newShow->showId = showId; + newShow->name = name; + + /* add to set */ + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + PhotoSet &pset = locked_getPhotoSet(mOwnId); + pset.shows[showId] = newShow; + + mRepublish = true; + + return showId; +} + + +bool p3PhotoService::deleteShow(std::string showId) +{ + /* add to set */ + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + PhotoSet &pset = locked_getPhotoSet(mOwnId); + + std::map::iterator sit; + sit = pset.shows.find(showId); + if (sit == pset.shows.end()) + { +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::deleteShow() no existant"; + std::cerr << std::endl; +#endif + return false; + } + + + RsPhotoShowItem *oldShow = sit->second; + pset.shows.erase(sit); + delete oldShow; + + mRepublish = true; + + return true; +} + + +bool p3PhotoService::addPhotoToShow(std::string showId, std::string photoId, int16_t index) +{ + +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::addPhotoToShow() showId: " << showId; + std::cerr << " photoId: " << photoId; + std::cerr << std::endl; +#endif + + /* add to set */ + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + + RsPhotoItem *photo = locked_getPhoto(mOwnId, photoId); + RsPhotoShowItem *show = locked_getShow(mOwnId, showId); + + if ((!photo) || (!show)) + { +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::addPhotoToShow() NULL data"; + std::cerr << std::endl; +#endif + return false; + } + + /* can have duplicates so just add it in */ + RsPhotoRefItem ref; + ref.photoId = photoId; + + /* add in at correct location! */ + //uint32_t i = 0; + //for(it = show.photos.begin(); + // (i < index) && (it != show.photos.end()); it++, i++); + + show->photos.push_back(ref); + + mRepublish = true; + + return true; +} + +bool p3PhotoService::movePhotoInShow(std::string showId, std::string photoId, int16_t index) +{ + return false; +} + +bool p3PhotoService::removePhotoFromShow(std::string showId, std::string photoId) +{ + return false; +} + + +std::string p3PhotoService::addPhoto(std::string path) /* add from file */ +{ + /* check file exists */ + std::string hash; + uint64_t size; + + if (!RsDirUtil::getFileHash(path, hash, size)) + { + return hash; + } + + /* copy to outgoing directory TODO */ + + /* create item */ + RsPhotoItem *item = new RsPhotoItem(); + + { + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + item->PeerId(mOwnId); + } + + item->srcId = item->PeerId(); + item->photoId = hash; + item->name = RsDirUtil::getTopDir(path); + item->path = path; + item->size = size; + item->isAvailable = true; + item->comment = L"No Comment Yet!"; + + /* add in */ + loadPhotoItem(item); + + /* flag for republish */ + { + RsStackMutex stack(mPhotoMtx); /********** STACK LOCKED MTX ******/ + mRepublish = true; + } + + return hash; +} + + + + +bool p3PhotoService::addPhoto(std::string srcId, std::string photoId) /* add from peers photos */ +{ + return false; +} + +bool p3PhotoService::deletePhoto(std::string photoId) +{ + return false; +} + + +/* modify properties (TODO) */ +bool p3PhotoService::modifyShow(std::string showId, std::wstring name, std::wstring comment) +{ + return false; +} + +bool p3PhotoService::modifyPhoto(std::string photoId, std::wstring name, std::wstring comment) +{ + return false; +} + +bool p3PhotoService::modifyShowComment(std::string showId, std::string photoId, std::wstring comment) +{ + return false; +} + +/********************************************************************************/ +/******************* Utility Functions ******************************************/ +/********************************************************************************/ + +PhotoSet &p3PhotoService::locked_getPhotoSet(std::string id) +{ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::locked_getPhotoSet() pid: " << id; + std::cerr << std::endl; +#endif + + std::map::iterator it; + it = mPhotos.find(id); + if (it == mPhotos.end()) + { + /* missing group -> add it in */ + PhotoSet pset; + pset.pid = id; + mPhotos[id] = pset; + + it = mPhotos.find(id); + } + + return (it->second); +} + + +RsPhotoItem *p3PhotoService::locked_getPhoto(std::string id, std::string photoId) +{ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::locked_getPhoto() pid: " << id; + std::cerr << " photoId: " << photoId; + std::cerr << std::endl; +#endif + + PhotoSet &pset = locked_getPhotoSet(id); + + std::map::iterator pit; + pit = pset.photos.find(photoId); + if (pit == pset.photos.end()) + { +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::getPhotoDetails() Failed - noPhoto"; + std::cerr << std::endl; +#endif + return NULL; + } + return pit->second; +} + + +RsPhotoShowItem *p3PhotoService::locked_getShow(std::string id, std::string showId) +{ +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::locked_getShow() pid: " << id; + std::cerr << " showId: " << showId; + std::cerr << std::endl; +#endif + + PhotoSet &pset = locked_getPhotoSet(id); + + std::map::iterator sit; + sit = pset.shows.find(showId); + if (sit == pset.shows.end()) + { +#ifdef PHOTO_DEBUG + std::cerr << "p3PhotoService::locked_getShow() Failed - no Show"; + std::cerr << std::endl; +#endif + return NULL; + } + return sit->second; +} + + + + +std::string generateRandomShowId() +{ + std::ostringstream out; + out << std::hex; + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + /* 4 bytes per random number: 4 x 4 = 16 bytes */ + for(int i = 0; i < 4; i++) + { + out << std::setw(8) << std::setfill('0'); + uint32_t rint = random(); + out << rint; + } +#else + srand(time(NULL)); + /* 2 bytes per random number: 8 x 2 = 16 bytes */ + for(int i = 0; i < 8; i++) + { + out << std::setw(4) << std::setfill('0'); + uint16_t rint = rand(); /* only gives 16 bits */ + out << rint; + } +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + return out.str(); +} + + +void p3PhotoService::createDummyData() +{ + +#if 0 + RsRankLinkMsg *msg = new RsRankLinkMsg(); + + time_t now = time(NULL); + + msg->PeerId(mOwnId); + msg->rid = "0001"; + msg->title = L"Original Awesome Site!"; + msg->timestamp = now - 60 * 60 * 24 * 15; + msg->link = L"http://www.retroshare.org"; + msg->comment = L"Retroshares Website"; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId(mOwnId); + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 123; + msg->link = L"http://www.lunamutt.org"; + msg->comment = L"Lunamutt's Website"; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId("ALTID"); + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 60 * 60 * 24 * 29; + msg->link = L"http://www.lunamutt.org"; + msg->comment = L"Lunamutt's Website (TWO) How Long can this comment be!\n"; + msg->comment += L"What happens to the second line?\n"; + msg->comment += L"And a 3rd!"; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId("ALTID2"); + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 60 * 60 * 7; + msg->link = L"http://www.lunamutt.org"; + msg->comment += L"A Short Comment"; + + addRankMsg(msg); + + + /***** Third one ****/ + + msg = new RsRankLinkMsg(); + msg->PeerId(mOwnId); + msg->rid = "0003"; + msg->title = L"Weird Site!"; + msg->timestamp = now - 60 * 60; + msg->link = L"http://www.lunamutt.com"; + msg->comment = L""; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId("ALTID"); + msg->rid = "0003"; + msg->title = L"Weird Site!"; + msg->timestamp = now - 60 * 60 * 24 * 2; + msg->link = L"http://www.lunamutt.com"; + msg->comment = L""; + + addRankMsg(msg); + +#endif + +} + diff --git a/libretroshare/src/services/p3photoservice.h b/libretroshare/src/services/p3photoservice.h new file mode 100644 index 000000000..5d57a35bd --- /dev/null +++ b/libretroshare/src/services/p3photoservice.h @@ -0,0 +1,143 @@ +/* + * libretroshare/src/services: p3photoservice.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2008-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_PHOTO_SERVICE_HEADER +#define P3_PHOTO_SERVICE_HEADER + +#include "dbase/cachestrapper.h" +#include "pqi/pqiservice.h" +#include "pqi/pqistreamer.h" + +#include "serialiser/rsserial.h" +#include "serialiser/rsphotoitems.h" + +#include "retroshare/rsphoto.h" + +/* + * Photo Service + */ + +class PhotoSet +{ + public: + + PhotoSet(); + std::string pid; + + std::map photos; + std::map shows; +}; + + + +class p3PhotoService: public CacheSource, public CacheStore +{ + public: + + p3PhotoService(uint16_t type, CacheStrapper *cs, CacheTransfer *cft, + std::string sourcedir, std::string storedir); + +void tick(); + +/******************************* CACHE SOURCE / STORE Interface *********************/ + + /* overloaded functions from Cache Source */ +virtual bool loadLocalCache(const CacheData &data); + + /* overloaded functions from Cache Store */ +virtual int loadCache(const CacheData &data); + +/******************************* CACHE SOURCE / STORE Interface *********************/ + + public: + +/************* Extern Interface *******/ + + /* things changed */ +bool updated(); + + /* access data */ +bool getPhotoList(std::string id, std::list &hashs); +bool getShowList(std::string id, std::list &showIds); +bool getShowDetails(std::string id, std::string showId, RsPhotoShowDetails &detail); +bool getPhotoDetails(std::string id, std::string photoId, RsPhotoDetails &detail); + + /* add / delete */ +std::string createShow(std::string name); +bool deleteShow(std::string showId); +bool addPhotoToShow(std::string showId, std::string photoId, int16_t index); +bool movePhotoInShow(std::string showId, std::string photoId, int16_t index); +bool removePhotoFromShow(std::string showId, std::string photoId); + +std::string addPhoto(std::string path); /* add from file */ +bool addPhoto(std::string srcId, std::string photoId); /* add from peers photos */ +bool deletePhoto(std::string photoId); + + /* modify properties (TODO) */ +bool modifyShow(std::string showId, std::wstring name, std::wstring comment); +bool modifyPhoto(std::string photoId, std::wstring name, std::wstring comment); +bool modifyShowComment(std::string showId, std::string photoId, std::wstring comment); + + + + private: + + /* cache processing */ + +void loadPhotoIndex(std::string filename, std::string hash, std::string src); +void availablePhoto(std::string filename, std::string hash, std::string src); + +bool loadPhotoItem(RsPhotoItem *item); +bool loadPhotoShowItem(RsPhotoShowItem *item); +void publishPhotos(); + + + /* locate info */ + +PhotoSet &locked_getPhotoSet(std::string id); +RsPhotoItem *locked_getPhoto(std::string id, std::string photoId); +RsPhotoShowItem *locked_getShow(std::string id, std::string showId); + + + /* test functions */ +void createDummyData(); + + + + RsMutex mPhotoMtx; + + /***** below here is locked *****/ + + bool mRepublish; + std::string mOwnId; + + bool mUpdated; + + std::map mPhotos; + + +}; + +#endif diff --git a/libretroshare/src/services/p3portservice.cc b/libretroshare/src/services/p3portservice.cc new file mode 100644 index 000000000..3a0763880 --- /dev/null +++ b/libretroshare/src/services/p3portservice.cc @@ -0,0 +1,123 @@ +/* + * "$Id: p3PortService.cc,v 1.24 2007-05-05 16:10:06 rmf24 Exp $" + * + * Other Bits for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "services/p3portservice.h" +#include "serialiser/rsserviceids.h" + +p3PortService::p3PortService(p3ConnectMgr *cm) + :p3Service(RS_SERVICE_TYPE_PORT), mConnMgr(cm), mEnabled(false) +{ + /* For Version 1, we'll just use the very simple RsRawItem packets + * which are handled in the RsServiceSerialiser + */ + addSerialType(new RsServiceSerialiser()); +} + +int p3PortService::tick() +{ +#ifdef PORT_DEBUG + std::cerr << "p3PortService::tick()"; + std::cerr << std::endl; +#endif + + /* discard data if not enabled */ + if (!mEnabled) + { + RsItem *i; + while(NULL != (i = recvItem())) + { + delete i; + } + } + + /* Rough list of what might happen (once the sockets are opened!) */ + + + /* check for data on sockets */ + //int sockfd; + RsRawItem *item; + + //while(0 < (len = recv(sockfd, ....))) ... etc. + { + + /* example of how to package data up + * We use RsRawItem as it'll handle a single binary chunk. + * This is enough for version 1.... but versions 2 + 3 will + * need their own serialiser. + * + * */ + + /* input data TODO! */ + void *data; + uint32_t len=0; + + uint32_t packetId = (((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + + (((uint32_t) RS_SERVICE_TYPE_PORT) << 8); + + /* create Packet for RS Transport */ + RsRawItem *item = new RsRawItem(packetId, len); + void *item_data = item->getRawData(); + memcpy(item_data, data, len); + + /* set the correct peer destination. */ + item->PeerId(mPeerId); + + /* send data */ + sendItem(item); + + /* no delete -> packet cleaned up by RS internals */ + } + + + /* get any incoming data */ + while(NULL != (item = (RsRawItem*) recvItem())) + { + /* unpackage data */ + std::string src = item->PeerId(); +// void *item_data = item->getRawData(); +// uint32_t item_len = item->getRawLength(); + + /* push out to the socket .... */ + // send(sockfd, item_len, item_data....) + + /* cleanup packet */ + delete item; + } + + return 0; +} + +bool p3PortService::enablePortForwarding(uint32_t port, std::string peerId) +{ + mPort = port; + mPeerId = peerId; + mEnabled = true; + + return true; +} + + + diff --git a/libretroshare/src/services/p3portservice.h b/libretroshare/src/services/p3portservice.h new file mode 100644 index 000000000..b1ef089f9 --- /dev/null +++ b/libretroshare/src/services/p3portservice.h @@ -0,0 +1,88 @@ +/* + * libretroshare/src/services: p3portservice.h + * + * Services for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef SERVICE_PORT_FORWARD_HEADER +#define SERVICE_PORT_FORWARD_HEADER + +/* + * The start of a port forwarding service. + * + * This is just a very rough example of what might be required for version 1. + * + * FIRST VERSION: + * + * listen to a single port and send data with a single RS peer. + * + * + * SECOND VERSION: + * + * enable multiple port forwardings. + * + * each forwarding consists of a 'port, peerId & Connection Id'. + * + * THIRD VERSION: + * + * add broadcast/multicast forwardings. + * i.e. data gets sent to multiple peers. + * + * each forwarding with then consist of 'port, connectionId + list of peerIds' + * NOTE: version 3 needs some thought - might require a master host + * which distributes to all others.... or other more complicated systems. + * + */ + +#include +#include + +#include "serialiser/rsbaseitems.h" +#include "services/p3service.h" +#include "pqi/p3connmgr.h" + + +class p3PortService: public p3Service +{ + public: + p3PortService(p3ConnectMgr *cm); + + /* example setup functions */ +bool enablePortForwarding(uint32_t port, std::string peerId); + + /* overloaded */ +virtual int tick(); + + private: + + p3ConnectMgr *mConnMgr; + + bool mEnabled; + bool mPeerOnline; + + uint32_t mPort; + std::string mPeerId; + +}; + +#endif // SERVICE_PORT_FORWARD_HEADER diff --git a/libretroshare/src/services/p3ranking.cc b/libretroshare/src/services/p3ranking.cc new file mode 100644 index 000000000..f3781f9f7 --- /dev/null +++ b/libretroshare/src/services/p3ranking.cc @@ -0,0 +1,1360 @@ +/* + * libretroshare/src/services p3ranking.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsrankitems.h" +#include "services/p3ranking.h" +#include + +#include "pqi/pqibin.h" +#include "pqi/authssl.h" + +const uint32_t RANK_MAX_FWD_OFFSET = (60 * 60 * 24 * 2); /* 2 Days */ + +const uint32_t FRIEND_RANK_REPUBLISH_PERIOD = 60; /* every minute for testing */ +//const uint32_t FRIEND_RANK_REPUBLISH_PERIOD = 1800; /* every 30 minutes */ + +std::string generateRandomLinkId(); + +/***** + * TODO + * (1) Streaming. + * (2) Ranking. + * + */ + +/********* + * #define RANK_DEBUG 1 + *********/ + +p3Ranking::p3Ranking(p3ConnectMgr *connMgr, + uint16_t type, CacheStrapper *cs, CacheTransfer *cft, + std::string sourcedir, std::string storedir, + uint32_t storePeriod) + :CacheSource(type, true, cs, sourcedir), + CacheStore(type, true, cs, cft, storedir), + p3Config(CONFIG_TYPE_RANK_LINK), + mConnMgr(connMgr), + mRepublish(false), mRepublishFriends(false), mRepublishFriendTS(0), + mStorePeriod(storePeriod), mUpdated(true) +{ + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + mOwnId = mConnMgr->getOwnId(); + mViewPeriod = 60 * 60 * 24 * 30; /* one Month */ + mSortType = RS_RANK_ALG; + + } RsStackMutex stack(mRankMtx); + +// createDummyData(); + return; +} + +bool p3Ranking::loadLocalCache(const CacheData &data) +{ + std::string filename = data.path + '/' + data.name; + std::string hash = data.hash; + //uint64_t size = data.size; + std::string source = data.pid; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadLocalCache()"; + std::cerr << std::endl; + std::cerr << "\tSource: " << source; + std::cerr << std::endl; + std::cerr << "\tFilename: " << filename; + std::cerr << std::endl; + std::cerr << "\tHash: " << hash; + std::cerr << std::endl; + std::cerr << "\tSize: " << data.size; + std::cerr << std::endl; +#endif + + loadRankFile(filename, source); + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mRepublish = false; + } + + if (data.size > 0) /* don't refresh zero sized caches */ + { + refreshCache(data); + } + return true; +} + +int p3Ranking::loadCache(const CacheData &data) +{ + std::string filename = data.path + '/' + data.name; + std::string hash = data.hash; + //uint64_t size = data.size; + std::string source = data.pid; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadCache()"; + std::cerr << std::endl; + std::cerr << "\tSource: " << source; + std::cerr << std::endl; + std::cerr << "\tFilename: " << filename; + std::cerr << std::endl; + std::cerr << "\tHash: " << hash; + std::cerr << std::endl; + std::cerr << "\tSize: " << data.size; + std::cerr << std::endl; +#endif + + loadRankFile(filename, source); + + + CacheStore::lockData(); /***** LOCK ****/ + locked_storeCacheEntry(data); + CacheStore::unlockData(); /***** UNLOCK ****/ + + return 1; +} + + +void p3Ranking::loadRankFile(std::string filename, std::string src) +{ + /* create the serialiser to load info */ + RsSerialiser *rsSerialiser = new RsSerialiser(); + rsSerialiser->addSerialType(new RsRankSerialiser()); + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_READABLE; + BinInterface *bio = new BinFileInterface(filename.c_str(), bioflags); + pqistore *store = new pqistore(rsSerialiser, src, bio, BIN_FLAGS_READABLE); + + time_t now = time(NULL); + time_t min, max; + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + min = now - mStorePeriod; + max = now + RANK_MAX_FWD_OFFSET; + + } /********** STACK LOCKED MTX ******/ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile()"; + std::cerr << std::endl; + std::cerr << "\tSource: " << src; + std::cerr << std::endl; + std::cerr << "\tFilename: " << filename; + std::cerr << std::endl; +#endif + + RsItem *item; + RsRankLinkMsg *newMsg; + + while(NULL != (item = store->GetItem())) + { + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile() Got Item:"; + std::cerr << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + if (NULL == (newMsg = dynamic_cast(item))) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile() Item not LinkMsg (deleting):"; + std::cerr << std::endl; +#endif + + delete item; + } + /* check timestamp */ + else if (((time_t) newMsg->timestamp < min) || + ((time_t) newMsg->timestamp > max)) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile() Outside TimeRange (deleting):"; + std::cerr << std::endl; +#endif + /* if outside range -> remove */ + delete newMsg; + } + else + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile() Loading Item"; + std::cerr << std::endl; +#endif + /* correct the source (if is a message from a friend) */ + newMsg->PeerId(newMsg->pid); + addRankMsg(newMsg); + } + } + + delete store; +} + + +void p3Ranking::publishMsgs(bool own) +{ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs()"; + std::cerr << std::endl; +#endif + + std::string path = CacheSource::getCacheDir(); + std::ostringstream out; + uint16_t subid; + + + /* setup name / etc based on whether we're + * publishing own or friends... + */ + + if (own) + { + /* setup to publish own messages */ + out << "rank-links-" << time(NULL) << ".rsrl"; + subid = 1; + } + else + { + /* setup to publish friend messages */ + out << "rank-friend-links-" << time(NULL) << ".rsrl"; + subid = 2; + } + + /* determine filename */ + std::string tmpname = out.str(); + std::string fname = path + "/" + tmpname; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() Storing to: " << fname; + std::cerr << std::endl; +#endif + + RsSerialiser *rsSerialiser = new RsSerialiser(); + rsSerialiser->addSerialType(new RsRankSerialiser()); + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_WRITEABLE; + BinInterface *bio = new BinFileInterface(fname.c_str(), bioflags); + pqistore *store = new pqistore(rsSerialiser, mOwnId, bio, BIN_FLAGS_NO_DELETE | BIN_FLAGS_WRITEABLE); + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + /* iterate through list */ + std::map::iterator it; + std::map::iterator cit; + + for(it = mData.begin(); it != mData.end(); it++) + { + if (own) + { + if (it->second.ownTag) + { + /* write to serialiser */ + RsItem *item = it->second.comments[mOwnId]; + if (item) + { + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() Storing Item:"; + std::cerr << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + store->SendItem(item); + } + } + else + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() Skipping Foreign item"; + std::cerr << std::endl; +#endif + } + } + else + { + /* if we have pushed it out already - don't bother */ + if (it->second.ownTag) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() (Friends) Skipping Own Item"; + std::cerr << std::endl; +#endif + continue; + } + + /* if we have some comments ... then a friend has recommended it + * serialise a sanitized version. + */ + if (it->second.comments.size() > 0) + { + RsRankLinkMsg *origmsg = (it->second.comments.begin())->second; + RsRankLinkMsg *msg = new RsRankLinkMsg(); + + /* copy anon data */ + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + msg->clear(); + msg->PeerId(""); + msg->pid = ""; /* Anon */ + msg->rid = origmsg->rid; + msg->link = origmsg->link; + msg->title = origmsg->title; + msg->timestamp = origmsg->timestamp; + msg->score = 0; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() (Friends) Storing (Anon) Item:"; + std::cerr << std::endl; + msg->print(std::cerr, 10); + std::cerr << std::endl; +#endif + store->SendItem(msg); + + /* cleanup */ + delete msg; + } + } + } + + + /* now we also add our anon messages to the friends list */ + if (!own) + { + std::list::iterator ait; + for(ait=mAnon.begin(); ait != mAnon.end(); ait++) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() (Friends) Adding Own Anon Item:"; + std::cerr << std::endl; + (*ait)->print(std::cerr, 10); + std::cerr << std::endl; +#endif + store->SendItem(*ait); + } + } + + } /********** STACK LOCKED MTX ******/ + + /* flag as new info */ + CacheData data; + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + data.pid = mOwnId; + } /********** STACK LOCKED MTX ******/ + + data.cid = CacheId(CacheSource::getCacheType(), subid); + + data.path = path; + data.name = tmpname; + + data.hash = bio->gethash(); + data.size = bio->bytecount(); + data.recvd = time(NULL); + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() refreshing Cache"; + std::cerr << std::endl; + std::cerr << "\tCache Path: " << data.path; + std::cerr << std::endl; + std::cerr << "\tCache Name: " << data.name; + std::cerr << std::endl; + std::cerr << "\tCache Hash: " << data.hash; + std::cerr << std::endl; + std::cerr << "\tCache Size: " << data.size; + std::cerr << std::endl; +#endif + if (data.size > 0) /* don't refresh zero sized caches */ + { + refreshCache(data); + } + + delete store; +} + + + +void p3Ranking::addRankMsg(RsRankLinkMsg *msg) +{ + /* find msg */ + std::string id = msg->PeerId(); + std::string rid = msg->rid; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() Item:"; + std::cerr << std::endl; + msg->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it; + it = mData.find(rid); + if (it == mData.end()) + { + /* add a new one */ + RankGroup grp; + grp.rid = rid; + grp.ownTag = false; + grp.rank = 0.0f; + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + + grp.link = msg->link; + grp.title = msg->title; + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + + mData[rid] = grp; + it = mData.find(rid); + + if (id == "") + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() New Anon Link: mUpdated = true"; + std::cerr << std::endl; +#endif + locked_reSortGroup(it->second); + mUpdated = true; + } + } + + /**** If it is an anonymous Link (ie Friend of a Friend) Drop out now ***/ + if (id == "") + { + return; + } + + /* check for old comment */ + std::map::iterator cit; + cit = (it->second).comments.find(id); + + /* Check that it is different! */ + bool newComment = false; + if ((it->second).comments.end() == cit) + { + newComment = true; + } + else + { + RsRankLinkMsg *old = cit->second; + if ((msg->timestamp != old->timestamp) || + (msg->comment != old->comment)) + { + newComment = true; + } + } + + if (newComment) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() New Comment"; + std::cerr << std::endl; +#endif + /* clean up old */ + if ((it->second).comments.end() != cit) + { + delete (cit->second); + (it->second).comments.erase(cit); + } + + /* add in */ + (it->second).comments[id] = msg; + + /* republish? */ + if (id == mOwnId) + { + it->second.ownTag = true; + mRepublish = true; +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() Own Comment: mRepublish = true"; + std::cerr << std::endl; +#endif + } + else + { + mRepublishFriends = true; +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() Other Comment: mRepublishFriends = true"; + std::cerr << "p3Ranking::addRankMsg() Old Comment ignoring"; + std::cerr << std::endl; +#endif + } + + locked_reSortGroup(it->second); + + mUpdated = true; + } + else + { + delete msg; +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() Old Comment ignoring"; + std::cerr << std::endl; +#endif + } +} + + +/***************** Sorting ****************/ + +bool p3Ranking::setSortPeriod(uint32_t period) +{ + bool reSort = false; + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + reSort = (mViewPeriod != period); + mViewPeriod = period; + } + + + if (reSort) + { + sortAllMsgs(); + } + + return true; +} + +bool p3Ranking::setSortMethod(uint32_t type) +{ + bool reSort = false; + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + reSort = (mSortType != type); + mSortType = type; + } + + if (reSort) + { + sortAllMsgs(); + } + + return true; +} + +bool p3Ranking::clearPeerFilter() +{ + bool reSort = false; + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + reSort = (mPeerFilter.size() > 0); + mPeerFilter.clear(); + } + + + if (reSort) + { + sortAllMsgs(); + } + + return true; +} + +bool p3Ranking::setPeerFilter(std::list peers) +{ + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mPeerFilter = peers; + } + + sortAllMsgs(); + + return true; +} + +float p3Ranking::locked_calcRank(RankGroup &grp) +{ + /* Ranking Calculations ..... + */ + + time_t now = time(NULL); + time_t minTime = now-mViewPeriod; + bool doFilter = (mPeerFilter.size() > 0); + bool doScore = (mSortType & RS_RANK_SCORE); + bool doTime = (mSortType & RS_RANK_TIME); + + uint32_t count = 0; + float algScore = 0; + float comboScore = 0; + float popScore = 0; + +#ifdef RANK_DEBUG + std::string normlink(grp.link.begin(), grp.link.end()); + std::cerr << "p3Ranking::locked_calcRank() for: " << normlink; + std::cerr << std::endl; + std::cerr << "Period: " << mViewPeriod; + std::cerr << " doFilter: " << doFilter; + std::cerr << " doScore: " << doScore; + std::cerr << " doTime: " << doTime; + std::cerr << std::endl; +#endif + + std::map::iterator it; + for(it = grp.comments.begin(); it != grp.comments.end(); it++) + { +#ifdef RANK_DEBUG + std::cerr << "Comment by:" << it->first << " age: " << now - it->second->timestamp; + std::cerr << std::endl; +#endif + if (doFilter) + { + if (mPeerFilter.end() == + std::find(mPeerFilter.begin(), mPeerFilter.end(), it->first)) + { + continue; /* skip it */ +#ifdef RANK_DEBUG + std::cerr << "\tFiltered Out"; + std::cerr << std::endl; +#endif + + } + } + + /* if Scoring is involved... drop old ones */ + if ((doScore) && ((time_t) it->second->timestamp < minTime)) + { +#ifdef RANK_DEBUG + std::cerr << "\tToo Old"; + std::cerr << std::endl; +#endif + continue; + } + + time_t deltaT; + if ((time_t) it->second->timestamp > now) + { + deltaT = it->second->timestamp - now; + } + else + { + deltaT = now - it->second->timestamp; + } + float timeScore = ((float) mViewPeriod - deltaT) / (mViewPeriod + 0.01); + +#ifdef RANK_DEBUG + std::cerr << "\tTimeScore: " << timeScore; + std::cerr << std::endl; +#endif + + /* algScore is sum of (filtered) timeScores */ + /* timeScore is average of (all) timeScores */ + /* popScore is just count of valid scores */ + + algScore += timeScore; + count++; + + /* for more advanced scoring (where each peer gives a score +2 -> -2) */ + /* combo = SUM value * timeScore */ + /* time = same as before (average) */ + /* popScore = SUM value */ + + float value = it->second->score; + comboScore += value * timeScore; + popScore += value; + } + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::locked_calcRank() algScore: " << algScore; + std::cerr << " Count: " << count; + std::cerr << std::endl; +#endif + + if ((count <= 0) || (algScore <= 0)) + { +#ifdef RANK_DEBUG + std::cerr << "Final score: 0"; + std::cerr << std::endl; +#endif + return 0; + } + + if ((doScore) && (doTime)) + { +#ifdef RANK_DEBUG + std::cerr << "Old (alg) score:" << algScore; + std::cerr << std::endl; + std::cerr << "Final (Combo) score:" << comboScore; + std::cerr << std::endl; +#endif + + if (comboScore < 0) + { +#ifdef RANK_DEBUG + std::cerr << "Combo score reset = 0"; + std::cerr << std::endl; +#endif + comboScore = 0; + } + return comboScore; + + } + else if (doScore) + { +#ifdef RANK_DEBUG + std::cerr << "Old (tally) score:" << count; + std::cerr << std::endl; + std::cerr << "Final (pop) score:" << popScore; + std::cerr << std::endl; +#endif + if (popScore < 0) + { +#ifdef RANK_DEBUG + std::cerr << "Pop score reset = 0"; + std::cerr << std::endl; +#endif + popScore = 0; + } + return popScore; + } + else if (doTime) + { +#ifdef RANK_DEBUG + std::cerr << "Final (time) score:" << algScore / count; + std::cerr << std::endl; +#endif + return algScore / count; + } + return 0; +} + + +void p3Ranking::locked_reSortGroup(RankGroup &grp) +{ + std::string rid = grp.rid; + + /* remove from existings rankings */ + std::multimap::iterator rit; + rit = mRankings.lower_bound(grp.rank); + for(; (rit != mRankings.end()) && (rit->first == grp.rank); rit++) + { + if (rit->second == rid) + { + mRankings.erase(rit); + break; + } + } + + /* add it back in */ + grp.rank = locked_calcRank(grp); + mRankings.insert( + std::pair(grp.rank, rid)); +} + +void p3Ranking::sortAllMsgs() +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + /* iterate through list and re-score each one */ + std::map::iterator it; + + mRankings.clear(); + + for(it = mData.begin(); it != mData.end(); it++) + { + (it->second).rank = locked_calcRank(it->second); + if (it->second.rank < 0) + { + it->second.rank = 0; + } + + mRankings.insert( + std::pair + (it->second.rank, it->first)); + } +} + +/******** ACCESS *************/ + + /* get Ids */ +uint32_t p3Ranking::getRankingsCount() +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + return mRankings.size(); +} + +float p3Ranking::getMaxRank() +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + if (mRankings.size() == 0) + return 0; + + return mRankings.rbegin()->first; +} + +bool p3Ranking::getRankings(uint32_t first, uint32_t count, std::list &rids) +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::getRankings() First: " << first << " Count: " << count; + std::cerr << std::endl; +#endif + + uint32_t i = 0; + std::multimap::reverse_iterator rit; + for(rit = mRankings.rbegin(); (i < first) && (rit != mRankings.rend()); rit++, i++) ; + + i = 0; + for(; (i < count) && (rit != mRankings.rend()); rit++, i++) + { + rids.push_back(rit->second); + } + return true; +} + + +bool p3Ranking::getRankDetails(std::string rid, RsRankDetails &details) +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + /* get the details. */ + + std::map::iterator it; + it = mData.find(rid); + if (mData.end() == it) + { + return false; + } + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + + details.rid = it->first; + details.link = (it->second).link; + details.title = (it->second).title; + details.rank = (it->second).rank; + details.ownTag = (it->second).ownTag; + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + + std::map::iterator cit; + for(cit = (it->second).comments.begin(); + cit != (it->second).comments.end(); cit++) + { + RsRankComment comm; + comm.id = (cit->second)->PeerId(); + comm.timestamp = (cit->second)->timestamp; + comm.comment = (cit->second)->comment; + comm.score = (cit->second)->score; + + details.comments.push_back(comm); + } + + return true; +} + + +void p3Ranking::tick() +{ + bool repub = false; + bool repubFriends = false; + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + repub = mRepublish; + repubFriends = mRepublishFriends && (time(NULL) > mRepublishFriendTS); + } + + if (repub) + { + publishMsgs(true); + + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mRepublish = false; + } + + + if (repubFriends) + { + publishMsgs(false); + + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mRepublishFriends = false; + mRepublishFriendTS = time(NULL) + FRIEND_RANK_REPUBLISH_PERIOD; + } + + +} + +bool p3Ranking::updated() +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + if (mUpdated) + { + mUpdated = false; + return true; + } + return false; +} + +/***** NEW CONTENT *****/ +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ +std::string p3Ranking::newRankMsg(std::wstring link, std::wstring title, std::wstring comment, int32_t score) +{ + /* generate an id */ + std::string rid = generateRandomLinkId(); + + RsRankLinkMsg *msg = new RsRankLinkMsg(); + + time_t now = time(NULL); + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + msg->PeerId(mOwnId); + msg->pid = mOwnId; + } + + msg->rid = rid; + msg->title = title; + msg->timestamp = now; + msg->comment = comment; + msg->score = score; + + msg->linktype = RS_LINK_TYPE_WEB; + msg->link = link; + + + addRankMsg(msg); + + return rid; +} + + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ +bool p3Ranking::updateComment(std::string rid, std::wstring comment, int32_t score) +{ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::updateComment() rid:" << rid; + std::cerr << std::endl; +#endif + RsRankLinkMsg *msg = NULL; + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it; + it = mData.find(rid); + if (it == mData.end()) + { + /* missing group -> fail */ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::updateComment() Failed - noData"; + std::cerr << std::endl; +#endif + return false; + } + + msg = new RsRankLinkMsg(); + + time_t now = time(NULL); + + msg->PeerId(mOwnId); + msg->pid = mOwnId; + msg->rid = rid; + msg->timestamp = now; + msg->title = (it->second).title; + msg->comment = comment; + msg->score = score; + + msg->linktype = RS_LINK_TYPE_WEB; + msg->link = (it->second).link; + + } /********** STACK UNLOCKED MTX ******/ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::updateComment() Item:"; + std::cerr << std::endl; + msg->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + addRankMsg(msg); + return true; +} + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ +std::string p3Ranking::anonRankMsg(std::string rid, std::wstring link, std::wstring title) +{ + bool alreadyExists = true; + + if (rid == "") + { + alreadyExists = false; + /* generate an id */ + rid = generateRandomLinkId(); + } + + RsRankLinkMsg *msg1 = new RsRankLinkMsg(); + RsRankLinkMsg *msg2 = new RsRankLinkMsg(); + + time_t now = time(NULL); + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + msg1->PeerId(""); + msg1->pid = ""; + + msg2->PeerId(""); + msg2->pid = ""; + } + + msg1->rid = rid; + msg1->title = title; + msg1->timestamp = now; + msg1->comment.clear(); + msg1->score = 0; + + msg1->linktype = RS_LINK_TYPE_WEB; + msg1->link = link; + + msg2->rid = rid; + msg2->title = title; + msg2->timestamp = now; + msg2->comment.clear(); + msg2->score = 0; + + msg2->linktype = RS_LINK_TYPE_WEB; + msg2->link = link; + + if (alreadyExists) + { + delete msg1; + } + else + { + addRankMsg(msg1); + } + + addAnonToList(msg2); + + return rid; +} + + + +pqistore *createStore(std::string file, std::string src, bool reading) +{ + + RsSerialiser *rsSerialiser = new RsSerialiser(); + rsSerialiser->addSerialType(new RsRankSerialiser()); + + uint32_t bioflags = BIN_FLAGS_HASH_DATA; + if (reading) + { + bioflags |= BIN_FLAGS_READABLE; + } + else + { + bioflags |= BIN_FLAGS_WRITEABLE; + } + + /* bin flags: READ | WRITE | HASH_DATA */ + BinInterface *bio = new BinFileInterface(file.c_str(), bioflags); + /* store flags: NO_DELETE (yes) | NO_CLOSE (no) */ + pqistore *store = new pqistore(rsSerialiser, src, bio, BIN_FLAGS_NO_DELETE | (bioflags & BIN_FLAGS_WRITEABLE)); + + return store; +} + +std::string generateRandomLinkId() +{ + std::ostringstream out; + out << std::hex; +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + /* 4 bytes per random number: 4 x 4 = 16 bytes */ + for(int i = 0; i < 4; i++) + { + out << std::setw(8) << std::setfill('0'); + uint32_t rint = random(); + out << rint; + } +#else + srand(time(NULL)); + /* 2 bytes per random number: 8 x 2 = 16 bytes */ + for(int i = 0; i < 8; i++) + { + out << std::setw(4) << std::setfill('0'); + uint16_t rint = rand(); /* only gives 16 bits */ + out << rint; + } +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + return out.str(); +} + + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ +void p3Ranking::createDummyData() +{ + RsRankLinkMsg *msg = new RsRankLinkMsg(); + + time_t now = time(NULL); + + msg->PeerId(mOwnId); + msg->pid = mOwnId; + msg->rid = "0001"; + msg->title = L"Original Awesome Site!"; + msg->timestamp = now - 60 * 60 * 24 * 15; + msg->link = L"http://www.retroshare.org"; + msg->comment = L"Retroshares Website"; + msg->score = 1; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId(mOwnId); + msg->pid = mOwnId; + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 123; + msg->link = L"http://www.lunamutt.org"; + msg->comment = L"Lunamutt's Website"; + msg->score = 1; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId("ALTID"); + msg->pid = "ALTID"; + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 60 * 60 * 24 * 29; + msg->link = L"http://www.lunamutt.org"; + msg->comment = L"Lunamutt's Website (TWO) How Long can this comment be!\n"; + msg->comment += L"What happens to the second line?\n"; + msg->comment += L"And a 3rd!"; + msg->score = 1; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId("ALTID2"); + msg->pid = "ALTID2"; + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 60 * 60 * 7; + msg->link = L"http://www.lunamutt.org"; + msg->comment += L"A Short Comment"; + msg->score = 1; + + addRankMsg(msg); + + + /***** Third one ****/ + + msg = new RsRankLinkMsg(); + msg->PeerId(mOwnId); + msg->pid = mOwnId; + msg->rid = "0003"; + msg->title = L"Weird Site!"; + msg->timestamp = now - 60 * 60; + msg->link = L"http://www.lunamutt.com"; + msg->comment = L""; + msg->score = 1; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId("ALTID"); + msg->pid = "ALTID"; + msg->rid = "0003"; + msg->title = L"Weird Site!"; + msg->timestamp = now - 60 * 60 * 24 * 2; + msg->link = L"http://www.lunamutt.com"; + msg->comment = L""; + msg->score = 1; + + addRankMsg(msg); + +} + + +/***************************************************************************/ +/****************************** CONFIGURATION HANDLING *********************/ +/***************************************************************************/ + +/**** Store Anon Links: OVERLOADED FROM p3Config ****/ + +RsSerialiser *p3Ranking::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + + /* add in the types we need! */ + rss->addSerialType(new RsRankSerialiser()); + return rss; +} + +bool p3Ranking::addAnonToList(RsRankLinkMsg *msg) +{ + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + std::list::iterator it; + for(it = mAnon.begin(); it != mAnon.end(); it++) + { + if (msg->rid == (*it)->rid) + break; + } + + if (it != mAnon.end()) + { + delete msg; + return false; + } + + mAnon.push_back(msg); + mRepublishFriends = true; + } + + IndicateConfigChanged(); /**** INDICATE CONFIG CHANGED! *****/ + return true; +} + +bool p3Ranking::saveList(bool &cleanup, std::list & saveData) +{ + + mRankMtx.lock(); /*********************** LOCK *******/ + + cleanup = false; + + std::list::iterator it; + for(it = mAnon.begin(); it != mAnon.end(); it++) + { + saveData.push_back(*it); + } + + /* list completed! */ + return true; +} + +void p3Ranking::saveDone() +{ + mRankMtx.unlock(); /*********************** UNLOCK *******/ + return; +} + +bool p3Ranking::loadList(std::list& load) +{ + std::list::iterator it; + RsRankLinkMsg *msg; + +#ifdef SERVER_DEBUG + std::cerr << "p3Ranking::loadList() Item Count: " << load.size(); + std::cerr << std::endl; +#endif + + time_t now = time(NULL); + time_t min, max; + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + min = now - mStorePeriod; + max = now + RANK_MAX_FWD_OFFSET; + + } /********** STACK LOCKED MTX ******/ + + for(it = load.begin(); it != load.end(); it++) + { + /* switch on type */ + if (NULL != (msg = dynamic_cast(*it))) + { + /* check date -> if old expire */ + if (((time_t) msg->timestamp < min) || + ((time_t) msg->timestamp > max)) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadList() Outside TimeRange (deleting Own Anon):"; + std::cerr << std::endl; +#endif + /* if outside range -> remove */ + delete msg; + continue; + } + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadList() Anon TimeRange ok"; + std::cerr << std::endl; +#endif + msg->PeerId(""); + msg->pid = ""; + + RsRankLinkMsg *msg2 = new RsRankLinkMsg(); + msg2->clear(); + msg2->PeerId(msg->PeerId()); + msg2->pid = msg->pid; + msg2->rid = msg->rid; + msg2->title = msg->title; + msg2->timestamp = msg->timestamp; + msg2->comment.clear(); + msg2->score = 0; + + msg2->linktype = msg->linktype; + msg2->link = msg->link; + + /* make a copy to add into standard map */ + addRankMsg(msg); + + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mAnon.push_back(msg2); + } + else + { + /* cleanup */ + delete (*it); + } + } + + return true; + +} + diff --git a/libretroshare/src/services/p3ranking.h b/libretroshare/src/services/p3ranking.h new file mode 100644 index 000000000..94be29778 --- /dev/null +++ b/libretroshare/src/services/p3ranking.h @@ -0,0 +1,167 @@ +/* + * libretroshare/src/services: p3ranking.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_GENERIC_RANKING_HEADER +#define P3_GENERIC_RANKING_HEADER + +#include "dbase/cachestrapper.h" +#include "pqi/pqiservice.h" +#include "pqi/pqistore.h" +#include "pqi/p3connmgr.h" +#include "pqi/p3cfgmgr.h" + +#include "serialiser/rsserial.h" + +#include "retroshare/rsrank.h" + +/* + * A Generic Ranking system. + * Each User provides one cache... + * + * can be overloaded for specific types + * (links, shares, photos etc) + * + * This is not generic yet!!! + */ + +class RsRankMsg; +class RsRankLinkMsg; + +class RankGroup +{ + public: + + std::string rid; /* Random Id */ + std::wstring link; + std::wstring title; + float rank; + bool ownTag; + std::map comments; +}; + + +class p3Ranking: public CacheSource, public CacheStore, public p3Config +{ + public: + + p3Ranking(p3ConnectMgr *connMgr, + uint16_t type, CacheStrapper *cs, CacheTransfer *cft, + std::string sourcedir, std::string storedir, + uint32_t storePeriod); + +/******************************* CACHE SOURCE / STORE Interface *********************/ + + /* overloaded functions from Cache Source */ +virtual bool loadLocalCache(const CacheData &data); + + /* overloaded functions from Cache Store */ +virtual int loadCache(const CacheData &data); + +/******************************* CACHE SOURCE / STORE Interface *********************/ + + public: + +/************* Extern Interface *******/ + + /* changed */ +virtual bool updated(); + + /* Set Sort Methods */ +virtual bool setSortPeriod(uint32_t period); +virtual bool setSortMethod(uint32_t type); +virtual bool clearPeerFilter(); +virtual bool setPeerFilter(std::list peers); + + /* get Ids */ +virtual uint32_t getRankingsCount(); +virtual float getMaxRank(); +virtual bool getRankings(uint32_t first, uint32_t count, std::list &rids); +virtual bool getRankDetails(std::string rid, RsRankDetails &details); + + /* Add New Comment / Msg */ +virtual std::string newRankMsg(std::wstring link, std::wstring title, std::wstring comment, int32_t score); +virtual bool updateComment(std::string rid, std::wstring comment, int32_t score); +virtual std::string anonRankMsg(std::string rid, std::wstring link, std::wstring title); + + +void tick(); + +void loadRankFile(std::string filename, std::string src); +void addRankMsg(RsRankLinkMsg *msg); +void publishMsgs(bool own); + +float locked_calcRank(RankGroup &grp); /* returns 0->100 */ +void locked_reSortGroup(RankGroup &grp); + +void sortAllMsgs(); +pqistore *createStore(std::string file, std::string src, bool reading); + + + /****************** p3Config STUFF *******************/ + protected: +bool addAnonToList(RsRankLinkMsg *msg); + +virtual RsSerialiser *setupSerialiser(); +virtual bool saveList(bool &cleanup, std::list&); +virtual bool loadList(std::list& load); +virtual void saveDone(); + + private: + +void createDummyData(); + + p3ConnectMgr *mConnMgr; + + RsMutex mRankMtx; + + /***** below here is locked *****/ + + bool mRepublish; + bool mRepublishFriends; + time_t mRepublishFriendTS; + + uint32_t mStorePeriod; + + std::string mOwnId; + bool mUpdated; + bool mRepost; + + std::map mData; + std::multimap mRankings; + + /* Filter/Sort params */ + std::list mPeerFilter; + uint32_t mViewPeriod; + uint32_t mSortType; + + /* Anonymous Link List */ + std::list mAnon; + +}; + +#endif + + + diff --git a/libretroshare/src/services/p3service.cc b/libretroshare/src/services/p3service.cc new file mode 100644 index 000000000..e3a40a785 --- /dev/null +++ b/libretroshare/src/services/p3service.cc @@ -0,0 +1,244 @@ +/* + * libretroshare/src/services p3service.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqi.h" +#include "services/p3service.h" +#include +#include + +/***** + * #define SERV_DEBUG 1 + ****/ + +void p3Service::addSerialType(RsSerialType *st) +{ + rsSerialiser->addSerialType(st); +} + +RsItem *p3Service::recvItem() +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + + if (recv_queue.size() == 0) + { + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + return NULL; /* nothing there! */ + } + + /* get something off front */ + RsItem *item = recv_queue.front(); + recv_queue.pop_front(); + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + return item; +} + + +bool p3Service::receivedItems() +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + + bool moreData = (recv_queue.size() != 0); + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + + return moreData; +} + + +int p3Service::sendItem(RsItem *item) +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + + send_queue.push_back(item); + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + + return 1; +} + + // overloaded pqiService interface. +int p3Service::receive(RsRawItem *raw) +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + +#ifdef SERV_DEBUG + std::cerr << "p3Service::receive()"; + std::cerr << std::endl; +#endif + + /* convert to RsServiceItem */ + uint32_t size = raw->getRawLength(); + RsItem *item = rsSerialiser->deserialise(raw->getRawData(), &size); + if ((!item) || (size != raw->getRawLength())) + { + /* error in conversion */ +#ifdef SERV_DEBUG + std::cerr << "p3Service::receive() Error" << std::endl; + std::cerr << "p3Service::receive() Size: " << size << std::endl; + std::cerr << "p3Service::receive() RawLength: " << raw->getRawLength() << std::endl; +#endif + + if (item) + { +#ifdef SERV_DEBUG + std::cerr << "p3Service::receive() Bad Item:"; + std::cerr << std::endl; + item->print(std::cerr, 0); + std::cerr << std::endl; +#endif + delete item; + item=NULL ; + } + } + + + /* if we have something - pass it on */ + if (item) + { +#ifdef SERV_DEBUG + std::cerr << "p3Service::receive() item:"; + std::cerr << std::endl; + item->print(std::cerr, 0); + std::cerr << std::endl; +#endif + + /* ensure PeerId is transferred */ + item->PeerId(raw->PeerId()); + recv_queue.push_back(item); + } + + /* cleanup input */ + delete raw; + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + + return (item != NULL); +} + +RsRawItem *p3Service::send() +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + + if (send_queue.size() == 0) + { + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + return NULL; /* nothing there! */ + } + + /* get something off front */ + RsItem *si = send_queue.front(); + send_queue.pop_front(); + +#ifdef SERV_DEBUG + std::cerr << "p3Service::send() Sending item:"; + std::cerr << std::endl; + si->print(std::cerr, 0); + std::cerr << std::endl; +#endif + + /* try to convert */ + uint32_t size = rsSerialiser->size(si); + if (!size) + { +#ifdef SERV_DEBUG + std::cerr << "p3Service::send() ERROR size == 0"; + std::cerr << std::endl; +#endif + + /* can't convert! */ + delete si; + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + return NULL; + } + + RsRawItem *raw = new RsRawItem(si->PacketId(), size); + if (!rsSerialiser->serialise(si, raw->getRawData(), &size)) + { +#ifdef SERV_DEBUG + std::cerr << "p3Service::send() ERROR serialise failed"; + std::cerr << std::endl; +#endif + delete raw; + raw = NULL; + } + + if ((raw) && (size != raw->getRawLength())) + { +#ifdef SERV_DEBUG + std::cerr << "p3Service::send() ERROR serialise size mismatch"; + std::cerr << std::endl; +#endif + delete raw; + raw = NULL; + } + + /* ensure PeerId is transferred */ + if (raw) + { + raw->PeerId(si->PeerId()); + raw->setQueueType(si->queueType()) ; + } + + /* cleanup */ + delete si; + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ +#ifdef SERV_DEBUG + std::cerr << "p3Service::send() returning RawItem."; + std::cerr << std::endl; +#endif + return raw; +} + + +std::string generateRandomServiceId() +{ + std::ostringstream out; + out << std::hex; +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + /* 4 bytes per random number: 4 x 4 = 16 bytes */ + for(int i = 0; i < 4; i++) + { + out << std::setw(8) << std::setfill('0'); + uint32_t rint = random(); + out << rint; + } +#else + srand(time(NULL)); + /* 2 bytes per random number: 8 x 2 = 16 bytes */ + for(int i = 0; i < 8; i++) + { + out << std::setw(4) << std::setfill('0'); + uint16_t rint = rand(); /* only gives 16 bits */ + out << rint; + } +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + return out.str(); +} + + diff --git a/libretroshare/src/services/p3service.h b/libretroshare/src/services/p3service.h new file mode 100644 index 000000000..8007ac378 --- /dev/null +++ b/libretroshare/src/services/p3service.h @@ -0,0 +1,145 @@ +/* + * libretroshare/src/services p3service.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_GENERIC_SERVICE_HEADER +#define P3_GENERIC_SERVICE_HEADER + +#include "pqi/pqi.h" +#include "pqi/pqiservice.h" +#include "util/rsthreads.h" + +/* This provides easy to use extensions to the pqiservice class provided in src/pqi. + * + * We will have a number of different strains. + * + * (1) p3Service -> pqiService + * + * Basic service with serialisation handled by a RsSerialiser. + * + * (2) p3ThreadedService -> p3service. + * + * Independent thread with mutex locks for i/o Queues. + * ideal for games etc. + * + * (3) p3CacheService -> p3service + CacheSource + CacheStore. + * + * For both Cached and Messages. + */ + +std::string generateRandomServiceId(); + +//TODO : encryption and upload / download rate implementation + +class p3Service: public pqiService +{ + protected: + + p3Service(uint16_t type) + :pqiService((((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + (((uint32_t) type) << 8)), + rsSerialiser(NULL) + { + rsSerialiser = new RsSerialiser(); + return; + } + + public: + +virtual ~p3Service() { delete rsSerialiser; return; } + +/*************** INTERFACE ******************************/ + /* called from Thread/tick/GUI */ +int sendItem(RsItem *); +RsItem * recvItem(); +bool receivedItems(); + +virtual int tick() { return 0; } +/*************** INTERFACE ******************************/ + + + public: + // overloaded pqiService interface. +virtual int receive(RsRawItem *); +virtual RsRawItem * send(); + + protected: +void addSerialType(RsSerialType *); + + private: + + RsMutex srvMtx; + /* below locked by Mutex */ + + RsSerialiser *rsSerialiser; + std::list recv_queue, send_queue; +}; + + +class nullService: public pqiService +{ + protected: + + nullService(uint16_t type) + :pqiService((((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + (((uint32_t) type) << 8)) + { + return; + } + +//virtual int tick() + + public: + // overloaded NULL pqiService interface. +virtual int receive(RsRawItem *item) + { + /* drop any items */ + delete item; + return 1; + } + +virtual RsRawItem * send() + { + return NULL; + } + +}; + + +class p3ThreadedService: public p3Service, public RsThread +{ + protected: + + p3ThreadedService(uint16_t type) + :p3Service(type) { return; } + + public: + +virtual ~p3ThreadedService() { return; } + + private: + +}; + + +#endif // P3_GENERIC_SERVICE_HEADER + diff --git a/libretroshare/src/services/p3statusservice.cc b/libretroshare/src/services/p3statusservice.cc new file mode 100644 index 000000000..f0601ab49 --- /dev/null +++ b/libretroshare/src/services/p3statusservice.cc @@ -0,0 +1,383 @@ +/* + * libretroshare/src/services: p3statusservice.cc + * + * RetroShare C++ . + * + * Copyright 2008 by Vinny Do, Chris Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "services/p3statusservice.h" +#include "serialiser/rsstatusitems.h" +#include "retroshare/rsiface.h" + +#include +#include +#include +#include + +std::ostream& operator<<(std::ostream& out, const StatusInfo& si) +{ + out << "StatusInfo: " << std::endl; + out << "id: " << si.id << std::endl; + out << "status: " << si.status << std::endl; + out << "time_stamp: " << si.time_stamp << std::endl; + return out; +} + +RsStatus *rsStatus = NULL; + +p3StatusService::p3StatusService(p3ConnectMgr *cm) + :p3Service(RS_SERVICE_TYPE_STATUS), p3Config(CONFIG_TYPE_STATUS), mConnMgr(cm) +{ + addSerialType(new RsStatusSerialiser()); + +} + +p3StatusService::~p3StatusService() +{ +} + +bool p3StatusService::getOwnStatus(StatusInfo& statusInfo) +{ +#ifdef STATUS_DEBUG + std::cerr << "p3StatusService::getOwnStatus() " << std::endl; +#endif + + std::map::iterator it; + std::string ownId = mConnMgr->getOwnId(); + + RsStackMutex stack(mStatusMtx); + it = mStatusInfoMap.find(ownId); + + if (it == mStatusInfoMap.end()){ + std::cerr << "p3StatusService::saveList() :" << "Did not find your status" << ownId << std::endl; + return false; + } + + statusInfo = it->second; + + return true; +} + +bool p3StatusService::getStatusList(std::list& statusInfo) +{ +#ifdef STATUS_DEBUG + std::cerr << "p3StatusService::getStatusList() " << std::endl; +#endif + + statusInfo.clear(); + + RsStackMutex stack(mStatusMtx); + + // fill up statusInfo list with this information + std::map::iterator mit; + for(mit = mStatusInfoMap.begin(); mit != mStatusInfoMap.end(); mit++){ + statusInfo.push_back(mit->second); + } + + return true; +} + +bool p3StatusService::getStatus(std::string &id, StatusInfo &statusInfo) +{ +#ifdef STATUS_DEBUG + std::cerr << "p3StatusService::getStatus() " << std::endl; +#endif + + RsStackMutex stack(mStatusMtx); + + std::map::iterator mit = mStatusInfoMap.find(id); + + if (mit == mStatusInfoMap.end()) { + /* return fake status info as offline */ + statusInfo = StatusInfo(); + + statusInfo.id = id; + statusInfo.status = RS_STATUS_OFFLINE; + return false; + } + + statusInfo = mit->second; + + return true; +} + +/* id = "", status is sent to all online peers */ +bool p3StatusService::sendStatus(const std::string &id, uint32_t status) +{ + StatusInfo statusInfo; + std::list onlineList; + + { + RsStackMutex stack(mStatusMtx); + + statusInfo.id = mConnMgr->getOwnId(); + statusInfo.status = status; + + // don't save inactive status + if(statusInfo.status != RS_STATUS_INACTIVE){ + + // If your id is not set, set it + if(mStatusInfoMap.find(statusInfo.id) == mStatusInfoMap.end()){ + + std::pair pr(statusInfo.id, statusInfo); + mStatusInfoMap.insert(pr); + IndicateConfigChanged(); + } else if(mStatusInfoMap[statusInfo.id].status != statusInfo.status){ + + IndicateConfigChanged(); + mStatusInfoMap[statusInfo.id] = statusInfo; + } + } + + if (id.empty()) { + mConnMgr->getOnlineList(onlineList); + } else { + onlineList.push_back(id); + } + } + + std::list::iterator it; + +#ifdef STATUS_DEBUG + std::cerr << "p3StatusService::sendStatus() " << std::endl; + std::cerr << statusInfo; +#endif + + // send to all peers online + for(it = onlineList.begin(); it != onlineList.end(); it++){ + RsStatusItem* statusItem = new RsStatusItem(); + statusItem->sendTime = time(NULL); + statusItem->status = statusInfo.status; + statusItem->PeerId(*it); + sendItem(statusItem); + } + + /* send notify of own status change */ + rsicontrol->getNotify().notifyPeerStatusChanged(statusInfo.id, statusInfo.status); + + return true; +} + +/******************************/ + +void p3StatusService::receiveStatusQueue() +{ + std::map changed; + + { + RsStackMutex stack(mStatusMtx); + + RsItem* item; + + while(NULL != (item = recvItem())){ + + RsStatusItem* status_item = dynamic_cast(item); + + if(status_item == NULL) { + std::cerr << "p3Status::getStatusQueue() " << "Failed to cast Item \n" << std::endl; + delete (item); + continue; + } + +#ifdef STATUS_DEBUG + std::cerr << "p3StatusService::getStatusQueue()" << std::endl; + std::cerr << "PeerId : " << status_item->PeerId() << std::endl; + std::cerr << "Status: " << status_item->status << std::endl; + std::cerr << "Got status Item" << std::endl; +#endif + + std::map::iterator mit = mStatusInfoMap.find(status_item->PeerId()); + + if(mit != mStatusInfoMap.end()){ + mit->second.id = status_item->PeerId(); + + if (mit->second.status != status_item->status) { + changed [mit->second.id] = status_item->status; + } + + mit->second.status = status_item->status; + mit->second.time_stamp = status_item->sendTime; +#ifdef STATUS_DEBUG + } else { + std::cerr << "getStatus() " << "Could not find Peer" << status_item->PeerId(); + std::cerr << std::endl; +#endif + } + + delete (status_item); + } + + } /* UNLOCKED */ + + if (changed.size()) { + std::map::iterator it; + for (it = changed.begin(); it != changed.end(); it++) { + rsicontrol->getNotify().notifyPeerStatusChanged(it->first, it->second); + } + rsicontrol->getNotify().notifyPeerStatusChangedSummary(); + } +} + +/* p3Config */ + +RsSerialiser* p3StatusService::setupSerialiser(){ + + RsSerialiser *rss = new RsSerialiser; + rss->addSerialType(new RsStatusSerialiser); + + return rss; +} + +bool p3StatusService::saveList(bool& cleanup, std::list& ilist){ + + // save your status before quiting + cleanup = true; + RsStatusItem* own_status = new RsStatusItem; + StatusInfo own_info; + + std::map::iterator it; + + { + RsStackMutex stack(mStatusMtx); + it = mStatusInfoMap.find(mConnMgr->getOwnId()); + + if(it == mStatusInfoMap.end()){ + std::cerr << "p3StatusService::saveList() :" << "Did not find your status" + << mConnMgr->getOwnId() << std::endl; + delete own_status; + return false; + } + + own_info = it->second; + } + + own_status->PeerId(own_info.id); + own_status->sendTime = own_info.time_stamp; + own_status->status = own_info.status; + + ilist.push_back(own_status); + + return true; +} + +bool p3StatusService::loadList(std::list& load){ + + // load your status from last rs session + StatusInfo own_info; + std::list::const_iterator it = load.begin(); + + if(it == load.end()){ + std::cerr << "p3StatusService::loadList(): Failed to load " << std::endl; + return false; + } + + for(; it != load.end(); it++){ + RsStatusItem* own_status = dynamic_cast(*it); + + + if(own_status != NULL){ + + own_info.id = mConnMgr->getOwnId(); + own_info.status = own_status->status; + own_info.time_stamp = own_status->sendTime; + delete own_status; + + { + RsStackMutex stack(mStatusMtx); + std::pair pr(mConnMgr->getOwnId(), own_info); + mStatusInfoMap.insert(pr); + } + + return true; + }else{ + std::cerr << "p3StatusService::loadList " << "Failed to load list " + << std::endl; + } + + } + return false; +} + + +int p3StatusService::tick() +{ + if (receivedItems()) { + receiveStatusQueue(); + } + + return 0; +} + +int p3StatusService::status(){ + return 1; +} + +/*************** pqiMonitor callback ***********************/ + +void p3StatusService::statusChange(const std::list &plist) +{ + bool changedState = false; + + StatusInfo statusInfo; + std::list::const_iterator it; + for (it = plist.begin(); it != plist.end(); it++) { + if (it->state & RS_PEER_S_FRIEND) { + if (it->actions & RS_PEER_DISCONNECTED) + { + { + RsStackMutex stack(mStatusMtx); + /* remove peer from status map */ + mStatusInfoMap.erase(it->id); + } /* UNLOCKED */ + + changedState = true; + rsicontrol->getNotify().notifyPeerStatusChanged(it->id, RS_STATUS_OFFLINE); + } + + if (it->actions & RS_PEER_CONNECTED) { + /* send current status, only call getOwnStatus once in the loop */ + if (statusInfo.id.empty() == false || getOwnStatus(statusInfo)) { + sendStatus(it->id, statusInfo.status); + } + + { + RsStackMutex stack(mStatusMtx); + + /* We assume that the peer is online. If not, he send us a new status */ + StatusInfo info; + info.id = it->id; + info.status = RS_STATUS_ONLINE; + info.time_stamp = time(NULL); + + mStatusInfoMap[it->id] = info; + } /* UNLOCKED */ + + changedState = true; + rsicontrol->getNotify().notifyPeerStatusChanged(it->id, RS_STATUS_ONLINE); + } + } + } + + if (changedState) + { + rsicontrol->getNotify().notifyPeerStatusChangedSummary(); + } +} diff --git a/libretroshare/src/services/p3statusservice.h b/libretroshare/src/services/p3statusservice.h new file mode 100644 index 000000000..bd98df7f6 --- /dev/null +++ b/libretroshare/src/services/p3statusservice.h @@ -0,0 +1,101 @@ +#ifndef RS_P3_STATUS_INTERFACE_H +#define RS_P3_STATUS_INTERFACE_H + +/* + * libretroshare/src/services: p3statusService.h + * + * RetroShare C++ + * + * Copyright 2008 by Vinny Do, Chris Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include + +#include "serialiser/rsstatusitems.h" +#include "retroshare/rsstatus.h" +#include "services/p3service.h" +#include "pqi/p3connmgr.h" + +//! handles standard status messages (busy, away, online, offline) set by user +/*! + * The is a retroshare service which allows peers + * to inform each other about their status in a standard way, as opposed to + * custom string. + * @see rsiface/rsstatus.h for status constants + */ +class p3StatusService: public p3Service, public p3Config, public pqiMonitor +{ + public: + + p3StatusService(p3ConnectMgr* ); +virtual ~p3StatusService(); + +/***** overloaded from p3Service *****/ +virtual int tick(); +virtual int status(); + +/*************** pqiMonitor callback ***********************/ +virtual void statusChange(const std::list &plist); + +/********* RsStatus ***********/ + +/** + * Status is set to offline as default if no info received from relevant peer + */ +virtual bool getOwnStatus(StatusInfo& statusInfo); +virtual bool getStatusList(std::list& statusInfo); +virtual bool getStatus(std::string &id, StatusInfo &statusInfo); +/* id = "", status is sent to all online peers */ +virtual bool sendStatus(const std::string &id, uint32_t status); + +/******************************/ + + +/** implemented from p3Config **/ + +/*! + * @return The serialiser the enables storage of save info + */ +virtual RsSerialiser *setupSerialiser(); + +/*! + * This stores information on what your status was before you exited rs + */ +virtual bool saveList(bool& cleanup, std::list&); + +/*! + * @param load Should contain a single item which is clients status from last rs session + */ +virtual bool loadList(std::list& load); + + private: + +virtual void receiveStatusQueue(); + +p3ConnectMgr *mConnMgr; + +std::map mStatusInfoMap; + +RsMutex mStatusMtx; + +}; + +#endif diff --git a/libretroshare/src/services/p3tunnel.cc b/libretroshare/src/services/p3tunnel.cc new file mode 100644 index 000000000..d9bc45bce --- /dev/null +++ b/libretroshare/src/services/p3tunnel.cc @@ -0,0 +1,351 @@ +/* + * libretroshare/src/services: p3tunnel.cc + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "retroshare/rsiface.h" +#include "retroshare/rsinit.h" /* for PGPSSL flag */ +#include "retroshare/rspeers.h" +#include "services/p3tunnel.h" +#include "pqi/pqissltunnel.h" +#include + +#include "pqi/authssl.h" +#include "pqi/p3connmgr.h" + +#include + +#include "util/rsdebug.h" +#include "util/rsprint.h" +#include "util/rsversion.h" + +#define TUNNEL_HANDSHAKE_INIT 1 +#define TUNNEL_HANDSHAKE_ACK 2 +#define TUNNEL_HANDSHAKE_REFUSE 0 + + p3tunnel::p3tunnel(p3ConnectMgr *cm, pqipersongrp *perGrp) +:p3Service(RS_SERVICE_TYPE_TUNNEL), mConnMgr(cm), mPqiPersonGrp(perGrp) +{ + RsStackMutex stack(mTunnelMtx); /********** STACK LOCKED MTX ******/ + + ownId = mConnMgr->getOwnId(); + std::cerr << "ownId : " << mConnMgr->getOwnId() << std::endl; + addSerialType(new RsTunnelSerialiser()); + + return; +} + +void p3tunnel::statusChange(const std::list &plist) { +} + +int p3tunnel::tick() +{ + return handleIncoming(); +} + +int p3tunnel::handleIncoming() +{ + RsItem *item = NULL; + +#ifdef P3TUNNEL_DEBUG + //std::cerr << "p3tunnel::handleIncoming() called." << std::endl; +#endif + + int nhandled = 0; + // While messages read + while(NULL != (item = recvItem())) + { + if (!mConnMgr->getTunnelConnection()) { + //no tunnel allowed, just drop the packet + continue; + } + + RsTunnelDataItem *tdi = NULL; + RsTunnelHandshakeItem *thi = NULL; + + { +#ifdef P3TUNNEL_DEBUG + std::ostringstream out; + out << "p3tunnel::handleIncoming()"; + out << " Received Message!" << std::endl; + item -> print(out); + std::cerr << out.str(); +#endif + } + + if (NULL != (tdi = dynamic_cast (item))) { + recvTunnelData(tdi); + nhandled++; + } else if (NULL != (thi = dynamic_cast (item))) { + recvTunnelHandshake(thi); + nhandled++; + } + delete item; + } + return nhandled; +} + +/*************************************************************************************/ +/* Output Network Msgs */ +/*************************************************************************************/ +void p3tunnel::sendTunnelData(std::string destPeerId, std::string relayPeerId, void *data, int data_length) { + sendTunnelDataPrivate(relayPeerId, ownId,relayPeerId, destPeerId, data, data_length); +} + + +void p3tunnel::sendTunnelDataPrivate(std::string to, std::string sourcePeerId, std::string relayPeerId, std::string destPeerId, void *data, int data_length) { + if (!mConnMgr->getTunnelConnection()) { + //no tunnel allowed, just drop the request + return; + } + + RsStackMutex stack(mTunnelMtx); /********** STACK LOCKED MTX ******/ + + // Then send message. + { +#ifdef P3TUNNEL_DEBUG + std::ostringstream out; + out << "p3tunnel::sendTunnelDataPrivate() Constructing a RsTunnelItem Message!" << std::endl; + out << "Sending to: " << to; + std::cerr << out.str() << std::endl; +#endif + } + + // Construct a message + RsTunnelDataItem *rdi = new RsTunnelDataItem(); + rdi->destPeerId = destPeerId; + rdi->sourcePeerId = sourcePeerId; + rdi->relayPeerId = relayPeerId; + rdi->encoded_data_len = data_length; + + if(data_length > 0) + { + rdi->encoded_data = (void*)malloc(data_length); + memcpy(rdi->encoded_data, data, data_length); + } + + rdi->PeerId(to); + +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::sendTunnelDataPrivate() data_length : "<< data_length << std::endl; +#endif + /* send msg */ + sendItem(rdi); +} + +void p3tunnel::pingTunnelConnection(std::string relayPeerId, std::string destPeerId) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::pingTunnelConnection() sending ping with relay id : " << relayPeerId << std::endl; + std::cerr << "ownId : " << ownId << std::endl; + std::cerr << "destPeerId : " << destPeerId << std::endl; +#endif + this->sendTunnelDataPrivate(relayPeerId, ownId, relayPeerId, destPeerId, NULL, 0); +} + +void p3tunnel::initiateHandshake(std::string relayPeerId, std::string destPeerId) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::initiateHandshake() initiating handshake with relay id : " << relayPeerId << std::endl; + std::cerr << "ownId : " << ownId << std::endl; + std::cerr << "destPeerId : " << destPeerId << std::endl; +#endif + // Construct a message + RsTunnelHandshakeItem *rhi = new RsTunnelHandshakeItem(); + rhi->destPeerId = destPeerId; + rhi->sourcePeerId = ownId; + rhi->relayPeerId = relayPeerId; + rhi->connection_accepted = TUNNEL_HANDSHAKE_INIT; + rhi->sslCertPEM = AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); + + rhi->PeerId(relayPeerId); + + /* send msg */ + sendItem(rhi); +} + +/*************************************************************************************/ +/* Input Network Msgs */ +/*************************************************************************************/ +void p3tunnel::recvTunnelHandshake(RsTunnelHandshakeItem *item) +{ +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::recvTunnelHandshake() From: " << item->PeerId() << std::endl; +#endif + + RsPeerDetails pd; + if (!AuthSSL::getAuthSSL()->LoadDetailsFromStringCert(item->sslCertPEM, pd)) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::recvTunnelHandshake() cert is not valid. This might be a intrusion attempt." << std::endl; +#endif + return; + } + + if (item->sourcePeerId != pd.id) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::recvTunnelHandshake() cert is not issued from the source id of the tunnel. This might be a intrusion attempt." << std::endl; +#endif + return; + } + + //compare the peer id from the item sender to the ids in the item. + if (item->PeerId() == item->sourcePeerId && ownId == item->relayPeerId) { + if (mConnMgr->isOnline(item->destPeerId)) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::recvTunnelHandshake() relaying packet." << std::endl; +#endif + //relaying the handshake + RsTunnelHandshakeItem* forwardItem = new RsTunnelHandshakeItem(); + forwardItem->sourcePeerId = item->sourcePeerId; + forwardItem->relayPeerId = item->relayPeerId; + forwardItem->destPeerId = item->destPeerId; + forwardItem->connection_accepted = item->connection_accepted; + forwardItem->sslCertPEM = item->sslCertPEM; + forwardItem->PeerId(item->destPeerId); + sendItem(forwardItem); + } else { + //sending back refuse + //not implemented +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::recvTunnelHandshake() not relaying packet because destination is offline." << std::endl; +#endif + } + } else if (item->PeerId() == item->relayPeerId && ownId == item->destPeerId) { + if (item->connection_accepted == TUNNEL_HANDSHAKE_INIT || item->connection_accepted == TUNNEL_HANDSHAKE_ACK) { + //check if we accept connection + if (!mConnMgr->isFriend(pd.id)) { + //send back a refuse + // not implemented + } else { + if (item->connection_accepted == TUNNEL_HANDSHAKE_INIT) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::recvTunnelHandshake() sending back acknowledgement to " << item->sourcePeerId << std::endl; +#endif + //send back acknowledgement + RsTunnelHandshakeItem* ack = new RsTunnelHandshakeItem(); + ack->sourcePeerId = ownId; + ack->relayPeerId = item->relayPeerId; + ack->destPeerId = item->sourcePeerId; + ack->connection_accepted = TUNNEL_HANDSHAKE_ACK; + ack->sslCertPEM = AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); + ack->PeerId(item->relayPeerId); + sendItem(ack); + } + + //open the local tunnel connection +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::recvTunnelHandshake() opening localy the tunnel connection emulation." << std::endl; +#endif + pqiperson *pers = mPqiPersonGrp->getPeer(item->sourcePeerId); + pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); + pqicon->IncommingHanshakePacket(item->relayPeerId); + } + } + } +} + + +void p3tunnel::recvTunnelData(RsTunnelDataItem *item) +{ +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::recvPeerConnectRequest() From: " << item->PeerId() << std::endl; +#endif + + //compare the peer id from the item sender to the ids in the item. + if (item->PeerId() == item->sourcePeerId && ownId == item->relayPeerId) { + privateRecvTunnelDataRelaying(item); + } else if (item->PeerId() == item->relayPeerId && ownId == item->destPeerId) { + privateRecvTunnelDataDestination(item); + } +} + +void p3tunnel::privateRecvTunnelDataRelaying(RsTunnelDataItem *item) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataRelaying() I am relaying, let's see if it's possible to send the packet to destination." << std::endl; +#endif + if (!mConnMgr->isFriend(item->sourcePeerId) || !mConnMgr->isFriend(item->destPeerId)) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataDestination() not trusting relay or dest peer. Aborting." << std::endl; +#endif + return; + } + if (mConnMgr->isOnline(item->destPeerId)) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataRelaying() I am relaying, relay the packet to destination." << std::endl; +#endif + sendTunnelDataPrivate(item->destPeerId, item->sourcePeerId, ownId, item->destPeerId, item->encoded_data, item->encoded_data_len); + return; + } +} + +void p3tunnel::privateRecvTunnelDataDestination(RsTunnelDataItem *item) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataDestination() I am the destination Id, let's make some checks and read the packet." << std::endl; +#endif + + if (!mConnMgr->isFriend(item->sourcePeerId) || !mConnMgr->isFriend(item->relayPeerId)) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataDestination() not trusting relay or source peer. Aborting." << std::endl; +#endif + return; + } + + if (!mConnMgr->isOnline(item->relayPeerId)) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataDestination() relay peer is not connected, connection impossible. Aborting." << std::endl; +#endif + return; + } + + pqiperson *pers = mPqiPersonGrp->getPeer(item->sourcePeerId); + if (pers == NULL) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataDestination() tunnel connection not found. Aborting." << std::endl; +#endif + return; + } + + pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); + if (pqicon == NULL || !pqicon->isactive()) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataDestination() tunnel connection not found. Aborting." << std::endl; +#endif + return; + } + + //send the packet to the net emulation layer + if (item->encoded_data_len == 0) { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataDestination() receiving a ping packet, activating connection and sending back acknowlegment." << std::endl; +#endif + pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); + pqicon->IncommingPingPacket(); + } else { +#ifdef P3TUNNEL_DEBUG + std::cerr << "p3tunnel::privateRecvTunnelDataDestination() receiving a data packet, transfer it to the pqissltunnel connection." << std::endl; + std::cerr << "p3tunnel::privateRecvTunnelDataDestination() getRsItemSize(item->encoded_data) : " << getRsItemSize(item->encoded_data) << std::endl; +#endif + pqissltunnel *pqicon = (pqissltunnel *)(((pqiconnect *) pers->getKid(PQI_CONNECT_TUNNEL))->ni); + pqicon->addIncomingPacket(item->encoded_data, item->encoded_data_len); + } + return; +} diff --git a/libretroshare/src/services/p3tunnel.h b/libretroshare/src/services/p3tunnel.h new file mode 100644 index 000000000..ec5a03896 --- /dev/null +++ b/libretroshare/src/services/p3tunnel.h @@ -0,0 +1,82 @@ +/* + * libretroshare/src/services: p3tunnel.h + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_PQI_TUNNEL_H +#define MRK_PQI_TUNNEL_H + +// The AutoDiscovery Class + +#include "pqi/pqipersongrp.h" + +// system specific network headers +#include "pqi/pqi.h" + +class p3ConnectMgr; + +#include "pqi/pqimonitor.h" +#include "services/p3service.h" +#include "serialiser/rstunnelitems.h" +#include "pqi/authssl.h" + +class p3tunnel: public p3Service, public pqiMonitor +{ + public: + +virtual void statusChange(const std::list &plist); + + p3tunnel(p3ConnectMgr *cm, pqipersongrp *persGrp); + +int tick(); + +void sendTunnelData(std::string destPeerId, std::string relayPeerId, void *data, int data_length); + +void pingTunnelConnection(std::string relayPeerId, std::string destPeerId); +void initiateHandshake(std::string relayPeerId, std::string destPeerId); + + private: + +void sendTunnelDataPrivate(std::string to, std::string sourcePeerId, std::string relayPeerId, std::string destPeerId, void *data, int data_length); + +void privateRecvTunnelDataRelaying(RsTunnelDataItem *item); //invoked when I am relaying +void privateRecvTunnelDataDestination(RsTunnelDataItem *item); //invoked when I am the destination of the tunnel + + /* Network Input */ +int handleIncoming(); +void recvTunnelData(RsTunnelDataItem *item); +void recvTunnelHandshake(RsTunnelHandshakeItem *item); + + + private: + + p3ConnectMgr *mConnMgr; + pqipersongrp *mPqiPersonGrp; + std::string ownId; + + + /* data */ + RsMutex mTunnelMtx; +}; + +#endif // MRK_PQI_TUNNEL_H diff --git a/libretroshare/src/svn_revision.bat b/libretroshare/src/svn_revision.bat new file mode 100644 index 000000000..d828ece90 --- /dev/null +++ b/libretroshare/src/svn_revision.bat @@ -0,0 +1,2 @@ +@echo off +"D:\Programme\TortoiseSVN\bin\SubWCRev" . util\rsversion.in util\rsversion.h \ No newline at end of file diff --git a/libretroshare/src/tcponudp/bio_tou.h b/libretroshare/src/tcponudp/bio_tou.h new file mode 100644 index 000000000..cf02825e1 --- /dev/null +++ b/libretroshare/src/tcponudp/bio_tou.h @@ -0,0 +1,46 @@ +/* + * "$Id: bio_tou.h,v 1.2 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef BIO_TCPONUDP_H +#define BIO_TCPONUDP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +int BIO_tou_socket_should_retry(int s, int e); +int BIO_tou_socket_non_fatal_error(int error); + +#define BIO_TYPE_TOU_SOCKET (30|0x0400|0x0100) /* NEW rmfern type */ + +BIO_METHOD *BIO_s_tou_socket(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libretroshare/src/tcponudp/bss_tou.c b/libretroshare/src/tcponudp/bss_tou.c new file mode 100644 index 000000000..f96abb19d --- /dev/null +++ b/libretroshare/src/tcponudp/bss_tou.c @@ -0,0 +1,392 @@ +/* + * bss_tou.c Based on bss_*.c from OpenSSL Library.... + * Therefore - released under their licence. + * Copyright 2004-2006 by Robert Fernie. (retroshare@lunamutt.com) + */ + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef OPENSSL_NO_SOCK + +#include "bio_tou.h" + +// STUFF defined in the header....... +//int BIO_tou_socket_should_retry(int s, int e); +//int BIO_tou_socket_non_fatal_error(int error); +//#define BIO_TYPE_TOU_SOCKET (30|0x0400|0x0100) /* NEW rmfern type */ +//BIO_METHOD *BIO_s_tou_socket(void); + +#include +#include +#define USE_SOCKETS +//#include "cryptlib.h" +#include +#include /* for strlen() */ + + +static int tou_socket_write(BIO *h, const char *buf, int num); +static int tou_socket_read(BIO *h, char *buf, int size); +static int tou_socket_puts(BIO *h, const char *str); +static long tou_socket_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int tou_socket_new(BIO *h); +static int tou_socket_free(BIO *data); +static int get_last_tou_socket_error(int s); +static int clear_tou_socket_error(int s); + +#include "tou.h" + + + +static BIO_METHOD methods_tou_sockp= + { + BIO_TYPE_TOU_SOCKET, + "tou_socket", + tou_socket_write, + tou_socket_read, + tou_socket_puts, + NULL, /* tou_gets, */ + tou_socket_ctrl, + tou_socket_new, + tou_socket_free, + NULL, + }; + +BIO_METHOD *BIO_s_tou_socket(void) + { +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "BIO_s_tou_socket(void)\n"); +#endif + return(&methods_tou_sockp); + } + +BIO *BIO_new_tou_socket(int fd, int close_flag) + { + BIO *ret; +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "BIO_new_tou_socket(%d)\n", fd); +#endif + + ret=BIO_new(BIO_s_tou_socket()); + if (ret == NULL) return(NULL); + BIO_set_fd(ret,fd,close_flag); + return(ret); + } + +static int tou_socket_new(BIO *bi) + { +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_socket_new()\n"); +#endif + bi->init=0; + bi->num=0; + bi->ptr=NULL; + bi->flags=0; + return(1); + } + +static int tou_socket_free(BIO *a) + { +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_socket_free()\n"); +#endif + if (a == NULL) return(0); + if (a->shutdown) + { + if (a->init) + { + tou_close(a->num); + } + a->init=0; + a->flags=0; + } + return(1); + } + +static int tou_socket_read(BIO *b, char *out, int outl) + { + int ret=0; +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_socket_read(%p,%p,%d)\n",b,out,outl); +#endif + + if (out != NULL) + { + clear_tou_socket_error(b->num); + /* call tou library */ + ret=tou_read(b->num,out,outl); + BIO_clear_retry_flags(b); + if (ret <= 0) + { + if (BIO_tou_socket_should_retry(b->num, ret)) + BIO_set_retry_read(b); + } + } +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_socket_read() = %d\n", ret); +#endif + return(ret); + } + +static int tou_socket_write(BIO *b, const char *in, int inl) + { + int ret; +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_socket_write(%p,%p,%d)\n",b,in,inl); +#endif + + clear_tou_socket_error(b->num); + /* call tou library */ + ret=tou_write(b->num,in,inl); + BIO_clear_retry_flags(b); + if (ret <= 0) + { + if (BIO_tou_socket_should_retry(b->num,ret)) + { + BIO_set_retry_write(b); +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_socket_write() setting retry flag\n"); +#endif + } + } +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_socket_write() = %d\n", ret); +#endif + return(ret); + } + +static long tou_socket_ctrl(BIO *b, int cmd, long num, void *ptr) + { + long ret=1; + int *ip; +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_socket_ctrl(%p,%d,%ld)\n", b, cmd, num); +#endif + + switch (cmd) + { + case BIO_CTRL_RESET: + num=0; + case BIO_C_FILE_SEEK: + ret=0; + break; + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret=0; + break; + case BIO_C_SET_FD: + tou_socket_free(b); + b->num= *((int *)ptr); + b->shutdown=(int)num; + b->init=1; + break; + case BIO_C_GET_FD: + if (b->init) + { + ip=(int *)ptr; + if (ip != NULL) *ip=b->num; + ret=b->num; + } + else + ret= -1; + break; + case BIO_CTRL_GET_CLOSE: + ret=b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown=(int)num; + break; + case BIO_CTRL_PENDING: + ret = tou_maxread(b->num); +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_pending = %ld\n", ret); +#endif + break; + case BIO_CTRL_WPENDING: + ret = tou_maxwrite(b->num); +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_wpending = %ld\n", ret); +#endif + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret=1; + break; + default: + ret=0; + break; + } + return(ret); + } + +static int tou_socket_puts(BIO *bp, const char *str) + { + int n,ret; + +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "tou_socket_puts()\n"); +#endif + + n=strlen(str); + ret=tou_socket_write(bp,str,n); + return(ret); + } + +static int clear_tou_socket_error(int fd) +{ +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "clear_tou_socket_error()\n"); +#endif + return tou_clear_error(fd); +} + +static int get_last_tou_socket_error(int s) +{ +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "get_last_tou_socket_error()\n"); +#endif + return tou_errno(s); +} + +int BIO_tou_socket_should_retry(int s, int i) + { + int err; +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "BIO_tou_socket_should_retry()\n"); +#endif + + if ((i == 0) || (i == -1)) + { + err=get_last_tou_socket_error(s); + +#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ + if ((i == -1) && (err == 0)) + return(1); +#endif + + return(BIO_tou_socket_non_fatal_error(err)); + } + return(0); + } + +int BIO_tou_socket_non_fatal_error(int err) + { + switch (err) + { +#if defined(OPENSSL_SYS_WINDOWS) +# if defined(WSAEWOULDBLOCK) + case WSAEWOULDBLOCK: +# endif + +# if 0 /* This appears to always be an error */ +# if defined(WSAENOTCONN) + case WSAENOTCONN: +# endif +# endif +#endif + +#ifdef EWOULDBLOCK +# ifdef WSAEWOULDBLOCK +# if WSAEWOULDBLOCK != EWOULDBLOCK + case EWOULDBLOCK: +# endif +# else + case EWOULDBLOCK: +# endif +#endif + +#if defined(ENOTCONN) + case ENOTCONN: +#endif + +#ifdef EINTR + case EINTR: +#endif + +#ifdef EAGAIN +#if EWOULDBLOCK != EAGAIN + case EAGAIN: +# endif +#endif + +#ifdef EPROTO + case EPROTO: +#endif + +#ifdef EINPROGRESS + case EINPROGRESS: +#endif + +#ifdef EALREADY + case EALREADY: +#endif + + +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "BIO_tou_socket_non_fatal_error(%d) = 1\n", err); +#endif + return(1); + /* break; */ + default: + break; + } +#ifdef DEBUG_TOU_BIO + fprintf(stderr, "BIO_tou_socket_non_fatal_error(%d) = 0\n", err); +#endif + return(0); + } +#endif diff --git a/libretroshare/src/tcponudp/rsudpstack.h b/libretroshare/src/tcponudp/rsudpstack.h new file mode 100644 index 000000000..c6efad240 --- /dev/null +++ b/libretroshare/src/tcponudp/rsudpstack.h @@ -0,0 +1,72 @@ +#ifndef RS_UDP_STACK_RECEIVER_H +#define RS_UDP_STACK_RECEIVER_H + +/* + * tcponudp/rsudpstack.h + * + * libretroshare. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +/*******************************************************/ +#ifdef RS_USE_BITDHT + +#include "udp/udpstack.h" + + +#else + +class UdpStack +{ + public: + UdpStack(struct sockaddr_in &local) { return; } + + /* from pqiNetListener */ +virtual bool resetAddress(struct sockaddr_in &local) { return false; } + +}; + +#endif +/*******************************************************/ + +#include "pqi/pqimonitor.h" +#include + +class rsUdpStack: public UdpStack, public pqiNetListener +{ + public: + rsUdpStack(struct sockaddr_in &local) + :UdpStack(local) { return; } + + /* from pqiNetListener */ +virtual bool resetListener(struct sockaddr_in &local) + { + // The const_cast below is not so nice but without it, the compiler can't + // find the correct operator<<(). No idea why! + std::cerr << "rsUdpStack::resetListener(" << const_cast(local) << ")"; + std::cerr << std::endl; + return resetAddress(local); + } + +}; + +#endif diff --git a/libretroshare/src/tcponudp/tcppacket.cc b/libretroshare/src/tcponudp/tcppacket.cc new file mode 100644 index 000000000..23b007d5b --- /dev/null +++ b/libretroshare/src/tcponudp/tcppacket.cc @@ -0,0 +1,249 @@ +/* + * "$Id: tcppacket.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +#include "tcppacket.h" + +/* + * #include + */ + +#include "util/rsnet.h" /* for winsock.h -> htons etc */ + +#include +#include + +#include + +/* NOTE That these BIT #defines will only + * work on little endian machines.... + * due to the ntohs ... + */ + +/* flags 16bit is: + * + * || 0 1 2 3 | 4 5 6 7 || 8 9 | 10 11 12 13 14 15 || + * <- HLen -> <--- unused ---> <---- flags -------> + * URG PSH SYN + * ACK RST FIN + * + * + * So in little endian world. + * 0 & 1 -> unused... + * URG -> bit 2 => 0x0004 + * ACK -> bit 3 => 0x0008 + * PSH -> bit 4 => 0x0010 + * RST -> bit 5 => 0x0020 + * SYN -> bit 6 => 0x0040 + * FIN -> bit 7 => 0x0080 + * + * and second byte 0-3 -> hlen, 4-7 unused. + */ + +#define TCP_URG_BIT 0x0004 +#define TCP_ACK_BIT 0x0008 +#define TCP_PSH_BIT 0x0010 +#define TCP_RST_BIT 0x0020 +#define TCP_SYN_BIT 0x0040 +#define TCP_FIN_BIT 0x0080 + + +TcpPacket::TcpPacket(uint8 *ptr, int size) + :data(0), datasize(0), seqno(0), ackno(0), hlen_flags(0), + winsize(0), ts(0), retrans(0) + { + if (size > 0) + { + datasize = size; + data = (uint8 *) malloc(datasize); + memcpy(data, (void *) ptr, size); + } + return; + } + +TcpPacket::TcpPacket() /* likely control packet */ + :data(0), datasize(0), seqno(0), ackno(0), hlen_flags(0), + winsize(0), ts(0), retrans(0) + { + return; + } + + +TcpPacket::~TcpPacket() + { + if (data) + free(data); + } + + +int TcpPacket::writePacket(void *buf, int &size) +{ + if (size < TCP_PSEUDO_HDR_SIZE + datasize) + { + size = 0; + return -1; + } + + /* byte: 0 => uint16 srcport = 0 */ + *((uint16 *) &(((uint8 *) buf)[0])) = htons(0); + + /* byte: 2 => uint16 destport = 0 */ + *((uint16 *) &(((uint8 *) buf)[2])) = htons(0); + + /* byte: 4 => uint32 seqno */ + *((uint32 *) &(((uint8 *) buf)[4])) = htonl(seqno); + + /* byte: 8 => uint32 ackno */ + *((uint32 *) &(((uint8 *) buf)[8])) = htonl(ackno); + + /* byte: 12 => uint16 len + flags */ + *((uint16 *) &(((uint8 *) buf)[12])) = htons(hlen_flags); + + /* byte: 14 => uint16 winsize */ + *((uint16 *) &(((uint8 *) buf)[14])) = htons(winsize); + + /* byte: 16 => uint16 chksum */ + *((uint16 *) &(((uint8 *) buf)[16])) = htons(0); + + /* byte: 18 => uint16 urgptr */ + *((uint16 *) &(((uint8 *) buf)[18])) = htons(0); + + /* total 20 bytes */ + + /* now the data */ + memcpy((void *) &(((uint8 *) buf)[20]), data, datasize); + + return size = TCP_PSEUDO_HDR_SIZE + datasize; +} + + +int TcpPacket::readPacket(void *buf, int size) +{ + if (size < TCP_PSEUDO_HDR_SIZE) + { + std::cerr << "TcpPacket::readPacket() Failed Too Small!"; + std::cerr << std::endl; + return -1; + } + + /* byte: 0 => uint16 srcport = 0 ******************* + *((uint16 *) &(((uint8 *) buf)[0])) = htons(0); + ***********/ + + /* byte: 2 => uint16 destport = 0 ****************** + *((uint16 *) &(((uint8 *) buf)[2])) = htons(0); + ***********/ + + /* byte: 4 => uint32 seqno */ + seqno = ntohl( *((uint32 *) &(((uint8 *) buf)[4])) ); + + /* byte: 8 => uint32 ackno */ + ackno = ntohl( *((uint32 *) &(((uint8 *) buf)[8])) ); + + /* byte: 12 => uint16 len + flags */ + hlen_flags = ntohs( *((uint16 *) &(((uint8 *) buf)[12])) ); + + /* byte: 14 => uint16 winsize */ + winsize = ntohs( *((uint16 *) &(((uint8 *) buf)[14])) ); + + /* byte: 16 => uint16 chksum ************************* + *((uint16 *) &(((uint8 *) buf)[16])) = htons(0); + ***********/ + + /* byte: 18 => uint16 urgptr ************************* + *((uint16 *) &(((uint8 *) buf)[18])) = htons(0); + ***********/ + + /* total 20 bytes */ + + if (data) + { + free(data); + } + datasize = size - TCP_PSEUDO_HDR_SIZE; + data = (uint8 *) malloc(datasize); + + /* now the data */ + memcpy(data, (void *) &(((uint8 *) buf)[20]), datasize); + + return size; +} + + /* flags */ +bool TcpPacket::hasSyn() +{ + return (hlen_flags & TCP_SYN_BIT); +} + +bool TcpPacket::hasFin() +{ + return (hlen_flags & TCP_FIN_BIT); +} + +bool TcpPacket::hasAck() +{ + return (hlen_flags & TCP_ACK_BIT); +} + +bool TcpPacket::hasRst() +{ + return (hlen_flags & TCP_RST_BIT); +} + + +void TcpPacket::setSyn() +{ + hlen_flags |= TCP_SYN_BIT; +} + +void TcpPacket::setFin() +{ + hlen_flags |= TCP_FIN_BIT; +} + +void TcpPacket::setRst() +{ + hlen_flags |= TCP_RST_BIT; +} + +void TcpPacket::setAckFlag() +{ + hlen_flags |= TCP_ACK_BIT; +} + +void TcpPacket::setAck(uint32 val) +{ + setAckFlag(); + ackno = val; +} + +uint32 TcpPacket::getAck() +{ + return ackno; +} + + diff --git a/libretroshare/src/tcponudp/tcppacket.h b/libretroshare/src/tcponudp/tcppacket.h new file mode 100644 index 000000000..3b0fe4371 --- /dev/null +++ b/libretroshare/src/tcponudp/tcppacket.h @@ -0,0 +1,97 @@ +/* + * "$Id: tcppacket.h,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef TOU_TCP_PACKET_H +#define TOU_TCP_PACKET_H + +#include + + +typedef unsigned int uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; + +#define TCP_PSEUDO_HDR_SIZE 20 + +class TcpPacket +{ + public: + + uint8 *data; + int datasize; + + + /* ports aren't needed -> in udp + * uint16 srcport, destport + **************************/ + uint32 seqno, ackno; + uint16 hlen_flags; + uint16 winsize; + /* don't need these -> in udp + not supported + uint16 chksum, urgptr; + **************************/ + /* no options. + **************************/ + + + /* other variables */ + double ts; /* transmit time */ + uint16 retrans; /* retransmit counter */ + + TcpPacket(uint8 *ptr, int size); + TcpPacket(); /* likely control packet */ + ~TcpPacket(); + +int writePacket(void *buf, int &size); +int readPacket(void *buf, int size); + +void *getData(); +void *releaseData(); + +void *setData(void *data, int size); +int getDataSize(); + + /* flags */ +bool hasSyn(); +bool hasFin(); +bool hasAck(); +bool hasRst(); + +void setSyn(); +void setFin(); +void setRst(); +void setAckFlag(); + +void setAck(uint32 val); +uint32 getAck(); + + +}; + + +#endif + diff --git a/libretroshare/src/tcponudp/tcpstream.cc b/libretroshare/src/tcponudp/tcpstream.cc new file mode 100644 index 000000000..a545c8f47 --- /dev/null +++ b/libretroshare/src/tcponudp/tcpstream.cc @@ -0,0 +1,2553 @@ +/* + * "$Id: tcpstream.cc,v 1.11 2007-03-01 01:09:39 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include + +#include "tcpstream.h" +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Debugging for STATE change, and Startup SYNs */ +#include "util/rsdebug.h" +const int rstcpstreamzone = 28455; + + +/* + * #define DEBUG_TCP_STREAM 1 + */ + +/* + *#define DEBUG_TCP_STREAM_EXTRA 1 + */ + +/* + * #define TCP_NO_PARTIAL_READ 1 + */ + +#ifdef DEBUG_TCP_STREAM +int checkData(uint8 *data, int size, int idx); +int setupBinaryCheck(std::string fname); +#endif + +static const uint32 kMaxQueueSize = 100; +static const uint32 kMaxPktRetransmit = 20; +static const uint32 kMaxSynPktRetransmit = 1000; // up to 1000 (16 min?) startup +static const int TCP_STD_TTL = 64; +static const int TCP_DEFAULT_FIREWALL_TTL = 4; + +static const double RTT_ALPHA = 0.875; + +// platform independent fractional timestamp. +static double getCurrentTS(); + +TcpStream::TcpStream(UdpSubReceiver *lyr) + :inSize(0), outSizeRead(0), outSizeNet(0), + state(TCP_CLOSED), + inStreamActive(false), + outStreamActive(false), + outSeqno(0), outAcked(0), outWinSize(0), + inAckno(0), inWinSize(0), + maxWinSize(TCP_MAX_WIN), + keepAliveTimeout(TCP_ALIVE_TIMEOUT), + retransTimeout(TCP_RETRANS_TIMEOUT), + lastWriteTF(0),lastReadTF(0), + wcount(0), rcount(0), + errorState(0), + /* retranmission variables - init to large */ + rtt_est(TCP_RETRANS_TIMEOUT), + rtt_dev(0), + congestThreshold(TCP_MAX_WIN), + congestWinSize(MAX_SEG), + congestUpdate(0), + mTTL_period(0), + mTTL_start(0), + mTTL_end(0), + peerKnown(false), + udp(lyr) +{ + return; +} + +/* Stream Control! */ +int TcpStream::connect(const struct sockaddr_in &raddr, uint32_t conn_period) +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + setRemoteAddress(raddr); + + /* check state */ + if (state != TCP_CLOSED) + { + if (state == TCP_ESTABLISHED) + { + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return 0; + } + else if (state < TCP_ESTABLISHED) + { + errorState = EAGAIN; + } + else + { + // major issues! + errorState = EFAULT; + } + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return -1; + } + + /* setup Seqnos */ + outSeqno = genSequenceNo(); + initOurSeqno = outSeqno; + + outAcked = outSeqno; /* min - 1 expected */ + inWinSize = maxWinSize; + + congestThreshold = TCP_MAX_WIN; + congestWinSize = MAX_SEG; + congestUpdate = outAcked + congestWinSize; + + /* Init Connection */ + /* send syn packet */ + TcpPacket *pkt = new TcpPacket(); + pkt -> setSyn(); + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::connect() Send Init Pkt" << std::endl; +#endif + + + /* ********* SLOW START ************* + * As this is the only place where a syn + * is sent ..... we switch the ttl to 0, + * and increment it as we retransmit the packet.... + * This should help the firewalls along. + */ + + setTTL(1); + + mTTL_start = getCurrentTS(); + mTTL_period = conn_period; + mTTL_end = mTTL_start + mTTL_period; + + toSend(pkt); + /* change state */ + state = TCP_SYN_SENT; + errorState = EAGAIN; + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream STATE -> TCP_SYN_SENT" << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_SYN_SENT"; + out << " (Connect)"; + rslog(RSL_WARNING,rstcpstreamzone,out.str()); + } + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + + return -1; +} + + +int TcpStream::listenfor(const struct sockaddr_in &raddr) +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + setRemoteAddress(raddr); + + /* check state */ + if (state != TCP_CLOSED) + { + if (state == TCP_ESTABLISHED) + { + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return 0; + } + else if (state < TCP_ESTABLISHED) + { + errorState = EAGAIN; + } + else + { + // major issues! + errorState = EFAULT; + } + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return -1; + } + + errorState = EAGAIN; + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return -1; +} + + +/* Stream Control! */ +int TcpStream::close() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + cleanup(); + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return 0; +} + +int TcpStream::closeWrite() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + /* check state */ + /* will always close socket.... */ + /* if in TCP_ESTABLISHED.... + * -> to state: TCP_FIN_WAIT_1 + * and shutdown outward stream. + */ + + /* if in CLOSE_WAIT.... + * -> to state: TCP_LAST_ACK + * and shutdown outward stream. + * do this one first!. + */ + + outStreamActive = false; + + if (state == TCP_CLOSE_WAIT) + { + /* don't think we need to be + * graceful at this point... + * connection already closed by other end. + * XXX might fix later with scheme + * + * flag stream closed, and when outqueue + * emptied then fin will be sent. + */ + + /* do nothing */ + } + + if (state == TCP_ESTABLISHED) + { + /* fire off the damned thing. */ + /* by changing state */ + + /* again this is handled by internals + * the flag however indicates that + * no more data can be send, + * and once the queue empties + * the FIN will be sent. + */ + + } + if (state == TCP_CLOSED) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::close() Flag Set" << std::endl; +#endif + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return 0; + } + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::close() pending" << std::endl; +#endif + errorState = EAGAIN; + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return -1; +} + +bool TcpStream::isConnected() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + bool isConn = (state == TCP_ESTABLISHED); + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + + return isConn; +} + +int TcpStream::status(std::ostream &out) +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + int tmpstate = state; + + // can leave the timestamp here as time()... rough but okay. + out << "TcpStream::status @ (" << time(NULL) << ")" << std::endl; + out << "TcpStream::state = " << (int) state << std::endl; + out << std::endl; + out << "writeBuffer: " << inSize << " + 1500 * " << inQueue.size(); + out << " bytes Queued for transmission" << std::endl; + out << "readBuffer: " << outSizeRead << " + 1500 * "; + out << outQueue.size() << " + " << outSizeNet; + out << " incoming bytes waiting" << std::endl; + out << std::endl; + out << "inPkts: " << inPkt.size() << " packets waiting for processing"; + out << std::endl; + out << "outPkts: " << outPkt.size() << " packets waiting for acks"; + out << std::endl; + out << "us -> peer: nextSeqno: " << outSeqno << " lastAcked: " << outAcked; + out << " winsize: " << outWinSize; + out << std::endl; + out << "peer -> us: Expected SeqNo: " << inAckno; + out << " winsize: " << inWinSize; + out << std::endl; + out << std::endl; + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + + return tmpstate; +} + +int TcpStream::write_allowed() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + int ret = 1; + if (state == TCP_CLOSED) + { + errorState = EBADF; + ret = -1; + } + else if (state < TCP_ESTABLISHED) + { + errorState = EAGAIN; + ret = -1; + } + else if (!outStreamActive) + { + errorState = EBADF; + ret = -1; + } + + if (ret < 1) + { + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return ret; + } + + int maxwrite = (kMaxQueueSize - inQueue.size()) * MAX_SEG; + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return maxwrite; +} + +int TcpStream::read_pending() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + /* error should be detected next time */ + int maxread = int_read_pending(); + if (state == TCP_CLOSED) + { + errorState = EBADF; + maxread = -1; + } + else if (state < TCP_ESTABLISHED) + { + errorState = EAGAIN; + maxread = -1; + } + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + + return maxread; +} + +/* INTERNAL */ +int TcpStream::int_read_pending() +{ + return outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; +} + + + /* stream Interface */ +int TcpStream::write(char *dta, int size) /* write -> pkt -> net */ +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + int ret = 1; /* initial error checking */ + +#ifdef DEBUG_TCP_STREAM_EXTRA +static uint32 TMPtotalwrite = 0; +#endif + + if (state == TCP_CLOSED) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::write() Error TCP_CLOSED" << std::endl; +#endif + errorState = EBADF; + ret = -1; + } + else if (state < TCP_ESTABLISHED) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::write() Error TCP Not Established" << std::endl; +#endif + errorState = EAGAIN; + ret = -1; + } + else if (inQueue.size() > kMaxQueueSize) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::write() Error EAGAIN" << std::endl; +#endif + errorState = EAGAIN; + ret = -1; + } + else if (!outStreamActive) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::write() Error TCP_CLOSED" << std::endl; +#endif + errorState = EBADF; + ret = -1; + } + + if (ret < 1) /* check for initial error */ + { + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return ret; + } + + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::write() = Will Succeed " << size << std::endl; + std::cerr << "TcpStream::write() Write Start: " << TMPtotalwrite << std::endl; + std::cerr << printPktOffset(TMPtotalwrite, dta, size) << std::endl; + TMPtotalwrite += size; +#endif + + + if (size + inSize < MAX_SEG) + { +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::write() Add Itty Bit" << std::endl; + std::cerr << "TcpStream::write() inData: " << (void *) inData; + std::cerr << " inSize: " << inSize << " dta: " << (void *) dta; + std::cerr << " size: " << size << " dest: " << (void *) &(inData[inSize]); + std::cerr << std::endl; +#endif +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::write() = " << size << std::endl; +#endif + memcpy((void *) &(inData[inSize]), dta, size); + inSize += size; + //std::cerr << "Small Packet - write to net:" << std::endl; + //std::cerr << printPkt(dta, size) << std::endl; + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return size; + } + + /* otherwise must construct a dataBuffer. + */ + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::write() filling 1 dataBuffer" << std::endl; + std::cerr << "TcpStream::write() from inData(" << inSize << ")" << std::endl; + std::cerr << "TcpStream::write() + dta(" << MAX_SEG - inSize; + std::cerr << "/" << size << ")" << std::endl; +#endif + + /* first create 1. */ + dataBuffer *db = new dataBuffer; + memcpy((void *) db->data, (void *) inData, inSize); + + + int remSize = size; + memcpy((void *) &(db->data[inSize]), dta, MAX_SEG - inSize); + + inQueue.push_back(db); + remSize -= (MAX_SEG - inSize); + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::write() remaining " << remSize << " bytes to load" << std::endl; +#endif + + while(remSize >= MAX_SEG) + { +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::write() filling whole dataBuffer" << std::endl; + std::cerr << "TcpStream::write() from dta[" << size-remSize << "]" << std::endl; +#endif + db = new dataBuffer; + memcpy((void *) db->data, (void *) &(dta[size-remSize]), MAX_SEG); + + inQueue.push_back(db); + remSize -= MAX_SEG; + } + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::write() = " << size << std::endl; +#endif + + if (remSize > 0) + { + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::write() putting last bit in inData" << std::endl; + std::cerr << "TcpStream::write() from dta[" << size-remSize << "] size: "; + std::cerr << remSize << std::endl; +#endif + memcpy((void *) inData, (void *) &(dta[size-remSize]), remSize); + inSize = remSize; + } + else + { + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::write() Data fitted exactly in dataBuffer!" << std::endl; +#endif + inSize = 0; + } + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return size; +} + +int TcpStream::read(char *dta, int size) /* net -> pkt -> read */ +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + +#ifdef DEBUG_TCP_STREAM_EXTRA +static uint32 TMPtotalread = 0; +#endif + /* max available data is + * outDataRead + outQueue + outDataNet + */ + + int maxread = outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; + int ret = 1; /* used only for initial errors */ + + if (state == TCP_CLOSED) + { + errorState = EBADF; + ret = -1; + } + else if (state < TCP_ESTABLISHED) + { + errorState = EAGAIN; + ret = -1; + } + else if ((!inStreamActive) && (maxread == 0)) + { + // finished stream. + ret = 0; + } + else if (maxread == 0) + { + /* must wait for more data */ + errorState = EAGAIN; + ret = -1; + } + + if (ret < 1) /* if ret has been changed */ + { + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return ret; + } + + if (maxread < size) + { +#ifdef TCP_NO_PARTIAL_READ + if (inStreamActive) + { + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::read() No Partial Read! "; + std::cerr << "Can only supply " << maxread << " of "; + std::cerr << size; + std::cerr << std::endl; +#endif + errorState = EAGAIN; + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return -1; + } +#endif /* TCP_NO_PARTIAL_READ */ + size = maxread; + } + + /* if less than outDataRead size */ + if (((unsigned) (size) < outSizeRead) && (outSizeRead)) + { +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() Add Itty Bit" << std::endl; + std::cerr << "TcpStream::read() outSizeRead: " << outSizeRead; + std::cerr << " size: " << size << " remaining: " << outSizeRead - size; + std::cerr << std::endl; +#endif + memcpy(dta,(void *) outDataRead, size); + memmove((void *) outDataRead, + (void *) &(outDataRead[size]), outSizeRead - (size)); + outSizeRead -= size; + + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; + std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; + std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; +#endif + +#ifdef DEBUG_TCP_STREAM_EXTRA + checkData((uint8 *) dta, size, TMPtotalread); + TMPtotalread += size; +#endif + + /* can allow more in! - update inWinSize */ + UpdateInWinSize(); + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return size; + } + + /* move the whole of outDataRead. */ + if (outSizeRead) + { +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() Move All outSizeRead" << std::endl; + std::cerr << "TcpStream::read() outSizeRead: " << outSizeRead; + std::cerr << " size: " << size; + std::cerr << std::endl; +#endif + memcpy(dta,(void *) outDataRead, outSizeRead); + + } + + int remSize = size - outSizeRead; + outSizeRead = 0; + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() remaining size: " << remSize << std::endl; +#endif + + while((outQueue.size() > 0) && (remSize > 0)) + { + dataBuffer *db = outQueue.front(); + outQueue.pop_front(); /* remove */ + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() Taking Data from outQueue" << std::endl; +#endif + + /* load into outDataRead */ + if (remSize < MAX_SEG) + { +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() Partially using Segment" << std::endl; + std::cerr << "TcpStream::read() moving: " << remSize << " to dta @: " << size-remSize; + std::cerr << std::endl; + std::cerr << "TcpStream::read() rest to outDataRead: " << MAX_SEG - remSize; + std::cerr << std::endl; +#endif + memcpy((void *) &(dta[(size)-remSize]), (void *) db->data, remSize); + memcpy((void *) outDataRead, (void *) &(db->data[remSize]), MAX_SEG - remSize); + outSizeRead = MAX_SEG - remSize; + + delete db; + + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; + std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; + std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; +#endif + +#ifdef DEBUG_TCP_STREAM_EXTRA + checkData((uint8 *) dta, size, TMPtotalread); + TMPtotalread += size; +#endif + + /* can allow more in! - update inWinSize */ + UpdateInWinSize(); + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return size; + } +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() Move Whole Segment to dta @ " << size-remSize << std::endl; +#endif + + /* else copy whole segment */ + memcpy((void *) &(dta[(size)-remSize]), (void *) db->data, MAX_SEG); + remSize -= MAX_SEG; + delete db; + } + + /* assumes that outSizeNet >= remSize due to initial + * constraint + */ + if ((remSize > 0)) + { +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() Using up : " << remSize; + std::cerr << " last Bytes, leaving: " << outSizeNet - remSize << std::endl; +#endif + + + memcpy((void *) &(dta[(size)-remSize]),(void *) outDataNet, remSize); + outSizeNet -= remSize; + if (outSizeNet > 0) + { + /* move to the outDataRead */ + memcpy((void *) outDataRead,(void *) &(outDataNet[remSize]), outSizeNet); + outSizeRead = outSizeNet; + outSizeNet = 0; +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() moving last of outSizeNet to outSizeRead: " << outSizeRead; + std::cerr << std::endl; +#endif + + } + + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; + std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; + std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; +#endif + +#ifdef DEBUG_TCP_STREAM_EXTRA + checkData((uint8 *) dta, size, TMPtotalread); + TMPtotalread += size; +#endif + + /* can allow more in! - update inWinSize */ + UpdateInWinSize(); + + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return size; + } + +#ifdef DEBUG_TCP_STREAM_EXTRA + std::cerr << "TcpStream::read() = Succeeded " << size << std::endl; + std::cerr << "TcpStream::read() Read Start: " << TMPtotalread << std::endl; + std::cerr << printPktOffset(TMPtotalread, dta, size) << std::endl; +#endif + +#ifdef DEBUG_TCP_STREAM_EXTRA + checkData((uint8 *) dta, size, TMPtotalread); + TMPtotalread += size; +#endif + + /* can allow more in! - update inWinSize */ + UpdateInWinSize(); + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return size; +} + + + /* Callback from lower Layers */ +void TcpStream::recvPkt(void *data, int size) +{ +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::recvPkt()"; + std::cerr << std::endl; +#endif + + tcpMtx.lock(); /********** LOCK MUTEX *********/ + uint8 *input = (uint8 *) data; + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::recvPkt() Past Lock!"; + std::cerr << std::endl; +#endif + +#ifdef DEBUG_TCP_STREAM + if (state > TCP_SYN_RCVD) + { + int availRead = outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; + std::cerr << "TcpStream::recvPkt() CC: "; + std::cerr << " iWS: " << inWinSize; + std::cerr << " aRead: " << availRead; + std::cerr << " iAck: " << inAckno; + std::cerr << std::endl; + } + else + { + std::cerr << "TcpStream::recv() Not Connected"; + std::cerr << std::endl; + } +#endif + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::recv() ReadPkt(" << size << ")" << std::endl; + //std::cerr << printPkt(input, size); + //std::cerr << std::endl; +#endif + TcpPacket *pkt = new TcpPacket(); + if (0 < pkt -> readPacket(input, size)) + { + lastIncomingPkt = getCurrentTS(); + handleIncoming(pkt); + } + else + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::recv() Bad Packet Deleting!"; + std::cerr << std::endl; +#endif + delete pkt; + } + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return; +} + + +int TcpStream::tick() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + //std::cerr << "TcpStream::tick()" << std::endl; + recv_check(); /* recv is async */ + send(); + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + + return 1; +} + +bool TcpStream::getRemoteAddress(struct sockaddr_in &raddr) +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + if (peerKnown) + { + raddr = peeraddr; + } + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + + return peerKnown; +} + +uint8 TcpStream::TcpState() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + uint8 err = state; + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + + return err; +} + +int TcpStream::TcpErrorState() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + + int err = errorState; + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + + return err; +} + + + +/********************* SOME EXPOSED DEBUGGING FNS ******************/ + +static int ilevel = 100; + +bool TcpStream::widle() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + /* init */ + if (!lastWriteTF) + { + lastWriteTF = int_wbytes(); + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return false; + } + + if ((lastWriteTF == int_wbytes()) && (inSize + inQueue.size() == 0)) + { + wcount++; + if (wcount > ilevel) + { + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return true; + } + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return false; + } + wcount = 0; + lastWriteTF = int_wbytes(); + + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return false; +} + + +bool TcpStream::ridle() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + /* init */ + if (!lastReadTF) + { + lastReadTF = int_rbytes(); + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return false; + } + + if ((lastReadTF == int_rbytes()) && (outSizeRead + outQueue.size() + outSizeNet== 0)) + { + rcount++; + if (rcount > ilevel) + { + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return true; + } + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return false; + } + rcount = 0; + lastReadTF = int_rbytes(); + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return false; +} + +uint32 TcpStream::wbytes() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + uint32 wb = int_wbytes(); + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return wb; +} + +uint32 TcpStream::rbytes() +{ + tcpMtx.lock(); /********** LOCK MUTEX *********/ + uint32 rb = int_rbytes(); + tcpMtx.unlock(); /******** UNLOCK MUTEX *********/ + return rb; +} + +/********************* ALL BELOW HERE IS INTERNAL ****************** + ******************* AND ALWAYS PROTECTED BY A MUTEX ***************/ + +int TcpStream::recv_check() +{ + double cts = getCurrentTS(); // fractional seconds. + +#ifdef DEBUG_TCP_STREAM + if (state > TCP_SYN_RCVD) + { + int availRead = outSizeRead + outQueue.size() * MAX_SEG + outSizeNet; + std::cerr << "TcpStream::recv_check() CC: "; + std::cerr << " iWS: " << inWinSize; + std::cerr << " aRead: " << availRead; + std::cerr << " iAck: " << inAckno; + std::cerr << std::endl; + } + else + { + std::cerr << "TcpStream::recv_check() Not Connected"; + std::cerr << std::endl; + } +#endif + + // make sure we've rcvd something! + if ((state > TCP_SYN_RCVD) && + (cts - lastIncomingPkt > kNoPktTimeout)) + { + /* shut it all down */ + /* this period should be equivalent + * to the firewall timeouts ??? + * + * for max efficiency + */ + + { + std::ostringstream out; + out << "TcpStream::state => TCP_CLOSED"; + out << " (kNoPktTimeout)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + + outStreamActive = false; + inStreamActive = false; + state = TCP_CLOSED; + cleanup(); + } + return 1; +} + +int TcpStream::cleanup() +{ + // This shuts it all down! no matter what. + { + std::ostringstream out; + out << "TcpStream::cleanup() state = TCP_CLOSED"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + + outStreamActive = false; + inStreamActive = false; + state = TCP_CLOSED; + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream STATE -> TCP_CLOSED" << std::endl; +#endif + + //peerKnown = false; //??? NOT SURE -> for a rapid reconnetion this might be key?? + + /* reset TTL */ + setTTL(TCP_STD_TTL); + + // clear arrays. + inSize = 0; + while(inQueue.size() > 0) + { + dataBuffer *db = inQueue.front(); + inQueue.pop_front(); + delete db; + } + + while(outPkt.size() > 0) + { + TcpPacket *pkt = outPkt.front(); + outPkt.pop_front(); + delete pkt; + } + + + // clear arrays. + outSizeRead = 0; + outSizeNet = 0; + while(outQueue.size() > 0) + { + dataBuffer *db = outQueue.front(); + outQueue.pop_front(); + delete db; + } + + while(inPkt.size() > 0) + { + TcpPacket *pkt = inPkt.front(); + inPkt.pop_front(); + delete pkt; + } + return 1; +} + +int TcpStream::handleIncoming(TcpPacket *pkt) +{ +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::handleIncoming()" << std::endl; +#endif + switch(state) + { + case TCP_CLOSED: + case TCP_LISTEN: + /* if receive SYN + * -> respond SYN/ACK + * To State: SYN_RCVD + * + * else Discard. + */ + return incoming_Closed(pkt); + break; + case TCP_SYN_SENT: + /* if receive SYN + * -> respond SYN/ACK + * To State: SYN_RCVD + * + * if receive SYN+ACK + * -> respond ACK + * To State: TCP_ESTABLISHED + * + * else Discard. + */ + return incoming_SynSent(pkt); + break; + case TCP_SYN_RCVD: + /* if receive ACK + * To State: TCP_ESTABLISHED + */ + return incoming_SynRcvd(pkt); + break; + case TCP_ESTABLISHED: + /* if receive FIN + * -> respond ACK + * To State: TCP_CLOSE_WAIT + * else Discard. + */ + return incoming_Established(pkt); + break; + case TCP_FIN_WAIT_1: + /* state entered by close() call. + * if receive FIN + * -> respond ACK + * To State: TCP_CLOSING + * + * if receive ACK + * -> no response + * To State: TCP_FIN_WAIT_2 + * + * if receive FIN+ACK + * -> respond ACK + * To State: TCP_TIMED_WAIT + * + */ + return incoming_Established(pkt); + //return incoming_FinWait1(pkt); + break; + case TCP_FIN_WAIT_2: + /* if receive FIN + * -> respond ACK + * To State: TCP_TIMED_WAIT + */ + return incoming_Established(pkt); + //return incoming_FinWait2(pkt); + break; + case TCP_CLOSING: + /* if receive ACK + * To State: TCP_TIMED_WAIT + */ + /* all handled in Established */ + return incoming_Established(pkt); + //return incoming_Closing(pkt); + break; + case TCP_CLOSE_WAIT: + /* + * wait for our close to be called. + */ + /* all handled in Established */ + return incoming_Established(pkt); + //return incoming_CloseWait(pkt); + break; + case TCP_LAST_ACK: + /* entered by the local close() after sending FIN. + * if receive ACK + * To State: TCP_CLOSED + */ + /* all handled in Established */ + return incoming_Established(pkt); + /* + return incoming_LastAck(pkt); + */ + + break; + /* this is actually the only + * final state where packets not expected! + */ + case TCP_TIMED_WAIT: + /* State: TCP_TIMED_WAIT + * + * discard all -> both connections FINed + * timeout of this state. + * + */ + state = TCP_CLOSED; + // return incoming_TimedWait(pkt); + { + std::ostringstream out; + out << "TcpStream::state => TCP_CLOSED"; + out << " (recvd TCP_TIMED_WAIT?)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + break; + } + delete pkt; + return 1; +} + + +int TcpStream::incoming_Closed(TcpPacket *pkt) +{ + /* if receive SYN + * -> respond SYN/ACK + * To State: SYN_RCVD + * + * else Discard. + */ + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::incoming_Closed()" << std::endl; +#endif + if ((pkt -> hasSyn()) && (!pkt -> hasAck())) + { + /* Init Connection */ + + /* save seqno */ + initPeerSeqno = pkt -> seqno; + inAckno = initPeerSeqno + 1; + outWinSize = pkt -> winsize; + + + inWinSize = maxWinSize; + + /* we can get from SynSent as well, + * but only send one SYN packet + */ + + /* start packet */ + TcpPacket *rsp = new TcpPacket(); + + if (state == TCP_CLOSED) + { + outSeqno = genSequenceNo(); + initOurSeqno = outSeqno; + outAcked = outSeqno; /* min - 1 expected */ + + /* setup Congestion Charging */ + congestThreshold = TCP_MAX_WIN; + congestWinSize = MAX_SEG; + congestUpdate = outAcked + congestWinSize; + + rsp -> setSyn(); + } + + rsp -> setAck(inAckno); + /* seq + winsize set in toSend() */ + + /* as we have received something ... we can up the TTL */ + setTTL(TCP_STD_TTL); + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::incoming_Closed() Sending reply" << std::endl; + std::cerr << "SeqNo: " << rsp->seqno << " Ack: " << rsp->ackno; + std::cerr << std::endl; +#endif + + toSend(rsp); + /* change state */ + state = TCP_SYN_RCVD; + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream STATE -> TCP_SYN_RCVD" << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_SYN_RECVD"; + out << " (recvd SYN & !ACK)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + } + + delete pkt; + return 1; +} + + +int TcpStream::incoming_SynSent(TcpPacket *pkt) +{ + /* if receive SYN + * -> respond SYN/ACK + * To State: SYN_RCVD + * + * if receive SYN+ACK + * -> respond ACK + * To State: TCP_ESTABLISHED + * + * else Discard. + */ + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::incoming_SynSent()" << std::endl; +#endif + + if ((pkt -> hasSyn()) && (pkt -> hasAck())) + { + /* check stuff */ + if (pkt -> getAck() != outSeqno) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::incoming_SynSent() Bad Ack - Deleting " << std::endl; +#endif + /* bad ignore */ + delete pkt; + return -1; + } + + /* Complete Connection */ + + /* save seqno */ + initPeerSeqno = pkt -> seqno; + inAckno = initPeerSeqno + 1; + + outWinSize = pkt -> winsize; + + outAcked = pkt -> getAck(); + + /* before ACK, reset the TTL + * As they have sent something, and we have received + * through the firewall, set to STD. + */ + setTTL(TCP_STD_TTL); + + /* ack the Syn Packet */ + sendAck(); + + /* change state */ + state = TCP_ESTABLISHED; + outStreamActive = true; + inStreamActive = true; + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream STATE -> TCP_ESTABLISHED" << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_ESTABLISHED"; + out << " (recvd SUN & ACK)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + + delete pkt; + } + else /* same as if closed! (simultaneous open) */ + { + return incoming_Closed(pkt); + } + return 1; +} + + +int TcpStream::incoming_SynRcvd(TcpPacket *pkt) +{ + /* if receive ACK + * To State: TCP_ESTABLISHED + */ + if (pkt -> hasRst()) + { + /* trouble */ + state = TCP_CLOSED; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream STATE -> TCP_CLOSED" << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_CLOSED"; + out << " (recvd RST)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + delete pkt; + return 1; + } + + bool ackWithData = false; + + if (pkt -> hasAck()) + { + if (pkt -> hasSyn()) + { + /* has resent syn -> check it matches */ +#ifdef DEBUG_TCP_STREAM + std::cerr << "incoming_SynRcvd -> Pkt with ACK + SYN" << std::endl; +#endif + } + + /* check stuff */ + if (pkt -> getAck() != outSeqno) + { + /* bad ignore */ +#ifdef DEBUG_TCP_STREAM + std::cerr << "incoming_SynRcvd -> Ignoring Pkt with bad ACK" << std::endl; +#endif + delete pkt; + return -1; + } + + /* Complete Connection */ + + /* save seqno */ + if (pkt -> datasize > 0) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::incoming_SynRcvd() ACK with Data!" << std::endl; + std::cerr << "TcpStream::incoming_SynRcvd() Shoudn't recv ... unless initACK lost!" << std::endl; +#endif + // managed to trigger this under windows... + // perhaps the initial Ack was lost, + // believe we should just pass this packet + // directly to the incoming_Established... once + // the following has been done. + // and it should all work! + //exit(1); + ackWithData = true; + } + + inAckno = pkt -> seqno; /* + pkt -> datasize; */ + outWinSize = pkt -> winsize; + + outAcked = pkt -> getAck(); + + + /* As they have sent something, and we have received + * through the firewall, set to STD. + */ + setTTL(TCP_STD_TTL); + + /* change state */ + state = TCP_ESTABLISHED; + outStreamActive = true; + inStreamActive = true; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream STATE -> TCP_ESTABLISHED" << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_ESTABLISHED"; + out << " (have SYN, recvd ACK)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + + } + + if (ackWithData) + { + /* connection Established -> handle normally */ +#ifdef DEBUG_TCP_STREAM + std::cerr << "incoming_SynRcvd -> Handling Data with Ack Pkt!"; + std::cerr << std::endl; +#endif + incoming_Established(pkt); + } + else + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "incoming_SynRcvd -> Ignoring Pkt!" << std::endl; +#endif + /* else nothing */ + delete pkt; + } + return 1; +} + +int TcpStream::incoming_Established(TcpPacket *pkt) +{ + /* first handle the Ack ... + * this must be done before the queue, + * to keep the values as up-to-date as possible. + * + * must sanity check ..... + * make sure that the sequence number is within the correct range. + */ + + if ((!isOldSequence(pkt->seqno, inAckno)) && // seq >= inAckno + isOldSequence(pkt->seqno, inAckno + maxWinSize)) // seq < inAckno + maxWinSize. + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::incoming_Established() valid Packet Seqno."; + std::cerr << std::endl; +#endif + if (pkt->hasAck()) + { + outAcked = pkt->ackno; +#ifdef DEBUG_TCP_STREAM + std::cerr << "\tUpdating OutAcked to: " << outAcked; + std::cerr << std::endl; +#endif + } + + outWinSize = pkt->winsize; + +#ifdef DEBUG_TCP_STREAM + std::cerr << "\tUpdating OutWinSize to: " << outWinSize; + std::cerr << std::endl; +#endif + } + else + { + /* what we do! */ +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::incoming_Established() ERROR out-of-range Packet Seqno."; + std::cerr << std::endl; + std::cerr << "TcpStream::incoming_Established() Sending Ack to update Peer"; + std::cerr << std::endl; +#endif + + sendAck(); + } + + + /* add to queue */ + inPkt.push_back(pkt); + + if (inPkt.size() > kMaxQueueSize) + { + TcpPacket *pkt = inPkt.front(); + inPkt.pop_front(); + delete pkt; + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::incoming_Established() inPkt reached max size...Discarding Oldest Pkt"; + std::cerr << std::endl; +#endif + + } + + /* use as many packets as possible */ + return check_InPkts(); +} + +int TcpStream::check_InPkts() +{ + bool found = true; + TcpPacket *pkt; + std::list::iterator it; + while(found) + { + found = false; + for(it = inPkt.begin(); (!found) && (it != inPkt.end());) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "Checking expInAck: " << inAckno << " vs: " << (*it)->seqno << std::endl; +#endif + pkt = *it; + if ((*it)->seqno == inAckno) + { + found = true; + inPkt.erase(it); + + } + + /* see if we can discard it */ + /* if smaller seqno, and not wrapping around */ + else if (isOldSequence((*it)->seqno, inAckno)) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "Discarding Old Packet expAck: " << inAckno; + std::cerr << " seqno: " << (*it)->seqno << std::endl; +#endif + + /* discard */ + it = inPkt.erase(it); + delete pkt; + + } + else + { + it++; + } + } + if (found) + { + +#ifdef DEBUG_TCP_STREAM_EXTRA + if (pkt->datasize) + { + checkData(pkt->data, pkt->datasize, pkt->seqno-initPeerSeqno-1); + } +#endif + + /* update ack number - let it rollover */ + inAckno = pkt->seqno + pkt->datasize; + + /* XXX This shouldn't be here, as it prevents + * the Ack being used until the packet is. + * This means that a dropped packet will stop traffic in both + * directions.... + * + * Moved it to incoming_Established .... but extra + * check here to be sure! + */ + + if (pkt->hasAck()) + { + if (isOldSequence(outAcked, pkt->ackno)) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::check_inPkts() ERROR Ack Not Already Used!"; + std::cerr << std::endl; +#endif + outAcked = pkt->ackno; + outWinSize = pkt->winsize; + +#ifdef DEBUG_TCP_STREAM + std::cerr << "\tUpdating OutAcked to: " << outAcked; + std::cerr << std::endl; + std::cerr << "\tUpdating OutWinSize to: " << outWinSize; + std::cerr << std::endl; +#endif + + } + else + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::check_inPkts() GOOD Ack Already Used!"; + std::cerr << std::endl; +#endif + } + } + + /* push onto queue */ + + if (outSizeNet + pkt->datasize < MAX_SEG) + { + /* move onto outSizeNet */ + if (pkt->datasize) + { + memcpy((void *) &(outDataNet[outSizeNet]), pkt->data, pkt->datasize); + outSizeNet += pkt->datasize; + } + } + else + { + /* if it'll overflow the buffer. */ + dataBuffer *db = new dataBuffer(); + + /* move outDatNet -> buffer */ + memcpy((void *) db->data, (void *) outDataNet, outSizeNet); + + /* fill rest of space */ + int remSpace = MAX_SEG - outSizeNet; + memcpy((void *) &(db->data[outSizeNet]), (void *) pkt->data, remSpace); + + /* remove any remaining to outDataNet */ + outSizeNet = pkt->datasize - remSpace; + if (outSizeNet > 0) + { + memcpy((void *) outDataNet, (void *) &(pkt->data[remSpace]), outSizeNet); + } + + /* push packet onto queue */ + outQueue.push_back(db); + } + + /* can allow more in! - update inWinSize */ + UpdateInWinSize(); + + /* if pkt is FIN */ + /* these must be here -> at the end of the reliable stream */ + /* if the fin is set, ack it specially close stream */ + if (pkt->hasFin()) + { + /* send final ack */ + sendAck(); + + /* closedown stream */ + inStreamActive = false; + + if (state == TCP_ESTABLISHED) + { + state = TCP_CLOSE_WAIT; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::state = TCP_CLOSE_WAIT"; + std::cerr << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_CLOSE_WAIT"; + out << " (recvd FIN)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + } + else if (state == TCP_FIN_WAIT_1) + { + state = TCP_CLOSING; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::state = TCP_CLOSING"; + std::cerr << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_CLOSING"; + out << " (FIN_WAIT_1, recvd FIN)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + } + else if (state == TCP_FIN_WAIT_2) + { + state = TCP_TIMED_WAIT; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::state = TCP_TIMED_WAIT"; + std::cerr << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_TIMED_WAIT"; + out << " (FIN_WAIT_2, recvd FIN)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + cleanup(); + } + } + + /* if ack for our FIN */ + if ((pkt->hasAck()) && (!outStreamActive) + && (pkt->ackno == outSeqno)) + { + if (state == TCP_FIN_WAIT_1) + { + state = TCP_FIN_WAIT_2; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::state = TCP_FIN_WAIT_2"; + std::cerr << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_FIN_WAIT_2"; + out << " (FIN_WAIT_1, recvd ACK)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + } + else if (state == TCP_LAST_ACK) + { + state = TCP_CLOSED; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::state = TCP_CLOSED"; + std::cerr << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_CLOSED"; + out << " (LAST_ACK, recvd ACK)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + cleanup(); + } + else if (state == TCP_CLOSING) + { + state = TCP_TIMED_WAIT; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::state = TCP_TIMED_WAIT"; + std::cerr << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_TIMED_WAIT"; + out << " (TCP_CLOSING, recvd ACK)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + cleanup(); + } + } + + delete pkt; + + } /* end of found */ + } /* while(found) */ + return 1; +} + +/* This Fn should be called after each read, or recvd data (thats added to the buffer) + */ +int TcpStream::UpdateInWinSize() +{ + /* InWinSize = maxWinSze - QueuedData, + * actually we can allow a lot more to queue up... + * inWinSize = 65536, unless QueuedData > 65536. + * inWinSize = 2 * maxWinSize - QueuedData; + * + */ + + uint32 queuedData = int_read_pending(); + if (queuedData < maxWinSize) + { + inWinSize = maxWinSize; + } + else if (queuedData < 2 * maxWinSize) + { + inWinSize = 2 * maxWinSize - queuedData; + } + else + { + inWinSize = 0; + } + return inWinSize; +} + +int TcpStream::sendAck() +{ + /* simple -> toSend fills in ack/winsize + * and the rest is history + */ +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::sendAck()"; + std::cerr << std::endl; +#endif + + return toSend(new TcpPacket(), false); +} + +void TcpStream::setRemoteAddress(const struct sockaddr_in &raddr) +{ + peeraddr = raddr; + peerKnown = true; +} + + +int TcpStream::toSend(TcpPacket *pkt, bool retrans) +{ + int outPktSize = MAX_SEG + TCP_PSEUDO_HDR_SIZE; + char tmpOutPkt[outPktSize]; + + if (!peerKnown) + { + /* Major Error! */ +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::toSend() peerUnknown ERROR!!!"; + std::cerr << std::endl; +#endif + return 0; + } + + /* get accurate timestamp */ + double cts = getCurrentTS(); + + pkt -> winsize = inWinSize; + pkt -> seqno = outSeqno; + + /* increment seq no */ + if (pkt->datasize) + { +#ifdef DEBUG_TCP_STREAM_EXTRA + checkData(pkt->data, pkt->datasize, outSeqno-initOurSeqno-1); +#endif + outSeqno += pkt->datasize; + } + + if (pkt->hasSyn()) + { + /* should not have data! */ + if (pkt->datasize) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "SYN Packet shouldn't contain data!" << std::endl; +#endif + } + outSeqno++; + } + else + { + /* cannot auto Ack SynPackets */ + pkt -> setAck(inAckno); + } + + pkt -> winsize = inWinSize; + + /* store old info */ + lastSentAck = pkt -> ackno; + lastSentWinSize = pkt -> winsize; + keepAliveTimer = cts; + + pkt -> writePacket(tmpOutPkt, outPktSize); + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::toSend() Seqno: "; + std::cerr << pkt->seqno << " size: " << pkt->datasize; + std::cerr << " Ackno: "; + std::cerr << pkt->ackno << " winsize: " << pkt->winsize; + std::cerr << std::endl; + //std::cerr << printPkt(tmpOutPkt, outPktSize) << std::endl; +#endif + + udp -> sendPkt(tmpOutPkt, outPktSize, peeraddr, ttl); + + if (retrans) + { + /* restart timers */ + pkt -> ts = cts; + pkt -> retrans = 0; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::toSend() Adding to outPkt --> Seqno: "; + std::cerr << pkt->seqno << " size: " << pkt->datasize; + std::cerr << std::endl; +#endif + + outPkt.push_back(pkt); + } + else + { + delete pkt; + } + return 1; +} + + + +int TcpStream::retrans() +{ + int outPktSize = MAX_SEG + TCP_PSEUDO_HDR_SIZE; + char tmpOutPkt[outPktSize]; + bool updateCongestion = true; + + if (!peerKnown) + { + /* Major Error! */ +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::retrans() peerUnknown ERROR!!!"; + std::cerr << std::endl; +#endif + return 0; + } + + /* now retrans */ + double cts = getCurrentTS(); + std::list::iterator it; + for(it = outPkt.begin(); (it != outPkt.end()); it++) + { + outPktSize = MAX_SEG + TCP_PSEUDO_HDR_SIZE; + TcpPacket *pkt = (*it); + if (cts - pkt->ts > retransTimeout) + { + + /* retransmission -> adjust the congestWinSize and congestThreshold + * but only once per cycle + */ + if (updateCongestion) + { + congestThreshold = congestWinSize / 2; + congestWinSize = MAX_SEG; + congestUpdate = outAcked + congestWinSize; // point when we can up the winSize. + updateCongestion = false; + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::retrans() Adjusting Congestion Parameters: "; + std::cerr << std::endl; + std::cerr << "\tcongestWinSize: " << congestWinSize; + std::cerr << " congestThreshold: " << congestThreshold; + std::cerr << " congestUpdate: " << congestUpdate; + std::cerr << std::endl; +#endif + + } + + /* before we can retranmit, + * we need to check that its within the congestWinSize + * -> actually only checking that the start (seqno) is within window! + */ + + + if (isOldSequence(outAcked + congestWinSize, pkt->seqno)) + { + /* cannot send .... */ +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::retrans() Retranmission Delayed by CongestionWindow"; + std::cerr << std::endl; + + std::cerr << "\toutAcked: " << outAcked; + std::cerr << " CongestWinSize:" << congestWinSize; + std::cerr << std::endl; + + std::cerr << "\tAttempted Packet: Seqno: "; + std::cerr << pkt->seqno << " size: " << pkt->datasize; + std::cerr << " retrans: " << (int) pkt->retrans; + std::cerr << " timeout: " << retransTimeout; + std::cerr << std::endl; +#endif + /* as packets in order, can drop out of the fn now */ + return 0; + } + + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::retrans() Seqno: "; + std::cerr << pkt->seqno << " size: " << pkt->datasize; + std::cerr << " retrans: " << (int) pkt->retrans; + std::cerr << " timeout: " << retransTimeout; + std::cerr << std::endl; +#endif + + /* update ackno and winsize */ + if (!(pkt->hasSyn())) + { + pkt->setAck(inAckno); + lastSentAck = pkt -> ackno; + } + + pkt->winsize = inWinSize; + lastSentWinSize = pkt -> winsize; + + keepAliveTimer = cts; + + (*it) -> writePacket(tmpOutPkt, outPktSize); + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::retrans() ReSending Pkt" << std::endl; + std::cerr << "TcpStream::retrans Seqno: "; + std::cerr << (*it)->seqno << " size: " << (*it)->datasize; + std::cerr << " Ackno: "; + std::cerr << (*it)->ackno << " winsize: " << (*it)->winsize; + std::cerr << std::endl; + //std::cerr << printPkt(tmpOutPkt, outPktSize) << std::endl; +#endif + /* if its a syn packet ** thats been + * transmitting for a while, maybe + * we should increase the ttl. + */ + + if ((pkt->hasSyn()) && (getTTL() < TCP_STD_TTL)) + { + /* calculate a new TTL */ + if (mTTL_end > cts) + { + setTTL(TCP_DEFAULT_FIREWALL_TTL); + } + else + { + setTTL(getTTL() + 1); + } + + std::ostringstream out; + out << "TcpStream::retrans() Startup SYNs "; + out << "retrans count: " << pkt->retrans; + out << " New TTL: " << getTTL(); + + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + +#ifdef DEBUG_TCP_STREAM + std::cerr << out.str() << std::endl; +#endif + + + } + + /* catch excessive retransmits + * - Allow Syn case more.... + * - if not SYN or TTL has reached STD then timeout quickly. + */ + + if ((pkt->hasSyn() && (pkt->retrans > kMaxSynPktRetransmit)) || + (((!pkt->hasSyn()) || (TCP_STD_TTL == getTTL())) + && (pkt->retrans > kMaxPktRetransmit))) + { + /* too many attempts close stream */ +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::retrans() Too many Retransmission Attempts ("; + std::cerr << (int) pkt->retrans << ") for Pkt" << std::endl; + std::cerr << "TcpStream::retrans() Closing Socket Connection"; + std::cerr << std::endl; +#endif + + { + std::ostringstream out; + out << "TcpStream::state => TCP_CLOSED"; + out << " (Too Many Retransmits)"; + rslog(RSL_WARNING,rstcpstreamzone,out.str()); + } + + outStreamActive = false; + inStreamActive = false; + state = TCP_CLOSED; + cleanup(); + return 0; + } + + + udp -> sendPkt(tmpOutPkt, outPktSize, peeraddr, ttl); + + /* restart timers */ + (*it) -> ts = cts; + (*it) -> retrans++; + + /* finally - double the retransTimeout ... (Karn's Algorithm) + * this ensures we don't retransmit all the packets that + * following a dropped packet! + * + * but if we have lots of dropped this ain't going to help much! + * + * not doubling retransTimeout, that is can go manic and result + * in excessive timeouts, and no data flow. + */ + retransTimeout = 2.0 * (rtt_est + 4.0 * rtt_dev); +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::retrans() Doubling std retranTimeout to:"; + std::cerr << retransTimeout; + std::cerr << std::endl; +#endif + } + } + return 1; +} + + +void TcpStream::acknowledge() +{ + /* cleans up acknowledge packets */ + /* packets are pushed back in order */ + std::list::iterator it; + double cts = getCurrentTS(); + bool updateRTT = true; + + for(it = outPkt.begin(); (it != outPkt.end()) && + (isOldSequence((*it)->seqno, outAcked)); + it = outPkt.erase(it)) + { + TcpPacket *pkt = (*it); + + + /* adjust the congestWinSize and congestThreshold + * congestUpdate <= outAcked + * + ***/ + + if (!isOldSequence(outAcked, congestUpdate)) + { + if (congestWinSize < congestThreshold) + { + /* double it baby! */ + congestWinSize *= 2; + } + else + { + /* linear increase */ + congestWinSize += MAX_SEG; + } + + if (congestWinSize > maxWinSize) + { + congestWinSize = maxWinSize; + } + + congestUpdate = outAcked + congestWinSize; // point when we can up the winSize. + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::acknowledge() Adjusting Congestion Parameters: "; + std::cerr << std::endl; + std::cerr << "\tcongestWinSize: " << congestWinSize; + std::cerr << " congestThreshold: " << congestThreshold; + std::cerr << " congestUpdate: " << congestUpdate; + std::cerr << std::endl; +#endif + } + + + /* update the RoundTripTime, + * using Jacobson's values. + * RTT = a RTT + (1-a) M + * where + * RTT is RoundTripTime estimate. + * a = 7/8, + * M = time for ack. + * + * D = a D + (1 - a) | RTT - M | + * where + * D is approx Deviation. + * a,RTT & M are the same as above. + * + * Timeout = RTT + 4 * D. + * + * And Karn's Algorithm... + * which says + * (1) do not update RTT or D for retransmitted packets. + * + the ones that follow .... (the ones whos ack was + * delayed by the retranmission) + * (2) double timeout, when packets fail. (done in retrans). + */ + + if (pkt->retrans) + { + updateRTT = false; + } + + if (updateRTT) /* can use for RTT calc */ + { + double ack_time = cts - pkt->ts; + rtt_est = RTT_ALPHA * rtt_est + (1.0 - RTT_ALPHA) * ack_time; + rtt_dev = RTT_ALPHA * rtt_dev + (1.0 - RTT_ALPHA) * fabs(rtt_est - ack_time); + retransTimeout = rtt_est + 4.0 * rtt_dev; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::acknowledge() Updating RTT: "; + std::cerr << std::endl; + std::cerr << "\tAckTime: " << ack_time; + std::cerr << std::endl; + std::cerr << "\tRRT_est: " << rtt_est; + std::cerr << std::endl; + std::cerr << "\tRTT_dev: " << rtt_dev; + std::cerr << std::endl; + std::cerr << "\tTimeout: " << retransTimeout; + std::cerr << std::endl; +#endif + } + +#ifdef DEBUG_TCP_STREAM + else + { + std::cerr << "TcpStream::acknowledge() Not Updating RTT for retransmitted Pkt Sequence"; + std::cerr << std::endl; + } +#endif + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::acknowledge() Removing Seqno: "; + std::cerr << pkt->seqno << " size: " << pkt->datasize; + std::cerr << std::endl; +#endif + delete pkt; + } + + /* This is triggered if we have recieved acks for retransmitted packets.... + * In this case we want to reset the timeout, and remove the doubling. + * + * If we don't do this, and there have been more dropped packets, + * the the timeout gets continually doubled. which will virtually stop + * all communication. + * + * This will effectively trigger the retransmission of the next dropped packet. + */ + + if (!updateRTT) + { + retransTimeout = rtt_est + 4.0 * rtt_dev; + } + + return; +} + + +int TcpStream::send() +{ + /* handle network interface always */ + /* clean up as much as possible */ + acknowledge(); + /* send any old packets */ + retrans(); + + + if (state < TCP_ESTABLISHED) + { + return -1; + } + + /* get the inQueue, can send */ + + + /* determine exactly how much we can send */ + uint32 maxsend = congestWinSize; + uint32 inTransit; + + if (outWinSize < congestWinSize) + { + maxsend = outWinSize; + } + + if (outSeqno < outAcked) + { + inTransit = (TCP_MAX_SEQ - outAcked) + outSeqno; + } + else + { + inTransit = outSeqno - outAcked; + } + + if (maxsend > inTransit) + { + maxsend -= inTransit; + } + else + { + maxsend = 0; + } + +#ifdef DEBUG_TCP_STREAM + int availSend = inQueue.size() * MAX_SEG + inSize; + std::cerr << "TcpStream::send() CC: "; + std::cerr << "oWS: " << outWinSize; + std::cerr << " cWS: " << congestWinSize; + std::cerr << " | inT: " << inTransit; + std::cerr << " mSnd: " << maxsend; + std::cerr << " aSnd: " << availSend; + std::cerr << " | oSeq: " << outSeqno; + std::cerr << " oAck: " << outAcked; + std::cerr << " cUpd: " << congestUpdate; + std::cerr << std::endl; +#endif + + int sent = 0; + while((inQueue.size() > 0) && (maxsend >= MAX_SEG)) + { + dataBuffer *db = inQueue.front(); + inQueue.pop_front(); + + TcpPacket *pkt = new TcpPacket(db->data, MAX_SEG); +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::send() Segment ===> Seqno: "; + std::cerr << pkt->seqno << " size: " << pkt->datasize; + std::cerr << std::endl; +#endif + sent++; + maxsend -= MAX_SEG; + toSend(pkt); + delete db; + } + + /* if inqueue empty, and enough window space, send partial stuff */ + if ((!sent) && (inQueue.size() == 0) && (maxsend >= inSize) && (inSize)) + { + TcpPacket *pkt = new TcpPacket(inData, inSize); +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::send() Remaining ===>"; + std::cerr << std::endl; +#endif + inSize = 0; + sent++; + maxsend -= inSize; + toSend(pkt); + } + + /* if send nothing */ + bool needsAck = false; + + if (!sent) + { + double cts = getCurrentTS(); + /* if needs ack */ + if (isOldSequence(lastSentAck,inAckno)) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::send() Ack Triggered (Ackno)"; + std::cerr << std::endl; +#endif + needsAck = true; + } + + /* if needs window + * if added enough space for packet, or + * (this case is equivalent to persistence timer) + * haven't sent anything for a while, and the + * window size has drastically increased. + * */ + if (((lastSentWinSize < MAX_SEG) && (inWinSize > MAX_SEG)) || + ((cts - keepAliveTimer > retransTimeout * 4) && + (inWinSize > lastSentWinSize + 4 * MAX_SEG))) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::send() Ack Triggered (Window)"; + std::cerr << std::endl; +#endif + needsAck = true; + } + + /* if needs keepalive */ + if (cts - keepAliveTimer > keepAliveTimeout) + { +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::send() Ack Triggered (KAlive)"; + std::cerr << std::endl; +#endif + needsAck = true; + } + + + /* if end of stream -> switch mode -> send fin (with ack) */ + if ((!outStreamActive) && (inQueue.size() + inSize == 0) && + ((state == TCP_ESTABLISHED) || (state == TCP_CLOSE_WAIT))) + { + /* finish the stream */ + TcpPacket *pkt = new TcpPacket(); + pkt -> setFin(); + + needsAck = false; + toSend(pkt, false); + +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::send() Fin Triggered"; + std::cerr << std::endl; +#endif + + if (state == TCP_ESTABLISHED) + { + state = TCP_FIN_WAIT_1; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::state = TCP_FIN_WAIT_1"; + std::cerr << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_FIN_WAIT_1"; + out << " (End of Stream)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + } + else if (state == TCP_CLOSE_WAIT) + { + state = TCP_LAST_ACK; +#ifdef DEBUG_TCP_STREAM + std::cerr << "TcpStream::state = TCP_LAST_ACK"; + std::cerr << std::endl; +#endif + { + std::ostringstream out; + out << "TcpStream::state => TCP_LAST_ACK"; + out << " (CLOSE_WAIT, End of Stream)"; + rslog(RSL_WARNING, rstcpstreamzone, out.str()); + } + } + + } + + if (needsAck) + { + sendAck(); + } +#ifdef DEBUG_TCP_STREAM_EXTRA + else + { + std::cerr << "TcpStream::send() No Ack"; + std::cerr << std::endl; + } +#endif + } +#ifdef DEBUG_TCP_STREAM_EXTRA + else + { + std::cerr << "TcpStream::send() Stuff Sent"; + std::cerr << std::endl; + } +#endif + return 1; +} + + +uint32 TcpStream::genSequenceNo() +{ + //return 1000; // TCP_MAX_SEQ - 1000; //1000; //(rand() - 100000) + time(NULL) % 100000; + return (rand() - 100000) + time(NULL) % 100000; +} + + +bool TcpStream::isOldSequence(uint32 tst, uint32 curr) +{ + return ((int)((tst)-(curr)) < 0); + + std::cerr << "TcpStream::isOldSequence(): Case "; + /* if tst < curr */ + if ((int)((tst)-(curr)) < 0) + { + if (curr - tst < TCP_MAX_SEQ/2) /* diff less than half span -> old */ + { + std::cerr << "1T" << std::endl; + return true; + } + std::cerr << "2F" << std::endl; + return false; + } + else if ((tst - curr) > TCP_MAX_SEQ/2) + { + std::cerr << "3T: tst-curr:" << (tst-curr) << std::endl; + return true; + } + std::cerr << "4F: tst-curr:" << (tst-curr) << std::endl; + return false; +} + +#ifdef WINDOWS_SYS +#include +#include +#endif + +// Little fn to get current timestamp in an independent manner. +static double getCurrentTS() +{ + +#ifndef WINDOWS_SYS + struct timeval cts_tmp; + gettimeofday(&cts_tmp, NULL); + double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; +#else + struct _timeb timebuf; + _ftime( &timebuf); + double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; +#endif + return cts; +} + + + +uint32 TcpStream::int_wbytes() +{ + return outSeqno - initOurSeqno - 1; +} + +uint32 TcpStream::int_rbytes() +{ + return inAckno - initPeerSeqno - 1; +} + + + + +/********* Special debugging stuff *****/ + +#ifdef DEBUG_TCP_STREAM_EXTRA + +#include + +static FILE *bc_fd = 0; +int setupBinaryCheck(std::string fname) +{ + bc_fd = RsDirUtil::rs_fopen(fname.c_str(), "r"); + return 1; +} + +/* uses seq number to track position -> ensure no rollover */ +int checkData(uint8 *data, int size, int idx) +{ + if (bc_fd <= 0) + { + return -1; + } + std::cerr << "checkData(" << idx << "+" << size << ")"; + + int tmpsize = size; + uint8 tmpdata[tmpsize]; + if (-1 == fseek(bc_fd, idx, SEEK_SET)) + { + std::cerr << "Fseek Issues!" << std::endl; + exit(1); + return -1; + } + + if (1 != fread(tmpdata, tmpsize, 1, bc_fd)) + { + std::cerr << "Length Difference!" << std::endl; + exit(1); + return -1; + } + + for(int i = 0; i < size; i++) + { + if (data[i] != tmpdata[i]) + { + std::cerr << "Byte Difference!" << std::endl; + exit(1); + return -1; + } + } + std::cerr << "OK" << std::endl; + return 1; +} + +#endif + + diff --git a/libretroshare/src/tcponudp/tcpstream.h b/libretroshare/src/tcponudp/tcpstream.h new file mode 100644 index 000000000..29c627554 --- /dev/null +++ b/libretroshare/src/tcponudp/tcpstream.h @@ -0,0 +1,248 @@ +/* + * "$Id: tcpstream.h,v 1.5 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef TOU_TCP_PROTO_H +#define TOU_TCP_PROTO_H + + +/* so the packet will contain + * a tcp header + data. + * + * This is done simplistically for speed. + */ + +#include "tcppacket.h" +#include "udppeer.h" + +#define MAX_SEG 1500 +#define TCP_MAX_SEQ UINT_MAX +#define TCP_MAX_WIN 65500 +#define TCP_ALIVE_TIMEOUT 15 /* 15 sec ... < 20 sec UDP state limit on some firewalls */ +#define TCP_RETRANS_TIMEOUT 1 /* 1 sec (Initial value) */ +#define kNoPktTimeout 60 /* 1 min */ + + +#define TCP_CLOSED 0 +#define TCP_LISTEN 1 +#define TCP_SYN_SENT 2 +#define TCP_SYN_RCVD 3 +#define TCP_ESTABLISHED 4 +#define TCP_FIN_WAIT_1 5 +#define TCP_FIN_WAIT_2 6 +#define TCP_TIMED_WAIT 7 +#define TCP_CLOSING 8 +#define TCP_CLOSE_WAIT 9 +#define TCP_LAST_ACK 10 + +class dataBuffer +{ + public: + uint8 data[MAX_SEG]; +}; + +#include +#include + + +class TcpStream: public UdpPeer +{ + public: + /* Top-Level exposed */ + + TcpStream(UdpSubReceiver *udp); +virtual ~TcpStream() { return; } + + /* user interface */ +int status(std::ostream &out); +int connect(const struct sockaddr_in &raddr, uint32_t conn_period); +int listenfor(const struct sockaddr_in &raddr); +bool isConnected(); + + /* get tcp information */ +bool getRemoteAddress(struct sockaddr_in &raddr); +uint8 TcpState(); +int TcpErrorState(); + + /* stream Interface */ +int write(char *dta, int size); /* write -> pkt -> net */ +int read(char *dta, int size); /* net -> pkt -> read */ + + /* check ahead for allowed bytes */ +int write_allowed(); +int read_pending(); + +int closeWrite(); /* non-standard, but for clean exit */ +int close(); /* standard unix behaviour */ + +int tick(); /* check iface etc */ + + /* Callback Funcion from UDP Layers */ +virtual void recvPkt(void *data, int size); /* overloaded */ + + + + /* Exposed Data Counting */ +bool widle(); /* write idle */ +bool ridle(); /* read idle */ +uint32 wbytes(); +uint32 rbytes(); + + private: + + /* Internal Functions - use the Mutex (not reentrant) */ + /* Internal Functions - that don't need mutex protection */ + +uint32 genSequenceNo(); +bool isOldSequence(uint32 tst, uint32 curr); + + RsMutex tcpMtx; + + /* Internal Functions - only called inside mutex protection */ + +int cleanup(); + +/* incoming data */ +int recv_check(); +int handleIncoming(TcpPacket *pkt); +int incoming_Closed(TcpPacket *pkt); +int incoming_SynSent(TcpPacket *pkt); +int incoming_SynRcvd(TcpPacket *pkt); +int incoming_Established(TcpPacket *pkt); +int incoming_FinWait1(TcpPacket *pkt); +int incoming_FinWait2(TcpPacket *pkt); +int incoming_TimedWait(TcpPacket *pkt); +int incoming_Closing(TcpPacket *pkt); +int incoming_CloseWait(TcpPacket *pkt); +int incoming_LastAck(TcpPacket *pkt); +int check_InPkts(); +int UpdateInWinSize(); +int int_read_pending(); + +/* outgoing data */ +int send(); +int toSend(TcpPacket *pkt, bool retrans = true); +void acknowledge(); +int retrans(); +int sendAck(); +void setRemoteAddress(const struct sockaddr_in &raddr); + +int getTTL() { return ttl; } +void setTTL(int t) { ttl = t; } + +/* data counting */ +uint32 int_wbytes(); +uint32 int_rbytes(); + + /* Internal Data - must have mutex to access! */ + + /* data (in -> pkts) && (pkts -> out) */ + + /* for small amounts of data */ + uint8 inData[MAX_SEG]; + uint32 inSize; + + + /* two variable sized buffers required here */ + uint8 outDataRead[MAX_SEG]; + uint32 outSizeRead; + uint8 outDataNet[MAX_SEG]; + uint32 outSizeNet; + + /* get packed into here as size increases */ + std::deque inQueue, outQueue; + + /* packets waiting for acks */ + std::list inPkt, outPkt; + + + uint8 state; /* stream state */ + bool inStreamActive; + bool outStreamActive; + + uint32 outSeqno; /* next out */ + uint32 outAcked; /* other size has received */ + uint32 outWinSize; /* we allowed to send */ + + uint32 inAckno; /* next expected */ + uint32 inWinSize; /* allowing other to send */ + uint32 rrt; + + /* some (initially) consts */ + uint32 maxWinSize; + uint32 keepAliveTimeout; + double retransTimeout; + + /* some timers */ + double keepAliveTimer; + double lastIncomingPkt; + + /* tracking */ + uint32 lastSentAck; + uint32 lastSentWinSize; + uint32 initOurSeqno; + uint32 initPeerSeqno; + + uint32 lastWriteTF,lastReadTF; + uint16 wcount, rcount; + + int errorState; + + /* RoundTripTime estimations */ + double rtt_est; + double rtt_dev; + + /* congestion limits */ + uint32 congestThreshold; + uint32 congestWinSize; + uint32 congestUpdate; + + /* existing TTL for this stream (tweaked at startup) */ + int ttl; + + double mTTL_period; + double mTTL_start; + double mTTL_end; + + struct sockaddr_in peeraddr; + bool peerKnown; + + /* UdpSubReceiver (has own Mutex!) */ + UdpSubReceiver *udp; + +}; + + +/* for debugging */ + +#ifdef TCP_DEBUG_STREAM_EXTRA /* for extra checking! */ +int setupBinaryCheck(std::string fname); +#endif + + + +#endif + diff --git a/libretroshare/src/tcponudp/tou.cc b/libretroshare/src/tcponudp/tou.cc new file mode 100644 index 000000000..83443ac31 --- /dev/null +++ b/libretroshare/src/tcponudp/tou.cc @@ -0,0 +1,671 @@ +/* + * "$Id: tou.cc,v 1.7 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +#include "tou.h" + +static const int kInitStreamTable = 5; + +#include +#include + +#include "udp/udpstack.h" +#include "tcpstream.h" +#include +#include + +#include + +#define DEBUG_TOU_INTERFACE 1 + +struct TcpOnUdp_t +{ + int tou_fd; + int lasterrno; + TcpStream *tcp; + UdpSubReceiver *udpsr; + int udptype; + bool idle; +}; + +typedef struct TcpOnUdp_t TcpOnUdp; + +static std::vector tou_streams; + +static int tou_inited = 0; + + +#include "tcponudp/udppeer.h" +#include "tcponudp/udprelay.h" + +static UdpSubReceiver *udpSR[MAX_TOU_RECEIVERS] = {NULL}; +static uint32_t udpType[MAX_TOU_RECEIVERS] = {NULL}; +static uint32_t noUdpSR = 0; + +static int tou_tick_all(); + +/* tou_init + * + * Modified to accept a number of UdpSubRecievers! + * these can be linked to arbitary UdpStacks. + * (removed all UdpStack references here!) + * + * Unfortunately, the UdpSubReceivers have different initialisation for starting a connection. + * So the TOU interface has to accomodate this. + * + */ +/* tou_init - opens the udp port (universal bind) */ +int tou_init(void **in_udpsubrecvs, int *type, int number) +{ + UdpSubReceiver **usrArray = (UdpSubReceiver **) in_udpsubrecvs; + if (number > MAX_TOU_RECEIVERS) + { + std::cerr << "tou_init() Invalid number of receivers"; + std::cerr << std::endl; + return 0; + } + + if (tou_inited) + { + return 1; + } + + noUdpSR = number; + int i; + for(i = 0; i < noUdpSR; i++) + { + udpSR[i] = usrArray[i]; + udpType[i] = type[i]; + } + + tou_streams.resize(kInitStreamTable); + + tou_inited = 1; + return 1; +} + + +/* open - allocates a sockfd, and checks that the type is okay */ +int tou_socket(int recvIdx, int type, int /*protocol*/) +{ + if (!tou_inited) + { + return -1; + } + + if (recvIdx >= noUdpSR) + { + std::cerr << "tou_socket() ERROR recvIdx greater than #receivers"; + std::cerr << std::endl; + return -1; + } + + /* check that the index matches the type */ + UdpSubReceiver *recver = udpSR[recvIdx]; + uint32_t recverType = udpType[recvIdx]; + + if (recverType != type) + { + std::cerr << "tou_socket() ERROR type doesn't match expected type"; + std::cerr << std::endl; + return -1; + } + + for(unsigned int i = 1; i < tou_streams.size(); i++) + { + if (tou_streams[i] == NULL) + { + tou_streams[i] = new TcpOnUdp(); + tou_streams[i] -> tou_fd = i; + tou_streams[i] -> tcp = NULL; + tou_streams[i] -> udpsr = recver; + tou_streams[i] -> udptype = recverType; + return i; + } + } + + TcpOnUdp *tou = new TcpOnUdp(); + + tou_streams.push_back(tou); + + if (tou == tou_streams[tou_streams.size() -1]) + { + tou -> tou_fd = tou_streams.size() -1; + tou -> tcp = NULL; + tou -> udpsr = recver; + tou -> udptype = recverType; + return tou->tou_fd; + } + + tou -> lasterrno = EUSERS; + + return -1; +} + +/* bind - opens the udp port */ +int tou_bind(int sockfd, const struct sockaddr * /* my_addr */, socklen_t /* addrlen */ ) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + + /* this now always returns an error! */ + tous -> lasterrno = EADDRINUSE; + return -1; +} + +/* records peers address, and sends syn pkt + * the timeout is very slow initially - to give + * the peer a chance to startup + * + * - like a tcp/ip connection, the connect + * will return -1 EAGAIN, until connection complete. + * - always non blocking. + */ +int tou_connect(int sockfd, const struct sockaddr *serv_addr, + socklen_t addrlen, uint32_t conn_period) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + + + if (addrlen != sizeof(struct sockaddr_in)) + { + tous -> lasterrno = EINVAL; + return -1; + } + + /* enforce that the udptype is correct */ + if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER) + { + std::cerr << "tou_connect() ERROR connect method invalid for udptype"; + std::cerr << std::endl; + tous -> lasterrno = EINVAL; + return -1; + } + + +#ifdef TOU_DYNAMIC_CAST_CHECK + /* extra checking -> for testing purposes (dynamic cast) */ + UdpPeerReceiver *upr = dynamic_cast(tous->udpsr); + if (!upr) + { + std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver"; + std::cerr << std::endl; + tous -> lasterrno = EINVAL; + return -1; + } +#else + UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr); +#endif + + /* create a TCP stream to connect with. */ + if (!tous->tcp) + { + tous->tcp = new TcpStream(tous->udpsr); + upr->addUdpPeer(tous->tcp, + *((const struct sockaddr_in *) serv_addr)); + } + + tous->tcp->connect(*(const struct sockaddr_in *) serv_addr, conn_period); + tous->tcp->tick(); + tou_tick_all(); + if (tous->tcp->isConnected()) + { + return 0; + } + + tous -> lasterrno = EINPROGRESS; + return -1; +} + +/* is this ever used? should it be depreciated? */ +int tou_listenfor(int sockfd, const struct sockaddr *serv_addr, + socklen_t addrlen) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + + if (addrlen != sizeof(struct sockaddr_in)) + { + tous -> lasterrno = EINVAL; + return -1; + } + + /* enforce that the udptype is correct */ + if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER) + { + std::cerr << "tou_connect() ERROR connect method invalid for udptype"; + std::cerr << std::endl; + tous -> lasterrno = EINVAL; + return -1; + } + +#ifdef TOU_DYNAMIC_CAST_CHECK + /* extra checking -> for testing purposes (dynamic cast) */ + UdpPeerReceiver *upr = dynamic_cast(tous->udpsr); + if (!upr) + { + std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver"; + std::cerr << std::endl; + tous -> lasterrno = EINVAL; + return -1; + } +#else + UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr); +#endif + + /* create a TCP stream to connect with. */ + if (!tous->tcp) + { + tous->tcp = new TcpStream(tous->udpsr); + upr->addUdpPeer(tous->tcp, + *((const struct sockaddr_in *) serv_addr)); + } + + tous->tcp->listenfor(*((struct sockaddr_in *) serv_addr)); + tous->tcp->tick(); + tou_tick_all(); + + return 0; +} + +int tou_listen(int /* sockfd */ , int /* backlog */ ) +{ + tou_tick_all(); + return 1; +} + +/* + * This is the alternative RELAY connection. + * + * User needs to provide 3 ip addresses. + * These addresses should have been provided by the RELAY negogiation + * a) own ip:port + * b) proxy ip:port + * c) dest ip:port + * + * The reset of the startup is similar to other TOU connections. + * As this is likely to be run over an established UDP connection, + * there is little need for a big connection period. + * + * - like a tcp/ip connection, the connect + * will return -1 EAGAIN, until connection complete. + * - always non blocking. + */ +#define DEFAULT_RELAY_CONN_PERIOD 1 + +int tou_connect_via_relay(int sockfd, + const struct sockaddr_in *own_addr, + const struct sockaddr_in *proxy_addr, + const struct sockaddr_in *dest_addr) + +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + + /* enforce that the udptype is correct */ + if (tous -> udptype != TOU_RECEIVER_TYPE_UDPRELAY) + { + std::cerr << "tou_connect() ERROR connect method invalid for udptype"; + std::cerr << std::endl; + tous -> lasterrno = EINVAL; + return -1; + } + +#ifdef TOU_DYNAMIC_CAST_CHECK + /* extra checking -> for testing purposes (dynamic cast) */ + UdpRelayReceiver *urr = dynamic_cast(tous->udpsr); + if (!urr) + { + std::cerr << "tou_connect() ERROR cannot convert type to UdpRelayReceiver"; + std::cerr << std::endl; + tous -> lasterrno = EINVAL; + return -1; + } +#else + UdpRelayReceiver *urr = (UdpRelayReceiver *) (tous->udpsr); +#endif + + /* create a TCP stream to connect with. */ + if (!tous->tcp) + { + tous->tcp = new TcpStream(tous->udpsr); + + UdpRelayAddrSet addrSet(own_addr, dest_addr); + urr->addUdpPeer(tous->tcp, &addrSet, proxy_addr); + } + + /* We Point it at the Destination Address. + * The UdpRelayReceiver wraps and re-directs the packets to the proxy + */ + tous->tcp->connect(*dest_addr, DEFAULT_RELAY_CONN_PERIOD); + tous->tcp->tick(); + tou_tick_all(); + if (tous->tcp->isConnected()) + { + return 0; + } + + tous -> lasterrno = EINPROGRESS; + return -1; +} + + + /* slightly different - returns sockfd on connection */ +int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + + if (*addrlen != sizeof(struct sockaddr_in)) + { + tous -> lasterrno = EINVAL; + return -1; + } + + //tous->tcp->connect(); + tous->tcp->tick(); + tou_tick_all(); + if (tous->tcp->isConnected()) + { + // should get remote address + tous->tcp->getRemoteAddress(*((struct sockaddr_in *) addr)); + return sockfd; + } + + tous -> lasterrno = EAGAIN; + return -1; +} + + +int tou_connected(int sockfd) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + + tous->tcp->tick(); + tou_tick_all(); + + return (tous->tcp->TcpState() == 4); +} + + +/* standard stream read/write non-blocking of course + */ + +ssize_t tou_read(int sockfd, void *buf, size_t count) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + + tous->tcp->tick(); + tou_tick_all(); + + int err = tous->tcp->read((char *) buf, count); + if (err < 0) + { + tous->lasterrno = tous->tcp->TcpErrorState(); + return -1; + } + return err; +} + +ssize_t tou_write(int sockfd, const void *buf, size_t count) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + + + int err = tous->tcp->write((char *) buf, count); + if (err < 0) + { + tous->lasterrno = tous->tcp->TcpErrorState(); + tous->tcp->tick(); + tou_tick_all(); + return -1; + } + tous->tcp->tick(); + tou_tick_all(); + return err; +} + + /* check stream */ +int tou_maxread(int sockfd) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + tous->tcp->tick(); + tou_tick_all(); + + int ret = tous->tcp->read_pending(); + if (ret < 0) + { + tous->lasterrno = tous->tcp->TcpErrorState(); + return 0; // error detected next time. + } + return ret; +} + +int tou_maxwrite(int sockfd) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + tous->tcp->tick(); + tou_tick_all(); + + int ret = tous->tcp->write_allowed(); + if (ret < 0) + { + tous->lasterrno = tous->tcp->TcpErrorState(); + return 0; // error detected next time? + } + return ret; +} + + +/* close down the tcp over udp connection */ +int tou_close(int sockfd) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + + tou_tick_all(); + + if (tous->tcp) + { + tous->tcp->tick(); + + /* shut it down */ + tous->tcp->close(); + + /* now we need to work out which type of receiver we have */ +#ifdef TOU_DYNAMIC_CAST_CHECK + /* extra checking -> for testing purposes (dynamic cast) */ + UdpRelayReceiver *urr = dynamic_cast(tous->udpsr); + UdpPeerReceiver *upr = dynamic_cast(tous->udpsr); + if (urr) + { + urr->removeUdpPeer(tous->tcp); + } + else if (upr) + { + upr->removeUdpPeer(tous->tcp); + } + else + { + /* error */ + std::cerr << "tou_close() ERROR unknown udptype"; + std::cerr << std::endl; + tous -> lasterrno = EINVAL; + } +#else + if (tous -> udptype == TOU_RECEIVER_TYPE_UDPRELAY) + { + UdpRelayReceiver *urr = (UdpRelayReceiver *) (tous->udpsr); + urr->removeUdpPeer(tous->tcp); + } + else if (tous -> udptype == TOU_RECEIVER_TYPE_UDPPEER) + { + UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr); + upr->removeUdpPeer(tous->tcp); + } + else + { + /* error */ + std::cerr << "tou_close() ERROR unknown udptype"; + std::cerr << std::endl; + tous -> lasterrno = EINVAL; + } + +#endif + + delete tous->tcp; + + } + + delete tous; + tou_streams[sockfd] = NULL; + return 1; +} + +/* get an error number */ +int tou_errno(int sockfd) +{ + if (tou_streams[sockfd] == NULL) + { + return ENOTSOCK; + } + TcpOnUdp *tous = tou_streams[sockfd]; + return tous->lasterrno; +} + +int tou_clear_error(int sockfd) +{ + if (tou_streams[sockfd] == NULL) + { + return -1; + } + TcpOnUdp *tous = tou_streams[sockfd]; + tous->lasterrno = 0; + return 0; +} + +/* unfortuately the library needs to be ticked. (not running a thread) + * you can put it in a thread! + */ + +/* + * Some helper functions for stuff. + * + */ + +static int tou_passall(); +static int tou_active_rw(); + +static int nextActiveCycle; +static int nextIdleCheck; +static const int kActiveCycleStep = 1; +static const int kIdleCheckStep = 5; + +static int tou_tick_all() +{ + tou_passall(); + return 1; + + /* check timer */ + int ts = time(NULL); + if (ts > nextActiveCycle) + { + tou_active_rw(); + nextActiveCycle += kActiveCycleStep; + } + if (ts > nextIdleCheck) + { + tou_passall(); + nextIdleCheck += kIdleCheckStep; + } + return 0; +} + + +static int tou_passall() +{ + /* iterate through all and clean up old sockets. + * check if idle are still idle. + */ + std::vector::iterator it; + for(it = tou_streams.begin(); it != tou_streams.end(); it++) + { + if ((*it) && ((*it)->tcp)) + { + (*it)->tcp->tick(); + } + } + return 1; +} + +static int tou_active_rw() +{ + /* iterate through actives and tick + */ + return 1; +} + + diff --git a/libretroshare/src/tcponudp/tou.h b/libretroshare/src/tcponudp/tou.h new file mode 100644 index 000000000..905c7387b --- /dev/null +++ b/libretroshare/src/tcponudp/tou.h @@ -0,0 +1,144 @@ +/* + * "$Id: tou.h,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#ifndef TOU_C_HEADER_H +#define TOU_C_HEADER_H + + +/* get OS-specific definitions for: + * struct sockaddr, socklen_t, ssize_t + */ + +#ifndef WINDOWS_SYS + + #include + #include + #include + +#else + #include "util/rswin.h" + #include + #include + #include + #include +// #include + typedef int socklen_t; +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* standard C interface (as Unix-like as possible) + * for the tou (Tcp On Udp) library + */ + /* + * Init: + * The TOU library no longer references any UdpStack items. + * instead, two arrays should be passed to the init function. + * int tou_init( (void **) UdpSubReceiver **udpRecvers, int *udpType, int nUdps); + * + * The UdpSubReceivers should be derived classes, with corresponding types: + * UdpPeerReceiver TOU_RECEIVER_TYPE_UDPPEER + * UdpRelayReceiver TOU_RECEIVER_TYPE_UDPRELAY + * + */ + +#define MAX_TOU_RECEIVERS 16 + +#define TOU_RECEIVER_TYPE_NONE 0x0000 +#define TOU_RECEIVER_TYPE_UDPPEER 0x0001 +#define TOU_RECEIVER_TYPE_UDPRELAY 0x0002 + +// hack to avoid classes in C code. (MacOSX complaining) +int tou_init(void **udpSubRecvs, int *udpTypes, int nUdps); + + /* Connections are as similar to UNIX as possible + * (1) create a socket: tou_socket() this reserves a socket id. + * (2) connect: active: tou_connect() or passive: tou_listenfor(). + * (3) use as a normal socket. + * + * connect() now has a conn_period parameter - this is the + * estimate (in seconds) of how slowly the connection should proceed. + * + * tou_bind() is not valid. tou_init performs this role. + * tou_listen() is not valid. (must listen for a specific address) use tou_listenfor() instead. + * tou_accept() can still be used. + * + ****** THE ABOVE IS BECOMING LESS TRUE ******** + * + * I have now added Multiple type of TOU Connections (Proxy, Relay), + * and multiple UDP Receivers (meaning you can use different ports too). + * + * The UDP receivers must be specified at startup (new tou_init()) + * and the Receiver, and Type of connection must be specified when you + * open the socket. + * + * The parameters to tou_socket, therefore mean something! + * some extra checking has been put in to try and catch bad usage. + */ + + /* creation/connections */ +int tou_socket(int domain, int type, int protocol); +int tou_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen); /* null op now */ +int tou_listen(int sockfd, int backlog); /* null op now */ +int tou_connect(int sockfd, const struct sockaddr *serv_addr, + socklen_t addrlen, uint32_t conn_period); +int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); + + /* for relay connections */ +int tou_connect_via_relay(int sockfd, + const struct sockaddr_in *own_addr, + const struct sockaddr_in *proxy_addr, + const struct sockaddr_in *dest_addr); + +/* non-standard bonuses */ +int tou_connected(int sockfd); +int tou_listenfor(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); + + + + /* UNIX interface: minimum for the SSL BIO interface */ +ssize_t tou_read(int sockfd, void *buf, size_t count); +ssize_t tou_write(int sockfd, const void *buf, size_t count); +int tou_close(int sockfd); + + /* non-standard */ +int tou_errno(int sockfd); +int tou_clear_error(int sockfd); + + /* check stream */ +int tou_maxread(int sockfd); +int tou_maxwrite(int sockfd); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/libretroshare/src/tcponudp/udppeer.cc b/libretroshare/src/tcponudp/udppeer.cc new file mode 100644 index 000000000..4f532324a --- /dev/null +++ b/libretroshare/src/tcponudp/udppeer.cc @@ -0,0 +1,144 @@ +/* + * tcponudp/udppeer.cc + * + * libretroshare. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "udppeer.h" +#include + +/* + * #define DEBUG_UDP_PEER 1 + */ + + +UdpPeerReceiver::UdpPeerReceiver(UdpPublisher *pub) + :UdpSubReceiver(pub) +{ + return; +} + +/* higher level interface */ +int UdpPeerReceiver::recvPkt(void *data, int size, struct sockaddr_in &from) +{ + /* print packet information */ +#ifdef DEBUG_UDP_PEER + std::cerr << "UdpPeerReceiver::recvPkt(" << size << ") from: " << from; + std::cerr << std::endl; +#endif + + RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ + + /* look for a peer */ + std::map::iterator it; + it = streams.find(from); + + if (it == streams.end()) + { + /* peer unknown */ +#ifdef DEBUG_UDP_PEER + std::cerr << "UdpPeerReceiver::recvPkt() Peer Unknown!"; + std::cerr << std::endl; +#endif + return 0; + } + else + { + /* forward to them */ +#ifdef DEBUG_UDP_PEER + std::cerr << "UdpPeerReceiver::recvPkt() Sending to UdpPeer: "; + std::cerr << it->first; + std::cerr << std::endl; +#endif + (it->second)->recvPkt(data, size); + return 1; + } + /* done */ +} + + +int UdpPeerReceiver::status(std::ostream &out) +{ + RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ + + out << "UdpPeerReceiver::status()" << std::endl; + out << "UdpPeerReceiver::peers:" << std::endl; + std::map::iterator it; + for(it = streams.begin(); it != streams.end(); it++) + { + out << "\t" << it->first << std::endl; + } + out << std::endl; + + return 1; +} + + /* add a TCPonUDP stream */ +int UdpPeerReceiver::addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr) +{ + RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ + + + /* check for duplicate */ + std::map::iterator it; + it = streams.find(raddr); + bool ok = (it == streams.end()); + if (!ok) + { +#ifdef DEBUG_UDP_PEER + std::cerr << "UdpPeerReceiver::addUdpPeer() Peer already exists!" << std::endl; + std::cerr << "UdpPeerReceiver::addUdpPeer() ERROR" << std::endl; +#endif + } + else + { + streams[raddr] = peer; + } + + return ok; +} + +int UdpPeerReceiver::removeUdpPeer(UdpPeer *peer) +{ + RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/ + + /* check for duplicate */ + std::map::iterator it; + for(it = streams.begin(); it != streams.end(); it++) + { + if (it->second == peer) + { +#ifdef DEBUG_UDP_PEER + std::cerr << "UdpPeerReceiver::removeUdpPeer() SUCCESS" << std::endl; +#endif + streams.erase(it); + return 1; + } + } + +#ifdef DEBUG_UDP_PEER + std::cerr << "UdpPeerReceiver::removeUdpPeer() ERROR" << std::endl; +#endif + return 0; +} + + diff --git a/libretroshare/src/tcponudp/udppeer.h b/libretroshare/src/tcponudp/udppeer.h new file mode 100644 index 000000000..f25d1cffc --- /dev/null +++ b/libretroshare/src/tcponudp/udppeer.h @@ -0,0 +1,74 @@ +#ifndef RS_UDP_PEER_RECV_H +#define RS_UDP_PEER_RECV_H + +/* + * tcponudp/udppeer.h + * + * libretroshare. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef WINDOWS_SYS +#include +#endif + +#include "util/rsthreads.h" + +#include +#include +#include + +#include "tcponudp/rsudpstack.h" + +class UdpPeer +{ + public: +virtual ~UdpPeer() { return; } +virtual void recvPkt(void *data, int size) = 0; +}; + + +class UdpPeerReceiver: public UdpSubReceiver +{ + public: + + UdpPeerReceiver(UdpPublisher *pub); +virtual ~UdpPeerReceiver() { return; } + + /* add a TCPonUDP stream */ +int addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr); +int removeUdpPeer(UdpPeer *peer); + + /* callback for recved data (overloaded from UdpReceiver) */ +virtual int recvPkt(void *data, int size, struct sockaddr_in &from); + +int status(std::ostream &out); + + private: + + RsMutex peerMtx; /* for all class data (below) */ + + std::map streams; + +}; + + +#endif diff --git a/libretroshare/src/tcponudp/udprelay.cc b/libretroshare/src/tcponudp/udprelay.cc new file mode 100644 index 000000000..27c53ed4f --- /dev/null +++ b/libretroshare/src/tcponudp/udprelay.cc @@ -0,0 +1,868 @@ +/* + * tcponudp/udprelay.cc + * + * libretroshare. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "udprelay.h" +#include + +/* + * #define DEBUG_UDP_RELAY 1 + */ + +//#define DEBUG_UDP_RELAY 1 + + +#ifdef DEBUG_UDP_RELAY +// DEBUG FUNCTION +#include +#include +int displayUdpRelayPacketHeader(const void *data, const int size); +#endif + +/****************** UDP RELAY STUFF **********/ + +#define MAX_RELAY_UDP_PACKET_SIZE 1024 + +UdpRelayReceiver::UdpRelayReceiver(UdpPublisher *pub) + :UdpSubReceiver(pub) +{ + mClassLimit.resize(UDP_RELAY_NUM_CLASS); + mClassCount.resize(UDP_RELAY_NUM_CLASS); + + setRelayTotal(UDP_RELAY_DEFAULT_COUNT_ALL); + + for(int i = 0; i < UDP_RELAY_NUM_CLASS; i++) + { + mClassCount[i] = 0; + } + + /* only allocate this space once */ + mTmpSendPkt = malloc(MAX_RELAY_UDP_PACKET_SIZE); + mTmpSendSize = MAX_RELAY_UDP_PACKET_SIZE; + + return; +} + +UdpRelayReceiver::~UdpRelayReceiver() +{ + free(mTmpSendPkt); +} + + +int UdpRelayReceiver::addUdpPeer(UdpPeer *peer, UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr) +{ + struct sockaddr_in realPeerAddr = endPoints->mDestAddr; + { + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* check for duplicate */ + std::map::iterator it; + it = mStreams.find(realPeerAddr); + bool ok = (it == mStreams.end()); + if (!ok) + { + #ifdef DEBUG_UDP_RELAY + std::cerr << "UdpPeerReceiver::addUdpPeer() ERROR Peer already exists!" << std::endl; + #endif + return 0; + } + + /* setup a peer */ + UdpRelayEnd ure(endPoints, proxyaddr); + + mStreams[realPeerAddr] = ure; + } + + { + RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ + + +#ifdef DEBUG_UDP_RELAY + std::cerr << "UdpPeerReceiver::addUdpPeer() Just installing UdpPeer!" << std::endl; +#endif + + /* just overwrite */ + mPeers[realPeerAddr] = peer; + } + + return 1; +} + + +int UdpRelayReceiver::removeUdpPeer(UdpPeer *peer) +{ + bool found = false; + struct sockaddr_in realPeerAddr; + + /* cleanup UdpPeer, and get reference for data */ + { + RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ + + std::map::iterator it; + for(it = mPeers.begin(); it != mPeers.end(); it++) + { + if (it->second == peer) + { + mPeers.erase(it); + found = true; + realPeerAddr = it->first; + + break; + } + } + } + + if (!found) + { + return 0; + } + + /* now we cleanup the associated data */ + { + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + std::map::iterator it; + it = mStreams.find(realPeerAddr); + if (it != mStreams.end()) + { + mStreams.erase(it); + } + else + { + /* ERROR */ + } + } + return 1; +} + +int UdpRelayReceiver::getRelayEnds(std::list &relayEnds) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + std::map::iterator rit; + + for(rit = mStreams.begin(); rit != mStreams.end(); rit++) + { + relayEnds.push_back(rit->second); + } + return 1; + + +} + +int UdpRelayReceiver::getRelayProxies(std::list &relayProxies) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + std::map::iterator rit; + + for(rit = mRelays.begin(); rit != mRelays.end(); rit++) + { + relayProxies.push_back(rit->second); + } + return 1; +} + +#define RELAY_MAX_BANDWIDTH 1000 +#define RELAY_TIMEOUT 30 + + +int UdpRelayReceiver::checkRelays() +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* iterate through the Relays */ + + std::cerr << "UdpRelayReceiver::checkRelays()"; + std::cerr << std::endl; + + std::list eraseList; + std::map::iterator rit; + time_t now = time(NULL); + + for(rit = mRelays.begin(); rit != mRelays.end(); rit++) + { + /* calc bandwidth */ + rit->second.mBandwidth = rit->second.mDataSize / (float) (now - rit->second.mLastBandwidthTS); + rit->second.mDataSize = 0; + rit->second.mLastBandwidthTS = now; + + std::cerr << "UdpRelayReceiver::checkRelays()"; + std::cerr << "Relay: " << rit->first; + std::cerr << " using bandwidth: " << rit->second.mBandwidth; + std::cerr << std::endl; + + if (rit->second.mBandwidth > RELAY_MAX_BANDWIDTH) + { + std::cerr << "UdpRelayReceiver::checkRelays()"; + std::cerr << "Dropping Relay due to excessive Bandwidth: " << rit->first; + std::cerr << std::endl; + + /* if exceeding bandwidth -> drop */ + eraseList.push_back(rit->first); + } + else if (now - rit->second.mLastTS > RELAY_TIMEOUT) + { + /* if haven't transmitted for ages -> drop */ + std::cerr << "UdpRelayReceiver::checkRelays()"; + std::cerr << "Dropping Relay due to Timeout: " << rit->first; + std::cerr << std::endl; + eraseList.push_back(rit->first); + } + } + + std::list::iterator it; + for(it = eraseList.begin(); it != eraseList.end(); it++) + { + removeUdpRelay_relayLocked(&(*it)); + } + return 1; +} + + +int UdpRelayReceiver::removeUdpRelay(UdpRelayAddrSet *addrSet) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + return removeUdpRelay_relayLocked(addrSet); +} + + +int UdpRelayReceiver::addUdpRelay(UdpRelayAddrSet *addrSet, int relayClass) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* check for duplicate */ + std::map::iterator rit = mRelays.find(*addrSet); + int ok = (rit == mRelays.end()); + if (!ok) + { +//#ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::addUdpRelay() ERROR Peer already exists!" << std::endl; +//#endif + return 0; + } + + /* will install if there is space! */ + if (installRelayClass_relayLocked(relayClass)) + { +//#ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::addUdpRelay() adding Relay" << std::endl; +//#endif + /* create UdpRelay */ + UdpRelayProxy udpRelay(addrSet, relayClass); + UdpRelayAddrSet alt = addrSet->flippedSet(); + UdpRelayProxy altUdpRelay(&alt, relayClass); + + /* must install two (A, B) & (B, A) */ + mRelays[*addrSet] = udpRelay; + mRelays[alt] = altUdpRelay; + + return 1; + } + +//#ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::addUdpRelay() WARNING Too many Relays!" << std::endl; +//#endif + return 0; +} + + + +int UdpRelayReceiver::removeUdpRelay_relayLocked(UdpRelayAddrSet *addrSet) +{ + /* find in Relay list */ + std::map::iterator rit = mRelays.find(*addrSet); + if (rit == mRelays.end()) + { + /* ERROR */ + std::cerr << "UdpRelayReceiver::removeUdpRelay()"; + std::cerr << "ERROR Finding Relay: " << *addrSet; + std::cerr << std::endl; + } + else + { + /* lets drop the count here too */ + removeRelayClass_relayLocked(rit->second.mRelayClass); + mRelays.erase(rit); + } + + /* rotate around and delete matching set */ + UdpRelayAddrSet alt = addrSet->flippedSet(); + + rit = mRelays.find(alt); + if (rit == mRelays.end()) + { + std::cerr << "UdpRelayReceiver::removeUdpRelay()"; + std::cerr << "ERROR Finding Alt Relay: " << alt; + std::cerr << std::endl; + /* ERROR */ + } + else + { + mRelays.erase(rit); + } + return 1; +} + + /* Need some stats, to work out how many relays we are supporting */ +int UdpRelayReceiver::installRelayClass_relayLocked(int classIdx) +{ + /* check for total number of Relays */ + if (mClassCount[UDP_RELAY_CLASS_ALL] >= mClassLimit[UDP_RELAY_CLASS_ALL]) + { + std::cerr << "UdpRelayReceiver::installRelayClass() WARNING Too many Relays already"; + std::cerr << std::endl; + return 0; + } + + /* check the idx too */ + if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) + { + std::cerr << "UdpRelayReceiver::installRelayClass() ERROR class Idx invalid"; + std::cerr << std::endl; + return 0; + } + + /* now check the specifics of the class */ + if (mClassCount[classIdx] >= mClassLimit[classIdx]) + { + std::cerr << "UdpRelayReceiver::installRelayClass() WARNING Relay Class Limit Exceeded"; + std::cerr << std::endl; + + return 0; + } + + std::cerr << "UdpRelayReceiver::installRelayClass() Relay Class Ok, Count incremented"; + std::cerr << std::endl; + + /* if we get here we can add one */ + mClassCount[UDP_RELAY_CLASS_ALL]++; + mClassCount[classIdx]++; + + return 1; +} + +int UdpRelayReceiver::removeRelayClass_relayLocked(int classIdx) +{ + /* check for total number of Relays */ + if (mClassCount[UDP_RELAY_CLASS_ALL] < 1) + { + std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR no relays installed"; + std::cerr << std::endl; + return 0; + } + + /* check the idx too */ + if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) + { + std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR class Idx invalid"; + std::cerr << std::endl; + return 0; + } + + /* now check the specifics of the class */ + if (mClassCount[classIdx] < 1) + { + std::cerr << "UdpRelayReceiver::removeRelayClass() ERROR no relay of class installed"; + std::cerr << std::endl; + + return 0; + } + + std::cerr << "UdpRelayReceiver::removeRelayClass() Ok, Count decremented"; + std::cerr << std::endl; + + /* if we get here we can add one */ + mClassCount[UDP_RELAY_CLASS_ALL]--; + mClassCount[classIdx]--; + + return 1; +} + + +int UdpRelayReceiver::setRelayTotal(int count) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + mClassLimit[UDP_RELAY_CLASS_ALL] = count; + mClassLimit[UDP_RELAY_CLASS_GENERAL] = (int) (UDP_RELAY_FRAC_GENERAL * count); + mClassLimit[UDP_RELAY_CLASS_FOF] = (int) (UDP_RELAY_FRAC_FOF * count); + mClassLimit[UDP_RELAY_CLASS_FRIENDS] = (int) (UDP_RELAY_FRAC_FRIENDS * count); + + return count; +} + + +int UdpRelayReceiver::setRelayClassMax(int classIdx, int count) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* check the idx */ + if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) + { + std::cerr << "UdpRelayReceiver::setRelayMaximum() ERROR class Idx invalid"; + std::cerr << std::endl; + return 0; + } + + mClassLimit[classIdx] = count; + return 1; +} + + +int UdpRelayReceiver::getRelayClassMax(int classIdx) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* check the idx */ + if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) + { + std::cerr << "UdpRelayReceiver::getRelayMaximum() ERROR class Idx invalid"; + std::cerr << std::endl; + return 0; + } + + return mClassLimit[classIdx]; +} + +int UdpRelayReceiver::getRelayCount(int classIdx) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* check the idx */ + if ((classIdx < 0) || (classIdx >= UDP_RELAY_NUM_CLASS)) + { + std::cerr << "UdpRelayReceiver::getRelayCount() ERROR class Idx invalid"; + std::cerr << std::endl; + return 0; + } + + return mClassCount[classIdx]; +} + + +int UdpRelayReceiver::RelayStatus(std::ostream &out) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* iterate through the Relays */ + out << "UdpRelayReceiver::RelayStatus()"; + out << std::endl; + + std::map::iterator rit; + for(rit = mRelays.begin(); rit != mRelays.end(); rit++) + { + out << "Relay for: " << rit->first; + out << std::endl; + + out << "\tClass: " << rit->second.mRelayClass; + out << "\tBandwidth: " << rit->second.mBandwidth; + out << "\tDataSize: " << rit->second.mDataSize; + out << "\tLastBandwidthTS: " << rit->second.mLastBandwidthTS; + } + return 1; +} + +int UdpRelayReceiver::status(std::ostream &out) +{ + + out << "UdpRelayReceiver::status()" << std::endl; + out << "UdpRelayReceiver::Relayed Connections:" << std::endl; + + RelayStatus(out); + + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + out << "UdpRelayReceiver::Connections:" << std::endl; + + std::map::iterator pit; + for(pit = mStreams.begin(); pit != mStreams.end(); pit++) + { + out << "\t" << pit->first << " : " << pit->second; + out << std::endl; + } + + return 1; +} + +#define UDP_RELAY_HEADER_SIZE 16 + +/* higher level interface */ +int UdpRelayReceiver::recvPkt(void *data, int size, struct sockaddr_in &from) +{ + /* print packet information */ +#ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::recvPkt(" << size << ") from: " << from; + std::cerr << std::endl; + displayUdpRelayPacketHeader(data, size); + +#endif + + if (!isUdpRelayPacket(data, size)) + { +#ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::recvPkt() is Not RELAY Pkt"; + std::cerr << std::endl; +#endif + return 0; + } + + /* decide if we are the relay, or the endpoint */ + UdpRelayAddrSet addrSet; + if (!extractUdpRelayAddrSet(data, size, addrSet)) + { + /* fails most basic test, drop */ + return 0; + } + + { + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* lookup relay first (double entries) */ + std::map::iterator rit = mRelays.find(addrSet); + if (rit != mRelays.end()) + { + /* we are the relay */ + #ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::recvPkt() We are the Relay. Passing onto: "; + std::cerr << rit->first.mDestAddr; + std::cerr << std::endl; + #endif + /* do accounting */ + rit->second.mLastTS = time(NULL); + rit->second.mDataSize += size; + + mPublisher->sendPkt(data, size, rit->first.mDestAddr, STD_RELAY_TTL); + return 1; + } + } + + /* otherwise we are likely to be the endpoint, + * use the peers Address from the header + */ + + { + RsStackMutex stack(udppeerMtx); /********** LOCK MUTEX *********/ + + std::map::iterator pit = mPeers.find(addrSet.mSrcAddr); + if (pit != mPeers.end()) + { + /* we are the end-point */ + #ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::recvPkt() Sending to UdpPeer: "; + std::cerr << pit->first; + std::cerr << std::endl; + #endif + /* remove the header */ + void *pktdata = (void *) (((uint8_t *) data) + UDP_RELAY_HEADER_SIZE); + int pktsize = size - UDP_RELAY_HEADER_SIZE; + if (pktsize > 0) + { + (pit->second)->recvPkt(pktdata, pktsize); + } + else + { + /* packet undersized */ + #ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::recvPkt() ERROR Packet Undersized"; + std::cerr << std::endl; + #endif + } + return 1; + } + /* done */ + } + + /* unknown */ +#ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::recvPkt() Peer Unknown!"; + std::cerr << std::endl; +#endif + return 0; +} + + +/* the address here must be the end point!, + * it cannot be proxy, as we could be using the same proxy for multiple connections. + */ +int UdpRelayReceiver::sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl) +{ + RsStackMutex stack(relayMtx); /********** LOCK MUTEX *********/ + + /* work out who the proxy is */ + std::map::iterator it; + it = mStreams.find(to); + if (it == mStreams.end()) + { +//#ifdef DEBUG_UDP_RELAY + std::cerr << "UdpRelayReceiver::sendPkt() Peer Unknown!"; + std::cerr << std::endl; +//#endif + return 0; + } + + /* add a header to packet */ + int finalPktSize = createRelayUdpPacket(data, size, mTmpSendPkt, MAX_RELAY_UDP_PACKET_SIZE, &(it->second)); + + /* send the packet on */ + return mPublisher->sendPkt(mTmpSendPkt, finalPktSize, it->second.mProxyAddr, STD_RELAY_TTL); +} + +/***** RELAY PACKET FORMAT **************************** + * + * + * [ 0 | 1 | 2 | 3 ] + * + * [ 'R' 'L' 'Y' Version ] + * [ IP Address 1 ] + * [ Port 1 ][ IP Address 2 .... + * ... IP Address 2][ Port 2 ] + * [.... TUNNELLED DATA .... + * + * + * ... ] + * + * 16 Bytes: 4 ID, 6 IP:Port 1, 6 IP:Port 2 + */ + +#define UDP_IDENTITY_STRING_V1 "RLY1" +#define UDP_IDENTITY_SIZE_V1 4 + +int isUdpRelayPacket(const void *data, const int size) +{ + if (size < UDP_RELAY_HEADER_SIZE) + return 0; + + return (0 == strncmp((char *) data, UDP_IDENTITY_STRING_V1, UDP_IDENTITY_SIZE_V1)); +} + +#ifdef DEBUG_UDP_RELAY + +int displayUdpRelayPacketHeader(const void *data, const int size) +{ + int dsize = UDP_RELAY_HEADER_SIZE + 16; + if (size < dsize) + { + dsize = size; + } + + std::ostringstream out; + for(int i = 0; i < dsize; i++) + { + if ((i > 0) && (i % 16 == 0)) + { + out << std::endl; + } + + out << std::setw(2) << std::setfill('0') << std::hex << (uint32_t) ((uint8_t*) data)[i]; + } + + std::cerr << "displayUdpRelayPacketHeader()" << std::endl; + std::cerr << out.str(); + std::cerr << std::endl; + +} +#endif + + +int extractUdpRelayAddrSet(const void *data, const int size, UdpRelayAddrSet &addrSet) +{ + if (size < UDP_RELAY_HEADER_SIZE) + { + std::cerr << "createRelayUdpPacket() ERROR invalid size"; + std::cerr << std::endl; + return 0; + } + + uint8_t *header = (uint8_t *) data; + + sockaddr_clear(&(addrSet.mSrcAddr)); + sockaddr_clear(&(addrSet.mDestAddr)); + + /* as IP:Port are already in network byte order, we can just write them to the dataspace */ + uint32_t ipaddr; + uint16_t port; + + memcpy(&ipaddr, &(header[4]), 4); + memcpy(&port, &(header[8]), 2); + + addrSet.mSrcAddr.sin_addr.s_addr = ipaddr; + addrSet.mSrcAddr.sin_port = port; + + memcpy(&ipaddr, &(header[10]), 4); + memcpy(&port, &(header[14]), 2); + + addrSet.mDestAddr.sin_addr.s_addr = ipaddr; + addrSet.mDestAddr.sin_port = port; + + return 1; +} + + +int createRelayUdpPacket(const void *data, const int size, void *newpkt, int newsize, UdpRelayEnd *ure) +{ + int pktsize = size + UDP_RELAY_HEADER_SIZE; + if (newsize < pktsize) + { + std::cerr << "createRelayUdpPacket() ERROR invalid size"; + std::cerr << std::endl; + return 0; + } + uint8_t *header = (uint8_t *) newpkt; + memcpy(header, UDP_IDENTITY_STRING_V1, UDP_IDENTITY_SIZE_V1); + + /* as IP:Port are already in network byte order, we can just write them to the dataspace */ + uint32_t ipaddr = ure->mLocalAddr.sin_addr.s_addr; + uint16_t port = ure->mLocalAddr.sin_port; + + memcpy(&(header[4]), &ipaddr, 4); + memcpy(&(header[8]), &port, 2); + + ipaddr = ure->mRemoteAddr.sin_addr.s_addr; + port = ure->mRemoteAddr.sin_port; + + memcpy(&(header[10]), &ipaddr, 4); + memcpy(&(header[14]), &port, 2); + + memcpy(&(header[16]), data, size); + + return pktsize; +} + + + +/******* Small Container Class Helper Functions ****/ + +UdpRelayAddrSet::UdpRelayAddrSet() +{ + sockaddr_clear(&mSrcAddr); + sockaddr_clear(&mDestAddr); +} + +UdpRelayAddrSet::UdpRelayAddrSet(const sockaddr_in *ownAddr, const sockaddr_in *destAddr) +{ + mSrcAddr = *ownAddr; + mDestAddr = *destAddr; +} + +UdpRelayAddrSet UdpRelayAddrSet::flippedSet() +{ + UdpRelayAddrSet flipped(&mDestAddr, &mSrcAddr); + return flipped; +} + + +int operator<(const UdpRelayAddrSet &a, const UdpRelayAddrSet &b) +{ + if (a.mSrcAddr < b.mSrcAddr) + { + return 1; + } + + if (a.mSrcAddr == b.mSrcAddr) + { + if (a.mDestAddr < b.mDestAddr) + { + return 1; + } + } + return 0; +} + + +UdpRelayProxy::UdpRelayProxy() +{ + mBandwidth = 0; + mDataSize = 0; + mLastBandwidthTS = 0; + mLastTS = time(NULL); // Must be set here, otherwise Proxy Timesout before anything can happen! + mRelayClass = 0; +} + +UdpRelayProxy::UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass) +{ + mAddrs = *addrSet; + mRelayClass = relayClass; + + mBandwidth = 0; + mDataSize = 0; + mLastBandwidthTS = 0; + mLastTS = time(NULL); +} + +UdpRelayEnd::UdpRelayEnd() +{ + sockaddr_clear(&mLocalAddr); + sockaddr_clear(&mProxyAddr); + sockaddr_clear(&mRemoteAddr); + +} + +UdpRelayEnd::UdpRelayEnd(UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr) +{ + mLocalAddr = endPoints->mSrcAddr; + mRemoteAddr = endPoints->mDestAddr; + mProxyAddr = *proxyaddr; +} + + + + + +std::ostream &operator<<(std::ostream &out, const UdpRelayAddrSet &uras) +{ + out << "<" << uras.mSrcAddr << "," << uras.mDestAddr << ">"; + return out; +} + +std::ostream &operator<<(std::ostream &out, const UdpRelayProxy &urp) +{ + time_t now = time(NULL); + out << "UdpRelayProxy for " << urp.mAddrs; + out << std::endl; + out << "\tRelayClass: " << urp.mRelayClass; + out << std::endl; + out << "\tBandwidth: " << urp.mBandwidth; + out << std::endl; + out << "\tDataSize: " << urp.mDataSize; + out << std::endl; + out << "\tLastBandwidthTS: " << now - urp.mLastBandwidthTS << " secs ago"; + out << std::endl; + out << "\tLastTS: " << now - urp.mLastTS << " secs ago"; + out << std::endl; + + return out; +} + +std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure) +{ + out << "UdpRelayEnd: <" << ure.mLocalAddr << " => " << ure.mProxyAddr << " <= "; + out << ure.mRemoteAddr << ">"; + return out; +} + + + + diff --git a/libretroshare/src/tcponudp/udprelay.h b/libretroshare/src/tcponudp/udprelay.h new file mode 100644 index 000000000..0df12262b --- /dev/null +++ b/libretroshare/src/tcponudp/udprelay.h @@ -0,0 +1,186 @@ +#ifndef RS_UDP_RELAY_H +#define RS_UDP_RELAY_H + +/* + * tcponudp/udprelay.h + * + * libretroshare. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "tcponudp/udppeer.h" +#include + +class UdpRelayAddrSet; + +class UdpRelayAddrSet +{ + public: + UdpRelayAddrSet(); + UdpRelayAddrSet(const sockaddr_in *ownAddr, const sockaddr_in *destAddr); + + UdpRelayAddrSet flippedSet(); + + struct sockaddr_in mSrcAddr; /* msg source */ + struct sockaddr_in mDestAddr; /* final destination */ +}; + +int operator<(const UdpRelayAddrSet &a, const UdpRelayAddrSet &b); + +class UdpRelayProxy +{ + public: + UdpRelayProxy(); + UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass); + + UdpRelayAddrSet mAddrs; + double mBandwidth; + uint32_t mDataSize; + time_t mLastBandwidthTS; + time_t mLastTS; + + int mRelayClass; +}; + + +class UdpRelayEnd +{ + public: + + UdpRelayEnd(); + UdpRelayEnd(UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr); + + struct sockaddr_in mLocalAddr; + struct sockaddr_in mProxyAddr; + struct sockaddr_in mRemoteAddr; +}; + +std::ostream &operator<<(std::ostream &out, const UdpRelayAddrSet &uras); +std::ostream &operator<<(std::ostream &out, const UdpRelayProxy &urp); +std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure); + +/* we define a couple of classes (determining which class is done elsewhere) + * There will be various maximums for each type. + * Ideally you want to allow your friends to use your proxy in preference + * to randoms. + * + * At N x 2 x maxBandwidth. + * + * 10 x 2 x 1Kb/s => 20Kb/s In and Out. (quite a bit!) + * 20 x 2 x 1Kb/s => 40Kb/s Huge. + */ + +#define UDP_RELAY_DEFAULT_COUNT_ALL 10 +#define UDP_RELAY_FRAC_GENERAL (0.2) +#define UDP_RELAY_FRAC_FOF (0.5) +#define UDP_RELAY_FRAC_FRIENDS (0.8) + +#define UDP_RELAY_NUM_CLASS 4 + +#define UDP_RELAY_CLASS_ALL 0 +#define UDP_RELAY_CLASS_GENERAL 1 +#define UDP_RELAY_CLASS_FOF 2 +#define UDP_RELAY_CLASS_FRIENDS 3 + +#define STD_RELAY_TTL 64 + +class UdpRelayReceiver: public UdpSubReceiver +{ + public: + + UdpRelayReceiver(UdpPublisher *pub); +virtual ~UdpRelayReceiver(); + + /* add a TCPonUDP stream (ENDs) */ +int addUdpPeer(UdpPeer *peer, UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr); +int removeUdpPeer(UdpPeer *peer); + + /* add a Relay Point (for the Relay). + * These don't have to be explicitly removed. + * They will be timed out when + * the end-points drop the connections + */ + + int addUdpRelay(UdpRelayAddrSet *addrs, int classIdx); + int removeUdpRelay(UdpRelayAddrSet *addrs); + + /* Need some stats, to work out how many relays we are supporting */ + int checkRelays(); + + int setRelayTotal(int count); /* sets all the Relay Counts (frac based on total) */ + int setRelayClassMax(int classIdx, int count); /* set a specific class maximum */ + int getRelayClassMax(int classIdx); + int getRelayCount(int classIdx); /* how many relays (of this type) do we have */ + int RelayStatus(std::ostream &out); + + /* Extract Relay Data */ + int getRelayEnds(std::list &relayEnds); + int getRelayProxies(std::list &relayProxies); + + /* callback for recved data (overloaded from UdpReceiver) */ +virtual int recvPkt(void *data, int size, struct sockaddr_in &from); + + /* wrapper function for relay (overloaded from UdpSubReceiver) */ +virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); + +int status(std::ostream &out); + + private: + + int removeUdpRelay_relayLocked(UdpRelayAddrSet *addrs); + int installRelayClass_relayLocked(int classIdx); + int removeRelayClass_relayLocked(int classIdx); + + /* Unfortunately, Due the reentrant nature of this classes activities... + * the SendPkt() must be callable from inside RecvPkt(). + * This means we need two seperate mutexes. + * - one for UdpPeer's, and one for Relay Data. + * + * care must be taken to lock these mutex's in a consistent manner to avoid deadlock. + * - You are not allowed to hold both at the same time! + */ + + RsMutex udppeerMtx; /* for all class data (below) */ + + std::map mPeers; /* indexed by */ + + RsMutex relayMtx; /* for all class data (below) */ + + std::vector mClassLimit, mClassCount; + std::map mStreams; /* indexed by */ + std::map mRelays; /* indexed by */ + + void *mTmpSendPkt; + uint32_t mTmpSendSize; + +}; + +/* utility functions for creating / extracting UdpRelayPackets */ +int isUdpRelayPacket(const void *data, const int size); +int getPacketFromUdpRelayPacket(const void *data, const int size, void **realdata, int *realsize); + +int createRelayUdpPacket(const void *data, const int size, void *newpkt, int newsize, UdpRelayEnd *ure); +int extractUdpRelayAddrSet(const void *data, const int size, UdpRelayAddrSet &addrSet); + + + + +#endif diff --git a/libretroshare/src/tcponudp/udpstunner.cc b/libretroshare/src/tcponudp/udpstunner.cc new file mode 100644 index 000000000..7cc235b9e --- /dev/null +++ b/libretroshare/src/tcponudp/udpstunner.cc @@ -0,0 +1,871 @@ +/* + * tcponudp/udpstunner.cc + * + * libretroshare. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "udpstunner.h" +#include +#include + +#include "util/rsprint.h" + +static const int STUN_TTL = 64; + +#define TOU_STUN_MIN_PEERS 5 + +/* + * #define DEBUG_UDP_STUNNER 1 + */ +//#define DEBUG_UDP_STUNNER 1 + +const int32_t TOU_STUN_MAX_FAIL_COUNT = 3; /* 3 tries (could be higher?) */ +const int32_t TOU_STUN_MAX_SEND_RATE = 5; /* every 5 seconds */ +const int32_t TOU_STUN_MAX_RECV_RATE = 25; /* every 25 seconds */ +// TIMEOUT is now tied to STUN RATE ... const int32_t TOU_STUN_ADDR_MAX_AGE = 120; /* 2 minutes */ + +const int32_t TOU_STUN_DEFAULT_TARGET_RATE = 15; /* 20 secs is minimum to keep a NAT UDP port open */ +const double TOU_SUCCESS_LPF_FACTOR = 0.90; + + +UdpStunner::UdpStunner(UdpPublisher *pub) + :UdpSubReceiver(pub), eaddrKnown(false), eaddrStable(false), + mStunLastRecvResp(0), mStunLastRecvAny(0), + mStunLastSendStun(0), mStunLastSendAny(0) +{ +#ifdef UDPSTUN_ALLOW_LOCALNET + mAcceptLocalNet = false; +#endif + + + + /* these parameters determine the rate we attempt stuns */ + mPassiveStunMode = false; + mSuccessRate = 0.0; + mTargetStunPeriod = TOU_STUN_DEFAULT_TARGET_RATE; + + return; +} + +#ifdef UDPSTUN_ALLOW_LOCALNET + + // For Local Testing Only (Releases should have the #define disabled) +void UdpStunner::SetAcceptLocalNet() +{ + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + mAcceptLocalNet = true; +} + +#endif + +void UdpStunner::setTargetStunPeriod(uint32_t sec_per_stun) +{ + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + if (sec_per_stun == 0) + { + mPassiveStunMode = true; + } + else + { + mPassiveStunMode = false; + } + mTargetStunPeriod = sec_per_stun; + +} + +/* higher level interface */ +int UdpStunner::recvPkt(void *data, int size, struct sockaddr_in &from) +{ + /* print packet information */ +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::recvPkt(" << size << ") from: " << from; + std::cerr << std::endl; +#endif + + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + /* check for STUN packet */ + if (UdpStun_isStunPacket(data, size)) + { + mStunLastRecvAny = time(NULL); +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::recvPkt() is Stun Packet"; + std::cerr << std::endl; +#endif + + /* respond */ + locked_handleStunPkt(data, size, from); + + return 1; + } + return 0; +} + + +int UdpStunner::status(std::ostream &out) +{ + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + out << "UdpStunner::status() TargetStunPeriod: " << mTargetStunPeriod; + out << " SuccessRate: " << mSuccessRate; + out << std::endl; + + out << "UdpStunner::status()" << std::endl; + out << "UdpStunner::potentialpeers:" << std::endl; + std::list::iterator it; + for(it = mStunList.begin(); it != mStunList.end(); it++) + { + out << "\t" << it->id << std::endl; + } + out << std::endl; + + return 1; +} + +int UdpStunner::tick() +{ + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::tick()" << std::endl; +#endif + + if (checkStunDesired()) + { + attemptStun(); + } + + return 1; +} + +/******************************* STUN Handling ********************************/ + + /* respond */ +bool UdpStunner::locked_handleStunPkt(void *data, int size, struct sockaddr_in &from) +{ + if (size == 20) /* request */ + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::handleStunPkt() got Request from: "; + std::cerr << inet_ntoa(from.sin_addr) << ":" << ntohs(from.sin_port); + std::cerr << std::endl; +#endif + /* generate a response */ + int len; + void *pkt = UdpStun_generate_stun_reply(&from, &len); + if (!pkt) + return false; + + time_t now = time(NULL); + mStunLastSendAny = now; + int sentlen = sendPkt(pkt, len, from, STUN_TTL); + free(pkt); + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::handleStunPkt() sent Response size:" << sentlen; + std::cerr << std::endl; +#endif + + return (len == sentlen); + } + else if (size == 28) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::handleStunPkt() got Response"; + std::cerr << std::endl; +#endif + /* got response */ + struct sockaddr_in eAddr; + bool good = UdpStun_response(data, size, eAddr); + if (good) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::handleStunPkt() got Ext Addr: "; + std::cerr << inet_ntoa(eAddr.sin_addr) << ":" << ntohs(eAddr.sin_port); + std::cerr << " from: " << from; + std::cerr << std::endl; +#endif + locked_recvdStun(from, eAddr); + + return true; + } + } + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::handleStunPkt() Bad Packet"; + std::cerr << std::endl; +#endif + return false; +} + + +bool UdpStunner::externalAddr(struct sockaddr_in &external, uint8_t &stable) +{ + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + if (eaddrKnown) + { + /* address timeout */ + if (time(NULL) - eaddrTime > (mTargetStunPeriod * 2)) + { + std::cerr << "UdpStunner::externalAddr() eaddr expired"; + std::cerr << std::endl; + + return false; + } + + external = eaddr; + + if (eaddrStable) + stable = 1; + else + stable = 0; + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::externalAddr() eaddr:" << inet_ntoa(external.sin_addr); + std::cerr << ":" << ntohs(external.sin_port) << " stable: " << (int) stable; + std::cerr << std::endl; +#endif + + return true; + } +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::externalAddr() eaddr unknown"; + std::cerr << std::endl; +#endif + + return false; +} + + +int UdpStunner::doStun(struct sockaddr_in stun_addr) +{ +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::doStun()"; + std::cerr << std::endl; +#endif + + /* send out a stun packet -> save in the local variable */ + +#define MAX_STUN_SIZE 64 + char stundata[MAX_STUN_SIZE]; + int tmplen = MAX_STUN_SIZE; + bool done = UdpStun_generate_stun_pkt(stundata, &tmplen); + if (!done) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::doStun() Failed"; + std::cerr << std::endl; +#endif + //pqioutput(PQL_ALERT, pqistunzone, "pqistunner::stun() Failed!"); + return 0; + } + + /* send it off */ + int sentlen = sendPkt(stundata, tmplen, stun_addr, STUN_TTL); + + { + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + time_t now = time(NULL); + mStunLastSendStun = now; + mStunLastSendAny = now; + } + +#ifdef DEBUG_UDP_STUNNER + std::ostringstream out; + out << "UdpStunner::doStun() Sent Stun Packet(" << sentlen << ") "; + out << " to:"; + out << inet_ntoa(stun_addr.sin_addr) << ":" << ntohs(stun_addr.sin_port); + + std::cerr << out.str() << std::endl; + + //pqioutput(PQL_ALERT, pqistunzone, out.str()); +#endif + + return 1; +} + +/******************************* STUN Handling ********************************/ +/***** These next functions are generic and not dependent on class variables **/ +/******************************* STUN Handling ********************************/ + +bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr) +{ + /* check what type it is */ + if (size < 28) + { + return false; + } + + if (htons(((uint16_t *) stun_pkt)[0]) != 0x0101) + { + /* not a response */ + return false; + } + + /* iterate through the packet */ + /* for now assume the address follows the header directly */ + /* all stay in netbyteorder! */ + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = ((uint32_t *) stun_pkt)[6]; + addr.sin_port = ((uint16_t *) stun_pkt)[11]; + + +#ifdef DEBUG_UDP_STUNNER + std::ostringstream out; + out << "UdpStunner::response() Recvd a Stun Response, ext_addr: "; + out << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port); + std::cerr << out.str() << std::endl; +#endif + + return true; + +} + +bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len) +{ + if (*len < 20) + { + return false; + } + + /* just the header */ + ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(0x0001); + ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(20); /* only header */ + /* transaction id - should be random */ + ((uint32_t *) stun_pkt)[1] = (uint32_t) htonl(0x0020); + ((uint32_t *) stun_pkt)[2] = (uint32_t) htonl(0x0121); + ((uint32_t *) stun_pkt)[3] = (uint32_t) htonl(0x0111); + ((uint32_t *) stun_pkt)[4] = (uint32_t) htonl(0x1010); + *len = 20; + return true; +} + + +void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len) +{ + /* just the header */ + void *stun_pkt = malloc(28); + ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(0x0101); + ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(28); /* only header + 8 byte addr */ + /* transaction id - should be random */ + ((uint32_t *) stun_pkt)[1] = (uint32_t) htonl(0x0f20); + ((uint32_t *) stun_pkt)[2] = (uint32_t) htonl(0x0f21); + ((uint32_t *) stun_pkt)[3] = (uint32_t) htonl(0x0f11); + ((uint32_t *) stun_pkt)[4] = (uint32_t) htonl(0x1010); + /* now add address + * 0 1 2 3 + * + * + */ + + /* THESE SHOULD BE NET ORDER ALREADY */ + ((uint16_t *) stun_pkt)[10] = AF_INET; + ((uint16_t *) stun_pkt)[11] = stun_addr->sin_port; + ((uint32_t *) stun_pkt)[6] = stun_addr->sin_addr.s_addr; + + *len = 28; + return stun_pkt; +} + +bool UdpStun_isStunPacket(void *data, int size) +{ +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::isStunPacket() ?"; + std::cerr << std::endl; +#endif + + if (size < 20) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::isStunPacket() (size < 20) -> false"; + std::cerr << std::endl; +#endif + return false; + } + + /* match size field */ + uint16_t pktsize = ntohs(((uint16_t *) data)[1]); + if (size != pktsize) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::isStunPacket() (size != pktsize) -> false"; + std::cerr << std::endl; +#endif + return false; + } + + if ((size == 20) && (0x0001 == ntohs(((uint16_t *) data)[0]))) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::isStunPacket() (size=20 & data[0]=0x0001) -> true"; + std::cerr << std::endl; +#endif + /* request */ + return true; + } + + if ((size == 28) && (0x0101 == ntohs(((uint16_t *) data)[0]))) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::isStunPacket() (size=28 & data[0]=0x0101) -> true"; + std::cerr << std::endl; +#endif + /* response */ + return true; + } + return false; +} + + +/******************************* STUN Handling ******************************** + * KeepAlive has been replaced by a targetStunRate. Set this to zero to disable. + */ + +/******************************* STUN Handling ********************************/ + + +bool UdpStunner::addStunPeer(const struct sockaddr_in &remote, const char *peerid) +{ + /* add to the list */ +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::addStunPeer()"; + std::cerr << std::endl; +#endif + + bool toStore = true; + { + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + /* only store if we're active */ + toStore = !mPassiveStunMode; + } + + if (toStore) + { + storeStunPeer(remote, peerid, 0); + } + return true; +} + +bool UdpStunner::storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent) +{ + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::storeStunPeer()"; + std::cerr << std::endl; +#endif + + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + std::list::iterator it; + for(it = mStunList.begin(); it != mStunList.end(); it++) + { + if ((remote.sin_addr.s_addr == it->remote.sin_addr.s_addr) && + (remote.sin_port == it->remote.sin_port)) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::storeStunPeer() Peer Already There!"; + std::cerr << std::endl; +#endif + /* already there */ + if (sent) + { + it->failCount += 1; + it->lastsend = time(NULL); + } + return false; + } + } + + TouStunPeer peer(std::string(peerid), remote); + if (sent) + { + peer.failCount += 1; + peer.lastsend = time(NULL); + } + + mStunList.push_back(peer); + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::storeStunPeer() Added Peer"; + std::cerr << std::endl; +#endif + + return true; +} + + +bool UdpStunner::checkStunDesired() +{ + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::checkStunDesired()"; + std::cerr << std::endl; +#endif + + time_t now; + { + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + if (mPassiveStunMode) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::checkStunDesired() In Passive Mode"; + std::cerr << std::endl; +#endif + return false; /* all good */ + } + + if (!eaddrKnown) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::checkStunDesired() YES, we don't have extAddr Yet"; + std::cerr << std::endl; +#endif + return true; /* want our external address */ + } + + /* check if we need to send one now */ + now = time(NULL); + + /* based on SuccessRate & TargetStunRate, we work out if we should send one + * + * if we have 100% success rate, then we can delay until exactly TARGET RATE. + * if we have 0% success rate, then try at double TARGET RATE. + * + */ + double stunPeriod = (mTargetStunPeriod / 2.0) * (1.0 + mSuccessRate); + time_t nextStun = mStunLastRecvResp + (int) stunPeriod; + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::checkStunDesired() TargetStunPeriod: " << mTargetStunPeriod; + std::cerr << " SuccessRate: " << mSuccessRate; + std::cerr << " DesiredStunPeriod: " << stunPeriod; + std::cerr << " NextStun: " << nextStun - now << " secs"; + std::cerr << std::endl; +#endif + + if (now >= nextStun) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::checkStunDesired() Stun is Desired"; + std::cerr << std::endl; +#endif + return true; + } + else + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::checkStunDesired() Stun is Not Needed"; + std::cerr << std::endl; +#endif + return false; + } + } +} + + +bool UdpStunner::attemptStun() +{ + bool found = false; + TouStunPeer peer; + time_t now = time(NULL); + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::attemptStun()"; + std::cerr << std::endl; +#endif + + { + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + int i; + for(i = 0; ((i < mStunList.size()) && (mStunList.size() > 0) && (!found)); i++) + { + /* extract entry */ + peer = mStunList.front(); + mStunList.pop_front(); + + /* check if expired */ + if (peer.failCount > TOU_STUN_MAX_FAIL_COUNT) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::attemptStun() Peer has expired, dropping"; + std::cerr << std::endl; +#endif + } + else + { + // Peer Okay, check last send time. + if (now - peer.lastsend < TOU_STUN_MAX_SEND_RATE) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::attemptStun() Peer was sent to Too Recently, pushing back"; + std::cerr << std::endl; +#endif + mStunList.push_back(peer); + } + else + { + /* we have found a peer! */ +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::attemptStun() Found Peer to Stun."; + std::cerr << std::endl; +#endif + peer.failCount++; + peer.lastsend = now; + mStunList.push_back(peer); + mSuccessRate *= TOU_SUCCESS_LPF_FACTOR; + + found = true; + } + } + } // END OF WHILE LOOP. + + if (mStunList.size() < 1) + { +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::attemptStun() No Peers in List. FAILED"; + std::cerr << std::endl; +#endif + return false; + } + +#ifdef DEBUG_UDP_STUNNER + locked_printStunList(); +#endif + + } // END OF MUTEX LOCKING. + + if (found) + { + doStun(peer.remote); + return true; + } + return false; +} + + +bool UdpStunner::locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr) +{ +#ifdef DEBUG_UDP_STUNNER + std::ostringstream out; + out << "UdpStunner::locked_recvdStun() from:"; + out << inet_ntoa(remote.sin_addr) << ":" << ntohs(remote.sin_port); + out << " claiming ExtAddr is:"; + out << inet_ntoa(extaddr.sin_addr) << ":" << ntohs(extaddr.sin_port); + + std::cerr << out.str() << std::endl; +#endif + + bool found = true; + std::list::iterator it; + for(it = mStunList.begin(); it != mStunList.end(); it++) + { + if ((remote.sin_addr.s_addr == it->remote.sin_addr.s_addr) && + (remote.sin_port == it->remote.sin_port)) + { + it->failCount = 0; + it->eaddr = extaddr; + it->response = true; + + found = true; + break; + } + } + + /* if not found.. should we add it back in? */ + + /* How do we calculate the success rate? + * Don't want to count all the stuns? + * Low Pass filter won't work either... + * at send... + * mSuccessRate = 0.95 * mSuccessRate. + * at recv... + * mSuccessRate = 0.95 * mSuccessRate + 0.05; + * + * But if we split into a two stage eqn. it'll work! + * a + * mSuccessRate = 0.95 * mSuccessRate. + * at recv... + * mSuccessRate += 0.05; + */ + + mSuccessRate += (1.0-TOU_SUCCESS_LPF_FACTOR); + + time_t now = time(NULL); + mStunLastRecvResp = now; + mStunLastRecvAny = now; + +#ifdef DEBUG_UDP_STUNNER + locked_printStunList(); +#endif + + locked_checkExternalAddress(); + + return found; +} + +bool UdpStunner::locked_checkExternalAddress() +{ +#ifdef DEBUG_UDP_STUNNER + std::ostringstream out; + out << "UdpStunner::locked_checkExternalAddress()"; + std::cerr << out.str() << std::endl; +#endif + + bool found1 = false; + bool found2 = false; + time_t now = time(NULL); + /* iterator backwards - as these are the most recent */ + std::list::reverse_iterator it; + std::list::reverse_iterator p1; + std::list::reverse_iterator p2; + for(it = mStunList.rbegin(); it != mStunList.rend(); it++) + { + /* check: + 1) have response. + 2) have eaddr. + 3) no fails. + 4) recent age. + */ + + time_t age = (now - it->lastsend); + if (it->response && +#ifdef UDPSTUN_ALLOW_LOCALNET + ( mAcceptLocalNet || isExternalNet(&(it->eaddr.sin_addr))) && +#else + (isExternalNet(&(it->eaddr.sin_addr))) && +#endif + (it->failCount == 0) && (age < (mTargetStunPeriod * 2))) + { + if (!found1) + { + p1 = it; + found1 = true; + } + else + { + p2 = it; + found2 = true; + break; + } + } + } + + if (found1 && found2) + { + if ((p1->eaddr.sin_addr.s_addr == p2->eaddr.sin_addr.s_addr) && + (p1->eaddr.sin_port == p2->eaddr.sin_port)) + { + eaddrStable = true; + } + else + { + eaddrStable = false; + } + eaddrKnown = true; + eaddr = p1->eaddr; + eaddrTime = now; + +#ifdef DEBUG_UDP_STUNNER + std::cerr << "UdpStunner::locked_checkExternalAddress() Found State:"; + if (eaddrStable) + std::cerr << " Stable NAT translation (GOOD!) "; + else + std::cerr << " unStable (symmetric NAT translation (BAD!) "; + std::cerr << std::endl; +#endif + + return true; + } + + return false; +} + + + +bool UdpStunner::locked_printStunList() +{ +#ifdef DEBUG_UDP_STUNNER + std::ostringstream out; + + time_t now = time(NULL); + out << "locked_printStunList()" << std::endl; + out << "\tLastSendStun: " << now - mStunLastSendStun << std::endl; + out << "\tLastSendAny: " << now - mStunLastSendAny << std::endl; + out << "\tLastRecvResp: " << now - mStunLastRecvResp << std::endl; + out << "\tLastRecvAny: " << now - mStunLastRecvAny << std::endl; + + std::list::iterator it; + for(it = mStunList.begin(); it != mStunList.end(); it++) + { + out << "id:" << RsUtil::BinToHex(it->id) << " addr: " << inet_ntoa(it->remote.sin_addr); + out << ":" << htons(it->remote.sin_port); + out << " eaddr: " << inet_ntoa(it->eaddr.sin_addr); + out << ":" << htons(it->eaddr.sin_port); + out << " failCount: " << it->failCount; + out << " lastSend: " << now - it->lastsend; + out << std::endl; + } + + std::cerr << out.str(); +#endif + + return true; +} + + +bool UdpStunner::getStunPeer(int idx, std::string &id, + struct sockaddr_in &remote, struct sockaddr_in &eaddr, + uint32_t &failCount, time_t &lastSend) +{ + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + std::list::iterator it; + int i; + for(i=0, it=mStunList.begin(); (iid); + remote = it->remote; + eaddr = it->eaddr; + failCount = it->failCount; + lastSend = it->lastsend; + return true; + } + + return false; +} + + +bool UdpStunner::needStunPeers() +{ + RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/ + + return (mStunList.size() < TOU_STUN_MIN_PEERS); +} + + diff --git a/libretroshare/src/tcponudp/udpstunner.h b/libretroshare/src/tcponudp/udpstunner.h new file mode 100644 index 000000000..e0223dba0 --- /dev/null +++ b/libretroshare/src/tcponudp/udpstunner.h @@ -0,0 +1,153 @@ +#ifndef RS_UDP_STUN_H +#define RS_UDP_STUN_H +/* + * tcponudp/udpstunner.h + * + * libretroshare. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 3 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#endif + +#ifndef WINDOWS_SYS +#include +#endif + +#include "tcponudp/rsudpstack.h" +#include "util/rsthreads.h" +#include + +/* UdpStun. + * Stuns peers to determine external addresses. + */ + +class TouStunPeer +{ + public: + TouStunPeer() + :response(false), lastsend(0), failCount(0) + { + eaddr.sin_addr.s_addr = 0; + eaddr.sin_port = 0; + return; + } + + TouStunPeer(std::string id_in, const struct sockaddr_in &addr) + :id(id_in), remote(addr), response(false), lastsend(0), failCount(0) + { + eaddr.sin_addr.s_addr = 0; + eaddr.sin_port = 0; + return; + } + + std::string id; + struct sockaddr_in remote, eaddr; + bool response; + time_t lastsend; + uint32_t failCount; +}; + +/* + * #define UDPSTUN_ALLOW_LOCALNET 1 + */ + +class UdpStunner: public UdpSubReceiver +{ + public: + + UdpStunner(UdpPublisher *pub); +virtual ~UdpStunner() { return; } + +#ifdef UDPSTUN_ALLOW_LOCALNET + // For Local Testing Mode. + void SetAcceptLocalNet(); +#endif + +void setTargetStunPeriod(uint32_t sec_per_stun); +bool addStunPeer(const struct sockaddr_in &remote, const char *peerid); +bool getStunPeer(int idx, std::string &id, + struct sockaddr_in &remote, struct sockaddr_in &eaddr, + uint32_t &failCount, time_t &lastSend); + +bool needStunPeers(); + +bool externalAddr(struct sockaddr_in &remote, uint8_t &stable); + + /* Packet IO */ +virtual int recvPkt(void *data, int size, struct sockaddr_in &from); +virtual int status(std::ostream &out); + + /* monitoring / updates */ + int tick(); + + private: + +bool checkStunDesired(); +bool attemptStun(); + +int doStun(struct sockaddr_in stun_addr); +bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent); + + + /* STUN handling */ +bool locked_handleStunPkt(void *data, int size, struct sockaddr_in &from); + +bool locked_printStunList(); +bool locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr); +bool locked_checkExternalAddress(); + + + RsMutex stunMtx; /* for all class data (below) */ + + struct sockaddr_in eaddr; /* external addr */ + + bool eaddrKnown; + bool eaddrStable; /* if true then usable. if false -> Symmettric NAT */ + time_t eaddrTime; + + time_t mStunLastRecvResp; + time_t mStunLastRecvAny; + time_t mStunLastSendStun; + time_t mStunLastSendAny; + + std::list mStunList; /* potentials */ + +#ifdef UDPSTUN_ALLOW_LOCALNET + // For Local Testing Mode. + bool mAcceptLocalNet; +#endif + + bool mPassiveStunMode; + uint32_t mTargetStunPeriod; + double mSuccessRate; + +}; + + /* generic stun functions */ + +bool UdpStun_isStunPacket(void *data, int size); +bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr); +void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len); +bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len); + +#endif diff --git a/libretroshare/src/tests/TestNotes.txt b/libretroshare/src/tests/TestNotes.txt new file mode 100644 index 000000000..6505574cb --- /dev/null +++ b/libretroshare/src/tests/TestNotes.txt @@ -0,0 +1,21 @@ + +This file documents the high-level status of the regression cases. +------------------------------------------------------------------------------------ +DIRECTORY STATUS TODO +------------------------------------------------------------------------------------ +services : NO TESTS write test framework for services. +turtle : NO TESTS write tests +rsserver : NO TESTS write tests +upnp : NO TESTS write tests. +util : limited manual tests complete tests, convert to automatic +dbase : limited manual tests complete tests, convert to automatic +pqi : limited manual tests complete tests, convert to automatic +ft : manual tests complete tests, convert to automatic +tcponudp : manual tests convert to automatic +dht : manual tests ignore - old code - to be replaced soon. +serialiser : automatic tests complete tests, update tests. + + + + + diff --git a/libretroshare/src/tests/dbase/Makefile b/libretroshare/src/tests/dbase/Makefile new file mode 100644 index 000000000..6dd13174b --- /dev/null +++ b/libretroshare/src/tests/dbase/Makefile @@ -0,0 +1,54 @@ + +RS_TOP_DIR = ../.. +DHT_TOP_DIR = ../../../../libbitdht/src +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/config.mk +############################################################### + +TESTOBJ = fitest2.o fisavetest.o searchtest.o #ficachetest.o +#ficachetest.o + +TESTS = fitest2 fisavetest searchtest #ficachetest +#ficachetest + +ifeq ($(OS),Linux) + TESTOBJ += fimontest.o + TESTS += fimontest +endif + + +ifeq ($(OS),MacOSX) + TESTOBJ += fimontest.o + TESTS += fimontest +endif + + +all: tests + +fitest2 : fitest2.o $(OBJ) + $(CC) $(CFLAGS) -o fitest2 fitest2.o $(OBJ) $(LIBS) + +fisavetest : fisavetest.o $(OBJ) + $(CC) $(CFLAGS) -o fisavetest fisavetest.o $(OBJ) $(LIBS) + +fimontest : fimontest.o $(OBJ) + $(CC) $(CFLAGS) -o fimontest fimontest.o $(OBJ) $(LIBS) + +ficachetest : ficachetest.o $(OBJ) + $(CC) $(CFLAGS) -o ficachetest ficachetest.o $(OBJ) $(LIBS) + +searchtest : searchtest.o $(OBJ) + $(CC) $(CFLAGS) -o searchtest searchtest.o $(OBJ) $(LIBS) + +clobber: rmtestfiles + +rmtestfiles: + $(RM) test.index + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/tests/dbase/ficachetest.cc b/libretroshare/src/tests/dbase/ficachetest.cc new file mode 100644 index 000000000..fa00d03b4 --- /dev/null +++ b/libretroshare/src/tests/dbase/ficachetest.cc @@ -0,0 +1,208 @@ +/* + * RetroShare FileCache Module: ficachetest.cc + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "dbase/cachestrapper.h" +#include "dbase/cachetest.h" +#include "pqi/p3connmgr.h" + +#include +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS +#else + #include +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + +void handleQuery(CacheStrapper *csp, RsPeerId pid, + std::map &strappers); + +/* A simple test of the CacheStrapper Code. + * + * create 3 different CacheStrappers, each with a Source/Store Pair and Transfer Class. + * pass queries and responses between the CacheStrappers, + * and ensure that the hashes in the Caches are updated. + * + */ + +int main(int argc, char **argv) +{ + + time_t period = 11; + RsPeerId pid1("0x0101"); + RsPeerId pid2("0x0102"); + RsPeerId pid3("0x0103"); + + p3ConnectMgr *connMgr1 = new p3ConnectMgr(); + p3ConnectMgr *connMgr2 = connMgr1; + p3ConnectMgr *connMgr3 = connMgr1; + + CacheStrapper sc1(connMgr1); + CacheStrapper sc2(connMgr2); + CacheStrapper sc3(connMgr3); + CacheTransfer ctt1(&sc1); + CacheTransfer ctt2(&sc2); + CacheTransfer ctt3(&sc3); + + std::map strappers; + strappers[pid1] = &sc1; + strappers[pid2] = &sc2; + strappers[pid3] = &sc3; + + + std::string nulldir = ""; + + CacheSource *csrc1 = new CacheTestSource(&sc1, nulldir); + CacheStore *cstore1 = new CacheTestStore(&ctt1, &sc1, nulldir); + CacheId cid1(TESTID, 0); + + CacheSource *csrc2 = new CacheTestSource(&sc2, nulldir); + CacheStore *cstore2 = new CacheTestStore(&ctt2, &sc2, nulldir); + CacheId cid2(TESTID, 0); + + CacheSource *csrc3 = new CacheTestSource(&sc3, nulldir); + CacheStore *cstore3 = new CacheTestStore(&ctt3, &sc3, nulldir); + CacheId cid3(TESTID, 0); + + CachePair cp1(csrc1, cstore1, cid1); + CachePair cp2(csrc2, cstore2, cid2); + CachePair cp3(csrc3, cstore3, cid3); + + sc1.addCachePair(cp1); + sc2.addCachePair(cp2); + sc3.addCachePair(cp3); + + /* add in a cache to sc2 */ + CacheData cdata; + + cdata.pid = pid1; + cdata.cid = cid1; + cdata.name = "Perm Cache"; + cdata.path = "./"; + cdata.hash = "GHJKI"; + + csrc1->refreshCache(cdata); + + cdata.pid = pid2; + cdata.cid = cid2; + cdata.name = "Funny Cache"; + cdata.path = "./"; + cdata.hash = "ABCDEF"; + + csrc2->refreshCache(cdata); + + /* now exercise it */ + + for(int i = 0; 1 ; i++) + { + RsPeerId src(""); + CacheStrapper *csp = NULL; + + if (i % 5 == 1) + { + src = pid1; + csp = &sc1; + } + else if (i % 5 == 2) + { + src = pid2; + csp = &sc2; + } + else if (i % 5 == 3) + { + src = pid3; + csp = &sc3; + } + std::cerr << std::endl; + std::cerr << "Cache Iteraton: " << time(NULL) << std::endl; + std::cerr << std::endl; + + if (src != "") + { + handleQuery(csp, src, strappers); + } + + + if (i % 21 == 0) + { + /* print out the resources */ + sc1.listCaches(std::cerr); + sc2.listCaches(std::cerr); + sc3.listCaches(std::cerr); + } + + /* every once in a while change the cache on 2 */ + if (i % 31 == 25) + { + cdata.hash += "X"; + csrc2->refreshCache(cdata); + } + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + sleep(1); +#else + Sleep(1000); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + /* tick the systems */ + + } + + /* Cleanup - TODO */ + + return 1; +} + +void handleQuery(CacheStrapper *csp, RsPeerId pid, + std::map &strappers) +{ + /* query */ + std::list ids; + std::list::iterator pit; + + std::cerr << "Cache Query from: " << pid << std::endl; + + //csp -> sendCacheQuery(ids, time(NULL)); + for(pit = ids.begin(); pit != ids.end(); pit++) + { + std::cerr << "Cache Query for: " << (*pit) << std::endl; + std::map::iterator sit; + if (strappers.end() != (sit = strappers.find(*pit))) + { + std::map hashs; + std::map::iterator hit; + (sit -> second) -> handleCacheQuery(pid, hashs); + for(hit = hashs.begin(); hit != hashs.end(); hit++) + { + csp -> recvCacheResponse(hit->second, time(NULL)); + } + } + else + { + std::cerr << "Unknown Query Destination!" << std::endl; + } + } +} + diff --git a/libretroshare/src/tests/dbase/fimontest.cc b/libretroshare/src/tests/dbase/fimontest.cc new file mode 100644 index 000000000..00422659c --- /dev/null +++ b/libretroshare/src/tests/dbase/fimontest.cc @@ -0,0 +1,99 @@ +/* + * RetroShare FileCache Module: fimontest.cc + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/p3connmgr.h" +#include "retroshare/rsiface.h" +#include "dbase/cachestrapper.h" +#include "dbase/findex.h" +#include "dbase/fimonitor.h" + +#include + +void usage(char *name) +{ + std::cerr << "Usage: " << name << " [-p ] shareDir1 [shareDir2 [shareDir3 [...]]]"; + std::cerr << std::endl; + exit(1); +} + + +/*! + * What is tested: + * 1. + * 2. + * 3. + */ +int main(int argc, char **argv) +{ + /* handle commandline arguments */ + int c; + int period = 60; /* recheck period in seconds */ + + while((c = getopt(argc, argv,"p:")) != -1) + { + switch(c) + { + case 'p': + period = atoi(optarg); + break; + default: + std::cerr << "Bad Option."; + std::cerr << std::endl; + usage(argv[0]); + break; + } + } + + std::list rootdirs; + + /* add all the rest of the commandline arguments to rootdirs list */ + for(; optind < argc; optind++) + { + SharedDirInfo dir; + dir.filename = argv[optind]; + dir.shareflags = RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE; + rootdirs.push_back(dir); + std::cerr << "Adding shared directory: " << argv[optind] << std::endl; + } + + if (rootdirs.size() < 1) + { + usage(argv[0]); + } + + //p3ConnectMgr connMgr; + NotifyBase nb; + CacheStrapper* cs = NULL; + + FileIndexMonitor mon(cs, &nb, "", "OWN ID", std::string(".")); + + /* setup monitor */ + mon.setSharedDirectories(rootdirs); + + /* simulate running the thread */ + mon.run(); + + return 1; +} + + diff --git a/libretroshare/src/tests/dbase/fisavetest.cc b/libretroshare/src/tests/dbase/fisavetest.cc new file mode 100644 index 000000000..edaa52520 --- /dev/null +++ b/libretroshare/src/tests/dbase/fisavetest.cc @@ -0,0 +1,119 @@ +/* + * RetroShare FileCache Module: fisavetest.cc + * + * Copyright 2004-2007 by Kefei Zhou. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "dbase/findex.h" +#include + +FileIndex *createBasicFileIndex(time_t age); + +int main() +{ + FileIndex *fi1 = createBasicFileIndex(100); + FileIndex *fi2 = new FileIndex("A SILLY ID"); + + fi1->printFileIndex(std::cout); + std::string fhash; + uint64_t size; + std::set forbiddenroots; + fi1->saveIndex("test.index", fhash, size, forbiddenroots); + + std::cout << " Saved Index: Size: " << size << " Hash: " << fhash << std::endl; + std::cout << " -- new file index -- " << std::endl; + + fi2->loadIndex("test.index", fhash, size); + fi2->printFileIndex(std::cout); + + delete fi1; + delete fi2; + + return 1; +} + + +FileIndex *createBasicFileIndex(time_t age) +{ + FileIndex *fi = new FileIndex("A SILLY ID"); + + FileEntry fe; + + std::list rootdirs; + rootdirs.push_back("base1"); + rootdirs.push_back("base2"); + rootdirs.push_back("base3"); + + fi -> setRootDirectories(rootdirs, age); + + /* add some entries */ + fe.name = "dir1"; + fi -> updateDirEntry("base1",fe, age); + fe.name = "dir2"; + fi -> updateDirEntry("base1",fe, age); + + fe.name = "dir01"; + fi -> updateDirEntry("/base1/dir1/",fe, age); + + fe.name = "dir001"; + fi -> updateDirEntry("/base1/dir1/dir01/",fe, age); + + fe.name = "file1"; + fi -> updateFileEntry("/base1/dir1/",fe, age); + fe.name = "file2"; + fi -> updateFileEntry("/base1/dir1/",fe, age); + fe.name = "file3"; + fi -> updateFileEntry("/base1/dir1/",fe, age); + fe.name = "file4"; + fi -> updateFileEntry("/base1/dir1/",fe, age); + + + fe.name = "dir2"; + fi -> updateDirEntry("/base1",fe, age); + fe.name = "file5"; + fi -> updateFileEntry("/base1/dir2/",fe, age); + fe.name = "file6"; + fi -> updateFileEntry("/base1/dir2/",fe, age); + fe.name = "file7"; + fi -> updateFileEntry("/base1/dir2/",fe, age); + fe.name = "file8"; + fi -> updateFileEntry("/base1/",fe, age); + + + fe.name = "dir3"; + fi -> updateDirEntry("/base1/dir2/",fe, age); + fe.name = "file10"; + fi -> updateFileEntry("/base1/dir2/dir3",fe, age); + fe.name = "file11"; + fi -> updateFileEntry("/base1/dir2/dir3",fe, age); + fe.name = "file12"; + fi -> updateFileEntry("/base1/dir2/dir3",fe, age); + + + fe.name = "dir4"; + fi -> updateDirEntry("/base3/",fe, age); + fe.name = "file20"; + fi -> updateFileEntry("/base3/dir4/",fe, age); + fe.name = "file21"; + fi -> updateFileEntry("/base3/dir4",fe, age); + + return fi; +} + diff --git a/libretroshare/src/tests/dbase/fitest2.cc b/libretroshare/src/tests/dbase/fitest2.cc new file mode 100644 index 000000000..7d1fc4c9a --- /dev/null +++ b/libretroshare/src/tests/dbase/fitest2.cc @@ -0,0 +1,213 @@ +/* + * RetroShare FileCache Module: fitest2.cc + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "dbase/findex.h" + +#include + +FileIndex *createBasicFileIndex(time_t age); + +int test1(FileIndex *fi); +int test2(FileIndex *fi); + +int main() +{ + FileIndex *fi = createBasicFileIndex(100); + + test1(fi); + + delete fi; + + return 1; +} + +int test1(FileIndex *fi) +{ + /* in this test we are going to get the old directories - and update them */ + time_t stamp = 200; + + DirEntry *olddir = NULL; + FileEntry fe; + while((olddir = fi -> findOldDirectory(stamp))) + { + /* update the directories and files here */ + std::map::iterator dit; + std::map::iterator fit; + + /* update this dir */ + fe.name = olddir->name; + fi -> updateDirEntry(olddir->parent->path, fe, stamp); + + /* update subdirs */ + for(dit = olddir->subdirs.begin(); dit != olddir->subdirs.end(); dit++) + { + fe.name = (dit->second)->name; + /* set the age as out-of-date so that it gets checked */ + fi -> updateDirEntry(olddir->path, fe, 0); + } + + /* update files */ + for(fit = olddir->files.begin(); fit != olddir->files.end(); fit++) + { + fe.name = (fit->second)->name; + fi -> updateFileEntry(olddir->path, fe, stamp); + } + + /* clean up the dir (should have no effect) */ + fi -> removeOldDirectory(olddir->parent->path, olddir->name, stamp); + fi -> printFileIndex(std::cout); + } + + fi -> printFileIndex(std::cout); + + return 1; +} + + +int test2(FileIndex *fi) +{ + /* in this test we are going to simulate that 2 directories have disappeared */ + time_t stamp = 200; + + DirEntry *olddir = NULL; + FileEntry fe; + bool missingdir = false; + int i = 0; + + while((olddir = fi -> findOldDirectory(stamp))) + { + missingdir = false; + if (i % 2 == 0) + { + std::cerr << " Simulating that dir doesnt exist :" << olddir->path; + std::cerr << std::endl; + missingdir = true; + } + i++; + + if (!missingdir) + { + /* update the directories and files here */ + std::map::iterator dit; + std::map::iterator fit; + + /* update this dir */ + fe.name = olddir->name; + fi -> updateDirEntry(olddir->parent->path, fe, stamp); + + /* update subdirs */ + for(dit = olddir->subdirs.begin(); dit != olddir->subdirs.end(); dit++) + { + fe.name = (dit->second)->name; + /* set the age as out-of-date so that it gets checked */ + fi -> updateDirEntry(olddir->path, fe, 0); + } + + /* update files */ + for(fit = olddir->files.begin(); fit != olddir->files.end(); fit++) + { + fe.name = (fit->second)->name; + fi -> updateFileEntry(olddir->path, fe, stamp); + } + } + /* clean up the dir */ + fi -> removeOldDirectory(olddir->parent->path, olddir->name, stamp); + + fi -> printFileIndex(std::cout); + } + + fi -> printFileIndex(std::cout); + + return 1; +} + + + + + +FileIndex *createBasicFileIndex(time_t age) +{ + FileIndex *fi = new FileIndex("A SILLY ID"); + + FileEntry fe; + + /* print empty FileIndex */ + fi -> printFileIndex(std::cout); + + std::list rootdirs; + rootdirs.push_back("base1"); + rootdirs.push_back("base2"); + rootdirs.push_back("base3"); + + fi -> setRootDirectories(rootdirs, age); + + /* add some entries */ + fe.name = "dir1"; + fi -> updateDirEntry("base1",fe, age); + fe.name = "file1"; + fi -> updateFileEntry("/base1/dir1/",fe, age); + fe.name = "file2"; + fi -> updateFileEntry("/base1/dir1/",fe, age); + fe.name = "file3"; + fi -> updateFileEntry("/base1/dir1/",fe, age); + fe.name = "file4"; + fi -> updateFileEntry("/base1/dir1/",fe, age); + + fe.name = "dir2"; + fi -> updateDirEntry("/base1",fe, age); + fe.name = "file5"; + fi -> updateFileEntry("/base1/dir2/",fe, age); + fe.name = "file6"; + fi -> updateFileEntry("/base1/dir2/",fe, age); + fe.name = "file7"; + fi -> updateFileEntry("/base1/dir2/",fe, age); + fe.name = "file8"; + fi -> updateFileEntry("/base1/",fe, age); + + + fe.name = "dir3"; + fi -> updateDirEntry("/base1/dir2/",fe, age); + fe.name = "file10"; + fi -> updateFileEntry("/base1/dir2/dir3",fe, age); + fe.name = "file11"; + fi -> updateFileEntry("/base1/dir2/dir3",fe, age); + fe.name = "file12"; + fi -> updateFileEntry("/base1/dir2/dir3",fe, age); + + + fe.name = "dir4"; + fi -> updateDirEntry("/base3/",fe, age); + fe.name = "file20"; + fi -> updateFileEntry("/base3/dir4/",fe, age); + fe.name = "file21"; + fi -> updateFileEntry("/base3/dir4",fe, age); + + // one that will fail. + fe.name = "file20"; + fi -> updateFileEntry("/base3/",fe, age); + + fi -> printFileIndex(std::cout); + + return fi; +} + diff --git a/libretroshare/src/tests/dbase/searchtest.cc b/libretroshare/src/tests/dbase/searchtest.cc new file mode 100644 index 000000000..2bd4bffa0 --- /dev/null +++ b/libretroshare/src/tests/dbase/searchtest.cc @@ -0,0 +1,74 @@ +/* + * RetroShare FileCache Module: searchtest.cc + * + * Copyright 2004-2007 by Kefei Zhou. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "dbase/findex.h" +#include +#include + +int main() +{ + + std::cout << std::string::npos << std::endl; + std::string testfile = "searchtest.index"; + std::string fhash = "6851c28d99a6616a86942c3914476bf11997242a"; + FileIndex *fi = new FileIndex("DUMB ID"); + + // loading fileindex + std::cout << std::endl << "Test load" << std::endl; + fi->loadIndex(testfile, fhash, 1532); + fi->printFileIndex(std::cout); + std::cout << "FileIndex Loaded" << std::endl << std::endl; + + std::list hashresult; + std::list termresult; + + // searchhash + std::string findhash = "82bffa6e1cdf8419397311789391238174817481"; + + + std::cout << "Search hash : " << findhash << std::endl; + fi->searchHash(findhash, hashresult); + + while(!hashresult.empty()) + { + hashresult.back()->print(std::cout); + hashresult.pop_back(); + } + + // searchterm + std::list terms; + terms.push_back("paper"); + terms.push_back("doc"); + + std::cout << "Search terms" << std::endl; + fi->searchTerms(terms, termresult); + + while(!termresult.empty()) + { + termresult.back()->print(std::cout); + termresult.pop_back(); + } + + delete fi; + return 1; +} diff --git a/libretroshare/src/tests/ft/Makefile b/libretroshare/src/tests/ft/Makefile new file mode 100644 index 000000000..628c38f78 --- /dev/null +++ b/libretroshare/src/tests/ft/Makefile @@ -0,0 +1,54 @@ + +RS_TOP_DIR = ../.. +DHT_TOP_DIR = ../../../../libbitdht/src +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/config.mk +############################################################### + +TESTOBJ = ftfileprovidertest.o ftfilecreatortest.o ftextralisttest.o ftdataplextest.o fttransfermoduletest.o ftcrc32test.o ftcrossprovidercreatortest.o ftcontrollertest.o ftserver1test.o ftserver2test.o ftserver3test.o + +TESTS = ftfileprovidertest ftfilecreatortest ftextralisttest ftdataplextest fttransfermoduletest ftcrc32test ftcrossprovidercreatortest ftcontrollertest ftserver1test ftserver2test fttransfermoduletest ftserver3test + +all: tests + +ftcontrollertest : ftcontrollertest.o + $(CC) $(CFLAGS) -o ftcontrollertest ftcontrollertest.o $(LIBS) + +ftfilecreatortest : ftfilecreatortest.o + $(CC) $(CFLAGS) -o ftfilecreatortest ftfilecreatortest.o $(LIBS) + +ftcrossprovidercreatortest : ftcrossprovidercreatortest.o + $(CC) $(CFLAGS) -o ftcrossprovidercreatortest ftcrossprovidercreatortest.o $(LIBS) + +ftfileprovidertest : ftfileprovidertest.o + $(CC) $(CFLAGS) -o ftfileprovidertest ftfileprovidertest.o $(LIBS) + +fttransfermoduletest : fttransfermoduletest.o + $(CC) $(CFLAGS) -o fttransfermoduletest fttransfermoduletest.o $(LIBS) + +ftextralisttest : ftextralisttest.o + $(CC) $(CFLAGS) -o ftextralisttest ftextralisttest.o $(LIBS) + +ftdataplextest : ftdataplextest.o + $(CC) $(CFLAGS) -o ftdataplextest ftdataplextest.o $(LIBS) + +ftserver1test : ftserver1test.o + $(CC) $(CFLAGS) -o ftserver1test ftserver1test.o $(LIBS) + +ftserver2test : ftserver2test.o + $(CC) $(CFLAGS) -o ftserver2test ftserver2test.o $(LIBS) + +ftserver3test : ftserver3test.o + $(CC) $(CFLAGS) -o ftserver3test ftserver3test.o $(LIBS) + +ftcrc32test : ftcrc32test.o + $(CC) $(CFLAGS) -O0 -g -o ftcrc32test ftcrc32test.o $(LIBS) + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/rules.mk +############################################################### + + diff --git a/libretroshare/src/tests/ft/TestNotes.txt b/libretroshare/src/tests/ft/TestNotes.txt new file mode 100644 index 000000000..013fe879e --- /dev/null +++ b/libretroshare/src/tests/ft/TestNotes.txt @@ -0,0 +1,54 @@ + +Features that need to be tested, and which test checks it. +----------------------------------------------------------- + +(*) Transfer Related + +(*) Search Related + +(*) ExtraList Related + +(*) Cache Related + +(*) Config / Storage. + Change Config Directory works dynamically. (no restart required). + + +(*) Miscelleous + + + +----------------------------------------------------------- +----------------------------------------------------------- +Actual Tests, and what they check. +----------------------------------------------------------- + +ftserver1test.cc +================== + +Used to develop test framework. +Tests. + 1) Test Framework. OK + 2) File Indexing. OK + 3) Cache Packet Exchange. OK + 4) Cache downloads (including loopback). FAILS + 5) FileIndex Store loading. + 6) Basic Search. + +ftserver2test.cc +================== + +Test out the ExtraList functions. +Demonstrates the use of libretroshare/src/util/utest.h + +Tests. + 1) Load ExtraList path OK + 2) Hashing of ExtraList File OK + 3) ExtraHashDone. OK + 4) Local Search for ExtraList Data. OK + 5) Remote Search of ExtraList (should Fail) OK + 6) Transfer of ExtraList File (Local) TODO + 7) Transfer of ExtraList File (Remote) TODO + + + diff --git a/libretroshare/src/tests/ft/ftcontrollertest.cc b/libretroshare/src/tests/ft/ftcontrollertest.cc new file mode 100644 index 000000000..391bc3cd4 --- /dev/null +++ b/libretroshare/src/tests/ft/ftcontrollertest.cc @@ -0,0 +1,418 @@ +/* + * libretroshare/src/ft: ftserver1test.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* + * ftServer2Test - Demonstrates how to check for test stuff. + */ + +#include "retroshare/rsfiles.h" +#include "ft/ftserver.h" + +#include "ft/ftextralist.h" +#include "ft/ftdatamultiplex.h" +#include "ft/ftfilesearch.h" + +#include "pqi/p3authmgr.h" +#include "pqi/p3connmgr.h" + +#include "util/rsdebug.h" + +#include "pqitestor.h" +#include "util/rsdir.h" +#include "util/utest.h" + + +#include + + +class TestData +{ + public: + + ftServer *loadServer; + std::list otherServers; + std::list extraList; +}; + + +extern "C" void *do_server_test_thread(void *p); + + +void usage(char *name) +{ + std::cerr << "Usage: " << name << " [-sa] [-p ] [-d ] [-e ] [ [ ... ]] "; + std::cerr << std::endl; +} + +int main(int argc, char **argv) +{ + int c; + uint32_t period = 1; + uint32_t debugLevel = 5; + bool debugStderr = true; + bool loadAll = false; + + std::list fileList; + std::list extraList; + std::list peerIds; + std::map mFtServers; + std::map mConnMgrs; + + ftServer *mLoadServer = NULL; + std::list mOtherServers; + std::list::iterator eit; + + while(-1 != (c = getopt(argc, argv, "asd:p:e:"))) + { + switch (c) + { + case 'p': + peerIds.push_back(optarg); + break; + case 'd': + debugLevel = atoi(optarg); + break; + case 's': + debugStderr = true; + break; + case 'e': + extraList.push_back(optarg); + break; + case 'a': + loadAll = true; + break; + default: + usage(argv[0]); + break; + } + } + + /* do logging */ + setOutputLevel(debugLevel); + + if (optind >= argc) + { + std::cerr << "Missing Shared Directories" << std::endl; + usage(argv[0]); + } + + for(; optind < argc; optind++) + { + std::cerr << "Adding: " << argv[optind] << std::endl; + + SharedDirInfo info ; + info.shareflags = RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE ; + info.filename = std::string(argv[optind]); + info.virtualname = info.filename ; + + fileList.push_back(info) ; + } + + /* We need to setup a series 2 - 4 different ftServers.... + * + * Each one needs: + * + * + * A List of peerIds... + */ + + std::list::const_iterator it, jit; + + std::list baseFriendList, friendList; + std::list::iterator fit; + + P3Hub *testHub = new P3Hub(0,NULL); + testHub->start(); + + /* Setup Base Friend Info */ + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + pqiAuthDetails pad; + pad.id = *it; + pad.name = *it; + pad.trustLvl = 5; + pad.ownsign = true; + pad.trusted = false; + + baseFriendList.push_back(pad); + + std::cerr << "ftserver1test::setup peer: " << *it; + std::cerr << std::endl; + } + + std::ostringstream pname; + pname << "/tmp/rstst-" << time(NULL); + + std::string basepath = pname.str(); + RsDirUtil::checkCreateDirectory(basepath); + + + + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + friendList = baseFriendList; + /* remove current one */ + for(fit = friendList.begin(); fit != friendList.end(); fit++) + { + if (fit->id == *it) + { + friendList.erase(fit); + break; + } + } + + p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); + p3ConnectMgr *connMgr = new p3ConnectMgr(authMgr); + mConnMgrs[*it] = connMgr; + + + for(fit = friendList.begin(); fit != friendList.end(); fit++) + { + /* add as peer to authMgr */ + connMgr->addFriend(fit->id); + } + + P3Pipe *pipe = new P3Pipe(); //(*it); + + /* add server */ + ftServer *server; + server = new ftServer(connMgr); + mFtServers[*it] = server; + if (!mLoadServer) + { + mLoadServer = server; + } + else + { + mOtherServers.push_back(server); + } + + + server->setP3Interface(pipe); + + std::string configpath = basepath + "/" + *it; + RsDirUtil::checkCreateDirectory(configpath); + + std::string cachepath = configpath + "/cache"; + RsDirUtil::checkCreateDirectory(cachepath); + + std::string localpath = cachepath + "/local"; + RsDirUtil::checkCreateDirectory(localpath); + + std::string remotepath = cachepath + "/remote"; + RsDirUtil::checkCreateDirectory(remotepath); + + server->setConfigDirectory(configpath); + + NotifyBase *base = NULL; + server->SetupFtServer(base); + + testHub->addP3Pipe(*it, pipe, connMgr); + server->StartupThreads(); + + /* setup any extra bits */ + if (loadAll) + { + server->setSharedDirectories(fileList); + for(eit = extraList.begin(); eit != extraList.end(); eit++) + { + server->ExtraFileHash(*eit, 3600, 0); + } + } + + } + + if (mLoadServer) + { + mLoadServer->setSharedDirectories(fileList); + for(eit = extraList.begin(); eit != extraList.end(); eit++) + { + mLoadServer->ExtraFileHash(*eit, 3600, 0); + } + } + + + /* stick your real test here */ + std::map::iterator sit; + std::map::iterator cit; + + /* Start up test thread */ + pthread_t tid; + TestData *mFt = new TestData; + + /* set data */ + mFt->loadServer = mLoadServer; + mFt->otherServers = mOtherServers; + mFt->extraList = extraList; + + void *data = (void *) mFt; + pthread_create(&tid, 0, &do_server_test_thread, data); + pthread_detach(tid); /* so memory is reclaimed in linux */ + + while(1) + { + std::cerr << "ftserver2test::sleep()"; + std::cerr << std::endl; + sleep(1); + + /* tick the connmgrs */ + for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) + { + /* update */ + (sit->second)->tick(); + } + + for(cit = mConnMgrs.begin(); cit != mConnMgrs.end(); cit++) + { + /* update */ + (cit->second)->tick(); + } + } +} + +/* So our actual test can run here..... + * + */ + +INITTEST(); + +void *do_server_test_thread(void *data) +{ + TestData *mFt = (TestData *) data; + + std::cerr << "do_server_test_thread() running"; + std::cerr << std::endl; + + /************************* TEST 1 ********************** + * Check that the extra List has been processed. + */ + time_t start = time(NULL); + + FileInfo info, info2; + time_t now = time(NULL); + std::list::iterator eit; + for(eit = mFt->extraList.begin(); eit != mFt->extraList.end(); eit++) + { + while(!mFt->loadServer->ExtraFileStatus(*eit, info)) + { + + /* max of 30 seconds */ + now = time(NULL); + if (now - start > 30) + { + /* FAIL */ + REPORT2( false, "Extra File Hashing"); + } + + sleep(1); + } + + /* Got ExtraFileStatus */ + REPORT("Successfully Found ExtraFile"); + + /* now we can try a search (should succeed) */ + uint32_t hintflags = 0; + if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) + { + CHECK(info2.hash == info.hash); + CHECK(info2.size == info.size); + CHECK(info2.fname == info.fname); + } + else + { + REPORT2( false, "Search for Extra File (Basic)"); + } + + /* search with flags (should succeed) */ + hintflags = RS_FILE_HINTS_EXTRA; + if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) + { + CHECK(info2.hash == info.hash); + CHECK(info2.size == info.size); + CHECK(info2.fname == info.fname); + } + else + { + REPORT2( false, "Search for Extra File (Extra Flag)"); + } + + /* search with other flags (should fail) */ + hintflags = RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY; + if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) + { + REPORT2( false, "Search for Extra File (Fail Flags)"); + } + else + { + REPORT("Search for Extra File (Fail Flags)"); + } + + /* if we try to download it ... should just find existing one*/ + + REPORT("Testing with Extra File"); + } + + FINALREPORT("ExtraList Hashing, Searching and Downloading"); + + /************************* TEST 2 ********************** + * test ftController and ftTransferModule + */ + ftServer *server=mFt->loadServer; + + std::string fname,filehash,destination; + uint32_t size,flags; + std::list srcIds; + + /* select a file from otherServers */ + if (mFt->otherServers == NULL) + { + REPORT2(false,"No otherServers available"); + exit(1); + } + + DirDetails details; + flags = DIR_FLAGS_DETAILS | DIR_FLAGS_REMOTE; + void *ref = NULL; + + if(!server->RequestDirDetails(ref,details,flags)) + { + REPORT2(false,"fail to call RequestDirDetails"); + } + + if (details.type == DIR_TYPE_FILE) + { + REPORT("RemoteDirModel::downloadSelected() Calling File Request"); + std::list srcIds; + srcIds.push_back(details.id); + server->FileRequest(details.name, details.hash, + details.count, "", 0, srcIds); + } + + exit(1); +} + + + + diff --git a/libretroshare/src/tests/ft/ftcrc32test.cc b/libretroshare/src/tests/ft/ftcrc32test.cc new file mode 100644 index 000000000..fcdb8462e --- /dev/null +++ b/libretroshare/src/tests/ft/ftcrc32test.cc @@ -0,0 +1,117 @@ +/* + * libretroshare/src/ft: ftcrc32test.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include "retroshare/rstypes.h" +#include +#include + +#ifdef WIN32 +#include "util/rswin.h" +#endif + +#include "util/rsdir.h" + +void usage(char *name) +{ + std::cerr << "Computes a CRC32 map of a file." << std::endl; + std::cerr << "Usage: " << name << " -h " << std::endl; +} + +int main(int argc, char **argv) +{ + int c; + uint32_t period = 1; + uint32_t dPeriod = 600; /* default 10 minutes */ + + std::list hashList; + + while(-1 != (c = getopt(argc, argv, "f:h:"))) + { + switch (c) + { + case 'f': + hashList.push_back(std::string(optarg)); + break; + default: + usage(argv[0]); + break; + } + } + + uint32_t flags = 0; + for(std::list::const_iterator it(hashList.begin()); it != hashList.end(); it++) + { + std::cerr << "Hashing file :" << *it << std::endl ; + + std::string hash ; + RsDirUtil::hashFile( *it,hash) ; + + std::cerr << "Hash = " << hash << std::endl; + + FILE *f = fopen( (*it).c_str(),"rb" ) ; + + if(f == NULL) + { + std::cerr << "Could not open this file! Sorry." << std::endl ; + return 0 ; + } + CRC32Map crc_map ; + + if(fseek(f,0,SEEK_END)) + { + std::cerr << "Could not fseek to end of this file! Sorry." << std::endl ; + fclose(f) ; + return 0 ; + } + + uint64_t size = ftell(f) ; + + if(fseek(f,0,SEEK_SET)) + { + std::cerr << "Could not fseek to beginning of this file! Sorry." << std::endl ; + fclose(f) ; + return 0 ; + } + + std::cerr << "File size:" << size << std::endl ; + + RsDirUtil::crc32File(f,size,ChunkMap::CHUNKMAP_FIXED_CHUNK_SIZE,crc_map) ; + fclose(f) ; + + std::cerr << "Got this CRC map: "<< std::endl ; + + for(uint32_t i=0;i +#include "ft/ftfilecreator.h" + +#include "util/utest.h" +#include "util/rsdir.h" +#include + +#include "util/rswin.h" +#include "ft/ftserver.h" + +INITTEST(); + +static void createTmpFile(const std::string& name,uint64_t size,std::string& hash) ; +static void transfer(ftFileProvider *server, const std::string& server_peer_id,ftFileCreator *client,const std::string& client_peer_id) ; + +int main() +{ + // We create two file creators and feed them with a file both from elsewhere + // and from each others, as file providers. This test should check that no + // data race occurs while reading/writting data and exchanging chunks. The + // test is designed so that servers do not always have the required chunk, + // meaning that many requests can't be fullfilled. This is a good way to + // test if chunks availability is correctly handled. + + // 1 - Create a temporary file, compute its hash + // + std::string fname = "source_tmp.bin" ; + std::string fname_copy_1 = "copy_1_tmp.bin" ; + std::string fname_copy_2 = "copy_2_tmp.bin" ; + uint64_t size = 5560000 ; + std::string hash = "" ; + + pthread_t seed = 6;//getpid() ; + + std::cerr << "Seeding random generator with " << seed << std::endl ; + srand48(seed) ; + createTmpFile(fname,size,hash) ; + + // 2 - Create one file provider for this file, and 2 file creators + // + + ftFileProvider *server = new ftFileProvider(fname,size,hash) ; + ftFileCreator *client1 = new ftFileCreator(fname_copy_1,size,hash) ; + ftFileCreator *client2 = new ftFileCreator(fname_copy_2,size,hash) ; + + // 3 - Exchange chunks, and build two copies of the file. + // + std::string peer_id_1("client peer id 1") ; + std::string peer_id_2("client peer id 2") ; + std::string server_id("server peer id") ; + + while( !(client1->finished() && client2->finished())) + { + // 1 - select a random client, get the data from him. + + ftFileProvider *tmpserver ; + ftFileCreator *tmpclient ; + std::string tmpserver_pid ; + std::string tmpclient_pid ; + + // choose client and server, randomly, provided that they are not finished. + // + if((!client1->finished()) && (client2->finished() || (lrand48()&1))) + { + //std::cerr << "###### Client 1 asking to " ; + tmpclient = client1 ; + tmpclient_pid = peer_id_1 ; + + if(lrand48()&1) + { + //std::cerr << "Client 2 " ; + tmpserver = client2 ; + tmpserver_pid = peer_id_2 ; + } + else + { + //std::cerr << "Server "; + tmpserver = server ; + tmpserver_pid = server_id ; + } + } + else // client 2 is necessarily unfinished there. + { + //std::cerr << "###### Client 2 asking to " ; + tmpclient = client2 ; + tmpclient_pid = peer_id_2 ; + + if(lrand48()&1) + { + //std::cerr << "Client 1 " ; + tmpserver = client1 ; + tmpserver_pid = peer_id_1 ; + } + else + { + //std::cerr << "Server " ; + tmpserver = server ; + tmpserver_pid = server_id ; + } + + } + + // 2 - transfer from the server to the client. + + transfer(tmpserver,tmpserver_pid,tmpclient,tmpclient_pid) ; + + printf("Client1: %08lld, Client2: %08lld, transfer from %s to %s\r",client1->getRecvd(),client2->getRecvd(),tmpserver_pid.c_str(),tmpclient_pid.c_str()) ; + fflush(stdout) ; + } + + // hash the received data + + std::string hash1 ; client1->hashReceivedData(hash1) ; + std::string hash2 ; client2->hashReceivedData(hash2) ; + + std::cout << "Hash = " << hash << std::endl ; + std::cout << "Hash1 = " << hash1 << std::endl ; + std::cout << "Hash2 = " << hash2 << std::endl ; + + if(hash != hash1) FAILED("hashs 0/1 defer after transfer !") ; + if(hash != hash2) FAILED("hashs 0/2 defer after transfer !") ; + if(hash1 != hash2) FAILED("hashs 1/2 defer after transfer !") ; + + FINALREPORT("File transfer test"); + + return TESTRESULT(); +} + +void transfer(ftFileProvider *server, const std::string& server_peer_id,ftFileCreator *client,const std::string& client_peer_id) +{ + uint32_t size_hint = 128 + (lrand48()%8000) ; + uint64_t offset = 0; + uint32_t chunk_size = 0; + bool toOld = false ; + + //std::cerr << " for a pending chunk of size " << size_hint ; + + if(! client->getMissingChunk(server_peer_id, size_hint, offset, chunk_size, toOld)) + return ; + + //std::cerr << "###### Got chunk " << offset << ", size=" << chunk_size << std::endl ; + + void *data = malloc(chunk_size) ; + //std::cerr << "###### Asking data " << offset << ", size=" << chunk_size << std::endl ; + + if( server->getFileData(client_peer_id,offset,chunk_size,data) ) + { + client->addFileData(offset,chunk_size,data) ; + //std::cerr << "###### Added data " << offset << ", size=" << chunk_size << std::endl ; + } + + //std::cerr << ", completion=" << client->getRecvd() << std::endl ; + + // Normally this can't be true, because the ChunkMap class assumes availability for non turtle + // peers. + if(toOld) + { + //std::cerr << "###### Map is too old. Transferring" << std::endl ; + CompressedChunkMap map ; + server->getAvailabilityMap(map) ; + client->setSourceMap(server_peer_id,map) ; + } + free(data) ; +} + +void createTmpFile(const std::string& name,uint64_t S,std::string& hash) +{ + FILE *tmpf = fopen("source_tmp.bin","w") ; + + // write 1MB chunks + uint64_t C = 1024*1024 ; + uint8_t *data = new uint8_t[C] ; + + for(uint i=0;i<=S/C;++i) + { + int Cp = C ; + if(i==S/C) + { + if(S%C>0) + Cp = S%C ; + else + break ; + } + + for(int k=0;k &files); + + +void usage(char *name) +{ + std::cerr << "Usage: " << name << " [-p ] [-d ] [ ... ] "; + std::cerr << std::endl; +} + +int main(int argc, char **argv) +{ + int c; + uint32_t period = 1; + uint32_t dPeriod = 600; /* default 10 minutes */ + + std::list fileList; + + while(-1 != (c = getopt(argc, argv, "d:p:"))) + { + switch (c) + { + case 'p': + period = atoi(optarg); + break; + case 'd': + dPeriod = atoi(optarg); + break; + default: + usage(argv[0]); + break; + } + } + + if (optind >= argc) + { + std::cerr << "Missing Files" << std::endl; + usage(argv[0]); + } + + for(; optind < argc; optind++) + { + std::cerr << "Adding: " << argv[optind] << std::endl; + fileList.push_back(std::string(argv[optind])); + } + + ftExtraList *eList = new ftExtraList(); + eList->start(); + + ftSearch *ftsd = new ftSearchDummy(); + ftFileSearch *ftfs = new ftFileSearch(); + + ftfs-> addSearchMode(ftsd, RS_FILE_HINTS_LOCAL); + ftfs-> addSearchMode(eList, RS_FILE_HINTS_EXTRA); + + ftDataSend *ftds = new ftDataSendDummy(); + + /* setup Actual Test bit */ + ftDataMultiplex *ftmplex = new ftDataMultiplex("ownId", ftds, ftfs); + ftmplex->start(); + + /* Setup Search with some valid results */ + + + /* Request Data */ + + /* now work the thread */ + std::list::iterator it; + uint32_t flags = 0; + for(it = fileList.begin(); it != fileList.end(); it++) + { + eList->hashExtraFile(*it, dPeriod, flags); + } + + + /* now request files from ftDataMultiplex */ + + /* just request random data packets first */ + do_random_server_test(ftmplex, eList, fileList); +} + + + +uint32_t do_random_server_iteration(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) +{ + std::cerr << "do_random_server_iteration()"; + std::cerr << std::endl; + + std::list::iterator it; + uint32_t i = 0; + for(it = files.begin(); it != files.end(); it++) + { + FileInfo info; + if (eList->hashExtraFileDone(*it, info)) + { + std::cerr << "Hash Done for: " << *it; + std::cerr << std::endl; + std::cerr << info << std::endl; + + std::cerr << "Requesting Data Packet"; + std::cerr << std::endl; + + /* Server Recv */ + uint64_t offset = 10000; + uint32_t chunk = 20000; + mplex->recvDataRequest("Peer", info.hash, info.size, offset, chunk); + + i++; + } + else + { + std::cerr << "do_random_server_iteration() Hash Not Done for: " << *it; + std::cerr << std::endl; + } + } + + return i; + +} + + +void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) +{ + std::cerr << "do_random_server_test()"; + std::cerr << std::endl; + + uint32_t size = files.size(); + while(size > do_random_server_iteration(mplex, eList, files)) + { + std::cerr << "do_random_server_test() sleep"; + std::cerr << std::endl; + + sleep(10); + } +} + + diff --git a/libretroshare/src/tests/ft/ftextralisttest.cc b/libretroshare/src/tests/ft/ftextralisttest.cc new file mode 100644 index 000000000..f3fdf76aa --- /dev/null +++ b/libretroshare/src/tests/ft/ftextralisttest.cc @@ -0,0 +1,166 @@ +/* + * libretroshare/src/ft: ftextralisttest.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifdef WIN32 +#include "util/rswin.h" +#endif + +#include "ft/ftextralist.h" + +extern "C" void* runExtraList(void* p) +{ + ftExtraList *eList = (ftExtraList *) p; + if (!eList) + { + pthread_exit(NULL); + } + + while (1) + { + //eList->tick(); + sleep(1); + + } + + delete eList; + + pthread_exit(NULL); + + return NULL; +} + + + +void displayExtraListDetails(ftExtraList *eList, std::list toHash, std::list hashed); + + +void usage(char *name) +{ + std::cerr << "Usage: " << name << " -h -p -d "; + std::cerr << std::endl; +} + +int main(int argc, char **argv) +{ + int c; + uint32_t period = 1; + uint32_t dPeriod = 600; /* default 10 minutes */ + + std::list hashList; + + while(-1 != (c = getopt(argc, argv, "h:p:d:"))) + { + switch (c) + { + case 'h': + hashList.push_back(std::string(optarg)); + break; + case 'p': + period = atoi(optarg); + break; + case 'd': + dPeriod = atoi(optarg); + break; + default: + usage(argv[0]); + break; + } + } + + ftExtraList *eList = new ftExtraList(); + + /* now startup background thread to keep it reunning */ + eList->start(); + + + + /* now work the thread */ + std::list toHash; + std::list hashed; + std::list::iterator it; + + uint32_t flags = 0; + for(it = hashList.begin(); it != hashList.end(); it++) + { + sleep(period); + + /* load up file */ + //eList->addExtraFile(*it); + eList->hashExtraFile(*it, dPeriod, flags); + + toHash.push_back(*it); + + displayExtraListDetails(eList, toHash, hashed); + } + + for(int i=0;i<50;++i) + { + sleep(period); + + displayExtraListDetails(eList, toHash, hashed); + } +} + +void displayExtraListDetails(ftExtraList *eList, std::list toHash, std::list hashed) +{ + std::cerr << "displayExtraListDetails()"; + std::cerr << std::endl; + + std::list::iterator it; + for(it = toHash.begin(); it != toHash.end(); it++) + { + FileInfo info; + if (eList->hashExtraFileDone(*it, info)) + { + std::cerr << "displayExtraListDetails() Hash Completed for: " << *it; + std::cerr << std::endl; + std::cerr << info << std::endl; + } + else + { + std::cerr << "displayExtraListDetails() Hash Not Done for: " << *it; + std::cerr << std::endl; + } + } + + for(it = hashed.begin(); it != hashed.end(); it++) + { + FileInfo info; + if (eList->search(*it, 0, info)) + { + std::cerr << "displayExtraListDetails() Found Hash: " << *it; + std::cerr << std::endl; + std::cerr << info << std::endl; + } + else + { + std::cerr << "displayExtraListDetails() Hash Not Found: " << *it; + std::cerr << std::endl; + } + } +} + + + diff --git a/libretroshare/src/tests/ft/ftfilecreatortest.cc b/libretroshare/src/tests/ft/ftfilecreatortest.cc new file mode 100644 index 000000000..7c9d9ecbb --- /dev/null +++ b/libretroshare/src/tests/ft/ftfilecreatortest.cc @@ -0,0 +1,134 @@ +#include "ft/ftfilecreator.h" + +#include "util/utest.h" +#include + +#include "util/rswin.h" +#include "pqi/p3cfgmgr.h" +#include "pqi/p3connmgr.h" +#include "ft/ftserver.h" +#include "turtle/p3turtle.h" + +INITTEST(); + +static int test_timeout(ftFileCreator *creator); +static int test_fill(ftFileCreator *creator); + +int main() +{ + /* use ftcreator to create a file on tmp drive */ + ftFileCreator fcreator("/tmp/rs-ftfc-test.dta",100000,"hash", false); + + test_timeout(&fcreator); + test_fill(&fcreator); + + FINALREPORT("RsTlvItem Stack Tests"); + + return TESTRESULT(); +} + + +int test_timeout(ftFileCreator *creator) +{ + uint32_t chunk = 1000; + uint64_t offset = 0; + int max_timeout = 5; + int max_offset = chunk * max_timeout; + int i; + std::cerr << "60 second test of chunk queue."; + std::cerr << std::endl; + + uint32_t size_hint = 1000; + std::string peer_id = "dummyId"; + bool toOld = false; + + for(i = 0; i < max_timeout; i++) + { + creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld); + std::cerr << "Allocated Offset: " << offset << " chunk: " << chunk << std::endl; + + CHECK(offset <= max_offset); + // sleep(1); + } + + std::cerr << "Expect Repeats now"; + std::cerr << std::endl; + + for(i = 0; i < max_timeout; i++) + { + // sleep(1); + creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld); + std::cerr << "Allocated Offset: " << offset << " chunk: " << chunk << std::endl; + + CHECK(offset <= max_offset); + } + REPORT("Chunk Queue"); + + return 1; +} + + +int test_fill(ftFileCreator *creator) +{ + uint32_t chunk = 1000; + uint64_t offset = 0; + + uint64_t init_size = creator->getFileSize(); + uint64_t init_trans = creator->getRecvd(); + std::cerr << "Initial FileSize: " << init_size << std::endl; + std::cerr << "Initial Transferred:" << init_trans << std::endl; + + uint32_t size_hint = 1000; + std::string peer_id = "dummyId"; + bool toOld = false; + + while(creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld)) + { + if (chunk == 0) + { + std::cerr << "Missing Data already Alloced... wait"; + std::cerr << std::endl; + sleep(1); + chunk = 1000; + continue; + } + + /* give it to them */ + void *data = malloc(chunk); + /* fill with ascending numbers */ + for(int i = 0; i < chunk; i++) + { + ((uint8_t *) data)[i] = 'a' + i % 27; + if (i % 27 == 26) + { + ((uint8_t *) data)[i] = '\n'; + } + } + + creator->addFileData(offset, chunk, data); + free(data); +#ifndef WINDOWS_SYS +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + usleep(250000); /* 1/4 of sec */ +#else +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + Sleep(250); /* 1/4 of sec */ +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + chunk = 1000; /* reset chunk size */ + + } + + uint64_t end_size = creator->getFileSize(); + uint64_t end_trans = creator->getRecvd(); + std::cerr << "End FileSize: " << end_size << std::endl; + std::cerr << "End Transferred:" << end_trans << std::endl; + CHECK(init_size == end_size); + CHECK(end_trans == end_size); + + REPORT("Test Fill"); + + return 1; +} + diff --git a/libretroshare/src/tests/ft/ftfileprovidertest.cc b/libretroshare/src/tests/ft/ftfileprovidertest.cc new file mode 100644 index 000000000..2a12aa1ae --- /dev/null +++ b/libretroshare/src/tests/ft/ftfileprovidertest.cc @@ -0,0 +1,97 @@ +#include "ft/ftfileprovider.h" +#include "ft/ftfilecreator.h" + +#include "util/utest.h" +#include + +#include "util/rswin.h" + +INITTEST() + +int main() +{ + std::string ownId = "00000000000000000000000" ; + + /* create a random file */ + uint64_t size = 100000; + uint32_t max_chunk = 10000; + uint32_t chunk = 1000; + uint64_t offset = 0; + + std::string filename = "/tmp/ft_test.dta"; + std::string filename2 = "/tmp/ft_test.dta.dup"; + + /* use creator to make it */ + + void *data = malloc(max_chunk); + for(int i = 0; i < max_chunk; i++) + { + ((uint8_t *) data)[i] = 'a' + i % 27; + if (i % 27 == 26) + { + ((uint8_t *) data)[i] = '\n'; + } + } + + ftFileCreator *creator = new ftFileCreator(filename, size, "hash", true); + for(offset = 0; offset != size; offset += chunk) + { + if (!creator->addFileData(offset, chunk, data)) + { + FAILED("Create Test Data File"); + std::cerr << "Failed to add data (CREATE)"; + std::cerr << std::endl; + } + } + delete creator; + + std::cerr << "Created file: " << filename << " of size: " << size; + std::cerr << std::endl; + + /* load it with file provider */ + creator = new ftFileCreator(filename2, size, "hash", true); + ftFileProvider *provider = new ftFileProvider(filename, size, "hash"); + + /* create duplicate with file creator */ + std::string peer_id = "dummyId"; + uint32_t size_hint = 10000; + bool toOld = false; + + while(creator->getMissingChunk(peer_id, size_hint, offset, chunk, toOld)) + { + if (chunk == 0) + { + std::cerr << "All currently allocated .... waiting"; + std::cerr << std::endl; + sleep(1); + /* reset chunk size */ + chunk = (uint64_t) max_chunk * (rand() / (1.0 + RAND_MAX)); + std::cerr << "ChunkSize = " << chunk << std::endl; + continue; + } + + if (!provider->getFileData(ownId,offset, chunk, data)) + { + FAILED("Read from Test Data File"); + std::cerr << "Failed to get data"; + std::cerr << std::endl; + } + + if (!creator->addFileData(offset, chunk, data)) + { + FAILED("Write to Duplicate"); + std::cerr << "Failed to add data"; + std::cerr << std::endl; + } + + std::cerr << "Transferred: " << chunk << " @ " << offset; + std::cerr << std::endl; + + + /* reset chunk size */ + chunk = (uint64_t) max_chunk * (rand() / (1.0 + RAND_MAX)); + + std::cerr << "ChunkSize = " << chunk << std::endl; + } + return 1; +} diff --git a/libretroshare/src/tests/ft/ftserver1test.cc b/libretroshare/src/tests/ft/ftserver1test.cc new file mode 100644 index 000000000..d8d2f2461 --- /dev/null +++ b/libretroshare/src/tests/ft/ftserver1test.cc @@ -0,0 +1,329 @@ +/* + * libretroshare/src/ft: ftserver1test.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* + * Test for Whole Basic system..... + * + * Put it all together, and make it compile. + */ + +#ifdef WIN32 +#include "util/rswin.h" +#endif + +#include "ft/ftserver.h" + +#include "ft/ftextralist.h" +#include "ft/ftdatamultiplex.h" +#include "ft/ftfilesearch.h" + +#include "pqi/p3authmgr.h" +#include "pqi/p3connmgr.h" + +#include "util/rsdebug.h" + +#include "pqitestor.h" +#include "util/rsdir.h" + +#include + + + +void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files); + + +void usage(char *name) +{ + std::cerr << "Usage: " << name << " [-p ] [-d ] [ ... ] "; + std::cerr << std::endl; +} + +int main(int argc, char **argv) +{ + int c; + uint32_t period = 1; + uint32_t debugLevel = 5; + bool debugStderr = true; + + std::list fileList; + std::list peerIds; + std::map mFtServers; + std::map mConnMgrs; + +#ifdef PTW32_STATIC_LIB + pthread_win32_process_attach_np(); +#endif + +#ifdef WIN32 + // Windows Networking Init. + WORD wVerReq = MAKEWORD(2,2); + WSADATA wsaData; + + if (0 != WSAStartup(wVerReq, &wsaData)) + { + std::cerr << "Failed to Startup Windows Networking"; + std::cerr << std::endl; + } + else + { + std::cerr << "Started Windows Networking"; + std::cerr << std::endl; + } + +#endif + + + while(-1 != (c = getopt(argc, argv, "d:p:s"))) + { + switch (c) + { + case 'p': + peerIds.push_back(optarg); + break; + case 'd': + debugLevel = atoi(optarg); + break; + case 's': + debugStderr = true; + break; + default: + usage(argv[0]); + break; + } + } + + /* do logging */ + setOutputLevel(debugLevel); + + if (optind >= argc) + { + std::cerr << "Missing Files" << std::endl; + usage(argv[0]); + } + std::cerr << "Point 1" << std::endl; + + for(; optind < argc; optind++) + { + std::cerr << "Adding: " << argv[optind] << std::endl; + fileList.push_back(std::string(argv[optind])); + } + std::cerr << "Point 2" << std::endl; + + /* We need to setup a series 2 - 4 different ftServers.... + * + * Each one needs: + * + * + * A List of peerIds... + */ + + std::list::const_iterator it, jit; + + std::list baseFriendList, friendList; + std::list::iterator fit; + + std::cerr << "Point 3" << std::endl; + P3Hub *testHub = new P3Hub(0, NULL); + testHub->start(); + std::cerr << "Point 4" << std::endl; + + /* Setup Base Friend Info */ + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + pqiAuthDetails pad; + pad.id = *it; + pad.name = *it; + pad.trustLvl = 5; + pad.ownsign = true; + pad.trusted = false; + + baseFriendList.push_back(pad); + + std::cerr << "ftserver1test::setup peer: " << *it; + std::cerr << std::endl; + } + std::cerr << "Point 5" << std::endl; + + std::ostringstream pname; + pname << "/tmp/rstst-" << time(NULL); + + std::string basepath = pname.str(); + RsDirUtil::checkCreateDirectory(basepath); + + std::cerr << "Point 6" << std::endl; + + + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + friendList = baseFriendList; + /* remove current one */ + for(fit = friendList.begin(); fit != friendList.end(); fit++) + { + if (fit->id == *it) + { + friendList.erase(fit); + break; + } + } + + p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); + p3ConnectMgr *connMgr = new p3ConnectMgr(authMgr); + mConnMgrs[*it] = connMgr; + + + for(fit = friendList.begin(); fit != friendList.end(); fit++) + { + /* add as peer to authMgr */ + connMgr->addFriend(fit->id); + } + + P3Pipe *pipe = new P3Pipe(); //(*it); + + /* add server */ + ftServer *server; + server = new ftServer(authMgr, connMgr); + mFtServers[*it] = server; + + server->setP3Interface(pipe); + + std::string configpath = basepath + "/" + *it; + RsDirUtil::checkCreateDirectory(configpath); + + std::string cachepath = configpath + "/cache"; + RsDirUtil::checkCreateDirectory(cachepath); + + std::string partialspath = configpath + "/partials"; + RsDirUtil::checkCreateDirectory(partialspath); + + std::string downloadpath = configpath + "/downloads"; + RsDirUtil::checkCreateDirectory(downloadpath); + + std::string localpath = cachepath + "/local"; + RsDirUtil::checkCreateDirectory(localpath); + + std::string remotepath = cachepath + "/remote"; + RsDirUtil::checkCreateDirectory(remotepath); + + server->setConfigDirectory(configpath); + + //sleep(60); + + NotifyBase *base = NULL; + server->SetupFtServer(base); + + testHub->addP3Pipe(*it, pipe, connMgr); + server->StartupThreads(); + + /* setup any extra bits */ + server->setPartialsDirectory(partialspath); + server->setDownloadDirectory(downloadpath); + server->setSharedDirectories(fileList); + + } + + /* stick your real test here */ + std::map::iterator sit; + std::map::iterator cit; + + while(1) + { + std::cerr << "ftserver1test::sleep()"; + std::cerr << std::endl; + sleep(1); + + /* tick the connmgrs */ + for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) + { + /* update */ + (sit->second)->tick(); + } + + for(cit = mConnMgrs.begin(); cit != mConnMgrs.end(); cit++) + { + /* update */ + (cit->second)->tick(); + } + } +} + + +#if 0 + +uint32_t do_random_server_iteration(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) +{ + std::cerr << "do_random_server_iteration()"; + std::cerr << std::endl; + + std::list::iterator it; + uint32_t i = 0; + for(it = files.begin(); it != files.end(); it++) + { + FileInfo info; + if (eList->hashExtraFileDone(*it, info)) + { + std::cerr << "Hash Done for: " << *it; + std::cerr << std::endl; + std::cerr << info << std::endl; + + std::cerr << "Requesting Data Packet"; + std::cerr << std::endl; + + /* Server Recv */ + uint64_t offset = 10000; + uint32_t chunk = 20000; + mplex->recvDataRequest("Peer", info.hash, info.size, offset, chunk); + + i++; + } + else + { + std::cerr << "do_random_server_iteration() Hash Not Done for: " << *it; + std::cerr << std::endl; + } + } + + return i; + +} + + +void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files) +{ + std::cerr << "do_random_server_test()"; + std::cerr << std::endl; + + uint32_t size = files.size(); + while(size > do_random_server_iteration(mplex, eList, files)) + { + std::cerr << "do_random_server_test() sleep"; + std::cerr << std::endl; + + sleep(10); + } +} + + +#endif + diff --git a/libretroshare/src/tests/ft/ftserver2test.cc b/libretroshare/src/tests/ft/ftserver2test.cc new file mode 100644 index 000000000..173da6e1b --- /dev/null +++ b/libretroshare/src/tests/ft/ftserver2test.cc @@ -0,0 +1,429 @@ +/* + * libretroshare/src/ft: ftserver1test.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* + * ftServer2Test - Demonstrates how to check for test stuff. + * This tests hashing of files using extraList. + */ + +#ifdef WIN32 +#include "util/rswin.h" +#endif + + +#include "retroshare/rsfiles.h" +#include "ft/ftserver.h" + +#include "ft/ftextralist.h" +#include "ft/ftdatamultiplex.h" +#include "ft/ftfilesearch.h" + +#include "pqi/p3authmgr.h" +#include "pqi/p3connmgr.h" + +#include "util/rsdebug.h" + +#include "pqitestor.h" +#include "util/rsdir.h" +#include "util/utest.h" + + +#include + + +class TestData +{ + public: + + ftServer *loadServer; + std::list otherServers; + std::list extraList; +}; + + +extern "C" void *do_server_test_thread(void *p); + + +void usage(char *name) +{ + std::cerr << "Usage: " << name << " [-sa] [-p ] [-d ] [-e ] [ [ ... ]] "; + std::cerr << std::endl; +} + +int main(int argc, char **argv) +{ + int c; + uint32_t period = 1; + uint32_t debugLevel = 5; + bool debugStderr = true; + bool loadAll = false; + + std::list fileList; + std::list extraList; + std::list peerIds; + std::map mFtServers; + std::map mConnMgrs; + + ftServer *mLoadServer = NULL; + std::list mOtherServers; + std::list::iterator eit; + +#ifdef PTW32_STATIC_LIB + pthread_win32_process_attach_np(); +#endif + +#ifdef WIN32 + // Windows Networking Init. + WORD wVerReq = MAKEWORD(2,2); + WSADATA wsaData; + + if (0 != WSAStartup(wVerReq, &wsaData)) + { + std::cerr << "Failed to Startup Windows Networking"; + std::cerr << std::endl; + } + else + { + std::cerr << "Started Windows Networking"; + std::cerr << std::endl; + } + +#endif + + + while(-1 != (c = getopt(argc, argv, "asd:p:e:"))) + { + switch (c) + { + case 'p': + peerIds.push_back(optarg); + break; + case 'd': + debugLevel = atoi(optarg); + break; + case 's': + debugStderr = true; + break; + case 'e': + extraList.push_back(optarg); + break; + case 'a': + loadAll = true; + break; + default: + usage(argv[0]); + break; + } + } + + /* do logging */ + setOutputLevel(debugLevel); + + if (optind >= argc) + { + std::cerr << "Missing Shared Directories" << std::endl; + usage(argv[0]); + } + + for(; optind < argc; optind++) + { + std::cerr << "Adding: " << argv[optind] << std::endl; + SharedDirInfo info ; + info.shareflag = RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE ; + info.filename = string(argv[optind]); + info.virtualname = string(argv[optind]); + fileList.push_back(info) ; + } + + /* We need to setup a series 2 - 4 different ftServers.... + * + * Each one needs: + * + * + * A List of peerIds... + */ + + std::list::const_iterator it, jit; + + std::list baseFriendList, friendList; + std::list::iterator fit; + + + /* Add in serialiser */ + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + rss->addSerialType(new RsCacheItemSerialiser()); + rss->addSerialType(new RsServiceSerialiser()); + + + P3Hub *testHub = new P3Hub(0, rss); + testHub->start(); + + /* Setup Base Friend Info */ + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + pqiAuthDetails pad; + pad.id = *it; + pad.name = *it; + pad.trustLvl = 5; + pad.ownsign = true; + pad.trusted = false; + + baseFriendList.push_back(pad); + + std::cerr << "ftserver1test::setup peer: " << *it; + std::cerr << std::endl; + } + + std::ostringstream pname; + pname << "/tmp/rstst-" << time(NULL); + + std::string basepath = pname.str(); + RsDirUtil::checkCreateDirectory(basepath); + + + + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + friendList = baseFriendList; + /* remove current one */ + for(fit = friendList.begin(); fit != friendList.end(); fit++) + { + if (fit->id == *it) + { + friendList.erase(fit); + break; + } + } + + p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); + p3ConnectMgr *connMgr = new p3ConnectMgr(authMgr); + mConnMgrs[*it] = connMgr; + + + for(fit = friendList.begin(); fit != friendList.end(); fit++) + { + /* add as peer to authMgr */ + connMgr->addFriend(fit->id); + } + + P3Pipe *pipe = new P3Pipe(); //(*it); + + /* add server */ + ftServer *server; + server = new ftServer(authMgr, connMgr); + mFtServers[*it] = server; + if (!mLoadServer) + { + mLoadServer = server; + } + else + { + mOtherServers.push_back(server); + } + + + server->setP3Interface(pipe); + + std::string configpath = basepath + "/" + *it; + RsDirUtil::checkCreateDirectory(configpath); + + std::string cachepath = configpath + "/cache"; + RsDirUtil::checkCreateDirectory(cachepath); + + std::string partialspath = configpath + "/partials"; + RsDirUtil::checkCreateDirectory(partialspath); + + std::string downloadpath = configpath + "/downloads"; + RsDirUtil::checkCreateDirectory(downloadpath); + + std::string localpath = cachepath + "/local"; + RsDirUtil::checkCreateDirectory(localpath); + + std::string remotepath = cachepath + "/remote"; + RsDirUtil::checkCreateDirectory(remotepath); + + server->setConfigDirectory(configpath); + + NotifyBase *base = NULL; + server->SetupFtServer(base); + + testHub->addP3Pipe(*it, pipe, connMgr); + server->StartupThreads(); + + /* setup any extra bits */ + /* everyone gets download directories */ + server->setPartialsDirectory(partialspath); + server->setDownloadDirectory(downloadpath); + + if (loadAll) + { + server->setSharedDirectories(fileList); + for(eit = extraList.begin(); eit != extraList.end(); eit++) + { + server->ExtraFileHash(*eit, 3600, 0); + } + } + + } + + if (mLoadServer) + { + mLoadServer->setSharedDirectories(fileList); + for(eit = extraList.begin(); eit != extraList.end(); eit++) + { + mLoadServer->ExtraFileHash(*eit, 3600, 0); + } + } + + + /* stick your real test here */ + std::map::iterator sit; + std::map::iterator cit; + + /* Start up test thread */ + pthread_t tid; + TestData *mFt = new TestData; + + /* set data */ + mFt->loadServer = mLoadServer; + mFt->otherServers = mOtherServers; + mFt->extraList = extraList; + + void *data = (void *) mFt; + pthread_create(&tid, 0, &do_server_test_thread, data); + pthread_detach(tid); /* so memory is reclaimed in linux */ + + while(1) + { + std::cerr << "ftserver2test::sleep()"; + std::cerr << std::endl; + sleep(1); + + /* tick the connmgrs */ + for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) + { + /* update */ + (sit->second)->tick(); + } + + for(cit = mConnMgrs.begin(); cit != mConnMgrs.end(); cit++) + { + /* update */ + (cit->second)->tick(); + } + } +} + +/* So our actual test can run here..... + * + */ + +INITTEST(); + +void *do_server_test_thread(void *data) +{ + TestData *mFt = (TestData *) data; + + std::cerr << "do_server_test_thread() running"; + std::cerr << std::endl; + + /************************* TEST 1 ********************** + * Check that the extra List has been processed. + */ + time_t start = time(NULL); + + FileInfo info, info2; + time_t now = time(NULL); + std::list::iterator eit; + for(eit = mFt->extraList.begin(); eit != mFt->extraList.end(); eit++) + { + while(!mFt->loadServer->ExtraFileStatus(*eit, info)) + { + + /* max of 30 seconds */ + now = time(NULL); + if (now - start > 30) + { + /* FAIL */ + REPORT2( false, "Extra File Hashing"); + } + + sleep(1); + } + + /* Got ExtraFileStatus */ + REPORT("Successfully Found ExtraFile"); + + /* now we can try a search (should succeed) */ + uint32_t hintflags = 0; + if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) + { + CHECK(info2.hash == info.hash); + CHECK(info2.size == info.size); + CHECK(info2.fname == info.fname); + } + else + { + REPORT2( false, "Search for Extra File (Basic)"); + } + + /* search with flags (should succeed) */ + hintflags = RS_FILE_HINTS_EXTRA; + if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) + { + CHECK(info2.hash == info.hash); + CHECK(info2.size == info.size); + CHECK(info2.fname == info.fname); + } + else + { + REPORT2( false, "Search for Extra File (Extra Flag)"); + } + + /* search with other flags (should fail) */ + hintflags = RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY; + if (mFt->loadServer->FileDetails(info.hash, hintflags, info2)) + { + REPORT2( false, "Search for Extra File (Fail Flags)"); + } + else + { + REPORT("Search for Extra File (Fail Flags)"); + } + + /* if we try to download it ... should just find existing one*/ + + REPORT("Testing with Extra File"); + } + + FINALREPORT("ExtraList Hashing, Searching and Downloading"); + exit(1); +} + + + + diff --git a/libretroshare/src/tests/ft/ftserver3test.cc b/libretroshare/src/tests/ft/ftserver3test.cc new file mode 100644 index 000000000..f7110a967 --- /dev/null +++ b/libretroshare/src/tests/ft/ftserver3test.cc @@ -0,0 +1,469 @@ +/* + * libretroshare/src/ft: ftserver3test.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* + * ftServer3Test - Test of the file transfer from a server level. + * Steps: + * 1) load shared directories into others, and let them be + transferred between clients. + * 2) search for local item on others. + * 3) request item on load server. + should transfer from all others simultaneously. + */ + +#ifdef WIN32 +#include "util/rswin.h" +#endif + +#include "retroshare/rsexpr.h" + +#include "ft/ftserver.h" + +#include "ft/ftextralist.h" +#include "ft/ftdatamultiplex.h" +#include "ft/ftfilesearch.h" + +#include "pqi/p3authmgr.h" +#include "pqi/p3connmgr.h" + +#include "util/rsdebug.h" + +#include "pqitestor.h" +#include "util/rsdir.h" +#include "util/utest.h" + + +#include + + +class TestData +{ + public: + + ftServer *loadServer; + std::list otherServers; + std::list extraList; +}; + + +extern "C" void *do_server_test_thread(void *p); + + +void usage(char *name) +{ + std::cerr << "Usage: " << name << " [-soa] [-p ] [-d ] [-e ] [ [ ... ]] "; + std::cerr << std::endl; +} + +int main(int argc, char **argv) +{ + int c; + uint32_t period = 1; + uint32_t debugLevel = 5; + bool debugStderr = true; + bool loadAll = false; + bool loadOthers = false; + + std::list fileList; + std::list extraList; + std::list peerIds; + std::map mFtServers; + std::map mConnMgrs; + + ftServer *mLoadServer = NULL; + std::list mOtherServers; + std::list::iterator eit; + +#ifdef PTW32_STATIC_LIB + pthread_win32_process_attach_np(); +#endif + +#ifdef WIN32 + // Windows Networking Init. + WORD wVerReq = MAKEWORD(2,2); + WSADATA wsaData; + + if (0 != WSAStartup(wVerReq, &wsaData)) + { + std::cerr << "Failed to Startup Windows Networking"; + std::cerr << std::endl; + } + else + { + std::cerr << "Started Windows Networking"; + std::cerr << std::endl; + } + +#endif + + + while(-1 != (c = getopt(argc, argv, "aosd:p:e:"))) + { + switch (c) + { + case 'p': + peerIds.push_back(optarg); + break; + case 'd': + debugLevel = atoi(optarg); + break; + case 's': + debugStderr = true; + break; + case 'e': + extraList.push_back(optarg); + break; + case 'a': + loadAll = true; + break; + case 'o': + loadOthers = true; + break; + default: + usage(argv[0]); + break; + } + } + + /* do logging */ + setOutputLevel(debugLevel); + + if (optind >= argc) + { + std::cerr << "Missing Shared Directories" << std::endl; + usage(argv[0]); + } + + for(; optind < argc; optind++) + { + std::cerr << "Adding: " << argv[optind] << std::endl; + + SharedDirInfo info ; + info.filename = std::string(argv[optind]); + info.virtualname = info.filename ; + info.shareflags = RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE ; + + fileList.push_back(info) ; + } + + /* We need to setup a series 2 - 4 different ftServers.... + * + * Each one needs: + * + * + * A List of peerIds... + */ + + std::list::const_iterator it, jit; + + std::list baseFriendList, friendList; + std::list::iterator fit; + + /* Add in Serialiser Test + */ + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + rss->addSerialType(new RsCacheItemSerialiser()); + rss->addSerialType(new RsServiceSerialiser()); + + P3Hub *testHub = new P3Hub(0, rss); + testHub->start(); + + /* Setup Base Friend Info */ + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + pqiAuthDetails pad; + pad.id = *it; + pad.name = *it; + pad.trustLvl = 5; + pad.ownsign = true; + pad.trusted = false; + + baseFriendList.push_back(pad); + + std::cerr << "ftserver1test::setup peer: " << *it; + std::cerr << std::endl; + } + + std::ostringstream pname; + pname << "/tmp/rstst-" << time(NULL); + + std::string basepath = pname.str(); + RsDirUtil::checkCreateDirectory(basepath); + + + + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + friendList = baseFriendList; + /* remove current one */ + for(fit = friendList.begin(); fit != friendList.end(); fit++) + { + if (fit->id == *it) + { + friendList.erase(fit); + break; + } + } + + p3AuthMgr *authMgr = new p3DummyAuthMgr(*it, friendList); + p3ConnectMgr *connMgr = new p3ConnectMgr(authMgr); + mConnMgrs[*it] = connMgr; + + + for(fit = friendList.begin(); fit != friendList.end(); fit++) + { + /* add as peer to authMgr */ + connMgr->addFriend(fit->id); + } + + P3Pipe *pipe = new P3Pipe(); //(*it); + + /* add server */ + ftServer *server; + server = new ftServer(authMgr, connMgr); + mFtServers[*it] = server; + bool isOther; + if (!mLoadServer) + { + mLoadServer = server; + isOther = false; + } + else + { + mOtherServers.push_back(server); + isOther = true; + } + + + server->setP3Interface(pipe); + + std::string configpath = basepath + "/" + *it; + RsDirUtil::checkCreateDirectory(configpath); + + std::string cachepath = configpath + "/cache"; + RsDirUtil::checkCreateDirectory(cachepath); + + std::string partialspath = configpath + "/partials"; + RsDirUtil::checkCreateDirectory(partialspath); + + std::string downloadpath = configpath + "/downloads"; + RsDirUtil::checkCreateDirectory(downloadpath); + + std::string localpath = cachepath + "/local"; + RsDirUtil::checkCreateDirectory(localpath); + + std::string remotepath = cachepath + "/remote"; + RsDirUtil::checkCreateDirectory(remotepath); + + server->setConfigDirectory(configpath); + + NotifyBase *base = NULL; + server->SetupFtServer(base); + + testHub->addP3Pipe(*it, pipe, connMgr); + server->StartupThreads(); + + /* setup any extra bits */ + server->setPartialsDirectory(partialspath); + server->setDownloadDirectory(downloadpath); + + if ((loadAll) || (isOther && loadOthers)) + { + server->setSharedDirectories(fileList); + for(eit = extraList.begin(); eit != extraList.end(); eit++) + { + server->ExtraFileHash(*eit, 3600, 0); + } + } + + } + + if ((mLoadServer) && (!loadOthers)) + { + mLoadServer->setSharedDirectories(fileList); + for(eit = extraList.begin(); eit != extraList.end(); eit++) + { + mLoadServer->ExtraFileHash(*eit, 3600, 0); + } + } + + + /* stick your real test here */ + std::map::iterator sit; + std::map::iterator cit; + + /* Start up test thread */ + pthread_t tid; + TestData *mFt = new TestData; + + /* set data */ + mFt->loadServer = mLoadServer; + mFt->otherServers = mOtherServers; + mFt->extraList = extraList; + + void *data = (void *) mFt; + pthread_create(&tid, 0, &do_server_test_thread, data); + pthread_detach(tid); /* so memory is reclaimed in linux */ + + while(1) + { + //std::cerr << "ftserver3test::sleep()"; + //std::cerr << std::endl; + sleep(1); + + /* tick the connmgrs */ + for(sit = mFtServers.begin(); sit != mFtServers.end(); sit++) + { + /* update */ + (sit->second)->tick(); + } + + for(cit = mConnMgrs.begin(); cit != mConnMgrs.end(); cit++) + { + /* update */ + (cit->second)->tick(); + } + } +} + +/* So our actual test can run here..... + * + */ + +INITTEST(); + +void *do_server_test_thread(void *data) +{ + TestData *mFt = (TestData *) data; + time_t startTS = time(NULL); + + std::cerr << "do_server_test_thread() running"; + std::cerr << std::endl; + + /* search Others for a suitable file + * (Tests GUI search functionality) + */ + if (mFt->otherServers.size() < 1) + { + std::cerr << "no Other Servers to search on"; + std::cerr << std::endl; + exit(1); + return NULL; + } + + + for(int i = 0; i < 90; i++) + { + int age = time(NULL) - startTS; + std::cerr << "Waited " << age << " seconds to share caches"; + std::cerr << std::endl; + sleep(1); + } + + ftServer *oServer = *(mFt->otherServers.begin()); + std::string oId = oServer->OwnId(); + + /* create Expression */ + uint64_t minFileSize = 100000; + //SizeExpression se(Greater, minFileSize); + SizeExpression se(Smaller, minFileSize); + Expression *expr = &se; + + std::list results; + std::list::iterator it; + + oServer->SearchBoolExp(expr, results, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE); + + if (results.size() < 1) + { + std::cerr << "no Shared Files > " << minFileSize; + std::cerr << std::endl; + exit(1); + return NULL; + } + + /* find the first remote entry */ + DirDetails sFile; + bool foundFile = false; + for(it = results.begin(); (it != results.end()); it++) + { + std::cerr << "Shared File: " << it->name; + std::cerr << std::endl; + + if (!foundFile) + { + if (it->id != mFt->loadServer->OwnId()) + { + std::cerr << "Selected: " << it->name; + std::cerr << std::endl; + foundFile = true; + sFile = *it; + } + else + { + std::cerr << "LoadId: "; + std::cerr << mFt->loadServer->OwnId(); + std::cerr << "FileId: "; + std::cerr << it->id; + std::cerr << std::endl; + } + } + } + + if (!foundFile) + { + std::cerr << "Not Found Suitable File"; + std::cerr << std::endl; + } + + + /*** Now Download it! ***/ + std::list srcIds; + //srcIds.push_back(sFile.id); + // Don't add srcId - to test whether the search works - or not + //srcIds.push_back(oId); + if (foundFile) + { + mFt->loadServer->FileRequest(sFile.name, sFile.hash, + sFile.size, "", 0, srcIds); + } + + /* Give it a while to transfer */ + for(int i = 0; i < 100; i++) + { + int age = time(NULL) - startTS; + std::cerr << "Waited " << age << " seconds for tranfer"; + std::cerr << std::endl; + sleep(1); + } + + FINALREPORT("Shared Directories, Bool Search, multi-source transfers"); + exit(1); +} + + + + diff --git a/libretroshare/src/tests/ft/fttransfermoduletest.cc b/libretroshare/src/tests/ft/fttransfermoduletest.cc new file mode 100644 index 000000000..d1f06fd96 --- /dev/null +++ b/libretroshare/src/tests/ft/fttransfermoduletest.cc @@ -0,0 +1,180 @@ +/* + * libretroshare/src/ft: fttransfermoduletest.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* + * Test for Multiplexor..... + * As this is a key middle component, it is hard to test without other bits. + * It relies on ftFileProvider/ftFileCreator/ftTransferModule... + * + * And has dummy ftDataSend and ftSearch. + * + */ + +#ifdef WIN32 +#include "util/rswin.h" +#endif + +#include "ft/ftextralist.h" +#include "ft/ftdatamultiplex.h" +#include "ft/ftfilesearch.h" + +#include "ft/ftfileprovider.h" +#include "ft/ftfilecreator.h" +#include "ft/ftcontroller.h" +#include "ft/fttransfermodule.h" + +#include "util/utest.h" + +INITTEST() + + +void do_random_server_test(ftDataMultiplex *mplex, ftExtraList *eList, std::list &files); + + +void usage(char *name) +{ + std::cerr << "Usage: " << name << " [-p ] [-d ] [ ... ] "; + std::cerr << std::endl; +} + +int main(int argc, char **argv) +{ + int c; + uint32_t period = 1; + uint32_t dPeriod = 600; /* default 10 minutes */ + + std::list fileList; + + while(-1 != (c = getopt(argc, argv, "d:p:"))) + { + switch (c) + { + case 'p': + period = atoi(optarg); + break; + case 'd': + dPeriod = atoi(optarg); + break; + default: + usage(argv[0]); + break; + } + } + + if (optind >= argc) + { + std::cerr << "Missing Files" << std::endl; + usage(argv[0]); + } + + for(; optind < argc; optind++) + { + std::cerr << "Adding: " << argv[optind] << std::endl; + fileList.push_back(std::string(argv[optind])); + } + + ftExtraList *eList = new ftExtraList(); + eList->start(); + + ftSearch *ftsd = new ftSearchDummy(); + ftFileSearch *ftfs = new ftFileSearch(); + + ftfs-> addSearchMode(ftsd, RS_FILE_HINTS_LOCAL); + ftfs-> addSearchMode(eList, RS_FILE_HINTS_EXTRA); + + ftDataSendPair *ftds1 = new ftDataSendPair(NULL); + ftDataSendPair *ftds2 = new ftDataSendPair(NULL); + + /* setup Actual Test bit */ + ftDataMultiplex *ftmplex1 = new ftDataMultiplex("ownId", ftds2, ftfs); + ftDataMultiplex *ftmplex2 = new ftDataMultiplex("ownId", ftds1, ftfs); + + ftds1->mDataRecv = ftmplex1; + ftds2->mDataRecv = ftmplex2; + + ftmplex1->start(); + ftmplex2->start(); + + /* Setup Search with some valid results */ + /* Request Data */ + + /* now work the thread */ + std::list::iterator it; + uint32_t flags = 0; + for(it = fileList.begin(); it != fileList.end(); it++) + { + eList->hashExtraFile(*it, dPeriod, flags); + } + + if (fileList.size() < 1) + { + std::cerr << "come on, give us some files..."; + std::cerr << std::endl; + return 0; + } + + /* now request files from ftDataMultiplex + * by adding in a ftTransferModule! + */ + std::string filename = *(fileList.begin()); + + /* wait for file to hash */ + FileInfo info; + while(!eList->hashExtraFileDone(filename, info)) + { + std::cerr << "Waiting for file to hash"; + std::cerr << std::endl; + sleep(1); + } + + std::string savename = "/tmp/" + info.fname; + ftFileCreator *creator = new ftFileCreator(savename, info.size, info.hash); + ftController *controller = NULL; + + ftTransferModule *transfer = new ftTransferModule(creator, ftmplex1, controller); + + ftmplex1->addTransferModule(transfer, creator); + + std::list peerIds; + peerIds.push_back("ownId2"); + + transfer->setFileSources(peerIds); + transfer->setPeerState("ownId2", PQIPEER_IDLE, 1000); + //transfer->resumeTransfer(); + + /* check file progress */ + while(1) + { + std::cerr << "File Transfer Status"; + std::cerr << std::endl; + + std::cerr << "Transfered: " << creator->getRecvd(); + std::cerr << std::endl; + + transfer->tick(); + sleep(1); + } +} + diff --git a/libretroshare/src/tests/ft/pqitestor.cc b/libretroshare/src/tests/ft/pqitestor.cc new file mode 100644 index 000000000..85756c40b --- /dev/null +++ b/libretroshare/src/tests/ft/pqitestor.cc @@ -0,0 +1,444 @@ +/* + * libretroshare/src/ft: pqitestor.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "ft/pqitestor.h" +#include "pqi/p3connmgr.h" + +/****** + *#define HUB_DEBUG 1 + *****/ + +P3Hub::P3Hub(uint32_t flags, RsSerialiser *rss) + :mSerialiser(rss), mUseSerialiser(false) +{ + if (rss) + { + mUseSerialiser = true; + } + return; +} + +void P3Hub::addP3Pipe(std::string id, P3Pipe *pqi, p3ConnectMgr *mgr) +{ + hubItem item(id, pqi, mgr); + + std::map::iterator it; + for(it = mPeers.begin(); it != mPeers.end(); it++) + { + (it->second).mConnMgr->connectResult(id, true, 0); + mgr->connectResult(it->first, true, 0); + } + + mPeers[id] = item; + + /* tell all the other peers we are connected */ + +#ifdef HUB_DEBUG + std::cerr << "P3Hub::addPQIPipe()"; + std::cerr << std::endl; +#endif + +} + +RsItem *P3Hub::SerialiserPass(RsItem *inItem) +{ + /* pass through serialiser */ + + RsItem *item = NULL; + + uint32_t pktsize = mSerialiser->size(inItem); + void *ptr = malloc(pktsize); + +#ifdef HUB_DEBUG + std::cerr << "P3Hub::SerialiserPass() Expected Size: " << pktsize; + std::cerr << std::endl; +#endif + + if (!mSerialiser->serialise(inItem, ptr, &pktsize)) + { + +#ifdef HUB_DEBUG + std::cerr << "P3Hub::SerialiserPass() serialise Failed"; + std::cerr << std::endl; +#endif + + } + else + { + +#ifdef HUB_DEBUG + std::cerr << "P3Hub::SerialiserPass() serialise success, size: " << pktsize; + std::cerr << std::endl; +#endif + + item = mSerialiser->deserialise(ptr, &pktsize); + item->PeerId(inItem->PeerId()); + + if (!item) + { +#ifdef HUB_DEBUG + std::cerr << "P3Hub::SerialiserPass() deSerialise Failed"; + std::cerr << std::endl; +#endif + } + } + + delete inItem; + free(ptr); + return item; +} + + +void P3Hub::run() +{ +#ifdef HUB_DEBUG + std::cerr << "P3Hub::run()"; + std::cerr << std::endl; +#endif + + RsItem *item; + std::list > recvdQ; + std::list >::iterator lit; + while(1) + { +#ifdef HUB_DEBUG + std::cerr << "P3Hub::run()"; + std::cerr << std::endl; +#endif + + std::map::iterator it; + for(it = mPeers.begin(); it != mPeers.end(); it++) + { + while (NULL != (item = it->second.mPQI->PopSentItem())) + { +#ifdef HUB_DEBUG + std::cerr << "P3Hub::run() recvd msg from: "; + std::cerr << it->first; + std::cerr << " for " << item->PeerId(); + std::cerr << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + if (mUseSerialiser) + { + item = SerialiserPass(item); + } + + /* serialiser might hav munched it. */ + if (item) + { + recvdQ.push_back(make_pair(it->first, item)); + } + } + } + + /* now send out */ + for(lit = recvdQ.begin(); lit != recvdQ.end(); lit++) + { + std::string srcId = lit->first; + std::string destId = (lit->second)->PeerId(); + if (mPeers.end() == (it = mPeers.find(destId))) + { +#ifdef HUB_DEBUG + std::cerr << "Failed to Find destination: " << destId; + std::cerr << std::endl; + std::cerr << "Deleting Packet"; + std::cerr << std::endl; +#endif + + delete (lit->second); + + } + else + { + /* now we have dest, set source Id */ + (lit->second)->PeerId(srcId); +#ifdef HUB_DEBUG + std::cerr << "P3Hub::run() sending msg from: "; + std::cerr << srcId << "to: "; + std::cerr << destId; + std::cerr << std::endl; + (lit->second)->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + (it->second).mPQI->PushRecvdItem(lit->second); + } + } + + recvdQ.clear(); + + + + /* Tick the Connection Managers (normally done by rsserver) + */ + + /* sleep a bit */ +#ifdef WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } +} + + + + + + +PQIPipe::PQIPipe(std::string peerId) + :PQInterface(peerId) +{ + return; +} + +int PQIPipe::SendItem(RsItem *item) +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + mSentItems.push_back(item); + + return 1; +} + +RsItem *PQIPipe::PopSentItem() +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + if (mSentItems.size() == 0) + { + return NULL; + } + + RsItem *item = mSentItems.front(); + mSentItems.pop_front(); + + return item; +} + +int PQIPipe::PushRecvdItem(RsItem *item) +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + mRecvdItems.push_back(item); + + return 1; +} + +RsItem *PQIPipe::GetItem() +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + if (mRecvdItems.size() == 0) + { + return NULL; + } + + RsItem *item = mRecvdItems.front(); + mRecvdItems.pop_front(); + + return item; +} + + + + +/***** P3Pipe here *****/ + + + + +int P3Pipe::SendAllItem(RsItem *item) +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + mSentItems.push_back(item); + + return 1; +} + +RsItem *P3Pipe::PopSentItem() +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + if (mSentItems.size() == 0) + { + return NULL; + } + + RsItem *item = mSentItems.front(); + mSentItems.pop_front(); + + return item; +} + +int P3Pipe::PushRecvdItem(RsItem *item) +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + RsCacheRequest *rcr; + RsCacheItem *rci; + RsFileRequest *rfr; + RsFileData *rfd; + RsRawItem *rri; + + if (NULL != (rcr = dynamic_cast(item))) + { + mRecvdRsCacheRequests.push_back(rcr); + } + else if (NULL != (rci = dynamic_cast(item))) + { + mRecvdRsCacheItems.push_back(rci); + } + else if (NULL != (rfr = dynamic_cast(item))) + { + mRecvdRsFileRequests.push_back(rfr); + } + else if (NULL != (rfd = dynamic_cast(item))) + { + mRecvdRsFileDatas.push_back(rfd); + } + else if (NULL != (rri = dynamic_cast(item))) + { + mRecvdRsRawItems.push_back(rri); + } + + return 1; +} + +int P3Pipe::SearchSpecific(RsCacheRequest *item) +{ + SendAllItem(item); + return 1; +} + +int P3Pipe::SendSearchResult(RsCacheItem *item) +{ + SendAllItem(item); + return 1; +} + +int P3Pipe::SendFileRequest(RsFileRequest *item) +{ + SendAllItem(item); + return 1; +} + +int P3Pipe::SendFileData(RsFileData *item) +{ + SendAllItem(item); + return 1; +} + +int P3Pipe::SendRsRawItem(RsRawItem *item) +{ + SendAllItem(item); + return 1; +} + + // Cache Requests +RsCacheRequest *P3Pipe::RequestedSearch() +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + if (mRecvdRsCacheRequests.size() == 0) + { + return NULL; + } + + RsCacheRequest *item = mRecvdRsCacheRequests.front(); + mRecvdRsCacheRequests.pop_front(); + + return item; +} + + + // Cache Results +RsCacheItem *P3Pipe::GetSearchResult() +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + if (mRecvdRsCacheItems.size() == 0) + { + return NULL; + } + + RsCacheItem *item = mRecvdRsCacheItems.front(); + mRecvdRsCacheItems.pop_front(); + + return item; +} + + + // FileTransfer. +RsFileRequest *P3Pipe::GetFileRequest() +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + if (mRecvdRsFileRequests.size() == 0) + { + return NULL; + } + + RsFileRequest *item = mRecvdRsFileRequests.front(); + mRecvdRsFileRequests.pop_front(); + + return item; +} + + +RsFileData *P3Pipe::GetFileData() +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + if (mRecvdRsFileDatas.size() == 0) + { + return NULL; + } + + RsFileData *item = mRecvdRsFileDatas.front(); + mRecvdRsFileDatas.pop_front(); + + return item; +} + + +RsRawItem *P3Pipe::GetRsRawItem() +{ + RsStackMutex stack(pipeMtx); /***** LOCK MUTEX ****/ + + if (mRecvdRsRawItems.size() == 0) + { + return NULL; + } + + RsRawItem *item = mRecvdRsRawItems.front(); + mRecvdRsRawItems.pop_front(); + + return item; +} + diff --git a/libretroshare/src/tests/ft/pqitestor.h b/libretroshare/src/tests/ft/pqitestor.h new file mode 100644 index 000000000..d06cb66b2 --- /dev/null +++ b/libretroshare/src/tests/ft/pqitestor.h @@ -0,0 +1,161 @@ +/* + * libretroshare/src/ft: pqitestor.h + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef PQI_HUB_TEST_H +#define PQI_HUB_TEST_H + +/* + * pqi Test Interface. + */ + +/*** + * Structures for ftserver simulations + * + ****/ + +#include "pqi/pqi.h" +#include "util/rsthreads.h" + +#include + +class hubItem; +class PQIPipe; +class PQIHub; +class P3Pipe; +class P3Hub; +class p3ConnectMgr; + + +class hubItem +{ + public: + hubItem() + :mPQI(NULL), mConnMgr(NULL) { return; } + + hubItem(std::string id, P3Pipe *pqi, p3ConnectMgr *mgr) + :mPeerId(id), mPQI(pqi), mConnMgr(mgr) { return; } + + std::string mPeerId; + P3Pipe *mPQI; + p3ConnectMgr *mConnMgr; +}; + + +class P3Hub: public RsThread +{ + public: + + P3Hub(uint32_t flags, RsSerialiser *rss); +void addP3Pipe(std::string id, P3Pipe *, p3ConnectMgr *mgr); + +virtual void run(); + + private: + +RsItem* SerialiserPass(RsItem *inItem); + + std::map mPeers; + RsSerialiser *mSerialiser; + bool mUseSerialiser; +}; + + +class PQIPipe: public PQInterface +{ +public: + PQIPipe(std::string peerId); + +virtual int SendItem(RsItem *); +virtual RsItem *GetItem(); + + // PQIHub Interface. +RsItem *PopSentItem(); +int PushRecvdItem(RsItem *); + + /* + */ + +private: + + RsMutex pipeMtx; + + std::list mSentItems; + std::list mRecvdItems; + +}; + +class P3Pipe: public P3Interface +{ + public: + P3Pipe() {return; } + virtual ~P3Pipe() {return; } + + virtual int tick() { return 1; } + virtual int status() { return 1; } + + /* Overloaded from P3Interface */ + virtual int SearchSpecific(RsCacheRequest *item); + virtual int SendSearchResult(RsCacheItem *item); + virtual int SendFileRequest(RsFileRequest *item); + virtual int SendFileData(RsFileData *item); + virtual int SendRsRawItem(RsRawItem *item); + + virtual RsCacheRequest *RequestedSearch(); + virtual RsCacheItem *GetSearchResult(); + virtual RsFileRequest *GetFileRequest(); + virtual RsFileData *GetFileData(); + virtual RsRawItem *GetRsRawItem(); + + virtual RsFileChunkMapRequest* GetFileChunkMapRequest() ; + virtual int SendFileChunkMapRequest(RsFileChunkMapRequest*) ; + virtual RsFileChunkMap* GetFileChunkMap() ; + virtual int SendFileChunkMap(RsFileChunkMap*) ; + virtual RsFileCRC32MapRequest* GetFileCRC32MapRequest() ; + virtual int SendFileCRC32MapRequest(RsFileCRC32MapRequest*) ; + virtual RsFileCRC32Map* GetFileCRC32Map() ; + virtual int SendFileCRC32Map(RsFileCRC32Map*) ; + + /* Lower Interface for PQIHub */ + + RsItem *PopSentItem(); + int PushRecvdItem(RsItem *item); + + private: + + int SendAllItem(RsItem *item); + + RsMutex pipeMtx; + + std::list mSentItems; + + std::list mRecvdRsCacheRequests; + std::list mRecvdRsCacheItems; + std::list mRecvdRsFileRequests; + std::list mRecvdRsFileDatas; + std::list mRecvdRsRawItems; +}; + + +#endif diff --git a/libretroshare/src/tests/general/Makefile b/libretroshare/src/tests/general/Makefile new file mode 100644 index 000000000..fed684583 --- /dev/null +++ b/libretroshare/src/tests/general/Makefile @@ -0,0 +1,27 @@ + +RS_TOP_DIR = ../.. +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/config.mk +############################################################### + +TESTOBJ = netsetup_test.o random_test.o memory_management_test.o +TESTS = netsetup_test random_test memory_management_test + +all: tests + +netsetup_test: netsetup_test.o + $(CC) $(CFLAGS) -o netsetup_test netsetup_test.o $(LIBS) + +random_test: random_test.o + $(CC) $(CFLAGS) -o random_test random_test.o $(LIBS) + +memory_management_test: memory_management_test.o + $(CC) $(CFLAGS) -o memory_management_test memory_management_test.o $(LIBS) + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/tests/general/memory_management_test.cc b/libretroshare/src/tests/general/memory_management_test.cc new file mode 100644 index 000000000..2b680a293 --- /dev/null +++ b/libretroshare/src/tests/general/memory_management_test.cc @@ -0,0 +1,61 @@ +#ifdef LINUX +#include +#endif +#include +#include +#include +#include +#include "util/utest.h" +#include "serialiser/rsserial.h" + +INITTEST(); + +// Make a fake class of size n. +// +template class RsTestItem: public RsItem +{ + public: + unsigned char buff[n] ; + + RsTestItem(uint32_t s) : RsItem(s) {} + virtual void clear() {} + virtual std::ostream& print(std::ostream& o, uint16_t) { return o ; } +}; + +int main(int argc, char **argv) +{ +#ifdef LINUX + feenableexcept(FE_INVALID) ; + feenableexcept(FE_DIVBYZERO) ; +#endif + typedef RsTestItem<17> Test17 ; + typedef RsTestItem<31> Test31 ; + + std::vector v; + + for(int i=0;i<300;++i) + v.push_back(new Test17(0)) ; + for(int i=0;i<700;++i) + v.push_back(new Test31(0)) ; + + RsMemoryManagement::printStatistics() ; + + // Now delete objects randomly. + // + for(int i=0;i<1000;++i) + { + int indx = lrand48()%(int)v.size() ; + + delete v[indx] ; + v[indx] = v.back() ; + v.pop_back() ; + } + + std::cerr << "After memory free: " << std::endl; + + RsMemoryManagement::printStatistics() ; + + FINALREPORT("memory_management_test"); + exit(TESTRESULT()); +} + diff --git a/libretroshare/src/tests/general/netsetup_test.cc b/libretroshare/src/tests/general/netsetup_test.cc new file mode 100644 index 000000000..4c096ba74 --- /dev/null +++ b/libretroshare/src/tests/general/netsetup_test.cc @@ -0,0 +1,281 @@ + +#include "pqi/p3connmgr.h" +#include "pqi/p3authmgr.h" +#include "util/utest.h" + +#include "upnp/upnphandler.h" +#include "dht/opendhtmgr.h" +#include "tcponudp/tou.h" + + +INITTEST(); + +int end_test() +{ + FINALREPORT("net_test1"); + + exit(TESTRESULT()); +} + + +void printNetworkStatus(p3ConnectMgr *connMgr) +{ + std::cerr << "network status for : " << connMgr->getOwnId() << std::endl; + std::cerr << "Net Ok:" << connMgr->getNetStatusOk() << std::endl; + std::cerr << "Upnp Ok:" << connMgr->getNetStatusUpnpOk() << std::endl; + std::cerr << "DHT Ok:" << connMgr->getNetStatusDhtOk() << std::endl; + std::cerr << "Ext Ok:" << connMgr->getNetStatusExtOk() << std::endl; + std::cerr << "Udp Ok:" << connMgr->getNetStatusUdpOk() << std::endl; + std::cerr << "Tcp Ok:" << connMgr->getNetStatusTcpOk() << std::endl; + std::cerr << "network status for : " << connMgr->getOwnId() << std::endl; + + peerConnectState state; + if (connMgr->getOwnNetStatus(state)) + { + std::string txt = textPeerConnectState(state); + std::cerr << "State: " << txt << std::endl; + } + else + { + std::cerr << "No Net Status" << std::endl; + } +} + + +void setupTest(int i, p3ConnectMgr *cMgr) +{ + switch(i) + { + case 1: + { + /* Test One */ + + } + break; + + case 10: + { + /* Test One */ + + } + break; + + case 15: + { + /* Test One */ + + } + break; + + case 20: + { + /* Test One */ + + } + break; + + case 13: + { + /* Test One */ + + } + break; + + default: + std::cerr << "setupTest(" << i << ") no test here" << std::endl; + } +} + +void checkResults(int i, p3ConnectMgr *cMgr) +{ + switch(i) + { + /* Test One: Setup - without any support */ + case 1: + { + /* Expect UDP ports to be established by now */ + + //CHECK(isExternalNet(&loopback_addr)==false); + } + break; + + case 10: + { + /* Expect Local IP Address to be known */ + + } + break; + + case 15: + { + + REPORT("Basic Networking Setup"); + } + break; + + /* Test Two: DHT Running */ + case 111: + { + /* Expect UDP ports to be established by now */ + + //CHECK(isExternalNet(&loopback_addr)==false); + } + break; + + case 110: + { + /* Expect Local IP Address to be known */ + + } + break; + + /* Test 3: */ + case 145: + { + + } + break; + + case 100: + { + /* Test One */ + + } + break; + + case 5000: + { + /* End of Tests */ + end_test(); + } + break; + + default: + { + std::cerr << "checkResults(" << i << ") no test here" << std::endl; + printNetworkStatus(cMgr); + + } + } +} + +class TestMonitor: public pqiMonitor +{ + public: +virtual void statusChange(const std::list &plist) +{ + std::cerr << "TestMonitor::statusChange()"; + std::cerr << std::endl; + std::list::const_iterator it; + for(it = plist.begin(); it != plist.end(); it++) + { + std::cerr << "Event!"; + std::cerr << std::endl; + } +} + +}; + +int main(int argc, char **argv) +{ + /* options */ + bool enable_upnp = true; + bool enable_dht = true; + bool enable_forward = true; + + /* handle options */ + + int testtype = 1; + switch(testtype) + { + case 1: + /* udp test */ + enable_upnp = false; + enable_forward = false; + enable_dht = true; + break; + + } + + +#ifndef WINDOWS_SYS +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else + // Windows Networking Init. + WORD wVerReq = MAKEWORD(2,2); + WSADATA wsaData; + + if (0 != WSAStartup(wVerReq, &wsaData)) + { + std::cerr << "Failed to Startup Windows Networking"; + std::cerr << std::endl; + } + else + { + std::cerr << "Started Windows Networking"; + std::cerr << std::endl; + } + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + + std::string ownId = "OWNID"; + + /* create a dummy auth mgr */ + p3AuthMgr *authMgr = new p3DummyAuthMgr(); + p3ConnectMgr *connMgr = new p3ConnectMgr(authMgr); + + /* Setup Notify Early - So we can use it. */ + //rsNotify = new p3Notify(); + + pqiNetAssistFirewall *upnpMgr = NULL; + p3DhtMgr *dhtMgr = NULL; + + if (enable_upnp) + { + std::cerr << "Switching on UPnP" << std::endl; + upnpMgr = new upnphandler(); + connMgr->addNetAssistFirewall(1, upnpMgr); + } + + if (enable_dht) + { + p3DhtMgr *dhtMgr = new OpenDHTMgr(ownId, connMgr, "./"); + connMgr->addNetAssistConnect(1, dhtMgr); + + dhtMgr->start(); + std::cerr << "Switching on DHT" << std::endl; + dhtMgr->enable(true); + } + + + /**************************************************************************/ + /* need to Monitor too! */ + + TestMonitor *testmonitor = new TestMonitor(); + connMgr->addMonitor(testmonitor); + + connMgr->checkNetAddress(); + int i; + for(i=0; 1; i++) + { + connMgr->tick(); + + setupTest(i, connMgr); +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + sleep(1); +#else + Sleep(1000); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + connMgr->tick(); + + checkResults(i, connMgr); + + tou_tick_stunkeepalive(); + } +} + diff --git a/libretroshare/src/tests/general/random_test.cc b/libretroshare/src/tests/general/random_test.cc new file mode 100644 index 000000000..6232829ab --- /dev/null +++ b/libretroshare/src/tests/general/random_test.cc @@ -0,0 +1,162 @@ +#ifdef LINUX +#include +#endif +#include +#include +#include +#include +#include "util/utest.h" +#include "util/rsrandom.h" + +INITTEST(); +typedef double (* Ifctn)( double t); +/* Numerical integration method */ +double Simpson3_8( Ifctn f, double a, double b, int N) +{ + int j; + double l1; + double h = (b-a)/N; + double h1 = h/3.0; + double sum = f(a) + f(b); + + for (j=3*N-1; j>0; j--) { + l1 = (j%3)? 3.0 : 2.0; + sum += l1*f(a+h1*j) ; + } + return h*sum/8.0; +} + +#define A 12 +double Gamma_Spouge( double z ) +{ + int k; + static double cspace[A]; + static double *coefs = NULL; + double accum; + double a = A; + + if (!coefs) { + double k1_factrl = 1.0; + coefs = cspace; + coefs[0] = sqrt(2.0*M_PI); + for(k=1; k 2.0e-8) && (y < x)) y += .4; + if (y>x) y=x; + + return 1.0 - Simpson3_8( &f0, 0, y, std::max(5,(int)(y/h)))/Gamma_Spouge(a); +} + +double chi2Probability( int dof, double distance) +{ + return GammaIncomplete_Q( 0.5*dof, 0.5*distance); +} + +class myThread: public RsThread +{ + public: + myThread() + { + _finished = false ; + } + virtual void run() + { + // test that random numbers are regularly disposed + // + int N = 500 ; + int B = 8 ; + + std::vector buckets(B,0) ; + + for(int i=0;i significance) + std::cerr << ": passed" << std::endl ; + else + std::cerr << ": failed" << std::endl ; + + _finished = true ; + } + + bool finished() const { return _finished ; } + private: + bool _finished ; +}; + + +int main(int argc, char **argv) +{ +#ifdef LINUX + feenableexcept(FE_INVALID) ; + feenableexcept(FE_DIVBYZERO) ; +#endif + std::cerr << "Generating random 64 chars string (run that again to test that it's changing): " << RSRandom::random_alphaNumericString(64) << std::endl; + int nt = 10 ; // number of threads. + std::vector threads(nt,(myThread*)NULL) ; + + for(int i=0;istart() ; + } + + while(true) + { + bool finished = true ; + + for(int i=0;ifinished()) + finished = false ; + + if(finished) + break ; + } + for(int i=0;i +#include + +/******************************************************* + * + * Test structure + *****************/ + + +/* static test variables */ +uint32_t testCounter = 0; +pqiconnect *testConnectPointer[NUM_CONN_MAX]; +PQInterface *testConnectParent[NUM_CONN_MAX]; +uint32_t testConnectState[NUM_CONN_MAX]; +std::list testConnectTimes[NUM_CONN_MAX]; +std::list testConnectAddrs[NUM_CONN_MAX]; + +std::list testResetState[NUM_CONN_MAX]; +std::list testResetTimes[NUM_CONN_MAX]; + +uint32_t testConnectAction[NUM_CONN_MAX] = { 0 }; +time_t testConnectPeriod[NUM_CONN_MAX] = { 0 }; + +uint32_t defTestConnectAction = TST_ACTION_FAILED; + + +uint32_t findWhichConnect(pqiconnect *conn) +{ + int i; + for(i = 0; i < NUM_CONN_MAX; i++) + { + if (testConnectPointer[i] == conn) + { + return i; + } + } + // error. + std::cerr << "Connect Missing" << std::endl; + exit(1); + return 0; +} + +void addTestConnect(pqiconnect *pqi, PQInterface *parent) +{ + testConnectPointer[testCounter] = pqi; + testConnectParent[testCounter] = parent; + testConnectState[testCounter] = 0; + testCounter++; + if (testCounter > NUM_CONN_MAX) + { + std::cerr << "Too Many Connects" << std::endl; + exit(1); + } +} + +void resetTestConnects() +{ + testCounter = 0; + int i; + for(i = 0; i < NUM_CONN_MAX; i++) + { + testConnectAddrs[i].clear(); + testConnectTimes[i].clear(); + testResetState[i].clear(); + testResetTimes[i].clear(); + } +} + +/* setup callback actions */ +void setDefaultTestConnectAction(uint32_t action) +{ + defTestConnectAction = action; +} + +void forceConnect(uint32_t idx) +{ + /* flag as con */ +} + + +testConnect::testConnect(RsSerialiser *rss, NetBinInterface *ni_in) + :pqiconnect(rss, ni_in) +{ + +} + +testConnect::~testConnect() +{ + return; +} + + /* dummyConnect */ +int testConnect::connect(struct sockaddr_in raddr) +{ + int cidx = findWhichConnect(this); + time_t now = time(NULL); + + testConnectState[cidx] |= TST_STATE_CONNECT; + testConnectTimes[cidx].push_back(now); + testConnectAddrs[cidx].push_back(raddr); + testConnectAction[cidx] = defTestConnectAction; + + std::cerr << "testConnect[" << cidx << "].connect() called"; + std::cerr << std::endl; + return 0; +} + +int testConnect::listen() +{ + int cidx = findWhichConnect(this); + testConnectState[cidx] |= TST_STATE_LISTEN; + std::cerr << "testConnect[" << cidx << "].listen() called"; + std::cerr << std::endl; + return 1; +} + +int testConnect::stoplistening() +{ + int cidx = findWhichConnect(this); + testConnectState[cidx] &= ~TST_STATE_LISTEN; + std::cerr << "testConnect[" << cidx << "].stoplistening() called"; + std::cerr << std::endl; + return 1; +} + +int testConnect::reset() +{ + int cidx = findWhichConnect(this); + time_t now = time(NULL); + + // reset everything except listening. + testResetState[cidx].push_back(testConnectState[cidx]); + testResetTimes[cidx].push_back(now); + testConnectState[cidx] &= TST_STATE_LISTEN; + + std::cerr << "testConnect[" << cidx << "].reset() called"; + std::cerr << std::endl; + return 1; +} + +// leave this as is virtual int disconnect() { return ni -> reset(); } + +bool testConnect::connect_parameter(uint32_t type, uint32_t value) +{ + int cidx = findWhichConnect(this); + //testConnectState[cidx] |= TST_STATE_LISTEN; + std::cerr << "testConnect[" << cidx << "].connect_parameter() called"; + std::cerr << std::endl; + + /* sum up PERIOD and DELAY */ + if (type == NET_PARAM_CONNECT_DELAY) + { + std::cerr << "PARAMETER: DELAY: " << value; + std::cerr << std::endl; + + //testConnectPeriod[cidx] = value; + } + else if (type == NET_PARAM_CONNECT_PERIOD) + { + std::cerr << "PARAMETER: PERIOD: " << value; + std::cerr << std::endl; + + //testConnectPeriod[cidx] += value; + } + else if (type == NET_PARAM_CONNECT_TIMEOUT) + { + std::cerr << "PARAMETER: TIMEOUT: " << value; + std::cerr << std::endl; + + testConnectPeriod[cidx] = value; + //testConnectPeriod[cidx] += value; + } + std::cerr << "total testConnectPeriod: " << testConnectPeriod[cidx]; + std::cerr << std::endl; + + return true; +} + +int testConnect::getConnectAddress(struct sockaddr_in &raddr) +{ + int cidx = findWhichConnect(this); + if (testConnectAddrs[cidx].size() > 0) + { + raddr = testConnectAddrs[cidx].back(); + return 1; + } + std::cerr << "testConnect[" << cidx << "].getConnectAddress() called"; + std::cerr << std::endl; + return 0; +} + + +int testConnect::tick() +{ + int cidx = findWhichConnect(this); + + std::cerr << "testConnect[" << cidx << "].tick()"; + std::cerr << std::endl; + + if (testConnectState[cidx] & TST_STATE_CONNECT) + { + time_t now = time(NULL); + time_t cTime = testConnectTimes[cidx].back(); + if (now - cTime > testConnectPeriod[cidx]) + { + + std::cerr << "testConnect[" << cidx << "].tick() reached ConnectPeriod"; + std::cerr << " age: " << now - cTime << " period: " << testConnectPeriod[cidx]; + std::cerr << std::endl; + + PQInterface *connParent = testConnectParent[cidx]; + + testConnectState[cidx] &= ~TST_STATE_CONNECT; + /* do callback now */ + if (testConnectAction[cidx] == TST_ACTION_SUCCESS) + { + std::cerr << "testConnect[" << cidx << "].tick() CONNECTED callback"; + std::cerr << std::endl; + + testConnectState[cidx] &= ~TST_STATE_CONNECTED; + /* do callback */ + connParent -> notifyEvent(this->ni, NET_CONNECT_SUCCESS); + + } + else if (testConnectAction[cidx] == TST_ACTION_FAILED) + { + std::cerr << "testConnect[" << cidx << "].tick() FAILED callback"; + std::cerr << std::endl; + + /* do callback */ + connParent -> notifyEvent(this->ni, NET_CONNECT_FAILED); + + } + else + { + std::cerr << "testConnect[" << cidx << "].tick() no callback (BAD)"; + std::cerr << std::endl; + } + + } + } + return 0; +} + + + + + diff --git a/libretroshare/src/tests/pqi/conn_harness.h b/libretroshare/src/tests/pqi/conn_harness.h new file mode 100644 index 000000000..697faca99 --- /dev/null +++ b/libretroshare/src/tests/pqi/conn_harness.h @@ -0,0 +1,87 @@ +#ifndef TEST_PQICONNECT_H +#define TEST_PQICONNECT_H + +/* + * libretroshare/src/test/pqi testconnect.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqiperson.h" +//#include "pqi/pqibin.h" +#include "util/rsnet.h" + +/******************************************************* + * + * Test structure + *****************/ + + +#define NUM_CONN_MAX 50 + +#define TST_STATE_CONNECT 0x0001 +#define TST_STATE_LISTEN 0x0002 +#define TST_STATE_CONNECTED 0x0004 + +#define TST_ACTION_NONE 0x0000 +#define TST_ACTION_FAILED 0x0001 +#define TST_ACTION_SUCCESS 0x0002 + +/* static test variables */ +extern uint32_t testCounter; +extern pqiconnect *testConnectPointer[NUM_CONN_MAX]; +extern uint32_t testConnectState[NUM_CONN_MAX]; +extern std::list testConnectTimes[NUM_CONN_MAX]; +extern std::list testConnectAddrs[NUM_CONN_MAX]; + +extern std::list testResetState[NUM_CONN_MAX]; +extern std::list testResetTimes[NUM_CONN_MAX]; + +uint32_t findWhichConnect(pqiconnect *conn); +void addTestConnect(pqiconnect *pqi, PQInterface *parent); +void resetTestConnects(); + +void setDefaultTestConnectAction(uint32_t action); + +class testConnect: public pqiconnect +{ + public: + + testConnect(RsSerialiser *rss, NetBinInterface *ni_in); + virtual ~testConnect(); + + /* dummyConnect */ + virtual int tick(); + virtual int connect(struct sockaddr_in raddr); + virtual int listen(); + virtual int stoplistening(); + virtual int reset(); + virtual bool connect_parameter(uint32_t type, uint32_t value); + virtual int getConnectAddress(struct sockaddr_in &raddr); +}; // end of testConnect. + + +pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); + + +#endif + diff --git a/libretroshare/src/tests/pqi/conn_test.cc b/libretroshare/src/tests/pqi/conn_test.cc new file mode 100644 index 000000000..f80a6b7c8 --- /dev/null +++ b/libretroshare/src/tests/pqi/conn_test.cc @@ -0,0 +1,362 @@ + + +#include "pqi/p3connmgr.h" + + +/***** Test for the new DHT system *****/ + + +#include "util/rsnet.h" +#include "util/rsthreads.h" +#include "util/rsprint.h" +#include "pqi/p3dhtmgr.h" +#include "pqi/p3connmgr.h" +#include "pqi/pqisecurity.h" +#include "pqi/pqipersongrp.h" + +#include +#include + +#include "tcponudp/udpsorter.h" + +/***** Test Framework *****/ + +const int NumOfPeers = 10; +std::string peerIds[NumOfPeers] = + {"PEER01", + "PEER02", /* Always online, no notify */ + "PEER03", /* notify/online at 20sec */ + "PEER04", /* Always online, notify at 30 sec */ + "PEER05", + "PEER06", /* notify/online at 50sec */ + "PEER07", + "PEER08", + "PEER09", /* notify/online at 80sec */ + "PEER10"}; + +#define STUN_PORT 7777 + +std::string ownId = "OWNID-AAAA"; +time_t ownPublishTs; + +RsMutex frmMtx; +std::list searchIds; +std::list searchModes; + +std::map onlineMap; +std::map notifyMap; + +void initTestData() +{ + ownPublishTs = 0; + /* setup Peers that are online always */ + bool online; + uint32_t ts; + for(int i = 0; i < NumOfPeers; i++) + { + online = false; + if ((i == 1) || (i == 3)) + { + online = true; + } + onlineMap[peerIds[i]] = online; + + if ((i == 2) || (i == 3) || + (i == 5) || (i == 8)) + { + ts = i * 10; + notifyMap[ts] = peerIds[i]; + } + } +} + +void respondPublish() +{ + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + if (!ownPublishTs) + { + std::cerr << "Own ID first published!" << std::endl; + ownPublishTs = time(NULL); + } + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ +} + +void respondSearch(p3DhtMgr *mgr, std::string id, uint32_t mode) +{ + std::cerr << "Checking for Search Results" << std::endl; + time_t now = time(NULL); + bool doNotify = false; + bool doOnline = false; + std::string notifyId; + + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + if ((mode == DHT_MODE_NOTIFY) && (ownPublishTs)) + { + /* */ + std::map::iterator it; + uint32_t delta_t = now - ownPublishTs; + it = notifyMap.begin(); + if (it != notifyMap.end()) + { + if (it->first <= delta_t) + { + notifyId = it->second; + onlineMap[notifyId] = true; + notifyMap.erase(it); + doNotify = true; + } + } + } + else if (mode == DHT_MODE_SEARCH) + { + + /* translate */ + std::map::iterator mit; + for(mit = onlineMap.begin(); (mit != onlineMap.end()) && + (RsUtil::HashId(mit->first, false) != id); mit++); + + if (mit != onlineMap.end()) + { + doOnline = mit->second; + } + } + + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ + + uint32_t type = 0; + + struct sockaddr_in laddr; + inet_aton("10.0.0.129", &(laddr.sin_addr)); + laddr.sin_port = htons(7812); + laddr.sin_family = AF_INET; + + struct sockaddr_in raddr; + inet_aton("127.0.0.1", &(raddr.sin_addr)); + raddr.sin_port = htons(STUN_PORT); + raddr.sin_family = AF_INET; + + if (doNotify) + { + std::cerr << "Responding to Notify: id:" << notifyId << std::endl; + mgr->dhtResultNotify(RsUtil::HashId(notifyId, true)); + } + + if (doOnline) + { + std::cerr << "Responding to Search" << std::endl; + mgr->dhtResultSearch(id, laddr, raddr, type, ""); + } + +} + + +/***** Test Framework *****/ + +class DhtMgrTester: public p3DhtMgr +{ + + /* Implementation */ + public: + + DhtMgrTester(std::string id, pqiConnectCb *cb) + :p3DhtMgr(id, cb) + { + return; + } + + + + + + /* Blocking calls (only from thread) */ +virtual bool dhtPublish(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign) +{ + std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id); + std::cerr << " laddr: " << rs_inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port); + std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port); + std::cerr << " type: " << type << " sign: " << sign; + std::cerr << std::endl; + + respondPublish(); + + return true; +} + +virtual bool dhtNotify(std::string peerid, std::string ownid, std::string sign) +{ + std::cerr << "DhtMgrTester::dhtNotify() id: " << RsUtil::BinToHex(peerid) << ", ownId: " << RsUtil::BinToHex(ownId); + std::cerr << " sign: " << sign; + std::cerr << std::endl; + + return true; +} + +virtual bool dhtSearch(std::string id, uint32_t mode) +{ + std::cerr << "DhtMgrTester::dhtSearch(id: " << RsUtil::BinToHex(id) << ", mode: " << mode << ")" << std::endl; + + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + searchIds.push_back(id); + searchModes.push_back(mode); + frmMtx.unlock(); /* LOCK TEST FRAMEWORK MUTEX */ + + return true; +} + +}; + + +/* OVERLOAD THE ConnMgr - to insert peers */ +class p3TestConnMgr: public p3ConnectMgr +{ + public: + p3TestConnMgr(int mode) + :p3ConnectMgr(new p3DummyAuthMgr()), mTestMode(mode) { return; } + + protected: + /* must be virtual for testing */ +virtual void loadConfiguration() +{ + + /* setup own address */ + ownState.id = ownId; + ownState.name = "SELF NAME"; + ownState.localaddr.sin_family = AF_INET; + inet_aton("127.0.0.1", &(ownState.localaddr.sin_addr)); + ownState.localaddr.sin_port = htons(7812); + ownState.netMode = RS_NET_MODE_UDP; + ownState.visState = RS_VIS_STATE_STD; + + /* others not important */ + //ownState.state = 0; + //ownState.actions = 0; + + + if (mTestMode == 1) /* Add to Stun List */ + { + for(int i = 0; i < NumOfPeers; i++) + { + mStunList.push_back(peerIds[i]); + } + } + else if (mTestMode == 2) /* add to peers */ + { + /* add in as peers */ + //addPeer(); + for(int i = 0; i < NumOfPeers; i++) + { + if (i < 5) + { + mStunList.push_back(RsUtil::HashId(peerIds[i])); + } + else + { + addFriend(peerIds[i]); + } + } + } +} + + protected: + + uint32_t mTestMode; +}; + + +int main() +{ + time_t startTime = time(NULL); + /* setup system */ + initTestData(); + + /* setup a Stunner to respond to ConnMgr */ + + struct sockaddr_in saddr; + saddr.sin_family = AF_INET; + inet_aton("127.0.0.1", &(saddr.sin_addr)); + saddr.sin_port = htons(STUN_PORT); + UdpSorter stunner(saddr); /* starts a receiving thread */ + + p3TestConnMgr connMgr(2); + DhtMgrTester dhtTester(ownId, &connMgr); + + /* now add in some peers */ + connMgr.setDhtMgr(&dhtTester); + connMgr.setUpnpMgr(NULL); + + /************ ADD pqipersongrp as pqimonitor *****************/ + + SecurityPolicy *pol = secpolicy_create(); + unsigned long flags = 0; + pqipersongrp *pqipg = new pqipersongrpDummy(pol, flags); + + connMgr.addMonitor(pqipg); + + /************ ADD pqipersongrp as pqimonitor *****************/ + + + /* startup dht */ + std::cerr << "Starting up DhtTester()" << std::endl; + dhtTester.start(); + + /* wait for a little before switching on */ +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + sleep(1); +#else + Sleep(1000); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + std::cerr << "Switching on DhtTester()" << std::endl; + dhtTester.setDhtOn(true); + + /* wait loop */ + while(1) + { +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + sleep(1); +#else + Sleep(1000); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + connMgr.tick(); + pqipg->tick(); + + /* handle async search */ + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + + std::string id; + uint32_t mode; + bool doRespond = false; + if (searchIds.size() > 0) + { + id = searchIds.front(); + mode = searchModes.front(); + doRespond = true; + searchIds.pop_front(); + searchModes.pop_front(); + } + + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ + + if (doRespond) + { + respondSearch(&dhtTester, id, mode); + } + } +}; + + + + + + + + + + diff --git a/libretroshare/src/tests/pqi/dht_test.cc b/libretroshare/src/tests/pqi/dht_test.cc new file mode 100644 index 000000000..0fa76adfe --- /dev/null +++ b/libretroshare/src/tests/pqi/dht_test.cc @@ -0,0 +1,310 @@ + + +/***** Test for the new DHT system *****/ + + +#include "pqi/pqinetwork.h" + +#include "util/rsnet.h" +#include "util/rsthreads.h" +#include "util/rsprint.h" + +#include "pqi/p3dhtmgr.h" + +#include +#include + + +/***** Test Framework *****/ + +const int NumOfPeers = 10; +std::string peerIds[NumOfPeers] = + {"PEER01", + "PEER02", /* Always online, no notify */ + "PEER03", /* notify/online at 20sec */ + "PEER04", /* Always online, notify at 30 sec */ + "PEER05", + "PEER06", /* notify/online at 50sec */ + "PEER07", + "PEER08", + "PEER09", /* notify/online at 80sec */ + "PEER10"}; + +std::string ownId = "AAAA"; +time_t ownPublishTs; + +RsMutex frmMtx; +std::list searchIds; +std::list searchModes; + +std::map onlineMap; +std::map notifyMap; + +void initTestData() +{ + ownPublishTs = 0; + /* setup Peers that are online always */ + bool online; + uint32_t ts; + for(int i = 0; i < NumOfPeers; i++) + { + online = false; + if ((i == 1) || (i == 3)) + { + online = true; + } + onlineMap[peerIds[i]] = online; + + if ((i == 2) || (i == 3) || + (i == 5) || (i == 8)) + { + ts = i * 10; + notifyMap[ts] = peerIds[i]; + } + } +} + +void respondPublish() +{ + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + if (!ownPublishTs) + { + std::cerr << "Own ID first published!" << std::endl; + ownPublishTs = time(NULL); + } + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ +} + +void respondSearch(p3DhtMgr *mgr, std::string id, uint32_t mode) +{ + std::cerr << "Checking for Search Results" << std::endl; + time_t now = time(NULL); + bool doNotify = false; + bool doOnline = false; + std::string notifyId; + + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + if ((mode == DHT_MODE_NOTIFY) && (ownPublishTs)) + { + /* */ + std::map::iterator it; + uint32_t delta_t = now - ownPublishTs; + it = notifyMap.begin(); + if (it != notifyMap.end()) + { + if (it->first <= delta_t) + { + notifyId = it->second; + onlineMap[notifyId] = true; + notifyMap.erase(it); + doNotify = true; + } + } + } + else if (mode == DHT_MODE_SEARCH) + { + /* translate */ + std::map::iterator mit; + for(mit = onlineMap.begin(); (mit != onlineMap.end()) && + (RsUtil::HashId(mit->first, false) != id); mit++); + + if (mit != onlineMap.end()) + { + doOnline = mit->second; + } + } + + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ + + uint32_t type = 0; + + struct sockaddr_in laddr; + inet_aton("10.0.0.129", &(laddr.sin_addr)); + laddr.sin_port = htons(7812); + laddr.sin_family = AF_INET; + + struct sockaddr_in raddr; + inet_aton("10.0.0.19", &(raddr.sin_addr)); + raddr.sin_port = htons(7812); + raddr.sin_family = AF_INET; + + if (doNotify) + { + std::cerr << "Responding to Notify" << std::endl; + mgr->dhtResultNotify(RsUtil::HashId(notifyId, true)); + } + + if (doOnline) + { + std::cerr << "Responding to Search" << std::endl; + mgr->dhtResultSearch(id, laddr, raddr, type, ""); + } +} + + + + + + +/***** Test Framework *****/ + + + + +class DhtMgrTester: public p3DhtMgr +{ + + /* Implementation */ + public: + + DhtMgrTester(std::string id, pqiConnectCb *cb) + :p3DhtMgr(id, cb) + { + return; + } + + + /* Blocking calls (only from thread) */ +virtual bool dhtPublish(std::string id, + struct sockaddr_in &laddr, struct sockaddr_in &raddr, + uint32_t type, std::string sign) +{ + std::cerr << "DhtMgrTester::dhtPublish() id: " << RsUtil::BinToHex(id); + std::cerr << " laddr: " << rs_inet_ntoa(laddr.sin_addr) << " lport: " << ntohs(laddr.sin_port); + std::cerr << " raddr: " << rs_inet_ntoa(raddr.sin_addr) << " rport: " << ntohs(raddr.sin_port); + std::cerr << " type: " << type << " sign: " << sign; + std::cerr << std::endl; + + respondPublish(); + + return true; +} + +virtual bool dhtNotify(std::string peerid, std::string ownid, std::string sign) +{ + std::cerr << "DhtMgrTester::dhtNotify() id: " << RsUtil::BinToHex(peerid) << ", ownId: " << RsUtil::BinToHex(ownId); + std::cerr << " sign: " << sign; + std::cerr << std::endl; + + return true; +} + +virtual bool dhtSearch(std::string id, uint32_t mode) +{ + std::cerr << "DhtMgrTester::dhtSearch(id: " << RsUtil::BinToHex(id) << ", mode: " << mode << ")" << std::endl; + + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + searchIds.push_back(id); + searchModes.push_back(mode); + frmMtx.unlock(); /* LOCK TEST FRAMEWORK MUTEX */ + + return true; +} + +}; + +int main() +{ + time_t startTime = time(NULL); + bool haveOwnAddress = false; + /* setup system */ + initTestData(); + + pqiConnectCbDummy cbTester; + DhtMgrTester dhtTester(ownId, &cbTester); + + /* now add in some peers */ + + /* startup dht */ + std::cerr << "Starting up DhtTester()" << std::endl; + dhtTester.start(); + + /* wait for a little before switching on */ +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + sleep(1); +#else + Sleep(1000); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + std::cerr << "Switching on DhtTester()" << std::endl; + dhtTester.enable(true); + + std::cerr << "Adding a List of Peers" << std::endl; + for(int i = 0; i < NumOfPeers; i++) + { + dhtTester.findPeer(peerIds[i]); + } + + + /* wait loop */ + while(1) + { + std::cerr << "Main waiting..." << std::endl; +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + sleep(3); +#else + Sleep(3000); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + + /* handle async search */ + frmMtx.lock(); /* LOCK TEST FRAMEWORK MUTEX */ + + std::string id; + uint32_t mode; + bool doRespond = false; + if (searchIds.size() > 0) + { + id = searchIds.front(); + mode = searchModes.front(); + doRespond = true; + searchIds.pop_front(); + searchModes.pop_front(); + } + + frmMtx.unlock(); /* UNLOCK TEST FRAMEWORK MUTEX */ + + if (doRespond) + { + respondSearch(&dhtTester, id, mode); + } + + if (!haveOwnAddress) + { + if (time(NULL) - startTime > 20) + { + std::cerr << "Setting Own Address!" << std::endl; + haveOwnAddress = true; + + uint32_t type = DHT_ADDR_UDP; + + struct sockaddr_in laddr; + inet_aton("10.0.0.111", &(laddr.sin_addr)); + laddr.sin_port = htons(7812); + laddr.sin_family = AF_INET; + + struct sockaddr_in raddr; + inet_aton("10.0.0.11", &(raddr.sin_addr)); + raddr.sin_port = htons(7812); + raddr.sin_family = AF_INET; + + dhtTester.setExternalInterface(laddr, raddr, type); + } + } + + } +}; + + + + + + + + + + diff --git a/libretroshare/src/tests/pqi/dnsresolver_test.cc b/libretroshare/src/tests/pqi/dnsresolver_test.cc new file mode 100644 index 000000000..2a20ecc90 --- /dev/null +++ b/libretroshare/src/tests/pqi/dnsresolver_test.cc @@ -0,0 +1,83 @@ + +/* + * "$Id:$" + * + * RetroShare C++ Interface. + * + * Copyright 2010-2011 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#include "util/dnsresolver.h" + +#include +#include +#include + +int main() +{ + std::list names; + + DNSResolver *r = new DNSResolver ; + + names.push_back("cortinaire.inrialpes.fr") ; + names.push_back("www.google.com") ; + names.push_back("www.ego.cn") ; + names.push_back("free.fr") ; + + for(int i=0;i<5;++i) + { + for(std::list::const_iterator it = names.begin(); it != names.end(); it++) + { + in_addr addr ; + bool res = r->getIPAddressFromString(*it,addr) ; + + if(res) + std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << ": addr = " << (void*)addr.s_addr << std::endl; + else + std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << std::endl; + } + + std::cerr << std::endl; + usleep(200000) ; + } + + r->reset() ; + + for(int i=0;i<5;++i) + { + for(std::list::const_iterator it = names.begin(); it != names.end(); it++) + { + in_addr addr ; + bool res = r->getIPAddressFromString(*it,addr) ; + + if(res) + std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << ": addr = " << (void*)addr.s_addr << std::endl; + else + std::cerr << "Lookup of " << *it << ": " << (res?"done":"pending") << std::endl ; + } + std::cerr << std::endl; + usleep(200000) ; + } + + delete r ; +} + diff --git a/libretroshare/src/tests/pqi/extaddrfinder_test.cc b/libretroshare/src/tests/pqi/extaddrfinder_test.cc new file mode 100644 index 000000000..1ae234be0 --- /dev/null +++ b/libretroshare/src/tests/pqi/extaddrfinder_test.cc @@ -0,0 +1,37 @@ +#include "util/utest.h" + +#include +#include "pqi/pqinetwork.h" + +#include +#include + +INITTEST(); + +int main() +{ + std::cerr << "Testing the ext address finder service. This might take up to 10 secs..." << std::endl ; + + ExtAddrFinder fnd ; + in_addr addr ; + uint32_t tries = 0 ; + + while(! fnd.hasValidIP( &addr )) + { + sleep(1) ; + + if(++tries > 20) + { + std::cerr << "Failed !" << std::endl ; + CHECK(false) ; + } + } + + std::cerr << "Found the following IP: " << inet_ntoa(addr) << std::endl ; + + FINALREPORT("extaddrfinder_test"); + + return TESTRESULT() ; +} + + diff --git a/libretroshare/src/tests/pqi/gpgme_tst.c b/libretroshare/src/tests/pqi/gpgme_tst.c new file mode 100644 index 000000000..ec88a8439 --- /dev/null +++ b/libretroshare/src/tests/pqi/gpgme_tst.c @@ -0,0 +1,76 @@ + +#include "pqi/authgpg.h" + +const std::string key_path("./tmp/privkey.pem"); +const std::string passwd("8764"); +const std::string gpg_passwd("aaaa"); +const std::string name("Test X509"); +const std::string email("test@email.com"); +const std::string org("Org"); +const std::string loc("Loc"); +const std::string state("State"); +const std::string country("GB"); + +int main() +{ + /* Init the auth manager */ + + GPGAuthMgr mgr; + + + /* Select which GPG Keys we use */ + + /* print all keys */ + mgr.printKeys(); + + std::list idList; + mgr.availablePGPCertificates(idList); + + if (idList.size() < 1) + { + fprintf(stderr, "No GPG Certificate to use!\n"); + exit(1); + } + std::string id = idList.front(); + fprintf(stderr, "Using GPG Certificate:%s \n", id.c_str()); + + std::string noname; + mgr.GPGInit(id); + mgr.LoadGPGPassword(gpg_passwd); + + /* Init SSL library */ + mgr.InitAuth(NULL, NULL, NULL); + + /* then try to generate and sign a X509 certificate */ + int nbits_in = 2048; + std::string errString; + + /* Generate a Certificate Request */ + X509_REQ *req = GenerateX509Req(key_path, passwd, name, email, org, + loc, state, country, nbits_in, errString); + + // setup output. + BIO *bio_out = NULL; + bio_out = BIO_new(BIO_s_file()); + BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); + + /* Print it out */ + int nmflag = 0; + int reqflag = 0; + + X509_REQ_print_ex(bio_out, req, nmflag, reqflag); + + X509 *x509 = mgr.SignX509Req(req, 100, gpg_passwd); + + X509_print_ex(bio_out, x509, nmflag, reqflag); + + BIO_flush(bio_out); + BIO_free(bio_out); + + /* now try to validate it */ + mgr.AuthX509(x509); + + //sleep(10); +} + + diff --git a/libretroshare/src/tests/pqi/net_test.cc b/libretroshare/src/tests/pqi/net_test.cc new file mode 100644 index 000000000..6056be712 --- /dev/null +++ b/libretroshare/src/tests/pqi/net_test.cc @@ -0,0 +1,320 @@ +/* + * libretroshare/src/test/pqi net_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * NETWORKING Test to check Big/Little Endian behaviour + * as well as socket behaviour + * + */ + +#include "util/utest.h" + +#include "pqi/pqinetwork.h" +#include "util/rsnet.h" +#include +#include + + +bool test_byte_manipulation(); +bool test_local_address_manipulation(); +bool test_address_listen(); + + +INITTEST(); + +int main(int argc, char **argv) +{ + std::cerr << "libretroshare:pqi " << argv[0] << std::endl; + + test_byte_manipulation(); + test_local_address_manipulation(); + test_address_listen(); + + FINALREPORT("libretroshare Net Basics Tests"); + return TESTRESULT(); +} + + /* test 1: byte manipulation */ +bool test_byte_manipulation() +{ + uint64_t num1 = 0x0000000000000000ffULL; /* 255 */ + uint64_t num2 = 0x00000000000000ff00ULL; /* */ + + uint64_t n_num1 = htonll(num1); + uint64_t n_num2 = htonll(num2); + + uint64_t h_num1 = ntohll(n_num1); + uint64_t h_num2 = ntohll(n_num2); + + std::ostringstream out; + out << std::hex; + out << "num1: " << num1 << " netOrder: " << n_num1 << " hostOrder: " << h_num1 << std::endl; + out << "num2: " << num2 << " netOrder: " << n_num2 << " hostOrder: " << h_num2 << std::endl; + + std::cerr << out.str(); + + CHECK( num1 == h_num1 ); + CHECK( num2 == h_num2 ); + + REPORT("Test Byte Manipulation"); + + return true; +} + +const char * loopback_addrstr = "127.0.0.1"; +const char * localnet1_addrstr = "192.168.0.1"; +const char * localnet2_addrstr = "10.0.0.1"; +const char * localnet3_addrstr = "10.5.63.78"; +const char * localnet4_addrstr = "192.168.74.91"; + + /* test 2: address manipulation */ +bool test_local_address_manipulation() +{ + struct sockaddr_in loopback_addr; + struct sockaddr_in localnet1_addr; + struct sockaddr_in localnet2_addr; + struct sockaddr_in localnet3_addr; + struct sockaddr_in localnet4_addr; + + std::cerr << "test_local_address_manipulation() NB: This function demonstrates "; + std::cerr << "the strange behaviour of inet_netof() and inet_network()"; + std::cerr << std::endl; + std::cerr << "FAILures are not counted in the test!"; + std::cerr << std::endl; + + /* setup some addresses */ + inet_aton(loopback_addrstr, &(loopback_addr.sin_addr)); + inet_aton(localnet1_addrstr, &(localnet1_addr.sin_addr)); + inet_aton(localnet2_addrstr, &(localnet2_addr.sin_addr)); + inet_aton(localnet3_addrstr, &(localnet3_addr.sin_addr)); + inet_aton(localnet4_addrstr, &(localnet4_addr.sin_addr)); + + + std::cerr << "Loopback Addr " << rs_inet_ntoa(loopback_addr.sin_addr); + std::cerr << std::endl; + + std::cerr << "Localnet1 Addr " << rs_inet_ntoa(localnet1_addr.sin_addr); + std::cerr << std::endl; + std::cerr << "Localnet2 Addr " << rs_inet_ntoa(localnet2_addr.sin_addr); + std::cerr << std::endl; + std::cerr << "Localnet3 Addr " << rs_inet_ntoa(localnet3_addr.sin_addr); + std::cerr << std::endl; + std::cerr << "Localnet4 Addr " << rs_inet_ntoa(localnet4_addr.sin_addr); + std::cerr << std::endl; + std::cerr << std::endl; + + std::cerr << "Test 1a - networks"; + std::cerr << std::endl; + + struct sockaddr_in addr_ans, addr1, addr2; + std::string addr_ans_str; + + addr_ans_str = "127.0.0.0"; + inet_aton(addr_ans_str.c_str(), &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = htonl(inet_netof(loopback_addr.sin_addr)); + addr2.sin_addr.s_addr = htonl(inet_network(loopback_addrstr)); + + std::cerr << "Loopback Net(expected): " << addr_ans_str; + std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr))); + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr))); + + + addr_ans_str = "192.168.0.0"; + inet_aton(addr_ans_str.c_str(), &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = htonl(inet_netof(localnet1_addr.sin_addr)); + addr2.sin_addr.s_addr = htonl(inet_network(localnet1_addrstr)); + + std::cerr << "Localnet1 Net(expected): " << addr_ans_str; + std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr))); + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr))); + + addr_ans_str = "10.0.0.0"; + inet_aton(addr_ans_str.c_str(), &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = htonl(inet_netof(localnet2_addr.sin_addr)); + addr2.sin_addr.s_addr = htonl(inet_network(localnet2_addrstr)); + + std::cerr << "Localnet2 Net(expected): " << addr_ans_str; + std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr))); + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr))); + + + addr_ans_str = "10.0.0.0"; + inet_aton(addr_ans_str.c_str(), &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = htonl(inet_netof(localnet3_addr.sin_addr)); + addr2.sin_addr.s_addr = htonl(inet_network(localnet3_addrstr)); + + std::cerr << "Localnet3 Net(expected): " << addr_ans_str; + std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr))); + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr))); + + + addr_ans_str = "192.168.0.0"; + inet_aton(addr_ans_str.c_str(), &(addr_ans.sin_addr)); + addr1.sin_addr.s_addr = htonl(inet_netof(localnet4_addr.sin_addr)); + addr2.sin_addr.s_addr = htonl(inet_network(localnet4_addrstr)); + + std::cerr << "Localnet4 Net(expected): " << addr_ans_str; + std::cerr << " -> " << rs_inet_ntoa(addr_ans.sin_addr); + std::cerr << " Net(1):" << rs_inet_ntoa(addr1.sin_addr); + std::cerr << " Net(2):" << rs_inet_ntoa(addr2.sin_addr); + std::cerr << std::endl; + + + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr1.sin_addr))); + //CHECK( 0 == strcmp(addr_ans_str.c_str(), rs_inet_ntoa(addr2.sin_addr))); + + REPORT("Test Local Address Manipulation"); + return true; +} + + + +#if 0 + +std::ostream &showSocketError(std::ostream &out); + +std::string socket_errorType(int err); +int sockaddr_cmp(struct sockaddr_in &addr1, struct sockaddr_in &addr2 ); +int inaddr_cmp(struct sockaddr_in addr1, struct sockaddr_in addr1 ); +int inaddr_cmp(struct sockaddr_in addr1, unsigned long); + +std::list getLocalInterfaces(); // returns all possible addrs. +bool isExternalNet(struct in_addr *addr); // if Valid & is not Private or Loopback. +bool isPrivateNet(struct in_addr *addr); // if inside 10.0.0.0 or + // other then firewalled. +bool isLoopbackNet(struct in_addr *addr); +bool sameNet(struct in_addr *addr, struct in_addr *addr2); +bool isValidNet(struct in_addr *addr); + + // checks (addr1 & 255.255.255.0) == (addr2 & 255.255.255.0) +bool isSameSubnet(struct in_addr *addr1, struct in_addr *addr2); + + +struct in_addr getPreferredInterface(); // returns best addr. + +in_addr_t pqi_inet_netof(struct in_addr addr); // our implementation. + +bool LookupDNSAddr(std::string name, struct sockaddr_in &addr); + +/* universal socket interface */ + +int unix_close(int sockfd); +int unix_socket(int domain, int type, int protocol); +int unix_fcntl_nonblock(int sockfd); +int unix_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); +int unix_getsockopt_error(int sockfd, int *err); + +#endif + + +bool test_bind_addr(struct sockaddr_in addr); + +bool test_address_listen() +{ + struct sockaddr_in addr1, addr2, addr3; + + sockaddr_clear(&addr1); + addr1.sin_family = AF_INET; + inet_aton(loopback_addrstr, &(addr1.sin_addr)); + addr1.sin_port = htons(12345); + + sockaddr_clear(&addr2); + addr2.sin_family = AF_INET; + getPreferredInterface(addr2.sin_addr); // returns best addr. + addr2.sin_port = htons(13245); + + sockaddr_clear(&addr3); + addr3.sin_family = AF_INET; + getPreferredInterface(addr3.sin_addr); // returns best addr. + addr3.sin_port = htons(23451); + + /* test bind to loopback, and preferred interfaces */ + test_bind_addr(addr1); + test_bind_addr(addr2); + test_bind_addr(addr3); + + + + REPORT("Test Address Listen"); + return true; +} + +bool test_bind_addr(struct sockaddr_in addr) +{ + + int err; + + std::cerr << "test_bind_addr()"; + std::cerr << std::endl; + + std::cerr << "\tAddress Family: " << (int) addr.sin_family; + std::cerr << std::endl; + std::cerr << "\tAddress: " << rs_inet_ntoa(addr.sin_addr); + std::cerr << std::endl; + std::cerr << "\tPort: " << ntohs(addr.sin_port); + std::cerr << std::endl; + + int sockfd = unix_socket(PF_INET, SOCK_STREAM, 0); + CHECK( 0 < sockfd ); + + if (0 != (err = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)))) + { + std::cerr << " Failed to Bind to Local Address!" << std::endl; + showSocketError(std::cerr); + + FAILED("Couldn't Bind to socket"); + + return false; + } + + std::cerr << " Successfully Bound Socket to Address" << std::endl; + unix_close(sockfd); + + return true; +} + + diff --git a/libretroshare/src/tests/pqi/net_test1.cc b/libretroshare/src/tests/pqi/net_test1.cc new file mode 100644 index 000000000..599bacbf2 --- /dev/null +++ b/libretroshare/src/tests/pqi/net_test1.cc @@ -0,0 +1,268 @@ +/* + * libretroshare/src/pqi net_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * NETWORKING Test to check Big/Little Endian behaviour + * as well as socket behaviour + * + */ + +#include "pqi/pqinetwork.h" +#include "util/rsnet.h" +#include +#include +#include "util/utest.h" + +const char * loopback_addrstr = "127.0.0.1"; + +const char * localnet1_addrstr = "10.0.0.1"; +const char * localnet2_addrstr = "169.254.0.1"; +const char * localnet3_addrstr = "172.16.0.1"; +const char * localnet4_addrstr = "192.168.1.1"; + +const char * localnet5_addrstr = "10.4.28.34"; +const char * localnet6_addrstr = "169.254.1.81"; +const char * localnet7_addrstr = "172.20.9.201"; +const char * localnet8_addrstr = "192.168.1.254"; + +const char * external_addrstr = "74.125.19.99"; /* google */ +const char * invalid_addrstr = "AAA.BBB.256.256"; + +int test_isExternalNet(); +int test_isPrivateNet(); +int test_isLoopbackNet(); +int test_sameNet(); +int test_isValidNet(); +int test_isSameSubnet(); +int test_pqi_inet_netof(); + +INITTEST(); + +int main(int argc, char **argv) +{ + std::cerr << "net_test1" << std::endl; + + test_isExternalNet(); + test_isPrivateNet(); + test_isLoopbackNet(); + test_sameNet(); + test_isValidNet(); + test_isSameSubnet(); + test_pqi_inet_netof(); + + FINALREPORT("net_test1"); + + return TESTRESULT(); +} + +int test_isExternalNet() +{ + struct in_addr loopback_addr; + struct in_addr localnet1_addr; + struct in_addr localnet2_addr; + struct in_addr localnet3_addr; + struct in_addr localnet4_addr; + struct in_addr external_addr; + struct in_addr invalid_addr; + struct in_addr invalid_addr2; + + inet_aton(loopback_addrstr, &loopback_addr); + inet_aton(localnet1_addrstr, &localnet1_addr); + inet_aton(localnet2_addrstr, &localnet2_addr); + inet_aton(localnet3_addrstr, &localnet3_addr); + inet_aton(localnet4_addrstr, &localnet4_addr); + inet_aton(external_addrstr, &external_addr); + invalid_addr.s_addr = 0; + invalid_addr2.s_addr = -1; + + CHECK(isExternalNet(&loopback_addr)==false); + CHECK(isExternalNet(&localnet1_addr)==false); + CHECK(isExternalNet(&localnet2_addr)==false); + CHECK(isExternalNet(&localnet3_addr)==false); + CHECK(isExternalNet(&localnet4_addr)==false); + CHECK(isExternalNet(&external_addr)==true); + CHECK(isExternalNet(&invalid_addr)==false); + CHECK(isExternalNet(&invalid_addr2)==false); + + REPORT("isExternalNet()"); + + return 1; +} + +int test_isPrivateNet() +{ + struct in_addr loopback_addr; + struct in_addr localnet1_addr; + struct in_addr localnet2_addr; + struct in_addr localnet3_addr; + struct in_addr localnet4_addr; + struct in_addr external_addr; + + inet_aton(loopback_addrstr, &loopback_addr); + inet_aton(localnet1_addrstr, &localnet1_addr); + inet_aton(localnet2_addrstr, &localnet2_addr); + inet_aton(localnet3_addrstr, &localnet3_addr); + inet_aton(localnet4_addrstr, &localnet4_addr); + inet_aton(external_addrstr, &external_addr); + + CHECK(isPrivateNet(&loopback_addr)==false); //loopback not considered a "private network" + CHECK(isPrivateNet(&localnet1_addr)==true); + CHECK(isPrivateNet(&localnet2_addr)==true); + CHECK(isPrivateNet(&localnet3_addr)==true); + CHECK(isPrivateNet(&localnet4_addr)==true); + CHECK(isPrivateNet(&external_addr)==false); + + REPORT("isPrivateNet()"); + + return 1; +} + +int test_isLoopbackNet() +{ + struct in_addr loopback_addr; + struct in_addr localnet1_addr; + struct in_addr external_addr; + + inet_aton(loopback_addrstr, &loopback_addr); + inet_aton(localnet1_addrstr, &localnet1_addr); + inet_aton(external_addrstr, &external_addr); + + CHECK(isLoopbackNet(&loopback_addr)==true); + CHECK(isLoopbackNet(&localnet1_addr)==false); + CHECK(isLoopbackNet(&external_addr)==false); + + REPORT("isLoopbackNet()"); + + return 1; +} + +int test_sameNet() +{ + struct in_addr localnet1_addr; + struct in_addr localnet2_addr; + struct in_addr localnet3_addr; + struct in_addr localnet4_addr; + struct in_addr localnet5_addr; + struct in_addr localnet6_addr; + struct in_addr localnet7_addr; + struct in_addr localnet8_addr; + struct in_addr external_addr; + + inet_aton(localnet1_addrstr, &localnet1_addr); + inet_aton(localnet2_addrstr, &localnet2_addr); + inet_aton(localnet3_addrstr, &localnet3_addr); + inet_aton(localnet4_addrstr, &localnet4_addr); + inet_aton(localnet5_addrstr, &localnet5_addr); + inet_aton(localnet6_addrstr, &localnet6_addr); + inet_aton(localnet7_addrstr, &localnet7_addr); + inet_aton(localnet8_addrstr, &localnet8_addr); + inet_aton(external_addrstr, &external_addr); + + CHECK(sameNet(&localnet1_addr, &localnet5_addr)==true); + CHECK(sameNet(&localnet2_addr, &localnet6_addr)==true); + CHECK(sameNet(&localnet3_addr, &localnet7_addr)==true); + CHECK(sameNet(&localnet4_addr, &localnet8_addr)==true); + CHECK(sameNet(&localnet1_addr, &external_addr)==false); + CHECK(sameNet(&localnet2_addr, &external_addr)==false); + CHECK(sameNet(&localnet3_addr, &external_addr)==false); + CHECK(sameNet(&localnet4_addr, &external_addr)==false); + + REPORT("sameNet()"); + + return 1; +} + +int test_isValidNet() +{ + struct in_addr localnet1_addr; + struct in_addr invalid_addr; + + inet_aton(localnet1_addrstr, &localnet1_addr); + CHECK(isValidNet(&localnet1_addr)==true); + + CHECK(inet_aton(invalid_addrstr, &invalid_addr)==0); + std::cerr << rs_inet_ntoa(invalid_addr) << std::endl; + //CHECK(isValidNet(&invalid_addr)==false); + + REPORT("isValidNet()"); + + return 1; +} + +int test_isSameSubnet() +{ + struct in_addr localnet1_addr; + struct in_addr classc1_addr; + struct in_addr classc2_addr; + + inet_aton(localnet1_addrstr, &localnet1_addr); + //random class C addresses + inet_aton("197.67.28.93", &classc1_addr); + inet_aton("197.67.28.3", &classc2_addr); + + CHECK(isSameSubnet(&localnet1_addr, &classc1_addr)==false); + CHECK(isSameSubnet(&classc1_addr, &classc2_addr)==true); + + REPORT("isSameSubnet()"); + + return 1; +} + +int test_pqi_inet_netof() +{ + struct in_addr localnet1_addr; + struct in_addr localnet2_addr; + struct in_addr localnet3_addr; + struct in_addr localnet4_addr; + struct in_addr localnet5_addr; + struct in_addr localnet6_addr; + struct in_addr localnet7_addr; + struct in_addr localnet8_addr; + struct in_addr external_addr; + + inet_aton(localnet1_addrstr, &localnet1_addr); + inet_aton(localnet2_addrstr, &localnet2_addr); + inet_aton(localnet3_addrstr, &localnet3_addr); + inet_aton(localnet4_addrstr, &localnet4_addr); + inet_aton(localnet5_addrstr, &localnet5_addr); + inet_aton(localnet6_addrstr, &localnet6_addr); + inet_aton(localnet7_addrstr, &localnet7_addr); + inet_aton(localnet8_addrstr, &localnet8_addr); + inet_aton(external_addrstr, &external_addr); + + CHECK(pqi_inet_netof(localnet1_addr)==htonl(10<<24)); + CHECK(pqi_inet_netof(localnet2_addr)==htonl(169<<24 | 254<<16)); + CHECK(pqi_inet_netof(localnet3_addr)==htonl(172<<24 | 16<<16)); + CHECK(pqi_inet_netof(localnet4_addr)==htonl(192<<24 | 168<<16 | 1<<8)); + CHECK(pqi_inet_netof(localnet5_addr)==htonl(10<<24)); + CHECK(pqi_inet_netof(localnet6_addr)==htonl(169<<24 | 254<<16)); + CHECK(pqi_inet_netof(localnet7_addr)==htonl(172<<24 | 20<<16)); + CHECK(pqi_inet_netof(localnet8_addr)==htonl(192<<24 | 168<<16 | 1<<8)); + CHECK(pqi_inet_netof(external_addr)==htonl(74<<24)); + + REPORT("pqi_inet_netof()"); + + return 1; +} diff --git a/libretroshare/src/tests/pqi/netiface_test.cc b/libretroshare/src/tests/pqi/netiface_test.cc new file mode 100644 index 000000000..a031ff178 --- /dev/null +++ b/libretroshare/src/tests/pqi/netiface_test.cc @@ -0,0 +1,122 @@ +/* + * libretroshare/src/pqi net_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * NETWORKING Test to check Big/Little Endian behaviour + * as well as socket behaviour + * + */ + +#include "pqi/pqinetwork.h" +#include "util/rsnet.h" +#include +#include + + +bool test_iface(); +bool test_iface_loop(); + +int main(int argc, char **argv) +{ + bool repeat = false; + if (argc > 1) + { + repeat = true; + } + + test_iface(); + + if (repeat) + { + test_iface_loop(); + } + + return 1; +} + + /* test 1: single check if interfaces */ +bool test_iface() +{ + struct in_addr pref_iface; + std::list ifaces; + std::list::iterator it; + + getPreferredInterface(pref_iface); + getLocalInterfaces(ifaces); + + std::cerr << "test_iface()" << std::endl; + for(it = ifaces.begin(); it != ifaces.end(); it++) + { + std::cerr << "available iface: " << rs_inet_ntoa(*it) << std::endl; + } + std::cerr << "preferred " << rs_inet_ntoa(pref_iface) << std::endl; + + return true; +} + + /* test 2: catch changing interfaces */ +bool test_iface_loop() +{ + std::cerr << "test_iface_loop()" << std::endl; + struct in_addr curr_pref_iface; + getPreferredInterface(curr_pref_iface); + time_t start = time(NULL); + while(1) + { + struct in_addr pref_iface; + std::list ifaces; + std::list::iterator it; + + getPreferredInterface(pref_iface); + getLocalInterfaces(ifaces); + + + std::cerr << "T(" << time(NULL) - start << ") "; + + for(it = ifaces.begin(); it != ifaces.end(); it++) + { + std::cerr << " I: " << rs_inet_ntoa(*it); + } + std::cerr << " P: " << rs_inet_ntoa(pref_iface) << std::endl; + + if (curr_pref_iface.s_addr != + pref_iface.s_addr) + { + std::cerr << "+++++++++++++ Address CHANGED ++++++++++"; + std::cerr << std::endl; + std::cerr << "+++++++++++++ Address CHANGED ++++++++++"; + std::cerr << std::endl; + std::cerr << "+++++++++++++ Address CHANGED ++++++++++"; + std::cerr << std::endl; + + curr_pref_iface = pref_iface; + } + + sleep(1); + } + return true; +} + + diff --git a/libretroshare/src/tests/pqi/p3connmgr_connect_test.cc b/libretroshare/src/tests/pqi/p3connmgr_connect_test.cc new file mode 100644 index 000000000..e2d40fe1a --- /dev/null +++ b/libretroshare/src/tests/pqi/p3connmgr_connect_test.cc @@ -0,0 +1,195 @@ +/* + * libretroshare/src/test/pqi p3connmgr_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * p3connmgr test module. + * + * create a p3connmgr and run the following tests. + * 1) UDP test + * 2) UPNP test + * 3) ExtAddr test. + * 4) full reset in between. + * + */ + + +#include +#include +#include + + +#include "ppg_harness.h" +#include "conn_harness.h" + +#include "pqi/p3connmgr.h" +#include "pqi/authssltest.h" +#include "pqi/authgpgtest.h" + +#include "pqi/p3dhtmgr.h" +#include "upnp/upnphandler.h" + +#include "util/rsnet.h" +#include +#include +#include "util/utest.h" + +INITTEST(); + +/* generic startup test */ +#define MAX_TIME_SHORT_TEST 10 +#define MAX_TIME_BASIC_TEST 60 + +int run_connect_test(time_t timeout); + +/******************************************************* + * + * Test structure + *****************/ + +#define FLAG_UPNP 1 +#define FLAG_UDP 2 +#define FLAG_DHT 4 +#define FLAG_EXT 8 + +p3ConnectMgr *mConnMgr; +pqiNetAssistFirewall *mUpnpMgr = NULL; +p3DhtMgr *mDhtMgr = NULL; + +void createP3ConnMgr(std::string id, uint32_t testFlags) +{ + /* now add test children */ + { + std::cerr << "createP3ConnMgr()"; + std::cerr << std::endl; + } + + mConnMgr = new p3ConnectMgr(); + + mDhtMgr = NULL; //new p3DhtMgr(); + + /* setup status */ + //mConnMgr->setStatus(UPNP); +} + + +/* ACTUAL TEST */ +int main(int argc, char **argv) +{ + /* test p3connmgr net stuff */ + std::cerr << "p3connmgr_net_connect_test" << std::endl; + + // setup test authssl. + setAuthGPG(new AuthGPGtest()); + setAuthSSL(new AuthSSLtest()); + + createP3ConnMgr("abcd", 0); + pqiNetStatus status; + + setupPqiPersonGrpTH(); + + /* install ppg as a monitor */ + + mConnMgr->addMonitor(mPqiPersonGrpTH); + + + std::string peer1_gpgid = "PEERID0001_GPG__"; + std::string peer1_sslid = "PEERID0001_SSL__"; + + /* first test, add a single peer (no Addresses) */ + mConnMgr->addFriend(peer1_sslid, peer1_gpgid); + + run_connect_test(MAX_TIME_SHORT_TEST); + + mConnMgr->getNetStatus(status); + + CHECK(status.mLocalAddrOk == false); + CHECK(status.mExtAddrOk == false); + + // Check that there have been... 1 reset / 0 connects / 1 listen + // per connect. + + REPORT("p3connmgr_connect_test() SINGLE PEER - NO Addresses"); + /* second test, add addresses for peer */ + + time_t now = time(NULL); + + pqiIpAddrSet peer1_tst2_addrs; + pqiIpAddress paddr; + inet_aton("192.168.1.1", &(paddr.mAddr.sin_addr)); + paddr.mAddr.sin_port = htons(6411); + paddr.mSeenTime = now - 10; + peer1_tst2_addrs.mLocal.updateIpAddressList(paddr); + + inet_aton("192.168.1.2", &(paddr.mAddr.sin_addr)); + paddr.mAddr.sin_port = htons(6422); + paddr.mSeenTime = now - 20; + peer1_tst2_addrs.mLocal.updateIpAddressList(paddr); + + inet_aton("23.56.25.1", &(paddr.mAddr.sin_addr)); + paddr.mAddr.sin_port = htons(6511); + paddr.mSeenTime = now - 30; + peer1_tst2_addrs.mExt.updateIpAddressList(paddr); + + inet_aton("23.56.25.2", &(paddr.mAddr.sin_addr)); + paddr.mAddr.sin_port = htons(6522); + paddr.mSeenTime = now - 40; + peer1_tst2_addrs.mExt.updateIpAddressList(paddr); + + mConnMgr->updateAddressList(peer1_sslid, peer1_tst2_addrs); + mConnMgr->retryConnect(peer1_sslid); + + run_connect_test(MAX_TIME_BASIC_TEST); + + // Check that there have been: + // 0 Listens / 0 resets. + // 0 connect attempts on UDP + // 4 connect attempts on TCP + // 0 connect attempts on TUNNEL + REPORT("p3connmgr_connect_test() SINGLE PEER - 4 Addresses"); + + /* third test, add an second peer with addresses */ + + /* fourth test, setup default action as connect */ + setDefaultTestConnectAction(TST_ACTION_SUCCESS); +} + +/* Generic restart test */ +int run_connect_test(time_t timeout) +{ + /* tick */ + time_t start = time(NULL); + bool extAddr = false; + + while ((start > time(NULL) - timeout) && (!extAddr)) + { + mConnMgr->tick(); + tickPqiPersonGrpTH(); + + sleep(1); + } + return 1; +} + + diff --git a/libretroshare/src/tests/pqi/p3connmgr_reset_test.cc b/libretroshare/src/tests/pqi/p3connmgr_reset_test.cc new file mode 100644 index 000000000..971ec4164 --- /dev/null +++ b/libretroshare/src/tests/pqi/p3connmgr_reset_test.cc @@ -0,0 +1,320 @@ +/* + * libretroshare/src/test/pqi p3connmgr_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * p3connmgr test module. + * + * create a p3connmgr and run the following tests. + * 1) UDP test + * 2) UPNP test + * 3) ExtAddr test. + * 4) full reset in between. + * + */ + + +#include +#include +#include + + + + +#include "pqi/p3connmgr.h" +#include "pqi/authssltest.h" +#include "pqi/authgpgtest.h" + +#include "pqi/p3dhtmgr.h" +#include "upnp/upnphandler.h" + +#include "util/rsnet.h" +#include +#include +#include "util/utest.h" + +INITTEST(); + +/* generic startup test */ +#define MAX_TIME_BASIC_TEST 40 +#define MAX_TIME_UPNP_TEST 700 /* seems to take a while */ + +#define RESTART_EXPECT_NO_EXT_ADDR 1 +#define RESTART_EXPECT_EXTFINDER_ADDR 2 +#define RESTART_EXPECT_UPNP_ADDR 3 +#define RESTART_EXPECT_DHT_ADDR 4 + +int test_p3connmgr_restart_test(uint32_t expectState, time_t timeout); + + +#define RESET_VIA_LOCAL_ADDR 1 +#define RESET_VIA_REMOTE_ADDR 2 + + +int force_reset(uint32_t method); + + +/******************************************************* + * + * Test structure + *****************/ + +#define FLAG_UPNP 1 +#define FLAG_UDP 2 +#define FLAG_DHT 4 +#define FLAG_EXT 8 + +p3ConnectMgr *mConnMgr; +pqiNetAssistFirewall *mUpnpMgr = NULL; +p3DhtMgr *mDhtMgr = NULL; + +void createP3ConnMgr(std::string id, uint32_t testFlags) +{ + /* now add test children */ + { + std::cerr << "createP3ConnMgr()"; + std::cerr << std::endl; + } + + mConnMgr = new p3ConnectMgr(); + + mDhtMgr = NULL; //new p3DhtMgr(); + + /* setup status */ + //mConnMgr->setStatus(UPNP); +} + +void add_upnp() +{ + pqiNetAssistFirewall *mUpnpMgr = new upnphandler(); + mDhtMgr = NULL; //new p3DhtMgr(); + + //mConnMgr->addNetAssistConnect(1, mDhtMgr); + mConnMgr->addNetAssistFirewall(1, mUpnpMgr); +} + +void disableUpnp() +{ + //mConnMgr-> +} + + +void enableUpnp() +{ + + + +} + +void disableExtFinder() +{ + //mConnMgr-> + mConnMgr->setIPServersEnabled(false); +} + + +void enableExtFinder() +{ + mConnMgr->setIPServersEnabled(true); +} + + +/* ACTUAL TEST */ +int main(int argc, char **argv) +{ + /* test p3connmgr net stuff */ + std::cerr << "p3connmgr_net_restart_test" << std::endl; + + // setup test authssl. + setAuthGPG(new AuthGPGtest()); + setAuthSSL(new AuthSSLtest()); + + createP3ConnMgr("abcd", 0); + pqiNetStatus status; + + + /* first test, no Upnp / ExtFinder -> expect no Ext Address */ + mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); + disableExtFinder(); + + mConnMgr->getNetStatus(status); + + CHECK(status.mLocalAddrOk == false); + CHECK(status.mExtAddrOk == false); + test_p3connmgr_restart_test(RESTART_EXPECT_NO_EXT_ADDR, MAX_TIME_BASIC_TEST); + + REPORT("test_p3connmgr_restart_test()"); + + /* second test, add ExtFinder -> expect Ext Address */ + enableExtFinder(); + mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); + force_reset(RESET_VIA_LOCAL_ADDR); + + CHECK(status.mLocalAddrOk == false); + CHECK(status.mExtAddrOk == false); + test_p3connmgr_restart_test(RESTART_EXPECT_EXTFINDER_ADDR, MAX_TIME_BASIC_TEST); + + /* third test. disable ExtFinder again -> expect No Ext Address */ + disableExtFinder(); + mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); + force_reset(RESET_VIA_LOCAL_ADDR); + CHECK(status.mLocalAddrOk == false); + CHECK(status.mExtAddrOk == false); + test_p3connmgr_restart_test(RESTART_EXPECT_NO_EXT_ADDR, MAX_TIME_BASIC_TEST); + + + /* fourth test. enable Upnp -> expect Upnp Ext Address */ + add_upnp(); + enableUpnp(); + mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UPNP); + force_reset(RESET_VIA_LOCAL_ADDR); + CHECK(status.mLocalAddrOk == false); + CHECK(status.mExtAddrOk == false); + + + test_p3connmgr_restart_test(RESTART_EXPECT_UPNP_ADDR, MAX_TIME_UPNP_TEST); + /* fifth test. disable Upnp -> expect No Ext Address */ + disableUpnp(); + mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UDP); + force_reset(RESET_VIA_LOCAL_ADDR); + CHECK(status.mLocalAddrOk == false); + CHECK(status.mExtAddrOk == false); + + test_p3connmgr_restart_test(RESTART_EXPECT_NO_EXT_ADDR, MAX_TIME_BASIC_TEST); + /* sixth test. enable both Ext and Upnp -> expect UpnP Ext Address (prefered) */ + enableExtFinder(); + enableUpnp(); + mConnMgr->setNetworkMode(AuthSSL::getAuthSSL()->OwnId(), RS_NET_MODE_UPNP); + force_reset(RESET_VIA_LOCAL_ADDR); + CHECK(status.mLocalAddrOk == false); + CHECK(status.mExtAddrOk == false); + + test_p3connmgr_restart_test(RESTART_EXPECT_UPNP_ADDR, MAX_TIME_UPNP_TEST); + REPORT("test_p3connmgr_restart_test()"); + + FINALREPORT("p3connmgr_net_restart_test"); + + return TESTRESULT(); +} + +/****************************************************** + * + */ + +int force_reset(uint32_t method) +{ + /* force reset network */ + struct sockaddr_in tst_addr; + inet_aton("123.45.2.2", &(tst_addr.sin_addr)); + tst_addr.sin_port = ntohs(8461); + + mConnMgr->setLocalAddress(AuthSSL::getAuthSSL()->OwnId(), tst_addr); + + return 1; +} + +/* Generic restart test */ +int test_p3connmgr_restart_test(uint32_t expectState, time_t timeout) +{ + /* force reset network */ + struct sockaddr_in tst_addr; + inet_aton("123.45.2.2", &(tst_addr.sin_addr)); + tst_addr.sin_port = ntohs(8461); + + mConnMgr->setLocalAddress(AuthSSL::getAuthSSL()->OwnId(), tst_addr); + + /* tick */ + time_t start = time(NULL); + bool extAddr = false; + + while ((start > time(NULL) - timeout) && (!extAddr)) + { + mConnMgr->tick(); + + pqiNetStatus status; + mConnMgr->getNetStatus(status); + std::cerr << "test_p3connmgr_restart_test() Age: " << time(NULL) - start; + std::cerr << " netStatus:"; + std::cerr << std::endl; + status.print(std::cerr); + + if (status.mExtAddrOk) + { + std::cerr << "test_p3connmgr_restart_test() Got ExtAddr. Finished Restart."; + std::cerr << std::endl; + extAddr = true; + } + sleep(1); + } + + std::cerr << "test_p3connmgr_restart_test() Test Mode: " << expectState << " Complete"; + std::cerr << std::endl; + + pqiNetStatus status; + mConnMgr->getNetStatus(status); + status.print(std::cerr); + if (status.mExtAddrOk) + { + CHECK(isValidNet(&(status.mExtAddr.sin_addr))); + } + CHECK(isValidNet(&(status.mLocalAddr.sin_addr))); + + /* check expectState */ + switch(expectState) + { + default: + case RESTART_EXPECT_NO_EXT_ADDR: + CHECK(status.mLocalAddrOk == true); + CHECK(status.mExtAddrOk == false); + CHECK(status.mExtAddrStableOk == false); + CHECK(status.mUpnpOk == false); + CHECK(status.mDhtOk == false); + break; + + case RESTART_EXPECT_EXTFINDER_ADDR: + CHECK(status.mLocalAddrOk == true); + CHECK(status.mExtAddrOk == true); + CHECK(status.mExtAddrStableOk == false); + CHECK(status.mUpnpOk == false); + break; + + case RESTART_EXPECT_UPNP_ADDR: + CHECK(status.mLocalAddrOk == true); + CHECK(status.mExtAddrOk == true); + CHECK(status.mExtAddrStableOk == true); + CHECK(status.mUpnpOk == true); + break; + + case RESTART_EXPECT_DHT_ADDR: + CHECK(status.mLocalAddrOk == true); + CHECK(status.mExtAddrOk == false); + CHECK(status.mUpnpOk == false); + CHECK(status.mDhtOk == true); + break; + } + + return 1; +} + + diff --git a/libretroshare/src/tests/pqi/pkt_test.cc b/libretroshare/src/tests/pqi/pkt_test.cc new file mode 100644 index 000000000..49f6edd47 --- /dev/null +++ b/libretroshare/src/tests/pqi/pkt_test.cc @@ -0,0 +1,109 @@ +/* + * libretroshare/src/tests/pqi pkt_tst.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * pkt_tst. + * + * This is not testing serialisation.... so we only need 1 type of packet. + * using FileData packets - as these can have arbitary size. + */ + +#include "pkt_test.h" +#include + +uint8_t testdata[TEST_DATA_LEN]; + +void generate_test_data() +{ + srand(1); + + int i; + for(i = 0; i < TEST_DATA_LEN; i++) + { + testdata[i] = rand() % 256; + } +} + +bool check_data(void *data_in, int len) +{ + int i; + uint8_t *data = (uint8_t *) data_in; + + for(i = 0; i < len; i++) + { + if (data[i] != testdata[i]) + { + std::cerr << "check_data() Different Byte: " << i; + std::cerr << std::endl; + + return false; + } + } + return true; +} + +RsFileData *gen_packet(int datasize, std::string pid) +{ + /* generate some packets */ + RsFileData *data = new RsFileData(); + data->fd.file.filesize = TEST_PKT_SIZE; + data->fd.file.hash = TEST_PKT_HASH; + data->fd.file_offset = TEST_PKT_OFFSET; + data->fd.binData.setBinData(testdata, datasize); + data->PeerId(pid); + + return data; +} + +bool check_packet(RsFileData *pkt) +{ + if (pkt->fd.file.filesize != TEST_PKT_SIZE) + { + std::cerr << "check_packet() FileSize Different"; + std::cerr << std::endl; + + return false; + } + + if (pkt->fd.file.hash != TEST_PKT_HASH) + { + std::cerr << "check_packet() FileHash Different"; + std::cerr << std::endl; + + return false; + } + + if (pkt->fd.file_offset != TEST_PKT_OFFSET) + { + std::cerr << "check_packet() FileOffset Different"; + std::cerr << std::endl; + + return false; + } + + return check_data(pkt->fd.binData.bin_data, pkt->fd.binData.bin_len); +} + + diff --git a/libretroshare/src/tests/pqi/pkt_test.h b/libretroshare/src/tests/pqi/pkt_test.h new file mode 100644 index 000000000..072274574 --- /dev/null +++ b/libretroshare/src/tests/pqi/pkt_test.h @@ -0,0 +1,50 @@ +#ifndef RS_TEST_PACKETS +#define RS_TEST_PACKETS +/* + * libretroshare/src/tests/pqi pkt_tst.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * pkt_tst. + * + * This is not testing serialisation.... so we only need 1 type of packet. + * using FileData packets - as these can have arbitary size. + */ + +#include "serialiser/rsbaseitems.h" + +#define TEST_PKT_SIZE 1234567 +#define TEST_PKT_HASH "HASHTESTHASH" +#define TEST_PKT_OFFSET 1234 + +#define TEST_DATA_LEN (1024 * 1024) // MB + +void generate_test_data(); +bool check_data(void *data_in, int len); + +RsFileData *gen_packet(int datasize, std::string pid); +bool check_packet(RsFileData *pkt); + + +#endif diff --git a/libretroshare/src/tests/pqi/ppg_harness.cc b/libretroshare/src/tests/pqi/ppg_harness.cc new file mode 100644 index 000000000..58b89a971 --- /dev/null +++ b/libretroshare/src/tests/pqi/ppg_harness.cc @@ -0,0 +1,141 @@ +/* + * libretroshare/src/test/pqi pqiperson_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * pqiperson acts as the wrapper for all connection methods to a single peer. + * + * This test creates, a pqiperson and simulates connections, disconnections. + * packets passing through. + * + */ + + +#include "conn_harness.h" +#include "ppg_harness.h" + +#include "pqi/pqiperson.h" +#include "pqi/pqibin.h" + +#include "util/rsnet.h" +#include +#include + +/******************************************************* + * + * Test structure + *****************/ + + +pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); + +pqipersongrpTestHarness *mPqiPersonGrpTH = NULL; + +void setupPqiPersonGrpTH() +{ + mPqiPersonGrpTH = new pqipersongrpTestHarness(NULL, 0); +} + +void tickPqiPersonGrpTH() +{ + mPqiPersonGrpTH->tick(); +} + + +pqipersongrpTestHarness::pqipersongrpTestHarness(SecurityPolicy *pol, unsigned long flags) + :pqipersongrp(pol, flags) +{ + return; +} + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +pqilistener *pqipersongrpTestHarness::createListener(struct sockaddr_in laddr) +{ + return new pqilistener(); +} + +pqiperson *pqipersongrpTestHarness::createPerson(std::string id, pqilistener *listener) +{ + return createTestPerson(id, this); +} + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ + + + + +pqiperson *createTestPerson(std::string id, pqipersongrp *ppg) +{ + /* now add test children */ + { + std::cerr << "createTestPerson()"; + std::cerr << std::endl; + } + + pqiperson *pqip = new pqiperson(id, ppg); + + /* construct the serialiser .... + * Needs: + * * FileItem + * * FileData + * * ServiceGeneric + */ + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + rss->addSerialType(new RsCacheItemSerialiser()); + rss->addSerialType(new RsServiceSerialiser()); + + NetBinDummy *dummy1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); + pqiconnect *pqisc = new testConnect(rss, dummy1); + addTestConnect(pqisc, pqip); + pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); + + RsSerialiser *rss2 = new RsSerialiser(); + rss2->addSerialType(new RsFileItemSerialiser()); + rss2->addSerialType(new RsCacheItemSerialiser()); + rss2->addSerialType(new RsServiceSerialiser()); + + NetBinDummy *dummy2 = new NetBinDummy(pqip, id, PQI_CONNECT_TUNNEL); + pqiconnect *pqicontun = new testConnect(rss2, dummy2); + addTestConnect(pqicontun, pqip); + pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); + + + RsSerialiser *rss3 = new RsSerialiser(); + rss3->addSerialType(new RsFileItemSerialiser()); + rss3->addSerialType(new RsCacheItemSerialiser()); + rss3->addSerialType(new RsServiceSerialiser()); + + NetBinDummy *dummy3 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); + pqiconnect *pqiusc = new testConnect(rss3, dummy3); + addTestConnect(pqiusc, pqip); + pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); + + return pqip; +} + + + + diff --git a/libretroshare/src/tests/pqi/ppg_harness.h b/libretroshare/src/tests/pqi/ppg_harness.h new file mode 100644 index 000000000..85e664548 --- /dev/null +++ b/libretroshare/src/tests/pqi/ppg_harness.h @@ -0,0 +1,61 @@ +#ifndef PPG_HARNESS_TEST_H +#define PPG_HARNESS_TEST_H + +/* + * libretroshare/src/test/pqi ppg_harness.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * test harness for pqipersongrp / pqihandler. + */ + +#include "pqi/pqiperson.h" +#include "pqi/pqipersongrp.h" + +/******************************************************* + * + * Test structure + *****************/ + +void setupPqiPersonGrpTH(); +void tickPqiPersonGrpTH(); + +class pqipersongrpTestHarness; +extern pqipersongrpTestHarness *mPqiPersonGrpTH; + +class pqipersongrpTestHarness: public pqipersongrp +{ + public: + pqipersongrpTestHarness(SecurityPolicy *pol, unsigned long flags); + + protected: + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +virtual pqilistener *createListener(struct sockaddr_in laddr); +virtual pqiperson *createPerson(std::string id, pqilistener *listener); + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +}; + +#endif diff --git a/libretroshare/src/tests/pqi/pqiarchive_test.cc b/libretroshare/src/tests/pqi/pqiarchive_test.cc new file mode 100644 index 000000000..abe88bab7 --- /dev/null +++ b/libretroshare/src/tests/pqi/pqiarchive_test.cc @@ -0,0 +1,130 @@ +/* + * libretroshare/src/tests/pqi pqiarchive_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2009-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * pqiarchive test. + * + * This is not testing serialisation.... so we only need 1 type of packet. + * using FileData packets - as these can have arbitary size. + */ + +#include "pqi/pqiarchive.h" +#include "pqi/pqibin.h" + +#include "serialiser/rsbaseitems.h" + +#include "util/rsnet.h" +#include +#include +#include "util/utest.h" + +#include "pkt_test.h" + +INITTEST(); + +int test_pqiarchive_generate(); + +int main(int argc, char **argv) +{ + std::cerr << "pqiarchive_test" << std::endl; + + generate_test_data(); + + test_pqiarchive_generate(); + + FINALREPORT("pqiarchive_test"); + + return TESTRESULT(); +} + +const char *archive_fname = "/tmp/rs_tst_archive.tmp"; + +int test_pqiarchive_generate() +{ + + std::string pid = "123456789012345678901234567890ZZ"; + /* create a pqiarchive */ + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + + int flags = BIN_FLAGS_WRITEABLE; + BinInterface *bio_in = new BinFileInterface(archive_fname, flags); + + int bio_flagsin = flags; + pqiarchive *pqia = new pqiarchive(rss, bio_in, bio_flagsin); + CHECK(pqia != NULL); + + int i; + for(i = 10; i < TEST_DATA_LEN; i = (int) (i * 1.1)) + { + RsFileData *pkt = gen_packet(i, pid); + pqia->SendItem(pkt); + pqia->tick(); + } + + /* close it up */ + delete pqia; + + /* setup read */ + flags = BIN_FLAGS_READABLE; + + rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + + bio_in = new BinFileInterface(archive_fname, flags); + bio_flagsin = flags; + pqia = new pqiarchive(rss, bio_in, bio_flagsin); + + for(i = 10; i < TEST_DATA_LEN; i = (int) (i * 1.1)) + //for(i = 10; i < TEST_DATA_LEN; i += 111) + { + RsItem *pkt = pqia->GetItem(); + pqia->tick(); + + /* check the packet */ + RsFileData *data = dynamic_cast(pkt); + CHECK(data != NULL); + if (data) + { + CHECK(data->fd.binData.bin_len == i); + CHECK(check_packet(data) == true); + delete data; + } + } + + /* if there are anymore packets -> error! */ + for(i = 0; i < 1000; i++) + { + RsItem *pkt = pqia->GetItem(); + CHECK(pkt == NULL); + } + + REPORT("pqiarchive_generate()"); + + return 1; +} + + + diff --git a/libretroshare/src/tests/pqi/pqiipset_test.cc b/libretroshare/src/tests/pqi/pqiipset_test.cc new file mode 100644 index 000000000..9fc715750 --- /dev/null +++ b/libretroshare/src/tests/pqi/pqiipset_test.cc @@ -0,0 +1,156 @@ +/* + * libretroshare/src/test/pqi pqiipset_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * NETWORKING Test to check Big/Little Endian behaviour + * as well as socket behaviour + * + */ + +#include "util/utest.h" + +#include "pqi/pqiipset.h" +#include "pqi/pqinetwork.h" +#include "util/rsnet.h" +#include +#include + + +bool test_addr_list(); + + +INITTEST(); + +int main(int argc, char **argv) +{ + std::cerr << "libretroshare:pqi " << argv[0] << std::endl; + + test_addr_list(); + + FINALREPORT("libretroshare pqiipset Tests"); + return TESTRESULT(); +} + + /* test 1: byte manipulation */ +bool test_addr_list() +{ + pqiIpAddress addr; + pqiIpAddrList list; + + for(int i = 100; i < 150; i++) + { + std::ostringstream out; + out << "192.168.2." << i; + inet_aton(out.str().c_str(), &(addr.mAddr.sin_addr)); + addr.mAddr.sin_port = htons(7812); + addr.mSeenTime = time(NULL) - i; + + list.updateIpAddressList(addr); + + if (i < 100 + 4) + { + /* check that was added to the back */ + CHECK(list.mAddrs.back().mSeenTime == addr.mSeenTime); + CHECK(list.mAddrs.back().mAddr.sin_addr.s_addr == addr.mAddr.sin_addr.s_addr); + CHECK(list.mAddrs.back().mAddr.sin_port == addr.mAddr.sin_port); + } + else + { + /* check that wasn't added to the back */ + CHECK(list.mAddrs.back().mSeenTime != addr.mSeenTime); + CHECK(list.mAddrs.back().mAddr.sin_addr.s_addr != addr.mAddr.sin_addr.s_addr); + } + } + + /* print out the list */ + std::cerr << "IpAddressList (expect variation: 192.168.2.[100-103]:7812)"; + std::cerr << std::endl; + list.printIpAddressList(std::cerr); + std::cerr << std::endl; + + const uint32_t expectedListSize = 4; + CHECK(list.mAddrs.size() == expectedListSize); + + time_t min_time = time(NULL) - expectedListSize + 100; + + /* expect the most recent ones to appear */ + std::list::iterator it; + for(it = list.mAddrs.begin(); it != list.mAddrs.end(); it++) + { + CHECK(it->mSeenTime < min_time); + } + + /* now add some with same address + port */ + { + std::ostringstream out; + out << "192.168.2.200"; + inet_aton(out.str().c_str(), &(addr.mAddr.sin_addr)); + addr.mAddr.sin_port = htons(8812); + } + + /* make sure it more recent than the previous ones */ + for(int i = 99; i > 89; i--) + { + addr.mSeenTime = time(NULL) - i; + list.updateIpAddressList(addr); + + /* check that was added to the front */ + CHECK(list.mAddrs.front().mSeenTime == addr.mSeenTime); + CHECK(list.mAddrs.front().mAddr.sin_addr.s_addr == addr.mAddr.sin_addr.s_addr); + CHECK(list.mAddrs.front().mAddr.sin_port == addr.mAddr.sin_port); + } + + /* print out the list */ + std::cerr << "IpAddressList (first item to be 192.168.2.200:8812)"; + std::cerr << std::endl; + list.printIpAddressList(std::cerr); + std::cerr << std::endl; + + /* now add with the different ports */ + + for(int i = 70; i > 50; i--) + { + addr.mAddr.sin_port = htons(8000 + i); + addr.mSeenTime = time(NULL) - i; + + list.updateIpAddressList(addr); + + /* check that was added to the back */ + CHECK(list.mAddrs.front().mSeenTime == addr.mSeenTime); + CHECK(list.mAddrs.front().mAddr.sin_addr.s_addr == addr.mAddr.sin_addr.s_addr); + CHECK(list.mAddrs.front().mAddr.sin_port == addr.mAddr.sin_port); + + } + + std::cerr << "IpAddressList (expect same Ip, but variations in port)"; + std::cerr << std::endl; + list.printIpAddressList(std::cerr); + std::cerr << std::endl; + + REPORT("pqiIpAddrList Test"); + + return 1; +} + diff --git a/libretroshare/src/tests/pqi/pqiperson_test.cc b/libretroshare/src/tests/pqi/pqiperson_test.cc new file mode 100644 index 000000000..25af19537 --- /dev/null +++ b/libretroshare/src/tests/pqi/pqiperson_test.cc @@ -0,0 +1,227 @@ +/* + * libretroshare/src/test/pqi pqiperson_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * pqiperson acts as the wrapper for all connection methods to a single peer. + * + * This test creates, a pqiperson and simulates connections, disconnections. + * packets passing through. + * + */ + + + + + + +#include "pqi/pqiperson.h" +#include "pqi/pqibin.h" + +#include "testconnect.h" + +#include "util/rsnet.h" +#include +#include +#include "util/utest.h" + +INITTEST(); + +int test_person_basic_reset(); +int test_person_basic_listen(); + + +int main(int argc, char **argv) +{ + std::cerr << "pqiperson_test" << std::endl; + + test_person_basic_reset(); + test_person_basic_listen(); + + FINALREPORT("pqiperson_test"); + + return TESTRESULT(); +} + +/****************************************************** + * + * tests() + * + **** ensure that functions call children + * pqiperson::reset() + * pqiperson::listen() + * pqiperson::stoplistening() + * + * + * pqiperson::connect(...) + * -> check that gets through to children. + * -> check that cannot have simultaneous connections. + * -> + * + */ + + +/******************************************************* + * + * Test structure + *****************/ + +#define NUM_CHILDREN 3 + +pqiperson *createTestPerson(std::string id, pqipersongrp *ppg) +{ + /* now add test children */ + { + std::cerr << "createTestPerson()"; + std::cerr << std::endl; + } + + pqiperson *pqip = new pqiperson(id, ppg); + + /* construct the serialiser .... + * Needs: + * * FileItem + * * FileData + * * ServiceGeneric + */ + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + rss->addSerialType(new RsCacheItemSerialiser()); + rss->addSerialType(new RsServiceSerialiser()); + + NetBinDummy *dummy1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); + pqiconnect *pqisc = new testConnect(rss, dummy1); + addTestConnect(pqisc); + pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); + + RsSerialiser *rss2 = new RsSerialiser(); + rss2->addSerialType(new RsFileItemSerialiser()); + rss2->addSerialType(new RsCacheItemSerialiser()); + rss2->addSerialType(new RsServiceSerialiser()); + + NetBinDummy *dummy2 = new NetBinDummy(pqip, id, PQI_CONNECT_TUNNEL); + pqiconnect *pqicontun = new testConnect(rss2, dummy2); + addTestConnect(pqicontun); + pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); + + + RsSerialiser *rss3 = new RsSerialiser(); + rss3->addSerialType(new RsFileItemSerialiser()); + rss3->addSerialType(new RsCacheItemSerialiser()); + rss3->addSerialType(new RsServiceSerialiser()); + + NetBinDummy *dummy3 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); + pqiconnect *pqiusc = new testConnect(rss3, dummy3); + addTestConnect(pqiusc); + pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); + + return pqip; +} + + +/* First Sets of Tests are very basic: + * reset() + * connect() + * listen() / stoplistening() + * disconnect() + */ + +int test_person_basic_reset() +{ + /* reset test */ + resetTestConnects(); + + /* create test person */ + std::string id = "12345678901234567890123456789012"; + pqipersongrp *ppg = NULL; + pqiperson *person = createTestPerson(id, ppg); + + /* reset person */ + person->reset(); + + /* count number of resets */ + CHECK(NUM_CHILDREN == testCounter); + + int i; + for(i = 0; i < NUM_CHILDREN; i++) + { + CHECK(testResetTimes[i].size() == 1); + CHECK(testConnectState[i] == 0); + CHECK(testConnectTimes[i].size() == 0); + } + + /* clean up */ + delete person; + + REPORT("test_person_basic_reset()"); + + return 1; +} + + +int test_person_basic_listen() +{ + /* reset test */ + resetTestConnects(); + + /* create test person */ + std::string id = "12345678901234567890123456789012"; + pqipersongrp *ppg = NULL; + pqiperson *person = createTestPerson(id, ppg); + + /* reset person */ + person->listen(); + + /* count number of resets */ + CHECK(NUM_CHILDREN == testCounter); + + int i; + for(i = 0; i < NUM_CHILDREN; i++) + { + CHECK(testResetTimes[i].size() == 0); + CHECK(testConnectTimes[i].size() == 0); + CHECK(testConnectState[i] == TST_STATE_LISTEN); + } + + person->stoplistening(); + + for(i = 0; i < NUM_CHILDREN; i++) + { + CHECK(testResetTimes[i].size() == 0); + CHECK(testConnectTimes[i].size() == 0); + CHECK(testConnectState[i] == 0); + } + + /* clean up */ + delete person; + + REPORT("test_person_basic_listen()"); + + return 1; +} + + + + diff --git a/libretroshare/src/tests/pqi/pqipersongrp_test.cc b/libretroshare/src/tests/pqi/pqipersongrp_test.cc new file mode 100644 index 000000000..d189c94fc --- /dev/null +++ b/libretroshare/src/tests/pqi/pqipersongrp_test.cc @@ -0,0 +1,266 @@ +/* + * libretroshare/src/test/pqi pqiperson_test.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * pqiperson acts as the wrapper for all connection methods to a single peer. + * + * This test creates, a pqiperson and simulates connections, disconnections. + * packets passing through. + * + */ + + + + + + +#include "pqi/pqiperson.h" +#include "pqi/pqibin.h" + +#include "testconnect.h" + +#include "util/rsnet.h" +#include +#include +#include "util/utest.h" + +INITTEST(); + +int test_person_basic_reset(); +int test_person_basic_listen(); + + +int main(int argc, char **argv) +{ + std::cerr << "pqiperson_test" << std::endl; + + test_person_basic_reset(); + test_person_basic_listen(); + + FINALREPORT("pqiperson_test"); + + return TESTRESULT(); +} + +/****************************************************** + * + * tests() + * + **** ensure that functions call children + * pqiperson::reset() + * pqiperson::listen() + * pqiperson::stoplistening() + * + * + * pqiperson::connect(...) + * -> check that gets through to children. + * -> check that cannot have simultaneous connections. + * -> + * + */ + + +/******************************************************* + * + * Test structure + *****************/ + +#define NUM_CHILDREN 3 + +pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); + +class pqipersongrpTestHarness: public pqipersongrp +{ + public: + pqipersongrpTestHarness(SecurityPolicy *pol, unsigned long flags) + :pqipersongrp(pol, flags) + { + return; + } + + protected: + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +virtual pqilistener *createListener(struct sockaddr_in laddr) +{ + return new pqilistener(laddr); +} + +virtual pqiperson *createPerson(std::string id, pqilistener *listener) +{ + return createTestPerson(id, this); +} + + /********* FUNCTIONS to OVERLOAD for specialisation ********/ +}; + + + + +pqiperson *createTestPerson(std::string id, pqipersongrp *ppg) +{ + /* now add test children */ + { + std::cerr << "createTestPerson()"; + std::cerr << std::endl; + } + + pqiperson *pqip = new pqiperson(id, ppg); + + /* construct the serialiser .... + * Needs: + * * FileItem + * * FileData + * * ServiceGeneric + */ + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsFileItemSerialiser()); + rss->addSerialType(new RsCacheItemSerialiser()); + rss->addSerialType(new RsServiceSerialiser()); + + NetBinDummy *dummy1 = new NetBinDummy(pqip, id, PQI_CONNECT_TCP); + pqiconnect *pqisc = new testConnect(rss, dummy1); + addTestConnect(pqisc); + pqip -> addChildInterface(PQI_CONNECT_TCP, pqisc); + + RsSerialiser *rss2 = new RsSerialiser(); + rss2->addSerialType(new RsFileItemSerialiser()); + rss2->addSerialType(new RsCacheItemSerialiser()); + rss2->addSerialType(new RsServiceSerialiser()); + + NetBinDummy *dummy2 = new NetBinDummy(pqip, id, PQI_CONNECT_TUNNEL); + pqiconnect *pqicontun = new testConnect(rss2, dummy2); + addTestConnect(pqicontun); + pqip -> addChildInterface(PQI_CONNECT_TUNNEL, pqicontun); + + + RsSerialiser *rss3 = new RsSerialiser(); + rss3->addSerialType(new RsFileItemSerialiser()); + rss3->addSerialType(new RsCacheItemSerialiser()); + rss3->addSerialType(new RsServiceSerialiser()); + + NetBinDummy *dummy3 = new NetBinDummy(pqip, id, PQI_CONNECT_UDP); + pqiconnect *pqiusc = new testConnect(rss3, dummy3); + addTestConnect(pqiusc); + pqip -> addChildInterface(PQI_CONNECT_UDP, pqiusc); + + return pqip; +} + + +/* First Sets of Tests are very basic: + * reset() + * connect() + * listen() / stoplistening() + * disconnect() + */ + +int test_person_basic_reset() +{ + /* reset test */ + resetTestConnects(); + + /* create test person */ + std::string id = "12345678901234567890123456789012"; + + pqipersongrp *ppg = pqipersongrpTestHarness(NULL, 0); + + /* setup fake other bits */ + + + /* add peers - and watch it all happen! */ + + + + pqiperson *person = createTestPerson(id, ppg); + + /* reset person */ + person->reset(); + + /* count number of resets */ + CHECK(NUM_CHILDREN == testCounter); + + int i; + for(i = 0; i < NUM_CHILDREN; i++) + { + CHECK(testResetTimes[i].size() == 1); + CHECK(testConnectState[i] == 0); + CHECK(testConnectTimes[i].size() == 0); + } + + /* clean up */ + delete person; + + REPORT("test_person_basic_reset()"); + + return 1; +} + + +int test_person_basic_listen() +{ + /* reset test */ + resetTestConnects(); + + /* create test person */ + std::string id = "12345678901234567890123456789012"; + pqipersongrp *ppg = NULL; + pqiperson *person = createTestPerson(id, ppg); + + /* reset person */ + person->listen(); + + /* count number of resets */ + CHECK(NUM_CHILDREN == testCounter); + + int i; + for(i = 0; i < NUM_CHILDREN; i++) + { + CHECK(testResetTimes[i].size() == 0); + CHECK(testConnectTimes[i].size() == 0); + CHECK(testConnectState[i] == TST_STATE_LISTEN); + } + + person->stoplistening(); + + for(i = 0; i < NUM_CHILDREN; i++) + { + CHECK(testResetTimes[i].size() == 0); + CHECK(testConnectTimes[i].size() == 0); + CHECK(testConnectState[i] == 0); + } + + /* clean up */ + delete person; + + REPORT("test_person_basic_listen()"); + + return 1; +} + + + + diff --git a/libretroshare/src/tests/pqi/testconnect.cc b/libretroshare/src/tests/pqi/testconnect.cc new file mode 100644 index 000000000..bc9193e7b --- /dev/null +++ b/libretroshare/src/tests/pqi/testconnect.cc @@ -0,0 +1,186 @@ +/* + * libretroshare/src/test/pqi testconnect.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****** + * pqiperson acts as the wrapper for all connection methods to a single peer. + * + * This test creates, a pqiperson and simulates connections, disconnections. + * packets passing through. + * + */ + + +#include "testconnect.h" +#include "pqi/pqibin.h" +#include +#include + +/******************************************************* + * + * Test structure + *****************/ + + +#define NUM_CONN_MAX 10 +#define NUM_CHILDREN 3 + +#define TST_STATE_CONNECT 0x0001 +#define TST_STATE_LISTEN 0x0002 + +/* static test variables */ +uint32_t testCounter = 0; +pqiconnect *testConnectPointer[NUM_CONN_MAX]; +uint32_t testConnectState[NUM_CONN_MAX]; +std::list testConnectTimes[NUM_CONN_MAX]; +std::list testConnectAddrs[NUM_CONN_MAX]; + +std::list testResetState[NUM_CONN_MAX]; +std::list testResetTimes[NUM_CONN_MAX]; + +uint32_t findWhichConnect(pqiconnect *conn) +{ + int i; + for(i = 0; i < NUM_CONN_MAX; i++) + { + if (testConnectPointer[i] == conn) + { + return i; + } + } + // error. + std::cerr << "Connect Missing" << std::endl; + exit(1); + return 0; +} + +void addTestConnect(pqiconnect *pqi) +{ + testConnectPointer[testCounter] = pqi; + testConnectState[testCounter] = 0; + testCounter++; + if (testCounter > NUM_CONN_MAX) + { + std::cerr << "Too Many Connects" << std::endl; + exit(1); + } +} + +void resetTestConnects() +{ + testCounter = 0; + int i; + for(i = 0; i < NUM_CONN_MAX; i++) + { + testConnectAddrs[i].clear(); + testConnectTimes[i].clear(); + testResetState[i].clear(); + testResetTimes[i].clear(); + } +} + + +testConnect::testConnect(RsSerialiser *rss, NetBinInterface *ni_in) + :pqiconnect(rss, ni_in) +{ + +} + +testConnect::~testConnect() +{ + return; +} + + /* dummyConnect */ +int testConnect::connect(struct sockaddr_in raddr) +{ + int cidx = findWhichConnect(this); + time_t now = time(NULL); + + testConnectState[cidx] |= TST_STATE_CONNECT; + testConnectTimes[cidx].push_back(now); + testConnectAddrs[cidx].push_back(raddr); + + std::cerr << "testConnect[" << cidx << "].connect() called"; + std::cerr << std::endl; + return 0; +} + +int testConnect::listen() +{ + int cidx = findWhichConnect(this); + testConnectState[cidx] |= TST_STATE_LISTEN; + std::cerr << "testConnect[" << cidx << "].listen() called"; + std::cerr << std::endl; + return 1; +} + +int testConnect::stoplistening() +{ + int cidx = findWhichConnect(this); + testConnectState[cidx] &= ~TST_STATE_LISTEN; + std::cerr << "testConnect[" << cidx << "].stoplistening() called"; + std::cerr << std::endl; + return 1; +} + +int testConnect::reset() +{ + int cidx = findWhichConnect(this); + time_t now = time(NULL); + + // reset everything except listening. + testResetState[cidx].push_back(testConnectState[cidx]); + testResetTimes[cidx].push_back(now); + testConnectState[cidx] &= TST_STATE_LISTEN; + + std::cerr << "testConnect[" << cidx << "].reset() called"; + std::cerr << std::endl; + return 1; +} + +// leave this as is virtual int disconnect() { return ni -> reset(); } + +bool testConnect::connect_parameter(uint32_t type, uint32_t value) +{ + int cidx = findWhichConnect(this); + //testConnectState[cidx] |= TST_STATE_LISTEN; + std::cerr << "testConnect[" << cidx << "].connect_parameter() called"; + std::cerr << std::endl; + return true; +} + +int testConnect::getConnectAddress(struct sockaddr_in &raddr) +{ + int cidx = findWhichConnect(this); + if (testConnectAddrs[cidx].size() > 0) + { + raddr = testConnectAddrs[cidx].back(); + return 1; + } + std::cerr << "testConnect[" << cidx << "].getConnectAddress() called"; + std::cerr << std::endl; + return 0; +} + diff --git a/libretroshare/src/tests/pqi/testconnect.h b/libretroshare/src/tests/pqi/testconnect.h new file mode 100644 index 000000000..c0eda479c --- /dev/null +++ b/libretroshare/src/tests/pqi/testconnect.h @@ -0,0 +1,79 @@ +#ifndef TEST_PQICONNECT_H +#define TEST_PQICONNECT_H + +/* + * libretroshare/src/test/pqi testconnect.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2010 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqiperson.h" +//#include "pqi/pqibin.h" +#include "util/rsnet.h" + +/******************************************************* + * + * Test structure + *****************/ + + +#define NUM_CONN_MAX 10 + +#define TST_STATE_CONNECT 0x0001 +#define TST_STATE_LISTEN 0x0002 + +/* static test variables */ +extern uint32_t testCounter; +extern pqiconnect *testConnectPointer[NUM_CONN_MAX]; +extern uint32_t testConnectState[NUM_CONN_MAX]; +extern std::list testConnectTimes[NUM_CONN_MAX]; +extern std::list testConnectAddrs[NUM_CONN_MAX]; + +extern std::list testResetState[NUM_CONN_MAX]; +extern std::list testResetTimes[NUM_CONN_MAX]; + +uint32_t findWhichConnect(pqiconnect *conn); +void addTestConnect(pqiconnect *pqi); +void resetTestConnects(); + +class testConnect: public pqiconnect +{ + public: + + testConnect(RsSerialiser *rss, NetBinInterface *ni_in); + virtual ~testConnect(); + + /* dummyConnect */ + virtual int connect(struct sockaddr_in raddr); + virtual int listen(); + virtual int stoplistening(); + virtual int reset(); + virtual bool connect_parameter(uint32_t type, uint32_t value); + virtual int getConnectAddress(struct sockaddr_in &raddr); +}; // end of testConnect. + + +pqiperson *createTestPerson(std::string id, pqipersongrp *ppg); + + +#endif + diff --git a/libretroshare/src/tests/printcache/argstream.h b/libretroshare/src/tests/printcache/argstream.h new file mode 100644 index 000000000..137856794 --- /dev/null +++ b/libretroshare/src/tests/printcache/argstream.h @@ -0,0 +1,814 @@ +/* Copyright (C) 2004 Xavier Dcoret +* + * argsteam is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Foobar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ARGSTREAM_H +#define ARGSTREAM_H + + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + class argstream; + + template + class ValueHolder; + + template + argstream& operator>> (argstream&, const ValueHolder&); + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of ValueHolder + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + template + class ValueHolder + { + public: + ValueHolder(char s, + const char* l, + T& b, + const char* desc, + bool mandatory); + ValueHolder(const char* l, + T& b, + const char* desc, + bool mandatory); + ValueHolder(char s, + T& b, + const char* desc, + bool mandatory); + friend argstream& operator>><>(argstream& s,const ValueHolder& v); + std::string name() const; + std::string description() const; + private: + std::string shortName_; + std::string longName_; + T* value_; + T initialValue_; + std::string description_; + bool mandatory_; + }; + template + inline ValueHolder + parameter(char s, + const char* l, + T& b, + const char* desc="", + bool mandatory = true) + { + return ValueHolder(s,l,b,desc,mandatory); + } + template + inline ValueHolder + parameter(char s, + T& b, + const char* desc="", + bool mandatory = true) + { + return ValueHolder(s,b,desc,mandatory); + } + template + inline ValueHolder + parameter(const char* l, + T& b, + const char* desc="", + bool mandatory = true) + { + return ValueHolder(l,b,desc,mandatory); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of OptionHolder + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + class OptionHolder + { + public: + inline OptionHolder(char s, + const char* l, + bool& b, + const char* desc); + inline OptionHolder(const char* l, + bool& b, + const char* desc); + inline OptionHolder(char s, + bool& b, + const char* desc); + friend argstream& operator>>(argstream& s,const OptionHolder& v); + inline std::string name() const; + inline std::string description() const; + protected: + inline OptionHolder(char s, + const char* l, + const char* desc); + friend OptionHolder help(char s='h', + const char* l="help", + const char* desc="Display this help"); + private: + std::string shortName_; + std::string longName_; + bool* value_; + std::string description_; + }; + inline OptionHolder + option(char s, + const char* l, + bool& b, + const char* desc="") + { + return OptionHolder(s,l,b,desc); + } + inline OptionHolder + option(char s, + bool& b, + const char* desc="") + { + return OptionHolder(s,b,desc); + } + inline OptionHolder + option(const char* l, + bool& b, + const char* desc="") + { + return OptionHolder(l,b,desc); + } + inline OptionHolder + help(char s, + const char* l, + const char* desc) + { + return OptionHolder(s,l,desc); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of ValuesHolder + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + template + class ValuesHolder + { + public: + ValuesHolder(const O& o, + const char* desc, + int len); + template friend argstream& operator>>(argstream& s,const ValuesHolder& v); + std::string name() const; + std::string description() const; + typedef T value_type; + private: + mutable O value_; + std::string description_; + int len_; + char letter_; + }; + template + inline ValuesHolder + values(const O& o, + const char* desc="", + int len=-1) + { + return ValuesHolder(o,desc,len); + } + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of ValueParser + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + template + class ValueParser + { + public: + inline T operator()(const std::string& s) const + { + std::istringstream is(s); + T t; + is>>t; + return t; + } + }; + // We need to specialize for string otherwise parsing of a value that + // contains space (for example a string with space passed in quotes on the + // command line) would parse only the first element of the value!!! + template <> + class ValueParser + { + public: + inline std::string operator()(const std::string& s) const + { + return s; + } + }; + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // Interface of argstream + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + class argstream + { + public: + inline argstream(int argc,char** argv); + inline argstream(const char* c); + template + friend argstream& operator>>(argstream& s,const ValueHolder& v); + friend inline argstream& operator>>(argstream& s,const OptionHolder& v); + template + friend argstream& operator>>(argstream& s,const ValuesHolder& v); + + inline bool helpRequested() const; + inline bool isOk() const; + inline std::string errorLog() const; + inline std::string usage() const; + inline void defaultErrorHandling(bool ignoreUnused=false) const; + static inline char uniqueLetter(); + protected: + void parse(int argc,char** argv); + private: + typedef std::list::iterator value_iterator; + typedef std::pair help_entry; + std::string progName_; + std::map options_; + std::list values_; + bool minusActive_; + bool isOk_; + std::deque argHelps_; + std::string cmdLine_; + std::deque errors_; + bool helpRequested_; + }; + //************************************************************ + // Implementation of ValueHolder + //************************************************************ + template + ValueHolder::ValueHolder(char s, + const char* l, + T& v, + const char* desc, + bool mandatory) + : shortName_(1,s), + longName_(l), + value_(&v), + initialValue_(v), + description_(desc), + mandatory_(mandatory) + { + } + template + ValueHolder::ValueHolder(const char* l, + T& v, + const char* desc, + bool mandatory) + : longName_(l), + value_(&v), + initialValue_(v), + description_(desc), + mandatory_(mandatory) + { + } + template + ValueHolder::ValueHolder(char s, + T& v, + const char* desc, + bool mandatory) + : shortName_(1,s), + value_(&v), + initialValue_(v), + description_(desc), + mandatory_(mandatory) + { + } + template + std::string + ValueHolder::name() const + { + std::ostringstream os; + if (!shortName_.empty()) os<<'-'< + std::string + ValueHolder::description() const + { + std::ostringstream os; + os< + //************************************************************ + template + ValuesHolder::ValuesHolder(const O& o, + const char* desc, + int len) + : value_(o), + description_(desc), + len_(len) + { + letter_ = argstream::uniqueLetter(); + } + template + std::string + ValuesHolder::name() const + { + std::ostringstream os; + os< + std::string + ValuesHolder::description() const + { + return description_; + } + //************************************************************ + // Implementation of argstream + //************************************************************ + inline + argstream::argstream(int argc,char** argv) + : progName_(argv[0]), + minusActive_(true), + isOk_(true) + { + parse(argc,argv); + } + inline + argstream::argstream(const char* c) + : progName_(""), + minusActive_(true), + isOk_(true) + { + std::string s(c); + // Build argc, argv from s. We must add a dummy first element for + // progName because parse() expects it!! + std::deque args; + args.push_back(""); + std::istringstream is(s); + while (is.good()) + { + std::string t; + is>>t; + args.push_back(t); + } + char* pargs[args.size()]; + char** p = pargs; + for (std::deque::const_iterator + iter = args.begin(); + iter != args.end();++iter) + { + *p++ = const_cast(iter->c_str()); + } + parse(args.size(),pargs); + } + inline void + argstream::parse(int argc,char** argv) + { + // Run thru all arguments. + // * it has -- in front : it is a long name option, if remainder is empty, + // it is an error + // * it has - in front : it is a sequence of short name options, if + // remainder is empty, deactivates option (- will + // now be considered a char). + // * if any other char, or if option was deactivated + // : it is a value. Values are split in parameters + // (immediately follow an option) and pure values. + // Each time a value is parsed, if the previously parsed argument was an + // option, then the option is linked to the value in case of it is a + // option with parameter. The subtle point is that when several options + // are given with short names (ex: -abc equivalent to -a -b -c), the last + // parsed option is -c). + // Since we use map for option, any successive call overides the previous + // one: foo -a -b -a hello is equivalent to foo -b -a hello + // For values it is not true since we might have several times the same + // value. + value_iterator* lastOption = NULL; + for (char** a = argv,**astop=a+argc;++a!=astop;) + { + std::string s(*a); + if (minusActive_ && s[0] == '-') + { + if (s.size() > 1 && s[1] == '-') + { + if (s.size() == 2) + { + minusActive_ = false; + continue; + } + lastOption = &(options_[s.substr(2)] = values_.end()); + } + else + { + if (s.size() > 1) + { + // Parse all chars, if it is a minus we have an error + for (std::string::const_iterator cter = s.begin(); + ++cter != s.end();) + { + if (*cter == '-') + { + isOk_ = false; + std::ostringstream os; + os<<"- in the middle of a switch "<::const_iterator + iter = options_.begin();iter != options_.end();++iter) + { + std::cout<<"DEBUG: option "<first; + if (iter->second != values_.end()) + { + std::cout<<" -> "<<*(iter->second); + } + std::cout<::const_iterator + iter = values_.begin();iter != values_.end();++iter) + { + std::cout<<"DEBUG: value "<<*iter<::const_iterator + iter = argHelps_.begin();iter != argHelps_.end();++iter) + { + if (lmaxfirst.size()) lmax = iter->first.size(); + } + for (std::deque::const_iterator + iter = argHelps_.begin();iter != argHelps_.end();++iter) + { + os<<'\t'<first<first.size(),' ') + <<" : "<second<<'\n'; + } + return os.str(); + } + inline std::string + argstream::errorLog() const + { + std::string s; + for(std::deque::const_iterator iter = errors_.begin(); + iter != errors_.end();++iter) + { + s += *iter; + s += '\n'; + } + return s; + } + inline char + argstream::uniqueLetter() + { + static unsigned int c = 'a'; + return c++; + } + template + argstream& + operator>>(argstream& s,const ValueHolder& v) + { + // Search in the options if there is any such option defined either with a + // short name or a long name. If both are found, only the last one is + // used. +#ifdef ARGSTREAM_DEBUG + std::cout<<"DEBUG: searching "<::iterator iter = + s.options_.find(v.shortName_); + if (iter == s.options_.end()) + { + iter = s.options_.find(v.longName_); + } + if (iter != s.options_.end()) + { + // If we find counterpart for value holder on command line, either it + // has an associated value in which case we assign it, or it has not, in + // which case we have an error. + if (iter->second != s.values_.end()) + { +#ifdef ARGSTREAM_DEBUG + std::cout<<"DEBUG: found value "<<*(iter->second)< p; + *(v.value_) = p(*(iter->second)); + // The option and its associated value are removed, the subtle thing + // is that someother options might have this associated value too, + // which we must invalidate. + s.values_.erase(iter->second); + for (std::map::iterator + jter = s.options_.begin();jter != s.options_.end();++jter) + { + if (jter->second == iter->second) + { + jter->second = s.values_.end(); + } + } + s.options_.erase(iter); + } + else + { + s.isOk_ = false; + std::ostringstream os; + os<<"No value following switch "<first + <<" on command line"; + s.errors_.push_back(os.str()); + } + } + else + { + if (v.mandatory_) + { + s.isOk_ = false; + std::ostringstream os; + os<<"Mandatory parameter "; + if (!v.shortName_.empty()) os<<'-'<>(argstream& s,const OptionHolder& v) + { + // Search in the options if there is any such option defined either with a + // short name or a long name. If both are found, only the last one is + // used. +#ifdef ARGSTREAM_DEBUG + std::cout<<"DEBUG: searching "<::iterator iter = + s.options_.find(v.shortName_); + if (iter == s.options_.end()) + { + iter = s.options_.find(v.longName_); + } + if (iter != s.options_.end()) + { + // If we find counterpart for value holder on command line then the + // option is true and if an associated value was found, it is ignored + if (v.value_ != NULL) + { + *(v.value_) = true; + } + else + { + s.helpRequested_ = true; + } + // The option only is removed + s.options_.erase(iter); + } + else + { + if (v.value_ != NULL) + { + *(v.value_) = false; + } + else + { + s.helpRequested_ = false; + } + } + return s; + } + template + argstream& + operator>>(argstream& s,const ValuesHolder& v) + { + s.argHelps_.push_back(argstream::help_entry(v.name(),v.description())); + { + std::ostringstream os; + os<<' '<::iterator first = s.values_.begin(); + // We add to the iterator as much values as we can, limited to the length + // specified (if different of -1) + int n = v.len_ != -1?v.len_:s.values_.size(); + while (first != s.values_.end() && n-->0) + { + // Read the value from the string *first + ValueParser p; + *(v.value_++) = p(*first ); + s.argHelps_.push_back(argstream::help_entry(v.name(),v.description())); + // The value we just removed was maybe "remembered" by an option so we + // remove it now. + for (std::map::iterator + jter = s.options_.begin();jter != s.options_.end();++jter) + { + if (jter->second == first) + { + jter->second = s.values_.end(); + } + } + ++first; + } + // Check if we have enough values + if (n != 0) + { + s.isOk_ = false; + std::ostringstream os; + os<<"Expecting "< +#include +#include + +#include "argstream.h" +#include "pqi/pqistreamer.h" +#include "pqi/pqibin.h" +#include "serialiser/rsdistribitems.h" +#include "pqi/pqistore.h" + +int main(int argc, char **argv) +{ + try + { + argstream as(argc,argv) ; + bool full_print = false ; + + std::string cacheFileName; + + as >> parameter('f',"file",cacheFileName,"cache file name to read",true) + >> option('F',"full",full_print,"full dump of distrib items") + >> help() ; + + as.defaultErrorHandling() ; + + std::cout << "opening file: " << cacheFileName << std::endl; + // open file + BinInterface *bio = new BinFileInterface(cacheFileName.c_str(), BIN_FLAGS_READABLE); + RsSerialiser *rsSerialiser = new RsSerialiser(); + RsSerialType *serialType = new RsDistribSerialiser(); + rsSerialiser->addSerialType(serialType); + pqistore *store = new pqistore(rsSerialiser, "", bio, BIN_FLAGS_READABLE); + RsItem* item; + + std::set already ; + int signed_msgs = 0 ; + int distrib_msgs = 0 ; + int nb_duplicated = 0 ; + + // then print out contents to screen + while(NULL != (item = store->GetItem())) + { + + if(full_print) + item->print(std::cout, 0); + else + { + { + RsDistribMsg *i = dynamic_cast(item) ; + if(i!=NULL) + { + std::cerr << "Grp=" << i->grpId << ", parent=" << i->parentId << ", msgId=" << i->msgId ; + + if(already.find(i->msgId)!=already.end()) + { + std::cerr << " *** double ***" ; + ++nb_duplicated ; + } + else + already.insert(i->msgId) ; + + std::cerr << std::endl; + ++distrib_msgs ; + } + } + { + RsDistribSignedMsg *i = dynamic_cast(item) ; + if(i!=NULL) + { + std::cerr << "Grp=" << i->grpId << ", msgId=" << i->msgId << ", type=" << i->packet.tlvtype << ", len=" << i->packet.bin_len ; + + if(already.find(i->msgId)!=already.end()) + { + std::cerr << " *** double ***" ; + ++nb_duplicated ; + } + else + already.insert(i->msgId) ; + + std::cerr << std::endl; + + ++signed_msgs ; + } + } + } + } + + std::cerr << std::endl ; + std::cerr << "Signed messages (RsDistribMsg) : " << distrib_msgs << std::endl; + std::cerr << "Signed messages (RsDistribSignedMsg): " << signed_msgs << std::endl; + std::cerr << "Duplicate messages : " << nb_duplicated << std::endl; + + return 0; + } + catch(std::exception& e) + { + std::cerr << "Unhandled exception: " << e.what() << std::endl; + return 1 ; + } +} + + + diff --git a/libretroshare/src/tests/printcache/main_extended.cpp b/libretroshare/src/tests/printcache/main_extended.cpp new file mode 100644 index 000000000..0c77a6348 --- /dev/null +++ b/libretroshare/src/tests/printcache/main_extended.cpp @@ -0,0 +1,153 @@ +/* + * main.cpp + * + * Created on: 11 Apr 2011 + * Author: greyfox + */ + +#include +#include +#include + +#include "argstream.h" +#include "pqi/pqistreamer.h" +#include "pqi/pqibin.h" +#include "serialiser/rsdistribitems.h" +#include "pqi/pqistore.h" + +int storeMsg(std::map > &msgMap, std::string filename, + std::string grpId, std::string msgId); + +pqistore *BuildSerialiser(int type, std::string filename); + +int main(int argc, char **argv) +{ + + std::list fileList; + std::list::iterator fit; + + for(int i = 1; i < argc; i++) + { + fileList.push_back(argv[i]); + } + + std::map > msgMap; + std::map >::iterator mit; + + bool printInput = true; + bool printAll = true; + bool printSummary = true; + int distrib_msgs = 0; + int signed_msgs = 0; + + for(fit = fileList.begin(); fit != fileList.end(); fit++) + { + if (printInput) + { + std::cerr << "Loading File: " << *fit; + std::cerr << std::endl; + } + + /* process this file */ + pqistore *store = BuildSerialiser(0, *fit); + RsItem* item; + RsDistribMsg *distMsg; + RsDistribSignedMsg *signMsg; + + while(NULL != (item = store->GetItem())) + { + if (NULL != (distMsg = dynamic_cast(item))) + { + if (printInput) + { + std::cerr << "Grp = " << distMsg->grpId; + std::cerr << ", parent = " << distMsg->parentId; + std::cerr << ", msgId = " << distMsg->msgId; + std::cerr << std::endl; + } + storeMsg(msgMap, *fit, distMsg->grpId, distMsg->msgId); + ++distrib_msgs ; + } + if (NULL != (signMsg = dynamic_cast(item))) + { + if (printInput) + { + std::cerr << "Grp = " << signMsg->grpId; + std::cerr << ", msgId = " << signMsg->msgId; + std::cerr << ", type = " << signMsg->packet.tlvtype; + std::cerr << ", len = " << signMsg->packet.bin_len; + std::cerr << std::endl; + } + storeMsg(msgMap, *fit, signMsg->grpId, signMsg->msgId); + ++signed_msgs ; + } + } + + delete store; + } + for(mit = msgMap.begin(); mit != msgMap.end(); mit++) + { + bool print = printAll; + if (mit->second.size() > 1) + { + /* duplicates */ + print = true; + } + + if (print) + { + std::cerr << "MsgId: " << mit->first; + std::cerr << " in Files: "; + + std::list::iterator fit; + for(fit = mit->second.begin(); fit != mit->second.end(); fit++) + { + std::cerr << *fit << " "; + } + std::cerr << std::endl; + } + } + if (printSummary) + { + std::cerr << "# RsDistribMsg(s): " << distrib_msgs << std::endl; + std::cerr << "# RsDistribSignedMsg(s): " << signed_msgs << std::endl; + std::cerr << std::endl; + } +} + + +int storeMsg(std::map > &msgMap, std::string filename, + std::string grpId, std::string msgId) +{ + std::map >::iterator mit; + mit = msgMap.find(msgId); + if (mit == msgMap.end()) + { + std::list fileList; + fileList.push_back(filename); + msgMap[msgId] = fileList; + } + else + { + (mit->second).push_back(filename); + } + return 1; +} + + +pqistore *BuildSerialiser(int type, std::string filename) +{ + BinInterface *bio = new BinFileInterface(filename.c_str(), BIN_FLAGS_READABLE); + RsSerialiser *rsSerialiser = new RsSerialiser(); + RsSerialType *serialType = new RsDistribSerialiser(); + rsSerialiser->addSerialType(serialType); + + // can use type to add more serialiser types + //RsSerialType *serialType = new RsDistribSerialiser(); + //rsSerialiser->addSerialType(serialType); + + pqistore *store = new pqistore(rsSerialiser, "", bio, BIN_FLAGS_READABLE); + return store; +} + + diff --git a/libretroshare/src/tests/printcache/printcache.pro b/libretroshare/src/tests/printcache/printcache.pro new file mode 100644 index 000000000..04b19511c --- /dev/null +++ b/libretroshare/src/tests/printcache/printcache.pro @@ -0,0 +1,30 @@ +TEMPLATE = app +CONFIG = debug + +#SOURCES = main.cpp +SOURCES = main_extended.cpp + +INCLUDEPATH *= ../.. +linux { + #LIBS = -lstdc++ -lm + LIBS += ../../lib/libretroshare.a ../../../../libbitdht/src/lib/libbitdht.a + LIBS += -lssl -lcrypto -lgpgme -lupnp -lgnome-keyring +} +macx { + # ENABLE THIS OPTION FOR Univeral Binary BUILD. + # CONFIG += ppc x86 + # QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 + # CONFIG -= uitools + + LIBS += ../../lib/libretroshare.a + LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan + LIBS += ../../../../../miniupnpc-1.0/libminiupnpc.a + LIBS += ../../../../libbitdht/src/lib/libbitdht.a + LIBS += -framework CoreFoundation + LIBS += -framework Security + + # LIBS += -framework CoreServices + + +} + diff --git a/libretroshare/src/tests/scripts/checks.mk b/libretroshare/src/tests/scripts/checks.mk new file mode 100644 index 000000000..dcb19ff3f --- /dev/null +++ b/libretroshare/src/tests/scripts/checks.mk @@ -0,0 +1,25 @@ +#Basic checks + +ifndef RS_TOP_DIR +dummy: + echo "RS_TOP_DIR is not defined in your makefile" +endif + +#ifndef SSL_DIR +#dummy: +# echo "you must define SSL_DIR before you can compile" +# +#endif + +ifneq ($(OS),Linux) + ifneq ($(OS),MacOSX) + ifndef PTHREADS_DIR +dummy: + echo "you must define PTHREADS_DIR before you can compile" + + endif + endif +endif + + + diff --git a/libretroshare/src/tests/scripts/config-cygwin.mk b/libretroshare/src/tests/scripts/config-cygwin.mk new file mode 100644 index 000000000..ec4518f68 --- /dev/null +++ b/libretroshare/src/tests/scripts/config-cygwin.mk @@ -0,0 +1,118 @@ +ifneq ($(OS),Cygwin) +dummy: + echo "ERROR Cygwin configuration file included, but (OS != Cygwin) + +endif + +############ LINUX CONFIGURATION ######################## + +# flags for components.... +PQI_USE_XPGP = 1 +#PQI_USE_PROXY = 1 +#PQI_USE_CHANNELS = 1 +#USE_FILELOOK = 1 + +########################################################################### + +#### DrBobs Versions.... Please Don't Delete. +### Comment out if needed. +ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW +SRC_ROOT=../../../.. + +PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads/pthreads.2 + +################### + +#ALT_SRC_ROOT=/cygdrive/c/RetroShareBuild/src +#SRC_ROOT=/cygdrive/c/RetroShareBuild/src + +#PTHREADS_DIR=$(ALT_SRC_ROOT)/pthreads-w32-2-8-0-release + +################### + +ZLIB_DIR=$(ALT_SRC_ROOT)/zlib-1.2.3 + +SSL_DIR=$(SRC_ROOT)/openssl-0.9.7g-xpgp-0.1c +UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 + +include $(RS_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ######################## + +CC = g++ +RM = /bin/rm +RANLIB = ranlib +LIBDIR = $(RS_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +# Unix: Linux/Cygwin +INCLUDE = -I $(RS_TOP_DIR) + +ifdef PQI_DEBUG + CFLAGS = -Wall -g $(INCLUDE) +else + CFLAGS = -Wall -O2 $(INCLUDE) +endif + +ifdef PQI_USE_XPGP + INCLUDE += -I $(SSL_DIR)/include +endif + +ifdef PQI_USE_XPGP + CFLAGS += -DPQI_USE_XPGP +endif + +ifdef PQI_USE_PROXY + CFLAGS += -DPQI_USE_PROXY +endif + +ifdef PQI_USE_CHANNELS + CFLAGS += -DPQI_USE_CHANNELS +endif + +ifdef USE_FILELOOK + CFLAGS += -DUSE_FILELOOK +endif + + +RSCFLAGS = -Wall -g $(INCLUDE) + +######################################################################### +# OS Compile Options +######################################################################### + +# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) +BIOCC = gcc + +# Cygwin - ?same? as Linux flags +BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM + +######################################################################### +# OS specific Linking. +######################################################################### + +# for static pthread libs.... +WININC += -DPTW32_STATIC_LIB +WININC += -mno-cygwin -mwindows -fno-exceptions +WININC += -DWINDOWS_SYS + +WINLIB = -lws2_32 -luuid -lole32 -liphlpapi +WINLIB += -lcrypt32 -lwinmm + +CFLAGS += -I$(PTHREADS_DIR) $(WININC) +CFLAGS += -I$(ZLIB_DIR) + +LIBS = -L$(LIBDIR) -lretroshare +ifdef PQI_USE_XPGP + LIBS += -L$(SSL_DIR) +endif + +LIBS += -lssl -lcrypto +LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += -L$(ZLIB_DIR) -lz +LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d +LIBS += $(WINLIB) + +RSCFLAGS += $(WININC) + + diff --git a/libretroshare/src/tests/scripts/config-linux.mk b/libretroshare/src/tests/scripts/config-linux.mk new file mode 100644 index 000000000..3f7a297da --- /dev/null +++ b/libretroshare/src/tests/scripts/config-linux.mk @@ -0,0 +1,74 @@ + +ifneq ($(OS),Linux) +dummy: + echo "ERROR Linux configuration file included, but (OS != Linux) + +endif + +############ LINUX CONFIGURATION ######################## + +#UPNPC_DIR=../../../../miniupnpc-1.0 + +# Need to define miniupnpc version because API changed a little between v1.0 and 1.2 +# put 10 for 1.0 and 12 for 1.2 +DEFINES += -D_FILE_OFFSET_BITS=64 + +include $(RS_TOP_DIR)/tests/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ######################## + +CC = g++ +RM = /bin/rm +RANLIB = ranlib +LIBDIR = $(RS_TOP_DIR)/lib +BITDIR = $(DHT_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a +BITDHT = $(BITDIR)/libbitdht.a +# Unix: Linux/Cygwin +INCLUDE = -I $(RS_TOP_DIR) +CFLAGS = -Wall -g $(INCLUDE) +#CFLAGS += -fprofile-arcs -ftest-coverage +CFLAGS += ${DEFINES} + +#ifdef PQI_USE_XPGP +# INCLUDE += -I $(SSL_DIR)/include +#endif +# +#ifdef PQI_USE_XPGP +# CFLAGS += -DPQI_USE_XPGP +#endif + +RSCFLAGS = -Wall -g $(INCLUDE) +######################################################################### +# OS Compile Options +######################################################################### + +# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) +BIOCC = gcc + +# march=i686 causes problems while 64Bit compiling, GCC tries to generate Output for a m64 machine, but the marchi686 +# doesnt allow the instructionfs for that. +# +# gcc docu: http://gcc.gnu.org/onlinedocs/gcc-4.0.3/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options + +# Linux flags +BIOCFLAGS = -I $(SSL_DIR)/include ${DEFINES} -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM + +######################################################################### +# OS specific Linking. +######################################################################### + +LIBS = -lgpgme -L$(LIBDIR) -lretroshare +LIBS += -L$(BITDIR) -lbitdht -lgnome-keyring +ifdef PQI_USE_XPGP + LIBS += -L$(SSL_DIR) + endif +LIBS += -lssl -lcrypto -lpthread +#LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += $(XLIB) -ldl -lz +LIBS += -lupnp + + +RSLIBS = $(LIBS) + + diff --git a/libretroshare/src/tests/scripts/config-macosx.mk b/libretroshare/src/tests/scripts/config-macosx.mk new file mode 100644 index 000000000..6b5fa8c66 --- /dev/null +++ b/libretroshare/src/tests/scripts/config-macosx.mk @@ -0,0 +1,97 @@ + +ifneq ($(OS),MacOSX) +dummy: + echo "ERROR MacOSX configuration file included, but (OS != MacOSX) + +endif + +############ LINUX CONFIGURATION ######################## + + +# FLAGS to decide if we want i386 Build or ppc Build +# +# + +# PPC is default +# Could define both for combined compilation... +# except might not work for bio_tou.c file! +# +# MAC_I386_BUILD = 1 +# MAC_PPC_BUILD = 1 + +MAC_I386_BUILD = 1 +#MAC_PPC_BUILD = 1 + +ifndef MAC_I386_BUILD + MAC_PPC_BUILD = 1 +endif + +UPNPC_DIR=../../../../../../src/miniupnpc-1.0 + +include $(RS_TOP_DIR)/tests/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ######################## + +CC = g++ +RM = /bin/rm + +RANLIB = ranlib + +# Dummy ranlib -> can't do it until afterwards with universal binaries. +# RANLIB = ls -l + +LIBDIR = $(RS_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +OPT_DIR = /opt/local +OPT_INCLUDE = $(OPT_DIR)/include +OPT_LIBS = $(OPT_DIR)/lib + +INCLUDE = -I $(RS_TOP_DIR) -I $(OPT_INCLUDE) +#CFLAGS = -Wall -O3 +CFLAGS = -Wall -g + +# Flags for architecture builds. +ifdef MAC_I386_BUILD + CFLAGS += -arch i386 +endif + +ifdef MAC_PPC_BUILD + CFLAGS += -arch ppc +endif + +CFLAGS += $(INCLUDE) + +# This Line is for Universal BUILD for 10.4 + 10.5 +# (but unlikely to work unless Qt Libraries are build properly) +#CFLAGS += -isysroot /Developer/SDKs/MacOSX10.5.sdk + +# RSCFLAGS = -Wall -O3 $(INCLUDE) + +######################################################################### +# OS Compile Options +######################################################################### + +######################################################################### +# OS specific Linking. +######################################################################### + +LIBS = -Wl,-search_paths_first + +# for Univeral BUILD +# LIBS += -arch ppc -arch i386 +#LIBS += -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5u.sdk + +LIBS += -L$(LIBDIR) -lretroshare +ifdef PQI_USE_XPGP + LIBS += -L$(SSL_DIR) + endif +LIBS += -lssl -lcrypto -lpthread +LIBS += -L$(OPT_LIBS) +LIBS += -lgpgme -lgpg-error +LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += $(XLIB) -ldl -lz + +RSLIBS = $(LIBS) + + diff --git a/libretroshare/src/tests/scripts/config-mingw.mk b/libretroshare/src/tests/scripts/config-mingw.mk new file mode 100644 index 000000000..c0040ac4e --- /dev/null +++ b/libretroshare/src/tests/scripts/config-mingw.mk @@ -0,0 +1,138 @@ +#ifneq ($(OS),"Win ") +#dummy: +# echo "ERROR OS = $(OS)" +# echo "ERROR MinGW configuration file included, but (OS != Win) +# +#endif + +############ LINUX CONFIGURATION ######################## + +# flags for components.... +#PQI_USE_XPGP = 1 +#PQI_USE_PROXY = 1 +#PQI_USE_CHANNELS = 1 +#USE_FILELOOK = 1 + +########################################################################### + +#### DrBobs Versions.... Please Don't Delete. +### Comment out if needed. +SRC_ROOT_PKG=/home/Mark/prog/retroshare/package/rs-win-v0.5.0/src +SRC_ROOT_GPG=/local + +#ALT_SRC_ROOT=/cygdrive/c/home/rmfern/prog/MinGW +#SRC_ROOT=../../../.. + +PTHREADS_DIR=$(SRC_ROOT_PKG)/pthreads-w32-2-8-0/Pre-built.2 +ZLIB_DIR=$(SRC_ROOT_PKG)/zlib-1.2.3 +SSL_DIR=$(SRC_ROOT_PKG)/openssl-tmp +UPNPC_DIR=$(SRC_ROOT_PKG)/miniupnpc-1.3 + +########################################################################### + +#### Enable this section for compiling with MSYS/MINGW compile +#SRC_ROOT=/home/linux + +#SSL_DIR=$(SRC_ROOT)/OpenSSL +#GPGME_DIR=$(SRC_ROOT)/gpgme-1.1.8 +#GPG_ERROR_DIR=$(SRC_ROOT)/libgpg-error-1.7 + +#ZLIB_DIR=$(SRC_ROOT)/zlib-1.2.3 +#UPNPC_DIR=$(SRC_ROOT)/miniupnpc-1.0 +#PTHREADS_DIR=$(SRC_ROOT)/pthreads-w32-2-8-0-release + +include $(RS_TOP_DIR)/scripts/checks.mk + +############ ENFORCE DIRECTORY NAMING ####################################### + +CC = g++ +RM = /bin/rm +RANLIB = ranlib +LIBDIR = $(RS_TOP_DIR)/lib +LIBRS = $(LIBDIR)/libretroshare.a + +# Unix: Linux/Cygwin +INCLUDE = -I $(RS_TOP_DIR) + +ifdef PQI_DEBUG + CFLAGS = -Wall -g $(INCLUDE) +else + CFLAGS = -Wall -O2 $(INCLUDE) +endif + +# These aren't used anymore.... really. +ifdef PQI_USE_XPGP + CFLAGS += -DPQI_USE_XPGP +endif + +ifdef PQI_USE_PROXY + CFLAGS += -DPQI_USE_PROXY +endif + +ifdef PQI_USE_CHANNELS + CFLAGS += -DPQI_USE_CHANNELS +endif + +ifdef USE_FILELOOK + CFLAGS += -DUSE_FILELOOK +endif + + +# SSL / pthreads / Zlib +# included by default for Windows compilation. +INCLUDE += -I $(SSL_DIR)/include +INCLUDE += -I$(PTHREADS_DIR) +INCLUDE += -I$(ZLIB_DIR) + + +######################################################################### +# OS Compile Options +######################################################################### + +# For the SSL BIO compilation. (Copied from OpenSSL compilation flags) +BIOCC = gcc + +# Cygwin - ?same? as Linux flags +BIOCFLAGS = -I $(SSL_DIR)/include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -O3 -fomit-frame-pointer -m486 -Wall -DSHA1_ASM -DMD5_ASM -DRMD160_ASM +BIOCFLAGS += -DWINDOWS_SYS + +######################################################################### +# OS specific Linking. +######################################################################### + +# for static pthread libs.... +#WININC += -DPTW32_STATIC_LIB +#WININC += -mno-cygwin -mwindows -fno-exceptions + +WININC += -DWINDOWS_SYS + +WINLIB = -lws2_32 -luuid -lole32 -liphlpapi +WINLIB += -lcrypt32 -lwinmm + +CFLAGS += -I$(SSL_DIR)/include +CFLAGS += -I$(PTHREADS_DIR)/include +CFLAGS += -I$(ZLIB_DIR) +CFLAGS += -I$(SRC_ROOT_GPG)/include + +### Enable this for GPGME and GPG ERROR dirs +#CFLAGS += -I$(GPGME_DIR)/src +#CFLAGS += -I$(GPG_ERROR_DIR)/src + +CFLAGS += $(WININC) + + + +LIBS = -L$(LIBDIR) -lretroshare + +LIBS += -L$(SSL_DIR) + +LIBS += -lssl -lcrypto +LIBS += -L$(UPNPC_DIR) -lminiupnpc +LIBS += -L$(ZLIB_DIR) -lz +LIBS += -L$(PTHREADS_DIR) -lpthreadGC2d +LIBS += $(WINLIB) + +#RSCFLAGS = -Wall -g $(INCLUDE) +#RSCFLAGS += $(WININC) + + diff --git a/libretroshare/src/tests/scripts/config.mk b/libretroshare/src/tests/scripts/config.mk new file mode 100644 index 000000000..951eca4c6 --- /dev/null +++ b/libretroshare/src/tests/scripts/config.mk @@ -0,0 +1,27 @@ + +# determine which operating system +# +########################################################################### +#Define OS. +# +OS = Linux +#OS = MacOSX +#OS = Cygwin +#OS = Win # MinGw. +########################################################################### + +ifeq ($(OS),Linux) + include $(RS_TOP_DIR)/tests/scripts/config-linux.mk +else + ifeq ($(OS),MacOSX) + include $(RS_TOP_DIR)/tests/scripts/config-macosx.mk + else + ifeq ($(OS),Cygwin) + include $(RS_TOP_DIR)/tests/scripts/config-cygwin.mk + else + include $(RS_TOP_DIR)/tests/scripts/config-mingw.mk + endif + endif +endif + +########################################################################### diff --git a/libretroshare/src/tests/scripts/regress.mk b/libretroshare/src/tests/scripts/regress.mk new file mode 100644 index 000000000..7d69df664 --- /dev/null +++ b/libretroshare/src/tests/scripts/regress.mk @@ -0,0 +1,25 @@ + +testoutputfiles = $(foreach tt,$(1),$(tt).tstout) + +%.tstout : %.sh % + -sh ./$< > $@ 2>&1 + +%.tstout : % + -./$< > $@ 2>&1 + +TESTOUT = $(call testoutputfiles,$(TESTS)) + +.phony : tests regress retest clobber + +tests: $(TESTS) + +regress: $(TESTOUT) + @-echo "--------------- SUCCESS (count):" + @-grep -c SUCCESS $(TESTOUT) + @-echo "--------------- FAILURE REPORTS:" + @-grep FAILURE $(TESTOUT) || echo no failures + @-echo "--------------- end" + +retest: + -/bin/rm $(TESTOUT) + diff --git a/libretroshare/src/tests/scripts/rules.mk b/libretroshare/src/tests/scripts/rules.mk new file mode 100644 index 000000000..3df30a488 --- /dev/null +++ b/libretroshare/src/tests/scripts/rules.mk @@ -0,0 +1,24 @@ + +# defines required / used. +# +# CFLAGS +# +# + +librs: $(RSOBJ) + $(AR) r $(LIBRS) $(RSOBJ) + $(RANLIB) $(LIBRS) + +.cc.o: + $(CC) $(CFLAGS) -c $< + +clean: + -/bin/rm -f $(RSOBJ) $(EXECOBJ) $(TESTOBJ) *.gcno *.gcda \ + *.gcov *.tstout $(TESTS) + +clobber: clean retest + -/bin/rm $(EXEC) $(TESTS) + + +include $(RS_TOP_DIR)/tests/scripts/regress.mk + diff --git a/libretroshare/src/tests/serialiser/Makefile b/libretroshare/src/tests/serialiser/Makefile new file mode 100644 index 000000000..062543b2b --- /dev/null +++ b/libretroshare/src/tests/serialiser/Makefile @@ -0,0 +1,76 @@ + +RS_TOP_DIR = ../.. +DHT_TOP_DIR = ../../../../libbitdht/src + +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/config.mk +############################################################### + +TESTOBJ = tlvbase_test.o tlvbase_test2.o rstunnelitem_test.o +TESTOBJ += tlvitems_test.o tlvstack_test.o rsserial_test.o +TESTOBJ += rstlvwidetest.o tlvrandom_test.o rsturtleitem_test.o +TESTOBJ += tlvtypes_test.o support.o distribitem_test.o rsmsgitem_test.o +TESTOBJ += rsstatusitem_test.o rsconfigitem_test.o + +TESTS = tlvbase_test tlvbase_test2 rstlvwidetest +TESTS += tlvitems_test tlvstack_test rstunnelitem_test +TESTS += tlvrandom_test rsserial_test rsturtleitem_test +TESTS += tlvtypes_test distribitem_test rsmsgitem_test +TESTS += rsstatusitem_test rsconfigitem_test + +#rsbaseitem_test + +all: tests + +tlvbase_test : tlvbase_test.o + $(CC) $(CFLAGS) -o tlvbase_test tlvbase_test.o $(OBJ) $(LIBS) + +tlvbase_test2 : tlvbase_test2.o + $(CC) $(CFLAGS) -o tlvbase_test2 tlvbase_test2.o $(OBJ) $(LIBS) + +tlvitems_test : tlvitems_test.o + $(CC) $(CFLAGS) -o tlvitems_test tlvitems_test.o $(OBJ) $(LIBS) + +tlvstack_test : tlvstack_test.o + $(CC) $(CFLAGS) -o tlvstack_test tlvstack_test.o $(OBJ) $(LIBS) + +rsserial_test : rsserial_test.o + $(CC) $(CFLAGS) -o rsserial_test rsserial_test.o $(OBJ) $(LIBS) + +rsbaseitem_test : rsbaseitem_test.o + $(CC) $(CFLAGS) -o rsbaseitem_test rsbaseitem_test.o $(OBJ) $(LIBS) + +rstlvwidetest : rstlvwidetest.o + $(CC) $(CFLAGS) -o rstlvwidetest rstlvwidetest.o $(OBJ) $(LIBS) + +tlvrandom_test : tlvrandom_test.o + $(CC) $(CFLAGS) -o tlvrandom_test tlvrandom_test.o $(OBJ) $(LIBS) + +rsturtleitem_test : rsturtleitem_test.o support.o + $(CC) $(CFLAGS) -o rsturtleitem_test rsturtleitem_test.o support.o $(OBJ) $(LIBS) + +rstunnelitem_test : rstunnelitem_test.o support.o + $(CC) $(CFLAGS) -o rstunnelitem_test rstunnelitem_test.o support.o $(OBJ) $(LIBS) + +tlvtypes_test : tlvtypes_test.o + $(CC) $(CFLAGS) -o tlvtypes_test tlvtypes_test.o $(OBJ) $(LIBS) + +distribitem_test : distribitem_test.o support.o + $(CC) $(CFLAGS) -o distribitem_test distribitem_test.o support.o $(OBJ) $(LIBS) + +rsmsgitem_test : rsmsgitem_test.o support.o + $(CC) $(CFLAGS) -o rsmsgitem_test rsmsgitem_test.o support.o $(OBJ) $(LIBS) + +rsstatusitem_test : rsstatusitem_test.o support.o + $(CC) $(CFLAGS) -o rsstatusitem_test rsstatusitem_test.o support.o $(OBJ) $(LIBS) + +rsconfigitem_test : rsconfigitem_test.o + $(CC) $(CFLAGS) -o rsconfigitem_test rsconfigitem_test.o support.o $(OBJ) $(LIBS) + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/tests/serialiser/TestNotes.txt b/libretroshare/src/tests/serialiser/TestNotes.txt new file mode 100644 index 000000000..90c459120 --- /dev/null +++ b/libretroshare/src/tests/serialiser/TestNotes.txt @@ -0,0 +1,56 @@ + +Few test still need to be done. Needs to be automated + +used support(.h/.cc) file for testing RsItems + +Components and Tests. +============================================================ +------------------------------------------------------------ +Basic Items +------------------------------------------------------------ +rsbaseitems.cc : needed +rsbaseserial.cc : needed +rsconfigitems.cc : needed +rsserial.cc : needed + + + + +------------------------------------------------------------ +Compound TLV Components +------------------------------------------------------------ + +rstlvaddrs.cc : needed +rstlvbase.cc : not finished, tlvbase_test +rstlvfileitem.cc : tlvtypes_test +rstlvimage.cc : tlvtypes_test +rstlvkeys.cc : tlvtypes_test +rstlvkvwide.cc : rstlvwidetest +rstlvtypes.cc : tlvtypes_test +rstlvutil.cc : no need + +------------------------------------------------------------ +Service Components +------------------------------------------------------------ +rstunnelitems.cc : rstunnelitem_test & rsturtleitem_test +rsdistribitem.cc : distribitem_test +rsmsgitem.cc : msgitem_test +rsdiscitems.cc : needed +rsrankitems.cc : needed +rsblogitems.cc : distribitem_test +rschannelitems.cc : distribitem_test +rsforumitems.cc : distribitem_test +rsstatusitems.cc : needed +rsgameitems.cc : TBC +rsphotoitems.cc : TBC + +============================================================ +Test Specifics +============================================================ + +------------------------------------------------------------ +Basic Components +------------------------------------------------------------ + + + diff --git a/libretroshare/src/tests/serialiser/distribitem_test.cc b/libretroshare/src/tests/serialiser/distribitem_test.cc new file mode 100644 index 000000000..a3d479735 --- /dev/null +++ b/libretroshare/src/tests/serialiser/distribitem_test.cc @@ -0,0 +1,365 @@ +/* + * libretroshare/src/serialiser: distribitem_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2010 by Christopher Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include "serialiser/rsdistribitems.h" +#include "serialiser/rschannelitems.h" +#include "serialiser/rsforumitems.h" +#include "serialiser/rsblogitems.h" +#include "retroshare/rsdistrib.h" +#include "serialiser/rstlvutil.h" +#include "util/utest.h" +#include "support.h" + +#include "distribitem_test.h" + +INITTEST() + +/** base rs distrib items **/ + + + + +RsSerialType* init_item(RsDistribGrp& grp) +{ + + time_t now = time(NULL); + + /* create Keys */ + + /* Create Group Description */ + + randString(SHORT_STR, grp.grpName); + randString(LARGE_STR, grp.grpDesc); + + grp.timestamp = now; + grp.grpFlags = (RS_DISTRIB_PRIVACY_MASK | RS_DISTRIB_AUTHEN_MASK); + grp.grpControlFlags = 0; + + init_item(grp.grpPixmap); + + /* set keys */ + + RsTlvSecurityKey publish_key; + + init_item(grp.adminKey); + init_item(publish_key); + init_item(grp.adminSignature); + + grp.publishKeys.keys[publish_key.keyId] = publish_key; + grp.publishKeys.groupId = grp.adminKey.keyId; + grp.grpId = grp.adminKey.keyId; + + init_item(grp.grpControlList); + + return new RsDistribSerialiser(); + +} + + +RsSerialType* init_item(RsDistribGrpKey& gk) +{ + + init_item(gk.key); + gk.grpId = gk.key.keyId; + + return new RsDistribSerialiser(); + +} + + +bool operator==(const RsDistribGrpKey& gk1, const RsDistribGrpKey& gk2) +{ + if(gk1.grpId != gk1.grpId) return false; + if(!(gk1.key == gk2.key)) return false; + + return true; +} + +RsSerialType* init_item(RsDistribSignedMsg& sMsg) +{ + + RsChannelMsg chMsg; + RsSerialType* ser = init_item(chMsg); + uint32_t chMsgSize = ser->size(&chMsg); + char* chMsgData = new char[chMsgSize]; + ser->serialise(&chMsg, chMsgData, &chMsgSize); + delete ser; + + sMsg.packet.setBinData(chMsgData, chMsgSize); + sMsg.flags = rand()%300; + randString(SHORT_STR, sMsg.grpId); + + return new RsDistribSerialiser(); +} + +bool operator==(const RsDistribSignedMsg& sMsg1,const RsDistribSignedMsg& sMsg2) +{ + + if(!(sMsg1.packet == sMsg2.packet)) return false; + if(sMsg1.grpId != sMsg2.grpId) return false; + if(sMsg1.flags != sMsg2.flags) return false; + + return true; +} + + +RsSerialType* init_item(RsChannelMsg& chMsg) +{ + randString(SHORT_STR, chMsg.grpId); + randString(LARGE_STR, chMsg.message); + randString(SHORT_STR, chMsg.subject); + randString(SHORT_STR, chMsg.threadId); + chMsg.timestamp = rand()%31452; + init_item(chMsg.thumbnail); + init_item(chMsg.attachment); + + return new RsChannelSerialiser(); +} + + +bool operator==(const RsChannelMsg& chMsg1,const RsChannelMsg& chMsg2) +{ + + if(chMsg1.grpId != chMsg2.grpId) return false; + if(chMsg1.message != chMsg2.message) return false; + if(!(chMsg1.attachment == chMsg2.attachment)) return false; + if(chMsg1.subject != chMsg2.subject) return false; + if(chMsg2.threadId != chMsg2.threadId) return false; + if(chMsg1.timestamp != chMsg2.timestamp) return false; + if(!(chMsg1.thumbnail.binData == chMsg2.thumbnail.binData)) return false; + if(chMsg1.thumbnail.image_type != chMsg2.thumbnail.image_type) return false; + + return true; +} + +RsSerialType* init_item(RsForumMsg& fMsg) +{ + + fMsg.timestamp = rand()%242; + randString(SHORT_STR, fMsg.grpId); + randString(LARGE_STR, fMsg.msg); + randString(SHORT_STR, fMsg.parentId); + randString(SHORT_STR, fMsg.srcId); + randString(SHORT_STR, fMsg.threadId); + randString(SHORT_STR, fMsg.title); + + return new RsForumSerialiser(); +} + + + +bool operator==(const RsForumMsg& fMsg1, const RsForumMsg& fMsg2) +{ + if(fMsg1.grpId != fMsg2.grpId) return false; + if(fMsg1.msg != fMsg2.msg) return false; + if(fMsg1.parentId != fMsg2.parentId) return false; + if(fMsg1.srcId != fMsg2.srcId) return false; + if(fMsg1.threadId != fMsg2.threadId) return false; + if(fMsg1.timestamp != fMsg2.timestamp) return false; + if(fMsg1.title != fMsg2.title) return false; + + return true; +} + +RsSerialType* init_item(RsBlogMsg& bMsg) +{ + bMsg.timestamp = rand()%223; + randString(SHORT_STR, bMsg.grpId); + randString(LARGE_STR, bMsg.message); + randString(SHORT_STR, bMsg.subject); + randString(SHORT_STR, bMsg.parentId); + randString(SHORT_STR, bMsg.threadId); + RsTlvImage image; + int nImages = rand()%5; + + for(int i=0; i < nImages; i++) + { + init_item(image); + bMsg.graphic_set.push_back(image); + } + + return new RsBlogSerialiser(); +} + + +bool operator==(const RsDistribGrp& g1, const RsDistribGrp& g2) +{ + + if(g1.grpCategory != g2.grpCategory) return false; + if(g1.grpControlFlags != g2.grpControlFlags) return false; + if(!(g1.grpControlList == g2.grpControlList)) return false; + if(g1.grpDesc != g2.grpDesc) return false; + if(g1.grpFlags != g2.grpFlags) return false; + if(g1.grpId != g2.grpId) return false; + if(g1.grpName != g2.grpName) return false; + if(g1.timestamp != g2.timestamp) return false; + + // admin key + + if(!(g1.adminKey == g2.adminKey)) return false; + if(!(g1.adminSignature == g2.adminSignature)) return false; + if(g1.grpPixmap.image_type != g2.grpPixmap.image_type) return false; + if(!(g1.grpPixmap.binData == g2.grpPixmap.binData)) return false; + + return true; +} + + + +RsSerialType* init_item(RsForumReadStatus& fRdStatus) +{ + randString(SHORT_STR, fRdStatus.forumId); + fRdStatus.save_type = rand()%42; + + std::map::iterator mit = fRdStatus.msgReadStatus.begin(); + + std::string id; + uint32_t status = 0; + + int numMaps = rand()%12; + + for(int i = 0; i < numMaps; i++) + { + randString(SHORT_STR, id); + status = rand()%23; + + fRdStatus.msgReadStatus.insert(std::pair(id, status)); + } + + return new RsForumSerialiser(); +} + +bool operator==(const RsForumReadStatus& frs1, const RsForumReadStatus& frs2) +{ + if(frs1.forumId != frs2.forumId) return false; + if(frs1.save_type != frs2.save_type) return false; + + if(frs1.msgReadStatus.size() != frs2.msgReadStatus.size()) return false; + + std::map::const_iterator mit + = frs1.msgReadStatus.begin(); + + + + for(;mit != frs1.msgReadStatus.end(); mit++) + { + if(mit->second != frs2.msgReadStatus.find(mit->first)->second) return false; + } + + return true; + +} + + + +RsSerialType* init_item(RsChannelReadStatus& fRdStatus) +{ + randString(SHORT_STR, fRdStatus.channelId); + fRdStatus.save_type = rand()%42; + + std::map::iterator mit = fRdStatus.msgReadStatus.begin(); + + std::string id; + uint32_t status = 0; + + int numMaps = rand()%12; + + for(int i = 0; i < numMaps; i++) + { + randString(SHORT_STR, id); + status = rand()%23; + + fRdStatus.msgReadStatus.insert(std::pair(id, status)); + } + + return new RsChannelSerialiser(); +} + +bool operator==(const RsChannelReadStatus& frs1, const RsChannelReadStatus& frs2) +{ + if(frs1.channelId != frs2.channelId) return false; + if(frs1.save_type != frs2.save_type) return false; + + if(frs1.msgReadStatus.size() != frs2.msgReadStatus.size()) return false; + + std::map::const_iterator mit + = frs1.msgReadStatus.begin(); + + + + for(;mit != frs1.msgReadStatus.end(); mit++) + { + if(mit->second != frs2.msgReadStatus.find(mit->first)->second) return false; + } + + return true; + +} + + +bool operator==(const RsBlogMsg& bMsg1,const RsBlogMsg& bMsg2) +{ + + if(bMsg1.timestamp != bMsg2.timestamp) return false; + if(bMsg1.grpId != bMsg2.grpId) return false; + if(bMsg1.message != bMsg2.message) return false; + if(bMsg1.subject != bMsg2.subject) return false; + if(bMsg1.threadId != bMsg2.threadId) return false; + if(bMsg1.parentId != bMsg2.parentId) return false; + + std::list::const_iterator it1 = bMsg1.graphic_set.begin(), + it2 = bMsg2.graphic_set.begin(); + + if(bMsg1.graphic_set.size() != bMsg2.graphic_set.size()) return false; + + for(; it1 != bMsg1.graphic_set.end() ; it1++, it2++) + { + if(!(*it1 == *it2)) return false; + } + + return true; +} + +int main(){ + + std::cerr << "RsDistribItem Tests" << std::endl; + + test_RsItem(); REPORT("Serialise/Deserialise RsDistribGrp"); + test_RsItem(); REPORT("Serialise/Deserialise RsDistribGrpKey"); + test_RsItem(); REPORT("Serialise/Deserialise RsDistribSignedMsg"); + test_RsItem(); REPORT("Serialise/Deserialise RsChannelMsg"); + test_RsItem(); REPORT("Serialise/Deserialise RsChannelReadStatus"); + test_RsItem(); REPORT("Serialise/Deserialise RsForumMsg"); + test_RsItem(); REPORT("Serialise/Deserialise RsForumReadStatus"); + test_RsItem(); REPORT("Serialise/Deserialise RsBlogMsg"); + + + FINALREPORT("RsDistribItem Tests"); + + return TESTRESULT(); +} + diff --git a/libretroshare/src/tests/serialiser/distribitem_test.h b/libretroshare/src/tests/serialiser/distribitem_test.h new file mode 100644 index 000000000..1eedfd643 --- /dev/null +++ b/libretroshare/src/tests/serialiser/distribitem_test.h @@ -0,0 +1,55 @@ +#ifndef DISTRIBITEM_TEST_H_ +#define DISTRIBITEM_TEST_H_ + +/* + * libretroshare/src/serialiser: distribitem_test.h + * + * RetroShare Serialiser tests + * + * Copyright 2010 by Christopher Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsdistribitems.h" +#include "serialiser/rschannelitems.h" +#include "serialiser/rsforumitems.h" +#include "serialiser/rsblogitems.h" + + + +RsSerialType* init_item(RsDistribGrp&); +RsSerialType* init_item(RsDistribGrpKey&); +RsSerialType* init_item(RsDistribSignedMsg&); +RsSerialType* init_item(RsChannelMsg&); +RsSerialType* init_item(RsForumMsg&); +RsSerialType* init_item(RsForumReadStatus&); +RsSerialType* init_item(RsBlogMsg&); + +bool operator==(const RsDistribGrp& , const RsDistribGrp& ); +bool operator==(const RsDistribGrpKey& , const RsDistribGrpKey& ); +bool operator==(const RsDistribSignedMsg& , const RsDistribSignedMsg& ); +bool operator==(const RsChannelMsg& , const RsChannelMsg& ); +bool operator==(const RsForumMsg& , const RsForumMsg& ); +bool operator==(const RsForumReadStatus&, const RsForumReadStatus& ); +bool operator==(const RsBlogMsg& , const RsBlogMsg& ); + + + + +#endif /* DISTRIBITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsbaseitem_test.cc b/libretroshare/src/tests/serialiser/rsbaseitem_test.cc new file mode 100644 index 000000000..4743e5248 --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsbaseitem_test.cc @@ -0,0 +1,191 @@ + +/* + * libretroshare/src/serialiser: rsbaseitem_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****************************************************************** + * tlvfileitem test. + * + * + */ + +#include +#include +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvutil.h" +#include "util/utest.h" + +INITTEST(); + +static int test_RsFileItem(); +static int test_RsFileData(); + +int main() +{ + std::cerr << "RsFile[Item/Data/...] Tests" << std::endl; + + test_RsFileItem(); + test_RsFileData(); + + FINALREPORT("RsTlvFile[Item/Data/...] Tests"); + + return TESTRESULT(); +} + +int test_RsTlvFileItem() +{ + + + + + RsTlvFileItem i1; + RsTlvFileItem i2; + + /* initialise */ + i1.filesize = 101010; + i1.hash = "ABCDEFEGHE"; + i1.name = "TestFile.txt"; + i1.pop = 12; + i1.age = 456; + + CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); + + /* check the data is the same */ + CHECK(i1.filesize == i2.filesize); + CHECK(i1.hash == i2.hash); + CHECK(i1.name == i2.name); + CHECK(i1.path == i2.path); + CHECK(i1.pop == i2.pop); + CHECK(i1.age == i2.age); + + /* do it again without optional data */ + i1.filesize = 123; + i1.name = ""; + i1.pop = 0; + i1.age = 0; + + CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); + + /* check the data is the same */ + CHECK(i1.filesize == i2.filesize); + CHECK(i1.hash == i2.hash); + CHECK(i1.name == i2.name); + CHECK(i1.path == i2.path); + CHECK(i1.pop == i2.pop); + CHECK(i1.age == i2.age); + + /* one more time - long file name, some optional data */ + i1.filesize = 123; + i1.name = "A Very Long File name that should fit in easily ??? with som $&%&^%* strange char (**$^%#&^$#*^%(&^ in there too!!!! ~~~!!$#(^$)$)(&%^)&\" oiyu thend"; + i1.pop = 666; + i1.age = 0; + + CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); + + /* check the data is the same */ + CHECK(i1.filesize == i2.filesize); + CHECK(i1.hash == i2.hash); + CHECK(i1.name == i2.name); + CHECK(i1.path == i2.path); + CHECK(i1.pop == i2.pop); + CHECK(i1.age == i2.age); + + REPORT("Serialise/Deserialise RsTlvFileItem"); + + return 1; +} + +int test_RsTlvFileSet() +{ + RsTlvFileSet s1; + RsTlvFileSet s2; + + int i = 0; + for(i = 0; i < 15; i++) + { + RsTlvFileItem fi; + fi.filesize = 16 + i * i; + fi.hash = "ABCDEF"; + std::ostringstream out; + out << "File" << i << "_inSet.txt"; + fi.name = out.str(); + if (i % 2 == 0) + { + fi.age = 10 * i; + } + else + { + fi.age = 0; + } + fi.pop = 0; + + s1.items.push_back(fi); + } + + CHECK(test_SerialiseTlvItem(std::cerr, &s1, &s2)); + + /* check the data is the same - TODO */ + + REPORT("Serialise/Deserialise RsTlvFileSet"); + + return 1; +} + + +int test_RsTlvFileData() +{ + RsTlvFileData d1; + RsTlvFileData d2; + + /* initialise */ + d1.file.filesize = 101010; + d1.file.hash = "ABCDEFEGHE"; + d1.file.name = ""; + d1.file.age = 0; + d1.file.pop = 0; + + char data[15]; + d1.binData.setBinData(data, 15); + + d1.file_offset = 222; + + CHECK(test_SerialiseTlvItem(std::cerr, &d1, &d2)); + + /* check the data is the same */ + CHECK(d1.file.filesize == d2.file.filesize); + CHECK(d1.file.hash == d2.file.hash); + CHECK(d1.file.name == d2.file.name); + CHECK(d1.file.path == d2.file.path); + CHECK(d1.file.pop == d2.file.pop); + CHECK(d1.file.age == d2.file.age); + + CHECK(d1.file_offset == d2.file_offset); + CHECK(d1.binData.bin_len == d2.binData.bin_len); + + REPORT("Serialise/Deserialise RsTlvFileData"); + + return 1; +} + + diff --git a/libretroshare/src/tests/serialiser/rsconfigitem_test.cc b/libretroshare/src/tests/serialiser/rsconfigitem_test.cc new file mode 100644 index 000000000..1ac41ae09 --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsconfigitem_test.cc @@ -0,0 +1,328 @@ +/* + * libretroshare/src/tests/serialiser: rsconfigitemstest.cc + * + * RetroShare Serialiser tests. + * + * Copyright 2011 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rsconfigitem_test.h" +#include "util/utest.h" +#include "support.h" + + + +INITTEST() + +RsSerialType* init_item(RsPeerNetItem& rpn) +{ + randString(SHORT_STR, rpn.dyndns); + randString(SHORT_STR, rpn.gpg_id); + randString(SHORT_STR, rpn.location); + randString(SHORT_STR, rpn.pid); + + rpn.lastContact = rand()%42424; + rpn.netMode = rand()%313190; + rpn.visState = rand()%63635; + + + inet_aton("10.0.0.111", &(rpn.currentlocaladdr.sin_addr)); + rpn.currentlocaladdr.sin_port = htons(1111); + + inet_aton("123.1.2.123", &(rpn.currentremoteaddr.sin_addr)); + rpn.currentremoteaddr.sin_port = htons(1234); + + RsTlvIpAddressInfo ipa1, ipa2; + + ipa1.addr = rpn.currentlocaladdr; + ipa1.seenTime = rand()%40149013; + ipa1.source = rand()%13423; + + ipa2.addr = rpn.currentremoteaddr; + ipa2.seenTime = rand()%40139013; + ipa2.source = rand()%1343443; + + rpn.extAddrList.addrs.push_back(ipa1); + rpn.extAddrList.addrs.push_back(ipa2); + + rpn.localAddrList.addrs.push_back(ipa1); + rpn.localAddrList.addrs.push_back(ipa2); + + + return new RsPeerConfigSerialiser(); +} + +RsSerialType* init_item(RsPeerOldNetItem& rpon) +{ + return new RsPeerConfigSerialiser(); +} + +RsSerialType* init_item(RsPeerGroupItem& rpgi){ + + rpgi.flag = rand()%134344; + randString(SHORT_STR, rpgi.id); + randString(SHORT_STR, rpgi.name); + std::string p1, p2, p3; + randString(SHORT_STR, p1); + randString(SHORT_STR, p2); + randString(SHORT_STR, p3); + + rpgi.peerIds.push_back(p1); + rpgi.peerIds.push_back(p2); + rpgi.peerIds.push_back(p3); + + return new RsPeerConfigSerialiser(); +} + +RsSerialType* init_item(CompressedChunkMap& map) +{ + map._map.clear() ; + for(uint32_t i=0;i<15;++i) + map._map.push_back(rand()) ; + + return new RsTurtleSerialiser(); +} + +RsSerialType* init_item(RsPeerStunItem& rpsi) +{ + std::string p1, p2, p3; + randString(SHORT_STR, p1); + randString(SHORT_STR, p2); + randString(SHORT_STR, p3); + + rpsi.stunList.ids.push_back(p1); + rpsi.stunList.ids.push_back(p2); + rpsi.stunList.ids.push_back(p3); + + rpsi.stunList.mType = TLV_TYPE_PEERSET; + + return new RsPeerConfigSerialiser(); +} +RsSerialType* init_item(RsCacheConfig& rcc) +{ + + rcc.cachesubid = rand()%2342; + rcc.cachetypeid = rand()%323; + rcc.recvd = rand()%2252243; + rcc.size = rand()%02203; + randString(SHORT_STR, rcc.hash); + randString(SHORT_STR, rcc.name); + randString(SHORT_STR, rcc.path); + randString(SHORT_STR, rcc.pid); + + return new RsCacheConfigSerialiser(); +} + +RsSerialType* init_item(RsFileTransfer& rft) +{ + + std::string p1, p2, p3; + randString(SHORT_STR, p1); + randString(SHORT_STR, p2); + randString(SHORT_STR, p3); + + rft.allPeerIds.ids.push_back(p1); + rft.allPeerIds.ids.push_back(p2); + rft.allPeerIds.ids.push_back(p3); + rft.allPeerIds.mType = TLV_TYPE_PEERSET; + +// +// rft.compressed_chunk_map._map.clear(); +// const int mapSize = 15; +// rft.compressed_chunk_map._map.resize(mapSize); +// for(int i=0; i& left, + const std::list& right) +{ + std::list::const_iterator cit1 = left.begin(), + cit2 = right.begin(); + + for(; cit1 != left.end() ; cit1++, cit2++){ + + if(*cit1 != *cit2) + return false; + } + + return true; +} + +bool operator!=(const sockaddr_in& left, const sockaddr_in& right) +{ + if(left.sin_addr.s_addr != right.sin_addr.s_addr) return true; + if(left.sin_port != right.sin_port) return true; + + return false; +} + +bool operator!=(const RsTlvIpAddressInfo& left, const RsTlvIpAddressInfo& right) +{ + + if(left.addr != right.addr) return true; + if(left.seenTime != right.seenTime) return true; + if(left.source != right.source) return true; + + return false; +} + + +bool operator==(const RsPeerOldNetItem& left, const RsPeerOldNetItem& right) +{ + return false; +} + +bool operator==(const RsPeerGroupItem& left, const RsPeerGroupItem& right) +{ + if(left.flag != right.flag) return false; + if(left.id != right.id) return false; + if(left.name != right.name) return false; + if(left.peerIds != right.peerIds) return false; + + return true; +} + +bool operator!=(const std::list& left, + const std::list& right) +{ + std::list::const_iterator cit1 = left.begin(), + cit2 = right.begin(); + + for(; cit1 != left.end(); cit1++, cit2++){ + + if(*cit1 != *cit2) + return true; + } + + return false; +} + +bool operator==(const RsPeerStunItem& left, const RsPeerStunItem& right) +{ + if(!(left.stunList == right.stunList)) return false; + + return true; +} + +//bool operator==(const RsTlvPeerIdSet& left, const RsTlvPeerIdSet& right) +//{ +// if(left.mType != right.mType) return false; +// +// std::list::iterator cit1 = left.ids.begin(), +// cit2 = right.ids.begin(); +// +// for(; cit1 != left.ids.end(); cit1++, cit2++){ +// +// if(*cit1 != *cit2) +// return false; +// } +// +// return true; +//} + +bool operator==(const RsCacheConfig& left, const RsCacheConfig& right) +{ + + if(left.cachesubid != right.cachesubid) return false; + if(left.cachetypeid != right.cachetypeid) return false; + if(left.hash != right.hash) return false; + if(left.path != right.path) return false; + if(left.pid != right.pid) return false; + if(left.recvd != right.recvd) return false; + if(left.size != right.size) return false; + + return true; +} + +bool operator==(const RsFileTransfer& left, const RsFileTransfer& right) +{ + + if(!(left.allPeerIds == right.allPeerIds)) return false; + if(left.cPeerId != right.cPeerId) return false; + if(left.chunk_strategy != right.chunk_strategy) return false; + if(left.compressed_chunk_map._map != right.compressed_chunk_map._map) return false; + if(left.crate != right.crate) return false; + if(!(left.file == right.file)) return false; + if(left.flags != right.flags) return false; + if(left.in != right.in) return false; + if(left.lrate != right.lrate) return false; + if(left.ltransfer != right.ltransfer) return false; + if(left.state != right.state) return false; + if(left.transferred != right.transferred) return false; + if(left.trate != right.trate) return false; + + return true; +} + + + +int main() +{ + + std::cerr << "RsConfigItems Tests" << std::endl; + + test_RsItem(); REPORT("Serialise/Deserialise RsPeerNetItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsPeerGroupItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsPeerStunItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsCacheConfig"); + test_RsItem(); REPORT("Serialise/Deserialise RsFileTransfer"); + + FINALREPORT("RsConfigItems Tests"); + + return TESTRESULT(); +} diff --git a/libretroshare/src/tests/serialiser/rsconfigitem_test.h b/libretroshare/src/tests/serialiser/rsconfigitem_test.h new file mode 100644 index 000000000..2571d5c30 --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsconfigitem_test.h @@ -0,0 +1,59 @@ +/* + * libretroshare/src/serialiser: rsconfigitem_test.h + * + * RetroShare Serialiser tests. + * + * Copyright 2011 by Christopher Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef RSCONFIGITEM_TEST_H_ +#define RSCONFIGITEM_TEST_H_ + +#include "serialiser/rsconfigitems.h" +#include "turtle/rsturtleitem.h" + +RsSerialType* init_item(CompressedChunkMap& map); +RsSerialType* init_item(RsPeerNetItem& ); +RsSerialType* init_item(RsPeerOldNetItem& ); +RsSerialType* init_item(RsPeerGroupItem& ); +RsSerialType* init_item(RsPeerStunItem& ); +RsSerialType* init_item(RsCacheConfig& ); +RsSerialType* init_item(RsFileTransfer& ); + +bool operator==(const RsPeerNetItem&, const RsPeerNetItem& ); +bool operator==(const RsPeerOldNetItem&, const RsPeerOldNetItem& ); +bool operator==(const RsPeerGroupItem&, const RsPeerGroupItem& ); +bool operator==(const RsPeerStunItem&, const RsPeerStunItem& ); +bool operator==(const RsCacheConfig&, const RsCacheConfig& ); +bool operator==(const RsFileTransfer&, const RsFileTransfer& ); + +bool operator==(const std::list&, + const std::list&); + +bool operator!=(const sockaddr_in&, const sockaddr_in&); +bool operator!=(const RsTlvIpAddressInfo&, const RsTlvIpAddressInfo& ); +bool operator!=(const std::list& left, + const std::list& right); +//bool operator==(const RsTlvPeerIdSet& left, const RsTlvPeerIdSet& right); +bool operator==(const RsTlvFileItem&, const RsTlvFileItem& ); + + + +#endif /* RSCONFIGITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsmsgitem_test.cc b/libretroshare/src/tests/serialiser/rsmsgitem_test.cc new file mode 100644 index 000000000..6d60d25ee --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsmsgitem_test.cc @@ -0,0 +1,263 @@ +/* + * libretroshare/src/tests/serialiser: msgitem_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2010 by Christopher Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsmsgitems.h" +#include "serialiser/rstlvutil.h" +#include "util/utest.h" +#include "support.h" +#include "rsmsgitem_test.h" + +INITTEST(); + +RsSerialType* init_item(RsChatMsgItem& cmi) +{ + cmi.chatFlags = rand()%34; + cmi.sendTime = rand()%422224; + randString(LARGE_STR, cmi.message); + + return new RsChatSerialiser(); +} + +RsSerialType* init_item(RsPrivateChatMsgConfigItem& pcmi) +{ + randString(SHORT_STR, pcmi.configPeerId); + pcmi.chatFlags = rand()%34; + pcmi.configFlags = rand()%21; + pcmi.sendTime = rand()%422224; + randString(LARGE_STR, pcmi.message); + pcmi.recvTime = rand()%344443; + + return new RsChatSerialiser(); +} + +RsSerialType* init_item(RsChatStatusItem& csi) +{ + + randString(SHORT_STR, csi.status_string); + csi.flags = rand()%232; + + return new RsChatSerialiser(); + +} + +RsSerialType* init_item(RsChatAvatarItem& cai) +{ + std::string image_data; + randString(LARGE_STR, image_data); + cai.image_data = new unsigned char[image_data.size()]; + + memcpy(cai.image_data, image_data.c_str(), image_data.size()); + cai.image_size = image_data.size(); + + return new RsChatSerialiser(); +} + +RsSerialType* init_item(RsMsgItem& mi) +{ + init_item(mi.attachment); + init_item(mi.msgbcc); + init_item(mi.msgcc); + init_item(mi.msgto); + + randString(LARGE_STR, mi.message); + randString(SHORT_STR, mi.subject); + + mi.msgId = rand()%324232; + mi.recvTime = rand()%44252; + mi.sendTime = mi.recvTime; + mi.msgFlags = mi.recvTime; + + return new RsMsgSerialiser(true); +} + +RsSerialType* init_item(RsMsgTagType& mtt) +{ + mtt.rgb_color = rand()%5353; + mtt.tagId = rand()%24242; + randString(SHORT_STR, mtt.text); + + return new RsMsgSerialiser(); +} + + +RsSerialType* init_item(RsMsgTags& mt) +{ + mt.msgId = rand()%3334; + + int i; + for (i = 0; i < 10; i++) { + mt.tagIds.push_back(rand()%21341); + } + + return new RsMsgSerialiser(); +} + +RsSerialType* init_item(RsMsgSrcId& ms) +{ + ms.msgId = rand()%434; + randString(SHORT_STR, ms.srcId); + + return new RsMsgSerialiser(); +} + +RsSerialType* init_item(RsMsgParentId& ms) +{ + ms.msgId = rand()%354; + ms.msgParentId = rand()%476; + + return new RsMsgSerialiser(); +} + +bool operator ==(const RsChatMsgItem& cmiLeft,const RsChatMsgItem& cmiRight) +{ + + if(cmiLeft.chatFlags != cmiRight.chatFlags) return false; + if(cmiLeft.message != cmiRight.message) return false; + if(cmiLeft.sendTime != cmiRight.sendTime) return false; + + return true; +} + +bool operator ==(const RsPrivateChatMsgConfigItem& pcmiLeft,const RsPrivateChatMsgConfigItem& pcmiRight) +{ + + if(pcmiLeft.configPeerId != pcmiRight.configPeerId) return false; + if(pcmiLeft.chatFlags != pcmiRight.chatFlags) return false; + if(pcmiLeft.configFlags != pcmiRight.configFlags) return false; + if(pcmiLeft.message != pcmiRight.message) return false; + if(pcmiLeft.sendTime != pcmiRight.sendTime) return false; + if(pcmiLeft.recvTime != pcmiRight.recvTime) return false; + + return true; +} + +bool operator ==(const RsChatStatusItem& csiLeft, const RsChatStatusItem& csiRight) +{ + if(csiLeft.flags != csiRight.flags) return false; + if(csiLeft.status_string != csiRight.status_string) return false; + + return true; +} + + + +bool operator ==(const RsChatAvatarItem& caiLeft, const RsChatAvatarItem& caiRight) +{ + unsigned char* image_dataLeft = (unsigned char*)caiLeft.image_data; + unsigned char* image_dataRight = (unsigned char*)caiRight.image_data; + + // make image sizes are the same to prevent dereferencing garbage + if(caiLeft.image_size == caiRight.image_size) + { + image_dataLeft = (unsigned char*)caiLeft.image_data; + image_dataRight = (unsigned char*)caiRight.image_data; + } + else + { + return false; + } + + for(uint32_t i = 0; i < caiLeft.image_size; i++) + if(image_dataLeft[i] != image_dataRight[i]) return false; + + return true; + +} + +bool operator ==(const RsMsgItem& miLeft, const RsMsgItem& miRight) +{ + if(miLeft.message != miRight.message) return false; + if(miLeft.msgFlags != miRight.msgFlags) return false; + if(miLeft.recvTime != miRight.recvTime) return false; + if(miLeft.sendTime != miRight.sendTime) return false; + if(miLeft.subject != miRight.subject) return false; + if(miLeft.msgId != miRight.msgId) return false; + + if(!(miLeft.attachment == miRight.attachment)) return false; + if(!(miLeft.msgbcc == miRight.msgbcc)) return false; + if(!(miLeft.msgcc == miRight.msgcc)) return false; + if(!(miLeft.msgto == miRight.msgto)) return false; + + return true; +} + +bool operator ==(const RsMsgTagType& mttLeft, const RsMsgTagType& mttRight) +{ + if(mttLeft.rgb_color != mttRight.rgb_color) return false; + if(mttLeft.tagId != mttRight.tagId) return false; + if(mttLeft.text != mttRight.text) return false; + + return true; +} + +bool operator ==(const RsMsgTags& mtLeft, const RsMsgTags& mtRight) +{ + if(mtLeft.msgId != mtRight.msgId) return false; + if(mtLeft.tagIds != mtRight.tagIds) return false; + + return true; +} + +bool operator ==(const RsMsgSrcId& msLeft, const RsMsgSrcId& msRight) +{ + if(msLeft.msgId != msRight.msgId) return false; + if(msLeft.srcId != msRight.srcId) return false; + + return true; +} + +bool operator ==(const RsMsgParentId& msLeft, const RsMsgParentId& msRight) +{ + if(msLeft.msgId != msRight.msgId) return false; + if(msLeft.msgParentId != msRight.msgParentId) return false; + + return true; +} + +int main() +{ + test_RsItem(); REPORT("Serialise/Deserialise RsChatMsgItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsPrivateChatMsgConfigItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsChatStatusItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsChatAvatarItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsMsgItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsMsgTagType"); + test_RsItem(); REPORT("Serialise/Deserialise RsMsgTags"); + test_RsItem(); REPORT("Serialise/Deserialise RsMsgSrcId"); + test_RsItem(); REPORT("Serialise/Deserialise RsMsgParentId"); + + std::cerr << std::endl; + + FINALREPORT("RsMsgItem Tests"); + + return TESTRESULT(); +} + + + + + diff --git a/libretroshare/src/tests/serialiser/rsmsgitem_test.h b/libretroshare/src/tests/serialiser/rsmsgitem_test.h new file mode 100644 index 000000000..392792fa3 --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsmsgitem_test.h @@ -0,0 +1,50 @@ +#ifndef MSGITEM_TEST_H_ +#define MSGITEM_TEST_H_ + +/* + * libretroshare/src/tests/serialiser: msgitem_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2010 by Christopher Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include "serialiser/rsmsgitems.h" + + +RsSerialType* init_item(RsChatMsgItem& ); +RsSerialType* init_item(RsChatStatusItem& ); +RsSerialType* init_item(RsChatAvatarItem& ); +RsSerialType* init_item(RsMsgItem& ); +RsSerialType* init_item(RsMsgTagType& ); +RsSerialType* init_item(RsMsgTags& ); +RsSerialType* init_item(RsMsgSrcId& ); + +bool operator ==(const RsChatMsgItem& ,const RsChatMsgItem& ); +bool operator ==(const RsChatStatusItem& , const RsChatStatusItem& ); +bool operator ==(const RsChatAvatarItem&, const RsChatAvatarItem& ); +bool operator ==(const RsMsgTagType&, const RsMsgTagType& ); +bool operator ==(const RsMsgTags&, const RsMsgTags& ); +bool operator ==(const RsMsgItem&, const RsMsgItem& ); +bool operator ==(const RsMsgSrcId&, const RsMsgSrcId& ); + +#endif /* MSGITEM_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rsserial_test.cc b/libretroshare/src/tests/serialiser/rsserial_test.cc new file mode 100644 index 000000000..e9193fee0 --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsserial_test.cc @@ -0,0 +1,136 @@ + +/* + * libretroshare/src/serialiser: rsserial_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****************************************************************** + * tlvfileitem test. + * + * + */ + +#include +#include +#include "serialiser/rsserial.h" +#include "serialiser/rsbaseitems.h" +#include "serialiser/rstlvutil.h" +#include "util/utest.h" + +INITTEST(); + +static int test_RsFileItem(); +static int test_RsFileData(); + +int main() +{ + std::cerr << "RsFile[Item/Data/...] Tests" << std::endl; + + + test_RsFileItem(); + //test_RsFileData(); + + FINALREPORT("RsTlvFile[Item/Data/...] Tests"); + + return TESTRESULT(); +} + +int test_RsFileItem() +{ + /* make a serialisable FileItem */ + + RsSerialiser srl; + RsFileRequest rsfi; + + /* initialise */ + rsfi.file.filesize = 101010; + rsfi.file.hash = "ABCDEFEGHE"; + rsfi.file.name = "TestFile.txt"; + rsfi.file.pop = 12; + rsfi.file.age = 456; + + /* attempt to serialise it before we add it to the serialiser */ + + CHECK(0 == srl.size(&rsfi)); + +#define MAX_BUFSIZE 16000 + + char buffer[MAX_BUFSIZE]; + uint32_t sersize = MAX_BUFSIZE; + + CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); + + + /* now add to serialiser */ + + RsFileItemSerialiser *rsfis = new RsFileItemSerialiser(); + srl.addSerialType(rsfis); + + uint32_t size = srl.size(&rsfi); + bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); + + std::cerr << "test_RsFileItem() size: " << size << std::endl; + std::cerr << "test_RsFileItem() done: " << done << std::endl; + std::cerr << "test_RsFileItem() sersize: " << sersize << std::endl; + + std::cerr << "test_RsFileItem() serialised:" << std::endl; + displayRawPacket(std::cerr, (void *) buffer, sersize); + + CHECK(done == true); + + uint32_t sersize2 = sersize; + RsItem *output = srl.deserialise((void *) buffer, &sersize2); + + CHECK(output != NULL); + CHECK(sersize2 == sersize); + + RsFileRequest *outfi = dynamic_cast(output); + + CHECK(outfi != NULL); + + if (outfi) + { + /* check the data is the same */ + CHECK(rsfi.file.filesize == outfi->file.filesize); + CHECK(rsfi.file.hash == outfi->file.hash); + CHECK(rsfi.file.name == outfi->file.name); + CHECK(rsfi.file.path == outfi->file.path); + CHECK(rsfi.file.pop == outfi->file.pop); + CHECK(rsfi.file.age == outfi->file.age); + } + + sersize2 = MAX_BUFSIZE; + bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); + + CHECK(sersize2 == sersize); + + displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); + + + REPORT("Serialise/Deserialise RsFileRequest"); + + return 1; +} + + + diff --git a/libretroshare/src/tests/serialiser/rsstatusitem_test.cc b/libretroshare/src/tests/serialiser/rsstatusitem_test.cc new file mode 100644 index 000000000..db6d5c181 --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsstatusitem_test.cc @@ -0,0 +1,60 @@ +/* + * libretroshare/src/tests/serialiser: rsstatusitem_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2010 by Christopher Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "support.h" +#include "rsstatusitem_test.h" + +INITTEST(); + +RsSerialType* init_item(RsStatusItem& rsi) +{ + + rsi.sendTime = rand()%5353; + rsi.status = rand()%2032; + return new RsStatusSerialiser(); +} + +bool operator ==(RsStatusItem& rsi1, RsStatusItem& rsi2) +{ + // note: recv time is not serialised + + if(rsi1.sendTime != rsi2.sendTime) return false; + if(rsi1.status != rsi2.status) return false; + + return true; +} + + +int main() +{ + + std::cerr << "RsStatusItem Tests" << std::endl; + + test_RsItem(); REPORT("Serialise/Deserialise RsStatusItem"); + FINALREPORT("RsStatusItem Tests"); + + return TESTRESULT(); +} diff --git a/libretroshare/src/tests/serialiser/rsstatusitem_test.h b/libretroshare/src/tests/serialiser/rsstatusitem_test.h new file mode 100644 index 000000000..cf25c5429 --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsstatusitem_test.h @@ -0,0 +1,35 @@ +#ifndef RSSTATUS_TEST_H_ +#define RSSTATUS_TEST_H_ + +/* + * libretroshare/src/tests/serialiser: rsstatusitem_test.h + * + * RetroShare Serialiser. + * + * Copyright 2010 by Christopher Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsstatusitems.h" + +RsSerialType* init_item(RsStatusItem& ); + +bool operator ==(RsStatusItem& , RsStatusItem& ); + +#endif /* RSSTATUS_TEST_H_ */ diff --git a/libretroshare/src/tests/serialiser/rstlvwidetest.cc b/libretroshare/src/tests/serialiser/rstlvwidetest.cc new file mode 100644 index 000000000..91f663387 --- /dev/null +++ b/libretroshare/src/tests/serialiser/rstlvwidetest.cc @@ -0,0 +1,88 @@ +/* + * libretroshare/src/serialiser: rstlvkvwidetest.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include +#include "serialiser/rstlvkvwide.h" +#include "serialiser/rstlvutil.h" +#include "util/utest.h" + + +INITTEST(); + + /* define utility functions to test out with */ + + //static int testRstlvWide(); +static int testRsTlvWideSet(); + +int main() +{ + std::cerr << "RsTlvWideTest[Item/Data/...] Tests" << std::endl; + + testRsTlvWideSet(); + + FINALREPORT("RsTlvWideTest[Item/Data/...] Tests"); + + return TESTRESULT(); +} + +int testRsTlvWideSet() +{ + RsTlvKeyValueWideSet i1, i2; // one to set and other to get + RsTlvKeyValueWide i_pair; // input pair + RsTlvFileItem hello; + + std::string randString("it should work now."); + int j, k; + + std::cerr << "entering loop now" << std::endl; + /* store a 15 random pairs */ + + for(int i = 0; i < 15 ; i++) + { + j = rand() % 4; + k = rand() % 4; + std::cerr << "j: " << j << " k: " << k << std::endl; + i_pair.wKey.assign(randString.begin(), randString.end()); + std::cerr << "loop count:" << i << std::endl; + i_pair.wValue.assign(randString.begin(), randString.end()); + std::cerr << "loop count:" << i << std::endl; + i1.wPairs.push_back(i_pair); + + i_pair.TlvClear(); + } + + std::cerr << "out of loop now" << std::endl; + + CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); + + /*check that the data is the same*/ + + REPORT("Serialize/Deserialize RsTlvKeyValueWideSet"); + + return 1; +} diff --git a/libretroshare/src/tests/serialiser/rstunnelitem_test.cc b/libretroshare/src/tests/serialiser/rstunnelitem_test.cc new file mode 100644 index 000000000..ccc01fd9c --- /dev/null +++ b/libretroshare/src/tests/serialiser/rstunnelitem_test.cc @@ -0,0 +1,109 @@ + +/* + * libretroshare/src/serialiser: rstunnelitems_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****************************************************************** + */ + +#include +#include +#include +#include +#include +#include "util/utest.h" +#include "support.h" + + + +RsTunnelSerialiser* init_item(RsTunnelDataItem& item) +{ + uint32_t S = rand()%20000 ; + item.encoded_data = malloc(S) ; + item.encoded_data_len = S ; + for(uint32_t i=0;i(); REPORT("Serialise/Deserialise RsTunnelDataItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsTunnelHandshakeItem"); + } + + FINALREPORT("RstunnelItem Tests"); + + return TESTRESULT(); +} + + diff --git a/libretroshare/src/tests/serialiser/rsturtleitem_test.cc b/libretroshare/src/tests/serialiser/rsturtleitem_test.cc new file mode 100644 index 000000000..d7810d5e8 --- /dev/null +++ b/libretroshare/src/tests/serialiser/rsturtleitem_test.cc @@ -0,0 +1,254 @@ + +/* + * libretroshare/src/serialiser: rsturtleitems_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****************************************************************** + */ + +#include +#include +#include "turtle/rsturtleitem.h" +#include +#include "support.h" +#include "util/utest.h" + +INITTEST(); + +RsSerialType* init_item(CompressedChunkMap& map) +{ + map._map.clear() ; + for(uint32_t i=0;i<15;++i) + map._map.push_back(rand()) ; + + return new RsTurtleSerialiser(); +} +bool operator==(const CompressedChunkMap& m1,const CompressedChunkMap& m2) +{ + if(m1._map.size() != m2._map.size()) return false ; + + for(uint32_t i=0;i::const_iterator i1(it1.result.begin()) ; + std::list::const_iterator i2(it2.result.begin()) ; + + for(;i1!=it1.result.end() && i2!=it2.result.end();++i1,++i2) + if( !(*i1 == *i2)) + return false ; + + return true ; +} + +int main() +{ + std::cerr << "RsTurtleItem Tests" << std::endl; + + for(uint32_t i=0;i<20;++i) + { + test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileMapRequestItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileMapItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileDataItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsTurtleFileRequestItem"); + test_RsItem(); REPORT("Serialise/Deserialise RsTurtleTunnelOkItem "); + test_RsItem(); REPORT("Serialise/Deserialise RsTurtleOpenTunnelItem "); + test_RsItem(); REPORT("Serialise/Deserialise RsTurtleSearchResultItem "); + test_RsItem(); REPORT("Serialise/Deserialise RsTurtleStringSearchRequestItem "); + test_RsItem(); REPORT("Serialise/Deserialise RsTurtleRegExpSearchRequestItem "); + } + + FINALREPORT("RsturtleItem Tests"); + + return TESTRESULT(); +} + + diff --git a/libretroshare/src/tests/serialiser/support.cc b/libretroshare/src/tests/serialiser/support.cc new file mode 100644 index 000000000..bfb577490 --- /dev/null +++ b/libretroshare/src/tests/serialiser/support.cc @@ -0,0 +1,265 @@ +/* + * libretroshare/src/serialiser: t_support.h.cc + * + * RetroShare Serialiser tests. + * + * Copyright 2007-2008 by Christopher Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "support.h" +#include "serialiser/rstlvbase.h" + +void randString(const uint32_t length, std::string& outStr) +{ + char alpha = 'a'; + char* stringData = NULL; + + stringData = new char[length]; + + for(uint32_t i=0; i != length; i++) + stringData[i] = alpha + (rand() % 26); + + outStr.assign(stringData, length); + delete[] stringData; + + return; +} + +void randString(const uint32_t length, std::wstring& outStr) +{ + wchar_t alpha = L'a'; + wchar_t* stringData = NULL; + + stringData = new wchar_t[length]; + + for(uint32_t i=0; i != length; i++) + stringData[i] = (alpha + (rand() % 26)); + + outStr.assign(stringData, length); + delete[] stringData; + + return; +} + +bool operator==(const RsTlvSecurityKey& sk1, const RsTlvSecurityKey& sk2) +{ + + if(sk1.startTS != sk2.startTS) return false; + if(sk1.endTS != sk2.endTS) return false; + if(sk1.keyFlags != sk2.keyFlags) return false; + if(sk1.keyId != sk2.keyId) return false; + if(!(sk1.keyData == sk1.keyData)) return false; + + return true; +} + +bool operator==(const RsTlvKeySignature& ks1, const RsTlvKeySignature& ks2) +{ + + if(ks1.keyId != ks2.keyId) return false; + if(!(ks1.signData == ks2.signData)) return false; + + return true; +} + +bool operator==(const RsTlvPeerIdSet& pids1, const RsTlvPeerIdSet& pids2) +{ + std::list::const_iterator it1 = pids1.ids.begin(), + it2 = pids2.ids.begin(); + + + for(; ((it1 != pids1.ids.end()) && (it2 != pids2.ids.end())); it1++, it2++) + { + if(*it1 != *it2) return false; + } + + return true; + +} + + +void init_item(RsTlvImage& im) +{ + std::string imageData; + randString(LARGE_STR, imageData); + im.binData.setBinData(imageData.c_str(), imageData.size()); + im.image_type = RSTLV_IMAGE_TYPE_PNG; + + return; +} + +bool operator==(const RsTlvBinaryData& bd1, const RsTlvBinaryData& bd2) +{ + if(bd1.tlvtype != bd2.tlvtype) return false; + if(bd1.bin_len != bd2.bin_len) return false; + + unsigned char *bin1 = (unsigned char*)(bd1.bin_data), + *bin2 = (unsigned char*)(bd2.bin_data); + + for(uint32_t i=0; i < bd1.bin_len; bin1++, bin2++, i++) + { + if(*bin1 != *bin2) + return false; + } + + return true; +} + + +void init_item(RsTlvSecurityKey& sk) +{ + int randnum = rand()%313131; + + sk.endTS = randnum; + sk.keyFlags = randnum; + sk.startTS = randnum; + randString(SHORT_STR, sk.keyId); + + std::string randomStr; + randString(LARGE_STR, randomStr); + + sk.keyData.setBinData(randomStr.c_str(), randomStr.size()); + + return; +} + +void init_item(RsTlvKeySignature& ks) +{ + randString(SHORT_STR, ks.keyId); + + std::string signData; + randString(LARGE_STR, signData); + + ks.signData.setBinData(signData.c_str(), signData.size()); + + return; +} + + +bool operator==(const RsTlvImage& img1, const RsTlvImage& img2) +{ + if(img1.image_type != img2.image_type) return false; + if(!(img1.binData == img2.binData)) return false; + + return true; + +} + +/** channels, forums and blogs **/ + +void init_item(RsTlvHashSet& hs) +{ + std::string hash; + + for(int i=0; i < 10; i++) + { + randString(SHORT_STR, hash); + hs.ids.push_back(hash); + } + + hs.mType = TLV_TYPE_HASHSET; + return; +} + +void init_item(RsTlvPeerIdSet& ps) +{ + std::string peer; + + for(int i=0; i < 10; i++) + { + randString(SHORT_STR, peer); + ps.ids.push_back(peer); + } + + ps.mType = TLV_TYPE_PEERSET; + return; +} + +bool operator==(const RsTlvHashSet& hs1,const RsTlvHashSet& hs2) +{ + if(hs1.mType != hs2.mType) return false; + + std::list::const_iterator it1 = hs1.ids.begin(), + it2 = hs2.ids.begin(); + + for(; ((it1 != hs1.ids.end()) && (it2 != hs2.ids.end())); it1++, it2++) + { + if(*it1 != *it2) return false; + } + + return true; +} + +void init_item(RsTlvFileItem& fi) +{ + fi.age = rand()%200; + fi.filesize = rand()%34030313; + randString(SHORT_STR, fi.hash); + randString(SHORT_STR, fi.name); + randString(SHORT_STR, fi.path); + fi.piecesize = rand()%232; + fi.pop = rand()%2354; + init_item(fi.hashset); + + return; +} + +void init_item(RsTlvFileSet& fSet){ + + randString(LARGE_STR, fSet.comment); + randString(SHORT_STR, fSet.title); + RsTlvFileItem fi1, fi2; + init_item(fi1); + init_item(fi2); + fSet.items.push_back(fi1); + fSet.items.push_back(fi2); + + return; +} + +bool operator==(const RsTlvFileSet& fs1,const RsTlvFileSet& fs2) +{ + if(fs1.comment != fs2.comment) return false; + if(fs1.title != fs2.title) return false; + + std::list::const_iterator it1 = fs1.items.begin(), + it2 = fs2.items.begin(); + + for(; ((it1 != fs1.items.end()) && (it2 != fs2.items.end())); it1++, it2++) + if(!(*it1 == *it2)) return false; + + return true; +} + +bool operator==(const RsTlvFileItem& fi1,const RsTlvFileItem& fi2) +{ + if(fi1.age != fi2.age) return false; + if(fi1.filesize != fi2.filesize) return false; + if(fi1.hash != fi2.hash) return false; + if(!(fi1.hashset == fi2.hashset)) return false; + if(fi1.name != fi2.name) return false; + if(fi1.path != fi2.path) return false; + if(fi1.piecesize != fi2.piecesize) return false; + if(fi1.pop != fi2.pop) return false; + + return true; +} diff --git a/libretroshare/src/tests/serialiser/support.h b/libretroshare/src/tests/serialiser/support.h new file mode 100644 index 000000000..b1b0d5702 --- /dev/null +++ b/libretroshare/src/tests/serialiser/support.h @@ -0,0 +1,161 @@ +#ifndef SUPPORT_H_ +#define SUPPORT_H_ + +/* + * libretroshare/src/tests/serialiser: + * + * RetroShare Serialiser tests. + * + * Copyright 2007-2008 by Christopher Evi-Parker, Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include + +#include "util/utest.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvutil.h" +#include "serialiser/rstlvkeys.h" +#include "serialiser/rstlvtypes.h" + + + +/** + * This contains functions that may be useful for testing throughout the + * retroshare's serialiser + * package, if you find a function you keep using everywhere, might be a good idea to add it here + */ + + +#define SHORT_STR 100 +#define LARGE_STR 1000 + +void randString(const uint32_t, std::string&); +void randString(const uint32_t, std::wstring&); + + +/* for testing compound tlv items */ + +void init_item(RsTlvSecurityKey&); +void init_item(RsTlvKeySignature&); +void init_item(RsTlvBinaryData&); +void init_item(RsTlvFileItem&); +void init_item(RsTlvFileSet&); +void init_item(RsTlvHashSet&); +void init_item(RsTlvPeerIdSet&); +void init_item(RsTlvImage&); +void init_item(RsTlvPeerIdSet&); + +bool operator==(const RsTlvSecurityKey&, const RsTlvSecurityKey& ); +bool operator==(const RsTlvKeySignature&, const RsTlvKeySignature& ); +bool operator==(const RsTlvBinaryData&, const RsTlvBinaryData&); +bool operator==(const RsTlvFileItem&, const RsTlvFileItem&); +bool operator==(const RsTlvFileSet&, const RsTlvFileSet& ); +bool operator==(const RsTlvHashSet&, const RsTlvHashSet&); +bool operator==(const RsTlvImage&, const RsTlvImage& ); +bool operator==(const RsTlvPeerIdSet& , const RsTlvPeerIdSet& ); + + + +/*! + * This templated test function which allows you to test + * retroshare serialiser items (except compound tlv items) + * you the function must implement a function + * + * 'RsSerialType* init_item(YourRsItem& rs_item)' + * which returns valid serialiser that + * can serialiser rs_item. You also need to implement an operator + * + * Also need to implement a function + * 'bool operator =(YourRsItem& rs_itemL, YourRsItem& rs_temR)' + * which allows this function to test for equality between both parameters. + * rs_temR is the result of deserialising the left operand (1st parameter). + * not YourRsItem in specifier in about functions should be a derived type from RsItem + * + * @param T the item you want to test + */ + +template int test_RsItem() +{ + /* make a serialisable RsTurtleItem */ + + RsSerialiser srl; + + /* initialise */ + T rsfi ; + RsSerialType *rsfis = init_item(rsfi) ; + + /* attempt to serialise it before we add it to the serialiser */ + + CHECK(0 == srl.size(&rsfi)); + + static const uint32_t MAX_BUFSIZE = 22000 ; + + char *buffer = new char[MAX_BUFSIZE]; + uint32_t sersize = MAX_BUFSIZE; + + CHECK(false == srl.serialise(&rsfi, (void *) buffer, &sersize)); + + /* now add to serialiser */ + + srl.addSerialType(rsfis); + + uint32_t size = srl.size(&rsfi); + bool done = srl.serialise(&rsfi, (void *) buffer, &sersize); + + std::cerr << "test_Item() size: " << size << std::endl; + std::cerr << "test_Item() done: " << done << std::endl; + std::cerr << "test_Item() sersize: " << sersize << std::endl; + + std::cerr << "test_Item() serialised:" << std::endl; + //displayRawPacket(std::cerr, (void *) buffer, sersize); + + CHECK(done == true); + + uint32_t sersize2 = sersize; + RsItem *output = srl.deserialise((void *) buffer, &sersize2); + + CHECK(output != NULL); + CHECK(sersize2 == sersize); + + T *outfi = dynamic_cast(output); + + CHECK(outfi != NULL); + + if (outfi) + CHECK(*outfi == rsfi) ; + + sersize2 = MAX_BUFSIZE; + bool done2 = srl.serialise(outfi, (void *) &(buffer[16*8]), &sersize2); + + CHECK(done2) ; + CHECK(sersize2 == sersize); + +// displayRawPacket(std::cerr, (void *) buffer, 16 * 8 + sersize2); + + delete[] buffer ; + //delete rsfis; + + return 1; +} + + +#endif /* SUPPORT_H_ */ diff --git a/libretroshare/src/tests/serialiser/tlvbase_test.cc b/libretroshare/src/tests/serialiser/tlvbase_test.cc new file mode 100644 index 000000000..1f0e92def --- /dev/null +++ b/libretroshare/src/tests/serialiser/tlvbase_test.cc @@ -0,0 +1,195 @@ + +/* + * libretroshare/src/serialiser: tlvbase_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Horatio. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +#include +#include +#include +#include + +#include "serialiser/rstlvbase.h" +#include "util/utest.h" +#include "util/rsnet.h" + +INITTEST(); + +static int test_RsTlvBase(); +int main() +{ + std::cerr << " RsTlvBase Tests" < +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvutil.h" +#include "util/utest.h" +#include "util/rsnet.h" + +INITTEST(); + +static int test_RsTlvString(); +static int test_RsTlvUInt32(); +static int test_RsTlvIPAddr(); + +int main() +{ + std::cerr << "RsTlvBase Tests" << std::endl; + + test_RsTlvString(); + test_RsTlvUInt32(); + test_RsTlvIPAddr(); + + FINALREPORT("RsTlvBase Tests"); + + return TESTRESULT(); +} + +int test_RsTlvUInt32() +{ + return 1; +} + +int test_OneString(std::string input, uint16_t type); + +int test_RsTlvString() +{ + std::string nullString; + std::string oneString = "1"; + std::string shortString = "ab cd"; + std::string longString = "abcd efgh ijkl mnop qrst uvw"; + + std::cerr << "test_RsTlvString() Testing" << std::endl; + test_OneString(nullString, 1234); + test_OneString(oneString, 12); + test_OneString(shortString, 79); + test_OneString(longString, 7654); + + REPORT("Serialise RsTlvFileItem"); + + return 1; +} + + +int test_OneString(std::string input, uint16_t type) +{ + /* an array to work from */ + char tlvdata[2048]; + std::string OutString; + + std::cerr << "test_OneString() Testing ... Print/Serialise/Deserialise"; + std::cerr << std::endl; + /* start with SetTlvString() */ + + uint16_t initsize = GetTlvStringSize(input); + uint32_t outOffset = 0; + uint32_t inOffset = 0; + + std::cerr << "Serialising: " << input << std::endl; + CHECK(SetTlvString((void*)tlvdata, 2048, &outOffset, type, input)); + std::cerr << "Init Size: " << initsize << std::endl; + std::cerr << "Serialised Size: " << outOffset << std::endl; + displayRawPacket(std::cerr, tlvdata, outOffset); + + CHECK(outOffset == initsize); /* check that the offset matches the size */ + + std::cerr << "DeSerialising" << std::endl; + + /* fails if type is wrong! */ + CHECK(0 == GetTlvString((void*)tlvdata, outOffset, &inOffset, type-1, OutString)); + CHECK(GetTlvString((void*)tlvdata, outOffset, &inOffset, type, OutString)); + + CHECK(initsize == inOffset); /* check that the offset matches the size */ + CHECK(input == OutString); /* check that strings match */ + std::cerr << "Deserialised: Size: " << inOffset << std::endl; + std::cerr << "Deserialised: String: " << OutString << std::endl; + + REPORT("Serialise OneString"); + + return 1; +} + +int test_IpAddr(struct sockaddr_in *addr, uint16_t type); + +static int test_RsTlvIPAddr() +{ + struct sockaddr_in addr; + + inet_aton("10.0.0.111", &(addr.sin_addr)); + addr.sin_port = htons(1111); + + test_IpAddr(&addr, 1234); + + inet_aton("255.255.255.1", &(addr.sin_addr)); + addr.sin_port = htons(9999); + + test_IpAddr(&addr, 1234); + + inet_aton("128.255.255.1", &(addr.sin_addr)); + addr.sin_port = htons(1); + + test_IpAddr(&addr, 1234); + + return 1; +} + +int test_IpAddr(struct sockaddr_in *addr, uint16_t type) +{ + /* an array to work from */ + char tlvdata[2048]; + struct sockaddr_in outaddr; + + std::cerr << "test_IpAddr() Testing ... Print/Serialise/Deserialise"; + std::cerr << std::endl; + /* start with SetTlvString() */ + + uint16_t initsize = GetTlvIpAddrPortV4Size(); + uint32_t outOffset = 0; + uint32_t inOffset = 0; + + std::cerr << "Serialising IPAddr: " << inet_ntoa(addr->sin_addr) << std::endl; + std::cerr << " Port : " << ntohs(addr->sin_port) << std::endl; + + CHECK(SetTlvIpAddrPortV4((void*)tlvdata, 2048, &outOffset, type, addr)); + std::cerr << "Init Size: " << initsize << std::endl; + std::cerr << "Serialised Size: " << outOffset << std::endl; + displayRawPacket(std::cerr, tlvdata, outOffset); + + CHECK(outOffset == initsize); /* check that the offset matches the size */ + + std::cerr << "DeSerialising" << std::endl; + + /* fails if type is wrong! */ + CHECK(0 == GetTlvIpAddrPortV4((void*)tlvdata, outOffset, &inOffset, type-1, &outaddr)); + CHECK(GetTlvIpAddrPortV4((void*)tlvdata, outOffset, &inOffset, type, &outaddr)); + + CHECK(initsize == inOffset); /* check that the offset matches the size */ + CHECK(addr->sin_addr.s_addr == outaddr.sin_addr.s_addr); /* check that IP match */ + CHECK(addr->sin_port == outaddr.sin_port); /* check that Port match */ + std::cerr << "Deserialised: Size: " << inOffset << std::endl; + std::cerr << "Deserialised IPAddr: " << inet_ntoa(outaddr.sin_addr) << std::endl; + std::cerr << " Port : " << ntohs(outaddr.sin_port) << std::endl; + + REPORT("Serialise OneIP/Port"); + + return 1; +} + + + diff --git a/libretroshare/src/tests/serialiser/tlvitems_test.cc b/libretroshare/src/tests/serialiser/tlvitems_test.cc new file mode 100644 index 000000000..cb6ff0857 --- /dev/null +++ b/libretroshare/src/tests/serialiser/tlvitems_test.cc @@ -0,0 +1,89 @@ + +/* + * libretroshare/src/serialiser: tlvitems_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****************************************************************** + * tlvfileitem test. + * + * + */ + +#include +#include +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvutil.h" +#include "util/utest.h" + +INITTEST(); + +static int test_RsTlvBinData(); +static int test_RsTlvStepping(); + +int main() +{ + std::cerr << "RsTlvItems Tests" << std::endl; + + test_RsTlvBinData(); + + FINALREPORT("RsTlvItems Tests"); + + return TESTRESULT(); +} + +#define BIN_LEN 65536 /* bigger than 64k */ + +int test_RsTlvBinData() +{ + RsTlvBinaryData d1(1023); + RsTlvBinaryData d2(1023); + + char data[BIN_LEN] = {0}; + int i, j; + for(i = 0; i < BIN_LEN; i++) + { + data[i] = i%13; + } + + for(j = 1; j < BIN_LEN; j *= 2) + { + d1.setBinData(data, j); + CHECK(test_SerialiseTlvItem(std::cerr, &d1, &d2)); + + CHECK(d1.bin_len == d2.bin_len); + CHECK(0 == memcmp(d1.bin_data, d2.bin_data, d1.bin_len)); + } + + REPORT("Serialise/Deserialise RsTlvBinData"); + + return 1; +} + +int test_RsTlvStepping() +{ + + + return 1; +} + diff --git a/libretroshare/src/tests/serialiser/tlvrandom_test.cc b/libretroshare/src/tests/serialiser/tlvrandom_test.cc new file mode 100644 index 000000000..758451988 --- /dev/null +++ b/libretroshare/src/tests/serialiser/tlvrandom_test.cc @@ -0,0 +1,197 @@ + +/* + * libretroshare/src/serialiser: tlvrandom_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2009 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****************************************************************** + * tlvrandom_test. + * + * This test is designed to attempt to break the TLV serialiser. + * + * To do this we throw random data at the serialisers and try to decode it. + * As the serialiser will only attempt to deserialise if the tlvtype matches + * we cheat a little, and make this match - to increase to actual deserialise + * attempts. + * + * This test runs for 30 seconds and attempts to do as + * many deserialisation as possible. + */ + +#include +#include +#include +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvkeys.h" +#include "serialiser/rstlvkvwide.h" +#include "serialiser/rstlvutil.h" + +#include "util/utest.h" + +INITTEST(); + +#define TEST_LENGTH 10 + +static int test_TlvRandom(void *data, uint32_t len, uint32_t offset); + +int main() +{ + std::cerr << "TlvRandom Tests" << std::endl; + + /* random data array to work through */ + uint32_t dsize = 10000000; + uint32_t i; + uint8_t *data = (uint8_t *) malloc(dsize); + + if (!data) + { + std::cerr << "Failed to allocate array"; + std::cerr << std::endl; + exit(1); + } + + time_t startTs = time(NULL); + time_t endTs = startTs + TEST_LENGTH; + + srand(startTs); + for(i = 0; i < dsize; i++) + { + data[i] = rand() % 256; + } + + std::cerr << "TlvRandom Tests: setup data." << std::endl; + + int count = 0; + for(i = 0; endTs > time(NULL); i += 2) + { + uint32_t len = dsize - i; + count += test_TlvRandom(&(data[i]), len, i); + + std::cerr << "Run: " << count << " tests"; + std::cerr << std::endl; + } + + FINALREPORT("RsTlvItems Tests"); + + return TESTRESULT(); +} + +#define BIN_LEN 523456 /* bigger than 64k */ + +bool test_TlvItem(RsTlvItem *item, void *data, uint32_t size, uint32_t offset); +bool test_SetTlvItem(RsTlvItem *item, uint16_t type, void *data, uint32_t size, uint32_t offset); + + +int test_TlvRandom(void *data, uint32_t len, uint32_t offset) +{ + uint32_t tmpoffset = 0; + + /* List of all the TLV types it could be! */ + RsTlvSecurityKey skey; + RsTlvSecurityKeySet skeyset; + RsTlvKeySignature keysign; + + RsTlvBinaryData bindata(TLV_TYPE_IMAGE); + + RsTlvFileItem fileitem; + RsTlvFileSet fileset; + RsTlvFileData filedata; + + RsTlvPeerIdSet peerset; + RsTlvServiceIdSet servset; + + RsTlvKeyValue kv; + RsTlvKeyValueSet kvset; + RsTlvKeyValueWide kvwide; + RsTlvKeyValueWideSet kvwideset; + + RsTlvImage image; + + /* try to decode - with all types first */ + std::cerr << "test_TlvRandom:: Testing Files " << std::endl; + CHECK(test_TlvItem(&bindata, data, len, offset)); + CHECK(test_TlvItem(&fileitem, data, len, offset)); + CHECK(test_TlvItem(&fileset, data, len, offset)); + CHECK(test_TlvItem(&filedata, data, len, offset)); + std::cerr << "test_TlvRandom:: Testing Sets " << std::endl; + CHECK(test_TlvItem(&peerset, data, len, offset)); + CHECK(test_TlvItem(&servset, data, len, offset)); + CHECK(test_TlvItem(&kv, data, len, offset)); + CHECK(test_TlvItem(&kvset, data, len, offset)); + CHECK(test_TlvItem(&kvwide, data, len, offset)); + CHECK(test_TlvItem(&kvwideset, data, len, offset)); + std::cerr << "test_TlvRandom:: Testing Keys " << std::endl; + CHECK(test_TlvItem(&skey, data, len, offset)); + CHECK(test_TlvItem(&skeyset, data, len, offset)); + CHECK(test_TlvItem(&keysign, data, len, offset)); + + /* now set the type correctly before decoding */ + std::cerr << "test_TlvRandom:: Testing Files (TYPESET)" << std::endl; + CHECK(test_SetTlvItem(&bindata, TLV_TYPE_IMAGE, data, len, offset)); + CHECK(test_SetTlvItem(&fileitem,TLV_TYPE_FILEITEM, data, len, offset)); + CHECK(test_SetTlvItem(&fileset, TLV_TYPE_FILESET, data, len, offset)); + CHECK(test_SetTlvItem(&filedata, TLV_TYPE_FILEDATA, data, len, offset)); + std::cerr << "test_TlvRandom:: Testing Sets (TYPESET)" << std::endl; + CHECK(test_SetTlvItem(&peerset, TLV_TYPE_PEERSET, data, len, offset)); + CHECK(test_SetTlvItem(&servset, TLV_TYPE_SERVICESET, data, len, offset)); + CHECK(test_SetTlvItem(&kv, TLV_TYPE_KEYVALUE, data, len, offset)); + CHECK(test_SetTlvItem(&kvset, TLV_TYPE_KEYVALUESET, data, len, offset)); + CHECK(test_SetTlvItem(&kvwide, TLV_TYPE_WKEYVALUE, data, len, offset)); + CHECK(test_SetTlvItem(&kvwideset, TLV_TYPE_WKEYVALUESET, data, len, offset)); + std::cerr << "test_TlvRandom:: Testing Keys (TYPESET)" << std::endl; + CHECK(test_SetTlvItem(&skey, TLV_TYPE_SECURITYKEY, data, len, offset)); + CHECK(test_SetTlvItem(&skeyset, TLV_TYPE_SECURITYKEYSET, data, len, offset)); + CHECK(test_SetTlvItem(&keysign, TLV_TYPE_KEYSIGNATURE, data, len, offset)); + + return 26; /* number of tests */ +} + +bool test_TlvItem(RsTlvItem *item, void *data, uint32_t size, uint32_t offset) +{ + uint32_t tmp_offset = offset; + if (item->GetTlv(data, size, &tmp_offset)) + { + std::cerr << "TLV decoded Random!"; + std::cerr << std::endl; + item->print(std::cerr, 20); + return false; + } + else + { + std::cerr << "TLV failed to decode"; + std::cerr << std::endl; + return true; + } +} + +bool test_SetTlvItem(RsTlvItem *item, uint16_t type, void *data, uint32_t size, uint32_t offset) +{ + /* set TLV type first! */ + void *typedata = (((uint8_t *) data) + offset); + SetTlvType(typedata, size - offset, type); + + return test_TlvItem(item, data, size, offset); +} + + diff --git a/libretroshare/src/tests/serialiser/tlvstack_test.cc b/libretroshare/src/tests/serialiser/tlvstack_test.cc new file mode 100644 index 000000000..fe174f37e --- /dev/null +++ b/libretroshare/src/tests/serialiser/tlvstack_test.cc @@ -0,0 +1,104 @@ + +/* + * libretroshare/src/serialiser: tlvstack_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/****************************************************************** + * tlvfileitem test. + * + * + */ + +#include +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvutil.h" +#include "util/utest.h" + +INITTEST(); + +static int test_RsTlvStack(); + +int main() +{ + std::cerr << "RsTlvItem Stack Tests" << std::endl; + + test_RsTlvStack(); + + FINALREPORT("RsTlvItem Stack Tests"); + + return TESTRESULT(); +} + + +#define BIN_LEN 53 + +int test_RsTlvStack() +{ + + /* now create a set of TLV items for the random generator */ + + RsTlvBinaryData *bd1 = new RsTlvBinaryData(123); + RsTlvBinaryData *bd2 = new RsTlvBinaryData(125); + + char data[BIN_LEN] = {0}; + int i; + for(i = 0; i < BIN_LEN; i++) + { + data[i] = i%13; + } + + bd1->setBinData(data, 5); + bd2->setBinData(data, 21); + + RsTlvFileItem *fi1 = new RsTlvFileItem(); + RsTlvFileItem *fi2 = new RsTlvFileItem(); + + /* initialise */ + fi1->filesize = 101010; + fi1->hash = "ABCDEFEGHE"; + fi1->name = "TestFile.txt"; + fi1->pop = 12; + fi1->age = 456; + + fi2->filesize = 101010; + fi2->hash = "ABCDEFEGHE"; + fi2->name = "TestFile.txt"; + fi2->pop = 0; + fi2->age = 0;; + + std::vector items; + items.resize(4); + items[0] = bd1; + items[1] = bd2; + items[2] = fi1; + items[3] = fi2; + + test_TlvSet(items, 1024); + + REPORT("Serialise/Deserialise RsTlvBinData"); + + return 1; +} + + diff --git a/libretroshare/src/tests/serialiser/tlvtypes_test.cc b/libretroshare/src/tests/serialiser/tlvtypes_test.cc new file mode 100644 index 000000000..640940e8b --- /dev/null +++ b/libretroshare/src/tests/serialiser/tlvtypes_test.cc @@ -0,0 +1,406 @@ +/* + * libretroshare/src/serialiser: tlvfileitem_test.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie, Chris Evi-Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include +#include +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvutil.h" +#include "serialiser/rstlvbase.h" +#include "util/utest.h" + +INITTEST(); + +#define RAND_SEED 1352534 + +static int test_RsTlvBinData(); +static int test_RsTlvFileItem(); +static int test_RsTlvFileSet(); +static int test_RsTlvFileData(); +static int test_RsTlvStringSet(); +static int test_RsTlvPeerIdSet(); +static int test_RsTlvServiceIdSet(); +static int test_RsTlvKeyValue(); +static int test_RsTlvKeyValueSet(); +static int test_RsTlvHashSet(); +static int test_RsTlvImage(); + + + +int main() +{ + std::cerr << "RsTlvTypes[Item/Data/...] Tests" << std::endl; + + srand(RAND_SEED); + + test_RsTlvFileItem(); + test_RsTlvFileData(); + test_RsTlvFileSet(); + test_RsTlvPeerIdSet(); + test_RsTlvServiceIdSet(); + test_RsTlvKeyValue(); + test_RsTlvKeyValueSet(); + test_RsTlvBinData(); + test_RsTlvImage(); + test_RsTlvHashSet(); + + FINALREPORT("RsTlvTypes[Item/Data/...] Tests"); + + return TESTRESULT(); +} + +int test_RsTlvFileItem() +{ + RsTlvFileItem i1; + RsTlvFileItem i2; + + /* initialise */ + i1.filesize = 101010; + i1.hash = "ABCDEFEGHE"; + i1.name = "TestFile.txt"; + i1.pop = 12; + i1.age = 456; + + CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); + + /* check the data is the same */ + CHECK(i1.filesize == i2.filesize); + CHECK(i1.hash == i2.hash); + CHECK(i1.name == i2.name); + CHECK(i1.path == i2.path); + CHECK(i1.pop == i2.pop); + CHECK(i1.age == i2.age); + + /* do it again without optional data */ + i1.filesize = 123; + i1.name = ""; + i1.pop = 0; + i1.age = 0; + + CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); + + /* check the data is the same */ + CHECK(i1.filesize == i2.filesize); + CHECK(i1.hash == i2.hash); + CHECK(i1.name == i2.name); + CHECK(i1.path == i2.path); + CHECK(i1.pop == i2.pop); + CHECK(i1.age == i2.age); + + /* one more time - long file name, some optional data */ + i1.filesize = 123; + i1.name = "A Very Long File name that should fit in easily ??? with som $&%&^%* strange char (**$^%#&^$#*^%(&^ in there too!!!! ~~~!!$#(^$)$)(&%^)&\" oiyu thend"; + i1.pop = 666; + i1.age = 0; + + CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); + + /* check the data is the same */ + CHECK(i1.filesize == i2.filesize); + CHECK(i1.hash == i2.hash); + CHECK(i1.name == i2.name); + CHECK(i1.path == i2.path); + CHECK(i1.pop == i2.pop); + CHECK(i1.age == i2.age); + + REPORT("Serialise/Deserialise RsTlvFileItem"); + + return 1; +} + +int test_RsTlvFileSet() +{ + RsTlvFileSet s1; + RsTlvFileSet s2; + + int i = 0; + for(i = 0; i < 15; i++) + { + RsTlvFileItem fi; + fi.filesize = 16 + i * i; + fi.hash = "ABCDEF"; + std::ostringstream out; + out << "File" << i << "_inSet.txt"; + fi.name = out.str(); + if (i % 2 == 0) + { + fi.age = 10 * i; + } + else + { + fi.age = 0; + } + fi.pop = 0; + + s1.items.push_back(fi); + } + + CHECK(test_SerialiseTlvItem(std::cerr, &s1, &s2)); + + /* check the data is the same - TODO */ + + REPORT("Serialise/Deserialise RsTlvFileSet"); + + return 1; +} + + +int test_RsTlvFileData() +{ + RsTlvFileData d1; + RsTlvFileData d2; + + /* initialise */ + d1.file.filesize = 101010; + d1.file.hash = "ABCDEFEGHE"; + d1.file.name = ""; + d1.file.age = 0; + d1.file.pop = 0; + + char data[15]; + d1.binData.setBinData(data, 15); + + d1.file_offset = 222; + + CHECK(test_SerialiseTlvItem(std::cerr, &d1, &d2)); + + /* check the data is the same */ + CHECK(d1.file.filesize == d2.file.filesize); + CHECK(d1.file.hash == d2.file.hash); + CHECK(d1.file.name == d2.file.name); + CHECK(d1.file.path == d2.file.path); + CHECK(d1.file.pop == d2.file.pop); + CHECK(d1.file.age == d2.file.age); + + CHECK(d1.file_offset == d2.file_offset); + CHECK(d1.binData.bin_len == d2.binData.bin_len); + + REPORT("Serialise/Deserialise RsTlvFileData"); + + return 1; +} + + +int test_RsTlvPeerIdSet() +{ + + RsTlvPeerIdSet i1, i2; // one to set and other to get + + std::string testString; + + std::string randString[5]; + randString[0] = "e$424!�!�"; + randString[1] = "e~:@L{L{KHKG"; + randString[2] = "e{@O**/*/*"; + randString[3] = "e?<HG�!�%$"; + randString[4] = "e>HG�!�%$"; + randString[4] = "e> randStrings; + + char alpha = 'a'; + char* stringData = NULL; + + for(int i=0; i < numRandStrings; i++){ + + int stringLength = rand()%200; + stringData = new char[stringLength]; + + for(int i=0; i != stringLength; i++) + stringData[i] = alpha + (rand() % 26); + + + randString = new std::string(stringData, stringLength); + randStrings.push_back(*randString); + + // release memory resources + delete randString; + delete stringData; + stringData = NULL; + randString = NULL; + } + + + /* store a number of random ids */ + + for(int i = 0; i < numRandStrings ; i++) + { + i1.ids = randStrings; + } + + CHECK(test_SerialiseTlvItem(std::cerr, &i1, &i2)); + + /*check that the data is the same*/ + + REPORT("Serialize/Deserialize RsTlvHashSet"); + + return 1; + +} diff --git a/libretroshare/src/tests/serialiser/valgrind_all.sh b/libretroshare/src/tests/serialiser/valgrind_all.sh new file mode 100755 index 000000000..d69bd2679 --- /dev/null +++ b/libretroshare/src/tests/serialiser/valgrind_all.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +echo This script will call valgrind on all executables of the current directory and launch a debugger in case it finds an error. If the script terminate with non error, then the test passes. Press enter when ready... +read tmp + +for i in `find . -executable -type f | grep -v valgrind`; do + echo testing $i + valgrind --tool=memcheck --db-attach=yes ./$i +done diff --git a/libretroshare/src/tests/services/Makefile b/libretroshare/src/tests/services/Makefile new file mode 100644 index 000000000..a0170e6c1 --- /dev/null +++ b/libretroshare/src/tests/services/Makefile @@ -0,0 +1,31 @@ + +RS_TOP_DIR = ../.. +DHT_TOP_DIR = ../../../../libbitdht/src +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/config.mk +############################################################### + + +TESTOBJ = servicetest.o forumservicetest.o chatservicetest.o +TESTOBJ += chattest.o distribtest.o + +TESTS = chattest distribtest + +all: tests + +distribtest: distribtest.o servicetest.o forumservicetest.o + $(CC) $(CFLAGS) -o distribtest distribtest.o servicetest.o \ + forumservicetest.o $(OBJ) $(LIBS) + +chattest: chattest.o servicetest.o chatservicetest.o + $(CC) $(CFLAGS) -o chattest chattest.o servicetest.o \ + chatservicetest.o $(OBJ) $(LIBS) + + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/tests/services/chatservicetest.cc b/libretroshare/src/tests/services/chatservicetest.cc new file mode 100644 index 000000000..b2b3619cc --- /dev/null +++ b/libretroshare/src/tests/services/chatservicetest.cc @@ -0,0 +1,26 @@ +/* + * chatservicetest.cpp + * + * Created on: 17 Jun 2011 + * Author: greyfox + */ + +#include "chatservicetest.h" + +chatServiceTest::chatServiceTest() + : ServiceTest() { + + mChat = new p3ChatService(mConnMgr); +} + +chatServiceTest::~chatServiceTest() { + delete mChat; +} + +void chatServiceTest::runTests(){ + +} + +void chatServiceTest::insertChatItems(){ + +} diff --git a/libretroshare/src/tests/services/chatservicetest.h b/libretroshare/src/tests/services/chatservicetest.h new file mode 100644 index 000000000..c25537136 --- /dev/null +++ b/libretroshare/src/tests/services/chatservicetest.h @@ -0,0 +1,32 @@ +/* + * chatservicetest.h + * + * Created on: 17 Jun 2011 + * Author: greyfox + */ + +#ifndef CHATSERVICETEST_H_ +#define CHATSERVICETEST_H_ + +#include "servicetest.h" +#include "services/p3chatservice.h" +#include "util/utest.h" + +class chatServiceTest: public ServiceTest { + +public: + chatServiceTest(); + virtual ~chatServiceTest(); + +public: + void runTests(); + + void insertChatItems(); + +private: + + p3ChatService* mChat; + +}; + +#endif /* CHATSERVICETEST_H_ */ diff --git a/libretroshare/src/tests/services/chattest.cc b/libretroshare/src/tests/services/chattest.cc new file mode 100644 index 000000000..9c35bcf3b --- /dev/null +++ b/libretroshare/src/tests/services/chattest.cc @@ -0,0 +1,14 @@ +/* + * chattest.cc + * + * Created on: 17 Jun 2011 + * Author: greyfox + */ + +#include "chatservicetest.h" + +// chat service is tested here +int main(){ + + return 0; +} diff --git a/libretroshare/src/tests/services/distribtest.cc b/libretroshare/src/tests/services/distribtest.cc new file mode 100644 index 000000000..4919c13b4 --- /dev/null +++ b/libretroshare/src/tests/services/distribtest.cc @@ -0,0 +1,39 @@ +/* + * libretroshare/src/tests/services distrib_test_main.cc + * + * RetroShare Service Testing + * + * Copyright 2011 by Christopher Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "forumservicetest.h" + + +// distrib services are tested here +int main() +{ + forumServiceTest forumTest; + forumTest.runTests(); + REPORT("Forum Tests"); + + FINALREPORT("Distrib Test"); + + return TESTRESULT(); +} diff --git a/libretroshare/src/tests/services/forumservicetest.cc b/libretroshare/src/tests/services/forumservicetest.cc new file mode 100644 index 000000000..5353e03c0 --- /dev/null +++ b/libretroshare/src/tests/services/forumservicetest.cc @@ -0,0 +1,61 @@ +/* + * libretroshare/src/tests/services distrib_services.cc + * + * RetroShare Service Testing + * + * Copyright 2010 by Chris Evi-Parker, Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "forumservicetest.h" + + +forumServiceTest::forumServiceTest() + : ServiceTest() { + + mForums = NULL; + +} + + +forumServiceTest::~forumServiceTest(){ + if(mForums != NULL) + delete mForums; +} + +bool forumServiceTest::getForumMsgTest(){ + return false; +} + +bool forumServiceTest::setForumMsgTest(){ + return false; +} + +bool forumServiceTest::createGroupTests(){ + return false; +} + +void forumServiceTest::runTests(){ + +} + +void forumServiceTest::loadDummyData(){ + +} diff --git a/libretroshare/src/tests/services/forumservicetest.h b/libretroshare/src/tests/services/forumservicetest.h new file mode 100644 index 000000000..9e0cf8ebc --- /dev/null +++ b/libretroshare/src/tests/services/forumservicetest.h @@ -0,0 +1,63 @@ +/* + * libretroshare/src/tests/services distrib_services.h + * + * RetroShare Service Testing + * + * Copyright 2010 by Chris Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef DISTRIB_SERVICE_TEST_H_ +#define DISTRIB_SERVICE_TEST_H_ + +#include "servicetest.h" +#include "services/p3forums.h" +#include "util/utest.h" + + INITTEST() + +class forumServiceTest : public ServiceTest { + +public: + + forumServiceTest(); + ~forumServiceTest(); + + + void runTests(); + +private: + + bool getForumMsgTest(); + bool setForumMsgTest(); + bool createGroupTests(); + +private: + + void loadDummyData(); + +private: + + p3Forums* mForums; + +}; + + +#endif /* DISTRIB_SERVICE_TEST_H_ */ diff --git a/libretroshare/src/tests/services/servicetest.cc b/libretroshare/src/tests/services/servicetest.cc new file mode 100644 index 000000000..88f556430 --- /dev/null +++ b/libretroshare/src/tests/services/servicetest.cc @@ -0,0 +1,53 @@ +/* + * libretroshare/src/tests/services Service_Test.cc + * + * RetroShare Service Testing + * + * Copyright 2010 by Chris Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "servicetest.h" +#include "pqi/pqisslpersongrp.h" + + +ServiceTest::ServiceTest() +{ + + mConnMgr = new p3ConnectMgr(); + SecurityPolicy *none = secpolicy_create(); + mPersonGrp = new pqisslpersongrp(none, NULL); + mPeers = new p3Peers(mConnMgr); + + mConnMgr->addFriend(fakePeer); +} + +ServiceTest::~ServiceTest() +{ + // release resources + delete mConnMgr; + delete mPersonGrp; + delete mPeers; +} + + + + + + diff --git a/libretroshare/src/tests/services/servicetest.h b/libretroshare/src/tests/services/servicetest.h new file mode 100644 index 000000000..ca24e9f0e --- /dev/null +++ b/libretroshare/src/tests/services/servicetest.h @@ -0,0 +1,74 @@ +/* + * libretroshare/src/tests/services Service_Test.h + * + * RetroShare Service Testing + * + * Copyright 2010 by Chris Evi-Parker. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef SERVICE_TEST_H_ +#define SERVICE_TEST_H_ + +#include "pqi/p3connmgr.h" +#include "rsserver/p3peers.h" +#include "dbase/cachestrapper.h" +#include "pqi/pqipersongrp.h" + + + + +/*! + * A convenience class from which tests derive from + * This enables user to test in shallow manner the public methods + * of a service + */ +class ServiceTest { + +public: + ServiceTest(); + virtual ~ServiceTest(); + + /*! + * all tests of service should be implemented here + */ + virtual void runTests() = 0; + + /*! + * use this to populate the service with messages + */ + void sendItem(RsItem* item); + +protected: + + + p3ConnectMgr* mConnMgr; + CacheStrapper *mCs; + CacheTransfer *mCt; + p3Peers* mPeers; + pqipersongrp* mPersonGrp; + + std::string fakePeer; // ssl id of fake receiving peer + +}; + + + +#endif /* SERVICE_TEST_H_ */ diff --git a/libretroshare/src/tests/tcponudp/Makefile b/libretroshare/src/tests/tcponudp/Makefile new file mode 100644 index 000000000..6186f9f2c --- /dev/null +++ b/libretroshare/src/tests/tcponudp/Makefile @@ -0,0 +1,67 @@ + +RS_TOP_DIR = ../.. +DHT_TOP_DIR = ../../../../libbitdht/src +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/config.mk +############################################################### + +#BIOOBJ = bss_tou.o + +#RSOBJ = tou_net.o udplayer.o udpsorter.o udptestfn.o extaddrfinder.o +#RSOBJ += tcppacket.o tcpstream.o tou.o $(BIOOBJ) + +OBJ = udptestfn.o + +EXECS = udpsock_test udpsort_test udp_server test_tou +#pair_tou reset_tou internal_tou largefile_tou + +TESTOBJ = udpsock_test.o udpsort_test.o udp_server.o test_tou.o +#TESTOBJ += pair_tou.o reset_tou.o largefile_tou.o +#internal_tou.o + +TESTS = udpsock_test udpsort_test udp_server test_tou +# Unfortunately the design of tou has changed over time. +# and these tests cannot be performed at the moment. +#TESTS += pair_tou reset_tou largefile_tou +#internal_tou + +all: tests + +udpsock_test : $(OBJ) udpsock_test.o + $(CC) $(CFLAGS) -o udpsock_test udpsock_test.o $(OBJ) $(LIBS) + +udpsort_test : $(OBJ) udpsort_test.o + $(CC) $(CFLAGS) -o udpsort_test udpsort_test.o $(OBJ) $(LIBS) + +udp_server: $(OBJ) udp_server.o + $(CC) $(CFLAGS) -o udp_server udp_server.o $(OBJ) $(LIBS) + +test_tou : $(OBJ) test_tou.o + $(CC) $(CFLAGS) -o test_tou test_tou.o $(OBJ) $(LIBS) + +pair_tou : $(OBJ) pair_tou.o + $(CC) $(CFLAGS) -o pair_tou pair_tou.o $(OBJ) $(LIBS) + +reset_tou : $(OBJ) reset_tou.o + $(CC) $(CFLAGS) -o reset_tou reset_tou.o $(OBJ) $(LIBS) + +internal_tou : $(OBJ) internal_tou.o + $(CC) $(CFLAGS) -o internal_tou internal_tou.o $(OBJ) $(LIBS) + +largefile_tou : $(OBJ) largefile_tou.o + $(CC) $(CFLAGS) -o largefile_tou largefile_tou.o $(OBJ) $(LIBS) + + +# Extra Rule for BIOFLAGS +.c.o: + $(BIOCC) $(BIOCFLAGS) -c $< + +############################################################### +include $(RS_TOP_DIR)/tests/scripts/rules.mk +############################################################### + +CFLAGS += -DRS_USE_BITDHT -I$(DHT_TOP_DIR) + diff --git a/libretroshare/src/tests/tcponudp/internal_tou.cc b/libretroshare/src/tests/tcponudp/internal_tou.cc new file mode 100644 index 000000000..353fecedc --- /dev/null +++ b/libretroshare/src/tests/tcponudp/internal_tou.cc @@ -0,0 +1,632 @@ +/* + * "$Id: internal_tou.cc,v 1.2 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +/********************************************************** + * There appears (was) to be an elusive bug in the tou internals. + * most likely to be in the packing and unpacking of the + * data queues. + * + * This test is designed to load the queues up and then + * transfer the data, repeatly with different size packets. + * + * to do this effectively we need to access the TcpStream + * objects, instead of the tou.h interface. + * + */ + +#include + +// for printing sockaddr +#include "udplayer.h" +#include "tcpstream.h" + +#include "tou.h" +#include "tou_net.h" + +#include +#include +#include + + +/* This is a simple test to ensure that the tou behaviour + * is almost identical to a standard tcp socket. + * + * In this version we open 2 sockets, and attempt to + * communicate with ourselves.... + * + */ + +int setup_socket(struct sockaddr_in addr); +int connect_socket_pair(int fd1, int fd2, + struct sockaddr_in addr1, struct sockaddr_in addr2); +int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size); + +void usage(char *name) +{ + std::cerr << "Usage: " << name; + std::cerr << " [-pco] "; + std::cerr << " "; + std::cerr << std::endl; + exit(1); + return; +} + +int main(int argc, char **argv) +{ + int c; + bool isProxy = false; + bool toConnect = false; + bool stayOpen = false; + int i,j; + + while(-1 != (c = getopt(argc, argv, "pco"))) + { + switch (c) + { + case 'p': + isProxy = true; + break; + case 'c': + toConnect = true; + break; + case 'o': + stayOpen = true; + break; + default: + usage(argv[0]); + break; + } + } + + if (argc-optind < 4) + { + usage(argv[0]); + return 1; + } + + // tounet_init(); + + + /* setup the local/remote addresses. + */ + struct sockaddr_in laddr; + struct sockaddr_in raddr; + + laddr.sin_family = AF_INET; + raddr.sin_family = AF_INET; + + if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) || + (!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) + { + std::cerr << "Invalid addresses!" << std::endl; + usage(argv[0]); + } + + unsigned short laddr_port = atoi(argv[optind+1]); + unsigned short raddr_port = atoi(argv[optind+3]); + + laddr.sin_port = htons(laddr_port); + raddr.sin_port = htons(raddr_port); + + /* so create the Udp/Tcp components */ + //UdpLayer udp1(laddr); + //UdpLayer udp2(raddr); + LossyUdpLayer udp1(laddr, 0.10); + LossyUdpLayer udp2(raddr, 0.10); + + /* check that they are okay */ + if ((!udp1.okay()) || (!udp2.okay())) + { + std::cerr << "Trouble opening udp ports!"; + std::cerr << std::endl; + return 1; + } + + TcpStream tcp1(&udp1); + TcpStream tcp2(&udp2); + + udp1.setRemoteAddr(raddr); + udp2.setRemoteAddr(laddr); + tcp1.connect(); // start the connection. + + /* now connect them */ + while ((!tcp1.isConnected()) || (!tcp2.isConnected())) + { + usleep(10000); /* 10 ms */ + tcp1.tick(); + tcp2.tick(); + } + + std::cerr << "Connection Established!" << std::endl; + + for(i = 0; i < 10; i++) + { + + int size = 1024000; + char rnddata1[size]; + char rnddata2[size]; + + for(j = 0; j < size; j++) + { + rnddata1[j] = (unsigned char) (255.0 * + rand() / (RAND_MAX + 1.0)); + + rnddata2[j] = (unsigned char) (255.0 * + rand() / (RAND_MAX + 1.0)); + } + + /* for each iteration, we want to + * (1) fill up the outgoing buffers with stuff + */ + + int sent1 = 0; + int sent2 = 0; + int fill1, fill2; + int MaxSend = 1000000; + + while((fill1 = tcp1.write_allowed()) && (sent1 < MaxSend)) + { + /* fill with a random little bit more */ + int psize = (int) ((i + 1.0) * 255.0 * + rand() / (RAND_MAX + 1.0)); + + /* don't overload */ + if (psize > fill1) + { + std::cerr << "LAST FILL1" << std::endl; + psize = fill1; + } + + int ret = tcp1.write(&(rnddata1[sent1]), psize); + + if (ret) + { + sent1 += ret; + std::cerr << "Filled tcp1 with " << ret << " more bytes, total:"; + std::cerr << sent1 << " was allowed: " << fill1; + std::cerr << std::endl; + } + + //tcp1.status(std::cerr); + + } + std::cerr << "Tcp1 full with " << sent1 << " bytes "; + std::cerr << std::endl; + + while((fill2 = tcp2.write_allowed()) && (sent2 < MaxSend)) + { + /* fill with a random little bit more */ + /* slightly larger sizes */ + int psize = (int) ((i + 1.0) * 1255.0 * + rand() / (RAND_MAX + 1.0)); + + /* don't overload */ + if (psize > fill2) + { + std::cerr << "LAST FILL2" << std::endl; + psize = fill2; + } + + int ret = tcp2.write(&(rnddata2[sent2]), psize); + + if (ret) + { + sent2 += ret; + std::cerr << "Filled tcp2 with " << ret << " more bytes, total:"; + std::cerr << sent2 << " was allowed: " << fill2; + std::cerr << std::endl; + } + + //tcp2.status(std::cerr); + + } + std::cerr << "Tcp2 full with " << sent2 << " bytes "; + std::cerr << std::endl; + + /* for every second iteration, fill up the read buffer before starting */ + if (i % 2 == 0) + { + for(j = 0; j < 100; j++) + { + tcp1.tick(); + tcp2.tick(); + } + } + + /* now we read/tick and empty */ + int read1 = 0; + int read2 = 0; + + while(read1 < sent2) + { + tcp1.tick(); + tcp2.tick(); + + /* fill with a random little bit more */ + /* This one has a small read, while tcp2 has a large read */ + int psize = (int) ((i + 1.0) * 100.0 * + rand() / (RAND_MAX + 1.0)); + + /* limit to what we have! */ + if (psize > sent2 - read1) + { + std::cerr << "LAST READ1" << std::endl; + psize = sent2 - read1; + } + + char rbuf[psize]; + int rsize = psize; + + int ret = tcp1.read(rbuf, rsize); + if (0 < ret) + { + /* check the data */ + for(j = 0; j < ret; j++) + { + if (rnddata2[read1 + j] != rbuf[j]) + { + std::cerr << "Error Data Mismatch @ read1:" << read1; + std::cerr << " + j:" << j << " rsize: " << rsize; + std::cerr << " Index: " << read1 + j; + std::cerr << std::endl; + + int badoffset = read1 + j; + for(int k = -10; k < 10; k++) + { + printf("Orig: %02x, Trans: %02x\n", + (unsigned char) rnddata2[badoffset+k], + (unsigned char) rbuf[j + k]); + } + + + exit(1); + } + } + read1 += ret; + } + else + { + std::cerr << "Read Error: " << ret << std::endl; + } + std::cerr << "Requested " << psize << ", got " << ret << " bytes" << std::endl; + std::cerr << "Read " << read1 << " of " << sent2 << " bytes" << std::endl; + } + + sleep(2); + + + while(read2 < sent1) + { + tcp1.tick(); + tcp2.tick(); + + /* fill with a random little bit more */ + int psize = (int) ((i + 1.0) * 10000.0 * + rand() / (RAND_MAX + 1.0)); + + /* limit to what we have! */ + if (psize > sent1 - read2) + { + std::cerr << "LAST READ2" << std::endl; + psize = sent1 - read2; + } + + char rbuf[psize]; + int rsize = psize; + + int ret = tcp2.read(rbuf, rsize); + if (0 < ret) + { + /* check the data */ + for(j = 0; j < ret; j++) + { + if (rnddata1[read2 + j] != rbuf[j]) + { + std::cerr << "Error Data Mismatch @ read2:" << read2; + std::cerr << " + j:" << j << " rsize: " << rsize; + std::cerr << " Index: " << read2 + j; + std::cerr << std::endl; + exit(1); + } + } + read2 += ret; + } + else + { + std::cerr << "Read Error: " << ret << std::endl; + } + std::cerr << "Requested " << psize << ", got " << ret << " bytes" << std::endl; + std::cerr << "Read " << read2 << " of " << sent1 << " bytes" << std::endl; + } + + std::cerr << "Iteration " << i + 1 << " finished correctly!" << std::endl; + sleep(5); + + } + return 1; +} + +int setup_socket(struct sockaddr_in addr) +{ + int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); + + if (sockfd <= 0) + { + std::cerr << "Failed to open socket!: "; + std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; + return -1; + } + + std::cerr << "Socket Created: " << sockfd << std::endl; + + int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); + + if (err < 0) + { + std::cerr << "Error: Cannot bind socket: "; + std::cerr << err << std::endl; + return -1; + } + + std::cerr << "Socket1 Bound to: " << addr << std::endl; + return sockfd; +} + +int connect_socket_pair(int fd1, int fd2, + struct sockaddr_in addr1, struct sockaddr_in addr2) +{ + std::cerr << "Socket2 Listening " << std::endl; + /* listen */ + int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1)); + int err_num; + + if (err < 0) + { + err_num = tou_errno(fd2); + if (err_num != EINPROGRESS) + { + std::cerr << "Cannot Listen!: " << err_num << std::endl; + return -1; + } + } + + + std::cerr << "Socket1 Connecting to: " << addr2 << std::endl; + err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2)); + if (err < 0) + { + err_num = tou_errno(fd1); + if (err_num != EINPROGRESS) + { + std::cerr << "Cannot Connect!: " << err_num << std::endl; + return -1; + } + } + + bool sock1Connected = false; + bool sock2Connected = false; + + while((!sock1Connected) || (!sock2Connected)) + { + sleep(1); + + /* sock1 */ + if((!sock1Connected) && (0 == (err = tou_connected(fd1)))) + { + std::cerr << "Waiting for Connect (Sock1)!" << std::endl; + } + + if ((!sock1Connected) && (err < 0)) + { + std::cerr << "Connect Failed" << std::endl; + return 1; + } + else if (!sock1Connected) + { + // else connected! + sock1Connected = true; + } + + /* accept - sock2 */ + struct sockaddr_in inaddr; + socklen_t addrlen = sizeof(inaddr); + int nsock = -1; + + if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2, + (struct sockaddr *) &inaddr, &addrlen)))) + { + errno = tou_errno(fd2); + if (errno != EAGAIN) + { + std::cerr << "Cannot Connect!: " << errno << std::endl; + return 1; + } + else + { + std::cerr << "Waiting for Connect (Sock2)!" << std::endl; + } + } + else if (nsock > 0) + { + /* connected */ + sock2Connected = true; + fd2 = nsock; + std::cerr << "Socket Accepted from: " << inaddr << std::endl; + } + } + + std::cerr << "Socket Connected" << std::endl; + + return 1; +} + + +/* This transmits into sockfd1, and check to see that we recv + * it back from sockfd2 + */ + +int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size) +{ + /* what we recvd */ + char *recvd = (char *) malloc(size * 2); + int recvdsize = 0; + int sent = 0; + int sendsize = 0; + + int ts_start = time(NULL); + + int minsends = 100; /* min of 100 sends to complete all data */ + /* ensure we don't end up sending nothing */ + if (minsends * 10 > size) + { + minsends = size / 10; + } + + bool doneWrite = false; + bool doneRead = false; + while((!doneWrite) || (!doneRead)) + { + /* have a little break */ + //usleep(10000); /* 0.01 sec */ + //usleep(250000); /* 0.25 sec */ + usleep(500000); /* 0.50 sec */ + /* decide how much to send */ + sendsize = (int) (((float) (size / minsends)) * + (rand() / (RAND_MAX + 1.0))); + + /* limit send */ + if (sent + sendsize > size) + { + sendsize = size - sent; + } + /* if we've finished */ + if (sent == size) + { + /* eof */ + std::cerr << "Write Done!" << std::endl; + doneWrite = true; + sendsize = 0; + } + + /* now we write */ + if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize))) + { + std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl; + if (tou_errno(sockfd1) != EAGAIN) + { + std::cerr << "FATAL ERROR ending transfer" << std::endl; + doneRead = true; + doneWrite = true; + } + + } + else + { + sent += sendsize; + } + + int ret = 0; + int readsize = (int) (((float) (size / minsends)) * + (rand() / (RAND_MAX + 1.0))); + + if (readsize > size - recvdsize) + readsize = size - recvdsize; + + if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize))) + { + std::cerr << "TF(" << ret << ")" << std::endl; + recvdsize += ret; + } + else if (ret == 0) + { + doneRead = true; + std::cerr << "Read Done! (ret:0)" << std::endl; + } + else + { + std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl; + std::cerr << "Read " << recvdsize << "/" << size; + std::cerr << " attempted: " << readsize << std::endl; + if (tou_errno(sockfd2) != EAGAIN) + { + std::cerr << "FATAL ERROR ending transfer" << std::endl; + doneRead = true; + doneWrite = true; + } + + } + + if (recvdsize == size) + { + doneRead = true; + std::cerr << "Read Done!" << std::endl; + } + + } + + /* we have transmitted it all, so + * check the data + */ + + int i; + int diffCount = 0; + for(i = 0; i < size; i++) + { + if (recvd[i] != data[i]) + { + diffCount++; + if (diffCount < 10) + { + std::cerr << "Error Byte:" << i << " is different"; + std::cerr << std::endl; + } + } + } + if (diffCount) + { + std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!"; + std::cerr << std::endl; + exit(1); + } + + int ts_end = time(NULL); + double rough_rate = size / (double) (ts_end - ts_start); + + std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs"; + std::cerr << std::endl; + std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec"; + std::cerr << std::endl; + + return 1; +} + + + + + + + + diff --git a/libretroshare/src/tests/tcponudp/largefile_tou.cc b/libretroshare/src/tests/tcponudp/largefile_tou.cc new file mode 100644 index 000000000..1bf0bebca --- /dev/null +++ b/libretroshare/src/tests/tcponudp/largefile_tou.cc @@ -0,0 +1,502 @@ +/* + * "$Id: largefile_tou.cc,v 1.2 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +/********************************************************** + * This test is designed to test large data blocks/files + * running to tou. Currently we see occasional errors + * every 1/2 -> 1 MB of transfer.... + * + * This test will continually fill the output buffer, + * and then empty the receive one. To ensure the + * whole system gets a good workout. + * + */ + +#include + +// for printing sockaddr +#include "udplayer.h" + +#include "tou.h" +#include "tou_net.h" + +#include +#include +#include + +int setup_socket(struct sockaddr_in addr); +int connect_socket_pair(int fd1, int fd2, + struct sockaddr_in addr1, struct sockaddr_in addr2); +int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size); + +void usage(char *name) +{ + std::cerr << "Usage: " << name; + std::cerr << " [-pco] "; + std::cerr << " "; + std::cerr << std::endl; + exit(1); + return; +} + +int main(int argc, char **argv) +{ + int c; + bool isProxy = false; + bool toConnect = false; + bool stayOpen = false; + int i,j; + + while(-1 != (c = getopt(argc, argv, "pco"))) + { + switch (c) + { + case 'p': + isProxy = true; + break; + case 'c': + toConnect = true; + break; + case 'o': + stayOpen = true; + break; + default: + usage(argv[0]); + break; + } + } + + if (argc-optind < 4) + { + usage(argv[0]); + return 1; + } + + tounet_init(); + + + /* setup the local/remote addresses. + */ + struct sockaddr_in laddr; + struct sockaddr_in raddr; + + laddr.sin_family = AF_INET; + raddr.sin_family = AF_INET; + + if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) || + (!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) + { + std::cerr << "Invalid addresses!" << std::endl; + usage(argv[0]); + } + + unsigned short laddr_port = atoi(argv[optind+1]); + unsigned short raddr_port = atoi(argv[optind+3]); + + for(i = 0; i < 10; i++) + { + laddr.sin_port = htons(laddr_port); + raddr.sin_port = htons(raddr_port); + //laddr.sin_port = htons(laddr_port + i); + //raddr.sin_port = htons(raddr_port + i); + + std::cerr << "Interation: " << i << std::endl; + + + /* setup the sockets */ + int sockfd1 = setup_socket(laddr); + int sockfd2 = setup_socket(raddr); + + if ((sockfd1 < 0) || (sockfd2 < 0)) + { + std::cerr << "Failed to setup sockets!"; + std::cerr << std::endl; + return -1; + } + + std::cerr << "Local Address: " << laddr; + std::cerr << " fd: " << sockfd1 << std::endl; + std::cerr << "Remote Address: " << raddr; + std::cerr << " fd: " << sockfd2 << std::endl; + + /* connect */ + int err = connect_socket_pair(sockfd1, sockfd2, laddr, raddr); + if (err < 0) + { + std::cerr << "Failed to connect sockets!"; + std::cerr << std::endl; + return -1; + } + + /* send the data */ + int size = 3093237; + char rnddata[size]; + + int data_loops = (i+1) * (i+1); + for(int k = 0; k < data_loops; k++) + { + std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; + for(j = 0; j < size; j++) + { + rnddata[j] = (unsigned char) (255.0 * + rand() / (RAND_MAX + 1.0)); + } + send_data_via_pair(sockfd1, sockfd2, rnddata, size); + std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; + sleep(2); + } + + std::cerr << "Completed Successful transfer of " << size * data_loops << " bytes"; + std::cerr << std::endl; + + sleep(10); + std::cerr << "closing sockfd1: " << sockfd1 << std::endl; + tou_close(sockfd1); + + std::cerr << "closing sockfd2: " << sockfd2 << std::endl; + tou_close(sockfd2); + + + } + return 1; +} + +int setup_socket(struct sockaddr_in addr) +{ + int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); + + if (sockfd <= 0) + { + std::cerr << "Failed to open socket!: "; + std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; + return -1; + } + + std::cerr << "Socket Created: " << sockfd << std::endl; + + int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); + + if (err < 0) + { + std::cerr << "Error: Cannot bind socket: "; + std::cerr << err << std::endl; + return -1; + } + + std::cerr << "Socket1 Bound to: " << addr << std::endl; + return sockfd; +} + +int connect_socket_pair(int fd1, int fd2, + struct sockaddr_in addr1, struct sockaddr_in addr2) +{ + std::cerr << "Socket2 Listening " << std::endl; + /* listen */ + int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1)); + int err_num; + + if (err < 0) + { + err_num = tou_errno(fd2); + if (err_num != EINPROGRESS) + { + std::cerr << "Cannot Listen!: " << err_num << std::endl; + return -1; + } + } + + + std::cerr << "Socket1 Connecting to: " << addr2 << std::endl; + err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2), 30); + if (err < 0) + { + err_num = tou_errno(fd1); + if (err_num != EINPROGRESS) + { + std::cerr << "Cannot Connect!: " << err_num << std::endl; + return -1; + } + } + + bool sock1Connected = false; + bool sock2Connected = false; + + while((!sock1Connected) || (!sock2Connected)) + { + sleep(1); + + /* sock1 */ + if((!sock1Connected) && (0 == (err = tou_connected(fd1)))) + { + std::cerr << "Waiting for Connect (Sock1)!" << std::endl; + } + + if ((!sock1Connected) && (err < 0)) + { + std::cerr << "Connect Failed" << std::endl; + return 1; + } + else if (!sock1Connected) + { + // else connected! + sock1Connected = true; + } + + /* accept - sock2 */ + struct sockaddr_in inaddr; + socklen_t addrlen = sizeof(inaddr); + int nsock = -1; + + if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2, + (struct sockaddr *) &inaddr, &addrlen)))) + { + errno = tou_errno(fd2); + if (errno != EAGAIN) + { + std::cerr << "Cannot Connect!: " << errno << std::endl; + return 1; + } + else + { + std::cerr << "Waiting for Connect (Sock2)!" << std::endl; + } + } + else if (nsock > 0) + { + /* connected */ + sock2Connected = true; + fd2 = nsock; + std::cerr << "Socket Accepted from: " << inaddr << std::endl; + } + } + + std::cerr << "Socket Connected" << std::endl; + + return 1; +} + + +/* This transmits into sockfd1, and check to see that we recv + * it back from sockfd2 + */ + +int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size) +{ + /* what we recvd */ + char *recvd = (char *) malloc(size * 2); + int recvdsize = 0; + int sent = 0; + int sendsize = 0; + + int ts_start = time(NULL); + + int minsends = 100; /* min of 100 sends to complete all data */ + /* ensure we don't end up sending nothing */ + if (minsends * 10 > size) + { + minsends = size / 10; + } + + bool doneWrite = false; + bool doneRead = false; + + int maxtransfer = (int) (size / minsends) + (int) (((float) (size / minsends)) * + (rand() / (RAND_MAX + 1.0))); + /* allow the transfer ratio read/write to vary between 0.4->1,5. */ + double tf_ratio = 0.4 + 1.1 * (rand() / (RAND_MAX + 1.0)); + + while((!doneWrite) || (!doneRead)) + { + /* have a little break */ + //usleep(10000); /* 0.01 sec */ + usleep(20000); /* 0.02 sec */ + //usleep(250000); /* 0.25 sec */ + //usleep(500000); /* 0.50 sec */ + /* decide how much to send */ + sendsize = (int) (((float) (maxtransfer)) * + (rand() / (RAND_MAX + 1.0))); + + /* limit send */ + if (sent + sendsize > size) + { + std::cerr << "Last WRITE!" << std::endl; + sendsize = size - sent; + } + /* if we've finished */ + if (sent == size) + { + /* eof */ + std::cerr << "Write Done!" << std::endl; + doneWrite = true; + sendsize = 0; + } + + /* now we write */ + if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize))) + { + std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl; + if (tou_errno(sockfd1) != EAGAIN) + { + std::cerr << "FATAL ERROR ending transfer" << std::endl; + doneRead = true; + doneWrite = true; + } + + } + else + { + sent += sendsize; + } + + int ret = 0; + + // read size about 1/4 of write to exercise the buffers. + int readsize = (int) (((float) (maxtransfer)) * tf_ratio * + (rand() / (RAND_MAX + 1.0))); + + if (readsize > size - recvdsize) + { + std::cerr << "Last READ!" << std::endl; + readsize = size - recvdsize; + } + + if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize))) + { + std::cerr << "TF(" << ret << ")" << std::endl; + + /* check the data at this point */ + + int i; + int diffCount = 0; + int init_err = 0; + for(i = 0; i < ret; i++) + { + if (recvd[recvdsize + i] != data[recvdsize + i]) + { + if (!diffCount) + { + init_err = i; + } + diffCount++; + if (diffCount < 10) + { + std::cerr << "Error Byte:" << recvdsize + i << " is different"; + std::cerr << std::endl; + } + } + } + if (diffCount) + { + std::cerr << "Errors (" << diffCount << "/" << ret << ") in read, "; + std::cerr << std::endl; + std::cerr << " At Blk Start: " << recvdsize << " offset: " << init_err; + std::cerr << " ==> At index: " << recvdsize + init_err << "... Exiting!"; + std::cerr << std::endl; + exit(1); + } + else + { + std::cerr << "Checked (" << recvdsize << "+ 0 => " << ret << ") Okay" << std::endl; + } + + recvdsize += ret; + } + else if (ret == 0) + { + //doneRead = true; + std::cerr << "Read Done? (ret:0)" << std::endl; + } + else + { + std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl; + std::cerr << "Read " << recvdsize << "/" << size; + std::cerr << " attempted: " << readsize << std::endl; + if (tou_errno(sockfd2) != EAGAIN) + { + std::cerr << "FATAL ERROR ending transfer" << std::endl; + doneRead = true; + doneWrite = true; + } + + } + + if (recvdsize == size) + { + doneRead = true; + std::cerr << "Read Done!" << std::endl; + } + + } + + /* we have transmitted it all, so + * check the data + */ + + int i; + int diffCount = 0; + for(i = 0; i < size; i++) + { + if (recvd[i] != data[i]) + { + diffCount++; + if (diffCount < 10) + { + std::cerr << "Error Byte:" << i << " is different"; + std::cerr << std::endl; + } + } + } + if (diffCount) + { + std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!"; + std::cerr << std::endl; + exit(1); + } + + int ts_end = time(NULL); + double rough_rate = size / (double) (ts_end - ts_start); + + std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs"; + std::cerr << std::endl; + std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec"; + std::cerr << std::endl; + std::cerr << "Transfer Ratio: " << tf_ratio; + std::cerr << std::endl; + + free(recvd); + + return 1; +} + + + + + + + + diff --git a/libretroshare/src/tests/tcponudp/pair_tou.cc b/libretroshare/src/tests/tcponudp/pair_tou.cc new file mode 100644 index 000000000..d2d7cdc80 --- /dev/null +++ b/libretroshare/src/tests/tcponudp/pair_tou.cc @@ -0,0 +1,493 @@ +/* + * "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +#include +#include + +//#define USE_TCP_SOCKET + +// for printing sockaddr +#include "udp/udpstack.h" + +#ifndef USE_TCP_SOCKET + #include "tcponudp/tou.h" +#endif + +#include "util/bdnet.h" + +#include +#include +#include + + +/* This is a simple test to ensure that the tou behaviour + * is almost identical to a standard tcp socket. + * + * In this version we open 2 sockets, and attempt to + * communicate with ourselves.... + * + */ + +int Check_Socket(int fd); + +void usage(char *name) +{ + std::cerr << "Usage: " << name; + std::cerr << " [-pco] "; + std::cerr << " "; + std::cerr << std::endl; + exit(1); + return; +} + +int main(int argc, char **argv) +{ + int c; + bool isProxy = false; + bool toConnect = false; + bool stayOpen = false; + + int totalwbytes = 0; + int totalrbytes = 0; + + while(-1 != (c = getopt(argc, argv, "pco"))) + { + switch (c) + { + case 'p': + isProxy = true; + break; + case 'c': + toConnect = true; + break; + case 'o': + stayOpen = true; + break; + default: + usage(argv[0]); + break; + } + } + + if (argc-optind < 4) + { + usage(argv[0]); + return 1; + } + + /* setup the local/remote addresses. + */ + struct sockaddr_in laddr; + struct sockaddr_in raddr; + + laddr.sin_family = AF_INET; + raddr.sin_family = AF_INET; + + if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || + (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) + { + std::cerr << "Invalid addresses!" << std::endl; + usage(argv[0]); + } + + laddr.sin_port = htons(atoi(argv[optind+1])); + raddr.sin_port = htons(atoi(argv[optind+3])); + + std::cerr << "Local Address: " << laddr << std::endl; + std::cerr << "Remote Address: " << raddr << std::endl; + + UdpStack udps(laddr); + tou_init((void *) &udps); + + +#ifdef USE_TCP_SOCKET + int sockfd = socket(PF_INET, SOCK_STREAM, 0); + int sockfd2 = socket(PF_INET, SOCK_STREAM, 0); +#else + int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); + int sockfd2 = tou_socket(PF_INET, SOCK_STREAM, 0); +#endif + if ((sockfd <= 0) || (sockfd2 <= 0)) + { + std::cerr << "Failed to open socket!: "; +#ifdef USE_TCP_SOCKET + std::cerr << "Socket Error:" << errno << std::endl; +#else + std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; + std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl; +#endif + return -1; + } + std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl; + + + /* make nonblocking */ +#ifdef USE_TCP_SOCKET + int err = fcntl(sockfd,F_SETFD,O_NONBLOCK); + int err2 = fcntl(sockfd2,F_SETFD,O_NONBLOCK); +#else + int err = 0; + int err2 = 0; +#endif + if ((err < 0) || (err2 < 0)) + { + std::cerr << "Error: Cannot make socket NON-Blocking: "; + std::cerr << err << std::endl; + return -1; + } + + std::cerr << "Socket Non-Blocking" << std::endl; + +#ifdef USE_TCP_SOCKET + err = bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); + err2 = bind(sockfd2, (struct sockaddr *) &raddr, sizeof(raddr)); +#else + err = tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); + err2 = tou_bind(sockfd2, (struct sockaddr *) &raddr, sizeof(raddr)); +#endif + if ((err < 0) || (err2 < 0)) + { + std::cerr << "Error: Cannot bind socket: "; + std::cerr << err << std::endl; + return -1; + } + + std::cerr << "Socket1 Bound to: " << laddr << std::endl; + std::cerr << "Socket2 Bound to: " << raddr << std::endl; + + // listening. + if (1) // socket2. + { + std::cerr << "Socket2 Listening " << std::endl; + /* listen */ +#ifdef USE_TCP_SOCKET + err = listen(sockfd2, 1); +#else + err = tou_listenfor(sockfd2, + (struct sockaddr *) &laddr, sizeof(laddr)); +#endif + } + + + if (1) // only one program. + { + std::cerr << "Socket1 Connecting to: " << raddr << std::endl; +#ifdef USE_TCP_SOCKET + err = connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr)); +#else + err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); +#endif + if (err < 0) + { +#ifndef USE_TCP_SOCKET + errno = tou_errno(sockfd); +#endif + if (errno != EINPROGRESS) + { + std::cerr << "Cannot Connect!: " << errno << std::endl; + return 1; + } + } + } + + bool sock1Connected = false; + bool sock2Connected = false; + + while((!sock1Connected) || (!sock2Connected)) + { + sleep(1); + + + /* sock1 */ +#ifdef USE_TCP_SOCKET + if((!sock1Connected) && (0 == (err = Check_Socket(sockfd)))) +#else + if((!sock1Connected) && (0 == (err = tou_connected(sockfd)))) +#endif + { + std::cerr << "Waiting for Connect (Sock1)!" << std::endl; + } + if ((!sock1Connected) && (err < 0)) + { + std::cerr << "Connect Failed" << std::endl; + return 1; + } + else if (!sock1Connected) + { + // else connected! + sock1Connected = true; + } + + /* accept - sock2 */ + struct sockaddr_in inaddr; + socklen_t addrlen = sizeof(inaddr); + int nsock = -1; + +#ifdef USE_TCP_SOCKET + if ((!sock2Connected) && (0 > (nsock = accept(sockfd2, + (struct sockaddr *) &inaddr, &addrlen)))) +#else + if ((!sock2Connected) && (0 > (nsock = tou_accept(sockfd2, + (struct sockaddr *) &inaddr, &addrlen)))) +#endif + { +#ifndef USE_TCP_SOCKET + errno = tou_errno(sockfd2); +#endif + if (errno != EAGAIN) + { + std::cerr << "Cannot Connect!: " << errno << std::endl; + return 1; + } + else + { + std::cerr << "Waiting for Connect (Sock2)!" << std::endl; + } + } + else if (nsock > 0) + { + /* connected */ + sock2Connected = true; + sockfd2 = nsock; + std::cerr << "Socket Accepted from: " << inaddr << std::endl; + } + } + + std::cerr << "Socket Connected" << std::endl; + + /* send data */ + int bufsize = 1511; + char buffer[bufsize]; + char data[bufsize]; + int readsize = 0; + + bdnet_fcntl(0, F_SETFL, O_NONBLOCK); + bdnet_fcntl(1,F_SETFL,O_NONBLOCK); + + bool doneWrite = false; + bool doneRead = false; + bool blockread = false; + while((!doneWrite) || (!doneRead)) + { + /* read -> write_socket... */ + sleep(1); + if (blockread != true) + { + readsize = read(0, buffer, bufsize); + } + if (readsize == 0) + { + /* eof */ + doneWrite = true; + } + /* now we write */ +#ifdef USE_TCP_SOCKET + if ((readsize > 0) && (-1 == write(sockfd, buffer, readsize))) +#else + if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize))) +#endif + { + //std::cerr << "Blocked Write!" << std::endl; +#ifndef USE_TCP_SOCKET + //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; +#endif + blockread = true; + } + else + { + blockread = false; + totalwbytes += readsize; + } + + int ret = 0; +#ifdef USE_TCP_SOCKET + if (0 < (ret = read(sockfd2, data, bufsize))) +#else + if (0 < (ret = tou_read(sockfd2, data, bufsize))) +#endif + + { + std::cerr << "TF(" << ret << ")" << std::endl; + write(1, data, ret); + totalrbytes += ret; + } + else if (ret == 0) + { + doneRead = true; + } + else + { + //std::cerr << "Blocked Read!" << std::endl; +#ifndef USE_TCP_SOCKET + //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; +#endif + } + + + } + +#ifdef USE_TCP_SOCKET + close(sockfd); + close(sockfd2); +#else + /* this is blocking??? */ + tou_close(sockfd); + tou_close(sockfd2); +#endif + + std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; + std::cerr << std::endl; + return 1; +} + +#ifdef USE_TCP_SOCKET + + +int Check_Socket(int fd) +{ + std::cerr << "Check_Socket()" << std::endl; + + std::cerr << "1) Checking with Select()" << std::endl; + + fd_set ReadFDs, WriteFDs, ExceptFDs; + FD_ZERO(&ReadFDs); + FD_ZERO(&WriteFDs); + FD_ZERO(&ExceptFDs); + + FD_SET(fd, &ReadFDs); + FD_SET(fd, &WriteFDs); + FD_SET(fd, &ExceptFDs); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + int sr = 0; + if (0 > (sr = select(fd + 1, + &ReadFDs, &WriteFDs, &ExceptFDs, &timeout))) + { + std::cerr << "Check_Socket() Select ERROR: " << sr << std::endl; + return -1; + } + + if (FD_ISSET(fd, &ExceptFDs)) + { + std::cerr << "Check_Socket() Exception on socket!" << std::endl; + return -1; + } + + if (FD_ISSET(fd, &WriteFDs)) + { + std::cerr << "Check_Socket() Can Write!" << std::endl; + } + else + { + // not ready return 0; + std::cerr << "Check_Socket() Cannot Write!" << std::endl; + std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; + return 0; + } + + if (FD_ISSET(fd, &ReadFDs)) + { + std::cerr << "Check_Socket() Can Read!" << std::endl; + } + else + { + std::cerr << "Check_Socket() Cannot Read!" << std::endl; + std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; + return 0; + } + + std::cerr << "Select() Tests indicate Socket Good!" << std::endl; + std::cerr << "2) Checking with getsockopt()" << std::endl; + + int err = 1; + socklen_t optlen = 4; + if (0==getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen)) + { + std::cerr << "Check_Socket() getsockopt returned :" << err; + std::cerr << ", optlen:" << optlen; + std::cerr << std::endl; + + if (err == 0) + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates TCP Connection Complete:"; + std::cerr << std::endl; + return 1; + } + else if (err == EINPROGRESS) + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates TCP Connection INPROGRESS"; + std::cerr << std::endl; + return 0; + } + else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; + std::cerr << std::endl; + return -1; + } + else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN)) + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; + std::cerr << std::endl; + return -1; + } + else + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates Other Error: " << err; + std::cerr << std::endl; + return -1; + } + + + } + else + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " FAILED "; + std::cerr << std::endl; + return -1; + } +} + + +#else + +int Check_Socket(int fd) +{ + return 0; +} + +#endif diff --git a/libretroshare/src/tests/tcponudp/reset_tou.cc b/libretroshare/src/tests/tcponudp/reset_tou.cc new file mode 100644 index 000000000..3faa8851c --- /dev/null +++ b/libretroshare/src/tests/tcponudp/reset_tou.cc @@ -0,0 +1,453 @@ +/* + * "$Id: reset_tou.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +/********************************************************** + * This test is designed to ensure that tou networking + * can be reset, and restarted. + * + */ + +#include + +// for printing sockaddr +#include "udplayer.h" + +#include "tou.h" +#include "tou_net.h" + +#include +#include +#include + + +/* This is a simple test to ensure that the tou behaviour + * is almost identical to a standard tcp socket. + * + * In this version we open 2 sockets, and attempt to + * communicate with ourselves.... + * + */ + +int setup_socket(struct sockaddr_in addr); +int connect_socket_pair(int fd1, int fd2, + struct sockaddr_in addr1, struct sockaddr_in addr2); +int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size); + +void usage(char *name) +{ + std::cerr << "Usage: " << name; + std::cerr << " [-pco] "; + std::cerr << " "; + std::cerr << std::endl; + exit(1); + return; +} + +int main(int argc, char **argv) +{ + int c; + bool isProxy = false; + bool toConnect = false; + bool stayOpen = false; + int i,j; + + while(-1 != (c = getopt(argc, argv, "pco"))) + { + switch (c) + { + case 'p': + isProxy = true; + break; + case 'c': + toConnect = true; + break; + case 'o': + stayOpen = true; + break; + default: + usage(argv[0]); + break; + } + } + + if (argc-optind < 4) + { + usage(argv[0]); + return 1; + } + + tounet_init(); + + + /* setup the local/remote addresses. + */ + struct sockaddr_in laddr; + struct sockaddr_in raddr; + + laddr.sin_family = AF_INET; + raddr.sin_family = AF_INET; + + if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) || + (!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) + { + std::cerr << "Invalid addresses!" << std::endl; + usage(argv[0]); + } + + unsigned short laddr_port = atoi(argv[optind+1]); + unsigned short raddr_port = atoi(argv[optind+3]); + + for(i = 0; i < 10; i++) + { + laddr.sin_port = htons(laddr_port); + raddr.sin_port = htons(raddr_port); + //laddr.sin_port = htons(laddr_port + i); + //raddr.sin_port = htons(raddr_port + i); + + std::cerr << "Interation: " << i << std::endl; + + + /* setup the sockets */ + int sockfd1 = setup_socket(laddr); + int sockfd2 = setup_socket(raddr); + + if ((sockfd1 < 0) || (sockfd2 < 0)) + { + std::cerr << "Failed to setup sockets!"; + std::cerr << std::endl; + return -1; + } + + std::cerr << "Local Address: " << laddr; + std::cerr << " fd: " << sockfd1 << std::endl; + std::cerr << "Remote Address: " << raddr; + std::cerr << " fd: " << sockfd2 << std::endl; + + /* connect */ + int err = connect_socket_pair(sockfd1, sockfd2, laddr, raddr); + if (err < 0) + { + std::cerr << "Failed to connect sockets!"; + std::cerr << std::endl; + return -1; + } + + /* send the data */ + int size = 102400; + char rnddata[size]; + + int data_loops = (i+1) * (i+1); + for(int k = 0; k < data_loops; k++) + { + std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; + for(j = 0; j < size; j++) + { + rnddata[j] = (unsigned char) (255.0 * + rand() / (RAND_MAX + 1.0)); + } + send_data_via_pair(sockfd1, sockfd2, rnddata, size); + std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl; + sleep(2); + } + + std::cerr << "Completed Successful transfer of " << size * data_loops << " bytes"; + std::cerr << std::endl; + + sleep(10); + std::cerr << "closing sockfd1: " << sockfd1 << std::endl; + tou_close(sockfd1); + + std::cerr << "closing sockfd2: " << sockfd2 << std::endl; + tou_close(sockfd2); + + + } + return 1; +} + +int setup_socket(struct sockaddr_in addr) +{ + int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); + + if (sockfd <= 0) + { + std::cerr << "Failed to open socket!: "; + std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; + return -1; + } + + std::cerr << "Socket Created: " << sockfd << std::endl; + + int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); + + if (err < 0) + { + std::cerr << "Error: Cannot bind socket: "; + std::cerr << err << std::endl; + return -1; + } + + std::cerr << "Socket1 Bound to: " << addr << std::endl; + return sockfd; +} + +int connect_socket_pair(int fd1, int fd2, + struct sockaddr_in addr1, struct sockaddr_in addr2) +{ + std::cerr << "Socket2 Listening " << std::endl; + /* listen */ + int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1)); + int err_num; + + if (err < 0) + { + err_num = tou_errno(fd2); + if (err_num != EINPROGRESS) + { + std::cerr << "Cannot Listen!: " << err_num << std::endl; + return -1; + } + } + + + std::cerr << "Socket1 Connecting to: " << addr2 << std::endl; + err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2), 30); + if (err < 0) + { + err_num = tou_errno(fd1); + if (err_num != EINPROGRESS) + { + std::cerr << "Cannot Connect!: " << err_num << std::endl; + return -1; + } + } + + bool sock1Connected = false; + bool sock2Connected = false; + + while((!sock1Connected) || (!sock2Connected)) + { + sleep(1); + + /* sock1 */ + if((!sock1Connected) && (0 == (err = tou_connected(fd1)))) + { + std::cerr << "Waiting for Connect (Sock1)!" << std::endl; + } + + if ((!sock1Connected) && (err < 0)) + { + std::cerr << "Connect Failed" << std::endl; + return 1; + } + else if (!sock1Connected) + { + // else connected! + sock1Connected = true; + } + + /* accept - sock2 */ + struct sockaddr_in inaddr; + socklen_t addrlen = sizeof(inaddr); + int nsock = -1; + + if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2, + (struct sockaddr *) &inaddr, &addrlen)))) + { + errno = tou_errno(fd2); + if (errno != EAGAIN) + { + std::cerr << "Cannot Connect!: " << errno << std::endl; + return 1; + } + else + { + std::cerr << "Waiting for Connect (Sock2)!" << std::endl; + } + } + else if (nsock > 0) + { + /* connected */ + sock2Connected = true; + fd2 = nsock; + std::cerr << "Socket Accepted from: " << inaddr << std::endl; + } + } + + std::cerr << "Socket Connected" << std::endl; + + return 1; +} + + +/* This transmits into sockfd1, and check to see that we recv + * it back from sockfd2 + */ + +int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size) +{ + /* what we recvd */ + char *recvd = (char *) malloc(size * 2); + int recvdsize = 0; + int sent = 0; + int sendsize = 0; + + int ts_start = time(NULL); + + int minsends = 100; /* min of 100 sends to complete all data */ + /* ensure we don't end up sending nothing */ + if (minsends * 10 > size) + { + minsends = size / 10; + } + + bool doneWrite = false; + bool doneRead = false; + while((!doneWrite) || (!doneRead)) + { + /* have a little break */ + //usleep(10000); /* 0.01 sec */ + //usleep(250000); /* 0.25 sec */ + usleep(500000); /* 0.50 sec */ + /* decide how much to send */ + sendsize = (int) (((float) (size / minsends)) * + (rand() / (RAND_MAX + 1.0))); + + /* limit send */ + if (sent + sendsize > size) + { + sendsize = size - sent; + } + /* if we've finished */ + if (sent == size) + { + /* eof */ + std::cerr << "Write Done!" << std::endl; + doneWrite = true; + sendsize = 0; + } + + /* now we write */ + if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize))) + { + std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl; + if (tou_errno(sockfd1) != EAGAIN) + { + std::cerr << "FATAL ERROR ending transfer" << std::endl; + doneRead = true; + doneWrite = true; + } + + } + else + { + sent += sendsize; + } + + int ret = 0; + int readsize = (int) (((float) (size / minsends)) * + (rand() / (RAND_MAX + 1.0))); + + if (readsize > size - recvdsize) + readsize = size - recvdsize; + + if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize))) + { + std::cerr << "TF(" << ret << ")" << std::endl; + recvdsize += ret; + } + else if (ret == 0) + { + doneRead = true; + std::cerr << "Read Done! (ret:0)" << std::endl; + } + else + { + std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl; + std::cerr << "Read " << recvdsize << "/" << size; + std::cerr << " attempted: " << readsize << std::endl; + if (tou_errno(sockfd2) != EAGAIN) + { + std::cerr << "FATAL ERROR ending transfer" << std::endl; + doneRead = true; + doneWrite = true; + } + + } + + if (recvdsize == size) + { + doneRead = true; + std::cerr << "Read Done!" << std::endl; + } + + } + + /* we have transmitted it all, so + * check the data + */ + + int i; + int diffCount = 0; + for(i = 0; i < size; i++) + { + if (recvd[i] != data[i]) + { + diffCount++; + if (diffCount < 10) + { + std::cerr << "Error Byte:" << i << " is different"; + std::cerr << std::endl; + } + } + } + if (diffCount) + { + std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!"; + std::cerr << std::endl; + exit(1); + } + + int ts_end = time(NULL); + double rough_rate = size / (double) (ts_end - ts_start); + + std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs"; + std::cerr << std::endl; + std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec"; + std::cerr << std::endl; + + return 1; +} + + + + + + + + diff --git a/libretroshare/src/tests/tcponudp/test_tou.cc b/libretroshare/src/tests/tcponudp/test_tou.cc new file mode 100644 index 000000000..70fc89b12 --- /dev/null +++ b/libretroshare/src/tests/tcponudp/test_tou.cc @@ -0,0 +1,518 @@ +/* + * "$Id: test_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +#include +#include + +//#define USE_TCP_SOCKET + +// for printing sockaddr +#include "udp/udpstack.h" + +#ifndef USE_TCP_SOCKET + #include "tcponudp/tou.h" +#endif + +/* shouldn't do this - but for convenience + * using tou_net.h for universal fns + * generally this should be only internal to libtou.h + * + * This includes the whole networking interface + */ + +#include "util/bdnet.h" + +/* These three includes appear to work in both W & L. + * and they shouldn't!!!! maybe cygwin is allowing it... + * will only use them for tou test fns. + * + * they appear to provide getopt + read/write in windows. + */ + +#include +#include +#include + +/* This is a simple test to ensure that the tou behaviour + * is almost identical to a standard tcp socket. + * + */ + +int Check_Socket(int fd); + +void usage(char *name) +{ + std::cerr << "Usage: " << name; + std::cerr << " [-pco] "; + std::cerr << " "; + std::cerr << std::endl; + exit(1); + return; +} + +int main(int argc, char **argv) +{ + int c; + bool isProxy = false; + bool toConnect = false; + bool stayOpen = false; + + int totalwbytes = 0; + int totalrbytes = 0; + + while(-1 != (c = getopt(argc, argv, "pco"))) + { + switch (c) + { + case 'p': + isProxy = true; + break; + case 'c': + toConnect = true; + break; + case 'o': + stayOpen = true; + break; + default: + usage(argv[0]); + break; + } + } + + if (argc-optind < 4) + { + usage(argv[0]); + return 1; + } + + + /* setup the local/remote addresses. + */ + struct sockaddr_in laddr; + struct sockaddr_in raddr; + + laddr.sin_family = AF_INET; + raddr.sin_family = AF_INET; + + if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || + (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) + { + std::cerr << "Invalid addresses!" << std::endl; + usage(argv[0]); + } + + laddr.sin_port = htons(atoi(argv[optind+1])); + raddr.sin_port = htons(atoi(argv[optind+3])); + + std::cerr << "Local Address: " << laddr << std::endl; + std::cerr << "Remote Address: " << raddr << std::endl; + + UdpStack udps(laddr); + tou_init((void *) &udps); + +#ifdef USE_TCP_SOCKET + int sockfd = socket(PF_INET, SOCK_STREAM, 0); +#else + int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0); +#endif + if (sockfd < 0) + { + std::cerr << "Failed to open socket!: "; +#ifdef USE_TCP_SOCKET + std::cerr << "Socket Error:" << errno << std::endl; +#else + std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl; +#endif + return -1; + } + std::cerr << "Socket Created" << std::endl; + + + /* make nonblocking */ +#ifdef USE_TCP_SOCKET + int err = bdnet_fcntl(sockfd,F_SETFL,O_NONBLOCK); +#else + int err = 0; +#endif + if (err < 0) + { + std::cerr << "Error: Cannot make socket NON-Blocking: "; + std::cerr << err << std::endl; + return -1; + } + + std::cerr << "Socket Non-Blocking" << std::endl; + +#ifdef USE_TCP_SOCKET + err = bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); + if (err < 0) + { + std::cerr << "Error: Cannot bind socket: "; + std::cerr << err << std::endl; + return -1; + } + std::cerr << "Socket Bound to: " << laddr << std::endl; +#else + err = tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr)); + if (err < 0) + { + std::cerr << "As expected, cannot bind a tou socket"; + std::cerr << err << std::endl; + //return -1; + } +#endif + + + if (toConnect) + { + std::cerr << "Socket Connecting to: " << raddr << std::endl; +#ifdef USE_TCP_SOCKET + err = connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr)); +#else + err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30); +#endif + if (err < 0) + { +#ifndef USE_TCP_SOCKET + errno = tou_errno(sockfd); +#endif + if (errno != EINPROGRESS) + { + std::cerr << "Cannot Connect!" << std::endl; + return 1; + } +#ifdef USE_TCP_SOCKET + while(0 == (err = Check_Socket(sockfd))) +#else + while(0 == (err = tou_connected(sockfd))) +#endif + { + std::cerr << "Waiting for Connect!" << std::endl; + sleep(1); + } + if (err < 0) + { + std::cerr << "Connect Failed" << std::endl; + return 1; + } + // else connected! + } + } + else + { + std::cerr << "Socket Listening " << std::endl; + /* listen */ +#ifdef USE_TCP_SOCKET + err = listen(sockfd, 1); +#else + //err = tou_listen(sockfd, 1); + err = tou_listenfor(sockfd, + (struct sockaddr *) &raddr, sizeof(raddr)); +#endif + + /* accept */ + struct sockaddr_in inaddr; + socklen_t addrlen = sizeof(inaddr); + int nsock; + +#ifdef USE_TCP_SOCKET + while(0 > (nsock = accept(sockfd, + (struct sockaddr *) &inaddr, &addrlen))) +#else + while(0 > (nsock = tou_accept(sockfd, + (struct sockaddr *) &inaddr, &addrlen))) +#endif + { +#ifndef USE_TCP_SOCKET + errno = tou_errno(sockfd); +#endif + if (errno != EAGAIN) + { + std::cerr << "Cannot Connect!" << std::endl; + return 1; + } + sleep(1); + } + /* changed sockfd */ + sockfd = nsock; + std::cerr << "Socket Accepted from: " << inaddr << std::endl; + } + + std::cerr << "Socket Connected" << std::endl; + + if (toConnect) + { + /* send data */ + int bufsize = 15011; + char buffer[bufsize]; + int readsize = 0; + + bdnet_fcntl(0, F_SETFL, O_NONBLOCK); + + bool done = false; + bool blockread = false; + while(!done) + { + //sleep(1); + //usleep(10000); + usleep(100); + if (blockread != true) + { + readsize = read(0, buffer, bufsize); + } + if (readsize == 0) + { + /* eof */ + done = true; + } + else if ((readsize == -1) && ( EAGAIN == errno )) + { + continue; + } + + + /* now we write */ +#ifdef USE_TCP_SOCKET + if (-1 == write(sockfd, buffer, readsize)) +#else + if (-1 == tou_write(sockfd, buffer, readsize)) +#endif + { + //std::cerr << "Blocked Write!" << std::endl; +#ifndef USE_TCP_SOCKET + //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; +#endif + blockread = true; + } + else + { + blockread = false; + totalwbytes += readsize; + } + } + +#ifdef USE_TCP_SOCKET + close(sockfd); +#else + /* this is blocking??? */ + tou_close(sockfd); +#endif + + std::cerr << "Transfer Complete: " << totalwbytes << " bytes"; + std::cerr << std::endl; + + // ACTUALLY tou_close() is not blocking... + // and kills the connection instantly. + // The transfer will fail if there is any data left in the send queue (which there is in most cases). + // Interestingly.. if we slow the transmit and speed up the recv, + // Then it can succeed. + // + // The settings are done to make this fail. + + return 1; + } + + /* recv data */ + int bufsize = 1523; + char data[bufsize]; + bdnet_fcntl(1,F_SETFL,O_NONBLOCK); + while(1) + { + //sleep(1); + //usleep(10000); + //usleep(1000); + usleep(100); + int writesize = bufsize; + int ret; + +#ifdef USE_TCP_SOCKET + if (0 < (ret = read(sockfd, data, writesize))) +#else + if (0 < (ret = tou_read(sockfd, data, writesize))) +#endif + + { + std::cerr << "TF(" << ret << ")" << std::endl; + write(1, data, ret); + totalrbytes += ret; + } + else if (ret == 0) + { + break; + } + else + { + //std::cerr << "Blocked Read!" << std::endl; +#ifndef USE_TCP_SOCKET + //std::cerr << "Error: " << tou_errno(sockfd) << std::endl; +#endif + + } + } + +#ifdef USE_TCP_SOCKET + close(sockfd); +#else + tou_close(sockfd); +#endif + + std::cerr << "Transfer complete :" << totalrbytes; + std::cerr << " bytes" << std::endl; + close(1); + + return 1; +} + + + +#ifdef USE_TCP_SOCKET + + +int Check_Socket(int fd) +{ + std::cerr << "Check_Socket()" << std::endl; + + std::cerr << "1) Checking with Select()" << std::endl; + + fd_set ReadFDs, WriteFDs, ExceptFDs; + FD_ZERO(&ReadFDs); + FD_ZERO(&WriteFDs); + FD_ZERO(&ExceptFDs); + + FD_SET(fd, &ReadFDs); + FD_SET(fd, &WriteFDs); + FD_SET(fd, &ExceptFDs); + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + int sr = 0; + if (0 > (sr = select(fd + 1, + &ReadFDs, &WriteFDs, &ExceptFDs, &timeout))) + { + std::cerr << "Check_Socket() Select ERROR: " << sr << std::endl; + return -1; + } + + if (FD_ISSET(fd, &ExceptFDs)) + { + std::cerr << "Check_Socket() Exception on socket!" << std::endl; + return -1; + } + + if (FD_ISSET(fd, &WriteFDs)) + { + std::cerr << "Check_Socket() Can Write!" << std::endl; + } + else + { + // not ready return 0; + std::cerr << "Check_Socket() Cannot Write!" << std::endl; + std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; + return 0; + } + + if (FD_ISSET(fd, &ReadFDs)) + { + std::cerr << "Check_Socket() Can Read!" << std::endl; + } + else + { + std::cerr << "Check_Socket() Cannot Read!" << std::endl; + std::cerr << "Check_Socket() Socket Not Ready!" << std::endl; + return 0; + } + + std::cerr << "Select() Tests indicate Socket Good!" << std::endl; + std::cerr << "2) Checking with getsockopt()" << std::endl; + + int err = 1; + socklen_t optlen = 4; + if (0==getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen)) + { + std::cerr << "Check_Socket() getsockopt returned :" << err; + std::cerr << ", optlen:" << optlen; + std::cerr << std::endl; + + if (err == 0) + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates TCP Connection Complete:"; + std::cerr << std::endl; + return 1; + } + else if (err == EINPROGRESS) + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates TCP Connection INPROGRESS"; + std::cerr << std::endl; + return 0; + } + else if ((err == ENETUNREACH) || (err == ETIMEDOUT)) + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; + std::cerr << std::endl; + return -1; + } + else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN)) + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT"; + std::cerr << std::endl; + return -1; + } + else + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " Indicates Other Error: " << err; + std::cerr << std::endl; + return -1; + } + + + } + else + { + std::cerr << "Check_Socket() getsockopt"; + std::cerr << " FAILED "; + std::cerr << std::endl; + return -1; + } +} + + +#else + +int Check_Socket(int fd) +{ + return 0; +} + +#endif diff --git a/libretroshare/src/tests/tcponudp/udp_server.cc b/libretroshare/src/tests/tcponudp/udp_server.cc new file mode 100644 index 000000000..1f720561a --- /dev/null +++ b/libretroshare/src/tests/tcponudp/udp_server.cc @@ -0,0 +1,285 @@ +/* + * "$Id: udp_server.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $" + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + + +#include "udp/udpstack.h" +#include "tcponudp/udppeer.h" +#include "tcponudp/tcpstream.h" +#include "tcponudp/tou.h" + +#include + +#include +#include +#include + +void usage(char *name) +{ + std::cerr << "Usage: " << name; + std::cerr << " [-pco] "; + std::cerr << " "; + std::cerr << std::endl; + exit(1); + return; +} + +int main(int argc, char **argv) +{ + int c; + bool isProxy = false; + bool toConnect = false; + bool stayOpen = false; + + while(-1 != (c = getopt(argc, argv, "f:pco"))) + { + switch (c) + { + case 'p': + isProxy = true; + break; + case 'c': + toConnect = true; + break; + case 'o': + stayOpen = true; + break; + case 'f': + /* this can only work when the define below exists in tcpstream */ +#ifdef DEBUG_TCP_STREAM_EXTRA + setupBinaryCheck(std::string(optarg)); +#else + std::cerr << "Binary Check no Enabled!" << std::endl; +#endif + break; + default: + usage(argv[0]); + break; + } + } + + if (argc-optind < 4) + { + usage(argv[0]); + return 1; + } + /* setup the local/remote addresses. + */ + + + struct sockaddr_in laddr; + struct sockaddr_in raddr; + + laddr.sin_family = AF_INET; + raddr.sin_family = AF_INET; + + if ((!bdnet_inet_aton(argv[optind], &(laddr.sin_addr))) || + (!bdnet_inet_aton(argv[optind+2], &(raddr.sin_addr)))) + { + std::cerr << "Invalid addresses!" << std::endl; + usage(argv[0]); + } + + laddr.sin_port = htons(atoi(argv[optind+1])); + raddr.sin_port = htons(atoi(argv[optind+3])); + + std::cerr << "Local Address: " << laddr << std::endl; + std::cerr << "Remote Address: " << raddr << std::endl; + + UdpStack udps(laddr); + UdpPeerReceiver *upr = new UdpPeerReceiver(&udps); + udps.addReceiver(upr); + + if (!udps.okay()) + { + std::cerr << "UdpSorter not Okay (Cannot Open Local Address): " << laddr << std::endl; + exit(1); + } + + TcpStream tcp(upr); + upr->addUdpPeer(&tcp, raddr); + + if (toConnect) + { + tcp.connect(raddr, 30); + } + else + { + tcp.listenfor(raddr); + } + + while(!tcp.isConnected()) + { + sleep(1); + std::cerr << "Waiting for TCP to Connect!" << std::endl; + udps.status(std::cerr); + tcp.status(std::cerr); + tcp.tick(); + } + std::cerr << "TCP Connected***************************" << std::endl; + udps.status(std::cerr); + tcp.status(std::cerr); + std::cerr << "TCP Connected***************************" << std::endl; + + int count = 1; + + if (toConnect) + { + /* send data */ + int bufsize = 51; + char buffer[bufsize]; + int readsize = 0; + + bdnet_fcntl(0, F_SETFL, O_NONBLOCK); + + bool done = false; + bool blockread = false; + while(!done) + { + //sleep(1); + //usleep(100000); + usleep(1000); + if (blockread != true) + { + readsize = read(0, buffer, bufsize); + } + if (readsize == 0) + { + /* eof */ + done = true; + } + else if ((readsize == -1) && ( EAGAIN == errno )) + { + continue; + } + + /* now we write */ + if (-1 == tcp.write(buffer, readsize)) + blockread = true; + else + blockread = false; + + + tcp.tick(); + if (count++ % 10 == 0) + { + std::cerr << "******************************************" << std::endl; + tcp.status(std::cerr); + } + } + + tcp.closeWrite(); + + while(!tcp.widle()) + { + //sleep(1); + usleep(100000); + //usleep(1000); + tcp.tick(); + if (count++ % 10 == 0) + { + std::cerr << "Waiting for Idle()" << std::endl; + std::cerr << "******************************************" << std::endl; + tcp.status(std::cerr); + } + } + + std::cerr << "Transfer Complete: " << tcp.wbytes() << " bytes"; + std::cerr << std::endl; + return 1; + } + + /* recv data */ + int bufsize = 1523; + char data[bufsize]; + bdnet_fcntl(1,F_SETFL,O_NONBLOCK); + while(1) + { + //sleep(1); + usleep(100000); + //usleep(1000); + //int writesize = bufsize; + int ret; + if (0 < (ret = tcp.read(data, bufsize))) + { + std::cerr << "TF(" << ret << ")" << std::endl; + write(1, data, ret); + } + else if (ret == 0) + { + /* completed transfer */ + std::cerr << "Transfer complete :" << tcp.rbytes(); + std::cerr << " bytes" << std::endl; + break; + } + + tcp.tick(); + if (count++ % 10 == 0) + { + std::cerr << "******************************************" << std::endl; + tcp.status(std::cerr); + } + if ((!stayOpen) && tcp.ridle()) + { + std::cerr << "Transfer Idle after " << tcp.rbytes(); + std::cerr << " bytes" << std::endl; + close(1); + break; + } + } + + tcp.closeWrite(); + + /* tick for a bit */ + while((stayOpen) || (!tcp.ridle())) + { + tcp.tick(); + //sleep(1); + usleep(100000); + //usleep(1000); + if (count++ % 10 == 0) + { + std::cerr << "Waiting for Idle()" << std::endl; + std::cerr << "******************************************" << std::endl; + tcp.status(std::cerr); + } + } + + + if ((!stayOpen) && tcp.ridle()) + { + //std::cerr << "Transfer complete :" << tcp.rbytes(); + //std::cerr << " bytes" << std::endl; + close(1); + return 1; + } + + return 1; +} + + + + diff --git a/libretroshare/src/tests/tcponudp/udpsock_test.cc b/libretroshare/src/tests/tcponudp/udpsock_test.cc new file mode 100644 index 000000000..bc9aeaf86 --- /dev/null +++ b/libretroshare/src/tests/tcponudp/udpsock_test.cc @@ -0,0 +1,92 @@ +/* + * libretroshare/src/tcponudp: udpsock_test.cc + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "udptestfn.h" +#include "udp/udplayer.h" +#include + +#define MAX_PEERS 16 + +int main(int argc, char **argv) +{ + /* get local and remote addresses */ + struct sockaddr_in local; + struct sockaddr_in peers[MAX_PEERS]; + int numpeers = 0; + int i,j; + + local.sin_family = AF_INET; + inet_aton("127.0.0.1", &(local.sin_addr)); + local.sin_port = htons(8767); + + for(i = 0; i < MAX_PEERS; i++) + { + peers[i].sin_family = AF_INET; + inet_aton("127.0.0.1", &(peers[i].sin_addr)); + peers[i].sin_port = htons(8768); + } + + if (argc < 3) + { + std::cerr << "Usage: " << argv[0] << " [ [addUdpPeer(pt, peers[i-2]); + } + + int size = 12; + void *data = malloc(size); + int ttl = 64; + + /* push packets to the peer */ + for(i = 0; i < 60; i++) + { + sleep(1); + for(j = 0; j < numpeers; j++) + { + udps.sendPkt(data, size, peers[j], ttl); + } + } + return 1; +} + + + diff --git a/libretroshare/src/tests/tcponudp/udptestfn.cc b/libretroshare/src/tests/tcponudp/udptestfn.cc new file mode 100644 index 000000000..6c9b72431 --- /dev/null +++ b/libretroshare/src/tests/tcponudp/udptestfn.cc @@ -0,0 +1,48 @@ +/* + * libretroshare/src/tcponudp: udptestfn.cc + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "udptestfn.h" + +int UdpRecvTest::recvPkt(void *data, int size, struct sockaddr_in &from) +{ + /* print packet information */ + std::cerr << "UdpRecvTest::recvPkt(" << size << ") from: " << from; + std::cerr << std::endl; +} + +UdpPeerTest::UdpPeerTest(struct sockaddr_in &addr) + :raddr(addr) +{ + return; +} + +void UdpPeerTest::recvPkt(void *data, int size) +{ + /* print packet information */ + std::cerr << "UdpPeerTest::recvPkt(" << size << ") from: " << raddr; + std::cerr << std::endl; +} + + diff --git a/libretroshare/src/tests/tcponudp/udptestfn.h b/libretroshare/src/tests/tcponudp/udptestfn.h new file mode 100644 index 000000000..d25a23223 --- /dev/null +++ b/libretroshare/src/tests/tcponudp/udptestfn.h @@ -0,0 +1,53 @@ +/* + * libretroshare/src/tcponudp: udptestfn.h + * + * TCP-on-UDP (tou) network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "udp/udplayer.h" +#include "udp/udpstack.h" +#include "tcponudp/udppeer.h" + +//#include "udpsorter.h" + +#ifndef TOU_UDP_TEST_FN_H +#define TOU_UDP_TEST_FN_H + +class UdpRecvTest: public UdpReceiver +{ + public: +virtual int recvPkt(void *data, int size, struct sockaddr_in &from); +virtual int status(std::ostream&) { return 0; } +}; + + +class UdpPeerTest: public UdpPeer +{ + public: + UdpPeerTest(struct sockaddr_in &addr); +virtual void recvPkt(void *data, int size); + + struct sockaddr_in raddr; +}; + + +#endif diff --git a/libretroshare/src/tests/util/dir2test.cc b/libretroshare/src/tests/util/dir2test.cc new file mode 100644 index 000000000..efbf54c2e --- /dev/null +++ b/libretroshare/src/tests/util/dir2test.cc @@ -0,0 +1,79 @@ +/* + * dirtest.cc + * + * RetroShare Test Program. + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "util/rsdir.h" + +#include + +int processpath(std::string path); + +int main() +{ + + std::string path1 = "/home/tst1//test2///test3/"; + std::string path2 = "home2/tst4//test5///test6"; + std::string path3 = "//home3"; + std::string path4 = "//"; + std::string path5 = "/a/b/c/d/"; + std::string path6 = "a//b/c//d"; + + processpath(path1); + processpath(path2); + processpath(path3); + processpath(path4); + processpath(path5); + processpath(path6); + + return 1; +} + + +int processpath(std::string path) +{ + std::string pathtogo = path; + while(pathtogo != "") + { + std::string basedir = RsDirUtil::getRootDir(pathtogo); + std::string rempath = RsDirUtil::removeRootDir(pathtogo); + std::string topdir = RsDirUtil::getTopDir(pathtogo); + std::string remtoppath = RsDirUtil::removeTopDir(pathtogo); + + std::cerr << "Processing: \"" << pathtogo << "\"" << std::endl; + std::cerr << "\tRootDir : \"" << basedir << "\"" << std::endl; + std::cerr << "\tRemaining: \"" << rempath << "\"" << std::endl; + std::cerr << "\tTopDir : \"" << topdir << "\"" << std::endl; + std::cerr << "\tRemaining(Top): \"" << remtoppath << "\"" << std::endl; + std::cerr << std::endl; + + pathtogo = rempath; + } + return 1; +} + + + + + diff --git a/libretroshare/src/tests/util/dirtest.cc b/libretroshare/src/tests/util/dirtest.cc new file mode 100644 index 000000000..b2cbd4d3a --- /dev/null +++ b/libretroshare/src/tests/util/dirtest.cc @@ -0,0 +1,99 @@ + +/* + * "$Id: dirtest.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#include "util/rsdir.h" + +#include +#include +#include + +bool testRsDirUtils(std::string path); + +int main() +{ + + std::list dirs; + std::list::iterator it; + dirs.push_back("/incoming/htuyr/file.txt"); + dirs.push_back("/incoming/htuyr/file.txt "); + dirs.push_back("/incoming/htuyr/file.txt/"); + dirs.push_back("/incoming/htuyr/file.txt//"); + dirs.push_back("/incoming/htuyr//file.txt//"); + dirs.push_back("/incoming/htuyr//file .txt"); + dirs.push_back("/incoming/htuyr/Q"); + dirs.push_back("/incoming/htuyr/Q//"); + dirs.push_back("/incoming/htuyr/Q/"); + dirs.push_back("/incoming/htuyr/Q/text"); + dirs.push_back("/home/tst1//test2///test3/"); + dirs.push_back("home2/tst4//test5///test6"); + dirs.push_back("//home3"); + dirs.push_back("//"); + dirs.push_back("A"); + dirs.push_back("ABC"); + dirs.push_back("////ABC////"); + dirs.push_back("A/B/C"); + + for(it = dirs.begin(); it != dirs.end(); it++) + { + testRsDirUtils(*it); + } +} + +bool testRsDirUtils(std::string path) +{ + + std::cerr << "RsUtilTest input: [" << path << "]"; + std::cerr << std::endl; + + std::string top = RsDirUtil::getTopDir(path); + std::string root = RsDirUtil::getRootDir(path); + std::string topdirs = RsDirUtil::removeRootDir(path); + std::string topdirs2 = RsDirUtil::removeRootDirs(path, root); + std::string restdirs = RsDirUtil::removeTopDir(path); + std::list split; + std::list::iterator it; + RsDirUtil::breakupDirList(path, split); + + std::cerr << "\tTop: [" << top << "]"; + std::cerr << std::endl; + std::cerr << "\tRest: [" << restdirs << "]"; + std::cerr << std::endl; + + std::cerr << "\tRoot: [" << root << "]"; + std::cerr << std::endl; + std::cerr << "\tRemoveRoot: [" << topdirs << "]"; + std::cerr << std::endl; + std::cerr << "\tSplit Up "; + for(it = split.begin(); it != split.end(); it++) + { + std::cerr << ":" << (*it); + } + std::cerr << std::endl; + std::cerr << std::endl; + return true; +} diff --git a/libretroshare/src/turtle/Makefile b/libretroshare/src/turtle/Makefile new file mode 100644 index 000000000..745a340ac --- /dev/null +++ b/libretroshare/src/turtle/Makefile @@ -0,0 +1,23 @@ +RS_TOP_DIR = .. +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/scripts/config.mk +############################################################### + +RSOBJ = p3turtle.o rsturtleitem.o + +#TESTOBJ = + +#TESTS = + +all: librs tests + +#tlvbase_test : tlvbase_test.o +# $(CC) $(CFLAGS) -o tlvbase_test tlvbase_test.o $(OBJ) $(LIBS) + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc new file mode 100644 index 000000000..49903eaa7 --- /dev/null +++ b/libretroshare/src/turtle/p3turtle.cc @@ -0,0 +1,2293 @@ +/* + * libretroshare/src/services: p3turtle.cc + * + * Services for RetroShare. + * + * Copyright 2009 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "csoler@users.sourceforge.net". + * + */ + +//#define P3TURTLE_DEBUG + +#include +#include +#include +#ifdef P3TURTLE_DEBUG +#include +#endif + +#include "retroshare/rsiface.h" +#include "retroshare/rspeers.h" +#include "retroshare/rsfiles.h" + +#include "pqi/authssl.h" +#include "pqi/p3connmgr.h" +#include "pqi/pqinotify.h" + +#include "ft/ftserver.h" +#include "ft/ftdatamultiplex.h" +#include "ft/ftcontroller.h" + +#include "p3turtle.h" + +#include +#include +#include + +#include +#include + +#include "util/rsdebug.h" +#include "util/rsprint.h" +#include "util/rsrandom.h" +#include "pqi/pqinetwork.h" + +#ifdef TUNNEL_STATISTICS +static std::vector TS_tunnel_length(8,0) ; +static std::map > > TS_request_time_stamps ; +static std::map > TS_request_bounces ; +void TS_dumpState() ; +#endif + +// These number may be quite important. I setup them with sensible values, but +// an in-depth test would be better to get an idea of what the ideal values +// could ever be. +// +// update of 14-03-11: +// - I raised the cache time for tunnel requests. This avoids inconsistencies such as: +// * tunnel requests bouncing back while the original request is not in the cache anymore +// * special case of this for own file transfer: an outgoing tunnel is built with no end. +// - changed tunnel speed estimate time lapse to 5 secs. Too small a value favors high variations. +// - the max number of tunnel requests per second is now enforced. It was before defaulting to +// QUEUE_LENGTH*0.1, meaning 0.5. I set it to 0.1. +// +static const time_t TUNNEL_REQUESTS_LIFE_TIME = 60 ; /// life time for tunnel requests in the cache. +static const time_t SEARCH_REQUESTS_LIFE_TIME = 60 ; /// life time for search requests in the cache +static const time_t REGULAR_TUNNEL_DIGGING_TIME = 300 ; /// maximum interval between two tunnel digging campaigns. +static const time_t MAXIMUM_TUNNEL_IDLE_TIME = 60 ; /// maximum life time of an unused tunnel. +static const time_t EMPTY_TUNNELS_DIGGING_TIME = 50 ; /// look into tunnels regularly every 50 sec. +static const time_t TUNNEL_SPEED_ESTIMATE_LAPSE = 5 ; /// estimate tunnel speed every 5 seconds +static const time_t TUNNEL_CLEANING_LAPS_TIME = 10 ; /// clean tunnels every 10 secs +static const uint32_t MAX_TUNNEL_REQS_PER_SECOND= 1 ; /// maximum number of tunnel requests issued per second. Was 0.5 before +static const uint32_t MAX_ALLOWED_SR_IN_CACHE = 120 ; /// maximum number of search requests allowed in cache. That makes 2 per sec. + +p3turtle::p3turtle(p3ConnectMgr *cm,ftServer *fs) + :p3Service(RS_SERVICE_TYPE_TURTLE), p3Config(CONFIG_TYPE_TURTLE), mConnMgr(cm) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + _ft_server = fs ; + _ft_controller = fs->getController() ; + + _random_bias = RSRandom::random_u32() ; + + addSerialType(new RsTurtleSerialiser()); + + _last_clean_time = 0 ; + _last_tunnel_management_time = 0 ; + _last_tunnel_campaign_time = 0 ; + _last_tunnel_speed_estimate_time = 0 ; + + _traffic_info.reset() ; + _sharing_strategy = SHARE_ENTIRE_NETWORK ; +} + +int p3turtle::tick() +{ + // Handle tunnel trafic + // + handleIncoming(); // handle incoming packets + + time_t now = time(NULL) ; + +#ifdef TUNNEL_STATISTICS + static time_t last_now = now ; + if(now - last_now > 2) + std::cerr << "******************* WARNING: now - last_now = " << now - last_now << std::endl; + last_now = now ; +#endif + + bool should_autowash,should_estimatespeed ; + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + should_autowash = now > TUNNEL_CLEANING_LAPS_TIME+_last_clean_time ; + should_estimatespeed = now >= TUNNEL_SPEED_ESTIMATE_LAPSE + _last_tunnel_speed_estimate_time ; + } + + // Tunnel management: + // - we digg new tunnels at least every 5 min (300 sec). + // - we digg new tunnels each time a new peer connects + // - we digg new tunnels each time a new hash is asked for + // + if(now >= _last_tunnel_management_time+1) // call every second + { +#ifdef P3TURTLE_DEBUG + std::cerr << "Calling tunnel management." << std::endl ; +#endif + manageTunnels() ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + _last_tunnel_management_time = now ; + + // Update traffic statistics. The constants are important: they allow a smooth variation of the + // traffic speed, which is used to moderate tunnel requests statistics. + // + _traffic_info = _traffic_info*0.9 + _traffic_info_buffer*0.1 ; + _traffic_info_buffer.reset() ; + } + } + + // Clean every 10 sec. + // + if(should_autowash) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "Calling autowash." << std::endl ; +#endif + autoWash() ; // clean old/unused tunnels and file hashes, as well as search and tunnel requests. + + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + _last_clean_time = now ; + } + + if(should_estimatespeed) + { + estimateTunnelSpeeds() ; + + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + _last_tunnel_speed_estimate_time = now ; + } + +#ifdef TUNNEL_STATISTICS + // Dump state for debugging, every 20 sec. + // + static time_t TS_last_dump = time(NULL) ; + + if(now > 20+TS_last_dump) + { + TS_last_dump = now ; + TS_dumpState() ; + } +#endif + +#ifdef P3TURTLE_DEBUG + // Dump state for debugging, every 20 sec. + // + static time_t last_dump = time(NULL) ; + + if(now > 20+last_dump) + { + last_dump = now ; + dumpState() ; + } +#endif + return 0 ; +} + +// -----------------------------------------------------------------------------------// +// ------------------------------ Tunnel maintenance. ------------------------------ // +// -----------------------------------------------------------------------------------// +// + +#ifdef TO_REMOVE +// This method handles peer connexion/deconnexion +// If A connects, new tunnels should be initiated from A +// If A disconnects, the tunnels passed through A should be closed. +// +void p3turtle::statusChange(const std::list &plist) // derived from pqiMonitor +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // We actually do not shut down tunnels when peers get down: Tunnels that + // are not working properly get automatically removed after some time. + + // save the list of active peers. This is useful for notifying the ftContoller + _online_peers = plist ; + + std::cerr << "p3turtle: status change triggered. Saving list of " << plist.size() << " peers." << std::endl ; + + /* if any have switched to 'connected' then we force digging new tunnels */ + + for(std::list::const_iterator pit = plist.begin(); pit != plist.end(); pit++) + if ((pit->state & RS_PEER_S_FRIEND) && (pit->actions & RS_PEER_CONNECTED)) + _force_digg_new_tunnels = true ; +} +#endif + +// adds a virtual peer to the list that is communicated ot ftController. +// +void p3turtle::locked_addDistantPeer(const TurtleFileHash&,TurtleTunnelId tid) +{ + char buff[400] ; + sprintf(buff,"Anonymous F2F tunnel %08x",tid) ; + + _virtual_peers[TurtleVirtualPeerId(buff)] = tid ; +#ifdef P3TURTLE_DEBUG + assert(_local_tunnels.find(tid)!=_local_tunnels.end()) ; +#endif + _local_tunnels[tid].vpid = TurtleVirtualPeerId(buff) ; +} + +void p3turtle::getVirtualPeersList(std::list& list) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + list.clear() ; + + for(std::map::const_iterator it(_virtual_peers.begin());it!=_virtual_peers.end();++it) + { + pqipeer vp ; + vp.id = it->first ; + vp.name = "Virtual (distant) peer" ; + vp.state = RS_PEER_S_CONNECTED ; + vp.actions = RS_PEER_CONNECTED ; + list.push_back(vp) ; + } +} + +// This method handles digging new tunnels as needed. +// New tunnels are dug when: +// - new peers have connected. The resulting tunnels should be checked against doubling. +// - new hashes are submitted for handling. +// +class hashPairComparator +{ + public: + virtual bool operator()(const std::pair& p1,const std::pair& p2) const + { + return p1.second < p2.second ; + } +}; +void p3turtle::manageTunnels() +{ + // Collect hashes for which tunnel digging is necessary / recommended. Hashes get in the list for two reasons: + // - the hash has no tunnel -> tunnel digging every EMPTY_TUNNELS_DIGGING_TIME seconds + // - the hash hasn't been tunneled for more than REGULAR_TUNNEL_DIGGING_TIME seconds, even if downloading. + // + // Candidate hashes are sorted, by olderness. The older gets tunneled first. At most MAX_TUNNEL_REQS_PER_SECOND are + // treated at once, as this method is called every second. + // Note: Because REGULAR_TUNNEL_DIGGING_TIME is larger than EMPTY_TUNNELS_DIGGING_TIME, files being downloaded get + // re-tunneled in priority. As this happens less, they don't obliterate tunneling for files that have no tunnels yet. + + std::vector > hashes_to_digg ; + time_t now = time(NULL) ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // digg new tunnels if no tunnels are available and force digg new tunnels at regular (large) interval + // + for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) + if( (it->second.tunnels.empty() && now >= it->second.last_digg_time+EMPTY_TUNNELS_DIGGING_TIME) || now >= it->second.last_digg_time + REGULAR_TUNNEL_DIGGING_TIME) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "pushed hash " << it->first << ", for digging. Old = " << now - it->second.last_digg_time << std::endl; +#endif + hashes_to_digg.push_back(std::pair(it->first,it->second.last_digg_time)) ; + } + } +#ifdef TUNNEL_STATISTICS + std::cerr << hashes_to_digg.size() << " hashes candidate for tunnel digging." << std::endl; +#endif + + std::sort(hashes_to_digg.begin(),hashes_to_digg.end(),hashPairComparator()) ; + + for(unsigned int i=0;i::iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) + { + TurtleTunnel& tunnel(it->second) ; + + float speed_estimate = tunnel.transfered_bytes / float(TUNNEL_SPEED_ESTIMATE_LAPSE) ; + tunnel.speed_Bps = 0.75*tunnel.speed_Bps + 0.25*speed_estimate ; + tunnel.transfered_bytes = 0 ; + } +} + +void p3turtle::autoWash() +{ +#ifdef P3TURTLE_DEBUG + std::cerr << " In autowash." << std::endl ; +#endif + // Remove hashes that are marked as such. + // + + std::vector > peers_to_remove ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + for(unsigned int i=0;i<_hashes_to_remove.size();++i) + { + std::map::iterator it(_incoming_file_hashes.find(_hashes_to_remove[i])) ; + + if(it == _incoming_file_hashes.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: asked to stop monitoring file hash " << _hashes_to_remove[i] << ", but this hash is actually not handled by the turtle router." << std::endl ; +#endif + continue ; + } + + // copy the list of tunnels to remove. +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: stopping monitoring for file hash " << _hashes_to_remove[i] << ", and closing " << it->second.tunnels.size() << " tunnels (" ; +#endif + std::vector tunnels_to_remove ; + + for(std::vector::const_iterator it2(it->second.tunnels.begin());it2!=it->second.tunnels.end();++it2) + { +#ifdef P3TURTLE_DEBUG + std::cerr << (void*)*it2 << "," ; +#endif + tunnels_to_remove.push_back(*it2) ; + } +#ifdef P3TURTLE_DEBUG + std::cerr << ")" << std::endl ; +#endif + for(unsigned int k=0;k::iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();) + if(now > (time_t)(it->second.time_stamp + SEARCH_REQUESTS_LIFE_TIME)) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " removed search request " << (void *)it->first << ", timeout." << std::endl ; +#endif + std::map::iterator tmp(it) ; + ++tmp ; + _search_requests_origins.erase(it) ; + it = tmp ; + } + else + ++it; + } + + // Tunnel requests + // + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + for(std::map::iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();) + if(now > (time_t)(it->second.time_stamp + TUNNEL_REQUESTS_LIFE_TIME)) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " removed tunnel request " << (void *)it->first << ", timeout." << std::endl ; +#endif + std::map::iterator tmp(it) ; + ++tmp ; + _tunnel_requests_origins.erase(it) ; + it = tmp ; + } + else + ++it ; + } + + // Tunnels. + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + std::vector tunnels_to_close ; + + for(std::map::iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) + if(now > (time_t)(it->second.time_stamp + MAXIMUM_TUNNEL_IDLE_TIME)) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " removing tunnel " << (void *)it->first << ": timeout." << std::endl ; +#endif + tunnels_to_close.push_back(it->first) ; + } + for(unsigned int i=0;iremoveFileSource(peers_to_remove[i].first,peers_to_remove[i].second) ; + +} + +void p3turtle::locked_closeTunnel(TurtleTunnelId tid,std::vector >& sources_to_remove) +{ + // This is closing a given tunnel, removing it from file sources, and from the list of tunnels of its + // corresponding file hash. In the original turtle4privacy paradigm, they also send back and forward + // tunnel closing commands. In our case, this is not necessary, because if a tunnel is closed somewhere, its + // source is not going to be used and the tunnel will eventually disappear. + // + std::map::iterator it(_local_tunnels.find(tid)) ; + + if(it == _local_tunnels.end()) + { + std::cerr << "p3turtle: was asked to close tunnel " << (void*)tid << ", which actually doesn't exist." << std::endl ; + return ; + } +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: Closing tunnel " << (void*)tid << std::endl ; +#endif + + if(it->second.local_src == mConnMgr->getOwnId()) // this is a starting tunnel. We thus remove + // - the virtual peer from the vpid list + // - the tunnel id from the file hash + // - the virtual peer from the file sources in the file transfer controller. + { + TurtleTunnelId tid = it->first ; + TurtleVirtualPeerId vpid = it->second.vpid ; + TurtleFileHash hash = it->second.hash ; + +#ifdef P3TURTLE_DEBUG + std::cerr << " Tunnel is a starting point. Also removing:" << std::endl ; + std::cerr << " Virtual Peer Id " << vpid << std::endl ; + std::cerr << " Associated file source." << std::endl ; +#endif + sources_to_remove.push_back(std::pair(hash,vpid)) ; + + // Let's be cautious. Normally we should never be here without consistent information, + // but still, this happens, rarely. + // + if(_virtual_peers.find(vpid) != _virtual_peers.end()) + _virtual_peers.erase(_virtual_peers.find(vpid)) ; + + std::map::iterator it(_incoming_file_hashes.find(hash)) ; + + if(it != _incoming_file_hashes.end()) + { + std::vector& tunnels(it->second.tunnels) ; + + // Remove tunnel id from it's corresponding hash. For security we + // go through the whole tab, although the tunnel id should only be listed once + // in this tab. + // + for(unsigned int i=0;isecond.local_dst == mConnMgr->getOwnId()) // This is a ending tunnel. We also remove the virtual peer id + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Tunnel is a ending point. Also removing associated outgoing hash." ; +#endif + std::map::iterator itHash = _outgoing_file_hashes.find(it->second.hash); + if(itHash != _outgoing_file_hashes.end()) + _outgoing_file_hashes.erase(itHash) ; + } + + _local_tunnels.erase(it) ; +} + +void p3turtle::stopMonitoringFileTunnels(const std::string& hash) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: Marking hash " << hash << " to be removed during autowash." << std::endl ; +#endif + // We don't do the deletion in this process, because it can cause a race with tunnel management. + _hashes_to_remove.push_back(hash) ; +} + +// -----------------------------------------------------------------------------------// +// -------------------------------- Config functions ------------------------------ // +// -----------------------------------------------------------------------------------// +// +RsSerialiser *p3turtle::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser ; + rss->addSerialType(new RsTurtleSerialiser) ; + + return rss ; +} + +bool p3turtle::saveList(bool& cleanup, std::list&) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: saving list..." << std::endl ; +#endif + cleanup = true ; + ; +#ifdef TO_REMOVE + RsTurtleSearchResultItem *item = new RsTurtleSearchResultItem ; + item->PeerId("") ; + + for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) + { + TurtleFileInfo finfo ; + finfo.name = it->second.name ; + finfo.size = it->second.size ; + finfo.hash = it->first ; +#ifdef P3TURTLE_DEBUG + std::cerr << " Saving item " << finfo.name << ", " << finfo.hash << ", " << finfo.size << std::endl ; +#endif + + item->result.push_back(finfo) ; + } + lst.push_back(item) ; +#endif + return true ; +} + +#ifdef TO_REMOVE +bool p3turtle::loadList(std::list load) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: loading list..." << std::endl ; +#endif + for(std::list::const_iterator it(load.begin());it!=load.end();++it) + { + RsTurtleSearchResultItem *item = dynamic_cast(*it) ; + +#ifdef P3TURTLE_DEBUG + assert(item!=NULL) ; +#endif + if(item == NULL) + continue ; + + for(std::list::const_iterator it2(item->result.begin());it2!=item->result.end();++it2) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Restarting tunneling for: " << it2->hash << " " << it2->size << " " << it2->name << std::endl ; +#endif + monitorFileTunnels(it2->name,it2->hash,it2->size) ; + } + delete item ; + } + return true ; +} +#endif + + +// -----------------------------------------------------------------------------------// +// -------------------------------- Helper functions ------------------------------ // +// -----------------------------------------------------------------------------------// +// +uint32_t p3turtle::generateRandomRequestId() +{ + return RSRandom::random_u32() ; +} + +uint32_t p3turtle::generatePersonalFilePrint(const TurtleFileHash& hash,bool b) +{ + // whatever cooking from the file hash and OwnId that cannot be recovered. + // The only important thing is that the saem couple (hash,SSL id) produces the same tunnel + // id. The result uses a boolean to allow generating non symmetric tunnel ids. + + std::string buff(hash + mConnMgr->getOwnId()) ; + uint32_t res = 0 ; + uint32_t decal = 0 ; + + for(int i=0;i<(int)buff.length();++i) + { + res += 7*buff[i] + decal ; + + if(b) + decal = decal*44497+15641+(res%86243) ; + else + decal = decal*86243+15649+(res%44497) ; + } + + return res ; +} +// -----------------------------------------------------------------------------------// +// -------------------------------- Global routing. -------------------------------- // +// -----------------------------------------------------------------------------------// +// +int p3turtle::handleIncoming() +{ + int nhandled = 0; + // While messages read + // + RsItem *item = NULL; + + while(NULL != (item = recvItem())) + { + nhandled++; + + RsTurtleGenericTunnelItem *gti = dynamic_cast(item) ; + + if(gti != NULL) + routeGenericTunnelItem(gti) ; /// Generic packets, that travel through established tunnels. + else /// These packets should be destroyed by the client. + { + /// Special packets that require specific treatment, because tunnels do not exist for these packets. + /// These packets are destroyed here, after treatment. + // + switch(item->PacketSubType()) + { + case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST: + case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST: handleSearchRequest(dynamic_cast(item)) ; + break ; + + case RS_TURTLE_SUBTYPE_SEARCH_RESULT : handleSearchResult(dynamic_cast(item)) ; + break ; + + case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : handleTunnelRequest(dynamic_cast(item)) ; + break ; + + case RS_TURTLE_SUBTYPE_TUNNEL_OK : handleTunnelResult(dynamic_cast(item)) ; + break ; + default: + std::cerr << "p3turtle::handleIncoming: Unknown packet subtype " << item->PacketSubType() << std::endl ; + } + delete item; + } + } + + return nhandled; +} + +// -----------------------------------------------------------------------------------// +// -------------------------------- Search handling. ------------------------------- // +// -----------------------------------------------------------------------------------// +// +void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + // take a look at the item: + // - If the item destimation is + +#ifdef P3TURTLE_DEBUG + std::cerr << "Received search request from peer " << item->PeerId() << ": " << std::endl ; + item->print(std::cerr,0) ; +#endif + if(_search_requests_origins.size() > MAX_ALLOWED_SR_IN_CACHE) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Dropping, because the search request cache is full." << std::endl ; +#endif + std::cerr << " More than " << MAX_ALLOWED_SR_IN_CACHE << " search request in cache. A peer is probably trying to flood your network See the depth charts to find him." << std::endl; + return ; + } + + // If the item contains an already handled search request, give up. This + // happens when the same search request gets relayed by different peers + // + if(_search_requests_origins.find(item->request_id) != _search_requests_origins.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " This is a bouncing request. Ignoring and deleting it." << std::endl ; +#endif + return ; + } + + // This is a new request. Let's add it to the request map, and forward it to + // open peers. + + TurtleRequestInfo& req( _search_requests_origins[item->request_id] ) ; + req.origin = item->PeerId() ; + req.time_stamp = time(NULL) ; + req.depth = item->depth ; + + // If it's not for us, perform a local search. If something found, forward the search result back. + + if(item->PeerId() != mConnMgr->getOwnId()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Request not from us. Performing local search" << std::endl ; +#endif + if(_sharing_strategy != SHARE_FRIENDS_ONLY || item->depth < 2) + { + std::list result ; + + item->performLocalSearch(result) ; + + RsTurtleSearchResultItem *res_item = NULL ; + uint32_t item_size = 0 ; + +#ifdef P3TURTLE_DEBUG + if(!result.empty()) + std::cerr << " " << result.size() << " matches found. Sending back to origin (" << item->PeerId() << ")." << std::endl ; +#endif + while(!result.empty()) + { + // Let's chop search results items into several chunks of finite size to avoid exceeding streamer's capacity. + // + static const uint32_t RSTURTLE_MAX_SEARCH_RESPONSE_SIZE = 10000 ; + + if(res_item == NULL) + { + res_item = new RsTurtleSearchResultItem ; + item_size = 0 ; + + res_item->depth = 0 ; + res_item->request_id = item->request_id ; + res_item->PeerId(item->PeerId()) ; // send back to the same guy + } + res_item->result.push_back(result.front()) ; + + item_size += 8 /* size */ + result.front().hash.size() + result.front().name.size() ; + result.pop_front() ; + + if(item_size > RSTURTLE_MAX_SEARCH_RESPONSE_SIZE || result.empty()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Sending back chunk of size " << item_size << ", for " << res_item->result.size() << " elements." << std::endl ; +#endif + sendItem(res_item) ; + res_item = NULL ; + } + } + } +#ifdef P3TURTLE_DEBUG + else + std::cerr << " Rejecting local search because strategy is FRIENDS_ONLY and item depth=" << item->depth << std::endl ; +#endif + } + + // If search depth not too large, also forward this search request to all other peers. + // + // We use a random factor on the depth test that is biased by a mix between the session id and the partial tunnel id + // to scramble a possible search-by-depth attack. + // + bool random_bypass = (item->depth == TURTLE_MAX_SEARCH_DEPTH && (((_random_bias ^ item->request_id)&0x7)==2)) ; + + if(item->depth < TURTLE_MAX_SEARCH_DEPTH || random_bypass) + { + std::list onlineIds ; + mConnMgr->getOnlineList(onlineIds); +#ifdef P3TURTLE_DEBUG + std::cerr << " Looking for online peers" << std::endl ; +#endif + + for(std::list::const_iterator it(onlineIds.begin());it!=onlineIds.end();++it) + if(*it != item->PeerId()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Forwarding request to peer = " << *it << std::endl ; +#endif + // Copy current item and modify it. + RsTurtleSearchRequestItem *fwd_item = item->clone() ; + + ++(fwd_item->depth) ; // increase search depth + fwd_item->PeerId(*it) ; + + sendItem(fwd_item) ; + } + } +#ifdef P3TURTLE_DEBUG + else + std::cout << " Dropping this item, as search depth is " << item->depth << std::endl ; +#endif +} + +void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + // Find who actually sent the corresponding request. + // + std::map::const_iterator it = _search_requests_origins.find(item->request_id) ; +#ifdef P3TURTLE_DEBUG + std::cerr << "Received search result:" << std::endl ; + item->print(std::cerr,0) ; +#endif + if(it == _search_requests_origins.end()) + { + // This is an error: how could we receive a search result corresponding to a search item we + // have forwarded but that it not in the list ?? + + std::cerr << __PRETTY_FUNCTION__ << ": search result has no peer direction!" << std::endl ; + return ; + } + + // Is this result's target actually ours ? + + ++(item->depth) ; // increase depth + + if(it->second.origin == mConnMgr->getOwnId()) + returnSearchResult(item) ; // Yes, so send upward. + else + { // Nope, so forward it back. +#ifdef P3TURTLE_DEBUG + std::cerr << " Forwarding result back to " << it->second.origin << std::endl; +#endif + RsTurtleSearchResultItem *fwd_item = new RsTurtleSearchResultItem(*item) ; // copy the item + + // Normally here, we should setup the forward adress, so that the owner's + // of the files found can be further reached by a tunnel. + + fwd_item->PeerId(it->second.origin) ; + fwd_item->depth = 2 + (rand() % 256) ; // obfuscate the depth for non immediate friends. + + sendItem(fwd_item) ; + } +} + +// -----------------------------------------------------------------------------------// +// --------------------------------- File Transfer. -------------------------------- // +// -----------------------------------------------------------------------------------// + +// Routing of turtle tunnel items in a generic manner. Most tunnel packets will use this function, except packets designed for +// contructing the tunnels and searching, namely TurtleSearchRequests/Results and OpenTunnel/TunnelOkItems +// +void p3turtle::routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "p3Turtle: treating generic tunnel item:" << std::endl ; + item->print(std::cerr,1) ; +#endif + RsTurtleGenericTunnelItem::Direction direction = item->travelingDirection() ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // look for the tunnel id. + // + std::map::iterator it(_local_tunnels.find(item->tunnelId())) ; + + if(it == _local_tunnels.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: got file map with unknown tunnel id " << (void*)item->tunnelId() << std::endl ; +#endif + delete item; + return ; + } + + TurtleTunnel& tunnel(it->second) ; + + // Only file data transfer updates tunnels time_stamp field, to avoid maintaining tunnel that are incomplete. + if(item->shouldStampTunnel()) + tunnel.time_stamp = time(NULL) ; + + tunnel.transfered_bytes += static_cast(item)->serial_size() ; + + // Let's figure out whether this packet is for us or not. + + if(direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT && tunnel.local_src != mConnMgr->getOwnId()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Forwarding generic item to peer " << tunnel.local_src << std::endl ; +#endif + item->PeerId(tunnel.local_src) ; + + _traffic_info_buffer.unknown_updn_Bps += static_cast(item)->serial_size() ; + + sendItem(item) ; + return ; + } + + if(direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER && tunnel.local_dst != mConnMgr->getOwnId()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Forwarding generic item to peer " << tunnel.local_dst << std::endl ; +#endif + item->PeerId(tunnel.local_dst) ; + + _traffic_info_buffer.unknown_updn_Bps += static_cast(item)->serial_size() ; + + sendItem(item) ; + return ; + } + } + + // The packet was not forwarded, so it is for us. Let's treat it. + // This is done off-mutex, to avoid various deadlocks + // + + switch(item->PacketSubType()) + { + case RS_TURTLE_SUBTYPE_FILE_REQUEST: handleRecvFileRequest(dynamic_cast(item)) ; + break ; + + case RS_TURTLE_SUBTYPE_FILE_DATA : handleRecvFileData(dynamic_cast(item)) ; + break ; + + case RS_TURTLE_SUBTYPE_FILE_MAP : handleRecvFileMap(dynamic_cast(item)) ; + break ; + + case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST: handleRecvFileMapRequest(dynamic_cast(item)) ; + break ; + + case RS_TURTLE_SUBTYPE_FILE_CRC : handleRecvFileCRC32Map(dynamic_cast(item)) ; + break ; + + case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST: handleRecvFileCRC32MapRequest(dynamic_cast(item)) ; + break ; + default: + std::cerr << "WARNING: Unknown packet type received: id=" << (void*)(item->PacketSubType()) << ". Is somebody trying to poison you ?" << std::endl ; +#ifdef P3TURTLE_DEBUG + exit(-1) ; +#endif + } + + delete item ; +} + +void p3turtle::handleRecvFileRequest(RsTurtleFileRequestItem *item) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "p3Turtle: received file request item:" << std::endl ; + item->print(std::cerr,1) ; +#endif + // This is a new request. Let's add it to the request map, and forward it to + // open peers. + + TurtleVirtualPeerId vpid ; + uint64_t size ; + TurtleFileHash hash ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; + + if(it2 == _local_tunnels.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: got file request with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; +#endif + return ; + } + + TurtleTunnel& tunnel(it2->second) ; + std::map::const_iterator it(_outgoing_file_hashes.find(tunnel.hash)) ; +#ifdef P3TURTLE_DEBUG + assert(!tunnel.hash.empty()) ; + assert(it != _outgoing_file_hashes.end()) ; + + std::cerr << " This is an endpoint for this file request." << std::endl ; + std::cerr << " Forwarding data request to the multiplexer." << std::endl ; + std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; +#endif + size = it->second.size ; + vpid = tunnel.vpid ; + hash = tunnel.hash ; + } + + // This call is voluntarily off-mutex gards because it can cause cross mutex locks with the multiplexer. + // (Yeah, this bug was a shity hard one to catch). + // + _ft_server->getMultiplexer()->recvDataRequest(vpid,hash,size,item->chunk_offset,item->chunk_size) ; +} + +void p3turtle::handleRecvFileData(RsTurtleFileDataItem *item) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "p3Turtle: received file data item:" << std::endl ; + item->print(std::cerr,1) ; +#endif + TurtleVirtualPeerId vpid ; + uint64_t size ; + TurtleFileHash hash ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + _traffic_info_buffer.data_dn_Bps += static_cast(item)->serial_size() ; + + std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; + + if(it2 == _local_tunnels.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: got file data with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; +#endif + return ; + } + + TurtleTunnel& tunnel(it2->second) ; + std::map::iterator it( _incoming_file_hashes.find(tunnel.hash) ) ; +#ifdef P3TURTLE_DEBUG + assert(!tunnel.hash.empty()) ; +#endif + if(it==_incoming_file_hashes.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "No tunnel for incoming data. Maybe the tunnel is being closed." << std::endl ; +#endif + return ; + } + + const TurtleFileHashInfo& hash_info(it->second) ; +#ifdef P3TURTLE_DEBUG + std::cerr << " This is an endpoint for this data chunk." << std::endl ; + std::cerr << " Forwarding data to the multiplexer." << std::endl ; + std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; +#endif + //_ft_server->getMultiplexer()->recvData(tunnel.vpid,tunnel.hash,hash_info.size,item->chunk_offset,item->chunk_size,item->chunk_data) ; + vpid = tunnel.vpid ; + hash = tunnel.hash ; + size = hash_info.size ; + + // also update the hash time stamp to show that it's actually being downloaded. + //it->second.time_stamp = time(NULL) ; + } + + _ft_server->getMultiplexer()->recvData(vpid,hash,size,item->chunk_offset,item->chunk_size,item->chunk_data) ; + item->chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted + // down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData +} + +void p3turtle::handleRecvFileMapRequest(RsTurtleFileMapRequestItem *item) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "p3Turtle: received file Map item:" << std::endl ; + item->print(std::cerr,1) ; +#endif + std::string hash,vpid ; + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; + + if(it2 == _local_tunnels.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: got file data with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; +#endif + return ; + } + + TurtleTunnel& tunnel(it2->second) ; +#ifdef P3TURTLE_DEBUG + assert(!tunnel.hash.empty()) ; + + std::cerr << " This is an endpoint for this file map request." << std::endl ; + std::cerr << " Forwarding data to the multiplexer." << std::endl ; + std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; +#endif + // we should check that there is no backward call to the turtle router! + // + hash = tunnel.hash ; + vpid = tunnel.vpid ; + } + + _ft_server->getMultiplexer()->recvChunkMapRequest(vpid,hash,item->direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; +} + +void p3turtle::handleRecvFileMap(RsTurtleFileMapItem *item) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "p3Turtle: received file Map item:" << std::endl ; + item->print(std::cerr,1) ; +#endif + std::string hash,vpid ; + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; + + if(it2 == _local_tunnels.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: got file data with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; +#endif + return ; + } + + TurtleTunnel& tunnel(it2->second) ; + +#ifdef P3TURTLE_DEBUG + assert(!tunnel.hash.empty()) ; + + std::cerr << " This is an endpoint for this file map." << std::endl ; + std::cerr << " Forwarding data to the multiplexer." << std::endl ; + std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; +#endif + // We should check that there is no backward call to the turtle router! + // + vpid = tunnel.vpid ; + hash = tunnel.hash ; + } + _ft_server->getMultiplexer()->recvChunkMap(vpid,hash,item->compressed_map,item->direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; +} + +void p3turtle::handleRecvFileCRC32MapRequest(RsTurtleFileCrcRequestItem *item) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "p3Turtle: received file CRC32 Map Request item:" << std::endl ; + item->print(std::cerr,1) ; +#endif + std::string hash,vpid ; + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; + + if(it2 == _local_tunnels.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: got file data with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; +#endif + return ; + } + + TurtleTunnel& tunnel(it2->second) ; +#ifdef P3TURTLE_DEBUG + assert(!tunnel.hash.empty()) ; + + std::cerr << " This is an endpoint for this file crc request." << std::endl ; + std::cerr << " Forwarding data to the multiplexer." << std::endl ; + std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; +#endif + // we should check that there is no backward call to the turtle router! + // + hash = tunnel.hash ; + vpid = tunnel.vpid ; + } + + _ft_server->getMultiplexer()->recvCRC32MapRequest(vpid,hash) ; +} + +void p3turtle::handleRecvFileCRC32Map(RsTurtleFileCrcItem *item) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "p3Turtle: received file CRC32 Map item:" << std::endl ; + item->print(std::cerr,1) ; +#endif + std::string hash,vpid ; + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; + + if(it2 == _local_tunnels.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: got file CRC32 map with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; +#endif + return ; + } + + TurtleTunnel& tunnel(it2->second) ; + +#ifdef P3TURTLE_DEBUG + assert(!tunnel.hash.empty()) ; + + std::cerr << " This is an endpoint for this file map." << std::endl ; + std::cerr << " Forwarding data to the multiplexer." << std::endl ; + std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; +#endif + // We should check that there is no backward call to the turtle router! + // + vpid = tunnel.vpid ; + hash = tunnel.hash ; + } + _ft_server->getMultiplexer()->recvCRC32Map(vpid,hash,item->crc_map) ; +} +// Send a data request into the correct tunnel for the given file hash +void p3turtle::sendDataRequest(const std::string& peerId, const std::string& , uint64_t, uint64_t offset, uint32_t chunksize) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // get the proper tunnel for this file hash and peer id. + std::map::const_iterator it(_virtual_peers.find(peerId)) ; + + if(it == _virtual_peers.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle::senddataRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; +#endif + return ; + } + TurtleTunnelId tunnel_id = it->second ; + TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; + +#ifdef P3TURTLE_DEBUG + assert(hash == tunnel.hash) ; +#endif + RsTurtleFileRequestItem *item = new RsTurtleFileRequestItem ; + item->tunnel_id = tunnel_id ; // we should randomly select a tunnel, or something more clever. + item->chunk_offset = offset ; + item->chunk_size = chunksize ; + item->PeerId(tunnel.local_dst) ; + +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: sending file req (chunksize=" << item->chunk_size << ", offset=" << item->chunk_offset << ", hash=0x" << hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << tunnel.local_dst << std::endl ; +#endif + sendItem(item) ; +} + +// Send file data into the correct tunnel for the given file hash +void p3turtle::sendFileData(const std::string& peerId, const std::string& , uint64_t, uint64_t offset, uint32_t chunksize, void *data) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // get the proper tunnel for this file hash and peer id. + std::map::const_iterator it(_virtual_peers.find(peerId)) ; + + if(it == _virtual_peers.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle::sendData: cannot find virtual peer " << peerId << " in VP list." << std::endl ; +#endif + return ; + } + TurtleTunnelId tunnel_id = it->second ; + TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; + + tunnel.time_stamp = time(NULL) ; +#ifdef P3TURTLE_DEBUG + assert(hash == tunnel.hash) ; +#endif + RsTurtleFileDataItem *item = new RsTurtleFileDataItem ; + item->tunnel_id = tunnel_id ; + item->chunk_offset = offset ; + item->chunk_size = chunksize ; + item->chunk_data = malloc(chunksize) ; + + tunnel.transfered_bytes += static_cast(item)->serial_size(); + + if(item->chunk_data == NULL) + { + std::cerr << "p3turtle: Warning: failed malloc of " << chunksize << " bytes for sending data packet." << std::endl ; + delete item; + return ; + } + memcpy(item->chunk_data,(void*)((uint8_t*)data),chunksize) ; + item->PeerId(tunnel.local_src) ; + +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: sending file data (chunksize=" << item->chunk_size << ", offset=" << item->chunk_offset << ", hash=0x" << hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << tunnel.local_src << std::endl ; +#endif + _traffic_info_buffer.data_up_Bps += static_cast(item)->serial_size() ; + + sendItem(item) ; +} + +void p3turtle::sendChunkMapRequest(const std::string& peerId,const std::string& ,bool is_client) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // get the proper tunnel for this file hash and peer id. + std::map::const_iterator it(_virtual_peers.find(peerId)) ; + + if(it == _virtual_peers.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle::senddataRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; +#endif + return ; + } + TurtleTunnelId tunnel_id = it->second ; + TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; + +#ifdef P3TURTLE_DEBUG + assert(hash == tunnel.hash) ; +#endif + RsTurtleFileMapRequestItem *item = new RsTurtleFileMapRequestItem ; + item->tunnel_id = tunnel_id ; + + std::string ownid = mConnMgr->getOwnId() ; + + if(tunnel.local_src == ownid) + { + assert(!is_client) ; + item->direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ; + item->PeerId(tunnel.local_dst) ; + } + else if(tunnel.local_dst == ownid) + { + assert(is_client) ; + item->direction = RsTurtleGenericTunnelItem::DIRECTION_CLIENT ; + item->PeerId(tunnel.local_src) ; + } + else + std::cerr << "p3turtle::sendChunkMapRequest: consistency error!" << std::endl ; + +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: sending chunk map req to peer " << peerId << ", hash=0x" << hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; +#endif + sendItem(item) ; +} + +void p3turtle::sendChunkMap(const std::string& peerId,const std::string& ,const CompressedChunkMap& cmap,bool is_client) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // get the proper tunnel for this file hash and peer id. + std::map::const_iterator it(_virtual_peers.find(peerId)) ; + + if(it == _virtual_peers.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle::senddataRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; +#endif + return ; + } + TurtleTunnelId tunnel_id = it->second ; + TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; + +#ifdef P3TURTLE_DEBUG + assert(hash == tunnel.hash) ; +#endif + RsTurtleFileMapItem *item = new RsTurtleFileMapItem ; + item->tunnel_id = tunnel_id ; + item->compressed_map = cmap ; + + std::string ownid = mConnMgr->getOwnId() ; + + if(tunnel.local_src == ownid) + { + assert(!is_client) ; + item->direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ; + item->PeerId(tunnel.local_dst) ; + } + else if(tunnel.local_dst == ownid) + { + assert(is_client) ; + item->direction = RsTurtleGenericTunnelItem::DIRECTION_CLIENT ; + item->PeerId(tunnel.local_src) ; + } + else + std::cerr << "p3turtle::sendChunkMap: consistency error!" << std::endl ; + +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: sending chunk map to peer " << peerId << ", hash=0x" << hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; +#endif + sendItem(item) ; +} + +void p3turtle::sendCRC32MapRequest(const std::string& peerId,const std::string& ) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // get the proper tunnel for this file hash and peer id. + std::map::const_iterator it(_virtual_peers.find(peerId)) ; + + if(it == _virtual_peers.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle::sendCRC32MapRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; +#endif + return ; + } + TurtleTunnelId tunnel_id = it->second ; + TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; + +#ifdef P3TURTLE_DEBUG + assert(hash == tunnel.hash) ; +#endif + RsTurtleFileCrcRequestItem *item = new RsTurtleFileCrcRequestItem; + item->tunnel_id = tunnel_id ; +// item->crc_map = cmap ; + item->PeerId(tunnel.local_dst) ; + +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: sending CRC32 map request to peer " << peerId << ", hash=0x" << hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; +#endif + sendItem(item) ; +} +void p3turtle::sendCRC32Map(const std::string& peerId,const std::string& ,const CRC32Map& cmap) +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // get the proper tunnel for this file hash and peer id. + std::map::const_iterator it(_virtual_peers.find(peerId)) ; + + if(it == _virtual_peers.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle::senddataRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; +#endif + return ; + } + TurtleTunnelId tunnel_id = it->second ; + TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; + +#ifdef P3TURTLE_DEBUG + assert(hash == tunnel.hash) ; +#endif + RsTurtleFileCrcItem *item = new RsTurtleFileCrcItem ; + item->tunnel_id = tunnel_id ; + item->crc_map = cmap ; + item->PeerId(tunnel.local_src) ; + +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: sending CRC32 map to peer " << peerId << ", hash=0x" << hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; +#endif + sendItem(item) ; +} + +bool p3turtle::isTurtlePeer(const std::string& peer_id) const +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + return _virtual_peers.find(peer_id) != _virtual_peers.end() ; +} + +std::string p3turtle::getTurtlePeerId(TurtleTunnelId tid) const +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + std::map::const_iterator it( _local_tunnels.find(tid) ) ; + +#ifdef P3TURTLE_DEBUG + assert(it!=_local_tunnels.end()) ; + assert(it->second.vpid != "") ; +#endif + + return it->second.vpid ; +} + +bool p3turtle::isOnline(const std::string& peer_id) const +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // we could do something mre clever here... + // + return _virtual_peers.find(peer_id) != _virtual_peers.end() ; +} + + +// -----------------------------------------------------------------------------------// +// -------------------------------- Tunnel handling. ------------------------------- // +// -----------------------------------------------------------------------------------// +// + +TurtleRequestId p3turtle::diggTunnel(const TurtleFileHash& hash) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "DiggTunnel: performing tunnel request. OwnId = " << mConnMgr->getOwnId() << " for hash=" << hash << std::endl ; +#endif + while(mConnMgr->getOwnId() == "") + { + std::cerr << "... waiting for connect manager to form own id." << std::endl ; +#ifdef WIN32 + Sleep(1000) ; +#else + sleep(1) ; +#endif + } + + TurtleRequestId id = generateRandomRequestId() ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + // Store the request id, so that we can find the hash back when we get the response. + // + _incoming_file_hashes[hash].last_request = id ; + _incoming_file_hashes[hash].last_digg_time = time(NULL) ; + } + + // Form a tunnel request packet that simulates a request from us. + // + RsTurtleOpenTunnelItem *item = new RsTurtleOpenTunnelItem ; + + item->PeerId(mConnMgr->getOwnId()) ; + item->file_hash = hash ; + item->request_id = id ; + item->partial_tunnel_id = generatePersonalFilePrint(hash,true) ; + item->depth = 0 ; + + // send it + +#ifdef TUNNEL_STATISTICS + TS_request_bounces[item->request_id].clear() ; // forces initialization +#endif + handleTunnelRequest(item) ; + delete item ; + + return id ; +} + +void p3turtle::handleTunnelRequest(RsTurtleOpenTunnelItem *item) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << "Received tunnel request from peer " << item->PeerId() << ": " << std::endl ; + item->print(std::cerr,0) ; +#endif + +#ifdef TUNNEL_STATISTICS + if(TS_request_bounces.find(item->request_id) != TS_request_bounces.end()) + TS_request_bounces[item->request_id].push_back(time(NULL)) ; +#endif + // TR forwarding. We must pay attention not to flood the network. The policy is to force a statistical behavior + // according to the followin grules: + // - below a number of tunnel request forwards per second MAX_TR_FORWARD_PER_SEC, we keep the traffic + // - if we get close to that limit, we drop long tunnels first with a probability that is larger for long tunnels + // + // Variables involved: + // distance_to_maximum : in [0,inf] is the proportion of the current up TR speed with respect to the maximum allowed speed. This is estimated + // as an average between the average number of TR over the 60 last seconds and the current TR up speed. + // corrected_distance : in [0,inf] is a squeezed version of distance: small values become very small and large values become very large. + // depth_peer_probability : basic probability of forwarding when the speed limit is reached. + // forward_probability : final probability of forwarding the packet, per peer. + // + // When the number of peers increases, the speed limit is reached faster, but the behavior per peer is the same. + // + static const float depth_peer_probability[7] = { 1.0f,0.99f,0.9f,0.7f,0.4f,0.15f,0.1f } ; + static const int TUNNEL_REQUEST_PACKET_SIZE = 50 ; + static const int MAX_TR_FORWARD_PER_SEC = 20 ; + static const int DISTANCE_SQUEEZING_POWER = 8 ; + + float forward_probability ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + _traffic_info_buffer.tr_dn_Bps += static_cast(item)->serial_size() ; + + float distance_to_maximum = std::min(100.0f,_traffic_info.tr_up_Bps/(float)(TUNNEL_REQUEST_PACKET_SIZE*MAX_TR_FORWARD_PER_SEC)) ; + float corrected_distance = pow(distance_to_maximum,DISTANCE_SQUEEZING_POWER) ; + forward_probability = pow(depth_peer_probability[std::min((uint16_t)6,item->depth)],corrected_distance) ; +#ifdef P3TURTLE_DEBUG + std::cerr << "Forwarding probability: depth=" << item->depth << ", distance to max speed=" << distance_to_maximum << ", corrected=" << corrected_distance << ", prob.=" << forward_probability << std::endl; +#endif + if(forward_probability < 0.1) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "Dropped packet!" << std::endl; +#endif + return ; + } + } + + // If the item contains an already handled tunnel request, give up. This + // happens when the same tunnel request gets relayed by different peers. We + // have to be very careful here, not to call ftController while mTurtleMtx is + // locked. + // + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it = _tunnel_requests_origins.find(item->request_id) ; + + if(it != _tunnel_requests_origins.end()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " This is a bouncing request. Ignoring and deleting item." << std::endl ; +#endif + // This trick allows to shorten tunnels, favoring tunnels of smallest length, with a bias that + // depends on a mix between a session-based constant and the tunnel partial id. This means + // that for a given couple of (source,hash), the optimisation always performs the same. + // overall, 80% tunnels are re-routed. The probability of a tunnel to have optimal length is + // thus 0.875^n where n is the length of the tunnel, supposing that it has 2 branching peers + // at each node. This makes: + // n probability + // 1 0.875 + // 2 0.76 + // 3 0.67 + // 4 0.58 + // 5 0.512 + // + // The lower the probability, the higher the anonymity level. + // + if(it->second.depth > item->depth && ((item->partial_tunnel_id ^ _random_bias)&0x7)>0) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " re-routing tunnel request. Item age difference = " << time(NULL)-it->second.time_stamp << std::endl; + std::cerr << " - old source: " << it->second.origin << ", old depth=" << it->second.depth << std::endl ; + std::cerr << " - new source: " << item->PeerId() << ", new depth=" << item->depth << std::endl ; + std::cerr << " - half id: " << (void*)it->first << std::endl ; +#endif + it->second.origin = item->PeerId() ; + it->second.depth = item->depth ; + } + return ; + } + // This is a new request. Let's add it to the request map, and forward + // it to open peers, while the mutex is locked, so no-one can trigger the + // lock before the data is consistent. + + TurtleRequestInfo& req( _tunnel_requests_origins[item->request_id] ) ; + req.origin = item->PeerId() ; + req.time_stamp = time(NULL) ; + req.depth = item->depth ; + +#ifdef TUNNEL_STATISTICS + std::cerr << "storing tunnel request " << (void*)(item->request_id) << std::endl ; + + ++TS_tunnel_length[item->depth] ; + TS_request_time_stamps[item->file_hash].push_back(std::pair(time(NULL),item->request_id)) ; +#endif + } + + // If it's not for us, perform a local search. If something found, forward the search result back. + // We're off-mutex here. + + bool found = false ; + FileInfo info ; + + if(item->PeerId() != mConnMgr->getOwnId()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Request not from us. Performing local search" << std::endl ; +#endif + found = (_sharing_strategy != SHARE_FRIENDS_ONLY || item->depth < 2) && performLocalHashSearch(item->file_hash,info) ; + } + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + if(found) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Local hash found. Sending tunnel ok to origin (" << item->PeerId() << ")." << std::endl ; +#endif + // Send back tunnel ok to the same guy + // + RsTurtleTunnelOkItem *res_item = new RsTurtleTunnelOkItem ; + + res_item->request_id = item->request_id ; + res_item->tunnel_id = item->partial_tunnel_id ^ generatePersonalFilePrint(item->file_hash,false) ; + res_item->PeerId(item->PeerId()) ; + + sendItem(res_item) ; + + // Note in the tunnels list that we have an ending tunnel here. + TurtleTunnel tt ; + tt.local_src = item->PeerId() ; + tt.hash = item->file_hash ; + tt.local_dst = mConnMgr->getOwnId() ; // this means us + tt.time_stamp = time(NULL) ; + tt.transfered_bytes = 0 ; + tt.speed_Bps = 0.0f ; + + _local_tunnels[res_item->tunnel_id] = tt ; + + // We add a virtual peer for that tunnel+hash combination. + // + locked_addDistantPeer(item->file_hash,res_item->tunnel_id) ; + + // Store the size of the file, to be able to re-form data requests to the multiplexer. + // + _outgoing_file_hashes[item->file_hash] = info ; + + // We return straight, because when something is found, there's no need to digg a tunnel further. + return ; + } +#ifdef P3TURTLE_DEBUG + else + std::cerr << " No hash found locally, or local file not allowed for distant peers. Forwarding. " << std::endl ; +#endif + } + + // If search depth not too large, also forward this search request to all other peers. + // + bool random_bypass = (item->depth >= TURTLE_MAX_SEARCH_DEPTH && (((_random_bias ^ item->partial_tunnel_id)&0x7)==2)) ; + + if(item->depth < TURTLE_MAX_SEARCH_DEPTH || random_bypass) + { + std::list onlineIds ; + mConnMgr->getOnlineList(onlineIds); +#ifdef P3TURTLE_DEBUG + std::cerr << " Forwarding tunnel request: Looking for online peers" << std::endl ; +#endif + + for(std::list::const_iterator it(onlineIds.begin());it!=onlineIds.end();++it) + if(*it != item->PeerId() && RSRandom::random_f32() <= forward_probability) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Forwarding request to peer = " << *it << std::endl ; +#endif + // Copy current item and modify it. + RsTurtleOpenTunnelItem *fwd_item = new RsTurtleOpenTunnelItem(*item) ; + + ++(fwd_item->depth) ; // increase tunnel depth + fwd_item->PeerId(*it) ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + _traffic_info_buffer.tr_up_Bps += static_cast(fwd_item)->serial_size() ; + } + + sendItem(fwd_item) ; + } + } +#ifdef P3TURTLE_DEBUG + else + std::cout << " Dropping this item, as tunnel depth is " << item->depth << std::endl ; +#endif +} + +void p3turtle::handleTunnelResult(RsTurtleTunnelOkItem *item) +{ + bool new_tunnel = false ; + TurtleFileHash new_hash ; + + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // Find who actually sent the corresponding turtle tunnel request. + // + std::map::iterator it = _tunnel_requests_origins.find(item->request_id) ; +#ifdef P3TURTLE_DEBUG + std::cerr << "Received tunnel result:" << std::endl ; + item->print(std::cerr,0) ; +#endif + + if(it == _tunnel_requests_origins.end()) + { + // This is an error: how could we receive a tunnel result corresponding to a tunnel item we + // have forwarded but that it not in the list ?? Actually that happens, when tunnel requests + // get too old, before the tunnelOk item gets back. But this is quite unusual. + +#ifdef P3TURTLE_DEBUG + std::cerr << __PRETTY_FUNCTION__ << ": tunnel result has no peer direction!" << std::endl ; +#endif + return ; + } + if(it->second.responses.find(item->tunnel_id) != it->second.responses.end()) + { + std::cerr << "p3turtle: ERROR: received a tunnel response twice. That should not happen." << std::endl; + return ; + } + else + it->second.responses.insert(item->tunnel_id) ; + + // store tunnel info. + bool found = (_local_tunnels.find(item->tunnel_id) != _local_tunnels.end()) ; + TurtleTunnel& tunnel(_local_tunnels[item->tunnel_id]) ; + + if(found) + { +#ifdef P3TURTLE_DEBUG + std::cerr << "Tunnel id " << (void*)item->tunnel_id << " is already there. Not storing." << std::endl ; +#endif + } + else + { + tunnel.local_src = it->second.origin ; + tunnel.local_dst = item->PeerId() ; + tunnel.hash = "" ; + tunnel.time_stamp = time(NULL) ; + tunnel.transfered_bytes = 0 ; + tunnel.speed_Bps = 0.0f ; + +#ifdef P3TURTLE_DEBUG + std::cerr << " storing tunnel info. src=" << tunnel.local_src << ", dst=" << tunnel.local_dst << ", id=" << item->tunnel_id << std::endl ; +#endif + } + + // Is this result's target actually ours ? + + if(it->second.origin == mConnMgr->getOwnId()) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Tunnel starting point. Storing id=" << (void*)item->tunnel_id << " for hash (unknown) and tunnel request id " << it->second.origin << std::endl; +#endif + // Tunnel is ending here. Add it to the list of tunnels for the given hash. + + // 1 - find which file hash issued this request. This is not costly, + // because there is not too much file hashes to be active at a time, + // and this mostly prevents from sending the hash back in the tunnel. + + bool found = false ; + for(std::map::iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) + if(it->second.last_request == item->request_id) + { + found = true ; + + // add the tunnel uniquely + bool found = false ; + + for(unsigned int j=0;jsecond.tunnels.size();++j) + if(it->second.tunnels[j] == item->tunnel_id) + found = true ; + + if(!found) + it->second.tunnels.push_back(item->tunnel_id) ; + + tunnel.hash = it->first ; // because it's a local tunnel + + // Adds a virtual peer to the list of online peers. + // We do this later, because of the mutex protection. + // + new_tunnel = true ; + new_hash = it->first ; + + locked_addDistantPeer(new_hash,item->tunnel_id) ; + } + if(!found) + std::cerr << "p3turtle: error. Could not find hash that emmitted tunnel request " << (void*)item->tunnel_id << std::endl ; + } + else + { // Nope, forward it back. +#ifdef P3TURTLE_DEBUG + std::cerr << " Forwarding result back to " << it->second.origin << std::endl; +#endif + RsTurtleTunnelOkItem *fwd_item = new RsTurtleTunnelOkItem(*item) ; // copy the item + fwd_item->PeerId(it->second.origin) ; + + sendItem(fwd_item) ; + } + } + + // A new tunnel has been created. Add the corresponding virtual peer to the list, and + // notify the file transfer controller for the new file source. This should be done off-mutex + // so we deported this code here. + // + if(new_tunnel) + { + _ft_controller->addFileSource(new_hash,_local_tunnels[item->tunnel_id].vpid) ; + _ft_controller->statusChange(_online_peers) ; + } +} + +// -----------------------------------------------------------------------------------// +// ------------------------------ IO with libretroshare ----------------------------// +// -----------------------------------------------------------------------------------// +// +void RsTurtleStringSearchRequestItem::performLocalSearch(std::list& result) const +{ + /* call to core */ + std::list initialResults; + std::list words ; + + // to do: split search string into words. + words.push_back(match_string) ; + +#ifdef P3TURTLE_DEBUG + std::cerr << "Performing rsFiles->search()" << std::endl ; +#endif + // now, search! + rsFiles->SearchKeywords(words, initialResults,DIR_FLAGS_LOCAL | DIR_FLAGS_NETWORK_WIDE); + +#ifdef P3TURTLE_DEBUG + std::cerr << initialResults.size() << " matches found." << std::endl ; +#endif + result.clear() ; + + for(std::list::const_iterator it(initialResults.begin());it!=initialResults.end();++it) + { + // retain only file type + if (it->type == DIR_TYPE_DIR) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Skipping directory " << it->name << std::endl ; +#endif + continue; + } + + TurtleFileInfo i ; + i.hash = it->hash ; + i.size = it->count ; + i.name = it->name ; + + result.push_back(i) ; + } +} +void RsTurtleRegExpSearchRequestItem::performLocalSearch(std::list& result) const +{ + /* call to core */ + std::list initialResults; + + // to do: split search string into words. + Expression *exp = LinearizedExpression::toExpr(expr) ; + + if(exp == NULL) + return ; + + // now, search! + rsFiles->SearchBoolExp(exp,initialResults,DIR_FLAGS_LOCAL | DIR_FLAGS_NETWORK_WIDE); + + result.clear() ; + + for(std::list::const_iterator it(initialResults.begin());it!=initialResults.end();++it) + { + TurtleFileInfo i ; + i.hash = it->hash ; + i.size = it->count ; + i.name = it->name ; + + result.push_back(i) ; + } + delete exp ; +} + +TurtleRequestId p3turtle::turtleSearch(const std::string& string_to_match) +{ + // generate a new search id. + + TurtleRequestId id = generateRandomRequestId() ; + + // Form a request packet that simulates a request from us. + // + RsTurtleStringSearchRequestItem *item = new RsTurtleStringSearchRequestItem ; + +#ifdef P3TURTLE_DEBUG + std::cerr << "performing search. OwnId = " << mConnMgr->getOwnId() << std::endl ; +#endif + while(mConnMgr->getOwnId() == "") + { + std::cerr << "... waitting for connect manager to form own id." << std::endl ; +#ifdef WIN32 + Sleep(1000) ; +#else + sleep(1) ; +#endif + } + + item->PeerId(mConnMgr->getOwnId()) ; + item->match_string = string_to_match ; + item->request_id = id ; + item->depth = 0 ; + + // send it + + handleSearchRequest(item) ; + + delete item ; + + return id ; +} +TurtleRequestId p3turtle::turtleSearch(const LinearizedExpression& expr) +{ + // generate a new search id. + + TurtleRequestId id = generateRandomRequestId() ; + + // Form a request packet that simulates a request from us. + // + RsTurtleRegExpSearchRequestItem *item = new RsTurtleRegExpSearchRequestItem ; + +#ifdef P3TURTLE_DEBUG + std::cerr << "performing search. OwnId = " << mConnMgr->getOwnId() << std::endl ; +#endif + while(mConnMgr->getOwnId() == "") + { + std::cerr << "... waitting for connect manager to form own id." << std::endl ; +#ifdef WIN32 + Sleep(1000) ; +#else + sleep(1) ; +#endif + } + + item->PeerId(mConnMgr->getOwnId()) ; + item->expr = expr ; + item->request_id = id ; + item->depth = 0 ; + + // send it + + handleSearchRequest(item) ; + + delete item ; + + return id ; +} + +void p3turtle::monitorFileTunnels(const std::string& name,const std::string& file_hash,uint64_t size) +{ + { + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + // First, check if the hash is tagged for removal (there's a delay) + + for(uint32_t i=0;i<_hashes_to_remove.size();++i) + if(_hashes_to_remove[i] == file_hash) + { + _hashes_to_remove[i] = _hashes_to_remove.back() ; + _hashes_to_remove.pop_back() ; +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: File hash " << file_hash << " Was scheduled for removal. Canceling the removal." << std::endl ; +#endif + } + + // Then, check if the hash is already there + // + if(_incoming_file_hashes.find(file_hash) != _incoming_file_hashes.end()) // download already asked. + { +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: File hash " << file_hash << " already in pool. Returning." << std::endl ; +#endif + return ; + } +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: Received order for turtle download fo hash " << file_hash << std::endl ; +#endif + + // No tunnels at start, but this triggers digging new tunnels. + // + _incoming_file_hashes[file_hash].tunnels.clear(); + + // also should send associated request to the file transfer module. + _incoming_file_hashes[file_hash].size = size ; + _incoming_file_hashes[file_hash].name = name ; + _incoming_file_hashes[file_hash].last_digg_time = RSRandom::random_u32()%10 ; + } + + IndicateConfigChanged() ; // initiates saving of handled hashes. +} + +void p3turtle::returnSearchResult(RsTurtleSearchResultItem *item) +{ + // just cout for now, but it should be notified to the gui + +#ifdef P3TURTLE_DEBUG + std::cerr << " Returning result for search request " << (void*)item->request_id << " upwards." << std::endl ; +#endif + + rsicontrol->getNotify().notifyTurtleSearchResult(item->request_id,item->result) ; +} + +/// Warning: this function should never be called while the turtle mutex is locked. +/// Otherwize this is a possible source of cross-lock with the File mutex. +// +bool p3turtle::performLocalHashSearch(const TurtleFileHash& hash,FileInfo& info) +{ + return rsFiles->FileDetails(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_DOWNLOAD, info); +} + +static std::string printFloatNumber(float num,bool friendly=false) +{ + std::ostringstream out ; + + if(friendly) + { + char tmp[100] ; + std::string units[4] = { "B/s","KB/s","MB/s","GB/s" } ; + + int k=0 ; + while(num >= 800.0f && k<5) + num /= 1024.0f,++k; + + sprintf(tmp,"%3.2f %s",num,units[k].c_str()) ; + return std::string(tmp) ; + } + else + { + out << num ; + return out.str() ; + } +} +static std::string printNumber(uint64_t num,bool hex=false) +{ + if(hex) + { + char tmp[100] ; + + if(num < (((uint64_t)1)<<32)) + sprintf(tmp,"%08x", uint32_t(num)) ; + else + sprintf(tmp,"%08x%08x", uint32_t(num >> 32),uint32_t(num & ( (((uint64_t)1)<<32)-1 ))) ; + return std::string(tmp) ; + } + else + { + std::ostringstream out ; + out << num ; + return out.str() ; + } +} + +void p3turtle::getTrafficStatistics(TurtleTrafficStatisticsInfo& info) const +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + info = _traffic_info ; +} + +void p3turtle::getInfo( std::vector >& hashes_info, + std::vector >& tunnels_info, + std::vector& search_reqs_info, + std::vector& tunnel_reqs_info) const +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + time_t now = time(NULL) ; + + hashes_info.clear() ; + + for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) + { + hashes_info.push_back(std::vector()) ; + + std::vector& hashes(hashes_info.back()) ; + + hashes.push_back(it->first) ; + hashes.push_back(it->second.name) ; + hashes.push_back(printNumber(it->second.tunnels.size())) ; + //hashes.push_back(printNumber(now - it->second.time_stamp)+" secs ago") ; + } + + tunnels_info.clear(); + + for(std::map::const_iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) + { + tunnels_info.push_back(std::vector()) ; + std::vector& tunnel(tunnels_info.back()) ; + + tunnel.push_back(printNumber(it->first,true)) ; + + RsPeerDetails sslDetails; + + if(rsPeers->getPeerDetails(it->second.local_src,sslDetails)) + tunnel.push_back(sslDetails.name + " - " + sslDetails.location) ; + else + tunnel.push_back(it->second.local_src) ; + + if(rsPeers->getPeerDetails(it->second.local_dst,sslDetails)) + tunnel.push_back(sslDetails.name + " - " + sslDetails.location) ; + else + tunnel.push_back(it->second.local_dst); + + tunnel.push_back(it->second.hash) ; + tunnel.push_back(printNumber(now-it->second.time_stamp) + " secs ago") ; + tunnel.push_back(printFloatNumber(it->second.speed_Bps,true)) ; + } + + search_reqs_info.clear(); + + for(std::map::const_iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();++it) + { + TurtleRequestDisplayInfo info ; + + info.request_id = it->first ; + info.source_peer_id = it->second.origin ; + info.age = now - it->second.time_stamp ; + info.depth = it->second.depth ; + + search_reqs_info.push_back(info) ; + } + + tunnel_reqs_info.clear(); + + for(std::map::const_iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();++it) + { + TurtleRequestDisplayInfo info ; + + info.request_id = it->first ; + info.source_peer_id = it->second.origin ; + info.age = now - it->second.time_stamp ; + info.depth = it->second.depth ; + + tunnel_reqs_info.push_back(info) ; + } +} + +#ifdef P3TURTLE_DEBUG +void p3turtle::dumpState() +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + + time_t now = time(NULL) ; + + std::cerr << std::endl ; + std::cerr << "********************** Turtle router dump ******************" << std::endl ; + std::cerr << " Active incoming file hashes: " << _incoming_file_hashes.size() << std::endl ; + for(std::map::const_iterator it(_incoming_file_hashes.begin());it!=_incoming_file_hashes.end();++it) + { + std::cerr << " hash=0x" << it->first << ", name=" << it->second.name << ", size=" << it->second.size << ", tunnel ids =" ; + for(std::vector::const_iterator it2(it->second.tunnels.begin());it2!=it->second.tunnels.end();++it2) + std::cerr << " " << (void*)*it2 ; + std::cerr << ", last_req=" << (void*)it->second.last_request << ", time_stamp = " << it->second.time_stamp << "(" << now-it->second.time_stamp << " secs ago)" << std::endl ; + } + std::cerr << " Active outgoing file hashes: " << _outgoing_file_hashes.size() << std::endl ; + for(std::map::const_iterator it(_outgoing_file_hashes.begin());it!=_outgoing_file_hashes.end();++it) + std::cerr << " hash=0x" << it->first << ", name=" << it->second.fname << ", size=" << it->second.size << std::endl ; + + std::cerr << " Local tunnels:" << std::endl ; + for(std::map::const_iterator it(_local_tunnels.begin());it!=_local_tunnels.end();++it) + std::cerr << " " << (void*)it->first << ": from=" + << it->second.local_src << ", to=" << it->second.local_dst + << ", hash=0x" << it->second.hash << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp << " secs ago)" + << ", peer id =" << it->second.vpid << std::endl ; + + std::cerr << " buffered request origins: " << std::endl ; + std::cerr << " Search requests: " << _search_requests_origins.size() << std::endl ; + + for(std::map::const_iterator it(_search_requests_origins.begin());it!=_search_requests_origins.end();++it) + std::cerr << " " << (void*)it->first << ": from=" << it->second.origin + << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp + << " secs ago)" << std::endl ; + + std::cerr << " Tunnel requests: " << _tunnel_requests_origins.size() << std::endl ; + for(std::map::const_iterator it(_tunnel_requests_origins.begin());it!=_tunnel_requests_origins.end();++it) + std::cerr << " " << (void*)it->first << ": from=" << it->second.origin + << ", ts=" << it->second.time_stamp << " (" << now-it->second.time_stamp + << " secs ago)" << std::endl ; + + std::cerr << " Virtual peers:" << std::endl ; + for(std::map::const_iterator it(_virtual_peers.begin());it!=_virtual_peers.end();++it) + std::cerr << " id=" << it->first << ", tunnel=" << (void*)(it->second) << std::endl ; + std::cerr << " Online peers: " << std::endl ; + for(std::list::const_iterator it(_online_peers.begin());it!=_online_peers.end();++it) + std::cerr << " id=" << it->id << ", name=" << it->name << ", state=" << it->state << ", actions=" << it->actions << std::endl ; +} +#endif + +#ifdef TUNNEL_STATISTICS +void p3turtle::TS_dumpState() +{ + RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + time_t now = time(NULL) ; + std::cerr << "Dumping tunnel statistics:" << std::endl; + + std::cerr << "TR Bounces: " << TS_request_bounces.size() << std::endl; + for(std::map >::const_iterator it(TS_request_bounces.begin());it!=TS_request_bounces.end();++it) + { + std::cerr << (void*)it->first << ": " ; + for(uint32_t i=0;isecond.size();++i) + std::cerr << it->second[i] - it->second[0] << " " ; + std::cerr << std::endl; + } + std::cerr << "TR in cache: " << _tunnel_requests_origins.size() << std::endl; + std::cerr << "TR by size: " ; + for(int i=0;i<8;++i) + std::cerr << "N(" << i << ")=" << TS_tunnel_length[i] << ", " ; + std::cerr << std::endl; + + std::cerr << "Total different requested files: " << TS_request_time_stamps.size() << std::endl; + for(std::map > >::const_iterator it(TS_request_time_stamps.begin());it!=TS_request_time_stamps.end();++it) + { + std::cerr << "hash = " << it->first << ": seconds ago: " ; + float average = 0 ; + for(uint32_t i=std::max(0,(int)it->second.size()-25);isecond.size();++i) + { + std::cerr << now - it->second[i].first << " (" << (void*)it->second[i].second << ") " ; + + if(i>0) + average += it->second[i].first - it->second[i-1].first ; + } + + if(it->second.size()>1) + std::cerr << ", average delay=" << average/(float)(it->second.size()-1) << std::endl; + else + std::cerr << std::endl; + } +} +#endif diff --git a/libretroshare/src/turtle/p3turtle.h b/libretroshare/src/turtle/p3turtle.h new file mode 100644 index 000000000..f814e6150 --- /dev/null +++ b/libretroshare/src/turtle/p3turtle.h @@ -0,0 +1,431 @@ +/* + * libretroshare/src/services: p3turtle.h + * + * Services for RetroShare. + * + * Copyright 2009 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "csoler@users.sourceforge.net". + * + */ + +//====================================== General setup of the router ===================================// +// +// This class implements the turtle hopping router. It basically serves as +// - a cache of turtle tunnels which are the communicating ways between distant peers. +// - turtle tunnels are either end-point tunnels, or transitory points, in which case items are just +// re-serialized and passed on along the tunnel. +// - turtle tunnels are dug on request when calling diggTurtleTunnel(const std::string& hash) +// this command lets a trace in each peer along the tunnel of where +// packets come from and where they should go. Doing so, once a tunnel is +// dug, packets are directly forwarded to the correct peer. +// - an entry point for search request from the interface +// - search results, as they come back, are forwarded upwards with some additional info: +// - depth // depth of the file. setup to 1 for immediate friends and 2 for long distance friends. +// - hash // hash of the file found +// - name // name of the file found +// - search request id. // +// +// - when downloading: +// - for a given hash, a set of starting tunnels is maintained. Transitory +// tunnels are also maintained for other hashes as requested by distant +// peers. +// +//============================================= Operations =============================================// +// +// A download session works as follows: +// Initiation: +// 1 - the user searches for files (turtle search), and selects one and clicks download. +// 2 - In parallel: +// - the ft module gets a request, and searches for peers to provide this using its search modules. +// - the turtle router is informed that a turtle download will happen with the given hash, so +// it initiates tunnels for this hash. +// In a loop: +// 3 - the ft module asks the hash to the turtle searchModule, and sends file requests to the pqi +// interface of this module. +// 4 - the turtle pqi interface forwards these requests to the turtle router, which sends them to +// the correct peers, selecting randomly among all the possible tunnels for this hash. +// 5 - when a file data packet gets back, the turtle router forwards it back to the file transfer module. +// +//================================ connexion to the file transfer module ===============================// +// +// The turtle router should provide the ft module with the necessary interface for asking files, and +// retreiving data: +// - a search module that responds with a given fake peer id for hash request for which it has tunnels. +// - a pqi interface to ask for file data +// - p3turtle sends back file data packets to the file transfer module +// +//========================================== Tunnel usage rules ========================================// +// +// Tunnels should be used according to their capacity. This is an unsolved problem as for now. +// +//======================================= Tunnel maintenance rules =====================================// +// +// P3turtle should derive from pqihandler, just as p3disc, so that newly connected peers should trigger +// asking for new tunnels, and disconnecting peers should produce a close tunnel packet. To simplify this, +// I maintain a time stamp in tunnels, that is updated each time a file data packet travels in the tunnel. +// Doing so, if a tunnel is not used for some time, it just disapears. Additional rules apply: +// +// - when a peer A connects: +// - initiate new tunnels for all active file hashes (go through the list of hashes) by +// asking to A, for the same hash and the same source. Only report tunnels for which the destination +// endpoint is different, which should not happen in fact, because of bouncing gards. +// +// - when a peer A disconnects. +// - do nothing. +// +// - when receive open tunnel from A +// - check whether it's a bouncing request. If yes, give up. +// - check hash against local files. +// if > 0 +// return tunnel ok item. No need to go forward, as sub tunnels are not useful. +// else +// forward request to peers, notting source and hashes. +// +// - when receive tunnel ok from A +// - no need to check whether we already have this tunnel, as bouncing gards prevent this. +// - leave a trace for the tunnel, and send (forward) backward. +// +// Ids management: +// - tunnel ids should be identical for requests between 2 same peers for the same file hash. +// - tunnel ids should be asymetric +// - tunnel requests should never be identical, to allow searching multiple times for the same string. +// So: +// - when issuing an open tunnel order, +// - a random request id is generated and used for packet routing +// - a partial tunnel id is build, which is unique to the pair (source,file hash) +// - when tunnel_ok is sent back, the tunnel id is completed so that it is unique to the +// triplet (source, destination, file hash). +// +// For these needs, tunnels are represented by: +// - their file hash. Each tunnel is only designed for transferring a single and same file. +// - their local endpoints id. These are the ids of the peers in direction to the source and destination. +// - the tunnel id, which is unique to the triple hash+global source+global destination. +// - there is a difference between source and destination in tunnels. The source is the file asker, the +// destination is the file provider. This helps sorting tunnels. +// - a timestamp, used for cleaning unused tunnels. +// +// The turtle router has: +// - a list of search requests and where to bounce them back. +// - a list of tunnel digging requests and where to bounce them, back. +// - a list of active file hashes, for which is should constantly maintain tunnels. +// - a list of active tunnels, some being transitory, some being endpoints. +// +// Turtle router entries: +// - a function for performing turtle search +// - a function for handling tunnels for a given file hash. +// +// Questions: +// - should tunnels be re-used ? nope. The only useful case would be when two peers are exchanging files, which happens quite rarely. +// + + +#ifndef MRK_PQI_TURTLE_H +#define MRK_PQI_TURTLE_H + +#include +#include +#include + +#include "pqi/pqinetwork.h" +#include "pqi/pqi.h" +#include "pqi/pqimonitor.h" +#include "services/p3service.h" +#include "ft/ftsearch.h" +#include "retroshare/rsturtle.h" +#include "rsturtleitem.h" +#include "turtlestatistics.h" + +//#define TUNNEL_STATISTICS + +class ftServer ; +class p3ConnectMgr; +class ftDataMultiplex; +class RsSerialiser; + +static const int TURTLE_MAX_SEARCH_DEPTH = 6 ; + +// This class is used to keep trace of requests (searches and tunnels). +// +class TurtleRequestInfo +{ + public: + TurtlePeerId origin ; // where the request came from. + uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels. + int depth ; // depth of the request. Used to optimize tunnel length. + std::set responses; // responses to this request. Useful to avoid spamming tunnel responses. +}; + +class TurtleTunnel +{ + public: + /* For all tunnels */ + + TurtlePeerId local_src ; // where packets come from. Direction to the source. + TurtlePeerId local_dst ; // where packets should go. Direction to the destination. + uint32_t time_stamp ; // last time the tunnel was actually used. Used for cleaning old tunnels. + uint32_t transfered_bytes ; // total bytes transferred in this tunnel. + float speed_Bps ; // speed of the traffic through the tunnel + + /* For ending/starting tunnels only. */ + + TurtleFileHash hash; // Hash of the file for this tunnel + TurtleVirtualPeerId vpid; // Virtual peer id for this tunnel. +}; + +// This class keeps trace of the activity for the file hashes the turtle router is asked to monitor. +// +class TurtleFileHashInfo +{ + public: + std::vector tunnels ; // list of active tunnel ids for this file hash + TurtleRequestId last_request ; // last request for the tunnels of this hash + + TurtleFileName name ; + time_t last_digg_time ; + uint64_t size ; +}; + +// Subclassing: +// +// Class | Brings what | Usage +// -----------+------------------+------------------------------------------------------ +// p3Service | sendItem() | handle packet sending/receiving to/from friend peers. +// pqiMonitor | configChanged() | handle who's connecting/disconnecting to dig new tunnels +// RsTurtle | start/stop file()| brings interface for turtle service +// ftSearch | search() | used to allow searching for monitored files. +// p3Config | ConfigChanged() | used to load/save .cfg file for turtle variales. +// -----------+------------------+------------------------------------------------------ +// +class p3turtle: public p3Service, /*public pqiMonitor,*/ public RsTurtle,/* public ftSearch */ public p3Config +{ + public: + p3turtle(p3ConnectMgr *cm,ftServer *m); + + // Lauches a search request through the pipes, and immediately returns + // the request id, which will be further used by the gui to store results + // as they come back. + // + virtual TurtleSearchRequestId turtleSearch(const std::string& string_to_match) ; + virtual TurtleSearchRequestId turtleSearch(const LinearizedExpression& expr) ; + + // Initiates tunnel handling for the given file hash. tunnels. Launches + // an exception if an error occurs during the initialization process. The + // turtle router itself does not initiate downloads, it only maintains + // tunnels for the given hash. The download should be driven by the file + // transfer module. Maybe this function can do the whole thing: + // - initiate tunnel handling + // - send the file request to the file transfer module + // - populate the file transfer module with the adequate pqi interface and search module. + // + // This function should be called in addition to ftServer::FileRequest() so that the turtle router + // automatically provide tunnels for the file to download. + // + virtual void monitorFileTunnels(const std::string& name,const std::string& file_hash,uint64_t size) ; + + /// This should be called when canceling a file download, so that the turtle router stops + /// handling tunnels for this file. + /// + virtual void stopMonitoringFileTunnels(const std::string& file_hash) ; + + /// get info about tunnels + virtual void getInfo(std::vector >&, + std::vector >&, + std::vector&, + std::vector&) const ; + + virtual void getTrafficStatistics(TurtleTrafficStatisticsInfo& info) const ; + +#ifdef TO_REMOVE + /************* from pqiMonitor *******************/ + /// Informs the turtle router that some peers are (dis)connected. This should initiate digging new tunnels, + /// and closing other tunnels. + /// + virtual void statusChange(const std::list &plist); +#endif + + /************* from pqiMonitor *******************/ + + /// This function does many things: + /// - It handles incoming and outgoing packets + /// - it sorts search requests and forwards search results upward. + /// - it cleans unused (tunnel+search) requests. + /// - it maintains the pool of tunnels, for each request file hash. + /// + virtual int tick(); + + /************* from p3Config *******************/ + virtual RsSerialiser *setupSerialiser() ; + virtual bool saveList(bool& cleanup, std::list&) ; + virtual bool loadList(std::list& load) { return true; } + + /************* Communication with ftserver *******************/ + /// Does the turtle router manages tunnels to this peer ? (this is not a + /// real id, but a fake one, that the turtle router is capable of connecting with a tunnel id). + virtual bool isTurtlePeer(const std::string& peer_id) const ; + + /// Examines the peer id, finds the turtle tunnel in it, and respond yes if the tunnel is ok and operational. + bool isOnline(const std::string& peer_id) const ; + + /// Returns a unique peer id, corresponding to the given tunnel. + std::string getTurtlePeerId(TurtleTunnelId tid) const ; + + /// returns the list of virtual peers for all tunnels. + void getVirtualPeersList(std::list& list) ; + + /// Send a data request into the correct tunnel for the given file hash + void sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) ; + + /// Send file data into the correct tunnel for the given file hash + void sendFileData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t baseoffset, uint32_t chunksize, void *data) ; + + /// Send a request for the chunk map of this file to the given peer + void sendChunkMapRequest(const std::string& peerId, const std::string& hash,bool is_client) ; + + /// Send a chunk map of this file to the given peer + void sendChunkMap(const std::string& peerId, const std::string& hash,const CompressedChunkMap& cmap,bool is_client) ; + + /// Send a request for the crc32 map of this file to the given peer + void sendCRC32MapRequest(const std::string& peerId, const std::string& hash) ; + + /// Send a crc32 map of this file to the given peer + void sendCRC32Map(const std::string& peerId, const std::string& hash,const CRC32Map& cmap) ; + + private: + //--------------------------- Admin/Helper functions -------------------------// + + /// Generates a cyphered combination of ownId() and file hash + uint32_t generatePersonalFilePrint(const TurtleFileHash&,bool) ; + + /// Generates a random uint32_t number. + uint32_t generateRandomRequestId() ; + + /// Auto cleaning of unused tunnels, search requests and tunnel requests. + void autoWash() ; + + //------------------------------ Tunnel handling -----------------------------// + + /// initiates tunnels from here to any peers having the given file hash + TurtleRequestId diggTunnel(const TurtleFileHash& hash) ; + + /// adds info related to a new virtual peer. + void locked_addDistantPeer(const TurtleFileHash&, TurtleTunnelId) ; + + /// estimates the speed of the traffic into tunnels. + void estimateTunnelSpeeds() ; + + //----------------------------- Routing functions ----------------------------// + + /// Handle tunnel digging for current file hashes + void manageTunnels() ; + + /// Closes a given tunnel. Should be called with mutex set. + /// The hashes and peers to remove (by calling + /// ftController::removeFileSource() are happended to the supplied vector + /// so that they can be removed off the turtle mutex. + void locked_closeTunnel(TurtleTunnelId tid,std::vector >& peers_to_remove) ; + + /// Main routing function + int handleIncoming(); + + /// Generic routing function for all tunnel packets that derive from RsTurtleGenericTunnelItem + void routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) ; + + /// specific routing functions for handling particular packets. + void handleSearchRequest(RsTurtleSearchRequestItem *item); + void handleSearchResult(RsTurtleSearchResultItem *item); + void handleTunnelRequest(RsTurtleOpenTunnelItem *item); + void handleTunnelResult(RsTurtleTunnelOkItem *item); + void handleRecvFileRequest(RsTurtleFileRequestItem *item); + void handleRecvFileData(RsTurtleFileDataItem *item); + void handleRecvFileMapRequest(RsTurtleFileMapRequestItem*); + void handleRecvFileMap(RsTurtleFileMapItem*); + void handleRecvFileCRC32MapRequest(RsTurtleFileCrcRequestItem*); + void handleRecvFileCRC32Map(RsTurtleFileCrcItem*); + + //------ Functions connecting the turtle router to other components.----------// + + /// Performs a search calling local cache and search structure. + void performLocalSearch(const std::string& match_string,std::list& result) ; + + /// Returns a search result upwards (possibly to the gui) + void returnSearchResult(RsTurtleSearchResultItem *item) ; + + /// Returns true if the file with given hash is hosted locally. + bool performLocalHashSearch(const TurtleFileHash& hash,FileInfo& info) ; + + //--------------------------- Local variables --------------------------------// + + /* data */ + p3ConnectMgr *mConnMgr; + ftServer *_ft_server ; + ftController *_ft_controller ; + + mutable RsMutex mTurtleMtx; + + /// keeps trace of who emmitted a given search request + std::map _search_requests_origins ; + + /// keeps trace of who emmitted a tunnel request + std::map _tunnel_requests_origins ; + + /// stores adequate tunnels for each file hash locally managed + std::map _incoming_file_hashes ; + + /// stores file info for each file we provide. + std::map _outgoing_file_hashes ; + + /// local tunnels, stored by ids (Either transiting or ending). + std::map _local_tunnels ; + + /// Peers corresponding to each tunnel. + std::map _virtual_peers ; + + /// Hashes marked to be deleted. + std::vector _hashes_to_remove ; + + time_t _last_clean_time ; + time_t _last_tunnel_management_time ; + time_t _last_tunnel_campaign_time ; + time_t _last_tunnel_speed_estimate_time ; + + std::list _online_peers; + + /// used to force digging new tunnels + bool _force_digg_new_tunnels ; + + /// used as a bias to introduce randomness in a consistent way, for + /// altering tunnel request depths, and tunnel re-routing actions. + /// + uint32_t _random_bias ; + + // Used to collect statistics on turtle traffic. + // + TurtleTrafficStatisticsInfoOp _traffic_info ; // used for recording speed + TurtleTrafficStatisticsInfoOp _traffic_info_buffer ; // used as a buffer to collect bytes + +#ifdef P3TURTLE_DEBUG + // debug function + void dumpState() ; +#endif +#ifdef TUNNEL_STATISTICS + void TS_dumpState(); +#endif +}; + +#endif + diff --git a/libretroshare/src/turtle/rsturtleitem.cc b/libretroshare/src/turtle/rsturtleitem.cc new file mode 100644 index 000000000..c3f078df8 --- /dev/null +++ b/libretroshare/src/turtle/rsturtleitem.cc @@ -0,0 +1,1112 @@ +#ifndef WINDOWS_SYS +#include +#endif +#include +#include "turtletypes.h" +#include "rsturtleitem.h" + +//#define P3TURTLE_DEBUG +// -----------------------------------------------------------------------------------// +// -------------------------------- Serialization. --------------------------------- // +// -----------------------------------------------------------------------------------// +// + +// +// ---------------------------------- Packet sizes -----------------------------------// +// + +uint32_t RsTurtleStringSearchRequestItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // request_id + s += 2 ; // depth + s += GetTlvStringSize(match_string) ; // match_string + + return s ; +} +uint32_t RsTurtleRegExpSearchRequestItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // request_id + s += 2 ; // depth + + s += 4 ; // number of strings + + for(unsigned int i=0;i::const_iterator it(result.begin());it!=result.end();++it) + { + s += 8 ; // file size + s += GetTlvStringSize(it->hash) ; // file hash + s += GetTlvStringSize(it->name) ; // file name + } + + return s ; +} + +uint32_t RsTurtleOpenTunnelItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += GetTlvStringSize(file_hash) ; // file hash + s += 4 ; // tunnel request id + s += 4 ; // partial tunnel id + s += 2 ; // depth + + return s ; +} + +uint32_t RsTurtleTunnelOkItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 4 ; // tunnel request id + + return s ; +} + +uint32_t RsTurtleFileRequestItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 8 ; // file offset + s += 4 ; // chunk size + + return s ; +} + +uint32_t RsTurtleFileDataItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 8 ; // file offset + s += 4 ; // chunk size + s += chunk_size ; // actual data size. + + return s ; +} + +uint32_t RsTurtleFileMapRequestItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 4 ; // direction + + return s ; +} + +uint32_t RsTurtleFileMapItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 4 ; // direction + s += 4 ; // compressed_map.size() + + s += 4 * compressed_map._map.size() ; + + return s ; +} + +uint32_t RsTurtleFileCrcRequestItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + + return s ; +} + +uint32_t RsTurtleFileCrcItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + + s += 4 ; // size of _map + s += 4 ; // size of _crcs + + s += 4 * crc_map._crcs.size() ; + s += 4 * crc_map._ccmap._map.size() ; + + return s ; +} +// +// ---------------------------------- Serialization ----------------------------------// +// +RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size) +{ + // look what we have... + + /* get the type */ + uint32_t rstype = getRsItemId(data); +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: deserialising packet: " << std::endl ; +#endif + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_TURTLE != getRsItemService(rstype))) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Wrong type !!" << std::endl ; +#endif + return NULL; /* wrong type */ + } + +#ifndef WINDOWS_SYS + try + { +#endif + switch(getRsItemSubType(rstype)) + { + case RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST : return new RsTurtleStringSearchRequestItem(data,*size) ; + case RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST : return new RsTurtleRegExpSearchRequestItem(data,*size) ; + case RS_TURTLE_SUBTYPE_SEARCH_RESULT : return new RsTurtleSearchResultItem(data,*size) ; + case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : return new RsTurtleOpenTunnelItem(data,*size) ; + case RS_TURTLE_SUBTYPE_TUNNEL_OK : return new RsTurtleTunnelOkItem(data,*size) ; + case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(data,*size) ; + case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(data,*size) ; + case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(data,*size) ; + case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(data,*size) ; + case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST : return new RsTurtleFileCrcRequestItem(data,*size) ; + case RS_TURTLE_SUBTYPE_FILE_CRC : return new RsTurtleFileCrcItem(data,*size) ; + + default: + std::cerr << "Unknown packet type in RsTurtle!" << std::endl ; + return NULL ; + } +#ifndef WINDOWS_SYS + } + catch(std::exception& e) + { + std::cerr << "Exception raised: " << e.what() << std::endl ; + return NULL ; + } +#endif + +} + +bool RsTurtleFileMapRequestItem::serialize(void *data,uint32_t& pktsize) +{ + uint32_t tlvsize = serial_size(); + uint32_t offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + + ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id); + ok &= setRawUInt32(data, tlvsize, &offset, direction); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl; +#endif + } + + return ok; +} + +bool RsTurtleFileMapItem::serialize(void *data,uint32_t& pktsize) +{ + uint32_t tlvsize = serial_size(); + uint32_t offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + + ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id); + ok &= setRawUInt32(data, tlvsize, &offset, direction); + ok &= setRawUInt32(data, tlvsize, &offset, compressed_map._map.size()); + + for(uint32_t i=0;i::const_iterator it(result.begin());it!=result.end();++it) + { + ok &= setRawUInt64(data, tlvsize, &offset, it->size); // file size + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_HASH_SHA1, it->hash); // file hash + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, it->name); // file name + } + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsTurtleFileMapItem::RsTurtleFileMapItem(void *data,uint32_t pktsize) + : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP) +{ +#ifdef P3TURTLE_DEBUG + std::cerr << " type = file map item" << std::endl ; +#endif + uint32_t offset = 8; // skip the header + + /* add mandatory parts first */ + + bool ok = true ; + uint32_t s,d ; + ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id); + ok &= getRawUInt32(data, pktsize, &offset, &d); + direction = d ; + ok &= getRawUInt32(data, pktsize, &offset, &s) ; + + compressed_map._map.resize(s) ; + + for(uint32_t i=0;i::const_iterator it(result.begin());it!=result.end();++it) + o << " " << it->hash << " " << it->size << " " << it->name << std::endl ; + + return o ; +} + +std::ostream& RsTurtleOpenTunnelItem::print(std::ostream& o, uint16_t) +{ + o << "Open Tunnel:" << std::endl ; + + o << " Peer id : " << PeerId() << std::endl ; + o << " Partial tId: " << (void *)partial_tunnel_id << std::endl ; + o << " Req. Id : " << (void *)request_id << std::endl ; + o << " Depth : " << depth << std::endl ; + o << " Hash : " << file_hash << std::endl ; + + return o ; +} + +std::ostream& RsTurtleTunnelOkItem::print(std::ostream& o, uint16_t) +{ + o << "Tunnel Ok:" << std::endl ; + + o << " Peer id : " << PeerId() << std::endl ; + o << " tunnel id : " << (void*)tunnel_id << std::endl ; + o << " Req. Id : " << (void *)request_id << std::endl ; + + return o ; +} + +std::ostream& RsTurtleFileRequestItem::print(std::ostream& o, uint16_t) +{ + o << "File request item:" << std::endl ; + + o << " tunnel id : " << (void*)tunnel_id << std::endl ; + o << " offset : " << chunk_offset << std::endl ; + o << " chunk size: " << chunk_size << std::endl ; + + return o ; +} + +std::ostream& RsTurtleFileDataItem::print(std::ostream& o, uint16_t) +{ + o << "File request item:" << std::endl ; + + o << " tunnel id : " << (void*)tunnel_id << std::endl ; + o << " offset : " << chunk_offset << std::endl ; + o << " chunk size: " << chunk_size << std::endl ; + o << " data : " << (void*)chunk_data << std::endl ; + + return o ; +} + +std::ostream& RsTurtleFileMapItem::print(std::ostream& o, uint16_t) +{ + o << "File map item:" << std::endl ; + + o << " tunnel id : " << (void*)tunnel_id << std::endl ; + o << " direction : " << direction << std::endl ; + o << " map : " ; + + for(uint32_t i=0;i 1, this field is a larger arbitrary integer. + + std::list result ; + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + protected: + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleSearchRequestItem: public RsTurtleItem +{ + public: + RsTurtleSearchRequestItem(uint32_t subtype) : RsTurtleItem(subtype) {} + + virtual RsTurtleSearchRequestItem *clone() const = 0 ; // used for cloning in routing methods + virtual void performLocalSearch(std::list&) const = 0 ; // abstracts the search method + + uint32_t request_id ; // randomly generated request id. + uint16_t depth ; // Used for limiting search depth. +}; + +class RsTurtleStringSearchRequestItem: public RsTurtleSearchRequestItem +{ + public: + RsTurtleStringSearchRequestItem() : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST) {} + RsTurtleStringSearchRequestItem(void *data,uint32_t size) ; + + std::string match_string ; // string to match + + virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleStringSearchRequestItem(*this) ; } + virtual void performLocalSearch(std::list&) const ; + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + protected: + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleRegExpSearchRequestItem: public RsTurtleSearchRequestItem +{ + public: + RsTurtleRegExpSearchRequestItem() : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST) {} + RsTurtleRegExpSearchRequestItem(void *data,uint32_t size) ; + + LinearizedExpression expr ; // Reg Exp in linearised mode + + virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleRegExpSearchRequestItem(*this) ; } + virtual void performLocalSearch(std::list&) const ; + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + protected: + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +/***********************************************************************************/ +/* Turtle Tunnel Item classes */ +/***********************************************************************************/ + +class RsTurtleOpenTunnelItem: public RsTurtleItem +{ + public: + RsTurtleOpenTunnelItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_OPEN_TUNNEL) {} + RsTurtleOpenTunnelItem(void *data,uint32_t size) ; // deserialization + + TurtleFileHash file_hash ; // hash to match + uint32_t request_id ; // randomly generated request id. + uint32_t partial_tunnel_id ; // uncomplete tunnel id. Will be completed at destination. + uint16_t depth ; // Used for limiting search depth. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + protected: + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleTunnelOkItem: public RsTurtleItem +{ + public: + RsTurtleTunnelOkItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_TUNNEL_OK) {} + RsTurtleTunnelOkItem(void *data,uint32_t size) ; // deserialization + + uint32_t tunnel_id ; // id of the tunnel. Should be identical for a tunnel between two same peers for the same hash. + uint32_t request_id ; // randomly generated request id corresponding to the intial request. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + protected: + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +/***********************************************************************************/ +/* Generic turtle packets for tunnels */ +/***********************************************************************************/ + +class RsTurtleGenericTunnelItem: public RsTurtleItem +{ + public: + RsTurtleGenericTunnelItem(uint8_t sub_packet_id) : RsTurtleItem(sub_packet_id) {} + + typedef uint32_t Direction ; + static const Direction DIRECTION_CLIENT = 0x001 ; + static const Direction DIRECTION_SERVER = 0x002 ; + + /// Does this packet stamps tunnels when it passes through ? + /// This is used for keeping trace weither tunnels are active or not. + + virtual bool shouldStampTunnel() const = 0 ; + + /// All tunnels derived from RsTurtleGenericTunnelItem should have a tunnel id to + /// indicate which tunnel they are travelling through. + + virtual TurtleTunnelId tunnelId() const = 0 ; + + /// Indicate weither the packet is a client packet (goign back to the + /// client) or a server packet (going to the server. Typically file + /// requests are server packets, whereas file data are client packets. + + virtual Direction travelingDirection() const = 0 ; + + /// Generic tunnel items (such as file data) are added into the data queue + virtual RsItem::QueueType queueType() const { return RsItem::DATA_QUEUE ; } +}; + +/***********************************************************************************/ +/* Turtle File Transfer item classes */ +/***********************************************************************************/ + +class RsTurtleFileRequestItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_REQUEST) {} + RsTurtleFileRequestItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return false ; } + virtual TurtleTunnelId tunnelId() const { return tunnel_id ; } + virtual Direction travelingDirection() const { return DIRECTION_SERVER ; } + + uint32_t tunnel_id ; // id of the tunnel to travel through + uint64_t chunk_offset ; + uint32_t chunk_size ; + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + protected: + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleFileDataItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_DATA) {} + ~RsTurtleFileDataItem() ; + RsTurtleFileDataItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return true ; } + virtual TurtleTunnelId tunnelId() const { return tunnel_id ; } + virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; } + + uint32_t tunnel_id ; // id of the tunnel to travel through + uint64_t chunk_offset ; // offset in the file + uint32_t chunk_size ; // size of the file chunk + void *chunk_data ; // actual data. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleFileMapRequestItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileMapRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST) {} + RsTurtleFileMapRequestItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return false ; } + virtual TurtleTunnelId tunnelId() const { return tunnel_id ; } + virtual Direction travelingDirection() const { return direction ; } + + Direction direction ; // travel direction for this packet (server/client) + uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source + // this info from the file size, but this allows a security check. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleFileMapItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileMapItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP) {} + RsTurtleFileMapItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return false ; } + virtual TurtleTunnelId tunnelId() const { return tunnel_id ; } + virtual Direction travelingDirection() const { return direction ; } + + Direction direction ; // travel direction for this packet (server/client) + uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source + // this info from the file size, but this allows a security check. + + CompressedChunkMap compressed_map ; // Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have" + // by default, we suppose the peer has all the chunks. This info will thus be and-ed + // with the default file map for this source. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleFileCrcRequestItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileCrcRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST) {} + RsTurtleFileCrcRequestItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return false ; } + virtual TurtleTunnelId tunnelId() const { return tunnel_id ; } + virtual Direction travelingDirection() const { return DIRECTION_SERVER ; } + + uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source + // this info from the file size, but this allows a security check. + +// CompressedChunkMap _map ; // list of chunks for which we need the CRC + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + + +class RsTurtleFileCrcItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileCrcItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC) {} + RsTurtleFileCrcItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return true ; } + virtual TurtleTunnelId tunnelId() const { return tunnel_id ; } + virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; } + + uint32_t tunnel_id ; // id of the tunnel to travel through. Also used for identifying the file source + // this info from the file size, but this allows a security check. + + CRC32Map crc_map ;// Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have" + // by default, we suppose the peer has all the chunks. This info will thus be and-ed + // with the default file map for this source. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +/***********************************************************************************/ +/* Turtle Serialiser class */ +/***********************************************************************************/ + +class RsTurtleSerialiser: public RsSerialType +{ + public: + RsTurtleSerialiser() : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_TURTLE) {} + + virtual uint32_t size (RsItem *item) + { + return dynamic_cast(item)->serial_size() ; + } + virtual bool serialise(RsItem *item, void *data, uint32_t *size) + { + return dynamic_cast(item)->serialize(data,*size) ; + } + virtual RsItem *deserialise (void *data, uint32_t *size) ; +}; + diff --git a/libretroshare/src/turtle/turtlestatistics.h b/libretroshare/src/turtle/turtlestatistics.h new file mode 100644 index 000000000..5aaeda676 --- /dev/null +++ b/libretroshare/src/turtle/turtlestatistics.h @@ -0,0 +1,51 @@ +#include + +class TurtleTrafficStatisticsInfoOp: public TurtleTrafficStatisticsInfo +{ + public: + TurtleTrafficStatisticsInfoOp() + { + reset() ; + } + + void reset() + { + unknown_updn_Bps = 0.0f ; + data_up_Bps = 0.0f ; + data_dn_Bps = 0.0f ; + tr_up_Bps = 0.0f ; + tr_dn_Bps = 0.0f ; + total_up_Bps = 0.0f ; + total_dn_Bps = 0.0f ; + } + + TurtleTrafficStatisticsInfoOp operator*(float f) const + { + TurtleTrafficStatisticsInfoOp i(*this) ; + + i.unknown_updn_Bps *= f ; + i.data_up_Bps *= f ; + i.data_dn_Bps *= f ; + i.tr_up_Bps *= f ; + i.tr_dn_Bps *= f ; + i.total_up_Bps *= f ; + i.total_dn_Bps *= f ; + + return i ; + } + TurtleTrafficStatisticsInfoOp operator+(const TurtleTrafficStatisticsInfoOp& j) const + { + TurtleTrafficStatisticsInfoOp i(*this) ; + + i.unknown_updn_Bps += j.unknown_updn_Bps ; + i.data_up_Bps += j.data_up_Bps ; + i.data_dn_Bps += j.data_dn_Bps ; + i.tr_up_Bps += j.tr_up_Bps ; + i.tr_dn_Bps += j.tr_dn_Bps ; + i.total_up_Bps += j.total_up_Bps ; + i.total_dn_Bps += j.total_dn_Bps ; + + return i ; + } +}; + diff --git a/libretroshare/src/turtle/turtletypes.h b/libretroshare/src/turtle/turtletypes.h new file mode 100644 index 000000000..e1dc80e12 --- /dev/null +++ b/libretroshare/src/turtle/turtletypes.h @@ -0,0 +1,15 @@ +#pragma once + +#include "retroshare/rsturtle.h" + +typedef std::string TurtlePeerId ; +typedef std::string TurtleVirtualPeerId ; +typedef std::string TurtleFileHash ; +typedef std::string TurtleFileName ; + +typedef TurtleRequestId TurtleSearchRequestId ; + +typedef uint32_t TurtleTunnelRequestId ; +typedef uint32_t TurtleTunnelId ; + + diff --git a/libretroshare/src/upnp/Makefile b/libretroshare/src/upnp/Makefile new file mode 100644 index 000000000..d579a2273 --- /dev/null +++ b/libretroshare/src/upnp/Makefile @@ -0,0 +1,28 @@ + +RS_TOP_DIR = .. +##### Define any flags that are needed for this section ####### +############################################################### + +EXTRA_CFLAGS += -I$(UPNPC_DIR) -DMINIUPNP_EXPORTS + +############################################################### +include $(RS_TOP_DIR)/scripts/config.mk +############################################################### + +CFLAGS += $(EXTRA_CFLAGS) + +RSOBJ = upnphandler.o upnputil.o + +TESTOBJ = upnptest.o + +TESTS = upnptest + +all: librs tests + +upnptest: $(OBJ) upnptest.o + $(CC) $(CFLAGS) -o upnptest $(OBJ) upnptest.o $(LIBS) + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/upnp/UPnPBase.cpp b/libretroshare/src/upnp/UPnPBase.cpp new file mode 100644 index 000000000..484fe0f8f --- /dev/null +++ b/libretroshare/src/upnp/UPnPBase.cpp @@ -0,0 +1,1760 @@ +// +// This file is part of the aMule Project. +// +// Copyright (c) 2004-2009 Marcelo Roberto Jimenez ( phoenix@amule.org ) +// Copyright (c) 2006-2009 aMule Team ( admin@amule.org / http://www.amule.org ) +// Copyright (c) 2009-2010 Retroshare Team +// +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// You are also granted to use it with the LGPL License +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License or the LGPL +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +// + +//This file uses libupnp + +#define UPNP_C + +#include "UPnPBase.h" +#include +#include + +#include // For transform() + + +#ifdef __GNUC__ + #if __GNUC__ >= 4 + #define REINTERPRET_CAST(x) reinterpret_cast + #endif +#endif +#ifndef REINTERPRET_CAST + // Let's hope that function pointers are equal in size to data pointers + #define REINTERPRET_CAST(x) (x) +#endif + + +/** + * Case insensitive std::string comparison + */ +bool stdStringIsEqualCI(const std::string &s1, const std::string &s2) +{ + std::string ns1(s1); + std::string ns2(s2); + std::transform(ns1.begin(), ns1.end(), ns1.begin(), tolower); + std::transform(ns2.begin(), ns2.end(), ns2.begin(), tolower); + return ns1 == ns2; +} + + +CUPnPPortMapping::CUPnPPortMapping( + int ex_port, + int in_port, + const std::string &protocol, + bool enabled, + const std::string &description) +: +m_ex_port(), +m_in_port(), +m_protocol(protocol), +m_enabled(enabled ? "1" : "0"), +m_description(description), +m_key() +{ + std::ostringstream oss; + oss << ex_port; + m_ex_port = oss.str(); + std::ostringstream oss2; + oss2 << in_port; + m_in_port = oss2.str(); + m_key = m_protocol + m_ex_port; +} + + +const std::string &CUPnPLib::UPNP_ROOT_DEVICE = + "upnp:rootdevice"; + +const std::string &CUPnPLib::UPNP_DEVICE_IGW = + "urn:schemas-upnp-org:device:InternetGatewayDevice:1"; +const std::string &CUPnPLib::UPNP_DEVICE_WAN = + "urn:schemas-upnp-org:device:WANDevice:1"; +const std::string &CUPnPLib::UPNP_DEVICE_WAN_CONNECTION = + "urn:schemas-upnp-org:device:WANConnectionDevice:1"; +const std::string &CUPnPLib::UPNP_DEVICE_LAN = + "urn:schemas-upnp-org:device:LANDevice:1"; + +const std::string &CUPnPLib::UPNP_SERVICE_LAYER3_FORWARDING = + "urn:schemas-upnp-org:service:Layer3Forwarding:1"; +const std::string &CUPnPLib::UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG = + "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"; +const std::string &CUPnPLib::UPNP_SERVICE_WAN_IP_CONNECTION = + "urn:schemas-upnp-org:service:WANIPConnection:1"; +const std::string &CUPnPLib::UPNP_SERVICE_WAN_PPP_CONNECTION = + "urn:schemas-upnp-org:service:WANPPPConnection:1"; + + +CUPnPLib::CUPnPLib(CUPnPControlPoint &ctrlPoint) +: +m_ctrlPoint(ctrlPoint) +{ +} + + +std::string CUPnPLib::GetUPnPErrorMessage(int code) const +{ + return UpnpGetErrorMessage(code); +} + + +std::string CUPnPLib::processUPnPErrorMessage( + const std::string &messsage, + int errorCode, + const DOMString errorString, + IXML_Document *doc) const +{ + std::ostringstream msg; +#ifdef UPNP_DEBUG + if (errorString == NULL || *errorString == 0) { + errorString = "Not available"; + } + if (errorCode > 0) { + std::cerr << "CUPnPLib::processUPnPErrorMessage() Error: " << + messsage << + ": Error code :'"; + if (doc) { + CUPnPError e(*this, doc); + std::cerr << e.getErrorCode() << + "', Error description :'" << + e.getErrorDescription() << + "'."; + } else { + std::cerr << errorCode << + "', Error description :'" << + errorString << + "'."; + } + std::cerr << std::endl; + } else { + std::cerr << "CUPnPLib::processUPnPErrorMessage() Error: " << + messsage << + ": UPnP SDK error: " << + GetUPnPErrorMessage(errorCode) << + " (" << errorCode << ")."; + std::cerr << std::endl; + } +#endif + return msg.str(); +} + + +void CUPnPLib::ProcessActionResponse( + IXML_Document *RespDoc, + const std::string &actionName) const +{ + std::ostringstream msg; + msg << "Response: "; + IXML_Element *root = Element_GetRootElement(RespDoc); + IXML_Element *child = Element_GetFirstChild(root); + if (child) { + while (child) { + const DOMString childTag = Element_GetTag(child); + std::string childValue = Element_GetTextValue(child); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPLib::ProcessActionResponse() \n " << + childTag << "='" << + childValue << "'"; +#endif + //add the variable to the wanservice property map + (m_ctrlPoint.m_WanService->propertyMap)[std::string(childTag)] = std::string(childValue); + child = Element_GetNextSibling(child); + } + } else { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPLib::ProcessActionResponse() \n Empty response for action '" << + actionName << "'."; +#endif + } +#ifdef UPNP_DEBUG + std::cerr << std::endl; +#endif +} + + +/*! + * \brief Returns the root node of a given document. + */ +IXML_Element *CUPnPLib::Element_GetRootElement( + IXML_Document *doc) const +{ + IXML_Element *root = REINTERPRET_CAST(IXML_Element *)( + ixmlNode_getFirstChild( + REINTERPRET_CAST(IXML_Node *)(doc))); + + return root; +} + + +/*! + * \brief Returns the first child of a given element. + */ +IXML_Element *CUPnPLib::Element_GetFirstChild( + IXML_Element *parent) const +{ + IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(parent); + IXML_Node *child = ixmlNode_getFirstChild(node); + + return REINTERPRET_CAST(IXML_Element *)(child); +} + + +/*! + * \brief Returns the next sibling of a given child. + */ +IXML_Element *CUPnPLib::Element_GetNextSibling( + IXML_Element *child) const +{ + IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(child); + IXML_Node *sibling = ixmlNode_getNextSibling(node); + + return REINTERPRET_CAST(IXML_Element *)(sibling); +} + + +/*! + * \brief Returns the element tag (name) + */ +const DOMString CUPnPLib::Element_GetTag( + IXML_Element *element) const +{ + IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(element); + const DOMString tag = ixmlNode_getNodeName(node); + + return tag; +} + + +/*! + * \brief Returns the TEXT node value of the current node. + */ +const std::string CUPnPLib::Element_GetTextValue( + IXML_Element *element) const +{ + if (!element) { + return stdEmptyString; + } + IXML_Node *text = ixmlNode_getFirstChild( + REINTERPRET_CAST(IXML_Node *)(element)); + const DOMString s = ixmlNode_getNodeValue(text); + std::string ret; + if (s) { + ret = s; + } + + return ret; +} + + +/*! + * \brief Returns the TEXT node value of the first child matching tag. + */ +const std::string CUPnPLib::Element_GetChildValueByTag( + IXML_Element *element, + const DOMString tag) const +{ + IXML_Element *child = + Element_GetFirstChildByTag(element, tag); + + return Element_GetTextValue(child); +} + + +/*! + * \brief Returns the first child element that matches the requested tag or + * NULL if not found. + */ +IXML_Element *CUPnPLib::Element_GetFirstChildByTag( + IXML_Element *element, + const DOMString tag) const +{ + if (!element || !tag) { + return NULL; + } + + IXML_Node *node = REINTERPRET_CAST(IXML_Node *)(element); + IXML_Node *child = ixmlNode_getFirstChild(node); + const DOMString childTag = ixmlNode_getNodeName(child); + while(child && childTag && strcmp(tag, childTag)) { + child = ixmlNode_getNextSibling(child); + childTag = ixmlNode_getNodeName(child); + } + + return REINTERPRET_CAST(IXML_Element *)(child); +} + + +/*! + * \brief Returns the next sibling element that matches the requested tag. Should be + * used with the return value of Element_GetFirstChildByTag(). + */ +IXML_Element *CUPnPLib::Element_GetNextSiblingByTag( + IXML_Element *element, const DOMString tag) const +{ + if (!element || !tag) { + return NULL; + } + + IXML_Node *child = REINTERPRET_CAST(IXML_Node *)(element); + const DOMString childTag = NULL; + do { + child = ixmlNode_getNextSibling(child); + childTag = ixmlNode_getNodeName(child); + } while(child && childTag && strcmp(tag, childTag)); + + return REINTERPRET_CAST(IXML_Element *)(child); +} + + +const std::string CUPnPLib::Element_GetAttributeByTag( + IXML_Element *element, const DOMString tag) const +{ + IXML_NamedNodeMap *NamedNodeMap = ixmlNode_getAttributes( + REINTERPRET_CAST(IXML_Node *)(element)); + IXML_Node *attribute = ixmlNamedNodeMap_getNamedItem(NamedNodeMap, tag); + const DOMString s = ixmlNode_getNodeValue(attribute); + std::string ret; + if (s) { + ret = s; + } + ixmlNamedNodeMap_free(NamedNodeMap); + + return ret; +} + + +CUPnPError::CUPnPError( + const CUPnPLib &upnpLib, + IXML_Document *errorDoc) +: +m_root (upnpLib.Element_GetRootElement(errorDoc)), +m_ErrorCode (upnpLib.Element_GetChildValueByTag(m_root, "errorCode")), +m_ErrorDescription(upnpLib.Element_GetChildValueByTag(m_root, "errorDescription")) +{ +} + + +CUPnPArgument::CUPnPArgument( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *argument, + const std::string &SCPDURL) +: +m_UPnPControlPoint(upnpControlPoint), +m_name (upnpLib.Element_GetChildValueByTag(argument, "name")), +m_direction (upnpLib.Element_GetChildValueByTag(argument, "direction")), +m_retval (upnpLib.Element_GetFirstChildByTag(argument, "retval")), +m_relatedStateVariable(upnpLib.Element_GetChildValueByTag(argument, "relatedStateVariable")) +{ + +#ifdef UPNP_DEBUG + std::cerr << "CUPnPArgument::CUPnPArgument() \n Argument:" << + "\n name: " << m_name << + "\n direction: " << m_direction << + "\n retval: " << m_retval << + "\n relatedStateVariable: " << m_relatedStateVariable; + std::cerr << std::endl; +#endif +} + + +CUPnPAction::CUPnPAction( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *action, + const std::string &SCPDURL) +: +m_UPnPControlPoint(upnpControlPoint), +m_ArgumentList(upnpControlPoint, upnpLib, action, SCPDURL), +m_name(upnpLib.Element_GetChildValueByTag(action, "name")) +{ +#ifdef UPNP_DEBUG + std::cerr << "CUPnPAction::CUPnPAction() \n Action:" << + "\n name: " << m_name; + std::cerr << std::endl; +#endif +} + + +CUPnPAllowedValue::CUPnPAllowedValue( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *allowedValue, + const std::string &SCPDURL) +: +m_UPnPControlPoint(upnpControlPoint), +m_allowedValue(upnpLib.Element_GetTextValue(allowedValue)) +{ +#ifdef UPNP_DEBUG + std::cerr << "CUPnPAllowedValue::CUPnPAllowedValue() \n AllowedValue:" << + "\n allowedValue: " << m_allowedValue; + std::cerr << std::endl; +#endif +} + + +CUPnPStateVariable::CUPnPStateVariable( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *stateVariable, + const std::string &SCPDURL) +: +m_UPnPControlPoint(upnpControlPoint), +m_AllowedValueList(upnpControlPoint, upnpLib, stateVariable, SCPDURL), +m_name (upnpLib.Element_GetChildValueByTag(stateVariable, "name")), +m_dataType (upnpLib.Element_GetChildValueByTag(stateVariable, "dataType")), +m_defaultValue(upnpLib.Element_GetChildValueByTag(stateVariable, "defaultValue")), +m_sendEvents (upnpLib.Element_GetAttributeByTag (stateVariable, "sendEvents")) +{ +#ifdef UPNP_DEBUG + std::cerr << "CUPnPStateVariable::CUPnPStateVariable() \n StateVariable:" << + "\n name: " << m_name << + "\n dataType: " << m_dataType << + "\n defaultValue: " << m_defaultValue << + "\n sendEvents: " << m_sendEvents; + std::cerr << std::endl; +#endif +} + + +CUPnPSCPD::CUPnPSCPD( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *scpd, + const std::string &SCPDURL) +: +m_UPnPControlPoint(upnpControlPoint), +m_ActionList(upnpControlPoint, upnpLib, scpd, SCPDURL), +m_ServiceStateTable(upnpControlPoint, upnpLib, scpd, SCPDURL), +m_SCPDURL(SCPDURL) +{ +} + + +CUPnPArgumentValue::CUPnPArgumentValue() +: +m_argument(), +m_value() +{ +} + + +CUPnPArgumentValue::CUPnPArgumentValue( + const std::string &argument, const std::string &value) +: +m_argument(argument), +m_value(value) +{ +} + + +CUPnPService::CUPnPService( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *service, + const std::string &URLBase) +: +m_UPnPControlPoint(upnpControlPoint), +m_upnpLib(upnpLib), +m_serviceType(upnpLib.Element_GetChildValueByTag(service, "serviceType")), +m_serviceId (upnpLib.Element_GetChildValueByTag(service, "serviceId")), +m_SCPDURL (upnpLib.Element_GetChildValueByTag(service, "SCPDURL")), +m_controlURL (upnpLib.Element_GetChildValueByTag(service, "controlURL")), +m_eventSubURL(upnpLib.Element_GetChildValueByTag(service, "eventSubURL")), +m_timeout(1801), +m_SCPD(NULL) +{ + std::ostringstream msg; + int errcode; + + std::vector vscpdURL(URLBase.length() + m_SCPDURL.length() + 1); + char *scpdURL = &vscpdURL[0]; + errcode = UpnpResolveURL( + URLBase.c_str(), + m_SCPDURL.c_str(), + scpdURL); + if( errcode != UPNP_E_SUCCESS ) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::CUPnPService() Error generating scpdURL from " << + "|" << URLBase << "|" << + m_SCPDURL << "|."; + std::cerr << std::endl; +#endif + } else { + m_absSCPDURL = scpdURL; + } + + std::vector vcontrolURL( + URLBase.length() + m_controlURL.length() + 1); + char *controlURL = &vcontrolURL[0]; + errcode = UpnpResolveURL( + URLBase.c_str(), + m_controlURL.c_str(), + controlURL); + if( errcode != UPNP_E_SUCCESS ) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::CUPnPService() Error generating controlURL from " << + "|" << URLBase << "|" << + m_controlURL << "|."; + std::cerr << std::endl; +#endif + } else { + m_absControlURL = controlURL; + } + + std::vector veventURL( + URLBase.length() + m_eventSubURL.length() + 1); + char *eventURL = &veventURL[0]; + errcode = UpnpResolveURL( + URLBase.c_str(), + m_eventSubURL.c_str(), + eventURL); + if( errcode != UPNP_E_SUCCESS ) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::CUPnPService() Error generating eventURL from " << + "|" << URLBase << "|" << + m_eventSubURL << "|."; + std::cerr << std::endl; +#endif + } else { + m_absEventSubURL = eventURL; + } + +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::CUPnPService() \n Service:" << + "\n serviceType: " << m_serviceType << + "\n serviceId: " << m_serviceId << + "\n SCPDURL: " << m_SCPDURL << + "\n absSCPDURL: " << m_absSCPDURL << + "\n controlURL: " << m_controlURL << + "\n absControlURL: " << m_absControlURL << + "\n eventSubURL: " << m_eventSubURL << + "\n absEventSubURL: " << m_absEventSubURL; + std::cerr << std::endl; +#endif + + if (m_serviceType == upnpLib.UPNP_SERVICE_WAN_IP_CONNECTION || + m_serviceType == upnpLib.UPNP_SERVICE_WAN_PPP_CONNECTION) { +#if 0 + m_serviceType == upnpLib.UPNP_SERVICE_WAN_PPP_CONNECTION || + m_serviceType == upnpLib.UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG || + m_serviceType == upnpLib.UPNP_SERVICE_LAYER3_FORWARDING) { +#endif +#if 0 +//#warning Delete this code on release. + if (!upnpLib.m_ctrlPoint.WanServiceDetected()) { + // This condition can be used to suspend the parse + // of the XML tree. +#endif +//#warning Delete this code when m_WanService is no longer used. + upnpLib.m_ctrlPoint.SetWanService(this); + // Log it + msg.str(""); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::CUPnPService() WAN Service Detected: '" << + m_serviceType << "'."; + std::cerr << std::endl; +#endif + // Subscribe + upnpLib.m_ctrlPoint.Subscribe(*this); +#if 0 +//#warning Delete this code on release. + } else { + msg.str(""); +#ifdef UPNP_DEBUG + std::cerr << "WAN service detected again: '" << + m_serviceType << + "'. Will only use the first instance."; + std::cerr << std::endl; +#endif + } +#endif + } else { + msg.str(""); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::CUPnPService() Uninteresting service detected: '" << + m_serviceType << "'. Ignoring."; + std::cerr << std::endl; +#endif + } +} + + +CUPnPService::~CUPnPService() +{ +} + + +bool CUPnPService::Execute( + const std::string &ActionName, + const std::vector &ArgValue) const +{ +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() called." << std::endl; +#endif + if (m_SCPD.get() == NULL) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() Service without SCPD Document, cannot execute action '" << ActionName << + "' for service '" << GetServiceType() << "'."; + std::cerr << std::endl; +#endif + return false; + } +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() Sending action " << std::endl; +#endif + // Check for correct action name + ActionList::const_iterator itAction = + m_SCPD->GetActionList().find(ActionName); + if (itAction == m_SCPD->GetActionList().end()) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() invalid action name '" << ActionName << + "' for service '" << GetServiceType() << "'."; + std::cerr << std::endl; +#endif + return false; + } +#ifdef UPNP_DEBUG + std::cerr << ActionName << "("; +#endif + bool firstTime = true; + // Check for correct Argument/Value pairs + const CUPnPAction &action = *(itAction->second); + for (unsigned int i = 0; i < ArgValue.size(); ++i) { + ArgumentList::const_iterator itArg = + action.GetArgumentList().find(ArgValue[i].GetArgument()); + if (itArg == action.GetArgumentList().end()) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() Invalid argument name '" << ArgValue[i].GetArgument() << + "' for action '" << action.GetName() << + "' for service '" << GetServiceType() << "'."; + std::cerr << std::endl; +#endif + return false; + } + const CUPnPArgument &argument = *(itArg->second); + if (tolower(argument.GetDirection()[0]) != 'i' || + tolower(argument.GetDirection()[1]) != 'n') { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() Invalid direction for argument '" << + ArgValue[i].GetArgument() << + "' for action '" << action.GetName() << + "' for service '" << GetServiceType() << "'."; + std::cerr << std::endl; +#endif + return false; + } + const std::string relatedStateVariableName = + argument.GetRelatedStateVariable(); + if (!relatedStateVariableName.empty()) { + ServiceStateTable::const_iterator itSVT = + m_SCPD->GetServiceStateTable(). + find(relatedStateVariableName); + if (itSVT == m_SCPD->GetServiceStateTable().end()) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() Inconsistent Service State Table, did not find '" << + relatedStateVariableName << + "' for argument '" << argument.GetName() << + "' for action '" << action.GetName() << + "' for service '" << GetServiceType() << "'."; + std::cerr << std::endl; +#endif + return false; + } + const CUPnPStateVariable &stateVariable = *(itSVT->second); + if ( !stateVariable.GetAllowedValueList().empty() && + stateVariable.GetAllowedValueList().find(ArgValue[i].GetValue()) == + stateVariable.GetAllowedValueList().end()) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() Value not allowed '" << ArgValue[i].GetValue() << + "' for state variable '" << relatedStateVariableName << + "' for argument '" << argument.GetName() << + "' for action '" << action.GetName() << + "' for service '" << GetServiceType() << "'."; +#endif + + return false; + } + } + if (firstTime) { + firstTime = false; + } else { +#ifdef UPNP_DEBUG + std::cerr << ", "; +#endif + } +#ifdef UPNP_DEBUG + std::cerr << + ArgValue[i].GetArgument() << + "='" << + ArgValue[i].GetValue() << + "'"; +#endif + } +#ifdef UPNP_DEBUG + std::cerr << ")" << std::endl; +#endif + // Everything is ok, make the action + IXML_Document *ActionDoc = NULL; + if (ArgValue.size()) { + for (unsigned int i = 0; i < ArgValue.size(); ++i) { + int ret = UpnpAddToAction( + &ActionDoc, + action.GetName().c_str(), + GetServiceType().c_str(), + ArgValue[i].GetArgument().c_str(), + ArgValue[i].GetValue().c_str()); + if (ret != UPNP_E_SUCCESS) { + m_upnpLib.processUPnPErrorMessage( + "UpnpAddToAction", ret, NULL, NULL); + return false; + } + } + } else { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() UpnpMakeAction" << std::endl; +#endif + ActionDoc = UpnpMakeAction( + action.GetName().c_str(), + GetServiceType().c_str(), + 0, NULL); + if (!ActionDoc) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::Execute() Error: UpnpMakeAction returned NULL." << std::endl; +#endif + return false; + } + } + + // Send the action asynchronously + UpnpSendActionAsync( + m_UPnPControlPoint.GetUPnPClientHandle(), + GetAbsControlURL().c_str(), + GetServiceType().c_str(), + NULL, ActionDoc, + static_cast(&CUPnPControlPoint::Callback), + NULL); + return true; +} + + +const std::string CUPnPService::GetStateVariable( + const std::string &stateVariableName) +{ + std::map::iterator it; + it = propertyMap.find(stateVariableName); + if (it != propertyMap.end()) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::GetStateVariable(" << stateVariableName << ") = " << (*it).second << std::endl; +#endif + return (*it).second; + } else { + //property map is not populated with the specified value. + //we will try to get it with an event + + //this getvar is just to make the event happening + DOMString StVarVal; + UpnpGetServiceVarStatus( + m_UPnPControlPoint.GetUPnPClientHandle(), + GetAbsControlURL().c_str(), + stateVariableName.c_str(), + &StVarVal); + if (StVarVal != NULL) { + std::string varValue = std::string(StVarVal); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::GetStateVariable() varValue returned by UpnpGetServiceVarStatus : " << varValue << std::endl; +#endif + return varValue; + } else { + //use event to get state variable +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::GetStateVariable() pausing in case of an UPnP event incomming."; +#endif + time_t begin_time = time(NULL); + while (true) { + if (time(NULL) - begin_time > 7) { + break; + } + } + } + + //propertyMap should be populated by nom + it = propertyMap.find(stateVariableName); + if (it != propertyMap.end()) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::GetStateVariable(" << stateVariableName << ") = " << (*it).second << std::endl; +#endif + return (*it).second; + } else { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPService::GetStateVariable(" << stateVariableName << ") = " << "Empty String" << std::endl; +#endif + return stdEmptyString; + } + } +} + + +CUPnPDevice::CUPnPDevice( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *device, + const std::string &URLBase) +: +m_UPnPControlPoint(upnpControlPoint), +m_DeviceList(upnpControlPoint, upnpLib, device, URLBase), +m_ServiceList(upnpControlPoint, upnpLib, device, URLBase), +m_deviceType (upnpLib.Element_GetChildValueByTag(device, "deviceType")), +m_friendlyName (upnpLib.Element_GetChildValueByTag(device, "friendlyName")), +m_manufacturer (upnpLib.Element_GetChildValueByTag(device, "manufacturer")), +m_manufacturerURL (upnpLib.Element_GetChildValueByTag(device, "manufacturerURL")), +m_modelDescription (upnpLib.Element_GetChildValueByTag(device, "modelDescription")), +m_modelName (upnpLib.Element_GetChildValueByTag(device, "modelName")), +m_modelNumber (upnpLib.Element_GetChildValueByTag(device, "modelNumber")), +m_modelURL (upnpLib.Element_GetChildValueByTag(device, "modelURL")), +m_serialNumber (upnpLib.Element_GetChildValueByTag(device, "serialNumber")), +m_UDN (upnpLib.Element_GetChildValueByTag(device, "UDN")), +m_UPC (upnpLib.Element_GetChildValueByTag(device, "UPC")), +m_presentationURL (upnpLib.Element_GetChildValueByTag(device, "presentationURL")) +{ + std::ostringstream msg; + int presURLlen = strlen(URLBase.c_str()) + + strlen(m_presentationURL.c_str()) + 2; + std::vector vpresURL(presURLlen); + char* presURL = &vpresURL[0]; + int errcode = UpnpResolveURL( + URLBase.c_str(), + m_presentationURL.c_str(), + presURL); + if (errcode != UPNP_E_SUCCESS) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPDevice::CUPnPDevice() Error generating presentationURL from " << + "|" << URLBase << "|" << + m_presentationURL << "|."; + std::cerr << std::endl; +#endif + } else { + m_presentationURL = presURL; + } + + msg.str(""); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPDevice::CUPnPDevice() \n Device: " << + "\n friendlyName: " << m_friendlyName << + "\n deviceType: " << m_deviceType << + "\n manufacturer: " << m_manufacturer << + "\n manufacturerURL: " << m_manufacturerURL << + "\n modelDescription: " << m_modelDescription << + "\n modelName: " << m_modelName << + "\n modelNumber: " << m_modelNumber << + "\n modelURL: " << m_modelURL << + "\n serialNumber: " << m_serialNumber << + "\n UDN: " << m_UDN << + "\n UPC: " << m_UPC << + "\n presentationURL: " << m_presentationURL + << std::endl; +#endif +} + + +CUPnPRootDevice::CUPnPRootDevice( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *rootDevice, + const std::string &OriginalURLBase, + const std::string &FixedURLBase, + const char *location, + int expires) +: +CUPnPDevice(upnpControlPoint, upnpLib, rootDevice, FixedURLBase), +m_UPnPControlPoint(upnpControlPoint), +m_URLBase(OriginalURLBase), +m_location(location), +m_expires(expires) +{ +#ifdef UPNP_DEBUG + std::cerr << + "CUPnPRootDevice::CUPnPRootDevice() \n Root Device: " << + "\n URLBase: " << m_URLBase << + "\n Fixed URLBase: " << FixedURLBase << + "\n location: " << m_location << + "\n expires: " << m_expires + << std::endl; +#endif +} + + +CUPnPControlPoint *CUPnPControlPoint::s_CtrlPoint = NULL; + + +CUPnPControlPoint::CUPnPControlPoint(unsigned short udpPort) +: +m_upnpLib(*this), +m_UPnPClientHandle(), +m_RootDeviceMap(), +m_ServiceMap(), +m_ActivePortMappingsMap(), +m_RootDeviceListMutex(), +m_IGWDeviceDetected(false), +m_WanService(NULL) +{ +#ifdef UPNP_DEBUG + std::cerr << "UPnPControlPoint::CUPnPControlPoint() Constructor" << std::endl; +#endif + // Pointer to self + s_CtrlPoint = this; + + // Start UPnP + int ret; + char *ipAddress = NULL; + unsigned short port = 0; +#ifdef UPNP_DEBUG + int resLog = UpnpInitLog(); + std::cerr << "UPnPControlPoint::CUPnPControlPoint() Init log : " << resLog << std::endl; +#endif + ret = UpnpInit(ipAddress, udpPort); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint Constructor UpnpInit finished" << std::endl; +#endif + if (ret != UPNP_E_SUCCESS && ret !=UPNP_E_INIT) { +#ifdef UPNP_DEBUG + std::cerr << "UPnPControlPoint::CUPnPControlPoint() error(UpnpInit): Error code : "; +#endif + goto error; + } + port = UpnpGetServerPort(); + ipAddress = UpnpGetServerIpAddress(); +#ifdef UPNP_DEBUG + std::cerr << "UPnPControlPoint::CUPnPControlPoint() bound to " << ipAddress << ":" << + port << "." << std::endl; +#endif + + ret = UpnpRegisterClient( + static_cast(&CUPnPControlPoint::Callback), + &m_UPnPClientHandle, + &m_UPnPClientHandle); + if (ret != UPNP_E_SUCCESS) { +#ifdef UPNP_DEBUG + std::cerr << "UPnPControlPoint::CUPnPControlPoint() error(UpnpRegisterClient): Error registering callback: "; +#endif + goto error; + } + + // We could ask for just the right device here. If the root device + // contains the device we want, it will respond with the full XML doc, + // including the root device and every sub-device it has. + // + // But lets find out what we have in our network by calling UPNP_ROOT_DEVICE. + // + // We should not search twice, because this will produce two + // UPNP_DISCOVERY_SEARCH_TIMEOUT events, and we might end with problems + // on the mutex. +// UpnpSetContentLength(m_UPnPClientHandle, 5000000); +// UpnpSetMaxContentLength(5000000); + ret = UpnpSearchAsync(m_UPnPClientHandle, 20, m_upnpLib.UPNP_DEVICE_IGW.c_str(), NULL); + //ret = UpnpSearchAsync(m_UPnPClientHandle, 3, m_upnpLib.UPNP_DEVICE_IGW.c_str(), this); + //ret = UpnpSearchAsync(m_UPnPClientHandle, 3, m_upnpLib.UPNP_DEVICE_LAN.c_str(), this); + //ret = UpnpSearchAsync(m_UPnPClientHandle, 3, m_upnpLib.UPNP_DEVICE_WAN_CONNECTION.c_str(), this); + if (ret != UPNP_E_SUCCESS) { +#ifdef UPNP_DEBUG + std::cerr << "UPnPControlPoint::CUPnPControlPoint() error(UpnpSearchAsync): Error sending search request: "; +#endif + goto error; + } + + // Wait for the UPnP initialization to complete. + { + // Lock the search timeout mutex + m_WaitForSearchTimeoutMutex.lock(); + + // Lock it again, so that we block. Unlocking will only happen + // when the UPNP_DISCOVERY_SEARCH_TIMEOUT event occurs at the + // callback. +#ifdef UPNP_DEBUG + std::cerr << "UPnPControlPoint::CUPnPControlPoint() blocking m_WaitForSearchTimeoutMutex." << std::endl; +#endif + //RsMutex toto(m_WaitForSearchTimeoutMutex); + m_WaitForSearchTimeoutMutex.lock(); +#ifdef UPNP_DEBUG + std::cerr << "UPnPControlPoint::CUPnPControlPoint() m_WaitForSearchTimeoutMutex blocking finished." << std::endl; +#endif + } + + //clean the PortMappingNumberOfEntries as it is erroneus on the first event with the french neufbox + if (WanServiceDetected()) { + m_WanService->propertyMap.erase("PortMappingNumberOfEntries"); + } + +#ifdef UPNP_DEBUG + std::cerr << "UPnPControlPoint::CUPnPControlPoint() CUPnPControlPoint Constructor finished" << std::endl; +#endif + return; + + // Error processing +error: +#ifdef UPNP_DEBUG + std::cerr << ret << ": " << m_upnpLib.GetUPnPErrorMessage(ret) << "." << std::endl; +#endif + UpnpFinish(); +#ifdef UPNP_DEBUG + std::cerr << "UPnPControlPoint::CUPnPControlPoint() UpnpFinish called within CUPnPControlPoint constructor." << std::endl; +#endif + return; +} + + +char* CUPnPControlPoint::getInternalIpAddress() +{ + char * addr = UpnpGetServerIpAddress(); + if (addr == NULL) { + addr = new char[10] ; + sprintf(addr,"%s","127.0.0.1"); + } + return addr; +} + +CUPnPControlPoint::~CUPnPControlPoint() +{ + for( RootDeviceMap::iterator it = m_RootDeviceMap.begin(); + it != m_RootDeviceMap.end(); + ++it) { + delete it->second; + } + // Remove all first + // RemoveAll(); + UpnpUnRegisterClient(m_UPnPClientHandle); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::~CUPnPControlPoint() UpnpFinish called within CUPnPControlPoint destructor." << std::endl; +#endif + UpnpFinish(); +} + + +bool CUPnPControlPoint::AddPortMappings( + std::vector &upnpPortMapping) +{ + if (!WanServiceDetected()) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::AddPortMappings() UPnP Error: " + "CUPnPControlPoint::AddPortMapping: " + "WAN Service not detected." << std::endl; +#endif + return false; + } +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::AddPortMappings() called." << std::endl; +#endif + + int n = upnpPortMapping.size(); + bool ok = false; + + // Check the number of port mappings before + //have a little break in case we just modified the variable, so we have to wait for an event +// std::cerr << "GetStateVariable pausing in case of an UPnP event incomming."; +// time_t begin_time = time(NULL); +// while (true) { +// if (time(NULL) - begin_time > 7) { +// break; +// } +// } + std::istringstream OldPortMappingNumberOfEntries( + m_WanService->GetStateVariable( + "PortMappingNumberOfEntries")); + int oldNumberOfEntries; + OldPortMappingNumberOfEntries >> oldNumberOfEntries; + + // Add the enabled port mappings + for (int i = 0; i < n; ++i) { + if (upnpPortMapping[i].getEnabled() == "1") { + // Add the mapping to the control point + // active mappings list + m_ActivePortMappingsMap[upnpPortMapping[i].getKey()] = + upnpPortMapping[i]; + + // Add the port mapping + PrivateAddPortMapping(upnpPortMapping[i]); + } + } + + // Not very good, must find a better test : check the new number of port entries + //have a little break in case we just modified the variable, so we have to wait for an event +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::AddPortMappings() GetStateVariable pausing in case of an UPnP event incomming."; +#endif + time_t begin_time = time(NULL); + while (true) { + if (time(NULL) - begin_time > 4) { + break; + } + } + std::istringstream NewPortMappingNumberOfEntries( + m_WanService->GetStateVariable( + "PortMappingNumberOfEntries")); + int newNumberOfEntries; + NewPortMappingNumberOfEntries >> newNumberOfEntries; +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::AddPortMappings() CUPnPControlPoint::AddPortMappings() newNumberOfEntries - oldNumberOfEntries : " << (newNumberOfEntries - oldNumberOfEntries) << std::endl; +#endif + ok = newNumberOfEntries - oldNumberOfEntries >= 1; + +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::AddPortMappings() finished. Success = " << ok << std::endl; +#endif + + return ok; +} + +std::string CUPnPControlPoint::getExternalAddress() +{ + if (!WanServiceDetected()) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::getExternalAddress() UPnP Error: " + "CUPnPControlPoint::AddPortMapping: " + "WAN Service not detected." << std::endl; +#endif + return ""; + } + std::string result = m_WanService->GetStateVariable("NewExternalIPAddress"); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::getExternalAddress() m_WanService->GetStateVariable(NewExternalIPAddress) = " << result << std::endl; +#endif + if (result == "") { + PrivateGetExternalIpAdress(); + result = m_WanService->GetStateVariable("NewExternalIPAddress"); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::getExternalAddress() m_WanService->GetStateVariable(NewExternalIPAddress) = " << result << std::endl; +#endif + if (result == "") { + result = m_WanService->GetStateVariable("ExternalIPAddress"); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::getExternalAddress() m_WanService->GetStateVariable(ExternalIPAddress) = " << result << std::endl; +#endif + } + } + return result; +} + +void CUPnPControlPoint::RefreshPortMappings() +{ + for ( PortMappingMap::iterator it = m_ActivePortMappingsMap.begin(); + it != m_ActivePortMappingsMap.end(); + ++it) { + PrivateAddPortMapping(it->second); + } +} + + +bool CUPnPControlPoint::PrivateAddPortMapping( + CUPnPPortMapping &upnpPortMapping) +{ + // Get an IP address. The UPnP server one must do. + std::string ipAddress(UpnpGetServerIpAddress()); + + // Start building the action + std::string actionName("AddPortMapping"); + std::vector argval(8); + + // Action parameters + argval[0].SetArgument("NewRemoteHost"); + argval[0].SetValue(""); + argval[1].SetArgument("NewExternalPort"); + argval[1].SetValue(upnpPortMapping.getExPort()); + argval[2].SetArgument("NewProtocol"); + argval[2].SetValue(upnpPortMapping.getProtocol()); + argval[3].SetArgument("NewInternalPort"); + argval[3].SetValue(upnpPortMapping.getInPort()); + argval[4].SetArgument("NewInternalClient"); + argval[4].SetValue(ipAddress); + argval[5].SetArgument("NewEnabled"); + argval[5].SetValue("1"); + argval[6].SetArgument("NewPortMappingDescription"); + argval[6].SetValue(upnpPortMapping.getDescription()); + argval[7].SetArgument("NewLeaseDuration"); + argval[7].SetValue("0"); + + // Execute + bool ret = true; + for (ServiceMap::iterator it = m_ServiceMap.begin(); + it != m_ServiceMap.end(); ++it) { + ret &= it->second->Execute(actionName, argval); + } + + return ret; +} + + +bool CUPnPControlPoint::DeletePortMappings( + std::vector &upnpPortMapping) +{ +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::DeletePortMappings() called." << std::endl; +#endif + if (!WanServiceDetected()) { +#ifdef UPNP_DEBUG + std::cerr << "UPnP Error: " + "CUPnPControlPoint::DeletePortMapping: " + "WAN Service not detected." << std::endl; +#endif + return false; + } + + int n = upnpPortMapping.size(); + + // Delete the enabled port mappings + for (int i = 0; i < n; ++i) { + if (upnpPortMapping[i].getEnabled() == "1") { + // Delete the mapping from the control point + // active mappings list + PortMappingMap::iterator it = + m_ActivePortMappingsMap.find( + upnpPortMapping[i].getKey()); + if (it != m_ActivePortMappingsMap.end()) { + m_ActivePortMappingsMap.erase(it); + } else { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::DeletePortMappings() UPnP Error: " + "CUPnPControlPoint::DeletePortMapping: " + "Mapping was not found in the active " + "mapping map." << std::endl; +#endif + } + + // Delete the port mapping + PrivateDeletePortMapping(upnpPortMapping[i]); + } + } + + return true; +} + + +bool CUPnPControlPoint::PrivateDeletePortMapping( + CUPnPPortMapping &upnpPortMapping) +{ + // Start building the action + std::string actionName("DeletePortMapping"); + std::vector argval(3); + + // Action parameters + argval[0].SetArgument("NewRemoteHost"); + argval[0].SetValue(""); + argval[1].SetArgument("NewExternalPort"); + argval[1].SetValue(upnpPortMapping.getExPort()); + argval[2].SetArgument("NewProtocol"); + argval[2].SetValue(upnpPortMapping.getProtocol()); + + // Execute + bool ret = true; + for (ServiceMap::iterator it = m_ServiceMap.begin(); + it != m_ServiceMap.end(); ++it) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::PrivateDeletePortMapping() Sending a delete port mapping action." << std::endl; +#endif + ret &= it->second->Execute(actionName, argval); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::PrivateDeletePortMapping() Delete port mapping action finished." << std::endl; +#endif + } + + return ret; +} + +bool CUPnPControlPoint::PrivateGetExternalIpAdress() +{ + // Start building the action + std::string actionName("GetExternalIPAddress"); + std::vector argval(0); + + // Execute + bool ret = true; + for (ServiceMap::iterator it = m_ServiceMap.begin(); + it != m_ServiceMap.end(); ++it) { + ret &= it->second->Execute(actionName, argval); + } + + return ret; +} + + +// This function is static +int CUPnPControlPoint::Callback(Upnp_EventType EventType, void *Event, void * /*Cookie*/) +{ + std::ostringstream msg; + std::ostringstream msg2; + // Somehow, this is unreliable. UPNP_DISCOVERY_ADVERTISEMENT_ALIVE events + // happen with a wrong cookie and... boom! + // CUPnPControlPoint *upnpCP = static_cast(Cookie); + CUPnPControlPoint *upnpCP = CUPnPControlPoint::s_CtrlPoint; + + //fprintf(stderr, "Callback: %d, Cookie: %p\n", EventType, Cookie); + switch (EventType) { + case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE: +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() UPNP_DISCOVERY_ADVERTISEMENT_ALIVE: "; +#endif + goto upnpDiscovery; + case UPNP_DISCOVERY_SEARCH_RESULT: { +#ifdef UPNP_DEBUG + std::cerr << "UPNP_DISCOVERY_SEARCH_RESULT: "; +#endif + // UPnP Discovery +upnpDiscovery: + struct Upnp_Discovery *d_event = (struct Upnp_Discovery *)Event; + IXML_Document *doc = NULL; + int ret; + if (d_event->ErrCode != UPNP_E_SUCCESS) { +#ifdef UPNP_DEBUG + std::cerr << upnpCP->m_upnpLib.GetUPnPErrorMessage(d_event->ErrCode) << "." << std::endl; +#endif + } +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() URetrieving device description from " << + d_event->Location << "." << std::endl; +#endif + // Get the XML tree device description in doc + ret = UpnpDownloadXmlDoc(d_event->Location, &doc); + if (ret != UPNP_E_SUCCESS) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() UError retrieving device description from " << + d_event->Location << ": " << + upnpCP->m_upnpLib.GetUPnPErrorMessage(ret) << "."; +#endif + } else { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() URetrieving device description from " << + d_event->Location << "." << std::endl; +#endif + } + if (doc) { + // Get the root node + IXML_Element *root = + upnpCP->m_upnpLib.Element_GetRootElement(doc); + // Extract the URLBase + const std::string urlBase = upnpCP->m_upnpLib. + Element_GetChildValueByTag(root, "URLBase"); + // Get the root device + IXML_Element *rootDevice = upnpCP->m_upnpLib. + Element_GetFirstChildByTag(root, "device"); + // Extract the deviceType + std::string devType(upnpCP->m_upnpLib. + Element_GetChildValueByTag(rootDevice, "deviceType")); + // Only add device if it is an InternetGatewayDevice + if (stdStringIsEqualCI(devType, upnpCP->m_upnpLib.UPNP_DEVICE_IGW)) { + // This condition can be used to auto-detect + // the UPnP device we are interested in. + // Obs.: Don't block the entry here on this + // condition! There may be more than one device, + // and the first that enters may not be the one + // we are interested in! + upnpCP->SetIGWDeviceDetected(true); + // Log it if not UPNP_DISCOVERY_ADVERTISEMENT_ALIVE, + // we don't want to spam our logs. + //if (EventType != UPNP_DISCOVERY_ADVERTISEMENT_ALIVE) { +#ifdef UPNP_DEBUG + std::cerr << "Internet Gateway Device Detected." << std::endl; +#endif + //} +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() UGetting root device desc." << std::endl; +#endif + // Add the root device to our list + upnpCP->AddRootDevice(rootDevice, urlBase, + d_event->Location, d_event->Expires); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() UFinishing getting root device desc." << std::endl; +#endif + } + // Free the XML doc tree + ixmlDocument_free(doc); + } + break; + } + case UPNP_DISCOVERY_SEARCH_TIMEOUT: { + //fprintf(stderr, "Callback: UPNP_DISCOVERY_SEARCH_TIMEOUT\n"); + // Search timeout +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() UUPNP_DISCOVERY_SEARCH_TIMEOUT : unlocking mutex." << std::endl; +#endif + + // Unlock the search timeout mutex + upnpCP->m_WaitForSearchTimeoutMutex.unlock(); + + break; + } + case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE: { + //fprintf(stderr, "Callback: UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE\n"); + // UPnP Device Removed + struct Upnp_Discovery *dab_event = (struct Upnp_Discovery *)Event; + if (dab_event->ErrCode != UPNP_E_SUCCESS) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() Uerror(UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE): " << + upnpCP->m_upnpLib.GetUPnPErrorMessage(dab_event->ErrCode) << + "." << std::endl; +#endif + } + std::string devType = dab_event->DeviceType; + // Check for an InternetGatewayDevice and removes it from the list + std::transform(devType.begin(), devType.end(), devType.begin(), tolower); + if (stdStringIsEqualCI(devType, upnpCP->m_upnpLib.UPNP_DEVICE_IGW)) { + upnpCP->RemoveRootDevice(dab_event->DeviceId); + } + break; + } + case UPNP_EVENT_RECEIVED: { +#ifdef UPNP_DEBUG + fprintf(stderr, "Callback: UPNP_EVENT_RECEIVED\n"); +#endif + // Event reveived + struct Upnp_Event *e_event = (struct Upnp_Event *)Event; + const std::string Sid = e_event->Sid; + // Parses the event + upnpCP->OnEventReceived(Sid, e_event->EventKey, e_event->ChangedVariables); + break; + } + case UPNP_EVENT_SUBSCRIBE_COMPLETE: + //fprintf(stderr, "Callback: UPNP_EVENT_SUBSCRIBE_COMPLETE\n"); + msg << "error(UPNP_EVENT_SUBSCRIBE_COMPLETE): "; + goto upnpEventRenewalComplete; + case UPNP_EVENT_UNSUBSCRIBE_COMPLETE: + //fprintf(stderr, "Callback: UPNP_EVENT_UNSUBSCRIBE_COMPLETE\n"); + msg << "error(UPNP_EVENT_UNSUBSCRIBE_COMPLETE): "; + goto upnpEventRenewalComplete; + case UPNP_EVENT_RENEWAL_COMPLETE: { + //fprintf(stderr, "Callback: UPNP_EVENT_RENEWAL_COMPLETE\n"); + msg << "error(UPNP_EVENT_RENEWAL_COMPLETE): "; +upnpEventRenewalComplete: + struct Upnp_Event_Subscribe *es_event = + (struct Upnp_Event_Subscribe *)Event; + if (es_event->ErrCode != UPNP_E_SUCCESS) { + msg << "Error in Event Subscribe Callback"; + upnpCP->m_upnpLib.processUPnPErrorMessage( + msg.str(), es_event->ErrCode, NULL, NULL); + } else { +#if 0 + TvCtrlPointHandleSubscribeUpdate( + es_event->PublisherUrl, + es_event->Sid, + es_event->TimeOut ); +#endif + } + + break; + } + + case UPNP_EVENT_AUTORENEWAL_FAILED: + //fprintf(stderr, "Callback: UPNP_EVENT_AUTORENEWAL_FAILED\n"); + msg << "CUPnPControlPoint::Callback() error(UPNP_EVENT_AUTORENEWAL_FAILED): "; + msg2 << "UPNP_EVENT_AUTORENEWAL_FAILED: "; + goto upnpEventSubscriptionExpired; + case UPNP_EVENT_SUBSCRIPTION_EXPIRED: { + //fprintf(stderr, "Callback: UPNP_EVENT_SUBSCRIPTION_EXPIRED\n"); + msg << "CUPnPControlPoint::Callback() error(UPNP_EVENT_SUBSCRIPTION_EXPIRED): "; + msg2 << "UPNP_EVENT_SUBSCRIPTION_EXPIRED: "; +upnpEventSubscriptionExpired: + struct Upnp_Event_Subscribe *es_event = + (struct Upnp_Event_Subscribe *)Event; + Upnp_SID newSID; + int TimeOut = 1801; + int ret = UpnpSubscribe( + upnpCP->m_UPnPClientHandle, + es_event->PublisherUrl, + &TimeOut, + newSID); + if (ret != UPNP_E_SUCCESS) { + msg << "Error Subscribing to EventURL"; + upnpCP->m_upnpLib.processUPnPErrorMessage( + msg.str(), es_event->ErrCode, NULL, NULL); + } else { + ServiceMap::iterator it = + upnpCP->m_ServiceMap.find(es_event->PublisherUrl); + if (it != upnpCP->m_ServiceMap.end()) { + CUPnPService &service = *(it->second); + service.SetTimeout(TimeOut); + service.SetSID(newSID); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() Re-subscribed to EventURL '" << + es_event->PublisherUrl << + "' with SID == '" << + newSID << "'." << std::endl; +#endif + // In principle, we should test to see if the + // service is the same. But here we only have one + // service, so... + upnpCP->RefreshPortMappings(); + } else { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() Error: did not find service " << + newSID << " in the service map." << std::endl; +#endif + } + } + break; + } + case UPNP_CONTROL_ACTION_COMPLETE: { + //fprintf(stderr, "Callback: UPNP_CONTROL_ACTION_COMPLETE\n"); + // This is here if we choose to do this asynchronously + struct Upnp_Action_Complete *a_event = + (struct Upnp_Action_Complete *)Event; + if (a_event->ErrCode != UPNP_E_SUCCESS) { + upnpCP->m_upnpLib.processUPnPErrorMessage( + "UpnpSendActionAsync", + a_event->ErrCode, NULL, + a_event->ActionResult); + } else { + // Check the response document + upnpCP->m_upnpLib.ProcessActionResponse( + a_event->ActionResult, + ""); + } + /* No need for any processing here, just print out results. + * Service state table updates are handled by events. + */ + break; + } + case UPNP_CONTROL_GET_VAR_COMPLETE: { +#ifdef UPNP_DEBUG + fprintf(stderr, "CUPnPControlPoint::Callback() Callback: UPNP_CONTROL_GET_VAR_COMPLETE\n"); +#endif + msg << "CUPnPControlPoint::Callback() error(UPNP_CONTROL_GET_VAR_COMPLETE): "; + struct Upnp_State_Var_Complete *sv_event = + (struct Upnp_State_Var_Complete *)Event; + if (sv_event->ErrCode != UPNP_E_SUCCESS) { + msg << "m_UpnpGetServiceVarStatusAsync"; + upnpCP->m_upnpLib.processUPnPErrorMessage( + msg.str(), sv_event->ErrCode, NULL, NULL); + } else { + //add the variable to the wanservice property map + (upnpCP->m_WanService->propertyMap)[std::string(sv_event->StateVarName)] = std::string(sv_event->CurrentVal); + } + break; + } + // ignore these cases, since this is not a device + case UPNP_CONTROL_GET_VAR_REQUEST: + //fprintf(stderr, "Callback: UPNP_CONTROL_GET_VAR_REQUEST\n"); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() error(UPNP_CONTROL_GET_VAR_REQUEST): "; +#endif + goto eventSubscriptionRequest; + case UPNP_CONTROL_ACTION_REQUEST: + //fprintf(stderr, "Callback: UPNP_CONTROL_ACTION_REQUEST\n"); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() error(UPNP_CONTROL_ACTION_REQUEST): "; +#endif + goto eventSubscriptionRequest; + case UPNP_EVENT_SUBSCRIPTION_REQUEST: + //fprintf(stderr, "Callback: UPNP_EVENT_SUBSCRIPTION_REQUEST\n"); +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() error(UPNP_EVENT_SUBSCRIPTION_REQUEST): "; +#endif +eventSubscriptionRequest: +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Callback() This is not a UPnP Device, this is a UPnP Control Point, event ignored." << std::endl; +#endif + break; + default: + // Humm, this is not good, we forgot to handle something... +#ifdef UPNP_DEBUG + fprintf(stderr, + "Callback: default... Unknown event:'%d', not good.\n", + EventType); + std::cerr << "CUPnPControlPoint::Callback() error(UPnP::Callback): Event not handled:'" << + EventType << "'." << std::endl; +#endif + // Better not throw in the callback. Who would catch it? + //throw CUPnPException(msg); + break; + } + + return 0; +} + + +void CUPnPControlPoint::OnEventReceived( + const std::string &Sid, + int EventKey, + IXML_Document *ChangedVariablesDoc) +{ +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::OnEventReceived() UPNP_EVENT_RECEIVED:" << + "\n SID: " << Sid << + "\n Key: " << EventKey << std::endl; + std::cerr << "CUPnPControlPoint::OnEventReceived() m_WanService->GetServiceId() : " << m_WanService->GetSID() << std::endl; +#endif + + if (m_WanService->GetSID() == Sid) { + //let's store the properties if it is an event of the wan device +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::OnEventReceived() \n Property list:"; +#endif + + IXML_Element *root = + m_upnpLib.Element_GetRootElement(ChangedVariablesDoc); + IXML_Element *child = + m_upnpLib.Element_GetFirstChild(root); + if (child) { + while (child) { + IXML_Element *child2 = + m_upnpLib.Element_GetFirstChild(child); + const DOMString childTag = + m_upnpLib.Element_GetTag(child2); + std::string childValue = + m_upnpLib.Element_GetTextValue(child2); +#ifdef UPNP_DEBUG + std::cerr << "\n " << + childTag << "='" << + childValue << "'"; +#endif + const std::string cTag(childTag); + const std::string cValue(childValue); + (m_WanService->propertyMap)[cTag] = cValue; + child = m_upnpLib.Element_GetNextSibling(child); + } + } else { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::OnEventReceived() \n Empty property list."; +#endif + } +#ifdef UPNP_DEBUG + std::cerr << std::endl; +#endif + // Freeing that doc segfaults. Probably should not be freed. + //ixmlDocument_free(ChangedVariablesDoc); + } +} + + +void CUPnPControlPoint::AddRootDevice( + IXML_Element *rootDevice, const std::string &urlBase, + const char *location, int expires) +{ + // Lock the Root Device List + RsMutex toto(m_RootDeviceListMutex); + + // Root node's URLBase + std::string OriginalURLBase(urlBase); + std::string FixedURLBase(OriginalURLBase.empty() ? + location : + OriginalURLBase); + + // Get the UDN (Unique Device Name) + std::string UDN( + m_upnpLib.Element_GetChildValueByTag(rootDevice, "UDN")); + RootDeviceMap::iterator it = m_RootDeviceMap.find(UDN); + bool alreadyAdded = it != m_RootDeviceMap.end(); + if (alreadyAdded) { + // Just set the expires field + it->second->SetExpires(expires); + } else { + // Add a new root device to the root device list + CUPnPRootDevice *upnpRootDevice = new CUPnPRootDevice( + *this, m_upnpLib, rootDevice, + OriginalURLBase, FixedURLBase, + location, expires); + m_RootDeviceMap[upnpRootDevice->GetUDN()] = upnpRootDevice; + } +} + + +void CUPnPControlPoint::RemoveRootDevice(const char *udn) +{ + // Lock the Root Device List + RsMutex toto(m_RootDeviceListMutex); + + // Remove + std::string UDN(udn); + RootDeviceMap::iterator it = m_RootDeviceMap.find(UDN); + if (it != m_RootDeviceMap.end()) { + delete it->second; + m_RootDeviceMap.erase(UDN); + } +} + + +void CUPnPControlPoint::Subscribe(CUPnPService &service) +{ + + IXML_Document *scpdDoc = NULL; + int errcode = UpnpDownloadXmlDoc( + service.GetAbsSCPDURL().c_str(), &scpdDoc); + if (errcode == UPNP_E_SUCCESS) { + // Get the root node of this service (the SCPD Document) + IXML_Element *scpdRoot = + m_upnpLib.Element_GetRootElement(scpdDoc); + CUPnPSCPD *scpd = new CUPnPSCPD(*this, m_upnpLib, + scpdRoot, service.GetAbsSCPDURL()); + service.SetSCPD(scpd); + m_ServiceMap[service.GetAbsEventSubURL()] = &service; +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Subscribe() Successfully retrieved SCPD Document for service " << + service.GetServiceType() << ", absEventSubURL: " << + service.GetAbsEventSubURL() << "." << std::endl; +#endif + + // Now try to subscribe to this service. If the subscription + // is not successfull, we will not be notified about events, + // but it may be possible to use the service anyway. + errcode = UpnpSubscribe(m_UPnPClientHandle, + service.GetAbsEventSubURL().c_str(), + service.GetTimeoutAddr(), + service.GetSID()); + if (errcode == UPNP_E_SUCCESS) { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Subscribe() Successfully subscribed to service " << + service.GetServiceType() << ", absEventSubURL: " << + service.GetAbsEventSubURL() << "." << std::endl; +#endif + } else { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Subscribe() Error subscribing to service " << + service.GetServiceType() << ", absEventSubURL: " << + service.GetAbsEventSubURL() << ", error: " << + m_upnpLib.GetUPnPErrorMessage(errcode) << "."; +#endif + goto error; + } + } else { +#ifdef UPNP_DEBUG + std::cerr << "CUPnPControlPoint::Subscribe() Error getting SCPD Document from " << + service.GetAbsSCPDURL() << "." << std::endl; +#endif + } + + return; + +error: + ; +#ifdef UPNP_DEBUG + std::cerr << std::endl; +#endif +} + + +void CUPnPControlPoint::Unsubscribe(CUPnPService &service) +{ + ServiceMap::iterator it = m_ServiceMap.find(service.GetAbsEventSubURL()); + if (it != m_ServiceMap.end()) { + m_ServiceMap.erase(it); + UpnpUnSubscribe(m_UPnPClientHandle, service.GetSID()); + } +} + + +// File_checked_for_headers diff --git a/libretroshare/src/upnp/UPnPBase.h b/libretroshare/src/upnp/UPnPBase.h new file mode 100644 index 000000000..799933115 --- /dev/null +++ b/libretroshare/src/upnp/UPnPBase.h @@ -0,0 +1,629 @@ +// +// This file is part of the aMule Project. +// +// Copyright (c) 2004-2009 Marcelo Roberto Jimenez ( phoenix@amule.org ) +// Copyright (c) 2006-2009 aMule Team ( admin@amule.org / http://www.amule.org ) +// Copyright (c) 2009-2010 Retroshare Team +// +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// You are also granted to use it with the LGPL License +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License or the LGPL +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +// + +//This file uses libupnp + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "util/rsthreads.h" + +#include +#include + +#ifdef UPNP_C + std::string stdEmptyString; +#else // UPNP_C + extern std::string stdEmptyString; +#endif // UPNP_C + + +/** + * Case insensitive std::string comparison + */ +bool stdStringIsEqualCI( + const std::string &s1, + const std::string &s2); + + +class CUPnPPortMapping +{ +private: + std::string m_ex_port; + std::string m_in_port; + std::string m_protocol; + std::string m_enabled; + std::string m_description; + std::string m_key; + +public: + CUPnPPortMapping( + int in_port = 0, + int ex_port = 0, + const std::string &protocol = stdEmptyString, + bool enabled = false, + const std::string &description = stdEmptyString); + ~CUPnPPortMapping() {} + + const std::string &getExPort() const + { return m_ex_port; } + const std::string &getInPort() const + { return m_in_port; } + const std::string &getProtocol() const + { return m_protocol; } + const std::string &getEnabled() const + { return m_enabled; } + const std::string &getDescription() const + { return m_description; } + const std::string &getKey() const + { return m_key; } +}; + + +class CUPnPControlPoint; + + +class CUPnPLib +{ +public: + static const std::string &UPNP_ROOT_DEVICE; + static const std::string &UPNP_DEVICE_IGW; + static const std::string &UPNP_DEVICE_WAN; + static const std::string &UPNP_DEVICE_WAN_CONNECTION; + static const std::string &UPNP_DEVICE_LAN; + static const std::string &UPNP_SERVICE_LAYER3_FORWARDING; + static const std::string &UPNP_SERVICE_WAN_COMMON_INTERFACE_CONFIG; + static const std::string &UPNP_SERVICE_WAN_IP_CONNECTION; + static const std::string &UPNP_SERVICE_WAN_PPP_CONNECTION; + CUPnPControlPoint &m_ctrlPoint; + +public: + CUPnPLib(CUPnPControlPoint &ctrlPoint); + ~CUPnPLib() {} + + // Convenience function so we don't have to write explicit calls + // to char2unicode every time + std::string GetUPnPErrorMessage(int code) const; + + // Convenience function to avoid repetitive processing of error + // messages + std::string processUPnPErrorMessage( + const std::string &messsage, + int code, + const DOMString errorString, + IXML_Document *doc) const; + + // Processing response to actions + void ProcessActionResponse( + IXML_Document *RespDoc, + const std::string &actionName) const; + + // IXML_Element + IXML_Element *Element_GetRootElement( + IXML_Document *doc) const; + IXML_Element *Element_GetFirstChild( + IXML_Element *parent) const; + IXML_Element *Element_GetNextSibling( + IXML_Element *child) const; + const DOMString Element_GetTag( + IXML_Element *element) const; + const std::string Element_GetTextValue( + IXML_Element *element) const; + const std::string Element_GetChildValueByTag( + IXML_Element *element, + const DOMString tag) const; + IXML_Element *Element_GetFirstChildByTag( + IXML_Element *element, + const DOMString tag) const; + IXML_Element *Element_GetNextSiblingByTag( + IXML_Element *element, + const DOMString tag) const; + const std::string Element_GetAttributeByTag( + IXML_Element *element, + const DOMString tag) const; +}; + + +class CUPnPControlPoint; + +/* + * Even though we can retrieve the upnpLib handler from the upnpControlPoint, + * we must pass it separetly at this point, because the class CUPnPControlPoint + * must be declared after. + * + * CUPnPLib can only be removed from the constructor once we agree to link to + * UPnPLib explicitly, making this dlopen() stuff unnecessary. + */ +template +class CXML_List : public std::map +{ +public: + CXML_List( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *parent, + const std::string &url); + ~CXML_List(); +}; + + +template +CXML_List::CXML_List( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *parent, + const std::string &url) +{ + IXML_Element *elementList = + upnpLib.Element_GetFirstChildByTag(parent, XML_LIST_NAME); + unsigned int i = 0; + for ( IXML_Element *element = upnpLib.Element_GetFirstChildByTag(elementList, XML_ELEMENT_NAME); + element; + element = upnpLib.Element_GetNextSiblingByTag(element, XML_ELEMENT_NAME)) { + // Add a new element to the element list + T *upnpElement = new T(upnpControlPoint, upnpLib, element, url); + (*this)[upnpElement->GetKey()] = upnpElement; + ++i; + } + std::ostringstream msg; + msg << "\n " << XML_LIST_NAME << ": " << + i << " " << XML_ELEMENT_NAME << "s."; + std::cerr << msg; +} + + +template +CXML_List::~CXML_List() +{ + typename CXML_List::iterator it; + for(it = this->begin(); it != this->end(); ++it) { + delete (*it).second; + } +} + +extern const char s_argument[]; +extern const char s_argumentList[]; +extern const char s_action[]; +extern const char s_actionList[]; +extern const char s_allowedValue[]; +extern const char s_allowedValueList[]; +extern const char s_stateVariable[]; +extern const char s_serviceStateTable[]; +extern const char s_service[]; +extern const char s_serviceList[]; +extern const char s_device[]; +extern const char s_deviceList[]; + +#ifdef UPNP_C + const char s_argument[] = "argument"; + const char s_argumentList[] = "argumentList"; + const char s_action[] = "action"; + const char s_actionList[] = "actionList"; + const char s_allowedValue[] = "allowedValue"; + const char s_allowedValueList[] = "allowedValueList"; + const char s_stateVariable[] = "stateVariable"; + const char s_serviceStateTable[] = "serviceStateTable"; + const char s_service[] = "service"; + const char s_serviceList[] = "serviceList"; + const char s_device[] = "device"; + const char s_deviceList[] = "deviceList"; +#endif // UPNP_C + + +class CUPnPArgument; +typedef CXML_List ArgumentList; +class CUPnPAction; +typedef CXML_List ActionList; +class CUPnPStateVariable; +typedef CXML_List ServiceStateTable; +class CUPnPAllowedValue; +typedef CXML_List AllowedValueList; +class CUPnPService; +typedef CXML_List ServiceList; +class CUPnPDevice; +typedef CXML_List DeviceList; + + +class CUPnPError +{ +private: + IXML_Element *m_root; + const std::string m_ErrorCode; + const std::string m_ErrorDescription; +public: + CUPnPError( + const CUPnPLib &upnpLib, + IXML_Document *errorDoc); + ~CUPnPError() {} + const std::string &getErrorCode() const + { return m_ErrorCode; } + const std::string &getErrorDescription() const + { return m_ErrorDescription; } +}; + + +class CUPnPArgument +{ +private: + const CUPnPControlPoint &m_UPnPControlPoint; + const std::string m_name; + const std::string m_direction; + bool m_retval; + const std::string m_relatedStateVariable; + +public: + CUPnPArgument( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *argument, + const std::string &SCPDURL); + ~CUPnPArgument() {} + const std::string &GetName() const + { return m_name; } + const std::string &GetDirection() const + { return m_direction; } + bool GetRetVal() const + { return m_retval; } + const std::string &GetRelatedStateVariable() const + { return m_relatedStateVariable; } + const std::string &GetKey() const + { return m_name; } +}; + + + +class CUPnPAction +{ +private: + const CUPnPControlPoint &m_UPnPControlPoint; + ArgumentList m_ArgumentList; + const std::string m_name; + +public: + CUPnPAction( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *action, + const std::string &SCPDURL); + ~CUPnPAction() {} + const std::string &GetName() const + { return m_name; } + const std::string &GetKey() const + { return m_name; } + const ArgumentList &GetArgumentList() const + { return m_ArgumentList; } +}; + + +class CUPnPAllowedValue +{ +private: + const CUPnPControlPoint &m_UPnPControlPoint; + const std::string m_allowedValue; + +public: + CUPnPAllowedValue( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *allowedValue, + const std::string &SCPDURL); + ~CUPnPAllowedValue() {} + const std::string &GetAllowedValue() const + { return m_allowedValue; } + const std::string &GetKey() const + { return m_allowedValue; } +}; + + +class CUPnPStateVariable +{ +private: + const CUPnPControlPoint &m_UPnPControlPoint; + AllowedValueList m_AllowedValueList; + const std::string m_name; + const std::string m_dataType; + const std::string m_defaultValue; + const std::string m_sendEvents; + +public: + CUPnPStateVariable( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *stateVariable, + const std::string &URLBase); + ~CUPnPStateVariable() {} + const std::string &GetNname() const + { return m_name; } + const std::string &GetDataType() const + { return m_dataType; } + const std::string &GetDefaultValue() const + { return m_defaultValue; } + const std::string &GetKey() const + { return m_name; } + const AllowedValueList &GetAllowedValueList() const + { return m_AllowedValueList; } +}; + + +class CUPnPSCPD +{ +private: + const CUPnPControlPoint &m_UPnPControlPoint; + ActionList m_ActionList; + ServiceStateTable m_ServiceStateTable; + const std::string m_SCPDURL; + +public: + CUPnPSCPD( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *scpd, + const std::string &SCPDURL); + ~CUPnPSCPD() {} + const ActionList &GetActionList() const + { return m_ActionList; } + const ServiceStateTable &GetServiceStateTable() const + { return m_ServiceStateTable; } +}; + + +class CUPnPArgumentValue +{ +private: + std::string m_argument; + std::string m_value; + +public: + CUPnPArgumentValue(); + CUPnPArgumentValue(const std::string &argument, const std::string &value); + ~CUPnPArgumentValue() {} + + const std::string &GetArgument() const { return m_argument; } + const std::string &GetValue() const { return m_value; } + const std::string &SetArgument(const std::string& argument) { return m_argument = argument; } + const std::string &SetValue(const std::string &value) { return m_value = value; } +}; + + +class CUPnPService +{ +private: + const CUPnPControlPoint &m_UPnPControlPoint; + CUPnPLib &m_upnpLib; + const std::string m_serviceType; + const std::string m_serviceId; + const std::string m_SCPDURL; + const std::string m_controlURL; + const std::string m_eventSubURL; + std::string m_absSCPDURL; + std::string m_absControlURL; + std::string m_absEventSubURL; + int m_timeout; + Upnp_SID m_SID; + std::auto_ptr m_SCPD; + +public: + std::map propertyMap; + CUPnPService( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *service, + const std::string &URLBase); + ~CUPnPService(); + + const std::string &GetServiceType() const + { return m_serviceType; } + const std::string &GetServiceId() const + { return m_serviceId; } + const std::string &GetSCPDURL() const + { return m_SCPDURL; } + const std::string &GetAbsSCPDURL() const + { return m_absSCPDURL; } + const std::string &GetControlURL() const + { return m_controlURL; } + const std::string &GetEventSubURL() const + { return m_eventSubURL; } + const std::string &GetAbsControlURL() const + { return m_absControlURL; } + const std::string &GetAbsEventSubURL() const + { return m_absEventSubURL; } + int GetTimeout() const + { return m_timeout; } + void SetTimeout(int t) + { m_timeout = t; } + int *GetTimeoutAddr() + { return &m_timeout; } + char *GetSID() + { return m_SID; } + void SetSID(const char *s) + { memcpy(m_SID, s, sizeof(Upnp_SID)); } + const std::string &GetKey() const + { return m_serviceId; } + bool IsSubscribed() const + { return m_SCPD.get() != NULL; } + void SetSCPD(CUPnPSCPD *SCPD) + { m_SCPD.reset(SCPD); } + + bool Execute( + const std::string &ActionName, + const std::vector &ArgValue) const; + const std::string GetStateVariable( + const std::string &stateVariableName); + +}; + + +class CUPnPDevice +{ +private: + const CUPnPControlPoint &m_UPnPControlPoint; + + // Please, lock these lists before use + DeviceList m_DeviceList; + ServiceList m_ServiceList; + + const std::string m_deviceType; + const std::string m_friendlyName; + const std::string m_manufacturer; + const std::string m_manufacturerURL; + const std::string m_modelDescription; + const std::string m_modelName; + const std::string m_modelNumber; + const std::string m_modelURL; + const std::string m_serialNumber; + const std::string m_UDN; + const std::string m_UPC; + std::string m_presentationURL; + +public: + CUPnPDevice( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *device, + const std::string &URLBase); + ~CUPnPDevice() {} + + const std::string &GetUDN() const + { return m_UDN; } + const std::string &GetDeviceType() const + { return m_deviceType; } + const std::string &GetFriendlyName() const + { return m_friendlyName; } + const std::string &GetPresentationURL() const + { return m_presentationURL; } + const std::string &GetKey() const + { return m_UDN; } +}; + + +class CUPnPRootDevice : public CUPnPDevice +{ +private: + const CUPnPControlPoint &m_UPnPControlPoint; + const std::string m_URLBase; + const std::string m_location; + int m_expires; + +public: + CUPnPRootDevice( + const CUPnPControlPoint &upnpControlPoint, + CUPnPLib &upnpLib, + IXML_Element *rootDevice, + const std::string &OriginalURLBase, + const std::string &FixedURLBase, + const char *location, + int expires); + ~CUPnPRootDevice() {} + + const std::string &GetURLBase() const + { return m_URLBase; } + const std::string &GetLocation() const + { return m_location; } + int GetExpires() const + { return m_expires; } + void SetExpires(int expires) + { m_expires = expires; } +}; + + +typedef std::map RootDeviceMap; +typedef std::map ServiceMap; +typedef std::map PortMappingMap; + + +class CUPnPControlPoint +{ +private: + // upnp stuff + CUPnPLib m_upnpLib; + UpnpClient_Handle m_UPnPClientHandle; + RootDeviceMap m_RootDeviceMap; + ServiceMap m_ServiceMap; + PortMappingMap m_ActivePortMappingsMap; + RsMutex m_RootDeviceListMutex; + bool m_IGWDeviceDetected; + RsMutex m_WaitForSearchTimeoutMutex; + +public: + CUPnPService *m_WanService; + std::string m_getStateVariableLastResult; + static CUPnPControlPoint *s_CtrlPoint; + CUPnPControlPoint(unsigned short udpPort); + ~CUPnPControlPoint(); + char* getInternalIpAddress(); + std::string getExternalAddress(); + void Subscribe(CUPnPService &service); + void Unsubscribe(CUPnPService &service); + bool AddPortMappings( + std::vector &upnpPortMapping); + bool DeletePortMappings( + std::vector &upnpPortMapping); + + UpnpClient_Handle GetUPnPClientHandle() const + { return m_UPnPClientHandle; } + + bool GetIGWDeviceDetected() const + { return m_IGWDeviceDetected; } + void SetIGWDeviceDetected(bool b) + { m_IGWDeviceDetected = b; } + bool WanServiceDetected() const + { return !m_ServiceMap.empty(); } + void SetWanService(CUPnPService *service) + { m_WanService = service; } + + // Callback function + static int Callback( + Upnp_EventType EventType, + void* Event, + void* Cookie); + void OnEventReceived( + const std::string &Sid, + int EventKey, + IXML_Document *ChangedVariables); + +private: + void AddRootDevice( + IXML_Element *rootDevice, + const std::string &urlBase, + const char *location, + int expires); + void RemoveRootDevice( + const char *udn); + void RefreshPortMappings(); + bool PrivateAddPortMapping( + CUPnPPortMapping &upnpPortMapping); + bool PrivateDeletePortMapping( + CUPnPPortMapping &upnpPortMapping); + bool PrivateGetExternalIpAdress(); +}; + +// File_checked_for_headers diff --git a/libretroshare/src/upnp/upnphandler.cc b/libretroshare/src/upnp/upnphandler.cc new file mode 100644 index 000000000..2772c81a7 --- /dev/null +++ b/libretroshare/src/upnp/upnphandler.cc @@ -0,0 +1,1005 @@ +//Linux only +#if !defined(WINDOWS_SYS) && !defined(__APPLE__) + +/* This stuff is actually C */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern C */ +#endif +/* This stuff is actually C */ + +#include "upnp/upnphandler.h" + +#include "util/rsnet.h" + +bool upnphandler::initUPnPState() +{ + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState" << std::endl; + #endif + cUPnPControlPoint = new CUPnPControlPoint(2000); + + bool IGWDetected = cUPnPControlPoint->GetIGWDeviceDetected(); + + if (IGWDetected) { + /* MODIFY STATE */ + dataMtx.lock(); /* LOCK MUTEX */ + upnpState = RS_UPNP_S_READY; + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState cUPnPControlPoint internal ip adress : "; + std::cerr << cUPnPControlPoint->getInternalIpAddress() << std::endl; + #endif + + //const char ipaddr = cUPnPControlPoint->getInternalIpAddress().c_str(); + inet_aton(cUPnPControlPoint->getInternalIpAddress(), &(upnp_iaddr.sin_addr)); + upnp_iaddr.sin_port = htons(iport); + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState READY" << std::endl; + #endif + dataMtx.unlock(); /* UNLOCK MUTEX */ + + } else { + upnpState = RS_UPNP_S_UNAVAILABLE; + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::initUPnPState UNAVAILABLE" << std::endl; + #endif + } + + return 0; +} + +class upnpThreadData +{ + public: + upnphandler *handler; + bool start; + bool stop; +}; + + /* Thread routines */ +extern "C" void* doSetupUPnP(void* p) +{ + #ifdef UPNP_DEBUG + std::cerr << "doSetupUPnP Creating upnp thread." << std::endl; + #endif + upnpThreadData *data = (upnpThreadData *) p; + if ((!data) || (!data->handler)) + { + pthread_exit(NULL); + } + + /* publish it! */ + if (data -> stop) + { + data->handler->shutdown_upnp(); + } + + if (data -> start) + { + data->handler->initUPnPState(); + data->handler->start_upnp(); + } + + delete data; + pthread_exit(NULL); + + return NULL; +} + +bool upnphandler::background_setup_upnp(bool start, bool stop) +{ + pthread_t tid; + + /* launch thread */ + #ifdef UPNP_DEBUG + std::cerr << "background_setup_upnp Creating upnp thread." << std::endl; + #endif + upnpThreadData *data = new upnpThreadData(); + data->handler = this; + data->start = start; + data->stop = stop; + + pthread_create(&tid, 0, &doSetupUPnP, (void *) data); + pthread_detach(tid); /* so memory is reclaimed in linux */ + + return true; +} + +bool upnphandler::start_upnp() +{ + if (!(upnpState >= RS_UPNP_S_READY)) + { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::start_upnp() Not Ready" << std::endl; + #endif + return false; + } + + struct sockaddr_in localAddr; + { + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + /* if we're to load -> load */ + /* select external ports */ + eport_curr = eport; + if (!eport_curr) + { + /* use local port if eport is zero */ + eport_curr = iport; + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::start_upnp() Using LocalPort for extPort." << std::endl; + #endif + } + + if (!eport_curr) + { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::start_upnp() Invalid eport ... " << std::endl; + #endif + return false; + } + + /* our port */ + char in_addr[256]; + char in_port1[256]; + + upnp_iaddr.sin_port = htons(iport); + localAddr = upnp_iaddr; + uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); + snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); + snprintf(in_addr, 256, "%d.%d.%d.%d", + ((linaddr >> 24) & 0xff), + ((linaddr >> 16) & 0xff), + ((linaddr >> 8) & 0xff), + ((linaddr >> 0) & 0xff)); + + #ifdef UPNP_DEBUG + std::cerr << "Attempting Redirection: InAddr: " << in_addr; + std::cerr << " InPort: " << in_port1; + std::cerr << " ePort: " << eport_curr; + std::cerr << " eProt: " << "TCP and UDP"; + std::cerr << std::endl; + #endif + } + + //first of all, build the mappings + std::vector upnpPortMapping1; + CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "TCP", true, "tcp retroshare redirection"); + upnpPortMapping1.push_back(cUPnPPortMapping1); + std::vector upnpPortMapping2; + CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, ntohs(localAddr.sin_port), "UDP", true, "udp retroshare redirection"); + upnpPortMapping2.push_back(cUPnPPortMapping2); + + //attempt to remove formal port redirection rules + cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); + cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); + + //add new rules + bool res = cUPnPControlPoint->AddPortMappings(upnpPortMapping1); + bool res2 = cUPnPControlPoint->AddPortMappings(upnpPortMapping2); + + struct sockaddr_in extAddr; + bool extAddrResult = getExternalAddress(extAddr); + + { + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + if (extAddrResult && (res || res2)) { + upnpState = RS_UPNP_S_ACTIVE; + } else { + upnpState = RS_UPNP_S_TCP_AND_FAILED; + } + + toStart = false; + } + + return (upnpState == RS_UPNP_S_ACTIVE); + +} + +bool upnphandler::shutdown_upnp() +{ + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + /* always attempt this (unless no port number) */ + if (eport_curr > 0 && eport > 0 && (upnpState >= RS_UPNP_S_ACTIVE)) + { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; + std::cerr << " Prot: TCP"; + std::cerr << std::endl; + #endif + + std::vector upnpPortMapping1; + CUPnPPortMapping cUPnPPortMapping1 = CUPnPPortMapping(eport_curr, 0, "TCP", true, "tcp redirection"); + upnpPortMapping1.push_back(cUPnPPortMapping1); + cUPnPControlPoint->DeletePortMappings(upnpPortMapping1); + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown_upnp() : Attempting To Remove Redirection: port: " << eport_curr; + std::cerr << " Prot: UDP"; + std::cerr << std::endl; + #endif + + std::vector upnpPortMapping2; + CUPnPPortMapping cUPnPPortMapping2 = CUPnPPortMapping(eport_curr, 0, "UDP", true, "udp redirection"); + upnpPortMapping2.push_back(cUPnPPortMapping2); + cUPnPControlPoint->DeletePortMappings(upnpPortMapping2); + + //destroy the upnp object + cUPnPControlPoint->~CUPnPControlPoint(); + } else { + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown_upnp() : avoid upnp connection for shutdonws because probably a net flag went down." << std::endl; + #endif + } + + //stopping os ok, set starting to true for next net reset + toStop = false; + toStart = true; + upnpState = RS_UPNP_S_UNINITIALISED; + + return true; + +} + +/************************ External Interface ***************************** + * + * + * + */ + +upnphandler::upnphandler() + : + upnpState(RS_UPNP_S_UNINITIALISED), + cUPnPControlPoint(NULL), + toEnable(false), toStart(false), toStop(false), + iport(0),eport(0), eport_curr(0) +{ +} + +upnphandler::~upnphandler() +{ + return; +} + + /* RsIface */ +void upnphandler::enable(bool active) +{ + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::enable called with argument active : " << active << std::endl; + std::cerr << "toEnable : " << toEnable << std::endl; + std::cerr << "toStart : " << toStart << std::endl; + #endif + + dataMtx.lock(); /*** LOCK MUTEX ***/ + if (active != toEnable) + { + if (active) + { + toStart = true; + } + else + { + toStop = true; + } + } + toEnable = active; + + bool start = toStart; + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + if (start) + { + /* make background thread to startup UPnP */ + background_setup_upnp(true, false); + } +} + + +void upnphandler::shutdown() +{ + /* blocking call to shutdown upnp */ + + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::shutdown() called." << std::endl; + #endif + shutdown_upnp(); +} + + +void upnphandler::restart() +{ + /* non-blocking call to shutdown upnp, and startup again. */ + #ifdef UPNP_DEBUG + std::cerr << "upnphandler::restart() called." << std::endl; + #endif + background_setup_upnp(true, true); +} + + + +bool upnphandler::getEnabled() +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + + bool on = toEnable; + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return on; +} + +bool upnphandler::getActive() +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + + #ifdef UPNP_DEBUG + std::cerr <<"upnphandler::getActive() result : " << (upnpState == RS_UPNP_S_ACTIVE) << std::endl; + #endif + + bool on = (upnpState == RS_UPNP_S_ACTIVE); + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return on; +} + + /* the address that the listening port is on */ +void upnphandler::setInternalPort(unsigned short iport_in) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + if (iport != iport_in) + { + iport = iport_in; + if ((toEnable) && + (upnpState == RS_UPNP_S_ACTIVE)) + { + toStop = true; + toStart = true; + } + } + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ +} + +void upnphandler::setExternalPort(unsigned short eport_in) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + /* flag both shutdown/start -> for restart */ + if (eport != eport_in) + { + eport = eport_in; + if ((toEnable) && + (upnpState == RS_UPNP_S_ACTIVE)) + { + toStop = true; + toStart = true; + } + } + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ +} + + /* as determined by uPnP */ +bool upnphandler::getInternalAddress(struct sockaddr_in &addr) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + addr = upnp_iaddr; + bool valid = (upnpState >= RS_UPNP_S_ACTIVE); + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return valid; +} + +bool upnphandler::getExternalAddress(struct sockaddr_in &addr) +{ + std::string externalAdress = cUPnPControlPoint->getExternalAddress(); + + if(!externalAdress.empty() && externalAdress != "") + { + const char* externalIPAddress = externalAdress.c_str(); + + #ifdef UPNP_DEBUG + std::cerr << " upnphandler::getExternalAddress() : " << externalIPAddress; + std::cerr << ":" << eport_curr; + std::cerr << std::endl; + #endif + + dataMtx.lock(); /*** LOCK MUTEX ***/ + sockaddr_clear(&upnp_eaddr); + inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); + upnp_eaddr.sin_family = AF_INET; + upnp_eaddr.sin_port = htons(eport_curr); + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + addr = upnp_eaddr; + return true; + } + else + { + return false; + } +} +#endif + + + +// Windows / Mac version. +#if defined(WINDOWS_SYS) || defined(__APPLE__) + +/* This stuff is actually C */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} /* extern C */ +#endif +/* This stuff is actually C */ + +#include "upnp/upnphandler.h" +#include "upnp/upnputil.h" + +class uPnPConfigData +{ + public: + struct UPNPDev * devlist; + struct UPNPUrls urls; + struct IGDdatas data; + char lanaddr[16]; /* my ip address on the LAN */ +}; + +#include +#include + +#include "util/rsnet.h" + +bool upnphandler::initUPnPState() +{ + /* allocate memory */ + uPnPConfigData *upcd = new uPnPConfigData; + +#if MINIUPNPC_VERSION >= 11 + /* Starting from version 1.1, miniupnpc api has a new parameter (int sameport) */ + upcd->devlist = upnpDiscover(2000, NULL, NULL, 0); +#else + upcd->devlist = upnpDiscover(2000, NULL, NULL); +#endif + + if(upcd->devlist) + { + struct UPNPDev * device; + printf("List of UPNP devices found on the network :\n"); + for(device=upcd->devlist;device;device=device->pNext) + { + printf("\n desc: %s\n st: %s\n", + device->descURL, device->st); + } + putchar('\n'); + if(UPNP_GetValidIGD(upcd->devlist, &(upcd->urls), + &(upcd->data), upcd->lanaddr, + sizeof(upcd->lanaddr))) + { + printf("Found valid IGD : %s\n", + upcd->urls.controlURL); + printf("Local LAN ip address : %s\n", + upcd->lanaddr); + + /* MODIFY STATE */ + dataMtx.lock(); /* LOCK MUTEX */ + + /* convert to ipaddress. */ + inet_aton(upcd->lanaddr, &(upnp_iaddr.sin_addr)); + upnp_iaddr.sin_port = htons(iport); + + upnpState = RS_UPNP_S_READY; + if (upnpConfig) + { + delete upnpConfig; + } + upnpConfig = upcd; /* */ + + dataMtx.unlock(); /* UNLOCK MUTEX */ + + + /* done -> READY */ + return 1; + + } + else + { + fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n"); + } + + + freeUPNPDevlist(upcd->devlist); + upcd->devlist = 0; + } + else + { + fprintf(stderr, "No IGD UPnP Device found on the network !\n"); + } + + /* MODIFY STATE */ + dataMtx.lock(); /* LOCK MUTEX */ + + upnpState = RS_UPNP_S_UNAVAILABLE; + delete upcd; + upnpConfig = NULL; + + dataMtx.unlock(); /* UNLOCK MUTEX */ + + /* done, FAILED -> NOT AVAILABLE */ + + return 0; +} + +bool upnphandler::printUPnPState() +{ + std::cerr << "upnphandler::printUPnPState() ... locking"; + std::cerr << std::endl; + + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + std::cerr << "upnphandler::printUPnPState() ... locked"; + std::cerr << std::endl; + + uPnPConfigData *config = upnpConfig; + if ((upnpState >= RS_UPNP_S_READY) && (config)) + { + DisplayInfos(&(config -> urls), &(config->data)); + GetConnectionStatus(&(config -> urls), &(config->data)); + ListRedirections(&(config -> urls), &(config->data)); + } + else + { + std::cerr << "UPNP not Ready" << std::endl; + } + + return 1; +} + + +bool upnphandler::checkUPnPActive() +{ + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + uPnPConfigData *config = upnpConfig; + if ((upnpState > RS_UPNP_S_READY) && (config)) + { + char eprot1[] = "TCP"; + char eprot2[] = "UDP"; + + char in_addr[256]; + char in_port1[256]; + char in_port2[256]; + char eport1[256]; + char eport2[256]; + + struct sockaddr_in localAddr = upnp_iaddr; + uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); + + snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); + snprintf(in_port2, 256, "%d", ntohs(localAddr.sin_port)); + + snprintf(in_addr, 256, "%d.%d.%d.%d", + ((linaddr >> 24) & 0xff), + ((linaddr >> 16) & 0xff), + ((linaddr >> 8) & 0xff), + ((linaddr >> 0) & 0xff)); + + snprintf(eport1, 256, "%d", eport_curr); + snprintf(eport2, 256, "%d", eport_curr); + + std::cerr << "upnphandler::checkUPnPState()"; + std::cerr << " Checking Redirection: InAddr: " << in_addr; + std::cerr << " InPort: " << in_port1; + std::cerr << " ePort: " << eport1; + std::cerr << " eProt: " << eprot1; + std::cerr << std::endl; + + + bool tcpOk = TestRedirect(&(config -> urls), &(config->data), + in_addr, in_port1, eport1, eprot1); + bool udpOk = TestRedirect(&(config -> urls), &(config->data), + in_addr, in_port2, eport2, eprot2); + + if ((!tcpOk) || (!udpOk)) + { + std::cerr << "upnphandler::checkUPnPState() ... Redirect Expired, restarting"; + std::cerr << std::endl; + + toStop = true; + toStart = true; + } + } + + return true; +} + +class upnpThreadData +{ + public: + upnphandler *handler; + bool start; + bool stop; +}; + + /* Thread routines */ +extern "C" void* doSetupUPnP(void* p) +{ + upnpThreadData *data = (upnpThreadData *) p; + if ((!data) || (!data->handler)) + { + pthread_exit(NULL); + } + + /* publish it! */ + if (data -> stop) + { + data->handler->shutdown_upnp(); + } + + if (data -> start) + { + data->handler->initUPnPState(); + data->handler->start_upnp(); + } + + data->handler->printUPnPState(); + + delete data; + pthread_exit(NULL); + + return NULL; +} + +bool upnphandler::background_setup_upnp(bool start, bool stop) +{ + pthread_t tid; + + /* launch thread */ + upnpThreadData *data = new upnpThreadData(); + data->handler = this; + data->start = start; + data->stop = stop; + + pthread_create(&tid, 0, &doSetupUPnP, (void *) data); + pthread_detach(tid); /* so memory is reclaimed in linux */ + + return true; +} + +bool upnphandler::start_upnp() +{ + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + uPnPConfigData *config = upnpConfig; + if (!((upnpState >= RS_UPNP_S_READY) && (config))) + { + std::cerr << "upnphandler::start_upnp() Not Ready"; + std::cerr << std::endl; + return false; + } + + char eprot1[] = "TCP"; + char eprot2[] = "UDP"; + + /* if we're to load -> load */ + /* select external ports */ + eport_curr = eport; + if (!eport_curr) + { + /* use local port if eport is zero */ + eport_curr = iport; + std::cerr << "Using LocalPort for extPort!"; + std::cerr << std::endl; + } + + if (!eport_curr) + { + std::cerr << "Invalid eport ... "; + std::cerr << std::endl; + return false; + } + + + /* our port */ + char in_addr[256]; + char in_port1[256]; + char in_port2[256]; + char eport1[256]; + char eport2[256]; + + upnp_iaddr.sin_port = htons(iport); + struct sockaddr_in localAddr = upnp_iaddr; + uint32_t linaddr = ntohl(localAddr.sin_addr.s_addr); + + snprintf(in_port1, 256, "%d", ntohs(localAddr.sin_port)); + snprintf(in_port2, 256, "%d", ntohs(localAddr.sin_port)); + snprintf(in_addr, 256, "%d.%d.%d.%d", + ((linaddr >> 24) & 0xff), + ((linaddr >> 16) & 0xff), + ((linaddr >> 8) & 0xff), + ((linaddr >> 0) & 0xff)); + + snprintf(eport1, 256, "%d", eport_curr); + snprintf(eport2, 256, "%d", eport_curr); + + std::cerr << "Attempting Redirection: InAddr: " << in_addr; + std::cerr << " InPort: " << in_port1; + std::cerr << " ePort: " << eport1; + std::cerr << " eProt: " << eprot1; + std::cerr << std::endl; + + if (!SetRedirectAndTest(&(config -> urls), &(config->data), + in_addr, in_port1, eport1, eprot1)) + { + upnpState = RS_UPNP_S_TCP_FAILED; + } + else if (!SetRedirectAndTest(&(config -> urls), &(config->data), + in_addr, in_port2, eport2, eprot2)) + { + upnpState = RS_UPNP_S_UDP_FAILED; + } + else + { + upnpState = RS_UPNP_S_ACTIVE; + } + + + /* now store the external address */ + char externalIPAddress[32]; + UPNP_GetExternalIPAddress(config -> urls.controlURL, + config->data.servicetype, + externalIPAddress); + + sockaddr_clear(&upnp_eaddr); + + if(externalIPAddress[0]) + { + std::cerr << "Stored External address: " << externalIPAddress; + std::cerr << ":" << eport_curr; + std::cerr << std::endl; + + inet_aton(externalIPAddress, &(upnp_eaddr.sin_addr)); + upnp_eaddr.sin_family = AF_INET; + upnp_eaddr.sin_port = htons(eport_curr); + } + else + { + std::cerr << "FAILED To get external Address"; + std::cerr << std::endl; + } + + toStart = false; + + return true; + +} + +bool upnphandler::shutdown_upnp() +{ + RsStackMutex stack(dataMtx); /* LOCK STACK MUTEX */ + + uPnPConfigData *config = upnpConfig; + if (!((upnpState >= RS_UPNP_S_READY) && (config))) + { + return false; + } + + char eprot1[] = "TCP"; + char eprot2[] = "UDP"; + + /* always attempt this (unless no port number) */ + if (eport_curr > 0) + { + + char eport1[256]; + char eport2[256]; + + snprintf(eport1, 256, "%d", eport_curr); + snprintf(eport2, 256, "%d", eport_curr); + + std::cerr << "Attempting To Remove Redirection: port: " << eport1; + std::cerr << " Prot: " << eprot1; + std::cerr << std::endl; + + RemoveRedirect(&(config -> urls), &(config->data), + eport1, eprot1); + + + std::cerr << "Attempting To Remove Redirection: port: " << eport2; + std::cerr << " Prot: " << eprot2; + std::cerr << std::endl; + + RemoveRedirect(&(config -> urls), &(config->data), + eport2, eprot2); + + upnpState = RS_UPNP_S_READY; + toStop = false; + } + + return true; + +} + +/************************ External Interface ***************************** + * + * + * + */ + +upnphandler::upnphandler() + :toEnable(false), toStart(false), toStop(false), + eport(0), eport_curr(0), + upnpState(RS_UPNP_S_UNINITIALISED), + upnpConfig(NULL) +{ + return; +} + +upnphandler::~upnphandler() +{ + return; +} + + /* RsIface */ +void upnphandler::enable(bool active) +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + + if (active != toEnable) + { + if (active) + { + toStart = true; + } + else + { + toStop = true; + } + } + toEnable = active; + + bool start = toStart; + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + if (start) + { + /* make background thread to startup UPnP */ + background_setup_upnp(true, false); + } + + +} + + +void upnphandler::shutdown() +{ + /* blocking call to shutdown upnp */ + + shutdown_upnp(); +} + + +void upnphandler::restart() +{ + /* non-blocking call to shutdown upnp, and startup again. */ + background_setup_upnp(true, true); +} + + + +bool upnphandler::getEnabled() +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + + bool on = toEnable; + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return on; +} + +bool upnphandler::getActive() +{ + dataMtx.lock(); /*** LOCK MUTEX ***/ + + bool on = (upnpState == RS_UPNP_S_ACTIVE); + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return on; +} + + /* the address that the listening port is on */ +void upnphandler::setInternalPort(unsigned short iport_in) +{ +// std::cerr << "UPnPHandler::setInternalAddress() pre Lock!" << std::endl; + dataMtx.lock(); /*** LOCK MUTEX ***/ +// std::cerr << "UPnPHandler::setInternalAddress() postLock!" << std::endl; + + std::cerr << "UPnPHandler::setInternalPort(" << iport_in << ") current port: "; + std::cerr << iport << std::endl; + + if (iport != iport_in) + { + iport = iport_in; + if ((toEnable) && + (upnpState == RS_UPNP_S_ACTIVE)) + { + toStop = true; + toStart = true; + } + } + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ +} + +void upnphandler::setExternalPort(unsigned short eport_in) +{ +// std::cerr << "UPnPHandler::getExternalPort() pre Lock!" << std::endl; + dataMtx.lock(); /*** LOCK MUTEX ***/ +// std::cerr << "UPnPHandler::getExternalPort() postLock!" << std::endl; + + std::cerr << "UPnPHandler::setExternalPort(" << eport_in << ") current port: "; + std::cerr << eport << std::endl; + + /* flag both shutdown/start -> for restart */ + if (eport != eport_in) + { + eport = eport_in; + if ((toEnable) && + (upnpState == RS_UPNP_S_ACTIVE)) + { + toStop = true; + toStart = true; + } + } + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ +} + + /* as determined by uPnP */ +bool upnphandler::getInternalAddress(struct sockaddr_in &addr) +{ +// std::cerr << "UPnPHandler::getInternalAddress() pre Lock!" << std::endl; + dataMtx.lock(); /*** LOCK MUTEX ***/ +// std::cerr << "UPnPHandler::getInternalAddress() postLock!" << std::endl; + + std::cerr << "UPnPHandler::getInternalAddress()" << std::endl; + + addr = upnp_iaddr; + bool valid = (upnpState >= RS_UPNP_S_ACTIVE); + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return valid; +} + +bool upnphandler::getExternalAddress(struct sockaddr_in &addr) +{ +// std::cerr << "UPnPHandler::getExternalAddress() pre Lock!" << std::endl; + dataMtx.lock(); /*** LOCK MUTEX ***/ +// std::cerr << "UPnPHandler::getExternalAddress() postLock!" << std::endl; + + std::cerr << "UPnPHandler::getExternalAddress()" << std::endl; + addr = upnp_eaddr; + bool valid = (upnpState == RS_UPNP_S_ACTIVE); + + dataMtx.unlock(); /*** UNLOCK MUTEX ***/ + + return valid; +} + +#endif diff --git a/libretroshare/src/upnp/upnphandler.h b/libretroshare/src/upnp/upnphandler.h new file mode 100644 index 000000000..80b8560de --- /dev/null +++ b/libretroshare/src/upnp/upnphandler.h @@ -0,0 +1,197 @@ +//Linux only... +#if !defined(WINDOWS_SYS) && !defined(__APPLE__) + +#ifndef _RS_UPNP_IFACE_H +#define _RS_UPNP_IFACE_H + +#include + +/* platform independent networking... */ +#include "pqi/pqinetwork.h" +#include "pqi/pqiassist.h" + +#include "util/rsthreads.h" + +#include +#include "upnp/UPnPBase.h" + +#define RS_UPNP_S_UNINITIALISED 0 +#define RS_UPNP_S_UNAVAILABLE 1 +#define RS_UPNP_S_READY 2 +#define RS_UPNP_S_TCP_AND_FAILED 3 +//#define RS_UPNP_S_UDP_FAILED 4 +#define RS_UPNP_S_ACTIVE 5 + +class upnphandler: public pqiNetAssistFirewall +{ + public: + + upnphandler(); + virtual ~upnphandler(); + + /* External Interface (pqiNetAssistFirewall) */ + virtual void enable(bool active); + virtual void shutdown(); + virtual void restart(); + + virtual bool getEnabled(); + virtual bool getActive(); + + virtual void setInternalPort(unsigned short iport_in); + virtual void setExternalPort(unsigned short eport_in); + virtual bool getInternalAddress(struct sockaddr_in &addr); + virtual bool getExternalAddress(struct sockaddr_in &addr); + + /* Public functions - for background thread operation, + * but effectively private from rest of RS, as in derived class + */ + unsigned int upnpState; + + bool start_upnp(); + bool shutdown_upnp(); + + bool initUPnPState(); + + /* Mutex for data below */ + RsMutex dataMtx; + + private: + + CUPnPControlPoint *cUPnPControlPoint; + + bool background_setup_upnp(bool, bool); + + + bool toEnable; /* overall on/off switch */ + bool toStart; /* if set start forwarding */ + bool toStop; /* if set stop forwarding */ + + unsigned short iport; + unsigned short eport; /* config */ + unsigned short eport_curr; /* current forwarded */ + + /* info from upnp */ + struct sockaddr_in upnp_iaddr; + struct sockaddr_in upnp_eaddr; +}; + +/* info from upnp */ +int CtrlPointCallbackEventHandler(Upnp_EventType ,void* , void*); + +#endif /* _RS_UPNP_IFACE_H */ + +#endif + + + + + +#if defined(WINDOWS_SYS) || defined(__APPLE__) + +//windows implementation +#ifndef _RS_UPNP_IFACE_H +#define _RS_UPNP_IFACE_H + +#include + +#include +#include + +/* platform independent networking... */ +#include "pqi/pqinetwork.h" +#include "pqi/pqiassist.h" + +#include "util/rsthreads.h" + +class upnpentry +{ + public: + std::string name; + std::string id; + struct sockaddr_in addr; + unsigned int flags; + int status; + int lastTs; +}; + +class upnpforward +{ + public: + std::string name; + unsigned int flags; + struct sockaddr_in iaddr; + struct sockaddr_in eaddr; + int status; + int lastTs; +}; + + +#define RS_UPNP_S_UNINITIALISED 0 +#define RS_UPNP_S_UNAVAILABLE 1 +#define RS_UPNP_S_READY 2 +#define RS_UPNP_S_TCP_FAILED 3 +#define RS_UPNP_S_UDP_FAILED 4 +#define RS_UPNP_S_ACTIVE 5 + +class uPnPConfigData; + +class upnphandler: public pqiNetAssistFirewall +{ + public: + + upnphandler(); +virtual ~upnphandler(); + + /* External Interface (pqiNetAssistFirewall) */ +virtual void enable(bool active); +virtual void shutdown(); +virtual void restart(); + +virtual bool getEnabled(); +virtual bool getActive(); + +virtual void setInternalPort(unsigned short iport_in); +virtual void setExternalPort(unsigned short eport_in); +virtual bool getInternalAddress(struct sockaddr_in &addr); +virtual bool getExternalAddress(struct sockaddr_in &addr); + +/* Public functions - for background thread operation, + * but effectively private from rest of RS, as in derived class + */ + +bool start_upnp(); +bool shutdown_upnp(); + +bool initUPnPState(); +bool printUPnPState(); + + private: + +bool background_setup_upnp(bool, bool); +bool checkUPnPActive(); + + /* Mutex for data below */ + RsMutex dataMtx; + + bool toEnable; /* overall on/off switch */ + bool toStart; /* if set start forwarding */ + bool toStop; /* if set stop forwarding */ + + unsigned short iport; + unsigned short eport; /* config */ + unsigned short eport_curr; /* current forwarded */ + + /* info from upnp */ + unsigned int upnpState; + uPnPConfigData *upnpConfig; + + struct sockaddr_in upnp_iaddr; + struct sockaddr_in upnp_eaddr; + + /* active port forwarding */ + std::list activeForwards; + +}; + +#endif /* _RS_UPNP_IFACE_H */ +#endif diff --git a/libretroshare/src/upnp/upnptest.cc b/libretroshare/src/upnp/upnptest.cc new file mode 100644 index 000000000..c6f55e787 --- /dev/null +++ b/libretroshare/src/upnp/upnptest.cc @@ -0,0 +1,86 @@ +//this file use miniupnp + +#include "upnp/upnphandler.h" + + +int main(int argc, char **argv) +{ + + int id = argc % 3; + + /********* + char *fhash1 = "3509426505463458576487"; + char *hash2 = "1549879882341985914515"; + char *hash3 = "8743598543269526505434"; + + int port1 = 8754; + int port2 = 2355; + int port3 = 6621; + **********/ + + std::cerr << "Starting dhttest Id: " << id << std::endl; +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else + // Windows Networking Init. + WORD wVerReq = MAKEWORD(2,2); + WSADATA wsaData; + + if (0 != WSAStartup(wVerReq, &wsaData)) + { + std::cerr << "Failed to Startup Windows Networking"; + std::cerr << std::endl; + } + else + { + std::cerr << "Started Windows Networking"; + std::cerr << std::endl; + } + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + #ifdef PTW32_STATIC_LIB + pthread_win32_process_attach_np(); + #endif + + + upnphandler upnp; + + upnp.setInternalPort(12122); + + for(int i = 0; 1; i++) + { + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + sleep(1); +#else + + Sleep(1000); +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + if (i % 120 == 10) + { + /* start up a forward */ + upnp.enable(true); + + } + + if (i % 120 == 60) + { + /* shutdown a forward */ + upnp.restart(); + } + + if (i % 120 == 100) + { + /* shutdown a forward */ + upnp.shutdown(); + } + + } +} + diff --git a/libretroshare/src/upnp/upnputil.c b/libretroshare/src/upnp/upnputil.c new file mode 100644 index 000000000..cd7f7da20 --- /dev/null +++ b/libretroshare/src/upnp/upnputil.c @@ -0,0 +1,291 @@ +//this file uses miniupnp + +#include "upnp/upnputil.h" + +/* protofix() checks if protocol is "UDP" or "TCP" + * returns NULL if not */ +const char * protofix(const char * proto) +{ + static const char proto_tcp[4] = { 'T', 'C', 'P', 0}; + static const char proto_udp[4] = { 'U', 'D', 'P', 0}; + int i, b; + for(i=0, b=1; i<4; i++) + b = b && ( (proto[i] == proto_tcp[i]) + || (proto[i] == (proto_tcp[i] | 32)) ); + if(b) + return proto_tcp; + for(i=0, b=1; i<4; i++) + b = b && ( (proto[i] == proto_udp[i]) + || (proto[i] == (proto_udp[i] | 32)) ); + if(b) + return proto_udp; + return 0; +} + +void DisplayInfos(struct UPNPUrls * urls, + struct IGDdatas * data) +{ + char externalIPAddress[16]; + char connectionType[64]; + char status[64]; + char lastconnerror[64]; + unsigned int uptime; + unsigned int brUp, brDown; + UPNP_GetConnectionTypeInfo(urls->controlURL, + data->servicetype, + connectionType); + if(connectionType[0]) + printf("Connection Type : %s\n", connectionType); + else + printf("GetConnectionTypeInfo failed.\n"); + UPNP_GetStatusInfo(urls->controlURL, data->servicetype, status, &uptime, lastconnerror); + printf("Status : %s, uptime=%u LastConnError %s\n", status, uptime, lastconnerror); + UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->servicetype_CIF, + &brDown, &brUp); + printf("MaxBitRateDown : %u bps MaxBitRateUp %u bps\n", brDown, brUp); + UPNP_GetExternalIPAddress(urls->controlURL, + data->servicetype, + externalIPAddress); + if(externalIPAddress[0]) + printf("ExternalIPAddress = %s\n", externalIPAddress); + else + printf("GetExternalIPAddress failed.\n"); +} + +void GetConnectionStatus(struct UPNPUrls * urls, + struct IGDdatas * data) +{ + unsigned int bytessent, bytesreceived, packetsreceived, packetssent; + DisplayInfos(urls, data); + bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->servicetype_CIF); + bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->servicetype_CIF); + packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->servicetype_CIF); + packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->servicetype_CIF); + printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); + printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); +} + +void ListRedirections(struct UPNPUrls * urls, + struct IGDdatas * data) +{ + int r; + int i = 0; + char index[6]; + char intClient[16]; + char intPort[6]; + char extPort[6]; + char protocol[4]; + char desc[80]; + char enabled[6]; + char rHost[64]; + char duration[16]; + /*unsigned int num=0; + UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num); + printf("PortMappingNumberOfEntries : %u\n", num);*/ + do { + snprintf(index, 6, "%d", i); + rHost[0] = '\0'; enabled[0] = '\0'; + duration[0] = '\0'; desc[0] = '\0'; + extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; + r = UPNP_GetGenericPortMappingEntry(urls->controlURL, data->servicetype, + index, + extPort, intClient, intPort, + protocol, desc, enabled, + rHost, duration); + if(r==0) + printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n" + " desc='%s' rHost='%s'\n", + i, protocol, extPort, intClient, intPort, + enabled, duration, + desc, rHost); + i++; + } while(r==0); +} + +/* Test function + * 1 - get connection type + * 2 - get extenal ip address + * 3 - Add port mapping + * 4 - get this port mapping from the IGD */ +int SetRedirectAndTest(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * iaddr, + const char * iport, + const char * eport, + const char * proto) +{ + char externalIPAddress[16]; + char intClient[16]; + char intPort[6]; +// char leaseDuration[] = "3600"; /* 60 mins */ + int r; + int ok = 1; + + if(!iaddr || !iport || !eport || !proto) + { + fprintf(stderr, "Wrong arguments\n"); + return 0; + } + proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "invalid protocol\n"); + return 0; + } + + UPNP_GetExternalIPAddress(urls->controlURL, + data->servicetype, + externalIPAddress); + if(externalIPAddress[0]) + printf("ExternalIPAddress = %s\n", externalIPAddress); + else + printf("GetExternalIPAddress failed.\n"); + +// Unix at the moment! +#if MINIUPNPC_VERSION >= 13 + /* Starting from miniupnpc version 1.2, lease duration parameter is gone */ + r = UPNP_AddPortMapping(urls->controlURL, data->servicetype, + eport, iport, iaddr, 0, proto, NULL); +#else + #if MINIUPNPC_VERSION >= 12 + /* Starting from miniupnpc version 1.2, lease duration parameter is gone */ + r = UPNP_AddPortMapping(urls->controlURL, data->servicetype, + eport, iport, iaddr, 0, proto); + #else + /* The lease parameter is also gone in minupnpc 1.0 */ + r = UPNP_AddPortMapping(urls->controlURL, data->servicetype, + eport, iport, iaddr,0, 0, proto); + #endif +#endif + +// r = UPNP_AddPortMapping(urls->controlURL, data->servicetype, +// eport, iport, iaddr, 0, leaseDuration, proto); + +// r = UPNP_AddPortMapping(urls->controlURL, data->servicetype, +// eport, iport, iaddr, 0, proto); + if(r==0) + { + printf("AddPortMapping(%s, %s, %s) failed\n", eport, iport, iaddr); + //this seems to trigger for unknown reasons sometimes. + //rely on Checking it afterwards... + //should check IP address then! + //ok = 0; + } + + UPNP_GetSpecificPortMappingEntry(urls->controlURL, + data->servicetype, + eport, proto, + intClient, intPort); + if(intClient[0]) + printf("InternalIP:Port = %s:%s\n", intClient, intPort); + else + { + printf("GetSpecificPortMappingEntry failed.\n"); + ok = 0; + } + + if ((strcmp(iaddr, intClient) != 0) || (strcmp(iport, intPort) != 0)) + { + printf("PortMappingEntry to wrong location! FAILED\n"); + printf("IP1:\"%s\"\n", iaddr); + printf("IP2:\"%s\"\n", intClient); + printf("PORT1:\"%s\"\n", iport); + printf("PORT2:\"%s\"\n", intPort); + ok = 0; + } + + printf("external %s:%s is redirected to internal %s:%s\n", + externalIPAddress, eport, intClient, intPort); + + if (ok) + { + printf("uPnP Forward/Mapping Succeeded\n"); + } + else + { + printf("uPnP Forward/Mapping Failed\n"); + } + + return ok; +} + +int TestRedirect(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * iaddr, + const char * iport, + const char * eport, + const char * proto) +{ + char intClient[16]; + char intPort[6]; + int ok = 1; + + if(!iaddr || !iport || !eport || !proto) + { + fprintf(stderr, "Wrong arguments\n"); + return 0; + } + proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "invalid protocol\n"); + return 0; + } + + UPNP_GetSpecificPortMappingEntry(urls->controlURL, + data->servicetype, + eport, proto, + intClient, intPort); + if(intClient[0]) + printf("uPnP Check: InternalIP:Port = %s:%s\n", intClient, intPort); + else + { + printf("GetSpecificPortMappingEntry failed.\n"); + ok = 0; + } + + printf("uPnP Check: External port %s is redirected to internal %s:%s\n", + eport, intClient, intPort); + + if (ok) + { + printf("uPnP Check: uPnP Forward/Mapping still Active\n"); + } + else + { + printf("uPnP Check: Forward/Mapping has been Dropped\n"); + } + + return ok; +} + + + +int +RemoveRedirect(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * eport, + const char * proto) +{ + if(!proto || !eport) + { + fprintf(stderr, "invalid arguments\n"); + return 0; + } + proto = protofix(proto); + if(!proto) + { + fprintf(stderr, "protocol invalid\n"); + return 0; + } +#if MINIUPNPC_VERSION >= 13 + UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto, NULL); +#else + UPNP_DeletePortMapping(urls->controlURL, data->servicetype, eport, proto); +#endif + + return 1; +} + + +/* EOF */ diff --git a/libretroshare/src/upnp/upnputil.h b/libretroshare/src/upnp/upnputil.h new file mode 100644 index 000000000..64dca304a --- /dev/null +++ b/libretroshare/src/upnp/upnputil.h @@ -0,0 +1,67 @@ +//this file uses miniupnp + +#ifndef MINIUPNP_UTIL_H_ +#define MINIUPNP_UTIL_H_ + +/* $Id: upnpc.c,v 1.50 2007/04/26 19:00:10 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#include +#include +#include +#ifdef WIN32 +#include +#define snprintf _snprintf +#endif +#include +#include +#include + +/* Ensure linking names are okay on OSX platform. (C interface) */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* protofix() checks if protocol is "UDP" or "TCP" + * returns NULL if not */ +const char * protofix(const char * proto); +void DisplayInfos(struct UPNPUrls * urls, + struct IGDdatas * data); + +void GetConnectionStatus(struct UPNPUrls * urls, + struct IGDdatas * data); + +void ListRedirections(struct UPNPUrls * urls, + struct IGDdatas * data); + +int SetRedirectAndTest(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * iaddr, + const char * iport, + const char * eport, + const char * proto); + +int TestRedirect(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * iaddr, + const char * iport, + const char * eport, + const char * proto); + +int RemoveRedirect(struct UPNPUrls * urls, + struct IGDdatas * data, + const char * eport, + const char * proto); + +#ifdef __cplusplus +} +#endif + +/* EOF */ +#endif diff --git a/libretroshare/src/util/Makefile b/libretroshare/src/util/Makefile new file mode 100644 index 000000000..70f15b3be --- /dev/null +++ b/libretroshare/src/util/Makefile @@ -0,0 +1,27 @@ + +RS_TOP_DIR = .. +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/scripts/config.mk +############################################################### + +RSOBJ = rsthreads.o rsprint.o rsnet.o rsdebug.o rsdir.o rsversion.o + +TESTOBJ = dirtest.o dir2test.o + +TESTS = dirtest dir2test + +all: librs tests + +dirtest: $(OBJ) dirtest.o + $(CC) $(CFLAGS) -o dirtest dirtest.o $(OBJ) $(LIBS) + +dir2test: $(OBJ) dir2test.o + $(CC) $(CFLAGS) -o dir2test dir2test.o $(OBJ) $(LIBS) + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/util/dnsresolver.cc b/libretroshare/src/util/dnsresolver.cc new file mode 100644 index 000000000..0fa9267b8 --- /dev/null +++ b/libretroshare/src/util/dnsresolver.cc @@ -0,0 +1,165 @@ +#include "dnsresolver.h" + +#include "pqi/pqinetwork.h" + +#ifndef WIN32 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +const time_t MAX_TIME_BEFORE_RETRY = 300 ; /* seconds before retrying an ip address */ +const time_t MAX_KEEP_DNS_ENTRY = 3600 ; /* seconds during which a DNS entry is considered valid */ + +static const std::string ADDR_AGENT = "Mozilla/5.0"; + +void *solveDNSEntries(void *p) +{ + bool more_to_go = true ; + DNSResolver *dnsr = (DNSResolver*)p ; + + while(more_to_go) + { + // get an address request + time_t now = time(NULL) ; + more_to_go = false ; + + std::string next_call = "" ; + + { + RsStackMutex mut(dnsr->_rdnsMtx) ; + + if(dnsr->_addr_map != NULL) + for(std::map::iterator it(dnsr->_addr_map->begin());it!=dnsr->_addr_map->end() && next_call.empty();++it) + { + switch(it->second.state) + { + case DNSResolver::DNS_SEARCHING: + case DNSResolver::DNS_HAVE: break ; + + case DNSResolver::DNS_LOOKUP_ERROR: if(it->second.last_lookup_time + MAX_TIME_BEFORE_RETRY > now) + continue ; + + case DNSResolver::DNS_DONT_HAVE: next_call = it->first ; + it->second.state = DNSResolver::DNS_SEARCHING ; + it->second.last_lookup_time = now ; + more_to_go = true ; + break ; + } + } + else + return NULL; // the thread has been deleted. Return. + } + + if(!next_call.empty()) + { + hostent *pHost = gethostbyname(next_call.c_str()); + + { + RsStackMutex mut(dnsr->_rdnsMtx) ; + + if(pHost) + { + (*dnsr->_addr_map)[next_call].state = DNSResolver::DNS_HAVE ; + (*dnsr->_addr_map)[next_call].addr.s_addr = *(unsigned long*) (pHost->h_addr); + } + else + (*dnsr->_addr_map)[next_call].state = DNSResolver::DNS_LOOKUP_ERROR ; + } + } + } + + { + RsStackMutex mut(dnsr->_rdnsMtx) ; + *(dnsr->_thread_running) = false ; + } + return NULL ; +} + +void DNSResolver::start_request() +{ + { + RsStackMutex mut(_rdnsMtx) ; + *_thread_running = true ; + } + + void *data = (void *)this; + pthread_t tid ; + pthread_create(&tid, 0, &solveDNSEntries, data); + pthread_detach(tid); /* so memory is reclaimed in linux */ +} + +void DNSResolver::reset() +{ + RsStackMutex mut(_rdnsMtx) ; + + *_thread_running = false ; + _addr_map->clear(); + _addr_map = NULL ; +} + +bool DNSResolver::getIPAddressFromString(const std::string& server_name,struct in_addr& addr) +{ + addr.s_addr = 0 ; + bool running = false; + { + RsStackMutex mut(_rdnsMtx) ; + + std::map::iterator it(_addr_map->find(server_name)) ; + time_t now = time(NULL) ; + AddrInfo *addr_info ; + + if(it != _addr_map->end()) + { + // check that the address record is not too old + + if(it->second.last_lookup_time + MAX_KEEP_DNS_ENTRY > now && it->second.state == DNSResolver::DNS_HAVE) + { + addr = it->second.addr ; + return true ; + } + else + addr_info = &it->second ; + } + else + addr_info = &(*_addr_map)[server_name] ; + + // We don't have it. Let's push it into the names to lookup for, except if we're already into it. + + if(addr_info->state != DNSResolver::DNS_SEARCHING) + addr_info->state = DNSResolver::DNS_DONT_HAVE ; + + running = *_thread_running ; + } + + if(!running) + start_request(); + + return false ; +} + +DNSResolver::~DNSResolver() +{ + RsStackMutex mut(_rdnsMtx) ; + + delete _addr_map ; + _addr_map = NULL ; + delete _thread_running ; +} + +DNSResolver::DNSResolver() +{ + RsStackMutex mut(_rdnsMtx) ; + + _addr_map = new std::map() ; + _thread_running = new bool ; + *_thread_running = false ; +} + diff --git a/libretroshare/src/util/dnsresolver.h b/libretroshare/src/util/dnsresolver.h new file mode 100644 index 000000000..51aa77dc2 --- /dev/null +++ b/libretroshare/src/util/dnsresolver.h @@ -0,0 +1,40 @@ +#pragma once + +#include "pqi/pqinetwork.h" + +#ifndef WIN32 +#include +#endif + +#include +#include +#include "util/rsthreads.h" + +struct sockaddr ; + +class DNSResolver +{ + public: + DNSResolver() ; + ~DNSResolver() ; + + bool getIPAddressFromString(const std::string& server_name,struct in_addr& addr) ; + + void start_request() ; + void reset() ; + + private: + enum { DNS_DONT_HAVE,DNS_SEARCHING, DNS_HAVE, DNS_LOOKUP_ERROR } ; + + struct AddrInfo + { + uint32_t state ; // state: Looked-up, not found, have + time_t last_lookup_time ; // last lookup time + struct in_addr addr ; + }; + friend void *solveDNSEntries(void *p) ; + + RsMutex _rdnsMtx ; + bool *_thread_running ; + std::map *_addr_map ; +}; diff --git a/libretroshare/src/util/exampletst.c b/libretroshare/src/util/exampletst.c new file mode 100644 index 000000000..e96cd037e --- /dev/null +++ b/libretroshare/src/util/exampletst.c @@ -0,0 +1,40 @@ + +#include "utest.h" + +#include + +/* must define the global variables */ +INITTEST(); + +int main(int argc, char **argv) +{ + int a = 2; + int b = 3; + int c = 2; + + CHECK( a == c ); + + REPORT( "Initial Tests"); + + CHECK( (0 == strcmp("123", "123")) ); + + REPORT( "Successful Tests"); + + CHECK( a == b ); + CHECK( (0 == strcmp("123", "12345")) ); + + REPORT( "Failed Tests" ); + + CHECK( 1 ); + CHECK( a == c ); + + REPORT( "Later Successful Tests"); + + + FINALREPORT( "Example Tests" ); + + return TESTRESULT(); +} + + + diff --git a/libretroshare/src/util/extaddrfinder.cc b/libretroshare/src/util/extaddrfinder.cc new file mode 100644 index 000000000..50fb1ce6c --- /dev/null +++ b/libretroshare/src/util/extaddrfinder.cc @@ -0,0 +1,297 @@ +#include "extaddrfinder.h" + +#include "pqi/pqinetwork.h" + +#ifndef WIN32 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */ + +static const std::string ADDR_AGENT = "Mozilla/5.0"; + +static std::string scan_ip(const std::string& text) +{ + std::set digits ; + digits.insert('0') ; digits.insert('3') ; digits.insert('6') ; + digits.insert('1') ; digits.insert('4') ; digits.insert('7') ; + digits.insert('2') ; digits.insert('5') ; digits.insert('8') ; + digits.insert('9') ; + + for(int i=0;i<(int)text.size();++i) + { + while(i < (int)text.size() && digits.find(text[i])==digits.end()) ++i ; + + if(i>=(int)text.size()) + return "" ; + + unsigned int a,b,c,d ; + + if(sscanf(text.c_str()+i,"%u.%u.%u.%u",&a,&b,&c,&d) != 4) + continue ; + + if(a < 256 && b<256 && c<256 && d<256) + { + std::ostringstream o ; + o << a << "." << b << "." << c << "." << d ; + return o.str(); + } + } + return "" ; +} + +static void getPage(const std::string& server_name,std::string& page) +{ + page = "" ; + int sockfd,n=0; // socket descriptor + struct sockaddr_in serveur; // server's parameters + memset(&serveur.sin_zero, 0, sizeof(serveur.sin_zero)); + struct hostent *hostinfo=NULL; // structure for storing the server's ip + + char buf[1024]; + char request[1024]; +#ifdef EXTADDRSEARCH_DEBUG + std::cout << "ExtAddrFinder: connecting to " << server_name << std::endl ; +#endif + // socket creation + + sockfd = unix_socket(PF_INET,SOCK_STREAM,0); + + serveur.sin_family = AF_INET; + + // get server's ipv4 adress + + hostinfo = gethostbyname(server_name.c_str()); + + if (hostinfo == NULL) /* l'hôte n'existe pas */ + { + std::cerr << "ExtAddrFinder: Unknown host " << server_name << std::endl; + return ; + } + serveur.sin_addr = *(struct in_addr*) hostinfo->h_addr; + serveur.sin_port = htons(80); + +#ifdef EXTADDRSEARCH_DEBUG + printf("Connexion attempt\n"); +#endif + + if(unix_connect(sockfd,(struct sockaddr *)&serveur, sizeof(serveur)) == -1) + { + std::cerr << "ExtAddrFinder: Connexion error to " << server_name << std::endl ; + return ; + } +#ifdef EXTADDRSEARCH_DEBUG + std::cerr << "ExtAddrFinder: Connexion established to " << server_name << std::endl ; +#endif + + // envoi + sprintf( request, + "GET / HTTP/1.0\r\n" + "Host: %s:%d\r\n" + "Connection: Close\r\n" + "\r\n", + server_name.c_str(), 80); + + if(send(sockfd,request,strlen(request),0)== -1) + { + std::cerr << "ExtAddrFinder: Could not send request to " << server_name << std::endl ; + return ; + } + // recéption + + while((n = recv(sockfd, buf, sizeof buf - 1, 0)) > 0) + { + buf[n] = '\0'; + page += std::string(buf,n) ; + } + // fermeture de la socket + + unix_close(sockfd); +#ifdef EXTADDRSEARCH_DEBUG + std::cerr << "ExtAddrFinder: Got full page from " << server_name << std::endl ; +#endif +} + + +void* doExtAddrSearch(void *p) +{ + + std::vector res ; + + ExtAddrFinder *af = (ExtAddrFinder*)p ; + + for(std::list::const_iterator it(af->_ip_servers.begin());it!=af->_ip_servers.end();++it) + { + std::string page ; + + getPage(*it,page) ; + std::string ip = scan_ip(page) ; + + if(ip != "") + res.push_back(ip) ; +#ifdef EXTADDRSEARCH_DEBUG + std::cout << "ip found through " << *it << ": \"" << ip << "\"" << std::endl ; +#endif + } + + if(res.empty()) + { + // thread safe copy results. + // + { + RsStackMutex mtx(af->_addrMtx) ; + + *(af->_found) = false ; + *(af->mFoundTS) = time(NULL) ; + *(af->_searching) = false ; + } + pthread_exit(NULL); + return NULL ; + } + + sort(res.begin(),res.end()) ; // eliminates outliers. + + + if(!inet_aton(res[res.size()/2].c_str(),af->_addr)) + { + std::cerr << "ExtAddrFinder: Could not convert " << res[res.size()/2] << " into an address." << std::endl ; + { + RsStackMutex mtx(af->_addrMtx) ; + *(af->_found) = false ; + *(af->mFoundTS) = time(NULL) ; + *(af->_searching) = false ; + } + pthread_exit(NULL); + return NULL ; + } + + { + RsStackMutex mtx(af->_addrMtx) ; + *(af->_found) = true ; + *(af->mFoundTS) = time(NULL) ; + *(af->_searching) = false ; + } + + pthread_exit(NULL); + return NULL ; +} + + +void ExtAddrFinder::start_request() +{ + void *data = (void *)this; + pthread_t tid ; + pthread_create(&tid, 0, &doExtAddrSearch, data); + pthread_detach(tid); /* so memory is reclaimed in linux */ +} + +bool ExtAddrFinder::hasValidIP(struct in_addr *addr) +{ +#ifdef EXTADDRSEARCH_DEBUG + std::cerr << "ExtAddrFinder: Getting ip." << std::endl ; +#endif + + if(*_found) + { +#ifdef EXTADDRSEARCH_DEBUG + std::cerr << "ExtAddrFinder: Has stored ip: responding with this ip." << std::endl ; +#endif + *addr = *_addr; + } + + //timeout the current ip + time_t delta = time(NULL) - *mFoundTS; + if((uint32_t)delta > MAX_IP_STORE) {//launch a research + if( _addrMtx.trylock()) + { + if(!*_searching) + { + #ifdef EXTADDRSEARCH_DEBUG + std::cerr << "ExtAddrFinder: No stored ip: Initiating new search." << std::endl ; + #endif + *_searching = true ; + start_request() ; + } + #ifdef EXTADDRSEARCH_DEBUG + else + std::cerr << "ExtAddrFinder: Already searching." << std::endl ; + #endif + _addrMtx.unlock(); + } + #ifdef EXTADDRSEARCH_DEBUG + else + std::cerr << "ExtAddrFinder: (Note) Could not acquire lock. Busy." << std::endl ; + #endif + } + + return *_found ; +} + +void ExtAddrFinder::reset() +{ +// while(*_searching) +//#ifdef WIN32 +// Sleep(1000) ; +//#else +// sleep(1) ; +//#endif + + RsStackMutex mut(_addrMtx) ; + + *_found = false ; + *_searching = false ; + *mFoundTS = time(NULL) - MAX_IP_STORE; +} + +ExtAddrFinder::~ExtAddrFinder() +{ +#ifdef EXTADDRSEARCH_DEBUG + std::cerr << "ExtAddrFinder: Deleting ExtAddrFinder." << std::endl ; +#endif +// while(*_searching) +//#ifdef WIN32 +// Sleep(1000) ; +//#else +// sleep(1) ; +//#endif + + RsStackMutex mut(_addrMtx) ; + + delete _found ; + delete _searching ; + free (_addr) ; +} + +ExtAddrFinder::ExtAddrFinder() +{ +#ifdef EXTADDRSEARCH_DEBUG + std::cerr << "ExtAddrFinder: Creating new ExtAddrFinder." << std::endl ; +#endif + RsStackMutex mut(_addrMtx) ; + + _found = new bool ; + *_found = false ; + + _searching = new bool ; + *_searching = false ; + + mFoundTS = new time_t; + *mFoundTS = time(NULL) - MAX_IP_STORE; + + _addr = (in_addr*)malloc(sizeof(in_addr)) ; + + _ip_servers.push_back(std::string( "checkip.dyndns.org" )) ; + _ip_servers.push_back(std::string( "www.showmyip.com" )) ; + _ip_servers.push_back(std::string( "showip.net" )) ; + _ip_servers.push_back(std::string( "www.displaymyip.com")) ; +} + diff --git a/libretroshare/src/util/extaddrfinder.h b/libretroshare/src/util/extaddrfinder.h new file mode 100644 index 000000000..ec8782c7c --- /dev/null +++ b/libretroshare/src/util/extaddrfinder.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include "util/rsthreads.h" + +struct sockaddr ; + +class ExtAddrFinder +{ + public: + ExtAddrFinder() ; + ~ExtAddrFinder() ; + + bool hasValidIP(struct in_addr *addr) ; + void getIPServersList(std::list& ip_servers) { ip_servers = _ip_servers ; } + + void start_request() ; + + void reset() ; + + private: + friend void* doExtAddrSearch(void *p) ; + + time_t *mFoundTS; + RsMutex _addrMtx ; + struct in_addr *_addr ; + bool *_found ; + bool *_searching ; + std::list _ip_servers ; +}; diff --git a/libretroshare/src/util/folderiterator.cc b/libretroshare/src/util/folderiterator.cc new file mode 100644 index 000000000..6e744a082 --- /dev/null +++ b/libretroshare/src/util/folderiterator.cc @@ -0,0 +1,85 @@ +#include "folderiterator.h" +#include "rswin.h" + + +namespace librs { namespace util { + + +FolderIterator::FolderIterator(const std::string& folderName) +{ +#ifdef WINDOWS_SYS + std::wstring utf16Name; + if(! ConvertUtf8ToUtf16(folderName, utf16Name)) { + validity = false; + return; + } + + utf16Name += L"/*.*"; + + handle = FindFirstFileW(utf16Name.c_str(), &fileInfo); + validity = handle != INVALID_HANDLE_VALUE; + isFirstCall = true; +#else + handle = opendir(folderName.c_str()); + validity = handle != NULL; +#endif +} + +FolderIterator::~FolderIterator() +{ + closedir(); +} + +bool FolderIterator::readdir() { + if(!validity) + return false; + +#ifdef WINDOWS_SYS + if(isFirstCall) { + isFirstCall = false; + return true; + } + return FindNextFileW(handle, &fileInfo) != 0; +#else + ent = ::readdir(handle); + return ent != 0; +#endif +} + +bool FolderIterator::d_name(std::string& dest) +{ + if(!validity) + return false; + +#ifdef WINDOWS_SYS + if(! ConvertUtf16ToUtf8(fileInfo.cFileName, dest)) { + validity = false; + return false; + } +#else + if(ent == 0) + return false; + dest = ent->d_name; +#endif + + return true; +} + +bool FolderIterator::closedir() +{ + if(!validity) + return false; + + validity = false; + +#ifdef WINDOWS_SYS + return FindClose(handle) != 0; +#else + return ::closedir(handle) == 0; +#endif +} + + + + +} } // librs::util diff --git a/libretroshare/src/util/folderiterator.h b/libretroshare/src/util/folderiterator.h new file mode 100644 index 000000000..bfddc6b74 --- /dev/null +++ b/libretroshare/src/util/folderiterator.h @@ -0,0 +1,54 @@ +#ifndef FOLDERITERATOR_H +#define FOLDERITERATOR_H + + +#include +#include + +#ifdef WINDOWS_SYS + #include "util/rswin.h" + #include + #include + #include + #include +#else + #include +#endif + + +namespace librs { namespace util { + + +class FolderIterator +{ +public: + FolderIterator(const std::string& folderName); + ~FolderIterator(); + + bool isValid() const { return validity; } + + bool readdir(); + + bool d_name(std::string& dest); + + bool closedir(); + +private: + bool validity; + +#ifdef WINDOWS_SYS + HANDLE handle; + bool isFirstCall; + _WIN32_FIND_DATAW fileInfo; +#else + DIR* handle; + struct dirent* ent; +#endif + +}; + + +} } // librs::util + + +#endif // FOLDERITERATOR_H diff --git a/libretroshare/src/util/pugiconfig.h b/libretroshare/src/util/pugiconfig.h new file mode 100644 index 000000000..6b553ae04 --- /dev/null +++ b/libretroshare/src/util/pugiconfig.h @@ -0,0 +1,62 @@ +/** + * pugixml parser - version 1.0 + * -------------------------------------------------------- + * Copyright (C) 2006-2010, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at http://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#ifndef HEADER_PUGICONFIG_HPP +#define HEADER_PUGICONFIG_HPP + +// Uncomment this to enable wchar_t mode +// #define PUGIXML_WCHAR_MODE + +// Uncomment this to disable XPath +// #define PUGIXML_NO_XPATH + +// Uncomment this to disable STL +// Note: you can't use XPath with PUGIXML_NO_STL +// #define PUGIXML_NO_STL + +// Uncomment this to disable exceptions +// Note: you can't use XPath with PUGIXML_NO_EXCEPTIONS +// #define PUGIXML_NO_EXCEPTIONS + +// Set this to control attributes for public classes/functions, i.e.: +// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL +// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL +// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall +// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead + +#endif + +/** + * Copyright (c) 2006-2010 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/libretroshare/src/util/pugixml.cc b/libretroshare/src/util/pugixml.cc new file mode 100644 index 000000000..c4dc3fafc --- /dev/null +++ b/libretroshare/src/util/pugixml.cc @@ -0,0 +1,9576 @@ +/** + * pugixml parser - version 1.0 + * -------------------------------------------------------- + * Copyright (C) 2006-2010, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at http://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#include "pugixml.h" + +#include +#include +#include +#include +#include +#include + +#ifndef PUGIXML_NO_XPATH +# include +# include +#endif + +#ifndef PUGIXML_NO_STL +# include +# include +# include +#endif + +// For placement new +#include + +#ifdef _MSC_VER +# pragma warning(disable: 4127) // conditional expression is constant +# pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +# pragma warning(disable: 4611) // interaction between '_setjmp' and C++ object destruction is non-portable +# pragma warning(disable: 4702) // unreachable code +# pragma warning(disable: 4996) // this function or variable may be unsafe +#endif + +#ifdef __INTEL_COMPILER +# pragma warning(disable: 177) // function was declared but never referenced +# pragma warning(disable: 1478 1786) // function was declared "deprecated" +#endif + +#ifdef __BORLANDC__ +# pragma warn -8008 // condition is always false +# pragma warn -8066 // unreachable code +#endif + +#ifdef __SNC__ +# pragma diag_suppress=178 // function was declared but never referenced +# pragma diag_suppress=237 // controlling expression is constant +#endif + +// uintptr_t +#if !defined(_MSC_VER) || _MSC_VER >= 1600 +# include +#else +# if _MSC_VER < 1300 +// No native uintptr_t in MSVC6 +typedef size_t uintptr_t; +# endif +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef __int32 int32_t; +#endif + +// Inlining controls +#if defined(_MSC_VER) && _MSC_VER >= 1300 +# define PUGIXML_NO_INLINE __declspec(noinline) +#elif defined(__GNUC__) +# define PUGIXML_NO_INLINE __attribute__((noinline)) +#else +# define PUGIXML_NO_INLINE +#endif + +// Simple static assertion +#define STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; } + +// Digital Mars C++ bug workaround for passing char loaded from memory via stack +#ifdef __DMC__ +# define DMC_VOLATILE volatile +#else +# define DMC_VOLATILE +#endif + +using namespace pugi; + +// Memory allocation +namespace +{ + void* default_allocate(size_t size) + { + return malloc(size); + } + + void default_deallocate(void* ptr) + { + free(ptr); + } + + allocation_function global_allocate = default_allocate; + deallocation_function global_deallocate = default_deallocate; +} + +// String utilities +namespace +{ + // Get string length + size_t strlength(const char_t* s) + { + assert(s); + + #ifdef PUGIXML_WCHAR_MODE + return wcslen(s); + #else + return strlen(s); + #endif + } + + // Compare two strings + bool strequal(const char_t* src, const char_t* dst) + { + assert(src && dst); + + #ifdef PUGIXML_WCHAR_MODE + return wcscmp(src, dst) == 0; + #else + return strcmp(src, dst) == 0; + #endif + } + + // Compare lhs with [rhs_begin, rhs_end) + bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) + { + for (size_t i = 0; i < count; ++i) + if (lhs[i] != rhs[i]) + return false; + + return lhs[count] == 0; + } + +#ifdef PUGIXML_WCHAR_MODE + // Convert string to wide string, assuming all symbols are ASCII + void widen_ascii(wchar_t* dest, const char* source) + { + for (const char* i = source; *i; ++i) *dest++ = *i; + *dest = 0; + } +#endif +} + +#if !defined(PUGIXML_NO_STL) || !defined(PUGIXML_NO_XPATH) +// auto_ptr-like buffer holder for exception recovery +namespace +{ + struct buffer_holder + { + void* data; + void (*deleter)(void*); + + buffer_holder(void* data, void (*deleter)(void*)): data(data), deleter(deleter) + { + } + + ~buffer_holder() + { + if (data) deleter(data); + } + + void* release() + { + void* result = data; + data = 0; + return result; + } + }; +} +#endif + +namespace +{ + static const size_t xml_memory_page_size = 32768; + + static const uintptr_t xml_memory_page_alignment = 32; + static const uintptr_t xml_memory_page_pointer_mask = ~(xml_memory_page_alignment - 1); + static const uintptr_t xml_memory_page_name_allocated_mask = 16; + static const uintptr_t xml_memory_page_value_allocated_mask = 8; + static const uintptr_t xml_memory_page_type_mask = 7; + + struct xml_allocator; + + struct xml_memory_page + { + static xml_memory_page* construct(void* memory) + { + if (!memory) return 0; //$ redundant, left for performance + + xml_memory_page* result = static_cast(memory); + + result->allocator = 0; + result->memory = 0; + result->prev = 0; + result->next = 0; + result->busy_size = 0; + result->freed_size = 0; + + return result; + } + + xml_allocator* allocator; + + void* memory; + + xml_memory_page* prev; + xml_memory_page* next; + + size_t busy_size; + size_t freed_size; + + char data[1]; + }; + + struct xml_memory_string_header + { + uint16_t page_offset; // offset from page->data + uint16_t full_size; // 0 if string occupies whole page + }; + + struct xml_allocator + { + xml_allocator(xml_memory_page* root): _root(root), _busy_size(root->busy_size) + { + } + + xml_memory_page* allocate_page(size_t data_size) + { + size_t size = offsetof(xml_memory_page, data) + data_size; + + // allocate block with some alignment, leaving memory for worst-case padding + void* memory = global_allocate(size + xml_memory_page_alignment); + if (!memory) return 0; + + // align upwards to page boundary + void* page_memory = reinterpret_cast((reinterpret_cast(memory) + (xml_memory_page_alignment - 1)) & ~(xml_memory_page_alignment - 1)); + + // prepare page structure + xml_memory_page* page = xml_memory_page::construct(page_memory); + + page->memory = memory; + page->allocator = _root->allocator; + + return page; + } + + static void deallocate_page(xml_memory_page* page) + { + global_deallocate(page->memory); + } + + void* allocate_memory_oob(size_t size, xml_memory_page*& out_page); + + void* allocate_memory(size_t size, xml_memory_page*& out_page) + { + if (_busy_size + size > xml_memory_page_size) return allocate_memory_oob(size, out_page); + + void* buf = _root->data + _busy_size; + + _busy_size += size; + + out_page = _root; + + return buf; + } + + void deallocate_memory(void* ptr, size_t size, xml_memory_page* page) + { + if (page == _root) page->busy_size = _busy_size; + + assert(ptr >= page->data && ptr < page->data + page->busy_size); + (void)!ptr; + + page->freed_size += size; + assert(page->freed_size <= page->busy_size); + + if (page->freed_size == page->busy_size) + { + if (page->next == 0) + { + assert(_root == page); + + // top page freed, just reset sizes + page->busy_size = page->freed_size = 0; + _busy_size = 0; + } + else + { + assert(_root != page); + assert(page->prev); + + // remove from the list + page->prev->next = page->next; + page->next->prev = page->prev; + + // deallocate + deallocate_page(page); + } + } + } + + char_t* allocate_string(size_t length) + { + // allocate memory for string and header block + size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t); + + // round size up to pointer alignment boundary + size_t full_size = (size + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1); + + xml_memory_page* page; + xml_memory_string_header* header = static_cast(allocate_memory(full_size, page)); + + if (!header) return 0; + + // setup header + ptrdiff_t page_offset = reinterpret_cast(header) - page->data; + + assert(page_offset >= 0 && page_offset < (1 << 16)); + header->page_offset = static_cast(page_offset); + + // full_size == 0 for large strings that occupy the whole page + assert(full_size < (1 << 16) || (page->busy_size == full_size && page_offset == 0)); + header->full_size = static_cast(full_size < (1 << 16) ? full_size : 0); + + return reinterpret_cast(header + 1); + } + + void deallocate_string(char_t* string) + { + // get header + xml_memory_string_header* header = reinterpret_cast(string) - 1; + + // deallocate + size_t page_offset = offsetof(xml_memory_page, data) + header->page_offset; + xml_memory_page* page = reinterpret_cast(reinterpret_cast(header) - page_offset); + + // if full_size == 0 then this string occupies the whole page + size_t full_size = header->full_size == 0 ? page->busy_size : header->full_size; + + deallocate_memory(header, full_size, page); + } + + xml_memory_page* _root; + size_t _busy_size; + }; + + PUGIXML_NO_INLINE void* xml_allocator::allocate_memory_oob(size_t size, xml_memory_page*& out_page) + { + const size_t large_allocation_threshold = xml_memory_page_size / 4; + + xml_memory_page* page = allocate_page(size <= large_allocation_threshold ? xml_memory_page_size : size); + if (!page) return 0; + + if (size <= large_allocation_threshold) + { + _root->busy_size = _busy_size; + + // insert page at the end of linked list + page->prev = _root; + _root->next = page; + _root = page; + + _busy_size = size; + } + else + { + // insert page before the end of linked list, so that it is deleted as soon as possible + // the last page is not deleted even if it's empty (see deallocate_memory) + assert(_root->prev); + + page->prev = _root->prev; + page->next = _root; + + _root->prev->next = page; + _root->prev = page; + } + + // allocate inside page + page->busy_size = size; + + out_page = page; + return page->data; + } +} + +namespace pugi +{ + /// A 'name=value' XML attribute structure. + struct xml_attribute_struct + { + /// Default ctor + xml_attribute_struct(xml_memory_page* page): header(reinterpret_cast(page)), name(0), value(0), prev_attribute_c(0), next_attribute(0) + { + } + + uintptr_t header; + + char_t* name; ///< Pointer to attribute name. + char_t* value; ///< Pointer to attribute value. + + xml_attribute_struct* prev_attribute_c; ///< Previous attribute (cyclic list) + xml_attribute_struct* next_attribute; ///< Next attribute + }; + + /// An XML document tree node. + struct xml_node_struct + { + /// Default ctor + /// \param type - node type + xml_node_struct(xml_memory_page* page, xml_node_type type): header(reinterpret_cast(page) | (type - 1)), parent(0), name(0), value(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) + { + } + + uintptr_t header; + + xml_node_struct* parent; ///< Pointer to parent + + char_t* name; ///< Pointer to element name. + char_t* value; ///< Pointer to any associated string data. + + xml_node_struct* first_child; ///< First child + + xml_node_struct* prev_sibling_c; ///< Left brother (cyclic list) + xml_node_struct* next_sibling; ///< Right brother + + xml_attribute_struct* first_attribute; ///< First attribute + }; +} + +namespace +{ + struct xml_document_struct: public xml_node_struct, public xml_allocator + { + xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0) + { + } + + const char_t* buffer; + }; + + static inline xml_allocator& get_allocator(const xml_node_struct* node) + { + assert(node); + + return *reinterpret_cast(node->header & xml_memory_page_pointer_mask)->allocator; + } +} + +// Low-level DOM operations +namespace +{ + inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc) + { + xml_memory_page* page; + void* memory = alloc.allocate_memory(sizeof(xml_attribute_struct), page); + + return new (memory) xml_attribute_struct(page); + } + + inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type) + { + xml_memory_page* page; + void* memory = alloc.allocate_memory(sizeof(xml_node_struct), page); + + return new (memory) xml_node_struct(page, type); + } + + inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc) + { + uintptr_t header = a->header; + + if (header & xml_memory_page_name_allocated_mask) alloc.deallocate_string(a->name); + if (header & xml_memory_page_value_allocated_mask) alloc.deallocate_string(a->value); + + alloc.deallocate_memory(a, sizeof(xml_attribute_struct), reinterpret_cast(header & xml_memory_page_pointer_mask)); + } + + inline void destroy_node(xml_node_struct* n, xml_allocator& alloc) + { + uintptr_t header = n->header; + + if (header & xml_memory_page_name_allocated_mask) alloc.deallocate_string(n->name); + if (header & xml_memory_page_value_allocated_mask) alloc.deallocate_string(n->value); + + for (xml_attribute_struct* attr = n->first_attribute; attr; ) + { + xml_attribute_struct* next = attr->next_attribute; + + destroy_attribute(attr, alloc); + + attr = next; + } + + for (xml_node_struct* child = n->first_child; child; ) + { + xml_node_struct* next = child->next_sibling; + + destroy_node(child, alloc); + + child = next; + } + + alloc.deallocate_memory(n, sizeof(xml_node_struct), reinterpret_cast(header & xml_memory_page_pointer_mask)); + } + + PUGIXML_NO_INLINE xml_node_struct* append_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element) + { + xml_node_struct* child = allocate_node(alloc, type); + if (!child) return 0; + + child->parent = node; + + xml_node_struct* first_child = node->first_child; + + if (first_child) + { + xml_node_struct* last_child = first_child->prev_sibling_c; + + last_child->next_sibling = child; + child->prev_sibling_c = last_child; + first_child->prev_sibling_c = child; + } + else + { + node->first_child = child; + child->prev_sibling_c = child; + } + + return child; + } + + PUGIXML_NO_INLINE xml_attribute_struct* append_attribute_ll(xml_node_struct* node, xml_allocator& alloc) + { + xml_attribute_struct* a = allocate_attribute(alloc); + if (!a) return 0; + + xml_attribute_struct* first_attribute = node->first_attribute; + + if (first_attribute) + { + xml_attribute_struct* last_attribute = first_attribute->prev_attribute_c; + + last_attribute->next_attribute = a; + a->prev_attribute_c = last_attribute; + first_attribute->prev_attribute_c = a; + } + else + { + node->first_attribute = a; + a->prev_attribute_c = a; + } + + return a; + } +} + +// Helper classes for code generation +namespace +{ + struct opt_false + { + enum { value = 0 }; + }; + + struct opt_true + { + enum { value = 1 }; + }; +} + +// Unicode utilities +namespace +{ + inline uint16_t endian_swap(uint16_t value) + { + return static_cast(((value & 0xff) << 8) | (value >> 8)); + } + + inline uint32_t endian_swap(uint32_t value) + { + return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24); + } + + struct utf8_counter + { + typedef size_t value_type; + + static value_type low(value_type result, uint32_t ch) + { + // U+0000..U+007F + if (ch < 0x80) return result + 1; + // U+0080..U+07FF + else if (ch < 0x800) return result + 2; + // U+0800..U+FFFF + else return result + 3; + } + + static value_type high(value_type result, uint32_t) + { + // U+10000..U+10FFFF + return result + 4; + } + }; + + struct utf8_writer + { + typedef uint8_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + // U+0000..U+007F + if (ch < 0x80) + { + *result = static_cast(ch); + return result + 1; + } + // U+0080..U+07FF + else if (ch < 0x800) + { + result[0] = static_cast(0xC0 | (ch >> 6)); + result[1] = static_cast(0x80 | (ch & 0x3F)); + return result + 2; + } + // U+0800..U+FFFF + else + { + result[0] = static_cast(0xE0 | (ch >> 12)); + result[1] = static_cast(0x80 | ((ch >> 6) & 0x3F)); + result[2] = static_cast(0x80 | (ch & 0x3F)); + return result + 3; + } + } + + static value_type high(value_type result, uint32_t ch) + { + // U+10000..U+10FFFF + result[0] = static_cast(0xF0 | (ch >> 18)); + result[1] = static_cast(0x80 | ((ch >> 12) & 0x3F)); + result[2] = static_cast(0x80 | ((ch >> 6) & 0x3F)); + result[3] = static_cast(0x80 | (ch & 0x3F)); + return result + 4; + } + + static value_type any(value_type result, uint32_t ch) + { + return (ch < 0x10000) ? low(result, ch) : high(result, ch); + } + }; + + struct utf16_counter + { + typedef size_t value_type; + + static value_type low(value_type result, uint32_t) + { + return result + 1; + } + + static value_type high(value_type result, uint32_t) + { + return result + 2; + } + }; + + struct utf16_writer + { + typedef uint16_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + *result = static_cast(ch); + + return result + 1; + } + + static value_type high(value_type result, uint32_t ch) + { + uint32_t msh = (uint32_t)(ch - 0x10000) >> 10; + uint32_t lsh = (uint32_t)(ch - 0x10000) & 0x3ff; + + result[0] = static_cast(0xD800 + msh); + result[1] = static_cast(0xDC00 + lsh); + + return result + 2; + } + + static value_type any(value_type result, uint32_t ch) + { + return (ch < 0x10000) ? low(result, ch) : high(result, ch); + } + }; + + struct utf32_counter + { + typedef size_t value_type; + + static value_type low(value_type result, uint32_t) + { + return result + 1; + } + + static value_type high(value_type result, uint32_t) + { + return result + 1; + } + }; + + struct utf32_writer + { + typedef uint32_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + *result = ch; + + return result + 1; + } + + static value_type high(value_type result, uint32_t ch) + { + *result = ch; + + return result + 1; + } + + static value_type any(value_type result, uint32_t ch) + { + *result = ch; + + return result + 1; + } + }; + + template struct wchar_selector; + + template <> struct wchar_selector<2> + { + typedef uint16_t type; + typedef utf16_counter counter; + typedef utf16_writer writer; + }; + + template <> struct wchar_selector<4> + { + typedef uint32_t type; + typedef utf32_counter counter; + typedef utf32_writer writer; + }; + + typedef wchar_selector::counter wchar_counter; + typedef wchar_selector::writer wchar_writer; + + template struct utf_decoder + { + static inline typename Traits::value_type decode_utf8_block(const uint8_t* data, size_t size, typename Traits::value_type result) + { + const uint8_t utf8_byte_mask = 0x3f; + + while (size) + { + uint8_t lead = *data; + + // 0xxxxxxx -> U+0000..U+007F + if (lead < 0x80) + { + result = Traits::low(result, lead); + data += 1; + size -= 1; + + // process aligned single-byte (ascii) blocks + if ((reinterpret_cast(data) & 3) == 0) + { + while (size >= 4 && (*reinterpret_cast(data) & 0x80808080) == 0) + { + result = Traits::low(result, data[0]); + result = Traits::low(result, data[1]); + result = Traits::low(result, data[2]); + result = Traits::low(result, data[3]); + data += 4; + size -= 4; + } + } + } + // 110xxxxx -> U+0080..U+07FF + else if ((unsigned)(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80) + { + result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask)); + data += 2; + size -= 2; + } + // 1110xxxx -> U+0800-U+FFFF + else if ((unsigned)(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80) + { + result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask)); + data += 3; + size -= 3; + } + // 11110xxx -> U+10000..U+10FFFF + else if ((unsigned)(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80) + { + result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask)); + data += 4; + size -= 4; + } + // 10xxxxxx or 11111xxx -> invalid + else + { + data += 1; + size -= 1; + } + } + + return result; + } + + static inline typename Traits::value_type decode_utf16_block(const uint16_t* data, size_t size, typename Traits::value_type result) + { + const uint16_t* end = data + size; + + while (data < end) + { + uint16_t lead = opt_swap::value ? endian_swap(*data) : *data; + + // U+0000..U+D7FF + if (lead < 0xD800) + { + result = Traits::low(result, lead); + data += 1; + } + // U+E000..U+FFFF + else if ((unsigned)(lead - 0xE000) < 0x2000) + { + result = Traits::low(result, lead); + data += 1; + } + // surrogate pair lead + else if ((unsigned)(lead - 0xD800) < 0x400 && data + 1 < end) + { + uint16_t next = opt_swap::value ? endian_swap(data[1]) : data[1]; + + if ((unsigned)(next - 0xDC00) < 0x400) + { + result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff)); + data += 2; + } + else + { + data += 1; + } + } + else + { + data += 1; + } + } + + return result; + } + + static inline typename Traits::value_type decode_utf32_block(const uint32_t* data, size_t size, typename Traits::value_type result) + { + const uint32_t* end = data + size; + + while (data < end) + { + uint32_t lead = opt_swap::value ? endian_swap(*data) : *data; + + // U+0000..U+FFFF + if (lead < 0x10000) + { + result = Traits::low(result, lead); + data += 1; + } + // U+10000..U+10FFFF + else + { + result = Traits::high(result, lead); + data += 1; + } + } + + return result; + } + }; + + template inline void convert_utf_endian_swap(T* result, const T* data, size_t length) + { + for (size_t i = 0; i < length; ++i) result[i] = endian_swap(data[i]); + } + + inline void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length) + { + for (size_t i = 0; i < length; ++i) result[i] = static_cast(endian_swap(static_cast::type>(data[i]))); + } +} + +namespace +{ + enum chartype_t + { + ct_parse_pcdata = 1, // \0, &, \r, < + ct_parse_attr = 2, // \0, &, \r, ', " + ct_parse_attr_ws = 4, // \0, &, \r, ', ", \n, tab + ct_space = 8, // \r, \n, space, tab + ct_parse_cdata = 16, // \0, ], >, \r + ct_parse_comment = 32, // \0, -, >, \r + ct_symbol = 64, // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, . + ct_start_symbol = 128 // Any symbol > 127, a-z, A-Z, _, : + }; + + const unsigned char chartype_table[256] = + { + 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0, // 32-47 + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0, // 48-63 + 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 64-79 + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192, // 80-95 + 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 96-111 + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0, // 112-127 + + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 128+ + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192 + }; + + enum chartypex_t + { + ctx_special_pcdata = 1, // Any symbol >= 0 and < 32 (except \t, \r, \n), &, <, > + ctx_special_attr = 2, // Any symbol >= 0 and < 32 (except \t), &, <, >, " + ctx_start_symbol = 4, // Any symbol > 127, a-z, A-Z, _ + ctx_digit = 8, // 0-9 + ctx_symbol = 16 // Any symbol > 127, a-z, A-Z, 0-9, _, -, . + }; + + const unsigned char chartypex_table[256] = + { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3, // 0-15 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16-31 + 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47 + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 3, 0, // 48-63 + + 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 64-79 + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20, // 80-95 + 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 96-111 + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, // 112-127 + + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 128+ + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 + }; + +#ifdef PUGIXML_WCHAR_MODE + #define IS_CHARTYPE_IMPL(c, ct, table) ((static_cast(c) < 128 ? table[static_cast(c)] : table[128]) & (ct)) +#else + #define IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast(c)] & (ct)) +#endif + + #define IS_CHARTYPE(c, ct) IS_CHARTYPE_IMPL(c, ct, chartype_table) + #define IS_CHARTYPEX(c, ct) IS_CHARTYPE_IMPL(c, ct, chartypex_table) + + bool is_little_endian() + { + unsigned int ui = 1; + + return *reinterpret_cast(&ui) == 1; + } + + xml_encoding get_wchar_encoding() + { + STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); + + if (sizeof(wchar_t) == 2) + return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + else + return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + } + + xml_encoding guess_buffer_encoding(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) + { + // look for BOM in first few bytes + if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff) return encoding_utf32_be; + if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0) return encoding_utf32_le; + if (d0 == 0xfe && d1 == 0xff) return encoding_utf16_be; + if (d0 == 0xff && d1 == 0xfe) return encoding_utf16_le; + if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf) return encoding_utf8; + + // look for <, (contents); + + DMC_VOLATILE uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3]; + + return guess_buffer_encoding(d0, d1, d2, d3); + } + + bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + { + if (is_mutable) + { + out_buffer = static_cast(const_cast(contents)); + } + else + { + void* buffer = global_allocate(size > 0 ? size : 1); + if (!buffer) return false; + + memcpy(buffer, contents, size); + + out_buffer = static_cast(buffer); + } + + out_length = size / sizeof(char_t); + + return true; + } + +#ifdef PUGIXML_WCHAR_MODE + inline bool need_endian_swap_utf(xml_encoding le, xml_encoding re) + { + return (le == encoding_utf16_be && re == encoding_utf16_le) || (le == encoding_utf16_le && re == encoding_utf16_be) || + (le == encoding_utf32_be && re == encoding_utf32_le) || (le == encoding_utf32_le && re == encoding_utf32_be); + } + + bool convert_buffer_endian_swap(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + { + const char_t* data = static_cast(contents); + + if (is_mutable) + { + out_buffer = const_cast(data); + } + else + { + out_buffer = static_cast(global_allocate(size > 0 ? size : 1)); + if (!out_buffer) return false; + } + + out_length = size / sizeof(char_t); + + convert_wchar_endian_swap(out_buffer, data, out_length); + + return true; + } + + bool convert_buffer_utf8(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size) + { + const uint8_t* data = static_cast(contents); + + // first pass: get length in wchar_t units + out_length = utf_decoder::decode_utf8_block(data, size, 0); + + // allocate buffer of suitable length + out_buffer = static_cast(global_allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); + if (!out_buffer) return false; + + // second pass: convert utf8 input to wchar_t + wchar_writer::value_type out_begin = reinterpret_cast(out_buffer); + wchar_writer::value_type out_end = utf_decoder::decode_utf8_block(data, size, out_begin); + + assert(out_end == out_begin + out_length); + (void)!out_end; + + return true; + } + + template bool convert_buffer_utf16(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) + { + const uint16_t* data = static_cast(contents); + size_t length = size / sizeof(uint16_t); + + // first pass: get length in wchar_t units + out_length = utf_decoder::decode_utf16_block(data, length, 0); + + // allocate buffer of suitable length + out_buffer = static_cast(global_allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); + if (!out_buffer) return false; + + // second pass: convert utf16 input to wchar_t + wchar_writer::value_type out_begin = reinterpret_cast(out_buffer); + wchar_writer::value_type out_end = utf_decoder::decode_utf16_block(data, length, out_begin); + + assert(out_end == out_begin + out_length); + (void)!out_end; + + return true; + } + + template bool convert_buffer_utf32(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) + { + const uint32_t* data = static_cast(contents); + size_t length = size / sizeof(uint32_t); + + // first pass: get length in wchar_t units + out_length = utf_decoder::decode_utf32_block(data, length, 0); + + // allocate buffer of suitable length + out_buffer = static_cast(global_allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); + if (!out_buffer) return false; + + // second pass: convert utf32 input to wchar_t + wchar_writer::value_type out_begin = reinterpret_cast(out_buffer); + wchar_writer::value_type out_end = utf_decoder::decode_utf32_block(data, length, out_begin); + + assert(out_end == out_begin + out_length); + (void)!out_end; + + return true; + } + + bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) + { + // get native encoding + xml_encoding wchar_encoding = get_wchar_encoding(); + + // fast path: no conversion required + if (encoding == wchar_encoding) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); + + // only endian-swapping is required + if (need_endian_swap_utf(encoding, wchar_encoding)) return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable); + + // source encoding is utf8 + if (encoding == encoding_utf8) return convert_buffer_utf8(out_buffer, out_length, contents, size); + + // source encoding is utf16 + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + return (native_encoding == encoding) ? + convert_buffer_utf16(out_buffer, out_length, contents, size, opt_false()) : + convert_buffer_utf16(out_buffer, out_length, contents, size, opt_true()); + } + + // source encoding is utf32 + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + return (native_encoding == encoding) ? + convert_buffer_utf32(out_buffer, out_length, contents, size, opt_false()) : + convert_buffer_utf32(out_buffer, out_length, contents, size, opt_true()); + } + + assert(!"Invalid encoding"); + return false; + } +#else + template bool convert_buffer_utf16(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) + { + const uint16_t* data = static_cast(contents); + size_t length = size / sizeof(uint16_t); + + // first pass: get length in utf8 units + out_length = utf_decoder::decode_utf16_block(data, length, 0); + + // allocate buffer of suitable length + out_buffer = static_cast(global_allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); + if (!out_buffer) return false; + + // second pass: convert utf16 input to utf8 + uint8_t* out_begin = reinterpret_cast(out_buffer); + uint8_t* out_end = utf_decoder::decode_utf16_block(data, length, out_begin); + + assert(out_end == out_begin + out_length); + (void)!out_end; + + return true; + } + + template bool convert_buffer_utf32(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) + { + const uint32_t* data = static_cast(contents); + size_t length = size / sizeof(uint32_t); + + // first pass: get length in utf8 units + out_length = utf_decoder::decode_utf32_block(data, length, 0); + + // allocate buffer of suitable length + out_buffer = static_cast(global_allocate((out_length > 0 ? out_length : 1) * sizeof(char_t))); + if (!out_buffer) return false; + + // second pass: convert utf32 input to utf8 + uint8_t* out_begin = reinterpret_cast(out_buffer); + uint8_t* out_end = utf_decoder::decode_utf32_block(data, length, out_begin); + + assert(out_end == out_begin + out_length); + (void)!out_end; + + return true; + } + + bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) + { + // fast path: no conversion required + if (encoding == encoding_utf8) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); + + // source encoding is utf16 + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + return (native_encoding == encoding) ? + convert_buffer_utf16(out_buffer, out_length, contents, size, opt_false()) : + convert_buffer_utf16(out_buffer, out_length, contents, size, opt_true()); + } + + // source encoding is utf32 + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + return (native_encoding == encoding) ? + convert_buffer_utf32(out_buffer, out_length, contents, size, opt_false()) : + convert_buffer_utf32(out_buffer, out_length, contents, size, opt_true()); + } + + assert(!"Invalid encoding"); + return false; + } +#endif + + size_t as_utf8_begin(const wchar_t* str, size_t length) + { + STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); + + // get length in utf8 characters + return sizeof(wchar_t) == 2 ? + utf_decoder::decode_utf16_block(reinterpret_cast(str), length, 0) : + utf_decoder::decode_utf32_block(reinterpret_cast(str), length, 0); + } + + void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length) + { + STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); + + // convert to utf8 + uint8_t* begin = reinterpret_cast(buffer); + uint8_t* end = sizeof(wchar_t) == 2 ? + utf_decoder::decode_utf16_block(reinterpret_cast(str), length, begin) : + utf_decoder::decode_utf32_block(reinterpret_cast(str), length, begin); + + assert(begin + size == end); + (void)!end; + + // zero-terminate + buffer[size] = 0; + } + +#ifndef PUGIXML_NO_STL + std::string as_utf8_impl(const wchar_t* str, size_t length) + { + // first pass: get length in utf8 characters + size_t size = as_utf8_begin(str, length); + + // allocate resulting string + std::string result; + result.resize(size); + + // second pass: convert to utf8 + if (size > 0) as_utf8_end(&result[0], size, str, length); + + return result; + } + + std::wstring as_wide_impl(const char* str, size_t size) + { + const uint8_t* data = reinterpret_cast(str); + + // first pass: get length in wchar_t units + size_t length = utf_decoder::decode_utf8_block(data, size, 0); + + // allocate resulting string + std::wstring result; + result.resize(length); + + // second pass: convert to wchar_t + if (length > 0) + { + wchar_writer::value_type begin = reinterpret_cast(&result[0]); + wchar_writer::value_type end = utf_decoder::decode_utf8_block(data, size, begin); + + assert(begin + length == end); + (void)!end; + } + + return result; + } +#endif + + inline bool strcpy_insitu_allow(size_t length, uintptr_t allocated, char_t* target) + { + assert(target); + size_t target_length = strlength(target); + + // always reuse document buffer memory if possible + if (!allocated) return target_length >= length; + + // reuse heap memory if waste is not too great + const size_t reuse_threshold = 32; + + return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2); + } + + bool strcpy_insitu(char_t*& dest, uintptr_t& header, uintptr_t header_mask, const char_t* source) + { + size_t source_length = strlength(source); + + if (source_length == 0) + { + // empty string and null pointer are equivalent, so just deallocate old memory + xml_allocator* alloc = reinterpret_cast(header & xml_memory_page_pointer_mask)->allocator; + + if (header & header_mask) alloc->deallocate_string(dest); + + // mark the string as not allocated + dest = 0; + header &= ~header_mask; + + return true; + } + else if (dest && strcpy_insitu_allow(source_length, header & header_mask, dest)) + { + // we can reuse old buffer, so just copy the new data (including zero terminator) + memcpy(dest, source, (source_length + 1) * sizeof(char_t)); + + return true; + } + else + { + xml_allocator* alloc = reinterpret_cast(header & xml_memory_page_pointer_mask)->allocator; + + // allocate new buffer + char_t* buf = alloc->allocate_string(source_length + 1); + if (!buf) return false; + + // copy the string (including zero terminator) + memcpy(buf, source, (source_length + 1) * sizeof(char_t)); + + // deallocate old buffer (*after* the above to protect against overlapping memory and/or allocation failures) + if (header & header_mask) alloc->deallocate_string(dest); + + // the string is now allocated, so set the flag + dest = buf; + header |= header_mask; + + return true; + } + } + + struct gap + { + char_t* end; + size_t size; + + gap(): end(0), size(0) + { + } + + // Push new gap, move s count bytes further (skipping the gap). + // Collapse previous gap. + void push(char_t*& s, size_t count) + { + if (end) // there was a gap already; collapse it + { + // Move [old_gap_end, new_gap_start) to [old_gap_start, ...) + assert(s >= end); + memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); + } + + s += count; // end of current gap + + // "merge" two gaps + end = s; + size += count; + } + + // Collapse all gaps, return past-the-end pointer + char_t* flush(char_t* s) + { + if (end) + { + // Move [old_gap_end, current_pos) to [old_gap_start, ...) + assert(s >= end); + memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); + + return s - size; + } + else return s; + } + }; + + char_t* strconv_escape(char_t* s, gap& g) + { + char_t* stre = s + 1; + + switch (*stre) + { + case '#': // &#... + { + unsigned int ucsc = 0; + + if (stre[1] == 'x') // &#x... (hex code) + { + stre += 2; + + char_t ch = *stre; + + if (ch == ';') return stre; + + for (;;) + { + if (static_cast(ch - '0') <= 9) + ucsc = 16 * ucsc + (ch - '0'); + else if (static_cast((ch | ' ') - 'a') <= 5) + ucsc = 16 * ucsc + ((ch | ' ') - 'a' + 10); + else if (ch == ';') + break; + else // cancel + return stre; + + ch = *++stre; + } + + ++stre; + } + else // &#... (dec code) + { + char_t ch = *++stre; + + if (ch == ';') return stre; + + for (;;) + { + if (static_cast(ch - '0') <= 9) + ucsc = 10 * ucsc + (ch - '0'); + else if (ch == ';') + break; + else // cancel + return stre; + + ch = *++stre; + } + + ++stre; + } + + #ifdef PUGIXML_WCHAR_MODE + s = reinterpret_cast(wchar_writer::any(reinterpret_cast(s), ucsc)); + #else + s = reinterpret_cast(utf8_writer::any(reinterpret_cast(s), ucsc)); + #endif + + g.push(s, stre - s); + return stre; + } + case 'a': // &a + { + ++stre; + + if (*stre == 'm') // &am + { + if (*++stre == 'p' && *++stre == ';') // & + { + *s++ = '&'; + ++stre; + + g.push(s, stre - s); + return stre; + } + } + else if (*stre == 'p') // &ap + { + if (*++stre == 'o' && *++stre == 's' && *++stre == ';') // ' + { + *s++ = '\''; + ++stre; + + g.push(s, stre - s); + return stre; + } + } + break; + } + case 'g': // &g + { + if (*++stre == 't' && *++stre == ';') // > + { + *s++ = '>'; + ++stre; + + g.push(s, stre - s); + return stre; + } + break; + } + case 'l': // &l + { + if (*++stre == 't' && *++stre == ';') // < + { + *s++ = '<'; + ++stre; + + g.push(s, stre - s); + return stre; + } + break; + } + case 'q': // &q + { + if (*++stre == 'u' && *++stre == 'o' && *++stre == 't' && *++stre == ';') // " + { + *s++ = '"'; + ++stre; + + g.push(s, stre - s); + return stre; + } + break; + } + } + + return stre; + } + + // Utility macro for last character handling + #define ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e))) + + char_t* strconv_comment(char_t* s, char_t endch) + { + gap g; + + while (true) + { + while (!IS_CHARTYPE(*s, ct_parse_comment)) ++s; + + if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair + { + *s++ = '\n'; // replace first one with 0x0a + + if (*s == '\n') g.push(s, 1); + } + else if (s[0] == '-' && s[1] == '-' && ENDSWITH(s[2], '>')) // comment ends here + { + *g.flush(s) = 0; + + return s + (s[2] == '>' ? 3 : 2); + } + else if (*s == 0) + { + return 0; + } + else ++s; + } + } + + char_t* strconv_cdata(char_t* s, char_t endch) + { + gap g; + + while (true) + { + while (!IS_CHARTYPE(*s, ct_parse_cdata)) ++s; + + if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair + { + *s++ = '\n'; // replace first one with 0x0a + + if (*s == '\n') g.push(s, 1); + } + else if (s[0] == ']' && s[1] == ']' && ENDSWITH(s[2], '>')) // CDATA ends here + { + *g.flush(s) = 0; + + return s + 1; + } + else if (*s == 0) + { + return 0; + } + else ++s; + } + } + + typedef char_t* (*strconv_pcdata_t)(char_t*); + + template struct strconv_pcdata_impl + { + static char_t* parse(char_t* s) + { + gap g; + + while (true) + { + while (!IS_CHARTYPE(*s, ct_parse_pcdata)) ++s; + + if (*s == '<') // PCDATA ends here + { + *g.flush(s) = 0; + + return s + 1; + } + else if (opt_eol::value && *s == '\r') // Either a single 0x0d or 0x0d 0x0a pair + { + *s++ = '\n'; // replace first one with 0x0a + + if (*s == '\n') g.push(s, 1); + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (*s == 0) + { + return s; + } + else ++s; + } + } + }; + + strconv_pcdata_t get_strconv_pcdata(unsigned int optmask) + { + STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20); + + switch ((optmask >> 4) & 3) // get bitmask for flags (eol escapes) + { + case 0: return strconv_pcdata_impl::parse; + case 1: return strconv_pcdata_impl::parse; + case 2: return strconv_pcdata_impl::parse; + case 3: return strconv_pcdata_impl::parse; + default: return 0; // should not get here + } + } + + typedef char_t* (*strconv_attribute_t)(char_t*, char_t); + + template struct strconv_attribute_impl + { + static char_t* parse_wnorm(char_t* s, char_t end_quote) + { + gap g; + + // trim leading whitespaces + if (IS_CHARTYPE(*s, ct_space)) + { + char_t* str = s; + + do ++str; + while (IS_CHARTYPE(*str, ct_space)); + + g.push(s, str - s); + } + + while (true) + { + while (!IS_CHARTYPE(*s, ct_parse_attr_ws | ct_space)) ++s; + + if (*s == end_quote) + { + char_t* str = g.flush(s); + + do *str-- = 0; + while (IS_CHARTYPE(*str, ct_space)); + + return s + 1; + } + else if (IS_CHARTYPE(*s, ct_space)) + { + *s++ = ' '; + + if (IS_CHARTYPE(*s, ct_space)) + { + char_t* str = s + 1; + while (IS_CHARTYPE(*str, ct_space)) ++str; + + g.push(s, str - s); + } + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + + static char_t* parse_wconv(char_t* s, char_t end_quote) + { + gap g; + + while (true) + { + while (!IS_CHARTYPE(*s, ct_parse_attr_ws)) ++s; + + if (*s == end_quote) + { + *g.flush(s) = 0; + + return s + 1; + } + else if (IS_CHARTYPE(*s, ct_space)) + { + if (*s == '\r') + { + *s++ = ' '; + + if (*s == '\n') g.push(s, 1); + } + else *s++ = ' '; + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + + static char_t* parse_eol(char_t* s, char_t end_quote) + { + gap g; + + while (true) + { + while (!IS_CHARTYPE(*s, ct_parse_attr)) ++s; + + if (*s == end_quote) + { + *g.flush(s) = 0; + + return s + 1; + } + else if (*s == '\r') + { + *s++ = '\n'; + + if (*s == '\n') g.push(s, 1); + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + + static char_t* parse_simple(char_t* s, char_t end_quote) + { + gap g; + + while (true) + { + while (!IS_CHARTYPE(*s, ct_parse_attr)) ++s; + + if (*s == end_quote) + { + *g.flush(s) = 0; + + return s + 1; + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + }; + + strconv_attribute_t get_strconv_attribute(unsigned int optmask) + { + STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); + + switch ((optmask >> 4) & 15) // get bitmask for flags (wconv wnorm eol escapes) + { + case 0: return strconv_attribute_impl::parse_simple; + case 1: return strconv_attribute_impl::parse_simple; + case 2: return strconv_attribute_impl::parse_eol; + case 3: return strconv_attribute_impl::parse_eol; + case 4: return strconv_attribute_impl::parse_wconv; + case 5: return strconv_attribute_impl::parse_wconv; + case 6: return strconv_attribute_impl::parse_wconv; + case 7: return strconv_attribute_impl::parse_wconv; + case 8: return strconv_attribute_impl::parse_wnorm; + case 9: return strconv_attribute_impl::parse_wnorm; + case 10: return strconv_attribute_impl::parse_wnorm; + case 11: return strconv_attribute_impl::parse_wnorm; + case 12: return strconv_attribute_impl::parse_wnorm; + case 13: return strconv_attribute_impl::parse_wnorm; + case 14: return strconv_attribute_impl::parse_wnorm; + case 15: return strconv_attribute_impl::parse_wnorm; + default: return 0; // should not get here + } + } + + inline xml_parse_result make_parse_result(xml_parse_status status, ptrdiff_t offset = 0) + { + xml_parse_result result; + result.status = status; + result.offset = offset; + + return result; + } + + struct xml_parser + { + xml_allocator alloc; + char_t* error_offset; + jmp_buf error_handler; + + // Parser utilities. + #define SKIPWS() { while (IS_CHARTYPE(*s, ct_space)) ++s; } + #define OPTSET(OPT) ( optmsk & OPT ) + #define PUSHNODE(TYPE) { cursor = append_node(cursor, alloc, TYPE); if (!cursor) THROW_ERROR(status_out_of_memory, s); } + #define POPNODE() { cursor = cursor->parent; } + #define SCANFOR(X) { while (*s != 0 && !(X)) ++s; } + #define SCANWHILE(X) { while ((X)) ++s; } + #define ENDSEG() { ch = *s; *s = 0; ++s; } + #define THROW_ERROR(err, m) error_offset = m, longjmp(error_handler, err) + #define CHECK_ERROR(err, m) { if (*s == 0) THROW_ERROR(err, m); } + + xml_parser(const xml_allocator& alloc): alloc(alloc), error_offset(0) + { + } + + // DOCTYPE consists of nested sections of the following possible types: + // , , "...", '...' + // + // + // First group can not contain nested groups + // Second group can contain nested groups of the same type + // Third group can contain all other groups + char_t* parse_doctype_primitive(char_t* s) + { + if (*s == '"' || *s == '\'') + { + // quoted string + char_t ch = *s++; + SCANFOR(*s == ch); + if (!*s) THROW_ERROR(status_bad_doctype, s); + + s++; + } + else if (s[0] == '<' && s[1] == '?') + { + // + s += 2; + SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype + if (!*s) THROW_ERROR(status_bad_doctype, s); + + s += 2; + } + else if (s[0] == '<' && s[1] == '!' && s[2] == '-' && s[3] == '-') + { + s += 4; + SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype + if (!*s) THROW_ERROR(status_bad_doctype, s); + + s += 4; + } + else THROW_ERROR(status_bad_doctype, s); + + return s; + } + + char_t* parse_doctype_ignore(char_t* s) + { + assert(s[0] == '<' && s[1] == '!' && s[2] == '['); + s++; + + while (*s) + { + if (s[0] == '<' && s[1] == '!' && s[2] == '[') + { + // nested ignore section + s = parse_doctype_ignore(s); + } + else if (s[0] == ']' && s[1] == ']' && s[2] == '>') + { + // ignore section end + s += 3; + + return s; + } + else s++; + } + + THROW_ERROR(status_bad_doctype, s); + + return s; + } + + char_t* parse_doctype_group(char_t* s, char_t endch, bool toplevel) + { + assert(s[0] == '<' && s[1] == '!'); + s++; + + while (*s) + { + if (s[0] == '<' && s[1] == '!' && s[2] != '-') + { + if (s[2] == '[') + { + // ignore + s = parse_doctype_ignore(s); + } + else + { + // some control group + s = parse_doctype_group(s, endch, false); + } + } + else if (s[0] == '<' || s[0] == '"' || s[0] == '\'') + { + // unknown tag (forbidden), or some primitive group + s = parse_doctype_primitive(s); + } + else if (*s == '>') + { + s++; + + return s; + } + else s++; + } + + if (!toplevel || endch != '>') THROW_ERROR(status_bad_doctype, s); + + return s; + } + + char_t* parse_exclamation(char_t* s, xml_node_struct* cursor, unsigned int optmsk, char_t endch) + { + // parse node contents, starting with exclamation mark + ++s; + + if (*s == '-') // 'value = s; // Save the offset. + } + + if (OPTSET(parse_eol) && OPTSET(parse_comments)) + { + s = strconv_comment(s, endch); + + if (!s) THROW_ERROR(status_bad_comment, cursor->value); + } + else + { + // Scan for terminating '-->'. + SCANFOR(s[0] == '-' && s[1] == '-' && ENDSWITH(s[2], '>')); + CHECK_ERROR(status_bad_comment, s); + + if (OPTSET(parse_comments)) + *s = 0; // Zero-terminate this segment at the first terminating '-'. + + s += (s[2] == '>' ? 3 : 2); // Step over the '\0->'. + } + } + else THROW_ERROR(status_bad_comment, s); + } + else if (*s == '[') + { + // 'value = s; // Save the offset. + + if (OPTSET(parse_eol)) + { + s = strconv_cdata(s, endch); + + if (!s) THROW_ERROR(status_bad_cdata, cursor->value); + } + else + { + // Scan for terminating ']]>'. + SCANFOR(s[0] == ']' && s[1] == ']' && ENDSWITH(s[2], '>')); + CHECK_ERROR(status_bad_cdata, s); + + *s++ = 0; // Zero-terminate this segment. + } + } + else // Flagged for discard, but we still have to scan for the terminator. + { + // Scan for terminating ']]>'. + SCANFOR(s[0] == ']' && s[1] == ']' && ENDSWITH(s[2], '>')); + CHECK_ERROR(status_bad_cdata, s); + + ++s; + } + + s += (s[1] == '>' ? 2 : 1); // Step over the last ']>'. + } + else THROW_ERROR(status_bad_cdata, s); + } + else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && ENDSWITH(s[6], 'E')) + { + s -= 2; + + if (cursor->parent) THROW_ERROR(status_bad_doctype, s); + + char_t* mark = s + 9; + + s = parse_doctype_group(s, endch, true); + + if (OPTSET(parse_doctype)) + { + while (IS_CHARTYPE(*mark, ct_space)) ++mark; + + PUSHNODE(node_doctype); + + cursor->value = mark; + + assert((s[0] == 0 && endch == '>') || s[-1] == '>'); + s[*s == 0 ? 0 : -1] = 0; + + POPNODE(); + } + } + else if (*s == 0 && endch == '-') THROW_ERROR(status_bad_comment, s); + else if (*s == 0 && endch == '[') THROW_ERROR(status_bad_cdata, s); + else THROW_ERROR(status_unrecognized_tag, s); + + return s; + } + + char_t* parse_question(char_t* s, xml_node_struct*& ref_cursor, unsigned int optmsk, char_t endch) + { + // load into registers + xml_node_struct* cursor = ref_cursor; + char_t ch = 0; + + // parse node contents, starting with question mark + ++s; + + // read PI target + char_t* target = s; + + if (!IS_CHARTYPE(*s, ct_start_symbol)) THROW_ERROR(status_bad_pi, s); + + SCANWHILE(IS_CHARTYPE(*s, ct_symbol)); + CHECK_ERROR(status_bad_pi, s); + + // determine node type; stricmp / strcasecmp is not portable + bool declaration = (target[0] | ' ') == 'x' && (target[1] | ' ') == 'm' && (target[2] | ' ') == 'l' && target + 3 == s; + + if (declaration ? OPTSET(parse_declaration) : OPTSET(parse_pi)) + { + if (declaration) + { + // disallow non top-level declarations + if (cursor->parent) THROW_ERROR(status_bad_pi, s); + + PUSHNODE(node_declaration); + } + else + { + PUSHNODE(node_pi); + } + + cursor->name = target; + + ENDSEG(); + + // parse value/attributes + if (ch == '?') + { + // empty node + if (!ENDSWITH(*s, '>')) THROW_ERROR(status_bad_pi, s); + s += (*s == '>'); + + POPNODE(); + } + else if (IS_CHARTYPE(ch, ct_space)) + { + SKIPWS(); + + // scan for tag end + char_t* value = s; + + SCANFOR(s[0] == '?' && ENDSWITH(s[1], '>')); + CHECK_ERROR(status_bad_pi, s); + + if (declaration) + { + // replace ending ? with / so that 'element' terminates properly + *s = '/'; + + // we exit from this function with cursor at node_declaration, which is a signal to parse() to go to LOC_ATTRIBUTES + s = value; + } + else + { + // store value and step over > + cursor->value = value; + POPNODE(); + + ENDSEG(); + + s += (*s == '>'); + } + } + else THROW_ERROR(status_bad_pi, s); + } + else + { + // scan for tag end + SCANFOR(s[0] == '?' && ENDSWITH(s[1], '>')); + CHECK_ERROR(status_bad_pi, s); + + s += (s[1] == '>' ? 2 : 1); + } + + // store from registers + ref_cursor = cursor; + + return s; + } + + void parse(char_t* s, xml_node_struct* xmldoc, unsigned int optmsk, char_t endch) + { + strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk); + strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk); + + char_t ch = 0; + xml_node_struct* cursor = xmldoc; + char_t* mark = s; + + while (*s != 0) + { + if (*s == '<') + { + ++s; + + LOC_TAG: + if (IS_CHARTYPE(*s, ct_start_symbol)) // '<#...' + { + PUSHNODE(node_element); // Append a new node to the tree. + + cursor->name = s; + + SCANWHILE(IS_CHARTYPE(*s, ct_symbol)); // Scan for a terminator. + ENDSEG(); // Save char in 'ch', terminate & step over. + + if (ch == '>') + { + // end of tag + } + else if (IS_CHARTYPE(ch, ct_space)) + { + LOC_ATTRIBUTES: + while (true) + { + SKIPWS(); // Eat any whitespace. + + if (IS_CHARTYPE(*s, ct_start_symbol)) // <... #... + { + xml_attribute_struct* a = append_attribute_ll(cursor, alloc); // Make space for this attribute. + if (!a) THROW_ERROR(status_out_of_memory, s); + + a->name = s; // Save the offset. + + SCANWHILE(IS_CHARTYPE(*s, ct_symbol)); // Scan for a terminator. + CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance + + ENDSEG(); // Save char in 'ch', terminate & step over. + CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance + + if (IS_CHARTYPE(ch, ct_space)) + { + SKIPWS(); // Eat any whitespace. + CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance + + ch = *s; + ++s; + } + + if (ch == '=') // '<... #=...' + { + SKIPWS(); // Eat any whitespace. + + if (*s == '"' || *s == '\'') // '<... #="...' + { + ch = *s; // Save quote char to avoid breaking on "''" -or- '""'. + ++s; // Step over the quote. + a->value = s; // Save the offset. + + s = strconv_attribute(s, ch); + + if (!s) THROW_ERROR(status_bad_attribute, a->value); + + // After this line the loop continues from the start; + // Whitespaces, / and > are ok, symbols and EOF are wrong, + // everything else will be detected + if (IS_CHARTYPE(*s, ct_start_symbol)) THROW_ERROR(status_bad_attribute, s); + } + else THROW_ERROR(status_bad_attribute, s); + } + else THROW_ERROR(status_bad_attribute, s); + } + else if (*s == '/') + { + ++s; + + if (*s == '>') + { + POPNODE(); + s++; + break; + } + else if (*s == 0 && endch == '>') + { + POPNODE(); + break; + } + else THROW_ERROR(status_bad_start_element, s); + } + else if (*s == '>') + { + ++s; + + break; + } + else if (*s == 0 && endch == '>') + { + break; + } + else THROW_ERROR(status_bad_start_element, s); + } + + // !!! + } + else if (ch == '/') // '<#.../' + { + if (!ENDSWITH(*s, '>')) THROW_ERROR(status_bad_start_element, s); + + POPNODE(); // Pop. + + s += (*s == '>'); + } + else if (ch == 0) + { + // we stepped over null terminator, backtrack & handle closing tag + --s; + + if (endch != '>') THROW_ERROR(status_bad_start_element, s); + } + else THROW_ERROR(status_bad_start_element, s); + } + else if (*s == '/') + { + ++s; + + char_t* name = cursor->name; + if (!name) THROW_ERROR(status_end_element_mismatch, s); + + while (IS_CHARTYPE(*s, ct_symbol)) + { + if (*s++ != *name++) THROW_ERROR(status_end_element_mismatch, s); + } + + if (*name) + { + if (*s == 0 && name[0] == endch && name[1] == 0) THROW_ERROR(status_bad_end_element, s); + else THROW_ERROR(status_end_element_mismatch, s); + } + + POPNODE(); // Pop. + + SKIPWS(); + + if (*s == 0) + { + if (endch != '>') THROW_ERROR(status_bad_end_element, s); + } + else + { + if (*s != '>') THROW_ERROR(status_bad_end_element, s); + ++s; + } + } + else if (*s == '?') // 'header & xml_memory_page_type_mask) + 1 == node_declaration) goto LOC_ATTRIBUTES; + } + else if (*s == '!') // 'parent) + { + PUSHNODE(node_pcdata); // Append a new node on the tree. + cursor->value = s; // Save the offset. + + s = strconv_pcdata(s); + + POPNODE(); // Pop since this is a standalone. + + if (!*s) break; + } + else + { + SCANFOR(*s == '<'); // '...<' + if (!*s) break; + + ++s; + } + + // We're after '<' + goto LOC_TAG; + } + } + + // check that last tag is closed + if (cursor != xmldoc) THROW_ERROR(status_end_element_mismatch, s); + } + + static xml_parse_result parse(char_t* buffer, size_t length, xml_node_struct* root, unsigned int optmsk) + { + xml_document_struct* xmldoc = static_cast(root); + + // store buffer for offset_debug + xmldoc->buffer = buffer; + + // early-out for empty documents + if (length == 0) return make_parse_result(status_ok); + + // create parser on stack + xml_parser parser(*xmldoc); + + // save last character and make buffer zero-terminated (speeds up parsing) + char_t endch = buffer[length - 1]; + buffer[length - 1] = 0; + + // perform actual parsing + int error = setjmp(parser.error_handler); + + if (error == 0) + { + parser.parse(buffer, xmldoc, optmsk, endch); + } + + xml_parse_result result = make_parse_result(static_cast(error), parser.error_offset ? parser.error_offset - buffer : 0); + assert(result.offset >= 0 && static_cast(result.offset) <= length); + + // update allocator state + *static_cast(xmldoc) = parser.alloc; + + // since we removed last character, we have to handle the only possible false positive + if (result && endch == '<') + { + // there's no possible well-formed document with < at the end + return make_parse_result(status_unrecognized_tag, length); + } + + return result; + } + }; + + // Output facilities + xml_encoding get_write_native_encoding() + { + #ifdef PUGIXML_WCHAR_MODE + return get_wchar_encoding(); + #else + return encoding_utf8; + #endif + } + + xml_encoding get_write_encoding(xml_encoding encoding) + { + // replace wchar encoding with utf implementation + if (encoding == encoding_wchar) return get_wchar_encoding(); + + // replace utf16 encoding with utf16 with specific endianness + if (encoding == encoding_utf16) return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + // replace utf32 encoding with utf32 with specific endianness + if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + // only do autodetection if no explicit encoding is requested + if (encoding != encoding_auto) return encoding; + + // assume utf8 encoding + return encoding_utf8; + } + +#ifdef PUGIXML_WCHAR_MODE + size_t get_valid_length(const char_t* data, size_t length) + { + assert(length > 0); + + // discard last character if it's the lead of a surrogate pair + return (sizeof(wchar_t) == 2 && (unsigned)(static_cast(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length; + } + + size_t convert_buffer(char* result, const char_t* data, size_t length, xml_encoding encoding) + { + // only endian-swapping is required + if (need_endian_swap_utf(encoding, get_wchar_encoding())) + { + convert_wchar_endian_swap(reinterpret_cast(result), data, length); + + return length * sizeof(char_t); + } + + // convert to utf8 + if (encoding == encoding_utf8) + { + uint8_t* dest = reinterpret_cast(result); + + uint8_t* end = sizeof(wchar_t) == 2 ? + utf_decoder::decode_utf16_block(reinterpret_cast(data), length, dest) : + utf_decoder::decode_utf32_block(reinterpret_cast(data), length, dest); + + return static_cast(end - dest); + } + + // convert to utf16 + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + uint16_t* dest = reinterpret_cast(result); + + // convert to native utf16 + uint16_t* end = utf_decoder::decode_utf32_block(reinterpret_cast(data), length, dest); + + // swap if necessary + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); + + return static_cast(end - dest) * sizeof(uint16_t); + } + + // convert to utf32 + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + uint32_t* dest = reinterpret_cast(result); + + // convert to native utf32 + uint32_t* end = utf_decoder::decode_utf16_block(reinterpret_cast(data), length, dest); + + // swap if necessary + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); + + return static_cast(end - dest) * sizeof(uint32_t); + } + + assert(!"Invalid encoding"); + return 0; + } +#else + size_t get_valid_length(const char_t* data, size_t length) + { + assert(length > 4); + + for (size_t i = 1; i <= 4; ++i) + { + uint8_t ch = static_cast(data[length - i]); + + // either a standalone character or a leading one + if ((ch & 0xc0) != 0x80) return length - i; + } + + // there are four non-leading characters at the end, sequence tail is broken so might as well process the whole chunk + return length; + } + + size_t convert_buffer(char* result, const char_t* data, size_t length, xml_encoding encoding) + { + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + uint16_t* dest = reinterpret_cast(result); + + // convert to native utf16 + uint16_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); + + // swap if necessary + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); + + return static_cast(end - dest) * sizeof(uint16_t); + } + + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + uint32_t* dest = reinterpret_cast(result); + + // convert to native utf32 + uint32_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); + + // swap if necessary + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); + + return static_cast(end - dest) * sizeof(uint32_t); + } + + assert(!"Invalid encoding"); + return 0; + } +#endif + + class xml_buffered_writer + { + xml_buffered_writer(const xml_buffered_writer&); + xml_buffered_writer& operator=(const xml_buffered_writer&); + + public: + xml_buffered_writer(xml_writer& writer, xml_encoding user_encoding): writer(writer), bufsize(0), encoding(get_write_encoding(user_encoding)) + { + } + + ~xml_buffered_writer() + { + flush(); + } + + void flush() + { + flush(buffer, bufsize); + bufsize = 0; + } + + void flush(const char_t* data, size_t size) + { + if (size == 0) return; + + // fast path, just write data + if (encoding == get_write_native_encoding()) + writer.write(data, size * sizeof(char_t)); + else + { + // convert chunk + size_t result = convert_buffer(scratch, data, size, encoding); + assert(result <= sizeof(scratch)); + + // write data + writer.write(scratch, result); + } + } + + void write(const char_t* data, size_t length) + { + if (bufsize + length > bufcapacity) + { + // flush the remaining buffer contents + flush(); + + // handle large chunks + if (length > bufcapacity) + { + if (encoding == get_write_native_encoding()) + { + // fast path, can just write data chunk + writer.write(data, length * sizeof(char_t)); + return; + } + + // need to convert in suitable chunks + while (length > bufcapacity) + { + // get chunk size by selecting such number of characters that are guaranteed to fit into scratch buffer + // and form a complete codepoint sequence (i.e. discard start of last codepoint if necessary) + size_t chunk_size = get_valid_length(data, bufcapacity); + + // convert chunk and write + flush(data, chunk_size); + + // iterate + data += chunk_size; + length -= chunk_size; + } + + // small tail is copied below + bufsize = 0; + } + } + + memcpy(buffer + bufsize, data, length * sizeof(char_t)); + bufsize += length; + } + + void write(const char_t* data) + { + write(data, strlength(data)); + } + + void write(char_t d0) + { + if (bufsize + 1 > bufcapacity) flush(); + + buffer[bufsize + 0] = d0; + bufsize += 1; + } + + void write(char_t d0, char_t d1) + { + if (bufsize + 2 > bufcapacity) flush(); + + buffer[bufsize + 0] = d0; + buffer[bufsize + 1] = d1; + bufsize += 2; + } + + void write(char_t d0, char_t d1, char_t d2) + { + if (bufsize + 3 > bufcapacity) flush(); + + buffer[bufsize + 0] = d0; + buffer[bufsize + 1] = d1; + buffer[bufsize + 2] = d2; + bufsize += 3; + } + + void write(char_t d0, char_t d1, char_t d2, char_t d3) + { + if (bufsize + 4 > bufcapacity) flush(); + + buffer[bufsize + 0] = d0; + buffer[bufsize + 1] = d1; + buffer[bufsize + 2] = d2; + buffer[bufsize + 3] = d3; + bufsize += 4; + } + + void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4) + { + if (bufsize + 5 > bufcapacity) flush(); + + buffer[bufsize + 0] = d0; + buffer[bufsize + 1] = d1; + buffer[bufsize + 2] = d2; + buffer[bufsize + 3] = d3; + buffer[bufsize + 4] = d4; + bufsize += 5; + } + + void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5) + { + if (bufsize + 6 > bufcapacity) flush(); + + buffer[bufsize + 0] = d0; + buffer[bufsize + 1] = d1; + buffer[bufsize + 2] = d2; + buffer[bufsize + 3] = d3; + buffer[bufsize + 4] = d4; + buffer[bufsize + 5] = d5; + bufsize += 6; + } + + // utf8 maximum expansion: x4 (-> utf32) + // utf16 maximum expansion: x2 (-> utf32) + // utf32 maximum expansion: x1 + enum { bufcapacity = 2048 }; + + char_t buffer[bufcapacity]; + char scratch[4 * bufcapacity]; + + xml_writer& writer; + size_t bufsize; + xml_encoding encoding; + }; + + void write_bom(xml_writer& writer, xml_encoding encoding) + { + switch (encoding) + { + case encoding_utf8: + writer.write("\xef\xbb\xbf", 3); + break; + + case encoding_utf16_be: + writer.write("\xfe\xff", 2); + break; + + case encoding_utf16_le: + writer.write("\xff\xfe", 2); + break; + + case encoding_utf32_be: + writer.write("\x00\x00\xfe\xff", 4); + break; + + case encoding_utf32_le: + writer.write("\xff\xfe\x00\x00", 4); + break; + + default: + assert(!"Invalid encoding"); + } + } + + void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type) + { + while (*s) + { + const char_t* prev = s; + + // While *s is a usual symbol + while (!IS_CHARTYPEX(*s, type)) ++s; + + writer.write(prev, static_cast(s - prev)); + + switch (*s) + { + case 0: break; + case '&': + writer.write('&', 'a', 'm', 'p', ';'); + ++s; + break; + case '<': + writer.write('&', 'l', 't', ';'); + ++s; + break; + case '>': + writer.write('&', 'g', 't', ';'); + ++s; + break; + case '"': + writer.write('&', 'q', 'u', 'o', 't', ';'); + ++s; + break; + default: // s is not a usual symbol + { + unsigned int ch = static_cast(*s++); + assert(ch < 32); + + writer.write('&', '#', static_cast((ch / 10) + '0'), static_cast((ch % 10) + '0'), ';'); + } + } + } + } + + void text_output_cdata(xml_buffered_writer& writer, const char_t* s) + { + do + { + writer.write('<', '!', '[', 'C', 'D'); + writer.write('A', 'T', 'A', '['); + + const char_t* prev = s; + + // look for ]]> sequence - we can't output it as is since it terminates CDATA + while (*s && !(s[0] == ']' && s[1] == ']' && s[2] == '>')) ++s; + + // skip ]] if we stopped at ]]>, > will go to the next CDATA section + if (*s) s += 2; + + writer.write(prev, static_cast(s - prev)); + + writer.write(']', ']', '>'); + } + while (*s); + } + + void node_output_attributes(xml_buffered_writer& writer, const xml_node& node) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + + for (xml_attribute a = node.first_attribute(); a; a = a.next_attribute()) + { + writer.write(' '); + writer.write(a.name()[0] ? a.name() : default_name); + writer.write('=', '"'); + + text_output_escaped(writer, a.value(), ctx_special_attr); + + writer.write('"'); + } + } + + void node_output(xml_buffered_writer& writer, const xml_node& node, const char_t* indent, unsigned int flags, unsigned int depth) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + + if ((flags & format_indent) != 0 && (flags & format_raw) == 0) + for (unsigned int i = 0; i < depth; ++i) writer.write(indent); + + switch (node.type()) + { + case node_document: + { + for (xml_node n = node.first_child(); n; n = n.next_sibling()) + node_output(writer, n, indent, flags, depth); + break; + } + + case node_element: + { + const char_t* name = node.name()[0] ? node.name() : default_name; + + writer.write('<'); + writer.write(name); + + node_output_attributes(writer, node); + + if (flags & format_raw) + { + if (!node.first_child()) + writer.write(' ', '/', '>'); + else + { + writer.write('>'); + + for (xml_node n = node.first_child(); n; n = n.next_sibling()) + node_output(writer, n, indent, flags, depth + 1); + + writer.write('<', '/'); + writer.write(name); + writer.write('>'); + } + } + else if (!node.first_child()) + writer.write(' ', '/', '>', '\n'); + else if (node.first_child() == node.last_child() && (node.first_child().type() == node_pcdata || node.first_child().type() == node_cdata)) + { + writer.write('>'); + + if (node.first_child().type() == node_pcdata) + text_output_escaped(writer, node.first_child().value(), ctx_special_pcdata); + else + text_output_cdata(writer, node.first_child().value()); + + writer.write('<', '/'); + writer.write(name); + writer.write('>', '\n'); + } + else + { + writer.write('>', '\n'); + + for (xml_node n = node.first_child(); n; n = n.next_sibling()) + node_output(writer, n, indent, flags, depth + 1); + + if ((flags & format_indent) != 0 && (flags & format_raw) == 0) + for (unsigned int i = 0; i < depth; ++i) writer.write(indent); + + writer.write('<', '/'); + writer.write(name); + writer.write('>', '\n'); + } + + break; + } + + case node_pcdata: + text_output_escaped(writer, node.value(), ctx_special_pcdata); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + case node_cdata: + text_output_cdata(writer, node.value()); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + case node_comment: + writer.write('<', '!', '-', '-'); + writer.write(node.value()); + writer.write('-', '-', '>'); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + case node_pi: + case node_declaration: + writer.write('<', '?'); + writer.write(node.name()[0] ? node.name() : default_name); + + if (node.type() == node_declaration) + { + node_output_attributes(writer, node); + } + else if (node.value()[0]) + { + writer.write(' '); + writer.write(node.value()); + } + + writer.write('?', '>'); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + case node_doctype: + writer.write('<', '!', 'D', 'O', 'C'); + writer.write('T', 'Y', 'P', 'E'); + + if (node.value()[0]) + { + writer.write(' '); + writer.write(node.value()); + } + + writer.write('>'); + if ((flags & format_raw) == 0) writer.write('\n'); + break; + + default: + assert(!"Invalid node type"); + } + } + + inline bool has_declaration(const xml_node& node) + { + for (xml_node child = node.first_child(); child; child = child.next_sibling()) + { + xml_node_type type = child.type(); + + if (type == node_declaration) return true; + if (type == node_element) return false; + } + + return false; + } + + inline bool allow_insert_child(xml_node_type parent, xml_node_type child) + { + if (parent != node_document && parent != node_element) return false; + if (child == node_document || child == node_null) return false; + if (parent != node_document && (child == node_declaration || child == node_doctype)) return false; + + return true; + } + + void recursive_copy_skip(xml_node& dest, const xml_node& source, const xml_node& skip) + { + assert(dest.type() == source.type()); + + switch (source.type()) + { + case node_element: + { + dest.set_name(source.name()); + + for (xml_attribute a = source.first_attribute(); a; a = a.next_attribute()) + dest.append_attribute(a.name()).set_value(a.value()); + + for (xml_node c = source.first_child(); c; c = c.next_sibling()) + { + if (c == skip) continue; + + xml_node cc = dest.append_child(c.type()); + assert(cc); + + recursive_copy_skip(cc, c, skip); + } + + break; + } + + case node_pcdata: + case node_cdata: + case node_comment: + case node_doctype: + dest.set_value(source.value()); + break; + + case node_pi: + dest.set_name(source.name()); + dest.set_value(source.value()); + break; + + case node_declaration: + { + dest.set_name(source.name()); + + for (xml_attribute a = source.first_attribute(); a; a = a.next_attribute()) + dest.append_attribute(a.name()).set_value(a.value()); + + break; + } + + default: + assert(!"Invalid node type"); + } + } + + // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick + xml_parse_status get_file_size(FILE* file, size_t& out_result) + { + #if defined(_MSC_VER) && _MSC_VER >= 1400 + // there are 64-bit versions of fseek/ftell, let's use them + typedef __int64 length_type; + + _fseeki64(file, 0, SEEK_END); + length_type length = _ftelli64(file); + _fseeki64(file, 0, SEEK_SET); + #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && !defined(__STRICT_ANSI__) + // there are 64-bit versions of fseek/ftell, let's use them + typedef off64_t length_type; + + fseeko64(file, 0, SEEK_END); + length_type length = ftello64(file); + fseeko64(file, 0, SEEK_SET); + #else + // if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway. + typedef long length_type; + + fseek(file, 0, SEEK_END); + length_type length = ftell(file); + fseek(file, 0, SEEK_SET); + #endif + + // check for I/O errors + if (length < 0) return status_io_error; + + // check for overflow + size_t result = static_cast(length); + + if (static_cast(result) != length) return status_out_of_memory; + + // finalize + out_result = result; + + return status_ok; + } + + xml_parse_result load_file_impl(xml_document& doc, FILE* file, unsigned int options, xml_encoding encoding) + { + if (!file) return make_parse_result(status_file_not_found); + + // get file size (can result in I/O errors) + size_t size = 0; + xml_parse_status size_status = get_file_size(file, size); + + if (size_status != status_ok) + { + fclose(file); + return make_parse_result(size_status); + } + + // allocate buffer for the whole file + char* contents = static_cast(global_allocate(size > 0 ? size : 1)); + + if (!contents) + { + fclose(file); + return make_parse_result(status_out_of_memory); + } + + // read file in memory + size_t read_size = fread(contents, 1, size, file); + fclose(file); + + if (read_size != size) + { + global_deallocate(contents); + return make_parse_result(status_io_error); + } + + return doc.load_buffer_inplace_own(contents, size, options, encoding); + } + +#ifndef PUGIXML_NO_STL + template xml_parse_result load_stream_impl(xml_document& doc, std::basic_istream& stream, unsigned int options, xml_encoding encoding) + { + // get length of remaining data in stream + typename std::basic_istream::pos_type pos = stream.tellg(); + stream.seekg(0, std::ios::end); + std::streamoff length = stream.tellg() - pos; + stream.seekg(pos); + + if (stream.fail() || pos < 0) return make_parse_result(status_io_error); + + // guard against huge files + size_t read_length = static_cast(length); + + if (static_cast(read_length) != length || length < 0) return make_parse_result(status_out_of_memory); + + // read stream data into memory (guard against stream exceptions with buffer holder) + buffer_holder buffer(global_allocate((read_length > 0 ? read_length : 1) * sizeof(T)), global_deallocate); + if (!buffer.data) return make_parse_result(status_out_of_memory); + + stream.read(static_cast(buffer.data), static_cast(read_length)); + + // read may set failbit | eofbit in case gcount() is less than read_length (i.e. line ending conversion), so check for other I/O errors + if (stream.bad()) return make_parse_result(status_io_error); + + // load data from buffer + size_t actual_length = static_cast(stream.gcount()); + assert(actual_length <= read_length); + + return doc.load_buffer_inplace_own(buffer.release(), actual_length * sizeof(T), options, encoding); + } +#endif + +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) + FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) + { + return _wfopen(path, mode); + } +#else + char* convert_path_heap(const wchar_t* str) + { + assert(str); + + // first pass: get length in utf8 characters + size_t length = wcslen(str); + size_t size = as_utf8_begin(str, length); + + // allocate resulting string + char* result = static_cast(global_allocate(size + 1)); + if (!result) return 0; + + // second pass: convert to utf8 + as_utf8_end(result, size, str, length); + + return result; + } + + FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) + { + // there is no standard function to open wide paths, so our best bet is to try utf8 path + char* path_utf8 = convert_path_heap(path); + if (!path_utf8) return 0; + + // convert mode to ASCII (we mirror _wfopen interface) + char mode_ascii[4] = {0}; + for (size_t i = 0; mode[i]; ++i) mode_ascii[i] = static_cast(mode[i]); + + // try to open the utf8 path + FILE* result = fopen(path_utf8, mode_ascii); + + // free dummy buffer + global_deallocate(path_utf8); + + return result; + } +#endif +} + +namespace pugi +{ + xml_writer_file::xml_writer_file(void* file): file(file) + { + } + + void xml_writer_file::write(const void* data, size_t size) + { + fwrite(data, size, 1, static_cast(file)); + } + +#ifndef PUGIXML_NO_STL + xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(&stream), wide_stream(0) + { + } + + xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(0), wide_stream(&stream) + { + } + + void xml_writer_stream::write(const void* data, size_t size) + { + if (narrow_stream) + { + assert(!wide_stream); + narrow_stream->write(reinterpret_cast(data), static_cast(size)); + } + else + { + assert(wide_stream); + assert(size % sizeof(wchar_t) == 0); + + wide_stream->write(reinterpret_cast(data), static_cast(size / sizeof(wchar_t))); + } + } +#endif + + xml_tree_walker::xml_tree_walker(): _depth(0) + { + } + + xml_tree_walker::~xml_tree_walker() + { + } + + int xml_tree_walker::depth() const + { + return _depth; + } + + bool xml_tree_walker::begin(xml_node&) + { + return true; + } + + bool xml_tree_walker::end(xml_node&) + { + return true; + } + + xml_attribute::xml_attribute(): _attr(0) + { + } + + xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr) + { + } + + xml_attribute::operator xml_attribute::unspecified_bool_type() const + { + return _attr ? &xml_attribute::_attr : 0; + } + + bool xml_attribute::operator!() const + { + return !_attr; + } + + bool xml_attribute::operator==(const xml_attribute& r) const + { + return (_attr == r._attr); + } + + bool xml_attribute::operator!=(const xml_attribute& r) const + { + return (_attr != r._attr); + } + + bool xml_attribute::operator<(const xml_attribute& r) const + { + return (_attr < r._attr); + } + + bool xml_attribute::operator>(const xml_attribute& r) const + { + return (_attr > r._attr); + } + + bool xml_attribute::operator<=(const xml_attribute& r) const + { + return (_attr <= r._attr); + } + + bool xml_attribute::operator>=(const xml_attribute& r) const + { + return (_attr >= r._attr); + } + + xml_attribute xml_attribute::next_attribute() const + { + return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute(); + } + + xml_attribute xml_attribute::previous_attribute() const + { + return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute(); + } + + int xml_attribute::as_int() const + { + if (!_attr || !_attr->value) return 0; + + #ifdef PUGIXML_WCHAR_MODE + return (int)wcstol(_attr->value, 0, 10); + #else + return (int)strtol(_attr->value, 0, 10); + #endif + } + + unsigned int xml_attribute::as_uint() const + { + if (!_attr || !_attr->value) return 0; + + #ifdef PUGIXML_WCHAR_MODE + return (unsigned int)wcstoul(_attr->value, 0, 10); + #else + return (unsigned int)strtoul(_attr->value, 0, 10); + #endif + } + + double xml_attribute::as_double() const + { + if (!_attr || !_attr->value) return 0; + + #ifdef PUGIXML_WCHAR_MODE + return wcstod(_attr->value, 0); + #else + return strtod(_attr->value, 0); + #endif + } + + float xml_attribute::as_float() const + { + if (!_attr || !_attr->value) return 0; + + #ifdef PUGIXML_WCHAR_MODE + return (float)wcstod(_attr->value, 0); + #else + return (float)strtod(_attr->value, 0); + #endif + } + + bool xml_attribute::as_bool() const + { + if (!_attr || !_attr->value) return false; + + // only look at first char + char_t first = *_attr->value; + + // 1*, t* (true), T* (True), y* (yes), Y* (YES) + return (first == '1' || first == 't' || first == 'T' || first == 'y' || first == 'Y'); + } + + bool xml_attribute::empty() const + { + return !_attr; + } + + const char_t* xml_attribute::name() const + { + return (_attr && _attr->name) ? _attr->name : PUGIXML_TEXT(""); + } + + const char_t* xml_attribute::value() const + { + return (_attr && _attr->value) ? _attr->value : PUGIXML_TEXT(""); + } + + size_t xml_attribute::hash_value() const + { + return static_cast(reinterpret_cast(_attr) / sizeof(xml_attribute_struct)); + } + + xml_attribute_struct* xml_attribute::internal_object() const + { + return _attr; + } + + xml_attribute& xml_attribute::operator=(const char_t* rhs) + { + set_value(rhs); + return *this; + } + + xml_attribute& xml_attribute::operator=(int rhs) + { + set_value(rhs); + return *this; + } + + xml_attribute& xml_attribute::operator=(unsigned int rhs) + { + set_value(rhs); + return *this; + } + + xml_attribute& xml_attribute::operator=(double rhs) + { + set_value(rhs); + return *this; + } + + xml_attribute& xml_attribute::operator=(bool rhs) + { + set_value(rhs); + return *this; + } + + bool xml_attribute::set_name(const char_t* rhs) + { + if (!_attr) return false; + + return strcpy_insitu(_attr->name, _attr->header, xml_memory_page_name_allocated_mask, rhs); + } + + bool xml_attribute::set_value(const char_t* rhs) + { + if (!_attr) return false; + + return strcpy_insitu(_attr->value, _attr->header, xml_memory_page_value_allocated_mask, rhs); + } + + bool xml_attribute::set_value(int rhs) + { + char buf[128]; + sprintf(buf, "%d", rhs); + + #ifdef PUGIXML_WCHAR_MODE + char_t wbuf[128]; + widen_ascii(wbuf, buf); + + return set_value(wbuf); + #else + return set_value(buf); + #endif + } + + bool xml_attribute::set_value(unsigned int rhs) + { + char buf[128]; + sprintf(buf, "%u", rhs); + + #ifdef PUGIXML_WCHAR_MODE + char_t wbuf[128]; + widen_ascii(wbuf, buf); + + return set_value(wbuf); + #else + return set_value(buf); + #endif + } + + bool xml_attribute::set_value(double rhs) + { + char buf[128]; + sprintf(buf, "%g", rhs); + + #ifdef PUGIXML_WCHAR_MODE + char_t wbuf[128]; + widen_ascii(wbuf, buf); + + return set_value(wbuf); + #else + return set_value(buf); + #endif + } + + bool xml_attribute::set_value(bool rhs) + { + return set_value(rhs ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); + } + +#ifdef __BORLANDC__ + bool operator&&(const xml_attribute& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + bool operator||(const xml_attribute& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + xml_node::xml_node(): _root(0) + { + } + + xml_node::xml_node(xml_node_struct* p): _root(p) + { + } + + xml_node::operator xml_node::unspecified_bool_type() const + { + return _root ? &xml_node::_root : 0; + } + + bool xml_node::operator!() const + { + return !_root; + } + + xml_node::iterator xml_node::begin() const + { + return iterator(_root ? _root->first_child : 0, _root); + } + + xml_node::iterator xml_node::end() const + { + return iterator(0, _root); + } + + xml_node::attribute_iterator xml_node::attributes_begin() const + { + return attribute_iterator(_root ? _root->first_attribute : 0, _root); + } + + xml_node::attribute_iterator xml_node::attributes_end() const + { + return attribute_iterator(0, _root); + } + + bool xml_node::operator==(const xml_node& r) const + { + return (_root == r._root); + } + + bool xml_node::operator!=(const xml_node& r) const + { + return (_root != r._root); + } + + bool xml_node::operator<(const xml_node& r) const + { + return (_root < r._root); + } + + bool xml_node::operator>(const xml_node& r) const + { + return (_root > r._root); + } + + bool xml_node::operator<=(const xml_node& r) const + { + return (_root <= r._root); + } + + bool xml_node::operator>=(const xml_node& r) const + { + return (_root >= r._root); + } + + bool xml_node::empty() const + { + return !_root; + } + + const char_t* xml_node::name() const + { + return (_root && _root->name) ? _root->name : PUGIXML_TEXT(""); + } + + xml_node_type xml_node::type() const + { + return _root ? static_cast((_root->header & xml_memory_page_type_mask) + 1) : node_null; + } + + const char_t* xml_node::value() const + { + return (_root && _root->value) ? _root->value : PUGIXML_TEXT(""); + } + + xml_node xml_node::child(const char_t* name) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (i->name && strequal(name, i->name)) return xml_node(i); + + return xml_node(); + } + + xml_attribute xml_node::attribute(const char_t* name) const + { + if (!_root) return xml_attribute(); + + for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) + if (i->name && strequal(name, i->name)) + return xml_attribute(i); + + return xml_attribute(); + } + + xml_node xml_node::next_sibling(const char_t* name) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) + if (i->name && strequal(name, i->name)) return xml_node(i); + + return xml_node(); + } + + xml_node xml_node::next_sibling() const + { + if (!_root) return xml_node(); + + if (_root->next_sibling) return xml_node(_root->next_sibling); + else return xml_node(); + } + + xml_node xml_node::previous_sibling(const char_t* name) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) + if (i->name && strequal(name, i->name)) return xml_node(i); + + return xml_node(); + } + + xml_node xml_node::previous_sibling() const + { + if (!_root) return xml_node(); + + if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); + else return xml_node(); + } + + xml_node xml_node::parent() const + { + return _root ? xml_node(_root->parent) : xml_node(); + } + + xml_node xml_node::root() const + { + if (!_root) return xml_node(); + + xml_memory_page* page = reinterpret_cast(_root->header & xml_memory_page_pointer_mask); + + return xml_node(static_cast(page->allocator)); + } + + const char_t* xml_node::child_value() const + { + if (!_root) return PUGIXML_TEXT(""); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + { + xml_node_type type = static_cast((i->header & xml_memory_page_type_mask) + 1); + + if (i->value && (type == node_pcdata || type == node_cdata)) + return i->value; + } + + return PUGIXML_TEXT(""); + } + + const char_t* xml_node::child_value(const char_t* name) const + { + return child(name).child_value(); + } + + xml_attribute xml_node::first_attribute() const + { + return _root ? xml_attribute(_root->first_attribute) : xml_attribute(); + } + + xml_attribute xml_node::last_attribute() const + { + return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute(); + } + + xml_node xml_node::first_child() const + { + return _root ? xml_node(_root->first_child) : xml_node(); + } + + xml_node xml_node::last_child() const + { + return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); + } + + bool xml_node::set_name(const char_t* rhs) + { + switch (type()) + { + case node_pi: + case node_declaration: + case node_element: + return strcpy_insitu(_root->name, _root->header, xml_memory_page_name_allocated_mask, rhs); + + default: + return false; + } + } + + bool xml_node::set_value(const char_t* rhs) + { + switch (type()) + { + case node_pi: + case node_cdata: + case node_pcdata: + case node_comment: + case node_doctype: + return strcpy_insitu(_root->value, _root->header, xml_memory_page_value_allocated_mask, rhs); + + default: + return false; + } + } + + xml_attribute xml_node::append_attribute(const char_t* name) + { + if (type() != node_element && type() != node_declaration) return xml_attribute(); + + xml_attribute a(append_attribute_ll(_root, get_allocator(_root))); + a.set_name(name); + + return a; + } + + xml_attribute xml_node::prepend_attribute(const char_t* name) + { + if (type() != node_element && type() != node_declaration) return xml_attribute(); + + xml_attribute a(allocate_attribute(get_allocator(_root))); + if (!a) return xml_attribute(); + + a.set_name(name); + + xml_attribute_struct* head = _root->first_attribute; + + if (head) + { + a._attr->prev_attribute_c = head->prev_attribute_c; + head->prev_attribute_c = a._attr; + } + else + a._attr->prev_attribute_c = a._attr; + + a._attr->next_attribute = head; + _root->first_attribute = a._attr; + + return a; + } + + xml_attribute xml_node::insert_attribute_before(const char_t* name, const xml_attribute& attr) + { + if ((type() != node_element && type() != node_declaration) || attr.empty()) return xml_attribute(); + + // check that attribute belongs to *this + xml_attribute_struct* cur = attr._attr; + + while (cur->prev_attribute_c->next_attribute) cur = cur->prev_attribute_c; + + if (cur != _root->first_attribute) return xml_attribute(); + + xml_attribute a(allocate_attribute(get_allocator(_root))); + if (!a) return xml_attribute(); + + a.set_name(name); + + if (attr._attr->prev_attribute_c->next_attribute) + attr._attr->prev_attribute_c->next_attribute = a._attr; + else + _root->first_attribute = a._attr; + + a._attr->prev_attribute_c = attr._attr->prev_attribute_c; + a._attr->next_attribute = attr._attr; + attr._attr->prev_attribute_c = a._attr; + + return a; + } + + xml_attribute xml_node::insert_attribute_after(const char_t* name, const xml_attribute& attr) + { + if ((type() != node_element && type() != node_declaration) || attr.empty()) return xml_attribute(); + + // check that attribute belongs to *this + xml_attribute_struct* cur = attr._attr; + + while (cur->prev_attribute_c->next_attribute) cur = cur->prev_attribute_c; + + if (cur != _root->first_attribute) return xml_attribute(); + + xml_attribute a(allocate_attribute(get_allocator(_root))); + if (!a) return xml_attribute(); + + a.set_name(name); + + if (attr._attr->next_attribute) + attr._attr->next_attribute->prev_attribute_c = a._attr; + else + _root->first_attribute->prev_attribute_c = a._attr; + + a._attr->next_attribute = attr._attr->next_attribute; + a._attr->prev_attribute_c = attr._attr; + attr._attr->next_attribute = a._attr; + + return a; + } + + xml_attribute xml_node::append_copy(const xml_attribute& proto) + { + if (!proto) return xml_attribute(); + + xml_attribute result = append_attribute(proto.name()); + result.set_value(proto.value()); + + return result; + } + + xml_attribute xml_node::prepend_copy(const xml_attribute& proto) + { + if (!proto) return xml_attribute(); + + xml_attribute result = prepend_attribute(proto.name()); + result.set_value(proto.value()); + + return result; + } + + xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr) + { + if (!proto) return xml_attribute(); + + xml_attribute result = insert_attribute_after(proto.name(), attr); + result.set_value(proto.value()); + + return result; + } + + xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr) + { + if (!proto) return xml_attribute(); + + xml_attribute result = insert_attribute_before(proto.name(), attr); + result.set_value(proto.value()); + + return result; + } + + xml_node xml_node::append_child(xml_node_type type) + { + if (!allow_insert_child(this->type(), type)) return xml_node(); + + xml_node n(append_node(_root, get_allocator(_root), type)); + + if (type == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + xml_node xml_node::prepend_child(xml_node_type type) + { + if (!allow_insert_child(this->type(), type)) return xml_node(); + + xml_node n(allocate_node(get_allocator(_root), type)); + if (!n) return xml_node(); + + n._root->parent = _root; + + xml_node_struct* head = _root->first_child; + + if (head) + { + n._root->prev_sibling_c = head->prev_sibling_c; + head->prev_sibling_c = n._root; + } + else + n._root->prev_sibling_c = n._root; + + n._root->next_sibling = head; + _root->first_child = n._root; + + if (type == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + xml_node xml_node::insert_child_before(xml_node_type type, const xml_node& node) + { + if (!allow_insert_child(this->type(), type)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + xml_node n(allocate_node(get_allocator(_root), type)); + if (!n) return xml_node(); + + n._root->parent = _root; + + if (node._root->prev_sibling_c->next_sibling) + node._root->prev_sibling_c->next_sibling = n._root; + else + _root->first_child = n._root; + + n._root->prev_sibling_c = node._root->prev_sibling_c; + n._root->next_sibling = node._root; + node._root->prev_sibling_c = n._root; + + if (type == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + xml_node xml_node::insert_child_after(xml_node_type type, const xml_node& node) + { + if (!allow_insert_child(this->type(), type)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + xml_node n(allocate_node(get_allocator(_root), type)); + if (!n) return xml_node(); + + n._root->parent = _root; + + if (node._root->next_sibling) + node._root->next_sibling->prev_sibling_c = n._root; + else + _root->first_child->prev_sibling_c = n._root; + + n._root->next_sibling = node._root->next_sibling; + n._root->prev_sibling_c = node._root; + node._root->next_sibling = n._root; + + if (type == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + xml_node xml_node::append_child(const char_t* name) + { + xml_node result = append_child(node_element); + + result.set_name(name); + + return result; + } + + xml_node xml_node::prepend_child(const char_t* name) + { + xml_node result = prepend_child(node_element); + + result.set_name(name); + + return result; + } + + xml_node xml_node::insert_child_after(const char_t* name, const xml_node& node) + { + xml_node result = insert_child_after(node_element, node); + + result.set_name(name); + + return result; + } + + xml_node xml_node::insert_child_before(const char_t* name, const xml_node& node) + { + xml_node result = insert_child_before(node_element, node); + + result.set_name(name); + + return result; + } + + xml_node xml_node::append_copy(const xml_node& proto) + { + xml_node result = append_child(proto.type()); + + if (result) recursive_copy_skip(result, proto, result); + + return result; + } + + xml_node xml_node::prepend_copy(const xml_node& proto) + { + xml_node result = prepend_child(proto.type()); + + if (result) recursive_copy_skip(result, proto, result); + + return result; + } + + xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node) + { + xml_node result = insert_child_after(proto.type(), node); + + if (result) recursive_copy_skip(result, proto, result); + + return result; + } + + xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node) + { + xml_node result = insert_child_before(proto.type(), node); + + if (result) recursive_copy_skip(result, proto, result); + + return result; + } + + bool xml_node::remove_attribute(const char_t* name) + { + return remove_attribute(attribute(name)); + } + + bool xml_node::remove_attribute(const xml_attribute& a) + { + if (!_root || !a._attr) return false; + + // check that attribute belongs to *this + xml_attribute_struct* attr = a._attr; + + while (attr->prev_attribute_c->next_attribute) attr = attr->prev_attribute_c; + + if (attr != _root->first_attribute) return false; + + if (a._attr->next_attribute) a._attr->next_attribute->prev_attribute_c = a._attr->prev_attribute_c; + else if (_root->first_attribute) _root->first_attribute->prev_attribute_c = a._attr->prev_attribute_c; + + if (a._attr->prev_attribute_c->next_attribute) a._attr->prev_attribute_c->next_attribute = a._attr->next_attribute; + else _root->first_attribute = a._attr->next_attribute; + + destroy_attribute(a._attr, get_allocator(_root)); + + return true; + } + + bool xml_node::remove_child(const char_t* name) + { + return remove_child(child(name)); + } + + bool xml_node::remove_child(const xml_node& n) + { + if (!_root || !n._root || n._root->parent != _root) return false; + + if (n._root->next_sibling) n._root->next_sibling->prev_sibling_c = n._root->prev_sibling_c; + else if (_root->first_child) _root->first_child->prev_sibling_c = n._root->prev_sibling_c; + + if (n._root->prev_sibling_c->next_sibling) n._root->prev_sibling_c->next_sibling = n._root->next_sibling; + else _root->first_child = n._root->next_sibling; + + destroy_node(n._root, get_allocator(_root)); + + return true; + } + + xml_node xml_node::find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (i->name && strequal(name, i->name)) + { + for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) + if (strequal(attr_name, a->name) && strequal(attr_value, a->value)) + return xml_node(i); + } + + return xml_node(); + } + + xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) + if (strequal(attr_name, a->name) && strequal(attr_value, a->value)) + return xml_node(i); + + return xml_node(); + } + +#ifndef PUGIXML_NO_STL + string_t xml_node::path(char_t delimiter) const + { + string_t path; + + xml_node cursor = *this; // Make a copy. + + path = cursor.name(); + + while (cursor.parent()) + { + cursor = cursor.parent(); + + string_t temp = cursor.name(); + temp += delimiter; + temp += path; + path.swap(temp); + } + + return path; + } +#endif + + xml_node xml_node::first_element_by_path(const char_t* path, char_t delimiter) const + { + xml_node found = *this; // Current search context. + + if (!_root || !path || !path[0]) return found; + + if (path[0] == delimiter) + { + // Absolute path; e.g. '/foo/bar' + found = found.root(); + ++path; + } + + const char_t* path_segment = path; + + while (*path_segment == delimiter) ++path_segment; + + const char_t* path_segment_end = path_segment; + + while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end; + + if (path_segment == path_segment_end) return found; + + const char_t* next_segment = path_segment_end; + + while (*next_segment == delimiter) ++next_segment; + + if (*path_segment == '.' && path_segment + 1 == path_segment_end) + return found.first_element_by_path(next_segment, delimiter); + else if (*path_segment == '.' && *(path_segment+1) == '.' && path_segment + 2 == path_segment_end) + return found.parent().first_element_by_path(next_segment, delimiter); + else + { + for (xml_node_struct* j = found._root->first_child; j; j = j->next_sibling) + { + if (j->name && strequalrange(j->name, path_segment, static_cast(path_segment_end - path_segment))) + { + xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); + + if (subsearch) return subsearch; + } + } + + return xml_node(); + } + } + + bool xml_node::traverse(xml_tree_walker& walker) + { + walker._depth = -1; + + xml_node arg_begin = *this; + if (!walker.begin(arg_begin)) return false; + + xml_node cur = first_child(); + + if (cur) + { + ++walker._depth; + + do + { + xml_node arg_for_each = cur; + if (!walker.for_each(arg_for_each)) + return false; + + if (cur.first_child()) + { + ++walker._depth; + cur = cur.first_child(); + } + else if (cur.next_sibling()) + cur = cur.next_sibling(); + else + { + // Borland C++ workaround + while (!cur.next_sibling() && cur != *this && (bool)cur.parent()) + { + --walker._depth; + cur = cur.parent(); + } + + if (cur != *this) + cur = cur.next_sibling(); + } + } + while (cur && cur != *this); + } + + assert(walker._depth == -1); + + xml_node arg_end = *this; + return walker.end(arg_end); + } + + size_t xml_node::hash_value() const + { + return static_cast(reinterpret_cast(_root) / sizeof(xml_node_struct)); + } + + xml_node_struct* xml_node::internal_object() const + { + return _root; + } + + void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const + { + if (!_root) return; + + xml_buffered_writer buffered_writer(writer, encoding); + + node_output(buffered_writer, *this, indent, flags, depth); + } + +#ifndef PUGIXML_NO_STL + void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const + { + xml_writer_stream writer(stream); + + print(writer, indent, flags, encoding, depth); + } + + void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const + { + xml_writer_stream writer(stream); + + print(writer, indent, flags, encoding_wchar, depth); + } +#endif + + ptrdiff_t xml_node::offset_debug() const + { + xml_node_struct* r = root()._root; + + if (!r) return -1; + + const char_t* buffer = static_cast(r)->buffer; + + if (!buffer) return -1; + + switch (type()) + { + case node_document: + return 0; + + case node_element: + case node_declaration: + case node_pi: + return (_root->header & xml_memory_page_name_allocated_mask) ? -1 : _root->name - buffer; + + case node_pcdata: + case node_cdata: + case node_comment: + case node_doctype: + return (_root->header & xml_memory_page_value_allocated_mask) ? -1 : _root->value - buffer; + + default: + return -1; + } + } + +#ifdef __BORLANDC__ + bool operator&&(const xml_node& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + bool operator||(const xml_node& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + xml_node_iterator::xml_node_iterator() + { + } + + xml_node_iterator::xml_node_iterator(const xml_node& node): _wrap(node), _parent(node.parent()) + { + } + + xml_node_iterator::xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) + { + } + + bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const + { + return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; + } + + bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const + { + return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; + } + + xml_node& xml_node_iterator::operator*() + { + assert(_wrap._root); + return _wrap; + } + + xml_node* xml_node_iterator::operator->() + { + assert(_wrap._root); + return &_wrap; + } + + const xml_node_iterator& xml_node_iterator::operator++() + { + assert(_wrap._root); + _wrap._root = _wrap._root->next_sibling; + return *this; + } + + xml_node_iterator xml_node_iterator::operator++(int) + { + xml_node_iterator temp = *this; + ++*this; + return temp; + } + + const xml_node_iterator& xml_node_iterator::operator--() + { + _wrap = _wrap._root ? _wrap.previous_sibling() : _parent.last_child(); + return *this; + } + + xml_node_iterator xml_node_iterator::operator--(int) + { + xml_node_iterator temp = *this; + --*this; + return temp; + } + + xml_attribute_iterator::xml_attribute_iterator() + { + } + + xml_attribute_iterator::xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent): _wrap(attr), _parent(parent) + { + } + + xml_attribute_iterator::xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) + { + } + + bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const + { + return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root; + } + + bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const + { + return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root; + } + + xml_attribute& xml_attribute_iterator::operator*() + { + assert(_wrap._attr); + return _wrap; + } + + xml_attribute* xml_attribute_iterator::operator->() + { + assert(_wrap._attr); + return &_wrap; + } + + const xml_attribute_iterator& xml_attribute_iterator::operator++() + { + assert(_wrap._attr); + _wrap._attr = _wrap._attr->next_attribute; + return *this; + } + + xml_attribute_iterator xml_attribute_iterator::operator++(int) + { + xml_attribute_iterator temp = *this; + ++*this; + return temp; + } + + const xml_attribute_iterator& xml_attribute_iterator::operator--() + { + _wrap = _wrap._attr ? _wrap.previous_attribute() : _parent.last_attribute(); + return *this; + } + + xml_attribute_iterator xml_attribute_iterator::operator--(int) + { + xml_attribute_iterator temp = *this; + --*this; + return temp; + } + + xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto) + { + } + + xml_parse_result::operator bool() const + { + return status == status_ok; + } + + const char* xml_parse_result::description() const + { + switch (status) + { + case status_ok: return "No error"; + + case status_file_not_found: return "File was not found"; + case status_io_error: return "Error reading from file/stream"; + case status_out_of_memory: return "Could not allocate memory"; + case status_internal_error: return "Internal error occurred"; + + case status_unrecognized_tag: return "Could not determine tag type"; + + case status_bad_pi: return "Error parsing document declaration/processing instruction"; + case status_bad_comment: return "Error parsing comment"; + case status_bad_cdata: return "Error parsing CDATA section"; + case status_bad_doctype: return "Error parsing document type declaration"; + case status_bad_pcdata: return "Error parsing PCDATA section"; + case status_bad_start_element: return "Error parsing start element tag"; + case status_bad_attribute: return "Error parsing element attribute"; + case status_bad_end_element: return "Error parsing end element tag"; + case status_end_element_mismatch: return "Start-end tags mismatch"; + + default: return "Unknown error"; + } + } + + xml_document::xml_document(): _buffer(0) + { + create(); + } + + xml_document::~xml_document() + { + destroy(); + } + + void xml_document::reset() + { + destroy(); + create(); + } + + void xml_document::reset(const xml_document& proto) + { + reset(); + + for (xml_node cur = proto.first_child(); cur; cur = cur.next_sibling()) + append_copy(cur); + } + + void xml_document::create() + { + // initialize sentinel page + STATIC_ASSERT(offsetof(xml_memory_page, data) + sizeof(xml_document_struct) + xml_memory_page_alignment <= sizeof(_memory)); + + // align upwards to page boundary + void* page_memory = reinterpret_cast((reinterpret_cast(_memory) + (xml_memory_page_alignment - 1)) & ~(xml_memory_page_alignment - 1)); + + // prepare page structure + xml_memory_page* page = xml_memory_page::construct(page_memory); + + page->busy_size = xml_memory_page_size; + + // allocate new root + _root = new (page->data) xml_document_struct(page); + _root->prev_sibling_c = _root; + + // setup sentinel page + page->allocator = static_cast(_root); + } + + void xml_document::destroy() + { + // destroy static storage + if (_buffer) + { + global_deallocate(_buffer); + _buffer = 0; + } + + // destroy dynamic storage, leave sentinel page (it's in static memory) + if (_root) + { + xml_memory_page* root_page = reinterpret_cast(_root->header & xml_memory_page_pointer_mask); + assert(root_page && !root_page->prev && !root_page->memory); + + // destroy all pages + for (xml_memory_page* page = root_page->next; page; ) + { + xml_memory_page* next = page->next; + + xml_allocator::deallocate_page(page); + + page = next; + } + + // cleanup root page + root_page->allocator = 0; + root_page->next = 0; + root_page->busy_size = root_page->freed_size = 0; + + _root = 0; + } + } + +#ifndef PUGIXML_NO_STL + xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options, xml_encoding encoding) + { + reset(); + + return load_stream_impl(*this, stream, options, encoding); + } + + xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options) + { + reset(); + + return load_stream_impl(*this, stream, options, encoding_wchar); + } +#endif + + xml_parse_result xml_document::load(const char_t* contents, unsigned int options) + { + // Force native encoding (skip autodetection) + #ifdef PUGIXML_WCHAR_MODE + xml_encoding encoding = encoding_wchar; + #else + xml_encoding encoding = encoding_utf8; + #endif + + return load_buffer(contents, strlength(contents) * sizeof(char_t), options, encoding); + } + + xml_parse_result xml_document::load_file(const char* path, unsigned int options, xml_encoding encoding) + { + reset(); + + FILE* file = fopen(path, "rb"); + + return load_file_impl(*this, file, options, encoding); + } + + xml_parse_result xml_document::load_file(const wchar_t* path, unsigned int options, xml_encoding encoding) + { + reset(); + + FILE* file = open_file_wide(path, L"rb"); + + return load_file_impl(*this, file, options, encoding); + } + + xml_parse_result xml_document::load_buffer_impl(void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own) + { + reset(); + + // check input buffer + assert(contents || size == 0); + + // get actual encoding + xml_encoding buffer_encoding = get_buffer_encoding(encoding, contents, size); + + // get private buffer + char_t* buffer = 0; + size_t length = 0; + + if (!convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return make_parse_result(status_out_of_memory); + + // delete original buffer if we performed a conversion + if (own && buffer != contents && contents) global_deallocate(contents); + + // parse + xml_parse_result res = xml_parser::parse(buffer, length, _root, options); + + // remember encoding + res.encoding = buffer_encoding; + + // grab onto buffer if it's our buffer, user is responsible for deallocating contens himself + if (own || buffer != contents) _buffer = buffer; + + return res; + } + + xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + return load_buffer_impl(const_cast(contents), size, options, encoding, false, false); + } + + xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + return load_buffer_impl(contents, size, options, encoding, true, false); + } + + xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + return load_buffer_impl(contents, size, options, encoding, true, true); + } + + void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + if (flags & format_write_bom) write_bom(writer, get_write_encoding(encoding)); + + xml_buffered_writer buffered_writer(writer, encoding); + + if (!(flags & format_no_declaration) && !has_declaration(*this)) + { + buffered_writer.write(PUGIXML_TEXT("")); + if (!(flags & format_raw)) buffered_writer.write('\n'); + } + + node_output(buffered_writer, *this, indent, flags, 0); + } + +#ifndef PUGIXML_NO_STL + void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + xml_writer_stream writer(stream); + + save(writer, indent, flags, encoding); + } + + void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags) const + { + xml_writer_stream writer(stream); + + save(writer, indent, flags, encoding_wchar); + } +#endif + + bool xml_document::save_file(const char* path, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + FILE* file = fopen(path, "wb"); + if (!file) return false; + + xml_writer_file writer(file); + save(writer, indent, flags, encoding); + + fclose(file); + + return true; + } + + bool xml_document::save_file(const wchar_t* path, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + FILE* file = open_file_wide(path, L"wb"); + if (!file) return false; + + xml_writer_file writer(file); + save(writer, indent, flags, encoding); + + fclose(file); + + return true; + } + + xml_node xml_document::document_element() const + { + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if ((i->header & xml_memory_page_type_mask) + 1 == node_element) + return xml_node(i); + + return xml_node(); + } + +#ifndef PUGIXML_NO_STL + std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str) + { + assert(str); + + return as_utf8_impl(str, wcslen(str)); + } + + std::string PUGIXML_FUNCTION as_utf8(const std::wstring& str) + { + return as_utf8_impl(str.c_str(), str.size()); + } + + std::wstring PUGIXML_FUNCTION as_wide(const char* str) + { + assert(str); + + return as_wide_impl(str, strlen(str)); + } + + std::wstring PUGIXML_FUNCTION as_wide(const std::string& str) + { + return as_wide_impl(str.c_str(), str.size()); + } +#endif + + void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate) + { + global_allocate = allocate; + global_deallocate = deallocate; + } + + allocation_function PUGIXML_FUNCTION get_memory_allocation_function() + { + return global_allocate; + } + + deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function() + { + return global_deallocate; + } +} + +#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) +namespace std +{ + // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) + std::bidirectional_iterator_tag _Iter_cat(const xml_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + std::bidirectional_iterator_tag _Iter_cat(const xml_attribute_iterator&) + { + return std::bidirectional_iterator_tag(); + } +} +#endif + +#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) +namespace std +{ + // Workarounds for (non-standard) iterator category detection + std::bidirectional_iterator_tag __iterator_category(const xml_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + std::bidirectional_iterator_tag __iterator_category(const xml_attribute_iterator&) + { + return std::bidirectional_iterator_tag(); + } +} +#endif + +#ifndef PUGIXML_NO_XPATH + +// STL replacements +namespace +{ + struct equal_to + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs == rhs; + } + }; + + struct not_equal_to + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs != rhs; + } + }; + + struct less + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs < rhs; + } + }; + + struct less_equal + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs <= rhs; + } + }; + + template void swap(T& lhs, T& rhs) + { + T temp = lhs; + lhs = rhs; + rhs = temp; + } + + template I min_element(I begin, I end, const Pred& pred) + { + I result = begin; + + for (I it = begin + 1; it != end; ++it) + if (pred(*it, *result)) + result = it; + + return result; + } + + template void reverse(I begin, I end) + { + while (begin + 1 < end) swap(*begin++, *--end); + } + + template I unique(I begin, I end) + { + // fast skip head + while (begin + 1 < end && *begin != *(begin + 1)) begin++; + + if (begin == end) return begin; + + // last written element + I write = begin++; + + // merge unique elements + while (begin != end) + { + if (*begin != *write) + *++write = *begin++; + else + begin++; + } + + // past-the-end (write points to live element) + return write + 1; + } + + template void copy_backwards(I begin, I end, I target) + { + while (begin != end) *--target = *--end; + } + + template void insertion_sort(I begin, I end, const Pred& pred, T*) + { + assert(begin != end); + + for (I it = begin + 1; it != end; ++it) + { + T val = *it; + + if (pred(val, *begin)) + { + // move to front + copy_backwards(begin, it, it + 1); + *begin = val; + } + else + { + I hole = it; + + // move hole backwards + while (pred(val, *(hole - 1))) + { + *hole = *(hole - 1); + hole--; + } + + // fill hole with element + *hole = val; + } + } + } + + // std variant for elements with == + template void partition(I begin, I middle, I end, const Pred& pred, I* out_eqbeg, I* out_eqend) + { + I eqbeg = middle, eqend = middle + 1; + + // expand equal range + while (eqbeg != begin && *(eqbeg - 1) == *eqbeg) --eqbeg; + while (eqend != end && *eqend == *eqbeg) ++eqend; + + // process outer elements + I ltend = eqbeg, gtbeg = eqend; + + for (;;) + { + // find the element from the right side that belongs to the left one + for (; gtbeg != end; ++gtbeg) + if (!pred(*eqbeg, *gtbeg)) + { + if (*gtbeg == *eqbeg) swap(*gtbeg, *eqend++); + else break; + } + + // find the element from the left side that belongs to the right one + for (; ltend != begin; --ltend) + if (!pred(*(ltend - 1), *eqbeg)) + { + if (*eqbeg == *(ltend - 1)) swap(*(ltend - 1), *--eqbeg); + else break; + } + + // scanned all elements + if (gtbeg == end && ltend == begin) + { + *out_eqbeg = eqbeg; + *out_eqend = eqend; + return; + } + + // make room for elements by moving equal area + if (gtbeg == end) + { + if (--ltend != --eqbeg) swap(*ltend, *eqbeg); + swap(*eqbeg, *--eqend); + } + else if (ltend == begin) + { + if (eqend != gtbeg) swap(*eqbeg, *eqend); + ++eqend; + swap(*gtbeg++, *eqbeg++); + } + else swap(*gtbeg++, *--ltend); + } + } + + template void median3(I first, I middle, I last, const Pred& pred) + { + if (pred(*middle, *first)) swap(*middle, *first); + if (pred(*last, *middle)) swap(*last, *middle); + if (pred(*middle, *first)) swap(*middle, *first); + } + + template void median(I first, I middle, I last, const Pred& pred) + { + if (last - first <= 40) + { + // median of three for small chunks + median3(first, middle, last, pred); + } + else + { + // median of nine + size_t step = (last - first + 1) / 8; + + median3(first, first + step, first + 2 * step, pred); + median3(middle - step, middle, middle + step, pred); + median3(last - 2 * step, last - step, last, pred); + median3(first + step, middle, last - step, pred); + } + } + + template void sort(I begin, I end, const Pred& pred) + { + // sort large chunks + while (end - begin > 32) + { + // find median element + I middle = begin + (end - begin) / 2; + median(begin, middle, end - 1, pred); + + // partition in three chunks (< = >) + I eqbeg, eqend; + partition(begin, middle, end, pred, &eqbeg, &eqend); + + // loop on larger half + if (eqbeg - begin > end - eqend) + { + sort(eqend, end, pred); + end = eqbeg; + } + else + { + sort(begin, eqbeg, pred); + begin = eqend; + } + } + + // insertion sort small chunk + if (begin != end) insertion_sort(begin, end, pred, &*begin); + } +} + +// Allocator used for AST and evaluation stacks +namespace +{ + struct xpath_memory_block + { + xpath_memory_block* next; + + char data[4096]; + }; + + class xpath_allocator + { + xpath_memory_block* _root; + size_t _root_size; + + public: + #ifdef PUGIXML_NO_EXCEPTIONS + jmp_buf* error_handler; + #endif + + xpath_allocator(xpath_memory_block* root, size_t root_size = 0): _root(root), _root_size(root_size) + { + #ifdef PUGIXML_NO_EXCEPTIONS + error_handler = 0; + #endif + } + + void* allocate_nothrow(size_t size) + { + const size_t block_capacity = sizeof(_root->data); + + // align size so that we're able to store pointers in subsequent blocks + size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); + + if (_root_size + size <= block_capacity) + { + void* buf = _root->data + _root_size; + _root_size += size; + return buf; + } + else + { + size_t block_data_size = (size > block_capacity) ? size : block_capacity; + size_t block_size = block_data_size + offsetof(xpath_memory_block, data); + + xpath_memory_block* block = static_cast(global_allocate(block_size)); + if (!block) return 0; + + block->next = _root; + + _root = block; + _root_size = size; + + return block->data; + } + } + + void* allocate(size_t size) + { + void* result = allocate_nothrow(size); + + if (!result) + { + #ifdef PUGIXML_NO_EXCEPTIONS + assert(error_handler); + longjmp(*error_handler, 1); + #else + throw std::bad_alloc(); + #endif + } + + return result; + } + + void* reallocate(void* ptr, size_t old_size, size_t new_size) + { + // align size so that we're able to store pointers in subsequent blocks + old_size = (old_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); + new_size = (new_size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); + + // we can only reallocate the last object + assert(ptr == 0 || static_cast(ptr) + old_size == _root->data + _root_size); + + // adjust root size so that we have not allocated the object at all + bool only_object = (_root_size == old_size); + + if (ptr) _root_size -= old_size; + + // allocate a new version (this will obviously reuse the memory if possible) + void* result = allocate(new_size); + assert(result); + + // we have a new block + if (result != ptr && ptr) + { + // copy old data + assert(new_size > old_size); + memcpy(result, ptr, old_size); + + // free the previous page if it had no other objects + if (only_object) + { + assert(_root->data == result); + assert(_root->next); + + xpath_memory_block* next = _root->next->next; + + if (next) + { + // deallocate the whole page, unless it was the first one + global_deallocate(_root->next); + _root->next = next; + } + } + } + + return result; + } + + void revert(const xpath_allocator& state) + { + // free all new pages + xpath_memory_block* cur = _root; + + while (cur != state._root) + { + xpath_memory_block* next = cur->next; + + global_deallocate(cur); + + cur = next; + } + + // restore state + _root = state._root; + _root_size = state._root_size; + } + + void release() + { + xpath_memory_block* cur = _root; + assert(cur); + + while (cur->next) + { + xpath_memory_block* next = cur->next; + + global_deallocate(cur); + + cur = next; + } + } + }; + + struct xpath_allocator_capture + { + xpath_allocator_capture(xpath_allocator* alloc): _target(alloc), _state(*alloc) + { + } + + ~xpath_allocator_capture() + { + _target->revert(_state); + } + + xpath_allocator* _target; + xpath_allocator _state; + }; + + struct xpath_stack + { + xpath_allocator* result; + xpath_allocator* temp; + }; + + struct xpath_stack_data + { + xpath_memory_block blocks[2]; + xpath_allocator result; + xpath_allocator temp; + xpath_stack stack; + + #ifdef PUGIXML_NO_EXCEPTIONS + jmp_buf error_handler; + #endif + + xpath_stack_data(): result(blocks + 0), temp(blocks + 1) + { + blocks[0].next = blocks[1].next = 0; + + stack.result = &result; + stack.temp = &temp; + + #ifdef PUGIXML_NO_EXCEPTIONS + result.error_handler = temp.error_handler = &error_handler; + #endif + } + + ~xpath_stack_data() + { + result.release(); + temp.release(); + } + }; +} + +// String class +namespace +{ + class xpath_string + { + const char_t* _buffer; + bool _uses_heap; + + static char_t* duplicate_string(const char_t* string, size_t length, xpath_allocator* alloc) + { + char_t* result = static_cast(alloc->allocate((length + 1) * sizeof(char_t))); + assert(result); + + memcpy(result, string, length * sizeof(char_t)); + result[length] = 0; + + return result; + } + + static char_t* duplicate_string(const char_t* string, xpath_allocator* alloc) + { + return duplicate_string(string, strlength(string), alloc); + } + + public: + xpath_string(): _buffer(PUGIXML_TEXT("")), _uses_heap(false) + { + } + + explicit xpath_string(const char_t* str, xpath_allocator* alloc) + { + bool empty = (*str == 0); + + _buffer = empty ? PUGIXML_TEXT("") : duplicate_string(str, alloc); + _uses_heap = !empty; + } + + explicit xpath_string(const char_t* str, bool use_heap): _buffer(str), _uses_heap(use_heap) + { + } + + xpath_string(const char_t* begin, const char_t* end, xpath_allocator* alloc) + { + assert(begin <= end); + + bool empty = (begin == end); + + _buffer = empty ? PUGIXML_TEXT("") : duplicate_string(begin, static_cast(end - begin), alloc); + _uses_heap = !empty; + } + + void append(const xpath_string& o, xpath_allocator* alloc) + { + // skip empty sources + if (!*o._buffer) return; + + // fast append for constant empty target and constant source + if (!*_buffer && !_uses_heap && !o._uses_heap) + { + _buffer = o._buffer; + } + else + { + // need to make heap copy + size_t target_length = strlength(_buffer); + size_t source_length = strlength(o._buffer); + size_t length = target_length + source_length; + + // allocate new buffer + char_t* result = static_cast(alloc->reallocate(_uses_heap ? const_cast(_buffer) : 0, (target_length + 1) * sizeof(char_t), (length + 1) * sizeof(char_t))); + assert(result); + + // append first string to the new buffer in case there was no reallocation + if (!_uses_heap) memcpy(result, _buffer, target_length * sizeof(char_t)); + + // append second string to the new buffer + memcpy(result + target_length, o._buffer, source_length * sizeof(char_t)); + result[length] = 0; + + // finalize + _buffer = result; + _uses_heap = true; + } + } + + const char_t* c_str() const + { + return _buffer; + } + + size_t length() const + { + return strlength(_buffer); + } + + char_t* data(xpath_allocator* alloc) + { + // make private heap copy + if (!_uses_heap) + { + _buffer = duplicate_string(_buffer, alloc); + _uses_heap = true; + } + + return const_cast(_buffer); + } + + bool empty() const + { + return *_buffer == 0; + } + + bool operator==(const xpath_string& o) const + { + return strequal(_buffer, o._buffer); + } + + bool operator!=(const xpath_string& o) const + { + return !strequal(_buffer, o._buffer); + } + + bool uses_heap() const + { + return _uses_heap; + } + }; + + xpath_string xpath_string_const(const char_t* str) + { + return xpath_string(str, false); + } +} + +namespace +{ + bool starts_with(const char_t* string, const char_t* pattern) + { + while (*pattern && *string == *pattern) + { + string++; + pattern++; + } + + return *pattern == 0; + } + + const char_t* find_char(const char_t* s, char_t c) + { + #ifdef PUGIXML_WCHAR_MODE + return wcschr(s, c); + #else + return strchr(s, c); + #endif + } + + const char_t* find_substring(const char_t* s, const char_t* p) + { + #ifdef PUGIXML_WCHAR_MODE + // MSVC6 wcsstr bug workaround (if s is empty it always returns 0) + return (*p == 0) ? s : wcsstr(s, p); + #else + return strstr(s, p); + #endif + } + + // Converts symbol to lower case, if it is an ASCII one + char_t tolower_ascii(char_t ch) + { + return static_cast(ch - 'A') < 26 ? static_cast(ch | ' ') : ch; + } + + xpath_string string_value(const xpath_node& na, xpath_allocator* alloc) + { + if (na.attribute()) + return xpath_string_const(na.attribute().value()); + else + { + const xml_node& n = na.node(); + + switch (n.type()) + { + case node_pcdata: + case node_cdata: + case node_comment: + case node_pi: + return xpath_string_const(n.value()); + + case node_document: + case node_element: + { + xpath_string result; + + xml_node cur = n.first_child(); + + while (cur && cur != n) + { + if (cur.type() == node_pcdata || cur.type() == node_cdata) + result.append(xpath_string_const(cur.value()), alloc); + + if (cur.first_child()) + cur = cur.first_child(); + else if (cur.next_sibling()) + cur = cur.next_sibling(); + else + { + while (!cur.next_sibling() && cur != n) + cur = cur.parent(); + + if (cur != n) cur = cur.next_sibling(); + } + } + + return result; + } + + default: + return xpath_string(); + } + } + } + + unsigned int node_height(xml_node n) + { + unsigned int result = 0; + + while (n) + { + ++result; + n = n.parent(); + } + + return result; + } + + bool node_is_before(xml_node ln, unsigned int lh, xml_node rn, unsigned int rh) + { + // normalize heights + for (unsigned int i = rh; i < lh; i++) ln = ln.parent(); + for (unsigned int j = lh; j < rh; j++) rn = rn.parent(); + + // one node is the ancestor of the other + if (ln == rn) return lh < rh; + + // find common ancestor + while (ln.parent() != rn.parent()) + { + ln = ln.parent(); + rn = rn.parent(); + } + + // there is no common ancestor (the shared parent is null), nodes are from different documents + if (!ln.parent()) return ln < rn; + + // determine sibling order + for (; ln; ln = ln.next_sibling()) + if (ln == rn) + return true; + + return false; + } + + bool node_is_ancestor(xml_node parent, xml_node node) + { + while (node && node != parent) node = node.parent(); + + return parent && node == parent; + } + + const void* document_order(const xpath_node& xnode) + { + xml_node_struct* node = xnode.node().internal_object(); + + if (node) + { + if (node->name && (node->header & xml_memory_page_name_allocated_mask) == 0) return node->name; + if (node->value && (node->header & xml_memory_page_value_allocated_mask) == 0) return node->value; + return 0; + } + + xml_attribute_struct* attr = xnode.attribute().internal_object(); + + if (attr) + { + if ((attr->header & xml_memory_page_name_allocated_mask) == 0) return attr->name; + if ((attr->header & xml_memory_page_value_allocated_mask) == 0) return attr->value; + return 0; + } + + return 0; + } + + struct document_order_comparator + { + bool operator()(const xpath_node& lhs, const xpath_node& rhs) const + { + // optimized document order based check + const void* lo = document_order(lhs); + const void* ro = document_order(rhs); + + if (lo && ro) return lo < ro; + + // slow comparison + xml_node ln = lhs.node(), rn = rhs.node(); + + // compare attributes + if (lhs.attribute() && rhs.attribute()) + { + // shared parent + if (lhs.parent() == rhs.parent()) + { + // determine sibling order + for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute()) + if (a == rhs.attribute()) + return true; + + return false; + } + + // compare attribute parents + ln = lhs.parent(); + rn = rhs.parent(); + } + else if (lhs.attribute()) + { + // attributes go after the parent element + if (lhs.parent() == rhs.node()) return false; + + ln = lhs.parent(); + } + else if (rhs.attribute()) + { + // attributes go after the parent element + if (rhs.parent() == lhs.node()) return true; + + rn = rhs.parent(); + } + + if (ln == rn) return false; + + unsigned int lh = node_height(ln); + unsigned int rh = node_height(rn); + + return node_is_before(ln, lh, rn, rh); + } + }; + + struct duplicate_comparator + { + bool operator()(const xpath_node& lhs, const xpath_node& rhs) const + { + if (lhs.attribute()) return rhs.attribute() ? lhs.attribute() < rhs.attribute() : true; + else return rhs.attribute() ? false : lhs.node() < rhs.node(); + } + }; + + double gen_nan() + { + #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24)) + union { float f; int32_t i; } u[sizeof(float) == sizeof(int32_t) ? 1 : -1]; + u[0].i = 0x7fc00000; + return u[0].f; + #else + // fallback + const volatile double zero = 0.0; + return zero / zero; + #endif + } + + bool is_nan(double value) + { + #if defined(_MSC_VER) || defined(__BORLANDC__) + return !!_isnan(value); + #elif defined(fpclassify) && defined(FP_NAN) + return fpclassify(value) == FP_NAN; + #else + // fallback + const volatile double v = value; + return v != v; + #endif + } + + const char_t* convert_number_to_string_special(double value) + { + #if defined(_MSC_VER) || defined(__BORLANDC__) + if (_finite(value)) return (value == 0) ? PUGIXML_TEXT("0") : 0; + if (_isnan(value)) return PUGIXML_TEXT("NaN"); + return PUGIXML_TEXT("-Infinity") + (value > 0); + #elif defined(fpclassify) && defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) + switch (fpclassify(value)) + { + case FP_NAN: + return PUGIXML_TEXT("NaN"); + + case FP_INFINITE: + return PUGIXML_TEXT("-Infinity") + (value > 0); + + case FP_ZERO: + return PUGIXML_TEXT("0"); + + default: + return 0; + } + #else + // fallback + const volatile double v = value; + + if (v == 0) return PUGIXML_TEXT("0"); + if (v != v) return PUGIXML_TEXT("NaN"); + if (v * 2 == v) return PUGIXML_TEXT("-Infinity") + (value > 0); + return 0; + #endif + } + + bool convert_number_to_boolean(double value) + { + return (value != 0 && !is_nan(value)); + } + + void truncate_zeros(char* begin, char* end) + { + while (begin != end && end[-1] == '0') end--; + + *end = 0; + } + + // gets mantissa digits in the form of 0.xxxxx with 0. implied and the exponent +#if defined(_MSC_VER) && _MSC_VER >= 1400 + void convert_number_to_mantissa_exponent(double value, char* buffer, size_t buffer_size, char** out_mantissa, int* out_exponent) + { + // get base values + int sign, exponent; + _ecvt_s(buffer, buffer_size, value, DBL_DIG + 1, &exponent, &sign); + + // truncate redundant zeros + truncate_zeros(buffer, buffer + strlen(buffer)); + + // fill results + *out_mantissa = buffer; + *out_exponent = exponent; + } +#else + void convert_number_to_mantissa_exponent(double value, char* buffer, size_t buffer_size, char** out_mantissa, int* out_exponent) + { + // get a scientific notation value with IEEE DBL_DIG decimals + sprintf(buffer, "%.*e", DBL_DIG, value); + assert(strlen(buffer) < buffer_size); + (void)!buffer_size; + + // get the exponent (possibly negative) + char* exponent_string = strchr(buffer, 'e'); + assert(exponent_string); + + int exponent = atoi(exponent_string + 1); + + // extract mantissa string: skip sign + char* mantissa = buffer[0] == '-' ? buffer + 1 : buffer; + assert(mantissa[0] != '0' && mantissa[1] == '.'); + + // divide mantissa by 10 to eliminate integer part + mantissa[1] = mantissa[0]; + mantissa++; + exponent++; + + // remove extra mantissa digits and zero-terminate mantissa + truncate_zeros(mantissa, exponent_string); + + // fill results + *out_mantissa = mantissa; + *out_exponent = exponent; + } +#endif + + xpath_string convert_number_to_string(double value, xpath_allocator* alloc) + { + // try special number conversion + const char_t* special = convert_number_to_string_special(value); + if (special) return xpath_string_const(special); + + // get mantissa + exponent form + char mantissa_buffer[64]; + + char* mantissa; + int exponent; + convert_number_to_mantissa_exponent(value, mantissa_buffer, sizeof(mantissa_buffer), &mantissa, &exponent); + + // make the number! + char_t result[512]; + char_t* s = result; + + // sign + if (value < 0) *s++ = '-'; + + // integer part + if (exponent <= 0) + { + *s++ = '0'; + } + else + { + while (exponent > 0) + { + assert(*mantissa == 0 || (unsigned)(*mantissa - '0') <= 9); + *s++ = *mantissa ? *mantissa++ : '0'; + exponent--; + } + } + + // fractional part + if (*mantissa) + { + // decimal point + *s++ = '.'; + + // extra zeroes from negative exponent + while (exponent < 0) + { + *s++ = '0'; + exponent++; + } + + // extra mantissa digits + while (*mantissa) + { + assert((unsigned)(*mantissa - '0') <= 9); + *s++ = *mantissa++; + } + } + + // zero-terminate + assert(s < result + sizeof(result) / sizeof(result[0])); + *s = 0; + + return xpath_string(result, alloc); + } + + bool check_string_to_number_format(const char_t* string) + { + // parse leading whitespace + while (IS_CHARTYPE(*string, ct_space)) ++string; + + // parse sign + if (*string == '-') ++string; + + if (!*string) return false; + + // if there is no integer part, there should be a decimal part with at least one digit + if (!IS_CHARTYPEX(string[0], ctx_digit) && (string[0] != '.' || !IS_CHARTYPEX(string[1], ctx_digit))) return false; + + // parse integer part + while (IS_CHARTYPEX(*string, ctx_digit)) ++string; + + // parse decimal part + if (*string == '.') + { + ++string; + + while (IS_CHARTYPEX(*string, ctx_digit)) ++string; + } + + // parse trailing whitespace + while (IS_CHARTYPE(*string, ct_space)) ++string; + + return *string == 0; + } + + double convert_string_to_number(const char_t* string) + { + // check string format + if (!check_string_to_number_format(string)) return gen_nan(); + + // parse string + #ifdef PUGIXML_WCHAR_MODE + return wcstod(string, 0); + #else + return atof(string); + #endif + } + + bool convert_string_to_number(const char_t* begin, const char_t* end, double* out_result) + { + char_t buffer[32]; + + size_t length = static_cast(end - begin); + char_t* scratch = buffer; + + if (length >= sizeof(buffer) / sizeof(buffer[0])) + { + // need to make dummy on-heap copy + scratch = static_cast(global_allocate((length + 1) * sizeof(char_t))); + if (!scratch) return false; + } + + // copy string to zero-terminated buffer and perform conversion + memcpy(scratch, begin, length * sizeof(char_t)); + scratch[length] = 0; + + *out_result = convert_string_to_number(scratch); + + // free dummy buffer + if (scratch != buffer) global_deallocate(scratch); + + return true; + } + + double round_nearest(double value) + { + return floor(value + 0.5); + } + + double round_nearest_nzero(double value) + { + // same as round_nearest, but returns -0 for [-0.5, -0] + // ceil is used to differentiate between +0 and -0 (we return -0 for [-0.5, -0] and +0 for +0) + return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5); + } + + const char_t* qualified_name(const xpath_node& node) + { + return node.attribute() ? node.attribute().name() : node.node().name(); + } + + const char_t* local_name(const xpath_node& node) + { + const char_t* name = qualified_name(node); + const char_t* p = find_char(name, ':'); + + return p ? p + 1 : name; + } + + struct namespace_uri_predicate + { + const char_t* prefix; + size_t prefix_length; + + namespace_uri_predicate(const char_t* name) + { + const char_t* pos = find_char(name, ':'); + + prefix = pos ? name : 0; + prefix_length = pos ? static_cast(pos - name) : 0; + } + + bool operator()(const xml_attribute& a) const + { + const char_t* name = a.name(); + + if (!starts_with(name, PUGIXML_TEXT("xmlns"))) return false; + + return prefix ? name[5] == ':' && strequalrange(name + 6, prefix, prefix_length) : name[5] == 0; + } + }; + + const char_t* namespace_uri(const xml_node& node) + { + namespace_uri_predicate pred = node.name(); + + xml_node p = node; + + while (p) + { + xml_attribute a = p.find_attribute(pred); + + if (a) return a.value(); + + p = p.parent(); + } + + return PUGIXML_TEXT(""); + } + + const char_t* namespace_uri(const xml_attribute& attr, const xml_node& parent) + { + namespace_uri_predicate pred = attr.name(); + + // Default namespace does not apply to attributes + if (!pred.prefix) return PUGIXML_TEXT(""); + + xml_node p = parent; + + while (p) + { + xml_attribute a = p.find_attribute(pred); + + if (a) return a.value(); + + p = p.parent(); + } + + return PUGIXML_TEXT(""); + } + + const char_t* namespace_uri(const xpath_node& node) + { + return node.attribute() ? namespace_uri(node.attribute(), node.parent()) : namespace_uri(node.node()); + } + + void normalize_space(char_t* buffer) + { + char_t* write = buffer; + + for (char_t* it = buffer; *it; ) + { + char_t ch = *it++; + + if (IS_CHARTYPE(ch, ct_space)) + { + // replace whitespace sequence with single space + while (IS_CHARTYPE(*it, ct_space)) it++; + + // avoid leading spaces + if (write != buffer) *write++ = ' '; + } + else *write++ = ch; + } + + // remove trailing space + if (write != buffer && IS_CHARTYPE(write[-1], ct_space)) write--; + + // zero-terminate + *write = 0; + } + + void translate(char_t* buffer, const char_t* from, const char_t* to) + { + size_t to_length = strlength(to); + + char_t* write = buffer; + + while (*buffer) + { + DMC_VOLATILE char_t ch = *buffer++; + + const char_t* pos = find_char(from, ch); + + if (!pos) + *write++ = ch; // do not process + else if (static_cast(pos - from) < to_length) + *write++ = to[pos - from]; // replace + } + + // zero-terminate + *write = 0; + } + + struct xpath_variable_boolean: xpath_variable + { + xpath_variable_boolean(): value(false) + { + } + + bool value; + char_t name[1]; + }; + + struct xpath_variable_number: xpath_variable + { + xpath_variable_number(): value(0) + { + } + + double value; + char_t name[1]; + }; + + struct xpath_variable_string: xpath_variable + { + xpath_variable_string(): value(0) + { + } + + ~xpath_variable_string() + { + if (value) global_deallocate(value); + } + + char_t* value; + char_t name[1]; + }; + + struct xpath_variable_node_set: xpath_variable + { + xpath_node_set value; + char_t name[1]; + }; + + const xpath_node_set dummy_node_set; + + unsigned int hash_string(const char_t* str) + { + // Jenkins one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time) + unsigned int result = 0; + + while (*str) + { + result += static_cast(*str++); + result += result << 10; + result ^= result >> 6; + } + + result += result << 3; + result ^= result >> 11; + result += result << 15; + + return result; + } + + template T* new_xpath_variable(const char_t* name) + { + size_t length = strlength(name); + if (length == 0) return 0; // empty variable names are invalid + + // $$ we can't use offsetof(T, name) because T is non-POD, so we just allocate additional length characters + void* memory = global_allocate(sizeof(T) + length * sizeof(char_t)); + if (!memory) return 0; + + T* result = new (memory) T(); + + memcpy(result->name, name, (length + 1) * sizeof(char_t)); + + return result; + } + + xpath_variable* new_xpath_variable(xpath_value_type type, const char_t* name) + { + switch (type) + { + case xpath_type_node_set: + return new_xpath_variable(name); + + case xpath_type_number: + return new_xpath_variable(name); + + case xpath_type_string: + return new_xpath_variable(name); + + case xpath_type_boolean: + return new_xpath_variable(name); + + default: + return 0; + } + } + + template void delete_xpath_variable(T* var) + { + var->~T(); + global_deallocate(var); + } + + void delete_xpath_variable(xpath_value_type type, xpath_variable* var) + { + switch (type) + { + case xpath_type_node_set: + delete_xpath_variable(static_cast(var)); + break; + + case xpath_type_number: + delete_xpath_variable(static_cast(var)); + break; + + case xpath_type_string: + delete_xpath_variable(static_cast(var)); + break; + + case xpath_type_boolean: + delete_xpath_variable(static_cast(var)); + break; + + default: + assert(!"Invalid variable type"); + } + } + + xpath_variable* get_variable(xpath_variable_set* set, const char_t* begin, const char_t* end) + { + char_t buffer[32]; + + size_t length = static_cast(end - begin); + char_t* scratch = buffer; + + if (length >= sizeof(buffer) / sizeof(buffer[0])) + { + // need to make dummy on-heap copy + scratch = static_cast(global_allocate((length + 1) * sizeof(char_t))); + if (!scratch) return 0; + } + + // copy string to zero-terminated buffer and perform lookup + memcpy(scratch, begin, length * sizeof(char_t)); + scratch[length] = 0; + + xpath_variable* result = set->get(scratch); + + // free dummy buffer + if (scratch != buffer) global_deallocate(scratch); + + return result; + } +} + +// Internal node set class +namespace +{ + xpath_node_set::type_t xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type, bool rev) + { + xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; + + if (type == xpath_node_set::type_unsorted) + { + sort(begin, end, document_order_comparator()); + + type = xpath_node_set::type_sorted; + } + + if (type != order) reverse(begin, end); + + return order; + } + + xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type) + { + if (begin == end) return xpath_node(); + + switch (type) + { + case xpath_node_set::type_sorted: + return *begin; + + case xpath_node_set::type_sorted_reverse: + return *(end - 1); + + case xpath_node_set::type_unsorted: + return *min_element(begin, end, document_order_comparator()); + + default: + assert(!"Invalid node set type"); + return xpath_node(); + } + } + class xpath_node_set_raw + { + xpath_node_set::type_t _type; + + xpath_node* _begin; + xpath_node* _end; + xpath_node* _eos; + + public: + xpath_node_set_raw(): _type(xpath_node_set::type_unsorted), _begin(0), _end(0), _eos(0) + { + } + + xpath_node* begin() const + { + return _begin; + } + + xpath_node* end() const + { + return _end; + } + + bool empty() const + { + return _begin == _end; + } + + size_t size() const + { + return static_cast(_end - _begin); + } + + xpath_node first() const + { + return xpath_first(_begin, _end, _type); + } + + void push_back(const xpath_node& node, xpath_allocator* alloc) + { + if (_end == _eos) + { + size_t capacity = static_cast(_eos - _begin); + + // get new capacity (1.5x rule) + size_t new_capacity = capacity + capacity / 2 + 1; + + // reallocate the old array or allocate a new one + xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node))); + assert(data); + + // finalize + _begin = data; + _end = data + capacity; + _eos = data + new_capacity; + } + + *_end++ = node; + } + + void append(const xpath_node* begin, const xpath_node* end, xpath_allocator* alloc) + { + size_t size = static_cast(_end - _begin); + size_t capacity = static_cast(_eos - _begin); + size_t count = static_cast(end - begin); + + if (size + count > capacity) + { + // reallocate the old array or allocate a new one + xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), (size + count) * sizeof(xpath_node))); + assert(data); + + // finalize + _begin = data; + _end = data + size; + _eos = data + size + count; + } + + memcpy(_end, begin, count * sizeof(xpath_node)); + _end += count; + } + + void sort_do() + { + _type = xpath_sort(_begin, _end, _type, false); + } + + void truncate(xpath_node* pos) + { + assert(_begin <= pos && pos <= _end); + + _end = pos; + } + + void remove_duplicates() + { + if (_type == xpath_node_set::type_unsorted) + sort(_begin, _end, duplicate_comparator()); + + _end = unique(_begin, _end); + } + + xpath_node_set::type_t type() const + { + return _type; + } + + void set_type(xpath_node_set::type_t type) + { + _type = type; + } + }; +} + +namespace +{ + struct xpath_context + { + xpath_node n; + size_t position, size; + + xpath_context(const xpath_node& n, size_t position, size_t size): n(n), position(position), size(size) + { + } + }; + + enum lexeme_t + { + lex_none = 0, + lex_equal, + lex_not_equal, + lex_less, + lex_greater, + lex_less_or_equal, + lex_greater_or_equal, + lex_plus, + lex_minus, + lex_multiply, + lex_union, + lex_var_ref, + lex_open_brace, + lex_close_brace, + lex_quoted_string, + lex_number, + lex_slash, + lex_double_slash, + lex_open_square_brace, + lex_close_square_brace, + lex_string, + lex_comma, + lex_axis_attribute, + lex_dot, + lex_double_dot, + lex_double_colon, + lex_eof + }; + + struct xpath_lexer_string + { + const char_t* begin; + const char_t* end; + + xpath_lexer_string(): begin(0), end(0) + { + } + + bool operator==(const char_t* other) const + { + size_t length = static_cast(end - begin); + + return strequalrange(other, begin, length); + } + }; + + class xpath_lexer + { + const char_t* _cur; + const char_t* _cur_lexeme_pos; + xpath_lexer_string _cur_lexeme_contents; + + lexeme_t _cur_lexeme; + + public: + explicit xpath_lexer(const char_t* query): _cur(query) + { + next(); + } + + const char_t* state() const + { + return _cur; + } + + void next() + { + const char_t* cur = _cur; + + while (IS_CHARTYPE(*cur, ct_space)) ++cur; + + // save lexeme position for error reporting + _cur_lexeme_pos = cur; + + switch (*cur) + { + case 0: + _cur_lexeme = lex_eof; + break; + + case '>': + if (*(cur+1) == '=') + { + cur += 2; + _cur_lexeme = lex_greater_or_equal; + } + else + { + cur += 1; + _cur_lexeme = lex_greater; + } + break; + + case '<': + if (*(cur+1) == '=') + { + cur += 2; + _cur_lexeme = lex_less_or_equal; + } + else + { + cur += 1; + _cur_lexeme = lex_less; + } + break; + + case '!': + if (*(cur+1) == '=') + { + cur += 2; + _cur_lexeme = lex_not_equal; + } + else + { + _cur_lexeme = lex_none; + } + break; + + case '=': + cur += 1; + _cur_lexeme = lex_equal; + + break; + + case '+': + cur += 1; + _cur_lexeme = lex_plus; + + break; + + case '-': + cur += 1; + _cur_lexeme = lex_minus; + + break; + + case '*': + cur += 1; + _cur_lexeme = lex_multiply; + + break; + + case '|': + cur += 1; + _cur_lexeme = lex_union; + + break; + + case '$': + cur += 1; + + if (IS_CHARTYPEX(*cur, ctx_start_symbol)) + { + _cur_lexeme_contents.begin = cur; + + while (IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + + if (cur[0] == ':' && IS_CHARTYPEX(cur[1], ctx_symbol)) // qname + { + cur++; // : + + while (IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + } + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_var_ref; + } + else + { + _cur_lexeme = lex_none; + } + + break; + + case '(': + cur += 1; + _cur_lexeme = lex_open_brace; + + break; + + case ')': + cur += 1; + _cur_lexeme = lex_close_brace; + + break; + + case '[': + cur += 1; + _cur_lexeme = lex_open_square_brace; + + break; + + case ']': + cur += 1; + _cur_lexeme = lex_close_square_brace; + + break; + + case ',': + cur += 1; + _cur_lexeme = lex_comma; + + break; + + case '/': + if (*(cur+1) == '/') + { + cur += 2; + _cur_lexeme = lex_double_slash; + } + else + { + cur += 1; + _cur_lexeme = lex_slash; + } + break; + + case '.': + if (*(cur+1) == '.') + { + cur += 2; + _cur_lexeme = lex_double_dot; + } + else if (IS_CHARTYPEX(*(cur+1), ctx_digit)) + { + _cur_lexeme_contents.begin = cur; // . + + ++cur; + + while (IS_CHARTYPEX(*cur, ctx_digit)) cur++; + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_number; + } + else + { + cur += 1; + _cur_lexeme = lex_dot; + } + break; + + case '@': + cur += 1; + _cur_lexeme = lex_axis_attribute; + + break; + + case '"': + case '\'': + { + char_t terminator = *cur; + + ++cur; + + _cur_lexeme_contents.begin = cur; + while (*cur && *cur != terminator) cur++; + _cur_lexeme_contents.end = cur; + + if (!*cur) + _cur_lexeme = lex_none; + else + { + cur += 1; + _cur_lexeme = lex_quoted_string; + } + + break; + } + + case ':': + if (*(cur+1) == ':') + { + cur += 2; + _cur_lexeme = lex_double_colon; + } + else + { + _cur_lexeme = lex_none; + } + break; + + default: + if (IS_CHARTYPEX(*cur, ctx_digit)) + { + _cur_lexeme_contents.begin = cur; + + while (IS_CHARTYPEX(*cur, ctx_digit)) cur++; + + if (*cur == '.') + { + cur++; + + while (IS_CHARTYPEX(*cur, ctx_digit)) cur++; + } + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_number; + } + else if (IS_CHARTYPEX(*cur, ctx_start_symbol)) + { + _cur_lexeme_contents.begin = cur; + + while (IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + + if (cur[0] == ':') + { + if (cur[1] == '*') // namespace test ncname:* + { + cur += 2; // :* + } + else if (IS_CHARTYPEX(cur[1], ctx_symbol)) // namespace test qname + { + cur++; // : + + while (IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + } + } + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_string; + } + else + { + _cur_lexeme = lex_none; + } + } + + _cur = cur; + } + + lexeme_t current() const + { + return _cur_lexeme; + } + + const char_t* current_pos() const + { + return _cur_lexeme_pos; + } + + const xpath_lexer_string& contents() const + { + assert(_cur_lexeme == lex_var_ref || _cur_lexeme == lex_number || _cur_lexeme == lex_string || _cur_lexeme == lex_quoted_string); + + return _cur_lexeme_contents; + } + }; + + enum ast_type_t + { + ast_op_or, // left or right + ast_op_and, // left and right + ast_op_equal, // left = right + ast_op_not_equal, // left != right + ast_op_less, // left < right + ast_op_greater, // left > right + ast_op_less_or_equal, // left <= right + ast_op_greater_or_equal, // left >= right + ast_op_add, // left + right + ast_op_subtract, // left - right + ast_op_multiply, // left * right + ast_op_divide, // left / right + ast_op_mod, // left % right + ast_op_negate, // left - right + ast_op_union, // left | right + ast_predicate, // apply predicate to set; next points to next predicate + ast_filter, // select * from left where right + ast_filter_posinv, // select * from left where right; proximity position invariant + ast_string_constant, // string constant + ast_number_constant, // number constant + ast_variable, // variable + ast_func_last, // last() + ast_func_position, // position() + ast_func_count, // count(left) + ast_func_id, // id(left) + ast_func_local_name_0, // local-name() + ast_func_local_name_1, // local-name(left) + ast_func_namespace_uri_0, // namespace-uri() + ast_func_namespace_uri_1, // namespace-uri(left) + ast_func_name_0, // name() + ast_func_name_1, // name(left) + ast_func_string_0, // string() + ast_func_string_1, // string(left) + ast_func_concat, // concat(left, right, siblings) + ast_func_starts_with, // starts_with(left, right) + ast_func_contains, // contains(left, right) + ast_func_substring_before, // substring-before(left, right) + ast_func_substring_after, // substring-after(left, right) + ast_func_substring_2, // substring(left, right) + ast_func_substring_3, // substring(left, right, third) + ast_func_string_length_0, // string-length() + ast_func_string_length_1, // string-length(left) + ast_func_normalize_space_0, // normalize-space() + ast_func_normalize_space_1, // normalize-space(left) + ast_func_translate, // translate(left, right, third) + ast_func_boolean, // boolean(left) + ast_func_not, // not(left) + ast_func_true, // true() + ast_func_false, // false() + ast_func_lang, // lang(left) + ast_func_number_0, // number() + ast_func_number_1, // number(left) + ast_func_sum, // sum(left) + ast_func_floor, // floor(left) + ast_func_ceiling, // ceiling(left) + ast_func_round, // round(left) + ast_step, // process set left with step + ast_step_root // select root node + }; + + enum axis_t + { + axis_ancestor, + axis_ancestor_or_self, + axis_attribute, + axis_child, + axis_descendant, + axis_descendant_or_self, + axis_following, + axis_following_sibling, + axis_namespace, + axis_parent, + axis_preceding, + axis_preceding_sibling, + axis_self + }; + + enum nodetest_t + { + nodetest_none, + nodetest_name, + nodetest_type_node, + nodetest_type_comment, + nodetest_type_pi, + nodetest_type_text, + nodetest_pi, + nodetest_all, + nodetest_all_in_namespace + }; + + template struct axis_to_type + { + static const axis_t axis; + }; + + template const axis_t axis_to_type::axis = N; + + class xpath_ast_node + { + private: + // node type + char _type; + char _rettype; + + // for ast_step / ast_predicate + char _axis; + char _test; + + // tree node structure + xpath_ast_node* _left; + xpath_ast_node* _right; + xpath_ast_node* _next; + + union + { + // value for ast_string_constant + const char_t* string; + // value for ast_number_constant + double number; + // variable for ast_variable + xpath_variable* variable; + // node test for ast_step (node name/namespace/node type/pi target) + const char_t* nodetest; + } _data; + + xpath_ast_node(const xpath_ast_node&); + xpath_ast_node& operator=(const xpath_ast_node&); + + template static bool compare_eq(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) + { + xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); + + if (lt != xpath_type_node_set && rt != xpath_type_node_set) + { + if (lt == xpath_type_boolean || rt == xpath_type_boolean) + return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); + else if (lt == xpath_type_number || rt == xpath_type_number) + return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); + else if (lt == xpath_type_string || rt == xpath_type_string) + { + xpath_allocator_capture cr(stack.result); + + xpath_string ls = lhs->eval_string(c, stack); + xpath_string rs = rhs->eval_string(c, stack); + + return comp(ls, rs); + } + } + else if (lt == xpath_type_node_set && rt == xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ls = lhs->eval_node_set(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack); + + for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(string_value(*li, stack.result), string_value(*ri, stack.result))) + return true; + } + + return false; + } + else + { + if (lt == xpath_type_node_set) + { + swap(lhs, rhs); + swap(lt, rt); + } + + if (lt == xpath_type_boolean) + return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); + else if (lt == xpath_type_number) + { + xpath_allocator_capture cr(stack.result); + + double l = lhs->eval_number(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) + return true; + } + + return false; + } + else if (lt == xpath_type_string) + { + xpath_allocator_capture cr(stack.result); + + xpath_string l = lhs->eval_string(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(l, string_value(*ri, stack.result))) + return true; + } + + return false; + } + } + + assert(!"Wrong types"); + return false; + } + + template static bool compare_rel(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) + { + xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); + + if (lt != xpath_type_node_set && rt != xpath_type_node_set) + return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); + else if (lt == xpath_type_node_set && rt == xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ls = lhs->eval_node_set(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack); + + for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) + { + xpath_allocator_capture cri(stack.result); + + double l = convert_string_to_number(string_value(*li, stack.result).c_str()); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture crii(stack.result); + + if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) + return true; + } + } + + return false; + } + else if (lt != xpath_type_node_set && rt == xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + double l = lhs->eval_number(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) + return true; + } + + return false; + } + else if (lt == xpath_type_node_set && rt != xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ls = lhs->eval_node_set(c, stack); + double r = rhs->eval_number(c, stack); + + for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) + { + xpath_allocator_capture cri(stack.result); + + if (comp(convert_string_to_number(string_value(*li, stack.result).c_str()), r)) + return true; + } + + return false; + } + else + { + assert(!"Wrong types"); + return false; + } + } + + void apply_predicate(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack) + { + assert(ns.size() >= first); + + size_t i = 1; + size_t size = ns.size() - first; + + xpath_node* last = ns.begin() + first; + + // remove_if... or well, sort of + for (xpath_node* it = last; it != ns.end(); ++it, ++i) + { + xpath_context c(*it, i, size); + + if (expr->rettype() == xpath_type_number) + { + if (expr->eval_number(c, stack) == i) + *last++ = *it; + } + else if (expr->eval_boolean(c, stack)) + *last++ = *it; + } + + ns.truncate(last); + } + + void apply_predicates(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack) + { + if (ns.size() == first) return; + + for (xpath_ast_node* pred = _right; pred; pred = pred->_next) + { + apply_predicate(ns, first, pred->_left, stack); + } + } + + void step_push(xpath_node_set_raw& ns, const xml_attribute& a, const xml_node& parent, xpath_allocator* alloc) + { + if (!a) return; + + const char_t* name = a.name(); + + // There are no attribute nodes corresponding to attributes that declare namespaces + // That is, "xmlns:..." or "xmlns" + if (starts_with(name, PUGIXML_TEXT("xmlns")) && (name[5] == 0 || name[5] == ':')) return; + + switch (_test) + { + case nodetest_name: + if (strequal(name, _data.nodetest)) ns.push_back(xpath_node(a, parent), alloc); + break; + + case nodetest_type_node: + case nodetest_all: + ns.push_back(xpath_node(a, parent), alloc); + break; + + case nodetest_all_in_namespace: + if (starts_with(name, _data.nodetest)) + ns.push_back(xpath_node(a, parent), alloc); + break; + + default: + ; + } + } + + void step_push(xpath_node_set_raw& ns, const xml_node& n, xpath_allocator* alloc) + { + if (!n) return; + + switch (_test) + { + case nodetest_name: + if (n.type() == node_element && strequal(n.name(), _data.nodetest)) ns.push_back(n, alloc); + break; + + case nodetest_type_node: + ns.push_back(n, alloc); + break; + + case nodetest_type_comment: + if (n.type() == node_comment) + ns.push_back(n, alloc); + break; + + case nodetest_type_text: + if (n.type() == node_pcdata || n.type() == node_cdata) + ns.push_back(n, alloc); + break; + + case nodetest_type_pi: + if (n.type() == node_pi) + ns.push_back(n, alloc); + break; + + case nodetest_pi: + if (n.type() == node_pi && strequal(n.name(), _data.nodetest)) + ns.push_back(n, alloc); + break; + + case nodetest_all: + if (n.type() == node_element) + ns.push_back(n, alloc); + break; + + case nodetest_all_in_namespace: + if (n.type() == node_element && starts_with(n.name(), _data.nodetest)) + ns.push_back(n, alloc); + break; + + default: + assert(!"Unknown axis"); + } + } + + template void step_fill(xpath_node_set_raw& ns, const xml_node& n, xpath_allocator* alloc, T) + { + const axis_t axis = T::axis; + + switch (axis) + { + case axis_attribute: + { + for (xml_attribute a = n.first_attribute(); a; a = a.next_attribute()) + step_push(ns, a, n, alloc); + + break; + } + + case axis_child: + { + for (xml_node c = n.first_child(); c; c = c.next_sibling()) + step_push(ns, c, alloc); + + break; + } + + case axis_descendant: + case axis_descendant_or_self: + { + if (axis == axis_descendant_or_self) + step_push(ns, n, alloc); + + xml_node cur = n.first_child(); + + while (cur && cur != n) + { + step_push(ns, cur, alloc); + + if (cur.first_child()) + cur = cur.first_child(); + else if (cur.next_sibling()) + cur = cur.next_sibling(); + else + { + while (!cur.next_sibling() && cur != n) + cur = cur.parent(); + + if (cur != n) cur = cur.next_sibling(); + } + } + + break; + } + + case axis_following_sibling: + { + for (xml_node c = n.next_sibling(); c; c = c.next_sibling()) + step_push(ns, c, alloc); + + break; + } + + case axis_preceding_sibling: + { + for (xml_node c = n.previous_sibling(); c; c = c.previous_sibling()) + step_push(ns, c, alloc); + + break; + } + + case axis_following: + { + xml_node cur = n; + + // exit from this node so that we don't include descendants + while (cur && !cur.next_sibling()) cur = cur.parent(); + cur = cur.next_sibling(); + + for (;;) + { + step_push(ns, cur, alloc); + + if (cur.first_child()) + cur = cur.first_child(); + else if (cur.next_sibling()) + cur = cur.next_sibling(); + else + { + while (cur && !cur.next_sibling()) cur = cur.parent(); + cur = cur.next_sibling(); + + if (!cur) break; + } + } + + break; + } + + case axis_preceding: + { + xml_node cur = n; + + while (cur && !cur.previous_sibling()) cur = cur.parent(); + cur = cur.previous_sibling(); + + for (;;) + { + if (cur.last_child()) + cur = cur.last_child(); + else + { + // leaf node, can't be ancestor + step_push(ns, cur, alloc); + + if (cur.previous_sibling()) + cur = cur.previous_sibling(); + else + { + do + { + cur = cur.parent(); + if (!cur) break; + + if (!node_is_ancestor(cur, n)) step_push(ns, cur, alloc); + } + while (!cur.previous_sibling()); + + cur = cur.previous_sibling(); + + if (!cur) break; + } + } + } + + break; + } + + case axis_ancestor: + case axis_ancestor_or_self: + { + if (axis == axis_ancestor_or_self) + step_push(ns, n, alloc); + + xml_node cur = n.parent(); + + while (cur) + { + step_push(ns, cur, alloc); + + cur = cur.parent(); + } + + break; + } + + case axis_self: + { + step_push(ns, n, alloc); + + break; + } + + case axis_parent: + { + if (n.parent()) step_push(ns, n.parent(), alloc); + + break; + } + + default: + assert(!"Unimplemented axis"); + } + } + + template void step_fill(xpath_node_set_raw& ns, const xml_attribute& a, const xml_node& p, xpath_allocator* alloc, T v) + { + const axis_t axis = T::axis; + + switch (axis) + { + case axis_ancestor: + case axis_ancestor_or_self: + { + if (axis == axis_ancestor_or_self && _test == nodetest_type_node) // reject attributes based on principal node type test + step_push(ns, a, p, alloc); + + xml_node cur = p; + + while (cur) + { + step_push(ns, cur, alloc); + + cur = cur.parent(); + } + + break; + } + + case axis_descendant_or_self: + case axis_self: + { + if (_test == nodetest_type_node) // reject attributes based on principal node type test + step_push(ns, a, p, alloc); + + break; + } + + case axis_following: + { + xml_node cur = p; + + for (;;) + { + if (cur.first_child()) + cur = cur.first_child(); + else if (cur.next_sibling()) + cur = cur.next_sibling(); + else + { + while (cur && !cur.next_sibling()) cur = cur.parent(); + cur = cur.next_sibling(); + + if (!cur) break; + } + + step_push(ns, cur, alloc); + } + + break; + } + + case axis_parent: + { + step_push(ns, p, alloc); + + break; + } + + case axis_preceding: + { + // preceding:: axis does not include attribute nodes and attribute ancestors (they are the same as parent's ancestors), so we can reuse node preceding + step_fill(ns, p, alloc, v); + break; + } + + default: + assert(!"Unimplemented axis"); + } + } + + template xpath_node_set_raw step_do(const xpath_context& c, const xpath_stack& stack, T v) + { + const axis_t axis = T::axis; + bool attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self); + + xpath_node_set_raw ns; + ns.set_type((axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling) ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted); + + if (_left) + { + xpath_node_set_raw s = _left->eval_node_set(c, stack); + + // self axis preserves the original order + if (axis == axis_self) ns.set_type(s.type()); + + for (const xpath_node* it = s.begin(); it != s.end(); ++it) + { + size_t size = ns.size(); + + // in general, all axes generate elements in a particular order, but there is no order guarantee if axis is applied to two nodes + if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted); + + if (it->node()) + step_fill(ns, it->node(), stack.result, v); + else if (attributes) + step_fill(ns, it->attribute(), it->parent(), stack.result, v); + + apply_predicates(ns, size, stack); + } + } + else + { + if (c.n.node()) + step_fill(ns, c.n.node(), stack.result, v); + else if (attributes) + step_fill(ns, c.n.attribute(), c.n.parent(), stack.result, v); + + apply_predicates(ns, 0, stack); + } + + // child, attribute and self axes always generate unique set of nodes + // for other axis, if the set stayed sorted, it stayed unique because the traversal algorithms do not visit the same node twice + if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted) + ns.remove_duplicates(); + + return ns; + } + + public: + xpath_ast_node(ast_type_t type, xpath_value_type rettype, const char_t* value): + _type((char)type), _rettype((char)rettype), _axis(0), _test(0), _left(0), _right(0), _next(0) + { + assert(type == ast_string_constant); + _data.string = value; + } + + xpath_ast_node(ast_type_t type, xpath_value_type rettype, double value): + _type((char)type), _rettype((char)rettype), _axis(0), _test(0), _left(0), _right(0), _next(0) + { + assert(type == ast_number_constant); + _data.number = value; + } + + xpath_ast_node(ast_type_t type, xpath_value_type rettype, xpath_variable* value): + _type((char)type), _rettype((char)rettype), _axis(0), _test(0), _left(0), _right(0), _next(0) + { + assert(type == ast_variable); + _data.variable = value; + } + + xpath_ast_node(ast_type_t type, xpath_value_type rettype, xpath_ast_node* left = 0, xpath_ast_node* right = 0): + _type((char)type), _rettype((char)rettype), _axis(0), _test(0), _left(left), _right(right), _next(0) + { + } + + xpath_ast_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents): + _type((char)type), _rettype(xpath_type_node_set), _axis((char)axis), _test((char)test), _left(left), _right(0), _next(0) + { + _data.nodetest = contents; + } + + void set_next(xpath_ast_node* value) + { + _next = value; + } + + void set_right(xpath_ast_node* value) + { + _right = value; + } + + bool eval_boolean(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_op_or: + return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack); + + case ast_op_and: + return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack); + + case ast_op_equal: + return compare_eq(_left, _right, c, stack, equal_to()); + + case ast_op_not_equal: + return compare_eq(_left, _right, c, stack, not_equal_to()); + + case ast_op_less: + return compare_rel(_left, _right, c, stack, less()); + + case ast_op_greater: + return compare_rel(_right, _left, c, stack, less()); + + case ast_op_less_or_equal: + return compare_rel(_left, _right, c, stack, less_equal()); + + case ast_op_greater_or_equal: + return compare_rel(_right, _left, c, stack, less_equal()); + + case ast_func_starts_with: + { + xpath_allocator_capture cr(stack.result); + + xpath_string lr = _left->eval_string(c, stack); + xpath_string rr = _right->eval_string(c, stack); + + return starts_with(lr.c_str(), rr.c_str()); + } + + case ast_func_contains: + { + xpath_allocator_capture cr(stack.result); + + xpath_string lr = _left->eval_string(c, stack); + xpath_string rr = _right->eval_string(c, stack); + + return find_substring(lr.c_str(), rr.c_str()) != 0; + } + + case ast_func_boolean: + return _left->eval_boolean(c, stack); + + case ast_func_not: + return !_left->eval_boolean(c, stack); + + case ast_func_true: + return true; + + case ast_func_false: + return false; + + case ast_func_lang: + { + if (c.n.attribute()) return false; + + xpath_allocator_capture cr(stack.result); + + xpath_string lang = _left->eval_string(c, stack); + + for (xml_node n = c.n.node(); n; n = n.parent()) + { + xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang")); + + if (a) + { + const char_t* value = a.value(); + + // strnicmp / strncasecmp is not portable + for (const char_t* lit = lang.c_str(); *lit; ++lit) + { + if (tolower_ascii(*lit) != tolower_ascii(*value)) return false; + ++value; + } + + return *value == 0 || *value == '-'; + } + } + + return false; + } + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_boolean) + return _data.variable->get_boolean(); + + // fallthrough to type conversion + } + + default: + { + switch (_rettype) + { + case xpath_type_number: + return convert_number_to_boolean(eval_number(c, stack)); + + case xpath_type_string: + { + xpath_allocator_capture cr(stack.result); + + return !eval_string(c, stack).empty(); + } + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.result); + + return !eval_node_set(c, stack).empty(); + } + + default: + assert(!"Wrong expression for return type boolean"); + return false; + } + } + } + } + + double eval_number(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_op_add: + return _left->eval_number(c, stack) + _right->eval_number(c, stack); + + case ast_op_subtract: + return _left->eval_number(c, stack) - _right->eval_number(c, stack); + + case ast_op_multiply: + return _left->eval_number(c, stack) * _right->eval_number(c, stack); + + case ast_op_divide: + return _left->eval_number(c, stack) / _right->eval_number(c, stack); + + case ast_op_mod: + return fmod(_left->eval_number(c, stack), _right->eval_number(c, stack)); + + case ast_op_negate: + return -_left->eval_number(c, stack); + + case ast_number_constant: + return _data.number; + + case ast_func_last: + return (double)c.size; + + case ast_func_position: + return (double)c.position; + + case ast_func_count: + { + xpath_allocator_capture cr(stack.result); + + return (double)_left->eval_node_set(c, stack).size(); + } + + case ast_func_string_length_0: + { + xpath_allocator_capture cr(stack.result); + + return (double)string_value(c.n, stack.result).length(); + } + + case ast_func_string_length_1: + { + xpath_allocator_capture cr(stack.result); + + return (double)_left->eval_string(c, stack).length(); + } + + case ast_func_number_0: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(string_value(c.n, stack.result).c_str()); + } + + case ast_func_number_1: + return _left->eval_number(c, stack); + + case ast_func_sum: + { + xpath_allocator_capture cr(stack.result); + + double r = 0; + + xpath_node_set_raw ns = _left->eval_node_set(c, stack); + + for (const xpath_node* it = ns.begin(); it != ns.end(); ++it) + { + xpath_allocator_capture cri(stack.result); + + r += convert_string_to_number(string_value(*it, stack.result).c_str()); + } + + return r; + } + + case ast_func_floor: + { + double r = _left->eval_number(c, stack); + + return r == r ? floor(r) : r; + } + + case ast_func_ceiling: + { + double r = _left->eval_number(c, stack); + + return r == r ? ceil(r) : r; + } + + case ast_func_round: + return round_nearest_nzero(_left->eval_number(c, stack)); + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_number) + return _data.variable->get_number(); + + // fallthrough to type conversion + } + + default: + { + switch (_rettype) + { + case xpath_type_boolean: + return eval_boolean(c, stack) ? 1 : 0; + + case xpath_type_string: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(eval_string(c, stack).c_str()); + } + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(eval_string(c, stack).c_str()); + } + + default: + assert(!"Wrong expression for return type number"); + return 0; + } + + } + } + } + + xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) + { + assert(_type == ast_func_concat); + + xpath_allocator_capture ct(stack.temp); + + // count the string number + size_t count = 1; + for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++; + + // gather all strings + xpath_string static_buffer[4]; + xpath_string* buffer = static_buffer; + + // allocate on-heap for large concats + if (count > sizeof(static_buffer) / sizeof(static_buffer[0])) + { + buffer = static_cast(stack.temp->allocate(count * sizeof(xpath_string))); + assert(buffer); + } + + // evaluate all strings to temporary stack + xpath_stack swapped_stack = {stack.temp, stack.result}; + + buffer[0] = _left->eval_string(c, swapped_stack); + + size_t pos = 1; + for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack); + assert(pos == count); + + // get total length + size_t length = 0; + for (size_t i = 0; i < count; ++i) length += buffer[i].length(); + + // create final string + char_t* result = static_cast(stack.result->allocate((length + 1) * sizeof(char_t))); + assert(result); + + char_t* ri = result; + + for (size_t j = 0; j < count; ++j) + for (const char_t* bi = buffer[j].c_str(); *bi; ++bi) + *ri++ = *bi; + + *ri = 0; + + return xpath_string(result, true); + } + + xpath_string eval_string(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_string_constant: + return xpath_string_const(_data.string); + + case ast_func_local_name_0: + { + xpath_node na = c.n; + + return xpath_string_const(local_name(na)); + } + + case ast_func_local_name_1: + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ns = _left->eval_node_set(c, stack); + xpath_node na = ns.first(); + + return xpath_string_const(local_name(na)); + } + + case ast_func_name_0: + { + xpath_node na = c.n; + + return xpath_string_const(qualified_name(na)); + } + + case ast_func_name_1: + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ns = _left->eval_node_set(c, stack); + xpath_node na = ns.first(); + + return xpath_string_const(qualified_name(na)); + } + + case ast_func_namespace_uri_0: + { + xpath_node na = c.n; + + return xpath_string_const(namespace_uri(na)); + } + + case ast_func_namespace_uri_1: + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ns = _left->eval_node_set(c, stack); + xpath_node na = ns.first(); + + return xpath_string_const(namespace_uri(na)); + } + + case ast_func_string_0: + return string_value(c.n, stack.result); + + case ast_func_string_1: + return _left->eval_string(c, stack); + + case ast_func_concat: + return eval_string_concat(c, stack); + + case ast_func_substring_before: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + xpath_string p = _right->eval_string(c, swapped_stack); + + const char_t* pos = find_substring(s.c_str(), p.c_str()); + + return pos ? xpath_string(s.c_str(), pos, stack.result) : xpath_string(); + } + + case ast_func_substring_after: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + xpath_string p = _right->eval_string(c, swapped_stack); + + const char_t* pos = find_substring(s.c_str(), p.c_str()); + if (!pos) return xpath_string(); + + const char_t* result = pos + p.length(); + + return s.uses_heap() ? xpath_string(result, stack.result) : xpath_string_const(result); + } + + case ast_func_substring_2: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + size_t s_length = s.length(); + + double first = round_nearest(_right->eval_number(c, stack)); + + if (is_nan(first)) return xpath_string(); // NaN + else if (first >= s_length + 1) return xpath_string(); + + size_t pos = first < 1 ? 1 : (size_t)first; + assert(1 <= pos && pos <= s_length + 1); + + const char_t* rbegin = s.c_str() + (pos - 1); + + return s.uses_heap() ? xpath_string(rbegin, stack.result) : xpath_string_const(rbegin); + } + + case ast_func_substring_3: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + size_t s_length = s.length(); + + double first = round_nearest(_right->eval_number(c, stack)); + double last = first + round_nearest(_right->_next->eval_number(c, stack)); + + if (is_nan(first) || is_nan(last)) return xpath_string(); + else if (first >= s_length + 1) return xpath_string(); + else if (first >= last) return xpath_string(); + else if (last < 1) return xpath_string(); + + size_t pos = first < 1 ? 1 : (size_t)first; + size_t end = last >= s_length + 1 ? s_length + 1 : (size_t)last; + + assert(1 <= pos && pos <= end && end <= s_length + 1); + const char_t* rbegin = s.c_str() + (pos - 1); + const char_t* rend = s.c_str() + (end - 1); + + return (end == s_length + 1 && !s.uses_heap()) ? xpath_string_const(rbegin) : xpath_string(rbegin, rend, stack.result); + } + + case ast_func_normalize_space_0: + { + xpath_string s = string_value(c.n, stack.result); + + normalize_space(s.data(stack.result)); + + return s; + } + + case ast_func_normalize_space_1: + { + xpath_string s = _left->eval_string(c, stack); + + normalize_space(s.data(stack.result)); + + return s; + } + + case ast_func_translate: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, stack); + xpath_string from = _right->eval_string(c, swapped_stack); + xpath_string to = _right->_next->eval_string(c, swapped_stack); + + translate(s.data(stack.result), from.c_str(), to.c_str()); + + return s; + } + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_string) + return xpath_string_const(_data.variable->get_string()); + + // fallthrough to type conversion + } + + default: + { + switch (_rettype) + { + case xpath_type_boolean: + return xpath_string_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); + + case xpath_type_number: + return convert_number_to_string(eval_number(c, stack), stack.result); + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_node_set_raw ns = eval_node_set(c, swapped_stack); + return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result); + } + + default: + assert(!"Wrong expression for return type string"); + return xpath_string(); + } + } + } + } + + xpath_node_set_raw eval_node_set(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_op_union: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_node_set_raw ls = _left->eval_node_set(c, swapped_stack); + xpath_node_set_raw rs = _right->eval_node_set(c, stack); + + // we can optimize merging two sorted sets, but this is a very rare operation, so don't bother + rs.set_type(xpath_node_set::type_unsorted); + + rs.append(ls.begin(), ls.end(), stack.result); + rs.remove_duplicates(); + + return rs; + } + + case ast_filter: + case ast_filter_posinv: + { + xpath_node_set_raw set = _left->eval_node_set(c, stack); + + // either expression is a number or it contains position() call; sort by document order + if (_type == ast_filter) set.sort_do(); + + apply_predicate(set, 0, _right, stack); + + return set; + } + + case ast_func_id: + return xpath_node_set_raw(); + + case ast_step: + { + switch (_axis) + { + case axis_ancestor: + return step_do(c, stack, axis_to_type()); + + case axis_ancestor_or_self: + return step_do(c, stack, axis_to_type()); + + case axis_attribute: + return step_do(c, stack, axis_to_type()); + + case axis_child: + return step_do(c, stack, axis_to_type()); + + case axis_descendant: + return step_do(c, stack, axis_to_type()); + + case axis_descendant_or_self: + return step_do(c, stack, axis_to_type()); + + case axis_following: + return step_do(c, stack, axis_to_type()); + + case axis_following_sibling: + return step_do(c, stack, axis_to_type()); + + case axis_namespace: + // namespaced axis is not supported + return xpath_node_set_raw(); + + case axis_parent: + return step_do(c, stack, axis_to_type()); + + case axis_preceding: + return step_do(c, stack, axis_to_type()); + + case axis_preceding_sibling: + return step_do(c, stack, axis_to_type()); + + case axis_self: + return step_do(c, stack, axis_to_type()); + } + } + + case ast_step_root: + { + assert(!_right); // root step can't have any predicates + + xpath_node_set_raw ns; + + ns.set_type(xpath_node_set::type_sorted); + + if (c.n.node()) ns.push_back(c.n.node().root(), stack.result); + else if (c.n.attribute()) ns.push_back(c.n.parent().root(), stack.result); + + return ns; + } + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_node_set) + { + const xpath_node_set& s = _data.variable->get_node_set(); + + xpath_node_set_raw ns; + + ns.set_type(s.type()); + ns.append(s.begin(), s.end(), stack.result); + + return ns; + } + + // fallthrough to type conversion + } + + default: + assert(!"Wrong expression for return type node set"); + return xpath_node_set_raw(); + } + } + + bool is_posinv() + { + switch (_type) + { + case ast_func_position: + return false; + + case ast_string_constant: + case ast_number_constant: + case ast_variable: + return true; + + case ast_step: + case ast_step_root: + return true; + + case ast_predicate: + case ast_filter: + case ast_filter_posinv: + return true; + + default: + if (_left && !_left->is_posinv()) return false; + + for (xpath_ast_node* n = _right; n; n = n->_next) + if (!n->is_posinv()) return false; + + return true; + } + } + + xpath_value_type rettype() const + { + return static_cast(_rettype); + } + }; + + struct xpath_parser + { + xpath_allocator* _alloc; + xpath_lexer _lexer; + + const char_t* _query; + xpath_variable_set* _variables; + + xpath_parse_result* _result; + + #ifdef PUGIXML_NO_EXCEPTIONS + jmp_buf _error_handler; + #endif + + void throw_error(const char* message) + { + _result->error = message; + _result->offset = _lexer.current_pos() - _query; + + #ifdef PUGIXML_NO_EXCEPTIONS + longjmp(_error_handler, 1); + #else + throw xpath_exception(*_result); + #endif + } + + void throw_error_oom() + { + #ifdef PUGIXML_NO_EXCEPTIONS + throw_error("Out of memory"); + #else + throw std::bad_alloc(); + #endif + } + + void* alloc_node() + { + void* result = _alloc->allocate_nothrow(sizeof(xpath_ast_node)); + + if (!result) throw_error_oom(); + + return result; + } + + const char_t* alloc_string(const xpath_lexer_string& value) + { + if (value.begin) + { + size_t length = static_cast(value.end - value.begin); + + char_t* c = static_cast(_alloc->allocate_nothrow((length + 1) * sizeof(char_t))); + if (!c) throw_error_oom(); + + memcpy(c, value.begin, length * sizeof(char_t)); + c[length] = 0; + + return c; + } + else return 0; + } + + xpath_ast_node* parse_function_helper(ast_type_t type0, ast_type_t type1, size_t argc, xpath_ast_node* args[2]) + { + assert(argc <= 1); + + if (argc == 1 && args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); + + return new (alloc_node()) xpath_ast_node(argc == 0 ? type0 : type1, xpath_type_string, args[0]); + } + + xpath_ast_node* parse_function(const xpath_lexer_string& name, size_t argc, xpath_ast_node* args[2]) + { + switch (name.begin[0]) + { + case 'b': + if (name == PUGIXML_TEXT("boolean") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_boolean, xpath_type_boolean, args[0]); + + break; + + case 'c': + if (name == PUGIXML_TEXT("count") && argc == 1) + { + if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); + return new (alloc_node()) xpath_ast_node(ast_func_count, xpath_type_number, args[0]); + } + else if (name == PUGIXML_TEXT("contains") && argc == 2) + return new (alloc_node()) xpath_ast_node(ast_func_contains, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("concat") && argc >= 2) + return new (alloc_node()) xpath_ast_node(ast_func_concat, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("ceiling") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_ceiling, xpath_type_number, args[0]); + + break; + + case 'f': + if (name == PUGIXML_TEXT("false") && argc == 0) + return new (alloc_node()) xpath_ast_node(ast_func_false, xpath_type_boolean); + else if (name == PUGIXML_TEXT("floor") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_floor, xpath_type_number, args[0]); + + break; + + case 'i': + if (name == PUGIXML_TEXT("id") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_id, xpath_type_node_set, args[0]); + + break; + + case 'l': + if (name == PUGIXML_TEXT("last") && argc == 0) + return new (alloc_node()) xpath_ast_node(ast_func_last, xpath_type_number); + else if (name == PUGIXML_TEXT("lang") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_lang, xpath_type_boolean, args[0]); + else if (name == PUGIXML_TEXT("local-name") && argc <= 1) + return parse_function_helper(ast_func_local_name_0, ast_func_local_name_1, argc, args); + + break; + + case 'n': + if (name == PUGIXML_TEXT("name") && argc <= 1) + return parse_function_helper(ast_func_name_0, ast_func_name_1, argc, args); + else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1) + return parse_function_helper(ast_func_namespace_uri_0, ast_func_namespace_uri_1, argc, args); + else if (name == PUGIXML_TEXT("normalize-space") && argc <= 1) + return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_normalize_space_0 : ast_func_normalize_space_1, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("not") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_not, xpath_type_boolean, args[0]); + else if (name == PUGIXML_TEXT("number") && argc <= 1) + return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]); + + break; + + case 'p': + if (name == PUGIXML_TEXT("position") && argc == 0) + return new (alloc_node()) xpath_ast_node(ast_func_position, xpath_type_number); + + break; + + case 'r': + if (name == PUGIXML_TEXT("round") && argc == 1) + return new (alloc_node()) xpath_ast_node(ast_func_round, xpath_type_number, args[0]); + + break; + + case 's': + if (name == PUGIXML_TEXT("string") && argc <= 1) + return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]); + else if (name == PUGIXML_TEXT("string-length") && argc <= 1) + return new (alloc_node()) xpath_ast_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_string, args[0]); + else if (name == PUGIXML_TEXT("starts-with") && argc == 2) + return new (alloc_node()) xpath_ast_node(ast_func_starts_with, xpath_type_boolean, args[0], args[1]); + else if (name == PUGIXML_TEXT("substring-before") && argc == 2) + return new (alloc_node()) xpath_ast_node(ast_func_substring_before, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("substring-after") && argc == 2) + return new (alloc_node()) xpath_ast_node(ast_func_substring_after, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("substring") && (argc == 2 || argc == 3)) + return new (alloc_node()) xpath_ast_node(argc == 2 ? ast_func_substring_2 : ast_func_substring_3, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("sum") && argc == 1) + { + if (args[0]->rettype() != xpath_type_node_set) throw_error("Function has to be applied to node set"); + return new (alloc_node()) xpath_ast_node(ast_func_sum, xpath_type_number, args[0]); + } + + break; + + case 't': + if (name == PUGIXML_TEXT("translate") && argc == 3) + return new (alloc_node()) xpath_ast_node(ast_func_translate, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("true") && argc == 0) + return new (alloc_node()) xpath_ast_node(ast_func_true, xpath_type_boolean); + + break; + } + + throw_error("Unrecognized function or wrong parameter count"); + + return 0; + } + + axis_t parse_axis_name(const xpath_lexer_string& name, bool& specified) + { + specified = true; + + switch (name.begin[0]) + { + case 'a': + if (name == PUGIXML_TEXT("ancestor")) + return axis_ancestor; + else if (name == PUGIXML_TEXT("ancestor-or-self")) + return axis_ancestor_or_self; + else if (name == PUGIXML_TEXT("attribute")) + return axis_attribute; + + break; + + case 'c': + if (name == PUGIXML_TEXT("child")) + return axis_child; + + break; + + case 'd': + if (name == PUGIXML_TEXT("descendant")) + return axis_descendant; + else if (name == PUGIXML_TEXT("descendant-or-self")) + return axis_descendant_or_self; + + break; + + case 'f': + if (name == PUGIXML_TEXT("following")) + return axis_following; + else if (name == PUGIXML_TEXT("following-sibling")) + return axis_following_sibling; + + break; + + case 'n': + if (name == PUGIXML_TEXT("namespace")) + return axis_namespace; + + break; + + case 'p': + if (name == PUGIXML_TEXT("parent")) + return axis_parent; + else if (name == PUGIXML_TEXT("preceding")) + return axis_preceding; + else if (name == PUGIXML_TEXT("preceding-sibling")) + return axis_preceding_sibling; + + break; + + case 's': + if (name == PUGIXML_TEXT("self")) + return axis_self; + + break; + } + + specified = false; + return axis_child; + } + + nodetest_t parse_node_test_type(const xpath_lexer_string& name) + { + switch (name.begin[0]) + { + case 'c': + if (name == PUGIXML_TEXT("comment")) + return nodetest_type_comment; + + break; + + case 'n': + if (name == PUGIXML_TEXT("node")) + return nodetest_type_node; + + break; + + case 'p': + if (name == PUGIXML_TEXT("processing-instruction")) + return nodetest_type_pi; + + break; + + case 't': + if (name == PUGIXML_TEXT("text")) + return nodetest_type_text; + + break; + } + + return nodetest_none; + } + + // PrimaryExpr ::= VariableReference | '(' Expr ')' | Literal | Number | FunctionCall + xpath_ast_node* parse_primary_expression() + { + switch (_lexer.current()) + { + case lex_var_ref: + { + xpath_lexer_string name = _lexer.contents(); + + if (!_variables) + throw_error("Unknown variable: variable set is not provided"); + + xpath_variable* var = get_variable(_variables, name.begin, name.end); + + if (!var) + throw_error("Unknown variable: variable set does not contain the given name"); + + _lexer.next(); + + return new (alloc_node()) xpath_ast_node(ast_variable, var->type(), var); + } + + case lex_open_brace: + { + _lexer.next(); + + xpath_ast_node* n = parse_expression(); + + if (_lexer.current() != lex_close_brace) + throw_error("Unmatched braces"); + + _lexer.next(); + + return n; + } + + case lex_quoted_string: + { + const char_t* value = alloc_string(_lexer.contents()); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_string_constant, xpath_type_string, value); + _lexer.next(); + + return n; + } + + case lex_number: + { + double value = 0; + + if (!convert_string_to_number(_lexer.contents().begin, _lexer.contents().end, &value)) + throw_error_oom(); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_number_constant, xpath_type_number, value); + _lexer.next(); + + return n; + } + + case lex_string: + { + xpath_ast_node* args[2] = {0}; + size_t argc = 0; + + xpath_lexer_string function = _lexer.contents(); + _lexer.next(); + + xpath_ast_node* last_arg = 0; + + if (_lexer.current() != lex_open_brace) + throw_error("Unrecognized function call"); + _lexer.next(); + + if (_lexer.current() != lex_close_brace) + args[argc++] = parse_expression(); + + while (_lexer.current() != lex_close_brace) + { + if (_lexer.current() != lex_comma) + throw_error("No comma between function arguments"); + _lexer.next(); + + xpath_ast_node* n = parse_expression(); + + if (argc < 2) args[argc] = n; + else last_arg->set_next(n); + + argc++; + last_arg = n; + } + + _lexer.next(); + + return parse_function(function, argc, args); + } + + default: + throw_error("Unrecognizable primary expression"); + + return 0; + } + } + + // FilterExpr ::= PrimaryExpr | FilterExpr Predicate + // Predicate ::= '[' PredicateExpr ']' + // PredicateExpr ::= Expr + xpath_ast_node* parse_filter_expression() + { + xpath_ast_node* n = parse_primary_expression(); + + while (_lexer.current() == lex_open_square_brace) + { + _lexer.next(); + + xpath_ast_node* expr = parse_expression(); + + if (n->rettype() != xpath_type_node_set) throw_error("Predicate has to be applied to node set"); + + bool posinv = expr->rettype() != xpath_type_number && expr->is_posinv(); + + n = new (alloc_node()) xpath_ast_node(posinv ? ast_filter_posinv : ast_filter, xpath_type_node_set, n, expr); + + if (_lexer.current() != lex_close_square_brace) + throw_error("Unmatched square brace"); + + _lexer.next(); + } + + return n; + } + + // Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep + // AxisSpecifier ::= AxisName '::' | '@'? + // NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' + // NameTest ::= '*' | NCName ':' '*' | QName + // AbbreviatedStep ::= '.' | '..' + xpath_ast_node* parse_step(xpath_ast_node* set) + { + if (set && set->rettype() != xpath_type_node_set) + throw_error("Step has to be applied to node set"); + + bool axis_specified = false; + axis_t axis = axis_child; // implied child axis + + if (_lexer.current() == lex_axis_attribute) + { + axis = axis_attribute; + axis_specified = true; + + _lexer.next(); + } + else if (_lexer.current() == lex_dot) + { + _lexer.next(); + + return new (alloc_node()) xpath_ast_node(ast_step, set, axis_self, nodetest_type_node, 0); + } + else if (_lexer.current() == lex_double_dot) + { + _lexer.next(); + + return new (alloc_node()) xpath_ast_node(ast_step, set, axis_parent, nodetest_type_node, 0); + } + + nodetest_t nt_type = nodetest_none; + xpath_lexer_string nt_name; + + if (_lexer.current() == lex_string) + { + // node name test + nt_name = _lexer.contents(); + _lexer.next(); + + // was it an axis name? + if (_lexer.current() == lex_double_colon) + { + // parse axis name + if (axis_specified) throw_error("Two axis specifiers in one step"); + + axis = parse_axis_name(nt_name, axis_specified); + + if (!axis_specified) throw_error("Unknown axis"); + + // read actual node test + _lexer.next(); + + if (_lexer.current() == lex_multiply) + { + nt_type = nodetest_all; + nt_name = xpath_lexer_string(); + _lexer.next(); + } + else if (_lexer.current() == lex_string) + { + nt_name = _lexer.contents(); + _lexer.next(); + } + else throw_error("Unrecognized node test"); + } + + if (nt_type == nodetest_none) + { + // node type test or processing-instruction + if (_lexer.current() == lex_open_brace) + { + _lexer.next(); + + if (_lexer.current() == lex_close_brace) + { + _lexer.next(); + + nt_type = parse_node_test_type(nt_name); + + if (nt_type == nodetest_none) throw_error("Unrecognized node type"); + + nt_name = xpath_lexer_string(); + } + else if (nt_name == PUGIXML_TEXT("processing-instruction")) + { + if (_lexer.current() != lex_quoted_string) + throw_error("Only literals are allowed as arguments to processing-instruction()"); + + nt_type = nodetest_pi; + nt_name = _lexer.contents(); + _lexer.next(); + + if (_lexer.current() != lex_close_brace) + throw_error("Unmatched brace near processing-instruction()"); + _lexer.next(); + } + else + throw_error("Unmatched brace near node type test"); + + } + // QName or NCName:* + else + { + if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:* + { + nt_name.end--; // erase * + + nt_type = nodetest_all_in_namespace; + } + else nt_type = nodetest_name; + } + } + } + else if (_lexer.current() == lex_multiply) + { + nt_type = nodetest_all; + _lexer.next(); + } + else throw_error("Unrecognized node test"); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step, set, axis, nt_type, alloc_string(nt_name)); + + xpath_ast_node* last = 0; + + while (_lexer.current() == lex_open_square_brace) + { + _lexer.next(); + + xpath_ast_node* expr = parse_expression(); + + xpath_ast_node* pred = new (alloc_node()) xpath_ast_node(ast_predicate, xpath_type_node_set, expr); + + if (_lexer.current() != lex_close_square_brace) + throw_error("Unmatched square brace"); + _lexer.next(); + + if (last) last->set_next(pred); + else n->set_right(pred); + + last = pred; + } + + return n; + } + + // RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | RelativeLocationPath '//' Step + xpath_ast_node* parse_relative_location_path(xpath_ast_node* set) + { + xpath_ast_node* n = parse_step(set); + + while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) + { + lexeme_t l = _lexer.current(); + _lexer.next(); + + if (l == lex_double_slash) + n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); + + n = parse_step(n); + } + + return n; + } + + // LocationPath ::= RelativeLocationPath | AbsoluteLocationPath + // AbsoluteLocationPath ::= '/' RelativeLocationPath? | '//' RelativeLocationPath + xpath_ast_node* parse_location_path() + { + if (_lexer.current() == lex_slash) + { + _lexer.next(); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); + + // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path + lexeme_t l = _lexer.current(); + + if (l == lex_string || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply) + return parse_relative_location_path(n); + else + return n; + } + else if (_lexer.current() == lex_double_slash) + { + _lexer.next(); + + xpath_ast_node* n = new (alloc_node()) xpath_ast_node(ast_step_root, xpath_type_node_set); + n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); + + return parse_relative_location_path(n); + } + + // else clause moved outside of if because of bogus warning 'control may reach end of non-void function being inlined' in gcc 4.0.1 + return parse_relative_location_path(0); + } + + // PathExpr ::= LocationPath + // | FilterExpr + // | FilterExpr '/' RelativeLocationPath + // | FilterExpr '//' RelativeLocationPath + xpath_ast_node* parse_path_expression() + { + // Clarification. + // PathExpr begins with either LocationPath or FilterExpr. + // FilterExpr begins with PrimaryExpr + // PrimaryExpr begins with '$' in case of it being a variable reference, + // '(' in case of it being an expression, string literal, number constant or + // function call. + + if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace || + _lexer.current() == lex_quoted_string || _lexer.current() == lex_number || + _lexer.current() == lex_string) + { + if (_lexer.current() == lex_string) + { + // This is either a function call, or not - if not, we shall proceed with location path + const char_t* state = _lexer.state(); + + while (IS_CHARTYPE(*state, ct_space)) ++state; + + if (*state != '(') return parse_location_path(); + + // This looks like a function call; however this still can be a node-test. Check it. + if (parse_node_test_type(_lexer.contents()) != nodetest_none) return parse_location_path(); + } + + xpath_ast_node* n = parse_filter_expression(); + + if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) + { + lexeme_t l = _lexer.current(); + _lexer.next(); + + if (l == lex_double_slash) + { + if (n->rettype() != xpath_type_node_set) throw_error("Step has to be applied to node set"); + + n = new (alloc_node()) xpath_ast_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); + } + + // select from location path + return parse_relative_location_path(n); + } + + return n; + } + else return parse_location_path(); + } + + // UnionExpr ::= PathExpr | UnionExpr '|' PathExpr + xpath_ast_node* parse_union_expression() + { + xpath_ast_node* n = parse_path_expression(); + + while (_lexer.current() == lex_union) + { + _lexer.next(); + + xpath_ast_node* expr = parse_union_expression(); + + if (n->rettype() != xpath_type_node_set || expr->rettype() != xpath_type_node_set) + throw_error("Union operator has to be applied to node sets"); + + n = new (alloc_node()) xpath_ast_node(ast_op_union, xpath_type_node_set, n, expr); + } + + return n; + } + + // UnaryExpr ::= UnionExpr | '-' UnaryExpr + xpath_ast_node* parse_unary_expression() + { + if (_lexer.current() == lex_minus) + { + _lexer.next(); + + xpath_ast_node* expr = parse_unary_expression(); + + return new (alloc_node()) xpath_ast_node(ast_op_negate, xpath_type_number, expr); + } + else return parse_union_expression(); + } + + // MultiplicativeExpr ::= UnaryExpr + // | MultiplicativeExpr '*' UnaryExpr + // | MultiplicativeExpr 'div' UnaryExpr + // | MultiplicativeExpr 'mod' UnaryExpr + xpath_ast_node* parse_multiplicative_expression() + { + xpath_ast_node* n = parse_unary_expression(); + + while (_lexer.current() == lex_multiply || (_lexer.current() == lex_string && + (_lexer.contents() == PUGIXML_TEXT("mod") || _lexer.contents() == PUGIXML_TEXT("div")))) + { + ast_type_t op = _lexer.current() == lex_multiply ? ast_op_multiply : + _lexer.contents().begin[0] == 'd' ? ast_op_divide : ast_op_mod; + _lexer.next(); + + xpath_ast_node* expr = parse_unary_expression(); + + n = new (alloc_node()) xpath_ast_node(op, xpath_type_number, n, expr); + } + + return n; + } + + // AdditiveExpr ::= MultiplicativeExpr + // | AdditiveExpr '+' MultiplicativeExpr + // | AdditiveExpr '-' MultiplicativeExpr + xpath_ast_node* parse_additive_expression() + { + xpath_ast_node* n = parse_multiplicative_expression(); + + while (_lexer.current() == lex_plus || _lexer.current() == lex_minus) + { + lexeme_t l = _lexer.current(); + + _lexer.next(); + + xpath_ast_node* expr = parse_multiplicative_expression(); + + n = new (alloc_node()) xpath_ast_node(l == lex_plus ? ast_op_add : ast_op_subtract, xpath_type_number, n, expr); + } + + return n; + } + + // RelationalExpr ::= AdditiveExpr + // | RelationalExpr '<' AdditiveExpr + // | RelationalExpr '>' AdditiveExpr + // | RelationalExpr '<=' AdditiveExpr + // | RelationalExpr '>=' AdditiveExpr + xpath_ast_node* parse_relational_expression() + { + xpath_ast_node* n = parse_additive_expression(); + + while (_lexer.current() == lex_less || _lexer.current() == lex_less_or_equal || + _lexer.current() == lex_greater || _lexer.current() == lex_greater_or_equal) + { + lexeme_t l = _lexer.current(); + _lexer.next(); + + xpath_ast_node* expr = parse_additive_expression(); + + n = new (alloc_node()) xpath_ast_node(l == lex_less ? ast_op_less : l == lex_greater ? ast_op_greater : + l == lex_less_or_equal ? ast_op_less_or_equal : ast_op_greater_or_equal, xpath_type_boolean, n, expr); + } + + return n; + } + + // EqualityExpr ::= RelationalExpr + // | EqualityExpr '=' RelationalExpr + // | EqualityExpr '!=' RelationalExpr + xpath_ast_node* parse_equality_expression() + { + xpath_ast_node* n = parse_relational_expression(); + + while (_lexer.current() == lex_equal || _lexer.current() == lex_not_equal) + { + lexeme_t l = _lexer.current(); + + _lexer.next(); + + xpath_ast_node* expr = parse_relational_expression(); + + n = new (alloc_node()) xpath_ast_node(l == lex_equal ? ast_op_equal : ast_op_not_equal, xpath_type_boolean, n, expr); + } + + return n; + } + + // AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr + xpath_ast_node* parse_and_expression() + { + xpath_ast_node* n = parse_equality_expression(); + + while (_lexer.current() == lex_string && _lexer.contents() == PUGIXML_TEXT("and")) + { + _lexer.next(); + + xpath_ast_node* expr = parse_equality_expression(); + + n = new (alloc_node()) xpath_ast_node(ast_op_and, xpath_type_boolean, n, expr); + } + + return n; + } + + // OrExpr ::= AndExpr | OrExpr 'or' AndExpr + xpath_ast_node* parse_or_expression() + { + xpath_ast_node* n = parse_and_expression(); + + while (_lexer.current() == lex_string && _lexer.contents() == PUGIXML_TEXT("or")) + { + _lexer.next(); + + xpath_ast_node* expr = parse_and_expression(); + + n = new (alloc_node()) xpath_ast_node(ast_op_or, xpath_type_boolean, n, expr); + } + + return n; + } + + // Expr ::= OrExpr + xpath_ast_node* parse_expression() + { + return parse_or_expression(); + } + + xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result) + { + } + + xpath_ast_node* parse() + { + xpath_ast_node* result = parse_expression(); + + if (_lexer.current() != lex_eof) + { + // there are still unparsed tokens left, error + throw_error("Incorrect query"); + } + + return result; + } + + static xpath_ast_node* parse(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result) + { + xpath_parser parser(query, variables, alloc, result); + + #ifdef PUGIXML_NO_EXCEPTIONS + int error = setjmp(parser._error_handler); + + return (error == 0) ? parser.parse() : 0; + #else + return parser.parse(); + #endif + } + }; + + struct xpath_query_impl + { + static xpath_query_impl* create() + { + void* memory = global_allocate(sizeof(xpath_query_impl)); + + return new (memory) xpath_query_impl(); + } + + static void destroy(void* ptr) + { + if (!ptr) return; + + // free all allocated pages + static_cast(ptr)->alloc.release(); + + // free allocator memory (with the first page) + global_deallocate(ptr); + } + + xpath_query_impl(): root(0), alloc(&block) + { + block.next = 0; + } + + xpath_ast_node* root; + xpath_allocator alloc; + xpath_memory_block block; + }; + + xpath_string evaluate_string_impl(xpath_query_impl* impl, const xpath_node& n, xpath_stack_data& sd) + { + if (!impl) return xpath_string(); + + #ifdef PUGIXML_NO_EXCEPTIONS + if (setjmp(sd.error_handler)) return xpath_string(); + #endif + + xpath_context c(n, 1, 1); + + return impl->root->eval_string(c, sd.stack); + } +} + +namespace pugi +{ +#ifndef PUGIXML_NO_EXCEPTIONS + xpath_exception::xpath_exception(const xpath_parse_result& result): _result(result) + { + assert(result.error); + } + + const char* xpath_exception::what() const throw() + { + return _result.error; + } + + const xpath_parse_result& xpath_exception::result() const + { + return _result; + } +#endif + + xpath_node::xpath_node() + { + } + + xpath_node::xpath_node(const xml_node& node): _node(node) + { + } + + xpath_node::xpath_node(const xml_attribute& attribute, const xml_node& parent): _node(attribute ? parent : xml_node()), _attribute(attribute) + { + } + + xml_node xpath_node::node() const + { + return _attribute ? xml_node() : _node; + } + + xml_attribute xpath_node::attribute() const + { + return _attribute; + } + + xml_node xpath_node::parent() const + { + return _attribute ? _node : _node.parent(); + } + + xpath_node::operator xpath_node::unspecified_bool_type() const + { + return (_node || _attribute) ? &xpath_node::_node : 0; + } + + bool xpath_node::operator!() const + { + return !(_node || _attribute); + } + + bool xpath_node::operator==(const xpath_node& n) const + { + return _node == n._node && _attribute == n._attribute; + } + + bool xpath_node::operator!=(const xpath_node& n) const + { + return _node != n._node || _attribute != n._attribute; + } + +#ifdef __BORLANDC__ + bool operator&&(const xpath_node& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + bool operator||(const xpath_node& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + void xpath_node_set::_assign(const_iterator begin, const_iterator end) + { + assert(begin <= end); + + size_t size = static_cast(end - begin); + + if (size <= 1) + { + // deallocate old buffer + if (_begin != &_storage) global_deallocate(_begin); + + // use internal buffer + if (begin != end) _storage = *begin; + + _begin = &_storage; + _end = &_storage + size; + } + else + { + // make heap copy + xpath_node* storage = static_cast(global_allocate(size * sizeof(xpath_node))); + + if (!storage) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return; + #else + throw std::bad_alloc(); + #endif + } + + memcpy(storage, begin, size * sizeof(xpath_node)); + + // deallocate old buffer + if (_begin != &_storage) global_deallocate(_begin); + + // finalize + _begin = storage; + _end = storage + size; + } + } + + xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(&_storage), _end(&_storage) + { + } + + xpath_node_set::xpath_node_set(const_iterator begin, const_iterator end, type_t type): _type(type), _begin(&_storage), _end(&_storage) + { + _assign(begin, end); + } + + xpath_node_set::~xpath_node_set() + { + if (_begin != &_storage) global_deallocate(_begin); + } + + xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(ns._type), _begin(&_storage), _end(&_storage) + { + _assign(ns._begin, ns._end); + } + + xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns) + { + if (this == &ns) return *this; + + _type = ns._type; + _assign(ns._begin, ns._end); + + return *this; + } + + xpath_node_set::type_t xpath_node_set::type() const + { + return _type; + } + + size_t xpath_node_set::size() const + { + return _end - _begin; + } + + bool xpath_node_set::empty() const + { + return _begin == _end; + } + + const xpath_node& xpath_node_set::operator[](size_t index) const + { + assert(index < size()); + return _begin[index]; + } + + xpath_node_set::const_iterator xpath_node_set::begin() const + { + return _begin; + } + + xpath_node_set::const_iterator xpath_node_set::end() const + { + return _end; + } + + void xpath_node_set::sort(bool reverse) + { + _type = xpath_sort(_begin, _end, _type, reverse); + } + + xpath_node xpath_node_set::first() const + { + return xpath_first(_begin, _end, _type); + } + + xpath_parse_result::xpath_parse_result(): error("Internal error"), offset(0) + { + } + + xpath_parse_result::operator bool() const + { + return error == 0; + } + const char* xpath_parse_result::description() const + { + return error ? error : "No error"; + } + + xpath_variable::xpath_variable() + { + } + + const char_t* xpath_variable::name() const + { + switch (_type) + { + case xpath_type_node_set: + return static_cast(this)->name; + + case xpath_type_number: + return static_cast(this)->name; + + case xpath_type_string: + return static_cast(this)->name; + + case xpath_type_boolean: + return static_cast(this)->name; + + default: + assert(!"Invalid variable type"); + return 0; + } + } + + xpath_value_type xpath_variable::type() const + { + return _type; + } + + bool xpath_variable::get_boolean() const + { + return (_type == xpath_type_boolean) ? static_cast(this)->value : false; + } + + double xpath_variable::get_number() const + { + return (_type == xpath_type_number) ? static_cast(this)->value : gen_nan(); + } + + const char_t* xpath_variable::get_string() const + { + const char_t* value = (_type == xpath_type_string) ? static_cast(this)->value : 0; + return value ? value : PUGIXML_TEXT(""); + } + + const xpath_node_set& xpath_variable::get_node_set() const + { + return (_type == xpath_type_node_set) ? static_cast(this)->value : dummy_node_set; + } + + bool xpath_variable::set(bool value) + { + if (_type != xpath_type_boolean) return false; + + static_cast(this)->value = value; + return true; + } + + bool xpath_variable::set(double value) + { + if (_type != xpath_type_number) return false; + + static_cast(this)->value = value; + return true; + } + + bool xpath_variable::set(const char_t* value) + { + if (_type != xpath_type_string) return false; + + xpath_variable_string* var = static_cast(this); + + // duplicate string + size_t size = (strlength(value) + 1) * sizeof(char_t); + + char_t* copy = static_cast(global_allocate(size)); + if (!copy) return false; + + memcpy(copy, value, size); + + // replace old string + if (var->value) global_deallocate(var->value); + var->value = copy; + + return true; + } + + bool xpath_variable::set(const xpath_node_set& value) + { + if (_type != xpath_type_node_set) return false; + + static_cast(this)->value = value; + return true; + } + + xpath_variable_set::xpath_variable_set() + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) _data[i] = 0; + } + + xpath_variable_set::~xpath_variable_set() + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + { + xpath_variable* var = _data[i]; + + while (var) + { + xpath_variable* next = var->_next; + + delete_xpath_variable(var->_type, var); + + var = next; + } + } + } + + xpath_variable* xpath_variable_set::find(const char_t* name) const + { + const size_t hash_size = sizeof(_data) / sizeof(_data[0]); + size_t hash = hash_string(name) % hash_size; + + // look for existing variable + for (xpath_variable* var = _data[hash]; var; var = var->_next) + if (strequal(var->name(), name)) + return var; + + return 0; + } + + xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type) + { + const size_t hash_size = sizeof(_data) / sizeof(_data[0]); + size_t hash = hash_string(name) % hash_size; + + // look for existing variable + for (xpath_variable* var = _data[hash]; var; var = var->_next) + if (strequal(var->name(), name)) + return var->type() == type ? var : 0; + + // add new variable + xpath_variable* result = new_xpath_variable(type, name); + + if (result) + { + result->_type = type; + result->_next = _data[hash]; + + _data[hash] = result; + } + + return result; + } + + bool xpath_variable_set::set(const char_t* name, bool value) + { + xpath_variable* var = add(name, xpath_type_boolean); + return var ? var->set(value) : false; + } + + bool xpath_variable_set::set(const char_t* name, double value) + { + xpath_variable* var = add(name, xpath_type_number); + return var ? var->set(value) : false; + } + + bool xpath_variable_set::set(const char_t* name, const char_t* value) + { + xpath_variable* var = add(name, xpath_type_string); + return var ? var->set(value) : false; + } + + bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value) + { + xpath_variable* var = add(name, xpath_type_node_set); + return var ? var->set(value) : false; + } + + xpath_variable* xpath_variable_set::get(const char_t* name) + { + return find(name); + } + + const xpath_variable* xpath_variable_set::get(const char_t* name) const + { + return find(name); + } + + xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) + { + xpath_query_impl* impl = xpath_query_impl::create(); + + if (!impl) + { + #ifdef PUGIXML_NO_EXCEPTIONS + _result.error = "Out of memory"; + #else + throw std::bad_alloc(); + #endif + } + else + { + buffer_holder impl_holder(impl, xpath_query_impl::destroy); + + impl->root = xpath_parser::parse(query, variables, &impl->alloc, &_result); + + if (impl->root) + { + _impl = static_cast(impl_holder.release()); + _result.error = 0; + } + } + } + + xpath_query::~xpath_query() + { + xpath_query_impl::destroy(_impl); + } + + xpath_value_type xpath_query::return_type() const + { + if (!_impl) return xpath_type_none; + + return static_cast(_impl)->root->rettype(); + } + + bool xpath_query::evaluate_boolean(const xpath_node& n) const + { + if (!_impl) return false; + + xpath_context c(n, 1, 1); + xpath_stack_data sd; + + #ifdef PUGIXML_NO_EXCEPTIONS + if (setjmp(sd.error_handler)) return false; + #endif + + return static_cast(_impl)->root->eval_boolean(c, sd.stack); + } + + double xpath_query::evaluate_number(const xpath_node& n) const + { + if (!_impl) return gen_nan(); + + xpath_context c(n, 1, 1); + xpath_stack_data sd; + + #ifdef PUGIXML_NO_EXCEPTIONS + if (setjmp(sd.error_handler)) return gen_nan(); + #endif + + return static_cast(_impl)->root->eval_number(c, sd.stack); + } + +#ifndef PUGIXML_NO_STL + string_t xpath_query::evaluate_string(const xpath_node& n) const + { + xpath_stack_data sd; + + return evaluate_string_impl(static_cast(_impl), n, sd).c_str(); + } +#endif + + size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const + { + xpath_stack_data sd; + + xpath_string r = evaluate_string_impl(static_cast(_impl), n, sd); + + size_t full_size = r.length() + 1; + + if (capacity > 0) + { + size_t size = (full_size < capacity) ? full_size : capacity; + assert(size > 0); + + memcpy(buffer, r.c_str(), (size - 1) * sizeof(char_t)); + buffer[size - 1] = 0; + } + + return full_size; + } + + xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const + { + if (!_impl) return xpath_node_set(); + + xpath_ast_node* root = static_cast(_impl)->root; + + if (root->rettype() != xpath_type_node_set) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return xpath_node_set(); + #else + xpath_parse_result result; + result.error = "Expression does not evaluate to node set"; + + throw xpath_exception(result); + #endif + } + + xpath_context c(n, 1, 1); + xpath_stack_data sd; + + #ifdef PUGIXML_NO_EXCEPTIONS + if (setjmp(sd.error_handler)) return xpath_node_set(); + #endif + + xpath_node_set_raw r = root->eval_node_set(c, sd.stack); + + return xpath_node_set(r.begin(), r.end(), r.type()); + } + + const xpath_parse_result& xpath_query::result() const + { + return _result; + } + + xpath_query::operator xpath_query::unspecified_bool_type() const + { + return _impl ? &xpath_query::_impl : 0; + } + + bool xpath_query::operator!() const + { + return !_impl; + } + + xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const + { + xpath_query q(query, variables); + return select_single_node(q); + } + + xpath_node xml_node::select_single_node(const xpath_query& query) const + { + xpath_node_set s = query.evaluate_node_set(*this); + return s.empty() ? xpath_node() : s.first(); + } + + xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables) const + { + xpath_query q(query, variables); + return select_nodes(q); + } + + xpath_node_set xml_node::select_nodes(const xpath_query& query) const + { + return query.evaluate_node_set(*this); + } +} + +#endif + +/** + * Copyright (c) 2006-2010 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/libretroshare/src/util/pugixml.h b/libretroshare/src/util/pugixml.h new file mode 100644 index 000000000..faa6aef67 --- /dev/null +++ b/libretroshare/src/util/pugixml.h @@ -0,0 +1,1131 @@ +/** + * pugixml parser - version 1.0 + * -------------------------------------------------------- + * Copyright (C) 2006-2010, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at http://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#ifndef HEADER_PUGIXML_HPP +#define HEADER_PUGIXML_HPP + +#include "pugiconfig.h" + +#ifndef PUGIXML_NO_STL +namespace std +{ + struct bidirectional_iterator_tag; + +#ifdef __SUNPRO_CC + // Sun C++ compiler has a bug which forces template argument names in forward declarations to be the same as in actual definitions + template class allocator; + template struct char_traits; + template class basic_istream; + template class basic_ostream; + template class basic_string; +#else + // Borland C++ compiler has a bug which forces template argument names in forward declarations to be the same as in actual definitions + template class allocator; + template struct char_traits; + template class basic_istream; + template class basic_ostream; + template class basic_string; +#endif + + // Digital Mars compiler has a bug which requires a forward declaration for explicit instantiation (otherwise type selection is messed up later, producing link errors) + // Also note that we have to declare char_traits as a class here, since it's defined that way +#ifdef __DMC__ + template <> class char_traits; +#endif +} +#endif + +// Macro for deprecated features +#ifndef PUGIXML_DEPRECATED +# if defined(__GNUC__) +# define PUGIXML_DEPRECATED __attribute__((deprecated)) +# elif defined(_MSC_VER) && _MSC_VER >= 1300 +# define PUGIXML_DEPRECATED __declspec(deprecated) +# else +# define PUGIXML_DEPRECATED +# endif +#endif + +// Include exception header for XPath +#if !defined(PUGIXML_NO_XPATH) && !defined(PUGIXML_NO_EXCEPTIONS) +# include +#endif + +// If no API is defined, assume default +#ifndef PUGIXML_API +# define PUGIXML_API +#endif + +// If no API for classes is defined, assume default +#ifndef PUGIXML_CLASS +# define PUGIXML_CLASS PUGIXML_API +#endif + +// If no API for functions is defined, assume default +#ifndef PUGIXML_FUNCTION +# define PUGIXML_FUNCTION PUGIXML_API +#endif + +#include + +// Character interface macros +#ifdef PUGIXML_WCHAR_MODE +# define PUGIXML_TEXT(t) L ## t +# define PUGIXML_CHAR wchar_t +#else +# define PUGIXML_TEXT(t) t +# define PUGIXML_CHAR char +#endif + +namespace pugi +{ + // Character type used for all internal storage and operations; depends on PUGIXML_WCHAR_MODE + typedef PUGIXML_CHAR char_t; + +#ifndef PUGIXML_NO_STL + // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE + typedef std::basic_string, std::allocator > string_t; +#endif +} + +// The PugiXML namespace +namespace pugi +{ + // Tree node types + enum xml_node_type + { + node_null, // Empty (null) node handle + node_document, // A document tree's absolute root + node_element, // Element tag, i.e. '' + node_pcdata, // Plain character data, i.e. 'text' + node_cdata, // Character data, i.e. '' + node_comment, // Comment tag, i.e. '' + node_pi, // Processing instruction, i.e. '' + node_declaration, // Document declaration, i.e. '' + node_doctype // Document type declaration, i.e. '' + }; + + // Parsing options + + // Minimal parsing mode (equivalent to turning all other flags off). + // Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed. + const unsigned int parse_minimal = 0x0000; + + // This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default. + const unsigned int parse_pi = 0x0001; + + // This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default. + const unsigned int parse_comments = 0x0002; + + // This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default. + const unsigned int parse_cdata = 0x0004; + + // This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree. + // This flag is off by default; turning it on usually results in slower parsing and more memory consumption. + const unsigned int parse_ws_pcdata = 0x0008; + + // This flag determines if character and entity references are expanded during parsing. This flag is on by default. + const unsigned int parse_escapes = 0x0010; + + // This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default. + const unsigned int parse_eol = 0x0020; + + // This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default. + const unsigned int parse_wconv_attribute = 0x0040; + + // This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default. + const unsigned int parse_wnorm_attribute = 0x0080; + + // This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default. + const unsigned int parse_declaration = 0x0100; + + // This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default. + const unsigned int parse_doctype = 0x0200; + + // The default parsing mode. + // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, + // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. + const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol; + + // The full parsing mode. + // Nodes of all types are added to the DOM tree, character/reference entities are expanded, + // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. + const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype; + + // These flags determine the encoding of input data for XML document + enum xml_encoding + { + encoding_auto, // Auto-detect input encoding using BOM or < / >& stream); + xml_writer_stream(std::basic_ostream >& stream); + + virtual void write(const void* data, size_t size); + + private: + std::basic_ostream >* narrow_stream; + std::basic_ostream >* wide_stream; + }; + #endif + + // A light-weight handle for manipulating attributes in DOM tree + class PUGIXML_CLASS xml_attribute + { + friend class xml_attribute_iterator; + friend class xml_node; + + private: + xml_attribute_struct* _attr; + + typedef xml_attribute_struct* xml_attribute::*unspecified_bool_type; + + public: + // Default constructor. Constructs an empty attribute. + xml_attribute(); + + // Constructs attribute from internal pointer + explicit xml_attribute(xml_attribute_struct* attr); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators (compares wrapped attribute pointers) + bool operator==(const xml_attribute& r) const; + bool operator!=(const xml_attribute& r) const; + bool operator<(const xml_attribute& r) const; + bool operator>(const xml_attribute& r) const; + bool operator<=(const xml_attribute& r) const; + bool operator>=(const xml_attribute& r) const; + + // Check if attribute is empty + bool empty() const; + + // Get attribute name/value, or "" if attribute is empty + const char_t* name() const; + const char_t* value() const; + + // Get attribute value as a number, or 0 if conversion did not succeed or attribute is empty + int as_int() const; + unsigned int as_uint() const; + double as_double() const; + float as_float() const; + + // Get attribute value as bool (returns true if first character is in '1tTyY' set), or false if attribute is empty + bool as_bool() const; + + // Set attribute name/value (returns false if attribute is empty or there is not enough memory) + bool set_name(const char_t* rhs); + bool set_value(const char_t* rhs); + + // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") + bool set_value(int rhs); + bool set_value(unsigned int rhs); + bool set_value(double rhs); + bool set_value(bool rhs); + + // Set attribute value (equivalent to set_value without error checking) + xml_attribute& operator=(const char_t* rhs); + xml_attribute& operator=(int rhs); + xml_attribute& operator=(unsigned int rhs); + xml_attribute& operator=(double rhs); + xml_attribute& operator=(bool rhs); + + // Get next/previous attribute in the attribute list of the parent node + xml_attribute next_attribute() const; + xml_attribute previous_attribute() const; + + // Get hash value (unique for handles to the same object) + size_t hash_value() const; + + // Get internal pointer + xml_attribute_struct* internal_object() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_attribute& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_attribute& lhs, bool rhs); +#endif + + // A light-weight handle for manipulating nodes in DOM tree + class PUGIXML_CLASS xml_node + { + friend class xml_attribute_iterator; + friend class xml_node_iterator; + + protected: + xml_node_struct* _root; + + typedef xml_node_struct* xml_node::*unspecified_bool_type; + + public: + // Default constructor. Constructs an empty node. + xml_node(); + + // Constructs node from internal pointer + explicit xml_node(xml_node_struct* p); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators (compares wrapped node pointers) + bool operator==(const xml_node& r) const; + bool operator!=(const xml_node& r) const; + bool operator<(const xml_node& r) const; + bool operator>(const xml_node& r) const; + bool operator<=(const xml_node& r) const; + bool operator>=(const xml_node& r) const; + + // Check if node is empty. + bool empty() const; + + // Get node type + xml_node_type type() const; + + // Get node name/value, or "" if node is empty or it has no name/value + const char_t* name() const; + const char_t* value() const; + + // Get attribute list + xml_attribute first_attribute() const; + xml_attribute last_attribute() const; + + // Get children list + xml_node first_child() const; + xml_node last_child() const; + + // Get next/previous sibling in the children list of the parent node + xml_node next_sibling() const; + xml_node previous_sibling() const; + + // Get parent node + xml_node parent() const; + + // Get root of DOM tree this node belongs to + xml_node root() const; + + // Get child, attribute or next/previous sibling with the specified name + xml_node child(const char_t* name) const; + xml_attribute attribute(const char_t* name) const; + xml_node next_sibling(const char_t* name) const; + xml_node previous_sibling(const char_t* name) const; + + // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA + const char_t* child_value() const; + + // Get child value of child with specified name. Equivalent to child(name).child_value(). + const char_t* child_value(const char_t* name) const; + + // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) + bool set_name(const char_t* rhs); + bool set_value(const char_t* rhs); + + // Add attribute with specified name. Returns added attribute, or empty attribute on errors. + xml_attribute append_attribute(const char_t* name); + xml_attribute prepend_attribute(const char_t* name); + xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr); + xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr); + + // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors. + xml_attribute append_copy(const xml_attribute& proto); + xml_attribute prepend_copy(const xml_attribute& proto); + xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr); + xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr); + + // Add child node with specified type. Returns added node, or empty node on errors. + xml_node append_child(xml_node_type type = node_element); + xml_node prepend_child(xml_node_type type = node_element); + xml_node insert_child_after(xml_node_type type, const xml_node& node); + xml_node insert_child_before(xml_node_type type, const xml_node& node); + + // Add child element with specified name. Returns added node, or empty node on errors. + xml_node append_child(const char_t* name); + xml_node prepend_child(const char_t* name); + xml_node insert_child_after(const char_t* name, const xml_node& node); + xml_node insert_child_before(const char_t* name, const xml_node& node); + + // Add a copy of the specified node as a child. Returns added node, or empty node on errors. + xml_node append_copy(const xml_node& proto); + xml_node prepend_copy(const xml_node& proto); + xml_node insert_copy_after(const xml_node& proto, const xml_node& node); + xml_node insert_copy_before(const xml_node& proto, const xml_node& node); + + // Remove specified attribute + bool remove_attribute(const xml_attribute& a); + bool remove_attribute(const char_t* name); + + // Remove specified child + bool remove_child(const xml_node& n); + bool remove_child(const char_t* name); + + // Find attribute using predicate. Returns first attribute for which predicate returned true. + template xml_attribute find_attribute(Predicate pred) const + { + if (!_root) return xml_attribute(); + + for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute()) + if (pred(attrib)) + return attrib; + + return xml_attribute(); + } + + // Find child node using predicate. Returns first child for which predicate returned true. + template xml_node find_child(Predicate pred) const + { + if (!_root) return xml_node(); + + for (xml_node node = first_child(); node; node = node.next_sibling()) + if (pred(node)) + return node; + + return xml_node(); + } + + // Find node from subtree using predicate. Returns first node from subtree (depth-first), for which predicate returned true. + template xml_node find_node(Predicate pred) const + { + if (!_root) return xml_node(); + + xml_node cur = first_child(); + + while (cur._root && cur._root != _root) + { + if (pred(cur)) return cur; + + if (cur.first_child()) cur = cur.first_child(); + else if (cur.next_sibling()) cur = cur.next_sibling(); + else + { + while (!cur.next_sibling() && cur._root != _root) cur = cur.parent(); + + if (cur._root != _root) cur = cur.next_sibling(); + } + } + + return xml_node(); + } + + // Find child node by attribute name/value + xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const; + xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const; + + #ifndef PUGIXML_NO_STL + // Get the absolute node path from root as a text string. + string_t path(char_t delimiter = '/') const; + #endif + + // Search for a node by path consisting of node names and . or .. elements. + xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const; + + // Recursively traverse subtree with xml_tree_walker + bool traverse(xml_tree_walker& walker); + + #ifndef PUGIXML_NO_XPATH + // Select single node by evaluating XPath query. Returns first node from the resulting node set. + xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = 0) const; + xpath_node select_single_node(const xpath_query& query) const; + + // Select node set by evaluating XPath query + xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const; + xpath_node_set select_nodes(const xpath_query& query) const; + #endif + + // Print subtree using a writer object + void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; + + #ifndef PUGIXML_NO_STL + // Print subtree to stream + void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; + void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; + #endif + + // Child nodes iterators + typedef xml_node_iterator iterator; + + iterator begin() const; + iterator end() const; + + // Attribute iterators + typedef xml_attribute_iterator attribute_iterator; + + attribute_iterator attributes_begin() const; + attribute_iterator attributes_end() const; + + // Get node offset in parsed file/string (in char_t units) for debugging purposes + ptrdiff_t offset_debug() const; + + // Get hash value (unique for handles to the same object) + size_t hash_value() const; + + // Get internal pointer + xml_node_struct* internal_object() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_node& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_node& lhs, bool rhs); +#endif + + // Child node iterator (a bidirectional iterator over a collection of xml_node) + class PUGIXML_CLASS xml_node_iterator + { + friend class xml_node; + + private: + xml_node _wrap; + xml_node _parent; + + xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent); + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_node value_type; + typedef xml_node* pointer; + typedef xml_node& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_node_iterator(); + + // Construct an iterator which points to the specified node + xml_node_iterator(const xml_node& node); + + // Iterator operators + bool operator==(const xml_node_iterator& rhs) const; + bool operator!=(const xml_node_iterator& rhs) const; + + xml_node& operator*(); + xml_node* operator->(); + + const xml_node_iterator& operator++(); + xml_node_iterator operator++(int); + + const xml_node_iterator& operator--(); + xml_node_iterator operator--(int); + }; + + // Attribute iterator (a bidirectional iterator over a collection of xml_attribute) + class PUGIXML_CLASS xml_attribute_iterator + { + friend class xml_node; + + private: + xml_attribute _wrap; + xml_node _parent; + + xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent); + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_attribute value_type; + typedef xml_attribute* pointer; + typedef xml_attribute& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_attribute_iterator(); + + // Construct an iterator which points to the specified attribute + xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent); + + // Iterator operators + bool operator==(const xml_attribute_iterator& rhs) const; + bool operator!=(const xml_attribute_iterator& rhs) const; + + xml_attribute& operator*(); + xml_attribute* operator->(); + + const xml_attribute_iterator& operator++(); + xml_attribute_iterator operator++(int); + + const xml_attribute_iterator& operator--(); + xml_attribute_iterator operator--(int); + }; + + // Abstract tree walker class (see xml_node::traverse) + class PUGIXML_CLASS xml_tree_walker + { + friend class xml_node; + + private: + int _depth; + + protected: + // Get current traversal depth + int depth() const; + + public: + xml_tree_walker(); + virtual ~xml_tree_walker(); + + // Callback that is called when traversal begins + virtual bool begin(xml_node& node); + + // Callback that is called for each node traversed + virtual bool for_each(xml_node& node) = 0; + + // Callback that is called when traversal ends + virtual bool end(xml_node& node); + }; + + // Parsing status, returned as part of xml_parse_result object + enum xml_parse_status + { + status_ok = 0, // No error + + status_file_not_found, // File was not found during load_file() + status_io_error, // Error reading from file/stream + status_out_of_memory, // Could not allocate memory + status_internal_error, // Internal error occurred + + status_unrecognized_tag, // Parser could not determine tag type + + status_bad_pi, // Parsing error occurred while parsing document declaration/processing instruction + status_bad_comment, // Parsing error occurred while parsing comment + status_bad_cdata, // Parsing error occurred while parsing CDATA section + status_bad_doctype, // Parsing error occurred while parsing document type declaration + status_bad_pcdata, // Parsing error occurred while parsing PCDATA section + status_bad_start_element, // Parsing error occurred while parsing start element tag + status_bad_attribute, // Parsing error occurred while parsing element attribute + status_bad_end_element, // Parsing error occurred while parsing end element tag + status_end_element_mismatch // There was a mismatch of start-end tags (closing tag had incorrect name, some tag was not closed or there was an excessive closing tag) + }; + + // Parsing result + struct PUGIXML_CLASS xml_parse_result + { + // Parsing status (see xml_parse_status) + xml_parse_status status; + + // Last parsed offset (in char_t units from start of input data) + ptrdiff_t offset; + + // Source document encoding + xml_encoding encoding; + + // Default constructor, initializes object to failed state + xml_parse_result(); + + // Cast to bool operator + operator bool() const; + + // Get error description + const char* description() const; + }; + + // Document class (DOM tree root) + class PUGIXML_CLASS xml_document: public xml_node + { + private: + char_t* _buffer; + + char _memory[192]; + + // Non-copyable semantics + xml_document(const xml_document&); + const xml_document& operator=(const xml_document&); + + void create(); + void destroy(); + + xml_parse_result load_buffer_impl(void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own); + + public: + // Default constructor, makes empty document + xml_document(); + + // Destructor, invalidates all node/attribute handles to this document + ~xml_document(); + + // Removes all nodes, leaving the empty document + void reset(); + + // Removes all nodes, then copies the entire contents of the specified document + void reset(const xml_document& proto); + + #ifndef PUGIXML_NO_STL + // Load document from stream. + xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); + #endif + + // Load document from zero-terminated string. No encoding conversions are applied. + xml_parse_result load(const char_t* contents, unsigned int options = parse_default); + + // Load document from file + xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer. Copies/converts the buffer, so it may be deleted or changed after the function returns. + xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). + // You should ensure that buffer data will persist throughout the document's lifetime, and free the buffer memory manually once document is destroyed. + xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). + // You should allocate the buffer with pugixml allocation function; document will free the buffer when it is no longer needed (you can't use it anymore). + xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Save XML document to writer (semantics is slightly different from xml_node::print, see documentation for details). + void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + + #ifndef PUGIXML_NO_STL + // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details). + void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; + #endif + + // Save XML to file + bool save_file(const char* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + bool save_file(const wchar_t* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + + // Get document element + xml_node document_element() const; + }; + +#ifndef PUGIXML_NO_XPATH + // XPath query return type + enum xpath_value_type + { + xpath_type_none, // Unknown type (query failed to compile) + xpath_type_node_set, // Node set (xpath_node_set) + xpath_type_number, // Number + xpath_type_string, // String + xpath_type_boolean // Boolean + }; + + // XPath parsing result + struct PUGIXML_CLASS xpath_parse_result + { + // Error message (0 if no error) + const char* error; + + // Last parsed offset (in char_t units from string start) + ptrdiff_t offset; + + // Default constructor, initializes object to failed state + xpath_parse_result(); + + // Cast to bool operator + operator bool() const; + + // Get error description + const char* description() const; + }; + + // A single XPath variable + class PUGIXML_CLASS xpath_variable + { + friend class xpath_variable_set; + + protected: + xpath_value_type _type; + xpath_variable* _next; + + xpath_variable(); + + // Non-copyable semantics + xpath_variable(const xpath_variable&); + xpath_variable& operator=(const xpath_variable&); + + public: + // Get variable name + const char_t* name() const; + + // Get variable type + xpath_value_type type() const; + + // Get variable value; no type conversion is performed, default value (false, NaN, empty string, empty node set) is returned on type mismatch error + bool get_boolean() const; + double get_number() const; + const char_t* get_string() const; + const xpath_node_set& get_node_set() const; + + // Set variable value; no type conversion is performed, false is returned on type mismatch error + bool set(bool value); + bool set(double value); + bool set(const char_t* value); + bool set(const xpath_node_set& value); + }; + + // A set of XPath variables + class PUGIXML_CLASS xpath_variable_set + { + private: + xpath_variable* _data[64]; + + // Non-copyable semantics + xpath_variable_set(const xpath_variable_set&); + xpath_variable_set& operator=(const xpath_variable_set&); + + xpath_variable* find(const char_t* name) const; + + public: + // Default constructor/destructor + xpath_variable_set(); + ~xpath_variable_set(); + + // Add a new variable or get the existing one, if the types match + xpath_variable* add(const char_t* name, xpath_value_type type); + + // Set value of an existing variable; no type conversion is performed, false is returned if there is no such variable or if types mismatch + bool set(const char_t* name, bool value); + bool set(const char_t* name, double value); + bool set(const char_t* name, const char_t* value); + bool set(const char_t* name, const xpath_node_set& value); + + // Get existing variable by name + xpath_variable* get(const char_t* name); + const xpath_variable* get(const char_t* name) const; + }; + + // A compiled XPath query object + class PUGIXML_CLASS xpath_query + { + private: + void* _impl; + xpath_parse_result _result; + + typedef void* xpath_query::*unspecified_bool_type; + + // Non-copyable semantics + xpath_query(const xpath_query&); + xpath_query& operator=(const xpath_query&); + + public: + // Construct a compiled object from XPath expression. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. + explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0); + + // Destructor + ~xpath_query(); + + // Get query expression return type + xpath_value_type return_type() const; + + // Evaluate expression as boolean value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + bool evaluate_boolean(const xpath_node& n) const; + + // Evaluate expression as double value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + double evaluate_number(const xpath_node& n) const; + + #ifndef PUGIXML_NO_STL + // Evaluate expression as string value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + string_t evaluate_string(const xpath_node& n) const; + #endif + + // Evaluate expression as string value in the specified context; performs type conversion if necessary. + // At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero). + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty set instead. + size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const; + + // Evaluate expression as node set in the specified context. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node set instead. + xpath_node_set evaluate_node_set(const xpath_node& n) const; + + // Get parsing result (used to get compilation errors in PUGIXML_NO_EXCEPTIONS mode) + const xpath_parse_result& result() const; + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + }; + + #ifndef PUGIXML_NO_EXCEPTIONS + // XPath exception class + class PUGIXML_CLASS xpath_exception: public std::exception + { + private: + xpath_parse_result _result; + + public: + // Construct exception from parse result + explicit xpath_exception(const xpath_parse_result& result); + + // Get error message + virtual const char* what() const throw(); + + // Get parse result + const xpath_parse_result& result() const; + }; + #endif + + // XPath node class (either xml_node or xml_attribute) + class PUGIXML_CLASS xpath_node + { + private: + xml_node _node; + xml_attribute _attribute; + + typedef xml_node xpath_node::*unspecified_bool_type; + + public: + // Default constructor; constructs empty XPath node + xpath_node(); + + // Construct XPath node from XML node/attribute + xpath_node(const xml_node& node); + xpath_node(const xml_attribute& attribute, const xml_node& parent); + + // Get node/attribute, if any + xml_node node() const; + xml_attribute attribute() const; + + // Get parent of contained node/attribute + xml_node parent() const; + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators + bool operator==(const xpath_node& n) const; + bool operator!=(const xpath_node& n) const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xpath_node& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xpath_node& lhs, bool rhs); +#endif + + // A fixed-size collection of XPath nodes + class PUGIXML_CLASS xpath_node_set + { + public: + // Collection type + enum type_t + { + type_unsorted, // Not ordered + type_sorted, // Sorted by document order (ascending) + type_sorted_reverse // Sorted by document order (descending) + }; + + // Constant iterator type + typedef const xpath_node* const_iterator; + + // Default constructor. Constructs empty set. + xpath_node_set(); + + // Constructs a set from iterator range; data is not checked for duplicates and is not sorted according to provided type, so be careful + xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted); + + // Destructor + ~xpath_node_set(); + + // Copy constructor/assignment operator + xpath_node_set(const xpath_node_set& ns); + xpath_node_set& operator=(const xpath_node_set& ns); + + // Get collection type + type_t type() const; + + // Get collection size + size_t size() const; + + // Indexing operator + const xpath_node& operator[](size_t index) const; + + // Collection iterators + const_iterator begin() const; + const_iterator end() const; + + // Sort the collection in ascending/descending order by document order + void sort(bool reverse = false); + + // Get first node in the collection by document order + xpath_node first() const; + + // Check if collection is empty + bool empty() const; + + private: + type_t _type; + + xpath_node _storage; + + xpath_node* _begin; + xpath_node* _end; + + void _assign(const_iterator begin, const_iterator end); + }; +#endif + +#ifndef PUGIXML_NO_STL + // Convert wide string to UTF8 + std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const wchar_t* str); + std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const std::basic_string, std::allocator >& str); + + // Convert UTF8 to wide string + std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const char* str); + std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const std::basic_string, std::allocator >& str); +#endif + + // Memory allocation function interface; returns pointer to allocated memory or NULL on failure + typedef void* (*allocation_function)(size_t size); + + // Memory deallocation function interface + typedef void (*deallocation_function)(void* ptr); + + // Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions. + void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate); + + // Get current memory management functions + allocation_function PUGIXML_FUNCTION get_memory_allocation_function(); + deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function(); +} + +#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) +namespace std +{ + // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_attribute_iterator&); +} +#endif + +#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) +namespace std +{ + // Workarounds for (non-standard) iterator category detection + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_attribute_iterator&); +} +#endif + +#endif + +/** + * Copyright (c) 2006-2010 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/libretroshare/src/util/rsdebug.cc b/libretroshare/src/util/rsdebug.cc new file mode 100644 index 000000000..29ea59a1e --- /dev/null +++ b/libretroshare/src/util/rsdebug.cc @@ -0,0 +1,237 @@ +/* + * "$Id: pqidebug.cc,v 1.6 2007-02-18 21:46:49 rmf24 Exp $" + * + * 3P/RS network interface for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "util/rsdebug.h" +#include "util/rsthreads.h" +#include "util/rsdir.h" + +#include +#include + +const int RS_DEBUG_STDERR = 1; /* stuff goes to stderr */ +const int RS_DEBUG_LOGFILE = 2; /* stuff goes to logfile */ +const int RS_DEBUG_LOGCRASH = 3; /* minimal logfile stored after crashes */ +const int RS_DEBUG_LOGC_MAX = 100000; /* max length of crashfile log */ +const int RS_DEBUG_LOGC_MIN_SAVE = 100; /* min length of crashfile log */ + +static std::map zoneLevel; +static int defaultLevel = RSL_WARNING; +static FILE *ofd = stderr; + +static int debugMode = RS_DEBUG_STDERR; +static int lineCount = 0; +static std::string crashfile; +static int debugTS = 0; + +static RsMutex logMtx; + +int locked_setDebugFile(const char *fname); +int locked_getZoneLevel(int zone); + +int setDebugCrashMode(const char *cfile) +{ + RsStackMutex stack(logMtx); /******** LOCKED ****************/ + crashfile = cfile; + /* if the file exists - then we crashed, save it */ + FILE *tmpin = RsDirUtil::rs_fopen(crashfile.c_str(), "r"); + if (tmpin) + { + /* see how long it is */ + fseek(tmpin, 0, SEEK_END); + if (ftell(tmpin) > RS_DEBUG_LOGC_MIN_SAVE) + { + std::string crashfile_save = crashfile + "-save"; + fprintf(stderr, "Detected Old Crash File: %s\n", crashfile.c_str()); + fprintf(stderr, "Copying to: %s\n", crashfile_save.c_str()); + + /* go back to the start */ + fseek(tmpin, 0, SEEK_SET); + + FILE *tmpout = RsDirUtil::rs_fopen(crashfile_save.c_str(), "w"); + int da_size = 10240; + char dataarray[da_size]; /* 10k */ + unsigned int da_read = 0; + + if (!tmpout) + { + fprintf(stderr, "Failed to open CrashSave\n"); + fclose(tmpin); + return -1; + } + while(0 != (da_read = fread(dataarray, 1, da_size, tmpin))) + { + if (da_read != fwrite(dataarray, 1, da_read, tmpout)) + { + fprintf(stderr, "Failed writing to CrashSave\n"); + fclose(tmpout); + fclose(tmpin); + return -1; + } + } + fclose(tmpout); + fclose(tmpin); + } + else + { + fprintf(stderr, "Negligable Old CrashLog, ignoring\n"); + fclose(tmpin); + } + } + + if (0 < locked_setDebugFile(crashfile.c_str())) + { + fprintf(stderr, "Switching To CrashLog Mode!\n"); + debugMode = RS_DEBUG_LOGCRASH; + lineCount = 0; + debugTS = time(NULL); + } + return 1; +} + + +/* this is called when we exit normally */ +int clearDebugCrashLog() +{ + RsStackMutex stack(logMtx); /******** LOCKED ****************/ + /* check we are in crashLog Mode */ + if (debugMode != RS_DEBUG_LOGCRASH) + { + fprintf(stderr, "Not in CrashLog Mode - nothing to clear!\n"); + return 1; + } + + fprintf(stderr, "clearDebugCrashLog() Cleaning up\n"); + /* shutdown crashLog Mode */ + fclose(ofd); + ofd = stderr; + debugMode = RS_DEBUG_STDERR; + + /* just open the file, and then close */ + FILE *tmpin = RsDirUtil::rs_fopen(crashfile.c_str(), "w"); + fclose(tmpin); + + return 1; +} + + + +int setDebugFile(const char *fname) +{ + RsStackMutex stack(logMtx); /******** LOCKED ****************/ + return locked_setDebugFile(fname); +} + +int locked_setDebugFile(const char *fname) +{ + if (NULL != (ofd = RsDirUtil::rs_fopen(fname, "w"))) + { + fprintf(stderr, "Logging redirected to %s\n", fname); + debugMode = RS_DEBUG_LOGFILE; + return 1; + } + else + { + ofd = stderr; + debugMode = RS_DEBUG_STDERR; + fprintf(stderr, "Logging redirect to %s FAILED\n", fname); + return -1; + } +} + + +int setOutputLevel(int lvl) +{ + RsStackMutex stack(logMtx); /******** LOCKED ****************/ + return defaultLevel = lvl; +} + +int setZoneLevel(int lvl, int zone) +{ + RsStackMutex stack(logMtx); /******** LOCKED ****************/ + zoneLevel[zone] = lvl; + return zone; +} + + +int getZoneLevel(int zone) +{ + RsStackMutex stack(logMtx); /******** LOCKED ****************/ + return locked_getZoneLevel(zone); +} + +int locked_getZoneLevel(int zone) +{ + std::map::iterator it = zoneLevel.find(zone); + if (it == zoneLevel.end()) + { + return defaultLevel; + } + return it -> second; +} + +int rslog(unsigned int lvl, int zone, std::string msg) +{ + RsStackMutex stack(logMtx); /******** LOCKED ****************/ + if ((signed) lvl <= locked_getZoneLevel(zone)) + { + time_t t = time(NULL); + + if (debugMode == RS_DEBUG_LOGCRASH) + { + if (lineCount > RS_DEBUG_LOGC_MAX) + { + /* restarting logging */ + fprintf(stderr, "Rolling over the CrashLog\n"); + fclose(ofd); + ofd = NULL; + if (0 < locked_setDebugFile(crashfile.c_str())) + { + fprintf(ofd, "Debug CrashLog:"); + fprintf(ofd, " retroShare uptime %ld secs\n", + t-debugTS); + + debugMode = RS_DEBUG_LOGCRASH; + lineCount = 0; + } + else + { + fprintf(stderr, "Rollover Failed!\n"); + } + } + } + + std::string timestr = ctime(&t); + std::string timestr2 = timestr.substr(0,timestr.length()-1); + /* remove the endl */ + fprintf(ofd, "(%s Z: %d, lvl:%d): %s \n", + timestr2.c_str(), zone, lvl, msg.c_str()); + fflush(ofd); + lineCount++; + } + return 1; +} + + + diff --git a/libretroshare/src/util/rsdebug.h b/libretroshare/src/util/rsdebug.h new file mode 100644 index 000000000..87123ee1a --- /dev/null +++ b/libretroshare/src/util/rsdebug.h @@ -0,0 +1,73 @@ +/* + * libretroshare/src/util: rsdebug.h + * + * Debug interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +/* Moved from pqi/ to util/ so it can be used more generally. + */ + +#ifndef RS_LOG_DEBUG_H +#define RS_LOG_DEBUG_H + + + +#define RSL_NONE -1 +#define RSL_ALERT 1 +#define RSL_ERROR 3 +#define RSL_WARNING 5 +#define RSL_DEBUG_ALERT 6 +#define RSL_DEBUG_BASIC 8 +#define RSL_DEBUG_ALL 10 + + +#include + +int setDebugCrashMode(const char *cfile); +int clearDebugCrashLog(); + +int setDebugFile(const char *fname); +int setOutputLevel(int lvl); +int setZoneLevel(int lvl, int zone); +int rslog(unsigned int lvl, int zone, std::string msg); + + + +/* + * retaining old #DEFINES and functions for backward compatibility. + */ + +//int pqioutput(unsigned int lvl, int zone, std::string msg); +#define pqioutput rslog + +#define PQL_NONE RSL_NONE +#define PQL_ALERT RSL_ALERT +#define PQL_ERROR RSL_ERROR +#define PQL_WARNING RSL_WARNING +#define PQL_DEBUG_ALERT RSL_DEBUG_ALERT +#define PQL_DEBUG_BASIC RSL_DEBUG_BASIC +#define PQL_DEBUG_ALL RSL_DEBUG_ALL + + + +#endif diff --git a/libretroshare/src/util/rsdir.cc b/libretroshare/src/util/rsdir.cc new file mode 100644 index 000000000..3ed4ba533 --- /dev/null +++ b/libretroshare/src/util/rsdir.cc @@ -0,0 +1,1174 @@ + +/* + * "$Id: rsdir.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +// Includes for directory creation. +#include +#include +#include + +#include "util/rsdir.h" +#include "pqi/pqinotify.h" +#include "retroshare/rstypes.h" +#include "rsthreads.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if defined(WIN32) || defined(__CYGWIN__) +#include "util/rswin.h" +#include "wtypes.h" +#include +#else +#include +#endif + +/**** + * #define RSDIR_DEBUG 1 + ****/ + +std::string RsDirUtil::getTopDir(const std::string& dir) +{ + std::string top; + + /* find the subdir: [/][dir1.../][/] + */ + int i,j; + int len = dir.length(); + for(j = len - 1; (j > 0) && (dir[j] == '/'); j--) ; + for(i = j; (i > 0) && (dir[i] != '/'); i--) ; + + if (dir[i] == '/') + i++; + + for(; i <= j; i++) + { + top += dir[i]; + } + + return top; +} + +class CRC32Table +{ + public: + inline uint32_t operator[](unsigned char i) const { return _data[i] ; } + + CRC32Table() + { + _data = new uint32_t[256] ; + uint32_t polynmial = 0x04c11db7 ; + + for(uint32_t i=0;i<256;++i) + { + uint32_t a = reflect(i,8)<<24 ; + + for(uint32_t j=0;j<8;++j) + a = (a << 1)^ ( (a&(1<<31))?polynmial:0) ; + + _data[i] = reflect(a,32) ; + } + } + // Swap bits 0-7, 1-6, etc. + // + uint32_t reflect(uint32_t ref,unsigned char ch) + { + uint32_t val = 0 ; + for(int i=1;i>=1) + if(ref & 1) + val |= (1 << (ch-i)) ; + return val ; + } + ~CRC32Table() { delete[] _data ; } + + private: + uint32_t *_data ; +}; + +static const CRC32Table crc32_table ; + +uint32_t RsDirUtil::rs_CRC32(const unsigned char *data,uint32_t _len) +{ + uint32_t a = 0xffffffff ; + int64_t len = _len ; + + for(const unsigned char *buf=data;len>0;len--) + a = (a >> 8) ^ crc32_table[ (a & 0xff) ^ *buf++] ; + + return a ^ 0xffffffff ; +} + +bool RsDirUtil::crc32File(FILE *fd, uint64_t file_size,uint32_t chunk_size, CRC32Map& crc_map) +{ + if(fseeko64(fd,0,SEEK_SET) != 0) + { + std::cerr << "crc32File(): cannot fseek to beginnign of the file !!" << std::endl ; + return false ; + } + + crc_map = CRC32Map(file_size,chunk_size) ; + + unsigned char *buff = new unsigned char[chunk_size] ; + int len ; + uint64_t total_size = 0 ; + uint32_t nb_chunk = 0; + + while((len = fread(buff,(size_t)1, (size_t)chunk_size, fd)) > 0) + { + crc_map.set(nb_chunk++,rs_CRC32(buff,len)) ; + total_size += len ; + } + delete[] buff ; + + if(file_size != total_size) + { + std::cerr << "RsDirUtil::crc32File(): ERROR. The file size does not match the announced size." << std::endl ; + return false ; + } + return true ; +} + +std::string RsDirUtil::removeTopDir(const std::string& dir) +{ + std::string rest; + + /* remove the subdir: [/][dir1.../][/] + */ + int i,j; + int len = dir.length(); + for(j = len - 1; (j > 0) && (dir[j] == '/'); j--) ; + for(i = j; (i >= 0) && (dir[i] != '/'); i--) ; + + /* remove any more slashes */ + for(; (i >= 0) && (dir[i] == '/'); i--) ; + + for(j = 0; j <= i; j++) + { + rest += dir[j]; + } + + return rest; +} + +std::string RsDirUtil::getRootDir(const std::string& dir) +{ + std::string root; + + /* find the subdir: [/]root[/...] + */ + int i,j; + int len = dir.length(); + for(i = 0; (i < len) && (dir[i] == '/'); i++) ; + for(j = i; (j < len) && (dir[j] != '/'); j++) ; + if (i == j) + return root; /* empty */ + for(; i < j; i++) + { + root += dir[i]; + } + return root; +} + +std::string RsDirUtil::removeRootDir(const std::string& path) +{ + unsigned int i, j; + unsigned int len = path.length(); + std::string output; + + /* chew leading '/'s */ + for(i = 0; (i < len) && (path[i] == '/'); i++) ; + if (i == len) + return output; /* empty string */ + + for(j = i; (j < len) && (path[j] != '/'); j++) ; /* run to next '/' */ + for(; (j < len) && (path[j] == '/'); j++) ; /* chew leading '/'s */ + + for(; j < len; j++) + { + output += path[j]; + } + + return output; +} + +std::string RsDirUtil::removeRootDirs(const std::string& path, const std::string& root) +{ + /* too tired */ + std::string notroot; + + unsigned int i = 0, j = 0; + + /* catch empty data */ + if ((root.length() < 1) || (path.length() < 1)) + return notroot; + + if ((path[0] == '/') && (root[0] != '/')) + { + i++; + } + + for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++) ; + + /* should have consumed root. */ + if (j == root.length()) + { + //std::cerr << "matched root!" << std::endl; + } + else + { + //std::cerr << "failed i: " << i << ", j: " << j << std::endl; + //std::cerr << "root: " << root << " path: " << path << std::endl; + return notroot; + } + + if (path[i] == '/') + { + i++; + } + + for(; i < path.length(); i++) + { + notroot += path[i]; + } + + //std::cerr << "Found NotRoot: " << notroot << std::endl; + + return notroot; +} + + + +int RsDirUtil::breakupDirList(const std::string& path, + std::list &subdirs) +{ + int start = 0; + unsigned int i; + for(i = 0; i < path.length(); i++) + { + if (path[i] == '/') + { + if (i - start > 0) + { + subdirs.push_back(path.substr(start, i-start)); + } + start = i+1; + } + } + // get the final one. + if (i - start > 0) + { + subdirs.push_back(path.substr(start, i-start)); + } + return 1; +} + + +/**** Copied and Tweaked from ftcontroller ***/ +bool RsDirUtil::copyFile(const std::string& source,const std::string& dest) +{ +#ifdef WINDOWS_SYS + std::wstring sourceW; + std::wstring destW; + librs::util::ConvertUtf8ToUtf16(source,sourceW); + librs::util::ConvertUtf8ToUtf16(dest,destW); + + return (CopyFileW(sourceW.c_str(), destW.c_str(), FALSE) != 0); + +#else + FILE *in = fopen64(source.c_str(),"rb") ; + + if(in == NULL) + { + return false ; + } + + FILE *out = fopen64(dest.c_str(),"wb") ; + + if(out == NULL) + { + fclose (in); + return false ; + } + + size_t s=0; + size_t T=0; + + static const int BUFF_SIZE = 10485760 ; // 10 MB buffer to speed things up. + void *buffer = malloc(BUFF_SIZE) ; + + bool bRet = true; + + while( (s = fread(buffer,1,BUFF_SIZE,in)) > 0) + { + size_t t = fwrite(buffer,1,s,out) ; + T += t ; + + if(t != s) + { + bRet = false ; + break; + } + } + + fclose(in) ; + fclose(out) ; + + free(buffer) ; + + return true ; + +#endif + +} + + +bool RsDirUtil::checkFile(const std::string& filename) +{ + int val; + mode_t st_mode; +#ifdef WINDOWS_SYS + std::wstring wfilename; + librs::util::ConvertUtf8ToUtf16(filename, wfilename); + struct _stat buf; + val = _wstat(wfilename.c_str(), &buf); + st_mode = buf.st_mode; +#else + struct stat buf; + val = stat(filename.c_str(), &buf); + st_mode = buf.st_mode; +#endif + if (val == -1) + { +#ifdef RSDIR_DEBUG + std::cerr << "RsDirUtil::checkFile() "; + std::cerr << filename << " doesn't exist" << std::endl; +#endif + return false; + } + else if (!S_ISREG(st_mode)) + { + // Some other type - error. +#ifdef RSDIR_DEBUG + std::cerr << "RsDirUtil::checkFile() "; + std::cerr << filename << " is not a Regular File" << std::endl; +#endif + return false; + } + return true; +} + + +bool RsDirUtil::checkDirectory(const std::string& dir) +{ + int val; + mode_t st_mode; +#ifdef WINDOWS_SYS + std::wstring wdir; + librs::util::ConvertUtf8ToUtf16(dir, wdir); + struct _stat buf; + val = _wstat(wdir.c_str(), &buf); + st_mode = buf.st_mode; +#else + struct stat buf; + val = stat(dir.c_str(), &buf); + st_mode = buf.st_mode; +#endif + if (val == -1) + { +#ifdef RSDIR_DEBUG + std::cerr << "RsDirUtil::checkDirectory() "; + std::cerr << dir << " doesn't exist" << std::endl; +#endif + return false; + } + else if (!S_ISDIR(st_mode)) + { + // Some other type - error. +#ifdef RSDIR_DEBUG + std::cerr << "RsDirUtil::checkDirectory() "; + std::cerr << dir << " is not Directory" << std::endl; +#endif + return false; + } + return true; +} + + +bool RsDirUtil::checkCreateDirectory(const std::string& dir) +{ +#ifdef RSDIR_DEBUG + std::cerr << "RsDirUtil::checkCreateDirectory() dir: " << dir << std::endl; +#endif + +#ifdef WINDOWS_SYS + std::wstring wdir; + librs::util::ConvertUtf8ToUtf16(dir, wdir); + _WDIR *direc = _wopendir(wdir.c_str()); + if (!direc) +#else + DIR *direc = opendir(dir.c_str()); + if (!direc) +#endif + { + // directory don't exist. create. +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // UNIX + if (-1 == mkdir(dir.c_str(), 0777)) +#else // WIN + if (-1 == _wmkdir(wdir.c_str())) +#endif +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + { +#ifdef RSDIR_DEBUG + std::cerr << "check_create_directory() Fatal Error et oui--"; + std::cerr < &keepFiles) +{ + + /* check for the dir existance */ +#ifdef WINDOWS_SYS + std::wstring wcleandir; + librs::util::ConvertUtf8ToUtf16(cleandir, wcleandir); + _WDIR *dir = _wopendir(wcleandir.c_str()); +#else + DIR *dir = opendir(cleandir.c_str()); +#endif + + std::list::const_iterator it; + + if (!dir) + { + return false; + } + +#ifdef WINDOWS_SYS + struct _wdirent *dent; + struct _stat buf; + + while(NULL != (dent = _wreaddir(dir))) +#else + struct dirent *dent; + struct stat buf; + + while(NULL != (dent = readdir(dir))) +#endif + { + /* check entry type */ +#ifdef WINDOWS_SYS + const std::wstring &wfname = dent -> d_name; + std::wstring wfullname = wcleandir + L"/" + wfname; +#else + const std::string &fname = dent -> d_name; + std::string fullname = cleandir + "/" + fname; +#endif + +#ifdef WINDOWS_SYS + if (-1 != _wstat(wfullname.c_str(), &buf)) +#else + if (-1 != stat(fullname.c_str(), &buf)) +#endif + { + /* only worry about files */ + if (S_ISREG(buf.st_mode)) + { +#ifdef WINDOWS_SYS + std::string fname; + librs::util::ConvertUtf16ToUtf8(wfname, fname); +#endif + /* check if we should keep it */ + if (keepFiles.end() == (it = std::find(keepFiles.begin(), keepFiles.end(), fname))) + { + /* can remove */ +#ifdef WINDOWS_SYS + _wremove(wfullname.c_str()); +#else + remove(fullname.c_str()); +#endif + } + } + } + } + + /* close directory */ +#ifdef WINDOWS_SYS + _wclosedir(dir); +#else + closedir(dir); +#endif + + return true; +} + +/* slightly nicer helper function */ +bool RsDirUtil::hashFile(const std::string& filepath, + std::string &name, std::string &hash, uint64_t &size) +{ + if (getFileHash(filepath, hash, size)) + { + /* extract file name */ + name = RsDirUtil::getTopDir(filepath); + return true; + } + return false; +} + + +#include +#include +#include + +/* Function to hash, and get details of a file */ +bool RsDirUtil::getFileHash(const std::string& filepath, std::string &hash, uint64_t &size, RsThread *thread /*= NULL*/) +{ + FILE *fd; + int len; + SHA_CTX *sha_ctx = new SHA_CTX; + unsigned char sha_buf[SHA_DIGEST_LENGTH]; + unsigned char gblBuf[512]; + + if (NULL == (fd = RsDirUtil::rs_fopen(filepath.c_str(), "rb"))) + return false; + + /* determine size */ + fseeko64(fd, 0, SEEK_END); + size = ftello64(fd); + fseeko64(fd, 0, SEEK_SET); + + /* check if thread is running */ + bool isRunning = thread ? thread->isRunning() : true; + int runningCheckCount = 0; + + SHA1_Init(sha_ctx); + while(isRunning && (len = fread(gblBuf,1, 512, fd)) > 0) + { + SHA1_Update(sha_ctx, gblBuf, len); + + if (thread && ++runningCheckCount > (10 * 1024)) { + /* check all 50MB if thread is running */ + isRunning = thread->isRunning(); + runningCheckCount = 0; + } + } + + /* Thread has ended */ + if (isRunning == false) + { + delete sha_ctx; + fclose(fd); + return false; + } + + /* reading failed for some reason */ + if (ferror(fd)) + { + delete sha_ctx; + fclose(fd); + return false; + } + + SHA1_Final(&sha_buf[0], sha_ctx); + + std::ostringstream tmpout; + for(int i = 0; i < SHA_DIGEST_LENGTH; i++) + { + tmpout << std::setw(2) << std::setfill('0') << std::hex << (unsigned int) (sha_buf[i]); + } + hash = tmpout.str(); + + delete sha_ctx; + fclose(fd); + return true; +} + +bool RsDirUtil::renameFile(const std::string& from, const std::string& to) +{ + int loops = 0; + +#ifdef WINDOWS_SYS + std::wstring f; + librs::util::ConvertUtf8ToUtf16(from, f); + std::wstring t; + librs::util::ConvertUtf8ToUtf16(to, t); + + while (!MoveFileEx(f.c_str(), t.c_str(), MOVEFILE_REPLACE_EXISTING)) +#else + std::string f(from),t(to) ; + + while (rename(from.c_str(), to.c_str()) < 0) +#endif + { +#ifdef WIN32 + if (GetLastError() != ERROR_ACCESS_DENIED) +#else + if (errno != EACCES) +#endif + /* set errno? */ + return false ; +#ifdef WIN32 + Sleep(100000); /* us */ +#else + usleep(100000); /* us */ +#endif + + if (loops >= 30) + return false ; + + loops++; + } + + return true ; +} + +bool RsDirUtil::createBackup (const std::string& sFilename, unsigned int nCount) +{ +#ifdef WINDOWS_SYS + if (GetFileAttributesA (sFilename.c_str ()) == -1) { + // file doesn't exist + return true; + } + + // search last backup + int nLast; + for (nLast = nCount; nLast >= 1; nLast--) { + std::ostringstream sStream; + sStream << sFilename << nLast << ".bak"; + + if (GetFileAttributesA (sStream.str ().c_str ()) != -1) { + break; + } + } + + // delete max backup + if (nLast == nCount) { + std::ostringstream sStream; + sStream << sFilename << nCount << ".bak"; + if (DeleteFileA (sStream.str ().c_str ()) == FALSE) { + getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File delete error", "Error while deleting file " + sStream.str ()); + return false; + } + nLast--; + } + + // rename backups + for (int nIndex = nLast; nIndex >= 1; nIndex--) { + std::ostringstream sStream; + sStream << sFilename << nIndex << ".bak"; + std::ostringstream sStream1; + sStream1 << sFilename << nIndex + 1 << ".bak"; + + if (renameFile (sStream.str (), sStream1.str ()) == false) { + getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + sStream.str () + " to " + sStream1.str ()); + return false; + } + } + + // copy backup + std::ostringstream sStream; + sStream << sFilename << 1 << ".bak"; + if (CopyFileA (sFilename.c_str (), sStream.str ().c_str (), FALSE) == FALSE) { + getPqiNotify()->AddSysMessage (0, RS_SYS_WARNING, "File rename error", "Error while renaming file " + sFilename + " to " + sStream.str ()); + return false; + } +#endif + return true; +} + +FILE *RsDirUtil::rs_fopen(const char* filename, const char* mode) +{ +#ifdef WINDOWS_SYS + std::wstring wfilename; + librs::util::ConvertUtf8ToUtf16(filename, wfilename); + std::wstring wmode; + librs::util::ConvertUtf8ToUtf16(mode, wmode); + + return _wfopen(wfilename.c_str(), wmode.c_str()); +#else + return fopen64(filename, mode); +#endif +} + +std::string RsDirUtil::convertPathToUnix(std::string path) +{ + for (unsigned int i = 0; i < path.length(); i++) + { + if (path[i] == '\\') + path[i] = '/'; + } + return path; +} + +std::string RsDirUtil::makePath(const std::string &path1, const std::string &path2) +{ + std::string path = path1; + + if (path.empty() == false && *path.rbegin() != '/') { + path += "/"; + } + path += path2; + + return path; +} + +#if 0 // NOT ENABLED YET! +/************************* WIDE STRING ***************************/ +/************************* WIDE STRING ***************************/ +/************************* WIDE STRING ***************************/ + +std::wstring RsDirUtil::getWideTopDir(std::wstring dir) +{ + std::wstring top; + + /* find the subdir: [/][dir1.../][/] + */ + int i,j; + int len = dir.length(); + for(j = len - 1; (j > 0) && (dir[j] == '/'); j--); + for(i = j; (i > 0) && (dir[i] != '/'); i--); + + if (dir[i] == '/') + i++; + + for(; i <= j; i++) + { + top += dir[i]; + } + + return top; +} + +std::wstring RsDirUtil::removeWideTopDir(std::wstring dir) +{ + std::wstring rest; + + /* remove the subdir: [/][dir1.../][/] + */ + int i,j; + int len = dir.length(); + for(j = len - 1; (j > 0) && (dir[j] == '/'); j--); + for(i = j; (i >= 0) && (dir[i] != '/'); i--); + + /* remove any more slashes */ + for(; (i >= 0) && (dir[i] == '/'); i--); + + for(j = 0; j <= i; j++) + { + rest += dir[j]; + } + + return rest; +} + +std::wstring RsDirUtil::getWideRootDir(std::wstring dir) +{ + std::wstring root; + + /* find the subdir: [/]root[/...] + */ + int i,j; + int len = dir.length(); + for(i = 0; (i < len) && (dir[i] == '/'); i++); + for(j = i; (j < len) && (dir[j] != '/'); j++); + if (i == j) + return root; /* empty */ + for(; i < j; i++) + { + root += dir[i]; + } + return root; +} + +std::wstring RsDirUtil::removeWideRootDir(std::wstring path) +{ + unsigned int i, j; + unsigned int len = path.length(); + std::wstring output; + + /* chew leading '/'s */ + for(i = 0; (i < len) && (path[i] == '/'); i++); + if (i == len) + return output; /* empty string */ + + for(j = i; (j < len) && (path[j] != '/'); j++); /* run to next '/' */ + for(; (j < len) && (path[j] == '/'); j++); /* chew leading '/'s */ + + for(; j < len; j++) + { + output += path[j]; + } + + return output; +} + +std::wstring RsDirUtil::removeWideRootDirs(std::wstring path, std::wstring root) +{ + /* too tired */ + std::wstring notroot; + + unsigned int i = 0, j = 0; + + /* catch empty data */ + if ((root.length() < 1) || (path.length() < 1)) + return notroot; + + if ((path[0] == '/') && (root[0] != '/')) + { + i++; + } + + for(; (i < path.length()) && (j < root.length()) && (path[i] == root[j]); i++, j++); + + /* should have consumed root. */ + if (j == root.length()) + { + //std::cerr << "matched root!" << std::endl; + } + else + { + //std::cerr << "failed i: " << i << ", j: " << j << std::endl; + //std::cerr << "root: " << root << " path: " << path << std::endl; + return notroot; + } + + if (path[i] == '/') + { + i++; + } + + for(; i < path.length(); i++) + { + notroot += path[i]; + } + + //std::cerr << "Found NotRoot: " << notroot << std::endl; + + return notroot; +} + + + +int RsDirUtil::breakupWideDirList(std::wstring path, + std::list &subdirs) +{ + int start = 0; + unsigned int i; + for(i = 0; i < path.length(); i++) + { + if (path[i] == '/') + { + if (i - start > 0) + { + subdirs.push_back(path.substr(start, i-start)); + } + start = i+1; + } + } + // get the final one. + if (i - start > 0) + { + subdirs.push_back(path.substr(start, i-start)); + } + return 1; +} + + + +bool RsDirUtil::checkWideDirectory(std::wstring dir) +{ + struct stat buf; + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + std::string d(dir.begin(), dir.end()); + int val = stat(d.c_str(), &buf); + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + if (val == -1) + { +#ifdef RSDIR_DEBUG + std::cerr << "RsDirUtil::checkDirectory() "; + std::cerr << d << " doesn't exist" << std::endl; +#endif + return false; + } + else if (!S_ISDIR(buf.st_mode)) + { + // Some other type - error. +#ifdef RSDIR_DEBUG + std::cerr << "RsDirUtil::checkDirectory() "; + std::cerr << d << " is not Directory" << std::endl; +#endif + return false; + } + return true; +} + + +bool RsDirUtil::checkWideCreateDirectory(std::wstring dir) +{ + struct stat buf; + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + std::string d(dir.begin(), dir.end()); + int val = stat(d.c_str(), &buf); + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + if (val == -1) + { + // directory don't exist. create. +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // UNIX + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + if (-1 == mkdir(d.c_str(), 0777)) + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ +#else // WIN + if (-1 == mkdir(d.c_str())) +#endif +/******************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + { +#ifdef RSDIR_DEBUG + std::cerr << "check_create_directory() Fatal Error --"; + std::cerr < + +bool RsDirUtil::cleanupWideDirectory(std::wstring cleandir, std::list keepFiles) +{ + + /* check for the dir existance */ + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + std::string cd(cleandir.begin(), cleandir.end()); + DIR *dir = opendir(cd.c_str()); + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + std::list::const_iterator it; + + if (!dir) + { + return false; + } + + struct dirent *dent; + struct stat buf; + + while(NULL != (dent = readdir(dir))) + { + /* check entry type */ + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + std::string fname(dent -> d_name); + std::wstring wfname(fname.begin(), fname.end()); + std::string fullname = cd + "/" + fname; + + if (-1 != stat(fullname.c_str(), &buf)) + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + { + /* only worry about files */ + if (S_ISREG(buf.st_mode)) + { + /* check if we should keep it */ + if (keepFiles.end() == (it = std::find(keepFiles.begin(), keepFiles.end(), wfname))) + { + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + /* can remove */ + remove(fullname.c_str()); + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + } + } + } + } + /* close directory */ + closedir(dir); + + return true; +} + +/* slightly nicer helper function */ +bool RsDirUtil::hashWideFile(std::wstring filepath, + std::wstring &name, std::string &hash, uint64_t &size) +{ + if (getWideFileHash(filepath, hash, size)) + { + /* extract file name */ + name = RsDirUtil::getWideTopDir(filepath); + return true; + } + return false; +} + + +#include +#include +#include + +/* Function to hash, and get details of a file */ +bool RsDirUtil::getWideFileHash(std::wstring filepath, + std::string &hash, uint64_t &size) +{ + FILE *fd; + int len; + SHA_CTX *sha_ctx = new SHA_CTX; + unsigned char sha_buf[SHA_DIGEST_LENGTH]; + unsigned char gblBuf[512]; + + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + std::string fp(filepath.begin(), filepath.end()); + + if (NULL == (fd = fopen64(fp.c_str(), "rb"))) + return false; + + /***** XXX TO MAKE WIDE SYSTEM CALL ******************************************************/ + + /* determine size */ + fseeko64(fd, 0, SEEK_END); + size = ftello64(fd); + fseeko64(fd, 0, SEEK_SET); + + SHA1_Init(sha_ctx); + while((len = fread(gblBuf,1, 512, fd)) > 0) + { + SHA1_Update(sha_ctx, gblBuf, len); + } + + /* reading failed for some reason */ + if (ferror(fd)) + { + delete sha_ctx; + fclose(fd); + return false; + } + + SHA1_Final(&sha_buf[0], sha_ctx); + + std::ostringstream tmpout; + for(int i = 0; i < SHA_DIGEST_LENGTH; i++) + { + tmpout << std::setw(2) << std::setfill('0') << std::hex << (unsigned int) (sha_buf[i]); + } + hash = tmpout.str(); + + delete sha_ctx; + fclose(fd); + return true; +} + +bool RsDirUtil::renameWideFile(const std::wstring& from, const std::wstring& to) +{ + int loops = 0; + +#if defined(WIN32) || defined(MINGW) || defined(__CYGWIN__) +#ifdef WIN_CROSS_UBUNTU + std::wstring f,t ; + for(int i=0;i= 30) + return false ; + + loops++; + } + + return true ; +} + + +#endif // WIDE STUFF NOT ENABLED YET! diff --git a/libretroshare/src/util/rsdir.h b/libretroshare/src/util/rsdir.h new file mode 100644 index 000000000..73435774b --- /dev/null +++ b/libretroshare/src/util/rsdir.h @@ -0,0 +1,101 @@ + +/* + * "$Id: rsdir.h,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RSUTIL_DIRFNS_H +#define RSUTIL_DIRFNS_H + +#include +#include +#include + +class CRC32Map ; +class RsThread; + +namespace RsDirUtil { + +std::string getTopDir(const std::string&); +std::string getRootDir(const std::string&); +std::string removeRootDir(const std::string& path); +std::string removeTopDir(const std::string& dir); +std::string removeRootDirs(const std::string& path, const std::string& root); + +// Renames file from to file to. Files should be on the same file system. +// returns true if succeed, false otherwise. +bool renameFile(const std::string& from,const std::string& to) ; +bool createBackup (const std::string& sFilename, unsigned int nCount = 5); + +// returns the CRC32 of the data of length len +// +uint32_t rs_CRC32(const unsigned char *data,uint32_t len) ; + +// Computes the CRC32 map of a complete file, with given size and chunk size. +// +bool crc32File(FILE *f,uint64_t file_size,uint32_t chunk_size,CRC32Map& map) ; + +int breakupDirList(const std::string& path, std::list &subdirs); + +bool copyFile(const std::string& source,const std::string& dest); +bool checkFile(const std::string& filename); +bool checkDirectory(const std::string& dir); +bool checkCreateDirectory(const std::string& dir); +bool cleanupDirectory(const std::string& dir, const std::list &keepFiles); + +bool hashFile(const std::string& filepath, std::string &name, std::string &hash, uint64_t &size); +bool getFileHash(const std::string& filepath,std::string &hash, uint64_t &size, RsThread *thread = NULL); + + +std::wstring getWideTopDir(std::wstring); +std::wstring getWideRootDir(std::wstring); +std::wstring removeWideRootDir(std::wstring path); +std::wstring removeWideTopDir(std::wstring dir); +std::wstring removeWideRootDirs(std::wstring path, std::wstring root); + +// Renames file from to file to. Files should be on the same file system. +// returns true if succeed, false otherwise. +bool renameWideFile(const std::wstring& from,const std::wstring& to) ; + +int breakupWideDirList(std::wstring path, + std::list &subdirs); + +bool checkWideDirectory(std::wstring dir); +bool checkWideCreateDirectory(std::wstring dir); +bool cleanupWideDirectory(std::wstring dir, std::list keepFiles); + +bool hashWideFile(std::wstring filepath, + std::wstring &name, std::string &hash, uint64_t &size); + +bool getWideFileHash(std::wstring filepath, + std::string &hash, uint64_t &size); + +FILE *rs_fopen(const char* filename, const char* mode); + +std::string convertPathToUnix(std::string path); +std::string makePath(const std::string &path1, const std::string &path2); +} + + +#endif diff --git a/libretroshare/src/util/rsdiscspace.cc b/libretroshare/src/util/rsdiscspace.cc new file mode 100644 index 000000000..294914079 --- /dev/null +++ b/libretroshare/src/util/rsdiscspace.cc @@ -0,0 +1,196 @@ +/* + * libretroshare/src/util: rsdiscspace.cc + * + * Universal Networking Header for RetroShare. + * + * Copyright 2010-2010 by Cyril Soler. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "csoler@users.sourceforge.net". + * + */ + +#include +#include "retroshare/rsfiles.h" +#include "retroshare/rsiface.h" +#include "retroshare/rsinit.h" +#include "rsdiscspace.h" +#include +#ifndef WIN32 +#include +#endif + +#define DELAY_BETWEEN_CHECKS 2 + +/* + * #define DEBUG_RSDISCSPACE + */ + +time_t RsDiscSpace::_last_check[3] = { 0,0,0 } ; +uint32_t RsDiscSpace::_size_limit_mb = 100 ; +uint32_t RsDiscSpace::_current_size[3] = { 10000,10000,10000 } ; +bool RsDiscSpace::_last_res[3] = { true,true,true }; +RsMutex RsDiscSpace::_mtx ; + +bool RsDiscSpace::crossSystemDiskStats(const char *file, uint64_t& free_blocks, uint64_t& block_size) +{ +#if defined(WIN32) || defined(MINGW) || defined(__CYGWIN__) + + DWORD dwFreeClusters; + DWORD dwBytesPerSector; + DWORD dwSectorPerCluster; + DWORD dwTotalClusters; + +#ifdef WIN_CROSS_UBUNTU + wchar_t szDrive[4]; + szDrive[0] = file[0] ; + szDrive[1] = file[1] ; + szDrive[2] = file[2] ; +#else + char szDrive[4] = ""; + + char *pszFullPath = _fullpath (NULL, file, 0); + if (pszFullPath == 0) { + std::cerr << "Size estimate failed for drive (_fullpath) " << std::endl ; + return false; + } + _splitpath (pszFullPath, szDrive, NULL, NULL, NULL); + free (pszFullPath); +#endif + szDrive[3] = 0; + + if (!GetDiskFreeSpaceA (szDrive, &dwSectorPerCluster, &dwBytesPerSector, &dwFreeClusters, &dwTotalClusters)) + { + std::cerr << "Size estimate failed for drive " << szDrive << std::endl ; + return false; + } + + free_blocks = dwFreeClusters ; + block_size = dwSectorPerCluster * dwBytesPerSector ; +#else +#ifdef __APPLE__ + struct statvfs buf; + + if (0 != statvfs (file, &buf)) + { + std::cerr << "Size estimate failed for file " << file << std::endl ; + return false; + } + + + free_blocks = buf.f_bavail; + block_size = buf.f_frsize ; +#else + struct statvfs64 buf; + + if (0 != statvfs64 (file, &buf)) + { + std::cerr << "Size estimate failed for file " << file << std::endl ; + return false; + } + + + free_blocks = buf.f_bavail; + block_size = buf.f_bsize ; +#endif + +#endif + return true ; +} + +bool RsDiscSpace::checkForDiscSpace(RsDiscSpace::DiscLocation loc) +{ + RsStackMutex m(_mtx) ; // Locked + + if(!rsFiles) // + { + std::cerr << "checkForDiscSpace(): ERROR: rsFiles is 0x0" << std::endl ; + return true ; + } + + time_t now = time(NULL) ; + + if(_last_check[loc]+DELAY_BETWEEN_CHECKS < now) + { + uint64_t free_blocks,block_size ; + int rs = false; + +#ifdef DEBUG_RSDISCSPACE + std::cerr << "Size determination:" << std::endl ; +#endif + switch(loc) + { + case RS_DOWNLOAD_DIRECTORY: rs = crossSystemDiskStats(rsFiles->getDownloadDirectory().c_str(),free_blocks,block_size) ; +#ifdef DEBUG_RSDISCSPACE + std::cerr << " path = " << rsFiles->getDownloadDirectory() << std::endl ; +#endif + break ; + + case RS_PARTIALS_DIRECTORY: rs = crossSystemDiskStats(rsFiles->getPartialsDirectory().c_str(),free_blocks,block_size) ; +#ifdef DEBUG_RSDISCSPACE + std::cerr << " path = " << rsFiles->getPartialsDirectory() << std::endl ; +#endif + break ; + + case RS_CONFIG_DIRECTORY: rs = crossSystemDiskStats(RsInit::RsConfigDirectory().c_str(),free_blocks,block_size) ; +#ifdef DEBUG_RSDISCSPACE + std::cerr << " path = " << RsInit::RsConfigDirectory() << std::endl ; +#endif + break ; + } + + if(!rs) + { + std::cerr << "Determination of free disc space failed ! Be careful !" << std::endl ; + return true ; + } + _last_check[loc] = now ; + + // Now compute the size in megabytes + // + _current_size[loc] = uint32_t(block_size * free_blocks / (uint64_t)(1024*1024)) ; // on purpose integer division + +#ifdef DEBUG_RSDISCSPACE + std::cerr << " blocks available = " << free_blocks << std::endl ; + std::cerr << " blocks size = " << block_size << std::endl ; + std::cerr << " free MBs = " << _current_size[loc] << std::endl ; +#endif + } + + bool res = _current_size[loc] > _size_limit_mb ; + + if(_last_res[loc] && !res) + rsicontrol->getNotify().notifyDiskFull(loc,_size_limit_mb) ; + + _last_res[loc] = res ; + + return res ; +} + +void RsDiscSpace::setFreeSpaceLimit(uint32_t size_in_mb) +{ + RsStackMutex m(_mtx) ; // Locked + + _size_limit_mb = size_in_mb ; +} + +uint32_t RsDiscSpace::freeSpaceLimit() +{ + RsStackMutex m(_mtx) ; // Locked + + return _size_limit_mb ; +} + diff --git a/libretroshare/src/util/rsdiscspace.h b/libretroshare/src/util/rsdiscspace.h new file mode 100644 index 000000000..27a5b717c --- /dev/null +++ b/libretroshare/src/util/rsdiscspace.h @@ -0,0 +1,59 @@ +/* + * libretroshare/src/util: rsdiscspace.h + * + * Universal Networking Header for RetroShare. + * + * Copyright 2010-2010 by Cyril Soler. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "csoler@users.sourceforge.net". + * + */ + +#pragma once + +#include +#include +#include + +class RsDiscSpace +{ + public: + typedef uint32_t DiscLocation ; + + // Returns false is the disc space is lower than the given size limit, true otherwise. + // When the size limit is reached, this class calls notify to warn the user (possibly + // with a popup window). + // + static bool checkForDiscSpace(DiscLocation loc) ; + + // Allow the user to specify his own size limit. Should not be too low, especially not 0 MB ;-) + // 10MB to 100MB are sensible values. + // + static void setFreeSpaceLimit(uint32_t mega_bytes) ; + static uint32_t freeSpaceLimit() ; + + private: + static bool crossSystemDiskStats(const char *file, uint64_t& free_blocks, uint64_t& block_size) ; + + static RsMutex _mtx ; + + static time_t _last_check[3] ; + static uint32_t _size_limit_mb ; + static uint32_t _current_size[3] ; + static bool _last_res[3] ; +}; + diff --git a/libretroshare/src/util/rsnet.cc b/libretroshare/src/util/rsnet.cc new file mode 100644 index 000000000..61359df6b --- /dev/null +++ b/libretroshare/src/util/rsnet.cc @@ -0,0 +1,158 @@ +/* + * libretroshare/src/util: rsnet.cc + * + * Universal Networking Header for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "util/rsnet.h" +#include "util/rsthreads.h" +#include +#include + +#ifdef WINDOWS_SYS +#else +#include +#endif + +/* enforce LITTLE_ENDIAN on Windows */ +#ifdef WINDOWS_SYS + #define BYTE_ORDER 1234 + #define LITTLE_ENDIAN 1234 + #define BIG_ENDIAN 4321 +#endif + +uint64_t ntohll(uint64_t x) +{ +#ifdef BYTE_ORDER + #if BYTE_ORDER == BIG_ENDIAN + return x; + #elif BYTE_ORDER == LITTLE_ENDIAN + + uint32_t top = (uint32_t) (x >> 32); + uint32_t bot = (uint32_t) (0x00000000ffffffffULL & x); + + uint64_t rev = ((uint64_t) ntohl(top)) | (((uint64_t) ntohl(bot)) << 32); + + return rev; + #else + #error "ENDIAN determination Failed" + #endif +#else + #error "ENDIAN determination Failed (BYTE_ORDER not defined)" +#endif + +} + +uint64_t htonll(uint64_t x) +{ + return ntohll(x); +} + +void sockaddr_clear(struct sockaddr_in *addr) +{ + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; +} + + +bool isValidNet(const struct in_addr *addr) +{ + // invalid address. + if((*addr).s_addr == INADDR_NONE) + return false; + if((*addr).s_addr == 0) + return false; + // should do more tests. + return true; +} + + +bool isLoopbackNet(const struct in_addr *addr) +{ + in_addr_t taddr = ntohl(addr->s_addr); + return (taddr == (127 << 24 | 1)); +} + +bool isPrivateNet(const struct in_addr *addr) +{ + in_addr_t taddr = ntohl(addr->s_addr); + + // 10.0.0.0/8 + // 172.16.0.0/12 + // 192.168.0.0/16 + // 169.254.0.0/16 + if ((taddr>>24 == 10) || + (taddr>>20 == (172<<4 | 16>>4)) || + (taddr>>16 == (192<<8 | 168)) || + (taddr>>16 == (169<<8 | 254))) + { + return true; + } + else + { + return false; + } +} + +bool isExternalNet(const struct in_addr *addr) +{ + if (!isValidNet(addr)) + { + return false; + } + if (isLoopbackNet(addr)) + { + return false; + } + if (isPrivateNet(addr)) + { + return false; + } + return true; +} + +std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr) +{ + out << "[" << inet_ntoa(addr.sin_addr) << ":"; + out << htons(addr.sin_port) << "]"; + return out; +} + +/* thread-safe version of inet_ntoa */ +/*** XXX, PROBLEM this function is not Thread-Safe. + * because it can be called in lots of other parts of the program. + * which could still collide with this one! + * + * Must rewrite to make truely thread-safe. + */ + +std::string rs_inet_ntoa(struct in_addr in) +{ + std::ostringstream str; + uint8_t *bytes = (uint8_t *) &(in.s_addr); + str << (int) bytes[0] << "."; + str << (int) bytes[1] << "."; + str << (int) bytes[2] << "."; + str << (int) bytes[3]; + return str.str(); +} + diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h new file mode 100644 index 000000000..7b398dbe1 --- /dev/null +++ b/libretroshare/src/util/rsnet.h @@ -0,0 +1,83 @@ +/* + * libretroshare/src/util: rsnet.h + * + * Universal Networking Header for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef RS_UNIVERSAL_NETWORK_HEADER +#define RS_UNIVERSAL_NETWORK_HEADER + +#include +#include /* Included because GCC4.4 wants it */ +#include /* Included because GCC4.4 wants it */ +#include + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + +#include +#include +#include +#include + +#include +#include + +#else + +#include "util/rswin.h" + +#include +#include + +#include /* for ssize_t */ +//typedef uint32_t socklen_t; +typedef uint32_t in_addr_t; + +int inet_aton(const char *name, struct in_addr *addr); + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + +/* 64 bit conversions */ +uint64_t ntohll(uint64_t x); +uint64_t htonll(uint64_t x); + +/* blank a network address */ +void sockaddr_clear(struct sockaddr_in *addr); + +/* determine network type (moved from pqi/pqinetwork.cc) */ +bool isValidNet(const struct in_addr *addr); +bool isLoopbackNet(const struct in_addr *addr); +bool isPrivateNet(const struct in_addr *addr); +bool isExternalNet(const struct in_addr *addr); + +/* convert addresses */ +bool getIPAddressFromString (const char *addr_str, struct in_addr *addr); + +std::ostream& operator<<(std::ostream& o,const struct sockaddr_in&) ; + +/* thread-safe version of inet_ntoa */ +std::string rs_inet_ntoa(struct in_addr in); + + +#endif /* RS_UNIVERSAL_NETWORK_HEADER */ diff --git a/libretroshare/src/util/rsprint.cc b/libretroshare/src/util/rsprint.cc new file mode 100644 index 000000000..4e7f6c1e5 --- /dev/null +++ b/libretroshare/src/util/rsprint.cc @@ -0,0 +1,123 @@ + +/* + * libretroshare/src/util: rsprint.cc + * + * RetroShare Utilities + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "util/rsprint.h" +#include +#include +#include + +std::string RsUtil::BinToHex(std::string bin) +{ + return BinToHex(bin.c_str(), bin.length()); +} + +std::string RsUtil::BinToHex(const char *arr, const uint32_t len) +{ + std::ostringstream out; + + for(uint32_t j = 0; j < len; j++) + { + out << std::hex << std::setw(2) << std::setfill('0') << (int32_t) (((const uint8_t *) arr)[j]); + } + return out.str(); +} + + +std::string RsUtil::HashId(std::string id, bool reverse) +{ + std::string hash; + std::string tohash; + if (reverse) + { + std::string::reverse_iterator rit; + for(rit = id.rbegin(); rit != id.rend(); rit++) + { + tohash += (*rit); + } + } + else + { + tohash = id; + } + + SHA_CTX *sha_ctx = new SHA_CTX; + uint8_t sha_hash[SHA_DIGEST_LENGTH]; + + SHA1_Init(sha_ctx); + SHA1_Update(sha_ctx, tohash.c_str(), tohash.length()); + SHA1_Final(sha_hash, sha_ctx); + + for(uint16_t i = 0; i < SHA_DIGEST_LENGTH; i++) + { + hash += sha_hash[i]; + } + + /* cleanup */ + delete sha_ctx; + + return hash; +} + + + + +#ifdef WINDOWS_SYS +#include +#include +#endif + +#include +#include +#include + +static double getCurrentTS(); + +// Little fn to get current timestamp in an independent manner. +std::string RsUtil::AccurateTimeString() +{ + std::ostringstream out; + out << std::setprecision(15) << getCurrentTS(); + return out.str(); +} + +static double getCurrentTS() +{ + +#ifndef WINDOWS_SYS + struct timeval cts_tmp; + gettimeofday(&cts_tmp, NULL); + double cts = (cts_tmp.tv_sec) + ((double) cts_tmp.tv_usec) / 1000000.0; +#else + struct _timeb timebuf; + _ftime( &timebuf); + double cts = (timebuf.time) + ((double) timebuf.millitm) / 1000.0; +#endif + return cts; +} + + + + diff --git a/libretroshare/src/util/rsprint.h b/libretroshare/src/util/rsprint.h new file mode 100644 index 000000000..dd1cce9ca --- /dev/null +++ b/libretroshare/src/util/rsprint.h @@ -0,0 +1,44 @@ + +/* + * libretroshare/src/util: rsprint.h + * + * RetroShare Utilities + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RSUTIL_PRINTFNS_H +#define RSUTIL_PRINTFNS_H + +#include +#include + +namespace RsUtil { + +std::string BinToHex(std::string bin); +std::string BinToHex(const char *arr, const uint32_t len); +std::string HashId(std::string id, bool reverse = false); + +std::string AccurateTimeString(); + +} + +#endif diff --git a/libretroshare/src/util/rsrandom.cc b/libretroshare/src/util/rsrandom.cc new file mode 100644 index 000000000..bddccb997 --- /dev/null +++ b/libretroshare/src/util/rsrandom.cc @@ -0,0 +1,93 @@ +#include +#include +#include +#include "rsrandom.h" + +uint32_t RSRandom::index = 0 ; +std::vector RSRandom::MT(RSRandom::N,0u) ; +RsMutex RSRandom::rndMtx ; + +#ifdef WINDOWS_SYS +static bool auto_seed = RSRandom::seed( (time(NULL) + ((uint32_t) pthread_self().p)*0x1293fe)^0x18e34a12 ) ; +#else + #ifdef __APPLE__ + static bool auto_seed = RSRandom::seed( (time(NULL) + pthread_mach_thread_np(pthread_self())*0x1293fe + (getpid()^0x113ef76b))^0x18e34a12 ) ; + #else + static bool auto_seed = RSRandom::seed( (time(NULL) + pthread_self()*0x1293fe + (getpid()^0x113ef76b))^0x18e34a12 ) ; + #endif +#endif +bool RSRandom::seed(uint32_t s) +{ + RsStackMutex mtx(rndMtx) ; + + MT.resize(N,0) ; // because MT might not be already resized + + uint32_t j ; + MT[0]= s & 0xffffffffUL; + for (j=1; j> 30)) + j) & 0xffffffffUL ; + + return true ; +} + +void RSRandom::locked_next_state() +{ + for(uint32_t i=0;i> 1) ; + + if((y & 1) == 1) + MT[i] = MT[i] ^ 0x9908b0df ; + } + index = 0 ; +} + +uint32_t RSRandom::random_u32() +{ + uint32_t y; + + { + RsStackMutex mtx(rndMtx) ; + + y = MT[index++] ; + + if(index == N) + locked_next_state(); + } + + // Tempering + y ^= (y >> 11); + y ^= (y << 7 ) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + return y; +} + +uint64_t RSRandom::random_u64() +{ + return ((uint64_t)random_u32() << 32ul) + random_u32() ; +} + +float RSRandom::random_f32() +{ + return random_u32() / (float)(~(uint32_t)0) ; +} + +double RSRandom::random_f64() +{ + return random_u64() / (double)(~(uint64_t)0) ; +} + +std::string RSRandom::random_alphaNumericString(uint32_t len) +{ + std::string s = "" ; + + for(uint32_t i=0;i + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#pragma once + +// RSRandom contains a random number generator that is +// - thread safe +// - system independant +// - fast +// - cryptographically safe +// +// The implementation is adapted from the Mersenne Twister page of Wikipedia. +// +// http://en.wikipedia.org/wiki/Mersenne_twister + +#include +#include + +class RSRandom +{ + public: + static uint32_t random_u32() ; + static uint64_t random_u64() ; + static float random_f32() ; + static double random_f64() ; + + static bool seed(uint32_t s) ; + + static std::string random_alphaNumericString(uint32_t length) ; + + private: + static RsMutex rndMtx ; + + static const uint32_t N = 624; + static const uint32_t M = 397; + + static const uint32_t MATRIX_A = 0x9908b0dfUL; + static const uint32_t UMASK = 0x80000000UL; + static const uint32_t LMASK = 0x7fffffffUL; + + static void locked_next_state() ; + static uint32_t index ; + static std::vector MT ; +}; diff --git a/libretroshare/src/util/rsthreads.cc b/libretroshare/src/util/rsthreads.cc new file mode 100644 index 000000000..eeb61fff1 --- /dev/null +++ b/libretroshare/src/util/rsthreads.cc @@ -0,0 +1,171 @@ + +/* + * "$Id: rsthreads.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2007 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "rsthreads.h" +#include /* for usleep() */ +#include /* for usleep() */ +#include + +/******* + * #define DEBUG_THREADS 1 + *******/ + +#ifdef DEBUG_THREADS + #include +#endif + +extern "C" void* rsthread_init(void* p) +{ + RsThread *thread = (RsThread *) p; + if (!thread) + { + return 0; + } + thread -> run(); + return 0; +} + + +pthread_t createThread(RsThread &thread) +{ + pthread_t tid; + void *data = (void *) (&thread); + + thread.mMutex.lock(); + { + +#if 0 + int ret; + ret = pthread_attr_init(&tattr); + if (doDetached) + { + ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED); + } + else + { + ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_JOINABLE); + } + + pthread_create(&tid, &tattr, &rsthread_init, data); +#endif + + int err ; + + if( 0 == (err=pthread_create(&tid, 0, &rsthread_init, data))) + thread.mTid = tid; + else + std::cerr << "Fatal error: pthread_create could not create a thread. Error returned: " << err << " !!!!!!!" << std::endl; + } + thread.mMutex.unlock(); + + return tid; + +} + +RsThread::RsThread () +{ + mIsRunning = true; + +#ifdef WINDOWS_SYS + memset (&mTid, 0, sizeof(mTid)); +#else + mTid = 0; +#endif +} + +void RsThread::join() /* waits for the the mTid thread to stop */ +{ + // do we need a mutex for this ? + mIsRunning = false; + + void *ptr; + pthread_join(mTid, &ptr); +} + +void RsThread::stop() +{ + pthread_exit(NULL); +} + +bool RsThread::isRunning() +{ + // do we need a mutex for this ? + return mIsRunning; +} + +RsQueueThread::RsQueueThread(uint32_t min, uint32_t max, double relaxFactor ) + :mMinSleep(min), mMaxSleep(max), mRelaxFactor(relaxFactor) +{ + mLastSleep = (uint32_t)mMinSleep ; + mLastWork = time(NULL) ; +} + +void RsQueueThread::run() +{ + while(isRunning()) + { + bool doneWork = false; + while(workQueued() && doWork()) + { + doneWork = true; + } + time_t now = time(NULL); + if (doneWork) + { + mLastWork = now; + mLastSleep = (uint32_t) (mMinSleep + (mLastSleep - mMinSleep) / 2.0); +#ifdef DEBUG_THREADS + std::cerr << "RsQueueThread::run() done work: sleeping for: " << mLastSleep; + std::cerr << " ms"; + std::cerr << std::endl; +#endif + + } + else + { + uint32_t deltaT = now - mLastWork; + double frac = deltaT / mRelaxFactor; + + mLastSleep += (uint32_t) + ((mMaxSleep-mMinSleep) * (frac + 0.05)); + if (mLastSleep > mMaxSleep) + { + mLastSleep = mMaxSleep; + } +#ifdef DEBUG_THREADS + std::cerr << "RsQueueThread::run() no work: sleeping for: " << mLastSleep; + std::cerr << " ms"; + std::cerr << std::endl; +#endif + } +#ifdef WIN32 + Sleep(mLastSleep); +#else + usleep(1000 * mLastSleep); +#endif + } +} diff --git a/libretroshare/src/util/rsthreads.h b/libretroshare/src/util/rsthreads.h new file mode 100644 index 000000000..a96c0cd14 --- /dev/null +++ b/libretroshare/src/util/rsthreads.h @@ -0,0 +1,154 @@ +#ifndef RSIFACE_THREADS_H +#define RSIFACE_THREADS_H + +/* + * "$Id: rsthreads.h,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifdef WINDOWS_SYS +#include "util/rswin.h" +#endif + +#include +#include + +/* RsIface Thread Wrappers */ + +#undef RSTHREAD_SELF_LOCKING_GUARD + +class RsMutex +{ + public: + + RsMutex() + { + pthread_mutex_init(&realMutex, NULL); +#ifdef RSTHREAD_SELF_LOCKING_GUARD + _thread_id = 0 ; +#endif + } + ~RsMutex() + { + pthread_mutex_destroy(&realMutex); + } + + void lock() + { +#ifdef RSTHREAD_SELF_LOCKING_GUARD + if(!trylock()) + if(!pthread_equal(_thread_id,pthread_self())) +#endif + pthread_mutex_lock(&realMutex); + + _thread_id = pthread_self() ; +#ifdef RSTHREAD_SELF_LOCKING_GUARD + ++_cnt ; +#endif + } + void unlock() + { +#ifdef RSTHREAD_SELF_LOCKING_GUARD + if(--_cnt == 0) + { +#endif +#ifndef WIN32 + _thread_id = 0 ; +#endif + pthread_mutex_unlock(&realMutex); +#ifdef RSTHREAD_SELF_LOCKING_GUARD + } +#endif + } + bool trylock() { return (0 == pthread_mutex_trylock(&realMutex)); } + + private: + pthread_mutex_t realMutex; + pthread_t _thread_id ; +#ifdef RSTHREAD_SELF_LOCKING_GUARD + uint32_t _cnt ; +#endif +}; + +class RsStackMutex +{ + public: + + RsStackMutex(RsMutex &mtx): mMtx(mtx) { mMtx.lock(); } + ~RsStackMutex() { mMtx.unlock(); } + + private: + RsMutex &mMtx; +}; + +class RsThread; + +/* to create a thread! */ +pthread_t createThread(RsThread &thread); + +class RsThread +{ + public: + RsThread(); +virtual ~RsThread() {} + +virtual void start() { createThread(*this); } +virtual void run() = 0; /* called once the thread is started */ +virtual void join(); /* waits for the the mTid thread to stop */ +virtual void stop(); /* calls pthread_exit() */ + +bool isRunning(); + + pthread_t mTid; + RsMutex mMutex; + +private: + bool mIsRunning; +}; + + +class RsQueueThread: public RsThread +{ + public: + + RsQueueThread(uint32_t min, uint32_t max, double relaxFactor ); +virtual ~RsQueueThread() { return; } + +virtual void run(); + + protected: + +virtual bool workQueued() = 0; +virtual bool doWork() = 0; + + private: + uint32_t mMinSleep; /* ms */ + uint32_t mMaxSleep; /* ms */ + uint32_t mLastSleep; /* ms */ + time_t mLastWork; /* secs */ + float mRelaxFactor; +}; + + +#endif diff --git a/libretroshare/src/util/rsversion.cc b/libretroshare/src/util/rsversion.cc new file mode 100644 index 000000000..68241313c --- /dev/null +++ b/libretroshare/src/util/rsversion.cc @@ -0,0 +1,14 @@ +/* + * rsversion.cc + * + * Created on: Jun 23, 2009 + * Author: alexandrut + */ + +#include "rsversion.h" + +std::string RsUtil::retroshareVersion() +{ + return std::string(LIB_VERSION) + " " + std::string(SVN_REVISION); + +} diff --git a/libretroshare/src/util/rsversion.h b/libretroshare/src/util/rsversion.h new file mode 100644 index 000000000..1483843c9 --- /dev/null +++ b/libretroshare/src/util/rsversion.h @@ -0,0 +1,17 @@ +/* + * rsversion.h + * + * Created on: Jun 23, 2009 + * Author: alexandrut + */ + +#include + +#define LIB_VERSION "0.5.1d" +#define SVN_REVISION "Revision " + +namespace RsUtil { + + std::string retroshareVersion(); + +} \ No newline at end of file diff --git a/libretroshare/src/util/rsversion.in b/libretroshare/src/util/rsversion.in new file mode 100644 index 000000000..6013df8fc --- /dev/null +++ b/libretroshare/src/util/rsversion.in @@ -0,0 +1,17 @@ +/* + * rsversion.h + * + * Created on: Jun 23, 2009 + * Author: alexandrut + */ + +#include + +#define LIB_VERSION "0.5.1d" +#define SVN_REVISION "Revision $WCREV$" + +namespace RsUtil { + + std::string retroshareVersion(); + +} \ No newline at end of file diff --git a/libretroshare/src/util/rswin.cc b/libretroshare/src/util/rswin.cc new file mode 100644 index 000000000..a6b2dbc01 --- /dev/null +++ b/libretroshare/src/util/rswin.cc @@ -0,0 +1,55 @@ +#include "util/rswin.h" + + +#ifdef WINDOWS_SYS + + +namespace librs { namespace util { + + +bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest) { + int nbChars = MultiByteToWideChar(CP_UTF8, 0, + source.c_str(), -1, + 0, 0); + if(nbChars == 0) + return false; + + wchar_t* utf16Name = new wchar_t[nbChars]; + if( MultiByteToWideChar(CP_UTF8, 0, + source.c_str(), -1, + utf16Name, nbChars) == 0) { + return false; + } + + dest = utf16Name; + delete[] utf16Name; + + return true; +} + +bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest) { + int nbChars = WideCharToMultiByte(CP_UTF8, 0, + source.c_str(), -1, + 0, 0, + 0, 0); + if(nbChars == 0) + return false; + + char* utf8Name = new char[nbChars]; + if( WideCharToMultiByte(CP_UTF8, 0, + source.c_str(), -1, + utf8Name, nbChars, + 0, 0) == 0) { + return false; + } + + dest = utf8Name; + delete[] utf8Name; + return true; +} + + +} } // librs::util + + +#endif // WINDOWS_SYS diff --git a/libretroshare/src/util/rswin.h b/libretroshare/src/util/rswin.h new file mode 100644 index 000000000..f436de716 --- /dev/null +++ b/libretroshare/src/util/rswin.h @@ -0,0 +1,63 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, Thomas Kister + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +/** + * This file provides helper functions for the windows environment + */ + + +#ifndef RSWIN_H_ +#define RSWIN_H_ + + +#ifdef WINDOWS_SYS + +#ifdef _WIN32_WINNT +#error "Please include \"util/rswin.h\" *before* any other one as _WIN32_WINNT needs to predefined" +#endif + +// This defines the platform to be WinXP or later and is needed for getaddrinfo +// It must be declared before pthread.h includes windows.h +#define _WIN32_WINNT 0x0501 + +#include +#include + +// For win32 systems (tested on MingW+Ubuntu) +#define stat64 _stati64 + + +namespace librs { namespace util { + + +bool ConvertUtf8ToUtf16(const std::string& source, std::wstring& dest); + +bool ConvertUtf16ToUtf8(const std::wstring& source, std::string& dest); + + +} } // librs::util + + +#endif // WINDOWS_SYS + + +#endif // RSWIN_H_ diff --git a/libretroshare/src/util/smallobject.cc b/libretroshare/src/util/smallobject.cc new file mode 100644 index 000000000..ab7a6bf96 --- /dev/null +++ b/libretroshare/src/util/smallobject.cc @@ -0,0 +1,304 @@ +#include +#include "smallobject.h" +#include "util/rsthreads.h" + +using namespace RsMemoryManagement ; + +RsMutex SmallObject::_mtx ; +SmallObjectAllocator SmallObject::_allocator(RsMemoryManagement::MAX_SMALL_OBJECT_SIZE) ; + +void Chunk::init(size_t blockSize,unsigned char blocks) +{ + _data = new unsigned char[blockSize*blocks] ; + _firstAvailableBlock = 0 ; + _blocksAvailable = blocks ; + + // Inits the first byte of each block to point to the next available block + // + unsigned char *p = _data ; + + for(unsigned char i=0;i= 2) ; + + unsigned char *result = _data + _firstAvailableBlock*blockSize ; + + // Grab id of next available block from the block being allocated. + + // Always the case because the first available block is the first, so the next + // available block is given by *result. + // + _firstAvailableBlock = *result ; + --_blocksAvailable ; + + return result ; +} + +void Chunk::deallocate(void *p,size_t blockSize) +{ + assert(p >= _data) ; + + unsigned char *toRelease = static_cast(p) ; + + // alignment check + + assert( (toRelease - _data) % blockSize == 0 ) ; + + *toRelease = _firstAvailableBlock ; + _firstAvailableBlock = static_cast( (toRelease - _data)/blockSize) ; + + // truncation check + + assert(_firstAvailableBlock == (toRelease - _data)/blockSize); + + ++_blocksAvailable ; +} + +void Chunk::printStatistics(int blockSize) const +{ + std::cerr << " blocksAvailable : " << (int)_blocksAvailable << std::endl; + std::cerr << " firstBlockAvailable: " << (int)_firstAvailableBlock << std::endl; + std::cerr << " blocks : " << (void*)_data << " to " << (void*)(_data+BLOCKS_PER_CHUNK*blockSize) << std::endl; +} + +FixedAllocator::FixedAllocator(size_t bytes) +{ + _blockSize = bytes ; + _numBlocks = BLOCKS_PER_CHUNK ; + _allocChunk = -1 ; + _deallocChunk = -1 ; +} +FixedAllocator::~FixedAllocator() +{ + for(uint32_t i=0;i<_chunks.size();++i) + { + _chunks[i]->free() ; + delete _chunks[i] ; + } +} + +void *FixedAllocator::allocate() +{ + if(_allocChunk < 0 || _chunks[_allocChunk]->_blocksAvailable == 0) + { + // find availabel memory in this chunk + // + uint32_t i ; + _allocChunk = -1 ; + for(i=0;i<_chunks.size();++i) + if(_chunks[i]->_blocksAvailable > 0) // found a chunk + { + _allocChunk = i ; + break ; + } + if( _allocChunk < 0 ) + { + _chunks.reserve(_chunks.size()+1) ; + Chunk *newChunk = new Chunk; + + if(newChunk == NULL) + { + std::cerr << "RsMemoryManagement: ran out of memory !" << std::endl; + exit(-1) ; + } + newChunk->init(_blockSize,_numBlocks) ; + _chunks.push_back(newChunk) ; + + _allocChunk = _chunks.size()-1 ; + _deallocChunk = _chunks.size()-1 ; + } + + } + assert(_chunks[_allocChunk] != NULL) ; + assert(_chunks[_allocChunk]->_blocksAvailable > 0) ; + + return _chunks[_allocChunk]->allocate(_blockSize) ; +} +void FixedAllocator::deallocate(void *p) +{ + if(_deallocChunk < 0 || !chunkOwnsPointer(*_chunks[_deallocChunk],p)) + { + // find the chunk that contains this pointer. Perform a linear search. + + _deallocChunk = -1 ; + + for(uint32_t i=0;i<_chunks.size();++i) + if(chunkOwnsPointer(*_chunks[i],p)) + { + _deallocChunk = i ; + break ; + } + } + assert(_chunks[_deallocChunk] != NULL) ; + + _chunks[_deallocChunk]->deallocate(p,_blockSize) ; + + if(_chunks[_deallocChunk]->_blocksAvailable == BLOCKS_PER_CHUNK) + { + _chunks[_deallocChunk]->free() ; + delete _chunks[_deallocChunk] ; + + _chunks[_deallocChunk] = _chunks.back() ; + if(_allocChunk == _deallocChunk) _allocChunk = -1 ; + if(_allocChunk == ((int)_chunks.size())-1) _allocChunk = _deallocChunk ; + _deallocChunk = -1 ; + _chunks.pop_back(); + } +} +void FixedAllocator::printStatistics() const +{ + std::cerr << " numBLocks=" << (int)_numBlocks << std::endl; + std::cerr << " blockSize=" << (int)_blockSize << std::endl; + std::cerr << " Number of chunks: " << _chunks.size() << std::endl; + for(uint32_t i=0;i<_chunks.size();++i) + _chunks[i]->printStatistics(_blockSize) ; +} + +SmallObjectAllocator::SmallObjectAllocator(size_t maxObjectSize) + : _maxObjectSize(maxObjectSize) +{ + RsStackMutex m(SmallObject::_mtx) ; + + _lastAlloc = NULL ; + _lastDealloc = NULL ; + _active = true ; +} + +SmallObjectAllocator::~SmallObjectAllocator() +{ + RsStackMutex m(SmallObject::_mtx) ; + + for(std::map::const_iterator it(_pool.begin());it!=_pool.end();++it) + delete it->second ; + + _active = false ; +} + +void *SmallObjectAllocator::allocate(size_t bytes) +{ + if(bytes > _maxObjectSize) + return malloc(bytes) ; + else if(_lastAlloc != NULL && _lastAlloc->blockSize() == bytes) + return _lastAlloc->allocate() ; + else + { + std::map::iterator it(_pool.find(bytes)) ; + + if(it == _pool.end()) + { + _pool[bytes] = new FixedAllocator(bytes) ; + it = _pool.find(bytes) ; + } + _lastAlloc = it->second ; + + return it->second->allocate() ; + } +} + +void SmallObjectAllocator::deallocate(void *p,size_t bytes) +{ + if(bytes > _maxObjectSize) + free(p) ; + else if(_lastDealloc != NULL && _lastDealloc->blockSize() == bytes) + _lastDealloc->deallocate(p) ; + else + { + std::map::iterator it(_pool.find(bytes)) ; + + if(it == _pool.end()) + { + _pool[bytes] = new FixedAllocator(bytes) ; + it = _pool.find(bytes) ; + } + it->second->deallocate(p) ; + _lastDealloc = it->second ; + } +} + +void SmallObjectAllocator::printStatistics() const +{ + std::cerr << "RsMemoryManagement Statistics:" << std::endl; + std::cerr << " Total Fixed-size allocators: " << _pool.size() << std::endl; + std::cerr << "Pool" << std::endl; + + for(std::map::const_iterator it(_pool.begin());it!=_pool.end();++it) + { + std::cerr << " Allocator for size " << it->first << " : " << std::endl; + std::cerr << " Last Alloc: " << _lastAlloc << std::endl; + std::cerr << " Last Dealloc: " << _lastDealloc << std::endl; + it->second->printStatistics() ; + } +} + +void *SmallObject::operator new(size_t size) +{ +#ifdef DEBUG_MEMORY + bool print=false ; + { + RsStackMutex m(_mtx) ; + static time_t last_time = 0 ; + time_t now = time(NULL) ; + if(now > last_time + 20) + { + last_time = now ; + print=true ; + } + } + if(print) + printStatistics() ; +#endif + + RsStackMutex m(_mtx) ; + + if(!_allocator._active) + return (void*)NULL; + + void *p = _allocator.allocate(size) ; +#ifdef DEBUG_MEMORY + std::cerr << "new RsItem: " << p << ", size=" << size << std::endl; +#endif + return p ; +} + +void SmallObject::operator delete(void *p,size_t size) +{ + RsStackMutex m(_mtx) ; + + if(!_allocator._active) + return ; + + _allocator.deallocate(p,size) ; +#ifdef DEBUG_MEMORY + std::cerr << "del RsItem: " << p << ", size=" << size << std::endl; +#endif +} + +void SmallObject::printStatistics() +{ + RsStackMutex m(_mtx) ; + + if(!_allocator._active) + return ; + + _allocator.printStatistics() ; +} + +void RsMemoryManagement::printStatistics() +{ + SmallObject::printStatistics(); +} + + diff --git a/libretroshare/src/util/smallobject.h b/libretroshare/src/util/smallobject.h new file mode 100644 index 000000000..cec0301f6 --- /dev/null +++ b/libretroshare/src/util/smallobject.h @@ -0,0 +1,119 @@ +/* + * libretroshare/src/util: smallobject.h + * + * Universal Networking Header for RetroShare. + * + * Copyright 2011 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "cyril.soler@users.sourceforge.net". + * + */ + +#pragma once + +#include +#include + +#include +#include + +#include + +namespace RsMemoryManagement +{ + static const int MAX_SMALL_OBJECT_SIZE = 128 ; + static const unsigned char BLOCKS_PER_CHUNK = 255 ; + + struct Chunk + { + void init(size_t blockSize,unsigned char blocks); + void free() ; + + void *allocate(size_t); + void deallocate(void *p,size_t blockSize); + + unsigned char *_data ; + unsigned char _firstAvailableBlock ; + unsigned char _blocksAvailable ; + + void printStatistics(int blockSize) const ; + }; + + class FixedAllocator + { + public: + FixedAllocator(size_t bytes) ; + virtual ~FixedAllocator() ; + + void *allocate(); + void deallocate(void *p) ; + inline size_t blockSize() const { return _blockSize ; } + + inline bool chunkOwnsPointer(const Chunk& c,void *p) const + { + return p >= c._data && (static_cast(p)-c._data)/_blockSize < _numBlocks ; + } + + void printStatistics() const ; + private: + size_t _blockSize ; + unsigned char _numBlocks ; + std::vector _chunks ; + int _allocChunk ; // last chunk that provided allocation. -1 if not inited + int _deallocChunk ; // last chunk that provided de-allocation. -1 if not inited + }; + + class SmallObjectAllocator + { + public: + SmallObjectAllocator(size_t maxObjectSize) ; + virtual ~SmallObjectAllocator() ; + + void *allocate(size_t numBytes) ; + void deallocate(void *p,size_t size) ; + + void printStatistics() const ; + + bool _active ; + private: + std::map _pool ; + FixedAllocator *_lastAlloc ; + FixedAllocator *_lastDealloc ; + size_t _maxObjectSize ; + }; + + class SmallObject + { + public: + static void *operator new(size_t size) ; + static void operator delete(void *p,size_t size) ; + + static void printStatistics() ; + + virtual ~SmallObject() {} + + private: + static SmallObjectAllocator _allocator ; + static RsMutex _mtx; + + friend class SmallObjectAllocator ; + }; + + extern void printStatistics() ; +} + + diff --git a/libretroshare/src/util/utest.h b/libretroshare/src/util/utest.h new file mode 100644 index 000000000..1ebd9875a --- /dev/null +++ b/libretroshare/src/util/utest.h @@ -0,0 +1,23 @@ +#ifndef _UNIT_TEST_MACROS_H__ +#define _UNIT_TEST_MACROS_H__ + +#include + +#define TFAILURE( s ) printf( "FAILURE: " __FILE__ ":%-4d %s\n", __LINE__, s ) +#define TSUCCESS( s ) printf( "SUCCESS: " __FILE__ ":%-4d %s\n", __LINE__, s ) + +/* careful with this line (no protection) */ +#define INITTEST() int ok = 1; int gok = 1; + +/* declare the variables */ +extern int ok; +extern int gok; + +#define CHECK( b ) do { if ( ! (b) ) { ok = 0; TFAILURE( #b ); } } while(0) +#define FAILED( s ) do { ok = 0; TFAILURE( s ); } while(0) +#define REPORT( s ) do { if ( ! (ok) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) +#define REPORT2( b, s ) do { if ( ! (b) ) { ok = 0; TFAILURE( s ); } else { TSUCCESS( s );} gok &= ok; ok = 1; } while(0) +#define FINALREPORT( s ) do { gok &= ok; ok = 1; if ( ! (gok) ) { TFAILURE( s ); } else { TSUCCESS( s );} } while(0) +#define TESTRESULT() (!gok) + +#endif diff --git a/libretroshare/src/version_detail.sh b/libretroshare/src/version_detail.sh new file mode 100755 index 000000000..03da58d67 --- /dev/null +++ b/libretroshare/src/version_detail.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +#don't exit even if a command fails +set +e + + +if ( git log -n 1 &> /dev/null); then + #retrieve git information + version="git : $(git status | grep branch | cut -c 13-) $(git log -n 1 | grep commit | cut -c 8-)" +fi + +if ( git log -n 1 | grep svn &> /dev/null); then + #retrieve git svn information + version="$version svn : $(git log -n 1 | grep svn | awk '{print $2}' | head -1 | sed 's/.*@//')" +elif ( git log -n 10 | grep svn &> /dev/null); then + #retrieve git svn information + version="$version svn closest version : $(git log -n 10 | grep svn | awk '{print $2}' | head -1 | sed 's/.*@//')" +fi + +if ( svn info &> /dev/null); then + version=$(svn info | head -n 5 | tail -1) +fi +if [[ $version != '' ]]; then + version="$version date : $(date +'%T %m.%d.%y')" + echo "Writing version to util/rsversion.h : $version " + sed -i "s/SVN_REVISION .*/SVN_REVISION \"$version\"/g" util/rsversion.h +fi +echo "script version_detail.sh finished normally" +exit 0 diff --git a/plugins/ColorCode_plugin/COPYING b/plugins/ColorCode_plugin/COPYING new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/plugins/ColorCode_plugin/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/plugins/ColorCode_plugin/ColorCode.pro b/plugins/ColorCode_plugin/ColorCode.pro new file mode 100644 index 000000000..a1e7d3ef5 --- /dev/null +++ b/plugins/ColorCode_plugin/ColorCode.pro @@ -0,0 +1,65 @@ +# ------------------------------------------------- +# Project created by QtCreator 2009-06-24T21:25:25 +# ------------------------------------------------- +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin release + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(colorcode_plugin) + +HEADERS += ../PluginInterface.h \ + ColorCodePlugin.h +SOURCES += ColorCodePlugin.cpp + +#=============================================================================== + +# Input +HEADERS += about.h \ + colorcode.h \ + colorpeg.h \ + msg.h \ + pegrow.h \ + rowhint.h \ + ccsolver.h \ + background.h \ + solutionrow.h \ + graphicsbtn.h \ + settings.h \ + prefdialog.h +FORMS += about.ui \ + prefdialog.ui +SOURCES += about.cpp \ + colorcode.cpp \ + colorpeg.cpp \ + main.cpp \ + msg.cpp \ + pegrow.cpp \ + rowhint.cpp \ + ccsolver.cpp \ + background.cpp \ + solutionrow.cpp \ + graphicsbtn.cpp \ + settings.cpp \ + prefdialog.cpp +RESOURCES += resource.qrc +OTHER_FILES += docs/GPL.html +win32:RC_FILE = ColorCode.rc +TRANSLATIONS += trans_de.ts \ + trans_en.ts \ + trans_cs.ts \ + trans_fr.ts \ + trans_hu.ts +CODECFORTR = UTF-8 +CODECFORSRC = UTF-8 diff --git a/plugins/ColorCode_plugin/ColorCode.pro_win b/plugins/ColorCode_plugin/ColorCode.pro_win new file mode 100644 index 000000000..cb3c44055 --- /dev/null +++ b/plugins/ColorCode_plugin/ColorCode.pro_win @@ -0,0 +1,28 @@ +# ------------------------------------------------- +# Project created by QtCreator 2009-06-24T21:25:25 +# ------------------------------------------------- +TARGET = ColorCode +TEMPLATE = app +SOURCES += main.cpp \ + mainwindow.cpp \ + colorpeg.cpp \ + rowhint.cpp \ + pegrow.cpp \ + msg.cpp \ + about.cpp +HEADERS += mainwindow.h \ + colorpeg.h \ + rowhint.h \ + pegrow.h \ + msg.h \ + about.h +RESOURCES += resource.qrc +FORMS += about.ui +OTHER_FILES += docs/GPL.html \ + trans_en.ts \ + trans_de.ts +RC_FILE = ColorCode.rc +TRANSLATIONS = trans_en.ts \ + trans_de.ts +CODECFORTR = UTF-8 +CODECFORSRC = UTF-8 diff --git a/plugins/ColorCode_plugin/ColorCode.rc b/plugins/ColorCode_plugin/ColorCode.rc new file mode 100644 index 000000000..074a40e26 --- /dev/null +++ b/plugins/ColorCode_plugin/ColorCode.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "cc32.ico" diff --git a/plugins/ColorCode_plugin/ColorCodePlugin.cpp b/plugins/ColorCode_plugin/ColorCodePlugin.cpp new file mode 100644 index 000000000..456ef3ccb --- /dev/null +++ b/plugins/ColorCode_plugin/ColorCodePlugin.cpp @@ -0,0 +1,53 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +//#include +//#include +//#include + +#include "ColorCodePlugin.h" +#include "colorcode.h" + +QString +ColorCodePlugin::pluginDescription() const +{ + QString res; + res = "a ColorCode plugin" ; + + return res; +} + +QString +ColorCodePlugin::pluginName() const +{ + return "ColorCode" ; +} + +QWidget* +ColorCodePlugin::pluginWidget(QWidget * parent ) +{ + ColorCode* window = new ColorCode(); + + return window; +} + + +Q_EXPORT_PLUGIN2(colorcode_plugin, ColorCodePlugin) diff --git a/plugins/ColorCode_plugin/ColorCodePlugin.h b/plugins/ColorCode_plugin/ColorCodePlugin.h new file mode 100644 index 000000000..035cd4b33 --- /dev/null +++ b/plugins/ColorCode_plugin/ColorCodePlugin.h @@ -0,0 +1,48 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _COLORCODE_PLUGIN_H_ +#define _COLORCODE_PLUGIN_H_ + +#include + +#include +#include + +#include + +#include + +class ColorCodePlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/ColorCode_plugin/INSTALL b/plugins/ColorCode_plugin/INSTALL new file mode 100644 index 000000000..6a0dbd832 --- /dev/null +++ b/plugins/ColorCode_plugin/INSTALL @@ -0,0 +1,11 @@ +# simply run: + +qmake-qt4 +make + +# to install: +cp colorcode /usr/bin/ + +# to uninstall: +rm /usr/bin/colorcode + diff --git a/plugins/ColorCode_plugin/about.cpp b/plugins/ColorCode_plugin/about.cpp new file mode 100644 index 000000000..bd50d2e6f --- /dev/null +++ b/plugins/ColorCode_plugin/about.cpp @@ -0,0 +1,67 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include "about.h" + +About::About(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) +{ + setupUi(this); + setWindowIcon(QIcon(QPixmap(":/img/help-about.png"))); + mAuthorIcon->setPixmap(QPixmap(":/img/cc32.png")); + mLicenseIcon->setPixmap(QPixmap(":/img/GNU-icon32.png")); + + mAuthorText->setText("" + tr("ColorCode") + "
" + + tr("A needful game to train your brain ;-)") + + tr("

Free MasterMind clone including a built in,
rather intelligent solver.") + + "

" + tr("Version") + ": 0.6.1
" + tr("Author") + ": Dirk Laebisch"); + + QString license_file = ":/docs/GPL.html"; + if (QFile::exists(license_file)) + { + QFont fixed_font; + fixed_font.setStyleHint(QFont::TypeWriter); + fixed_font.setFamily("Courier"); + mLicenseText->setFont(fixed_font); + + QFile f(license_file); + if (f.open(QIODevice::ReadOnly)) + { + mLicenseText->setText(QString::fromUtf8(f.readAll().constData())); + } + f.close(); + } + else + { + mLicenseText->setText( + "" + + tr("This program is free software; you can redistribute it and/or modify " + "it under the terms of the GNU General Public License as published by " + "the Free Software Foundation; either version 2 of the License, or " + "(at your option) any later version.") + "" + ); + } +} + +About::~About() +{ +} + +QSize About::sizeHint () const +{ + return QSize(360, 270); +} diff --git a/plugins/ColorCode_plugin/about.h b/plugins/ColorCode_plugin/about.h new file mode 100644 index 000000000..97c221aca --- /dev/null +++ b/plugins/ColorCode_plugin/about.h @@ -0,0 +1,38 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef ABOUT_H +#define ABOUT_H + +#include "ui_about.h" + +#include +#include + +class About : public QDialog, public Ui::About +{ + Q_OBJECT + + public: + About(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~About(); + + virtual QSize sizeHint () const; +}; + +#endif // ABOUT_H diff --git a/plugins/ColorCode_plugin/about.ui b/plugins/ColorCode_plugin/about.ui new file mode 100644 index 000000000..21de7f803 --- /dev/null +++ b/plugins/ColorCode_plugin/about.ui @@ -0,0 +1,185 @@ + + + About + + + Qt::ApplicationModal + + + + 0 + 0 + 360 + 270 + + + + About ColorCode + + + + 6 + + + 9 + + + + + QTabWidget::Rounded + + + 0 + + + + &Author + + + + 6 + + + 9 + + + + + 6 + + + 0 + + + + + icon + + + + + + + Qt::Vertical + + + + 20 + 111 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + + + + + + &License + + + + 6 + + + 9 + + + + + 6 + + + 0 + + + + + icon + + + + + + + Qt::Vertical + + + + 20 + 111 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + tabWidget + mAuthorText + buttonBox + mLicenseText + + + + + buttonBox + accepted() + About + accept() + + + 248 + 254 + + + 157 + 274 + + + + + diff --git a/plugins/ColorCode_plugin/background.cpp b/plugins/ColorCode_plugin/background.cpp new file mode 100644 index 000000000..a9c7c8b11 --- /dev/null +++ b/plugins/ColorCode_plugin/background.cpp @@ -0,0 +1,141 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ +#include + +#include "background.h" + +using namespace std; + +BackGround::BackGround(QObject*) +{ + setCacheMode(QGraphicsItem::DeviceCoordinateCache); + setAcceptedMouseButtons(0); + + QLinearGradient topgrad(0, 16, 0, 129); + topgrad.setColorAt(0.0, QColor(0xf8, 0xf8, 0xf8)); + topgrad.setColorAt(0.6, QColor(0xb8, 0xb9, 0xbb)); + topgrad.setColorAt(1, QColor(0xd4, 0xd5, 0xd7)); + mTopGrad = QBrush(topgrad); + + QLinearGradient botgrad(0, 530, 0, 557); + botgrad.setColorAt(0.0, QColor("#d4d5d7")); + botgrad.setColorAt(0.3, QColor("#cecfd1")); + botgrad.setColorAt(1.0, QColor("#b0b1b3")); + mBotGrad = QBrush(botgrad); + + QLinearGradient lgrad(0, 190, 320, 370); + lgrad.setColorAt(0.0, QColor(0xff, 0xff, 0xff, 0xa0)); + lgrad.setColorAt(0.49, QColor(0xff, 0xff, 0xff, 0xa0)); + lgrad.setColorAt(0.50, QColor(0, 0, 0, 0x80)); + lgrad.setColorAt(1.0, QColor(0, 0, 0, 0x80)); + mFramePen = QPen(QBrush(lgrad), 1); + + mPend = QColor("#646568"); + mPenl = QColor("#ecedef"); + mGrad0 = QColor("#cccdcf"); + mGrad1 = QColor("#fcfdff"); + + mPend.setAlpha(0x32); + mPenl.setAlpha(0x50); + mGrad0.setAlpha(0x32); + mGrad1.setAlpha(0x32); +} + +BackGround::~BackGround() +{ + scene()->removeItem(this); +} + +QRectF BackGround::boundingRect() const +{ + const int margin = 1; + return outlineRect().adjusted(-margin, -margin, +margin, +margin); +} + +QRectF BackGround::outlineRect() const +{ + return QRectF(0.0, 0.0, 320.0, 560.0); +} + +void BackGround::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /* widget */) +{ + int i; + + painter->setPen(Qt::NoPen); + + QRectF cr = QRectF(3, 3, 314, 554); + QPainterPath cpath; + cpath.addRoundedRect(cr, 10.1, 10.1); + painter->setClipPath(cpath); + painter->setClipping(true); + + painter->setBrush(mTopGrad); + painter->drawRect(QRect(4, 4, 312, 125)); + painter->setBrush(QBrush(QColor("#707173"))); + painter->drawRect(QRect(1, 129, 318, 1)); + + painter->setPen(Qt::NoPen); + for (i = 0; i < 10; ++i) + { + painter->setBrush(QBrush(QColor("#9e9fa0"))); + painter->drawRect(QRect(1, i * 40 + 130, 318, 1)); + QLinearGradient rowgrad(0, i * 40 + 131, 0, i * 40 + 169); + rowgrad.setColorAt(0.0, QColor("#9a9b9d")); + rowgrad.setColorAt(1.0, QColor("#949597")); + painter->setBrush(QBrush(rowgrad)); + painter->drawRect(QRect(1, i * 40 + 131, 318, 38)); + painter->setBrush(QBrush(QColor("#88898b"))); + painter->drawRect(QRect(1, i * 40 + 169, 318, 1)); + + painter->setBrush(QBrush(mPenl)); + painter->drawRect(QRectF(277, i * 40 + 130, 39, 1)); + painter->drawRect(QRectF(277, i * 40 + 130, 1, 39)); + painter->setBrush(QBrush(mPend)); + painter->drawRect(QRectF(277, i * 40 + 130 + 39, 40, 1)); + painter->drawRect(QRectF(277 + 39, i * 40 + 130, 1, 40)); + + QRadialGradient grad(QPointF(277 + 10, i * 40 + 130 + 10), 100); + grad.setColorAt(0, mGrad0); + grad.setColorAt(1, mGrad1); + painter->setBrush(QBrush(grad)); + painter->drawRect(QRectF(277 + 1, i * 40 + 131, 38.0, 38.0)); + + painter->setBrush(Qt::NoBrush); + QPointF x0 = QPointF(279, i * 40 + 130 + 2); + QLinearGradient lgrad(x0, QPointF(x0.x() + 36, x0.y() + 36)); + lgrad.setColorAt(0.0, QColor(0, 0, 0, 0x80)); + lgrad.setColorAt(1.0, QColor(0xff, 0xff, 0xff, 0xa0)); + painter->setPen(QPen(QBrush(lgrad), 0.5)); + painter->drawEllipse(QRectF(x0.x(), x0.y(), 36, 36)); + painter->setPen(Qt::NoPen); + } + + painter->setBrush(mBotGrad); + painter->drawRect(QRect(1, 531, 318, 27)); + painter->setBrush(QBrush(QColor("#eff0f2"))); + painter->drawRect(QRect(1, 530, 318, 1)); + + painter->setClipping(false); + + QRectF r = QRectF(3.5, 3.5, 313, 553); + painter->setBrush(Qt::NoBrush); + painter->setPen(mFramePen); + painter->drawRoundedRect(r, 9.8, 9.8); +} + + diff --git a/plugins/ColorCode_plugin/background.h b/plugins/ColorCode_plugin/background.h new file mode 100644 index 000000000..b9515246f --- /dev/null +++ b/plugins/ColorCode_plugin/background.h @@ -0,0 +1,55 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef BACKGROUND_H +#define BACKGROUND_H + +#include +#include +#include +#include +#include +#include "colorcode.h" + +class BackGround : public QObject, public QGraphicsItem +{ + Q_OBJECT + + public: + BackGround(QObject* parent = 0); + ~BackGround(); + + QRectF boundingRect() const; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); + + private: + QRectF outlineRect() const; + + QBrush mTopGrad; + QBrush mBotGrad; + + QPen mFramePen; + + QColor mPend; + QColor mPenl; + QColor mGrad0; + QColor mGrad1; + +}; + +#endif // BACKGROUND_H diff --git a/plugins/ColorCode_plugin/cc32.ico b/plugins/ColorCode_plugin/cc32.ico new file mode 100644 index 000000000..f77ffc716 Binary files /dev/null and b/plugins/ColorCode_plugin/cc32.ico differ diff --git a/plugins/ColorCode_plugin/ccsolver.cpp b/plugins/ColorCode_plugin/ccsolver.cpp new file mode 100644 index 000000000..f310de133 --- /dev/null +++ b/plugins/ColorCode_plugin/ccsolver.cpp @@ -0,0 +1,677 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include "ccsolver.h" +#include + +using namespace std; + +const int CCSolver::STRENGTH_LOW = 0; +const int CCSolver::STRENGTH_MEDIUM = 1; +const int CCSolver::STRENGTH_HIGH = 2; + +const int CCSolver::mFGCnts[4][9][4] = { +{ + {2, 0, 0, 0}, + {2, 0, 0, 0}, + {1, 1, 0, 0}, + {1, 1, 0, 0}, + {1, 1, 0, 0}, + {1, 1, 0, 0}, + {1, 1, 0, 0}, + {1, 1, 0, 0}, + {1, 1, 0, 0} +}, +{ + {3, 0, 0, 0}, + {2, 1, 0, 0}, + {1, 1, 1, 0}, + {1, 1, 1, 0}, + {1, 1, 1, 0}, + {1, 1, 1, 0}, + {1, 1, 1, 0}, + {1, 1, 1, 0}, + {1, 1, 1, 0} +}, +{ + {3, 1, 0, 0}, + {3, 1, 0, 0}, + {2, 1, 1, 0}, + {2, 2, 0, 0}, + {2, 2, 0, 0}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1} +}, +{ + {4, 1, 0, 0}, + {3, 2, 0, 0}, + {3, 1, 1, 0}, + {2, 2, 1, 0}, + {2, 1, 1, 1}, + {2, 2, 1, 0}, + {2, 1, 1, 1}, + {2, 1, 1, 1}, + {2, 1, 1, 1} +} +}; + +CCSolver::CCSolver(ColorCode* cc) +{ + mCc = cc; + + mColorCnt = 0; + mPegCnt = 0; + mDoubles = -1; + mLevel = -1; + mMaxGuessCnt = 0; + + mAllCnt = 0; + mPosCnt = 0; + mHistCnt = 0; + mGuessCnt = 0; + mMaxRes = 0; + mResCnt = 0; + + mRestartCnt = 0; + + mResTable = NULL; + mCascade = NULL; + mPossible = NULL; + mAllTable = NULL; + mHist = NULL; + + mS = NULL; + mP = NULL; + + mBusy = false; +} + +CCSolver::~CCSolver() +{ + FreeTables(); +} + +void CCSolver::NewGame(const int ccnt, const int pcnt, const int doubles, const int level, const int gcnt) +{ + FreeTables(); + + mColorCnt = ccnt; + mPegCnt = pcnt; + mDoubles = doubles; + mLevel = level; + mMaxGuessCnt = gcnt; + + mAllCnt = 0; + mPosCnt = 0; + mHistCnt = 0; + mGuessCnt = 0; + mMaxRes = 0; + mResCnt = 0; + + mRestartCnt = 0; + mLastPosCnt = 0; + + InitTables(); +} + +void CCSolver::RestartGame() +{ + if (mGuessCnt > 0) + { + ++mRestartCnt; + } + + for (int i = 0 ; i < mMaxGuessCnt ; ++i) + { + mHist[i] = NULL; + } + + mGuessCnt = 0; +} + +void CCSolver::GuessIn(string str) +{ + int ix = Row2Ix(str); + mHist[mGuessCnt] = new int[2]; + mHist[mGuessCnt][0] = ix; +} + +void CCSolver::GuessIn(const vector* rowsol) +{ + int ix = Row2Ix(rowsol); + mHist[mGuessCnt] = new int[2]; + mHist[mGuessCnt][0] = ix; +} + +int* CCSolver::GuessOut() +{ + if (mPosCnt == mLastPosCnt && (mGuessCnt > 0 || mRestartCnt > 0)) + { + return mAllTable[mLastGuess]; + } + + int g = Guess(); + if (g < 0 || g >= mAllCnt) + { + return NULL; + } + + mLastPosCnt = mPosCnt; + mLastGuess = g; + return mAllTable[g]; +} + +int CCSolver::ResIn(const vector* res) +{ + int r = 0; + int len = res->size(); + int i; + for (i = 0; i < len; ++i) + { + if (res->at(i) == 2) + { + r += 10; + } + else if (res->at(i) == 1) + { + r += 1; + } + } + + mHist[mGuessCnt][1] = r; + UpdPos(mHist[mGuessCnt][0], r); + ++mGuessCnt; + + return r; +} + +void CCSolver::FreeTables() +{ + int i; + + delete [] mCascade; + mCascade = NULL; + + delete [] mPossible; + mPossible = NULL; + + for (i = 0 ; i < mAllCnt ; ++i) + { + delete [] mAllTable[i] ; + } + delete [] mAllTable; + mAllTable = NULL; + + for (i = 0 ; i < mMaxGuessCnt ; ++i) + { + delete [] mHist[i] ; + } + + delete [] mHist; + mHist = NULL; + + delete [] mResTable; + mResTable = NULL; + + delete [] mS; + mS = NULL; + + delete [] mP; + mP = NULL; +} + +void CCSolver::InitTables() +{ + int i, j, k; + + if (mDoubles != 1 && mColorCnt < mPegCnt) + { + return; + } + + mCascade = new int [mPegCnt]; + + for (i = 0; i < mPegCnt; ++i) + { + mCascade[i] = IntPow(mColorCnt, mPegCnt - i - 1); + } + + mAllCnt = 1; + for (i = 0; i < mPegCnt; ++i) + { + mAllCnt *= mColorCnt; + } + + mAllTable = new int* [mAllCnt]; + + for (i = 0; i < mAllCnt; ++i) + { + mAllTable[i] = new int [mPegCnt]; + } + + + mPossible = new int [mAllCnt]; + + for (i = 0; i < mAllCnt; ++i) + { + FillTable(i); + } + + mHist = new int* [mMaxGuessCnt]; + for (i = 0 ; i < mMaxGuessCnt ; ++i) + { + mHist[i] = NULL; + } + + mS = new int [mColorCnt]; + mP = new int [mColorCnt]; + + mMaxRes = mPegCnt * 10; + + mResCnt = (IntFac(mPegCnt + 2)) / (IntFac(mPegCnt) * 2) - 1; + + mResTable = new int[mResCnt]; + + k = 0; + for (i = 0; i <= mPegCnt; ++i) + { + for (j = 0; j <= mPegCnt - i; ++j, ++k) + { + if (i == mPegCnt - 1 && j == 1) + { + --k; + continue; + } + mResTable[k] = i * 10 + j; + } + } +} + +void CCSolver::FillTable(const int ix) +{ + int i; + int v = ix; + int pos = 1; + int j; + + for (i = 0; i < mPegCnt; ++i) + { + mAllTable[ix][i] = 0; + } + + for (i = 0; i < mPegCnt; ++i) + { + while (v >= mCascade[i]) + { + ++mAllTable[ix][i]; + v -= mCascade[i]; + } + if (mDoubles != 1 && pos == 1) + { + for (j = 0; j < i; j++) + { + if (mAllTable[ix][j] == mAllTable[ix][i]) + { + pos = 0; + break; + } + } + } + } + + mPosCnt += pos; + mPossible[ix] = pos; +} + +int CCSolver::RowCmp(const int* sol, const int* pat) +{ + int bl = 0; + int wh = 0; + int i; + + for (i = 0; i < mColorCnt; ++i) + { + mS[i] = mP[i] = 0; + } + + for (i = 0; i < mPegCnt; ++i) + { + if (sol[i] == pat[i]) + { + ++bl; + } + else + { + if (mP[sol[i]] > 0) + { + ++wh; + --mP[sol[i]]; + } + else + { + ++mS[sol[i]]; + } + + if (mS[pat[i]] > 0) + { + ++wh; + --mS[pat[i]]; + } + else + { + ++mP[pat[i]]; + } + } + } + + return (10 * bl + wh); +} + +void CCSolver::UpdPos(const int ix, const int res) +{ + int i; + for (i = 0; i < mAllCnt; ++i) + { + if (!mPossible[i]) + { + continue; + } + + if (RowCmp(mAllTable[i], mAllTable[ix]) != res) + { + mPossible[i] = 0; + --mPosCnt; + } + } +} + +string CCSolver::FirstGuess() +{ + int i, j, r; + int pegcnt = 0; + int diffcnt = 0; + + const int* fg = mFGCnts[mPegCnt-2][mColorCnt-2]; + char s[mPegCnt]; + int t[mColorCnt]; + + for (i = 0; i < mColorCnt; ++i) + { + t[i] = 0; + } + + if (mDoubles == 1) + { + for (i = 0; i < 4; ++i) + { + if (fg[i] == 0) + { + break; + } + + do + { + r = rand() % mColorCnt; + } + while (t[r] > 0); + ++t[r]; + ++diffcnt; + for (j = 0; j < fg[i]; ++j) + { + s[pegcnt++] = 'A' + r; + } + if (pegcnt == mPegCnt) + { + break; + } + } + + if (pegcnt != mPegCnt) + { + // + } + + if (mPegCnt > 2 && diffcnt > 1) + { + for (int i = 0; i < (mPegCnt - 1); ++i) + { + r = i + (rand() % (mPegCnt - i)); + if (i != r) + { + char tmp = s[i]; + s[i] = s[r]; + s[r] = tmp; + } + } + } + } + else + { + for (i = 0; i < mPegCnt; ++i) + { + do + { + r = rand() % mColorCnt; + } + while (t[r] > 0); + ++t[r]; + s[i] = 'A' + r; + } + } + + return string(s, mPegCnt); +} + +int CCSolver::Guess() +{ + clock_t start, finish; + start = clock(); + + if (mLevel > STRENGTH_LOW && mGuessCnt == 0 && mRestartCnt == 0) + { + return Row2Ix(FirstGuess()); + } + + mBusy = true; + + int level = mLevel; + if (level == STRENGTH_HIGH && mPosCnt > 10000) + { + level = STRENGTH_MEDIUM; + } + + int i, j; + + if (level == STRENGTH_LOW) + { + for (i = 0; i < mAllCnt; ++i) + { + if (mPossible[i]) + { + break; + } + } + } + else if (level == STRENGTH_MEDIUM) + { + int m = mPosCnt >> 1; + for (i = 0; i < mAllCnt; ++i) + { + if (mPossible[i]) + { + if (--m <= 0) + { + break; + } + } + } + } + else + { + // Donald E. Knuth. The Computer as Master Mind. J. Recreational Mathematics, 9 (1976-77), 1-6. + // Kenji Koyama, Tony W. Lai. An optimal Mastermind Strategy. J. Recreational Mathematics, 1994. + // we'll only take the still possible ones into account, but ... + + int solix = -1; + int shortest = 1000000; + int longest; + int res2pos[mMaxRes]; + + for (j = 0; j <= mMaxRes; ++j) + { + res2pos[j] = 0; + } + + for (i = 0; i < mAllCnt; ++i) + { + if (!mPossible[i]) + { + continue; + } + + for (j = 0; j < mAllCnt; ++j) + { + if (!mPossible[j]) + { + continue; + } + ++res2pos[RowCmp(mAllTable[j], mAllTable[i])]; + } + + longest = 0; + for (j = 0; j < mResCnt; ++j) + { + if (res2pos[mResTable[j]] > longest) + { + longest = res2pos[mResTable[j]]; + } + res2pos[mResTable[j]] = 0; + } + + if (longest < shortest) + { + shortest = longest; + solix = i; + } + } + + i = solix; + } + + finish = clock(); + mBusy = false; + + return i; +} + +string CCSolver::RowOut(const int* r) +{ + char s[mPegCnt]; + + int i; + for (i = 0; i < mPegCnt; ++i) + { + s[i] = 'A' + r[i]; + } + + return string(s, mPegCnt); +} + +int CCSolver::Row2Ix(const vector* v) +{ + int i; + int ix = 0; + int len = v->size(); + + if (len != mPegCnt) + { + return -1; + } + + int j; + for (i = 0; i < mPegCnt; ++i) + { + j = v->at(i); + if (j >= mColorCnt) + { + ix = -1; + break; + } + ix += j * mCascade[i]; + } + + if (ix >= 0 && ix < mAllCnt) + { + return ix; + } + return -1; +} + +int CCSolver::Row2Ix(const string str) +{ + int i; + int ix = 0; + int len = int(str.size()); + + if (len != mPegCnt) + { + return -1; + } + + int j; + for (i = 0; i < mPegCnt; ++i) + { + j = toupper(int(str[i])) - 'A'; + if (j >= mColorCnt) + { + ix = -1; + break; + } + ix += j * mCascade[i]; + } + + if (ix >= 0 && ix < mAllCnt) + { + return ix; + } + return -1; +} + +int CCSolver::IntPow(const int b, const int e) +{ + int i; + int ret = 1; + for (i = 0; i < e; ++i) + { + ret *= b; + } + return ret; +} + +int CCSolver::IntFac(const int n) +{ + int fac = 1; + int i; + for (i = n; i > 1; --i) + { + fac *= i; + } + return fac; +} diff --git a/plugins/ColorCode_plugin/ccsolver.h b/plugins/ColorCode_plugin/ccsolver.h new file mode 100644 index 000000000..116bb0ce3 --- /dev/null +++ b/plugins/ColorCode_plugin/ccsolver.h @@ -0,0 +1,94 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef CCSOLVER_H +#define CCSOLVER_H + +#include +#include "colorcode.h" + +using namespace std; + +class CCSolver +{ +public: + static const int STRENGTH_LOW; + static const int STRENGTH_MEDIUM; + static const int STRENGTH_HIGH; + + CCSolver(ColorCode* cc); + ~CCSolver(); + + void NewGame(const int ccnt, const int pcnt = 4, const int doubles = 1, const int level = 2, const int gcnt = 10); + void RestartGame(); + string FirstGuess(); + void GuessIn(string str); + void GuessIn(const vector* rowsol); + int ResIn(const vector* res); + int* GuessOut(); + + volatile bool mBusy; + +private: + static const int mFGCnts[4][9][4]; + + ColorCode* mCc; + + int mMaxGuessCnt; + int mColorCnt; + int mPegCnt; + int mDoubles; + int mLevel; + + int mLastGuess; + int mLastPosCnt; + + int mAllCnt; + int mPosCnt; + int mHistCnt; + int mGuessCnt; + int mMaxRes; + int mResCnt; + + int mRestartCnt; + + int* mResTable; + int* mCascade; + int* mPossible; + int** mAllTable; + int** mHist; + + int* mS; + int* mP; + + void FreeTables(); + void InitTables(); + void FillTable(const int ix); + int RowCmp(const int* sol, const int* pat); + void UpdPos(const int ix, const int res); + int Guess(); + + string RowOut(const int* r); + int Row2Ix(const string str); + int Row2Ix(const vector* v); + + int IntPow(const int b, const int e); + int IntFac(const int n); +}; + +#endif // CCSOLVER_H diff --git a/plugins/ColorCode_plugin/changelog b/plugins/ColorCode_plugin/changelog new file mode 100644 index 000000000..9906216c4 --- /dev/null +++ b/plugins/ColorCode_plugin/changelog @@ -0,0 +1,113 @@ +* 0.6.1 released, February 16, 2010 + * Translation + - Added french translation - thanks to Filippo Rusconi. + +* 0.6.0 released, February 14, 2010 + * Summary + - Second game mode (Computer vs. Human) + - Preferences dialog for persistent settings + - Additional settings options + * Preferences dialog + - To examine all available settings options, a preferences dialog has been introduced. + - The chosen preferences/settings are now persistent, so when starting the application, + the last used settings are applied. + * Settings options + - Game modes (Human vs Computer or Computer versus Human) + - To get a fair chance you may select a weaker solver strength level for your computer + opponent ;-) + - Let an impartial part :-) of your computer determine the corresponding hints for the + computer's guess. This option affects only Computer vs. Human games. If checked, you + only have to place your secret combination. Then the rest of the game runs automatically + until the end. + - To better watch your computer trying hard to break your code, you may + define a timeout between the guesses + - Select letters or numbers as text indicators and - if convenient - do + not use colors as indicators at all - but it's still ColorCode ;-) + * Layout/Design + - Some minor changes and new buttons for the second game mode. + + +* 0.5.5 released, October 31, 2009 + * Summary + - Accessibility and usability improvements + * Settings options + - For the color sensitive of us ;-) the posibility to change the color order by drag and drop + has been added. + - Press CTRL while dragging to flip two colors or CTRL+SHIFT to cyclic shift the color order. + You can do this even while a game is running - the whole existing display will change. + - New 'Reset Color Order' option in the settings menu to revert your changes. + - Also - and more important - for the more text aimed a settings option has been added, + to toggle the display of letter indicators for the different peg colors. + - Make the documentations page accessible from the game's help menu. + * Layout/Design + - Some minor changes. + + +* 0.5 released, October 21, 2009 + * Summary + - The number of columns in the game is now customizable. The column count can be any number + from 2 untill 5. + - Updated translation files + * Solver + - Changed how the solver determines the first guess. Also - for the following really calculated + guesses - if the number of possibilities is very high (mostly at the early phase of a 10 colors/ + 5 columns game) the solver will automatically fallback to a weaker algorithm until the number + of possibilities has been narrowed, to reduce calculating time + * Layout/Design + - Some minor changes to handle the variable number of columns. Added toolbar controls to enable + the change of all level related settings here. The statusbar now permanently shows the current + game's settings. + + +* 0.4 released, October 7, 2009 + * Summary + - The GUI has been changed completely and the Usability was improved by adding some keyboard + shortcuts for often needed interactions. + - Added czech translation. Thanks to Pavel Fric. + * Fixes + - To avoid those 'QGraphicsItem::ungrabMouse: not a mouse grabber' warnings emit the mouse event + only if the hint button hasn't been disabled just before ... + * License + - The License had been changed from the GPL v2 to GPL v3. + * Layout/Design + - Complete Change, so all paint methods had to be changed and optimized. The background is now + drawn by its own class, no more brushed metall background image anymore. + + +* 0.3 released, September 26, 2009 + * Summary + - Introduced a rather perfect MasterMind solver. It will watch any move you take and any hints + you have gotten, so you can at any time in a running game let your computer guess for you. + Of course you can change or discard it's suggestion :-) . + * Solver + - The solver has 3 built in levels of stregth. For the suggestions, currently only the most + powerfull is used. For the first guess it will use a reasonable random guess based on pre- + calculated combinations to reduce computation time. + * Layout/Design + - Make the solver's guess action accessible at the toolbar. + + +* 0.2 released, September 10, 2009 + * Summary + - Added 3 levels of difficulty (Easy, Medium, Hard) based on the possibility to change the + available number of colors for a game. You can play games with 6, 8 or 10 colors. + * Layout/Design + - Added a combo-box (select) control to the toolbar, to easily access the level (color count) + settings. + - Enable hiding the menubar, toolbar and statusbar. + - Changed to a centered layout (message display and game board). + + +* 0.1 released, September 6, 2009 + * Summary + - This is the initial release of ColorCode, a free MasterMind clone. Try to guess a combination + of 8 colors within at most 10 guesses. + - You may allow or not pegs of the same color. You can fill the rows by random or duplicate + a previous one. + * GUI + - English and German translations are available. + + + + + diff --git a/plugins/ColorCode_plugin/colorcode.cpp b/plugins/ColorCode_plugin/colorcode.cpp new file mode 100644 index 000000000..e1dbd9bce --- /dev/null +++ b/plugins/ColorCode_plugin/colorcode.cpp @@ -0,0 +1,2233 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include + +#include "settings.h" +#include "ccsolver.h" +#include "colorcode.h" +#include "colorpeg.h" +#include "pegrow.h" +#include "rowhint.h" +#include "msg.h" +#include "background.h" +#include "about.h" +#include "prefdialog.h" +#include "solutionrow.h" +#include "graphicsbtn.h" + +using namespace std; + +const int IdRole = Qt::UserRole; + +volatile bool ColorCode::mNoAct = false; + +const int ColorCode::STATE_RUNNING = 0; +const int ColorCode::STATE_WON = 1; +const int ColorCode::STATE_LOST = 2; +const int ColorCode::STATE_GAVE_UP = 3; +const int ColorCode::STATE_ERROR = 4; + +const int ColorCode::MODE_HVM = 0; +const int ColorCode::MODE_MVH = 1; + +const int ColorCode::MAX_COLOR_CNT = 10; + +const int ColorCode::LAYER_BG = 1; +const int ColorCode::LAYER_ROWS = 2; +const int ColorCode::LAYER_HINTS = 3; +const int ColorCode::LAYER_SOL = 4; +const int ColorCode::LAYER_MSG = 5; +const int ColorCode::LAYER_PEGS = 6; +const int ColorCode::LAYER_BTNS = 7; +const int ColorCode::LAYER_DRAG = 8; + +const int ColorCode::LEVEL_SETTINGS[5][3] = { + { 2, 2, 1}, + { 4, 3, 0}, + { 6, 4, 1}, + { 8, 4, 1}, + {10, 5, 1} + }; + +int ColorCode::mColorCnt = 0; +int ColorCode::mPegCnt = 0; +int ColorCode::mDoubles = 1; +int ColorCode::mXOffs = 0; +int ColorCode::mMaxZ = 0; +int ColorCode::mLevel = -1; +int ColorCode::mGameMode = ColorCode::MODE_HVM; + +ColorCode::ColorCode() +{ + QTime midnight(0, 0, 0); + qsrand(midnight.secsTo(QTime::currentTime())); + + QCoreApplication::setOrganizationName("dirks"); + QCoreApplication::setOrganizationDomain("laebisch.com"); + QCoreApplication::setApplicationName("colorcode"); + + mPrefDialog = NULL; + mSettings = new Settings(); + + ROW_CNT = 10; + ROW_Y0 = 130; + + mOrigSize = NULL; + + setWindowTitle(tr("ColorCode")); + setWindowIcon(QIcon(QPixmap(":/img/cc16.png"))); + setIconSize(QSize(16, 16)); + + mMenuBar = menuBar(); + + // as long as menuBar's size isn invalid populated initially ... +#ifdef Q_WS_X11 + scene = new QGraphicsScene(0, 0, 320, 580); +#else + scene = new QGraphicsScene(0, 0, 320, 560); +#endif + + scene->setBackgroundBrush(QBrush(QColor("#b0b1b3"))); + + view = new QGraphicsView; + view->setScene(scene); + view->setGeometry(0, 0, 320, 560); + view->setDragMode(QGraphicsView::NoDrag); + view->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); + view->setContextMenuPolicy(Qt::NoContextMenu); + view->setAlignment(Qt::AlignCenter); + view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setCentralWidget(view); + + mBg = new BackGround(); + scene->addItem(mBg); + mBg->setPos(0, 0); + mBg->setZValue(LAYER_BG); + + mMsg = new Msg; + scene->addItem(mMsg); + mMsg->setPos(20, 0); + mMsg->setZValue(LAYER_MSG); + + mDoneBtn = new GraphicsBtn; + mDoneBtn->SetLabel(tr("Done")); + scene->addItem(mDoneBtn); + mDoneBtn->setPos(84, 118); + mDoneBtn->setZValue(LAYER_BTNS); + mDoneBtn->ShowBtn(false); + connect(mDoneBtn, SIGNAL(BtnPressSignal(GraphicsBtn *)), this, SLOT(DoneBtnPressSlot(GraphicsBtn *))); + + mOkBtn = new GraphicsBtn; + mOkBtn->SetWidth(38); + mOkBtn->SetLabel("ok"); + scene->addItem(mOkBtn); + mOkBtn->setPos(5, 329); + mOkBtn->setZValue(LAYER_BTNS); + mOkBtn->ShowBtn(false); + connect(mOkBtn, SIGNAL(BtnPressSignal(GraphicsBtn *)), this, SLOT(DoneBtnPressSlot(GraphicsBtn *))); + + mSolver = new CCSolver(this); + mHintsDelayTimer = new QTimer(); + mHintsDelayTimer->setSingleShot(true); + mHintsDelayTimer->setInterval(500); + connect(mHintsDelayTimer, SIGNAL(timeout()), this, SLOT(SetAutoHintsSlot())); + + mCurRow = NULL; + mColorCnt = 0; + mGameCnt = 0; + mGameId = 0; + mGuessCnt = 0; + mHideColors = false; + mSolverStrength = CCSolver::STRENGTH_HIGH; + + InitTypesMap(); + InitActions(); + InitMenus(); + InitToolBars(); + + statusBar()->setStyleSheet("QStatusBar::item { border: 0px solid black }; "); + mStatusLabel = new QLabel(); + statusBar()->addPermanentWidget(mStatusLabel, 0); + + InitSolution(); + InitRows(); + InitPegBtns(); + + ApplySettings(); + + NewGame(); +} + +ColorCode::~ColorCode() +{ + mSettings->WriteSettings(); +} + +void ColorCode::InitSolution() +{ + mSolutionRow = new SolutionRow(); + mSolutionRow->setPos(50, 70); + mSolutionRow->setZValue(LAYER_SOL); + scene->addItem(mSolutionRow); + connect(mSolutionRow, SIGNAL(RemovePegSignal(ColorPeg*)), this, SLOT(RemovePegSlot(ColorPeg*))); + connect(mSolutionRow, SIGNAL(RowSolutionSignal(int)), this, SLOT(RowSolutionSlot(int))); +} + +void ColorCode::InitRows() +{ + PegRow* row; + RowHint* hint; + + int xpos = 60; + int ypos = ROW_Y0; + int i; + + for (i = 0; i < ROW_CNT; ++i) + { + row = new PegRow(); + row->SetIx(i); + row->setPos(QPoint(xpos, ypos + (ROW_CNT - (i + 1)) * 40)); + row->setZValue(LAYER_ROWS); + row->SetActive(false); + scene->addItem(row); + mPegRows[i] = row; + connect(row, SIGNAL(RemovePegSignal(ColorPeg*)), this, SLOT(RemovePegSlot(ColorPeg*))); + connect(row, SIGNAL(RowSolutionSignal(int)), this, SLOT(RowSolutionSlot(int))); + + hint = new RowHint; + hint->SetIx(i); + hint->setPos(QPoint(4, ypos + (ROW_CNT - (i + 1)) * 40)); + hint->setZValue(LAYER_HINTS); + hint->SetActive(false); + scene->addItem(hint); + mHintBtns[i] = hint; + connect(hint, SIGNAL(HintPressedSignal(int)), this, SLOT(HintPressedSlot(int))); + } +} + +void ColorCode::InitPegBtns() +{ + for (int i = 0; i < MAX_COLOR_CNT; ++i) + { + mPegBtns[i] = NULL; + } +} + +void ColorCode::InitTypesMap() +{ + int ix; + + QRadialGradient grad = QRadialGradient(20, 20, 40, 5, 5); + QRadialGradient grad2 = QRadialGradient(18, 18, 18, 12, 12); + + ix = 0; + mTypesMap[ix] = new PegType; + grad.setColorAt(0.0, QColor("#FFFF80")); + grad.setColorAt(1.0, QColor("#C05800")); + mGradMap[ix] = grad; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::green; + + ix = 1; + mTypesMap[ix] = new PegType; + grad.setColorAt(0.0, QColor("#FF3300")); + grad.setColorAt(1.0, QColor("#400040")); + mGradMap[ix] = grad; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::green; + + ix = 2; + mTypesMap[ix] = new PegType; + grad.setColorAt(0.0, QColor("#33CCFF")); + grad.setColorAt(1.0, QColor("#000080")); + mGradMap[ix] = grad; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::red; + + ix = 3; + mTypesMap[ix] = new PegType; + grad2.setColorAt(0.0, Qt::white); + grad2.setColorAt(0.5, QColor("#f8f8f0")); + grad2.setColorAt(0.7, QColor("#f0f0f0")); + grad2.setColorAt(1.0, QColor("#d0d0d0")); + mGradMap[ix] = grad2; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::green; + + ix = 4; + mTypesMap[ix] = new PegType; + grad.setColorAt(0.0, QColor("#808080")); + grad.setColorAt(1.0, Qt::black); + mGradMap[ix] = grad; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::red; + + ix = 5; + mTypesMap[ix] = new PegType; + grad.setColorAt(0.0, QColor("#66FF33")); + grad.setColorAt(1.0, QColor("#385009")); + mGradMap[ix] = grad; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::red; + + ix = 6; + mTypesMap[ix] = new PegType; + grad.setColorAt(0.0, QColor("#FF9900")); + grad.setColorAt(1.0, QColor("#A82A00")); + mGradMap[ix] = grad; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::red; + + ix = 7; + mTypesMap[ix] = new PegType; + grad.setColorAt(0.0, QColor("#BA88FF")); + grad.setColorAt(1.0, QColor("#38005D")); + mGradMap[ix] = grad; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::green; + + ix = 8; + mTypesMap[ix] = new PegType; + grad.setColorAt(0.0, QColor("#00FFFF")); + grad.setColorAt(1.0, QColor("#004040")); + mGradMap[ix] = grad; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::green; + + ix = 9; + mTypesMap[ix] = new PegType; + grad.setColorAt(0.0, QColor("#FFC0FF")); + grad.setColorAt(1.0, QColor("#800080")); + mGradMap[ix] = grad; + mTypesMap[ix]->grad = &mGradMap[ix]; + mTypesMap[ix]->ix = ix; + mTypesMap[ix]->pencolor = Qt::green; + + for (ix = 0; ix < MAX_COLOR_CNT; ++ix) + { + mTypesMap[ix]->let = 'A' + ix; + mGradBuff[ix] = mGradMap[ix]; + } +} + +void ColorCode::InitActions() +{ + mActNewGame = new QAction(tr("&New Game"), this); + mActNewGame->setIcon(QIcon(":/img/document-new.png")); + mActNewGame->setShortcut(tr("Ctrl+N")); + connect(mActNewGame, SIGNAL(triggered()), this, SLOT(NewGameSlot())); + + mActRestartGame = new QAction(tr("&Restart Game"), this); + mActRestartGame->setIcon(QIcon(":/img/view-refresh.png")); + mActRestartGame->setShortcut(tr("Ctrl+Shift+N")); + connect(mActRestartGame, SIGNAL(triggered()), this, SLOT(RestartGameSlot())); + + mActGiveIn = new QAction(tr("&Throw In The Towel"), this); + mActGiveIn->setIcon(QIcon(":/img/face-sad.png")); + mActGiveIn->setShortcut(tr("Ctrl+G")); + connect(mActGiveIn, SIGNAL(triggered()), this, SLOT(GiveInSlot())); + + mActExit = new QAction(tr("E&xit"), this); + mActExit->setIcon(QIcon(":/img/application-exit.png")); + mActExit->setShortcut(tr("Ctrl+Q")); + connect(mActExit, SIGNAL(triggered()), this, SLOT(close())); + + mActShowToolbar = new QAction(tr("Show Toolbar"), this); + mActShowToolbar->setCheckable(true); + mActShowToolbar->setChecked(true); + mActShowToolbar->setShortcut(tr("Ctrl+T")); + connect(mActShowToolbar, SIGNAL(triggered()), this, SLOT(ShowToolbarSlot())); + + mActShowMenubar = new QAction(tr("Show Menubar"), this); + mActShowMenubar->setCheckable(true); + mActShowMenubar->setChecked(true); + mActShowMenubar->setShortcut(tr("Ctrl+M")); + connect(mActShowMenubar, SIGNAL(triggered()), this, SLOT(ShowMenubarSlot())); + + mActShowStatusbar = new QAction(tr("Show Statusbar"), this); + mActShowStatusbar->setCheckable(true); + mActShowStatusbar->setChecked(true); + mActShowStatusbar->setShortcut(tr("Ctrl+S")); + connect(mActShowStatusbar, SIGNAL(triggered()), this, SLOT(ShowStatusbarSlot())); + + mActResetColorsOrder = new QAction(tr("Reset Color Order"), this); + mActResetColorsOrder->setShortcut(tr("Ctrl+Shift+R")); + connect(mActResetColorsOrder, SIGNAL(triggered()), this, SLOT(ResetColorsOrderSlot())); + + mActShowLetter = new QAction(tr("Show Indicators"), this); + mActShowLetter->setCheckable(true); + mActShowLetter->setChecked(false); + mActShowLetter->setShortcut(tr("Ctrl+Shift+L")); + connect(mActShowLetter, SIGNAL(triggered()), this, SLOT(SetIndicators())); + + mActSameColor = new QAction(tr("Allow Pegs of the Same Color"), this); + mActSameColor->setCheckable(true); + mActSameColor->setChecked(true); + mActSameColor->setShortcut(tr("Ctrl+Shift+C")); + connect(mActSameColor, SIGNAL(triggered(bool)), this, SLOT(SameColorSlot(bool))); + + mActSameColorIcon = new QAction(tr("Allow Pegs of the Same Color"), this); + mActSameColorIcon->setCheckable(true); + mActSameColorIcon->setChecked(true); + mActSameColorIcon->setToolTip(tr("Disallow Pegs of the Same Color")); + mActSameColorIcon->setIcon(QIcon(":/img/same_color_1.png")); + connect(mActSameColorIcon, SIGNAL(triggered(bool)), this, SLOT(SameColorSlot(bool))); + + mActAutoClose = new QAction(tr("Close Rows when the last Peg is placed"), this); + mActAutoClose->setCheckable(true); + mActAutoClose->setChecked(false); + mActAutoClose->setShortcut(tr("Ctrl+L")); + connect(mActAutoClose, SIGNAL(triggered()), this, SLOT(AutoCloseSlot())); + + mActAutoHints = new QAction(tr("Set Hints automatically"), this); + mActAutoHints->setCheckable(true); + mActAutoHints->setChecked(false); + mActAutoHints->setShortcut(tr("Ctrl+Shift+H")); + connect(mActAutoHints, SIGNAL(triggered()), this, SLOT(AutoHintsSlot())); + + mLaunchHelpAction = new QAction(tr("Online &Help"), this); + mLaunchHelpAction->setIcon(QIcon(":/img/help.png")); + mLaunchHelpAction->setShortcut(tr("F1")); + connect(mLaunchHelpAction, SIGNAL(triggered()), this, SLOT(OnlineHelpSlot())); + + mActAbout = new QAction(tr("About &ColorCode"), this); + mActAbout->setIcon(QIcon(":/img/help-about.png")); + mActAbout->setShortcut(tr("Ctrl+A")); + connect(mActAbout, SIGNAL(triggered()), this, SLOT(AboutSlot())); + + mActAboutQt = new QAction(tr("About &Qt"), this); + mActAboutQt->setIcon(QIcon(":/img/qt.png")); + mActAboutQt->setShortcut(tr("Ctrl+I")); + connect(mActAboutQt, SIGNAL(triggered()), this, SLOT(AboutQtSlot())); + + mActRandRow = new QAction(tr("Fill Row by Random"), this); + mActRandRow->setIcon(QIcon(":/img/system-switch-user.png")); + mActRandRow->setShortcut(tr("Ctrl+R")); + connect(mActRandRow, SIGNAL(triggered()), this, SLOT(RandRowSlot())); + + mActPrevRow = new QAction(tr("Duplicate Previous Row"), this); + mActPrevRow->setIcon(QIcon(":/img/edit-copy.png")); + mActPrevRow->setShortcut(tr("Ctrl+D")); + connect(mActPrevRow, SIGNAL(triggered()), this, SLOT(PrevRowSlot())); + + mActClearRow = new QAction(tr("Clear Row"), this); + mActClearRow->setIcon(QIcon(":/img/edit-clear.png")); + mActClearRow->setShortcut(tr("Ctrl+C")); + connect(mActClearRow, SIGNAL(triggered()), this, SLOT(ClearRowSlot())); + + mActLevelEasy = new QAction(tr("Beginner (2 Colors, 2 Slots, Doubles)"), this); + mActLevelEasy->setData(0); + mActLevelEasy->setCheckable(true); + mActLevelEasy->setChecked(false); + connect(mActLevelEasy, SIGNAL(triggered()), this, SLOT(SetLevelSlot())); + + mActLevelClassic = new QAction(tr("Easy (4 Colors, 3 Slots, No Doubles)"), this); + mActLevelClassic->setData(1); + mActLevelClassic->setCheckable(true); + mActLevelClassic->setChecked(false); + connect(mActLevelClassic, SIGNAL(triggered()), this, SLOT(SetLevelSlot())); + + mActLevelMedium = new QAction(tr("Classic (6 Colors, 4 Slots, Doubles)"), this); + mActLevelMedium->setData(2); + mActLevelMedium->setCheckable(true); + mActLevelMedium->setChecked(true); + connect(mActLevelMedium, SIGNAL(triggered()), this, SLOT(SetLevelSlot())); + + mActLevelChallenging = new QAction(tr("Challenging (8 Colors, 4 Slots, Doubles)"), this); + mActLevelChallenging->setData(3); + mActLevelChallenging->setCheckable(true); + mActLevelChallenging->setChecked(false); + connect(mActLevelChallenging, SIGNAL(triggered()), this, SLOT(SetLevelSlot())); + + mActLevelHard = new QAction(tr("Hard (10 Colors, 5 Slots, Doubles)"), this); + mActLevelHard->setData(4); + mActLevelHard->setCheckable(true); + mActLevelHard->setChecked(false); + connect(mActLevelHard, SIGNAL(triggered()), this, SLOT(SetLevelSlot())); + + mActSetGuess = new QAction(tr("Computer's Guess"), this); + mActSetGuess->setIcon(QIcon(":/img/business_user.png")); + mActSetGuess->setShortcut(tr("Ctrl+H")); + connect(mActSetGuess, SIGNAL(triggered()), this, SLOT(SetGuessSlot())); + + mActSetHints = new QAction(tr("Rate it for me"), this); + mActSetHints->setIcon(QIcon(":/img/icon_female16.png")); + mActSetHints->setShortcut(tr("Ctrl+H")); + connect(mActSetHints, SIGNAL(triggered()), this, SLOT(SetHintsSlot())); + + mActModeHvM = new QAction(tr("Human vs Computer"), this); + mActModeHvM->setData(MODE_HVM); + mActModeHvM->setCheckable(true); + mActModeHvM->setChecked(true); + connect(mActModeHvM, SIGNAL(triggered()), this, SLOT(SetGameModeSlot())); + + mActModeMvH = new QAction(tr("Computer vs Human"), this); + mActModeMvH->setData(MODE_MVH); + mActModeMvH->setCheckable(true); + mActModeMvH->setChecked(false); + connect(mActModeMvH, SIGNAL(triggered()), this, SLOT(SetGameModeSlot())); + + mActPreferences = new QAction(tr("Preferences"), this); + mActPreferences->setIcon(QIcon(":/img/configure.png")); + mActPreferences->setShortcut(tr("Ctrl+P")); + connect(mActPreferences, SIGNAL(triggered()), this, SLOT(OpenPreferencesSlot())); +} + +void ColorCode::InitMenus() +{ + mMenuGame = mMenuBar->addMenu(tr("&Game")); + mMenuGame->addAction(mActNewGame); + mMenuGame->addAction(mActRestartGame); + mMenuGame->addAction(mActGiveIn); + mMenuGame->addSeparator(); + mMenuGame->addAction(mActExit); + + mMenuRow = mMenuBar->addMenu(tr("&Row")); + mMenuRow->addAction(mActRandRow); + mMenuRow->addAction(mActPrevRow); + mMenuRow->addAction(mActClearRow); + mMenuRow->addSeparator(); + mMenuRow->addAction(mActSetGuess); + mMenuRow->addAction(mActSetHints); + connect(mMenuRow, SIGNAL(aboutToShow()), this, SLOT(UpdateRowMenuSlot())); + + mMenuSettings = mMenuBar->addMenu(tr("&Settings")); + + mMenuModes = mMenuSettings->addMenu(tr("Game Mode")); + mActGroupModes = new QActionGroup(mMenuModes); + mActGroupModes->setExclusive(true); + mActGroupModes->addAction(mActModeHvM); + mActGroupModes->addAction(mActModeMvH); + QList modeacts = mActGroupModes->actions(); + mMenuModes->addActions(modeacts); + mMenuSettings->addSeparator(); + + mMenuSettings->addAction(mActShowMenubar); + mMenuSettings->addAction(mActShowToolbar); + mMenuSettings->addAction(mActShowStatusbar); + mMenuSettings->addSeparator(); + mMenuSettings->addAction(mActResetColorsOrder); + mMenuSettings->addAction(mActShowLetter); + mMenuSettings->addSeparator(); + + mMenuLevels = mMenuSettings->addMenu(tr("Level Presets")); + mActGroupLevels = new QActionGroup(mMenuLevels); + mActGroupLevels->addAction(mActLevelEasy); + mActGroupLevels->addAction(mActLevelClassic); + mActGroupLevels->addAction(mActLevelMedium); + mActGroupLevels->addAction(mActLevelChallenging); + mActGroupLevels->addAction(mActLevelHard); + QList levelacts = mActGroupLevels->actions(); + mMenuLevels->addActions(levelacts); + mMenuSettings->addSeparator(); + + mMenuSettings->addAction(mActSameColor); + mMenuSettings->addSeparator(); + + mMenuSettings->addAction(mActAutoClose); + mMenuSettings->addAction(mActAutoHints); + + mMenuSettings->addSeparator(); + mMenuSettings->addAction(mActPreferences); + + mMenuHelp = mMenuBar->addMenu(tr("&Help")); + mMenuHelp->addAction(mLaunchHelpAction); + mMenuHelp->addSeparator(); + mMenuHelp->addAction(mActAbout); + mMenuHelp->addAction(mActAboutQt); + + mMenuRowContext = new QMenu(); + mMenuRowContext->addAction(mActRandRow); + mMenuRowContext->addAction(mActPrevRow); + mMenuRowContext->addAction(mActClearRow); + mMenuRowContext->addSeparator(); + mMenuRowContext->addAction(mActSetGuess); + mMenuRowContext->addSeparator(); + mMenuRowContext->addAction(mActNewGame); + mMenuRowContext->addAction(mActRestartGame); + mMenuRowContext->addAction(mActGiveIn); + mMenuRowContext->addSeparator(); + mMenuRowContext->addAction(mActExit); + + addActions(mMenuBar->actions()); +} + +void ColorCode::InitToolBars() +{ + mGameToolbar = addToolBar(tr("Game")); + mGameToolbar->setAllowedAreas(Qt::NoToolBarArea); + mGameToolbar->setFloatable(false); + mGameToolbar->setIconSize(QSize(16, 16)); + mGameToolbar->setMovable(false); + mGameToolbar->addAction(mActNewGame); + mGameToolbar->addAction(mActRestartGame); + mGameToolbar->addAction(mActGiveIn); + mGameToolbar->addSeparator(); + mGameToolbar->addAction(mActSetGuess); + mGameToolbar->addAction(mActSetHints); + + mColorCntCmb = new QComboBox(); + mColorCntCmb->setLayoutDirection(Qt::LeftToRight); + mColorCntCmb->setFixedWidth(84); + mColorCntCmb->addItem("2 " + tr("Colors"), 2); + mColorCntCmb->addItem("3 " + tr("Colors"), 3); + mColorCntCmb->addItem("4 " + tr("Colors"), 4); + mColorCntCmb->addItem("5 " + tr("Colors"), 5); + mColorCntCmb->addItem("6 " + tr("Colors"), 6); + mColorCntCmb->addItem("7 " + tr("Colors"), 7); + mColorCntCmb->addItem("8 " + tr("Colors"), 8); + mColorCntCmb->addItem("9 " + tr("Colors"), 9); + mColorCntCmb->addItem("10 " + tr("Colors"), 10); + mColorCntCmb->setCurrentIndex(6); + connect(mColorCntCmb, SIGNAL(currentIndexChanged(int)), this, SLOT(ColorCntChangedSlot())); + + mPegCntCmb = new QComboBox(); + mPegCntCmb->setLayoutDirection(Qt::LeftToRight); + mPegCntCmb->setFixedWidth(76); + mPegCntCmb->addItem("2 " + tr("Slots"), 2); + mPegCntCmb->addItem("3 " + tr("Slots"), 3); + mPegCntCmb->addItem("4 " + tr("Slots"), 4); + mPegCntCmb->addItem("5 " + tr("Slots"), 5); + mPegCntCmb->setCurrentIndex(2); + connect(mPegCntCmb, SIGNAL(currentIndexChanged(int)), this, SLOT(PegCntChangedSlot())); + + mLevelToolbar = addToolBar(tr("Level")); + mLevelToolbar->setAllowedAreas(Qt::NoToolBarArea); + mLevelToolbar->setFloatable(false); + mLevelToolbar->setIconSize(QSize(16, 16)); + mLevelToolbar->setMovable(false); + mLevelToolbar->setLayoutDirection(Qt::RightToLeft); + mLevelToolbar->addWidget(mColorCntCmb); + QWidget* spacer = new QWidget(); + spacer->setMinimumWidth(4); + mLevelToolbar->addWidget(spacer); + mLevelToolbar->addWidget(mPegCntCmb); + QWidget* spacer2 = new QWidget(); + spacer2->setMinimumWidth(4); + mLevelToolbar->addWidget(spacer2); + mLevelToolbar->addAction(mActSameColorIcon); +} + +void ColorCode::ApplySettings() +{ + bool restart = NeedsRestart(); + mNoAct = true; + + mActShowToolbar->setChecked(mSettings->mShowToolBar); + ShowToolbarSlot(); + mActShowMenubar->setChecked(mSettings->mShowMenuBar); + ShowMenubarSlot(); + mActShowStatusbar->setChecked(mSettings->mShowStatusBar); + ShowStatusbarSlot(); + mActShowLetter->setChecked(mSettings->mShowIndicators); + SetIndicators(); + + mActAutoClose->setChecked(mSettings->mAutoClose); + mActAutoHints->setChecked(mSettings->mAutoHints); + + SetSameColor(mSettings->mSameColors); + int i; + i = mColorCntCmb->findData(mSettings->mColorCnt); + if (i != -1 && mColorCntCmb->currentIndex() != i) + { + mColorCntCmb->setCurrentIndex(i); + } + i = mPegCntCmb->findData(mSettings->mPegCnt); + if (i != -1 && mPegCntCmb->currentIndex() != i) + { + mPegCntCmb->setCurrentIndex(i); + } + CheckLevel(); + + if (mSettings->mGameMode == MODE_HVM) + { + mActModeHvM->setChecked(true); + } + else + { + mActModeMvH->setChecked(true); + } + + mHintsDelayTimer->setInterval(mSettings->mHintsDelay); + + mNoAct = false; + + if (restart) + { + TryNewGame(); + } +} + +void ColorCode::TryNewGame() +{ + int r = QMessageBox::Yes; + if (GamesRunning()) + { + r = QMessageBox::question( this, + tr("Message"), + tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); + } + + if (r == QMessageBox::Yes) + { + NewGame(); + } +} + +bool ColorCode::NeedsRestart() const +{ + bool need = false; + + if ( mSettings->mSameColors != mActSameColor->isChecked() + || mSettings->mColorCnt != mColorCnt + || mSettings->mPegCnt != mPegCnt + || mSettings->mGameMode != mGameMode + || (mGameMode == MODE_MVH && mSolverStrength != mSettings->mSolverStrength) ) + { + need = true; + } + + return need; +} + +void ColorCode::contextMenuEvent(QContextMenuEvent* e) +{ + + QList list = view->items(view->mapFromGlobal(e->globalPos())); + int i = 0; + bool isrow = false; + if (mGameState == STATE_RUNNING && mCurRow != NULL) + { + for (i = 0; i < list.size(); ++i) + { + if (list.at(i) == mCurRow || list.at(i) == mHintBtns[mCurRow->GetIx()]) + { + isrow = true; + break; + } + } + } + + if (isrow) + { + UpdateRowMenuSlot(); + mMenuRowContext->exec(e->globalPos()); + } + else + { + mMenuGame->exec(e->globalPos()); + } +} + +void ColorCode::resizeEvent (QResizeEvent* e) +{ + Q_UNUSED(e); + Scale(); +} + +void ColorCode::keyPressEvent(QKeyEvent *e) +{ + if (mCurRow == NULL || mGameState != STATE_RUNNING) + { + return; + } + + switch (e->key()) + { + case Qt::Key_Return: + case Qt::Key_Enter: + if (mGameMode == MODE_HVM) + { + int ix = mCurRow->GetIx(); + if (mHintBtns[ix]->mActive) + { + std::vector s = mCurRow->GetSolution(); + if (s.size() == (unsigned) mPegCnt) + { + mHintBtns[ix]->SetActive(false); + HintPressedSlot(ix); + } + } + } + else if (mGameMode == MODE_MVH) + { + if (mDoneBtn->isVisible() || mOkBtn->isVisible()) + { + DoneBtnPressSlot(); + } + } + break; + } +} + +void ColorCode::UpdateRowMenuSlot() +{ + if (mGameMode == MODE_HVM) + { + if (mGameState != STATE_RUNNING || mCurRow == NULL) + { + mActRandRow->setEnabled(false); + mActPrevRow->setEnabled(false); + mActClearRow->setEnabled(false); + mActSetGuess->setEnabled(false); + return; + } + else + { + mActRandRow->setEnabled(true); + } + + if (mCurRow->GetIx() < 1) + { + mActPrevRow->setEnabled(false); + } + else + { + mActPrevRow->setEnabled(true); + } + + if (mCurRow->GetPegCnt() == 0) + { + mActClearRow->setEnabled(false); + } + else + { + mActClearRow->setEnabled(true); + } + } + else if (mGameMode == MODE_MVH) + { + if (mGameState == STATE_RUNNING && mCurRow == mSolutionRow) + { + mActRandRow->setEnabled(true); + mActClearRow->setEnabled(true); + } + else + { + mActRandRow->setEnabled(false); + mActClearRow->setEnabled(false); + } + } +} + +void ColorCode::RestartGameSlot() +{ + if (mGameMode == MODE_HVM) + { + ResetRows(); + SetState(STATE_RUNNING); + + mCurRow = NULL; + mSolver->RestartGame(); + NextRow(); + } + else if (mGameMode == MODE_MVH) + { + mHintsDelayTimer->stop(); + mOkBtn->ShowBtn(false); + ResetRows(); + SetState(STATE_RUNNING); + + mCurRow = NULL; + mSolver->NewGame(mColorCnt, mPegCnt, mDoubles, mSolverStrength, ROW_CNT); + mSolutionRow->OpenRow(); + GetSolution(); + RowSolutionSlot(mSolutionRow->GetIx()); + } +} + +void ColorCode::NewGameSlot() +{ + if (mGameState == STATE_RUNNING && mCurRow != NULL) + { + int r = QMessageBox::warning( this, + tr("New Game"), + tr("Do you want to give in\nand start a new Game?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (r == QMessageBox::Yes) + { + NewGame(); + } + } + else + { + NewGame(); + } +} + +void ColorCode::GiveInSlot() +{ + int r = QMessageBox::Yes; + if (mGameState == STATE_RUNNING && mCurRow != NULL) + { + r = QMessageBox::warning( this, + tr("Give In"), + tr("Do you really want to give in?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + } + + if (r == QMessageBox::Yes) + { + SetState(STATE_GAVE_UP); + + if (mCurRow != NULL) + { + mCurRow->CloseRow(); + mHintBtns[mCurRow->GetIx()]->SetActive(false); + } + + ResolveGame(); + } +} + +void ColorCode::OpenPreferencesSlot() +{ + if (mPrefDialog == NULL) + { + CreatePrefDialog(); + } + if (mPrefDialog == NULL) + { + return; + } + + mSettings->SaveLastSettings(); + mPrefDialog->SetSettings(); + int r = mPrefDialog->exec(); + if (r == QDialog::Accepted) + { + ApplySettings(); + } + else + { + mSettings->RestoreLastSettings(); + } +} + +void ColorCode::OnlineHelpSlot() +{ + QDesktopServices::openUrl(QUrl("http://colorcode.laebisch.com/documentation", QUrl::TolerantMode)); +} + +void ColorCode::AboutSlot() +{ + About ab(this); + ab.exec(); +} + +void ColorCode::AboutQtSlot() +{ + QMessageBox::aboutQt( this, + tr("About Qt")); +} + +void ColorCode::ShowToolbarSlot() +{ + mSettings->mShowToolBar = mActShowToolbar->isChecked(); + if (!mActShowToolbar->isChecked()) + { + mGameToolbar->hide(); + mLevelToolbar->hide(); + } + else + { + mGameToolbar->show(); + mLevelToolbar->show(); + } + Scale(); +} + +void ColorCode::ShowMenubarSlot() +{ + mSettings->mShowMenuBar = mActShowMenubar->isChecked(); + if (!mActShowMenubar->isChecked()) + { + mMenuBar->hide(); + } + else + { + mMenuBar->show(); + } + Scale(); +} + +void ColorCode::ShowStatusbarSlot() +{ + mSettings->mShowStatusBar = mActShowStatusbar->isChecked(); + if (!mActShowStatusbar->isChecked()) + { + statusBar()->hide(); + } + else + { + statusBar()->show(); + } + Scale(); +} + +void ColorCode::ResetColorsOrderSlot() +{ + int ix; + for (ix = 0; ix < MAX_COLOR_CNT; ++ix) + { + mGradMap[ix] = mGradBuff[ix]; + } + scene->update(scene->sceneRect()); +} + +void ColorCode::SetIndicators() +{ + bool checked = mActShowLetter->isChecked(); + mSettings->mShowIndicators = checked; + if (!mSettings->mShowIndicators) + { + mHideColors = false; + } + else + { + mHideColors = mSettings->mHideColors; + } + vector::iterator it; + for (it = mAllPegs.begin(); it < mAllPegs.end(); it++) + { + (*it)->SetIndicator(checked, mSettings->mIndicatorType, mHideColors); + } +} + +void ColorCode::SameColorSlot(bool checked) +{ + if (mNoAct) + { + return; + } + + SetSameColor(checked); + + int r = QMessageBox::Yes; + if (GamesRunning()) + { + r = QMessageBox::question( this, + tr("Message"), + tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); + } + + if (r == QMessageBox::Yes) + { + NewGame(); + } +} + +void ColorCode::AutoCloseSlot() +{ + mSettings->mAutoClose = mActAutoClose->isChecked(); +} + +void ColorCode::AutoHintsSlot() +{ + mSettings->mAutoHints = mActAutoHints->isChecked(); +} + +void ColorCode::ColorCntChangedSlot() +{ + SetColorCnt(); + + if (mNoAct) + { + return; + } + + int r = QMessageBox::Yes; + if (GamesRunning()) + { + r = QMessageBox::question( this, + tr("Message"), + tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); + } + + if (r == QMessageBox::Yes) + { + NewGame(); + } +} + +void ColorCode::PegCntChangedSlot() +{ + SetPegCnt(); + + if (mNoAct) + { + return; + } + + int pcnt = mPegCntCmb->itemData(mPegCntCmb->currentIndex(), IdRole).toInt(); + if (pcnt == mPegCnt) + { + return; + } + + int r = QMessageBox::Yes; + if (GamesRunning()) + { + r = QMessageBox::question( this, + tr("Message"), + tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); + } + + if (r == QMessageBox::Yes) + { + NewGame(); + } +} + +void ColorCode::SetLevelSlot() +{ + mNoAct = true; + int ix = mActGroupLevels->checkedAction()->data().toInt(); + + if (ix < 0 || ix > 4) + { + return; + } + + int i; + i = mColorCntCmb->findData(LEVEL_SETTINGS[ix][0]); + if (i != -1 && mColorCntCmb->currentIndex() != i) + { + mColorCntCmb->setCurrentIndex(i); + SetColorCnt(); + } + i = mPegCntCmb->findData(LEVEL_SETTINGS[ix][1]); + if (i != -1 && mPegCntCmb->currentIndex() != i) + { + mPegCntCmb->setCurrentIndex(i); + SetPegCnt(); + } + + SetSameColor((LEVEL_SETTINGS[ix][2] == 1)); + + int r = QMessageBox::Yes; + if (GamesRunning()) + { + r = QMessageBox::question( this, + tr("Message"), + tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); + } + + mNoAct = false; + + if (r == QMessageBox::Yes) + { + NewGame(); + } +} + +void ColorCode::SetGameModeSlot() +{ + SetGameMode(); + + int r = QMessageBox::Yes; + if (GamesRunning()) + { + r = QMessageBox::question( this, + tr("Message"), + tr("The changed settings will only apply to new games!\nDo you want to give in the current and start a new Game?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); + } + + if (r == QMessageBox::Yes) + { + NewGame(); + } +} + + +void ColorCode::SetPegCnt() +{ + mSettings->mPegCnt = mPegCntCmb->itemData(mPegCntCmb->currentIndex(), IdRole).toInt(); +} + +void ColorCode::SetColorCnt() +{ + mSettings->mColorCnt = mColorCntCmb->itemData(mColorCntCmb->currentIndex(), IdRole).toInt(); +} + +void ColorCode::SetGameMode() +{ + int ix = mActGroupModes->checkedAction()->data().toInt(); + if (ix != MODE_HVM && ix != MODE_MVH) + { + return; + } + mSettings->mGameMode = ix; +} + + +void ColorCode::RemovePegSlot(ColorPeg* cp) +{ + RemovePeg(cp); +} + +void ColorCode::ShowMsgSlot(QString msg) +{ + mMsg->ShowMsg(msg); +} + +void ColorCode::PegPressSlot(ColorPeg* cp) +{ + if (cp == NULL) { return; } + + cp->setZValue(LAYER_DRAG); + + if (cp->IsBtn()) + { + cp->SetBtn(false); + mPegBtns[cp->GetPegType()->ix] = CreatePeg(cp->GetPegType()->ix); + mPegBtns[cp->GetPegType()->ix]->SetEnabled(false); + } +} + +void ColorCode::PegSortSlot(ColorPeg* cp) +{ + if (cp == NULL) { return; } + + cp->setZValue(LAYER_DRAG); + + if (cp->IsBtn()) + { + cp->SetBtn(false); + mPegBtns[cp->GetPegType()->ix] = CreatePeg(cp->GetPegType()->ix); + mPegBtns[cp->GetPegType()->ix]->SetEnabled(false); + } +} + +void ColorCode::PegReleasedSlot(ColorPeg* cp) +{ + if (cp == NULL || !cp) { return; } + + cp->setZValue(LAYER_PEGS); + scene->clearSelection(); + scene->clearFocus(); + + int i; + if (cp->GetSort() == 0) + { + bool snapped = false; + + if (mGameMode == MODE_HVM) + { + QList list = scene->items(QPointF(cp->pos().x() + 18, cp->pos().y() + 18)); + + for (i = 0; i < list.size(); ++i) + { + if (mCurRow != NULL && list.at(i) == mCurRow) + { + snapped = mCurRow->SnapCP(cp); + break; + } + } + } + else if (mGameMode == MODE_MVH) + { + snapped = mSolutionRow->SnapCP(cp); + } + + if (!snapped) + { + RemovePeg(cp); + } + } + else + { + int ystart = ROW_Y0 + (MAX_COLOR_CNT - mColorCnt) * 40; + int ix1 = qRound((qRound(cp->pos().y()) - ystart + 18) / 40); + ix1 = min(mColorCnt - 1, max(0, ix1)); + + int ix0 = cp->GetPegType()->ix; + if (ix0 != ix1) + { + QRadialGradient tmp = mGradMap[ix0]; + + if (cp->GetSort() == 1) + { + mGradMap[ix0] = mGradMap[ix1]; + } + else + { + int step = (ix1 > ix0) ? 1 : -1; + + + + for (i = ix0;; i += step) + { + mGradMap[i] = mGradMap[i + step]; + if (i == ix1 - step) + { + break; + } + } + } + + mGradMap[ix1] = tmp; + } + + RemovePeg(cp); + } + + if (!mPegBtns[cp->GetPegType()->ix]->isEnabled()) + { + mPegBtns[cp->GetPegType()->ix]->SetEnabled(true); + } +} + +void ColorCode::RowSolutionSlot(int ix) +{ + if (mGameMode == MODE_HVM) + { + if (ix == -1) { return; } + + std::vector s = mPegRows[ix]->GetSolution(); + if (s.size() == (unsigned) mPegCnt) + { + if (mActAutoClose->isChecked()) + { + HintPressedSlot(ix); + } + else + { + mHintBtns[ix]->SetActive(true); + ShowMsgSlot(tr("Press the Hint Field or Key Enter if You're done.")); + } + } + else + { + mHintBtns[ix]->SetActive(false); + ShowMsgSlot(tr("Place Your pegs ...")); + } + } + else if (mGameMode == MODE_MVH) + { + if (ix == -1) + { + std::vector s = mSolutionRow->GetSolution(); + if (s.size() == (unsigned) mPegCnt) + { + bool valid = true; + if (!mActSameColor->isChecked()) + { + int i; + int check[mColorCnt]; + for (i = 0; i < mColorCnt; ++i) + { + check[i] = 0; + } + + for (i = 0; (unsigned)i < s.size(); ++i) + { + if (s[i] >= mColorCnt) + { + valid = false; + break; + } + + if (check[s[i]] != 0) + { + valid = false; + break; + } + + check[s[i]] = 1; + } + } + + if (valid) + { + mDoneBtn->ShowBtn(true); + ShowMsgSlot(tr("Press the button below or Key Enter if You're done.")); + } + else + { + ShowMsgSlot(tr("The chosen settings do not allow pegs of the same color!")); + } + } + else + { + mDoneBtn->ShowBtn(false); + ShowMsgSlot(tr("Place Your secret ColorCode ...")); + } + } + } +} + +void ColorCode::HintPressedSlot(int) +{ + mCurRow->CloseRow(); + ResolveRow(); + NextRow(); + ResolveGame(); +} + +void ColorCode::RandRowSlot() +{ + if (mCurRow == NULL || !mCurRow->IsActive() || mGameState != STATE_RUNNING) + { + return; + } + + if (mGameMode == MODE_HVM || (mGameMode == MODE_MVH && mCurRow == mSolutionRow)) + { + mCurRow->ClearRow(); + + int i, rndm; + int check[mColorCnt]; + ColorPeg* peg; + for (i = 0; i < mColorCnt; ++i) + { + check[i] = 0; + } + + for (i = 0; i < mPegCnt; ++i) + { + rndm = qrand() % mColorCnt; + if (mDoubles == 0 && check[rndm] != 0) + { + --i; + continue; + } + + check[rndm] = 1; + + peg = CreatePeg(rndm); + mCurRow->ForceSnap(peg, i); + } + } +} + +void ColorCode::SetGuessSlot() +{ + if (mCurRow == NULL || mCurRow == mSolutionRow || mGameState != STATE_RUNNING || mSolver->mBusy) + { + return; + } + + mCurRow->ClearRow(); + mActSetGuess->setEnabled(false); + int* row = mSolver->GuessOut(); + if (row == NULL) + { + SetState(STATE_ERROR); + return; + } + mActSetGuess->setEnabled(true); + + ColorPeg* peg; + int i; + for (i = 0; i < mPegCnt; ++i) + { + peg = CreatePeg(row[i]); + mCurRow->ForceSnap(peg, i); + } +} + +void ColorCode::SetHintsSlot() +{ + if (mCurRow == NULL || mGameState != STATE_RUNNING) + { + return; + } + + if (mGameMode == MODE_MVH) + { + if (mCurRow == mSolutionRow || !mHintBtns[mCurRow->GetIx()]->IsActive()) + { + return; + } + + std::vector hints = RateSol2Guess(mSolution, mCurRow->GetSolution()); + mHintBtns[mCurRow->GetIx()]->DrawHints(hints); + } +} + +void ColorCode::PrevRowSlot() +{ + if (mCurRow == NULL || mGameState != STATE_RUNNING) + { + return; + } + + if (mCurRow->GetIx() < 1) + { + return; + } + + mCurRow->ClearRow(); + + ColorPeg* peg; + std::vector prev = mPegRows[mCurRow->GetIx() - 1]->GetSolution(); + int i; + for (i = 0; i < mPegCnt; ++i) + { + peg = CreatePeg(prev.at(i)); + mCurRow->ForceSnap(peg, i); + } +} + +void ColorCode::ClearRowSlot() +{ + if (mCurRow == NULL || mGameState != STATE_RUNNING) + { + return; + } + + mCurRow->ClearRow(); +} + +void ColorCode::DoneBtnPressSlot(GraphicsBtn*) +{ + mDoneBtn->ShowBtn(false); + mOkBtn->ShowBtn(false); + + if (mCurRow == mSolutionRow) + { + SetSolution(); + mActClearRow->setEnabled(false); + mActRandRow->setEnabled(false); + mActSetHints->setEnabled(true); + NextRow(); + } + else + { + ResolveHints(); + } +} + +void ColorCode::SetAutoHintsSlot() +{ + DoneBtnPressSlot(mOkBtn); +} + +void ColorCode::TestSlot() +{ + +} + +void ColorCode::ApplyPreferencesSlot() +{ + +} + +void ColorCode::CreatePrefDialog() +{ + mPrefDialog = new PrefDialog(this); + mPrefDialog->setModal(true); + mPrefDialog->InitSettings(mSettings); + connect(mPrefDialog, SIGNAL(accepted()), this, SLOT(ApplyPreferencesSlot())); + connect(mPrefDialog, SIGNAL(ResetColorOrderSignal()), this, SLOT(ResetColorsOrderSlot())); +} + +void ColorCode::CheckSameColorsSetting() +{ + if (mColorCnt < mPegCnt) + { + if (mActSameColor->isEnabled()) + { + mActSameColor->setEnabled(false); + } + if (mActSameColorIcon->isEnabled()) + { + mActSameColorIcon->setEnabled(false); + } + if (!mActSameColor->isChecked()) + { + mActSameColor->setChecked(true); + } + if (!mActSameColorIcon->isChecked()) + { + mActSameColorIcon->setChecked(true); + } + } + else + { + if (!mActSameColor->isEnabled()) + { + mActSameColor->setEnabled(true); + } + if (!mActSameColorIcon->isEnabled()) + { + mActSameColorIcon->setEnabled(true); + } + } + + if (mActSameColorIcon->isChecked()) + { + mActSameColorIcon->setIcon(QIcon(":/img/same_color_1.png")); + mActSameColorIcon->setToolTip(tr("Disallow Pegs of the Same Color")); + } + else + { + mActSameColorIcon->setIcon(QIcon(":/img/same_color_0.png")); + mActSameColorIcon->setToolTip(tr("Allow Pegs of the Same Color")); + } +} + +void ColorCode::SetSameColor(bool checked) +{ + mSettings->mSameColors = checked; + + mActSameColor->setChecked(checked); + mActSameColorIcon->setChecked(checked); + + if (checked) + { + mActSameColorIcon->setIcon(QIcon(":/img/same_color_1.png")); + mActSameColorIcon->setToolTip(tr("Disallow Pegs of the Same Color")); + } + else + { + mActSameColorIcon->setIcon(QIcon(":/img/same_color_0.png")); + mActSameColorIcon->setToolTip(tr("Allow Pegs of the Same Color")); + } +} + +void ColorCode::CheckLevel() +{ + int ix = -1; + for (int i = 0; i < 5; ++i) + { + if ( LEVEL_SETTINGS[i][0] == mColorCnt + && LEVEL_SETTINGS[i][1] == mPegCnt + && LEVEL_SETTINGS[i][2] == mDoubles ) + { + ix = i; + break; + } + } + + if (ix > -1) + { + QList levelacts = mActGroupLevels->actions(); + levelacts.at(ix)->setChecked(true); + } + else + { + QAction* act = mActGroupLevels->checkedAction(); + if (act != NULL) + { + act->setChecked(false); + } + } +} + +void ColorCode::ResetGame() +{ + mDoneBtn->ShowBtn(false); + mOkBtn->ShowBtn(false); + + ApplyPegCnt(); + + mSolutionRow->Reset(mPegCnt, mGameMode); + ResetRows(); + + mGameId = qrand(); + mGuessCnt = 0; + ++mGameCnt; + + ApplyColorCnt(); + + CheckSameColorsSetting(); + + mDoubles = (int) mActSameColor->isChecked(); + CheckLevel(); + + ApplySolverStrength(); +} + +void ColorCode::ResetRows() +{ + for (int i = 0; i < ROW_CNT; ++i) + { + mPegRows[i]->Reset(mPegCnt, mGameMode); + mHintBtns[i]->Reset(mPegCnt, mGameMode); + } +} + +void ColorCode::NewGame() +{ + mHintsDelayTimer->stop(); + ApplyGameMode(); + ResetGame(); + QString doubles = (mDoubles == 1) ? tr("Yes") : tr("No"); + QString colors = QString::number(mColorCnt, 10); + QString pegs = QString::number(mPegCnt, 10); + mStatusLabel->setText(tr("Pegs of Same Color") + ": " + doubles + " :: " + tr("Slots") + ": " + pegs + " :: " + tr("Colors") + ": " + colors + " "); + SetState(STATE_RUNNING); + + mCurRow = NULL; + + if (mGameMode == MODE_HVM) + { + mSolver->NewGame(mColorCnt, mPegCnt, mDoubles, CCSolver::STRENGTH_HIGH, ROW_CNT); + SetSolution(); + NextRow(); + } + else if (mGameMode == MODE_MVH) + { + mSolver->NewGame(mColorCnt, mPegCnt, mDoubles, mSolverStrength, ROW_CNT); + GetSolution(); + } +} + +void ColorCode::NextRow() +{ + if (mGameState != STATE_RUNNING) + { + return; + } + + if (mCurRow == NULL) + { + mCurRow = mPegRows[0]; + } + else if (mCurRow->GetIx() < ROW_CNT - 1) + { + mCurRow = mPegRows[mCurRow->GetIx() + 1]; + } + else + { + mCurRow = NULL; + SetState(STATE_LOST); + } + + if (mCurRow != NULL) + { + ++mGuessCnt; + mCurRow->SetActive(true); + if (mGameMode == MODE_HVM) + { + ShowMsgSlot(tr("Place Your pegs ...")); + } + else if (mGameMode == MODE_MVH) + { + SetGuessSlot(); + if (mGameState == STATE_RUNNING) + { + mCurRow->CloseRow(); + mHintBtns[mCurRow->GetIx()]->SetActive(true); + + if (mActAutoHints->isChecked()) + { + if (mOkBtn->isVisible()) + { + mOkBtn->ShowBtn(false); + } + ShowMsgSlot(tr("Please rate the guess. Press OK or Key Enter if You're done.")); + SetHintsSlot(); + mHintBtns[mCurRow->GetIx()]->SetActive(false); + + std::vector rowhints = mHintBtns[mCurRow->GetIx()]->GetHints(); + int b = 0; + for (unsigned i = 0; i < rowhints.size(); ++i) + { + if (rowhints.at(i) == 2) + { + ++b; + } + } + + if (b == mPegCnt) + { + SetState(STATE_WON); + ResolveGame(); + } + else + { + mHintsDelayTimer->start(); + } + } + else + { + ShowMsgSlot(tr("Please rate the guess. Press OK or Key Enter if You're done.")); + mOkBtn->setPos(5, mCurRow->pos().y() - 39); + mOkBtn->ShowBtn(true); + } + } + else + { + mCurRow->SetActive(false); + ResolveGame(); + } + } + } +} + +void ColorCode::ResolveRow() +{ + std::vector rowsol = mCurRow->GetSolution(); + mSolver->GuessIn(&rowsol); + + std::vector hints = RateSol2Guess(mSolution, rowsol); + + if (hints.size() == (unsigned) mPegCnt) + { + int bl = 0; + for (int i = 0; i < mPegCnt; ++i) + { + if (hints.at(i) == 2) + { + ++bl; + } + } + + if (bl == mPegCnt) + { + SetState(STATE_WON); + } + } + + mSolver->ResIn(&hints); + mHintBtns[mCurRow->GetIx()]->DrawHints(hints); +} + +std::vector ColorCode::RateSol2Guess(const std::vector sol, const std::vector guess) +{ + std::vector hints; + std::vector left1; + std::vector left0; + + int i, p0, p1; + for (i = 0; i < mPegCnt; ++i) + { + p0 = guess.at(i); + p1 = sol.at(i); + if (p0 == p1) + { + hints.push_back(2); + } + else + { + left0.push_back(p0); + left1.push_back(p1); + } + } + + if (hints.size() < (unsigned) mPegCnt) + { + int len0 = left0.size(); + for (i = 0; i < len0; ++i) + { + p0 = left0.at(i); + for (unsigned j = 0; j < left1.size(); ++j) + { + p1 = left1.at(j); + if (p0 == p1) + { + hints.push_back(1); + left1.erase(left1.begin() + j); + break; + } + } + } + } + + return hints; +} + +void ColorCode::ResolveHints() +{ + mHintBtns[mCurRow->GetIx()]->SetActive(false); + + std::vector rowsol = mCurRow->GetSolution(); + mSolver->GuessIn(&rowsol); + std::vector rowhints = mHintBtns[mCurRow->GetIx()]->GetHints(); + int b = 0; + int w = 0; + for (unsigned i = 0; i < rowhints.size(); ++i) + { + if (rowhints.at(i) == 2) + { + ++b; + } + else if (rowhints.at(i) == 1) + { + ++w; + } + } + + if (b == mPegCnt) + { + SetState(STATE_WON); + ResolveGame(); + } + else if (b == mPegCnt - 1 && w == 1) + { + + } + else + { + mSolver->ResIn(&rowhints); + NextRow(); + ResolveGame(); + } +} + +void ColorCode::ResolveGame() +{ + if (mGameMode == MODE_HVM) + { + switch (mGameState) + { + case STATE_WON: + ShowMsgSlot(tr("Congratulation! You have won!")); + break; + case STATE_LOST: + ShowMsgSlot(tr("Sorry! You lost!")); + break; + case STATE_GAVE_UP: + ShowMsgSlot(tr("Sure, You're too weak for me!")); + break; + case STATE_ERROR: + ShowMsgSlot(tr("The impossible happened, sorry.")); + break; + case STATE_RUNNING: + default: + return; + break; + } + + ShowSolution(); + } + else if (mGameMode == MODE_MVH) + { + switch (mGameState) + { + case STATE_WON: + ShowMsgSlot(tr("Yeah! I guessed it, man!")); + break; + case STATE_LOST: + ShowMsgSlot(tr("Embarrassing! I lost a game!")); + break; + case STATE_GAVE_UP: + ShowMsgSlot(tr("Don't you like to see me winning? ;-)")); + break; + case STATE_ERROR: + ShowMsgSlot(tr("Nope! Thats impossible! Did you gave me false hints?")); + break; + case STATE_RUNNING: + default: + return; + break; + } + + mDoneBtn->ShowBtn(false); + mOkBtn->ShowBtn(false); + } +} + +void ColorCode::ApplyGameMode() +{ + int ix = mActGroupModes->checkedAction()->data().toInt(); + + if (ix != MODE_HVM && ix != MODE_MVH) + { + return; + } + + mGameMode = ix; + + if (mGameMode == MODE_HVM) + { + mActSetHints->setVisible(false); + + mActSetGuess->setVisible(true); + mActPrevRow->setVisible(true); + } + else if (mGameMode == MODE_MVH) + { + mActSetHints->setVisible(true); + + mActSetGuess->setVisible(false); + mActPrevRow->setVisible(false); + } +} + +void ColorCode::ApplyPegCnt() +{ + int pegcnt = mPegCntCmb->itemData(mPegCntCmb->currentIndex(), IdRole).toInt(); + pegcnt = max(2, min(5, pegcnt)); + mPegCnt = pegcnt; + mXOffs = 160 - mPegCnt * 20; +} + +void ColorCode::ApplyColorCnt() +{ + int ccnt = mColorCntCmb->itemData(mColorCntCmb->currentIndex(), IdRole).toInt(); + ccnt = max(2, min(10, ccnt)); + + if (mColorCnt == ccnt) + { + return; + } + + mColorCnt = ccnt; + int xpos = 279; + int ystart = ROW_Y0 + (MAX_COLOR_CNT - mColorCnt) * 40; + int ypos; + int i; + + for (i = 0; i < MAX_COLOR_CNT; ++i) + { + ypos = ystart + i * 40 + 2; + mBtnPos[i] = QPoint(xpos, ypos); + + if (i < mColorCnt) + { + if (mPegBtns[i] == NULL) + { + mPegBtns[i] = CreatePeg(i); + } + mPegBtns[i]->setPos(mBtnPos[i]); + mPegBtns[i]->setVisible(true); + } + else if (mPegBtns[i] != NULL) + { + mPegBtns[i]->setVisible(false); + } + } +} + +void ColorCode::ApplySolverStrength() +{ + mSolverStrength = mSettings->mSolverStrength; +} + +void ColorCode::SetSolution() +{ + mSolution.clear(); + + if (mGameMode == MODE_HVM) + { + mSolutionRow->ClearRow(); + int i, rndm; + int check[mColorCnt]; + for (i = 0; i < mColorCnt; ++i) + { + check[i] = 0; + } + + for (i = 0; i < mPegCnt; ++i) + { + rndm = qrand() % mColorCnt; + if (mDoubles == 0 && check[rndm] != 0) + { + --i; + continue; + } + mSolution.push_back(rndm); + check[rndm] = 1; + } + } + else if (mGameMode == MODE_MVH) + { + std::vector s = mSolutionRow->GetSolution(); + if (s.size() == (unsigned) mPegCnt) + { + mSolutionRow->CloseRow(); + mDoneBtn->ShowBtn(false); + + for (int i = 0; i < mPegCnt; ++i) + { + mSolution.push_back(s.at(i)); + } + } + } +} + +void ColorCode::GetSolution() +{ + mActSetHints->setEnabled(false); + mActRandRow->setEnabled(true); + mActClearRow->setEnabled(true); + + ShowMsgSlot(tr("Place Your secret ColorCode ...")); + mSolutionRow->SetActive(true); + mCurRow = mSolutionRow; +} + +void ColorCode::ShowSolution() +{ + mSolutionRow->SetActive(true); + ColorPeg* peg; + for (int i = 0; i < mPegCnt; ++i) + { + peg = CreatePeg(mSolution.at(i)); + peg->SetBtn(false); + mSolutionRow->ForceSnap(peg, i); + } + mSolutionRow->CloseRow(); +} + +void ColorCode::SetState(const int s) +{ + if (mGameState == s) + { + return; + } + + mGameState = s; + + bool running = mGameState == STATE_RUNNING; + + mActRestartGame->setEnabled(running); + mActGiveIn->setEnabled(running); + mActSetGuess->setEnabled(running); + mActSetHints->setEnabled(running); +} + +bool ColorCode::GamesRunning() +{ + if (mGameMode == MODE_HVM) + { + return (mGameState == STATE_RUNNING && mGuessCnt > 1); + } + else if (mGameMode == MODE_MVH) + { + return (mGameState == STATE_RUNNING && mCurRow != mSolutionRow); + } + return false; +} + +void ColorCode::Scale() +{ + if (mGameCnt == 0) + { + return; + } + + qreal w = geometry().width() - 4; + qreal h = geometry().height() - 4; + + if (mActShowStatusbar->isChecked()) + { + h -= statusBar()->height(); + } + if (mActShowMenubar->isChecked()) + { + h -= mMenuBar->height(); + } + if (mActShowToolbar->isChecked()) + { + h -= mGameToolbar->height(); + } + + if (w < 50 || h < 50) + { + return; + } + + if (mOrigSize == NULL) + { + mOrigSize = new QSize(320, 560); + scene->setSceneRect(QRectF(0, 0, 320, 560)); + } + else + { + qreal sc = min(w / mOrigSize->width(), h / mOrigSize->height()); + view->resetTransform(); + view->scale(sc, sc); + } +} + +ColorPeg* ColorCode::CreatePeg(int ix) +{ + if (ix < 0 || ix >= mColorCnt) + { + ix = mAllPegs.size() % mColorCnt; + } + + PegType *pt = mTypesMap[ix]; + ColorPeg *peg; + + if (mPegBuff.empty()) + { + peg = new ColorPeg; + peg->SetPegType(pt); + peg->SetBtn(true); + peg->SetIndicator(mActShowLetter->isChecked(), mSettings->mIndicatorType, mHideColors); + peg->SetId(mAllPegs.size()); + scene->addItem(peg); + peg->setPos(mBtnPos[ix]); + peg->setZValue(LAYER_PEGS); + mAllPegs.push_back(peg); + scene->clearSelection(); + scene->update(mBtnPos[ix].x(), mBtnPos[ix].y(), 38, 38); + peg->setSelected(true); + + connect(peg, SIGNAL(PegPressSignal(ColorPeg *)), this, SLOT(PegPressSlot(ColorPeg *))); + connect(peg, SIGNAL(PegSortSignal(ColorPeg *)), this, SLOT(PegSortSlot(ColorPeg *))); + connect(peg, SIGNAL(PegReleasedSignal(ColorPeg *)), this, SLOT(PegReleasedSlot(ColorPeg *))); + } + else + { + unsigned int sz = mPegBuff.size(); + peg = mPegBuff.at(sz - 1); + mPegBuff.resize(sz - 1); + + peg->setVisible(true); + + peg->SetPegType(pt); + peg->SetBtn(true); + peg->SetEnabled(true); + peg->setPos(mBtnPos[ix]); + scene->clearSelection(); + scene->update(mBtnPos[ix].x(), mBtnPos[ix].y(), 38, 38); + peg->setSelected(true); + } + + return peg; +} + +void ColorCode::RemovePeg(ColorPeg* cp) +{ + if (cp != NULL) + { + cp->Reset(); + cp->setVisible(false); + mPegBuff.push_back(cp); + } +} diff --git a/plugins/ColorCode_plugin/colorcode.h b/plugins/ColorCode_plugin/colorcode.h new file mode 100644 index 000000000..06eb61c9b --- /dev/null +++ b/plugins/ColorCode_plugin/colorcode.h @@ -0,0 +1,284 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef COLORCODE_H +#define COLORCODE_H + +#include +#include + +struct PegType +{ + int ix; + char let; + QRadialGradient* grad; + QColor pencolor; +}; + +class QAction; +class QActionGroup; +class QComboBox; +class QLabel; +class QGraphicsItem; +class QGraphicsTextItem; +class QGraphicsScene; +class QGraphicsView; +class PrefDialog; +class Settings; +class CCSolver; +class ColorPeg; +class PegRow; +class RowHint; +class Msg; +class BackGround; +class SolutionRow; +class GraphicsBtn; + +class ColorCode : public QMainWindow +{ + Q_OBJECT + + public: + ColorCode(); + ~ColorCode(); + + static const int STATE_RUNNING; + static const int STATE_WON; + static const int STATE_LOST; + static const int STATE_GAVE_UP; + static const int STATE_ERROR; + + static const int MODE_HVM; + static const int MODE_MVH; + + static const int MAX_COLOR_CNT; + + static const int LEVEL_SETTINGS[5][3]; + + int ROW_CNT; + int ROW_Y0; + + Settings* mSettings; + + public slots: + void PegPressSlot(ColorPeg *cp); + void PegSortSlot(ColorPeg* cp); + void PegReleasedSlot(ColorPeg *cp); + void RowSolutionSlot(int ix); + void HintPressedSlot(int ix); + void ShowMsgSlot(QString msg); + void RemovePegSlot(ColorPeg* cp); + + void DoneBtnPressSlot(GraphicsBtn* btn = NULL); + + void ApplyPreferencesSlot(); + + protected : + void resizeEvent(QResizeEvent* e); + void contextMenuEvent(QContextMenuEvent* e); + void keyPressEvent(QKeyEvent *e); + + private slots: + void InitRows(); + void InitPegBtns(); + void NewGameSlot(); + void RestartGameSlot(); + void GiveInSlot(); + void ResetRows(); + void OnlineHelpSlot(); + void AboutSlot(); + void AboutQtSlot(); + void OpenPreferencesSlot(); + void ShowToolbarSlot(); + void ShowMenubarSlot(); + void ShowStatusbarSlot(); + void ResetColorsOrderSlot(); + void SetIndicators(); + void SameColorSlot(bool checked); + void SetSameColor(bool checked); + void AutoCloseSlot(); + void AutoHintsSlot(); + void SetLevelSlot(); + void SetGameModeSlot(); + + void RandRowSlot(); + void PrevRowSlot(); + void ClearRowSlot(); + + void ColorCntChangedSlot(); + void PegCntChangedSlot(); + + void UpdateRowMenuSlot(); + + void SetGuessSlot(); + void SetHintsSlot(); + void SetAutoHintsSlot(); + + void TestSlot(); + + private: + static const int LAYER_BG; + static const int LAYER_ROWS; + static const int LAYER_HINTS; + static const int LAYER_SOL; + static const int LAYER_MSG; + static const int LAYER_PEGS; + static const int LAYER_BTNS; + static const int LAYER_DRAG; + + static int mGameMode; + static int mLevel; + static int mColorCnt; + static int mPegCnt; + static int mDoubles; + static int mMaxZ; + static int mXOffs; + + volatile static bool mNoAct; + + int mGameState; + int mGameId; + int mGuessCnt; + int mGameCnt; + bool mHideColors; + int mSolverStrength; + + std::vector mSolution; + + QGraphicsScene* scene; + QGraphicsView* view; + QSize* mOrigSize; + + CCSolver* mSolver; + Msg* mMsg; + BackGround* mBg; + GraphicsBtn* mDoneBtn; + GraphicsBtn* mOkBtn; + PrefDialog* mPrefDialog; + + PegRow* mCurRow; + + std::vector mAllPegs; + std::vector mPegBuff; + SolutionRow* mSolutionRow; + PegRow* mPegRows[10]; + RowHint* mHintBtns[10]; + + PegType* mTypesMap[10]; + QRadialGradient mGradMap[10]; + QRadialGradient mGradBuff[10]; + ColorPeg* mPegBtns[10]; + QPoint mBtnPos[10]; + + QTimer* mHintsDelayTimer; + + void InitTypesMap(); + void InitSolution(); + void InitActions(); + void InitMenus(); + void InitToolBars(); + void CreatePrefDialog(); + void ApplySettings(); + bool NeedsRestart() const; + void TryNewGame(); + + void SetGameMode(); + void SetPegCnt(); + void SetColorCnt(); + + void ApplyGameMode(); + void ApplyPegCnt(); + void ApplyColorCnt(); + void ApplySolverStrength(); + + void CheckLevel(); + void CheckSameColorsSetting(); + void SetState(const int s); + void ResetGame(); + void NewGame(); + void SetSolution(); + void GetSolution(); + void ShowSolution(); + void NextRow(); + void ResolveRow(); + std::vector RateSol2Guess(const std::vector sol, const std::vector guess); + void ResolveHints(); + void ResolveGame(); + bool GamesRunning(); + void Scale(); + + ColorPeg* CreatePeg(int ix); + void RemovePeg(ColorPeg* cp); + + QMenu* mMenuGame; + QMenu* mMenuRow; + QMenu* mMenuRowContext; + QMenu* mMenuSettings; + QMenu* mMenuModes; + QMenu* mMenuLevels; + QMenu* mMenuHelp; + + QMenuBar* mMenuBar; + QToolBar* mGameToolbar; + QToolBar* mLevelToolbar; + + QComboBox* mColorCntCmb; + QComboBox* mPegCntCmb; + QLabel* mStatusLabel; + + QActionGroup* mActGroupLevels; + QActionGroup* mActGroupModes; + + QAction* mActNewGame; + QAction* mActRestartGame; + QAction* mActGiveIn; + QAction* mActShowToolbar; + QAction* mActShowMenubar; + QAction* mActShowStatusbar; + QAction* mActSameColor; + QAction* mActResetColorsOrder; + QAction* mActShowLetter; + QAction* mActSameColorIcon; + QAction* mActAutoClose; + QAction* mActAutoHints; + QAction* mActPreferences; + QAction* mActAbout; + QAction* mActAboutQt; + QAction* mActExit; + + QAction* mActSetPegCnt; + + QAction* mActModeHvM; + QAction* mActModeMvH; + + QAction* mActLevelEasy; + QAction* mActLevelClassic; + QAction* mActLevelMedium; + QAction* mActLevelChallenging; + QAction* mActLevelHard; + QAction* mLaunchHelpAction; + + QAction* mActRandRow; + QAction* mActPrevRow; + QAction* mActClearRow; + + QAction* mActSetGuess; + QAction* mActSetHints; +}; + +#endif // COLORCODE_H diff --git a/plugins/ColorCode_plugin/colorpeg.cpp b/plugins/ColorCode_plugin/colorpeg.cpp new file mode 100644 index 000000000..fa83d944e --- /dev/null +++ b/plugins/ColorCode_plugin/colorpeg.cpp @@ -0,0 +1,340 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include + +#include "colorpeg.h" + +using namespace std; + +const QFont ColorPeg::mFont = ColorPeg::GetLetterFont(); +const QBrush ColorPeg::mShadowBrush = ColorPeg::GetShadowBrush(); +const QBrush ColorPeg::mOutlineBrush = ColorPeg::GetOutlineBrush(); +const QBrush ColorPeg::mGlossyBrush = ColorPeg::GetGlossyBrush(); +const QBrush ColorPeg::mNeutralBrush = ColorPeg::GetNeutralBrush(); + +QFont ColorPeg::GetLetterFont() +{ + QFont lf("Arial", 12, QFont::Bold, false); + lf.setStyleHint(QFont::SansSerif); + + return lf; +} + +QBrush ColorPeg::GetNeutralBrush() +{ + QRadialGradient rgrad(20, 20, 40, 5, 5); + rgrad.setColorAt(0.0, QColor(0xff, 0xff, 0xff, 0xff)); + rgrad.setColorAt(1.0, QColor(0x80, 0x80, 0x80, 0xff)); + + return QBrush(rgrad); +} + +QBrush ColorPeg::GetShadowBrush() +{ + QRadialGradient rgrad(22, 22, 22, 22, 22); + rgrad.setColorAt(0.3, QColor(0, 0, 0, 0xff)); + rgrad.setColorAt(1.0, QColor(0, 0, 0, 0)); + + return QBrush(rgrad); +} + +QBrush ColorPeg::GetOutlineBrush() +{ + QLinearGradient lgrad(0, 0, 38, 38); + lgrad.setColorAt(0.0, QColor(0, 0, 0, 0xa0)); + lgrad.setColorAt(1.0, QColor(0xff, 0xff, 0xff, 0xa0)); + return QBrush(lgrad); +} + +QBrush ColorPeg::GetGlossyBrush() +{ + QLinearGradient lgrad(20, 4, 20, 20); + lgrad.setColorAt(0.0, QColor(0xff, 0xff, 0xff, 0x80)); + lgrad.setColorAt(1.0, QColor(0xff, 0xff, 0xff, 0x00)); + return QBrush(lgrad); +} + + +ColorPeg::ColorPeg(QObject*) +{ + setFlags(QGraphicsItem::GraphicsItemFlags(0)); + mPegType = NULL; + mPegRow = NULL; + SetBtn(true); + mIsDragged = false; + mShowIndicator = false; + mHideColor = false; + mSort = 0; + mId = -1; +} + +ColorPeg::~ColorPeg() +{ +} + +void ColorPeg::SetPegType(PegType *pt) +{ + mPegType = pt; + setFlags(ItemIsMovable | ItemIsSelectable); +} + +void ColorPeg::SetPegRow(PegRow *pr) +{ + mPegRow = pr; +} + +PegType* ColorPeg::GetPegType() +{ + return mPegType; +} + +void ColorPeg::SetId(int id) +{ + mId = id; +} + +bool ColorPeg::IsBtn() const +{ + return mIsBtn; +} + +int ColorPeg::GetSort() const +{ + return mSort; +} + +void ColorPeg::SetBtn(bool b) +{ + mIsBtn = b; + SetCursorShape(); +} + +int ColorPeg::GetType() const +{ + return mType; +} + +void ColorPeg::SetType(const int t) +{ + mType = t; +} + +void ColorPeg::Reset() +{ + SetIsDragged(false); + setSelected(false); + if (mPegRow != NULL) + { + mPegRow->RemovePeg(this); + mPegRow = NULL; + } +} + +void ColorPeg::SetIsDragged(bool b) +{ + if (false == b) + { + update(boundingRect()); + } + mIsDragged = b; +} + +void ColorPeg::SetEnabled(const bool b) +{ + setEnabled(b); + SetCursorShape(); +} + +void ColorPeg::SetIndicator(const bool b, const int t, const bool c) +{ + if (mShowIndicator != b || mIndicatorType != t || mHideColor != c) + { + mShowIndicator = b; + mIndicatorType = t; + mHideColor = c; + update(boundingRect()); + } +} + +void ColorPeg::SetCursorShape(Qt::CursorShape shape, const bool force) +{ + if (!force) + { + if (mIsDragged) + { + if (mSort == 0) + { + shape = Qt::ClosedHandCursor; + } + else if (mSort == 1) + { + shape = Qt::SizeVerCursor; + } + else + { + shape = Qt::SplitVCursor; + } + } + else if (isEnabled()) + { + shape = Qt::OpenHandCursor; + } + } + + if (cursor().shape() != shape) + { + setCursor(QCursor(shape)); + } +} + +QVariant ColorPeg::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemSelectedHasChanged) + { + scene()->update(scene()->sceneRect()); + } + return QGraphicsItem::itemChange(change, value); +} + +void ColorPeg::mousePressEvent(QGraphicsSceneMouseEvent *e) +{ + QGraphicsItem::mousePressEvent(e); + if (mPegType != NULL) + { + if (e->button() == Qt::LeftButton) + { + Reset(); + SetIsDragged(true); + if (IsBtn() && (e->modifiers() & Qt::ControlModifier) != 0) + { + if ((e->modifiers() & Qt::ShiftModifier) == 0) + { + mSort = 1; + } + else + { + mSort = 2; + } + } + else + { + mSort = 0; + + } + emit PegPressSignal(this); + SetCursorShape(); + } + } +} + +void ColorPeg::mouseReleaseEvent (QGraphicsSceneMouseEvent *e) +{ + QGraphicsItem::mouseReleaseEvent(e); + if (mPegType != NULL) + { + if (e->button() == Qt::LeftButton) + { + SetIsDragged(false); + emit PegReleasedSignal(this); + SetCursorShape(); + } + } +} + +QPainterPath ColorPeg::shape() const +{ + QPainterPath path; + path.addEllipse(boundingRect()); + return path; +} + +QRectF ColorPeg::boundingRect() const +{ + int margin; + if (mIsDragged) + { + margin = 8; + } + else + { + margin = 1; + } + return outlineRect().adjusted(-margin, -margin, +margin, +margin); +} + +QRectF ColorPeg::outlineRect() const +{ + QRectF rect(0.0, 0.0, 36.0, 36.0); + return rect; +} + +QRectF ColorPeg::GetColorRect() const +{ + QRectF rect(1.0, 1.0, 34.0, 34.0); + return rect; +} + +void ColorPeg::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget* /* widget */) +{ + painter->setPen(Qt::NoPen); + + if (!mIsDragged) + { + painter->setBrush(ColorPeg::mOutlineBrush); + painter->drawEllipse(outlineRect()); + } + else + { + painter->translate(QPointF(-2, -2)); + painter->setBrush(ColorPeg::mShadowBrush); + painter->drawEllipse(QRectF(0, 0, 44, 44)); + painter->translate(QPointF(2, 2)); + } + + if (!mHideColor) + { + painter->setBrush(QBrush(*mPegType->grad)); + painter->drawEllipse(GetColorRect()); + } + else + { + painter->setBrush(mNeutralBrush); + painter->drawEllipse(GetColorRect()); + } + + painter->setBrush(mGlossyBrush); + painter->drawEllipse(QRectF(5, 3, 24, 20)); + + if (mShowIndicator) + { + painter->setPen(QPen(QColor("#303133"))); + painter->setRenderHint(QPainter::TextAntialiasing, true); + painter->setFont(mFont); + QString ind; + if (mIndicatorType == Settings::INDICATOR_LETTER) + { + ind = QString(mPegType->let); + } + else + { + ind.setNum((mPegType->ix + 1)); + } + painter->drawText(QRectF(1.5, 2.0, 32.0, 32.0), Qt::AlignCenter, ind); + } +} diff --git a/plugins/ColorCode_plugin/colorpeg.h b/plugins/ColorCode_plugin/colorpeg.h new file mode 100644 index 000000000..5f3bd8f19 --- /dev/null +++ b/plugins/ColorCode_plugin/colorpeg.h @@ -0,0 +1,109 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef COLORPEG_H +#define COLORPEG_H + +#include +#include +#include +#include +#include +#include +#include "colorcode.h" +#include "pegrow.h" +#include "rowhint.h" +#include "settings.h" + + +class ColorPeg : public QObject, public QGraphicsItem +{ + Q_OBJECT + +public: + ColorPeg(QObject* parent = 0); + ~ColorPeg(); + + int mId; + void SetId(int id); + + void SetPegType(PegType* pt); + void SetPegRow(PegRow* pr); + + QRectF boundingRect() const; + QPainterPath shape() const; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); + + void SetType(const int t); + void SetEnabled(const bool b); + void SetIndicator(const bool b, const int t, const bool c); + void SetCursorShape( Qt::CursorShape shape = Qt::ArrowCursor, const bool force = false); + PegType* GetPegType(); + int GetType() const; + QColor GetPenColor() const; + QColor GetBrushColor() const; + + bool IsBtn() const; + int GetSort() const; + void SetBtn(bool b); + void Reset(); + +signals: + void PegReleasedSignal(ColorPeg* cp); + void PegPressSignal(ColorPeg* cp); + void PegSortSignal(ColorPeg* cp); + +protected: + PegType* mPegType; + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + + void mousePressEvent(QGraphicsSceneMouseEvent* e); + void mouseReleaseEvent(QGraphicsSceneMouseEvent* e); + +private: + static const QFont mFont; + static QFont GetLetterFont(); + static const QBrush mShadowBrush; + static QBrush GetShadowBrush(); + static const QBrush mOutlineBrush; + static QBrush GetOutlineBrush(); + static const QBrush mGlossyBrush; + static QBrush GetGlossyBrush(); + static const QBrush mNeutralBrush; + static QBrush GetNeutralBrush(); + + QRectF GetColorRect() const; + QRectF outlineRect() const; + void SetIsDragged(bool b); + + PegRow* mPegRow; + + const QBrush mBrush; + + int mType; + int mSort; + bool mIsBtn; + bool mIsDragged; + bool mShowIndicator; + int mIndicatorType; + bool mHideColor; +}; + + + +#endif // COLORPEG_H diff --git a/plugins/ColorCode_plugin/docs/GPL.html b/plugins/ColorCode_plugin/docs/GPL.html new file mode 100644 index 000000000..77894b212 --- /dev/null +++ b/plugins/ColorCode_plugin/docs/GPL.html @@ -0,0 +1,694 @@ + + + + + GNU General Public License - GNU Project - Free Software Foundation (FSF) + + + +

GNU GENERAL PUBLIC LICENSE

+

Version 3, 29 June 2007

+ +

Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>

+ Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed.

+ +

Preamble

+ +

The GNU General Public License is a free, copyleft license for +software and other kinds of works.

+ +

The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too.

+ +

When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things.

+ +

To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others.

+ +

For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights.

+ +

Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it.

+ +

For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions.

+ +

Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users.

+ +

Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free.

+ +

The precise terms and conditions for copying, distribution and +modification follow.

+ +

TERMS AND CONDITIONS

+ +

0. Definitions.

+ +

“This License” refers to version 3 of the GNU General Public License.

+ +

“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks.

+ +

“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations.

+ +

To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work.

+ +

A “covered work” means either the unmodified Program or a work based +on the Program.

+ +

To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well.

+ +

To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying.

+ +

An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion.

+ +

1. Source Code.

+ +

The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work.

+ +

A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language.

+ +

The “System Libraries” of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it.

+ +

The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work.

+ +

The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source.

+ +

The Corresponding Source for a work in source code form is that +same work.

+ +

2. Basic Permissions.

+ +

All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law.

+ +

You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you.

+ +

Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary.

+ +

3. Protecting Users' Legal Rights From Anti-Circumvention Law.

+ +

No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures.

+ +

When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures.

+ +

4. Conveying Verbatim Copies.

+ +

You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program.

+ +

You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee.

+ +

5. Conveying Modified Source Versions.

+ +

You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions:

+ +
    +
  • a) The work must carry prominent notices stating that you modified + it, and giving a relevant date.
  • + +
  • b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + “keep intact all notices”.
  • + +
  • c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it.
  • + +
  • d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so.
  • +
+ +

A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate.

+ +

6. Conveying Non-Source Forms.

+ +

You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways:

+ +
    +
  • a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange.
  • + +
  • b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge.
  • + +
  • c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b.
  • + +
  • d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements.
  • + +
  • e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d.
  • +
+ +

A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work.

+ +

A “User Product” is either (1) a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product.

+ +

“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made.

+ +

If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM).

+ +

The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network.

+ +

Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying.

+ +

7. Additional Terms.

+ +

“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions.

+ +

When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission.

+ +

Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms:

+ +
    +
  • a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or
  • + +
  • b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or
  • + +
  • c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or
  • + +
  • d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or
  • + +
  • e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or
  • + +
  • f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors.
  • +
+ +

All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying.

+ +

If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms.

+ +

Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way.

+ +

8. Termination.

+ +

You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11).

+ +

However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation.

+ +

Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice.

+ +

Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10.

+ +

9. Acceptance Not Required for Having Copies.

+ +

You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so.

+ +

10. Automatic Licensing of Downstream Recipients.

+ +

Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License.

+ +

An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts.

+ +

You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it.

+ +

11. Patents.

+ +

A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”.

+ +

A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License.

+ +

Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version.

+ +

In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party.

+ +

If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid.

+ +

If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it.

+ +

A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007.

+ +

Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law.

+ +

12. No Surrender of Others' Freedom.

+ +

If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program.

+ +

13. Use with the GNU Affero General Public License.

+ +

Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such.

+ +

14. Revised Versions of this License.

+ +

The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns.

+ +

Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation.

+ +

If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program.

+ +

Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version.

+ +

15. Disclaimer of Warranty.

+ +

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

+ +

16. Limitation of Liability.

+ +

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES.

+ +

17. Interpretation of Sections 15 and 16.

+ +

If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee.

+ +

END OF TERMS AND CONDITIONS

+ +

How to Apply These Terms to Your New Programs

+ +

If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms.

+ +

To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found.

+ +
    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ +

Also add information on how to contact you by electronic and paper mail.

+ +

If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode:

+ +
    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+ +

The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an “about box”.

+ +

You should also get your employer (if you work as a programmer) or school, +if any, to sign a “copyright disclaimer” for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>.

+ +

The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>.

+ + + diff --git a/plugins/ColorCode_plugin/gameboard.h b/plugins/ColorCode_plugin/gameboard.h new file mode 100644 index 000000000..6e253219a --- /dev/null +++ b/plugins/ColorCode_plugin/gameboard.h @@ -0,0 +1,4 @@ +#ifndef GAMEBOARD_H +#define GAMEBOARD_H + +#endif // GAMEBOARD_H diff --git a/plugins/ColorCode_plugin/graphicsbtn.cpp b/plugins/ColorCode_plugin/graphicsbtn.cpp new file mode 100644 index 000000000..e8f301221 --- /dev/null +++ b/plugins/ColorCode_plugin/graphicsbtn.cpp @@ -0,0 +1,151 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include +#include +#include "graphicsbtn.h" + +using namespace std; + +GraphicsBtn::GraphicsBtn() +{ + mWidth = 152; + + setCursor(Qt::PointingHandCursor); + setAcceptHoverEvents (true); + mLabel = ""; + mLabelWidth = 0; + mYOffs = 0; + + InitGraphics(); + SetShapes(); + + mFillBrush = &mFillOutBrush; + mFrameBrush = &mFrameOutBrush; + + mFont = QFont("Arial", 12, QFont::Bold, false); + mFont.setStyleHint(QFont::SansSerif); + mFont.setStyleStrategy(QFont::PreferAntialias); +} + +void GraphicsBtn::SetWidth(int w) +{ + mWidth = w; + SetShapes(); +} + +void GraphicsBtn::SetLabel(QString str) +{ + mLabel = str; +} + +void GraphicsBtn::ShowBtn(bool b) +{ + if (b) + { + mFillBrush = &mFillOutBrush; + mFrameBrush = &mFrameOutBrush; + } + setVisible(b); +} + +void GraphicsBtn::hoverEnterEvent(QGraphicsSceneHoverEvent* e) +{ + mFillBrush = &mFillOverBrush; + QGraphicsItem::hoverEnterEvent(e); +} + +void GraphicsBtn::hoverLeaveEvent(QGraphicsSceneHoverEvent* e) +{ + mFillBrush = &mFillOutBrush; + QGraphicsItem::hoverLeaveEvent(e); +} + +void GraphicsBtn::mousePressEvent(QGraphicsSceneMouseEvent*) +{ + mFrameBrush = &mFrameOverBrush; + mYOffs = 1; + update(mRect); +} + +void GraphicsBtn::mouseReleaseEvent(QGraphicsSceneMouseEvent* e) +{ + mFrameBrush = &mFrameOutBrush; + mYOffs = 0; + if ( e->pos().x() >= 0 + && e->pos().x() <= boundingRect().width() + && e->pos().y() >= 0 + && e->pos().y() <= boundingRect().height() ) + { + emit BtnPressSignal(this); + } + update(mRect); +} + +void GraphicsBtn::InitGraphics() +{ + QLinearGradient fillgrad(0, 2, 0, 36); + fillgrad.setColorAt(0.0, QColor("#f7f8fa")); + fillgrad.setColorAt(0.5, QColor("#b9babc")); + mFillOutBrush = QBrush(fillgrad); + + QLinearGradient fillovergrad(0, 2, 0, 36); + fillovergrad.setColorAt(0.0, QColor("#f7f8fa")); + fillovergrad.setColorAt(1.0, QColor("#b9babc")); + mFillOverBrush = QBrush(fillovergrad); + + QLinearGradient framegrad(0, 0, 0, 40); + framegrad.setColorAt(1.0, QColor(0, 0, 0, 0xa0)); + framegrad.setColorAt(0.0, QColor(0xff, 0xff, 0xff, 0xa0)); + mFrameOutBrush = QBrush(framegrad); + + QLinearGradient frameovergrad(0, 0, 0, 40); + frameovergrad.setColorAt(0.0, QColor(0, 0, 0, 0xa0)); + frameovergrad.setColorAt(1.0, QColor(0xff, 0xff, 0xff, 0xa0)); + mFrameOverBrush = QBrush(frameovergrad); +} + +void GraphicsBtn::SetShapes() +{ + mRect = QRectF(0, 0, mWidth, 38); + mRectFill = QRectF(1, 1, mWidth - 2, 36); +} + +QRectF GraphicsBtn::boundingRect() const +{ + const double margin = 0.5; + return mRect.adjusted(-margin, -margin, 2 * margin, 2 * margin); +} + +void GraphicsBtn::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget* /* widget */) +{ + painter->setPen(Qt::NoPen); + painter->setBrush(*mFrameBrush); + painter->drawRoundedRect(mRect, 20, 20); + + painter->setBrush(*mFillBrush); + painter->drawRoundedRect(mRectFill, 18, 18); + + if (mLabel != "") + { + painter->setRenderHint(QPainter::TextAntialiasing, true); + painter->setPen(QPen(QColor("#303133"))); + painter->setFont(mFont); + painter->drawText(mRectFill.adjusted(0, mYOffs, 0, mYOffs), Qt::AlignCenter, mLabel); + } +} diff --git a/plugins/ColorCode_plugin/graphicsbtn.h b/plugins/ColorCode_plugin/graphicsbtn.h new file mode 100644 index 000000000..f3e01786e --- /dev/null +++ b/plugins/ColorCode_plugin/graphicsbtn.h @@ -0,0 +1,76 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef GRAPHICSBTN_H +#define GRAPHICSBTN_H + +#include +#include +#include +#include +#include +#include +#include + +class GraphicsBtn : public QObject, public QGraphicsItem +{ + Q_OBJECT + +public: + GraphicsBtn(); + + void SetWidth(int w); + void SetLabel(QString str); + void ShowBtn(bool b); + + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); + QRectF boundingRect() const; + +signals: + void BtnPressSignal(GraphicsBtn* btn); + +protected: + void hoverEnterEvent(QGraphicsSceneHoverEvent* e); + void hoverLeaveEvent(QGraphicsSceneHoverEvent* e); + void mousePressEvent(QGraphicsSceneMouseEvent* e); + void mouseReleaseEvent(QGraphicsSceneMouseEvent* e); + + virtual void InitGraphics(); + virtual void SetShapes(); + + QString mLabel; + int mWidth; + int mLabelWidth; + int mYOffs; + + QRectF mRect; + QRectF mRectFill; + QRectF mIconRect; + + QBrush mFillOutBrush; + QBrush mFillOverBrush; + QBrush* mFillBrush; + + QBrush mFrameOutBrush; + QBrush mFrameOverBrush; + QBrush* mFrameBrush; + + QFont mFont; +}; + +#endif // GRAPHICSBTN_H diff --git a/plugins/ColorCode_plugin/img/GNU-icon.png b/plugins/ColorCode_plugin/img/GNU-icon.png new file mode 100644 index 000000000..c32ad6db8 Binary files /dev/null and b/plugins/ColorCode_plugin/img/GNU-icon.png differ diff --git a/plugins/ColorCode_plugin/img/GNU-icon16.png b/plugins/ColorCode_plugin/img/GNU-icon16.png new file mode 100644 index 000000000..245d84ed7 Binary files /dev/null and b/plugins/ColorCode_plugin/img/GNU-icon16.png differ diff --git a/plugins/ColorCode_plugin/img/GNU-icon32.png b/plugins/ColorCode_plugin/img/GNU-icon32.png new file mode 100644 index 000000000..b297876f1 Binary files /dev/null and b/plugins/ColorCode_plugin/img/GNU-icon32.png differ diff --git a/plugins/ColorCode_plugin/img/GNU-icon64.png b/plugins/ColorCode_plugin/img/GNU-icon64.png new file mode 100644 index 000000000..4f8c1a4d9 Binary files /dev/null and b/plugins/ColorCode_plugin/img/GNU-icon64.png differ diff --git a/plugins/ColorCode_plugin/img/Thumbs.db b/plugins/ColorCode_plugin/img/Thumbs.db new file mode 100644 index 000000000..2d9421f42 Binary files /dev/null and b/plugins/ColorCode_plugin/img/Thumbs.db differ diff --git a/plugins/ColorCode_plugin/img/application-exit.png b/plugins/ColorCode_plugin/img/application-exit.png new file mode 100644 index 000000000..4839c6142 Binary files /dev/null and b/plugins/ColorCode_plugin/img/application-exit.png differ diff --git a/plugins/ColorCode_plugin/img/bm03.png b/plugins/ColorCode_plugin/img/bm03.png new file mode 100644 index 000000000..9654e54b7 Binary files /dev/null and b/plugins/ColorCode_plugin/img/bm03.png differ diff --git a/plugins/ColorCode_plugin/img/business_user.png b/plugins/ColorCode_plugin/img/business_user.png new file mode 100644 index 000000000..65f5d9a8e Binary files /dev/null and b/plugins/ColorCode_plugin/img/business_user.png differ diff --git a/plugins/ColorCode_plugin/img/cc16.png b/plugins/ColorCode_plugin/img/cc16.png new file mode 100644 index 000000000..fc878582c Binary files /dev/null and b/plugins/ColorCode_plugin/img/cc16.png differ diff --git a/plugins/ColorCode_plugin/img/cc32.png b/plugins/ColorCode_plugin/img/cc32.png new file mode 100644 index 000000000..d9a9dc185 Binary files /dev/null and b/plugins/ColorCode_plugin/img/cc32.png differ diff --git a/plugins/ColorCode_plugin/img/cc64.png b/plugins/ColorCode_plugin/img/cc64.png new file mode 100644 index 000000000..2b2857056 Binary files /dev/null and b/plugins/ColorCode_plugin/img/cc64.png differ diff --git a/plugins/ColorCode_plugin/img/colorcode32.xpm b/plugins/ColorCode_plugin/img/colorcode32.xpm new file mode 100644 index 000000000..b0658e12e --- /dev/null +++ b/plugins/ColorCode_plugin/img/colorcode32.xpm @@ -0,0 +1,632 @@ +/* XPM */ +static char * colorcode32_xpm[] = { +"32 32 597 2", +" c None", +". c #727272", +"+ c #574E49", +"@ c #52575C", +"# c #54606B", +"$ c #616D78", +"% c #757779", +"& c #86807B", +"* c #8B8B8B", +"= c #929292", +"- c #939393", +"; c #8F8F8E", +"> c #6D6E71", +", c #4D4D53", +"' c #656155", +") c #746E5D", +"! c #7C776D", +"~ c #737478", +"{ c #6D6E74", +"] c #4A4542", +"^ c #1E4C60", +"/ c #27ACDC", +"( c #20BDF8", +"_ c #1AB6F9", +": c #17A8F4", +"< c #1B97EA", +"[ c #338BD0", +"} c #768897", +"| c #8D8A88", +"1 c #9A9A9A", +"2 c #999999", +"3 c #848484", +"4 c #2E2D2F", +"5 c #9C954A", +"6 c #F5EA6B", +"7 c #FFF467", +"8 c #FFF15D", +"9 c #FDE855", +"0 c #F2D954", +"a c #C8B567", +"b c #838182", +"c c #322C2A", +"d c #23A1C1", +"e c #28DEFF", +"f c #25CCF8", +"g c #22C2F5", +"h c #20B7F2", +"i c #1EACEF", +"j c #1C9FEB", +"k c #1992E7", +"l c #1183E7", +"m c #568ABA", +"n c #94918D", +"o c #A0A0A0", +"p c #838383", +"q c #363520", +"r c #F9F67F", +"s c #FEFA80", +"t c #FBF474", +"u c #FAF06C", +"v c #F8EB62", +"w c #F8E65B", +"x c #F6E053", +"y c #F7DB4A", +"z c #F1D148", +"A c #9B9584", +"B c #4A4441", +"C c #23A0C1", +"D c #29DEFE", +"E c #27D5FB", +"F c #26CEF8", +"G c #23C4F6", +"H c #21B9F3", +"I c #1EAFF0", +"J c #1CA3EC", +"K c #1A96E9", +"L c #1789E4", +"M c #0F77E2", +"N c #5E89B5", +"O c #9D9C9B", +"P c #A5A5A5", +"Q c #A2A2A1", +"R c #2E2C21", +"S c #FFFF88", +"T c #FDFA85", +"U c #FDF87E", +"V c #FCF476", +"W c #FAF16D", +"X c #F9ED65", +"Y c #F8E75E", +"Z c #F7E156", +"` c #F5DC4E", +" . c #F4D547", +".. c #F3CE3F", +"+. c #8E8C83", +"@. c #737272", +"#. c #1E4C61", +"$. c #26D1F9", +"%. c #25CBF8", +"&. c #22C3F5", +"*. c #1FAFF0", +"=. c #1A98E9", +"-. c #188BE6", +";. c #177EE1", +">. c #0D6CDE", +",. c #8C949A", +"'. c #ADADAD", +"). c #505158", +"!. c #CCC764", +"~. c #FDFA81", +"{. c #FDF980", +"]. c #FCF77A", +"^. c #F9ED64", +"/. c #F9E85E", +"(. c #F7E257", +"_. c #F5DD50", +":. c #F4D649", +"<. c #F3CF40", +"[. c #E0C055", +"}. c #72757E", +"|. c #564E49", +"1. c #26ACDB", +"2. c #26CDF8", +"3. c #24C6F7", +"4. c #22BFF5", +"5. c #20B7F3", +"6. c #1EADF0", +"7. c #1CA2ED", +"8. c #1A97E9", +"9. c #167EE1", +"0. c #146FDD", +"a. c #517FBA", +"b. c #AAA9A8", +"c. c #AEAEAE", +"d. c #4F4C3C", +"e. c #FFFF78", +"f. c #FCF678", +"g. c #FBF36F", +"h. c #FAEF6B", +"i. c #F9EB63", +"j. c #F6E256", +"k. c #F6DC4F", +"l. c #F4D749", +"m. c #F2CF42", +"n. c #F4C831", +"o. c #948F82", +"p. c #52565B", +"q. c #20BCF8", +"r. c #22BEF5", +"s. c #21BAF3", +"t. c #1FB2F1", +"u. c #1EA8EE", +"v. c #1BA0EB", +"w. c #1A95E8", +"x. c #1788E4", +"y. c #157CE1", +"z. c #1570DC", +"A. c #256FCF", +"B. c #ABA8A3", +"C. c #9B9B9C", +"D. c #978F51", +"E. c #FDF26C", +"F. c #FAF270", +"G. c #FBF270", +"H. c #FBF16D", +"I. c #FAF06B", +"J. c #F9E960", +"K. c #F8E55A", +"L. c #F6E054", +"M. c #F3CE40", +"N. c #F3C838", +"O. c #B4A06A", +"P. c #53606B", +"Q. c #1AB7F9", +"R. c #1FB1F1", +"S. c #1EACF0", +"T. c #1DA3ED", +"U. c #1A9AEA", +"V. c #1990E7", +"W. c #1786E4", +"X. c #1678DF", +"Y. c #146EDC", +"Z. c #1161D4", +"`. c #B2AEA7", +" + c #8F8F91", +".+ c #B3A95C", +"++ c #F9EC64", +"@+ c #F9EE67", +"#+ c #FAEF69", +"$+ c #FAEE67", +"%+ c #F9EC65", +"&+ c #F9EB61", +"*+ c #F8E65C", +"=+ c #F7E357", +"-+ c #F6DE51", +";+ c #F5DA4C", +">+ c #F4D446", +",+ c #F2CD40", +"'+ c #F1C639", +")+ c #C8AD60", +"!+ c #626E78", +"~+ c #1FADF0", +"{+ c #1EA9EE", +"]+ c #1B9CEB", +"^+ c #1A93E8", +"/+ c #188BE5", +"(+ c #167FE2", +"_+ c #1575DE", +":+ c #136ADB", +"<+ c #125FD1", +"[+ c #B5B0AA", +"}+ c #9C9C9D", +"|+ c #B7AC61", +"1+ c #F9E75C", +"2+ c #F8E95F", +"3+ c #F9E95F", +"4+ c #F8E85F", +"5+ c #F7DF52", +"6+ c #F5DB4D", +"7+ c #F3D143", +"8+ c #F2CB3D", +"9+ c #F1C537", +"0+ c #C0A65E", +"a+ c #1783E3", +"b+ c #167AE0", +"c+ c #146FDC", +"d+ c #1265D9", +"e+ c #2D6BC5", +"f+ c #B9B6B2", +"g+ c #B2B2B2", +"h+ c #A89B6A", +"i+ c #F9E353", +"j+ c #F7E457", +"k+ c #F7E459", +"l+ c #F7E458", +"m+ c #F7E254", +"n+ c #F6DF52", +"o+ c #F4D849", +"p+ c #F4D345", +"q+ c #F2CE40", +"r+ c #F1C73A", +"s+ c #F3C231", +"t+ c #A9996C", +"u+ c #857F7B", +"v+ c #338CD0", +"w+ c #1991E8", +"x+ c #1A94E8", +"y+ c #1782E3", +"z+ c #167CE1", +"A+ c #1573DD", +"B+ c #0F5ED8", +"C+ c #5B7CAD", +"D+ c #C7C7C7", +"E+ c #C8C8C8", +"F+ c #8C8A84", +"G+ c #FADE4A", +"H+ c #F6DE50", +"I+ c #F6DF51", +"J+ c #F6DE52", +"K+ c #F6DD4F", +"L+ c #F5D849", +"M+ c #F3D346", +"N+ c #F3D041", +"O+ c #F2CA3D", +"P+ c #F1C538", +"Q+ c #EFBB2D", +"R+ c #8D8C89", +"S+ c #8C8C8D", +"T+ c #758796", +"U+ c #1182E7", +"V+ c #136ADA", +"W+ c #1263D8", +"X+ c #1158CC", +"Y+ c #B2B1AE", +"Z+ c #C9C9C9", +"`+ c #A5A7AB", +" @ c #CEB865", +".@ c #F5D846", +"+@ c #F5D94B", +"@@ c #F4D84A", +"#@ c #F3D447", +"$@ c #F3D244", +"%@ c #F3CE41", +"&@ c #F1C638", +"*@ c #F1C133", +"=@ c #C1A457", +"-@ c #8B8B8D", +";@ c #5689BB", +">@ c #0F78E2", +",@ c #1574DE", +"'@ c #0753D3", +")@ c #8493A8", +"!@ c #CBCBCB", +"~@ c #CACACA", +"{@ c #989899", +"]@ c #EAC84D", +"^@ c #F3D142", +"/@ c #F3D243", +"(@ c #F3D042", +"_@ c #F2CF41", +":@ c #F2CC3F", +"<@ c #F2C93B", +"[@ c #F1C539", +"}@ c #F1C234", +"|@ c #DCB13D", +"1@ c #8E8E91", +"2@ c #95918D", +"3@ c #1365D9", +"4@ c #1058CB", +"5@ c #8493A7", +"6@ c #CCCCCC", +"7@ c #9C9B9B", +"8@ c #DEBF55", +"9@ c #F5CB36", +"0@ c #F1C83B", +"a@ c #F0C338", +"b@ c #F2BE2C", +"c@ c #D1AB49", +"d@ c #949393", +"e@ c #9D9C9A", +"f@ c #527FBA", +"g@ c #1161D5", +"h@ c #1260D1", +"i@ c #2D6AC4", +"j@ c #5B7BAC", +"k@ c #B3B1AE", +"l@ c #CDCDCD", +"m@ c #CECECE", +"n@ c #CCCCCB", +"o@ c #AAABB0", +"p@ c #AFA382", +"q@ c #D5B65B", +"r@ c #E9BE3E", +"s@ c #EEBF33", +"t@ c #E6BB3B", +"u@ c #CFAD54", +"v@ c #A79B7E", +"w@ c #9A9CA0", +"x@ c #B3AEA7", +"y@ c #B5B0AB", +"z@ c #B8B6B2", +"A@ c #B1B2B5", +"B@ c #A9ABB2", +"C@ c #A6A9B1", +"D@ c #A3A5AB", +"E@ c #A8A9AB", +"F@ c #9B9C9C", +"G@ c #8F9191", +"H@ c #9C9E9E", +"I@ c #C8C7C7", +"J@ c #B4B4B4", +"K@ c #8F8F8F", +"L@ c #ABABAB", +"M@ c #A2A1A1", +"N@ c #515B5C", +"O@ c #4B3836", +"P@ c #8D362D", +"Q@ c #A63A30", +"R@ c #A83F38", +"S@ c #985652", +"T@ c #898080", +"U@ c #A7ACAC", +"V@ c #9F9F9F", +"W@ c #484848", +"X@ c #595959", +"Y@ c #A3A3A3", +"Z@ c #9C9C9C", +"`@ c #818181", +" # c #7B7B7B", +".# c #9B9B9B", +"+# c #838484", +"@# c #2D201E", +"## c #C6260C", +"$# c #FC2303", +"%# c #F02007", +"&# c #E8200B", +"*# c #E21D0D", +"=# c #DD170C", +"-# c #D5150E", +";# c #B24544", +"># c #979999", +",# c #616161", +"'# c #4D4D4D", +")# c #D7D7D7", +"!# c #F5F5F5", +"~# c #EFEFEF", +"{# c #EDEDED", +"]# c #EBEBEB", +"^# c #EAEAEA", +"/# c #D6D6D6", +"(# c #959595", +"_# c #888888", +":# c #351612", +"<# c #FF2A02", +"[# c #F92703", +"}# c #F52605", +"|# c #F02208", +"1# c #EA200A", +"2# c #E41F0C", +"3# c #DD1C0F", +"4# c #D61A11", +"5# c #CD1412", +"6# c #BF2526", +"7# c #9C9999", +"8# c #626262", +"9# c #717171", +"0# c #F3F3EF", +"a# c #F6F6EF", +"b# c #F6F6F0", +"c# c #F3F3F0", +"d# c #F0F0EF", +"e# c #E9E9E9", +"f# c #E3E3E3", +"g# c #868686", +"h# c #909090", +"i# c #2C2F30", +"j# c #F62904", +"k# c #FA2902", +"l# c #F82704", +"m# c #F52506", +"n# c #F12308", +"o# c #EA210A", +"p# c #E51F0D", +"q# c #DE1C0E", +"r# c #D81A10", +"s# c #CF1714", +"t# c #C71415", +"u# c #B53439", +"v# c #ABB2B2", +"w# c #4E4E4E", +"x# c #F5F5F0", +"y# c #F9F9F2", +"z# c #F9F9F5", +"A# c #F9F9F4", +"B# c #F8F8F2", +"C# c #F7F7F0", +"D# c #F1F1F0", +"E# c #E8E8E8", +"F# c #E1E1E1", +"G# c #8C8C8C", +"H# c #6D7272", +"I# c #932112", +"J# c #F92603", +"K# c #F72605", +"L# c #F22406", +"M# c #EF2209", +"N# c #E41E0D", +"O# c #DE1C0F", +"P# c #D01814", +"Q# c #C71615", +"R# c #BF0C10", +"S# c #A07679", +"T# c #F2F2EF", +"U# c #FCFCF9", +"V# c #FDFDFB", +"W# c #FAFAF6", +"X# c #F4F4EF", +"Y# c #EEEEEF", +"Z# c #E4E4E4", +"`# c #D3D3D3", +" $ c #4E5556", +".$ c #E7250C", +"+$ c #F22407", +"@$ c #F22506", +"#$ c #F02307", +"$$ c #EC2109", +"%$ c #E9200B", +"&$ c #D81A11", +"*$ c #BF1518", +"=$ c #AC4046", +"-$ c #B2B5B5", +";$ c #B5B5B5", +">$ c #FDFDFD", +",$ c #FBFBF6", +"'$ c #F8F8F0", +")$ c #F0F0F0", +"!$ c #E0E0E0", +"~$ c #615150", +"{$ c #F01E08", +"]$ c #EC2209", +"^$ c #EE2309", +"/$ c #EE2208", +"($ c #EC210A", +"_$ c #E61E0C", +":$ c #E11E0D", +"<$ c #DC1B10", +"[$ c #D61911", +"}$ c #CE1715", +"|$ c #C61516", +"1$ c #BE1419", +"2$ c #B11A23", +"3$ c #ACB3B3", +"4$ c #FCFCF8", +"5$ c #FAFAF5", +"6$ c #F2F2F0", +"7$ c #A8A8A8", +"8$ c #6D5856", +"9$ c #EC1806", +"0$ c #E71F0B", +"a$ c #E7200B", +"b$ c #E51E0D", +"c$ c #D21912", +"d$ c #CA1615", +"e$ c #C41616", +"f$ c #BB1419", +"g$ c #B00F19", +"h$ c #A9B3B2", +"i$ c #F9F9F3", +"j$ c #DFDFDF", +"k$ c #B1B1B1", +"l$ c #766866", +"m$ c #E2170A", +"n$ c #E11E0E", +"o$ c #E31E0D", +"p$ c #E21E0D", +"q$ c #E01D0E", +"r$ c #D91A10", +"s$ c #D41912", +"t$ c #CD1814", +"u$ c #C11517", +"v$ c #B8131A", +"w$ c #AC1824", +"x$ c #A6AEAD", +"y$ c #F8F8F1", +"z$ c #F7F7EF", +"A$ c #A4A4A4", +"B$ c #74797A", +"C$ c #D12019", +"D$ c #D91B11", +"E$ c #DB1B0F", +"F$ c #DC1B0F", +"G$ c #D71A11", +"H$ c #D31912", +"I$ c #CE1714", +"J$ c #C91615", +"K$ c #C31517", +"L$ c #BB1418", +"M$ c #B4121B", +"N$ c #A33D46", +"O$ c #A9ACAB", +"P$ c #828282", +"Q$ c #F4F4F0", +"R$ c #DEDEDE", +"S$ c #8D8D8D", +"T$ c #6F7777", +"U$ c #AF4A48", +"V$ c #D21610", +"W$ c #D51911", +"X$ c #D51912", +"Y$ c #D11813", +"Z$ c #CC1815", +"`$ c #BE1418", +" % c #B7131A", +".% c #AE0914", +"+% c #977478", +"@% c #F1F1EF", +"#% c #EEEEEE", +"$% c #737373", +"%% c #828181", +"&% c #C71A1A", +"*% c #CA1715", +"=% c #CB1615", +"-% c #BD1418", +";% c #B1101B", +">% c #A12F3A", +",% c #9DA1A1", +"'% c #949494", +")% c #E2E2E2", +"!% c #DCDCDC", +"~% c #937C7C", +"{% c #C21416", +"]% c #C41515", +"^% c #BA1319", +"/% c #B6131A", +"(% c #B10F19", +"_% c #A3202C", +":% c #939293", +"<% c #898989", +"[% c #A2A2A2", +"}% c #8A7F80", +"|% c #B6353A", +"1% c #BA0A10", +"2% c #B91016", +"3% c #B91319", +"4% c #B6121A", +"5% c #B30C16", +"6% c #AB0915", +"7% c #9B434C", +"8% c #CFCFCF", +"9% c #758180", +"0% c #8E7D7E", +"a% c #9B595E", +"b% c #A44D53", +"c% c #9E4C52", +"d% c #945E64", +"e% c #8B8889", +"f% c #8B8E8D", +" . + @ # $ % & * = = - - - - = = ; > , ' ) ! ~ { ", +" ] ^ / ( _ : < [ } | 1 2 2 2 2 1 3 4 5 6 7 8 9 0 a b ", +" c d e f g h i j k l m n o o o o p q r s t u v w x y z A ", +" B C D E F G H I J K L M N O P P Q R S T U V W X Y Z ` ...+. ", +"@.#.e E $.%.&.H *.J =.-.;.>.,.'.'.).!.~.{.].t W ^./.(._.:.<.[.}.", +"|.1.f 2.%.3.4.5.6.7.8.-.9.0.a.b.c.d.e.f.f.t g.h.i.Y j.k.l.m.n.o.", +"p.q.g G &.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.X J.K.L.` .M.N.O.", +"P.Q.h H H 5.R.S.T.U.V.W.X.Y.Z.`. +.+++@+#+$+%+&+*+=+-+;+>+,+'+)+", +"!+: i I *.~+{+T.]+^+/+(+_+:+<+[+}+|+1+2+J.3+4+w =+5+6+l.7+8+9+0+", +"% < j J J 7.v.U.^+-.a+b+c+d+e+f+g+h+i+j+k+l+j+m+n+` o+p+q+r+s+t+", +"u+v+w+K =.8.x+V./+y+z+A+:+B+C+D+E+F+G+H+I+n+J+K+6+L+M+N+O+P+Q+R+", +"S+T+U+L -.-.x.W.(+b+A+V+W+X+Y+Z+Z+`+ @.@o++@@@l.#@$@%@8+&@*@=@-@", +"= | ;@>@9.9.y.X.,@c+:+W+'@)@!@~@~@!@{@]@^@/@$@(@_@:@<@[@}@|@1@= ", +"= 1 2@N >.0.z.Y.V+3@B+4@5@Z+!@6@6@!@Z+7@8@9@8+O+0@'+a@b@c@d@1 = ", +"- 2 o e@,.f@A.g@h@i@j@k@!@!@l@m@m@l@!@n@o@p@q@r@s@t@u@v@w@o 2 - ", +"- 2 o P '.b.B.x@y@z@D+Z+~@6@m@m@m@m@6@~@Z+D+A@B@C@D@E@'.P o 2 - ", +"- 2 o P '.c.F@G@H@g+I@Z+~@6@m@m@m@m@6@~@Z+Z+J@2 K@1 L@'.P o 2 - ", +"- 2 o M@N@O@P@Q@R@S@T@U@6@!@l@m@m@l@!@6@V@W@X@K@Y@Z@`@ #.#o 2 - ", +"= 1 +#@###$#%#&#*#=#-#;#>#Z+!@6@6@!@6@,#'#)#!#~#{#]#^#/#(#_#1 = ", +"= p :#<#[#}#|#1#2#3#4#5#6#7#!@~@~@6@8#9#!#0#a#b#a#c#d#e#f#L@g#= ", +"h#i#j#k#l#m#n#o#p#q#r#s#t#u#v#Z+Z+o w#!#x#y#z#A#B#C#c#D#E#F#1 G#", +"H#I#J#K#m#L#M#o#N#O#r#P#Q#R#S#D+Z+W@)#T#y#U#V#U#W#y#C#X#Y#Z#`#`@", +" $.$+$@$L##$$$%$N#3#&$s#Q#*$=$-$;$X@!#a#z#V#>$U#,$A#'$x#)$E#!$= ", +"~${$]$^$/$($%$_$:$<$[$}$|$1$2$3$2 K@~#b#A#U#U#4$5$A#C#x#6$^#!$7$", +"8$9$0$%$%$a$b$*#3#r#c$d$e$f$g$h$K@Y@{#a#B#W#,$5$5$i$C#x#D#^#j$k$", +"l$m$n$o$o$p$q$3#r$s$t$Q#u$v$w$x$1 Z@]#c#C#y#A#A#i$y$z$0#)$E#j$A$", +"B$C$D$E$E$F$r$G$H$I$J$K$L$M$N$O$L@P$^#d#Q$C#'$C#C#z$c#6${#Z#R$S$", +"T$U$V$s$W$X$H$Y$Z$J$e$`$ %.%+%'.'. #/#e#@%Q$x#x#x#c#D##%E#j$l@$%", +" %%&%*%Z$Z$=%J$|$K$-%v$;%>%,%P P .#'%f#E##%)$6$D#d#{#E#)%!%h# ", +" ~%{%]%e$e$u$*$^%/%(%_%:%o o o o <%L@F#Z#E#^#^#E#Z#j$!%[% ", +" }%|%1%2%3%4%5%6%7%G@1 2 2 2 2 1 g#1 `#!$!$j$j$R$8%K@ ", +" 9%0%a%b%c%d%e%f%= = - - - - = = * `@= 7$k$P S$. "}; diff --git a/plugins/ColorCode_plugin/img/configure.png b/plugins/ColorCode_plugin/img/configure.png new file mode 100644 index 000000000..95bd319ce Binary files /dev/null and b/plugins/ColorCode_plugin/img/configure.png differ diff --git a/plugins/ColorCode_plugin/img/document-new.png b/plugins/ColorCode_plugin/img/document-new.png new file mode 100644 index 000000000..8431237bd Binary files /dev/null and b/plugins/ColorCode_plugin/img/document-new.png differ diff --git a/plugins/ColorCode_plugin/img/edit-clear.png b/plugins/ColorCode_plugin/img/edit-clear.png new file mode 100644 index 000000000..19a1665ba Binary files /dev/null and b/plugins/ColorCode_plugin/img/edit-clear.png differ diff --git a/plugins/ColorCode_plugin/img/edit-copy.png b/plugins/ColorCode_plugin/img/edit-copy.png new file mode 100644 index 000000000..5cdeb5fc7 Binary files /dev/null and b/plugins/ColorCode_plugin/img/edit-copy.png differ diff --git a/plugins/ColorCode_plugin/img/face-sad.png b/plugins/ColorCode_plugin/img/face-sad.png new file mode 100644 index 000000000..929672d59 Binary files /dev/null and b/plugins/ColorCode_plugin/img/face-sad.png differ diff --git a/plugins/ColorCode_plugin/img/gplv3-80x32.png b/plugins/ColorCode_plugin/img/gplv3-80x32.png new file mode 100644 index 000000000..7f6731699 Binary files /dev/null and b/plugins/ColorCode_plugin/img/gplv3-80x32.png differ diff --git a/plugins/ColorCode_plugin/img/help-about.png b/plugins/ColorCode_plugin/img/help-about.png new file mode 100644 index 000000000..e1eb7972d Binary files /dev/null and b/plugins/ColorCode_plugin/img/help-about.png differ diff --git a/plugins/ColorCode_plugin/img/help.png b/plugins/ColorCode_plugin/img/help.png new file mode 100644 index 000000000..9f0c92f23 Binary files /dev/null and b/plugins/ColorCode_plugin/img/help.png differ diff --git a/plugins/ColorCode_plugin/img/icon_female16.png b/plugins/ColorCode_plugin/img/icon_female16.png new file mode 100644 index 000000000..5e6bcc90b Binary files /dev/null and b/plugins/ColorCode_plugin/img/icon_female16.png differ diff --git a/plugins/ColorCode_plugin/img/qt.png b/plugins/ColorCode_plugin/img/qt.png new file mode 100644 index 000000000..cbed1a901 Binary files /dev/null and b/plugins/ColorCode_plugin/img/qt.png differ diff --git a/plugins/ColorCode_plugin/img/same_color_0.png b/plugins/ColorCode_plugin/img/same_color_0.png new file mode 100644 index 000000000..0ffbe8b2e Binary files /dev/null and b/plugins/ColorCode_plugin/img/same_color_0.png differ diff --git a/plugins/ColorCode_plugin/img/same_color_1.png b/plugins/ColorCode_plugin/img/same_color_1.png new file mode 100644 index 000000000..35aca3870 Binary files /dev/null and b/plugins/ColorCode_plugin/img/same_color_1.png differ diff --git a/plugins/ColorCode_plugin/img/story-editor.png b/plugins/ColorCode_plugin/img/story-editor.png new file mode 100644 index 000000000..7f9b3c4df Binary files /dev/null and b/plugins/ColorCode_plugin/img/story-editor.png differ diff --git a/plugins/ColorCode_plugin/img/system-switch-user.png b/plugins/ColorCode_plugin/img/system-switch-user.png new file mode 100644 index 000000000..b84e2b775 Binary files /dev/null and b/plugins/ColorCode_plugin/img/system-switch-user.png differ diff --git a/plugins/ColorCode_plugin/img/view-refresh.png b/plugins/ColorCode_plugin/img/view-refresh.png new file mode 100644 index 000000000..86b6f82c1 Binary files /dev/null and b/plugins/ColorCode_plugin/img/view-refresh.png differ diff --git a/plugins/ColorCode_plugin/main.cpp b/plugins/ColorCode_plugin/main.cpp new file mode 100644 index 000000000..4ea5648f9 --- /dev/null +++ b/plugins/ColorCode_plugin/main.cpp @@ -0,0 +1,91 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include +#include +#include +#include +#include +#include "colorcode.h" + +int main(int argc, char* argv[]) +{ + using namespace std; + + string lang(""); + if (argc > 1) + { + string str; + for (int i = 1; i < argc; ++i) + { + str = argv[i]; + if (str == "-h" || str == "--help") + { + cout << "usage: ColorCode [options]" << endl; + cout << " options:" << endl; + cout << " -l cc, --lang=cc use country code cc instead of system locale, accepted values for cc: en|de|cs|fr|hu" << endl; + cout << " -h, --help prints this message ;-)" << endl; + return 0; + } + else if (str == "-l" && i < argc - 1) + { + if (std::string(argv[i + 1]) == "de" || std::string(argv[i + 1]) == "en" || std::string(argv[i + 1]) == "cs" || std::string(argv[i + 1]) == "fr" || std::string(argv[i + 1]) == "hu") + { + std::string test(argv[i]); + lang = argv[i + 1]; + cerr << "Lang: " << lang << endl; + } + } + else if ( str.size() == 9 + && str.find("--lang=") != string::npos + && (str.substr(7) == "en" || str.substr(7) == "de" || str.substr(7) == "cs" || str.substr(7) == "fr" || str.substr(7) == "hu") ) + { + lang = str.substr(7); + cerr << "Lang: " << lang << endl; + } + } + } + + QApplication app(argc, argv); + + QTranslator qtTranslator; + if (lang == "") + { + qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + } + else + { + qtTranslator.load("qt_" + QString::fromStdString(lang), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + } + app.installTranslator(&qtTranslator); + + QTranslator appTranslator; + if (lang == "") + { + appTranslator.load(":/trans_" + QLocale::system().name()); + } + else + { + appTranslator.load(":/trans_" + QString::fromStdString(lang)); + } + app.installTranslator(&appTranslator); + + ColorCode w; + w.show(); + return app.exec(); +} diff --git a/plugins/ColorCode_plugin/msg.cpp b/plugins/ColorCode_plugin/msg.cpp new file mode 100644 index 000000000..e1e5992d9 --- /dev/null +++ b/plugins/ColorCode_plugin/msg.cpp @@ -0,0 +1,88 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include + +#include "msg.h" + +using namespace std; + +Msg::Msg() +{ + mFont = QFont("Arial", 12, QFont::Bold, false); + mFont.setStyleHint(QFont::SansSerif); + mFont.setPixelSize(16); + mLay = new QTextLayout(); + mLay->setFont(mFont); + mLay->setTextOption(QTextOption(Qt::AlignHCenter)); + mUpdateRect = QRectF(0, 0, 10, 10); +} + +Msg::~Msg() +{ +} + +void Msg::ShowMsg(const QString str) +{ + mUpdateRect = boundingRect(); + + mLay->setText(str); + int leading = -3; + qreal h = 0; + qreal maxw = 0; + qreal maxh = 0; + mLay->beginLayout(); + + while (1) + { + QTextLine line = mLay->createLine(); + if (!line.isValid()) + { + break; + } + + line.setLineWidth(280); + h += leading; + line.setPosition(QPointF(0, h)); + h += line.height(); + maxw = qMax(maxw, line.naturalTextWidth()); + } + mLay->endLayout(); + + float ypos = 4 + (70 - mLay->boundingRect().height()) / 2; + + maxw = qMax(mUpdateRect.width(), mLay->boundingRect().width()); + maxh = qMax(mUpdateRect.height(), mLay->boundingRect().height() + ypos); + + mUpdateRect = QRectF(0, 0, maxw, maxh + ypos); + + update(boundingRect()); +} + +QRectF Msg::boundingRect() const +{ + return mUpdateRect; +} + +void Msg::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /* widget */) +{ + painter->setRenderHint(QPainter::TextAntialiasing, true); + painter->setPen(QPen(QColor("#303133"))); + float ypos = 4 + (70 - mLay->boundingRect().height()) / 2; + mLay->draw(painter, QPointF(0, ypos)); +} diff --git a/plugins/ColorCode_plugin/msg.h b/plugins/ColorCode_plugin/msg.h new file mode 100644 index 000000000..c4d013c87 --- /dev/null +++ b/plugins/ColorCode_plugin/msg.h @@ -0,0 +1,45 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef MSG_H +#define MSG_H + +#include +#include +#include +#include +#include +#include + +class Msg : public QGraphicsTextItem +{ +public: + Msg(); + ~Msg(); + + void ShowMsg(const QString str); + QRectF boundingRect() const; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); + +private: + QTextLayout* mLay; + QFont mFont; + QRectF mUpdateRect; +}; + +#endif // MSG_H diff --git a/plugins/ColorCode_plugin/pegrow.cpp b/plugins/ColorCode_plugin/pegrow.cpp new file mode 100644 index 000000000..f96e051ee --- /dev/null +++ b/plugins/ColorCode_plugin/pegrow.cpp @@ -0,0 +1,374 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include + +#include "colorpeg.h" +#include "pegrow.h" +#include "rowhint.h" + +using namespace std; + +PegRow::PegRow(QObject*) +{ + setAcceptedMouseButtons(0); + + mIx = -1; + mPegCnt = 0; + mXOffs = 0; + mPend = QColor("#646568"); + mPenl = QColor("#ecedef"); + mGrad0 = QColor("#cccdcf"); + mGrad1 = QColor("#fcfdff"); + + mColorPegs = NULL; + + Reset(0, 0); +} + +PegRow::~PegRow() +{ + for (int i = 0; i < mPegCnt; ++i) + { + delete mColorPegs[i]; + } + delete [] mColorPegs; + mColorPegs = NULL; +} + +bool PegRow::IsActive() const +{ + return mIsActive; +} + +void PegRow::Reset(const int pegcnt, const int gamemode) +{ + ClearRow(); + mSolution.clear(); + SetActive(false); + mSolved = false; + SetPegCnt(pegcnt); + SetGameMode(gamemode); +} + +void PegRow::ClearRow() +{ + if (mColorPegs == NULL) { return; }; + + for (int i = 0; i < mPegCnt; ++i) + { + if (mColorPegs[i] != NULL) + { + emit(RemovePegSignal(mColorPegs[i])); + } + } +} + +int PegRow::GetIx() const +{ + return mIx; +} + +void PegRow::SetIx(const int ix) +{ + mIx = ix; +} + +void PegRow::SetPegCnt(const int pegcnt) +{ + ClearRow(); + for (int i = 0; i < mPegCnt; ++i) + { + delete mColorPegs[i]; + } + delete [] mColorPegs; + mColorPegs = NULL; + + mPegCnt = pegcnt; + mColorPegs = new ColorPeg* [mPegCnt]; + for (int i = 0; i < mPegCnt; ++i) + { + mColorPegs[i] = NULL; + } + SetXOffs(); +} + +void PegRow::SetGameMode(const int gamemode) +{ + mGameMode = gamemode; +} + +void PegRow::SetXOffs() +{ + mXOffs = 100 - mPegCnt * 20; +} + +int PegRow::GetPegCnt() const +{ + if (mColorPegs == NULL) { return 0; }; + + int cnt = 0; + int i = 0; + for (i = 0; i < mPegCnt; ++i) + { + if (mColorPegs[i] != NULL) + { + ++cnt; + } + } + return cnt; +} + +ColorPeg** PegRow::GetPegs() +{ + return mColorPegs; +} + +void PegRow::SetActive(const bool b) +{ + mIsActive = b; + update(boundingRect()); +} + +bool PegRow::SnapCP(ColorPeg *cp) +{ + if (mColorPegs == NULL) + { + return false; + } + + bool snapped = false; + if (mIsActive) + { + QPointF p = mapFromParent(cp->pos()); + + p.rx() += 18; + p.ry() += 18; + + int ix = -1; + int i; + + if (p.y() >= 0 && p.y() <= 40) + { + for (i = 0; i < mPegCnt; ++i) + { + if (p.x() >= mXOffs + i * 40 && p.x() < mXOffs + (i + 1) * 40) + { + if (mColorPegs[i] != NULL) + { + emit RemovePegSignal(mColorPegs[i]); + mColorPegs[i] = NULL; + } + mColorPegs[i] = cp; + cp->SetPegRow(this); + ix = i; + cp->setPos(mapToParent(mXOffs + i * 40 + 2, 2)); + break; + } + } + } + + snapped = ix > -1; + CheckSolution(); + } + + return snapped; +} + +void PegRow::ForceSnap(ColorPeg* cp, int posix) +{ + if (mColorPegs == NULL) + { + return; + } + + if (posix > mPegCnt - 1) + { + return; + } + + if (mIsActive) + { + if (mColorPegs[posix] != NULL) + { + emit RemovePegSignal(mColorPegs[posix]); + mColorPegs[posix] = NULL; + } + mColorPegs[posix] = cp; + cp->SetPegRow(this); + cp->setPos(mapToParent(mXOffs + posix * 40 + 2, 2)); + + CheckSolution(); + } +} + +void PegRow::CloseRow() +{ + mSolved = true; + if (mColorPegs == NULL) + { + + } + else + { + for (int i = 0; i < mPegCnt; ++i) + { + if (mColorPegs[i] != NULL) + { + mColorPegs[i]->SetEnabled(false); + } + } + } + SetActive(false); +} + +void PegRow::OpenRow() +{ + mSolved = false; + if (mColorPegs == NULL) + { + + } + else + { + for (int i = 0; i < mPegCnt; ++i) + { + if (mColorPegs[i] != NULL) + { + mColorPegs[i]->SetEnabled(true); + } + } + } + SetActive(true); +} + +void PegRow::CheckSolution() +{ + mSolution.clear(); + if (mColorPegs == NULL) + { + + } + else + { + for (int i = 0; i < mPegCnt; ++i) + { + if (mColorPegs[i] != NULL) + { + mSolution.push_back(mColorPegs[i]->GetPegType()->ix); + } + } + } + + emit RowSolutionSignal(mIx); +} + +std::vector PegRow::GetSolution() const +{ + return mSolution; +} + +void PegRow::RemovePeg(ColorPeg *cp) +{ + if (mColorPegs == NULL) + { + return; + } + + for (int i = 0; i < mPegCnt; ++i) + { + if (mColorPegs[i] == cp) + { + mColorPegs[i] = NULL; + if (mIsActive) + { + CheckSolution(); + } + } + } +} + +QVariant PegRow::itemChange(GraphicsItemChange change, const QVariant &value) +{ + return QGraphicsItem::itemChange(change, value); +} + +QPainterPath PegRow::shape() const +{ + QPainterPath path; + path.addRect(boundingRect()); + return path; +} + +QRectF PegRow::boundingRect() const +{ + const int Margin = 1; + return outlineRect().adjusted(-Margin, -Margin, +Margin, +Margin); +} + +QRectF PegRow::outlineRect() const +{ + return QRectF(0.0, 0.0, 200.0, 40.0); +} + +void PegRow::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget* /* widget */) +{ + if (mPegCnt == 0) + { + return; + } + + if (mIsActive) + { + mPend.setAlpha(0xff); + mPenl.setAlpha(0xff); + mGrad0.setAlpha(0xff); + mGrad1.setAlpha(0xff); + } + else if (mSolved) + { + mPend.setAlpha(0xa0); + mPenl.setAlpha(0xa0); + mGrad0.setAlpha(0xa0); + mGrad1.setAlpha(0xa0); + } + else + { + mPend.setAlpha(0x32); + mPenl.setAlpha(0x50); + mGrad0.setAlpha(0x32); + mGrad1.setAlpha(0x32); + } + painter->setPen(Qt::NoPen); + int i; + for (i = 0; i < mPegCnt; i++) + { + painter->setBrush(QBrush(mPenl)); + painter->drawRect(QRectF(mXOffs + i * 40, 0.0, 39, 1)); + painter->drawRect(QRectF(mXOffs + i * 40, 0.0, 1, 39)); + painter->setBrush(QBrush(mPend)); + painter->drawRect(QRectF(mXOffs + i * 40, 39.0, 40, 1)); + painter->drawRect(QRectF(mXOffs + i * 40 + 39, 0.0, 1, 40)); + + QRadialGradient grad(QPointF(mXOffs + i * 40 + 10, 10), 100); + grad.setColorAt(0, mGrad0); + grad.setColorAt(1, mGrad1); + painter->setBrush(QBrush(grad)); + painter->drawRect(QRectF(mXOffs + i * 40 + 1, 1.0, 38.0, 38.0)); + } +} diff --git a/plugins/ColorCode_plugin/pegrow.h b/plugins/ColorCode_plugin/pegrow.h new file mode 100644 index 000000000..6402d12fe --- /dev/null +++ b/plugins/ColorCode_plugin/pegrow.h @@ -0,0 +1,95 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef PEGROW_H +#define PEGROW_H + +#include +#include +#include +#include +#include +#include +#include +#include "colorcode.h" +#include "colorpeg.h" + +class PegRow : public QObject, public QGraphicsItem +{ + Q_OBJECT + +public: + PegRow(QObject* parent = 0); + ~PegRow(); + + int GetIx() const; + bool IsActive() const; + int GetPegCnt() const; + ColorPeg** GetPegs(); + std::vector GetSolution() const; + void SetIx(const int ix); + void SetPegCnt(const int pegcnt); + void SetGameMode(const int gamemode); + void SetActive(const bool b); + bool SnapCP(ColorPeg* cp); + void ForceSnap(ColorPeg* cp, int posix); + void RemovePeg(ColorPeg* cp); + + void CloseRow(); + void OpenRow(); + void ClearRow(); + void Reset(const int pegcnt, const int gamemode); + + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); + QRectF boundingRect() const; + QPainterPath shape() const; + +signals: + void RowSolutionSignal(int ix); + void RemovePegSignal(ColorPeg* cp); + +protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + + std::vector mSolution; + + QColor mPend; + QColor mPenl; + QColor mGrad0; + QColor mGrad1; + bool mIsActive; + bool mSolved; + int mIx; + int mPegCnt; + int mGameMode; + int mXOffs; + + virtual void SetXOffs(); + + void CheckSolution(); + ColorPeg** mColorPegs; + QRectF outlineRect() const; + +private slots: + //void FillRandSlot(); + +private: + +}; + +#endif // PEGROW_H diff --git a/plugins/ColorCode_plugin/prefdialog.cpp b/plugins/ColorCode_plugin/prefdialog.cpp new file mode 100644 index 000000000..f736ad851 --- /dev/null +++ b/plugins/ColorCode_plugin/prefdialog.cpp @@ -0,0 +1,314 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include "prefdialog.h" + +using namespace std; + +PrefDialog::PrefDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) +{ + setupUi(this); + setSizeGripEnabled(false); + mSuppressSlots = false; + InitControls(); +} + +PrefDialog::~PrefDialog() +{ +} + +void PrefDialog::InitControls() +{ + mLevelPresetsCmb->addItem(tr("... Select from predefined level settings"), -1); + mLevelPresetsCmb->addItem(tr("Beginner (2 Colors, 2 Slots, Doubles)"), 0); + mLevelPresetsCmb->addItem(tr("Easy (4 Colors, 3 Slots, No Doubles)"), 1); + mLevelPresetsCmb->addItem(tr("Classic (6 Colors, 4 Slots, Doubles)"), 2); + mLevelPresetsCmb->addItem(tr("Challenging (8 Colors, 4 Slots, Doubles)"), 3); + mLevelPresetsCmb->addItem(tr("Hard (10 Colors, 5 Slots, Doubles)"), 4); + + mPegCntCmb->addItem("2 " + tr("Slots"), 2); + mPegCntCmb->addItem("3 " + tr("Slots"), 3); + mPegCntCmb->addItem("4 " + tr("Slots"), 4); + mPegCntCmb->addItem("5 " + tr("Slots"), 5); + + mColorCntCmb->addItem("2 " + tr("Colors"), 2); + mColorCntCmb->addItem("3 " + tr("Colors"), 3); + mColorCntCmb->addItem("4 " + tr("Colors"), 4); + mColorCntCmb->addItem("5 " + tr("Colors"), 5); + mColorCntCmb->addItem("6 " + tr("Colors"), 6); + mColorCntCmb->addItem("7 " + tr("Colors"), 7); + mColorCntCmb->addItem("8 " + tr("Colors"), 8); + mColorCntCmb->addItem("9 " + tr("Colors"), 9); + mColorCntCmb->addItem("10 " + tr("Colors"), 10); + + mGameModeCmb->addItem(tr("Human vs. Computer"), ColorCode::MODE_HVM); + mGameModeCmb->addItem(tr("Computer vs. Human"), ColorCode::MODE_MVH); + + mStrengthCmb->addItem(tr("Low"), CCSolver::STRENGTH_LOW); + mStrengthCmb->addItem(tr("Medium"), CCSolver::STRENGTH_MEDIUM); + mStrengthCmb->addItem(tr("High"), CCSolver::STRENGTH_HIGH); + mDelaySb->setMaximum(10000); + mDelaySb->setMinimum(0); + mDelaySb->setSingleStep(100); + + mRestoreBtn = mButtonBox->button(QDialogButtonBox::RestoreDefaults); + mOkBtn = mButtonBox->button(QDialogButtonBox::Ok); + mApplyBtn = mButtonBox->button(QDialogButtonBox::Apply); + mCancelBtn = mButtonBox->button(QDialogButtonBox::Cancel); + + connect(mLevelPresetsCmb, SIGNAL(currentIndexChanged(int)), this, SLOT(LevelPresetChangedSlot())); + connect(mColorCntCmb, SIGNAL(currentIndexChanged(int)), this, SLOT(ColorCntChangedSlot())); + connect(mPegCntCmb, SIGNAL(currentIndexChanged(int)), this, SLOT(PegCntChangedSlot())); + connect(mSameColorsCb, SIGNAL(stateChanged(int)), this, SLOT(SameColorsChangedSlot())); + connect(mShowIndicatorsCb, SIGNAL(stateChanged(int)), this, SLOT(ShowIndicatorsChangedSlot())); + + connect(mResetColorOrderBtn, SIGNAL(clicked()), this, SLOT(ResetColorOrderSlot())); + + connect(mRestoreBtn, SIGNAL(clicked()), this, SLOT(RestoreDefSlot())); + connect(mApplyBtn, SIGNAL(clicked()), this, SLOT(ApplySlot())); + connect(mCancelBtn, SIGNAL(clicked()), this, SLOT(CancelSlot())); + connect(mOkBtn, SIGNAL(clicked()), this, SLOT(OkSlot())); +} + +void PrefDialog::InitSettings(Settings* set) +{ + mSettings = set; + SetSettings(); +} + +void PrefDialog::SetSettings() +{ + bool sup = SetSuppressSlots(true); + + mMenuBarCb->setChecked(mSettings->mShowMenuBar); + mStatusBarCb->setChecked(mSettings->mShowStatusBar); + mToolBarCb->setChecked(mSettings->mShowToolBar); + + mShowIndicatorsCb->setChecked(mSettings->mShowIndicators); + if (mSettings->mIndicatorType == Settings::INDICATOR_NUMBER) + { + mNumbersRb->setChecked(true); + } + else + { + mLettersRb->setChecked(true); + } + mHideColorsCb->setChecked(mSettings->mHideColors); + + CheckIndicators(); + + int i; + i = mColorCntCmb->findData(mSettings->mColorCnt); + if (i != -1 && mColorCntCmb->currentIndex() != i) + { + mColorCntCmb->setCurrentIndex(i); + } + i = mPegCntCmb->findData(mSettings->mPegCnt); + if (i != -1 && mPegCntCmb->currentIndex() != i) + { + mPegCntCmb->setCurrentIndex(i); + } + + mSameColorsCb->setChecked(mSettings->mSameColors); + CheckLevelPresets(); + + i = mGameModeCmb->findData(mSettings->mGameMode); + if (i != -1 && mGameModeCmb->currentIndex() != i) + { + mGameModeCmb->setCurrentIndex(i); + } + + i = mStrengthCmb->findData(mSettings->mSolverStrength); + if (i != -1 && mStrengthCmb->currentIndex() != i) + { + mStrengthCmb->setCurrentIndex(i); + } + + mAutoCloseCb->setChecked(mSettings->mAutoClose); + mAutoHintsCb->setChecked(mSettings->mAutoHints); + + mDelaySb->setValue(mSettings->mHintsDelay); + + if (sup) + { + SetSuppressSlots(false); + } +} + +void PrefDialog::LevelPresetChangedSlot() +{ + int ix, i; + ix = mLevelPresetsCmb->itemData(mLevelPresetsCmb->currentIndex()).toInt(); + + if (ix < 0 || ix > 4) + { + return; + } + + bool sup = SetSuppressSlots(true); + + i = mColorCntCmb->findData(ColorCode::LEVEL_SETTINGS[ix][0]); + if (i != -1 && mColorCntCmb->currentIndex() != i) + { + mColorCntCmb->setCurrentIndex(i); + } + i = mPegCntCmb->findData(ColorCode::LEVEL_SETTINGS[ix][1]); + if (i != -1 && mPegCntCmb->currentIndex() != i) + { + mPegCntCmb->setCurrentIndex(i); + } + + mSameColorsCb->setChecked((ColorCode::LEVEL_SETTINGS[ix][2] == 1)); + + if (sup) + { + SetSuppressSlots(false); + } +} + +void PrefDialog::CheckLevelPresets() +{ + int ix = -1; + for (int i = 0; i < 5; ++i) + { + if ( ColorCode::LEVEL_SETTINGS[i][0] == mColorCntCmb->itemData(mColorCntCmb->currentIndex()).toInt() + && ColorCode::LEVEL_SETTINGS[i][1] == mPegCntCmb->itemData(mPegCntCmb->currentIndex()).toInt() + && ColorCode::LEVEL_SETTINGS[i][2] == (int) mSameColorsCb->isChecked() ) + { + ix = i; + break; + } + } + + mLevelPresetsCmb->setCurrentIndex(mLevelPresetsCmb->findData(ix)); +} + +void PrefDialog::ColorCntChangedSlot() +{ + if (!mSuppressSlots) + { + CheckLevelPresets(); + } +} + +void PrefDialog::PegCntChangedSlot() +{ + if (!mSuppressSlots) + { + CheckLevelPresets(); + } +} + +void PrefDialog::SameColorsChangedSlot() +{ + if (!mSuppressSlots) + { + CheckLevelPresets(); + } +} + +void PrefDialog::ShowIndicatorsChangedSlot() +{ + if (!mSuppressSlots) + { + CheckIndicators(); + } +} + +void PrefDialog::CheckIndicators() +{ + +} + +void PrefDialog::ResetColorOrderSlot() +{ + emit ResetColorOrderSignal(); +} + +void PrefDialog::RestoreDefSlot() +{ + mSettings->RestoreDefSettings(); + SetSettings(); +} + +void PrefDialog::ApplySlot() +{ + ApplySettings(); + setResult(QDialog::Accepted); + hide(); +} + +void PrefDialog::OkSlot() +{ + ApplySettings(); + setResult(QDialog::Accepted); + hide(); +} + +void PrefDialog::CancelSlot() +{ + setResult(QDialog::Rejected); + hide(); +} + +bool PrefDialog::SetSuppressSlots(bool b, bool force) +{ + if (mSuppressSlots == b && !force) + { + return false; + } + mSuppressSlots = b; + return true; +} + +void PrefDialog::ApplySettings() +{ + mSettings->mShowMenuBar = mMenuBarCb->isChecked(); + mSettings->mShowStatusBar = mStatusBarCb->isChecked(); + mSettings->mShowToolBar = mToolBarCb->isChecked(); + + mSettings->mShowIndicators = mShowIndicatorsCb->isChecked(); + + if (mNumbersRb->isChecked()) + { + mSettings->mIndicatorType = Settings::INDICATOR_NUMBER; + } + else + { + mSettings->mIndicatorType = Settings::INDICATOR_LETTER; + } + mSettings->mHideColors = mHideColorsCb->isChecked(); + + mSettings->mColorCnt = mColorCntCmb->itemData(mColorCntCmb->currentIndex()).toInt(); + mSettings->mPegCnt = mPegCntCmb->itemData(mPegCntCmb->currentIndex()).toInt(); + mSettings->mSameColors = mSameColorsCb->isChecked(); + + mSettings->mGameMode = mGameModeCmb->itemData(mGameModeCmb->currentIndex()).toInt(); + mSettings->mSolverStrength = mStrengthCmb->itemData(mStrengthCmb->currentIndex()).toInt(); + + mSettings->mAutoClose = mAutoCloseCb->isChecked(); + mSettings->mAutoHints = mAutoHintsCb->isChecked(); + mSettings->mHintsDelay = mDelaySb->value(); + + mSettings->Validate(); +} + +QSize PrefDialog::sizeHint () const +{ + return QSize(500, 400); +} diff --git a/plugins/ColorCode_plugin/prefdialog.h b/plugins/ColorCode_plugin/prefdialog.h new file mode 100644 index 000000000..3a87192f8 --- /dev/null +++ b/plugins/ColorCode_plugin/prefdialog.h @@ -0,0 +1,75 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef PREFDIALOG_H +#define PREFDIALOG_H + +#include "ui_prefdialog.h" +#include "settings.h" +#include "colorcode.h" +#include "ccsolver.h" +#include +#include + +class PrefDialog : public QDialog, public Ui::PrefDialog +{ + Q_OBJECT + + public: + PrefDialog(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~PrefDialog(); + + void InitSettings(Settings* set); + void SetSettings(); + virtual QSize sizeHint () const; + + signals: + void ResetColorOrderSignal(); + + private slots: + void ApplySlot(); + void RestoreDefSlot(); + void CancelSlot(); + void OkSlot(); + + void LevelPresetChangedSlot(); + void ColorCntChangedSlot(); + void PegCntChangedSlot(); + void SameColorsChangedSlot(); + void ShowIndicatorsChangedSlot(); + void ResetColorOrderSlot(); + + private: + bool SetSuppressSlots(bool b, bool force = false); + void InitControls(); + void CheckLevelPresets(); + void CheckIndicators(); + void ApplySettings(); + + QPushButton* mRestoreBtn; + QPushButton* mOkBtn; + QPushButton* mApplyBtn; + QPushButton* mCancelBtn; + + Settings* mSettings; + + bool mSuppressSlots; + +}; + +#endif // PREFDIALOG_H diff --git a/plugins/ColorCode_plugin/prefdialog.ui b/plugins/ColorCode_plugin/prefdialog.ui new file mode 100644 index 000000000..85760d0d0 --- /dev/null +++ b/plugins/ColorCode_plugin/prefdialog.ui @@ -0,0 +1,434 @@ + + + PrefDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 500 + 400 + + + + Preferences + + + + :/img/configure.png:/img/configure.png + + + true + + + + + + 1 + + + + Appearance + + + + + 10 + 10 + 451 + 118 + + + + + + + Controls + + + + + + + 0 + 0 + + + + Show or hide the Menubar. + + + Show Menubar + + + + + + + + 0 + 0 + + + + Show or hide the Toolbar. + + + Show Toolbar + + + + + + + + 0 + 0 + + + + Show or hide the Statusbar. + + + Show Statusbar + + + + + + + + + 10 + 140 + 451 + 171 + + + + Indicators + + + + + + + 0 + 0 + + + + If this option is checked, an indicator +inside each peg is displayed. + + + Show Indicators inside pegs + + + + + + + 30 + + + + + + 0 + 0 + + + + Use unique letters as indicators. + + + Letter Indicators + + + + + + + + 0 + 0 + + + + Use unique numbers as indicators. + + + Number Indicators + + + + + + + + 0 + 0 + + + + Use the same neutral background color for each peg, +when indicators are shown. + + + Hide Colors + + + + + + + + + + 0 + 0 + + + + Click here if you have changed the color order +and now you want to revert it to it's initial state. + + + Reset Color Order + + + + + + + + + Game Settings + + + + + 8 + 13 + 461 + 301 + + + + + + + Level Presets + + + + + + + Select from predefined combinations +of the three different level related settings, +the number of colors, the number of slots (columns) +and the possibility of pegs of the same color in one row. + + + + + + + Number of Slots + + + + + + + Number of Colors + + + + + + + Number of pegs in a single row. +Higher values are harder to guess. + + + + + + + Number of all possible colors. +Higher values are harder to guess. + + + + + + + If this option is checked, the hidden combination +may contain one or more (even all would be possible) +pegs of the same color. +If checked, the combination is generally harder to guess. + + + Allow Pegs of Same Color + + + + + + + Qt::Horizontal + + + + + + + Game Mode + + + + + + + Select from the different game modes. +In the 1. mode you have to to guess the hidden, +computer generated combination, +In the 2. mode your computer will try to guess your +own secret combination. + + + + + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + If checked, a row is closed as soon as you place the last peg +and your guess is submitted immediatly. +This option only affects the Human vs. Computer game mode. + + + Close Rows when the last Peg is placed + + + + + + + + 0 + 0 + + + + If checked, the computer will determine the corresponding hints for the solver's guess. +This option affects only Computer vs. Human games. +If checked, you only have to place your secret combination. +Then the rest of the game runs automatically until the end. +But you can set a delay between the guesses. + + + Set Hints automatically + + + + + + + + 0 + 0 + + + + Adjust the delay (in ms) between two guesses. + + + + + + + Delay in ms + + + + + + + Qt::Horizontal + + + + + + + Solver Strength + + + + + + + Select from 3 different strength levels for your computer opponent. +This option only affects the Computer vs. Human game mode. +For the computer's guess in the Human vs. Computer mode +always the highest level will be used. + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + + + + + + + + + + + + 10 + + + 10 + + + true + + + true + + + true + + + diff --git a/plugins/ColorCode_plugin/resource.qrc b/plugins/ColorCode_plugin/resource.qrc new file mode 100644 index 000000000..14ef5fa7d --- /dev/null +++ b/plugins/ColorCode_plugin/resource.qrc @@ -0,0 +1,33 @@ + + + docs/GPL.html + img/application-exit.png + img/document-new.png + img/GNU-icon16.png + img/GNU-icon32.png + img/GNU-icon64.png + img/GNU-icon.png + img/help-about.png + img/qt.png + img/story-editor.png + img/view-refresh.png + trans_de.qm + img/face-sad.png + img/edit-clear.png + img/edit-copy.png + img/system-switch-user.png + img/cc16.png + img/cc32.png + img/cc64.png + cc32.ico + img/business_user.png + trans_cs.qm + img/same_color_0.png + img/same_color_1.png + img/help.png + img/icon_female16.png + img/configure.png + trans_fr.qm + trans_hu.qm + + diff --git a/plugins/ColorCode_plugin/rowhint.cpp b/plugins/ColorCode_plugin/rowhint.cpp new file mode 100644 index 000000000..ee94ad511 --- /dev/null +++ b/plugins/ColorCode_plugin/rowhint.cpp @@ -0,0 +1,310 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include + +#include "rowhint.h" + +using namespace std; + +const int RowHint::mPegPos[4][5][3] = { + { + { 6, 14, 12 }, + { 22, 14, 12 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { + { 6, 6, 12 }, + { 22, 6, 12 }, + { 14, 22, 12 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }, + { + { 6, 6, 12 }, + { 22, 6, 12 }, + { 6, 22, 12 }, + { 22, 22, 12 }, + { 0, 0, 0 }, + }, + { + { 4, 4, 12 }, + { 24, 4, 12 }, + { 14, 14, 12 }, + { 4, 24, 12 }, + { 24, 24, 12 } + } + }; + +RowHint::RowHint(QObject*) +{ + mIx = -1; + mPegCnt = 0; + + mPen = QPen(QColor("#808080")); + mPen.setWidth(2); + + QRadialGradient grad(QPointF(10, 10), 100); + grad.setColorAt(0, QColor("#d8d8d8")); + grad.setColorAt(1, QColor("#ffffff")); + mBrush1 = QBrush(grad); + grad.setColorAt(0, QColor(216, 216, 216, 51)); + grad.setColorAt(1, QColor(255, 255, 255, 51)); + mBrush0 = QBrush(grad); + + Reset(0, 0); +} + +RowHint::~RowHint() +{ + scene()->removeItem(this); +} + +void RowHint::Reset(const int pegcnt, const int gamemode) +{ + mActive = true; + mSolved = false; + SetPegCnt(pegcnt); + mHints.clear(); + mHints.assign(mPegCnt, 0); + SetGameMode(gamemode); + SetActive(false); +} + +int RowHint::GetIx() const +{ + return mIx; +} + +void RowHint::SetIx(const int ix) +{ + mIx = ix; +} + +void RowHint::SetPegCnt(const int pegcnt) +{ + mPegCnt = pegcnt; +} + +void RowHint::SetGameMode(const int gamemode) +{ + mGameMode = gamemode; +} + +bool RowHint::IsActive() const +{ + return mActive; +} + +void RowHint::SetActive(bool b) +{ + if (b == mActive) + { + return; + } + + mActive = b; + setAcceptHoverEvents(b); + setEnabled(b); + if (b) + { + if (mGameMode == ColorCode::MODE_HVM) + { + setCursor(Qt::PointingHandCursor); + setToolTip(tr("Commit Your solution")); + } + else if (mGameMode == ColorCode::MODE_MVH) + { + mSolved = true; + mHints.assign(mPegCnt, 0); + setCursor(Qt::ArrowCursor); + setToolTip(tr("Click the circles to rate my guess.\nHit Ctrl+H or the corresponding toolbar button to let an impartial part of me do this for you ;-)")); + } + } + else + { + setCursor(Qt::ArrowCursor); + setToolTip(QString("")); + } + update(boundingRect()); +} + +std::vector RowHint::GetHints() +{ + return mHints; +} + +void RowHint::DrawHints(std::vector res) +{ + mHints.clear(); + mHints.assign(mPegCnt, 0); + for (unsigned i = 0; i < res.size(); ++i) + { + mHints.at(i) = res.at(i); + } + mSolved = true; + update(boundingRect()); +} + +void RowHint::mousePressEvent(QGraphicsSceneMouseEvent* e) +{ + if (mGameMode == ColorCode::MODE_HVM) + { + bool disabled = false; + if (mActive && !mSolved) + { + if (e->button() == Qt::LeftButton) + { + SetActive(false); + emit HintPressedSignal(mIx); + disabled = true; + } + } + + if (!disabled) + { + QGraphicsItem::mousePressEvent(e); + } + } + else if (mGameMode == ColorCode::MODE_MVH) + { + qreal xm = e->pos().x(); + qreal ym = e->pos().y(); + + int posix = mPegCnt - 2; + for (int i = 0; i < mPegCnt; i++) + { + if ( xm >= mPegPos[posix][i][0] && xm <= mPegPos[posix][i][0] + mPegPos[posix][i][2] + && ym >= mPegPos[posix][i][1] && ym <= mPegPos[posix][i][1] + mPegPos[posix][i][2]) + { + ++mHints.at(i); + if (mHints.at(i) > 2) + { + mHints.at(i) = 0; + } + } + } + update(boundingRect()); + } +} + +QPainterPath RowHint::shape() const +{ + QPainterPath path; + path.addRect(boundingRect()); + return path; +} + +QRectF RowHint::boundingRect() const +{ + const int margin = 1; + return outlineRect().adjusted(-margin, -margin, 2 * margin, 2 * margin); +} + +QRectF RowHint::outlineRect() const +{ + return QRectF(0.0, 0.0, 40.0, 40.0); +} + +void RowHint::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /* widget */) +{ + if (mPegCnt == 0) + { + return; + } + + int i; + + QColor pend = QColor("#646568"); + QColor penl = QColor("#ecedef"); + QColor grad0 = QColor("#cccdcf"); + QColor grad1 = QColor("#fcfdff"); + if (mActive) + { + pend.setAlpha(0xff); + penl.setAlpha(0xff); + grad0.setAlpha(0xff); + grad1.setAlpha(0xff); + } + else if (mSolved) + { + pend.setAlpha(0xa0); + penl.setAlpha(0xa0); + grad0.setAlpha(0xa0); + grad1.setAlpha(0xa0); + } + else + { + pend.setAlpha(0x32); + penl.setAlpha(0x50); + grad0.setAlpha(0x32); + grad1.setAlpha(0x32); + } + painter->setPen(Qt::NoPen); + + painter->setBrush(QBrush(penl)); + painter->drawRect(QRectF(0.0, 0.0, 39, 1)); + painter->drawRect(QRectF(0.0, 0.0, 1, 39)); + painter->setBrush(QBrush(pend)); + painter->drawRect(QRectF(0.0, 39.0, 40, 1)); + painter->drawRect(QRectF(39, 0.0, 1, 40)); + + QRadialGradient grad(QPointF(10, 10), 100); + grad.setColorAt(0, grad0); + grad.setColorAt(1, grad1); + painter->setBrush(QBrush(grad)); + painter->drawRect(QRectF(1, 1.0, 38.0, 38.0)); + + painter->setBrush(Qt::NoBrush); + + int posix = mPegCnt - 2; + QPointF x0; + for (i = 0; i < mPegCnt; i++) + { + x0 = QPointF(mPegPos[posix][i][0], mPegPos[posix][i][1]); + QLinearGradient lgrad(x0, QPointF(x0.x() + 10, x0.y() + 10)); + lgrad.setColorAt(0.0, QColor(0, 0, 0, 0xa0)); + lgrad.setColorAt(1.0, QColor(0xff, 0xff, 0xff, 0xa0)); + painter->setPen(QPen(QBrush(lgrad), 0.5)); + painter->drawEllipse(QRectF(mPegPos[posix][i][0], mPegPos[posix][i][1], mPegPos[posix][i][2], mPegPos[posix][i][2])); + } + + if (mSolved) + { + painter->setPen(Qt::NoPen); + for (unsigned i = 0; i < mHints.size(); i++) + { + if (mHints.at(i) == 0) + { + continue; + } + + if (mHints.at(i) == 2) + { + painter->setBrush(QBrush(Qt::black)); + } + else + { + painter->setBrush(QBrush(Qt::white)); + } + painter->drawEllipse(QRectF(mPegPos[posix][i][0], mPegPos[posix][i][1], mPegPos[posix][i][2], mPegPos[posix][i][2])); + } + } +} diff --git a/plugins/ColorCode_plugin/rowhint.h b/plugins/ColorCode_plugin/rowhint.h new file mode 100644 index 000000000..4a8ab3be5 --- /dev/null +++ b/plugins/ColorCode_plugin/rowhint.h @@ -0,0 +1,76 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef ROWHINT_H +#define ROWHINT_H + +#include +#include +#include +#include +#include +#include +#include "colorcode.h" + +class RowHint : public QObject, public QGraphicsItem +{ + Q_OBJECT + +public: + RowHint(QObject* parent = 0); + ~RowHint(); + + int mIx; + bool mActive; + bool mSolved; + std::vector mHints; + + int GetIx() const; + bool IsActive() const; + std::vector GetHints(); + void SetIx(const int ix); + void SetPegCnt(const int pegcnt); + void SetGameMode(const int gamemode); + void SetActive(bool b); + void DrawHints(std::vector res); + void Reset(const int pegcnt, const int gamemode); + + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); + QRectF boundingRect() const; + QPainterPath shape() const; + +signals: + void HintPressedSignal(int ix); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent* e); + +private: + static const int mPegPos[4][5][3]; + + int mPegCnt; + int mGameMode; + + QPen mPen; + QBrush mBrush0; + QBrush mBrush1; + + QRectF outlineRect() const; +}; + +#endif // ROWHINT_H diff --git a/plugins/ColorCode_plugin/settings.cpp b/plugins/ColorCode_plugin/settings.cpp new file mode 100644 index 000000000..13d6f5276 --- /dev/null +++ b/plugins/ColorCode_plugin/settings.cpp @@ -0,0 +1,213 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include "settings.h" +#include "colorcode.h" +#include "ccsolver.h" + +using namespace std; + +const int Settings::INDICATOR_LETTER = 0; +const int Settings::INDICATOR_NUMBER = 1; + +Settings::Settings() +{ + mSettings.setDefaultFormat(QSettings::IniFormat); + mSettings.setFallbacksEnabled(false); + + InitSettings(); + SaveSettingsMap(mDefMap); + ReadSettings(); + SaveSettingsMap(mLastMap); +} + +Settings::~Settings() +{ +} + +void Settings::InitSettings() +{ + mShowToolBar = true; + mShowMenuBar = true; + mShowStatusBar = true; + + mShowIndicators = false; + mIndicatorType = INDICATOR_LETTER; + + mHideColors = false; + + mPegCnt = 4; + mColorCnt = 8; + mSameColors = true; + mGameMode = ColorCode::MODE_HVM; + mAutoClose = false; + mAutoHints = false; + mHintsDelay = 500; + + mSolverStrength = CCSolver::STRENGTH_HIGH; +} + +void Settings::SaveLastSettings() +{ + SaveSettingsMap(mLastMap); +} + +void Settings::RestoreLastSettings() +{ + RestoreSettingsMap(mLastMap); +} + +void Settings::RestoreDefSettings() +{ + RestoreSettingsMap(mDefMap); +} + +void Settings::RestoreSettingsMap(QMap &map) +{ + mShowToolBar = map["ShowToolBar"].toBool(); + mShowMenuBar = map["ShowMenuBar"].toBool(); + mShowStatusBar = map["ShowStatusBar"].toBool(); + + mShowIndicators = map["ShowIndicators"].toBool(); + mIndicatorType = map["IndicatorType"].toInt(); + mHideColors = map["HideColors"].toBool(); + + mPegCnt = map["ColumnCount"].toInt(); + mColorCnt = map["ColorCount"].toInt(); + mSameColors = map["SameColors"].toBool(); + + mGameMode = map["GameMode"].toInt(); + mAutoClose = map["AutoClose"].toBool(); + mAutoHints = map["AutoHints"].toBool(); + mHintsDelay = map["HintsDelay"].toInt(); + + mSolverStrength = map["SolverStrength"].toInt(); + Validate(); +} + +void Settings::SaveSettingsMap(QMap &map) +{ + map["ShowToolBar"] = mShowToolBar; + map["ShowMenuBar"] = mShowMenuBar; + map["ShowStatusBar"] = mShowStatusBar; + + map["ShowIndicators"] = mShowIndicators; + map["IndicatorType"] = mIndicatorType; + map["HideColors"] = mHideColors; + + map["ColumnCount"] = mPegCnt; + map["ColorCount"] = mColorCnt; + map["SameColors"] = mSameColors; + + map["GameMode"] = mGameMode; + map["AutoClose"] = mAutoClose; + map["AutoHints"] = mAutoHints; + map["HintsDelay"] = mHintsDelay; + + map["SolverStrength"] = mSolverStrength; +} + +void Settings::ReadSettings() +{ + mSettings.beginGroup("Appearance"); + mShowToolBar = mSettings.value("ShowToolBar", mShowToolBar).toBool(); + mShowMenuBar = mSettings.value("ShowMenuBar", mShowMenuBar).toBool(); + mShowStatusBar = mSettings.value("ShowStatusBar", mShowStatusBar).toBool(); + + mShowIndicators = mSettings.value("ShowIndicators", mShowIndicators).toBool(); + mIndicatorType = mSettings.value("IndicatorType", mIndicatorType).toInt(); + mHideColors = mSettings.value("HideColors", mHideColors).toBool(); + mSettings.endGroup(); + + mSettings.beginGroup("Game"); + mPegCnt = mSettings.value("ColumnCount", mPegCnt).toInt(); + mColorCnt = mSettings.value("ColorCount", mColorCnt).toInt(); + mSameColors = mSettings.value("SameColors", mSameColors).toBool(); + + mGameMode = mSettings.value("GameMode", mGameMode).toInt(); + mAutoClose = mSettings.value("AutoClose", mAutoClose).toBool(); + mAutoHints = mSettings.value("AutoHints", mAutoHints).toBool(); + mHintsDelay = mSettings.value("HintsDelay", mHintsDelay).toInt(); + + mSolverStrength = mSettings.value("SolverStrength", mSolverStrength).toInt(); + + mSettings.endGroup(); + Validate(); +} + +void Settings::Validate() +{ + if (mIndicatorType != INDICATOR_LETTER && mIndicatorType != INDICATOR_NUMBER) + { + mIndicatorType = INDICATOR_LETTER; + } + if (mPegCnt < 2 || mPegCnt > 5) + { + mPegCnt = 4; + } + if (mColorCnt < 2 || mColorCnt > 10) + { + mColorCnt = 8; + } + if (mGameMode != ColorCode::MODE_HVM && mGameMode != ColorCode::MODE_MVH) + { + mGameMode = ColorCode::MODE_HVM; + } + if (mSolverStrength < CCSolver::STRENGTH_LOW || mSolverStrength > CCSolver::STRENGTH_HIGH) + { + mSolverStrength = CCSolver::STRENGTH_HIGH; + } + if (mHintsDelay > 10000) + { + mHintsDelay = 10000; + } + else if (mHintsDelay < 0) + { + mHintsDelay = 0; + } +} + +void Settings::WriteSettings() +{ + mSettings.beginGroup("Appearance"); + mSettings.setValue("ShowToolBar", mShowToolBar); + mSettings.setValue("ShowMenuBar", mShowMenuBar); + mSettings.setValue("ShowStatusBar", mShowStatusBar); + + mSettings.setValue("ShowIndicators", mShowIndicators); + mSettings.setValue("IndicatorType", mIndicatorType); + mSettings.setValue("HideColors", mHideColors); + mSettings.endGroup(); + + mSettings.beginGroup("Game"); + mSettings.setValue("ColumnCount", mPegCnt); + mSettings.setValue("ColorCount", mColorCnt); + mSettings.setValue("SameColors", mSameColors); + + mSettings.setValue("GameMode", mGameMode); + mSettings.setValue("AutoClose", mAutoClose); + mSettings.setValue("AutoHints", mAutoHints); + mSettings.setValue("HintsDelay", mHintsDelay); + + mSettings.setValue("SolverStrength", mSolverStrength); + mSettings.endGroup(); + + mSettings.sync(); +} + + diff --git a/plugins/ColorCode_plugin/settings.h b/plugins/ColorCode_plugin/settings.h new file mode 100644 index 000000000..c3738a448 --- /dev/null +++ b/plugins/ColorCode_plugin/settings.h @@ -0,0 +1,67 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef SETTINGS_H +#define SETTINGS_H + +#include +#include + +class Settings +{ + public: + Settings(); + ~Settings(); + + static const int INDICATOR_LETTER; + static const int INDICATOR_NUMBER; + + void InitSettings(); + void ReadSettings(); + void Validate(); + void SaveLastSettings(); + void RestoreLastSettings(); + void RestoreDefSettings(); + void WriteSettings(); + + QSettings mSettings; + + bool mShowToolBar; + bool mShowMenuBar; + bool mShowStatusBar; + bool mShowIndicators; + int mIndicatorType; + bool mHideColors; + + int mPegCnt; + int mColorCnt; + bool mSameColors; + int mGameMode; + bool mAutoClose; + bool mAutoHints; + int mSolverStrength; + int mHintsDelay; + + private: + void RestoreSettingsMap(QMap &map); + void SaveSettingsMap(QMap &map); + QMap mDefMap; + QMap mLastMap; +}; + +#endif // SETTINGS_H diff --git a/plugins/ColorCode_plugin/solrow.cpp b/plugins/ColorCode_plugin/solrow.cpp new file mode 100644 index 000000000..32c6b7c92 --- /dev/null +++ b/plugins/ColorCode_plugin/solrow.cpp @@ -0,0 +1,97 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include +#include "solrow.h" + +using namespace std; + +SolRow::SolRow() +{ + setCacheMode(QGraphicsItem::DeviceCoordinateCache); + + mPegCnt = 0; + mSolved = false; + + mRect = QRectF(0.5, 0.5, 219, 39); + mRectC = QRectF(2, 2, 216, 36); + + QLinearGradient solgrad(0, 0, 0, 40); + solgrad.setColorAt(0.0, QColor("#9fa0a2")); + solgrad.setColorAt(1.0, QColor("#8c8d8f")); + mBgBrush = QBrush(solgrad); + + QLinearGradient framegrad(0, 0, 0, 40); + framegrad.setColorAt(0.0, QColor("#4e4f51")); + framegrad.setColorAt(1.0, QColor("#ebecee")); + mFramePen = QPen(QBrush(framegrad), 1); + + mFont = QFont("Arial", 22, QFont::Bold, false); + mFont.setStyleHint(QFont::SansSerif); +} + +void SolRow::SetState(const int pegcnt, const bool solved) +{ + mPegCnt = pegcnt; + mSolved = solved; + update(boundingRect()); +} + +QRectF SolRow::boundingRect() const +{ + const double margin = 0.5; + return mRect.adjusted(-margin, -margin, 2 * margin, 2 * margin); +} + +void SolRow::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget* /* widget */) +{ + if (mPegCnt == 0) + { + return; + } + + int i; + painter->setBrush(mBgBrush); + painter->setPen(mFramePen); + painter->drawRoundedRect(mRect, 20, 20); + + QPainterPath cpath; + cpath.addRoundedRect(mRectC, 19, 19); + painter->setClipPath(cpath); + + painter->setRenderHint(QPainter::TextAntialiasing, true); + + int x0 = (220 - mPegCnt * 40) / 2; + int xpos; + for (i = 0; i <= mPegCnt; ++i) + { + xpos = x0 + i * 40; + painter->setPen(Qt::NoPen); + painter->setBrush(QBrush(QColor(0x7d, 0x7e, 0x80, 0x80))); + painter->drawRect(xpos - 1, 1, 1, 38); + painter->setBrush(QBrush(QColor(0xc3, 0xc4, 0xc6, 0x80))); + painter->drawRect(xpos, 1, 1, 38); + + if (i < mPegCnt) + { + painter->setPen(QPen(QColor("#ff9933"))); + painter->setFont(mFont); + painter->drawText(QRectF(xpos + 3.0, 3.0, 34.0, 34.0), Qt::AlignCenter, QString('?')); + } + } +} diff --git a/plugins/ColorCode_plugin/solrow.h b/plugins/ColorCode_plugin/solrow.h new file mode 100644 index 000000000..a87dcf168 --- /dev/null +++ b/plugins/ColorCode_plugin/solrow.h @@ -0,0 +1,45 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef SOLROW_H +#define SOLROW_H + +#include +#include + +class SolRow : public QGraphicsItem +{ +public: + SolRow(); + + void SetState(const int pegcnt, const bool solved); + QRectF boundingRect() const; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); + +private: + QRectF mRect; + QRectF mRectC; + QBrush mBgBrush; + QPen mFramePen; + QFont mFont; + + int mPegCnt; + bool mSolved; +}; + +#endif // SOLROW_H diff --git a/plugins/ColorCode_plugin/solutionrow.cpp b/plugins/ColorCode_plugin/solutionrow.cpp new file mode 100644 index 000000000..217007376 --- /dev/null +++ b/plugins/ColorCode_plugin/solutionrow.cpp @@ -0,0 +1,100 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#include +#include "solutionrow.h" + +using namespace std; + +SolutionRow::SolutionRow(QObject*) +{ + setCacheMode(QGraphicsItem::DeviceCoordinateCache); + InitGraphics(); +} + +SolutionRow::~SolutionRow() +{ +} + +void SolutionRow::InitGraphics() +{ + mRect = QRectF(0.5, 0.5, 219, 39); + mRectC = QRectF(2, 2, 216, 36); + + QLinearGradient solgrad(0, 0, 0, 40); + solgrad.setColorAt(0.0, QColor("#9fa0a2")); + solgrad.setColorAt(1.0, QColor("#8c8d8f")); + mBgBrush = QBrush(solgrad); + + QLinearGradient framegrad(0, 0, 0, 40); + framegrad.setColorAt(0.0, QColor("#4e4f51")); + framegrad.setColorAt(1.0, QColor("#ebecee")); + mFramePen = QPen(QBrush(framegrad), 1); + + mFont = QFont("Arial", 22, QFont::Bold, false); + mFont.setStyleHint(QFont::SansSerif); +} + +void SolutionRow::SetXOffs() +{ + mXOffs = 110 - mPegCnt * 20; +} + +QRectF SolutionRow::boundingRect() const +{ + const double margin = 0.5; + return mRect.adjusted(-margin, -margin, 2 * margin, 2 * margin); +} + +void SolutionRow::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget* /* widget */) +{ + if (mPegCnt == 0) + { + return; + } + + int i; + painter->setBrush(mBgBrush); + painter->setPen(mFramePen); + painter->drawRoundedRect(mRect, 20, 20); + + QPainterPath cpath; + cpath.addRoundedRect(mRectC, 19, 19); + painter->setClipPath(cpath); + + painter->setRenderHint(QPainter::TextAntialiasing, true); + + int x0 = (220 - mPegCnt * 40) / 2; + int xpos; + for (i = 0; i <= mPegCnt; ++i) + { + xpos = x0 + i * 40; + painter->setPen(Qt::NoPen); + painter->setBrush(QBrush(QColor(0x7d, 0x7e, 0x80, 0x80))); + painter->drawRect(xpos - 1, 1, 1, 38); + painter->setBrush(QBrush(QColor(0xc3, 0xc4, 0xc6, 0x80))); + painter->drawRect(xpos, 1, 1, 38); + + if (i < mPegCnt) + { + painter->setPen(QPen(QColor("#ff9933"))); + painter->setFont(mFont); + painter->drawText(QRectF(xpos + 3.0, 3.0, 34.0, 34.0), Qt::AlignCenter, QString('?')); + } + } +} diff --git a/plugins/ColorCode_plugin/solutionrow.h b/plugins/ColorCode_plugin/solutionrow.h new file mode 100644 index 000000000..7c7787f2c --- /dev/null +++ b/plugins/ColorCode_plugin/solutionrow.h @@ -0,0 +1,50 @@ +/* ColorCode, a free MasterMind clone with built in solver + * Copyright (C) 2009 Dirk Laebisch + * http://www.laebisch.com/ + * + * ColorCode is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ColorCode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ColorCode. If not, see . +*/ + +#ifndef SOLUTIONROW_H +#define SOLUTIONROW_H + +#include +#include +#include +#include "pegrow.h" + +class SolutionRow : public PegRow +{ + +public: + SolutionRow(QObject* parent = 0); + ~SolutionRow(); + + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); + QRectF boundingRect() const; + +protected: + void SetXOffs(); + +private: + void InitGraphics(); + + QRectF mRect; + QRectF mRectC; + QBrush mBgBrush; + QPen mFramePen; + QFont mFont; +}; + +#endif // SOLUTIONROW_H diff --git a/plugins/ColorCode_plugin/trans_cs.qm b/plugins/ColorCode_plugin/trans_cs.qm new file mode 100644 index 000000000..6cb548ce1 Binary files /dev/null and b/plugins/ColorCode_plugin/trans_cs.qm differ diff --git a/plugins/ColorCode_plugin/trans_cs.ts b/plugins/ColorCode_plugin/trans_cs.ts new file mode 100644 index 000000000..c467b8119 --- /dev/null +++ b/plugins/ColorCode_plugin/trans_cs.ts @@ -0,0 +1,667 @@ + + + +UTF-8 + + About + + &Author + &Autor + + + icon + ikona + + + &License + &Povolení + + + A needful game to train your brain ;-) + Hra potřebná pro udržení bdělosti <br>vašeho mozku :-) + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Tento program je svobodným. Můžete jej šířit a/nebo upravovat za podmínek GNU General Public License, jak jsou zveřejněny Free Software Foundation, buď podle verze 2 licence nebo (podle své volby) podle jakékoli pozdější verze. + + + ColorCode + ColorCode + + + About ColorCode + O ColorCode + + + <br><br>Free MasterMind clone including a built in,<br>rather intelligent solver. + <br><br>Klon Free MasterMind s vestavěným<br>celkem schopným řešitelem. + + + Version + Verze + + + Author + Autor + + + + ColorCode + + New Game + Nová hra + + + Do you want to give in +and start a new Game? + Chcete vzdát hru +a začít novou? + + + About Qt + O Qt + + + &New Game + &Nová hra + + + Ctrl+N + Ctrl+N + + + &Restart Game + &Začít hru znovu + + + Ctrl+R + Ctrl+R + + + E&xit + &Ukončit + + + Ctrl+Q + Ctrl+Q + + + Ctrl+T + Ctrl+T + + + Ctrl+C + Ctrl+C + + + Ctrl+A + Ctrl+A + + + About &Qt + O &Qt + + + &Game + &Hra + + + &Settings + &Nastavení + + + &Help + &Nápověda + + + Game + Hra + + + Message + Hlášení + + + The changed settings will only apply to new games! +Do you want to give in the current and start a new Game? + Změny v nastavení se projeví teprve po novém spuštění hry! +Chcete vzdát nynější hru a začít novou? + + + Place Your pegs ... + Umístěte své kameny... + + + Congratulation! You have won! + Blahopřejeme! Vyhrál jste! + + + Sorry! You lost! + Promiňte, ale nezvládl jste to! + + + Ctrl+I + Ctrl+I + + + Give In + Vzdát se + + + Do you really want to give in? + Skutečně chcete hru vzdát? + + + &Throw In The Towel + &Vhodit ručník + + + Ctrl+G + Ctrl+G + + + Sure, You're too weak for me! + Je jasné, že jste pro mě příliš slabý! + + + Ctrl+Shift+R + Ctrl+Shift+R + + + Ctrl+Shift+C + Ctrl+Shift+C + + + Fill Row by Random + Naplnit řádek náhodně + + + Duplicate Previous Row + Zdvojit předchozí řádek + + + Ctrl+D + Ctrl+D + + + Clear Row + Vyprázdnit řádek + + + &Row + &Řádek + + + ColorCode + ColorCode + + + About &ColorCode + O &ColorCode + + + Ctrl+M + Ctrl+M + + + Ctrl+S + Ctrl+S + + + Show Toolbar + Ukázat nástrojový pruh + + + Show Menubar + Ukázat pruh s hlavní nabídkou + + + Show Statusbar + Ukázat stavový pruh + + + Allow Pegs of the Same Color + Povolit kameny se stejnou barvou + + + Level + Stupeň obtížnosti + + + Computer's Guess + Nechat počítač hádat + + + Ctrl+H + Ctrl+H + + + Press the Hint Field or Key Enter if You're done. + Pokud jste hotov, klepněte na pole s radou. + + + Disallow Pegs of the Same Color + Zákázat kameny stejné barvy + + + Close Rows when the last Peg is placed + Zavřít řádky po umístění posledního kamene + + + Ctrl+L + Ctrl+L + + + Beginner (2 Colors, 2 Slots, Doubles) + Začátečník (2 barvy, 2 pole, zdvojení) + + + Easy (4 Colors, 3 Slots, No Doubles) + Lehká hra (4 barvy, 3 pole, bez zdvojení) + + + Classic (6 Colors, 4 Slots, Doubles) + Klasická hra (6 barev, 4 pole, zdvojení) + + + Challenging (8 Colors, 4 Slots, Doubles) + Náročná hra (8 barev, 4 pole, zdvojení) + + + Hard (10 Colors, 5 Slots, Doubles) + Těžká hra (10 barev, 5 polí, zdvojení) + + + Level Presets + Přednastavení stupně obtížnosti + + + Colors + barev + + + Pegs of Same Color + Kameny téže barvy + + + Slots + pole + + + Yes + Ano + + + No + Ne + + + Reset Color Order + Znovu nastavit pořadí barev + + + Ctrl+Shift+L + Ctrl+Shift+L + + + Online &Help + &Nápověda po internetu + + + F1 + F1 + + + Done + Hotovo + + + Ctrl+Shift+N + Ctrl+Shift+N + + + Rate it for me + Ohodnoť to pro mě + + + Human vs Computer + Člověk proti počítači + + + Computer vs Human + Počítač proti člověku + + + Game Mode + Herní režim + + + Press the button below or Key Enter if You're done. + Pokud jste hotov, použijte tlačítko dole nebo klávesu Enter. + + + Place Your secret ColorCode ... + Umístěte svůj tajný ColorCode... + + + Please rate the guess. Press OK or Key Enter if You're done. + Ohodnoťte, prosím, můj návrh. Pokud jste hotov, použijte tlačítko OK nebo klávesu Enter. + + + The impossible happened, sorry. + Bohužel se stalo nemožné. + + + Yeah! I guessed it, man! + Jo! Já to tušil! + + + Embarrassing! I lost a game! + Trapné! Já tu hru ztratil! + + + Nope! Thats impossible! Did you gave me false hints? + Ne! To není možné! Dal jste mi špatné rady? + + + Don't you like to see me winning? ;-) + Nelíbí se vám, když vyhrávám? :-) + + + Set Hints automatically + Nastavit rady automaticky + + + Ctrl+Shift+H + Ctrl+Shift+H + + + Preferences + Nastavení + + + Ctrl+P + Ctrl+P + + + Show Indicators + Ukázat ukazatele + + + The chosen settings do not allow pegs of the same color! + Zvolená nastavení nedovolují kameny stejné barvy. + + + + PrefDialog + + ... Select from predefined level settings + ... Vybrat stupeň obtížnosti + + + Beginner (2 Colors, 2 Slots, Doubles) + Začátečník (2 barvy, 2 pole, zdvojení) + + + Easy (4 Colors, 3 Slots, No Doubles) + Lehká hra (4 barvy, 3 pole, bez zdvojení) + + + Classic (6 Colors, 4 Slots, Doubles) + Klasická hra (6 barev, 4 pole, zdvojení) + + + Challenging (8 Colors, 4 Slots, Doubles) + Náročná hra (8 barev, 4 pole, zdvojení) + + + Hard (10 Colors, 5 Slots, Doubles) + Těžká hra (10 barev, 5 polí, zdvojení) + + + Slots + pole + + + Colors + barev + + + Human vs. Computer + Člověk proti počítači + + + Computer vs. Human + Člověk proti počítači + + + Low + Nízká + + + Medium + Střední + + + High + Vysoká + + + Preferences + Nastavení + + + Appearance + Vzhled + + + Controls + Ovládací prvky + + + Show or hide the Menubar. + Ukázat nebo skrýt pruh s hlavní nabídkou. + + + Show Menubar + Ukázat pruh s hlavní nabídkou + + + Show or hide the Toolbar. + Ukázat nebo skrýt nástrojový pruh. + + + Show Toolbar + Ukázat nástrojový pruh + + + Show or hide the Statusbar. + Ukázat nebo skrýt stavový pruh. + + + Show Statusbar + Ukázat stavový pruh + + + Indicators + Ukazatelé + + + If this option is checked, an indicator +inside each peg is displayed. + Když je zapnuta tato volba, je u každého +kamene zobrazen dodatečný ukazatel. + + + Show Indicators inside pegs + Ukázat dodatečné ukazatele pro kameny + + + Use unique letters as indicators. + Použít písmena jako ukazatele. + + + Letter Indicators + Písmenní ukazatelé + + + Use unique numbers as indicators. + Použít čísla jako ukazatele. + + + Number Indicators + Číselní ukazatelé + + + Use the same neutral background color for each peg, +when indicators are shown. + Pro všechny kameny použít, v případě že jsou zobrazováni ukazatelé, +stejnou nenápadnou barvu pozadí. + + + Hide Colors + Skrýt barvy + + + Click here if you have changed the color order +and now you want to revert it to it's initial state. + Klepněte sem, pokud jste změnil pořadí barev, +a nyní to chcete vrátit do počátečního stavu. + + + Reset Color Order + Znovu nastavit pořadí barev + + + Game Settings + Herní nastavení + + + Level Presets + Přednastavení stupně obtížnosti + + + Select from predefined combinations +of the three different level related settings, +the number of colors, the number of slots (columns) +and the possibility of pegs of the same color in one row. + Vyberte z přednastavených spojení tří různých +nastavení souvisejících se stupni obtížnosti: +počet barev, počet polí (sloupců) a možnost +kamenů stejné barvy v jednom řádku. + + + Number of Slots + Počet polí + + + Number of Colors + Počet barev + + + Number of pegs in a single row. +Higher values are harder to guess. + Počet kamenů v jednom řádku. +Vyšší hodnoty je těžší uhodnout. + + + Number of all possible colors. +Higher values are harder to guess. + Celkový počet všech možných barev. +Vyšší hodnoty je těžší uhodnout. + + + If this option is checked, the hidden combination +may contain one or more (even all would be possible) +pegs of the same color. +If checked, the combination is generally harder to guess. + Když je zapnuta tato volba, skryté spojení může +obsahovat jeden nebo více kamenů stejné barvy +(dokonce je možné, že všechny). +Je-li zaškrtnuto, je spojení obecně obtížněji uhodnutelné. + + + Allow Pegs of Same Color + Povolit kameny téže barvy + + + Game Mode + Herní režim + + + Select from the different game modes. +In the 1. mode you have to to guess the hidden, +computer generated combination, +In the 2. mode your computer will try to guess your +own secret combination. + Vyberte z různých herních režimů. +V prvním režimu musíte uhodnout skryté, +počítačem vytvořené spojení. +Ve druhém režimu se počítač pokusí uhodnout +vaše vlastní tajné spojení. + + + If checked, a row is closed as soon as you place the last peg +and your guess is submitted immediatly. +This option only affects the Human vs. Computer game mode. + Když je zapnuta tato volba, je řádek uzavřen, jakmile umístíte poslední kámen +a váš herní tah je okamžitě vyhodnocen. +Tato volba účinkuje pouze v herním režimu, kdy hraje člověk proti počítači. + + + Close Rows when the last Peg is placed + Zavřít řádky po umístění posledního kamene + + + If checked, the computer will determine the corresponding hints for the solver's guess. +This option affects only Computer vs. Human games. +If checked, you only have to place your secret combination. +Then the rest of the game runs automatically until the end. +But you can set a delay between the guesses. + Je-li zapnuta tato volba, budou automaticky vyplněna pole s ödpovídajícími radami pro odhad počítače. +Tato volba účinkuje pouze při hře počítače proti člověku. +Je-li zaškrtnuta, musíte pouze umístit své tajné spojení. +Pak běží zbytek hry automaticky až do konce. +Ovšem mezi herními tahy můžete nastavit zpoždění. + + + Set Hints automatically + Nastavit rady automaticky + + + Adjust the delay (in ms) between two guesses. + Upravit zpoždění v milisekundách mezi dvěma herními tahy. + + + Delay in ms + Zpoždění v ms + + + Solver Strength + Síla počítače + + + Select from 3 different strength levels for your computer opponent. +This option only affects the Computer vs. Human game mode. +For the computer's guess in the Human vs. Computer mode +always the highest level will be used. + Vyberte jednu ze tří různých herních sil pro vašeho počítačového protivníka. +Tato volba účinkuje pouze v herním režimu, kdy hraje počítač proti člověku. +Pro počítačův herní tah v režimu, kdy hraje člověk proti počítači se vždy použije +nejvyšší úroveň herní síly. + + + + RowHint + + Commit Your solution + Vyzkoušet své řešení + + + Click the circles to rate my guess. +Hit Ctrl+H or the corresponding toolbar button to let an impartial part of me do this for you ;-) + Klepněte na kruhy pro vyhodnocení mého herního tahu. +Stiskněte Ctrl+H nebo odpovídající tlačítko v nástrojovém pruhu, abyste přenesl onu záležitost s vyhodnocením na tu moji část, která je v tomto případě zcela nestranná. :-) + + + diff --git a/plugins/ColorCode_plugin/trans_de.qm b/plugins/ColorCode_plugin/trans_de.qm new file mode 100644 index 000000000..26fc1a7a2 Binary files /dev/null and b/plugins/ColorCode_plugin/trans_de.qm differ diff --git a/plugins/ColorCode_plugin/trans_de.ts b/plugins/ColorCode_plugin/trans_de.ts new file mode 100644 index 000000000..8a02d2406 --- /dev/null +++ b/plugins/ColorCode_plugin/trans_de.ts @@ -0,0 +1,664 @@ + + + +UTF-8 + + About + + &Author + &Autor + + + icon + + + + &License + &Lizenz + + + A needful game to train your brain ;-) + Ein Spiel, um den Verstand<br>wachzuhalten ;-) + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder (nach Ihrer Option) jeder späteren Version. + + + ColorCode + ColorCode + + + About ColorCode + Info ColorCode + + + <br><br>Free MasterMind clone including a built in,<br>rather intelligent solver. + <br><br>Freie MasterMind-Variante mit ziemlich <br>intelligentem Rechner-Spieler. + + + Version + Version + + + Author + Autor + + + + ColorCode + + New Game + Neues Spiel + + + Do you want to give in +and start a new Game? + Wollen Sie aufgeben und +ein neues Spiel beginnen? + + + About Qt + Info Qt + + + &New Game + &Neues Spiel + + + Ctrl+N + + + + &Restart Game + Spiel neu &beginnen + + + Ctrl+R + + + + E&xit + B&eenden + + + Ctrl+Q + + + + Ctrl+T + + + + Ctrl+C + + + + Ctrl+A + + + + About &Qt + Info &Qt + + + &Game + &Spiel + + + &Settings + &Einstellungen + + + &Help + &Hilfe + + + Game + Spiel + + + Message + Hinweis + + + The changed settings will only apply to new games! +Do you want to give in the current and start a new Game? + Die geänderten Einstellungen werden erst in neuen Spielen berücksichtigt! +Möchten Sie das gegenwärtige Spiel aufgeben und ein neues Spiel beginnen? + + + Place Your pegs ... + Setzen Sie Ihre Steine ... + + + Congratulation! You have won! + Glückwunsch! Sie haben gewonnen! + + + Sorry! You lost! + Schade, aber Sie haben es nicht vermocht! + + + Ctrl+I + + + + Give In + Aufgeben + + + Do you really want to give in? + Wollen Sie wirklich aufgeben? + + + &Throw In The Towel + &Handtuch werfen + + + Ctrl+G + + + + Sure, You're too weak for me! + Klar, Sie sind zu schwach für mich! + + + Ctrl+Shift+R + + + + Ctrl+Shift+C + + + + Fill Row by Random + Reihe zufällig füllen + + + Duplicate Previous Row + Vorherige Reihe duplizieren + + + Ctrl+D + + + + Clear Row + Reihe leeren + + + &Row + &Reihe + + + ColorCode + ColorCode + + + About &ColorCode + Info &ColorCode + + + Ctrl+M + + + + Ctrl+S + + + + Show Toolbar + Werkzeugleiste anzeigen + + + Show Menubar + Menüleiste anzeigen + + + Show Statusbar + Statusleiste anzeigen + + + Allow Pegs of the Same Color + Steine gleicher Farbe erlauben + + + Level + Schwierigkeitsgrad + + + Computer's Guess + Lassen Sie Ihren Rechner raten + + + Ctrl+H + + + + Press the Hint Field or Key Enter if You're done. + Fertig? Benutzen Sie das Hinweis-Feld oder die Eingabetaste. + + + Disallow Pegs of the Same Color + Keine Steine gleicher Farbe erlauben + + + Close Rows when the last Peg is placed + Reihen nach Setzen des letzten Steins auswerten + + + Ctrl+L + + + + Beginner (2 Colors, 2 Slots, Doubles) + Anfänger (2 Farben, 2 Slots, Doppelte) + + + Easy (4 Colors, 3 Slots, No Doubles) + Leicht (4 Farben, 3 Slots, Keine Doppelten) + + + Classic (6 Colors, 4 Slots, Doubles) + Klassisch (6 Farben, 4 Slots, Doppelte) + + + Challenging (8 Colors, 4 Slots, Doubles) + Fordernd (8 Farben, 4 Slots, Doppelte) + + + Hard (10 Colors, 5 Slots, Doubles) + Schwer (10 Farben, 5 Slots, Doppelte) + + + Level Presets + Schwierigkeitsstufen + + + Colors + Farben + + + Pegs of Same Color + Steine gleicher Farbe + + + Slots + Felder + + + Yes + Ja + + + No + Nein + + + Reset Color Order + Farbreihenfolge zurücksetzen + + + Ctrl+Shift+L + + + + Online &Help + Online-&Hilfe + + + F1 + + + + Done + Fertig + + + Ctrl+Shift+N + + + + Rate it for me + Bewerte für mich + + + Human vs Computer + Mensch gegen Rechner + + + Computer vs Human + Rechner gegen Mensch + + + Game Mode + Spiel Modus + + + Press the button below or Key Enter if You're done. + Fertig? Benutzen Sie den Button oder die Eingabetaste. + + + Place Your secret ColorCode ... + Platzieren Sie den geheimen ColorCode ... + + + Please rate the guess. Press OK or Key Enter if You're done. + Bitte bewerten Sie meinen Vorschlag. Nutzen Sie Ok-Button oder Eingabetaste wenn fertig. + + + The impossible happened, sorry. + Das Unmögliche ist eingetreten, leider. + + + Yeah! I guessed it, man! + Ich hab's geahnt! + + + Embarrassing! I lost a game! + Peinlich! Ich hab ein Spiel verloren! + + + Nope! Thats impossible! Did you gave me false hints? + Nein! Das ist unmöglich! Haben Sie falsch bewertet? + + + Don't you like to see me winning? ;-) + Ertragen Sie es nicht, mich gewinnen zu sehen? ;-) + + + Set Hints automatically + Hinweise automatisch setzen + + + Ctrl+Shift+H + + + + Preferences + Einstellungen + + + Ctrl+P + + + + Show Indicators + Bezeichner anzeigen + + + The chosen settings do not allow pegs of the same color! + Die gewählten Einstellungen erlauben keine Steine gleicher Farbe! + + + + PrefDialog + + ... Select from predefined level settings + ... Schwierigkeitsstufe auswählen + + + Beginner (2 Colors, 2 Slots, Doubles) + Anfänger (2 Farben, 2 Slots, Doppelte) + + + Easy (4 Colors, 3 Slots, No Doubles) + Leicht (4 Farben, 3 Slots, Keine Doppelten) + + + Classic (6 Colors, 4 Slots, Doubles) + Klassisch (6 Farben, 4 Slots, Doppelte) + + + Challenging (8 Colors, 4 Slots, Doubles) + Fordernd (8 Farben, 4 Slots, Doppelte) + + + Hard (10 Colors, 5 Slots, Doubles) + Schwer (10 Farben, 5 Slots, Doppelte) + + + Slots + Felder + + + Colors + Farben + + + Human vs. Computer + Mensch gegen Rechner + + + Computer vs. Human + Rechner gegen Mensch + + + Low + Schwach + + + Medium + Mittel + + + High + Stark + + + Preferences + Einstellungen + + + Appearance + Erscheinungsbild + + + Controls + Bedienelemente + + + Show or hide the Menubar. + Menüleiste anzeigen oder ausblenden. + + + Show Menubar + Menüleiste anzeigen + + + Show or hide the Toolbar. + Werkzeugleiste anzeigen oder ausblenden. + + + Show Toolbar + Werkzeugleiste anzeigen + + + Show or hide the Statusbar. + Statusleiste anzeigen oder ausblenden. + + + Show Statusbar + Statusleiste anzeigen + + + Indicators + Bezeichner + + + If this option is checked, an indicator +inside each peg is displayed. + Wenn diese Option aktiv ist, wird ein +zusätzlicher Bezeichner für jeden Stein angezeigt. + + + Show Indicators inside pegs + Bezeichner für Steine anzeigen + + + Use unique letters as indicators. + Buchstaben als Bezeichner verwenden. + + + Letter Indicators + Buchstaben-Bezeichner + + + Use unique numbers as indicators. + Zahlen als Bezeichner verwenden. + + + Number Indicators + Zahlen-Bezeichner + + + Use the same neutral background color for each peg, +when indicators are shown. + Die gleiche, neutrale Farbe für alle Steine verwenden, +falls Bezeichner angezeigt werden. + + + Hide Colors + Farben ausblenden + + + Click here if you have changed the color order +and now you want to revert it to it's initial state. + Klicken Sie hier, falls Sie die Farben-Anordnung geändert haben, +um diese wieder in den ursprünglichen Zustand zurückzuversetzen. + + + Reset Color Order + Farbreihenfolge zurücksetzen + + + Game Settings + Spiel-Einstellungen + + + Level Presets + Schwierigkeitsstufen + + + Select from predefined combinations +of the three different level related settings, +the number of colors, the number of slots (columns) +and the possibility of pegs of the same color in one row. + Wählen Sie eine vordefinierte Kombination +der drei verschiedenen, den Schwierigkeitsgrad +beeinflussenden Einstellungen. + + + Number of Slots + Anzahl der Felder + + + Number of Colors + Anzahl der Farben + + + Number of pegs in a single row. +Higher values are harder to guess. + Die Anzahl der Steine in einer einzelnen +Reihe. Höhere Werte sind schwerer zu erraten. + + + Number of all possible colors. +Higher values are harder to guess. + Gesamtanzahl der möglichen Farben. +Höhere Werte sind schwerer zu erraten. + + + If this option is checked, the hidden combination +may contain one or more (even all would be possible) +pegs of the same color. +If checked, the combination is generally harder to guess. + Wenn diese Option aktiv ist, können Kombinationen +Steine gleicher Farbe enthalten. Solche Kombinationen +sind etwas schwerer zu erraten. + + + Allow Pegs of Same Color + Steine gleicher Farbe erlauben + + + Game Mode + Spiel Modus + + + Select from the different game modes. +In the 1. mode you have to to guess the hidden, +computer generated combination, +In the 2. mode your computer will try to guess your +own secret combination. + Wählen Sie einen Spiel-Modus aus. +Im 1. Fall müssen Sie versuchen, die verborgene, +rechnergenerierte Kombination zu erraten. +Im 2. Fall wird Ihr Rechner versuchen, eine geheime +Kombination Ihrer Wahl zu erraten. + + + If checked, a row is closed as soon as you place the last peg +and your guess is submitted immediatly. +This option only affects the Human vs. Computer game mode. + Wenn aktiv, wird eine Reihe als geschlossen betrachtet, sobald +Sie den letzten Stein platziert haben, und Ihr Vorschlag wird sofort +ausgewertet. Diese Option hat nur Auswirkungen in Mensch-gegen-Rechner-Spielen. + + + Close Rows when the last Peg is placed + Reihen nach Setzen des letzten Steins auswerten + + + If checked, the computer will determine the corresponding hints for the solver's guess. +This option affects only Computer vs. Human games. +If checked, you only have to place your secret combination. +Then the rest of the game runs automatically until the end. +But you can set a delay between the guesses. + Wenn aktiv, werden die Hinweisfelder zu den Rechner-Schätzungen automatisch ausgefüllt. +Diese Option betrifft nur Rechner-gegen-Mensch-Spiele. +Falls aktiv, müssen Sie nur Ihre geheime Kombination anordnen. Der Rest des Spiels +läuft dann automatisch bis zum Ende ab. Sie können allerdings eine Verzögerung bestimmen. + + + Set Hints automatically + Hinweise automatisch setzen + + + Adjust the delay (in ms) between two guesses. + Verzögerung (in ms) zwischen den Spielzügen. + + + Delay in ms + Verzögerung in ms + + + Solver Strength + Rechner-Stärke + + + Select from 3 different strength levels for your computer opponent. +This option only affects the Computer vs. Human game mode. +For the computer's guess in the Human vs. Computer mode +always the highest level will be used. + Wählen Sie eine der 3 verschiedenen Spielstärken für Ihren Rechner-Gegner aus. +Diese Option hat nur Einfluß auf Rechner-gegen-Mensch-Spiele. +Für die Rechner-Rat-Funktion im Mensch-gegen-Rechner-Modus wird immer die +höchste Spielstärke verwendet. + + + + RowHint + + Commit Your solution + Kombination testen + + + Click the circles to rate my guess. +Hit Ctrl+H or the corresponding toolbar button to let an impartial part of me do this for you ;-) + Klicken Sie die Kreise, um meinen Vorschlag zu bewerten. +Drücken Sie Strg+H oder die entsprechende Werkzeugleisten-Schaltfläche, um die Bewertung einem unparteiischen Teil von mir zu übertragen ;-) + + + diff --git a/plugins/ColorCode_plugin/trans_en.qm b/plugins/ColorCode_plugin/trans_en.qm new file mode 100644 index 000000000..be651eede --- /dev/null +++ b/plugins/ColorCode_plugin/trans_en.qm @@ -0,0 +1 @@ + + + +UTF-8 + + About + + &Author + + + + icon + + + + &License + + + + A needful game to train your brain ;-) + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + + + ColorCode + + + + About ColorCode + + + + <br><br>Free MasterMind clone including a built in,<br>rather intelligent solver. + + + + Version + + + + Author + + + + + ColorCode + + New Game + + + + Do you want to give in +and start a new Game? + + + + About Qt + + + + &New Game + + + + Ctrl+N + + + + &Restart Game + + + + Ctrl+R + + + + E&xit + + + + Ctrl+Q + + + + Ctrl+T + + + + Ctrl+C + + + + Ctrl+A + + + + About &Qt + + + + &Game + + + + &Settings + + + + &Help + + + + Game + + + + Message + + + + The changed settings will only apply to new games! +Do you want to give in the current and start a new Game? + + + + Place Your pegs ... + + + + Congratulation! You have won! + + + + Sorry! You lost! + + + + Ctrl+I + + + + Give In + + + + Do you really want to give in? + + + + &Throw In The Towel + + + + Ctrl+G + + + + Sure, You're too weak for me! + + + + Ctrl+Shift+R + + + + Ctrl+Shift+C + + + + Fill Row by Random + + + + Duplicate Previous Row + + + + Ctrl+D + + + + Clear Row + + + + &Row + + + + ColorCode + + + + About &ColorCode + + + + Ctrl+M + + + + Ctrl+S + + + + Show Toolbar + + + + Show Menubar + + + + Show Statusbar + + + + Allow Pegs of the Same Color + + + + Level + + + + Computer's Guess + + + + Ctrl+H + + + + Press the Hint Field or Key Enter if You're done. + + + + Disallow Pegs of the Same Color + + + + Close Rows when the last Peg is placed + + + + Ctrl+L + + + + Beginner (2 Colors, 2 Slots, Doubles) + + + + Easy (4 Colors, 3 Slots, No Doubles) + + + + Classic (6 Colors, 4 Slots, Doubles) + + + + Challenging (8 Colors, 4 Slots, Doubles) + + + + Hard (10 Colors, 5 Slots, Doubles) + + + + Level Presets + + + + Colors + + + + Pegs of Same Color + + + + Slots + + + + Yes + + + + No + + + + Reset Color Order + + + + Ctrl+Shift+L + + + + Online &Help + + + + F1 + + + + Done + + + + Ctrl+Shift+N + + + + Rate it for me + + + + Human vs Computer + + + + Computer vs Human + + + + Game Mode + + + + Press the button below or Key Enter if You're done. + + + + Place Your secret ColorCode ... + + + + Please rate the guess. Press OK or Key Enter if You're done. + + + + The impossible happened, sorry. + + + + Yeah! I guessed it, man! + + + + Embarrassing! I lost a game! + + + + Nope! Thats impossible! Did you gave me false hints? + + + + Don't you like to see me winning? ;-) + + + + Set Hints automatically + + + + Ctrl+Shift+H + + + + Preferences + + + + Ctrl+P + + + + Show Indicators + + + + The chosen settings do not allow pegs of the same color! + + + + + PrefDialog + + ... Select from predefined level settings + + + + Beginner (2 Colors, 2 Slots, Doubles) + + + + Easy (4 Colors, 3 Slots, No Doubles) + + + + Classic (6 Colors, 4 Slots, Doubles) + + + + Challenging (8 Colors, 4 Slots, Doubles) + + + + Hard (10 Colors, 5 Slots, Doubles) + + + + Slots + + + + Colors + + + + Human vs. Computer + + + + Computer vs. Human + + + + Low + + + + Medium + + + + High + + + + Preferences + + + + Appearance + + + + Controls + + + + Show or hide the Menubar. + + + + Show Menubar + + + + Show or hide the Toolbar. + + + + Show Toolbar + + + + Show or hide the Statusbar. + + + + Show Statusbar + + + + Indicators + + + + If this option is checked, an indicator +inside each peg is displayed. + + + + Show Indicators inside pegs + + + + Use unique letters as indicators. + + + + Letter Indicators + + + + Use unique numbers as indicators. + + + + Number Indicators + + + + Use the same neutral background color for each peg, +when indicators are shown. + + + + Hide Colors + + + + Click here if you have changed the color order +and now you want to revert it to it's initial state. + + + + Reset Color Order + + + + Game Settings + + + + Level Presets + + + + Select from predefined combinations +of the three different level related settings, +the number of colors, the number of slots (columns) +and the possibility of pegs of the same color in one row. + + + + Number of Slots + + + + Number of Colors + + + + Number of pegs in a single row. +Higher values are harder to guess. + + + + Number of all possible colors. +Higher values are harder to guess. + + + + If this option is checked, the hidden combination +may contain one or more (even all would be possible) +pegs of the same color. +If checked, the combination is generally harder to guess. + + + + Allow Pegs of Same Color + + + + Game Mode + + + + Select from the different game modes. +In the 1. mode you have to to guess the hidden, +computer generated combination, +In the 2. mode your computer will try to guess your +own secret combination. + + + + If checked, a row is closed as soon as you place the last peg +and your guess is submitted immediatly. +This option only affects the Human vs. Computer game mode. + + + + Close Rows when the last Peg is placed + + + + If checked, the computer will determine the corresponding hints for the solver's guess. +This option affects only Computer vs. Human games. +If checked, you only have to place your secret combination. +Then the rest of the game runs automatically until the end. +But you can set a delay between the guesses. + + + + Set Hints automatically + + + + Adjust the delay (in ms) between two guesses. + + + + Delay in ms + + + + Solver Strength + + + + Select from 3 different strength levels for your computer opponent. +This option only affects the Computer vs. Human game mode. +For the computer's guess in the Human vs. Computer mode +always the highest level will be used. + + + + + RowHint + + Commit Your solution + + + + Click the circles to rate my guess. +Hit Ctrl+H or the corresponding toolbar button to let an impartial part of me do this for you ;-) + + + + diff --git a/plugins/ColorCode_plugin/trans_fr.qm b/plugins/ColorCode_plugin/trans_fr.qm new file mode 100644 index 000000000..b812fcb4a Binary files /dev/null and b/plugins/ColorCode_plugin/trans_fr.qm differ diff --git a/plugins/ColorCode_plugin/trans_fr.ts b/plugins/ColorCode_plugin/trans_fr.ts new file mode 100644 index 000000000..298998d3e --- /dev/null +++ b/plugins/ColorCode_plugin/trans_fr.ts @@ -0,0 +1,660 @@ + + + +UTF-8 + + About + + &Author + &Auteur + + + icon + icône + + + &License + &Licence + + + A needful game to train your brain ;-) + Un programme incontournable pour entraîner votre cerveau ;-) + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier selon les termes de la GNU General Public License (licence générale publique du projet GNU), telle qu'elle est publiée par la Free Software Foundation (Fondation pour le Logiciel Libre), soit sous sa version 2, soit (selon votre choix) sous n'importe quelle version ultérieure. + + + ColorCode + ColorCode + + + About ColorCode + À propos de ColorCode + + + <br><br>Free MasterMind clone including a built in,<br>rather intelligent solver. + <br><br>Clone du logiciel MasterMind incluant un solveur plutôt malin. + + + Version + Version + + + Author + Auteur + + + + ColorCode + + New Game + Nouvelle partie + + + Do you want to give in +and start a new Game? + Voulez-vous abandonner +et démarrer une nouvelle partie ? + + + About Qt + À propos de Qt + + + &New Game + &Nouvelle partie + + + Ctrl+N + + + + &Restart Game + &Redémarrer la partie + + + Ctrl+R + Ctrl+R + + + E&xit + &Quitter + + + Ctrl+Q + + + + Ctrl+T + + + + Ctrl+C + + + + Ctrl+A + + + + About &Qt + À propos de &Qt + + + &Game + &Partie + + + &Settings + &Préférences + + + &Help + &Aide + + + Game + Partie + + + Message + + + + The changed settings will only apply to new games! +Do you want to give in the current and start a new Game? + Les préférences modifiées ne s'appliqueront qu'aux nouvelles parties ! +Voulez-vous abandonner la partie et en démarrer une nouvelle ? + + + Place Your pegs ... + Placez vos fiches... + + + Congratulation! You have won! + Congratulations ! Vous gagnâtes ! + + + Sorry! You lost! + Désolé ! Vous perdîtes ! + + + Ctrl+I + + + + Give In + Abandonner + + + Do you really want to give in? + Voulez-vous réellement abandonner ? + + + &Throw In The Towel + &Donner sa langue au chat + + + Ctrl+G + + + + Sure, You're too weak for me! + Vous êtes trop faible pour moi ; c'est sûr ! + + + Ctrl+Shift+R + + + + Ctrl+Shift+C + + + + Fill Row by Random + Garnir la rangée au hasard + + + Duplicate Previous Row + Dupliquer la rangée précédente + + + Ctrl+D + + + + Clear Row + Effacer la rangée + + + &Row + &Rangée + + + ColorCode + + + + About &ColorCode + À propos de &ColorCode + + + Ctrl+M + + + + Ctrl+S + + + + Show Toolbar + Afficher la barre d'outils + + + Show Menubar + Afficher la barre de menu + + + Show Statusbar + Afficher la barre d'état + + + Allow Pegs of the Same Color + Autoriser plusieurs fiches de même couleur + + + Level + Niveau + + + Computer's Guess + Essai de l'ordinateur + + + Ctrl+H + + + + Press the Hint Field or Key Enter if You're done. + Cliquer sur le champ des fiches d'indices ou pressez <Entrée> quand vous êtes prêt. + + + Disallow Pegs of the Same Color + Interdire plusieurs fiches de même couleur + + + Close Rows when the last Peg is placed + Finaliser la rangée quand la dernière fiche est placée + + + Ctrl+L + + + + Beginner (2 Colors, 2 Slots, Doubles) + Débutant (2 couleurs, 2 trous, doubles) + + + Easy (4 Colors, 3 Slots, No Doubles) + Facile (4 couleurs, 3 trous, pas de doubles) + + + Classic (6 Colors, 4 Slots, Doubles) + Classique (6 couleurs, 4 trous, doubles) + + + Challenging (8 Colors, 4 Slots, Doubles) + Évolué (8 couleurs, 4 trous, doubles) + + + Hard (10 Colors, 5 Slots, Doubles) + Difficile (10 couleurs, 5 trous, doubles) + + + Level Presets + Niveaux + + + Colors + Couleurs + + + Pegs of Same Color + Fiches de même couleurs autorisées + + + Slots + Trous + + + Yes + Oui + + + No + Non + + + Reset Color Order + Réinitialiser l'ordre des couleurs + + + Ctrl+Shift+L + + + + Online &Help + &Aide en ligne + + + F1 + + + + Done + Fait + + + Ctrl+Shift+N + + + + Rate it for me + Évaluer pour moi + + + Human vs Computer + Humain contre Ordinateur + + + Computer vs Human + Ordinateur contre Humain + + + Game Mode + Mode de jeu + + + Press the button below or Key Enter if You're done. + Cliquer le bouton ci-dessous ou presser <Entrée> quand vous êtes prêt. + + + Place Your secret ColorCode ... + Placez votre code couleur secret... + + + Please rate the guess. Press OK or Key Enter if You're done. + Veuillez évaluer l'essai. Cliquer OK ou presser <Entrée> quand vous êtes prêt. + + + The impossible happened, sorry. + L'impossible advint, désolé. + + + Yeah! I guessed it, man! + Youpi! Je l'ai deviné ! + + + Embarrassing! I lost a game! + Embarassant ! J'ai perdu la partie ! + + + Nope! Thats impossible! Did you gave me false hints? + Nenni ! Ceci est impossible ! M'avez-vous donné de faux indices ? + + + Don't you like to see me winning? ;-) + Aimez-vous me voir gagner ? ;-) + + + Set Hints automatically + Afficher les indices automatiquement + + + Ctrl+Shift+H + + + + Preferences + Préférences + + + Ctrl+P + + + + Show Indicators + Montrer les indicateurs sur les fiches + + + The chosen settings do not allow pegs of the same color! + Les préférences choisies ne permettent pas plusieurs fiches de même couleur ! + + + + PrefDialog + + ... Select from predefined level settings + ... Sélectionner à partir des préférences de niveau + + + Beginner (2 Colors, 2 Slots, Doubles) + Débutant (2 couleurs, 2 trous, doubles) + + + Easy (4 Colors, 3 Slots, No Doubles) + Facile (4 couleurs, 3 trous, pas de doubles) + + + Classic (6 Colors, 4 Slots, Doubles) + Classique (6 couleurs, 4 trous, doubles) + + + Challenging (8 Colors, 4 Slots, Doubles) + Évolué (8 couleurs, 4 trous, doubles) + + + Hard (10 Colors, 5 Slots, Doubles) + Difficile (10 couleurs, 5 trous, doubles) + + + Slots + Trous + + + Colors + Couleurs + + + Human vs. Computer + Humain contre Ordinateur + + + Computer vs. Human + Ordinateur contre Humain + + + Low + Bas + + + Medium + Moyen + + + High + Élevé + + + Preferences + Préférences + + + Appearance + Apparence + + + Controls + Contrôles + + + Show or hide the Menubar. + Afficher ou cacher la barre de menu. + + + Show Menubar + Afficher la barre de menu + + + Show or hide the Toolbar. + Afficher ou cacher la barre d'outils. + + + Show Toolbar + Afficher la barre d'outils + + + Show or hide the Statusbar. + Afficher ou cacher la barre d'état. + + + Show Statusbar + Afficher la barre d'état + + + Indicators + Indicateurs de fiche + + + If this option is checked, an indicator +inside each peg is displayed. + Si cette option est cochée, un indicateur +est affiché à l'intérieur de chaque fiche. + + + Show Indicators inside pegs + Montrer les indicateurs sur les fiches + + + Use unique letters as indicators. + Utiliser des lettres uniques comme indicateurs. + + + Letter Indicators + Lettres indicateur + + + Use unique numbers as indicators. + Utiliser des chiffres uniques comme indicateurs. + + + Number Indicators + Chiffres indicateur + + + Use the same neutral background color for each peg, +when indicators are shown. + Utiliser la même couleur de fond neutre pour chaque fiche, +quand les indicateurs sont affichés. + + + Hide Colors + Cacher les couleurs + + + Click here if you have changed the color order +and now you want to revert it to it's initial state. + Cliquer ici si vous avez changé l'ordre des couleurs +et que vous voulez revenir à son état initial. + + + Reset Color Order + Réinitialiser l'ordre des couleurs + + + Game Settings + Préférences de jeu + + + Level Presets + Niveaux prédéfinis + + + Select from predefined combinations +of the three different level related settings, +the number of colors, the number of slots (columns) +and the possibility of pegs of the same color in one row. + Sélectionner un niveau à partir de +niveaux prédéfinis. + + + Number of Slots + Nombre de trous + + + Number of Colors + Nombre de couleurs + + + Number of pegs in a single row. +Higher values are harder to guess. + Nombre de fiches sur une rangée. +Plus le nombre est élevé, plus la combinaison +est difficile à deviner. + + + Number of all possible colors. +Higher values are harder to guess. + Nombre de couleurs autorisées. +Plus le nombre est élevé, plus la combinaison +est difficile à deviner. + + + If this option is checked, the hidden combination +may contain one or more (even all would be possible) +pegs of the same color. +If checked, the combination is generally harder to guess. + Si cette option est cochée, la combinaison cachée +peut contenir une ou plusieurs (ou toutes) fiches +de même couleur. Dans ce cas, la combinaison est +généralement plus difficile à deviner. + + + Allow Pegs of Same Color + Autoriser plusieurs fiches de même couleur + + + Game Mode + Mode de jeu + + + Select from the different game modes. +In the 1. mode you have to to guess the hidden, +computer generated combination, +In the 2. mode your computer will try to guess your +own secret combination. + Sélectionner un mode de jeu parmi deux +modes prédéfinis. + + + If checked, a row is closed as soon as you place the last peg +and your guess is submitted immediatly. +This option only affects the Human vs. Computer game mode. + Si cette opions est cochée, votre essai est immédiatement +évalué dès que la dernière fiche est placée dans son trou. + + + Close Rows when the last Peg is placed + Finaliser la rangée quand la dernière fiche est placée + + + If checked, the computer will determine the corresponding hints for the solver's guess. +This option affects only Computer vs. Human games. +If checked, you only have to place your secret combination. +Then the rest of the game runs automatically until the end. +But you can set a delay between the guesses. + Si cette option est cochée, l'ordinateur déterminera les indices pour l'essai. +Cette option affecte uniquement les jeus Ordinateur contre Humain. +Ensuite, le restant du jeu se déroule automatiquement jusques à la fin. +Mais vous pouvez régler un délai entre les essais. + + + Set Hints automatically + Afficher les indices automatiquement + + + Adjust the delay (in ms) between two guesses. + Régler le délai (en millisecondes) entre deux essais. + + + Delay in ms + Délai en millisecondes + + + Solver Strength + Force du solveur + + + Select from 3 different strength levels for your computer opponent. +This option only affects the Computer vs. Human game mode. +For the computer's guess in the Human vs. Computer mode +always the highest level will be used. + Sélectionner la force de votre adversaire parmi trois niveaux prédéfinis. + + + + RowHint + + Commit Your solution + Envoyer votre solution + + + Click the circles to rate my guess. +Hit Ctrl+H or the corresponding toolbar button to let an impartial part of me do this for you ;-) + Cliquer les cercles pour évaluer mon essai. +Pressez Ctrl+H ou le bouton de barre d'outils pour que je le fasse à votre place +de la manière la plus impartiales possible ;-) + + + diff --git a/plugins/ColorCode_plugin/trans_hu.qm b/plugins/ColorCode_plugin/trans_hu.qm new file mode 100644 index 000000000..44f5691c3 Binary files /dev/null and b/plugins/ColorCode_plugin/trans_hu.qm differ diff --git a/plugins/ColorCode_plugin/trans_hu.ts b/plugins/ColorCode_plugin/trans_hu.ts new file mode 100644 index 000000000..3a181abbe --- /dev/null +++ b/plugins/ColorCode_plugin/trans_hu.ts @@ -0,0 +1,666 @@ + + + +UTF-8 + + About + + ColorCode + ColorCode + + + A needful game to train your brain ;-) + Az agytekervények megmozgatására szolgáló játék ;-) + + + <br><br>Free MasterMind clone including a built in,<br>rather intelligent solver. + <br><br>Egy ingyenes MasterMind klón,<br> kiegészítve egy meglehetősen intelligens megoldóval. + + + Version + Verzió + + + Author + Szerző + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Ez a program egy szabad szoftver, amit továbbadhatsz és/vagy módosíthatsz a GNU General Public Licensz alapján, amit a Free Software Foundation adott ki; a 2. Licensz verzió szerint, vagy bármely későbbi (tetszés szerint) verzió alapján. + + + About ColorCode + Névjegy: ColorCode + + + &Author + &Szerző + + + icon + ikon + + + &License + &Licensz + + + + ColorCode + + ColorCode + ColorCode + + + Done + Befejez + + + &New Game + &Új játék + + + Ctrl+N + Ctrl+N + + + &Restart Game + &Játék újrakezdése + + + Ctrl+Shift+N + Ctrl+Shift+N + + + &Throw In The Towel + Játék &feladása + + + Ctrl+G + Ctrl+G + + + E&xit + &Kilép + + + Ctrl+Q + Ctrl+Q + + + Show Toolbar + Eszköztár mutatása + + + Ctrl+T + Ctrl+T + + + Show Menubar + Menüsor mutatása + + + Ctrl+M + Ctrl+M + + + Show Statusbar + Állapotsor mutatása + + + Ctrl+S + Ctrl+S + + + Reset Color Order + Szín sorrend nullázása + + + Ctrl+Shift+R + Ctrl+Shift+R + + + Show Indicators + Jelzők használata + + + Ctrl+Shift+L + Ctrl+Shift+L + + + Allow Pegs of the Same Color + Azonos színű ékek engedélyezése + + + Ctrl+Shift+C + Ctrl+Shift+C + + + Disallow Pegs of the Same Color + Azonos színű ékek tiltása + + + Close Rows when the last Peg is placed + Sor zárolása az utolsó ék behelyezése után + + + Ctrl+L + Ctrl+L + + + Set Hints automatically + Automatikus útmutatások + + + Ctrl+Shift+H + Ctrl+Shift+H + + + Online &Help + Online &segítség + + + F1 + F1 + + + About &ColorCode + Névejgy: &ColorCode + + + Ctrl+A + Ctrl+A + + + About &Qt + Névjegy: &Qt + + + Ctrl+I + Ctrl+I + + + Fill Row by Random + Sorok kitöltése véletlenszerűen + + + Ctrl+R + Ctrl+R + + + Duplicate Previous Row + Előző sor duplázása + + + Ctrl+D + Ctrl+D + + + Clear Row + Sor törlése + + + Ctrl+C + Ctrl+C + + + Beginner (2 Colors, 2 Slots, Doubles) + Kezdő (2 szín, 2 lyuk, duplázás) + + + Easy (4 Colors, 3 Slots, No Doubles) + Könnyű (4 szín, 3 lyuk, nincs duplázás) + + + Classic (6 Colors, 4 Slots, Doubles) + Klasszikus (6 szín, 4 lyuk, duplázás) + + + Challenging (8 Colors, 4 Slots, Doubles) + Kihívás (8 szín, 4 lyuk, duplázás) + + + Hard (10 Colors, 5 Slots, Doubles) + Nehéz (10 szín, 5 lyuk, duplázás) + + + Computer's Guess + Gép tippje + + + Ctrl+H + Ctrl+H + + + Rate it for me + Értékeld nekem + + + Human vs Computer + Ember kontra számítógép + + + Computer vs Human + Számítógép kontra ember + + + Preferences + Beállítások + + + Ctrl+P + Ctrl+P + + + &Game + &Játék + + + &Row + &Sor + + + &Settings + &Beállítások + + + Game Mode + Játék mód + + + Level Presets + Nehézség beállítása + + + &Help + &Segítség + + + Game + Játék + + + Colors + Színek + + + Slots + Lyukak + + + Level + Nehézség + + + Message + Üzenet + + + The changed settings will only apply to new games! +Do you want to give in the current and start a new Game? + A megváltozott beállítások csak az új játékra lesznek érvényesek! +Feladod a jelenlegi játékot, és indítasz egy újat? + + + New Game + Új játék + + + Do you want to give in +and start a new Game? + Feladod, és kezdesz egy újat? + + + Give In + Felad + + + Do you really want to give in? + Tényleg feladod? + + + About Qt + Névjegy: Qt + + + Press the Hint Field or Key Enter if You're done. + Nyomd meg az útmutatás mezőt, vagy üsd le az entert ha kész vagy. + + + Place Your pegs ... + Helyezd el az ékeket... + + + Press the button below or Key Enter if You're done. + Nyomd meg a fenti gombot, vagy üsd le az entert ha végeztél. + + + The chosen settings do not allow pegs of the same color! + A megadott beállítások nem engedélyezik az azonos színeket! + + + Place Your secret ColorCode ... + Helyezd el a titkos színkombinációt... + + + Yes + Igen + + + No + Nem + + + Pegs of Same Color + Azonos színű ékek + + + Please rate the guess. Press OK or Key Enter if You're done. + Értékeld a tippet. Kattints az OK-ra, vagy üss entert ha kész vagy. + + + Congratulation! You have won! + Gratulálok! Nyertél! + + + Sorry! You lost! + Sajnálom! Vesztettél! + + + Sure, You're too weak for me! + Biztos, Túl kevés vagy hozzám! + + + The impossible happened, sorry. + A lehetetlen megtörtént, bocsi. + + + Yeah! I guessed it, man! + Fain! Kitalátam öcsém! + + + Embarrassing! I lost a game! + Lenyűgöző! Elvesztettem a játékot! + + + Don't you like to see me winning? ;-) + Nem akarsz győzni látni engem? ;-) + + + Nope! Thats impossible! Did you gave me false hints? + Neee! Ez hihetetlen! Hamis útmutatást adtál nekem? + + + + PrefDialog + + ... Select from predefined level settings + ... Válassz az előre meghatározott szint beállítások közül + + + Beginner (2 Colors, 2 Slots, Doubles) + Kezdő (2szín, 2 lyuk, duplázás) + + + Easy (4 Colors, 3 Slots, No Doubles) + Könnyű (4 szín, 3 lyuk, nincs duplázás) + + + Classic (6 Colors, 4 Slots, Doubles) + Klasszikus (6 szín, 4 lyuk, duplázás) + + + Challenging (8 Colors, 4 Slots, Doubles) + Kihívás (8 szín, 4 lyuk, duplázás) + + + Hard (10 Colors, 5 Slots, Doubles) + Nehéz (10 szín, 5 lyuk, duplázás) + + + Slots + Lyukak + + + Colors + Színek + + + Human vs. Computer + Ember kontra számítógép + + + Computer vs. Human + Számítógép kontra ember + + + Low + Könnyű + + + Medium + Közepes + + + High + Nehéz + + + Preferences + Beállítások + + + Appearance + Megjelenés + + + Controls + Gombok + + + Show or hide the Menubar. + Menüsor mutatása vagy elrejtése. + + + Show Menubar + Meüsor mutatása + + + Show or hide the Toolbar. + Eszköztár mutatása vagy elrejtése. + + + Show Toolbar + Eszköztár mutatása + + + Show or hide the Statusbar. + Állapotsor mutatása vagy elrejtése. + + + Show Statusbar + Állapotsor mutatása + + + Indicators + Jelzők + + + If this option is checked, an indicator +inside each peg is displayed. + Ha ez az opció be van jelölve, +akkor minden ékben megjelenik egy jelző. + + + Show Indicators inside pegs + Jelzők mutatása az ékeken belül + + + Use unique letters as indicators. + Egyedi betűk használata jelzőként. + + + Letter Indicators + Betű jelzők + + + Use unique numbers as indicators. + Egydi számok használata jelzőként. + + + Number Indicators + Szám jelzők + + + Use the same neutral background color for each peg, +when indicators are shown. + Egyforma sima háttér használata az ékeknél, +amikor a jelzők látszanak. + + + Hide Colors + Színek elrejtése + + + Click here if you have changed the color order +and now you want to revert it to it's initial state. + Kattints ide ha megváltoztattad a szín sorrendet, +és visszakarod állatani az eredetire. + + + Reset Color Order + Szín sorrend nullázása + + + Game Settings + Játék beállítások + + + Level Presets + Nehézségi beállítások + + + Select from predefined combinations +of the three different level related settings, +the number of colors, the number of slots (columns) +and the possibility of pegs of the same color in one row. + Válassz az előre meghatározott nehézségi szint +3 különböző lehetősége közül, +színek száma, lyukak (oszlop) száma, +és az egy sorban lehetséges azonos színek száma. + + + Number of Slots + Lyukak száma + + + Number of Colors + Színek száma + + + Number of pegs in a single row. +Higher values are harder to guess. + Ékek száma egy sorban. +A nyagyobb értéket nehezebb eltalálni. + + + Number of all possible colors. +Higher values are harder to guess. + A lehetséges színek száma. +A nagyobb értéket nehezebb eltalálni. + + + If this option is checked, the hidden combination +may contain one or more (even all would be possible) +pegs of the same color. +If checked, the combination is generally harder to guess. + Amennyiben ez a lehetőség be van kapcsolva, +akkor a rejtett kombináció tartalmazhat egy vagy több +(akár az összes) azonos színű éket. +Ha be van kapcsolva, nehezebb megfejteni a kombinációt. + + + Allow Pegs of Same Color + Azonons színű ékek engedélyezése + + + Game Mode + Játék mód + + + Select from the different game modes. +In the 1. mode you have to to guess the hidden, +computer generated combination, +In the 2. mode your computer will try to guess your +own secret combination. + Válassz a különböző játék módok közül. +Az 1. módban neked kell kitalálnod a titkos kombinációt, +amit a gép kigondolt. +A 2. módban a gépnek kell kitalálnia +az általad megadott kombinációt. + + + If checked, a row is closed as soon as you place the last peg +and your guess is submitted immediatly. +This option only affects the Human vs. Computer game mode. + Ha ez be van kapcsolva, akkor a sor zárolásra kerül, amint beraktad az utolsó éket, +és a tipped azonnal ki lesz értékelve. +Ez az opció csak az Ember kontra számítógép módban működik. + + + Close Rows when the last Peg is placed + Sor zárolása, amint az utolsó ék is a helyére került + + + If checked, the computer will determine the corresponding hints for the solver's guess. +This option affects only Computer vs. Human games. +If checked, you only have to place your secret combination. +Then the rest of the game runs automatically until the end. +But you can set a delay between the guesses. + Ha ezt bekapcsolod, akkor a gép automatikusan kiértékeli a tippet a jelzők segítségével. +Ez a lehetőség csak a Számítógép kontra ember módnál működik. +Bekapcsolt állapotban, csak titkos kombinációt kell megadnod, +majd a játék hátralevő részét a gép automatikusan lejátsza. +De meg tudsz adni késleltetést a tippek közé. + + + Set Hints automatically + Jelzők automatikus használata + + + Adjust the delay (in ms) between two guesses. + Tippek közti késleltetés megadása. + + + Delay in ms + Késleltelés ms-ban + + + Solver Strength + Megoldási nehézség + + + Select from 3 different strength levels for your computer opponent. +This option only affects the Computer vs. Human game mode. +For the computer's guess in the Human vs. Computer mode +always the highest level will be used. + Válassz a 3 különböző nehézség közül a gépi ellenfél számára. +Ez az opció csak a Számítógép kontra ember módot befolyásolja. +A gép tippjeinél az Ember kontra számítógép módban +a legnehezebb nehézségi szint lesz használva. + + + + RowHint + + Commit Your solution + Kövesd a megoldásodat + + + Click the circles to rate my guess. +Hit Ctrl+H or the corresponding toolbar button to let an impartial part of me do this for you ;-) + Kattints a körökbe, hogy kiértékeld a tippemet. +Vagy nyomd le a Ctrl+H billentyűkombinációt, vagy használd az eszköztár adott gombját, hogy megtegyem ezt helyetted;-) + + + diff --git a/plugins/Common/retroshare_plugin.pri b/plugins/Common/retroshare_plugin.pri new file mode 100644 index 000000000..41f539190 --- /dev/null +++ b/plugins/Common/retroshare_plugin.pri @@ -0,0 +1,11 @@ +TEMPLATE = lib + +INCLUDEPATH += ../../libretroshare/src/ ../../retroshare-gui/src/ + +linux-g++ { + LIBS *= -ldl +} +linux-g++-64 { + LIBS *= -ldl +} + diff --git a/plugins/LinksCloud/AddLinksDialog.cpp b/plugins/LinksCloud/AddLinksDialog.cpp new file mode 100644 index 000000000..0edee0f01 --- /dev/null +++ b/plugins/LinksCloud/AddLinksDialog.cpp @@ -0,0 +1,124 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "AddLinksDialog.h" +#include +#include "rsrank.h" + +/* Images for context menu icons */ +#define IMAGE_EXPORTFRIEND ":/images/exportpeers_16x16.png" +#define IMAGE_GREAT ":/images/filerating5.png" +#define IMAGE_GOOD ":/images/filerating4.png" +#define IMAGE_OK ":/images/filerating3.png" +#define IMAGE_SUX ":/images/filerating2.png" +#define IMAGE_BADLINK ":/images/filerating1.png" + +/** Constructor */ +AddLinksDialog::AddLinksDialog(QString url, QWidget *parent) +: QDialog(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + /* add button */ + connect(ui.addLinkButton, SIGNAL(clicked()), this, SLOT(addLinkComment())); + connect(ui.closepushButton, SIGNAL(clicked()), this, SLOT(close())); + + connect( ui.anonBox, SIGNAL( stateChanged ( int ) ), this, SLOT( load ( void ) ) ); + + ui.linkLineEdit->setText(url); + + RetroShareLink link(url); + + if(link.valid() && link.type() == RetroShareLink::TYPE_FILE) + ui.titleLineEdit->setText(link.name()); + else + ui.titleLineEdit->setText("New File"); + + load(); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +int AddLinksDialog::IndexToScore(int index) +{ + if ((index == -1) || (index > 4)) + return 0; + int score = 2 - index; + return score; +} + +void AddLinksDialog::addLinkComment() +{ + /* get the title / link / comment */ + QString title = ui.titleLineEdit->text(); + QString link = ui.linkLineEdit->text(); + QString comment = ui.linkTextEdit->toPlainText(); + int32_t score = AddLinksDialog::IndexToScore(ui.scoreBox->currentIndex()); + + if ((link == "") || (title == "")) + { + QMessageBox::warning(NULL, tr("Add Link Failure"), tr("Missing Link and/or Title"), QMessageBox::Ok); + /* can't do anything */ + return; + } + + /* add it either way */ + if (ui.anonBox->isChecked()) + { + rsRanks->anonRankMsg("", link.toStdWString(), title.toStdWString()); + } + else + { + rsRanks->newRankMsg(link.toStdWString(), + title.toStdWString(), + comment.toStdWString(), score); + } + + close(); +} + +void AddLinksDialog::load() +{ + if (ui.anonBox->isChecked()) + { + + /* disable comment + score */ + ui.scoreBox->setEnabled(false); + ui.linkTextEdit->setEnabled(false); + + /* done! */ + return; + } + else + { + /* enable comment + score */ + ui.scoreBox->setEnabled(true); + ui.linkTextEdit->setEnabled(true); + } +} diff --git a/plugins/LinksCloud/AddLinksDialog.h b/plugins/LinksCloud/AddLinksDialog.h new file mode 100644 index 000000000..9e4451117 --- /dev/null +++ b/plugins/LinksCloud/AddLinksDialog.h @@ -0,0 +1,48 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _ADDLINKS_DIALOG_H +#define _ADDLINKS_DIALOG_H + +#include "ui_AddLinksDialog.h" + +class AddLinksDialog : public QDialog +{ + Q_OBJECT + +public: + /** Default Constructor */ + AddLinksDialog(QString url, QWidget *parent = 0); + /** Default Destructor */ + + static int IndexToScore(int index); + +public slots: + void addLinkComment(); + + void load(); + +private: + /** Qt Designer generated object */ + Ui::AddLinksDialog ui; +}; + +#endif diff --git a/plugins/LinksCloud/AddLinksDialog.ui b/plugins/LinksCloud/AddLinksDialog.ui new file mode 100644 index 000000000..04b9363a4 --- /dev/null +++ b/plugins/LinksCloud/AddLinksDialog.ui @@ -0,0 +1,288 @@ + + + AddLinksDialog + + + + 0 + 0 + 614 + 415 + + + + Add Link + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + 0 + + + + + + 16777215 + 52 + + + + QFrame#frame{background-image: url(:/images/connect/connectFriendBanner.png);} + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + 32 + 32 + + + + + + + :/images/irkick.png + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Cancel + + + + + + + Add Link + + + false + + + true + + + + + + + Qt::Horizontal + + + + 375 + 20 + + + + + + + + Add a new Link + + + + 1 + + + + + + + + + Title: + + + + + + + Url: + + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + 16777215 + 40 + + + + QFrame#frame_3{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Add Anonymous Link + + + + + + + + +2 Great! + + + + :/images/filerating5.png:/images/filerating5.png + + + + + +1 Good + + + + :/images/filerating4.png:/images/filerating4.png + + + + + 0 Okay + + + + :/images/filerating3.png:/images/filerating3.png + + + + + -1 Sux + + + + :/images/filerating2.png:/images/filerating2.png + + + + + -2 Bad Link + + + + :/images/filerating1.png:/images/filerating1.png + + + + + + + + Qt::Horizontal + + + + 299 + 20 + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + + + + + + + + + diff --git a/plugins/LinksCloud/LinksCloud.pro b/plugins/LinksCloud/LinksCloud.pro new file mode 100644 index 000000000..fdc4f3032 --- /dev/null +++ b/plugins/LinksCloud/LinksCloud.pro @@ -0,0 +1,11 @@ +!include("../Common/retroshare_plugin.pri"): error("Could not include file ../Common/retroshare_plugin.pri") + +CONFIG *= qt uic debug resources + +SOURCES = p3ranking.cc LinksDialog.cpp rsrankitems.cc AddLinksDialog.cpp LinksCloudPlugin.cpp +HEADERS = rsrank.h p3ranking.h LinksDialog.h rsrankitems.h AddLinksDialog.h LinksCloudPlugin.h +FORMS = LinksDialog.ui AddLinksDialog.ui + +TARGET = LinksCloud + +RESOURCES = images.qrc diff --git a/plugins/LinksCloud/LinksCloudPlugin.cpp b/plugins/LinksCloud/LinksCloudPlugin.cpp new file mode 100644 index 000000000..d1787ae4a --- /dev/null +++ b/plugins/LinksCloud/LinksCloudPlugin.cpp @@ -0,0 +1,58 @@ +#include + +#include "LinksCloudPlugin.h" +#include "LinksDialog.h" + +static void *inited = new LinksCloudPlugin() ; + +extern "C" { + void *RETROSHARE_PLUGIN_provide() + { + static LinksCloudPlugin *p = new LinksCloudPlugin() ; + + return (void*)p ; + } +} + +#define IMAGE_LINKS ":/images/irkick.png" + +LinksCloudPlugin::LinksCloudPlugin() +{ + mRanking = NULL ; + mainpage = NULL ; + mIcon = NULL ; +} + +MainPage *LinksCloudPlugin::qt_page() const +{ + if(mainpage == NULL) + mainpage = new LinksDialog ; + + return mainpage ; +} + +RsCacheService *LinksCloudPlugin::rs_cache_service() const +{ + if(mRanking == NULL) + { + mRanking = new p3Ranking ; // , 3600 * 24 * 30 * 6); // 6 Months + rsRanks = mRanking ; + } + + return mRanking ; +} + +QIcon *LinksCloudPlugin::qt_icon() const +{ + if(mIcon == NULL) + mIcon = new QIcon(IMAGE_LINKS) ; + + return mIcon ; +} + +std::string LinksCloudPlugin::getShortPluginDescription() const +{ + return "This plugin provides a set of cached links, and a voting system to promote them." ; +} + + diff --git a/plugins/LinksCloud/LinksCloudPlugin.h b/plugins/LinksCloud/LinksCloudPlugin.h new file mode 100644 index 000000000..35af536cb --- /dev/null +++ b/plugins/LinksCloud/LinksCloudPlugin.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include "p3ranking.h" + +class LinksCloudPlugin: public RsPlugin +{ + public: + LinksCloudPlugin() ; + virtual ~LinksCloudPlugin() {} + + virtual RsCacheService *rs_cache_service() const ; + virtual MainPage *qt_page() const ; + virtual QIcon *qt_icon() const ; + virtual uint16_t rs_service_id() const { return RS_SERVICE_TYPE_RANK ; } + + virtual std::string configurationFileName() const { return std::string() ; } + + virtual std::string getShortPluginDescription() const ; + virtual std::string getPluginName() const { return "LinksCloud" ; } + private: + mutable p3Ranking *mRanking ; + mutable MainPage *mainpage ; + mutable QIcon *mIcon ; +}; + diff --git a/plugins/LinksCloud/LinksDialog.cpp b/plugins/LinksCloud/LinksDialog.cpp new file mode 100644 index 000000000..917b97ed8 --- /dev/null +++ b/plugins/LinksCloud/LinksDialog.cpp @@ -0,0 +1,1060 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include + +#include "LinksDialog.h" +#include +#include "AddLinksDialog.h" +#include +#include +#include "rsrank.h" + +#include + + +/* Images for context menu icons */ +#define IMAGE_EXPORTFRIEND ":/images/exportpeers_16x16.png" +#define IMAGE_GREAT ":/images/filerating5.png" +#define IMAGE_GOOD ":/images/filerating4.png" +#define IMAGE_OK ":/images/filerating3.png" +#define IMAGE_SUX ":/images/filerating2.png" +#define IMAGE_BADLINK ":/images/filerating1.png" +#define IMAGE_NOCOMMENTRATING ":/images/filerating0.png" +#define IMAGE_DOWNLOAD ":/images/download16.png" + +/****** + * #define LINKS_DEBUG 1 + *****/ + +/** Constructor */ +LinksDialog::LinksDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.linkTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( linkTreeWidgetCostumPopupMenu( QPoint ) ) ); + + + /* link combos */ + connect( ui.rankComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( changedSortRank( int ) ) ); + connect( ui.periodComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( changedSortPeriod( int ) ) ); + connect( ui.fromComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( changedSortFrom( int ) ) ); + connect( ui.topComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( changedSortTop( int ) ) ); + + /* add button */ + connect( ui.addButton, SIGNAL( clicked( void ) ), this, SLOT( addLinkComment( void ) ) ); + connect( ui.expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggleWindows( void ) ) ); + + connect( ui.pushButton, SIGNAL( clicked( ) ), this, SLOT( addNewLink( ) ) ); + + connect( ui.linkTreeWidget, SIGNAL( currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem * ) ), + this, SLOT( changedItem ( QTreeWidgetItem *, QTreeWidgetItem * ) ) ); + + connect( ui.linkTreeWidget, SIGNAL( itemDoubleClicked ( QTreeWidgetItem *, int ) ), + this, SLOT( openLink ( QTreeWidgetItem *, int ) ) ); + + connect( ui.anonBox, SIGNAL( stateChanged ( int ) ), this, SLOT( checkAnon ( void ) ) ); + + connect( ui.linklabel, SIGNAL(anchorClicked(const QUrl &)), SLOT(anchorClicked(const QUrl &))); + + + mStart = 0; + + + /* Set header resize modes and initial section sizes */ + QHeaderView * _header = ui.linkTreeWidget->header () ; + _header->setResizeMode (0, QHeaderView::Interactive); + _header->setResizeMode (1, QHeaderView::Interactive); + _header->setResizeMode (2, QHeaderView::Interactive); + + _header->resizeSection ( 0, 400 ); + _header->resizeSection ( 1, 60 ); + _header->resizeSection ( 2, 150 ); + + ui.linkTreeWidget->setSortingEnabled(true); + + ui.linklabel->setMinimumWidth(20); + + + /* Set a GUI update timer - much cleaner than + * doing everything through the notify agent + */ + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + timer->start(1000); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif + +} + +void LinksDialog::checkUpdate() +{ + std::cerr << "In linksDialog::checkUpdate()" << std::endl; + /* update */ + if (!rsRanks) + { + std::cerr << " rsRanks = 0 !!!!" << std::endl; + return; + } + + if (rsRanks->updated()) + { + std::cerr << " rsRanks was updated -> redraw()" << std::endl; + updateLinks(); + } + + return; +} + +void LinksDialog::linkTreeWidgetCostumPopupMenu( QPoint point ) +{ + + QMenu contextMnu( this ); + + QAction *voteupAct = new QAction(QIcon(IMAGE_EXPORTFRIEND), tr( "Share Link Anonymously" ), &contextMnu ); + connect( voteupAct , SIGNAL( triggered() ), this, SLOT( voteup_anon() ) ); + + + QMenu *voteMenu = new QMenu( tr("Vote on Link"), &contextMnu ); + voteMenu->setIcon(QIcon(IMAGE_EXPORTFRIEND)); + + QAction *vote_p2 = new QAction( QIcon(IMAGE_GREAT), "[+2] Great", &contextMnu ); + connect( vote_p2 , SIGNAL( triggered() ), this, SLOT( voteup_p2() ) ); + voteMenu->addAction(vote_p2); + QAction *vote_p1 = new QAction( QIcon(IMAGE_GOOD), "[+1] Good", &contextMnu ); + connect( vote_p1 , SIGNAL( triggered() ), this, SLOT( voteup_p1() ) ); + voteMenu->addAction(vote_p1); + QAction *vote_p0 = new QAction( QIcon(IMAGE_OK), "[+0] Okay", &contextMnu ); + connect( vote_p0 , SIGNAL( triggered() ), this, SLOT( voteup_p0() ) ); + voteMenu->addAction(vote_p0); + QAction *vote_m1 = new QAction( QIcon(IMAGE_SUX), "[-1] Sux", &contextMnu ); + connect( vote_m1 , SIGNAL( triggered() ), this, SLOT( voteup_m1() ) ); + voteMenu->addAction(vote_m1); + QAction *vote_m2 = new QAction( QIcon(IMAGE_BADLINK), "[-2] BAD LINK", &contextMnu ); + connect( vote_m2 , SIGNAL( triggered() ), this, SLOT( voteup_m2() ) ); + voteMenu->addAction(vote_m2); + + QAction *downloadAct = new QAction(QIcon(IMAGE_DOWNLOAD), tr("Download"), &contextMnu); + connect(downloadAct, SIGNAL(triggered()), this, SLOT(downloadSelected())); + + contextMnu.addAction(voteupAct); + contextMnu.addSeparator(); + contextMnu.addMenu(voteMenu); + contextMnu.addSeparator(); + contextMnu.addAction(downloadAct); + + contextMnu.exec(QCursor::pos()); +} + +void LinksDialog::changedSortRank( int index ) +{ + /* update */ + if (!rsRanks) + return; + + /* translate */ + uint32_t type = 0; + switch (index) + { + case 1: + type = RS_RANK_TIME; + break; + case 2: + type = RS_RANK_SCORE; + break; + default: + case 0: + type = RS_RANK_ALG; + break; + } + + if (type) + { + rsRanks->setSortMethod(type); + } + updateLinks(); +} + +void LinksDialog::changedSortPeriod( int index ) +{ + /* update */ + if (!rsRanks) + return; + + /* translate */ + uint32_t period = 0; + switch (index) + { + case 1: + period = 60 * 60 * 24 * 7; /* WEEK */ + break; + case 2: + period = 60 * 60 * 24; /* DAY */ + break; + default: + case 0: + period = 60 * 60 * 24 * 30; /* MONTH */ + break; + } + + if (period) + { + rsRanks->setSortPeriod(period); + } + updateLinks(); +} + +void LinksDialog::changedSortFrom( int index ) +{ + /* update */ + if (!rsRanks) + return; + + std::list peers; + + /* translate */ + switch (index) + { + default: + case 0: + break; + case 1: + peers.push_back(rsPeers->getOwnId()); + break; + } + + if (peers.size() < 1) + { + rsRanks->clearPeerFilter(); + } + else + { + rsRanks->setPeerFilter(peers); + } + updateLinks(); +} + +#define ENTRIES_PER_BLOCK 100 + +void LinksDialog::changedSortTop( int index ) +{ + /* update */ + if (!rsRanks) + return; + + std::list peers; + + /* translate */ + switch (index) + { + default: + case 0: + mStart = 0; + break; + case 1: + mStart = 1 * ENTRIES_PER_BLOCK; + break; + case 2: + mStart = 2 * ENTRIES_PER_BLOCK; + break; + case 3: + mStart = 3 * ENTRIES_PER_BLOCK; + break; + case 4: + mStart = 4 * ENTRIES_PER_BLOCK; + break; + case 5: + mStart = -1; + break; + } + updateLinks(); +} + + +/* get the list of Links from the RsRanks. */ +void LinksDialog::updateLinks() +{ + + std::list rids; + std::list::iterator rit; + std::list::iterator cit; + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::updateLinks()" << std::endl; +#endif + + /* Work out the number/entries to show */ + uint32_t count = rsRanks->getRankingsCount(); + uint32_t start; + + uint32_t entries = ENTRIES_PER_BLOCK; + if (count < entries) + { + entries = count; + } + + if (mStart == -1) + { + /* backwards */ + start = count-entries; + } + else + { + start = mStart; + if (start + entries > count) + { + start = count - entries; + } + } + + /* get a link to the table */ + QTreeWidget *linkWidget = ui.linkTreeWidget; + QList items; + + rsRanks->getRankings(start, entries, rids); + float maxRank = rsRanks->getMaxRank(); + + for(rit = rids.begin(); rit != rids.end(); rit++) + { + RsRankDetails detail; + if (!rsRanks->getRankDetails(*rit, detail)) + { + continue; + } + + /* create items */ + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + + /* (0) Title */ + { + item -> setText(0, QString::fromStdWString(detail.title)); + item -> setSizeHint(0, QSize( 20,20 ) ); + + /* Bold and bigger */ + /*QFont font = item->font(0); + font.setBold(true); + font.setPointSize(font.pointSize() + 2); + item->setFont(0, font);*/ + } + + /* (1) Rank */ + { + std::ostringstream out; + out << 100 * (detail.rank / (maxRank + 0.01)); + item -> setText(1, QString::fromStdString(out.str())); + item -> setSizeHint(1, QSize( 20,20 ) ); + + /* Bold and bigger */ + /*QFont font = item->font(1); + font.setBold(true); + font.setPointSize(font.pointSize() + 2); + item->setFont(1, font);*/ + } + + /* (2) Link */ + { + item -> setText(2, QString::fromStdWString(detail.link)); + item -> setSizeHint(2, QSize( 20,20 ) ); + + /* Bold and bigger */ + /*QFont font = item->font(2); + font.setBold(true); + font.setPointSize(font.pointSize() + 2); + item->setFont(2, font);*/ + } + + /* (3) Date */ + /*{ + QDateTime qtime; + qtime.setTime_t(it->lastPost); + QString timestamp = qtime.toString("yyyy-MM-dd hh:mm:ss"); + item -> setText(3, timestamp); + }*/ + + + /* (4) rid */ + item -> setText(4, QString::fromStdString(detail.rid)); + + + /* add children */ + int i = 0; + for(cit = detail.comments.begin(); + cit != detail.comments.end(); cit++, i++) + { + /* create items */ + QTreeWidgetItem *child = new QTreeWidgetItem((QTreeWidget*)0); + + QString commentText; + QString peerScore; + if (cit->score > 1) + { + peerScore = "[+2] "; + child -> setIcon(0,(QIcon(IMAGE_GREAT))); + item -> setIcon(0,(QIcon(IMAGE_GREAT))); + //peerScore = "[+2 Great Link] "; + } + else if (cit->score == 1) + { + peerScore = "[+1] "; + child -> setIcon(0,(QIcon(IMAGE_GOOD))); + item -> setIcon(0,(QIcon(IMAGE_GOOD))); + //peerScore = "[+1 Good] "; + } + else if (cit->score == 0) + { + peerScore = "[+0] "; + child -> setIcon(0,(QIcon(IMAGE_OK))); + item -> setIcon(0,(QIcon(IMAGE_OK))); + //peerScore = "[+0 Okay] "; + } + else if (cit->score == -1) + { + peerScore = "[-1] "; + child -> setIcon(0,(QIcon(IMAGE_SUX))); + item -> setIcon(0,(QIcon(IMAGE_SUX))); + //peerScore = "[-1 Not Worth It] "; + } + else //if (cit->score < -1) + { + peerScore = "[-2 BAD] "; + child -> setIcon(0,(QIcon(IMAGE_BADLINK))); + item -> setIcon(0,(QIcon(IMAGE_BADLINK))); + //peerScore = "[-2 BAD Link] "; + } + + /* (0) Comment */ + if (cit->comment != L"") + { + commentText = peerScore + QString::fromStdWString(cit->comment); + } + else + { + commentText = peerScore + "No Comment"; + } + child -> setText(0, commentText); + + /* (2) Peer / Date */ + { + QDateTime qtime; + qtime.setTime_t(cit->timestamp); + QString timestamp = qtime.toString("yyyy-MM-dd hh:mm:ss"); + + QString peerLabel = QString::fromStdString(rsPeers->getPeerName(cit->id)); + if (peerLabel == "") + { + peerLabel = "<"; + peerLabel += QString::fromStdString(cit->id); + peerLabel += ">"; + } + peerLabel += " "; + + peerLabel += timestamp; + child -> setText(2, peerLabel); + + } + + /* (4) Id */ + child -> setText(4, QString::fromStdString(cit->id)); + + if (i % 2 == 1) + { + /* set to light gray background */ + child->setBackground(0,QBrush(Qt::lightGray)); + child->setBackground(1,QBrush(Qt::lightGray)); + child->setBackground(2,QBrush(Qt::lightGray)); + } + + /* push to items */ + item->addChild(child); + } + + /* add to the list */ + items.append(item); + } + + /* remove old items */ + linkWidget->clear(); + linkWidget->setColumnCount(3); + + /* add the items in! */ + linkWidget->insertTopLevelItems(0, items); + + linkWidget->update(); /* update display */ + + +} + +void LinksDialog::openLink ( QTreeWidgetItem * item, int ) +{ +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::openLink()" << std::endl; +#endif + + /* work out the ids */ + if (!item) + { + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::openLink() Failed Item" << std::endl; +#endif + return; + } + + std::string rid; + std::string pid; + + QTreeWidgetItem *parent = item->parent(); + if (parent) + { + /* a child comment -> ignore double click */ +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::openLink() Failed Child" << std::endl; +#endif + return; + } + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::openLink() " << (item->text(2)).toStdString() << std::endl; +#endif + /* open a browser */ + QUrl url(item->text(2)); + QDesktopServices::openUrl ( url ); + + /* close expansion */ + bool state = item->isExpanded(); + item->setExpanded(!state); +} + +void LinksDialog::changedItem(QTreeWidgetItem *curr, QTreeWidgetItem *) +{ + /* work out the ids */ + if (!curr) + { + updateComments("", ""); + return; + } + + std::string rid; + std::string pid; + + QTreeWidgetItem *parent = curr->parent(); + if (parent) + { + rid = (parent->text(4)).toStdString(); + pid = (curr->text(4)).toStdString(); + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::changedItem() Rid: " << rid << " Pid: " << pid; + std::cerr << std::endl; +#endif + + updateComments(rid, pid); + } + else + { + rid = (curr->text(4)).toStdString(); + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::changedItem() Rid: " << rid << " Pid: NULL"; + std::cerr << std::endl; +#endif + + updateComments(rid, ""); + } +} + +void LinksDialog::checkAnon() +{ + changedItem(ui.linkTreeWidget->currentItem(), NULL); +} + + +int IndexToScore(int index) +{ + if ((index == -1) || (index > 4)) + return 0; + int score = 2 - index; + return score; +} + +int ScoreToIndex(int score) +{ + if ((score < -2) || (score > 2)) + return 2; + int index = 2 - score; + return index; +} + + +/* get the list of Links from the RsRanks. */ +void LinksDialog::updateComments(std::string rid, std::string ) +{ + std::list::iterator cit; + + + if (ui.anonBox->isChecked()) + { + /* empty everything */ + ui.titleLineEdit->setText(""); + ui.linkLineEdit->setText(""); + ui.linkTextEdit->setText(""); + ui.scoreBox->setCurrentIndex(ScoreToIndex(0)); + mLinkId = rid; /* must be set for Context Menu */ + + /* disable comment + score */ + ui.scoreBox->setEnabled(false); + ui.linkTextEdit->setEnabled(false); + + /* done! */ + return; + } + else + { + /* enable comment + score */ + ui.scoreBox->setEnabled(true); + ui.linkTextEdit->setEnabled(true); + } + + + RsRankDetails detail; + if ((rid == "") || (!rsRanks->getRankDetails(rid, detail))) + { + /* clear it up */ + ui.titleLineEdit->setText(""); + ui.linkLineEdit->setText(""); + ui.linkTextEdit->setText(""); + ui.scoreBox->setCurrentIndex(ScoreToIndex(0)); + mLinkId = rid; + return; + } + + + /* set Link details */ + ui.titleLineEdit->setText(QString::fromStdWString(detail.title)); + ui.linkLineEdit->setText(QString::fromStdWString(detail.link)); + ui.linklabel->setHtml(" " + QString::fromStdWString(detail.link) +""); + + + if (mLinkId == rid) + { + /* leave comments */ + //ui.linkTextEdit->setText(""); + return; + } + + mLinkId = rid; + + /* Add your text to the comment */ + std::string ownId = rsPeers->getOwnId(); + + for(cit = detail.comments.begin(); cit != detail.comments.end(); cit++) + { + if (cit->id == ownId) + break; + } + + if (cit != detail.comments.end()) + { + QString comment = QString::fromStdWString(cit->comment); + ui.linkTextEdit->setText(comment); + ui.scoreBox->setCurrentIndex(ScoreToIndex(cit->score)); + } + else + { + ui.linkTextEdit->setText(""); + ui.scoreBox->setCurrentIndex(ScoreToIndex(0)); + + } + + return; +} + +void LinksDialog::addLinkComment( void ) +{ + /* get the title / link / comment */ + QString title = ui.titleLineEdit->text(); + QString link = ui.linkLineEdit->text(); + QString comment = ui.linkTextEdit->toPlainText(); + int32_t score = IndexToScore(ui.scoreBox->currentIndex()); + + if ((mLinkId == "") || (ui.anonBox->isChecked())) + { + if ((link == "") || (title == "")) + { + QMessageBox::warning ( NULL, "Add Link Failure", "Missing Link and/or Title", QMessageBox::Ok); + /* can't do anything */ + return; + } + + /* add it either way */ + if (ui.anonBox->isChecked()) + { + rsRanks->anonRankMsg("", link.toStdWString(), title.toStdWString()); + } + else + { + rsRanks->newRankMsg( + link.toStdWString(), + title.toStdWString(), + comment.toStdWString(), score); + } + + updateLinks(); + return; + } + + /* get existing details */ + + RsRankDetails detail; + if (!rsRanks->getRankDetails(mLinkId, detail)) + { + /* strange error! */ + QMessageBox::warning ( NULL, "Add Link Failure", "Missing Link Data", QMessageBox::Ok); + return; + } + + if (link.toStdWString() == detail.link) /* same link! - we can add a comment */ + { + if (comment == "") /* no comment! */ + { + QMessageBox::warning ( NULL, "Add Link Failure", "Missing Comment", QMessageBox::Ok); + return; + } + + rsRanks->updateComment(mLinkId, + comment.toStdWString(), + score); + } + else + { + QMessageBox::StandardButton sb = QMessageBox::Yes; + + if ((title.toStdWString() == detail.title) /* same title! - wrong */ + || (title == "")) + { + sb = QMessageBox::question ( NULL, "Link Title Not Changed", + "Do you want to continue?", + (QMessageBox::Yes | QMessageBox::No)); + } + + /* add Link! */ + if (sb == QMessageBox::Yes) + { + rsRanks->newRankMsg( + link.toStdWString(), + title.toStdWString(), + comment.toStdWString(), + score); + } + } + updateLinks(); + return; +} + +void LinksDialog::toggleWindows( void ) +{ + /* if msg header visible -> hide by changing splitter + */ + + QList sizeList = ui.msgSplitter->sizes(); + QList::iterator it; + + int listSize = 0; + int msgSize = 0; + int i = 0; + + for(it = sizeList.begin(); it != sizeList.end(); it++, i++) + { + if (i == 0) + { + listSize = (*it); + } + else if (i == 1) + { + msgSize = (*it); + } + } + + int totalSize = listSize + msgSize; + + bool toShrink = true; + if (msgSize < (int) totalSize / 10) + { + toShrink = false; + } + + QList newSizeList; + if (toShrink) + { + newSizeList.push_back(totalSize); + newSizeList.push_back(0); + ui.expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + ui.expandButton->setToolTip(tr("Expand")); + } + else + { + newSizeList.push_back(totalSize * 3/4); + newSizeList.push_back(totalSize * 1/4); + ui.expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + ui.expandButton->setToolTip(tr("Hide")); + } + + ui.msgSplitter->setSizes(newSizeList); + return; +} + + +QTreeWidgetItem *LinksDialog::getCurrentLine() +{ + /* get the current, and extract the Id */ + + /* get a link to the table */ + QTreeWidget *peerWidget = ui.linkTreeWidget; + QTreeWidgetItem *item = peerWidget -> currentItem(); + if (!item) + { +#ifdef LINKS_DEBUG + std::cerr << "Invalid Current Item" << std::endl; +#endif + return NULL; + } + +#ifdef LINKS_DEBUG + /* Display the columns of this item. */ + std::ostringstream out; + out << "CurrentPeerItem: " << std::endl; + + for(int i = 1; i < 6; i++) + { + QString txt = item -> text(i); + out << "\t" << i << ":" << txt.toStdString() << std::endl; + } + std::cerr << out.str(); +#endif + + return item; +} + +void LinksDialog::voteup_anon() +{ + //QTreeWidgetItem *c = getCurrentLine(); + + if (mLinkId == "") + { + return; + } + + RsRankDetails detail; + if (!rsRanks->getRankDetails(mLinkId, detail)) + { + /* not there! */ + return; + } + + QString link = QString::fromStdWString(detail.link); +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::voteup_anon() : " << link.toStdString() << std::endl; +#endif + // need a proper anon sharing option. + rsRanks->anonRankMsg(mLinkId, detail.link, detail.title); +} + + + + +void LinksDialog::voteup_score(int score) +{ + if (mLinkId == "") + { + return; + } + + RsRankDetails detail; + if (!rsRanks->getRankDetails(mLinkId, detail)) + { + /* not there! */ + return; + } + + QString link = QString::fromStdWString(detail.link); + std::wstring comment; +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::voteup_score() : " << link.toStdString() << std::endl; +#endif + + + std::list::iterator cit; + /* Add your text to the comment */ + std::string ownId = rsPeers->getOwnId(); + + for(cit = detail.comments.begin(); cit != detail.comments.end(); cit++) + { + if (cit->id == ownId) + break; + } + + if (cit != detail.comments.end()) + { + comment = cit->comment; + } + + rsRanks->updateComment(mLinkId, comment, score); +} + + +void LinksDialog::voteup_p2() +{ + voteup_score(2); +} + +void LinksDialog::voteup_p1() +{ + voteup_score(1); +} + +void LinksDialog::voteup_p0() +{ + voteup_score(0); +} + +void LinksDialog::voteup_m1() +{ + voteup_score(-1); +} + +void LinksDialog::voteup_m2() +{ + voteup_score(-2); +} + +void LinksDialog::downloadSelected() +{ + if (mLinkId == "") + { + return; + } + + RsRankDetails detail; + if (!rsRanks->getRankDetails(mLinkId, detail)) + { + /* not there! */ + return; + } + + QString link = QString::fromStdWString(detail.link); + std::wstring comment; +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::downloadSelected() : " << link.toStdString() << std::endl; +#endif + + RetroShareLink rslink(QString::fromStdWString(detail.link)); + + if(!rslink.valid() || rslink.type() != RetroShareLink::TYPE_FILE) + { + QMessageBox::critical(NULL,"Badly formed link","This link is badly formed. Can't parse/use it. This is a bug. Please contact the developers.") ; + return ; + } + + /* retrieve all peers id for this file */ + FileInfo info; + rsFiles->FileDetails(rslink.hash().toStdString(), 0, info); + + std::list srcIds; + std::list::iterator pit; + for (pit = info.peers.begin(); pit != info.peers.end(); pit ++) + srcIds.push_back(pit->peerId); + + rsFiles->FileRequest(rslink.name().toStdString(), rslink.hash().toStdString(), rslink.size(), "", 0, srcIds); +} + +void LinksDialog::anchorClicked (const QUrl& link ) +{ + #ifdef LINK_DEBUG + std::cerr << "LinksDialog::anchorClicked link.scheme() : " << link.scheme().toStdString() << std::endl; + #endif + + if (link.scheme() == "retroshare") + { + QStringList L = link.toString().split("|") ; + + std::string fileName = L.at(1).toStdString() ; + uint64_t fileSize = L.at(2).toULongLong(); + std::string fileHash = L.at(3).toStdString() ; + +#ifdef LINK_DEBUG + std::cerr << "LinksDialog::anchorClicked FileRequest : fileName : " << fileName << ". fileHash : " << fileHash << ". fileSize : " << fileSize << std::endl; +#endif + + if (fileName != "" && fileHash != "") + { + std::list srcIds; + + if(rsFiles->FileRequest(fileName, fileHash, fileSize, "", RS_FILE_HINTS_NETWORK_WIDE, srcIds)) + { + QMessageBox mb(tr("File Request Confirmation"), tr("The file has been added to your download list."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + else + { + QMessageBox mb(tr("File Request canceled"), tr("The file has not been added to your download list, because you already have it."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } + } + else + { + QMessageBox mb(tr("File Request Error"), tr("The file link is malformed."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + } + else if (link.scheme() == "http") + { + QDesktopServices::openUrl(link); + } + else if (link.scheme() == "") + { + //it's probably a web adress, let's add http:// at the beginning of the link + QString newAddress = link.toString(); + newAddress.prepend("http://"); + QDesktopServices::openUrl(QUrl(newAddress)); + } +} + +void LinksDialog::addNewLink() +{ + + AddLinksDialog *nAddLinksDialog = new AddLinksDialog(""); + + nAddLinksDialog->show(); + + /* window will destroy itself! */ +} diff --git a/plugins/LinksCloud/LinksDialog.h b/plugins/LinksCloud/LinksDialog.h new file mode 100644 index 000000000..38a15e98f --- /dev/null +++ b/plugins/LinksCloud/LinksDialog.h @@ -0,0 +1,92 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _LINKS_DIALOG_H +#define _LINKS_DIALOG_H + +#include +#include "ui_LinksDialog.h" + + +class LinksDialog : public MainPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + LinksDialog(QWidget *parent = 0); + /** Default Destructor */ + + void insertExample(); + +private slots: + /** Create the context popup menu and it's submenus */ + void linkTreeWidgetCostumPopupMenu( QPoint point ); + + void voteup_anon(); + void voteup_score(int score); + void voteup_p2(); + void voteup_p1(); + void voteup_p0(); + void voteup_m1(); + void voteup_m2(); + void downloadSelected(); + + void changedSortRank( int index ); + void changedSortPeriod( int index ); + void changedSortFrom( int index ); + void changedSortTop( int index ); + + void updateLinks(); + void addLinkComment( void ); + void toggleWindows( void ); + + void openLink ( QTreeWidgetItem * item, int column ); + void changedItem(QTreeWidgetItem *curr, QTreeWidgetItem *prev); + void checkAnon(); + + void checkUpdate(); + + void anchorClicked (const QUrl &); + + void addNewLink(); + +private: + +void updateComments(std::string rid, std::string pid); + + int mStart; /* start of rank list */ + std::string mLinkId; + + /* Worker Functions */ + /* (1) Update Display */ + + /* (2) Utility Fns */ + QTreeWidgetItem *getCurrentLine(); + + QTreeWidget *exampletreeWidget; + + /** Qt Designer generated object */ + Ui::LinksDialog ui; +}; + +#endif + diff --git a/plugins/LinksCloud/LinksDialog.ui b/plugins/LinksCloud/LinksDialog.ui new file mode 100644 index 000000000..59055342b --- /dev/null +++ b/plugins/LinksCloud/LinksDialog.ui @@ -0,0 +1,587 @@ + + + LinksDialog + + + + 0 + 0 + 738 + 583 + + + + + + + + 6 + + + 0 + + + + + + 0 + 0 + + + + Qt::Vertical + + + + + + + + 9 + + + + Qt::CustomContextMenu + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + + + + + + + + :/images/edit_remove24.png:/images/edit_remove24.png + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + + 75 + true + + + + Sort by + + + + + + + + Combo + + + + + Time + + + + :/images/kalarm.png:/images/kalarm.png + + + + + Ranking + + + + :/images/records.png:/images/records.png + + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + + 75 + true + + + + In last + + + + + + + + Month + + + + :/images/view_calendar_month.png:/images/view_calendar_month.png + + + + + Week + + + + :/images/view_calendar_week.png:/images/view_calendar_week.png + + + + + Day + + + + :/images/view_calendar_day.png:/images/view_calendar_day.png + + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + + 75 + true + + + + From + + + + + + + + All Peers + + + + :/images/user/friends24.png:/images/user/friends24.png + + + + + Own Links + + + + :/images/user/identity16.png:/images/user/identity16.png + + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + + 75 + true + + + + Show + + + + + + + + Top 100 + + + + :/images/records.png:/images/records.png + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + + + + + 16777215 + 22 + + + + QTextBrowser{border: 2px solid #CCCCCC; +border-radius: 10px; +background: white;} + + + Qt::ScrollBarAlwaysOff + + + false + + + + + + + + 75 + true + + + + Link: + + + + + + + + + + + + + Qt::Horizontal + + + + 311 + 32 + + + + + + + + + 50 + false + + + + Add Anonymous Link + + + + + + + Add Link/Comment + + + + + + + + + + + Title: + + + + + + + QLineEdit{border: 2px solid #CCCCCC; +border-radius: 10px; +background: white;} + + + + + + + Score: + + + + + + + + +2 Great! + + + + :/images/filerating5.png:/images/filerating5.png + + + + + +1 Good + + + + :/images/filerating4.png:/images/filerating4.png + + + + + 0 Okay + + + + :/images/filerating3.png:/images/filerating3.png + + + + + -1 Sux + + + + :/images/filerating2.png:/images/filerating2.png + + + + + -2 Bad Link + + + + :/images/filerating1.png:/images/filerating1.png + + + + + + + + + + + + Url: + + + + + + + QLineEdit{border: 2px solid #CCCCCC; +border-radius: 10px; +background: white;} + + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QTextEdit{border: 2px solid #CCCCCC; +border-radius: 10px; +background: white;} + + + + + + + + + + + + 16777215 + 32 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + + 24 + 24 + + + + + + + :/images/irkick.png + + + true + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 596 + 15 + + + + + + + + QPushButton:hover { +border: 1px solid #CCCCCC; +} + + + Add new link + + + + :/images/edit_add24.png:/images/edit_add24.png + + + true + + + + + + + + + + + + + diff --git a/plugins/LinksCloud/images.qrc b/plugins/LinksCloud/images.qrc new file mode 100644 index 000000000..8b2550249 --- /dev/null +++ b/plugins/LinksCloud/images.qrc @@ -0,0 +1,5 @@ + + + images/irkick.png + + diff --git a/plugins/LinksCloud/images/irkick.png b/plugins/LinksCloud/images/irkick.png new file mode 100644 index 000000000..b399814ff Binary files /dev/null and b/plugins/LinksCloud/images/irkick.png differ diff --git a/plugins/LinksCloud/p3ranking.cc b/plugins/LinksCloud/p3ranking.cc new file mode 100644 index 000000000..566affb78 --- /dev/null +++ b/plugins/LinksCloud/p3ranking.cc @@ -0,0 +1,1354 @@ +/* + * libretroshare/src/services p3ranking.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rsrankitems.h" +#include "p3ranking.h" +#include +#include + +#include "pqi/p3connmgr.h" +#include "pqi/pqibin.h" +#include "pqi/authssl.h" +#include "pqi/pqistore.h" + +RsRanks *rsRanks = NULL ; + +const uint32_t RANK_MAX_FWD_OFFSET = (60 * 60 * 24 * 2); /* 2 Days */ +const uint32_t RANK_STORE_PERIOD = (60 * 60 * 24 * 30 * 6); /* 6 months */ + +const uint32_t FRIEND_RANK_REPUBLISH_PERIOD = 60; /* every minute for testing */ +//const uint32_t FRIEND_RANK_REPUBLISH_PERIOD = 1800; /* every 30 minutes */ + +std::string generateRandomLinkId(); + +/***** + * TODO + * (1) Streaming. + * (2) Ranking. + * + */ + +/********* + * #define RANK_DEBUG 1 + *********/ +#define RANK_DEBUG 1 + +p3Ranking::p3Ranking() + : RsCacheService(RS_SERVICE_TYPE_RANK,CONFIG_TYPE_RANK_LINK,5), + mRepublish(false), mRepublishFriends(false), mRepublishFriendTS(0), mStorePeriod(RANK_STORE_PERIOD), mUpdated(true) +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + mOwnId = rsPlugins->getConnectMgr()->getOwnId(); + mViewPeriod = 60 * 60 * 24 * 30; /* one Month */ + mSortType = RS_RANK_ALG; +} + +bool p3Ranking::loadLocalCache(const CacheData &data) +{ + std::string filename = data.path + '/' + data.name; + std::string hash = data.hash; + //uint64_t size = data.size; + std::string source = data.pid; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadLocalCache()"; + std::cerr << std::endl; + std::cerr << "\tSource: " << source; + std::cerr << std::endl; + std::cerr << "\tFilename: " << filename; + std::cerr << std::endl; + std::cerr << "\tHash: " << hash; + std::cerr << std::endl; + std::cerr << "\tSize: " << data.size; + std::cerr << std::endl; +#endif + + loadRankFile(filename, source); + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mRepublish = false; + } + + if (data.size > 0) /* don't refresh zero sized caches */ + { + refreshCache(data); + } + return true; +} + +int p3Ranking::loadCache(const CacheData &data) +{ + std::string filename = data.path + '/' + data.name; + std::string hash = data.hash; + //uint64_t size = data.size; + std::string source = data.pid; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadCache()"; + std::cerr << std::endl; + std::cerr << "\tSource: " << source; + std::cerr << std::endl; + std::cerr << "\tFilename: " << filename; + std::cerr << std::endl; + std::cerr << "\tHash: " << hash; + std::cerr << std::endl; + std::cerr << "\tSize: " << data.size; + std::cerr << std::endl; +#endif + + loadRankFile(filename, source); + + + CacheStore::lockData(); /***** LOCK ****/ + locked_storeCacheEntry(data); + CacheStore::unlockData(); /***** UNLOCK ****/ + + return 1; +} + + +void p3Ranking::loadRankFile(std::string filename, std::string src) +{ + /* create the serialiser to load info */ + RsSerialiser *rsSerialiser = new RsSerialiser(); + rsSerialiser->addSerialType(new RsRankSerialiser()); + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_READABLE; + BinInterface *bio = new BinFileInterface(filename.c_str(), bioflags); + pqistore *store = new pqistore(rsSerialiser, src, bio, BIN_FLAGS_READABLE); + + time_t now = time(NULL); + time_t min, max; + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + min = now - mStorePeriod; + max = now + RANK_MAX_FWD_OFFSET; + + } /********** STACK LOCKED MTX ******/ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile()"; + std::cerr << std::endl; + std::cerr << "\tSource: " << src; + std::cerr << std::endl; + std::cerr << "\tFilename: " << filename; + std::cerr << std::endl; +#endif + + RsItem *item; + RsRankLinkMsg *newMsg; + + while(NULL != (item = store->GetItem())) + { + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile() Got Item:"; + std::cerr << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + if (NULL == (newMsg = dynamic_cast(item))) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile() Item not LinkMsg (deleting):"; + std::cerr << std::endl; +#endif + + delete item; + } + /* check timestamp */ + else if (((time_t) newMsg->timestamp < min) || + ((time_t) newMsg->timestamp > max)) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile() Outside TimeRange (deleting):"; + std::cerr << std::endl; +#endif + /* if outside range -> remove */ + delete newMsg; + } + else + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadRankFile() Loading Item"; + std::cerr << std::endl; +#endif + /* correct the source (if is a message from a friend) */ + newMsg->PeerId(newMsg->pid); + addRankMsg(newMsg); + } + } + + delete store; +} + + +void p3Ranking::publishMsgs(bool own) +{ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs()"; + std::cerr << std::endl; +#endif + + std::string path = CacheSource::getCacheDir(); + std::ostringstream out; + uint16_t subid; + + + /* setup name / etc based on whether we're + * publishing own or friends... + */ + + if (own) + { + /* setup to publish own messages */ + out << "rank-links-" << time(NULL) << ".rsrl"; + subid = 1; + } + else + { + /* setup to publish friend messages */ + out << "rank-friend-links-" << time(NULL) << ".rsrl"; + subid = 2; + } + + /* determine filename */ + std::string tmpname = out.str(); + std::string fname = path + "/" + tmpname; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() Storing to: " << fname; + std::cerr << std::endl; +#endif + + RsSerialiser *rsSerialiser = new RsSerialiser(); + rsSerialiser->addSerialType(new RsRankSerialiser()); + + uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_WRITEABLE; + BinInterface *bio = new BinFileInterface(fname.c_str(), bioflags); + pqistore *store = new pqistore(rsSerialiser, mOwnId, bio, BIN_FLAGS_NO_DELETE | BIN_FLAGS_WRITEABLE); + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + /* iterate through list */ + std::map::iterator it; + std::map::iterator cit; + + for(it = mData.begin(); it != mData.end(); it++) + { + if (own) + { + if (it->second.ownTag) + { + /* write to serialiser */ + RsItem *item = it->second.comments[mOwnId]; + if (item) + { + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() Storing Item:"; + std::cerr << std::endl; + item->print(std::cerr, 10); + std::cerr << std::endl; +#endif + store->SendItem(item); + } + } + else + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() Skipping Foreign item"; + std::cerr << std::endl; +#endif + } + } + else + { + /* if we have pushed it out already - don't bother */ + if (it->second.ownTag) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() (Friends) Skipping Own Item"; + std::cerr << std::endl; +#endif + continue; + } + + /* if we have some comments ... then a friend has recommended it + * serialise a sanitized version. + */ + if (it->second.comments.size() > 0) + { + RsRankLinkMsg *origmsg = (it->second.comments.begin())->second; + RsRankLinkMsg *msg = new RsRankLinkMsg(); + + /* copy anon data */ + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + msg->clear(); + msg->PeerId(""); + msg->pid = ""; /* Anon */ + msg->rid = origmsg->rid; + msg->link = origmsg->link; + msg->title = origmsg->title; + msg->timestamp = origmsg->timestamp; + msg->score = 0; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() (Friends) Storing (Anon) Item:"; + std::cerr << std::endl; + msg->print(std::cerr, 10); + std::cerr << std::endl; +#endif + store->SendItem(msg); + + /* cleanup */ + delete msg; + } + } + } + + + /* now we also add our anon messages to the friends list */ + if (!own) + { + std::list::iterator ait; + for(ait=mAnon.begin(); ait != mAnon.end(); ait++) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() (Friends) Adding Own Anon Item:"; + std::cerr << std::endl; + (*ait)->print(std::cerr, 10); + std::cerr << std::endl; +#endif + store->SendItem(*ait); + } + } + + } /********** STACK LOCKED MTX ******/ + + /* flag as new info */ + CacheData data; + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + data.pid = mOwnId; + } /********** STACK LOCKED MTX ******/ + + data.cid = CacheId(CacheSource::getCacheType(), subid); + + data.path = path; + data.name = tmpname; + + data.hash = bio->gethash(); + data.size = bio->bytecount(); + data.recvd = time(NULL); + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::publishMsgs() refreshing Cache"; + std::cerr << std::endl; + std::cerr << "\tCache Path: " << data.path; + std::cerr << std::endl; + std::cerr << "\tCache Name: " << data.name; + std::cerr << std::endl; + std::cerr << "\tCache Hash: " << data.hash; + std::cerr << std::endl; + std::cerr << "\tCache Size: " << data.size; + std::cerr << std::endl; +#endif + if (data.size > 0) /* don't refresh zero sized caches */ + { + refreshCache(data); + } + + delete store; +} + + + +void p3Ranking::addRankMsg(RsRankLinkMsg *msg) +{ + /* find msg */ + std::string id = msg->PeerId(); + std::string rid = msg->rid; + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() Item:"; + std::cerr << std::endl; + msg->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it; + it = mData.find(rid); + if (it == mData.end()) + { + /* add a new one */ + RankGroup grp; + grp.rid = rid; + grp.ownTag = false; + grp.rank = 0.0f; + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + + grp.link = msg->link; + grp.title = msg->title; + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + + mData[rid] = grp; + it = mData.find(rid); + + if (id == "") + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() New Anon Link: mUpdated = true"; + std::cerr << std::endl; +#endif + locked_reSortGroup(it->second); + mUpdated = true; + } + } + + /**** If it is an anonymous Link (ie Friend of a Friend) Drop out now ***/ + if (id == "") + { + return; + } + + /* check for old comment */ + std::map::iterator cit; + cit = (it->second).comments.find(id); + + /* Check that it is different! */ + bool newComment = false; + if ((it->second).comments.end() == cit) + { + newComment = true; + } + else + { + RsRankLinkMsg *old = cit->second; + if ((msg->timestamp != old->timestamp) || + (msg->comment != old->comment)) + { + newComment = true; + } + } + + if (newComment) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() New Comment"; + std::cerr << std::endl; +#endif + /* clean up old */ + if ((it->second).comments.end() != cit) + { + delete (cit->second); + (it->second).comments.erase(cit); + } + + /* add in */ + (it->second).comments[id] = msg; + + /* republish? */ + if (id == mOwnId) + { + it->second.ownTag = true; + mRepublish = true; +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() Own Comment: mRepublish = true"; + std::cerr << std::endl; +#endif + } + else + { + mRepublishFriends = true; +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() Other Comment: mRepublishFriends = true"; + std::cerr << "p3Ranking::addRankMsg() Old Comment ignoring"; + std::cerr << std::endl; +#endif + } + + locked_reSortGroup(it->second); + + mUpdated = true; + } + else + { + delete msg; +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::addRankMsg() Old Comment ignoring"; + std::cerr << std::endl; +#endif + } +} + + +/***************** Sorting ****************/ + +bool p3Ranking::setSortPeriod(uint32_t period) +{ + bool reSort = false; + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + reSort = (mViewPeriod != period); + mViewPeriod = period; + } + + + if (reSort) + { + sortAllMsgs(); + } + + return true; +} + +bool p3Ranking::setSortMethod(uint32_t type) +{ + bool reSort = false; + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + reSort = (mSortType != type); + mSortType = type; + } + + if (reSort) + { + sortAllMsgs(); + } + + return true; +} + +bool p3Ranking::clearPeerFilter() +{ + bool reSort = false; + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + reSort = (mPeerFilter.size() > 0); + mPeerFilter.clear(); + } + + + if (reSort) + { + sortAllMsgs(); + } + + return true; +} + +bool p3Ranking::setPeerFilter(std::list peers) +{ + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mPeerFilter = peers; + } + + sortAllMsgs(); + + return true; +} + +float p3Ranking::locked_calcRank(RankGroup &grp) +{ + /* Ranking Calculations ..... + */ + + time_t now = time(NULL); + time_t minTime = now-mViewPeriod; + bool doFilter = (mPeerFilter.size() > 0); + bool doScore = (mSortType & RS_RANK_SCORE); + bool doTime = (mSortType & RS_RANK_TIME); + + uint32_t count = 0; + float algScore = 0; + float comboScore = 0; + float popScore = 0; + +#ifdef RANK_DEBUG + std::string normlink(grp.link.begin(), grp.link.end()); + std::cerr << "p3Ranking::locked_calcRank() for: " << normlink; + std::cerr << std::endl; + std::cerr << "Period: " << mViewPeriod; + std::cerr << " doFilter: " << doFilter; + std::cerr << " doScore: " << doScore; + std::cerr << " doTime: " << doTime; + std::cerr << std::endl; +#endif + + std::map::iterator it; + for(it = grp.comments.begin(); it != grp.comments.end(); it++) + { +#ifdef RANK_DEBUG + std::cerr << "Comment by:" << it->first << " age: " << now - it->second->timestamp; + std::cerr << std::endl; +#endif + if (doFilter) + { + if (mPeerFilter.end() == + std::find(mPeerFilter.begin(), mPeerFilter.end(), it->first)) + { + continue; /* skip it */ +#ifdef RANK_DEBUG + std::cerr << "\tFiltered Out"; + std::cerr << std::endl; +#endif + + } + } + + /* if Scoring is involved... drop old ones */ + if ((doScore) && ((time_t) it->second->timestamp < minTime)) + { +#ifdef RANK_DEBUG + std::cerr << "\tToo Old"; + std::cerr << std::endl; +#endif + continue; + } + + time_t deltaT; + if ((time_t) it->second->timestamp > now) + { + deltaT = it->second->timestamp - now; + } + else + { + deltaT = now - it->second->timestamp; + } + float timeScore = ((float) mViewPeriod - deltaT) / (mViewPeriod + 0.01); + +#ifdef RANK_DEBUG + std::cerr << "\tTimeScore: " << timeScore; + std::cerr << std::endl; +#endif + + /* algScore is sum of (filtered) timeScores */ + /* timeScore is average of (all) timeScores */ + /* popScore is just count of valid scores */ + + algScore += timeScore; + count++; + + /* for more advanced scoring (where each peer gives a score +2 -> -2) */ + /* combo = SUM value * timeScore */ + /* time = same as before (average) */ + /* popScore = SUM value */ + + float value = it->second->score; + comboScore += value * timeScore; + popScore += value; + } + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::locked_calcRank() algScore: " << algScore; + std::cerr << " Count: " << count; + std::cerr << std::endl; +#endif + + if ((count <= 0) || (algScore <= 0)) + { +#ifdef RANK_DEBUG + std::cerr << "Final score: 0"; + std::cerr << std::endl; +#endif + return 0; + } + + if ((doScore) && (doTime)) + { +#ifdef RANK_DEBUG + std::cerr << "Old (alg) score:" << algScore; + std::cerr << std::endl; + std::cerr << "Final (Combo) score:" << comboScore; + std::cerr << std::endl; +#endif + + if (comboScore < 0) + { +#ifdef RANK_DEBUG + std::cerr << "Combo score reset = 0"; + std::cerr << std::endl; +#endif + comboScore = 0; + } + return comboScore; + + } + else if (doScore) + { +#ifdef RANK_DEBUG + std::cerr << "Old (tally) score:" << count; + std::cerr << std::endl; + std::cerr << "Final (pop) score:" << popScore; + std::cerr << std::endl; +#endif + if (popScore < 0) + { +#ifdef RANK_DEBUG + std::cerr << "Pop score reset = 0"; + std::cerr << std::endl; +#endif + popScore = 0; + } + return popScore; + } + else if (doTime) + { +#ifdef RANK_DEBUG + std::cerr << "Final (time) score:" << algScore / count; + std::cerr << std::endl; +#endif + return algScore / count; + } + return 0; +} + + +void p3Ranking::locked_reSortGroup(RankGroup &grp) +{ + std::string rid = grp.rid; + + /* remove from existings rankings */ + std::multimap::iterator rit; + rit = mRankings.lower_bound(grp.rank); + for(; (rit != mRankings.end()) && (rit->first == grp.rank); rit++) + { + if (rit->second == rid) + { + mRankings.erase(rit); + break; + } + } + + /* add it back in */ + grp.rank = locked_calcRank(grp); + mRankings.insert( + std::pair(grp.rank, rid)); +} + +void p3Ranking::sortAllMsgs() +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + /* iterate through list and re-score each one */ + std::map::iterator it; + + mRankings.clear(); + + for(it = mData.begin(); it != mData.end(); it++) + { + (it->second).rank = locked_calcRank(it->second); + if (it->second.rank < 0) + { + it->second.rank = 0; + } + + mRankings.insert( + std::pair + (it->second.rank, it->first)); + } +} + +/******** ACCESS *************/ + + /* get Ids */ +uint32_t p3Ranking::getRankingsCount() +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + return mRankings.size(); +} + +float p3Ranking::getMaxRank() +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + if (mRankings.size() == 0) + return 0; + + return mRankings.rbegin()->first; +} + +bool p3Ranking::getRankings(uint32_t first, uint32_t count, std::list &rids) +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::getRankings() First: " << first << " Count: " << count; + std::cerr << std::endl; +#endif + + uint32_t i = 0; + std::multimap::reverse_iterator rit; + for(rit = mRankings.rbegin(); (i < first) && (rit != mRankings.rend()); rit++, i++); + + i = 0; + for(; (i < count) && (rit != mRankings.rend()); rit++, i++) + { + rids.push_back(rit->second); + } + return true; +} + + +bool p3Ranking::getRankDetails(std::string rid, RsRankDetails &details) +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + /* get the details. */ + + std::map::iterator it; + it = mData.find(rid); + if (mData.end() == it) + { + return false; + } + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + + details.rid = it->first; + details.link = (it->second).link; + details.title = (it->second).title; + details.rank = (it->second).rank; + details.ownTag = (it->second).ownTag; + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ + + std::map::iterator cit; + for(cit = (it->second).comments.begin(); + cit != (it->second).comments.end(); cit++) + { + RsRankComment comm; + comm.id = (cit->second)->PeerId(); + comm.timestamp = (cit->second)->timestamp; + comm.comment = (cit->second)->comment; + comm.score = (cit->second)->score; + + details.comments.push_back(comm); + } + + return true; +} + + +void p3Ranking::tick() +{ + bool repub = false; + bool repubFriends = false; + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + repub = mRepublish; + repubFriends = mRepublishFriends && (time(NULL) > mRepublishFriendTS); + } + + if (repub) + { + publishMsgs(true); + + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mRepublish = false; + } + + + if (repubFriends) + { + publishMsgs(false); + + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mRepublishFriends = false; + mRepublishFriendTS = time(NULL) + FRIEND_RANK_REPUBLISH_PERIOD; + } + + +} + +bool p3Ranking::updated() +{ + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + if (mUpdated) + { + mUpdated = false; + return true; + } + return false; +} + +/***** NEW CONTENT *****/ +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ +std::string p3Ranking::newRankMsg(std::wstring link, std::wstring title, std::wstring comment, int32_t score) +{ + /* generate an id */ + std::string rid = generateRandomLinkId(); + + RsRankLinkMsg *msg = new RsRankLinkMsg(); + + time_t now = time(NULL); + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + msg->PeerId(mOwnId); + msg->pid = mOwnId; + } + + msg->rid = rid; + msg->title = title; + msg->timestamp = now; + msg->comment = comment; + msg->score = score; + + msg->linktype = RS_LINK_TYPE_WEB; + msg->link = link; + + + addRankMsg(msg); + + return rid; +} + + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ +bool p3Ranking::updateComment(std::string rid, std::wstring comment, int32_t score) +{ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::updateComment() rid:" << rid; + std::cerr << std::endl; +#endif + RsRankLinkMsg *msg = NULL; + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + std::map::iterator it; + it = mData.find(rid); + if (it == mData.end()) + { + /* missing group -> fail */ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::updateComment() Failed - noData"; + std::cerr << std::endl; +#endif + return false; + } + + msg = new RsRankLinkMsg(); + + time_t now = time(NULL); + + msg->PeerId(mOwnId); + msg->pid = mOwnId; + msg->rid = rid; + msg->timestamp = now; + msg->title = (it->second).title; + msg->comment = comment; + msg->score = score; + + msg->linktype = RS_LINK_TYPE_WEB; + msg->link = (it->second).link; + + } /********** STACK UNLOCKED MTX ******/ + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::updateComment() Item:"; + std::cerr << std::endl; + msg->print(std::cerr, 10); + std::cerr << std::endl; +#endif + + addRankMsg(msg); + return true; +} + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ +std::string p3Ranking::anonRankMsg(std::string rid, std::wstring link, std::wstring title) +{ + bool alreadyExists = true; + + if (rid == "") + { + alreadyExists = false; + /* generate an id */ + rid = generateRandomLinkId(); + } + + RsRankLinkMsg *msg1 = new RsRankLinkMsg(); + RsRankLinkMsg *msg2 = new RsRankLinkMsg(); + + time_t now = time(NULL); + + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + msg1->PeerId(""); + msg1->pid = ""; + + msg2->PeerId(""); + msg2->pid = ""; + } + + msg1->rid = rid; + msg1->title = title; + msg1->timestamp = now; + msg1->comment.clear(); + msg1->score = 0; + + msg1->linktype = RS_LINK_TYPE_WEB; + msg1->link = link; + + msg2->rid = rid; + msg2->title = title; + msg2->timestamp = now; + msg2->comment.clear(); + msg2->score = 0; + + msg2->linktype = RS_LINK_TYPE_WEB; + msg2->link = link; + + if (alreadyExists) + { + delete msg1; + } + else + { + addRankMsg(msg1); + } + + addAnonToList(msg2); + + return rid; +} + + + +pqistore *createStore(std::string file, std::string src, bool reading) +{ + + RsSerialiser *rsSerialiser = new RsSerialiser(); + rsSerialiser->addSerialType(new RsRankSerialiser()); + + uint32_t bioflags = BIN_FLAGS_HASH_DATA; + if (reading) + { + bioflags |= BIN_FLAGS_READABLE; + } + else + { + bioflags |= BIN_FLAGS_WRITEABLE; + } + + /* bin flags: READ | WRITE | HASH_DATA */ + BinInterface *bio = new BinFileInterface(file.c_str(), bioflags); + /* store flags: NO_DELETE (yes) | NO_CLOSE (no) */ + pqistore *store = new pqistore(rsSerialiser, src, bio, BIN_FLAGS_NO_DELETE | (bioflags & BIN_FLAGS_WRITEABLE)); + + return store; +} + +std::string generateRandomLinkId() +{ + std::ostringstream out; + out << std::hex; +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS + /* 4 bytes per random number: 4 x 4 = 16 bytes */ + for(int i = 0; i < 4; i++) + { + out << std::setw(8) << std::setfill('0'); + uint32_t rint = random(); + out << rint; + } +#else + srand(time(NULL)); + /* 2 bytes per random number: 8 x 2 = 16 bytes */ + for(int i = 0; i < 8; i++) + { + out << std::setw(4) << std::setfill('0'); + uint16_t rint = rand(); /* only gives 16 bits */ + out << rint; + } +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + return out.str(); +} + + +/*************************************************************************/ +/****************************** LINK SPECIFIC ****************************/ +/*************************************************************************/ +void p3Ranking::createDummyData() +{ + RsRankLinkMsg *msg = new RsRankLinkMsg(); + + time_t now = time(NULL); + + msg->PeerId(mOwnId); + msg->pid = mOwnId; + msg->rid = "0001"; + msg->title = L"Original Awesome Site!"; + msg->timestamp = now - 60 * 60 * 24 * 15; + msg->link = L"http://www.retroshare.org"; + msg->comment = L"Retroshares Website"; + msg->score = 1; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId(mOwnId); + msg->pid = mOwnId; + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 123; + msg->link = L"http://www.lunamutt.org"; + msg->comment = L"Lunamutt's Website"; + msg->score = 1; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId("ALTID"); + msg->pid = "ALTID"; + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 60 * 60 * 24 * 29; + msg->link = L"http://www.lunamutt.org"; + msg->comment = L"Lunamutt's Website (TWO) How Long can this comment be!\n"; + msg->comment += L"What happens to the second line?\n"; + msg->comment += L"And a 3rd!"; + msg->score = 1; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId("ALTID2"); + msg->pid = "ALTID2"; + msg->rid = "0002"; + msg->title = L"Awesome Site!"; + msg->timestamp = now - 60 * 60 * 7; + msg->link = L"http://www.lunamutt.org"; + msg->comment += L"A Short Comment"; + msg->score = 1; + + addRankMsg(msg); + + + /***** Third one ****/ + + msg = new RsRankLinkMsg(); + msg->PeerId(mOwnId); + msg->pid = mOwnId; + msg->rid = "0003"; + msg->title = L"Weird Site!"; + msg->timestamp = now - 60 * 60; + msg->link = L"http://www.lunamutt.com"; + msg->comment = L""; + msg->score = 1; + + addRankMsg(msg); + + msg = new RsRankLinkMsg(); + msg->PeerId("ALTID"); + msg->pid = "ALTID"; + msg->rid = "0003"; + msg->title = L"Weird Site!"; + msg->timestamp = now - 60 * 60 * 24 * 2; + msg->link = L"http://www.lunamutt.com"; + msg->comment = L""; + msg->score = 1; + + addRankMsg(msg); + +} + + +/***************************************************************************/ +/****************************** CONFIGURATION HANDLING *********************/ +/***************************************************************************/ + +/**** Store Anon Links: OVERLOADED FROM p3Config ****/ + +RsSerialiser *p3Ranking::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser(); + + /* add in the types we need! */ + rss->addSerialType(new RsRankSerialiser()); + return rss; +} + +bool p3Ranking::addAnonToList(RsRankLinkMsg *msg) +{ + { + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + std::list::iterator it; + for(it = mAnon.begin(); it != mAnon.end(); it++) + { + if (msg->rid == (*it)->rid) + break; + } + + if (it != mAnon.end()) + { + delete msg; + return false; + } + + mAnon.push_back(msg); + mRepublishFriends = true; + } + + IndicateConfigChanged(); /**** INDICATE CONFIG CHANGED! *****/ + return true; +} + +bool p3Ranking::saveList(bool &cleanup, std::list & saveData) +{ + + mRankMtx.lock(); /*********************** LOCK *******/ + + cleanup = false; + + std::list::iterator it; + for(it = mAnon.begin(); it != mAnon.end(); it++) + { + saveData.push_back(*it); + } + + /* list completed! */ + return true; +} + +void p3Ranking::saveDone() +{ + mRankMtx.unlock(); /*********************** UNLOCK *******/ + return; +} + +bool p3Ranking::loadList(std::list& load) +{ + std::list::iterator it; + RsRankLinkMsg *msg; + +#ifdef SERVER_DEBUG + std::cerr << "p3Ranking::loadList() Item Count: " << load.size(); + std::cerr << std::endl; +#endif + + time_t now = time(NULL); + time_t min, max; + + { RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + + min = now - mStorePeriod; + max = now + RANK_MAX_FWD_OFFSET; + + } /********** STACK LOCKED MTX ******/ + + for(it = load.begin(); it != load.end(); it++) + { + /* switch on type */ + if (NULL != (msg = dynamic_cast(*it))) + { + /* check date -> if old expire */ + if (((time_t) msg->timestamp < min) || + ((time_t) msg->timestamp > max)) + { +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadList() Outside TimeRange (deleting Own Anon):"; + std::cerr << std::endl; +#endif + /* if outside range -> remove */ + delete msg; + continue; + } + +#ifdef RANK_DEBUG + std::cerr << "p3Ranking::loadList() Anon TimeRange ok"; + std::cerr << std::endl; +#endif + msg->PeerId(""); + msg->pid = ""; + + RsRankLinkMsg *msg2 = new RsRankLinkMsg(); + msg2->clear(); + msg2->PeerId(msg->PeerId()); + msg2->pid = msg->pid; + msg2->rid = msg->rid; + msg2->title = msg->title; + msg2->timestamp = msg->timestamp; + msg2->comment.clear(); + msg2->score = 0; + + msg2->linktype = msg->linktype; + msg2->link = msg->link; + + /* make a copy to add into standard map */ + addRankMsg(msg); + + RsStackMutex stack(mRankMtx); /********** STACK LOCKED MTX ******/ + mAnon.push_back(msg2); + } + else + { + /* cleanup */ + delete (*it); + } + } + + return true; + +} + diff --git a/plugins/LinksCloud/p3ranking.h b/plugins/LinksCloud/p3ranking.h new file mode 100644 index 000000000..6b5abac7f --- /dev/null +++ b/plugins/LinksCloud/p3ranking.h @@ -0,0 +1,165 @@ +/* + * libretroshare/src/services: p3ranking.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_GENERIC_RANKING_HEADER +#define P3_GENERIC_RANKING_HEADER + +class pqistore ; + +#include "retroshare/rsplugin.h" +#include "plugins/pluginclasses.h" + +#include "rsrank.h" + +/* + * A Generic Ranking system. + * Each User provides one cache... + * + * can be overloaded for specific types + * (links, shares, photos etc) + * + * This is not generic yet!!! + */ + +class RsRankMsg; +class RsRankLinkMsg; + +const uint16_t RS_SERVICE_TYPE_RANK = 0x0002 ; +const uint32_t CONFIG_TYPE_RANK_LINK = 0x0011 ; + +class RankGroup +{ + public: + + std::string rid; /* Random Id */ + std::wstring link; + std::wstring title; + float rank; + bool ownTag; + std::map comments; +}; + +class p3Ranking: public RsCacheService, public RsRanks +{ + public: + + p3Ranking() ; + + + /******************************* CACHE SOURCE / STORE Interface *********************/ + + /* overloaded functions from Cache Source */ + virtual bool loadLocalCache(const CacheData &data); + + /* overloaded functions from Cache Store */ + virtual int loadCache(const CacheData &data); + + /******************************* CACHE SOURCE / STORE Interface *********************/ + + public: + + /************* Extern Interface *******/ + + /* changed */ + virtual bool updated(); + + /* Set Sort Methods */ + virtual bool setSortPeriod(uint32_t period); + virtual bool setSortMethod(uint32_t type); + virtual bool clearPeerFilter(); + virtual bool setPeerFilter(std::list peers); + + /* get Ids */ + virtual uint32_t getRankingsCount(); + virtual float getMaxRank(); + virtual bool getRankings(uint32_t first, uint32_t count, std::list &rids); + virtual bool getRankDetails(std::string rid, RsRankDetails &details); + + /* Add New Comment / Msg */ + virtual std::string newRankMsg(std::wstring link, std::wstring title, std::wstring comment, int32_t score); + virtual bool updateComment(std::string rid, std::wstring comment, int32_t score); + virtual std::string anonRankMsg(std::string rid, std::wstring link, std::wstring title); + + + virtual void tick(); + + void loadRankFile(std::string filename, std::string src); + void addRankMsg(RsRankLinkMsg *msg); + void publishMsgs(bool own); + + float locked_calcRank(RankGroup &grp); /* returns 0->100 */ + void locked_reSortGroup(RankGroup &grp); + + void sortAllMsgs(); + pqistore *createStore(std::string file, std::string src, bool reading); + + + /****************** p3Config STUFF *******************/ + protected: + bool addAnonToList(RsRankLinkMsg *msg); + + virtual RsSerialiser *setupSerialiser(); + virtual bool saveList(bool &cleanup, std::list&); + virtual bool loadList(std::list& load); + virtual void saveDone(); + + private: + + void createDummyData(); + + uint32_t storePeriod; + p3ConnectMgr *mConnMgr; + + RsMutex mRankMtx; + + /***** below here is locked *****/ + + bool mRepublish; + bool mRepublishFriends; + time_t mRepublishFriendTS; + + uint32_t mStorePeriod; + + std::string mOwnId; + bool mUpdated; + bool mRepost; + + std::map mData; + std::multimap mRankings; + + /* Filter/Sort params */ + std::list mPeerFilter; + uint32_t mViewPeriod; + uint32_t mSortType; + + /* Anonymous Link List */ + std::list mAnon; + +}; + +#endif + + + diff --git a/plugins/LinksCloud/rsrank.h b/plugins/LinksCloud/rsrank.h new file mode 100644 index 000000000..a69425c91 --- /dev/null +++ b/plugins/LinksCloud/rsrank.h @@ -0,0 +1,96 @@ +#ifndef RETROSHARE_RANKING_GUI_INTERFACE_H +#define RETROSHARE_RANKING_GUI_INTERFACE_H + +/* + * libretroshare/src/rsiface: rsrank.h + * + * RetroShare C++ Interface. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include +#include + +/* The Main Interface Class - for information about your Peers */ +class RsRanks; +extern RsRanks *rsRanks; + +class RsRankComment +{ + public: + + std::string id; + std::wstring comment; + int32_t score; + time_t timestamp; +}; + +class RsRankDetails +{ + public: + + std::string rid; + std::wstring link; + std::wstring title; + float rank; + bool ownTag; + + std::list comments; +}; + +const uint32_t RS_RANK_SCORE = 0x0001; +const uint32_t RS_RANK_TIME = 0x0002; +const uint32_t RS_RANK_ALG = 0x0003; + +std::ostream &operator<<(std::ostream &out, const RsRankDetails &detail); + +class RsRanks +{ + public: + + RsRanks() { return; } +virtual ~RsRanks() { return; } + + /* needs update? */ +virtual bool updated() = 0; + + /* Set Sort Methods */ +virtual bool setSortPeriod(uint32_t period) = 0; +virtual bool setSortMethod(uint32_t type) = 0; +virtual bool clearPeerFilter() = 0; +virtual bool setPeerFilter(std::list peers) = 0; + + /* get Ids */ +virtual uint32_t getRankingsCount() = 0; +virtual float getMaxRank() = 0; +virtual bool getRankings(uint32_t first, uint32_t count, std::list &rids) = 0; +virtual bool getRankDetails(std::string rid, RsRankDetails &details) = 0; + + /* Add New Comment / Msg */ +virtual std::string newRankMsg(std::wstring link, std::wstring title, std::wstring comment, int32_t score) = 0; +virtual bool updateComment(std::string rid, std::wstring comment, int32_t score) = 0; + +virtual std::string anonRankMsg(std::string rid, std::wstring link, std::wstring title) = 0; + +}; + +#endif diff --git a/plugins/LinksCloud/rsrankitems.cc b/plugins/LinksCloud/rsrankitems.cc new file mode 100644 index 000000000..dbae0de68 --- /dev/null +++ b/plugins/LinksCloud/rsrankitems.cc @@ -0,0 +1,253 @@ + +/* + * libretroshare/src/serialiser: rsbaseitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rstlvbase.h" +#include "rsrankitems.h" + +#define RSSERIAL_DEBUG 1 +#include + +/*************************************************************************/ + +void RsRankMsg::clear() +{ + rid.clear(); + timestamp = 0; + title.clear(); + comment.clear(); +} + +std::ostream &RsRankMsg::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsRankMsg", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "rid: " << rid << std::endl; + + printIndent(out, int_Indent); + out << "timestamp: " << timestamp << std::endl; + + + printIndent(out, int_Indent); + + std::string cnv_title(title.begin(), title.end()); + out << "msg: " << cnv_title << std::endl; + + printIndent(out, int_Indent); + std::string cnv_comment(comment.begin(), comment.end()); + out << "comment: " << cnv_comment << std::endl; + + printIndent(out, int_Indent); + out << "score: " << score << std::endl; + + printRsItemEnd(out, "RsRankMsg", indent); + return out; +} + +/*************************************************************************/ + +void RsRankLinkMsg::clear() +{ + rid.clear(); + pid.clear(); + timestamp = 0; + title.clear(); + comment.clear(); + score = 0; + linktype = 0; + link.clear(); +} + +std::ostream &RsRankLinkMsg::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsRankLinkMsg", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "rid: " << rid << std::endl; + printIndent(out, int_Indent); + out << "pid: " << pid << std::endl; + + printIndent(out, int_Indent); + out << "timestamp: " << timestamp << std::endl; + + printIndent(out, int_Indent); + + std::string cnv_title(title.begin(), title.end()); + out << "msg: " << cnv_title << std::endl; + + printIndent(out, int_Indent); + std::string cnv_comment(comment.begin(), comment.end()); + out << "comment: " << cnv_comment << std::endl; + + printIndent(out, int_Indent); + out << "score: " << score << std::endl; + + printIndent(out, int_Indent); + out << "linktype: " << linktype << std::endl; + printIndent(out, int_Indent); + std::string cnv_link(link.begin(), link.end()); + out << "link: " << cnv_link << std::endl; + + printRsItemEnd(out, "RsRankLinkMsg", indent); + return out; +} + + +uint32_t RsRankSerialiser::sizeLink(RsRankLinkMsg *item) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(item->rid); + s += GetTlvStringSize(item->pid); + s += 4; /* timestamp */ + s += GetTlvWideStringSize(item->title); + s += GetTlvWideStringSize(item->comment); + s += 4; /* score */ + s += 4; /* linktype */ + s += GetTlvWideStringSize(item->link); + + return s; +} + +/* serialise the data to the buffer */ +bool RsRankSerialiser::serialiseLink(RsRankLinkMsg *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeLink(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GENID, item->rid); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->pid); + + ok &= setRawUInt32(data, tlvsize, &offset, item->timestamp); + + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_TITLE, item->title); + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_COMMENT, item->comment); + + ok &= setRawUInt32(data, tlvsize, &offset, *((uint32_t *) &(item->score))); + + ok &= setRawUInt32(data, tlvsize, &offset, item->linktype); + + ok &= SetTlvWideString(data, tlvsize, &offset, TLV_TYPE_WSTR_LINK, item->link); + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsRankLinkSerialiser::serialiseLink() Size Error! " << std::endl; + } + + return ok; +} + +RsRankLinkMsg *RsRankSerialiser::deserialiseLink(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_RANK != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_RANK_LINK3 != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsRankLinkMsg *item = new RsRankLinkMsg(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GENID, item->rid); + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->pid); + ok &= getRawUInt32(data, rssize, &offset, &(item->timestamp)); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_TITLE, item->title); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_COMMENT, item->comment); + ok &= getRawUInt32(data, rssize, &offset, (uint32_t *) &(item->score)); + ok &= getRawUInt32(data, rssize, &offset, &(item->linktype)); + ok &= GetTlvWideString(data, rssize, &offset, TLV_TYPE_WSTR_LINK, item->link); + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +uint32_t RsRankSerialiser::size(RsItem *item) +{ + return sizeLink((RsRankLinkMsg *) item); +} + +bool RsRankSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +{ + return serialiseLink((RsRankLinkMsg *) item, data, pktsize); +} + +RsItem *RsRankSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + return deserialiseLink(data, pktsize); +} + + + +/*************************************************************************/ + diff --git a/plugins/LinksCloud/rsrankitems.h b/plugins/LinksCloud/rsrankitems.h new file mode 100644 index 000000000..a3ddc78aa --- /dev/null +++ b/plugins/LinksCloud/rsrankitems.h @@ -0,0 +1,110 @@ +#ifndef RS_RANK_ITEMS_H +#define RS_RANK_ITEMS_H + +/* + * libretroshare/src/serialiser: rsrankitems.h + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsserial.h" +#include "serialiser/rstlvtypes.h" + +#include "p3ranking.h" + +const uint8_t RS_PKT_SUBTYPE_RANK_LINK3 = 0x04; +const uint8_t RS_PKT_SUBTYPE_RANK_PHOTO = 0x05; + +/**************************************************************************/ + + +class RsRankMsg: public RsItem +{ + public: + RsRankMsg(uint8_t subtype) :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_RANK, subtype) { return; } + + virtual ~RsRankMsg() { return; } + virtual void clear(); + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + std::string rid; /* Random Id */ + std::string pid; /* Peer Id (cannot use RsItem::PeerId - as FoF transport!) */ + uint32_t timestamp; + std::wstring title; + std::wstring comment; + int32_t score; +}; + + +/* Flags */ +const uint32_t RS_LINK_TYPE_WEB = 0x0001; +const uint32_t RS_LINK_TYPE_OFF = 0x0002; + +class RsRankLinkMsg: public RsRankMsg +{ + public: + RsRankLinkMsg() + :RsRankMsg(RS_PKT_SUBTYPE_RANK_LINK3) { return; } +virtual ~RsRankLinkMsg() { return; } +virtual void clear(); +virtual std::ostream& print(std::ostream &out, uint16_t indent = 0); + + /**** SAME as RsRankMsg **** + std::string rid; + uint32_t timestamp; + std::wstring title; + std::wstring comment; + int32_t score; + ***************************/ + + /* Link specific Fields */ + uint32_t linktype; /* to be used later! */ + std::wstring link; +}; + +class RsRankSerialiser: public RsSerialType +{ + public: + RsRankSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_RANK) + { return; } +virtual ~RsRankSerialiser() + { return; } + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + + /* For RS_PKT_SUBTYPE_RANK_LINK */ +virtual uint32_t sizeLink(RsRankLinkMsg *); +virtual bool serialiseLink (RsRankLinkMsg *item, void *data, uint32_t *size); +virtual RsRankLinkMsg *deserialiseLink(void *data, uint32_t *size); + +}; + +/**************************************************************************/ + +#endif /* RS_RANK_ITEMS_H */ + + diff --git a/plugins/PluginInterface.h b/plugins/PluginInterface.h new file mode 100644 index 000000000..5d64df426 --- /dev/null +++ b/plugins/PluginInterface.h @@ -0,0 +1,51 @@ +#ifndef _PLUGIN_INTERFACE_H_ +#define _PLUGIN_INTERFACE_H_ + +#include + +#include +/*** +QT_BEGIN_NAMESPACE +class QString; +class QWidget; +QT_END_NAMESPACE +***/ + +//! a base class for plugins + +//! All plugin classes must inherite this class and QObject. +class PluginInterface +{ +public: + virtual ~PluginInterface() {} + +public slots: + //! A description of the plugin + + //! A description of the plugin. Is not used in current version. + virtual QString pluginDescription() const = 0; + + //! The plugin's name + + //! A name serves like an unique ID. The name is used in all operations + //! such as installing, removing, receiving a widget + virtual QString pluginName() const = 0; + + //! plugin's widget. + + //! Returns the widget, which is actually a plugin. Main application must + //! delete the widget; usually, a parent widget does it. If you want to use + //! the widget as top-level (i.e. parent==0), please, set + //! Qt::WA_DeleteOnClose flag . + virtual QWidget* pluginWidget(QWidget * parent = 0) = 0; +}; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_INTERFACE(PluginInterface, + "com.beardog.retroshare.PluginInterface/1.0") + +QT_END_NAMESPACE + +#endif + diff --git a/plugins/calculator_plugin/calculator.js b/plugins/calculator_plugin/calculator.js new file mode 100644 index 000000000..1efe90b69 --- /dev/null +++ b/plugins/calculator_plugin/calculator.js @@ -0,0 +1,264 @@ +//! [0] +function Plugin(ui) +{ + this.ui = ui; + + this.pendingAdditiveOperator = ""; + this.pendingMultiplicativeOperator = ""; + this.sumInMemory = 0; + this.sumSoFar = 0; + this.factorSoFar = 0; + this.waitingForOperand = true; + + with (ui) { + display.text = "0"; + + zeroButton.clicked.connect(this, this.digitClicked); + oneButton.clicked.connect(this, "digitClicked"); + twoButton.clicked.connect(this, "digitClicked"); + threeButton.clicked.connect(this, "digitClicked"); + fourButton.clicked.connect(this, "digitClicked"); + fiveButton.clicked.connect(this, "digitClicked"); + sixButton.clicked.connect(this, "digitClicked"); + sevenButton.clicked.connect(this, "digitClicked"); + eightButton.clicked.connect(this, "digitClicked"); + nineButton.clicked.connect(this, "digitClicked"); + + pointButton.clicked.connect(this, "pointClicked"); + changeSignButton.clicked.connect(this, "changeSignClicked"); + + backspaceButton.clicked.connect(this, "backspaceClicked"); + clearButton.clicked.connect(this, "clear"); + clearAllButton.clicked.connect(this, "clearAll"); + + clearMemoryButton.clicked.connect(this, "clearMemory"); + readMemoryButton.clicked.connect(this, "readMemory"); + setMemoryButton.clicked.connect(this, "setMemory"); + addToMemoryButton.clicked.connect(this, "addToMemory"); + + divisionButton.clicked.connect(this, "multiplicativeOperatorClicked"); + timesButton.clicked.connect(this, "multiplicativeOperatorClicked"); + minusButton.clicked.connect(this, "additiveOperatorClicked"); + plusButton.clicked.connect(this, "additiveOperatorClicked"); + + squareRootButton.clicked.connect(this, "unaryOperatorClicked"); + powerButton.clicked.connect(this, "unaryOperatorClicked"); + reciprocalButton.clicked.connect(this, "unaryOperatorClicked"); + equalButton.clicked.connect(this, "equalClicked"); + } +} +//! [0] + +Plugin.prototype.abortOperation = function() +{ + this.clearAll(); + this.ui.display.text = "####"; +} + +Plugin.prototype.calculate = function(rightOperand, pendingOperator) +{ + if (pendingOperator == "+") { + this.sumSoFar += rightOperand; + } else if (pendingOperator == "-") { + this.sumSoFar -= rightOperand; + } else if (pendingOperator == "*") { + this.factorSoFar *= rightOperand; + } else if (pendingOperator == "/") { + if (rightOperand == 0) + return false; + this.factorSoFar /= rightOperand; + } + return true; +} + +//! [1] +Plugin.prototype.digitClicked = function() +{ + var digitValue = __qt_sender__.text - 0; + if ((digitValue == 0) && (this.ui.display.text == "0")) + return; + if (this.waitingForOperand) { + this.ui.display.clear(); + this.waitingForOperand = false; + } + this.ui.display.text += digitValue; +} +//! [1] + +Plugin.prototype.unaryOperatorClicked = function() +{ + var operand = this.ui.display.text - 0; + var result = 0; + if (__qt_sender__.text == "Sqrt") { + if (operand < 0) { + this.abortOperation(); + return; + } + result = Math.sqrt(operand); + } else if (__qt_sender__.text == "x^2") { + result = Math.pow(operand, 2); + } else if (__qt_sender__.text == "1/x") { + if (operand == 0.0) { + this.abortOperation(); + return; + } + result = 1 / operand; + } + this.ui.display.text = result + ""; + this.waitingForOperand = true; +} + +Plugin.prototype.additiveOperatorClicked = function() +{ + var operand = this.ui.display.text - 0; + + if (this.pendingMultiplicativeOperator.length != 0) { + if (!this.calculate(operand, this.pendingMultiplicativeOperator)) { + this.abortOperation(); + return; + } + this.ui.display.text = this.factorSoFar + ""; + operand = this.factorSoFar; + this.factorSoFar = 0; + this.pendingMultiplicativeOperator = ""; + } + + if (this.pendingAdditiveOperator.length != 0) { + if (!this.calculate(operand, this.pendingAdditiveOperator)) { + this.abortOperation(); + return; + } + this.ui.display.text = this.sumSoFar + ""; + } else { + this.sumSoFar = operand; + } + + this.pendingAdditiveOperator = __qt_sender__.text; + this.waitingForOperand = true; +} + +Plugin.prototype.multiplicativeOperatorClicked = function() +{ + var operand = this.ui.display.text - 0; + + if (this.pendingMultiplicativeOperator.length != 0) { + if (!this.calculate(operand, this.pendingMultiplicativeOperator)) { + this.abortOperation(); + return; + } + this.ui.display.text = this.factorSoFar + ""; + } else { + this.factorSoFar = operand; + } + + this.pendingMultiplicativeOperator = __qt_sender__.text; + this.waitingForOperand = true; +} + +Plugin.prototype.equalClicked = function() +{ + var operand = this.ui.display.text - 0; + + if (this.pendingMultiplicativeOperator.length != 0) { + if (!this.calculate(operand, this.pendingMultiplicativeOperator)) { + this.abortOperation(); + return; + } + operand = this.factorSoFar; + this.factorSoFar = 0.0; + this.pendingMultiplicativeOperator = ""; + } + if (this.pendingAdditiveOperator.length != 0) { + if (!this.calculate(operand, this.pendingAdditiveOperator)) { + this.abortOperation(); + return; + } + this.pendingAdditiveOperator = ""; + } else { + this.sumSoFar = operand; + } + + this.ui.display.text = this.sumSoFar + ""; + this.sumSoFar = 0.0; + this.waitingForOperand = true; +} + +Plugin.prototype.pointClicked = function() +{ + if (this.waitingForOperand) + this.ui.display.text = "0"; + if (this.ui.display.text.indexOf(".") == -1) + this.ui.display.text += "."; + this.waitingForOperand = false; +} + +//! [2] +Plugin.prototype.changeSignClicked = function() +{ + var text = this.ui.display.text; + var value = text - 0; + + if (value > 0) { + text = "-" + text; + } else if (value < 0) { + text = text.slice(1); + } + this.ui.display.text = text; +} +//! [2] + +Plugin.prototype.backspaceClicked = function() +{ + if (this.waitingForOperand) + return; + + var text = this.ui.display.text; + text = text.slice(0, -1); + if (text.length == 0) { + text = "0"; + this.waitingForOperand = true; + } + this.ui.display.text = text; +} + +Plugin.prototype.clear = function() +{ + if (this.waitingForOperand) + return; + + this.ui.display.text = "0"; + this.waitingForOperand = true; +} + +Plugin.prototype.clearAll = function() +{ + this.sumSoFar = 0.0; + this.factorSoFar = 0.0; + this.pendingAdditiveOperator = ""; + this.pendingMultiplicativeOperator = ""; + this.ui.display.text = "0"; + this.waitingForOperand = true; +} + +Plugin.prototype.clearMemory = function() +{ + this.sumInMemory = 0.0; +} + +Plugin.prototype.readMemory = function() +{ + this.ui.display.text = this.sumInMemory + ""; + this.waitingForOperand = true; +} + +Plugin.prototype.setMemory = function() +{ + this.equalClicked(); + this.sumInMemory = this.ui.display.text - 0; +} + +Plugin.prototype.addToMemory = function() +{ + this.equalClicked(); + this.sumInMemory += this.ui.display.text - 0; +} diff --git a/plugins/calculator_plugin/calculator.ui b/plugins/calculator_plugin/calculator.ui new file mode 100644 index 000000000..1488892fa --- /dev/null +++ b/plugins/calculator_plugin/calculator.ui @@ -0,0 +1,406 @@ + + Calculator + + + + 0 + 0 + 314 + 301 + + + + + 0 + 0 + + + + + 314 + 301 + + + + + 314 + 301 + + + + Calculator + + + + + 10 + 50 + 91 + 41 + + + + Backspace + + + + + + 110 + 50 + 91 + 41 + + + + Clear :) + + + + + + 210 + 50 + 91 + 41 + + + + Clear All + + + + + + 10 + 100 + 41 + 41 + + + + MC + + + + + + 10 + 150 + 41 + 41 + + + + MR + + + + + + 10 + 200 + 41 + 41 + + + + MS + + + + + + 10 + 250 + 41 + 41 + + + + M+ + + + + + + 60 + 100 + 41 + 41 + + + + 7 + + + + + + 110 + 100 + 41 + 41 + + + + 8 + + + + + + 160 + 100 + 41 + 41 + + + + 9 + + + + + + 60 + 150 + 41 + 41 + + + + 4 + + + + + + 110 + 150 + 41 + 41 + + + + 5 + + + + + + 160 + 150 + 41 + 41 + + + + 6 + + + + + + 60 + 200 + 41 + 41 + + + + 1 + + + + + + 110 + 200 + 41 + 41 + + + + 2 + + + + + + 160 + 200 + 41 + 41 + + + + 3 + + + + + + 60 + 250 + 41 + 41 + + + + 0 + + + + + + 110 + 250 + 41 + 41 + + + + . + + + + + + 160 + 250 + 41 + 41 + + + + +- + + + + + + 210 + 250 + 41 + 41 + + + + + + + + + + + 210 + 100 + 41 + 41 + + + + / + + + + + + 210 + 150 + 41 + 41 + + + + * + + + + + + 210 + 200 + 41 + 41 + + + + - + + + + + + 260 + 100 + 41 + 41 + + + + Sqrt + + + + + + 260 + 150 + 41 + 41 + + + + x^2 + + + + + + 260 + 200 + 41 + 41 + + + + 1/x + + + + + + 260 + 250 + 41 + 41 + + + + = + + + + + + 10 + 10 + 291 + 31 + + + + 15 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + diff --git a/plugins/calendar_plugin/calendar_plugin.pro b/plugins/calendar_plugin/calendar_plugin.pro new file mode 100644 index 000000000..36b06d931 --- /dev/null +++ b/plugins/calendar_plugin/calendar_plugin.pro @@ -0,0 +1,28 @@ +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin debug + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(calendar_plugin) + +HEADERS += ../PluginInterface.h \ + src/CalendarPlugin.h +SOURCES += src/CalendarPlugin.cpp + +#=============================================================================== + +#=== and this are definitions, specific for this program ======================= +HEADERS += src/mainwindow.h +SOURCES += src/mainwindow.cpp +#=============================================================================== diff --git a/plugins/calendar_plugin/src/CalendarPlugin.cpp b/plugins/calendar_plugin/src/CalendarPlugin.cpp new file mode 100644 index 000000000..04a532769 --- /dev/null +++ b/plugins/calendar_plugin/src/CalendarPlugin.cpp @@ -0,0 +1,33 @@ +//#include +//#include +//#include + +#include "CalendarPlugin.h" +#include "mainwindow.h" + +QString +CalendarPlugin::pluginDescription() const +{ + QString res; + res = "A simple plugin, based on QT calendar(richtext) example" ; + + return res; +} + +QString +CalendarPlugin::pluginName() const +{ + return "Calendar" ; +} + +QWidget* +CalendarPlugin::pluginWidget(QWidget * parent ) +{ + MainWindow* window = new MainWindow(parent); + //window->openImage(":/images/example.jpg"); + + return window; +} + + +Q_EXPORT_PLUGIN2(calendar_plugin, CalendarPlugin) diff --git a/plugins/calendar_plugin/src/CalendarPlugin.h b/plugins/calendar_plugin/src/CalendarPlugin.h new file mode 100644 index 000000000..d1a0b47b8 --- /dev/null +++ b/plugins/calendar_plugin/src/CalendarPlugin.h @@ -0,0 +1,27 @@ +#ifndef _HWA_PLUGIN_H_ +#define _HWA_PLUGIN_H_ + +#include + +#include +#include + +#include + +#include + +class CalendarPlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/calendar_plugin/src/mainwindow.cpp b/plugins/calendar_plugin/src/mainwindow.cpp new file mode 100644 index 000000000..715ce3025 --- /dev/null +++ b/plugins/calendar_plugin/src/mainwindow.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information +** to ensure GNU General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. In addition, as a special +** exception, Nokia gives you certain additional rights. These rights +** are described in the Nokia Qt GPL Exception version 1.3, included in +** the file GPL_EXCEPTION.txt in this package. +** +** Qt for Windows(R) Licensees +** As a special exception, Nokia, as the sole copyright holder for Qt +** Designer, grants users of the Qt/Eclipse Integration plug-in the +** right for the Qt/Eclipse Integration to link to functionality +** provided by Qt Designer and its related libraries. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include + +#include "mainwindow.h" + +//! [0] +MainWindow::MainWindow(QWidget* parent) + :QFrame(parent) +{ + selectedDate = QDate::currentDate(); + fontSize = 10; + + // QWidget *centralWidget = new QWidget; +//! [0] + +//! [1] + QLabel *dateLabel = new QLabel(tr("Date:")); + QComboBox *monthCombo = new QComboBox; + + for (int month = 1; month <= 12; ++month) + monthCombo->addItem(QDate::longMonthName(month)); + + QDateTimeEdit *yearEdit = new QDateTimeEdit; + yearEdit->setDisplayFormat("yyyy"); + yearEdit->setDateRange(QDate(1753, 1, 1), QDate(8000, 1, 1)); +//! [1] + + monthCombo->setCurrentIndex(selectedDate.month() - 1); + yearEdit->setDate(selectedDate); + +//! [2] + QLabel *fontSizeLabel = new QLabel(tr("Font size:")); + QSpinBox *fontSizeSpinBox = new QSpinBox; + fontSizeSpinBox->setRange(1, 64); + fontSizeSpinBox->setValue(10); + + editor = new QTextBrowser; + insertCalendar(); +//! [2] + +//! [3] + connect(monthCombo, SIGNAL(activated(int)), this, SLOT(setMonth(int))); + connect(yearEdit, SIGNAL(dateChanged(QDate)), this, SLOT(setYear(QDate))); + connect(fontSizeSpinBox, SIGNAL(valueChanged(int)), + this, SLOT(setFontSize(int))); +//! [3] + +//! [4] + QHBoxLayout *controlsLayout = new QHBoxLayout; + controlsLayout->addWidget(dateLabel); + controlsLayout->addWidget(monthCombo); + controlsLayout->addWidget(yearEdit); + controlsLayout->addSpacing(24); + controlsLayout->addWidget(fontSizeLabel); + controlsLayout->addWidget(fontSizeSpinBox); + controlsLayout->addStretch(1); + + QVBoxLayout *centralLayout = new QVBoxLayout; + centralLayout->addLayout(controlsLayout); + centralLayout->addWidget(editor, 1); + //centralWidget->setLayout(centralLayout); + this->setLayout(centralLayout); + + //setCentralWidget(centralWidget); +//! [4] +} + +//! [5] +void MainWindow::insertCalendar() +{ + editor->clear(); + QTextCursor cursor = editor->textCursor(); + cursor.beginEditBlock(); + + QDate date(selectedDate.year(), selectedDate.month(), 1); +//! [5] + +//! [6] + QTextTableFormat tableFormat; + tableFormat.setAlignment(Qt::AlignHCenter); + tableFormat.setBackground(QColor("#e0e0e0")); + tableFormat.setCellPadding(2); + tableFormat.setCellSpacing(4); +//! [6] //! [7] + QVector constraints; + constraints << QTextLength(QTextLength::PercentageLength, 14) + << QTextLength(QTextLength::PercentageLength, 14) + << QTextLength(QTextLength::PercentageLength, 14) + << QTextLength(QTextLength::PercentageLength, 14) + << QTextLength(QTextLength::PercentageLength, 14) + << QTextLength(QTextLength::PercentageLength, 14) + << QTextLength(QTextLength::PercentageLength, 14); + tableFormat.setColumnWidthConstraints(constraints); +//! [7] + +//! [8] + QTextTable *table = cursor.insertTable(1, 7, tableFormat); +//! [8] + +//! [9] + QTextFrame *frame = cursor.currentFrame(); + QTextFrameFormat frameFormat = frame->frameFormat(); + frameFormat.setBorder(1); + frame->setFrameFormat(frameFormat); +//! [9] + +//! [10] + QTextCharFormat format = cursor.charFormat(); + format.setFontPointSize(fontSize); + + QTextCharFormat boldFormat = format; + boldFormat.setFontWeight(QFont::Bold); + + QTextCharFormat highlightedFormat = boldFormat; + highlightedFormat.setBackground(Qt::yellow); +//! [10] + +//! [11] + for (int weekDay = 1; weekDay <= 7; ++weekDay) { + QTextTableCell cell = table->cellAt(0, weekDay-1); +//! [11] //! [12] + QTextCursor cellCursor = cell.firstCursorPosition(); + cellCursor.insertText(QString("%1").arg(QDate::longDayName(weekDay)), + boldFormat); + } +//! [12] + +//! [13] + table->insertRows(table->rows(), 1); +//! [13] + + while (date.month() == selectedDate.month()) { + int weekDay = date.dayOfWeek(); + QTextTableCell cell = table->cellAt(table->rows()-1, weekDay-1); + QTextCursor cellCursor = cell.firstCursorPosition(); + + if (date == QDate::currentDate()) + cellCursor.insertText(QString("%1").arg(date.day()), highlightedFormat); + else + cellCursor.insertText(QString("%1").arg(date.day()), format); + + date = date.addDays(1); + if (weekDay == 7 && date.month() == selectedDate.month()) + table->insertRows(table->rows(), 1); + } + + cursor.endEditBlock(); +//! [14] + setWindowTitle(tr("Calendar for %1 %2" + ).arg(QDate::longMonthName(selectedDate.month()) + ).arg(selectedDate.year())); +} +//! [14] + +//! [15] +void MainWindow::setFontSize(int size) +{ + fontSize = size; + insertCalendar(); +} +//! [15] + +//! [16] +void MainWindow::setMonth(int month) +{ + selectedDate = QDate(selectedDate.year(), month + 1, selectedDate.day()); + insertCalendar(); +} +//! [16] + +//! [17] +void MainWindow::setYear(QDate date) +{ + selectedDate = QDate(date.year(), selectedDate.month(), selectedDate.day()); + insertCalendar(); +} +//! [17] diff --git a/plugins/calendar_plugin/src/mainwindow.h b/plugins/calendar_plugin/src/mainwindow.h new file mode 100644 index 000000000..737d7c9ba --- /dev/null +++ b/plugins/calendar_plugin/src/mainwindow.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information +** to ensure GNU General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. In addition, as a special +** exception, Nokia gives you certain additional rights. These rights +** are described in the Nokia Qt GPL Exception version 1.3, included in +** the file GPL_EXCEPTION.txt in this package. +** +** Qt for Windows(R) Licensees +** As a special exception, Nokia, as the sole copyright holder for Qt +** Designer, grants users of the Qt/Eclipse Integration plug-in the +** right for the Qt/Eclipse Integration to link to functionality +** provided by Qt Designer and its related libraries. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +//#include +#include + +QT_BEGIN_NAMESPACE +class QTextBrowser; +QT_END_NAMESPACE + +//! [0] +class MainWindow : public QFrame +{ + Q_OBJECT + +public: + MainWindow(QWidget* parent); + +public slots: + void setFontSize(int size); + void setMonth(int month); + void setYear(QDate date); + +private: + void insertCalendar(); + + int fontSize; + QDate selectedDate; + QTextBrowser *editor; +}; +//! [0] + +#endif diff --git a/plugins/patience_plugin/Patience/Ablagestapel.cpp b/plugins/patience_plugin/Patience/Ablagestapel.cpp new file mode 100644 index 000000000..3ff654093 --- /dev/null +++ b/plugins/patience_plugin/Patience/Ablagestapel.cpp @@ -0,0 +1,59 @@ +#include "Ablagestapel.h" +#include "Karte.h" +#include "Proportionen.h" +#include "Scene.h" + +using namespace std; + +Ablagestapel::Ablagestapel(const QPixmap& pixmap, Scene* oparent, QGraphicsItem* gparent) : Basisstapel(pixmap, oparent, gparent) +{ +} + + +Ablagestapel::~Ablagestapel() +{ +} + + +QPointF Ablagestapel::ablageposition() const +{ +QPointF erg; + +// im ablagestapel sollen die karten aufgefaechert abgelegt werden, deshalb YDRIFT hinzufuegen. die position ist relative zum parent grafik objekt +if (kartenliste.size() > 0) erg.setY(boundingRect().height() / ABLAGESTAPEL_YDRIFT_VERHAELTNIS); + +return erg; +} + + +bool Ablagestapel::ablage_moeglich(Karte* karte) const +{ +bool erg = false; + +if (Basisstapel::ablage_moeglich(karte) == true && ((oberste_karte() == 0 && karte->wert() == 13) || (oberste_karte() != 0 && oberste_karte()->farbe() != karte->farbe() && karte->wert() == (oberste_karte()->wert() - 1)))) erg = true; + +if (erg == true && oberste_karte() != 0) +{ +if (karte->farbe() == KARTEN_KREUTZ && oberste_karte()->farbe() == KARTEN_PIK) erg = false; +else if (karte->farbe() == KARTEN_PIK && oberste_karte()->farbe() == KARTEN_KREUTZ) erg = false; +else if (karte->farbe() == KARTEN_HERZ && oberste_karte()->farbe() == KARTEN_KARO) erg = false; +else if (karte->farbe() == KARTEN_KARO && oberste_karte()->farbe() == KARTEN_HERZ) erg = false; +} + +return erg; +} + + +void Ablagestapel::passe_groesse_an(double wert) +{ +if (oberste_karte() != 0) oberste_karte()->nach_hause(); + +Basisstapel::passe_groesse_an(wert); + +for (register int idx = 1; idx < kartenliste.size(); idx++) +{ +kartenliste.at(idx)->setPos(kartenliste.at(idx)->pos().x(), (double) boundingRect().height() / ABLAGESTAPEL_YDRIFT_VERHAELTNIS); + +kartenliste.at(idx)->speichere_zuhause(); +} +} diff --git a/plugins/patience_plugin/Patience/Ablagestapel.h b/plugins/patience_plugin/Patience/Ablagestapel.h new file mode 100644 index 000000000..91735ee47 --- /dev/null +++ b/plugins/patience_plugin/Patience/Ablagestapel.h @@ -0,0 +1,23 @@ +#ifndef ABLAGESTAPEL_H +#define ABLAGESTAPEL_H + +#include "Basisstapel.h" + +class Ablagestapel : public Basisstapel +{ +Q_OBJECT + +public: +Ablagestapel(const QPixmap& pixmap, Scene* oparent, QGraphicsItem* gparent = 0); +virtual ~Ablagestapel(); + +virtual bool ablage_moeglich(Karte*) const; + +public slots: +virtual void passe_groesse_an(double); + +protected: +virtual QPointF ablageposition() const; +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Austeilcostapel.cpp b/plugins/patience_plugin/Patience/Austeilcostapel.cpp new file mode 100644 index 000000000..30d0cb630 --- /dev/null +++ b/plugins/patience_plugin/Patience/Austeilcostapel.cpp @@ -0,0 +1,141 @@ +#include "Austeilcostapel.h" +#include "Karte.h" +#include "Proportionen.h" +#include "Scene.h" + +using namespace std; + +Austeilcostapel::Austeilcostapel(const QPixmap& pixmap, Scene* oparent, QGraphicsItem* gparent) : Basisstapel(pixmap, oparent, gparent), austeilstapel(0), ablagenummer(0) +{ +} + + +Austeilcostapel::~Austeilcostapel() +{ +} + + +void Austeilcostapel::registriere_austeilstapel(Basisstapel* stapel) +{ +austeilstapel = stapel; +} + + +bool Austeilcostapel::ablage_moeglich(Karte * karte) const +{ +bool erg = false; + +if (karte->eigentuemer_stapel()->objectName() == BASISSTAPEL_AUSTEILSTAPEL) erg = true; + +return erg; +} + + +QPointF Austeilcostapel::ablageposition() const +{ +QPointF erg(Basisstapel::ablageposition()); + +// wenn drei karten gezogen werden und die ablagenummer groesser als 0 ist eine drift nach rechts zur position hinzufuegen +if (nur_eine_wird_gezogen() == false && ablagenummer > 0) erg.setX(erg.x() + (boundingRect().width() / AUSTEILCOSTAPEL_XDRIFT_VERHAELTNIS)); + +return erg; +} + + +bool Austeilcostapel::lege_karte_ab(Karte* karte) +{ +bool erg = false; + +// nur, wenn eine ablage ueberhaupt moeglich ist +if (ablage_moeglich(karte) == true) +{ +if (nur_eine_wird_gezogen() == false && oberste_karte() != 0) oberste_karte()->setFlag(QGraphicsItem::ItemIsMovable, false); + +// wenn bereits 3 karten aufgefaechert daliegen +if (nur_eine_wird_gezogen() == false && ablagenummer == 3) +{ +// ablagenummer wieder zuruecksetzen (die nachste karte wird ohne drift eingefuegt) +ablagenummer = 0; + +// die bisher im stapel befindlichen karten sollen ohne drift am stapel liegen +alle_karten_einreihen(); +} + +erg = Basisstapel::lege_karte_ab(karte); + +// wenn drei karten gezogen werden die ablagenummer um 1 erhoehen +if (nur_eine_wird_gezogen() == false) ablagenummer++; +} + +return erg; +} + + +void Austeilcostapel::alle_karten_einreihen() +{ +// von allen karten im stapel die drift entfernen +for (register int idx = 0; idx < kartenliste.size(); idx++) kartenliste.at(idx)->setPos(0, 0); +} + + +void Austeilcostapel::resette_ablagenummer() +{ +// die ablagenummer zuruecksetzen +ablagenummer = 0; + +// von allen karten im stapel die drift entfernen +alle_karten_einreihen(); +} + + +void Austeilcostapel::entferne_karte(Karte* karte) +{ +Basisstapel::entferne_karte(karte); + +if (oberste_karte() != 0) oberste_karte()->setFlag(QGraphicsItem::ItemIsMovable); +} + + +void Austeilcostapel::hilfsanfrage_start(Karte*) +{ +} + + +const QStringList Austeilcostapel::speichere() const +{ +QStringList erg(Basisstapel::speichere()); + +// die ablegenummer speichern +erg.append(QString::number(ablagenummer)); + +return erg; +} + + +bool Austeilcostapel::lade(const QStringList& daten) +{ +bool erg = Basisstapel::lade(daten); + +if (erg == true && daten.size() >= AUSTEILSTAPEL_ANZAHL_SPEICHERELEMENTE) +{ +// die ablagenummer laden +ablagenummer = daten.at(AUSTEILSTAPEL_ABLAGENUMMER_IDX).toInt(); +} + +return erg; +} + + +void Austeilcostapel::passe_groesse_an(double wert) +{ +if (oberste_karte() != 0) oberste_karte()->nach_hause(); + +Basisstapel::passe_groesse_an(wert); + +for (register int idx1 = kartenliste.size() - 1, idx2 = 0; eine_wird_gezogen() == false && idx1 > 0 && idx2 < ablagenummer; idx1--, idx2++) +{ +kartenliste.at(idx1)->setPos(QPointF(boundingRect().width() / AUSTEILCOSTAPEL_XDRIFT_VERHAELTNIS, kartenliste.at(idx1)->pos().y())); + +kartenliste.at(idx1)->speichere_zuhause(); +} +} diff --git a/plugins/patience_plugin/Patience/Austeilcostapel.h b/plugins/patience_plugin/Patience/Austeilcostapel.h new file mode 100644 index 000000000..e62f812c5 --- /dev/null +++ b/plugins/patience_plugin/Patience/Austeilcostapel.h @@ -0,0 +1,37 @@ +#ifndef AUSTEILCOSTAPEL_H +#define AUSTEILCOSTAPEL_H + +#include "Basisstapel.h" + +class Austeilcostapel : public Basisstapel +{ +Q_OBJECT + +public: +Austeilcostapel(const QPixmap& pixmap, Scene* oparent, QGraphicsItem* gparent = 0); +virtual ~Austeilcostapel(); + +virtual void registriere_austeilstapel(Basisstapel*); +virtual bool ablage_moeglich(Karte *) const; +virtual bool lege_karte_ab(Karte*); +virtual void entferne_karte(Karte*); +virtual const QStringList speichere() const; +virtual bool lade(const QStringList&); + +public slots: +virtual void resette_ablagenummer(); +virtual void hilfsanfrage_start(Karte*); +virtual void passe_groesse_an(double); + +private: +Basisstapel *austeilstapel; +bool nur_eine_ziehen; +virtual void alle_karten_einreihen(); + +protected: +int ablagenummer; + +virtual QPointF ablageposition() const; +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Austeilstapel.cpp b/plugins/patience_plugin/Patience/Austeilstapel.cpp new file mode 100644 index 000000000..e2aea3e0c --- /dev/null +++ b/plugins/patience_plugin/Patience/Austeilstapel.cpp @@ -0,0 +1,100 @@ +#include "Austeilstapel.h" +#include "Karte.h" +#include "Proportionen.h" +#include +#include + +using namespace std; + +Austeilstapel::Austeilstapel(const QPixmap& pixmap, Scene* oparent , QGraphicsItem* gparent) : Basisstapel(pixmap, oparent , gparent), costapel(0) +{ +} + + +Austeilstapel::~Austeilstapel() +{ +} + + +void Austeilstapel::registriere_costapel(Basisstapel* costapel_) +{ +costapel = costapel_; +} + + +void Austeilstapel::karte_wurde_aufgedeckt(Karte* karte) +{ +Basisstapel::karte_wurde_aufgedeckt(karte); + +costapel->lege_karte_ab(karte); + +// nur, wenn drei karten gezogen werden +if (nur_eine_wird_gezogen() == false) +{ +// zwei weitere karten ... +for (register int idx = 0; idx < 2 && oberste_karte() != 0; idx++) +{ +Karte *tmp_karte = oberste_karte(); + +// ... auf costapel legen, ... +costapel->lege_karte_ab(tmp_karte); + +// ... und dort aufdecken +tmp_karte->zeige_vorderseite(); +} + +// die neue oberste karte auf costapel beweglich machen +if (costapel->oberste_karte() != 0) costapel->oberste_karte()->setFlag(QGraphicsItem::ItemIsMovable); +} + +normalisiere_zwert(); +} + + +bool Austeilstapel::ablage_moeglich(Karte *karte) const +{ +bool erg = false; + +if (karte->eigentuemer_stapel()->objectName() == BASISSTAPEL_AUSTEILCOSTAPEL && karte->ist_rueckseite() == true) erg = true; + +return erg; +} + + +void Austeilstapel::mousePressEvent(QGraphicsSceneMouseEvent* event) +{ +QGraphicsPixmapItem::mousePressEvent(event); + +if (event->button() == Qt::LeftButton) +{ +if (kartenliste.isEmpty() == true) +{ +if (nur_eine_wird_gezogen() == false) costapel->resette_ablagenummer(); + +while (costapel->karten() > 0) +{ +costapel->oberste_karte()->zeige_rueckseite(); + +lege_karte_ab(costapel->oberste_karte()); +} + +if (kartenliste.isEmpty() == false) emit stapel_durch(); +} + +// sicherstellen, das die scene aktualisiert wird. ist dies ein fehler in QT ??? +scene()->update(); +} +} + + +void Austeilstapel::hilfsanfrage_start(Karte*) +{ +} + + +void Austeilstapel::undo_karten_ablage(Karte* karte) +{ +karte->zeige_rueckseite(); + +Basisstapel::undo_karten_ablage(karte); +} diff --git a/plugins/patience_plugin/Patience/Austeilstapel.h b/plugins/patience_plugin/Patience/Austeilstapel.h new file mode 100644 index 000000000..80550e909 --- /dev/null +++ b/plugins/patience_plugin/Patience/Austeilstapel.h @@ -0,0 +1,28 @@ +#ifndef AUSTEILSTAPEL_H +#define AUSTEILSTAPEL_H + +#include "Basisstapel.h" + +class Austeilstapel : public Basisstapel +{ +Q_OBJECT + +public: +Austeilstapel(const QPixmap& pixmap, Scene* oparent, QGraphicsItem* gparent = 0); +virtual ~Austeilstapel(); + +virtual void registriere_costapel(Basisstapel*); +virtual void karte_wurde_aufgedeckt(Karte*); +virtual bool ablage_moeglich(Karte*) const; +virtual void undo_karten_ablage(Karte*); + +public slots: +virtual void hilfsanfrage_start(Karte*); + +private: +Basisstapel *costapel; + +virtual void mousePressEvent(QGraphicsSceneMouseEvent*); +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Basisstapel.cpp b/plugins/patience_plugin/Patience/Basisstapel.cpp new file mode 100644 index 000000000..3d2b45e65 --- /dev/null +++ b/plugins/patience_plugin/Patience/Basisstapel.cpp @@ -0,0 +1,410 @@ +#include "Basisstapel.h" +#include "Karte.h" +#include "Rahmen.h" +#include "Hilfszeiger.h" +#include "Scene.h" +#include "Proportionen.h" + +using namespace std; + +Basisstapel::Basisstapel(const QPixmap& pixmap, Scene* oparent, QGraphicsItem* gparent) : QObject(oparent), QGraphicsPixmapItem(pixmap, gparent), meine_scene(oparent), nur_eine_ziehen(true), meinrahmen(0), meinhilfszeiger(0), bild(pixmap), bild_skaliert(pixmap), stapelgroesse(pixmap.height()) +{ +// den hilfszeiger erstellen +meinhilfszeiger = new Hilfszeiger(this); +meinhilfszeiger->hide(); +} + + +Basisstapel::~Basisstapel() +{ +} + + +bool Basisstapel::lege_karte_ab(Karte* karte) +{ +bool erg = false; + +if (ablage_moeglich(karte) == true) +{ +erg = true; + +Basisstapel *quelle(karte->eigentuemer_stapel()); + +// die oberste karte,oder den stapel, wenn keine karte vorhanden ist zum parent der karte machen +if (oberste_karte() == 0) karte->setParentItem(this); +else karte->setParentItem(oberste_karte()); + +// die position der karte einstellen +karte->setPos(ablageposition()); + +// die karte aus dem alten stapel entfernen +karte->eigentuemer_stapel()->entferne_karte(karte); + +// der karten den stapel, zu der sie jetzt gehoert mitteilen +karte->setze_meinstapel(this); + +// die rueckkehrposition der karte anpassen +karte->setze_rueckehrkoordinaten(karte->pos()); + +// den zwert der karte setzen +karte->setZValue(zwert()); + +// die karte in die kartenliste einfuegen +kartenliste.append(karte); + +// die kinder karten der karten ebenfalls ablegen +lege_child_karten_ab(karte); + +emit zug(Zug(karte, quelle, this)); + +ablage_erfolgt(); +} + +return erg; +} + + +bool Basisstapel::beruehrungstest(Karte* karte) +{ +return gesamt_rect().intersects(karte->gesamt_rect()); +} + + +bool Basisstapel::ablage_moeglich(Karte* karte) const +{ +bool erg = false; + +if ((oberste_karte() == 0 || (oberste_karte() != 0 && oberste_karte()->ist_vorderseite() == true)) && karte->eigentuemer_stapel() != this) erg = true; + +return erg; +} + + +QPointF Basisstapel::ablageposition() const +{ +return QPointF(0, 0); +} + + +void Basisstapel::initialisiere_karte(Karte* karte) +{ +// die oberste karte,oder den stapel wenn keine karte vorhanden ist zum parent der karte machen +if (oberste_karte() == 0) karte->setParentItem(this); +else karte->setParentItem(oberste_karte()); + +// die position der karte einstellen +karte->setPos(ablageposition()); + +// der karten den stapel, zu der sie jetzt gehoert mitteilen +karte->setze_meinstapel(this); + +// die rueckkehrposition der karte anpassen +karte->setze_rueckehrkoordinaten(karte->pos()); + +// den zwert der karte setzen +karte->setZValue(zwert()); + +// die karte in die kartenliste einfuegen +kartenliste.append(karte); +} + + +int Basisstapel::zwert() const +{ +int erg = zValue(); + +if (kartenliste.isEmpty() == false) erg = kartenliste.last()->zValue(); + +erg++; + +return erg; +} + + +Karte* Basisstapel::oberste_karte() const +{ +Karte* erg = 0; + +if (kartenliste.isEmpty() == false) erg = kartenliste.last(); + +return erg; +} + + +bool Basisstapel::ist_oberste_karte(Karte* karte) +{ +bool erg = false; + +if (oberste_karte() != 0 && oberste_karte() == karte) erg = true; + +return erg; +} + + +void Basisstapel::entferne_karte(Karte* karte) +{ +if (kartenliste.contains(karte) == true) kartenliste.removeAll(karte); +} + + +void Basisstapel::karte_wurde_aufgedeckt(Karte* karte) +{ +emit zug(Zug(karte, this)); +} + + +void Basisstapel::lege_child_karten_ab(Karte* karte) +{ +QList kinder(karte->kinderkarten()); + +for (register int idx = 0; idx < kinder.size(); idx++) +{ +// die position der karte einstellen +kinder.at(idx)->setPos(ablageposition()); + +// die karte aus dem alten stapel entfernen +kinder.at(idx)->eigentuemer_stapel()->entferne_karte(kinder.at(idx)); + +// der karten den stapel, zu der sie jetzt gehoert mitteilen +kinder.at(idx)->setze_meinstapel(this); + +// die rueckkehrposition der karte anpassen +kinder.at(idx)->setze_rueckehrkoordinaten(kinder.at(idx)->pos()); + +// den zwert der karte setzen +kinder.at(idx)->setZValue(zwert()); + +// die karte in die kartenliste einfuegen +kartenliste.append(kinder.at(idx)); +} +} + + +void Basisstapel::erhoehe_zwert() +{ +setZValue(1000); +} + + +void Basisstapel::normalisiere_zwert() +{ +setZValue(0); +} + + +int Basisstapel::karten() const +{ +return kartenliste.size(); +} + + +void Basisstapel::setze_kartenliste_zurueck() +{ +kartenliste.clear(); +} + + +void Basisstapel::ablage_erfolgt() +{ +} + + +QRectF Basisstapel::gesamt_rect() const +{ +QRectF erg(sceneBoundingRect()); + +if (oberste_karte() != 0) erg.setBottomRight(oberste_karte()->sceneBoundingRect().bottomRight()); + +return erg; +} + + +int Basisstapel::ueberlappungs_flaeche(Karte* karte) +{ +QRectF ueberlappung_rect(gesamt_rect().intersect(karte->gesamt_rect())); + +return ueberlappung_rect.width() * ueberlappung_rect.height(); +} + + +bool Basisstapel::nur_eine_wird_gezogen() const +{ +return nur_eine_ziehen; +} + + +void Basisstapel::eine_ziehen() +{ +nur_eine_ziehen = true; +} + + +void Basisstapel::drei_ziehen() +{ +nur_eine_ziehen = false; +} + + +void Basisstapel::registriere_costapel(Basisstapel*) +{ +} + + +void Basisstapel::registriere_austeilstapel(Basisstapel*) +{ +} + + +void Basisstapel::resette_ablagenummer() +{ +} + + +void Basisstapel::alle_karten_einreihen() +{ +} + + +void Basisstapel::registriere_siegkontrolle(Siegkontrolle*) +{ +} + + +void Basisstapel::registriere_nachbar_zielstapel(Basisstapel*, Basisstapel*, Basisstapel*) +{ +} + + +void Basisstapel::registriere_rahmen(Rahmen *rahmen) +{ +meinrahmen = rahmen; +} + + +void Basisstapel::zeige_rahmen() +{ +if (meinrahmen != 0) +{ +QPointF position(scenePos()); + +if (oberste_karte() != 0) position = oberste_karte()->scenePos(); + +meinrahmen->zeige(this, position); +} +} + + +void Basisstapel::hilfsanfrage_start(Karte* karte) +{ +// wenn die ablage der karte moeglich ist +if (ablage_moeglich(karte) == true) +{ +// die position des hilfszeiger setzen + +meinhilfszeiger->setPos(QPointF(boundingRect().width() / 2 - meinhilfszeiger->boundingRect().width() / 2, gesamt_rect().height() + stapelgroesse / BASISSTAPEL_ABSTAND_HILFSZEIGER_VERHAELTNIS)); +meinhilfszeiger->show(); +} +} + + +void Basisstapel::hilfsanfrage_ende() +{ +// den hilfszeiger verstecken +meinhilfszeiger->hide(); +} + + +void Basisstapel::undo_karten_ablage(Karte* karte) +{ +// die oberste karte,oder den stapel, wenn keine karte vorhanden ist zum parent der karte machen +if (oberste_karte() == 0) karte->setParentItem(this); +else karte->setParentItem(oberste_karte()); + +// die position der karte einstellen +karte->setPos(ablageposition()); + +// die karte aus dem alten stapel entfernen +karte->eigentuemer_stapel()->entferne_karte(karte); + +// der karten den stapel, zu der sie jetzt gehoert mitteilen +karte->setze_meinstapel(this); + +// die rueckkehrposition der karte anpassen +karte->setze_rueckehrkoordinaten(karte->pos()); + +// den zwert der karte setzen +karte->setZValue(zwert()); + +// die karte in die kartenliste einfuegen +kartenliste.append(karte); + +// die kinder karten der karten ebenfalls ablegen +lege_child_karten_ab(karte); +} + + +const QStringList Basisstapel::speichere() const +{ +QStringList erg; + +// den namen des stapels als id speichern +erg.append(objectName()); + +// die enthaltenen karten speichern +QString karten; + +for (register int idx = 0; idx < kartenliste.size(); idx++) +{ +if (idx > 0) karten.append(BASISSTAPEL_KARTEN_SPLITTER); + +karten.append(kartenliste.at(idx)->objectName()); +} + +erg.append(karten); + +return erg; +} + + +bool Basisstapel::lade(const QStringList& daten) +{ +bool erg = false; + +if (daten.size() >= BASISSTAPEL_ANZAHL_SPEICHERELEMENTE && daten.first() == objectName()) +{ +erg = true; + +// die enthaltenen karten laden und an den stapel anhaengen +QStringList karten(daten.at(BASISSTAPEL_KARTEN_IDX).split(BASISSTAPEL_KARTEN_SPLITTER, QString::SkipEmptyParts)); + +for (register int idx = 0; idx < karten.size(); idx++) +{ +Karte *karte = meine_scene->suche_karte(karten.at(idx)); + +if (karte == 0) erg = false; +else initialisiere_karte(karte); +} +} + +return erg; +} + + +void Basisstapel::passe_groesse_an(double wert) +{ +stapelgroesse = wert; + +bild_skaliert = bild.scaledToHeight(stapelgroesse, Qt::SmoothTransformation); + +setPixmap(bild_skaliert); + +// auch den hiflszeiger und den rahmen anpassen +if (meinhilfszeiger != 0) meinhilfszeiger->passe_groesse_an(boundingRect()); +if (meinrahmen != 0) meinrahmen->passe_groesse_an(boundingRect()); +} + + +bool Basisstapel::eine_wird_gezogen() +{ +return nur_eine_ziehen; +} diff --git a/plugins/patience_plugin/Patience/Basisstapel.h b/plugins/patience_plugin/Patience/Basisstapel.h new file mode 100644 index 000000000..30a8348bf --- /dev/null +++ b/plugins/patience_plugin/Patience/Basisstapel.h @@ -0,0 +1,85 @@ +#ifndef BASISSTAPEL_H +#define BASISSTAPEL_H + +#include "Zug.h" +#include +#include +#include +#include +#include +#include + +class Karte; +class Siegkontrolle; +class Rahmen; +class Hilfszeiger; +class Scene; + +class Basisstapel : public QObject, public QGraphicsPixmapItem +{ +Q_OBJECT + +public: +Basisstapel(const QPixmap& pixmap, Scene* oparent, QGraphicsItem* gparent = 0); +virtual ~Basisstapel(); + +void registriere_rahmen(Rahmen*); +void zeige_rahmen(); + +virtual bool beruehrungstest(Karte*); +virtual Karte* oberste_karte() const; +virtual bool ist_oberste_karte(Karte*); +virtual void lege_child_karten_ab(Karte*); +virtual void erhoehe_zwert(); +virtual void normalisiere_zwert(); +virtual int karten() const; +virtual void setze_kartenliste_zurueck(); +virtual QRectF gesamt_rect() const; +virtual int ueberlappungs_flaeche(Karte*); +virtual bool nur_eine_wird_gezogen() const; +virtual bool ablage_moeglich(Karte *) const; +virtual bool lege_karte_ab(Karte*); +virtual void undo_karten_ablage(Karte*); +virtual void initialisiere_karte(Karte*); +virtual void karte_wurde_aufgedeckt(Karte*); +virtual void ablage_erfolgt(); +virtual void entferne_karte(Karte*); +virtual void registriere_costapel(Basisstapel*); +virtual void registriere_austeilstapel(Basisstapel*); +virtual void resette_ablagenummer(); +virtual void registriere_siegkontrolle(Siegkontrolle*); +virtual void registriere_nachbar_zielstapel(Basisstapel*, Basisstapel*, Basisstapel*); +virtual const QStringList speichere() const; +virtual bool lade(const QStringList&); + +bool eine_wird_gezogen(); + +public slots: +virtual void eine_ziehen(); +virtual void drei_ziehen(); +virtual void hilfsanfrage_start(Karte*); +virtual void hilfsanfrage_ende(); +virtual void passe_groesse_an(double); + +signals: +void zug(const Zug&); +void stapel_durch(); + +protected: +QList kartenliste; + +virtual QPointF ablageposition() const; +virtual int zwert() const; + +private: +Scene *meine_scene; +bool nur_eine_ziehen; +Rahmen *meinrahmen; +Hilfszeiger *meinhilfszeiger; +QPixmap bild, bild_skaliert; +double stapelgroesse; + +virtual void alle_karten_einreihen(); +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Highscore.cpp b/plugins/patience_plugin/Patience/Highscore.cpp new file mode 100644 index 000000000..fa69fe6b3 --- /dev/null +++ b/plugins/patience_plugin/Patience/Highscore.cpp @@ -0,0 +1,180 @@ +#include "Highscore.h" +#include "Proportionen.h" +#include +#include +#include +#include +#include + +using namespace std; + +Highscore::Highscore(QWidget *parent) : QDialog(parent), einstellungen(0) +{ +setupUi(this); + +tabelle->setRowCount(HIGHSCORE_ZEILEN); + +// die tabelle mit elementen befuellen +for (register int idx1 = 0; idx1 < tabelle->rowCount(); idx1++) +{ +for (register int idx2 = 0; idx2 <= HIGHSCORE_ZEIT_POSITION; idx2++) +{ +QTableWidgetItem *tmp_item = new QTableWidgetItem(); + +tmp_item->setText(HIGHSCORE_LEER); + +tabelle->setItem(idx1, idx2, tmp_item); +} +} +} + + +Highscore::~Highscore() +{ +} + + +bool Highscore::neues_ergebnis(int punkte, long sekunden) +{ +bool erg = false; +int ziel = -1; + +for (register int idx = HIGHSCORE_ZEILEN - 1; idx >= 0; idx--) +{ +int element_sekundenverbrauch = 0, element_ergebnis = 0; + +QStringList tmp_zeit(tabelle->item(idx, HIGHSCORE_ZEIT_POSITION)->text().split(HIGHSCORE_SPLITTER, QString::SkipEmptyParts)); + +// wenn das element an idx leer ist ist es auf jeden fall unterlegen +if (tabelle->item(idx, HIGHSCORE_NAME_POSITION)->text() == HIGHSCORE_LEER || tabelle->item(idx, HIGHSCORE_PUNKTE_POSITION)->text() == HIGHSCORE_LEER || tabelle->item(idx, HIGHSCORE_ZEIT_POSITION)->text() == HIGHSCORE_LEER) +{ +ziel = idx; +} + +// ansonsten +else if (tmp_zeit.size() == 3) +{ +// die bewertung des tabellenelements an idx berechnen. je mehr mienen und felder, je mehr punkte +element_ergebnis = tabelle->item(idx, HIGHSCORE_PUNKTE_POSITION)->text().toInt(); + +// den sekundenverbrauch fuer des tabellenelements an idx berechnen +element_sekundenverbrauch = (tmp_zeit.at(0).toInt() * 3600) + (tmp_zeit.at(1).toInt() * 60) + tmp_zeit.at(2).toInt(); +} + +// wenn das neue ergebnis mehr punkte hat als das tabellenelement oder gleich viel punkte wie das tabellenelement enthaelt, aber weniger zeit verbraucht hat ist es ueberlegen +if (punkte > element_ergebnis || (punkte == element_ergebnis && sekunden < element_sekundenverbrauch)) ziel = idx; +} + +// wenn das neue element in die tabelle darf +if (ziel >= 0 && ziel < tabelle->rowCount()) +{ +// eine neue reihe an ziel in die tabelle einfuegen ... +tabelle->insertRow(ziel); + +// ... und mit elementen befuellen +tabelle->setItem(ziel, HIGHSCORE_NAME_POSITION, new QTableWidgetItem()); +tabelle->setItem(ziel, HIGHSCORE_PUNKTE_POSITION, new QTableWidgetItem()); +tabelle->setItem(ziel, HIGHSCORE_ZEIT_POSITION, new QTableWidgetItem()); + +// der letzte muss die tabelle verlassen +tabelle->removeRow(tabelle->rowCount() - 1); + +erg = true; +bool ok; + +// den namen des nutzers abfragen +QString name_vorbereitung(QDir::home().dirName()); + +// wenn name_vorbereitung nicht leer ist +if (name_vorbereitung.isEmpty() == false) +{ +QChar erstes_zeichen = name_vorbereitung.at(0); + +if (erstes_zeichen.isLower() == true) name_vorbereitung[0] = erstes_zeichen.toUpper(); +} + +QString name = QInputDialog::getText(parentWidget(), tr("Patience"), tr("You got a Highscore !"), QLineEdit::Normal, name_vorbereitung, &ok); + +// wenn kein nutzername eingegeben wurde den namen auf unbekannt setzen +if (ok == false || name.isEmpty() == true) name = tr("Unknown"); + +// wenn der name LEER entspricht den namen ebenfalls auf unbekannt setzen +if (name == HIGHSCORE_LEER) name = tr("Unknown"); + +int stunden = sekunden / 3600; + +int minuten = (sekunden - (stunden * 3600)) / 60; + +int sekunden_ = sekunden - (minuten * 60) - (stunden * 3600); + +QString stunden_string = QString::number(stunden); +QString minuten_string = QString::number(minuten); +QString sekunden_string = QString::number(sekunden_); + +if (stunden < 10) stunden_string.prepend('0'); +if (minuten < 10) minuten_string.prepend('0'); +if (sekunden_ < 10) sekunden_string.prepend('0'); + +tabelle->item(ziel, HIGHSCORE_NAME_POSITION)->setText(name); +tabelle->item(ziel, HIGHSCORE_PUNKTE_POSITION)->setText(QString::number(punkte)); +tabelle->item(ziel, HIGHSCORE_ZEIT_POSITION)->setText(stunden_string + HIGHSCORE_SPLITTER + minuten_string + HIGHSCORE_SPLITTER + sekunden_string); + +// die highscoretabelle anzeigen +show(); +} + +return erg; +} + + +void Highscore::registriere_einstellungen(QSettings* einstellungen_) +{ +einstellungen = einstellungen_; +} + + +void Highscore::einstellungen_laden() +{ +if (einstellungen != 0) +{ +// die breite der spalten laden +tabelle->setColumnWidth(HIGHSCORE_NAME_POSITION, einstellungen->value(QString("tabelle/spalte_") + QString::number(HIGHSCORE_NAME_POSITION), HIGHSCORE_NAME_SPALTE_STANDARTGROESSE).toInt()); +tabelle->setColumnWidth(HIGHSCORE_PUNKTE_POSITION, einstellungen->value(QString("tabelle/spalte_") + QString::number(HIGHSCORE_PUNKTE_POSITION), tabelle->columnWidth(HIGHSCORE_PUNKTE_POSITION)).toInt()); +tabelle->setColumnWidth(HIGHSCORE_ZEIT_POSITION, einstellungen->value(QString("tabelle/spalte_") + QString::number(HIGHSCORE_ZEIT_POSITION), tabelle->columnWidth(HIGHSCORE_ZEIT_POSITION)).toInt()); +} + +// den inhalt der tabelle laden +for (register int idx = 0; idx < tabelle->rowCount() && einstellungen != 0; idx++) +{ +// den namen laden +tabelle->item(idx, HIGHSCORE_NAME_POSITION)->setText(einstellungen->value(QString("highscore/") + QString::number(idx) + QString("name"), HIGHSCORE_LEER).toString()); + +// die punkte laden +tabelle->item(idx, HIGHSCORE_PUNKTE_POSITION)->setText(einstellungen->value(QString("highscore/") + QString::number(idx) + QString("breite"), HIGHSCORE_LEER).toString()); + +// die zeit laden +tabelle->item(idx, HIGHSCORE_ZEIT_POSITION)->setText(einstellungen->value(QString("highscore/") + QString::number(idx) + QString("hoehe"), HIGHSCORE_LEER).toString()); +} +} + + +void Highscore::einstellungen_speichern() +{ +// die breite der spalten speichern +einstellungen->setValue(QString("tabelle/spalte_") + QString::number(HIGHSCORE_NAME_POSITION), tabelle->columnWidth(HIGHSCORE_NAME_POSITION)); +einstellungen->setValue(QString("tabelle/spalte_") + QString::number(HIGHSCORE_PUNKTE_POSITION), tabelle->columnWidth(HIGHSCORE_PUNKTE_POSITION)); +einstellungen->setValue(QString("tabelle/spalte_") + QString::number(HIGHSCORE_ZEIT_POSITION), tabelle->columnWidth(HIGHSCORE_ZEIT_POSITION)); + +// den inhalt der tabelle speichern +for (register int idx = 0; idx < tabelle->rowCount() && einstellungen != 0; idx++) +{ +// den namen speichern +einstellungen->setValue(QString("highscore/") + QString::number(idx) + QString("name"), tabelle->item(idx, HIGHSCORE_NAME_POSITION)->text()); + +// die punkte speichern +einstellungen->setValue(QString("highscore/") + QString::number(idx) + QString("breite"), tabelle->item(idx, HIGHSCORE_PUNKTE_POSITION)->text()); + +// die zeit speichern +einstellungen->setValue(QString("highscore/") + QString::number(idx) + QString("hoehe"), tabelle->item(idx, HIGHSCORE_ZEIT_POSITION)->text()); +} +} diff --git a/plugins/patience_plugin/Patience/Highscore.h b/plugins/patience_plugin/Patience/Highscore.h new file mode 100644 index 000000000..3d7084596 --- /dev/null +++ b/plugins/patience_plugin/Patience/Highscore.h @@ -0,0 +1,27 @@ +#ifndef HIGHSCORE_H +#define HIGHSCORE_H + +#include +#include +#include "ui_Highscore.h" + +class QSettings; + +class Highscore : public QDialog, private Ui::Highscore +{ +Q_OBJECT + +public: +Highscore(QWidget *parent); +virtual ~Highscore(); + +bool neues_ergebnis(int, long); +void registriere_einstellungen(QSettings*); +void einstellungen_laden(); +void einstellungen_speichern(); + +private: +QSettings *einstellungen; +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Highscore.ui b/plugins/patience_plugin/Patience/Highscore.ui new file mode 100644 index 000000000..c499f9ae0 --- /dev/null +++ b/plugins/patience_plugin/Patience/Highscore.ui @@ -0,0 +1,111 @@ + + + Highscore + + + Qt::WindowModal + + + + 0 + 0 + 528 + 300 + + + + + 528 + 300 + + + + Patience - Highscore + + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SelectRows + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + true + + + + Name + + + + + Points + + + + + Time + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Ok + + + false + + + true + + + + + + + + + + + ok_button + clicked() + Highscore + accept() + + + 485 + 275 + + + 356 + 263 + + + + + diff --git a/plugins/patience_plugin/Patience/Hilfszeiger.cpp b/plugins/patience_plugin/Patience/Hilfszeiger.cpp new file mode 100644 index 000000000..6353f3038 --- /dev/null +++ b/plugins/patience_plugin/Patience/Hilfszeiger.cpp @@ -0,0 +1,49 @@ +#include "Hilfszeiger.h" +#include "Basisstapel.h" +#include "Proportionen.h" +#include + +using namespace std; + +Hilfszeiger::Hilfszeiger(Basisstapel *parent) : QObject(parent), QGraphicsItem(parent), meinstapel(parent), breite(parent->boundingRect().width() / HILFSZEIGER_BREITE_VERHAELTNIS), hoehe(parent->boundingRect().height() / HILFSZEIGER_HOEHE_VERHAELTNIS), dicke(parent->boundingRect().height() / HILFSZEIGER_DICKE_VERHAELTNIS) +{ +setZValue(1000); +} + + +Hilfszeiger::~Hilfszeiger() +{ +} + + +void Hilfszeiger::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) +{ +painter->setPen(Qt::darkBlue); +painter->setBrush(Qt::darkBlue); + +QPen stift(painter->pen()); +stift.setWidth(dicke); +painter->setPen(stift); + +painter->drawLine(breite / 2, 0 + (dicke / 2), breite / 2, hoehe - (dicke / 2)); +painter->drawLine(breite / 2, 0 + (dicke / 2), dicke / 2, (hoehe / 2)); +painter->drawLine(breite / 2, 0 + (dicke / 2), breite - (dicke / 2), (hoehe / 2)); +} + + +QRectF Hilfszeiger::boundingRect() const +{ +return QRectF(0, 0, breite, hoehe); +} + + +void Hilfszeiger::passe_groesse_an(const QRectF& wert) +{ +prepareGeometryChange(); + +breite = wert.width() / HILFSZEIGER_BREITE_VERHAELTNIS; +hoehe = wert.height() / HILFSZEIGER_HOEHE_VERHAELTNIS; +dicke = wert.height() / HILFSZEIGER_DICKE_VERHAELTNIS; + +update(); +} diff --git a/plugins/patience_plugin/Patience/Hilfszeiger.h b/plugins/patience_plugin/Patience/Hilfszeiger.h new file mode 100644 index 000000000..3c14206be --- /dev/null +++ b/plugins/patience_plugin/Patience/Hilfszeiger.h @@ -0,0 +1,27 @@ +#ifndef HILFSZEIGER_H +#define HILFSZEIGER_H + +#include +#include + +class Basisstapel; + +class Hilfszeiger : public QObject, public QGraphicsItem +{ +Q_OBJECT + +public: +Hilfszeiger(Basisstapel *parent); +virtual ~Hilfszeiger(); + +virtual QRectF boundingRect() const; +void passe_groesse_an(const QRectF&); + +private: +Basisstapel *meinstapel; +double breite, hoehe, dicke; + +virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Karte.cpp b/plugins/patience_plugin/Patience/Karte.cpp new file mode 100644 index 000000000..af769dd7d --- /dev/null +++ b/plugins/patience_plugin/Patience/Karte.cpp @@ -0,0 +1,424 @@ +#include "Karte.h" +#include "Basisstapel.h" +#include "Proportionen.h" +#include "Scene.h" +#include +#include + +using namespace std; + +Karte::Karte(const QPixmap& vorderseite, const QPixmap& hinterseite, Scene *oparent, QGraphicsItem *gparent) : QObject(oparent), QGraphicsPixmapItem(hinterseite, gparent), vorne(vorderseite), hinten(hinterseite), vorne_skaliert(vorderseite), hinten_skaliert(hinterseite), Wert(0), vorderseite_oben(false), rahmen_anzeigen(true), double_click_sperre(false), gegrabbt(false), scene(oparent), kreutzstapel(0), pikstapel(0), herzstapel(0), karostapel(0), kartengroesse(vorderseite.height()) +{ +setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton); +} + + +Karte::~Karte() +{ +} + + +void Karte::setze_farbe(const QString& farbe_) +{ +Farbe = farbe_; +} + + +const QString& Karte::farbe() const +{ +return Farbe; +} + + +void Karte::setze_wert(int wert_) +{ +Wert = wert_; +} + + +int Karte::wert() const +{ +return Wert; +} + + +void Karte::zeige_vorderseite() +{ +vorderseite_oben = true; + +setPixmap(vorne_skaliert); + +Meinstapel->karte_wurde_aufgedeckt(this); + +// wenn es sich beim stapel nicht um austeilcostapel handelt die karte beweglich machen +if (Meinstapel->objectName() != BASISSTAPEL_AUSTEILCOSTAPEL) setFlag(QGraphicsItem::ItemIsMovable, true); + +// ansonsten die karte unbeweglich machen. dies muss spaeter, im mouse release event wieder rueckgaengig gemacht werden +else setFlag(QGraphicsItem::ItemIsMovable, false); +} + + +void Karte::zeige_rueckseite() +{ +vorderseite_oben = false; + +setPixmap(hinten_skaliert); + +setFlag(QGraphicsItem::ItemIsMovable, false); +} + + +bool Karte::ist_vorderseite() const +{ +return vorderseite_oben; +} + + +bool Karte::ist_rueckseite() const +{ +return !vorderseite_oben; +} + + +void Karte::registriere_stapel(const QList& stapelliste_) +{ +stapelliste = stapelliste_; +} + + +void Karte::setze_meinstapel(Basisstapel *meinstapel_) +{ +Meinstapel = meinstapel_; +} + + +void Karte::setze_rueckehrkoordinaten(const QPointF& punkt) +{ +Rueckkehrkoordinaten = punkt; +} + + +// diese methode ist fuer das ablegen der karte auf dem passenden zielstapel zustaendig, sofern moeglich +void Karte::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) +{ +if (event->buttons() == Qt::LeftButton && gegrabbt == false && flags() == QGraphicsItem::ItemIsMovable && event->button() == Qt::LeftButton && ist_vorderseite() == true && Meinstapel->ist_oberste_karte(this) == true && hat_kinderkarten() == false && Meinstapel->objectName().contains(BASISSTAPEL_ZIELSTAPEL) == false) +{ +// nach einem double click soll die karte bis zum naechsten release gegen bewegungen geschuetzt werden +double_click_sperre = true; + +// die karte soll nicht mehr über die anderen erhoeht werden +Meinstapel->normalisiere_zwert(); + +if (farbe() == KARTEN_KREUTZ) kreutzstapel->lege_karte_ab(this); +else if (farbe() == KARTEN_PIK) pikstapel->lege_karte_ab(this); +else if (farbe() == KARTEN_HERZ) herzstapel->lege_karte_ab(this); +else if (farbe() == KARTEN_KARO) karostapel->lege_karte_ab(this); + +// sicherstellen, das die scene aktualisiert wird +scene->update(); +} +} + + +void Karte::mousePressEvent(QGraphicsSceneMouseEvent* event) +{ +// linke maustaste +if (event->button() == Qt::LeftButton && gegrabbt == false) +{ +gegrabbt = true; + +// die karte soll ueber den anderen erhoeht angezeigt werden +Meinstapel->erhoehe_zwert(); + +if (ist_vorderseite() == true) QGraphicsPixmapItem::mousePressEvent(event); + +// wenn diese karte die oberste karte ist und noch nicht die vorderseite gezeigt wird die vorderseite zeigen +else if (Meinstapel->ist_oberste_karte(this) == true && ist_vorderseite() == false) zeige_vorderseite(); +} + +// wenn die rechte maustaste gedrueckt wurde und die karte beweglich, jedoch nicht gegrabbt ist eine hilfsanfrage starten +else if (event->button() == Qt::RightButton && flags() == QGraphicsItem::ItemIsMovable && gegrabbt == false) +{ +gegrabbt = true; + +emit hilfsanfrage_start(this); +} +} + + +void Karte::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) +{ +// die karte soll nicht mehr über die anderen erhoeht werden +Meinstapel->normalisiere_zwert(); + +QGraphicsPixmapItem::mouseReleaseEvent(event); + +// nur wenn keine weitere maustaste mehr gehalten wird +if (event->buttons() == Qt::NoButton) +{ +// wenn double klick sperre nicht aktive ist +if (double_click_sperre == false) +{ +Basisstapel *ziel = suche_ziel(); + +if (ziel == 0) setPos(Rueckkehrkoordinaten); + +else if (ziel != 0 && ziel->lege_karte_ab(this) == false) setPos(Rueckkehrkoordinaten); + +else setPos(Rueckkehrkoordinaten); + +// die ist noetig, weil beim aufdecken auf dem austeilcostapel die karte unbeweglich gemacht wurde. dies ist jedoch nur zulaessig, wenn nur eine karte gezogen wird. wenn 3 gezogen werden, erfolgt die freigabe aus dem austeilstapel heraus +if (Meinstapel->objectName() == BASISSTAPEL_AUSTEILCOSTAPEL && Meinstapel->nur_eine_wird_gezogen() == true) setFlag(QGraphicsItem::ItemIsMovable, true); +} + +// wenn double klick sperre doch aktive ist +else setPos(Rueckkehrkoordinaten); +} + +// wenn doch noch eine weitere maustaste gehalten wird +else setPos(Rueckkehrkoordinaten); + +// den rahmen wieder verstecken +emit rahmen_verstecken(); + +// den hilfs pfeil wieder ausblenden +emit hilfsanfrage_ende(); + +// die double click sperre wieder aufheben, damit die karte zukuenftig wieder beweglich ist +double_click_sperre = false; + +gegrabbt = false; + +// sicherstellen, das das element nicht laenger gegrabbt ist !!! +ungrabMouse(); +} + + +Basisstapel* Karte::eigentuemer_stapel() +{ +return Meinstapel; +} + + +void Karte::registriere_zielstapel(Basisstapel* kreutzstapel_, Basisstapel* pikstapel_, Basisstapel* herzstapel_, Basisstapel* karostapel_) +{ +kreutzstapel = kreutzstapel_; +pikstapel = pikstapel_; +herzstapel = herzstapel_; +karostapel = karostapel_; +} + + +void Karte::setze_kartenbilder(const QPixmap& vorne_, const QPixmap& hinten_) +{ +vorne = vorne_; +hinten = hinten_; + +passe_groesse_an(kartengroesse); +} + + +Basisstapel* Karte::suche_ziel() +{ +QList moegliche_ziele(stapelliste); + +Basisstapel *erg = 0; + +// den eigenen stapel aus moegliche_ziele entfernen +moegliche_ziele.removeAll(Meinstapel); + +// alle unmoeglichen stapel entfernen +for (register int idx = 0; idx < moegliche_ziele.size(); idx++) if (moegliche_ziele.at(idx)->ablage_moeglich(this) == false && (moegliche_ziele.at(idx)->objectName().contains("ziel") == false || (moegliche_ziele.at(idx)->objectName().contains("ziel") == true && kreutzstapel->ablage_moeglich(this) == false && pikstapel->ablage_moeglich(this) == false && herzstapel->ablage_moeglich(this) == false && karostapel->ablage_moeglich(this) == false))) +{ +moegliche_ziele.removeAt(idx); + +idx--; +} + +// wenn das ziel noch nicht eindeutig ist die groesste ueberlappung finden +if (moegliche_ziele.size() > 1) +{ +// das ziel mit der groessten ueberlappenden flaeche finden +Basisstapel *ziel = 0; +int groesste_ueberlappung = 0; + +for (register int idx = 0; idx < moegliche_ziele.size(); idx++) +{ +int ueberlappung = moegliche_ziele.at(idx)->ueberlappungs_flaeche(this); + +if (ueberlappung > groesste_ueberlappung) +{ +groesste_ueberlappung = ueberlappung; + +ziel = moegliche_ziele.at(idx); +} +} + +erg = ziel; +} + +else if (moegliche_ziele.size() == 1) erg = moegliche_ziele.first(); + +// besteht mit dem sieger eine beruehrung ? +if (erg != 0 && erg->beruehrungstest(this) == false) erg = 0; + +// wird ein zielstapel angepeilt? +if (erg != 0 && erg->objectName().contains("ziel") == true) +{ +if (farbe() == KARTEN_KREUTZ && kreutzstapel->ablage_moeglich(this) == true) erg = kreutzstapel; +else if (farbe() == KARTEN_PIK && pikstapel->ablage_moeglich(this) == true) erg = pikstapel; +else if (farbe() == KARTEN_HERZ && herzstapel->ablage_moeglich(this) == true) erg = herzstapel; +else if (farbe() == KARTEN_KARO && karostapel->ablage_moeglich(this) == true) erg = karostapel; +else erg = 0; +} + +return erg; +} + + +void Karte::mouseMoveEvent(QGraphicsSceneMouseEvent* event) +{ +if (gegrabbt == true) +{ +if (double_click_sperre == false && event->buttons() == Qt::LeftButton) QGraphicsPixmapItem::mouseMoveEvent(event); + +else setPos(Rueckkehrkoordinaten); + +if (rahmen_anzeigen == true) +{ +Basisstapel *ziel = suche_ziel(); + +if (ziel != 0) ziel->zeige_rahmen(); + +else +{ +emit rahmen_verstecken(); +} +} +} +} + + +void Karte::sichtbarkeit_rahmen(bool wert) +{ +rahmen_anzeigen = wert; +} + + +QRectF Karte::gesamt_rect() +{ +QRectF erg(sceneBoundingRect()); + +Karte *testkarte = unterste_karte(); + +erg.setBottomRight(testkarte->sceneBoundingRect().bottomRight()); + +return erg; +} + + +Karte* Karte::unterste_karte() +{ +Karte *erg = this; + +if (hat_kinderkarten() == true) erg = kinderkarten().last(); + +return erg; +} + + +// wenn die karte child items besitzt, die nicht vom typ karte sind muessen diese hier herausgefiltert werden !!! +bool Karte::hat_kinderkarten() const +{ +bool erg = false; + +if (childItems().size() > 1) +{ +qDebug() << tr("The Card ") << objectName() << tr(" have more than one Child Card"); + +exit(1); +} + +if (childItems().size() > 0) erg = true; + +return erg; +} + + +// wenn die karte child items besitzt, die nicht vom typ karte sind muessen diese hier herausgefiltert werden !!! +QList Karte::kinderkarten() +{ +QList erg; + +if (childItems().size() > 1) +{ +qDebug() << tr("The Card ") << objectName() << tr(" have more than one Child Card"); + +exit(1); +} + +if (childItems().isEmpty() == false) erg.append((Karte*) childItems().first()); + +if (erg.isEmpty() == false) erg.append(erg.first()->kinderkarten()); + +return erg; +} + + +const QStringList Karte::speichere() const +{ +QStringList erg; + +// die karten id speichern +erg.append(objectName()); + +// die kartenseite speichern +erg.append(QString::number(ist_vorderseite())); + +return erg; +} + + +bool Karte::lade(const QStringList& daten) +{ +bool erg = false; + +if (daten.size() == KARTE_ANZAHL_SPEICHERELEMENTE && daten.first() == objectName()) +{ +erg = true; + +if (daten.at(KARTE_IST_VORNE_IDX).toInt() == 1) zeige_vorderseite(); + +else zeige_rueckseite(); +} + +return erg; +} + + +void Karte::passe_groesse_an(double wert) +{ +kartengroesse = wert; + +vorne_skaliert = vorne.scaledToHeight(kartengroesse, Qt::SmoothTransformation); +hinten_skaliert = hinten.scaledToHeight(kartengroesse, Qt::SmoothTransformation); + +if (ist_vorderseite() == true) setPixmap(vorne_skaliert); +else setPixmap(hinten_skaliert); +} + + +void Karte::nach_hause() +{ +setPos(Rueckkehrkoordinaten); + +emit rahmen_verstecken(); + +if (scene->mouseGrabberItem() == this) ungrabMouse(); +} + + +void Karte::speichere_zuhause() +{ +Rueckkehrkoordinaten = pos(); +} diff --git a/plugins/patience_plugin/Patience/Karte.h b/plugins/patience_plugin/Patience/Karte.h new file mode 100644 index 000000000..13535240e --- /dev/null +++ b/plugins/patience_plugin/Patience/Karte.h @@ -0,0 +1,74 @@ +#ifndef KARTE_H +#define KARTE_H + +#include +#include +#include +#include +#include +#include +#include + +class Scene; +class Basisstapel; + +class Karte : public QObject, public QGraphicsPixmapItem +{ +Q_OBJECT + +public: +Karte(const QPixmap& vorderseite, const QPixmap& hinterseite, Scene *oparent, QGraphicsItem *gparent = 0); +virtual ~Karte(); + +void setze_farbe(const QString&); +const QString& farbe() const; +void setze_wert(int); +int wert() const; +bool ist_vorderseite() const; +bool ist_rueckseite() const; +void registriere_stapel(const QList& stapelliste_); +void setze_meinstapel(Basisstapel *meinstapel_); +void setze_rueckehrkoordinaten(const QPointF&); +void registriere_zielstapel(Basisstapel* kreutzstapel_, Basisstapel* pikstapel_, Basisstapel* herzstapel_, Basisstapel* karoherzstapel_); +Basisstapel* eigentuemer_stapel(); +void setze_kartenbilder(const QPixmap&, const QPixmap&); +Basisstapel* suche_ziel(); +QList kinderkarten(); +QRectF gesamt_rect(); +Karte* unterste_karte(); +bool hat_kinderkarten() const; +const QStringList speichere() const; +bool lade(const QStringList&); +void nach_hause(); +void speichere_zuhause(); + +public slots: +void zeige_vorderseite(); +void zeige_rueckseite(); +void sichtbarkeit_rahmen(bool); +void passe_groesse_an(double); + +signals: +void rahmen_verstecken(); +void hilfsanfrage_start(Karte*); +void hilfsanfrage_ende(); + +private: +QPixmap vorne, hinten, vorne_skaliert, hinten_skaliert; +QString Farbe; +int Wert; +bool vorderseite_oben, rahmen_anzeigen, double_click_sperre, gegrabbt; +Scene *scene; +QList stapelliste; +Basisstapel *Meinstapel; +QPointF Rueckkehrkoordinaten; +Basisstapel *kreutzstapel, *pikstapel, *herzstapel, *karostapel; +double kartengroesse; + +virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); +virtual void mousePressEvent(QGraphicsSceneMouseEvent*); +virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent*); +virtual void mouseMoveEvent(QGraphicsSceneMouseEvent*); +}; + +#endif diff --git a/plugins/patience_plugin/Patience/MainWindow.cpp b/plugins/patience_plugin/Patience/MainWindow.cpp new file mode 100644 index 000000000..aef7907cd --- /dev/null +++ b/plugins/patience_plugin/Patience/MainWindow.cpp @@ -0,0 +1,350 @@ +#include "MainWindow.h" +#include "Scene.h" +#include "Highscore.h" +#include "Speichern_frage.h" +#include +#include +#include +#include +#include +#include + +using namespace std; + +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) +{ +// die benutzeroberflaeche aufbauen +setupUi(this); + +// osx spezifische einstellungen vornehmen +#ifdef Q_WS_MAC + +setUnifiedTitleAndToolBarOnMac(true); + +#endif + +// einstellungen erstellen +einstellungen = new QSettings("konarski-wuppertal", "Patience", this); + +// es ist noetigm das einige einstellungen vorab geladen werden, damit sie von vorne herein verfuegbar sind !!! +// den kartentyp laden +QString kartentyp(einstellungen->value("deckblatt", "french").toString()); + +// sicherstellen, das der geladene kartentyp gueltig ist +if (kartentyp != "french" && kartentyp != "german") kartentyp = "french"; + +// action_french und action_german zu einer gruppe verbinden +QActionGroup *deckblatt_gruppe = new QActionGroup(this); +deckblatt_gruppe->addAction(action_french); +deckblatt_gruppe->addAction(action_german); + +// die action gruppe initialisieren +if (kartentyp == "french") action_french->setChecked(true); +else action_german->setChecked(true); + +// action_eine_ziehen und action_drei_ziehen zu einer gruppe verbinden ... +QActionGroup *spieltyp_gruppe = new QActionGroup(this); +spieltyp_gruppe->addAction(action_eine_ziehen); +spieltyp_gruppe->addAction(action_drei_ziehen); + +// ... und initialisieren +action_eine_ziehen->setChecked(true); + +// action_speichern und action_nicht_speichern zu eoner gruppe verbinden +QActionGroup *speichern_gruppe = new QActionGroup(this); +speichern_gruppe->addAction(action_speichern); +speichern_gruppe->addAction(action_nicht_speichern); + +// scene erstellen ... +scene = new Scene(kartentyp, viewer); +scene->setObjectName("scene"); +scene->setSceneRect(0, 0, 795, 595); +scene->registriere_einstellungen(einstellungen); + +// ... und in viewer registrieren +viewer->setScene(scene); + +// siegmeldung erzeugen +siegmeldung = new QMessageBox(this); +siegmeldung->setWindowModality(Qt::WindowModal); +siegmeldung->setWindowTitle(tr("Patience - You won !")); +siegmeldung->setText(tr("You won, but you don't reach a highscore.")); +siegmeldung->addButton(QMessageBox::Ok); + +sicherheitsfrage = new QMessageBox(this); +sicherheitsfrage->setWindowModality(Qt::WindowModal); +sicherheitsfrage->setWindowTitle(tr("Patience - Start new game ?")); +sicherheitsfrage->setText(tr("Start a new Game and break the current Game ?")); +sicherheitsfrage->addButton(QMessageBox::Yes); +sicherheitsfrage->addButton(QMessageBox::No); + +// punktelabel und zeitlabel erzeugen ... +punktelabel = new QLabel(this); +zeitlabel = new QLabel(this); + +// ... und der statusleiste als permanentes widget hinzufuegen +statusBar()->addPermanentWidget(punktelabel); +statusBar()->addPermanentWidget(zeitlabel); + +// highscore erzeugen +highscore = new Highscore(this); +highscore->registriere_einstellungen(einstellungen); + +// speichern_frage erstellen +speichern_frage = new Speichern_frage(this); +speichern_frage->setObjectName("speichern_frage"); + +// signal - slot verbindungen +// das starten neuer spiele ermoeglichen +connect(action_neues_spiel, SIGNAL(triggered(bool)), this, SLOT(neues_spiel())); + +// action_about ermoeglichen +connect(action_about, SIGNAL(triggered(bool)), this, SLOT(about())); + +// action_about_qt ermoeglichen +connect(action_about_qt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); + +// das anzeigen der siegmeldung ermoeglichen +connect(scene, SIGNAL(gewonnen(int, long)), this, SLOT(gewonnen(int, long))); + +// das umschalten des deckblattes waehrend des spiels ermoeglichen +connect(action_french, SIGNAL(triggered(bool)), scene, SLOT(lade_franzoesisches_deckblatt())); +connect(action_german, SIGNAL(triggered(bool)), scene, SLOT(lade_deutsches_deckblatt())); + +// das aktualisieren der punkte ermoeglichen +connect(scene, SIGNAL(neue_punktzahl(int)), this, SLOT(aktualisiere_punktelabel(int))); + +// das aktualisieren der spielzeit ermoeglichen +connect(scene, SIGNAL(verstrichene_sekunden(long)), this, SLOT(aktualisiere_spielzeit(long))); + +// das anzeigen der highscore ermoeglichen +connect(action_highscore, SIGNAL(triggered(bool)), highscore, SLOT(show())); + +// das umschalten des spieltyps ermoeglichen +connect(action_eine_ziehen, SIGNAL(triggered(bool)), this, SLOT(eine_ziehen())); +connect(action_drei_ziehen, SIGNAL(triggered(bool)), this, SLOT(drei_ziehen())); + +// das steuern der rahmen sichtbarkeit ermoeglichen +connect(action_rahmen, SIGNAL(triggered(bool)), scene, SIGNAL(rahmen_anzeigen(bool))); + +// action_schliessen ermoeglichen +connect(action_beenden, SIGNAL(triggered(bool)), this, SLOT(close())); + +// action_undo ermoeglichen +connect(action_undo, SIGNAL(triggered(bool)), scene, SLOT(rueckgaengig())); + +// steuerung der verfuegbarkeit von action_undo ermoeglichen +connect(scene, SIGNAL(undo_verfuegbar(bool)), action_undo, SLOT(setEnabled(bool))); + +// action_fragen und speichern_frage verbinden +connect(action_fragen, SIGNAL(toggled(bool)), speichern_frage, SLOT(verbindung_merken(bool))); +connect(speichern_frage, SIGNAL(verbindung_merk_status(bool)), action_fragen, SLOT(setChecked(bool))); + +// den speicher status mit action_speichern und action_nicht_speichern verbinden +connect(speichern_frage, SIGNAL(wird_gespeichert(bool)), action_speichern, SLOT(setChecked(bool))); +connect(speichern_frage, SIGNAL(wird_nicht_gespeichert(bool)), action_nicht_speichern, SLOT(setChecked(bool))); +connect(action_speichern, SIGNAL(toggled(bool)), speichern_frage, SLOT(setze_speichern(bool))); + +// die restlichen einstellungen laden +restliche_einstellungen_laden(); +} + + +MainWindow::~MainWindow() +{ +// die einstellungen speichern +einstellungen_speichern(); +} + + +void MainWindow::neues_spiel() +{ +// wenn kein spiel laueft, einfach eins starten ... +if (scene->laufendes_spiel() == false) scene->neues_spiel(); + +// ansonsten erst nach einer sicherheitsfrage ein neues spiel starten +else +{ +QAbstractButton *sicherheitsfrage_ja = sicherheitsfrage->button(QMessageBox::Yes); + +sicherheitsfrage->exec(); + +if (sicherheitsfrage->clickedButton() == sicherheitsfrage_ja) scene->neues_spiel(); +} +} + + +void MainWindow::about() +{ +QMessageBox::about(this, tr("About Patience"), tr("Patience Version " VERSION " \n\nAuthor:\tAndreas Konarski\nLizenz:\tgpl\n\nKontakt:\n\nprogrammieren@konarski-wuppertal.de\nwww.konarski-wuppertal.de")); +} + + +void MainWindow::restliche_einstellungen_laden() +{ +// die fenstergeometrie laden +restoreGeometry(einstellungen->value("mainwindow/geometry").toByteArray()); + +// den spieltyp laden +if (einstellungen->value("spieltyp", 1).toInt() == 3) +{ +scene->drei_ziehen(); +action_drei_ziehen->setChecked(true); +} + +// die sichtbarkeit des rahmens laden +action_rahmen->setChecked(einstellungen->value("mainwindow/rahmen", true).toBool()); +scene->initialisiere_rahmen(action_rahmen->isChecked()); + +// die highscore laden +highscore->einstellungen_laden(); + +// den spielstand laden oder ein neues spiel starten +if (einstellungen->value("begonnenes_spiel", false).toBool() == false) scene->neues_spiel(); +else scene->lade_spielstand(); + +// einstellungen fuer speichern_frage laden +speichern_frage->setze_merken(einstellungen->value("speichern_frage/merken", false).toBool()); +speichern_frage->setze_speichern(einstellungen->value("speichern_frage/speichern", true).toBool()); +} + + +void MainWindow::einstellungen_speichern() +{ +// die fenstergeometrie speichern +einstellungen->setValue("mainwindow/geometry", saveGeometry()); + +// den spieltyp speichern +if (scene->nur_eine_wird_gezogen() == true) einstellungen->setValue("spieltyp", 1); +else einstellungen->setValue("spieltyp", 3); + +// die sichtbarkeit des rahmens speichern +einstellungen->setValue("mainwindow/rahmen", action_rahmen->isChecked()); + +// die deckblatt sprache speichern +if (action_french->isChecked() == true) einstellungen->setValue("deckblatt", "french"); +else einstellungen->setValue("deckblatt", "german"); + +// die highscore speichern +highscore->einstellungen_speichern(); + +// wenn ein spiel laueft und der spielstand gespeichert werden soll, den spielstand speichern +if (scene->begonnenes_spiel() == true && speichern_frage->soll_speichern() == true) +{ +scene->speichere_spielstand(); + +// speichern, ob ein spiel begonnen wurde +einstellungen->setValue("begonnenes_spiel", scene->begonnenes_spiel()); +} + +else einstellungen->setValue("begonnenes_spiel", false); + +// einstellungen fuer speichern_frage speichern +einstellungen->setValue("speichern_frage/merken", speichern_frage->soll_merken()); +einstellungen->setValue("speichern_frage/speichern", speichern_frage->soll_speichern()); +} + + +void MainWindow::gewonnen(int punkte, long sekunden) +{ +if (highscore->neues_ergebnis(punkte, sekunden) == false) siegmeldung->show(); +} + + +void MainWindow::aktualisiere_punktelabel(int wert) +{ +punktelabel->setText(QString::number(wert) + tr(" Points")); +} + + +void MainWindow::aktualisiere_spielzeit(long verstrichene_sekunden) +{ +// die verstrichenen sekunden aufbereiten +int stunden = verstrichene_sekunden / 3600; + +int minuten = (verstrichene_sekunden - (stunden * 3600)) / 60; + +int sekunden = verstrichene_sekunden - (minuten * 60) - (stunden * 3600); + +QString stunden_string = QString::number(stunden); +QString minuten_string = QString::number(minuten); +QString sekunden_string = QString::number(sekunden); + +if (stunden < 10) stunden_string.prepend('0'); +if (minuten < 10) minuten_string.prepend('0'); +if (sekunden < 10) sekunden_string.prepend('0'); + +zeitlabel->setText(stunden_string + ":" + minuten_string + ":" + sekunden_string); +} + + +void MainWindow::eine_ziehen() +{ +// wenn kein spiel laueft, einfach eins starten ... +if (scene->laufendes_spiel() == false) +{ +scene->eine_ziehen(); +scene->neues_spiel(); +} + +// ansonsten erst nach einer sicherheitsfrage ein neues spiel starten +else +{ +QAbstractButton *sicherheitsfrage_ja = sicherheitsfrage->button(QMessageBox::Yes); + +sicherheitsfrage->exec(); + +if (sicherheitsfrage->clickedButton() == sicherheitsfrage_ja) +{ +scene->eine_ziehen(); +scene->neues_spiel(); +} + +else action_drei_ziehen->setChecked(true); +} +} + + +void MainWindow::drei_ziehen() +{ +// wenn kein spiel laueft, einfach eins starten ... +if (scene->laufendes_spiel() == false) +{ +scene->drei_ziehen(); +scene->neues_spiel(); +} + +// ansonsten erst nach einer sicherheitsfrage ein neues spiel starten +else +{ +QAbstractButton *sicherheitsfrage_ja = sicherheitsfrage->button(QMessageBox::Yes); + +sicherheitsfrage->exec(); + +if (sicherheitsfrage->clickedButton() == sicherheitsfrage_ja) +{ +scene->drei_ziehen(); +scene->neues_spiel(); +} + +else action_eine_ziehen->setChecked(true); +} +} + + +void MainWindow::closeEvent(QCloseEvent* event) +{ +bool brauche_frage = true; + +// wenn kein spiel begonnen wurde oder speichern_frage auf merken (dabei jedoch nicht auf reject) eingestellt ist wird keine frage gebraucht +if (scene->begonnenes_spiel() == false || (speichern_frage->soll_merken() == true && speichern_frage->result() != QDialog::Rejected)) brauche_frage = false; + +// wenn eine frage gebraucht wird +if (brauche_frage == true) speichern_frage->exec(); + +// wenn speichern_frage akzeptiert wurde das schliessen der anwendung erlauben, ... +if (speichern_frage->result() == QDialog::Accepted) QMainWindow::closeEvent(event); + +// ... ansonsten, wenn nicht akzeptiert, verhindern +else if (speichern_frage->result() == QDialog::Rejected) event->ignore(); +} diff --git a/plugins/patience_plugin/Patience/MainWindow.h b/plugins/patience_plugin/Patience/MainWindow.h new file mode 100644 index 000000000..49bf718de --- /dev/null +++ b/plugins/patience_plugin/Patience/MainWindow.h @@ -0,0 +1,46 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#define VERSION "0.81" + +#include +#include "ui_MainWindow.h" + +class Scene; +class QSettings; +class QMessageBox; +class QLabel; +class Highscore; +class Speichern_frage; + +class MainWindow : public QMainWindow, private Ui::MainWindow +{ +Q_OBJECT + +public: +MainWindow(QWidget *parent = 0); +virtual ~MainWindow(); + +private slots: +void neues_spiel(); +void about(); +void restliche_einstellungen_laden(); +void einstellungen_speichern(); +void gewonnen(int, long); +void aktualisiere_punktelabel(int); +void aktualisiere_spielzeit(long); +void eine_ziehen(); +void drei_ziehen(); + +private: +Scene *scene; +QSettings *einstellungen; +QMessageBox *siegmeldung, *sicherheitsfrage; +QLabel *punktelabel, *zeitlabel; +Highscore *highscore; +Speichern_frage *speichern_frage; + +virtual void closeEvent(QCloseEvent*); +}; + +#endif diff --git a/plugins/patience_plugin/Patience/MainWindow.ui b/plugins/patience_plugin/Patience/MainWindow.ui new file mode 100644 index 000000000..053cd28d5 --- /dev/null +++ b/plugins/patience_plugin/Patience/MainWindow.ui @@ -0,0 +1,269 @@ + + + MainWindow + + + + 0 + 0 + 810 + 653 + + + + Patience + + + + + 5 + + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QPainter::Antialiasing|QPainter::HighQualityAntialiasing|QPainter::SmoothPixmapTransform|QPainter::TextAntialiasing + + + QGraphicsView::CacheBackground + + + QGraphicsView::FullViewportUpdate + + + + + + + + + 0 + 0 + 810 + 22 + + + + + Game + + + + + + + + &Help + + + + + + + &Settings + + + + &Cardset + + + + + + + Gametype + + + + + + + Save Game + + + + + + + + + + + + + + + + &Highscore + + + + + + &Edit + + + + + + + + + + + + + &New Game + + + Ctrl+N + + + + + Close + + + + + About Patience + + + + + About QT + + + + + true + + + French + + + + + true + + + German + + + + + &Show + + + + + true + + + Take One + + + + + true + + + Take Three + + + + + true + + + French + + + + + true + + + German + + + + + true + + + Take One + + + + + true + + + Take Three + + + + + true + + + true + + + Frame + + + + + Undo + + + + + true + + + true + + + Ask + + + + + true + + + false + + + Save + + + + + true + + + Don't save + + + + + + Viewer + QGraphicsView +
Viewer.h
+
+
+ + + + +
diff --git a/plugins/patience_plugin/Patience/Patience.rc b/plugins/patience_plugin/Patience/Patience.rc new file mode 100644 index 000000000..2f554233d --- /dev/null +++ b/plugins/patience_plugin/Patience/Patience.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "icon.ico" diff --git a/plugins/patience_plugin/Patience/PatiencePlugin.cpp b/plugins/patience_plugin/Patience/PatiencePlugin.cpp new file mode 100644 index 000000000..83b2624f9 --- /dev/null +++ b/plugins/patience_plugin/Patience/PatiencePlugin.cpp @@ -0,0 +1,53 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +//#include +//#include +//#include + +#include "PatiencePlugin.h" +#include "MainWindow.h" + +QString +PatiencePlugin::pluginDescription() const +{ + QString res; + res = "a Patience plugin" ; + + return res; +} + +QString +PatiencePlugin::pluginName() const +{ + return "Patience" ; +} + +QWidget* +PatiencePlugin::pluginWidget(QWidget * parent ) +{ + MainWindow* window = new MainWindow(); + + return window; +} + + +Q_EXPORT_PLUGIN2(patience_plugin, PatiencePlugin) diff --git a/plugins/patience_plugin/Patience/PatiencePlugin.h b/plugins/patience_plugin/Patience/PatiencePlugin.h new file mode 100644 index 000000000..f70af5768 --- /dev/null +++ b/plugins/patience_plugin/Patience/PatiencePlugin.h @@ -0,0 +1,48 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _PATIENCE_PLUGIN_H_ +#define _PATIENCE_PLUGIN_H_ + +#include + +#include +#include + +#include + +#include + +class PatiencePlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Proportionen.h b/plugins/patience_plugin/Patience/Proportionen.h new file mode 100644 index 000000000..1998a892e --- /dev/null +++ b/plugins/patience_plugin/Patience/Proportionen.h @@ -0,0 +1,128 @@ +#ifndef PROPORTIONEN_H +#define PROPORTIONEN_H + +// fuer Basisstapel +#define BASISSTAPEL_AUSTEILSTAPEL "austeilstapel" +#define BASISSTAPEL_AUSTEILCOSTAPEL "austeilcostapel" +#define BASISSTAPEL_ZIELSTAPEL "zielstapel" +#define BASISSTAPEL_ABLAGESTAPEL "ablagestapel" +#define BASISSTAPEL_ABSTAND_HILFSZEIGER_VERHAELTNIS 28.0 +#define BASISSTAPEL_ANZAHL_SPEICHERELEMENTE 2 +#define BASISSTAPEL_SAVE_ID_IDX 0 +#define BASISSTAPEL_KARTEN_IDX 1 +#define BASISSTAPEL_KARTEN_SPLITTER "," + +// fuer Ablagestapel +#define ABLAGESTAPEL_YDRIFT_VERHAELTNIS 9.333333333333333 + + +// fuer Austeilcostapel +#define AUSTEILCOSTAPEL_XDRIFT_VERHAELTNIS 7.0 + +// muss um 1 groesser sein als BASISSTAPEL_KARTEN_IDX !!! +#define AUSTEILSTAPEL_ABLAGENUMMER_IDX 2 + +// muss um mindestens 1 groesser sein als BASISSTAPEL_ANZAHL_SPEICHERELEMENTE !!! +#define AUSTEILSTAPEL_ANZAHL_SPEICHERELEMENTE 3 + +// fuer Highscore +#define HIGHSCORE_NAME_POSITION 0 +#define HIGHSCORE_PUNKTE_POSITION 1 +#define HIGHSCORE_ZEIT_POSITION 2 +#define HIGHSCORE_ZEILEN 15 +#define HIGHSCORE_LEER "n / a" +#define HIGHSCORE_SPLITTER ":" +#define HIGHSCORE_NAME_SPALTE_STANDARTGROESSE 250 + + +// fuer Hilfszeiger +#define HILFSZEIGER_BREITE_VERHAELTNIS 6.0 +#define HILFSZEIGER_HOEHE_VERHAELTNIS 7.0 +#define HILFSZEIGER_DICKE_VERHAELTNIS 70 + + +// fuer Karten +#define KARTEN_KREUTZ "kreutz" +#define KARTEN_PIK "pik" +#define KARTEN_HERZ "herz" +#define KARTEN_KARO "karo" +#define KARTEN_ASS "ass" +#define KARTEN_BUBE "bube" +#define KARTEN_DAME "dame" +#define KARTEN_KOENIG "koenig" +#define KARTE_ANZAHL_SPEICHERELEMENTE 2 +#define KARTE_SAVE_ID_IDX 0 +#define KARTE_IST_VORNE_IDX 1 +#define KARTE_VERHAELTNIS_BREITE_ZU_HOEHE 1.555555555555556 + + +// fuer Punktezaehler +// punkte wenn nur eine karte gezogen wird +#define PUNKTEZAEHLER_EINE_ZIEHEN_AUSTEILSTAPEL_ZU_ABLAGESTAPEL 5 +#define PUNKTEZAEHLER_EINE_ZIEHEN_AUSTEILSTAPEL_ZU_ZIELSTAPEL 15 +#define PUNKTEZAEHLER_EINE_ZIEHEN_ABLAGESTAPEL_ZU_ZIELSTAPEL 10 +#define PUNKTEZAEHLER_EINE_ZIEHEN_PUNKTEABZUG_ZEIT 2 +#define PUNKTEZAEHLER_EINE_ZIEHEN_KARTE_AUF_ABLAGESTAPEL_AUFGEDECKT 5 +#define PUNKTEZAEHLER_EINE_ZIEHEN_AUSTEILSTAPEL_DURCH 100 + +// punkte wenn drei karten gezogen werden +#define PUNKTEZAEHLER_DREI_ZIEHEN_AUSTEILSTAPEL_ZU_ABLAGESTAPEL 5 +#define PUNKTEZAEHLER_DREI_ZIEHEN_AUSTEILSTAPEL_ZU_ZIELSTAPEL 15 +#define PUNKTEZAEHLER_DREI_ZIEHEN_ABLAGESTAPEL_ZU_ZIELSTAPEL 10 +#define PUNKTEZAEHLER_DREI_ZIEHEN_PUNKTEABZUG_ZEIT 1 +#define PUNKTEZAEHLER_DREI_ZIEHEN_KARTE_AUF_ABLAGESTAPEL_AUFGEDECKT 5 +#define PUNKTEZAEHLER_DREI_ZIEHEN_AUSTEILSTAPEL_DURCH 50 + +#define PUNKTEZAEHLER_SPLITTER "<<<" + +#define PUNKTEZAEHLER_ANZAHL_SPEICHERELEMENTE 4 +#define PUNKTEZAEHLER_STRING_SPLITTER "," +#define PUNKTEZAEHLER_SAVE_ID_IDX 0 +#define PUNKTEZAEHLER_STRAFTIMER_ON_IDX 1 +#define PUNKTEZAEHLER_NACH_OBEN_LISTE_IDX 2 +#define PUNKTEZAEHLER_PUNKTE_IDX 3 + + +// fuer Rahmen +#define RAHMEN_DICKE_VERHAELTNIS 23.333333333333333 +#define RAHMEN_ECKRADIUS_VERHAELTNIS 9.333333333333333 + +// fuer Scene +#define SCENE_ABLAGE_STAPELZAHL 7 +#define SCENE_ANZAHL_SPEICHERELEMENTE 3 +#define SCENE_SAVE_ID_IDX 0 +#define SCENE_EINE_ZIEHEN_IDX 1 +#define SCENE_VERSTRICHENE_ZEIT_IDX 2 +#define SCENE_AUSGANGSBREITE 795.0 +#define SCENE_AUSGANGSHOEHE 595.0 +#define SCENE_AUSTEILSTAPEL_X_VERHAELTNIS 34.565217391304348 +#define SCENE_AUSTEILCOSTAPEL_X_VERHAELTNIS 5.977443609022556 +#define SCENE_KREUTZZIELSTAPEL_X_VERHAELTNIS 2.252124645892351 +#define SCENE_PIKZIELSTAPEL_X_VERHAELTNIS 1.717062634989201 +#define SCENE_KAROZIELSTAPEL_X_VERHAELTNIS 1.387434554973822 +#define SCENE_HERZZIELSTAPEL_X_VERHAELTNIS 1.16398243045388 +#define SCENE_ABLAGESTAPEL_01_X_VERHAELTNIS 34.565217391304348 +#define SCENE_ABLAGESTAPEL_02_X_VERHAELTNIS 5.977443609022556 +#define SCENE_ABLAGESTAPEL_03_X_VERHAELTNIS 3.271604938271605 +#define SCENE_ABLAGESTAPEL_04_X_VERHAELTNIS 2.252124645892351 +#define SCENE_ABLAGESTAPEL_05_X_VERHAELTNIS 1.717062634989201 +#define SCENE_ABLAGESTAPEL_06_X_VERHAELTNIS 1.387434554973822 +#define SCENE_ABLAGESTAPEL_07_X_VERHAELTNIS 1.16398243045388 +#define SCENE_ABLAGESTAPEL_Y_VERHAELTNIS 3.305555555555556 +#define SCENE_VERHAELTNIS_BREITE_ZU_HOEHE 1.336134453781513 +#define SCENE_VERHAELTNIS_HOEHE_ZU_BREITE 0.748427672955975 +#define SCENE_HOEHE_ZU_KARTENHOEHE 4.25 +#define SCENE_OBERE_STAPEL_Y_VERHAELTNIS 59.5 + + +// fuer Undo +#define ZUEGE_PRO_BEWEGUNG 1.0 +#define ZUEGE_PRO_AUFDECKUNG 0.5 +#define UNDO_LIMIT 3.0 +#define ZUEGE_SPLITTER "," +#define ZUEGE_NACH_SPLITTER "." +#define UNDO_ANZAHL_SPEICHERELEMENTE 2 +#define UNDO_SAVE_ID_IDX 0 +#define UNDO_VERLAUF_IDX 1 + +#endif diff --git a/plugins/patience_plugin/Patience/Punktezaehler.cpp b/plugins/patience_plugin/Patience/Punktezaehler.cpp new file mode 100644 index 000000000..478e31ba5 --- /dev/null +++ b/plugins/patience_plugin/Patience/Punktezaehler.cpp @@ -0,0 +1,284 @@ +#include "Punktezaehler.h" +#include "Scene.h" +#include "Basisstapel.h" +#include "Proportionen.h" +#include +#include + +using namespace std; + +Punktezaehler::Punktezaehler(Scene *parent) : QObject(parent), punkte(0), scene(parent), nur_eine_ziehen(true) +{ +// straftimer erstellen und seinen intervall auf 10 sekunden einstellen +straftimer = new QTimer(this); +straftimer->setInterval(10000); + +// signal - slot verbindungen +// reaktionen auf straftimer ermoeglichen +connect(straftimer, SIGNAL(timeout()), this, SLOT(reaktion_auf_timeout())); +} + + +Punktezaehler::~Punktezaehler() +{ +} + + +void Punktezaehler::neuer_zug(const Zug& zug) +{ +// auf ungueltigen zug pruefen +if (zug.ist_gueltig() == false) +{ +qDebug() << tr("Invalid move in Punktzaehler::neuer_zug()"); + +exit(1); +} + +// nur, wenn ein spiel laeuft +if (scene->laufendes_spiel() == true) +{ +// wenn straftimer noch nicht laueft +if (straftimer->isActive() == false && scene->laufendes_spiel() == true) +{ +straftimer->start(); + +emit erster_zug(); +} + +punkte += kalkuliere_punkte(zug); + +if (straftimer->isActive() == true && bringt_zeitaufschub(zug) == true) +{ +straftimer->stop(); +straftimer->start(); +} + +emit neue_punktzahl(punkte); +} +} + + +void Punktezaehler::neues_spiel() +{ +straftimer->stop(); + +punkte = 0; + +emit neue_punktzahl(punkte); + +nach_oben_liste.clear(); +} + + +void Punktezaehler::spiel_zuende() +{ +straftimer->stop(); +} + + +void Punktezaehler::reaktion_auf_timeout() +{ +if (punkte > 0) +{ +if (nur_eine_ziehen == true) punkte -= PUNKTEZAEHLER_EINE_ZIEHEN_PUNKTEABZUG_ZEIT; +else punkte -= PUNKTEZAEHLER_DREI_ZIEHEN_PUNKTEABZUG_ZEIT; + +if (punkte < 0) punkte = 0; + +emit neue_punktzahl(punkte); +} +} + + +void Punktezaehler::stapel_durch() +{ +if (punkte > 0) +{ +if (nur_eine_ziehen == true) punkte -= PUNKTEZAEHLER_EINE_ZIEHEN_AUSTEILSTAPEL_DURCH; +else punkte -= PUNKTEZAEHLER_DREI_ZIEHEN_AUSTEILSTAPEL_DURCH; + +if (punkte < 0) punkte = 0; + +emit neue_punktzahl(punkte); +} +} + + +int Punktezaehler::punktstand() const +{ +return punkte; +} + + +void Punktezaehler::eine_ziehen() +{ +nur_eine_ziehen = true; +} + + +void Punktezaehler::drei_ziehen() +{ +nur_eine_ziehen = false; +} + + +void Punktezaehler::undo_meldung(const Zug& zug) +{ +// die punke des rueckgaengi gemachten zuges wieder abziehen +nach_oben_liste.removeAll(zug.karte_name()); +punkte -= kalkuliere_punkte(zug); + +emit neue_punktzahl(punkte); +} + + +int Punktezaehler::kalkuliere_punkte(const Zug& zug) const +{ +int erg = 0; + +// wenn es sich um eine bewegung handelt +if (zug.ist_bewegung() == true) +{ +// vom austeilstapel zu einem ablagestapel bringt 5 punkte +if (zug.herkunft_name() == BASISSTAPEL_AUSTEILCOSTAPEL && zug.ziel_name().contains(BASISSTAPEL_ABLAGESTAPEL) == true) +{ +if (nur_eine_ziehen == true) erg += PUNKTEZAEHLER_EINE_ZIEHEN_AUSTEILSTAPEL_ZU_ABLAGESTAPEL; +else erg += PUNKTEZAEHLER_DREI_ZIEHEN_AUSTEILSTAPEL_ZU_ABLAGESTAPEL; +} + +// vom austeilcostapel zum zielstapel bringt 15 punkte +else if (zug.herkunft_name() == BASISSTAPEL_AUSTEILCOSTAPEL && zug.ziel_name().contains(BASISSTAPEL_ZIELSTAPEL) == true && nach_oben_liste.contains(zug.karte_name()) == false) +{ +// man soll fuer das hochlegen einer karte nicht mehrfach punkte kassieren koennen +if (nur_eine_ziehen == true) erg += PUNKTEZAEHLER_EINE_ZIEHEN_AUSTEILSTAPEL_ZU_ZIELSTAPEL; +else erg += PUNKTEZAEHLER_DREI_ZIEHEN_AUSTEILSTAPEL_ZU_ZIELSTAPEL; +} + +// von unten zum zielstapel bringt 10 punkte +else if (zug.herkunft_name().contains(BASISSTAPEL_ABLAGESTAPEL) == true && zug.ziel_name().contains(BASISSTAPEL_ZIELSTAPEL) == true && nach_oben_liste.contains(zug.karte_name()) == false) +{ +if (nur_eine_ziehen == true) erg += PUNKTEZAEHLER_EINE_ZIEHEN_ABLAGESTAPEL_ZU_ZIELSTAPEL; +else erg += PUNKTEZAEHLER_DREI_ZIEHEN_ABLAGESTAPEL_ZU_ZIELSTAPEL; +} +} + +// wenn es sich bei zug um eine aufdeckung handelt +else if (zug.ist_aufdeckgung() == true) +{ +// wenn eine karte vom ablagestapel aufgedeckt wurde gibt's dafuer 5 punkte +if (zug.herkunft_name().contains(BASISSTAPEL_ABLAGESTAPEL) == true) +{ +if (nur_eine_ziehen == true) erg += PUNKTEZAEHLER_EINE_ZIEHEN_KARTE_AUF_ABLAGESTAPEL_AUFGEDECKT; +else erg += PUNKTEZAEHLER_DREI_ZIEHEN_KARTE_AUF_ABLAGESTAPEL_AUFGEDECKT; +} +} + +// wenn es sich weder um eine bewegung noch um eine aufdeckung handelt ist zug ungueltig +else +{ +qDebug() << tr("Invalid move in Punktzaehler::kalkuliere_punkte(const Zug& zug)"); + +exit(1); +} + +return erg; +} + + +bool Punktezaehler::bringt_zeitaufschub(const Zug& zug) const +{ +bool erg = false; + +// wenn es sich um eine bewegung handelt +if (zug.ist_bewegung() == true) +{ +// vom austeilstapel zu einem ablagestapel bringt zeitaufschub +if (zug.herkunft_name() == BASISSTAPEL_AUSTEILCOSTAPEL && zug.ziel_name().contains(BASISSTAPEL_ABLAGESTAPEL) == true) erg = true; + +// vom austeilcostapel zum zielstapel bringt zeitaufschub +else if (zug.herkunft_name() == BASISSTAPEL_AUSTEILCOSTAPEL && zug.ziel_name().contains(BASISSTAPEL_ZIELSTAPEL) == true && nach_oben_liste.contains(zug.karte_name()) == false) erg = true; + +// karte unten umstapeln bringt zeitaufschub +else if (zug.herkunft_name().contains(BASISSTAPEL_ABLAGESTAPEL) == true && zug.ziel_name().contains(BASISSTAPEL_ABLAGESTAPEL) == true) erg = true; + +// von unten zum zielstapel bringt zeitaufschub +else if (zug.herkunft_name().contains(BASISSTAPEL_ABLAGESTAPEL) == true && zug.ziel_name().contains(BASISSTAPEL_ZIELSTAPEL) == true && nach_oben_liste.contains(zug.karte_name()) == false) erg = true; + +// karten vom zielstapel nach unten bringt nur zeitaufschub +else if (zug.herkunft_name().contains(BASISSTAPEL_ZIELSTAPEL) == true && zug.ziel_name().contains(BASISSTAPEL_ABLAGESTAPEL) == true) erg = true; +} + +// wenn es sich bei zug um eine aufdeckung handelt +else if (zug.ist_aufdeckgung() == true) +{ +// wenn eine karte vom ablagestapel aufgedeckt wurde gibt's dafuer 5 punkte +if (zug.herkunft_name().contains(BASISSTAPEL_ABLAGESTAPEL) == true) erg = true; +} + +else +{ +qDebug() << tr("Invalid move in Punktzaehler::bringt_zeitaufschub(const Zug& zug)"); + +exit(1); +} + +return erg; +} + + +const QStringList Punktezaehler::speichere() const +{ +QStringList erg; + +// die id speichern +erg.append(objectName()); + +// straftimer zustand speichern +erg.append(QString::number(straftimer->isActive())); + +// die nach_oben_liste speichern +QString nach_oben_string; + +for (register int idx = 0; idx < nach_oben_liste.size(); idx++) +{ +if (idx > 0) nach_oben_string.append(PUNKTEZAEHLER_STRING_SPLITTER); +nach_oben_string.append(nach_oben_liste.at(idx)); +} + +erg.append(nach_oben_string); + +// die punkte speichern +erg.append(QString::number(punkte)); + +return erg; +} + + +bool Punktezaehler::lade(const QStringList& daten) +{ +bool erg = false; + +if (daten.size() == PUNKTEZAEHLER_ANZAHL_SPEICHERELEMENTE && daten.first() == objectName()) +{ +erg = true; + +// noetigenfalls den straftimer starten +if (daten.at(PUNKTEZAEHLER_STRAFTIMER_ON_IDX).toInt() == 1) straftimer->start(); + +// die nach_oben_liste laden +nach_oben_liste = daten.at(PUNKTEZAEHLER_NACH_OBEN_LISTE_IDX).split(PUNKTEZAEHLER_STRING_SPLITTER, QString::SkipEmptyParts); + +// die punkte laden +punkte = daten.at(PUNKTEZAEHLER_PUNKTE_IDX).toInt(); + +emit neue_punktzahl(punkte); +} + +return erg; +} + + +bool Punktezaehler::begonnenes_spiel() const +{ +return straftimer->isActive(); +} diff --git a/plugins/patience_plugin/Patience/Punktezaehler.h b/plugins/patience_plugin/Patience/Punktezaehler.h new file mode 100644 index 000000000..a3a6fac5c --- /dev/null +++ b/plugins/patience_plugin/Patience/Punktezaehler.h @@ -0,0 +1,52 @@ +#ifndef PUNKTEZAEHLER_H +#define PUNKTEZAEHLER_H + +#include +#include +#include +#include "Zug.h" + +class QTimer; +class Scene; + +class Punktezaehler : public QObject +{ +Q_OBJECT + +public: +Punktezaehler(Scene *parent); +virtual ~Punktezaehler(); + +int punktstand() const; +const QStringList speichere() const; +bool lade(const QStringList&); +bool begonnenes_spiel() const; + +public slots: +void neuer_zug(const Zug&); +void stapel_durch(); +void neues_spiel(); +void spiel_zuende(); +void eine_ziehen(); +void drei_ziehen(); +void undo_meldung(const Zug&); + +signals: +void neue_punktzahl(int); +void erster_zug(); + +private slots: +void reaktion_auf_timeout(); + +private: +int punkte; +QTimer *straftimer; +Scene *scene; +QStringList nach_oben_liste; + +bool nur_eine_ziehen; +int kalkuliere_punkte(const Zug&) const; +bool bringt_zeitaufschub(const Zug&) const; +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Rahmen.cpp b/plugins/patience_plugin/Patience/Rahmen.cpp new file mode 100644 index 000000000..b63b21d72 --- /dev/null +++ b/plugins/patience_plugin/Patience/Rahmen.cpp @@ -0,0 +1,74 @@ +#include "Rahmen.h" +#include "Basisstapel.h" +#include "Proportionen.h" +#include + +using namespace std; + +Rahmen::Rahmen(Basisstapel* parent) : QObject(parent), QGraphicsItem(0), Groesse(QSizeF(parent->boundingRect().size().width() + (((parent->boundingRect().size().height() / RAHMEN_DICKE_VERHAELTNIS) - 1) * 2), parent->boundingRect().size().height() + (((parent->boundingRect().size().height() / RAHMEN_DICKE_VERHAELTNIS) - 1) * 2))), meinstapel(0), dicke(parent->boundingRect().size().height() / RAHMEN_DICKE_VERHAELTNIS), eckradius(parent->boundingRect().size().height() / RAHMEN_ECKRADIUS_VERHAELTNIS) +{ +setZValue(500); + +setVisible(false); +} + + +Rahmen::~Rahmen() +{ +} + + +void Rahmen::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*) +{ +QPen stift(painter->pen()); + +stift.setWidth(dicke); +stift.setColor(Qt::darkRed); + +painter->setPen(stift); + +painter->drawRoundedRect(boundingRect().adjusted(dicke / 2, dicke / 2, -(dicke / 2), -(dicke / 2)), eckradius, eckradius); +} + + +QRectF Rahmen::boundingRect() const +{ +return QRectF(QPointF(0, 0), Groesse); +} + + +void Rahmen::zeige(Basisstapel* stapel, const QPointF& position) +{ +if (stapel != meinstapel || isVisible() == false) + +meinstapel = stapel; + +setPos(QPointF(position.x() - (dicke), position.y() - (dicke))); + +setVisible(true); +} + + +void Rahmen::verstecke() +{ +if (isVisible() == true) setVisible(false); +} + + +Basisstapel* Rahmen::aktueller_stapel() const +{ +return meinstapel; +} + + +void Rahmen::passe_groesse_an(const QRectF& wert) +{ +prepareGeometryChange(); + +Groesse = QSizeF(wert.size().width() + ((wert.size().height() / RAHMEN_DICKE_VERHAELTNIS) * 2), wert.size().height() + ((wert.size().height() / RAHMEN_DICKE_VERHAELTNIS) * 2)); + +dicke = wert.size().height() / RAHMEN_DICKE_VERHAELTNIS; +eckradius = wert.size().height() / RAHMEN_ECKRADIUS_VERHAELTNIS; + +update(); +} diff --git a/plugins/patience_plugin/Patience/Rahmen.h b/plugins/patience_plugin/Patience/Rahmen.h new file mode 100644 index 000000000..d6faebef5 --- /dev/null +++ b/plugins/patience_plugin/Patience/Rahmen.h @@ -0,0 +1,38 @@ +#ifndef RAHMEN_H +#define RAHMEN_H + +#include +#include + +class Basisstapel; + +class Rahmen : public QObject, public QGraphicsItem +{ +Q_OBJECT + +public: +Rahmen(Basisstapel* parent); +virtual ~Rahmen(); + +void zeige(Basisstapel*, const QPointF&); +Basisstapel *aktueller_stapel() const; +void passe_groesse_an(const QRectF&); + +public slots: +void verstecke(); + +signals: + +private slots: + +private: +QSizeF Groesse; +Basisstapel* meinstapel; +double dicke; +double eckradius; + +void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); +QRectF boundingRect() const; +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Random.cpp b/plugins/patience_plugin/Patience/Random.cpp new file mode 100644 index 000000000..5c9ff40c6 --- /dev/null +++ b/plugins/patience_plugin/Patience/Random.cpp @@ -0,0 +1,77 @@ +#include "Random.h" +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace Random +{ + +int random(int min, int max) +{ +int ergebnis = 0; +unsigned int differenz = 0; +unsigned int zufall = qrand(); + +// min muss kleiner als max sein +if (min < max) +{ +// die differenz zwischen min und max berechnen +if (min < 0) +{ +differenz = max + (0 - min); +} + +else +{ +differenz = max - min; +} + +// dafuer sorgen, das auch der max als ergebnis moeglich ist. jedoch nur, wenn differenz kleiner als UINT_MAX ist ! +if (differenz < UINT_MAX) differenz++; + +// wenn die differenz groesser als RAND_MAX ist und RAND_MAX kleiner als UINT_MAX ist zufall durch addition zusaetzlicher zufallszahlen vergroessern +if (differenz > RAND_MAX && RAND_MAX < UINT_MAX) +{ +// wie oft passt RAND_MAX in ULONG_MAX ? +int schleifen = UINT_MAX / RAND_MAX; + +// so oft, wie RAND_MAX in UINT_MAX passt die schleife durchlaufen lassen. dabei beruecksichtigen, das eine abfrage bereits erledigt ist +for (register int idx = 1; idx < schleifen; idx++) zufall += qrand(); +} + +// zufall in den bereich der differenz bringen +if (zufall > differenz) +{ +zufall = zufall % differenz; +} + +ergebnis = min + zufall; +} + +// wenn min gleich max ist, ist onehin nur ein wert moeglich +else if (min == max) +{ +ergebnis = min; +} + +else +{ +qDebug() << QObject::tr("min is bigger than max !"); + +exit(1); +} + +return ergebnis; +} + +void initialisiere() +{ +// den zufallssimulator initialisieren +qsrand(QDateTime::currentDateTime().toTime_t() + QTime::currentTime().msec()); +} +} diff --git a/plugins/patience_plugin/Patience/Random.h b/plugins/patience_plugin/Patience/Random.h new file mode 100644 index 000000000..cf94406a8 --- /dev/null +++ b/plugins/patience_plugin/Patience/Random.h @@ -0,0 +1,30 @@ +/* + +Name: Random +Autor: Andreas Konarski +Erstellt: 18.12.2009. +Version: 0.05 +Lizenz: GPL v3 +Plattformen: Alle Systeme, auf denen QT 4.5 verfuegbar ist. + +Kontakt: programmieren@konarski-wuppertal.de +home: www.konarski-wuppertal.de + +Falls ich mit diesem Programm die Rechte von irgend jemand verletzen sollte, bitte ich um einen Hinweis. Wenn dies Tatsaechlich der Fall ist, entferne ich es schnellstmoeglich von meiner Homepage. + +*/ + + +#ifndef RANDOM_H + +#define RANDOM_H + +namespace Random +{ + +int random(int min, int max); +void initialisiere(); + +} + +#endif diff --git a/plugins/patience_plugin/Patience/Scene.cpp b/plugins/patience_plugin/Patience/Scene.cpp new file mode 100644 index 000000000..157955e75 --- /dev/null +++ b/plugins/patience_plugin/Patience/Scene.cpp @@ -0,0 +1,1213 @@ +/* + +Achtung! Die Objektnamen der hier erzeugten Objekte dürfen auf keinen Fall, auch nicht zur korrektur von eventuell vorhandenen Rechtschreibfehlern geaendert werden, da sie in verschiedenen Situationen zur Laufzeit des Programms zum auffinden und identifizieren von Objekten verwendet werden!!! + +*/ + +#include "Scene.h" +#include "Karte.h" +#include "Random.h" +#include "Basisstapel.h" +#include "Austeilstapel.h" +#include "Austeilcostapel.h" +#include "Zielstapel.h" +#include "Ablagestapel.h" +#include "Siegkontrolle.h" +#include "Punktezaehler.h" +#include "Rahmen.h" +#include "Undo.h" +#include "Zug.h" +#include "Proportionen.h" +#include +#include +#include +#include +#include +#include + +using namespace std; + +Scene::Scene(const QString& deckblatt, QObject *parent) : QGraphicsScene(parent), Laufendes_spiel(false), nur_eine_ziehen(true) +{ +// den zufallssimulator initialisieren +Random::initialisiere(); + +// die hintergrundfarbe einstellen +setBackgroundBrush(Qt::darkGreen); + +// die klasse Zug fuer das signal - slot system registrieren +qRegisterMetaType("Zug"); + +/* + +Wichtiger Hinweis: + +Die Reihenfolge, in der die Karten aufgebaut und in die Kartenliste eingefuegt werden, darf auf keinen Fall veraendert werden, da es ansonsten beim aendern des Deckblattes zu fehlern kommen wuerde! Ausserdem darf auch die Anzahl der Karten auf keinen Fall geaendert werden !!! + +*/ + +// die karten erstellen +// die 4 asse erstellen +// kreutz +Karte *kreutz_ass = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/01c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_ass->setObjectName(QString(KARTEN_KREUTZ) + "_" + KARTEN_ASS); +kreutz_ass->setze_farbe(KARTEN_KREUTZ); +kreutz_ass->setze_wert(1); +kartenliste.append(kreutz_ass); + +// karo +Karte *karo_ass = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/01d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_ass->setObjectName(QString(KARTEN_KARO) + "_" + KARTEN_ASS); +karo_ass->setze_farbe(KARTEN_KARO); +karo_ass->setze_wert(1); +kartenliste.append(karo_ass); + +// herz +Karte *herz_ass = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/01h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_ass->setObjectName(QString(KARTEN_HERZ) + "_" + KARTEN_ASS); +herz_ass->setze_farbe(KARTEN_HERZ); +herz_ass->setze_wert(1); +kartenliste.append(herz_ass); + +// pik +Karte *pik_ass = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/01s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_ass->setObjectName(QString(KARTEN_PIK) + "_" + KARTEN_ASS); +pik_ass->setze_farbe(KARTEN_PIK); +pik_ass->setze_wert(1); +kartenliste.append(pik_ass); + +// die 2er erstellen +// kreutz +Karte *kreutz_2 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/02c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_2->setObjectName(QString(KARTEN_KREUTZ) + "_2"); +kreutz_2->setze_farbe(KARTEN_KREUTZ); +kreutz_2->setze_wert(2); +kartenliste.append(kreutz_2); + +// karo +Karte *karo_2 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/02d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_2->setObjectName(QString(KARTEN_KARO) + "_2"); +karo_2->setze_farbe(KARTEN_KARO); +karo_2->setze_wert(2); +kartenliste.append(karo_2); + +// herz +Karte *herz_2 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/02h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_2->setObjectName(QString(KARTEN_HERZ) + "_2"); +herz_2->setze_farbe(KARTEN_HERZ); +herz_2->setze_wert(2); +kartenliste.append(herz_2); + +// pik +Karte *pik_2 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/02s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_2->setObjectName(QString(KARTEN_PIK) + "_2"); +pik_2->setze_farbe(KARTEN_PIK); +pik_2->setze_wert(2); +kartenliste.append(pik_2); + +// die 3er erstellen +// kreutz +Karte *kreutz_3 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/03c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_3->setObjectName(QString(KARTEN_KREUTZ) + "_3"); +kreutz_3->setze_farbe(KARTEN_KREUTZ); +kreutz_3->setze_wert(3); +kartenliste.append(kreutz_3); + +// karo +Karte *karo_3 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/03d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_3->setObjectName(QString(KARTEN_KARO) + "_3"); +karo_3->setze_farbe(KARTEN_KARO); +karo_3->setze_wert(3); +kartenliste.append(karo_3); + +// herz +Karte *herz_3 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/03h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_3->setObjectName(QString(KARTEN_HERZ) + "_3"); +herz_3->setze_farbe(KARTEN_HERZ); +herz_3->setze_wert(3); +kartenliste.append(herz_3); + +// pik +Karte *pik_3 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/03s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_3->setObjectName(QString(KARTEN_PIK) + "_3"); +pik_3->setze_farbe(KARTEN_PIK); +pik_3->setze_wert(3); +kartenliste.append(pik_3); + +// die 4er erstellen +// kreutz +Karte *kreutz_4 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/04c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_4->setObjectName(QString(KARTEN_KREUTZ) + "_4"); +kreutz_4->setze_farbe(KARTEN_KREUTZ); +kreutz_4->setze_wert(4); +kartenliste.append(kreutz_4); + +// karo +Karte *karo_4 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/04d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_4->setObjectName(QString(KARTEN_KARO) + "_4"); +karo_4->setze_farbe(KARTEN_KARO); +karo_4->setze_wert(4); +kartenliste.append(karo_4); + +// herz +Karte *herz_4 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/04h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_4->setObjectName(QString(KARTEN_HERZ) + "_4"); +herz_4->setze_farbe(KARTEN_HERZ); +herz_4->setze_wert(4); +kartenliste.append(herz_4); + +// pik +Karte *pik_4 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/04s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_4->setObjectName(QString(KARTEN_PIK) + "_4"); +pik_4->setze_farbe(KARTEN_PIK); +pik_4->setze_wert(4); +kartenliste.append(pik_4); + +// die 5er erstellen +// kreutz +Karte *kreutz_5 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/05c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_5->setObjectName(QString(KARTEN_KREUTZ) + "_5"); +kreutz_5->setze_farbe(KARTEN_KREUTZ); +kreutz_5->setze_wert(5); +kartenliste.append(kreutz_5); + +// karo +Karte *karo_5 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/05d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_5->setObjectName(QString(KARTEN_KARO) + "_5"); +karo_5->setze_farbe(KARTEN_KARO); +karo_5->setze_wert(5); +kartenliste.append(karo_5); + +// herz +Karte *herz_5 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/05h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_5->setObjectName(QString(KARTEN_HERZ) + "_5"); +herz_5->setze_farbe(KARTEN_HERZ); +herz_5->setze_wert(5); +kartenliste.append(herz_5); + +// pik +Karte *pik_5 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/05s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_5->setObjectName(QString(KARTEN_PIK) + "_5"); +pik_5->setze_farbe(KARTEN_PIK); +pik_5->setze_wert(5); +kartenliste.append(pik_5); + +// die 6er erstellen +// kreutz +Karte *kreutz_6 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/06c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_6->setObjectName(QString(KARTEN_KREUTZ) + "_6"); +kreutz_6->setze_farbe(KARTEN_KREUTZ); +kreutz_6->setze_wert(6); +kartenliste.append(kreutz_6); + +// karo +Karte *karo_6 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/06d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_6->setObjectName(QString(KARTEN_KARO) + "_6"); +karo_6->setze_farbe(KARTEN_KARO); +karo_6->setze_wert(6); +kartenliste.append(karo_6); + +// herz +Karte *herz_6 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/06h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_6->setObjectName(QString(KARTEN_HERZ) + "_6"); +herz_6->setze_farbe(KARTEN_HERZ); +herz_6->setze_wert(6); +kartenliste.append(herz_6); + +// pik +Karte *pik_6 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/06s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_6->setObjectName(QString(KARTEN_PIK) + "_6"); +pik_6->setze_farbe(KARTEN_PIK); +pik_6->setze_wert(6); +kartenliste.append(pik_6); + +// die 7er erstellen +// kreutz +Karte *kreutz_7 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/07c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_7->setObjectName(QString(KARTEN_KREUTZ) + "_7"); +kreutz_7->setze_farbe(KARTEN_KREUTZ); +kreutz_7->setze_wert(7); +kartenliste.append(kreutz_7); + +// karo +Karte *karo_7 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/07d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_7->setObjectName(QString(KARTEN_KARO) + "_7"); +karo_7->setze_farbe(KARTEN_KARO); +karo_7->setze_wert(7); +kartenliste.append(karo_7); + +// herz +Karte *herz_7 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/07h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_7->setObjectName(QString(KARTEN_HERZ) + "_7"); +herz_7->setze_farbe(KARTEN_HERZ); +herz_7->setze_wert(7); +kartenliste.append(herz_7); + +// pik +Karte *pik_7 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/07s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_7->setObjectName(QString(KARTEN_PIK) + "_7"); +pik_7->setze_farbe(KARTEN_PIK); +pik_7->setze_wert(7); +kartenliste.append(pik_7); + +// die 8er erstellen +// kreutz +Karte *kreutz_8 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/08c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_8->setObjectName(QString(KARTEN_KREUTZ) + "_8"); +kreutz_8->setze_farbe(KARTEN_KREUTZ); +kreutz_8->setze_wert(8); +kartenliste.append(kreutz_8); + +// karo +Karte *karo_8 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/08d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_8->setObjectName(QString(KARTEN_KARO) + "_8"); +karo_8->setze_farbe(KARTEN_KARO); +karo_8->setze_wert(8); +kartenliste.append(karo_8); + +// herz +Karte *herz_8 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/08h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_8->setObjectName(QString(KARTEN_HERZ) + "_8"); +herz_8->setze_farbe(KARTEN_HERZ); +herz_8->setze_wert(8); +kartenliste.append(herz_8); + +// pik +Karte *pik_8 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/08s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_8->setObjectName(QString(KARTEN_PIK) + "_8"); +pik_8->setze_farbe(KARTEN_PIK); +pik_8->setze_wert(8); +kartenliste.append(pik_8); + +// die 9er erstellen +// kreutz +Karte *kreutz_9 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/09c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_9->setObjectName(QString(KARTEN_KREUTZ) + "_9"); +kreutz_9->setze_farbe(KARTEN_KREUTZ); +kreutz_9->setze_wert(9); +kartenliste.append(kreutz_9); + +// karo +Karte *karo_9 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/09d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_9->setObjectName(QString(KARTEN_KARO) + "_9"); +karo_9->setze_farbe(KARTEN_KARO); +karo_9->setze_wert(9); +kartenliste.append(karo_9); + +// herz +Karte *herz_9 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/09h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_9->setObjectName(QString(KARTEN_HERZ) + "_9"); +herz_9->setze_farbe(KARTEN_HERZ); +herz_9->setze_wert(9); +kartenliste.append(herz_9); + +// pik +Karte *pik_9 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/09s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_9->setObjectName(QString(KARTEN_PIK) + "_9"); +pik_9->setze_farbe(KARTEN_PIK); +pik_9->setze_wert(9); +kartenliste.append(pik_9); + +// die 10er erstellen +// kreutz +Karte *kreutz_10 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/10c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_10->setObjectName(QString(KARTEN_KREUTZ) + "_10"); +kreutz_10->setze_farbe(KARTEN_KREUTZ); +kreutz_10->setze_wert(10); +kartenliste.append(kreutz_10); + +// karo +Karte *karo_10 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/10d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_10->setObjectName(QString(KARTEN_KARO) + "_10"); +karo_10->setze_farbe(KARTEN_KARO); +karo_10->setze_wert(10); +kartenliste.append(karo_10); + +// herz +Karte *herz_10 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/10h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_10->setObjectName(QString(KARTEN_HERZ) + "_10"); +herz_10->setze_farbe(KARTEN_HERZ); +herz_10->setze_wert(10); +kartenliste.append(herz_10); + +// pik +Karte *pik_10 = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/10s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_10->setObjectName(QString(KARTEN_PIK) + "_10"); +pik_10->setze_farbe(KARTEN_PIK); +pik_10->setze_wert(10); +kartenliste.append(pik_10); + +// die buben erstellen +// kreutz +Karte *kreutz_bube = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/11c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_bube->setObjectName(QString(KARTEN_KREUTZ) + "_" + KARTEN_BUBE); +kreutz_bube->setze_farbe(KARTEN_KREUTZ); +kreutz_bube->setze_wert(11); +kartenliste.append(kreutz_bube); + +// karo +Karte *karo_bube = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/11d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_bube->setObjectName(QString(KARTEN_KARO) + "_" + KARTEN_BUBE); +karo_bube->setze_farbe(KARTEN_KARO); +karo_bube->setze_wert(11); +kartenliste.append(karo_bube); + +// herz +Karte *herz_bube = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/11h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_bube->setObjectName(QString(KARTEN_HERZ) + "_" + KARTEN_BUBE); +herz_bube->setze_farbe(KARTEN_HERZ); +herz_bube->setze_wert(11); +kartenliste.append(herz_bube); + +// pik +Karte *pik_bube = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/11s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_bube->setObjectName(QString(KARTEN_PIK) + "_" + KARTEN_BUBE); +pik_bube->setze_farbe(KARTEN_PIK); +pik_bube->setze_wert(11); +kartenliste.append(pik_bube); + +// die damen erstellen +// kreutz +Karte *kreutz_dame = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/12c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_dame->setObjectName(QString(KARTEN_KREUTZ) + "_" + KARTEN_DAME); +kreutz_dame->setze_farbe(KARTEN_KREUTZ); +kreutz_dame->setze_wert(12); +kartenliste.append(kreutz_dame); + +// karo +Karte *karo_dame = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/12d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_dame->setObjectName(QString(KARTEN_KARO) + "_" + KARTEN_DAME); +karo_dame->setze_farbe(KARTEN_KARO); +karo_dame->setze_wert(12); +kartenliste.append(karo_dame); + +// herz +Karte *herz_dame = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/12h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_dame->setObjectName(QString(KARTEN_HERZ) + "_" + KARTEN_DAME); +herz_dame->setze_farbe(KARTEN_HERZ); +herz_dame->setze_wert(12); +kartenliste.append(herz_dame); + +// pik +Karte *pik_dame = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/12s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_dame->setObjectName(QString(KARTEN_PIK) + "_" + KARTEN_DAME); +pik_dame->setze_farbe(KARTEN_PIK); +pik_dame->setze_wert(12); +kartenliste.append(pik_dame); + +// die koenige erstellen +// kreutz +Karte *kreutz_koenig = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/13c.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +kreutz_koenig->setObjectName(QString(KARTEN_KREUTZ) + "_" + KARTEN_KOENIG); +kreutz_koenig->setze_farbe(KARTEN_KREUTZ); +kreutz_koenig->setze_wert(13); +kartenliste.append(kreutz_koenig); + +// karo +Karte *karo_koenig = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/13d.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +karo_koenig->setObjectName(QString(KARTEN_KARO) + "_" + KARTEN_KOENIG); +karo_koenig->setze_farbe(KARTEN_KARO); +karo_koenig->setze_wert(13); +kartenliste.append(karo_koenig); + +// herz +Karte *herz_koenig = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/13h.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +herz_koenig->setObjectName(QString(KARTEN_HERZ) + "_" + KARTEN_KOENIG); +herz_koenig->setze_farbe(KARTEN_HERZ); +herz_koenig->setze_wert(13); +kartenliste.append(herz_koenig); + +// pik +Karte *pik_koenig = new Karte(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/13s.gif"), QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/back01.gif"), this); +pik_koenig->setObjectName(QString(KARTEN_PIK) + "_" + KARTEN_KOENIG); +pik_koenig->setze_farbe(KARTEN_PIK); +pik_koenig->setze_wert(13); +kartenliste.append(pik_koenig); + +// die stapel erzeugen ... +austeilstapel = new Austeilstapel(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/shade.gif"), this); +austeilstapel->setObjectName(BASISSTAPEL_AUSTEILSTAPEL); +austeilstapel->setZValue(0); + +austeilcostapel = new Austeilcostapel(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/shade.gif"), this); +austeilcostapel->setObjectName(BASISSTAPEL_AUSTEILCOSTAPEL); +austeilcostapel->setZValue(0); + +// austeilstapel und austeilcostapel gegenseitig registrieren +austeilstapel->registriere_costapel(austeilcostapel); +austeilcostapel->registriere_austeilstapel(austeilstapel); + +kreutzzielstapel = new Zielstapel(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/shade.gif"), this); +kreutzzielstapel->setObjectName(QString(KARTEN_KREUTZ) + BASISSTAPEL_ZIELSTAPEL); +kreutzzielstapel->setZValue(0); + +Rahmen *zielrahmen = new Rahmen(kreutzzielstapel); +kreutzzielstapel->registriere_rahmen(zielrahmen); +addItem(zielrahmen); + +pikzielstapel = new Zielstapel(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/shade.gif"), this); +pikzielstapel->setObjectName(QString(KARTEN_PIK) + BASISSTAPEL_ZIELSTAPEL); +pikzielstapel->setZValue(0); +pikzielstapel->registriere_rahmen(zielrahmen); + +karozielstapel = new Zielstapel(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/shade.gif"), this); +karozielstapel->setObjectName(QString(KARTEN_KARO) + BASISSTAPEL_ZIELSTAPEL); +karozielstapel->setZValue(0); +karozielstapel->registriere_rahmen(zielrahmen); + + +herzzielstapel = new Zielstapel(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/shade.gif"), this); +herzzielstapel->setObjectName(QString(KARTEN_HERZ) + BASISSTAPEL_ZIELSTAPEL); +herzzielstapel->setZValue(0); +herzzielstapel->registriere_rahmen(zielrahmen); + +// die zielstapel verknuepfen +kreutzzielstapel->registriere_nachbar_zielstapel(pikzielstapel, karozielstapel, herzzielstapel); +pikzielstapel->registriere_nachbar_zielstapel(kreutzzielstapel, karozielstapel, herzzielstapel); +karozielstapel->registriere_nachbar_zielstapel(kreutzzielstapel, pikzielstapel, herzzielstapel); +herzzielstapel->registriere_nachbar_zielstapel(kreutzzielstapel, pikzielstapel, karozielstapel); + +for (register int idx = 0; idx < SCENE_ABLAGE_STAPELZAHL; idx++) +{ +Basisstapel *tmp_stapel = new Ablagestapel(QPixmap(":/" + deckblatt + "/karten/" + deckblatt + "/shade.gif"), this); +tmp_stapel->setObjectName(QString(BASISSTAPEL_ABLAGESTAPEL) + "_" + QString::number(idx + 1)); +tmp_stapel->setZValue(0); + +// den rahmen fuer den stapel erzeugen +tmp_stapel->registriere_rahmen(zielrahmen); + +ablagestapel.append(tmp_stapel); +} + +// ... ihre positionen setzen +austeilstapel->setPos(SCENE_AUSGANGSBREITE / SCENE_AUSTEILSTAPEL_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +austeilcostapel->setPos(SCENE_AUSGANGSBREITE / SCENE_AUSTEILCOSTAPEL_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +kreutzzielstapel->setPos(SCENE_AUSGANGSBREITE / SCENE_KREUTZZIELSTAPEL_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +pikzielstapel->setPos(SCENE_AUSGANGSBREITE / SCENE_PIKZIELSTAPEL_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +karozielstapel->setPos(SCENE_AUSGANGSBREITE / SCENE_KAROZIELSTAPEL_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +herzzielstapel->setPos(SCENE_AUSGANGSBREITE / SCENE_HERZZIELSTAPEL_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +ablagestapel.at(0)->setPos(SCENE_AUSGANGSBREITE / SCENE_ABLAGESTAPEL_01_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(1)->setPos(SCENE_AUSGANGSBREITE / SCENE_ABLAGESTAPEL_02_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(2)->setPos(SCENE_AUSGANGSBREITE / SCENE_ABLAGESTAPEL_03_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(3)->setPos(SCENE_AUSGANGSBREITE / SCENE_ABLAGESTAPEL_04_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(4)->setPos(SCENE_AUSGANGSBREITE / SCENE_ABLAGESTAPEL_05_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(5)->setPos(SCENE_AUSGANGSBREITE / SCENE_ABLAGESTAPEL_06_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(6)->setPos(SCENE_AUSGANGSBREITE / SCENE_ABLAGESTAPEL_07_X_VERHAELTNIS, SCENE_AUSGANGSHOEHE / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); + +// ... und in die scene einfuegen +addItem(austeilstapel); +addItem(austeilcostapel); +addItem(kreutzzielstapel); +addItem(pikzielstapel); +addItem(karozielstapel); +addItem(herzzielstapel); + +for (register int idx = 0; idx < SCENE_ABLAGE_STAPELZAHL; idx++) addItem(ablagestapel.at(idx)); + +// eine liste erstellen, die alle stapel enthaelt +allestapel = ablagestapel; +allestapel.append(austeilstapel); +allestapel.append(austeilcostapel); +allestapel.append(kreutzzielstapel); +allestapel.append(pikzielstapel); +allestapel.append(karozielstapel); +allestapel.append(herzzielstapel); + +for (register int idx = 0; idx < kartenliste.size(); idx++) +{ +// die stapelliste an alle karten uebergeben +kartenliste.at(idx)->registriere_stapel(allestapel); + +// den karten die zielstapel mitteilen +kartenliste.at(idx)->registriere_zielstapel(kreutzzielstapel, pikzielstapel, herzzielstapel, karozielstapel); + +// alle karten in die scene einfuegen +addItem(kartenliste.at(idx)); +} + +// siegkontrolle erstellen ... +siegkontrolle = new Siegkontrolle(this); +siegkontrolle->setObjectName("siegkontrolle"); + +// ... und in den zielstapeln registrieren +kreutzzielstapel->registriere_siegkontrolle(siegkontrolle); +pikzielstapel->registriere_siegkontrolle(siegkontrolle); +karozielstapel->registriere_siegkontrolle(siegkontrolle); +herzzielstapel->registriere_siegkontrolle(siegkontrolle); + +// in siegkontrolle die zielstapel registrieren +siegkontrolle->registriere_zielstapel(kreutzzielstapel, pikzielstapel, herzzielstapel, karozielstapel); + +// punktezaehler erzeugen +punktezaehler = new Punktezaehler(this); +punktezaehler->setObjectName("punktezaehler"); + +// spieltimer erstellen +spieltimer = new QTimer(this); +spieltimer->setInterval(1000); + +// die auffindhilfen aufbauen +for (register int idx = 0; idx < allestapel.size(); idx++) stapelfinder.insert(allestapel.at(idx)->objectName(), allestapel.at(idx)); +for (register int idx = 0; idx < kartenliste.size(); idx++) kartenfinder.insert(kartenliste.at(idx)->objectName(), kartenliste.at(idx)); + +// undo erstellen +undo = new Undo(this); +undo->setObjectName("undo"); + +// signal - slot verbindungen +// bei spielende (sieg) sollen alle karten blockert werden +connect(siegkontrolle, SIGNAL(gewonnen()), this, SLOT(blockiere_alle_karten())); + +// alle stapel am punktezaehler anschliessen, damit die stapel zuege an punktzaehler melden koennen +for (register int idx = 0; idx < allestapel.size(); idx++) +{ +connect(allestapel.at(idx), SIGNAL(zug(const Zug&)), punktezaehler, SLOT(neuer_zug(const Zug&))); +} + + + +// verbindungen herstellen, die alle karten betreffen +for (register int idx = 0; idx < kartenliste.size(); idx++) +{ +for (register int ablagestapelidx = 0; ablagestapelidx < ablagestapel.size(); ablagestapelidx++) +{ +// allen karten das senden von hilfsanfragen ermoeglichen +// das starten von hilfsanfragen ermoeglichen +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_start(Karte*)), ablagestapel.at(ablagestapelidx), SLOT(hilfsanfrage_start(Karte*))); + +// das stoppen von hilfsanfragen ermoeglichen +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_ende()), ablagestapel.at(ablagestapelidx), SLOT(hilfsanfrage_ende())); +} + +// das starten von hilfsanfragen ermoeglichen +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_start(Karte*)), herzzielstapel, SLOT(hilfsanfrage_start(Karte*))); +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_start(Karte*)), karozielstapel, SLOT(hilfsanfrage_start(Karte*))); +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_start(Karte*)), pikzielstapel, SLOT(hilfsanfrage_start(Karte*))); +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_start(Karte*)), kreutzzielstapel, SLOT(hilfsanfrage_start(Karte*))); + +// das stoppen von hilfsanfragen ermoeglichen +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_ende()), herzzielstapel, SLOT(hilfsanfrage_ende())); +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_ende()), karozielstapel, SLOT(hilfsanfrage_ende())); +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_ende()), pikzielstapel, SLOT(hilfsanfrage_ende())); +connect(kartenliste.at(idx), SIGNAL(hilfsanfrage_ende()), kreutzzielstapel, SLOT(hilfsanfrage_ende())); + +// allen karten das verstecken des zielrahmens ermoeglichen und das steuern der sichtbarkeit des rahmens ermoeglichen +connect(kartenliste.at(idx), SIGNAL(rahmen_verstecken()), zielrahmen, SLOT(verstecke())); +connect(this, SIGNAL(rahmen_anzeigen(bool)), kartenliste.at(idx), SLOT(sichtbarkeit_rahmen(bool))); + +// das skalieren der kartengroesse ermoeglichen +connect(this, SIGNAL(neue_groesse_karten(double)), kartenliste.at(idx), SLOT(passe_groesse_an(double))); +} + + + +// den punktezaehler ueber den start neuer spiele unterrichten +connect(this, SIGNAL(neues_spiel_gestartet()), punktezaehler, SLOT(neues_spiel())); + +// den punktezaehler ueber spielende unterrichten +connect(siegkontrolle, SIGNAL(gewonnen()), punktezaehler, SLOT(spiel_zuende())); + +// punktezaehler das melden der punktzahl ermoeglichen +connect(punktezaehler, SIGNAL(neue_punktzahl(int)), this, SIGNAL(neue_punktzahl(int))); + +// wenn bei austeilstapel der stapel durch ist dies an punktzaehler melden +connect(austeilstapel, SIGNAL(stapel_durch()), punktezaehler, SLOT(stapel_durch())); + +// starten und stoppen von spieltimer ermoeglichen. erste der erste zug startet die zeit +connect(punktezaehler, SIGNAL(erster_zug()), this, SLOT(starte_spieltimer())); +connect(siegkontrolle, SIGNAL(gewonnen()), this, SLOT(stoppe_spieltimer())); + +// reaktionen auf spieltimer ermoeglichen +connect(spieltimer, SIGNAL(timeout()), this, SLOT(reaktionen_auf_spieltimer())); + +// das durchreichen von siegmeldungen ermoeglichen +connect(siegkontrolle, SIGNAL(gewonnen()), this, SLOT(gewonnen_relay())); + +// wenn ein neues spiel gestartet wird, muss austeilcostapel die ablagenummer resetten +connect(this, SIGNAL(neues_spiel_gestartet()), austeilcostapel, SLOT(resette_ablagenummer())); + +// austeilstapel und austeilcostapel sollen den spieltyp kennen +connect(this, SIGNAL(relay_eine_ziehen()), austeilstapel, SLOT(eine_ziehen())); +connect(this, SIGNAL(relay_eine_ziehen()), austeilcostapel, SLOT(eine_ziehen())); +connect(this, SIGNAL(relay_drei_ziehen()), austeilstapel, SLOT(drei_ziehen())); +connect(this, SIGNAL(relay_drei_ziehen()), austeilcostapel, SLOT(drei_ziehen())); + +// auch der punktezaehler soll den spieltyp kennen +connect(this, SIGNAL(relay_eine_ziehen()), punktezaehler, SLOT(eine_ziehen())); +connect(this, SIGNAL(relay_drei_ziehen()), punktezaehler, SLOT(drei_ziehen())); + +// allen ablagestapel stapel ausser austeilstapel an undo anschliessen +for (register int idx = 0; idx < ablagestapel.size(); idx++) +{ +connect(ablagestapel.at(idx), SIGNAL(zug(const Zug&)), undo, SLOT(speichere_zug(const Zug&))); +} + +connect(austeilcostapel, SIGNAL(zug(const Zug&)), undo, SLOT(speichere_zug(const Zug&))); +connect(herzzielstapel, SIGNAL(zug(const Zug&)), undo, SLOT(speichere_zug(const Zug&))); +connect(karozielstapel, SIGNAL(zug(const Zug&)), undo, SLOT(speichere_zug(const Zug&))); +connect(pikzielstapel, SIGNAL(zug(const Zug&)), undo, SLOT(speichere_zug(const Zug&))); +connect(kreutzzielstapel, SIGNAL(zug(const Zug&)), undo, SLOT(speichere_zug(const Zug&))); + +// undo meldungen an punktezaehler ermoeglichen +connect(undo, SIGNAL(undo_meldung(const Zug&)), punktezaehler, SLOT(undo_meldung(const Zug&))); + +// verfuegbarkeit von undo melden +connect(undo, SIGNAL(undo_verfuegbar(bool)), this, SIGNAL(undo_verfuegbar(bool))); + +// verbindungen, die alle stapel betreffen +for (register int idx = 0; idx < allestapel.size(); idx++) +{ +// groessenanpassung aller stapel ermoeglichen +connect(this, SIGNAL(neue_groesse_karten(double)), allestapel.at(idx), SLOT(passe_groesse_an(double))); +} +} + + +Scene::~Scene() +{ +} + + +QList Scene::mischen() const +{ +QList gemischt, mischquelle(kartenliste); + +while (mischquelle.isEmpty() == false) gemischt.append(mischquelle.takeAt(Random::random(0, mischquelle.size() - 1))); + +if (mischquelle.isEmpty() == false) +{ +qDebug() << tr("Missing Cards in Scene !"); + +exit(1); +} + +return gemischt; +} + + +void Scene::neues_spiel() +{ +// zunaechst den spieltimer stoppen +stoppe_spieltimer(); + +// die verstrichenen sekunden ohne den spieltimer auf 0 setzen, weil die startzeit noch vom letzten spiel stammt und dies zu falschen werten fuehren wuerde. dies wird, wenn punktzaehler den ersten zug meldet angepasst +emit verstrichene_sekunden(0); + +// das spielfeld aufraeumen +setze_spiel_zurueck(); + +// die karten mischen +QList aufbauliste(mischen()); + +// 1 karte auf den ersten ablagestapel legen +ablagestapel.at(0)->initialisiere_karte(aufbauliste.takeFirst()); + +// 2 karte auf den zweiten ablagestapel legen +for (register int idx = 0; idx < 2; idx++) ablagestapel.at(1)->initialisiere_karte(aufbauliste.takeFirst()); + +// 3 karte auf den dritten ablagestapel legen +for (register int idx = 0; idx < 3; idx++) ablagestapel.at(2)->initialisiere_karte(aufbauliste.takeFirst()); + +// 4 karte auf den vierten ablagestapel legen +for (register int idx = 0; idx < 4; idx++) ablagestapel.at(3)->initialisiere_karte(aufbauliste.takeFirst()); + +// 5 karte auf den fuenften ablagestapel legen +for (register int idx = 0; idx < 5; idx++) ablagestapel.at(4)->initialisiere_karte(aufbauliste.takeFirst()); + +// 6 karte auf den sechsten ablagestapel legen +for (register int idx = 0; idx < 6; idx++) ablagestapel.at(5)->initialisiere_karte(aufbauliste.takeFirst()); + +// 7 karte auf den siebten ablagestapel legen +for (register int idx = 0; idx < 7; idx++) ablagestapel.at(6)->initialisiere_karte(aufbauliste.takeFirst()); + +// die restlichen karten auf den austeilstapel legen +while (aufbauliste.isEmpty() == false) austeilstapel->initialisiere_karte(aufbauliste.takeFirst()); + +// die obersten karten auf den ablagestapeln aufdecken +for (register int idx = 0; idx < ablagestapel.size(); idx++) +{ +if (ablagestapel.at(idx)->oberste_karte() != 0) ablagestapel.at(idx)->oberste_karte()->zeige_vorderseite(); +} + +// undo leeren. damit wird undo auch gleich blockiert. +undo->clear(); + +Laufendes_spiel = true; + +emit neues_spiel_gestartet(); +} + + +void Scene::alle_karten_verdecken() +{ +for (register int idx = 0; idx < kartenliste.size(); idx++) kartenliste.at(idx)->zeige_rueckseite(); +} + + +void Scene::setze_spiel_zurueck() +{ +// undo leeren. damit wird undo auch gleich blockiert. +undo->clear(); + +// alle karten sollen wieder die rueckseite zeigen +alle_karten_verdecken(); + +for (register int idx = 0; idx < kartenliste.size(); idx++) +{ +// meinstapel wieder zuruecksetzen +kartenliste.at(idx)->setze_meinstapel(0); + +// die rueckkehrkoordinaten zuruecksetzen +kartenliste.at(idx)->setze_rueckehrkoordinaten(QPointF(0, 0)); +} + +// die kartenlisten der stapel zuruecksetzen +for (register int idx = 0; idx < allestapel.size(); idx++) allestapel.at(idx)->setze_kartenliste_zurueck(); +} + + +void Scene::blockiere_alle_karten() +{ +// undo leeren. damit wird undo auch gleich blockiert. +undo->clear(); + +Laufendes_spiel = false; + +for (register int idx = 0; idx < kartenliste.size(); idx++) kartenliste.at(idx)->setFlag(QGraphicsItem::ItemIsMovable, false); +} + + +bool Scene::laufendes_spiel() const +{ +return Laufendes_spiel; +} + + +void Scene::lade_franzoesisches_deckblatt() +{ +// sicherstellen, das alle 52 karten vorhanden sind +if (kartenliste.size() == 52) +{ +int idx = 0; + +// die franzoesischen kartenbilder laden +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/01c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/01d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/01h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/01s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/02c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/02d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/02h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/02s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/03c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/03d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/03h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/03s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/04c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/04d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/04h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/04s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/05c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/05d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/05h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/05s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/06c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/06d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/06h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/06s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/07c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/07d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/07h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/07s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/08c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/08d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/08h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/08s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/09c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/09d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/09h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/09s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/10c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/10d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/10h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/10s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/11c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/11d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/11h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/11s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/12c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/12d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/12h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/12s.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/13c.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/13d.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/13h.gif"), QPixmap(":/french/karten/french/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/french/karten/french/13s.gif"), QPixmap(":/french/karten/french/back01.gif")); +} +} + + +void Scene::lade_deutsches_deckblatt() +{ +// sicherstellen, das alle 52 karten vorhanden sind +if (kartenliste.size() == 52) +{ +int idx = 0; + +// die deutschen kartenbilder laden +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/01c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/01d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/01h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/01s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/02c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/02d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/02h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/02s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/03c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/03d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/03h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/03s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/04c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/04d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/04h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/04s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/05c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/05d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/05h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/05s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/06c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/06d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/06h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/06s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/07c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/07d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/07h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/07s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/08c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/08d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/08h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/08s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/09c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/09d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/09h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/09s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/10c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/10d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/10h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/10s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/11c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/11d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/11h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/11s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/12c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/12d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/12h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/12s.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/13c.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/13d.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/13h.gif"), QPixmap(":/german/karten/german/back01.gif")); +kartenliste.at(idx++)->setze_kartenbilder(QPixmap(":/german/karten/german/13s.gif"), QPixmap(":/german/karten/german/back01.gif")); +} +} + + +void Scene::starte_spieltimer() +{ +// den startzeitpunkt erfassen +startzeitpunkt = QDateTime::currentDateTime(); + +// den timer zur aktualisierung der spielzeit starten +spieltimer->start(); + +// die berechnete zeit einmal sofort senden +reaktionen_auf_spieltimer(); +} + + +void Scene::stoppe_spieltimer() +{ +spieltimer->stop(); +} + + +void Scene::reaktionen_auf_spieltimer() +{ +emit verstrichene_sekunden(startzeitpunkt.secsTo(QDateTime::currentDateTime())); +} + + +void Scene::gewonnen_relay() +{ +// die daten fuer eine vollstaendige siegmeldung senden +emit gewonnen(punktezaehler->punktstand(), startzeitpunkt.secsTo(QDateTime::currentDateTime())); +} + + +void Scene::eine_ziehen() +{ +nur_eine_ziehen = true; + +emit relay_eine_ziehen(); +} + + +void Scene::drei_ziehen() +{ +nur_eine_ziehen = false; + +emit relay_drei_ziehen(); +} + + +bool Scene::nur_eine_wird_gezogen() const +{ +return nur_eine_ziehen; +} + + +void Scene::initialisiere_rahmen(bool wert) +{ +emit rahmen_anzeigen(wert); +} + + +void Scene::rueckgaengig() +{ +undo->undo(); +} + + +Karte* Scene::suche_karte(const QString& name) const +{ +Karte *erg = 0; + +if (kartenfinder.contains(name) == true) erg = kartenfinder.value(name); + +return erg; +} + + +const QStringList Scene::speichere() const +{ +QStringList erg; + +// die id speichern +erg.append(objectName()); + +// nur_eine_ziehen speichern +erg.append(QString::number(nur_eine_ziehen)); + +// die verstrichene zeit speichern +erg.append(QString::number(startzeitpunkt.secsTo(QDateTime::currentDateTime()))); + +return erg; +} + + +bool Scene::lade(const QStringList& daten) +{ +bool erg = false; + +if (daten.size() == SCENE_ANZAHL_SPEICHERELEMENTE && daten.first() == objectName()) +{ +erg = true; + +// nur_eine_ziehen laden +nur_eine_ziehen = daten.at(SCENE_EINE_ZIEHEN_IDX).toInt(); + +// eine zur verstrichenen zeit passende startzeit berechnen +startzeitpunkt = QDateTime::currentDateTime().addSecs(-daten.at(SCENE_VERSTRICHENE_ZEIT_IDX).toInt()); +} + +return erg; +} + + +void Scene::registriere_einstellungen(QSettings* einstellungen_) +{ +einstellungen = einstellungen_; +} + + +void Scene::lade_spielstand() +{ +bool erg = true; + +// den zustand der scene laden +erg = lade(einstellungen->value("Spielstand/" + objectName(), QStringList()).toStringList()); + +if (erg == false) qDebug() << tr("Unable to restore scene !"); + +// den zustand der stapel laden +if (erg == true) +{ +for (register int idx = 0; idx < allestapel.size() && erg == true; idx++) erg = allestapel.at(idx)->lade(einstellungen->value("Spielstand/" + allestapel.at(idx)->objectName(), QStringList()).toStringList()); + +if (erg == false) qDebug() << tr("Unable to restore stacks !"); +} + +// den zustand der karten laden +if (erg == true) +{ +for (register int idx = 0; idx < kartenliste.size() && erg == true; idx++) erg = kartenliste.at(idx)->lade(einstellungen->value("Spielstand/" + kartenliste.at(idx)->objectName(), QStringList()).toStringList()); + +if (erg == false) qDebug() << tr("Unable to restore cards !"); +} + +// den zustand von undo laden +if (erg == true) +{ +erg = undo->lade(einstellungen->value("Spielstand/" + undo->objectName(), QStringList()).toStringList()); + +if (erg == false) qDebug() << tr("Unable to restore undo !"); +} + +// den zustand des punktezaehlers laden +if (erg == true) +{ +erg = punktezaehler->lade(einstellungen->value("Spielstand/" + punktezaehler->objectName(), QStringList()).toStringList()); + +if (erg == false) qDebug() << tr("Unable to restore points !"); +} + +// testen, ob alle karten einen eigentuemer stapel haben +if (erg == true) +{ +for (register int idx = 0; idx < kartenliste.size() && erg == true; idx++) if (kartenliste.at(idx)->eigentuemer_stapel() == 0) erg = false; + +if (erg == false) qDebug() << tr("Card with 0 batch after restoring gamestate !"); +} + +// die pruefsumme des geladenen spiels testen +if (erg == true) +{ +if (berechne_pruefsumme_spielstand() != einstellungen->value(QString("Spielstand/") + "pruefsumme", QByteArray()).toByteArray()) +{ +erg = false; + +qDebug() << tr("Wrong checksumm while restoring saved game !"); +} +} + +if (erg == true) +{ +Laufendes_spiel = true; + +spieltimer->start(); + +emit verstrichene_sekunden(startzeitpunkt.secsTo(QDateTime::currentDateTime())); +} + +// wenn beim laden etwas schief gegangen ist ein neues spiel starten +else +{ +if (erg == false) qDebug() << tr("Unable to restore saved game. Trying to start a new game ..."); + +neues_spiel(); +} +} + + +void Scene::speichere_spielstand() +{ +// den zustand der scene speichern +einstellungen->setValue("Spielstand/" + objectName(), speichere()); + +// den zustand der stapel speichern +for (register int idx = 0; idx < allestapel.size(); idx++) einstellungen->setValue("Spielstand/" + allestapel.at(idx)->objectName(), allestapel.at(idx)->speichere()); + +// den zustand der karten speichern +for (register int idx = 0; idx < kartenliste.size(); idx++) einstellungen->setValue("Spielstand/" + kartenliste.at(idx)->objectName(), kartenliste.at(idx)->speichere()); + +// den zustand von undo speichern +einstellungen->setValue("Spielstand/" + undo->objectName(), undo->speichere()); + +// den zustand des punktezaehlers speichern +einstellungen->setValue("Spielstand/" + punktezaehler->objectName(), punktezaehler->speichere()); + +// die md5 des spielstands speichern +einstellungen->setValue(QString("Spielstand/") + "pruefsumme", berechne_pruefsumme_spielstand()); +} + + +bool Scene::begonnenes_spiel() const +{ +return punktezaehler->begonnenes_spiel(); +} + + +Basisstapel* Scene::suche_stapel(const QString& name) const +{ +Basisstapel *stapel = 0; + +if (stapelfinder.contains(name) == true) stapel = stapelfinder.value(name); + +return stapel; +} + + +bool Scene::enthaelt_karte(const QString& name) const +{ +return kartenfinder.contains(name); +} + + +bool Scene::enthaelt_stapel(const QString& name) const +{ +return stapelfinder.contains(name); +} + + +const QByteArray Scene::berechne_pruefsumme_spielstand() +{ +QByteArray erg; +QCryptographicHash hash(QCryptographicHash::Sha1); + +// den wert von scene abfragen +hash.addData(einstellungen->value("Spielstand/" + objectName(), QByteArray()).toByteArray()); + +// den wert der stapel abfragen +for (register int idx = 0; idx < allestapel.size(); idx++) hash.addData(einstellungen->value("Spielstand/" + allestapel.at(idx)->objectName(), QByteArray()).toByteArray()); + +// den wert von karten abfragen +for (register int idx = 0; idx < kartenliste.size(); idx++) hash.addData(einstellungen->value("Spielstand/" + kartenliste.at(idx)->objectName(), QByteArray()).toByteArray()); + +// den wert von undo abfragen +hash.addData(einstellungen->value("Spielstand/" + undo->objectName(), QByteArray()).toByteArray()); + +// den wert von punktezaehlers abfragen +hash.addData(einstellungen->value("Spielstand/" + punktezaehler->objectName(), QByteArray()).toByteArray()); + +erg = hash.result(); + +return erg; +} + + +void Scene::groessenanpassung(QResizeEvent* event) +{ +if (event->size().width() > 0 && event->size().height() > 0) +{ +double breite = event->size().width(), hoehe = event->size().height(); + +if (hoehe > (breite / SCENE_VERHAELTNIS_BREITE_ZU_HOEHE)) hoehe = breite / SCENE_VERHAELTNIS_BREITE_ZU_HOEHE; + +setSceneRect(QRectF(0, 0, event->size().width() - 5, event->size().height() - 5)); + +austeilstapel->setPos(breite / SCENE_AUSTEILSTAPEL_X_VERHAELTNIS, hoehe / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +austeilcostapel->setPos(breite / SCENE_AUSTEILCOSTAPEL_X_VERHAELTNIS, hoehe / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +kreutzzielstapel->setPos(breite / SCENE_KREUTZZIELSTAPEL_X_VERHAELTNIS, hoehe / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +pikzielstapel->setPos(breite / SCENE_PIKZIELSTAPEL_X_VERHAELTNIS, hoehe / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +karozielstapel->setPos(breite / SCENE_KAROZIELSTAPEL_X_VERHAELTNIS, hoehe / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +herzzielstapel->setPos(breite / SCENE_HERZZIELSTAPEL_X_VERHAELTNIS, hoehe / SCENE_OBERE_STAPEL_Y_VERHAELTNIS); +ablagestapel.at(0)->setPos(breite / SCENE_ABLAGESTAPEL_01_X_VERHAELTNIS, hoehe / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(1)->setPos(breite / SCENE_ABLAGESTAPEL_02_X_VERHAELTNIS, hoehe / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(2)->setPos(breite / SCENE_ABLAGESTAPEL_03_X_VERHAELTNIS, hoehe / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(3)->setPos(breite / SCENE_ABLAGESTAPEL_04_X_VERHAELTNIS, hoehe / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(4)->setPos(breite / SCENE_ABLAGESTAPEL_05_X_VERHAELTNIS, hoehe / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(5)->setPos(breite / SCENE_ABLAGESTAPEL_06_X_VERHAELTNIS, hoehe / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); +ablagestapel.at(6)->setPos(breite / SCENE_ABLAGESTAPEL_07_X_VERHAELTNIS, hoehe / SCENE_ABLAGESTAPEL_Y_VERHAELTNIS); + +emit neue_groesse_karten(hoehe / SCENE_HOEHE_ZU_KARTENHOEHE); +} +} diff --git a/plugins/patience_plugin/Patience/Scene.h b/plugins/patience_plugin/Patience/Scene.h new file mode 100644 index 000000000..de3250550 --- /dev/null +++ b/plugins/patience_plugin/Patience/Scene.h @@ -0,0 +1,90 @@ +#ifndef SCENE_H +#define SCENE_H + +#include +#include +#include +#include +#include + +class Karte; +class Basisstapel; +class Ablagestapel; +class Siegkontrolle; +class Punktezaehler; +class QTimer; +class Undo; +class QSettings; +class QResizeEvent; + +class Scene : public QGraphicsScene +{ +Q_OBJECT + +public: +Scene(const QString& deckblatt, QObject *parent = 0); +virtual ~Scene(); + +QList mischen() const; +void alle_karten_verdecken(); +bool laufendes_spiel() const; +bool nur_eine_wird_gezogen() const; +void initialisiere_rahmen(bool); +Karte* suche_karte(const QString&) const; +Basisstapel *suche_stapel(const QString&) const; +bool enthaelt_karte(const QString&) const; +bool enthaelt_stapel(const QString&) const; +const QStringList speichere() const; +bool lade(const QStringList&); +void registriere_einstellungen(QSettings*); +void lade_spielstand(); +void speichere_spielstand(); +bool begonnenes_spiel() const; +void groessenanpassung(QResizeEvent*); + +public slots: +void setze_spiel_zurueck(); +void neues_spiel(); +void lade_franzoesisches_deckblatt(); +void lade_deutsches_deckblatt(); +void eine_ziehen(); +void drei_ziehen(); +void rueckgaengig(); + +signals: +void gewonnen(int, long); +void neues_spiel_gestartet(); +void neue_punktzahl(int); +void verstrichene_sekunden(long); +void relay_eine_ziehen(); +void relay_drei_ziehen(); +void rahmen_anzeigen(bool); +void undo_verfuegbar(bool); +void neue_groesse_karten(double); + +private slots: +void blockiere_alle_karten(); +void starte_spieltimer(); +void stoppe_spieltimer(); +void reaktionen_auf_spieltimer(); +void gewonnen_relay(); + +private: +QList kartenliste; +QMap kartenfinder; +Basisstapel *austeilstapel, *austeilcostapel, *kreutzzielstapel, *pikzielstapel, *karozielstapel, *herzzielstapel; +QList ablagestapel; +QList allestapel; +QMap stapelfinder; +Siegkontrolle *siegkontrolle; +bool Laufendes_spiel, nur_eine_ziehen; +Punktezaehler *punktezaehler; +QTimer *spieltimer; +QDateTime startzeitpunkt; +Undo *undo; +QSettings *einstellungen; + +const QByteArray berechne_pruefsumme_spielstand(); +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Screenshot unter OSX.png b/plugins/patience_plugin/Patience/Screenshot unter OSX.png new file mode 100644 index 000000000..634d17511 Binary files /dev/null and b/plugins/patience_plugin/Patience/Screenshot unter OSX.png differ diff --git a/plugins/patience_plugin/Patience/Siegkontrolle.cpp b/plugins/patience_plugin/Patience/Siegkontrolle.cpp new file mode 100644 index 000000000..1d240bcb6 --- /dev/null +++ b/plugins/patience_plugin/Patience/Siegkontrolle.cpp @@ -0,0 +1,29 @@ +#include "Siegkontrolle.h" +#include "Basisstapel.h" + +using namespace std; + +Siegkontrolle::Siegkontrolle(QObject *parent) : QObject(parent) +{ +} + + +Siegkontrolle::~Siegkontrolle() +{ +} + + +void Siegkontrolle::teste_auf_sieg() +{ +// wenn alle zielstapel 13 karten enthalten hat der spieler gewonnen +if (zielstapel.at(0)->karten() == 13 && zielstapel.at(1)->karten() == 13 && zielstapel.at(2)->karten() == 13 && zielstapel.at(3)->karten() == 13) emit gewonnen(); +} + + +void Siegkontrolle::registriere_zielstapel(Basisstapel* kreutzstapel, Basisstapel* pikstapel, Basisstapel* herzstapel, Basisstapel* karostapel) +{ +zielstapel.append(kreutzstapel); +zielstapel.append(pikstapel); +zielstapel.append(herzstapel); +zielstapel.append(karostapel); +} diff --git a/plugins/patience_plugin/Patience/Siegkontrolle.h b/plugins/patience_plugin/Patience/Siegkontrolle.h new file mode 100644 index 000000000..f2efb626d --- /dev/null +++ b/plugins/patience_plugin/Patience/Siegkontrolle.h @@ -0,0 +1,27 @@ +#ifndef SIEGKONTROLLE_H +#define SIEGKONTROLLE_H + +#include + +class Basisstapel; +class Karte; + +class Siegkontrolle : public QObject +{ +Q_OBJECT + +public: +Siegkontrolle(QObject *parent = 0); +virtual ~Siegkontrolle(); + +void teste_auf_sieg(); +void registriere_zielstapel(Basisstapel* kreutzstapel, Basisstapel* pikstapel, Basisstapel* herzstapel, Basisstapel *karostapel); + +signals: +void gewonnen(); + +private: +QList zielstapel; +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Speichern_frage.cpp b/plugins/patience_plugin/Patience/Speichern_frage.cpp new file mode 100644 index 000000000..13bd77d2b --- /dev/null +++ b/plugins/patience_plugin/Patience/Speichern_frage.cpp @@ -0,0 +1,98 @@ +#include "Speichern_frage.h" + +using namespace std; + +Speichern_frage::Speichern_frage(QWidget *parent) : QDialog(parent), speichern_wert(true) +{ +setupUi(this); + +// das resultat voreinstellen +setResult(QDialog::Accepted); + +// die groesse des dialogs auf size hint feststellen +setFixedSize(sizeHint()); + +// signal - slot verbindungen +// die buttons ermoeglichen +connect(nein_button, SIGNAL(clicked()), this, SLOT(nicht_speichern())); +connect(cancel_button, SIGNAL(clicked()), this, SLOT(abbruch())); +connect(ok_button, SIGNAL(clicked()), this, SLOT(speichern())); + +connect(merk_box, SIGNAL(toggled(bool)), this, SLOT(releay_verbindung_merk_status(bool))); +} + + +Speichern_frage::~Speichern_frage() +{ +} + + +void Speichern_frage::speichern() +{ +speichern_wert = true; + +emit wird_gespeichert(true); + +accept(); +} + + +void Speichern_frage::nicht_speichern() +{ +speichern_wert = false; + +emit wird_nicht_gespeichert(true); + +accept(); +} + + +void Speichern_frage::abbruch() +{ +merk_box->setChecked(false); + +reject(); +} + + +void Speichern_frage::setze_merken(bool wert) +{ +if (wert == true) setResult(QDialog::Accepted); + +merk_box->setChecked(wert); + +emit verbindung_merk_status(!wert); +} + + +bool Speichern_frage::soll_merken() const +{ +return merk_box->isChecked(); +} + + +void Speichern_frage::setze_speichern(bool wert) +{ +speichern_wert = wert; + +if (wert == true) ok_button->click(); +else nein_button->click(); +} + + +bool Speichern_frage::soll_speichern() const +{ +return speichern_wert; +} + + +void Speichern_frage::verbindung_merken(bool wert) +{ +setze_merken(!wert); +} + + +void Speichern_frage::releay_verbindung_merk_status(bool wert) +{ +emit verbindung_merk_status(!wert); +} diff --git a/plugins/patience_plugin/Patience/Speichern_frage.h b/plugins/patience_plugin/Patience/Speichern_frage.h new file mode 100644 index 000000000..3ea690859 --- /dev/null +++ b/plugins/patience_plugin/Patience/Speichern_frage.h @@ -0,0 +1,38 @@ +#ifndef SPEICHERN_FRAGE_H +#define SPEICHERN_FRAGE_H + +#include +#include "ui_Speichern_frage.h" + +class Speichern_frage : public QDialog, private Ui::Speichern_frage +{ +Q_OBJECT + +public: +Speichern_frage(QWidget *parent = 0); +virtual ~Speichern_frage(); + +bool soll_merken() const; +bool soll_speichern() const; + +public slots: +void setze_merken(bool); +void setze_speichern(bool); +void verbindung_merken(bool); + +private slots: +void speichern(); +void nicht_speichern(); +void abbruch(); +void releay_verbindung_merk_status(bool); + +signals: +void verbindung_merk_status(bool); +void wird_gespeichert(bool); +void wird_nicht_gespeichert(bool); + +private: +bool speichern_wert; +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Speichern_frage.ui b/plugins/patience_plugin/Patience/Speichern_frage.ui new file mode 100644 index 000000000..c9346f970 --- /dev/null +++ b/plugins/patience_plugin/Patience/Speichern_frage.ui @@ -0,0 +1,165 @@ + + + Speichern_frage + + + Qt::WindowModal + + + + 0 + 0 + 365 + 127 + + + + Patience - Save game and quit ? + + + + 5 + + + 5 + + + 5 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 21 + + + + Save the game and quit ? + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Don't Save + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Cancel + + + false + + + true + + + + + + + OK + + + false + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 15 + + + + Qt::RightToLeft + + + Remember answer + + + + + + + + + + diff --git a/plugins/patience_plugin/Patience/Uebersetzung_de.qm b/plugins/patience_plugin/Patience/Uebersetzung_de.qm new file mode 100644 index 000000000..2db9e62a1 Binary files /dev/null and b/plugins/patience_plugin/Patience/Uebersetzung_de.qm differ diff --git a/plugins/patience_plugin/Patience/Uebersetzung_de.ts b/plugins/patience_plugin/Patience/Uebersetzung_de.ts new file mode 100644 index 000000000..9c0f9e680 --- /dev/null +++ b/plugins/patience_plugin/Patience/Uebersetzung_de.ts @@ -0,0 +1,364 @@ + + + + + Highscore + + + Patience + Patience + + + + You got a Highscore ! + Du hast eine Highscore ! + + + + + Unknown + Unbekannt + + + + Patience - Highscore + Patience - Highscore + + + + Name + Name + + + + Points + Poits + Punkte + + + + Time + Zeit + + + + Ok + Fertig + + + + Karte + + + + The Card + Die Karte + + + + + have more than one Child Card + hat mehr als eine Kinder Karte + + + + MainWindow + + + Patience - You won ! + Patience - Du hast gewonnen ! + + + + You won, but you don't reach a highscore. + Du hast gewonnen, es hat jedoch zu keiner Highscore gereicht. + + + + Patience - Start new game ? + Patience - Wirklich ein neues Spiel starten ? + + + + Start a new Game and break the current Game ? + Wirklich ein neues Spiel starten und das momentane Spiel beenden ? + + + + + About Patience + Über Patience + + + + Patience Version + Patience Version + + + + Points + Punkte + Punkte + + + + Patience + Patience + + + + Game + Spiel + + + + &Help + &Hilfe + + + + &Cardset + &Kartentyp + + + + &Highscore + &Highscore + + + + Gametype + Spieltyp + + + + &Settings + &Einstellungen + + + + Save Game + Spiel speichern + + + + &Edit + &Bearbeiten + + + + &New Game + &Neues Spiel + + + + Ctrl+N + Ctrl+N + + + + Close + Schliessen + + + + About QT + Über QT + + + + + French + Französisch + + + + + German + Deutsch + + + + &Show + &Anzeigen + + + + + Take One + Eine ziehen + + + + + Take Three + Drei ziehen + + + + Frame + Rahmen + + + + Ask + Fragen + + + + Save + Speichern + + + + Don't save + Nicht speichern + + + Ask for saving on quit. + Ask for saving on quit + Beim beenden wegen speichern fragen. + + + Disable for slow computers. + Für langsame Computer deaktivieren. + + + + Undo + Rückgängig + + + + Punktezaehler + + + Invalid move in Punktzaehler::neuer_zug() + Ungültiger zug in Punktzaehler::neuer_zug() + + + + Invalid move in Punktzaehler::kalkuliere_punkte(const Zug& zug) + Ungültiger zug in Punktzaehler::kalkuliere_punkte(const Zug& zug) + + + + Invalid move in Punktzaehler::bringt_zeitaufschub(const Zug& zug) + Ungültiger zug in Punktzaehler::bringt_zeitaufschub(const Zug& zug) + + + + QObject + + + min is bigger than max ! + min ist größer als max ! + + + + Scene + + + Missing Cards in Scene ! + Fehlende Karte in Scene ! + + + + Unable to restore scene ! + Kann Scene nicht wiederherstellen ! + + + + Unable to restore stacks ! + Kann Stapel nicht wiederherstellen ! + + + + Unable to restore cards ! + Kann Karten nicht wiederherstellen ! + + + + Unable to restore undo ! + Kann Undo nicht wiederherstellen ! + + + + Unable to restore points ! + Kann Punkte nicht wiederherstellen ! + + + + Card with 0 batch after restoring gamestate ! + Karte mit 0 Eigentümer Stapel nach dem wiederherstellen eines Spielstandes ! + + + + Wrong checksumm while restoring saved game ! + Falsche Prüfsumme beim wiederherstellen des Spielstandes ! + + + + Unable to restore saved game. Trying to start a new game ... + Das gespeicherte Spiel kann nicht wiederhergestellt werden. Versuche ein neues Spiel zu starten ... + + + + Speichern_frage + + + Patience - Save game and quit ? + Patience - Spiel beenden und speichern ? + + + + Save the game and quit ? + Spiel beenden & speichern ? + + + + Don't Save + Nicht speichern + + + + Cancel + Abbrechen + + + + OK + OK + + + + Remember answer + Antwort merken + + + + Undo + + + + Invalid move in Undo::undo() + Ungültiger zug in Undo::undo() + + + Invalid cover in Undo::undo() + Ungültige Karten zudeckung in Undo::undo() + + + Invalid history entry in Undo + Ungültiger History Eintrag in Undo + + + + Zielstapel + + + Destination not found in Zielstapel::lege_karte_ab(Karte* karte) + Zielstapel nicht auffindbar in Zielstapel::lege_karte_ab(Karte* karte) + + + diff --git a/plugins/patience_plugin/Patience/Undo.cpp b/plugins/patience_plugin/Patience/Undo.cpp new file mode 100644 index 000000000..28cfc9a0c --- /dev/null +++ b/plugins/patience_plugin/Patience/Undo.cpp @@ -0,0 +1,194 @@ +#include "Undo.h" +#include "Karte.h" +#include "Basisstapel.h" +#include "Scene.h" +#include "Proportionen.h" +#include +#include + +using namespace std; + +Undo::Undo(Scene *parent) : QObject(parent), scene(parent) +{ +} + + +Undo::~Undo() +{ +} + + +void Undo::speichere_zug(const Zug& zug) +{ +if (zug.ist_bewegung() == true) +{ +verlauf.append(zug); + +// wenn es sich um den ersten gespeicherten zug handelt +if (verlauf.size() == 1) emit undo_verfuegbar(true); +} + +else if (zug.ist_aufdeckgung() == true) +{ +verlauf.append(zug); + +// wenn es sich um den ersten gespeicherten zug handelt +if (verlauf.size() == 1) emit undo_verfuegbar(true); +} + +else +{ +qDebug() << tr("Invalid move in Undo::undo()"); + +exit(1); +} + +// ueberschuessige undoelemente loeschen +loesche_ueberschuessige_undoelemente(); +} + + +void Undo::undo() +{ +// wenn der verlauf nicht leer ist +if (verlauf.isEmpty() == false) +{ +Zug zugelement(verlauf.takeLast()); + +// wenn das zug element ungueltig ist eine fehlermeldung ausgeben und das programm abbrechen +if (zugelement.ist_gueltig() == false) +{ +qDebug() << tr("Invalid move in Undo::undo()"); + +exit(1); +} + +// wenn es sich um eine bewegung handelt +if (zugelement.ist_bewegung() == true) +{ +// den zug unter umgehung der ueberpruefungen und signale rueckgaengig machen. +zugelement.herkunft()->undo_karten_ablage(zugelement.karte()); + +scene->update(); +} + +// wenn es sich um eine karten aufdeckung handelt +else if (zugelement.ist_aufdeckgung() == true) +{ +// die karten aufdeckung unter umgehung der ueberpruefungen und signale rueckgaengig machen. +zugelement.karte()->zeige_rueckseite(); + +scene->update(); +} + +emit undo_verfuegbar(!verlauf.isEmpty()); +emit undo_meldung(zugelement); +} +} + +void Undo::clear() +{ +emit undo_verfuegbar(false); + +verlauf.clear(); +} + + +void Undo::loesche_ueberschuessige_undoelemente() +{ +float summe = 0; + +// den wert der zuege, die sich derzeit in verlauf befinden berechnen +for (register int idx = 0; idx < verlauf.size(); idx++) +{ +if (verlauf.at(idx).ist_bewegung() == true) summe += ZUEGE_PRO_BEWEGUNG; +else if (verlauf.at(idx).ist_aufdeckgung() == true) summe += ZUEGE_PRO_AUFDECKUNG; +} + +// den ueberschuss entfernen +float ueberschuss = summe - UNDO_LIMIT; + +// wenn ein ueberschuss vorhanden ist ... +if (ueberschuss > 0.1) +{ +// solange, wie ein ueberschuss vorhanden ist +while (verlauf.isEmpty() == false && ueberschuss > 0.1) +{ +// dem zug entsprechende punktzahl abziehen +if (verlauf.first().ist_bewegung() == true) ueberschuss -= ZUEGE_PRO_BEWEGUNG; +else if (verlauf.first().ist_aufdeckgung() == true) ueberschuss -= ZUEGE_PRO_AUFDECKUNG; + +// das aelteste element entfernen +verlauf.removeFirst(); +} +} +} + + +const QStringList Undo::speichere() const +{ +QStringList erg; + +// die id speichern +erg.append(objectName()); + +// die verlauf liste speichern +QString verlauf_string; + +for (register int idx = 0; idx < verlauf.size(); idx++) +{ +if (idx > 0) verlauf_string.append(ZUEGE_SPLITTER); + +verlauf_string.append(verlauf.at(idx).karte_name()); +verlauf_string.append(ZUEGE_NACH_SPLITTER); +verlauf_string.append(verlauf.at(idx).herkunft_name()); + +if (verlauf.at(idx).ist_bewegung() == true) +{ +verlauf_string.append(ZUEGE_NACH_SPLITTER); +verlauf_string.append(verlauf.at(idx).ziel_name()); +} +} + +erg.append(verlauf_string); + +return erg; +} + + +bool Undo::lade(const QStringList& daten) +{ +bool erg = false; + +if (daten.size() == UNDO_ANZAHL_SPEICHERELEMENTE && daten.first() == objectName()) +{ +erg = true; + +QStringList tmp_daten(daten.at(UNDO_VERLAUF_IDX).split(ZUEGE_SPLITTER, QString::SkipEmptyParts)); + +for (register int idx = 0; idx < tmp_daten.size(); idx++) +{ +QStringList tmp_zug(tmp_daten.at(idx).split(ZUEGE_NACH_SPLITTER, QString::SkipEmptyParts)); + +if (tmp_zug.size() == 2) +{ +if (scene->enthaelt_karte(tmp_zug.at(0)) == true && scene->enthaelt_stapel(tmp_zug.at(1)) == true) verlauf.append(Zug(scene->suche_karte(tmp_zug.at(0)), scene->suche_stapel(tmp_zug.at(1)))); + +else erg = false; +} + +else if (tmp_zug.size() == 3) +{ +if (scene->enthaelt_karte(tmp_zug.at(0)) == true && scene->enthaelt_stapel(tmp_zug.at(1)) == true && scene->enthaelt_stapel(tmp_zug.at(2)) == true) verlauf.append(Zug(scene->suche_karte(tmp_zug.at(0)), scene->suche_stapel(tmp_zug.at(1)), scene->suche_stapel(tmp_zug.at(2)))); + +else erg = false; +} + +else erg = false; +} +} + +if (erg == true && verlauf.isEmpty() == false) emit undo_verfuegbar(true); + +return erg; +} diff --git a/plugins/patience_plugin/Patience/Undo.h b/plugins/patience_plugin/Patience/Undo.h new file mode 100644 index 000000000..a1013ad2a --- /dev/null +++ b/plugins/patience_plugin/Patience/Undo.h @@ -0,0 +1,40 @@ +#ifndef UNDO_H +#define UNDO_H + +#include +#include +#include +#include "Zug.h" + +class Karte; +class Basisstapel; +class Scene; + +class Undo : public QObject +{ +Q_OBJECT + +public: +Undo(Scene *parent); +virtual ~Undo(); + +const QStringList speichere() const; +bool lade(const QStringList&); + +public slots: +void speichere_zug(const Zug&); +void undo(); +void clear(); + +signals: +void undo_meldung(const Zug&); +void undo_verfuegbar(bool); + +private: +QList verlauf; +Scene *scene; + +void loesche_ueberschuessige_undoelemente(); +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Viewer.cpp b/plugins/patience_plugin/Patience/Viewer.cpp new file mode 100644 index 000000000..19f394174 --- /dev/null +++ b/plugins/patience_plugin/Patience/Viewer.cpp @@ -0,0 +1,22 @@ +#include "Viewer.h" +#include "Scene.h" +#include + +using namespace std; + +Viewer::Viewer(QWidget *parent) : QGraphicsView(parent) +{ +} + + +Viewer::~Viewer() +{ +} + + +void Viewer::resizeEvent(QResizeEvent* event) +{ +QGraphicsView::resizeEvent(event); + +if (scene() != 0) ((Scene*) scene())->groessenanpassung(event); +} diff --git a/plugins/patience_plugin/Patience/Viewer.h b/plugins/patience_plugin/Patience/Viewer.h new file mode 100644 index 000000000..d89d963b5 --- /dev/null +++ b/plugins/patience_plugin/Patience/Viewer.h @@ -0,0 +1,18 @@ +#ifndef VIEWER_H +#define VIEWER_H + +#include + +class Viewer : public QGraphicsView +{ +Q_OBJECT + +public: +Viewer(QWidget *parent = 0); +virtual ~Viewer(); + +private: +virtual void resizeEvent(QResizeEvent*); +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Zielstapel.cpp b/plugins/patience_plugin/Patience/Zielstapel.cpp new file mode 100644 index 000000000..789ca001c --- /dev/null +++ b/plugins/patience_plugin/Patience/Zielstapel.cpp @@ -0,0 +1,80 @@ +#include "Zielstapel.h" +#include "Karte.h" +#include "Siegkontrolle.h" +#include + +using namespace std; + +Zielstapel::Zielstapel(const QPixmap& pixmap, Scene* oparent, QGraphicsItem* gparent) : Basisstapel(pixmap, oparent, gparent), siegkontrolle(0) +{ +} + + +Zielstapel::~Zielstapel() +{ +} + + +bool Zielstapel::ablage_moeglich(Karte* karte) const +{ +bool erg = false; + +if (Basisstapel::ablage_moeglich(karte) == true && ((oberste_karte() == 0 && karte->wert() == 1) || (oberste_karte() != 0 &&oberste_karte()->farbe() == karte->farbe() && karte->wert() == (oberste_karte()->wert() + 1))) && karte->hat_kinderkarten() == false) erg = true; + +return erg; +} + + +void Zielstapel::registriere_siegkontrolle(Siegkontrolle* siegkontrolle_) +{ +siegkontrolle = siegkontrolle_; +} + + +void Zielstapel::ablage_erfolgt() +{ +siegkontrolle->teste_auf_sieg(); +} + + +void Zielstapel::registriere_nachbar_zielstapel(Basisstapel* erster, Basisstapel* zweiter, Basisstapel* dritter) +{ +nachbarn.append(erster); +nachbarn.append(zweiter); +nachbarn.append(dritter); +} + + +bool Zielstapel::lege_karte_ab(Karte* karte) +{ +bool erg = false; +Basisstapel *ziel = 0; + +QString quelle(karte->eigentuemer_stapel()->objectName()); + +// wenn dieser stapel der richtige ist ... +if (objectName().contains(karte->farbe()) == true) erg = Basisstapel::lege_karte_ab(karte); + +// ansonsten den richtigen stapel suchen ... +else +{ +for (register int idx = 0; idx < nachbarn.size() && ziel == 0; idx++) if (nachbarn.at(idx)->objectName().contains(karte->farbe()) == true) ziel = nachbarn.at(idx); + +// ... und die karte auf diesem ablegen +if (ziel != 0) erg = ziel->lege_karte_ab(karte); + +else +{ +qDebug() << tr("Destination not found in Zielstapel::lege_karte_ab(Karte* karte)"); +} +} + +return erg; +} + + +void Zielstapel::hilfsanfrage_start(Karte* karte) +{ +// dafuer sorgen, das der hilfspfeil nur uber dem richtigen zielstapel erscheint +if (objectName().contains(karte->farbe()) == true) Basisstapel::hilfsanfrage_start(karte); +} diff --git a/plugins/patience_plugin/Patience/Zielstapel.h b/plugins/patience_plugin/Patience/Zielstapel.h new file mode 100644 index 000000000..c0b930ec7 --- /dev/null +++ b/plugins/patience_plugin/Patience/Zielstapel.h @@ -0,0 +1,32 @@ +#ifndef ZIELSTAPEL_H +#define ZIELSTAPEL_H + +#include "Basisstapel.h" +#include + +class Siegkontrolle; + +class Zielstapel : public Basisstapel +{ +Q_OBJECT + +public: +Zielstapel(const QPixmap& pixmap, Scene* oparent, QGraphicsItem* gparent = 0); +virtual ~Zielstapel(); + +virtual void registriere_siegkontrolle(Siegkontrolle*); +virtual void registriere_nachbar_zielstapel(Basisstapel*, Basisstapel*, Basisstapel*); + +virtual void ablage_erfolgt(); +virtual bool ablage_moeglich(Karte *) const; +virtual bool lege_karte_ab(Karte*); + +public slots: +virtual void hilfsanfrage_start(Karte*); + +private: +Siegkontrolle *siegkontrolle; +QList nachbarn; +}; + +#endif diff --git a/plugins/patience_plugin/Patience/Zug.cpp b/plugins/patience_plugin/Patience/Zug.cpp new file mode 100644 index 000000000..e65786862 --- /dev/null +++ b/plugins/patience_plugin/Patience/Zug.cpp @@ -0,0 +1,131 @@ +#include "Zug.h" +#include "Karte.h" +#include "Basisstapel.h" +#include + +using namespace std; + +Zug::Zug() : Karte_(0), Herkunft(0), Ziel(0) +{ +} + + +Zug::~Zug() +{ +} + + +bool Zug::ist_gueltig() const +{ +bool erg = false; + +if (ist_bewegung() == true) erg = true; + +else if (ist_aufdeckgung() == true) erg = true; + +return erg; +} + + +bool Zug::ist_bewegung() const +{ +bool erg = false; + +if (Karte_ != 0 && Herkunft != 0 && Ziel != 0) erg = true; + +return erg; +} + + +bool Zug::ist_aufdeckgung() const +{ +bool erg = false; + +if (Karte_ != 0 && Herkunft != 0 && Ziel == 0) erg = true; + +return erg; +} + + +void Zug::setze_bewegung(Karte* karte, Basisstapel *herkunft_, Basisstapel *ziel_) +{ +Karte_ = karte; +Herkunft = herkunft_; +Ziel = ziel_; +} + + +void Zug::setze_aufdeckung(Karte* karte, Basisstapel *ort) +{ +Karte_ = karte; +Herkunft = ort; +Ziel = 0; +} + + +Karte* Zug::karte() const +{ +return Karte_; +} + + +Basisstapel* Zug::herkunft() const +{ +return Herkunft; +} + + +Basisstapel* Zug::ziel() const +{ +return Ziel; +} + + +QString Zug::karte_name() const +{ +QString erg; + +if (Karte_ != 0) erg = Karte_->objectName(); + +return erg; +} + + +QString Zug::herkunft_name() const +{ +QString erg; + +if (Herkunft != 0) erg = Herkunft->objectName(); + +return erg; +} + + +QString Zug::ziel_name() const +{ +QString erg; + +if (Ziel != 0) erg = Ziel->objectName(); + +return erg; +} + + +Zug::Zug(Karte* karte, Basisstapel *herkunft, Basisstapel *ziel) : Karte_(karte), Herkunft(herkunft), Ziel(ziel) +{ +} + + +Zug::Zug(Karte* karte, Basisstapel *ort) : Karte_(karte), Herkunft(ort), Ziel(0) +{ +} + + +bool Zug::operator==(const Zug& anderer) const +{ +bool erg = false; + +if (karte() == anderer.karte() && herkunft() == anderer.herkunft() && ziel() == anderer.ziel()) erg = true; + +return erg; +} diff --git a/plugins/patience_plugin/Patience/Zug.h b/plugins/patience_plugin/Patience/Zug.h new file mode 100644 index 000000000..6dc18fb82 --- /dev/null +++ b/plugins/patience_plugin/Patience/Zug.h @@ -0,0 +1,40 @@ +#ifndef ZUG_H +#define ZUG_H + +#include + +class Karte; +class Basisstapel; + +class Zug +{ +public: +Zug(); +Zug(Karte* karte, Basisstapel *herkunft, Basisstapel *ziel); +Zug(Karte* karte, Basisstapel *ort); +virtual ~Zug(); + +bool ist_gueltig() const; +bool ist_bewegung() const; +bool ist_aufdeckgung() const; + +void setze_bewegung(Karte* karte, Basisstapel *herkunft_, Basisstapel *ziel_); +void setze_aufdeckung(Karte* karte, Basisstapel *ort); + +Karte* karte() const; +Basisstapel* herkunft() const; +Basisstapel* ziel() const; + + +QString karte_name() const; +QString herkunft_name() const; +QString ziel_name() const; + +bool operator==(const Zug& anderer) const; + +private: +Karte *Karte_; +Basisstapel *Herkunft, *Ziel; +}; + +#endif diff --git a/plugins/patience_plugin/Patience/gpl.txt b/plugins/patience_plugin/Patience/gpl.txt new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/plugins/patience_plugin/Patience/gpl.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/plugins/patience_plugin/Patience/icon.icns b/plugins/patience_plugin/Patience/icon.icns new file mode 100644 index 000000000..abf9c44a4 Binary files /dev/null and b/plugins/patience_plugin/Patience/icon.icns differ diff --git a/plugins/patience_plugin/Patience/icon.ico b/plugins/patience_plugin/Patience/icon.ico new file mode 100644 index 000000000..0c4881759 Binary files /dev/null and b/plugins/patience_plugin/Patience/icon.ico differ diff --git a/plugins/patience_plugin/Patience/karten/french/01c.gif b/plugins/patience_plugin/Patience/karten/french/01c.gif new file mode 100644 index 000000000..5d6f17e90 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/01c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/01d.gif b/plugins/patience_plugin/Patience/karten/french/01d.gif new file mode 100644 index 000000000..6921fbbd3 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/01d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/01h.gif b/plugins/patience_plugin/Patience/karten/french/01h.gif new file mode 100644 index 000000000..de1463493 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/01h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/01s.gif b/plugins/patience_plugin/Patience/karten/french/01s.gif new file mode 100644 index 000000000..e736e0384 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/01s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/02c.gif b/plugins/patience_plugin/Patience/karten/french/02c.gif new file mode 100644 index 000000000..96c72fb28 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/02c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/02d.gif b/plugins/patience_plugin/Patience/karten/french/02d.gif new file mode 100644 index 000000000..c767600f4 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/02d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/02h.gif b/plugins/patience_plugin/Patience/karten/french/02h.gif new file mode 100644 index 000000000..c05260ffb Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/02h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/02s.gif b/plugins/patience_plugin/Patience/karten/french/02s.gif new file mode 100644 index 000000000..bca720b36 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/02s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/03c.gif b/plugins/patience_plugin/Patience/karten/french/03c.gif new file mode 100644 index 000000000..8a123585b Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/03c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/03d.gif b/plugins/patience_plugin/Patience/karten/french/03d.gif new file mode 100644 index 000000000..78e9fe3dc Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/03d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/03h.gif b/plugins/patience_plugin/Patience/karten/french/03h.gif new file mode 100644 index 000000000..7601b6b0f Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/03h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/03s.gif b/plugins/patience_plugin/Patience/karten/french/03s.gif new file mode 100644 index 000000000..a2d6d48e0 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/03s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/04c.gif b/plugins/patience_plugin/Patience/karten/french/04c.gif new file mode 100644 index 000000000..f56f522de Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/04c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/04d.gif b/plugins/patience_plugin/Patience/karten/french/04d.gif new file mode 100644 index 000000000..88bc6c3c2 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/04d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/04h.gif b/plugins/patience_plugin/Patience/karten/french/04h.gif new file mode 100644 index 000000000..23e85858a Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/04h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/04s.gif b/plugins/patience_plugin/Patience/karten/french/04s.gif new file mode 100644 index 000000000..f5c82e21a Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/04s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/05c.gif b/plugins/patience_plugin/Patience/karten/french/05c.gif new file mode 100644 index 000000000..34aa41845 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/05c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/05d.gif b/plugins/patience_plugin/Patience/karten/french/05d.gif new file mode 100644 index 000000000..94b8e6084 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/05d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/05h.gif b/plugins/patience_plugin/Patience/karten/french/05h.gif new file mode 100644 index 000000000..2b42dc602 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/05h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/05s.gif b/plugins/patience_plugin/Patience/karten/french/05s.gif new file mode 100644 index 000000000..34349820c Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/05s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/06c.gif b/plugins/patience_plugin/Patience/karten/french/06c.gif new file mode 100644 index 000000000..89f60a920 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/06c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/06d.gif b/plugins/patience_plugin/Patience/karten/french/06d.gif new file mode 100644 index 000000000..94be5a09b Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/06d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/06h.gif b/plugins/patience_plugin/Patience/karten/french/06h.gif new file mode 100644 index 000000000..455d37ae8 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/06h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/06s.gif b/plugins/patience_plugin/Patience/karten/french/06s.gif new file mode 100644 index 000000000..3281dcbf1 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/06s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/07c.gif b/plugins/patience_plugin/Patience/karten/french/07c.gif new file mode 100644 index 000000000..e624b13c6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/07c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/07d.gif b/plugins/patience_plugin/Patience/karten/french/07d.gif new file mode 100644 index 000000000..727b03425 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/07d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/07h.gif b/plugins/patience_plugin/Patience/karten/french/07h.gif new file mode 100644 index 000000000..0ea9b3f83 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/07h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/07s.gif b/plugins/patience_plugin/Patience/karten/french/07s.gif new file mode 100644 index 000000000..f3ed5f49c Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/07s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/08c.gif b/plugins/patience_plugin/Patience/karten/french/08c.gif new file mode 100644 index 000000000..539a65e23 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/08c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/08d.gif b/plugins/patience_plugin/Patience/karten/french/08d.gif new file mode 100644 index 000000000..dcc28c525 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/08d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/08h.gif b/plugins/patience_plugin/Patience/karten/french/08h.gif new file mode 100644 index 000000000..2410476cf Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/08h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/08s.gif b/plugins/patience_plugin/Patience/karten/french/08s.gif new file mode 100644 index 000000000..cb4992b30 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/08s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/09c.gif b/plugins/patience_plugin/Patience/karten/french/09c.gif new file mode 100644 index 000000000..6f75d70ee Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/09c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/09d.gif b/plugins/patience_plugin/Patience/karten/french/09d.gif new file mode 100644 index 000000000..08fe38c80 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/09d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/09h.gif b/plugins/patience_plugin/Patience/karten/french/09h.gif new file mode 100644 index 000000000..2f819439e Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/09h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/09s.gif b/plugins/patience_plugin/Patience/karten/french/09s.gif new file mode 100644 index 000000000..cb7ad69a8 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/09s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/10c.gif b/plugins/patience_plugin/Patience/karten/french/10c.gif new file mode 100644 index 000000000..59b980a3e Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/10c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/10d.gif b/plugins/patience_plugin/Patience/karten/french/10d.gif new file mode 100644 index 000000000..357733124 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/10d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/10h.gif b/plugins/patience_plugin/Patience/karten/french/10h.gif new file mode 100644 index 000000000..1a7ee6ddf Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/10h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/10s.gif b/plugins/patience_plugin/Patience/karten/french/10s.gif new file mode 100644 index 000000000..d31d9878c Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/10s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/11c.gif b/plugins/patience_plugin/Patience/karten/french/11c.gif new file mode 100644 index 000000000..96b717547 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/11c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/11d.gif b/plugins/patience_plugin/Patience/karten/french/11d.gif new file mode 100644 index 000000000..5c545603b Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/11d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/11h.gif b/plugins/patience_plugin/Patience/karten/french/11h.gif new file mode 100644 index 000000000..4f0773456 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/11h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/11s.gif b/plugins/patience_plugin/Patience/karten/french/11s.gif new file mode 100644 index 000000000..7c2359e6c Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/11s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/12c.gif b/plugins/patience_plugin/Patience/karten/french/12c.gif new file mode 100644 index 000000000..39fd11ca1 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/12c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/12d.gif b/plugins/patience_plugin/Patience/karten/french/12d.gif new file mode 100644 index 000000000..44351acf5 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/12d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/12h.gif b/plugins/patience_plugin/Patience/karten/french/12h.gif new file mode 100644 index 000000000..d3bc62397 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/12h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/12s.gif b/plugins/patience_plugin/Patience/karten/french/12s.gif new file mode 100644 index 000000000..c8d0fbf62 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/12s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/13c.gif b/plugins/patience_plugin/Patience/karten/french/13c.gif new file mode 100644 index 000000000..dacd466c8 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/13c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/13d.gif b/plugins/patience_plugin/Patience/karten/french/13d.gif new file mode 100644 index 000000000..2c8e77dea Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/13d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/13h.gif b/plugins/patience_plugin/Patience/karten/french/13h.gif new file mode 100644 index 000000000..2104c258b Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/13h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/13s.gif b/plugins/patience_plugin/Patience/karten/french/13s.gif new file mode 100644 index 000000000..5688bcd81 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/13s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/COPYRIGHT.txt b/plugins/patience_plugin/Patience/karten/french/COPYRIGHT.txt new file mode 100644 index 000000000..dc217dc3f --- /dev/null +++ b/plugins/patience_plugin/Patience/karten/french/COPYRIGHT.txt @@ -0,0 +1,8 @@ +This PySol cardset was adapted from the game XSkat 4.0 + +Copyright (C) 2004 Gunter Gerhardt (http://www.xskat.de) + +This cardset is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 of +the License, or (at your option) any later version. diff --git a/plugins/patience_plugin/Patience/karten/french/back01.gif b/plugins/patience_plugin/Patience/karten/french/back01.gif new file mode 100644 index 000000000..d98c699d1 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/back01.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/bottom01.gif b/plugins/patience_plugin/Patience/karten/french/bottom01.gif new file mode 100644 index 000000000..45f16b206 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/bottom01.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/bottom02.gif b/plugins/patience_plugin/Patience/karten/french/bottom02.gif new file mode 100644 index 000000000..11332ae4c Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/bottom02.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/bottom03.gif b/plugins/patience_plugin/Patience/karten/french/bottom03.gif new file mode 100644 index 000000000..75d817ed9 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/bottom03.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/bottom04.gif b/plugins/patience_plugin/Patience/karten/french/bottom04.gif new file mode 100644 index 000000000..2531b7e4c Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/bottom04.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/bottom05.gif b/plugins/patience_plugin/Patience/karten/french/bottom05.gif new file mode 100644 index 000000000..173a9f989 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/bottom05.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/bottom06.gif b/plugins/patience_plugin/Patience/karten/french/bottom06.gif new file mode 100644 index 000000000..3fed1f427 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/bottom06.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/bottom07.gif b/plugins/patience_plugin/Patience/karten/french/bottom07.gif new file mode 100644 index 000000000..e3c20d648 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/bottom07.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/config.txt b/plugins/patience_plugin/Patience/karten/french/config.txt new file mode 100644 index 000000000..8398ca926 --- /dev/null +++ b/plugins/patience_plugin/Patience/karten/french/config.txt @@ -0,0 +1,6 @@ +PySol solitaire cardset;5;.gif;1;52;7,1006;2004 +12442-xskat-french-large;XSkat-French-Large +90 140 8 +18 18 9 9 +back01.gif +back01.gif diff --git a/plugins/patience_plugin/Patience/karten/french/l01.gif b/plugins/patience_plugin/Patience/karten/french/l01.gif new file mode 100644 index 000000000..57b03e3c3 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/l01.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/l02.gif b/plugins/patience_plugin/Patience/karten/french/l02.gif new file mode 100644 index 000000000..f86683951 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/l02.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/l03.gif b/plugins/patience_plugin/Patience/karten/french/l03.gif new file mode 100644 index 000000000..31b426556 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/l03.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/l04.gif b/plugins/patience_plugin/Patience/karten/french/l04.gif new file mode 100644 index 000000000..4323285af Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/l04.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shade.gif b/plugins/patience_plugin/Patience/karten/french/shade.gif new file mode 100644 index 000000000..7e0085f61 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shade.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow00.gif b/plugins/patience_plugin/Patience/karten/french/shadow00.gif new file mode 100644 index 000000000..8eb2d7d73 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow00.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow01.gif b/plugins/patience_plugin/Patience/karten/french/shadow01.gif new file mode 100644 index 000000000..ae8eb168d Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow01.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow02.gif b/plugins/patience_plugin/Patience/karten/french/shadow02.gif new file mode 100644 index 000000000..5bd510faa Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow02.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow03.gif b/plugins/patience_plugin/Patience/karten/french/shadow03.gif new file mode 100644 index 000000000..cad23b5a9 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow03.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow04.gif b/plugins/patience_plugin/Patience/karten/french/shadow04.gif new file mode 100644 index 000000000..69b0b55a6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow04.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow05.gif b/plugins/patience_plugin/Patience/karten/french/shadow05.gif new file mode 100644 index 000000000..d6b59f5eb Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow05.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow06.gif b/plugins/patience_plugin/Patience/karten/french/shadow06.gif new file mode 100644 index 000000000..89331c1cc Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow06.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow07.gif b/plugins/patience_plugin/Patience/karten/french/shadow07.gif new file mode 100644 index 000000000..f2f05d1d6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow07.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow08.gif b/plugins/patience_plugin/Patience/karten/french/shadow08.gif new file mode 100644 index 000000000..fd9773326 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow08.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow09.gif b/plugins/patience_plugin/Patience/karten/french/shadow09.gif new file mode 100644 index 000000000..0fc862f55 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow09.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow10.gif b/plugins/patience_plugin/Patience/karten/french/shadow10.gif new file mode 100644 index 000000000..e949e23c6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow10.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow11.gif b/plugins/patience_plugin/Patience/karten/french/shadow11.gif new file mode 100644 index 000000000..812eca48d Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow11.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow12.gif b/plugins/patience_plugin/Patience/karten/french/shadow12.gif new file mode 100644 index 000000000..dad065377 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow12.gif differ diff --git a/plugins/patience_plugin/Patience/karten/french/shadow13.gif b/plugins/patience_plugin/Patience/karten/french/shadow13.gif new file mode 100644 index 000000000..25eae560e Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/french/shadow13.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/01c.gif b/plugins/patience_plugin/Patience/karten/german/01c.gif new file mode 100644 index 000000000..b3c40d72e Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/01c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/01d.gif b/plugins/patience_plugin/Patience/karten/german/01d.gif new file mode 100644 index 000000000..eb4a6f899 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/01d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/01h.gif b/plugins/patience_plugin/Patience/karten/german/01h.gif new file mode 100644 index 000000000..99f8fc903 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/01h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/01s.gif b/plugins/patience_plugin/Patience/karten/german/01s.gif new file mode 100644 index 000000000..2e9b211bc Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/01s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/02c.gif b/plugins/patience_plugin/Patience/karten/german/02c.gif new file mode 100644 index 000000000..2cc3ac4bc Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/02c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/02d.gif b/plugins/patience_plugin/Patience/karten/german/02d.gif new file mode 100644 index 000000000..8bff1256a Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/02d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/02h.gif b/plugins/patience_plugin/Patience/karten/german/02h.gif new file mode 100644 index 000000000..d18f3f7c0 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/02h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/02s.gif b/plugins/patience_plugin/Patience/karten/german/02s.gif new file mode 100644 index 000000000..0346bc38a Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/02s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/03c.gif b/plugins/patience_plugin/Patience/karten/german/03c.gif new file mode 100644 index 000000000..2d12bcd8e Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/03c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/03d.gif b/plugins/patience_plugin/Patience/karten/german/03d.gif new file mode 100644 index 000000000..324c12be0 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/03d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/03h.gif b/plugins/patience_plugin/Patience/karten/german/03h.gif new file mode 100644 index 000000000..6b300fefe Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/03h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/03s.gif b/plugins/patience_plugin/Patience/karten/german/03s.gif new file mode 100644 index 000000000..3750eaa14 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/03s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/04c.gif b/plugins/patience_plugin/Patience/karten/german/04c.gif new file mode 100644 index 000000000..0d7b92db6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/04c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/04d.gif b/plugins/patience_plugin/Patience/karten/german/04d.gif new file mode 100644 index 000000000..4298cdb97 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/04d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/04h.gif b/plugins/patience_plugin/Patience/karten/german/04h.gif new file mode 100644 index 000000000..15ee2eaac Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/04h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/04s.gif b/plugins/patience_plugin/Patience/karten/german/04s.gif new file mode 100644 index 000000000..2c1b441f5 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/04s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/05c.gif b/plugins/patience_plugin/Patience/karten/german/05c.gif new file mode 100644 index 000000000..6b284db16 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/05c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/05d.gif b/plugins/patience_plugin/Patience/karten/german/05d.gif new file mode 100644 index 000000000..19fa424a6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/05d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/05h.gif b/plugins/patience_plugin/Patience/karten/german/05h.gif new file mode 100644 index 000000000..82ece7c25 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/05h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/05s.gif b/plugins/patience_plugin/Patience/karten/german/05s.gif new file mode 100644 index 000000000..a45e1a8a1 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/05s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/06c.gif b/plugins/patience_plugin/Patience/karten/german/06c.gif new file mode 100644 index 000000000..096901be7 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/06c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/06d.gif b/plugins/patience_plugin/Patience/karten/german/06d.gif new file mode 100644 index 000000000..63a4402df Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/06d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/06h.gif b/plugins/patience_plugin/Patience/karten/german/06h.gif new file mode 100644 index 000000000..e2bb4bd92 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/06h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/06s.gif b/plugins/patience_plugin/Patience/karten/german/06s.gif new file mode 100644 index 000000000..16e866bd3 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/06s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/07c.gif b/plugins/patience_plugin/Patience/karten/german/07c.gif new file mode 100644 index 000000000..951c08d72 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/07c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/07d.gif b/plugins/patience_plugin/Patience/karten/german/07d.gif new file mode 100644 index 000000000..696c86af7 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/07d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/07h.gif b/plugins/patience_plugin/Patience/karten/german/07h.gif new file mode 100644 index 000000000..9a86c613d Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/07h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/07s.gif b/plugins/patience_plugin/Patience/karten/german/07s.gif new file mode 100644 index 000000000..6702ebd6a Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/07s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/08c.gif b/plugins/patience_plugin/Patience/karten/german/08c.gif new file mode 100644 index 000000000..af8f06afe Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/08c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/08d.gif b/plugins/patience_plugin/Patience/karten/german/08d.gif new file mode 100644 index 000000000..7c3a77f48 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/08d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/08h.gif b/plugins/patience_plugin/Patience/karten/german/08h.gif new file mode 100644 index 000000000..c1151c717 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/08h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/08s.gif b/plugins/patience_plugin/Patience/karten/german/08s.gif new file mode 100644 index 000000000..7f49f46f5 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/08s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/09c.gif b/plugins/patience_plugin/Patience/karten/german/09c.gif new file mode 100644 index 000000000..a1cdd15a8 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/09c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/09d.gif b/plugins/patience_plugin/Patience/karten/german/09d.gif new file mode 100644 index 000000000..bf7e793c8 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/09d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/09h.gif b/plugins/patience_plugin/Patience/karten/german/09h.gif new file mode 100644 index 000000000..4784c6101 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/09h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/09s.gif b/plugins/patience_plugin/Patience/karten/german/09s.gif new file mode 100644 index 000000000..e649f6dc6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/09s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/10c.gif b/plugins/patience_plugin/Patience/karten/german/10c.gif new file mode 100644 index 000000000..5395d2699 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/10c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/10d.gif b/plugins/patience_plugin/Patience/karten/german/10d.gif new file mode 100644 index 000000000..17cf41a7e Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/10d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/10h.gif b/plugins/patience_plugin/Patience/karten/german/10h.gif new file mode 100644 index 000000000..0a652db02 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/10h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/10s.gif b/plugins/patience_plugin/Patience/karten/german/10s.gif new file mode 100644 index 000000000..2d56f51a9 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/10s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/11c.gif b/plugins/patience_plugin/Patience/karten/german/11c.gif new file mode 100644 index 000000000..48675d218 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/11c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/11d.gif b/plugins/patience_plugin/Patience/karten/german/11d.gif new file mode 100644 index 000000000..a3d880120 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/11d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/11h.gif b/plugins/patience_plugin/Patience/karten/german/11h.gif new file mode 100644 index 000000000..914ef7d4d Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/11h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/11s.gif b/plugins/patience_plugin/Patience/karten/german/11s.gif new file mode 100644 index 000000000..a9bfccf32 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/11s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/12c.gif b/plugins/patience_plugin/Patience/karten/german/12c.gif new file mode 100644 index 000000000..72c787f48 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/12c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/12d.gif b/plugins/patience_plugin/Patience/karten/german/12d.gif new file mode 100644 index 000000000..b928c8862 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/12d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/12h.gif b/plugins/patience_plugin/Patience/karten/german/12h.gif new file mode 100644 index 000000000..f9793595a Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/12h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/12s.gif b/plugins/patience_plugin/Patience/karten/german/12s.gif new file mode 100644 index 000000000..9f50f3c20 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/12s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/13c.gif b/plugins/patience_plugin/Patience/karten/german/13c.gif new file mode 100644 index 000000000..982285885 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/13c.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/13d.gif b/plugins/patience_plugin/Patience/karten/german/13d.gif new file mode 100644 index 000000000..321dd4a91 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/13d.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/13h.gif b/plugins/patience_plugin/Patience/karten/german/13h.gif new file mode 100644 index 000000000..73a38a5c2 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/13h.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/13s.gif b/plugins/patience_plugin/Patience/karten/german/13s.gif new file mode 100644 index 000000000..5ec887991 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/13s.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/COPYRIGHT b/plugins/patience_plugin/Patience/karten/german/COPYRIGHT new file mode 100644 index 000000000..dc217dc3f --- /dev/null +++ b/plugins/patience_plugin/Patience/karten/german/COPYRIGHT @@ -0,0 +1,8 @@ +This PySol cardset was adapted from the game XSkat 4.0 + +Copyright (C) 2004 Gunter Gerhardt (http://www.xskat.de) + +This cardset is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 of +the License, or (at your option) any later version. diff --git a/plugins/patience_plugin/Patience/karten/german/back01.gif b/plugins/patience_plugin/Patience/karten/german/back01.gif new file mode 100644 index 000000000..d98c699d1 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/back01.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/bottom01.gif b/plugins/patience_plugin/Patience/karten/german/bottom01.gif new file mode 100644 index 000000000..45f16b206 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/bottom01.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/bottom02.gif b/plugins/patience_plugin/Patience/karten/german/bottom02.gif new file mode 100644 index 000000000..11332ae4c Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/bottom02.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/bottom03.gif b/plugins/patience_plugin/Patience/karten/german/bottom03.gif new file mode 100644 index 000000000..75d817ed9 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/bottom03.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/bottom04.gif b/plugins/patience_plugin/Patience/karten/german/bottom04.gif new file mode 100644 index 000000000..2531b7e4c Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/bottom04.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/bottom05.gif b/plugins/patience_plugin/Patience/karten/german/bottom05.gif new file mode 100644 index 000000000..173a9f989 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/bottom05.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/bottom06.gif b/plugins/patience_plugin/Patience/karten/german/bottom06.gif new file mode 100644 index 000000000..3fed1f427 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/bottom06.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/bottom07.gif b/plugins/patience_plugin/Patience/karten/german/bottom07.gif new file mode 100644 index 000000000..e3c20d648 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/bottom07.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/config.txt b/plugins/patience_plugin/Patience/karten/german/config.txt new file mode 100644 index 000000000..e782358c6 --- /dev/null +++ b/plugins/patience_plugin/Patience/karten/german/config.txt @@ -0,0 +1,6 @@ +PySol solitaire cardset;5;.gif;1;52;7,1006;2004 +12442-xskat-german-large;XSkat-German-Large +90 140 8 +18 18 9 9 +back01.gif +back01.gif diff --git a/plugins/patience_plugin/Patience/karten/german/l01.gif b/plugins/patience_plugin/Patience/karten/german/l01.gif new file mode 100644 index 000000000..57b03e3c3 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/l01.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/l02.gif b/plugins/patience_plugin/Patience/karten/german/l02.gif new file mode 100644 index 000000000..f86683951 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/l02.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/l03.gif b/plugins/patience_plugin/Patience/karten/german/l03.gif new file mode 100644 index 000000000..31b426556 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/l03.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/l04.gif b/plugins/patience_plugin/Patience/karten/german/l04.gif new file mode 100644 index 000000000..4323285af Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/l04.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shade.gif b/plugins/patience_plugin/Patience/karten/german/shade.gif new file mode 100644 index 000000000..7e0085f61 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shade.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow00.gif b/plugins/patience_plugin/Patience/karten/german/shadow00.gif new file mode 100644 index 000000000..8eb2d7d73 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow00.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow01.gif b/plugins/patience_plugin/Patience/karten/german/shadow01.gif new file mode 100644 index 000000000..ae8eb168d Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow01.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow02.gif b/plugins/patience_plugin/Patience/karten/german/shadow02.gif new file mode 100644 index 000000000..5bd510faa Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow02.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow03.gif b/plugins/patience_plugin/Patience/karten/german/shadow03.gif new file mode 100644 index 000000000..cad23b5a9 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow03.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow04.gif b/plugins/patience_plugin/Patience/karten/german/shadow04.gif new file mode 100644 index 000000000..69b0b55a6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow04.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow05.gif b/plugins/patience_plugin/Patience/karten/german/shadow05.gif new file mode 100644 index 000000000..d6b59f5eb Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow05.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow06.gif b/plugins/patience_plugin/Patience/karten/german/shadow06.gif new file mode 100644 index 000000000..89331c1cc Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow06.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow07.gif b/plugins/patience_plugin/Patience/karten/german/shadow07.gif new file mode 100644 index 000000000..f2f05d1d6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow07.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow08.gif b/plugins/patience_plugin/Patience/karten/german/shadow08.gif new file mode 100644 index 000000000..fd9773326 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow08.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow09.gif b/plugins/patience_plugin/Patience/karten/german/shadow09.gif new file mode 100644 index 000000000..0fc862f55 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow09.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow10.gif b/plugins/patience_plugin/Patience/karten/german/shadow10.gif new file mode 100644 index 000000000..e949e23c6 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow10.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow11.gif b/plugins/patience_plugin/Patience/karten/german/shadow11.gif new file mode 100644 index 000000000..812eca48d Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow11.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow12.gif b/plugins/patience_plugin/Patience/karten/german/shadow12.gif new file mode 100644 index 000000000..dad065377 Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow12.gif differ diff --git a/plugins/patience_plugin/Patience/karten/german/shadow13.gif b/plugins/patience_plugin/Patience/karten/german/shadow13.gif new file mode 100644 index 000000000..25eae560e Binary files /dev/null and b/plugins/patience_plugin/Patience/karten/german/shadow13.gif differ diff --git a/plugins/patience_plugin/Patience/main.cpp b/plugins/patience_plugin/Patience/main.cpp new file mode 100644 index 000000000..5113ebf14 --- /dev/null +++ b/plugins/patience_plugin/Patience/main.cpp @@ -0,0 +1,66 @@ +/* + +Name: Patience +Autor: Andreas Konarski +Begonnen: 05.08.2009. +Erstellt: 08.02.2010. +Version: 0.81 +Lizenz: GPL v3 or later +Plattformen: Alle Systeme, auf denen QT 4.5 verfuegbar ist. + +Kontakt: programmieren@konarski-wuppertal.de +home: www.konarski-wuppertal.de + +Falls ich mit diesem Programm die Rechte von irgend jemand verletzen sollte, bitte ich um einen Hinweis. Wenn dies Tatsaechlich der Fall ist, entferne ich es schnellstmoeglich von meiner Homepage. + + +Zu den Kartenbildern: + +This PySol cardset was adapted from the game XSkat 4.0 + +Copyright (C) 2004 Gunter Gerhardt (http://www.xskat.de) + +This cardset is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 of +the License, or (at your option) any later version. + +*/ + +#include +#include +#include +#include +#include "MainWindow.h" + +using namespace std; + +int main(int argc, char *argv[]) +{ +QApplication anwendung(argc, argv); + +// die anwendung uebersetzen +QTranslator uebersetzer, uebersetzer2; + +QString dateiname_eigene_uebersetzung; +dateiname_eigene_uebersetzung = QString(":/translations/Uebersetzung_%1").arg(QLocale::system().name()); + +// die uebersetzungs dateien in die uebersetzer laden +uebersetzer.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); +uebersetzer2.load(dateiname_eigene_uebersetzung); + +// die uebersetzer installieren +anwendung.installTranslator(&uebersetzer); +anwendung.installTranslator(&uebersetzer2); + +// den anwendungsnamen setzen +anwendung.setApplicationName("Patience"); + +// das hauptfenster erzeugen ... +MainWindow hauptfenster; + +// ... und anzeigen +hauptfenster.show(); + +return anwendung.exec(); +} diff --git a/plugins/patience_plugin/Patience/patience_plugin.pro b/plugins/patience_plugin/Patience/patience_plugin.pro new file mode 100644 index 000000000..78be1d883 --- /dev/null +++ b/plugins/patience_plugin/Patience/patience_plugin.pro @@ -0,0 +1,81 @@ +###################################################################### +# Automatically generated by qmake (2.01a) Mo. Feb 8 10:09:24 2010 +###################################################################### + +# ------------------------------------------------- +# Project created by QtCreator 2009-12-21T21:25:25 +# ------------------------------------------------- +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin release + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(patience_plugin) + +HEADERS += ../../PluginInterface.h \ + PatiencePlugin.h +SOURCES += PatiencePlugin.cpp + +#=============================================================================== + +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +ICON = icon.icns + +RC_FILE = Patience.rc + +# Input +HEADERS += Ablagestapel.h \ + Austeilcostapel.h \ + Austeilstapel.h \ + Basisstapel.h \ + Highscore.h \ + Hilfszeiger.h \ + Karte.h \ + MainWindow.h \ + Proportionen.h \ + Punktezaehler.h \ + Rahmen.h \ + Random.h \ + Scene.h \ + Siegkontrolle.h \ + Speichern_frage.h \ + Undo.h \ + Viewer.h \ + Zielstapel.h \ + Zug.h +FORMS += Highscore.ui MainWindow.ui Speichern_frage.ui +SOURCES += Ablagestapel.cpp \ + Austeilcostapel.cpp \ + Austeilstapel.cpp \ + Basisstapel.cpp \ + Highscore.cpp \ + Hilfszeiger.cpp \ + Karte.cpp \ + main.cpp \ + MainWindow.cpp \ + Punktezaehler.cpp \ + Rahmen.cpp \ + Random.cpp \ + Scene.cpp \ + Siegkontrolle.cpp \ + Speichern_frage.cpp \ + Undo.cpp \ + Viewer.cpp \ + Zielstapel.cpp \ + Zug.cpp +RESOURCES += resourcen.qrc +TRANSLATIONS += Uebersetzung_de.ts diff --git a/plugins/patience_plugin/Patience/readme.txt b/plugins/patience_plugin/Patience/readme.txt new file mode 100644 index 000000000..f247ff051 --- /dev/null +++ b/plugins/patience_plugin/Patience/readme.txt @@ -0,0 +1,18 @@ +Readme File for Patience + +Autor: Andreas Konarski +Contact: andreaskw@gmx.de + programmieren@konarski-wuppertal.de +Licence: GPL V3 + +Windows XP: +Just extract the zip file and launch Patience.exe. Place the Patience Folder where you want, but don’t change the internal structure of the folder, or the application will stop working. + +MacOSX 10.6 Snow Leopard: +Just place the bundle where you want. It should solve all dependencies, but i don’t have a second mac without qt installed to check this. + +Linux: +You have to build the application fro scratch. First install the latest version of qt4, if not already happened. Extract the sources and run qmake and make inside the folder with the sources. + +Other operating systems supported by qt4: +You have to build the application from scratch. Install the latest version of qt4 if not already happened and build the application the way, it should be done on your platform. \ No newline at end of file diff --git a/plugins/patience_plugin/Patience/resourcen.qrc b/plugins/patience_plugin/Patience/resourcen.qrc new file mode 100644 index 000000000..0cfa58d0f --- /dev/null +++ b/plugins/patience_plugin/Patience/resourcen.qrc @@ -0,0 +1,167 @@ + + + karten/french/01c.gif + karten/french/01d.gif + karten/french/01h.gif + karten/french/01s.gif + karten/french/02c.gif + karten/french/02d.gif + karten/french/02h.gif + karten/french/02s.gif + karten/french/03c.gif + karten/french/03d.gif + karten/french/03h.gif + karten/french/03s.gif + karten/french/04c.gif + karten/french/04d.gif + karten/french/04h.gif + karten/french/04s.gif + karten/french/05c.gif + karten/french/05d.gif + karten/french/05h.gif + karten/french/05s.gif + karten/french/06c.gif + karten/french/06d.gif + karten/french/06h.gif + karten/french/06s.gif + karten/french/07c.gif + karten/french/07d.gif + karten/french/07h.gif + karten/french/07s.gif + karten/french/08c.gif + karten/french/08d.gif + karten/french/08h.gif + karten/french/08s.gif + karten/french/09c.gif + karten/french/09d.gif + karten/french/09h.gif + karten/french/09s.gif + karten/french/10c.gif + karten/french/10d.gif + karten/french/10h.gif + karten/french/10s.gif + karten/french/11c.gif + karten/french/11d.gif + karten/french/11h.gif + karten/french/11s.gif + karten/french/12c.gif + karten/french/12d.gif + karten/french/12h.gif + karten/french/12s.gif + karten/french/13c.gif + karten/french/13d.gif + karten/french/13h.gif + karten/french/13s.gif + karten/french/back01.gif + karten/french/bottom01.gif + karten/french/bottom02.gif + karten/french/bottom03.gif + karten/french/bottom04.gif + karten/french/bottom05.gif + karten/french/bottom06.gif + karten/french/bottom07.gif + karten/french/l01.gif + karten/french/l02.gif + karten/french/l03.gif + karten/french/l04.gif + karten/french/shade.gif + karten/french/shadow00.gif + karten/french/shadow01.gif + karten/french/shadow02.gif + karten/french/shadow03.gif + karten/french/shadow04.gif + karten/french/shadow05.gif + karten/french/shadow06.gif + karten/french/shadow07.gif + karten/french/shadow08.gif + karten/french/shadow09.gif + karten/french/shadow10.gif + karten/french/shadow11.gif + karten/french/shadow12.gif + karten/french/shadow13.gif + + + Uebersetzung_de.qm + + + karten/german/01c.gif + karten/german/01d.gif + karten/german/01h.gif + karten/german/01s.gif + karten/german/02c.gif + karten/german/02d.gif + karten/german/02h.gif + karten/german/02s.gif + karten/german/03c.gif + karten/german/03d.gif + karten/german/03h.gif + karten/german/03s.gif + karten/german/04c.gif + karten/german/04d.gif + karten/german/04h.gif + karten/german/04s.gif + karten/german/05c.gif + karten/german/05d.gif + karten/german/05h.gif + karten/german/05s.gif + karten/german/06c.gif + karten/german/06d.gif + karten/german/06h.gif + karten/german/06s.gif + karten/german/07c.gif + karten/german/07d.gif + karten/german/07h.gif + karten/german/07s.gif + karten/german/08c.gif + karten/german/08d.gif + karten/german/08h.gif + karten/german/08s.gif + karten/german/09c.gif + karten/german/09d.gif + karten/german/09h.gif + karten/german/09s.gif + karten/german/10c.gif + karten/german/10d.gif + karten/german/10h.gif + karten/german/10s.gif + karten/german/11c.gif + karten/german/11d.gif + karten/german/11h.gif + karten/german/11s.gif + karten/german/12c.gif + karten/german/12d.gif + karten/german/12h.gif + karten/german/12s.gif + karten/german/13c.gif + karten/german/13d.gif + karten/german/13h.gif + karten/german/13s.gif + karten/german/back01.gif + karten/german/bottom01.gif + karten/german/bottom02.gif + karten/german/bottom03.gif + karten/german/bottom04.gif + karten/german/bottom05.gif + karten/german/bottom06.gif + karten/german/bottom07.gif + karten/german/l01.gif + karten/german/l02.gif + karten/german/l03.gif + karten/german/l04.gif + karten/german/shade.gif + karten/german/shadow00.gif + karten/german/shadow01.gif + karten/german/shadow02.gif + karten/german/shadow03.gif + karten/german/shadow04.gif + karten/german/shadow05.gif + karten/german/shadow06.gif + karten/german/shadow07.gif + karten/german/shadow08.gif + karten/german/shadow09.gif + karten/german/shadow10.gif + karten/german/shadow11.gif + karten/german/shadow12.gif + karten/german/shadow13.gif + + diff --git a/plugins/patience_plugin/Patience/ui_Highscore.h b/plugins/patience_plugin/Patience/ui_Highscore.h new file mode 100644 index 000000000..9f9e5a7ae --- /dev/null +++ b/plugins/patience_plugin/Patience/ui_Highscore.h @@ -0,0 +1,107 @@ +/******************************************************************************** +** Form generated from reading ui file 'Highscore.ui' +** +** Created: Mon 8. Feb 22:40:48 2010 +** by: Qt User Interface Compiler version 4.5.2 +** +** WARNING! All changes made in this file will be lost when recompiling ui file! +********************************************************************************/ + +#ifndef UI_HIGHSCORE_H +#define UI_HIGHSCORE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Highscore +{ +public: + QVBoxLayout *verticalLayout; + QTableWidget *tabelle; + QHBoxLayout *horizontalLayout; + QSpacerItem *horizontalSpacer; + QPushButton *ok_button; + + void setupUi(QDialog *Highscore) + { + if (Highscore->objectName().isEmpty()) + Highscore->setObjectName(QString::fromUtf8("Highscore")); + Highscore->setWindowModality(Qt::WindowModal); + Highscore->resize(528, 300); + Highscore->setMinimumSize(QSize(528, 300)); + verticalLayout = new QVBoxLayout(Highscore); + verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); + tabelle = new QTableWidget(Highscore); + if (tabelle->columnCount() < 3) + tabelle->setColumnCount(3); + QTableWidgetItem *__qtablewidgetitem = new QTableWidgetItem(); + tabelle->setHorizontalHeaderItem(0, __qtablewidgetitem); + QTableWidgetItem *__qtablewidgetitem1 = new QTableWidgetItem(); + tabelle->setHorizontalHeaderItem(1, __qtablewidgetitem1); + QTableWidgetItem *__qtablewidgetitem2 = new QTableWidgetItem(); + tabelle->setHorizontalHeaderItem(2, __qtablewidgetitem2); + tabelle->setObjectName(QString::fromUtf8("tabelle")); + tabelle->setEditTriggers(QAbstractItemView::NoEditTriggers); + tabelle->setSelectionBehavior(QAbstractItemView::SelectRows); + tabelle->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + tabelle->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); + tabelle->horizontalHeader()->setStretchLastSection(true); + + verticalLayout->addWidget(tabelle); + + horizontalLayout = new QHBoxLayout(); + horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); + horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout->addItem(horizontalSpacer); + + ok_button = new QPushButton(Highscore); + ok_button->setObjectName(QString::fromUtf8("ok_button")); + ok_button->setAutoDefault(false); + ok_button->setDefault(true); + + horizontalLayout->addWidget(ok_button); + + + verticalLayout->addLayout(horizontalLayout); + + + retranslateUi(Highscore); + QObject::connect(ok_button, SIGNAL(clicked()), Highscore, SLOT(accept())); + + QMetaObject::connectSlotsByName(Highscore); + } // setupUi + + void retranslateUi(QDialog *Highscore) + { + Highscore->setWindowTitle(QApplication::translate("Highscore", "Patience - Highscore", 0, QApplication::UnicodeUTF8)); + QTableWidgetItem *___qtablewidgetitem = tabelle->horizontalHeaderItem(0); + ___qtablewidgetitem->setText(QApplication::translate("Highscore", "Name", 0, QApplication::UnicodeUTF8)); + QTableWidgetItem *___qtablewidgetitem1 = tabelle->horizontalHeaderItem(1); + ___qtablewidgetitem1->setText(QApplication::translate("Highscore", "Points", 0, QApplication::UnicodeUTF8)); + QTableWidgetItem *___qtablewidgetitem2 = tabelle->horizontalHeaderItem(2); + ___qtablewidgetitem2->setText(QApplication::translate("Highscore", "Time", 0, QApplication::UnicodeUTF8)); + ok_button->setText(QApplication::translate("Highscore", "Ok", 0, QApplication::UnicodeUTF8)); + Q_UNUSED(Highscore); + } // retranslateUi + +}; + +namespace Ui { + class Highscore: public Ui_Highscore {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_HIGHSCORE_H diff --git a/plugins/patience_plugin/Patience/ui_MainWindow.h b/plugins/patience_plugin/Patience/ui_MainWindow.h new file mode 100644 index 000000000..c71bda704 --- /dev/null +++ b/plugins/patience_plugin/Patience/ui_MainWindow.h @@ -0,0 +1,231 @@ +/******************************************************************************** +** Form generated from reading ui file 'MainWindow.ui' +** +** Created: Mon 8. Feb 22:40:48 2010 +** by: Qt User Interface Compiler version 4.5.2 +** +** WARNING! All changes made in this file will be lost when recompiling ui file! +********************************************************************************/ + +#ifndef UI_MAINWINDOW_H +#define UI_MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Viewer.h" + +QT_BEGIN_NAMESPACE + +class Ui_MainWindow +{ +public: + QAction *action_neues_spiel; + QAction *action_beenden; + QAction *action_about; + QAction *action_about_qt; + QAction *action_french_; + QAction *action_german_; + QAction *action_highscore; + QAction *action_eine_ziehen_; + QAction *action_drei_ziehen_; + QAction *action_french; + QAction *action_german; + QAction *action_eine_ziehen; + QAction *action_drei_ziehen; + QAction *action_rahmen; + QAction *action_undo; + QAction *action_fragen; + QAction *action_speichern; + QAction *action_nicht_speichern; + QWidget *centralwidget; + QGridLayout *gridLayout; + Viewer *viewer; + QMenuBar *menubar; + QMenu *menuSpiel; + QMenu *menu_Hilfe; + QMenu *menu_Einstellungen; + QMenu *menu_Cardset; + QMenu *menu_Gametype; + QMenu *menuSave_Game; + QMenu *menu_Highscore; + QMenu *menu_Edit; + QStatusBar *statusbar; + + void setupUi(QMainWindow *MainWindow) + { + if (MainWindow->objectName().isEmpty()) + MainWindow->setObjectName(QString::fromUtf8("MainWindow")); + MainWindow->resize(810, 653); + action_neues_spiel = new QAction(MainWindow); + action_neues_spiel->setObjectName(QString::fromUtf8("action_neues_spiel")); + action_beenden = new QAction(MainWindow); + action_beenden->setObjectName(QString::fromUtf8("action_beenden")); + action_about = new QAction(MainWindow); + action_about->setObjectName(QString::fromUtf8("action_about")); + action_about_qt = new QAction(MainWindow); + action_about_qt->setObjectName(QString::fromUtf8("action_about_qt")); + action_french_ = new QAction(MainWindow); + action_french_->setObjectName(QString::fromUtf8("action_french_")); + action_french_->setCheckable(true); + action_german_ = new QAction(MainWindow); + action_german_->setObjectName(QString::fromUtf8("action_german_")); + action_german_->setCheckable(true); + action_highscore = new QAction(MainWindow); + action_highscore->setObjectName(QString::fromUtf8("action_highscore")); + action_eine_ziehen_ = new QAction(MainWindow); + action_eine_ziehen_->setObjectName(QString::fromUtf8("action_eine_ziehen_")); + action_eine_ziehen_->setCheckable(true); + action_drei_ziehen_ = new QAction(MainWindow); + action_drei_ziehen_->setObjectName(QString::fromUtf8("action_drei_ziehen_")); + action_drei_ziehen_->setCheckable(true); + action_french = new QAction(MainWindow); + action_french->setObjectName(QString::fromUtf8("action_french")); + action_french->setCheckable(true); + action_german = new QAction(MainWindow); + action_german->setObjectName(QString::fromUtf8("action_german")); + action_german->setCheckable(true); + action_eine_ziehen = new QAction(MainWindow); + action_eine_ziehen->setObjectName(QString::fromUtf8("action_eine_ziehen")); + action_eine_ziehen->setCheckable(true); + action_drei_ziehen = new QAction(MainWindow); + action_drei_ziehen->setObjectName(QString::fromUtf8("action_drei_ziehen")); + action_drei_ziehen->setCheckable(true); + action_rahmen = new QAction(MainWindow); + action_rahmen->setObjectName(QString::fromUtf8("action_rahmen")); + action_rahmen->setCheckable(true); + action_rahmen->setChecked(true); + action_undo = new QAction(MainWindow); + action_undo->setObjectName(QString::fromUtf8("action_undo")); + action_fragen = new QAction(MainWindow); + action_fragen->setObjectName(QString::fromUtf8("action_fragen")); + action_fragen->setCheckable(true); + action_fragen->setChecked(true); + action_speichern = new QAction(MainWindow); + action_speichern->setObjectName(QString::fromUtf8("action_speichern")); + action_speichern->setCheckable(true); + action_speichern->setChecked(false); + action_nicht_speichern = new QAction(MainWindow); + action_nicht_speichern->setObjectName(QString::fromUtf8("action_nicht_speichern")); + action_nicht_speichern->setCheckable(true); + centralwidget = new QWidget(MainWindow); + centralwidget->setObjectName(QString::fromUtf8("centralwidget")); + gridLayout = new QGridLayout(centralwidget); + gridLayout->setMargin(5); + gridLayout->setObjectName(QString::fromUtf8("gridLayout")); + viewer = new Viewer(centralwidget); + viewer->setObjectName(QString::fromUtf8("viewer")); + viewer->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + viewer->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + viewer->setRenderHints(QPainter::Antialiasing|QPainter::HighQualityAntialiasing|QPainter::SmoothPixmapTransform|QPainter::TextAntialiasing); + viewer->setCacheMode(QGraphicsView::CacheBackground); + viewer->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + + gridLayout->addWidget(viewer, 0, 0, 1, 1); + + MainWindow->setCentralWidget(centralwidget); + menubar = new QMenuBar(MainWindow); + menubar->setObjectName(QString::fromUtf8("menubar")); + menubar->setGeometry(QRect(0, 0, 810, 22)); + menuSpiel = new QMenu(menubar); + menuSpiel->setObjectName(QString::fromUtf8("menuSpiel")); + menu_Hilfe = new QMenu(menubar); + menu_Hilfe->setObjectName(QString::fromUtf8("menu_Hilfe")); + menu_Einstellungen = new QMenu(menubar); + menu_Einstellungen->setObjectName(QString::fromUtf8("menu_Einstellungen")); + menu_Cardset = new QMenu(menu_Einstellungen); + menu_Cardset->setObjectName(QString::fromUtf8("menu_Cardset")); + menu_Gametype = new QMenu(menu_Einstellungen); + menu_Gametype->setObjectName(QString::fromUtf8("menu_Gametype")); + menuSave_Game = new QMenu(menu_Einstellungen); + menuSave_Game->setObjectName(QString::fromUtf8("menuSave_Game")); + menu_Highscore = new QMenu(menubar); + menu_Highscore->setObjectName(QString::fromUtf8("menu_Highscore")); + menu_Edit = new QMenu(menubar); + menu_Edit->setObjectName(QString::fromUtf8("menu_Edit")); + MainWindow->setMenuBar(menubar); + statusbar = new QStatusBar(MainWindow); + statusbar->setObjectName(QString::fromUtf8("statusbar")); + MainWindow->setStatusBar(statusbar); + + menubar->addAction(menuSpiel->menuAction()); + menubar->addAction(menu_Edit->menuAction()); + menubar->addAction(menu_Einstellungen->menuAction()); + menubar->addAction(menu_Highscore->menuAction()); + menubar->addAction(menu_Hilfe->menuAction()); + menuSpiel->addAction(action_neues_spiel); + menuSpiel->addSeparator(); + menuSpiel->addAction(action_beenden); + menu_Hilfe->addAction(action_about); + menu_Hilfe->addAction(action_about_qt); + menu_Einstellungen->addAction(menu_Cardset->menuAction()); + menu_Einstellungen->addAction(menu_Gametype->menuAction()); + menu_Einstellungen->addAction(menuSave_Game->menuAction()); + menu_Einstellungen->addSeparator(); + menu_Einstellungen->addAction(action_rahmen); + menu_Einstellungen->addSeparator(); + menu_Cardset->addAction(action_french); + menu_Cardset->addAction(action_german); + menu_Gametype->addAction(action_eine_ziehen); + menu_Gametype->addAction(action_drei_ziehen); + menuSave_Game->addAction(action_speichern); + menuSave_Game->addAction(action_nicht_speichern); + menuSave_Game->addSeparator(); + menuSave_Game->addAction(action_fragen); + menu_Highscore->addAction(action_highscore); + menu_Edit->addAction(action_undo); + + retranslateUi(MainWindow); + + QMetaObject::connectSlotsByName(MainWindow); + } // setupUi + + void retranslateUi(QMainWindow *MainWindow) + { + MainWindow->setWindowTitle(QApplication::translate("MainWindow", "Patience", 0, QApplication::UnicodeUTF8)); + action_neues_spiel->setText(QApplication::translate("MainWindow", "&New Game", 0, QApplication::UnicodeUTF8)); + action_neues_spiel->setShortcut(QApplication::translate("MainWindow", "Ctrl+N", 0, QApplication::UnicodeUTF8)); + action_beenden->setText(QApplication::translate("MainWindow", "Close", 0, QApplication::UnicodeUTF8)); + action_about->setText(QApplication::translate("MainWindow", "About Patience", 0, QApplication::UnicodeUTF8)); + action_about_qt->setText(QApplication::translate("MainWindow", "About QT", 0, QApplication::UnicodeUTF8)); + action_french_->setText(QApplication::translate("MainWindow", "French", 0, QApplication::UnicodeUTF8)); + action_german_->setText(QApplication::translate("MainWindow", "German", 0, QApplication::UnicodeUTF8)); + action_highscore->setText(QApplication::translate("MainWindow", "&Show", 0, QApplication::UnicodeUTF8)); + action_eine_ziehen_->setText(QApplication::translate("MainWindow", "Take One", 0, QApplication::UnicodeUTF8)); + action_drei_ziehen_->setText(QApplication::translate("MainWindow", "Take Three", 0, QApplication::UnicodeUTF8)); + action_french->setText(QApplication::translate("MainWindow", "French", 0, QApplication::UnicodeUTF8)); + action_german->setText(QApplication::translate("MainWindow", "German", 0, QApplication::UnicodeUTF8)); + action_eine_ziehen->setText(QApplication::translate("MainWindow", "Take One", 0, QApplication::UnicodeUTF8)); + action_drei_ziehen->setText(QApplication::translate("MainWindow", "Take Three", 0, QApplication::UnicodeUTF8)); + action_rahmen->setText(QApplication::translate("MainWindow", "Frame", 0, QApplication::UnicodeUTF8)); + action_undo->setText(QApplication::translate("MainWindow", "Undo", 0, QApplication::UnicodeUTF8)); + action_fragen->setText(QApplication::translate("MainWindow", "Ask", 0, QApplication::UnicodeUTF8)); + action_speichern->setText(QApplication::translate("MainWindow", "Save", 0, QApplication::UnicodeUTF8)); + action_nicht_speichern->setText(QApplication::translate("MainWindow", "Don't save", 0, QApplication::UnicodeUTF8)); + menuSpiel->setTitle(QApplication::translate("MainWindow", "Game", 0, QApplication::UnicodeUTF8)); + menu_Hilfe->setTitle(QApplication::translate("MainWindow", "&Help", 0, QApplication::UnicodeUTF8)); + menu_Einstellungen->setTitle(QApplication::translate("MainWindow", "&Settings", 0, QApplication::UnicodeUTF8)); + menu_Cardset->setTitle(QApplication::translate("MainWindow", "&Cardset", 0, QApplication::UnicodeUTF8)); + menu_Gametype->setTitle(QApplication::translate("MainWindow", "Gametype", 0, QApplication::UnicodeUTF8)); + menuSave_Game->setTitle(QApplication::translate("MainWindow", "Save Game", 0, QApplication::UnicodeUTF8)); + menu_Highscore->setTitle(QApplication::translate("MainWindow", "&Highscore", 0, QApplication::UnicodeUTF8)); + menu_Edit->setTitle(QApplication::translate("MainWindow", "&Edit", 0, QApplication::UnicodeUTF8)); + } // retranslateUi + +}; + +namespace Ui { + class MainWindow: public Ui_MainWindow {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_MAINWINDOW_H diff --git a/plugins/patience_plugin/Patience/ui_Speichern_frage.h b/plugins/patience_plugin/Patience/ui_Speichern_frage.h new file mode 100644 index 000000000..1afc8a579 --- /dev/null +++ b/plugins/patience_plugin/Patience/ui_Speichern_frage.h @@ -0,0 +1,158 @@ +/******************************************************************************** +** Form generated from reading ui file 'Speichern_frage.ui' +** +** Created: Mon 8. Feb 22:40:48 2010 +** by: Qt User Interface Compiler version 4.5.2 +** +** WARNING! All changes made in this file will be lost when recompiling ui file! +********************************************************************************/ + +#ifndef UI_SPEICHERN_FRAGE_H +#define UI_SPEICHERN_FRAGE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Speichern_frage +{ +public: + QVBoxLayout *verticalLayout; + QHBoxLayout *horizontalLayout_4; + QSpacerItem *horizontalSpacer_3; + QLabel *label; + QSpacerItem *horizontalSpacer_4; + QHBoxLayout *horizontalLayout_5; + QHBoxLayout *horizontalLayout_2; + QPushButton *nein_button; + QSpacerItem *horizontalSpacer; + QHBoxLayout *horizontalLayout; + QPushButton *cancel_button; + QPushButton *ok_button; + QHBoxLayout *horizontalLayout_3; + QSpacerItem *horizontalSpacer_2; + QCheckBox *merk_box; + + void setupUi(QDialog *Speichern_frage) + { + if (Speichern_frage->objectName().isEmpty()) + Speichern_frage->setObjectName(QString::fromUtf8("Speichern_frage")); + Speichern_frage->setWindowModality(Qt::WindowModal); + Speichern_frage->resize(365, 127); + verticalLayout = new QVBoxLayout(Speichern_frage); + verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); + verticalLayout->setContentsMargins(5, -1, 5, 5); + horizontalLayout_4 = new QHBoxLayout(); + horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4")); + horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_4->addItem(horizontalSpacer_3); + + label = new QLabel(Speichern_frage); + label->setObjectName(QString::fromUtf8("label")); + QFont font; + font.setPointSize(21); + label->setFont(font); + + horizontalLayout_4->addWidget(label); + + horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_4->addItem(horizontalSpacer_4); + + + verticalLayout->addLayout(horizontalLayout_4); + + horizontalLayout_5 = new QHBoxLayout(); + horizontalLayout_5->setObjectName(QString::fromUtf8("horizontalLayout_5")); + horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2")); + nein_button = new QPushButton(Speichern_frage); + nein_button->setObjectName(QString::fromUtf8("nein_button")); + nein_button->setAutoDefault(false); + + horizontalLayout_2->addWidget(nein_button); + + horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_2->addItem(horizontalSpacer); + + + horizontalLayout_5->addLayout(horizontalLayout_2); + + horizontalLayout = new QHBoxLayout(); + horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); + cancel_button = new QPushButton(Speichern_frage); + cancel_button->setObjectName(QString::fromUtf8("cancel_button")); + cancel_button->setAutoDefault(false); + cancel_button->setDefault(true); + + horizontalLayout->addWidget(cancel_button); + + ok_button = new QPushButton(Speichern_frage); + ok_button->setObjectName(QString::fromUtf8("ok_button")); + ok_button->setAutoDefault(false); + + horizontalLayout->addWidget(ok_button); + + + horizontalLayout_5->addLayout(horizontalLayout); + + + verticalLayout->addLayout(horizontalLayout_5); + + horizontalLayout_3 = new QHBoxLayout(); + horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3")); + horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_3->addItem(horizontalSpacer_2); + + merk_box = new QCheckBox(Speichern_frage); + merk_box->setObjectName(QString::fromUtf8("merk_box")); + QFont font1; + font1.setPointSize(15); + merk_box->setFont(font1); + merk_box->setLayoutDirection(Qt::RightToLeft); + + horizontalLayout_3->addWidget(merk_box); + + + verticalLayout->addLayout(horizontalLayout_3); + + + retranslateUi(Speichern_frage); + + QMetaObject::connectSlotsByName(Speichern_frage); + } // setupUi + + void retranslateUi(QDialog *Speichern_frage) + { + Speichern_frage->setWindowTitle(QApplication::translate("Speichern_frage", "Patience - Save game and quit ?", 0, QApplication::UnicodeUTF8)); + label->setText(QApplication::translate("Speichern_frage", "Save the game and quit ?", 0, QApplication::UnicodeUTF8)); + nein_button->setText(QApplication::translate("Speichern_frage", "Don't Save", 0, QApplication::UnicodeUTF8)); + cancel_button->setText(QApplication::translate("Speichern_frage", "Cancel", 0, QApplication::UnicodeUTF8)); + ok_button->setText(QApplication::translate("Speichern_frage", "OK", 0, QApplication::UnicodeUTF8)); + merk_box->setText(QApplication::translate("Speichern_frage", "Remember answer", 0, QApplication::UnicodeUTF8)); + Q_UNUSED(Speichern_frage); + } // retranslateUi + +}; + +namespace Ui { + class Speichern_frage: public Ui_Speichern_frage {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_SPEICHERN_FRAGE_H diff --git a/plugins/plugins.pro b/plugins/plugins.pro new file mode 100644 index 000000000..f73d078b1 --- /dev/null +++ b/plugins/plugins.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs + +SUBDIRS += \ + calendar_plugin puzzle_plugin qcheckers_plugin qdiagram_plugin + + + + diff --git a/plugins/puzzle_plugin/example.jpg b/plugins/puzzle_plugin/example.jpg new file mode 100644 index 000000000..839f52a58 Binary files /dev/null and b/plugins/puzzle_plugin/example.jpg differ diff --git a/plugins/puzzle_plugin/puzzle.qrc b/plugins/puzzle_plugin/puzzle.qrc new file mode 100644 index 000000000..4076cec02 --- /dev/null +++ b/plugins/puzzle_plugin/puzzle.qrc @@ -0,0 +1,5 @@ + + + example.jpg + + diff --git a/plugins/puzzle_plugin/puzzle_plugin.pro b/plugins/puzzle_plugin/puzzle_plugin.pro new file mode 100644 index 000000000..b16864ab8 --- /dev/null +++ b/plugins/puzzle_plugin/puzzle_plugin.pro @@ -0,0 +1,37 @@ +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin debug + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(puzzle_plugin) + +HEADERS += ../PluginInterface.h \ + src/PuzzlePlugin.h +SOURCES += src/PuzzlePlugin.cpp + +#=============================================================================== + + + +#=== and here are definitions, specific for this program ======================= +HEADERS += src/mainwindow.h \ + src/pieceslist.h \ + src/puzzlewidget.h + +RESOURCES = puzzle.qrc + +SOURCES += src/mainwindow.cpp \ + src/pieceslist.cpp \ + src/puzzlewidget.cpp +#=============================================================================== diff --git a/plugins/puzzle_plugin/src/PuzzlePlugin.cpp b/plugins/puzzle_plugin/src/PuzzlePlugin.cpp new file mode 100644 index 000000000..5a132867a --- /dev/null +++ b/plugins/puzzle_plugin/src/PuzzlePlugin.cpp @@ -0,0 +1,33 @@ +//#include +//#include +//#include + +#include "PuzzlePlugin.h" +#include "mainwindow.h" + +QString +PuzzlePlugin::pluginDescription() const +{ + QString res; + res = "A simple plugin, based on QT puzzle example" ; + + return res; +} + +QString +PuzzlePlugin::pluginName() const +{ + return "Puzzle" ; +} + +QWidget* +PuzzlePlugin::pluginWidget(QWidget * parent ) +{ + MainWindow* window = new MainWindow(parent); + window->openImage(":/images/example.jpg"); + + return window; +} + + +Q_EXPORT_PLUGIN2(puzzle_plugin, PuzzlePlugin) diff --git a/plugins/puzzle_plugin/src/PuzzlePlugin.h b/plugins/puzzle_plugin/src/PuzzlePlugin.h new file mode 100644 index 000000000..2684e3c16 --- /dev/null +++ b/plugins/puzzle_plugin/src/PuzzlePlugin.h @@ -0,0 +1,27 @@ +#ifndef _HWA_PLUGIN_H_ +#define _HWA_PLUGIN_H_ + +#include + +#include +#include + +#include + +#include + +class PuzzlePlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/puzzle_plugin/src/mainwindow.cpp b/plugins/puzzle_plugin/src/mainwindow.cpp new file mode 100644 index 000000000..eca9e3428 --- /dev/null +++ b/plugins/puzzle_plugin/src/mainwindow.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information +** to ensure GNU General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. In addition, as a special +** exception, Nokia gives you certain additional rights. These rights +** are described in the Nokia Qt GPL Exception version 1.3, included in +** the file GPL_EXCEPTION.txt in this package. +** +** Qt for Windows(R) Licensees +** As a special exception, Nokia, as the sole copyright holder for Qt +** Designer, grants users of the Qt/Eclipse Integration plug-in the +** right for the Qt/Eclipse Integration to link to functionality +** provided by Qt Designer and its related libraries. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include +#include + +#include "mainwindow.h" +#include "pieceslist.h" +#include "puzzlewidget.h" + +MainWindow::MainWindow(QWidget *parent) + :QFrame(parent) + //: QMainWindow(parent) +{ + //setupMenus(); + setupWidgets(); + + setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + //setWindowTitle(tr("Puzzle")); +} + +void MainWindow::openImage(const QString &path) +{ + QString fileName = path; + + if (fileName.isNull()) + fileName = QFileDialog::getOpenFileName(this, + tr("Open Image"), "", "Image Files (*.png *.jpg *.bmp)"); + + if (!fileName.isEmpty()) { + QPixmap newImage; + if (!newImage.load(fileName)) { + QMessageBox::warning(this, tr("Open Image"), + tr("The image file could not be loaded."), + QMessageBox::Cancel); + return; + } + puzzleImage = newImage; + setupPuzzle(); + } +} + +void MainWindow::setCompleted() +{ + QMessageBox::information(this, tr("Puzzle Completed"), + tr("Congratulations! You have completed the puzzle!\n" + "Click OK to start again."), + QMessageBox::Ok); + + setupPuzzle(); +} + +void MainWindow::setupPuzzle() +{ + int size = qMin(puzzleImage.width(), puzzleImage.height()); + puzzleImage = puzzleImage.copy((puzzleImage.width() - size)/2, + (puzzleImage.height() - size)/2, size, size).scaled(400, + 400, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + piecesList->clear(); + + for (int y = 0; y < 5; ++y) { + for (int x = 0; x < 5; ++x) { + QPixmap pieceImage = puzzleImage.copy(x*80, y*80, 80, 80); + piecesList->addPiece(pieceImage, QPoint(x, y)); + } + } + + qsrand(QCursor::pos().x() ^ QCursor::pos().y()); + + for (int i = 0; i < piecesList->count(); ++i) { + if (int(2.0*qrand()/(RAND_MAX+1.0)) == 1) { + QListWidgetItem *item = piecesList->takeItem(i); + piecesList->insertItem(0, item); + } + } + + puzzleWidget->clear(); +} +/* +void MainWindow::setupMenus() +{ + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + + QAction *openAction = fileMenu->addAction(tr("&Open...")); + openAction->setShortcut(QKeySequence(tr("Ctrl+O"))); + + QAction *exitAction = fileMenu->addAction(tr("E&xit")); + exitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); + + QMenu *gameMenu = menuBar()->addMenu(tr("&Game")); + + QAction *restartAction = gameMenu->addAction(tr("&Restart")); + + connect(openAction, SIGNAL(triggered()), this, SLOT(openImage())); + connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit())); + connect(restartAction, SIGNAL(triggered()), this, SLOT(setupPuzzle())); +} +*/ +void MainWindow::setupWidgets() +{/* + QFrame *frame = new QFrame; + QHBoxLayout *frameLayout = new QHBoxLayout(frame); + + piecesList = new PiecesList; + puzzleWidget = new PuzzleWidget; + + connect(puzzleWidget, SIGNAL(puzzleCompleted()), + this, SLOT(setCompleted()), Qt::QueuedConnection); + + frameLayout->addWidget(piecesList); + frameLayout->addWidget(puzzleWidget); + setCentralWidget(frame); + */ + + QHBoxLayout *frameLayout = new QHBoxLayout(this); + + piecesList = new PiecesList; + puzzleWidget = new PuzzleWidget; + + connect(puzzleWidget, SIGNAL(puzzleCompleted()), + this, SLOT(setCompleted()), Qt::QueuedConnection); + + frameLayout->addWidget(piecesList); + frameLayout->addWidget(puzzleWidget); +} diff --git a/plugins/puzzle_plugin/src/mainwindow.h b/plugins/puzzle_plugin/src/mainwindow.h new file mode 100644 index 000000000..e44b85a02 --- /dev/null +++ b/plugins/puzzle_plugin/src/mainwindow.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information +** to ensure GNU General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. In addition, as a special +** exception, Nokia gives you certain additional rights. These rights +** are described in the Nokia Qt GPL Exception version 1.3, included in +** the file GPL_EXCEPTION.txt in this package. +** +** Qt for Windows(R) Licensees +** As a special exception, Nokia, as the sole copyright holder for Qt +** Designer, grants users of the Qt/Eclipse Integration plug-in the +** right for the Qt/Eclipse Integration to link to functionality +** provided by Qt Designer and its related libraries. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +//#include +#include + +class PiecesList; +class PuzzleWidget; +QT_BEGIN_NAMESPACE +class QListWidgetItem; +QT_END_NAMESPACE + +class MainWindow : public QFrame//QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = 0); + +public slots: + void openImage(const QString &path = QString()); + void setupPuzzle(); + +private slots: + void setCompleted(); + +private: + //void setupMenus(); + void setupWidgets(); + + QPixmap puzzleImage; + PiecesList *piecesList; + PuzzleWidget *puzzleWidget; +}; + +#endif diff --git a/plugins/puzzle_plugin/src/pieceslist.cpp b/plugins/puzzle_plugin/src/pieceslist.cpp new file mode 100644 index 000000000..14c063c02 --- /dev/null +++ b/plugins/puzzle_plugin/src/pieceslist.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information +** to ensure GNU General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. In addition, as a special +** exception, Nokia gives you certain additional rights. These rights +** are described in the Nokia Qt GPL Exception version 1.3, included in +** the file GPL_EXCEPTION.txt in this package. +** +** Qt for Windows(R) Licensees +** As a special exception, Nokia, as the sole copyright holder for Qt +** Designer, grants users of the Qt/Eclipse Integration plug-in the +** right for the Qt/Eclipse Integration to link to functionality +** provided by Qt Designer and its related libraries. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include + +#include "pieceslist.h" + +PiecesList::PiecesList(QWidget *parent) + : QListWidget(parent) +{ + setDragEnabled(true); + setViewMode(QListView::IconMode); + setIconSize(QSize(60, 60)); + setSpacing(10); + setAcceptDrops(true); + setDropIndicatorShown(true); +} + +void PiecesList::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasFormat("image/x-puzzle-piece")) + event->accept(); + else + event->ignore(); +} + +void PiecesList::dragMoveEvent(QDragMoveEvent *event) +{ + if (event->mimeData()->hasFormat("image/x-puzzle-piece")) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } else + event->ignore(); +} + +void PiecesList::dropEvent(QDropEvent *event) +{ + if (event->mimeData()->hasFormat("image/x-puzzle-piece")) { + QByteArray pieceData = event->mimeData()->data("image/x-puzzle-piece"); + QDataStream dataStream(&pieceData, QIODevice::ReadOnly); + QPixmap pixmap; + QPoint location; + dataStream >> pixmap >> location; + + addPiece(pixmap, location); + + event->setDropAction(Qt::MoveAction); + event->accept(); + } else + event->ignore(); +} + +void PiecesList::addPiece(QPixmap pixmap, QPoint location) +{ + QListWidgetItem *pieceItem = new QListWidgetItem(this); + pieceItem->setIcon(QIcon(pixmap)); + pieceItem->setData(Qt::UserRole, QVariant(pixmap)); + pieceItem->setData(Qt::UserRole+1, location); + pieceItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable + | Qt::ItemIsDragEnabled); +} + +void PiecesList::startDrag(Qt::DropActions /*supportedActions*/) +{ + QListWidgetItem *item = currentItem(); + + QByteArray itemData; + QDataStream dataStream(&itemData, QIODevice::WriteOnly); + QPixmap pixmap = qVariantValue(item->data(Qt::UserRole)); + QPoint location = item->data(Qt::UserRole+1).toPoint(); + + dataStream << pixmap << location; + + QMimeData *mimeData = new QMimeData; + mimeData->setData("image/x-puzzle-piece", itemData); + + QDrag *drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2)); + drag->setPixmap(pixmap); + + if (drag->exec(Qt::MoveAction) == Qt::MoveAction) + delete takeItem(row(item)); +} diff --git a/plugins/puzzle_plugin/src/pieceslist.h b/plugins/puzzle_plugin/src/pieceslist.h new file mode 100644 index 000000000..1f1065b58 --- /dev/null +++ b/plugins/puzzle_plugin/src/pieceslist.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information +** to ensure GNU General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. In addition, as a special +** exception, Nokia gives you certain additional rights. These rights +** are described in the Nokia Qt GPL Exception version 1.3, included in +** the file GPL_EXCEPTION.txt in this package. +** +** Qt for Windows(R) Licensees +** As a special exception, Nokia, as the sole copyright holder for Qt +** Designer, grants users of the Qt/Eclipse Integration plug-in the +** right for the Qt/Eclipse Integration to link to functionality +** provided by Qt Designer and its related libraries. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef PIECESLIST_H +#define PIECESLIST_H + +#include + +class PiecesList : public QListWidget +{ + Q_OBJECT + +public: + PiecesList(QWidget *parent = 0); + void addPiece(QPixmap pixmap, QPoint location); + +protected: + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); + void startDrag(Qt::DropActions supportedActions); +}; + +#endif diff --git a/plugins/puzzle_plugin/src/puzzlewidget.cpp b/plugins/puzzle_plugin/src/puzzlewidget.cpp new file mode 100644 index 000000000..6640877f8 --- /dev/null +++ b/plugins/puzzle_plugin/src/puzzlewidget.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information +** to ensure GNU General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. In addition, as a special +** exception, Nokia gives you certain additional rights. These rights +** are described in the Nokia Qt GPL Exception version 1.3, included in +** the file GPL_EXCEPTION.txt in this package. +** +** Qt for Windows(R) Licensees +** As a special exception, Nokia, as the sole copyright holder for Qt +** Designer, grants users of the Qt/Eclipse Integration plug-in the +** right for the Qt/Eclipse Integration to link to functionality +** provided by Qt Designer and its related libraries. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include + +#include "puzzlewidget.h" + +PuzzleWidget::PuzzleWidget(QWidget *parent) + : QWidget(parent) +{ + setAcceptDrops(true); + setMinimumSize(400, 400); + setMaximumSize(400, 400); +} + +void PuzzleWidget::clear() +{ + pieceLocations.clear(); + piecePixmaps.clear(); + pieceRects.clear(); + highlightedRect = QRect(); + inPlace = 0; + update(); +} + +void PuzzleWidget::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasFormat("image/x-puzzle-piece")) + event->accept(); + else + event->ignore(); +} + +void PuzzleWidget::dragLeaveEvent(QDragLeaveEvent *event) +{ + QRect updateRect = highlightedRect; + highlightedRect = QRect(); + update(updateRect); + event->accept(); +} + +void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event) +{ + QRect updateRect = highlightedRect.unite(targetSquare(event->pos())); + + if (event->mimeData()->hasFormat("image/x-puzzle-piece") + && findPiece(targetSquare(event->pos())) == -1) { + + highlightedRect = targetSquare(event->pos()); + event->setDropAction(Qt::MoveAction); + event->accept(); + } else { + highlightedRect = QRect(); + event->ignore(); + } + + update(updateRect); +} + +void PuzzleWidget::dropEvent(QDropEvent *event) +{ + if (event->mimeData()->hasFormat("image/x-puzzle-piece") + && findPiece(targetSquare(event->pos())) == -1) { + + QByteArray pieceData = event->mimeData()->data("image/x-puzzle-piece"); + QDataStream dataStream(&pieceData, QIODevice::ReadOnly); + QRect square = targetSquare(event->pos()); + QPixmap pixmap; + QPoint location; + dataStream >> pixmap >> location; + + pieceLocations.append(location); + piecePixmaps.append(pixmap); + pieceRects.append(square); + + highlightedRect = QRect(); + update(square); + + event->setDropAction(Qt::MoveAction); + event->accept(); + + if (location == QPoint(square.x()/80, square.y()/80)) { + inPlace++; + if (inPlace == 25) + emit puzzleCompleted(); + } + } else { + highlightedRect = QRect(); + event->ignore(); + } +} + +int PuzzleWidget::findPiece(const QRect &pieceRect) const +{ + for (int i = 0; i < pieceRects.size(); ++i) { + if (pieceRect == pieceRects[i]) { + return i; + } + } + return -1; +} + +void PuzzleWidget::mousePressEvent(QMouseEvent *event) +{ + QRect square = targetSquare(event->pos()); + int found = findPiece(square); + + if (found == -1) + return; + + QPoint location = pieceLocations[found]; + QPixmap pixmap = piecePixmaps[found]; + pieceLocations.removeAt(found); + piecePixmaps.removeAt(found); + pieceRects.removeAt(found); + + if (location == QPoint(square.x()/80, square.y()/80)) + inPlace--; + + update(square); + + QByteArray itemData; + QDataStream dataStream(&itemData, QIODevice::WriteOnly); + + dataStream << pixmap << location; + + QMimeData *mimeData = new QMimeData; + mimeData->setData("image/x-puzzle-piece", itemData); + + QDrag *drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->setHotSpot(event->pos() - square.topLeft()); + drag->setPixmap(pixmap); + + if (!(drag->exec(Qt::MoveAction) == Qt::MoveAction)) { + pieceLocations.insert(found, location); + piecePixmaps.insert(found, pixmap); + pieceRects.insert(found, square); + update(targetSquare(event->pos())); + + if (location == QPoint(square.x()/80, square.y()/80)) + inPlace++; + } +} + +void PuzzleWidget::paintEvent(QPaintEvent *event) +{ + QPainter painter; + painter.begin(this); + painter.fillRect(event->rect(), Qt::white); + + if (highlightedRect.isValid()) { + painter.setBrush(QColor("#ffcccc")); + painter.setPen(Qt::NoPen); + painter.drawRect(highlightedRect.adjusted(0, 0, -1, -1)); + } + + for (int i = 0; i < pieceRects.size(); ++i) { + painter.drawPixmap(pieceRects[i], piecePixmaps[i]); + } + painter.end(); +} + +const QRect PuzzleWidget::targetSquare(const QPoint &position) const +{ + return QRect(position.x()/80 * 80, position.y()/80 * 80, 80, 80); +} diff --git a/plugins/puzzle_plugin/src/puzzlewidget.h b/plugins/puzzle_plugin/src/puzzlewidget.h new file mode 100644 index 000000000..89b0d4287 --- /dev/null +++ b/plugins/puzzle_plugin/src/puzzlewidget.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information +** to ensure GNU General Public Licensing requirements will be met: +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. In addition, as a special +** exception, Nokia gives you certain additional rights. These rights +** are described in the Nokia Qt GPL Exception version 1.3, included in +** the file GPL_EXCEPTION.txt in this package. +** +** Qt for Windows(R) Licensees +** As a special exception, Nokia, as the sole copyright holder for Qt +** Designer, grants users of the Qt/Eclipse Integration plug-in the +** right for the Qt/Eclipse Integration to link to functionality +** provided by Qt Designer and its related libraries. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef PUZZLEWIDGET_H +#define PUZZLEWIDGET_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QDragEnterEvent; +class QDropEvent; +class QMouseEvent; +QT_END_NAMESPACE + +class PuzzleWidget : public QWidget +{ + Q_OBJECT + +public: + PuzzleWidget(QWidget *parent = 0); + void clear(); + +signals: + void puzzleCompleted(); + +protected: + void dragEnterEvent(QDragEnterEvent *event); + void dragLeaveEvent(QDragLeaveEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); + void mousePressEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event); + +private: + int findPiece(const QRect &pieceRect) const; + const QRect targetSquare(const QPoint &position) const; + + QList piecePixmaps; + QList pieceRects; + QList pieceLocations; + QRect highlightedRect; + int inPlace; +}; + +#endif diff --git a/plugins/qOrganizer_plugin/CHANGELOG.txt b/plugins/qOrganizer_plugin/CHANGELOG.txt new file mode 100644 index 000000000..5dd1504b5 --- /dev/null +++ b/plugins/qOrganizer_plugin/CHANGELOG.txt @@ -0,0 +1,183 @@ +v3.1 Update 4: + -Added Polish translation thanks to Dariusz Gadomski + -Fixed a bug that caused memory problems and crashes on 64 bit systems + -Removed compiler warning messages + -Binaries recompiled with Qt 4.4 + +v3.1 Update 3: + -Added German and French translation thanks to Jens Körner (German) and Naji Mammeri (French). + -The scrollbars in the Booklet are now synchronized. + -Added German date format to settings dialog + +v3.1 Update 2: + -Fixed some errors in the Romanian translation + -Added a Dutch translation thanks to Wouter Gelderblom + + +v3.1 Update 1: + The v3.1 release of qOrganizer has been updated, a bug was fixed(http://sourceforge.net/tracker/index.php?func=detail&aid=1808726&group_id=199558&atid=969974) + and the website url was added to the about box. + +v3.1 is another bugfix release: + +Changes: + -Fixed a bug in the journal, now text can be pasted from any source, not only images. + -Corrected minor translation errors + -Set the window title for the Settings dialog. + +Not too big changes but I feel they are needed.If you encounter any other bugs, please report them. +Thanks and enjoy! + +----------------------------------------------------------------------------------------------------------------------------------------------- +3.0 has a lot of new features, a lot of polishing went into it, let's see the changes. + +Changes in 3.0: + +-Added Estonian translation thanks to Jefim Borissov. + +-New storing modes, since many people consider storing data in text files primitive, qOrganizer v3.0 lets you choose what storing mode you want.You can choose between text files, an SQLite database or you could connect to a MySQL server over the network, the choice is yours. + +-Ability to save between storing modes. If you stored all your data in text files you can browse through all your schedules and press Save to SQLite database(on the toolbar) for the ones you want to save if you change the storing mode to SQLite, same goes for MySQL. +Although you can move all your data between storing modes, I advise you to keep the storing mode you currently use, text files are fast, +SQLite database is slower for the intensive saving operations of Autosave, but Autosave can be disabled. + +Note:The user and password of the MySQL server is stored on the local machine unencrypted so don't use any important MySQL servers. + +-You can switch between storing modes without restarting the program. + +-Search function, now you can search through all your schedules and journals it will cycle between results, when you hit the clear button in the right part of the line edit it will jump back to the current date. + +-The settings dialog get cleaned up, now it's more well organized, using tabs. + +-Now the column widths set by the user are stored and reset when the program restarts + +-University (college) students requested that I incorporate a feature that allows one to keep and switch between two timetables, one for even weeks (example:week 36) and one of odd weeks (example:week 37).It's a common habit of universities to use different timetables depending on the parity of the week index.Now qOrganizer does this.This feature can be disabled, also the normal order of weeks can be reversed, depending on what week does the university consider odd or even. + +-Drag and drop support for images in the journal. Now you can just open konqueror(or explorer) select one of your favorite images and just drag and drop it onto the journal for that day, it will be displayed and saved. + +-Fixed some bugs in the printing functions, now every title string is translated, and when printing the booklet the mark table is next to the absence table, not under. + +-Removed all xpm icons, switched to png, and replaced the toolbar icons with original nuvoX 0.7 icons (nuvoX 0.7 iconset was released under the GPL by Xavier Corredor Lliano, whom I thanks for this). + +-Added slightly modded nuvoX icons to save between storing modes to the toolbar. + +-Moved every setting to ini file in .qOrganizer folder, generated by QSettings (well except one, the path to .qOrganizer is stored in the registry with QSettings, or .config under Linux).No more config.txt. + And now you can switch between storing folders, the correct data and the settings from the ini file in that folder will be loaded, you don't need to restart the program. + +-Added dates to mark table, now you can assign a date to any mark, if there is no date assigned the current date will be shown, this can be stored in text files and database too, depending on your storing mode. I didn't insert this in the table, but added a QDateEdit next to the average fields, so it won't confuse you in the table. + +-Added "Thanks to" tab in the about dialog with the name of the contributors. + +-Fixed bugs along the way. + +-Added Albanian and Macedonian translation thanks to Driton Bakiu. + +-Added Spanish translation by Nicolas Schubert. + +Now available translations:Russian (thanks to Evgeniy Ivanov), Portuguese (thanks to Luis Bastos), Slovenian (thanks to Blaz Kure),Estonian(thanks to Jefim Borissov), Albanian and Macedonian (thanks to Driton Bakiu), Spanish(thanks to Nicolas Schubert), Hungarian and Romanian (done by me). + +Thanks to João Pinto for publishing qOrganizer v2.1 on getdeb. + +Thanks to all contributors and all users, to anyone who liked this software, + + + +Please back up the .qOrganizer folder before upgrading. +If you encounter any bugs please report them on the projects sourceforge (btw: thanks to SourceForge for hosting the project and for excellent services) page: + +http://sourceforge.net/projects/qOrganizer + +Or just write me an e-mail: balazsbela ( a t ) gmail.com +If you would like to translate qOrganizer, or request a feature, or just tell me your opinion you can contact me at the e-mail address above. +All feedback is welcomed and appreciated! + + +Usefull links: + +Project page : http://sourceforge.net/projects/qorganizer +Qt-apps.org page: http://qt-apps.org/content/show.php/qOrganizer?content=61219 +Getdeb.net page: http://www.getdeb.net/app.php?name=qOrganizer +My blog(I post much about qOrganizer):http://balazsbela.blogspot.com/ + +Enjoy! + + +----------------------------------------------------------------------------------------------------------------------------------------------- +2.1 is a bugfix release. +I am planning to make pretty radical changes to the code (like adding SQLite support to store data), school is close, the vacation is comming to an end, I don't know when I'll get those implemented so I thought I'll make a bugfix release for 2.0 to get rid of the most annoying bugs. + +Changes in 2.1: + +-Fixed that ugly bug that occures the first time when you run qOrganizer, the bug that causes the main window to not appear until you quit (this was Windows only) +-Enforced UTF8 on the config file too, so now if you have an UTF8 character in your path, it won't cause problems. +-Updated Portuguese translation. +-Made the to-do list and the timetable a lot bigger in size, so now the progress bar in the Completed column is more detailed even on Windows. +-Added saving, and jumping to the current date even when the window is hidden by clicking the systray icon. + +That's all folks. +Enjoy! + + + +----------------------------------------------------------------------------------------------------------------------------------------------- +The new release of qOrganizer comes loaded with many sweet features and is more polished than the previous releases. +The version number 2.0 is well deserved considering all improvements compared to 1.0. + +Changes in 2.0: + +-Average calculation implemented to deal with subjects separately and recalculate average for the subject when the row changes in the +mark table. Also added a textfield containing the total average (all averages are rounded and their average is calculated) + +-Added the ability to change the date format displayed (thanks for the patch to Evgeniy Ivanov (powerfox)) + +-Added a feature for uploading and downloading all data files stored by the program to a remote ftp server. +So when you go on holyday (I know it's late know :D) you just provide the details to access the ftp server hit the download button and you have immediate access to all data stored by qOrganizer. + +BIG FAT NOTE: Do not use an important ftp server for this feature, also don't use untrusted ftp servers to upload sensitive data (because all data is stored unencrypted on the server). +If you are not sure that your computer is secure do not use this feature because the password to the ftp server is stored on the local machine. +I can not be hold responsible for any damage caused by this software.This program is provided WITHOUT WARRANTY, read the file COPYING for details. +But normally you should be okay. + +-Added support for non Latin charsets :) +(again thanks to Evgeniy Ivanov for figuring this out and submitting a patch) + +-Corrected some memory leaks. + +-Added custom delegates in the tables to improve usability and the intuitively of the interface. + +-Added extra menus, and made everything accessible from the menu (or with keyboard shortcuts) + +-Added an option to reload data when the view changes. +This feature was suggested by Blaz Kure, it improves using multiple computers with one folder of settings stored on a network drive. + +-Added a column labeled Start to represent the date when a task was started. + +-Made the timetable headers translatable. + +-Added sound to reminders, when a reminder hits a sound is played. +I used a sound from k3b, since it's under GPL, the file named:k3b_success1.wav. +Of course this setting can be turned off in the settings dialog. + +-A lot of bug fixes! + +-Added translations: Portuguese (thanks to Luis Bastos (http://programaslivres.net/)), Slovenian (thanks to Blaz Kure), Russian (thanks to Evgeniy Ivanov). + +BIG THANKS TO ALL TRANSLATORS :) +AND A SPECIAL THANKS TO Evgeniy Ivanov for his contributions. + +Please back up the .qOrganizer folder before upgrading, the to-do list will be broken because of the new Start column, everything else should be fine.Of course adjust all settings. + +If you encounter any bugs please report them on the projects sourceforge (btw: thanks to SourceForge for hosting the project and for excellent services) page: + +http://sourceforge.net/projects/qOrganizer + +Or just write me an e-mail: balazsbela ( a t ) gmail.com +If you would like to translate qOrganizer, or request a feature, or just tell me your opinion you can contact me at the e-mail address above. +All feedback is welcomed and appreciated! + +And as always, enjoy! + + + + + diff --git a/plugins/qOrganizer_plugin/COPYING b/plugins/qOrganizer_plugin/COPYING new file mode 100644 index 000000000..5b6e7c66c --- /dev/null +++ b/plugins/qOrganizer_plugin/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/plugins/qOrganizer_plugin/application.qrc b/plugins/qOrganizer_plugin/application.qrc new file mode 100644 index 000000000..b99dffcc8 --- /dev/null +++ b/plugins/qOrganizer_plugin/application.qrc @@ -0,0 +1,36 @@ + + + images/settings.png + images/save.png + images/splash.png + images/icon.png + images/icon.png + images/logo.png + images/booklet.png + images/timetable.png + images/todo.png + images/calendar.png + images/print.png + images/exit.png + images/upload.png + images/download.png + lang/Hungarian.qm + lang/Romanian.qm + lang/Slovenian.qm + lang/Portuguese.qm + lang/Russian.qm + lang/Estonian.qm + lang/Spanish.qm + lang/Albanian.qm + lang/Macedonian.qm + lang/Dutch.qm + lang/German.qm + lang/French.qm + lang/Polish.qm + images/sound.wav + images/clear.png + images/upload.png + images/databasesqlite.png + images/databasemysql.png + + diff --git a/plugins/qOrganizer_plugin/delegates.cpp b/plugins/qOrganizer_plugin/delegates.cpp new file mode 100644 index 000000000..4ac481f93 --- /dev/null +++ b/plugins/qOrganizer_plugin/delegates.cpp @@ -0,0 +1,280 @@ +/*************************************************************************** + * Copyright (C) 2007 by Balázs Béla * + * balazsbela@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation version 2 of the License * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "delegates.h" + +//----------------------------------------------------Absence table delegate------------------------------------------------ +absenceDelegate::absenceDelegate(QObject *parent) : QItemDelegate(parent) +{ +} + +QWidget *absenceDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option*/,const QModelIndex &/*index*/) const +{ + QDateEdit *editor = new QDateEdit(QDate::currentDate(),parent); + editor->setDisplayFormat("dd/M/yyyy"); + editor->setCalendarPopup(true); + return editor; +} + +void absenceDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const +{ + QDateEdit *dateEditor = qobject_cast(editor); + if (dateEditor) + dateEditor->setDate(QDate::fromString(index.model()->data(index, Qt::EditRole).toString(), "d/M/yyyy")); +} + + +void absenceDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const +{ + + QDateEdit *dateEditor = qobject_cast(editor); + if (dateEditor) + model->setData(index, dateEditor->date().toString("dd/M/yyyy")); + +} + +void absenceDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + +//----------------------------------------------------To-do list delegate---------------------------------------------------- + +todoDelegate::todoDelegate(QObject* parent): QItemDelegate(parent) +{ +} + +void todoDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + if(index.column()==4) + { + int progress = index.model()->data(index, Qt::EditRole).toInt(); + //lets draw our cool progress bar here + QStyleOptionProgressBar opt; + opt.rect = option.rect; + opt.minimum = 0; + opt.maximum = 100; + opt.progress = progress; + opt.text = QString("%1%").arg(progress); + opt.textVisible = true; + QApplication::style()->drawControl(QStyle::CE_ProgressBar, &opt, painter, 0); + } + else + QItemDelegate::paint(painter, option, index); +} + +QWidget *todoDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option*/,const QModelIndex &index) const +{ + if((index.column()==2)||(index.column()==0)) + { + QDateEdit *editor = new QDateEdit(QDate::currentDate(),parent); + editor->setDisplayFormat("dd/M/yyyy"); + editor->setCalendarPopup(true); + return editor; + } + else + if(index.column()==3) + { + QComboBox *editor = new QComboBox(parent); + editor -> setEditable(true); + for(int i=1;i<=10;i++) editor->addItem(QString::number(i)); + return editor; + } + else + if(index.column()==1) + { + QLineEdit *editor = new QLineEdit(parent); + return editor; + } + if(index.column()==4) + { + QLineEdit *editor = new QLineEdit(parent); + return editor; + } +} + +void todoDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const +{ + if((index.column()==2)||(index.column()==0)) + { + QDateEdit *dateEditor = qobject_cast(editor); + if (dateEditor) { + model->setData(index, dateEditor->date().toString("dd/M/yyyy"));} + } + else + if(index.column()==3) + { + QComboBox *priorityBox = static_cast(editor); + if (priorityBox) + model->setData(index, priorityBox->currentText()); + } + else + if(index.column()==1) + { + QLineEdit *taskEdit = static_cast(editor); + if (taskEdit) + model->setData(index, taskEdit->text()); + } + if(index.column()==4) + { + QLineEdit *taskEdit = static_cast(editor); + if (taskEdit) + model->setData(index, taskEdit->text()); + } +} + +void todoDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + +//----------------------------------------------------Schedule Delegate ----------------------------------------------------------- + +scheduleDelegate::scheduleDelegate(QObject *parent) : QItemDelegate(parent) +{ +} + +QWidget *scheduleDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option*/,const QModelIndex &index) const +{ + + if(index.column()!=0) + { + QTimeEdit *editor = new QTimeEdit(QTime::currentTime().addSecs(60),parent); + editor->setDisplayFormat("hh:mm"); + return editor; + } + else + { + QLineEdit *editor = new QLineEdit(parent); + return editor; + } +} + +void scheduleDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const +{ + if(index.column()!=0) + { + QTimeEdit *timeEditor = qobject_cast< QTimeEdit *>(editor); + if (timeEditor) + model->setData(index, timeEditor->time().toString("hh:mm")); + } + else + { + QLineEdit *eventEdit = static_cast(editor); + if (eventEdit) + model->setData(index, eventEdit->text()); + } +} + +void scheduleDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + + +//---------------------------------------------------Time Table Delegate ------------------------------------------------------ + +timeTableDelegate::timeTableDelegate(QObject *parent) : QItemDelegate(parent) +{ +} + +QWidget *timeTableDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option*/,const QModelIndex &index) const +{ + + if((index.column()==0)||(index.column()==1)) + { + QTimeEdit *editor = new QTimeEdit(QTime::currentTime().addSecs(60),parent); + editor->setDisplayFormat("hh:mm"); + return editor; + } + else + { + QLineEdit *editor = new QLineEdit(parent); + return editor; + } +} + +void timeTableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const +{ + if((index.column()==0)||(index.column()==1)) + { + QTimeEdit *timeEditor = qobject_cast< QTimeEdit *>(editor); + if (timeEditor) + model->setData(index, timeEditor->time().toString("hh:mm")); + } + else + { + QLineEdit *eventEdit = static_cast(editor); + if (eventEdit) + model->setData(index, eventEdit->text()); + } +} + +void timeTableDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + + +//-------------------------------------------MARK TABLE DELEGATE + +//---------------------------------------------------Time Table Delegate ------------------------------------------------------ + +markDelegate::markDelegate(QObject *parent) : QItemDelegate(parent) +{ +} + +QWidget *markDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option*/,const QModelIndex &index) const +{ + + if(index.column() % 2!=0) + { + QDateEdit *editor = new QDateEdit(QDate::currentDate(),parent); + editor->setDisplayFormat("d.M.yy"); + editor->setCalendarPopup(true); + return editor; + } + else + { + QLineEdit *editor = new QLineEdit(parent); + return editor; + } +} + +void markDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const +{ + if(index.column() % 2!=0) + { + QDateEdit *dateEditor = qobject_cast(editor); + if (dateEditor) { + model->setData(index, dateEditor->date().toString("d.M.yy"));} + } + else + { + QLineEdit *markEdit = static_cast(editor); + if (markEdit) + model->setData(index, markEdit->text()); + } +} + +void markDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/* index */) const +{ + editor->setGeometry(option.rect); +} + diff --git a/plugins/qOrganizer_plugin/delegates.h b/plugins/qOrganizer_plugin/delegates.h new file mode 100644 index 000000000..2fea6cc8a --- /dev/null +++ b/plugins/qOrganizer_plugin/delegates.h @@ -0,0 +1,98 @@ +/*************************************************************************** + * Copyright (C) 2007 by Balázs Béla * + * balazsbela@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation version 2 of the License * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +#ifndef DELEGATES_H +#define DELEGATES_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//The delegate for the absence table +class absenceDelegate : public QItemDelegate +{ + Q_OBJECT + public: + absenceDelegate(QObject *parent = 0); + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const; + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const; + void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + +//The delegate for the absence table +class markDelegate : public QItemDelegate +{ + Q_OBJECT + public: + markDelegate(QObject *parent = 0); + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const; + void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + + +//Delegate for the to-do list +class todoDelegate: public QItemDelegate +{ + Q_OBJECT + public: + todoDelegate(QObject *parent = 0); + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const; + void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + +//Delegate for the schedule + +class scheduleDelegate : public QItemDelegate +{ + Q_OBJECT + public: + scheduleDelegate(QObject *parent = 0); + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const; + void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + +class timeTableDelegate : public QItemDelegate +{ + Q_OBJECT + public: + timeTableDelegate(QObject *parent = 0); + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const; + void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + + + +#endif diff --git a/plugins/qOrganizer_plugin/images/booklet.png b/plugins/qOrganizer_plugin/images/booklet.png new file mode 100644 index 000000000..df0589bd1 Binary files /dev/null and b/plugins/qOrganizer_plugin/images/booklet.png differ diff --git a/plugins/qOrganizer_plugin/images/calendar.png b/plugins/qOrganizer_plugin/images/calendar.png new file mode 100644 index 000000000..45ce3d54e Binary files /dev/null and b/plugins/qOrganizer_plugin/images/calendar.png differ diff --git a/plugins/qOrganizer_plugin/images/clear.png b/plugins/qOrganizer_plugin/images/clear.png new file mode 100644 index 000000000..90aec98cb Binary files /dev/null and b/plugins/qOrganizer_plugin/images/clear.png differ diff --git a/plugins/qOrganizer_plugin/images/databasemysql.png b/plugins/qOrganizer_plugin/images/databasemysql.png new file mode 100644 index 000000000..4cb5fa81b Binary files /dev/null and b/plugins/qOrganizer_plugin/images/databasemysql.png differ diff --git a/plugins/qOrganizer_plugin/images/databasesqlite.png b/plugins/qOrganizer_plugin/images/databasesqlite.png new file mode 100644 index 000000000..015023e81 Binary files /dev/null and b/plugins/qOrganizer_plugin/images/databasesqlite.png differ diff --git a/plugins/qOrganizer_plugin/images/download.png b/plugins/qOrganizer_plugin/images/download.png new file mode 100644 index 000000000..2d85aebb1 Binary files /dev/null and b/plugins/qOrganizer_plugin/images/download.png differ diff --git a/plugins/qOrganizer_plugin/images/exit.png b/plugins/qOrganizer_plugin/images/exit.png new file mode 100644 index 000000000..87c5c00d7 Binary files /dev/null and b/plugins/qOrganizer_plugin/images/exit.png differ diff --git a/plugins/qOrganizer_plugin/images/icon.png b/plugins/qOrganizer_plugin/images/icon.png new file mode 100644 index 000000000..78d2468dc Binary files /dev/null and b/plugins/qOrganizer_plugin/images/icon.png differ diff --git a/plugins/qOrganizer_plugin/images/icon64.png b/plugins/qOrganizer_plugin/images/icon64.png new file mode 100644 index 000000000..c598cb084 Binary files /dev/null and b/plugins/qOrganizer_plugin/images/icon64.png differ diff --git a/plugins/qOrganizer_plugin/images/logo.png b/plugins/qOrganizer_plugin/images/logo.png new file mode 100644 index 000000000..0592104ea Binary files /dev/null and b/plugins/qOrganizer_plugin/images/logo.png differ diff --git a/plugins/qOrganizer_plugin/images/print.png b/plugins/qOrganizer_plugin/images/print.png new file mode 100644 index 000000000..8b00d14cb Binary files /dev/null and b/plugins/qOrganizer_plugin/images/print.png differ diff --git a/plugins/qOrganizer_plugin/images/save.png b/plugins/qOrganizer_plugin/images/save.png new file mode 100644 index 000000000..226019c39 Binary files /dev/null and b/plugins/qOrganizer_plugin/images/save.png differ diff --git a/plugins/qOrganizer_plugin/images/settings.png b/plugins/qOrganizer_plugin/images/settings.png new file mode 100644 index 000000000..8bc7711c5 Binary files /dev/null and b/plugins/qOrganizer_plugin/images/settings.png differ diff --git a/plugins/qOrganizer_plugin/images/sound.wav b/plugins/qOrganizer_plugin/images/sound.wav new file mode 100644 index 000000000..7a42a2b9f Binary files /dev/null and b/plugins/qOrganizer_plugin/images/sound.wav differ diff --git a/plugins/qOrganizer_plugin/images/splash.png b/plugins/qOrganizer_plugin/images/splash.png new file mode 100644 index 000000000..a66a13591 Binary files /dev/null and b/plugins/qOrganizer_plugin/images/splash.png differ diff --git a/plugins/qOrganizer_plugin/images/timetable.png b/plugins/qOrganizer_plugin/images/timetable.png new file mode 100644 index 000000000..499c9feef Binary files /dev/null and b/plugins/qOrganizer_plugin/images/timetable.png differ diff --git a/plugins/qOrganizer_plugin/images/todo.png b/plugins/qOrganizer_plugin/images/todo.png new file mode 100644 index 000000000..1b3a65c7f Binary files /dev/null and b/plugins/qOrganizer_plugin/images/todo.png differ diff --git a/plugins/qOrganizer_plugin/images/upload.png b/plugins/qOrganizer_plugin/images/upload.png new file mode 100644 index 000000000..2c849a766 Binary files /dev/null and b/plugins/qOrganizer_plugin/images/upload.png differ diff --git a/plugins/qOrganizer_plugin/lang/Albanian.qm b/plugins/qOrganizer_plugin/lang/Albanian.qm new file mode 100644 index 000000000..a09f78c9e Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Albanian.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Albanian.ts b/plugins/qOrganizer_plugin/lang/Albanian.ts new file mode 100644 index 000000000..7c97ae933 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Albanian.ts @@ -0,0 +1,867 @@ + + + + + SettingsDialog + + + Some settings require restarting qOrganizer + Që të kenë efekt disa ndryshime, duhet që të restartohet qOrganizer + + + + Path to data folder: + Rruga deri te folderi i të të dhënave: + + + + Browse + Kërko + + + + Reminder check interval: + Intervali i kohës mes përkujtimeve: + + + + First day of week: + Dita e parë e javës: + + + + Monday + E Hënë + + + + Tuesday + E Martë + + + + Wednesday + E Mërkurë + + + + Thursday + E Ejnte + + + + Friday + E Premte + + + + Saturday + E Shtunë + + + + Sunday + E Diellë + + + + Date format: + Formati i datës: + + + + Autosave: + Ruajtje automatike: + + + + Remind type: + Tipi i përkujtimit: + + + + Language: + Gjuha: + + + + Row number for empty schedule: + Numri i rreshtit për orar të zhprazët: + + + + Round subject averages when calculating total average + Nota e rrumbullakësuar mesatare, pas kalkulimit të mesatares totale + + + + Show saving buttons on toolbar + Paraqiti butonet e ruajtjes në shiritin punues + + + + Cancel + Anulo + + + + Reload data on view change + Ringarko të të dhënat në ndryshim të pikëpamjes + + + + Hide to system tray on close + Fshehu në shiritin e sistemit në mbyllje + + + + Port: + Port-i: + + + + Host: + Host-i: + + + + Username: + Emri: + + + + Password: + Passoword-i: + + + + Path on ftp server: + Rruga deri te server-i i FTP-s: + + + + Synchronize with ftp server: + Sinkronizo me serverin e FTP-s: + + + + Play sound on remind + Lësho zër në mbikujtim + + + + Use different timetables for even and odd weeks + Përdor orarë të ndryshëm per javë tek dhe çift + + + + Reverse normal order of weeks for timetable + Rënditje e kundërt e javëve per orar + + + + Text files + File-a teksti + + + + SQLite database + Baza e të të dhënave SQLite + + + + MySQL database + Baza e të të dhënave MySQL + + + + Store data in: + Ruaj të dhënat në: + + + + Database name: + Emri i bazës së të dhënave: + + + + FTP synchronization is not available for MySQL database + Sinkronizimi i FTP-s nuk është në dizpozicion për bazën e të të dhënave MySQL + + + + &General + &Gjenerale + + + + &Calendar + &Kalendar + + + + FTP + FTP + + + + Storing + Ruajtje + + + + Select Directory + Zgjedhe folder-in + + + + aboutDialog + + + About + Për ne + + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + <br>Ky software është i licencuar me GPL verzionin 2 <br>i publikuar nga Fondacioni i Software-it të Lirë (FSF).<br> + +<br>Ky aplikacion ka për qëllim që të ju sjell lehtësi në jetën e juaj <br> duke organizuar të dhënat e juaja në mënyrë intiutive që çdoherë të mund të gjejni atë që ju duhet dhe që asnjëherë mos të harroni diçka të rëndësishme.<br>Ky aplikacion është kryesisht i paramenduar për studentë, duke <br>ju sjellur disa veçori që ata mund t'i gjejnë të dobishme.<br> + + + + + Thanks to + Në sajë të + + + + qOrganizer + + + &Calendar + &Kalendar + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + Calendar + Kalendar + + + + Save + Ruaj + + + + Ctrl+Y + Ctrl+Y + + + + &SQLite Database + &SQLite baza e të të dhënave + + + + Ctrl+D + Ctrl+D + + + + Save to SQLite database + Ruaj në SQLite bazën e të të dhënave + + + + &MySQL Database + &MySQL baza e të të dhënave + + + + Ctrl+M + Ctrl+M + + + + Save to MySQL database + Ruaj në MySQL bazën e të të dhënave + + + + &Text files + &File-a teksti + + + + Ctrl+T + Ctrl+T + + + + Save to text files + Ruaj në file-a teksti + + + + &To-do List + &Lista e detyrave + + + + Ctrl+Alt+T + Ctrl+Alt+T + + + + Edit your to-do list + Ndryshoje listën për-të-bërë + + + + To-do list + Lista e detyrave + + + + &TimeTable + &Orar + + + + Ctrl+Alt+L + Ctrl+Alt+L + + + + Edit your timetable + Ndryshoje orarin tënd + + + + Timetable + Orar + + + + &Booklet + &Broshurë + + + + Ctrl+Alt+B + Ctrl+Alt+B + + + + Keep track of your school marks and absences + Ndjeki notat dhe mungesat e tuaja në shkollë + + + + Booklet + Broshurë + + + + &Print + &Shtyp + + + + Ctrl+P + Ctrl+P + + + + Print Page + Shtyp faqen + + + + E&xit + D&alje + + + + Ctrl+Q + Ctrl+Q + + + + Exit the application + Dil prej aplikacioni + + + + &About + &Për + + + + Show the application's About box + Demonstro kutinë Për, të aplikacionit + + + + About &Qt + About &Qt + + + + Show the Qt library's About box + Paraqit kutinë Për, të Qt bibliotekës + + + + &Upload + &Ngarko + + + + Ctrl+Alt+U + Ctrl+Alt+U + + + + Upload data to FTP server + Ngarko të dhëna në server FTP + + + + &Download + &Shkarko + + + + Ctrl+Alt+W + Ctrl+Alt+W + + + + Download data from FTP server + Shkarko të dhëna prej FTP serveri + + + + &Settings + &Setinze + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Configure application + Konfiguroje aplikacionin + + + + &File + &File-i + + + + Save to + Ruaj në + + + + &View + &Shiko + + + + FT&P + FT&P + + + + &Help + &Help + + + + File + File-i + + + + Ready + Gati + + + + Schedule for + Orar për + + + + Event + Ngjarje + + + + From + Prej + + + + Until + Deri + + + + Reminder + Përkujtues + + + + New event + Ngjarje e re + + + + Delete event + Fshij ngjarjen + + + + B + B + + + + I + I + + + + U + U + + + + Important notes, journal for + Shënime të rëndësishme, ditar për + + + + Search: + Kërko: + + + + General to-do list + Lista gjenerale e detyrave + + + + Start + Nis + + + + Task + Detyra + + + + Deadline + Afat i fundit + + + + Priority + Prioritet + + + + Completed + Kryer + + + + New task + Detyrë e re + + + + Delete task + Detyra të fshiera + + + + Monday + E Hënë + + + + Tuesday + E Martë + + + + Wednesday + E Merkurë + + + + Thursday + E Ejnte + + + + Friday + E Premte + + + + New row + Rresht i ri + + + + New column + Vargë i ri + + + + Delete column + Fshi vargun + + + + Delete row + Fshi rreshtin + + + + Timetable for: + Orar për: + + + + Odd weeks + Javë tek + + + + Even weeks + Javë çift + + + + English + Anglisht + + + + Math + Matematikë + + + + IT + Informatikë + + + + History + Histori + + + + Geography + Gjeografi + + + + Biology + Biologji + + + + Physics + Fizikë + + + + Chemistry + Kimi + + + + New mark column + Varg i ri i notave + + + + New subject + Lëndë e re + + + + Delete subject + Fshij lëndën + + + + Delete mark column + Fshij vargun e notave + + + + New absence column + Varg i mungesave i ri + + + + Delete absence column + Fshij vargun e mungesave + + + + Subject average: + Mesatarja e lëndës: + + + + Absences: + Mungesa: + + + + Total average: + Mesatarje e përgjithshme: + + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Nuk është vënduar përkujtuesi! +Egzistojnë dy formate të pranueshme për përkujtues. +Njëri format është hh:mm +Shembull: 17:58. +Mënyra tjetër është t'a shkruajsh orën. +Shembull: 3 është e barabartëme 3:00 ose me 03:00 + + + + Column name: + Emri i vargut: + + + + Saturday + E shtunë + + + + Subject name: + Emri i lëndës: + + + + + + + + + General to-do list: + Lista "Detyra" gjenerale: + + + + Marks: + Notat: + + + + Uploading... + Duke ngarkuar... + + + + Downloading... + Duke shkarukuar... + + + + Done! + Kryer! + + + + Done + Kryer + + + + Download finished! + Shkarkimi mbaroi! + + + + Couldn't download files: + + Shkarkimi i këtyre file-ave ishte i pamundur: + + + + Upload finished! + Ngarkimi mbaroi! + + + + Error + Gabim + + + + Couldn't upload files: + + File-at nuk janë ngarkuar: + + + + Previous + Më para + + + + Next + Tjetër + + + + Date: + Data: + + + + Could not connect to database! + Nuk është bërë lidhja me bazën e të të dhënave! + + + + No entries found! + Asnjë hyrje nuk është gjetur! + + + diff --git a/plugins/qOrganizer_plugin/lang/Dutch.qm b/plugins/qOrganizer_plugin/lang/Dutch.qm new file mode 100644 index 000000000..00ddc2a59 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Dutch.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Estonian.qm b/plugins/qOrganizer_plugin/lang/Estonian.qm new file mode 100644 index 000000000..ba32cf7a6 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Estonian.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Estonian.ts b/plugins/qOrganizer_plugin/lang/Estonian.ts new file mode 100644 index 000000000..1c97305a5 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Estonian.ts @@ -0,0 +1,1098 @@ + + + + + SettingsDialog + + + Some settings require restarting qOrganizer + Mõned sätted vajavad qOrganizeri taaskäivitust + + + + Path to data folder: + Tee andme kaustani: + + + + Browse + Sirvi + + + + Reminder check interval: + Meeldetuletuste kontrolli ajavahemik: + + + + First day of week: + Esimene nädala päev: + + + + Monday + Esmaspäev + + + + Tuesday + Teisipäev + + + + Wednesday + Kolmapäev + + + + Thursday + Neljapäev + + + + Friday + Reede + + + + Saturday + Laupäev + + + + Sunday + Pühapäev + + + + Date format: + Kuupäeva formaat: + + + + Autosave: + Autosalvestamine: + + + + Remind type: + Meeldetuletuste tüüp: + + + + Language: + Keel: + + + + Row number for empty schedule: + Ridade number tühjas ajakavas: + + + + Round subject averages when calculating total average + Ümarda aine keskmine üldise keskmise arvutamisel + + + + Show saving buttons on toolbar + Näita salvestamise nuppe tööriistarabal + + + + Cancel + Loobu + + + + Reload data on view change + Värskenda andmed kui vaade muutub + + + + Hide to system tray on close + Peida system tray-sse kinnitamisel + + + + Port: + Port: + + + + Host: + Host: + + + + Username: + Kasutajanimi: + + + + Password: + Parool: + + + + Path on ftp server: + Kaust FTP serveril: + + + + Synchronize with ftp server: + Sünkroniseeri FTP-serveriga: + + + + Play sound on remind + Tavita heliga meeldetulemusel + + + + Use different timetables for even and odd weeks + Kasuta erinevad ajakavad paaris ja paaritu nädalatel + + + + Reverse normal order of weeks for timetable + Pööra ümber nädalate kord ajakavas + + + + Text files + Teksti fail + + + + SQLite database + SQLite andmebaas + + + + MySQL database + MySQL andmebaas + + + + Store data in: + Salvesta andmed: + + + + Database name: + Andmebaasi nimi: + + + + FTP synchronization is not available for MySQL database + FTP sünkroniseerimine ei tööta MySQL andmebaasi korral + + + + &General + &Üldine + + + + &Calendar + &Kalender + + + + FTP + FTP + + + + Storing + Salvestamine + + + + Select Directory + Vali kaust + + + + aboutDialog + + + About + Teave + + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + +<br>Käesolev tarkvara on levitatud GPL v2 litsensiga, avaldatud Free Software Foundation poolt.<br> + +<br>Käesolev programmi sihiks on teie elu lihtsustamine intuitiivse planeerimisega, niiet te alati leiate infot mida otsite ning kunagi ei unusta tähtsaid asju.<br>Käesolev tarkvara on mõeldud tudengitele ning selle funktsionaalsus koosneb nendest asjadest, mis on nendele kasulik. <br> + + + + + Thanks to + Tänan ka + + + + qOrganizer + + + About qOrganizer + Teate qOrganizeri kohta + + + + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + + +<img src=:/images/logo.png><br> + + +<br>This software is licenced under GPL version 2 published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by organizing your data in an intuitive way so you can always find what you need and never forget something important.<br>This application focuses on students, providing the features they consider usefull.<br><br> +Special thanks to:my girlfriend for supporting me, to my friends for testing this application,and to Xavier Corredor Llano, for releasing the nuvoX iconset under GPL</b> + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> +E-mail:balazsbela@gmail.com<br> + +<img src=:/images/logo.png><br> +<br>Käesolev tarkvara on levitatud GPL v2 litsensiga, avaldatud Free Software Foundation poolt.<br> +<br>Käesolev programmi sihiks on teie elu lihtsustamine intuitiivse planeerimisega, niiet te alati leiate infot mida otsite ning kunagi ei unusta tähtsaid asju.<br>Käesolev tarkvara on mõeldud tudengitele ning selle funktsionaalsus koosneb nendest asjadest, mis on nendele kasulik.<br><br> +Tänud minu neiule toetuse eest, minu sõpradele programmi testimise eest ning Xavier Corredor Llanole nuvoX ikoonide GPL litsensi eest.</b> + + + + &Calendar + &Kalender + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + Calendar + Kalender + + + + Save + Salvesta + + + + Ctrl+S + Ctrl+S + + + + &To-do List + To-do &nimekiri + + + + Ctrl+Alt+T + Ctrl+Alt+T + + + + Edit your to-do list + Redigeeri oma to-do minekiri + + + + To-do list + To-do nimekiri + + + + &TimeTable + &Ajakava + + + + Ctrl+Alt+L + Ctrl+Alt+L + + + + Edit your timetable + Redigeeri ajakava + + + + Timetable + Ajakava + + + + &Booklet + &Päevik + + + + Ctrl+Alt+B + Ctrl+Alt+B + + + + Keep track of your school marks and absences + Jälgi oma kooli hindeid ning puudumisi + + + + Booklet + Päevik + + + + &Print + &Prindi + + + + Ctrl+P + Ctrl+P + + + + Print Page + Prindi leht + + + + E&xit + &Välju + + + + Ctrl+Q + Ctrl+Q + + + + Exit the application + Välju programmist + + + + &About + &Programmist + + + + Show the application's About box + Näita teate qOrganizeri kohta + + + + About &Qt + Teate &Qt kohta + + + + Show the Qt library's About box + Näita teate Qt-st kohta + + + + &Upload + &Lae üles + + + + Ctrl+Alt+U + Ctrl+Alt+U + + + + Upload data to FTP server + Lae andmed FTP serverile üles + + + + &Download + &Tõmba alla + + + + Ctrl+Alt+W + Ctrl+Alt+W + + + + Download data from FTP server + Tõmba andmed FTP-serverist alla + + + + &Settings + &Sätted + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Configure application + Muuda sätted + + + + &File + &Fail + + + + &View + &Vaade + + + + &FTP + &FTP + + + + &Help + &Abi + + + + File + Fail + + + + Ready + Valmis + + + + <center><font size="5">Schedule for + <center><font size="5">Ajakava + + + + :</font></center> + :</font></center> + + + + Event + Sündmus + + + + From + Algus + + + + Until + Lõpp + + + + Reminder + Meeldetuletus + + + + New event + Uus sündmus + + + + Delete event + Kustuta sündmust + + + + B + B + + + + I + I + + + + U + U + + + + <font size="5">Important notes, journal for + <font size="5">Tähtsad märged, päevik + + + + :</font> + :</font> + + + + <center><font size="5" >General to-do list:</center> + <center><font size="5" >Üldine to-do nimekiri:</center> + + + + Start + Start + + + + Task + Tegevus + + + + Deadline + Tähtaeg + + + + Priority + Prioriteet + + + + Completed + Valmis + + + + New task + Uus tegevus + + + + Delete task + Kustuta tegevust + + + + <center><font size="5">Timetable:</font></center> + <center><font size="5">Ajakava:</font></center> + + + + Monday + Esmaspäev + + + + Tuesday + Teisipäev + + + + Wednesday + Kolmapäev + + + + Thursday + Neljapäev + + + + Friday + Reede + + + + New row + Uus rida + + + + New column + Uus veerg + + + + Delete column + Kustuta veerg + + + + Delete row + Kustuta rida + + + + <center><font size="5">Booklet</font></center> + <center><font size="5">Päevik</font></center> + + + + <center>Marks:</center> + <center>Hinned</center> + + + + <center>Absences:</center> + <center>Puudumised:<center> + + + + English + Inglise keel + + + + Math + matemaatika + + + + IT + IT + + + + History + Ajalugu + + + + Geography + Geograafia + + + + Biology + Bioloogia + + + + Physics + Füüsika + + + + Chemistry + Keemia + + + + New mark column + Uus hinnete veerg + + + + New subject + Uus aine + + + + Delete subject + Kustuta aine + + + + Delete mark column + Kustuta hinnete veerg + + + + New absence column + Uus puudumiste veerg + + + + Delete absence column + Kustuta puudumiste veerg + + + + Subject average: + Aine keskmine hinne: + + + + Absences: + Puudumised: + + + + Total average: + Keskmine hinne: + + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Ei õnnestunud meeldetuletust lisada! +Kasutage järgmiseid formaate aega määramiseks: +1. hh:mm (näide: 17:58) +2. h (näide: 3 - tähendab 03:00) + + + + Column name: + Veeru nimi: + + + + Saturday + Laupäev + + + + Subject name: + Aine nimi: + + + + Uploading... + Laen üles... + + + + Downloading... + Tõmban alla... + + + + Done! + Valmis! + + + + Done + Valmis + + + + Download finished! + Alla tõmbamine on lõppenud! + + + + Couldn't download files: + + Ei saanud alla tõmmata faile: + + + + + Upload finished! + Üles laadimine on lõppenud! + + + + Error + Viga + + + + Couldn't upload files: + + Ei saanud üles laadima failid: + + + + + + + + + + Ctrl+Y + Ctrl+Y + + + + &SQLite Database + &SQLite andmebaas + + + + Ctrl+D + Ctrl+D + + + + Save to SQLite database + Salvesta SQLite andmebaasi + + + + &MySQL Database + &MySQL andmebaas + + + + Ctrl+M + Ctrl+M + + + + Save to MySQL database + Salvesta MySQL andmebaasi + + + + &Text files + &Teksti failid + + + + Ctrl+T + Ctrl+T + + + + Save to text files + Salvesta teksti failidesse + + + + Save to + Salvesta + + + + FT&P + FT&P + + + + Schedule for + Ajakava + + + + Important notes, journal for + Tähtsad märjed, päevik + + + + Search: + Otsi: + + + + General to-do list + Üldine to-do nimekiri + + + + Timetable for: + Ajakava: + + + + Odd weeks + Paaris nädalad + + + + Even weeks + Paaritu nädalad + + + + General to-do list: + Üldine to-do nimekiri: + + + + Marks: + Hinned: + + + + Previous + Eelmine + + + + Next + Järgmine + + + + Date: + Kuupäev: + + + + Could not connect to database! + Ei õnnestunud andmebaasiga ühendada! + + + + No entries found! + Ei leidnud ühtegi kirjet! + + + + settings + + + Some settings require restarting qOrganizer + Mõned sätted vajavad qOrganizeri taaskäivitust + + + + Config folder's path: + Sätete kausta asukoht: + + + + Browse + Sirvi + + + + Reminder check interval: + Meeldetuletuste kontrolli ajavahemik: + + + + First day of week: + Esimene nädala päev: + + + + Monday + Esmaspäev + + + + Tuesday + Teisipäev + + + + Wednesday + Kolmapäev + + + + Thursday + Neljapäev + + + + Friday + Reede + + + + Saturday + Laupäev + + + + Sunday + Pühapäev + + + + Date format: + Kuupäeva formaat: + + + + Autosave: + Autosalvestamine: + + + + Remind type: + Meeldetuletuste tüüp: + + + + Language: + Keel: + + + + Row number for empty schedule: + Ridade number tühjas ajakavas: + + + + Cancel + Loobu + + + + Reload data on view change + Värskenda andmed kui vaade muutub + + + + Hide to system tray on close + Peida system tray-sse kinnitamisel + + + + Port: + Port: + + + + Host: + Host: + + + + Username: + Kasutajanimi: + + + + Password: + Parool: + + + + Path on ftp server: + Kaust FTP serveril: + + + + Synchronize with ftp server: + Sünkroniseeri FTP-serveriga: + + + + Play sound on remind + Tavita heliga meeldetulemusel + + + + Select Directory + Vali kaust + + + + &Calendar + &Kalender + + + diff --git a/plugins/qOrganizer_plugin/lang/French.qm b/plugins/qOrganizer_plugin/lang/French.qm new file mode 100644 index 000000000..9c0488f09 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/French.qm differ diff --git a/plugins/qOrganizer_plugin/lang/French.ts b/plugins/qOrganizer_plugin/lang/French.ts new file mode 100644 index 000000000..f00fd91f6 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/French.ts @@ -0,0 +1,705 @@ + + + SettingsDialog + + &Settings + &Paramètres + + + Some settings require restarting qOrganizer + Quelques paramètres nécessitent le redémarrage de qOrganizer pour être prises en compte + + + Path to data folder: + Chemin vers le dossier des données : + + + Browse + Parcourir + + + Reminder check interval: + Intervalle de vérification du mémo : + + + First day of week: + Premier jour de la semaine : + + + Monday + Lundi + + + Tuesday + Mardi + + + Wednesday + Mercredi + + + Thursday + Jeudi + + + Friday + Vendredi + + + Saturday + Samedi + + + Sunday + Dimanche + + + Date format: + Format de date : + + + Autosave: + Sauvegarde automatique : + + + Remind type: + Type de mémo : + + + Language: + Langue : + + + Row number for empty schedule: + Numéro de ligne pour un calendrier vide : + + + Round subject averages when calculating total average + Arrondir les moyennes de matières lors du calcul de la moyenne générale + + + Show saving buttons on toolbar + Afficher les boutons de sauvegarde sur la barre d'outils + + + Cancel + Annuler + + + Reload data on view change + Recharger les données après un changement de vue + + + Hide to system tray on close + Cacher dans la zone de notification système à la fermeture + + + Port: + Port : + + + Host: + Hôte : + + + Username: + Nom d'utilisateur : + + + Password: + Mot de passe : + + + Path on ftp server: + Chemin du serveur FTP : + + + Synchronize with ftp server: + Synchroniser avec le serveur FTP : + + + Play sound on remind + Jouer un son au mémo + + + Use different timetables for even and odd weeks + Utiliser des emplois du temps différents pour les semaines paires et impaires + + + Reverse normal order of weeks for timetable + Inverser l'ordre normal des semaines pour l'emploi du temps + + + Text files + Fichiers texte + + + SQLite database + Base de données SQLite + + + MySQL database + Base de données MySQL + + + Store data in: + Sauver les données dans : + + + Database name: + Nom de la base de données : + + + FTP synchronization is not available for MySQL database + La synchronisation FTP n'est pas disponible pour des bases de données MySQL + + + &General + &Général + + + &Calendar + &Calendrier + + + FTP + FTP + + + Storing + Sauvegarde + + + Select Directory + Choisissez le répertoire + + + + aboutDialog + + About + À propos + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + +<br>Ce logiciel est sous la licence GPL v2,<br>telle que publiée par la Free Software Foundation.<br> + +<br>Cette application vise à apporter un peu de simplicité dans votre vie en<br>organisant vos données d'une manière intuitive de manière à ce que vous puissiez toujours<br>trouver ce dont vous avez besoin et ne jamais oublier quelque chose d'important.<br> Cette application est principalement destinée à des étudiants, leur offrant les fonctionnalités qu'ils considèrent utiles.<br> + + + + Thanks to + Remerciements à + + + + qOrganizer + + &Calendar + &Calendrier + + + Ctrl+Alt+C + Ctrl+Alt+C + + + Calendar + Calendrier + + + Save + Sauvegarder + + + Ctrl+Y + Ctrl+Y + + + &SQLite Database + Base de données &SQLite + + + Ctrl+D + Ctrl+D + + + Save to SQLite database + Sauvegarder dans la base de données SQL + + + &MySQL Database + Base de données &MySQL + + + Ctrl+M + Ctrl+M + + + Save to MySQL database + Sauvegarder dans la base de données MySQL + + + &Text files + Fichiers &texte + + + Ctrl+T + Ctrl+T + + + Save to text files + Sauvegarde dans des fichiers texte + + + &To-do List + &Liste "À faire" + + + Ctrl+Alt+T + Ctrl+Alt+T + + + Edit your to-do list + Modifier la liste "À faire" + + + To-do list + Liste "À faire" + + + &TimeTable + Emploi du &temps + + + Ctrl+Alt+L + Ctrl+Alt+L + + + Edit your timetable + Modifier votre emploi du temps + + + Timetable + Emploi du temps + + + &Booklet + &Carnet de notes + + + Ctrl+Alt+B + Ctrl+Alt+B + + + Keep track of your school marks and absences + Gardez une trace de vos notes scolaires et de vos absences + + + Booklet + Carnet de notes + + + &Print + Im&primer + + + Ctrl+P + Ctrl+P + + + Print Page + Imprimer la page + + + E&xit + &Quitter + + + Ctrl+Q + Ctrl+Q + + + Exit the application + Quitter l'application + + + &About + &À propos + + + Show the application's About box + Afficher la fenêtre d'informations du logiciel + + + About &Qt + À propos de &Qt + + + Show the Qt library's About box + Afficher la fenêtre d'informations de Qt + + + &Upload + &Uploader + + + Ctrl+Alt+U + Ctrl+Alt+U + + + Upload data to FTP server + Envoyer les données sur le serveur FTP + + + &Download + &Télécharger + + + Ctrl+Alt+W + Ctrl+Alt+W + + + Download data from FTP server + Télécharge les données du serveur FTP + + + &Settings + &Paramètres + + + Ctrl+Alt+S + Ctrl+Alt+S + + + Configure application + Configurer l'application + + + &File + &Fichier + + + Save to + Sauvegarder sous + + + &View + &Vue + + + FT&P + FT&P + + + &Help + &Aide + + + File + Fichier + + + Ready + Prêt + + + Schedule for + Calendrier pour + + + Event + Évènement + + + From + De + + + Until + À + + + Reminder + Mémo + + + New event + Nouvel évènement + + + Delete event + Supprimer l'évènement + + + B + G + + + I + I + + + U + S + + + Important notes, journal for + Notes importantes, journal pour + + + Search: + Rechercher : + + + Previous + Précédent + + + Next + Suivant + + + General to-do list + Liste "À faire" générale + + + Start + Début + + + Task + Tâche + + + Deadline + Date limite + + + Priority + Priorité + + + Completed + Complété + + + New task + Nouvelle tâche + + + Delete task + Supprimer la tâche + + + Monday + Lundi + + + Tuesday + Mardi + + + Wednesday + Mercredi + + + Thursday + Jeudi + + + Friday + Vendredi + + + New row + Nouvelle ligne + + + New column + Nouvelle colonne + + + Delete column + Supprimer la colonne + + + Delete row + Supprimer la ligne + + + Timetable for: + Emploi du temps pour : + + + Odd weeks + Semaines impaires + + + Even weeks + Semaines paires + + + Marks: + Notes : + + + Absences: + Absences : + + + English + Français + + + Math + Maths + + + IT + Informatique + + + History + Histoire + + + Geography + Géographie + + + Biology + Biologie + + + Physics + Physique + + + Chemistry + Chimie + + + New mark column + Nouvelle colonne de notes + + + New subject + Nouvelle matière + + + Delete subject + Supprimer la matière + + + Delete mark column + Supprimer la colonne de notes + + + New absence column + Nouvelle colonne d'absences + + + Delete absence column + Supprimer la colonne d'absences + + + Subject average: + Moyenne de la matière : + + + Date: + Date : + + + Total average: + Moyenne générale : + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Impossible de configurer le mémo ! +Il y a deux formats possibles pour le mémo : +Un est hh:mm (exemple : 17:58), +L'autre consiste à n'écrire que l'heure (exemple : 3 équivaut à 03:00) + + + + Column name: + Nom de la colonne : + + + Saturday + Samedi + + + Subject name: + Nom de la matière : + + + + + + + General to-do list: + Liste "À faire" générale : + + + Uploading... + Envoi... + + + Downloading... + Téléchargement... + + + Done! + Fait ! + + + Done + Fait + + + Download finished! + Téléchargement achevé ! + + + Couldn't download files: + + Impossible de télécharger les fichiers : + + + + Upload finished! + Envoi achevé ! + + + Error + Erreur + + + Couldn't upload files: + + Impossible d'envoyer les fichiers : + + + + Could not connect to database! + Impossible de se connecter à la base de données ! + + + + No entries found! + Aucune entrée trouvée ! + + + diff --git a/plugins/qOrganizer_plugin/lang/German.qm b/plugins/qOrganizer_plugin/lang/German.qm new file mode 100644 index 000000000..c68874056 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/German.qm differ diff --git a/plugins/qOrganizer_plugin/lang/German.ts b/plugins/qOrganizer_plugin/lang/German.ts new file mode 100644 index 000000000..b178655cf --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/German.ts @@ -0,0 +1,875 @@ + + + + + SettingsDialog + + + &Settings + &Einstellungen + + + + Some settings require restarting qOrganizer + Einige Einstellungen erfordern einen Neustart von qOrganizer + + + + Path to data folder: + Pfad zum Datenverzeichnis: + + + + Browse + Suchen + + + + Reminder check interval: + Mit diesem Zeitabstand soll eine Daten-Durchsuchung auf Erinnerungen hin erfolgen: + + + + First day of week: + Erster Wochentag: + + + + Monday + Montag + + + + Tuesday + Dienstag + + + + Wednesday + Mittwoch + + + + Thursday + Donnerstag + + + + Friday + Freitag + + + + Saturday + Samstag + + + + Sunday + Sonntag + + + + Date format: + Format des Datums: + + + + Autosave: + Automatische Sicherung: + + + + Remind type: + Art der Erinnerung: + + + + Language: + Sprache: + + + + Row number for empty schedule: + Reihenanzahl einer leeren Tabelle : + + + + Round subject averages when calculating total average + Einzelbeträge beim Berechnen einer gerundeten Gesamtsumme mit runden + + + + Show saving buttons on toolbar + Zeige die Symbole zum Abspeichern in der Symbolleiste + + + + Cancel + Abbrechen + + + + Reload data on view change + Daten bei Darstellungswechseln neu einlesen + + + + Hide to system tray on close + Beim Verlassen im 'System Tray' verbergen + + + + Port: + Port: + + + + Host: + Host: + + + + Username: + Benutzername: + + + + Password: + Passwort: + + + + Path on ftp server: + Pfad zum FTP-Server: + + + + Synchronize with ftp server: + Mit diesem FTP-Server abgleichen: + + + + Play sound on remind + Bei Erinnerungen einen Klang abspielen + + + + Use different timetables for even and odd weeks + Unterschiedliche Stundenpläne für gerade und ungerade Wochen benutzen + + + + Reverse normal order of weeks for timetable + Umgekehrte Reihenfolge der Wochen im Stundenplan + + + + Text files + Textdateien + + + + SQLite database + SQLite-Datenbank + + + + MySQL database + MySQL-Datenbank + + + + Store data in: + Speichern der Daten in: + + + + Database name: + Datenbank-Name: + + + + FTP synchronization is not available for MySQL database + Der FTP-Abgleich funktioniert nicht bei der Benutzung einer MySQL-Datenbank + + + + &General + &Allgemein + + + + &Calendar + &Kalender + + + + FTP + FTP + + + + Storing + Datenspeicherung + + + + Select Directory + Verzeichnis auswählen + + + + aboutDialog + + + About + Über + + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + +<br>Diese Software fällt unter die GPL Lizenz Version 2 <br> der Free Software Foundation.<br> + +<br>Diese Anwendung lässt vieles einfacher werden.<br> Termine werden sinnvoll geordnet und sind damit<br> immer greifbar, nichts wichtiges wird vergessen. <br>Das Programm ist in erster Linie für Studenten gedacht, <br>da sie genau das bietet, was diese als nützlich erachten. <br> + + + + + Thanks to + Mein Dank geht an + + + + qOrganizer + + + &Calendar + &Kalender + + + + Ctrl+Alt+C + Ctrl+Alt+K + + + + Calendar + Kalender + + + + Save + Speichern + + + + Ctrl+Y + Ctrl+Y + + + + &SQLite Database + &SQLite + + + + Ctrl+D + Ctrl+D + + + + Save to SQLite database + Speicherung in einer SQLite-Datenbank + + + + &MySQL Database + &MySQL + + + + Ctrl+M + Ctrl+M + + + + Save to MySQL database + Speichern in einer MySQL-Datenbank + + + + &Text files + &Text-Dateien + + + + Ctrl+T + Ctrl+T + + + + Save to text files + In einer Textdatei abspeichern + + + + &To-do List + &Zu-Erledigen-Liste + + + + Ctrl+Alt+T + Ctrl+Alt+Z + + + + Edit your to-do list + Die Zu-Erledigen-Liste ändern + + + + To-do list + Zu-Erledigen-Liste + + + + &TimeTable + &Stundenplan + + + + Ctrl+Alt+L + Ctrl+Alt+S + + + + Edit your timetable + Den Stundenplan anpassen + + + + Timetable + Stundenplan + + + + &Booklet + &Notizliste + + + + Ctrl+Alt+B + Ctrl+Alt+N + + + + Keep track of your school marks and absences + Übersicht über schulische Leistung und Abwesenheit + + + + Booklet + Notizliste + + + + &Print + &Drucken + + + + Ctrl+P + Ctrl+D + + + + Print Page + Seite ausdrucken + + + + E&xit + &Verlassen + + + + Ctrl+Q + Ctrl+Q + + + + Exit the application + Die Anwendung beenden + + + + &About + &Über + + + + Show the application's About box + Zeige die Kurzinformationen dieser Anwendug + + + + About &Qt + Über &Qt + + + + Show the Qt library's About box + Zeige die Kurzinformationen über die Qt-Bibliotheken + + + + &Upload + &Hochladen + + + + Ctrl+Alt+U + Ctrl+Alt+H + + + + Upload data to FTP server + Zu einem FTP-Server hochladen + + + + &Download + &Herunterladen + + + + Ctrl+Alt+W + Ctrl+Alt+W + + + + Download data from FTP server + Von einem FTP-Server herunterladen + + + + &Settings + &Einstellungen + + + + Ctrl+Alt+S + Ctrl+Alt+E + + + + Configure application + Die Einstellungen der Anwendung ändern + + + + &File + &Datei + + + + Save to + Speichern in + + + + &View + &Öffnen + + + + FT&P + FT&P + + + + &Help + &Hilfe + + + + File + Datei + + + + Ready + Fertig + + + + Schedule for + Terminplan vom + + + + Event + Termin + + + + From + Von + + + + Until + Bis + + + + Reminder + Benachrichtigung + + + + New event + Neuer Termin + + + + Delete event + Termin löschen + + + + B + Fett + + + + I + Schräg + + + + U + Unterstrichen + + + + Important notes, journal for + Wichtige Notizen, Protokoll für + + + + Search: + Suche: + + + + Previous + Vorheriges + + + + Next + Nächstes + + + + General to-do list + Übersicht + + + + Start + Beginn + + + + Task + Aufgabe + + + + Deadline + Ende + + + + Priority + Dringlichkeitsstufe + + + + Completed + Abgeschlossen + + + + New task + Neue Aufgabe + + + + Delete task + Aufgabe löschen + + + + Monday + Montag + + + + Tuesday + Dienstag + + + + Wednesday + Mittwoch + + + + Thursday + Donnerstag + + + + Friday + Freitag + + + + New row + Neue Zeile + + + + New column + Neue Spalte + + + + Delete column + Spalte löschen + + + + Delete row + Zeile löschen + + + + Timetable for: + Stundenplan für: + + + + Odd weeks + Ungerade Wochen + + + + Even weeks + Gerade Wochen + + + + Marks: + Benotungen: + + + + Absences: + Abwesenheiten: + + + + English + Englisch + + + + Math + Mathematik + + + + IT + IT + + + + History + Geschichte + + + + Geography + Geografie + + + + Biology + Biologie + + + + Physics + Physik + + + + Chemistry + Chemie + + + + New mark column + Neue Notenspalte + + + + New subject + Neues Fach + + + + Delete subject + Fach löschen + + + + Delete mark column + Benotungsspalte löschen + + + + New absence column + Neue Abwesenheitsspalte + + + + Delete absence column + Abwesenheitsspalte löschen + + + + Subject average: + Fachdurchschnitt: + + + + Date: + Datum: + + + + Total average: + Gesamtdurchschnitt: + + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Der Erinnerer kann nicht eingstellt werden! +Es sind zwei Verschiedene Formate dafür möglich. +Das erste ist hh:mm. +Beispiel:17:58. +Beim anderen wird lediglich die Stunde eingetragen. +Beispiel: 3 wird wie 3:00 oder wie 03:00 interpretiert + + + + Column name: + Spaltenname: + + + + Saturday + Samstag + + + + Subject name: + Fach-Name: + + + + + + + + + General to-do list: + Terminübersicht: + + + + Uploading... + Hochladen... + + + + Downloading... + Herunterladen... + + + + Done! + Fertig! + + + + Done + Fertig + + + + Download finished! + Das Herunterladen ist beendet! + + + + Couldn't download files: + + Die Dateien konnten nicht heruntergeladen werden: + + + + + Upload finished! + Hochladen beendet! + + + + Error + Fehler + + + + Couldn't upload files: + + Die Dateien konnten nicht hochgeladen werden: + + + + + Could not connect to database! + Es konnte keine Verbindung zur Datenbank hergestellt werden! + + + + No entries found! + Keine Einträge gefunden! + + + diff --git a/plugins/qOrganizer_plugin/lang/Hungarian.qm b/plugins/qOrganizer_plugin/lang/Hungarian.qm new file mode 100644 index 000000000..225beced5 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Hungarian.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Hungarian.ts b/plugins/qOrganizer_plugin/lang/Hungarian.ts new file mode 100644 index 000000000..d21a59d17 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Hungarian.ts @@ -0,0 +1,1188 @@ + + + + + SettingsDialog + + + Some settings require restarting qOrganizer + Egyes beállitások igénylik a program újrainditását + + + + Path to data folder: + Út az adatok mappájához: + + + + Browse + Tallóz + + + + Reminder check interval: + Emlékeztető ellenörzési intervallum: + + + + First day of week: + A hét első napja: + + + + Monday + Hétfő + + + + Tuesday + Kedd + + + + Wednesday + Szerda + + + + Thursday + Csütörtök + + + + Friday + Péntek + + + + Saturday + Szombat + + + + Sunday + Vasárnap + + + + Date format: + Dátum formátum: + + + + Autosave: + Automatikus mentes: + + + + Remind type: + Emlékeztető tipusa: + + + + Language: + Nyelv: + + + + Row number for empty schedule: + Sorok száma üres ütemtervben: + + + + Round subject averages when calculating total average + Tantárgy átlagok kerekitése teljes átlag kiszámolásakor + + + + Show saving buttons on toolbar + Mentés gombok megjelenitése + + + + Cancel + Mégse + + + + Reload data on view change + Adatok újratöltése nézetváltáskor + + + + Hide to system tray on close + Elrejtés a tálcára bezáráskor + + + + Port: + Port: + + + + Host: + Cím: + + + + Username: + Felhasználónév: + + + + Password: + Jelszó: + + + + Path on ftp server: + Út az FTP szerveren: + + + + Synchronize with ftp server: + Szinkronizálás FTP szerverrel: + + + + Play sound on remind + Hang lejátszása emlékeztetéskor + + + + Use different timetables for even and odd weeks + Különböző órarend páros és páratlan hetekre + + + + Reverse normal order of weeks for timetable + Hetek sorrendjének megforditása + + + + Text files + Szöveges állományok + + + + SQLite database + SQLite adatbázis + + + + MySQL database + MySQL adatbázis + + + + Store data in: + Adatok tárolási módja: + + + + Database name: + Adatbázis neve: + + + + FTP synchronization is not available for MySQL database + MySQL adatbázis nem szinkronizálható FTP szerverrel + + + + &General + &Általános + + + + &Calendar + &Kalendárium + + + + FTP + FTP + + + + Storing + Tárolás + + + + Select Directory + Mappa kiválasztása + + + + aboutDialog + + + About + Névjegy + + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + <br>Ez a szoftver a, Szabad Szoftver Alapitvány által kiadott, <br> GPL 2 licensz alatt van engedélyezve.<br> + <br>A program célja az egyszerüség, intuitiv felületével rendezi a fontos<br> + információkat igy biztositva hogy nem feledkezünk meg róluk,<br> bárhol lennénk. +<br>Különös hangsúlyt fektet a diákok igényeire.<br><br> + + + + Thanks to + Köszönet + + + + qOrganizer + + + About qOrganizer + qOrganizer névjegy + + + + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + + +<img src=:/logo.png><br> + + +<br>This software is licenced under GPL version 2 published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by organizing your data in an intuitive way so you can always find what you need and never forget something important.<br>This application focuses on students, providing the features they consider usefull.<br><br> +Special thanks to:my girlfriend for supporting me, to my friends for testing this application,and to Xavier Corredor Llano, for releasing the nuvoX iconset under GPL</b> + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br>E-mail:balazsbela@gmail.com<br><img src=:/logo.png><br><br>Ez a szoftver a Szabad Szoftver Alapitvány GPL 2. licence alatt van engedélyezve<br><br>A program célja az egyszerüség, intuitiv felületével rendezi a számunkra fontos információkat igy biztositva hogy nem feledkezünk meg róluk. <br>Különös hangsúlyt fektet a diákok igényeire.<br><br> Köszönet:a barátnőmnek amiért támogatott a fejlesztés során, a barátaimnak akik tesztelték ezt az alkalmazást és Xavier Corredor Llano-nak aki GPL alatt adta ki a nuvoX ikonszettet amit felhasználtam ikonaim készitésekor</b> + + + + &Calendar + &Kalendárium + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + Calendar + Kalendárium + + + + Save + Mentés + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + &To-do List + &Tennivalók listája + + + + Ctrl+Alt+T + Ctrl+Alt+T + + + + Edit your to-do list + Szerkeszd a tennivalóid listáját + + + + To-do list + Tennivalók listája + + + + &TimeTable + &Órarend + + + + Ctrl+Alt+L + Ctrl+Alt+L + + + + Edit your timetable + Szerkeszd az órarended + + + + Timetable + Órarend + + + + &Booklet + &Ellenörző + + + + Ctrl+Alt+B + Ctrl+Alt+B + + + + Keep track of your school marks and absences + Kövesd nyomon a jegyeidet és hiányzásaidat + + + + Booklet + Ellenörző + + + + &Print + &Nyomtat + + + + Ctrl+Alt+P + Ctrl+Alt+P + + + + Print Page + Oldal nyomtatása + + + + E&xit + &Kilépés + + + + Ctrl+Q + Ctrl+Q + + + + Exit the application + Kilépés az alkalmazásból + + + + &About + &Névjegy + + + + Show the application's About box + Megmutatja az alkalmazás névjegyét + + + + About &Qt + A &Qt névjegye + + + + Show the Qt library's About box + Megmutatja a Qt könyvtárak névjegyét + + + + &File + &Állomány + + + + &Help + &Súgó + + + + File + Állomány + + + + Ready + Készenlét + + + + Event + Esemény + + + + From + Kezdet + + + + Until + Vég + + + + Reminder + Emlékeztető + + + + New event + Új esemény + + + + Delete event + Esemény törlése + + + + B + F + + + + I + D + + + + U + A + + + + <center><font size="5" >General to-do list:</center> + <center><font size="5" >Általános tennivalólista:</center> + + + + Task + Tennivaló + + + + Deadline + Határidő + + + + Priority + Fontosság + + + + Completed + Befelyezett + + + + New task + Új tennivaló + + + + Delete task + Tennivaló törlése + + + + <center><font size="5">Timetable:</font></center> + <center><font size="5">Órarend:</font></center> + + + + Monday + Hétfő + + + + Tuesday + Kedd + + + + Wednesday + Szerda + + + + Thursday + Csütörtök + + + + Friday + Péntek + + + + New row + Új sor + + + + New column + Új oszlop + + + + Delete column + Oszlop törlése + + + + Delete row + Sor törlése + + + + Average: + Átlag: + + + + Absences: + Hiányzások: + + + + Column name: + Oszlop neve: + + + + Saturday + Szombat + + + + Subject name: + Tantárgy neve: + + + + + + + + + <center><font size="5">Schedule for + <center><font size="5">Ütemterv: + + + + :</font></center> + </font></center> + + + + <font size="5">Important notes, jurnal for + <font size="5"> Fontos jegyzetek napló: + + + + :</font> + </font> + + + + <center><font size="5">Booklet</font></center> + <center><font size="5">Ellenörző</font></center> + + + + <center>Marks:</center> + <center>Jegyek:</center> + + + + <center>Absences:</center> + <center>Hiányzások:</center> + + + + English + Angol + + + + Math + Matematika + + + + IT + Informatika + + + + History + Tortenelem + + + + Geography + Foldrajz + + + + Biology + Biologia + + + + Physics + Fizika + + + + Chemistry + Kemia + + + + New mark column + Új jegy oszlop + + + + New subject + Új tantárgy + + + + Delete subject + Tantárgy törlése + + + + Delete mark column + Jegy oszlop törlése + + + + New absence column + Új hiányzás oszlop + + + + Delete absence column + Hiányzás oszlop törlése + + + + Ctrl+S + Ctrl+S + + + + &Settings + &Beállitások + + + + Configure application + Az alkalmazás beállitásai + + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Emlékeztető beállitása sikertelen! +Az emlékeztetőknek két elfogadott formátumuk van. +Az egyik óra:perc . +Példa:17:58 +A másik pedig csak az óra. +Példa: 3 egyenlő 3:00 vagy 03:00 + + + + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + + +<img src=:/images/logo.png><br> + + +<br>This software is licenced under GPL version 2 published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by organizing your data in an intuitive way so you can always find what you need and never forget something important.<br>This application focuses on students, providing the features they consider usefull.<br><br> +Special thanks to:my girlfriend for supporting me, to my friends for testing this application,and to Xavier Corredor Llano, for releasing the nuvoX iconset under GPL</b> + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br>E-mail:balazsbela@gmail.com<br><img src=:/images/logo.png><br><br>Ez a szoftver a Szabad Szoftver Alapitvány GPL 2. licence alatt van engedélyezve<br><br>A program célja az egyszerüség, intuitiv felületével rendezi a számunkra fontos információkat igy biztositva hogy nem feledkezünk meg róluk. <br>Különös hangsúlyt fektet a diákok igényeire.<br><br> Köszönet:a barátnőmnek amiért támogatott a fejlesztés során, a barátaimnak akik tesztelték ezt az alkalmazást és Xavier Corredor Llano-nak aki GPL alatt adta ki a nuvoX ikonszettet amit felhasználtam ikonaim készitésekor</b> + + + + <font size="5">Important notes, journal for + <font size="5">Fontos jegyzetek,naplo: + + + + Subject average: + Tantárgy átlag: + + + + Total average: + Teljes átlag: + + + + &Upload + &Feltöltés + + + + Ctrl+Alt+U + Ctrl+Alt+U + + + + Upload data to FTP server + Adatok feltöltése FTP szerverre + + + + &Download + &Letöltés + + + + Ctrl+Alt+W + Ctrl+Alt+W + + + + Download data from FTP server + Adatok letöltése FTP szerverröl + + + + Uploading... + Feltöltés... + + + + Downloading... + Letölt... + + + + Done! + Kész! + + + + Done + Kész + + + + Download finished! + Letöltés befejeződött! + + + + Couldn't download files: + + Adatok letöltése sikertelen: + + + + + Upload finished! + Feltöltés befejeződött! + + + + Error + Hiba + + + + Couldn't upload files: + + Adatok feltöltése sikertelen: + + + + &View + &Nézet + + + + &FTP + &FTP + + + + Ctrl+P + Ctrl+P + + + + Start + Kezdet + + + + Ctrl+Y + Ctrl+Y + + + + &SQLite Database + &SQLite adatbázis + + + + Ctrl+D + Ctrl+D + + + + Save to SQLite database + Mentés SQLite adatbázisba + + + + &MySQL Database + &MySQL adatbázis + + + + Ctrl+M + Ctrl+M + + + + Save to MySQL database + Mentés MySQL adatbázisba + + + + &Text files + &Szöveg + + + + Ctrl+T + Ctrl+T + + + + Save to text files + Mentés szöveges állományokba + + + + Save to + Mentés + + + + FT&P + FT&P + + + + Schedule for + Ütemterv + + + + Important notes, journal for + Fontos jegyzetek, napló + + + + Search: + Keresés: + + + + General to-do list + Általános tennivalólista + + + + Timetable for: + Órarend: + + + + Odd weeks + Páratlan hetekre + + + + Even weeks + Páros hetekre + + + + General to-do list: + Általános tennivalólista: + + + + Marks: + Jegyek: + + + + Marks + Jegyek + + + + Next + Következő + + + + Previous + Előző + + + + Could not connect to database! + Adatbázis csatlakozás létrehozása sikertelen! + + + + No entries found! + Nincs találat! + + + + Date: + Dátum: + + + + settings + + + Config folder's path: + Út a beállitás mappához: + + + + Reminder check interval: + Emlékeztető ellenörzési intervallum: + + + + First day of week: + A hét első napja: + + + + Monday + Hétfő + + + + Tuesday + Kedd + + + + Wednesday + Szerda + + + + Thursday + Csütörtök + + + + Friday + Péntek + + + + Saturday + Szombat + + + + Sunday + Vasárnap + + + + Autosave: + Automatikus mentes: + + + + Remind type: + Emlékeztető tipusa: + + + + Cancel + Mégse + + + + Select Directory + Mappa kiválasztása + + + + Browse + Tallóz + + + + Language: + Nyelv: + + + + Row number for empty schedule: + Sorok száma üres ütemtervben: + + + + Some settings require restarting qOrganizer + Egyes beállitások igénylik a program újrainditását + + + + Date format: + Dátum formátum: + + + + Port: + Port: + + + + Host: + Cím: + + + + Username: + Felhasználónév: + + + + Password: + Jelszó: + + + + Synchronize with ftp server: + Szinkronizálás FTP szerverrel: + + + + Path on ftp server: + Út az FTP szerveren: + + + + Reload data on view change + Adatok újratöltése nézetváltáskor + + + + Hide to system tray on close + Elrejtés a tálcára bezáráskor + + + + Play sound on remind + Hang lejátszása emlékeztetéskor + + + + Text files + Szöveges állományok + + + + SQLite database + SQLite adatbázis + + + + Store data in: + Adatok tárolási módja: + + + + Use different timetables for even and odd weeks + Különböző órarend páros és páratlan hetekre + + + + Reverse normal order of weeks for timetable + Hetek sorrendjének megforditása + + + + MySQL database + MySQL adatbázis + + + + Database name: + Adatbázis neve: + + + + FTP synchronization is not available for MySQL database + MySQL adatbázis nem szinkronizálható FTP szerverrel + + + + &General + &Általános + + + + &Calendar + &Kalendárium + + + + FTP + FTP + + + + Storing + Tárolás + + + + Path to data folder: + Út az adatok mappájához: + + + diff --git a/plugins/qOrganizer_plugin/lang/Macedonian.qm b/plugins/qOrganizer_plugin/lang/Macedonian.qm new file mode 100644 index 000000000..879d6a2e7 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Macedonian.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Macedonian.ts b/plugins/qOrganizer_plugin/lang/Macedonian.ts new file mode 100644 index 000000000..a7289ab17 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Macedonian.ts @@ -0,0 +1,866 @@ + + + + + SettingsDialog + + + Some settings require restarting qOrganizer + За да имаат ефект некои промени, qOrganizer мора да се рестартира + + + + Path to data folder: + Патот до folder-от на податоци: + + + + Browse + Побарај + + + + Reminder check interval: + Интервал на проверки на потсетникот: + + + + First day of week: + Првиот ден на неделата: + + + + Monday + Понеделник + + + + Tuesday + Вторник + + + + Wednesday + Среда + + + + Thursday + Четврток + + + + Friday + Петок + + + + Saturday + Сабота + + + + Sunday + Недела + + + + Date format: + Формат на датумите: + + + + Autosave: + Автоматско зачувување: + + + + Remind type: + Типот на потсетување: + + + + Language: + Јазик: + + + + Row number for empty schedule: + Број на ред за празен распоред: + + + + Round subject averages when calculating total average + Заобиколен број на просек на предмети откако се пресметува вкупниот просек + + + + Show saving buttons on toolbar + Покажи ги копчињата Зачувај во toolbar-от + + + + Cancel + Прекини + + + + Reload data on view change + Вчитувај ги податоците пак во случај на промена на гледната точка + + + + Hide to system tray on close + Скриј се во system tray-от на излез + + + + Port: + Port: + + + + Host: + Host: + + + + Username: + Корисничко име: + + + + Password: + Лозинка: + + + + Path on ftp server: + Патот во FTP серверот: + + + + Synchronize with ftp server: + Синхронизирај со FTP сервер: + + + + Play sound on remind + Пушти звук на потсетување + + + + Use different timetables for even and odd weeks + Користи различен распоред за парни и непарни недели + + + + Reverse normal order of weeks for timetable + Сврти го наопаку нормалниот тек на недели за распоред + + + + Text files + Текст file-ови + + + + SQLite database + SQLite база на податоци + + + + MySQL database + MySQL база на податоци + + + + Store data in: + Складирај податоци во: + + + + Database name: + Името на базата на податоци: + + + + FTP synchronization is not available for MySQL database + FTP синхронизација не е достапна за MySQL база на податоци + + + + &General + &Генерално + + + + &Calendar + &Календар + + + + FTP + FTP + + + + Storing + Складирање + + + + Select Directory + Одбери Folder + + + + aboutDialog + + + About + За + + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + +<br>Овој software е лиценциран под GPL втора верзија <br>публицирано од Фондацијата на Слободен Софтвер. <br> + +<br>Оваа апликација цели кон донесување на едноставност во твојот живот со <br> организирање на твоите податоци на интиутивен начин, со тоа што секогаш ќе можеш <br> да го најдеш тоа што го бараш, и да не заборавиш ништо што ти е важно.<br>Оваа апликација се фокусира на студенти, донесувајќи <br>им можности кои можат да ги најдат корисни.<br> + + + + + Thanks to + Благодарение на + + + + qOrganizer + + + &Calendar + &Календар + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + Calendar + Календар + + + + Save + Зачувај + + + + Ctrl+Y + Ctrl+Y + + + + &SQLite Database + &SQLite база на податоци + + + + Ctrl+D + Ctrl+D + + + + Save to SQLite database + Зачувај во SQLite база на податоци + + + + &MySQL Database + &MySQL база на податоци + + + + Ctrl+M + Ctrl+M + + + + Save to MySQL database + Зачувај во MySQL база на податоци + + + + &Text files + &Текст file-oви + + + + Ctrl+T + Ctrl+T + + + + Save to text files + Зачувај во текст file + + + + &To-do List + &Листа на задачи + + + + Ctrl+Alt+T + Ctrl+Alt+T + + + + Edit your to-do list + Промени ја твојата листа на задачи + + + + To-do list + Листа на задачи + + + + &TimeTable + &Распоред + + + + Ctrl+Alt+L + Ctrl+Alt+L + + + + Edit your timetable + Промени го твојот распоред + + + + Timetable + Распоред + + + + &Booklet + &Брошура + + + + Ctrl+Alt+B + Ctrl+Alt+B + + + + Keep track of your school marks and absences + Следи ги твоите оцени и заостаноци + + + + Booklet + Брошура + + + + &Print + &Испринтај + + + + Ctrl+P + Ctrl+P + + + + Print Page + Испринтај ја страницава + + + + E&xit + И&злези + + + + Ctrl+Q + Ctrl+Q + + + + Exit the application + Излези од апликацијава + + + + &About + &За + + + + Show the application's About box + Покажи ја кутијата "За" на апликацијава + + + + About &Qt + За &Qt + + + + Show the Qt library's About box + Покажи ја "За" кутијата, на Qt библиотеката + + + + &Upload + &Прикачи + + + + Ctrl+Alt+U + Ctrl+Alt+U + + + + Upload data to FTP server + Прикачи податоци на FTP сервер + + + + &Download + &Симни + + + + Ctrl+Alt+W + Ctrl+Alt+W + + + + Download data from FTP server + Симни податоци од FTP сервер + + + + &Settings + &Сетинзи + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Configure application + Конфигурирај ја апликацијата + + + + &File + &Податок + + + + Save to + Зачувај во + + + + &View + &Погледни + + + + FT&P + FT&P + + + + &Help + &Помош + + + + File + Податок + + + + Ready + Подготвен + + + + Schedule for + Распоред за + + + + Event + Настан + + + + From + Од + + + + Until + До + + + + Reminder + Потсетник + + + + New event + Нов настан + + + + Delete event + Избриши настан + + + + B + B + + + + I + I + + + + U + U + + + + Important notes, journal for + Важни белешки, дневник за + + + + Search: + Барај: + + + + General to-do list + Генерална листа на задачи + + + + Start + Почни + + + + Task + Задача + + + + Deadline + Краен рок + + + + Priority + Приоритет + + + + Completed + Завршено + + + + New task + Нова задача + + + + Delete task + Избриши задача + + + + Monday + Понеделник + + + + Tuesday + Вторник + + + + Wednesday + Среда + + + + Thursday + Четврток + + + + Friday + Петок + + + + New row + Нов ред + + + + New column + Нова рубрика + + + + Delete column + Избриши рубрика + + + + Delete row + Избриши ред + + + + Timetable for: + Распоред за: + + + + Odd weeks + Непарни недели + + + + Even weeks + Парни недели + + + + English + Англиски + + + + Math + Математика + + + + IT + Информатика + + + + History + Историја + + + + Geography + Географија + + + + Biology + Биологија + + + + Physics + Физика + + + + Chemistry + Хемија + + + + New mark column + Нова колона на оцени + + + + New subject + Нов предмет + + + + Delete subject + Избриши предмет + + + + Delete mark column + Избриши колона на оцени + + + + New absence column + Нова колона на изостаноци + + + + Delete absence column + Избриши колона на изостаноци + + + + Subject average: + Просечна оцена на предметов: + + + + Absences: + Изостаноци: + + + + Total average: + Вкупен просек: + + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Потсетникот не можеше да се намести! +Има два прифатени формата за потсетници. +Едниот е: hh:mm.Другиот е запишување на часот. +На пример: 3 е еднакво на 3:00 или на 03:00 + + + + Column name: + Име на колона: + + + + Saturday + Сабота + + + + Subject name: + Име на предмет: + + + + + + + + + General to-do list: + Генерална листа на задачи: + + + + Marks: + Оцени: + + + + Uploading... + Прикачувајќи... + + + + Downloading... + Симнувајќи... + + + + Done! + Завршено! + + + + Done + Завршено + + + + Download finished! + Симнувањето е завршено! + + + + Couldn't download files: + + Не можеа да се симнат file-овите: + + + + Upload finished! + Прикачувањето е завршено! + + + + Error + Грешка + + + + Couldn't upload files: + + Прикачувањето на file-ов/ите беше неуспешно: + + + + Previous + Претходен + + + + Next + Следен + + + + Date: + Датум: + + + + Could not connect to database! + Не можеше да се воспостави врска со базата на податоци! + + + + No entries found! + Ниеден запис не е пронајден! + + + diff --git a/plugins/qOrganizer_plugin/lang/Polish.qm b/plugins/qOrganizer_plugin/lang/Polish.qm new file mode 100644 index 000000000..9403a6d8d Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Polish.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Polish.ts b/plugins/qOrganizer_plugin/lang/Polish.ts new file mode 100644 index 000000000..aed534830 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Polish.ts @@ -0,0 +1,710 @@ + + + + + SettingsDialog + + &Settings + U&stawienia + + + Some settings require restarting qOrganizer + Zmiana wartości niektórych ustawień wymaga restartu programu qOrganizer + + + Path to data folder: + Ścieżka do katalogu z danymi: + + + Browse + Przeglądaj + + + Reminder check interval: + Interwał sprawdzania przypomnień: + + + First day of week: + Pierwszy dzień tygodnia: + + + Monday + Poniedziałek + + + Tuesday + Wtorek + + + Wednesday + Środa + + + Thursday + Czwartek + + + Friday + Piątek + + + Saturday + Sobota + + + Sunday + Niedziela + + + Date format: + Format daty: + + + Autosave: + Autozapis: + + + Remind type: + Typ przypomnienia: + + + Language: + Język: + + + Row number for empty schedule: + Liczba rzędów dla pustego rozkładu dnia: + + + Round subject averages when calculating total average + Zaokrąglanie średnich z przedmiotów przy obliczaniu średniej ogółem + + + Show saving buttons on toolbar + Wyświetlanie przycisków zapisu na pasku narzędzi + + + Cancel + Anuluj + + + Reload data on view change + Przeładowanie danych przy zmianie widoku + + + Hide to system tray on close + Chowanie do tacki systemowej przy zamykaniu + + + Port: + Port: + + + Host: + Host: + + + Username: + Nazwa użytkownika: + + + Password: + Hasło: + + + Path on ftp server: + Ściężka na serwerze FTP: + + + Synchronize with ftp server: + Synchronizacja z serwerem FTP: + + + Play sound on remind + Odtwarzanie dźwięku przy przypomnieniu + + + Use different timetables for even and odd weeks + Użycie innych planów dnia dla tygodni parzystych i nieparzystych + + + Reverse normal order of weeks for timetable + Odwróć normalny porządek tygodni dla planu dnia + + + Text files + Pliki tekstowe + + + SQLite database + baza SQLite + + + MySQL database + baza MySQL + + + Store data in: + Zachowanie danych w: + + + Database name: + Nazwa bazy danych: + + + FTP synchronization is not available for MySQL database + Synchronizacja z FTP jest niedostępna dla bazy MySQL + + + &General + O&gólne + + + &Calendar + &Kalendarz + + + FTP + FTP + + + Storing + Zapisywanie + + + Select Directory + Wybierz katalog + + + + aboutDialog + + About + O programie + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + +To oprogramowanie jest objęte licencją GPL w wersij 2 <br> +opublikowaną przez Free Software Foundation.<br><br> + +Celem tej aplikacji jest uproszczenie życia Użytkownika poprzez<br> + intuicyjną organizację danych tak, by miał On dostęp do<br> +wszystkich potrzebnych informacji oraz by nie przeoczył<br> +żadnego ważnego wydarzenia.<br> +Zawiera szereg funkcji przydatnych uczniom i studentom.<br> + + + + Thanks to + Podziękowania dla + + + + qOrganizer + + &Calendar + &Kalendarz + + + Ctrl+Alt+C + Ctrl+Alt+C + + + Calendar + Kalendarz + + + Save + Zapisz + + + Ctrl+Y + Ctrl+Y + + + &SQLite Database + Baza &SQLite + + + Ctrl+D + Ctrl+D + + + Save to SQLite database + Zapisz do bazy SQLite + + + &MySQL Database + Baza &MySQL + + + Ctrl+M + Ctrl+M + + + Save to MySQL database + Zapisz do bazy MySQL + + + &Text files + Pliki &tekstowe + + + Ctrl+T + Ctrl+T + + + Save to text files + Zapisz do plików tekstowych + + + &To-do List + Lista &to-do + + + Ctrl+Alt+T + Ctrl+Alt+T + + + Edit your to-do list + Edycja listy to-do + + + To-do list + Lista to-do + + + &TimeTable + &Plan dnia + + + Ctrl+Alt+L + Ctrl+Alt+L + + + Edit your timetable + Edytuj swój plan dnia + + + Timetable + Plan dnia + + + &Booklet + &Dzienniczek + + + Ctrl+Alt+B + Ctrl+Alt+B + + + Keep track of your school marks and absences + Śledzenie stopni szkolnych i nieobecności + + + Booklet + Dzienniczek + + + &Print + &Drukuj + + + Ctrl+P + Ctrl+P + + + Print Page + Drukuj stronę + + + E&xit + &Wyjście + + + Ctrl+Q + Ctrl+Q + + + Exit the application + Wyjście z aplikacji + + + &About + &O programie + + + Show the application's About box + Wyświetlenie okna 'O programie' + + + About &Qt + O &Qt + + + Show the Qt library's About box + Wyświetlenie okna 'O Qt' + + + &Upload + &Wysłanie + + + Ctrl+Alt+U + Ctrl+Alt+U + + + Upload data to FTP server + Wysłanie danych do serwera FTP + + + &Download + &Pobranie + + + Ctrl+Alt+W + Ctrl+Alt+W + + + Download data from FTP server + Pobranie danych z serwera FTP + + + &Settings + &Ustawienia + + + Ctrl+Alt+S + Ctrl+Alt+S + + + Configure application + Konfiguracja aplikacji + + + &File + &Plik + + + Save to + Zapisz do + + + &View + &Widok + + + FT&P + &FTP + + + &Help + P&omoc + + + File + Plik + + + Ready + Gotowe + + + Schedule for + Rozkład dnia + + + Event + Wydarzenie + + + From + Od + + + Until + Do + + + Reminder + Przypomnienie + + + New event + Nowe wydarzenie + + + Delete event + Skasuj zdarzenie + + + B + B + + + I + I + + + U + U + + + Important notes, journal for + Ważne notatki, wpis dla + + + Search: + Szukaj: + + + Previous + Poprzednie + + + Next + Następne + + + General to-do list + Główna lista to-do + + + Start + Start + + + Task + Zadanie + + + Deadline + Termin + + + Priority + Priorytet + + + Completed + Zakończone + + + New task + Nowe zadanie + + + Delete task + Skasuj zadanie + + + Monday + Poniedziałek + + + Tuesday + Wtorek + + + Wednesday + Środa + + + Thursday + Czwartek + + + Friday + Piątek + + + New row + Nowy rząd + + + New column + Nowa kolumna + + + Delete column + Skasuj kolumnę + + + Delete row + Skasuj rząd + + + Timetable for: + Plan dnia dla: + + + Odd weeks + Tygodnie nieparzyste + + + Even weeks + Tygodnie parzyste + + + Marks: + Stopnie: + + + Absences: + Nieobecności: + + + English + Angielski + + + Math + Matematyka + + + IT + Informatyka + + + History + Historia + + + Geography + Geografia + + + Biology + Biologia + + + Physics + Fizyka + + + Chemistry + Chemia + + + New mark column + Nowa kolumna ze stopniami + + + New subject + Nowy przedmiot + + + Delete subject + Skaskuj przedmiot + + + Delete mark column + Skasuj kolumnę ze stopniami + + + New absence column + Nowa kolumna z nieobecnościami + + + Delete absence column + Skasuj kolumnę z nieobecnościami + + + Subject average: + Średnia z przedmiotu: + + + Date: + Data: + + + Total average: + Średnia ogółem: + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Nie można ustawić przypomnienia! +Proszę zastosować jedno z dwóch akceptowanych formatów dla przypomnień: +1) hh:mm +Przykład: 17:58 +2) wpisanie godziny +Przykład: 3 jest równoważne z 3:00 oraz 03:00 + + + Column name: + Nazwa kolumny: + + + Saturday + Sobota + + + Subject name: + Nazwa przedmiotu: + + + + + + + General to-do list: + Główna lista to-do: + + + Uploading... + Wysyłanie... + + + Downloading... + Pobieranie... + + + Done! + Gotowe! + + + Done + Gotowe + + + Download finished! + Pobieranie ukończone! + + + Couldn't download files: + + Nie udało się pobrac plików: + + + Upload finished! + Wysyłanie ukończone! + + + Error + Błąd + + + Couldn't upload files: + + Nie udało się wysłać plików: + + + Could not connect to database! + Nie udało się połączyć z bazą danych! + + + No entries found! + Nie znaleziono żadnych wpisów! + + + diff --git a/plugins/qOrganizer_plugin/lang/Portuguese.qm b/plugins/qOrganizer_plugin/lang/Portuguese.qm new file mode 100644 index 000000000..adc711364 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Portuguese.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Portuguese.ts b/plugins/qOrganizer_plugin/lang/Portuguese.ts new file mode 100644 index 000000000..a09e8c6c7 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Portuguese.ts @@ -0,0 +1,1108 @@ + + + + SettingsDialog + + + Some settings require restarting qOrganizer + Precisa reiniciar o qOrganizer para efectivar algumas configurações + + + + Path to data folder: + Caminho para a pasta de dados: + + + + Browse + Procurar + + + + Reminder check interval: + Intervalo dos lembretes: + + + + First day of week: + Primeiro dia da semana: + + + + Monday + Segunda-Feira + + + + Tuesday + Terça-Feira + + + + Wednesday + Quarta-Feira + + + + Thursday + Quinta-Feira + + + + Friday + Sexta-Feira + + + + Saturday + Sábado + + + + Sunday + Domingo + + + + Date format: + Formato da data: + + + + Autosave: + Gravação automática: + + + + Remind type: + Tipo de lembrete: + + + + Language: + Idioma: + + + + Row number for empty schedule: + Número de linhas para agenda vazia: + + + + Round subject averages when calculating total average + Arredondar da média das disciplinas quando calcula a média total + + + + Show saving buttons on toolbar + Mostar botões de gravação na barra de ferramenta + + + + Cancel + Cancelar + + + + Reload data on view change + Actualizar dados na mudança de visualização + + + + Hide to system tray on close + Esconder na área de notificação quando fechar + + + + Port: + Porta: + + + + Host: + Endereço servidor: + + + + Username: + Utilizador: + + + + Password: + Senha: + + + + Path on ftp server: + Caminho no servidor FTP: + + + + Synchronize with ftp server: + Sincronizar com o servidor FTP: + + + + Play sound on remind + Tocar som nos lembretes + + + + Use different timetables for even and odd weeks + Usar horários diferentes para semnas pares ou impares + + + + Reverse normal order of weeks for timetable + Repor a ordem normal das semanas para os horários + + + + Text files + Ficheiros de texto + + + + SQLite database + SQLite + + + + MySQL database + MySQL + + + + Store data in: + Guardar dados em: + + + + Database name: + Nome da base de dados: + + + + FTP synchronization is not available for MySQL database + A sincronização FTP não está disponível para bases de dados MySQL + + + + &General + &Geral + + + + &Calendar + &Calendário + + + + FTP + FTP + + + + Storing + Dados + + + + Select Directory + Seleccionar o directório + + + + aboutDialog + + + About + Sobre + + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + +<br>Este programa é licenciado sob a licença GPL versão 2<br> publicada pela Free Software Foundation.<br> + +<br>Esta aplicação pretende trazer simplicidade nas nossas vidas<br> organizando o nosso tempo de forma intuitiva para podermos encontrar o que pretendemos e nunca esquecer algo de importante.<br>Esta aplicação foca-se nos estudantes fornecendo-lhes ferramentas úteis.<br> + + + + + Thanks to + Agredecimentos a + + + + qOrganizer + + + About qOrganizer + Sobre o qOrganizer + + + + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + + +<img src=:/images/logo.png><br> + + +<br>This software is licenced under GPL version 2 published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by organizing your data in an intuitive way so you can always find what you need and never forget something important.<br>This application focuses on students, providing the features they consider usefull.<br><br> +Special thanks to:my girlfriend for supporting me, to my friends for testing this application,and to Xavier Corredor Llano, for releasing the nuvoX iconset under GPL</b> + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + + +<img src=:/images/logo.png><br> + + +<br>Este programa é licenciado sob a licença GPL versão 2 publicada pela Free Software Foundation.<br> +<br>Esta aplicação pretende trazer simplicidade nas nossas vidas organizando o nosso tempo de forma intuitiva para podermos encontrar o que pretendemos e nunca esquecer algo de importante.<br>Esta aplicação foca-se nos estudantes fornecendo-lhes ferramentas úteis.<br><br> + Agredecimentos especiais: Para a minha namorada por apoiar-me, para os meus amigos que testaram a aplicação, e para o Xavier Corredor Llano, por ter realizado o conjunto de icones nuvoX sob a licença GPL</b> + + + + &Calendar + &Calendário + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + Calendar + Calendário + + + + Save + Gravar + + + + Ctrl+S + Ctrl+S + + + + &To-do List + &Lista-A-Fazer + + + + Ctrl+Alt+T + Ctrl+Alt+T + + + + Edit your to-do list + Editar a sua lista a fazer + + + + To-do list + Lista-A-Fazer + + + + &TimeTable + &Horário + + + + Ctrl+Alt+L + Ctrl+Alt+L + + + + Edit your timetable + Editar o seu horário + + + + Timetable + Horário + + + + &Booklet + &Caderneta + + + + Ctrl+Alt+B + Ctrl+Alt+B + + + + Keep track of your school marks and absences + Mantenha-se a par das suas notas e faltas + + + + Booklet + Caderneta + + + + &Print + &Imprimir + + + + Ctrl+Alt+P + Ctrl+Alt+P + + + + Print Page + Página de impressão + + + + E&xit + S&air + + + + Ctrl+Q + Ctrl+Q + + + + Exit the application + Sair da aplicação + + + + &About + &Sobre + + + + Show the application's About box + Mostrar a caixa sobre + + + + About &Qt + Sobre &Qt + + + + Show the Qt library's About box + Mostrar a caixa sobre a bibioteca QT + + + + &Settings + &Configurações + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Configure application + Configurar aplicação + + + + &File + &Ficheiro + + + + &Help + &Ajuda + + + + File + Ficheiro + + + + Ready + Pronto + + + + <center><font size="5">Schedule for + <center><font size="5">Agenda para + + + + :</font></center> + :</font></center> + + + + Event + Evento + + + + From + De + + + + Until + Até + + + + Reminder + Lembrete + + + + New event + Novo evento + + + + Delete event + Apagar evento + + + + B + B + + + + I + I + + + + U + U + + + + <font size="5">Important notes, journal for + <font size="5">Notas importantes, jornal para + + + + :</font> + :</font> + + + + <center><font size="5" >General to-do list:</center> + <center><font size="5" >Lista a fazer geral:</center> + + + + Task + Tarefa + + + + Deadline + Prazo final + + + + Priority + Prioridade + + + + Completed + Completo + + + + New task + Nova tarefa + + + + Delete task + Apagar tarefa + + + + <center><font size="5">Timetable:</font></center> + <center><font size="5">Horário:</font></center> + + + + Monday + Segunda-Feira + + + + Tuesday + Terça-Feira + + + + Wednesday + Quarta-Feira + + + + Thursday + Quinta-Feira + + + + Friday + Sexta-Feira + + + + New row + Nova linha + + + + New column + Nova coluna + + + + Delete column + Apagar coluna + + + + Delete row + Apagar linha + + + + <center><font size="5">Booklet</font></center> + <center><font size="5">Caderneta</font></center> + + + + <center>Marks:</center> + <center>Notas:</center> + + + + <center>Absences:</center> + <center>Faltas:</center> + + + + English + Inglês + + + + Math + Matemática + + + + IT + IT + + + + History + História + + + + Geography + Geografia + + + + Biology + Biologia + + + + Physics + Física + + + + Chemistry + Química + + + + New mark column + Nova coluna de notas + + + + New subject + Nova disciplina + + + + Delete subject + Apagar disciplina + + + + Delete mark column + Apagar coluna de notas + + + + New absence column + Nova coluna de faltas + + + + Delete absence column + Apagar coluna de faltas + + + + Subject average: + Média da disciplina: + + + + Absences: + Faltas: + + + + Total average: + Média total: + + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Não foi possivel criar o lembrete! +Existem dois formatos excluidos para os lembretes. +Um é hh:mm. +Exemplo:17:58. +Ou o outro é apenas escrever a hora. +Exemplo: 3 é igual a 3:00 ou a 03:00 + + + + Column name: + Nome da coluna: + + + + Saturday + Sábado + + + + Subject name: + Nome da disciplina: + + + + + + + + + Ctrl+P + Ctrl+P + + + + &Upload + &Envio + + + + Ctrl+Alt+U + Ctrl+Alt+U + + + + Upload data to FTP server + Enviar dados para o servidor FTP + + + + &Download + &Transferir + + + + Ctrl+Alt+W + Ctrl+Alt+W + + + + Download data from FTP server + Transferir dados do servidor FTP + + + + &View + &Ver + + + + &FTP + &FTP + + + + Start + Iniciar + + + + Uploading... + A enviar... + + + + Downloading... + A transferir... + + + + Done! + Concluído! + + + + Done + Concluído + + + + Download finished! + Transferência concluída! + + + + Couldn't download files: + + Não foi possível transferir os ficheiros: + + + + + Upload finished! + Envio concluído! + + + + Error + Erro + + + + Couldn't upload files: + + Não foi possível enviar os ficheiros: + + + + + Ctrl+Y + Ctrl+Y + + + + &SQLite Database + &SQLite + + + + Ctrl+D + Ctrl+D + + + + Save to SQLite database + Gravar na base de dados SQLite + + + + &MySQL Database + &MySQL + + + + Ctrl+M + Ctrl+M + + + + Save to MySQL database + Gravar na base de dados MySQL + + + + &Text files + &Ficheiros de texto + + + + Ctrl+T + Ctrl+T + + + + Save to text files + Gravar em ficheiros de texto + + + + Save to + Gravar como + + + + FT&P + FT&P + + + + Schedule for + Agenda para + + + + Important notes, journal for + Notas importantes, diário para + + + + Search: + Procura: + + + + General to-do list + Lista-A-Fazer geral + + + + Timetable for: + Horário para: + + + + Odd weeks + Semanas pares + + + + Even weeks + Semanas ímpares + + + + General to-do list: + Lista-A-Fazer geral: + + + + Marks: + Notas: + + + + Previous + Anterior + + + + Next + Posterior + + + + Date: + Data: + + + + Could not connect to database! + Não foi possível conectar-se à base de dados! + + + + No entries found! + Nenhuma entrada encontrada! + + + + settings + + + Some settings require restarting qOrganizer + Precisa reiniciar o qOrganizer para efectivar algumas configurações + + + + Config folder's path: + Configurar o caminho da pasta: + + + + Browse + Procurar + + + + Reminder check interval: + Intervalo dos lembretes: + + + + First day of week: + Primeiro dia da semana: + + + + Monday + Segunda-Feira + + + + Tuesday + Terça-Feira + + + + Wednesday + Quarta-Feira + + + + Thursday + Quinta-Feira + + + + Friday + Sexta-Feira + + + + Saturday + Sábado + + + + Sunday + Domingo + + + + Date format: + Formato da data: + + + + Autosave: + Gravação automática: + + + + Remind type: + Tipo de lembrete: + + + + Language: + Idioma: + + + + Row number for empty schedule: + Número de linhas para agenda vazia: + + + + Cancel + Cancelar + + + + Port: + Porta: + + + + Host: + Hospedeiro: + + + + Username: + Utilizador: + + + + Password: + Senha: + + + + Synchronize with ftp server: + Sincronizar com o servidor FTP: + + + + Select Directory + Seleccionar o directório + + + + Reload data on view change + Reabrir dados na mudança de visualização + + + + Hide to system tray on close + Esconder na área de notificação quando fechar + + + + Path on ftp server: + Caminho no servidor FTP: + + + + Play sound on remind + Tocar som nos lembretes + + + + &Calendar + &Calendário + + + diff --git a/plugins/qOrganizer_plugin/lang/Romanian.qm b/plugins/qOrganizer_plugin/lang/Romanian.qm new file mode 100644 index 000000000..16e2163d0 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Romanian.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Romanian.ts b/plugins/qOrganizer_plugin/lang/Romanian.ts new file mode 100644 index 000000000..45d462d53 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Romanian.ts @@ -0,0 +1,1139 @@ + + + + + SettingsDialog + + + Some settings require restarting qOrganizer + Unele setari cer repornirea programului + + + + Path to data folder: + Dosarul de date: + + + + Browse + Browse + + + + Reminder check interval: + Intervalul de control pentru avertizări: + + + + First day of week: + Prima zi a săptămânii: + + + + Monday + Luni + + + + Tuesday + Marţi + + + + Wednesday + Miercuri + + + + Thursday + Joi + + + + Friday + Vineri + + + + Saturday + Sâmbătă + + + + Sunday + Duminică + + + + Date format: + Format dată: + + + + Autosave: + Salvare automată: + + + + Remind type: + Tip de avertizare: + + + + Language: + Limba: + + + + Row number for empty schedule: + Nr. de randuri implicit pentru programul zilnic: + + + + Round subject averages when calculating total average + Rotunjire medie subiect la calcularea mediei totale + + + + Show saving buttons on toolbar + Arată butoanele de salvare + + + + Cancel + Cancel + + + + Reload data on view change + Reîncarcă datele la schimbarea vederii + + + + Hide to system tray on close + Ascunde la tavă în loc de închidere + + + + Port: + Port: + + + + Host: + Adresă: + + + + Username: + Nume utilizator: + + + + Password: + Parolă: + + + + Path on ftp server: + Cale pe serverul FTP: + + + + Synchronize with ftp server: + Sincronizare cu server FTP: + + + + Play sound on remind + Redă sunet la atenţionare + + + + Use different timetables for even and odd weeks + Orare diferite pentru săptămâni pare şi impare + + + + Reverse normal order of weeks for timetable + Inversează ordinea normală a săptămâniilor + + + + Text files + Fişiere text + + + + SQLite database + Bază de date SQLite + + + + MySQL database + Bază de date MySQL + + + + Store data in: + Mod de stocare a datelor: + + + + Database name: + Nume bază de date: + + + + FTP synchronization is not available for MySQL database + Sincronizarea FTP nu este disponibil pentru baze de date MySQL + + + + &General + &General + + + + &Calendar + &Calendar + + + + FTP + FTP + + + + Storing + Stocare + + + + Select Directory + Selectaţi dosarul + + + + aboutDialog + + + About + Despre + + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + <br>Acest software este licenţat sub GPL v2 <br> publicat de Free Software Foundation.<br> + +<br>Aceasta aplicaţie are ca scop simplificarea organizării <br> informaţiilor importante într-un mod intuitiv.<br> +Asigurând că întotdeauna găsiţi ceea ce căutaţi.<br> +Acest program pune accent pe nevoile eleviilor <br> şi studenţiilor, punând la dispoziţie unelte <br>ce ei consideră importante.<br> + + + + + Thanks to + Mulţumiri + + + + qOrganizer + + + About qOrganizer + Despre qOrganizer + + + + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + + +<img src=:/logo.png><br> + + +<br>This software is licenced under GPL version 2 published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by organizing your data in an intuitive way so you can always find what you need and never forget something important.<br>This application focuses on students, providing the features they consider usefull.<br><br> +Special thanks to:my girlfriend for supporting me, to my friends for testing this application,and to Xavier Corredor Llano, for releasing the nuvoX iconset under GPL</b> + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br><img src=:/logo.png><br><br>Acest software este licenţat sub GPL v2 publicat de Free Software Foundation.<br> +<br>Aceasta aplicaţie are ca scop simplificarea organizării informaţiilor importante într-un mod intuitiv. +Asigurând că întotdeauna găsiţi cea ce căutaţi.<br> +Acest program pune accent pe nevoile eleviilor şi studenţiilor, punând la dispoziţie unelte ce ei consideră important<br> + +<br>Mulţumiri:prietenei mele, care m-a suportat în timpul dezvoltării, prieteniilor mei care au testat aplicaţia<br> +şi lui Xavier Corredor Llano pentru că a publicat iconsetul nuvoX, pe care mi-am bazat icoanele, sub GPL. + + + + &Calendar + &Calendar + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + Calendar + Calendar + + + + Save + Salvare + + + + Ctrl+S + Ctrl+S + + + + &To-do List + &Lista treburiilor + + + + Ctrl+Alt+T + Ctrl+Alt+T + + + + Edit your to-do list + Editeaza lista treburiilor, activităţiilor generale + + + + To-do list + Lista treburiilor + + + + &TimeTable + &Orar + + + + Ctrl+Alt+L + Ctrl+Alt+L + + + + Edit your timetable + Editarea orarului + + + + Timetable + Orar + + + + &Booklet + &Carnet + + + + Ctrl+Alt+B + Ctrl+Alt+B + + + + Keep track of your school marks and absences + Monitorizează notele şi absenţele tale + + + + Booklet + Carnet + + + + &Print + &Imprimare + + + + Ctrl+Alt+P + Ctrl+Alt+P + + + + Print Page + Imprimare pagină + + + + E&xit + &Ieşire + + + + Ctrl+Q + Ctrl+Q + + + + Exit the application + Ieşire din aplicaţie + + + + &About + &Despre + + + + Show the application's About box + Arată informaţii despre aplicaţie + + + + About &Qt + Despre &Qt + + + + Show the Qt library's About box + Despre Qt + + + + &Settings + &Setări + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Configure application + Configurarea aplicaţiei + + + + &File + &Fişier + + + + &Help + &Ajutor + + + + File + Fişier + + + + Ready + Disponibil + + + + <center><font size="5">Schedule for + <center><font size="5">Program pentru + + + + :</font></center> + :</font></center> + + + + Event + Eveniment + + + + From + De la + + + + Until + Până + + + + Reminder + Atenţionare + + + + New event + Eveniment nou + + + + Delete event + Ştergere eveniment + + + + B + B + + + + I + I + + + + U + U + + + + <font size="5">Important notes, jurnal for + <font size="5">Note importante, jurnal pentru + + + + :</font> + :</font> + + + + <center><font size="5" >General to-do list:</center> + <center><font size="5" >Lista treburiilor generale:</center> + + + + Task + Treabă + + + + Deadline + Limită + + + + Priority + Prioritate + + + + Completed + Completat + + + + New task + Treabă nouă + + + + Delete task + Ştergere treabă + + + + <center><font size="5">Timetable:</font></center> + <center><font size="5">Orar:</font></center> + + + + Monday + Luni + + + + Tuesday + Marţi + + + + Wednesday + Miercuri + + + + Thursday + Joi + + + + Friday + Vineri + + + + New row + Rând nou + + + + New column + Colonă nouă + + + + Delete column + Ştergere coloană + + + + Delete row + Ştergere rând + + + + <center><font size="5">Booklet</font></center> + <center><font size="5">Carnet</font></center> + + + + <center>Marks:</center> + <center>Note:</center> + + + + <center>Absences:</center> + <center>Absenţe:</center> + + + + English + Engleza + + + + Math + Matematica + + + + IT + Informatica + + + + History + Istorie + + + + Geography + Geografie + + + + Biology + Biologie + + + + Physics + Fizica + + + + Chemistry + Chimie + + + + New mark column + Coloană de note nouă + + + + New subject + Subiect nou + + + + Delete subject + Ştergere subiect + + + + Delete mark column + Ştergere coloană de note + + + + New absence column + Nouă coloană de absenţe + + + + Delete absence column + Ştergere absenţe + + + + Average: + Medie: + + + + Absences: + Absenţe: + + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + N-am reuşit să pun avertizarea +Există două formate acceptate pentru avertizări. +Unul este oră:minute +Exemplu:17:58 +Celălalt este doar ora +Exemplu: 3 este egal cu 3:00 şi cu 03:00 + + + + Column name: + Nume coloană: + + + + Saturday + Sâmbătă + + + + Subject name: + Nume subiect: + + + + + + + + + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + + +<img src=:/images/logo.png><br> + + +<br>This software is licenced under GPL version 2 published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by organizing your data in an intuitive way so you can always find what you need and never forget something important.<br>This application focuses on students, providing the features they consider usefull.<br><br> +Special thanks to:my girlfriend for supporting me, to my friends for testing this application,and to Xavier Corredor Llano, for releasing the nuvoX iconset under GPL</b> + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + +<img src=:/images/logo.png><br> +<br>Acest software este licenţat sub GPL v2 publicat de Free Software Foundation.<br> +<br>Aceasta aplicaţie are ca scop simplificarea organizării informaţiilor importante într-un mod intuitiv. +Asigurând că întotdeauna găsiţi cea ce căutaţi.<br> +Acest program pune accent pe nevoile eleviilor şi studenţiilor, punând la dispoziţie unelte ce ei consideră important<br> + +<br>Mulţumiri:prietenei mele, care m-a suportat în timpul dezvoltării, prieteniilor mei care au testat aplicaţia<br> +şi lui Xavier Corredor Llano pentru că a publicat iconsetul nuvoX, pe care mi-am bazat icoanele, sub GPL. + + + + <font size="5">Important notes, journal for + <font size="5">Note importante, jurnal pentru + + + + Subject average: + Medie subiect: + + + + Total average: + Media totală: + + + + &Upload + &Încărcare + + + + Ctrl+Alt+U + Ctrl+Alt+U + + + + Upload data to FTP server + Încărcarea datelor pe server FTP + + + + &Download + &Descărcare + + + + Ctrl+Alt+W + Ctrl+Alt+W + + + + Download data from FTP server + Descarcă date de pe server FTP + + + + Uploading... + Încărcare... + + + + Downloading... + Descărcare... + + + + Done! + Terminat! + + + + Done + Terminat + + + + Download finished! + Descărcare terminată! + + + + Couldn't download files: + + Descărcare nereuşită: + + + + + Upload finished! + Încărcare terminată! + + + + Error + Eroare + + + + Couldn't upload files: + + Încărcare nereuşită: + + + + &View + &Vedere + + + + &FTP + &FTP + + + + Ctrl+P + Ctrl+P + + + + Start + Început + + + + Ctrl+Y + Ctrl+Y + + + + &SQLite Database + Bază de date &SQLite + + + + Ctrl+D + Ctrl+D + + + + Save to SQLite database + Salvare în bază de date SQLite + + + + &MySQL Database + Bază de date &MySQL + + + + Ctrl+M + Ctrl+M + + + + Save to MySQL database + Salvare în bază de date MySQL + + + + &Text files + Fişiere &Text + + + + Ctrl+T + Ctrl+T + + + + Save to text files + Salvare în fişiere text + + + + Save to + Mod salvare + + + + FT&P + FT&P + + + + Schedule for + Program pentru + + + + Important notes, journal for + Note importante,jurnal pentru + + + + Search: + Căutare: + + + + Previous + Precedent + + + + Next + Următor + + + + General to-do list + Lista treburiilor generale + + + + Timetable for: + Orar pentru: + + + + Odd weeks + Săptămâni impare + + + + Even weeks + Săptămâni pare + + + + Marks: + Note: + + + + Date: + Dată: + + + + General to-do list: + Lista treburiilor generale: + + + + Could not connect to database! + Conectare la bază de date nereuşită! + + + + No entries found! + Nu s-a găsit nici un rezultat! + + + + settings + + + Config folder's path: + Cale pentru folderul config: + + + + Browse + Browse + + + + Reminder check interval: + Intervalul de control pentru avertizări: + + + + First day of week: + Prima zi a săptămânii: + + + + Monday + Luni + + + + Tuesday + Marţi + + + + Wednesday + Miercuri + + + + Thursday + Joi + + + + Friday + Vineri + + + + Saturday + Sâmbătă + + + + Sunday + Duminică + + + + Autosave: + Salvare automată: + + + + Remind type: + Tip de avertizare: + + + + Cancel + Cancel + + + + Select Directory + Selectaţi folderul + + + + Language: + Limba: + + + + Row number for empty schedule: + Nr. de randuri implicit pentru programul zilnic: + + + + Some settings require restarting qOrganizer + Unele setari cer repornirea programului + + + + Date format: + Format dată: + + + + Port: + Port: + + + + Host: + Adresă: + + + + Username: + Nume utilizator: + + + + Password: + Parolă: + + + + Synchronize with ftp server: + Sincronizare cu server FTP: + + + + Path on ftp server: + Cale pe serverul FTP: + + + + Reload data on view change + Reîncarcă datele la schimbarea vederii + + + + Hide to system tray on close + Ascunde la tavă în loc de închidere + + + + Play sound on remind + Redă sunet la atenţionare + + + diff --git a/plugins/qOrganizer_plugin/lang/Russian.qm b/plugins/qOrganizer_plugin/lang/Russian.qm new file mode 100644 index 000000000..5b5c44a01 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Russian.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Russian.ts b/plugins/qOrganizer_plugin/lang/Russian.ts new file mode 100644 index 000000000..b2da6ca3a --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Russian.ts @@ -0,0 +1,889 @@ + + + + + SettingsDialog + + Some settings require restarting qOrganizer + Некоторые настройки требуют перезапуска qOrganizer + + + Path to data folder: + Путь к каталогу с данными: + + + Browse + Обзор + + + Reminder check interval: + Интервал проверки напоминаний: + + + First day of week: + Первый день недели: + + + Monday + Понедельник + + + Tuesday + Вторник + + + Wednesday + Среда + + + Thursday + Четверг + + + Friday + Пятница + + + Saturday + Суббота + + + Sunday + Воскресенье + + + Date format: + Формат времени: + + + Autosave: + Автосохранение: + + + Remind type: + Тип напоминаний: + + + Language: + Язык: + + + Row number for empty schedule: + Число строк для пустого расписания: + + + Round subject averages when calculating total average + Округлять число пропущенных занятий при вычислении общего числа пропусков + + + Show saving buttons on toolbar + Показывать кнопки сохранения на тулбаре + + + Cancel + Отмена + + + Reload data on view change + Перезагружать данные при изменении вида + + + Hide to system tray on close + Прятать в системный трей при закрытии + + + Port: + Порт: + + + Host: + Хост: + + + Username: + Имя пользователя: + + + Password: + Пароль: + + + Path on ftp server: + Удалённый каталог (на ftp-сервере): + + + Synchronize with ftp server: + Синхронизировать с сервером: + + + Play sound on remind + Проигрывать звук при напоминании + + + Use different timetables for even and odd weeks + Использовать различное расписание для чётных и нечётных недель + + + Reverse normal order of weeks for timetable + Поменять порядок расписаний для чётных и нечётных недель + + + Text files + Текстовые файлы + + + SQLite database + База данных SQLite + + + MySQL database + База данных MySQL + + + Store data in: + Хранить информацию в: + + + Database name: + Имя базы данных: + + + FTP synchronization is not available for MySQL database + Синхронизация с FTP недоступна при использовании MySQL + + + &General + &Общие + + + &Calendar + &Календарь + + + FTP + FTP + + + Storing + Хранение данных + + + Select Directory + Выберите каталог + + + + aboutDialog + + About + О программе + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + <br>Программа распространяется на условиях LGPL v2, опубликованной Free Software Foundation.<br> + +<br>Целью данного приложения является внести упорядоченность в вашу жизнь, организовав личную информацию таким образом, чтобы вы не могли забыть нечто важное.<br>Это приложение, в первую очередь, предназначается для всех учащихся.<br> + + + + Thanks to + Благодарности + + + + qOrganizer + + About qOrganizer + О программе qOrganizer + + + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + + +<img src=:/images/logo.png><br> + + +<br>This software is licenced under GPL version 2 published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by organizing your data in an intuitive way so you can always find what you need and never forget something important.<br>This application focuses on students, providing the features they consider usefull.<br><br> +Special thanks to:my girlfriend for supporting me, to my friends for testing this application,and to Xavier Corredor Llano, for releasing the nuvoX iconset under GPL</b> + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> +E-mail:balazsbela@gmail.com<br> + +<img src=:/images/logo.png><br> +<br>Программа распространяется на условиях LGPL v2, опубликованной Free Software Foundation.<br> +<br>This application aims to bring simplicity in your life by organizing your data in an intuitive way so you can always find what you need and never forget something important.<br>This application focuses on students, providing the features they consider usefull.<br><br> Special thanks to:my girlfriend for supporting me, to my friends for testing this application,and to Xavier Corredor Llano, for releasing the nuvoX iconset under GPL</b> + + + &Calendar + &Календарь + + + Ctrl+Alt+C + Ctrl+Alt+C + + + Calendar + Кадендарь + + + Save + Сохранить + + + Ctrl+S + Ctrl+S + + + &To-do List + Список &дел + + + Ctrl+Alt+T + Ctrl+Alt+T + + + Edit your to-do list + Редактировать список дел + + + To-do list + Список дел + + + &TimeTable + &Расписание + + + Ctrl+Alt+L + Ctrl+Alt+L + + + Edit your timetable + Редактировать расписание + + + Timetable + Расписание + + + &Booklet + &Дневник + + + Ctrl+Alt+B + Ctrl+Alt+B + + + Keep track of your school marks and absences + Следите за вашими школьными оценками и пропусками + + + Booklet + Дневник + + + &Print + Пе&чать + + + Ctrl+P + Ctrl+P + + + Print Page + Страница печати + + + E&xit + В&ыход + + + Ctrl+Q + Ctrl+Q + + + Exit the application + Закрыть приложение + + + &About + О пр&ограмме + + + Show the application's About box + Показать информацию о приложении + + + About &Qt + О &Qt + + + Show the Qt library's About box + Показать информацию о библиотеке Qt + + + &Upload + &Отправить + + + Ctrl+Alt+U + Ctrl+Alt+U + + + Upload data to FTP server + Отправить данные на FTP-сервер + + + &Download + &Загрузить + + + Ctrl+Alt+W + Ctrl+Alt+W + + + Download data from FTP server + Загрузить данные с FTP-сервера + + + &Settings + &Настройки + + + Ctrl+Alt+S + Ctrl+Alt+S + + + Configure application + Настроить приложение + + + &File + &Файл + + + &View + &Вид + + + &FTP + &FTP + + + &Help + &Справка + + + File + Файл + + + Ready + Готово + + + <center><font size="5">Schedule for + <center><font size="5">Расписание для + + + :</font></center> + :</font></center> + + + Event + Событие + + + From + С + + + Until + До + + + Reminder + Напоминания + + + New event + Новое событие + + + Delete event + Удалить событие + + + B + Ж + + + I + К + + + U + П + + + <font size="5">Important notes, journal for + <font size="5">Важные заметки, журнал для + + + :</font> + :</font> + + + <center><font size="5" >General to-do list:</center> + <center><font size="5" >Основные задачи:</center> + + + Start + Начало + + + Task + Задача + + + Deadline + Дедлайн + + + Priority + Приоритет + + + Completed + Завершённость + + + New task + Новая задача + + + Delete task + Удалить задачу + + + <center><font size="5">Timetable:</font></center> + <center><font size="5">Расписание:</font></center> + + + Monday + Понедельник + + + Tuesday + Вторник + + + Wednesday + Среда + + + Thursday + Четверг + + + Friday + Пятница + + + New row + Новая строка + + + New column + Новый столбец + + + Delete column + Удалить столбец + + + Delete row + Удалить строку + + + <center><font size="5">Booklet</font></center> + <center><font size="5">Дневник</font></center> + + + <center>Marks:</center> + <center>Оценки</center> + + + <center>Absences:</center> + <center>Пропуски:<center> + + + English + Английский + + + Math + Математика + + + IT + Информатика + + + History + История + + + Geography + География + + + Biology + Биология + + + Physics + Физика + + + Chemistry + Химия + + + New mark column + Новый столбец оценок + + + New subject + Новый предмет + + + Delete subject + Удалить предмет + + + Delete mark column + Удалить столбец с оценками + + + New absence column + Новый столбец пропусков + + + Delete absence column + Удалить столбец пропусков + + + Subject average: + Средняя оценка по предмету: + + + Absences: + Пропуски: + + + Total average: + Средний балл: + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Невозможно установить напоминание! +Ожидается один из двух возможных форматов. +Первый: hh:mm. +Например, 17:58. +Другой возможный формат записи - просто указание часа. +Например, 3 эквивалентно 3.00 или 03.00 + + + Column name: + Название столбца: + + + Saturday + Суббота + + + Subject name: + Название предмета: + + + + + + + Uploading... + Идёт отправка... + + + Downloading... + Загрузка... + + + Done! + Готово! + + + Done + Готово + + + Download finished! + Загрузка завершена! + + + Couldn't download files: + + Невозможно загрузить файлы: + + + + Upload finished! + Отправка завершена! + + + Error + Ошибка + + + Couldn't upload files: + + Невозможно отправить файл: + + + + Ctrl+Y + Ctrl+Y + + + &SQLite Database + База данных &SQLite + + + Ctrl+D + Ctrl+D + + + Save to SQLite database + Сохранить в SQLite + + + &MySQL Database + База данных &MySQL + + + Ctrl+M + Ctrl+M + + + Save to MySQL database + Сохранить в MySQL + + + &Text files + Т&екстовые файлы + + + Ctrl+T + Ctrl+T + + + Save to text files + Сохранить в текстовые файлы + + + Save to + Сохранить в + + + FT&P + FT&P + + + Schedule for + Расписание для + + + Important notes, journal for + Важные заметки, журнал для + + + Search: + Поиск: + + + General to-do list + Основной список дел + + + Timetable for: + Расписание для: + + + Odd weeks + Нечётная неделя + + + Even weeks + Чётная неделя + + + General to-do list: + Основной список дел: + + + Marks: + Оценки: + + + Previous + Назад + + + Next + Вперёд + + + Date: + Дата: + + + Could not connect to database! + Невозможно соединиться с базой данных! + + + No entries found! + Записи не найдены! + + + + settings + + Some settings require restarting qOrganizer + Некоторые настройки требуют перезапуска qOrganizer + + + Config folder's path: + Путь к каталогу настроек: + + + Browse + Обзор + + + Reminder check interval: + Интервал проверки напоминаний: + + + First day of week: + Первый день недели: + + + Monday + Понедельник + + + Tuesday + Вторник + + + Wednesday + Среда + + + Thursday + Четверг + + + Friday + Пятница + + + Saturday + Суббота + + + Sunday + Воскресенье + + + Date format: + Формат времени: + + + Autosave: + Автосохранение: + + + Remind type: + Тип напоминаний: + + + Language: + Язык: + + + Row number for empty schedule: + Число строк для пустого расписания: + + + Cancel + Отмена + + + Reload data on view change + Перезагружать данные при изменении вида + + + Hide to system tray on close + Прятать в системный трей при закрытии + + + Port: + Порт: + + + Host: + Хост: + + + Username: + Имя пользователя: + + + Password: + Пароль: + + + Path on ftp server: + Удалённый каталог (на ftp-сервере): + + + Synchronize with ftp server: + Синхронизировать с сервером: + + + Play sound on remind + Проигрывать звук при напоминании + + + Select Directory + Выберите каталог + + + &Calendar + &Календарь + + + diff --git a/plugins/qOrganizer_plugin/lang/Slovenian.qm b/plugins/qOrganizer_plugin/lang/Slovenian.qm new file mode 100644 index 000000000..656ddfb00 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Slovenian.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Slovenian.ts b/plugins/qOrganizer_plugin/lang/Slovenian.ts new file mode 100644 index 000000000..8ec2170c5 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Slovenian.ts @@ -0,0 +1,897 @@ + + + + + SettingsDialog + + Some settings require restarting qOrganizer + Nekatere nastavitve zahtevajo ponovni zagon programa + + + Path to data folder: + Pot do mape s podatki: + + + Browse + Poišči + + + Reminder check interval: + Interval preverjanja opomnika: + + + First day of week: + Prvi dan v tednu: + + + Monday + Ponedeljek + + + Tuesday + Torek + + + Wednesday + Sreda + + + Thursday + Četrtek + + + Friday + Petek + + + Saturday + Sobota + + + Sunday + Nedelja + + + Date format: + Oblika datuma: + + + Autosave: + Samodejno shranjevanje: + + + Remind type: + Vrsta opomnika: + + + Language: + Jezik: + + + Row number for empty schedule: + Količina vrstic praznega seznama: + + + Round subject averages when calculating total average + Povprečje ocen zaokroženo ob izračunu povprečja + + + Show saving buttons on toolbar + Prikaži ikone za shranjevanje v orodni vrstici + + + Cancel + Prekliči + + + Reload data on view change + Osveži podatke ob prehodu med pogledi + + + Hide to system tray on close + Ob zaprtju skrij v sistemsko vrstico + + + Port: + Vrata: + + + Host: + Gostitelj: + + + Username: + Uporabniško ime: + + + Password: + Geslo: + + + Path on ftp server: + Lokacija na ftp strežnik: + + + Synchronize with ftp server: + Uskladi s ftp strežnikom: + + + Play sound on remind + Zvočni signal ob opomniku + + + Use different timetables for even and odd weeks + Uporabi različne urnike za sode in lihe tedne + + + Reverse normal order of weeks for timetable + Obrni normalno zaporedje tedno za urnik + + + Text files + Tekstovne datoteke + + + SQLite database + SQLite + + + MySQL database + MySQL + + + Store data in: + Shrani podatke v: + + + Database name: + Ime baze podatkov: + + + FTP synchronization is not available for MySQL database + FTP sinhronizacija ni možna za MySQL bazo podatkov + + + &General + &Glavno + + + &Calendar + &Koledar + + + FTP + FTP + + + Storing + Shranjevanje + + + Select Directory + Izberi Mapo + + + + aboutDialog + + About + O programu + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + +<br>Ta program je pod licenco GPL verzije 2 <br>izdan pod Free Software Foundation.<br> + +<br>Program vam prinese enostavnost v življenje, <br> z organizacijo vaših osebnih podatkov na način, da lahko vedno<br> najdete kar želite in nikoli pozabite česa pomembnega. <br>Ta program je osredotočen na študente, katerim <br> prinaša značilnosti ki se jim zdijo pomembne.<br> + + + + Thanks to + Zahvale + + + + qOrganizer + + About qOrganizer + O programu + + + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> + +E-mail:balazsbela@gmail.com<br> + + +<img src=:/images/logo.png><br> + + +<br>This software is licenced under GPL version 2 published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by organizing your data in an intuitive way so you can always find what you need and never forget something important.<br>This application focuses on students, providing the features they consider usefull.<br><br> +Special thanks to:my girlfriend for supporting me, to my friends for testing this application,and to Xavier Corredor Llano, for releasing the nuvoX iconset under GPL</b> + <b>qOrganizer : Copyright 2007 Bal&aacute;zs B&eacute;la<br> +E-mail:balazsbela@gmail.com<br> + + +<img src=:/images/logo.png><br> + + +<br>Ta program je pod licenco GPL verzije 2, objavila ga je Free Software Foundation.<br> +<br>Ta program zagotavlja poenostavitev življenja s pametno organizacijo vaših podatkov, da lahko vedno najdete kar želite in nikoli ne pozabite česa pomembnega.<br>Program je osredotočen na populacijo, ki se izobražuje, s tem da vsebuje elemente, ki so za študente uporabni.<br><br> +Posebna zahvala: mojemu dekletu za podporo, mojim prijateljem za testiranje programa in Xavier Corredor Llano-u, za objavo nuvoX ikonske grafike pod licenco GPL.</b> + + + &Calendar + &Koledar + + + Ctrl+Alt+C + Ctrl+Alt+C + + + Calendar + Koledar + + + Save + Shrani + + + Ctrl+S + Ctrl+S + + + &To-do List + &Seznam Opravil + + + Ctrl+Alt+T + Ctrl+Alt+T + + + Edit your to-do list + Uredi svoj seznam Opravil + + + To-do list + Seznam Opravil + + + &TimeTable + &Urnik + + + Ctrl+Alt+L + Ctrl+Alt+L + + + Edit your timetable + Uredi svoj urnik + + + Timetable + Urnik + + + &Booklet + &Beležka + + + Ctrl+Alt+B + Ctrl+Alt+B + + + Keep track of your school marks and absences + Zaznamuj si ocene in izostanke + + + Booklet + Beležka + + + &Print + &Tiskaj + + + Ctrl+Alt+P + Ctrl+Alt+P + + + Print Page + Natisni stran + + + E&xit + &Izhod + + + Ctrl+Q + Ctrl+Q + + + Exit the application + Izhod iz programa + + + &About + &O programu + + + Show the application's About box + Pokaži okno O Programu + + + About &Qt + O programu &Qt + + + Show the Qt library's About box + Prikaži informacije o Qt knjižnici + + + &Upload + &Naloži + + + Ctrl+Alt+U + Ctrl+Alt+U + + + Upload data to FTP server + Naloži podatke na FTP strežnik + + + &Download + &Prenesi + + + Ctrl+Alt+W + Ctrl+Alt+W + + + Download data from FTP server + Prenesi podatke iz FTP strežnika + + + &Settings + &Nastavitve + + + Ctrl+Alt+S + Ctrl+Alt+S + + + Configure application + Nastavi program + + + &File + &Datoteka + + + &View + &Pogled + + + &FTP + &FTP + + + &Help + &Pomoč + + + File + Datoteka + + + Ready + Pripravljen + + + <center><font size="5">Schedule for + <center><font size="5">Seznam za + + + :</font></center> + :</font></center> + + + Event + Dogodek + + + From + Od + + + Until + Do + + + Reminder + Opomnik + + + New event + Nov dogodek + + + Delete event + Zbriši dogodek + + + B + B + + + I + I + + + U + U + + + <font size="5">Important notes, journal for + <font size="5">Pomembni zapiski, dnevnik za + + + :</font> + :</font> + + + <center><font size="5" >General to-do list:</center> + <center><font size="5" >Glavni seznam Opravil:</center> + + + Task + Opravilo + + + Deadline + Skrajni rok + + + Priority + Prednost + + + Completed + Zaključeno + + + New task + Novo opravilo + + + Delete task + Zbriši opravilo + + + <center><font size="5">Timetable:</font></center> + <center><font size="5">Urnik:</font></center> + + + Monday + Ponedeljek + + + Tuesday + Torek + + + Wednesday + Sreda + + + Thursday + Četrtek + + + Friday + Petek + + + New row + Nova vrstica + + + New column + Nov stolpec + + + Delete column + Zbriši stolpec + + + Delete row + Zbriši vrstico + + + <center><font size="5">Booklet</font></center> + <center><font size="5">Beležka</font></center> + + + <center>Marks:</center> + <center>Ocene:</center> + + + <center>Absences:</center> + <center>Odsotnost:</center> + + + English + Angleščina + + + Math + Matematika + + + IT + Slovenščina + + + History + Zgodovina + + + Geography + Geografija + + + Biology + Biologija + + + Physics + Fizika + + + Chemistry + Kemija + + + New mark column + Nov stolpec ocen + + + New subject + Nov predmet + + + Delete subject + Zbriši predmet + + + Delete mark column + Zbriši stolpec ocen + + + New absence column + Nov stolpec izostanka + + + Delete absence column + Zbriši stolpec izostanka + + + Subject average: + Povprečje predmeta: + + + Absences: + Izostanki: + + + Total average: + Skupno povprečje: + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + Ni bilo možno nastaviti opomnika! +Obstajata dva možna formata za opomnik. +Prvi je hh:mm. +Drugi pa je le zapis željene ure. +Primer: 3 je enako kot 3:00 ali 03:00 + + + Column name: + Ime stolpca: + + + Saturday + Sobota + + + Subject name: + Ime predmeta: + + + + + + + Uploading... + Nalaganje... + + + Downloading... + Prenašanje... + + + Done! + Opravljeno! + + + Done + Opravljeno + + + Download finished! + Prenos zaključen! + + + Couldn't download files: + + Ni bilo možno prenesti datotek: + + + + Upload finished! + Nalaganje zaključeno! + + + Error + Napaka + + + Couldn't upload files: + + Ni bilo možno naložiti datotek: + + + + Ctrl+P + Ctrl+P + + + Start + Začni + + + Ctrl+Y + Ctrl +Y + + + &SQLite Database + &SQLite baza podatkov + + + Ctrl+D + Ctrl +D + + + Save to SQLite database + Shrani v SQLite bazo podatkov + + + &MySQL Database + &MySQL baza podatkov + + + Ctrl+M + Ctrl +M + + + Save to MySQL database + Shrani v MySQL bazo podatkov + + + &Text files + &Tekstovne datoteke + + + Ctrl+T + Ctrl +T + + + Save to text files + Shrani v tekstovne datoteke + + + Save to + Shrani v + + + FT&P + FT&P + + + Schedule for + Seznam za + + + Important notes, journal for + Pomembni zapiski, dnevni za + + + Search: + Išči: + + + General to-do list + Glavni seznam opravil + + + Timetable for: + Urnik za: + + + Odd weeks + Lihi tedni + + + Even weeks + Sodi tedni + + + General to-do list: + Glavni seznam opravil: + + + Marks: + Ocene: + + + Previous + Prejšnje + + + Next + Naslednje + + + Date: + Datum: + + + Could not connect to database! + Ne morem se povezati z bazo podatkov! + + + No entries found! + Ne najdem vpisov! + + + + settings + + Some settings require restarting qOrganizer + Nekatere nastavitve zahtevajo ponovni zagon programa + + + Config folder's path: + Lokacija mape z nastavitvami: + + + Browse + Poišči + + + Reminder check interval: + Interval preverjanja opomnika: + + + First day of week: + Prvi dan v tednu: + + + Monday + Ponedeljek + + + Tuesday + Torek + + + Wednesday + Sreda + + + Thursday + Četrtek + + + Friday + Petek + + + Saturday + Sobota + + + Sunday + Nedelja + + + Date format: + Oblika datuma: + + + Autosave: + Samodejno shranjevanje: + + + Remind type: + Vrsta opomnika: + + + Language: + Jezik: + + + Row number for empty schedule: + Količina vrstic praznega seznama: + + + Cancel + Prekliči + + + Reload data on view change + Osveži podatke ob prehodu med pogledi + + + Port: + Vrata: + + + Host: + Gostitelj: + + + Username: + Uporabniško ime: + + + Password: + Geslo: + + + Path on ftp server: + Lokacija na ftp strežnik: + + + Synchronize with ftp server: + Uskladi s ftp strežnikom: + + + Select Directory + Izberi Mapo + + + Hide to system tray on close + Ob zaprtju skrij v sistemsko vrstico + + + Play sound on remind + Zvočni signal ob opomniku + + + &Calendar + &Koledar + + + diff --git a/plugins/qOrganizer_plugin/lang/Spanish.qm b/plugins/qOrganizer_plugin/lang/Spanish.qm new file mode 100644 index 000000000..0af415279 Binary files /dev/null and b/plugins/qOrganizer_plugin/lang/Spanish.qm differ diff --git a/plugins/qOrganizer_plugin/lang/Spanish.ts b/plugins/qOrganizer_plugin/lang/Spanish.ts new file mode 100644 index 000000000..351d98891 --- /dev/null +++ b/plugins/qOrganizer_plugin/lang/Spanish.ts @@ -0,0 +1,1077 @@ + + + + + SettingsDialog + + + Some settings require restarting qOrganizer + Es necesario reiniciar qOrganizer para efectuar algunas configuraciones + + + + Path to data folder: + Ruta a la carpeta de datos: + + + + Browse + Buscar + + + + Reminder check interval: + Intervalo de los recordatorios: + + + + First day of week: + Primer día de la semana: + + + + Monday + Lunes + + + + Tuesday + Martes + + + + Wednesday + Miércoles + + + + Thursday + Jueves + + + + Friday + Viernes + + + + Saturday + Sábado + + + + Sunday + Domingo + + + + Date format: + Formato de fechas: + + + + Autosave: + Auto-guardar: + + + + Remind type: + Tipo de recordatorio: + + + + Language: + Idioma: + + + + Row number for empty schedule: + Número de lineas para agenda vacía: + + + + Round subject averages when calculating total average + Redondear los promedios de cada materia al calcular el promedio general + + + + Show saving buttons on toolbar + Mostrar el botones de guardado en la barra de herramientas + + + + Cancel + Cancelar + + + + Reload data on view change + Reabrir datos al cambiar de visualización + + + + Hide to system tray on close + Minimizar al área de notificación al cerrar + + + + Port: + Puerto: + + + + Host: + Host: + + + + Username: + Nombre de usuario: + + + + Password: + Contraseña: + + + + Path on ftp server: + Ruta en el servidor FTP: + + + + Synchronize with ftp server: + Sincronizar con el servidor FTP: + + + + Play sound on remind + Tocar sonido para los recordatorios + + + + Use different timetables for even and odd weeks + Usar horarios distintos para las semanas pares e impares + + + + Reverse normal order of weeks for timetable + Volver al orden normal de semanas para el horário + + + + Text files + Archivos de texto + + + + SQLite database + SQLite + + + + MySQL database + MySQL + + + + Store data in: + Guardar datos en: + + + + Database name: + Nombre de la base de datos: + + + + FTP synchronization is not available for MySQL database + La sincronización no está disponible para MySQL + + + + &General + &General + + + + &Calendar + &Calendário + + + + FTP + FTP + + + + Storing + Guardando + + + + Select Directory + Seleccionar el directório + + + + aboutDialog + + + About + Acerca de + + + + +<br>This software is licenced under GPL version 2 <br>published by the Free Software Foundation.<br> + +<br>This application aims to bring simplicity in your life by <br> organizing your data in an intuitive way so you can always<br> find what you need and never forget something important.<br>This application focuses on students, providing <br>the features they consider usefull. <br> + + +<br>Este programa esta licenciado bajo GPL versión 2 <br>publicado por la Free Software Foundation.<br> + +<br>Esta aplicación pretende simplificar su vida al permitirle organizar su tiempo de forma intuitiva para que pueda encontrar lo que necesita y nunca olvidar algo importante.<br>Esta aplicación se enfoca en los estudiantes y les entrega herramientas útiles.<br>(new line) + + + + Thanks to + Gracias a + + + + qOrganizer + + + About qOrganizer + Acerca de qOrganizer + + + + &Calendar + &Calendário + + + + Ctrl+Alt+C + Ctrl+Alt+C + + + + Calendar + Calendário + + + + Save + Guardar + + + + Ctrl+S + Ctrl+S + + + + &To-do List + &Cosas pendientes + + + + Ctrl+Alt+T + Ctrl+Alt+T + + + + Edit your to-do list + Edite su lista de cosas pendientes + + + + To-do list + Cosas pendientes + + + + &TimeTable + &Horário + + + + Ctrl+Alt+L + Ctrl+Alt+L + + + + Edit your timetable + Editar su horário + + + + Timetable + Horário + + + + &Booklet + &Libreta + + + + Ctrl+Alt+B + Ctrl+Alt+B + + + + Keep track of your school marks and absences + Mantenga un registro de sus notas e inasistencias + + + + Booklet + Libreta + + + + &Print + &Imprimir + + + + Ctrl+Alt+P + Ctrl+Alt+P + + + + Print Page + Imprimir Página + + + + E&xit + S&alir + + + + Ctrl+Q + Ctrl+Q + + + + Exit the application + Salir de la aplicación + + + + &About + &Sobre + + + + Show the application's About box + Mostrar el diálogo sobre la aplicación + + + + About &Qt + Sobre &Qt + + + + Show the Qt library's About box + Mostrar el dialogo sobre la biblioteca QT + + + + &Settings + &Configuraciones + + + + Ctrl+Alt+S + Ctrl+Alt+S + + + + Configure application + Configurar la aplicación + + + + &File + &Archivo + + + + &Help + &Ayuda + + + + File + Archivo + + + + Ready + Listo + + + + <center><font size="5">Schedule for + <center><font size="5">Agenda para + + + + :</font></center> + :</font></center> + + + + Event + Evento + + + + From + De + + + + Until + Hasta + + + + Reminder + Recordatorio + + + + New event + Nuevo evento + + + + Delete event + Eliminar evento + + + + B + B + + + + I + I + + + + U + U + + + + <font size="5">Important notes, journal for + <font size="5">Notas importantes, jornal para + + + + :</font> + :</font> + + + + <center><font size="5" >General to-do list:</center> + <center><font size="5" >Lista de cosas por hacer general:</center> + + + + Task + Tarea + + + + Deadline + Plazo final + + + + Priority + Prioridad + + + + Completed + Completado + + + + New task + Nueva tarea + + + + Delete task + Eliminar tarea + + + + <center><font size="5">Timetable:</font></center> + <center><font size="5">Horário:</font></center> + + + + Monday + Lunes + + + + Tuesday + Martes + + + + Wednesday + Miércoles + + + + Thursday + Jueves + + + + Friday + Viernes + + + + New row + Nueva linea + + + + New column + Nueva columna + + + + Delete column + Eliminar columna + + + + Delete row + Eliminar linea + + + + <center><font size="5">Booklet</font></center> + <center><font size="5">Libreta</font></center> + + + + <center>Marks:</center> + <center>Notas:</center> + + + + <center>Absences:</center> + <center>Inasistencias:</center> + + + + English + Inglés + + + + Math + Matemática + + + + IT + IT + + + + History + História + + + + Geography + Geografía + + + + Biology + Biología + + + + Physics + Física + + + + Chemistry + Química + + + + New mark column + Nueva columna de notas + + + + New subject + Nueva materia + + + + Delete subject + Eliminar materia + + + + Delete mark column + Eliminar columna de notas + + + + New absence column + Nueva columna de inasistencias + + + + Delete absence column + Eliminar columna de inasistencias + + + + Subject average: + Promedio del curso: + + + + Absences: + Inasistencias: + + + + Total average: + Promedio total: + + + + Couldn't set reminder! +There are two excepted formats for reminders. +One is hh:mm. +Example:17:58. +Or the other one is just writing the hour. +Example: 3 is equal to 3:00 or to 03:00 + No se pudo crear el recordatorio! +Existen dos formatos excluidos para los recordatorios. +Uno es hh:mm. +Ejemplo:17:58. +El otro es solo escribir la hora. +Ejemplo: 3 equivale a 3:00 o a 03:00 + + + + Column name: + Nombre de la columna: + + + + Saturday + Sábado + + + + Subject name: + Nombre del curso: + + + + + + + + + Ctrl+P + Ctrl+P + + + + &Upload + &Enviar + + + + Ctrl+Alt+U + Ctrl+Alt+U + + + + Upload data to FTP server + Enviar datos al servidor FTP + + + + &Download + &Bajar + + + + Ctrl+Alt+W + Ctrl+Alt+W + + + + Download data from FTP server + Transferir datos desde el servidor FTP + + + + &View + &Ver + + + + &FTP + &FTP + + + + Start + Iniciar + + + + Uploading... + Enviando... + + + + Downloading... + Transfiriendo... + + + + Done! + ¡Listo! + + + + Done + Listo + + + + Download finished! + ¡Transferencia lista! + + + + Couldn't download files: + + No fue posible transferir los archivos: + + + + + Upload finished! + Envío concluido! + + + + Error + Error + + + + Couldn't upload files: + + No fue posible enviar los archivos: + + + + + Ctrl+Y + Ctrl+Y + + + + &SQLite Database + &SQLite + + + + Ctrl+D + Ctrl+D + + + + Save to SQLite database + Guardar a SQLite + + + + &MySQL Database + &MySQL + + + + Ctrl+M + Ctrl+M + + + + Save to MySQL database + Guardar a MySQL + + + + &Text files + &Archivos de texto + + + + Ctrl+T + Ctrl+T + + + + Save to text files + Guardar a archivo de texto + + + + Save to + Guardar en + + + + FT&P + FT&P + + + + Schedule for + Horário para + + + + Important notes, journal for + Notas importantes, diária para + + + + Search: + Buscar: + + + + Previous + Anterior + + + + Next + Próximo + + + + General to-do list + Lista general de cosas pendientes + + + + Timetable for: + Horário para: + + + + Odd weeks + Semanas pares + + + + Even weeks + Semanas impares + + + + Marks: + Notas: + + + + Date: + Fecha: + + + + General to-do list: + Lista general de cosas pendientes: + + + + Could not connect to database! + ¡No se pudo conectar a la base de datos! + + + + No entries found! + ¡No se encontraron entradas! + + + + settings + + + Some settings require restarting qOrganizer + Es necesario reiniciar qOrganizer para efectuar algunas configuraciones + + + + Config folder's path: + Configurar la ruta de la carpeta: + + + + Browse + Buscar + + + + Reminder check interval: + Intervalo de los recordatorios: + + + + First day of week: + Primer dia de la semana: + + + + Monday + Lunes + + + + Tuesday + Martes + + + + Wednesday + Miércoles + + + + Thursday + Jueves + + + + Friday + Viernes + + + + Saturday + Sábado + + + + Sunday + Domingo + + + + Date format: + Formato de fechas: + + + + Autosave: + Auto-guardar: + + + + Remind type: + Tipo de recordatorio: + + + + Language: + Idioma: + + + + Row number for empty schedule: + Número de lineas para agenda vacía: + + + + Cancel + Cancelar + + + + Port: + Puerto: + + + + Host: + Host: + + + + Username: + Nombre de usuario: + + + + Password: + Contraseña: + + + + Synchronize with ftp server: + Sincronizar con el servidor FTP: + + + + Select Directory + Seleccionar el directório + + + + Reload data on view change + Reabrir datos al cambiar de visualización + + + + Hide to system tray on close + Minimizar al área de notificación al cerrar + + + + Path on ftp server: + Camino en el servidor FTP: + + + + Play sound on remind + Tocar sonido para los recordatorios + + + diff --git a/plugins/qOrganizer_plugin/main.cpp b/plugins/qOrganizer_plugin/main.cpp new file mode 100644 index 000000000..d32e570e2 --- /dev/null +++ b/plugins/qOrganizer_plugin/main.cpp @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2007 by Balázs Béla * + * balazsbela@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +#include +#include +#include +#include "qorganizer.h" +#include +#include + +//Config variable to know which language to use and other things needed to be done in main +QString C_LANGUAGE; +QString globalWDirPath; +QSize C_WINDOWSIZE; +bool C_MAXIMIZED; + +//Read it from the registry, easyer than re-reading the config file + +void getWDirPath() +{ + QSettings settings("qOrganizer","qOrganizer"); + globalWDirPath = settings.value("pathtowdir","home").toString(); + if(globalWDirPath=="home") globalWDirPath=QDir::homePath()+QDir::separator()+".qOrganizer"; + else globalWDirPath=globalWDirPath+QDir::separator()+".qOrganizer"; +} + +void readSettings() +{ + getWDirPath(); + QSettings::setPath(QSettings::IniFormat,QSettings::UserScope,globalWDirPath); + QSettings *settings = new QSettings(QSettings::IniFormat,QSettings::UserScope,"qOrganizer", "qOrganizer"); + C_LANGUAGE = settings -> value("language").toString(); + C_WINDOWSIZE = settings -> value("windowsize").toSize(); + C_MAXIMIZED = settings -> value("windowmaximized", true).toBool(); +} + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(application); + QApplication app(argc, argv); + QTranslator *translator = new QTranslator; + app.installTranslator(translator); + readSettings(); //Read the language + translator->load(C_LANGUAGE,":/lang"); //set it + QSplashScreen *splash = new QSplashScreen; + splash -> setPixmap(QPixmap(":/images/splash.png")); + splash -> show(); + qOrganizer mw; + if(!C_WINDOWSIZE.isEmpty()) + mw.resize(C_WINDOWSIZE); + if(C_MAXIMIZED) + mw.showMaximized(); + else + mw.show(); + //sleep(1); + splash -> hide(); + splash -> deleteLater(); + return app.exec(); + +} + diff --git a/plugins/qOrganizer_plugin/qOrganizer.png b/plugins/qOrganizer_plugin/qOrganizer.png new file mode 100644 index 000000000..c598cb084 Binary files /dev/null and b/plugins/qOrganizer_plugin/qOrganizer.png differ diff --git a/plugins/qOrganizer_plugin/qOrganizer_plugin.pro b/plugins/qOrganizer_plugin/qOrganizer_plugin.pro new file mode 100644 index 000000000..a84b95f2b --- /dev/null +++ b/plugins/qOrganizer_plugin/qOrganizer_plugin.pro @@ -0,0 +1,46 @@ +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin release + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(qorganizer_plugin) + +HEADERS += ../PluginInterface.h \ + qorganizerPlugin.h +SOURCES += qorganizerPlugin.cpp + +#=============================================================================== + +TARGET = +DEPENDPATH += . lang +INCLUDEPATH += . + +# Input +HEADERS += qorganizer.h settings.h delegates.h +SOURCES += main.cpp qorganizer.cpp settings.cpp delegates.cpp +RESOURCES += application.qrc +QT += network sql +TRANSLATIONS += lang/Hungarian.ts \ + lang/Romanian.ts \ + lang/Portuguese.ts \ + lang/Slovenian.ts \ + lang/Russian.ts \ + lang/Spanish.ts \ + lang/Albanian.ts \ + lang/Macedonian.ts \ + lang/Estonian.ts \ + lang/Dutch.ts \ + lang/German.ts \ + lang/French.ts \ + lang/Polish.ts diff --git a/plugins/qOrganizer_plugin/qorganizer.cpp b/plugins/qOrganizer_plugin/qorganizer.cpp new file mode 100644 index 000000000..f378bfb74 --- /dev/null +++ b/plugins/qOrganizer_plugin/qorganizer.cpp @@ -0,0 +1,4452 @@ +/*************************************************************************** + * Copyright (C) 2007 by Balázs Béla * + * balazsbela@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation version 2. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +/* + Special thanks to: Xavier Corredor Llano, the creator of the nuvoX iconset which my icons are mostly based on.I would like to thank him for releasing this great iconset under GPL. +*/ + +/* + For the interface we use a central QStackedWidget object named mainWid and we change the + currently active page with the help of the toolbar. +*/ + + +#include +#include "qorganizer.h" +#include +#include +#include +#include +#include +#include + +using namespace std; + +//The constructor +qOrganizer::qOrganizer() +{ + setWindowTitle("qOrganizer"); + QSize size(1024,768); + resize(size); + settings=0; + getWDirPath(); + readSettings(); + setWindowIcon(QIcon(":/images/icon.png")); + readConfigFile(); + connectToDB(); + addItems(); + createActions(); + createMenus(); + createToolBars(); + createStatusBar(); + setColumnWidths(); +} + +void qOrganizer::getWDirPath() +{ + QSettings registrySettings("qOrganizer","qOrganizer"); + globalWDirPath = registrySettings.value("pathtowdir","home").toString(); + C_PATH = globalWDirPath; + if(globalWDirPath=="home") globalWDirPath=QDir::homePath()+QDir::separator()+".qOrganizer"; + else globalWDirPath=C_PATH+QDir::separator()+".qOrganizer"; + + if(settings!=0) settings->deleteLater(); + QSettings::setPath(QSettings::IniFormat,QSettings::UserScope,globalWDirPath); + settings = new QSettings(QSettings::IniFormat,QSettings::UserScope,"qOrganizer", "qOrganizer",this); + +} + +void qOrganizer::readSettings() +{ + //QSettings settings("qOrganizer", "qOrganizer"); + + /*Already done in main: (because doing it here caused the window to not be shown on first launch. + + QSize size = settings -> value("windowsize").toSize(); + this -> resize(size); + bool maximized = settings -> value("windowmaximized").toBool(); + if(maximized) this->showMaximized();*/ + + C_LANGUAGETEXT = settings -> value("language").toString(); + //FTP settings: + C_HOST = settings -> value("host").toString(); + C_PORT = settings -> value("port").toInt(); + C_USER = settings -> value("user").toString(); + C_PASSWD = settings -> value("passwd").toString(); + C_FTPPATH = settings -> value("path").toString(); + //Other settings: + C_SYSTRAY = settings -> value("tosystrayonclose",0).toBool(); + C_SOUND = settings -> value("soundonremind",1).toBool(); + + C_STORINGMODE = settings -> value("storingmode").toInt(); + + //MySQL settings + + C_MYSQL_HOST=settings -> value("mysqlhost").toString(); + C_MYSQL_PORT=settings -> value("mysqlport").toInt(); + C_MYSQL_USER=settings -> value("mysqluser").toString(); + C_MYSQL_PASSWD=settings -> value("mysqlpasswd").toString(); + C_MYSQL_DB=settings -> value("mysqldb").toString(); + + //Different timetables + C_USE_ODDTT=settings -> value("useoddtimetable",0).toBool(); + C_TT_REVERSORDER=settings -> value("reverseweekorder",0).toBool(); + C_ROUND_ON_AVERAGE = settings -> value("roundonaverage",1).toBool(); + C_SHOW_SAVE = settings->value("showsavebuttons",1).toBool(); + +} + +void qOrganizer::writeSettings() +{ + //QSettings settings("qOrganizer", "qOrganizer"); + settings -> setValue("windowsize", this->size()); + settings -> setValue("windowmaximized", this->isMaximized()); +} + +//The about box + +aboutDialog::aboutDialog() +{ + setWindowTitle(tr("About")+" qOrganizer"+" v3.1"); + aboutLabel = new QLabel( + QString("qOrganizer : Copyright 2007 Balázs Béla
\n")+ + QString("E-mail:balazsbela@gmail.com
")+ + QString("http://qorganizer.sourceforge.net/
")+ + QString("
")+ + tr( + "\n
This software is licenced under GPL version 2
published by" + " the Free Software Foundation.
\n" + "\n" + "
This application aims to bring simplicity in your life by
" + " organizing your data in an intuitive way so you can always
" + " find what you need and never forget something important.
" + "This application focuses on students, providing
" + "the features they consider usefull.
\n") + ); + + aboutLabel->setWordWrap(1); + textLayout = new QHBoxLayout(); + textLayout -> addWidget(aboutLabel); + textLayout -> setAlignment(Qt::AlignHCenter); + textWidget = new QWidget(); + textWidget -> setLayout(textLayout); + + tabWidget = new QTabWidget(); + tabWidget -> addTab(textWidget,tr("About")); + + thanksToLabel = new QLabel("" + "Evgeniy Ivanov (Russian translation)
" + "Luis Bastos (Portuguese translation)
" + "Blaz Kure (Slovenian translation)
" + "Jefim Borissov (Estonian translation)
" + "Driton Bakiu (Albanian and Macedonian translation)
" + "Nicolas Schubert (Spanish translation)
" + "Wouter Gelderblom (Dutch translation)
" + "Jens Körner (German translation)
" + "Naji Mammeri (French translation)
" + "Dariusz Gadomski (Polish translation)
" + "Xavier Corredor Llano (nuvoX iconset)
"); + + thanksToLabel -> setWordWrap(0); + thanksLayout = new QHBoxLayout; + thanksLayout -> addWidget(thanksToLabel); + thanksLayout -> setAlignment(Qt::AlignHCenter); + + thanksWidget = new QWidget; + thanksWidget -> setLayout(thanksLayout); + tabWidget -> addTab(thanksWidget,tr("Thanks to")); + + okButton = new QPushButton("OK"); + okButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + okButton -> setFixedWidth(60); + okLayout = new QHBoxLayout; + okLayout -> setAlignment(Qt::AlignHCenter); + okLayout -> addWidget(okButton); + connect(okButton,SIGNAL(clicked()),this,SLOT(close())); + + layout = new QVBoxLayout; + layout -> addWidget(tabWidget); + layout -> addLayout(okLayout); + + setLayout(layout); +} + +void aboutDialog::close() +{ + this->deleteLater(); +} + +aboutDialog::~aboutDialog() +{ +}; + +void qOrganizer::about() +{ + /* QMessageBox::about(this, tr("About qOrganizer")+" v3.0", + tr("qOrganizer : Copyright 2007 Balázs Béla
\n" + "\nE-mail:balazsbela@gmail.com
\n" + "\n" + "\n
\n" + "\n" + "\n
This software is licenced under GPL version 2 published by" + " the Free Software Foundation.
\n" + "\n" + "
This application aims to bring simplicity in your life by " + " organizing your data in an intuitive way so you can " "always find what you need and never forget something " "important.
This application focuses on students, providing " + "the features they consider usefull.

\n" + "Special thanks to:my girlfriend for " "supporting me, to my friends for testing this " "application," + "and to Xavier Corredor Llano, for releasing the nuvoX " "iconset under GPL
" + ));*/ + aboutD = new aboutDialog; + aboutD->show(); +} + +//Actions +void qOrganizer::createActions() +{ + //calendar Action + calAct = new QAction(QIcon(":/images/calendar.png"), tr("&Calendar"), this); + calAct->setShortcut(tr("Ctrl+Alt+C")); + calAct->setStatusTip(tr("Calendar")); + calAct->setToolTip(tr("Calendar")); + connect(calAct, SIGNAL(triggered()),this, SLOT(ChangeToCalendar())); + + //save Action + saveAct = new QAction(QIcon(":/images/save.png"),tr("Save"),this); + saveAct->setShortcut(tr("Ctrl+Y")); + saveAct->setStatusTip(tr("Save")); + saveAct->setToolTip(tr("Save")); + connect(saveAct,SIGNAL(triggered()),this, SLOT(saveAll())); + + //save to database Action + saveToDBAct = new QAction(QIcon(":/images/databasesqlite.png"),tr("&SQLite Database"),this); + saveToDBAct->setShortcut(tr("Ctrl+D")); + saveToDBAct->setStatusTip(tr("Save to SQLite database")); + saveToDBAct->setToolTip(tr("Save to SQLite database")); + connect(saveToDBAct,SIGNAL(triggered()),this, SLOT(saveAlltoSQLiteDB())); + + saveToMySQLDBAct = new QAction(QIcon(":/images/databasemysql.png"),tr("&MySQL Database"),this); + saveToMySQLDBAct->setShortcut(tr("Ctrl+M")); + saveToMySQLDBAct->setStatusTip(tr("Save to MySQL database")); + saveToMySQLDBAct->setToolTip(tr("Save to MySQL database")); + connect(saveToMySQLDBAct,SIGNAL(triggered()),this, SLOT(saveAlltoMySQLDB())); + + saveToTXTAct = new QAction(QIcon(":/images/save.png"),tr("&Text files"),this); + saveToTXTAct->setShortcut(tr("Ctrl+T")); + saveToTXTAct->setStatusTip(tr("Save to text files")); + saveToTXTAct->setToolTip(tr("Save to text files")); + connect(saveToTXTAct,SIGNAL(triggered()),this, SLOT(saveAlltoTXT())); + + //The action that changes to the to-do page + toDoAct = new QAction(QIcon(":/images/todo.png"), tr("&To-do List"), this); + toDoAct->setShortcut(tr("Ctrl+Alt+T")); + toDoAct->setStatusTip(tr("Edit your to-do list")); + toDoAct->setToolTip(tr("To-do list")); + connect(toDoAct, SIGNAL(triggered()),this, SLOT(ChangetoToDoList())); + + //The action that changes to the timetable page + timeTableAct = new QAction(QIcon(":/images/timetable.png"), tr("&TimeTable"), this); + timeTableAct->setShortcut(tr("Ctrl+Alt+L")); + timeTableAct->setStatusTip(tr("Edit your timetable")); + timeTableAct->setToolTip(tr("Timetable")); + connect(timeTableAct, SIGNAL(triggered()),this, SLOT(ChangeToTimeTable())); + + //The action that changes to the booklet actions + bookletAct = new QAction(QIcon(":/images/booklet.png"), tr("&Booklet"), this); + bookletAct->setShortcut(tr("Ctrl+Alt+B")); + bookletAct->setStatusTip(tr("Keep track of your school marks and absences")); + bookletAct->setToolTip(tr("Booklet")); + connect(bookletAct, SIGNAL(triggered()),this, SLOT(ChangeToBooklet())); + + //Print action + printAct = new QAction(QIcon(":/images/print.png"), tr("&Print"), this); + printAct->setShortcut(tr("Ctrl+P")); + printAct->setStatusTip(tr("Print Page")); + printAct->setToolTip(tr("Print Page")); + connect(printAct, SIGNAL(triggered()),this, SLOT(printPage())); + + + //Exit action + exitAct = new QAction(QIcon(":/images/exit.png"),tr("E&xit"), this); + exitAct->setShortcut(tr("Ctrl+Q")); + exitAct->setStatusTip(tr("Exit the application")); + connect(exitAct, SIGNAL(triggered()), this, SLOT(exitApp())); + + //The action for the about box + aboutAct = new QAction(QIcon(":/images/icon.png"),tr("&About"), this); + aboutAct->setStatusTip(tr("Show the application's About box")); + connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); + + //About Qt + aboutQtAct = new QAction(tr("About &Qt"), this); + aboutQtAct->setStatusTip(tr("Show the Qt library's About box")); + connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + + //Upload to FTP server + uploadAct = new QAction(QIcon(":/images/upload.png"), tr("&Upload"), this); + uploadAct ->setShortcut(tr("Ctrl+Alt+U")); + uploadAct ->setStatusTip(tr("Upload data to FTP server")); + uploadAct ->setToolTip(tr("Upload data to FTP server")); + connect(uploadAct,SIGNAL(triggered()),this,SLOT(initUpload())); + + //Download from FTP server + downloadAct = new QAction(QIcon(":/images/download.png"), tr("&Download"), this); + downloadAct ->setShortcut(tr("Ctrl+Alt+W")); + downloadAct ->setStatusTip(tr("Download data from FTP server")); + downloadAct ->setToolTip(tr("Download data from FTP server")); + connect(downloadAct,SIGNAL(triggered()),this,SLOT(getFromFTP())); + + //Settings dialog + settingsAct = new QAction(QIcon(":/images/settings.png"),tr("&Settings"),this); + settingsAct -> setShortcut(tr("Ctrl+Alt+S")); + settingsAct -> setStatusTip(tr("Configure application")); + connect(settingsAct, SIGNAL(triggered()), this ,SLOT(showSettings())); + +} + + +//Set up menus +void qOrganizer::createMenus() +{ + fileMenu = menuBar()->addMenu(tr("&File")); + saveToMenu = new QMenu(fileMenu); + saveToMenu -> setTitle(tr("Save to")); + saveToMenu -> setIcon(QIcon(":/images/save.png")); + saveToMenu -> addAction(saveToDBAct); + saveToMenu -> addAction(saveToMySQLDBAct); + saveToMenu -> addAction(saveToTXTAct); + + fileMenu->addAction(saveAct); + fileMenu->addAction(saveToMenu->menuAction()); + fileMenu->addAction(printAct); + fileMenu->addAction(exitAct); + + viewMenu = menuBar()->addMenu(tr("&View")); + viewMenu -> addAction(calAct); + viewMenu -> addAction(toDoAct); + viewMenu -> addAction(timeTableAct); + viewMenu -> addAction(bookletAct); + + settingsMenu = menuBar()->addMenu(tr("&Settings")); + settingsMenu -> addAction(settingsAct); + + ftpMenu = menuBar() -> addMenu(tr("FT&P")); + ftpMenu -> addAction(uploadAct); + ftpMenu -> addAction(downloadAct); + + helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(aboutAct); + //helpMenu->addAction(aboutQtAct); + + contextMenu = new QMenu(); + contextMenu -> addAction(settingsAct); + contextMenu -> addAction(aboutAct); + contextMenu -> addAction(exitAct); + tray -> setContextMenu(contextMenu); +} + +//Set up toolbars +void qOrganizer::createToolBars() +{ + + fileToolBar = addToolBar(tr("File")); + fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); + fileToolBar->setIconSize(QSize(64,64)); + //fileToolBar->setContentsMargins(50,0,100,0); + fileToolBar->addAction(calAct); + fileToolBar->addAction(toDoAct); + fileToolBar->addAction(timeTableAct); + fileToolBar->addAction(bookletAct); + fileToolBar->addAction(printAct); + fileToolBar->addAction(saveAct); + if(C_AUTOSAVE_TOGGLE) saveAct->setVisible(false); + fileToolBar->addAction(downloadAct); + fileToolBar->addAction(uploadAct); + fileToolBar -> addAction(settingsAct); + fileToolBar->addAction(saveToTXTAct); + fileToolBar->addAction(saveToDBAct); + fileToolBar->addAction(saveToMySQLDBAct); + + if(C_STORINGMODE==0) + { + saveToTXTAct->setVisible(false); + } + else + if(C_STORINGMODE==1) + { + saveToDBAct->setVisible(false); + } + else + if(C_STORINGMODE==2) + { + saveToMySQLDBAct->setVisible(false); + } + + if(!C_SHOW_SAVE) + { + saveToTXTAct->setVisible(false); + saveToDBAct->setVisible(false); + saveToMySQLDBAct->setVisible(false); + } + + if(C_SYNCFTP) + { + downloadAct -> setVisible(true); + uploadAct -> setVisible(true); + } else + { + downloadAct -> setVisible(false); + uploadAct -> setVisible(false); + } + +} + +void qOrganizer::createStatusBar() +{ + statusBar()->showMessage(tr("Ready")); + statusProgress = new QProgressBar(statusBar()); + statusBar() -> addPermanentWidget(statusProgress,1); + statusProgress -> setMaximumHeight(20); + statusProgress -> setMaximumWidth(120); + statusProgress -> setMinimum(0); + statusProgress -> setMaximum(0); + statusProgress -> hide(); + +} + +void qOrganizer::addCalendarPageWidgets() +{ + //widgets in the page + calendar=new QCalendarWidget; //The Calendar + calendar->setGridVisible(true); + calendar-> setFirstDayOfWeek (Qt::DayOfWeek(C_FIRST_DAY_OF_WEEK)); + calendar->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed); + + QDate date = calendar->selectedDate(); + selDate = date.toString(C_DT_FORMAT); + QString Date = "
"+tr("Schedule for ")+selDate+":
"; + day = new QLabel(Date); + + connect(calendar, SIGNAL(selectionChanged()), this, SLOT(updateDay())); + + tableWid = new CQTableWidget(); + tableWid->setRowCount(C_NRROWS); + tableWid->setColumnCount(4); + tableWid->setParent(this); + tableWid -> verticalHeader()->hide(); +// tableWid -> setSortingEnabled(true); + tableWid -> setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + + Clabels << tr("Event") << tr("From")<< tr("Until")<setHorizontalHeaderLabels(Clabels); + tableWid -> setColumnWidth(0,285); + tableWid -> setColumnWidth(1,60); + tableWid -> setColumnWidth(2,60); + tableWid -> setColumnWidth(3,75); + + tableWid -> horizontalHeader() -> setStretchLastSection(true); + tableWid -> horizontalHeader() -> setMovable(true); + tableWid -> setItemDelegate(&schDelegate); + tableWid -> setObjectName("tableWid"); + + newButton = new QPushButton(tr("New event")); + newButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + connect(newButton, SIGNAL(clicked()),this, SLOT(insertRowToEnd())); + + deleteButton = new QPushButton(tr("Delete event")); + deleteButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + connect(deleteButton, SIGNAL(clicked()),this, SLOT(deleteRow())); + + textField = new CQTextEdit; + textField->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + textField->setAcceptDrops(true); + fontBox = new QFontComboBox; + /*fontBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); + fontBox->adjustSize();*/ + comboSize = new QComboBox(); + comboSize->setObjectName("comboSize"); + comboSize->setEditable(true); + //Populate the font combo box + QFontDatabase db; + foreach(int size, db.standardSizes()) + comboSize->addItem(QString::number(size)); + //Set it to 12 + comboSize->setCurrentIndex(6); + B=new QPushButton(tr("B")); + I=new QPushButton(tr("I")); + U=new QPushButton(tr("U")); + + B->setCheckable(true); + U->setCheckable(true); + I->setCheckable(true); + + B -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + I -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + U -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + + //Set the selected Font + this -> setFont(); + + QString note = "
"+tr("Important notes, journal for ")+selDate+":
"; + noteLabel = new QLabel(note); + + searchLabel = new QLabel(tr("Search:")); + searchField = new LineEdit(this); + searchPrevButton = new QPushButton(tr("Previous")); + searchPrevButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + searchNextButton = new QPushButton(tr("Next")); + searchNextButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + searchLayout = new QHBoxLayout; + searchLayout -> addWidget(searchLabel); + searchLayout -> addWidget(searchField); + searchLayout -> addWidget(searchPrevButton); + searchLayout -> addWidget(searchNextButton); + searchCurrentIndex=-1; +} + +void qOrganizer::connectCallendarPageWidgets() +{ + //Make sure that the new Font is set if the boxes change + connect(fontBox,SIGNAL(currentFontChanged(QFont)), this, SLOT(setFont())); + connect(comboSize,SIGNAL(currentIndexChanged(int)), this, SLOT(setFont())); + + connect(B,SIGNAL(clicked()), this, SLOT(setFont())); + connect(U,SIGNAL(clicked()), this, SLOT(setFont())); + connect(I,SIGNAL(clicked()), this, SLOT(setFont())); + + //Change the font for every new character + connect(textField, SIGNAL(textChanged()), this, SLOT(modifyText())); + //Update if calendar changed + connect(calendar, SIGNAL(selectionChanged()), this, SLOT(updateCalendar())); + //Automatically Save after every change :P + if(C_AUTOSAVE_TOGGLE) + connect(tableWid,SIGNAL(focusLost()),this,SLOT(saveSchedule())); + //for error checking call remind if cell changed + connect(tableWid,SIGNAL(cellChanged(int,int)),this,SLOT(remind())); + + if(C_AUTOSAVE_TOGGLE) + connect(textField,SIGNAL(focusLost()),this,SLOT(saveJurnal())); + //If an event gets deleted save + if(C_AUTOSAVE_TOGGLE) + connect(deleteButton, SIGNAL(clicked()), this , SLOT(saveSchedule())); + //Search + connect(searchPrevButton,SIGNAL(clicked()),this,SLOT(searchPrev())); + connect(searchNextButton,SIGNAL(clicked()),this,SLOT(searchNext())); +} + +void qOrganizer::layoutCalendarPageWidgets() +{ + //The layouts for the widgets + + buttonLayout = new QHBoxLayout; + buttonLayout -> addWidget(newButton); + buttonLayout -> addWidget(deleteButton); + + vl = new QVBoxLayout; //vertical layout + vl -> addWidget(calendar); + vl -> addWidget(day); + vl -> addWidget(tableWid); + vl -> addLayout(buttonLayout); + vl -> setSizeConstraint(QLayout::SetNoConstraint); + + QHBoxLayout *settingsLayout = new QHBoxLayout; + settingsLayout ->addWidget(fontBox); + settingsLayout ->addWidget(comboSize); + settingsLayout ->addWidget(B); + settingsLayout ->addWidget(I); + settingsLayout ->addWidget(U); + settingsLayout ->setSizeConstraint(QLayout::SetNoConstraint); + + textLayout = new QVBoxLayout; + textLayout ->addWidget(noteLabel); + textLayout ->addLayout(settingsLayout); + textLayout ->addWidget(textField); + textLayout ->addLayout(searchLayout); + + mainLayout = new QHBoxLayout;; + mainLayout ->addLayout(vl); + mainLayout ->addLayout(textLayout); + + CalendarPage= new QWidget; //Page that contains the callendar + CalendarPage->setLayout(mainLayout); + + mainWid->addWidget(CalendarPage); + mainWid->setCurrentIndex(0); + +} + + + +void qOrganizer::addCalendarPage() +{ + + addCalendarPageWidgets(); + if(C_STORINGMODE==0) loadJurnal(); else loadJurnalDB(); + if(C_STORINGMODE==0) loadSchedule(); else loadScheduleDB(); + connectCallendarPageWidgets(); + layoutCalendarPageWidgets(); + timer = new QTimer(); + setReminders(); +} + +//---------------------- TO-DO PAGE ----------------------------------- + +void qOrganizer::addToDoPage() +{ + + //Widgets: + + ToDoPage=new QWidget; + QLabel *ToDoTitle= new QLabel ("
"+tr("General to-do list")+"
"); + + list=new CQTableWidget; + list->setRowCount(10); + list->setColumnCount(5); + list->setParent(this); + list -> verticalHeader()->hide(); + list -> setObjectName("list"); + + TDlabels <setHorizontalHeaderLabels(TDlabels); + list -> setColumnWidth(0,80); + list -> setColumnWidth(1,620); + list -> setColumnWidth(2,80); + list -> setColumnWidth(3,80); + list -> setColumnWidth(4,90); + list -> horizontalHeader() -> setStretchLastSection(true); + list -> horizontalHeader() -> setMovable(true); + list -> setItemDelegate(&tdlistDelegate); + + newTaskButton = new QPushButton(tr("New task")); + deleteTaskButton = new QPushButton(tr("Delete task")); + newTaskButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + deleteTaskButton-> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + connect(newTaskButton,SIGNAL(clicked()),this,SLOT(newTask())); + connect(deleteTaskButton,SIGNAL(clicked()),this,SLOT(deleteTask())); + if(C_AUTOSAVE_TOGGLE) + connect(list,SIGNAL(focusLost()),this,SLOT(saveToDoList())); + + //Layouts: + + ToDoVl=new QVBoxLayout; + ToDoVl->addWidget(ToDoTitle); + ToDoVl->addWidget(list); + ToDoVl -> setSizeConstraint(QLayout::SetNoConstraint); + + buttonVl=new QHBoxLayout; + buttonVl->addWidget(newTaskButton); + buttonVl->addWidget(deleteTaskButton); + + mainHl = new QVBoxLayout; + mainHl ->addLayout(ToDoVl); + mainHl ->addLayout(buttonVl); + + QHBoxLayout *layout= new QHBoxLayout; + layout->addSpacing(10); + layout->addLayout(mainHl); + layout->addSpacing(10); + + ToDoPage->setLayout(layout); + mainWid->addWidget(ToDoPage); + +}; + +//----------------------------Timetable---------------------------------- + +void qOrganizer::addTimeTable() +{ + timeTablePage=new QWidget; + QLabel *timeTableTitle= new QLabel ("
"+tr("Timetable")+":
"); + + table=new CQTableWidget; + table->setRowCount(9); + table->setColumnCount(7); + table->setParent(this); + //table -> verticalHeader()->hide(); + table -> setSortingEnabled(false); + table -> setItemDelegate(&ttDelegate); + + TTlabels << tr("From") <setHorizontalHeaderLabels(TTlabels); + for(int i=0;i<=2;i++) + { + table -> setColumnWidth(i,55); + }; + for(int i=2;i<=table->columnCount()-1;i++) + { + table -> setColumnWidth(i,960/(table->columnCount()-1)); + } + table -> horizontalHeader() -> setStretchLastSection(true); + + newTTRow = new QPushButton(tr("New row")); + newTTCmn = new QPushButton(tr("New column")); + delTTCmn = new QPushButton(tr("Delete column")); + delTTRow = new QPushButton(tr("Delete row")); + newTTRow -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + newTTCmn -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + delTTRow-> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + delTTCmn-> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + connect(newTTRow,SIGNAL(clicked()),this,SLOT(newRow())); + connect(delTTRow,SIGNAL(clicked()),this,SLOT(delRow())); + connect(newTTCmn,SIGNAL(clicked()),this,SLOT(newColumn())); + connect(delTTCmn,SIGNAL(clicked()),this,SLOT(delColumn())); + if(C_AUTOSAVE_TOGGLE) + connect(table,SIGNAL(focusLost()),this,SLOT(saveTimeTable())); + + //Layouts: + + Vl=new QVBoxLayout; + Vl->addWidget(timeTableTitle); + Vl->addWidget(table); + Vl -> setSizeConstraint(QLayout::SetNoConstraint); + + ttLabel = new QLabel(tr("Timetable for:")); + ttCombo = new QComboBox; + + ttCombo -> addItem(tr("Odd weeks")); + ttCombo -> addItem(tr("Even weeks")); + + + QDate cDate = QDate::currentDate(); + if(!C_TT_REVERSORDER) + if(cDate.weekNumber() % 2 != 0) C_TIMETABLE_INDEX=0; else C_TIMETABLE_INDEX=1; + + if(C_TT_REVERSORDER) + if(cDate.weekNumber() % 2 != 0) C_TIMETABLE_INDEX=1; else C_TIMETABLE_INDEX=0; + + if(!C_USE_ODDTT) C_TIMETABLE_INDEX=0; + + ttCombo -> setCurrentIndex(C_TIMETABLE_INDEX); + + ttCombo->setFixedWidth(160); + ttCombo -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + calledFromTTCombo=0; + connect(ttCombo,SIGNAL(currentIndexChanged(int)),this,SLOT(changeTTIndex(int))); + + ttLayout = new QHBoxLayout; + ttLayout -> addWidget(ttLabel); + ttLayout -> addWidget(ttCombo); + ttLayout -> setAlignment(Qt::AlignRight); + if(!C_USE_ODDTT) + { + ttLabel->hide(); + ttCombo->hide(); + } + + centerLayout = new QHBoxLayout; + centerLayout->addWidget(newTTCmn); + centerLayout->addSpacing(50); + centerLayout->addWidget(delTTCmn); + centerLayout->addSpacing(50); + centerLayout->addWidget(newTTRow); + centerLayout->addSpacing(50); + centerLayout->addWidget(delTTRow); + centerLayout -> setAlignment(Qt::AlignHCenter); + + BHl=new QHBoxLayout; + BHl->addLayout(centerLayout); + BHl->addSpacing(50); + BHl->addLayout(ttLayout); + BHl-> setAlignment(Qt::AlignHCenter); + Vl->addLayout(BHl); + + QHBoxLayout *layout= new QHBoxLayout; + layout->addSpacing(10); + layout->addLayout(Vl); + layout->addSpacing(10); + + timeTablePage->setLayout(layout); + mainWid->addWidget(timeTablePage); +}; + +//-----------------------------Booklet---------------------------- + + +void qOrganizer::addBookletPage() +{ + bookletPage=new QWidget(); + //Widgets + QLabel *bLabel=new QLabel("
"+tr("Booklet")+"
"); + QLabel *markLabel = new QLabel("
"+tr("Marks:")+"
"); + QLabel *absenceLabel = new QLabel("
"+tr("Absences:")+"
"); + markTable = new CQTableWidget(); + absenceTable = new CQTableWidget(); + markTable -> setRowCount(8); + markTable -> setColumnCount(6); + markTable -> setParent(this); + markTable -> horizontalHeader()->hide(); + + + for(int i=0;i<=6;i++) + { + markTable -> setColumnWidth(i,50); + }; + + subjectList < setVerticalHeaderLabels(subjectList); + + absenceTable -> setRowCount(8); + absenceTable -> setColumnCount(5); + absenceTable -> setParent(this); + absenceTable -> horizontalHeader()->hide(); + absenceTable -> verticalHeader()->hide(); + absenceTable -> setItemDelegate(&absDelegate); + + for(int i=0;i<=absenceTable->columnCount();i++) + { + absenceTable -> setColumnWidth(i,630/absenceTable->columnCount()); + }; + + //Neded to delete cells in this, by the custom delegate + absenceTable->setObjectName(QString("absenceTable")); + + newMarkButton = new QPushButton(tr("New mark column")); + newSubjectButton = new QPushButton(tr("New subject")); + deleteSubjectButton = new QPushButton(tr("Delete subject")); + deleteMarkButton = new QPushButton(tr("Delete mark column")); + newAbsenceButton = new QPushButton(tr("New absence column")); + deleteAbsenceButton = new QPushButton(tr("Delete absence column")); + + newMarkButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + newSubjectButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + deleteMarkButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + deleteSubjectButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + newAbsenceButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + deleteAbsenceButton -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + + + QLabel *averageFieldLabel = new QLabel(tr("Subject average:")); + QLabel *absenceFieldLabel = new QLabel(tr("Absences:")); + QLabel *markDateLabel = new QLabel(tr("Date:")); + averageField = new QLineEdit(); + averageField->setFixedWidth(45); + averageField->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + absenceNrField = new QLineEdit(); + markDateField = new QDateEdit(QDate::currentDate(),this); + markDateField -> setDisplayFormat("dd/M/yyyy"); + markDateField->setCalendarPopup(true); + markDateField->setFixedWidth(100); + markDateField->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + averageField -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + absenceNrField -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + + totalAverageField = new QLineEdit(); + totalAverageField -> setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + totalAverageField -> setFixedWidth(45); + QLabel *totalAverageLabel = new QLabel(tr("Total average:")); + QLabel *voidLabel = new QLabel(" "); + //Layouts + + QHBoxLayout *averageLayout = new QHBoxLayout; + averageLayout -> addWidget(markDateLabel); + averageLayout -> addWidget(markDateField); + averageLayout -> addSpacing(20); + averageLayout -> addWidget(averageFieldLabel); + averageLayout -> addWidget(averageField); + averageLayout -> addWidget(voidLabel); + averageLayout -> addSpacing(20); + averageLayout -> addWidget(totalAverageLabel); + averageLayout -> addWidget(totalAverageField); + + QHBoxLayout *absenceFieldLayout = new QHBoxLayout; + absenceFieldLayout -> addWidget(absenceFieldLabel); + absenceFieldLayout -> addWidget(absenceNrField); + + QVBoxLayout *markLayout = new QVBoxLayout; + markLayout -> addWidget(markLabel); + markLayout -> addWidget(markTable); + markLayout -> addLayout(averageLayout); + + QVBoxLayout *absenceLayout = new QVBoxLayout; + absenceLayout -> addWidget(absenceLabel); + absenceLayout -> addWidget(absenceTable); + absenceLayout -> addLayout(absenceFieldLayout); + + + QHBoxLayout *tableLayout = new QHBoxLayout; + tableLayout -> addLayout(markLayout); + tableLayout -> addSpacing(30); + tableLayout -> addLayout(absenceLayout); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout -> addWidget(newMarkButton); + buttonLayout -> addWidget(deleteMarkButton); + buttonLayout -> addWidget(newSubjectButton); + buttonLayout -> addWidget(deleteSubjectButton); + buttonLayout -> addWidget(newAbsenceButton); + buttonLayout -> addWidget(deleteAbsenceButton); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout -> addWidget(bLabel); + mainLayout -> addLayout(tableLayout); + mainLayout -> addLayout(buttonLayout); + + bookletPage->setLayout(mainLayout); + mainWid->addWidget(bookletPage); + + //Connect buttons + if(C_STORINGMODE==0) loadMarksTable(); else loadMarksTableDB(); + if(C_STORINGMODE==0) loadMarkDates(); else loadMarkDatesDB(); + if(C_STORINGMODE==0) loadAbsenceTable(); else loadAbsenceTableDB(); + markTable->setCurrentCell(0,0); + updateAverage(0,0,1,0); + updateAbsenceNr(); + updateTotalAverage(); + + connect(newSubjectButton,SIGNAL(clicked()),this,SLOT(newSubject())); + connect(deleteSubjectButton,SIGNAL(clicked()),this,SLOT(deleteSubject())); + connect(newMarkButton,SIGNAL(clicked()),this,SLOT(newMark())); + connect(deleteMarkButton,SIGNAL(clicked()),this,SLOT(deleteMark())); + connect(newAbsenceButton,SIGNAL(clicked()),this,SLOT(newAbsence())); + connect(deleteAbsenceButton,SIGNAL(clicked()),this,SLOT(deleteAbsence())); + if(C_AUTOSAVE_TOGGLE) + connect(markTable,SIGNAL(focusLost()),this,SLOT(saveMarksTable())); + if(C_AUTOSAVE_TOGGLE) + connect(absenceTable,SIGNAL(focusLost()),this,SLOT(saveAbsenceTable())); + + connect(markTable,SIGNAL(currentCellChanged(int,int,int,int)),this,SLOT(updateAverage(int,int,int,int))); + connect(markTable,SIGNAL(cellChanged(int,int)),this,SLOT(updateTotalAverage())); + connect(absenceTable,SIGNAL(cellChanged(int,int)),this,SLOT(updateAbsenceNr())); + + connect(markTable,SIGNAL(currentCellChanged(int,int,int,int)),this,SLOT(updateDate(int,int,int,int))); + connect(markDateField,SIGNAL(dateChanged(QDate)),this,SLOT(saveDate(QDate))); + + //synch scrollbars + connect(markTable->verticalScrollBar(),SIGNAL(valueChanged(int)),absenceTable->verticalScrollBar(),SLOT(setValue(int))); + connect(absenceTable->verticalScrollBar(),SIGNAL(valueChanged(int)),markTable->verticalScrollBar(),SLOT(setValue(int))); +}; + + +// Let's put these all together + +void qOrganizer::addItems() +{ + QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF8")); + QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF8")); + setSTray(); + mainWid= new QStackedWidget; //Let's set up the Main Widget + setCentralWidget(mainWid); //Let's make it the Central Widget + addCalendarPage(); + addToDoPage(); + addTimeTable(); + addBookletPage(); + if(C_STORINGMODE==0) loadToDoList(); else loadToDoListDB(); + if(C_STORINGMODE==0) loadTimeTable(); else loadTimeTableDB(); + //Resize timetable + for(int i=2;i<=table->columnCount()-1;i++) + table -> setColumnWidth(i,960/(table->columnCount()-1)); + downloadingFromFTP=0; +}; + +//-----------------------SLOTS--------------------------------- + +/*This function sets the QStackedWidgets current index to 0 therefore makes the +calendar page active*/ + +void qOrganizer::ChangeToCalendar() +{ + if(C_LOAD_ON_CHANGE) + updateCalendar(); + + if((C_AUTOSAVE_TOGGLE)&&(C_STORINGMODE==0)) saveAll(); + mainWid->setCurrentIndex(0); +} + +/*This function sets the QStackedWidgets current index to 1 therefore makes the +to-do list page active*/ + +void qOrganizer::ChangetoToDoList() +{ + if(C_LOAD_ON_CHANGE) + if(C_STORINGMODE==0) loadToDoList(); else loadToDoListDB(); + if((C_AUTOSAVE_TOGGLE)&&(C_STORINGMODE==0)) saveAll(); + mainWid->setCurrentIndex(1); +} + +/*This function sets the QStackedWidgets current index to 2 therefore makes the +timetable page active*/ + +void qOrganizer::ChangeToTimeTable() +{ + if(C_LOAD_ON_CHANGE) + if(C_STORINGMODE==0) loadTimeTable(); else loadTimeTableDB(); + if((C_AUTOSAVE_TOGGLE)&&(C_STORINGMODE==0)) saveAll(); + mainWid->setCurrentIndex(2); +} + + +/*This function sets the QStackedWidgets current index to 3 therefore makes the +Booklet page active*/ + +void qOrganizer::ChangeToBooklet() +{ + if(C_LOAD_ON_CHANGE) + { + if(C_STORINGMODE==0) loadMarksTable(); else loadMarksTableDB(); + if(C_STORINGMODE==0) loadAbsenceTable(); else loadAbsenceTableDB(); + } + if((C_AUTOSAVE_TOGGLE)&&(C_STORINGMODE==0)) saveAll(); + mainWid->setCurrentIndex(3); +} + +//-----------------------CALENDAR SLOTS---------------------------- + +//adds a new row to the schedule table, which is named tableWid (from tableWidget) +void qOrganizer::insertRowToEnd() +{ + tableWid->setRowCount(tableWid->rowCount()+1); +} + +//deletes a row from the schedule table +void qOrganizer::deleteRow() +{ + tableWid->removeRow(tableWid->currentRow()); +} + +//Updates the two labels when the callendar changes date +void qOrganizer::updateDay() +{ + QDate date = calendar->selectedDate(); + selDate = date.toString(C_DT_FORMAT); + QString Date ="
"+tr("Schedule for ")+selDate+":
"; + day->setText(Date); + QString note ="
"+tr("Important notes, journal for ")+selDate+":
"; + noteLabel->setText(note); + +} + +/*TODO: Fix the BUG: The first characters font after change + Does not get changed.Don't know why. + +*/ + + +void qOrganizer::modifyText() +{ + /*When a new character apears select it and change it's font to the currently selected font*/ + + + cursor = textField->textCursor(); + if(cursor.selectedText()=="") + { + cursor.movePosition(QTextCursor::Left,QTextCursor::KeepAnchor); + //cout << "Selected text is:"; + textField->setCurrentFont(font); + /*cout << cursor.selectedText()<<"\n"; + cout <<"Font used:"; + cout << font.rawName() <<" "<currentFont(); + font.setPointSize((comboSize->currentText()).toInt()); + //fontBox->adjustSize(); + + if(B->isChecked()) + font.setBold(true); + + if(I->isChecked()) + font.setItalic(true); + + if(U->isChecked()) + font.setUnderline(true); + + textField->setCurrentFont(font); + + //cout << font.rawName() <<" "<clearContents(); + tableWid->setRowCount(C_NRROWS); + + tableWid -> setColumnWidth(0,285); + tableWid -> setColumnWidth(1,60); + tableWid -> setColumnWidth(2,60); + tableWid -> setColumnWidth(3,75); + +} + +//This function changes to the directory in which the callendar stores it's data +//By default this is ~/.qOrganizer/calendar but I plan to make a setting dialog for this +void qOrganizer::setCalDir() +{ + if(C_PATH=="home") + QDir::setCurrent(QDir::homePath()); + else QDir::setCurrent(C_PATH); + QDir currentDir = QDir::current(); + currentDir.mkdir(".qOrganizer"); + currentDir.cd(".qOrganizer"); + currentDir.mkdir("calendar"); + currentDir.cd("calendar"); + QDir::setCurrent(currentDir.path()); + QDate date = calendar->selectedDate(); + selDate = date.toString("MM_dd_yyyy")+".txt"; +} + + +void qOrganizer::loadSchedule() //Load the daily schedule into the schedule table named tableWid +{ + if(C_STORINGMODE!=0) loadScheduleDB(); else + { + setCalDir(); + QFile scheduleFile(selDate); + //For writing QStrings to stdout + QTextStream cout(stdout, QIODevice::WriteOnly); + + cout <<"Loading file:"<< selDate <<"\n"; + emptyTable(); + if (scheduleFile.open(QFile::ReadOnly)) + { + QTextStream in(&scheduleFile); + in.setCodec("UTF-8"); + int i=-1; + while(!in.atEnd()) + { + QString line=in.readLine(); + i++; + if(line!="\n") + { + QStringList list = line.split("|", QString::KeepEmptyParts); + if(i>=tableWid->rowCount()) + { + insertRowToEnd(); + //cout<<"Adding a new row:"<rowCount()<<"\n"; + } + for (int j = 0; j < list.size(); j++) + { + item= new QTableWidgetItem(QTableWidgetItem::Type); + if(list.at(j)==" ") + item->setText(""); + else + item->setText(list.at(j)); + //This is the way to access an item from the QStringList + if(tableWid->item(i,j)!=0) delete tableWid->takeItem(i,j); + tableWid->setItem(i,j,item); + } + } + } + tableWid->setRowCount(i+1); + scheduleFile.close(); + } + else + { + emptyTable(); + } + } +} + +//The tables are stored in a textfile, items are separated with | + +void qOrganizer::saveSchedule() //Save the daily schedule +{ + if(C_STORINGMODE!=0) saveScheduleDB(); else + { + setCalDir(); + QFile scheduleFile(selDate); + //For writing QStrings to stdout + QTextStream cin(stdin, QIODevice::ReadOnly); + QTextStream cout(stdout, QIODevice::WriteOnly); + QTextStream cerr(stderr, QIODevice::WriteOnly); + + cout << "Saving "<currentRow(); + int y=tableWid->currentColumn(); + + for(int i=0;irowCount();i++) + { + for(int j=0;jcolumnCount();j++) + { + tableWid->setCurrentCell(i,j); + item=tableWid->currentItem(); + if(item!=0) + out << item->text()+"|"; + else out << " |"; + } + out <<"\n"; + } + scheduleFile.close(); + tableWid->setCurrentCell(x,y); + } + else { + QMessageBox::warning(NULL, "qOrganizer", "Unable to write schedule file.", "OK"); + } + } +} + + +void qOrganizer::updateCalendar() +{ + saveCalendarColumnWidths(); + if(C_STORINGMODE==0) + { + loadSchedule(); + loadJurnal(); + } + else + { + loadScheduleDB(); + loadJurnalDB(); + } + setCalendarColumnWidths(); +} + +//----------------------JURNALS SLOTS FOR CALENDAR-------------------- + +//This saves the journal into an html file named as jurnal_currentDate.html +void qOrganizer::saveJurnal() +{ + if(C_STORINGMODE!=0) saveJurnalDB(); else + { + //For writing QStrings to stdout + QTextStream cin(stdin, QIODevice::ReadOnly); + QTextStream cout(stdout, QIODevice::WriteOnly); + QTextStream cerr(stderr, QIODevice::WriteOnly); + + setCalDir(); + QDate date = calendar->selectedDate(); + QString fileName ="jurnal_"+date.toString("MM_dd_yyyy")+".html"; + QFile jurnalFile(fileName); + cout <<"Saving journal file:\n"; + cout <toHtml(); + out << text; + } + else + { + QMessageBox::warning(NULL, "qOrganizer", "Unable to write journal file.", "OK"); + }; + jurnalFile.close(); + } +} + +//This loads the jurnal file to the CQTextEdit object named textField which is the Jurnal editor +void qOrganizer::loadJurnal() +{ + if(C_STORINGMODE!=0) loadJurnalDB(); else + { + //For writing QStrings to stdout + QTextStream cin(stdin, QIODevice::ReadOnly); + QTextStream cout(stdout, QIODevice::WriteOnly); + QTextStream cerr(stderr, QIODevice::WriteOnly); + + setCalDir(); + cout <<"Loading journal file:\n"; + QDate date = calendar->selectedDate(); + QString fileName ="jurnal_"+date.toString("MM_dd_yyyy")+".html"; + QFile jurnalFile(fileName); + cout<setHtml(text); + } + else + { + textField->setHtml(""); + }; + jurnalFile.close(); + } +} + +//This sets a timer to check for reminders every 30 seconds, this way we can still do the job in a +//CPU friendly way +void qOrganizer::setReminders() +{ + connect(timer, SIGNAL(timeout()), this, SLOT(remind())); + timer->start(C_TIMEOUT); +}; + +//We need this in the remind function +bool CQTableWidget::isBeingEdited() +{ + if(this->state()==QAbstractItemView::EditingState) + return 1; + else return 0; +}; + +//This checks if it has to remind the user of an event +void qOrganizer::remind() +{ + //This is for debuging purposes only + QTextStream cout(stdout, QIODevice::WriteOnly); + //We remember the coordinates of the current cell to set it back + int x=tableWid->currentRow(); + int y=tableWid->currentColumn(); + /*We need to set the calendar to the date of today to load all reminders for today + but this could be annoying for the user in a maximized state so we do it only if minimized + just to be safe + This is implemented in the reimplementation of hideEvent. + Everytime the app gets minimized it returns to the current day so reminders apply only for that + day and nothing is missed. + */ + + //We can't parse the table for data if the user is editing a cell because it would get it all //selected and when the user types a new character it would be overwritten, the reminder column is + //an exception because we need to check for errors and report them right away. + if((!tableWid->isBeingEdited())||(y==3)) + { + //Parse the table for reminders + for(int i=0;i<=tableWid->rowCount();i++) + { + tableWid->setCurrentCell(i,3); + item=tableWid->currentItem(); + if(item!=0) + { + QString timeString = item->text(); + tableWid->setCurrentCell(i,0); + item=tableWid->currentItem(); + QString eventString; + if(item!=0) + eventString = item->text(); + else eventString =""; + + //This is because there are to excepted formats for the timeString + // Example: 12:00 is equal to 12 + if(timeString.indexOf(":")!=-1) + { + //Cut the string and make it into a QTime object + if(timeString.size()==4) + timeString="0"+timeString; + QString hourString=timeString; + hourString.remove(hourString.indexOf(":"),3); + + QString minuteString=timeString; + minuteString.remove(0,3); + bool ok; + bool ok2; + int hour = hourString.toInt(&ok,10); + int minute = minuteString.toInt(&ok2,10); + if((ok&&ok2)&&(hour<24)&&(hour>=0)&&(minute>=0)&&(minute<=60)) + { + QTime time = QTime(hour,minute,0,0); + QDate date = calendar -> selectedDate(); + if((timesetCurrentCell(i,3); + item=tableWid->currentItem(); + item -> setText(""); + //To avoid phantom reminders + if(C_STORINGMODE==0) saveSchedule(); else saveScheduleDB(); + QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon(QSystemTrayIcon::Information); + /*Pops up a baloon in the system tray notifying the user about the event + This stays active for 2 hours (7200 seconds), I guess that's enough for the user to + notice it.*/ + if(C_BALOON_SET) + tray->showMessage("qOrganizer",eventString,icon,7200000); + else + { + if(!this->isVisible()) toggleVisibility(); + QMessageBox::about(this,"qOrganizer", eventString); + } + //This will look pretty and not block the sound since it's not modal. + tableWid->setCurrentCell(i,3); + item=tableWid->currentItem(); + item -> setText(""); + //To avoid phantom reminders + if(C_STORINGMODE==0) saveSchedule(); else saveScheduleDB(); + } + } + else + { + QMessageBox::warning(NULL, "qOrganizer",tr("Couldn't set reminder!\nThere are two excepted formats for reminders.\nOne is hh:mm.\nExample:17:58.\nOr the other one is just writing the hour.\nExample: 3 is equal to 3:00 or to 03:00" ) , "OK"); + tableWid->setCurrentCell(i,3); + item=tableWid->currentItem(); + item -> setText(""); + //To avoid phantom reminders + if(C_STORINGMODE==0) saveSchedule(); else saveScheduleDB(); + } + } + else + { + if((timeString.size()==2)||(timeString.size()==1)) + { + bool ok; + int hour = timeString.toInt(&ok,10); + if((ok)&&(hour<24)&&(hour>=0)) + { + QTime time = QTime(hour,0,0,0); + QDate date = calendar -> selectedDate(); + if((timesetCurrentCell(i,3); + item=tableWid->currentItem(); + item -> setText(""); + //To avoid phantom reminders + if(C_STORINGMODE==0) saveSchedule(); else saveScheduleDB(); + QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon(QSystemTrayIcon::Information); + if(C_BALOON_SET) + tray->showMessage("qOrganizer",eventString,icon,7200000); + else + { + if(!this->isVisible()) toggleVisibility(); + QMessageBox::about(this,"qOrganizer", eventString); + } + + //This will look pretty and not block the sound since it's not modal. + } + } + else + { + if((timeString.size()!=0)&&(timeString!=" ")&&(timeString!=" ") + &&(timeString!=" ")) + { + QMessageBox::warning(NULL, "qOrganizer",tr("Couldn't set reminder!\nThere are two excepted formats for reminders.\nOne is hh:mm.\nExample:17:58.\nOr the other one is just writing the hour.\nExample: 3 is equal to 3:00 or to 03:00" ) , "OK"); + tableWid->setCurrentCell(i,3); + item=tableWid->currentItem(); + item -> setText(""); + //To avoid phantom reminders + if(C_STORINGMODE==0) saveSchedule(); else saveScheduleDB(); + } + } + + } + else + { + if((timeString.size()!=0)&&(timeString!=" ")&&(timeString!=" ") + &&(timeString!=" ")) + { + QMessageBox::warning(NULL, "qOrganizer",tr("Couldn't set reminder!\nThere are two excepted formats for reminders.\nOne is hh:mm.\nExample:17:58.\nOr the other one is just writing the hour.\nExample: 3 is equal to 3:00 or to 03:00" ) , "OK"); + tableWid->setCurrentCell(i,3); + item=tableWid->currentItem(); + item -> setText(""); + //To avoid phantom reminders + if(C_STORINGMODE==0) saveSchedule(); else saveScheduleDB(); + } + } + } + }; + }; + tableWid -> setCurrentCell(x,y); + }; +}; + + +//---------------------------------------SIGNALS--------------------------------------- + +//Reimplementation of focusOutEvent to emit a signal we can catch to know +//when to save +//AUTOSAVE works on focusOutEvents so it consumes less cpu then connecting it to +//cellChanged(int,int) +void CQTableWidget::focusOutEvent( QFocusEvent * event ) +{ + if((event->reason()==Qt::MouseFocusReason) || + (event->reason()==Qt::TabFocusReason)|| + (event->reason()==Qt::ActiveWindowFocusReason)) + { + emit focusLost(); + } + +} + +void CQTextEdit::focusOutEvent( QFocusEvent * event ) +{ + if((event->reason()==Qt::MouseFocusReason) || + (event->reason()==Qt::TabFocusReason) || + (event->reason()==Qt::ActiveWindowFocusReason)) + { + emit focusLost(); + } +} + +bool CQTextEdit::canInsertFromMimeData( const QMimeData *source ) const + { + if (source->hasFormat("text/uri-list")) + return true; + else + return QTextEdit::canInsertFromMimeData(source); + } + +void CQTextEdit::insertFromMimeData( const QMimeData *source ) + { + + if (source->hasFormat("text/uri-list")) + { + QTextCursor cursor = this->textCursor(); + QTextDocument *document = this->document(); + QString origin = source->urls()[0].toLocalFile(); + #ifdef Q_OS_LINUX //toLocalFile() doesn't work + origin = source->urls()[0].toString(); + origin.remove("file://"); + #endif + #ifdef Q_OS_WIN32 + origin = source->urls()[0].toString(); + origin.remove("file:///"); + #endif + QImage *image = new QImage(origin); + if(!image->isNull()) + { + document->addResource(QTextDocument::ImageResource,origin,image); + cursor.insertImage(origin); + } + delete image; + } else QTextEdit::insertFromMimeData(source); + } + +//-----------------------------------------LINEEDIT WITH CLEAR BUTTON---------------------------------------- +LineEdit::LineEdit(qOrganizer *parent) : QLineEdit(parent) +{ + clearButton = new QToolButton(this); + Parent = parent; + QPixmap pixmap(":/images/clear.png"); + clearButton->setIcon(QIcon(pixmap)); + clearButton->setIconSize(pixmap.size()); + clearButton->setCursor(Qt::ArrowCursor); + clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); + clearButton->hide(); + connect(clearButton, SIGNAL(clicked()), this, SLOT(clearAndSetDateBack())); + connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateCloseButton(const QString&))); + int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(clearButton->sizeHint().width() + frameWidth + 1)); + QSize msz = minimumSizeHint(); + setMinimumSize(qMax(msz.width(), clearButton->sizeHint().height() + frameWidth * 2 + 2), + qMax(msz.height(), clearButton->sizeHint().height() + frameWidth * 2 + 2)); +} + +void LineEdit::resizeEvent(QResizeEvent *) +{ + QSize sz = clearButton->sizeHint(); + int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + clearButton->move(rect().right() - frameWidth - sz.width(), + (rect().bottom() + 1 - sz.height())/2); +} + +void LineEdit::updateCloseButton(const QString& text) +{ + clearButton->setVisible(!text.isEmpty()); +} + +void LineEdit::clearAndSetDateBack() +{ + this->clear(); + Parent->ChangeToCalendar(); + Parent->calendar->setSelectedDate(QDate::currentDate()); + Parent->updateDay(); + if(Parent->C_STORINGMODE==0) Parent->loadJurnal(); else Parent->loadJurnalDB(); + if(Parent->C_STORINGMODE==0) Parent->loadSchedule(); else Parent->loadScheduleDB(); + Parent->setCalendarColumnWidths(); +} + +//------------------------TO-DO LIST SLOTS-------------------------- + +void qOrganizer::newTask() +{ + list->setRowCount(list->rowCount()+1); +} + +void qOrganizer::deleteTask() +{ + list->removeRow(list->currentRow()); +}; + +//Sets the todo list directory +void qOrganizer::setTDDir() +{ + if(C_PATH=="home") + QDir::setCurrent(QDir::homePath ()); + else QDir::setCurrent(C_PATH); + QDir currentDir = QDir::current(); + currentDir.mkdir(".qOrganizer"); + currentDir.cd(".qOrganizer"); + currentDir.mkdir("todo"); + currentDir.cd("todo"); + QDir::setCurrent(currentDir.path()); +} + +//Saves the to-do list +void qOrganizer::saveToDoList() +{ + if(C_STORINGMODE!=0) saveToDoListDB(); else + { + setTDDir(); + QFile todoFile("todo.txt"); + cout <<"Saving to-do list file:\n"; + + if (todoFile.open(QFile::WriteOnly)) + { + QTextStream out(&todoFile); + out.setCodec("UTF-8"); + int x=list->currentRow(); + int y=list->currentColumn(); + for(int i=0;irowCount();i++) + { + for(int j=0;jcolumnCount();j++) + { + list->setCurrentCell(i,j); + item=list->currentItem(); + if(item!=0) + out << item->text()+"|"; + else out << " |"; + } + out <<"\n"; + } + todoFile.close(); + list->setCurrentCell(x,y); + } + else + { + QMessageBox::warning(NULL, "qOrganizer", "Unable to write To-Do list file.", "OK"); + } + } +} + +//Loads the to-do list +void qOrganizer::loadToDoList() +{ + if(C_STORINGMODE!=0) loadToDoListDB(); else + { + list -> setSortingEnabled(false); + list->clearContents(); + list->setRowCount(0); + setTDDir(); + QFile todoFile("todo.txt"); + if (todoFile.open(QFile::ReadOnly)) + { + cout << "Loading to-do list\n"; + QTextStream in(&todoFile); + in.setCodec("UTF-8"); + int i=-1; + while(!in.atEnd()) + { + QString line=in.readLine(); + i++; + if(line!="\n") + { + QStringList slist = line.split("|", QString::KeepEmptyParts); + if(i>=list->rowCount()) + { + newTask(); + cout<<"TODO:Adding a new row:"<rowCount()<<"\n"; + }; + for (int j = 0; j < slist.size(); j++) + { + item= new QTableWidgetItem(QTableWidgetItem::Type); + item->setText(slist.at(j)); + if(list->item(i,j)!=0) delete list->takeItem(i,j); + list->setItem(i,j,item); + }; + } + } + list->setRowCount(i+1); + if(i==-1) list->setRowCount(10); + } + else + { + cout << "Could not open to-do list file\n"; + list->setRowCount(10); + } + todoFile.close(); + list -> setSortingEnabled(true); + } +} + + +//-------------------------TIMETABLE SLOTS--------------------- + +void qOrganizer::newRow() +{ + table->setRowCount(table->rowCount()+1); +}; + +void qOrganizer::delRow() +{ + table->removeRow(table->currentRow()); +}; + +void qOrganizer::delColumn() +{ + TTlabels.removeAt(table->currentColumn()); + englishList.removeAt(table->currentColumn()); + table->removeColumn(table->currentColumn()); +} + +//This brings up a dialog and asks for a dayname to add as a column because in some countryes +//they have school even saturday.Doesn't that suck :( ? + +void qOrganizer::newColumn() +{ + bool ok; + QString text = QInputDialog::getText(this, + "", + tr("Column name:"), QLineEdit::Normal, + tr("Saturday"), &ok, + Qt::Dialog + ); + if (!ok || text.isEmpty()) + { + text=tr("Saturday"); + }; + + table->setColumnCount(table->columnCount()+1); + TTlabels<setHorizontalHeaderLabels(TTlabels); + for(int i=2;i<=table->columnCount()-1;i++) + table -> setColumnWidth(i,960/(table->columnCount()-1)); +} + +//Set's the directory for the Timetable +void qOrganizer::setTTDir() +{ + if(C_PATH=="home") + QDir::setCurrent(QDir::homePath ()); + else QDir::setCurrent(C_PATH); + QDir currentDir = QDir::current(); + currentDir.mkdir(".qOrganizer"); + currentDir.cd(".qOrganizer"); + currentDir.mkdir("timetable"); + currentDir.cd("timetable"); + QDir::setCurrent(currentDir.path()); +}; + +//Saves the timetable +void qOrganizer::saveTimeTable() +{ + if(C_STORINGMODE!=0) saveTimeTableDB(); else + { + setTTDir(); + QString ttFileName; + if(C_TIMETABLE_INDEX==0) ttFileName="timetable.txt"; else ttFileName="timetable_even.txt"; + QFile timeTableFile(ttFileName); + cout <<"Saving timetable file\n"; + if (timeTableFile.open(QFile::WriteOnly)) + { + QTextStream out(&timeTableFile); + out.setCodec("UTF-8"); + int x=table->currentRow(); + int y=table->currentColumn(); + //Save column names + if(!englishList.isEmpty()) + for(int i=0;irowCount();i++) + { + for(int j=0;jcolumnCount();j++) + { + table->setCurrentCell(i,j); + QTableWidgetItem *item=table->currentItem(); + if(item!=0) + out << item->text()+"|"; + else out <<" |"; + } + out <<"\n"; + } + timeTableFile.close(); + table->setCurrentCell(x,y); + } + else + { + QMessageBox::warning(NULL, "qOrganizer", "Unable to write timetable file.", "OK"); + } + } +} + +//Loads the timetable +void qOrganizer::loadTimeTable() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + + if(C_STORINGMODE!=0) loadTimeTableDB(); else + { + setTTDir(); + QString ttFileName; + if(C_TIMETABLE_INDEX==0) ttFileName="timetable.txt"; else ttFileName="timetable_even.txt"; + QFile timeTableFile(ttFileName); + if (timeTableFile.open(QFile::ReadOnly)) + { + cout << "Loading timetable:"<setColumnCount(labelsList.size()); + table->setHorizontalHeaderLabels(labelsList); + TTlabels = labelsList; + + while(!in.atEnd()) + { + QString line=in.readLine(); + i++; + if(line!="\n") + { + QStringList slist = line.split("|", QString::KeepEmptyParts); + if(i>=table->rowCount()) + { + newRow(); + cout<<"TimeTable:Adding a new row:"<rowCount()<<"\n"; + }; + for (int j = 0; j < slist.size(); j++) + { + item= new QTableWidgetItem(QTableWidgetItem::Type); + item->setText(slist.at(j)); + if(table->item(i,j)!=0) delete table->takeItem(i,j); + table->setItem(i,j,item); + } + } + } + table->setRowCount(i+1); + } + timeTableFile.close(); + } +} + +//------------------------------------------BOOKLET SLOTS------------------------------------------ + +//New Column +void qOrganizer::newMark() +{ + markTable->setColumnCount(markTable->columnCount()+1); + markTable->setColumnWidth(markTable->columnCount()-1,50); +}; + +//New row with custom header +void qOrganizer::newSubject() +{ + bool ok; + QString text = QInputDialog::getText(this, + "", + tr("Subject name:"), QLineEdit::Normal, + tr(""), &ok, + Qt::Dialog + ); + if (ok || !text.isEmpty()) + { + markTable->setRowCount(markTable->rowCount()+1); + absenceTable->setRowCount(markTable->rowCount()); + subjectList<setVerticalHeaderLabels(subjectList); + }; + +}; + +//Remove column +void qOrganizer::deleteMark() +{ + markTable -> removeColumn(markTable->currentColumn()); +}; + +//Remove row, this also affects the absence table and also deletes it from the QStringList called +//subjectList +void qOrganizer::deleteSubject() +{ + int pos = markTable->currentRow(); + markTable -> removeRow(markTable->currentRow()); + absenceTable->removeRow(markTable->currentRow()+1); + subjectList.removeAt(pos); +}; + +//New column in the absence table +void qOrganizer::newAbsence() +{ + absenceTable->setColumnCount(absenceTable->columnCount()+1); + absenceTable->setColumnWidth(absenceTable->columnCount()-1,80); +}; + +//Remove column from the absence table +void qOrganizer::deleteAbsence() +{ + absenceTable->removeColumn(absenceTable->currentColumn()); +}; + +void qOrganizer::setBDir() //set booklet directory +{ + if(C_PATH=="home") + QDir::setCurrent(QDir::homePath ()); + else QDir::setCurrent(C_PATH); + QDir currentDir = QDir::current(); + currentDir.mkdir(".qOrganizer"); + currentDir.cd(".qOrganizer"); + currentDir.mkdir("booklet"); + currentDir.cd("booklet"); + QDir::setCurrent(currentDir.path()); +}; + +//Saves the contents of the markTable into a textfile +//The first line contains the vertical headers (subjects) of the marktable separated with | +//The other lines contain the marks separated with | +void qOrganizer::saveMarksTable() +{ + if(C_STORINGMODE!=0) saveMarksTableDB(); else + { + setBDir(); + QFile markFile("marks.txt"); + cout <<"Saving marks file\n"; + + if (markFile.open(QFile::WriteOnly)) + { + QTextStream out(&markFile); + out.setCodec("UTF-8"); + int x=markTable->currentRow(); + int y=markTable->currentColumn(); + //Save row names + for(int i=0;irowCount();i++) + { + for(int j=0;jcolumnCount();j++) + { + markTable->setCurrentCell(i,j); + QTableWidgetItem *item=markTable->currentItem(); + if(item!=0) + out << item->text()+"|"; + else out <<" |"; + } + out <<"\n"; + } + markFile.close(); + markTable->setCurrentCell(x,y); + } + else + { + QMessageBox::warning(NULL, "qOrganizer", "Unable to write marks into file.", "OK"); + } + } +} + +/* + Here I kind of had a problem with QStringList::split, it worked buggy and I couldn't figure it out + why so I wrote my own using stl strings and vector +*/ + +void qOrganizer::splitMyString(QString s) +//According to a trace this had extreme memory problems under 64 bit, and therefore is not used anymore +{ + v.clear(); + string str = s.toStdString(); + string delim="|"; + unsigned int offset = 0; + unsigned int delimIndex = 0; + + delimIndex = str.find(delim, offset); + + while (delimIndex != string::npos) + { + v.push_back(str.substr(offset, delimIndex - offset)); + offset += delimIndex - offset + delim.length(); + delimIndex = str.find(delim, offset); + } + + v.push_back(str.substr(offset)); +} + + +//Loads the marks in markTable +//v is the vector in which the string get's splitted +void qOrganizer::loadMarksTable() +{ + if(C_STORINGMODE!=0) loadMarksTableDB(); else + { + setBDir(); + QFile markFile("marks.txt"); + /* //For writing QStrings to stdout + QTextStream cin(stdin, QIODevice::ReadOnly); + QTextStream cout(stdout, QIODevice::WriteOnly); + QTextStream cerr(stderr, QIODevice::WriteOnly);*/ + + if (markFile.open(QFile::ReadOnly)) + { + cout << "Loading marks!\n"; + QTextStream in(&markFile); + in.setCodec("UTF-8"); + int i=-1; + QString firstline=in.readLine(); + QStringList labelsList = firstline.split("|", QString::SkipEmptyParts); //Here it works, funny + markTable->setRowCount(labelsList.size()); + absenceTable->setRowCount(labelsList.size()); + markTable->setVerticalHeaderLabels(labelsList); + subjectList=labelsList; + QStringList slist; + + while(!in.atEnd()) + { + QString line=in.readLine(); + i++; + //splitMyString(line); Let's try something new because splitMyString is causing problems on 64bit + QStringList v = line.split("|",QString::KeepEmptyParts); + markTable->setColumnCount(v.size()-1); + //sets the Column count to the number of elements in a line of the textfile + for(int j=0;jsetText(v[j]); + if(markTable->item(i,j)!=0) delete markTable->takeItem(i,j); + markTable->setItem(i,j,item); + } + } + } + markFile.close(); + for(int a=0;acolumnCount();a++) + markTable->setColumnWidth(a,50); + } +} + +//Save absences same format absence dates separated with | +//Example: 20.03.2007|13.01.2007|08.05.2007| +void qOrganizer::saveAbsenceTable() +{ + if(C_STORINGMODE!=0) saveAbsenceTableDB(); else + { + setBDir(); + QFile absenceFile("absences.txt"); + cout <<"Saving absences into file\n"; + + if (absenceFile.open(QFile::WriteOnly)) + { + QTextStream out(&absenceFile); + out.setCodec("UTF-8"); + int x=absenceTable->currentRow(); + int y=absenceTable->currentColumn(); + + for(int i=0;irowCount();i++) + { + for(int j=0;jcolumnCount();j++) + { + absenceTable->setCurrentCell(i,j); + QTableWidgetItem *item=absenceTable->currentItem(); + if(item!=0) + out << item->text()+"|"; + else out <<" |"; + } + out <<"\n"; + } + absenceFile.close(); + absenceTable->setCurrentCell(x,y); + } + else + { + QMessageBox::warning(NULL, "qOrganizer", "Unable to write absences into file.", "OK"); + } + } +} + +//Load the absences into absenceTable +void qOrganizer::loadAbsenceTable() +{ + if(C_STORINGMODE!=0) loadAbsenceTableDB(); else + { + setBDir(); + QFile absenceFile("absences.txt"); + if (absenceFile.open(QFile::ReadOnly)) + { + cout << "Loading absences!\n"; + QTextStream in(&absenceFile); + in.setCodec("UTF-8"); + int i=-1; + QStringList slist; + while(!in.atEnd()) + { + QString line=in.readLine(); + i++; + //splitMyString(); + QStringList v = line.split("|",QString::KeepEmptyParts); + absenceTable->setColumnCount(v.size()-1); + for (int j = 0; j < v.size(); j++) + { + item= new QTableWidgetItem(QTableWidgetItem::Type); + item->setText(v[j]); + if(absenceTable->item(i,j)!=0) delete absenceTable->takeItem(i,j); + absenceTable->setItem(i,j,item); + }; + } + } + + absenceFile.close(); + for(int i=0;icolumnCount();i++) + absenceTable->setColumnWidth(i,80); + } +} + +double qOrganizer::calculateRowAverage(int row) +{ + double average; + double sum=0; + double nr=0; + + for(int j=0;jcolumnCount();j++) + { + markTable->setCurrentCell(row,j); + QTableWidgetItem *item=markTable->currentItem(); + if(item!=0) + { + sum=sum+(item->text()).toFloat(); + if((item->text()).toFloat()!=0) nr++; + } + } + if(nr!=0) average=sum/nr; + else average=0; + + + return average; +}; + +//This recalculates the average of the marks in markTable when the current row changes +//nr=new row, nc=new column, pr=previous row,pc=previous column + +void qOrganizer::updateAverage(int nr,int nc,int pr,int pc) +{ + Q_UNUSED(nc); + Q_UNUSED(pc); + if(nr!=pr) + { + + int x=markTable->currentRow(); + int y=markTable->currentColumn(); + double average = calculateRowAverage(x); + markTable->setCurrentCell(x,y); + //cout<<"Average:"<4) averageString.resize(4); + averageField->setText(averageString); + } +} + +//This recalculates the total average based on all data +void qOrganizer::updateTotalAverage() +{ + int x=markTable->currentRow(); + int y=markTable->currentColumn(); + + double sum=0; + double nr = markTable->rowCount(); + + for(int i=0;irowCount();i++) + { + double result = calculateRowAverage(i); + if(C_ROUND_ON_AVERAGE) result=round(result); + if(result==0) nr--; + sum=sum+result; + }; + + double average; + if(nr!=0) average=sum/nr; + else average=0; + cout << "Total average:"<4) averageString.resize(4); + totalAverageField->setText(averageString); + markTable->setCurrentCell(x,y); +}; + +//This recounts the absences in absenceTable when that looses focus +void qOrganizer::updateAbsenceNr() +{ + int nr=0; + + int x=absenceTable->currentRow(); + int y=absenceTable->currentColumn(); + + for(int i=0;irowCount();i++) + { + for(int j=0;jcolumnCount();j++) + { + absenceTable->setCurrentCell(i,j); + QTableWidgetItem *item=absenceTable->currentItem(); + if(item!=0) + { + if(((item->text()).size()!=0)&&(item->text()!=" ")&&(item->text()!=" ")) nr++; + } + } + } + + absenceTable->setCurrentCell(x,y); + absenceNrField->setText(QString::number(nr)); +}; + +//Close event, save on close and quit + +void qOrganizer::closeEvent(QCloseEvent *e) +{ + saveColumnWidths(); + if((C_AUTOSAVE_TOGGLE)&&(!downloadingFromFTP)) saveAll(); + writeSettings(); + + if(C_SYSTRAY) + { + e->ignore(); + hide(); + if(!downloadingFromFTP) + { + ChangeToCalendar(); + calendar->setSelectedDate(QDate::currentDate()); + updateDay(); + if(C_STORINGMODE==0) loadJurnal(); else loadJurnalDB(); + if(C_STORINGMODE==0) loadSchedule(); else loadScheduleDB(); + setCalendarColumnWidths(); + } + } + else + { + e->accept(); + tray->hide(); + qApp->quit(); + } + +} + +//---------------------------------SYSTEM TRAY------------------------ + + +//Sets the system tray Icon +void qOrganizer::setSTray() +{ + tray = new QSystemTrayIcon( this ); + tray->setIcon ( QIcon(":/images/icon.png") ); + connect(tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), +this,SLOT(trayActivated(QSystemTrayIcon::ActivationReason))); + tray->show(); +} + +//reimplementation of event +void qOrganizer::trayActivated(QSystemTrayIcon::ActivationReason reason) +{ + if (reason == QSystemTrayIcon::Trigger) + toggleVisibility(); +} + +//You guessed it toggles the visibility of the window +void qOrganizer::toggleVisibility() +{ + if(isHidden()) + { + show(); + if(isMinimized()) + { + if(isMaximized()) + showMaximized(); + else + showNormal(); + } + raise(); + activateWindow(); + } + else + { + hide(); + saveColumnWidths(); + if(!downloadingFromFTP) + { + cout << "Not Downloading so it's ok to load and save\n"; + if(C_AUTOSAVE_TOGGLE) saveAll(); + ChangeToCalendar(); + calendar->setSelectedDate(QDate::currentDate()); + updateDay(); + if(C_STORINGMODE==0) loadJurnal(); else loadJurnalDB(); + if(C_STORINGMODE==0) loadSchedule(); else loadScheduleDB(); + setCalendarColumnWidths(); + } + } +}; + +//This catches minimize events and saves when the window gets minimized and also hides +//the window entry in the taskbar so the program sits in the system tray +void qOrganizer::hideEvent(QHideEvent * event) +{ + Q_UNUSED(event); + if(this->isMinimized()) + { + if(!downloadingFromFTP) + { + if(C_AUTOSAVE_TOGGLE) saveAll(); + //Set the calendar back to the current day to make sure reminders will work + ChangeToCalendar(); + calendar->setSelectedDate(QDate::currentDate()); + updateDay(); + if(C_STORINGMODE==0) loadJurnal(); else loadJurnalDB(); + if(C_STORINGMODE==0) loadSchedule(); else loadScheduleDB(); + setCalendarColumnWidths(); + } + saveColumnWidths(); + } +} + +//-------------------------Printing---------------------------- + +//formats a document with the content of the callendar using a hidden QTextEdit widget and prints it +void qOrganizer::printCalendar() +{ + QTextEdit *hidden=new QTextEdit; + hidden->setParent(this); + hidden->show(); + //We construct a string in html and we use setHtml with the hidden QTextEdit + QString text=day->text(); + text.append("
"); + //Now for the schedule table + + int x=tableWid->currentRow(); + int y=tableWid->currentColumn(); //We remember the current column to set it back + + text.append(""); + text.append(""); + + text.append(""); + + for(int i=0;i"); + text.append(Clabels.at(i)); + text.append(""); + }; + + text.append(""); + + for(int i=0;irowCount();i++) + { + text.append(""); + + for(int j=0;jcolumnCount();j++) + { + tableWid->setCurrentCell(i,j); + item=tableWid->currentItem(); + if(item!=0) + text.append(""); + else + text.append(""); + } + text.append("
"); + } + + tableWid->setCurrentCell(x,y); + text.append("
"+item->text()+"


"); + //Jurnal + text.append(noteLabel->text()+"


"); + text.append(textField->toHtml()); + + hidden->setHtml(text); + QTextDocument *document = hidden->document(); + hidden->hide(); + document->print(printer); + delete printer; + delete hidden; +}; + +//Prints the to-do list under the same mechanism as in printCalendar() +void qOrganizer::printToDoList() +{ + QTextEdit *hidden=new QTextEdit; + hidden->setParent(this); + hidden->show(); + QString text; + int x=list->currentRow(); + int y=list->currentColumn(); + + text="
"+tr("General to-do list:")+"


"; + + text.append("
"); + text.append(""); + text.append(""); + + for(int i=0;i"); + text.append(TDlabels.at(i)); + text.append(""); + }; + + text.append(""); + + for(int i=0;irowCount();i++) + { + text.append(""); + + for(int j=0;jcolumnCount();j++) + { + list->setCurrentCell(i,j); + item=list->currentItem(); + if(item!=0) + text.append(""); + else + text.append(""); + } + text.append("
"); + } + + list->setCurrentCell(x,y); + text.append("
"+item->text()+"


"); + + hidden -> setHtml(text); + QTextDocument *document = hidden->document(); + hidden->hide(); + document->print(printer); + delete printer; + delete hidden; +}; + +//Prints the timetable +void qOrganizer::printTimeTable() +{ + QTextEdit *hidden=new QTextEdit; + hidden->setParent(this); + hidden->show(); + QString text; + int x=table->currentRow(); + int y=table->currentColumn(); + + text = "
"); + text.append("
"; + text.append("
"+tr("Timetable")+":
"); + text.append("
"); + text.append(""); + text.append(""); + + for(int i=0;i"); + text.append(TTlabels.at(i)); + text.append(""); + }; + + text.append(""); + + for(int i=0;irowCount();i++) + { + text.append(""); + + for(int j=0;jcolumnCount();j++) + { + table->setCurrentCell(i,j); + item=table->currentItem(); + if(item!=0) + text.append(""); + else + { + text.append(""); + }; + } + text.append("
"); + } + + table->setCurrentCell(x,y); + text.append("
"+item->text()+"


"); + + + hidden ->setHtml(text); + + QTextDocument *document = hidden->document(); + hidden->hide(); + document->print(printer); + delete printer; + delete hidden; +}; + +//Prints the booklet +void qOrganizer::printBooklet() +{ + QTextEdit *hidden=new QTextEdit; + hidden->setParent(this); + hidden->show(); + QString text; + + //Marks + int x=markTable->currentRow(); + int y=markTable->currentColumn(); + + text="
"); + + //Absences + + x=absenceTable->currentRow(); + y=absenceTable->currentColumn(); + + text.append("
"; + text.append("
"+tr("Marks:")+"

"); + + + text.append(""); + text.append(""); + + + for(int i=0;irowCount();i++) + { + text.append(""); + + for(int j=0;jcolumnCount();j++) + { + markTable->setCurrentCell(i,j); + item=markTable->currentItem(); + if(item!=0) + text.append(""); + else + { + text.append(""); + }; + } + text.append("
"); + } + + markTable->setCurrentCell(x,y); + text.append("
"); + text.append(subjectList.at(i)); + text.append(" "+item->text()+"

"+tr("Absences:")+"

"); + + text.append(""); + text.append(""); + + for(int i=0;irowCount();i++) + { + text.append(""); + + for(int j=0;jcolumnCount();j++) + { + absenceTable->setCurrentCell(i,j); + item=absenceTable->currentItem(); + if(item!=0) + text.append(""); + else + { + text.append(""); + }; + } + text.append("
"); + } + + absenceTable->setCurrentCell(x,y); + text.append("
"); + text.append(subjectList.at(i)); + text.append(" "+item->text()+"

"); + + hidden ->setHtml(text); + + QTextDocument *document = hidden->document(); + hidden->hide(); + document->print(printer); + delete printer; + delete hidden; +}; + + +//When the print button is hit on the toolbar the app checkes what page is active and prints the +//currently active page +void qOrganizer::printPage() +{ + printer = new QPrinter(); + QPrintDialog printDialog(printer, this); + if (printDialog.exec() == QDialog::Accepted) + { + if(mainWid->currentIndex()==0) + { + printCalendar(); + } + else + if(mainWid->currentIndex()==1) + { + printToDoList(); + } + else + if(mainWid->currentIndex()==2) + { + printTimeTable(); + } + else + if(mainWid->currentIndex()==3) + { + printBooklet(); + }; + }; + +}; + + +//-----------------------------------CONFIG FILE ------------------------------------------------ + +//sets the home directory where the config file is located +void qOrganizer::setConfigDir() +{ + QDir::setCurrent(QDir::homePath ()); + QDir currentDir = QDir::current(); + currentDir.mkdir(".qOrganizer"); + currentDir.cd(".qOrganizer"); + QDir::setCurrent(currentDir.path()); +}; + +//This is called if no config file is available, contains default settings +void qOrganizer::writeDefaultConfigFile() //this isn't used anymore! +{ + setConfigDir(); + QFile configFile("config.txt"); + cout <<"Writing default config file\n"; + + if (configFile.open(QFile::WriteOnly)) + { + QTextStream out(&configFile); + out.setCodec("UTF-8"); + out << "home" <<"\n"; //The default directory where the config file is located + out << "30000" <<"\n"; //The value for the timer to check for reminders + out << "1" <<"\n"; //First day of the week + out << "ON" <<"\n"; //Autosave toggle + out << "Baloon" <<"\n"; //Type of reminder + out << "4" <<"\n"; + out << "dddd MMMM d. yyyy" << "\n"; + out << "OFF" <<"\n"; + out << "OFF" <<"\n"; + } + else + { + QMessageBox::warning(NULL, "qOrganizer", "Unable to write config file.", "OK"); + }; + readConfigFile(); +}; + +//Reads the config file and sets the config variables which are noted all upercase starting +//with C_ (from CONFIG) +void qOrganizer::readConfigFile() +{ + /*setConfigDir(); + QFile configFile("config.txt"); + + if (configFile.open(QFile::ReadOnly)) + { + QTextStream in(&configFile); + in.setCodec("UTF-8"); + C_PATH = in.readLine(); + //QTextStream cout(stdout, QIODevice::WriteOnly); + C_TIMEOUT=(in.readLine()).toInt(); + C_FIRST_DAY_OF_WEEK = (in.readLine()).toInt(); + QString autosaveString = in.readLine(); + if(autosaveString=="ON") + C_AUTOSAVE_TOGGLE=true; + else C_AUTOSAVE_TOGGLE = false; + QString messageString = in.readLine(); + if(messageString=="Baloon") + C_BALOON_SET = true; + else C_BALOON_SET = false; + C_NRROWS = (in.readLine()).toInt(); + C_DT_FORMAT = in.readLine(); + QString ftpString = in.readLine(); + if(ftpString=="ON") + C_SYNCFTP=1; + else C_SYNCFTP=0; + QString loadString = in.readLine(); + if(loadString=="ON") + C_LOAD_ON_CHANGE=1; + else C_LOAD_ON_CHANGE=0; + } + else writeDefaultConfigFile();*/ + + //C_PATH =settings -> value("pathtowdir","home").toString(); + + C_TIMEOUT=settings -> value("rcheckinterval",20000).toInt(); + + C_FIRST_DAY_OF_WEEK=settings -> value("firstdayindex",1).toInt(); + + C_AUTOSAVE_TOGGLE=settings -> value("autosave",1).toBool(); + + if(settings -> value("remindertype","Baloon").toString()=="Baloon") + C_BALOON_SET = 1; else C_BALOON_SET=0; + + C_NRROWS = settings -> value("rownr",4).toInt(); + + C_DT_FORMAT = settings -> value("dateformat","dddd MMMM d. yyyy").toString(); + + C_SYNCFTP = settings -> value("ftpsynch",0).toBool(); + + C_LOAD_ON_CHANGE = settings -> value("reloaddata",0).toBool(); +} + +//Shows the setting dialog +void qOrganizer::showSettings() +{ + settingsDialog = new SettingsDialog(this); + settingsDialog -> show(); +}; + + +//Saves the config file this is connected to the OK button of the settings dialog +void qOrganizer::saveConfigFile() +{ + /*setConfigDir(); + QFile configFile("config.txt"); + if (configFile.open(QFile::WriteOnly)) + { + QTextStream out(&configFile); + out.setCodec("UTF-8"); + if(settingsDialog->pathEdit->text() == QDir::homePath()) + out << "home"; + else + if(!settingsDialog->pathEdit->text().endsWith(QDir::separator())) + out << settingsDialog->pathEdit->text()+QDir::separator(); + else + out << settingsDialog->pathEdit->text(); + out <<"\n"; + out << settingsDialog -> rBox -> value()<<"\n"; + out << settingsDialog -> firstDay -> currentIndex()+1<<"\n"; + if(settingsDialog->autoBox->isChecked()) + out <<"ON"; + else out << "OFF"; + out <<"\n"; + out << settingsDialog->messageCombo->currentText()<<"\n"; + out << settingsDialog->rownrBox->value()<<"\n"; + out << settingsDialog->dateFormatEdit->currentText()<<"\n"; + + if(settingsDialog->ftpBox->isChecked()) + out <<"ON"<<"\n"; + else out <<"OFF"<<"\n"; + + if(settingsDialog->loadBox->isChecked()) + out <<"ON"<<"\n"; + else out <<"OFF"<<"\n"; + } + else + { + QMessageBox::warning(NULL, "qOrganizer", "Unable to write config file.", "OK"); + };*/ + + /*if(settingsDialog->pathEdit->text() == QDir::homePath()) + settings -> setValue("pathtowdir", "home"); + else + if(!settingsDialog->pathEdit->text().endsWith(QDir::separator())) + settings -> setValue("pathtowdir",settingsDialog->pathEdit->text()+QDir::separator()); + else settings -> setValue("pathtowdir",settingsDialog->pathEdit->text());*/ + + //Store it in the registry + QSettings rsettings("qOrganizer","qOrganizer"); + if(settingsDialog->pathEdit->text() == QDir::homePath()) + rsettings.setValue("pathtowdir", "home"); + else + if(!settingsDialog->pathEdit->text().endsWith(QDir::separator())) + rsettings.setValue("pathtowdir",settingsDialog->pathEdit->text()+QDir::separator()); + else rsettings.setValue("pathtowdir",settingsDialog->pathEdit->text()); + + settings -> setValue("rcheckinterval",settingsDialog -> rBox -> value()); + settings -> setValue("firstdayindex",settingsDialog -> firstDay -> currentIndex()+1); + settings -> setValue("autosave",settingsDialog->autoBox->isChecked()); + settings -> setValue("remindertype",settingsDialog->messageCombo->currentText()); + settings -> setValue("rownr",settingsDialog->rownrBox->value()); + settings -> setValue("dateformat",settingsDialog->dateFormatEdit->currentText()); + settings -> setValue("ftpsynch",settingsDialog->ftpBox->isChecked()); + settings -> setValue("reloaddata",settingsDialog->loadBox->isChecked()); + + settings -> setValue("showsavebuttons",settingsDialog->saveAllBox->isChecked()); + //Store the selected language in the registry + //QSettings settings("qOrganizer", "qOrganizer"); + + settings -> setValue("language", settingsDialog->langCombo->currentText()); + settings -> setValue("host",settingsDialog->hostEdit->text()); + settings -> setValue("port",settingsDialog->portBox->value()); + settings -> setValue("user",settingsDialog->userEdit->text()); + settings -> setValue("passwd",settingsDialog->passEdit->text()); + settings -> setValue("path",settingsDialog->ftppathEdit->text()); + if(settingsDialog->trayBox->isChecked()) + settings -> setValue("tosystrayonclose",1); + else settings -> setValue("tosystrayonclose",0); + + if(settingsDialog->soundBox->isChecked()) + settings -> setValue("soundonremind",1); + else settings -> setValue("soundonremind",0); + + settings -> setValue("storingmode", settingsDialog->storingBox->currentIndex()); + + + //MySQL stuff + settings -> setValue("mysqlhost",settingsDialog->mysqlHostEdit->text()); + settings -> setValue("mysqlport",settingsDialog->mysqlPortBox->value()); + settings -> setValue("mysqluser",settingsDialog->mysqlUserEdit->text()); + settings -> setValue("mysqlpasswd",settingsDialog->mysqlPassEdit->text()); + settings -> setValue("mysqldb",settingsDialog->mysqldbEdit->text()); + + //Odd timetable + if(settingsDialog->oddTTBox->isChecked()) + settings -> setValue("useoddtimetable",1); + else settings -> setValue("useoddtimetable",0); + + if(settingsDialog->reverseTTBox->isChecked()) + settings -> setValue("reverseweekorder",1); + else settings -> setValue("reverseweekorder",0); + + if(settingsDialog->roundBox->isChecked()) + settings -> setValue("roundonaverage",1); + else settings -> setValue("roundonaverage",0); + + QTextStream cout(stdout, QIODevice::WriteOnly); + if(C_PATH!=settingsDialog->pathEdit->text()) + { + cout << "DirPath changed \n"; + if(C_AUTOSAVE_TOGGLE) toggleAutoSave(0); + getWDirPath(); + cout << C_PATH <<"\n"; + if(db.isOpen()) db.close(); + connectToDB(); + loadAll(); + if(changedAutoSave) toggleAutoSave(1); + } + + settingsDialog->close(); + readConfigFile(); //We re-read it only for the C_TIMEOUT variable to take effect instantly + readSettings(); //For the ftp to take effect instantly + + if(C_OLD_STORINGMODE!=C_STORINGMODE) + { + if(db.isOpen()) db.close(); + cout << C_PATH <<"\n"; + connectToDB(); + loadAll(); + } + + //If the user changed the storing mode then reload data + if(C_USE_ODDTT) + { + if(!ttLabel->isVisible()) ttLabel->show(); + if(!ttCombo->isVisible()) ttCombo->show(); + } + else + { + ttLabel->hide(); + ttCombo->hide(); + } + + if(!C_AUTOSAVE_TOGGLE) saveAct -> setVisible(true); + else saveAct->setVisible(false); + + if(C_SYNCFTP) + { + uploadAct->setVisible(true); + downloadAct->setVisible(true); + } + else + { + uploadAct->setVisible(false); + downloadAct->setVisible(false); + } + + if(!C_SHOW_SAVE) + { + saveToTXTAct->setVisible(false); + saveToDBAct->setVisible(false); + saveToMySQLDBAct->setVisible(false); + } + else + if(C_STORINGMODE==0) + { + saveToTXTAct->setVisible(false); + saveToDBAct->setVisible(true); + saveToMySQLDBAct->setVisible(true); + } + else + if(C_STORINGMODE==1) + { + saveToDBAct->setVisible(false); + saveToTXTAct->setVisible(true); + saveToMySQLDBAct->setVisible(true); + } + else + if(C_STORINGMODE==2) + { + saveToMySQLDBAct->setVisible(false); + saveToTXTAct->setVisible(true); + saveToDBAct->setVisible(true); + } +} + + +//------------------------------------FTP SYNC------------------------------------------------ + +/*Ok so this uploads a whole folder to a remote ftp server +The path is the folders name and the dir path is the folder where you keep it +Example: if the folder is /home/user/.qOrganizer then that is the path +and the dirPath is /home/user +This function is called from putToFTP() + +So QFtp is asynchronous, that's a good thing for the user, and bad for us, but we will deal with it.This is pretty readable and simple code: +*/ +void qOrganizer::sendFolder(const QString &path,const QString &dirPath) +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + QFileInfo fileInfo(path); + if (fileInfo.isDir()) + { + QString dirName = path; + dirName.remove(0,dirPath.size()); + if(!noFolders) + { + ftp->mkdir(dirName); + cout <<"Creating directory named:"<showMessage(tr("Uploading..."),10000); + sendFolder(dir.filePath(entry),dirPath); + } + } + else + { + QFile *file = new QFile(path); + uploadedFileQueue.enqueue(file); + if(file->open(QIODevice::ReadOnly)) + { + QString filename =path; + filename.remove(0,dirPath.size()); + putCommandVector.append(ftp->put(file,filename)); + cout << "put "<showMessage(tr("Uploading..."),10000); + file->close(); + } + else cout <<"Could not open file:"<list(path)); //we track the commands in vectors + stack.push(path); + localDir.mkdir(path); + connect(ftp,SIGNAL(listInfo(QUrlInfo)),this,SLOT(processFolder(QUrlInfo))); + connect(ftp,SIGNAL(commandFinished(int,bool)),this,SLOT(processCommand(int,bool))); + ftpEntryes = new QStringList; //this will contain the file list + lpath=localPath; +} + +//This makes us a QList with all entryes, folders first then files. + +void qOrganizer::processFolder(const QUrlInfo &i) +{ + if(i.isDir()) + { + entryList.push_front(i); + } + else + if(i.isFile()) + entryList.push_back(i); +} + + +static int nrcomfin=0; +//nr of finished command, this counts how many times this function is called +void qOrganizer::processCommand(int com,bool err) +{ + Q_UNUSED(err); + //Variables + nrcomfin++; + QString path; + QTextStream cout(stdout, QIODevice::WriteOnly); + bool containsSubfolders=0; + bool entryExists=0; + QDir localDir(lpath); + //If the command was list() then we start procesing our QList + if(listCommandVector.indexOf(com)!=-1) + { + path = stack.top(); + foreach(QUrlInfo entry,entryList) + { + if((entry.isFile())&&(listedFiles.indexOf(entry)==-1)) + { + QString foldPath = path+"/"+entry.name(); + ftpEntryes->append(foldPath); + listedFiles.append(entry); + //cout <<"File:"<list(foldPath)); + listedFolders.append(entry); + containsSubfolders=1; + entryExists=1; + break; + } + } + if((stack.size()>1)&&(nrcomfin%2!=0)) stack.pop(); + entryList.clear(); + //cout << stack.size() << stack.top() <<" "<list(stack.top())); + if((!containsSubfolders) && (!entryExists)) downloadFiles(); + } + else //If the command was a get + if(getCommandVector.indexOf(com)!=-1) + { + ftpFile=fileQueue.dequeue(); + ftpFile-> close(); + //cout <<"Completed:"<fileName()<<" "<<"Errors:"<deleteLater(); + } + else + if(putCommandVector.indexOf(com)!=-1) + { + QFile *myFile = uploadedFileQueue.dequeue(); + myFile->deleteLater(); + }; +} + +void qOrganizer::downloadFiles() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + //cout <<"Downloading"<<"\n"; + foreach(QString entry,*ftpEntryes) + { + QFile *file = new QFile(lpath+entry); + cout << "get " << entry <<" "<showMessage(tr("Downloading..."),10000); + fileQueue.enqueue(file); + file->open(QIODevice::WriteOnly); + getCommandVector.append(ftp -> get(entry,file)); + } +} + +void qOrganizer::connectToFTP() +{ + ftp = new QFtp(this); + ftp -> connectToHost(C_HOST,C_PORT); + ftp -> login(C_USER,C_PASSWD); + ftp -> cd(C_FTPPATH); +} + +//Two simplyfied aliases + +void qOrganizer::initUpload() +{ + noFolders=false; + putToFTP(); +} + +void qOrganizer::putToFTP() +{ + statusProgress -> show(); + connectToFTP(); + uploadAct->setEnabled(false); + connect(ftp,SIGNAL(done(bool)),this,SLOT(updateStatusP(bool))); + if(C_PATH=="home") + sendFolder(QDir::toNativeSeparators(QDir::homePath()+"/")+".qOrganizer",QDir::toNativeSeparators(QDir::homePath()+"/")); + else + sendFolder(C_PATH+".qOrganizer",C_PATH); +} + +void qOrganizer::getFromFTP() +{ + downloadingFromFTP=1; + statusProgress -> show(); + connectToFTP(); + downloadAct->setEnabled(false); + if(C_AUTOSAVE_TOGGLE) toggleAutoSave(0); + connect(ftp,SIGNAL(done(bool)),this,SLOT(updateStatusG(bool))); + if(C_PATH=="home") + getFolder(QString(".qOrganizer"),QDir::toNativeSeparators(QDir::homePath()+"/")); + else + getFolder(QString(".qOrganizer"),C_PATH); +} + +void qOrganizer::updateStatusG(bool error) +{ + downloadingFromFTP=0; + downloadAct->setEnabled(true); + statusProgress -> hide(); + if(!this->isVisible()) toggleVisibility(); + if(!error) + { + statusBar()->showMessage(tr("Done!"),10000); + QMessageBox::warning(NULL,tr("Done"),tr("Download finished!")); + loadAll(); + ftp->deleteLater(); + } + else + { + QMessageBox::warning(NULL, "Error",tr("Couldn't download files:\n")+ftp->errorString()); + ftp->deleteLater(); + } + disconnect(ftp, SIGNAL(done(bool)),this,SLOT(updateStatusG(bool))); + if(changedAutoSave) toggleAutoSave(1); + stack.clear(); + delete ftpEntryes; + entryList.clear(); + listedFiles.clear(); + listedFolders.clear(); + listCommandVector.clear(); + getCommandVector.clear(); + nrcomfin=0; +} + +void qOrganizer::updateStatusP(bool error) +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + statusProgress -> hide(); + cout << " Upload finished:"<errorString()<<"\n"; + uploadAct->setEnabled(true); + if(!this->isVisible()) toggleVisibility(); + if(!error) + { + statusBar()->showMessage(tr("Done!"),10000); + QMessageBox::warning(NULL,tr("Done"),tr("Upload finished!")); + ftp->deleteLater(); + noFolders=false; + } + else + { + if((ftp->errorString().indexOf(".qOrganizer")!=-1)&&(ftp->errorString().indexOf("exists")!=-1)) + { + noFolders=true; + ftp->deleteLater(); + disconnect(ftp, SIGNAL(done(bool)),this,SLOT(updateStatusP(bool))); + cout <<"Error encountered:Folder exists, entering noFolder mode and reuploading\n"; + //Don't know why we need to call it twice, but it doesn't work if it is called only once. + //Maybe one gets killed by deleteLater + putToFTP(); + putToFTP(); + } + else + { + QMessageBox::warning(NULL,tr("Error"),QString(tr("Couldn't upload files:\n")+ftp->errorString())); + ftp->deleteLater(); + } + } + disconnect(ftp, SIGNAL(done(bool)),this,SLOT(updateStatusP(bool))); +} + +//if ind is true turn it on else turn it off +void qOrganizer::toggleAutoSave(bool ind) +{ + if(!ind) + { + disconnect(tableWid,SIGNAL(focusLost()),this,SLOT(saveSchedule())); + disconnect(textField,SIGNAL(focusLost()),this,SLOT(saveJurnal())); + disconnect(list,SIGNAL(focusLost()),this,SLOT(saveToDoList())); + disconnect(table,SIGNAL(focusLost()),this,SLOT(saveTimeTable())); + disconnect(markTable,SIGNAL(focusLost()),this,SLOT(saveMarksTable())); + disconnect(absenceTable,SIGNAL(focusLost()),this,SLOT(saveAbsenceTable())); + changedAutoSave=1; + } + else + { + connect(tableWid,SIGNAL(focusLost()),this,SLOT(saveSchedule())); + connect(textField,SIGNAL(focusLost()),this,SLOT(saveJurnal())); + connect(list,SIGNAL(focusLost()),this,SLOT(saveToDoList())); + connect(table,SIGNAL(focusLost()),this,SLOT(saveTimeTable())); + connect(markTable,SIGNAL(focusLost()),this,SLOT(saveMarksTable())); + connect(absenceTable,SIGNAL(focusLost()),this,SLOT(saveAbsenceTable())); + changedAutoSave=0; + } +}; + + + + +//Needed by custom delegate to be able to delete from the absenceTable, all because there is no +//way to create an empty QDateTimeEdit +//We previously called setObjectName for these tables +void CQTableWidget::keyPressEvent (QKeyEvent * event) +{ + if(this->objectName()==QString("absenceTable")) //The table with the absences + { + if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) + { + this->currentItem()->setText(" "); + return; + } + } + else + if(this->objectName()==QString("list")) //To-do list table + { + if((this->currentColumn()==2)||(this->currentColumn()==0)) + { + if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) + { + this->currentItem()->setText(" "); + return; + } + } + } + else + if(this->objectName()==QString("tableWid")) //Schedule table + { + if(this->currentColumn()!=0) + { + if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) + { + this->currentItem()->setText(" "); + return; + } + } + } + return QTableWidget::keyPressEvent(event); +} + +void qOrganizer::saveAll() +{ + if(C_STORINGMODE==0) + { + saveToDoList(); + saveTimeTable(); + saveSchedule(); + saveJurnal(); + saveMarksTable(); + saveAbsenceTable(); + saveMarkDates(); + } + else + { + saveScheduleDB(); + saveJurnalDB(); + saveToDoListDB(); + saveTimeTableDB(); + saveMarksTableDB(); + saveAbsenceTableDB(); + saveMarkDatesDB(); + } +} + +void qOrganizer::loadAll() +{ + //if(C_AUTOSAVE_TOGGLE) toggleAutoSave(0); + if(C_STORINGMODE==0) + { + loadTimeTable(); + loadSchedule(); + loadJurnal(); + loadToDoList(); + loadMarksTable(); + loadAbsenceTable(); + loadMarkDates(); + } + else + { + loadScheduleDB(); + loadJurnalDB(); + loadTimeTableDB(); + loadToDoListDB(); + loadMarksTableDB(); + loadAbsenceTableDB(); + loadMarkDatesDB(); + } + //if(changedAutoSave) toggleAutoSave(1); +} + +void qOrganizer::exitApp() +{ + if(C_AUTOSAVE_TOGGLE) + { + saveAll(); + } + writeSettings(); + saveColumnWidths(); + if(db.open()) db.close(); + qApp->quit(); +} + +void qOrganizer::playSound() +{ + if(QSound::isAvailable()) + { + QFile soundFile(":images/sound.wav"); + if(C_PATH=="home") + { + soundFile.copy(QDir::homePath()+QDir::separator()+".qOrganizer"+QDir::separator()+"sound.wav"); + QSound::play(QDir::homePath()+QDir::separator()+".qOrganizer"+QDir::separator()+"sound.wav"); + } + else + { + soundFile.copy(C_PATH+".qOrganizer"+QDir::separator()+"sound.wav"); + QSound::play(C_PATH+".qOrganizer"+QDir::separator()+"sound.wav"); + } + } + else + {//Linux uses NAS, which kind of sucks with qt, so we have to do this primitively + #ifdef Q_OS_LINUX + QFile soundFile(":images/sound.wav"); + if(!soundFile.copy("/tmp/qremindersound.wav")) + cout << "Could not copy soundfile to /tmp\n"; + system("cat /tmp/qremindersound.wav >> /dev/dsp"); + #endif + } +} + +//------------------------------------------------------DATABASE SLOTS-------------------------------------------------------------- + + +void qOrganizer::setDBDir() +{ + if(C_PATH=="home") + dbPath=QDir::homePath()+QDir::separator()+".qOrganizer"; + else + dbPath=C_PATH+QDir::separator()+".qOrganizer"+QDir::separator(); + QDir::setCurrent(dbPath); +} + +void qOrganizer::connectToDB() +{ + setDBDir(); + QTextStream cout(stdout, QIODevice::WriteOnly); + if(C_STORINGMODE==1) + { + db = QSqlDatabase::addDatabase("QSQLITE"); + db.setDatabaseName("qorganizer.db"); + } + else + if(C_STORINGMODE==2) + { + db = QSqlDatabase::addDatabase("QMYSQL"); + db.setHostName(C_MYSQL_HOST); + db.setPort(C_MYSQL_PORT); + db.setDatabaseName(C_MYSQL_DB); + db.setUserName(C_MYSQL_USER); + db.setPassword(C_MYSQL_PASSWD); + } + + if ((!db.open())&&(C_STORINGMODE!=0)) + { + QMessageBox::critical(0,tr("Error"), + tr("Could not connect to database!") + ,QMessageBox::Ok); + C_STORINGMODE=0; //Revert to textfiles + } + else cout << "Connected to database\n"; +} + +bool qOrganizer::tableExistsDB(QString &tablename) +{ + bool result; + QStringList tableList = db.tables(QSql::Tables); + if(tableList.indexOf(tablename)!=-1) result=true; else result=false; + return result; +} + +//GOLDEN RULE: ALWAYS PREPARE YOUR SQL STATEMENTS BEFORE INSERT! + +void qOrganizer::loadScheduleDB() +{ + bool didntExist=0; + if(!db.isOpen()) connectToDB(); + emptyTable(); + QTextStream cout(stdout, QIODevice::WriteOnly); + QDate date = calendar->selectedDate(); + QString tableName ="schedule_"+date.toString("MM_dd_yyyy"); + cout<<"Loading schedule from database:"<=tableWid->rowCount()) insertRowToEnd();; + for(int j=0;jcolumnCount();j++) + { + QString text = query.value(j).toString(); + item= new QTableWidgetItem(QTableWidgetItem::Type); + item->setText(text); + if(tableWid->item(i,j)!=0) delete tableWid->takeItem(i,j); + tableWid->setItem(i,j,item); + } + } + tableWid->setRowCount(i+1); + //If the table didn't exist then set the preferred nr of rows + if(didntExist) + { + emptyTable(); + saveScheduleDB(); + } + +} + +void qOrganizer::saveScheduleDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + if(!db.isOpen()) connectToDB(); + //Get selected date + QDate date = calendar->selectedDate(); + QString tableName ="schedule_"+date.toString("MM_dd_yyyy"); + cout << "Saving schedule to database:"<currentRow(); + int y=tableWid->currentColumn(); + + for(int i=0;irowCount();i++) + { + textList.clear(); + for(int j=0;jcolumnCount();j++) + { + tableWid->setCurrentCell(i,j); + QTableWidgetItem *item=tableWid->currentItem(); + if(item!=0) + textList.append(item->text()); + else textList.append(""); + } + QString command = "INSERT INTO `"+tableName+"` VALUES"+ + "(:myevent,:myfrom,:myuntil,:myreminder)"; + query.prepare(command); + query.bindValue(":myevent",textList[0]); + query.bindValue(":myfrom",textList[1]); + query.bindValue(":myuntil",textList[2]); + query.bindValue(":myreminder",textList[3]); + query.exec(); + } + tableWid->setCurrentCell(x,y); + } +} + +void qOrganizer::loadJurnalDB() //I know it's Journal not Jurnal, but wth +{ + if(!db.isOpen()) connectToDB(); + QTextStream cout(stdout, QIODevice::WriteOnly); + QDate date = calendar->selectedDate(); + QString tableName ="jurnal_"+date.toString("MM_dd_yyyy"); + cout << "Loading jurnal from database:"<setHtml(text); +} + +void qOrganizer::saveJurnalDB() +{ + QString text; + if(!db.isOpen()) connectToDB(); + QTextStream cout(stdout, QIODevice::WriteOnly); + QDate date = calendar->selectedDate(); + QString tableName ="jurnal_"+date.toString("MM_dd_yyyy"); + cout << "Saving jurnal to database:"<toHtml(); + query.prepare("INSERT INTO `"+tableName+"` VALUES"+" (:mytext)"); + query.bindValue(":mytext",text); + query.exec(); +} + +void qOrganizer::loadToDoListDB() +{ + list->setSortingEnabled(false); + if(!db.isOpen()) connectToDB(); + QTextStream cout(stdout, QIODevice::WriteOnly); + QString tableName ="todolist"; + cout << "Loading to-do list from database\n"; + list->clearContents(); + QSqlQuery query(db); + bool didntexist=0; + if(!tableExistsDB(tableName)) didntexist=1; + //Create table if it does not exist. + query.exec("CREATE TABLE `"+tableName+"` (`_start_` TEXT,`_task_` TEXT,`_deadline_` TEXT,`_priority_` TEXT,`_completed_` TEXT)"); + //Select all from the table + query.exec("SELECT _start_,_task_,_deadline_,_priority_,_completed_ FROM `"+tableName+"`"); + //Row counter, it will get incremented + int i=-1; + while(query.next()) + { + i++; + if(i>=list->rowCount()) newTask(); + for(int j=0;jcolumnCount();j++) + { + QString text = query.value(j).toString(); + item= new QTableWidgetItem(QTableWidgetItem::Type); + item->setText(text); + if(list->item(i,j)!=0) delete list->takeItem(i,j); + list->setItem(i,j,item); + } + } + if(didntexist) + { + list->setRowCount(10); + }else list->setRowCount(i+1); + list->setSortingEnabled(true); +} + +void qOrganizer::saveToDoListDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + if(!db.isOpen()) connectToDB(); + QString tableName ="todolist"; + cout << "Saving to-do list to database"<<"\n"; + //Variables + QSqlQuery query(db); + //Create table if it does not exist. + query.exec("CREATE TABLE `"+tableName+"` (`_start_` TEXT,`_task_` TEXT,`_deadline_` TEXT,`_priority_` TEXT,`_completed_` TEXT)"); + query.exec("DELETE FROM `"+tableName+"`"); + int x=list->currentRow(); + int y=list->currentColumn(); + + for(int i=0;irowCount();i++) + { + textList.clear(); + for(int j=0;jcolumnCount();j++) + { + list->setCurrentCell(i,j); + QTableWidgetItem *item=list->currentItem(); + if(item!=0) + textList.append(item->text()); + else textList.append(""); + } + QString command = "INSERT INTO `"+tableName+"` VALUES"+ + "(:mystart,:mytask,:mydeadline,:mypriority,:mycompleted)"; + query.prepare(command); + query.bindValue(":mystart",textList[0]); + query.bindValue(":mytask",textList[1]); + query.bindValue(":mymydeadline",textList[2]); + query.bindValue(":mypriority",textList[3]); + query.bindValue(":mycompleted",textList[4]); + query.exec(); + } + list->setCurrentCell(x,y); +} + +void qOrganizer::setTTLabelsDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + if(!db.isOpen()) connectToDB(); + bool didntExists=0; + QString tableName="timetable_labels"; + QSqlQuery query(db); + QStringList timeTableLabels; + timeTableLabels.clear(); + //create if it doesn't exist + if(!tableExistsDB(tableName)) didntExists=1; + + query.exec("CREATE TABLE `"+tableName+"` (`_label_` TEXT)"); + if(didntExists) + { + QStringList localLabelList; + localLabelList <<"From"<<"Until"<<"Monday"<<"Tuesday"<<"Wednesday"<<"Thursday"<<"Friday"; + foreach(QString text,localLabelList) + query.exec("INSERT INTO "+tableName+" VALUES"+"('"+text+"')"); + } + + query.exec("SELECT _label_ FROM `"+tableName+"`"); + while(query.next()) + timeTableLabels << query.value(0).toString(); + + englishList = timeTableLabels; //the original + //translate them if we can. + for(int i=0;isetColumnCount(timeTableLabels.size()); + table->setHorizontalHeaderLabels(timeTableLabels); + TTlabels = timeTableLabels; +} + +void qOrganizer::loadTimeTableDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + cout << "Loading timetable from database \n"; + table->clearContents(); + setTTLabelsDB(); + if(!db.isOpen()) connectToDB(); + QString tableName="timetable"; + if(C_TIMETABLE_INDEX==0) tableName="timetable"; else tableName="timetable_even"; + QSqlQuery query(db); + bool didntexist=0; + if(!tableExistsDB(tableName)) didntexist=1; + //Create table if it does not exist. + query.exec("CREATE TABLE `"+tableName+ + "` (`_0_` TEXT,`_1_` TEXT,`_2_` TEXT,`_3_` TEXT"+ + ",`_4_` TEXT,`_5_` TEXT,`_6_` TEXT)"); + + //We get the table column names. + QSqlRecord record = db.record(tableName); + QString columns; + for(int i=0;i=table->rowCount()) newRow(); + for(int j=0;jcolumnCount();j++) + { + QString text = query.value(j).toString(); + item= new QTableWidgetItem(QTableWidgetItem::Type); + item->setText(text); + if(table->item(i,j)!=0) delete table->takeItem(i,j); + table->setItem(i,j,item); + } + } + if(didntexist) + { + table->setRowCount(9); + } else table->setRowCount(i+1); +} + +void qOrganizer::saveTTLabelsDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + if(!db.isOpen()) connectToDB(); + QSqlQuery query(db); + + QString tableName = "timetable_labels"; + //No we re create it with the new structure; + query.exec("CREATE TABLE `"+tableName+"` (`_label_` TEXT)"); + query.exec("DELETE FROM `"+tableName+"`"); + + for(int i=0;icolumnCount();i++) + { + columns+="`_"+QString::number(i)+"_`"+" TEXT"; + if(i!=table->columnCount()-1) columns=columns+","; + } + columns+=")"; + + //No we re create it with the new structure; + query.exec("CREATE TABLE `"+tableName+"` "+columns); + + int x=table->currentRow(); + int y=table->currentColumn(); + + for(int i=0;irowCount();i++) + { + textList.clear(); + for(int j=0;jcolumnCount();j++) + { + table->setCurrentCell(i,j); + QTableWidgetItem *item=table->currentItem(); + if(item!=0) + textList.append(item->text()); + else textList.append(""); + } + + QStringList valueList; + valueList.clear(); + QString values=""; + QString value=""; + for(int i=0;icolumnCount();i++) + { + value=":my"+QString::number(i); + valueList.append(value); + values += value; + if(i!=table->columnCount()-1) values += ","; + } + + query.prepare("INSERT INTO `"+tableName+"` VALUES("+values+")"); + for(int i=0;isetCurrentCell(x,y); +} + + + +void qOrganizer::setSubjectLabelsDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + if(!db.isOpen()) connectToDB(); + bool didntExists=0; + QString tableName="subjects"; + QSqlQuery query(db); + QStringList subjects; + subjects.clear(); + //create if it doesn't exist + if(!tableExistsDB(tableName)) didntExists=1; + query.exec("CREATE TABLE `"+tableName+"` (`_subject_` TEXT)"); + if(didntExists) + for(int i=0;isetRowCount(subjects.size()); + absenceTable->setRowCount(subjects.size()); + markTable->setVerticalHeaderLabels(subjects); + subjectList = subjects; +} + +void qOrganizer::loadMarksTableDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + cout << "Loading marks from database \n"; + markTable->clearContents(); + setSubjectLabelsDB(); + if(!db.isOpen()) connectToDB(); + QString tableName="marks"; + QSqlQuery query(db); + bool didntexist=0; + if(!tableExistsDB(tableName)) didntexist=1; + //Create table if it does not exist. + query.exec("CREATE TABLE `"+tableName+ + "` (`_0_` TEXT,`_1_` TEXT,`_2_` TEXT,`_3_` TEXT"+ + ",`_4_` TEXT,`_5_` TEXT)"); + + //We get the table column names. + QSqlRecord record = db.record(tableName); + QString columns; + for(int i=0;isetColumnCount(record.count()); + query.exec("SELECT "+columns+" FROM `"+tableName+"`"); + //Load data into the table + int i=-1; + while(query.next()) + { + i++; + for(int j=0;jcolumnCount();j++) + { + QString text = query.value(j).toString(); + item= new QTableWidgetItem(QTableWidgetItem::Type); + item->setText(text); + if(markTable->item(i,j)!=0) delete markTable->takeItem(i,j); + markTable->setItem(i,j,item); + } + } + for(int a=0;acolumnCount();a++) markTable->setColumnWidth(a,50); + +} + +void qOrganizer::saveSubjectLabelsDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + if(!db.isOpen()) connectToDB(); + QString tableName="subjects"; + QSqlQuery query(db); + //create if it doesn't exist + query.exec("CREATE TABLE `"+tableName+"` (`_subject_` TEXT)"); + query.exec("DELETE FROM `"+tableName+"`"); + foreach(QString text,subjectList) + { + query.prepare("INSERT INTO "+tableName+" VALUES (:subject)"); + query.bindValue(":subject",text); + query.exec(); + } +} + +void qOrganizer::saveMarksTableDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + cout << "Saving marks to database \n"; + saveSubjectLabelsDB(); + QString tableName="marks"; + if(!db.isOpen()) connectToDB(); + QSqlQuery query(db); + //Delete it's contents + query.exec("DROP TABLE `"+tableName+"`"); + QString columns="("; + for(int i=0;icolumnCount();i++) + { + columns+="`_"+QString::number(i)+"_`"+" TEXT"; + if(i!=markTable->columnCount()-1) columns=columns+","; + } + columns+=")"; + //No we re create it with the new structure; + query.exec("CREATE TABLE `"+tableName+"` "+columns); + int x=markTable->currentRow(); + int y=markTable->currentColumn(); + for(int i=0;irowCount();i++) + { + textList.clear(); + for(int j=0;jcolumnCount();j++) + { + markTable->setCurrentCell(i,j); + QTableWidgetItem *item=markTable->currentItem(); + if(item!=0) + textList.append(item->text()); + else textList.append(""); + } + QStringList valueList; + valueList.clear(); + QString values=""; + QString value=""; + for(int i=0;icolumnCount();i++) + { + value=":my"+QString::number(i); + valueList.append(value); + values += value; + if(i!=markTable->columnCount()-1) values += ","; + } + query.prepare("INSERT INTO `"+tableName+"` VALUES("+values+")"); + for(int i=0;isetCurrentCell(x,y); +} + +void qOrganizer::loadAbsenceTableDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + cout << "Loading absences from database \n"; + absenceTable->clearContents(); + if(!db.isOpen()) connectToDB(); + QString tableName="absences"; + QSqlQuery query(db); + bool didntexist=0; + if(!tableExistsDB(tableName)) didntexist=1; + //Create table if it does not exist. + query.exec("CREATE TABLE `"+tableName+ + "` (`_0_` TEXT,`_1_` TEXT,`_2_` TEXT,`_3_` TEXT"+ + ",`_4_` TEXT,`_5_` TEXT)"); + + //We get the table column names. + QSqlRecord record = db.record(tableName); + QString columns; + for(int i=0;isetColumnCount(record.count()); + query.exec("SELECT "+columns+" FROM `"+tableName+"`"); + //Load data into the table + int i=-1; + while(query.next()) + { + i++; + for(int j=0;jcolumnCount();j++) + { + QString text = query.value(j).toString(); + item= new QTableWidgetItem(QTableWidgetItem::Type); + item->setText(text); + if(absenceTable->item(i,j)!=0) delete absenceTable->takeItem(i,j); + absenceTable->setItem(i,j,item); + } + } + for(int a=0;acolumnCount();a++) absenceTable->setColumnWidth(a,80); + +} + +void qOrganizer::saveAbsenceTableDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + cout << "Saving absences to database \n"; + saveSubjectLabelsDB(); //save them again + QString tableName="absences"; + if(!db.isOpen()) connectToDB(); + QSqlQuery query(db); + //Delete it's contents + query.exec("DROP TABLE `"+tableName+"`"); + QString columns="("; + for(int i=0;icolumnCount();i++) + { + columns+="`_"+QString::number(i)+"_`"+" TEXT"; + if(i!=absenceTable->columnCount()-1) columns=columns+","; + } + columns+=")"; + //No we re create it with the new structure; + query.exec("CREATE TABLE `"+tableName+"` "+columns); + int x=absenceTable->currentRow(); + int y=absenceTable->currentColumn(); + for(int i=0;irowCount();i++) + { + textList.clear(); + for(int j=0;jcolumnCount();j++) + { + absenceTable->setCurrentCell(i,j); + QTableWidgetItem *item=absenceTable->currentItem(); + if(item!=0) + textList.append(item->text()); + else textList.append(""); + } + QStringList valueList; + valueList.clear(); + QString values=""; + QString value=""; + for(int i=0;icolumnCount();i++) + { + value=":my"+QString::number(i); + valueList.append(value); + values += value; + if(i!=absenceTable->columnCount()-1) values += ","; + } + query.prepare("INSERT INTO `"+tableName+"` VALUES("+values+")"); + for(int i=0;isetCurrentCell(x,y); +} + +//Saving between txt and DB +void qOrganizer::saveAlltoTXT() +{ + int temp=C_STORINGMODE; + /*Quick and dirty hack to keep me from + getting those ifs out of the loading functions. + I know, I know, lazyness is bliss :D */ + C_STORINGMODE=0; + saveToDoList(); + saveTimeTable(); + saveSchedule(); + saveJurnal(); + saveMarksTable(); + saveAbsenceTable(); + saveMarkDates(); + C_STORINGMODE=temp; +} + +void qOrganizer::saveAlltoSQLiteDB() +{ + bool changedAS=0; + if(C_AUTOSAVE_TOGGLE) + { + toggleAutoSave(0); + changedAS=1; + C_AUTOSAVE_TOGGLE=0; + } + int temp=C_STORINGMODE; + if((!db.isOpen())||(C_STORINGMODE!=1)) + { + if(db.isOpen()) db.close(); + C_STORINGMODE=1; + connectToDB(); + } + if(C_STORINGMODE==1) + { + saveToDoListDB(); + saveTimeTableDB(); + saveScheduleDB(); + saveJurnalDB(); + saveMarksTableDB(); + saveAbsenceTableDB(); + saveMarkDatesDB(); + } + C_STORINGMODE=temp; + if(changedAS) + { + toggleAutoSave(1); + C_AUTOSAVE_TOGGLE=1; + } +} + +void qOrganizer::saveAlltoMySQLDB() +{ + bool changedAS=0; + if(C_AUTOSAVE_TOGGLE) + { + toggleAutoSave(0); + changedAS=1; + C_AUTOSAVE_TOGGLE=0; + } + int temp=C_STORINGMODE; + if((!db.isOpen())||(C_STORINGMODE!=2)) + { + if(db.isOpen()) db.close(); + C_STORINGMODE=2; + connectToDB(); + } + if(C_STORINGMODE==2) + { + saveToDoListDB(); + saveTimeTableDB(); + saveScheduleDB(); + saveJurnalDB(); + saveMarksTableDB(); + saveAbsenceTableDB(); + saveMarkDatesDB(); + } + C_STORINGMODE=temp; + if(changedAS) + { + toggleAutoSave(1); + C_AUTOSAVE_TOGGLE=1; + } +} + + +//-------------------------------------------------------SEARCH--------------------------------------------------------------- +//This is responsible for searching through events + +bool caseInsensitiveLessThan(const QString &s1, const QString &s2) +{ + return s1.toLower() < s2.toLower(); +} + +void qOrganizer::search() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + QString searchString = searchField->text(); + QList searchResultList; + QString tempText; + dateList.clear(); + if(C_STORINGMODE==0) + { + setCalDir(); + QDir dir = QDir::current(); + QStringList entries = dir.entryList(QDir::Files|QDir::NoDotAndDotDot,QDir::Name); + foreach (QString entry, entries) + { + QFile file(entry); + if(file.open(QFile::ReadOnly)) + { + QTextStream in(&file); + in.setCodec("UTF-8"); + QString text=in.readAll(); + if(text.indexOf(searchString,0,Qt::CaseInsensitive)!=-1) + { + cout <<"Found:"<< entry <<"\n"; + searchResultList.append(entry); + } + file.close(); + } + } + } + else + { + if(!db.isOpen()) connectToDB(); + QSqlQuery query(db); + QStringList tableList = db.tables(QSql::Tables); + QStringList scheduleList = tableList.filter("schedule"); + QStringList jurnalList = tableList.filter("jurnal"); + QStringList entryList = scheduleList + jurnalList; + qSort(entryList.begin(), entryList.end(), caseInsensitiveLessThan); + foreach(QString entry,entryList) + { + if(entry.indexOf("schedule")!=-1) + { + tempText=""; + query.exec("SELECT _event_,_from_,_until_,_reminder_ FROM `"+entry+"`"); + while(query.next()) + { + tempText+=query.value(0).toString()+"|"+query.value(1).toString()+"|"+ + query.value(2).toString()+"|"+query.value(3).toString()+"|"+"\n"; + } + if(tempText.indexOf(searchString,0,Qt::CaseInsensitive)!=-1) + { + cout <<"Found:"<< entry <<"\n"; + searchResultList.append(entry); + } + } + else //jurnal + { + query.exec("SELECT _text_ FROM `"+entry+"`"); + while(query.next()) + { + QString text = query.value(0).toString(); + if(text.indexOf(searchString,0,Qt::CaseInsensitive)!=-1) + { + cout << "Found:" << entry<<"\n"; + searchResultList.append(entry); + } + } + } + } + } + foreach(QString entry,searchResultList) + { + entry.remove(QString(".txt"),Qt::CaseSensitive); + entry.remove(QString(".html"),Qt::CaseSensitive); + entry.remove(QString("schedule_"),Qt::CaseSensitive); + entry.remove(QString("jurnal_"),Qt::CaseSensitive); + QDate date = QDate::fromString(entry,"MM_dd_yyyy"); + dateList.append(date); + } +} + +void qOrganizer::searchPrev() +{ + QString searchedString = searchField->text(); + if(searchedString!=oldSearchString) + { + searchCurrentIndex=0; + search(); + } + if(searchCurrentIndex<0) searchCurrentIndex=0; + if(searchCurrentIndex==0) searchCurrentIndex=dateList.count(); + if((dateList.isEmpty())&&(!searchedString.isEmpty())) + { + QMessageBox::warning(NULL, "qOrganizer",tr("No entries found!"), "OK"); + } + else + if((!searchedString.isEmpty())&&(searchedString!="|")) + { + if(searchCurrentIndex>0) + { + searchCurrentIndex--; + calendar->setSelectedDate(dateList[searchCurrentIndex]); + updateDay(); + if(C_STORINGMODE==0) loadJurnal(); else loadJurnalDB(); + if(C_STORINGMODE==0) loadSchedule(); else loadScheduleDB(); + setCalendarColumnWidths(); + } + } + + oldSearchString=searchedString; +} + +void qOrganizer::searchNext() +{ + QString searchedString = searchField->text(); + if(searchedString!=oldSearchString) + { + searchCurrentIndex=-1; + search(); + } + if(searchCurrentIndex>=dateList.count()-1) searchCurrentIndex=-1; + if((dateList.isEmpty())&&(!searchedString.isEmpty())) + { + QMessageBox::warning(NULL, "qOrganizer",tr("No entries found!"), "OK"); + } + else + { + if((!searchedString.isEmpty())&&(searchedString!="|")) + { + if(searchCurrentIndexsetSelectedDate(dateList[searchCurrentIndex]); + updateDay(); + if(C_STORINGMODE==0) loadJurnal(); else loadJurnalDB(); + if(C_STORINGMODE==0) loadSchedule(); else loadScheduleDB(); + setCalendarColumnWidths(); + } + } + } + oldSearchString=searchedString; +} + +//-------------------------------------------REMEMBER COLUMN WIDTHS------------------------------------------------------------ + +void qOrganizer::saveColumnWidths() +{ + cout << "Saving column widths\n"; + //QSettings settings("qOrganizer", "qOrganizer"); + //Schedule table + for(int i=0;icolumnCount();i++) + settings -> setValue("schedule"+QString::number(i),tableWid->columnWidth(i)); + + //To-Do List + for(int i=0;icolumnCount();i++) + settings -> setValue("todo"+QString::number(i),list->columnWidth(i)); + + //TimeTable + for(int i=0;icolumnCount();i++) + settings -> setValue("timetable"+QString::number(i),table->columnWidth(i)); + + //Mark table + for(int i=0;icolumnCount();i++) + settings -> setValue("marktable"+QString::number(i),markTable->columnWidth(i)); + + //Absence table + for(int i=0;icolumnCount();i++) + settings -> setValue("absencetable"+QString::number(i),absenceTable->columnWidth(i)); + +} + +void qOrganizer::setColumnWidths() +{ + cout << "Setting column widths\n"; + //QSettings settings("qOrganizer", "qOrganizer"); + //Schedule table + for(int i=0;icolumnCount();i++) + if(settings -> value("schedule"+QString::number(i)).toInt()!=0) + tableWid->setColumnWidth(i,settings -> value("schedule"+QString::number(i)).toInt()); + + //To-Do List + for(int i=0;icolumnCount();i++) + if(settings -> value("todo"+QString::number(i)).toInt()!=0) + list->setColumnWidth(i,settings -> value("todo"+QString::number(i)).toInt()); + + //TimeTable + for(int i=0;icolumnCount();i++) + if(settings -> value("timetable"+QString::number(i)).toInt()!=0) + table->setColumnWidth(i,settings -> value("timetable"+QString::number(i)).toInt()); + + //Mark table + for(int i=0;icolumnCount();i++) + if(settings -> value("marktable"+QString::number(i)).toInt()!=0) + markTable->setColumnWidth(i,settings -> value("marktable"+QString::number(i)).toInt()); + + //Absence table + for(int i=0;icolumnCount();i++) + if(settings -> value("absencetable"+QString::number(i)).toInt()!=0) + absenceTable->setColumnWidth(i,settings -> value("absencetable"+QString::number(i)).toInt()); +} + +void qOrganizer::saveCalendarColumnWidths() +{ + cout << "Saving calendar column widths\n"; + //QSettings settings("qOrganizer", "qOrganizer"); + //Schedule table + for(int i=0;icolumnCount();i++) + settings -> setValue("schedule"+QString::number(i),tableWid->columnWidth(i)); +} + +void qOrganizer::setCalendarColumnWidths() +{ + cout << "Setting calendar column widths\n"; + //QSettings settings("qOrganizer", "qOrganizer"); + //Schedule table + for(int i=0;icolumnCount();i++) + if(settings -> value("schedule"+QString::number(i)).toInt()!=0) + tableWid->setColumnWidth(i,settings -> value("schedule"+QString::number(i)).toInt()); +} + +//-----------------------------------------ODD or EVEN TIMETABLE----------------------------------------------- + +void qOrganizer::changeTTIndex(int ttindex) +{ + if(C_AUTOSAVE_TOGGLE) + if(C_STORINGMODE==0) saveTimeTable(); else saveTimeTableDB(); + calledFromTTCombo=1; + C_TIMETABLE_INDEX=ttindex; + table->clearContents(); + if(C_STORINGMODE==0) loadTimeTable(); else loadTimeTableDB(); + calledFromTTCombo=0; +} + +//-------------------------------------DATE STORING FOR BOOKLET ---------------------------------------------------- + +inline bool operator<(const CoordinatePair &p1, const CoordinatePair &p2) +{ + if((p1.x!=p2.x)&&(p1.y!=p2.y)) + { + return p1.x < p2.x; + } + else if(p1.x==p2.x) return p1.y < p2.y; + else if(p1.y==p2.y) return p1.x < p2.x; + return 0; +} + +void qOrganizer::loadMarkDates() +{ + if(C_STORINGMODE!=0) loadMarkDatesDB(); else + { + cout << "Loading mark dates\n"; + setBDir(); + QFile markDateFile("markdates.txt"); + map.clear(); //clear it + QTextStream cout(stdout, QIODevice::WriteOnly); + //cout << "Entered loadMarkDate()\n"; + if (markDateFile.open(QFile::ReadOnly)) + { + //cout << "File opened\n"; + QTextStream in(&markDateFile); + in.setCodec("UTF-8"); + int i=-1; + while(!in.atEnd()) + { + QString line=in.readLine(); + i++; + QStringList slist = line.split(" ", QString::KeepEmptyParts); + bool ok; + //cout << slist[0]<<" "< setDate(returnedDate); +} + +void qOrganizer::saveDate(QDate date) +{ + int a=markTable->currentRow(); + int b=markTable->currentColumn(); + CoordinatePair pair(a,b); + map.remove(pair); + map.insert(pair,date); + //saveMarkDates(); to CPU hungry specially with database +} + +void qOrganizer::saveMarkDates() +{ + if(C_STORINGMODE!=0) saveMarkDatesDB(); else + { + setBDir(); + QFile markDatesFile("markdates.txt"); + cout <<"Saving mark dates to file\n"; + + if (markDatesFile.open(QFile::WriteOnly)) + { + QTextStream out(&markDatesFile); + out.setCodec("UTF-8"); + QMapIterator i(map); + while (i.hasNext()) + { + i.next(); + out << i.key().x <<" "<< i.key().y <<" "<< i.value().toString("d/M/yyyy")<<"\n"; + } + markDatesFile.close(); + } + else + { + QMessageBox::warning(NULL, "qOrganizer", "Unable to write mark dates into file.", "OK"); + } + } +} + +void qOrganizer::saveMarkDatesDB() +{ + QTextStream cout(stdout, QIODevice::WriteOnly); + cout << "Saving mark dates to database \n"; + QString tableName="markdates"; + if(!db.isOpen()) connectToDB(); + QSqlQuery query(db); + query.exec("CREATE TABLE `"+tableName+"` (`_x_` TEXT,`_y_` TEXT,`_date_` TEXT)"); + query.exec("DELETE FROM `"+tableName+"`"); + QMapIterator i(map); + while (i.hasNext()) + { + i.next(); + //out << i.key().x <<" "<< i.key().y <<" "<< i.value().toString("d/M/yyyy")<<"\n"; + query.exec("INSERT INTO `"+tableName+"` VALUES ('"+QString::number(i.key().x)+"','"+QString::number(i.key().y)+"','"+i.value().toString("d/M/yyyy")+"')"); + //I wont prepare it now since the values have a strict format and the user can't modify it to cause problems + } +} + +qOrganizer::~qOrganizer() +{ +} diff --git a/plugins/qOrganizer_plugin/qorganizer.h b/plugins/qOrganizer_plugin/qorganizer.h new file mode 100644 index 000000000..f14f236cd --- /dev/null +++ b/plugins/qOrganizer_plugin/qorganizer.h @@ -0,0 +1,520 @@ +/*************************************************************************** + * Copyright (C) 2007 by Balázs Béla * + * balazsbela@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +#ifndef QORGANIZER_H +#define QORGANIZER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "settings.h" +#include "delegates.h" + +class QApplication; + +//Custom QTableWidget +/* + This is a subclass of QTableWidget so we can emit a signal every time in looses focus. + To this signal are connected the saving functions for the data container widgets +*/ +class CQTableWidget:public QTableWidget +{ + Q_OBJECT + + public: + bool isBeingEdited(); + + public: signals: + void focusLost(); + + protected: + void focusOutEvent(QFocusEvent * event); + //We need to reimplement this to be able to delete absences, + void keyPressEvent (QKeyEvent * event); + +}; + + +//Custom QTableWidget for the same thing. + +class CQTextEdit:public QTextEdit +{ + Q_OBJECT + + signals: + void focusLost(); + + protected: + void focusOutEvent(QFocusEvent * event); + /*void dragEnterEvent(QDragEnterEvent *event); + //void dropEvent(QDropEvent *e);*/ + void insertFromMimeData( const QMimeData *source ); + bool canInsertFromMimeData( const QMimeData *source ) const; + + +}; + +//LineEdit with clear button on the right. + +class LineEdit : public QLineEdit +{ + Q_OBJECT + +public: + LineEdit(qOrganizer *parent = 0); + +protected: + void resizeEvent(QResizeEvent *); + +private slots: + void updateCloseButton(const QString &text); + void clearAndSetDateBack(); +private: + QToolButton *clearButton; + qOrganizer *Parent; +}; + + +//coordinate class for storing dates in a QMap + +class CoordinatePair +{ + public: + CoordinatePair(int a, int b) + { + x=a; + y=b; + } + + int x; + int y; + +}; + +//about Dialog +class aboutDialog : public QDialog +{ + Q_OBJECT + public : + aboutDialog(); + ~aboutDialog(); + public slots: + void close(); + private: + QTabWidget *tabWidget; + QWidget *textWidget; + QWidget *thanksWidget; + QLabel *aboutLabel; + QLabel *thanksToLabel; + QLayout *thanksLayout; + QHBoxLayout *textLayout; + QVBoxLayout *layout; + QHBoxLayout *okLayout; + QPushButton *okButton; +}; + + +//Our class + + +class qOrganizer:public QMainWindow +{ + Q_OBJECT + +public: + qOrganizer(); + ~qOrganizer(); + void createActions(); + void createMenus(); + void createToolBars(); + void createStatusBar(); + void addItems(); + void addCalendarPage(); + void addToDoPage(); + void addCalendarPageWidgets(); + void addTimeTable(); + void addBookletPage(); + void connectCallendarPageWidgets(); + void layoutCalendarPageWidgets(); + void closeEvent(QCloseEvent *e); + void emptyTable(); + void setCalDir(); + void setTDDir(); + void setTTDir(); + void setBDir(); + void setConfigDir(); + void setSTray(); + void hideEvent(QHideEvent * event); + void printCalendar(); + void printToDoList(); + void printTimeTable(); + void printBooklet(); + void splitMyString(QString s); + void writeDefaultConfigFile(); + void writeSettings(); + void readSettings(); + double calculateRowAverage(int row); + void toggleAutoSave(bool ind); + void playSound(); + //DATABASE STUFF: + void connectToDB(); + void setDBDir(); + bool tableExistsDB(QString &tablename); + + + QLabel *noteLabel; + QString selDate; + QComboBox *comboSize; + QLabel *day; + QHBoxLayout *buttonLayout; + QPushButton *deleteButton; + QPushButton *newButton; + QTextEdit *textField; + QHBoxLayout *mainLayout; + QVBoxLayout *textLayout; + CQTableWidget *tableWid; + QStackedWidget *mainWid; + QMenu *fileMenu; + QMenu *viewMenu; + QMenu *settingsMenu; + QMenu *helpMenu; + QMenu *ftpMenu; + QMenu *saveToMenu; + QToolBar *fileToolBar; + QToolBar *editToolBar; + QAction *calAct; + QAction *bookletAct; + QAction *toDoAct; + QAction *saveAct; + QAction *timeTableAct; + QAction *exitAct; + QAction *aboutAct; + QAction *aboutQtAct; + QAction *printAct; + QAction *uploadAct; + QAction *downloadAct; + QAction *settingsAct; + QAction *saveToDBAct; + QAction *saveToTXTAct; + QAction *saveToMySQLDBAct; + QWidget *CallWid; + QVBoxLayout *vl; + QCalendarWidget *calendar; + QWidget *CalendarPage; + QFontComboBox *fontBox; + QVBoxLayout *ToDoVl; + QWidget *ToDoPage; + QStringList englishList; + QStringList universalTTlabels; + QWidget *timeTablePage; + CQTableWidget *list; + QTextCursor cursor; + QFont font; + QPushButton *B; + QPushButton *I; + QPushButton *U; + QTableWidgetItem* item; + QDir *dataDir; + + QPushButton *newTaskButton; + QPushButton *deleteTaskButton; + QVBoxLayout *mainHl; + QHBoxLayout *buttonVl; + + CQTableWidget *table; + QPushButton *newTTRow; + QPushButton *delTTRow; + QPushButton *newTTCmn; + QPushButton *delTTCmn; + QVBoxLayout *Vl; + QHBoxLayout *Hl; + QHBoxLayout *BHl; + QStringList TDlabels; + QStringList TTlabels; + QStringList Clabels; + QHBoxLayout *ttLayout; + QHBoxLayout *centerLayout; + QLabel *ttLabel; + QComboBox *ttCombo; + + QSystemTrayIcon *tray; + QPrinter *printer; + + QWidget *bookletPage; + CQTableWidget *markTable; + CQTableWidget *absenceTable; + QPushButton *newMarkButton; + QPushButton *deleteMarkButton; + QPushButton *newSubjectButton; + QPushButton *deleteSubjectButton; + QPushButton *newAbsenceButton; + QPushButton *deleteAbsenceButton; + QStringList subjectList; + + QLineEdit *averageField; + QLineEdit *totalAverageField; + QLineEdit *absenceNrField; + QDateEdit *markDateField; + + QTimer *timer; + + std::vector v; + QMenu *contextMenu; + + //CONFIG VARIABLES + QString C_PATH; + QString C_DT_FORMAT; //date time format + unsigned long long int C_TIMEOUT; + unsigned int C_FIRST_DAY_OF_WEEK; + bool C_AUTOSAVE_TOGGLE; + bool C_BALOON_SET; + unsigned int C_NRROWS; + //Ftp settings + bool C_SYNCFTP; + QString C_HOST; + unsigned int C_PORT; + QString C_USER; + QString C_PASSWD; + QString C_FTPPATH; + QString C_LANGUAGETEXT; + bool C_LOAD_ON_CHANGE; + bool C_SYSTRAY; + bool C_SOUND; + bool C_SHOW_SAVE; + unsigned int C_STORINGMODE; + unsigned int C_OLD_STORINGMODE; + //MySQL stuff + QString C_MYSQL_HOST; + unsigned int C_MYSQL_PORT; + QString C_MYSQL_USER; + QString C_MYSQL_PASSWD; + QString C_MYSQL_DB; + unsigned int C_TIMETABLE_INDEX; + bool calledFromTTCombo; + bool C_USE_ODDTT; + bool C_TT_REVERSORDER; + bool C_ROUND_ON_AVERAGE; + //Settings dialog + SettingsDialog *settingsDialog; + //global settings object + QSettings *settings; + QString globalWDirPath; + + QFtp *ftp; + QStringList *ftpEntryes; + QStack stack; + QVector listCommandVector; + QVector getCommandVector; + QVector putCommandVector; + QList entryList; + QList listedFiles; + QList listedFolders; + int listCommand; + QString lpath; + QFile *ftpFile; + QQueue fileQueue; + QQueue uploadedFileQueue; + bool noFolders; + bool changedAutoSave; + + //Delegates: + absenceDelegate absDelegate; + markDelegate marksDelegate; + todoDelegate tdlistDelegate; + scheduleDelegate schDelegate; + timeTableDelegate ttDelegate; + //Status progress bar + QProgressBar *statusProgress; + + QSound *sound; //reminder sound + //Database stuff: + QList textList; + QSqlDatabase db; + QString dbPath; + bool connectionExists; + + //Search stuff + QList dateList; + QLabel *searchLabel; + LineEdit *searchField; + QPushButton *searchPrevButton; + QPushButton *searchNextButton; + QHBoxLayout *searchLayout; + int searchCurrentIndex; + QString oldSearchString; + + bool downloadingFromFTP; + + //Dates in booklet + QMap map; + + //about dialog; + aboutDialog *aboutD; + public slots: + void about(); + void ChangeToCalendar(); + void ChangetoToDoList(); + void ChangeToTimeTable(); + void ChangeToBooklet(); + void insertRowToEnd(); + void deleteRow(); + void updateDay(); + void modifyText(); + void setFont(); + void loadSchedule(); + void saveSchedule(); + void saveJurnal(); + void loadJurnal(); + + void newTask(); + void deleteTask(); + void saveToDoList(); + void loadToDoList(); + + void newRow(); + void newColumn(); + void delColumn(); + void delRow(); + void saveTimeTable(); + void loadTimeTable(); + + void newMark(); + void newSubject(); + void deleteMark(); + void deleteSubject(); + void newAbsence(); + void deleteAbsence(); + void saveMarksTable(); + void saveAbsenceTable(); + void loadMarksTable(); + void loadAbsenceTable(); + + void trayActivated(QSystemTrayIcon::ActivationReason reason); + void toggleVisibility(); + void printPage(); + + void updateAbsenceNr(); + void updateAverage(int nx,int ny,int px,int py); + void updateTotalAverage(); + void setReminders(); + void remind(); + + void readConfigFile(); + void showSettings(); + void saveConfigFile(); + + void initUpload(); + void putToFTP(); + void getFromFTP(); + void connectToFTP(); + void processFolder(const QUrlInfo &i); + void processCommand(int com,bool err); + void getFolder(QString path,QString localPath); + void sendFolder(const QString& path,const QString &dirPath); + void downloadFiles(); + void updateStatusG(bool error); + void updateStatusP(bool error); + + //DATABASE SLOTS: + void saveScheduleDB(); + void loadScheduleDB(); + void loadJurnalDB(); + void saveJurnalDB(); + void loadToDoListDB(); + void saveToDoListDB(); + void loadTimeTableDB(); + void saveTimeTableDB(); + void setTTLabelsDB(); + void saveTTLabelsDB(); + void setSubjectLabelsDB(); + void saveSubjectLabelsDB(); + void loadMarksTableDB(); + void saveMarksTableDB(); + void loadAbsenceTableDB(); + void saveAbsenceTableDB(); + void saveAlltoSQLiteDB(); + void saveAlltoTXT(); + void saveAlltoMySQLDB(); + + void saveAll(); + void loadAll(); + void updateCalendar(); + + //Search: + void search(); + void searchPrev(); + void searchNext(); + //Saving column widths + void saveColumnWidths(); + void setColumnWidths(); + void saveCalendarColumnWidths(); + void setCalendarColumnWidths(); + //Odd or even in timetable + void changeTTIndex(int); + //settings + void getWDirPath(); + + //marks date + void loadMarkDates(); + void loadMarkDatesDB(); + void saveMarkDates(); + void saveMarkDatesDB(); + + void updateDate(int currentX,int currentY,int prevX,int prevY); + void saveDate(QDate date); + void exitApp(); + + +}; + +#endif diff --git a/plugins/qOrganizer_plugin/qorganizerPlugin.cpp b/plugins/qOrganizer_plugin/qorganizerPlugin.cpp new file mode 100644 index 000000000..cb8049468 --- /dev/null +++ b/plugins/qOrganizer_plugin/qorganizerPlugin.cpp @@ -0,0 +1,33 @@ +//#include +//#include +//#include + +#include "qorganizerPlugin.h" +#include "qorganizer.h" + +QString +qorganizerPlugin::pluginDescription() const +{ + QString res; + res = "A qOrganizer plugin" ; + + return res; +} + +QString +qorganizerPlugin::pluginName() const +{ + return "Organizer" ; +} + +QWidget* +qorganizerPlugin::pluginWidget(QWidget * parent ) +{ + qOrganizer* window = new qOrganizer(); + //window->openImage(":/images/example.jpg"); + + return window; +} + + +Q_EXPORT_PLUGIN2(qorganizer_plugin, qorganizerPlugin) diff --git a/plugins/qOrganizer_plugin/qorganizerPlugin.h b/plugins/qOrganizer_plugin/qorganizerPlugin.h new file mode 100644 index 000000000..8d14eb37d --- /dev/null +++ b/plugins/qOrganizer_plugin/qorganizerPlugin.h @@ -0,0 +1,27 @@ +#ifndef _HWA_PLUGIN_H_ +#define _HWA_PLUGIN_H_ + +#include + +#include +#include + +#include + +#include + +class qorganizerPlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/qOrganizer_plugin/settings.cpp b/plugins/qOrganizer_plugin/settings.cpp new file mode 100644 index 000000000..7841831d8 --- /dev/null +++ b/plugins/qOrganizer_plugin/settings.cpp @@ -0,0 +1,498 @@ +/*************************************************************************** + * Copyright (C) 2007 by Balázs Béla * + * balazsbela@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "settings.h" +#include +#include +#include +#include +#include "qorganizer.h" +#include +#include + + +SettingsDialog::SettingsDialog(qOrganizer* parent) +{ + + parent->C_OLD_STORINGMODE=parent->C_STORINGMODE; + //Interface + + //Title string hack: + QString titleString = tr("&Settings"); //This is translated but we need Settings + titleString.remove("&",Qt::CaseSensitive); + setWindowTitle(titleString); + //Widgets + + warnLabel = new QLabel("
"+tr("Some settings require restarting qOrganizer")+"
"); + pathLabel=new QLabel(tr("Path to data folder:")); + pathEdit = new QLineEdit(parent->C_PATH); + if(parent->C_PATH=="home") + pathEdit->setText(QDir::homePath()); + pathButton = new QPushButton(tr("Browse")); + + pathEdit->setEnabled(false); + + rLabel = new QLabel(tr("Reminder check interval:")); + rBox = new QSpinBox(); + rBox ->setRange(10000,60000); + rBox -> setValue(parent->C_TIMEOUT); + + firstDayLabel = new QLabel(tr("First day of week:")); + firstDay = new QComboBox(); + firstDay -> addItem(tr("Monday")); + firstDay -> addItem(tr("Tuesday")); + firstDay -> addItem(tr("Wednesday")); + firstDay -> addItem(tr("Thursday")); + firstDay -> addItem(tr("Friday")); + firstDay -> addItem(tr("Saturday")); + firstDay -> addItem(tr("Sunday")); + firstDay -> setCurrentIndex(parent->C_FIRST_DAY_OF_WEEK-1); + + dateFormatLabel = new QLabel(tr("Date format:")); + dateFormatEdit = new QComboBox(); + dateFormatEdit -> setEditable(true); + dateFormatEdit -> addItem("dddd MMMM d. yyyy"); + dateFormatEdit -> addItem("d. MMMM dddd yyyy"); + dateFormatEdit -> addItem("MMMM d. dddd yyyy"); + dateFormatEdit -> addItem("yyyy MMMM d. dddd"); + dateFormatEdit -> addItem("yyyy d. MMMM dddd"); + dateFormatEdit -> addItem("yyyy MMMM d. dddd"); + dateFormatEdit -> addItem("yyyy dddd MMMM d. "); + dateFormatEdit -> addItem("dddd d. MMMM yyyy"); + + autoLabel = new QLabel(tr("Autosave:")); + autoBox = new QCheckBox(); + if(parent->C_AUTOSAVE_TOGGLE) + autoBox -> setChecked(true); + + messageLabel = new QLabel(tr("Remind type:")); + messageCombo = new QComboBox(); + messageCombo -> addItem("Baloon"); + messageCombo -> addItem("Message box"); + if(!parent->C_BALOON_SET) messageCombo->setCurrentIndex(1); + + langLabel = new QLabel(tr("Language:")); + langCombo = new QComboBox(); + langCombo -> addItem("English"); + readLangDir(); + if(langCombo->findText(parent->C_LANGUAGETEXT)!=-1) langCombo->setCurrentIndex(langCombo->findText(parent->C_LANGUAGETEXT)); + + rownrLabel = new QLabel(tr("Row number for empty schedule:")); + rownrBox = new QSpinBox(); + rownrBox -> setRange(0,40); + rownrBox -> setValue(parent->C_NRROWS); + + QLabel *roundLabel = new QLabel(tr("Round subject averages when calculating total average")); + roundBox = new QCheckBox; + roundBox->setChecked(parent->C_ROUND_ON_AVERAGE); + + QLabel *saveAllLabel = new QLabel(tr("Show saving buttons on toolbar")); + saveAllBox = new QCheckBox; + saveAllBox->setChecked(parent->C_SHOW_SAVE); + + QHBoxLayout *roundLayout = new QHBoxLayout; + roundLayout -> addWidget(roundLabel); + roundLayout -> addWidget(roundBox); + + QHBoxLayout *saveAllLayout = new QHBoxLayout; + saveAllLayout -> addWidget(saveAllLabel); + saveAllLayout -> addWidget(saveAllBox); + + QPushButton *okButton = new QPushButton("OK"); + QPushButton *cancelButton = new QPushButton(tr("Cancel")); + + okButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + cancelButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + + QLabel *loadLabel = new QLabel(tr("Reload data on view change")); + loadBox = new QCheckBox(this); + if(parent->C_LOAD_ON_CHANGE) loadBox->setChecked(true); else loadBox->setChecked(false); + QHBoxLayout *loadLayout = new QHBoxLayout; + loadLayout -> addWidget(loadLabel); + loadLayout -> addWidget(loadBox); + + trayLabel = new QLabel(tr("Hide to system tray on close")); + trayBox = new QCheckBox; + if(parent->C_SYSTRAY) trayBox->setChecked(true); + else trayBox->setChecked(false); + + QHBoxLayout *trayLayout = new QHBoxLayout; + trayLayout-> addWidget(trayLabel); + trayLayout-> addWidget(trayBox); + //Ftp sync labels + portLabel=new QLabel(tr("Port:")); + hostLabel=new QLabel(tr("Host:")); + userLabel=new QLabel(tr("Username:")); + passLabel=new QLabel(tr("Password:")); + ftppathLabel=new QLabel(tr("Path on ftp server:")); + ftpSyncLabel=new QLabel(tr("Synchronize with ftp server:")); + + hostEdit=new QLineEdit; + hostEdit->setFixedWidth(190); + hostEdit -> setText(parent->C_HOST); + portBox=new QSpinBox; + portBox->setRange(21,65535); + portBox->setValue(parent->C_PORT); + portBox->setFixedWidth(90); + //I don't think ftp servers are running on a lower port than 21 + //If this ever causes problems contact me. + + userEdit=new QLineEdit; + userEdit->setFixedWidth(100); + userEdit->setText(parent->C_USER); + passEdit=new QLineEdit; + passEdit->setFixedWidth(100); + passEdit->setEchoMode(QLineEdit::Password); + passEdit->setText(parent->C_PASSWD); + + ftppathEdit = new QLineEdit; + ftppathEdit->setFixedWidth(240); + ftppathEdit->setText(parent->C_FTPPATH); + + ftpBox = new QCheckBox; + connect(ftpBox,SIGNAL(stateChanged(int)),this,SLOT(toggleFTP(int))); + if(parent->C_SYNCFTP) + ftpBox->setChecked(true); + else + { + ftpBox->setChecked(false); + toggleFTP(0); + } + + QHBoxLayout *soundLayout = new QHBoxLayout; + soundLabel = new QLabel(tr("Play sound on remind")); + soundBox = new QCheckBox; + + if(parent->C_SOUND) + soundBox->setChecked(true); + else soundBox->setChecked(false); + + soundLayout -> addWidget(soundLabel); + soundLayout -> addWidget(soundBox); + + + QLabel *oddTTLabel = new QLabel(tr("Use different timetables for even and odd weeks")); + oddTTBox = new QCheckBox; + + QHBoxLayout *oddTTLayout = new QHBoxLayout; + oddTTLayout -> addWidget(oddTTLabel); + oddTTLayout -> addWidget(oddTTBox); + oddTTBox->setChecked(parent->C_USE_ODDTT); + + QLabel *reverseTTLabel = new QLabel(tr("Reverse normal order of weeks for timetable")); + reverseTTBox = new QCheckBox; + QHBoxLayout *reverseTTLayout = new QHBoxLayout; + reverseTTBox->setChecked(parent->C_TT_REVERSORDER); + reverseTTLayout->addWidget(reverseTTLabel); + reverseTTLayout->addWidget(reverseTTBox); + + //FTP Layouts + QHBoxLayout *ftpBoxLayout = new QHBoxLayout; + ftpBoxLayout -> addWidget(ftpSyncLabel); + ftpBoxLayout -> addWidget(ftpBox); + + QHBoxLayout *portLayout = new QHBoxLayout; + portLayout -> addWidget(portLabel); + portLayout -> addWidget(portBox); + + QHBoxLayout *hostLayout = new QHBoxLayout; + hostLayout -> addWidget(hostLabel); + hostLayout -> addWidget(hostEdit); + hostLayout -> addLayout(portLayout); + + QHBoxLayout *passLayout = new QHBoxLayout; + passLayout -> addWidget(passLabel); + passLayout -> addWidget(passEdit); + + QHBoxLayout *userLayout = new QHBoxLayout; + userLayout -> addWidget(userLabel); + userLayout -> addWidget(userEdit); + userLayout -> addLayout(passLayout); + + QHBoxLayout *ftppathLayout = new QHBoxLayout; + ftppathLayout -> addWidget(ftppathLabel); + ftppathLayout -> addWidget(ftppathEdit); + + //Layouts + QHBoxLayout *pathLayout = new QHBoxLayout; + pathLayout -> addWidget(pathLabel); + pathLayout -> addWidget(pathEdit); + pathLayout -> addWidget(pathButton); + + QHBoxLayout *rLayout = new QHBoxLayout; + rLayout -> addWidget(rLabel); + rLayout -> addWidget(rBox); + + QHBoxLayout *dayLayout = new QHBoxLayout; + dayLayout -> addWidget(firstDayLabel); + dayLayout -> addWidget(firstDay); + + QHBoxLayout *autoLayout = new QHBoxLayout; + autoLayout -> addWidget(autoLabel); + autoLayout -> addWidget(autoBox); + + QHBoxLayout *messageLayout = new QHBoxLayout; + messageLayout -> addWidget(messageLabel); + messageLayout -> addWidget(messageCombo); + + QHBoxLayout *langLayout = new QHBoxLayout; + langLayout -> addWidget(langLabel); + langLayout -> addWidget(langCombo); + + QHBoxLayout *rownrLayout = new QHBoxLayout; + rownrLayout -> addWidget(rownrLabel); + rownrLayout -> addWidget(rownrBox); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout -> addWidget(okButton); + buttonLayout -> addWidget(cancelButton); + + QHBoxLayout *dateFormatLayout = new QHBoxLayout; + dateFormatLayout-> addWidget(dateFormatLabel); + dateFormatLayout-> addWidget(dateFormatEdit); + + QVBoxLayout *ftpVLayout = new QVBoxLayout; + ftpVLayout -> addLayout(ftpBoxLayout); + ftpVLayout -> addLayout(hostLayout); + ftpVLayout -> addLayout(userLayout); + ftpVLayout -> addLayout(ftppathLayout); + + storingBox = new QComboBox; + storingBox-> addItem(tr("Text files")); + storingBox-> addItem(tr("SQLite database")); + storingBox-> addItem(tr("MySQL database")); + + + QLabel *storingLabel = new QLabel(tr("Store data in:")); + QHBoxLayout *storingSelectLayout = new QHBoxLayout; + storingSelectLayout -> addWidget(storingLabel); + storingSelectLayout -> addWidget(storingBox); + + storingBox->setCurrentIndex(parent->C_STORINGMODE); + + + QVBoxLayout *storingLayout = new QVBoxLayout; + storingLayout -> addLayout(storingSelectLayout); + storingLayout -> addSpacing(20); + + + mysqlHostEdit = new QLineEdit; + mysqlHostEdit->setFixedWidth(190); + mysqlHostEdit->setText(parent->C_MYSQL_HOST); + + mysqlPortBox = new QSpinBox; + mysqlPortBox->setRange(21,65535); + mysqlPortBox->setValue(3306); + if((parent->C_MYSQL_PORT) > 0) mysqlPortBox->setValue(parent->C_MYSQL_PORT); + + mysqlPortBox->setFixedWidth(90); + + QLabel *mysqlHostLabel = new QLabel(tr("Host:")); + QLabel *mysqlPortLabel = new QLabel(tr("Port:")); + + QHBoxLayout *mysqlHostLayout = new QHBoxLayout; + mysqlHostLayout->addWidget(mysqlHostLabel); + mysqlHostLayout->addWidget(mysqlHostEdit); + mysqlHostLayout->addWidget(mysqlPortLabel); + mysqlHostLayout->addWidget(mysqlPortBox); + storingLayout -> addLayout(mysqlHostLayout); + + + mysqlUserEdit = new QLineEdit; + mysqlUserEdit->setFixedWidth(100); + mysqlUserEdit->setText(parent->C_MYSQL_USER); + + mysqlPassEdit = new QLineEdit; + mysqlPassEdit->setFixedWidth(100); + mysqlPassEdit->setText(parent->C_MYSQL_PASSWD); + mysqlPassEdit->setEchoMode(QLineEdit::Password); + QLabel *mysqlUserLabel = new QLabel(tr("Username:")); + QLabel *mysqlPassLabel = new QLabel(tr("Password:")); + + + QHBoxLayout *mysqlUserLayout = new QHBoxLayout; + mysqlUserLayout->addWidget(mysqlUserLabel); + mysqlUserLayout->addWidget(mysqlUserEdit); + mysqlUserLayout->addWidget(mysqlPassLabel); + mysqlUserLayout->addWidget(mysqlPassEdit); + storingLayout -> addLayout(mysqlUserLayout); + + QLabel *mysqlDBLabel = new QLabel(tr("Database name:")); + mysqldbEdit = new QLineEdit; + mysqldbEdit->setText(parent->C_MYSQL_DB); + QHBoxLayout *mysqlDBLayout = new QHBoxLayout; + mysqlDBLayout->addWidget(mysqlDBLabel); + mysqlDBLayout->addWidget(mysqldbEdit); + storingLayout -> addLayout(mysqlDBLayout); + + QLabel *mysqlFtpLabel = new QLabel(tr("FTP synchronization is not available for MySQL database")); + storingLayout -> addWidget(mysqlFtpLabel); + + QVBoxLayout *main = new QVBoxLayout; + /*main -> addWidget(warnLabel); + main -> addLayout(pathLayout); + main -> addLayout(rLayout); + main -> addLayout(dayLayout); + main -> addLayout(dateFormatLayout); + main -> addLayout(autoLayout); + main -> addLayout(messageLayout); + main -> addLayout(langLayout); + main -> addLayout(rownrLayout); + main -> addLayout(loadLayout); + main -> addLayout(trayLayout); + main -> addLayout(soundLayout); + main -> addSpacing(10); + main -> addLayout(ftpVLayout); + main -> addSpacing(10); + main -> addLayout(storingLayout); + main -> addSpacing(10); + main -> addLayout(buttonLayout);*/ + + //QTabWidget + tabWidget = new QTabWidget(this); + main->addWidget(tabWidget); + main->addWidget(warnLabel); + main->addLayout(buttonLayout); + + setLayout(main); + + QVBoxLayout *generalLayout = new QVBoxLayout; + generalLayout -> addLayout(pathLayout); + generalLayout -> addLayout(autoLayout); + generalLayout -> addLayout(langLayout); + generalLayout -> addLayout(loadLayout); + generalLayout -> addLayout(trayLayout); + generalLayout -> addLayout(oddTTLayout); + generalLayout -> addLayout(reverseTTLayout); + generalLayout -> addLayout(roundLayout); + generalLayout -> addLayout(saveAllLayout); + + QVBoxLayout *calendarLayout = new QVBoxLayout; + calendarLayout -> addLayout(rLayout); + calendarLayout -> addLayout(dayLayout); + calendarLayout -> addLayout(dateFormatLayout); + calendarLayout -> addLayout(messageLayout); + calendarLayout -> addLayout(rownrLayout); + calendarLayout -> addLayout(soundLayout); + + + + General = new QWidget(); + General -> setLayout(generalLayout); + + Calendar = new QWidget(); + Calendar -> setLayout(calendarLayout); + + Ftp = new QWidget(); + Ftp -> setLayout(ftpVLayout); + + Storing = new QWidget(); + Storing -> setLayout(storingLayout); + + tabWidget -> addTab(General,tr("&General")); + tabWidget -> addTab(Calendar,tr("&Calendar")); + tabWidget -> addTab(Ftp,tr("FTP")); + tabWidget -> addTab(Storing,tr("Storing")); + toggleMySQL(parent->C_STORINGMODE); + + okButton->setFocus(); + //Connecting buttons + connect(pathButton,SIGNAL(clicked()),this,SLOT(setDir())); + connect(cancelButton,SIGNAL(clicked()),this,SLOT(close())); + connect(okButton, SIGNAL(clicked()),parent,SLOT(saveConfigFile())); + connect(storingBox,SIGNAL(currentIndexChanged(int)),this,SLOT(toggleMySQL(int))); +} + + +/*This function reads all qm files from the lang folder included in the resources +and adds them to the combo box. +We store languages in the resources to make sure it works every time and .qm files don't +get lost. So if you are translating this app, add your qm file to the lang folder, +add an entry in application.qrc and recompile qOrganizer*/ + +void SettingsDialog::readLangDir() +{ + QDir dir = QDir(":/lang"); + QString filter = "*.qm"; + QDir::Filters filters = QDir::Files | QDir::Readable; + QDir::SortFlags sort = QDir::Name; + QFileInfoList entries = dir.entryInfoList(QStringList()<< filter, filters, sort); + foreach (QFileInfo file, entries) + { + langCombo -> addItem(file.baseName()); + } +}; + +SettingsDialog::~SettingsDialog() +{ +}; + +void SettingsDialog::setDir() +{ + QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory"), + "", + QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks); + pathEdit->setText(dir); +} + +void SettingsDialog::toggleFTP(int state) +{ + if(state==0) + { + hostEdit->setEnabled(false); + portBox->setEnabled(false); + userEdit->setEnabled(false); + passEdit->setEnabled(false); + ftppathEdit->setEnabled(false); + } + else + { + hostEdit->setEnabled(true); + portBox->setEnabled(true); + userEdit->setEnabled(true); + passEdit->setEnabled(true); + ftppathEdit->setEnabled(true); + } +} + +void SettingsDialog::toggleMySQL(int state) +{ + if(state!=2) + { + mysqlHostEdit->setEnabled(false); + mysqlPortBox->setEnabled(false); + mysqlUserEdit->setEnabled(false); + mysqlPassEdit->setEnabled(false); + mysqldbEdit->setEnabled(false); + } + else + { + mysqlHostEdit->setEnabled(true); + mysqlPortBox->setEnabled(true); + mysqlUserEdit->setEnabled(true); + mysqlPassEdit->setEnabled(true); + mysqldbEdit->setEnabled(true); + } +} + +void SettingsDialog::close() +{ + this -> deleteLater(); +}; diff --git a/plugins/qOrganizer_plugin/settings.h b/plugins/qOrganizer_plugin/settings.h new file mode 100644 index 000000000..74a02f61d --- /dev/null +++ b/plugins/qOrganizer_plugin/settings.h @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2007 by Balázs Béla * + * balazsbela@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation version 2 of the License * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include +#include +#include +#include +#include +#include +#include + +class qOrganizer; + +class SettingsDialog : public QDialog +{ + Q_OBJECT + + public : + SettingsDialog(qOrganizer *parent); + ~SettingsDialog(); + + QLabel *warnLabel; + QLabel *pathLabel; + QLineEdit *pathEdit; + QPushButton *pathButton; + QLabel *rLabel; + QSpinBox *rBox; + QLabel *firstDayLabel; + QComboBox *firstDay; + QLabel *dateFormatLabel; + QComboBox *dateFormatEdit; + QLabel *autoLabel; + QCheckBox *autoBox; + QLabel *messageLabel; + QComboBox *messageCombo; + QLabel *langLabel; + QComboBox *langCombo; + QLabel *rownrLabel; + QSpinBox *rownrBox; + //Labels for ftp + QLabel *portLabel; + QLabel *hostLabel; + QLabel *userLabel; + QLabel *passLabel; + QLabel *ftpSyncLabel; + QLabel *ftppathLabel; + + QLabel *soundLabel; + QCheckBox *soundBox; + + QCheckBox *ftpBox; + QLineEdit *hostEdit; + QSpinBox *portBox; + QLineEdit *userEdit; + QLineEdit *passEdit; + QLineEdit *ftppathEdit; + + QCheckBox *loadBox; + QLabel *trayLabel; + QCheckBox *trayBox; + + QComboBox *storingBox; + + QTabWidget *tabWidget; + QWidget *General; + QWidget *Calendar; + QWidget *Ftp; + QWidget *Storing; + + QCheckBox *mysqlBox; + QLineEdit *mysqlHostEdit; + QSpinBox *mysqlPortBox; + QLineEdit *mysqlUserEdit; + QLineEdit *mysqlPassEdit; + QLineEdit *mysqldbEdit; + + QCheckBox *oddTTBox; + QCheckBox *reverseTTBox; + QCheckBox *roundBox; + QCheckBox *saveAllBox; + void readLangDir(); + public slots : + void setDir(); + void toggleFTP(int state); + void toggleMySQL(int state); + void close(); +}; + +#endif + + diff --git a/plugins/qcheckers_plugin/AUTHORS b/plugins/qcheckers_plugin/AUTHORS new file mode 100644 index 000000000..fd88dae2a --- /dev/null +++ b/plugins/qcheckers_plugin/AUTHORS @@ -0,0 +1,7 @@ +Andi Peredri +Artur Wiebe + +Contributors: + Sebastien Prud'homme + Guillaume Bedot french translations + diff --git a/plugins/qcheckers_plugin/ChangeLog b/plugins/qcheckers_plugin/ChangeLog new file mode 100644 index 000000000..bf066f66c --- /dev/null +++ b/plugins/qcheckers_plugin/ChangeLog @@ -0,0 +1,70 @@ +2005-12-29 Artur Wiebe + * toplevel.cc, view.h: Removed unused slots. + * Renamed info to histrory. + * history.cc: Removed useless code. + +2005-12-19 Artur Wiebe + * KCheckers 0.8 released. + * Added support for free men placement at the beginning of the game. + * Added multiple undos/redos: free movement in move history. + * Removed network code: there will be network in the next version. + * See below for more changes since 0.6. + +2005-09-09 Artur Wiebe + * KCheckers 0.7 is done - will not be released. + * Ported to Qt 4.0. So watch out for more bugs. + * Added basic Theme support. + * Improved thread termination. + * Redesigned GUI. + * echeckers.cc: Fixed bug: man reaching the king row became king and + continued move. + * Improved PDN support. Can now re-play games. + +2005-04-11 Artur Wiebe + * KCheckers 0.6 released. + * New game mode: Human vs. Human. + * Added Info widget next to game's board. + * Added different board sizes. + * Rewrote menubar and toolbar code. + * Rewrote network code. + * Fixed some bugs, introduced new. + +2004-08-08 Artur Wiebe + * KCheckers 0.5 released. + * Machine thinks in a thread now. + * Added Internationalization support. + * Added Network support. + * Altered GUI interface to match KDE specifications. + * Extended Preview in File Open Dialog. + * Various improvements. + +2003-01-15 Andi Peredri + * KCheckers 0.4 released. + * Added support for Portable Draughts Notation database format. + * Added saving, loading and restarting of game. + * Added PDN preview widget. + * Added 20 PDN compositions. + * Added game information box. + * Various improvements. + +2002-06-10 Andi Peredri + * KCheckers 0.3 released. + * Ported to Qt 3. + * Added toolbar. + * Added green theme of the board. + * Added undo of last move. + * Added auto saving of settings. + * Added optional notation of the board. + +2002-03-10 Andi Peredri + * KCheckers 0.2 released. + * Ported to pure Qt. + * KCheckers engine improvements. + * Added support of english checkers. + * Added wooden theme of the board. + * Added auto change of the men's color. + * Added on-line description of the play's rules. + +2002-01-15 Andi Peredri + * Initial Release. + diff --git a/plugins/qcheckers_plugin/FAQ b/plugins/qcheckers_plugin/FAQ new file mode 100644 index 000000000..63df0fbcd --- /dev/null +++ b/plugins/qcheckers_plugin/FAQ @@ -0,0 +1,49 @@ +What is my IP address? +---------------------- +Run ifconfig and loop for the eth0/ppp0/ippp0 entry. The second line starts +with "inet addr". That's your IP address! + + +How to create a themes? +----------------------- +There are two places you can put your own theme directories: +$SHARE/themes or $HOME/.kcheckers/themes. $SHARE is /usr/local/kcheckers on +default. simply create a directory there that contains the following files: + tile1.png - unused tiles. + tile2.png - where men are placed. + frame.png - around selected man. + manblack.png - + manwhite.png - + kingblack.png - + kingwhite.png - + theme - the first line should be the default/english name + - of the theme. This will be used if the correct locale + - name should not be found. + - Locale specific names can be provided with the + - following syntax: [locale]=Theme Name. + - Example theme file: + - Line 1) This is a default theme name + - Line 2) [de_DE]=Das ist Deutsch + - Line 2) [en]=This is English +Directory name will be shown as theme name. All pictures are the same size. + + +My theme is not loaded. Why? +---------------------------- +Start kcheckers in a x-terminal. Watch out for errors otherwise send me your +compressed theme directory. + + +PDN. +---- +Because draught is a fast (compared to chess) game there are less situations +one will save a game. Nevertheless, this is possible in kcheckers. + +Now, imagine you want to see how a match on the last WCM was played. You simply +open the PDN file, select the game you are interested in from the list and +click move after a move and watch how the men on the board are moved. + +If you want to continue a game at certain position, no problem, click on the +"Continue" button in toolbar. But consider who is next on turn, what kind of +game (against computer or human) you are playing. + diff --git a/plugins/qcheckers_plugin/QcheckersPlugin.cpp b/plugins/qcheckers_plugin/QcheckersPlugin.cpp new file mode 100644 index 000000000..c63ef98d6 --- /dev/null +++ b/plugins/qcheckers_plugin/QcheckersPlugin.cpp @@ -0,0 +1,33 @@ +//#include +//#include +//#include + +#include "QcheckersPlugin.h" +#include "toplevel.h" + +QString +QcheckersPlugin::pluginDescription() const +{ + QString res; + res = "A QCheckers plugin" ; + + return res; +} + +QString +QcheckersPlugin::pluginName() const +{ + return "QCheckers" ; +} + +QWidget* +QcheckersPlugin::pluginWidget(QWidget * parent ) +{ + myTopLevel* top = new myTopLevel(); + + return top; + +} + + +Q_EXPORT_PLUGIN2(qcheckers_plugin, QcheckersPlugin) diff --git a/plugins/qcheckers_plugin/QcheckersPlugin.h b/plugins/qcheckers_plugin/QcheckersPlugin.h new file mode 100644 index 000000000..957b22c3c --- /dev/null +++ b/plugins/qcheckers_plugin/QcheckersPlugin.h @@ -0,0 +1,27 @@ +#ifndef _HWA_PLUGIN_H_ +#define _HWA_PLUGIN_H_ + +#include + +#include +#include + +#include + +#include + +class QcheckersPlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/qcheckers_plugin/README b/plugins/qcheckers_plugin/README new file mode 100644 index 000000000..a1f9620c1 --- /dev/null +++ b/plugins/qcheckers_plugin/README @@ -0,0 +1,83 @@ + + KCheckers is a Qt-based checkers board game. + + Requirements: Qt 3.0 + + Installation: Read INSTALLS for more information. + + Information: If you find any bugs, send a report to wibix@gmx.de. + For further information and recent versions of KCheckers, + please visit it's Homepage at + + http://kcheckers.org + http://kcheckers.wibix.de + + Usage: Read FAQ for more information. + + PDN Format: For storing the positions of games KCheckers uses the + Portable Draughts Notation (PDN) database format. It is + used by many other checkers programs, and is becoming + the standard way to swap games. + + PDN is based on the Portable Game Notation (PGN) standard + which is widely used for Chess. + + For details see http://www.chessandcheckers.com/pdn.htm + + ----------------------------------------------------------------------- + PDN File: [Event "Game 1"] + [Black "Nemet,A"] + [White "Terens,B"] + [Date "11.05.2002"] + [Result "1-0"] + [GameType "21"] + [SetUp "1"] + [FEN "W:WK4,28:BK11,19."] + + 1. 4-8 11x4 2. 28-24 19x28 {black win...} 1-0 + + ----------------------------------------------------------------------- + Results: 1-0 White wins + 0-1 Black wins + 1/2-1/2 Drawn game + * Unfinished game + + ----------------------------------------------------------------------- + Game Types: 0: Chess + 1: Chinese chess + 2-19: Future chess expansion + 20: International draughts + 21: English draughts + 22: Italian draughts + 23: American pool + 24: Spanish draughts + 25: Russian draughts + 26: Brazilian draughts + 27: Canadian draughts + 28: Portugese draughts + 29-49: Future draughts expansion + 50: Othello + + ----------------------------------------------------------------------- + FEN: If a game starts from a set-up position, a Forsyth-Edwards + Notation (FEN) header is given with the position. + + W Turn + :W White pieces + K4 King on field 4 + 28 Man on field 28 + :B Black pieces + + ----------------------------------------------------------------------- + Rules: Board BackCapture MoveKing TakeMax + International 10x10 + >1 + + English 8x8 kings 1 - + Italian 8x8 kings 1 + + American pool 8x8 + >1 - + Spanish 8x8 kings >1 + + Russian 8x8 + >1 - + Brasilian 8x8 + >1 + + Canadian 12x12 + >1 + + + ----------------------------------------------------------------------- + diff --git a/plugins/qcheckers_plugin/board.cc b/plugins/qcheckers_plugin/board.cc new file mode 100644 index 000000000..7b20f1d92 --- /dev/null +++ b/plugins/qcheckers_plugin/board.cc @@ -0,0 +1,364 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +#include "board.h" +#include "common.h" +#include "pdn.h" +#include "echeckers.h" +#include "rcheckers.h" +/* +#include "newgamedlg.h" + +#include "player.h" +#include "humanplayer.h" +#include "computerplayer.h" +*/ + + +myBoard::myBoard(QWidget* parent) + : QFrame(parent) +{ + /* + * board & info + */ + setFrameStyle(QFrame::Box|QFrame::Plain); + for(int i=0; i<64; i++) + m_fields[i] = new Field(this, i); + + QGridLayout* grid = new QGridLayout(this); + grid->setSpacing(0); + grid->setMargin(0); + for(int i=0; i<4; i++) { + for(int k=0; k<4; k++) { + grid->addWidget(m_fields[i*8+k+32], i*2, k*2 ); + grid->addWidget(m_fields[i*8+k ], i*2, k*2+1); + grid->addWidget(m_fields[i*8+k+4 ], i*2+1,k*2 ); + grid->addWidget(m_fields[i*8+k+36], i*2+1,k*2+1); + } + } + + for(int i=0; i<32; i++) + connect(m_fields[i], SIGNAL(click(int)), + this, SIGNAL(fieldClicked(int))); + + + /* + * game init + */ + m_game = 0; + + xpmPat1 = 0; + xpmPat2 = 0; + xpmFrame= 0; + xpmManBlack = 0; + xpmManWhite = 0; + xpmKingBlack= 0; + xpmKingWhite= 0; +} + + +myBoard::~myBoard() +{ + if(m_game) + delete m_game; +} + + +void myBoard::setTheme(const QString& path, bool set_white) +{ + // delete them later. + QPixmap* p1 = xpmManWhite; + QPixmap* p2 = xpmManBlack; + QPixmap* p3 = xpmKingWhite; + QPixmap* p4 = xpmKingBlack; + QPixmap* p5 = xpmPat1; + QPixmap* p6 = xpmPat2; + QPixmap* p7 = xpmFrame; + + if(path == DEFAULT_THEME) { + // just in case no themes installed. + xpmPat1 = new QPixmap(":/icons/theme/tile1.png"); + xpmPat2 = new QPixmap(":/icons/theme/tile2.png"); + xpmFrame= new QPixmap(":/icons/theme/frame.png"); + xpmManBlack = new QPixmap(":/icons/theme/manblack.png"); + xpmManWhite = new QPixmap(":/icons/theme/manwhite.png"); + xpmKingBlack= new QPixmap(":/icons/theme/kingblack.png"); + xpmKingWhite= new QPixmap(":/icons/theme/kingwhite.png"); + } else { + xpmPat1 = new QPixmap(path+"/"THEME_TILE1); + xpmPat2 = new QPixmap(path+"/"THEME_TILE2); + xpmFrame= new QPixmap(path+"/"THEME_FRAME); + xpmManBlack + = new QPixmap(path+"/"THEME_MANBLACK); + xpmManWhite + = new QPixmap(path+"/"THEME_MANWHITE); + xpmKingBlack + = new QPixmap(path+"/"THEME_KINGBLACK); + xpmKingWhite + = new QPixmap(path+"/"THEME_KINGWHITE); + } + + setColorWhite(set_white); + + for(int i=0; i<32; i++) + m_fields[i]->setPattern(xpmPat2); + for(int i=32; i<64; i++) + m_fields[i]->setPattern(xpmPat1); + for(int i=0; i<32; i++) + m_fields[i]->setFrame(xpmFrame); + + setFixedSize(xpmMan1->width()*8 + 2*frameWidth(), + xpmMan1->height()*8 + 2*frameWidth()); + + if(m_game) + do_draw(); + + // now delete. + if(p1) delete p1; + if(p2) delete p2; + if(p3) delete p3; + if(p4) delete p4; + if(p5) delete p5; + if(p6) delete p6; + if(p7) delete p7; +} + + +void myBoard::reset() +{ + int new_board[32]; + + for(int i=0; i<12; i++) + new_board[i]=MAN2; + for(int i=12; i<20; i++) + new_board[i]=FREE; + for(int i=20; i<32; i++) + new_board[i]=MAN1; + + // reset frames. + for(int i=0; i<32; i++) + m_fields[i]->showFrame(false); + + if(m_game) + m_game->setup(new_board); + + do_draw(); +} + + +void myBoard::adjustNotation(bool bottom_is_white) +{ + if(!m_game) + return; + + QString notation = (m_game->type()==ENGLISH + ? ENOTATION : QString(RNOTATION).toUpper()); + + if(bottom_is_white) { + for(int i=0; i<32; i++) + m_fields[i]->setLabel(notation.mid(i*2,2).trimmed()); + } else { + for(int i=0; i<32; i++) + m_fields[i]->setLabel(notation.mid(62-i*2,2).trimmed()); + } +} + + +void myBoard::do_draw() +{ + for(int i=0; i<32; i++) { + switch(m_game->item(i)) { + case MAN1: + m_fields[i]->setPicture(xpmMan1); + break; + case MAN2: + m_fields[i]->setPicture(xpmMan2); + break; + case KING1: + m_fields[i]->setPicture(xpmKing1); + break; + case KING2: + m_fields[i]->setPicture(xpmKing2); + break; + default: + m_fields[i]->setPicture(NULL); + } + } +} + + +void myBoard::setColorWhite(bool b) +{ + if(b) { + xpmMan1 = xpmManWhite; + xpmMan2 = xpmManBlack; + xpmKing1= xpmKingWhite; + xpmKing2= xpmKingBlack; + } else { + xpmMan1 = xpmManBlack; + xpmMan2 = xpmManWhite; + xpmKing1= xpmKingBlack; + xpmKing2= xpmKingWhite; + } +} + +void myBoard::setNotation(bool s, bool above) +{ + for(int i=0; i<32; i++) + m_fields[i]->showLabel(s, above); +} + +/* +void myBoard::do_move(const QString& move) +{ + qDebug() << __PRETTY_FUNCTION__; + if(!m_current->isHuman()) { + add_log(myBoard::Warning, tr("It's not your turn.")); + return; + } + + int from_num, to_num; + if(extract_move(move, &from_num, &to_num)) { + slot_click(from_num); + slot_click(to_num); + } else + add_log(myBoard::Warning, tr("Syntax error. Usage: /from-to")); +} + */ + + + +bool myBoard::convert_move(const QString& move_orig, int* from_num, int* to_num) +{ + QString move = move_orig.toUpper().replace('X', '-'); + QString from; + QString to; + int sect = move.count('-'); + + *from_num = *to_num = -1; + + from = move.section('-', 0, 0); + to = move.section('-', sect, sect); + + if(from!=QString::null && to!=QString::null) { + for(int i=0; i<32; i++) { + if(m_fields[i]->label()==from) + *from_num = m_fields[i]->number(); + if(m_fields[i]->label()==to) + *to_num = m_fields[i]->number(); + } + + if(*from_num>=0 && *to_num>=0) + return true; + } + + return false; +} + + +void myBoard::setNotationFont(const QFont& f) +{ + setFont(f); + for(int i=0; i<32; i++) + m_fields[i]->fontUpdate(); +} + + +void myBoard::setGame(int rules) +{ + if(m_game) + delete m_game; + + if(rules==ENGLISH) { + m_game = new ECheckers(); + } else { + m_game = new RCheckers(); + } + + reset(); +} + + +void myBoard::selectField(int field_num, bool is_on) +{ + for(int i=0; i<32; i++) { + if(i==field_num) + m_fields[i]->showFrame(is_on); + else + m_fields[i]->showFrame(false); + } +} + + +QString myBoard::doMove(int from_num, int to_num, bool white_player) +{ + bool bottom_player = (white_player && (xpmMan1==xpmManWhite)) + || (!white_player && (xpmMan1==xpmManBlack)); + + int from_pos = from_num; + int to_pos = to_num; + + if(!bottom_player) { + from_pos = 31-from_pos; + to_pos = 31-to_pos; + m_game->fromString(m_game->toString(true)); + } + if(!m_game->go1(from_pos, to_pos)) { + return QString::null; + /* + qDebug() << __PRETTY_FUNCTION__ + << from_pos << "," << to_pos + << " could not move."; + */ + } + if(!bottom_player) { + m_game->fromString(m_game->toString(true)); + } + + do_draw(); + + return QString("%1?%3") + .arg(m_fields[from_num]->label()) + .arg(m_fields[to_num]->label()); +} + + +bool myBoard::doMove(const QString& move, bool white_player) +{ + int from_pos, to_pos; + if(convert_move(move, &from_pos, &to_pos)) { + doMove(from_pos, to_pos, white_player); + return true; + } + return false; +} + + +void myBoard::doFreeMove(int from, int to) +{ + int old_to = m_game->item(to); + int old_from = m_game->item(from); + m_game->setItem(to, old_from); + m_game->setItem(from, old_to); + do_draw(); +} + diff --git a/plugins/qcheckers_plugin/board.h b/plugins/qcheckers_plugin/board.h new file mode 100644 index 000000000..2273761b1 --- /dev/null +++ b/plugins/qcheckers_plugin/board.h @@ -0,0 +1,94 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + + +#include + +#include "field.h" +#include "checkers.h" + + +class myBoard : public QFrame +{ + Q_OBJECT + +public: + myBoard(QWidget* parent); + ~myBoard(); + + // returns coded move string: from_pos_string?to_pos_string + QString doMove(int from_pos, int to_pos, bool white_player); + // coded move. + bool doMove(const QString& move, bool white_player); + // + void doFreeMove(int from, int to); + + void selectField(int field_num, bool is_on); + + void setTheme(const QString& theme_path, bool set_white); + + void setNotation(bool enabled, bool show_above); + void setNotationFont(const QFont& f); + + void setColorWhite(bool); + void reset(); + void adjustNotation(bool bottom_is_white); + + void setGame(int rules); + + bool whiteIsNext() const; + + int type() const { return m_game->type(); } + // TODO + const Checkers* game() const { return m_game; } + +signals: + void fieldClicked(int); + +private: + bool convert_move(const QString&, int* from, int* to); + void do_draw(); + +private: + Field* m_fields[64]; + + QPixmap* xpmPat1; + QPixmap* xpmPat2; + QPixmap* xpmFrame; + + QPixmap* xpmMan1; + QPixmap* xpmMan2; + QPixmap* xpmKing1; + QPixmap* xpmKing2; + + QPixmap* xpmManBlack; + QPixmap* xpmManWhite; + QPixmap* xpmKingBlack; + QPixmap* xpmKingWhite; + + Checkers* m_game; +}; + + +#endif + diff --git a/plugins/qcheckers_plugin/checkers.cc b/plugins/qcheckers_plugin/checkers.cc new file mode 100644 index 000000000..b3dd35489 --- /dev/null +++ b/plugins/qcheckers_plugin/checkers.cc @@ -0,0 +1,451 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +// +// KCheckers Engine + +// +// Internal: External: +// +// Board = 54 Fields: Board = 32 Fields: +// +// | 06 07 08 09| MAN2 | 00 01 02 03| +// |11 12 13 14 | |04 05 06 07 | +// | 17 18 19 20| | 08 09 10 11| +// |22 23 24 25 | |12 13 14 15 | +// | 28 29 30 31| | 16 17 18 19| +// |33 34 35 36 | |20 21 22 23 | +// | 39 40 41 42| | 24 25 26 27| +// |44 45 46 47 | MAN1 |28 29 30 31 | + +#include +#include + +#include + +#include "checkers.h" + + +int Checkers::internal(int external) const +{ + const int i[]={6,7,8,9,11,12,13,14,17,18,19,20,22,23,24,25, + 28,29,30,31,33,34,35,36,39,40,41,42,44,45,46,47}; + return i[external]; +} + + +/* +int Checkers::external(int internal) const +{ + const int i[]={ + -1,-1,-1,-1,-1,-1,0,1,2,3, // 0-9 internal + -1,4,5,6,7,-1,-1,8,9,10, // 10-19 + 11,-1,12,13,14,15,-1,-1,16,17, // 20-29 + 18,19,-1,20,21,22,23,-1,-1,24, // 30-39 + 25,26,27,-1,28,29,30,31,-1,-1, // 40-49 + -1,-1,-1,-1}; // 50-53 + return i[internal]; +} +*/ + + +Checkers::Checkers() +{ + for(int i=0;i<54;i++) board[i] = NONE; + + for(int i=0; i<12; i++) board[internal(i)] = MAN2; + for(int i=12; i<20; i++) board[internal(i)] = FREE; + for(int i=20; i<32; i++) board[internal(i)] = MAN1; + + levelmax = 2; + + srand(time(0)); // Seed the random number generator +} + + +bool Checkers::setup(int setupboard[]) +{ + /*aw - caused problems + int sum1=0; // Sum of MAN1 & KING1 + int sum2=0; // Sum of MAN2 & KING2 + + for(int i=0; i<32; i++) { + switch(setupboard[i]) { + case MAN1: + case KING1: sum1++; break; + case MAN2: + case KING2: sum2++; break; + + case FREE: break; + + default: return false; + } + } + + if(sum1>12 || sum1==0 || sum2>12 || sum2==0) + return false; + + for(int i=0; i<4; i++) + if(setupboard[i]==MAN1) return false; + + for(int i=28; i<32; i++) + if(setupboard[i]==MAN2) return false; + */ + + for(int i=0; i<32; i++) + board[internal(i)] = setupboard[i]; + + return true; +} + + +/////////////////////////////////////////////////// +// +// Player Functions +// +/////////////////////////////////////////////////// + + +bool Checkers::checkMove1() const +{ + for(int i=6;i<48;i++) + if(checkMove1(i)) + return true; + return false; +} + + +bool Checkers::checkMove1(int i) const +{ + switch(board[i]) { + case MAN1: + if(board[i-6]==FREE) return true; + if(board[i-5]==FREE) return true; + break; + case KING1: + if(board[i-6]==FREE) return true; + if(board[i-5]==FREE) return true; + if(board[i+5]==FREE) return true; + if(board[i+6]==FREE) return true; + } + return false; +} + + +//////////////////////////////////////////////////// +// +// Computer Functions +// +//////////////////////////////////////////////////// + + +void Checkers::go2() +{ + // + level=0; + for(int i=6;i<48;i++) + bestboard[i] = board[i]; + turn(); + for(int i=6;i<48;i++) + board[i] = bestboard[i]; + ; +} + + +void Checkers::turn(int& resMax, bool capture) +{ + if(levelresMax) { + resMax=res; + if(level==1) { + for(int i=6;i<48;i++) bestboard[i]=board[i]; + bestcounter=1; + } + } else if(res==resMax && level==1) { + bestcounter++; + if((rand()%bestcounter)==0) { + for(int i=6;i<48;i++) bestboard[i]=board[i]; + } + } + + if(capture) { + if(f12) board[12]=NONE; + if(f13) board[13]=NONE; + if(f14) board[14]=NONE; + if(f17) board[17]=NONE; + if(f18) board[18]=NONE; + if(f19) board[19]=NONE; + if(f23) board[23]=NONE; + if(f24) board[24]=NONE; + if(f25) board[25]=NONE; + if(f28) board[28]=NONE; + if(f29) board[29]=NONE; + if(f30) board[30]=NONE; + if(f34) board[34]=NONE; + if(f35) board[35]=NONE; + if(f36) board[36]=NONE; + if(f39) board[39]=NONE; + if(f40) board[40]=NONE; + if(f41) board[41]=NONE; + } + } + else if(resMax<0) resMax=0; +} + + +bool Checkers::checkMove2() const +{ + for(int i=6;i<48;i++) { + switch(board[i]) { + case MAN2: + if(board[i+5]==FREE) return true; + if(board[i+6]==FREE) return true; + break; + case KING2: + if(board[i-6]==FREE) return true; + if(board[i-5]==FREE) return true; + if(board[i+5]==FREE) return true; + if(board[i+6]==FREE) return true; + } + } + return false; +} + + +int Checkers::turn() +{ + int resMax=(level-levelmax)*10; + level++; + + if(checkCapture2()) { + for(int i=6; i<48; i++) { + switch(board[i]) { + case MAN2: + manCapture2(i, resMax); + break; + case KING2: + kingCapture2(i,UL,resMax); + kingCapture2(i,UR,resMax); + kingCapture2(i,DL,resMax); + kingCapture2(i,DR,resMax); + } + } + + } else if(checkMove2()) { + for(int i=6;i<48;i++) { + switch(board[i]) { + case MAN2: + if(board[i+5]==FREE) { // down left + board[i]=FREE; + if(i>38) + board[i+5]=KING2; + else + board[i+5]=MAN2; + turn(resMax); + board[i+5]=FREE; + board[i]=MAN2; + } + if(board[i+6]==FREE) { // down right + board[i]=FREE; + if(i>38) + board[i+6]=KING2; + else + board[i+6]=MAN2; + turn(resMax); + board[i+6]=FREE; + board[i]=MAN2; + } + break; + case KING2: + kingMove2(i,resMax); + break; + } + } + + } else ; + + level--; + return resMax; +} + + +QString Checkers::toString(bool rotate) const +{ + int fields[32]; + int it; + + for(int i=0; i<32; i++) { + it = item(i); + if(rotate) + fields[31-i] = (~it&7)-1; + else + fields[i] = it; + } + + QString str; + for(int i=0; i<32; i++) + str += QString("").sprintf("%.2u", fields[i]); + + return str; +} + + +bool Checkers::fromString(const QString& str) +{ + int fields[32]; + + for(int i=0; i<32; i++) + fields[i] = str.mid(i*2, 2).toInt(); + + // apply + if(!setup(fields)) { + qDebug() << "Checkers::fromString:" << str; + return false; + } + + return true; +} + diff --git a/plugins/qcheckers_plugin/checkers.h b/plugins/qcheckers_plugin/checkers.h new file mode 100644 index 000000000..c9381e533 --- /dev/null +++ b/plugins/qcheckers_plugin/checkers.h @@ -0,0 +1,105 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef CHECKERS_H +#define CHECKERS_H + + +#include + + +// do not change - hard coded +#define NONE 0 +#define MAN1 1 +#define KING1 2 +#define FREE 3 +#define KING2 4 +#define MAN2 5 +#define FULL 6 + +#define UL -6 +#define UR -5 +#define DL 5 +#define DR 6 + + +class Checkers +{ +public: + Checkers(); + virtual ~Checkers() {} + + bool setup(int setupboard[]); + virtual bool go1(int from, int to)=0; + + void go2(); + + void setSkill(int i) { levelmax=i; }; + int skill() const { return levelmax; } + virtual int type() const = 0; + + int item(int i) const { return board[internal(i)]; } + void setItem(int i, int item) { board[internal(i)] = item; } + + // string representation of the game board. + // set rotate to switch player sides. + QString toString(bool rotate) const; + bool fromString(const QString&); + + // checks for a capture/move for particular stone in external + // representation. human player only. + bool canCapture1(int i) { return checkCapture1(internal(i)); } + bool canMove1(int i) { return checkMove1(internal(i)); } + + bool checkMove1() const; + bool checkMove2() const; + virtual bool checkCapture1() const = 0; + virtual bool checkCapture2() const = 0; + +protected: + bool checkMove1(int) const; + virtual bool checkCapture1(int) const = 0; + + int level; // Current level + int levelmax; // Maximum level + + int turn(); + void turn(int&, bool capture=false); + + int to; + int board[54]; + int bestboard[54]; + int bestcounter; + + virtual void kingMove2(int,int &)=0; + + virtual bool manCapture2(int,int &)=0; + virtual bool kingCapture2(int,int,int &)=0; + + virtual bool manCapture1(int,int,bool &)=0; + virtual bool kingCapture1(int,int,bool &)=0; + + int internal(int) const; // Return internal board position +}; + + +#endif diff --git a/plugins/qcheckers_plugin/common.h b/plugins/qcheckers_plugin/common.h new file mode 100644 index 000000000..8b34655f5 --- /dev/null +++ b/plugins/qcheckers_plugin/common.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + + +#define APPNAME "QCheckers" +#define VERSION "0.8.1" +#define EXT "pdn" + + +#define HOMEPAGE "http://kcheckers.org" +#define COPYRIGHT "(c) 2002-2003, Andi Peredri (andi@ukr.net)
" \ + "(c) 2004-2005, Artur Wiebe (wibix@gmx.de)" +#define CONTRIBS "Sebastien Prud'homme (prudhomme@laposte.net)
" \ + "Guillaume Bedot (guillaume.bedot@wanadoo.fr)" + +/* !!! Do not change PREFIX variable name, please. !!! */ +/* !!! It is used in qcheckers.pro. !!! */ +#define PREFIX "/usr/local" +#define USER_PATH ".kcheckers" // in $HOME +#define THEME_DIR "themes/" + +// some keys for QSettings +#define CFG_KEY "/"APPNAME"/" + +// +#define DEFAULT_THEME "Default" +// +#define THEME_TILE1 "tile1.png" +#define THEME_TILE2 "tile2.png" +#define THEME_FRAME "frame.png" +#define THEME_MANBLACK "manblack.png" +#define THEME_MANWHITE "manwhite.png" +#define THEME_KINGBLACK "kingblack.png" +#define THEME_KINGWHITE "kingwhite.png" +#define THEME_FILE "theme" + +// +#define MAX_TILE_SIZE 64 + +#endif + diff --git a/plugins/qcheckers_plugin/computerplayer.cc b/plugins/qcheckers_plugin/computerplayer.cc new file mode 100644 index 000000000..0d9539847 --- /dev/null +++ b/plugins/qcheckers_plugin/computerplayer.cc @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "computerplayer.h" +#include "pdn.h" +#include "rcheckers.h" +#include "echeckers.h" +#include "checkers.h" + + +myComputerPlayer::myComputerPlayer(const QString& name, bool white, int skill) + : myPlayer(name, white) +{ + m_game = 0; + m_thread = 0; + m_skill = skill; +} + + +myComputerPlayer::~myComputerPlayer() +{ + if(m_thread) { + m_thread->stop(); + // delete m_thread + } + delete m_game; +} + + +void myComputerPlayer::yourTurn(const Checkers* g) +{ + if(m_thread) + qDebug("myComputerPlayer::yourTurn: a thread exists."); + + // first create it. + if(!m_game || m_game->type()!=g->type()) { + delete m_game; + if(g->type()==RUSSIAN) + m_game = new RCheckers(); + else + m_game = new ECheckers(); + } + + m_game->setSkill(m_skill); + m_game->fromString(g->toString(false)); + + m_thread = new myThread(this, m_game); + m_thread->start(); +} + + +void myComputerPlayer::stop() +{ + if(m_thread) { + m_thread->stop(); + } +} + + +void myComputerPlayer::customEvent(QEvent* ev) +{ + if(ev->type() == QEvent::MaxUser) { + m_thread->wait(); + + delete m_thread; + m_thread = 0; + + emit moveDone(m_game->toString(false)); + } +} + + + +/**************************************************************************** + * + * + ***************************************************************************/ +void myThread::run() +{ + m_game->go2(); + if(!m_aborted) { + QEvent* ev = new QEvent(QEvent::MaxUser); + QApplication::postEvent(m_player, ev); + } else + qDebug("thread.aborted.done."); +} + + +void myThread::stop() +{ + m_aborted = true; + m_game->setSkill(0); +} + diff --git a/plugins/qcheckers_plugin/computerplayer.h b/plugins/qcheckers_plugin/computerplayer.h new file mode 100644 index 000000000..553389f3a --- /dev/null +++ b/plugins/qcheckers_plugin/computerplayer.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _COMPUTERPLAYER_H_ +#define _COMPUTERPLAYER_H_ + + +#include + +#include "player.h" + + +class myThread; + + +class myComputerPlayer : public myPlayer +{ + Q_OBJECT + +public: + myComputerPlayer(const QString& name, bool white, int skill); + ~myComputerPlayer(); + + virtual void yourTurn(const Checkers* game); + virtual void stop(); + + // need this to process thread's events + virtual void customEvent(QEvent*); + +private: + myThread* m_thread; + Checkers* m_game; + int m_skill; +}; + + + +/****************************************************************************/ +class myThread : public QThread { +public: + myThread(myComputerPlayer* p, Checkers* g) + : m_player(p), m_game(g), m_aborted(false) {} + + virtual void run(); + + void stop(); + + Checkers* game() const { return m_game; } + +private: + myComputerPlayer* m_player; + Checkers* m_game; + bool m_aborted; +}; + + +#endif + diff --git a/plugins/qcheckers_plugin/copying b/plugins/qcheckers_plugin/copying new file mode 100644 index 000000000..c7aea1896 --- /dev/null +++ b/plugins/qcheckers_plugin/copying @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/plugins/qcheckers_plugin/echeckers.cc b/plugins/qcheckers_plugin/echeckers.cc new file mode 100644 index 000000000..362e59e1b --- /dev/null +++ b/plugins/qcheckers_plugin/echeckers.cc @@ -0,0 +1,423 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +// aw?1 - due to english rules a man reaching the king-row becomes a king +// and the is complete. +// +// English Checkers + + +#include "echeckers.h" + + +/////////////////////////////////////////////////// +// +// Player Functions +// +/////////////////////////////////////////////////// + + +bool ECheckers::go1(int from, int field) +{ + from=internal(from); + field=internal(field); + + to=field; + + if(checkCapture1()) { + bool capture=false; + + switch(board[from]) { + case MAN1: + if(manCapture1(from, UL, capture)) return true; + if(manCapture1(from, UR, capture)) return true; + return false; + case KING1: + if(kingCapture1(from, UL, capture)) return true; + if(kingCapture1(from, UR, capture)) return true; + if(kingCapture1(from, DL, capture)) return true; + if(kingCapture1(from, DR, capture)) return true; + return false; + } + + } else { + switch(board[from]) { + case MAN1: + if((to==(from-6))||(to==(from-5))) { + board[from]=FREE; + if(to<10) + board[to]=KING1; + else + board[to]=MAN1; + return true; + } + return false; + case KING1: + if((to==(from-6))||(to==(from-5)) || + (to==(from+5))||(to==(from+6)) ) { + board[from]=FREE; + board[to]=KING1; + return true; + } + return false; + } + } + + return false; +} + + +bool ECheckers::checkCapture1() const +{ + for(int i=6;i<48;i++) + if(checkCapture1(i)) + return true; + + return false; +} + + +bool ECheckers::checkCapture1(int i) const +{ + switch(board[i]) { + case MAN1: + // forward-left + if(board[i-6]==MAN2 || board[i-6]==KING2) + if(board[i-12]==FREE) return true; + // forward-right + if(board[i-5]==MAN2 || board[i-5]==KING2) + if(board[i-10]==FREE) return true; + break; + + case KING1: + // forward-left + if(board[i-6]==MAN2 || board[i-6]==KING2) + if(board[i-12]==FREE) return true; + // forward-right + if(board[i-5]==MAN2 || board[i-5]==KING2) + if(board[i-10]==FREE) return true; + // backward-left + if(board[i+5]==MAN2 || board[i+5]==KING2) + if(board[i+10]==FREE) return true; + // backward-right + if(board[i+6]==MAN2 || board[i+6]==KING2) + if(board[i+12]==FREE) return true; + } + + return false; +} + + +/* ORIG FUNC aw??? +bool ECheckers::checkCapture1() +{ + for(int i=6;i<48;i++) { + switch(board[i]) { + case MAN1: + // forward-left + if(board[i-6]==MAN2 || board[i-6]==KING2) + if(board[i-12]==FREE) return true; + // forward-right + if(board[i-5]==MAN2 || board[i-5]==KING2) + if(board[i-10]==FREE) return true; + break; + + case KING1: + // forward-left + if(board[i-6]==MAN2 || board[i-6]==KING2) + if(board[i-12]==FREE) return true; + // forward-right + if(board[i-5]==MAN2 || board[i-5]==KING2) + if(board[i-10]==FREE) return true; + // backward-left + if(board[i+5]==MAN2 || board[i+5]==KING2) + if(board[i+10]==FREE) return true; + // backward-right + if(board[i+6]==MAN2 || board[i+6]==KING2) + if(board[i+12]==FREE) return true; + } + } + + return false; +} +*/ + + +// Return TRUE if a course of the player true +// Return FALSE if a course of the player incorrect + +bool ECheckers::manCapture1(int from, int direction, bool& capture) +{ + int i=from+direction; + + if(board[i]==MAN2 || board[i]==KING2) { + int k=i+direction; + if(board[k]==FREE) { + bool next=false; + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + + // become a king! + if(k<10) { + board[k]=KING1; + /*aw?1 + if(kingCapture1(k, direction+11, next)) { + board[i]=FREE; + return true; + } + */ + } else { + board[k]=MAN1; + if(manCapture1(k,UL,next)) {board[i]=FREE; return true;} + if(manCapture1(k,UR,next)) {board[i]=FREE; return true;} + } + + //?? make move here, too??? + if((!next) && k==to) {board[i]=FREE; return true;}// move success + + // move failed, restore + board[k]=FREE; + board[i]=save; + board[from]=MAN1; + capture=true; + } + } + + return false; +} + + +bool ECheckers::kingCapture1(int from, int direction, bool& capture) +{ + int i=from+direction; + if(board[i]==MAN2 || board[i]==KING2) + { + int k=i+direction; + if(board[k]==FREE) + { + bool next=false; + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + board[k]=KING1; + + if(direction==UL || direction==DR) { + if(kingCapture1(k,UR,next)) {board[i]=FREE;return true;} + if(kingCapture1(k,DL,next)) {board[i]=FREE;return true;} + } else { + if(kingCapture1(k,UL,next)) {board[i]=FREE;return true;} + if(kingCapture1(k,DR,next)) {board[i]=FREE;return true;} + } + if(kingCapture1(k,direction,next)) {board[i]=FREE;return true;} + + if((!next) && k==to) {board[i]=FREE;return true;}// move ok + + // move failed, restore + board[k]=FREE; + board[i]=save; + board[from]=KING1; + capture=true; + } + } + return false; +} + + +//////////////////////////////////////////////////// +// +// Computer Functions +// +//////////////////////////////////////////////////// + + +void ECheckers::kingMove2(int from, int& resMax) +{ + board[from]=FREE; + + int i=from-6; + if(board[i]==FREE) { + board[i]=KING2; + turn(resMax); + board[i]=FREE; + } + + i=from-5; + if(board[i]==FREE) { + board[i]=KING2; + turn(resMax); + board[i]=FREE; + } + + i=from+5; + if(board[i]==FREE) { + board[i]=KING2; + turn(resMax); + board[i]=FREE; + } + + i=from+6; + if(board[i]==FREE) { + board[i]=KING2; + turn(resMax); + board[i]=FREE; + } + + board[from]=KING2; +} + + +bool ECheckers::checkCapture2() const +{ + for(int i=6;i<48;i++) + { + switch(board[i]) + { + case MAN2: + if(board[i+5]==MAN1 || board[i+5]==KING1) + if(board[i+10]==FREE) return true; + if(board[i+6]==MAN1 || board[i+6]==KING1) + if(board[i+12]==FREE) return true; + break; + case KING2: + if(board[i-6]==MAN1 || board[i-6]==KING1) + if(board[i-12]==FREE) return true; + if(board[i-5]==MAN1 || board[i-5]==KING1) + if(board[i-10]==FREE) return true; + if(board[i+5]==MAN1 || board[i+5]==KING1) + if(board[i+10]==FREE) return true; + if(board[i+6]==MAN1 || board[i+6]==KING1) + if(board[i+12]==FREE) return true; + } + } + return false; +} + + +// Return TRUE if it is possible to capture +// Return FALSE if it is impossible to capture +bool ECheckers::manCapture2(int from, int& resMax) +{ + bool capture=false; + + // try left-down + int i=from+5; + if(board[i]==MAN1 || board[i]==KING1) { + int k=from+10; + if(board[k]==FREE) { + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + resMax--; + + // become a king! + if(from>32) { + board[k]=KING2; + // aw?1 + turn(resMax, true); //aw??? + //aw??if(!kingCapture2(k, UL, resMax)) turn(resMax, true); + } else { + board[k]=MAN2; + if(!manCapture2(k, resMax)) turn(resMax, true); + } + + // restore + resMax++; + board[k]=FREE; + board[i]=save; + board[from]=MAN2; + capture=true; + } + } + + // now right-down + i=from+6; + if(board[i]==MAN1 || board[i]==KING1) { + int k=from+12; + if(board[k]==FREE) { + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + resMax--; + + // become a king! + if(from>32) { + board[k]=KING2; + // aw?1 + turn(resMax, true); // aw??? + //aw???if(!kingCapture2(k,UR,resMax)) turn(resMax,true); + } else { + board[k]=MAN2; + if(!manCapture2(k,resMax)) turn(resMax,true); + } + + // restore + resMax++; + board[k]=FREE; + board[i]=save; + board[from]=MAN2; + capture=true; + } + } + + if(capture) return true; + return false; +} + + +bool ECheckers::kingCapture2(int from, int direction, int &resMax) +{ + int i=from+direction; + if(board[i]==MAN1 || board[i]==KING1) + { + int k=i+direction; + if(board[k]==FREE) + { + bool capture=false; + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + resMax--; + + board[k]=KING2; + if(direction==UL || direction==DR) { + if(kingCapture2(k,UR,resMax)) capture=true; + if(kingCapture2(k,DL,resMax)) capture=true; + } else { + if(kingCapture2(k,UL,resMax)) capture=true; + if(kingCapture2(k,DR,resMax)) capture=true; + } + if(kingCapture2(k,direction,resMax)) capture=true; + + if(!capture) turn(resMax,true); + board[k]=FREE; + + //restore + resMax++; + board[i]=save; + board[from]=KING2; + return true; + } + } + return false; +} + + diff --git a/plugins/qcheckers_plugin/echeckers.h b/plugins/qcheckers_plugin/echeckers.h new file mode 100644 index 000000000..89d1da551 --- /dev/null +++ b/plugins/qcheckers_plugin/echeckers.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef ECHECKERS_H +#define ECHECKERS_H + +#include "checkers.h" +#include "pdn.h" + + +class ECheckers:public Checkers +{ +public: + virtual bool go1(int,int); + + + virtual int type() const { return ENGLISH; } + + virtual bool checkCapture1() const; + virtual bool checkCapture2() const; + +protected: + virtual bool checkCapture1(int) const; + +private: + void kingMove2(int,int &); + + bool manCapture1(int,int,bool &); + bool kingCapture1(int,int,bool &); + + bool manCapture2(int,int &); + bool kingCapture2(int,int,int &); + +}; + +#endif diff --git a/plugins/qcheckers_plugin/field.cc b/plugins/qcheckers_plugin/field.cc new file mode 100644 index 000000000..6006a5537 --- /dev/null +++ b/plugins/qcheckers_plugin/field.cc @@ -0,0 +1,150 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * Copyright (C) 2004-2005 Artur Wiebe + * wibix@gmx.de + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include "field.h" +#include "common.h" + + +Field::Field(QWidget* parent,int i) + : QWidget(parent) +{ + pixmap = new QPixmap(MAX_TILE_SIZE, MAX_TILE_SIZE); + + m_number=i; + + m_pattern=NULL; + m_checker=NULL; + m_frame=NULL; + + show_frame = false; + + m_show_label = true; +} + + +void Field::paintEvent(QPaintEvent*) +{ + QPainter p(this); + + p.drawPixmap(0, 0, *pixmap); + + p.end(); +} + + +void Field::mousePressEvent(QMouseEvent* me) +{ + if(me->button() != Qt::LeftButton) + return; + emit click(m_number); +} + + +void Field::draw() +{ + QPainter paint; + paint.begin(pixmap); + paint.setFont(font()); + + if(m_pattern) + paint.drawPixmap(0, 0, *m_pattern); + + // notation + paint.setPen(Qt::white); + QRect not_rect = paint.boundingRect(2, 2, 0, 0, Qt::AlignLeft, m_label); + if(m_show_above) { + if(m_checker) + paint.drawPixmap(0, 0, *m_checker); + if(m_show_label) { + paint.fillRect(not_rect, Qt::black); + paint.drawText(not_rect, Qt::AlignTop|Qt::AlignLeft, m_label); + } + } else { + if(m_show_label) + paint.drawText(not_rect, Qt::AlignTop|Qt::AlignLeft, m_label); + if(m_checker) + paint.drawPixmap(0, 0, *m_checker); + } + + if(show_frame) + paint.drawPixmap(0, 0, *m_frame); + + paint.end(); + update(); +} + + +void Field::setFrame(QPixmap* xpm) +{ + m_frame = xpm; +} + + +void Field::showFrame(bool b) +{ + if(show_frame != b) { + show_frame = b; + draw(); + } +} + + +void Field::setPicture(QPixmap* xpm) +{ + if(m_checker!=xpm) { + m_checker = xpm; + draw(); + } +} + + +void Field::setPattern(QPixmap* xpm) +{ + if(m_pattern != xpm) { + m_pattern = xpm; + draw(); + } +} + + +void Field::setLabel(const QString& str) +{ + if(m_label!=str) { + m_label=str; + draw(); + } +} + + +void Field::showLabel(bool s, bool a) +{ + if(s!=m_show_label || a!=m_show_above) { + m_show_above = a; + m_show_label = s; + draw(); + } +} + diff --git a/plugins/qcheckers_plugin/field.h b/plugins/qcheckers_plugin/field.h new file mode 100644 index 000000000..8e62d8af0 --- /dev/null +++ b/plugins/qcheckers_plugin/field.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef FIELD_H +#define FIELD_H + +#include +#include + + +class Field : public QWidget +{ + Q_OBJECT + +public: + Field(QWidget*, int num); + + const QString& label() const { return m_label; } + void setLabel(const QString&); + void showLabel(bool s, bool above); + + void showFrame(bool); + void setFrame(QPixmap*); + void setPicture(QPixmap*); + void setPattern(QPixmap*); + + int number() const { return m_number; } + + void fontUpdate() { draw(); } + +signals: + void click(int); + +protected: + + void paintEvent(QPaintEvent*); + void mousePressEvent(QMouseEvent*); + +private: + void draw(); + + int m_number; + + // pixmap = pattern + label + picture + frame; + + QPixmap* m_frame; + QPixmap* m_checker; + QPixmap* m_pattern; + + QString m_label; + bool m_show_label; + bool m_show_above; + + QPixmap* pixmap; + + bool show_frame; +}; + +#endif + + diff --git a/plugins/qcheckers_plugin/history.cc b/plugins/qcheckers_plugin/history.cc new file mode 100644 index 000000000..22303cffc --- /dev/null +++ b/plugins/qcheckers_plugin/history.cc @@ -0,0 +1,514 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "history.h" +#include "common.h" + + + +#define COL_TAG_NR 0 // m_tags, this col is hidden. +#define COL_TAG_NAME 1 +#define COL_TAG_VAL 2 + +#define COL_MOVE_NR 0 // m_movelist +#define COL_MOVE 1 +#define COL_MOVE_COMM 2 + + +myHistory::myHistory(QWidget* parent) + : QFrame(parent) +{ + setFixedWidth(240); + + m_gamelist = new QComboBox(this); + connect(m_gamelist, SIGNAL(activated(int)), + this, SLOT(slot_game_selected(int))); + + m_taglist = new QTreeWidget(this); + m_taglist->setColumnCount(3); + m_taglist->header()->hide(); + m_taglist->setColumnHidden(COL_TAG_NR, true); +// m_taglist->header()->setStretchLastSection(true); +// m_taglist->header()->setResizeMode(QHeaderView::Stretch); + m_taglist->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + connect(m_taglist, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), + this, SLOT(slot_modify_tag(QTreeWidgetItem*, int))); + + m_movelist = new QTreeWidget(this); + m_movelist->setColumnCount(3); + m_movelist->header()->setStretchLastSection(true); + m_movelist->header()->setMovable(false); + m_movelist->setRootIsDecorated(false); + QStringList header; + header << "#" << tr("Move") << tr("Comment"); + m_movelist->setHeaderLabels(header); + // + connect(m_movelist, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), + this, SLOT(slot_modify_comment(QTreeWidgetItem*, int))); + connect(m_movelist, + SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), + this, + SLOT(slot_move(QTreeWidgetItem*, QTreeWidgetItem*))); + + // history + /* + gameUndo = new QAction(QIcon(":/icons/undo.png"), tr("&Undo"), this); + connect(gameUndo, SIGNAL(triggered()), m_view, SLOT(slotUndo())); + + gameRedo = new QAction(QIcon(":/icons/redo.png"), tr("&Redo"), this); + connect(gameRedo, SIGNAL(triggered()), m_view, SLOT(slotRedo())); + + gameContinue = new QAction(QIcon(":/icons/continue.png"), + tr("&Continue"), this); + connect(gameContinue, SIGNAL(triggered()), m_view, SLOT(slotContinue())); + + + */ + m_mode_icon = new QLabel(this); + m_mode_icon->setFrameStyle(QFrame::Panel | QFrame::Sunken); + + m_undo = new QToolButton(this); + m_undo->setIcon(QIcon(":/icons/undo.png")); + m_undo->setToolTip(tr("Undo")); + connect(m_undo, SIGNAL(clicked()), this, SLOT(slot_undo())); + + m_redo = new QToolButton(this); + m_redo->setIcon(QIcon(":/icons/redo.png")); + m_redo->setToolTip(tr("Redo")); + connect(m_redo, SIGNAL(clicked()), this, SLOT(slot_redo())); + + m_cont = new QToolButton(this); + m_cont->setIcon(QIcon(":/icons/continue.png")); + m_cont->setToolTip(tr("Continue")); + connect(m_cont, SIGNAL(clicked()), this, SLOT(slot_continue())); + + m_current = new QLabel(this); + + QHBoxLayout* history = new QHBoxLayout(); + history->addWidget(m_mode_icon); +//TODO history->addStretch(); + history->addWidget(m_undo); + history->addWidget(m_redo); + history->addWidget(m_cont); + history->addStretch(); + history->addWidget(m_current); + + // layout + QVBoxLayout* vb = new QVBoxLayout(this); + vb->setMargin(0); + vb->addWidget(m_gamelist, 0); + vb->addWidget(m_taglist, 2); + vb->addWidget(m_movelist, 4); + vb->addLayout(history); + + /* + * other stuff + */ + m_pdn = new Pdn(); + m_disable_moves = false; + // + m_paused = true; // little hack ensures a mode change. + m_freeplace = false; + set_mode(false); +} + + +myHistory::~myHistory() +{ + delete m_pdn; +} + + +void myHistory::clear() +{ + m_gamelist->clear(); + m_pdn->clear(); + m_taglist->clear(); + m_movelist->clear(); +} + + +void myHistory::setTag(PdnGame::Tag tag, const QString& val) +{ + QTreeWidgetItem* item = 0; + QList item_list = m_taglist->findItems( + tag_to_string(tag), Qt::MatchExactly, COL_TAG_NAME); + if(item_list.count()) { + if(item_list.count() == 1) + item = item_list[0]; + else + qDebug() << __PRETTY_FUNCTION__ << "ERR"; + } + + if(item) { + item->setText(COL_TAG_VAL, val); + } else { + item = new QTreeWidgetItem(m_taglist); + item->setText(COL_TAG_NR, QString::number(tag)); + item->setText(COL_TAG_NAME, tag_to_string(tag)); + item->setText(COL_TAG_VAL, val); + } + + if(tag==PdnGame::Type) { + item->setText(COL_TAG_VAL, val + " (" + + typeToString(QString("%1").arg(val).toInt()) + + ")"); + } + + m_game->set(tag, val); +//TODO m_taglist->resizeColumnToContents(COL_TAG_NAME); +} + + +QString myHistory::getTag(PdnGame::Tag tag) +{ + QList item_list = m_taglist->findItems( + tag_to_string(tag), Qt::MatchExactly, COL_TAG_NAME); + if(item_list.count() == 1) + return item_list[0]->text(COL_TAG_VAL); + return ""; +} + + +QString myHistory::tag_to_string(PdnGame::Tag tag) +{ + switch(tag) { + case PdnGame::Date: return /*tr(*/"Date";//); + case PdnGame::Site: return /*tr(*/"Site";//); + case PdnGame::Type: return /*tr(*/"Type";//); + case PdnGame::Event: return /*tr(*/"Event";//); + case PdnGame::Round: return /*tr(*/"Round";//); + case PdnGame::White: return /*tr(*/"White";//); + case PdnGame::Black: return /*tr(*/"Black";//); + case PdnGame::Result: return /*tr(*/"Result";//); + } + + return "Site"; // FIXME +} + + +void myHistory::appendMove(const QString& text, const QString& comm) +{ + m_disable_moves = true; + + QTreeWidgetItem* new_item = new QTreeWidgetItem(m_movelist); + new_item->setText(COL_MOVE, text); + new_item->setText(COL_MOVE_COMM, comm); + + int move_nr = (m_movelist->topLevelItemCount() - 2) / 2; + PdnMove* m = m_game->getMove(move_nr); + + if(m_movelist->topLevelItemCount()%2) { + m->m_second = text; + m->m_comsecond = comm; + } else { + new_item->setText(COL_MOVE_NR, QString("%1.").arg(move_nr+1)); + m->m_first = text; + m->m_comfirst = comm; + } + + m_movelist->setCurrentItem(new_item); + m_movelist->scrollToItem(new_item); + + // TODO + m_movelist->resizeColumnToContents(COL_MOVE_NR); + + m_disable_moves = false; +} + + +void myHistory::slot_modify_comment(QTreeWidgetItem* item, int) +{ + if(!item || item==m_movelist->topLevelItem(0) || m_paused) + return; + + bool ok; + QString new_text = QInputDialog::getText(this, tr("Set Comment"),//FIXME + tr("Comment")+":", QLineEdit::Normal, item->text(COL_MOVE_COMM), + &ok); + if(!ok) + return; + + new_text.remove('{'); + new_text.remove('}'); + if(new_text != item->text(COL_MOVE_COMM)) { + // gui + item->setText(COL_MOVE_COMM, new_text); + + // pdn + int index = m_movelist->indexOfTopLevelItem(item); + PdnMove* move = m_game->getMove((index - 1) / 2); + if(index%2==1) + move->m_comfirst = new_text; + else + move->m_comsecond = new_text; + } +} + + +void myHistory::slot_modify_tag(QTreeWidgetItem* item, int/* col*/) +{ + if(!item || m_paused) + return; + + PdnGame::Tag tag =(PdnGame::Tag)item->text(COL_TAG_NR).toUInt(); + if(tag==PdnGame::Type) { + return; + } + + bool ok; + QString new_text = QInputDialog::getText(this, tr("Set Tag"),//FIXME + tr("Tag")+":", QLineEdit::Normal, item->text(COL_TAG_VAL), &ok); + if(!ok) + return; + + new_text.remove('"'); + new_text.remove('['); + new_text.remove(']'); + + if(new_text != item->text(COL_TAG_VAL)) { + item->setText(COL_TAG_VAL, new_text); + m_game->set(tag, new_text); + if(tag==PdnGame::Event) + m_gamelist->setItemText(m_gamelist->currentIndex(), + new_text); + } +} + + +bool myHistory::openPdn(const QString& filename, QString& log_text) +{ + if(!m_pdn->open(filename, this, tr("Reading file..."), log_text)) { + set_mode(false); + return false; + } + + set_mode(true); + + m_gamelist->clear(); + m_movelist->clear(); + m_taglist->clear(); + + QProgressDialog progress(this); + progress.setModal(true); + progress.setLabelText(tr("Importing games...")); + progress.setRange(0, m_pdn->count()); + progress.setMinimumDuration(0); + + for(int i=0; icount(); ++i) { + if((i%10)==0) + progress.setValue(i); + m_gamelist->insertItem(i, m_pdn->game(i)->get(PdnGame::Event)); + } + + slot_game_selected(0); + + return true; +} + + +bool myHistory::savePdn(const QString& fn) +{ + return m_pdn->save(fn); +} + + +void myHistory::slot_game_selected(int index) +{ + if(index>=m_pdn->count()) { + qDebug() << __PRETTY_FUNCTION__ << "Index" << index + << "out of range >=" << m_pdn->count(); + return; + } + + m_game = m_pdn->game(index); + m_movelist->clear(); + + QTreeWidgetItem* root = new QTreeWidgetItem(m_movelist); + for(int i=0; imovesCount(); ++i) { + PdnMove* m = m_game->getMove(i); + + appendMove(m->m_first, m->m_comfirst); + if(m->m_second.length()) + appendMove(m->m_second, m->m_comsecond); + } + + setTag(PdnGame::Site, m_game->get(PdnGame::Site)); + setTag(PdnGame::Black, m_game->get(PdnGame::Black)); + setTag(PdnGame::White, m_game->get(PdnGame::White)); + setTag(PdnGame::Result, m_game->get(PdnGame::Result)); + setTag(PdnGame::Date, m_game->get(PdnGame::Date)); + setTag(PdnGame::Site, m_game->get(PdnGame::Site)); + setTag(PdnGame::Type, m_game->get(PdnGame::Type)); + setTag(PdnGame::Round, m_game->get(PdnGame::Round)); + setTag(PdnGame::Event, m_game->get(PdnGame::Event)); + + // signal to view + if(m_paused && !m_freeplace) { + emit previewGame(m_game->get(PdnGame::Type).toInt()); + } + + m_movelist->setCurrentItem(root); + slot_move(root, 0); +} + + +void myHistory::newPdn(const QString& event, bool freeplace) +{ + m_freeplace = freeplace; + m_paused = !m_freeplace; // FIXME - needed to force view update. + set_mode(m_freeplace); + + PdnGame* game = m_pdn->newGame(); + game->set(PdnGame::Event, event); + + int index = m_gamelist->count(); + m_gamelist->insertItem(index, event); + m_gamelist->setCurrentIndex(index); + + slot_game_selected(index); +} + + +QString myHistory::typeToString(int type) +{ + switch(type) { + case ENGLISH: return tr("English draughts"); + case RUSSIAN: return tr("Russian draughts"); + }; + return tr("Unknown game type"); +} + + +void myHistory::set_mode(bool paused) +{ + if(m_paused != paused) { + m_paused = paused; + + if(m_paused) { + if(m_freeplace) { + m_mode_icon->setPixmap(QPixmap(":/icons/freeplace.png")); + m_mode_icon->setToolTip(tr("Free Placement Mode")); + } else { + m_mode_icon->setPixmap(QPixmap(":/icons/paused.png")); + m_mode_icon->setToolTip(tr("Paused Mode")); + } + } else { + m_mode_icon->setPixmap(QPixmap(":/icons/logo.png")); + m_mode_icon->setToolTip(tr("Play Mode")); + } + + m_gamelist->setEnabled(m_paused); + //FIXME m_movelist->setEnabled(yes); + + emit newMode(m_paused, m_freeplace); + } +} + + +void myHistory::slot_move(QTreeWidgetItem* item, QTreeWidgetItem*) +{ + // update history buttons. + bool curr_is_first = + (m_movelist->topLevelItem(0) == m_movelist->currentItem()); + bool curr_is_last = + (m_movelist->indexOfTopLevelItem(m_movelist->currentItem()) + == m_movelist->topLevelItemCount()-1); + + m_undo->setEnabled(!curr_is_first); + m_redo->setEnabled(!curr_is_last); + m_cont->setEnabled(m_paused); + + + // process + if(!item || !m_paused || m_disable_moves) + return; + + do_moves(); +} + + +void myHistory::history_undo(bool move_backwards) +{ + int next = m_movelist->indexOfTopLevelItem(m_movelist->currentItem()) + + (move_backwards ? -1 : +1); + + if(next>=0 && nexttopLevelItemCount()) + m_movelist->setCurrentItem(m_movelist->topLevelItem(next)); +} + + +void myHistory::do_moves() +{ + QString moves; + QTreeWidgetItem* item = m_movelist->currentItem(); + for(int i=0; itopLevelItemCount(); ++i) { + QTreeWidgetItem* cur = m_movelist->topLevelItem(i); + moves += cur->text(COL_MOVE) + MOVE_SPLIT; + if(m_movelist->topLevelItem(i)==item) + break; + } + emit applyMoves(moves); +} + + +void myHistory::delete_moves() +{ + int curr = m_movelist->indexOfTopLevelItem(m_movelist->currentItem()); + while(m_movelist->topLevelItemCount() > curr+1) { + delete m_movelist->topLevelItem( + m_movelist->topLevelItemCount()-1); + } +} + + +void myHistory::slot_undo() +{ + set_mode(true); + history_undo(true); + do_moves(); +} + +void myHistory::slot_redo() +{ + set_mode(true); + history_undo(false); + do_moves(); +} + + +void myHistory::slot_continue() +{ + delete_moves(); + set_mode(false); +} + + +void myHistory::slotWorking(bool b) +{ + setEnabled(!b); +} + diff --git a/plugins/qcheckers_plugin/history.h b/plugins/qcheckers_plugin/history.h new file mode 100644 index 000000000..8ca495fd4 --- /dev/null +++ b/plugins/qcheckers_plugin/history.h @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef _HISTORY_H_ +#define _HISTORY_H_ + + +#include +#include +#include +#include +#include + +#include "pdn.h" + + +#define MOVE_SPLIT '#' + + +class myHistory : public QFrame +{ + Q_OBJECT + +public: + myHistory(QWidget* parent); + ~myHistory(); + + void newPdn(const QString& event, bool freeplace); + bool openPdn(const QString& filename, QString& log_text); + bool savePdn(const QString& fn); + + void clear(); + + bool isPaused() const { return m_paused; } + bool isFreePlacement() const { return m_freeplace; } + + void setTag(PdnGame::Tag, const QString& val); + QString getTag(PdnGame::Tag); + + void appendMove(const QString& move, const QString& comment); + // FIXME - provide a function that returns who is next, black or white. + int moveCount() const { return m_movelist->topLevelItemCount()-1; } + + static QString typeToString(int type); + + void setCurrent(const QString& t) { m_current->setText(t); } + +signals: + void previewGame(int game_type); + void applyMoves(const QString& moves); + void newMode(bool paused, bool freeplace); + +public slots: + void slotWorking(bool); + +private slots: + void slot_move(QTreeWidgetItem*, QTreeWidgetItem*); + void slot_game_selected(int index); + void slot_modify_tag(QTreeWidgetItem* item, int col); + void slot_modify_comment(QTreeWidgetItem* item, int col); + + void slot_undo(); + void slot_redo(); + void slot_continue(); + +private: + QString tag_to_string(PdnGame::Tag); + void set_mode(bool); + + void do_moves(); + void history_undo(bool move_backwards); + void delete_moves(); + + +private: + QTreeWidget* m_taglist; + QTreeWidget* m_movelist; + QComboBox* m_gamelist; + Pdn* m_pdn; + PdnGame* m_game; + + bool m_paused; + bool m_freeplace; + bool m_disable_moves; + + QToolButton* m_undo; + QToolButton* m_redo; + QToolButton* m_cont; + + QLabel* m_mode_icon; + QLabel* m_current; +}; + + +#endif + diff --git a/plugins/qcheckers_plugin/humanplayer.cc b/plugins/qcheckers_plugin/humanplayer.cc new file mode 100644 index 000000000..31e50a108 --- /dev/null +++ b/plugins/qcheckers_plugin/humanplayer.cc @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "humanplayer.h" +#include "rcheckers.h" +#include "echeckers.h" +#include "pdn.h" + + +myHumanPlayer::myHumanPlayer(const QString& name, bool white, + bool second_player) + : myPlayer(name, white) +{ + selected = false; + + m_second = second_player; + m_game = 0; +} + + +myHumanPlayer::~myHumanPlayer() +{ +} + + +void myHumanPlayer::yourTurn(const Checkers* g) +{ + if(!m_game || m_game->type()!=g->type()) { + delete m_game; + if(g->type()==RUSSIAN) + m_game = new RCheckers(); + else + m_game = new ECheckers(); + } + + // synchronize + m_game->fromString(g->toString(m_second)); +} + + +bool myHumanPlayer::fieldClicked(int field_num, bool* select, QString& errmsg) +{ + if(m_second) + field_num = 31 - field_num; + + switch(m_game->item(field_num)) { + case MAN1: + case KING1: + if(m_game->checkCapture1() && !m_game->canCapture1(field_num)) { + errmsg = tr("You must capture."); //TODO better text. + return false; + } + if(!m_game->canCapture1(field_num) && !m_game->canMove1(field_num)) { + errmsg = tr("Cannot move this."); //TODO better text. + return false; + } + + // Player (re)selects + from = field_num; + fromField = field_num; + selected = true; + *select = true; + return true; + break; + + case FREE: + if(!selected) + return true; + + if(!go(field_num)) + return false; // incorrect course + + // move done - unselect + if(selected) + *select = false; + selected = false; + + emit moveDone(m_game->toString(m_second)); + break; + + default: + break; + } + + return true; +} + + +bool myHumanPlayer::go(int to) +{ + return m_game->go1(from, to); +} + diff --git a/plugins/qcheckers_plugin/humanplayer.h b/plugins/qcheckers_plugin/humanplayer.h new file mode 100644 index 000000000..807f6bc91 --- /dev/null +++ b/plugins/qcheckers_plugin/humanplayer.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _HUMANPLAYER_H_ +#define _HUMANPLAYER_H_ + +#include "player.h" + +#include + + +class myHumanPlayer : public myPlayer +{ + Q_OBJECT + +public: + // when playing player vs. player on same computer. the second + // player must invert some things. + myHumanPlayer(const QString& name, bool white, bool second_player); + ~myHumanPlayer(); + + virtual void yourTurn(const Checkers* game); + virtual bool fieldClicked(int fieldnumber, bool*, QString& err_msg); + virtual void stop() {} + + virtual bool isHuman() const { return true; } + + +public slots: +// virtual void getReady() { emit readyToPlay(); } + +private: + bool go(int fieldnumber); + +private: + bool m_second; + + Checkers* m_game; + bool selected; + + int from; // on Checkers board + int fromField; // on GUI board +}; + + +#endif + diff --git a/plugins/qcheckers_plugin/i18n/kcheckers_de.qm b/plugins/qcheckers_plugin/i18n/kcheckers_de.qm new file mode 100644 index 000000000..50c459474 Binary files /dev/null and b/plugins/qcheckers_plugin/i18n/kcheckers_de.qm differ diff --git a/plugins/qcheckers_plugin/i18n/kcheckers_de.ts b/plugins/qcheckers_plugin/i18n/kcheckers_de.ts new file mode 100644 index 000000000..2dd665fc6 --- /dev/null +++ b/plugins/qcheckers_plugin/i18n/kcheckers_de.ts @@ -0,0 +1,611 @@ + + + myHistory + + Move + Zug + + + Comment + Kommentar + + + Undo + Rückgängig + + + Redo + Wiederholen + + + Continue + Fortsetzen + + + Set Comment + Setze Kommentar + + + Set Tag + Setze Tag + + + Tag + Tag + + + Reading file... + Lese Datei... + + + Importing games... + Importiere Spiele... + + + English draughts + Englische Regeln + + + Russian draughts + Russische Regeln + + + Unknown game type + Unbekannter Spieltyp + + + Free Placement Mode + Platzieren-Modus + + + Paused Mode + Pause-Modus + + + Play Mode + Spiel-Modus + + + + myHumanPlayer + + You must capture. + Sie müssen Schlagen. + + + Unmovable. + Unbewegbar. + + + you must capture + Sie müssen Schlagen + + + unmovable + unbewegbar + + + Cannot move this. + Kann nicht bewegen. + + + + myInfo + + Move + Zug + + + Comment + Kommentar + + + White + Weiß + + + Black + Schwarz + + + English draughts + Englische Regeln + + + Russian draughts + Russische Regeln + + + Unknown game type + Unbekannter Spieltyp + + + Importing games... + Importiere Spiele... + + + Reading file... + Lese Datei... + + + Continue + Fortsetzen + + + Previous + Zurück + + + Next + Vor + + + Undo + Rückgängig + + + Redo + Wiederholen + + + Set Comment + Setze Kommentar + + + Set Tag + Setze Tag + + + Free Placement Mode + Platzieren-Modus + + + Paused Mode + Pause-Modus + + + Play Mode + Spiel-Modus + + + Tag + Tag + + + + myNewGameDlg + + New Game + Neues Spiel + + + Rules + Regeln + + + Skill + Schwierigkeitsgrad + + + Beginner + Anfänger + + + Novice + Novize + + + Average + Durchschnitt + + + Good + Gut + + + Expert + Experte + + + Master + Meister + + + Accept + Akzeptieren + + + Address: + Adresse: + + + Servername: + Servername: + + + Serverinfo: + Serverinfo: + + + &Start + &Starten + + + &Cancel + A&bbrechen + + + Wait... + Warte... + + + Waiting for client to connect... + Warte auf Netzwerkspieler... + + + Waiting for server to accept... + Warte auf Serverbestätigung... + + + Server denied. + Server lehnt ab. + + + Connection aborted. + Verbindung getrennt. + + + Human + Mensch + + + Player One + Spieler Eins + + + White + Weiß + + + Player Two + Spieler Zwei + + + Computer + Computer + + + Network - New Game + Netzwerk - Neues Spiel + + + Network - Join Game + Netzwerk - Spiel betreten + + + Server + Server + + + Could not create a game on the server. + Konnte kein Spiel auf dem Server erstellen. + + + Could not join the game. + Konnte dem Spiel nicht beitreten. + + + Client connected. + Mit dem Client verbunden. + + + Client disconnected. + Client hat sich verabschiedet. + + + Free Men Placement + Freies Platzieren der Figuren + + + + myTopLevel + + &New... + &Neu... + + + CTRL+N + File|New + CTRL+N + + + &Next Round + &Nächste Runde + + + &Stop + &Stopp + + + &Undo Move + &Zug rückgängig + + + CTRL+Z + File|Undo + CTRL+Z + + + &Information + &Information + + + &Open... + &Öffnen... + + + CTRL+O + File|Open + CTRL+O + + + &Save... + &Speichern... + + + CTRL+S + File|Save + CTRL+S + + + &Quit + &Beenden + + + CTRL+Q + File|Quit + CTRL+Q + + + &Show Notation + &Zeige Notation + + + &Green Board + &Grünes Brett + + + &Marble Board + &Rotes Brett + + + &Wooden Board + &Hölzernes Brett + + + &Console + &Konsole + + + What's This + Was ist das + + + SHIFT+F1 + Help|WhatsThis + SHIFT+F1 + + + &Rules of Play + &Spielregeln + + + F1 + Help|Help + F1 + + + About &Qt + Über &Qt + + + &Game + &Spiel + + + &View + &Ansicht + + + &Settings + &Einstellungen + + + &Help + &Hilfe + + + Error + Fehler + + + &Close + &Schließen + + + Save Game + Spiel speichern + + + Could not save: + Konnte nicht speichern: + + + Open Game + Spiel laden + + + Could not load: + Konnte nicht öffnen: + + + Game Info + Spielinfo + + + Rules of Play + Spielregeln + + + About + Über + + + Current game will be lost if you continue. +Do you really want to discard it? + Das aktuelle Spiel geht verloren, wenn Sie fortfahren. +Wollen sie es wirklich verwerfen? + + + Abort Game? + Spiel abbrechen? + + + <p>In the beginning of game you have 12 checkers (men). White always moves first. The men move forward only. The men can capture:<ul><li>by jumping forward only (english rules);<li>by jumping forward or backward (russian rules).</ul><p>A man which reaches the far side of the board becomes a king. The kings move forward or backward:<ul><li>to one square only (english rules);<li>to any number of squares (russian rules).</ul><p>The kings capture by jumping forward or backward. Whenever a player is able to make a capture he must do so. + <p>Sie beginnen mit 12 Steinen. Weiß beginnt das Spiel. Sie können die Steine nur nach vorne bewegen. Diese können andere Steine schlagen:<ul><li>indem sie nur nach vorne springen (Englische Regeln);<li>indem sie sowohl nach vorn als auch nach hinten springen (Russische Regeln).</ul><p>Ein Stein der die gegenüberliegende Seite erreicht, wird zur Dame.Die Dame bewegt sich sowohl vorwärts als auch rückwärts:<ul><li>immer nur ein Feld pro Zug (Englische Regeln);<li>beliebig viele Felder pro Zug (Russische Regeln).</ul><p>Die Dame kann vor-/ und rückwärts schlagen. Schlagen ist Pflicht. + + + &Confirm aborting current game + &Bestätige Abbrechen des laufenden Spiels + + + &Open console on new messages + &Öffne Konsole beim Entreiffen neues Nachrichten + + + &Small board + &Kleines Brett + + + &Big board + &Großes Brett + + + &About + &Über + + + Show notation &above + Zeige Notation &über + + + &Notation font... + &Notationsschrift... + + + <p>In the beginning of game you have 12 checkers (men). The men move forward only. The men can capture:<ul><li>by jumping forward only (english rules);<li>by jumping forward or backward (russian rules).</ul><p>A man which reaches the far side of the board becomes a king. The kings move forward or backward:<ul><li>to one square only (english rules);<li>to any number of squares (russian rules).</ul><p>The kings capture by jumping forward or backward. Whenever a player is able to make a capture he must do so. + <p>Sie beginnen mit 12 Steinen. Sie können die Steine nur nach vorne bewegen. Diese können andere Steine schlagen:<ul><li>indem sie nur nach vorne springen (Englische Regeln);<li>indem sie sowohl nach vorn als auch nach hinten springen (Russische Regeln).</ul><p>Ein Stein der die gegenüberliegende Seite erreicht, wird zur Dame.Die Dame bewegt sich sowohl vorwärts als auch rückwärts:<ul><li>immer nur ein Feld pro Zug (Englische Regeln);<li>beliebig viele Felder pro Zug (Russische Regeln).</ul><p>Die Dame kann vor-/ und rückwärts schlagen. Schlagen ist Pflicht. + + + File already exists. +Do you really want to override it? + Die Datei existiert bereits. +Wollen Sie sie wirklich überschreiben? + + + Clear &log on new round + Lösche &Log bei Rundenbeginn + + + Shift+/ + Shift+/ + + + Show notation &above men + Zeige Notation &über Spielsteinen + + + &Toolbar + &Toolleiste + + + + myView + + Go! + Los! + + + Game aborted. + Spiel abgebrochen. + + + Connection closed. + Verbundung getrennt. + + + Drawn game. + Unentschieden. + + + Invalid move. + Ungültiger Zug. + + + Waiting for opponent to move... + Warte auf Gegenspieler... + + + White wins! + Weiß gewinnt! + + + Black wins! + Schwarz gewinnt! + + + White + Weiß + + + Black + Schwarz + + + Invalid move + Ungültiger Zug + + + It's not your turn. + Du bist nicht am Zug. + + + opponent + Gegner + + + Warning! Some errors occured. + Warnung! Es sind Fehler aufgetreten. + + + Preview mode + Vorschau-Modus + + + Syntax error. Usage: /from-to + Syntaxfehler. Gebrauch: /von-nach + + + Saved: + Gespeichert: + + + Opened: + Geöffnet: + + + Play mode + Spiel-Modus + + + diff --git a/plugins/qcheckers_plugin/i18n/kcheckers_fr.qm b/plugins/qcheckers_plugin/i18n/kcheckers_fr.qm new file mode 100644 index 000000000..769e705ae Binary files /dev/null and b/plugins/qcheckers_plugin/i18n/kcheckers_fr.qm differ diff --git a/plugins/qcheckers_plugin/i18n/kcheckers_fr.ts b/plugins/qcheckers_plugin/i18n/kcheckers_fr.ts new file mode 100644 index 000000000..068641a70 --- /dev/null +++ b/plugins/qcheckers_plugin/i18n/kcheckers_fr.ts @@ -0,0 +1,570 @@ + + + myHistory + + Move + Déplacer + + + Comment + Commentaire + + + Undo + Annuler + + + Redo + Refaire + + + Continue + Continuer + + + Set Comment + Définir le Commentaire + + + Set Tag + Définir le Tag + + + Tag + Tag + + + Reading file... + Lecture du fichier en cours... + + + Importing games... + Importe les jeux... + + + English draughts + Dames anglaises + + + Russian draughts + Dames russes + + + Unknown game type + Type de jeu inconnu + + + Free Placement Mode + Mode de Placement Libre + + + Paused Mode + Mode Pause + + + Play Mode + Mode Jeu + + + + myHumanPlayer + + Go! + Commencer ! + + + Incorrect course. + Mouvement impossible. Peut-être une capture est-elle possible ? + + + You must capture. + Vous devez capturer. + + + Cannot move this. + Impossible de déplacer cet élément. + + + + myInfo + + Move + Déplacer + + + Comment + Commentaire + + + Undo + Annuler + + + Redo + Refaire + + + Continue + Continuer + + + Set Comment + Définir le Commentaire + + + Set Tag + Définir le Tag + + + Reading file... + Lecture du fichier en cours... + + + Importing games... + Importe les jeux... + + + English draughts + Dames anglaises + + + Russian draughts + Dames russes + + + Unknown game type + Type de jeu inconnu + + + Free Placement Mode + Mode de Placement Libre + + + Paused Mode + Mode Pause + + + Play Mode + Mode Jeu + + + Tag + Tag + + + + myNewGameDlg + + New Game + Nouveau Jeu + + + Against CPU on this PC + Contre l'ordinateur local + + + Against Human on Network - New Game + Contre un humain en réseau - Nouvelle partie + + + Against Human on Network - Join Game + Contre un humain en réseau - Joindre une partie + + + Rules + Règles + + + English + Anglaises + + + Russian + Russes + + + Skill + Niveau de difficulté + + + Beginner + Débutant + + + Novice + Novice + + + Average + Moyen + + + Good + Bon + + + Expert + Expert + + + Master + Maître + + + Server IP: + IP du serveur: + + + Pick free port + Prendre un port libre + + + &Start + &Commencer + + + &Cancel + &Annuler + + + Human + Humain + + + Player One + Joueur Un + + + White + Blancs + + + Player Two + Joueur Deux + + + Computer + Ordinateur + + + Free Men Placement + Placement des Pions Libre + + + + myTopLevel + + &New... + &Nouveau... + + + CTRL+N + File|New + CTRL+N + + + &Next Round + Niveau &Suivant + + + &Stop + &Arrêter + + + &Undo Move + &Annuler le mouvement + + + CTRL+Z + File|Undo + CTRL+Z + + + &Information + &Information + + + &Open... + &Ouvrir... + + + CTRL+O + File|Open + CTRL+O + + + &Save... + &Enregistrer... + + + CTRL+S + File|Save + CTRL+S + + + &Quit + &Quitter + + + CTRL+Q + File|Quit + CTRL+Q + + + &Show Notation + &Afficher la notation + + + &Green Board + &Plateau vert + + + &Marble Board + &Plateau marbré + + + &Wooden Board + &Plateau en bois + + + What's This + Qu'est ce que c'est ? + + + SHIFT+F1 + Help|WhatsThis + SHIFT+F1 + + + &Rules of Play + &Règles du jeu + + + F1 + Help|Help + F1 + + + &About + À &propos + + + About &Qt + À propos de &Qt + + + &Game + &Jeu + + + &View + &Afficher + + + &Settings + &Configurer KCheckers + + + &Help + &Aide + + + Error + Erreur + + + &Close + &Fermer + + + Save Game + Enregistrer la Partie + + + Could not save: + Impossible d'enregistrer : + + + Open Game + Charger une Partie + + + Could not load: + Impossible d'ouvrir: + + + Game Info + Informations sur la partie + + + Rules of Play + Règles de jeu + + + About + À propos + + + Quit Game? + Quitter la partie ? + + + Current game will be lost if you continue. +Do you really want to discard it? + La partie en cours sera perdue si vous continuez. +Voulez-vous vraiment l'abandonner ? + + + Abort Game? + Abandonner la partie ? + + + &Confirm aborting current game + &Confirmer l'abandon de la partie + + + &About + &À Propos + + + Show notation &above men + Afficher la notation &au dessus des pions + + + Clear &log on new round + Nettoyer le &log au niveau niveau + + + &Notation font... + Fonte pour la &notation... + + + &Toolbar + &Barre d'outils + + + <p>In the beginning of game you have 12 checkers (men). The men move forward only. The men can capture:<ul><li>by jumping forward only (english rules);<li>by jumping forward or backward (russian rules).</ul><p>A man which reaches the far side of the board becomes a king. The kings move forward or backward:<ul><li>to one square only (english rules);<li>to any number of squares (russian rules).</ul><p>The kings capture by jumping forward or backward. Whenever a player is able to make a capture he must do so. + <p>Au début vous avez 12 pions. Les pions peuvent se déplacer uniquement en avant. Ils peuvent capturer :<ul><li>en sautant en avant seulement (règles anglaises),<li>en sautant en avant ou en arrière (règles russes).</ul><p>Un pion qui arrive du côté adverse du plateau devient une dame. Les dames peuvent se déplacer en avant ou en arrière :<ul><li>d'une seule case (règles anglaises),<li>de plusieurs cases (règles russes).</ul><p>Les dames peuvent capturer en sautant en avant ou en arrière. Quand une capture est possible, elle doit obligatoirement être exécutée. + + + + + myView + + Go! + Commencer ! + + + You have lost. Game over. + Vous avez perdu. Fin de la partie. + + + Congratulation! You have won! + Félicitations ! Vous avez gagné ! + + + I am thinking... + Je pense... + + + Waiting network player to move... + En attente du mouvement du joueur distant... + + + Incorrect course. + Mouvement impossible. Peut-être une capture est-elle possible ? + + + Waiting for network player to connect... + En attente de la connexion du joueur distant... + + + Waiting for server to reply... + En attente de la réponse du serveur... + + + Game aborted. + Partie abandonnée. + + + ENGLISH rules. + Règles ANGLAISES. + + + RUSSIAN rules. + Règles RUSSES. + + + +New Network Game + +Nouvelle partie en réseau + + + +Join Network Game + +Rejoindre une partie en réseau + + + Unknown rules. Playing current rules: + Règles inconnues. Adopte les règles courantes : + + + Unknown skill. Keeping current skill: + Niveau inconnu. Conserve le niveau courant : + + + Player + Le joueur + + + is played by KCheckers with current skill: + est controllé par KCheckers avec le niveau courant : + + + This is not implemented yet. + Ceci n'est pas encore implémenté. + + + Please consider Information mismatch. + Veuillez considérer que les informations sont discordantes. + + + Russian + Russes + + + Drawn game. + Match nul. + + + Invalid move. + Mouvement invalide. + + + White wins! + Les blancs gagnent ! + + + Black wins! + Les noirs gagnent ! + + + opponent + adversaire + + + Opened: + Ouvert : + + + Warning! Some errors occured. + Attention ! Des erreurs sont survenues. + + + Saved: + Enregistré : + + + diff --git a/plugins/qcheckers_plugin/i18n/kcheckers_ru.ts b/plugins/qcheckers_plugin/i18n/kcheckers_ru.ts new file mode 100644 index 000000000..222ecdbff --- /dev/null +++ b/plugins/qcheckers_plugin/i18n/kcheckers_ru.ts @@ -0,0 +1,545 @@ + + + PdnPreview + + White + Белые + + + Black + Черные + + + Open board only + Показывать доску + + + No preview available. + Предпросмотр невозможен. + + + English draughts + Английские чекерсы + + + Russian draughts + Русские шашки + + + Unknown game type + Правила неизвестны + + + + myConsole + + Clear + Очистить + + + Save + Сохранить + + + Save Console + Сохранить команды + + + + myHumanPlayer + + You must capture. + Вы должны бить. + + + Unmovable. + Нет хода. + + + Cannot move this. + Нет хода. + + + + myInfo + + White + Белые + + + Black + Черные + + + English draughts + Английские чекерсы + + + Russian draughts + Русские шашки + + + Unknown game type + Правила неизвестны + + + Importing games... + + + + Reading file... + + + + Continue + + + + Move + + + + Comment + + + + Undo + + + + Redo + + + + Set Comment + + + + Set Tag + + + + Free Placement Mode + + + + Paused Mode + + + + Play Mode + + + + Tag + + + + + myNewGameDlg + + New Game + Новая игра + + + Rules + Правила + + + Skill + Уровень + + + Beginner + Подготовительный + + + Novice + Начальный + + + Average + Средний + + + Good + Сложный + + + Expert + Эксперт + + + Master + Мастер + + + Accept + Принять + + + Address: + Адрес: + + + Servername: + Имя сервера: + + + Serverinfo: + Информация о сервере: + + + &Start + &Старт + + + &Cancel + &Отмена + + + Wait... + Подождите... + + + Waiting for client to connect... + Ожидание связи с клиентом... + + + Waiting for server to accept... + Ожидание ответа от сервера... + + + Server denied. + Сервер недоступен. + + + Connection aborted. + Связь прервана. + + + Human + Человек + + + Player One + Первый игрок + + + White + Белые + + + Player Two + Второй игрок + + + Computer + Компьютер + + + Network - New Game + Сеть - Новая игра + + + Network - Join Game + Сеть - Присоединиться + + + Server + Сервер + + + Client + Клиент + + + Could not create a game on the server. + Невозможно запустить игру на сервере. + + + Could not join the game. + Невозможно присоединиться к игре. + + + Client connected. + Связь с клиентом установлена. + + + Client disconnected. + Связь с клиентом разорвана. + + + Free Men Placement + + + + + myTopLevel + + &New... + &Новая... + + + CTRL+N + File|New + CTRL+N + + + &Next Round + &Следующая партия + + + &Stop + &Стоп + + + &Undo Move + &Ход назад + + + CTRL+Z + File|Undo + CTRL+Z + + + &Information + &Информация + + + &Open... + &Открыть... + + + CTRL+O + File|Open + CTRL+O + + + &Save... + &Сохранить... + + + CTRL+S + File|Save + CTRL+S + + + &Quit + &Выход + + + CTRL+Q + File|Quit + CTRL+Q + + + &Show Notation + &Показать нотацию + + + &Green Board + &Зеленая доска + + + &Marble Board + &Мраморная доска + + + &Wooden Board + &Деревянная доска + + + &Console + &Консоль + + + What's This + Что это + + + SHIFT+F1 + Help|WhatsThis + SHIFT+F1 + + + &Rules of Play + &Правила игры + + + F1 + Help|Help + F1 + + + About &Qt + О &Qt + + + &Game + &Игра + + + &View + &Вид + + + &Settings + &Настройки + + + &Help + &Справка + + + Error + Ошибка + + + &Close + &Закрыть + + + Save Game + Сохранить игру + + + Could not save: + Невозможно сохранить: + + + Open Game + Открыть игру + + + Could not load: + Невозможно открыть: + + + Game Info + Информация об игре + + + Rules of Play + Правила игры + + + About + О программе + + + Current game will be lost if you continue. +Do you really want to discard it? + Текущая игра будет прервана. +Вы действительно этого хотите? + + + Abort Game? + Прервать игру? + + + <p>In the beginning of game you have 12 checkers (men). White always moves first. The men move forward only. The men can capture:<ul><li>by jumping forward only (english rules);<li>by jumping forward or backward (russian rules).</ul><p>A man which reaches the far side of the board becomes a king. The kings move forward or backward:<ul><li>to one square only (english rules);<li>to any number of squares (russian rules).</ul><p>The kings capture by jumping forward or backward. Whenever a player is able to make a capture he must do so. + <p>В начале игры у вас есть 12 пешек. Белые всегда начинают. Пешки могут ходить только вперед. Пешки могут бить:<ul><li>только вперед (английские правила);<li>вперед и назад (русские правила).</ul><p>Пешка, достигающая противоположного края доски, становится дамкой. Дамки ходят вперед и назад:<ul><li>только на соседние поля (английские правила);<li>на любое количество клеток (русские правила).</ul><p>Дамки могут бить и вперед и назад. Если игрок может бить, то он обязан это сделать. + + + + &Confirm aborting current game + &Подтвердите прерывание текущей игры + + + &Open console on new messages + &Открытие консоли для сообщений + + + &Small board + &Маленькая доска + + + &Big board + &Большая доска + + + &About + &О программе + + + &Notation font... + + + + <p>In the beginning of game you have 12 checkers (men). The men move forward only. The men can capture:<ul><li>by jumping forward only (english rules);<li>by jumping forward or backward (russian rules).</ul><p>A man which reaches the far side of the board becomes a king. The kings move forward or backward:<ul><li>to one square only (english rules);<li>to any number of squares (russian rules).</ul><p>The kings capture by jumping forward or backward. Whenever a player is able to make a capture he must do so. + <p>В начале игры у вас есть 12 пешек. Пешки могут ходить только вперед. Пешки могут бить:<ul><li>только вперед (английские правила);<li>вперед и назад (русские правила).</ul><p>Пешка, достигающая противоположного края доски, становится дамкой. Дамки ходят вперед и назад:<ul><li>только на соседние поля (английские правила);<li>на любое количество клеток (русские правила).</ul><p>Дамки могут бить и вперед и назад. Если игрок может бить, то он обязан это сделать. + + + Clear &log on new round + + + + Show notation &above men + + + + &Toolbar + + + + + myView + + Go! + Ваш ход! + + + Game aborted. + Игра прервана. + + + Connection closed. + Соединение закрыто. + + + Drawn game. + Затявнушаяся игра. + + + Invalid move. + Неверный ход. + + + Waiting for opponent to move... + Ожидание хода противника... + + + White wins! + Выиграли белые! + + + Black wins! + Выиграли черные! + + + White + Белые + + + Black + Черные + + + opponent + противник + + + Warning! Some errors occured. + + + + Saved: + + + + Opened: + + + + diff --git a/plugins/qcheckers_plugin/icons/Thumbs.db b/plugins/qcheckers_plugin/icons/Thumbs.db new file mode 100644 index 000000000..2ab7ca9bd Binary files /dev/null and b/plugins/qcheckers_plugin/icons/Thumbs.db differ diff --git a/plugins/qcheckers_plugin/icons/biglogo.png b/plugins/qcheckers_plugin/icons/biglogo.png new file mode 100644 index 000000000..a4b052a34 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/biglogo.png differ diff --git a/plugins/qcheckers_plugin/icons/clear.png b/plugins/qcheckers_plugin/icons/clear.png new file mode 100644 index 000000000..66d96d85c Binary files /dev/null and b/plugins/qcheckers_plugin/icons/clear.png differ diff --git a/plugins/qcheckers_plugin/icons/console.png b/plugins/qcheckers_plugin/icons/console.png new file mode 100644 index 000000000..ef1fb8979 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/console.png differ diff --git a/plugins/qcheckers_plugin/icons/context.png b/plugins/qcheckers_plugin/icons/context.png new file mode 100644 index 000000000..e8e6b4d45 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/context.png differ diff --git a/plugins/qcheckers_plugin/icons/continue.png b/plugins/qcheckers_plugin/icons/continue.png new file mode 100644 index 000000000..4d069e52a Binary files /dev/null and b/plugins/qcheckers_plugin/icons/continue.png differ diff --git a/plugins/qcheckers_plugin/icons/dialog.png b/plugins/qcheckers_plugin/icons/dialog.png new file mode 100644 index 000000000..c5630c6ba Binary files /dev/null and b/plugins/qcheckers_plugin/icons/dialog.png differ diff --git a/plugins/qcheckers_plugin/icons/down.png b/plugins/qcheckers_plugin/icons/down.png new file mode 100644 index 000000000..9990d86d4 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/down.png differ diff --git a/plugins/qcheckers_plugin/icons/exit.png b/plugins/qcheckers_plugin/icons/exit.png new file mode 100644 index 000000000..363c9b4c3 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/exit.png differ diff --git a/plugins/qcheckers_plugin/icons/fileopen.png b/plugins/qcheckers_plugin/icons/fileopen.png new file mode 100644 index 000000000..e4bdb3df1 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/fileopen.png differ diff --git a/plugins/qcheckers_plugin/icons/filesave.png b/plugins/qcheckers_plugin/icons/filesave.png new file mode 100644 index 000000000..869209e31 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/filesave.png differ diff --git a/plugins/qcheckers_plugin/icons/freeplace.png b/plugins/qcheckers_plugin/icons/freeplace.png new file mode 100644 index 000000000..5ec4b060c Binary files /dev/null and b/plugins/qcheckers_plugin/icons/freeplace.png differ diff --git a/plugins/qcheckers_plugin/icons/info.png b/plugins/qcheckers_plugin/icons/info.png new file mode 100644 index 000000000..36524824b Binary files /dev/null and b/plugins/qcheckers_plugin/icons/info.png differ diff --git a/plugins/qcheckers_plugin/icons/logo.png b/plugins/qcheckers_plugin/icons/logo.png new file mode 100644 index 000000000..16facdd15 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/logo.png differ diff --git a/plugins/qcheckers_plugin/icons/next.png b/plugins/qcheckers_plugin/icons/next.png new file mode 100644 index 000000000..93fa94c81 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/next.png differ diff --git a/plugins/qcheckers_plugin/icons/paused.png b/plugins/qcheckers_plugin/icons/paused.png new file mode 100644 index 000000000..9d4b7d911 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/paused.png differ diff --git a/plugins/qcheckers_plugin/icons/redo.png b/plugins/qcheckers_plugin/icons/redo.png new file mode 100644 index 000000000..defa358de Binary files /dev/null and b/plugins/qcheckers_plugin/icons/redo.png differ diff --git a/plugins/qcheckers_plugin/icons/stop.png b/plugins/qcheckers_plugin/icons/stop.png new file mode 100644 index 000000000..ea7ddcdad Binary files /dev/null and b/plugins/qcheckers_plugin/icons/stop.png differ diff --git a/plugins/qcheckers_plugin/icons/theme/Thumbs.db b/plugins/qcheckers_plugin/icons/theme/Thumbs.db new file mode 100644 index 000000000..f207dea2d Binary files /dev/null and b/plugins/qcheckers_plugin/icons/theme/Thumbs.db differ diff --git a/plugins/qcheckers_plugin/icons/theme/frame.png b/plugins/qcheckers_plugin/icons/theme/frame.png new file mode 100644 index 000000000..669aa8d71 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/theme/frame.png differ diff --git a/plugins/qcheckers_plugin/icons/theme/kingblack.png b/plugins/qcheckers_plugin/icons/theme/kingblack.png new file mode 100644 index 000000000..b6a596a4f Binary files /dev/null and b/plugins/qcheckers_plugin/icons/theme/kingblack.png differ diff --git a/plugins/qcheckers_plugin/icons/theme/kingwhite.png b/plugins/qcheckers_plugin/icons/theme/kingwhite.png new file mode 100644 index 000000000..64fc42f1a Binary files /dev/null and b/plugins/qcheckers_plugin/icons/theme/kingwhite.png differ diff --git a/plugins/qcheckers_plugin/icons/theme/manblack.png b/plugins/qcheckers_plugin/icons/theme/manblack.png new file mode 100644 index 000000000..32372efee Binary files /dev/null and b/plugins/qcheckers_plugin/icons/theme/manblack.png differ diff --git a/plugins/qcheckers_plugin/icons/theme/manwhite.png b/plugins/qcheckers_plugin/icons/theme/manwhite.png new file mode 100644 index 000000000..6262d38f1 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/theme/manwhite.png differ diff --git a/plugins/qcheckers_plugin/icons/theme/tile1.png b/plugins/qcheckers_plugin/icons/theme/tile1.png new file mode 100644 index 000000000..843fa0043 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/theme/tile1.png differ diff --git a/plugins/qcheckers_plugin/icons/theme/tile2.png b/plugins/qcheckers_plugin/icons/theme/tile2.png new file mode 100644 index 000000000..c415b4d0d Binary files /dev/null and b/plugins/qcheckers_plugin/icons/theme/tile2.png differ diff --git a/plugins/qcheckers_plugin/icons/undo.png b/plugins/qcheckers_plugin/icons/undo.png new file mode 100644 index 000000000..3ad9e865c Binary files /dev/null and b/plugins/qcheckers_plugin/icons/undo.png differ diff --git a/plugins/qcheckers_plugin/icons/up.png b/plugins/qcheckers_plugin/icons/up.png new file mode 100644 index 000000000..27f475c89 Binary files /dev/null and b/plugins/qcheckers_plugin/icons/up.png differ diff --git a/plugins/qcheckers_plugin/main.cc b/plugins/qcheckers_plugin/main.cc new file mode 100644 index 000000000..f3dede268 --- /dev/null +++ b/plugins/qcheckers_plugin/main.cc @@ -0,0 +1,49 @@ +#include +#include +#include +#include +//#include + + +#include "toplevel.h" +#include "common.h" + + +int main(int argc, char *argv[]) +{ + QApplication app(argc,argv); +// app.setStyle(new QPlastiqueStyle); + + qDebug() + << "Your Locale:" << QLocale::system().name() << endl + << "Prefix path:" << PREFIX; + + // Qt translations + QTranslator qt_tr; + if(qt_tr.load("qt_" + QLocale::system().name())) + app.installTranslator(&qt_tr); + else + qDebug() << "Loading Qt translations failed."; + + // App translations + QTranslator app_tr; + if(app_tr.load("kcheckers_" + QLocale::system().name(), + PREFIX"/share/kcheckers")) + app.installTranslator(&app_tr); + else + qDebug() << "Loading KCheckers translations failed."; + + myTopLevel* top = new myTopLevel(); + top->show(); + + // command line + if(app.argc()==2) + top->open(app.argv()[1]); + + int exit = app.exec(); + + delete top; + return exit; +} + + diff --git a/plugins/qcheckers_plugin/newgamedlg.cc b/plugins/qcheckers_plugin/newgamedlg.cc new file mode 100644 index 000000000..d13af8f1c --- /dev/null +++ b/plugins/qcheckers_plugin/newgamedlg.cc @@ -0,0 +1,324 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include + +#include +#include + +#include "newgamedlg.h" +#include "pdn.h" +#include "common.h" +#include "history.h" + +#include "player.h" + + +#define BEGINNER 2 +#define NOVICE 4 +#define AVERAGE 6 +#define GOOD 7 +#define EXPERT 8 +#define MASTER 9 + +#define CFG_SKILL CFG_KEY"Skill" +#define CFG_RULES CFG_KEY"Rules" +#define CFG_WHITE CFG_KEY"White" +#define CFG_PLAYER1 CFG_KEY"Player1" +#define CFG_PLAYER2 CFG_KEY"Player2" + + +myNewGameDlg::myNewGameDlg(QWidget* parent) + : QDialog(parent) +{ + setModal(true); + setWindowTitle(tr("New Game")+QString(" - "APPNAME)); + + + /* + * buttons, options. + */ + start_button = new QPushButton(tr("&Start"), this); + start_button->setDefault(true); + connect(start_button, SIGNAL(clicked()), this, SLOT(slot_start())); + + QPushButton* cn = new QPushButton(tr("&Cancel"), this); + connect(cn, SIGNAL(clicked()), this, SLOT(slot_reject())); + + // TODO - better text + m_freeplace = new QCheckBox(tr("Free Men Placement"), this); + + QHBoxLayout* buttons_layout = new QHBoxLayout(); + buttons_layout->addWidget(m_freeplace); + buttons_layout->addStretch(); + buttons_layout->addWidget(start_button); + buttons_layout->addWidget(cn); + + + /* + * global layout. + */ + QHBoxLayout* players_layout = new QHBoxLayout(); + players_layout->addWidget(create_player_one()); + players_layout->addWidget(create_player_two()); + + QVBoxLayout* global_layout = new QVBoxLayout(this); + global_layout->addLayout(players_layout); + global_layout->addLayout(buttons_layout); +} + + +myNewGameDlg::~myNewGameDlg() +{ +} + + +QWidget* myNewGameDlg::create_human_options() +{ + QFrame* frm = new QFrame(); + QVBoxLayout* frm_layout = new QVBoxLayout(frm); + frm_layout->addWidget(new QLabel("No options available.")); + frm_layout->addStretch(); + + return frm; +} + + +QWidget* myNewGameDlg::create_player_one() +{ + m_player_one.box = new QGroupBox(tr("Player One"), this); + + // name + m_player_one.name = new QLineEdit(m_player_one.box); + + // rules group box + m_player_one.rules = new QGroupBox(tr("Rules"), m_player_one.box); + m_player_one.rule_english = new QRadioButton( + myHistory::typeToString(ENGLISH), m_player_one.rules); + m_player_one.rule_russian = new QRadioButton( + myHistory::typeToString(RUSSIAN), m_player_one.rules); + + QVBoxLayout* rules_layout = new QVBoxLayout(m_player_one.rules); + rules_layout->addWidget(m_player_one.rule_english); + rules_layout->addWidget(m_player_one.rule_russian); + + // play white men? + m_player_one.white = new QCheckBox(tr("White"), m_player_one.box); + + // layout + QVBoxLayout* vb1_layout = new QVBoxLayout(m_player_one.box); + vb1_layout->addWidget(m_player_one.name); + vb1_layout->addWidget(m_player_one.rules); + vb1_layout->addWidget(m_player_one.white); + + return m_player_one.box; +} + + +QWidget* myNewGameDlg::create_player_two() +{ + m_player_two.box = new QGroupBox(tr("Player Two"), this); + + // name + m_player_two.name = new QLineEdit(m_player_two.box); + + // options + m_player_two.options = new QTabWidget(m_player_two.box); + m_player_two.options->insertTab(COMPUTER, create_computer_options(), tr("Computer")); + m_player_two.options->insertTab(HUMAN, create_human_options(), tr("Human")); + connect(m_player_two.options, SIGNAL(currentChanged(int)), + this, SLOT(slot_game(int))); + + /* + * frame layout + */ + QVBoxLayout* frm_layout = new QVBoxLayout(m_player_two.box); + frm_layout->addWidget(m_player_two.name); + frm_layout->addWidget(m_player_two.options); + + return m_player_two.box; +} + + +QWidget* myNewGameDlg::create_computer_options() +{ + QFrame* frm = new QFrame(); + + // skills + QGroupBox* skills = new QGroupBox(tr("Skill"), frm); + m_player_two.computer.skills[BEGINNER] = new QRadioButton(tr("Beginner"), + skills); + m_player_two.computer.skills[NOVICE] = new QRadioButton(tr("Novice"), + skills); + m_player_two.computer.skills[AVERAGE] = new QRadioButton(tr("Average"), + skills); + m_player_two.computer.skills[GOOD] = new QRadioButton(tr("Good"), + skills); + m_player_two.computer.skills[EXPERT] = new QRadioButton(tr("Expert"), + skills); + m_player_two.computer.skills[MASTER] = new QRadioButton(tr("Master"), + skills); + + QGridLayout* skills_layout = new QGridLayout(skills); + int row = 0; + int col = 0; + foreach(QRadioButton* rb, m_player_two.computer.skills) { + skills_layout->addWidget(rb, row++, col); + connect(rb, SIGNAL(clicked()), this, SLOT(slot_skills())); + if(row > 2) { + row = 0; + col = 1; + } + } + + // layout + QHBoxLayout* frm_layout = new QHBoxLayout(frm); + frm_layout->addWidget(skills); + + return frm; +} + + +void myNewGameDlg::slot_reject() +{ + reject(); +} + + +void myNewGameDlg::slot_start() +{ + accept(); +} + + +void myNewGameDlg::slot_skills() +{ + QRadioButton* skill = 0; + foreach(QRadioButton* rb, m_player_two.computer.skills) { + if(rb->isChecked()) { + skill = rb; + break; + } + } + + if(skill) + m_player_two.name->setText("*"+skill->text()+"*"); +} + + +void myNewGameDlg::slot_game_start(int id) +{ + slot_game(id); + slot_start(); +} + + +void myNewGameDlg::slot_game(int id) +{ + start_button->setEnabled(true); + m_player_one.box->setEnabled(true); + m_player_two.options->setEnabled(true); + + if(m_player_two.last_game_index==HUMAN) { + m_cfg_player2 = m_player_two.name->text(); + } + + m_player_two.last_game_index = id; + + switch(id) { + case COMPUTER: + m_player_two.name->setReadOnly(true); + slot_skills(); + + m_player_one.rules->setEnabled(true); + m_player_one.white->setEnabled(true); + break; + + case HUMAN: + m_player_two.name->setReadOnly(false); + m_player_two.name->setText(m_cfg_player2); + + m_player_one.rules->setEnabled(true); + m_player_one.white->setEnabled(true); + break; + + default: + qDebug() << __PRETTY_FUNCTION__ << "ERR"; + break; + } +} + + +void myNewGameDlg::writeSettings(QSettings* cfg) +{ + cfg->setValue(CFG_SKILL, skill()); + cfg->setValue(CFG_RULES, rules()); + cfg->setValue(CFG_WHITE, m_player_one.white->isChecked()); + + cfg->setValue(CFG_PLAYER1, m_player_one.name->text()); + cfg->setValue(CFG_PLAYER2, m_cfg_player2); +} + + +void myNewGameDlg::readSettings(QSettings* cfg) +{ + int skills = cfg->value(CFG_SKILL, BEGINNER).toInt(); + QMap::iterator it; + it = m_player_two.computer.skills.find(skills); + if(it != m_player_two.computer.skills.end()) + it.value()->setChecked(true); + else + m_player_two.computer.skills[BEGINNER]->setChecked(true); + slot_skills(); + + int rules = cfg->value(CFG_RULES, ENGLISH).toInt(); + if(rules == ENGLISH) + m_player_one.rule_english->setChecked(true); + else + m_player_one.rule_russian->setChecked(true); + + m_player_one.white->setChecked(cfg->value(CFG_WHITE, false).toBool()); + + m_player_one.name->setText(cfg->value(CFG_PLAYER1, + getenv("USER")).toString()); + m_cfg_player2 = cfg->value(CFG_PLAYER2, "Player2").toString(); +} + + +int myNewGameDlg::skill() const +{ + QMap::const_iterator it; + it = m_player_two.computer.skills.begin(); + for(; it!=m_player_two.computer.skills.end(); ++it) { + if(it.value()->isChecked()) + return it.key(); + } + + qDebug() << __PRETTY_FUNCTION__ << "No skill selected."; + return BEGINNER; +} + + +int myNewGameDlg::rules() const +{ + if(m_player_one.rule_english->isChecked()) + return ENGLISH; + return RUSSIAN; +} + diff --git a/plugins/qcheckers_plugin/newgamedlg.h b/plugins/qcheckers_plugin/newgamedlg.h new file mode 100644 index 000000000..22b4dc34a --- /dev/null +++ b/plugins/qcheckers_plugin/newgamedlg.h @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _NEWGAMEDLG_H_ +#define _NEWGAMEDLG_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define COMPUTER 0 +#define HUMAN 1 + + +class myPlayer; + + +class myNewGameDlg : public QDialog +{ + Q_OBJECT + +public: + myNewGameDlg(QWidget* parent); + ~myNewGameDlg(); + + // playing against the computer + int rules() const; + // return HUMAN/COMPUTER + int opponent() const { return m_player_two.options->currentIndex(); } + // + int skill() const; + // + bool freePlacement() const { return m_freeplace->isChecked(); } + + // + const QString name() const { return m_player_one.name->text(); } + bool isWhite() const { return m_player_one.white->isChecked(); } + const QString opponentName() const { return m_player_two.name->text(); } + + // for settings + void writeSettings(QSettings*); + void readSettings(QSettings*); + +private slots: + void slot_game(int id); // ListWidget + void slot_game_start(int id); + void slot_skills(); + + void slot_reject(); + void slot_start(); + +private: + QWidget* create_player_one(); + QWidget* create_player_two(); + + QWidget* create_human_options(); + QWidget* create_computer_options(); + +private: + struct player_one_struct { + QGroupBox* box; + QLineEdit* name; + QGroupBox* rules; + QRadioButton* rule_english; + QRadioButton* rule_russian; + QCheckBox* white; + }; + struct player_one_struct m_player_one; + + struct player_two_struct { + QGroupBox* box; + QLineEdit* name; + int last_game_index; + QTabWidget* options; + // human options + // computer options + struct computer_stuct { + QMap skills; + }; + struct computer_stuct computer; + }; + struct player_two_struct m_player_two; + + QCheckBox* m_freeplace; + QPushButton* start_button; + + QString m_cfg_player2; +}; + +#endif + diff --git a/plugins/qcheckers_plugin/pdn.cc b/plugins/qcheckers_plugin/pdn.cc new file mode 100644 index 000000000..01d32f269 --- /dev/null +++ b/plugins/qcheckers_plugin/pdn.cc @@ -0,0 +1,541 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include + +#include "checkers.h" +#include "pdn.h" + + +#define PLAYER true +#define COMPUTER false + +#define END_OF_MOVELINE "@." + + +Pdn::Pdn() +{ +} + + +Pdn::~Pdn() +{ + qDeleteAll(m_database); + m_database.clear(); +} + + +bool Pdn::open(const QString& filename, QWidget* parent, + const QString& label, QString& text_to_log) +{ + qDeleteAll(m_database); + m_database.clear(); + + QFile file(filename); + if(!file.open(QFile::ReadOnly)) return false; + + QTextStream ts(&file); + + QString str1, str2; + + QProgressDialog progress(parent); + progress.setModal(true); + progress.setLabelText(label); + progress.setRange(0, file.size()); + progress.setMinimumDuration(0); + + unsigned int line_nr = 1; + unsigned int game_started = 1; + bool in_tags = false; + while(!ts.atEnd()) { + str1 = ts.readLine().trimmed(); + if(ts.atEnd()) + str2 += str1; + + if((str1.length() && str1[0]=='[') || ts.atEnd()) { + if(!in_tags) { + // tags begin again, so a game is ended. + if(str2.length()) { + if((m_database.count()%10)==0) + progress.setValue(file.pos()); + + QString log_txt; + PdnGame* game = new PdnGame(str2, log_txt); + m_database.append(game); + + if(log_txt.length()) { + text_to_log + += QString("%1. game begins at line %2:\n") + .arg(m_database.count()) + .arg(game_started); + text_to_log += log_txt; + } + + game_started = line_nr; + str2=""; + } + + in_tags = true; + } + } else { + if(in_tags) + in_tags = false; + } + + str2.append(str1+"\n"); + + if(progress.wasCanceled()) + break; + + line_nr++; + } + + file.close(); + + return true; +} + + +bool Pdn::save(const QString& filename) +{ + QFile file(filename); + if(!file.open(QFile::WriteOnly)) + return false; + + QTextStream ts(&file); + + foreach(PdnGame* game, m_database) { + ts << game->toString() << endl << endl; + } + + file.close(); + return true; +} + + + +PdnGame* Pdn::newGame() +{ + QString log_txt; // here: ignore TODO + PdnGame* game = new PdnGame("", log_txt); + m_database.append(game); + return game; +} + + +/*************************************************************************** + * * + * * + ***************************************************************************/ +PdnMove::PdnMove(QString line) +{ + if(line[0]=='{') { + qDebug("a move must not begin with a comment."); + return; + } + + // first move. + m_first = line.section(' ', 0, 0); + line = line.mid(m_first.length()).trimmed(); + + // check for a first comment. + if(line[0]=='{') { + int end = line.indexOf('}', 1); + if(end>=0) { + m_comfirst = line.mid(1, end-1); + line.remove(0, end+1); + line = line.trimmed(); + } else + qDebug("no comment ending of the first comment."); + } + + // second move. + m_second = line.section(' ', 0, 0); + line = line.mid(m_second.length()).trimmed(); + + // check for a second comment. + if(line[0]=='{') { + int end = line.indexOf('}', 1); + if(end>=0) + m_comsecond = line.mid(1, end-1); + else + qDebug("no comment ending of the second comment."); + } +} + + +/*************************************************************************** + * * + * * + ***************************************************************************/ +PdnGame::PdnGame(const QString& game_string, QString& log_txt) +{ + white = PLAYER; + for(int i=0; i<12; i++) + board[i]=MAN2; + for(int i=20; i<32; i++) + board[i]=MAN1; + + if(!parse(game_string, log_txt)) { + qDebug(" errors occured while processing game."); // TODO + } +} + + +PdnGame::~PdnGame() +{ + qDeleteAll(m_moves); + m_moves.clear(); +} + + +QString PdnGame::get(Tag tag) const +{ + switch(tag) { + case Date: return pdnDate; + case Site: return pdnSite; + case Type: return pdnType; + case Event: return pdnEvent; + case Round: return pdnRound; + case White: return pdnWhite; + case Black: return pdnBlack; + default: return pdnResult; + } +} + + +void PdnGame::set(Tag tag, const QString& string) +{ + switch(tag) { + case Date: pdnDate=string; break; + case Site: pdnSite=string; break; + case Type: pdnType=string; break; + case Event: pdnEvent=string;break; + case Round: pdnRound=string;break; + case White: pdnWhite=string;break; + case Black: pdnBlack=string;break; + default: pdnResult=string; + } +} + + +bool PdnGame::parse_moves(const QString& line) +{ + qDeleteAll(m_moves); + m_moves.clear(); + + QStringList list = line.split(' '); + + QString current_move; + int move_num = 0; + bool in_comment = false; + foreach(QString str, list) { + if(str.startsWith("{")) + in_comment = true; + if(str.endsWith("}")) + in_comment = false; + + if(str.endsWith(".") && !in_comment) { + if(str!=END_OF_MOVELINE) { + if((move_num+1) != str.mid(0, str.length()-1).toInt()) { + qDebug() << "Move num expected:" << move_num+1 + << "received:" << str; + return false; + } + move_num++; + } + + current_move = current_move.trimmed(); + if(current_move.length()) { + m_moves.append(new PdnMove(current_move)); + current_move = ""; + } + continue; + } + + if(str.isEmpty()) + current_move += " "; + else + current_move += str + " "; + } + + return true; +} + + +bool PdnGame::parse(const QString& pdngame, QString& log_txt) +{ + QString fen; + QString moves; + int num = pdngame.count("\n"); // Number of lines + + for(int i=0; i<=num; i++) { + QString line = pdngame.section('\n',i ,i); + if(!line.length()) + continue; + + if(line.startsWith("[")) { + line.remove(0, 1); + line = line.trimmed(); + + if(line.startsWith("GameType")) pdnType=line.section('"',1,1); + else if(line.startsWith("FEN")) fen=line.section('"',1,1); + else if(line.startsWith("Date")) pdnDate=line.section('"',1,1); + else if(line.startsWith("Site")) pdnSite=line.section('"',1,1); + else if(line.startsWith("Event")) pdnEvent=line.section('"',1,1); + else if(line.startsWith("Round")) pdnRound=line.section('"',1,1); + else if(line.startsWith("White")) pdnWhite=line.section('"',1,1); + else if(line.startsWith("Black")) pdnBlack=line.section('"',1,1); + else if(line.startsWith("Result")) pdnResult=line.section('"',1,1); + else ; // Skip other unsupported tags + + } else { + moves += " " + line; + } + } + + // parse move section. + if(moves.endsWith(pdnResult)) + moves.truncate(moves.length()-pdnResult.length()); + else { + log_txt += " +Different result at the end of the movelist:\n" + + QString(" \"%1\" expected, got \"%2\"\n") + .arg(pdnResult) + .arg(moves.right(pdnResult.length())); + + // need to remove the incorrect result. + if(moves.endsWith(" *")) { + log_txt += " => Ignoring \" *\" from the end.\n"; + moves.truncate(moves.length()-2); + } else { + int pos = moves.lastIndexOf('-') - 1; + bool skip_ws = true; + for(int i=pos; i>=0; i--) { + if(moves[i]==' ') { + if(!skip_ws) { + log_txt += " => Ignoring \"" + + moves.right(moves.length()-i-1) + + "\" from the end.\n", + moves.truncate(i+1); + break; + } + } else { + skip_ws = false; + } + } + } + } + + if(!parse_moves(moves+" "END_OF_MOVELINE)) { // :) + log_txt += "\n +parsing moves failed."; + return false; + } + + // Translation of the GameType tag + switch(pdnType.toInt()) { + case ENGLISH: + case RUSSIAN: + break; + default: +// log_txt += "\n +setting game type to english."; + pdnType.setNum(ENGLISH); + break; + } + + // Parsing of the Forsyth-Edwards Notation (FEN) tag + if(fen.isNull()) + return true; + + fen=fen.trimmed(); + + for(int i=fen.indexOf(" "); i!=-1; i=fen.indexOf(" ")) + fen=fen.remove(i,1); + + if(fen.startsWith("W:W")) + white=PLAYER; + else if(fen.startsWith("B:W")) + white=COMPUTER; + else + return false; + + QString string = fen.mid(3).section(":B",0,0); + if(!parse(string, white)) + return false; + + string=fen.section(":B",1,1); + if(string.endsWith(".")) + string.truncate(string.length()-1); + if(!parse(string, !white)) + return false; + + return true; +} + + +bool PdnGame::parse(const QString& str, bool side) +{ + QString notation; + + if(pdnType.toInt() == ENGLISH) + notation=QString(ENOTATION); + else + notation=QString(RNOTATION); + + QStringList sections = str.split(","); + foreach(QString pos, sections) { + bool king=false; + + if(pos.startsWith("K")) { + pos=pos.remove(0,1); + king=true; + } + if(pos.length()==1) + pos.append(' '); + if(pos.length()!=2) + return false; + + int index = notation.indexOf(pos); + if(index%2) + index=notation.indexOf(pos,index+1); + if(index == -1) + return false; + + if(white==COMPUTER) + index=62-index; + + if(side==PLAYER) + board[index/2]=(king ? KING1 : MAN1); + else + board[index/2]=(king ? KING2 : MAN2); + } + return true; +} + + +PdnMove* PdnGame::getMove(int i) +{ + if(im_moves.count()) + qDebug("PdnGame::getMove(%u) m_moves.count()=%u", + i, m_moves.count()); + + PdnMove* m = new PdnMove(""); + m_moves.append(m); + return m; +} + + +QString PdnGame::toString() +{ + QString fen; + QString moves; + + /* + * fen + */ + if(!movesCount()) { + qDebug("FEN tag with lots of errors."); + QString string1; + QString string2; + QString notation; + + if(pdnType.toInt() == ENGLISH) + notation=QString(ENOTATION); + else + notation=QString(RNOTATION); + + for(int i=0; i<32; i++) { + int index=i*2; + if(white==COMPUTER) index=62-index; + + QString pos; + + switch(board[i]) { + case KING1: + pos.append('K'); + case MAN1: + pos.append(notation.mid(index,2).trimmed()); + if(string1.length()) string1.append(','); + string1.append(pos); + break; + case KING2: + pos.append('K'); + case MAN2: + pos.append(notation.mid(index,2).trimmed()); + if(string2.length()) string2.append(','); + string2.append(pos); + default: + break; + } + } + if(white==PLAYER) + fen.append("W:W"+string1+":B"+string2+"."); + else + fen.append("B:W"+string2+":B"+string1+"."); + } + + /* + * moves + */ + unsigned int count = 1; + foreach(PdnMove* move, m_moves) { + moves += QString("%1. %2 %3%4%5\n") + .arg(count) + .arg(move->m_first) + .arg(move->m_comfirst.length() ? "{"+move->m_comfirst+"} " : "") + .arg(move->m_second) + .arg(move->m_comsecond.length() ? " {"+move->m_comsecond+"}" : ""); + count++; + } + + + /* + * create format and write tags+fen+moves. + */ + QString str; + + if(pdnEvent.length()) str.append("[Event \""+pdnEvent+"\"]\n"); + if(pdnSite.length()) str.append("[Site \"" +pdnSite +"\"]\n"); + if(pdnDate.length()) str.append("[Date \"" +pdnDate +"\"]\n"); + if(pdnRound.length()) str.append("[Round \""+pdnRound+"\"]\n"); + if(pdnWhite.length()) str.append("[White \""+pdnWhite+"\"]\n"); + if(pdnBlack.length()) str.append("[Black \""+pdnBlack+"\"]\n"); + + if(fen.length()) { + str.append("[SetUp \"1\"]\n"); + str.append("[FEN \""+fen+"\"]\n\n"); + } + + str.append("[Result \""+pdnResult+"\"]\n"); + str.append("[GameType \""+pdnType+"\"]\n"); + str.append(moves); + str.append(pdnResult+"\n"); + + return str; +} + diff --git a/plugins/qcheckers_plugin/pdn.h b/plugins/qcheckers_plugin/pdn.h new file mode 100644 index 000000000..8110fd655 --- /dev/null +++ b/plugins/qcheckers_plugin/pdn.h @@ -0,0 +1,125 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef PDN_H +#define PDN_H + + +#include +#include + + +#define ENOTATION "1 2 3 4 5 6 7 8 9 1011121314151617181920212223242526272829303132" +//#define ENOTATION "32313029282726252423222120191817161514131211109 8 7 6 5 4 3 2 1 " +#define RNOTATION "b8d8f8h8a7c7e7g7b6d6f6h6a5c5e5g5b4d4f4h4a3c3e3g3b2d2f2h2a1c1e1g1" + +#define ENGLISH 21 +#define RUSSIAN 25 + + +class PdnMove; +class PdnGame; + + +// Portable Draughts Notation Format File parser +class Pdn +{ +public: + Pdn(); + virtual ~Pdn(); + + int count() const { return m_database.count(); } + PdnGame* game(int i) { return m_database.at(i); } + PdnGame* newGame(); + + void clear() { m_database.clear(); } + // parent is needed to display a progress dialog. + bool open(const QString& filename, QWidget* parent, + const QString& label, QString& text_to_log); + bool save(const QString& filename); + +private: + QList m_database; +}; + + +/* + * m_first, m_second are mandatary. + * comments are optional. + */ +class PdnMove +{ +public: + PdnMove(QString whole_line_of_move); + + QString m_first, m_comfirst; + QString m_second, m_comsecond; +}; + + +/* + * represents each game in a pdn-file. + */ +class PdnGame +{ +public: + PdnGame(const QString& game_string, QString& text_to_log); + ~PdnGame(); + + enum Tag { Date, Site, Type, Event, Round, White, Black,Result }; + + int item(int i) const { return board[i]; } + void setItem(int i, int set) { board[i]=set; } + + bool isWhite() const { return white; } + void setWhite(bool set) { white=set; } + + void set(Tag tag, const QString& string); + QString get(Tag tag) const; + + int movesCount() const { return m_moves.count(); } + PdnMove* getMove(int i); + PdnMove* addMove(); + void clearMoves() { m_moves.clear(); } + + QString toString(); + +private: + bool parse(const QString& game_string, QString& log_txt); + bool parse(const QString& string, bool side); + bool parse_moves(const QString& moves_line); + +private: + bool white; + int board[32]; + QString pdnDate; + QString pdnSite; + QString pdnType; + QString pdnEvent; + QString pdnRound; + QString pdnWhite; + QString pdnBlack; + QString pdnResult; + QList m_moves; +}; + + +#endif + diff --git a/plugins/qcheckers_plugin/player.h b/plugins/qcheckers_plugin/player.h new file mode 100644 index 000000000..eb62f8f79 --- /dev/null +++ b/plugins/qcheckers_plugin/player.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 by Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _PLAYER_H_ +#define _PLAYER_H_ + +#include + + +class Checkers; +class Field; + + +class myPlayer : public QObject +{ + Q_OBJECT + +public: + myPlayer(const QString& name, bool white) + : m_name(name), m_white(white), m_opponent(0) {} + + // information + bool isWhite() const { return m_white; } + void setWhite(bool b) { m_white = b; } + // + const QString& name() const { return m_name; } + void setName(const QString& n) { m_name = n; } + // + virtual bool isHuman() const { return false; } + + // + virtual void yourTurn(const Checkers* game) = 0; + // return false on incorrect course. + // set select to true to select the select, or unselect. + // QString contains error msg. + virtual bool fieldClicked(int, bool*,QString&) { return true; } + // computerplayer terminates his thinking thread. + // humanplayer + // networkplayer disconnects from the server. + virtual void stop() = 0; + + void setOpponent(myPlayer* o) { m_opponent=o; } + myPlayer* opponent() const { return m_opponent; } + +signals: + // emitted when move is done, provides the complete board converted to + // string. + void moveDone(const QString&); + +private: + QString m_name; + bool m_white; + + myPlayer* m_opponent; +}; + + +#endif diff --git a/plugins/qcheckers_plugin/qcheckers.qrc b/plugins/qcheckers_plugin/qcheckers.qrc new file mode 100644 index 000000000..74bccb5f3 --- /dev/null +++ b/plugins/qcheckers_plugin/qcheckers.qrc @@ -0,0 +1,29 @@ + + + icons/biglogo.png + icons/fileopen.png + icons/filesave.png + icons/stop.png + icons/dialog.png + icons/undo.png + icons/redo.png + icons/exit.png + icons/info.png + icons/next.png + icons/context.png + icons/logo.png + icons/paused.png + icons/freeplace.png + icons/clear.png + icons/continue.png + + icons/theme/frame.png + icons/theme/kingwhite.png + icons/theme/manwhite.png + icons/theme/tile2.png + icons/theme/kingblack.png + icons/theme/manblack.png + icons/theme/tile1.png + + + diff --git a/plugins/qcheckers_plugin/qcheckers_plugin.pro b/plugins/qcheckers_plugin/qcheckers_plugin.pro new file mode 100644 index 000000000..aead3b193 --- /dev/null +++ b/plugins/qcheckers_plugin/qcheckers_plugin.pro @@ -0,0 +1,58 @@ +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin release + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(qcheckers_plugin) + +HEADERS += ../PluginInterface.h \ + QCheckersPlugin.h +SOURCES += QCheckersPlugin.cpp + +#=============================================================================== + +HEADERS += pdn.h \ + checkers.h echeckers.h rcheckers.h \ + field.h toplevel.h view.h history.h board.h \ + newgamedlg.h \ + common.h \ + player.h humanplayer.h computerplayer.h + + +SOURCES += pdn.cc \ + checkers.cc echeckers.cc rcheckers.cc \ + field.cc toplevel.cc view.cc history.cc board.cc \ + newgamedlg.cc \ + humanplayer.cc computerplayer.cc + +RESOURCES = qcheckers.qrc + + +#PREFIX = $$system(grep 'define PREFIX' common.h | cut -d'"' -f2) +#SHARE_PATH = $$system(grep 'define SHARE_PATH' common.h | cut -d'"' -f2) + +TRANSLATIONS = i18n/kcheckers_de.ts i18n/kcheckers_fr.ts +# i18n/kcheckers_ru.ts + +target.path = $$PREFIX/bin +INSTALLS += target + + +# +# This hack is needed for i18n support. +# +share.path += $$PREFIX/share/kcheckers +share.files += kcheckers.pdn COPYING AUTHORS ChangeLog README themes i18n/* +INSTALLS += share + diff --git a/plugins/qcheckers_plugin/rcheckers.cc b/plugins/qcheckers_plugin/rcheckers.cc new file mode 100644 index 000000000..c24ba138d --- /dev/null +++ b/plugins/qcheckers_plugin/rcheckers.cc @@ -0,0 +1,553 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +// +// Russian Checkers + + +#include "rcheckers.h" + + +/////////////////////////////////////////////////// +// +// Player Functions +// +/////////////////////////////////////////////////// + + +bool RCheckers::go1(int from,int field) +{ + from=internal(from); + field=internal(field); + + to=field; + + if(checkCapture1()) + { + bool capture=false; + switch(board[from]) + { + case MAN1: + if(manCapture1(from,UL,capture)) return true; + if(manCapture1(from,UR,capture)) return true; + if(manCapture1(from,DL,capture)) return true; + if(manCapture1(from,DR,capture)) return true; + return false; + case KING1: + if(kingCapture1(from,UL,capture)) return true; + if(kingCapture1(from,UR,capture)) return true; + if(kingCapture1(from,DL,capture)) return true; + if(kingCapture1(from,DR,capture)) return true; + return false; + } + } + else + { + switch(board[from]) + { + case MAN1: + if((to==(from-6))||(to==(from-5))) + { + board[from]=FREE; + if(to<10) board[to]=KING1; + else board[to]=MAN1; + return true; + } + return false; + case KING1: + for(int i=from-6;;i-=6) + { + if(i==to) + { + board[from]=FREE; + board[to]=KING1; + return true; + } + else if(board[i]==FREE) continue; + else break; + } + for(int i=from-5;;i-=5) + { + if(i==to) + { + board[from]=FREE; + board[to]=KING1; + return true; + } + else if(board[i]==FREE) continue; + else break; + } + for(int i=from+5;;i+=5) + { + if(i==to) + { + board[from]=FREE; + board[to]=KING1; + return true; + } + else if(board[i]==FREE) continue; + else break; + } + for(int i=from+6;;i+=6) + { + if(i==to) + { + board[from]=FREE; + board[to]=KING1; + return true; + } + else if(board[i]==FREE) continue; + else break; + } + return false; + } + } + return false; +} + + + +bool RCheckers::checkCapture1() const +{ + for(int i=6;i<48;i++) + if(checkCapture1(i)) + return true; + + return false; +} + + +bool RCheckers::checkCapture1(int i) const +{ + switch(board[i]) + { + case MAN1: + if(board[i-6]==MAN2 || board[i-6]==KING2) + if(board[i-12]==FREE) return true; + if(board[i-5]==MAN2 || board[i-5]==KING2) + if(board[i-10]==FREE) return true; + if(board[i+5]==MAN2 || board[i+5]==KING2) + if(board[i+10]==FREE) return true; + if(board[i+6]==MAN2 || board[i+6]==KING2) + if(board[i+12]==FREE) return true; + break; + case KING1: + int k; + for(k=i-6;board[k]==FREE;k-=6); + if(board[k]==MAN2 || board[k]==KING2) + if(board[k-6]==FREE) return true; + + for(k=i-5;board[k]==FREE;k-=5); + if(board[k]==MAN2 || board[k]==KING2) + if(board[k-5]==FREE) return true; + + for(k=i+5;board[k]==FREE;k+=5); + if(board[k]==MAN2 || board[k]==KING2) + if(board[k+5]==FREE) return true; + + for(k=i+6;board[k]==FREE;k+=6); + if(board[k]==MAN2 || board[k]==KING2) + if(board[k+6]==FREE) return true; + } + + return false; +} + + +/* ORIG func aw +bool RCheckers::checkCapture1() +{ + for(int i=6;i<48;i++) + { + switch(board[i]) + { + case MAN1: + if(board[i-6]==MAN2 || board[i-6]==KING2) + if(board[i-12]==FREE) return true; + if(board[i-5]==MAN2 || board[i-5]==KING2) + if(board[i-10]==FREE) return true; + if(board[i+5]==MAN2 || board[i+5]==KING2) + if(board[i+10]==FREE) return true; + if(board[i+6]==MAN2 || board[i+6]==KING2) + if(board[i+12]==FREE) return true; + break; + case KING1: + int k; + for(k=i-6;board[k]==FREE;k-=6); + if(board[k]==MAN2 || board[k]==KING2) + if(board[k-6]==FREE) return true; + + for(k=i-5;board[k]==FREE;k-=5); + if(board[k]==MAN2 || board[k]==KING2) + if(board[k-5]==FREE) return true; + + for(k=i+5;board[k]==FREE;k+=5); + if(board[k]==MAN2 || board[k]==KING2) + if(board[k+5]==FREE) return true; + + for(k=i+6;board[k]==FREE;k+=6); + if(board[k]==MAN2 || board[k]==KING2) + if(board[k+6]==FREE) return true; + } + } + return false; +} +*/ + + +// Return TRUE if a course of the player true +// Return FALSE if a course of the player incorrect + +bool RCheckers::manCapture1(int from,int direction,bool &capture) +{ + int i=from+direction; + if(board[i]==MAN2 || board[i]==KING2) + { + int k=i+direction; + if(board[k]==FREE) + { + bool next=false; + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + + if(k<10) + { + board[k]=KING1; + if(kingCapture1(k,direction+11,next)) + { + board[i]=FREE; + return true; + } + } + else + { + board[k]=MAN1; + if(direction==UL || direction==DR) + { + if(manCapture1(k,UR,next)) {board[i]=FREE;return true;} + if(manCapture1(k,DL,next)) {board[i]=FREE;return true;} + } + else + { + if(manCapture1(k,UL,next)) {board[i]=FREE;return true;} + if(manCapture1(k,DR,next)) {board[i]=FREE;return true;} + } + if(manCapture1(k,direction,next)) {board[i]=FREE;return true;} + } + + if((!next) && k==to) {board[i]=FREE;return true;} + + board[k]=FREE; + board[i]=save; + board[from]=MAN1; + capture=true; + } + } + return false; +} + + +bool RCheckers::kingCapture1(int from,int direction,bool &capture) +{ + int i; + for(i=from+direction;board[i]==FREE;i+=direction); + + if(board[i]==MAN2 || board[i]==KING2) + { + int k=i+direction; + if(board[k]==FREE) + { + bool next=false; + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + + for(;board[k]==FREE;k+=direction) + { + board[k]=KING1; + if(direction==UL || direction==DR) + { + if(kingCapture1(k,UR,next)) {board[i]=FREE;return true;} + if(kingCapture1(k,DL,next)) {board[i]=FREE;return true;} + } + else + { + if(kingCapture1(k,UL,next)) {board[i]=FREE;return true;} + if(kingCapture1(k,DR,next)) {board[i]=FREE;return true;} + } + board[k]=FREE; + } + + board[k-=direction]=KING1; + if(kingCapture1(k,direction,next)) {board[i]=FREE;return true;} + board[k]=FREE; + + if(!next) + for(;k!=i;k-=direction) + if(k==to) {board[i]=FREE;board[k]=KING1;return true;} + + board[i]=save; + board[from]=KING1; + capture=true; + } + } + return false; +} + + +//////////////////////////////////////////////////// +// +// Computer Functions +// +//////////////////////////////////////////////////// + + +void RCheckers::kingMove2(int from,int &resMax) +{ + board[from]=FREE; + for(int i=from-6;board[i]==FREE;i-=6) + { + board[i]=KING2; + turn(resMax); + board[i]=FREE; + } + for(int i=from-5;board[i]==FREE;i-=5) + { + board[i]=KING2; + turn(resMax); + board[i]=FREE; + } + for(int i=from+5;board[i]==FREE;i+=5) + { + board[i]=KING2; + turn(resMax); + board[i]=FREE; + } + for(int i=from+6;board[i]==FREE;i+=6) + { + board[i]=KING2; + turn(resMax); + board[i]=FREE; + } + board[from]=KING2; +} + + +bool RCheckers::checkCapture2() const +{ + for(int i=6;i<48;i++) + { + switch(board[i]) + { + case MAN2: + if(board[i-6]==MAN1 || board[i-6]==KING1) + if(board[i-12]==FREE) return true; + if(board[i-5]==MAN1 || board[i-5]==KING1) + if(board[i-10]==FREE) return true; + if(board[i+5]==MAN1 || board[i+5]==KING1) + if(board[i+10]==FREE) return true; + if(board[i+6]==MAN1 || board[i+6]==KING1) + if(board[i+12]==FREE) return true; + break; + case KING2: + int k; + for(k=i-6;board[k]==FREE;k-=6); + if(board[k]==MAN1 || board[k]==KING1) + if(board[k-6]==FREE) return true; + + for(k=i-5;board[k]==FREE;k-=5); + if(board[k]==MAN1 || board[k]==KING1) + if(board[k-5]==FREE) return true; + + for(k=i+5;board[k]==FREE;k+=5); + if(board[k]==MAN1 || board[k]==KING1) + if(board[k+5]==FREE) return true; + + for(k=i+6;board[k]==FREE;k+=6); + if(board[k]==MAN1 || board[k]==KING1) + if(board[k+6]==FREE) return true; + } + } + return false; +} + + +// Return TRUE if it is possible to capture +// Return FALSE if it is impossible to capture + +bool RCheckers::manCapture2(int from,int &resMax) +{ + bool capture=false; + + int i=from-6; + if(board[i]==MAN1 || board[i]==KING1) + { + int k=from-12; + if(board[k]==FREE) + { + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + board[k]=MAN2; + resMax--; + if(!manCapture2(k,resMax)) turn(resMax,true); + resMax++; + board[k]=FREE; + board[i]=save; + board[from]=MAN2; + capture=true; + } + } + + i=from-5; + if(board[i]==MAN1 || board[i]==KING1) + { + int k=from-10; + if(board[k]==FREE) + { + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + board[k]=MAN2; + resMax--; + if(!manCapture2(k,resMax)) turn(resMax,true); + resMax++; + board[k]=FREE; + board[i]=save; + board[from]=MAN2; + capture=true; + } + } + + i=from+5; + if(board[i]==MAN1 || board[i]==KING1) + { + int k=from+10; + if(board[k]==FREE) + { + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + resMax--; + if(from>32) + { + board[k]=KING2; + if(!kingCapture2(k,UL,resMax)) turn(resMax,true); + } + else + { + board[k]=MAN2; + if(!manCapture2(k,resMax)) turn(resMax,true); + } + resMax++; + board[k]=FREE; + board[i]=save; + board[from]=MAN2; + capture=true; + } + } + + i=from+6; + if(board[i]==MAN1 || board[i]==KING1) + { + int k=from+12; + if(board[k]==FREE) + { + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + resMax--; + if(from>32) + { + board[k]=KING2; + if(!kingCapture2(k,UR,resMax)) turn(resMax,true); + } + else + { + board[k]=MAN2; + if(!manCapture2(k,resMax)) turn(resMax,true); + } + resMax++; + board[k]=FREE; + board[i]=save; + board[from]=MAN2; + capture=true; + } + } + + if(capture) return true; + return false; +} + + +bool RCheckers::kingCapture2(int from,int direction,int &resMax) +{ + int i; + for(i=from+direction;board[i]==FREE;i+=direction); + + if(board[i]==MAN1 || board[i]==KING1) + { + int k=i+direction; + if(board[k]==FREE) + { + bool capture=false; + int save=board[i]; + board[from]=FREE; + board[i]=NONE; + resMax--; + + for(;board[k]==FREE;k+=direction) + { + board[k]=KING2; + if(direction==UL || direction==DR) + { + if(kingCapture2(k,UR,resMax)) capture=true; + if(kingCapture2(k,DL,resMax)) capture=true; + } + else + { + if(kingCapture2(k,UL,resMax)) capture=true; + if(kingCapture2(k,DR,resMax)) capture=true; + } + board[k]=FREE; + } + + board[k-=direction]=KING2; + if(kingCapture2(k,direction,resMax)) capture=true; + board[k]=FREE; + + if(!capture) + for(;k!=i;k-=direction) + { + board[k]=KING2; + turn(resMax,true); + board[k]=FREE; + } + + resMax++; + board[i]=save; + board[from]=KING2; + return true; + } + } + return false; +} + + diff --git a/plugins/qcheckers_plugin/rcheckers.h b/plugins/qcheckers_plugin/rcheckers.h new file mode 100644 index 000000000..dcb11a6f4 --- /dev/null +++ b/plugins/qcheckers_plugin/rcheckers.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef RCHECKERS_H +#define RCHECKERS_H + +#include "checkers.h" +#include "pdn.h" + + +class RCheckers:public Checkers +{ + +public: + virtual bool go1(int,int); + + + virtual int type() const { return RUSSIAN; } + + virtual bool checkCapture1() const; + virtual bool checkCapture2() const; + +protected: + virtual bool checkCapture1(int) const; + +private: + + void kingMove2(int,int &); + + bool manCapture1(int,int,bool &); + bool kingCapture1(int,int,bool &); + + bool manCapture2(int,int &); + bool kingCapture2(int,int,int &); + +}; + +#endif + + diff --git a/plugins/qcheckers_plugin/themes/marble/Thumbs.db b/plugins/qcheckers_plugin/themes/marble/Thumbs.db new file mode 100644 index 000000000..4c1790994 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/marble/Thumbs.db differ diff --git a/plugins/qcheckers_plugin/themes/marble/frame.png b/plugins/qcheckers_plugin/themes/marble/frame.png new file mode 100644 index 000000000..4c65e86d5 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/marble/frame.png differ diff --git a/plugins/qcheckers_plugin/themes/marble/kingblack.png b/plugins/qcheckers_plugin/themes/marble/kingblack.png new file mode 100644 index 000000000..b6a596a4f Binary files /dev/null and b/plugins/qcheckers_plugin/themes/marble/kingblack.png differ diff --git a/plugins/qcheckers_plugin/themes/marble/kingwhite.png b/plugins/qcheckers_plugin/themes/marble/kingwhite.png new file mode 100644 index 000000000..64fc42f1a Binary files /dev/null and b/plugins/qcheckers_plugin/themes/marble/kingwhite.png differ diff --git a/plugins/qcheckers_plugin/themes/marble/manblack.png b/plugins/qcheckers_plugin/themes/marble/manblack.png new file mode 100644 index 000000000..32372efee Binary files /dev/null and b/plugins/qcheckers_plugin/themes/marble/manblack.png differ diff --git a/plugins/qcheckers_plugin/themes/marble/manwhite.png b/plugins/qcheckers_plugin/themes/marble/manwhite.png new file mode 100644 index 000000000..6262d38f1 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/marble/manwhite.png differ diff --git a/plugins/qcheckers_plugin/themes/marble/theme b/plugins/qcheckers_plugin/themes/marble/theme new file mode 100644 index 000000000..120b87409 --- /dev/null +++ b/plugins/qcheckers_plugin/themes/marble/theme @@ -0,0 +1 @@ +Marble diff --git a/plugins/qcheckers_plugin/themes/marble/tile1.png b/plugins/qcheckers_plugin/themes/marble/tile1.png new file mode 100644 index 000000000..5e41ce8e3 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/marble/tile1.png differ diff --git a/plugins/qcheckers_plugin/themes/marble/tile2.png b/plugins/qcheckers_plugin/themes/marble/tile2.png new file mode 100644 index 000000000..94f4d42a0 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/marble/tile2.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_big/Thumbs.db b/plugins/qcheckers_plugin/themes/simple_big/Thumbs.db new file mode 100644 index 000000000..fa85713aa Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_big/Thumbs.db differ diff --git a/plugins/qcheckers_plugin/themes/simple_big/frame.png b/plugins/qcheckers_plugin/themes/simple_big/frame.png new file mode 100644 index 000000000..932e11319 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_big/frame.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_big/kingblack.png b/plugins/qcheckers_plugin/themes/simple_big/kingblack.png new file mode 100644 index 000000000..856878b34 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_big/kingblack.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_big/kingwhite.png b/plugins/qcheckers_plugin/themes/simple_big/kingwhite.png new file mode 100644 index 000000000..e50d6ddf8 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_big/kingwhite.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_big/manblack.png b/plugins/qcheckers_plugin/themes/simple_big/manblack.png new file mode 100644 index 000000000..0963e2911 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_big/manblack.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_big/manwhite.png b/plugins/qcheckers_plugin/themes/simple_big/manwhite.png new file mode 100644 index 000000000..09fea5f20 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_big/manwhite.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_big/theme b/plugins/qcheckers_plugin/themes/simple_big/theme new file mode 100644 index 000000000..5aaa68e8c --- /dev/null +++ b/plugins/qcheckers_plugin/themes/simple_big/theme @@ -0,0 +1 @@ +Simple Big diff --git a/plugins/qcheckers_plugin/themes/simple_big/tile1.png b/plugins/qcheckers_plugin/themes/simple_big/tile1.png new file mode 100644 index 000000000..54e0f001d Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_big/tile1.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_big/tile2.png b/plugins/qcheckers_plugin/themes/simple_big/tile2.png new file mode 100644 index 000000000..9091400a9 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_big/tile2.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_small/Thumbs.db b/plugins/qcheckers_plugin/themes/simple_small/Thumbs.db new file mode 100644 index 000000000..e6e39a4bb Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_small/Thumbs.db differ diff --git a/plugins/qcheckers_plugin/themes/simple_small/frame.png b/plugins/qcheckers_plugin/themes/simple_small/frame.png new file mode 100644 index 000000000..f7e8e4e18 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_small/frame.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_small/kingblack.png b/plugins/qcheckers_plugin/themes/simple_small/kingblack.png new file mode 100644 index 000000000..e6ce1c2bf Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_small/kingblack.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_small/kingwhite.png b/plugins/qcheckers_plugin/themes/simple_small/kingwhite.png new file mode 100644 index 000000000..7cf9614b1 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_small/kingwhite.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_small/manblack.png b/plugins/qcheckers_plugin/themes/simple_small/manblack.png new file mode 100644 index 000000000..92bc5e29f Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_small/manblack.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_small/manwhite.png b/plugins/qcheckers_plugin/themes/simple_small/manwhite.png new file mode 100644 index 000000000..54ac91600 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_small/manwhite.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_small/theme b/plugins/qcheckers_plugin/themes/simple_small/theme new file mode 100644 index 000000000..bddb41245 --- /dev/null +++ b/plugins/qcheckers_plugin/themes/simple_small/theme @@ -0,0 +1 @@ +Simple Small diff --git a/plugins/qcheckers_plugin/themes/simple_small/tile1.png b/plugins/qcheckers_plugin/themes/simple_small/tile1.png new file mode 100644 index 000000000..1f5f4b269 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_small/tile1.png differ diff --git a/plugins/qcheckers_plugin/themes/simple_small/tile2.png b/plugins/qcheckers_plugin/themes/simple_small/tile2.png new file mode 100644 index 000000000..63f60d237 Binary files /dev/null and b/plugins/qcheckers_plugin/themes/simple_small/tile2.png differ diff --git a/plugins/qcheckers_plugin/toplevel.cc b/plugins/qcheckers_plugin/toplevel.cc new file mode 100644 index 000000000..c7048045f --- /dev/null +++ b/plugins/qcheckers_plugin/toplevel.cc @@ -0,0 +1,574 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pdn.h" +#include "toplevel.h" +#include "newgamedlg.h" +#include "view.h" +#include "common.h" + +#define CFG_THEME_PATH CFG_KEY"ThemePath" +#define CFG_FILENAME CFG_KEY"Filename" +#define CFG_KEEPDIALOG CFG_KEY"ShowKeepDialog" +#define CFG_NOTATION CFG_KEY"Notation" +#define CFG_NOT_ABOVE CFG_KEY"NotationAbove" +#define CFG_NOT_FONT CFG_KEY"NotationFont" +#define CFG_CLEAR_LOG CFG_KEY"ClearLogOnNewRound" + + +myTopLevel::myTopLevel() +{ + setWindowTitle(APPNAME); + setWindowIcon(QIcon(":/icons/biglogo.png")); + + m_newgame = new myNewGameDlg(this); + make_central_widget(); + make_actions(); + restore_settings(); + + /* + * new computer game. + */ + m_view->newGame(m_newgame->rules(), m_newgame->freePlacement(), + m_newgame->name(), + m_newgame->isWhite(), m_newgame->opponent(), + m_newgame->opponentName(), m_newgame->skill()); + + if(layout()) + layout()->setSizeConstraint(QLayout::SetFixedSize); +} + + +void myTopLevel::make_actions() +{ + // game menu actions + gameNew = new QAction(QIcon(":/icons/logo.png"), tr("&New..."), this); + gameNew->setShortcut(tr("CTRL+N", "File|New")); + connect(gameNew, SIGNAL(triggered()), this, SLOT(slot_new_game())); + + gameNextRound = new QAction(QIcon(":/icons/next.png"), + tr("&Next Round"), this); + connect(gameNextRound, SIGNAL(triggered()), + this, SLOT(slot_next_round())); + + gameStop = new QAction(QIcon(":/icons/stop.png"), tr("&Stop"), this); + connect(gameStop, SIGNAL(triggered()), m_view, SLOT(slotStopGame())); + + gameOpen = new QAction(QIcon(":/icons/fileopen.png"), tr("&Open..."), + this); + gameOpen->setShortcut(tr("CTRL+O", "File|Open")); + connect(gameOpen, SIGNAL(triggered()), this, SLOT(slot_open_game())); + + gameSave = new QAction(QIcon(":/icons/filesave.png"), tr("&Save..."), + this); + gameSave->setShortcut(tr("CTRL+S", "File|Save")); + connect(gameSave, SIGNAL(triggered()), this, SLOT(slot_save_game())); + + QAction* gameQuit = new QAction(QIcon(":/icons/exit.png"), tr("&Quit"), + this); + gameQuit->setShortcut(tr("CTRL+Q", "File|Quit")); + connect(gameQuit, SIGNAL(triggered()), + this, SLOT(close())); +// QApplication::instance(), SLOT(quit())); + + // view menu actions + viewNotation = new QAction(tr("&Show Notation"), this); + viewNotation->setCheckable(true); + connect(viewNotation, SIGNAL(toggled(bool)), + this, SLOT(slot_notation(bool))); + + viewNotationAbove = new QAction(tr("Show notation &above men"), this); + viewNotationAbove->setCheckable(true); + connect(viewNotationAbove, SIGNAL(toggled(bool)), + this, SLOT(slot_notation(bool))); + + // settings menu + settingsKeep = new QAction(tr("&Confirm aborting current game"), this); + settingsKeep->setCheckable(true); + // + settingsClearLog = new QAction(tr("Clear &log on new round"), this); + settingsClearLog->setCheckable(true); + connect(settingsClearLog, SIGNAL(toggled(bool)), + m_view, SLOT(slotClearLog(bool))); + // + QAction* settingsNotationFont = new QAction(tr("&Notation font..."), + this); + connect(settingsNotationFont, SIGNAL(triggered()), + this, SLOT(slot_notation_font())); + + // help menu actions + QAction* helpRules = new QAction(tr("&Rules of Play"), this); + helpRules->setShortcut(tr("F1", "Help|Help")); + connect(helpRules, SIGNAL(triggered()), this, SLOT(slot_help())); + + QAction* helpAbout = new QAction(QIcon(":/icons/logo.png"), + tr("&About")+" "APPNAME, this); + connect(helpAbout, SIGNAL(triggered()), this, SLOT(slot_about())); + + QAction* helpAboutQt = new QAction(tr("About &Qt"), this); + connect(helpAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + + + /* + * toolbar + */ + QToolBar* tb = addToolBar(tr("&Toolbar")); + tb->setMovable(false); + tb->addAction(gameNew); + tb->addAction(gameOpen); + tb->addAction(gameSave); + tb->addSeparator(); + tb->addAction(gameNextRound); + tb->addAction(gameStop); + + + /* + * menus + */ + QMenu* gameMenu = menuBar()->addMenu(tr("&Game")); + gameMenu->addAction(gameNew); + gameMenu->addAction(gameOpen); + gameMenu->addAction(gameSave); + gameMenu->addSeparator(); + gameMenu->addAction(gameNextRound); + gameMenu->addAction(gameStop); + gameMenu->addSeparator(); + gameMenu->addAction(gameQuit); + + viewMenu = menuBar()->addMenu(tr("&View")); + viewMenu->addAction(tb->toggleViewAction()); + viewMenu->addSeparator(); + viewMenu->addAction(viewNotation); + viewMenu->addAction(viewNotationAbove); + + QMenu* settingsMenu = menuBar()->addMenu(tr("&Settings")); + settingsMenu->addAction(settingsKeep); + settingsMenu->addSeparator(); + settingsMenu->addAction(settingsNotationFont); + settingsMenu->addSeparator(); + settingsMenu->addAction(settingsClearLog); + + QMenu* helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(helpRules); + helpMenu->addSeparator(); + helpMenu->addAction(helpAbout); + helpMenu->addAction(helpAboutQt); + + + /* + * THEMES. create a default theme. + */ + QActionGroup* themes_grp = new QActionGroup(this); + themes_grp->setExclusive(true); + + QAction* default_theme = new QAction(tr(DEFAULT_THEME), themes_grp); + default_theme->setCheckable(true); + m_themes[default_theme] = DEFAULT_THEME; + default_theme->setChecked(true); + set_theme(default_theme);//FIXME TODO + themes_grp->addAction(default_theme); + + viewMenu->addSeparator(); + viewMenu->addAction(default_theme); + read_themes(themes_grp, + viewMenu,QDir::homePath()+"/"USER_PATH"/"THEME_DIR); + //TODO-hardcoded + read_themes(themes_grp, + viewMenu, PREFIX"/share/kcheckers/"THEME_DIR); + + connect(themes_grp, SIGNAL(triggered(QAction*)), + this, SLOT(set_theme(QAction*))); +} + + +void myTopLevel::read_themes(QActionGroup* menu_grp, QMenu* menu, + const QString& path) +{ + QDir sharedir(path); + QStringList themes = sharedir.entryList(QDir::Dirs|QDir::Readable); + themes.removeAll("."); + themes.removeAll(".."); + + for(QStringList::iterator it=themes.begin(); it!=themes.end(); ++it) { + sharedir.cd(*it); + + QString theme_dir = sharedir.absolutePath(); + QString errtext; + + QStringList files + = sharedir.entryList(QDir::Files|QDir::Readable); + + // all files are there. + if(files.count()!=8 || + files.indexOf(THEME_TILE1) == -1 || + files.indexOf(THEME_TILE2) == -1 || + files.indexOf(THEME_FRAME) == -1 || + files.indexOf(THEME_MANBLACK) == -1 || + files.indexOf(THEME_MANWHITE) == -1 || + files.indexOf(THEME_KINGBLACK) == -1 || + files.indexOf(THEME_KINGWHITE) == -1 || + files.indexOf(THEME_FILE) == -1) { + // TODO not translated. + errtext += "Wrong number of files. "; + } + files.removeAll(THEME_FILE); + + // check pic size. + QSize size = QPixmap(theme_dir+"/"+files[0]).size(); + if(size.width()>MAX_TILE_SIZE || size.height()>MAX_TILE_SIZE) + // TODO not translated. + errtext += "Picture(s) too big. "; + + if(size.width()==0 || size.height()==0) + // TODO not translated. + errtext += "Width/Height is zero. "; + + // check pics all the same size. + foreach(QString file, files) { + if(QPixmap(theme_dir+"/"+file).size() != size) { + // TODO not translated. + errtext += "Pictures are different in size. "; + break; + } + } + + if(errtext.length()) { + // TODO not translated. + qWarning() << endl << "Theme in" + << sharedir.absolutePath() << endl << errtext; + + } else { + QString themename = sharedir.dirName(); + + /*TODO + QFile file(theme_dir+"/"+THEME_FILE); + if(file.open(QFile::ReadOnly)) { + QTextStream ts(&file); + if(!ts.atEnd()) + themename = ts.readLine(); + // try go get locale theme name + // TODO + QString locale = QString("[%1]=").arg(QTextCodec::locale()); + while(!ts.atEnd()) { + QString line = ts.readLine(); + if(line.startsWith(locale)) { + themename = line.mid(locale.length()); + break; + } + } + file.close(); + } + */ + // + QAction* action = new QAction(themename, this); + menu_grp->addAction(action); + menu->addAction(action); + action->setCheckable(true); + m_themes[action] = theme_dir; + } + + sharedir.cdUp(); + } +} + + +void myTopLevel::restore_settings() +{ + QSettings cfg(APPNAME, APPNAME); + + QString theme_path = cfg.value(CFG_THEME_PATH, DEFAULT_THEME) + .toString(); + for(myThemeMap::iterator it = m_themes.begin(); it!=m_themes.end();it++) + if(it.value() == theme_path) { + it.key()->setChecked(true); + set_theme(it.key()); + break; + } + + filename = cfg.value(CFG_FILENAME).toString(); + + viewNotation->setChecked(cfg.value(CFG_NOTATION, false).toBool()); + viewNotationAbove->setChecked(cfg.value(CFG_NOT_ABOVE, true).toBool()); + slot_notation(true); // here: arg is ignored by the function + + bool clear_log = cfg.value(CFG_CLEAR_LOG, true).toBool(); + settingsClearLog->setChecked(clear_log); + m_view->slotClearLog(clear_log); + + // + settingsKeep->setChecked(cfg.value(CFG_KEEPDIALOG, true).toBool()); + + QFont cfont; + if(cfont.fromString(cfg.value(CFG_NOT_FONT, "").toString())) + m_view->setNotationFont(cfont); + + // new game + m_newgame->readSettings(&cfg); +} + + +void myTopLevel::make_central_widget() +{ + m_view = new myView(this); + + connect(m_view, SIGNAL(working(bool)), + this, SLOT(slot_working(bool))); + + setCentralWidget(m_view); +} + + +void myTopLevel::warning(const QString& text) +{ + QMessageBox::warning(this, tr("Error")+" - "APPNAME, text); +} + + +void myTopLevel::information(const QString& caption, const QString& text) +{ + QDialog* dlg = new QDialog(this); + dlg->setModal(true); + dlg->setWindowTitle(caption+" - "APPNAME); + + // logo left + QLabel* logo = new QLabel(dlg); + logo->setPixmap(QPixmap(":/icons/dialog.png")); + + // text editor + QTextEdit* te = new QTextEdit(text, dlg); + te->setReadOnly(true); + te->setMinimumWidth(m_view->width()-100); + te->setMinimumHeight(m_view->height()-200); + + // close button + QPushButton* button = new QPushButton(tr("&Close"), dlg); + connect(button, SIGNAL(clicked()), dlg, SLOT(accept())); + + // Layout. + QHBoxLayout* hb = new QHBoxLayout(); + hb->addWidget(logo, 0, Qt::AlignTop); + hb->addWidget(te, 1); + + QHBoxLayout* hb_button = new QHBoxLayout(); + hb_button->addStretch(); + hb_button->addWidget(button); + + QVBoxLayout* vb = new QVBoxLayout(dlg); + vb->addLayout(hb, 1); + vb->addSpacing(5); + vb->addLayout(hb_button); + + // go + dlg->exec(); + delete dlg; +} + + +void myTopLevel::slot_save_game() +{ + QString fn = QFileDialog::getSaveFileName(this, + tr("Save Game")+" - "APPNAME, filename, "PDN Files (*."EXT")"); + if(!fn.isEmpty()) { + if(fn.right(3)!=EXT) + fn += "."EXT; + + if(m_view->savePdn(fn)) + filename = fn; + else + warning(tr("Could not save: ")+filename); + } +} + + +void myTopLevel::slot_open_game() +{ + QString fn = QFileDialog::getOpenFileName(this, + tr("Open Game")+" - "APPNAME, filename, "PDN Files (*."EXT")"); + if(!fn.isEmpty()) + open(fn); +} + + +void myTopLevel::open(const QString& fn) +{ + if(m_view->openPdn(fn)) + filename = fn; +} + + +void myTopLevel::closeEvent(QCloseEvent* e) +{ + if(!keep_game()) { + store_settings(); + e->accept(); + } else { + e->ignore(); + } +} + + +void myTopLevel::store_settings() +{ + QSettings config(APPNAME, APPNAME); + + for(myThemeMap::iterator it=m_themes.begin(); it!=m_themes.end(); it++) + if(it.key()->isChecked()) { + config.setValue(CFG_THEME_PATH, it.value()); + break; + } + + config.setValue(CFG_FILENAME, filename); + + config.setValue(CFG_NOTATION, viewNotation->isChecked()); + config.setValue(CFG_NOT_ABOVE, viewNotationAbove->isChecked()); + + config.setValue(CFG_KEEPDIALOG, settingsKeep->isChecked()); + config.setValue(CFG_NOT_FONT, m_view->notationFont().toString()); + config.setValue(CFG_CLEAR_LOG, settingsClearLog->isChecked()); + + // new game + m_newgame->writeSettings(&config); +} + + +void myTopLevel::set_theme(QAction* action) +{ + QString path = m_themes[action]; + m_view->setTheme(path); +} + + +void myTopLevel::slot_help() +{ + QString text = + tr("

In the beginning of game you have 12 checkers (men). " + "The men move forward only. The men can capture:" + "

    " + "
  • by jumping forward only (english rules);" + "
  • by jumping forward or backward (russian rules)." + "
" + "

A man which reaches the far side of the board becomes a king. " + "The kings move forward or backward:" + "

    " + "
  • to one square only (english rules);" + "
  • to any number of squares (russian rules)." + "
" + "

The kings capture by jumping forward or backward. " + "Whenever a player is able to make a capture he must do so."); + + information(tr("Rules of Play"), text); +} + + +void myTopLevel::slot_about() +{ + QString text = + APPNAME", a board game.
Version "VERSION"

" + COPYRIGHT"
" + ""HOMEPAGE"

" + "Contributors:
"CONTRIBS"

" + "This program is distributed under the terms " + "of the GNU General Public License."; + + information(tr("About"), text); +} + + +void myTopLevel::slot_new_game() +{ + if(keep_game()) + return; + + if(m_newgame->exec()==QDialog::Accepted) { + m_view->newGame(m_newgame->rules(), m_newgame->freePlacement(), + m_newgame->name(), + m_newgame->isWhite(), m_newgame->opponent(), + m_newgame->opponentName(), m_newgame->skill()); + } +} + + +void myTopLevel::slot_working(bool working) +{ + bool disable = !working; + + gameNew->setEnabled(disable); + gameSave->setEnabled(disable); + + gameNextRound->setEnabled(disable);// FIXME !m_view->isAborted()); + gameOpen->setEnabled(disable); + gameStop->setEnabled(!disable); + + m_view->setEnabled(disable); +} + + +bool myTopLevel::keep_game() +{ + if(!settingsKeep->isChecked() || m_view->isAborted()) + return false; + + int answer = QMessageBox::question(this, tr("Abort Game?")+" - "APPNAME, + tr("Current game will be lost if you continue.\n" + "Do you really want to discard it?"), + QMessageBox::Yes, QMessageBox::No); + + if(answer == QMessageBox::Yes) + return false; + + return true; +} + + +void myTopLevel::slot_next_round() +{ + if(!keep_game()) + m_view->slotNextRound(); +} + + +void myTopLevel::slot_notation_font() +{ + bool ok; + QFont font = QFontDialog::getFont(&ok, m_view->notationFont(), this); + if(ok) + m_view->setNotationFont(font); +} + + +void myTopLevel::slot_notation(bool) +{ + m_view->setNotation(viewNotation->isChecked(), + viewNotationAbove->isChecked()); +} + diff --git a/plugins/qcheckers_plugin/toplevel.h b/plugins/qcheckers_plugin/toplevel.h new file mode 100644 index 000000000..684dd6553 --- /dev/null +++ b/plugins/qcheckers_plugin/toplevel.h @@ -0,0 +1,104 @@ +/*************************************************************************** + * Copyright (C) 2002-2003 Andi Peredri * + * andi@ukr.net * + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef _TOPLEVEL_H_ +#define _TOPLEVEL_H_ + +#include +#include +#include + + +class myView; +class myNewGameDlg; + + +class myTopLevel : public QMainWindow +{ + Q_OBJECT + +public: + myTopLevel(); + + void open(const QString& filename); + +protected: + void closeEvent(QCloseEvent*); + +private slots: + void slot_help(); + void slot_about(); + + void slot_new_game(); + void slot_open_game(); + void slot_save_game(); + void slot_next_round(); + + void slot_notation(bool); + void slot_notation_font(); + + void slot_working(bool); + + void set_theme(QAction*); + + void warning(const QString& text); + + +private: + void make_actions(); + void make_central_widget(); + void restore_settings(); + void store_settings(); + + // add themes to this menu. + void read_themes(QActionGroup*, QMenu*, const QString& path); + + void information(const QString& caption, const QString& text); + + // returns true if the user wishes to keep current game + bool keep_game(); + +private: + QMenu* viewMenu; + // + QAction* gameNew; + QAction* gameStop; + QAction* gameOpen; + QAction* gameSave; + QAction* gameNextRound; + // + QAction* viewNotation; + QAction* viewNotationAbove; + // + QAction* settingsKeep; + QAction* settingsClearLog; + + QString filename; // PDN File Name + + myView* m_view; + myNewGameDlg* m_newgame; + + typedef QMap myThemeMap; + myThemeMap m_themes; +}; + +#endif + diff --git a/plugins/qcheckers_plugin/view.cc b/plugins/qcheckers_plugin/view.cc new file mode 100644 index 000000000..3628e8c8b --- /dev/null +++ b/plugins/qcheckers_plugin/view.cc @@ -0,0 +1,587 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include + +#include "pdn.h" +#include "echeckers.h" +#include "rcheckers.h" +#include "view.h" +#include "common.h" +#include "history.h" +#include "newgamedlg.h" + +#include "player.h" +#include "humanplayer.h" +#include "computerplayer.h" + + +#define MAX_CMD_LEN 80 +#define MOVE_PAUSE 1000 + +// this class is used to note differencies between moves. +class myDiff { +public: + myDiff(int pos, int from, int to) + : m_pos(pos), m_from(from), m_to(to) {} + int m_pos; + int m_from; + int m_to; +}; + + +myView::myView(QWidget* parent) + : QFrame(parent) +{ + /* + * board & info + */ + m_board = new myBoard(this); + connect(m_board, SIGNAL(fieldClicked(int)), + this, SLOT(slot_click(int))); + + m_history = new myHistory(this); + connect(m_history, SIGNAL(previewGame(int)), + this, SLOT(slot_preview_game(int))); + connect(m_history, SIGNAL(applyMoves(const QString&)), + this, SLOT(slot_apply_moves(const QString&))); + connect(m_history, SIGNAL(newMode(bool, bool)), + this, SLOT(slot_new_mode(bool, bool))); + connect(this, SIGNAL(working(bool)), + m_history, SLOT(slotWorking(bool))); + + QHBoxLayout* hb = new QHBoxLayout(0); + hb->addWidget(m_board); + hb->addSpacing(5); + hb->addWidget(m_history); + + + /* + * + */ + m_log = new QTextEdit(this); + m_log->setFixedHeight(100); //FIXME + m_log->setReadOnly(true); + + + /* + * it's the final layout. + */ + QVBoxLayout* vb = new QVBoxLayout(this); + vb->addLayout(hb); + vb->addWidget(m_log); + vb->setSizeConstraint(QLayout::SetFixedSize); + + + /* + * game init + */ + m_player = m_current = 0; +} + + +myView::~myView() +{ + if(m_player) { + delete m_player; + delete m_player->opponent(); + } +} + + +void myView::setEnabled(bool b) +{ + m_board->setEnabled(b); + if(b) + setCursor(Qt::ArrowCursor); // should be m_board bound. + else + setCursor(Qt::WaitCursor); +} + + +void myView::setTheme(const QString& path) +{ + m_board->setTheme(path, m_player ? m_player->isWhite() : true); + m_history->setFixedHeight(m_board->height()); +} + + +void myView::newGame(int rules, bool freeplace, + const QString& name, bool is_white, + int opponent, const QString& opp_name, int skill) +{ + m_freeplace_from = -1; + + if(m_player) { + delete m_player; + delete m_player->opponent(); + } + + m_board->setColorWhite(is_white); + + // create players + myPlayer* plr = new myHumanPlayer(name, is_white, false); + myPlayer* opp = 0; + if(opponent==HUMAN) + opp = new myHumanPlayer(opp_name, !is_white, true); + else + opp = new myComputerPlayer(opp_name, !is_white, skill); + + emit working(true); + + + /* + * set up player stuff. slots/signals. + */ + m_player = plr; + + plr->setOpponent(opp); + opp->setOpponent(plr); + + plr->disconnect(); + opp->disconnect(); + + connect(plr, SIGNAL(moveDone(const QString&)), + this, SLOT(slot_move_done(const QString&))); + + connect(opp, SIGNAL(moveDone(const QString&)), + this, SLOT(slot_move_done(const QString&))); + + + /* + * create game board. + */ + m_board->setGame(rules); + + m_board->reset(); + m_history->clear(); + + begin_game(1, freeplace); +} + + +void myView::begin_game(unsigned int round, bool freeplace) +{ + if(m_clear_log) + m_log->clear(); + + m_board->adjustNotation(m_player->isWhite()); + + m_history->newPdn(APPNAME" Game", freeplace); + m_history->setTag(PdnGame::Type, QString::number(m_board->type())); + m_history->setTag(PdnGame::Date, + QDate::currentDate().toString("yyyy.MM.dd")); + m_history->setTag(PdnGame::Result, "*"); + m_history->setTag(PdnGame::Round, QString::number(round)); + + + /* + * go! + */ + myPlayer* last_player = get_first_player()->opponent(); + + m_game_over = false; + m_aborted = false; + m_current = last_player; + + // setup names + if(m_player->isWhite()) { + m_history->setTag(PdnGame::White, m_player->name()); + m_history->setTag(PdnGame::Black, m_player->opponent()->name()); + } else { + m_history->setTag(PdnGame::White, m_player->opponent()->name()); + m_history->setTag(PdnGame::Black, m_player->name()); + } + + if(m_history->isFreePlacement()) + emit working(false); + else + slot_move_done(m_board->game()->toString(false)); +} + + +bool myView::check_game_over() +{ + if(m_game_over) // no further checks + return true; + + m_game_over = true; + + bool player_can = m_board->game()->checkMove1() + || m_board->game()->checkCapture1(); + bool opp_can = m_board->game()->checkMove2() + || m_board->game()->checkCapture2(); + + // player cannot go but opponent can -> player lost. + if(/*FIXME*/m_player==m_current && !player_can && opp_can) { + you_won(false); + return m_game_over; + } + // player can go but opponent cannot -> player won. + if(/*FIXME*/m_player!=m_current && player_can && !opp_can) { + you_won(true); + return m_game_over; + } + // neither of the player can go -> draw. + if(!player_can && !opp_can) { + add_log(myView::System, tr("Drawn game.")); + m_history->setTag(PdnGame::Result, "1/2-1/2"); + return m_game_over; + } + + m_game_over = false; + return m_game_over; +} + + +void myView::slot_click(int field_num) +{ + if(m_game_over || m_aborted) + return; + + if(m_history->isPaused()) { + if(m_history->isFreePlacement()) { + // FIXME - hightlight fields + if(m_freeplace_from < 0) { + m_freeplace_from = field_num; + m_board->selectField(field_num, true); + } else { + m_board->selectField(m_freeplace_from, false); + m_board->doFreeMove(m_freeplace_from, + field_num); + m_freeplace_from = -1; + } + } + } else { + bool select = false; + QString err_msg; + + if(!m_current->fieldClicked(field_num, &select, err_msg)) { + add_log(myView::Warning, m_current->name()+": " + + (err_msg.length() + ? err_msg + : tr("Invalid move."))); + } else { + m_board->selectField(field_num, select); + } + } +} + + +void myView::slotNextRound() +{ + if(m_aborted) + return; + + m_player->setWhite(!m_player->isWhite()); + m_player->opponent()->setWhite(!m_player->isWhite()); + + m_board->setColorWhite(m_player->isWhite()); + m_board->reset(); + + unsigned int round = m_history->getTag(PdnGame::Round).toUInt() + 1; + begin_game(round, m_history->isFreePlacement()); +} + + +void myView::slotStopGame() +{ + m_player->stop(); + m_player->opponent()->stop(); +} + + +void myView::stop_game(const QString& msg) +{ + m_game_over = true; + m_aborted = true; + + QString text(tr("Game aborted.")+(!msg.isEmpty() ? "\n"+msg : "")); + add_log(myView::System, text); + + emit working(false); +} + + +void myView::slot_move_done(const QString& board_str) +{ + if(m_history->isPaused()) // FIXME - ??? + return; + + perform_jumps(m_board->game()->toString(false), board_str); + + // show who is next? + m_current = m_current->opponent(); + m_history->setCurrent(m_current->name()); + + if(!m_current->isHuman()) { + emit working(true); + } else { + emit working(false); + } + + if(m_current->opponent()->isHuman() && !m_current->isHuman()) + QTimer::singleShot(MOVE_PAUSE, this, + SLOT(slot_move_done_step_two())); + else + slot_move_done_step_two(); +} + +void myView::slot_move_done_step_two() +{ + // + m_current->yourTurn(m_board->game()); + + if(check_game_over()) + emit working(false); +} + + +void myView::you_won(bool yes) +{ + if(yes&&m_player->isWhite() || !yes&&!m_player->isWhite()) { + m_history->setTag(PdnGame::Result, "1-0"); // white wins + add_log(myView::System, tr("White wins!")); + } else { + m_history->setTag(PdnGame::Result, "0-1"); // black wins + add_log(myView::System, tr("Black wins!")); + } + + emit working(false); +} + + +bool myView::openPdn(const QString& fn) +{ + emit working(false); + + m_current->stop(); + + QString log_text; + if(!m_history->openPdn(fn, log_text)) { + return false; + } + + if(log_text.length()) { + add_log(myView::System, tr("Opened:")+" "+fn); + add_log(myView::Error, log_text.trimmed()); + add_log(myView::Warning, tr("Warning! Some errors occured.")); + } + + return true; +} + + +bool myView::savePdn(const QString& fn) +{ + if(!m_history->savePdn(fn)) { + qDebug() << __PRETTY_FUNCTION__ << "failed."; + return false; + } + add_log(myView::System, tr("Saved:")+" "+fn); + return true; +} + + +void myView::slot_new_mode(bool paused, bool freeplace) +{ + if(paused) { + if(freeplace) + m_board->setCursor(Qt::PointingHandCursor); + else + m_board->setCursor(Qt::ForbiddenCursor); + } else { + m_board->setCursor(Qt::ArrowCursor); + } + + // resume game: ask info for who is next, black or white.XXX FIXME TODO + if(!paused) { + myPlayer* next = 0; + if(m_history->moveCount()%2==0) + next = get_first_player(); + else + next = get_first_player()->opponent(); + + m_current = next->opponent(); + slot_move_done(m_board->game()->toString(false)); + } +} + + +void myView::slot_preview_game(int rules) +{ + if(rules!=RUSSIAN && rules!=ENGLISH) { + qDebug() << __PRETTY_FUNCTION__ << rules << "Wrong game type."; + return; + } + + m_board->setGame(rules); + + if(m_player->isWhite() && rules==RUSSIAN) { + m_player->setName(m_history->getTag(PdnGame::White)); + m_player->opponent()->setName(m_history->getTag(PdnGame::Black)); + } else { + m_player->setName(m_history->getTag(PdnGame::Black)); + m_player->opponent()->setName(m_history->getTag(PdnGame::White)); + } + + // FIXME + m_player->setWhite(rules==RUSSIAN);// FIXME TODO + m_player->opponent()->setWhite(!m_player->isWhite()); + m_board->setColorWhite(m_player->isWhite()); + m_board->adjustNotation(m_player->isWhite()); +} + + +void myView::slot_apply_moves(const QString& moves) +{ + QStringList move_list= moves.split(MOVE_SPLIT, QString::SkipEmptyParts); + + m_board->reset(); + + bool white_player = get_first_player()->isWhite(); + foreach(QString move, move_list) { + m_board->doMove(move, white_player); + white_player = !white_player; + } + + // set current player who pulls next. assume is white. + m_current = (m_player->isWhite() ? m_player : m_player->opponent()); + if(!white_player) + m_current = m_current->opponent(); + m_history->setCurrent(m_current->name()); +} + + +void myView::add_log(enum LogType type, const QString& text) +{ + QString str = text; + str = str.replace('<', "<"); + str = str.replace('>', ">"); + + QString tag_b, tag_e; + switch(type) { + case Error: tag_b="

    "; tag_e="
"; break; + case Warning: tag_b=""; tag_e=""; break; + case System: tag_b=""; tag_e=""; break; + default: break; + } + + m_log->append(tag_b + str + tag_e); + + m_log->ensureCursorVisible(); +} + + +void myView::perform_jumps(const QString& from_board, const QString& to_board) +{ + if(from_board==to_board) { + return; + } + + QString new_to_board = to_board; + + //qDebug("F:%s\nT:%s", from_board.latin1(), new_to_board.latin1()); + + // diff + QList diff_list; + + // collect information + for(int i=0; i<32; i++) { + if(from_board[2*i]!=new_to_board[2*i] + || from_board[2*i+1]!=new_to_board[2*i+1]) { + myDiff* diff = new myDiff(i, + from_board.mid(2*i, 2).toInt(), + new_to_board.mid(2*i, 2).toInt()); + diff_list.append(diff); + + //qDebug(">%d: %d->%d", diff->m_pos, diff->m_from, diff->m_to); + } + } + + int from_pos = -1; + int to_pos = -1; + bool captured = (diff_list.count()>2); + + int man = -1; + // find the dest. first: so we have the man moved. + foreach(myDiff* diff, diff_list) { + if(diff->m_to!=FREE) { + man = diff->m_to; + to_pos = diff->m_pos; + break; + } + } + + int king = -1; + switch(man) { + case MAN1: king=KING1; break; + case KING1: king=MAN1; break; + case MAN2: king=KING2; break; + case KING2: king=MAN2; break; + } + // find src. + foreach(myDiff* diff, diff_list) { + if(diff->m_to==FREE) { + if(diff->m_from==man || diff->m_from==king) { + from_pos = diff->m_pos; + break; + } + } + } + + /* + qDebug(" to_pos=%d with man/king=%d from=%d", to_pos, man, + from_pos); + */ + + // finally - animate :) + QString move = m_board->doMove(from_pos, to_pos, m_current->isWhite()); + m_history->appendMove(move.replace("?", captured ? "x" : "-" ), ""); + + qDeleteAll(diff_list); +} + +void myView::setNotation(bool enabled, bool show_above) +{ + // TODO - intermediate function - remove somehow! + m_board->setNotation(enabled, show_above); +} + + +void myView::setNotationFont(const QFont& f) +{ + // TODO - intermediate function - remove somehow! + m_board->setNotationFont(f); +} + + +myPlayer* myView::get_first_player() const +{ + bool white = m_board->type()==RUSSIAN ? true : false; + // it is white. + if((white && m_player->isWhite()) || (!white && !m_player->isWhite())) + return m_player; + return m_player->opponent(); +} + + diff --git a/plugins/qcheckers_plugin/view.h b/plugins/qcheckers_plugin/view.h new file mode 100644 index 000000000..7330325d6 --- /dev/null +++ b/plugins/qcheckers_plugin/view.h @@ -0,0 +1,122 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 Artur Wiebe * + * wibix@gmx.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _VIEW_H_ +#define _VIEW_H_ + + +#include +#include +#include +#include + + +#include "board.h" + + +class Pdn; +class myPlayer; +class myHistory; + + +class myView : public QFrame +{ + Q_OBJECT + +public: + myView(QWidget* parent); + ~myView(); + + void newGame(int rules, bool free_place, + const QString& name, bool is_white, + int opponent, const QString& opp_name, int skill); + bool openPdn(const QString& fn); + bool savePdn(const QString& fn); + + void setTheme(const QString& theme_path); + + bool isAborted() const { return m_aborted; } + + void setNotation(bool enabled, bool show_above); + void setNotationFont(const QFont& f); + QFont notationFont() const { return m_board->font(); } + +public slots: + virtual void setEnabled(bool); + + void slotClearLog(bool b) { m_clear_log = b; } + + void slotStopGame(); + void slotNextRound(); + +signals: + void working(bool); + +private slots: + void slot_click(int); + + void slot_move_done(const QString& board_str); + void slot_move_done_step_two(); + + void slot_preview_game(int game_type); + void slot_apply_moves(const QString& moves); + void slot_new_mode(bool paused, bool freeplace); + +private: + void begin_game(unsigned int round, bool freeplacement); + + void perform_jumps(const QString& from_board, const QString& to_board); + bool extract_move(const QString& move, int* from_num, int* to_num); + + void stop_game(const QString&); + void you_won(bool really); + bool check_game_over(); + + enum LogType { + None, + Error, + Warning, + System, + User, + Opponent, + }; + void add_log(enum LogType type, const QString& text); + + myPlayer* get_first_player() const; + +private: + bool m_clear_log; + + bool m_game_over;// need this to avoid multiple calls to isGameOver() + bool m_aborted; + + myPlayer* m_player; + myPlayer* m_current; + + myBoard* m_board; + myHistory* m_history; + QTextEdit* m_log; + + int m_freeplace_from; +}; + + +#endif + diff --git a/plugins/qdiagram_plugin/DiagramPlugin.cpp b/plugins/qdiagram_plugin/DiagramPlugin.cpp new file mode 100644 index 000000000..c574352f2 --- /dev/null +++ b/plugins/qdiagram_plugin/DiagramPlugin.cpp @@ -0,0 +1,33 @@ +//#include +//#include +//#include + +#include "DiagramPlugin.h" +#include "mainwindow.h" + +QString +DiagramPlugin::pluginDescription() const +{ + QString res; + res = "A qdiagram plugin" ; + + return res; +} + +QString +DiagramPlugin::pluginName() const +{ + return "QDiagram" ; +} + +QWidget* +DiagramPlugin::pluginWidget(QWidget * parent ) +{ + MainWindow* window = new MainWindow(); + //window->openImage(":/images/example.jpg"); + + return window; +} + + +Q_EXPORT_PLUGIN2(qdiagram_plugin, DiagramPlugin) diff --git a/plugins/qdiagram_plugin/DiagramPlugin.h b/plugins/qdiagram_plugin/DiagramPlugin.h new file mode 100644 index 000000000..c6d9e7875 --- /dev/null +++ b/plugins/qdiagram_plugin/DiagramPlugin.h @@ -0,0 +1,27 @@ +#ifndef _HWA_PLUGIN_H_ +#define _HWA_PLUGIN_H_ + +#include + +#include +#include + +#include + +#include + +class DiagramPlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/qdiagram_plugin/cmd.exe.lnk b/plugins/qdiagram_plugin/cmd.exe.lnk new file mode 100644 index 000000000..7dde98ed7 Binary files /dev/null and b/plugins/qdiagram_plugin/cmd.exe.lnk differ diff --git a/plugins/qdiagram_plugin/diagramdrawitem.cpp b/plugins/qdiagram_plugin/diagramdrawitem.cpp new file mode 100644 index 000000000..68abd20e8 --- /dev/null +++ b/plugins/qdiagram_plugin/diagramdrawitem.cpp @@ -0,0 +1,374 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include +#include + +#include "diagramdrawitem.h" +#include "diagramscene.h" + +//! [0] +DiagramDrawItem::DiagramDrawItem(DiagramType diagramType, QMenu *contextMenu, + QGraphicsItem *parent, QGraphicsScene *scene) + : DiagramItem(contextMenu,parent,scene) +{ + myPos2=pos(); + myDiagramType = diagramType; + myContextMenu = contextMenu; + + myPolygon=createPath(); + setPolygon(myPolygon); + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); + setAcceptHoverEvents(true); + myHoverPoint=-1; + mySelPoint=-1; + myHandlerWidth=2.0; +} +//! [0] +DiagramDrawItem::DiagramDrawItem(const DiagramDrawItem& diagram) + : DiagramItem(diagram.myContextMenu,diagram.parentItem(),0) +{ + + myDiagramType=diagram.myDiagramType; + // copy from general GraphcsItem + setBrush(diagram.brush()); + setPen(diagram.pen()); + setTransform(diagram.transform()); + myPos2=diagram.myPos2; + myPolygon=createPath(); + setPolygon(myPolygon); + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); + setAcceptHoverEvents(true); + myHoverPoint=-1; + mySelPoint=-1; + myHandlerWidth=2.0; + +} +//! [1] +QPolygonF DiagramDrawItem::createPath() +{ + qreal dx=myPos2.x(); + qreal dy=myPos2.y(); + + QPainterPath path; + QPolygonF polygon; + switch (myDiagramType) { + case Rectangle: + path.moveTo(0, 0); + path.lineTo(dx,0); + path.lineTo(dx,dy); + path.lineTo(0,dy); + path.lineTo(0,0); + polygon = path.toFillPolygon(); + break; + case Ellipse: + path.addEllipse(0,0,dx,dy); + polygon = path.toFillPolygon(); + break; + default: + break; + polygon = 0; + } + return polygon; +} +//! [4] +QPixmap DiagramDrawItem::image() const +{ + QPixmap pixmap(250, 250); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + painter.setPen(QPen(Qt::black, 8)); + painter.translate(10, 10); + painter.drawPolyline(myPolygon); + + return pixmap; +} +//! [4] + +//! [5] +void DiagramDrawItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + scene()->clearSelection(); + setSelected(true); + myContextMenu->exec(event->screenPos()); +} +//! [5] + +//! [6] +QVariant DiagramDrawItem::itemChange(GraphicsItemChange change, + const QVariant &value) +{ + if (change == QGraphicsItem::ItemPositionChange) { + ; + } + + return value; +} +//! [6] +DiagramItem* DiagramDrawItem::copy() +{ + DiagramDrawItem* newDiagramDrawItem=new DiagramDrawItem(*this); + return dynamic_cast(newDiagramDrawItem); +} + +void DiagramDrawItem::setPos2(qreal x,qreal y) +{ + myPos2=mapFromScene(QPointF(x,y)); + myPolygon=createPath(); + setPolygon(myPolygon); +} + +void DiagramDrawItem::setPos2(QPointF newPos) +{ + prepareGeometryChange(); + myPos2=mapFromScene(newPos); + myPolygon=createPath(); + setPolygon(myPolygon); +} + +void DiagramDrawItem::setDimension(QPointF newPos) +{ + prepareGeometryChange(); + myPos2=newPos; + myPolygon=createPath(); + setPolygon(myPolygon); +} + +QPointF DiagramDrawItem::getDimension() +{ + return myPos2; +} + +void DiagramDrawItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, + QWidget *) +{ + painter->setPen(pen()); + painter->setBrush(brush()); + painter->drawPolygon(polygon()); + // selected + if(isSelected()){ + // Rect + QPen selPen=QPen(Qt::DashLine); + selPen.setColor(Qt::black); + QBrush selBrush=QBrush(Qt::NoBrush); + painter->setBrush(selBrush); + painter->setPen(selPen); + painter->drawRect(QRectF(QPointF(0,0),myPos2)); + // Draghandles + selBrush=QBrush(Qt::cyan,Qt::SolidPattern); + selPen=QPen(Qt::cyan); + painter->setBrush(selBrush); + painter->setPen(selPen); + QPointF point; + for(int i=0;i<8;i++) + { + if(i<3) point=QPointF(myPos2.x()/2*i,0); + if(i==3) point=QPointF(myPos2.x(),myPos2.y()/2); + if(i>3 && i<7) point=QPointF(myPos2.x()/2*(i-4),myPos2.y()); + if(i==7) point=QPointF(0,myPos2.y()/2); + if(i==myHoverPoint){ + painter->setBrush(QBrush(Qt::red)); + } + // Rect around valid point + painter->drawRect(QRectF(point-QPointF(2,2),point+QPointF(2,2))); + if(i==myHoverPoint){ + painter->setBrush(selBrush); + } + }// foreach + }// if +} + +void DiagramDrawItem::hoverMoveEvent(QGraphicsSceneHoverEvent *e) { +#ifdef DEBUG + std::cout << "entered" << std::endl; + std::cout << e->pos().x() << "/" << e->pos().y() << std::endl; +#endif + if (isSelected()) { + QPointF hover_point = e -> pos(); + QPointF point; + for(myHoverPoint=0;myHoverPoint<8;myHoverPoint++){ + if(myHoverPoint<3) point=QPointF(myPos2.x()/2*myHoverPoint,0); + if(myHoverPoint==3) point=QPointF(myPos2.x(),myPos2.y()/2); + if(myHoverPoint>3 && myHoverPoint<7) point=QPointF(myPos2.x()/2*(myHoverPoint-4),myPos2.y()); + if(myHoverPoint==7) point=QPointF(0,myPos2.y()/2); + if(hasClickedOn(hover_point,point)) break; + }//for + if(myHoverPoint==8) myHoverPoint=-1; + else update(); + } + DiagramItem::hoverEnterEvent(e); +} + +void DiagramDrawItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *e) { +#ifdef DEBUG + std::cout << "left" << std::endl; +#endif + if (isSelected()) { + if(myHoverPoint>-1){ + myHoverPoint=-1; + update(); + } + } + DiagramItem::hoverLeaveEvent(e); +} + +bool DiagramDrawItem::hasClickedOn(QPointF press_point, QPointF point) const { + return ( + press_point.x() >= point.x() - myHandlerWidth &&\ + press_point.x() < point.x() + myHandlerWidth &&\ + press_point.y() >= point.y() - myHandlerWidth &&\ + press_point.y() < point.y() + myHandlerWidth + ); +} + +QPointF DiagramDrawItem::onGrid(QPointF pos) +{ + DiagramScene* myScene = dynamic_cast(scene()); + QPointF result = myScene->onGrid(pos); + return result; +} + +QPainterPath DiagramDrawItem::shape() const { + QPainterPath myPath; + myPath.addPolygon(polygon()); + if(isSelected()){ + QPointF point; + for(int i=0;i<8;i++) + { + if(i<3) point=QPointF(myPos2.x()/2*i,0); + if(i==3) point=QPointF(myPos2.x(),myPos2.y()/2); + if(i>3 && i<7) point=QPointF(myPos2.x()/2*(i-4),myPos2.y()); + if(i==7) point=QPointF(0,myPos2.y()/2); + // Rect around valid point + myPath.addRect(QRectF(point-QPointF(myHandlerWidth,myHandlerWidth),point+QPointF(myHandlerWidth,myHandlerWidth))); + }// for + }// if + return myPath; +} + +QRectF DiagramDrawItem::boundingRect() const +{ + qreal extra = pen().width()+20 / 2.0 + myHandlerWidth; + qreal minx = myPos2.x() < 0 ? myPos2.x() : 0; + qreal maxx = myPos2.x() < 0 ? 0 : myPos2.x() ; + qreal miny = myPos2.y() < 0 ? myPos2.y() : 0; + qreal maxy = myPos2.y() < 0 ? 0 : myPos2.y() ; + + QRectF newRect = QRectF(minx,miny,maxx-minx,maxy-miny) + .adjusted(-extra, -extra, extra, extra); + return newRect; +} + +void DiagramDrawItem::mousePressEvent(QGraphicsSceneMouseEvent *e) { + if(isSelected()){ + if (e -> buttons() & Qt::LeftButton) { + QPointF mouse_point = e -> pos(); + QPointF point; + for(mySelPoint=0;mySelPoint<8;mySelPoint++){ + if(mySelPoint<3) point=QPointF(myPos2.x()/2*mySelPoint,0); + if(mySelPoint==3) point=QPointF(myPos2.x(),myPos2.y()/2); + if(mySelPoint>3 && mySelPoint<7) point=QPointF(myPos2.x()/2*(mySelPoint-4),myPos2.y()); + if(mySelPoint==7) point=QPointF(0,myPos2.y()/2); + if(hasClickedOn(mouse_point,point)) break; + }//for + if(mySelPoint==8) mySelPoint=-1; + else e->accept(); + } + } + DiagramItem::mousePressEvent(e); +} + +void DiagramDrawItem::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { + // left click + if ((e -> buttons() & Qt::LeftButton)&&(mySelPoint>-1)) { + QPointF mouse_point = onGrid(e -> pos()); +#ifdef DEBUG + std::cout << "Corner: " << mySelPoint << std::endl; + std::cout << "mouse: " << mouse_point.x() << "/" << mouse_point.y() << std::endl; + std::cout << "pos2: " << myPos2.x() << "/" << myPos2.y() << std::endl; +#endif + prepareGeometryChange(); + switch (mySelPoint) { + case 0: + myPos2=myPos2-mouse_point; + setPos(mapToScene(mouse_point)); + break; + case 1: + setPos(pos().x(),mapToScene(mouse_point).y()); + myPos2.setY(myPos2.y()-mouse_point.y()); + break; + case 2: + myPos2.setX(mouse_point.x()); + setPos(pos().x(),mapToScene(mouse_point).y()); + myPos2.setY(myPos2.y()-mouse_point.y()); + break; + case 3: + myPos2.setX(mouse_point.x()); + break; + case 6: + myPos2.setX(mouse_point.x()); + myPos2.setY(mouse_point.y()); + break; + case 5: + myPos2.setY(mouse_point.y()); + break; + case 4: + myPos2.setY(mouse_point.y()); + setPos(mapToScene(mouse_point).x(),pos().y()); + myPos2.setX(myPos2.x()-mouse_point.x()); + break; + case 7: + setPos(mapToScene(mouse_point).x(),pos().y()); + myPos2.setX(myPos2.x()-mouse_point.x()); + break; + default: + break; + } + myPolygon=createPath(); + setPolygon(myPolygon); + } + else + DiagramItem::mouseMoveEvent(e); +} diff --git a/plugins/qdiagram_plugin/diagramdrawitem.h b/plugins/qdiagram_plugin/diagramdrawitem.h new file mode 100644 index 000000000..406b7d216 --- /dev/null +++ b/plugins/qdiagram_plugin/diagramdrawitem.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef DiagramDrawItem_H +#define DiagramDrawItem_H + +#include +#include +#include "diagramitem.h" + +QT_BEGIN_NAMESPACE +class QPixmap; +class QGraphicsItem; +class QGraphicsScene; +class QTextEdit; +class QGraphicsSceneMouseEvent; +class QMenu; +class QGraphicsSceneContextMenuEvent; +class QPainter; +class QStyleOptionGraphicsItem; +class QWidget; +class QPolygonF; +QT_END_NAMESPACE + +//! [0] +class DiagramDrawItem : public DiagramItem +{ +public: + enum { Type = UserType + 16 }; + enum DiagramType { Ellipse, Rectangle }; + + DiagramDrawItem(DiagramType diagramType, QMenu *contextMenu, + QGraphicsItem *parent = 0, QGraphicsScene *scene = 0); + DiagramDrawItem(const DiagramDrawItem& diagram);//copy constructor + + DiagramItem* copy(); + + DiagramType diagramType() const + { return myDiagramType; } + QPolygonF polygon() const + { return myPolygon; } + QPixmap image() const; + int type() const + { return Type;} + + void setPos2(qreal x,qreal y); + void setPos2(QPointF pos); + QPointF getPos2() const + { return mapToScene(myPos2); } + + void setDimension(QPointF newPos); + QPointF getDimension(); + + +protected: + void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + QPolygonF createPath(); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); + QPainterPath shape() const; + QRectF boundingRect() const; + void hoverMoveEvent(QGraphicsSceneHoverEvent *e); + void hoverLeaveEvent(QGraphicsSceneHoverEvent *e); + void mousePressEvent(QGraphicsSceneMouseEvent *e); + void mouseMoveEvent(QGraphicsSceneMouseEvent *e); + bool hasClickedOn(QPointF press_point, QPointF point) const ; + QPointF onGrid(QPointF pos); + +private: + DiagramType myDiagramType; + QPolygonF myPolygon; + QMenu *myContextMenu; + QPointF myPos2; + int myHoverPoint,mySelPoint; + qreal myHandlerWidth; +}; +//! [0] + +#endif diff --git a/plugins/qdiagram_plugin/diagramitem.cpp b/plugins/qdiagram_plugin/diagramitem.cpp new file mode 100644 index 000000000..daf142c25 --- /dev/null +++ b/plugins/qdiagram_plugin/diagramitem.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include + +#include "diagramitem.h" + +//! [0] +DiagramItem::DiagramItem(DiagramType diagramType, QMenu *contextMenu, + QGraphicsItem *parent, QGraphicsScene *scene) + : QGraphicsPolygonItem(parent, scene) +{ + myDiagramType = diagramType; + myContextMenu = contextMenu; + + QPainterPath path; + switch (myDiagramType) { + case StartEnd: + path.moveTo(200, 50); + path.arcTo(150, 0, 50, 50, 0, 90); + path.arcTo(50, 0, 50, 50, 90, 90); + path.arcTo(50, 50, 50, 50, 180, 90); + path.arcTo(150, 50, 50, 50, 270, 90); + path.lineTo(200, 25); + myPolygon = path.toFillPolygon(); + break; + case Conditional: + myPolygon << QPointF(-100, 0) << QPointF(0, 100) + << QPointF(100, 0) << QPointF(0, -100) + << QPointF(-100, 0); + break; + case Step: + myPolygon << QPointF(-100, -100) << QPointF(100, -100) + << QPointF(100, 100) << QPointF(-100, 100) + << QPointF(-100, -100); + break; + default: + myPolygon << QPointF(-120, -80) << QPointF(-70, 80) + << QPointF(120, 80) << QPointF(70, -80) + << QPointF(-120, -80); + break; + } + setPolygon(myPolygon); + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); +} + +DiagramItem::DiagramItem(QMenu *contextMenu, + QGraphicsItem *parent, QGraphicsScene *scene) + : QGraphicsPolygonItem(parent, scene) +{ + myDiagramType = None; + myContextMenu = contextMenu; + + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); +} +//! [0] +DiagramItem::DiagramItem(const DiagramItem& diagram) +{ + QGraphicsPolygonItem(diagram.parentItem(),diagram.scene()); + //QGraphicsPolygonItem(static_cast(diagram)); + // copy from general GraphcsItem + setBrush(diagram.brush()); + setPen(diagram.pen()); + setTransform(diagram.transform()); + + // copy DiagramItem + myDiagramType = diagram.myDiagramType; + myContextMenu = diagram.myContextMenu; + + QPainterPath path; + switch (myDiagramType) { + case StartEnd: + path.moveTo(200, 50); + path.arcTo(150, 0, 50, 50, 0, 90); + path.arcTo(50, 0, 50, 50, 90, 90); + path.arcTo(50, 50, 50, 50, 180, 90); + path.arcTo(150, 50, 50, 50, 270, 90); + path.lineTo(200, 25); + myPolygon = path.toFillPolygon(); + break; + case Conditional: + myPolygon << QPointF(-100, 0) << QPointF(0, 100) + << QPointF(100, 0) << QPointF(0, -100) + << QPointF(-100, 0); + break; + case Step: + myPolygon << QPointF(-100, -100) << QPointF(100, -100) + << QPointF(100, 100) << QPointF(-100, 100) + << QPointF(-100, -100); + break; + default: + myPolygon << QPointF(-120, -80) << QPointF(-70, 80) + << QPointF(120, 80) << QPointF(70, -80) + << QPointF(-120, -80); + break; + } + setPolygon(myPolygon); + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); +} + + +//! [4] +QPixmap DiagramItem::image() const +{ + QPixmap pixmap(250, 250); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + painter.setPen(QPen(Qt::black, 8)); + painter.translate(125, 125); + painter.drawPolyline(myPolygon); + + return pixmap; +} +//! [4] + +//! [5] +void DiagramItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + scene()->clearSelection(); + setSelected(true); + myContextMenu->exec(event->screenPos()); +} +//! [5] + +//! [6] +QVariant DiagramItem::itemChange(GraphicsItemChange change, + const QVariant &value) +{ + if (change == QGraphicsItem::ItemPositionChange) { + ; + } + + return value; +} +//! [6] +DiagramItem* DiagramItem::copy() +{ + DiagramItem* newDiagramItem=new DiagramItem(*this); + return newDiagramItem; +} diff --git a/plugins/qdiagram_plugin/diagramitem.h b/plugins/qdiagram_plugin/diagramitem.h new file mode 100644 index 000000000..3b70aa87d --- /dev/null +++ b/plugins/qdiagram_plugin/diagramitem.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef DIAGRAMITEM_H +#define DIAGRAMITEM_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QPixmap; +class QGraphicsItem; +class QGraphicsScene; +class QTextEdit; +class QGraphicsSceneMouseEvent; +class QMenu; +class QGraphicsSceneContextMenuEvent; +class QPainter; +class QStyleOptionGraphicsItem; +class QWidget; +class QPolygonF; +QT_END_NAMESPACE + +//! [0] +class DiagramItem : public QGraphicsPolygonItem +{ +public: + enum { Type = UserType + 15 }; + enum DiagramType { Step, Conditional, StartEnd, Io, None }; + + DiagramItem(DiagramType diagramType, QMenu *contextMenu, + QGraphicsItem *parent = 0, QGraphicsScene *scene = 0); + DiagramItem(QMenu *contextMenu, + QGraphicsItem *parent, QGraphicsScene *scene);//constructor fuer Vererbung + DiagramItem(const DiagramItem& diagram);//copy constructor + + virtual DiagramItem* copy(); + + DiagramType diagramType() const + { return myDiagramType; } + QPolygonF polygon() const + { return myPolygon; } + QPixmap image() const; + int type() const + { return Type;} + +protected: + void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + +private: + DiagramType myDiagramType; + QPolygonF myPolygon; + QMenu *myContextMenu; +}; +//! [0] + +#endif diff --git a/plugins/qdiagram_plugin/diagrampathitem.cpp b/plugins/qdiagram_plugin/diagrampathitem.cpp new file mode 100644 index 000000000..404710619 --- /dev/null +++ b/plugins/qdiagram_plugin/diagrampathitem.cpp @@ -0,0 +1,401 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include +#include + +#include "diagrampathitem.h" +#include "diagramscene.h" + +#define NDEBUG + +//! [0] +DiagramPathItem::DiagramPathItem(DiagramType diagramType, QMenu *contextMenu, + QGraphicsItem *parent, QGraphicsScene *scene) + : QGraphicsPathItem(parent) +{ + myDiagramType = diagramType; + myContextMenu = contextMenu; + myPoints.clear(); + + len = 10.0; // Pfeillnge + breite = 4.0; // Divisor Pfeilbreite + + // standard initialize + mySelPoint=-1; + myHandlerWidth = 2.0; + myHoverPoint=-1; + + setBrush(QBrush(Qt::black)); + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, false); + setAcceptHoverEvents(true); +} + +DiagramPathItem::DiagramPathItem(QMenu *contextMenu, + QGraphicsItem *parent, QGraphicsScene *scene) + : QGraphicsPathItem(parent) +{ + myDiagramType = Path; + myContextMenu = contextMenu; + myPoints.clear(); + + len = 10.0; // Pfeillnge + breite = 4.0; // Divisor Pfeilbreite + + // standard initialize + mySelPoint=-1; + myHandlerWidth = 2.0; + myHoverPoint=-1; + + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); + setAcceptHoverEvents(true); +} +//! [0] +DiagramPathItem::DiagramPathItem(const DiagramPathItem& diagram) +{ + QGraphicsPathItem(diagram.parentItem(),diagram.scene()); + + // copy from general GraphcsItem + setBrush(diagram.brush()); + setPen(diagram.pen()); + setTransform(diagram.transform()); + + // copy DiagramPathItem + myDiagramType = diagram.myDiagramType; + myContextMenu = diagram.myContextMenu; + myPoints = diagram.myPoints; + + len = diagram.len; + + setPath(diagram.path()); + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); + setAcceptHoverEvents(true); + + // standard initialize + mySelPoint=-1; + myHandlerWidth = 2.0; + myHoverPoint=-1; +} + +void DiagramPathItem::createPath() +{ + QPainterPath myPath=getPath(); + if(myPath.elementCount()>0) setPath(myPath); +} + +QPainterPath DiagramPathItem::getPath() const +{ + QPainterPath myPath; + QPointF p1,p2; + if(myPoints.size()>1) + { + for (int i = 1; i < myPoints.size(); ++i) { + p1=myPoints.at(i-1); + p2=myPoints.at(i); + if( (i==1)&&((myDiagramType==Start) || (myDiagramType==StartEnd)) ) + { + QPainterPath arrow = createArrow(p2,p1); + myPath.addPath(arrow); + } + + myPath.moveTo(p2); + myPath.lineTo(p1); + myPath.closeSubpath(); + } + if((myDiagramType==End) or (myDiagramType==StartEnd)){ + QPainterPath arrow = createArrow(p1,p2); + myPath.addPath(arrow); + } + } + return myPath; +} + +QPainterPath DiagramPathItem::createArrow(QPointF p1, QPointF p2) const +{ +#define pi 3.141592654 + QPainterPath arrow; + qreal dx=p1.x()-p2.x(); + qreal dy=p1.y()-p2.y(); + qreal m=sqrt(dx*dx+dy*dy); + if(m>1){ + arrow.moveTo(p2); + arrow.lineTo(-len/breite*dy/m+len*dx/m+p2.x(),len/breite*dx/m+len*dy/m+p2.y()); + arrow.lineTo(len/breite*dy/m+len*dx/m+p2.x(),-len/breite*dx/m+len*dy/m+p2.y()); + arrow.closeSubpath(); + } + return arrow; +} + +//! [4] +QPixmap DiagramPathItem::image() const +{ + QPixmap pixmap(250, 250); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + painter.setPen(QPen(Qt::black, 8)); + painter.translate(125, 125); + QPolygonF myPolygon; + myPolygon << QPointF(-100,-100) << QPointF(0,-100) << QPointF(0,100) << QPointF(100,100) ;; + painter.drawPolyline(myPolygon); + return pixmap; +} +//! [4] +QPixmap DiagramPathItem::icon() +{ + QPixmap pixmap(50, 80); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + painter.setPen(QPen(Qt::black, 8)); + myPoints.clear(); + myPoints.append(QPointF(5,40)); + myPoints.append(QPointF(45,40)); + len=10.0; + breite=1.0; + painter.drawPath(getPath()); + return pixmap; +} + + +//! [5] +void DiagramPathItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + scene()->clearSelection(); + setSelected(true); + myContextMenu->exec(event->screenPos()); +} +//! [5] + +//! [6] +void DiagramPathItem::append(const QPointF point) +{ + if(myPoints.size()>1) + { + prepareGeometryChange(); + updateLast(point); + myPoints.append(mapFromScene(point)); + } + else + { + /*myPoints.append(point-pos()); + myPoints.append(point-pos());*/ + myPoints.append(mapFromScene(point)); + myPoints.append(mapFromScene(point)); + createPath(); + } +} + +void DiagramPathItem::remove() +{ + if(myPoints.size()>1) + { + prepareGeometryChange(); + myPoints.removeLast(); + updateLast(mapToScene(myPoints.last())); + } +} + +void DiagramPathItem::updateLast(const QPointF point) +{ + int i = myPoints.size()-1; + if (i>0){ + prepareGeometryChange(); + myPoints[i]=mapFromScene(point); + createPath(); + } +} + +QVariant DiagramPathItem::itemChange(GraphicsItemChange change, + const QVariant &value) +{ + if (change == QGraphicsItem::ItemPositionChange) { + //foreach (Arrow *arrow, arrows) { + // arrow->updatePosition(); + //} + } + + return value; +} +//! [6] +DiagramPathItem* DiagramPathItem::copy() +{ + DiagramPathItem* newDiagramPathItem=new DiagramPathItem(*this); + return newDiagramPathItem; +} + +void DiagramPathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, + QWidget *) +{ + painter->setPen(pen()); + painter->setBrush(brush()); + painter->drawPath(getPath()); + // selected + if(isSelected()){ + QBrush selBrush=QBrush(Qt::cyan); + QPen selPen=QPen(Qt::cyan); + painter->setBrush(selBrush); + painter->setPen(selPen); + QPointF point; + for(int i=0;isetBrush(QBrush(Qt::red)); + } + // Rect around valid point + painter->drawRect(QRectF(point-QPointF(2,2),point+QPointF(2,2))); + if(i==myHoverPoint){ + painter->setBrush(selBrush); + } + }// foreach + }// if +} + +QRectF DiagramPathItem::boundingRect() const +{ + qreal extra = (pen().width() + 20) / 2.0; + + qreal minx,maxx,miny,maxy; + bool first=true; + foreach(QPointF point,myPoints){ + if(first){ + minx=point.x(); + miny=point.y(); + maxx=point.x(); + maxy=point.y(); + first=false; + } + else{ + if(point.x()maxx) maxx=point.x(); + if(point.y()maxy) maxy=point.y(); + } + + } + + return QRectF(minx,miny,maxx-minx,maxy-miny) + .adjusted(-extra, -extra, extra, extra); +} + +void DiagramPathItem::mousePressEvent(QGraphicsSceneMouseEvent *e) { + if(isSelected()){ + if (e -> buttons() & Qt::LeftButton) { + QPointF mouse_point = onGrid(e -> pos()); + for(mySelPoint=0;mySelPointaccept(); + } + } + QGraphicsPathItem::mousePressEvent(e); +} + +void DiagramPathItem::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { + // left click + if ((e -> buttons() & Qt::LeftButton)&&(mySelPoint>-1)) { + QPointF mouse_point = onGrid(e -> pos()); + myPoints.replace(mySelPoint,onGrid(mouse_point)); + createPath(); + } +} + +QPainterPath DiagramPathItem::shape() const { + QPainterPath myPath = getPath(); + if(isSelected()){ + foreach (QPointF point, myPoints) + { + // Rect around valid point + myPath.addRect(QRectF(point-QPointF(myHandlerWidth,myHandlerWidth),point+QPointF(myHandlerWidth,myHandlerWidth))); + }// foreach + }// if + return myPath; +} + +bool DiagramPathItem::hasClickedOn(QPointF press_point, QPointF point) const { + return ( + press_point.x() >= point.x() - myHandlerWidth &&\ + press_point.x() < point.x() + myHandlerWidth &&\ + press_point.y() >= point.y() - myHandlerWidth &&\ + press_point.y() < point.y() + myHandlerWidth + ); +} + +QPointF DiagramPathItem::onGrid(QPointF pos) +{ + DiagramScene* myScene = dynamic_cast(scene()); + QPointF result = myScene->onGrid(pos); + return result; +} + +void DiagramPathItem::hoverEnterEvent(QGraphicsSceneHoverEvent *e) { +#ifdef DEBUG + std::cout << "entered" << std::endl; + std::cout << e->pos().x() << "/" << e->pos().y() << std::endl; +#endif + if (isSelected()) { + QPointF hover_point = onGrid(e -> pos()); + for(myHoverPoint=0;myHoverPoint-1){ + myHoverPoint=-1; + update(); + } + } + QGraphicsPathItem::hoverLeaveEvent(e); +} diff --git a/plugins/qdiagram_plugin/diagrampathitem.h b/plugins/qdiagram_plugin/diagrampathitem.h new file mode 100644 index 000000000..d4f057fac --- /dev/null +++ b/plugins/qdiagram_plugin/diagrampathitem.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef DIAGRAMPATHITEM_H +#define DIAGRAMPATHITEM_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QPixmap; +class QGraphicsItem; +class QGraphicsScene; +class QTextEdit; +class QGraphicsSceneMouseEvent; +class QMenu; +class QGraphicsSceneContextMenuEvent; +class QPainter; +class QStyleOptionGraphicsItem; +class QWidget; +class QPolygonF; +QT_END_NAMESPACE + +//! [0] +class DiagramPathItem : public QGraphicsPathItem +{ +public: + enum { Type = UserType + 6 }; + enum DiagramType { Path, Start, End, StartEnd }; + + DiagramPathItem(DiagramType diagramType, QMenu *contextMenu, + QGraphicsItem *parent = 0, QGraphicsScene *scene = 0); + DiagramPathItem(QMenu *contextMenu, + QGraphicsItem *parent, QGraphicsScene *scene);//constructor fuer Vererbung + DiagramPathItem(const DiagramPathItem& diagram);//copy constructor + + virtual DiagramPathItem* copy(); + + void append(const QPointF point); + void remove(); + void updateLast(const QPointF point); + + DiagramType diagramType() const + { return myDiagramType; } + + virtual void setDiagramType(DiagramType type) + { myDiagramType=type; } + + QPixmap image() const; + QPixmap icon(); + QPainterPath getPath() const; + QList getPoints() + { return myPoints; } + int type() const + { return Type;} + void setHandlerWidth(const qreal width) + { + myHandlerWidth = width; + } + +protected: + void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + void createPath(); + QPainterPath createArrow(QPointF p1, QPointF p2) const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); + QRectF boundingRect() const; + QPainterPath shape() const; + bool hasClickedOn(QPointF press_point, QPointF point) const; + void mousePressEvent(QGraphicsSceneMouseEvent *e); + void mouseMoveEvent(QGraphicsSceneMouseEvent *e); + void hoverEnterEvent(QGraphicsSceneHoverEvent *e); + void hoverLeaveEvent(QGraphicsSceneHoverEvent *e); + QPointF onGrid(QPointF pos); + +private: + DiagramType myDiagramType; + QMenu *myContextMenu; + QList myPoints; + qreal len,breite; + int mySelPoint,myHoverPoint; + qreal myHandlerWidth; + +}; +//! [0] + +#endif diff --git a/plugins/qdiagram_plugin/diagramscene.cpp b/plugins/qdiagram_plugin/diagramscene.cpp new file mode 100644 index 000000000..09aa738ed --- /dev/null +++ b/plugins/qdiagram_plugin/diagramscene.cpp @@ -0,0 +1,1246 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include +#include + +#include "diagramscene.h" + +#define NDEBUG + +//! [0] +DiagramScene::DiagramScene(QMenu *itemMenu, QObject *parent) + : QGraphicsScene(parent) +{ + myItemMenu = itemMenu; + myMode = MoveItem; + myItemType = DiagramItem::Step; + line = 0; + textItem = 0; + insertedItem = 0; + insertedDrawItem = 0; + insertedPathItem = 0; + copiedItems = 0; + myDx=0.0; + myDy=0.0; + maxZ=0; + myItemColor = Qt::white; + myTextColor = Qt::black; + myLineColor = Qt::black; + myArrow=DiagramPathItem::Path; + myGrid=10.0; + myGridVisible=false; + myGridScale=1; + // no Item in Moveitems + myMoveItems.clear(); + // initialisiere Cursor + myCursorWidth = 4.0; + myCursor.setRect(QRectF(-myCursorWidth/2,-myCursorWidth/2,myCursorWidth,myCursorWidth)); + myCursor.setPen(QPen(Qt::gray)); + myCursor.setZValue(10.0); + addItem(&myCursor); +} +//! [0] + +//! [1] +void DiagramScene::setLineColor(const QColor &color) +{ + myLineColor = color; + if(insertedPathItem!=0) insertedPathItem->setPen(myLineColor); + if(insertedItem!=0) insertedItem->setPen(myLineColor); + if(insertedDrawItem!=0) insertedDrawItem->setPen(myLineColor); + if (!selectedItems().empty()){ + foreach(QGraphicsItem* item,selectedItems()){ + switch(item->type()){ + case QGraphicsItem::UserType+3: + // Textitem does not possess Linecolor ! + break; + case QGraphicsItem::UserType+6: + qgraphicsitem_cast(item)->setPen(myLineColor); + qgraphicsitem_cast(item)->setBrush(myLineColor); + break; + default: + dynamic_cast(item)->setPen(myLineColor); + break; + } + } + } +} +//! [1] + +//! [2] +void DiagramScene::setTextColor(const QColor &color) +{ + myTextColor = color; + if (isItemChange(DiagramTextItem::Type)) { + DiagramTextItem *item = + qgraphicsitem_cast(selectedItems().first()); + item->setDefaultTextColor(myTextColor); + } +} +//! [2] + +//! [3] +void DiagramScene::setItemColor(const QColor &color) +{ + myItemColor = color; + if(insertedItem!=0) insertedItem->setBrush(myItemColor); + if(insertedDrawItem!=0) insertedDrawItem->setBrush(myItemColor); + if (!selectedItems().empty()){ + foreach(QGraphicsItem* item,selectedItems()){ + switch(item->type()){ + case QGraphicsItem::UserType+3: + // Textitem does not possess Linecolor ! + break; + case QGraphicsItem::UserType+6: + // Path does not need Backgroundcolor + break; + default: + dynamic_cast(item)->setBrush(myItemColor); + break; + } + } + } + // old code by Trolltech + /*if (isItemChange(DiagramItem::Type)) { + DiagramItem *item = + qgraphicsitem_cast(selectedItems().first()); + item->setBrush(myItemColor); + }*/ +} +//! [3] + +//! [4] +void DiagramScene::setFont(const QFont &font) +{ + myFont = font; + + if (isItemChange(DiagramTextItem::Type)) { + QGraphicsTextItem *item = + qgraphicsitem_cast(selectedItems().first()); + item->setFont(myFont); + // testing + /* + item->setTextWidth(200.0); + QTextCursor cursor = item->textCursor(); + cursor.select(QTextCursor::Document); + QTextBlockFormat bfmt = cursor.blockFormat(); + bfmt.setAlignment(Qt::AlignHCenter); + cursor.setBlockFormat(bfmt); + item->setTextCursor(cursor); + */ + } +} +//! [4] + +void DiagramScene::setMode(Mode mode,bool m_abort) +{ + if(m_abort) abort(true); + /* + if(myMode==InsertLine){ + if(insertedPathItem!=0){ + insertedPathItem->remove(); + insertedPathItem->setFlag(QGraphicsItem::ItemIsSelectable, true); + insertedPathItem=0; + } + } + */ + myMode = mode; + switch (mode) { + case MoveItem: + enableAllItems(true); + break; + case MoveItems: + enableAllItems(true); + break; + case CopyItem: + enableAllItems(true); + break; + case CopyingItem: + enableAllItems(false); + break; + case Zoom: + enableAllItems(false); + break; + default: + enableAllItems(false); + break; + } +} + +void DiagramScene::enableAllItems(bool enable) +{ + foreach(QGraphicsItem* item,items()){ + item->setEnabled(enable); + } +} + +/*enum DiagramScene::getMode() +{ + return mode; +}*/ + +void DiagramScene::setItemType(DiagramItem::DiagramType type) +{ + myItemType = type; +} +void DiagramScene::setItemType(DiagramDrawItem::DiagramType type) +{ + myDrawItemType = type; +} + + +//! [5] +void DiagramScene::editorLostFocus(DiagramTextItem *item) +{ + //Debug +#ifdef DEBUG + std::cout << "textItem:" << int(textItem) << std::endl; + if(textItem){ + std::cout << "Focus ?:" << textItem->hasFocus() << std::endl; + } +#endif + QTextCursor cursor = item->textCursor(); + cursor.clearSelection(); + item->setTextCursor(cursor); + +#ifdef DEBUG + std::cout << item->toPlainText().toStdString() << std::endl; +#endif + + if (item->toPlainText().isEmpty()) { + removeItem(item); + item->deleteLater(); + } + // avoid double lose focus, which erroneously activates shortcuts for second textitem + if((textItem==item)or(textItem==0)){ + textItem=0; + emit editorHasLostFocus(); + } + +} +void DiagramScene::editorReceivedFocus(DiagramTextItem *item) +{ + emit editorHasReceivedFocus(); +} +//! [5] + +//! [6] +void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ +#ifdef DEBUG + std::cout << "click" << myMode << std::endl; +#endif + if (mouseEvent->button() == Qt::RightButton){ + switch (myMode) { + case InsertItem: + if (insertedItem != 0){ + insertedItem->rotate(90); + } + break; + default: + ; + } + return; + } + + if (mouseEvent->button() == Qt::MidButton){ + switch (myMode) { + case InsertLine: + if (insertedPathItem != 0){ + insertedPathItem->updateLast(onGrid(mouseEvent->scenePos())); + insertedPathItem->setFlag(QGraphicsItem::ItemIsSelectable, true); + insertedPathItem->setEnabled(false); + insertedPathItem = 0; + } + break; + default: + ; + } + return; + } + + if (mouseEvent->button() != Qt::LeftButton) + return; + + //DiagramItem *item; + switch (myMode) { + case InsertItem: + if (insertedItem == 0){ + insertedItem = new DiagramItem(myItemType, myItemMenu); + insertedItem->setBrush(myItemColor); + insertedItem->setPen(myLineColor); + insertedItem->setZValue(maxZ); + maxZ+=0.1; + addItem(insertedItem); + } + insertedItem->setPos(onGrid(mouseEvent->scenePos())); + insertedItem->setEnabled(false); + emit itemInserted(insertedItem); + insertedItem = 0; + + break; +//! [6] //! [7] + case InsertDrawItem: + if (insertedDrawItem == 0){ + insertedDrawItem = new DiagramDrawItem(myDrawItemType, myItemMenu); + insertedDrawItem->setBrush(myItemColor); + insertedDrawItem->setPen(myLineColor); + insertedDrawItem->setZValue(maxZ); + maxZ+=0.1; + addItem(insertedDrawItem); + insertedDrawItem->setPos(onGrid(mouseEvent->scenePos())); + } + else + { + insertedDrawItem->setPos2(onGrid(mouseEvent->scenePos())); + insertedDrawItem->setEnabled(false); + insertedDrawItem = 0; + } + + break; + case MoveItems: + { + QPointF point=onGrid(mouseEvent->scenePos()); + if(!myMoveItems.isEmpty()){ + qreal dx=point.rx()-myDx; + qreal dy=point.ry()-myDy; + foreach(QGraphicsItem* item,myMoveItems){ + if(item->parentItem()!=0){ + if(!item->parentItem()->isSelected()) item->moveBy(-dx,-dy); + } + else { + item->moveBy(dx,dy); + } + } + myMoveItems.clear(); + myMode=MoveItem; + } + else + { + if(!selectedItems().isEmpty()){ + // lsche doppelte Verweise (Child&selected) + myMoveItems=selectedItems(); + foreach(QGraphicsItem* item,myMoveItems){ + if(item->parentItem()) + if(item->parentItem()->isSelected()) { + item->setSelected(false); + myMoveItems.removeOne(item); + } + } + // speichere Referenzpunkt + myDx=point.rx(); + myDy=point.ry(); + } + } + break; + } + case InsertLine: + if (insertedPathItem == 0){ + insertedPathItem = new DiagramPathItem(myArrow,myItemMenu); + insertedPathItem->setPen(myLineColor); + insertedPathItem->setBrush(myLineColor); + insertedPathItem->setZValue(maxZ); + maxZ+=0.1; + addItem(insertedPathItem); + insertedPathItem->setPos(onGrid(mouseEvent->scenePos())); + //insertedPathItem->setFlag(QGraphicsItem::ItemIsSelectable, true); + } + insertedPathItem->append(onGrid(mouseEvent->scenePos())); + break; +//! [7] //! [8] + case InsertText: + emit editorHasReceivedFocus(); + textItem = new DiagramTextItem(); + textItem->setFont(myFont); + textItem->setTextInteractionFlags(Qt::TextEditorInteraction); + textItem->setZValue(maxZ); + maxZ+=0.1; + connect(textItem, SIGNAL(lostFocus(DiagramTextItem *)), + this, SLOT(editorLostFocus(DiagramTextItem *))); + connect(textItem, SIGNAL(receivedFocus(DiagramTextItem *)), + this, SLOT(editorReceivedFocus(DiagramTextItem *))); + connect(textItem, SIGNAL(selectedChange(QGraphicsItem *)), + this, SIGNAL(itemSelected(QGraphicsItem *))); + addItem(textItem); + textItem->setDefaultTextColor(myTextColor); + textItem->setFocus(); + textItem->setCenterPoint(onGrid(mouseEvent->scenePos())); + textItem->activateEditor(); + emit textInserted(textItem); + mouseEvent->setAccepted(true); + break; +//! [8] //! [9] + case CopyItem: + if (!selectedItems().empty()){ + copiedItems=new QList; + copiedItems->clear(); + // lsche doppelte Verweise (Child&selected) + QList myList=selectedItems(); + foreach(QGraphicsItem* item,myList){ + if(item->parentItem()) + if(item->parentItem()->isSelected()) { + item->setSelected(false); + myList.removeOne(item); + } + } + // Vorbereitung copy + QGraphicsItem *insItem; + insItem=myList.first(); + QPointF point=onGrid(mouseEvent->scenePos()); + myDx=insItem->pos().rx()-point.rx(); + myDy=insItem->pos().ry()-point.ry(); + // copy + foreach(QGraphicsItem* item,myList){ + insItem=copy(item); + addItem(insItem); + insItem->setPos(item->pos()); + copiedItems->append(item); + item->setZValue(maxZ); + maxZ+=0.1; + //check for children + if(item->childItems().count()>0){ + foreach(QGraphicsItem* item_l1,item->childItems()){ + QGraphicsItem* addedItem=copy(item_l1); + addItem(addedItem); + addedItem->setParentItem(insItem); + addedItem->setPos(item_l1->pos()); + } + } + //move original to knew position + item->setSelected(true); +#ifdef DEBUG + std::cout<< item->pos().rx()<< ","<pos().ry() << std::endl; +#endif + } + myMode=CopyingItem; + } + break; + case CopyingItem: + if (copiedItems->count() > 0){ + insertedItem=static_cast(copiedItems->first()); + QPointF point=onGrid(mouseEvent->scenePos()); + qreal dx=insertedItem->pos().rx()-point.rx()-myDx; + qreal dy=insertedItem->pos().ry()-point.ry()-myDy; + foreach(QGraphicsItem* item,*copiedItems){ + if(item->parentItem()!=0){ + if(!item->parentItem()->isSelected()) item->moveBy(-dx,-dy); + } + else { + item->moveBy(-dx,-dy); + } + } + clearSelection(); + insertedItem=0; + myDx=0.0; + myDy=0.0; + myMode=MoveItem; + } + break; + default: + ; + } +if(!mouseEvent->isAccepted()) QGraphicsScene::mousePressEvent(mouseEvent); +} +//! [9] + +//! [10] +void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + // move cursor + myCursor.setPos(onGrid(mouseEvent->scenePos())); + + // preview der Zeichnung + switch (myMode){ + case InsertLine: + if (insertedPathItem != 0) { + insertedPathItem->updateLast(onGrid(mouseEvent->scenePos())); + } + break; + case MoveItem: + QGraphicsScene::mouseMoveEvent(mouseEvent); + checkOnGrid(); + break; + case MoveItems: + { + QPointF point=onGrid(mouseEvent->scenePos()); + qreal dx=point.rx()-myDx; + qreal dy=point.ry()-myDy; + foreach(QGraphicsItem* item,myMoveItems){ + if(item->parentItem()!=0){ + if(!item->parentItem()->isSelected()) item->moveBy(dx,dy); + } + else { + item->moveBy(dx,dy); + } + } + myDx=point.rx(); + myDy=point.ry(); + break; + } + case InsertItem: + if (insertedItem == 0){ + insertedItem = new DiagramItem(myItemType, myItemMenu); + insertedItem->setBrush(myItemColor); + insertedItem->setPen(myLineColor); + insertedItem->setSelected(true); + insertedItem->setZValue(maxZ); + maxZ+=0.1; + addItem(insertedItem); + } + insertedItem->setPos(onGrid(mouseEvent->scenePos())); + break; + case InsertDrawItem: + if (insertedDrawItem != 0){ + insertedDrawItem->setPos2(onGrid(mouseEvent->scenePos())); + } + break; + case CopyingItem: + if (copiedItems->count() > 0){ + //copiedItems->setPos(onGrid(mouseEvent->scenePos())); + insertedItem=static_cast(copiedItems->first()); + QPointF point=onGrid(mouseEvent->scenePos()); + qreal dx=insertedItem->pos().rx()-point.rx()-myDx; + qreal dy=insertedItem->pos().ry()-point.ry()-myDy; + foreach(QGraphicsItem* item,*copiedItems){ + if(item->parentItem()!=0){ + if(!item->parentItem()->isSelected()) item->moveBy(-dx,-dy); + } + else { + item->moveBy(-dx,-dy); + } + } + } + break; + + default: + ; + } +} +//! [10] + +//! [11] +void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + if (myMode == Zoom) { + emit zoomRect(mouseEvent->scenePos(),mouseEvent->lastScenePos()); + return; + } +//! [12] //! [13] + line = 0; + QGraphicsScene::mouseReleaseEvent(mouseEvent); +} +//! [13] +void DiagramScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ +#ifdef DEBUG + std::cout << "d click" << myMode << std::endl; +#endif + switch (myMode){ + case InsertLine: + //insertedPathItem->updateLast(onGrid(mouseEvent->scenePos())); + insertedPathItem->remove(); + insertedPathItem->setFlag(QGraphicsItem::ItemIsSelectable, true); + insertedPathItem->setEnabled(false); + insertedPathItem=0; + break; + default: + if(!selectedItems().isEmpty()){ + QGraphicsItem *item = selectedItems().first();//itemAt(mouseEvent->scenePos()); + if(item){ + QList children = item->childItems(); + if (children.count()>0){ + if (QGraphicsTextItem *child = (QGraphicsTextItem*) item->childItems().first()) { +#ifdef DEBUG + std::cout << "edit:" << child->toPlainText().toStdString() << std::endl; +#endif + if (child->textInteractionFlags() == Qt::NoTextInteraction) + child->setTextInteractionFlags(Qt::TextEditorInteraction); + emit editorHasReceivedFocus(); + child->setFocus(); + } + } + else { + if(item->type()!=DiagramTextItem::Type){ + // added + // text wird per Doppelclick eingefuegt + textItem = new DiagramTextItem(); + textItem->setFont(myFont); + textItem->setTextInteractionFlags(Qt::TextEditorInteraction); + textItem->setZValue(1000.0); + connect(textItem, SIGNAL(lostFocus(DiagramTextItem *)), + this, SLOT(editorLostFocus(DiagramTextItem *))); + connect(textItem, SIGNAL(receivedFocus(DiagramTextItem *)), + this, SLOT(editorReceivedFocus(DiagramTextItem *))); + connect(textItem, SIGNAL(selectedChange(QGraphicsItem *)), + this, SIGNAL(itemSelected(QGraphicsItem *))); + addItem(textItem); + textItem->setParentItem(item); + textItem->setDefaultTextColor(myTextColor); + QPointF mPos=QPointF(0,0); + // mPos adaptieren je nach DiaType ... + switch (item->type()) { + case DiagramDrawItem::Type: + mPos+=dynamic_cast(item)->getDimension()/2; + break; + default: + break; + } + //textItem->setPos(mPos); + textItem->setCenterPoint(mPos); + emit editorHasReceivedFocus(); + emit textInserted(textItem); + textItem->setFocus(Qt::OtherFocusReason); + } + else + QGraphicsScene::mouseDoubleClickEvent(mouseEvent); + } + } + } + } +} + +void DiagramScene::wheelEvent(QGraphicsSceneWheelEvent *mouseEvent) +{ + if(mouseEvent->modifiers()==Qt::ControlModifier){ + int i = mouseEvent->delta(); + qreal factor; + if(i>=0){ + factor = i/100.0; + } + else { + factor = -100.0/i; // negative Richtung ... + } + emit zoom(factor); + mouseEvent->setAccepted(true); + return; + } + QGraphicsScene::wheelEvent(mouseEvent); +} + + +//! [14] +void setArrow(const int i) +{ +} + +bool DiagramScene::isItemChange(int type) +{ + foreach (QGraphicsItem *item, selectedItems()) { + if (item->type() == type) + return true; + } + return false; +} +//! [14] +void DiagramScene::checkOnGrid() +{ + foreach (QGraphicsItem *item, selectedItems()) { + + if(item->type()==DiagramTextItem::Type){ + // not item position but center position needs to be on grid + QPointF centerPoint=dynamic_cast(item)->centerPoint(); + std::cout << "rec:" << centerPoint.x() << "/" << centerPoint.y() << std::endl; + qreal x = qRound(centerPoint.x()/10)*10.0; + qreal y = qRound(centerPoint.y()/10)*10.0; + dynamic_cast(item)->setCenterPoint(QPointF(x,y)); + } + else + { + qreal x = qRound(item->x()/10)*10.0; + qreal y = qRound(item->y()/10)*10.0; + item->setPos(x,y); + } + } +} + +QPointF DiagramScene::onGrid(QPointF pos) +{ + qreal x = qRound(pos.x()/myGrid)*myGrid; + qreal y = qRound(pos.y()/myGrid)*myGrid; + QPointF result = QPointF(x,y); + return result; +} + +void DiagramScene::abort(bool keepSelection) +{ + switch(myMode){ + case CopyingItem: + //removeItem(copiedItems); + //destroyItemGroup(copiedItems); + //removeItem(insertedItem); + break; + case InsertItem: + removeItem(insertedItem); + break; + case InsertDrawItem: + removeItem(insertedDrawItem); + break; + case InsertLine: + removeItem(insertedPathItem); + break; + default: + ; + } + + insertedItem=0; + insertedDrawItem=0; + copiedItems=0; + myMode=MoveItem; + if(!keepSelection) clearSelection(); +} + +QGraphicsItem* DiagramScene::copy(QGraphicsItem* item) +{ +#ifdef DEBUG + std::cout<<"copy: " << item->type()<type()){ + case QGraphicsItem::UserType+3: + return qgraphicsitem_cast(qgraphicsitem_cast(item)->copy()); + break; + case QGraphicsItem::UserType+6: + return qgraphicsitem_cast(qgraphicsitem_cast(item)->copy()); + break; + default: + { + DiagramItem* newItem=dynamic_cast(item)->copy(); + return dynamic_cast(newItem); + } + break; + } +} + +void DiagramScene::setArrow(const int i) +{ + myArrow=DiagramPathItem::DiagramType(i); + if(insertedPathItem!=0){ + insertedPathItem->setDiagramType(myArrow); + } + if (!selectedItems().empty()){ + foreach(QGraphicsItem* item,selectedItems()){ + switch(item->type()){ + case QGraphicsItem::UserType+3: + // Textitem does not possess Linecolor ! + break; + case QGraphicsItem::UserType+6: + qgraphicsitem_cast(item)->setDiagramType(myArrow); + break; + default: + // nothing to do + break; + } + } + } + + +} + +bool DiagramScene::event(QEvent *mEvent) +{ + if (mEvent->type()==QEvent::Enter) { + myCursor.setVisible(true); + return true; + } + if (mEvent->type()==QEvent::Leave) { + myCursor.setVisible(false); + return true; + } + return QGraphicsScene::event(mEvent); +} + +bool DiagramScene::save(QFile *file) +{ +#ifdef DEBUG + std::cout << "save..." << std::endl; +#endif + QXmlStreamWriter xmlWriter(file); + xmlWriter.setAutoFormatting(true); + xmlWriter.writeStartDocument(); + xmlWriter.writeComment("File for QDiagram"); + xmlWriter.writeStartElement("doc"); + foreach(QGraphicsItem* item, items()){ + if(item->type()>QGraphicsItem::UserType){ + xmlWriter.writeStartElement("Item"); + xmlWriter.writeAttribute("Type",QString::number(item->type())); + xmlWriter.writeEmptyElement("Pos"); + xmlWriter.writeAttribute("x",QString::number(item->pos().x())); + xmlWriter.writeAttribute("y",QString::number(item->pos().y())); + xmlWriter.writeAttribute("z",QString::number(item->zValue())); + switch (item->type()) { + case QGraphicsItem::UserType+16: + { + DiagramDrawItem *mItem = dynamic_cast(item); + //xmlWriter.writeComment("DiagramDrawItem"); + xmlWriter.writeEmptyElement("DiagramType"); + xmlWriter.writeAttribute("type",QString::number(mItem->diagramType())); + xmlWriter.writeEmptyElement("Dimensions"); + xmlWriter.writeAttribute("width",QString::number(mItem->getDimension().x())); + xmlWriter.writeAttribute("height",QString::number(mItem->getDimension().y())); + xmlWriter.writeEmptyElement("Pen"); + xmlWriter.writeAttribute("color",mItem->pen().color().name()); + xmlWriter.writeAttribute("alpha",QString::number(mItem->pen().color().alpha())); + xmlWriter.writeEmptyElement("Brush"); + xmlWriter.writeAttribute("color",mItem->brush().color().name()); + xmlWriter.writeAttribute("alpha",QString::number(mItem->brush().color().alpha())); + } + break; + case QGraphicsItem::UserType+15: + { + DiagramItem *mItem = dynamic_cast(item); + //xmlWriter.writeComment("DiagramItem"); + xmlWriter.writeEmptyElement("DiagramType"); + xmlWriter.writeAttribute("type",QString::number(mItem->diagramType())); + xmlWriter.writeEmptyElement("Pen"); + xmlWriter.writeAttribute("color",mItem->pen().color().name()); + xmlWriter.writeAttribute("alpha",QString::number(mItem->pen().color().alpha())); + xmlWriter.writeEmptyElement("Brush"); + xmlWriter.writeAttribute("color",mItem->brush().color().name()); + xmlWriter.writeAttribute("alpha",QString::number(mItem->brush().color().alpha())); + } + break; + case QGraphicsItem::UserType+3: + { + DiagramTextItem *mItem = dynamic_cast(item); + //xmlWriter.writeComment("DiagramTextItem"); + xmlWriter.writeEmptyElement("DiagramType"); + xmlWriter.writeAttribute("type","0"); + xmlWriter.writeStartElement("Text"); + xmlWriter.writeCharacters(mItem->toHtml()); + xmlWriter.writeEndElement(); + } + break; + case QGraphicsItem::UserType+6: + { + DiagramPathItem *mItem = dynamic_cast(item); + //xmlWriter.writeComment("DiagramPathItem"); + xmlWriter.writeEmptyElement("DiagramType"); + xmlWriter.writeAttribute("type",QString::number(mItem->diagramType())); + xmlWriter.writeEmptyElement("Pen"); + xmlWriter.writeAttribute("color",mItem->pen().color().name()); + xmlWriter.writeAttribute("alpha",QString::number(mItem->pen().color().alpha())); + xmlWriter.writeEmptyElement("Brush"); + xmlWriter.writeAttribute("color",mItem->brush().color().name()); + xmlWriter.writeAttribute("alpha",QString::number(mItem->brush().color().alpha())); + foreach(QPointF point, mItem->getPoints()){ + xmlWriter.writeEmptyElement("Point"); + xmlWriter.writeAttribute("x",QString::number(point.x())); + xmlWriter.writeAttribute("y",QString::number(point.y())); + } + } + break; + default: + break; + } + xmlWriter.writeEmptyElement("Transform"); + xmlWriter.writeAttribute("m11",QString::number(item->transform().m11())); + xmlWriter.writeAttribute("m12",QString::number(item->transform().m12())); + xmlWriter.writeAttribute("m21",QString::number(item->transform().m21())); + xmlWriter.writeAttribute("m22",QString::number(item->transform().m22())); + xmlWriter.writeAttribute("dx",QString::number(item->transform().dx())); + xmlWriter.writeAttribute("dy",QString::number(item->transform().dy())); + xmlWriter.writeEndElement(); + } + + } + xmlWriter.writeEndElement(); + xmlWriter.writeEndDocument(); + return true; +} +bool DiagramScene::load(QFile *file) +{ +#ifdef DEBUG + std::cout << "Load..." << std::endl; +#endif + QXmlStreamReader xmlReader(file); + int DiaType = 0; + QPointF mPos; + qreal z; + int type; + insertedItem=0; + insertedPathItem=0; + insertedDrawItem=0; + textItem=0; + while(!xmlReader.atEnd()){ + xmlReader.readNext(); +#ifdef DEBUG + std::cout << "name: " << DiaType << ":" << qPrintable(xmlReader.name().toString()) << std::endl; +#endif + if(xmlReader.isStartDocument()) continue; + if(xmlReader.isStartElement()){ + if(xmlReader.name()=="doc") continue; + if(!DiaType and (xmlReader.name()=="Item")){ + bool ok; + DiaType = xmlReader.attributes().value("Type").toString().toInt(&ok); + if(!ok) + { + xmlReader.raiseError(tr("Item: type number conversion failed")); + } + continue; + } + if(DiaType and (xmlReader.name()=="Pos")){ + bool ok,okay; + okay=true; + mPos.setX(xmlReader.attributes().value("x").toString().toDouble(&ok)); + okay&=ok; + mPos.setY(xmlReader.attributes().value("y").toString().toDouble(&ok)); + okay&=ok; + z=xmlReader.attributes().value("z").toString().toDouble(&ok); + okay&=ok; + if(!okay) + { + xmlReader.raiseError(tr("Pos: number conversion failed")); + } + continue; + } + if(DiaType and (xmlReader.name()=="DiagramType")){ + bool ok; + type = xmlReader.attributes().value("type").toString().toInt(&ok); + if(!ok) + { + xmlReader.raiseError(tr("DiagramType: type number conversion failed")); + continue; + } + switch (DiaType) { + case QGraphicsItem::UserType+15: + insertedItem = new DiagramItem(DiagramItem::DiagramType(type),myItemMenu); + addItem(insertedItem); +#ifdef DEBUG + std::cout << "DiagramItem" << std::endl; +#endif + insertedItem->setPos(mPos); + insertedItem->setZValue(z); + break; + case QGraphicsItem::UserType+16: + insertedDrawItem = new DiagramDrawItem(DiagramDrawItem::DiagramType(type),myItemMenu); + addItem(insertedDrawItem); +#ifdef DEBUG + std::cout << "DiagramDrawItem" << std::endl; +#endif + insertedDrawItem->setPos(mPos); + insertedDrawItem->setZValue(z); + break; + case QGraphicsItem::UserType+6: + insertedPathItem = new DiagramPathItem(DiagramPathItem::DiagramType(type),myItemMenu); + addItem(insertedPathItem); +#ifdef DEBUG + std::cout << "DiagramPathItem" << std::endl; +#endif + insertedPathItem->setPos(mPos); + insertedPathItem->setZValue(z); + insertedPathItem->setFlag(QGraphicsItem::ItemIsMovable, true); + insertedPathItem->setFlag(QGraphicsItem::ItemIsSelectable, true); + break; + case QGraphicsItem::UserType+3: + textItem = new DiagramTextItem(); + textItem->setTextInteractionFlags(Qt::TextEditorInteraction); + textItem->setZValue(z); + connect(textItem, SIGNAL(lostFocus(DiagramTextItem *)), + this, SLOT(editorLostFocus(DiagramTextItem *))); + connect(textItem, SIGNAL(receivedFocus(DiagramTextItem *)), + this, SLOT(editorReceivedFocus(DiagramTextItem *))); + connect(textItem, SIGNAL(selectedChange(QGraphicsItem *)), + this, SIGNAL(itemSelected(QGraphicsItem *))); + addItem(textItem); + textItem->setPos(mPos); + break; + default: + break; + } + continue; + } + //DiamgramType nicht gesetzt ? -> Fehler + if(DiaType and !(insertedItem or insertedDrawItem or textItem or insertedPathItem)){ + xmlReader.raiseError(tr("DiagramType definition missing")); + continue; + } + // weitere Properties setzen (Farbe,Punkte,etc.) + if(DiaType and (xmlReader.name()=="Pen")){ + QColor color; + color.setNamedColor(xmlReader.attributes().value("color").toString()); + if(!color.isValid()){ + xmlReader.raiseError(tr("DiagramType: type number conversion failed")); + continue; + } + bool ok; + color.setAlpha(xmlReader.attributes().value("alpha").toString().toUInt(&ok)); + if(!ok) + { + xmlReader.raiseError(tr("DiagramType: type number conversion failed")); + continue; + } + switch (DiaType) { + case QGraphicsItem::UserType+15: + insertedItem->setPen(color); + break; + case QGraphicsItem::UserType+16: + insertedDrawItem->setPen(color); + break; + case QGraphicsItem::UserType+6: + insertedPathItem->setPen(color); + break; + default: + break; + } + continue; + } + if(DiaType and (xmlReader.name()=="Brush")){ + QColor color; + bool ok; + QString colorName = xmlReader.attributes().value("color").toString(); + color.setNamedColor(colorName); + if(!color.isValid()){ + xmlReader.raiseError(tr("DiagramType: type number conversion failed")); + continue; + } + color.setAlpha(xmlReader.attributes().value("alpha").toString().toUInt(&ok)); + if(!ok) + { + xmlReader.raiseError(tr("DiagramType: type number conversion failed")); + continue; + } + switch (DiaType) { + case QGraphicsItem::UserType+15: + insertedItem->setBrush(color); + break; + case QGraphicsItem::UserType+16: + insertedDrawItem->setBrush(color); + break; + case QGraphicsItem::UserType+6: + insertedPathItem->setBrush(color); + break; + default: + break; + } + continue; + } + if(DiaType and (xmlReader.name()=="Dimensions")){ + QPointF mPos2; + bool okay,ok; + okay=true; + mPos2.setX(xmlReader.attributes().value("width").toString().toDouble(&ok)); + okay&=ok; + mPos2.setY(xmlReader.attributes().value("height").toString().toDouble(&ok)); + okay&=ok; + if(!ok) + { + xmlReader.raiseError(tr("Dimensions: number conversion failed")); + continue; + } + switch (DiaType) { + case QGraphicsItem::UserType+16: + insertedDrawItem->setDimension(mPos2); + break; + default: + break; + } + continue; + } + if(DiaType and (xmlReader.name()=="Point")){ + QPointF mPos2; + bool okay,ok; + okay=true; + mPos2.setX(xmlReader.attributes().value("x").toString().toDouble(&ok)); + okay&=ok; + mPos2.setY(xmlReader.attributes().value("y").toString().toDouble(&ok)); + okay&=ok; + if(!ok) + { + xmlReader.raiseError(tr("Point: number conversion failed")); + continue; + } + switch (DiaType) { + case QGraphicsItem::UserType+6: + insertedPathItem->append(mPos2+insertedPathItem->pos()); + break; + default: + break; + } + continue; + } + if(DiaType and (xmlReader.name()=="Text")){ + QString mText; + mText = xmlReader.readElementText(); + switch (DiaType) { + case QGraphicsItem::UserType+3: + textItem->setHtml(mText); + break; + default: + break; + } + continue; + } + if(DiaType and (xmlReader.name()=="Transform")){ + bool ok,okay; + okay=true; + qreal m11=xmlReader.attributes().value("m11").toString().toDouble(&ok); + okay&=ok; + qreal m12=xmlReader.attributes().value("m12").toString().toDouble(&ok); + okay&=ok; + qreal m21=xmlReader.attributes().value("m21").toString().toDouble(&ok); + okay&=ok; + qreal m22=xmlReader.attributes().value("m22").toString().toDouble(&ok); + okay&=ok; + qreal dx=xmlReader.attributes().value("dx").toString().toDouble(&ok); + okay&=ok; + qreal dy=xmlReader.attributes().value("dx").toString().toDouble(&ok); + okay&=ok; + if(!ok) + { + xmlReader.raiseError(tr("Transform: number conversion failed")); + continue; + } + QTransform trans=QTransform(m11,m12,m21,m22,dx,dy); + switch (DiaType) { + case QGraphicsItem::UserType+15: + insertedItem->setTransform(trans); + break; + case QGraphicsItem::UserType+16: + insertedDrawItem->setTransform(trans); + break; + case QGraphicsItem::UserType+6: + insertedPathItem->setTransform(trans); + break; + case QGraphicsItem::UserType+3: + textItem->setTransform(trans); + break; + default: + break; + } + continue; + } + else { + xmlReader.raiseError(tr("unexpected start element")); + continue; + } + + } + if(xmlReader.isEndElement()){ + if(DiaType and (xmlReader.name()=="Item")){ + DiaType = 0; + insertedItem = 0; + insertedDrawItem = 0; + insertedPathItem = 0; + textItem = 0; + } + } + + } + if(xmlReader.hasError()){ + std::cerr << "Error in XML Read-in: " + << qPrintable(xmlReader.errorString()) + << std::endl + << "Line: " + << xmlReader.lineNumber() + << std::endl; + } + // Aufrumen + insertedItem = 0; + insertedDrawItem = 0; + insertedPathItem = 0; + textItem = 0; + myMode = MoveItem; + return true; +} + +void DiagramScene::clear() +{ + foreach(QGraphicsItem *item,items()){ + if(item!=&myCursor) + { + removeItem(item); + delete item; + } + } +} + +void DiagramScene::setCursorVisible(bool vis) +{ + if(vis){ + if(myCursor.scene()==0){ + addItem(&myCursor); + } + } + else + { + if(myCursor.scene()) removeItem(&myCursor); + } +} + +void DiagramScene::drawBackground(QPainter *p, const QRectF &r) { + p -> save(); + + // desactive tout antialiasing, sauf pour le texte + p -> setRenderHint(QPainter::Antialiasing, false); + p -> setRenderHint(QPainter::TextAntialiasing, true); + p -> setRenderHint(QPainter::SmoothPixmapTransform, false); + + // dessine un fond blanc + p -> setPen(Qt::NoPen); + p -> setBrush(Qt::white); + p -> drawRect(r); + + if (myGridVisible) { + // to ease transition from qelec + int xGrid=myGridScale * (int) myGrid; + int yGrid=myGridScale * (int) myGrid; + // dessine les points de la grille + p -> setPen(Qt::black); + p -> setBrush(Qt::NoBrush); + qreal limite_x = r.x() + r.width(); + qreal limite_y = r.y() + r.height(); + + int g_x = (int)ceil(r.x()); + while (g_x % xGrid) ++ g_x; + int g_y = (int)ceil(r.y()); + while (g_y % yGrid) ++ g_y; + + for (int gx = g_x ; gx < limite_x ; gx += xGrid) { + for (int gy = g_y ; gy < limite_y ; gy += yGrid) { + p -> drawPoint(gx, gy); + } + } + } + + p -> restore(); +} diff --git a/plugins/qdiagram_plugin/diagramscene.h b/plugins/qdiagram_plugin/diagramscene.h new file mode 100644 index 000000000..85660dcfb --- /dev/null +++ b/plugins/qdiagram_plugin/diagramscene.h @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef DIAGRAMSCENE_H +#define DIAGRAMSCENE_H + +#include +#include "diagramitem.h" +#include "diagramdrawitem.h" +#include "diagramtextitem.h" +#include "diagrampathitem.h" + +QT_BEGIN_NAMESPACE +class QGraphicsSceneMouseEvent; +class QMenu; +class QPointF; +class QGraphicsLineItem; +class QFont; +class QGraphicsTextItem; +class QColor; +class QFile; +QT_END_NAMESPACE + +//! [0] +class DiagramScene : public QGraphicsScene +{ + Q_OBJECT + +public: + enum Mode { InsertItem, InsertLine, InsertText, MoveItem, CopyItem, CopyingItem, InsertDrawItem, Zoom , MoveItems}; + + DiagramScene(QMenu *itemMenu, QObject *parent = 0); + QFont font() const + { return myFont; } + QColor textColor() const + { return myTextColor; } + QColor itemColor() const + { return myItemColor; } + QColor lineColor() const + { return myLineColor; } + void setLineColor(const QColor &color); + void setTextColor(const QColor &color); + void setItemColor(const QColor &color); + void setFont(const QFont &font); + void setArrow(const int i); + void setGrid(const qreal grid) + { + myGrid=grid; + } + void setGridVisible(const bool vis) + { + myGridVisible=vis; + } + bool isGridVisible() + { + return myGridVisible; + } + void setGridScale(const int k) + { + myGridScale=k; + } + bool save(QFile *file); + bool load(QFile *file); + QPointF onGrid(QPointF pos); + void setCursorVisible(bool t); + +public slots: + void setMode(Mode mode,bool m_abort=true); + void abort(bool keepSelection=false); + void setItemType(DiagramItem::DiagramType type); + void setItemType(DiagramDrawItem::DiagramType type); + void editorLostFocus(DiagramTextItem *item); + void editorReceivedFocus(DiagramTextItem *item); + void checkOnGrid(); + void clear(); + +signals: + void itemInserted(DiagramItem *item); + void textInserted(QGraphicsTextItem *item); + void itemSelected(QGraphicsItem *item); + void editorHasLostFocus(); + void editorHasReceivedFocus(); + void zoomRect(QPointF p1,QPointF p2); + void zoom(const qreal factor); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent); + void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent); + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent); + void wheelEvent(QGraphicsSceneWheelEvent *mouseEvent); + bool event(QEvent *mEvent); + QGraphicsItem* copy(QGraphicsItem* item); + void drawBackground(QPainter *p, const QRectF &r); + void enableAllItems(bool enable=true); + + +private: + bool isItemChange(int type); + + DiagramItem::DiagramType myItemType; + DiagramDrawItem::DiagramType myDrawItemType; + QMenu *myItemMenu; + Mode myMode; + bool leftButtonDown; + QPointF startPoint; + QGraphicsLineItem *line; + QFont myFont; + DiagramTextItem *textItem; + QColor myTextColor; + QColor myItemColor; + QColor myLineColor; + DiagramItem *insertedItem; + DiagramDrawItem *insertedDrawItem; + DiagramPathItem *insertedPathItem; + QList *copiedItems; + qreal myDx,myDy; + DiagramPathItem::DiagramType myArrow; + qreal myGrid; + QGraphicsRectItem myCursor; + qreal myCursorWidth; + bool myGridVisible; + int myGridScale; + QList myMoveItems; + qreal maxZ; +}; +//! [0] + +#endif diff --git a/plugins/qdiagram_plugin/diagramtextitem.cpp b/plugins/qdiagram_plugin/diagramtextitem.cpp new file mode 100644 index 000000000..6254bdbfe --- /dev/null +++ b/plugins/qdiagram_plugin/diagramtextitem.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include + +#include "diagramtextitem.h" +#include "diagramscene.h" +#include + +//! [0] +DiagramTextItem::DiagramTextItem(QGraphicsItem *parent, QGraphicsScene *scene) + : QGraphicsTextItem(parent, scene) +{ + setFlag(QGraphicsItem::ItemIsMovable); + setFlag(QGraphicsItem::ItemIsSelectable); + QObject::connect(this->document(), SIGNAL(contentsChanged()), + this, SLOT(textChanged())); +} +//! [0] +DiagramTextItem::DiagramTextItem(const DiagramTextItem& textItem) +{ + //QGraphicsTextItem(); + setFont(textItem.font()); + setDefaultTextColor(textItem.defaultTextColor()); + setHtml(textItem.toHtml()); + setTransform(textItem.transform()); + setFlag(QGraphicsItem::ItemIsMovable); + setFlag(QGraphicsItem::ItemIsSelectable); + m_adapt=false; +} + + +//! [1] +QVariant DiagramTextItem::itemChange(GraphicsItemChange change, + const QVariant &value) +{ + if (change == QGraphicsItem::ItemSelectedHasChanged) + emit selectedChange(this); + if (change == QGraphicsItem::ItemPositionHasChanged) + { + if(!m_adapt) { + qreal width=boundingRect().width(); + qreal height=boundingRect().height(); + mCenterPoint=mapToParent(mapFromParent(scenePos())+QPointF(width/2,height/2)); + m_adapt=true; + prepareGeometryChange(); + return mapToParent(mapFromParent(mCenterPoint)+QPointF(-width/2,-height/2)); + } + m_adapt=false; + return value.toPointF(); + } + return value; +} +//! [1] + +//! [2] +void DiagramTextItem::focusOutEvent(QFocusEvent *event) +{ + setTextInteractionFlags(Qt::NoTextInteraction); + emit lostFocus(this); + QGraphicsTextItem::focusOutEvent(event); +} +void DiagramTextItem::focusInEvent(QFocusEvent *event) +{ + //emit receivedFocus(this); + QGraphicsTextItem::focusInEvent(event); +} +//! [2] + +//! [5] +void DiagramTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) +{ + if (textInteractionFlags() == Qt::NoTextInteraction) + setTextInteractionFlags(Qt::TextEditorInteraction); + emit receivedFocus(this); + QGraphicsTextItem::mouseDoubleClickEvent(event); +} +//! [5] +DiagramTextItem* DiagramTextItem::copy() +{ + DiagramTextItem* newTextItem=new DiagramTextItem(*this); + return newTextItem; +} + +void DiagramTextItem::textChanged() +{ + qreal width=boundingRect().width(); + qreal height=boundingRect().height(); + m_adapt=true; + prepareGeometryChange(); + setPos(mapToParent(mapFromParent(mCenterPoint)+QPointF(-width/2,-height/2))); +} + +void DiagramTextItem::setCenterPoint(const QPointF point) +{ + mCenterPoint=point; + textChanged(); +} + +void DiagramTextItem::activateEditor() +{ + if (textInteractionFlags() == Qt::NoTextInteraction) + setTextInteractionFlags(Qt::TextEditorInteraction); + QGraphicsSceneMouseEvent *event=new QGraphicsSceneMouseEvent(); + event->setPos(QPointF(0,0)); + QGraphicsTextItem::mousePressEvent(event); + delete event; +} diff --git a/plugins/qdiagram_plugin/diagramtextitem.h b/plugins/qdiagram_plugin/diagramtextitem.h new file mode 100644 index 000000000..126c150ad --- /dev/null +++ b/plugins/qdiagram_plugin/diagramtextitem.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef DIAGRAMTEXTITEM_H +#define DIAGRAMTEXTITEM_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QFocusEvent; +class QGraphicsItem; +class QGraphicsScene; +class QGraphicsSceneMouseEvent; +QT_END_NAMESPACE + +//! [0] +class DiagramTextItem : public QGraphicsTextItem +{ + Q_OBJECT + +public: + enum { Type = UserType + 3 }; + + DiagramTextItem(QGraphicsItem *parent = 0, QGraphicsScene *scene = 0); + DiagramTextItem(const DiagramTextItem& textItem); + + DiagramTextItem* copy(); + QPointF centerPoint(){ + return mCenterPoint; + } + void setCenterPoint(const QPointF point); + void activateEditor(); + + int type() const + { return Type; } + +signals: + void lostFocus(DiagramTextItem *item); + void receivedFocus(DiagramTextItem *item); + void selectedChange(QGraphicsItem *item); + +protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + void focusOutEvent(QFocusEvent *event); + void focusInEvent(QFocusEvent *event); + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); + +protected slots: + void textChanged(); + +private: + //qreal width,height; + QPointF mCenterPoint; + bool m_adapt; +}; +//! [0] + +#endif diff --git a/plugins/qdiagram_plugin/images/Thumbs.db b/plugins/qdiagram_plugin/images/Thumbs.db new file mode 100644 index 000000000..339f8b94f Binary files /dev/null and b/plugins/qdiagram_plugin/images/Thumbs.db differ diff --git a/plugins/qdiagram_plugin/images/background1.png b/plugins/qdiagram_plugin/images/background1.png new file mode 100644 index 000000000..0f93c6bf4 Binary files /dev/null and b/plugins/qdiagram_plugin/images/background1.png differ diff --git a/plugins/qdiagram_plugin/images/background2.png b/plugins/qdiagram_plugin/images/background2.png new file mode 100644 index 000000000..1e293db67 Binary files /dev/null and b/plugins/qdiagram_plugin/images/background2.png differ diff --git a/plugins/qdiagram_plugin/images/background3.png b/plugins/qdiagram_plugin/images/background3.png new file mode 100644 index 000000000..3db4f8ea5 Binary files /dev/null and b/plugins/qdiagram_plugin/images/background3.png differ diff --git a/plugins/qdiagram_plugin/images/background4.png b/plugins/qdiagram_plugin/images/background4.png new file mode 100644 index 000000000..9c1f3bfd7 Binary files /dev/null and b/plugins/qdiagram_plugin/images/background4.png differ diff --git a/plugins/qdiagram_plugin/images/bold.png b/plugins/qdiagram_plugin/images/bold.png new file mode 100644 index 000000000..986e65e25 Binary files /dev/null and b/plugins/qdiagram_plugin/images/bold.png differ diff --git a/plugins/qdiagram_plugin/images/bringtofront.png b/plugins/qdiagram_plugin/images/bringtofront.png new file mode 100644 index 000000000..bda27578a Binary files /dev/null and b/plugins/qdiagram_plugin/images/bringtofront.png differ diff --git a/plugins/qdiagram_plugin/images/delete.png b/plugins/qdiagram_plugin/images/delete.png new file mode 100644 index 000000000..df2a147d2 Binary files /dev/null and b/plugins/qdiagram_plugin/images/delete.png differ diff --git a/plugins/qdiagram_plugin/images/floodfill.png b/plugins/qdiagram_plugin/images/floodfill.png new file mode 100644 index 000000000..54c0dae23 Binary files /dev/null and b/plugins/qdiagram_plugin/images/floodfill.png differ diff --git a/plugins/qdiagram_plugin/images/italic.png b/plugins/qdiagram_plugin/images/italic.png new file mode 100644 index 000000000..9a438b57a Binary files /dev/null and b/plugins/qdiagram_plugin/images/italic.png differ diff --git a/plugins/qdiagram_plugin/images/lc_aligncenter.png b/plugins/qdiagram_plugin/images/lc_aligncenter.png new file mode 100644 index 000000000..c6178f84c Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_aligncenter.png differ diff --git a/plugins/qdiagram_plugin/images/lc_aligndown.png b/plugins/qdiagram_plugin/images/lc_aligndown.png new file mode 100644 index 000000000..06d59bdbe Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_aligndown.png differ diff --git a/plugins/qdiagram_plugin/images/lc_alignmiddle.png b/plugins/qdiagram_plugin/images/lc_alignmiddle.png new file mode 100644 index 000000000..ec8fdd84f Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_alignmiddle.png differ diff --git a/plugins/qdiagram_plugin/images/lc_alignup.png b/plugins/qdiagram_plugin/images/lc_alignup.png new file mode 100644 index 000000000..ebbb41e1f Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_alignup.png differ diff --git a/plugins/qdiagram_plugin/images/lc_backward.png b/plugins/qdiagram_plugin/images/lc_backward.png new file mode 100644 index 000000000..88167bb89 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_backward.png differ diff --git a/plugins/qdiagram_plugin/images/lc_bold.png b/plugins/qdiagram_plugin/images/lc_bold.png new file mode 100644 index 000000000..19cc69482 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_bold.png differ diff --git a/plugins/qdiagram_plugin/images/lc_bringtofront.png b/plugins/qdiagram_plugin/images/lc_bringtofront.png new file mode 100644 index 000000000..4da328da3 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_bringtofront.png differ diff --git a/plugins/qdiagram_plugin/images/lc_copy.png b/plugins/qdiagram_plugin/images/lc_copy.png new file mode 100644 index 000000000..719540c3e Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_copy.png differ diff --git a/plugins/qdiagram_plugin/images/lc_cut.png b/plugins/qdiagram_plugin/images/lc_cut.png new file mode 100644 index 000000000..245fcc89e Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_cut.png differ diff --git a/plugins/qdiagram_plugin/images/lc_fliphorizontal.png b/plugins/qdiagram_plugin/images/lc_fliphorizontal.png new file mode 100644 index 000000000..6eed97595 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_fliphorizontal.png differ diff --git a/plugins/qdiagram_plugin/images/lc_flipvertical.png b/plugins/qdiagram_plugin/images/lc_flipvertical.png new file mode 100644 index 000000000..5440863b8 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_flipvertical.png differ diff --git a/plugins/qdiagram_plugin/images/lc_forward.png b/plugins/qdiagram_plugin/images/lc_forward.png new file mode 100644 index 000000000..c62e70fd9 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_forward.png differ diff --git a/plugins/qdiagram_plugin/images/lc_grid.png b/plugins/qdiagram_plugin/images/lc_grid.png new file mode 100644 index 000000000..c63ffe119 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_grid.png differ diff --git a/plugins/qdiagram_plugin/images/lc_griduse.png b/plugins/qdiagram_plugin/images/lc_griduse.png new file mode 100644 index 000000000..108451490 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_griduse.png differ diff --git a/plugins/qdiagram_plugin/images/lc_gridvisible.png b/plugins/qdiagram_plugin/images/lc_gridvisible.png new file mode 100644 index 000000000..b59a3b8a0 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_gridvisible.png differ diff --git a/plugins/qdiagram_plugin/images/lc_group.png b/plugins/qdiagram_plugin/images/lc_group.png new file mode 100644 index 000000000..52e6a5b13 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_group.png differ diff --git a/plugins/qdiagram_plugin/images/lc_italic.png b/plugins/qdiagram_plugin/images/lc_italic.png new file mode 100644 index 000000000..f703f15ce Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_italic.png differ diff --git a/plugins/qdiagram_plugin/images/lc_objectalign.png b/plugins/qdiagram_plugin/images/lc_objectalign.png new file mode 100644 index 000000000..01b95db41 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_objectalign.png differ diff --git a/plugins/qdiagram_plugin/images/lc_objectalignleft.png b/plugins/qdiagram_plugin/images/lc_objectalignleft.png new file mode 100644 index 000000000..6a52b6273 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_objectalignleft.png differ diff --git a/plugins/qdiagram_plugin/images/lc_objectalignright.png b/plugins/qdiagram_plugin/images/lc_objectalignright.png new file mode 100644 index 000000000..9242f1ea5 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_objectalignright.png differ diff --git a/plugins/qdiagram_plugin/images/lc_open.png b/plugins/qdiagram_plugin/images/lc_open.png new file mode 100644 index 000000000..06cc09911 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_open.png differ diff --git a/plugins/qdiagram_plugin/images/lc_redo.png b/plugins/qdiagram_plugin/images/lc_redo.png new file mode 100644 index 000000000..df2915f6d Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_redo.png differ diff --git a/plugins/qdiagram_plugin/images/lc_save.png b/plugins/qdiagram_plugin/images/lc_save.png new file mode 100644 index 000000000..b2aa10336 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_save.png differ diff --git a/plugins/qdiagram_plugin/images/lc_saveas.png b/plugins/qdiagram_plugin/images/lc_saveas.png new file mode 100644 index 000000000..c4557692f Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_saveas.png differ diff --git a/plugins/qdiagram_plugin/images/lc_sendtoback.png b/plugins/qdiagram_plugin/images/lc_sendtoback.png new file mode 100644 index 000000000..700d16d7b Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_sendtoback.png differ diff --git a/plugins/qdiagram_plugin/images/lc_toggleobjectrotatemode.png b/plugins/qdiagram_plugin/images/lc_toggleobjectrotatemode.png new file mode 100644 index 000000000..a5f693705 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_toggleobjectrotatemode.png differ diff --git a/plugins/qdiagram_plugin/images/lc_underline.png b/plugins/qdiagram_plugin/images/lc_underline.png new file mode 100644 index 000000000..ac01df4ef Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_underline.png differ diff --git a/plugins/qdiagram_plugin/images/lc_undo.png b/plugins/qdiagram_plugin/images/lc_undo.png new file mode 100644 index 000000000..28bbdacb7 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_undo.png differ diff --git a/plugins/qdiagram_plugin/images/lc_ungroup.png b/plugins/qdiagram_plugin/images/lc_ungroup.png new file mode 100644 index 000000000..d095eae80 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_ungroup.png differ diff --git a/plugins/qdiagram_plugin/images/lc_zoom.png b/plugins/qdiagram_plugin/images/lc_zoom.png new file mode 100644 index 000000000..e20d06062 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_zoom.png differ diff --git a/plugins/qdiagram_plugin/images/lc_zoomin.png b/plugins/qdiagram_plugin/images/lc_zoomin.png new file mode 100644 index 000000000..f607ebc32 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_zoomin.png differ diff --git a/plugins/qdiagram_plugin/images/lc_zoomminus.png b/plugins/qdiagram_plugin/images/lc_zoomminus.png new file mode 100644 index 000000000..60f57fc18 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_zoomminus.png differ diff --git a/plugins/qdiagram_plugin/images/lc_zoomoptimal.png b/plugins/qdiagram_plugin/images/lc_zoomoptimal.png new file mode 100644 index 000000000..c2033067b Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_zoomoptimal.png differ diff --git a/plugins/qdiagram_plugin/images/lc_zoompagewidth.png b/plugins/qdiagram_plugin/images/lc_zoompagewidth.png new file mode 100644 index 000000000..8abe44077 Binary files /dev/null and b/plugins/qdiagram_plugin/images/lc_zoompagewidth.png differ diff --git a/plugins/qdiagram_plugin/images/linecolor.png b/plugins/qdiagram_plugin/images/linecolor.png new file mode 100644 index 000000000..98a821f27 Binary files /dev/null and b/plugins/qdiagram_plugin/images/linecolor.png differ diff --git a/plugins/qdiagram_plugin/images/linepointer.png b/plugins/qdiagram_plugin/images/linepointer.png new file mode 100644 index 000000000..66933d43b Binary files /dev/null and b/plugins/qdiagram_plugin/images/linepointer.png differ diff --git a/plugins/qdiagram_plugin/images/pointer.png b/plugins/qdiagram_plugin/images/pointer.png new file mode 100644 index 000000000..0b0b0aa69 Binary files /dev/null and b/plugins/qdiagram_plugin/images/pointer.png differ diff --git a/plugins/qdiagram_plugin/images/sendtoback.png b/plugins/qdiagram_plugin/images/sendtoback.png new file mode 100644 index 000000000..5aa3b0a24 Binary files /dev/null and b/plugins/qdiagram_plugin/images/sendtoback.png differ diff --git a/plugins/qdiagram_plugin/images/textpointer.png b/plugins/qdiagram_plugin/images/textpointer.png new file mode 100644 index 000000000..b25832cad Binary files /dev/null and b/plugins/qdiagram_plugin/images/textpointer.png differ diff --git a/plugins/qdiagram_plugin/images/underline.png b/plugins/qdiagram_plugin/images/underline.png new file mode 100644 index 000000000..9b8209f52 Binary files /dev/null and b/plugins/qdiagram_plugin/images/underline.png differ diff --git a/plugins/qdiagram_plugin/mainwindow.cpp b/plugins/qdiagram_plugin/mainwindow.cpp new file mode 100644 index 000000000..d3a5f9c1c --- /dev/null +++ b/plugins/qdiagram_plugin/mainwindow.cpp @@ -0,0 +1,1258 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include +#include +#include + +#include "mainwindow.h" +#include "diagramitem.h" +#include "diagramdrawitem.h" +#include "diagrampathitem.h" +#include "diagramscene.h" +#include "diagramtextitem.h" + +const int InsertTextButton = 10; +const int InsertDrawItemButton = 64; + +#define NDEBUG + +//! [0] +MainWindow::MainWindow() +{ + createActions(); + createToolBox(); + createMenus(); + + scene = new DiagramScene(itemMenu); + scene->setSceneRect(QRectF(0, 0, 5000, 5000)); + myGrid=10.0; + scene->setGrid(myGrid); + connect(scene, SIGNAL(itemInserted(DiagramItem *)), + this, SLOT(itemInserted(DiagramItem *))); + connect(scene, SIGNAL(textInserted(QGraphicsTextItem *)), + this, SLOT(textInserted(QGraphicsTextItem *))); + connect(scene, SIGNAL(itemSelected(QGraphicsItem *)), + this, SLOT(itemSelected(QGraphicsItem *))); + // activate/deactivate shortcuts when text is edited in scene + connect(scene, SIGNAL(editorHasReceivedFocus()), + this, SLOT(deactivateShortcuts())); + connect(scene, SIGNAL(editorHasLostFocus()), + this, SLOT(activateShortcuts())); + connect(scene, SIGNAL(zoomRect(QPointF,QPointF)), + this, SLOT(doZoomRect(QPointF,QPointF))); + connect(scene, SIGNAL(zoom(const qreal)), + this, SLOT(zoom(const qreal))); + createToolbars(); + + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(toolBox); + view = new QGraphicsView(scene); + view->setDragMode(QGraphicsView::RubberBandDrag); + view->setCacheMode(QGraphicsView::CacheBackground); + layout->addWidget(view); + + QWidget *widget = new QWidget; + widget->setLayout(layout); + + setCentralWidget(widget); + setWindowTitle(tr("QDiagram")); + + myFileName.clear(); + + myShowGrid=false; +} +//! [0] + +//! [1] +void MainWindow::backgroundButtonGroupClicked(QAbstractButton *button) +{ + QList buttons = backgroundButtonGroup->buttons(); + foreach (QAbstractButton *myButton, buttons) { + if (myButton != button) + button->setChecked(false); + } + QString text = button->text(); + if (text == tr("Blue Grid")) + scene->setBackgroundBrush(QPixmap(":/images/background1.png")); + else if (text == tr("White Grid")) + scene->setBackgroundBrush(QPixmap(":/images/background2.png")); + else if (text == tr("Gray Grid")) + scene->setBackgroundBrush(QPixmap(":/images/background3.png")); + else + scene->setBackgroundBrush(QPixmap(":/images/background4.png")); + + scene->update(); + view->update(); +} +//! [1] + +//! [2] +void MainWindow::buttonGroupClicked(int id) +{ + QList buttons = buttonGroup->buttons(); + foreach (QAbstractButton *button, buttons) { + if (buttonGroup->button(id) != button) + button->setChecked(false); + } + if (id == InsertTextButton) { + scene->setMode(DiagramScene::InsertText); + } + else + if ((id&192) == InsertDrawItemButton){ + scene->setItemType(DiagramDrawItem::DiagramType(id&63)); + scene->setMode(DiagramScene::InsertDrawItem); + } + else { + scene->setItemType(DiagramItem::DiagramType(id)); + scene->setMode(DiagramScene::InsertItem); + } + view->setDragMode(QGraphicsView::NoDrag); + //pointerTypeGroup->checkedButton()->setChecked(false); + buttons = pointerTypeGroup->buttons(); + foreach (QAbstractButton *button, buttons) { + button->setChecked(false); + } +} +//! [2] + +//! [3] +void MainWindow::deleteItem() +{ + foreach (QGraphicsItem *item, scene->selectedItems()) { + if (item->type() == DiagramItem::Type) { + //qgraphicsitem_cast(item)->removeArrows(); + } + scene->removeItem(item); + } +} +//! [3] + +//! [4] +void MainWindow::pointerGroupClicked(int id) +{ + QList buttons = pointerTypeGroup->buttons(); + foreach (QAbstractButton *button, buttons) { + if (pointerTypeGroup->button(id) != button) + button->setChecked(false); + } + if(pointerTypeGroup->checkedId()!=DiagramScene::MoveItem) view->setDragMode(QGraphicsView::NoDrag); + else view->setDragMode(QGraphicsView::RubberBandDrag); + scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId())); +} +//! [4] + +//! [5] +void MainWindow::bringToFront() +{ + //std::cout << "bring to front" << std::endl; + if (scene->selectedItems().isEmpty()) + return; + + QGraphicsItem *selectedItem = scene->selectedItems().first(); + QList overlapItems = selectedItem->collidingItems(); + + qreal zValue = 0; + foreach (QGraphicsItem *item, overlapItems) { + if (item->zValue() >= zValue) //&& + //item->type() == DiagramItem::Type) + zValue = item->zValue() + 0.1; + } + selectedItem->setZValue(zValue); +} +//! [5] + +//! [6] +void MainWindow::sendToBack() +{ + //std::cout << "send to back" << std::endl; + if (scene->selectedItems().isEmpty()) + return; + + QGraphicsItem *selectedItem = scene->selectedItems().first(); + QList overlapItems = selectedItem->collidingItems(); + + qreal zValue = 0; + foreach (QGraphicsItem *item, overlapItems) { + if (item->zValue() <= zValue)// && + //item->type() == DiagramItem::Type) + zValue = item->zValue() - 0.1; + } + selectedItem->setZValue(zValue); +} + +void MainWindow::rotateRight() +{ + if (scene->selectedItems().isEmpty()) + return; + + QGraphicsItem *selectedItem = scene->selectedItems().first(); + //selectedItem->rotate(90); + QTransform trans=selectedItem->transform(); + selectedItem->setTransform(trans*QTransform().rotate(90),false); +#ifdef DEBUG + std::cout << "rotate done" << std::endl; +#endif +} + +void MainWindow::rotateLeft() +{ + if (scene->selectedItems().isEmpty()) + return; + + QGraphicsItem *selectedItem = scene->selectedItems().first(); + //selectedItem->rotate(-90); + QTransform trans=selectedItem->transform(); + selectedItem->setTransform(trans*QTransform().rotate(-90),false); +#ifdef DEBUG + std::cout << "rotate left done" << std::endl; +#endif +} + +void MainWindow::flipX() +{ + if (scene->selectedItems().isEmpty()) + return; + + QGraphicsItem *selectedItem = scene->selectedItems().first(); + //selectedItem->setTransform(QTransform(-1,0,0,1,0,0),true); + QTransform trans=selectedItem->transform(); + selectedItem->setTransform(trans*QTransform(-1,0,0,1,0,0),false); + //selectedItem->scale(-1,1); +#ifdef DEBUG + std::cout << trans.m11() << "," + << trans.m12() << "," + << trans.m21() << "," + << trans.m22() << "," << std::endl; + + std::cout << "flipX done" << std::endl; +#endif +} + +void MainWindow::flipY() +{ + if (scene->selectedItems().isEmpty()) + return; + + QGraphicsItem *selectedItem = scene->selectedItems().first(); + QTransform trans=selectedItem->transform(); + selectedItem->setTransform(trans*QTransform(1,0,0,-1,0,0),false); + //selectedItem->scale(1,-1); +#ifdef DEBUG + std::cout << "flipY done" << std::endl; +#endif +} + +void MainWindow::moveItems() +{ + scene->setMode(DiagramScene::MoveItems); + view->setDragMode(QGraphicsView::RubberBandDrag); +#ifdef DEBUG + std::cout << "set move mode" << std::endl; +#endif +} + +void MainWindow::abort() +{ + scene->abort(); + scene->setMode(DiagramScene::MoveItem); + view->setDragMode(QGraphicsView::RubberBandDrag); +#ifdef DEBUG + std::cout << "abort done" << std::endl; +#endif +} + +void MainWindow::copyItems() +{ + scene->setMode(DiagramScene::CopyItem); + view->setDragMode(QGraphicsView::RubberBandDrag); +#ifdef DEBUG + std::cout << "copy mode" << std::endl; +#endif +} + +void MainWindow::groupItems() +{ + if (scene->selectedItems().isEmpty()) + return; + + QGraphicsItemGroup *test = scene->createItemGroup(scene->selectedItems()); + test->setFlag(QGraphicsItem::ItemIsMovable, true); + test->setFlag(QGraphicsItem::ItemIsSelectable, true); +} + +void MainWindow::ungroupItems() +{ + if (scene->selectedItems().isEmpty()) + return; +#ifdef DEBUG + std::cout << "ungroup" << std::endl; + std::cout << scene->selectedItems().count() << std::endl; +#endif + foreach (QGraphicsItem *item, scene->selectedItems()) { +#ifdef DEBUG + std::cout << item->type() << std::endl; + std::cout << typeid(item).name() << std::endl; +#endif + if (item->type()==10) { + QGraphicsItemGroup *group = (QGraphicsItemGroup*) item; + scene->destroyItemGroup(group); + } + } +#ifdef DEBUG + //std::cout << qPrintable(scene->selectedItems().first()->objectName())<< std::endl; +#endif + //QGraphicsItemGroup *group = (QGraphicsItemGroup*)scene->selectedItems().first(); + //scene->destroyItemGroup(group); + //scene->destroyItemGroup(scene->selectedItems()); +} +//! [6] + +//! [7] +void MainWindow::itemInserted(DiagramItem *item) +{ + //scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId())); + buttonGroup->button(int(item->diagramType()))->setChecked(false); +} +//! [7] + +//! [8] +void MainWindow::textInserted(QGraphicsTextItem *) +{ + buttonGroup->button(InsertTextButton)->setChecked(false); + scene->setMode(DiagramScene::MoveItem); + view->setDragMode(QGraphicsView::RubberBandDrag); + pointerTypeGroup->button(DiagramScene::MoveItem)->setChecked(true); +} +//! [8] +void MainWindow::activateShortcuts() +{ + foreach(QAction* item,listOfActions){ + item->setEnabled(true); + } + foreach(QShortcut* item,listOfShortcuts){ + item->setEnabled(true); + } +#ifdef DEBUG + std::cout<<"activate"<setEnabled(false); + } + foreach(QShortcut* item,listOfShortcuts){ + item->setEnabled(false); + } +#ifdef DEBUG + std::cout<<"deactivate"<(sender()); + fontColorToolButton->setIcon(createColorToolButtonIcon( + ":/images/textpointer.png", + qVariantValue(textAction->data()))); + textButtonTriggered(); +} +//! [12] + +//! [13] +void MainWindow::itemColorChanged() +{ + fillAction = qobject_cast(sender()); + fillColorToolButton->setIcon(createColorToolButtonIcon( + ":/images/floodfill.png", + qVariantValue(fillAction->data()))); + fillButtonTriggered(); +} +//! [13] + +//! [14] +void MainWindow::lineColorChanged() +{ + lineAction = qobject_cast(sender()); + lineColorToolButton->setIcon(createColorToolButtonIcon( + ":/images/linecolor.png", + qVariantValue(lineAction->data()))); + lineButtonTriggered(); +} +//! [14] + +//! [15] +void MainWindow::textButtonTriggered() +{ + scene->setTextColor(qVariantValue(textAction->data())); +} +//! [15] + +//! [16] +void MainWindow::fillButtonTriggered() +{ + scene->setItemColor(qVariantValue(fillAction->data())); +} +//! [16] + +//! [17] +void MainWindow::lineButtonTriggered() +{ + scene->setLineColor(qVariantValue(lineAction->data())); +} +//! [17] + +//! [18] +void MainWindow::handleFontChange() +{ + QFont font = fontCombo->currentFont(); + font.setPointSize(fontSizeCombo->currentText().toInt()); + font.setWeight(boldAction->isChecked() ? QFont::Bold : QFont::Normal); + font.setItalic(italicAction->isChecked()); + font.setUnderline(underlineAction->isChecked()); + + scene->setFont(font); +} +//! [18] + +//! [19] +void MainWindow::itemSelected(QGraphicsItem *item) +{ + DiagramTextItem *textItem = + qgraphicsitem_cast(item); + + QFont font = textItem->font(); + QColor color = textItem->defaultTextColor(); + fontCombo->setCurrentFont(font); + fontSizeCombo->setEditText(QString().setNum(font.pointSize())); + boldAction->setChecked(font.weight() == QFont::Bold); + italicAction->setChecked(font.italic()); + underlineAction->setChecked(font.underline()); +} +//! [19] + +//! [20] +void MainWindow::about() +{ + QMessageBox::about(this, tr("About Diagram Scene"), + tr("The Diagram Scene example shows " + "use of the graphics framework.")); +} +//! [20] +void MainWindow::print() +{ + QPrinter printer; + if (QPrintDialog(&printer).exec() == QDialog::Accepted) { + QPainter painter(&printer); + painter.setRenderHint(QPainter::Antialiasing); + scene->render(&painter); + } +} + +void MainWindow::exportImage() +{ + QFileDialog::Options options; + options = 0; + QString selectedFilter; + QString fileName = QFileDialog::getSaveFileName(this, + tr("Export Diagram to ..."), + ".jpg", + tr("Jpg (*.jpg);;Png (*.png);;Pdf (*.pdf);;Postscript (*.ps)"), + &selectedFilter, + options); + if (!fileName.isEmpty()){ +#ifdef DEBUG + std::cout << "Selected Filter: " << qPrintable(selectedFilter) << std::endl; +#endif + if((selectedFilter=="Pdf (*.pdf)")or(selectedFilter=="Postscript (*.ps)")) { + QRectF rect=scene->itemsBoundingRect(); // Bonding der Elemente in scene + QPrinter printer; + printer.setOutputFileName(fileName); + QSizeF size=printer.paperSize(QPrinter::Millimeter); // definiere Paper mit gleichen Aspectratio wie rect + size.setHeight(size.width()*rect.height()/rect.width()); + printer.setPaperSize(size,QPrinter::Millimeter); + printer.setPageMargins(0,0,0,0,QPrinter::Millimeter); + QPainter painter(&printer);// generate PDF/PS + painter.setRenderHint(QPainter::Antialiasing); + scene->render(&painter,QRectF(),rect); + } + else { + QPixmap pixmap(1000,1000); + pixmap.fill(); + QPainter painter(&pixmap); + painter.setRenderHint(QPainter::Antialiasing); + QRectF rect=scene->itemsBoundingRect(); + scene->render(&painter,QRectF(),rect); + painter.end(); + + pixmap.save(fileName); + } + + } +} + +//! [21] +void MainWindow::createToolBox() +{ + buttonGroup = new QButtonGroup; + buttonGroup->setExclusive(false); + connect(buttonGroup, SIGNAL(buttonClicked(int)), + this, SLOT(buttonGroupClicked(int))); + QGridLayout *layout = new QGridLayout; + layout->addWidget(createCellWidget(tr("Conditional"), + DiagramItem::Conditional), 0, 0); + layout->addWidget(createCellWidget(tr("Process"), + DiagramItem::Step),0, 1); + layout->addWidget(createCellWidget(tr("Input/Output"), + DiagramItem::Io), 1, 0); +// added DrawItem + layout->addWidget(createCellWidget(tr("Rectangle"), + DiagramDrawItem::Rectangle), 2, 0); + layout->addWidget(createCellWidget(tr("Ellipse"), + DiagramDrawItem::Ellipse), 2, 1); +//! [21] + + QToolButton *textButton = new QToolButton; + textButton->setCheckable(true); + buttonGroup->addButton(textButton, InsertTextButton); + textButton->setIcon(QIcon(QPixmap(":/images/textpointer.png") + .scaled(30, 30))); + textButton->setIconSize(QSize(50, 50)); + QGridLayout *textLayout = new QGridLayout; + textLayout->addWidget(textButton, 0, 0, Qt::AlignHCenter); + textLayout->addWidget(new QLabel(tr("Text")), 1, 0, Qt::AlignCenter); + QWidget *textWidget = new QWidget; + textWidget->setLayout(textLayout); + layout->addWidget(textWidget, 1, 1); + + layout->setRowStretch(3, 10); + layout->setColumnStretch(2, 10); + + QWidget *itemWidget = new QWidget; + itemWidget->setLayout(layout); + + backgroundButtonGroup = new QButtonGroup; + connect(backgroundButtonGroup, SIGNAL(buttonClicked(QAbstractButton *)), + this, SLOT(backgroundButtonGroupClicked(QAbstractButton *))); + + QGridLayout *backgroundLayout = new QGridLayout; + backgroundLayout->addWidget(createBackgroundCellWidget(tr("Blue Grid"), + ":/images/background1.png"), 0, 0); + backgroundLayout->addWidget(createBackgroundCellWidget(tr("White Grid"), + ":/images/background2.png"), 0, 1); + backgroundLayout->addWidget(createBackgroundCellWidget(tr("Gray Grid"), + ":/images/background3.png"), 1, 0); + backgroundLayout->addWidget(createBackgroundCellWidget(tr("No Grid"), + ":/images/background4.png"), 1, 1); + + backgroundLayout->setRowStretch(2, 10); + backgroundLayout->setColumnStretch(2, 10); + + QWidget *backgroundWidget = new QWidget; + backgroundWidget->setLayout(backgroundLayout); + + +//! [22] + toolBox = new QToolBox; + toolBox->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Ignored)); + toolBox->setMinimumWidth(itemWidget->sizeHint().width()); + toolBox->addItem(itemWidget, tr("Basic Flowchart Shapes")); + toolBox->addItem(backgroundWidget, tr("Backgrounds")); +} +//! [22] + +//! [23] +void MainWindow::createActions() +{ + toFrontAction = new QAction(QIcon(":/images/lc_bringtofront.png"), + tr("Bring to &Front"), this); + toFrontAction->setShortcut(tr("Ctrl+F")); + toFrontAction->setStatusTip(tr("Bring item to front")); + connect(toFrontAction, SIGNAL(triggered()), + this, SLOT(bringToFront())); +//! [23] + + sendBackAction = new QAction(QIcon(":/images/lc_sendtoback.png"), + tr("Send to &Back"), this); + sendBackAction->setShortcut(tr("Ctrl+B")); + sendBackAction->setStatusTip(tr("Send item to back")); + connect(sendBackAction, SIGNAL(triggered()), + this, SLOT(sendToBack())); + + QPixmap pixmap2=QPixmap(":/images/lc_toggleobjectrotatemode.png").transformed(QTransform(-1,0,0,1,0,0)); + rotateRightAction = new QAction(QIcon(pixmap2), + tr("rotate &Right"), this); + rotateRightAction->setShortcut(tr("R")); + rotateRightAction->setStatusTip(tr("rotate item 90 degrees right")); + connect(rotateRightAction, SIGNAL(triggered()), + this, SLOT(rotateRight())); + listOfActions.append(rotateRightAction); + + rotateLeftAction = new QAction(QIcon(":/images/lc_toggleobjectrotatemode.png"), + tr("rotate &Left"), this); + rotateLeftAction->setShortcut(tr("Shift+R")); + rotateLeftAction->setStatusTip(tr("rotate item 90 degrees left")); + connect(rotateLeftAction, SIGNAL(triggered()), + this, SLOT(rotateLeft())); + listOfActions.append(rotateLeftAction); + + groupAction = new QAction(QIcon(":/images/lc_group.png"), + tr("&group Items"), this); + groupAction->setShortcut(tr("Ctrl+G")); + groupAction->setStatusTip(tr("group Items")); + connect(groupAction, SIGNAL(triggered()), + this, SLOT(groupItems())); + + ungroupAction = new QAction(QIcon(":/images/lc_ungroup.png"), + tr("&ungroup Item"), this); + ungroupAction->setShortcut(tr("Shift+Ctrl+G")); + ungroupAction->setStatusTip(tr("ungruoup Items")); + connect(ungroupAction, SIGNAL(triggered()), + this, SLOT(ungroupItems())); + + deleteAction = new QAction(QIcon(":/images/delete.png"), + tr("&Delete"), this); + deleteAction->setShortcut(tr("Delete")); + deleteAction->setStatusTip(tr("Delete item from diagram")); + connect(deleteAction, SIGNAL(triggered()), + this, SLOT(deleteItem())); + listOfActions.append(deleteAction); + + printAction = new QAction(tr("&Print"), this); + printAction->setStatusTip(tr("Print Diagram")); + connect(printAction, SIGNAL(triggered()), this, SLOT(print())); + + exportAction = new QAction(tr("&Export Diagram"), this); + exportAction->setStatusTip(tr("Export Diagram to image")); + connect(exportAction, SIGNAL(triggered()), this, SLOT(exportImage())); + + exitAction = new QAction(tr("E&xit"), this); + exitAction->setShortcut(tr("Ctrl+X")); + exitAction->setStatusTip(tr("Quit Scenediagram example")); + connect(exitAction, SIGNAL(triggered()), this, SLOT(close())); + + boldAction = new QAction(tr("Bold"), this); + boldAction->setCheckable(true); + QPixmap pixmap(":/images/lc_bold.png"); + boldAction->setIcon(QIcon(pixmap)); + //boldAction->setShortcut(tr("Ctrl+B")); + connect(boldAction, SIGNAL(triggered()), + this, SLOT(handleFontChange())); + + italicAction = new QAction(QIcon(":/images/lc_italic.png"), + tr("Italic"), this); + italicAction->setCheckable(true); + //italicAction->setShortcut(tr("Ctrl+I")); + connect(italicAction, SIGNAL(triggered()), + this, SLOT(handleFontChange())); + + underlineAction = new QAction(QIcon(":/images/lc_underline.png"), + tr("Underline"), this); + underlineAction->setCheckable(true); + //underlineAction->setShortcut(tr("Ctrl+U")); + connect(underlineAction, SIGNAL(triggered()), + this, SLOT(handleFontChange())); + + aboutAction = new QAction(tr("A&bout"), this); + //aboutAction->setShortcut(tr("Ctrl+B")); + connect(aboutAction, SIGNAL(triggered()), + this, SLOT(about())); + + copyAction = new QAction(tr("&Copy"), this); + copyAction->setShortcut(tr("c")); + connect(copyAction, SIGNAL(triggered()), + this, SLOT(copyItems())); + listOfActions.append(copyAction); + + moveAction = new QAction(tr("&Move"), this); + moveAction->setShortcut(tr("m")); + connect(moveAction, SIGNAL(triggered()), + this, SLOT(moveItems())); + listOfActions.append(moveAction); + + flipXAction = new QAction(QIcon(":/images/lc_flipvertical.png"), + tr("Flip &X"), this); + flipXAction->setShortcut(tr("f")); + connect(flipXAction, SIGNAL(triggered()), + this, SLOT(flipX())); + listOfActions.append(flipXAction); + + flipYAction = new QAction(QIcon(":/images/lc_fliphorizontal.png"),tr("Flip &Y"), this); + flipYAction->setShortcut(tr("Shift+F")); + connect(flipYAction, SIGNAL(triggered()), + this, SLOT(flipY())); + listOfActions.append(flipYAction); + + escShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), + this); + connect(escShortcut,SIGNAL(activated()),this,SLOT(abort())); + + // Zoom in/out + zoomInAction = new QAction(QIcon(":/images/lc_zoomin.png"),tr("Zoom &in"), this); + zoomInAction->setShortcut(tr("Shift+z")); + connect(zoomInAction, SIGNAL(triggered()), + this, SLOT(zoomIn())); + listOfActions.append(zoomInAction); + + zoomOutAction = new QAction(QIcon(":/images/lc_zoomminus.png"),tr("Zoom &out"), this); + zoomOutAction->setShortcut(tr("Ctrl+z")); + connect(zoomOutAction, SIGNAL(triggered()), + this, SLOT(zoomOut())); + + zoomAction = new QAction(QIcon(":/images/lc_zoomoptimal.png"),tr("&Zoom area"), this); + zoomAction->setShortcut(tr("z")); + connect(zoomAction, SIGNAL(triggered()), + this, SLOT(zoomRect())); + listOfActions.append(zoomAction); + + zoomFitAction = new QAction(QIcon(":/images/lc_zoompagewidth.png"),tr("Zoom &Fit"), this); + zoomFitAction->setShortcut(tr("v")); + connect(zoomFitAction, SIGNAL(triggered()), + this, SLOT(zoomFit())); + listOfActions.append(zoomFitAction); + + showGridAction = new QAction(QIcon(":/images/lc_gridvisible.png"),tr("Show &Grid"), this); + showGridAction->setCheckable(true); + showGridAction->setChecked(false); + connect(showGridAction, SIGNAL(toggled(bool)), + this, SLOT(toggleGrid(bool))); + + loadAction = new QAction(QIcon(":/images/lc_open.png"),tr("L&oad ..."), this); + loadAction->setShortcut(tr("Ctrl+o")); + connect(loadAction, SIGNAL(triggered()), + this, SLOT(load())); + + saveAction = new QAction(QIcon(":/images/lc_save.png"),tr("&Save ..."), this); + saveAction->setShortcut(tr("Ctrl+s")); + connect(saveAction, SIGNAL(triggered()), + this, SLOT(save())); + + saveAsAction = new QAction(QIcon(":/images/lc_saveas.png"),tr("Save &As ..."), this); + saveAsAction->setShortcut(tr("Ctrl+s")); + connect(saveAsAction, SIGNAL(triggered()), + this, SLOT(saveAs())); +} + +//! [24] +void MainWindow::createMenus() +{ + fileMenu = menuBar()->addMenu(tr("&File")); + fileMenu->addAction(loadAction); + fileMenu->addAction(saveAction); + fileMenu->addAction(saveAsAction); + fileMenu->addAction(printAction); + fileMenu->addAction(exportAction); + fileMenu->addAction(exitAction); + + viewMenu = menuBar()->addMenu(tr("&View")); + viewMenu->addAction(zoomInAction); + viewMenu->addAction(zoomOutAction); + viewMenu->addAction(zoomAction); + viewMenu->addAction(zoomFitAction); + viewMenu->addSeparator(); + viewMenu->addAction(showGridAction); + + itemMenu = menuBar()->addMenu(tr("&Item")); + itemMenu->addAction(deleteAction); + itemMenu->addAction(copyAction); + itemMenu->addAction(moveAction); + itemMenu->addSeparator(); + itemMenu->addAction(toFrontAction); + itemMenu->addAction(sendBackAction); + itemMenu->addSeparator(); + itemMenu->addAction(rotateRightAction); + itemMenu->addAction(rotateLeftAction); + itemMenu->addAction(flipXAction); + itemMenu->addAction(flipYAction); + itemMenu->addAction(groupAction); + itemMenu->addAction(ungroupAction); + + aboutMenu = menuBar()->addMenu(tr("&Help")); + aboutMenu->addAction(aboutAction); +} +//! [24] + +//! [25] +void MainWindow::createToolbars() +{ +//! [25] + editToolBar = addToolBar(tr("Edit")); + editToolBar->addAction(deleteAction); + editToolBar->addAction(toFrontAction); + editToolBar->addAction(sendBackAction); + editToolBar->addAction(flipXAction); + editToolBar->addAction(flipYAction); + editToolBar->addAction(rotateRightAction); + editToolBar->addAction(rotateLeftAction); + + fontCombo = new QFontComboBox(); + fontSizeCombo = new QComboBox(); + connect(fontCombo, SIGNAL(currentFontChanged(const QFont &)), + this, SLOT(currentFontChanged(const QFont &))); + + fontSizeCombo = new QComboBox; + fontSizeCombo->setEditable(true); + for (int i = 8; i < 30; i = i + 2) + fontSizeCombo->addItem(QString().setNum(i)); + QIntValidator *validator = new QIntValidator(2, 64, this); + fontSizeCombo->setValidator(validator); + connect(fontSizeCombo, SIGNAL(currentIndexChanged(const QString &)), + this, SLOT(fontSizeChanged(const QString &))); + + fontColorToolButton = new QToolButton; + fontColorToolButton->setPopupMode(QToolButton::MenuButtonPopup); + fontColorToolButton->setMenu(createColorMenu(SLOT(textColorChanged()), + Qt::black)); + textAction = fontColorToolButton->menu()->defaultAction(); + fontColorToolButton->setIcon(createColorToolButtonIcon( + ":/images/textpointer.png", Qt::black)); + fontColorToolButton->setAutoFillBackground(true); + connect(fontColorToolButton, SIGNAL(clicked()), + this, SLOT(textButtonTriggered())); + +//! [26] + fillColorToolButton = new QToolButton; + fillColorToolButton->setPopupMode(QToolButton::MenuButtonPopup); + fillColorToolButton->setMenu(createColorMenu(SLOT(itemColorChanged()), + Qt::white)); + fillAction = fillColorToolButton->menu()->defaultAction(); + fillColorToolButton->setIcon(createColorToolButtonIcon( + ":/images/floodfill.png", Qt::white)); + connect(fillColorToolButton, SIGNAL(clicked()), + this, SLOT(fillButtonTriggered())); +//! [26] + + lineColorToolButton = new QToolButton; + lineColorToolButton->setPopupMode(QToolButton::MenuButtonPopup); + lineColorToolButton->setMenu(createColorMenu(SLOT(lineColorChanged()), + Qt::black)); + lineAction = lineColorToolButton->menu()->defaultAction(); + lineColorToolButton->setIcon(createColorToolButtonIcon( + ":/images/linecolor.png", Qt::black)); + connect(lineColorToolButton, SIGNAL(clicked()), + this, SLOT(lineButtonTriggered())); + + textToolBar = addToolBar(tr("Font")); + textToolBar->addWidget(fontCombo); + textToolBar->addWidget(fontSizeCombo); + textToolBar->addAction(boldAction); + textToolBar->addAction(italicAction); + textToolBar->addAction(underlineAction); + + colorToolBar = addToolBar(tr("Color")); + colorToolBar->addWidget(fontColorToolButton); + colorToolBar->addWidget(fillColorToolButton); + colorToolBar->addWidget(lineColorToolButton); + + QToolButton *pointerButton = new QToolButton; + pointerButton->setCheckable(true); + pointerButton->setChecked(true); + pointerButton->setIcon(QIcon(":/images/pointer.png")); + linePointerButton = new QToolButton; + linePointerButton->setCheckable(true); + //linePointerButton->setIcon(QIcon(":/images/linepointer.png")); + linePointerButton->setIcon(createArrowIcon(0)); + linePointerButton->setPopupMode(QToolButton::MenuButtonPopup); + linePointerButton->setMenu(createArrowMenu(SLOT(lineArrowChanged()), + 0)); + arrowAction = linePointerButton->menu()->defaultAction(); + connect(linePointerButton, SIGNAL(clicked()), + this, SLOT(lineArrowButtonTriggered())); + + pointerTypeGroup = new QButtonGroup; + pointerTypeGroup->setExclusive(false); + pointerTypeGroup->addButton(pointerButton, int(DiagramScene::MoveItem)); + pointerTypeGroup->addButton(linePointerButton, + int(DiagramScene::InsertLine)); + connect(pointerTypeGroup, SIGNAL(buttonClicked(int)), + this, SLOT(pointerGroupClicked(int))); + + pointerToolbar = addToolBar(tr("Pointer type")); + pointerToolbar->addWidget(pointerButton); + pointerToolbar->addWidget(linePointerButton); + + zoomToolbar = addToolBar(tr("Zoom")); + zoomToolbar->addAction(zoomInAction); + zoomToolbar->addAction(zoomOutAction); + zoomToolbar->addAction(zoomAction); + zoomToolbar->addAction(zoomFitAction); +//! [27] +} +//! [27] + +//! [28] +QWidget *MainWindow::createBackgroundCellWidget(const QString &text, + const QString &image) +{ + QToolButton *button = new QToolButton; + button->setText(text); + button->setIcon(QIcon(image)); + button->setIconSize(QSize(50, 50)); + button->setCheckable(true); + backgroundButtonGroup->addButton(button); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(button, 0, 0, Qt::AlignHCenter); + layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter); + + QWidget *widget = new QWidget; + widget->setLayout(layout); + + return widget; +} +//! [28] + +//! [29] +QWidget *MainWindow::createCellWidget(const QString &text, + DiagramItem::DiagramType type) +{ + + DiagramItem item(type, itemMenu); + QIcon icon(item.image()); + + QToolButton *button = new QToolButton; + button->setIcon(icon); + button->setIconSize(QSize(50, 50)); + button->setCheckable(true); + buttonGroup->addButton(button, int(type)); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(button, 0, 0, Qt::AlignHCenter); + layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter); + + QWidget *widget = new QWidget; + widget->setLayout(layout); + + return widget; +} +//! [29] +QWidget *MainWindow::createCellWidget(const QString &text, + DiagramDrawItem::DiagramType type) +{ + + DiagramDrawItem item(type, itemMenu); + item.setPos2(230,230); + QIcon icon(item.image()); + + QToolButton *button = new QToolButton; + button->setIcon(icon); + button->setIconSize(QSize(50, 50)); + button->setCheckable(true); + buttonGroup->addButton(button, int(type)+64); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(button, 0, 0, Qt::AlignHCenter); + layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter); + + QWidget *widget = new QWidget; + widget->setLayout(layout); + + return widget; +} + +//! [30] +QMenu *MainWindow::createColorMenu(const char *slot, QColor defaultColor) +{ + QList colors; + colors << Qt::black << Qt::white << Qt::red << Qt::blue << Qt::yellow; + QStringList names; + names << tr("black") << tr("white") << tr("red") << tr("blue") + << tr("yellow"); + + QMenu *colorMenu = new QMenu; + for (int i = 0; i < colors.count(); ++i) { + QAction *action = new QAction(names.at(i), this); + action->setData(colors.at(i)); + action->setIcon(createColorIcon(colors.at(i))); + connect(action, SIGNAL(triggered()), + this, slot); + colorMenu->addAction(action); + if (colors.at(i) == defaultColor) { + colorMenu->setDefaultAction(action); + } + } + return colorMenu; +} +//! [30] + +//! [31] +QIcon MainWindow::createColorToolButtonIcon(const QString &imageFile, + QColor color) +{ + QPixmap pixmap(50, 80); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + QPixmap image(imageFile); + QRect target(0, 0, 50, 60); + QRect source(0, 0, 42, 42); + painter.fillRect(QRect(0, 60, 50, 80), color); + painter.drawPixmap(target, image, source); + + return QIcon(pixmap); +} +//! [31] + +//! [32] +QIcon MainWindow::createColorIcon(QColor color) +{ + QPixmap pixmap(20, 20); + QPainter painter(&pixmap); + painter.setPen(Qt::NoPen); + painter.fillRect(QRect(0, 0, 20, 20), color); + + return QIcon(pixmap); +} +//! [32] + +QMenu *MainWindow::createArrowMenu(const char *slot, const int def) +{ + QStringList names; + names << tr("Path") << tr("Start") << tr("End") << tr("StartEnd"); + QMenu *arrowMenu = new QMenu; + for (int i = 0; i < names.count(); ++i) { + QAction *action = new QAction(names.at(i), this); + action->setData(i); + action->setIcon(createArrowIcon(i)); + connect(action, SIGNAL(triggered()), + this, slot); + arrowMenu->addAction(action); + if (i == def) { + arrowMenu->setDefaultAction(action); + } + } + return arrowMenu; +} + +QIcon MainWindow::createArrowIcon(const int i) +{ + QPixmap pixmap(50, 80); + DiagramPathItem* item=new DiagramPathItem(DiagramPathItem::DiagramType(i),0,0); + pixmap=item->icon(); + delete item; + + return QIcon(pixmap); +} + +void MainWindow::lineArrowButtonTriggered() +{ + scene->setArrow(qVariantValue(arrowAction->data())); + pointerTypeGroup->button(int(DiagramScene::MoveItem))->setChecked(false); +} + +void MainWindow::lineArrowChanged() +{ + arrowAction = qobject_cast(sender()); + linePointerButton->setIcon(createArrowIcon(qVariantValue(arrowAction->data()))); + lineArrowButtonTriggered(); +} + +void MainWindow::zoomIn() +{ + zoom(2.0); +} + +void MainWindow::zoomOut() +{ + zoom(0.5); +} + +void MainWindow::zoom(const qreal factor) +{ + QPointF topLeft = view->mapToScene( 0, 0 ); + QPointF bottomRight = view->mapToScene( view->viewport()->width() - 1, view->viewport()->height() - 1 ); + qreal width=bottomRight.x()-topLeft.x(); + qreal height=bottomRight.y()-topLeft.y(); + //std::cout << width << "/" << height << " : " << factor << std::endl; + if((width/factor<=5000)&&(height/factor<=5000)){ + QMatrix oldMatrix = view->matrix(); + qreal newScale=oldMatrix.m11()*factor; + view->resetMatrix(); + view->translate(oldMatrix.dx(), oldMatrix.dy()); + view->scale(newScale, newScale); + + setGrid(); + } +} + +void MainWindow::zoomRect() +{ + scene->setMode(DiagramScene::Zoom); + view->setDragMode(QGraphicsView::RubberBandDrag); + setGrid(); +} + +void MainWindow::doZoomRect(QPointF p1,QPointF p2) +{ + view->fitInView(QRectF(p1,p2),Qt::KeepAspectRatio); + setGrid(); +} + +void MainWindow::zoomFit() +{ + scene->setCursorVisible(false); + view->fitInView(scene->itemsBoundingRect(),Qt::KeepAspectRatio); + scene->setCursorVisible(true); + setGrid(); +} + +void MainWindow::toggleGrid(bool grid) +{ + scene->setGridVisible(grid); + //view->repaint(); + QPointF topLeft = view->mapToScene( 0, 0 ); + QPointF bottomRight = view->mapToScene( view->viewport()->width() - 1, view->viewport()->height() - 1 ); + scene->invalidate(topLeft.x(),topLeft.y(),bottomRight.x()-topLeft.x(),bottomRight.y()-topLeft.y()); + //scene->update(); + //view->update(); + +} + +void MainWindow::setGrid() +{ + if(scene->isGridVisible()){ + QPointF topLeft = view->mapToScene( 0, 0 ); + QPointF bottomRight = view->mapToScene( view->viewport()->width() - 1, view->viewport()->height() - 1 ); + qreal width=bottomRight.x()-topLeft.x(); + qreal height=bottomRight.y()-topLeft.y(); + qreal zw=width; + std::cout << width << "/" << height << std::endl; + if(zw50) + { + k=k*2; + } + std::cout << k << std::endl; + scene->setGridScale(k); + scene->update(); + } +} + +void MainWindow::saveAs() +{ + QFileDialog::Options options; + options = 0; + QString selectedFilter; + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save Diagram as ..."), + ".qdiag", + tr("QDiagram (*.qdiag)"), + &selectedFilter, + options); + if (!fileName.isEmpty()){ + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)){ + QMessageBox::warning(this,tr("File operation error"),file.errorString()); + } + else + { + if(scene->save(&file)){ + myFileName=fileName; + } + file.close(); + if(file.error()){ + std::cerr << "Error: cannot write file " + << qPrintable(file.fileName()) + << qPrintable(file.errorString()) + << std::endl ; + } + } + } +} + +void MainWindow::save() +{ + if (!myFileName.isEmpty()){ + QFile file(myFileName); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)){ + QMessageBox::warning(this,tr("File operation error"),file.errorString()); + } + else + { + scene->save(&file); + } + } +} + +void MainWindow::load() +{ + QFileDialog::Options options; + options = 0; + QString selectedFilter; + QString fileName = QFileDialog::getOpenFileName(this, + tr("Save Diagram as ..."), + ".qdiag", + tr("QDiagram (*.qdiag)"), + &selectedFilter, + options); + if (!fileName.isEmpty()){ + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){ + QMessageBox::warning(this,tr("File operation error"),file.errorString()); + } + else + { + scene->clear(); + scene->load(&file); + myFileName=fileName; + } + + } +} diff --git a/plugins/qdiagram_plugin/mainwindow.h b/plugins/qdiagram_plugin/mainwindow.h new file mode 100644 index 000000000..2095bda54 --- /dev/null +++ b/plugins/qdiagram_plugin/mainwindow.h @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +#include "diagramitem.h" +#include "diagramdrawitem.h" +#include "diagrampathitem.h" + +class DiagramScene; + +QT_BEGIN_NAMESPACE +class QAction; +class QToolBox; +class QSpinBox; +class QComboBox; +class QFontComboBox; +class QButtonGroup; +class QLineEdit; +class QGraphicsTextItem; +class QFont; +class QToolButton; +class QAbstractButton; +class QGraphicsView; +QT_END_NAMESPACE + +//! [0] +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + +private slots: + void backgroundButtonGroupClicked(QAbstractButton *button); + void buttonGroupClicked(int id); + void deleteItem(); + void pointerGroupClicked(int id); + void bringToFront(); + void sendToBack(); + void rotateRight(); + void rotateLeft(); + void flipX(); + void flipY(); + void abort(); + void print(); + void exportImage(); + void copyItems(); + void groupItems(); + void ungroupItems(); + void itemInserted(DiagramItem *item); + void textInserted(QGraphicsTextItem *item); + void currentFontChanged(const QFont &font); + void fontSizeChanged(const QString &size); + void textColorChanged(); + void itemColorChanged(); + void lineColorChanged(); + void lineArrowChanged(); + void textButtonTriggered(); + void fillButtonTriggered(); + void lineButtonTriggered(); + void lineArrowButtonTriggered(); + void handleFontChange(); + void itemSelected(QGraphicsItem *item); + void about(); + void activateShortcuts(); + void deactivateShortcuts(); + void zoomIn(); + void zoomOut(); + void zoom(const qreal factor); + void zoomRect(); + void doZoomRect(QPointF p1,QPointF p2); + void zoomFit(); + void toggleGrid(bool grid); + void save(); + void saveAs(); + void load(); + void moveItems(); + +private: + void createToolBox(); + void createActions(); + void createMenus(); + void createToolbars(); + void setGrid(); + QWidget *createBackgroundCellWidget(const QString &text, + const QString &image); + QWidget *createCellWidget(const QString &text, + DiagramItem::DiagramType type); + QWidget *createCellWidget(const QString &text, + DiagramDrawItem::DiagramType type); + QMenu *createColorMenu(const char *slot, QColor defaultColor); + QIcon createColorToolButtonIcon(const QString &image, QColor color); + QIcon createColorIcon(QColor color); + + QMenu *createArrowMenu(const char *slot, const int def); + QIcon createArrowIcon(const int i); + + DiagramScene *scene; + QGraphicsView *view; + + QAction *exitAction; + QAction *addAction; + QAction *deleteAction; + + QAction *toFrontAction; + QAction *sendBackAction; + QAction *rotateRightAction; + QAction *rotateLeftAction; + QAction *flipXAction; + QAction *flipYAction; + QAction *copyAction; + QAction *moveAction; + QAction *groupAction; + QAction *ungroupAction; + QAction *aboutAction; + + QAction *zoomInAction; + QAction *zoomOutAction; + QAction *zoomAction; + QAction *zoomFitAction; + QAction *showGridAction; + + QAction *printAction; + QAction *exportAction; + + QShortcut *escShortcut; + + QMenu *fileMenu; + QMenu *viewMenu; + QMenu *itemMenu; + QMenu *aboutMenu; + + QToolBar *textToolBar; + QToolBar *editToolBar; + QToolBar *colorToolBar; + QToolBar *pointerToolbar; + QToolBar *zoomToolbar; + + QComboBox *itemColorCombo; + QComboBox *textColorCombo; + QComboBox *fontSizeCombo; + QFontComboBox *fontCombo; + + QToolBox *toolBox; + QButtonGroup *buttonGroup; + QButtonGroup *pointerTypeGroup; + QButtonGroup *backgroundButtonGroup; + QToolButton *fontColorToolButton; + QToolButton *fillColorToolButton; + QToolButton *lineColorToolButton; + QToolButton *linePointerButton; + QAction *boldAction; + QAction *underlineAction; + QAction *italicAction; + QAction *textAction; + QAction *fillAction; + QAction *lineAction; + QAction *arrowAction; + QAction *loadAction; + QAction *saveAction; + QAction *saveAsAction; + + QList listOfActions; + QList listOfShortcuts; + + bool myShowGrid; // Grid visible ? + qreal myGrid; // Grid distance (dx=dy) + + QString myFileName; // aktueller Filename + +}; +//! [0] + +#endif diff --git a/plugins/qdiagram_plugin/qdiagram.qrc b/plugins/qdiagram_plugin/qdiagram.qrc new file mode 100644 index 000000000..854e048ae --- /dev/null +++ b/plugins/qdiagram_plugin/qdiagram.qrc @@ -0,0 +1,53 @@ + + + images/background1.png + images/background2.png + images/background3.png + images/background4.png + images/bold.png + images/bringtofront.png + images/delete.png + images/floodfill.png + images/italic.png + images/lc_aligncenter.png + images/lc_aligndown.png + images/lc_alignmiddle.png + images/lc_alignup.png + images/lc_backward.png + images/lc_bold.png + images/lc_bringtofront.png + images/lc_copy.png + images/lc_cut.png + images/lc_fliphorizontal.png + images/lc_flipvertical.png + images/lc_forward.png + images/lc_grid.png + images/lc_griduse.png + images/lc_gridvisible.png + images/lc_group.png + images/lc_italic.png + images/lc_objectalign.png + images/lc_objectalignleft.png + images/lc_objectalignright.png + images/lc_open.png + images/lc_redo.png + images/lc_save.png + images/lc_saveas.png + images/lc_sendtoback.png + images/lc_toggleobjectrotatemode.png + images/lc_underline.png + images/lc_undo.png + images/lc_ungroup.png + images/lc_zoom.png + images/lc_zoomin.png + images/lc_zoomminus.png + images/lc_zoomoptimal.png + images/lc_zoompagewidth.png + images/linecolor.png + images/linepointer.png + images/pointer.png + images/sendtoback.png + images/textpointer.png + images/underline.png + + diff --git a/plugins/qdiagram_plugin/qdiagram_plugin.pro b/plugins/qdiagram_plugin/qdiagram_plugin.pro new file mode 100644 index 000000000..61c1790a8 --- /dev/null +++ b/plugins/qdiagram_plugin/qdiagram_plugin.pro @@ -0,0 +1,50 @@ +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin release + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(qdiagram_plugin) + +HEADERS += ../PluginInterface.h \ + DiagramPlugin.h +SOURCES += DiagramPlugin.cpp + +#=============================================================================== + + +HEADERS += diagrampathitem.h \ + diagramdrawitem.h \ + mainwindow.h \ + diagramitem.h \ + diagramscene.h \ + diagramtextitem.h +SOURCES += diagrampathitem.cpp \ + diagramdrawitem.cpp \ + mainwindow.cpp \ + diagramitem.cpp \ + diagramtextitem.cpp \ + diagramscene.cpp +RESOURCES = qdiagram.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/diagramscene +sources.files = $$SOURCES \ + $$HEADERS \ + $$RESOURCES \ + $$FORMS \ + diagramscene.pro \ + images +sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/diagramscene +INSTALLS += target \ + sources diff --git a/plugins/qsolocards_plugin/._.DS_Store b/plugins/qsolocards_plugin/._.DS_Store new file mode 100644 index 000000000..460d887a2 Binary files /dev/null and b/plugins/qsolocards_plugin/._.DS_Store differ diff --git a/plugins/qsolocards_plugin/._QSoloCards.icns b/plugins/qsolocards_plugin/._QSoloCards.icns new file mode 100644 index 000000000..f98f3396f Binary files /dev/null and b/plugins/qsolocards_plugin/._QSoloCards.icns differ diff --git a/plugins/qsolocards_plugin/About.cpp b/plugins/qsolocards_plugin/About.cpp new file mode 100644 index 000000000..4112ad3ee --- /dev/null +++ b/plugins/qsolocards_plugin/About.cpp @@ -0,0 +1,96 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "About.h" +#include +#include +#include +#include +#include +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +About::About(QWidget * pParent) + :QDialog(pParent) +{ + this->setWindowTitle(tr("About QSoloCards").trimmed()); + + // Layout the dialog a Vbox that will be the top level. And contain the HBox that has the icon and text + // and then the dialogButtonBox for the close button. + QVBoxLayout * pLayout=new QVBoxLayout; + + QHBoxLayout * pMainLayout=new QHBoxLayout; + + QLabel * pIconLabel=new QLabel(this); + + pIconLabel->setPixmap(QPixmap(":/images/sol128x128.png")); + + pMainLayout->addWidget(pIconLabel,0,Qt::AlignTop|Qt::AlignLeft); + + QLabel * pWordsLabel=new QLabel(this); + + pWordsLabel->setWordWrap(true); + + // set the text for the about box. The .pro file is setup to pass + // VER_MAJ, VER_MIN, VER_PAT as a param when the file is compiled + // So, version info is contained only in the .pro file and can be + // easily changed in one place. + pWordsLabel->setText(tr("

QSoloCards %1.%2.%3

" + "

A collection of Solitaire Games written in Qt.

" + "

" + "

" + "

Copyright 2009 Steve Moore

" + "

" + "

License: GPLv3

" + "

" + "

" + "

Graphics: Playing cards are a modified version of the anglo_bitmap cards from Gnome-Games' AisleRiot.

" + ).arg(QString::number(VER_MAJ)).arg(QString::number(VER_MIN)).arg(QString::number(VER_PAT))); + + connect(pWordsLabel,SIGNAL(linkActivated(QString)), + this,SLOT(slotLinkActivated(QString))); + + pMainLayout->addWidget(pWordsLabel,0,Qt::AlignTop|Qt::AlignHCenter); + + + pLayout->addLayout(pMainLayout,20); + + QDialogButtonBox * pButtonBox=new QDialogButtonBox(this); + + pButtonBox->addButton(QDialogButtonBox::Close); + + pLayout->addWidget(pButtonBox,1); + + connect(pButtonBox, SIGNAL(rejected()), this, SLOT(reject())); + + // don't allow resizing the window. + pLayout->setSizeConstraint(QLayout::SetFixedSize); + + this->setLayout(pLayout); +} +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +About::~About() +{ +} + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +void About::slotLinkActivated(const QString & link) +{ + emit showLink(link); +} diff --git a/plugins/qsolocards_plugin/About.h b/plugins/qsolocards_plugin/About.h new file mode 100644 index 000000000..39fce3eb1 --- /dev/null +++ b/plugins/qsolocards_plugin/About.h @@ -0,0 +1,34 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef ABOUT_H +#define ABOUT_H +#include + +class About: public QDialog +{ + Q_OBJECT +public: + About(QWidget * pParent); + ~About(); +public slots: + void slotLinkActivated(const QString & link); +signals: + void showLink(const QString & link); +}; +#endif // ABOUT_H diff --git a/plugins/qsolocards_plugin/CardAnimationLock.cpp b/plugins/qsolocards_plugin/CardAnimationLock.cpp new file mode 100644 index 000000000..80ecd7949 --- /dev/null +++ b/plugins/qsolocards_plugin/CardAnimationLock.cpp @@ -0,0 +1,66 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "CardAnimationLock.h" +#include "CardStack.h" + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +CardAnimationLock::~CardAnimationLock() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +CardAnimationLock & CardAnimationLock::getInst() +{ + static CardAnimationLock aniLock; + + return aniLock; +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void CardAnimationLock::lock() +{ + if (m_aniEnabled && !m_demoStarted) + { + CardStack::lockUserInteration(); + emit animationStarted(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void CardAnimationLock::unlock() +{ + if (m_aniEnabled && !m_demoStarted) + { + CardStack::lockUserInteration(false); + emit animationComplete(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +CardAnimationLock::CardAnimationLock() + :m_aniEnabled(true), + m_demoStarted(false) +{ +} + diff --git a/plugins/qsolocards_plugin/CardAnimationLock.h b/plugins/qsolocards_plugin/CardAnimationLock.h new file mode 100644 index 000000000..30ef47338 --- /dev/null +++ b/plugins/qsolocards_plugin/CardAnimationLock.h @@ -0,0 +1,57 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef CARDANIMATIONLOCK_H +#define CARDANIMATIONLOCK_H + +#include + +class CardAnimationLock:public QObject +{ + Q_OBJECT +public: + virtual ~CardAnimationLock(); + + static CardAnimationLock & getInst(); + + inline void setDemoMode(bool isDemo){m_demoStarted=isDemo;} + inline bool isDemoRunning()const{return m_demoStarted;} + + inline bool animationsEnabled()const{return m_aniEnabled;} + inline void enableAnimations(bool enabled){m_aniEnabled=enabled;} + + // The lock just sends a single not to allow user interaction, + // and calls the static lockUserInteraction function of CardStack. + // The signal is used by mainwindow to know when not to allow menu + // items to be clicked. + void lock(); + void unlock(); + +signals: + void animationStarted(); + void animationComplete(); + +protected: + CardAnimationLock(); + +private: + bool m_aniEnabled; + bool m_demoStarted; +}; + +#endif diff --git a/plugins/qsolocards_plugin/CardDeck.cpp b/plugins/qsolocards_plugin/CardDeck.cpp new file mode 100644 index 000000000..7281de1cf --- /dev/null +++ b/plugins/qsolocards_plugin/CardDeck.cpp @@ -0,0 +1,123 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "CardDeck.h" + +#include + + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +CardDeck::CardDeck(unsigned short numDecks) + :m_deckOfCards(), + m_shuffledCardVector(), + m_numDecks(numDecks) +{ + // This creates the default deck of cards that will be used + for (unsigned short i=0;ishuffle(); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +CardDeck::CardDeck(const PlayingCardVector & cardsForDeck, unsigned short numDecks) + :m_deckOfCards(), + m_shuffledCardVector(), + m_numDecks(numDecks) +{ + for (unsigned short i=0;im_deckOfCards.push_back(cardsForDeck[j]); + } + } + + this->shuffle(); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +CardDeck::~CardDeck() +{ +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Create a shuffled deck by generating a vector of playing cards. And then randomly generating an index +// into that vector. And then pull the card out of that vector and adding it to the end of another vector. +// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +void CardDeck::shuffle() +{ + PlayingCardVector cardVector; + + cardVector=this->m_deckOfCards; + + if (this->m_shuffledCardVector.size()>0) + { + this->m_shuffledCardVector.clear(); + } + + qsrand(QDateTime::currentDateTime().toTime_t()); + + + while(cardVector.size()>0) + { + unsigned int index=qrand()%cardVector.size(); + + // make sure our random number is not off the end of the vector + if (index>=cardVector.size()) + { + index=cardVector.size()-1; + } + + this->m_shuffledCardVector.push_back(cardVector[index]); + cardVector.erase(cardVector.begin()+index); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +PlayingCard CardDeck::next() +{ + // create an invalid card. + PlayingCard playingCard(PlayingCard::MaxSuit,PlayingCard::MaxCardIndex); + + // if we have any cards left get the first one and return it. + // then remove that card from the vector. + if (this->m_shuffledCardVector.size()>0) + { + playingCard=this->m_shuffledCardVector[0]; + this->m_shuffledCardVector.erase(this->m_shuffledCardVector.begin()); + } + + return playingCard; +} diff --git a/plugins/qsolocards_plugin/CardDeck.h b/plugins/qsolocards_plugin/CardDeck.h new file mode 100644 index 000000000..47de6992d --- /dev/null +++ b/plugins/qsolocards_plugin/CardDeck.h @@ -0,0 +1,56 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef CARDDECK_H +#define CARDDECK_H + +#include + +#include "PlayingCard.h" + +typedef std::vector PlayingCardVector; + +class CardDeck +{ + public: + // by default we just want to include one complete deck. + CardDeck(unsigned short numDecks=1); + + // this constructor adds a little flexibility. So, that a deck of only certain cards + // can be built easily. + CardDeck(const PlayingCardVector & cardsForDeck, unsigned short numDecks=1); + ~CardDeck(); + + // will clear any remaining cards in the shuffled deck and create a new shuffled deck + // this function is automatically called by the constructor. + void shuffle(); + + inline bool isEmpty() const {return m_shuffledCardVector.empty();} + + // get the next card in the shuffled deck. + PlayingCard next(); + + private: + PlayingCardVector m_deckOfCards; + PlayingCardVector m_shuffledCardVector; + + unsigned short m_numDecks; +}; + + +#endif // CARDDECK_H diff --git a/plugins/qsolocards_plugin/CardMoveRecord.cpp b/plugins/qsolocards_plugin/CardMoveRecord.cpp new file mode 100644 index 000000000..0fc433bc3 --- /dev/null +++ b/plugins/qsolocards_plugin/CardMoveRecord.cpp @@ -0,0 +1,68 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "CardMoveRecord.h" + + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +CardMoveRecordItem::CardMoveRecordItem(const std::string & stackName, + int flipIndex) + :m_moveType(CardMoveRecordItem::FlipCard), + m_cardVector(), + m_flipIndex(flipIndex), + m_stackName(stackName) +{ +} + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +CardMoveRecordItem::CardMoveRecordItem(const std::string & stackName, + MoveType m_type, + const PlayingCardVector & cardVector) + :m_moveType(m_type), + m_cardVector(cardVector), + m_flipIndex(-1), + m_stackName(stackName) +{ +} + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +CardMoveRecordItem::CardMoveRecordItem(const CardMoveRecordItem & rh) +{ + *this=rh; +} + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +CardMoveRecordItem::~CardMoveRecordItem() +{ +} + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +CardMoveRecordItem & CardMoveRecordItem::operator=(const CardMoveRecordItem & rh) +{ + m_moveType=rh.moveType(); + m_cardVector=rh.cardVector(); + m_flipIndex=rh.flipIndex(); + m_stackName=rh.stackName(); + + return *this; +} diff --git a/plugins/qsolocards_plugin/CardMoveRecord.h b/plugins/qsolocards_plugin/CardMoveRecord.h new file mode 100644 index 000000000..2e15f372b --- /dev/null +++ b/plugins/qsolocards_plugin/CardMoveRecord.h @@ -0,0 +1,62 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef CARDMOVERECORD_H +#define CARDMOVERECORD_H + +#include "CardDeck.h" +#include +#include + +class CardMoveRecordItem +{ + public: + enum MoveType + { + AddCards=0, + RemoveCards=1, + FlipCard=2 + }; + + CardMoveRecordItem(const std::string & stackName, + int flipIndex=-1); // Case where we are just flipping a card + CardMoveRecordItem(const std::string & stackName, + MoveType m_type, + const PlayingCardVector & cardVector); // case where we are adding or removing cards + CardMoveRecordItem(const CardMoveRecordItem & rh); + + virtual ~CardMoveRecordItem(); + + CardMoveRecordItem & operator=(const CardMoveRecordItem & rh); + + inline MoveType moveType() const {return m_moveType;} + inline const PlayingCardVector & cardVector() const {return m_cardVector;} + inline int flipIndex() const {return m_flipIndex;} + inline const std::string & stackName() const{return m_stackName;} + + private: + MoveType m_moveType; + PlayingCardVector m_cardVector; + int m_flipIndex; + std::string m_stackName; +}; + +typedef std::list CardMoveRecord; + + +#endif // CARDMOVERECORD_H diff --git a/plugins/qsolocards_plugin/CardPixmaps.cpp b/plugins/qsolocards_plugin/CardPixmaps.cpp new file mode 100644 index 000000000..95090de82 --- /dev/null +++ b/plugins/qsolocards_plugin/CardPixmaps.cpp @@ -0,0 +1,193 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "CardPixmaps.h" +#include +#include + +const qreal CardPixmaps::CardWidthToHeight=.66; +const QString CardPixmaps::EmptyStackName("empty"); +const QString CardPixmaps::EmptyStackRedealName("emtpy_redeal"); +const QString CardPixmaps::CardBackName("back"); +const QString CardPixmaps::TransparentNoCard("transparent"); + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +CardPixmaps::~CardPixmaps() +{ + delete m_pSvgRendCard; +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +CardPixmaps & CardPixmaps::getInst() +{ + static CardPixmaps cardPixmaps; + + return cardPixmaps; +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardPixmaps::setCardWidth(unsigned int width) +{ + m_cardSize.setWidth(width); + m_cardSize.setHeight(width/CardWidthToHeight); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardPixmaps::setCardHeight(unsigned int height) +{ + m_cardSize.setHeight(height); + m_cardSize.setWidth(height*CardWidthToHeight); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +CardPixmaps::CardPixmaps() + :m_pSvgRendCard(new QSvgRenderer(QString(":/images/anglo_bitmap.svg"))), + m_pixmapMap(), + m_cardSize(0,0) +{ +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +const QPixmap & CardPixmaps::getCardPixmap(const QString & imageName,bool highlighted) +{ + QString fullImageName(""); + + if (highlighted) + { + fullImageName+="hl_"; + } + fullImageName+=imageName; + + CardPixmapMap::iterator it=m_pixmapMap.find(fullImageName.toStdString()); + + if (m_pixmapMap.end()!=it) + { + return it->second; + } + + QPainter painter; + + QPixmap dummyPix(m_cardSize); + + dummyPix.fill(Qt::transparent); + + m_pixmapMap[fullImageName.toStdString()]=dummyPix; + painter.begin(&m_pixmapMap[fullImageName.toStdString()]); + if (imageName==EmptyStackName || imageName==EmptyStackRedealName) + { + drawEmptyStack(painter,highlighted,imageName==EmptyStackRedealName); + } + else if (imageName==TransparentNoCard) + { + } + else if (highlighted) + { + drawHighlightedCard(painter,imageName); + } + else + { + QRect pixRect(QPoint(0,0),m_cardSize); + + m_pSvgRendCard->render(&painter,imageName,pixRect); + } + + painter.end(); + + return m_pixmapMap[fullImageName.toStdString()]; +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardPixmaps::drawEmptyStack(QPainter & painter,bool highlighted,bool redealCircle) +{ + QPoint topLeft(0,0); + QPen pen; + + + pen.setColor(QColor("#006520")); + + pen.setWidth(3); + painter.setPen(pen); + + + QRect rect(topLeft,m_cardSize); + + painter.setRenderHint(QPainter::Antialiasing,true); + + + if (redealCircle) + { + QPoint ellipseCenter(rect.left()+rect.width()/2, + rect.top()+rect.height()/2); + + pen.setWidth(10); + painter.setBrush(QColor("#006520")); + painter.drawEllipse(ellipseCenter, + rect.width()/3,rect.width()/3); + } + + painter.setBrush(Qt::transparent); + + // draw the highlight rect if necessary. + if (highlighted) + { + painter.setBrush(QBrush(QColor("#806000"),Qt::Dense4Pattern)); + } + + painter.drawRoundedRect(rect.adjusted(1,1,-1,-1),6.0,6.0); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardPixmaps::drawHighlightedCard(QPainter & painter,const QString & imageName) +{ + // for the highlighted case we are going to manipulate the original + // image and change the background of the card to a yellowish color + // to highlight it. + + // A QImage is necessary in Format_ARGB32_Premultiplied or Format_ARGB32 + // is required to use the composite modes. So, draw the pixmap on the + // QImage. And then render the result in our pixmap. + + QRect pixRect(QPoint(0,0),m_cardSize); + + QImage image(m_cardSize,QImage::Format_ARGB32_Premultiplied); + + image.fill(Qt::transparent); + + QPainter imagePainter; + + imagePainter.begin(&image); + + imagePainter.setPen(Qt::NoPen); + + imagePainter.setBrush(QColor("#ffff90")); + imagePainter.drawPixmap(QPoint(0,0),getCardPixmap(imageName)); + + imagePainter.setCompositionMode(QPainter::CompositionMode_Darken); + imagePainter.drawRoundedRect(pixRect.adjusted(0,0,-1,-1),4.0,4.0); + + imagePainter.end(); + painter.drawImage(QPoint(0,0),image); +} diff --git a/plugins/qsolocards_plugin/CardPixmaps.h b/plugins/qsolocards_plugin/CardPixmaps.h new file mode 100644 index 000000000..47bce4f67 --- /dev/null +++ b/plugins/qsolocards_plugin/CardPixmaps.h @@ -0,0 +1,93 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef CARDPIXMAPS_H +#define CARDPIXMAPS_H + +#include "PlayingCard.h" +#include +#include +#include +#include + +typedef std::map CardPixmapMap; + + +class CardPixmaps +{ +public: + static const qreal CardWidthToHeight; // This is the percentage of the height to the width + // that is used to render a card. + + static const QString EmptyStackName; + static const QString EmptyStackRedealName; + static const QString CardBackName; + static const QString TransparentNoCard; + + ~CardPixmaps(); + + static CardPixmaps & getInst(); + + + void setCardWidth(unsigned int width); + void setCardHeight(unsigned int height); + + inline const QSize & getCardSize() {return m_cardSize;} + + inline void clearPixmapCache(){m_pixmapMap.clear();} + + // functions to make it easier to get card pixmaps. + const QPixmap & getCardPixmap(const PlayingCard & card,bool highlighted=false) + {return getCardPixmap(card.asString(),highlighted);} + + const QPixmap & getCardBackPixmap(bool highlighted=false) + {return getCardPixmap(CardBackName,highlighted);} + + const QPixmap & getTransparentPixmap() + {return getCardPixmap(TransparentNoCard);} + + // the redeal circle is just a circle in the middle of the empty stack that indicates that + // you can d-click on the stack to recycle the cards. Used in games like Klondike where + // can go through the flip stack multiple times + const QPixmap & getCardNonePixmap(bool highlighted=false,bool redealCircle=false) + {return getCardPixmap(redealCircle?EmptyStackRedealName:EmptyStackName,highlighted);} + + +protected: + CardPixmaps(); + +private: + const QPixmap & getCardPixmap(const QString & imageName, bool highlighted=false); + void drawEmptyStack(QPainter & painter,bool highlighted,bool redealCircle); + void drawHighlightedCard(QPainter & painter,const QString & imageName); + + + QSvgRenderer * m_pSvgRendCard; // the svg render will be created the first time + // it is needed. It has to be done after Qt is initialized. + // And we just want to create it once. Loading it is fairly + // expensive. + CardPixmapMap m_pixmapMap; // this is a map of cards that is built as a card is needed. + // It will also contain the card back. And highlighted + // versions of cards. + QSize m_cardSize; // this is the card size that is used for every card + // that is drawn. The height of a card is determined + // from the width. So, the value is set by calling + // setCardWidth. +}; + +#endif diff --git a/plugins/qsolocards_plugin/CardStack.cpp b/plugins/qsolocards_plugin/CardStack.cpp new file mode 100644 index 000000000..0e4e36325 --- /dev/null +++ b/plugins/qsolocards_plugin/CardStack.cpp @@ -0,0 +1,857 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "CardStack.h" +#include +#include +#include +#include +#include +#include +#include "CardPixmaps.h" +#include "CardAnimationLock.h" + +#include + +CardStackMap CardStack::m_cardStackMap; +bool CardStack::m_lockUserInteraction=false; + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +CardStack::CardStack() + :QObject(),QGraphicsPixmapItem(), + m_hintHighlightIndex(-1), + m_stackName(), + m_cardVector(), + m_highlighted(false), + m_showRedealCircle(false), + m_autoFaceUp(false), + m_mouseMoved(false), + m_dragStartPos(0,0), + m_flipAni(), + m_dragStack(this) +{ + // set the name of this stack and add it to the map of stacks. + m_stackName=QString::number((qlonglong)this); + m_cardStackMap[this->stackName()]=this; + + // accept drops and mouse hover events + this->setAcceptDrops(true); + this->setAcceptHoverEvents(true); + + this->setZValue(1); + + this->setCursor(Qt::PointingHandCursor); + this->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + + // call update stack to set the initial view of the stack as empty. + this->updateStack(); + + + this->connect(&m_flipAni,SIGNAL(flipComplete(CardStack *)), + this,SLOT(slotFlipComplete(CardStack *))); + + this->connect(&m_dragStack,SIGNAL(cardsMoved(const CardMoveRecord &)), + this,SLOT(slotDragCardsMoved(const CardMoveRecord &))); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +CardStack::~CardStack() +{ + // remove the pointer from the map of stacks to the class. + m_cardStackMap.erase(this->stackName()); +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +bool CardStack::allCardsFaceUp()const +{ + bool rc=true; + unsigned int i; + + for(i=0;im_cardVector.size();i++) + { + if (!this->m_cardVector[i].isFaceUp()) + { + rc=false; + break; + } + } + + return rc; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +bool CardStack::cardsAscendingTopToBottom()const +{ + bool rc=true; + const PlayingCardVector & cardVector=this->getCardVector(); + int i; + + // see if the cards are in descending order from + // index 0 to n. + for (i=cardVector.size()-1;i>0;i--) + { + if (cardVector[i]>cardVector[i-1]) + { + rc=false; + break; + } + } + + return rc; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +bool CardStack::cardsDecendingTopToBottom()const +{ + bool rc=true; + const PlayingCardVector & cardVector=this->getCardVector(); + int i; + + // see if the cards are in descending order from + // index 0 to n. + for (i=cardVector.size()-1;i>0;i--) + { + if (cardVector[i]m_cardVector.size()>0 && faceUp!=this->m_cardVector[this->m_cardVector.size()-1].isFaceUp()) + { + flipCard(-1); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +bool CardStack::flipCard(int index,bool aniIfEnabled) +{ + bool rc=false; + if (this->m_cardVector.size()>0) + { + // if index is less than 0 assume it is the last card. + if (index<0) + { + index=this->m_cardVector.size()-1; + } + + if (index<(int)this->m_cardVector.size()) + { + if (aniIfEnabled) + { + m_flipAni.flipCard(this); + } + this->m_cardVector[index].setFaceUp(!this->m_cardVector[index].isFaceUp()); + this->updateStack(); + rc=true; + } + } + + return rc; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +bool CardStack::flipCard(int index,CardMoveRecord & moveRecord,bool aniIfEnabled) +{ + bool rc=flipCard(index,aniIfEnabled); + if (rc) + { + // if index is less than 0 assume it is the last card. + if (index<0) + { + index=this->m_cardVector.size()-1; + } + + moveRecord.push_back(CardMoveRecordItem(this->stackName(),index)); + } + + return rc; +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::addCard(const PlayingCard & newCard) +{ + m_cardVector.push_back(newCard); + + if (isFlipAniRunning()) + { + m_flipAni.stopAni(); + this->updateStack(); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::addCards(const PlayingCardVector & cardVector) +{ + for(unsigned int i=0;iupdateStack(); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::addCard(const PlayingCard & newCard,CardMoveRecord & moveRecord,bool justUpdateRec) +{ + if (!justUpdateRec) + { + this->addCard(newCard); + } + + PlayingCardVector cardVector; + cardVector.push_back(newCard); + moveRecord.push_back(CardMoveRecordItem(this->stackName(),CardMoveRecordItem::AddCards,cardVector)); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::addCards(const PlayingCardVector & cardVector,CardMoveRecord & moveRecord,bool justUpdateRec) +{ + if (!justUpdateRec) + { + this->addCards(cardVector); + } + moveRecord.push_back(CardMoveRecordItem(this->stackName(),CardMoveRecordItem::AddCards,cardVector)); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +PlayingCard CardStack::removeTopCard() +{ + PlayingCard card(PlayingCard::MaxSuit,PlayingCard::MaxCardIndex); + + if (!this->m_cardVector.empty()) + { + card=m_cardVector.back(); + this->m_cardVector.pop_back(); + } + return card; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +PlayingCard CardStack::removeTopCard(CardMoveRecord & moveRecord) +{ + PlayingCard card(PlayingCard::MaxSuit,PlayingCard::MaxCardIndex); + card=this->removeTopCard(); + + // if the card is valid update the moveRecord + if (card.isValid()) + { + PlayingCardVector cardVector; + cardVector.push_back(card); + + moveRecord.push_back(CardMoveRecordItem(this->stackName(),CardMoveRecordItem::RemoveCards,cardVector)); + } + + return card; +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +bool CardStack::removeCardsStartingAt(unsigned int index,PlayingCardVector & removedCards) +{ + bool rc=false; + + if (indexm_cardVector.size()) + { + rc=true; + + unsigned int i; + + removedCards.clear(); + + for(i=index;im_cardVector.size();i++) + { + removedCards.push_back(this->m_cardVector[i]); + } + + while(m_cardVector.size()>index) + { + this->m_cardVector.pop_back(); + } + } + + return rc; +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +bool CardStack::removeCardsStartingAt(unsigned int index, + PlayingCardVector & removedCards, + CardMoveRecord & moveRecord, + bool justUpdateRec) +{ + bool rc=false; + + + if (!justUpdateRec) + { + rc=this->removeCardsStartingAt(index,removedCards); + } + else if (indexm_cardVector.size()) + { + rc=true; + + unsigned int i; + + removedCards.clear(); + + for(i=index;im_cardVector.size();i++) + { + removedCards.push_back(this->m_cardVector[i]); + } + } + + if (rc) + { + // ok now add the move records for removal of the cards from this stack + // it will be a remove and then a flip of the card before if it is face down + moveRecord.push_back(CardMoveRecordItem(this->stackName(),CardMoveRecordItem::RemoveCards,removedCards)); + + // also if we are in autoflip mode add that to the flip record. + if (0!=index && this->m_autoFaceUp && !this->m_cardVector[index-1].isFaceUp()) + { + moveRecord.push_back(CardMoveRecordItem(this->stackName(),index-1)); + } + } + + return rc; +} + + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardStack::removeAllCards() +{ + // stop any flip animation we have going. + m_flipAni.stopAni(); + + m_cardVector.clear(); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +bool CardStack::getMovableCards(PlayingCardVector & cardVector, + unsigned int & index) const +{ + bool rc=false; + + if (this->m_cardVector.size()>0) + { + int moveIndex=-1; + // ok let's go up the stack and find the last card that we can move + for (int i=this->m_cardVector.size()-1;i>=0;i--) + { + if (this->canMoveCard((unsigned int)i)) + { + moveIndex=i; + } + else + { + break; + } + } + + // did we get an index of a card. + if (moveIndex>=0) + { + rc=true; + + + for(unsigned int j=(unsigned int)moveIndex;jm_cardVector.size();j++) + { + cardVector.push_back(this->m_cardVector[j]); + } + + index=(unsigned int)moveIndex; + } + } + + return rc; +} + + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardStack::updateStack() +{ + QPixmap * pPixmap=NULL; + + if (this->isFlipAniRunning()) + { + PlayingCardVector cardVector(this->m_cardVector); + + // the stack should have at least one card ie the one being flipped + // but make sure. + if (this->m_cardVector.size()>0) + { + cardVector.pop_back(); + } + + pPixmap=getStackPixmap(cardVector,m_highlighted,m_hintHighlightIndex); + } + else + { + pPixmap=getStackPixmap(this->m_cardVector,m_highlighted,m_hintHighlightIndex); + } + + if (NULL!=pPixmap) + { + this->setPixmap(*pPixmap); + delete pPixmap; + } +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +QPixmap * CardStack::getStackPixmap(const PlayingCardVector & cardVector, + bool highlighted, + int hintHighlightIndex) +{ + bool hl=((hintHighlightIndex>=0 || + (HintHighlightNoCards==hintHighlightIndex && 0==cardVector.size()))|| + highlighted); + + QPixmap * pPixmap=NULL; + + // if the stack is not empty either show a card or the card back + if (cardVector.size()>0) + { + PlayingCard card(cardVector[cardVector.size()-1]); + + + if (card.isFaceUp()) + { + pPixmap=new QPixmap(CardPixmaps::getInst().getCardPixmap(card,hl)); + } + else + { + pPixmap=new QPixmap(CardPixmaps::getInst().getCardBackPixmap(hl)); + } + } + // if the stack is empty show the empty pixmap. + else + { + pPixmap=new QPixmap(CardPixmaps::getInst().getCardNonePixmap(hl,this->m_showRedealCircle)); + } + + return pPixmap; +} + + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardStack::updateAllStacks() +{ + CardStackMap::iterator it; + + CardPixmaps::getInst().clearPixmapCache(); + + for (it=m_cardStackMap.begin();it!=m_cardStackMap.end();it++) + { + it->second->updateStack(); + } +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardStack::clearAllStacks() +{ + CardStackMap::iterator it; + + for (it=m_cardStackMap.begin();it!=m_cardStackMap.end();it++) + { + it->second->removeAllCards(); + } +} + + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +CardStack * CardStack::getStackByName(const std::string & stackName) +{ + CardStack * pStack=NULL; + + CardStackMap::iterator it=m_cardStackMap.find(stackName); + + if (m_cardStackMap.end()!=it) + { + pStack=it->second; + } + + return pStack; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +bool CardStack::isCardStack(QGraphicsItem * pGraphicsItem) +{ + CardStack * pCardStack=getStackByName(QString::number((qlonglong)pGraphicsItem).toStdString()); + bool rc=false; + + if (NULL!=pCardStack) + { + rc=true; + } + + return true; +} + + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardStack::processCardMoveRecord(ProcessCardMoveRecordType type, + CardMoveRecord moveRecord) +{ + while(!moveRecord.empty()) + { + CardMoveRecordItem currItem(((CardStack::RedoMove==type)?moveRecord.front():moveRecord.back())); + CardStack * pStack=CardStack::m_cardStackMap[currItem.stackName()]; + const PlayingCardVector & cardVector=currItem.cardVector(); + unsigned int i; + + CardMoveRecordItem::MoveType moveType=currItem.moveType(); + + // for undo we are actually undoing something that was done + // so we need to AddCards if they were removed or RemoveCards + // if they were added + if (CardStack::UndoMove==type) + { + if (CardMoveRecordItem::RemoveCards==moveType) + { + moveType=CardMoveRecordItem::AddCards; + } + else if (CardMoveRecordItem::AddCards==moveType) + { + moveType=CardMoveRecordItem::RemoveCards; + } + } + + switch(moveType) + { + // remove cards to a stack + case CardMoveRecordItem::RemoveCards: + { + for (i=0;iremoveTopCard(); + } + pStack->updateStack(); + } + break; + // add cards to a stack + case CardMoveRecordItem::AddCards: + { + pStack->addCards(cardVector); + pStack->updateStack(); + } + break; + + // for this case we are just going to flip the card over + case CardMoveRecordItem::FlipCard: + { + // in this case we just want to flip the last card + if (pStack->m_cardVector.size()>0) + { + unsigned int flipIndex=0; + bool isValid=false; + if (currItem.flipIndex()<0) + { + flipIndex=pStack->m_cardVector.size()-1; + isValid=true; + } + else if (currItem.flipIndex()<(int)(pStack->m_cardVector.size())) + { + flipIndex=(unsigned int)currItem.flipIndex(); + isValid=true; + } + + if (isValid) + { + pStack->m_cardVector[flipIndex].setFaceUp(!pStack->m_cardVector[flipIndex].isFaceUp()); + pStack->updateStack(); + } + } + } + break; + }; + + if (CardStack::RedoMove==type) + { + moveRecord.pop_front(); + } + else + { + moveRecord.pop_back(); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void CardStack::showHint(CardStack * pSrc, + unsigned int srcCardIndex, + CardStack * pDst) +{ + if (NULL!=pSrc && NULL!=pDst) + { + pSrc->slotHintHighlight(srcCardIndex); + pDst->slotDelayedHintHighlight(); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::slotDelayedHintHighlight() +{ + QTimer::singleShot(1000,this,SLOT(slotHintHighlight())); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::slotHintHighlight(int index) +{ + // if the index is less than 0 then the last card should be highlighted + // or the card pad if no cards are in the stack. + if (index<0) + { + this->m_hintHighlightIndex=HintHighlightNoCards; + + if (this->m_cardVector.size()>0) + { + this->m_hintHighlightIndex=this->m_cardVector.size()-1; + } + } + else if (index<(int)this->m_cardVector.size()) + { + this->m_hintHighlightIndex=index; + } + + this->updateStack(); + + QTimer::singleShot(1000,this,SLOT(slotHintHighlightComplete())); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::slotHintHighlightComplete() +{ + this->m_hintHighlightIndex=-1; + this->updateStack(); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::slotFlipComplete(CardStack * pSrc) +{ + Q_UNUSED(pSrc); + + this->updateStack(); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::slotDragCardsMoved(const CardMoveRecord & initRecord) +{ + CardMoveRecord moveRecord(initRecord); + + // if we are in autotop card up flip the top card. and emit a signal + // that we moved the cards. + if (!this->isEmpty() && this->isAutoTopCardUp()) + { + int lastIndex=this->m_cardVector.size()-1; + + if (!this->m_cardVector[lastIndex].isFaceUp()) + { + this->flipCard(lastIndex,moveRecord); + } + } + + emit cardsMovedByDragDrop(moveRecord); +} + + +////////////////////////////////////////////////////////////////////////// +// for this case when all cards are directly stacked on top of each other +// if there are cards in the stack we will always just return the last card. +////////////////////////////////////////////////////////////////////////// +bool CardStack::getCardIndex(const QPointF & pos,unsigned int & index) +{ + Q_UNUSED(pos); + + bool rc=false; + + if (this->m_cardVector.size()>0) + { + index=this->m_cardVector.size()-1; + rc=true; + } + + return rc; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_lockUserInteraction || this->isFlipAniRunning() || CardAnimationLock::getInst().isDemoRunning()) + { + QGraphicsPixmapItem::mousePressEvent(event); + return; + } + + + this->m_mouseMoved=false; + this->m_dragStartPos=event->pos(); + +} +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_lockUserInteraction || this->isFlipAniRunning() || CardAnimationLock::getInst().isDemoRunning()) + { + QGraphicsPixmapItem::mouseReleaseEvent(event); + return; + } + + if (!m_mouseMoved) + { + + unsigned int index; + + if (this->isEmpty()) + { + emit padClicked(this); + } + else if (this->getCardIndex(event->pos(),index)) + { + if (this->canMoveCard(index)) + { + PlayingCardVector moveCards; + CardMoveRecord moveRecord; + + // create a move record and a vector containing the cards + // but don't remove them. + if (CardStack::removeCardsStartingAt(index,moveCards, + moveRecord,true)) + { + emit movableCardsClicked(this,moveCards,moveRecord); + } + } + else + { + emit cardClicked(this,index); + } + } + + } + else if (m_dragStack.cardDragStarted()) + { + m_dragStack.mouseReleaseEvent(event); + } +} +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_lockUserInteraction || this->isFlipAniRunning() || CardAnimationLock::getInst().isDemoRunning()) + { + QGraphicsPixmapItem::mouseMoveEvent(event); + return; + } + + + QPointF posDiff=(event->pos()-this->m_dragStartPos); + if ( (qAbs(posDiff.x()) + qAbs((int)posDiff.y()))< QApplication::startDragDistance()) + { + return; + } + + m_mouseMoved=true; + + if (!m_dragStack.cardDragStarted()) + { + unsigned int index=0; + bool haveCardIndex=this->getCardIndex(event->pos(),index); + + if (haveCardIndex && this->canMoveCard(index)) + { + unsigned int i; + PlayingCardVector dragCardVector; + + for (i=index;im_cardVector.size();i++) + { + dragCardVector.push_back(this->m_cardVector[i]); + } + + m_dragStack.startCardMove(event->scenePos(),index,dragCardVector); + } + } + else + { + m_dragStack.mouseMoveEvent(event); + } +} + + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void CardStack::hoverMoveEvent(QGraphicsSceneHoverEvent * event) +{ + unsigned int index; + + if (this->getCardIndex(event->pos(),index) && + this->canMoveCard(index)) + { + this->setCursor(Qt::OpenHandCursor); + } + else + { + this->setCursor(Qt::PointingHandCursor); + } + + QGraphicsPixmapItem::hoverMoveEvent(event); +} diff --git a/plugins/qsolocards_plugin/CardStack.h b/plugins/qsolocards_plugin/CardStack.h new file mode 100644 index 000000000..6e07cdf63 --- /dev/null +++ b/plugins/qsolocards_plugin/CardStack.h @@ -0,0 +1,238 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef CARDSTACK_H +#define CARDSTACK_H + +#include +#include + +#include "CardMoveRecord.h" + +#include "FlipAnimation.h" +#include "DragCardStack.h" + +#include +#include + +class CardStack; + +typedef std::map CardStackMap; + + +class CardStack: public QObject,public QGraphicsPixmapItem +{ + Q_OBJECT +public: + enum ProcessCardMoveRecordType + { + UndoMove=0, + RedoMove=1 + }; + + enum + { + HintHighlightNoCards=-2 + }; + + CardStack(); + virtual ~CardStack(); + + inline const std::string stackName()const{return m_stackName.toStdString();} + + inline bool isFlipAniRunning()const {return m_flipAni.isAniRunning();} + + + bool allCardsFaceUp()const; + + // top is in this case the last card in the stack. bottom is index 0 + bool cardsAscendingTopToBottom()const; + bool cardsDecendingTopToBottom()const; + + void setTopCardUp(bool faceUp=true); + + bool flipCard(int index,bool aniIfEnabled=true); + bool flipCard(int index,CardMoveRecord & moveRecord,bool aniIfEnabled=true); + + inline void setAutoTopCardUp(bool autoFaceUp=true){this->m_autoFaceUp=autoFaceUp;} + inline bool isAutoTopCardUp()const {return m_autoFaceUp;} + + + inline bool isHighlighted() const {return m_highlighted;} + inline void setHighlighted(bool state=true){m_highlighted=state;} + + inline int hintHighlightIndex() const {return m_hintHighlightIndex;} + + + inline bool showRedealCircle(){return m_showRedealCircle;} + inline void setShowRedealCircle(bool state=true){m_showRedealCircle=state;} + + void addCard(const PlayingCard & newCard); + void addCards(const PlayingCardVector & cardVector); + + void addCard(const PlayingCard & newCard,CardMoveRecord & moveRecord,bool justUpdateRec=false); + void addCards(const PlayingCardVector & cardVector,CardMoveRecord & moveRecord,bool justUpdateRec=false); + + + // pull the top card off of the stack + PlayingCard removeTopCard(); + PlayingCard removeTopCard(CardMoveRecord & moveRecord); + + // the cardVector contains the cards that were removed if the index is valid. + bool removeCardsStartingAt(unsigned int index,PlayingCardVector & removedCards); + bool removeCardsStartingAt(unsigned int index,PlayingCardVector & removedCards, + CardMoveRecord & moveRecord,bool justUpdateRec=false); + + void removeAllCards(); + + inline bool isEmpty() const {return m_cardVector.empty();} + + const PlayingCardVector & getCardVector()const{return m_cardVector;} + + virtual bool canAddCards(const PlayingCardVector &){return false;} + + // this function will return the cards at the end of the stack that can be moved. + // the function canMoveCards that can be overridden by subclasses controls the + // cards that can be moved. This function can also be overridden if something other + // than the default of just cards at the end of the stack is desired. + // + // the cards that can be moved will be added to the end of the card vector passed in + // the start index of the cards is also set if the function returns true + // the function returns true if it has cards that can be moved or false if it has none. + + // this function has been added to aid in creating hints for moving cards + virtual bool getMovableCards(PlayingCardVector &, unsigned int & index) const; + + // this function gets the point in the scene that a card would be added to this stack. + inline virtual QPointF getGlobalCardAddPt() const {return mapToScene(QPointF(0,0));}; + inline virtual QPointF getGlobalLastCardPt() const {return mapToScene(QPointF(0,0));}; + inline virtual QPointF getGlobalCardPt(int index) const {Q_UNUSED(index);return mapToScene(QPointF(0,0));}; + + // this function will update the bounding rectangle for the cards. And update the + // pixmap for the stack. The default implementation implementation just calls + // getStackPixmap. Subclasses may want to override this version to record bounding + // rectangles for cards and then call the base class. + virtual void updateStack(); + + // this function returns a pointer to a pixmap of the stack. The pixmap is the responsiblity + // of the caller to free. This function can be overridden in subclasses to create + // different look for the stack when drawn or cards from it are dragged to a different + // stack. + virtual QPixmap * getStackPixmap(const PlayingCardVector & cardVector, + bool highlighted=false, + int hintHighlightIndex=-1); + + // override in subclasses for scoring per stack if desired. + virtual int score() const{return 0;} + + /////////////////////////////////////////////////////////////////////////////// + // public static functions + /////////////////////////////////////////////////////////////////////////////// + static void updateAllStacks(); + + static void clearAllStacks(); + + static inline void lockUserInteration(bool lock=true){m_lockUserInteraction=lock;} + static inline bool isUserInteractionLocked() {return m_lockUserInteraction;} + + static CardStack * getStackByName(const std::string & stackName); + + static bool isCardStack(QGraphicsItem *); + + static void processCardMoveRecord(ProcessCardMoveRecordType type, + CardMoveRecord moveRecord); + + // this is a helper function that will show a move hint by highlighting the src widget starting with the + // srcCardIndex in the stack for one second. And then highlighting the last card in the dest stack for + // one second. + static void showHint(CardStack * pSrcWidget,unsigned int srcCardIndex,CardStack * pDstWidget); + +public slots: + // the slotDelayedHintHighlight() allows you to call slotHintHighlight() for the src stack + // and slotDelayedHintHighlight() for the destination stack at the same time. + void slotDelayedHintHighlight(); // show a hint highlight delayed + void slotHintHighlight(int index=-1); // show the highlight hint immediately it will timeout in one second + void slotHintHighlightComplete(); + + void slotFlipComplete(CardStack * pSrc); + + void slotDragCardsMoved(const CardMoveRecord & moveRecord); + +signals: + // when a card is clicked this signal is emitted + void cardClicked(CardStack * pCardStackWidget,unsigned int index); + // This signal is emitted when there are no cards + // in the stack and the pad area where the first card would be is clicked + void padClicked(CardStack * pCardStackWidget); + + // this signal indicates that cards where clicked, but they are also movable + // and it includes a move record of what would happen if the card was moved. This + // can be used to make the move by calling processCardMoveRecord. If the move is accepted + // the add move can be added to the move record. And then processCardMoveRecord can be + // called to perform the move. The index is the index of the card that was clicked. + void movableCardsClicked(CardStack * pCardStack, + const PlayingCardVector & cardVector, + const CardMoveRecord &); + + // the card record will contain all changes made by the drag and + // drop. The remove from one stack. The flip of the card if in + // autoCardUp mode and the card under the remove cards was face + // down. And then the add of the cards to the other stack. + // The signal will be emitted by the stack that started the drag + // operation. + void cardsMovedByDragDrop(const CardMoveRecord &); + +protected: + int m_hintHighlightIndex; + + // subclasses should reimplement canMoveCard and canAddCards + // for the rules of whatever game they are implementing. + virtual bool canMoveCard(unsigned int index) const{Q_UNUSED(index); return false;} + virtual bool getCardIndex(const QPointF & pos,unsigned int & index); + + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + + virtual void hoverMoveEvent ( QGraphicsSceneHoverEvent * event ); + +private: + QString m_stackName; + PlayingCardVector m_cardVector; + bool m_highlighted; + bool m_showRedealCircle; + bool m_autoFaceUp; + bool m_mouseMoved; // set to true if the mouse is moved while the button is down + // using this to determine a mouse click on the CardStack. The + // mouse should not move. + QPointF m_dragStartPos; // used to figure out when the mouse has been moved enough to + // start a drag operation + + FlipAnimation m_flipAni; + DragCardStack m_dragStack; + + /////////////////////////////////////////////////////////////////////////////// + // static variables + /////////////////////////////////////////////////////////////////////////////// + static CardStackMap m_cardStackMap; // this is a map that contains all of the current instances + // of CardStack. They are mapped by a unique name to a + // pointer to the instance. + static bool m_lockUserInteraction; +}; + +#endif diff --git a/plugins/qsolocards_plugin/DealAnimation.cpp b/plugins/qsolocards_plugin/DealAnimation.cpp new file mode 100644 index 000000000..b4ef55e10 --- /dev/null +++ b/plugins/qsolocards_plugin/DealAnimation.cpp @@ -0,0 +1,480 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "DealAnimation.h" +#include "CardAnimationLock.h" + + +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +DealItem::DealItem(CardStack * pDst,CardStack * pSrc) + :m_pDst(pDst), + m_pSrc(pSrc), + m_flipList() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +DealItem::DealItem(const DealItem & rh) + :m_pDst(NULL), + m_pSrc(NULL), + m_flipList() +{ + *this=rh; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +DealItem::~DealItem() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +bool DealItem::getNextCard() +{ + bool rc=false; + + if (!m_flipList.empty()) + { + rc=m_flipList.front(); + m_flipList.pop_front(); + } + + + return rc; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +DealItem & DealItem::operator=(const DealItem & rh) +{ + m_pSrc=rh.m_pSrc; + m_pDst=rh.m_pDst; + m_flipList=rh.m_flipList; + + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +DealGraphicsItem::DealGraphicsItem(DealItem & dealItem,CardMoveRecord &moveRecord) + :QObject(), + QGraphicsPixmapItem(), + m_dealItem(dealItem), + m_flipCard(dealItem.getNextCard()), + m_card(PlayingCard::MaxSuit,PlayingCard::MaxCardIndex), + m_pGItemAni(new QGraphicsItemAnimation), + m_moveRecord(moveRecord), + m_timeLine(), + m_delayTimer(), + m_emitFinished(true) +{ + this->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); +} +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +DealGraphicsItem::~DealGraphicsItem() +{ + +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +void DealGraphicsItem::slotAniFinished() +{ + // add the card + m_dealItem.dst()->addCard(m_card,m_moveRecord); + + // now update the destination + m_dealItem.dst()->updateStack(); + + // remove the item from the scene + m_dealItem.src()->scene()->removeItem(this); + + // now if the card needs to be flipped. Flip it. If we are not + // emitting a finish signal. Then disable animation for the flip. + if (m_flipCard) + { + m_dealItem.dst()->flipCard(m_dealItem.dst()->getCardVector().size()-1,m_moveRecord,m_emitFinished); + } + + delete m_pGItemAni; + + m_pGItemAni=NULL; + + if (m_emitFinished) + { + emit aniFinished(this); + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +void DealGraphicsItem::slotTimeToStart() +{ + m_timeLine.start(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +void DealGraphicsItem::setupAnimation(unsigned int duration,unsigned int delay,unsigned int zValue) +{ + m_timeLine.setDuration(duration); + this->connect(&m_timeLine,SIGNAL(finished()), + this,SLOT(slotAniFinished())); + + QPointF startPt(m_dealItem.src()->getGlobalLastCardPt()); + + this->m_card=m_dealItem.src()->removeTopCard(m_moveRecord); + + PlayingCardVector cardVector; + + cardVector.push_back(this->m_card); + + QPixmap * pPixmap=m_dealItem.src()->getStackPixmap(cardVector); + + if (pPixmap) + { + this->setPixmap(*pPixmap); + delete pPixmap; + } + + // set the z value passed in + this->setZValue(zValue); + + // add the item to the scene and move it over the stack in the + // place of the cards we are going to move + m_dealItem.src()->scene()->addItem(this); + this->setPos(startPt); + + + + // setup the animation + m_pGItemAni->setItem(this); + m_pGItemAni->setTimeLine(&m_timeLine); + + m_pGItemAni->setPosAt (0, startPt); + m_pGItemAni->setPosAt (1, m_dealItem.dst()->getGlobalCardAddPt()); + m_pGItemAni->setRotationAt (0, 0); + + // change the rotation slightly depending on how far apart in the + // x direction that stacks are apart. + if (qAbs((int)(startPt.x()-m_dealItem.dst()->getGlobalCardAddPt().x()))<5) + { + } + else if (startPt.x()>=m_dealItem.dst()->getGlobalCardAddPt().x()) + { + m_pGItemAni->setRotationAt (.5, 90); + } + else + { + m_pGItemAni->setRotationAt (.5, -90); + } + + m_pGItemAni->setRotationAt (1, 0); + + // redraw the source stack. + m_dealItem.src()->updateStack(); + + if (delay>0) + { + m_delayTimer.setSingleShot(true); + m_delayTimer.setInterval(delay); + this->connect(&m_delayTimer,SIGNAL(timeout()), + this,SLOT(slotTimeToStart())); + m_delayTimer.start(); + } + else + { + this->slotTimeToStart(); + } +} + +void DealGraphicsItem::stopAni() +{ + bool stopping=false; + if (QTimeLine::Running==m_timeLine.state()) + { + m_timeLine.stop(); + stopping=true; + } + + if (m_delayTimer.isActive()) + { + m_delayTimer.stop(); + stopping=true; + } + + if (stopping) + { + m_emitFinished=false; + this->slotAniFinished(); + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +DealAnimation::DealAnimation() + :m_moveRecord(), + m_dealItemVector(), + m_graphicsItemVector(), + m_aniRunning(false), + m_stopAni(false), + m_duration(DealAnimation::PerDealDuration), + m_createMoveRecord(true) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +DealAnimation::~DealAnimation() +{ + this->stopAni(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +bool DealAnimation::dealCards(const DealItemVector & itemVector, bool createMoveRecord) +{ + if (m_aniRunning) + { + return false; + } + + + m_createMoveRecord=createMoveRecord; + + + // clear any previous items in the move record. + m_moveRecord.clear(); + + // clear any previous items in the dealItemVector + // and set it equal to the new one. + m_dealItemVector.clear(); + m_dealItemVector=itemVector; + + if (!CardAnimationLock::getInst().animationsEnabled()) + { + this->noAniStackUdpates(); + } + else + { + this->buildAniStackUpdates(); + CardAnimationLock::getInst().lock(); + + this->m_aniRunning=true; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +void DealAnimation::stopAni() +{ + // ok we only want to do this if animation is running. + if (m_aniRunning) + { + m_aniRunning=false; + + unsigned int i; + + // different from the case when we are cleaning these up as we go we want a hard update, and then + // delete of the objects. + for (i=0;istopAni(); + delete m_graphicsItemVector[i]; + } + + m_graphicsItemVector.clear(); + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +void DealAnimation::slotAniFinished(DealGraphicsItem * pDealGraphicsItem) +{ + if (m_aniRunning) + { + // cleanup and finialize addition of items to new stacks. + this->cleanUpGraphicsItem(pDealGraphicsItem); + + if (m_graphicsItemVector.empty()) + { + m_aniRunning=false; + + CardAnimationLock::getInst().unlock(); + + if (!m_createMoveRecord) + { + m_moveRecord.clear(); + } + + emit cardsMoved(m_moveRecord); + } + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +bool DealAnimation::cardsRemaining() +{ + bool rc=false; + unsigned int i; + + for (i=0;ideleteLater(); + break; + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +void DealAnimation::cleanUpGraphicsItems() +{ + unsigned int i; + + for (i=0;ideleteLater(); + } + + m_graphicsItemVector.clear(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +void DealAnimation::noAniStackUdpates() +{ + unsigned int i; + bool oneNotEmpty=true; + + while (oneNotEmpty) + { + oneNotEmpty=false; + for (i=0;iremoveTopCard(m_moveRecord)); + + m_dealItemVector[i].dst()->addCard(card,m_moveRecord); + + if (flip) + { + m_dealItemVector[i].dst()->flipCard(-1,m_moveRecord); + } + m_dealItemVector[i].src()->updateStack(); + m_dealItemVector[i].dst()->updateStack(); + + oneNotEmpty=true; + } + } + } + + if (!m_createMoveRecord) + { + m_moveRecord.clear(); + } + + if (m_aniRunning) + { + emit cardsMoved(m_moveRecord); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +void DealAnimation::buildAniStackUpdates() +{ + unsigned int i; + unsigned int j=0; + + bool oneNotEmpty=true; + + while (oneNotEmpty) + { + oneNotEmpty=false; + + + for (i=0;isetupAnimation(m_duration,j*PerCardDelay,j+2); + + this->connect(pCurrGraphicsItem,SIGNAL(aniFinished(DealGraphicsItem *)), + this,SLOT(slotAniFinished(DealGraphicsItem *))); + + m_graphicsItemVector.push_back(pCurrGraphicsItem); + + oneNotEmpty=true; + j++; + } + } + } +} diff --git a/plugins/qsolocards_plugin/DealAnimation.h b/plugins/qsolocards_plugin/DealAnimation.h new file mode 100644 index 000000000..1f5ae29a3 --- /dev/null +++ b/plugins/qsolocards_plugin/DealAnimation.h @@ -0,0 +1,149 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __DEALANIMATION_H__ +#define __DEALANIMATION_H__ + +#include + +#include "CardStack.h" +#include "CardMoveRecord.h" +#include +#include + +#include +#include +#include + +// DealItems can be used to define the cards that will be dealt to a stack. +// The DealItem can then be added to the DealItemVector which is the overall +// definition of the deal. +class DealItem +{ +public: + DealItem(CardStack * pDst,CardStack * pSrc); + DealItem(const DealItem & rh); + ~DealItem(); + + inline bool isEmpty()const{return (m_flipList.empty() || m_pSrc->isEmpty());} + inline void addCard(bool flip){m_flipList.push_back(flip);} + + // returns the flip value of the next card and pops it off the list. + bool getNextCard(); + + inline CardStack * dst(){return m_pDst;} + inline CardStack * src(){return m_pSrc;} + + DealItem & operator=(const DealItem & rh); + +private: + CardStack * m_pDst; + CardStack * m_pSrc; + std::list m_flipList; // the list allows a record of how many cards to deal from the + // src to the dst and which ones need to be flipped. + // The cards will only be flipped once added to the dst stack. +}; + +typedef std::vector DealItemVector; + +class DealGraphicsItem:public QObject,public QGraphicsPixmapItem +{ + Q_OBJECT +public: + DealGraphicsItem(DealItem & dealItem,CardMoveRecord & moveRecord); + virtual ~DealGraphicsItem(); + + inline DealItem & getItem(){return m_dealItem;} + + void setupAnimation(unsigned int duration,unsigned int delay,unsigned int zValue); + + inline bool flipCard()const{return m_flipCard;} + + inline const PlayingCard & card()const{return m_card;} + + void stopAni(); + +signals: + void aniFinished(DealGraphicsItem *); +public slots: + void slotAniFinished(); + void slotTimeToStart(); + +private: + DealItem & m_dealItem; + bool m_flipCard; + PlayingCard m_card; + QGraphicsItemAnimation * m_pGItemAni; + CardMoveRecord & m_moveRecord; + QTimeLine m_timeLine; + QTimer m_delayTimer; + bool m_emitFinished; +}; + +typedef std::vector DealGraphicsItemVector; + +class DealAnimation: public QObject +{ + Q_OBJECT +public: + enum + { + PerDealDuration=400, + PerCardDelay=60 + }; + + DealAnimation(); + virtual ~DealAnimation(); + + // this duration may not be the total for the entire deal. This the duration for one round. + // So, if you have ten stacks and are dealing 5 cards to eacy stack. The entire duration will + // be the duration x 5. + inline void setDuration(int durInMilSecs=PerDealDuration){m_duration=durInMilSecs;} + inline int getDuration()const{return m_duration;} + + // the option of sending the complete signal is for cases like the initial deal of the cards. + // In that case the caller does not care when it is done as long as the user can't do anything + // until the deal is complete. The use of the CardAnimationLock will ensure this whether or not + // the caller wants to get the notification. + bool dealCards(const DealItemVector & itemVector,bool createMoveRecord=true); + + void stopAni(); + +signals: + void cardsMoved(const CardMoveRecord & moveRecord); + +public slots: + void slotAniFinished(DealGraphicsItem * pDealGraphicsItem); + +private: + bool cardsRemaining(); + void cleanUpGraphicsItem(DealGraphicsItem * pDealGraphicsItem); + void cleanUpGraphicsItems(); + void noAniStackUdpates(); + void buildAniStackUpdates(); + + CardMoveRecord m_moveRecord; + DealItemVector m_dealItemVector; + DealGraphicsItemVector m_graphicsItemVector; + bool m_aniRunning; + bool m_stopAni; + int m_duration; + bool m_createMoveRecord; +}; + +#endif diff --git a/plugins/qsolocards_plugin/DragCardStack.cpp b/plugins/qsolocards_plugin/DragCardStack.cpp new file mode 100644 index 000000000..d4d0460f6 --- /dev/null +++ b/plugins/qsolocards_plugin/DragCardStack.cpp @@ -0,0 +1,209 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "DragCardStack.h" +#include "CardStack.h" + +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +DragCardStack::DragCardStack(CardStack * pSrc) + :QObject(),QGraphicsPixmapItem(), + m_cardVector(), + m_pSrc(pSrc), + m_size(0,0), + m_cursorPt(0,0), + m_dragStarted(false), + m_pDst(NULL) +{ + this->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + this->setCursor(Qt::ClosedHandCursor); +} + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +DragCardStack::~DragCardStack() +{ +} + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +void DragCardStack::startCardMove(const QPointF & globalMousePt, + unsigned int startCardIndex, + const PlayingCardVector & moveCards) +{ + if (startCardIndexgetCardVector().size() && + moveCards.size()>0) + { + this->m_cardVector.clear(); + this->m_cardVector=moveCards; + + QPixmap * pPixmap=m_pSrc->getStackPixmap(this->m_cardVector); + + if (NULL!=pPixmap) + { + this->setPixmap(*pPixmap); + m_size=pPixmap->size(); + delete pPixmap; + } + + // set the z value to 2 so it will be on top of the + // stacks. + this->setZValue(2); + + + QPointF startPt=m_pSrc->getGlobalCardPt(startCardIndex); + + // this gets the relative position of the mouse on the new object. + m_cursorPt.setX(globalMousePt.x()-startPt.x()); + m_cursorPt.setY(globalMousePt.y()-startPt.y()); + + // add the item to the scene and move it over the stack in the + // place of the cards that we want to move + m_pSrc->scene()->addItem(this); + this->setPos(startPt); + + // remove the cards from the stack and repaint + unsigned int i; + + for(i=m_pSrc->getCardVector().size()-1;i>=startCardIndex && !m_pSrc->isEmpty();i--) + { + m_pSrc->removeTopCard(); + } + m_pSrc->updateStack(); + m_pSrc->setCursor(Qt::ClosedHandCursor); + + + m_dragStarted=true; + + m_pDst=NULL; + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +void DragCardStack::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); + + if (m_dragStarted) + { + m_dragStarted=false; + m_pSrc->scene()->removeItem(this); + + if (NULL!=m_pDst && + this->m_pDst->canAddCards(this->m_cardVector)) + { + CardMoveRecord moveRecord; + + moveRecord.push_back(CardMoveRecordItem(this->m_pSrc->stackName(), + CardMoveRecordItem::RemoveCards, + this->m_cardVector)); + + m_pDst->addCards(this->m_cardVector,moveRecord); + m_pDst->setHighlighted(false); + m_pDst->updateStack(); + + emit cardsMoved(moveRecord); + + m_pDst=NULL; + } + else + { + m_pSrc->addCards(this->m_cardVector); + m_pSrc->updateStack(); + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +void DragCardStack::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_dragStarted) + { + // get the topleft from the mouse pos and then adjust for where the mouse + // is positioned on the card. + QPointF topLeft(event->scenePos()); + topLeft.rx()-=m_cursorPt.x(); + topLeft.ry()-=m_cursorPt.y(); + + // move the card to it's new place. + this->setPos(topLeft); + + // calc our bounding rect. + QRectF boundingRect(topLeft,QSizeF(m_size.width(),m_size.height())); + + // now find which items this item intersects with. + QList intersectItems=this->scene()->items(boundingRect); + + CardStack * pNewDst=NULL; + + qreal largestArea=0; + + for(int i=0;isceneBoundingRect(); + + if (boundingCurr.contains(event->scenePos())) + { + pNewDst=pCurrDst; + break; + } + else + { + QRectF commonRect(boundingRect.intersected(boundingCurr)); + + qreal currArea=commonRect.width()*commonRect.height(); + + if (currArea>largestArea) + { + largestArea=currArea; + pNewDst=pCurrDst; + } + } + } + } + + if (pNewDst!=this->m_pDst) + { + if (NULL!=this->m_pDst) + { + this->m_pDst->setHighlighted(false); + this->m_pDst->updateStack(); + } + this->m_pDst=pNewDst; + + if (NULL!=this->m_pDst && + this->m_pDst->canAddCards(this->m_cardVector)) + { + this->m_pDst->setHighlighted(true); + this->m_pDst->updateStack(); + } + } + } +} diff --git a/plugins/qsolocards_plugin/DragCardStack.h b/plugins/qsolocards_plugin/DragCardStack.h new file mode 100644 index 000000000..be4d7d4e2 --- /dev/null +++ b/plugins/qsolocards_plugin/DragCardStack.h @@ -0,0 +1,58 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifndef __DRAGCARDSTACK_H__ +#define __DRAGCARDSTACK_H__ + +#include +#include +#include "CardDeck.h" +#include "CardMoveRecord.h" + +class CardStack; + +class DragCardStack:public QObject,public QGraphicsPixmapItem +{ + Q_OBJECT +public: + DragCardStack(CardStack * pSrc); + virtual ~DragCardStack(); + + inline bool cardDragStarted()const{return m_dragStarted;} + + void startCardMove(const QPointF & globalMousePt, + unsigned int startCardIndex, + const PlayingCardVector & moveCards); + +signals: + void cardsMoved(const CardMoveRecord & moveRecord); + +protected: + friend class CardStack; + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + +private: + PlayingCardVector m_cardVector; + CardStack * m_pSrc; + QSize m_size; + QPoint m_cursorPt; + bool m_dragStarted; + CardStack * m_pDst; +}; + +#endif diff --git a/plugins/qsolocards_plugin/FlipAnimation.cpp b/plugins/qsolocards_plugin/FlipAnimation.cpp new file mode 100644 index 000000000..679d8f0f8 --- /dev/null +++ b/plugins/qsolocards_plugin/FlipAnimation.cpp @@ -0,0 +1,193 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "FlipAnimation.h" +#include "CardStack.h" +#include "CardAnimationLock.h" + +#include + + +/////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////// +FlipAnimation::FlipAnimation() + :m_pSrc(NULL), + m_card(), + m_timeLine(), + m_pItemAni(NULL), + m_pPixmapItem(NULL), + m_flipPtReached(false), + m_aniRunning(false) +{ + // connect up the slot so we will know when it is finished. + this->connect(&m_timeLine,SIGNAL(finished()), + this,SLOT(slotAniFinished())); + + this->connect(&m_timeLine,SIGNAL(valueChanged(qreal)), + this,SLOT(slotFlipAniProgress(qreal))); +} + +/////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////// +FlipAnimation::~FlipAnimation() +{ + delete m_pItemAni; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////// +void FlipAnimation::flipCard(CardStack * pSrc,int duration) +{ + // if animation is off just immediately emit the flipComplete + // signal + if (!CardAnimationLock::getInst().animationsEnabled() || + pSrc->isEmpty()) + { + emit flipComplete(pSrc); + } + else + { + // first if we have an animation running stop it. + this->stopAni(); + m_pSrc=pSrc; + runAnimation(duration); + } + +} + + +/////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////// +void FlipAnimation::stopAni() +{ + if (this->isAniRunning()) + { + m_aniRunning=false; + + this->m_timeLine.stop(); + + // remove the animation object + m_pSrc->scene()->removeItem(m_pPixmapItem); + delete m_pPixmapItem; + m_pPixmapItem=NULL; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////// +bool FlipAnimation::isAniRunning() const +{ + return m_aniRunning; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////// +void FlipAnimation::slotAniFinished() +{ + m_aniRunning=false; + + emit flipComplete(m_pSrc); + + // remove the animation object + m_pSrc->scene()->removeItem(m_pPixmapItem); + delete m_pPixmapItem; + m_pPixmapItem=NULL; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////// +void FlipAnimation::slotFlipAniProgress(qreal currProgress) +{ + if (currProgress>=.5 && !m_flipPtReached) + { + m_flipPtReached=true; + + m_card.setFaceUp(!m_card.isFaceUp()); + + PlayingCardVector cardVector; + + cardVector.push_back(m_card); + + QPixmap * pPixmap=m_pSrc->getStackPixmap(cardVector); + + if (pPixmap) + { + m_pPixmapItem->setPixmap(*pPixmap); + delete pPixmap; + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////// +void FlipAnimation::runAnimation(int duration) +{ + m_flipPtReached=false; + + delete m_pItemAni; + delete m_pPixmapItem; + + m_timeLine.setDuration(duration); + m_pItemAni=new QGraphicsItemAnimation; + m_pPixmapItem=new QGraphicsPixmapItem; + + m_card=m_pSrc->getCardVector()[m_pSrc->getCardVector().size()-1]; + + PlayingCardVector cardVector; + + cardVector.push_back(m_card); + + QPixmap * pPixmap=m_pSrc->getStackPixmap(cardVector); + + if (pPixmap) + { + m_pPixmapItem->setPixmap(*pPixmap); + delete pPixmap; + } + + m_pPixmapItem->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + + QPointF initPt(m_pSrc->getGlobalLastCardPt()); + + QPoint halfWayPt(initPt.x()+pPixmap->width()/2,initPt.y()+pPixmap->height()/2); + + // set the z value to 2 so it will be on top of the + // stacks. + m_pPixmapItem->setZValue(2); + + // add the item to the scene and move it over the stack in the + // place of the card we are going to flip + m_pSrc->scene()->addItem(m_pPixmapItem); + m_pPixmapItem->setPos(initPt); + + // setup the animation + m_pItemAni->setItem(m_pPixmapItem); + m_pItemAni->setTimeLine(&m_timeLine); + + m_pItemAni->setPosAt (0, initPt); + m_pItemAni->setPosAt (.5, halfWayPt); + m_pItemAni->setPosAt (1, initPt); + + m_pItemAni->setScaleAt( 0, 1, 1 ); + m_pItemAni->setScaleAt( 0.5, 0.0, 1 ); + m_pItemAni->setScaleAt( 1, 1, 1 ); + + + m_aniRunning=true; + m_timeLine.start(); +} diff --git a/plugins/qsolocards_plugin/FlipAnimation.h b/plugins/qsolocards_plugin/FlipAnimation.h new file mode 100644 index 000000000..5d13b05cd --- /dev/null +++ b/plugins/qsolocards_plugin/FlipAnimation.h @@ -0,0 +1,75 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifndef __FLIPANIMATION_H__ +#define __FLIPANIMATION_H__ + +#include "CardMoveRecord.h" + +#include +#include +#include +#include +#include + +class CardStack; + +// This animation is different from the DealAnimation and StackToStackAniMove in that +// it will require the stack to change during the animation. Since, the effect of the +// animation is to show a card flipping the stack below it will be shown. And the stack +// needs to be shown without the card in it when it is exposed by the animation. So, the +// animation is a combination of the FlipAnimation object and CardStack object to get the +// flip effect. +class FlipAnimation: public QObject +{ + Q_OBJECT +public: + FlipAnimation(); + virtual ~FlipAnimation(); + + // This animation is specifically for flipping the last card in a + // stack. Cases where a card is flipped that is under other cards + // is not covered. If needed it can be added later. Something where + // the cards on top of it are pivoted out of the way, doing + // a flip of the desired card, and pivoting the cards back down on + // top of the flip card would be a very nice effect. + void flipCard(CardStack * pSrc,int duration=300); + + void stopAni(); + + bool isAniRunning() const; + +signals: + void flipComplete(CardStack * pSrc); + +public slots: + void slotAniFinished(); + void slotFlipAniProgress(qreal currProgress); + +private: + void runAnimation(int duration); + + CardStack * m_pSrc; + PlayingCard m_card; + QTimeLine m_timeLine; + QGraphicsItemAnimation * m_pItemAni; + QGraphicsPixmapItem * m_pPixmapItem; + bool m_flipPtReached; + bool m_aniRunning; +}; + +#endif diff --git a/plugins/qsolocards_plugin/FreeCellBoard.cpp b/plugins/qsolocards_plugin/FreeCellBoard.cpp new file mode 100644 index 000000000..32fc04daa --- /dev/null +++ b/plugins/qsolocards_plugin/FreeCellBoard.cpp @@ -0,0 +1,693 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "FreeCellBoard.h" +#include "CardPixmaps.h" +#include "CardDeck.h" +#include "CardAnimationLock.h" + +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +FreeCellBoard::FreeCellBoard() + :GameBoard(NULL,QString(tr("Freecell")).trimmed(),QString("Freecell")), + m_pDeck(NULL), + m_freeVector(), + m_stackVector(), + m_homeVector(), + m_cheat(false) +{ + this->setHelpFile(":/help/FreeCellHelp.html"); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +FreeCellBoard::~FreeCellBoard() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::undoMove() +{ + GameBoard::undoMove(); + + this->setNumStackMoveCards(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::redoMove() +{ + GameBoard::redoMove(); + + this->setNumStackMoveCards(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +bool FreeCellBoard::getHint(CardStack * & pSrc, + unsigned int & srcIndex, + CardStack * & pDst) +{ + bool rc=false; + unsigned int i; + unsigned int j; + + + // first see if we have any cards from the free cells to move + // home + for (i=0;im_freeVector.size() && !rc;i++) + { + if (!this->m_freeVector[i]->isEmpty()) + { + const PlayingCardVector & cardVector=this->m_freeVector[i]->getCardVector(); + PlayingCardVector moveCards; + + srcIndex=cardVector.size()-1; + + moveCards.push_back(cardVector[srcIndex]); + + for (j=0;jm_homeVector.size();j++) + { + if (this->m_homeVector[j]->canAddCards(moveCards)) + { + pSrc=this->m_freeVector[i]; + pDst=this->m_homeVector[j]; + rc=true; + break; + } + } + } + } + + // now see if there are any cards in the stacks to move home + if (!rc) + { + for (i=0;im_stackVector.size() && !rc;i++) + { + if (!this->m_stackVector[i]->isEmpty()) + { + const PlayingCardVector & cardVector=this->m_stackVector[i]->getCardVector(); + PlayingCardVector moveCards; + + srcIndex=cardVector.size()-1; + + moveCards.push_back(cardVector[srcIndex]); + + for (j=0;jm_homeVector.size();j++) + { + if (this->m_homeVector[j]->canAddCards(moveCards)) + { + pSrc=this->m_stackVector[i]; + pDst=this->m_homeVector[j]; + rc=true; + break; + } + } + } + } + } + + // now see if we can move cards from the free cells to the stacks + if (!rc) + { + for (i=0;im_freeVector.size() && !rc;i++) + { + if (!this->m_freeVector[i]->isEmpty()) + { + PlayingCardVector moveCards; + + if (this->m_freeVector[i]->getMovableCards(moveCards,srcIndex)) + { + for (j=0;jm_stackVector.size();j++) + { + if (this->m_stackVector[j]->canAddCards(moveCards)) + { + pSrc=this->m_freeVector[i]; + pDst=this->m_stackVector[j]; + rc=true; + break; + } + } + } + } + } + } + + // now look for stack to stack moves + if (!rc) + { + for (i=0;im_stackVector.size() && !rc;i++) + { + if (!this->m_stackVector[i]->isEmpty()) + { + PlayingCardVector moveCards; + + if (this->m_stackVector[i]->getMovableCards(moveCards,srcIndex)) + { + // look through the stacks if we couldn't move the card home + for (j=0;jm_stackVector.size();j++) + { + // make sure not the same stackVector and that we are not moving + // the last card in a stack to an empty stack. Moving the last + // card in a stack to an empty stack doesn't do anything. And lastly + // if the cards can be added we have a match. + if (i!=j && + !(0==srcIndex && this->m_stackVector[j]->isEmpty()) && + this->m_stackVector[j]->canAddCards(moveCards)) + { + pSrc=this->m_stackVector[i]; + pDst=this->m_stackVector[j]; + rc=true; + break; + } + } + } + } + } + } + + + // now look to move something to a free cell if all else has failed + // for now just going to be a basic move an available card from the first + // stack with cards in it to the free cell. + if (!rc) + { + // first find an open free cell. If we don't have one no need to continue. + pDst=NULL; + + for (i=0;im_freeVector.size();i++) + { + if (this->m_freeVector[i]->isEmpty()) + { + pDst=this->m_freeVector[i]; + break; + } + } + + if (NULL!=pDst) + { + for (i=0;im_stackVector.size();i++) + { + if (!this->m_stackVector[i]->isEmpty()) + { + PlayingCardVector moveCards; + + + if (this->m_stackVector[i]->getMovableCards(moveCards,srcIndex) && + pDst->canAddCards(moveCards)) + { + pSrc=this->m_stackVector[i]; + rc=true; + break; + } + } + } + } + } + + + return rc; +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::newGame() +{ + // call the base class to clean up + GameBoard::newGame(); + + CardDeck deck; + unsigned int i; + + + // add all the cards to the deck + while(!deck.isEmpty()) + { + this->m_pDeck->addCard(deck.next()); + } + + // setup the deal of cards + DealItemVector dealItemVector; + + // Create the dealItemVector to direct the DealAnimation object on + // how to deal the cards. + for (i=0;im_stackVector.size();i++) + { + unsigned int j; + unsigned int cardsInStack=((i<4)?7:6); + + dealItemVector.push_back(DealItem(this->m_stackVector[i],m_pDeck)); + + for (j=0;jsetCheat(cheat); + } +} + + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::slotCardsMoved(const CardMoveRecord & moveRecord) +{ + GameBoard::slotCardsMoved(moveRecord); + + this->setNumStackMoveCards(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::slotFreeCardsClicked(CardStack * pCardStack, + const PlayingCardVector & cardVector, + const CardMoveRecord & startMoveRecord) +{ + Q_UNUSED(pCardStack); + + CardStack * pEmptyStack=NULL; + CardStack * pMoveStack=NULL; + unsigned int i; + + // ok look for where we would move the cards to. We will look first at the home stacks. + // After the home stacks the next priority will be a non-empty stack and then lastly + // an empty stack. + + for (i=0;im_homeVector.size();i++) + { + if (this->m_homeVector[i]->canAddCards(cardVector)) + { + pMoveStack=this->m_homeVector[i]; + break; + } + } + + // if we did not find a match continue to look + if (NULL==pMoveStack) + { + for (i=0;im_stackVector.size();i++) + { + if (this->m_stackVector[i]->canAddCards(cardVector)) + { + if (this->m_stackVector[i]->isEmpty()) + { + pEmptyStack=this->m_stackVector[i]; + } + else + { + pMoveStack=this->m_stackVector[i]; + break; + } + } + } + } + + if (NULL!=pMoveStack || NULL!=pEmptyStack) + { + if (NULL==pMoveStack) + { + pMoveStack=pEmptyStack; + } + + CardMoveRecord moveRecord(startMoveRecord); + pMoveStack->addCards(cardVector,moveRecord,true); + + // perform the move of the cards and animate it if animations + // are enabled + m_sToSAniMove.moveCards(moveRecord); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::slotStackCardsClicked(CardStack * pCardStack, + const PlayingCardVector & cardVector, + const CardMoveRecord & startMoveRecord) +{ + CardStack * pEmptyStack=NULL; + CardStack * pMoveStack=NULL; + unsigned int i; + + // ok look for where we would move the cards to. We will look first at the home stacks. + // After the home stacks the next priority will be a non-empty stack then an empty stack. + // And lastly a free cell. + + for (i=0;im_homeVector.size();i++) + { + if (this->m_homeVector[i]->canAddCards(cardVector)) + { + pMoveStack=this->m_homeVector[i]; + break; + } + } + + // if we did not find a match continue to look + if (NULL==pMoveStack) + { + for (i=0;im_stackVector.size();i++) + { + if (this->m_stackVector[i]!=pCardStack) + { + if (this->m_stackVector[i]->canAddCards(cardVector)) + { + if (this->m_stackVector[i]->isEmpty()) + { + pEmptyStack=this->m_stackVector[i]; + } + else + { + pMoveStack=this->m_stackVector[i]; + break; + } + } + } + } + } + + // now look in the free cells + if (NULL==pMoveStack) + { + for (i=0;im_freeVector.size();i++) + { + if (this->m_freeVector[i]->canAddCards(cardVector)) + { + pMoveStack=this->m_freeVector[i]; + break; + } + } + } + + if (NULL!=pMoveStack || NULL!=pEmptyStack) + { + if (NULL==pMoveStack) + { + pMoveStack=pEmptyStack; + } + + CardMoveRecord moveRecord(startMoveRecord); + pMoveStack->addCards(cardVector,moveRecord,true); + + // perform the move of the cards and animate it if animations + // are enabled + m_sToSAniMove.moveCards(moveRecord); + } + +} + + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::calcScore() +{ + int score=0; + + for(unsigned int i=0;im_homeVector.size();i++) + { + score+=this->m_homeVector[i]->score(); + } + + emit scoreChanged(score,""); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::resizeEvent (QResizeEvent * event) +{ + unsigned int i; + + GameBoard::resizeEvent(event); + + + QSize cardSize(CardPixmaps::getInst().getCardSize()); + + QPointF currPos(GameBoard::LayoutSpacing,GameBoard::LayoutSpacing); + + for (i=0;isetPos(currPos); + currPos.rx()+=cardSize.width()+GameBoard::LayoutSpacing; + } + + currPos.rx()+=(cardSize.width() + GameBoard::LayoutSpacing)/2; + + m_pDeck->setPos(currPos); + + currPos.setX(GameBoard::LayoutSpacing*7 + cardSize.width()*6); + + + for (i=0;isetPos(currPos); + currPos.rx()+=cardSize.width()+GameBoard::LayoutSpacing; + } + + currPos.setY(GameBoard::LayoutSpacing*2+cardSize.height()); + currPos.setX(GameBoard::LayoutSpacing*2+cardSize.width()); + for (i=0;isetPos(currPos); + currPos.rx()+=cardSize.width()+GameBoard::LayoutSpacing; + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +bool FreeCellBoard::runDemo(bool stopWhenNoMore) +{ + bool rc=true; + + if (!GameBoard::runDemo(false)) + { + // if we didn't find a move. Try to just move a card to a freecell. + CardStack * pDst=NULL; + bool foundMove=false; + CardStack * pSrc=NULL; + unsigned int srcIndex=0; + PlayingCardVector moveCards; + unsigned int i; + + for (i=0;im_freeVector.size();i++) + { + if (this->m_freeVector[i]->isEmpty()) + { + pDst=this->m_freeVector[i]; + break; + } + } + + if (NULL!=pDst) + { + for (i=0;im_stackVector.size();i++) + { + if (!this->m_stackVector[i]->isEmpty()) + { + if (this->m_stackVector[i]->getMovableCards(moveCards,srcIndex) && + pDst->canAddCards(moveCards)) + { + pSrc=this->m_stackVector[i]; + foundMove=true; + break; + } + } + } + } + + // if we found a move create the move record. And call the stack to stack + // animation to move it. + if (foundMove) + { + CardMoveRecord moveRecord; + + pSrc->removeCardsStartingAt(srcIndex,moveCards,moveRecord,true); + pDst->addCards(moveCards,moveRecord,true); + + m_sToSAniMove.moveCards(moveRecord,this->getDemoCardAniTime()); + } + else + { + if (stopWhenNoMore) + { + stopDemo(); + rc=false; + } + else + { + rc=false; + } + } + } + + return rc; + +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::createStacks() +{ + this->setCardResizeAlg(10,ResizeByWidth); + + unsigned int i; + + // first create the home widgets where the cards need to be eventually stacked to + // win the game. + for(i=0;i<4;i++) + { + this->m_homeVector.push_back(new FreeCellHome); + this->m_scene.addItem(m_homeVector[i]); + } + + // now create the free cells + for(i=0;i<4;i++) + { + this->m_freeVector.push_back(new FreeCellFree); + this->m_scene.addItem(m_freeVector[i]); + this->connect(this->m_freeVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + this->connect(this->m_freeVector[i],SIGNAL(movableCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotFreeCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord))); + } + + // now create the 8 rows for the stacks. + for (i=0;i<8;i++) + { + this->m_stackVector.push_back(new FreeCellStack); + this->m_scene.addItem(m_stackVector[i]); + this->connect(this->m_stackVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + this->connect(this->m_stackVector[i],SIGNAL(movableCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotStackCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord))); + } + + this->m_pDeck=new FreeCellDeck; + this->m_scene.addItem(this->m_pDeck); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +bool FreeCellBoard::isGameWon()const +{ + bool rc=true; + + for (unsigned int i=0;im_homeVector.size();i++) + { + if (!this->m_homeVector[i]->isStackComplete()) + { + rc=false; + break; + } + } + + return rc; +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +bool FreeCellBoard::isGameWonNotComplete()const +{ + bool rc=true; + + for (unsigned int i=0;im_stackVector.size();i++) + { + if (!this->m_stackVector[i]->cardsAscendingTopToBottom()) + { + rc=false; + break; + } + } + + return rc; +} + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +void FreeCellBoard::setNumStackMoveCards() +{ + // as a convience allow dragging of cards if there would be enough + // freecells to move the cards + unsigned int numDragCards=1; + unsigned int i; + + for (i=0;iisEmpty()) + { + numDragCards++; + } + } + + // in the case that we might be dragging the cards to a free + // space, we don't want the free space to count. It would not + // be a free space to dump a card. So, it can't be counted. + if (numDragCards>1) + { + numDragCards--; + } + + for (i=0;iisEmpty()) + { + numDragCards++; + } + } + + for (i=0;isetMaxMoveCards(numDragCards); + } +} diff --git a/plugins/qsolocards_plugin/FreeCellBoard.h b/plugins/qsolocards_plugin/FreeCellBoard.h new file mode 100644 index 000000000..a35aedb9f --- /dev/null +++ b/plugins/qsolocards_plugin/FreeCellBoard.h @@ -0,0 +1,93 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __FREECELLBOARD_H__ +#define __FREECELLBOARD_H__ + +#include "GameBoard.h" +#include "FreeCellDeck.h" +#include "FreeCellFree.h" +#include "FreeCellStack.h" +#include "FreeCellHome.h" +#include "VCardStack.h" + +#include + +class FreeCellBoard: public GameBoard +{ + Q_OBJECT +public: + FreeCellBoard(); + virtual ~FreeCellBoard(); + + virtual void undoMove(); + virtual void redoMove(); + + bool getHint(CardStack * & pSrc, + unsigned int & srcIndex, + CardStack * & pDst); + + inline bool hasDemo() const {return true;} + + void newGame(); + + void addGameMenuItems(QMenu & menu); + + void loadSettings(const QSettings & settings); + void saveSettings(QSettings & settings); + + inline bool isCheating() const {return m_cheat;} + + void setCheat(bool cheat); + + inline bool supportsScore() const{return true;} +public slots: + virtual void slotCardsMoved(const CardMoveRecord &); + + void slotFreeCardsClicked(CardStack * pCardStackWidget, + const PlayingCardVector & cardVector, + const CardMoveRecord &); + void slotStackCardsClicked(CardStack * pCardStackWidget, + const PlayingCardVector & cardVector, + const CardMoveRecord &); + +protected: + void calcScore(); + + virtual void resizeEvent (QResizeEvent * event); + + bool runDemo(bool stopWhenNoMore=true); + + void createStacks(); + bool isGameWon()const; + bool isGameWonNotComplete()const; + + void setNumStackMoveCards(); + +private: + + FreeCellDeck * m_pDeck; // the deck will only be used for the initial deal of cards + + std::vector m_freeVector; // free cells that any card can be placed in there will be 4 + std::vector m_stackVector; // we will have 8 items in this vector + std::vector m_homeVector; // we will have 4 items in this vector one for each suit + + bool m_cheat; +}; + +#endif diff --git a/plugins/qsolocards_plugin/FreeCellDeck.cpp b/plugins/qsolocards_plugin/FreeCellDeck.cpp new file mode 100644 index 000000000..83416dded --- /dev/null +++ b/plugins/qsolocards_plugin/FreeCellDeck.cpp @@ -0,0 +1,50 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "FreeCellDeck.h" +#include "CardPixmaps.h" + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +FreeCellDeck::FreeCellDeck() + :CardStack() +{ +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +FreeCellDeck::~FreeCellDeck() +{ +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void FreeCellDeck::updateStack() +{ + // after the initial deal of cards we want this + // stack to be transparent. So, if the stack + // is empty use the transparent card pixmap. + if (this->isEmpty()) + { + this->setPixmap(CardPixmaps::getInst().getTransparentPixmap()); + } + else + { + CardStack::updateStack(); + } +} diff --git a/plugins/qsolocards_plugin/FreeCellDeck.h b/plugins/qsolocards_plugin/FreeCellDeck.h new file mode 100644 index 000000000..658204d55 --- /dev/null +++ b/plugins/qsolocards_plugin/FreeCellDeck.h @@ -0,0 +1,35 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __FREECELLDECK_H__ +#define __FREECELLDECK_H__ + +#include "CardStack.h" + +class FreeCellDeck: public CardStack +{ + Q_OBJECT +public: + FreeCellDeck(); + virtual ~FreeCellDeck(); + + virtual void updateStack(); + +}; + +#endif diff --git a/plugins/qsolocards_plugin/FreeCellFree.cpp b/plugins/qsolocards_plugin/FreeCellFree.cpp new file mode 100644 index 000000000..5f7ad6cf0 --- /dev/null +++ b/plugins/qsolocards_plugin/FreeCellFree.cpp @@ -0,0 +1,59 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "FreeCellFree.h" + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +FreeCellFree::FreeCellFree() + :CardStack() +{ +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +FreeCellFree::~FreeCellFree() +{ +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +bool FreeCellFree::canAddCards(const PlayingCardVector & newCardVector) +{ + bool rc=false; + + if (1==newCardVector.size() && this->isEmpty()) + { + rc=true; + } + + return rc; +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +bool FreeCellFree::canMoveCard(unsigned int index) const +{ + bool rc=false; + + if (0==index && this->getCardVector().size()==1) + { + rc=true; + } + return rc; +} diff --git a/plugins/qsolocards_plugin/FreeCellFree.h b/plugins/qsolocards_plugin/FreeCellFree.h new file mode 100644 index 000000000..65e1832ef --- /dev/null +++ b/plugins/qsolocards_plugin/FreeCellFree.h @@ -0,0 +1,36 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __FREECELLFREE_H__ +#define __FREECELLFREE_H__ + +#include "CardStack.h" + +class FreeCellFree : public CardStack +{ + Q_OBJECT +public: + FreeCellFree(); + ~FreeCellFree(); + + bool canAddCards(const PlayingCardVector &); +protected: + bool canMoveCard(unsigned int index) const; +}; + +#endif // __FREECELLFREE_H__ diff --git a/plugins/qsolocards_plugin/FreeCellHome.cpp b/plugins/qsolocards_plugin/FreeCellHome.cpp new file mode 100644 index 000000000..3a3a44ba6 --- /dev/null +++ b/plugins/qsolocards_plugin/FreeCellHome.cpp @@ -0,0 +1,57 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "FreeCellHome.h" + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +FreeCellHome::FreeCellHome() + :CardStack() +{ +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +FreeCellHome::~FreeCellHome() +{ +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +bool FreeCellHome::canAddCards(const PlayingCardVector & newCardVector) +{ + bool rc=false; + const PlayingCardVector & cardVector=this->getCardVector(); + + if (1==newCardVector.size()) + { + + if (this->isEmpty() && PlayingCard::Ace==newCardVector[0].getIndex()) + { + rc=true; + } + else if (!this->isEmpty() && + cardVector[cardVector.size()-1].isSameSuit(newCardVector[0]) && + cardVector[cardVector.size()-1].isNextCardIndex(newCardVector[0])) + { + rc=true; + } + } + + return rc; +} diff --git a/plugins/qsolocards_plugin/FreeCellHome.h b/plugins/qsolocards_plugin/FreeCellHome.h new file mode 100644 index 000000000..dfabb73f7 --- /dev/null +++ b/plugins/qsolocards_plugin/FreeCellHome.h @@ -0,0 +1,37 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __FREECELLHOME_H__ +#define __FREECELLHOME_H__ + +#include "CardStack.h" + +class FreeCellHome : public CardStack +{ + Q_OBJECT +public: + FreeCellHome(); + ~FreeCellHome(); + + inline bool isStackComplete(){return getCardVector().size()==PlayingCard::MaxCardIndex;} + + inline int score() const {return getCardVector().size();} + bool canAddCards(const PlayingCardVector &); +}; + +#endif // __FREECELLHOME_H__ diff --git a/plugins/qsolocards_plugin/FreeCellStack.cpp b/plugins/qsolocards_plugin/FreeCellStack.cpp new file mode 100644 index 000000000..978e2f6f4 --- /dev/null +++ b/plugins/qsolocards_plugin/FreeCellStack.cpp @@ -0,0 +1,95 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "FreeCellStack.h" + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +FreeCellStack::FreeCellStack() + :m_cheat(false), + m_maxMoveCards(1) +{ +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +FreeCellStack::~FreeCellStack() +{ +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +bool FreeCellStack::canAddCards(const PlayingCardVector & newCardVector) +{ + if (m_cheat) + { + return true; + } + + bool rc=false; + const PlayingCardVector & cardVector=this->getCardVector(); + + if (newCardVector.size()>0) + { + // if there are no cards in the stack then we will accept any cards + if (0==cardVector.size()) + { + rc=true; + } + else if (cardVector.size()>0 && + (cardVector[cardVector.size()-1].isRed() ^ newCardVector[0].isRed()) && + cardVector[cardVector.size()-1].isPrevCardIndex(newCardVector[0])) + { + rc=true; + } + } + + return rc; +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +bool FreeCellStack::canMoveCard(unsigned int index) const +{ + bool rc=false; + const PlayingCardVector & cardVector=this->getCardVector(); + + if (index. +*/ + +#ifndef __FREECELLSTACK_H__ +#define __FREECELLSTACK_H__ + +#include "VCardStack.h" + +class FreeCellStack : public VCardStack +{ + Q_OBJECT +public: + FreeCellStack(); + ~FreeCellStack(); + inline bool isCheating() const{return m_cheat;} + + inline void setCheat(bool cheat=true){m_cheat=cheat;} + + bool canAddCards(const PlayingCardVector &); + + inline void setMaxMoveCards(unsigned int maxMoveCards){m_maxMoveCards=((maxMoveCards>1)?(maxMoveCards):(1));} +protected: + bool canMoveCard(unsigned int index) const; + +private: + bool m_cheat; + unsigned int m_maxMoveCards; +}; + +#endif // __FREECELLSTACK_H__ diff --git a/plugins/qsolocards_plugin/GameBoard.cpp b/plugins/qsolocards_plugin/GameBoard.cpp new file mode 100644 index 000000000..d438b7ce6 --- /dev/null +++ b/plugins/qsolocards_plugin/GameBoard.cpp @@ -0,0 +1,434 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "GameBoard.h" +#include +#include "CardPixmaps.h" +#include +#include +#include + +#include "CardAnimationLock.h" + +#include + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +GameBoard::GameBoard(QWidget * pParent, + const QString & gameName, + const QString & gameSettingsId) + :QGraphicsView(pParent), + m_scene(), + m_sToSAniMove(), + m_dealAni(), + m_gameName(gameName), + m_gameSettingsId(gameSettingsId), + m_gamePixmap(":/images/sol32x32.png"), + m_undoStack(), + m_redoStack(), + m_helpFile(""), + m_numColsOrRows(1), + m_resizeType(ResizeByWidth), + m_demoRunning(false), + m_pDemoSrcPrev(NULL), + m_pDemoDstPrev(NULL), + m_demoCardsPrev(), + m_demoCardAniTime(GameBoard::DemoNormalCardAniTime), + m_stacksCreated(false) +{ + // set the background image + this->setBackgroundBrush(QImage(":/images/greenfelt.png")); + this->setCacheMode(QGraphicsView::CacheBackground); + + // add the scene to the view. + // and set it to rescale. + this->setScene(&m_scene); + + // turnoff the scroll bars on the view + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + + // hook up the animation signal for stack to stack moves. This will enable us + // to update things just like it was a drag and drop move + this->connect(&m_sToSAniMove,SIGNAL(cardsMoved(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + + this->connect(&m_dealAni,SIGNAL(cardsMoved(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); +} + +/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////// +GameBoard::~GameBoard() +{ + CardAnimationLock::getInst().setDemoMode(false); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::setCardResizeAlg(unsigned int colsOrRows,CardResizeType resizeType) +{ + if (colsOrRows<1) + { + colsOrRows=1; + } + + m_numColsOrRows=colsOrRows; + + m_resizeType=resizeType; + + this->updateCardSize(this->size()); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::updateCardSize(const QSize & newSize) +{ + if (GameBoard::ResizeByHeight==m_resizeType) + { + CardPixmaps::getInst().setCardHeight((newSize.height()-(LayoutSpacing*(m_numColsOrRows+1)))/m_numColsOrRows); + } + else + { + CardPixmaps::getInst().setCardWidth((newSize.width()-(LayoutSpacing*(m_numColsOrRows+1)))/m_numColsOrRows); + } +} +//////////////////////////////////////////////////////////////////////////////// +// ok go through and restore the last state of all stacks +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::undoMove() +{ + if (!this->m_undoStack.empty()) + { + CardMoveRecord moveRecord(m_undoStack.top()); + + CardStack::processCardMoveRecord(CardStack::UndoMove,m_undoStack.top()); + m_undoStack.pop(); + + // if we no longer have any undo info let users know. + if (!this->canUndoMove()) + { + emit undoAvail(false); + } + + bool canRedo=this->canRedoMove(); + + m_redoStack.push(moveRecord); + + // if we didn't have a redo previously and now have one + // emit a signal to tell listeners about it. + if (!canRedo) + { + emit redoAvail(true); + } + + // calc the score with the changes + this->calcScore(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// ok go through and redo the last state of all stacks +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::redoMove() +{ + if (!this->m_redoStack.empty()) + { + CardMoveRecord moveRecord(m_redoStack.top()); + + CardStack::processCardMoveRecord(CardStack::RedoMove,m_redoStack.top()); + m_redoStack.pop(); + + // emit a signal that we are out of redo info + if (!this->canRedoMove()) + { + emit redoAvail(false); + } + + bool canUndo=this->canUndoMove(); + m_undoStack.push(moveRecord); + + // emit a signal that we now have undo info + if (!canUndo) + { + emit undoAvail(true); + } + + // calc the score with the changes + this->calcScore(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +bool GameBoard::canUndoMove() const +{ + return !m_undoStack.empty(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +bool GameBoard::canRedoMove() const +{ + return !m_redoStack.empty(); +} + +//////////////////////////////////////////////////////////////////////////////// +// adding some to the undo stack also means that the redo stack is cleared. +// since +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::addUndoMove(const CardMoveRecord &moveRecord) +{ + bool canUndo=this->canUndoMove(); + + m_undoStack.push(moveRecord); + + // send a signal that we now have undo info + if (!canUndo) + { + emit undoAvail(true); + } + + // clear the redo stack because we have made a move + while(!m_redoStack.empty()) + { + m_redoStack.pop(); + } + + // since we have made a move the redo stack is now gone. + emit redoAvail(false); + + // calc the score with the changes + this->calcScore(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::clearUndoRedoStacks() +{ + while (!this->m_undoStack.empty()) + { + m_undoStack.pop(); + } + + while (!this->m_redoStack.empty()) + { + m_redoStack.pop(); + } + + emit undoAvail(false); + emit redoAvail(false); + + // calc the score with the changes + this->calcScore(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::restartGame() +{ + this->stopDemo(); + while (!this->m_undoStack.empty()) + { + CardMoveRecord moveRecord(m_undoStack.top()); + + CardStack::processCardMoveRecord(CardStack::UndoMove,m_undoStack.top()); + m_undoStack.pop(); + } + + this->clearUndoRedoStacks(); + + // update the screen for the new layout + this->update(); + + // calc the score with the changes + this->calcScore(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::showHint() +{ + unsigned int index; + CardStack * pFromStack=NULL; + CardStack * pToStack=NULL; + + // show hint if we found one. + if (this->getHint(pFromStack,index,pToStack) && pToStack && pFromStack) + { + CardStack::showHint(pFromStack,index,pToStack); + } + else + { + QMessageBox::critical(this,this->gameName(), + tr("No move found involving full sets of movable cards. " + "It might be possible to make a move not using the full set of movable cards.").trimmed()); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::startDemo(GameBoard::DemoCardAniTime demoCardAniTime) +{ + if (!m_demoRunning) + { + m_pDemoSrcPrev=NULL; + m_pDemoDstPrev=NULL; + m_demoCardsPrev.clear(); + + m_demoCardAniTime=demoCardAniTime; + + m_demoRunning=true; + CardAnimationLock::getInst().setDemoMode(true); + emit demoStarted(); + runDemo(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::stopDemo() +{ + if (m_demoRunning) + { + m_demoRunning=false; + CardAnimationLock::getInst().setDemoMode(false); + emit demoStopped(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::newGame() +{ + m_dealAni.stopAni(); + m_sToSAniMove.stopAni(); + + stopDemo(); + + CardStack::clearAllStacks(); + CardStack::updateAllStacks(); + + // clear the undo and redo info + this->clearUndoRedoStacks(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::slotCardsMoved(const CardMoveRecord & moveRecord) +{ + // calc the score with the changes + this->calcScore(); + + // if the move record is not empty add it. + if (!moveRecord.empty()) + { + this->addUndoMove(moveRecord); + } + + if (this->hasDemo()&& this->isDemoRunning()) + { + runDemo(); + } + // if all suits are sent home the game is over. Show a dialog stating that + // and start the game over. + if (this->isGameWon()) + { + QMessageBox::information(this,this->gameName(),tr("Congratulations you won!").trimmed()); + this->newGame(); + } + else if (CardAnimationLock::getInst().animationsEnabled() && + this->hasDemo() && !this->isDemoRunning() && + this->isGameWonNotComplete()) + { + this->startDemo(DemoEndGameCardAniTime); + } + +} + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void GameBoard::resizeEvent (QResizeEvent * event) +{ + QGraphicsView::resizeEvent(event); + + this->updateCardSize(event->size()); + this->m_scene.setSceneRect(QRectF(QPointF(0,0),event->size())); + + if (!m_stacksCreated) + { + m_stacksCreated=true; + this->createStacks(); + } + + CardStack::updateAllStacks(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +bool GameBoard::runDemo(bool stopWhenNoMore) +{ + bool rc=false; + unsigned int index; + CardStack * pFromStack=NULL; + CardStack * pToStack=NULL; + PlayingCardVector moveCards; + CardMoveRecord moveRecord; + + // here we are looking to stop moving cards back and forth over and over + // between two stacks + if (this->getHint(pFromStack,index,pToStack) && pToStack && pFromStack) + { + rc=true; + if (pFromStack->removeCardsStartingAt(index,moveCards,moveRecord,true)) + { + if (m_pDemoSrcPrev==pToStack && + m_pDemoDstPrev==pFromStack && + m_demoCardsPrev==moveCards) + { + rc=false; + } + } + } + + // if there is a hint perform the move + if (rc) + { + pToStack->addCards(moveCards,moveRecord,true); + + m_pDemoSrcPrev=pFromStack; + m_pDemoDstPrev=pToStack; + m_demoCardsPrev=moveCards; + + this->m_sToSAniMove.moveCards(moveRecord,m_demoCardAniTime); + } + else if (stopWhenNoMore) + { + stopDemo(); + rc=false; + } + else + { + rc=false; + } + + return rc; +} diff --git a/plugins/qsolocards_plugin/GameBoard.h b/plugins/qsolocards_plugin/GameBoard.h new file mode 100644 index 000000000..3b68acb14 --- /dev/null +++ b/plugins/qsolocards_plugin/GameBoard.h @@ -0,0 +1,213 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef GAMEBOARD_H +#define GAMEBOARD_H + +#include +#include +#include +#include +#include +#include + +#include + +#include "CardStack.h" +#include "CardMoveRecord.h" +#include "StackToStackAniMove.h" +#include "DealAnimation.h" + +// Generic base class for a games board +class GameBoard : public QGraphicsView +{ + Q_OBJECT + +public: + enum + { + LayoutSpacing=10 + }; + + enum CardResizeType + { + ResizeByWidth=0, + ResizeByHeight=1 + }; + + enum DemoCardAniTime + { + DemoEndGameCardAniTime=100, + DemoNormalCardAniTime=400 + }; + + GameBoard(QWidget * pWidget, + const QString & gameName, + const QString & gameSettingsId); + virtual ~GameBoard(); + + virtual void setGameName(const QString & gameName){m_gameName=gameName;} + virtual void setGameId(const QString & gameId){ m_gameSettingsId=gameId;} + + // this function show be called in the constructor of classes inheriting from this + // class to set the way that cards will be resized. + virtual void setCardResizeAlg(unsigned int colsOrRows,CardResizeType resizeType); + + // this function is called when setCardResizeAlg is called or when the GameBoard is resized. + virtual void updateCardSize(const QSize & newSize); + + // undoMove and redoMove pop items off there respective stacks + // and process the move. They also call calcScore to update the + // score. + // signals undoAvail and redoAvail are also emitted if necessary + virtual void undoMove(); + virtual void redoMove(); + + virtual bool canUndoMove() const; + virtual bool canRedoMove() const; + + // addUndoMove will add the move to the undo stack. clear the redo stack + // and call calcScore. + // signals undoAvail and redoAvail are also emitted if necessary + virtual void addUndoMove(const CardMoveRecord &); + + // will clear all contents of both the redo and undo stacks, call calcScore, and + // signals undoAvail and redoAvail are also emitted if necessary + virtual void clearUndoRedoStacks(); + + virtual void restartGame(); + + virtual void showHint(); + + // this function is split into a separate virtual function + // it will allow the function to be used both for showing a + // hint and for demo mode. + virtual bool getHint(CardStack * & pSrcWidget, + unsigned int & srcStackIndex, + CardStack * & pDstWidget)=0; + + virtual void startDemo(DemoCardAniTime demoCardAniTime=DemoNormalCardAniTime); + virtual void stopDemo(); + inline bool isDemoRunning() const { return m_demoRunning;} + + inline DemoCardAniTime getDemoCardAniTime()const{return m_demoCardAniTime;} + + // override this function if the game is implementing demo mode. + // The runDemo() function will need to be called after + // each move. Bestway would be to add something at the end of the slot + // that catches the cardsMoved signal from the move animations. + // By default runDemo will call getHint and if a move is returned it will + // perform the move. If something else is desired the function can be overridden. + // it also returns a bool. So, if it is overridden the base class can be called + // first to see if there is a basic move. If not something else can be done. + virtual bool hasDemo() const {return false;} + + virtual void newGame(); + + virtual bool isCheating() const=0; + + virtual void setCheat(bool cheat)=0; + + virtual void addGameMenuItems(QMenu &)=0; + + virtual void loadSettings(const QSettings & settings)=0; + virtual void saveSettings(QSettings & settings)=0; + + virtual bool supportsScore() const=0; + + virtual const QString & helpFile() const { return m_helpFile;} + + const QPixmap & getGamePixmap() const{return m_gamePixmap;} + + const QString & gameName() const{return m_gameName;} + + const QString & gameSettingsId() const {return m_gameSettingsId;} + +public slots: + virtual void slotCardsMoved(const CardMoveRecord &); + +signals: + // this signal should be emitted on a state change of undo from available + // to unavailable or unavailable to available by sub classes + void undoAvail(bool avail); + + // this signal should be emitted on a state change of redo from available + // to unavailable or unavailable to available by sub classes + void redoAvail(bool avail); + + // signal emitted by a game when its score changed. + // The string is extra info the game can pass to show + // additional info. + void scoreChanged(int score,const QString &); + + + void demoStarted(); + void demoStopped(); + +protected: + virtual void calcScore()=0; // called when the score is changed by add to rewinding the undo and redo stacks + // subclasses should override for customizing score calculations + + virtual void setHelpFile(const QString & helpFile){m_helpFile=helpFile;} + + virtual void resizeEvent (QResizeEvent * event); + + // called to create the CardStacks for the game. + virtual void createStacks()=0; + + // this function can be overloaded for more complex behavior for the demo. By default it + // will just peform the hint returned if it found one. + virtual bool runDemo(bool stopWhenNoMore=true); + + // implement in subclasses to determine if the game is won. + virtual bool isGameWon()const=0; + + // implement in subclasses when cards are in position that the + // game will be won. When this function returns true the demo + // will be started if it is available to move the remaining cards + virtual bool isGameWonNotComplete()const=0; + + + QGraphicsScene m_scene; + StackToStackAniMove m_sToSAniMove; + DealAnimation m_dealAni; + +private: + QString m_gameName; + QString m_gameSettingsId; + QPixmap m_gamePixmap; + + std::stack m_undoStack; // stack to keep track of moves + std::stack m_redoStack; // stack to keep track of moves + + QString m_helpFile; + + unsigned int m_numColsOrRows; + CardResizeType m_resizeType; + + bool m_demoRunning; + + CardStack * m_pDemoSrcPrev; + CardStack * m_pDemoDstPrev; + PlayingCardVector m_demoCardsPrev; + DemoCardAniTime m_demoCardAniTime; + + bool m_stacksCreated; // variable to keep track if we have called createStacks +}; + +#endif // GAMEBOARD_H diff --git a/plugins/qsolocards_plugin/GameMgr.cpp b/plugins/qsolocards_plugin/GameMgr.cpp new file mode 100644 index 000000000..aedd5b183 --- /dev/null +++ b/plugins/qsolocards_plugin/GameMgr.cpp @@ -0,0 +1,107 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "GameMgr.h" +#include "SpiderBoard.h" +#include "Spider3DeckBoard.h" +#include "SpideretteBoard.h" +#include "KlondikeBoard.h" +#include "FreeCellBoard.h" +#include "YukonBoard.h" +#include + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +GameMgr::GameMgr() + :m_lastGameId(GameMgr::NoGame) +{ + // build the list of games + m_gameDspNameList<m_gameDspNameList.at(i),pGameGroup); + pCurrAction->setData(QVariant(i)); + pCurrAction->setCheckable(true); + if (i==this->m_lastGameId) + { + pCurrAction->setChecked(true); + } + menu.addAction(pCurrAction); + } +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +GameBoard * GameMgr::getGame(GameId gameId) +{ + GameBoard * pGame=NULL; + + switch(gameId) + { + case GameMgr::Spider: + pGame=new SpiderBoard(NULL); + break; + case GameMgr::Klondike: + pGame=new KlondikeBoard(NULL); + break; + case GameMgr::FreeCell: + pGame=new FreeCellBoard; + break; + case GameMgr::ThreeDeckSpider: + pGame=new Spider3DeckBoard; + break; + case GameMgr::Spiderette: + pGame=new SpideretteBoard; + break; + case GameMgr::Yukon: + pGame=new YukonBoard; + break; + case GameMgr::NoGame: + default: + pGame=NULL; + break; + }; + + // if we were able to create a valid game board. Set the last + // game id + if (NULL!=pGame) + { + this->m_lastGameId=gameId; + } + + return pGame; +} diff --git a/plugins/qsolocards_plugin/GameMgr.h b/plugins/qsolocards_plugin/GameMgr.h new file mode 100644 index 000000000..a2d408148 --- /dev/null +++ b/plugins/qsolocards_plugin/GameMgr.h @@ -0,0 +1,62 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef GAMEMGR_H +#define GAMEMGR_H + +#include "GameBoard.h" +#include +#include + +class GameMgr +{ +public: + enum GameId + { + Spider=0, + Klondike=1, + FreeCell=2, + ThreeDeckSpider=3, + Spiderette=4, + Yukon=5, + NoGame=6, + DefaultGame=Spider + }; + GameMgr(); + virtual ~GameMgr(); + + // Add menu items for the games. A menu item will be created with the data object set + // as an integer with the GameId value. The caller can connect to the menus triggered + // signal and then get the data object from the QAction and call getGame with the id + // to create a game board. + void buildGameListMenu(QMenu & menu) const; + + // get a game based on the gameId. The returned GameBoard ptr + // is the responsibility of the caller to delete. If the game id is not valid + // NULL is returned. + GameBoard * getGame(GameId gameId=DefaultGame); + + GameId getGameId() const {return m_lastGameId;} + +private: + GameId m_lastGameId; // the game id of the game requested at the last call to + // getGame. The default is NoGame. + QStringList m_gameDspNameList; +}; + +#endif // GAMEMGR_H diff --git a/plugins/qsolocards_plugin/Help.cpp b/plugins/qsolocards_plugin/Help.cpp new file mode 100644 index 000000000..77675f838 --- /dev/null +++ b/plugins/qsolocards_plugin/Help.cpp @@ -0,0 +1,76 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "Help.h" + +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +Help::Help(QWidget * pParent,const QString & helpFile) + :QDialog(pParent), + m_pBrowser(NULL) +{ + this->setWindowTitle(tr("QSoloCards: Game Help").trimmed()); + + this->setAttribute(Qt::WA_DeleteOnClose,true); + + m_pBrowser=new QTextBrowser; + + QHBoxLayout * pLayout=new QHBoxLayout; + + pLayout->addWidget(m_pBrowser,20); + + this->setLayout(pLayout); + + this->setHelpFile(helpFile); +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +Help::~Help() +{ +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +void Help::setHelpFile(const QString & helpFile) +{ + QFile file(helpFile); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + return; + } + + QTextStream in(&file); + QString line = in.readLine(); + + QString text; + + while (!line.isNull()) + { + text.append(line); + text.append(" "); + line = in.readLine(); + } + + m_pBrowser->setHtml(text); +} + diff --git a/plugins/qsolocards_plugin/Help.h b/plugins/qsolocards_plugin/Help.h new file mode 100644 index 000000000..18f349d06 --- /dev/null +++ b/plugins/qsolocards_plugin/Help.h @@ -0,0 +1,40 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef HELP_H +#define HELP_H + +#include +#include +#include + +class Help: public QDialog +{ + Q_OBJECT +public: + Help(QWidget * pParent,const QString & helpFile); + ~Help(); + + void setHelpFile(const QString &); + +private: + + QTextBrowser * m_pBrowser; +}; + +#endif // HELP_H diff --git a/plugins/qsolocards_plugin/KlondikeBoard.cpp b/plugins/qsolocards_plugin/KlondikeBoard.cpp new file mode 100644 index 000000000..ef6c7eed3 --- /dev/null +++ b/plugins/qsolocards_plugin/KlondikeBoard.cpp @@ -0,0 +1,770 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "KlondikeBoard.h" +#include + +#include "CardDeck.h" +#include "CardPixmaps.h" +#include "CardAnimationLock.h" + +const QString KlondikeBoard::GameTypeKeyStr("GameType"); + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +KlondikeBoard::KlondikeBoard(QWidget * pWidget) + :GameBoard(pWidget,QString(tr("Klondike Solitaire")).trimmed(),QString("Klondike")), + m_pDeck(NULL), + m_pFlipDeck(NULL), + m_homeVector(), + m_stackVector(), + m_cheat(false), + m_gameType(KlondikeBoard::FlipOne), + m_flipNum(0), + m_sToSFlipAni() +{ + this->setHelpFile(":/help/KlondikeHelp.html"); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +KlondikeBoard::~KlondikeBoard() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::undoMove() +{ + bool emptyBefore=false; + bool emptyAfter=false; + + emptyBefore=m_pDeck->isEmpty(); + + GameBoard::undoMove(); + + emptyAfter=m_pDeck->isEmpty(); + + // if we undone a redeal decrement the flip count + if (!emptyBefore && emptyAfter) + { + this->m_flipNum--; + if (!(KlondikeBoard::FlipOne==this->m_gameType && + this->m_flipNum<2) && + !(KlondikeBoard::FlipThree==this->m_gameType)) + { + this->m_pDeck->setShowRedealCircle(false); + this->m_pDeck->updateStack(); + } + else + { + this->m_pDeck->setShowRedealCircle(true); + this->m_pDeck->updateStack(); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::redoMove() +{ + bool emptyBefore=false; + bool emptyAfter=false; + + emptyBefore=m_pDeck->isEmpty(); + + GameBoard::redoMove(); + + emptyAfter=m_pDeck->isEmpty(); + + // if we are redoing a redeal increment the flip count + if (emptyBefore && !emptyAfter) + { + this->m_flipNum++; + + if (!(KlondikeBoard::FlipOne==this->m_gameType && + this->m_flipNum<2) && + !(KlondikeBoard::FlipThree==this->m_gameType)) + { + this->m_pDeck->setShowRedealCircle(false); + this->m_pDeck->updateStack(); + } + else + { + this->m_pDeck->setShowRedealCircle(true); + this->m_pDeck->updateStack(); + } + } + +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::restartGame() +{ + // call the base class to rewind the undo stack + GameBoard::restartGame(); + + // reset the flip count + this->m_flipNum=0; + // and set the redeal circle depending on game type + if (KlondikeBoard::NoRedeals==this->m_gameType) + { + this->m_pDeck->setShowRedealCircle(false); + } + else + { + this->m_pDeck->setShowRedealCircle(true); + } + +} + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +bool KlondikeBoard::getHint(CardStack * & pFromStack, + unsigned int & index, + CardStack * & pToStack) +{ + // first see if we can move anything to one of the home stacks. + PlayingCardVector moveCards; + unsigned int i; + bool matchFound=false; + + + // ok check to see if we have a card from the stacks that can + // be added to a home stack + for (i=0;im_stackVector.size() && !matchFound;i++) + { + if (!this->m_stackVector[i]->isEmpty()) + { + const PlayingCardVector & currCards=this->m_stackVector[i]->getCardVector(); + moveCards.clear(); + moveCards.push_back(currCards[currCards.size()-1]); // just get the last card since we are moving to the home stack + index=currCards.size()-1; + + for (unsigned int j=0;jm_homeVector.size();j++) + { + if (this->m_homeVector[j]->canAddCards(moveCards)) + { + pToStack=this->m_homeVector[j]; + pFromStack=this->m_stackVector[i]; + matchFound=true; + break; + } + } + } + } + + // next check for stack to stack moves. + if (!matchFound) + { + moveCards.clear(); + pToStack=NULL; + pFromStack=NULL; + + for (i=0;im_stackVector.size() && !matchFound;i++) + { + moveCards.clear(); + if (!this->m_stackVector[i]->isEmpty() && + this->m_stackVector[i]->getMovableCards(moveCards,index)) + { + // we want to eliminate a move that starts with a stack that + // has a faceup king as the first card. We will just end up + // suggesting to move it to another empty row. Which is not + // really a move. + if (PlayingCard::King==moveCards[0].getIndex() && + moveCards.size()== this->m_stackVector[i]->getCardVector().size()) + { + continue; + } + for (unsigned int j=0;jm_stackVector.size();j++) + { + if (this->m_stackVector[i]!=this->m_stackVector[j] && + this->m_stackVector[j]->canAddCards(moveCards)) + { + pToStack=this->m_stackVector[j]; + pFromStack=this->m_stackVector[i]; + matchFound=true; + break; + } + } + } + } + } + + + // check the flip deck. We can just call getMovableCards for it + // since, it will always be just one card. + if (!matchFound) + { + moveCards.clear(); + pToStack=NULL; + pFromStack=NULL; + + if (!this->m_pFlipDeck->isEmpty() && + this->m_pFlipDeck->getMovableCards(moveCards,index)) + { + // first see if we can send a card to one of the home + // stacks + for(i=0;im_homeVector.size();i++) + { + if (this->m_homeVector[i]->canAddCards(moveCards)) + { + pToStack=this->m_homeVector[i]; + pFromStack=this->m_pFlipDeck; + matchFound=true; + break; + } + } + + // if no match now check to see if we can add the card to the + // normal stacks + if (!matchFound) + { + for(i=0;im_stackVector.size();i++) + { + if (this->m_stackVector[i]->canAddCards(moveCards)) + { + pToStack=this->m_stackVector[i]; + pFromStack=this->m_pFlipDeck; + matchFound=true; + break; + } + } + } + } + } + + + return matchFound; +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::newGame() +{ + // stop any animation of flipping cards + m_sToSFlipAni.stopAni(); + // call the base class + GameBoard::newGame(); + + CardDeck deck; + unsigned int i; + + this->m_flipNum=0; + + // only show the redeal circle in the cases that we can redeal + if (KlondikeBoard::NoRedeals==this->m_gameType) + { + this->m_pDeck->setShowRedealCircle(false); + } + else + { + this->m_pDeck->setShowRedealCircle(true); + } + + + this->m_pFlipDeck->cardsToShow(((KlondikeBoard::FlipThree==this->m_gameType)?3:1)); + + + + while(!deck.isEmpty()) + { + this->m_pDeck->addCard(deck.next()); + } + + + DealItemVector dealItemVector; + + + // Create the dealItemVector to direct the DealAnimation object on + // how to deal the cards. + for (i=0;im_stackVector.size();i++) + { + dealItemVector.push_back(DealItem(this->m_stackVector[i],m_pDeck)); + + unsigned int j; + + for (j=0;jsetShortcut(QKeySequence(Qt::CTRL + Qt::Key_1)); + pFlipOneAction->setCheckable(true); + connect(pFlipOneAction,SIGNAL(triggered()), + this,SLOT(slotSetFlipOne())); + + QAction * pFlipThreeAction=new QAction(tr("Flip three").trimmed(),pFlipCardsGroup); + pFlipThreeAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_3)); + pFlipThreeAction->setCheckable(true); + connect(pFlipThreeAction,SIGNAL(triggered()), + this,SLOT(slotSetFlipThree())); + + QAction * pNoRedealsAction=new QAction(tr("No redeals (flip one)").trimmed(),pFlipCardsGroup); + pNoRedealsAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_0)); + pNoRedealsAction->setCheckable(true); + connect(pNoRedealsAction,SIGNAL(triggered()), + this,SLOT(slotSetNoRedeals())); + + // select the correct item in the list + switch (this->m_gameType) + { + case KlondikeBoard::FlipOne: + pFlipOneAction->setChecked(true); + break; + + case KlondikeBoard::FlipThree: + pFlipThreeAction->setChecked(true); + break; + + case KlondikeBoard::NoRedeals: + pNoRedealsAction->setChecked(true); + break; + }; + + + menu.addAction(pFlipOneAction); + menu.addAction(pFlipThreeAction); + menu.addAction(pNoRedealsAction); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::loadSettings(const QSettings & settings) +{ + int gameType=settings.value(this->GameTypeKeyStr,KlondikeBoard::FlipOne).toInt(); + + switch (gameType) + { + case KlondikeBoard::NoRedeals: + this->m_gameType=KlondikeBoard::NoRedeals; + break; + + case KlondikeBoard::FlipThree: + this->m_gameType=KlondikeBoard::FlipThree; + break; + + case KlondikeBoard::FlipOne: + default: + this->m_gameType=KlondikeBoard::FlipOne; + break; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::saveSettings(QSettings & settings) +{ + settings.setValue(this->GameTypeKeyStr,this->m_gameType); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::setCheat(bool cheat) +{ + this->m_cheat=cheat; + + for(unsigned int i=0;im_stackVector.size();i++) + { + m_stackVector[i]->setCheat(cheat); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::slotFlipCards(CardStack * pCardStack, + unsigned int index) +{ + Q_UNUSED(pCardStack); + Q_UNUSED(index); + // just use the game type to indicate the number of flip cards + // the enum is assigned the number of cards that will be flipped + // the exception is the NoRedeals in that case we are just flipping + // one card. + unsigned int numFlipCards=this->m_gameType; + if (KlondikeBoard::NoRedeals==this->m_gameType) + { + numFlipCards=KlondikeBoard::FlipOne; + } + + + m_sToSFlipAni.moveCards(m_pFlipDeck,m_pDeck,numFlipCards); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::slotRedealCards(CardStack * pCardStack) +{ + Q_UNUSED(pCardStack); + // ignore an attempt to redeal if the game type is NoRedeals. + // otherwise take all the cards from the Flip stack and put them back + // in the deal stack + if (KlondikeBoard::NoRedeals!=this->m_gameType && + ((KlondikeBoard::FlipOne==this->m_gameType && + this->m_flipNum<2) || + KlondikeBoard::FlipThree==this->m_gameType)) + { + unsigned int numFlipCards=this->m_gameType; + if (KlondikeBoard::NoRedeals==this->m_gameType) + { + numFlipCards=KlondikeBoard::FlipOne; + } + + // flip the cards back. Flip the cards back over. Show the bottom 3 if in FlipThree mode. Otherwise + // just show one. + m_sToSFlipAni.moveCards(m_pDeck,m_pFlipDeck,this->m_pFlipDeck->getCardVector().size(),numFlipCards); + + this->m_flipNum++; + + if (!(KlondikeBoard::FlipOne==this->m_gameType && + this->m_flipNum<2) && + !(KlondikeBoard::FlipThree==this->m_gameType)) + { + this->m_pDeck->setShowRedealCircle(false); + } + } + else + { + // if a demo is running stop it. Can't redeal any more. + this->stopDemo(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::slotStackCardsClicked(CardStack * pCardStack, + const PlayingCardVector & cardVector, + const CardMoveRecord & startMoveRecord) +{ + unsigned int i=0; + CardStack * pFoundStack=NULL; + + if (NULL==pCardStack) + { + return; + } + + // first see if the card can be added to the sent home stack + if (cardVector.size()==1) + { + for(i=0;im_homeVector.size();i++) + { + if (pCardStack!=this->m_homeVector[i] && + this->m_homeVector[i]->canAddCards(cardVector)) + { + pFoundStack=this->m_homeVector[i]; + break; + } + } + } + + // if we did not find a match look at the stacks. + // the home will use the same logic so just call that slot + if (NULL==pFoundStack) + { + this->slotHomeCardsClicked(pCardStack,cardVector,startMoveRecord); + } + + if (pFoundStack) + { + CardMoveRecord moveRecord(startMoveRecord); + pFoundStack->addCards(cardVector,moveRecord,true); + + // perform the move of the cards and animate it if animations + // are enabled + m_sToSAniMove.moveCards(moveRecord); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::slotHomeCardsClicked(CardStack * pCardStack, + const PlayingCardVector & cardVector, + const CardMoveRecord & startMoveRecord) +{ + unsigned int i=0; + CardStack * pFoundStack=NULL; + + if (NULL==pCardStack) + { + return; + } + + for(i=0;im_stackVector.size();i++) + { + if (pCardStack!=this->m_stackVector[i] && + this->m_stackVector[i]->canAddCards(cardVector)) + { + pFoundStack=this->m_stackVector[i]; + break; + } + } + + if (pFoundStack) + { + CardMoveRecord moveRecord(startMoveRecord); + pFoundStack->addCards(cardVector,moveRecord,true); + + // perform the move of the cards and animate it if animations + // are enabled + m_sToSAniMove.moveCards(moveRecord); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::slotSetNoRedeals() +{ + this->m_gameType=KlondikeBoard::NoRedeals; + this->newGame(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::slotSetFlipOne() +{ + this->m_gameType=KlondikeBoard::FlipOne; + this->newGame(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::slotSetFlipThree() +{ + this->m_gameType=KlondikeBoard::FlipThree; + this->newGame(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::calcScore() +{ + int score=0; + + for(unsigned int i=0;im_homeVector.size();i++) + { + score+=this->m_homeVector[i]->score(); + } + + emit scoreChanged(score,""); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::resizeEvent (QResizeEvent * event) +{ + unsigned int i; + + GameBoard::resizeEvent(event); + + + QSize cardSize(CardPixmaps::getInst().getCardSize()); + + QPointF currPos(GameBoard::LayoutSpacing,GameBoard::LayoutSpacing); + + m_pDeck->setPos(currPos); + + currPos.rx()+=GameBoard::LayoutSpacing + cardSize.width(); + + m_pFlipDeck->setPos(currPos); + + currPos.rx()+=GameBoard::LayoutSpacing*3 + cardSize.width()*3; + + + for (i=0;isetPos(currPos); + currPos.rx()+=cardSize.width()+GameBoard::LayoutSpacing; + } + + currPos.setY(GameBoard::LayoutSpacing*2+cardSize.height()); + currPos.setX(GameBoard::LayoutSpacing*2+cardSize.width()); + for (i=0;isetPos(currPos); + currPos.rx()+=cardSize.width()+GameBoard::LayoutSpacing; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +bool KlondikeBoard::runDemo(bool stopWhenNoMore) +{ + bool rc=true; + + if (!GameBoard::runDemo(false)) + { + if (!m_pDeck->isEmpty()) + { + this->slotFlipCards(); + } + else if (!m_pFlipDeck->isEmpty()) + { + this->slotRedealCards(); + } + else if (stopWhenNoMore) + { + stopDemo(); + rc=false; + } + else + { + rc=false; + } + } + + return rc; + +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void KlondikeBoard::createStacks() +{ + setCardResizeAlg(8,ResizeByWidth); + + + unsigned int i; + + // first create the home widgets where the cards need to be eventually stacked to + // win the game. + for(i=0;i<4;i++) + { + this->m_homeVector.push_back(new KlondikeHomeStack); + this->m_scene.addItem(m_homeVector[i]); + this->connect(this->m_homeVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + this->connect(this->m_homeVector[i],SIGNAL(movableCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotHomeCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord))); + } + + // now create the 7 rows for the stacks. + for (i=0;i<7;i++) + { + this->m_stackVector.push_back(new KlondikeStack); + this->m_scene.addItem(m_stackVector[i]); + this->connect(this->m_stackVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + this->connect(this->m_stackVector[i],SIGNAL(movableCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotStackCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord))); + } + + this->m_pDeck=new CardStack; + this->m_scene.addItem(this->m_pDeck); + + this->m_pDeck->setShowRedealCircle(); + + + // if a card is double clicked that means we need to flip over the next set of cards + this->connect(this->m_pDeck,SIGNAL(cardClicked(CardStack*,uint)), + this,SLOT(slotFlipCards(CardStack*,uint))); + + // if there are no cards in the deck and the pad is clicked that means we need + // to flip the deck back over. If the version of the game is not No redeals. + this->connect(this->m_pDeck,SIGNAL(padClicked(CardStack*)), + this,SLOT(slotRedealCards(CardStack*))); + + this->m_pFlipDeck=new KlondikeFlipStack; + this->m_scene.addItem(this->m_pFlipDeck); + + this->connect(this->m_pFlipDeck,SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + this->connect(this->m_pFlipDeck,SIGNAL(movableCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotStackCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord))); + + + + // hook up the animation signal for flipping cards over from the deck to the flip + // stack. And then back. + this->connect(&m_sToSFlipAni,SIGNAL(cardsMoved(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +bool KlondikeBoard::isGameWon()const +{ + bool rc=true; + + for (unsigned int i=0;im_homeVector.size();i++) + { + if (!this->m_homeVector[i]->isStackComplete()) + { + rc=false; + break; + } + } + + return rc; +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +bool KlondikeBoard::isGameWonNotComplete()const +{ + bool rc=false; + + rc=m_pDeck->isEmpty(); + + if (rc) + { + rc=this->m_pFlipDeck->cardsAscendingTopToBottom(); + } + + if (rc) + { + for (unsigned int i=0;im_stackVector.size();i++) + { + if (!(this->m_stackVector[i]->cardsAscendingTopToBottom() && + this->m_stackVector[i]->allCardsFaceUp())) + { + rc=false; + break; + } + } + } + + return rc; + +} diff --git a/plugins/qsolocards_plugin/KlondikeBoard.h b/plugins/qsolocards_plugin/KlondikeBoard.h new file mode 100644 index 000000000..016871466 --- /dev/null +++ b/plugins/qsolocards_plugin/KlondikeBoard.h @@ -0,0 +1,115 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef KLONDIKEBOARD_H +#define KLONDIKEBOARD_H + +#include "GameBoard.h" +#include "KlondikeStack.h" +#include "KlondikeHomeStack.h" +#include "KlondikeFlipStack.h" +#include "CardStack.h" +#include "StackToStackFlipAni.h" + +#include + + +class KlondikeBoard : public GameBoard +{ + Q_OBJECT +public: + enum GameType + { + NoRedeals=0, + FlipOne=1, + FlipThree=3 + }; + + static const QString GameTypeKeyStr; + + KlondikeBoard(QWidget * pParent=NULL); + ~KlondikeBoard(); + + virtual void undoMove(); + virtual void redoMove(); + + void restartGame(); + + bool getHint(CardStack * & pSrcWidget, + unsigned int & srcStackIndex, + CardStack * & pDstWidget); + + inline bool hasDemo() const {return true;} + + void newGame(); + + void addGameMenuItems(QMenu & menu); + + void loadSettings(const QSettings & settings); + void saveSettings(QSettings & settings); + + inline bool isCheating() const {return m_cheat;} + + void setCheat(bool cheat); + + inline bool supportsScore() const{return true;} + +public slots: + void slotFlipCards(CardStack * pCardStackWidget=NULL,unsigned int index=0); + void slotRedealCards(CardStack * pCardStackWidget=NULL); + + void slotStackCardsClicked(CardStack * pCardStackWidget, + const PlayingCardVector & cardVector, + const CardMoveRecord &); + void slotHomeCardsClicked(CardStack * pCardStackWidget, + const PlayingCardVector & cardVector, + const CardMoveRecord &); + + void slotSetNoRedeals(); + void slotSetFlipOne(); + void slotSetFlipThree(); + +protected: + void calcScore(); + + virtual void resizeEvent (QResizeEvent * event); + + bool runDemo(bool stopWhenNoMore=true); + + virtual void createStacks(); + + bool isGameWon()const; + bool isGameWonNotComplete()const; + +private: + + CardStack * m_pDeck; + KlondikeFlipStack * m_pFlipDeck; + + std::vector m_homeVector; // we will have 4 items in this vector one for each suit + std::vector m_stackVector; // we will have 7 items in this vector + + bool m_cheat; + + GameType m_gameType; + unsigned int m_flipNum; + + StackToStackFlipAni m_sToSFlipAni; +}; + +#endif // KLONDIKEBOARD_H diff --git a/plugins/qsolocards_plugin/KlondikeFlipStack.cpp b/plugins/qsolocards_plugin/KlondikeFlipStack.cpp new file mode 100644 index 000000000..3db1d2a8c --- /dev/null +++ b/plugins/qsolocards_plugin/KlondikeFlipStack.cpp @@ -0,0 +1,259 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "KlondikeFlipStack.h" +#include "CardPixmaps.h" + +#include +#include + +const qreal KlondikeFlipStack::ExposedPrecent=.18; + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +KlondikeFlipStack::KlondikeFlipStack() + :CardStack(), + m_bRectVector(), + m_cardsShown(1), + m_firstShowCard(0) +{ +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +KlondikeFlipStack::~KlondikeFlipStack() +{ +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +QPointF KlondikeFlipStack::getGlobalCardAddPt() const +{ + QPointF pt(0,0); + + const PlayingCardVector & cardVector=this->getCardVector(); + + // We are going to do this by the bounding rects and not by actual cards + // in the stacks. That way we can add something before doing animations + // and then update the display when the animation is complete + if (m_bRectVector.size()>0 && cardVector.size()>=m_bRectVector.size()) + { + pt=m_bRectVector[m_bRectVector.size()-1].topLeft(); + + pt.rx()+=this->getOverlapIncrement(cardVector,m_bRectVector.size()-1,m_firstShowCard); + } + + return mapToScene(pt); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +QPointF KlondikeFlipStack::getGlobalLastCardPt() const +{ + QPointF pt(0,0); + + const PlayingCardVector & cardVector=this->getCardVector(); + + // We are going to do this by the bounding rects and not by actual cards + // in the stacks. That way we can add something before doing animations + // and then update the display when the animation is complete + if (m_bRectVector.size()>0 && cardVector.size()>=m_bRectVector.size()) + { + pt=m_bRectVector[m_bRectVector.size()-1].topLeft(); + } + + return mapToScene(pt); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +QPointF KlondikeFlipStack::getGlobalCardPt(int index) const +{ + QPointF pt(0,0); + + if (index>=0 && index<(int)m_bRectVector.size()) + { + pt=m_bRectVector[index].topLeft(); + } + + return mapToScene(pt); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void KlondikeFlipStack::updateStack() +{ + PlayingCardVector cardVector=this->getCardVector(); + m_bRectVector.clear(); + + // if the stack has no cards in it just call the base + // class to render the empty stack. + if (0==cardVector.size()) + { + CardStack::updateStack(); + return; + } + + // figure out the index of the first card to show + if (m_cardsShown>=cardVector.size()) + { + m_firstShowCard=0; + } + else + { + m_firstShowCard=cardVector.size()-m_cardsShown; + } + + // now calc the size of the pixmap we will need + QSize pixmapSize; + + this->calcPixmapSize(cardVector,pixmapSize,m_firstShowCard); + + QPixmap pixmap(pixmapSize); + // for linux the transparent fill must be done before + // we associate the pixmap with the painter + pixmap.fill(Qt::transparent); + + QPainter painter; + + painter.begin(&pixmap); + + QPoint pt(0,0); + QSize cardSize(CardPixmaps::getInst().getCardSize()); + unsigned int i; + + for (i=0;i=m_firstShowCard) + { + bool hl=((hintHighlightIndex()>=0 && hintHighlightIndex()<=(int)i) || + ((cardVector.size()-1==i) && isHighlighted())); + + if (cardVector[i].isFaceUp()) + { + painter.drawPixmap(pt,CardPixmaps::getInst().getCardPixmap(cardVector[i],hl)); + } + else + { + painter.drawPixmap(pt,CardPixmaps::getInst().getCardBackPixmap(hl)); + } + } + + if (cardVector.size()-1==i) + { + m_bRectVector.push_back(QRectF(QPoint(pt.x(),0), + cardSize)); + } + else + { + m_bRectVector.push_back(QRectF(QPoint(pt.x(),0), + QSize(incrementValue,cardSize.height()))); + } + + // increment the point that we are going to paint the + // card pixmap onto this pixmap + pt.rx()+=incrementValue; + } + + painter.end(); + + this->setPixmap(pixmap); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +bool KlondikeFlipStack::getCardIndex(const QPointF & pos,unsigned int & index) +{ + bool rc=false; + unsigned int i; + + // go through the bounding rect backwards. The ones lower for cards that are + // not visible are just place holders. + for(i=m_bRectVector.size();i>0;i--) + { + if (m_bRectVector[i-1].contains(pos)) + { + index=i-1; + rc=true; + break; + } + } + + return rc; +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void KlondikeFlipStack::calcPixmapSize(const PlayingCardVector & cardVector, + QSize & size,unsigned int showIndex) +{ + QSize cardSize(CardPixmaps::getInst().getCardSize()); + unsigned int i; + + size.setWidth(0); + size.setHeight(cardSize.height()); + + for(i=0;igetOverlapIncrement(cardVector,i,showIndex); + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +int KlondikeFlipStack::getOverlapIncrement(const PlayingCardVector & cardVector, + unsigned int index,unsigned int showIndex) const +{ + int increment=0; + + if (index=showIndex) + { + increment=CardPixmaps::getInst().getCardSize().width()*ExposedPrecent; + } + } + + return increment; +} + + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +bool KlondikeFlipStack::canMoveCard(unsigned int index) const +{ + bool rc=false; + + // ok the only time a card can be moved is if the card is the last in the stack. + if (!this->isEmpty() && (index==(this->getCardVector().size()-1))) + { + rc=true; + } + + return rc; +} diff --git a/plugins/qsolocards_plugin/KlondikeFlipStack.h b/plugins/qsolocards_plugin/KlondikeFlipStack.h new file mode 100644 index 000000000..43035f46a --- /dev/null +++ b/plugins/qsolocards_plugin/KlondikeFlipStack.h @@ -0,0 +1,62 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef KLONDIKEFLIPSTACK_H +#define KLONDIKEFLIPSTACK_H + +#include "CardStack.h" +#include +#include + +class KlondikeFlipStack : public CardStack +{ + Q_OBJECT +public: + static const qreal ExposedPrecent; + + KlondikeFlipStack(); + virtual ~KlondikeFlipStack(); + + inline void cardsToShow(unsigned int cardsToShow=1){m_cardsShown=((0==cardsToShow)?1:cardsToShow);} + + // this function gets the point in the scene that a card would be added to this stack. + virtual QPointF getGlobalCardAddPt() const; + virtual QPointF getGlobalLastCardPt() const; + virtual QPointF getGlobalCardPt(int index) const; + + virtual void updateStack(); + +protected: + virtual bool getCardIndex(const QPointF & pos,unsigned int & index); + + void calcPixmapSize(const PlayingCardVector & cardVector, + QSize & size,unsigned int showIndex); + + int getOverlapIncrement(const PlayingCardVector & cardVector, + unsigned int index, + unsigned int showIndex) const; + + bool canMoveCard(unsigned int index) const; + +private: + std::vector m_bRectVector; + unsigned int m_cardsShown; + unsigned int m_firstShowCard; +}; + +#endif // KLONDIKEFLIPSTACK_H diff --git a/plugins/qsolocards_plugin/KlondikeHomeStack.cpp b/plugins/qsolocards_plugin/KlondikeHomeStack.cpp new file mode 100644 index 000000000..acca976a2 --- /dev/null +++ b/plugins/qsolocards_plugin/KlondikeHomeStack.cpp @@ -0,0 +1,75 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "KlondikeHomeStack.h" + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +KlondikeHomeStack::KlondikeHomeStack() + :CardStack() +{ +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +KlondikeHomeStack::~KlondikeHomeStack() +{ +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +bool KlondikeHomeStack::canAddCards(const PlayingCardVector & newCardVector) +{ + bool rc=false; + const PlayingCardVector & cardVector=this->getCardVector(); + + if (1==newCardVector.size()) + { + + if (this->isEmpty() && PlayingCard::Ace==newCardVector[0].getIndex()) + { + rc=true; + } + else if (!this->isEmpty() && + cardVector[cardVector.size()-1].isSameSuit(newCardVector[0]) && + cardVector[cardVector.size()-1].isNextCardIndex(newCardVector[0])) + { + rc=true; + } + } + + return rc; +} + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +bool KlondikeHomeStack::canMoveCard(unsigned int index) const +{ + bool rc=false; + + if (!this->isEmpty()) + { + const PlayingCardVector & cardVector=this->getCardVector(); + + if ((cardVector.size()-1)==index) + { + rc=true; + } + } + return rc; +} diff --git a/plugins/qsolocards_plugin/KlondikeHomeStack.h b/plugins/qsolocards_plugin/KlondikeHomeStack.h new file mode 100644 index 000000000..4d4d0f307 --- /dev/null +++ b/plugins/qsolocards_plugin/KlondikeHomeStack.h @@ -0,0 +1,40 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef KLONDIKEHOMESTACK_H +#define KLONDIKEHOMESTACK_H + +#include "CardStack.h" + +class KlondikeHomeStack : public CardStack +{ + Q_OBJECT +public: + KlondikeHomeStack(); + ~KlondikeHomeStack(); + + inline bool isStackComplete(){return getCardVector().size()==PlayingCard::MaxCardIndex;} + + inline int score() const {return getCardVector().size();} + bool canAddCards(const PlayingCardVector &); +protected: + bool canMoveCard(unsigned int index) const; + +}; + +#endif // KLONDIKEHOMESTACK_H diff --git a/plugins/qsolocards_plugin/KlondikeStack.cpp b/plugins/qsolocards_plugin/KlondikeStack.cpp new file mode 100644 index 000000000..ee95fea99 --- /dev/null +++ b/plugins/qsolocards_plugin/KlondikeStack.cpp @@ -0,0 +1,91 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "KlondikeStack.h" + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +KlondikeStack::KlondikeStack() + :VCardStack(), + m_cheat(false) +{ + this->setAutoTopCardUp(); +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +KlondikeStack::~KlondikeStack() +{ +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +bool KlondikeStack::canAddCards(const PlayingCardVector & newCardVector) +{ + if (m_cheat) + { + return true; + } + + bool rc=false; + const PlayingCardVector & cardVector=this->getCardVector(); + + if (newCardVector.size()>0) + { + // if there are no cards in the stack then the first card + // must be a king. + if (0==cardVector.size() && + PlayingCard::King==newCardVector[0].getIndex()) + { + rc=true; + } + else if (cardVector.size()>0 && + (cardVector[cardVector.size()-1].isRed() ^ newCardVector[0].isRed()) && + cardVector[cardVector.size()-1].isPrevCardIndex(newCardVector[0]) && + cardVector[cardVector.size()-1].isFaceUp()) + { + rc=true; + } + } + + return rc; +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +bool KlondikeStack::canMoveCard(unsigned int index) const +{ + if (m_cheat) + { + return true; + } + + bool rc=false; + const PlayingCardVector & cardVector=this->getCardVector(); + + // ok if we have cards in the stack and the index is valid + // see if we can move it. + // For klondike as long as the card is faceup we should be able to move the + // card and all cards after it in the stack. + if (cardVector.size()>0 && index. +*/ + +#ifndef KLONDIKESTACK_H +#define KLONDIKESTACK_H + +#include "VCardStack.h" + +class KlondikeStack : public VCardStack +{ + Q_OBJECT +public: + KlondikeStack(); + ~KlondikeStack(); + inline bool isCheating() const{return m_cheat;} + + inline void setCheat(bool cheat=true){m_cheat=cheat;} + + bool canAddCards(const PlayingCardVector &); + +protected: + bool canMoveCard(unsigned int index) const; + +private: + bool m_cheat; + +}; + +#endif // KLONDIKESTACK_H diff --git a/plugins/qsolocards_plugin/Makefile b/plugins/qsolocards_plugin/Makefile new file mode 100644 index 000000000..f1b3f1738 --- /dev/null +++ b/plugins/qsolocards_plugin/Makefile @@ -0,0 +1,142 @@ +############################################################################# +# Makefile for building: qsolocards_plugin +# Generated by qmake (2.01a) (Qt 4.6.1) on: Mo 15. Feb 12:18:27 2010 +# Project: qsolocards_plugin.pro +# Template: lib +# Command: d:\qt\2010.01\qt\bin\qmake.exe -win32 -o Makefile qsolocards_plugin.pro +############################################################################# + +first: release +install: release-install +uninstall: release-uninstall +MAKEFILE = Makefile +QMAKE = d:\qt\2010.01\qt\bin\qmake.exe +DEL_FILE = del +CHK_DIR_EXISTS= if not exist +MKDIR = mkdir +COPY = copy /y +COPY_FILE = $(COPY) +COPY_DIR = xcopy /s /q /y /i +INSTALL_FILE = $(COPY_FILE) +INSTALL_PROGRAM = $(COPY_FILE) +INSTALL_DIR = $(COPY_DIR) +DEL_FILE = del +SYMLINK = +DEL_DIR = rmdir +MOVE = move +CHK_DIR_EXISTS= if not exist +MKDIR = mkdir +SUBTARGETS = \ + release \ + debug + +release: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_default: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_first: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release first +release-all: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release all +release-clean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release clean +release-distclean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release distclean +release-install: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release install +release-uninstall: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release uninstall +debug: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_default: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_first: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug first +debug-all: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug all +debug-clean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug clean +debug-distclean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug distclean +debug-install: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug install +debug-uninstall: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug uninstall + +Makefile: qsolocards_plugin.pro d:/Qt/2010.01/qt/mkspecs/default/qmake.conf d:/Qt/2010.01/qt/mkspecs/qconfig.pri \ + d:/Qt/2010.01/qt/mkspecs/features/qt_functions.prf \ + d:/Qt/2010.01/qt/mkspecs/features/qt_config.prf \ + d:/Qt/2010.01/qt/mkspecs/features/exclusive_builds.prf \ + d:/Qt/2010.01/qt/mkspecs/features/default_pre.prf \ + d:/Qt/2010.01/qt/mkspecs/features/win32/default_pre.prf \ + d:/Qt/2010.01/qt/mkspecs/features/release.prf \ + d:/Qt/2010.01/qt/mkspecs/features/debug_and_release.prf \ + d:/Qt/2010.01/qt/mkspecs/features/default_post.prf \ + d:/Qt/2010.01/qt/mkspecs/features/win32/default_post.prf \ + d:/Qt/2010.01/qt/mkspecs/features/win32/rtti.prf \ + d:/Qt/2010.01/qt/mkspecs/features/win32/exceptions.prf \ + d:/Qt/2010.01/qt/mkspecs/features/win32/stl.prf \ + d:/Qt/2010.01/qt/mkspecs/features/shared.prf \ + d:/Qt/2010.01/qt/mkspecs/features/dll.prf \ + d:/Qt/2010.01/qt/mkspecs/features/warn_on.prf \ + d:/Qt/2010.01/qt/mkspecs/features/qt.prf \ + d:/Qt/2010.01/qt/mkspecs/features/win32/thread.prf \ + d:/Qt/2010.01/qt/mkspecs/features/moc.prf \ + d:/Qt/2010.01/qt/mkspecs/features/win32/windows.prf \ + d:/Qt/2010.01/qt/mkspecs/features/resources.prf \ + d:/Qt/2010.01/qt/mkspecs/features/uic.prf \ + d:/Qt/2010.01/qt/mkspecs/features/yacc.prf \ + d:/Qt/2010.01/qt/mkspecs/features/lex.prf + $(QMAKE) -win32 -o Makefile qsolocards_plugin.pro +d:\Qt\2010.01\qt\mkspecs\qconfig.pri: +d:\Qt\2010.01\qt\mkspecs\features\qt_functions.prf: +d:\Qt\2010.01\qt\mkspecs\features\qt_config.prf: +d:\Qt\2010.01\qt\mkspecs\features\exclusive_builds.prf: +d:\Qt\2010.01\qt\mkspecs\features\default_pre.prf: +d:\Qt\2010.01\qt\mkspecs\features\win32\default_pre.prf: +d:\Qt\2010.01\qt\mkspecs\features\release.prf: +d:\Qt\2010.01\qt\mkspecs\features\debug_and_release.prf: +d:\Qt\2010.01\qt\mkspecs\features\default_post.prf: +d:\Qt\2010.01\qt\mkspecs\features\win32\default_post.prf: +d:\Qt\2010.01\qt\mkspecs\features\win32\rtti.prf: +d:\Qt\2010.01\qt\mkspecs\features\win32\exceptions.prf: +d:\Qt\2010.01\qt\mkspecs\features\win32\stl.prf: +d:\Qt\2010.01\qt\mkspecs\features\shared.prf: +d:\Qt\2010.01\qt\mkspecs\features\dll.prf: +d:\Qt\2010.01\qt\mkspecs\features\warn_on.prf: +d:\Qt\2010.01\qt\mkspecs\features\qt.prf: +d:\Qt\2010.01\qt\mkspecs\features\win32\thread.prf: +d:\Qt\2010.01\qt\mkspecs\features\moc.prf: +d:\Qt\2010.01\qt\mkspecs\features\win32\windows.prf: +d:\Qt\2010.01\qt\mkspecs\features\resources.prf: +d:\Qt\2010.01\qt\mkspecs\features\uic.prf: +d:\Qt\2010.01\qt\mkspecs\features\yacc.prf: +d:\Qt\2010.01\qt\mkspecs\features\lex.prf: +qmake: qmake_all FORCE + @$(QMAKE) -win32 -o Makefile qsolocards_plugin.pro + +qmake_all: FORCE + +make_default: release-make_default debug-make_default FORCE +make_first: release-make_first debug-make_first FORCE +all: release-all debug-all FORCE +clean: release-clean debug-clean FORCE + -$(DEL_FILE) ..\..\bin\libqsolocards_plugin0.a +distclean: release-distclean debug-distclean FORCE + -$(DEL_FILE) Makefile + +release-mocclean: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocclean +debug-mocclean: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocclean +mocclean: release-mocclean debug-mocclean + +release-mocables: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocables +debug-mocables: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocables +mocables: release-mocables debug-mocables +FORCE: + +$(MAKEFILE).Release: Makefile +$(MAKEFILE).Debug: Makefile diff --git a/plugins/qsolocards_plugin/Makefile.Debug b/plugins/qsolocards_plugin/Makefile.Debug new file mode 100644 index 000000000..4f842faa9 --- /dev/null +++ b/plugins/qsolocards_plugin/Makefile.Debug @@ -0,0 +1,991 @@ +############################################################################# +# Makefile for building: qsolocards_plugin +# Generated by qmake (2.01a) (Qt 4.6.1) on: Mo 15. Feb 12:18:27 2010 +# Project: qsolocards_plugin.pro +# Template: lib +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_PLUGIN -DQT_SVG_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT +CFLAGS = -g -Wall $(DEFINES) +CXXFLAGS = -DVER_MAJ=0 -DVER_MIN=99 -DVER_PAT=1 -frtti -fexceptions -mthreads -Wall $(DEFINES) +INCPATH = -I"d:\Qt\2010.01\qt\include\QtCore" -I"d:\Qt\2010.01\qt\include\QtGui" -I"d:\Qt\2010.01\qt\include\QtSvg" -I"d:\Qt\2010.01\qt\include" -I".." -I"d:\Qt\2010.01\qt\include\ActiveQt" -I"temp\moc" -I"d:\Qt\2010.01\qt\mkspecs\default" +LINK = g++ +LFLAGS = -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mthreads -Wl -shared -Wl,--out-implib,..\..\bin\libqsolocards_plugin0.a +LIBS = -L"d:\Qt\2010.01\qt\lib" -lQtSvgd4 -lQtGuid4 -lQtCored4 +QMAKE = d:\qt\2010.01\qt\bin\qmake.exe +IDC = d:\Qt\2010.01\qt\bin\idc.exe +IDL = midl +ZIP = zip -r -9 +DEF_FILE = +RES_FILE = +COPY = copy /y +COPY_FILE = $(COPY) +COPY_DIR = xcopy /s /q /y /i +DEL_FILE = del +DEL_DIR = rmdir +MOVE = move +CHK_DIR_EXISTS= if not exist +MKDIR = mkdir +INSTALL_FILE = $(COPY_FILE) +INSTALL_PROGRAM = $(COPY_FILE) +INSTALL_DIR = $(COPY_DIR) + +####### Output directory + +OBJECTS_DIR = temp\obj + +####### Files + +SOURCES = QSoloCardsPlugin.cpp \ + main.cpp \ + mainwindow.cpp \ + PlayingCard.cpp \ + CardDeck.cpp \ + CardPixmaps.cpp \ + CardStack.cpp \ + DragCardStack.cpp \ + VCardStack.cpp \ + CardAnimationLock.cpp \ + StackToStackAniMove.cpp \ + DealAnimation.cpp \ + FlipAnimation.cpp \ + StackToStackFlipAni.cpp \ + GameBoard.cpp \ + CardMoveRecord.cpp \ + About.cpp \ + Help.cpp \ + GameMgr.cpp \ + SpiderBoard.cpp \ + SpiderHomeStack.cpp \ + SpiderStack.cpp \ + KlondikeStack.cpp \ + KlondikeFlipStack.cpp \ + KlondikeHomeStack.cpp \ + KlondikeBoard.cpp \ + FreeCellBoard.cpp \ + FreeCellDeck.cpp \ + FreeCellStack.cpp \ + FreeCellHome.cpp \ + FreeCellFree.cpp \ + Spider3DeckBoard.cpp \ + SpideretteBoard.cpp \ + YukonBoard.cpp temp\moc\moc_QSoloCardsPlugin.cpp \ + temp\moc\moc_mainwindow.cpp \ + temp\moc\moc_CardStack.cpp \ + temp\moc\moc_DragCardStack.cpp \ + temp\moc\moc_VCardStack.cpp \ + temp\moc\moc_CardAnimationLock.cpp \ + temp\moc\moc_StackToStackAniMove.cpp \ + temp\moc\moc_DealAnimation.cpp \ + temp\moc\moc_FlipAnimation.cpp \ + temp\moc\moc_StackToStackFlipAni.cpp \ + temp\moc\moc_GameBoard.cpp \ + temp\moc\moc_About.cpp \ + temp\moc\moc_Help.cpp \ + temp\moc\moc_SpiderBoard.cpp \ + temp\moc\moc_SpiderStack.cpp \ + temp\moc\moc_KlondikeStack.cpp \ + temp\moc\moc_KlondikeFlipStack.cpp \ + temp\moc\moc_KlondikeHomeStack.cpp \ + temp\moc\moc_KlondikeBoard.cpp \ + temp\moc\moc_FreeCellBoard.cpp \ + temp\moc\moc_FreeCellDeck.cpp \ + temp\moc\moc_FreeCellStack.cpp \ + temp\moc\moc_FreeCellHome.cpp \ + temp\moc\moc_FreeCellFree.cpp \ + temp\moc\moc_Spider3DeckBoard.cpp \ + temp\moc\moc_SpideretteBoard.cpp \ + temp\moc\moc_YukonBoard.cpp \ + temp\qrc\qrc_QSoloCards.cpp +OBJECTS = temp/obj/QSoloCardsPlugin.o \ + temp/obj/main.o \ + temp/obj/mainwindow.o \ + temp/obj/PlayingCard.o \ + temp/obj/CardDeck.o \ + temp/obj/CardPixmaps.o \ + temp/obj/CardStack.o \ + temp/obj/DragCardStack.o \ + temp/obj/VCardStack.o \ + temp/obj/CardAnimationLock.o \ + temp/obj/StackToStackAniMove.o \ + temp/obj/DealAnimation.o \ + temp/obj/FlipAnimation.o \ + temp/obj/StackToStackFlipAni.o \ + temp/obj/GameBoard.o \ + temp/obj/CardMoveRecord.o \ + temp/obj/About.o \ + temp/obj/Help.o \ + temp/obj/GameMgr.o \ + temp/obj/SpiderBoard.o \ + temp/obj/SpiderHomeStack.o \ + temp/obj/SpiderStack.o \ + temp/obj/KlondikeStack.o \ + temp/obj/KlondikeFlipStack.o \ + temp/obj/KlondikeHomeStack.o \ + temp/obj/KlondikeBoard.o \ + temp/obj/FreeCellBoard.o \ + temp/obj/FreeCellDeck.o \ + temp/obj/FreeCellStack.o \ + temp/obj/FreeCellHome.o \ + temp/obj/FreeCellFree.o \ + temp/obj/Spider3DeckBoard.o \ + temp/obj/SpideretteBoard.o \ + temp/obj/YukonBoard.o \ + temp/obj/moc_QSoloCardsPlugin.o \ + temp/obj/moc_mainwindow.o \ + temp/obj/moc_CardStack.o \ + temp/obj/moc_DragCardStack.o \ + temp/obj/moc_VCardStack.o \ + temp/obj/moc_CardAnimationLock.o \ + temp/obj/moc_StackToStackAniMove.o \ + temp/obj/moc_DealAnimation.o \ + temp/obj/moc_FlipAnimation.o \ + temp/obj/moc_StackToStackFlipAni.o \ + temp/obj/moc_GameBoard.o \ + temp/obj/moc_About.o \ + temp/obj/moc_Help.o \ + temp/obj/moc_SpiderBoard.o \ + temp/obj/moc_SpiderStack.o \ + temp/obj/moc_KlondikeStack.o \ + temp/obj/moc_KlondikeFlipStack.o \ + temp/obj/moc_KlondikeHomeStack.o \ + temp/obj/moc_KlondikeBoard.o \ + temp/obj/moc_FreeCellBoard.o \ + temp/obj/moc_FreeCellDeck.o \ + temp/obj/moc_FreeCellStack.o \ + temp/obj/moc_FreeCellHome.o \ + temp/obj/moc_FreeCellFree.o \ + temp/obj/moc_Spider3DeckBoard.o \ + temp/obj/moc_SpideretteBoard.o \ + temp/obj/moc_YukonBoard.o \ + temp/obj/qrc_QSoloCards.o +DIST = +QMAKE_TARGET = qsolocards_plugin +DESTDIR = ..\..\bin\ #avoid trailing-slash linebreak +TARGET = qsolocards_plugin0.dll +DESTDIR_TARGET = ..\..\bin\qsolocards_plugin0.dll + +####### Implicit rules + +.SUFFIXES: .cpp .cc .cxx .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + +first: all +all: Makefile.Debug $(DESTDIR_TARGET) + +$(DESTDIR_TARGET): $(OBJECTS) + $(LINK) $(LFLAGS) -o $(DESTDIR_TARGET) object_script.qsolocards_plugin.Debug $(LIBS) + + +qmake: FORCE + @$(QMAKE) -win32 -o Makefile.Debug qsolocards_plugin.pro + +dist: + $(ZIP) qsolocards_plugin.zip $(SOURCES) $(DIST) qsolocards_plugin.pro d:\Qt\2010.01\qt\mkspecs\qconfig.pri d:\Qt\2010.01\qt\mkspecs\features\qt_functions.prf d:\Qt\2010.01\qt\mkspecs\features\qt_config.prf d:\Qt\2010.01\qt\mkspecs\features\exclusive_builds.prf d:\Qt\2010.01\qt\mkspecs\features\default_pre.prf d:\Qt\2010.01\qt\mkspecs\features\win32\default_pre.prf d:\Qt\2010.01\qt\mkspecs\features\debug.prf d:\Qt\2010.01\qt\mkspecs\features\debug_and_release.prf d:\Qt\2010.01\qt\mkspecs\features\default_post.prf d:\Qt\2010.01\qt\mkspecs\features\win32\default_post.prf d:\Qt\2010.01\qt\mkspecs\features\build_pass.prf d:\Qt\2010.01\qt\mkspecs\features\win32\rtti.prf d:\Qt\2010.01\qt\mkspecs\features\win32\exceptions.prf d:\Qt\2010.01\qt\mkspecs\features\win32\stl.prf d:\Qt\2010.01\qt\mkspecs\features\shared.prf d:\Qt\2010.01\qt\mkspecs\features\dll.prf d:\Qt\2010.01\qt\mkspecs\features\warn_on.prf d:\Qt\2010.01\qt\mkspecs\features\qt.prf d:\Qt\2010.01\qt\mkspecs\features\win32\thread.prf d:\Qt\2010.01\qt\mkspecs\features\moc.prf d:\Qt\2010.01\qt\mkspecs\features\win32\windows.prf d:\Qt\2010.01\qt\mkspecs\features\resources.prf d:\Qt\2010.01\qt\mkspecs\features\uic.prf d:\Qt\2010.01\qt\mkspecs\features\yacc.prf d:\Qt\2010.01\qt\mkspecs\features\lex.prf HEADERS RESOURCES IMAGES SOURCES OBJECTIVE_SOURCES FORMS YACCSOURCES YACCSOURCES LEXSOURCES + +clean: compiler_clean + -$(DEL_FILE) temp\obj\QSoloCardsPlugin.o temp\obj\main.o temp\obj\mainwindow.o temp\obj\PlayingCard.o temp\obj\CardDeck.o temp\obj\CardPixmaps.o temp\obj\CardStack.o temp\obj\DragCardStack.o temp\obj\VCardStack.o temp\obj\CardAnimationLock.o temp\obj\StackToStackAniMove.o temp\obj\DealAnimation.o temp\obj\FlipAnimation.o temp\obj\StackToStackFlipAni.o temp\obj\GameBoard.o temp\obj\CardMoveRecord.o temp\obj\About.o temp\obj\Help.o temp\obj\GameMgr.o temp\obj\SpiderBoard.o temp\obj\SpiderHomeStack.o temp\obj\SpiderStack.o temp\obj\KlondikeStack.o temp\obj\KlondikeFlipStack.o temp\obj\KlondikeHomeStack.o temp\obj\KlondikeBoard.o temp\obj\FreeCellBoard.o temp\obj\FreeCellDeck.o temp\obj\FreeCellStack.o temp\obj\FreeCellHome.o temp\obj\FreeCellFree.o temp\obj\Spider3DeckBoard.o temp\obj\SpideretteBoard.o temp\obj\YukonBoard.o temp\obj\moc_QSoloCardsPlugin.o temp\obj\moc_mainwindow.o temp\obj\moc_CardStack.o temp\obj\moc_DragCardStack.o temp\obj\moc_VCardStack.o temp\obj\moc_CardAnimationLock.o temp\obj\moc_StackToStackAniMove.o temp\obj\moc_DealAnimation.o temp\obj\moc_FlipAnimation.o temp\obj\moc_StackToStackFlipAni.o temp\obj\moc_GameBoard.o temp\obj\moc_About.o temp\obj\moc_Help.o temp\obj\moc_SpiderBoard.o temp\obj\moc_SpiderStack.o temp\obj\moc_KlondikeStack.o temp\obj\moc_KlondikeFlipStack.o temp\obj\moc_KlondikeHomeStack.o temp\obj\moc_KlondikeBoard.o temp\obj\moc_FreeCellBoard.o temp\obj\moc_FreeCellDeck.o temp\obj\moc_FreeCellStack.o temp\obj\moc_FreeCellHome.o temp\obj\moc_FreeCellFree.o temp\obj\moc_Spider3DeckBoard.o temp\obj\moc_SpideretteBoard.o temp\obj\moc_YukonBoard.o temp\obj\qrc_QSoloCards.o + -$(DEL_FILE) ..\..\bin\libqsolocards_plugin0.a + +distclean: clean + -$(DEL_FILE) $(DESTDIR_TARGET) + -$(DEL_FILE) Makefile.Debug + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: temp/moc/moc_QSoloCardsPlugin.cpp temp/moc/moc_mainwindow.cpp temp/moc/moc_CardStack.cpp temp/moc/moc_DragCardStack.cpp temp/moc/moc_VCardStack.cpp temp/moc/moc_CardAnimationLock.cpp temp/moc/moc_StackToStackAniMove.cpp temp/moc/moc_DealAnimation.cpp temp/moc/moc_FlipAnimation.cpp temp/moc/moc_StackToStackFlipAni.cpp temp/moc/moc_GameBoard.cpp temp/moc/moc_About.cpp temp/moc/moc_Help.cpp temp/moc/moc_SpiderBoard.cpp temp/moc/moc_SpiderStack.cpp temp/moc/moc_KlondikeStack.cpp temp/moc/moc_KlondikeFlipStack.cpp temp/moc/moc_KlondikeHomeStack.cpp temp/moc/moc_KlondikeBoard.cpp temp/moc/moc_FreeCellBoard.cpp temp/moc/moc_FreeCellDeck.cpp temp/moc/moc_FreeCellStack.cpp temp/moc/moc_FreeCellHome.cpp temp/moc/moc_FreeCellFree.cpp temp/moc/moc_Spider3DeckBoard.cpp temp/moc/moc_SpideretteBoard.cpp temp/moc/moc_YukonBoard.cpp +compiler_moc_header_clean: + -$(DEL_FILE) temp\moc\moc_QSoloCardsPlugin.cpp temp\moc\moc_mainwindow.cpp temp\moc\moc_CardStack.cpp temp\moc\moc_DragCardStack.cpp temp\moc\moc_VCardStack.cpp temp\moc\moc_CardAnimationLock.cpp temp\moc\moc_StackToStackAniMove.cpp temp\moc\moc_DealAnimation.cpp temp\moc\moc_FlipAnimation.cpp temp\moc\moc_StackToStackFlipAni.cpp temp\moc\moc_GameBoard.cpp temp\moc\moc_About.cpp temp\moc\moc_Help.cpp temp\moc\moc_SpiderBoard.cpp temp\moc\moc_SpiderStack.cpp temp\moc\moc_KlondikeStack.cpp temp\moc\moc_KlondikeFlipStack.cpp temp\moc\moc_KlondikeHomeStack.cpp temp\moc\moc_KlondikeBoard.cpp temp\moc\moc_FreeCellBoard.cpp temp\moc\moc_FreeCellDeck.cpp temp\moc\moc_FreeCellStack.cpp temp\moc\moc_FreeCellHome.cpp temp\moc\moc_FreeCellFree.cpp temp\moc\moc_Spider3DeckBoard.cpp temp\moc\moc_SpideretteBoard.cpp temp\moc\moc_YukonBoard.cpp +temp/moc/moc_QSoloCardsPlugin.cpp: QSoloCardsPlugin.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 QSoloCardsPlugin.h -o temp\moc\moc_QSoloCardsPlugin.cpp + +temp/moc/moc_mainwindow.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + Help.h \ + About.h \ + GameMgr.h \ + mainwindow.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 mainwindow.h -o temp\moc\moc_mainwindow.cpp + +temp/moc/moc_CardStack.cpp: CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 CardStack.h -o temp\moc\moc_CardStack.cpp + +temp/moc/moc_DragCardStack.cpp: CardDeck.h \ + PlayingCard.h \ + CardMoveRecord.h \ + DragCardStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 DragCardStack.h -o temp\moc\moc_DragCardStack.cpp + +temp/moc/moc_VCardStack.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + VCardStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 VCardStack.h -o temp\moc\moc_VCardStack.cpp + +temp/moc/moc_CardAnimationLock.cpp: CardAnimationLock.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 CardAnimationLock.h -o temp\moc\moc_CardAnimationLock.cpp + +temp/moc/moc_StackToStackAniMove.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 StackToStackAniMove.h -o temp\moc\moc_StackToStackAniMove.cpp + +temp/moc/moc_DealAnimation.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + DealAnimation.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 DealAnimation.h -o temp\moc\moc_DealAnimation.cpp + +temp/moc/moc_FlipAnimation.cpp: CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FlipAnimation.h -o temp\moc\moc_FlipAnimation.cpp + +temp/moc/moc_StackToStackFlipAni.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackFlipAni.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 StackToStackFlipAni.h -o temp\moc\moc_StackToStackFlipAni.cpp + +temp/moc/moc_GameBoard.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + GameBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 GameBoard.h -o temp\moc\moc_GameBoard.cpp + +temp/moc/moc_About.cpp: About.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 About.h -o temp\moc\moc_About.cpp + +temp/moc/moc_Help.cpp: Help.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 Help.h -o temp\moc\moc_Help.cpp + +temp/moc/moc_SpiderBoard.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + SpiderBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 SpiderBoard.h -o temp\moc\moc_SpiderBoard.cpp + +temp/moc/moc_SpiderStack.cpp: VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + SpiderStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 SpiderStack.h -o temp\moc\moc_SpiderStack.cpp + +temp/moc/moc_KlondikeStack.cpp: VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + KlondikeStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 KlondikeStack.h -o temp\moc\moc_KlondikeStack.cpp + +temp/moc/moc_KlondikeFlipStack.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + KlondikeFlipStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 KlondikeFlipStack.h -o temp\moc\moc_KlondikeFlipStack.cpp + +temp/moc/moc_KlondikeHomeStack.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + KlondikeHomeStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 KlondikeHomeStack.h -o temp\moc\moc_KlondikeHomeStack.cpp + +temp/moc/moc_KlondikeBoard.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + KlondikeStack.h \ + VCardStack.h \ + KlondikeHomeStack.h \ + KlondikeFlipStack.h \ + StackToStackFlipAni.h \ + KlondikeBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 KlondikeBoard.h -o temp\moc\moc_KlondikeBoard.cpp + +temp/moc/moc_FreeCellBoard.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + FreeCellDeck.h \ + FreeCellFree.h \ + FreeCellStack.h \ + VCardStack.h \ + FreeCellHome.h \ + FreeCellBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellBoard.h -o temp\moc\moc_FreeCellBoard.cpp + +temp/moc/moc_FreeCellDeck.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + FreeCellDeck.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellDeck.h -o temp\moc\moc_FreeCellDeck.cpp + +temp/moc/moc_FreeCellStack.cpp: VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + FreeCellStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellStack.h -o temp\moc\moc_FreeCellStack.cpp + +temp/moc/moc_FreeCellHome.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + FreeCellHome.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellHome.h -o temp\moc\moc_FreeCellHome.cpp + +temp/moc/moc_FreeCellFree.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + FreeCellFree.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellFree.h -o temp\moc\moc_FreeCellFree.cpp + +temp/moc/moc_Spider3DeckBoard.cpp: SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + Spider3DeckBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 Spider3DeckBoard.h -o temp\moc\moc_Spider3DeckBoard.cpp + +temp/moc/moc_SpideretteBoard.cpp: SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + SpideretteBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 SpideretteBoard.h -o temp\moc\moc_SpideretteBoard.cpp + +temp/moc/moc_YukonBoard.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + FreeCellHome.h \ + FreeCellDeck.h \ + KlondikeStack.h \ + VCardStack.h \ + YukonBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 YukonBoard.h -o temp\moc\moc_YukonBoard.cpp + +compiler_rcc_make_all: temp/qrc/qrc_QSoloCards.cpp +compiler_rcc_clean: + -$(DEL_FILE) temp\qrc\qrc_QSoloCards.cpp +temp/qrc/qrc_QSoloCards.cpp: QSoloCards.qrc \ + images/greenfelt.png \ + images/anglo_bitmap.svg \ + images/sol128x128.png \ + images/sol32x32.png \ + help/FreeCellHelp.html \ + help/SpideretteHelp.html \ + help/YukonHelp.html \ + help/SpiderHelp.html \ + help/Spider3DeckHelp.html \ + help/KlondikeHelp.html \ + help/gpl3.html + d:\Qt\2010.01\qt\bin\rcc.exe -name QSoloCards QSoloCards.qrc -o temp\qrc\qrc_QSoloCards.cpp + +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean compiler_rcc_clean + + + +####### Compile + +temp/obj/QSoloCardsPlugin.o: QSoloCardsPlugin.cpp QSoloCardsPlugin.h \ + mainwindow.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + Help.h \ + About.h \ + GameMgr.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\QSoloCardsPlugin.o QSoloCardsPlugin.cpp + +temp/obj/main.o: main.cpp mainwindow.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + Help.h \ + About.h \ + GameMgr.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\main.o main.cpp + +temp/obj/mainwindow.o: mainwindow.cpp mainwindow.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + Help.h \ + About.h \ + GameMgr.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\mainwindow.o mainwindow.cpp + +temp/obj/PlayingCard.o: PlayingCard.cpp PlayingCard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\PlayingCard.o PlayingCard.cpp + +temp/obj/CardDeck.o: CardDeck.cpp CardDeck.h \ + PlayingCard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardDeck.o CardDeck.cpp + +temp/obj/CardPixmaps.o: CardPixmaps.cpp CardPixmaps.h \ + PlayingCard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardPixmaps.o CardPixmaps.cpp + +temp/obj/CardStack.o: CardStack.cpp CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardPixmaps.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardStack.o CardStack.cpp + +temp/obj/DragCardStack.o: DragCardStack.cpp DragCardStack.h \ + CardDeck.h \ + PlayingCard.h \ + CardMoveRecord.h \ + CardStack.h \ + FlipAnimation.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\DragCardStack.o DragCardStack.cpp + +temp/obj/VCardStack.o: VCardStack.cpp VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\VCardStack.o VCardStack.cpp + +temp/obj/CardAnimationLock.o: CardAnimationLock.cpp CardAnimationLock.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardAnimationLock.o CardAnimationLock.cpp + +temp/obj/StackToStackAniMove.o: StackToStackAniMove.cpp StackToStackAniMove.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\StackToStackAniMove.o StackToStackAniMove.cpp + +temp/obj/DealAnimation.o: DealAnimation.cpp DealAnimation.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\DealAnimation.o DealAnimation.cpp + +temp/obj/FlipAnimation.o: FlipAnimation.cpp FlipAnimation.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + CardStack.h \ + DragCardStack.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FlipAnimation.o FlipAnimation.cpp + +temp/obj/StackToStackFlipAni.o: StackToStackFlipAni.cpp StackToStackFlipAni.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardAnimationLock.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\StackToStackFlipAni.o StackToStackFlipAni.cpp + +temp/obj/GameBoard.o: GameBoard.cpp GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + CardPixmaps.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\GameBoard.o GameBoard.cpp + +temp/obj/CardMoveRecord.o: CardMoveRecord.cpp CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardMoveRecord.o CardMoveRecord.cpp + +temp/obj/About.o: About.cpp About.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\About.o About.cpp + +temp/obj/Help.o: Help.cpp Help.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\Help.o Help.cpp + +temp/obj/GameMgr.o: GameMgr.cpp GameMgr.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderBoard.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + Spider3DeckBoard.h \ + SpideretteBoard.h \ + KlondikeBoard.h \ + KlondikeStack.h \ + KlondikeHomeStack.h \ + KlondikeFlipStack.h \ + StackToStackFlipAni.h \ + FreeCellBoard.h \ + FreeCellDeck.h \ + FreeCellFree.h \ + FreeCellStack.h \ + FreeCellHome.h \ + YukonBoard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\GameMgr.o GameMgr.cpp + +temp/obj/SpiderBoard.o: SpiderBoard.cpp SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\SpiderBoard.o SpiderBoard.cpp + +temp/obj/SpiderHomeStack.o: SpiderHomeStack.cpp SpiderHomeStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\SpiderHomeStack.o SpiderHomeStack.cpp + +temp/obj/SpiderStack.o: SpiderStack.cpp SpiderStack.h \ + VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + SpiderHomeStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\SpiderStack.o SpiderStack.cpp + +temp/obj/KlondikeStack.o: KlondikeStack.cpp KlondikeStack.h \ + VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\KlondikeStack.o KlondikeStack.cpp + +temp/obj/KlondikeFlipStack.o: KlondikeFlipStack.cpp KlondikeFlipStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\KlondikeFlipStack.o KlondikeFlipStack.cpp + +temp/obj/KlondikeHomeStack.o: KlondikeHomeStack.cpp KlondikeHomeStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\KlondikeHomeStack.o KlondikeHomeStack.cpp + +temp/obj/KlondikeBoard.o: KlondikeBoard.cpp KlondikeBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + KlondikeStack.h \ + VCardStack.h \ + KlondikeHomeStack.h \ + KlondikeFlipStack.h \ + StackToStackFlipAni.h \ + CardPixmaps.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\KlondikeBoard.o KlondikeBoard.cpp + +temp/obj/FreeCellBoard.o: FreeCellBoard.cpp FreeCellBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + FreeCellDeck.h \ + FreeCellFree.h \ + FreeCellStack.h \ + VCardStack.h \ + FreeCellHome.h \ + CardPixmaps.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellBoard.o FreeCellBoard.cpp + +temp/obj/FreeCellDeck.o: FreeCellDeck.cpp FreeCellDeck.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellDeck.o FreeCellDeck.cpp + +temp/obj/FreeCellStack.o: FreeCellStack.cpp FreeCellStack.h \ + VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellStack.o FreeCellStack.cpp + +temp/obj/FreeCellHome.o: FreeCellHome.cpp FreeCellHome.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellHome.o FreeCellHome.cpp + +temp/obj/FreeCellFree.o: FreeCellFree.cpp FreeCellFree.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellFree.o FreeCellFree.cpp + +temp/obj/Spider3DeckBoard.o: Spider3DeckBoard.cpp Spider3DeckBoard.h \ + SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\Spider3DeckBoard.o Spider3DeckBoard.cpp + +temp/obj/SpideretteBoard.o: SpideretteBoard.cpp SpideretteBoard.h \ + SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\SpideretteBoard.o SpideretteBoard.cpp + +temp/obj/YukonBoard.o: YukonBoard.cpp YukonBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + FreeCellHome.h \ + FreeCellDeck.h \ + KlondikeStack.h \ + VCardStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\YukonBoard.o YukonBoard.cpp + +temp/obj/moc_QSoloCardsPlugin.o: temp/moc/moc_QSoloCardsPlugin.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_QSoloCardsPlugin.o temp\moc\moc_QSoloCardsPlugin.cpp + +temp/obj/moc_mainwindow.o: temp/moc/moc_mainwindow.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_mainwindow.o temp\moc\moc_mainwindow.cpp + +temp/obj/moc_CardStack.o: temp/moc/moc_CardStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_CardStack.o temp\moc\moc_CardStack.cpp + +temp/obj/moc_DragCardStack.o: temp/moc/moc_DragCardStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_DragCardStack.o temp\moc\moc_DragCardStack.cpp + +temp/obj/moc_VCardStack.o: temp/moc/moc_VCardStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_VCardStack.o temp\moc\moc_VCardStack.cpp + +temp/obj/moc_CardAnimationLock.o: temp/moc/moc_CardAnimationLock.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_CardAnimationLock.o temp\moc\moc_CardAnimationLock.cpp + +temp/obj/moc_StackToStackAniMove.o: temp/moc/moc_StackToStackAniMove.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_StackToStackAniMove.o temp\moc\moc_StackToStackAniMove.cpp + +temp/obj/moc_DealAnimation.o: temp/moc/moc_DealAnimation.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_DealAnimation.o temp\moc\moc_DealAnimation.cpp + +temp/obj/moc_FlipAnimation.o: temp/moc/moc_FlipAnimation.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FlipAnimation.o temp\moc\moc_FlipAnimation.cpp + +temp/obj/moc_StackToStackFlipAni.o: temp/moc/moc_StackToStackFlipAni.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_StackToStackFlipAni.o temp\moc\moc_StackToStackFlipAni.cpp + +temp/obj/moc_GameBoard.o: temp/moc/moc_GameBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_GameBoard.o temp\moc\moc_GameBoard.cpp + +temp/obj/moc_About.o: temp/moc/moc_About.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_About.o temp\moc\moc_About.cpp + +temp/obj/moc_Help.o: temp/moc/moc_Help.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_Help.o temp\moc\moc_Help.cpp + +temp/obj/moc_SpiderBoard.o: temp/moc/moc_SpiderBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_SpiderBoard.o temp\moc\moc_SpiderBoard.cpp + +temp/obj/moc_SpiderStack.o: temp/moc/moc_SpiderStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_SpiderStack.o temp\moc\moc_SpiderStack.cpp + +temp/obj/moc_KlondikeStack.o: temp/moc/moc_KlondikeStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_KlondikeStack.o temp\moc\moc_KlondikeStack.cpp + +temp/obj/moc_KlondikeFlipStack.o: temp/moc/moc_KlondikeFlipStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_KlondikeFlipStack.o temp\moc\moc_KlondikeFlipStack.cpp + +temp/obj/moc_KlondikeHomeStack.o: temp/moc/moc_KlondikeHomeStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_KlondikeHomeStack.o temp\moc\moc_KlondikeHomeStack.cpp + +temp/obj/moc_KlondikeBoard.o: temp/moc/moc_KlondikeBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_KlondikeBoard.o temp\moc\moc_KlondikeBoard.cpp + +temp/obj/moc_FreeCellBoard.o: temp/moc/moc_FreeCellBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellBoard.o temp\moc\moc_FreeCellBoard.cpp + +temp/obj/moc_FreeCellDeck.o: temp/moc/moc_FreeCellDeck.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellDeck.o temp\moc\moc_FreeCellDeck.cpp + +temp/obj/moc_FreeCellStack.o: temp/moc/moc_FreeCellStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellStack.o temp\moc\moc_FreeCellStack.cpp + +temp/obj/moc_FreeCellHome.o: temp/moc/moc_FreeCellHome.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellHome.o temp\moc\moc_FreeCellHome.cpp + +temp/obj/moc_FreeCellFree.o: temp/moc/moc_FreeCellFree.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellFree.o temp\moc\moc_FreeCellFree.cpp + +temp/obj/moc_Spider3DeckBoard.o: temp/moc/moc_Spider3DeckBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_Spider3DeckBoard.o temp\moc\moc_Spider3DeckBoard.cpp + +temp/obj/moc_SpideretteBoard.o: temp/moc/moc_SpideretteBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_SpideretteBoard.o temp\moc\moc_SpideretteBoard.cpp + +temp/obj/moc_YukonBoard.o: temp/moc/moc_YukonBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_YukonBoard.o temp\moc\moc_YukonBoard.cpp + +temp/obj/qrc_QSoloCards.o: temp/qrc/qrc_QSoloCards.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\qrc_QSoloCards.o temp\qrc\qrc_QSoloCards.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/plugins/qsolocards_plugin/Makefile.Release b/plugins/qsolocards_plugin/Makefile.Release new file mode 100644 index 000000000..df4410744 --- /dev/null +++ b/plugins/qsolocards_plugin/Makefile.Release @@ -0,0 +1,991 @@ +############################################################################# +# Makefile for building: qsolocards_plugin +# Generated by qmake (2.01a) (Qt 4.6.1) on: Mo 15. Feb 12:18:26 2010 +# Project: qsolocards_plugin.pro +# Template: lib +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DUNICODE -DQT_LARGEFILE_SUPPORT -DQT_DLL -DQT_NO_DEBUG -DQT_PLUGIN -DQT_SVG_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT +CFLAGS = -O2 -Wall $(DEFINES) +CXXFLAGS = -DVER_MAJ=0 -DVER_MIN=99 -DVER_PAT=1 -frtti -fexceptions -mthreads -Wall $(DEFINES) +INCPATH = -I"d:\Qt\2010.01\qt\include\QtCore" -I"d:\Qt\2010.01\qt\include\QtGui" -I"d:\Qt\2010.01\qt\include\QtSvg" -I"d:\Qt\2010.01\qt\include" -I".." -I"d:\Qt\2010.01\qt\include\ActiveQt" -I"temp\moc" -I"d:\Qt\2010.01\qt\mkspecs\default" +LINK = g++ +LFLAGS = -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -Wl,-s -mthreads -Wl -shared -Wl,--out-implib,..\..\bin\libqsolocards_plugin0.a +LIBS = -L"d:\Qt\2010.01\qt\lib" -lQtSvg4 -lQtGui4 -lQtCore4 +QMAKE = d:\qt\2010.01\qt\bin\qmake.exe +IDC = d:\Qt\2010.01\qt\bin\idc.exe +IDL = midl +ZIP = zip -r -9 +DEF_FILE = +RES_FILE = +COPY = copy /y +COPY_FILE = $(COPY) +COPY_DIR = xcopy /s /q /y /i +DEL_FILE = del +DEL_DIR = rmdir +MOVE = move +CHK_DIR_EXISTS= if not exist +MKDIR = mkdir +INSTALL_FILE = $(COPY_FILE) +INSTALL_PROGRAM = $(COPY_FILE) +INSTALL_DIR = $(COPY_DIR) + +####### Output directory + +OBJECTS_DIR = temp\obj + +####### Files + +SOURCES = QSoloCardsPlugin.cpp \ + main.cpp \ + mainwindow.cpp \ + PlayingCard.cpp \ + CardDeck.cpp \ + CardPixmaps.cpp \ + CardStack.cpp \ + DragCardStack.cpp \ + VCardStack.cpp \ + CardAnimationLock.cpp \ + StackToStackAniMove.cpp \ + DealAnimation.cpp \ + FlipAnimation.cpp \ + StackToStackFlipAni.cpp \ + GameBoard.cpp \ + CardMoveRecord.cpp \ + About.cpp \ + Help.cpp \ + GameMgr.cpp \ + SpiderBoard.cpp \ + SpiderHomeStack.cpp \ + SpiderStack.cpp \ + KlondikeStack.cpp \ + KlondikeFlipStack.cpp \ + KlondikeHomeStack.cpp \ + KlondikeBoard.cpp \ + FreeCellBoard.cpp \ + FreeCellDeck.cpp \ + FreeCellStack.cpp \ + FreeCellHome.cpp \ + FreeCellFree.cpp \ + Spider3DeckBoard.cpp \ + SpideretteBoard.cpp \ + YukonBoard.cpp temp\moc\moc_QSoloCardsPlugin.cpp \ + temp\moc\moc_mainwindow.cpp \ + temp\moc\moc_CardStack.cpp \ + temp\moc\moc_DragCardStack.cpp \ + temp\moc\moc_VCardStack.cpp \ + temp\moc\moc_CardAnimationLock.cpp \ + temp\moc\moc_StackToStackAniMove.cpp \ + temp\moc\moc_DealAnimation.cpp \ + temp\moc\moc_FlipAnimation.cpp \ + temp\moc\moc_StackToStackFlipAni.cpp \ + temp\moc\moc_GameBoard.cpp \ + temp\moc\moc_About.cpp \ + temp\moc\moc_Help.cpp \ + temp\moc\moc_SpiderBoard.cpp \ + temp\moc\moc_SpiderStack.cpp \ + temp\moc\moc_KlondikeStack.cpp \ + temp\moc\moc_KlondikeFlipStack.cpp \ + temp\moc\moc_KlondikeHomeStack.cpp \ + temp\moc\moc_KlondikeBoard.cpp \ + temp\moc\moc_FreeCellBoard.cpp \ + temp\moc\moc_FreeCellDeck.cpp \ + temp\moc\moc_FreeCellStack.cpp \ + temp\moc\moc_FreeCellHome.cpp \ + temp\moc\moc_FreeCellFree.cpp \ + temp\moc\moc_Spider3DeckBoard.cpp \ + temp\moc\moc_SpideretteBoard.cpp \ + temp\moc\moc_YukonBoard.cpp \ + temp\qrc\qrc_QSoloCards.cpp +OBJECTS = temp/obj/QSoloCardsPlugin.o \ + temp/obj/main.o \ + temp/obj/mainwindow.o \ + temp/obj/PlayingCard.o \ + temp/obj/CardDeck.o \ + temp/obj/CardPixmaps.o \ + temp/obj/CardStack.o \ + temp/obj/DragCardStack.o \ + temp/obj/VCardStack.o \ + temp/obj/CardAnimationLock.o \ + temp/obj/StackToStackAniMove.o \ + temp/obj/DealAnimation.o \ + temp/obj/FlipAnimation.o \ + temp/obj/StackToStackFlipAni.o \ + temp/obj/GameBoard.o \ + temp/obj/CardMoveRecord.o \ + temp/obj/About.o \ + temp/obj/Help.o \ + temp/obj/GameMgr.o \ + temp/obj/SpiderBoard.o \ + temp/obj/SpiderHomeStack.o \ + temp/obj/SpiderStack.o \ + temp/obj/KlondikeStack.o \ + temp/obj/KlondikeFlipStack.o \ + temp/obj/KlondikeHomeStack.o \ + temp/obj/KlondikeBoard.o \ + temp/obj/FreeCellBoard.o \ + temp/obj/FreeCellDeck.o \ + temp/obj/FreeCellStack.o \ + temp/obj/FreeCellHome.o \ + temp/obj/FreeCellFree.o \ + temp/obj/Spider3DeckBoard.o \ + temp/obj/SpideretteBoard.o \ + temp/obj/YukonBoard.o \ + temp/obj/moc_QSoloCardsPlugin.o \ + temp/obj/moc_mainwindow.o \ + temp/obj/moc_CardStack.o \ + temp/obj/moc_DragCardStack.o \ + temp/obj/moc_VCardStack.o \ + temp/obj/moc_CardAnimationLock.o \ + temp/obj/moc_StackToStackAniMove.o \ + temp/obj/moc_DealAnimation.o \ + temp/obj/moc_FlipAnimation.o \ + temp/obj/moc_StackToStackFlipAni.o \ + temp/obj/moc_GameBoard.o \ + temp/obj/moc_About.o \ + temp/obj/moc_Help.o \ + temp/obj/moc_SpiderBoard.o \ + temp/obj/moc_SpiderStack.o \ + temp/obj/moc_KlondikeStack.o \ + temp/obj/moc_KlondikeFlipStack.o \ + temp/obj/moc_KlondikeHomeStack.o \ + temp/obj/moc_KlondikeBoard.o \ + temp/obj/moc_FreeCellBoard.o \ + temp/obj/moc_FreeCellDeck.o \ + temp/obj/moc_FreeCellStack.o \ + temp/obj/moc_FreeCellHome.o \ + temp/obj/moc_FreeCellFree.o \ + temp/obj/moc_Spider3DeckBoard.o \ + temp/obj/moc_SpideretteBoard.o \ + temp/obj/moc_YukonBoard.o \ + temp/obj/qrc_QSoloCards.o +DIST = +QMAKE_TARGET = qsolocards_plugin +DESTDIR = ..\..\bin\ #avoid trailing-slash linebreak +TARGET = qsolocards_plugin0.dll +DESTDIR_TARGET = ..\..\bin\qsolocards_plugin0.dll + +####### Implicit rules + +.SUFFIXES: .cpp .cc .cxx .c + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $< + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< + +####### Build rules + +first: all +all: Makefile.Release $(DESTDIR_TARGET) + +$(DESTDIR_TARGET): $(OBJECTS) + $(LINK) $(LFLAGS) -o $(DESTDIR_TARGET) object_script.qsolocards_plugin.Release $(LIBS) + + +qmake: FORCE + @$(QMAKE) -win32 -o Makefile.Release qsolocards_plugin.pro + +dist: + $(ZIP) qsolocards_plugin.zip $(SOURCES) $(DIST) qsolocards_plugin.pro d:\Qt\2010.01\qt\mkspecs\qconfig.pri d:\Qt\2010.01\qt\mkspecs\features\qt_functions.prf d:\Qt\2010.01\qt\mkspecs\features\qt_config.prf d:\Qt\2010.01\qt\mkspecs\features\exclusive_builds.prf d:\Qt\2010.01\qt\mkspecs\features\default_pre.prf d:\Qt\2010.01\qt\mkspecs\features\win32\default_pre.prf d:\Qt\2010.01\qt\mkspecs\features\release.prf d:\Qt\2010.01\qt\mkspecs\features\debug_and_release.prf d:\Qt\2010.01\qt\mkspecs\features\default_post.prf d:\Qt\2010.01\qt\mkspecs\features\win32\default_post.prf d:\Qt\2010.01\qt\mkspecs\features\build_pass.prf d:\Qt\2010.01\qt\mkspecs\features\win32\rtti.prf d:\Qt\2010.01\qt\mkspecs\features\win32\exceptions.prf d:\Qt\2010.01\qt\mkspecs\features\win32\stl.prf d:\Qt\2010.01\qt\mkspecs\features\shared.prf d:\Qt\2010.01\qt\mkspecs\features\dll.prf d:\Qt\2010.01\qt\mkspecs\features\warn_on.prf d:\Qt\2010.01\qt\mkspecs\features\qt.prf d:\Qt\2010.01\qt\mkspecs\features\win32\thread.prf d:\Qt\2010.01\qt\mkspecs\features\moc.prf d:\Qt\2010.01\qt\mkspecs\features\win32\windows.prf d:\Qt\2010.01\qt\mkspecs\features\resources.prf d:\Qt\2010.01\qt\mkspecs\features\uic.prf d:\Qt\2010.01\qt\mkspecs\features\yacc.prf d:\Qt\2010.01\qt\mkspecs\features\lex.prf HEADERS RESOURCES IMAGES SOURCES OBJECTIVE_SOURCES FORMS YACCSOURCES YACCSOURCES LEXSOURCES + +clean: compiler_clean + -$(DEL_FILE) temp\obj\QSoloCardsPlugin.o temp\obj\main.o temp\obj\mainwindow.o temp\obj\PlayingCard.o temp\obj\CardDeck.o temp\obj\CardPixmaps.o temp\obj\CardStack.o temp\obj\DragCardStack.o temp\obj\VCardStack.o temp\obj\CardAnimationLock.o temp\obj\StackToStackAniMove.o temp\obj\DealAnimation.o temp\obj\FlipAnimation.o temp\obj\StackToStackFlipAni.o temp\obj\GameBoard.o temp\obj\CardMoveRecord.o temp\obj\About.o temp\obj\Help.o temp\obj\GameMgr.o temp\obj\SpiderBoard.o temp\obj\SpiderHomeStack.o temp\obj\SpiderStack.o temp\obj\KlondikeStack.o temp\obj\KlondikeFlipStack.o temp\obj\KlondikeHomeStack.o temp\obj\KlondikeBoard.o temp\obj\FreeCellBoard.o temp\obj\FreeCellDeck.o temp\obj\FreeCellStack.o temp\obj\FreeCellHome.o temp\obj\FreeCellFree.o temp\obj\Spider3DeckBoard.o temp\obj\SpideretteBoard.o temp\obj\YukonBoard.o temp\obj\moc_QSoloCardsPlugin.o temp\obj\moc_mainwindow.o temp\obj\moc_CardStack.o temp\obj\moc_DragCardStack.o temp\obj\moc_VCardStack.o temp\obj\moc_CardAnimationLock.o temp\obj\moc_StackToStackAniMove.o temp\obj\moc_DealAnimation.o temp\obj\moc_FlipAnimation.o temp\obj\moc_StackToStackFlipAni.o temp\obj\moc_GameBoard.o temp\obj\moc_About.o temp\obj\moc_Help.o temp\obj\moc_SpiderBoard.o temp\obj\moc_SpiderStack.o temp\obj\moc_KlondikeStack.o temp\obj\moc_KlondikeFlipStack.o temp\obj\moc_KlondikeHomeStack.o temp\obj\moc_KlondikeBoard.o temp\obj\moc_FreeCellBoard.o temp\obj\moc_FreeCellDeck.o temp\obj\moc_FreeCellStack.o temp\obj\moc_FreeCellHome.o temp\obj\moc_FreeCellFree.o temp\obj\moc_Spider3DeckBoard.o temp\obj\moc_SpideretteBoard.o temp\obj\moc_YukonBoard.o temp\obj\qrc_QSoloCards.o + -$(DEL_FILE) ..\..\bin\libqsolocards_plugin0.a + +distclean: clean + -$(DEL_FILE) $(DESTDIR_TARGET) + -$(DEL_FILE) Makefile.Release + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: temp/moc/moc_QSoloCardsPlugin.cpp temp/moc/moc_mainwindow.cpp temp/moc/moc_CardStack.cpp temp/moc/moc_DragCardStack.cpp temp/moc/moc_VCardStack.cpp temp/moc/moc_CardAnimationLock.cpp temp/moc/moc_StackToStackAniMove.cpp temp/moc/moc_DealAnimation.cpp temp/moc/moc_FlipAnimation.cpp temp/moc/moc_StackToStackFlipAni.cpp temp/moc/moc_GameBoard.cpp temp/moc/moc_About.cpp temp/moc/moc_Help.cpp temp/moc/moc_SpiderBoard.cpp temp/moc/moc_SpiderStack.cpp temp/moc/moc_KlondikeStack.cpp temp/moc/moc_KlondikeFlipStack.cpp temp/moc/moc_KlondikeHomeStack.cpp temp/moc/moc_KlondikeBoard.cpp temp/moc/moc_FreeCellBoard.cpp temp/moc/moc_FreeCellDeck.cpp temp/moc/moc_FreeCellStack.cpp temp/moc/moc_FreeCellHome.cpp temp/moc/moc_FreeCellFree.cpp temp/moc/moc_Spider3DeckBoard.cpp temp/moc/moc_SpideretteBoard.cpp temp/moc/moc_YukonBoard.cpp +compiler_moc_header_clean: + -$(DEL_FILE) temp\moc\moc_QSoloCardsPlugin.cpp temp\moc\moc_mainwindow.cpp temp\moc\moc_CardStack.cpp temp\moc\moc_DragCardStack.cpp temp\moc\moc_VCardStack.cpp temp\moc\moc_CardAnimationLock.cpp temp\moc\moc_StackToStackAniMove.cpp temp\moc\moc_DealAnimation.cpp temp\moc\moc_FlipAnimation.cpp temp\moc\moc_StackToStackFlipAni.cpp temp\moc\moc_GameBoard.cpp temp\moc\moc_About.cpp temp\moc\moc_Help.cpp temp\moc\moc_SpiderBoard.cpp temp\moc\moc_SpiderStack.cpp temp\moc\moc_KlondikeStack.cpp temp\moc\moc_KlondikeFlipStack.cpp temp\moc\moc_KlondikeHomeStack.cpp temp\moc\moc_KlondikeBoard.cpp temp\moc\moc_FreeCellBoard.cpp temp\moc\moc_FreeCellDeck.cpp temp\moc\moc_FreeCellStack.cpp temp\moc\moc_FreeCellHome.cpp temp\moc\moc_FreeCellFree.cpp temp\moc\moc_Spider3DeckBoard.cpp temp\moc\moc_SpideretteBoard.cpp temp\moc\moc_YukonBoard.cpp +temp/moc/moc_QSoloCardsPlugin.cpp: QSoloCardsPlugin.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 QSoloCardsPlugin.h -o temp\moc\moc_QSoloCardsPlugin.cpp + +temp/moc/moc_mainwindow.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + Help.h \ + About.h \ + GameMgr.h \ + mainwindow.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 mainwindow.h -o temp\moc\moc_mainwindow.cpp + +temp/moc/moc_CardStack.cpp: CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 CardStack.h -o temp\moc\moc_CardStack.cpp + +temp/moc/moc_DragCardStack.cpp: CardDeck.h \ + PlayingCard.h \ + CardMoveRecord.h \ + DragCardStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 DragCardStack.h -o temp\moc\moc_DragCardStack.cpp + +temp/moc/moc_VCardStack.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + VCardStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 VCardStack.h -o temp\moc\moc_VCardStack.cpp + +temp/moc/moc_CardAnimationLock.cpp: CardAnimationLock.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 CardAnimationLock.h -o temp\moc\moc_CardAnimationLock.cpp + +temp/moc/moc_StackToStackAniMove.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 StackToStackAniMove.h -o temp\moc\moc_StackToStackAniMove.cpp + +temp/moc/moc_DealAnimation.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + DealAnimation.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 DealAnimation.h -o temp\moc\moc_DealAnimation.cpp + +temp/moc/moc_FlipAnimation.cpp: CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FlipAnimation.h -o temp\moc\moc_FlipAnimation.cpp + +temp/moc/moc_StackToStackFlipAni.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackFlipAni.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 StackToStackFlipAni.h -o temp\moc\moc_StackToStackFlipAni.cpp + +temp/moc/moc_GameBoard.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + GameBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 GameBoard.h -o temp\moc\moc_GameBoard.cpp + +temp/moc/moc_About.cpp: About.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 About.h -o temp\moc\moc_About.cpp + +temp/moc/moc_Help.cpp: Help.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 Help.h -o temp\moc\moc_Help.cpp + +temp/moc/moc_SpiderBoard.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + SpiderBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 SpiderBoard.h -o temp\moc\moc_SpiderBoard.cpp + +temp/moc/moc_SpiderStack.cpp: VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + SpiderStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 SpiderStack.h -o temp\moc\moc_SpiderStack.cpp + +temp/moc/moc_KlondikeStack.cpp: VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + KlondikeStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 KlondikeStack.h -o temp\moc\moc_KlondikeStack.cpp + +temp/moc/moc_KlondikeFlipStack.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + KlondikeFlipStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 KlondikeFlipStack.h -o temp\moc\moc_KlondikeFlipStack.cpp + +temp/moc/moc_KlondikeHomeStack.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + KlondikeHomeStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 KlondikeHomeStack.h -o temp\moc\moc_KlondikeHomeStack.cpp + +temp/moc/moc_KlondikeBoard.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + KlondikeStack.h \ + VCardStack.h \ + KlondikeHomeStack.h \ + KlondikeFlipStack.h \ + StackToStackFlipAni.h \ + KlondikeBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 KlondikeBoard.h -o temp\moc\moc_KlondikeBoard.cpp + +temp/moc/moc_FreeCellBoard.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + FreeCellDeck.h \ + FreeCellFree.h \ + FreeCellStack.h \ + VCardStack.h \ + FreeCellHome.h \ + FreeCellBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellBoard.h -o temp\moc\moc_FreeCellBoard.cpp + +temp/moc/moc_FreeCellDeck.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + FreeCellDeck.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellDeck.h -o temp\moc\moc_FreeCellDeck.cpp + +temp/moc/moc_FreeCellStack.cpp: VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + FreeCellStack.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellStack.h -o temp\moc\moc_FreeCellStack.cpp + +temp/moc/moc_FreeCellHome.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + FreeCellHome.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellHome.h -o temp\moc\moc_FreeCellHome.cpp + +temp/moc/moc_FreeCellFree.cpp: CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + FreeCellFree.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 FreeCellFree.h -o temp\moc\moc_FreeCellFree.cpp + +temp/moc/moc_Spider3DeckBoard.cpp: SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + Spider3DeckBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 Spider3DeckBoard.h -o temp\moc\moc_Spider3DeckBoard.cpp + +temp/moc/moc_SpideretteBoard.cpp: SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + SpideretteBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 SpideretteBoard.h -o temp\moc\moc_SpideretteBoard.cpp + +temp/moc/moc_YukonBoard.cpp: GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + FreeCellHome.h \ + FreeCellDeck.h \ + KlondikeStack.h \ + VCardStack.h \ + YukonBoard.h + d:/Qt/2010.01/qt/bin\moc.exe $(DEFINES) $(INCPATH) -D__GNUC__ -DWIN32 YukonBoard.h -o temp\moc\moc_YukonBoard.cpp + +compiler_rcc_make_all: temp/qrc/qrc_QSoloCards.cpp +compiler_rcc_clean: + -$(DEL_FILE) temp\qrc\qrc_QSoloCards.cpp +temp/qrc/qrc_QSoloCards.cpp: QSoloCards.qrc \ + images/greenfelt.png \ + images/anglo_bitmap.svg \ + images/sol128x128.png \ + images/sol32x32.png \ + help/FreeCellHelp.html \ + help/SpideretteHelp.html \ + help/YukonHelp.html \ + help/SpiderHelp.html \ + help/Spider3DeckHelp.html \ + help/KlondikeHelp.html \ + help/gpl3.html + d:\Qt\2010.01\qt\bin\rcc.exe -name QSoloCards QSoloCards.qrc -o temp\qrc\qrc_QSoloCards.cpp + +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean compiler_rcc_clean + + + +####### Compile + +temp/obj/QSoloCardsPlugin.o: QSoloCardsPlugin.cpp QSoloCardsPlugin.h \ + mainwindow.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + Help.h \ + About.h \ + GameMgr.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\QSoloCardsPlugin.o QSoloCardsPlugin.cpp + +temp/obj/main.o: main.cpp mainwindow.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + Help.h \ + About.h \ + GameMgr.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\main.o main.cpp + +temp/obj/mainwindow.o: mainwindow.cpp mainwindow.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + Help.h \ + About.h \ + GameMgr.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\mainwindow.o mainwindow.cpp + +temp/obj/PlayingCard.o: PlayingCard.cpp PlayingCard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\PlayingCard.o PlayingCard.cpp + +temp/obj/CardDeck.o: CardDeck.cpp CardDeck.h \ + PlayingCard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardDeck.o CardDeck.cpp + +temp/obj/CardPixmaps.o: CardPixmaps.cpp CardPixmaps.h \ + PlayingCard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardPixmaps.o CardPixmaps.cpp + +temp/obj/CardStack.o: CardStack.cpp CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardPixmaps.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardStack.o CardStack.cpp + +temp/obj/DragCardStack.o: DragCardStack.cpp DragCardStack.h \ + CardDeck.h \ + PlayingCard.h \ + CardMoveRecord.h \ + CardStack.h \ + FlipAnimation.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\DragCardStack.o DragCardStack.cpp + +temp/obj/VCardStack.o: VCardStack.cpp VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\VCardStack.o VCardStack.cpp + +temp/obj/CardAnimationLock.o: CardAnimationLock.cpp CardAnimationLock.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardAnimationLock.o CardAnimationLock.cpp + +temp/obj/StackToStackAniMove.o: StackToStackAniMove.cpp StackToStackAniMove.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\StackToStackAniMove.o StackToStackAniMove.cpp + +temp/obj/DealAnimation.o: DealAnimation.cpp DealAnimation.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\DealAnimation.o DealAnimation.cpp + +temp/obj/FlipAnimation.o: FlipAnimation.cpp FlipAnimation.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + CardStack.h \ + DragCardStack.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FlipAnimation.o FlipAnimation.cpp + +temp/obj/StackToStackFlipAni.o: StackToStackFlipAni.cpp StackToStackFlipAni.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardAnimationLock.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\StackToStackFlipAni.o StackToStackFlipAni.cpp + +temp/obj/GameBoard.o: GameBoard.cpp GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + CardPixmaps.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\GameBoard.o GameBoard.cpp + +temp/obj/CardMoveRecord.o: CardMoveRecord.cpp CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\CardMoveRecord.o CardMoveRecord.cpp + +temp/obj/About.o: About.cpp About.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\About.o About.cpp + +temp/obj/Help.o: Help.cpp Help.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\Help.o Help.cpp + +temp/obj/GameMgr.o: GameMgr.cpp GameMgr.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderBoard.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + Spider3DeckBoard.h \ + SpideretteBoard.h \ + KlondikeBoard.h \ + KlondikeStack.h \ + KlondikeHomeStack.h \ + KlondikeFlipStack.h \ + StackToStackFlipAni.h \ + FreeCellBoard.h \ + FreeCellDeck.h \ + FreeCellFree.h \ + FreeCellStack.h \ + FreeCellHome.h \ + YukonBoard.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\GameMgr.o GameMgr.cpp + +temp/obj/SpiderBoard.o: SpiderBoard.cpp SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\SpiderBoard.o SpiderBoard.cpp + +temp/obj/SpiderHomeStack.o: SpiderHomeStack.cpp SpiderHomeStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\SpiderHomeStack.o SpiderHomeStack.cpp + +temp/obj/SpiderStack.o: SpiderStack.cpp SpiderStack.h \ + VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + SpiderHomeStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\SpiderStack.o SpiderStack.cpp + +temp/obj/KlondikeStack.o: KlondikeStack.cpp KlondikeStack.h \ + VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\KlondikeStack.o KlondikeStack.cpp + +temp/obj/KlondikeFlipStack.o: KlondikeFlipStack.cpp KlondikeFlipStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\KlondikeFlipStack.o KlondikeFlipStack.cpp + +temp/obj/KlondikeHomeStack.o: KlondikeHomeStack.cpp KlondikeHomeStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\KlondikeHomeStack.o KlondikeHomeStack.cpp + +temp/obj/KlondikeBoard.o: KlondikeBoard.cpp KlondikeBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + KlondikeStack.h \ + VCardStack.h \ + KlondikeHomeStack.h \ + KlondikeFlipStack.h \ + StackToStackFlipAni.h \ + CardPixmaps.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\KlondikeBoard.o KlondikeBoard.cpp + +temp/obj/FreeCellBoard.o: FreeCellBoard.cpp FreeCellBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + FreeCellDeck.h \ + FreeCellFree.h \ + FreeCellStack.h \ + VCardStack.h \ + FreeCellHome.h \ + CardPixmaps.h \ + CardAnimationLock.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellBoard.o FreeCellBoard.cpp + +temp/obj/FreeCellDeck.o: FreeCellDeck.cpp FreeCellDeck.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellDeck.o FreeCellDeck.cpp + +temp/obj/FreeCellStack.o: FreeCellStack.cpp FreeCellStack.h \ + VCardStack.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellStack.o FreeCellStack.cpp + +temp/obj/FreeCellHome.o: FreeCellHome.cpp FreeCellHome.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellHome.o FreeCellHome.cpp + +temp/obj/FreeCellFree.o: FreeCellFree.cpp FreeCellFree.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\FreeCellFree.o FreeCellFree.cpp + +temp/obj/Spider3DeckBoard.o: Spider3DeckBoard.cpp Spider3DeckBoard.h \ + SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\Spider3DeckBoard.o Spider3DeckBoard.cpp + +temp/obj/SpideretteBoard.o: SpideretteBoard.cpp SpideretteBoard.h \ + SpiderBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + SpiderStack.h \ + VCardStack.h \ + SpiderHomeStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\SpideretteBoard.o SpideretteBoard.cpp + +temp/obj/YukonBoard.o: YukonBoard.cpp YukonBoard.h \ + GameBoard.h \ + CardStack.h \ + CardMoveRecord.h \ + CardDeck.h \ + PlayingCard.h \ + FlipAnimation.h \ + DragCardStack.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + FreeCellHome.h \ + FreeCellDeck.h \ + KlondikeStack.h \ + VCardStack.h \ + CardPixmaps.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\YukonBoard.o YukonBoard.cpp + +temp/obj/moc_QSoloCardsPlugin.o: temp/moc/moc_QSoloCardsPlugin.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_QSoloCardsPlugin.o temp\moc\moc_QSoloCardsPlugin.cpp + +temp/obj/moc_mainwindow.o: temp/moc/moc_mainwindow.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_mainwindow.o temp\moc\moc_mainwindow.cpp + +temp/obj/moc_CardStack.o: temp/moc/moc_CardStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_CardStack.o temp\moc\moc_CardStack.cpp + +temp/obj/moc_DragCardStack.o: temp/moc/moc_DragCardStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_DragCardStack.o temp\moc\moc_DragCardStack.cpp + +temp/obj/moc_VCardStack.o: temp/moc/moc_VCardStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_VCardStack.o temp\moc\moc_VCardStack.cpp + +temp/obj/moc_CardAnimationLock.o: temp/moc/moc_CardAnimationLock.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_CardAnimationLock.o temp\moc\moc_CardAnimationLock.cpp + +temp/obj/moc_StackToStackAniMove.o: temp/moc/moc_StackToStackAniMove.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_StackToStackAniMove.o temp\moc\moc_StackToStackAniMove.cpp + +temp/obj/moc_DealAnimation.o: temp/moc/moc_DealAnimation.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_DealAnimation.o temp\moc\moc_DealAnimation.cpp + +temp/obj/moc_FlipAnimation.o: temp/moc/moc_FlipAnimation.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FlipAnimation.o temp\moc\moc_FlipAnimation.cpp + +temp/obj/moc_StackToStackFlipAni.o: temp/moc/moc_StackToStackFlipAni.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_StackToStackFlipAni.o temp\moc\moc_StackToStackFlipAni.cpp + +temp/obj/moc_GameBoard.o: temp/moc/moc_GameBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_GameBoard.o temp\moc\moc_GameBoard.cpp + +temp/obj/moc_About.o: temp/moc/moc_About.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_About.o temp\moc\moc_About.cpp + +temp/obj/moc_Help.o: temp/moc/moc_Help.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_Help.o temp\moc\moc_Help.cpp + +temp/obj/moc_SpiderBoard.o: temp/moc/moc_SpiderBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_SpiderBoard.o temp\moc\moc_SpiderBoard.cpp + +temp/obj/moc_SpiderStack.o: temp/moc/moc_SpiderStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_SpiderStack.o temp\moc\moc_SpiderStack.cpp + +temp/obj/moc_KlondikeStack.o: temp/moc/moc_KlondikeStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_KlondikeStack.o temp\moc\moc_KlondikeStack.cpp + +temp/obj/moc_KlondikeFlipStack.o: temp/moc/moc_KlondikeFlipStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_KlondikeFlipStack.o temp\moc\moc_KlondikeFlipStack.cpp + +temp/obj/moc_KlondikeHomeStack.o: temp/moc/moc_KlondikeHomeStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_KlondikeHomeStack.o temp\moc\moc_KlondikeHomeStack.cpp + +temp/obj/moc_KlondikeBoard.o: temp/moc/moc_KlondikeBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_KlondikeBoard.o temp\moc\moc_KlondikeBoard.cpp + +temp/obj/moc_FreeCellBoard.o: temp/moc/moc_FreeCellBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellBoard.o temp\moc\moc_FreeCellBoard.cpp + +temp/obj/moc_FreeCellDeck.o: temp/moc/moc_FreeCellDeck.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellDeck.o temp\moc\moc_FreeCellDeck.cpp + +temp/obj/moc_FreeCellStack.o: temp/moc/moc_FreeCellStack.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellStack.o temp\moc\moc_FreeCellStack.cpp + +temp/obj/moc_FreeCellHome.o: temp/moc/moc_FreeCellHome.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellHome.o temp\moc\moc_FreeCellHome.cpp + +temp/obj/moc_FreeCellFree.o: temp/moc/moc_FreeCellFree.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_FreeCellFree.o temp\moc\moc_FreeCellFree.cpp + +temp/obj/moc_Spider3DeckBoard.o: temp/moc/moc_Spider3DeckBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_Spider3DeckBoard.o temp\moc\moc_Spider3DeckBoard.cpp + +temp/obj/moc_SpideretteBoard.o: temp/moc/moc_SpideretteBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_SpideretteBoard.o temp\moc\moc_SpideretteBoard.cpp + +temp/obj/moc_YukonBoard.o: temp/moc/moc_YukonBoard.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\moc_YukonBoard.o temp\moc\moc_YukonBoard.cpp + +temp/obj/qrc_QSoloCards.o: temp/qrc/qrc_QSoloCards.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o temp\obj\qrc_QSoloCards.o temp\qrc\qrc_QSoloCards.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/plugins/qsolocards_plugin/PlayingCard.cpp b/plugins/qsolocards_plugin/PlayingCard.cpp new file mode 100644 index 000000000..3528d7f52 --- /dev/null +++ b/plugins/qsolocards_plugin/PlayingCard.cpp @@ -0,0 +1,174 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "PlayingCard.h" + +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +PlayingCard::PlayingCard(PlayingCard::Suit suit, + PlayingCard::CardIndex index, + bool isFaceUp) + :m_suit(suit), + m_index(index), + m_isFaceUp(isFaceUp), + m_textStr(NULL) +{ + this->setTextStr(); +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +PlayingCard::PlayingCard(const PlayingCard & playingCard) + :m_textStr(NULL) +{ + *this=playingCard; +} + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +PlayingCard::~PlayingCard() +{ + delete []m_textStr; +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +unsigned short PlayingCard::hashValue() const +{ + return m_suit*MaxCardIndex + m_index; +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +PlayingCard PlayingCard::cardFromHashValue(unsigned short value) +{ + PlayingCard card(PlayingCard::MaxSuit,PlayingCard::MaxCardIndex); + // if the value is valid set the suit and index + if (value(const PlayingCard & rh) const +{ + return m_index>rh.getIndex(); +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +PlayingCard & PlayingCard::operator=(const PlayingCard & rh) +{ + m_suit=rh.getSuit(); + m_index=rh.getIndex(); + this->setFaceUp(rh.isFaceUp()); + setTextStr(); + return *this; +} + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +bool PlayingCard::isNextCardIndex(const PlayingCard & rh) const +{ + return m_index+1==rh.getIndex(); +} + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +bool PlayingCard::isPrevCardIndex(const PlayingCard & rh) const +{ + return m_index-1==rh.getIndex(); +} + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +void PlayingCard::setTextStr() +{ + std::string cardValue; + + switch (m_index) + { + case Ace: + cardValue="1"; + break; + case Jack: + cardValue="jack"; + break; + case Queen: + cardValue="queen"; + break; + case King: + cardValue="king"; + break; + case MaxCardIndex: + cardValue="invalid"; + break; + default: + { + char cardNumStr[20]; + sprintf(cardNumStr,"%i",(int)m_index+1); + cardValue=cardNumStr; + }; + break; + }; + + cardValue+="_"; + + switch (m_suit) + { + case Clubs: + cardValue+="club"; + break; + case Spades: + cardValue+="spade"; + break; + case Hearts: + cardValue+="heart"; + break; + case Diamonds: + cardValue+="diamond"; + break; + default: + cardValue+="Invalid Suit"; + break; + }; + + delete []m_textStr; + + this->m_textStr=new char[cardValue.size()+1]; + + strcpy(this->m_textStr,cardValue.c_str()); +} diff --git a/plugins/qsolocards_plugin/PlayingCard.h b/plugins/qsolocards_plugin/PlayingCard.h new file mode 100644 index 000000000..585460e51 --- /dev/null +++ b/plugins/qsolocards_plugin/PlayingCard.h @@ -0,0 +1,100 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PLAYINGCARD_H +#define PLAYINGCARD_H + +class PlayingCard +{ + public: + enum Suit + { + Clubs=0, + Diamonds=1, + Hearts=2, + Spades=3, + MaxSuit=4 + }; + + + enum CardIndex + { + Ace=0, + Two=1, + Three=2, + Four=3, + Five=4, + Six=5, + Seven=6, + Eight=7, + Nine=8, + Ten=9, + Jack=10, + Queen=11, + King=12, + MaxCardIndex=13 + }; + + PlayingCard(Suit suit=PlayingCard::MaxSuit, + CardIndex index=PlayingCard::MaxCardIndex, + bool isFaceUp=false); + PlayingCard(const PlayingCard & playingCard); + + virtual ~PlayingCard(); + + // a value to uniquely id the card + unsigned short hashValue() const; + static PlayingCard cardFromHashValue(unsigned short value); + + Suit getSuit() const {return m_suit;} + CardIndex getIndex() const {return m_index;} + + inline bool isValid() const{return (MaxSuit!=m_suit && MaxCardIndex!=m_index);} + + inline bool isSameSuit(const PlayingCard & cmp) const{return cmp.getSuit()==m_suit;} + inline bool isSameIndex(const PlayingCard & cmp) const{return cmp.getIndex()==m_index;} + + inline bool isRed() const{return ((PlayingCard::Diamonds==m_suit || PlayingCard::Hearts==m_suit)?true:false);} + inline bool isBlack() const{return ((PlayingCard::Spades==m_suit || PlayingCard::Clubs==m_suit)?true:false);} + + inline bool isFaceUp() const {return m_isFaceUp;} + inline void setFaceUp(bool state=true) {m_isFaceUp=state;} + + + inline bool operator==(const PlayingCard & rh) const {return (isSameSuit(rh) && isSameIndex(rh));} + + PlayingCard & operator=(const PlayingCard & rh); + + virtual bool operator<(const PlayingCard & rh) const; + virtual bool operator>(const PlayingCard & rh) const; + + virtual bool isNextCardIndex(const PlayingCard & rh) const; + virtual bool isPrevCardIndex(const PlayingCard & rh) const; + + inline const char * asString() const{return m_textStr;} + + private: + + void setTextStr(); + + Suit m_suit; + CardIndex m_index; + bool m_isFaceUp; + char * m_textStr; +}; +#endif // PLAYINGCARD_H diff --git a/plugins/qsolocards_plugin/QSoloCards.icns b/plugins/qsolocards_plugin/QSoloCards.icns new file mode 100644 index 000000000..e148c0daa Binary files /dev/null and b/plugins/qsolocards_plugin/QSoloCards.icns differ diff --git a/plugins/qsolocards_plugin/QSoloCards.qrc b/plugins/qsolocards_plugin/QSoloCards.qrc new file mode 100644 index 000000000..fe8c2c4c3 --- /dev/null +++ b/plugins/qsolocards_plugin/QSoloCards.qrc @@ -0,0 +1,15 @@ + + + images/greenfelt.png + images/anglo_bitmap.svg + images/sol32x32.png + images/sol128x128.png + help/SpiderHelp.html + help/Spider3DeckHelp.html + help/SpideretteHelp.html + help/KlondikeHelp.html + help/FreeCellHelp.html + help/YukonHelp.html + help/gpl3.html + + diff --git a/plugins/qsolocards_plugin/QSoloCardsPlugin.cpp b/plugins/qsolocards_plugin/QSoloCardsPlugin.cpp new file mode 100644 index 000000000..dcb4d6760 --- /dev/null +++ b/plugins/qsolocards_plugin/QSoloCardsPlugin.cpp @@ -0,0 +1,53 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +//#include +//#include +//#include + +#include "QSoloCardsPlugin.h" +#include "mainwindow.h" + +QString +QSoloCardsPlugin::pluginDescription() const +{ + QString res; + res = "a QSoloCards plugin" ; + + return res; +} + +QString +QSoloCardsPlugin::pluginName() const +{ + return "QSoloCards" ; +} + +QWidget* +QSoloCardsPlugin::pluginWidget(QWidget * parent ) +{ + MainWindow* window = new MainWindow(); + + return window; +} + + +Q_EXPORT_PLUGIN2(qsolocards_plugin, QSoloCardsPlugin) diff --git a/plugins/qsolocards_plugin/QSoloCardsPlugin.h b/plugins/qsolocards_plugin/QSoloCardsPlugin.h new file mode 100644 index 000000000..9537132df --- /dev/null +++ b/plugins/qsolocards_plugin/QSoloCardsPlugin.h @@ -0,0 +1,48 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _QSOLOCARDS_PLUGIN_H_ +#define _QSOLOCARDS_PLUGIN_H_ + +#include + +#include +#include + +#include + +#include + +class QSoloCardsPlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/qsolocards_plugin/Spider3DeckBoard.cpp b/plugins/qsolocards_plugin/Spider3DeckBoard.cpp new file mode 100644 index 000000000..1bd4ecc94 --- /dev/null +++ b/plugins/qsolocards_plugin/Spider3DeckBoard.cpp @@ -0,0 +1,181 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "Spider3DeckBoard.h" +#include "CardPixmaps.h" + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +Spider3DeckBoard::Spider3DeckBoard() + :SpiderBoard() +{ + this->setGameName(QString(tr("Three Deck Spider Solitaire")).trimmed()); + this->setGameId("ThreeDeckSpider"); + + this->setHelpFile(":/help/Spider3DeckHelp.html"); +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +Spider3DeckBoard::~Spider3DeckBoard() +{ +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void Spider3DeckBoard::newGame() +{ + // call the base class to do cleanup for us. + GameBoard::newGame(); + + CardDeck deck(3); + + // Put all cards in the m_pDeck stack. We will deal + // from this stack. + while(!deck.isEmpty()) + { + this->m_pDeck->addCard(deck.next()); + } + + unsigned int i; + unsigned int j; + + DealItemVector dealItemVector; + + // Create the dealItemVector to direct the DealAnimation object on + // how to deal the cards. + for (i=0;im_stackVector.size();i++) + { + unsigned int cardsInStack=((i<6)?5:4); + + dealItemVector.push_back(DealItem(this->m_stackVector[i],m_pDeck)); + + for (j=0;jsetPos(currPos); + + currPos.rx()+=GameBoard::LayoutSpacing+cardSize.width(); + + for (i=0;isetPos(currPos); + currPos.setX(currPos.x()+cardSize.width()+GameBoard::LayoutSpacing); + } + + currPos.setY(GameBoard::LayoutSpacing*2+cardSize.height()); + currPos.setX(GameBoard::LayoutSpacing*2+cardSize.width()); + for (i=0;isetPos(currPos); + currPos.setX(currPos.x()+cardSize.width()+GameBoard::LayoutSpacing); + } + +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +void Spider3DeckBoard::createStacks() +{ + setCardResizeAlg(13,ResizeByWidth); + + unsigned int i; + // create all the widgets for the board + for(i=0;i<12;i++) + { + this->m_homeVector.push_back(new SpiderHomeStack); + this->m_scene.addItem(m_homeVector[i]); + + // get signals when cards are added to the stack. So, we can add undo info and + // see when the game is over. + this->connect(this->m_homeVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + } + + for(i=0;i<12;i++) + { + this->m_stackVector.push_back(new SpiderStack); + this->m_scene.addItem(m_stackVector[i]); + + // get signals when cards are added to the stack. So, we can add undo info and + // see when the game is over. + this->connect(this->m_stackVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + this->connect(this->m_stackVector[i],SIGNAL(sendSuitHome(SpiderStack *,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotSendSuitHome(SpiderStack*,PlayingCardVector,CardMoveRecord))); + this->connect(this->m_stackVector[i],SIGNAL(moveCardsToDiffStack(SpiderStack *,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotMoveCardsToDiffStack(SpiderStack*,PlayingCardVector,CardMoveRecord))); + } + + m_pDeck=new CardStack; + this->m_scene.addItem(m_pDeck); + + // get signals when the deck is clicked on so we can deal the next set of cards + this->connect(this->m_pDeck,SIGNAL(cardClicked(CardStack*,uint)), + this,SLOT(slotDealNextCards(CardStack*,uint))); +} diff --git a/plugins/qsolocards_plugin/Spider3DeckBoard.h b/plugins/qsolocards_plugin/Spider3DeckBoard.h new file mode 100644 index 000000000..3ce28bc07 --- /dev/null +++ b/plugins/qsolocards_plugin/Spider3DeckBoard.h @@ -0,0 +1,43 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __SPIDER3DECKBOARD_H__ +#define __SPIDER3DECKBOARD_H__ + +#include "SpiderBoard.h" + +class Spider3DeckBoard:public SpiderBoard +{ + Q_OBJECT +public: + Spider3DeckBoard(); + virtual ~Spider3DeckBoard(); + + virtual void newGame(); + + virtual void addGameMenuItems(QMenu & menu); + + virtual void loadSettings(const QSettings & settings); + virtual void saveSettings(QSettings & settings); + +protected: + virtual void resizeEvent (QResizeEvent * event); + virtual void createStacks(); +}; + +#endif diff --git a/plugins/qsolocards_plugin/SpiderBoard.cpp b/plugins/qsolocards_plugin/SpiderBoard.cpp new file mode 100644 index 000000000..ae7a58bc4 --- /dev/null +++ b/plugins/qsolocards_plugin/SpiderBoard.cpp @@ -0,0 +1,754 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "SpiderBoard.h" +#include +#include +#include +#include +#include + +#include "CardPixmaps.h" +#include "CardDeck.h" + + +#include + +const QString SpiderBoard::GameTypeKeyStr("GameType"); + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +SpiderBoard::SpiderBoard(QWidget * pWidget) + :GameBoard(pWidget,QString(tr("Spider Solitaire")).trimmed(),QString("Spider")), + m_pDeck(NULL), + m_homeVector(), + m_stackVector(), + m_cheat(false), + m_gameType(SpiderBoard::FourSuits) +{ + this->setHelpFile(":/help/SpiderHelp.html"); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +SpiderBoard::~SpiderBoard() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// ok this is an attempt to offer hint moves. It will prefer same suit moves, then +// consecutive index matches, and then card to empty stack moves. It will try to +// move all cards that are movable in a stack. So, there are possibilities for +// tweaks. +//////////////////////////////////////////////////////////////////////////////// +bool SpiderBoard::getHint(CardStack * & pSrcWidget, + unsigned int & srcStackIndex, + CardStack * & pDstWidget) +{ + bool moveFound=false; + bool sameSuitFound=false; + bool nonSameSuitFound=false; + + CardStack * pCanMoveToEmpty=NULL; + CardStack * pCanMoveTo=NULL; + CardStack * pCanMoveToSameSuit=NULL; + bool newMoveFound=false; + int j; + + qsrand(QDateTime::currentDateTime().toTime_t()); + bool fromZero=((0==qrand()%2 ^ 1==qrand()%3)?true:false); // this introduces some randomness by selecting whether we are going + // to go through the stacks forward or backwards. + + + for ((fromZero?(j=0):(j=this->m_stackVector.size()-1)); + ((fromZero)?(j<(int)this->m_stackVector.size()):(j>=0))&& !sameSuitFound ;((fromZero)?(j++):(j--))) + { + PlayingCardVector cardVector; + unsigned int currSrcStackIndex; + bool fromZeroInner=((0==qrand()%2 ^ 1==qrand()%3)?true:false); // this introduces some randomness by selecting whether we are going + // to go through the stacks forward or backwards. + int i; + + newMoveFound=false; + + if (this->m_stackVector[j]->getMovableCards(cardVector,currSrcStackIndex)) + { + + // first see if the cards can be sent home + // the priority will be the same as a move to + // cards of the same suit + if (SpiderHomeStack::canSendHome(cardVector)) + { + // find an open home widget + for(unsigned int k=0;km_homeVector.size();k++) + { + if (this->m_homeVector[k]->isEmpty()) + { + pDstWidget=this->m_homeVector[k]; + break; + } + } + + if (NULL!=pDstWidget) + { + pSrcWidget=this->m_stackVector[j]; + srcStackIndex=currSrcStackIndex; + moveFound=true; + break; + } + } + + for ((fromZeroInner?(i=0):(i=this->m_stackVector.size()-1)); + ((fromZeroInner)?(i<(int)this->m_stackVector.size()):(i>=0)); + ((fromZeroInner)?(i++):(i--))) + { + + // ok we are only moving the cards if the hit is not on the same + // stack they are already located in + if (this->m_stackVector[i]!=this->m_stackVector[j]) + { + // see if we have a perferred move to a stack that has the same suit + // we will break out if we find a perferred match + if (this->m_stackVector[i]->canAddCardsSameSuit(cardVector)) + { + pCanMoveToSameSuit=this->m_stackVector[i]; + newMoveFound=true; + break; + } + // otherwise see if we can move the cards to the stack at all + else if (this->m_stackVector[i]->canAddCards(cardVector)) + { + if (this->m_stackVector[i]->isEmpty()) + { + pCanMoveToEmpty=this->m_stackVector[i]; + } + else + { + pCanMoveTo=this->m_stackVector[i]; + } + newMoveFound=true; + } + } + } + + if (newMoveFound) + { + // ok the best move is to a matching suit and consecutive + // next best is to a consecutive + // and lastly to an empty stack. + if (NULL!=pCanMoveToSameSuit) + { + pDstWidget=pCanMoveToSameSuit; + pSrcWidget=this->m_stackVector[j]; + srcStackIndex=currSrcStackIndex; + sameSuitFound=true; + } + else if (NULL!=pCanMoveTo && !nonSameSuitFound) + { + pDstWidget=pCanMoveTo; + pSrcWidget=this->m_stackVector[j]; + srcStackIndex=currSrcStackIndex; + nonSameSuitFound=true; + } + else if (NULL!=pCanMoveToEmpty && !nonSameSuitFound) + { + pDstWidget=pCanMoveToEmpty; + pSrcWidget=this->m_stackVector[j]; + srcStackIndex=currSrcStackIndex; + } + moveFound=true; + } + } + } + + + return moveFound; +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::newGame() +{ + // call the base class to do cleanup for us. + GameBoard::newGame(); + + CardDeck * pDeck=NULL; + + unsigned int i; + unsigned int j; + + switch(this->m_gameType) + { + case SpiderBoard::FourSuits: + pDeck=new CardDeck(2); + break; + + case SpiderBoard::TwoSuits: + { + PlayingCardVector cardVector; + // use hearts and spades as the two suits + for (i=PlayingCard::Ace;iisEmpty()) + { + this->m_pDeck->addCard(pDeck->next()); + } + + delete pDeck; + + + DealItemVector dealItemVector; + + + // Create the dealItemVector to direct the DealAnimation object on + // how to deal the cards. + for (i=0;im_stackVector.size();i++) + { + unsigned int cardsInStack=((i<4)?6:5); + + dealItemVector.push_back(DealItem(this->m_stackVector[i],m_pDeck)); + + for (j=0;jsetShortcut(QKeySequence(Qt::CTRL + Qt::Key_4)); + pFourSuitsAction->setCheckable(true); + connect(pFourSuitsAction,SIGNAL(triggered()), + this,SLOT(slotSetFourSuits())); + + QAction * pTwoSuitsAction=new QAction(tr("Two Suits").trimmed(),pNumSuitsGroup); + pTwoSuitsAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_2)); + pTwoSuitsAction->setCheckable(true); + connect(pTwoSuitsAction,SIGNAL(triggered()), + this,SLOT(slotSetTwoSuits())); + + QAction * pOneSuitAction=new QAction(tr("One Suit").trimmed(),pNumSuitsGroup); + pOneSuitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_1)); + pOneSuitAction->setCheckable(true); + connect(pOneSuitAction,SIGNAL(triggered()), + this,SLOT(slotSetOneSuit())); + + // select the correct item in the list + switch (this->m_gameType) + { + case SpiderBoard::FourSuits: + pFourSuitsAction->setChecked(true); + break; + + case SpiderBoard::TwoSuits: + pTwoSuitsAction->setChecked(true); + break; + + case SpiderBoard::OneSuit: + pOneSuitAction->setChecked(true); + break; + }; + + menu.addAction(pFourSuitsAction); + menu.addAction(pTwoSuitsAction); + menu.addAction(pOneSuitAction); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::loadSettings(const QSettings & settings) +{ + int gameType=settings.value(this->GameTypeKeyStr,SpiderBoard::FourSuits).toInt(); + + switch (gameType) + { + case SpiderBoard::OneSuit: + this->m_gameType=SpiderBoard::OneSuit; + break; + + case SpiderBoard::TwoSuits: + this->m_gameType=SpiderBoard::TwoSuits; + break; + + case SpiderBoard::FourSuits: + default: + this->m_gameType=SpiderBoard::FourSuits; + break; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::saveSettings(QSettings & settings) +{ + settings.setValue(this->GameTypeKeyStr,this->m_gameType); +} + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::setCheat(bool cheat) +{ + this->m_cheat=cheat; + + for(unsigned int i=0;im_stackVector.size();i++) + { + this->m_stackVector[i]->setCheat(cheat); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::slotDealNextCards(CardStack * pCardStackWidget, + unsigned int index) +{ + bool aStackIsEmpty=false; + unsigned int i; + + Q_UNUSED(pCardStackWidget); + Q_UNUSED(index); + + // if the deck has cards to deal make sure all the stacks have cards + // and deal them out + if (!this->m_pDeck->isEmpty()) + { + // first make sure none of the 10 stacks is empty. All must have at least one card. + // to be able to deal the cards. + for(i=0;im_stackVector.size();i++) + { + if (this->m_stackVector[i]->isEmpty()) + { + aStackIsEmpty=true; + break; + } + } + + + if (aStackIsEmpty) + { + QMessageBox::critical(this,this->gameName(), + tr("All stacks must contain at least one card before the next set of cards can be dealt!").trimmed()); + this->stopDemo(); + return; + } + + + DealItemVector dealItemVector; + + + // Create the dealItemVector to direct the DealAnimation object on + // how to deal the cards. + for (i=0;im_stackVector.size();i++) + { + dealItemVector.push_back(DealItem(this->m_stackVector[i],m_pDeck)); + + dealItemVector[i].addCard(true); + } + // ok now start the deal. + m_dealAni.dealCards(dealItemVector); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// ok we need to perform the move from the stackWidget to the sentHome widget +// and create the CardMoveRecord. Then just call slotCardsMoved and let the +// move be processed as if it was a drag and drop +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::slotSendSuitHome(SpiderStack * pStack, + const PlayingCardVector & cardVector, + const CardMoveRecord & startMoveRecord) +{ + if (NULL!=pStack) + { + // ok first find an empty sentHome widget to add the cards too. + SpiderHomeStack * pHome=NULL; + unsigned int i; + for (i=0;im_homeVector.size();i++) + { + if (this->m_homeVector[i]->isEmpty()) + { + pHome=this->m_homeVector[i]; + break; + } + } + + // we should always find an empty home widget. But check just in case + if (pHome) + { + CardMoveRecord moveRecord(startMoveRecord); + // add the cards to the update record. But don't move the + // cards + pHome->addCards(cardVector,moveRecord,true); + + // perform the move of the cards and animate it if animations + // are enabled + m_sToSAniMove.moveCards(moveRecord); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::slotMoveCardsToDiffStack(SpiderStack * pStack, + const PlayingCardVector & cardVector, + const CardMoveRecord & startMoveRecord) +{ + if (NULL!=pStack) + { + SpiderStack * pCanMoveToEmpty=NULL; + SpiderStack * pCanMoveTo=NULL; + SpiderStack * pCanMoveToSameSuit=NULL; + bool cardsWillMove=false; + + for (unsigned int i=0;im_stackVector.size();i++) + { + // ok we are only moving the cards if the hit is not on the same + // stack they are already located in + if (this->m_stackVector[i]!=pStack) + { + // see if we have a perferred move to a stack that has the same suit + // we will break out if we find a perferred match + if (this->m_stackVector[i]->canAddCardsSameSuit(cardVector)) + { + pCanMoveToSameSuit=this->m_stackVector[i]; + cardsWillMove=true; + break; + } + // otherwise see if we can move the cards to the stack at all + else if (this->m_stackVector[i]->canAddCards(cardVector)) + { + if (this->m_stackVector[i]->isEmpty()) + { + pCanMoveToEmpty=this->m_stackVector[i]; + } + else + { + pCanMoveTo=this->m_stackVector[i]; + } + cardsWillMove=true; + } + } + } + + // if we are going to move the cards + if (cardsWillMove) + { + SpiderStack * pNewStack=NULL; + + // ok the best move is to a matching suit and consecutive + // next best is to a consecutive + // and lastly to an empty stack. + if (NULL!=pCanMoveToSameSuit) + { + pNewStack=pCanMoveToSameSuit; + } + else if (NULL!=pCanMoveTo) + { + pNewStack=pCanMoveTo; + } + else + { + pNewStack=pCanMoveToEmpty; + } + + CardMoveRecord moveRecord(startMoveRecord); + pNewStack->addCards(cardVector,moveRecord,true); + + // perform the move of the cards and animate it if animations + // are enabled + m_sToSAniMove.moveCards(moveRecord); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::slotSetFourSuits() +{ + if (SpiderBoard::FourSuits!=this->m_gameType) + { + this->m_gameType=SpiderBoard::FourSuits; + this->newGame(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::slotSetTwoSuits() +{ + if (SpiderBoard::TwoSuits!=this->m_gameType) + { + this->m_gameType=SpiderBoard::TwoSuits; + this->newGame(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::slotSetOneSuit() +{ + if (SpiderBoard::OneSuit!=this->m_gameType) + { + this->m_gameType=SpiderBoard::OneSuit; + this->newGame(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::calcScore() +{ + int score=0; + unsigned int i; + + for(i=0;im_homeVector.size();i++) + { + score+=this->m_homeVector[i]->score(); + } + + for(i=0;im_stackVector.size();i++) + { + score+=this->m_stackVector[i]->score(); + } + + int deals=0; + + // The number of deals left is the number of cards in the deck widget divided by the number of stack widgets + if (!this->m_pDeck->isEmpty() && this->m_stackVector.size()>0) + { + const PlayingCardVector & cardVector=this->m_pDeck->getCardVector(); + + deals=cardVector.size()/this->m_stackVector.size(); + + if (cardVector.size()%this->m_stackVector.size()) + { + deals++; + } + } + + QString dealsLeft(tr("Deals remaining: %1").arg(QString::number(deals)).trimmed()); + + emit scoreChanged(score,dealsLeft); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::resizeEvent (QResizeEvent * event) +{ + unsigned int i; + + GameBoard::resizeEvent(event); + + + QSize cardSize(CardPixmaps::getInst().getCardSize()); + + QPointF currPos(GameBoard::LayoutSpacing,GameBoard::LayoutSpacing); + + m_pDeck->setPos(currPos); + + currPos.setX(GameBoard::LayoutSpacing*3 + cardSize.width()*2); + + for (i=0;isetPos(currPos); + currPos.setX(currPos.x()+cardSize.width()+GameBoard::LayoutSpacing); + } + + currPos.setY(GameBoard::LayoutSpacing*2+cardSize.height()); + currPos.setX(GameBoard::LayoutSpacing); + for (i=0;isetPos(currPos); + currPos.setX(currPos.x()+cardSize.width()+GameBoard::LayoutSpacing); + } + + std::cout<<__FUNCTION__<isEmpty()) + { + slotDealNextCards(); + } + else if (stopWhenNoMore) + { + stopDemo(); + rc=false; + } + else + { + rc=false; + } + } + + return rc; +} + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +void SpiderBoard::createStacks() +{ + setCardResizeAlg(10,ResizeByWidth); + + unsigned int i; + // create all the widgets for the board + for(i=0;i<8;i++) + { + this->m_homeVector.push_back(new SpiderHomeStack); + this->m_scene.addItem(m_homeVector[i]); + + // get signals when cards are added to the stack. So, we can add undo info and + // see when the game is over. + this->connect(this->m_homeVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + } + + for(i=0;i<10;i++) + { + this->m_stackVector.push_back(new SpiderStack); + this->m_scene.addItem(m_stackVector[i]); + + // get signals when cards are added to the stack. So, we can add undo info and + // see when the game is over. + + this->connect(this->m_stackVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + this->connect(this->m_stackVector[i],SIGNAL(sendSuitHome(SpiderStack *,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotSendSuitHome(SpiderStack*,PlayingCardVector,CardMoveRecord))); + this->connect(this->m_stackVector[i],SIGNAL(moveCardsToDiffStack(SpiderStack *,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotMoveCardsToDiffStack(SpiderStack*,PlayingCardVector,CardMoveRecord))); + + + } + + m_pDeck=new CardStack; + this->m_scene.addItem(m_pDeck); + + // get signals when the deck is clicked on so we can deal the next set of cards + this->connect(this->m_pDeck,SIGNAL(cardClicked(CardStack*,uint)), + this,SLOT(slotDealNextCards(CardStack*,uint))); + + std::cout<<__FUNCTION__<<__FILE__<m_homeVector.size();i++) + { + if (this->m_homeVector[i]->isEmpty()) + { + allSuitsSentHome=false; + break; + } + } + + return allSuitsSentHome; +} + + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +bool SpiderBoard::isGameWonNotComplete()const +{ + bool rc=m_pDeck->isEmpty(); + + if (rc) + { + for (unsigned int i=0;im_stackVector.size();i++) + { + if (!(this->m_stackVector[i]->cardsAscendingTopToBottom() && + this->m_stackVector[i]->allCardsFaceUp())) + { + rc=false; + break; + } + } + } + + return rc; +} + diff --git a/plugins/qsolocards_plugin/SpiderBoard.h b/plugins/qsolocards_plugin/SpiderBoard.h new file mode 100644 index 000000000..bd0e32a8e --- /dev/null +++ b/plugins/qsolocards_plugin/SpiderBoard.h @@ -0,0 +1,101 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef SPIDERBOARD_H +#define SPIDERBOARD_H + +#include "GameBoard.h" +#include "CardStack.h" +#include "SpiderStack.h" +#include "SpiderHomeStack.h" + +#include + +class SpiderBoard : public GameBoard +{ + Q_OBJECT + + public: + enum GameType + { + FourSuits=4, + TwoSuits=2, + OneSuit=1 + }; + + static const QString GameTypeKeyStr; + + SpiderBoard(QWidget * pParent=NULL); + virtual ~SpiderBoard(); + + bool getHint(CardStack * & pSrcWidget, + unsigned int & srcStackIndex, + CardStack * & pDstWidget); + + inline bool hasDemo() const {return true;} + + virtual void newGame(); + + virtual void addGameMenuItems(QMenu & menu); + + virtual void loadSettings(const QSettings & settings); + virtual void saveSettings(QSettings & settings); + + inline bool isCheating() const {return m_cheat;} + + void setCheat(bool cheat); + + inline bool supportsScore() const{return true;} + + public slots: + virtual void slotDealNextCards(CardStack * pCardStackWidget=NULL,unsigned int index=0); + + // these slot catch the signals from the SpiderStacks that are started by + // a click on a card instead of a drag + virtual void slotSendSuitHome(SpiderStack *,const PlayingCardVector &,const CardMoveRecord &); + virtual void slotMoveCardsToDiffStack(SpiderStack *,const PlayingCardVector &,const CardMoveRecord &); + + + void slotSetFourSuits(); + void slotSetTwoSuits(); + void slotSetOneSuit(); + + protected: + void calcScore(); + + virtual void resizeEvent (QResizeEvent * event); + + bool runDemo(bool stopWhenNoMore=true); + + virtual void createStacks(); + + virtual bool isGameWon()const; + virtual bool isGameWonNotComplete()const; + + CardStack * m_pDeck; + std::vector m_homeVector; // we will have 8 items in this + //vector one for each suit (2 decks) + std::vector m_stackVector; // we will have 10 items in this vector + + bool m_cheat; + + + GameType m_gameType; +}; + +#endif // SPIDERBOARD_H diff --git a/plugins/qsolocards_plugin/SpiderHomeStack.cpp b/plugins/qsolocards_plugin/SpiderHomeStack.cpp new file mode 100644 index 000000000..5fb666688 --- /dev/null +++ b/plugins/qsolocards_plugin/SpiderHomeStack.cpp @@ -0,0 +1,70 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "SpiderHomeStack.h" + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +SpiderHomeStack::SpiderHomeStack() + :CardStack() +{ +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +SpiderHomeStack::~SpiderHomeStack() +{ +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +bool SpiderHomeStack::canSendHome(const PlayingCardVector & cardVector) +{ + bool rc=false; + + if (PlayingCard::MaxCardIndex==cardVector.size() && + PlayingCard::King==cardVector[0].getIndex() && + PlayingCard::Ace==cardVector[cardVector.size()-1].getIndex()) + { + rc=true; + for(unsigned int i=1;iisEmpty()) + { + rc=SpiderHomeStack::canSendHome(newCards); + } + + return rc; +} diff --git a/plugins/qsolocards_plugin/SpiderHomeStack.h b/plugins/qsolocards_plugin/SpiderHomeStack.h new file mode 100644 index 000000000..108fb6314 --- /dev/null +++ b/plugins/qsolocards_plugin/SpiderHomeStack.h @@ -0,0 +1,46 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef SPIDERHOMESTACK_H +#define SPIDERHOMESTACK_H + +#include "CardStack.h" + +// When a suit is together from King to Ace it can be "sent home" or moved off the +// main board to a separate set stack. When all 8 sets of suits are "sent home" the +// game is won. +class SpiderHomeStack: public CardStack +{ + public: + SpiderHomeStack(); + ~SpiderHomeStack(); + + // this function just tests if the cardVector is complete + // King to Ace of the same suit + static bool canSendHome(const PlayingCardVector &); + + // for this type of stack the score will be 0 or 12 + // or one less than the number of cards in a suit. + // ie we have a sent home suit or nothing. + inline int score() const {return ((isEmpty())?0:PlayingCard::MaxCardIndex-1);} + + bool canAddCards(const PlayingCardVector &); + +}; + +#endif // SPIDERHOMESTACK_H diff --git a/plugins/qsolocards_plugin/SpiderStack.cpp b/plugins/qsolocards_plugin/SpiderStack.cpp new file mode 100644 index 000000000..5ff38576a --- /dev/null +++ b/plugins/qsolocards_plugin/SpiderStack.cpp @@ -0,0 +1,175 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "SpiderStack.h" +#include "SpiderHomeStack.h" + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +SpiderStack::SpiderStack() + :VCardStack(), + m_cheat(false) +{ + this->setAutoTopCardUp(); + + + // connect a slot to get the signal when a movable card is clicked + this->connect(this,SIGNAL(movableCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotMovableCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord))); +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +SpiderStack::~SpiderStack() +{ +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +int SpiderStack::score() const +{ + const PlayingCardVector & cardVector=this->getCardVector(); + int score=0; + + for (unsigned int i=1;igetCardVector(); + + if (newCardVector.size()>0) + { + // if there are no cards in the stack then we will accept any cards + if (0==cardVector.size()) + { + rc=true; + } + else if (cardVector[cardVector.size()-1].isPrevCardIndex(newCardVector[0]) && + cardVector[cardVector.size()-1].isFaceUp()) + { + rc=true; + } + } + + return rc; +} + +/////////////////////////////////////////////////////////////////////////////////// +// similar to can Add cards. But in this case the +// suit of the last card in this stack is the same as +// the first suit of the cardVector +/////////////////////////////////////////////////////////////////////////////////// +bool SpiderStack::canAddCardsSameSuit(const PlayingCardVector & newCardVector) +{ + bool rc=false; + + if (this->canAddCards(newCardVector) && !this->isEmpty() && newCardVector.size()>0) + { + const PlayingCardVector & cardVector=this->getCardVector(); + + rc=cardVector[cardVector.size()-1].isSameSuit(newCardVector[0]); + } + + return rc; +} + +/////////////////////////////////////////////////////////////////////////////////// +// if a card is clicked on see if it needs to be sent home or can just be moved +// to another stack. +/////////////////////////////////////////////////////////////////////////////////// +void SpiderStack::slotMovableCardsClicked(CardStack * pCardStack, + const PlayingCardVector & moveCards, + const CardMoveRecord & moveRecord) +{ + bool isSentHome=false; + + Q_UNUSED(pCardStack); + + // first see if the item needs to be sent home + if (SpiderHomeStack::canSendHome(moveCards)) + { + emit sendSuitHome(this,moveCards,moveRecord); + isSentHome=true; + } + + // if this is not a case when the suit can be sent home + // Then we will just emit a signal to try to move the + // set of cards. + if (!isSentHome) + { + emit moveCardsToDiffStack(this,moveCards,moveRecord); + } +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +bool SpiderStack::canMoveCard(unsigned int index) const +{ + if (m_cheat) + { + return true; + } + + bool rc=false; + const PlayingCardVector & cardVector=this->getCardVector(); + + // ok if we have cards in the stack and the index is valid + // see if we can move it. + if (cardVector.size()>0 && index. +*/ + +#ifndef SPIDERSTACK_H +#define SPIDERSTACK_H + +#include "VCardStack.h" + +// This is the stack of cards that are used for the main game play +// There are ten of these stacks. +class SpiderStack: public VCardStack +{ + Q_OBJECT + + public: + SpiderStack(); + ~SpiderStack(); + + inline bool isCheating() const{return m_cheat;} + + inline void setCheat(bool cheat=true){m_cheat=cheat;} + + int score() const; + + bool canAddCards(const PlayingCardVector &); + + // similar to can Add cards. But in this case the + // suit of the last card in this stack is the same as + // the first suit of the cardVector + bool canAddCardsSameSuit(const PlayingCardVector &); + + signals: + // signals that are emitted when a card that can be moved is clicked on + // the move record created will have the Remove and flip actions (if the flip of the + // card before the cards is necessary.) + void sendSuitHome(SpiderStack *,const PlayingCardVector &,const CardMoveRecord &); + void moveCardsToDiffStack(SpiderStack *,const PlayingCardVector &,const CardMoveRecord &); + + public slots: + void slotMovableCardsClicked(CardStack * pCardStack, + const PlayingCardVector &, + const CardMoveRecord &); + + + protected: + bool canMoveCard(unsigned int index) const; + + private: + bool m_cheat; +}; + +#endif // SPIDERSTACK_H diff --git a/plugins/qsolocards_plugin/SpideretteBoard.cpp b/plugins/qsolocards_plugin/SpideretteBoard.cpp new file mode 100644 index 000000000..3106dbbeb --- /dev/null +++ b/plugins/qsolocards_plugin/SpideretteBoard.cpp @@ -0,0 +1,182 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "SpideretteBoard.h" +#include "CardPixmaps.h" + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +SpideretteBoard::SpideretteBoard() +{ + this->setGameName(QString(tr("Spiderette Solitaire")).trimmed()); + this->setGameId("Spiderette"); + + this->setHelpFile(":/help/SpideretteHelp.html"); +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +SpideretteBoard::~SpideretteBoard() +{ +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +void SpideretteBoard::newGame() +{ + // call the base class + GameBoard::newGame(); + + CardDeck deck; + unsigned int i; + + while(!deck.isEmpty()) + { + this->m_pDeck->addCard(deck.next()); + } + + + DealItemVector dealItemVector; + + + // Create the dealItemVector to direct the DealAnimation object on + // how to deal the cards. + for (i=0;im_stackVector.size();i++) + { + dealItemVector.push_back(DealItem(this->m_stackVector[i],m_pDeck)); + + unsigned int j; + + for (j=0;jsetPos(currPos); + + currPos.rx()+=GameBoard::LayoutSpacing*4 + cardSize.width()*4; + + + for (i=0;isetPos(currPos); + currPos.rx()+=cardSize.width()+GameBoard::LayoutSpacing; + } + + currPos.setY(GameBoard::LayoutSpacing*2+cardSize.height()); + currPos.setX(GameBoard::LayoutSpacing*2+cardSize.width()); + for (i=0;isetPos(currPos); + currPos.rx()+=cardSize.width()+GameBoard::LayoutSpacing; + } +} + +/////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////// +void SpideretteBoard::createStacks() +{ + setCardResizeAlg(8,ResizeByWidth); + + + unsigned int i; + + // first create the home widgets where the cards need to be eventually stacked to + // win the game. + for(i=0;i<4;i++) + { + this->m_homeVector.push_back(new SpiderHomeStack); + this->m_scene.addItem(m_homeVector[i]); + + // get signals when cards are added to the stack. So, we can add undo info and + // see when the game is over. + this->connect(this->m_homeVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + } + + // now create the 7 rows for the stacks. + for (i=0;i<7;i++) + { + this->m_stackVector.push_back(new SpiderStack); + this->m_scene.addItem(m_stackVector[i]); + + // get signals when cards are added to the stack. So, we can add undo info and + // see when the game is over. + this->connect(this->m_stackVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + this->connect(this->m_stackVector[i],SIGNAL(sendSuitHome(SpiderStack *,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotSendSuitHome(SpiderStack*,PlayingCardVector,CardMoveRecord))); + this->connect(this->m_stackVector[i],SIGNAL(moveCardsToDiffStack(SpiderStack *,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotMoveCardsToDiffStack(SpiderStack*,PlayingCardVector,CardMoveRecord))); + } + + this->m_pDeck=new CardStack; + this->m_scene.addItem(this->m_pDeck); + + // get signals when the deck is clicked on so we can deal the next set of cards + this->connect(this->m_pDeck,SIGNAL(cardClicked(CardStack*,uint)), + this,SLOT(slotDealNextCards(CardStack*,uint))); +} diff --git a/plugins/qsolocards_plugin/SpideretteBoard.h b/plugins/qsolocards_plugin/SpideretteBoard.h new file mode 100644 index 000000000..01be53147 --- /dev/null +++ b/plugins/qsolocards_plugin/SpideretteBoard.h @@ -0,0 +1,43 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __SPIDERETTEBOARD_H__ +#define __SPIDERETTEBOARD_H__ + +#include "SpiderBoard.h" + +class SpideretteBoard:public SpiderBoard +{ + Q_OBJECT +public: + SpideretteBoard(); + virtual ~SpideretteBoard(); + + virtual void newGame(); + + virtual void addGameMenuItems(QMenu & menu); + + virtual void loadSettings(const QSettings & settings); + virtual void saveSettings(QSettings & settings); + +protected: + virtual void resizeEvent (QResizeEvent * event); + virtual void createStacks(); +}; + +#endif diff --git a/plugins/qsolocards_plugin/StackToStackAniMove.cpp b/plugins/qsolocards_plugin/StackToStackAniMove.cpp new file mode 100644 index 000000000..c00049f69 --- /dev/null +++ b/plugins/qsolocards_plugin/StackToStackAniMove.cpp @@ -0,0 +1,290 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "StackToStackAniMove.h" +#include "CardAnimationLock.h" + +#include + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +StackToStackAniMoveItem::StackToStackAniMoveItem(const CardMoveRecord & startMoveRecord,int duration) + :m_pSrc(NULL), + m_pDst(NULL), + m_pFlipStack(NULL), + m_flipIndex(-2), + m_srcTopCardIndex(-1), + m_cardVector(), + m_duration(duration), + m_moveRecord(startMoveRecord) +{ + CardMoveRecord moveRecord(startMoveRecord); + + while(!moveRecord.empty()) + { + CardMoveRecordItem currItem(moveRecord.back()); + CardStack * pStack=CardStack::getStackByName(currItem.stackName()); + const PlayingCardVector & cardVector=currItem.cardVector(); + + CardMoveRecordItem::MoveType moveType=currItem.moveType(); + + switch(moveType) + { + case CardMoveRecordItem::RemoveCards: + { + m_pSrc=pStack; + if (NULL!=m_pSrc) + { + m_srcTopCardIndex=m_pSrc->getCardVector().size()-cardVector.size(); + } + m_cardVector=cardVector; + } + break; + case CardMoveRecordItem::AddCards: + { + m_pDst=pStack; + } + break; + // for this case we are just going to flip the card over + case CardMoveRecordItem::FlipCard: + { + m_flipIndex=currItem.flipIndex(); + m_pFlipStack=pStack; + } + break; + }; + + moveRecord.pop_back(); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +StackToStackAniMoveItem::StackToStackAniMoveItem(const StackToStackAniMoveItem & rh) + :m_pSrc(NULL), + m_pDst(NULL), + m_pFlipStack(NULL), + m_flipIndex(-1), + m_srcTopCardIndex(-1), + m_cardVector(), + m_duration(0), + m_moveRecord() +{ + *this=rh; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +StackToStackAniMoveItem::StackToStackAniMoveItem() + :m_pSrc(NULL), + m_pDst(NULL), + m_pFlipStack(NULL), + m_flipIndex(-1), + m_srcTopCardIndex(-1), + m_cardVector(), + m_duration(0), + m_moveRecord() +{ +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +StackToStackAniMoveItem::~StackToStackAniMoveItem() +{ +} + +StackToStackAniMoveItem & StackToStackAniMoveItem::operator=(const StackToStackAniMoveItem & rh) +{ + m_pSrc=rh.m_pSrc; + m_pDst=rh.m_pDst; + m_pFlipStack=rh.m_pFlipStack; + m_flipIndex=rh.m_flipIndex; + m_srcTopCardIndex=rh.m_srcTopCardIndex; + m_cardVector=rh.m_cardVector; + m_duration=rh.m_duration; + m_moveRecord=rh.m_moveRecord; + + return *this; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +StackToStackAniMove::StackToStackAniMove() + :m_pTimeLine(NULL), + m_flipDelayTimer(), + m_pItemAni(NULL), + m_pPixmapItem(NULL), + m_aniMoveItem(), + m_aniRunning(false) +{ + m_flipDelayTimer.setSingleShot(true); + m_flipDelayTimer.setInterval(250); + this->connect(&m_flipDelayTimer,SIGNAL(timeout()), + this,SLOT(slotWaitForFlipComplete())); +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +StackToStackAniMove::~StackToStackAniMove() +{ + delete m_pTimeLine; + delete m_pItemAni; + delete m_pPixmapItem; +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void StackToStackAniMove::moveCards(const CardMoveRecord & moveRecord,int duration) +{ + // if animation is off just process the move record as normal + if (!CardAnimationLock::getInst().animationsEnabled()) + { + CardStack::processCardMoveRecord(CardStack::RedoMove,moveRecord); + emit cardsMoved(moveRecord); + } + else + { + // first if we have an animation running stop it. + slotAniFinished(); + m_aniMoveItem=StackToStackAniMoveItem(moveRecord,duration); + CardAnimationLock::getInst().lock(); + runAnimation(); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void StackToStackAniMove::stopAni() +{ + slotAniFinished(false); +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void StackToStackAniMove::slotAniFinished(bool emitSignal) +{ + if (m_aniRunning) + { + m_pItemAni->timeLine()->stop(); + + // add the cards to the destination + m_aniMoveItem.dst()->addCards(m_aniMoveItem.getCardVector()); + + // now update the destination + m_aniMoveItem.dst()->updateStack(); + + // remove the animation object + m_aniMoveItem.dst()->scene()->removeItem(m_pPixmapItem); + + delete m_pPixmapItem; + m_pPixmapItem=NULL; + + + + // use the emit signal to know whether or not to disable the animation. + if (m_aniMoveItem.flipIndex()>-2) + { + m_aniMoveItem.flipStack()->flipCard(m_aniMoveItem.flipIndex(),emitSignal); + } + + CardAnimationLock::getInst().unlock(); + + m_aniRunning=false; + + if (emitSignal) + { + // emit a signal that the move is complete + emit cardsMoved(m_aniMoveItem.moveRecord()); + } + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void StackToStackAniMove::slotWaitForFlipComplete() +{ + this->runAnimation(); +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +void StackToStackAniMove::runAnimation() +{ + m_aniRunning=true; + + // if the flip animation is running for the src or dst + // give it 1/2 a second to complete. + if (m_aniMoveItem.src()->isFlipAniRunning() || + m_aniMoveItem.dst()->isFlipAniRunning()) + { + m_flipDelayTimer.start(); + return; + } + + delete m_pTimeLine; + delete m_pItemAni; + delete m_pPixmapItem; + + + m_pTimeLine=new QTimeLine(m_aniMoveItem.duration()); + m_pItemAni=new QGraphicsItemAnimation; + m_pPixmapItem=new QGraphicsPixmapItem; + + QPixmap * pPixmap=m_aniMoveItem.src()->getStackPixmap(m_aniMoveItem.getCardVector()); + + if (pPixmap) + { + m_pPixmapItem->setPixmap(*pPixmap); + delete pPixmap; + } + + // set the z value to 2 so it will be on top of the + // stacks. + m_pPixmapItem->setZValue(2); + + // add the item to the scene and move it over the stack in the + // place of the cards we are going to move + m_aniMoveItem.src()->scene()->addItem(m_pPixmapItem); + m_pPixmapItem->setPos(m_aniMoveItem.src()->getGlobalCardPt(m_aniMoveItem.srcTopCardIndex())); + + + // setup the animation + m_pItemAni->setItem(m_pPixmapItem); + m_pItemAni->setTimeLine(m_pTimeLine); + + m_pItemAni->setPosAt (0, m_aniMoveItem.src()->getGlobalCardPt(m_aniMoveItem.srcTopCardIndex())); + m_pItemAni->setPosAt (1, m_aniMoveItem.dst()->getGlobalCardAddPt()); + + // connect up the slot so we will know when it is finished. + this->connect(m_pTimeLine,SIGNAL(finished()), + this,SLOT(slotAniFinished())); + + for (unsigned int i=0;iremoveTopCard(); + } + + // redraw the source stack and start the animation. + m_aniMoveItem.src()->updateStack(); + + m_pTimeLine->start(); +} diff --git a/plugins/qsolocards_plugin/StackToStackAniMove.h b/plugins/qsolocards_plugin/StackToStackAniMove.h new file mode 100644 index 000000000..3e6da6894 --- /dev/null +++ b/plugins/qsolocards_plugin/StackToStackAniMove.h @@ -0,0 +1,102 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __STACKTOSTACKANIMOVE_H__ +#define __STACKTOSTACKANIMOVE_H__ + +#include "CardStack.h" +#include "CardMoveRecord.h" + +#include +#include +#include +#include +#include + +/* + StackToStackAniMove is just for moving one set of cards to another stack. Normal usage is + when a card in one stack is clicked on and then it is determined that this should result + in moving the card(s) to a different stack. (Auto)flipping + a card when the move is complete is also done if included in the moveRecord. +*/ + +class StackToStackAniMoveItem +{ +public: + StackToStackAniMoveItem(const CardMoveRecord & startMoveRecord,int duration); + StackToStackAniMoveItem(const StackToStackAniMoveItem & rh); + StackToStackAniMoveItem(); + + virtual ~StackToStackAniMoveItem(); + + inline CardStack * src() {return m_pSrc;} + inline CardStack * dst() {return m_pDst;} + inline CardStack * flipStack() {return m_pFlipStack;} + inline int flipIndex()const{return m_flipIndex;} + inline int srcTopCardIndex()const {return m_srcTopCardIndex;} + inline const PlayingCardVector & getCardVector() const{return m_cardVector;} + inline int duration()const{return m_duration;} + inline const CardMoveRecord & moveRecord(){return m_moveRecord;} + + StackToStackAniMoveItem & operator=(const StackToStackAniMoveItem & rh); + +private: + CardStack * m_pSrc; + CardStack * m_pDst; + CardStack * m_pFlipStack; + int m_flipIndex; + int m_srcTopCardIndex; + PlayingCardVector m_cardVector; + int m_duration; + CardMoveRecord m_moveRecord; +}; + + +class StackToStackAniMove:public QObject +{ + Q_OBJECT +public: + StackToStackAniMove(); + virtual ~StackToStackAniMove(); + + void moveCards(const CardMoveRecord & startMoveRecord,int duration=400); + void stopAni(); + +signals: + void cardsMoved(const CardMoveRecord & moveRecord); + +public slots: + void slotAniFinished(bool emitSignal=true); + void slotWaitForFlipComplete(); + +protected: + + void runAnimation(); + +private: + QTimeLine * m_pTimeLine; + QTimer m_flipDelayTimer; + QGraphicsItemAnimation * m_pItemAni; + QGraphicsPixmapItem * m_pPixmapItem; + StackToStackAniMoveItem m_aniMoveItem; + bool m_aniRunning; +}; + + + +#endif diff --git a/plugins/qsolocards_plugin/StackToStackFlipAni.cpp b/plugins/qsolocards_plugin/StackToStackFlipAni.cpp new file mode 100644 index 000000000..6ec4565d9 --- /dev/null +++ b/plugins/qsolocards_plugin/StackToStackFlipAni.cpp @@ -0,0 +1,334 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "StackToStackFlipAni.h" +#include "CardAnimationLock.h" +#include "CardPixmaps.h" + +#include +#include + +#include + +const qreal StackToStackFlipAni::ExposedPrecentShownCards=.18; +const qreal StackToStackFlipAni::ExposedPrecentHiddenCards=.02; + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +StackToStackFlipAni::StackToStackFlipAni() + :m_pDst(NULL), + m_pSrc(NULL), + m_cardVector(), + m_firstCardToShow(0), + m_flipPtReached(false), + m_moveRecord(), + m_pTimeLine(NULL), + m_pItemAni(NULL), + m_pPixmapItem(NULL), + m_aniRunning(false) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +StackToStackFlipAni::~StackToStackFlipAni() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +void StackToStackFlipAni::moveCards(CardStack * pDst,CardStack * pSrc, + int numCards,int cardsShown, + int duration) +{ + // first if we have an animation running stop it. + this->stopAni(); + + // setup the next animation. + m_pDst=pDst; + m_pSrc=pSrc; + m_cardVector.clear(); + m_moveRecord.clear(); + m_flipPtReached=false; + + while( !m_pSrc->isEmpty() && numCards>0) + { + PlayingCard card(m_pSrc->removeTopCard(m_moveRecord)); + + m_cardVector.insert(m_cardVector.begin(),card); + numCards--; + } + + // by default we will show all cards + m_firstCardToShow=0; + + // if we are not showing all cards starting with index 0 + // then figure out the index of the first card that will + // be shown. + if (m_cardVector.size()>0 && cardsShown>=0 && + cardsShown<(int)m_cardVector.size()) + { + // ok if the value is 0 or 1. We will just show + // the last card. 0 doesn't make any sense if you + // are flipping cards. So, we will assume one for + // that case as well. + if (cardsShown<=1) + { + m_firstCardToShow=m_cardVector.size()-1; + } + else + { + m_firstCardToShow=m_cardVector.size()-cardsShown; + } + } + + + // if animation is off just immediately add the cards to the new + // stack. Call updateStack to redraw the stacks. And emit the + // signal that the cards have been moved. + if (!CardAnimationLock::getInst().animationsEnabled()) + { + this->flipCards(); + m_pSrc->updateStack(); + + m_pDst->addCards(m_cardVector,m_moveRecord); + m_pDst->updateStack(); + emit cardsMoved(m_moveRecord); + } + else + { + CardAnimationLock::getInst().lock(); + runAnimation(duration); + } + +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +void StackToStackFlipAni::slotAniFinished(bool emitSignal) +{ + if (m_aniRunning) + { + m_aniRunning=false; + this->m_pTimeLine->stop(); + + m_pDst->addCards(m_cardVector,m_moveRecord); + m_pDst->updateStack(); + + // remove the animation object + m_pSrc->scene()->removeItem(m_pPixmapItem); + delete m_pPixmapItem; + m_pPixmapItem=NULL; + + CardAnimationLock::getInst().unlock(); + + if (emitSignal) + { + emit cardsMoved(m_moveRecord); + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +void StackToStackFlipAni::slotAniProgress(qreal currProgress) +{ + if (currProgress>=.6 && !m_flipPtReached) + { + m_flipPtReached=true; + + this->flipCards(); + + QPixmap * pPixmap=this->getAniPixmap(); + + if (pPixmap) + { + m_pPixmapItem->setPixmap(*pPixmap); + delete pPixmap; + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +void StackToStackFlipAni::runAnimation(int duration) +{ + m_aniRunning=true; + + delete m_pTimeLine; + delete m_pItemAni; + delete m_pPixmapItem; + + + m_pTimeLine=new QTimeLine(duration); + m_pItemAni=new QGraphicsItemAnimation; + m_pPixmapItem=new QGraphicsPixmapItem; + + + QPixmap * pPixmap=this->getAniPixmap(); + + if (pPixmap) + { + m_pPixmapItem->setPixmap(*pPixmap); + delete pPixmap; + } + + // set the z value to 2 so it will be on top of the + // stacks. + m_pPixmapItem->setZValue(2); + + // add the item to the scene and move it over the stack in the + // place of the cards we are going to move + m_pSrc->scene()->addItem(m_pPixmapItem); + m_pPixmapItem->setPos(m_pSrc->getGlobalLastCardPt()); + + + // setup the animation + m_pItemAni->setItem(m_pPixmapItem); + m_pItemAni->setTimeLine(m_pTimeLine); + + // set the start and end point + m_pItemAni->setPosAt (0, m_pSrc->getGlobalLastCardPt()); + m_pItemAni->setPosAt (1, m_pDst->getGlobalCardAddPt()); + + // set the scaling to give the flipping effect. + m_pItemAni->setScaleAt( 0, 1, 1 ); + m_pItemAni->setScaleAt( 0.6, 0, 1 ); + m_pItemAni->setScaleAt( 1, 1, 1 ); + + // connect up the slot so we will know when it is finished. + this->connect(m_pTimeLine,SIGNAL(finished()), + this,SLOT(slotAniFinished())); + + this->connect(m_pTimeLine,SIGNAL(valueChanged(qreal)), + this,SLOT(slotAniProgress(qreal))); + + // update the src stack behind the flip item we just added + m_pSrc->updateStack(); + + m_pTimeLine->start(); +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +QPixmap * StackToStackFlipAni::getAniPixmap() +{ + QPixmap * pPixmap=NULL; + + if (m_cardVector.size()>0) + { + unsigned int i; + + pPixmap =new QPixmap(this->calcPixmapSize()); + // for linux the transparent fill must be done before + // we associate the pixmap with the painter + pPixmap->fill(Qt::transparent); + + QPainter painter(pPixmap); + + + QPoint pt(0,0); + + for (i=0;i=m_firstCardToShow && m_cardVector[index].isFaceUp()) + { + increment=CardPixmaps::getInst().getCardSize().width()*ExposedPrecentShownCards; + } + else + { + increment=CardPixmaps::getInst().getCardSize().width()*ExposedPrecentHiddenCards; + } + } + + return increment; +} + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +void StackToStackFlipAni::flipCards() +{ + + if (m_cardVector.size()>0) + { + int i; + + PlayingCardVector flipVector; + + for(i=m_cardVector.size()-1;i>=0;i--) + { + m_cardVector[i].setFaceUp(!m_cardVector[i].isFaceUp()); + flipVector.push_back(m_cardVector[i]); + } + + m_cardVector.clear(); + m_cardVector=flipVector; + } +} diff --git a/plugins/qsolocards_plugin/StackToStackFlipAni.h b/plugins/qsolocards_plugin/StackToStackFlipAni.h new file mode 100644 index 000000000..f4065c894 --- /dev/null +++ b/plugins/qsolocards_plugin/StackToStackFlipAni.h @@ -0,0 +1,80 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __STACKTOSTACKFLIPANI_H__ +#define __STACKTOSTACKFLIPANI_H__ + +#include "CardStack.h" +#include "CardMoveRecord.h" + +#include +#include +#include +#include +#include + +class StackToStackFlipAni: public QObject +{ + Q_OBJECT +public: + static const qreal ExposedPrecentShownCards; + static const qreal ExposedPrecentHiddenCards; + + StackToStackFlipAni(); + virtual ~StackToStackFlipAni(); + + inline bool isAniRunning() const{return m_aniRunning;} + + inline void stopAni(){if (m_aniRunning){slotAniFinished(false);m_aniRunning=false;}} + + void moveCards(CardStack * pDst,CardStack * pSrc, + int numCards=1,int cardsShown=-1, + int duration=500); + +signals: + void cardsMoved(const CardMoveRecord & moveRecord); + +public slots: + void slotAniFinished(bool emitSignal=true); + void slotAniProgress(qreal currProgress); + +protected: + virtual void runAnimation(int duration); + + virtual QPixmap * getAniPixmap(); + + QSize calcPixmapSize(); + int getOverlapIncrement(unsigned int index); + + void flipCards(); + +private: + CardStack * m_pDst; + CardStack * m_pSrc; + PlayingCardVector m_cardVector; + unsigned int m_firstCardToShow; // first index into m_cardVector to show + bool m_flipPtReached; + CardMoveRecord m_moveRecord; + + QTimeLine * m_pTimeLine; + QGraphicsItemAnimation * m_pItemAni; + QGraphicsPixmapItem * m_pPixmapItem; + bool m_aniRunning; +}; + +#endif diff --git a/plugins/qsolocards_plugin/VCardStack.cpp b/plugins/qsolocards_plugin/VCardStack.cpp new file mode 100644 index 000000000..3f4a21c6c --- /dev/null +++ b/plugins/qsolocards_plugin/VCardStack.cpp @@ -0,0 +1,333 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "VCardStack.h" +#include "CardPixmaps.h" +#include +#include + +#include + +const qreal VCardStack::ExposedPrecentFaceUp=.23; +const qreal VCardStack::ExposedPrecentFaceDown=.10; + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +VCardStack::VCardStack() + :m_bRectVector(), + m_compressValue(CompressNormal), + m_percentScene(1) +{ +} + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +VCardStack::~VCardStack() +{ +} + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +void VCardStack::setStackBottom(qreal percentScene) +{ + if(percentScene>=0 && percentScene<=1) + { + m_percentScene=percentScene; + } + else + { + m_percentScene=1; + } +} + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +QPointF VCardStack::getGlobalCardAddPt() const +{ + QPointF pt(0,0); + + const PlayingCardVector & cardVector=this->getCardVector(); + + // We are going to do this by the bounding rects and not by actual cards + // in the stacks. That way we can add something before doing animations + // and then update the display when the animation is complete + if (m_bRectVector.size()>0 && cardVector.size()>=m_bRectVector.size()) + { + pt=m_bRectVector[m_bRectVector.size()-1].topLeft(); + + pt.ry()+=getOverlapIncrement(cardVector[m_bRectVector.size()-1], + m_compressValue); + } + + return mapToScene(pt); +} + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +QPointF VCardStack::getGlobalLastCardPt() const +{ + QPointF pt(0,0); + + const PlayingCardVector & cardVector=this->getCardVector(); + + // We are going to do this by the bounding rects and not by actual cards + // in the stacks. That way we can add something before doing animations + // and then update the display when the animation is complete + if (m_bRectVector.size()>0 && cardVector.size()>=m_bRectVector.size()) + { + pt=m_bRectVector[m_bRectVector.size()-1].topLeft(); + } + + return mapToScene(pt); +} + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +QPointF VCardStack::getGlobalCardPt(int index) const +{ + QPointF pt(0,0); + + if (index>=0 && index<(int)m_bRectVector.size()) + { + pt=m_bRectVector[index].topLeft(); + } + + return mapToScene(pt); +} + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +void VCardStack::updateStack() +{ + QSize size; + const PlayingCardVector & cardVector=this->getCardVector(); + + // the compress value decresses how much of cards are exposed. + // The preferred exposed value is normal. But we will decrease the + // values down to a quarter of the desired to make the stack fit on + // the screen. This function uses the m_precentScene value to determine + // the bottom point of the stack + for(m_compressValue=CompressNormal;m_compressValuescene()->sceneRect().bottom()*m_percentScene)>mapToScene(QPointF(0,size.height())).y()) + { + break; + } + } + + QPixmap * pPixmap=NULL; + + // draw the card and calc the bounding rectangles while we are at it. + if (this->isFlipAniRunning()) + { + PlayingCardVector newCardVector(cardVector); + + // the stack should have at least one card ie the one being flipped + // but make sure. + if (cardVector.size()>0) + { + newCardVector.pop_back(); + } + + // draw the card and calc the bounding rectangles while we are at it. + pPixmap=getStackPixmap(newCardVector,isHighlighted(), + hintHighlightIndex(),m_compressValue, + &m_bRectVector); + } + else + { + // draw the card and calc the bounding rectangles while we are at it. + pPixmap=getStackPixmap(cardVector,isHighlighted(), + hintHighlightIndex(),m_compressValue, + &m_bRectVector); + } + + if (NULL!=pPixmap) + { + this->setPixmap(*pPixmap); + delete pPixmap; + } +} + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +QPixmap * VCardStack::getStackPixmap(const PlayingCardVector & cardVector, + bool highlighted, + int hintHighlightIndex) +{ + return getStackPixmap(cardVector,highlighted, + hintHighlightIndex,CompressNormal,NULL); +} + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +bool VCardStack::getCardIndex(const QPointF & pos,unsigned int & index) +{ + bool rc=false; + + unsigned int i; + + for(i=0;im_bRectVector.size();i++) + { + if (this->m_bRectVector[i].contains(pos)) + { + index=i; + rc=true; + break; + } + } + + return rc; +} + + +//////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////// +void VCardStack::calcPixmapSize(const PlayingCardVector & cardVector, + QSize & size,qreal compressValue) +{ + unsigned int i; + + if (0==cardVector.size()) + { + size=CardPixmaps::getInst().getCardSize(); + } + else + { + unsigned int sizeY=0; + + for (i=0;iclear(); + } + + // first handle the case that there are no cards in the stack + if (0==cardVector.size()) + { + bool hl=(highlighted || HintHighlightNoCards==hintHighlightIndex); + pPixmap=new QPixmap(CardPixmaps::getInst().getCardNonePixmap(hl,this->showRedealCircle())); + } + else + { + unsigned int i; + QSize cardSize(CardPixmaps::getInst().getCardSize()); + QSize pixmapSize(0,0); + + this->calcPixmapSize(cardVector,pixmapSize,compressValue); + + pPixmap =new QPixmap(pixmapSize); + // for linux the transparent fill must be done before + // we associate the pixmap with the painter + pPixmap->fill(Qt::transparent); + + QPainter painter(pPixmap); + + + QPoint pt(0,0); + + for (i=0;i=0 && hintHighlightIndex<=(int)i) || + ((cardVector.size()-1==i) && highlighted)); + + if (cardVector[i].isFaceUp()) + { + painter.drawPixmap(pt,CardPixmaps::getInst().getCardPixmap(cardVector[i],hl)); + } + else + { + painter.drawPixmap(pt,CardPixmaps::getInst().getCardBackPixmap(hl)); + } + + unsigned int incrementValue=getOverlapIncrement(cardVector[i], + compressValue); + + if (pBRectVector) + { + // if it is the last card we just want the full size + // of the card. + if (cardVector.size()-1==i) + { + pBRectVector->push_back(QRectF(QPointF(0,pt.y()),cardSize)); + } + else + { + pBRectVector->push_back(QRectF(QPointF(0,pt.y()),QSize(cardSize.width(),incrementValue))); + } + } + + // increment the point that we are going to paint the + // card pixmap onto this pixmap + pt.ry()+=incrementValue; + + } + } + return pPixmap; +} diff --git a/plugins/qsolocards_plugin/VCardStack.h b/plugins/qsolocards_plugin/VCardStack.h new file mode 100644 index 000000000..c78a0f8aa --- /dev/null +++ b/plugins/qsolocards_plugin/VCardStack.h @@ -0,0 +1,88 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef VCARDSTACK_H +#define VCARDSTACK_H + +#include "CardStack.h" +#include +#include + +typedef std::vector CardBRectVect; + + +// this class will show cards stacked but all cards +// will be partly visible with a card on top of a card revealing +// a portion of the top of the card beneath it. +class VCardStack: public CardStack +{ + Q_OBJECT +public: + static const qreal ExposedPrecentFaceUp; // the precentage show for a face up card will be more than + // that for a card that is face down. Since, we want to be + // able to see the value of the card if it is face up. + static const qreal ExposedPrecentFaceDown; + + enum + { + CompressNormal=1, + CompressMax=4 + }; + + VCardStack(); + virtual ~VCardStack(); + + + // this function allows the caller to set the preportion of the screen that the + // stack can decend too. For example, 1 is the default which means to the bottom + // of the scene. To make the bottom 3/4 of the scene use .75 etc... 1 is the maximum + // value. + void setStackBottom(qreal percentScene); + qreal stackBottom() const{return m_percentScene;} + + // this function gets the point in the scene that a card would be added to this stack. + virtual QPointF getGlobalCardAddPt() const; + virtual QPointF getGlobalLastCardPt() const; + virtual QPointF getGlobalCardPt(int index) const; + + virtual void updateStack(); + + virtual QPixmap * getStackPixmap(const PlayingCardVector & cardVector, + bool highlighted=false, + int hintHighlightIndex=-1); +protected: + virtual bool getCardIndex(const QPointF & pos,unsigned int & index); + + void calcPixmapSize(const PlayingCardVector & cardVector, + QSize & size,qreal compressValue); + + virtual unsigned int getOverlapIncrement(const PlayingCard & card,qreal compressValue) const; + + virtual QPixmap * getStackPixmap(const PlayingCardVector & cardVector, + bool highlighted, + int hintHighlightIndex, + qreal compressValue, + CardBRectVect * pBRectVector); + +private: + CardBRectVect m_bRectVector; + + qreal m_compressValue; + qreal m_percentScene; +}; +#endif diff --git a/plugins/qsolocards_plugin/YukonBoard.cpp b/plugins/qsolocards_plugin/YukonBoard.cpp new file mode 100644 index 000000000..e2865e4e9 --- /dev/null +++ b/plugins/qsolocards_plugin/YukonBoard.cpp @@ -0,0 +1,488 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "YukonBoard.h" +#include "CardPixmaps.h" +#include + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +YukonBoard::YukonBoard() + :GameBoard(NULL,QString(tr("Yukon Solitaire")).trimmed(),QString("Yukon")), + m_pDeck(NULL), + m_homeVector(), + m_stackVector(), + m_cheat(false) +{ + this->setHelpFile(":/help/YukonHelp.html"); +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +YukonBoard::~YukonBoard() +{ +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +bool YukonBoard::getHint(CardStack * & pSrc, + unsigned int & srcStackIndex, + CardStack * & pDst) +{ + bool rc=false; + unsigned int i; + + // ok we will look for a move based on trying to move the first faceup + // card in a stack. The basic strategy for this game is to get all cards turned + // over. + if (!rc) + { + for (i=0;im_stackVector.size() && !rc;i++) + { + unsigned int j; + + for (j=0;jm_stackVector.size() && !rc;j++) + { + // can't move a stack to itself + if (i!=j) + { + PlayingCardVector addCardVector(this->m_stackVector[j]->getCardVector()); + unsigned int k=0; + while (!rc && addCardVector.size()>0) + { + // ok find the first card that is faceup. + if (!addCardVector[0].isFaceUp()) + { + addCardVector.erase(addCardVector.begin()); + } + // no need to do this if a king is already face up and the first card in the stack. + else if (!(PlayingCard::King==addCardVector[0].getIndex() && 0==k && + this->m_stackVector[i]->isEmpty()) && + this->m_stackVector[i]->canAddCards(addCardVector)) + { + pDst=this->m_stackVector[i]; + srcStackIndex=k; + pSrc=this->m_stackVector[j]; + + rc=true; + } + else + { + break; + } + k++; + } + } + } + } + } + + // ok let's see if we have an empty stack + // and a face up king. + if (!rc) + { + CardStack * pEmptyStack=NULL; + CardStack * pFaceUpKingStack=NULL; + unsigned int faceUpKingIndex=0; + + for (i=0;im_stackVector.size() && !rc;i++) + { + if (NULL==pEmptyStack && this->m_stackVector[i]->isEmpty()) + { + pEmptyStack=this->m_stackVector[i]; + } + + if (NULL==pFaceUpKingStack) + { + const PlayingCardVector cardVector=this->m_stackVector[i]->getCardVector(); + + unsigned int j; + + for(j=0;jm_homeVector.size() && !rc;i++) + { + unsigned int j; + + for (j=0;jm_stackVector.size() && !rc;j++) + { + const PlayingCardVector cardVector=this->m_stackVector[j]->getCardVector(); + + if (cardVector.size()>0) + { + PlayingCardVector addCardVector; + + addCardVector.push_back(cardVector[cardVector.size()-1]); + + if (this->m_homeVector[i]->canAddCards(addCardVector)) + { + pDst=this->m_homeVector[i]; + srcStackIndex=cardVector.size()-1; + pSrc=this->m_stackVector[j]; + + rc=true; + } + } + } + } + } + + // look at each stack and try to find the first available card that from another + // stack that can be moved to the stack. + if (!rc) + { + for (i=0;im_stackVector.size() && !rc;i++) + { + unsigned int j; + + for (j=0;jm_stackVector.size() && !rc;j++) + { + // can't move a stack to itself + if (i!=j) + { + PlayingCardVector addCardVector(this->m_stackVector[j]->getCardVector()); + unsigned int k=0; + while (!rc && addCardVector.size()>0) + { + // ok find the first card that is faceup. + if (!addCardVector[0].isFaceUp()) + { + addCardVector.erase(addCardVector.begin()); + } + else if (this->m_stackVector[i]->canAddCards(addCardVector)) + { + pDst=this->m_stackVector[i]; + srcStackIndex=k; + pSrc=this->m_stackVector[j]; + + rc=true; + } + else + { + addCardVector.erase(addCardVector.begin()); + } + k++; + } + } + } + } + } + + + + return rc; +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void YukonBoard::newGame() +{ + // call the base class + GameBoard::newGame(); + + CardDeck deck; + unsigned int i; + + + while(!deck.isEmpty()) + { + this->m_pDeck->addCard(deck.next()); + } + + + DealItemVector dealItemVector; + + + // Create the dealItemVector to direct the DealAnimation object on + // how to deal the cards. + for (i=0;im_stackVector.size();i++) + { + dealItemVector.push_back(DealItem(this->m_stackVector[i],m_pDeck)); + + unsigned int j; + + for (j=0;j0) + { + for (j=0;j<4;j++) + { + dealItemVector[i].addCard(true); + } + } + } + + // ok now start the deal. We don't need a move record for this item. + m_dealAni.dealCards(dealItemVector,false); +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void YukonBoard::addGameMenuItems(QMenu & menu) +{ + Q_UNUSED(menu); +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void YukonBoard::loadSettings(const QSettings & settings) +{ + Q_UNUSED(settings); +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void YukonBoard::saveSettings(QSettings & settings) +{ + Q_UNUSED(settings); +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void YukonBoard::setCheat(bool cheat) +{ + this->m_cheat=cheat; + + for(unsigned int i=0;im_stackVector.size();i++) + { + m_stackVector[i]->setCheat(cheat); + } +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void YukonBoard::slotStackCardsClicked(CardStack * pCardStack, + const PlayingCardVector & cardVector, + const CardMoveRecord & startMoveRecord) +{ + unsigned int i=0; + CardStack * pFoundStack=NULL; + + if (NULL==pCardStack) + { + return; + } + + // first see if the card can be added to the sent home stack + if (cardVector.size()==1) + { + for(i=0;im_homeVector.size();i++) + { + if (pCardStack!=this->m_homeVector[i] && + this->m_homeVector[i]->canAddCards(cardVector)) + { + pFoundStack=this->m_homeVector[i]; + break; + } + } + } + + // if we did not find a match look at the stacks. + if (NULL==pFoundStack) + { + for(i=0;im_stackVector.size();i++) + { + if (pCardStack!=this->m_stackVector[i] && + this->m_stackVector[i]->canAddCards(cardVector)) + { + pFoundStack=this->m_stackVector[i]; + break; + } + } + } + + if (pFoundStack) + { + CardMoveRecord moveRecord(startMoveRecord); + pFoundStack->addCards(cardVector,moveRecord,true); + + // perform the move of the cards and animate it if animations + // are enabled + m_sToSAniMove.moveCards(moveRecord); + } +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void YukonBoard::calcScore() +{ + int score=0; + + for(unsigned int i=0;im_homeVector.size();i++) + { + score+=this->m_homeVector[i]->score(); + } + + emit scoreChanged(score,""); +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void YukonBoard::resizeEvent (QResizeEvent * event) +{ + int i; + + this->setCardResizeAlg(8,ResizeByWidth); + + GameBoard::resizeEvent(event); + + QSize cardSize(CardPixmaps::getInst().getCardSize()); + + // ok let's see if it fits when we size things by width + // basically we just need to check if we have room to draw + // 4 cards vertically. If we don't have enough room we + // will try to draw by height. + if (cardSize.height()*4+GameBoard::LayoutSpacing*5>event->size().height()) + { + this->setCardResizeAlg(4,ResizeByHeight); + + GameBoard::resizeEvent(event); + + cardSize=CardPixmaps::getInst().getCardSize(); + } + + + + QPointF currPos(GameBoard::LayoutSpacing,GameBoard::LayoutSpacing); + + + for (i=0;i(m_homeVector.size());i++) + { + m_homeVector[i]->setPos(currPos); + currPos.ry()+=GameBoard::LayoutSpacing+cardSize.height(); + } + + currPos.setX(event->size().width()-GameBoard::LayoutSpacing-cardSize.width()); + currPos.setY(GameBoard::LayoutSpacing); + for (i=m_stackVector.size()-1;i>=0;i--) + { + m_stackVector[i]->setPos(currPos); + currPos.rx()-=cardSize.width()+GameBoard::LayoutSpacing; + } + + + currPos.setX(GameBoard::LayoutSpacing*4+cardSize.width()*4); + currPos.setY(event->size().height()-GameBoard::LayoutSpacing-cardSize.height()); + + m_pDeck->setPos(currPos); + +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +void YukonBoard::createStacks() +{ + unsigned int i; + + // first create the home widgets where the cards need to be eventually stacked to + // win the game. + for(i=0;i<4;i++) + { + this->m_homeVector.push_back(new FreeCellHome); + this->m_scene.addItem(m_homeVector[i]); + } + + // now create the 7 rows for the stacks. + for (i=0;i<7;i++) + { + this->m_stackVector.push_back(new KlondikeStack); + this->m_scene.addItem(m_stackVector[i]); + this->connect(this->m_stackVector[i],SIGNAL(cardsMovedByDragDrop(CardMoveRecord)), + this,SLOT(slotCardsMoved(CardMoveRecord))); + this->connect(this->m_stackVector[i],SIGNAL(movableCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord)), + this,SLOT(slotStackCardsClicked(CardStack*,PlayingCardVector,CardMoveRecord))); + } + + this->m_pDeck=new FreeCellDeck; + this->m_scene.addItem(this->m_pDeck); + +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +bool YukonBoard::isGameWon()const +{ + bool rc=true; + + for (unsigned int i=0;im_homeVector.size();i++) + { + if (!this->m_homeVector[i]->isStackComplete()) + { + rc=false; + break; + } + } + + return rc; +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +bool YukonBoard::isGameWonNotComplete()const +{ + bool rc=true; + + for (unsigned int i=0;im_stackVector.size();i++) + { + if (!(this->m_stackVector[i]->cardsAscendingTopToBottom() && + this->m_stackVector[i]->allCardsFaceUp())) + { + rc=false; + break; + } + } + + return rc; +} diff --git a/plugins/qsolocards_plugin/YukonBoard.h b/plugins/qsolocards_plugin/YukonBoard.h new file mode 100644 index 000000000..64a38a740 --- /dev/null +++ b/plugins/qsolocards_plugin/YukonBoard.h @@ -0,0 +1,80 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __YUKONBOARD_H__ +#define __YUKONBOARD_H__ + +#include "GameBoard.h" +#include "FreeCellHome.h" +#include "FreeCellDeck.h" +#include "KlondikeStack.h" + +#include + + +class YukonBoard : public GameBoard +{ + Q_OBJECT +public: + YukonBoard(); + ~YukonBoard(); + + bool getHint(CardStack * & pSrc, + unsigned int & srcStackIndex, + CardStack * & pDst); + + inline bool hasDemo() const {return true;} + + void newGame(); + + void addGameMenuItems(QMenu & menu); + + void loadSettings(const QSettings & settings); + void saveSettings(QSettings & settings); + + inline bool isCheating() const {return m_cheat;} + + void setCheat(bool cheat); + + inline bool supportsScore() const{return true;} + +public slots: + void slotStackCardsClicked(CardStack * pCardStack, + const PlayingCardVector & cardVector, + const CardMoveRecord &); + +protected: + void calcScore(); + + virtual void resizeEvent (QResizeEvent * event); + + virtual void createStacks(); + + bool isGameWon()const; + bool isGameWonNotComplete()const; + +private: + FreeCellDeck * m_pDeck; + + std::vector m_homeVector; // we will have 4 items in this vector one for each suit + std::vector m_stackVector; // we will have 7 items in this vector + + bool m_cheat; +}; + +#endif // YUKONBOARD_H diff --git a/plugins/qsolocards_plugin/help/._gpl3.html b/plugins/qsolocards_plugin/help/._gpl3.html new file mode 100644 index 000000000..864802133 Binary files /dev/null and b/plugins/qsolocards_plugin/help/._gpl3.html differ diff --git a/plugins/qsolocards_plugin/help/FreeCellHelp.html b/plugins/qsolocards_plugin/help/FreeCellHelp.html new file mode 100644 index 000000000..71d1499eb --- /dev/null +++ b/plugins/qsolocards_plugin/help/FreeCellHelp.html @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + +

Freecell +Solitaire

+

Written +by Steve Moore

+

Overview

+

Freecell +Solitaire is a solitaire game played with the standard 52 card deck. +The object is to arrange cards of the same suit from ace to king.

+

Rules

+

The +board is setup with eight stacks of cards, four “freecells”, and +four home stacks. The goal is to move all cards to the home stacks in +ascending order from ace to king of the same suit. Cards are placed +one at a time in order on the home stacks. The eight stacks of cards +are dealt with the first four stacks containing seven cards and the +last four contains size cards. All cards in the eight stacks are +dealt face up. Cards can be moved between the stacks by placing red +cards on black cards in descending order from king to ace. But only +one card can be moved to a stack or freecell at a time. A card can +also be played on the home stack, if it is an ace or the next card in +ascending order of a suit in one of the home stacks. Any card can be +placed in an empty freecell or an empty stack. Play will continue +until all moves are exhausted or until all cards are moved to the +home stacks and the game is won. +

+

Scoring

+

A +point is scored when a card is moved to one of the home stacks. A +total of 52 points can be scored, one for each card in the deck. The +current score is indicated in the status bar at the bottom of the +game window.

+

Game +Play

+

Cards +that are movable will be indicated when the mouse is over them with +the open hand icon. Cards with the open hand icon displayed over them +can be dragged and dropped to another stack or clicked to move them +to another stack. Hints of possible moves are available from the menu +select Control->Hint.

+ + \ No newline at end of file diff --git a/plugins/qsolocards_plugin/help/KlondikeHelp.html b/plugins/qsolocards_plugin/help/KlondikeHelp.html new file mode 100644 index 000000000..1da5ab701 --- /dev/null +++ b/plugins/qsolocards_plugin/help/KlondikeHelp.html @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + +

Klondike +Solitaire

+

Written +by Steve Moore

+

Overview

+

Klondike +Solitaire is a solitaire game played with the standard 52 card deck. +The variations of the game all deal with how many cards are flipped +at once from the deck, and how many times the deck of cards can be +cycled through. The variations are:

+
    +
  • Flip + one – one card is flipped over from the deck at a time, and the + deck can be recycled two times.

    +
  • Flip + three – three cards are flipped over from the deck at a time, and + the there is no limit on the number of times the deck can be + recycled. +

    +
  • No + redeals (flip one) – one card is flipped over from the deck at a + time, and the deck cannot be recycled.

    +
+

Rules

+

The +board is setup with seven stacks of cards, a deck of the remaining +cards, and four home stacks. The goal is to move all cards to the +home stacks in ascending order from ace to king of the same suit. +Cards are placed one at a time in order on the home stacks. The +seven stacks of cards are dealt with each stack containing one more +card than the previous stack. The first stack will contain one card +and the last of the seven will contain seven cards. All cards in the +seven stacks are face down accept the top card. Cards can be moved +between the stacks by placing red cards on black cards in descending +order from king to ace. When a card is moved of a stack with a face +down card being exposed it will be flipped over automatically. A +card can also be played on the home stack, if it is an ace or the +next card in ascending order of a suit in one of the home stacks. +Once moves are exhausted on the board the next set of cards can be +flipped over from the deck. The top card in the flipped over cards +from the deck can be played using the same rules described for the +stacks. Play will continue until all moves are exhausted or until +all cards are moved to the home stacks and the game is won. +

+

Scoring

+

A +point is scored when a card is moved to one of the home stacks. A +total of 52 points can be scored, one for each card in the deck. The +current score is indicated in the status bar at the bottom of the +game window.

+

Game +Play

+

Cards +that are movable will be indicated when the mouse is over them with +the open hand icon. Cards with the open hand icon displayed over them +can be dragged and dropped to another stack or clicked to move +them to another stack. Hints of possible moves are available from the +menu select Control->Hint.

+ + diff --git a/plugins/qsolocards_plugin/help/Spider3DeckHelp.html b/plugins/qsolocards_plugin/help/Spider3DeckHelp.html new file mode 100644 index 000000000..2b81dcb09 --- /dev/null +++ b/plugins/qsolocards_plugin/help/Spider3DeckHelp.html @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + +

Three +Deck Spider Solitaire

+

Written +by Steve Moore

+

Overview

+

Three +Deck Spider Solitaire is a variation of Spider Solitaire played with +156 cards or three full decks of playing cards. +

+

Rules

+

The +cards are dealt into six rows of six cards, and six rows of five +cards. All the cards are face down except the last card in each +stack. A card can be moved from one stack to another if it is the +next card in descending order with King being high and Ace being low +regardless of suit. But a stack of cards can only be moved if they +are in descending order and the same suit. Once moves are exhausted +twelve cards can be dealt one on top of each stack ( The last deal is +an exception cards are only added to the first six stacks. ). Cards +cannot be dealt if there is an empty stack.

+

The +object of the game is to get all twelve suits in descending order +from King to Ace. Once a suit is complete it can be sent home or +moved to one of the twelve empty slots at the top of the board. Once +all twelve suits are sent home the game is over.

+

Scoring

+

A +point is scored when cards in descending order of the same suit are +stacked on one another. So, the total number of points available is +144 or 12 for each suit. The score along with the number of deals +remaining are indicated in the status bar at the bottom of the game +window.

+

Game +Play

+

Cards +that are movable will be indicated when the mouse is over them with +the open hand icon. Cards with the open hand icon displayed over them +can be dragged and dropped to another stack or clicked to move them +to another stack ( For the click case the cards are moved to a +matching suit, non-matching suit, or an empty stack in that order. In +some cases it might be necessary to drag and drop the cards to move +them to the exact stack desired. ). When all moves are exhausted, the +next set of cards can be dealt on top of the current cards by +clicking on the deck in the upper left corner of the board. +

+

Hints +of possible moves are available from the menu select Control->Hint.

+ + \ No newline at end of file diff --git a/plugins/qsolocards_plugin/help/SpiderHelp.html b/plugins/qsolocards_plugin/help/SpiderHelp.html new file mode 100644 index 000000000..8733b68bb --- /dev/null +++ b/plugins/qsolocards_plugin/help/SpiderHelp.html @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + +

Spider +Solitaire

+

Written +by Steve Moore

+

Overview

+

Spider +Solitaire is a solitaire game played with 104 cards. It has three +different variations.

+
    +
  • Four + suits – two complete 52 card decks are used.

    +
  • Two + suits – four sets each of hearts and spades are used.

    +
  • One + suit – eight sets of spades are used.

    +
+

Rules

+

The +game is played the same regardless of the variation. The cards are +dealt into four rows of six cards, and six rows of five cards. All +the cards are face down except the last card in each stack. A card +can be moved from one stack to another if it is the next card in +descending order with King being high and Ace being low regardless of +suit. But a stack of cards can only be moved if they are in +descending order and the same suit. Once moves are exhausted ten +cards can be dealt one on top of each stack. Cards cannot be dealt if +there is an empty stack.

+

The +object of the game is to get all eight sets of suits ( There are +eight sets regardless of the variation. ) in descending order from +King to Ace. Once a suit is complete it can be sent home or moved to +one of the eight empty slots at the top of the board. Once all eight +suits are sent home the game is over.

+

Scoring

+

A +point is scored when cards in descending order of the same suit are +stacked on one another. So, the total number of points available is +96 or 12 for each suit. The score along with the number of deals +remaining are indicated in the status bar at the bottom of the game +window.

+

Game +Play

+

Cards +that are movable will be indicated when the mouse is over them with +the open hand icon. Cards with the open hand icon displayed over them +can be dragged and dropped to another stack or clicked to move them +to another stack ( For the click case the cards are moved to a +matching suit, non-matching suit, or an empty stack in that order. In +some cases it might be necessary to drag and drop the cards to move +them to the exact stack desired. ). When all moves are exhausted, the +next set of cards can be dealt on top of the current cards by +clicking on the deck in the upper left corner of the board. +

+

Hints +of possible moves are available from the menu select Control->Hint.

+ + \ No newline at end of file diff --git a/plugins/qsolocards_plugin/help/SpideretteHelp.html b/plugins/qsolocards_plugin/help/SpideretteHelp.html new file mode 100644 index 000000000..20f7d22bc --- /dev/null +++ b/plugins/qsolocards_plugin/help/SpideretteHelp.html @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + +

Spiderette +Solitaire

+

Written +by Steve Moore

+

Overview

+

Spiderette +Solitaire is a solitaire game played with a standard 52 card deck. +It is a variation of Spider Solitaire that is played with a board +layout similar to that of Klondike Solitaire.

+

Rules

+

The +cards are dealt into seven stacks. The number of cards increases by +one for each stack. The first stack contains one card and the last +contains seven. All the cards are face down except the last card in +each stack. A card can be moved from one stack to another if it is +the next card in descending order with King being high and Ace being +low regardless of suit. But a stack of cards can only be moved if +they are in descending order and the same suit. Once moves are +exhausted seven cards can be dealt one on top of each stack ( The +last deal is an exception cards are only added to the first three +stacks. ). Cards cannot be dealt if there is an empty stack.

+

The +object of the game is to get all four suits in descending order from +King to Ace. Once a suit is complete it can be sent home or moved to +one of the four empty slots at the top of the board. Once all fourxs +suits are sent home the game is over.

+

Scoring

+

A +point is scored when cards in descending order of the same suit are +stacked on one another. So, the total number of points available is +48 or 12 for each suit. The score along with the number of deals +remaining are indicated in the status bar at the bottom of the game +window.

+

Game +Play

+

Cards +that are movable will be indicated when the mouse is over them with +the open hand icon. Cards with the open hand icon displayed over them +can be dragged and dropped to another stack or clicked to move them +to another stack ( For the click case the cards are moved to a +matching suit, non-matching suit, or an empty stack in that order. In +some cases it might be necessary to drag and drop the cards to move +them to the exact stack desired. ). When all moves are exhausted, the +next set of cards can be dealt on top of the current cards by +clicking on the deck in the upper left corner of the board. +

+

Hints +of possible moves are available from the menu select Control->Hint.

+ + \ No newline at end of file diff --git a/plugins/qsolocards_plugin/help/YukonHelp.html b/plugins/qsolocards_plugin/help/YukonHelp.html new file mode 100644 index 000000000..f56597dbc --- /dev/null +++ b/plugins/qsolocards_plugin/help/YukonHelp.html @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + +

Yukon +Solitaire

+

Written +by Steve Moore

+

Overview

+

Yukon +Solitaire is a solitaire game played with the standard 52 card deck. +The object is to arrange cards of the same suit from ace to king.

+

Rules

+

The +board is setup with seven stacks of cards, and four home stacks. The +goal is to move all cards to the home stacks in ascending order from +ace to king of the same suit. Cards are placed one at a time in order +on the home stacks. The seven stacks of cards are dealt. The first +stack has just one face up card. The remaining have one ( second +stack ) increasing to six ( seventh stack ) cards face down and five +cards face up. Cards can be moved between the stacks by placing red +cards on black cards in ascending order ( You can move cards as deep +in the a stack as you wish. The red to black ascending relationship +only applies to the top card being moved and the last card in the +stack to which it is moved. ). When a card is moved of a stack with +a face down card being exposed it will be flipped over automatically. +A card can also be played on the home stack, if it is an ace or the +next card in ascending order of a suit in one of the home stacks. +Once moves are exhausted on the board the next set of cards can be +flipped over from the deck. The top card in the flipped over cards +from the deck can be played using the same rules described for the +stacks. Play will continue until all moves are exhausted or until all +cards are moved to the home stacks and the game is won. +

+

Scoring

+

A +point is scored when a card is moved to one of the home stacks. A +total of 52 points can be scored, one for each card in the deck. The +current score is indicated in the status bar at the bottom of the +game window.

+

Game +Play

+

Cards +that are movable will be indicated when the mouse is over them with +the open hand icon. Cards with the open hand icon displayed over them +can be dragged and dropped to another stack or clicked to move them +to another stack. Hints of possible moves are available from the menu +select Control->Hint.

+ + \ No newline at end of file diff --git a/plugins/qsolocards_plugin/help/gpl3.html b/plugins/qsolocards_plugin/help/gpl3.html new file mode 100644 index 000000000..d127cadf1 --- /dev/null +++ b/plugins/qsolocards_plugin/help/gpl3.html @@ -0,0 +1,692 @@ + + + + + + GNU General Public License - GNU Project - Free Software Foundation (FSF) + +

GNU GENERAL PUBLIC LICENSE

+

Version 3, 29 June 2007

+ +

Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>

+ Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed.

+ +

Preamble

+ +

The GNU General Public License is a free, copyleft license for +software and other kinds of works.

+ +

The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too.

+ +

When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things.

+ +

To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others.

+ +

For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights.

+ +

Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it.

+ +

For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions.

+ +

Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users.

+ +

Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free.

+ +

The precise terms and conditions for copying, distribution and +modification follow.

+ +

TERMS AND CONDITIONS

+ +

0. Definitions.

+ +

“This License” refers to version 3 of the GNU General Public License.

+ +

“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks.

+ +

“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations.

+ +

To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work.

+ +

A “covered work” means either the unmodified Program or a work based +on the Program.

+ +

To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well.

+ +

To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying.

+ +

An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion.

+ +

1. Source Code.

+ +

The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work.

+ +

A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language.

+ +

The “System Libraries” of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it.

+ +

The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work.

+ +

The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source.

+ +

The Corresponding Source for a work in source code form is that +same work.

+ +

2. Basic Permissions.

+ +

All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law.

+ +

You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you.

+ +

Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary.

+ +

3. Protecting Users' Legal Rights From Anti-Circumvention Law.

+ +

No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures.

+ +

When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures.

+ +

4. Conveying Verbatim Copies.

+ +

You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program.

+ +

You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee.

+ +

5. Conveying Modified Source Versions.

+ +

You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions:

+ +
    +
  • a) The work must carry prominent notices stating that you modified + it, and giving a relevant date.
  • + +
  • b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + “keep intact all notices”.
  • + +
  • c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it.
  • + +
  • d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so.
  • +
+ +

A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate.

+ +

6. Conveying Non-Source Forms.

+ +

You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways:

+ +
    +
  • a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange.
  • + +
  • b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge.
  • + +
  • c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b.
  • + +
  • d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements.
  • + +
  • e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d.
  • +
+ +

A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work.

+ +

A “User Product” is either (1) a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product.

+ +

“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made.

+ +

If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM).

+ +

The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network.

+ +

Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying.

+ +

7. Additional Terms.

+ +

“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions.

+ +

When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission.

+ +

Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms:

+ +
    +
  • a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or
  • + +
  • b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or
  • + +
  • c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or
  • + +
  • d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or
  • + +
  • e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or
  • + +
  • f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors.
  • +
+ +

All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying.

+ +

If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms.

+ +

Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way.

+ +

8. Termination.

+ +

You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11).

+ +

However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation.

+ +

Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice.

+ +

Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10.

+ +

9. Acceptance Not Required for Having Copies.

+ +

You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so.

+ +

10. Automatic Licensing of Downstream Recipients.

+ +

Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License.

+ +

An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts.

+ +

You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it.

+ +

11. Patents.

+ +

A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”.

+ +

A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License.

+ +

Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version.

+ +

In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party.

+ +

If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid.

+ +

If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it.

+ +

A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007.

+ +

Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law.

+ +

12. No Surrender of Others' Freedom.

+ +

If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program.

+ +

13. Use with the GNU Affero General Public License.

+ +

Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such.

+ +

14. Revised Versions of this License.

+ +

The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns.

+ +

Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation.

+ +

If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program.

+ +

Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version.

+ +

15. Disclaimer of Warranty.

+ +

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

+ +

16. Limitation of Liability.

+ +

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES.

+ +

17. Interpretation of Sections 15 and 16.

+ +

If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee.

+ +

END OF TERMS AND CONDITIONS

+ +

How to Apply These Terms to Your New Programs

+ +

If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms.

+ +

To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found.

+ +
    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ +

Also add information on how to contact you by electronic and paper mail.

+ +

If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode:

+ +
    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+ +

The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an “about box”.

+ +

You should also get your employer (if you work as a programmer) or school, +if any, to sign a “copyright disclaimer” for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>.

+ +

The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>.

+ + + \ No newline at end of file diff --git a/plugins/qsolocards_plugin/images/anglo_bitmap.svg b/plugins/qsolocards_plugin/images/anglo_bitmap.svg new file mode 100644 index 000000000..e5cdb7fd5 --- /dev/null +++ b/plugins/qsolocards_plugin/images/anglo_bitmap.svg @@ -0,0 +1,10159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/qsolocards_plugin/images/greenfelt.png b/plugins/qsolocards_plugin/images/greenfelt.png new file mode 100644 index 000000000..9bed0cb77 Binary files /dev/null and b/plugins/qsolocards_plugin/images/greenfelt.png differ diff --git a/plugins/qsolocards_plugin/images/sol128x128.png b/plugins/qsolocards_plugin/images/sol128x128.png new file mode 100644 index 000000000..6a759d693 Binary files /dev/null and b/plugins/qsolocards_plugin/images/sol128x128.png differ diff --git a/plugins/qsolocards_plugin/images/sol16x16.png b/plugins/qsolocards_plugin/images/sol16x16.png new file mode 100644 index 000000000..42bf709e0 Binary files /dev/null and b/plugins/qsolocards_plugin/images/sol16x16.png differ diff --git a/plugins/qsolocards_plugin/images/sol256x256.png b/plugins/qsolocards_plugin/images/sol256x256.png new file mode 100644 index 000000000..9125e38c6 Binary files /dev/null and b/plugins/qsolocards_plugin/images/sol256x256.png differ diff --git a/plugins/qsolocards_plugin/images/sol32x32.png b/plugins/qsolocards_plugin/images/sol32x32.png new file mode 100644 index 000000000..a145497dc Binary files /dev/null and b/plugins/qsolocards_plugin/images/sol32x32.png differ diff --git a/plugins/qsolocards_plugin/images/sol512x512.png b/plugins/qsolocards_plugin/images/sol512x512.png new file mode 100644 index 000000000..438fa5e0a Binary files /dev/null and b/plugins/qsolocards_plugin/images/sol512x512.png differ diff --git a/plugins/qsolocards_plugin/main.cpp b/plugins/qsolocards_plugin/main.cpp new file mode 100644 index 000000000..7746402b0 --- /dev/null +++ b/plugins/qsolocards_plugin/main.cpp @@ -0,0 +1,28 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/plugins/qsolocards_plugin/mainwindow.cpp b/plugins/qsolocards_plugin/mainwindow.cpp new file mode 100644 index 000000000..9456b26f4 --- /dev/null +++ b/plugins/qsolocards_plugin/mainwindow.cpp @@ -0,0 +1,653 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "mainwindow.h" + +#include +#include +#include +#include +#include +#include + +#include "CardAnimationLock.h" + +const unsigned int MainWindow::MaxWidth=780; +const unsigned int MainWindow::MaxHeight=900; +const QString MainWindow::SizeStr("size"); +const QString MainWindow::PtStr("point"); +const QString MainWindow::HelpStr("help"); +const QString MainWindow::GameIdStr("LastGame"); +const QString MainWindow::AnimationStr("EnableAnimations"); + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent), + m_pGameBoard(NULL), + m_pMenuBar(NULL), + m_pGameOptionsMenu(NULL), + m_pHelpMenu(NULL), + m_settings("QSoloCards","QSoloCards"), + m_pNewGameAction(NULL), + m_pRestartAction(NULL), + m_pUndoAction(NULL), + m_pRedoAction(NULL), + m_pHintAction(NULL), + m_pAnimationAction(NULL), + m_pDemoAction(NULL), + m_pCheatAction(NULL), + m_pStatusBar(NULL), + m_pStatusBarLabel(NULL), + m_helpWindow(NULL), + m_aboutWindow(NULL), + m_gameMgr(), + m_firstShow(false) +{ + // make the window a nice size and make sure it is on the screen + QSize deskSize(QApplication::desktop()->size()); + + unsigned int width=MaxWidth<(unsigned int)deskSize.width()?MaxWidth:deskSize.width()-100; + unsigned int height=MaxHeight<(unsigned int)deskSize.height()?MaxHeight:deskSize.height()-100; + + int locX=(deskSize.width()-width)/2; + int locY=(deskSize.height()-height)/2; + + this->resize(m_settings.value(SizeStr, QSize(width, height)).toSize()); + this->move(m_settings.value(PtStr, QPoint(locX, locY)).toPoint()); + + // create the status bar we will use to show the score and game info. + this->m_pStatusBar=new QStatusBar; + this->m_pStatusBarLabel=new QLabel; + this->m_pStatusBar->addPermanentWidget(m_pStatusBarLabel); + this->setStatusBar(this->m_pStatusBar); + + // show the last game played or the default game if we don't have a last played. + // we need to create the board before adding the menus. This is done. So, the + // initial check state of the game selected will reflect the initial game. + int gameId=m_settings.value(GameIdStr, GameMgr::DefaultGame).toInt(); + GameBoard * pGameBoard=m_gameMgr.getGame((GameMgr::GameId)gameId); + + // add the menus for the window + this->addMenuItems(); + + // finally setup the board. + this->setupGameBoard(pGameBoard); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +MainWindow::~MainWindow() +{ + // save the current settings for the game + this->m_settings.beginGroup(this->m_pGameBoard->gameSettingsId()); + this->m_pGameBoard->saveSettings(this->m_settings); + this->m_settings.endGroup(); + + // save the position of the game window + this->m_settings.setValue(SizeStr,this->size()); + this->m_settings.setValue(PtStr,this->pos()); + + // save the current game being played + this->m_settings.setValue(GameIdStr,this->m_gameMgr.getGameId()); + + // save if animation is enabled or not + this->m_settings.setValue(AnimationStr,this->m_pAnimationAction->isChecked()); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotNewGame() +{ + if (NULL!=this->m_pGameBoard) + { + this->m_pGameBoard->newGame(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotRestartGame() +{ + if (NULL!=this->m_pGameBoard) + { + this->m_pGameBoard->restartGame(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotSelectGame(QAction * pAction) +{ + if (NULL!=pAction) + { + bool ok=false; + int gameId=pAction->data().toInt(&ok); + + // if we got the gameid and it is not the same as the current game + // set the game as the current. + if (ok && gameId!=this->m_gameMgr.getGameId()) + { + this->setupGameBoard(this->m_gameMgr.getGame((GameMgr::GameId)gameId)); + } + } +} + +void MainWindow::slotAnimation(bool checked) +{ + CardAnimationLock::getInst().enableAnimations(checked); + + if (this->m_pGameBoard->hasDemo() && checked) + { + this->m_pDemoAction->setEnabled(true); + } + else + { + this->m_pDemoAction->setEnabled(false); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotCheat(bool checked) +{ + if (NULL!=this->m_pGameBoard) + { + this->m_pGameBoard->setCheat(checked); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotUndo() +{ + if (NULL!=this->m_pGameBoard) + { + if (this->m_pGameBoard->canUndoMove()) + { + this->m_pGameBoard->undoMove(); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotRedo() +{ + if (NULL!=this->m_pGameBoard) + { + if (this->m_pGameBoard->canRedoMove()) + { + this->m_pGameBoard->redoMove(); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotHint() +{ + if (NULL!=this->m_pGameBoard) + { + this->m_pGameBoard->showHint(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotUndoAvail(bool avail) +{ + if (this->m_pUndoAction && !m_pDemoAction->isChecked()) + { + this->m_pRestartAction->setEnabled(avail); + + this->m_pUndoAction->setEnabled(avail); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotRedoAvail(bool avail) +{ + if (this->m_pRedoAction) + { + this->m_pRedoAction->setEnabled(avail); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotScoreChanged(int score,const QString & info) +{ + if (this->m_pStatusBar && !m_pDemoAction->isChecked()) + { + QString statusMsg(tr("%1 Score: %2").arg(info).arg(QString::number(score)).trimmed()); + + this->m_pStatusBarLabel->setText(statusMsg); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotAbout() +{ + if (NULL==this->m_aboutWindow) + { + this->m_aboutWindow=new About(this); + connect(this->m_aboutWindow.data(),SIGNAL(showLink(QString)), + this,SLOT(slotShowHelp(QString))); + } + this->m_aboutWindow->show(); + this->m_aboutWindow->activateWindow(); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotHelp() +{ + if (this->m_pGameBoard) + { + this->slotShowHelp(this->m_pGameBoard->helpFile()); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotHelpClosed(int finishCode) +{ + Q_UNUSED(finishCode); + + this->m_settings.beginGroup(HelpStr); + this->m_settings.setValue(SizeStr,this->m_helpWindow->size()); + this->m_settings.setValue(PtStr,this->m_helpWindow->pos()); + this->m_settings.endGroup(); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotShowHelp(const QString & helpFile) +{ + if (NULL==this->m_helpWindow) + { + this->m_helpWindow=new Help(this,helpFile); + this->m_settings.beginGroup(HelpStr); + this->m_helpWindow->resize(this->m_settings.value(SizeStr,QSize(640,480)).toSize()); + this->m_helpWindow->move(this->m_settings.value(PtStr,QPoint(200,200)).toPoint()); + this->m_settings.endGroup(); + this->connect(this->m_helpWindow,SIGNAL(finished(int)),this,SLOT(slotHelpClosed(int))); + this->m_helpWindow->show(); + } + else + { + this->m_helpWindow->setHelpFile(helpFile); + this->m_helpWindow->show(); + this->m_helpWindow->activateWindow(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotAnimationStarted() +{ + m_pRestartAction->setEnabled(false); + m_pDemoAction->setEnabled(false); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotAnimationComplete() +{ + m_pRestartAction->setEnabled(true); + m_pDemoAction->setEnabled(true); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// this timeout is just to delay slightly calling newGame for a board. So, the +// animation will start with the QGraphicsScene visible and the board will already be +// completely drawn. +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotNewGameTimer() +{ + if (this->m_pGameBoard) + { + this->m_pMenuBar->setEnabled(true); + this->m_pGameBoard->newGame(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotDemoStarted() +{ + m_pNewGameAction->setEnabled(false); + m_pRestartAction->setEnabled(false); + m_pUndoAction->setEnabled(false); + m_pRedoAction->setEnabled(false); + m_pHintAction->setEnabled(false); + m_pAnimationAction->setEnabled(false); + m_pGameSelectMenu->setEnabled(false); + m_pGameOptionsMenu->setEnabled(false); + m_pCheatAction->setEnabled(false); + + m_pDemoAction->setChecked(true); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotDemoStopped() +{ + m_pNewGameAction->setEnabled(true); + m_pRestartAction->setEnabled(true); + m_pHintAction->setEnabled(true); + m_pAnimationAction->setEnabled(true); + m_pGameSelectMenu->setEnabled(true); + m_pGameOptionsMenu->setEnabled(true); + m_pCheatAction->setEnabled(true); + + + if (this->m_pGameBoard->canUndoMove()) + { + m_pUndoAction->setEnabled(true); + } + + if (this->m_pGameBoard->canRedoMove()) + { + m_pRedoAction->setEnabled(true); + } + + m_pDemoAction->setChecked(false); + +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::slotDemoActionItem(bool checked) +{ + if (this->m_pGameBoard) + { + if (checked) + { + this->m_pGameBoard->startDemo(); + } + else + { + this->m_pGameBoard->stopDemo(); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// we are just using the showEvent to make sure that we don't start the animation of the dealing +// of cards for the game until the window has been shown. +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::showEvent(QShowEvent * pShowEvent) +{ + Q_UNUSED(pShowEvent); + if (!m_firstShow && NULL!=this->m_pGameBoard) + { + this->m_pGameBoard->newGame(); + + m_firstShow=true; + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::addMenuItems() +{ + // create the menu for the app. + this->m_pMenuBar=new QMenuBar(this); + + // create a game menu + QMenu * pGameMenu=new QMenu(tr("Game").trimmed(),this->m_pMenuBar); + + m_pNewGameAction=new QAction(tr("New Game").trimmed(),pGameMenu); + m_pNewGameAction->setShortcuts(QKeySequence::New); + this->connect(m_pNewGameAction,SIGNAL(triggered()), + this,SLOT(slotNewGame())); + pGameMenu->addAction(m_pNewGameAction); + + this->m_pRestartAction=new QAction(tr("Restart Game").trimmed(),pGameMenu); + this->m_pRestartAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); + this->connect(this->m_pRestartAction,SIGNAL(triggered()), + this,SLOT(slotRestartGame())); + + pGameMenu->addAction(this->m_pRestartAction); + + pGameMenu->addSeparator(); + + this->m_pGameSelectMenu=new QMenu(tr("Select Game").trimmed(),pGameMenu); + // add the available games to the menu. + this->m_gameMgr.buildGameListMenu(*this->m_pGameSelectMenu); + // connecting this one up a little different. Since, we are building + // a generic menu where we don't know what the contents are connect up + // to the menus triggered event. We can then get the action and from it's + // user data the id of the game selected. + this->connect(this->m_pGameSelectMenu,SIGNAL(triggered(QAction*)), + this,SLOT(slotSelectGame(QAction*))); + + pGameMenu->addMenu(this->m_pGameSelectMenu); + +#if !(defined Q_WS_MAC) + pGameMenu->addSeparator(); +#endif + + + QAction * pQuit=new QAction(tr("Quit").trimmed(),pGameMenu); + pQuit->setMenuRole(QAction::QuitRole); + pQuit->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); + this->connect(pQuit,SIGNAL(triggered()), + this,SLOT(close())); + pGameMenu->addAction(pQuit); + + this->m_pMenuBar->addMenu(pGameMenu); + + /////////////////////////////////////////////////////////////////////////// + // create a control menu + // for the cheat and undo menu items + /////////////////////////////////////////////////////////////////////////// + QMenu * pCtrlMenu=new QMenu(tr("Control").trimmed(),this->m_pMenuBar); + + m_pUndoAction=new QAction(tr("Undo").trimmed(),pCtrlMenu); + m_pUndoAction->setShortcuts(QKeySequence::Undo); + this->connect(m_pUndoAction,SIGNAL(triggered()), + this,SLOT(slotUndo())); + pCtrlMenu->addAction(m_pUndoAction); + + m_pRedoAction=new QAction(tr("Redo").trimmed(),pCtrlMenu); + m_pRedoAction->setShortcuts(QKeySequence::Redo); + this->connect(m_pRedoAction,SIGNAL(triggered()), + this,SLOT(slotRedo())); + pCtrlMenu->addAction(m_pRedoAction); + + m_pHintAction=new QAction(tr("Hint").trimmed(),pCtrlMenu); + m_pHintAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_H)); + this->connect(m_pHintAction,SIGNAL(triggered()), + this,SLOT(slotHint())); + pCtrlMenu->addAction(m_pHintAction); + + pCtrlMenu->addSeparator(); + + m_pAnimationAction=new QAction(tr("Animation").trimmed(),pCtrlMenu); + m_pAnimationAction->setCheckable(true); + this->connect(m_pAnimationAction,SIGNAL(triggered(bool)), + this,SLOT(slotAnimation(bool))); + pCtrlMenu->addAction(m_pAnimationAction); + + m_pAnimationAction->setChecked(m_settings.value(AnimationStr, true).toBool()); + + CardAnimationLock::getInst().enableAnimations(m_pAnimationAction->isChecked()); + + + m_pDemoAction=new QAction(tr("Demo").trimmed(),pCtrlMenu); + m_pDemoAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); + m_pDemoAction->setCheckable(true); + this->connect(m_pDemoAction,SIGNAL(triggered(bool)), + this,SLOT(slotDemoActionItem(bool))); + pCtrlMenu->addAction(m_pDemoAction); + + + pCtrlMenu->addSeparator(); + + m_pCheatAction=new QAction(tr("Cheat").trimmed(),pCtrlMenu); + m_pCheatAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C)); + m_pCheatAction->setCheckable(true); + this->connect(m_pCheatAction,SIGNAL(triggered(bool)), + this,SLOT(slotCheat(bool))); + pCtrlMenu->addAction(m_pCheatAction); + + + this->m_pMenuBar->addMenu(pCtrlMenu); + + + /////////////////////////////////////////////////////////////////////////// + // create a game options menu + // this menu will get the specific game option settings to add to the menu + // from the GameBoard class. We will not add it to the menu at this time. + // It will be added and/or removed when the game board is setup. It will + // only be added if it is needed. + /////////////////////////////////////////////////////////////////////////// + m_pGameOptionsMenu=new QMenu(tr("&Options").trimmed(),this->m_pMenuBar); + + //////////////////////////////////////////////////////////////////////////// + // add the help menu + //////////////////////////////////////////////////////////////////////////// + this->m_pHelpMenu=new QMenu(tr("&Help").trimmed(),this->m_pMenuBar); + + QAction * pHelp=new QAction(tr("Game Help").trimmed(),this->m_pHelpMenu); + pHelp->setShortcut(QKeySequence(Qt::Key_F1)); + this->connect(pHelp,SIGNAL(triggered()), + this,SLOT(slotHelp())); + this->m_pHelpMenu->addAction(pHelp); + +#if !(defined Q_WS_MAC) + this->m_pHelpMenu->addSeparator(); +#endif + + QAction * pAbout=new QAction(tr("&About").trimmed(),this->m_pHelpMenu); + pAbout->setMenuRole(QAction::AboutRole); + this->connect(pAbout,SIGNAL(triggered()), + this,SLOT(slotAbout())); + this->m_pHelpMenu->addAction(pAbout); + + this->m_pMenuBar->addMenu(this->m_pHelpMenu); + + + + this->setMenuBar(this->m_pMenuBar); + + // also go ahead and hook up the slots for the signals that animation is in progress + // now only used by the restart game menu item. Need the undo stack to be updated before + // we can restart a game. + connect(&CardAnimationLock::getInst(),SIGNAL(animationStarted()), + this,SLOT(slotAnimationStarted())); + + connect(&CardAnimationLock::getInst(),SIGNAL(animationComplete()), + this,SLOT(slotAnimationComplete())); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// Set a gameboard and hook up the menus, set the icon, etc... for the new board +// if there was a previous gameboard. When the QMainWindow::setCentralWidget function is called +// the old game board will be deleted by Qt. +///////////////////////////////////////////////////////////////////////////////////////////// +void MainWindow::setupGameBoard(GameBoard * pGameBoard) +{ + if (pGameBoard) + { + // save settings of the current game if we have one + if (NULL!=this->m_pGameBoard) + { + this->m_settings.beginGroup(this->m_pGameBoard->gameSettingsId()); + this->m_pGameBoard->saveSettings(this->m_settings); + this->m_settings.endGroup(); + } + + this->m_pGameBoard=pGameBoard; + + // connect the gameboards score changed signal to our slot so we + // can get score changes and display them. But first clear the + // current contents of the statusbar to get ride of old info if necessary. + this->m_pStatusBar->showMessage(""); + this->m_pStatusBarLabel->setText(""); + this->connect(this->m_pGameBoard,SIGNAL(scoreChanged(int,QString)), + this,SLOT(slotScoreChanged(int,QString))); + + this->m_settings.beginGroup(this->m_pGameBoard->gameSettingsId()); + this->m_pGameBoard->loadSettings(m_settings); + this->m_settings.endGroup(); + + + this->setCentralWidget(this->m_pGameBoard); + this->setWindowTitle(tr("QSoloCards: %1").arg(this->m_pGameBoard->gameName()).trimmed()); + + // connect up the game board to the menus + m_pUndoAction->setEnabled(this->m_pGameBoard->canUndoMove()); + m_pRedoAction->setEnabled(this->m_pGameBoard->canRedoMove()); + m_pRestartAction->setEnabled(this->m_pGameBoard->canUndoMove()); + + this->m_pMenuBar->removeAction(this->m_pGameOptionsMenu->menuAction()); + + this->m_pGameOptionsMenu->clear(); + this->m_pGameBoard->addGameMenuItems(*this->m_pGameOptionsMenu); + + if (!this->m_pGameOptionsMenu->isEmpty()) + { + this->m_pMenuBar->insertMenu(this->m_pHelpMenu->menuAction(),this->m_pGameOptionsMenu); + } + + // set the window icon for the game. + this->setWindowIcon(this->m_pGameBoard->getGamePixmap()); + + + /////////////////////////////////////////////////////////////////////////// + // connect up the slots so we will know when undo and redo actions are available + /////////////////////////////////////////////////////////////////////////// + this->connect(this->m_pGameBoard,SIGNAL(undoAvail(bool)), + this,SLOT(slotUndoAvail(bool))); + + this->connect(this->m_pGameBoard,SIGNAL(redoAvail(bool)), + this,SLOT(slotRedoAvail(bool))); + + if (this->isVisible()) + { + // disable the menus while we wait for the timer to pop. + this->m_pMenuBar->setEnabled(false); + QTimer::singleShot(100,this,SLOT(slotNewGameTimer())); + } + + this->m_pDemoAction->setChecked(false); + + if (this->m_pGameBoard->hasDemo() && CardAnimationLock::getInst().animationsEnabled()) + { + this->m_pDemoAction->setEnabled(true); + + this->connect(this->m_pGameBoard,SIGNAL(demoStarted()), + this,SLOT(slotDemoStarted())); + + this->connect(this->m_pGameBoard,SIGNAL(demoStopped()), + this,SLOT(slotDemoStopped())); + } + else + { + this->m_pDemoAction->setEnabled(false); + } + + } +} + diff --git a/plugins/qsolocards_plugin/mainwindow.h b/plugins/qsolocards_plugin/mainwindow.h new file mode 100644 index 000000000..9e4d874eb --- /dev/null +++ b/plugins/qsolocards_plugin/mainwindow.h @@ -0,0 +1,117 @@ +/* + QSoloCards is a collection of Solitaire card games written using Qt + Copyright (C) 2009 Steve Moore + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include + +#include "GameBoard.h" +#include "Help.h" +#include "About.h" +#include "GameMgr.h" + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + static const unsigned int MaxWidth; + static const unsigned int MaxHeight; + static const QString SizeStr; + static const QString PtStr; + static const QString HelpStr; + static const QString GameIdStr; + static const QString AnimationStr; + + MainWindow(QWidget *parent = 0); + ~MainWindow(); + +public slots: + void slotNewGame(); + void slotRestartGame(); + void slotSelectGame(QAction *); + void slotAnimation(bool); + void slotCheat(bool); + void slotUndo(); + void slotRedo(); + void slotHint(); + + void slotUndoAvail(bool avail); + void slotRedoAvail(bool avail); + + void slotScoreChanged(int score,const QString &); + + void slotHelp(); + void slotAbout(); + + void slotHelpClosed(int); + + void slotShowHelp(const QString & helpFile); + + void slotAnimationStarted(); + void slotAnimationComplete(); + + void slotNewGameTimer(); + + void slotDemoStarted(); + void slotDemoStopped(); + + void slotDemoActionItem(bool); +protected: + void showEvent(QShowEvent * pShowEvent); + +private: + void addMenuItems(); + void setupGameBoard(GameBoard * pGameBoard); + + + + GameBoard * m_pGameBoard; + QMenuBar * m_pMenuBar; + QMenu * m_pGameSelectMenu; + QMenu * m_pGameOptionsMenu; + QMenu * m_pHelpMenu; + QSettings m_settings; + + QAction * m_pNewGameAction; + QAction * m_pRestartAction; + QAction * m_pUndoAction; + QAction * m_pRedoAction; + QAction * m_pHintAction; + QAction * m_pAnimationAction; + QAction * m_pDemoAction; + QAction * m_pCheatAction; + + QStatusBar * m_pStatusBar; + QLabel * m_pStatusBarLabel; + QPointer m_helpWindow; // use a QPointer so we don't have to worry about knowing if + // the help window has been deleted. The Window auto deletes + // when closes. + QPointer m_aboutWindow; + GameMgr m_gameMgr; + bool m_firstShow; +}; + +#endif // MAINWINDOW_H diff --git a/plugins/qsolocards_plugin/object_script.qsolocards_plugin.Debug b/plugins/qsolocards_plugin/object_script.qsolocards_plugin.Debug new file mode 100644 index 000000000..cbdb74bc8 --- /dev/null +++ b/plugins/qsolocards_plugin/object_script.qsolocards_plugin.Debug @@ -0,0 +1,64 @@ +INPUT( +./temp\obj\QSoloCardsPlugin.o +./temp\obj\main.o +./temp\obj\mainwindow.o +./temp\obj\PlayingCard.o +./temp\obj\CardDeck.o +./temp\obj\CardPixmaps.o +./temp\obj\CardStack.o +./temp\obj\DragCardStack.o +./temp\obj\VCardStack.o +./temp\obj\CardAnimationLock.o +./temp\obj\StackToStackAniMove.o +./temp\obj\DealAnimation.o +./temp\obj\FlipAnimation.o +./temp\obj\StackToStackFlipAni.o +./temp\obj\GameBoard.o +./temp\obj\CardMoveRecord.o +./temp\obj\About.o +./temp\obj\Help.o +./temp\obj\GameMgr.o +./temp\obj\SpiderBoard.o +./temp\obj\SpiderHomeStack.o +./temp\obj\SpiderStack.o +./temp\obj\KlondikeStack.o +./temp\obj\KlondikeFlipStack.o +./temp\obj\KlondikeHomeStack.o +./temp\obj\KlondikeBoard.o +./temp\obj\FreeCellBoard.o +./temp\obj\FreeCellDeck.o +./temp\obj\FreeCellStack.o +./temp\obj\FreeCellHome.o +./temp\obj\FreeCellFree.o +./temp\obj\Spider3DeckBoard.o +./temp\obj\SpideretteBoard.o +./temp\obj\YukonBoard.o +./temp\obj\moc_QSoloCardsPlugin.o +./temp\obj\moc_mainwindow.o +./temp\obj\moc_CardStack.o +./temp\obj\moc_DragCardStack.o +./temp\obj\moc_VCardStack.o +./temp\obj\moc_CardAnimationLock.o +./temp\obj\moc_StackToStackAniMove.o +./temp\obj\moc_DealAnimation.o +./temp\obj\moc_FlipAnimation.o +./temp\obj\moc_StackToStackFlipAni.o +./temp\obj\moc_GameBoard.o +./temp\obj\moc_About.o +./temp\obj\moc_Help.o +./temp\obj\moc_SpiderBoard.o +./temp\obj\moc_SpiderStack.o +./temp\obj\moc_KlondikeStack.o +./temp\obj\moc_KlondikeFlipStack.o +./temp\obj\moc_KlondikeHomeStack.o +./temp\obj\moc_KlondikeBoard.o +./temp\obj\moc_FreeCellBoard.o +./temp\obj\moc_FreeCellDeck.o +./temp\obj\moc_FreeCellStack.o +./temp\obj\moc_FreeCellHome.o +./temp\obj\moc_FreeCellFree.o +./temp\obj\moc_Spider3DeckBoard.o +./temp\obj\moc_SpideretteBoard.o +./temp\obj\moc_YukonBoard.o +./temp\obj\qrc_QSoloCards.o +); diff --git a/plugins/qsolocards_plugin/object_script.qsolocards_plugin.Release b/plugins/qsolocards_plugin/object_script.qsolocards_plugin.Release new file mode 100644 index 000000000..cbdb74bc8 --- /dev/null +++ b/plugins/qsolocards_plugin/object_script.qsolocards_plugin.Release @@ -0,0 +1,64 @@ +INPUT( +./temp\obj\QSoloCardsPlugin.o +./temp\obj\main.o +./temp\obj\mainwindow.o +./temp\obj\PlayingCard.o +./temp\obj\CardDeck.o +./temp\obj\CardPixmaps.o +./temp\obj\CardStack.o +./temp\obj\DragCardStack.o +./temp\obj\VCardStack.o +./temp\obj\CardAnimationLock.o +./temp\obj\StackToStackAniMove.o +./temp\obj\DealAnimation.o +./temp\obj\FlipAnimation.o +./temp\obj\StackToStackFlipAni.o +./temp\obj\GameBoard.o +./temp\obj\CardMoveRecord.o +./temp\obj\About.o +./temp\obj\Help.o +./temp\obj\GameMgr.o +./temp\obj\SpiderBoard.o +./temp\obj\SpiderHomeStack.o +./temp\obj\SpiderStack.o +./temp\obj\KlondikeStack.o +./temp\obj\KlondikeFlipStack.o +./temp\obj\KlondikeHomeStack.o +./temp\obj\KlondikeBoard.o +./temp\obj\FreeCellBoard.o +./temp\obj\FreeCellDeck.o +./temp\obj\FreeCellStack.o +./temp\obj\FreeCellHome.o +./temp\obj\FreeCellFree.o +./temp\obj\Spider3DeckBoard.o +./temp\obj\SpideretteBoard.o +./temp\obj\YukonBoard.o +./temp\obj\moc_QSoloCardsPlugin.o +./temp\obj\moc_mainwindow.o +./temp\obj\moc_CardStack.o +./temp\obj\moc_DragCardStack.o +./temp\obj\moc_VCardStack.o +./temp\obj\moc_CardAnimationLock.o +./temp\obj\moc_StackToStackAniMove.o +./temp\obj\moc_DealAnimation.o +./temp\obj\moc_FlipAnimation.o +./temp\obj\moc_StackToStackFlipAni.o +./temp\obj\moc_GameBoard.o +./temp\obj\moc_About.o +./temp\obj\moc_Help.o +./temp\obj\moc_SpiderBoard.o +./temp\obj\moc_SpiderStack.o +./temp\obj\moc_KlondikeStack.o +./temp\obj\moc_KlondikeFlipStack.o +./temp\obj\moc_KlondikeHomeStack.o +./temp\obj\moc_KlondikeBoard.o +./temp\obj\moc_FreeCellBoard.o +./temp\obj\moc_FreeCellDeck.o +./temp\obj\moc_FreeCellStack.o +./temp\obj\moc_FreeCellHome.o +./temp\obj\moc_FreeCellFree.o +./temp\obj\moc_Spider3DeckBoard.o +./temp\obj\moc_SpideretteBoard.o +./temp\obj\moc_YukonBoard.o +./temp\obj\qrc_QSoloCards.o +); diff --git a/plugins/qsolocards_plugin/qsolocards_plugin.pro b/plugins/qsolocards_plugin/qsolocards_plugin.pro new file mode 100644 index 000000000..86393617a --- /dev/null +++ b/plugins/qsolocards_plugin/qsolocards_plugin.pro @@ -0,0 +1,106 @@ +# ------------------------------------------------- +# Project created by QtCreator 2009-03-07T14:27:09 +# ------------------------------------------------- +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin release + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(qsolocards_plugin) + +HEADERS += ../PluginInterface.h \ + QSoloCardsPlugin.h +SOURCES += QSoloCardsPlugin.cpp + +#=============================================================================== +SOURCES += main.cpp \ + mainwindow.cpp \ + PlayingCard.cpp \ + CardDeck.cpp \ + CardPixmaps.cpp \ + CardStack.cpp \ + DragCardStack.cpp \ + VCardStack.cpp \ + CardAnimationLock.cpp \ + StackToStackAniMove.cpp \ + DealAnimation.cpp \ + FlipAnimation.cpp \ + StackToStackFlipAni.cpp \ + GameBoard.cpp \ + CardMoveRecord.cpp \ + About.cpp \ + Help.cpp \ + GameMgr.cpp \ + SpiderBoard.cpp \ + SpiderHomeStack.cpp \ + SpiderStack.cpp \ + KlondikeStack.cpp \ + KlondikeFlipStack.cpp \ + KlondikeHomeStack.cpp \ + KlondikeBoard.cpp \ + FreeCellBoard.cpp \ + FreeCellDeck.cpp \ + FreeCellStack.cpp \ + FreeCellHome.cpp \ + FreeCellFree.cpp \ + Spider3DeckBoard.cpp \ + SpideretteBoard.cpp \ + YukonBoard.cpp +HEADERS += mainwindow.h \ + PlayingCard.h \ + CardDeck.h \ + CardPixmaps.h \ + CardStack.h \ + DragCardStack.h \ + VCardStack.h \ + CardAnimationLock.h \ + StackToStackAniMove.h \ + DealAnimation.h \ + FlipAnimation.h \ + StackToStackFlipAni.h \ + GameBoard.h \ + CardMoveRecord.h \ + About.h \ + Help.h \ + GameMgr.h \ + SpiderBoard.h \ + SpiderHomeStack.h \ + SpiderStack.h \ + KlondikeStack.h \ + KlondikeFlipStack.h \ + KlondikeHomeStack.h \ + KlondikeBoard.h \ + FreeCellBoard.h \ + FreeCellDeck.h \ + FreeCellStack.h \ + FreeCellHome.h \ + FreeCellFree.h \ + Spider3DeckBoard.h \ + SpideretteBoard.h \ + YukonBoard.h + +QT += svg +RESOURCES = QSoloCards.qrc + +mac:QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.4u.sdk +mac:CONFIG+=x86 ppc + +VER_MAJ = 0 +VER_MIN = 99 +VER_PAT = 1 +QMAKE_CXXFLAGS_DEBUG = -DVER_MAJ=$$VER_MAJ \ + -DVER_MIN=$$VER_MIN \ + -DVER_PAT=$$VER_PAT +QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CXXFLAGS_DEBUG +mac:ICON = QSoloCards.icns diff --git a/plugins/smplayer_plugin/SMPlayerPlugin.cpp b/plugins/smplayer_plugin/SMPlayerPlugin.cpp new file mode 100644 index 000000000..9339e6a40 --- /dev/null +++ b/plugins/smplayer_plugin/SMPlayerPlugin.cpp @@ -0,0 +1,49 @@ +//#include +//#include +#include + +#include "SMPlayerPlugin.h" +#include "smplayer.h" + +SMPlayerPluginWidget::SMPlayerPluginWidget(QWidget* parent, + Qt::WindowFlags flags ) + :QFrame(parent) +{ + player = new SMPlayer(); + + lay = new QVBoxLayout(this); + lay->addWidget( player->gui() ); +} + +SMPlayerPluginWidget::~SMPlayerPluginWidget() +{ + delete player; +} + + +//============================================================================== + +QString +SMPlayerPlugin::pluginDescription() const +{ + QString res; + res = "A SMPlayer plugin" ; + + return res; +} + +QString +SMPlayerPlugin::pluginName() const +{ + return "SMPlayer" ; +} + +QWidget* +SMPlayerPlugin::pluginWidget(QWidget * parent ) +{ + SMPlayerPluginWidget* wd = new SMPlayerPluginWidget(parent); + return wd ; +} + + +Q_EXPORT_PLUGIN2(smplayer_plugin, SMPlayerPlugin) diff --git a/plugins/smplayer_plugin/SMPlayerPlugin.h b/plugins/smplayer_plugin/SMPlayerPlugin.h new file mode 100644 index 000000000..fbb9e278f --- /dev/null +++ b/plugins/smplayer_plugin/SMPlayerPlugin.h @@ -0,0 +1,44 @@ +#ifndef _HWA_PLUGIN_H_ +#define _HWA_PLUGIN_H_ + +#include + +#include +#include +#include +class QVBoxLayout; + +#include + +#include + +class SMPlayer; + +class SMPlayerPluginWidget: public QFrame +{ + Q_OBJECT + + public: + SMPlayerPluginWidget(QWidget* parent, Qt::WindowFlags flags = 0 ); + ~SMPlayerPluginWidget(); + + protected: + SMPlayer* player; + QVBoxLayout* lay; +}; + +class SMPlayerPlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/smplayer_plugin/about.cpp b/plugins/smplayer_plugin/about.cpp new file mode 100644 index 000000000..2907253d2 --- /dev/null +++ b/plugins/smplayer_plugin/about.cpp @@ -0,0 +1,271 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "about.h" +#include "images.h" +#include "version.h" +#include "global.h" +#include "preferences.h" +#include "paths.h" +#include "mplayerversion.h" + +#include + +//#define TRANS_ORIG +#define TRANS_LIST +//#define TRANS_TABLE + +using namespace Global; + +About::About(QWidget * parent, Qt::WindowFlags f) + : QDialog(parent, f) +{ + setupUi(this); + setWindowIcon( Images::icon("logo", 64) ); + + logo->setPixmap( Images::icon("logo", 64) ); + contrib_icon->setPixmap( Images::icon("contributors" ) ); + translators_icon->setPixmap( Images::icon("translators" ) ); + license_icon->setPixmap( Images::icon("license" ) ); + + QString mplayer_version; + if (pref->mplayer_detected_version > 0) { + mplayer_version = tr("Using MPlayer %1").arg(MplayerVersion::toString(pref->mplayer_detected_version)) + "

"; + } + + info->setText( + "SMPlayer © 2006-2008 Ricardo Villalba <rvm@escomposlinux.org>

" + "" + tr("Version: %1").arg(smplayerVersion()) + "" + +#if PORTABLE_APP + " (" + tr("Portable Edition") + ")" + +#endif + "
" + + tr("Using Qt %1 (compiled with Qt %2)").arg(qVersion()).arg(QT_VERSION_STR) + "

" + + mplayer_version + + tr("Visit our web for updates:") +"
"+ + link("http://smplayer.berlios.de") + "
" + + link("http://smplayer.sf.net") + + "

" + + tr("Get help in our forum:") +"
" + link("http://smplayer.berlios.de/forums") + + "

" + + tr("You can support SMPlayer by making a donation.") +" "+ + link("https://sourceforge.net/donate/index.php?group_id=185512", tr("More info")) + //link("http://www.qt-apps.org/content/donate.php?content=61041", tr("More info")) + ); + + + QString license_file = Paths::doc("gpl.html", pref->language); + if (QFile::exists(license_file)) { + QFont fixed_font; + fixed_font.setStyleHint(QFont::TypeWriter); + fixed_font.setFamily("Courier"); + license->setFont(fixed_font); + + QFile f(license_file); + if (f.open(QIODevice::ReadOnly)) { + license->setText(QString::fromUtf8(f.readAll().constData())); + } + f.close(); + } else { + license->setText( + "" + + tr("This program is free software; you can redistribute it and/or modify " + "it under the terms of the GNU General Public License as published by " + "the Free Software Foundation; either version 2 of the License, or " + "(at your option) any later version.") + ""); + } + + translators->setHtml( getTranslators() ); + + contributions->setText( + tr("SMPlayer logo by %1").arg("Charles Barcza <kbarcza@blackpanther.hu>") + "

" + + tr("The following people have contributed with patches " + "(see the changelog for details):") + + "
" +
+        QString(
+		"corentin1234 \n"
+		"Florin Braghis \n"
+		"Francesco Cosoleto \n"
+		"Glaydus \n"
+		"Kamil Dziobek \n"
+		"LoRd_MuldeR (http://forum.doom9.org/member.php?u=78667)\n"
+		"Matthias Petri \n"
+		"profoX \n"
+		"redxii \n"
+		"Sikon \n"
+		"Simon \n"
+		"Stanislav Maslovski \n"
+		"Tanguy Krotoff \n"
+		).replace("<", "<").replace(">", ">") + 
+		"
" + + tr("If there's any omission, please report.") + ); + + // Copy the background color ("window") of the tab widget to the "base" color of the qtextbrowsers + // Problem, it doesn't work with some styles, so first we change the "window" color of the tab widgets. + info_tab->setAutoFillBackground(true); + contributions_tab->setAutoFillBackground(true); + translations_tab->setAutoFillBackground(true); + license_tab->setAutoFillBackground(true); + + QPalette pal = info_tab->palette(); + pal.setColor(QPalette::Window, palette().color(QPalette::Window) ); + + info_tab->setPalette(pal); + contributions_tab->setPalette(pal); + translations_tab->setPalette(pal); + license_tab->setPalette(pal); + + QPalette p = info->palette(); + //p.setBrush(QPalette::Base, info_tab->palette().window()); + p.setColor(QPalette::Base, info_tab->palette().color(QPalette::Window)); + + info->setPalette(p); + contributions->setPalette(p); + translators->setPalette(p); + //license->setPalette(p); + + adjustSize(); +} + +About::~About() { +} + +QString About::getTranslators() { + return QString( + tr("The following people have contributed with translations:") + +#ifndef TRANS_TABLE + "
    " + +#else + "" + +#endif + trad(tr("German"), "Henrikx ") + + trad(tr("Slovak"), "Sweto ") + + trad(tr("Italian"), "Giancarlo Scola ") + + trad(tr("French"), QStringList() + << "Olivier g <1got@caramail.com>" + << "Temet " + << "Erwann MEST ") + + trad(tr("Simplified-Chinese"), "Tim Green ") + + trad(tr("Russian"), QString::fromUtf8("Белый Владимир "))+ + trad(tr("Hungarian"), QStringList() + << "Charles Barcza " + << "CyberDragon ") + + trad(tr("Polish"), QStringList() + << "qla " + << "Jarek " ) + + trad(tr("Japanese"), "Nardog ") + + trad(tr("Dutch"), QStringList() + << "profoX " + << "BalaamsMiracle" + << "Kristof Bal ") + + trad(tr("Ukrainian"), QStringList() + << "Motsyo Gennadi " + << "Oleksandr Kovalenko " ) + + trad(tr("Portuguese - Brazil"), "Ventura ") + + trad(tr("Georgian"), "George Machitidze ") + + trad(tr("Czech"), QStringList() + << QString::fromUtf8("Martin Dvořák ") + << QString::fromUtf8("Jaromír Smrček ") ) + + trad(tr("Bulgarian"), "") + + trad(tr("Turkish"), "alper er ") + + trad(tr("Swedish"), "Leif Larsson ") + + trad(tr("Serbian"), "Kunalagon Umuhanik ") + + trad(tr("Traditional Chinese"), "Hoopoe ") + + trad(tr("Romanian"), "DoruH ") + + trad(tr("Portuguese - Portugal"), QStringList() + << "Waxman " + << QString::fromUtf8("Sérgio Marques ") ) + + trad(tr("Greek"), "my80s ") + + trad(tr("Finnish"), "peeaivo ") + + trad(tr("Korean"), "Heesu Yoon ") + + trad(tr("Macedonian"), "Marko Doda ") + + trad(tr("Basque"), "Piarres Beobide ") + + trad(tr("Catalan"), QString::fromUtf8("Roger Calvó ")) + + trad(tr("Slovenian"), "Janez Troha ") + + trad(tr("Arabic"), "Muhammad Nour Hajj Omar ") + + trad(tr("Kurdish"), "Si_murg56 ") + + trad(tr("Galician"), "Miguel Branco ") + +#ifndef TRANS_TABLE + ""); +#else + "
    "); +#endif +} + +QString About::trad(const QString & lang, const QString & author) { + return trad(lang, QStringList() << author); +} + +QString About::trad(const QString & lang, const QStringList & authors) { +#ifdef TRANS_ORIG + QString s; + + switch (authors.count()) { + case 2: s = tr("%1 and %2"); break; + case 3: s = tr("%1, %2 and %3"); break; + case 4: s = tr("%1, %2, %3 and %4"); break; + case 5: s = tr("%1, %2, %3, %4 and %5"); break; + default: s = "%1"; + } + + for (int n = 0; n < authors.count(); n++) { + QString author = authors[n]; + s = s.arg(author.replace("<", "<").replace(">", ">")); + } + + return "
  • "+ tr("%1: %2").arg(lang).arg(s) + "
  • "; +#endif + +#ifdef TRANS_LIST + QString s = "
      ";; + for (int n = 0; n < authors.count(); n++) { + QString author = authors[n]; + s += "
    • "+ author.replace("<", "<").replace(">", ">") + "
    • "; + } + s+= "
    "; + + return "
  • "+ tr("%1: %2").arg(lang).arg(s) + "
  • "; +#endif + +#ifdef TRANS_TABLE + QString s; + for (int n = 0; n < authors.count(); n++) { + QString author = authors[n]; + s += author.replace("<", "<").replace(">", ">"); + if (n < (authors.count()-1)) s += "
    "; + } + + return QString("%1%2").arg(lang).arg(s); +#endif +} + +QString About::link(const QString & url, QString name) { + if (name.isEmpty()) name = url; + return QString("" + name +""); +} + +QString About::contr(const QString & author, const QString & thing) { + return "
  • "+ tr("%1 (%2)").arg(author).arg(thing) +"
  • "; +} + +QSize About::sizeHint () const { + return QSize(518, 326); +} + +#include "moc_about.cpp" diff --git a/plugins/smplayer_plugin/about.h b/plugins/smplayer_plugin/about.h new file mode 100644 index 000000000..45a07cce7 --- /dev/null +++ b/plugins/smplayer_plugin/about.h @@ -0,0 +1,56 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _ABOUT_H_ +#define _ABOUT_H_ + +#include "ui_about.h" + +#include + +//! Shows the about smplayer dialog + +/*! + Displays copyright info, license, translators... +*/ + +class About : public QDialog, public Ui::About +{ + Q_OBJECT + +public: + About( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~About(); + + virtual QSize sizeHint () const; + +protected: + QString getTranslators(); + + //! Return a formatted string with the translator and language + QString trad(const QString & lang, const QString & author); + + QString trad(const QString & lang, const QStringList & authors); + + QString link(const QString & url, QString name = ""); + + //! Return a formatted string with the contributor and what he did + QString contr(const QString & author, const QString & thing); +}; + +#endif diff --git a/plugins/smplayer_plugin/about.ui b/plugins/smplayer_plugin/about.ui new file mode 100644 index 000000000..9f6f3a420 --- /dev/null +++ b/plugins/smplayer_plugin/about.ui @@ -0,0 +1,295 @@ + + About + + + + 0 + 0 + 518 + 326 + + + + About SMPlayer + + + + 9 + + + 6 + + + + + QTabWidget::Rounded + + + 0 + + + + &Info + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + icon + + + + + + + Qt::Vertical + + + + 20 + 111 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + + + + + + &Contributions + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + icon + + + + + + + Qt::Vertical + + + + 20 + 111 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + + + + + + &Translators + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + icon + + + + + + + Qt::Vertical + + + + 20 + 111 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + + + + + + &License + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + icon + + + + + + + Qt::Vertical + + + + 20 + 111 + + + + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + tabWidget + info + buttonBox + contributions + translators + license + + + + + buttonBox + accepted() + About + accept() + + + 248 + 254 + + + 157 + 274 + + + + + diff --git a/plugins/smplayer_plugin/actionseditor.cpp b/plugins/smplayer_plugin/actionseditor.cpp new file mode 100644 index 000000000..664870b65 --- /dev/null +++ b/plugins/smplayer_plugin/actionseditor.cpp @@ -0,0 +1,625 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This is based on qq14-actioneditor-code.zip from Qt */ + + +#include "actionseditor.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "images.h" +#include "filedialog.h" +#include "paths.h" + +#include "shortcutgetter.h" + + +/* +#include +#include + +class MyDelegate : public QItemDelegate +{ +public: + MyDelegate(QObject *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + virtual void setModelData(QWidget * editor, QAbstractItemModel * model, + const QModelIndex & index ) const; +}; + +MyDelegate::MyDelegate(QObject *parent) : QItemDelegate(parent) +{ +} + +static QString old_accel_text; + +QWidget * MyDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem & option, + const QModelIndex & index) const +{ + qDebug("MyDelegate::createEditor"); + + old_accel_text = index.model()->data(index, Qt::DisplayRole).toString(); + //qDebug( "text: %s", old_accel_text.toUtf8().data()); + + return QItemDelegate::createEditor(parent, option, index); +} + +void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + QLineEdit *line_edit = static_cast(editor); + + QString accelText = QKeySequence(line_edit->text()).toString(); + if (accelText.isEmpty() && !line_edit->text().isEmpty()) { + model->setData(index, old_accel_text); + } + else { + model->setData(index, accelText); + } +} +*/ + + +#if USE_MULTIPLE_SHORTCUTS +QString ActionsEditor::shortcutsToString(QList shortcuts_list) { + QString accelText = ""; + + for (int n=0; n < shortcuts_list.count(); n++) { + accelText += shortcuts_list[n].toString(QKeySequence::PortableText); + if (n < (shortcuts_list.count()-1)) accelText += ", "; + } + + return accelText; +} + +QList ActionsEditor::stringToShortcuts(QString shortcuts) { + QList shortcuts_list; + + QStringList l = shortcuts.split(','); + + for (int n=0; n < l.count(); n++) { + //qDebug("%s", l[n].toUtf8().data()); +#if QT_VERSION >= 0x040300 + // Qt 4.3 and 4.4 (at least on linux) seems to have a problem when using Traditional Chinese + // QKeysequence deletes the arrow key names from the shortcut + // so this is a work-around. + QString s = l[n].simplified(); +#else + QString s = QKeySequence( l[n].simplified() ); +#endif + + //Work-around for Simplified-Chinese + s.replace( QString::fromUtf8("左"), "Left"); + s.replace( QString::fromUtf8("下"), "Down"); + s.replace( QString::fromUtf8("右"), "Right"); + s.replace( QString::fromUtf8("上"), "Up"); + + shortcuts_list.append( s ); + //qDebug("ActionsEditor::stringToShortcuts: shortcut %d: '%s'", n, s.toUtf8().data()); + } + + return shortcuts_list; +} +#endif + + +#define COL_CONFLICTS 0 +#define COL_SHORTCUT 1 +#define COL_DESC 2 +#define COL_NAME 3 + +ActionsEditor::ActionsEditor(QWidget * parent, Qt::WindowFlags f) + : QWidget(parent, f) +{ + latest_dir = Paths::shortcutsPath(); + + actionsTable = new QTableWidget(0, COL_NAME +1, this); + actionsTable->setSelectionMode( QAbstractItemView::SingleSelection ); + actionsTable->verticalHeader()->hide(); + + actionsTable->horizontalHeader()->setResizeMode(COL_DESC, QHeaderView::Stretch); + actionsTable->horizontalHeader()->setResizeMode(COL_NAME, QHeaderView::Stretch); + + actionsTable->setAlternatingRowColors(true); +#if USE_SHORTCUTGETTER + actionsTable->setSelectionBehavior(QAbstractItemView::SelectRows); + actionsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); +#endif + //actionsTable->setItemDelegateForColumn( COL_SHORTCUT, new MyDelegate(actionsTable) ); + +#if !USE_SHORTCUTGETTER + connect(actionsTable, SIGNAL(currentItemChanged(QTableWidgetItem *,QTableWidgetItem *)), + this, SLOT(recordAction(QTableWidgetItem *)) ); + connect(actionsTable, SIGNAL(itemChanged(QTableWidgetItem *)), + this, SLOT(validateAction(QTableWidgetItem *)) ); +#else + connect(actionsTable, SIGNAL(itemActivated(QTableWidgetItem *)), + this, SLOT(editShortcut()) ); +#endif + + saveButton = new QPushButton(this); + loadButton = new QPushButton(this); + + connect(saveButton, SIGNAL(clicked()), this, SLOT(saveActionsTable())); + connect(loadButton, SIGNAL(clicked()), this, SLOT(loadActionsTable())); + +#if USE_SHORTCUTGETTER + editButton = new QPushButton(this); + connect( editButton, SIGNAL(clicked()), this, SLOT(editShortcut()) ); +#endif + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->setSpacing(8); +#if USE_SHORTCUTGETTER + buttonLayout->addWidget(editButton); +#endif + buttonLayout->addStretch(1); + buttonLayout->addWidget(loadButton); + buttonLayout->addWidget(saveButton); + + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->setMargin(8); + mainLayout->setSpacing(8); + mainLayout->addWidget(actionsTable); + mainLayout->addLayout(buttonLayout); + + retranslateStrings(); +} + +ActionsEditor::~ActionsEditor() { +} + +void ActionsEditor::retranslateStrings() { + actionsTable->setHorizontalHeaderLabels( QStringList() << "" << + tr("Shortcut") << tr("Description") << tr("Name") ); + + saveButton->setText(tr("&Save")); + saveButton->setIcon(Images::icon("save")); + + loadButton->setText(tr("&Load")); + loadButton->setIcon(Images::icon("open")); + +#if USE_SHORTCUTGETTER + editButton->setText(tr("&Change shortcut...")); +#endif + + //updateView(); // The actions are translated later, so it's useless +} + +bool ActionsEditor::isEmpty() { + return actionsList.isEmpty(); +} + +void ActionsEditor::clear() { + actionsList.clear(); +} + +void ActionsEditor::addActions(QWidget *widget) { + QAction *action; + + QList actions = widget->findChildren(); + for (int n=0; n < actions.count(); n++) { + action = static_cast (actions[n]); + if (!action->objectName().isEmpty() && !action->inherits("QWidgetAction")) + actionsList.append(action); + } + + updateView(); +} + +void ActionsEditor::updateView() { + actionsTable->setRowCount( actionsList.count() ); + + QAction *action; + QString accelText; + +#if !USE_SHORTCUTGETTER + dont_validate = true; +#endif + //actionsTable->setSortingEnabled(false); + + for (int n=0; n < actionsList.count(); n++) { + action = static_cast (actionsList[n]); + +#if USE_MULTIPLE_SHORTCUTS + accelText = shortcutsToString( action->shortcuts() ); +#else + accelText = action->shortcut().toString(); +#endif + + // Conflict column + QTableWidgetItem * i_conf = new QTableWidgetItem(); + + // Name column + QTableWidgetItem * i_name = new QTableWidgetItem(action->objectName()); + + // Desc column + QTableWidgetItem * i_desc = new QTableWidgetItem(action->text().replace("&","")); + i_desc->setIcon( action->icon() ); + + // Shortcut column + QTableWidgetItem * i_shortcut = new QTableWidgetItem(accelText); + + // Set flags +#if !USE_SHORTCUTGETTER + i_conf->setFlags(Qt::ItemIsEnabled); + i_name->setFlags(Qt::ItemIsEnabled); + i_desc->setFlags(Qt::ItemIsEnabled); +#else + i_conf->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); + i_name->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); + i_desc->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); + i_shortcut->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); +#endif + + // Add items to table + actionsTable->setItem(n, COL_CONFLICTS, i_conf ); + actionsTable->setItem(n, COL_NAME, i_name ); + actionsTable->setItem(n, COL_DESC, i_desc ); + actionsTable->setItem(n, COL_SHORTCUT, i_shortcut ); + + } + hasConflicts(); // Check for conflicts + + actionsTable->resizeColumnsToContents(); + actionsTable->setCurrentCell(0, COL_SHORTCUT); + +#if !USE_SHORTCUTGETTER + dont_validate = false; +#endif + //actionsTable->setSortingEnabled(true); +} + + +void ActionsEditor::applyChanges() { + qDebug("ActionsEditor::applyChanges"); + + for (int row = 0; row < (int)actionsList.size(); ++row) { + QAction *action = actionsList[row]; + QTableWidgetItem *i = actionsTable->item(row, COL_SHORTCUT); + +#if USE_MULTIPLE_SHORTCUTS + action->setShortcuts( stringToShortcuts(i->text()) ); +#else + action->setShortcut( QKeySequence(i->text()) ); +#endif + } +} + +#if !USE_SHORTCUTGETTER +void ActionsEditor::recordAction(QTableWidgetItem * i) { + //qDebug("ActionsEditor::recordAction"); + + //QTableWidgetItem * i = actionsTable->currentItem(); + if (i->column() == COL_SHORTCUT) { + //qDebug("ActionsEditor::recordAction: %d %d %s", i->row(), i->column(), i->text().toUtf8().data()); + oldAccelText = i->text(); + } +} + +void ActionsEditor::validateAction(QTableWidgetItem * i) { + //qDebug("ActionsEditor::validateAction"); + if (dont_validate) return; + + if (i->column() == COL_SHORTCUT) { + QString accelText = QKeySequence(i->text()).toString(); + + if (accelText.isEmpty() && !i->text().isEmpty()) { + /* + QAction * action = static_cast (actionsList[i->row()]); + QString oldAccelText= action->accel().toString(); + */ + i->setText(oldAccelText); + } + else { + i->setText(accelText); + } + + if (hasConflicts()) qApp->beep(); + } +} + +#else + +void ActionsEditor::editShortcut() { + QTableWidgetItem * i = actionsTable->item( actionsTable->currentRow(), COL_SHORTCUT ); + if (i) { + ShortcutGetter d(this); + QString result = d.exec( i->text() ); + + if (!result.isNull()) { + QString accelText = QKeySequence(result).toString(QKeySequence::PortableText); + i->setText(accelText); + if (hasConflicts()) qApp->beep(); + } + } +} +#endif + +int ActionsEditor::findActionName(const QString & name) { + for (int row=0; row < actionsTable->rowCount(); row++) { + if (actionsTable->item(row, COL_NAME)->text() == name) return row; + } + return -1; +} + +int ActionsEditor::findActionAccel(const QString & accel, int ignoreRow) { + for (int row=0; row < actionsTable->rowCount(); row++) { + QTableWidgetItem * i = actionsTable->item(row, COL_SHORTCUT); + if ( (i) && (i->text() == accel) ) { + if (ignoreRow == -1) return row; + else + if (ignoreRow != row) return row; + } + } + return -1; +} + +bool ActionsEditor::hasConflicts() { + int found; + bool conflict = false; + + QString accelText; + QTableWidgetItem *i; + + for (int n=0; n < actionsTable->rowCount(); n++) { + //actionsTable->setText( n, COL_CONFLICTS, " "); + i = actionsTable->item( n, COL_CONFLICTS ); + if (i) i->setIcon( QPixmap() ); + + i = actionsTable->item(n, COL_SHORTCUT ); + if (i) { + accelText = i->text(); + if (!accelText.isEmpty()) { + found = findActionAccel( accelText, n ); + if ( (found != -1) && (found != n) ) { + conflict = true; + //actionsTable->setText( n, COL_CONFLICTS, "!"); + actionsTable->item( n, COL_CONFLICTS )->setIcon( Images::icon("conflict") ); + } + } + } + } + //if (conflict) qApp->beep(); + return conflict; +} + + +void ActionsEditor::saveActionsTable() { + QString s = MyFileDialog::getSaveFileName( + this, tr("Choose a filename"), + latest_dir, + tr("Key files") +" (*.keys)" ); + + if (!s.isEmpty()) { + // If filename has no extension, add it + if (QFileInfo(s).suffix().isEmpty()) { + s = s + ".keys"; + } + if (QFileInfo(s).exists()) { + int res = QMessageBox::question( this, + tr("Confirm overwrite?"), + tr("The file %1 already exists.\n" + "Do you want to overwrite?").arg(s), + QMessageBox::Yes, + QMessageBox::No, + Qt::NoButton); + if (res == QMessageBox::No ) { + return; + } + } + latest_dir = QFileInfo(s).absolutePath(); + bool r = saveActionsTable(s); + if (!r) { + QMessageBox::warning(this, tr("Error"), + tr("The file couldn't be saved"), + QMessageBox::Ok, Qt::NoButton); + } + } +} + +bool ActionsEditor::saveActionsTable(const QString & filename) { + qDebug("ActionsEditor::saveActions: '%s'", filename.toUtf8().data()); + + QFile f( filename ); + if ( f.open( QIODevice::WriteOnly ) ) { + QTextStream stream( &f ); + stream.setCodec("UTF-8"); + + for (int row=0; row < actionsTable->rowCount(); row++) { + stream << actionsTable->item(row, COL_NAME)->text() << "\t" + << actionsTable->item(row, COL_SHORTCUT)->text() << "\n"; + } + f.close(); + return true; + } + return false; +} + +void ActionsEditor::loadActionsTable() { + QString s = MyFileDialog::getOpenFileName( + this, tr("Choose a file"), + latest_dir, tr("Key files") +" (*.keys)" ); + + if (!s.isEmpty()) { + latest_dir = QFileInfo(s).absolutePath(); + bool r = loadActionsTable(s); + if (!r) { + QMessageBox::warning(this, tr("Error"), + tr("The file couldn't be loaded"), + QMessageBox::Ok, Qt::NoButton); + } + } +} + +bool ActionsEditor::loadActionsTable(const QString & filename) { + qDebug("ActionsEditor::loadActions: '%s'", filename.toUtf8().data()); + + QRegExp rx("^(.*)\\t(.*)"); + int row; + + QFile f( filename ); + if ( f.open( QIODevice::ReadOnly ) ) { + +#if !USE_SHORTCUTGETTER + dont_validate = true; +#endif + + QTextStream stream( &f ); + stream.setCodec("UTF-8"); + + QString line; + while ( !stream.atEnd() ) { + line = stream.readLine(); + qDebug("line: '%s'", line.toUtf8().data()); + if (rx.indexIn(line) > -1) { + QString name = rx.cap(1); + QString accelText = rx.cap(2); + qDebug(" name: '%s' accel: '%s'", name.toUtf8().data(), accelText.toUtf8().data()); + row = findActionName(name); + if (row > -1) { + qDebug("Action found!"); + actionsTable->item(row, COL_SHORTCUT)->setText(accelText); + } + } else { + qDebug(" wrong line"); + } + } + f.close(); + hasConflicts(); // Check for conflicts + +#if !USE_SHORTCUTGETTER + dont_validate = false; +#endif + + return true; + } else { + return false; + } +} + + +// Static functions + +void ActionsEditor::saveToConfig(QObject *o, QSettings *set) { + qDebug("ActionsEditor::saveToConfig"); + + set->beginGroup("actions"); + + QAction *action; + QList actions = o->findChildren(); + for (int n=0; n < actions.count(); n++) { + action = static_cast (actions[n]); + if (!action->objectName().isEmpty() && !action->inherits("QWidgetAction")) { +#if USE_MULTIPLE_SHORTCUTS + QString accelText = shortcutsToString(action->shortcuts()); +#else + QString accelText = action->shortcut().toString(); +#endif + set->setValue(action->objectName(), accelText); + } + } + + set->endGroup(); +} + + +void ActionsEditor::loadFromConfig(QObject *o, QSettings *set) { + qDebug("ActionsEditor::loadFromConfig"); + + set->beginGroup("actions"); + + QAction *action; + QString accelText; + + QList actions = o->findChildren(); + for (int n=0; n < actions.count(); n++) { + action = static_cast (actions[n]); + if (!action->objectName().isEmpty() && !action->inherits("QWidgetAction")) { +#if USE_MULTIPLE_SHORTCUTS + QString current = shortcutsToString(action->shortcuts()); + accelText = set->value(action->objectName(), current).toString(); + action->setShortcuts( stringToShortcuts( accelText ) ); +#else + accelText = set->value(action->objectName(), action->shortcut().toString()).toString(); + action->setShortcut(QKeySequence(accelText)); +#endif + } + } + + set->endGroup(); +} + +QAction * ActionsEditor::findAction(QObject *o, const QString & name) { + QAction *action; + + QList actions = o->findChildren(); + for (int n=0; n < actions.count(); n++) { + action = static_cast (actions[n]); + if (name == action->objectName()) return action; + } + + return 0; +} + +QStringList ActionsEditor::actionsNames(QObject *o) { + QStringList l; + + QAction *action; + + QList actions = o->findChildren(); + for (int n=0; n < actions.count(); n++) { + action = static_cast (actions[n]); + //qDebug("action name: '%s'", action->objectName().toUtf8().data()); + //qDebug("action name: '%s'", action->text().toUtf8().data()); + if (!action->objectName().isEmpty()) + l.append( action->objectName() ); + } + + return l; +} + + +// Language change stuff +void ActionsEditor::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QWidget::changeEvent(e); + } +} + +#include "moc_actionseditor.cpp" diff --git a/plugins/smplayer_plugin/actionseditor.h b/plugins/smplayer_plugin/actionseditor.h new file mode 100644 index 000000000..b3c45552e --- /dev/null +++ b/plugins/smplayer_plugin/actionseditor.h @@ -0,0 +1,104 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This is based on qq14-actioneditor-code.zip from Qt */ + +#ifndef _ACTIONSEDITOR_H_ +#define _ACTIONSEDITOR_H_ + +#include +#include +#include +#include "guiconfig.h" + +class QTableWidget; +class QTableWidgetItem; +class QAction; +class QSettings; +class QPushButton; + +class ActionsEditor : public QWidget +{ + Q_OBJECT + +public: + ActionsEditor( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~ActionsEditor(); + + // Clear the actionlist + void clear(); + + // There are no actions yet? + bool isEmpty(); + + void addActions(QWidget * widget); + + // Static functions + static QAction * findAction(QObject *o, const QString & name); + static QStringList actionsNames(QObject *o); + + static void saveToConfig(QObject *o, QSettings *set); + static void loadFromConfig(QObject *o, QSettings *set); + +#if USE_MULTIPLE_SHORTCUTS + static QString shortcutsToString(QList shortcuts_list); + static QList stringToShortcuts(QString shortcuts); +#endif + +public slots: + void applyChanges(); + void saveActionsTable(); + bool saveActionsTable(const QString & filename); + void loadActionsTable(); + bool loadActionsTable(const QString & filename); + + void updateView(); + +protected: + virtual void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + + // Find in table, not in actionslist + int findActionName(const QString & name); + int findActionAccel(const QString & accel, int ignoreRow = -1); + bool hasConflicts(); + +protected slots: +#if !USE_SHORTCUTGETTER + void recordAction(QTableWidgetItem*); + void validateAction(QTableWidgetItem*); +#else + void editShortcut(); +#endif + +private: + QTableWidget *actionsTable; + QList actionsList; + QPushButton *saveButton; + QPushButton *loadButton; + QString latest_dir; + +#if USE_SHORTCUTGETTER + QPushButton *editButton; +#else + QString oldAccelText; + bool dont_validate; +#endif +}; + +#endif diff --git a/plugins/smplayer_plugin/assstyles.cpp b/plugins/smplayer_plugin/assstyles.cpp new file mode 100644 index 000000000..7f73c84ab --- /dev/null +++ b/plugins/smplayer_plugin/assstyles.cpp @@ -0,0 +1,118 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "assstyles.h" +#include +#include +#include +#include "colorutils.h" + +AssStyles::AssStyles() { + fontname = "Arial"; + fontsize = 20; + primarycolor = 0xFFFFFF; + backcolor = 0; + bold = false; + italic = false; + halignment = 2; // Centered + valignment = 0; // Bottom + borderstyle = 1; // Outline + outline = 1; + shadow = 2; + marginl = 20; + marginr = 20; + marginv = 8; +} + +void AssStyles::save(QSettings * set) { + qDebug("AssStyles::save"); + + set->setValue("styles/fontname", fontname); + set->setValue("styles/fontsize", fontsize); + set->setValue("styles/primarycolor", primarycolor); + set->setValue("styles/backcolor", backcolor); + set->setValue("styles/bold", bold); + set->setValue("styles/italic", italic); + set->setValue("styles/halignment", halignment); + set->setValue("styles/valignment", valignment); + set->setValue("styles/borderstyle", borderstyle); + set->setValue("styles/outline", outline); + set->setValue("styles/shadow", shadow); + set->setValue("styles/marginl", marginl); + set->setValue("styles/marginr", marginr); + set->setValue("styles/marginv", marginv); +} + +void AssStyles::load(QSettings * set) { + qDebug("AssStyles::load"); + + fontname = set->value("styles/fontname", fontname).toString(); + fontsize = set->value("styles/fontsize", fontsize).toInt(); + primarycolor = set->value("styles/primarycolor", primarycolor).toInt(); + backcolor = set->value("styles/backcolor", backcolor).toInt(); + bold = set->value("styles/bold", bold).toBool(); + italic = set->value("styles/italic", italic).toBool(); + halignment = set->value("styles/halignment", halignment).toInt(); + valignment = set->value("styles/valignment", valignment).toInt(); + borderstyle = set->value("styles/borderstyle", borderstyle).toInt(); + outline = set->value("styles/outline", outline).toInt(); + shadow = set->value("styles/shadow", shadow).toInt(); + marginl = set->value("styles/marginl", marginl).toInt(); + marginr = set->value("styles/marginr", marginr).toInt(); + marginv = set->value("styles/marginv", marginv).toInt(); +} + +bool AssStyles::exportStyles(const QString & filename) { + qDebug("AssStyles::exportStyles: filename: %s", filename.toUtf8().constData()); + + QFile f(filename); + if (f.open(QFile::WriteOnly)) { + QTextStream out(&f); + + int alignment = halignment; + if (valignment == 1) alignment += 3; // Middle + else + if (valignment == 2) alignment += 6; // Top + + out << "[Script Info]" << endl; + out << "ScriptType: v4.00+" << endl; + out << "Collisions: Normal" << endl; + out << endl; + out << "[V4+ Styles]" << endl; + out << "Format: Name, Fontname, Fontsize, PrimaryColour, BackColour, Bold, Italic, Alignment, BorderStyle, Outline, Shadow, MarginL, MarginR, MarginV" << endl; + out << "Style: Default,"; + out << fontname << "," ; + out << fontsize << "," ; + out << "&H" << ColorUtils::colorToAABBGGRR(primarycolor) << "," ; + out << "&H" << ColorUtils::colorToAABBGGRR(backcolor) << "," ; + out << (bold ? -1 : 0) << "," ; + out << (italic ? -1 : 0) << "," ; + out << alignment << "," ; + out << borderstyle << "," ; + out << outline << "," ; + out << shadow << "," ; + out << marginl << "," ; + out << marginr << "," ; + out << marginv; + out << endl; + + f.close(); + return true; + } + return false; +} diff --git a/plugins/smplayer_plugin/assstyles.h b/plugins/smplayer_plugin/assstyles.h new file mode 100644 index 000000000..a5fa9603a --- /dev/null +++ b/plugins/smplayer_plugin/assstyles.h @@ -0,0 +1,52 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _ASSSTYLES_H_ +#define _ASSSTYLES_H_ + +#include + +class QSettings; + +class AssStyles { + +public: + AssStyles(); + + QString fontname; + int fontsize; + unsigned int primarycolor; + unsigned int backcolor; + bool bold; + bool italic; + int halignment; + int valignment; + int borderstyle; + int outline; + int shadow; + int marginl; + int marginr; + int marginv; + + void save(QSettings * set); + void load(QSettings * set); + + bool exportStyles(const QString & filename); +}; + +#endif diff --git a/plugins/smplayer_plugin/audioequalizer.cpp b/plugins/smplayer_plugin/audioequalizer.cpp new file mode 100644 index 000000000..ff291263c --- /dev/null +++ b/plugins/smplayer_plugin/audioequalizer.cpp @@ -0,0 +1,140 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "audioequalizer.h" +#include "eqslider.h" +#include "images.h" +#include "preferences.h" +#include "global.h" +#include +#include +#include + +using namespace Global; + +AudioEqualizer::AudioEqualizer( QWidget* parent, Qt::WindowFlags f) + : QWidget(parent, f) +{ + QBoxLayout *bl = new QHBoxLayout; //(0, 4, 2); + + for (int n = 0; n < 10; n++) { + eq[n] = new EqSlider(this); + eq[n]->setIcon( QPixmap() ); + eq[n]->sliderWidget()->setRange(-120, 120); + bl->addWidget(eq[n]); + } + + reset_button = new QPushButton( "&Reset", this); + connect( reset_button, SIGNAL(clicked()), this, SLOT(reset()) ); + + set_default_button = new QPushButton( "&Set as default values", this ); + connect( set_default_button, SIGNAL(clicked()), this, SLOT(setDefaults()) ); + + apply_button = new QPushButton( "&Apply", this ); + connect( apply_button, SIGNAL(clicked()), this, SLOT(applyButtonClicked()) ); + + QBoxLayout *button_layout = new QHBoxLayout; //(0, 4, 2); + button_layout->addStretch(); + button_layout->addWidget(apply_button); + button_layout->addWidget(reset_button); + button_layout->addWidget(set_default_button); + + QBoxLayout *layout = new QVBoxLayout(this); //, 4, 2); + layout->addLayout(bl); + layout->addLayout(button_layout); + + retranslateStrings(); + + adjustSize(); + //setFixedSize( sizeHint() ); +} + +AudioEqualizer::~AudioEqualizer() { +} + +void AudioEqualizer::retranslateStrings() { + setWindowTitle( tr("Audio Equalizer") ); + setWindowIcon( Images::icon("logo") ); + + eq[0]->setLabel( tr("31.25 Hz") ); + eq[1]->setLabel( tr("62.50 Hz") ); + eq[2]->setLabel( tr("125.0 Hz") ); + eq[3]->setLabel( tr("250.0 Hz") ); + eq[4]->setLabel( tr("500.0 Hz") ); + eq[5]->setLabel( tr("1.000 kHz") ); + eq[6]->setLabel( tr("2.000 kHz") ); + eq[7]->setLabel( tr("4.000 kHz") ); + eq[8]->setLabel( tr("8.000 kHz") ); + eq[9]->setLabel( tr("16.00 kHz") ); + + apply_button->setText( tr("&Apply") ); + reset_button->setText( tr("&Reset") ); + set_default_button->setText( tr("&Set as default values") ); + + // What's this help: + set_default_button->setWhatsThis( + tr("Use the current values as default values for new videos.") ); + + reset_button->setWhatsThis( tr("Set all controls to zero.") ); + +} + +void AudioEqualizer::reset() { + for (int n = 0; n < 10; n++) { + eq[n]->setValue(0); + } +} + +void AudioEqualizer::setDefaults() { + AudioEqualizerList l; + for (int n = 0; n < 10; n++) { + l << eq[n]->value(); + } + pref->initial_audio_equalizer = l; + + QMessageBox::information(this, tr("Information"), + tr("The current values have been stored to be " + "used as default.") ); +} + +void AudioEqualizer::applyButtonClicked() { + AudioEqualizerList l; + for (int n = 0; n < 10; n++) { + l << eq[n]->value(); + } + emit applyClicked( l ); +} + +void AudioEqualizer::hideEvent( QHideEvent * ) { + emit visibilityChanged(); +} + +void AudioEqualizer::showEvent( QShowEvent * ) { + emit visibilityChanged(); +} + +// Language change stuff +void AudioEqualizer::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QWidget::changeEvent(e); + } +} + +#include "moc_audioequalizer.cpp" diff --git a/plugins/smplayer_plugin/audioequalizer.h b/plugins/smplayer_plugin/audioequalizer.h new file mode 100644 index 000000000..02a8ef8da --- /dev/null +++ b/plugins/smplayer_plugin/audioequalizer.h @@ -0,0 +1,67 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _AUDIOOEQUALIZER_H_ +#define _AUDIOOEQUALIZER_H_ + +#include +#include +#include +#include "audioequalizerlist.h" + +class QPushButton; +class EqSlider; + +class AudioEqualizer : public QWidget +{ + Q_OBJECT + +public: + AudioEqualizer( QWidget* parent = 0, Qt::WindowFlags f = Qt::Dialog ); + ~AudioEqualizer(); + + EqSlider * eq[10]; + +signals: + void visibilityChanged(); + void applyClicked(AudioEqualizerList new_values); + +public slots: + void reset(); + void setDefaults(); + +protected slots: + void applyButtonClicked(); + +protected: + virtual void hideEvent( QHideEvent * ); + virtual void showEvent( QShowEvent * ); + +protected: + virtual void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + +protected: + QPushButton * apply_button; + QPushButton * reset_button; + QPushButton * set_default_button; +}; + + +#endif diff --git a/plugins/smplayer_plugin/audioequalizerlist.h b/plugins/smplayer_plugin/audioequalizerlist.h new file mode 100644 index 000000000..fdd65774c --- /dev/null +++ b/plugins/smplayer_plugin/audioequalizerlist.h @@ -0,0 +1,27 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _AUDIOEQUALIZERLIST_H_ +#define _AUDIOEQUALIZERLIST_H_ + +#include +#include + +typedef QList AudioEqualizerList; + +#endif diff --git a/plugins/smplayer_plugin/basegui.cpp b/plugins/smplayer_plugin/basegui.cpp new file mode 100644 index 000000000..c75ef32e0 --- /dev/null +++ b/plugins/smplayer_plugin/basegui.cpp @@ -0,0 +1,4192 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "basegui.h" + +#include "filedialog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mplayerwindow.h" +#include "desktopinfo.h" +#include "helper.h" +#include "paths.h" +#include "colorutils.h" +#include "global.h" +#include "translator.h" +#include "images.h" +#include "preferences.h" +#include "timeslider.h" +#include "logwindow.h" +#include "playlist.h" +#include "filepropertiesdialog.h" +#include "eqslider.h" +#include "videoequalizer.h" +#include "audioequalizer.h" +#include "inputdvddirectory.h" +#include "inputmplayerversion.h" +#include "inputurl.h" +#include "recents.h" +#include "urlhistory.h" +#include "about.h" +#include "errordialog.h" +#include "timedialog.h" +#include "clhelp.h" +#include "findsubtitleswindow.h" +#include "videopreview.h" +#include "mplayerversion.h" + +#include "config.h" +#include "actionseditor.h" + +#include "myserver.h" + +#include "preferencesdialog.h" +#ifndef NO_USE_INI_FILES +#include "prefgeneral.h" +#endif +#include "prefinterface.h" +#include "prefinput.h" +#include "prefadvanced.h" + +#include "myaction.h" +#include "myactiongroup.h" + +#include "constants.h" + +#include "extensions.h" + +#ifdef Q_OS_WIN +#include "deviceinfo.h" +#endif + +using namespace Global; + +BaseGui::BaseGui( QWidget* parent, Qt::WindowFlags flags ) + : QMainWindow( parent, flags ), + near_top(false), + near_bottom(false) +{ +#ifdef Q_OS_WIN + /* Disable screensaver by event */ + just_stopped = false; +#endif + ignore_show_hide_events = false; + + setWindowTitle( "SMPlayer" ); + + // Not created objects + server = 0; + popup = 0; + pref_dialog = 0; + file_dialog = 0; + clhelp_window = 0; + find_subs_dialog = 0; + video_preview = 0; + + // Create objects: + createPanel(); + setCentralWidget(panel); + + createMplayerWindow(); + createCore(); + createPlaylist(); + createVideoEqualizer(); + createAudioEqualizer(); + + // Mouse Wheel + connect( this, SIGNAL(wheelUp()), + core, SLOT(wheelUp()) ); + connect( this, SIGNAL(wheelDown()), + core, SLOT(wheelDown()) ); + connect( mplayerwindow, SIGNAL(wheelUp()), + core, SLOT(wheelUp()) ); + connect( mplayerwindow, SIGNAL(wheelDown()), + core, SLOT(wheelDown()) ); + + // Set style before changing color of widgets: + // Set style +#if STYLE_SWITCHING + qDebug( "Style name: '%s'", qApp->style()->objectName().toUtf8().data() ); + qDebug( "Style class name: '%s'", qApp->style()->metaObject()->className() ); + + default_style = qApp->style()->objectName(); + if (!pref->style.isEmpty()) { + qApp->setStyle( pref->style ); + } +#endif + + mplayer_log_window = new LogWindow(0); + smplayer_log_window = new LogWindow(0); + + createActions(); + createMenus(); +#if AUTODISABLE_ACTIONS + setActionsEnabled(false); +#endif + +#if !DOCK_PLAYLIST + connect(playlist, SIGNAL(visibilityChanged(bool)), + showPlaylistAct, SLOT(setChecked(bool)) ); +#endif + + retranslateStrings(); + + setAcceptDrops(true); + + resize(pref->default_size); + + panel->setFocus(); + + initializeGui(); +} + +void BaseGui::initializeGui() { + if (pref->compact_mode) toggleCompactMode(TRUE); + changeStayOnTop(pref->stay_on_top); + toggleFrameCounter( pref->show_frame_counter ); + +#if ALLOW_CHANGE_STYLESHEET + changeStyleSheet(pref->iconset); +#endif + + updateRecents(); + + // Call loadActions() outside initialization of the class. + // Otherwise DefaultGui (and other subclasses) doesn't exist, and + // its actions are not loaded + QTimer::singleShot(20, this, SLOT(loadActions())); + + // Single instance + server = new MyServer(this); + connect(server, SIGNAL(receivedOpen(QString)), + this, SLOT(remoteOpen(QString))); + connect(server, SIGNAL(receivedOpenFiles(QStringList)), + this, SLOT(remoteOpenFiles(QStringList))); + connect(server, SIGNAL(receivedAddFiles(QStringList)), + this, SLOT(remoteAddFiles(QStringList))); + connect(server, SIGNAL(receivedFunction(QString)), + this, SLOT(processFunction(QString))); + + if (pref->use_single_instance) { + int port = 0; + if (!pref->use_autoport) port = pref->connection_port; + if (server->listen(port)) { + pref->autoport = server->serverPort(); + pref->save(); + qDebug("BaseGui::initializeGui: server running on port %d", pref->autoport); + } else { + qWarning("BaseGui::initializeGui: server couldn't be started"); + } + } +} + +void BaseGui::remoteOpen(QString file) { + qDebug("BaseGui::remoteOpen: '%s'", file.toUtf8().data()); + if (isMinimized()) showNormal(); + if (!isVisible()) show(); + raise(); + activateWindow(); + open(file); +} + +void BaseGui::remoteOpenFiles(QStringList files) { + qDebug("BaseGui::remoteOpenFiles"); + if (isMinimized()) showNormal(); + if (!isVisible()) show(); + raise(); + activateWindow(); + openFiles(files); +} + +void BaseGui::remoteAddFiles(QStringList files) { + qDebug("BaseGui::remoteAddFiles"); + if (isMinimized()) showNormal(); + if (!isVisible()) show(); + raise(); + activateWindow(); + + playlist->addFiles(files); + //open(files[0]); +} + +BaseGui::~BaseGui() { + delete core; // delete before mplayerwindow, otherwise, segfault... + delete mplayer_log_window; + delete smplayer_log_window; + +//#if !DOCK_PLAYLIST + if (playlist) { + delete playlist; + playlist = 0; + } +//#endif + + if (find_subs_dialog) { + delete find_subs_dialog; + find_subs_dialog = 0; // Necessary? + } + + if (video_preview) { + delete video_preview; + } +} + +void BaseGui::createActions() { + // Menu File + openFileAct = new MyAction( QKeySequence("Ctrl+F"), this, "open_file" ); + connect( openFileAct, SIGNAL(triggered()), + this, SLOT(openFile()) ); + + openDirectoryAct = new MyAction( this, "open_directory" ); + connect( openDirectoryAct, SIGNAL(triggered()), + this, SLOT(openDirectory()) ); + + openPlaylistAct = new MyAction( this, "open_playlist" ); + connect( openPlaylistAct, SIGNAL(triggered()), + playlist, SLOT(load()) ); + + openVCDAct = new MyAction( this, "open_vcd" ); + connect( openVCDAct, SIGNAL(triggered()), + this, SLOT(openVCD()) ); + + openAudioCDAct = new MyAction( this, "open_audio_cd" ); + connect( openAudioCDAct, SIGNAL(triggered()), + this, SLOT(openAudioCD()) ); + +#ifdef Q_OS_WIN + // VCD's and Audio CD's seem they don't work on windows + //openVCDAct->setEnabled(pref->enable_vcd_on_windows); + openAudioCDAct->setEnabled(pref->enable_audiocd_on_windows); +#endif + + openDVDAct = new MyAction( this, "open_dvd" ); + connect( openDVDAct, SIGNAL(triggered()), + this, SLOT(openDVD()) ); + + openDVDFolderAct = new MyAction( this, "open_dvd_folder" ); + connect( openDVDFolderAct, SIGNAL(triggered()), + this, SLOT(openDVDFromFolder()) ); + + openURLAct = new MyAction( QKeySequence("Ctrl+U"), this, "open_url" ); + connect( openURLAct, SIGNAL(triggered()), + this, SLOT(openURL()) ); + + exitAct = new MyAction( QKeySequence("Ctrl+X"), this, "close" ); + connect( exitAct, SIGNAL(triggered()), this, SLOT(closeWindow()) ); + + clearRecentsAct = new MyAction( this, "clear_recents" ); + connect( clearRecentsAct, SIGNAL(triggered()), this, SLOT(clearRecentsList()) ); + + + // Menu Play + playAct = new MyAction( this, "play" ); + connect( playAct, SIGNAL(triggered()), + core, SLOT(play()) ); + + playOrPauseAct = new MyAction( Qt::Key_MediaPlay, this, "play_or_pause" ); + connect( playOrPauseAct, SIGNAL(triggered()), + core, SLOT(play_or_pause()) ); + + pauseAct = new MyAction( Qt::Key_Space, this, "pause" ); + connect( pauseAct, SIGNAL(triggered()), + core, SLOT(pause()) ); + + pauseAndStepAct = new MyAction( this, "pause_and_frame_step" ); + connect( pauseAndStepAct, SIGNAL(triggered()), + core, SLOT(pause_and_frame_step()) ); + + stopAct = new MyAction( Qt::Key_MediaStop, this, "stop" ); + connect( stopAct, SIGNAL(triggered()), + core, SLOT(stop()) ); + + frameStepAct = new MyAction( Qt::Key_Period, this, "frame_step" ); + connect( frameStepAct, SIGNAL(triggered()), + core, SLOT(frameStep()) ); + + rewind1Act = new MyAction( Qt::Key_Left, this, "rewind1" ); + connect( rewind1Act, SIGNAL(triggered()), + core, SLOT(srewind()) ); + + rewind2Act = new MyAction( Qt::Key_Down, this, "rewind2" ); + connect( rewind2Act, SIGNAL(triggered()), + core, SLOT(rewind()) ); + + rewind3Act = new MyAction( Qt::Key_PageDown, this, "rewind3" ); + connect( rewind3Act, SIGNAL(triggered()), + core, SLOT(fastrewind()) ); + + forward1Act = new MyAction( Qt::Key_Right, this, "forward1" ); + connect( forward1Act, SIGNAL(triggered()), + core, SLOT(sforward()) ); + + forward2Act = new MyAction( Qt::Key_Up, this, "forward2" ); + connect( forward2Act, SIGNAL(triggered()), + core, SLOT(forward()) ); + + forward3Act = new MyAction( Qt::Key_PageUp, this, "forward3" ); + connect( forward3Act, SIGNAL(triggered()), + core, SLOT(fastforward()) ); + + repeatAct = new MyAction( this, "repeat" ); + repeatAct->setCheckable( true ); + connect( repeatAct, SIGNAL(toggled(bool)), + core, SLOT(toggleRepeat(bool)) ); + + gotoAct = new MyAction( QKeySequence("Ctrl+J"), this, "jump_to" ); + connect( gotoAct, SIGNAL(triggered()), + this, SLOT(showGotoDialog()) ); + + // Submenu Speed + normalSpeedAct = new MyAction( Qt::Key_Backspace, this, "normal_speed" ); + connect( normalSpeedAct, SIGNAL(triggered()), + core, SLOT(normalSpeed()) ); + + halveSpeedAct = new MyAction( Qt::Key_BraceLeft, this, "halve_speed" ); + connect( halveSpeedAct, SIGNAL(triggered()), + core, SLOT(halveSpeed()) ); + + doubleSpeedAct = new MyAction( Qt::Key_BraceRight, this, "double_speed" ); + connect( doubleSpeedAct, SIGNAL(triggered()), + core, SLOT(doubleSpeed()) ); + + decSpeed10Act = new MyAction( Qt::Key_BracketLeft, this, "dec_speed" ); + connect( decSpeed10Act, SIGNAL(triggered()), + core, SLOT(decSpeed10()) ); + + incSpeed10Act = new MyAction( Qt::Key_BracketRight, this, "inc_speed" ); + connect( incSpeed10Act, SIGNAL(triggered()), + core, SLOT(incSpeed10()) ); + + decSpeed4Act = new MyAction( this, "dec_speed_4" ); + connect( decSpeed4Act, SIGNAL(triggered()), + core, SLOT(decSpeed4()) ); + + incSpeed4Act = new MyAction( this, "inc_speed_4" ); + connect( incSpeed4Act, SIGNAL(triggered()), + core, SLOT(incSpeed4()) ); + + decSpeed1Act = new MyAction( this, "dec_speed_1" ); + connect( decSpeed1Act, SIGNAL(triggered()), + core, SLOT(decSpeed1()) ); + + incSpeed1Act = new MyAction( this, "inc_speed_1" ); + connect( incSpeed1Act, SIGNAL(triggered()), + core, SLOT(incSpeed1()) ); + + + // Menu Video + fullscreenAct = new MyAction( Qt::Key_F, this, "fullscreen" ); + fullscreenAct->setCheckable( true ); + connect( fullscreenAct, SIGNAL(toggled(bool)), + this, SLOT(toggleFullscreen(bool)) ); + + compactAct = new MyAction( QKeySequence("Ctrl+C"), this, "compact" ); + compactAct->setCheckable( true ); + connect( compactAct, SIGNAL(toggled(bool)), + this, SLOT(toggleCompactMode(bool)) ); + + videoEqualizerAct = new MyAction( QKeySequence("Ctrl+E"), this, "video_equalizer" ); + videoEqualizerAct->setCheckable( true ); + connect( videoEqualizerAct, SIGNAL(toggled(bool)), + this, SLOT(showVideoEqualizer(bool)) ); + + screenshotAct = new MyAction( Qt::Key_S, this, "screenshot" ); + connect( screenshotAct, SIGNAL(triggered()), + core, SLOT(screenshot()) ); + + videoPreviewAct = new MyAction( this, "video_preview" ); + connect( videoPreviewAct, SIGNAL(triggered()), + this, SLOT(showVideoPreviewDialog()) ); + + flipAct = new MyAction( this, "flip" ); + flipAct->setCheckable( true ); + connect( flipAct, SIGNAL(toggled(bool)), + core, SLOT(toggleFlip(bool)) ); + + mirrorAct = new MyAction( this, "mirror" ); + mirrorAct->setCheckable( true ); + connect( mirrorAct, SIGNAL(toggled(bool)), + core, SLOT(toggleMirror(bool)) ); + + // Submenu filter + postProcessingAct = new MyAction( this, "postprocessing" ); + postProcessingAct->setCheckable( true ); + connect( postProcessingAct, SIGNAL(toggled(bool)), + core, SLOT(togglePostprocessing(bool)) ); + + phaseAct = new MyAction( this, "autodetect_phase" ); + phaseAct->setCheckable( true ); + connect( phaseAct, SIGNAL(toggled(bool)), + core, SLOT(toggleAutophase(bool)) ); + + deblockAct = new MyAction( this, "deblock" ); + deblockAct->setCheckable( true ); + connect( deblockAct, SIGNAL(toggled(bool)), + core, SLOT(toggleDeblock(bool)) ); + + deringAct = new MyAction( this, "dering" ); + deringAct->setCheckable( true ); + connect( deringAct, SIGNAL(toggled(bool)), + core, SLOT(toggleDering(bool)) ); + + addNoiseAct = new MyAction( this, "add_noise" ); + addNoiseAct->setCheckable( true ); + connect( addNoiseAct, SIGNAL(toggled(bool)), + core, SLOT(toggleNoise(bool)) ); + +#if NEW_ASPECT_CODE + addLetterboxAct = new MyAction( this, "add_letterbox" ); + addLetterboxAct->setCheckable( true ); + connect( addLetterboxAct, SIGNAL(toggled(bool)), + core, SLOT(changeLetterbox(bool)) ); +#endif + + upscaleAct = new MyAction( this, "upscaling" ); + upscaleAct->setCheckable( true ); + connect( upscaleAct, SIGNAL(toggled(bool)), + core, SLOT(changeUpscale(bool)) ); + + + // Menu Audio + audioEqualizerAct = new MyAction( this, "audio_equalizer" ); + audioEqualizerAct->setCheckable( true ); + connect( audioEqualizerAct, SIGNAL(toggled(bool)), + this, SLOT(showAudioEqualizer(bool)) ); + + muteAct = new MyAction( Qt::Key_M, this, "mute" ); + muteAct->setCheckable( true ); + connect( muteAct, SIGNAL(toggled(bool)), + core, SLOT(mute(bool)) ); + +#if USE_MULTIPLE_SHORTCUTS + decVolumeAct = new MyAction( this, "decrease_volume" ); + decVolumeAct->setShortcuts( ActionsEditor::stringToShortcuts("9,/") ); +#else + decVolumeAct = new MyAction( Qt::Key_9, this, "dec_volume" ); +#endif + connect( decVolumeAct, SIGNAL(triggered()), + core, SLOT(decVolume()) ); + +#if USE_MULTIPLE_SHORTCUTS + incVolumeAct = new MyAction( this, "increase_volume" ); + incVolumeAct->setShortcuts( ActionsEditor::stringToShortcuts("0,*") ); +#else + incVolumeAct = new MyAction( Qt::Key_0, this, "inc_volume" ); +#endif + connect( incVolumeAct, SIGNAL(triggered()), + core, SLOT(incVolume()) ); + + decAudioDelayAct = new MyAction( Qt::Key_Minus, this, "dec_audio_delay" ); + connect( decAudioDelayAct, SIGNAL(triggered()), + core, SLOT(decAudioDelay()) ); + + incAudioDelayAct = new MyAction( Qt::Key_Plus, this, "inc_audio_delay" ); + connect( incAudioDelayAct, SIGNAL(triggered()), + core, SLOT(incAudioDelay()) ); + + loadAudioAct = new MyAction( this, "load_audio_file" ); + connect( loadAudioAct, SIGNAL(triggered()), + this, SLOT(loadAudioFile()) ); + + unloadAudioAct = new MyAction( this, "unload_audio_file" ); + connect( unloadAudioAct, SIGNAL(triggered()), + core, SLOT(unloadAudioFile()) ); + + + // Submenu Filters + extrastereoAct = new MyAction( this, "extrastereo_filter" ); + extrastereoAct->setCheckable( true ); + connect( extrastereoAct, SIGNAL(toggled(bool)), + core, SLOT(toggleExtrastereo(bool)) ); + + karaokeAct = new MyAction( this, "karaoke_filter" ); + karaokeAct->setCheckable( true ); + connect( karaokeAct, SIGNAL(toggled(bool)), + core, SLOT(toggleKaraoke(bool)) ); + + volnormAct = new MyAction( this, "volnorm_filter" ); + volnormAct->setCheckable( true ); + connect( volnormAct, SIGNAL(toggled(bool)), + core, SLOT(toggleVolnorm(bool)) ); + + + // Menu Subtitles + loadSubsAct = new MyAction( this, "load_subs" ); + connect( loadSubsAct, SIGNAL(triggered()), + this, SLOT(loadSub()) ); + + unloadSubsAct = new MyAction( this, "unload_subs" ); + connect( unloadSubsAct, SIGNAL(triggered()), + core, SLOT(unloadSub()) ); + + decSubDelayAct = new MyAction( Qt::Key_Z, this, "dec_sub_delay" ); + connect( decSubDelayAct, SIGNAL(triggered()), + core, SLOT(decSubDelay()) ); + + incSubDelayAct = new MyAction( Qt::Key_X, this, "inc_sub_delay" ); + connect( incSubDelayAct, SIGNAL(triggered()), + core, SLOT(incSubDelay()) ); + + decSubPosAct = new MyAction( Qt::Key_R, this, "dec_sub_pos" ); + connect( decSubPosAct, SIGNAL(triggered()), + core, SLOT(decSubPos()) ); + incSubPosAct = new MyAction( Qt::Key_T, this, "inc_sub_pos" ); + connect( incSubPosAct, SIGNAL(triggered()), + core, SLOT(incSubPos()) ); + + decSubScaleAct = new MyAction( Qt::SHIFT | Qt::Key_R, this, "dec_sub_scale" ); + connect( decSubScaleAct, SIGNAL(triggered()), + core, SLOT(decSubScale()) ); + + incSubScaleAct = new MyAction( Qt::SHIFT | Qt::Key_T, this, "inc_sub_scale" ); + connect( incSubScaleAct, SIGNAL(triggered()), + core, SLOT(incSubScale()) ); + + decSubStepAct = new MyAction( Qt::Key_G, this, "dec_sub_step" ); + connect( decSubStepAct, SIGNAL(triggered()), + core, SLOT(decSubStep()) ); + + incSubStepAct = new MyAction( Qt::Key_Y, this, "inc_sub_step" ); + connect( incSubStepAct, SIGNAL(triggered()), + core, SLOT(incSubStep()) ); + + useAssAct = new MyAction(this, "use_ass_lib"); + useAssAct->setCheckable(true); + connect( useAssAct, SIGNAL(toggled(bool)), core, SLOT(changeUseAss(bool)) ); + + useClosedCaptionAct = new MyAction(this, "use_closed_caption"); + useClosedCaptionAct->setCheckable(true); + connect( useClosedCaptionAct, SIGNAL(toggled(bool)), core, SLOT(toggleClosedCaption(bool)) ); + + useForcedSubsOnlyAct = new MyAction(this, "use_forced_subs_only"); + useForcedSubsOnlyAct->setCheckable(true); + connect( useForcedSubsOnlyAct, SIGNAL(toggled(bool)), core, SLOT(toggleForcedSubsOnly(bool)) ); + + showFindSubtitlesDialogAct = new MyAction( this, "show_find_sub_dialog" ); + connect( showFindSubtitlesDialogAct, SIGNAL(triggered()), + this, SLOT(showFindSubtitlesDialog()) ); + + openUploadSubtitlesPageAct = new MyAction( this, "upload_subtitles" ); //turbos + connect( openUploadSubtitlesPageAct, SIGNAL(triggered()), //turbos + this, SLOT(openUploadSubtitlesPage()) ); //turbos + + + // Menu Options + showPlaylistAct = new MyAction( QKeySequence("Ctrl+L"), this, "show_playlist" ); + showPlaylistAct->setCheckable( true ); + connect( showPlaylistAct, SIGNAL(toggled(bool)), + this, SLOT(showPlaylist(bool)) ); + + showPropertiesAct = new MyAction( QKeySequence("Ctrl+I"), this, "show_file_properties" ); + connect( showPropertiesAct, SIGNAL(triggered()), + this, SLOT(showFilePropertiesDialog()) ); + + frameCounterAct = new MyAction( this, "frame_counter" ); + frameCounterAct->setCheckable( true ); + connect( frameCounterAct, SIGNAL(toggled(bool)), + this, SLOT(toggleFrameCounter(bool)) ); + + motionVectorsAct = new MyAction( this, "motion_vectors" ); + motionVectorsAct->setCheckable( true ); + connect( motionVectorsAct, SIGNAL(toggled(bool)), + core, SLOT(visualizeMotionVectors(bool)) ); + + showPreferencesAct = new MyAction( QKeySequence("Ctrl+P"), this, "show_preferences" ); + connect( showPreferencesAct, SIGNAL(triggered()), + this, SLOT(showPreferencesDialog()) ); + + // Submenu Logs + showLogMplayerAct = new MyAction( QKeySequence("Ctrl+M"), this, "show_mplayer_log" ); + connect( showLogMplayerAct, SIGNAL(triggered()), + this, SLOT(showMplayerLog()) ); + + showLogSmplayerAct = new MyAction( QKeySequence("Ctrl+S"), this, "show_smplayer_log" ); + connect( showLogSmplayerAct, SIGNAL(triggered()), + this, SLOT(showLog()) ); + + // Menu Help + showFAQAct = new MyAction( this, "faq" ); + connect( showFAQAct, SIGNAL(triggered()), + this, SLOT(helpFAQ()) ); + + showCLOptionsAct = new MyAction( this, "cl_options" ); + connect( showCLOptionsAct, SIGNAL(triggered()), + this, SLOT(helpCLOptions()) ); + + showTipsAct = new MyAction( this, "tips" ); + connect( showTipsAct, SIGNAL(triggered()), + this, SLOT(helpTips()) ); + + aboutQtAct = new MyAction( this, "about_qt" ); + connect( aboutQtAct, SIGNAL(triggered()), + this, SLOT(helpAboutQt()) ); + + aboutThisAct = new MyAction( this, "about_smplayer" ); + connect( aboutThisAct, SIGNAL(triggered()), + this, SLOT(helpAbout()) ); + + // Playlist + playNextAct = new MyAction(Qt::Key_Greater, this, "play_next"); + connect( playNextAct, SIGNAL(triggered()), playlist, SLOT(playNext()) ); + + playPrevAct = new MyAction(Qt::Key_Less, this, "play_prev"); + connect( playPrevAct, SIGNAL(triggered()), playlist, SLOT(playPrev()) ); + + + // Move video window and zoom + moveUpAct = new MyAction(Qt::ALT | Qt::Key_Up, this, "move_up"); + connect( moveUpAct, SIGNAL(triggered()), mplayerwindow, SLOT(moveUp()) ); + + moveDownAct = new MyAction(Qt::ALT | Qt::Key_Down, this, "move_down"); + connect( moveDownAct, SIGNAL(triggered()), mplayerwindow, SLOT(moveDown()) ); + + moveLeftAct = new MyAction(Qt::ALT | Qt::Key_Left, this, "move_left"); + connect( moveLeftAct, SIGNAL(triggered()), mplayerwindow, SLOT(moveLeft()) ); + + moveRightAct = new MyAction(Qt::ALT | Qt::Key_Right, this, "move_right"); + connect( moveRightAct, SIGNAL(triggered()), mplayerwindow, SLOT(moveRight()) ); + + incZoomAct = new MyAction(Qt::Key_E, this, "inc_zoom"); + connect( incZoomAct, SIGNAL(triggered()), core, SLOT(incPanscan()) ); + + decZoomAct = new MyAction(Qt::Key_W, this, "dec_zoom"); + connect( decZoomAct, SIGNAL(triggered()), core, SLOT(decPanscan()) ); + + resetZoomAct = new MyAction(Qt::SHIFT | Qt::Key_E, this, "reset_zoom"); + connect( resetZoomAct, SIGNAL(triggered()), core, SLOT(resetPanscan()) ); + + autoZoomAct = new MyAction(Qt::SHIFT | Qt::Key_W, this, "auto_zoom"); + connect( autoZoomAct, SIGNAL(triggered()), core, SLOT(autoPanscan()) ); + + autoZoom169Act = new MyAction(Qt::SHIFT | Qt::Key_A, this, "zoom_169"); + connect( autoZoom169Act, SIGNAL(triggered()), core, SLOT(autoPanscanFor169()) ); + + autoZoom235Act = new MyAction(Qt::SHIFT | Qt::Key_S, this, "zoom_235"); + connect( autoZoom235Act, SIGNAL(triggered()), core, SLOT(autoPanscanFor235()) ); + + + // Actions not in menus or buttons + // Volume 2 +#if !USE_MULTIPLE_SHORTCUTS + decVolume2Act = new MyAction( Qt::Key_Slash, this, "dec_volume2" ); + connect( decVolume2Act, SIGNAL(triggered()), core, SLOT(decVolume()) ); + + incVolume2Act = new MyAction( Qt::Key_Asterisk, this, "inc_volume2" ); + connect( incVolume2Act, SIGNAL(triggered()), core, SLOT(incVolume()) ); +#endif + // Exit fullscreen + exitFullscreenAct = new MyAction( Qt::Key_Escape, this, "exit_fullscreen" ); + connect( exitFullscreenAct, SIGNAL(triggered()), this, SLOT(exitFullscreen()) ); + + nextOSDAct = new MyAction( Qt::Key_O, this, "next_osd"); + connect( nextOSDAct, SIGNAL(triggered()), core, SLOT(nextOSD()) ); + + decContrastAct = new MyAction( Qt::Key_1, this, "dec_contrast"); + connect( decContrastAct, SIGNAL(triggered()), core, SLOT(decContrast()) ); + + incContrastAct = new MyAction( Qt::Key_2, this, "inc_contrast"); + connect( incContrastAct, SIGNAL(triggered()), core, SLOT(incContrast()) ); + + decBrightnessAct = new MyAction( Qt::Key_3, this, "dec_brightness"); + connect( decBrightnessAct, SIGNAL(triggered()), core, SLOT(decBrightness()) ); + + incBrightnessAct = new MyAction( Qt::Key_4, this, "inc_brightness"); + connect( incBrightnessAct, SIGNAL(triggered()), core, SLOT(incBrightness()) ); + + decHueAct = new MyAction(Qt::Key_5, this, "dec_hue"); + connect( decHueAct, SIGNAL(triggered()), core, SLOT(decHue()) ); + + incHueAct = new MyAction( Qt::Key_6, this, "inc_hue"); + connect( incHueAct, SIGNAL(triggered()), core, SLOT(incHue()) ); + + decSaturationAct = new MyAction( Qt::Key_7, this, "dec_saturation"); + connect( decSaturationAct, SIGNAL(triggered()), core, SLOT(decSaturation()) ); + + incSaturationAct = new MyAction( Qt::Key_8, this, "inc_saturation"); + connect( incSaturationAct, SIGNAL(triggered()), core, SLOT(incSaturation()) ); + + decGammaAct = new MyAction( this, "dec_gamma"); + connect( decGammaAct, SIGNAL(triggered()), core, SLOT(decGamma()) ); + + incGammaAct = new MyAction( this, "inc_gamma"); + connect( incGammaAct, SIGNAL(triggered()), core, SLOT(incGamma()) ); + + nextVideoAct = new MyAction( this, "next_video"); + connect( nextVideoAct, SIGNAL(triggered()), core, SLOT(nextVideo()) ); + + nextAudioAct = new MyAction( Qt::Key_H, this, "next_audio"); + connect( nextAudioAct, SIGNAL(triggered()), core, SLOT(nextAudio()) ); + + nextSubtitleAct = new MyAction( Qt::Key_J, this, "next_subtitle"); + connect( nextSubtitleAct, SIGNAL(triggered()), core, SLOT(nextSubtitle()) ); + + nextChapterAct = new MyAction( Qt::Key_At, this, "next_chapter"); + connect( nextChapterAct, SIGNAL(triggered()), core, SLOT(nextChapter()) ); + + prevChapterAct = new MyAction( Qt::Key_Exclam, this, "prev_chapter"); + connect( prevChapterAct, SIGNAL(triggered()), core, SLOT(prevChapter()) ); + + doubleSizeAct = new MyAction( Qt::CTRL | Qt::Key_D, this, "toggle_double_size"); + connect( doubleSizeAct, SIGNAL(triggered()), core, SLOT(toggleDoubleSize()) ); + + resetVideoEqualizerAct = new MyAction( this, "reset_video_equalizer"); + connect( resetVideoEqualizerAct, SIGNAL(triggered()), video_equalizer, SLOT(reset()) ); + + resetAudioEqualizerAct = new MyAction( this, "reset_audio_equalizer"); + connect( resetAudioEqualizerAct, SIGNAL(triggered()), audio_equalizer, SLOT(reset()) ); + + showContextMenuAct = new MyAction( this, "show_context_menu"); + connect( showContextMenuAct, SIGNAL(triggered()), + this, SLOT(showPopupMenu()) ); + +#if NEW_ASPECT_CODE + nextAspectAct = new MyAction( Qt::Key_A, this, "next_aspect"); + connect( nextAspectAct, SIGNAL(triggered()), + core, SLOT(nextAspectRatio()) ); +#endif + + // Group actions + + // OSD + osdGroup = new MyActionGroup(this); + osdNoneAct = new MyActionGroupItem(this, osdGroup, "osd_none", Preferences::None); + osdSeekAct = new MyActionGroupItem(this, osdGroup, "osd_seek", Preferences::Seek); + osdTimerAct = new MyActionGroupItem(this, osdGroup, "osd_timer", Preferences::SeekTimer); + osdTotalAct = new MyActionGroupItem(this, osdGroup, "osd_total", Preferences::SeekTimerTotal); + connect( osdGroup, SIGNAL(activated(int)), core, SLOT(changeOSD(int)) ); + + // Denoise + denoiseGroup = new MyActionGroup(this); + denoiseNoneAct = new MyActionGroupItem(this, denoiseGroup, "denoise_none", MediaSettings::NoDenoise); + denoiseNormalAct = new MyActionGroupItem(this, denoiseGroup, "denoise_normal", MediaSettings::DenoiseNormal); + denoiseSoftAct = new MyActionGroupItem(this, denoiseGroup, "denoise_soft", MediaSettings::DenoiseSoft); + connect( denoiseGroup, SIGNAL(activated(int)), core, SLOT(changeDenoise(int)) ); + + // Video size + sizeGroup = new MyActionGroup(this); + size50 = new MyActionGroupItem(this, sizeGroup, "5&0%", "size_50", 50); + size75 = new MyActionGroupItem(this, sizeGroup, "7&5%", "size_75", 75); + size100 = new MyActionGroupItem(this, sizeGroup, "&100%", "size_100", 100); + size125 = new MyActionGroupItem(this, sizeGroup, "1&25%", "size_125", 125); + size150 = new MyActionGroupItem(this, sizeGroup, "15&0%", "size_150", 150); + size175 = new MyActionGroupItem(this, sizeGroup, "1&75%", "size_175", 175); + size200 = new MyActionGroupItem(this, sizeGroup, "&200%", "size_200", 200); + size300 = new MyActionGroupItem(this, sizeGroup, "&300%", "size_300", 300); + size400 = new MyActionGroupItem(this, sizeGroup, "&400%", "size_400", 400); + size100->setShortcut( Qt::CTRL | Qt::Key_1 ); + size200->setShortcut( Qt::CTRL | Qt::Key_2 ); + connect( sizeGroup, SIGNAL(activated(int)), core, SLOT(changeSize(int)) ); + // Make all not checkable + QList size_list = sizeGroup->actions(); + for (int n=0; n < size_list.count(); n++) { + size_list[n]->setCheckable(false); + } + + // Deinterlace + deinterlaceGroup = new MyActionGroup(this); + deinterlaceNoneAct = new MyActionGroupItem(this, deinterlaceGroup, "deinterlace_none", MediaSettings::NoDeinterlace); + deinterlaceL5Act = new MyActionGroupItem(this, deinterlaceGroup, "deinterlace_l5", MediaSettings::L5); + deinterlaceYadif0Act = new MyActionGroupItem(this, deinterlaceGroup, "deinterlace_yadif0", MediaSettings::Yadif); + deinterlaceYadif1Act = new MyActionGroupItem(this, deinterlaceGroup, "deinterlace_yadif1", MediaSettings::Yadif_1); + deinterlaceLBAct = new MyActionGroupItem(this, deinterlaceGroup, "deinterlace_lb", MediaSettings::LB); + deinterlaceKernAct = new MyActionGroupItem(this, deinterlaceGroup, "deinterlace_kern", MediaSettings::Kerndeint); + connect( deinterlaceGroup, SIGNAL(activated(int)), + core, SLOT(changeDeinterlace(int)) ); + + // Audio channels + channelsGroup = new MyActionGroup(this); + /* channelsDefaultAct = new MyActionGroupItem(this, channelsGroup, "channels_default", MediaSettings::ChDefault); */ + channelsStereoAct = new MyActionGroupItem(this, channelsGroup, "channels_stereo", MediaSettings::ChStereo); + channelsSurroundAct = new MyActionGroupItem(this, channelsGroup, "channels_surround", MediaSettings::ChSurround); + channelsFull51Act = new MyActionGroupItem(this, channelsGroup, "channels_ful51", MediaSettings::ChFull51); + connect( channelsGroup, SIGNAL(activated(int)), + core, SLOT(setAudioChannels(int)) ); + + // Stereo mode + stereoGroup = new MyActionGroup(this); + stereoAct = new MyActionGroupItem(this, stereoGroup, "stereo", MediaSettings::Stereo); + leftChannelAct = new MyActionGroupItem(this, stereoGroup, "left_channel", MediaSettings::Left); + rightChannelAct = new MyActionGroupItem(this, stereoGroup, "right_channel", MediaSettings::Right); + connect( stereoGroup, SIGNAL(activated(int)), + core, SLOT(setStereoMode(int)) ); + + // Video aspect + aspectGroup = new MyActionGroup(this); + aspectDetectAct = new MyActionGroupItem(this, aspectGroup, "aspect_detect", MediaSettings::AspectAuto); + aspect43Act = new MyActionGroupItem(this, aspectGroup, "aspect_4:3", MediaSettings::Aspect43); + aspect54Act = new MyActionGroupItem(this, aspectGroup, "aspect_5:4", MediaSettings::Aspect54 ); + aspect149Act = new MyActionGroupItem(this, aspectGroup, "aspect_14:9", MediaSettings::Aspect149 ); + aspect169Act = new MyActionGroupItem(this, aspectGroup, "aspect_16:9", MediaSettings::Aspect169 ); + aspect1610Act = new MyActionGroupItem(this, aspectGroup, "aspect_16:10", MediaSettings::Aspect1610 ); + aspect235Act = new MyActionGroupItem(this, aspectGroup, "aspect_2.35:1", MediaSettings::Aspect235 ); +#if NEW_ASPECT_CODE + aspect11Act = new MyActionGroupItem(this, aspectGroup, "aspect_1:1", MediaSettings::Aspect11 ); + { + QAction * sep = new QAction(aspectGroup); + sep->setSeparator(true); + } + aspectNoneAct = new MyActionGroupItem(this, aspectGroup, "aspect_none", MediaSettings::AspectNone); +#endif + +#if !NEW_ASPECT_CODE + QAction * aspect_separator = new QAction(aspectGroup); + aspect_separator->setSeparator(true); + aspect43LetterAct = new MyActionGroupItem(this, aspectGroup, "aspect_4:3_letterbox", MediaSettings::Aspect43Letterbox ); + aspect169LetterAct = new MyActionGroupItem(this, aspectGroup, "aspect_16:9_letterbox", MediaSettings::Aspect169Letterbox ); + aspect43PanscanAct = new MyActionGroupItem(this, aspectGroup, "aspect_4:3_panscan", MediaSettings::Aspect43Panscan ); + aspect43To169Act = new MyActionGroupItem(this, aspectGroup, "aspect_4:3_to_16:9", MediaSettings::Aspect43To169 ); +#endif + connect( aspectGroup, SIGNAL(activated(int)), + core, SLOT(changeAspectRatio(int)) ); + + // Rotate + rotateGroup = new MyActionGroup(this); + rotateNoneAct = new MyActionGroupItem(this, rotateGroup, "rotate_none", MediaSettings::NoRotate); + rotateClockwiseFlipAct = new MyActionGroupItem(this, rotateGroup, "rotate_clockwise_flip", MediaSettings::Clockwise_flip); + rotateClockwiseAct = new MyActionGroupItem(this, rotateGroup, "rotate_clockwise", MediaSettings::Clockwise); + rotateCounterclockwiseAct = new MyActionGroupItem(this, rotateGroup, "rotate_counterclockwise", MediaSettings::Counterclockwise); + rotateCounterclockwiseFlipAct = new MyActionGroupItem(this, rotateGroup, "rotate_counterclockwise_flip", MediaSettings::Counterclockwise_flip); + connect( rotateGroup, SIGNAL(activated(int)), + core, SLOT(changeRotate(int)) ); + + // On Top + onTopActionGroup = new MyActionGroup(this); + onTopAlwaysAct = new MyActionGroupItem( this,onTopActionGroup,"on_top_always",Preferences::AlwaysOnTop); + onTopNeverAct = new MyActionGroupItem( this,onTopActionGroup,"on_top_never",Preferences::NeverOnTop); + onTopWhilePlayingAct = new MyActionGroupItem( this,onTopActionGroup,"on_top_playing",Preferences::WhilePlayingOnTop); + connect( onTopActionGroup , SIGNAL(activated(int)), + this, SLOT(changeStayOnTop(int)) ); + +#if USE_ADAPTER + screenGroup = new MyActionGroup(this); + screenDefaultAct = new MyActionGroupItem(this, screenGroup, "screen_default", -1); +#ifdef Q_OS_WIN + DeviceList display_devices = DeviceInfo::displayDevices(); + if (!display_devices.isEmpty()) { + for (int n = 0; n < display_devices.count(); n++) { + int id = display_devices[n].ID().toInt(); + QString desc = display_devices[n].desc(); + MyAction * screen_item = new MyActionGroupItem(this, screenGroup, QString("screen_%1").arg(n).toAscii().constData(), id); + screen_item->change( "&"+QString::number(n) + " - " + desc); + } + } + else +#endif // Q_OS_WIN + for (int n = 1; n <= 4; n++) { + MyAction * screen_item = new MyActionGroupItem(this, screenGroup, QString("screen_%1").arg(n).toAscii().constData(), n); + screen_item->change( "&"+QString::number(n) ); + } + + connect( screenGroup, SIGNAL(activated(int)), + core, SLOT(changeAdapter(int)) ); +#endif + + // Video track + videoTrackGroup = new MyActionGroup(this); + connect( videoTrackGroup, SIGNAL(activated(int)), + core, SLOT(changeVideo(int)) ); + + // Audio track + audioTrackGroup = new MyActionGroup(this); + connect( audioTrackGroup, SIGNAL(activated(int)), + core, SLOT(changeAudio(int)) ); + + // Subtitle track + subtitleTrackGroup = new MyActionGroup(this); + connect( subtitleTrackGroup, SIGNAL(activated(int)), + core, SLOT(changeSubtitle(int)) ); + + // Titles + titleGroup = new MyActionGroup(this); + connect( titleGroup, SIGNAL(activated(int)), + core, SLOT(changeTitle(int)) ); + + // Angles + angleGroup = new MyActionGroup(this); + connect( angleGroup, SIGNAL(activated(int)), + core, SLOT(changeAngle(int)) ); + + // Chapters + chapterGroup = new MyActionGroup(this); + connect( chapterGroup, SIGNAL(activated(int)), + core, SLOT(changeChapter(int)) ); + +#if DVDNAV_SUPPORT + dvdnavUpAct = new MyAction(Qt::SHIFT | Qt::Key_Up, this, "dvdnav_up"); + connect( dvdnavUpAct, SIGNAL(triggered()), core, SLOT(dvdnavUp()) ); + + dvdnavDownAct = new MyAction(Qt::SHIFT | Qt::Key_Down, this, "dvdnav_down"); + connect( dvdnavDownAct, SIGNAL(triggered()), core, SLOT(dvdnavDown()) ); + + dvdnavLeftAct = new MyAction(Qt::SHIFT | Qt::Key_Left, this, "dvdnav_left"); + connect( dvdnavLeftAct, SIGNAL(triggered()), core, SLOT(dvdnavLeft()) ); + + dvdnavRightAct = new MyAction(Qt::SHIFT | Qt::Key_Right, this, "dvdnav_right"); + connect( dvdnavRightAct, SIGNAL(triggered()), core, SLOT(dvdnavRight()) ); + + dvdnavMenuAct = new MyAction(Qt::SHIFT | Qt::Key_Return, this, "dvdnav_menu"); + connect( dvdnavMenuAct, SIGNAL(triggered()), core, SLOT(dvdnavMenu()) ); + + dvdnavSelectAct = new MyAction(Qt::Key_Return, this, "dvdnav_select"); + connect( dvdnavSelectAct, SIGNAL(triggered()), core, SLOT(dvdnavSelect()) ); + + dvdnavPrevAct = new MyAction(Qt::SHIFT | Qt::Key_Escape, this, "dvdnav_prev"); + connect( dvdnavPrevAct, SIGNAL(triggered()), core, SLOT(dvdnavPrev()) ); + + dvdnavMouseAct = new MyAction( this, "dvdnav_mouse"); + connect( dvdnavMouseAct, SIGNAL(triggered()), core, SLOT(dvdnavMouse()) ); +#endif + +} + +#if AUTODISABLE_ACTIONS +void BaseGui::setActionsEnabled(bool b) { + // Menu Play + playAct->setEnabled(b); + playOrPauseAct->setEnabled(b); + pauseAct->setEnabled(b); + pauseAndStepAct->setEnabled(b); + stopAct->setEnabled(b); + frameStepAct->setEnabled(b); + rewind1Act->setEnabled(b); + rewind2Act->setEnabled(b); + rewind3Act->setEnabled(b); + forward1Act->setEnabled(b); + forward2Act->setEnabled(b); + forward3Act->setEnabled(b); + //repeatAct->setEnabled(b); + gotoAct->setEnabled(b); + + // Menu Speed + normalSpeedAct->setEnabled(b); + halveSpeedAct->setEnabled(b); + doubleSpeedAct->setEnabled(b); + decSpeed10Act->setEnabled(b); + incSpeed10Act->setEnabled(b); + decSpeed4Act->setEnabled(b); + incSpeed4Act->setEnabled(b); + decSpeed1Act->setEnabled(b); + incSpeed1Act->setEnabled(b); + + // Menu Video + videoEqualizerAct->setEnabled(b); + screenshotAct->setEnabled(b); + flipAct->setEnabled(b); + mirrorAct->setEnabled(b); + postProcessingAct->setEnabled(b); + phaseAct->setEnabled(b); + deblockAct->setEnabled(b); + deringAct->setEnabled(b); + addNoiseAct->setEnabled(b); +#if NEW_ASPECT_CODE + addLetterboxAct->setEnabled(b); +#endif + upscaleAct->setEnabled(b); + + // Menu Audio + audioEqualizerAct->setEnabled(b); + muteAct->setEnabled(b); + decVolumeAct->setEnabled(b); + incVolumeAct->setEnabled(b); + decAudioDelayAct->setEnabled(b); + incAudioDelayAct->setEnabled(b); + extrastereoAct->setEnabled(b); + karaokeAct->setEnabled(b); + volnormAct->setEnabled(b); + loadAudioAct->setEnabled(b); + //unloadAudioAct->setEnabled(b); + + // Menu Subtitles + loadSubsAct->setEnabled(b); + //unloadSubsAct->setEnabled(b); + decSubDelayAct->setEnabled(b); + incSubDelayAct->setEnabled(b); + decSubPosAct->setEnabled(b); + incSubPosAct->setEnabled(b); + incSubStepAct->setEnabled(b); + decSubStepAct->setEnabled(b); + incSubScaleAct->setEnabled(b); + decSubScaleAct->setEnabled(b); + + // Actions not in menus +#if !USE_MULTIPLE_SHORTCUTS + decVolume2Act->setEnabled(b); + incVolume2Act->setEnabled(b); +#endif + decContrastAct->setEnabled(b); + incContrastAct->setEnabled(b); + decBrightnessAct->setEnabled(b); + incBrightnessAct->setEnabled(b); + decHueAct->setEnabled(b); + incHueAct->setEnabled(b); + decSaturationAct->setEnabled(b); + incSaturationAct->setEnabled(b); + decGammaAct->setEnabled(b); + incGammaAct->setEnabled(b); + nextVideoAct->setEnabled(b); + nextAudioAct->setEnabled(b); + nextSubtitleAct->setEnabled(b); + nextChapterAct->setEnabled(b); + prevChapterAct->setEnabled(b); + doubleSizeAct->setEnabled(b); + + // Moving and zoom + moveUpAct->setEnabled(b); + moveDownAct->setEnabled(b); + moveLeftAct->setEnabled(b); + moveRightAct->setEnabled(b); + incZoomAct->setEnabled(b); + decZoomAct->setEnabled(b); + resetZoomAct->setEnabled(b); + autoZoomAct->setEnabled(b); + autoZoom169Act->setEnabled(b); + autoZoom235Act->setEnabled(b); + + // Groups + denoiseGroup->setActionsEnabled(b); + sizeGroup->setActionsEnabled(b); + deinterlaceGroup->setActionsEnabled(b); + aspectGroup->setActionsEnabled(b); + rotateGroup->setActionsEnabled(b); +#if USE_ADAPTER + screenGroup->setActionsEnabled(b); +#endif + channelsGroup->setActionsEnabled(b); + stereoGroup->setActionsEnabled(b); +} + +void BaseGui::enableActionsOnPlaying() { + qDebug("BaseGui::enableActionsOnPlaying"); + + setActionsEnabled(true); + + // Screenshot option + bool valid_directory = ( (!pref->screenshot_directory.isEmpty()) && + (QFileInfo(pref->screenshot_directory).isDir()) ); + screenshotAct->setEnabled( valid_directory ); + + // Disable the compact action if not using video window + compactAct->setEnabled( panel->isVisible() ); + + // Enable or disable the audio equalizer + audioEqualizerAct->setEnabled(pref->use_audio_equalizer); + + // Disable audio actions if there's not audio track + if ((core->mdat.audios.numItems()==0) && (core->mset.external_audio.isEmpty())) { + audioEqualizerAct->setEnabled(false); + muteAct->setEnabled(false); + decVolumeAct->setEnabled(false); + incVolumeAct->setEnabled(false); + decAudioDelayAct->setEnabled(false); + incAudioDelayAct->setEnabled(false); + extrastereoAct->setEnabled(false); + karaokeAct->setEnabled(false); + volnormAct->setEnabled(false); + channelsGroup->setActionsEnabled(false); + stereoGroup->setActionsEnabled(false); + } + + // Disable video actions if it's an audio file + if (core->mdat.novideo) { + videoEqualizerAct->setEnabled(false); + screenshotAct->setEnabled(false); + flipAct->setEnabled(false); + mirrorAct->setEnabled(false); + postProcessingAct->setEnabled(false); + phaseAct->setEnabled(false); + deblockAct->setEnabled(false); + deringAct->setEnabled(false); + addNoiseAct->setEnabled(false); +#if NEW_ASPECT_CODE + addLetterboxAct->setEnabled(false); +#endif + upscaleAct->setEnabled(false); + doubleSizeAct->setEnabled(false); + + // Moving and zoom + moveUpAct->setEnabled(false); + moveDownAct->setEnabled(false); + moveLeftAct->setEnabled(false); + moveRightAct->setEnabled(false); + incZoomAct->setEnabled(false); + decZoomAct->setEnabled(false); + resetZoomAct->setEnabled(false); + autoZoomAct->setEnabled(false); + autoZoom169Act->setEnabled(false); + autoZoom235Act->setEnabled(false); + + denoiseGroup->setActionsEnabled(false); + sizeGroup->setActionsEnabled(false); + deinterlaceGroup->setActionsEnabled(false); + aspectGroup->setActionsEnabled(false); + rotateGroup->setActionsEnabled(false); +#if USE_ADAPTER + screenGroup->setActionsEnabled(false); +#endif + } + +#if USE_ADAPTER + screenGroup->setActionsEnabled(pref->vo.startsWith(OVERLAY_VO)); +#endif +} + +void BaseGui::disableActionsOnStop() { + qDebug("BaseGui::disableActionsOnStop"); + + setActionsEnabled(false); + + playAct->setEnabled(true); + playOrPauseAct->setEnabled(true); + stopAct->setEnabled(true); +} +#endif // AUTODISABLE_ACTIONS + +void BaseGui::retranslateStrings() { + setWindowIcon( Images::icon("logo", 64) ); + + // ACTIONS + + // Menu File + openFileAct->change( Images::icon("open"), tr("&File...") ); + openDirectoryAct->change( Images::icon("openfolder"), tr("D&irectory...") ); + openPlaylistAct->change( Images::icon("open_playlist"), tr("&Playlist...") ); + openVCDAct->change( Images::icon("vcd"), tr("V&CD") ); + openAudioCDAct->change( Images::icon("cdda"), tr("&Audio CD") ); + openDVDAct->change( Images::icon("dvd"), tr("&DVD from drive") ); + openDVDFolderAct->change( Images::icon("dvd_hd"), tr("D&VD from folder...") ); + openURLAct->change( Images::icon("url"), tr("&URL...") ); + exitAct->change( Images::icon("close"), tr("C&lose") ); + + // Menu Play + playAct->change( tr("P&lay") ); + if (qApp->isLeftToRight()) + playAct->setIcon( Images::icon("play") ); + else + playAct->setIcon( Images::flippedIcon("play") ); + + pauseAct->change( Images::icon("pause"), tr("&Pause")); + stopAct->change( Images::icon("stop"), tr("&Stop") ); + frameStepAct->change( Images::icon("frame_step"), tr("&Frame step") ); + + playOrPauseAct->change( tr("Play / Pause") ); + if (qApp->isLeftToRight()) + playOrPauseAct->setIcon( Images::icon("play_pause") ); + else + playOrPauseAct->setIcon( Images::flippedIcon("play_pause") ); + + pauseAndStepAct->change( Images::icon("pause"), tr("Pause / Frame step") ); + + setJumpTexts(); // Texts for rewind*Act and forward*Act + + repeatAct->change( Images::icon("repeat"), tr("&Repeat") ); + gotoAct->change( Images::icon("jumpto"), tr("&Jump to...") ); + + // Submenu speed + normalSpeedAct->change( tr("&Normal speed") ); + halveSpeedAct->change( tr("&Halve speed") ); + doubleSpeedAct->change( tr("&Double speed") ); + decSpeed10Act->change( tr("Speed &-10%") ); + incSpeed10Act->change( tr("Speed &+10%") ); + decSpeed4Act->change( tr("Speed -&4%") ); + incSpeed4Act->change( tr("&Speed +4%") ); + decSpeed1Act->change( tr("Speed -&1%") ); + incSpeed1Act->change( tr("S&peed +1%") ); + + // Menu Video + fullscreenAct->change( Images::icon("fullscreen"), tr("&Fullscreen") ); + compactAct->change( Images::icon("compact"), tr("&Compact mode") ); + videoEqualizerAct->change( Images::icon("equalizer"), tr("&Equalizer") ); + screenshotAct->change( Images::icon("screenshot"), tr("&Screenshot") ); + videoPreviewAct->change( Images::icon("video_preview"), tr("Pre&view...") ); + flipAct->change( Images::icon("flip"), tr("Flip i&mage") ); + mirrorAct->change( Images::icon("mirror"), tr("Mirr&or image") ); + + decZoomAct->change( tr("Zoom &-") ); + incZoomAct->change( tr("Zoom &+") ); + resetZoomAct->change( tr("&Reset") ); + autoZoomAct->change( tr("&Auto zoom") ); + autoZoom169Act->change( tr("Zoom for &16:9") ); + autoZoom235Act->change( tr("Zoom for &2.35:1") ); + moveLeftAct->change( tr("Move &left") ); + moveRightAct->change( tr("Move &right") ); + moveUpAct->change( tr("Move &up") ); + moveDownAct->change( tr("Move &down") ); + + // Submenu Filters + postProcessingAct->change( tr("&Postprocessing") ); + phaseAct->change( tr("&Autodetect phase") ); + deblockAct->change( tr("&Deblock") ); + deringAct->change( tr("De&ring") ); + addNoiseAct->change( tr("Add n&oise") ); +#if NEW_ASPECT_CODE + addLetterboxAct->change( Images::icon("letterbox"), tr("Add &black borders") ); +#endif + upscaleAct->change( Images::icon("upscaling"), tr("Soft&ware scaling") ); + + // Menu Audio + audioEqualizerAct->change( Images::icon("audio_equalizer"), tr("E&qualizer") ); + QIcon icset( Images::icon("volume") ); + icset.addPixmap( Images::icon("mute"), QIcon::Normal, QIcon::On ); + muteAct->change( icset, tr("&Mute") ); + decVolumeAct->change( Images::icon("audio_down"), tr("Volume &-") ); + incVolumeAct->change( Images::icon("audio_up"), tr("Volume &+") ); + decAudioDelayAct->change( Images::icon("delay_down"), tr("&Delay -") ); + incAudioDelayAct->change( Images::icon("delay_up"), tr("D&elay +") ); + loadAudioAct->change( Images::icon("open"), tr("&Load external file...") ); + unloadAudioAct->change( Images::icon("unload"), tr("U&nload") ); + + // Submenu Filters + extrastereoAct->change( tr("&Extrastereo") ); + karaokeAct->change( tr("&Karaoke") ); + volnormAct->change( tr("Volume &normalization") ); + + // Menu Subtitles + loadSubsAct->change( Images::icon("open"), tr("&Load...") ); + unloadSubsAct->change( Images::icon("unload"), tr("U&nload") ); + decSubDelayAct->change( Images::icon("delay_down"), tr("Delay &-") ); + incSubDelayAct->change( Images::icon("delay_up"), tr("Delay &+") ); + decSubPosAct->change( Images::icon("sub_up"), tr("&Up") ); + incSubPosAct->change( Images::icon("sub_down"), tr("&Down") ); + decSubScaleAct->change( Images::icon("dec_sub_scale"), tr("S&ize -") ); + incSubScaleAct->change( Images::icon("inc_sub_scale"), tr("Si&ze +") ); + decSubStepAct->change( Images::icon("dec_sub_step"), + tr("&Previous line in subtitles") ); + incSubStepAct->change( Images::icon("inc_sub_step"), + tr("N&ext line in subtitles") ); + useAssAct->change( Images::icon("use_ass_lib"), tr("Use SSA/&ASS library") ); + useClosedCaptionAct->change( Images::icon("closed_caption"), tr("Enable &closed caption") ); + useForcedSubsOnlyAct->change( Images::icon("forced_subs"), tr("&Forced subtitles only") ); + + showFindSubtitlesDialogAct->change( tr("Find subtitles on &OpenSubtitles.org...") ); + openUploadSubtitlesPageAct->change( tr("Upload su&btitles to OpenSubtitles.org...") ); + + // Menu Options + showPlaylistAct->change( Images::icon("playlist"), tr("&Playlist") ); + showPropertiesAct->change( Images::icon("info"), tr("View &info and properties...") ); + frameCounterAct->change( Images::icon("frame_counter"), + tr("&Show frame counter") ); + motionVectorsAct->change( Images::icon("motion_vectors"), + tr("Visualize &motion vectors") ); + showPreferencesAct->change( Images::icon("prefs"), tr("P&references") ); + + // Submenu Logs + showLogMplayerAct->change( "MPlayer" ); + showLogSmplayerAct->change( "SMPlayer" ); + + // Menu Help + showFAQAct->change( Images::icon("faq"), tr("&FAQ") ); + showCLOptionsAct->change( Images::icon("cl_help"), tr("&Command line options") ); + showTipsAct->change( Images::icon("tips"), tr("&Tips") ); + aboutQtAct->change( QPixmap(":/icons-png/qt.png"), tr("About &Qt") ); + aboutThisAct->change( Images::icon("logo_small"), tr("About &SMPlayer") ); + + // Playlist + playNextAct->change( tr("&Next") ); + playPrevAct->change( tr("Pre&vious") ); + + if (qApp->isLeftToRight()) { + playNextAct->setIcon( Images::icon("next") ); + playPrevAct->setIcon( Images::icon("previous") ); + } else { + playNextAct->setIcon( Images::flippedIcon("next") ); + playPrevAct->setIcon( Images::flippedIcon("previous") ); + } + + + // Actions not in menus or buttons + // Volume 2 +#if !USE_MULTIPLE_SHORTCUTS + decVolume2Act->change( tr("Dec volume (2)") ); + incVolume2Act->change( tr("Inc volume (2)") ); +#endif + // Exit fullscreen + exitFullscreenAct->change( tr("Exit fullscreen") ); + + nextOSDAct->change( tr("OSD - Next level") ); + decContrastAct->change( tr("Dec contrast") ); + incContrastAct->change( tr("Inc contrast") ); + decBrightnessAct->change( tr("Dec brightness") ); + incBrightnessAct->change( tr("Inc brightness") ); + decHueAct->change( tr("Dec hue") ); + incHueAct->change( tr("Inc hue") ); + decSaturationAct->change( tr("Dec saturation") ); + incSaturationAct->change( tr("Inc saturation") ); + decGammaAct->change( tr("Dec gamma") ); + incGammaAct->change( tr("Inc gamma") ); + nextVideoAct->change( tr("Next video") ); + nextAudioAct->change( tr("Next audio") ); + nextSubtitleAct->change( tr("Next subtitle") ); + nextChapterAct->change( tr("Next chapter") ); + prevChapterAct->change( tr("Previous chapter") ); + doubleSizeAct->change( tr("&Toggle double size") ); + resetVideoEqualizerAct->change( tr("Reset video equalizer") ); + resetAudioEqualizerAct->change( tr("Reset audio equalizer") ); + showContextMenuAct->change( tr("Show context menu") ); +#if NEW_ASPECT_CODE + nextAspectAct->change( tr("Next aspect ratio") ); +#endif + + // Action groups + osdNoneAct->change( tr("&Disabled") ); + osdSeekAct->change( tr("&Seek bar") ); + osdTimerAct->change( tr("&Time") ); + osdTotalAct->change( tr("Time + T&otal time") ); + + + // MENUS + openMenu->menuAction()->setText( tr("&Open") ); + playMenu->menuAction()->setText( tr("&Play") ); + videoMenu->menuAction()->setText( tr("&Video") ); + audioMenu->menuAction()->setText( tr("&Audio") ); + subtitlesMenu->menuAction()->setText( tr("&Subtitles") ); + browseMenu->menuAction()->setText( tr("&Browse") ); + optionsMenu->menuAction()->setText( tr("Op&tions") ); + helpMenu->menuAction()->setText( tr("&Help") ); + + /* + openMenuAct->setIcon( Images::icon("open_menu") ); + playMenuAct->setIcon( Images::icon("play_menu") ); + videoMenuAct->setIcon( Images::icon("video_menu") ); + audioMenuAct->setIcon( Images::icon("audio_menu") ); + subtitlesMenuAct->setIcon( Images::icon("subtitles_menu") ); + browseMenuAct->setIcon( Images::icon("browse_menu") ); + optionsMenuAct->setIcon( Images::icon("options_menu") ); + helpMenuAct->setIcon( Images::icon("help_menu") ); + */ + + // Menu Open + recentfiles_menu->menuAction()->setText( tr("&Recent files") ); + recentfiles_menu->menuAction()->setIcon( Images::icon("recents") ); + clearRecentsAct->change( Images::icon("delete"), tr("&Clear") ); + + // Menu Play + speed_menu->menuAction()->setText( tr("Sp&eed") ); + speed_menu->menuAction()->setIcon( Images::icon("speed") ); + + // Menu Video + videotrack_menu->menuAction()->setText( tr("&Track", "video") ); + videotrack_menu->menuAction()->setIcon( Images::icon("video_track") ); + + videosize_menu->menuAction()->setText( tr("Si&ze") ); + videosize_menu->menuAction()->setIcon( Images::icon("video_size") ); + + panscan_menu->menuAction()->setText( tr("&Pan && scan") ); + panscan_menu->menuAction()->setIcon( Images::icon("panscan") ); + + aspect_menu->menuAction()->setText( tr("&Aspect ratio") ); + aspect_menu->menuAction()->setIcon( Images::icon("aspect") ); + + deinterlace_menu->menuAction()->setText( tr("&Deinterlace") ); + deinterlace_menu->menuAction()->setIcon( Images::icon("deinterlace") ); + + videofilter_menu->menuAction()->setText( tr("F&ilters") ); + videofilter_menu->menuAction()->setIcon( Images::icon("video_filters") ); + + rotate_menu->menuAction()->setText( tr("&Rotate") ); + rotate_menu->menuAction()->setIcon( Images::icon("rotate") ); + + ontop_menu->menuAction()->setText( tr("S&tay on top") ); + ontop_menu->menuAction()->setIcon( Images::icon("ontop") ); + +#if USE_ADAPTER + screen_menu->menuAction()->setText( tr("Scree&n") ); + screen_menu->menuAction()->setIcon( Images::icon("screen") ); +#endif + + /* + denoise_menu->menuAction()->setText( tr("De&noise") ); + denoise_menu->menuAction()->setIcon( Images::icon("denoise") ); + */ + + aspectDetectAct->change( tr("&Auto") ); + aspect43Act->change( "&4:3" ); + aspect54Act->change( "&5:4" ); + aspect149Act->change( "&14:9" ); + aspect169Act->change( "16:&9" ); + aspect1610Act->change( "1&6:10" ); + aspect235Act->change( "&2.35:1" ); +#if NEW_ASPECT_CODE + aspect11Act->change( "1&:1" ); + aspectNoneAct->change( tr("&Disabled") ); +#endif + +#if !NEW_ASPECT_CODE + aspect43LetterAct->change( tr("4:3 &Letterbox") ); + aspect169LetterAct->change( tr("16:9 L&etterbox") ); + aspect43PanscanAct->change( tr("4:3 &Panscan") ); + aspect43To169Act->change( tr("4:3 &to 16:9") ); +#endif + + deinterlaceNoneAct->change( tr("&None") ); + deinterlaceL5Act->change( tr("&Lowpass5") ); + deinterlaceYadif0Act->change( tr("&Yadif (normal)") ); + deinterlaceYadif1Act->change( tr("Y&adif (double framerate)") ); + deinterlaceLBAct->change( tr("Linear &Blend") ); + deinterlaceKernAct->change( tr("&Kerndeint") ); + + denoiseNoneAct->change( tr("Denoise o&ff") ); + denoiseNormalAct->change( tr("Denoise nor&mal") ); + denoiseSoftAct->change( tr("Denoise &soft") ); + + rotateNoneAct->change( tr("&Off") ); + rotateClockwiseFlipAct->change( tr("&Rotate by 90 degrees clockwise and flip") ); + rotateClockwiseAct->change( tr("Rotate by 90 degrees &clockwise") ); + rotateCounterclockwiseAct->change( tr("Rotate by 90 degrees counterclock&wise") ); + rotateCounterclockwiseFlipAct->change( tr("Rotate by 90 degrees counterclockwise and &flip") ); + + onTopAlwaysAct->change( tr("&Always") ); + onTopNeverAct->change( tr("&Never") ); + onTopWhilePlayingAct->change( tr("While &playing") ); + +#if USE_ADAPTER + screenDefaultAct->change( tr("&Default") ); +#endif + + // Menu Audio + audiotrack_menu->menuAction()->setText( tr("&Track", "audio") ); + audiotrack_menu->menuAction()->setIcon( Images::icon("audio_track") ); + + audiofilter_menu->menuAction()->setText( tr("&Filters") ); + audiofilter_menu->menuAction()->setIcon( Images::icon("audio_filters") ); + + audiochannels_menu->menuAction()->setText( tr("&Channels") ); + audiochannels_menu->menuAction()->setIcon( Images::icon("audio_channels") ); + + stereomode_menu->menuAction()->setText( tr("&Stereo mode") ); + stereomode_menu->menuAction()->setIcon( Images::icon("stereo_mode") ); + + /* channelsDefaultAct->change( tr("&Default") ); */ + channelsStereoAct->change( tr("&Stereo") ); + channelsSurroundAct->change( tr("&4.0 Surround") ); + channelsFull51Act->change( tr("&5.1 Surround") ); + + stereoAct->change( tr("&Stereo") ); + leftChannelAct->change( tr("&Left channel") ); + rightChannelAct->change( tr("&Right channel") ); + + // Menu Subtitle + subtitlestrack_menu->menuAction()->setText( tr("&Select") ); + subtitlestrack_menu->menuAction()->setIcon( Images::icon("sub") ); + + // Menu Browse + titles_menu->menuAction()->setText( tr("&Title") ); + titles_menu->menuAction()->setIcon( Images::icon("title") ); + + chapters_menu->menuAction()->setText( tr("&Chapter") ); + chapters_menu->menuAction()->setIcon( Images::icon("chapter") ); + + angles_menu->menuAction()->setText( tr("&Angle") ); + angles_menu->menuAction()->setIcon( Images::icon("angle") ); + + // Menu Options + osd_menu->menuAction()->setText( tr("&OSD") ); + osd_menu->menuAction()->setIcon( Images::icon("osd") ); + + logs_menu->menuAction()->setText( tr("&View logs") ); + logs_menu->menuAction()->setIcon( Images::icon("logs") ); + + + // To be sure that the "" string is translated + initializeMenus(); + + // Other things + mplayer_log_window->setWindowTitle( tr("SMPlayer - mplayer log") ); + smplayer_log_window->setWindowTitle( tr("SMPlayer - smplayer log") ); + + updateRecents(); + updateWidgets(); + + // Update actions view in preferences + // It has to be done, here. The actions are translated after the + // preferences dialog. + if (pref_dialog) pref_dialog->mod_input()->actions_editor->updateView(); +} + +void BaseGui::setJumpTexts() { + rewind1Act->change( tr("-%1").arg(Helper::timeForJumps(pref->seeking1)) ); + rewind2Act->change( tr("-%1").arg(Helper::timeForJumps(pref->seeking2)) ); + rewind3Act->change( tr("-%1").arg(Helper::timeForJumps(pref->seeking3)) ); + + forward1Act->change( tr("+%1").arg(Helper::timeForJumps(pref->seeking1)) ); + forward2Act->change( tr("+%1").arg(Helper::timeForJumps(pref->seeking2)) ); + forward3Act->change( tr("+%1").arg(Helper::timeForJumps(pref->seeking3)) ); + + if (qApp->isLeftToRight()) { + rewind1Act->setIcon( Images::icon("rewind10s") ); + rewind2Act->setIcon( Images::icon("rewind1m") ); + rewind3Act->setIcon( Images::icon("rewind10m") ); + + forward1Act->setIcon( Images::icon("forward10s") ); + forward2Act->setIcon( Images::icon("forward1m") ); + forward3Act->setIcon( Images::icon("forward10m") ); + } else { + rewind1Act->setIcon( Images::flippedIcon("rewind10s") ); + rewind2Act->setIcon( Images::flippedIcon("rewind1m") ); + rewind3Act->setIcon( Images::flippedIcon("rewind10m") ); + + forward1Act->setIcon( Images::flippedIcon("forward10s") ); + forward2Act->setIcon( Images::flippedIcon("forward1m") ); + forward3Act->setIcon( Images::flippedIcon("forward10m") ); + } +} + +void BaseGui::setWindowCaption(const QString & title) { + setWindowTitle(title); +} + +void BaseGui::createCore() { + core = new Core( mplayerwindow, this ); + + connect( core, SIGNAL(menusNeedInitialize()), + this, SLOT(initializeMenus()) ); + connect( core, SIGNAL(widgetsNeedUpdate()), + this, SLOT(updateWidgets()) ); + connect( core, SIGNAL(videoEqualizerNeedsUpdate()), + this, SLOT(updateVideoEqualizer()) ); + + connect( core, SIGNAL(audioEqualizerNeedsUpdate()), + this, SLOT(updateAudioEqualizer()) ); + + connect( core, SIGNAL(showFrame(int)), + this, SIGNAL(frameChanged(int)) ); + + connect( core, SIGNAL(showTime(double)), + this, SLOT(gotCurrentTime(double)) ); + + connect( core, SIGNAL(needResize(int, int)), + this, SLOT(resizeWindow(int,int)) ); + connect( core, SIGNAL(showMessage(QString)), + this, SLOT(displayMessage(QString)) ); + connect( core, SIGNAL(stateChanged(Core::State)), + this, SLOT(displayState(Core::State)) ); + connect( core, SIGNAL(stateChanged(Core::State)), + this, SLOT(checkStayOnTop(Core::State)), Qt::QueuedConnection ); + + connect( core, SIGNAL(mediaStartPlay()), + this, SLOT(enterFullscreenOnPlay()) ); + connect( core, SIGNAL(mediaStoppedByUser()), + this, SLOT(exitFullscreenOnStop()) ); + + connect( core, SIGNAL(mediaLoaded()), + this, SLOT(enableActionsOnPlaying()) ); +#if NOTIFY_SUB_CHANGES + connect( core, SIGNAL(audioTracksChanged()), + this, SLOT(enableActionsOnPlaying()) ); +#endif + connect( core, SIGNAL(mediaFinished()), + this, SLOT(disableActionsOnStop()) ); + connect( core, SIGNAL(mediaStoppedByUser()), + this, SLOT(disableActionsOnStop()) ); + + connect( core, SIGNAL(mediaStartPlay()), + this, SLOT(newMediaLoaded()), Qt::QueuedConnection ); + connect( core, SIGNAL(mediaInfoChanged()), + this, SLOT(updateMediaInfo()) ); + + connect( core, SIGNAL(mediaStartPlay()), + this, SLOT(checkPendingActionsToRun()), Qt::QueuedConnection ); +#if REPORT_OLD_MPLAYER + connect( core, SIGNAL(mediaStartPlay()), + this, SLOT(checkMplayerVersion()), Qt::QueuedConnection ); +#endif + connect( core, SIGNAL(failedToParseMplayerVersion(QString)), + this, SLOT(askForMplayerVersion(QString)) ); + + connect( core, SIGNAL(mplayerFailed(QProcess::ProcessError)), + this, SLOT(showErrorFromMplayer(QProcess::ProcessError)) ); + + connect( core, SIGNAL(mplayerFinishedWithError(int)), + this, SLOT(showExitCodeFromMplayer(int)) ); + + // Hide mplayer window + connect( core, SIGNAL(noVideo()), + this, SLOT(hidePanel()) ); + + // Log mplayer output + connect( core, SIGNAL(aboutToStartPlaying()), + this, SLOT(clearMplayerLog()) ); + connect( core, SIGNAL(logLineAvailable(QString)), + this, SLOT(recordMplayerLog(QString)) ); + + connect( core, SIGNAL(mediaLoaded()), + this, SLOT(autosaveMplayerLog()) ); +} + +void BaseGui::createMplayerWindow() { + mplayerwindow = new MplayerWindow( panel ); + mplayerwindow->setObjectName("mplayerwindow"); +#if USE_COLORKEY + mplayerwindow->setColorKey( pref->color_key ); +#endif + mplayerwindow->allowVideoMovement( pref->allow_video_movement ); + + QHBoxLayout * layout = new QHBoxLayout; + layout->setSpacing(0); + layout->setMargin(0); + layout->addWidget(mplayerwindow); + panel->setLayout(layout); + + // mplayerwindow + /* + connect( mplayerwindow, SIGNAL(rightButtonReleased(QPoint)), + this, SLOT(showPopupMenu(QPoint)) ); + */ + + // mplayerwindow mouse events + connect( mplayerwindow, SIGNAL(doubleClicked()), + this, SLOT(doubleClickFunction()) ); + connect( mplayerwindow, SIGNAL(leftClicked()), + this, SLOT(leftClickFunction()) ); + connect( mplayerwindow, SIGNAL(rightClicked()), + this, SLOT(rightClickFunction()) ); + connect( mplayerwindow, SIGNAL(middleClicked()), + this, SLOT(middleClickFunction()) ); + connect( mplayerwindow, SIGNAL(xbutton1Clicked()), + this, SLOT(xbutton1ClickFunction()) ); + connect( mplayerwindow, SIGNAL(xbutton2Clicked()), + this, SLOT(xbutton2ClickFunction()) ); + connect( mplayerwindow, SIGNAL(mouseMoved(QPoint)), + this, SLOT(checkMousePos(QPoint)) ); +} + +void BaseGui::createVideoEqualizer() { + // Equalizer + video_equalizer = new VideoEqualizer(this); + + connect( video_equalizer->contrast, SIGNAL(valueChanged(int)), + core, SLOT(setContrast(int)) ); + connect( video_equalizer->brightness, SIGNAL(valueChanged(int)), + core, SLOT(setBrightness(int)) ); + connect( video_equalizer->hue, SIGNAL(valueChanged(int)), + core, SLOT(setHue(int)) ); + connect( video_equalizer->saturation, SIGNAL(valueChanged(int)), + core, SLOT(setSaturation(int)) ); + connect( video_equalizer->gamma, SIGNAL(valueChanged(int)), + core, SLOT(setGamma(int)) ); + connect( video_equalizer, SIGNAL(visibilityChanged()), + this, SLOT(updateWidgets()) ); +} + +void BaseGui::createAudioEqualizer() { + // Audio Equalizer + audio_equalizer = new AudioEqualizer(this); + + connect( audio_equalizer->eq[0], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq0(int)) ); + connect( audio_equalizer->eq[1], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq1(int)) ); + connect( audio_equalizer->eq[2], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq2(int)) ); + connect( audio_equalizer->eq[3], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq3(int)) ); + connect( audio_equalizer->eq[4], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq4(int)) ); + connect( audio_equalizer->eq[5], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq5(int)) ); + connect( audio_equalizer->eq[6], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq6(int)) ); + connect( audio_equalizer->eq[7], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq7(int)) ); + connect( audio_equalizer->eq[8], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq8(int)) ); + connect( audio_equalizer->eq[9], SIGNAL(valueChanged(int)), + core, SLOT(setAudioEq9(int)) ); + + connect( audio_equalizer, SIGNAL(applyClicked(AudioEqualizerList)), + core, SLOT(setAudioAudioEqualizerRestart(AudioEqualizerList)) ); + + connect( audio_equalizer, SIGNAL(visibilityChanged()), + this, SLOT(updateWidgets()) ); +} + +void BaseGui::createPlaylist() { +#if DOCK_PLAYLIST + playlist = new Playlist(core, this, 0); +#else + //playlist = new Playlist(core, this, "playlist"); + playlist = new Playlist(core, 0); +#endif + + /* + connect( playlist, SIGNAL(playlistEnded()), + this, SLOT(exitFullscreenOnStop()) ); + */ + connect( playlist, SIGNAL(playlistEnded()), + this, SLOT(playlistHasFinished()) ); + /* + connect( playlist, SIGNAL(visibilityChanged()), + this, SLOT(playlistVisibilityChanged()) ); + */ + +} + +void BaseGui::createPanel() { + panel = new QWidget( this ); + panel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); + panel->setMinimumSize( QSize(1,1) ); + panel->setFocusPolicy( Qt::StrongFocus ); + + // panel + panel->setAutoFillBackground(TRUE); + ColorUtils::setBackgroundColor( panel, QColor(0,0,0) ); +} + +void BaseGui::createPreferencesDialog() { + pref_dialog = new PreferencesDialog(this); + pref_dialog->setModal(false); + /* pref_dialog->mod_input()->setActionsList( actions_list ); */ + connect( pref_dialog, SIGNAL(applied()), + this, SLOT(applyNewPreferences()) ); +} + +void BaseGui::createFilePropertiesDialog() { + file_dialog = new FilePropertiesDialog(this); + file_dialog->setModal(false); + connect( file_dialog, SIGNAL(applied()), + this, SLOT(applyFileProperties()) ); +} + + +void BaseGui::createMenus() { + // MENUS + openMenu = menuBar()->addMenu("Open"); + playMenu = menuBar()->addMenu("Play"); + videoMenu = menuBar()->addMenu("Video"); + audioMenu = menuBar()->addMenu("Audio"); + subtitlesMenu = menuBar()->addMenu("Subtitles"); + browseMenu = menuBar()->addMenu("Browwse"); + optionsMenu = menuBar()->addMenu("Options"); + helpMenu = menuBar()->addMenu("Help"); + + // OPEN MENU + openMenu->addAction(openFileAct); + + recentfiles_menu = new QMenu(this); + recentfiles_menu->addAction( clearRecentsAct ); + recentfiles_menu->addSeparator(); + + openMenu->addMenu( recentfiles_menu ); + + openMenu->addAction(openDirectoryAct); + openMenu->addAction(openPlaylistAct); + openMenu->addAction(openDVDAct); + openMenu->addAction(openDVDFolderAct); + openMenu->addAction(openVCDAct); + openMenu->addAction(openAudioCDAct); + openMenu->addAction(openURLAct); + + openMenu->addSeparator(); + openMenu->addAction(exitAct); + + // PLAY MENU + playMenu->addAction(playAct); + playMenu->addAction(pauseAct); + /* playMenu->addAction(playOrPauseAct); */ + playMenu->addAction(stopAct); + playMenu->addAction(frameStepAct); + playMenu->addSeparator(); + playMenu->addAction(rewind1Act); + playMenu->addAction(forward1Act); + playMenu->addAction(rewind2Act); + playMenu->addAction(forward2Act); + playMenu->addAction(rewind3Act); + playMenu->addAction(forward3Act); + playMenu->addSeparator(); + + // Speed submenu + speed_menu = new QMenu(this); + speed_menu->addAction(normalSpeedAct); + speed_menu->addSeparator(); + speed_menu->addAction(halveSpeedAct); + speed_menu->addAction(doubleSpeedAct); + speed_menu->addSeparator(); + speed_menu->addAction(decSpeed10Act); + speed_menu->addAction(incSpeed10Act); + speed_menu->addSeparator(); + speed_menu->addAction(decSpeed4Act); + speed_menu->addAction(incSpeed4Act); + speed_menu->addSeparator(); + speed_menu->addAction(decSpeed1Act); + speed_menu->addAction(incSpeed1Act); + + playMenu->addMenu(speed_menu); + + playMenu->addAction(repeatAct); + playMenu->addSeparator(); + playMenu->addAction(gotoAct); + playMenu->addSeparator(); + playMenu->addAction(playPrevAct); + playMenu->addAction(playNextAct); + + // VIDEO MENU + videotrack_menu = new QMenu(this); + + videoMenu->addMenu(videotrack_menu); + + videoMenu->addAction(fullscreenAct); + videoMenu->addAction(compactAct); + +#if USE_ADAPTER + // Screen submenu + screen_menu = new QMenu(this); + screen_menu->addActions( screenGroup->actions() ); + videoMenu->addMenu(screen_menu); +#endif + + // Size submenu + videosize_menu = new QMenu(this); + videosize_menu->addActions( sizeGroup->actions() ); + videosize_menu->addSeparator(); + videosize_menu->addAction(doubleSizeAct); + videoMenu->addMenu(videosize_menu); + + // Panscan submenu + panscan_menu = new QMenu(this); + panscan_menu->addAction(resetZoomAct); + panscan_menu->addSeparator(); + panscan_menu->addAction(autoZoomAct); + panscan_menu->addAction(autoZoom169Act); + panscan_menu->addAction(autoZoom235Act); + panscan_menu->addSeparator(); + panscan_menu->addAction(decZoomAct); + panscan_menu->addAction(incZoomAct); + panscan_menu->addSeparator(); + panscan_menu->addAction(moveLeftAct); + panscan_menu->addAction(moveRightAct); + panscan_menu->addAction(moveUpAct); + panscan_menu->addAction(moveDownAct); + + videoMenu->addMenu(panscan_menu); + + // Aspect submenu + aspect_menu = new QMenu(this); + aspect_menu->addActions( aspectGroup->actions() ); + + videoMenu->addMenu(aspect_menu); + + // Deinterlace submenu + deinterlace_menu = new QMenu(this); + deinterlace_menu->addActions( deinterlaceGroup->actions() ); + + videoMenu->addMenu(deinterlace_menu); + + // Video filter submenu + videofilter_menu = new QMenu(this); + videofilter_menu->addAction(postProcessingAct); + videofilter_menu->addAction(phaseAct); + videofilter_menu->addAction(deblockAct); + videofilter_menu->addAction(deringAct); + videofilter_menu->addAction(addNoiseAct); +#if NEW_ASPECT_CODE + videofilter_menu->addAction(addLetterboxAct); +#endif + videofilter_menu->addAction(upscaleAct); + videofilter_menu->addSeparator(); + videofilter_menu->addActions(denoiseGroup->actions()); + + videoMenu->addMenu(videofilter_menu); + + // Denoise submenu + /* + denoise_menu = new QMenu(this); + denoise_menu->addActions(denoiseGroup->actions()); + videoMenu->addMenu(denoise_menu); + */ + + // Rotate submenu + rotate_menu = new QMenu(this); + rotate_menu->addActions(rotateGroup->actions()); + + videoMenu->addMenu(rotate_menu); + + videoMenu->addAction(flipAct); + videoMenu->addAction(mirrorAct); + videoMenu->addSeparator(); + videoMenu->addAction(videoEqualizerAct); + videoMenu->addAction(screenshotAct); + + // Ontop submenu + ontop_menu = new QMenu(this); + ontop_menu->addActions(onTopActionGroup->actions()); + + videoMenu->addMenu(ontop_menu); + + videoMenu->addSeparator(); + videoMenu->addAction(videoPreviewAct); + + + // AUDIO MENU + + // Audio track submenu + audiotrack_menu = new QMenu(this); + + audioMenu->addMenu(audiotrack_menu); + + audioMenu->addAction(loadAudioAct); + audioMenu->addAction(unloadAudioAct); + + // Filter submenu + audiofilter_menu = new QMenu(this); + audiofilter_menu->addAction(extrastereoAct); + audiofilter_menu->addAction(karaokeAct); + audiofilter_menu->addAction(volnormAct); + + audioMenu->addMenu(audiofilter_menu); + + // Audio channels submenu + audiochannels_menu = new QMenu(this); + audiochannels_menu->addActions( channelsGroup->actions() ); + + audioMenu->addMenu(audiochannels_menu); + + // Stereo mode submenu + stereomode_menu = new QMenu(this); + stereomode_menu->addActions( stereoGroup->actions() ); + + audioMenu->addMenu(stereomode_menu); + audioMenu->addAction(audioEqualizerAct); + audioMenu->addSeparator(); + audioMenu->addAction(muteAct); + audioMenu->addSeparator(); + audioMenu->addAction(decVolumeAct); + audioMenu->addAction(incVolumeAct); + audioMenu->addSeparator(); + audioMenu->addAction(decAudioDelayAct); + audioMenu->addAction(incAudioDelayAct); + + + // SUBTITLES MENU + // Track submenu + subtitlestrack_menu = new QMenu(this); + + subtitlesMenu->addMenu(subtitlestrack_menu); + + subtitlesMenu->addAction(loadSubsAct); + subtitlesMenu->addAction(unloadSubsAct); + subtitlesMenu->addSeparator(); + subtitlesMenu->addAction(decSubDelayAct); + subtitlesMenu->addAction(incSubDelayAct); + subtitlesMenu->addSeparator(); + subtitlesMenu->addAction(decSubPosAct); + subtitlesMenu->addAction(incSubPosAct); + subtitlesMenu->addSeparator(); + subtitlesMenu->addAction(decSubScaleAct); + subtitlesMenu->addAction(incSubScaleAct); + subtitlesMenu->addSeparator(); + subtitlesMenu->addAction(decSubStepAct); + subtitlesMenu->addAction(incSubStepAct); + subtitlesMenu->addSeparator(); + subtitlesMenu->addAction(useClosedCaptionAct); + subtitlesMenu->addAction(useForcedSubsOnlyAct); + subtitlesMenu->addSeparator(); + subtitlesMenu->addAction(useAssAct); + subtitlesMenu->addSeparator(); //turbos + subtitlesMenu->addAction(showFindSubtitlesDialogAct); + subtitlesMenu->addAction(openUploadSubtitlesPageAct); //turbos + + // BROWSE MENU + // Titles submenu + titles_menu = new QMenu(this); + + browseMenu->addMenu(titles_menu); + + // Chapters submenu + chapters_menu = new QMenu(this); + + browseMenu->addMenu(chapters_menu); + + // Angles submenu + angles_menu = new QMenu(this); + + browseMenu->addMenu(angles_menu); + + // OPTIONS MENU + optionsMenu->addAction(showPropertiesAct); + optionsMenu->addAction(showPlaylistAct); + optionsMenu->addAction(frameCounterAct); + optionsMenu->addAction(motionVectorsAct); + + // OSD submenu + osd_menu = new QMenu(this); + osd_menu->addActions(osdGroup->actions()); + + optionsMenu->addMenu(osd_menu); + + // Logs submenu + logs_menu = new QMenu(this); + logs_menu->addAction(showLogMplayerAct); + logs_menu->addAction(showLogSmplayerAct); + + optionsMenu->addMenu(logs_menu); + + optionsMenu->addAction(showPreferencesAct); + + + // HELP MENU + helpMenu->addAction(showFAQAct); + helpMenu->addAction(showCLOptionsAct); + helpMenu->addAction(showTipsAct); + helpMenu->addSeparator(); + helpMenu->addAction(aboutQtAct); + helpMenu->addAction(aboutThisAct); + + // POPUP MENU + if (!popup) + popup = new QMenu(this); + else + popup->clear(); + + popup->addMenu( openMenu ); + popup->addMenu( playMenu ); + popup->addMenu( videoMenu ); + popup->addMenu( audioMenu ); + popup->addMenu( subtitlesMenu ); + popup->addMenu( browseMenu ); + popup->addMenu( optionsMenu ); + + // let's show something, even a entry + initializeMenus(); +} + +/* +void BaseGui::closeEvent( QCloseEvent * e ) { + qDebug("BaseGui::closeEvent"); + + qDebug("mplayer_log_window: %d x %d", mplayer_log_window->width(), mplayer_log_window->height() ); + qDebug("smplayer_log_window: %d x %d", smplayer_log_window->width(), smplayer_log_window->height() ); + + mplayer_log_window->close(); + smplayer_log_window->close(); + playlist->close(); + equalizer->close(); + + core->stop(); + e->accept(); +} +*/ + + +void BaseGui::closeWindow() { + qDebug("BaseGui::closeWindow"); + + core->stop(); + //qApp->quit(); + emit quitSolicited(); +} + +void BaseGui::showPlaylist() { + showPlaylist( !playlist->isVisible() ); +} + +void BaseGui::showPlaylist(bool b) { + if ( !b ) { + playlist->hide(); + } else { + exitFullscreenIfNeeded(); + playlist->show(); + } + //updateWidgets(); +} + +void BaseGui::showVideoEqualizer() { + showVideoEqualizer( !video_equalizer->isVisible() ); +} + +void BaseGui::showVideoEqualizer(bool b) { + if (!b) { + video_equalizer->hide(); + } else { + // Exit fullscreen, otherwise dialog is not visible + exitFullscreenIfNeeded(); + video_equalizer->show(); + } + updateWidgets(); +} + +void BaseGui::showAudioEqualizer() { + showAudioEqualizer( !audio_equalizer->isVisible() ); +} + +void BaseGui::showAudioEqualizer(bool b) { + if (!b) { + audio_equalizer->hide(); + } else { + // Exit fullscreen, otherwise dialog is not visible + exitFullscreenIfNeeded(); + audio_equalizer->show(); + } + updateWidgets(); +} + +void BaseGui::showPreferencesDialog() { + qDebug("BaseGui::showPreferencesDialog"); + + exitFullscreenIfNeeded(); + + if (!pref_dialog) { + createPreferencesDialog(); + } + + pref_dialog->setData(pref); + + pref_dialog->mod_input()->actions_editor->clear(); + pref_dialog->mod_input()->actions_editor->addActions(this); +#if !DOCK_PLAYLIST + pref_dialog->mod_input()->actions_editor->addActions(playlist); +#endif + pref_dialog->show(); +} + +// The user has pressed OK in preferences dialog +void BaseGui::applyNewPreferences() { + qDebug("BaseGui::applyNewPreferences"); + + bool need_update_language = false; + + pref_dialog->getData(pref); + + if (!pref->default_font.isEmpty()) { + QFont f; + f.fromString( pref->default_font ); + qApp->setFont(f); + } + +#ifndef NO_USE_INI_FILES + PrefGeneral *_general = pref_dialog->mod_general(); + if (_general->fileSettingsMethodChanged()) { + core->changeFileSettingsMethod(pref->file_settings_method); + } +#endif + + PrefInterface *_interface = pref_dialog->mod_interface(); + if (_interface->recentsChanged()) { + updateRecents(); + } + if (_interface->languageChanged()) need_update_language = true; + + if (_interface->iconsetChanged()) { + need_update_language = true; + // Stylesheet +#if ALLOW_CHANGE_STYLESHEET + changeStyleSheet(pref->iconset); +#endif + } + + if (!pref->use_single_instance && server->isListening()) { + server->close(); + qDebug("BaseGui::applyNewPreferences: server closed"); + } + else + { + bool server_requires_restart = _interface->serverPortChanged(); + if (pref->use_single_instance && !server->isListening()) + server_requires_restart=true; + + if (server_requires_restart) { + server->close(); + int port = 0; + if (!pref->use_autoport) port = pref->connection_port; + if (server->listen(port)) { + pref->autoport = server->serverPort(); + qDebug("BaseGui::applyNewPreferences: server running on port %d", pref->autoport); + } else { + qWarning("BaseGui::applyNewPreferences: server couldn't be started"); + } + } + } + + PrefAdvanced *advanced = pref_dialog->mod_advanced(); +#if REPAINT_BACKGROUND_OPTION + if (advanced->repaintVideoBackgroundChanged()) { + mplayerwindow->videoLayer()->setRepaintBackground(pref->repaint_video_background); + } +#endif +#if USE_COLORKEY + if (advanced->colorkeyChanged()) { + mplayerwindow->setColorKey( pref->color_key ); + } +#endif + if (advanced->monitorAspectChanged()) { + mplayerwindow->setMonitorAspect( pref->monitor_aspect_double() ); + } + + if (advanced->proxyChanged()) { + if (find_subs_dialog) find_subs_dialog->setProxy( userProxy() ); + } + + if (need_update_language) { + translator->load(pref->language); + } + + setJumpTexts(); // Update texts in menus + updateWidgets(); // Update the screenshot action + +#if STYLE_SWITCHING + if (_interface->styleChanged()) { + qDebug( "selected style: '%s'", pref->style.toUtf8().data() ); + if ( !pref->style.isEmpty()) { + qApp->setStyle( pref->style ); + } else { + qDebug("setting default style: '%s'", default_style.toUtf8().data() ); + qApp->setStyle( default_style ); + } + } +#endif + + // Restart the video if needed + if (pref_dialog->requiresRestart()) + core->restart(); + + // Update actions + pref_dialog->mod_input()->actions_editor->applyChanges(); + saveActions(); + +#ifndef NO_USE_INI_FILES + pref->save(); +#endif +} + + +void BaseGui::showFilePropertiesDialog() { + qDebug("BaseGui::showFilePropertiesDialog"); + + exitFullscreenIfNeeded(); + + if (!file_dialog) { + createFilePropertiesDialog(); + } + + setDataToFileProperties(); + + file_dialog->show(); +} + +void BaseGui::setDataToFileProperties() { + // Save a copy of the original values + if (core->mset.original_demuxer.isEmpty()) + core->mset.original_demuxer = core->mdat.demuxer; + + if (core->mset.original_video_codec.isEmpty()) + core->mset.original_video_codec = core->mdat.video_codec; + + if (core->mset.original_audio_codec.isEmpty()) + core->mset.original_audio_codec = core->mdat.audio_codec; + + QString demuxer = core->mset.forced_demuxer; + if (demuxer.isEmpty()) demuxer = core->mdat.demuxer; + + QString ac = core->mset.forced_audio_codec; + if (ac.isEmpty()) ac = core->mdat.audio_codec; + + QString vc = core->mset.forced_video_codec; + if (vc.isEmpty()) vc = core->mdat.video_codec; + + file_dialog->setDemuxer(demuxer, core->mset.original_demuxer); + file_dialog->setAudioCodec(ac, core->mset.original_audio_codec); + file_dialog->setVideoCodec(vc, core->mset.original_video_codec); + + file_dialog->setMplayerAdditionalArguments( core->mset.mplayer_additional_options ); + file_dialog->setMplayerAdditionalVideoFilters( core->mset.mplayer_additional_video_filters ); + file_dialog->setMplayerAdditionalAudioFilters( core->mset.mplayer_additional_audio_filters ); + + file_dialog->setMediaData( core->mdat ); +} + +void BaseGui::applyFileProperties() { + qDebug("BaseGui::applyFileProperties"); + + bool need_restart = false; + bool demuxer_changed = false; + +#undef TEST_AND_SET +#define TEST_AND_SET( Pref, Dialog ) \ + if ( Pref != Dialog ) { Pref = Dialog; need_restart = TRUE; } + + QString prev_demuxer = core->mset.forced_demuxer; + + QString demuxer = file_dialog->demuxer(); + if (demuxer == core->mset.original_demuxer) demuxer=""; + TEST_AND_SET(core->mset.forced_demuxer, demuxer); + + if (prev_demuxer != core->mset.forced_demuxer) { + // Demuxer changed + demuxer_changed = true; + core->mset.current_audio_id = MediaSettings::NoneSelected; + core->mset.current_sub_id = MediaSettings::NoneSelected; + } + + QString ac = file_dialog->audioCodec(); + if (ac == core->mset.original_audio_codec) ac=""; + TEST_AND_SET(core->mset.forced_audio_codec, ac); + + QString vc = file_dialog->videoCodec(); + if (vc == core->mset.original_video_codec) vc=""; + TEST_AND_SET(core->mset.forced_video_codec, vc); + + TEST_AND_SET(core->mset.mplayer_additional_options, file_dialog->mplayerAdditionalArguments()); + TEST_AND_SET(core->mset.mplayer_additional_video_filters, file_dialog->mplayerAdditionalVideoFilters()); + TEST_AND_SET(core->mset.mplayer_additional_audio_filters, file_dialog->mplayerAdditionalAudioFilters()); + + // Restart the video to apply + if (need_restart) { + if (demuxer_changed) { + core->reload(); + } else { + core->restart(); + } + } +} + + +void BaseGui::updateMediaInfo() { + qDebug("BaseGui::updateMediaInfo"); + + if (file_dialog) { + if (file_dialog->isVisible()) setDataToFileProperties(); + } + + setWindowCaption( core->mdat.displayName() + " - SMPlayer" ); +} + +void BaseGui::newMediaLoaded() { + qDebug("BaseGui::newMediaLoaded"); + + pref->history_recents->addItem( core->mdat.filename ); + updateRecents(); + + // If a VCD, Audio CD or DVD, add items to playlist + bool is_disc = ( (core->mdat.type == TYPE_VCD) || (core->mdat.type == TYPE_DVD) || (core->mdat.type == TYPE_AUDIO_CD) ); + if (pref->auto_add_to_playlist && is_disc) + { + int first_title = 1; + if (core->mdat.type == TYPE_VCD) first_title = pref->vcd_initial_title; + + QString type = "dvd"; + if (core->mdat.type == TYPE_VCD) type="vcd"; + else + if (core->mdat.type == TYPE_AUDIO_CD) type="cdda"; + + if (core->mset.current_title_id == first_title) { + playlist->clear(); + QStringList l; + QString s; + QString folder; + if (core->mdat.type == TYPE_DVD) { + folder = Helper::dvdSplitFolder( core->mdat.filename ); + } + for (int n=0; n < core->mdat.titles.numItems(); n++) { + s = type + "://" + QString::number(core->mdat.titles.itemAt(n).ID()); + if ( !folder.isEmpty() ) { + s += ":" + folder; + } + l.append(s); + } + playlist->addFiles(l); + //playlist->setModified(false); // Not a real playlist + } + } /*else { + playlist->clear(); + playlist->addCurrentFile(); + }*/ + + if ((core->mdat.type == TYPE_FILE) && (pref->auto_add_to_playlist) && (pref->add_to_playlist_consecutive_files)) { + // Look for consecutive files + QStringList files_to_add = Helper::searchForConsecutiveFiles(core->mdat.filename); + if (!files_to_add.empty()) playlist->addFiles(files_to_add); + } +} + +void BaseGui::clearMplayerLog() { + mplayer_log.clear(); + if (mplayer_log_window->isVisible()) mplayer_log_window->clear(); +} + +void BaseGui::recordMplayerLog(QString line) { + if (pref->log_mplayer) { + if ( (line.indexOf("A:")==-1) && (line.indexOf("V:")==-1) ) { + line.append("\n"); + mplayer_log.append(line); + if (mplayer_log_window->isVisible()) mplayer_log_window->appendText(line); + } + } +} + +void BaseGui::recordSmplayerLog(QString line) { + if (pref->log_smplayer) { + line.append("\n"); + smplayer_log.append(line); + if (smplayer_log_window->isVisible()) smplayer_log_window->appendText(line); + } +} + +/*! + Save the mplayer log to a file, so it can be used by external + applications. +*/ +void BaseGui::autosaveMplayerLog() { + qDebug("BaseGui::autosaveMplayerLog"); + + if (pref->autosave_mplayer_log) { + if (!pref->mplayer_log_saveto.isEmpty()) { + QFile file( pref->mplayer_log_saveto ); + if ( file.open( QIODevice::WriteOnly ) ) { + QTextStream strm( &file ); + strm << mplayer_log; + file.close(); + } + } + } +} + +void BaseGui::showMplayerLog() { + qDebug("BaseGui::showMplayerLog"); + + exitFullscreenIfNeeded(); + + mplayer_log_window->setText( mplayer_log ); + mplayer_log_window->show(); +} + +void BaseGui::showLog() { + qDebug("BaseGui::showLog"); + + exitFullscreenIfNeeded(); + + smplayer_log_window->setText( smplayer_log ); + smplayer_log_window->show(); +} + + +void BaseGui::initializeMenus() { + qDebug("BaseGui::initializeMenus"); + +#define EMPTY 1 + + int n; + + // Subtitles + subtitleTrackGroup->clear(true); + QAction * subNoneAct = subtitleTrackGroup->addAction( tr("&None") ); + subNoneAct->setData(MediaSettings::SubNone); + subNoneAct->setCheckable(true); + for (n=0; n < core->mdat.subs.numItems(); n++) { + QAction *a = new QAction(subtitleTrackGroup); + a->setCheckable(true); + a->setText(core->mdat.subs.itemAt(n).displayName()); + a->setData(n); + } + subtitlestrack_menu->addActions( subtitleTrackGroup->actions() ); + + // Audio + audioTrackGroup->clear(true); + if (core->mdat.audios.numItems()==0) { + QAction * a = audioTrackGroup->addAction( tr("") ); + a->setEnabled(false); + } else { + for (n=0; n < core->mdat.audios.numItems(); n++) { + QAction *a = new QAction(audioTrackGroup); + a->setCheckable(true); + a->setText(core->mdat.audios.itemAt(n).displayName()); + a->setData(core->mdat.audios.itemAt(n).ID()); + } + } + audiotrack_menu->addActions( audioTrackGroup->actions() ); + + // Video + videoTrackGroup->clear(true); + if (core->mdat.videos.numItems()==0) { + QAction * a = videoTrackGroup->addAction( tr("") ); + a->setEnabled(false); + } else { + for (n=0; n < core->mdat.videos.numItems(); n++) { + QAction *a = new QAction(videoTrackGroup); + a->setCheckable(true); + a->setText(core->mdat.videos.itemAt(n).displayName()); + a->setData(core->mdat.videos.itemAt(n).ID()); + } + } + videotrack_menu->addActions( videoTrackGroup->actions() ); + + // Titles + titleGroup->clear(true); + if (core->mdat.titles.numItems()==0) { + QAction * a = titleGroup->addAction( tr("") ); + a->setEnabled(false); + } else { + for (n=0; n < core->mdat.titles.numItems(); n++) { + QAction *a = new QAction(titleGroup); + a->setCheckable(true); + a->setText(core->mdat.titles.itemAt(n).displayName()); + a->setData(core->mdat.titles.itemAt(n).ID()); + } + } + titles_menu->addActions( titleGroup->actions() ); + +#if GENERIC_CHAPTER_SUPPORT + chapterGroup->clear(true); + if (core->mdat.chapters > 0) { + for (n=0; n < core->mdat.chapters; n++) { + QAction *a = new QAction(chapterGroup); + a->setCheckable(true); + a->setText( QString::number(n+1) ); + a->setData( n + Core::firstChapter() ); + } + } else { + QAction * a = chapterGroup->addAction( tr("") ); + a->setEnabled(false); + } + chapters_menu->addActions( chapterGroup->actions() ); +#else + // DVD Chapters + chapterGroup->clear(true); + if ( (core->mdat.type == TYPE_DVD) && (core->mset.current_title_id > 0) ) { + for (n=0; n < core->mdat.titles.item(core->mset.current_title_id).chapters(); n++) { + QAction *a = new QAction(chapterGroup); + a->setCheckable(true); + a->setText( QString::number(n+1) ); + a->setData( n + Core::dvdFirstChapter() ); + } + } else { + // *** Matroshka chapters *** + if (core->mdat.mkv_chapters > 0) { + for (n=0; n < core->mdat.mkv_chapters; n++) { + QAction *a = new QAction(chapterGroup); + a->setCheckable(true); + a->setText( QString::number(n+1) ); + a->setData( n + Core::firstChapter() ); + } + } else { + QAction * a = chapterGroup->addAction( tr("") ); + a->setEnabled(false); + } + } + chapters_menu->addActions( chapterGroup->actions() ); +#endif + + // Angles + angleGroup->clear(true); + if (core->mset.current_angle_id > 0) { + for (n=1; n <= core->mdat.titles.item(core->mset.current_title_id).angles(); n++) { + QAction *a = new QAction(angleGroup); + a->setCheckable(true); + a->setText( QString::number(n) ); + a->setData( n ); + } + } else { + QAction * a = angleGroup->addAction( tr("") ); + a->setEnabled(false); + } + angles_menu->addActions( angleGroup->actions() ); +} + +void BaseGui::updateRecents() { + qDebug("BaseGui::updateRecents"); + + // Not clear the first 2 items + while (recentfiles_menu->actions().count() > 2) { + QAction * a = recentfiles_menu->actions()[2]; + recentfiles_menu->removeAction( a ); + a->deleteLater(); + } + + int current_items = 0; + + if (pref->history_recents->count() > 0) { + for (int n=0; n < pref->history_recents->count(); n++) { + QString fullname = pref->history_recents->item(n); + QString filename = fullname; + QFileInfo fi(fullname); + //if (fi.exists()) filename = fi.fileName(); // Can be slow + + // Let's see if it looks like a file (no dvd://1 or something) + if (fullname.indexOf(QRegExp("^.*://.*")) == -1) filename = fi.fileName(); + + QAction * a = recentfiles_menu->addAction( filename ); + a->setStatusTip(fullname); + a->setData(n); + connect(a, SIGNAL(triggered()), this, SLOT(openRecent())); + current_items++; + } + } else { + QAction * a = recentfiles_menu->addAction( tr("") ); + a->setEnabled(false); + } + + recentfiles_menu->menuAction()->setVisible( current_items > 0 ); +} + +void BaseGui::clearRecentsList() { + // Delete items in menu + pref->history_recents->clear(); + updateRecents(); +} + +void BaseGui::updateWidgets() { + qDebug("BaseGui::updateWidgets"); + + // Subtitles menu + subtitleTrackGroup->setChecked( core->mset.current_sub_id ); + + // Disable the unload subs action if there's no external subtitles + unloadSubsAct->setEnabled( !core->mset.external_subtitles.isEmpty() ); + + // Audio menu + audioTrackGroup->setChecked( core->mset.current_audio_id ); + channelsGroup->setChecked( core->mset.audio_use_channels ); + stereoGroup->setChecked( core->mset.stereo_mode ); + // Disable the unload audio file action if there's no external audio file + unloadAudioAct->setEnabled( !core->mset.external_audio.isEmpty() ); + + // Video menu + videoTrackGroup->setChecked( core->mset.current_video_id ); + + // Aspect ratio + aspectGroup->setChecked( core->mset.aspect_ratio_id ); + + // Rotate + rotateGroup->setChecked( core->mset.rotate ); + +#if USE_ADAPTER + screenGroup->setChecked( pref->adapter ); +#endif + + // OSD + osdGroup->setChecked( pref->osd ); + + // Titles + titleGroup->setChecked( core->mset.current_title_id ); + + // Chapters + chapterGroup->setChecked( core->mset.current_chapter_id ); + + // Angles + angleGroup->setChecked( core->mset.current_angle_id ); + + // Deinterlace menu + deinterlaceGroup->setChecked( core->mset.current_deinterlacer ); + + // Video size menu + sizeGroup->setChecked( pref->size_factor ); + + // Auto phase + phaseAct->setChecked( core->mset.phase_filter ); + + // Deblock + deblockAct->setChecked( core->mset.deblock_filter ); + + // Dering + deringAct->setChecked( core->mset.dering_filter ); + + // Add noise + addNoiseAct->setChecked( core->mset.noise_filter ); + +#if NEW_ASPECT_CODE + // Letterbox + addLetterboxAct->setChecked( core->mset.add_letterbox ); +#endif + + // Upscaling + upscaleAct->setChecked( core->mset.upscaling_filter ); + + + // Postprocessing + postProcessingAct->setChecked( core->mset.postprocessing_filter ); + + // Denoise submenu + denoiseGroup->setChecked( core->mset.current_denoiser ); + + /* + // Fullscreen button + fullscreenbutton->setOn(pref->fullscreen); + + // Mute button + mutebutton->setOn(core->mset.mute); + if (core->mset.mute) + mutebutton->setPixmap( Images::icon("mute_small") ); + else + mutebutton->setPixmap( Images::icon("volume_small") ); + + // Volume slider + volumeslider->setValue( core->mset.volume ); + */ + + // Mute menu option + muteAct->setChecked( core->mset.mute ); + + // Karaoke menu option + karaokeAct->setChecked( core->mset.karaoke_filter ); + + // Extrastereo menu option + extrastereoAct->setChecked( core->mset.extrastereo_filter ); + + // Volnorm menu option + volnormAct->setChecked( core->mset.volnorm_filter ); + + // Repeat menu option + repeatAct->setChecked( pref->loop ); + + // Fullscreen action + fullscreenAct->setChecked( pref->fullscreen ); + + // Time slider + if (core->state()==Core::Stopped) { + //FIXME + //timeslider->setValue( (int) core->mset.current_sec ); + } + + // Video equalizer + videoEqualizerAct->setChecked( video_equalizer->isVisible() ); + + // Audio equalizer + audioEqualizerAct->setChecked( audio_equalizer->isVisible() ); + + // Playlist +#if !DOCK_PLAYLIST + //showPlaylistAct->setChecked( playlist->isVisible() ); +#endif + +#if DOCK_PLAYLIST + showPlaylistAct->setChecked( playlist->isVisible() ); +#endif + + // Frame counter + frameCounterAct->setChecked( pref->show_frame_counter ); + + // Motion vectors + motionVectorsAct->setChecked( pref->show_motion_vectors ); + + // Compact mode + compactAct->setChecked( pref->compact_mode ); + + // Stay on top + onTopActionGroup->setChecked( (int) pref->stay_on_top ); + + // Flip + flipAct->setChecked( core->mset.flip ); + + // Mirror + mirrorAct->setChecked( core->mset.mirror ); + + // Use ass lib + useAssAct->setChecked( pref->use_ass_subtitles ); + + // Closed caption and forces subs + useClosedCaptionAct->setChecked( pref->use_closed_caption_subs ); + useForcedSubsOnlyAct->setChecked( pref->use_forced_subs_only ); + + // Enable or disable subtitle options + bool e = ((core->mset.current_sub_id != MediaSettings::SubNone) && + (core->mset.current_sub_id != MediaSettings::NoneSelected)); + + if (pref->use_closed_caption_subs) e = true; // Enable if using closed captions + + decSubDelayAct->setEnabled(e); + incSubDelayAct->setEnabled(e); + decSubPosAct->setEnabled(e); + incSubPosAct->setEnabled(e); + decSubScaleAct->setEnabled(e); + incSubScaleAct->setEnabled(e); + decSubStepAct->setEnabled(e); + incSubStepAct->setEnabled(e); +} + +void BaseGui::updateVideoEqualizer() { + // Equalizer + video_equalizer->contrast->setValue( core->mset.contrast ); + video_equalizer->brightness->setValue( core->mset.brightness ); + video_equalizer->hue->setValue( core->mset.hue ); + video_equalizer->saturation->setValue( core->mset.saturation ); + video_equalizer->gamma->setValue( core->mset.gamma ); +} + +void BaseGui::updateAudioEqualizer() { + // Audio Equalizer + for (int n = 0; n < 10; n++) { + audio_equalizer->eq[n]->setValue( core->mset.audio_equalizer[n].toInt() ); + } +} + +/* +void BaseGui::playlistVisibilityChanged() { +#if !DOCK_PLAYLIST + bool visible = playlist->isVisible(); + + showPlaylistAct->setChecked( visible ); +#endif +} +*/ + +/* +void BaseGui::openRecent(int item) { + qDebug("BaseGui::openRecent: %d", item); + if ((item > -1) && (item < RECENTS_CLEAR)) { // 1000 = Clear item + open( recents->item(item) ); + } +} +*/ + +void BaseGui::openRecent() { + QAction *a = qobject_cast (sender()); + if (a) { + int item = a->data().toInt(); + qDebug("BaseGui::openRecent: %d", item); + QString file = pref->history_recents->item(item); + + if (pref->auto_add_to_playlist) { + if (playlist->maybeSave()) { + playlist->clear(); + playlist->addFile(file, Playlist::NoGetInfo); + + open( file ); + } + } else { + open( file ); + } + + } +} + +void BaseGui::open(QString file) { + qDebug("BaseGui::open: '%s'", file.toUtf8().data()); + + // If file is a playlist, open that playlist + QString extension = QFileInfo(file).suffix().toLower(); + if ( (extension=="m3u") || (extension=="m3u8") ) { + playlist->load_m3u(file); + } + else + if (extension=="pls") { + playlist->load_pls(file); + } + else + if (QFileInfo(file).isDir()) { + openDirectory(file); + } + else { + // Let the core to open it, autodetecting the file type + //if (playlist->maybeSave()) { + // playlist->clear(); + // playlist->addFile(file); + + core->open(file); + //} + } + + if (QFile::exists(file)) pref->latest_dir = QFileInfo(file).absolutePath(); +} + +void BaseGui::openFiles(QStringList files) { + qDebug("BaseGui::openFiles"); + if (files.empty()) return; + + if (files.count()==1) { + if (pref->auto_add_to_playlist) { + if (playlist->maybeSave()) { + playlist->clear(); + playlist->addFile(files[0], Playlist::NoGetInfo); + + open(files[0]); + } + } else { + open(files[0]); + } + } else { + if (playlist->maybeSave()) { + playlist->clear(); + playlist->addFiles(files); + open(files[0]); + } + } +} + +void BaseGui::openURL() { + qDebug("BaseGui::openURL"); + + exitFullscreenIfNeeded(); + + /* + bool ok; + QString s = QInputDialog::getText(this, + tr("SMPlayer - Enter URL"), tr("URL:"), QLineEdit::Normal, + pref->last_url, &ok ); + + if ( ok && !s.isEmpty() ) { + + //playlist->clear(); + //playlistdock->hide(); + + openURL(s); + } else { + // user entered nothing or pressed Cancel + } + */ + + InputURL d(this); + + for (int n=0; n < pref->history_urls->count(); n++) { + d.setURL( pref->history_urls->url(n), pref->history_urls->isPlaylist(n) ); + } + + if (d.exec() == QDialog::Accepted ) { + QString url = d.url(); + bool is_playlist = d.isPlaylist(); + if (!url.isEmpty()) { + pref->history_urls->addUrl(url, is_playlist); + if (is_playlist) url = url + IS_PLAYLIST_TAG; + openURL(url); + } + } +} + +void BaseGui::openURL(QString url) { + if (!url.isEmpty()) { + //pref->history_urls->addUrl(url); + + if (pref->auto_add_to_playlist) { + if (playlist->maybeSave()) { + core->openStream(url); + + playlist->clear(); + playlist->addFile(url, Playlist::NoGetInfo); + } + } else { + core->openStream(url); + } + } +} + + +void BaseGui::openFile() { + qDebug("BaseGui::fileOpen"); + + exitFullscreenIfNeeded(); + + Extensions e; + QString s = MyFileDialog::getOpenFileName( + this, tr("Choose a file"), pref->latest_dir, + tr("Multimedia") + e.allPlayable().forFilter()+";;" + + tr("Video") + e.video().forFilter()+";;" + + tr("Audio") + e.audio().forFilter()+";;" + + tr("Playlists") + e.playlist().forFilter()+";;" + + tr("All files") +" (*.*)" ); + + if ( !s.isEmpty() ) { + openFile(s); + } +} + +void BaseGui::openFile(QString file) { + qDebug("BaseGui::openFile: '%s'", file.toUtf8().data()); + + if ( !file.isEmpty() ) { + + //playlist->clear(); + //playlistdock->hide(); + + // If file is a playlist, open that playlist + QString extension = QFileInfo(file).suffix().toLower(); + if ( (extension=="m3u") || (extension=="m3u8") ) { + playlist->load_m3u(file); + } + else + if (extension=="pls") { + playlist->load_pls(file); + } + else + if (extension=="iso") { + if (playlist->maybeSave()) { + core->open(file); + } + } + else { + if (pref->auto_add_to_playlist) { + if (playlist->maybeSave()) { + core->openFile(file); + + playlist->clear(); + playlist->addFile(file, Playlist::NoGetInfo); + } + } else { + core->openFile(file); + } + } + if (QFile::exists(file)) pref->latest_dir = QFileInfo(file).absolutePath(); + } +} + +void BaseGui::configureDiscDevices() { + QMessageBox::information( this, tr("SMPlayer - Information"), + tr("The CDROM / DVD drives are not configured yet.\n" + "The configuration dialog will be shown now, " + "so you can do it."), QMessageBox::Ok); + + showPreferencesDialog(); + pref_dialog->showSection( PreferencesDialog::Drives ); +} + +void BaseGui::openVCD() { + qDebug("BaseGui::openVCD"); + + if ( (pref->dvd_device.isEmpty()) || + (pref->cdrom_device.isEmpty()) ) + { + configureDiscDevices(); + } else { + if (playlist->maybeSave()) { + core->openVCD( pref->vcd_initial_title ); + } + } +} + +void BaseGui::openAudioCD() { + qDebug("BaseGui::openAudioCD"); + + if ( (pref->dvd_device.isEmpty()) || + (pref->cdrom_device.isEmpty()) ) + { + configureDiscDevices(); + } else { + if (playlist->maybeSave()) { + core->openAudioCD(); + } + } +} + +void BaseGui::openDVD() { + qDebug("BaseGui::openDVD"); + + if ( (pref->dvd_device.isEmpty()) || + (pref->cdrom_device.isEmpty()) ) + { + configureDiscDevices(); + } else { + if (playlist->maybeSave()) { + core->openDVD("dvd://1"); + } + } +} + +void BaseGui::openDVDFromFolder() { + qDebug("BaseGui::openDVDFromFolder"); + + if (playlist->maybeSave()) { + InputDVDDirectory *d = new InputDVDDirectory(this); + d->setFolder( pref->last_dvd_directory ); + + if (d->exec() == QDialog::Accepted) { + qDebug("BaseGui::openDVDFromFolder: accepted"); + openDVDFromFolder( d->folder() ); + } + + delete d; + } +} + +void BaseGui::openDVDFromFolder(QString directory) { + //core->openDVD(TRUE, directory); + pref->last_dvd_directory = directory; + core->openDVD( "dvd://1:" + directory); +} + +void BaseGui::openDirectory() { + qDebug("BaseGui::openDirectory"); + + QString s = MyFileDialog::getExistingDirectory( + this, tr("Choose a directory"), + pref->latest_dir ); + + if (!s.isEmpty()) { + openDirectory(s); + } +} + +void BaseGui::openDirectory(QString directory) { + qDebug("BaseGui::openDirectory: '%s'", directory.toUtf8().data()); + + if (Helper::directoryContainsDVD(directory)) { + core->open(directory); + } + else { + QFileInfo fi(directory); + if ( (fi.exists()) && (fi.isDir()) ) { + playlist->clear(); + //playlist->addDirectory(directory); + playlist->addDirectory( fi.absoluteFilePath() ); + playlist->startPlay(); + } else { + qDebug("BaseGui::openDirectory: directory is not valid"); + } + } +} + +void BaseGui::loadSub() { + qDebug("BaseGui::loadSub"); + + exitFullscreenIfNeeded(); + + Extensions e; + QString s = MyFileDialog::getOpenFileName( + this, tr("Choose a file"), + pref->latest_dir, + tr("Subtitles") + e.subtitles().forFilter()+ ";;" + + tr("All files") +" (*.*)" ); + + if (!s.isEmpty()) core->loadSub(s); +} + +void BaseGui::setInitialSubtitle(const QString & subtitle_file) { + qDebug("BaseGui::setInitialSubtitle: '%s'", subtitle_file.toUtf8().constData()); + + core->setInitialSubtitle(subtitle_file); +} + +void BaseGui::loadAudioFile() { + qDebug("BaseGui::loadAudioFile"); + + exitFullscreenIfNeeded(); + + Extensions e; + QString s = MyFileDialog::getOpenFileName( + this, tr("Choose a file"), + pref->latest_dir, + tr("Audio") + e.audio().forFilter()+";;" + + tr("All files") +" (*.*)" ); + + if (!s.isEmpty()) core->loadAudioFile(s); +} + +void BaseGui::helpFAQ() { + QUrl url = QUrl::fromLocalFile(Paths::doc("faq.html", pref->language)); + qDebug("BaseGui::helpFAQ: file to open %s", url.toString().toUtf8().data()); + QDesktopServices::openUrl( url ); +} + +void BaseGui::helpCLOptions() { + if (clhelp_window == 0) { + clhelp_window = new LogWindow(this); + } + clhelp_window->setWindowTitle( tr("SMPlayer command line options") ); + clhelp_window->setHtml(CLHelp::help(true)); + clhelp_window->show(); +} + +void BaseGui::helpTips() { + QDesktopServices::openUrl( QUrl("http://smplayer.wiki.sourceforge.net/Tips") ); +} + +void BaseGui::helpAbout() { + About d(this); + d.exec(); +} + +void BaseGui::helpAboutQt() { + QMessageBox::aboutQt(this, tr("About Qt") ); +} + +void BaseGui::showGotoDialog() { + TimeDialog d(this); + d.setMaximumTime( (int) core->mdat.duration); + d.setTime( (int) core->mset.current_sec); + if (d.exec() == QDialog::Accepted) { + core->goToSec( d.time() ); + } +} + +void BaseGui::exitFullscreen() { + if (pref->fullscreen) { + toggleFullscreen(false); + } +} + +void BaseGui::toggleFullscreen() { + qDebug("BaseGui::toggleFullscreen"); + + toggleFullscreen(!pref->fullscreen); +} + +void BaseGui::toggleFullscreen(bool b) { + qDebug("BaseGui::toggleFullscreen: %d", b); + + if (b==pref->fullscreen) { + // Nothing to do + qDebug("BaseGui::toggleFullscreen: nothing to do, returning"); + return; + } + + pref->fullscreen = b; + + // If using mplayer window + if (pref->use_mplayer_window) { + core->tellmp("vo_fullscreen " + QString::number(b) ); + updateWidgets(); + return; + } + + if (!panel->isVisible()) return; // mplayer window is not used. + + if (pref->fullscreen) { + compactAct->setEnabled(false); + + if (pref->restore_pos_after_fullscreen) { + win_pos = pos(); + win_size = size(); + } + + was_maximized = isMaximized(); + qDebug("BaseGui::toggleFullscreen: was_maximized: %d", was_maximized); + + aboutToEnterFullscreen(); + + #ifdef Q_OS_WIN + // Avoid the video to pause + if (!pref->pause_when_hidden) hide(); + #endif + + showFullScreen(); + + } else { + #ifdef Q_OS_WIN + // Avoid the video to pause + if (!pref->pause_when_hidden) hide(); + #endif + + showNormal(); + + if (was_maximized) showMaximized(); // It has to be called after showNormal() + + aboutToExitFullscreen(); + + if (pref->restore_pos_after_fullscreen) { + move( win_pos ); + resize( win_size ); + } + + compactAct->setEnabled(true); + } + + updateWidgets(); + + if ((pref->add_blackborders_on_fullscreen) && + (!core->mset.add_letterbox)) + { + core->restart(); + } +} + + +void BaseGui::aboutToEnterFullscreen() { + if (!pref->compact_mode) { + menuBar()->hide(); + statusBar()->hide(); + } +} + +void BaseGui::aboutToExitFullscreen() { + if (!pref->compact_mode) { + menuBar()->show(); + statusBar()->show(); + } +} + +void BaseGui::toggleFrameCounter() { + toggleFrameCounter( !pref->show_frame_counter ); +} + +void BaseGui::toggleFrameCounter(bool b) { + pref->show_frame_counter = b; + updateWidgets(); +} + + +void BaseGui::leftClickFunction() { + qDebug("BaseGui::leftClickFunction"); + + if (!pref->mouse_left_click_function.isEmpty()) { + processFunction(pref->mouse_left_click_function); + } +} + +void BaseGui::rightClickFunction() { + qDebug("BaseGui::rightClickFunction"); + + if (!pref->mouse_right_click_function.isEmpty()) { + processFunction(pref->mouse_right_click_function); + } +} + +void BaseGui::doubleClickFunction() { + qDebug("BaseGui::doubleClickFunction"); + + if (!pref->mouse_double_click_function.isEmpty()) { + processFunction(pref->mouse_double_click_function); + } +} + +void BaseGui::middleClickFunction() { + qDebug("BaseGui::middleClickFunction"); + + if (!pref->mouse_middle_click_function.isEmpty()) { + processFunction(pref->mouse_middle_click_function); + } +} + +void BaseGui::xbutton1ClickFunction() { + qDebug("BaseGui::xbutton1ClickFunction"); + + if (!pref->mouse_xbutton1_click_function.isEmpty()) { + processFunction(pref->mouse_xbutton1_click_function); + } +} + +void BaseGui::xbutton2ClickFunction() { + qDebug("BaseGui::xbutton2ClickFunction"); + + if (!pref->mouse_xbutton2_click_function.isEmpty()) { + processFunction(pref->mouse_xbutton2_click_function); + } +} + +void BaseGui::processFunction(QString function) { + qDebug("BaseGui::processFunction: '%s'", function.toUtf8().data()); + + QAction * action = ActionsEditor::findAction(this, function); + if (!action) action = ActionsEditor::findAction(playlist, function); + + if (action) { + qDebug("BaseGui::processFunction: action found"); + if (action->isCheckable()) + //action->toggle(); + action->trigger(); + else + action->trigger(); + } +} + +void BaseGui::runActions(QString actions) { + qDebug("BaseGui::runActions"); + + QAction * action; + QStringList l = actions.split(" "); + + for (int n = 0; n < l.count(); n++) { + QString a = l[n]; + QString par = ""; + + if ( (n+1) < l.count() ) { + if ( (l[n+1].toLower() == "true") || (l[n+1].toLower() == "false") ) { + par = l[n+1].toLower(); + n++; + } + } + + action = ActionsEditor::findAction(this, a); + if (!action) action = ActionsEditor::findAction(playlist, a); + + if (action) { + qDebug("BaseGui::runActions: running action: '%s' (par: '%s')", + a.toUtf8().data(), par.toUtf8().data() ); + + if (action->isCheckable()) { + if (par.isEmpty()) { + //action->toggle(); + action->trigger(); + } else { + action->setChecked( (par == "true") ); + } + } + else { + action->trigger(); + } + } else { + qWarning("BaseGui::runActions: action: '%s' not found",a.toUtf8().data()); + } + } +} + +void BaseGui::checkPendingActionsToRun() { + qDebug("BaseGui::checkPendingActionsToRun"); + + QString actions; + if (!pending_actions_to_run.isEmpty()) { + actions = pending_actions_to_run; + pending_actions_to_run.clear(); + if (!pref->actions_to_run.isEmpty()) { + actions = pref->actions_to_run +" "+ actions; + } + } else { + actions = pref->actions_to_run; + } + + if (!actions.isEmpty()) { + qDebug("BaseGui::checkPendingActionsToRun: actions: '%s'", actions.toUtf8().constData()); + runActions(actions); + } +} + +#if REPORT_OLD_MPLAYER +void BaseGui::checkMplayerVersion() { + qDebug("BaseGui::checkMplayerVersion"); + + // Qt 4.3.5 is crazy, I can't popup a messagebox here, it calls + // this function once and again when the messagebox is shown + + if ( (pref->mplayer_detected_version > 0) && (!MplayerVersion::isMplayerAtLeast(25158)) ) { + QTimer::singleShot(1000, this, SLOT(displayWarningAboutOldMplayer())); + } +} + +void BaseGui::displayWarningAboutOldMplayer() { + qDebug("BaseGui::displayWarningAboutOldMplayer"); + + if (!pref->reported_mplayer_is_old) { + QMessageBox::warning(this, tr("Warning - Using old MPlayer"), + tr("The version of MPlayer (%1) installed on your system " + "is obsolete. SMPlayer can't work well with it: some " + "options won't work, subtitle selection may fail...") + .arg(MplayerVersion::toString(pref->mplayer_detected_version)) + + "

    " + + tr("Please, update your MPlayer.") + + "

    " + + tr("(This warning won't be displayed anymore)") ); + + pref->reported_mplayer_is_old = true; + } + //else + //statusBar()->showMessage( tr("Using an old MPlayer, please update it"), 10000 ); +} +#endif + +void BaseGui::dragEnterEvent( QDragEnterEvent *e ) { + qDebug("BaseGui::dragEnterEvent"); + + if (e->mimeData()->hasUrls()) { + e->acceptProposedAction(); + } +} + + + +void BaseGui::dropEvent( QDropEvent *e ) { + qDebug("BaseGui::dropEvent"); + + QStringList files; + + if (e->mimeData()->hasUrls()) { + QList l = e->mimeData()->urls(); + QString s; + for (int n=0; n < l.count(); n++) { + if (l[n].isValid()) { + qDebug("BaseGui::dropEvent: scheme: '%s'", l[n].scheme().toUtf8().data()); + if (l[n].scheme() == "file") + s = l[n].toLocalFile(); + else + s = l[n].toString(); + /* + qDebug(" * '%s'", l[n].toString().toUtf8().data()); + qDebug(" * '%s'", l[n].toLocalFile().toUtf8().data()); + */ + qDebug("BaseGui::dropEvent: file: '%s'", s.toUtf8().data()); + files.append(s); + } + } + } + + + qDebug( "BaseGui::dropEvent: count: %d", files.count()); + if (files.count() > 0) { + if (files.count() == 1) { + QFileInfo fi( files[0] ); + + Extensions e; + QRegExp ext_sub(e.subtitles().forRegExp()); + ext_sub.setCaseSensitivity(Qt::CaseInsensitive); + if (ext_sub.indexIn(fi.suffix()) > -1) { + qDebug( "BaseGui::dropEvent: loading sub: '%s'", files[0].toUtf8().data()); + core->loadSub( files[0] ); + } + else + if (fi.isDir()) { + openDirectory( files[0] ); + } else { + //openFile( files[0] ); + if (pref->auto_add_to_playlist) { + if (playlist->maybeSave()) { + playlist->clear(); + playlist->addFile(files[0], Playlist::NoGetInfo); + + open( files[0] ); + } + } else { + open( files[0] ); + } + } + } else { + // More than one file + qDebug("BaseGui::dropEvent: adding files to playlist"); + playlist->clear(); + playlist->addFiles(files); + //openFile( files[0] ); + playlist->startPlay(); + } + } +} + +void BaseGui::showPopupMenu() { + showPopupMenu(QCursor::pos()); +} + +void BaseGui::showPopupMenu( QPoint p ) { + //qDebug("BaseGui::showPopupMenu: %d, %d", p.x(), p.y()); + popup->move( p ); + popup->show(); +} + +/* +void BaseGui::mouseReleaseEvent( QMouseEvent * e ) { + qDebug("BaseGui::mouseReleaseEvent"); + + if (e->button() == Qt::LeftButton) { + e->accept(); + emit leftClicked(); + } + else + if (e->button() == Qt::MidButton) { + e->accept(); + emit middleClicked(); + } + // + //else + //if (e->button() == Qt::RightButton) { + // showPopupMenu( e->globalPos() ); + //} + // + else + e->ignore(); +} + +void BaseGui::mouseDoubleClickEvent( QMouseEvent * e ) { + e->accept(); + emit doubleClicked(); +} +*/ + +void BaseGui::wheelEvent( QWheelEvent * e ) { + qDebug("BaseGui::wheelEvent: delta: %d", e->delta()); + e->accept(); + + if (e->orientation() == Qt::Vertical) { + if (e->delta() >= 0) + emit wheelUp(); + else + emit wheelDown(); + } else { + qDebug("BaseGui::wheelEvent: horizontal event received, doing nothing"); + } +} + + +// Called when a video has started to play +void BaseGui::enterFullscreenOnPlay() { + if ( (pref->start_in_fullscreen) && (!pref->fullscreen) ) { + toggleFullscreen(TRUE); + } +} + +// Called when the playlist has stopped +void BaseGui::exitFullscreenOnStop() { + if (pref->fullscreen) { + toggleFullscreen(FALSE); + } +} + +void BaseGui::playlistHasFinished() { + qDebug("BaseGui::playlistHasFinished"); + exitFullscreenOnStop(); + + if (pref->close_on_finish) exitAct->trigger(); +} + +void BaseGui::displayState(Core::State state) { + qDebug("BaseGui::displayState: %s", core->stateToString().toUtf8().data()); + switch (state) { + case Core::Playing: statusBar()->showMessage( tr("Playing %1").arg(core->mdat.filename), 2000); break; + case Core::Paused: statusBar()->showMessage( tr("Pause") ); break; + case Core::Stopped: statusBar()->showMessage( tr("Stop") , 2000); break; + } + if (state == Core::Stopped) setWindowCaption( "SMPlayer" ); + +#ifdef Q_OS_WIN + /* Disable screensaver by event */ + just_stopped = false; + + if (state == Core::Stopped) { + just_stopped = true; + int time = 1000 * 60; // 1 minute + QTimer::singleShot( time, this, SLOT(clear_just_stopped()) ); + } +#endif +} + +void BaseGui::displayMessage(QString message) { + statusBar()->showMessage(message, 2000); +} + +void BaseGui::gotCurrentTime(double sec) { + //qDebug( "DefaultGui::displayTime: %f", sec); + + static int last_second = 0; + + if (floor(sec)==last_second) return; // Update only once per second + last_second = (int) floor(sec); + + QString time = Helper::formatTime( (int) sec ) + " / " + + Helper::formatTime( (int) core->mdat.duration ); + + //qDebug( " duration: %f, current_sec: %f", core->mdat.duration, core->mset.current_sec); + + emit timeChanged( time ); +} + +void BaseGui::resizeWindow(int w, int h) { + qDebug("BaseGui::resizeWindow: %d, %d", w, h); + + // If fullscreen, don't resize! + if (pref->fullscreen) return; + + if ( (pref->resize_method==Preferences::Never) && (panel->isVisible()) ) { + return; + } + + if (!panel->isVisible()) { + panel->show(); + + // Enable compact mode + //compactAct->setEnabled(true); + } + + if (pref->size_factor != 100) { + w = w * pref->size_factor / 100; + h = h * pref->size_factor / 100; + } + + qDebug("BaseGui::resizeWindow: size to scale: %d, %d", w, h); + + QSize video_size(w,h); + + if (video_size == panel->size()) { + qDebug("BaseGui::resizeWindow: the panel size is already the required size. Doing nothing."); + return; + } + + int diff_width = this->width() - panel->width(); + int diff_height = this->height() - panel->height(); + + int new_width = w + diff_width; + int new_height = h + diff_height; + +#if USE_MINIMUMSIZE + int minimum_width = minimumSizeHint().width(); + if (pref->gui_minimum_width != 0) minimum_width = pref->gui_minimum_width; + if (new_width < minimum_width) { + qDebug("BaseGui::resizeWindow: width is too small, setting width to %d", minimum_width); + new_width = minimum_width; + } +#endif + + resize(new_width, new_height); + + qDebug("BaseGui::resizeWindow: done: window size: %d, %d", this->width(), this->height()); + qDebug("BaseGui::resizeWindow: done: panel->size: %d, %d", + panel->size().width(), + panel->size().height() ); + qDebug("BaseGui::resizeWindow: done: mplayerwindow->size: %d, %d", + mplayerwindow->size().width(), + mplayerwindow->size().height() ); +} + +void BaseGui::hidePanel() { + qDebug("BaseGui::hidePanel"); + +#if ALLOW_TO_HIDE_VIDEO_WINDOW_ON_AUDIO_FILES + if (!pref->hide_video_window_on_audio_files) { + mplayerwindow->showLogo(true); + } + else +#endif + + if (panel->isVisible()) { + // Exit from fullscreen mode + if (pref->fullscreen) { toggleFullscreen(false); update(); } + + // Exit from compact mode first + if (pref->compact_mode) toggleCompactMode(false); + + //resizeWindow( size().width(), 0 ); + int width = size().width(); + if (width > pref->default_size.width()) width = pref->default_size.width(); + resize( width, size().height() - panel->size().height() ); + panel->hide(); + + // Disable compact mode + //compactAct->setEnabled(false); + } +} + +void BaseGui::displayGotoTime(int t) { +#ifdef SEEKBAR_RESOLUTION + int jump_time = (int)core->mdat.duration * t / SEEKBAR_RESOLUTION; +#else + int jump_time = (int)core->mdat.duration * t / 100; +#endif + //QString s = tr("Jump to %1").arg( Helper::formatTime(jump_time) ); + QString s = QString("Jump to %1").arg( Helper::formatTime(jump_time) ); + statusBar()->showMessage( s, 1000 ); + + if (pref->fullscreen) { + core->tellmp("osd_show_text \"" + s + "\" 3000 1"); + } +} + +void BaseGui::goToPosOnDragging(int t) { + if (pref->update_while_seeking) { +#if ENABLE_DELAYED_DRAGGING + #ifdef SEEKBAR_RESOLUTION + core->goToPosition(t); + #else + core->goToPos(t); + #endif +#else + if ( ( t % 4 ) == 0 ) { + qDebug("BaseGui::goToPosOnDragging: %d", t); + #ifdef SEEKBAR_RESOLUTION + core->goToPosition(t); + #else + core->goToPos(t); + #endif + } +#endif + } +} + +void BaseGui::toggleCompactMode() { + toggleCompactMode( !pref->compact_mode ); +} + +void BaseGui::toggleCompactMode(bool b) { + qDebug("BaseGui::toggleCompactMode: %d", b); + + if (b) + aboutToEnterCompactMode(); + else + aboutToExitCompactMode(); + + pref->compact_mode = b; + updateWidgets(); +} + +void BaseGui::aboutToEnterCompactMode() { + menuBar()->hide(); + statusBar()->hide(); +} + +void BaseGui::aboutToExitCompactMode() { + menuBar()->show(); + statusBar()->show(); +} + +void BaseGui::setStayOnTop(bool b) { + qDebug("BaseGui::setStayOnTop: %d", b); + + if ( (b && (windowFlags() & Qt::WindowStaysOnTopHint)) || + (!b && (!(windowFlags() & Qt::WindowStaysOnTopHint))) ) + { + // identical do nothing + qDebug("BaseGui::setStayOnTop: nothing to do"); + return; + } + + ignore_show_hide_events = true; + + bool visible = isVisible(); + + QPoint old_pos = pos(); + + if (b) { + setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); + } + else { + setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint); + } + + move(old_pos); + + if (visible) { + show(); + } + + ignore_show_hide_events = false; +} + +void BaseGui::changeStayOnTop(int stay_on_top) { + switch (stay_on_top) { + case Preferences::Always : setStayOnTop(true); break; + case Preferences::Never : setStayOnTop(false); break; + case Preferences::WhilePlayingOnTop : setStayOnTop((core->state() == Core::Playing)); break; + } + + pref->stay_on_top = (Preferences::OnTop) stay_on_top; + updateWidgets(); +} + +void BaseGui::checkStayOnTop(Core::State state) { + qDebug("BaseGui::checkStayOnTop"); + if ((!pref->fullscreen) && (pref->stay_on_top == Preferences::WhilePlayingOnTop)) { + setStayOnTop((state == Core::Playing)); + } +} + +// Called when a new window (equalizer, preferences..) is opened. +void BaseGui::exitFullscreenIfNeeded() { + /* + if (pref->fullscreen) { + toggleFullscreen(FALSE); + } + */ +} + +void BaseGui::checkMousePos(QPoint p) { + //qDebug("BaseGui::checkMousePos: %d, %d", p.x(), p.y()); + + bool compact = (pref->floating_display_in_compact_mode && pref->compact_mode); + + if (!pref->fullscreen && !compact) return; + + #define MARGIN 70 + + int margin = MARGIN + pref->floating_control_margin; + + if (p.y() > mplayerwindow->height() - margin) { + //qDebug("BaseGui::checkMousePos: %d, %d", p.x(), p.y()); + if (!near_bottom) { + emit cursorNearBottom(p); + near_bottom = true; + } + } else { + if (near_bottom) { + emit cursorFarEdges(); + near_bottom = false; + } + } + + if (p.y() < margin) { + //qDebug("BaseGui::checkMousePos: %d, %d", p.x(), p.y()); + if (!near_top) { + emit cursorNearTop(p); + near_top = true; + } + } else { + if (near_top) { + emit cursorFarEdges(); + near_top = false; + } + } +} + +#if ALLOW_CHANGE_STYLESHEET +void BaseGui::loadQss(QString filename) { + QFile file( filename ); + file.open(QFile::ReadOnly); + QString styleSheet = QLatin1String(file.readAll()); + + qApp->setStyleSheet(styleSheet); +} + +void BaseGui::changeStyleSheet(QString style) { + if (style.isEmpty()) { + qApp->setStyleSheet(""); + } + else { + QString qss_file = Paths::configPath() + "/themes/" + pref->iconset +"/style.qss"; + //qDebug("BaseGui::changeStyleSheet: '%s'", qss_file.toUtf8().data()); + if (!QFile::exists(qss_file)) { + qss_file = Paths::themesPath() +"/"+ pref->iconset +"/style.qss"; + } + if (QFile::exists(qss_file)) { + qDebug("BaseGui::changeStyleSheet: '%s'", qss_file.toUtf8().data()); + loadQss(qss_file); + } else { + qApp->setStyleSheet(""); + } + } +} +#endif + +void BaseGui::loadActions() { + qDebug("BaseGui::loadActions"); + ActionsEditor::loadFromConfig(this, settings); +#if !DOCK_PLAYLIST + ActionsEditor::loadFromConfig(playlist, settings); +#endif + + actions_list = ActionsEditor::actionsNames(this); +#if !DOCK_PLAYLIST + actions_list += ActionsEditor::actionsNames(playlist); +#endif + + //if (server) + server->setActionsList( actions_list ); +} + +void BaseGui::saveActions() { + qDebug("BaseGui::saveActions"); + + ActionsEditor::saveToConfig(this, settings); +#if !DOCK_PLAYLIST + ActionsEditor::saveToConfig(playlist, settings); +#endif +} + + +void BaseGui::showEvent( QShowEvent * ) { + qDebug("BaseGui::showEvent"); + + if (ignore_show_hide_events) return; + + //qDebug("BaseGui::showEvent: pref->pause_when_hidden: %d", pref->pause_when_hidden); + if ((pref->pause_when_hidden) && (core->state() == Core::Paused)) { + qDebug("BaseGui::showEvent: unpausing"); + core->pause(); // Unpauses + } +} + +void BaseGui::hideEvent( QHideEvent * ) { + qDebug("BaseGui::hideEvent"); + + if (ignore_show_hide_events) return; + + //qDebug("BaseGui::hideEvent: pref->pause_when_hidden: %d", pref->pause_when_hidden); + if ((pref->pause_when_hidden) && (core->state() == Core::Playing)) { + qDebug("BaseGui::hideEvent: pausing"); + core->pause(); + } +} + +void BaseGui::askForMplayerVersion(QString line) { + qDebug("BaseGui::askForMplayerVersion: %s", line.toUtf8().data()); + + if (pref->mplayer_user_supplied_version <= 0) { + InputMplayerVersion d(this); + d.setVersion( pref->mplayer_user_supplied_version ); + d.setVersionFromOutput(line); + if (d.exec() == QDialog::Accepted) { + pref->mplayer_user_supplied_version = d.version(); + qDebug("BaseGui::askForMplayerVersion: user supplied version: %d", pref->mplayer_user_supplied_version); + } + } else { + qDebug("BaseGui::askForMplayerVersion: already have a version supplied by user, so no asking"); + } +} + +void BaseGui::showExitCodeFromMplayer(int exit_code) { + qDebug("BaseGui::showExitCodeFromMplayer: %d", exit_code); + + if (!pref->report_mplayer_crashes) { + qDebug("BaseGui::showExitCodeFromMplayer: not displaying error dialog"); + return; + } + + if (exit_code != 255 ) { + ErrorDialog d(this); + d.setText(tr("MPlayer has finished unexpectedly.") + " " + + tr("Exit code: %1").arg(exit_code)); + d.setLog( mplayer_log ); + d.exec(); + } +} + +void BaseGui::showErrorFromMplayer(QProcess::ProcessError e) { + qDebug("BaseGui::showErrorFromMplayer"); + + if (!pref->report_mplayer_crashes) { + qDebug("showErrorFromMplayer: not displaying error dialog"); + return; + } + + if ((e == QProcess::FailedToStart) || (e == QProcess::Crashed)) { + ErrorDialog d(this); + if (e == QProcess::FailedToStart) { + d.setText(tr("MPlayer failed to start.") + " " + + tr("Please check the MPlayer path in preferences.")); + } else { + d.setText(tr("MPlayer has crashed.") + " " + + tr("See the log for more info.")); + } + d.setLog( mplayer_log ); + d.exec(); + } +} + + +void BaseGui::showFindSubtitlesDialog() { + qDebug("BaseGui::showFindSubtitlesDialog"); + + if (!find_subs_dialog) { + find_subs_dialog = new FindSubtitlesWindow(0, Qt::Window | Qt::WindowMinMaxButtonsHint); + find_subs_dialog->setSettings(Global::settings); + find_subs_dialog->setWindowIcon(windowIcon()); + find_subs_dialog->setProxy( userProxy() ); +#if DOWNLOAD_SUBS + connect(find_subs_dialog, SIGNAL(subtitleDownloaded(const QString &)), + core, SLOT(loadSub(const QString &))); +#endif + } + + find_subs_dialog->show(); + find_subs_dialog->setMovie(core->mdat.filename); +} + +void BaseGui::openUploadSubtitlesPage() { + //QDesktopServices::openUrl( QUrl("http://ds6.ovh.org/hashsubtitles/upload.php") ); + //QDesktopServices::openUrl( QUrl("http://www.opensubtitles.com/upload") ); + QDesktopServices::openUrl( QUrl("http://www.opensubtitles.org/uploadjava") ); +} + +void BaseGui::showVideoPreviewDialog() { + qDebug("BaseGui::showVideoPreviewDialog"); + + if (video_preview == 0) { + video_preview = new VideoPreview( pref->mplayer_bin, 0 ); + video_preview->setSettings(Global::settings); + } + + if (!core->mdat.filename.isEmpty()) { + video_preview->setVideoFile(core->mdat.filename); + + // DVD + if (core->mdat.type==TYPE_DVD) { + QString file = core->mdat.filename; + QString dvd_folder = Helper::dvdSplitFolder(file); + if (dvd_folder.isEmpty()) dvd_folder = pref->dvd_device; + // Remove trailing "/" + if (dvd_folder.endsWith("/")) { +#ifdef Q_OS_WIN + QRegExp r("^[A-Z]:/$"); + int pos = r.indexIn(dvd_folder); + qDebug("BaseGui::showVideoPreviewDialog: drive check: '%s': regexp: %d", dvd_folder.toUtf8().data(), pos); + if (pos == -1) +#endif + dvd_folder = dvd_folder.remove( dvd_folder.length()-1, 1); + } + int dvd_title = Helper::dvdSplitTitle(file); + file = "dvd://" + QString::number(dvd_title); + + video_preview->setVideoFile(file); + video_preview->setDVDDevice(dvd_folder); + } else { + video_preview->setDVDDevice(""); + } + } + + video_preview->setMplayerPath(pref->mplayer_bin); + + if ( (video_preview->showConfigDialog()) && (video_preview->createThumbnails()) ) { + video_preview->show(); + video_preview->adjustWindowSize(); + } +} + +QNetworkProxy BaseGui::userProxy() { + QNetworkProxy proxy; + if ( (pref->use_proxy) && (!pref->proxy_host.isEmpty()) ) { + proxy.setType((QNetworkProxy::ProxyType) pref->proxy_type); + proxy.setHostName(pref->proxy_host); + proxy.setPort(pref->proxy_port); + if ( (!pref->proxy_username.isEmpty()) && (!pref->proxy_password.isEmpty()) ) { + proxy.setUser(pref->proxy_username); + proxy.setPassword(pref->proxy_password); + } + qDebug("BaseGui::userProxy: using proxy: host: %s, port: %d, type: %d", + pref->proxy_host.toUtf8().constData(), pref->proxy_port, pref->proxy_type); + } else { + // No proxy + proxy.setType(QNetworkProxy::NoProxy); + qDebug("BaseGui::userProxy: no proxy"); + } + return proxy; +} + +// Language change stuff +void BaseGui::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QMainWindow::changeEvent(e); + } +} + +#ifdef Q_OS_WIN +/* Disable screensaver by event */ +bool BaseGui::winEvent ( MSG * m, long * result ) { + //qDebug("BaseGui::winEvent"); + if (m->message==WM_SYSCOMMAND) { + if ((m->wParam & 0xFFF0)==SC_SCREENSAVE || (m->wParam & 0xFFF0)==SC_MONITORPOWER) { + qDebug("BaseGui::winEvent: received SC_SCREENSAVE or SC_MONITORPOWER"); + if ((pref->disable_screensaver) && (core->state()==Core::Playing)) { + qDebug("BaseGui::winEvent: not allowing screensaver"); + (*result) = 0; + return true; + } else { + if ((pref->disable_screensaver) && (just_stopped)) { + qDebug("BaseGui::winEvent: file just stopped, so not allowing screensaver for a while"); + (*result) = 0; + return true; + } else { + qDebug("BaseGui::winEvent: allowing screensaver"); + return false; + } + } + } + } + return false; +} + +void BaseGui::clear_just_stopped() { + qDebug("BaseGui::clear_just_stopped"); + just_stopped = false; +} +#endif + +#include "moc_basegui.cpp" diff --git a/plugins/smplayer_plugin/basegui.h b/plugins/smplayer_plugin/basegui.h new file mode 100644 index 000000000..c86c8d8a1 --- /dev/null +++ b/plugins/smplayer_plugin/basegui.h @@ -0,0 +1,649 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _BASEGUI_H_ +#define _BASEGUI_H_ + +#include +#include +#include "mediadata.h" +#include "mediasettings.h" +#include "preferences.h" +#include "core.h" +#include "config.h" +#include "guiconfig.h" + +#ifdef Q_OS_WIN +/* Disable screensaver by event */ +#include +#endif + +class QWidget; +class QMenu; +class LogWindow; +class MplayerWindow; + +class QLabel; +class FilePropertiesDialog; +class VideoEqualizer; +class AudioEqualizer; +class FindSubtitlesWindow; +class VideoPreview; +class Playlist; + +class MyAction; +class MyActionGroup; + +class PreferencesDialog; +class MyServer; + + +class BaseGui : public QMainWindow +{ + Q_OBJECT + +public: + BaseGui( QWidget* parent = 0, Qt::WindowFlags flags = 0 ); + ~BaseGui(); + + /* Return true if the window shouldn't show on startup */ + virtual bool startHidden() { return false; }; + + //! Execute all actions in \a actions. The actions should be + //! separated by spaces. Checkable actions could have a parameter: + //! true or false. + void runActions(QString actions); + + //! Execute all the actions after the video has started to play + void runActionsLater(QString actions) { pending_actions_to_run = actions; }; + + //! Saves the line from the smplayer output + void recordSmplayerLog(QString line); + +public slots: + virtual void open(QString file); // Generic open, autodetect type. + virtual void openFile(); + virtual void openFile(QString file); + virtual void openFiles(QStringList files); + virtual void openURL(); + virtual void openURL(QString url); + virtual void openVCD(); + virtual void openAudioCD(); + virtual void openDVD(); + virtual void openDVDFromFolder(); + virtual void openDVDFromFolder(QString directory); + virtual void openDirectory(); + virtual void openDirectory(QString directory); + + virtual void helpFAQ(); + virtual void helpCLOptions(); + virtual void helpTips(); + virtual void helpAbout(); + virtual void helpAboutQt(); + + virtual void loadSub(); + virtual void loadAudioFile(); // Load external audio file + + void setInitialSubtitle(const QString & subtitle_file); + + virtual void showFindSubtitlesDialog(); + virtual void openUploadSubtitlesPage(); //turbos + + virtual void showVideoPreviewDialog(); + + virtual void showPlaylist(); + virtual void showPlaylist(bool b); + virtual void showVideoEqualizer(); + virtual void showVideoEqualizer(bool b); + virtual void showAudioEqualizer(); + virtual void showAudioEqualizer(bool b); + virtual void showMplayerLog(); + virtual void showLog(); + virtual void showPreferencesDialog(); + virtual void showFilePropertiesDialog(); + + virtual void showGotoDialog(); + + virtual void exitFullscreen(); + virtual void toggleFullscreen(); + virtual void toggleFullscreen(bool); + + virtual void toggleCompactMode(); + virtual void toggleCompactMode(bool); + + void setStayOnTop(bool b); + virtual void changeStayOnTop(int); + virtual void checkStayOnTop(Core::State); + + virtual void toggleFrameCounter(); + virtual void toggleFrameCounter(bool); + +protected slots: + virtual void closeWindow(); + + virtual void setJumpTexts(); + + // Replace for setCaption (in Qt 4 it's not virtual) + virtual void setWindowCaption(const QString & title); + + //virtual void openRecent(int item); + virtual void openRecent(); + virtual void enterFullscreenOnPlay(); + virtual void exitFullscreenOnStop(); + virtual void exitFullscreenIfNeeded(); + virtual void playlistHasFinished(); + + virtual void displayState(Core::State state); + virtual void displayMessage(QString message); + virtual void gotCurrentTime(double); + + virtual void initializeMenus(); + virtual void updateWidgets(); + virtual void updateVideoEqualizer(); + virtual void updateAudioEqualizer(); + + virtual void newMediaLoaded(); + virtual void updateMediaInfo(); + + void checkPendingActionsToRun(); + +#if REPORT_OLD_MPLAYER + void checkMplayerVersion(); + void displayWarningAboutOldMplayer(); +#endif + +#if AUTODISABLE_ACTIONS + virtual void enableActionsOnPlaying(); + virtual void disableActionsOnStop(); +#endif + + virtual void resizeWindow(int w, int h); + virtual void hidePanel(); + + /* virtual void playlistVisibilityChanged(); */ + + virtual void displayGotoTime(int); + //! You can call this slot to jump to the specified percentage in the video, while dragging the slider. + virtual void goToPosOnDragging(int); + + virtual void showPopupMenu(); + virtual void showPopupMenu( QPoint p ); + /* + virtual void mouseReleaseEvent( QMouseEvent * e ); + virtual void mouseDoubleClickEvent( QMouseEvent * e ); + */ + + virtual void leftClickFunction(); + virtual void rightClickFunction(); + virtual void doubleClickFunction(); + virtual void middleClickFunction(); + virtual void xbutton1ClickFunction(); + virtual void xbutton2ClickFunction(); + virtual void processFunction(QString function); + + virtual void dragEnterEvent( QDragEnterEvent * ) ; + virtual void dropEvent ( QDropEvent * ); + + virtual void applyNewPreferences(); + virtual void applyFileProperties(); + + virtual void clearRecentsList(); + + virtual void loadActions(); + virtual void saveActions(); + + // Check the mouse pos in fullscreen mode, to + // show the controlwidget if it's moved to + // the bottom area. + virtual void checkMousePos( QPoint ); + + // Single instance stuff + // Another instance request open a file + virtual void remoteOpen(QString file); + virtual void remoteOpenFiles(QStringList files); + virtual void remoteAddFiles(QStringList files); + + //! Called when core can't parse the mplayer version and there's no + //! version supplied by the user + void askForMplayerVersion(QString); + + void showExitCodeFromMplayer(int exit_code); + void showErrorFromMplayer(QProcess::ProcessError); + + // stylesheet +#if ALLOW_CHANGE_STYLESHEET + virtual void loadQss(QString filename); + virtual void changeStyleSheet(QString style); +#endif + +#ifdef Q_OS_WIN + /* Disable screensaver by event */ + void clear_just_stopped(); +#endif + + //! Clears the mplayer log + void clearMplayerLog(); + + //! Saves the line from the mplayer output + void recordMplayerLog(QString line); + + //! Saves the mplayer log to a file every time a file is loaded + void autosaveMplayerLog(); + +signals: + void frameChanged(int); + void timeChanged(QString time_ready_to_print); + + void cursorNearTop(QPoint); + void cursorNearBottom(QPoint); + void cursorFarEdges(); + + void wheelUp(); + void wheelDown(); + /* + void doubleClicked(); + void leftClicked(); + void middleClicked(); + */ + + //! Sent when the user wants to close the main window + void quitSolicited(); + +protected: + virtual void retranslateStrings(); + virtual void changeEvent(QEvent * event); + virtual void hideEvent( QHideEvent * ); + virtual void showEvent( QShowEvent * ); +#ifdef Q_OS_WIN + /* Disable screensaver by event */ + virtual bool winEvent ( MSG * m, long * result ); +#endif + + virtual void aboutToEnterFullscreen(); + virtual void aboutToExitFullscreen(); + virtual void aboutToEnterCompactMode(); + virtual void aboutToExitCompactMode(); + +protected: + void createCore(); + void createMplayerWindow(); + void createVideoEqualizer(); + void createAudioEqualizer(); + void createPlaylist(); + void createPanel(); + void createPreferencesDialog(); + void createFilePropertiesDialog(); + void setDataToFileProperties(); + void initializeGui(); + void createActions(); +#if AUTODISABLE_ACTIONS + void setActionsEnabled(bool); +#endif + void createMenus(); + void updateRecents(); + void configureDiscDevices(); + /* virtual void closeEvent( QCloseEvent * e ); */ + + //! Returns a proxy created from the user's preferences + QNetworkProxy userProxy(); + +protected: + virtual void wheelEvent( QWheelEvent * e ) ; + +protected: + QWidget * panel; + + // Menu File + MyAction * openFileAct; + MyAction * openDirectoryAct; + MyAction * openPlaylistAct; + MyAction * openVCDAct; + MyAction * openAudioCDAct; + MyAction * openDVDAct; + MyAction * openDVDFolderAct; + MyAction * openURLAct; + MyAction * exitAct; + MyAction * clearRecentsAct; + + // Menu Play + MyAction * playAct; + MyAction * playOrPauseAct; + MyAction * pauseAct; + MyAction * pauseAndStepAct; + MyAction * stopAct; + MyAction * frameStepAct; + MyAction * rewind1Act; + MyAction * rewind2Act; + MyAction * rewind3Act; + MyAction * forward1Act; + MyAction * forward2Act; + MyAction * forward3Act; + MyAction * repeatAct; + MyAction * gotoAct; + + // Menu Speed + MyAction * normalSpeedAct; + MyAction * halveSpeedAct; + MyAction * doubleSpeedAct; + MyAction * decSpeed10Act; + MyAction * incSpeed10Act; + MyAction * decSpeed4Act; + MyAction * incSpeed4Act; + MyAction * decSpeed1Act; + MyAction * incSpeed1Act; + + // Menu Video + MyAction * fullscreenAct; + MyAction * compactAct; + MyAction * videoEqualizerAct; + MyAction * screenshotAct; + MyAction * videoPreviewAct; + MyAction * flipAct; + MyAction * mirrorAct; + MyAction * postProcessingAct; + MyAction * phaseAct; + MyAction * deblockAct; + MyAction * deringAct; + MyAction * addNoiseAct; +#if NEW_ASPECT_CODE + MyAction * addLetterboxAct; +#endif + MyAction * upscaleAct; + + // Menu Audio + MyAction * audioEqualizerAct; + MyAction * muteAct; + MyAction * decVolumeAct; + MyAction * incVolumeAct; + MyAction * decAudioDelayAct; + MyAction * incAudioDelayAct; + MyAction * extrastereoAct; + MyAction * karaokeAct; + MyAction * volnormAct; + MyAction * loadAudioAct; + MyAction * unloadAudioAct; + + // Menu Subtitles + MyAction * loadSubsAct; + MyAction * unloadSubsAct; + MyAction * decSubDelayAct; + MyAction * incSubDelayAct; + MyAction * decSubPosAct; + MyAction * incSubPosAct; + MyAction * incSubStepAct; + MyAction * decSubStepAct; + MyAction * incSubScaleAct; + MyAction * decSubScaleAct; + MyAction * useAssAct; + MyAction * useClosedCaptionAct; + MyAction * useForcedSubsOnlyAct; + MyAction * showFindSubtitlesDialogAct; + MyAction * openUploadSubtitlesPageAct;//turbos + + // Menu Options + MyAction * showPlaylistAct; + MyAction * showPropertiesAct; + MyAction * frameCounterAct; + MyAction * motionVectorsAct; + MyAction * showPreferencesAct; + MyAction * showLogMplayerAct; + MyAction * showLogSmplayerAct; + + // Menu Help + MyAction * showFAQAct; + MyAction * showCLOptionsAct; // Command line options + MyAction * showTipsAct; + MyAction * aboutQtAct; + MyAction * aboutThisAct; + + // Playlist + MyAction * playPrevAct; + MyAction * playNextAct; + + // Actions not in menus +#if !USE_MULTIPLE_SHORTCUTS + MyAction * decVolume2Act; + MyAction * incVolume2Act; +#endif + MyAction * exitFullscreenAct; + MyAction * nextOSDAct; + MyAction * decContrastAct; + MyAction * incContrastAct; + MyAction * decBrightnessAct; + MyAction * incBrightnessAct; + MyAction * decHueAct; + MyAction * incHueAct; + MyAction * decSaturationAct; + MyAction * incSaturationAct; + MyAction * decGammaAct; + MyAction * incGammaAct; + MyAction * nextVideoAct; + MyAction * nextAudioAct; + MyAction * nextSubtitleAct; + MyAction * nextChapterAct; + MyAction * prevChapterAct; + MyAction * doubleSizeAct; + MyAction * resetVideoEqualizerAct; + MyAction * resetAudioEqualizerAct; + MyAction * showContextMenuAct; +#if NEW_ASPECT_CODE + MyAction * nextAspectAct; +#endif + + // Moving and zoom + MyAction * moveUpAct; + MyAction * moveDownAct; + MyAction * moveLeftAct; + MyAction * moveRightAct; + MyAction * incZoomAct; + MyAction * decZoomAct; + MyAction * resetZoomAct; + MyAction * autoZoomAct; + MyAction * autoZoom169Act; + MyAction * autoZoom235Act; + + // OSD Action Group + MyActionGroup * osdGroup; + MyAction * osdNoneAct; + MyAction * osdSeekAct; + MyAction * osdTimerAct; + MyAction * osdTotalAct; + + // Denoise Action Group + MyActionGroup * denoiseGroup; + MyAction * denoiseNoneAct; + MyAction * denoiseNormalAct; + MyAction * denoiseSoftAct; + + // Window Size Action Group + MyActionGroup * sizeGroup; + MyAction * size50; + MyAction * size75; + MyAction * size100; + MyAction * size125; + MyAction * size150; + MyAction * size175; + MyAction * size200; + MyAction * size300; + MyAction * size400; + + // Deinterlace Action Group + MyActionGroup * deinterlaceGroup; + MyAction * deinterlaceNoneAct; + MyAction * deinterlaceL5Act; + MyAction * deinterlaceYadif0Act; + MyAction * deinterlaceYadif1Act; + MyAction * deinterlaceLBAct; + MyAction * deinterlaceKernAct; + + // Aspect Action Group + MyActionGroup * aspectGroup; + MyAction * aspectDetectAct; +#if NEW_ASPECT_CODE + MyAction * aspectNoneAct; + MyAction * aspect11Act; // 1:1 +#endif + MyAction * aspect43Act; + MyAction * aspect54Act; + MyAction * aspect149Act; + MyAction * aspect169Act; + MyAction * aspect1610Act; + MyAction * aspect235Act; +#if !NEW_ASPECT_CODE + MyAction * aspect43LetterAct; + MyAction * aspect169LetterAct; + MyAction * aspect43PanscanAct; + MyAction * aspect43To169Act; +#endif + + // Rotate Group + MyActionGroup * rotateGroup; + MyAction * rotateNoneAct; + MyAction * rotateClockwiseFlipAct; + MyAction * rotateClockwiseAct; + MyAction * rotateCounterclockwiseAct; + MyAction * rotateCounterclockwiseFlipAct; + + // Menu StayOnTop + MyActionGroup * onTopActionGroup; + MyAction * onTopAlwaysAct; + MyAction * onTopNeverAct; + MyAction * onTopWhilePlayingAct; + +#if USE_ADAPTER + // Screen Group + MyActionGroup * screenGroup; + MyAction * screenDefaultAct; +#endif + + // Audio Channels Action Group + MyActionGroup * channelsGroup; + /* MyAction * channelsDefaultAct; */ + MyAction * channelsStereoAct; + MyAction * channelsSurroundAct; + MyAction * channelsFull51Act; + + // Stereo Mode Action Group + MyActionGroup * stereoGroup; + MyAction * stereoAct; + MyAction * leftChannelAct; + MyAction * rightChannelAct; + + // Other groups + MyActionGroup * videoTrackGroup; + MyActionGroup * audioTrackGroup; + MyActionGroup * subtitleTrackGroup; + MyActionGroup * titleGroup; + MyActionGroup * angleGroup; + MyActionGroup * chapterGroup; + +#if DVDNAV_SUPPORT + MyAction * dvdnavUpAct; + MyAction * dvdnavDownAct; + MyAction * dvdnavLeftAct; + MyAction * dvdnavRightAct; + MyAction * dvdnavMenuAct; + MyAction * dvdnavSelectAct; + MyAction * dvdnavPrevAct; + MyAction * dvdnavMouseAct; +#endif + + // MENUS + QMenu *openMenu; + QMenu *playMenu; + QMenu *videoMenu; + QMenu *audioMenu; + QMenu *subtitlesMenu; + QMenu *browseMenu; + QMenu *optionsMenu; + QMenu *helpMenu; + + QMenu * subtitlestrack_menu; + QMenu * videotrack_menu; + QMenu * audiotrack_menu; + QMenu * titles_menu; + QMenu * chapters_menu; + QMenu * angles_menu; + QMenu * aspect_menu; + QMenu * osd_menu; + QMenu * deinterlace_menu; + //QMenu * denoise_menu; + QMenu * videosize_menu; + QMenu * audiochannels_menu; + QMenu * stereomode_menu; + + QMenu * speed_menu; + QMenu * videofilter_menu; + QMenu * audiofilter_menu; + QMenu * logs_menu; + QMenu * panscan_menu; + QMenu * rotate_menu; + QMenu * ontop_menu; +#if USE_ADAPTER + QMenu * screen_menu; +#endif + + QMenu * popup; + QMenu * recentfiles_menu; + + LogWindow * mplayer_log_window; + LogWindow * smplayer_log_window; + LogWindow * clhelp_window; + + PreferencesDialog *pref_dialog; + FilePropertiesDialog *file_dialog; + Playlist * playlist; + VideoEqualizer * video_equalizer; + AudioEqualizer * audio_equalizer; + FindSubtitlesWindow * find_subs_dialog; + VideoPreview * video_preview; + + Core * core; + MplayerWindow *mplayerwindow; + + MyServer * server; + + QStringList actions_list; + + QString pending_actions_to_run; + +private: + QString default_style; + + bool near_top; + bool near_bottom; + + // Variables to restore pos and size of the window + // when exiting from fullscreen mode. + QPoint win_pos; + QSize win_size; + bool was_maximized; + +#ifdef Q_OS_WIN + /* Disable screensaver by event */ + bool just_stopped; +#endif + + QString mplayer_log; + QString smplayer_log; + + bool ignore_show_hide_events; +}; + +#endif + diff --git a/plugins/smplayer_plugin/baseguiplus.cpp b/plugins/smplayer_plugin/baseguiplus.cpp new file mode 100644 index 000000000..acde37317 --- /dev/null +++ b/plugins/smplayer_plugin/baseguiplus.cpp @@ -0,0 +1,591 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "baseguiplus.h" +#include "config.h" +#include "myaction.h" +#include "global.h" +#include "images.h" +#include "playlist.h" + +#include "widgetactions.h" + +#include +#include +#include +#include + +#if DOCK_PLAYLIST +#include +#include "playlistdock.h" +#include "desktopinfo.h" + +#define PLAYLIST_ON_SIDES 1 +#endif + +using namespace Global; + +BaseGuiPlus::BaseGuiPlus( QWidget * parent, Qt::WindowFlags flags ) + : BaseGui( parent, flags ) +{ + // Initialize variables + mainwindow_visible = true; + //infowindow_visible = false; + trayicon_playlist_was_visible = false; + widgets_size = 0; +#if DOCK_PLAYLIST + fullscreen_playlist_was_visible = false; + fullscreen_playlist_was_floating = false; + compact_playlist_was_visible = false; + ignore_playlist_events = false; +#endif + + + mainwindow_pos = pos(); + + tray = new QSystemTrayIcon( Images::icon("logo", 22), this ); + + tray->setToolTip( "SMPlayer" ); + connect( tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); + + quitAct = new MyAction(this, "quit"); + connect( quitAct, SIGNAL(triggered()), this, SLOT(quit()) ); + openMenu->addAction(quitAct); + + showTrayAct = new MyAction(this, "show_tray_icon" ); + showTrayAct->setCheckable(true); + connect( showTrayAct, SIGNAL(toggled(bool)), + tray, SLOT(setVisible(bool)) ); + optionsMenu->addAction(showTrayAct); + + showAllAct = new MyAction(this, "restore/hide"); + connect( showAllAct, SIGNAL(triggered()), + this, SLOT(toggleShowAll()) ); + + + context_menu = new QMenu(this); + context_menu->addAction(showAllAct); + context_menu->addSeparator(); + context_menu->addAction(openFileAct); + context_menu->addMenu(recentfiles_menu); + context_menu->addAction(openDirectoryAct); + context_menu->addAction(openDVDAct); + context_menu->addAction(openURLAct); + context_menu->addSeparator(); + context_menu->addAction(playOrPauseAct); + context_menu->addAction(stopAct); + context_menu->addSeparator(); + context_menu->addAction(playPrevAct); + context_menu->addAction(playNextAct); + context_menu->addSeparator(); + context_menu->addAction(showPlaylistAct); + context_menu->addAction(showPreferencesAct); + context_menu->addSeparator(); + context_menu->addAction(quitAct); + + tray->setContextMenu( context_menu ); + +#if DOCK_PLAYLIST + // Playlistdock + playlistdock = new PlaylistDock(this); + playlistdock->setObjectName("playlistdock"); + playlistdock->setFloating(false); // To avoid that the playlist is visible for a moment + playlistdock->setWidget(playlist); + playlistdock->setAllowedAreas(Qt::TopDockWidgetArea | + Qt::BottomDockWidgetArea +#if PLAYLIST_ON_SIDES + | Qt::LeftDockWidgetArea | + Qt::RightDockWidgetArea +#endif + ); + addDockWidget(Qt::BottomDockWidgetArea, playlistdock); + playlistdock->hide(); + playlistdock->setFloating(true); // Floating by default + + connect( playlistdock, SIGNAL(closed()), this, SLOT(playlistClosed()) ); +#if USE_DOCK_TOPLEVEL_EVENT + connect( playlistdock, SIGNAL(topLevelChanged(bool)), + this, SLOT(dockTopLevelChanged(bool)) ); +#else + connect( playlistdock, SIGNAL(visibilityChanged(bool)), + this, SLOT(dockVisibilityChanged(bool)) ); +#endif // USE_DOCK_TOPLEVEL_EVENT + + ignore_playlist_events = false; +#endif // DOCK_PLAYLIST + + retranslateStrings(); + + loadConfig(); +} + +BaseGuiPlus::~BaseGuiPlus() { + saveConfig(); +} + +bool BaseGuiPlus::startHidden() { +#ifdef Q_OS_WIN + return false; +#else + if ( (!showTrayAct->isChecked()) || (mainwindow_visible) ) + return false; + else + return true; +#endif +} + +void BaseGuiPlus::closeEvent( QCloseEvent * e ) { + qDebug("BaseGuiPlus::closeEvent"); + e->ignore(); + closeWindow(); +} + +void BaseGuiPlus::closeWindow() { + qDebug("BaseGuiPlus::closeWindow"); + + if (tray->isVisible()) { + //e->ignore(); + exitFullscreen(); + showAll(false); // Hide windows + if (core->state() == Core::Playing) core->stop(); + + if (pref->balloon_count > 0) { + tray->showMessage( "SMPlayer", + tr("SMPlayer is still running here"), + QSystemTrayIcon::Information, 3000 ); + pref->balloon_count--; + } + + } else { + BaseGui::closeWindow(); + } + //tray->hide(); + +} + +void BaseGuiPlus::quit() { + qDebug("BaseGuiPlus::quit"); + BaseGui::closeWindow(); +} + +void BaseGuiPlus::retranslateStrings() { + BaseGui::retranslateStrings(); + + quitAct->change( Images::icon("exit"), tr("&Quit") ); + showTrayAct->change( Images::icon("systray"), tr("S&how icon in system tray") ); + + updateShowAllAct(); + +#if DOCK_PLAYLIST + playlistdock->setWindowTitle( tr("Playlist") ); +#endif +} + +void BaseGuiPlus::updateShowAllAct() { + if (isVisible()) + showAllAct->change( tr("&Hide") ); + else + showAllAct->change( tr("&Restore") ); +} + +void BaseGuiPlus::saveConfig() { + qDebug("BaseGuiPlus::saveConfig"); + + QSettings * set = settings; + + set->beginGroup( "base_gui_plus"); + + set->setValue( "show_tray_icon", showTrayAct->isChecked() ); + set->setValue( "mainwindow_visible", isVisible() ); + + set->setValue( "trayicon_playlist_was_visible", trayicon_playlist_was_visible ); + set->setValue( "widgets_size", widgets_size ); +#if DOCK_PLAYLIST + set->setValue( "fullscreen_playlist_was_visible", fullscreen_playlist_was_visible ); + set->setValue( "fullscreen_playlist_was_floating", fullscreen_playlist_was_floating ); + set->setValue( "compact_playlist_was_visible", compact_playlist_was_visible ); + set->setValue( "ignore_playlist_events", ignore_playlist_events ); +#endif + +/* +#if DOCK_PLAYLIST + set->setValue( "playlist_and_toolbars_state", saveState() ); +#endif +*/ + + set->endGroup(); +} + +void BaseGuiPlus::loadConfig() { + qDebug("BaseGuiPlus::loadConfig"); + + QSettings * set = settings; + + set->beginGroup( "base_gui_plus"); + + bool show_tray_icon = set->value( "show_tray_icon", false).toBool(); + showTrayAct->setChecked( show_tray_icon ); + //tray->setVisible( show_tray_icon ); + + mainwindow_visible = set->value("mainwindow_visible", true).toBool(); + + trayicon_playlist_was_visible = set->value( "trayicon_playlist_was_visible", trayicon_playlist_was_visible ).toBool(); + widgets_size = set->value( "widgets_size", widgets_size ).toInt(); +#if DOCK_PLAYLIST + fullscreen_playlist_was_visible = set->value( "fullscreen_playlist_was_visible", fullscreen_playlist_was_visible ).toBool(); + fullscreen_playlist_was_floating = set->value( "fullscreen_playlist_was_floating", fullscreen_playlist_was_floating ).toBool(); + compact_playlist_was_visible = set->value( "compact_playlist_was_visible", compact_playlist_was_visible ).toBool(); + ignore_playlist_events = set->value( "ignore_playlist_events", ignore_playlist_events ).toBool(); +#endif + +/* +#if DOCK_PLAYLIST + restoreState( set->value( "playlist_and_toolbars_state" ).toByteArray() ); +#endif +*/ + + set->endGroup(); + + updateShowAllAct(); +} + + +void BaseGuiPlus::trayIconActivated(QSystemTrayIcon::ActivationReason reason) { + qDebug("DefaultGui::trayIconActivated: %d", reason); + + updateShowAllAct(); + + if (reason == QSystemTrayIcon::Trigger) { + toggleShowAll(); + } + else + if (reason == QSystemTrayIcon::MiddleClick) { + core->pause(); + } +} + +void BaseGuiPlus::toggleShowAll() { + // Ignore if tray is not visible + if (tray->isVisible()) { + showAll( !isVisible() ); + } +} + +void BaseGuiPlus::showAll(bool b) { + if (!b) { + // Hide all +#if DOCK_PLAYLIST + trayicon_playlist_was_visible = (playlistdock->isVisible() && + playlistdock->isFloating() ); + if (trayicon_playlist_was_visible) + playlistdock->hide(); + + /* + trayicon_playlist_was_visible = playlistdock->isVisible(); + playlistdock->hide(); + */ +#else + trayicon_playlist_was_visible = playlist->isVisible(); + playlist_pos = playlist->pos(); + playlist->hide(); +#endif + + mainwindow_pos = pos(); + hide(); + + /* + infowindow_visible = info_window->isVisible(); + infowindow_pos = info_window->pos(); + info_window->hide(); + */ + } else { + // Show all + move(mainwindow_pos); + show(); + +#if DOCK_PLAYLIST + if (trayicon_playlist_was_visible) { + playlistdock->show(); + } +#else + if (trayicon_playlist_was_visible) { + playlist->move(playlist_pos); + playlist->show(); + } +#endif + + /* + if (infowindow_visible) { + info_window->show(); + info_window->move(infowindow_pos); + } + */ + } + updateShowAllAct(); +} + +void BaseGuiPlus::resizeWindow(int w, int h) { + qDebug("BaseGuiPlus::resizeWindow: %d, %d", w, h); + + if ( (tray->isVisible()) && (!isVisible()) ) showAll(true); + + BaseGui::resizeWindow(w, h ); +} + +void BaseGuiPlus::updateMediaInfo() { + qDebug("BaseGuiPlus::updateMediaInfo"); + BaseGui::updateMediaInfo(); + + tray->setToolTip( windowTitle() ); +} + +void BaseGuiPlus::setWindowCaption(const QString & title) { + tray->setToolTip( title ); + + BaseGui::setWindowCaption( title ); +} + + +// Playlist stuff +void BaseGuiPlus::aboutToEnterFullscreen() { + qDebug("BaseGuiPlus::aboutToEnterFullscreen"); + + BaseGui::aboutToEnterFullscreen(); + +#if DOCK_PLAYLIST + int playlist_screen = QApplication::desktop()->screenNumber(playlistdock); + int mainwindow_screen = QApplication::desktop()->screenNumber(this); + qDebug("BaseGuiPlus::aboutToEnterFullscreen: mainwindow screen: %d, playlist screen: %d", mainwindow_screen, playlist_screen); + + fullscreen_playlist_was_visible = playlistdock->isVisible(); + fullscreen_playlist_was_floating = playlistdock->isFloating(); + + ignore_playlist_events = true; + + // Hide the playlist if it's in the same screen as the main window + if ((playlist_screen == mainwindow_screen) /* || + (!fullscreen_playlist_was_floating) */ ) + { + playlistdock->setFloating(true); + playlistdock->hide(); + } +#endif +} + +void BaseGuiPlus::aboutToExitFullscreen() { + qDebug("BaseGuiPlus::aboutToExitFullscreen"); + + BaseGui::aboutToExitFullscreen(); + +#if DOCK_PLAYLIST + if (fullscreen_playlist_was_visible) { + playlistdock->show(); + } + playlistdock->setFloating( fullscreen_playlist_was_floating ); + ignore_playlist_events = false; +#endif +} + +void BaseGuiPlus::aboutToEnterCompactMode() { +#if DOCK_PLAYLIST + compact_playlist_was_visible = (playlistdock->isVisible() && + !playlistdock->isFloating()); + if (compact_playlist_was_visible) + playlistdock->hide(); +#endif + + widgets_size = height() - panel->height(); + qDebug("BaseGuiPlus::aboutToEnterCompactMode: widgets_size: %d", widgets_size); + + BaseGui::aboutToEnterCompactMode(); + + if (pref->resize_method == Preferences::Always) { + resize( width(), height() - widgets_size ); + } +} + +void BaseGuiPlus::aboutToExitCompactMode() { + BaseGui::aboutToExitCompactMode(); + + if (pref->resize_method == Preferences::Always) { + resize( width(), height() + widgets_size ); + } + +#if DOCK_PLAYLIST + if (compact_playlist_was_visible) + playlistdock->show(); +#endif +} + +#if DOCK_PLAYLIST +void BaseGuiPlus::showPlaylist(bool b) { + qDebug("BaseGuiPlus::showPlaylist: %d", b); + qDebug("BaseGuiPlus::showPlaylist (before): playlist visible: %d", playlistdock->isVisible()); + qDebug("BaseGuiPlus::showPlaylist (before): playlist position: %d, %d", playlistdock->pos().x(), playlistdock->pos().y()); + qDebug("BaseGuiPlus::showPlaylist (before): playlist size: %d x %d", playlistdock->size().width(), playlistdock->size().height()); + + if ( !b ) { + playlistdock->hide(); + } else { + exitFullscreenIfNeeded(); + playlistdock->show(); + + // Check if playlist is outside of the screen + if (playlistdock->isFloating()) { + if (!DesktopInfo::isInsideScreen(playlistdock)) { + qWarning("BaseGuiPlus::showPlaylist: playlist is outside of the screen"); + playlistdock->move(0,0); + } + } + } + //updateWidgets(); + + qDebug("BaseGuiPlus::showPlaylist (after): playlist visible: %d", playlistdock->isVisible()); + qDebug("BaseGuiPlus::showPlaylist (after): playlist position: %d, %d", playlistdock->pos().x(), playlistdock->pos().y()); + qDebug("BaseGuiPlus::showPlaylist (after): playlist size: %d x %d", playlistdock->size().width(), playlistdock->size().height()); + +} + +void BaseGuiPlus::playlistClosed() { + showPlaylistAct->setChecked(false); +} + +#if !USE_DOCK_TOPLEVEL_EVENT +void BaseGuiPlus::dockVisibilityChanged(bool visible) { + qDebug("BaseGuiPlus::dockVisibilityChanged: %d", visible); + + if (!playlistdock->isFloating()) { + if (!visible) shrinkWindow(); else stretchWindow(); + } +} + +#else + +void BaseGuiPlus::dockTopLevelChanged(bool floating) { + qDebug("BaseGuiPlus::dockTopLevelChanged: %d", floating); + + if (floating) shrinkWindow(); else stretchWindow(); +} +#endif + +void BaseGuiPlus::stretchWindow() { + qDebug("BaseGuiPlus::stretchWindow"); + if ((ignore_playlist_events) || (pref->resize_method!=Preferences::Always)) return; + + qDebug("BaseGuiPlus::stretchWindow: dockWidgetArea: %d", (int) dockWidgetArea(playlistdock) ); + + if ( (dockWidgetArea(playlistdock) == Qt::TopDockWidgetArea) || + (dockWidgetArea(playlistdock) == Qt::BottomDockWidgetArea) ) + { + int new_height = height() + playlistdock->height(); + + //if (new_height > DesktopInfo::desktop_size(this).height()) + // new_height = DesktopInfo::desktop_size(this).height() - 20; + + qDebug("BaseGuiPlus::stretchWindow: stretching: new height: %d", new_height); + resize( width(), new_height ); + + //resizeWindow(core->mset.win_width, core->mset.win_height); + } + + else + + if ( (dockWidgetArea(playlistdock) == Qt::LeftDockWidgetArea) || + (dockWidgetArea(playlistdock) == Qt::RightDockWidgetArea) ) + { + int new_width = width() + playlistdock->width(); + + qDebug("BaseGuiPlus::stretchWindow: stretching: new width: %d", new_width); + resize( new_width, height() ); + } +} + +void BaseGuiPlus::shrinkWindow() { + qDebug("BaseGuiPlus::shrinkWindow"); + if ((ignore_playlist_events) || (pref->resize_method!=Preferences::Always)) return; + + qDebug("BaseGuiPlus::shrinkWindow: dockWidgetArea: %d", (int) dockWidgetArea(playlistdock) ); + + if ( (dockWidgetArea(playlistdock) == Qt::TopDockWidgetArea) || + (dockWidgetArea(playlistdock) == Qt::BottomDockWidgetArea) ) + { + int new_height = height() - playlistdock->height(); + qDebug("DefaultGui::shrinkWindow: shrinking: new height: %d", new_height); + resize( width(), new_height ); + + //resizeWindow(core->mset.win_width, core->mset.win_height); + } + + else + + if ( (dockWidgetArea(playlistdock) == Qt::LeftDockWidgetArea) || + (dockWidgetArea(playlistdock) == Qt::RightDockWidgetArea) ) + { + int new_width = width() - playlistdock->width(); + + qDebug("BaseGuiPlus::shrinkWindow: shrinking: new width: %d", new_width); + resize( new_width, height() ); + } +} + +#endif + +// Convenience functions intended for other GUI's +TimeSliderAction * BaseGuiPlus::createTimeSliderAction(QWidget * parent) { + TimeSliderAction * timeslider_action = new TimeSliderAction( parent ); + timeslider_action->setObjectName("timeslider_action"); + +#ifdef SEEKBAR_RESOLUTION + connect( timeslider_action, SIGNAL( posChanged(int) ), + core, SLOT(goToPosition(int)) ); + connect( core, SIGNAL(positionChanged(int)), + timeslider_action, SLOT(setPos(int)) ); +#else + connect( timeslider_action, SIGNAL( posChanged(int) ), + core, SLOT(goToPos(int)) ); + connect( core, SIGNAL(posChanged(int)), + timeslider_action, SLOT(setPos(int)) ); +#endif + connect( timeslider_action, SIGNAL( draggingPos(int) ), + this, SLOT(displayGotoTime(int)) ); +#if ENABLE_DELAYED_DRAGGING + timeslider_action->setDragDelay( pref->time_slider_drag_delay ); + + connect( timeslider_action, SIGNAL( delayedDraggingPos(int) ), + this, SLOT(goToPosOnDragging(int)) ); +#else + connect( timeslider_action, SIGNAL( draggingPos(int) ), + this, SLOT(goToPosOnDragging(int)) ); +#endif + return timeslider_action; +} + +VolumeSliderAction * BaseGuiPlus::createVolumeSliderAction(QWidget * parent) { + VolumeSliderAction * volumeslider_action = new VolumeSliderAction(parent); + volumeslider_action->setObjectName("volumeslider_action"); + + connect( volumeslider_action, SIGNAL( valueChanged(int) ), + core, SLOT( setVolume(int) ) ); + connect( core, SIGNAL(volumeChanged(int)), + volumeslider_action, SLOT(setValue(int)) ); + + return volumeslider_action; +} + +#include "moc_baseguiplus.cpp" diff --git a/plugins/smplayer_plugin/baseguiplus.h b/plugins/smplayer_plugin/baseguiplus.h new file mode 100644 index 000000000..e8f816c31 --- /dev/null +++ b/plugins/smplayer_plugin/baseguiplus.h @@ -0,0 +1,117 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _BASEGUIPLUS_H_ +#define _BASEGUIPLUS_H_ + +#include "basegui.h" +#include +#include +#include "guiconfig.h" + +class QMenu; +class PlaylistDock; + +class TimeSliderAction; +class VolumeSliderAction; + +class BaseGuiPlus : public BaseGui +{ + Q_OBJECT + +public: + BaseGuiPlus( QWidget* parent = 0, Qt::WindowFlags flags = 0 ); + ~BaseGuiPlus(); + + virtual bool startHidden(); + +protected: + virtual void retranslateStrings(); + + void loadConfig(); + void saveConfig(); + void updateShowAllAct(); + + virtual void aboutToEnterFullscreen(); + virtual void aboutToExitFullscreen(); + virtual void aboutToEnterCompactMode(); + virtual void aboutToExitCompactMode(); + + virtual void closeEvent( QCloseEvent * e ); + + // Functions for other GUI's + TimeSliderAction * createTimeSliderAction(QWidget * parent); + VolumeSliderAction * createVolumeSliderAction(QWidget * parent); + +protected slots: + // Reimplemented methods + virtual void closeWindow(); + virtual void setWindowCaption(const QString & title); + virtual void resizeWindow(int w, int h); + virtual void updateMediaInfo(); + // New + virtual void trayIconActivated(QSystemTrayIcon::ActivationReason); + virtual void toggleShowAll(); + virtual void showAll(bool b); + virtual void quit(); + +#if DOCK_PLAYLIST + virtual void showPlaylist(bool b); + void playlistClosed(); + +#if !USE_DOCK_TOPLEVEL_EVENT + void dockVisibilityChanged(bool visible); +#else + void dockTopLevelChanged(bool floating); +#endif + + void stretchWindow(); + void shrinkWindow(); +#endif + +protected: + QSystemTrayIcon * tray; + QMenu * context_menu; + + MyAction * quitAct; + MyAction * showTrayAct; + MyAction * showAllAct; + + // To save state + QPoint mainwindow_pos; + bool mainwindow_visible; + + QPoint playlist_pos; + bool trayicon_playlist_was_visible; + + //QPoint infowindow_pos; + //bool infowindow_visible; + + int widgets_size; // To be able to restore the original size after exiting from compact mode + +#if DOCK_PLAYLIST + PlaylistDock * playlistdock; + bool fullscreen_playlist_was_visible; + bool fullscreen_playlist_was_floating; + bool compact_playlist_was_visible; + bool ignore_playlist_events; +#endif + +}; + +#endif diff --git a/plugins/smplayer_plugin/clhelp.cpp b/plugins/smplayer_plugin/clhelp.cpp new file mode 100644 index 000000000..51ae47228 --- /dev/null +++ b/plugins/smplayer_plugin/clhelp.cpp @@ -0,0 +1,176 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "clhelp.h" +#include +#include +#include + +QString CLHelp::formatText(QString s, int col) { + QString res = ""; + + int last = 0; + int pos; + + pos = s.indexOf(" "); + while (pos != -1) { + + if (s.count() < col) { + res = res + s; + s = ""; + break; + } + + while ((pos < col) && (pos != -1)) { + last = pos; + pos = s.indexOf(" ", pos+1); + } + + res = res + s.left(last) + "\n"; + s = s.mid(last+1); + + last = 0; + pos = s.indexOf(" "); + + } + + if (!s.isEmpty()) res = res + s; + + return res; +} + +QString CLHelp::formatHelp(QString parameter, QString help, bool html) { + if (html) { + return ""+parameter+""+help+""; + } else { + int par_width = 20; + int help_width = 80 - par_width; + + QString s; + s = s.fill( ' ', par_width - (parameter.count()+2) ); + s = s + parameter + ": "; + + QString f; + f = f.fill(' ', par_width); + + QString s2 = formatText(help, help_width); + int pos = s2.indexOf('\n'); + while (pos != -1) { + s2 = s2.insert(pos+1, f); + pos = s2.indexOf('\n', pos+1); + } + + return s + s2 + "\n"; + } +} + + +QString CLHelp::help(bool html) { + QString app_name = QFileInfo(qApp->applicationFilePath()).baseName(); + + QString options = QString("%1 [-minigui] [-defaultgui] [-mpcgui] [-config-path %2] " + "[-send-action %3] [-actions %4] " + "[-close-at-end] [-no-close-at-end] [-fullscreen] [-no-fullscreen] " + "[-sub %5] " + "[-add-to-playlist] [-help|--help|-h|-?] " + "[[-playlist] %6] [[-playlist] %6]...") + .arg(app_name) + .arg(QObject::tr("directory")) + .arg(QObject::tr("action_name")) + .arg(QObject::tr("action_list")) + .arg(QObject::tr("subtitle_file")) + .arg(QObject::tr("media")); + + QString s; + + if (html) { + s = QObject::tr("Usage:") + " " + options + "
    "; + s += ""; + } else { + s = formatText(QObject::tr("Usage:") + " " + options, 80); + s += "\n\n"; + } + +#ifdef Q_OS_WIN + s += formatHelp( "-uninstall", QObject::tr( + "Restores the old associations and cleans up the registry."), html ); +#endif + s += formatHelp( "-minigui", QObject::tr( + "opens the mini gui instead of the default one."), html ); + + s += formatHelp( "-mpcgui", QObject::tr( + "opens the mpc gui."), html ); + + s += formatHelp( "-defaultgui", QObject::tr( + "opens the default gui."), html ); + + s += formatHelp( "-config-path", QObject::tr( + "specifies the directory where smplayer will store its configuration " + "files (smplayer.ini, smplayer_files.ini...)"), html ); + + s += formatHelp( "-send-action", QObject::tr( + "tries to make a connection to another running instance " + "and send to it the specified action. Example: -send-action pause " + "The rest of options (if any) will be ignored and the " + "application will exit. It will return 0 on success or -1 " + "on failure."), html ); + + s += formatHelp( "-actions", QObject::tr( + "action_list is a list of actions separated by spaces. " + "The actions will be executed just after loading the file (if any) " + "in the same order you entered. For checkable actions you can pass " + "true or false as parameter. Example: " + "-actions \"fullscreen compact true\". Quotes are necessary in " + "case you pass more than one action."), html ); + + s += formatHelp( "-close-at-end", QObject::tr( + "the main window will be closed when the file/playlist finishes."), html ); + + s += formatHelp( "-no-close-at-end", QObject::tr( + "the main window won't be closed when the file/playlist finishes."), html ); + + s += formatHelp( "-fullscreen", QObject::tr( + "the video will be played in fullscreen mode."), html ); + + s += formatHelp( "-no-fullscreen", QObject::tr( + "the video will be played in window mode."), html ); + + s += formatHelp( "-sub", QObject::tr( + "specifies the subtitle file to be loaded for the first video."), html ); + + s += formatHelp( "-help", QObject::tr( + "will show this message and then will exit."), html ); + + s += formatHelp( "-add-to-playlist", QObject::tr( + "if there's another instance running, the media will be added " + "to that instance's playlist. If there's no other instance, " + "this option will be ignored and the " + "files will be opened in a new instance."), html ); + + s += formatHelp( QObject::tr("media"), QObject::tr( + "'media' is any kind of file that SMPlayer can open. It can " + "be a local file, a DVD (e.g. dvd://1), an Internet stream " + "(e.g. mms://....) or a local playlist in format m3u or pls. " + "If the -playlist option is used, that means that SMPlayer " + "will pass the -playlist option to MPlayer, so MPlayer will " + "handle the playlist, not SMPlayer."), html ); + + if (html) s += "
    "; + + return s; +} diff --git a/plugins/smplayer_plugin/clhelp.h b/plugins/smplayer_plugin/clhelp.h new file mode 100644 index 000000000..237676be1 --- /dev/null +++ b/plugins/smplayer_plugin/clhelp.h @@ -0,0 +1,31 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +//! Provides help about the comand line options. + +class CLHelp +{ +public: + static QString help(bool html = false); + +protected: + static QString formatText(QString s, int col); + static QString formatHelp(QString parameter, QString help, bool html = false); +}; diff --git a/plugins/smplayer_plugin/colorutils.cpp b/plugins/smplayer_plugin/colorutils.cpp new file mode 100644 index 000000000..13d797450 --- /dev/null +++ b/plugins/smplayer_plugin/colorutils.cpp @@ -0,0 +1,73 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "colorutils.h" +#include + +QString ColorUtils::colorToRRGGBBAA(unsigned int color) { + QColor c; + c.setRgb( color ); + + QString s; + return s.sprintf("%02x%02x%02x00", c.red(), c.green(), c.blue() ); +} + +QString ColorUtils::colorToRRGGBB(unsigned int color) { + QColor c; + c.setRgb( color ); + + QString s; + return s.sprintf("%02x%02x%02x", c.red(), c.green(), c.blue() ); +} + +QString ColorUtils::colorToRGB(unsigned int color) { + QColor c; + c.setRgb( color ); + + QString s; + return s.sprintf("0x%02x%02x%02x", c.blue(), c.green(), c.red() ); +} + +QString ColorUtils::colorToAABBGGRR(unsigned int color) { + QColor c; + c.setRgb( color ); + + QString s; + return s.sprintf("00%02x%02x%02x", c.blue(), c.green(), c.red() ); +} + +void ColorUtils::setForegroundColor(QWidget * w, const QColor & color) { + QPalette p = w->palette(); + p.setColor(w->foregroundRole(), color); + w->setPalette(p); +} + +void ColorUtils::setBackgroundColor(QWidget * w, const QColor & color) { + QPalette p = w->palette(); + p.setColor(w->backgroundRole(), color); + w->setPalette(p); +} + +#if COLOR_OUTPUT_SUPPORT +QString ColorUtils::stripColorsTags(QString s) { + QRegExp rx_console_colors("\033\\[\\d\\d?;\\d\\d?m"); + int removePos = rx_console_colors.lastIndexIn(s); + removePos += rx_console_colors.matchedLength(); + return s.remove(0, removePos); +} +#endif diff --git a/plugins/smplayer_plugin/colorutils.h b/plugins/smplayer_plugin/colorutils.h new file mode 100644 index 000000000..8512d04c3 --- /dev/null +++ b/plugins/smplayer_plugin/colorutils.h @@ -0,0 +1,66 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _COLORUTILS_H_ +#define _COLORUTILS_H_ + +#include + +#ifndef Q_OS_WIN +#define COLOR_OUTPUT_SUPPORT 1 +#endif + +class QWidget; +class QColor; + +class ColorUtils { + +public: + + //! Returns a string suitable to be used for -ass-color + static QString colorToRRGGBBAA(unsigned int color); + static QString colorToRRGGBB(unsigned int color); + + //! Returns a string suitable to be used for -colorkey + static QString colorToRGB(unsigned int color); + + static QString colorToAABBGGRR(unsigned int color); + + //! Changes the foreground color of the specified widget + static void setForegroundColor(QWidget * w, const QColor & color); + + //! Changes the background color of the specified widget + static void setBackgroundColor(QWidget * w, const QColor & color); + + /** + ** \brief Strip colors and tags from MPlayer output lines + ** + ** Some MPlayer configurations (configured with --enable-color-console) + ** use colored/tagged console output. This function removes those colors + ** and tags. + ** + ** \param s The string to strip colors and tags from + ** \return Returns a clean string (no colors, no tags) + */ +#if COLOR_OUTPUT_SUPPORT + static QString stripColorsTags(QString s); +#endif + +}; + +#endif diff --git a/plugins/smplayer_plugin/config.h b/plugins/smplayer_plugin/config.h new file mode 100644 index 000000000..bca38d923 --- /dev/null +++ b/plugins/smplayer_plugin/config.h @@ -0,0 +1,139 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#include + + +// Activate the new code for aspect ratio + +#define NEW_ASPECT_CODE 1 + + +// STYLE_SWITCHING +// if 1, the preferences dialog will have an option to switch +// the Qt style + +#define STYLE_SWITCHING 1 + + +// EXTERNAL_SLEEP +// if 1, it will be used the function usleep() from unistd.h +// instead of QThread::msleep() +// It can be useful if your Qt doesn't have QThread support. +// Note: not much test it +// Note 2: not used anymore + +#define EXTERNAL_SLEEP 0 + + +// ENABLE_DELAYED_DRAGGING +// if 1, sends the dragging position of the time slider +// some ms later + +#define ENABLE_DELAYED_DRAGGING 1 + + +// SEEKBAR_RESOLUTION +// if SEEKBAR_RESOLUTION is defined, it specified the +// maximum value of the time slider + +#define SEEKBAR_RESOLUTION 1000 + + +// SMART_DVD_CHAPTERS +// if set to 1, the slave command "chapter" will use if not using a cache, +// otherwise mplayer will be restarted and -chapter will be used. + +#define SMART_DVD_CHAPTERS 1 + + +// ALLOW_TO_HIDE_VIDEO_WINDOW_ON_AUDIO_FILES +// if 1, the video window may be hidden when playing audio files +// depending on the hide_video_window_on_audio_files option in +// the config file + +#define ALLOW_TO_HIDE_VIDEO_WINDOW_ON_AUDIO_FILES 1 + + +// DELAYED_AUDIO_SETUP_ON_STARTUP +// if 1, the audio track will be initialized later once the file +// has begun to play + +#define DELAYED_AUDIO_SETUP_ON_STARTUP 0 + + +// CHECK_VIDEO_CODEC_FOR_NO_VIDEO +// if 1, the video codec will be checked to decide if the file +// has video or not. If it's empty it has no video. +// If 0, it will check for the line "Video: no video" + +#define CHECK_VIDEO_CODEC_FOR_NO_VIDEO 1 + + +// Just for testing, possibility to disable the use of the colorkey + +#define USE_COLORKEY 1 + + +// USE_MINIMUMSIZE +// if 1, the main window will not be smaller than the control widget +// size hint or pref->gui_minimum_width. + +#define USE_MINIMUMSIZE 1 + + +// GENERIC_CHAPTER_SUPPORT +// if 1, it will use a generic code for chapters which can be used +// for all kind of videos, not only DVDs and mkv files. + +#define GENERIC_CHAPTER_SUPPORT 1 + + +// DVDNAV_SUPPORT +// if 1, smplayer will be compiled with support for mplayer's dvdnav + +#ifndef Q_OS_WIN +#define DVDNAV_SUPPORT 1 +#endif + + +// Adds or not the "Repaint the background of the video window" option. +//#ifndef Q_OS_WIN +#define REPAINT_BACKGROUND_OPTION 1 +//#endif + + +// Enables/disables the use of -adapter +#ifdef Q_OS_WIN +#define USE_ADAPTER 1 +#define OVERLAY_VO "directx" +//#define OVERLAY_VO "xv" +#endif + + +// If 1, smplayer will check if mplayer is old +// and in that case it will report to the user +#ifndef Q_OS_WIN +#define REPORT_OLD_MPLAYER 1 +#endif + + +#endif diff --git a/plugins/smplayer_plugin/constants.h b/plugins/smplayer_plugin/constants.h new file mode 100644 index 000000000..50b46224c --- /dev/null +++ b/plugins/smplayer_plugin/constants.h @@ -0,0 +1,29 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _CONSTANTS_H_ +#define _CONSTANTS_H_ + +#define COMPANY "RVM" +#define PROGRAM "smplayer" + +#define IS_PLAYLIST_TAG "|smplayer:isplaylist" +#define IS_PLAYLIST_TAG_RX "\\|smplayer\\:isplaylist$" + +#endif + diff --git a/plugins/smplayer_plugin/core.cpp b/plugins/smplayer_plugin/core.cpp new file mode 100644 index 000000000..1488b8286 --- /dev/null +++ b/plugins/smplayer_plugin/core.cpp @@ -0,0 +1,3741 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "core.h" +#include +#include +#include +#include + +#include + +#include "mplayerwindow.h" +#include "desktopinfo.h" +#include "helper.h" +#include "paths.h" +#include "preferences.h" +#include "global.h" +#include "config.h" +#include "mplayerversion.h" +#include "constants.h" +#include "colorutils.h" + +#ifdef Q_OS_WIN +#include // To change app priority +#include // To get Windows version +#include "screensaver.h" +#endif + +#ifndef NO_USE_INI_FILES +#include "filesettings.h" +#include "filesettingshash.h" +#endif + +using namespace Global; + +Core::Core( MplayerWindow *mpw, QWidget* parent ) + : QObject( parent ) +{ + qRegisterMetaType("Core::State"); + + mplayerwindow = mpw; + + _state = Stopped; + + we_are_restarting = false; + just_loaded_external_subs = false; + just_unloaded_external_subs = false; + change_volume_after_unpause = false; + +#ifndef NO_USE_INI_FILES + // Create file_settings + #if NEW_SETTINGS_MANAGEMENT + file_settings = 0; + changeFileSettingsMethod(pref->file_settings_method); + #else + if (Paths::iniPath().isEmpty()) { + file_settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, + QString(COMPANY), QString("smplayer_files") ); + } else { + QString filename = Paths::iniPath() + "/smplayer_files.ini"; + file_settings = new QSettings( filename, QSettings::IniFormat ); + qDebug("Core::Core: file_settings: '%s'", filename.toUtf8().data()); + } + #endif +#endif + + proc = new MplayerProcess(this); + + // Do this the first + connect( proc, SIGNAL(processExited()), + mplayerwindow->videoLayer(), SLOT(playingStopped()) ); + + connect( proc, SIGNAL(error(QProcess::ProcessError)), + mplayerwindow->videoLayer(), SLOT(playingStopped()) ); + + connect( proc, SIGNAL(receivedCurrentSec(double)), + this, SLOT(changeCurrentSec(double)) ); + + connect( proc, SIGNAL(receivedCurrentFrame(int)), + this, SIGNAL(showFrame(int)) ); + + connect( proc, SIGNAL(receivedPause()), + this, SLOT(changePause()) ); + + connect( proc, SIGNAL(processExited()), + this, SLOT(processFinished()), Qt::QueuedConnection ); + + connect( proc, SIGNAL(mplayerFullyLoaded()), + this, SLOT(finishRestart()), Qt::QueuedConnection ); + + connect( proc, SIGNAL(lineAvailable(QString)), + this, SIGNAL(logLineAvailable(QString)) ); + + connect( proc, SIGNAL(receivedCacheMessage(QString)), + this, SLOT(displayMessage(QString)) ); + + connect( proc, SIGNAL(receivedCreatingIndex(QString)), + this, SLOT(displayMessage(QString)) ); + + connect( proc, SIGNAL(receivedConnectingToMessage(QString)), + this, SLOT(displayMessage(QString)) ); + + connect( proc, SIGNAL(receivedResolvingMessage(QString)), + this, SLOT(displayMessage(QString)) ); + + connect( proc, SIGNAL(receivedScreenshot(QString)), + this, SLOT(displayScreenshotName(QString)) ); + + connect( proc, SIGNAL(receivedUpdatingFontCache()), + this, SLOT(displayUpdatingFontCache()) ); + + connect( proc, SIGNAL(receivedWindowResolution(int,int)), + this, SLOT(gotWindowResolution(int,int)) ); + + connect( proc, SIGNAL(receivedNoVideo()), + this, SLOT(gotNoVideo()) ); + + connect( proc, SIGNAL(receivedVO(QString)), + this, SLOT(gotVO(QString)) ); + + connect( proc, SIGNAL(receivedAO(QString)), + this, SLOT(gotAO(QString)) ); + + connect( proc, SIGNAL(receivedEndOfFile()), + this, SLOT(fileReachedEnd()), Qt::QueuedConnection ); + + connect( proc, SIGNAL(receivedStartingTime(double)), + this, SLOT(gotStartingTime(double)) ); + + connect( proc, SIGNAL(receivedStreamTitleAndUrl(QString,QString)), + this, SLOT(streamTitleAndUrlChanged(QString,QString)) ); + + connect( proc, SIGNAL(failedToParseMplayerVersion(QString)), + this, SIGNAL(failedToParseMplayerVersion(QString)) ); + + connect( this, SIGNAL(mediaLoaded()), this, SLOT(checkIfVideoIsHD()), Qt::QueuedConnection ); +#if DELAYED_AUDIO_SETUP_ON_STARTUP + connect( this, SIGNAL(mediaLoaded()), this, SLOT(initAudioTrack()), Qt::QueuedConnection ); +#endif +#if NOTIFY_SUB_CHANGES + connect( proc, SIGNAL(subtitleInfoChanged(const SubTracks &)), + this, SLOT(initSubtitleTrack(const SubTracks &)), Qt::QueuedConnection ); + connect( proc, SIGNAL(subtitleInfoReceivedAgain(const SubTracks &)), + this, SLOT(setSubtitleTrackAgain(const SubTracks &)), Qt::QueuedConnection ); +#endif +#if NOTIFY_AUDIO_CHANGES + connect( proc, SIGNAL(audioInfoChanged(const Tracks &)), + this, SLOT(initAudioTrack(const Tracks &)), Qt::QueuedConnection ); +#endif + + connect( this, SIGNAL(stateChanged(Core::State)), + this, SLOT(watchState(Core::State)) ); + + connect( proc, SIGNAL(error(QProcess::ProcessError)), + this, SIGNAL(mplayerFailed(QProcess::ProcessError)) ); + + //pref->load(); + mset.reset(); + + // Mplayerwindow + connect( this, SIGNAL(aboutToStartPlaying()), + mplayerwindow->videoLayer(), SLOT(playingStarted()) ); + +#if REPAINT_BACKGROUND_OPTION + mplayerwindow->videoLayer()->setRepaintBackground(pref->repaint_video_background); +#endif + mplayerwindow->setMonitorAspect( pref->monitor_aspect_double() ); + +#ifdef Q_OS_WIN + // Windows screensaver + win_screensaver = new WinScreenSaver(); +#endif +} + + +Core::~Core() { +#ifndef NO_USE_INI_FILES + saveMediaInfo(); +#endif + + if (proc->isRunning()) stopMplayer(); + proc->terminate(); + delete proc; + +#ifndef NO_USE_INI_FILES + delete file_settings; +#endif + +#ifdef Q_OS_WIN + delete win_screensaver; +#endif +} + +#ifndef NO_USE_INI_FILES +void Core::changeFileSettingsMethod(QString method) { +#if NEW_SETTINGS_MANAGEMENT + qDebug("Core::changeFileSettingsMethod: %s", method.toUtf8().constData()); + if (file_settings) delete file_settings; + + if (method.toLower() == "hash") + file_settings = new FileSettingsHash(Paths::iniPath()); + else + file_settings = new FileSettings(Paths::iniPath()); +#endif +} +#endif + +void Core::setState(State s) { + if (s != _state) { + _state = s; + emit stateChanged(_state); + } +} + +QString Core::stateToString() { + if (state()==Playing) return "Playing"; + else + if (state()==Stopped) return "Stopped"; + else + if (state()==Paused) return "Paused"; + else + return "Unknown"; +} + +// Public restart +void Core::restart() { + qDebug("Core::restart"); + if (proc->isRunning()) { + restartPlay(); + } else { + qDebug("Core::restart: mplayer is not running"); + } +} + +void Core::reload() { + qDebug("Core::reload"); + + stopMplayer(); + we_are_restarting = false; + + initPlaying(); +} + +#ifndef NO_USE_INI_FILES +#if !NEW_SETTINGS_MANAGEMENT + +bool Core::checkHaveSettingsSaved(QString group_name) { + qDebug("Core::checkHaveSettingsSaved: group_name: '%s'", group_name.toUtf8().data()); + + file_settings->beginGroup( group_name ); + bool saved = file_settings->value( "saved", false ).toBool(); + file_settings->endGroup(); + + return saved; +} + +void Core::loadMediaInfo(QString group_name) { + qDebug("Core::loadMediaInfo: '%s'", group_name.toUtf8().data() ); + + file_settings->beginGroup( group_name ); + + /*mdat.load(*settings);*/ + mset.load(file_settings); + + file_settings->endGroup(); +} + +#endif // NEW_SETTINGS_MANAGEMENT + +void Core::saveMediaInfo() { + qDebug("Core::saveMediaInfo"); + + if (pref->dont_remember_media_settings) { + qDebug("Core::saveMediaInfo: not saving settings, disabled by user"); + return; + } + +#if NEW_SETTINGS_MANAGEMENT + if ( (mdat.type == TYPE_FILE) && (!mdat.filename.isEmpty()) ) { + file_settings->saveSettingsFor(mdat.filename, mset); + } +#else + QString group_name; + + /* + if ( (mdat.type == TYPE_DVD) && (!mdat.dvd_id.isEmpty()) ) { + group_name = dvdForPref( mdat.dvd_id, mset.current_title_id ); + } + else + */ + if ( (mdat.type == TYPE_FILE) && (!mdat.filename.isEmpty()) ) { + group_name = FileSettings::filenameToGroupname( mdat.filename ); + } + + if (!group_name.isEmpty()) { + file_settings->beginGroup( group_name ); + file_settings->setValue( "saved", true); + + /*mdat.save(*settings);*/ + mset.save(file_settings); + + file_settings->endGroup(); + } +#endif // NEW_SETTINGS_MANAGEMENT +} + +#endif // NO_USE_INI_FILES + +void Core::initializeMenus() { + qDebug("Core::initializeMenus"); + + emit menusNeedInitialize(); +} + + +void Core::updateWidgets() { + qDebug("Core::updateWidgets"); + + emit widgetsNeedUpdate(); +} + + +void Core::tellmp(const QString & command) { + qDebug("Core::tellmp: '%s'", command.toUtf8().data()); + + //qDebug("Command: '%s'", command.toUtf8().data()); + if (proc->isRunning()) { + proc->writeToStdin( command ); + } else { + qWarning(" tellmp: no process running: %s", command.toUtf8().data()); + } +} + +// Generic open, autodetect type +void Core::open(QString file, int seek) { + qDebug("Core::open: '%s'", file.toUtf8().data()); + + QFileInfo fi(file); + + if ( (fi.exists()) && (fi.suffix().toLower()=="iso") ) { + qDebug("Core::open: * identified as a dvd iso"); + openDVD("dvd://1:" + file); + } + else + if ( (fi.exists()) && (!fi.isDir()) ) { + qDebug("Core::open: * identified as local file"); + // Local file + file = QFileInfo(file).absoluteFilePath(); + openFile(file, seek); + } + else + if ( (fi.exists()) && (fi.isDir()) ) { + // Directory + qDebug("Core::open: * identified as a directory"); + qDebug("Core::open: checking if contains a dvd"); + file = QFileInfo(file).absoluteFilePath(); + if (Helper::directoryContainsDVD(file)) { + qDebug("Core::open: * directory contains a dvd"); + openDVD("dvd://1:"+ file); + } else { + qDebug("Core::open: * directory doesn't contain a dvd"); + qDebug("Core::open: opening nothing"); + } + } + else + if (file.toLower().startsWith("dvd:")) { + qDebug("Core::open: * identified as dvd"); + openDVD(file); + /* + QString f = file.lower(); + QRegExp s("^dvd://(\\d+)"); + if (s.indexIn(f) != -1) { + int title = s.cap(1).toInt(); + openDVD(title); + } else { + qWarning("Core::open: couldn't parse dvd title, playing first one"); + openDVD(); + } + */ + } + else + if (file.toLower().startsWith("vcd:")) { + qDebug("Core::open: * identified as vcd"); + + QString f = file.toLower(); + QRegExp s("^vcd://(\\d+)"); + if (s.indexIn(f) != -1) { + int title = s.cap(1).toInt(); + openVCD(title); + } else { + qWarning("Core::open: couldn't parse vcd title, playing first one"); + openVCD(); + } + } + else + if (file.toLower().startsWith("cdda:")) { + qDebug("Core::open: * identified as cdda"); + + QString f = file.toLower(); + QRegExp s("^cdda://(\\d+)"); + if (s.indexIn(f) != -1) { + int title = s.cap(1).toInt(); + openAudioCD(title); + } else { + qWarning("Core::open: couldn't parse cdda title, playing first one"); + openAudioCD(); + } + } + else { + qDebug("Core::open: * not identified, playing as stream"); + openStream(file); + } +} + +void Core::openFile(QString filename, int seek) { + qDebug("Core::openFile: '%s'", filename.toUtf8().data()); + + QFileInfo fi(filename); + if (fi.exists()) { + playNewFile(fi.absoluteFilePath(), seek); + } else { + //File doesn't exists + //TODO: error message + } +} + + +void Core::loadSub(const QString & sub ) { + if ( !sub.isEmpty() ) { + //tellmp( "sub_load " + sub ); + mset.external_subtitles = sub; + just_loaded_external_subs = true; + restartPlay(); + } +} + +void Core::unloadSub() { + if ( !mset.external_subtitles.isEmpty() ) { + mset.external_subtitles = ""; + just_unloaded_external_subs = true; + restartPlay(); + } +} + +void Core::loadAudioFile(const QString & audiofile) { + if (!audiofile.isEmpty()) { + mset.external_audio = audiofile; + restartPlay(); + } +} + +void Core::unloadAudioFile() { + if (!mset.external_audio.isEmpty()) { + mset.external_audio = ""; + restartPlay(); + } +} + +/* +void Core::openDVD( bool from_folder, QString directory) { + qDebug("Core::openDVD"); + + if (from_folder) { + if (!directory.isEmpty()) { + QFileInfo fi(directory); + if ( (fi.exists()) && (fi.isDir()) ) { + pref->dvd_directory = directory; + pref->play_dvd_from_hd = TRUE; + openDVD(); + } else { + qDebug("Core::openDVD: directory '%s' is not valid", directory.toUtf8().data()); + } + } else { + qDebug("Core::openDVD: directory is empty"); + } + } else { + pref->play_dvd_from_hd = FALSE; + openDVD(); + } +} + +void Core::openDVD() { + openDVD(1); +} + +void Core::openDVD(int title) { + qDebug("Core::openDVD: %d", title); + + if (proc->isRunning()) { + stopMplayer(); + } + + // Save data of previous file: + saveMediaInfo(); + + mdat.reset(); + mdat.filename = "dvd://" + QString::number(title); + mdat.type = TYPE_DVD; + + mset.reset(); + + mset.current_title_id = title; + mset.current_chapter_id = 1; + mset.current_angle_id = 1; + + initializeMenus(); + + initPlaying(); +} +*/ + +void Core::openVCD(int title) { + qDebug("Core::openVCD: %d", title); + + if (title == -1) title = pref->vcd_initial_title; + + if (proc->isRunning()) { + stopMplayer(); + } + + // Save data of previous file: +#ifndef NO_USE_INI_FILES + saveMediaInfo(); +#endif + + mdat.reset(); + mdat.filename = "vcd://" + QString::number(title); + mdat.type = TYPE_VCD; + + mset.reset(); + + mset.current_title_id = title; + mset.current_chapter_id = -1; + mset.current_angle_id = -1; + + /* initializeMenus(); */ + + initPlaying(); +} + +void Core::openAudioCD(int title) { + qDebug("Core::openAudioCD: %d", title); + + if (title == -1) title = 1; + + if (proc->isRunning()) { + stopMplayer(); + } + + // Save data of previous file: +#ifndef NO_USE_INI_FILES + saveMediaInfo(); +#endif + + mdat.reset(); + mdat.filename = "cdda://" + QString::number(title); + mdat.type = TYPE_AUDIO_CD; + + mset.reset(); + + mset.current_title_id = title; + mset.current_chapter_id = -1; + mset.current_angle_id = -1; + + /* initializeMenus(); */ + + initPlaying(); +} + +void Core::openDVD(QString dvd_url) { + qDebug("Core::openDVD: '%s'", dvd_url.toUtf8().data()); + + //Checks + QString folder = Helper::dvdSplitFolder(dvd_url); + int title = Helper::dvdSplitTitle(dvd_url); + + if (title == -1) { + qWarning("Core::openDVD: title invalid, not playing dvd"); + return; + } + + if (folder.isEmpty()) { + qDebug("Core::openDVD: not folder"); + } else { + QFileInfo fi(folder); + if ( (!fi.exists()) /*|| (!fi.isDir())*/ ) { + qWarning("Core::openDVD: folder invalid, not playing dvd"); + return; + } + } + + if (proc->isRunning()) { + stopMplayer(); + we_are_restarting = false; + } + + // Save data of previous file: +#ifndef NO_USE_INI_FILES + saveMediaInfo(); +#endif + + mdat.reset(); + mdat.filename = dvd_url; + mdat.type = TYPE_DVD; + + mset.reset(); + + mset.current_title_id = title; +#if GENERIC_CHAPTER_SUPPORT + mset.current_chapter_id = firstChapter(); +#else + mset.current_chapter_id = dvdFirstChapter(); +#endif + mset.current_angle_id = 1; + + /* initializeMenus(); */ + + initPlaying(); +} + +void Core::openStream(QString name) { + qDebug("Core::openStream: '%s'", name.toUtf8().data()); + + if (proc->isRunning()) { + stopMplayer(); + we_are_restarting = false; + } + + // Save data of previous file: +#ifndef NO_USE_INI_FILES + saveMediaInfo(); +#endif + + mdat.reset(); + mdat.filename = name; + mdat.type = TYPE_STREAM; + + mset.reset(); + + /* initializeMenus(); */ + + initPlaying(); +} + + +void Core::playNewFile(QString file, int seek) { + qDebug("Core::playNewFile: '%s'", file.toUtf8().data()); + + if (proc->isRunning()) { + stopMplayer(); + we_are_restarting = false; + } + + // Save data of previous file: +#ifndef NO_USE_INI_FILES + saveMediaInfo(); +#endif + + mdat.reset(); + mdat.filename = file; + mdat.type = TYPE_FILE; + + int old_volume = mset.volume; + mset.reset(); + +#ifndef NO_USE_INI_FILES + // Check if we already have info about this file + #if NEW_SETTINGS_MANAGEMENT + if (file_settings->existSettingsFor(file)) { + #else + if (checkHaveSettingsSaved( FileSettings::filenameToGroupname(file) )) { + #endif + qDebug("Core::playNewFile: We have settings for this file!!!"); + + // In this case we read info from config + if (!pref->dont_remember_media_settings) { + #if NEW_SETTINGS_MANAGEMENT + file_settings->loadSettingsFor(file, mset); + #else + loadMediaInfo( FileSettings::filenameToGroupname(file) ); + #endif + qDebug("Core::playNewFile: Media settings read"); + + // Resize the window and set the aspect as soon as possible + int saved_width = mset.win_width; + int saved_height = mset.win_height; + // 400x300 is the default size for win_width and win_height + // so we set them to 0 to avoid to resize the window on + // audio files + if ((saved_width == 400) && (saved_height == 300)) { + saved_width = 0; + saved_height = 0; + } + if ((saved_width > 0) && (saved_height > 0)) { + emit needResize(mset.win_width, mset.win_height); + changeAspectRatio(mset.aspect_ratio_id); + } + + if (pref->dont_remember_time_pos) { + mset.current_sec = 0; + qDebug("Core::playNewFile: Time pos reset to 0"); + } + } else { + qDebug("Core::playNewFile: Media settings have not read because of preferences setting"); + } + } else { + // Recover volume + mset.volume = old_volume; + } +#else + // Recover volume + mset.volume = old_volume; +#endif // NO_USE_INI_FILES + + /* initializeMenus(); */ + + qDebug("Core::playNewFile: volume: %d, old_volume: %d", mset.volume, old_volume); + initPlaying(seek); +} + + +void Core::restartPlay() { + we_are_restarting = true; + initPlaying(); +} + +void Core::initPlaying(int seek) { + qDebug("Core::initPlaying"); + + /* + mdat.list(); + mset.list(); + */ + + /* updateWidgets(); */ + + mplayerwindow->showLogo(FALSE); + + if (proc->isRunning()) { + stopMplayer(); + } + + int start_sec = (int) mset.current_sec; + if (seek > -1) start_sec = seek; + + startMplayer( mdat.filename, start_sec ); +} + +// This is reached when a new video has just started playing +// and maybe we need to give some defaults +void Core::newMediaPlaying() { + qDebug("Core::newMediaPlaying: --- start ---"); + + QString file = mdat.filename; + int type = mdat.type; + mdat = proc->mediaData(); + mdat.filename = file; + mdat.type = type; + + initializeMenus(); // Old + + // Video + if ( (mset.current_video_id == MediaSettings::NoneSelected) && + (mdat.videos.numItems() > 0) ) + { + changeVideo( mdat.videos.itemAt(0).ID(), false ); // Don't allow to restart + } + +#if !DELAYED_AUDIO_SETUP_ON_STARTUP && !NOTIFY_AUDIO_CHANGES + // First audio if none selected + if ( (mset.current_audio_id == MediaSettings::NoneSelected) && + (mdat.audios.numItems() > 0) ) + { + // Don't set mset.current_audio_id here! changeAudio will do. + // Otherwise changeAudio will do nothing. + + int audio = mdat.audios.itemAt(0).ID(); // First one + if (mdat.audios.existsItemAt(pref->initial_audio_track-1)) { + audio = mdat.audios.itemAt(pref->initial_audio_track-1).ID(); + } + + // Check if one of the audio tracks is the user preferred. + if (!pref->audio_lang.isEmpty()) { + int res = mdat.audios.findLang( pref->audio_lang ); + if (res != -1) audio = res; + } + + // Change the audio without restarting mplayer, it's not + // safe to do it here. + changeAudio( audio, false ); + + } +#endif + +#if !NOTIFY_SUB_CHANGES + // Subtitles + if (mset.external_subtitles.isEmpty()) { + if (pref->autoload_sub) { + //Select first subtitle if none selected + if (mset.current_sub_id == MediaSettings::NoneSelected) { + int sub = mdat.subs.selectOne( pref->subtitle_lang, pref->initial_subtitle_track-1 ); + changeSubtitle( sub ); + } + } else { + changeSubtitle( MediaSettings::SubNone ); + } + } +#endif + +#if GENERIC_CHAPTER_SUPPORT + if (mdat.chapters > 0) { +#else + // mkv chapters + if (mdat.mkv_chapters > 0) { +#endif + // Just to show the first chapter checked in the menu + mset.current_chapter_id = firstChapter(); + } + + mdat.initialized = TRUE; + + // MPlayer doesn't display the length in ID_LENGTH for audio CDs... + if ((mdat.duration == 0) && (mdat.type == TYPE_AUDIO_CD)) { + /* + qDebug(" *** get duration here from title info *** "); + qDebug(" *** current title: %d", mset.current_title_id ); + */ + if (mset.current_title_id > 0) { + mdat.duration = mdat.titles.item(mset.current_title_id).duration(); + } + } + + /* updateWidgets(); */ + + mdat.list(); + mset.list(); + + qDebug("Core::newMediaPlaying: --- end ---"); +} + +void Core::finishRestart() { + qDebug("Core::finishRestart: --- start ---"); + + if (!we_are_restarting) { + newMediaPlaying(); + //QTimer::singleShot(1000, this, SIGNAL(mediaStartPlay())); + emit mediaStartPlay(); + } + + if (we_are_restarting) { + // Update info about codecs and demuxer + mdat.video_codec = proc->mediaData().video_codec; + mdat.audio_codec = proc->mediaData().audio_codec; + mdat.demuxer = proc->mediaData().demuxer; + } + +#if !NOTIFY_SUB_CHANGES + // Subtitles + //if (we_are_restarting) { + if ( (just_loaded_external_subs) || (just_unloaded_external_subs) ) { + qDebug("Core::finishRestart: processing new subtitles"); + + // Just to simplify things + if (mset.current_sub_id == MediaSettings::NoneSelected) { + mset.current_sub_id = MediaSettings::SubNone; + } + + // Save current sub + SubData::Type type; + int ID; + int old_item = -1; + if ( mset.current_sub_id != MediaSettings::SubNone ) { + old_item = mset.current_sub_id; + type = mdat.subs.itemAt(old_item).type(); + ID = mdat.subs.itemAt(old_item).ID(); + } + + // Use the subtitle info from mplayerprocess + qDebug( "Core::finishRestart: copying sub data from proc to mdat"); + mdat.subs = proc->mediaData().subs; + initializeMenus(); + int item = MediaSettings::SubNone; + + // Try to recover old subtitle + if (just_unloaded_external_subs) { + if (old_item > -1) { + int new_item = mdat.subs.find(type, ID); + if (new_item > -1) item = new_item; + } + } + + // If we've just loaded a subtitle file + // select one if the user wants to autoload + // one subtitle + if (just_loaded_external_subs) { + if ( (pref->autoload_sub) && (item == MediaSettings::SubNone) ) { + qDebug("Core::finishRestart: cannot find previous subtitle"); + qDebug("Core::finishRestart: selecting a new one"); + item = mdat.subs.selectOne( pref->subtitle_lang ); + } + } + changeSubtitle( item ); + just_loaded_external_subs = false; + just_unloaded_external_subs = false; + } else { + // Normal restart, subtitles haven't changed + // Recover current subtitle + changeSubtitle( mset.current_sub_id ); + } +#endif + + we_are_restarting = false; + +#if NEW_ASPECT_CODE + changeAspectRatio(mset.aspect_ratio_id); +#else + if (mset.aspect_ratio_id < MediaSettings::Aspect43Letterbox) { + changeAspectRatio(mset.aspect_ratio_id); + } +#endif + + bool isMuted = mset.mute; + if (!pref->dont_change_volume) { + setVolume( mset.volume, TRUE ); + } + if (isMuted) mute(TRUE); + + if (pref->change_video_equalizer_on_startup && (mset.gamma != 0)) { + int gamma = mset.gamma; + mset.gamma = -1000; // if mset.gamma == new value, mset.gamma is not changed! + setGamma( gamma ); + } + // Hack to be sure that the equalizers are up to date + emit videoEqualizerNeedsUpdate(); + emit audioEqualizerNeedsUpdate(); + + changePanscan(mset.panscan_factor); + + emit mediaLoaded(); + emit mediaInfoChanged(); + + updateWidgets(); // New + + qDebug("Core::finishRestart: --- end ---"); +} + + +void Core::stop() +{ + qDebug("Core::stop"); + qDebug("Core::stop: state: %s", stateToString().toUtf8().data()); + + if (state()==Stopped) { + // if pressed stop twice, reset video to the beginning + qDebug("Core::stop: mset.current_sec: %f", mset.current_sec); + mset.current_sec = 0; + emit showTime( mset.current_sec ); +#ifdef SEEKBAR_RESOLUTION + emit positionChanged( 0 ); +#else + emit posChanged( 0 ); +#endif + //updateWidgets(); + } + + stopMplayer(); + emit mediaStoppedByUser(); +} + + +void Core::play() +{ + qDebug("Core::play"); + + if ((proc->isRunning()) && (state()==Paused)) { + tellmp("pause"); // Unpauses + } + else + if ((proc->isRunning()) && (state()==Playing)) { + // nothing to do, continue playing + } + else { + // if we're stopped, play it again + if ( !mdat.filename.isEmpty() ) { + /* + qDebug( "current_sec: %f, duration: %f", mset.current_sec, mdat.duration); + if ( (floor(mset.current_sec)) >= (floor(mdat.duration)) ) { + mset.current_sec = 0; + } + */ + restartPlay(); + } + } +} + +void Core::pause_and_frame_step() { + qDebug("Core::pause_and_frame_step"); + + if (proc->isRunning()) { + if (state() == Paused) { + tellmp("frame_step"); + } + else { + tellmp("pause"); + } + } +} + +void Core::pause() { + qDebug("Core::pause"); + qDebug("Core::pause: current state: %s", stateToString().toUtf8().data()); + + if (proc->isRunning()) { + // Pauses and unpauses + tellmp("pause"); + } +} + +void Core::play_or_pause() { + if (proc->isRunning()) { + pause(); + } else { + play(); + } +} + +void Core::frameStep() { + qDebug("Core::frameStep"); + + if (proc->isRunning()) { + tellmp("frame_step"); + } +} + +void Core::screenshot() { + qDebug("Core::screenshot"); + + if ( (!pref->screenshot_directory.isEmpty()) && + (QFileInfo(pref->screenshot_directory).isDir()) ) + { + tellmp( pausing_prefix() + " screenshot 0"); + qDebug("Core::screenshot: taken screenshot"); + } else { + qDebug("Core::screenshot: error: directory for screenshots not valid"); + QString text = "Screenshot NOT taken, folder not configured"; + tellmp("osd_show_text \"" + text + "\" 3000 1"); + emit showMessage(text); + } +} + +void Core::processFinished() +{ + qDebug("Core::processFinished"); + +#ifdef Q_OS_WIN + // Restores the Windows screensaver + if (pref->disable_screensaver) { + win_screensaver->restore(); + } +#endif + + qDebug("Core::processFinished: we_are_restarting: %d", we_are_restarting); + + //mset.current_sec = 0; + + if (!we_are_restarting) { + qDebug("Core::processFinished: play has finished!"); + setState(Stopped); + //emit stateChanged(state()); + } + + int exit_code = proc->exitCode(); + qDebug("Core::processFinished: exit_code: %d", exit_code); + if (exit_code != 0) { + emit mplayerFinishedWithError(exit_code); + } +} + +void Core::fileReachedEnd() { + /* + if (mdat.type == TYPE_VCD) { + // If the first vcd title has nothing, it doesn't start to play + // and menus are not initialized. + initializeMenus(); + } + */ + + // If we're at the end of the movie, reset to 0 + mset.current_sec = 0; + updateWidgets(); + + emit mediaFinished(); +} + +#if SEEKBAR_RESOLUTION +void Core::goToPosition(int value) { + qDebug("Core::goToPosition: value: %d", value); + if (mdat.duration > 0) { + int jump_time = (int) mdat.duration * value / SEEKBAR_RESOLUTION; + goToSec(jump_time); + } +} +#else +void Core::goToPos(int perc) { + qDebug("Core::goToPos: per: %d", perc); + tellmp( "seek " + QString::number(perc) + " 1"); +} +#endif + + +void Core::startMplayer( QString file, double seek ) { + qDebug("Core::startMplayer"); + + if (file.isEmpty()) { + qWarning("Core:startMplayer: file is empty!"); + return; + } + + if (proc->isRunning()) { + qWarning("Core::startMplayer: MPlayer still running!"); + return; + } + +#ifdef Q_OS_WIN + // Disable the Windows screensaver + if (pref->disable_screensaver) { + win_screensaver->disable(); + } +#endif + + bool is_mkv = (QFileInfo(file).suffix().toLower() == "mkv"); + + // DVD + QString dvd_folder; + int dvd_title = -1; + if (mdat.type==TYPE_DVD) { + dvd_folder = Helper::dvdSplitFolder(file); + if (dvd_folder.isEmpty()) dvd_folder = pref->dvd_device; + // Remove trailing "/" + if (dvd_folder.endsWith("/")) { +#ifdef Q_OS_WIN + QRegExp r("^[A-Z]:/$"); + int pos = r.indexIn(dvd_folder); + qDebug("Core::startMplayer: drive check: '%s': regexp: %d", dvd_folder.toUtf8().data(), pos); + if (pos == -1) +#endif + dvd_folder = dvd_folder.remove( dvd_folder.length()-1, 1); + } + dvd_title = Helper::dvdSplitTitle(file); + file = "dvd://" + QString::number(dvd_title); + } + + // URL + bool url_is_playlist = file.endsWith(IS_PLAYLIST_TAG); + if (url_is_playlist) file = file.remove( QRegExp(IS_PLAYLIST_TAG_RX) ); + + bool screenshot_enabled = ( (!pref->screenshot_directory.isEmpty()) && + (QFileInfo(pref->screenshot_directory).isDir()) ); + + proc->clearArguments(); + + // Set working directory to screenshot directory + if (screenshot_enabled) { + qDebug("Core::startMplayer: setting working directory to '%s'", pref->screenshot_directory.toUtf8().data()); + proc->setWorkingDirectory( pref->screenshot_directory ); + } + + // Use absolute path, otherwise after changing to the screenshot directory + // the mplayer path might not be found if it's a relative path + // (seems to be necessary only for linux) + QString mplayer_bin = pref->mplayer_bin; + QFileInfo fi(mplayer_bin); + if (fi.exists() && fi.isExecutable() && !fi.isDir()) { + mplayer_bin = fi.absoluteFilePath(); + } + + proc->addArgument( mplayer_bin ); + + proc->addArgument("-noquiet"); + + if (pref->fullscreen && pref->use_mplayer_window) { + proc->addArgument("-fs"); + } else { + // No mplayer fullscreen mode + proc->addArgument("-nofs"); + } + + // Demuxer and audio and video codecs: + if (!mset.forced_demuxer.isEmpty()) { + proc->addArgument("-demuxer"); + proc->addArgument(mset.forced_demuxer); + } + if (!mset.forced_audio_codec.isEmpty()) { + proc->addArgument("-ac"); + proc->addArgument(mset.forced_audio_codec); + } + if (!mset.forced_video_codec.isEmpty()) { + proc->addArgument("-vc"); + proc->addArgument(mset.forced_video_codec); + } + + if (pref->use_hwac3) { + proc->addArgument("-afm"); + proc->addArgument("hwac3"); + } + + + QString lavdopts; + + if ( (pref->h264_skip_loop_filter == Preferences::LoopDisabled) || + ((pref->h264_skip_loop_filter == Preferences::LoopDisabledOnHD) && + (mset.is264andHD)) ) + { + if (!lavdopts.isEmpty()) lavdopts += ":"; + lavdopts += "skiploopfilter=all"; + } + + if (pref->show_motion_vectors) { + if (!lavdopts.isEmpty()) lavdopts += ":"; + lavdopts += "vismv=7"; + } + + if (pref->threads > 1) { + if (!lavdopts.isEmpty()) lavdopts += ":"; + lavdopts += "threads=" + QString::number(pref->threads); + } + + if (!lavdopts.isEmpty()) { + proc->addArgument("-lavdopts"); + proc->addArgument(lavdopts); + } + + proc->addArgument("-sub-fuzziness"); + proc->addArgument( QString::number(pref->subfuzziness) ); + + proc->addArgument("-identify"); + +#if GENERIC_CHAPTER_SUPPORT + if (MplayerVersion::isMplayerAtLeast(27667)) { + // From r27667 the number of chapters can be obtained from ID_CHAPTERS + mset.current_chapter_id = 0; // Reset chapters + } else { +#endif + // We need this to get info about mkv chapters + if (is_mkv) { + proc->addArgument("-msglevel"); + proc->addArgument("demux=6"); + + // **** Reset chapter *** + // Select first chapter, otherwise we cannot + // resume playback at the same point + // (time would be relative to chapter) + mset.current_chapter_id = 0; + } +#if GENERIC_CHAPTER_SUPPORT + } +#endif + + proc->addArgument("-slave"); + + if (!pref->vo.isEmpty()) { + proc->addArgument( "-vo"); + proc->addArgument( pref->vo ); + } else { + proc->addArgument("-vo"); +#ifdef Q_OS_WIN + // On Windows Vista, the default vo is already set in preferences.cpp + proc->addArgument("directx,"); +#else + proc->addArgument("xv,"); +#endif + } + +#if USE_ADAPTER + if (pref->adapter > -1) { + proc->addArgument("-adapter"); + proc->addArgument(QString::number(pref->adapter)); + } +#endif + + if (!pref->ao.isEmpty()) { + proc->addArgument( "-ao"); + proc->addArgument( pref->ao ); + } +#ifndef Q_OS_WIN + else { + proc->addArgument( "-ao"); + proc->addArgument( "alsa," ); + } +#endif + + proc->addArgument( "-zoom"); + proc->addArgument("-nokeepaspect"); + + // Performance options + #ifdef Q_OS_WIN + QString p; + int app_p = NORMAL_PRIORITY_CLASS; + switch (pref->priority) { + case Preferences::Realtime: p = "realtime"; + app_p = REALTIME_PRIORITY_CLASS; + break; + case Preferences::High: p = "high"; + app_p = REALTIME_PRIORITY_CLASS; + break; + case Preferences::AboveNormal: p = "abovenormal"; + app_p = HIGH_PRIORITY_CLASS; + break; + case Preferences::Normal: p = "normal"; + app_p = ABOVE_NORMAL_PRIORITY_CLASS; + break; + case Preferences::BelowNormal: p = "belownormal"; break; + case Preferences::Idle: p = "idle"; break; + default: p = "normal"; + } + proc->addArgument("-priority"); + proc->addArgument( p ); + SetPriorityClass(GetCurrentProcess(), app_p); + qDebug("Core::startMplayer: priority of smplayer process set to %d", app_p); + #endif + + if (pref->frame_drop) { + proc->addArgument("-framedrop"); + } + + if (pref->hard_frame_drop) { + proc->addArgument("-hardframedrop"); + } + + if (pref->autosync) { + proc->addArgument("-autosync"); + proc->addArgument( QString::number( pref->autosync_factor ) ); + } + + if (pref->use_direct_rendering) { + proc->addArgument("-dr"); + } else { + proc->addArgument("-nodr"); + } + + if (pref->use_double_buffer) { + proc->addArgument("-double"); + } else { + proc->addArgument("-nodouble"); + } + +#ifndef Q_OS_WIN + if (!pref->use_mplayer_window) { + proc->addArgument( "-input" ); + proc->addArgument( "conf=" + Paths::dataPath() +"/input.conf" ); + } +#endif + +#ifdef Q_WS_X11 + if (pref->disable_screensaver) { + proc->addArgument("-stop-xscreensaver"); + } else { + proc->addArgument("-nostop-xscreensaver"); + } +#endif + + if (!pref->use_mplayer_window) { + proc->addArgument("-wid"); + proc->addArgument( QString::number( (int) mplayerwindow->videoLayer()->winId() ) ); + +#if USE_COLORKEY + #ifdef Q_OS_WIN + if ((pref->vo.startsWith("directx")) || (pref->vo.isEmpty())) { + proc->addArgument("-colorkey"); + //proc->addArgument( "0x"+QString::number(pref->color_key, 16) ); + proc->addArgument( ColorUtils::colorToRGB(pref->color_key) ); + } else { + #endif + qDebug("Core::startMplayer: * not using -colorkey for %s", pref->vo.toUtf8().data()); + qDebug("Core::startMplayer: * report if you can't see the video"); + #ifdef Q_OS_WIN + } + #endif +#endif + + // Square pixels + proc->addArgument("-monitorpixelaspect"); + proc->addArgument("1"); + } else { + // no -wid + if (!pref->monitor_aspect.isEmpty()) { + proc->addArgument("-monitoraspect"); + proc->addArgument( pref->monitor_aspect ); + } + } + + // Subtitles fonts + if ((pref->use_ass_subtitles) && (pref->freetype_support)) { + // ASS: + proc->addArgument("-ass"); + proc->addArgument("-embeddedfonts"); + + proc->addArgument("-ass-line-spacing"); + proc->addArgument(QString::number(pref->ass_line_spacing)); + + proc->addArgument( "-ass-font-scale"); + proc->addArgument( QString::number(mset.sub_scale_ass) ); + + // Load the styles.ass file + if (!QFile::exists(Paths::subtitleStyleFile())) { + // If file doesn't exist, create it + pref->ass_styles.exportStyles(Paths::subtitleStyleFile()); + } + if (QFile::exists(Paths::subtitleStyleFile())) { + proc->addArgument("-ass-styles"); + proc->addArgument( Paths::subtitleStyleFile() ); + } else { + qWarning("Core::startMplayer: '%s' doesn't exist", Paths::subtitleStyleFile().toUtf8().constData()); + } + // Use the same font for OSD + if (!pref->ass_styles.fontname.isEmpty()) { + proc->addArgument("-fontconfig"); + proc->addArgument("-font"); + proc->addArgument( pref->ass_styles.fontname ); + } + + } else { + // NO ASS: + if (pref->freetype_support) proc->addArgument("-noass"); + + if ( (pref->use_fontconfig) && (!pref->font_name.isEmpty()) ) { + proc->addArgument("-fontconfig"); + proc->addArgument("-font"); + proc->addArgument( pref->font_name ); + } + + if ( (!pref->use_fontconfig) && (!pref->font_file.isEmpty()) ) { + proc->addArgument("-font"); + proc->addArgument( pref->font_file ); + } + + if (pref->freetype_support) { + proc->addArgument( "-subfont-autoscale"); + proc->addArgument( QString::number( pref->font_autoscale ) ); + + proc->addArgument( "-subfont-text-scale"); + proc->addArgument( QString::number(mset.sub_scale) ); + } + } + + // Subtitle encoding + { + QString encoding; + if ( (pref->use_enca) && (!pref->enca_lang.isEmpty()) ) { + encoding = "enca:"+ pref->enca_lang; + if (!pref->subcp.isEmpty()) { + encoding += ":"+ pref->subcp; + } + } + else + if (!pref->subcp.isEmpty()) { + encoding = pref->subcp; + } + + if (!encoding.isEmpty()) { + proc->addArgument("-subcp"); + proc->addArgument( encoding ); + } + } + + if (pref->use_closed_caption_subs) { + proc->addArgument("-subcc"); + } + + if (pref->use_forced_subs_only) { + proc->addArgument("-forcedsubsonly"); + } + + if (mset.current_video_id != MediaSettings::NoneSelected) { + proc->addArgument("-vid"); + proc->addArgument( QString::number( mset.current_video_id ) ); + } + + if (mset.current_audio_id != MediaSettings::NoneSelected) { + proc->addArgument("-aid"); + proc->addArgument( QString::number( mset.current_audio_id ) ); + } + + if (!initial_subtitle.isEmpty()) { + mset.external_subtitles = initial_subtitle; + initial_subtitle = ""; + just_loaded_external_subs = true; // Big ugly hack :( + } + if (!mset.external_subtitles.isEmpty()) { + if (QFileInfo(mset.external_subtitles).suffix().toLower()=="idx") { + // sub/idx subtitles + QFileInfo fi; + + #ifdef Q_OS_WIN + if (pref->use_short_pathnames) + fi.setFile(Helper::shortPathName(mset.external_subtitles)); + else + #endif + fi.setFile(mset.external_subtitles); + + QString s = fi.path() +"/"+ fi.completeBaseName(); + qDebug("Core::startMplayer: subtitle file without extension: '%s'", s.toUtf8().data()); + proc->addArgument("-vobsub"); + proc->addArgument( s ); + } else { + proc->addArgument("-sub"); + #ifdef Q_OS_WIN + if (pref->use_short_pathnames) + proc->addArgument(Helper::shortPathName(mset.external_subtitles)); + else + #endif + proc->addArgument( mset.external_subtitles ); + } + } + + if (!mset.external_audio.isEmpty()) { + proc->addArgument("-audiofile"); + #ifdef Q_OS_WIN + if (pref->use_short_pathnames) + proc->addArgument(Helper::shortPathName(mset.external_audio)); + else + #endif + proc->addArgument( mset.external_audio ); + } + + proc->addArgument("-subpos"); + proc->addArgument( QString::number(mset.sub_pos) ); + + if (mset.audio_delay!=0) { + proc->addArgument("-delay"); + proc->addArgument( QString::number( (double) mset.audio_delay/1000 ) ); + } + + if (mset.sub_delay!=0) { + proc->addArgument("-subdelay"); + proc->addArgument( QString::number( (double) mset.sub_delay/1000 ) ); + } + + // Contrast, brightness... + if (pref->change_video_equalizer_on_startup) { + if (mset.contrast != 0) { + proc->addArgument("-contrast"); + proc->addArgument( QString::number( mset.contrast ) ); + } + + if (mset.brightness != 0) { + proc->addArgument("-brightness"); + proc->addArgument( QString::number( mset.brightness ) ); + } + + if (mset.hue != 0) { + proc->addArgument("-hue"); + proc->addArgument( QString::number( mset.hue ) ); + } + + if (mset.saturation != 0) { + proc->addArgument("-saturation"); + proc->addArgument( QString::number( mset.saturation ) ); + } + } + + // Set volume, requires mplayer svn r27872 + bool use_volume_option = (pref->use_volume_option == Preferences::Enabled); + if (pref->use_volume_option == Preferences::Detect) { + use_volume_option = (MplayerVersion::isMplayerAtLeast(27872)); + } + if ((use_volume_option) && (!pref->dont_change_volume)) { + proc->addArgument("-volume"); + // Note: mset.volume may not be right, it can be the volume of the previous video if + // playing a new one, but I think it's better to use anyway the current volume on + // startup than set it to 0 or something. + // The right volume will be set later, when the video starts to play. + proc->addArgument( QString::number( mset.volume ) ); + } + + + if (mdat.type==TYPE_DVD) { + if (!dvd_folder.isEmpty()) { + proc->addArgument("-dvd-device"); + proc->addArgument( dvd_folder ); + } else { + qWarning("Core::startMplayer: dvd device is empty!"); + } + } + + if ((mdat.type==TYPE_VCD) || (mdat.type==TYPE_AUDIO_CD)) { + if (!pref->cdrom_device.isEmpty()) { + proc->addArgument("-cdrom-device"); + proc->addArgument( pref->cdrom_device ); + } + } + + if (mset.current_chapter_id > 0) { + proc->addArgument("-chapter"); + int chapter = mset.current_chapter_id; + // Fix for older versions of mplayer: +#if GENERIC_CHAPTER_SUPPORT + if ((mdat.type == TYPE_DVD) && (firstChapter() == 0)) chapter++; +#else + if ((mdat.type == TYPE_DVD) && (dvdFirstChapter() == 0)) chapter++; +#endif + proc->addArgument( QString::number( chapter ) ); + } + + if (mset.current_angle_id > 0) { + proc->addArgument("-dvdangle"); + proc->addArgument( QString::number( mset.current_angle_id ) ); + } + + + int cache = 0; + switch (mdat.type) { + case TYPE_FILE : cache = pref->cache_for_files; break; + case TYPE_DVD : cache = pref->cache_for_dvds; break; + case TYPE_STREAM : cache = pref->cache_for_streams; break; + case TYPE_VCD : cache = pref->cache_for_vcds; break; + case TYPE_AUDIO_CD : cache = pref->cache_for_audiocds; break; + default: cache = 0; + } + + if (cache > 31) { // Minimum value for cache = 32 + proc->addArgument("-cache"); + proc->addArgument( QString::number( cache ) ); + } else { + proc->addArgument("-nocache"); + } + + if (mset.speed != 1.0) { + proc->addArgument("-speed"); + proc->addArgument( QString::number( mset.speed ) ); + } + + // If seek < 5 it's better to allow the video to start from the beginning + if ((seek >= 5) && (!pref->loop)) { + proc->addArgument("-ss"); + proc->addArgument( QString::number( seek ) ); + } + + proc->addArgument("-osdlevel"); + proc->addArgument( QString::number( pref->osd ) ); + + if (pref->use_idx) { + proc->addArgument("-idx"); + } + + if (mdat.type == TYPE_STREAM) { + if (pref->prefer_ipv4) { + proc->addArgument("-prefer-ipv4"); + } else { + proc->addArgument("-prefer-ipv6"); + } + } + + if (pref->use_correct_pts) { + proc->addArgument("-correct-pts"); + } else { + if (pref->mplayer_detected_version > 0) { + if (MplayerVersion::isMplayerAtLeast(26842)) { + proc->addArgument("-nocorrect-pts"); + } else { + proc->addArgument("-no-correct-pts"); + } + } else { + qDebug("Core::startMplayer: unknown version of mplayer, not passing -no(-)correct-pts"); + } + } + + // Video filters: + // Phase + if (mset.phase_filter) { + proc->addArgument("-vf-add"); + proc->addArgument( "phase=A" ); + } + + // Deinterlace + if (mset.current_deinterlacer != MediaSettings::NoDeinterlace) { + proc->addArgument("-vf-add"); + switch (mset.current_deinterlacer) { + case MediaSettings::L5: proc->addArgument("pp=l5"); break; + case MediaSettings::Yadif: proc->addArgument("yadif"); break; + case MediaSettings::LB: proc->addArgument("pp=lb"); break; + case MediaSettings::Yadif_1: proc->addArgument("yadif=1"); break; + case MediaSettings::Kerndeint: proc->addArgument("kerndeint=5"); break; + } + } + +#if !NEW_ASPECT_CODE + // Panscan (crop) + if (!mset.panscan_filter.isEmpty()) { + proc->addArgument( "-vf-add" ); + proc->addArgument( mset.panscan_filter ); + } + + // Crop 4:3 to 16:9 + if (!mset.crop_43to169_filter.isEmpty()) { + proc->addArgument( "-vf-add" ); + proc->addArgument( mset.crop_43to169_filter ); + } +#endif + + // Denoise + if (mset.current_denoiser != MediaSettings::NoDenoise) { + proc->addArgument("-vf-add"); + if (mset.current_denoiser==MediaSettings::DenoiseSoft) { + proc->addArgument( "hqdn3d=2:1:2" ); + } else { + proc->addArgument( "hqdn3d" ); + } + } + + // Deblock + if (mset.deblock_filter) { + proc->addArgument("-vf-add"); + proc->addArgument( "pp=vb/hb" ); + } + + // Dering + if (mset.dering_filter) { + proc->addArgument("-vf-add"); + proc->addArgument( "pp=dr" ); + } + + // Upscale + if (mset.upscaling_filter) { + int width = DesktopInfo::desktop_size(mplayerwindow).width(); + proc->addArgument("-sws"); + proc->addArgument("9"); + proc->addArgument("-vf-add"); + proc->addArgument("scale="+QString::number(width)+":-2"); + } + + // Addnoise + if (mset.noise_filter) { + proc->addArgument("-vf-add"); + proc->addArgument( "noise=9ah:5ah" ); + } + + // Postprocessing + if (mset.postprocessing_filter) { + proc->addArgument("-vf-add"); + proc->addArgument("pp"); + proc->addArgument("-autoq"); + proc->addArgument( QString::number(pref->autoq) ); + } + + + // Letterbox (expand) +#if NEW_ASPECT_CODE + if ((mset.add_letterbox) || (pref->fullscreen && pref->add_blackborders_on_fullscreen)) { + proc->addArgument("-vf-add"); + proc->addArgument( QString("expand=:::::%1,harddup").arg( DesktopInfo::desktop_aspectRatio(mplayerwindow)) ); + // Note: on some videos (h264 for instance) the subtitles doesn't disappear, + // appearing the new ones on top of the old ones. It seems adding another + // filter after expand fixes the problem. I chose harddup 'cos I think + // it will be harmless in mplayer. + // Anyway, if you know a proper way to fix the problem, please tell me. + } +#else + if (mset.letterbox == MediaSettings::Letterbox_43) { + proc->addArgument("-vf-add"); + proc->addArgument("expand=:::::4/3"); + } + else + if (mset.letterbox == MediaSettings::Letterbox_169) { + proc->addArgument("-vf-add"); + proc->addArgument("expand=:::::16/9"); + } +#endif + + // Software equalizer + if ( (pref->use_soft_video_eq) ) { + proc->addArgument("-vf-add"); + QString eq_filter = "eq2,hue"; + if ( (pref->vo == "gl") || (pref->vo == "gl2") +#ifdef Q_OS_WIN + || (pref->vo == "directx:noaccel") +#endif + ) eq_filter += ",scale"; + proc->addArgument(eq_filter); + } + + // Additional video filters, supplied by user + // File + if ( !mset.mplayer_additional_video_filters.isEmpty() ) { + proc->addArgument("-vf-add"); + proc->addArgument( mset.mplayer_additional_video_filters ); + } + // Global + if ( !pref->mplayer_additional_video_filters.isEmpty() ) { + proc->addArgument("-vf-add"); + proc->addArgument( pref->mplayer_additional_video_filters ); + } + + bool force_noslices = false; + + // Filters for subtitles on screenshots + if ((screenshot_enabled) && (pref->subtitles_on_screenshots)) + { + if (pref->use_ass_subtitles) { + proc->addArgument("-vf-add"); + proc->addArgument("ass"); + } else { + proc->addArgument("-vf-add"); + proc->addArgument("expand=osd=1"); + //proc->addArgument("-noslices"); + force_noslices = true; + } + } + + // Rotate + if (mset.rotate != MediaSettings::NoRotate) { + proc->addArgument( "-vf-add" ); + proc->addArgument( QString("rotate=%1").arg(mset.rotate) ); + } + + // Flip + if (mset.flip) { + proc->addArgument( "-vf-add" ); + // expand + flip doesn't work well, a workaround is to add another + // filter between them, so that's why harddup is here + proc->addArgument("harddup,flip"); + } + + // Mirror + if (mset.mirror) { + proc->addArgument( "-vf-add" ); + proc->addArgument("mirror"); + } + + // Screenshots + if (screenshot_enabled) { + proc->addArgument("-vf-add"); + proc->addArgument("screenshot"); + } + + // slices + if ((pref->use_slices) && (!force_noslices)) { + proc->addArgument("-slices"); + } else { + proc->addArgument("-noslices"); + } + + + // Audio channels + if (mset.audio_use_channels != 0) { + proc->addArgument("-channels"); + proc->addArgument( QString::number( mset.audio_use_channels ) ); + } + + // Stereo mode + if (mset.stereo_mode != 0) { + proc->addArgument("-stereo"); + proc->addArgument( QString::number( mset.stereo_mode ) ); + } + + // Audio filters + QString af=""; + if (mset.karaoke_filter) { + af="karaoke"; + } + + if (mset.extrastereo_filter) { + if (!af.isEmpty()) af += ","; + af += "extrastereo"; + } + + if (mset.volnorm_filter) { + if (!af.isEmpty()) af += ","; + af += "volnorm=2"; + } + + bool use_scaletempo = (pref->use_scaletempo == Preferences::Enabled); + if (pref->use_scaletempo == Preferences::Detect) { + use_scaletempo = (MplayerVersion::isMplayerAtLeast(24924)); + } + if (use_scaletempo) { + if (!af.isEmpty()) af += ","; + af += "scaletempo"; + } + + // Audio equalizer + if (pref->use_audio_equalizer) { + if (!af.isEmpty()) af += ","; + af += "equalizer=" + Helper::equalizerListToString(mset.audio_equalizer); + } + + + // Additional audio filters, supplied by user + // File + if ( !pref->mplayer_additional_audio_filters.isEmpty() ) { + if (!af.isEmpty()) af += ","; + af += pref->mplayer_additional_audio_filters; + } + // Global + if ( !mset.mplayer_additional_audio_filters.isEmpty() ) { + if (!af.isEmpty()) af += ","; + af += mset.mplayer_additional_audio_filters; + } + + if (!af.isEmpty()) { + proc->addArgument("-af"); + proc->addArgument( af ); + } + + if (pref->use_soft_vol) { + proc->addArgument("-softvol"); + proc->addArgument("-softvol-max"); + proc->addArgument( QString::number(pref->softvol_max) ); + } + + // Load edl file + if (pref->use_edl_files) { + QString edl_f; + QFileInfo f(file); + QString basename = f.path() + "/" + f.completeBaseName(); + + qDebug("Core::startMplayer: file basename: '%s'", basename.toUtf8().data()); + + if (QFile::exists(basename+".edl")) + edl_f = basename+".edl"; + else + if (QFile::exists(basename+".EDL")) + edl_f = basename+".EDL"; + + qDebug("Core::startMplayer: edl file: '%s'", edl_f.toUtf8().data()); + if (!edl_f.isEmpty()) { + proc->addArgument("-edl"); + proc->addArgument(edl_f); + } + } + + // Additional options supplied by the user + // File + if (!mset.mplayer_additional_options.isEmpty()) { + QStringList args = mset.mplayer_additional_options.split(" "); + QStringList::Iterator it = args.begin(); + while( it != args.end() ) { + proc->addArgument( (*it) ); + ++it; + } + } + // Global + if (!pref->mplayer_additional_options.isEmpty()) { + QStringList args = pref->mplayer_additional_options.split(" "); + QStringList::Iterator it = args.begin(); + while( it != args.end() ) { + proc->addArgument( (*it) ); + ++it; + } + } + + // File to play + if (url_is_playlist) { + proc->addArgument("-playlist"); + } + +#ifdef Q_OS_WIN + if (pref->use_short_pathnames) + proc->addArgument(Helper::shortPathName(file)); + else +#endif + proc->addArgument( file ); + + // It seems the loop option must be after the filename + if (pref->loop) { + proc->addArgument("-loop"); + proc->addArgument("0"); + } + + emit aboutToStartPlaying(); + + QString commandline = proc->arguments().join(" "); + qDebug("Core::startMplayer: command: '%s'", commandline.toUtf8().data()); + + //Log command + QString line_for_log = commandline + "\n"; + emit logLineAvailable(line_for_log); + + if ( !proc->start() ) { + // error handling + qWarning("Core::startMplayer: mplayer process didn't start"); + } + +} + +void Core::stopMplayer() { + qDebug("Core::stopMplayer"); + + if (!proc->isRunning()) { + qWarning("Core::stopMplayer: mplayer in not running!"); + return; + } + + tellmp("quit"); + + qDebug("Core::stopMplayer: Waiting mplayer to finish..."); + if (!proc->waitForFinished(5000)) { + qWarning("Core::stopMplayer: process didn't finish. Killing it..."); + proc->kill(); + } + + qDebug("Core::stopMplayer: Finished. (I hope)"); +} + + +void Core::goToSec( double sec ) { + qDebug("Core::goToSec: %f", sec); + + if (sec < 0) sec = 0; + if (sec > mdat.duration ) sec = mdat.duration - 20; + tellmp("seek " + QString::number(sec) + " 2"); +} + + +void Core::seek(int secs) { + qDebug("Core::seek: %d", secs); + if ( (proc->isRunning()) && (secs!=0) ) { + tellmp("seek " + QString::number(secs) + " 0"); + } +} + +void Core::sforward() { + qDebug("Core::sforward"); + seek( pref->seeking1 ); // +10s +} + +void Core::srewind() { + qDebug("Core::srewind"); + seek( -pref->seeking1 ); // -10s +} + + +void Core::forward() { + qDebug("Core::forward"); + seek( pref->seeking2 ); // +1m +} + + +void Core::rewind() { + qDebug("Core::rewind"); + seek( -pref->seeking2 ); // -1m +} + + +void Core::fastforward() { + qDebug("Core::fastforward"); + seek( pref->seeking3 ); // +10m +} + + +void Core::fastrewind() { + qDebug("Core::fastrewind"); + seek( -pref->seeking3 ); // -10m +} + +void Core::forward(int secs) { + qDebug("Core::forward: %d", secs); + seek(secs); +} + +void Core::rewind(int secs) { + qDebug("Core::rewind: %d", secs); + seek(-secs); +} + +void Core::wheelUp() { + qDebug("Core::wheelUp"); + switch (pref->wheel_function) { + case Preferences::Volume : incVolume(); break; + case Preferences::Zoom : incPanscan(); break; + case Preferences::Seeking : forward( pref->seeking4 ); break; + case Preferences::ChangeSpeed : incSpeed10(); break; + default : {} // do nothing + } +} + +void Core::wheelDown() { + qDebug("Core::wheelDown"); + switch (pref->wheel_function) { + case Preferences::Volume : decVolume(); break; + case Preferences::Zoom : decPanscan(); break; + case Preferences::Seeking : rewind( pref->seeking4 ); break; + case Preferences::ChangeSpeed : decSpeed10(); break; + default : {} // do nothing + } +} + + +void Core::toggleRepeat() { + qDebug("Core::toggleRepeat"); + toggleRepeat( !pref->loop ); +} + +void Core::toggleRepeat(bool b) { + qDebug("Core::toggleRepeat: %d", b); + if ( pref->loop != b ) { + pref->loop = b; + if (MplayerVersion::isMplayerAtLeast(23747)) { + // Use slave command + int v = -1; // no loop + if (pref->loop) v = 0; // infinite loop + tellmp( QString("loop %1 1").arg(v) ); + } else { + // Restart mplayer + if (proc->isRunning()) restartPlay(); + } + } +} + + +void Core::toggleFlip() { + qDebug("Core::toggleFlip"); + toggleFlip( !mset.flip ); +} + +void Core::toggleFlip(bool b) { + qDebug("Core::toggleFlip: %d", b); + + if (mset.flip != b) { + mset.flip = b; + if (proc->isRunning()) restartPlay(); + } +} + +void Core::toggleMirror() { + qDebug("Core::toggleMirror"); + toggleMirror( !mset.mirror ); +} + +void Core::toggleMirror(bool b) { + qDebug("Core::toggleMirror: %d", b); + + if (mset.mirror != b) { + mset.mirror = b; + if (proc->isRunning()) restartPlay(); + } +} + +// Audio filters +void Core::toggleKaraoke() { + toggleKaraoke( !mset.karaoke_filter ); +} + +void Core::toggleKaraoke(bool b) { + qDebug("Core::toggleKaraoke: %d", b); + if (b != mset.karaoke_filter) { + mset.karaoke_filter = b; + restartPlay(); + } +} + +void Core::toggleExtrastereo() { + toggleExtrastereo( !mset.extrastereo_filter ); +} + +void Core::toggleExtrastereo(bool b) { + qDebug("Core::toggleExtrastereo: %d", b); + if (b != mset.extrastereo_filter) { + mset.extrastereo_filter = b; + restartPlay(); + } +} + +void Core::toggleVolnorm() { + toggleVolnorm( !mset.volnorm_filter ); +} + +void Core::toggleVolnorm(bool b) { + qDebug("Core::toggleVolnorm: %d", b); + if (b != mset.volnorm_filter) { + mset.volnorm_filter = b; + restartPlay(); + } +} + +void Core::setAudioChannels(int channels) { + qDebug("Core::setAudioChannels:%d", channels); + if (channels != mset.audio_use_channels ) { + mset.audio_use_channels = channels; + restartPlay(); + } +} + +void Core::setStereoMode(int mode) { + qDebug("Core::setStereoMode:%d", mode); + if (mode != mset.stereo_mode ) { + mset.stereo_mode = mode; + restartPlay(); + } +} + + +// Video filters +void Core::toggleAutophase() { + toggleAutophase( !mset.phase_filter ); +} + +void Core::toggleAutophase( bool b ) { + qDebug("Core::toggleAutophase: %d", b); + if ( b != mset.phase_filter) { + mset.phase_filter = b; + restartPlay(); + } +} + +void Core::toggleDeblock() { + toggleDeblock( !mset.deblock_filter ); +} + +void Core::toggleDeblock(bool b) { + qDebug("Core::toggleDeblock: %d", b); + if ( b != mset.deblock_filter ) { + mset.deblock_filter = b; + restartPlay(); + } +} + +void Core::toggleDering() { + toggleDering( !mset.dering_filter ); +} + +void Core::toggleDering(bool b) { + qDebug("Core::toggleDering: %d", b); + if ( b != mset.dering_filter) { + mset.dering_filter = b; + restartPlay(); + } +} + +void Core::toggleNoise() { + toggleNoise( !mset.noise_filter ); +} + +void Core::toggleNoise(bool b) { + qDebug("Core::toggleNoise: %d", b); + if ( b!= mset.noise_filter ) { + mset.noise_filter = b; + restartPlay(); + } +} + +void Core::togglePostprocessing() { + togglePostprocessing( !mset.postprocessing_filter ); +} + +void Core::togglePostprocessing(bool b) { + qDebug("Core::togglePostprocessing: %d", b); + if ( b != mset.postprocessing_filter ) { + mset.postprocessing_filter = b; + restartPlay(); + } +} + +void Core::changeDenoise(int id) { + qDebug( "Core::changeDenoise: %d", id ); + if (id != mset.current_denoiser) { + mset.current_denoiser = id; + restartPlay(); + } +} + +void Core::changeUpscale(bool b) { + qDebug( "Core::changeUpscale: %d", b ); + if (mset.upscaling_filter != b) { + mset.upscaling_filter = b; + restartPlay(); + } +} + +void Core::setBrightness(int value) { + qDebug("Core::setBrightness: %d", value); + + if (value > 100) value = 100; + if (value < -100) value = -100; + + if (value != mset.brightness) { + tellmp(pausing_prefix() + " brightness " + QString::number(value) + " 1"); + mset.brightness = value; + displayMessage( tr("Brightness: %1").arg(value) ); + emit videoEqualizerNeedsUpdate(); + } +} + + +void Core::setContrast(int value) { + qDebug("Core::setContrast: %d", value); + + if (value > 100) value = 100; + if (value < -100) value = -100; + + if (value != mset.contrast) { + tellmp(pausing_prefix() + " contrast " + QString::number(value) + " 1"); + mset.contrast = value; + displayMessage( tr("Contrast: %1").arg(value) ); + emit videoEqualizerNeedsUpdate(); + } +} + +void Core::setGamma(int value) { + qDebug("Core::setGamma: %d", value); + + if (value > 100) value = 100; + if (value < -100) value = -100; + + if (value != mset.gamma) { + tellmp(pausing_prefix() + " gamma " + QString::number(value) + " 1"); + mset.gamma= value; + displayMessage( tr("Gamma: %1").arg(value) ); + emit videoEqualizerNeedsUpdate(); + } +} + +void Core::setHue(int value) { + qDebug("Core::setHue: %d", value); + + if (value > 100) value = 100; + if (value < -100) value = -100; + + if (value != mset.hue) { + tellmp(pausing_prefix() + " hue " + QString::number(value) + " 1"); + mset.hue = value; + displayMessage( tr("Hue: %1").arg(value) ); + emit videoEqualizerNeedsUpdate(); + } +} + +void Core::setSaturation(int value) { + qDebug("Core::setSaturation: %d", value); + + if (value > 100) value = 100; + if (value < -100) value = -100; + + if (value != mset.saturation) { + tellmp(pausing_prefix() + " saturation " + QString::number(value) + " 1"); + mset.saturation = value; + displayMessage( tr("Saturation: %1").arg(value) ); + emit videoEqualizerNeedsUpdate(); + } +} + +void Core::incBrightness() { + setBrightness(mset.brightness + 4); +} + +void Core::decBrightness() { + setBrightness(mset.brightness - 4); +} + +void Core::incContrast() { + setContrast(mset.contrast + 4); +} + +void Core::decContrast() { + setContrast(mset.contrast - 4); +} + +void Core::incGamma() { + setGamma(mset.gamma + 4); +} + +void Core::decGamma() { + setGamma(mset.gamma - 4); +} + +void Core::incHue() { + setHue(mset.hue + 4); +} + +void Core::decHue() { + setHue(mset.hue - 4); +} + +void Core::incSaturation() { + setSaturation(mset.saturation + 4); +} + +void Core::decSaturation() { + setSaturation(mset.saturation - 4); +} + +void Core::setSpeed( double value ) { + qDebug("Core::setSpeed: %f", value); + + if (value < 0.10) value = 0.10; + if (value > 100) value = 100; + + mset.speed = value; + tellmp( "speed_set " + QString::number( value ) ); +} + +void Core::incSpeed10() { + qDebug("Core::incSpeed10"); + setSpeed( (double) mset.speed + 0.1 ); +} + +void Core::decSpeed10() { + qDebug("Core::decSpeed10"); + setSpeed( (double) mset.speed - 0.1 ); +} + +void Core::incSpeed4() { + qDebug("Core::incSpeed4"); + setSpeed( (double) mset.speed + 0.04 ); +} + +void Core::decSpeed4() { + qDebug("Core::decSpeed4"); + setSpeed( (double) mset.speed - 0.04 ); +} + +void Core::incSpeed1() { + qDebug("Core::incSpeed1"); + setSpeed( (double) mset.speed + 0.01 ); +} + +void Core::decSpeed1() { + qDebug("Core::decSpeed1"); + setSpeed( (double) mset.speed - 0.01 ); +} + +void Core::doubleSpeed() { + qDebug("Core::doubleSpeed"); + setSpeed( (double) mset.speed * 2 ); +} + +void Core::halveSpeed() { + qDebug("Core::halveSpeed"); + setSpeed( (double) mset.speed / 2 ); +} + +void Core::normalSpeed() { + setSpeed(1); +} + +void Core::setVolume(int volume, bool force) { + qDebug("Core::setVolume: %d", volume); + + if ((volume==mset.volume) && (!force)) return; + + mset.volume = volume; + if (mset.volume > 100 ) mset.volume = 100; + if (mset.volume < 0 ) mset.volume = 0; + + if (state() == Paused) { + // Change volume later, after quiting pause + change_volume_after_unpause = true; + } else { + tellmp("volume " + QString::number(volume) + " 1"); + } + + //if (mset.mute) mute(TRUE); + mset.mute=false; + + updateWidgets(); + + displayMessage( tr("Volume: %1").arg(mset.volume) ); + emit volumeChanged( mset.volume ); +} + +void Core::switchMute() { + qDebug("Core::switchMute"); + + mset.mute = !mset.mute; + mute(mset.mute); +} + +void Core::mute(bool b) { + qDebug("Core::mute"); + + mset.mute = b; + + int v = 0; + if (mset.mute) v = 1; + tellmp( pausing_prefix() + " mute " + QString::number(v) ); + + updateWidgets(); +} + +void Core::incVolume() { + qDebug("Core::incVolume"); + setVolume(mset.volume + 4); +} + +void Core::decVolume() { + qDebug("Core::incVolume"); + setVolume(mset.volume-4); +} + +void Core::incSubDelay() { + qDebug("Core::incSubDelay"); + + mset.sub_delay += 100; + tellmp("sub_delay " + QString::number( (double) mset.sub_delay/1000 ) +" 1"); +} + +void Core::decSubDelay() { + qDebug("Core::decSubDelay"); + + mset.sub_delay -= 100; + tellmp("sub_delay " + QString::number( (double) mset.sub_delay/1000 ) +" 1"); +} + +void Core::incAudioDelay() { + qDebug("Core::incAudioDelay"); + + mset.audio_delay += 100; + tellmp("audio_delay " + QString::number( (double) mset.audio_delay/1000 ) +" 1"); +} + +void Core::decAudioDelay() { + qDebug("Core::decAudioDelay"); + + mset.audio_delay -= 100; + tellmp("audio_delay " + QString::number( (double) mset.audio_delay/1000 ) +" 1"); +} + +void Core::incSubPos() { + qDebug("Core::incSubPos"); + + mset.sub_pos++; + if (mset.sub_pos > 100) mset.sub_pos = 100; + tellmp("sub_pos " + QString::number( mset.sub_pos ) + " 1"); +} + +void Core::decSubPos() { + qDebug("Core::decSubPos"); + + mset.sub_pos--; + if (mset.sub_pos < 0) mset.sub_pos = 0; + tellmp("sub_pos " + QString::number( mset.sub_pos ) + " 1"); +} + +bool Core::subscale_need_restart() { + bool need_restart = false; + + need_restart = (pref->change_sub_scale_should_restart == Preferences::Enabled); + if (pref->change_sub_scale_should_restart == Preferences::Detect) { + if (pref->use_ass_subtitles) + need_restart = (!MplayerVersion::isMplayerAtLeast(25843)); + else + need_restart = (!MplayerVersion::isMplayerAtLeast(23745)); + } + return need_restart; +} + +void Core::changeSubScale(double value) { + qDebug("Core::changeSubScale: %f", value); + + bool need_restart = subscale_need_restart(); + + if (value < 0) value = 0; + + if (pref->use_ass_subtitles) { + if (value != mset.sub_scale_ass) { + mset.sub_scale_ass = value; + if (need_restart) { + restartPlay(); + } else { + tellmp("sub_scale " + QString::number( mset.sub_scale_ass ) + " 1"); + } + displayMessage( tr("Font scale: %1").arg(mset.sub_scale_ass) ); + } + } else { + // No ass + if (value != mset.sub_scale) { + mset.sub_scale = value; + if (need_restart) { + restartPlay(); + } else { + tellmp("sub_scale " + QString::number( mset.sub_scale ) + " 1"); + + } + displayMessage( tr("Font scale: %1").arg(mset.sub_scale) ); + } + } +} + +void Core::incSubScale() { + double step = 0.20; + + if (pref->use_ass_subtitles) { + changeSubScale( mset.sub_scale_ass + step ); + } else { + if (subscale_need_restart()) step = 1; + changeSubScale( mset.sub_scale + step ); + } +} + +void Core::decSubScale() { + double step = 0.20; + + if (pref->use_ass_subtitles) { + changeSubScale( mset.sub_scale_ass - step ); + } else { + if (subscale_need_restart()) step = 1; + changeSubScale( mset.sub_scale - step ); + } +} + +void Core::incSubStep() { + qDebug("Core::incSubStep"); + tellmp("sub_step +1"); +} + +void Core::decSubStep() { + qDebug("Core::decSubStep"); + tellmp("sub_step -1"); +} + +// Audio equalizer functions +void Core::setAudioEqualizer(AudioEqualizerList values, bool restart) { + mset.audio_equalizer = values; + + if (!restart) { + tellmp( "af_eq_set_bands " + Helper::equalizerListToString(values) ); + } else { + restartPlay(); + } + + emit audioEqualizerNeedsUpdate(); +} + +void Core::updateAudioEqualizer() { + setAudioEqualizer(mset.audio_equalizer); +} + +void Core::setAudioEq0(int value) { + mset.audio_equalizer[0] = value; + updateAudioEqualizer(); +} + +void Core::setAudioEq1(int value) { + mset.audio_equalizer[1] = value; + updateAudioEqualizer(); +} + +void Core::setAudioEq2(int value) { + mset.audio_equalizer[2] = value; + updateAudioEqualizer(); +} + +void Core::setAudioEq3(int value) { + mset.audio_equalizer[3] = value; + updateAudioEqualizer(); +} + +void Core::setAudioEq4(int value) { + mset.audio_equalizer[4] = value; + updateAudioEqualizer(); +} + +void Core::setAudioEq5(int value) { + mset.audio_equalizer[5] = value; + updateAudioEqualizer(); +} + +void Core::setAudioEq6(int value) { + mset.audio_equalizer[6] = value; + updateAudioEqualizer(); +} + +void Core::setAudioEq7(int value) { + mset.audio_equalizer[7] = value; + updateAudioEqualizer(); +} + +void Core::setAudioEq8(int value) { + mset.audio_equalizer[8] = value; + updateAudioEqualizer(); +} + +void Core::setAudioEq9(int value) { + mset.audio_equalizer[9] = value; + updateAudioEqualizer(); +} + + + +void Core::changeCurrentSec(double sec) { + mset.current_sec = sec; + + if (mset.starting_time != -1) { + mset.current_sec -= mset.starting_time; + } + + if (state() != Playing) { + setState(Playing); + qDebug("Core::changeCurrentSec: mplayer reports that now it's playing"); + //emit mediaStartPlay(); + //emit stateChanged(state()); + } + + emit showTime(mset.current_sec); + + // Emit posChanged: + static int last_second = 0; + + if (floor(sec)==last_second) return; // Update only once per second + last_second = (int) floor(sec); + +#ifdef SEEKBAR_RESOLUTION + int value = 0; + if ( (mdat.duration > 1) && (mset.current_sec > 1) && + (mdat.duration > mset.current_sec) ) + { + value = ( (int) mset.current_sec * SEEKBAR_RESOLUTION) / (int) mdat.duration; + } + emit positionChanged(value); +#else + int perc = 0; + if ( (mdat.duration > 1) && (mset.current_sec > 1) && + (mdat.duration > mset.current_sec) ) + { + perc = ( (int) mset.current_sec * 100) / (int) mdat.duration; + } + emit posChanged( perc ); +#endif +} + +void Core::gotStartingTime(double time) { + qDebug("Core::gotStartingTime: %f", time); + qDebug("Core::gotStartingTime: current_sec: %f", mset.current_sec); + if ((mset.starting_time == -1.0) && (mset.current_sec == 0)) { + mset.starting_time = time; + qDebug("Core::gotStartingTime: starting time set to %f", time); + } +} + + +void Core::changePause() { + qDebug("Core::changePause"); + qDebug("Core::changePause: mplayer reports that it's paused"); + setState(Paused); + //emit stateChanged(state()); +} + +void Core::changeDeinterlace(int ID) { + qDebug("Core::changeDeinterlace: %d", ID); + + if (ID!=mset.current_deinterlacer) { + mset.current_deinterlacer = ID; + restartPlay(); + } +} + + + +void Core::changeSubtitle(int ID) { + qDebug("Core::changeSubtitle: %d", ID); + + mset.current_sub_id = ID; + if (ID==MediaSettings::SubNone) { + ID=-1; + } + + if (ID==MediaSettings::NoneSelected) { + ID=-1; + qDebug("Core::changeSubtitle: subtitle is NoneSelected, this shouldn't happen. ID set to -1."); + } + + qDebug("Core::changeSubtitle: ID: %d", ID); + + bool use_new_commands = (pref->use_new_sub_commands == Preferences::Enabled); + if (pref->use_new_sub_commands == Preferences::Detect) { + use_new_commands = (MplayerVersion::isMplayerAtLeast(25158)); + } + + if (!use_new_commands) { + // Old command sub_select + tellmp( "sub_select " + QString::number(ID) ); + } else { + // New commands + int real_id = -1; + if (ID == -1) { + tellmp( "sub_source -1" ); + } else { + bool valid_item = ( (ID >= 0) && (ID < mdat.subs.numItems()) ); + if (!valid_item) qWarning("Core::changeSubtitle: ID: %d is not valid!", ID); + if ( (mdat.subs.numItems() > 0) && (valid_item) ) { + real_id = mdat.subs.itemAt(ID).ID(); + switch (mdat.subs.itemAt(ID).type()) { + case SubData::Vob: + tellmp( "sub_vob " + QString::number(real_id) ); + break; + case SubData::Sub: + tellmp( "sub_demux " + QString::number(real_id) ); + break; + case SubData::File: + tellmp( "sub_file " + QString::number(real_id) ); + break; + default: { + qWarning("Core::changeSubtitle: unknown type!"); + } + } + } else { + qWarning("Core::changeSubtitle: subtitle list is empty!"); + } + } + } + + updateWidgets(); +} + +void Core::nextSubtitle() { + qDebug("Core::nextSubtitle"); + + if ( (mset.current_sub_id == MediaSettings::SubNone) && + (mdat.subs.numItems() > 0) ) + { + changeSubtitle(0); + } + else { + int item = mset.current_sub_id + 1; + if (item >= mdat.subs.numItems()) { + item = MediaSettings::SubNone; + } + changeSubtitle( item ); + } +} + +void Core::changeAudio(int ID, bool allow_restart) { + qDebug("Core::changeAudio: ID: %d, allow_restart: %d", ID, allow_restart); + + if (ID!=mset.current_audio_id) { + mset.current_audio_id = ID; + qDebug("changeAudio: ID: %d", ID); + + bool need_restart = false; + if (allow_restart) { + need_restart = (pref->fast_audio_change == Preferences::Disabled); + if (pref->fast_audio_change == Preferences::Detect) { + need_restart = (!MplayerVersion::isMplayerAtLeast(21441)); + } + } + + if (need_restart) { + restartPlay(); + } else { + tellmp("switch_audio " + QString::number(ID) ); + //#ifdef Q_OS_WIN + // Workaround for a mplayer problem in windows, + // volume is too loud after changing audio. + + // Workaround too for a mplayer problem in linux, + // the volume is reduced if using -softvol-max. + if (!pref->dont_change_volume) { + setVolume( mset.volume, true ); + } + //#endif + if (mset.mute) mute(true); // if muted, mute again + updateWidgets(); + } + } +} + +void Core::nextAudio() { + qDebug("Core::nextAudio"); + + int item = mdat.audios.find( mset.current_audio_id ); + if (item == -1) { + qWarning("Core::nextAudio: audio ID %d not found!", mset.current_audio_id); + } else { + qDebug( "Core::nextAudio: numItems: %d, item: %d", mdat.audios.numItems(), item); + item++; + if (item >= mdat.audios.numItems()) item=0; + int ID = mdat.audios.itemAt(item).ID(); + qDebug( "Core::nextAudio: item: %d, ID: %d", item, ID); + changeAudio( ID ); + } +} + +void Core::changeVideo(int ID, bool allow_restart) { + qDebug("Core::changeVideo: ID: %d, allow_restart: %d", ID, allow_restart); + + if (ID != mset.current_video_id) { + mset.current_video_id = ID; + qDebug("Core::changeVideo: ID set to: %d", ID); + + bool need_restart = false; + if (allow_restart) { + // afaik lavf doesn't require to restart, any other? + need_restart = (mdat.demuxer != "lavf"); + } + + if (need_restart) { + restartPlay(); + } else { + tellmp("set_property switch_video " + QString::number(ID) ); + } + } +} + +void Core::nextVideo() { + qDebug("Core::nextVideo"); + + int item = mdat.videos.find( mset.current_video_id ); + if (item == -1) { + qWarning("Core::nextVideo: video ID %d not found!", mset.current_video_id); + } else { + qDebug( "Core::nextVideo: numItems: %d, item: %d", mdat.videos.numItems(), item); + item++; + if (item >= mdat.videos.numItems()) item=0; + int ID = mdat.videos.itemAt(item).ID(); + qDebug( "Core::nextVideo: item: %d, ID: %d", item, ID); + changeVideo( ID ); + } +} + + +void Core::changeTitle(int ID) { + if (mdat.type == TYPE_VCD) { + // VCD + openVCD( ID ); + } + else + if (mdat.type == TYPE_AUDIO_CD) { + // AUDIO CD + openAudioCD( ID ); + } + else + if (mdat.type == TYPE_DVD) { + QString dvd_url = "dvd://" + QString::number(ID); + QString folder = Helper::dvdSplitFolder(mdat.filename); + if (!folder.isEmpty()) dvd_url += ":" + folder; + + openDVD(dvd_url); + //openDVD( ID ); + } +} + +void Core::changeChapter(int ID) { + qDebug("Core::changeChapter: ID: %d", ID); + + if (ID != mset.current_chapter_id) { + //if (QFileInfo(mdat.filename).extension().lower()=="mkv") { +#if GENERIC_CHAPTER_SUPPORT + if (mdat.type != TYPE_DVD) { +#else + if (mdat.mkv_chapters > 0) { + // mkv doesn't require to restart +#endif + tellmp("seek_chapter " + QString::number(ID) +" 1"); + mset.current_chapter_id = ID; + updateWidgets(); + } else { +#if SMART_DVD_CHAPTERS + if (pref->cache_for_dvds == 0) { +#else + if (pref->fast_chapter_change) { +#endif + tellmp("seek_chapter " + QString::number(ID) +" 1"); + mset.current_chapter_id = ID; + updateWidgets(); + } else { + stopMplayer(); + mset.current_chapter_id = ID; + //goToPos(0); + mset.current_sec = 0; + restartPlay(); + } + } + } +} + +int Core::firstChapter() { + if (MplayerVersion::isMplayerAtLeast(25391)) + return 1; + else + return 0; +} + +#if !GENERIC_CHAPTER_SUPPORT +int Core::dvdFirstChapter() { + // TODO: check if the change really happens in the same version as mkv + return firstChapter(); +} +#endif + +void Core::prevChapter() { + qDebug("Core::prevChapter"); + +#if GENERIC_CHAPTER_SUPPORT + int last_chapter = 0; + int first_chapter = firstChapter(); + + last_chapter = mdat.chapters + firstChapter() - 1; + + int ID = mset.current_chapter_id - 1; + if (ID < first_chapter) { + ID = last_chapter; + } + changeChapter(ID); +#else + int last_chapter = 0; + bool matroshka = (mdat.mkv_chapters > 0); + + int first_chapter = dvdFirstChapter(); + if (matroshka) first_chapter = firstChapter(); + + // Matroshka chapters + if (matroshka) last_chapter = mdat.mkv_chapters + firstChapter() - 1; + else + // DVD chapters + if (mset.current_title_id > 0) { + last_chapter = mdat.titles.item(mset.current_title_id).chapters() + dvdFirstChapter() -1; + } + + int ID = mset.current_chapter_id - 1; + if (ID < first_chapter) { + ID = last_chapter; + } + changeChapter(ID); +#endif +} + +void Core::nextChapter() { + qDebug("Core::nextChapter"); + +#if GENERIC_CHAPTER_SUPPORT + int last_chapter = 0; + last_chapter = mdat.chapters + firstChapter() - 1; + + int ID = mset.current_chapter_id + 1; + if (ID > last_chapter) { + ID = firstChapter(); + } + changeChapter(ID); +#else + int last_chapter = 0; + bool matroshka = (mdat.mkv_chapters > 0); + + // Matroshka chapters + if (matroshka) last_chapter = mdat.mkv_chapters + firstChapter() - 1; + else + // DVD chapters + if (mset.current_title_id > 0) { + last_chapter = mdat.titles.item(mset.current_title_id).chapters() + dvdFirstChapter() - 1; + } + + int ID = mset.current_chapter_id + 1; + if (ID > last_chapter) { + if (matroshka) ID = firstChapter(); else ID = dvdFirstChapter(); + } + changeChapter(ID); +#endif +} + +void Core::changeAngle(int ID) { + qDebug("Core::changeAngle: ID: %d", ID); + + if (ID != mset.current_angle_id) { + mset.current_angle_id = ID; + restartPlay(); + } +} + +#if NEW_ASPECT_CODE +void Core::changeAspectRatio( int ID ) { + qDebug("Core::changeAspectRatio: %d", ID); + + mset.aspect_ratio_id = ID; + + double asp = mset.aspectToNum( (MediaSettings::Aspect) ID); + + if (!pref->use_mplayer_window) { + mplayerwindow->setAspect( asp ); + } else { + // Using mplayer own window + if (!mdat.novideo) { + tellmp("switch_ratio " + QString::number(asp)); + } + } + + QString asp_name = MediaSettings::aspectToString( (MediaSettings::Aspect) mset.aspect_ratio_id); + displayMessage( tr("Aspect ratio: %1").arg(asp_name) ); +} + +void Core::nextAspectRatio() { + int ID = mset.aspect_ratio_id + 1; + if (ID > MediaSettings:: Aspect11) ID = MediaSettings::AspectNone; + changeAspectRatio(ID); + + updateWidgets(); +} + +void Core::changeLetterbox(bool b) { + qDebug("Core::changeLetterbox: %d", b); + + if (mset.add_letterbox != b) { + mset.add_letterbox = b; + restartPlay(); + } +} + +#else +void Core::changeAspectRatio( int ID ) { + qDebug("Core::changeAspectRatio: %d", ID); + + int old_id = mset.aspect_ratio_id; + mset.aspect_ratio_id = ID; + bool need_restart = FALSE; + + double asp = mdat.video_aspect; // Set a default + + if (ID==MediaSettings::Aspect43Letterbox) { + need_restart = (old_id != MediaSettings::Aspect43Letterbox); + asp = (double) 4 / 3; + mset.letterbox = MediaSettings::Letterbox_43; + mset.panscan_filter = ""; + mset.crop_43to169_filter = ""; + } + else + if (ID==MediaSettings::Aspect169Letterbox) { + need_restart = (old_id != MediaSettings::Aspect169Letterbox); + asp = (double) 16 / 9; + mset.letterbox = MediaSettings::Letterbox_169; + mset.panscan_filter = ""; + mset.crop_43to169_filter = ""; + } + else + if (ID==MediaSettings::Aspect43Panscan) { + need_restart = (old_id != MediaSettings::Aspect43Panscan); + mset.crop_43to169_filter = ""; + mset.letterbox = MediaSettings::NoLetterbox; + + asp = (double) 4 / 3; + int real_width = (int) round(mdat.video_height * mdat.video_aspect); + mset.panscan_filter = QString("scale=%1:%2,").arg(real_width).arg(mdat.video_height); + mset.panscan_filter += QString("crop=%1:%2").arg(round(mdat.video_height * 4 /3)).arg(mdat.video_height); + //mset.crop = QSize( mdat.video_height * 4 /3, mdat.video_height ); + qDebug("Core::changeAspectRatio: panscan_filter = '%s'", mset.panscan_filter.toUtf8().data() ); + + } + else + if (ID==MediaSettings::Aspect43To169) { + need_restart = (old_id != MediaSettings::Aspect43To169); + mset.panscan_filter = ""; + mset.crop_43to169_filter = ""; + mset.letterbox = MediaSettings::NoLetterbox; + + int real_width = (int) round(mdat.video_height * mdat.video_aspect); + int height = (int) round(real_width * 9 / 16); + + qDebug("Core::changeAspectRatio: video_width: %d, video_height: %d", real_width, mdat.video_height); + qDebug("Core::changeAspectRatio: crop: %d, %d", real_width, height ); + + if (height > mdat.video_height) { + // Invalid size, source video is not 4:3 + need_restart = FALSE; + } else { + asp = (double) 16 / 9; + mset.crop_43to169_filter = QString("scale=%1:%2,").arg(real_width).arg(mdat.video_height); + mset.crop_43to169_filter += QString("crop=%1:%2").arg(real_width).arg(height); + qDebug("Core::changeAspectRatio: crop_43to169_filter = '%s'", mset.crop_43to169_filter.toUtf8().data() ); + } + } + else + { + //need_restart = (mset.force_letterbox == TRUE); + need_restart = ( (old_id == MediaSettings::Aspect43Letterbox) || + (old_id == MediaSettings::Aspect169Letterbox) || + (old_id == MediaSettings::Aspect43Panscan) || + (old_id == MediaSettings::Aspect43To169) ); + mset.letterbox = MediaSettings::NoLetterbox; + mset.panscan_filter = ""; + mset.crop_43to169_filter = ""; + switch (ID) { + //case MediaSettings::AspectAuto: asp = mdat.video_aspect; break; + case MediaSettings::AspectAuto: { + qDebug("Core::changeAspectRatio: mset.win_width %d, mset.win_height: %d", mset.win_width, mset.win_height); + asp = mset.win_aspect(); break; + } + case MediaSettings::Aspect43: asp = (double) 4 / 3; break; + case MediaSettings::Aspect169: asp = (double) 16 / 9; break; + case MediaSettings::Aspect149: asp = (double) 14 / 9; break; + case MediaSettings::Aspect1610: asp = (double) 16 / 10; break; + case MediaSettings::Aspect54: asp = (double) 5 / 4; break; + case MediaSettings::Aspect235: asp = 2.35; break; + } + } + + if (!pref->use_mplayer_window) { + mplayerwindow->setAspect( asp ); + } else { + // Using mplayer own window + tellmp("switch_ratio " + QString::number(asp)); + } + + updateWidgets(); + + if (need_restart) { + /*mdat.calculateWinResolution(mset.force_letterbox);*/ + restartPlay(); + } +} +#endif + +void Core::changeOSD(int v) { + qDebug("Core::changeOSD: %d", v); + + pref->osd = v; + tellmp("osd " + QString::number( pref->osd ) ); + updateWidgets(); +} + +void Core::nextOSD() { + int osd = pref->osd + 1; + if (osd > Preferences::SeekTimerTotal) { + osd = Preferences::None; + } + changeOSD( osd ); +} + +void Core::changeRotate(int r) { + qDebug("Core::changeRotate: %d", r); + + if (mset.rotate != r) { + mset.rotate = r; + restartPlay(); + } +} + +#if USE_ADAPTER +void Core::changeAdapter(int n) { + qDebug("Core::changeScreen: %d", n); + + if (pref->adapter != n) { + pref->adapter = n; + restartPlay(); + } +} +#endif + +void Core::changeSize(int n) { + if ( /*(n != pref->size_factor) &&*/ (!pref->use_mplayer_window) ) { + pref->size_factor = n; + + emit needResize(mset.win_width, mset.win_height); + updateWidgets(); + } +} + +void Core::toggleDoubleSize() { + if (pref->size_factor != 100) + changeSize(100); + else + changeSize(200); +} + +void Core::changePanscan(double p) { + qDebug("Core::changePanscan: %f", p); + if (p < ZOOM_MIN) p = ZOOM_MIN; + + mset.panscan_factor = p; + mplayerwindow->setZoom(p); + displayMessage( tr("Zoom: %1").arg(mset.panscan_factor) ); +} + +void Core::resetPanscan() { + changePanscan(1.0); +} + +void Core::autoPanscan() { + double video_aspect = mset.aspectToNum( (MediaSettings::Aspect) mset.aspect_ratio_id); + + if (video_aspect <= 0) { + QSize w = mplayerwindow->videoLayer()->size(); + video_aspect = (double) w.width() / w.height(); + } + + double screen_aspect = DesktopInfo::desktop_aspectRatio(mplayerwindow); + double zoom_factor; + + if (video_aspect > screen_aspect) + zoom_factor = video_aspect / screen_aspect; + else + zoom_factor = screen_aspect / video_aspect; + + qDebug("Core::autoPanscan: video_aspect: %f", video_aspect); + qDebug("Core::autoPanscan: screen_aspect: %f", screen_aspect); + qDebug("Core::autoPanscan: zoom_factor: %f", zoom_factor); + + changePanscan(zoom_factor); +} + +void Core::autoPanscanFromLetterbox(double aspect) { + qDebug("Core::autoPanscanFromLetterbox: %f", aspect); + + // Probably there's a much easy way to do this, but I'm not good with maths... + + QSize desktop = DesktopInfo::desktop_size(mplayerwindow); + + double video_aspect = mset.aspectToNum( (MediaSettings::Aspect) mset.aspect_ratio_id); + + if (video_aspect <= 0) { + QSize w = mplayerwindow->videoLayer()->size(); + video_aspect = (double) w.width() / w.height(); + } + + // Calculate size of the video in fullscreen + QSize video; + video.setHeight( desktop.height() );; + video.setWidth( (int) (video.height() * video_aspect) ); + if (video.width() > desktop.width()) { + video.setWidth( desktop.width() );; + video.setHeight( (int) (video.width() / video_aspect) ); + } + + qDebug("Core::autoPanscanFromLetterbox: max. size of video: %d %d", video.width(), video.height()); + + // Calculate the size of the actual video inside the letterbox + QSize actual_video; + actual_video.setWidth( video.width() ); + actual_video.setHeight( (int) (actual_video.width() / aspect) ); + + qDebug("Core::autoPanscanFromLetterbox: calculated size of actual video for aspect %f: %d %d", aspect, actual_video.width(), actual_video.height()); + + double zoom_factor = (double) desktop.height() / actual_video.height(); + + qDebug("Core::autoPanscanFromLetterbox: calculated zoom factor: %f", zoom_factor); + changePanscan(zoom_factor); +} + +void Core::autoPanscanFor169() { + autoPanscanFromLetterbox((double) 16 / 9); +} + +void Core::autoPanscanFor235() { + autoPanscanFromLetterbox(2.35); +} + +void Core::incPanscan() { + qDebug("Core::incPanscan"); + changePanscan( mset.panscan_factor + ZOOM_STEP ); +} + +void Core::decPanscan() { + qDebug("Core::decPanscan"); + changePanscan( mset.panscan_factor - ZOOM_STEP ); +} + +void Core::changeUseAss(bool b) { + qDebug("Core::changeUseAss: %d", b); + + if (pref->use_ass_subtitles != b) { + pref->use_ass_subtitles = b; + if (proc->isRunning()) restartPlay(); + } +} + +void Core::toggleClosedCaption(bool b) { + qDebug("Core::toggleClosedCaption: %d", b); + + if (pref->use_closed_caption_subs != b) { + pref->use_closed_caption_subs = b; + if (proc->isRunning()) restartPlay(); + } +} + +void Core::toggleForcedSubsOnly(bool b) { + qDebug("Core::toggleForcedSubsOnly: %d", b); + + if (pref->use_forced_subs_only != b) { + pref->use_forced_subs_only = b; + //if (proc->isRunning()) restartPlay(); + int v = 0; + if (b) v = 1; + tellmp( QString("forced_subs_only %1").arg(v) ); + } +} + +void Core::visualizeMotionVectors(bool b) { + qDebug("Core::visualizeMotionVectors: %d", b); + + if (pref->show_motion_vectors != b) { + pref->show_motion_vectors = b; + if (proc->isRunning()) restartPlay(); + } +} + +#if DVDNAV_SUPPORT +// dvdnav buttons +void Core::dvdnavUp() { + qDebug("Core::dvdnavUp"); + tellmp("dvdnav up"); +} + +void Core::dvdnavDown() { + qDebug("Core::dvdnavDown"); + tellmp("dvdnav down"); +} + +void Core::dvdnavLeft() { + qDebug("Core::dvdnavLeft"); + tellmp("dvdnav left"); +} + +void Core::dvdnavRight() { + qDebug("Core::dvdnavRight"); + tellmp("dvdnav right"); +} + +void Core::dvdnavMenu() { + qDebug("Core::dvdnavMenu"); + tellmp("dvdnav menu"); +} + +void Core::dvdnavSelect() { + qDebug("Core::dvdnavSelect"); + tellmp("dvdnav select"); +} + +void Core::dvdnavPrev() { + qDebug("Core::dvdnavPrev"); + tellmp("dvdnav prev"); +} + +void Core::dvdnavMouse() { + qDebug("Core::dvdnavMouse"); + + QPoint p = mplayerwindow->videoLayer()->mapFromGlobal(QCursor::pos()); + + tellmp(QString("set_mouse_pos %1 %2").arg(p.x()).arg(p.y())); + tellmp("dvdnav mouse"); +} +#endif + +void Core::displayMessage(QString text) { + qDebug("Core::displayMessage"); + emit showMessage(text); + + if ((pref->fullscreen) && (state() != Paused)) { + tellmp("osd_show_text \"" + text + "\" 3000 1"); + } +} + +void Core::displayScreenshotName(QString filename) { + qDebug("Core::displayScreenshotName"); + //QString text = tr("Screenshot saved as %1").arg(filename); + QString text = QString("Screenshot saved as %1").arg(filename); + + if (MplayerVersion::isMplayerAtLeast(27665)) { + tellmp( "pausing_keep_force osd_show_text \"" + text + "\" 3000 1"); + } + else + if (state() != Paused) { + // Dont' show the message on OSD while in pause, otherwise + // the video goes forward a frame. + tellmp("pausing_keep osd_show_text \"" + text + "\" 3000 1"); + } + + emit showMessage(text); +} + +void Core::displayUpdatingFontCache() { + qDebug("Core::displayUpdatingFontCache"); + emit showMessage( tr("Updating the font cache. This may take some seconds...") ); +} + +void Core::gotWindowResolution(int w, int h) { + qDebug("Core::gotWindowResolution: %d, %d", w, h); + //double aspect = (double) w/h; + + if (pref->use_mplayer_window) { + emit noVideo(); + } else { + if ((pref->resize_method==Preferences::Afterload) && (we_are_restarting)) { + // Do nothing + } else { + emit needResize(w,h); + } + } + + mset.win_width = w; + mset.win_height = h; + + //Override aspect ratio, is this ok? + //mdat.video_aspect = mset.win_aspect(); + + mplayerwindow->setResolution( w, h ); + mplayerwindow->setAspect( mset.win_aspect() ); +} + +void Core::gotNoVideo() { + // File has no video (a sound file) + + // Reduce size of window + /* + mset.win_width = mplayerwindow->size().width(); + mset.win_height = 0; + mplayerwindow->setResolution( mset.win_width, mset.win_height ); + emit needResize( mset.win_width, mset.win_height ); + */ + //mplayerwindow->showLogo(TRUE); + emit noVideo(); +} + +void Core::gotVO(QString vo) { + qDebug("Core::gotVO: '%s'", vo.toUtf8().data() ); + + if ( pref->vo.isEmpty()) { + qDebug("Core::gotVO: saving vo"); + pref->vo = vo; + } +} + +void Core::gotAO(QString ao) { + qDebug("Core::gotAO: '%s'", ao.toUtf8().data() ); + + if ( pref->ao.isEmpty()) { + qDebug("Core::gotAO: saving ao"); + pref->ao = ao; + } +} + +void Core::streamTitleAndUrlChanged(QString title, QString url) { + mdat.stream_title = title; + mdat.stream_url = url; + emit mediaInfoChanged(); +} + +//! Called when the state changes +void Core::watchState(Core::State state) { + if ((state == Playing) && (change_volume_after_unpause)) + { + // Delayed volume change + qDebug("Core::watchState: delayed volume change"); + tellmp("volume " + QString::number(mset.volume) + " 1"); + change_volume_after_unpause = false; + } +} + +void Core::checkIfVideoIsHD() { + qDebug("Core::checkIfVideoIsHD"); + + // Check if the video is in HD and uses ffh264 codec. + if ((mdat.video_codec=="ffh264") && (mset.win_height >= pref->HD_height)) { + qDebug("Core::checkIfVideoIsHD: video == ffh264 and height >= %d", pref->HD_height); + if (!mset.is264andHD) { + mset.is264andHD = true; + if (pref->h264_skip_loop_filter == Preferences::LoopDisabledOnHD) { + qDebug("Core::checkIfVideoIsHD: we're about to restart the video"); + restartPlay(); + } + } + } else { + mset.is264andHD = false; + // FIXME: if the video was previously marked as HD, and now it's not + // then the video should restart too. + } +} + +#if DELAYED_AUDIO_SETUP_ON_STARTUP && NOTIFY_AUDIO_CHANGES +#error "DELAYED_AUDIO_SETUP_ON_STARTUP and NOTIFY_AUDIO_CHANGES can't be both defined" +#endif + +#if DELAYED_AUDIO_SETUP_ON_STARTUP +void Core::initAudioTrack() { + qDebug("Core::initAudioTrack"); + + // First audio if none selected + if ( (mset.current_audio_id == MediaSettings::NoneSelected) && + (mdat.audios.numItems() > 0) ) + { + // Don't set mset.current_audio_id here! changeAudio will do. + // Otherwise changeAudio will do nothing. + + int audio = mdat.audios.itemAt(0).ID(); // First one + if (mdat.audios.existsItemAt(pref->initial_audio_track-1)) { + audio = mdat.audios.itemAt(pref->initial_audio_track-1).ID(); + } + + // Check if one of the audio tracks is the user preferred. + if (!pref->audio_lang.isEmpty()) { + int res = mdat.audios.findLang( pref->audio_lang ); + if (res != -1) audio = res; + } + + changeAudio( audio ); + } +} +#endif + +#if NOTIFY_AUDIO_CHANGES +void Core::initAudioTrack(const Tracks & audios) { + qDebug("Core::initAudioTrack"); + + qDebug("Core::initAudioTrack: num_items: %d", mdat.audios.numItems()); + + bool restore_audio = ((mdat.audios.numItems() > 0) || + (mset.current_audio_id != MediaSettings::NoneSelected)); + + mdat.audios = audios; + + qDebug("Core::initAudioTrack: list of audios:"); + mdat.audios.list(); + + initializeMenus(); + + if (!restore_audio) { + // Select initial track + qDebug("Core::initAudioTrack: selecting initial track"); + + int audio = mdat.audios.itemAt(0).ID(); // First one + if (mdat.audios.existsItemAt(pref->initial_audio_track-1)) { + audio = mdat.audios.itemAt(pref->initial_audio_track-1).ID(); + } + + // Check if one of the audio tracks is the user preferred. + if (!pref->audio_lang.isEmpty()) { + int res = mdat.audios.findLang( pref->audio_lang ); + if (res != -1) audio = res; + } + + changeAudio( audio ); + } else { + // Try to restore previous audio track + qDebug("Core::initAudioTrack: restoring audio"); + // Nothing to do, the audio is already set with -aid + } + + updateWidgets(); + + emit audioTracksChanged(); +} +#endif + +#if NOTIFY_SUB_CHANGES +void Core::initSubtitleTrack(const SubTracks & subs) { + qDebug("Core::initSubtitleTrack"); + + qDebug("Core::initSubtitleTrack: num_items: %d", mdat.subs.numItems()); + + bool restore_subs = ((mdat.subs.numItems() > 0) || + (mset.current_sub_id != MediaSettings::NoneSelected)); + + // Save current sub + SubData::Type previous_sub_type = SubData::Sub; + int previous_sub_id = -1; + if (mdat.subs.numItems() > 0) { + if ((mset.current_sub_id != MediaSettings::SubNone) && + (mset.current_sub_id != MediaSettings::NoneSelected)) + { + previous_sub_type = mdat.subs.itemAt(mset.current_sub_id).type(); + previous_sub_id = mdat.subs.itemAt(mset.current_sub_id).ID(); + } + } + qDebug("Core::initSubtitleTrack: previous subtitle: type: %d id: %d", previous_sub_type, previous_sub_id); + + mdat.subs = subs; + + qDebug("Core::initSubtitleTrack: list of subtitles:"); + mdat.subs.list(); + + initializeMenus(); + + if (just_unloaded_external_subs) { + qDebug("Core::initSubtitleTrack: just_unloaded_external_subs: true"); + restore_subs = false; + just_unloaded_external_subs = false; + } + if (just_loaded_external_subs) { + qDebug("Core::initSubtitleTrack: just_loaded_external_subs: true"); + restore_subs = false; + just_loaded_external_subs = false; + } + + if (!restore_subs) { + // Select initial track + qDebug("Core::initSubtitleTrack: selecting initial track"); + + if (!pref->autoload_sub) { + changeSubtitle( MediaSettings::SubNone ); + } else { + //Select first subtitle + int sub = mdat.subs.selectOne( pref->subtitle_lang, pref->initial_subtitle_track-1 ); + changeSubtitle( sub ); + } + } else { + // Try to restore previous subtitle track + qDebug("Core::initSubtitleTrack: restoring subtitle"); + + if (mset.current_sub_id == MediaSettings::SubNone) { + changeSubtitle( MediaSettings::SubNone ); + } + else + if (mset.current_sub_id != MediaSettings::NoneSelected) { + // Try to find old subtitle + int item = mset.current_sub_id; + if (previous_sub_id != -1) { + int sub_item = mdat.subs.find(previous_sub_type, previous_sub_id); + if (sub_item > -1) { + item = sub_item; + qDebug("Core::initSubtitleTrack: previous subtitle found: %d", sub_item); + } + } + if (item > -1) { + changeSubtitle(item ); + } else { + qDebug("Core::initSubtitleTrack: previous subtitle not found!"); + } + } + } + + updateWidgets(); +} + +void Core::setSubtitleTrackAgain(const SubTracks &) { + qDebug("Core::setSubtitleTrackAgain"); + changeSubtitle( mset.current_sub_id ); +} +#endif + +QString Core::pausing_prefix() { + qDebug("Core::pausing_prefix"); + + if ( (pref->use_pausing_keep_force) && + (MplayerVersion::isMplayerAtLeast(27665)) ) + { + return "pausing_keep_force"; + } else { + return "pausing_keep"; + } +} + +#include "moc_core.cpp" diff --git a/plugins/smplayer_plugin/core.h b/plugins/smplayer_plugin/core.h new file mode 100644 index 000000000..9f9922eaa --- /dev/null +++ b/plugins/smplayer_plugin/core.h @@ -0,0 +1,433 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _CORE_H_ +#define _CORE_H_ + +#include +#include // For QProcess::ProcessError +#include "mediadata.h" +#include "mediasettings.h" +#include "mplayerprocess.h" +#include "config.h" + +#define NEW_SETTINGS_MANAGEMENT 1 + +#ifndef NO_USE_INI_FILES +#if NEW_SETTINGS_MANAGEMENT +class FileSettingsBase; +#endif +#endif + +class MplayerProcess; +class MplayerWindow; +class QSettings; + +#ifdef Q_OS_WIN +class WinScreenSaver; +#endif + +class Core : public QObject +{ + Q_OBJECT + +public: + enum State { Stopped = 0, Playing = 1, Paused = 2 }; + + Core( MplayerWindow *mpw, QWidget* parent = 0 ); + ~Core(); + + MediaData mdat; + MediaSettings mset; + + //! Return the current state + State state() { return _state; }; + + //! Return a string with the name of the current state, + //! so it can be printed on debugging messages. + QString stateToString(); + +protected: + //! Change the current state (Stopped, Playing or Paused) + //! And sends the stateChanged() signal. + void setState(State s); + +public slots: + //! Generic open, with autodetection of type + void open(QString file, int seek=-1); + void openFile(QString filename, int seek=-1); + void openStream(QString name); + /* + void openDVD( bool from_folder, QString directory = ""); + void openDVD(); // Plays title 1 + void openDVD(int title = 1); + */ + void openDVD(QString dvd_url); + void openVCD(int title = -1); + void openAudioCD(int title = -1); + + void loadSub(const QString & sub); + void unloadSub(); + + //! Forces to use the specified subtitle file. It's not loaded immediately but stored + //! and will be used for the next video. After that the variable is cleared. + void setInitialSubtitle(const QString & subtitle_file) { initial_subtitle = subtitle_file; }; + + void loadAudioFile(const QString & audiofile); + void unloadAudioFile(); + + void stop(); + void play(); + void play_or_pause(); + void pause_and_frame_step(); + void pause(); + void frameStep(); + void screenshot(); + + //! Public restart, for the GUI. + void restart(); + + //! Reopens the file (no restart) + void reload(); + +#ifdef SEEKBAR_RESOLUTION + void goToPosition( int value ); +#else + void goToPos( int perc ); +#endif + void goToSec( double sec ); + + void toggleRepeat(); + void toggleRepeat(bool b); + + void toggleFlip(); + void toggleFlip(bool b); + + void toggleMirror(); + void toggleMirror(bool b); + + // Audio filters + void toggleKaraoke(); + void toggleKaraoke(bool b); + void toggleExtrastereo(); + void toggleExtrastereo(bool b); + void toggleVolnorm(); + void toggleVolnorm(bool b); + + void setAudioChannels(int channels); + void setStereoMode(int mode); + + // Video filters + void toggleAutophase(); + void toggleAutophase(bool b); + void toggleDeblock(); + void toggleDeblock(bool b); + void toggleDering(); + void toggleDering(bool b); + void toggleNoise(); + void toggleNoise(bool b); + void togglePostprocessing(); + void togglePostprocessing(bool b); + void changeDenoise(int); +#if NEW_ASPECT_CODE + void changeLetterbox(bool); +#endif + void changeUpscale(bool); + + void seek(int secs); + void sforward(); // + 10 seconds + void srewind(); // - 10 seconds + void forward(); // + 1 minute + void rewind(); // -1 minute + void fastforward(); // + 10 minutes + void fastrewind(); // - 10 minutes + void forward(int secs); + void rewind(int secs); + void wheelUp(); + void wheelDown(); + + void setSpeed( double value ); + void incSpeed10(); //!< Inc speed 10% + void decSpeed10(); //!< Dec speed 10% + void incSpeed4(); //!< Inc speed 4% + void decSpeed4(); //!< Dec speed 4% + void incSpeed1(); //!< Inc speed 1% + void decSpeed1(); //!< Dec speed 1% + void doubleSpeed(); + void halveSpeed(); + void normalSpeed(); + + void setVolume(int volume, bool force = false); + void switchMute(); + void mute(bool b); + void incVolume(); + void decVolume(); + + void setBrightness(int value); + void setContrast(int value); + void setGamma(int value); + void setHue(int value); + void setSaturation(int value); + + void incBrightness(); + void decBrightness(); + void incContrast(); + void decContrast(); + void incGamma(); + void decGamma(); + void incHue(); + void decHue(); + void incSaturation(); + void decSaturation(); + + void incSubDelay(); + void decSubDelay(); + + void incAudioDelay(); + void decAudioDelay(); + + void incSubPos(); + void decSubPos(); + + void changeSubScale(double value); + void incSubScale(); + void decSubScale(); + + //! Select next line in subtitle file + void incSubStep(); + //! Select previous line in subtitle file + void decSubStep(); + + //! Audio equalizer + void setAudioEqualizer(AudioEqualizerList values, bool restart = false); + void setAudioAudioEqualizerRestart(AudioEqualizerList values) { setAudioEqualizer(values, true); }; + void updateAudioEqualizer(); + + void setAudioEq0(int value); + void setAudioEq1(int value); + void setAudioEq2(int value); + void setAudioEq3(int value); + void setAudioEq4(int value); + void setAudioEq5(int value); + void setAudioEq6(int value); + void setAudioEq7(int value); + void setAudioEq8(int value); + void setAudioEq9(int value); + + void changeDeinterlace(int); + void changeSubtitle(int); + void nextSubtitle(); + void changeAudio(int ID, bool allow_restart = true); + void nextAudio(); + void changeVideo(int ID, bool allow_restart = true); + void nextVideo(); + void changeTitle(int); + void changeChapter(int); + void prevChapter(); + void nextChapter(); + void changeAngle(int); + void changeAspectRatio(int); +#if NEW_ASPECT_CODE + void nextAspectRatio(); +#endif + void changeOSD(int); + void nextOSD(); + + void changeSize(int); // Size of the window + void toggleDoubleSize(); + void changePanscan(double); // Zoom on mplayerwindow + + void changeRotate(int r); + +#if USE_ADAPTER + void changeAdapter(int n); +#endif + + void incPanscan(); + void decPanscan(); + void resetPanscan(); + void autoPanscan(); + void autoPanscanFromLetterbox(double video_aspect); + void autoPanscanFor169(); + void autoPanscanFor235(); + + void changeUseAss(bool); + void toggleClosedCaption(bool); + void toggleForcedSubsOnly(bool); + + void visualizeMotionVectors(bool); + +#if DVDNAV_SUPPORT + // dvdnav buttons + void dvdnavUp(); + void dvdnavDown(); + void dvdnavLeft(); + void dvdnavRight(); + void dvdnavMenu(); + void dvdnavSelect(); + void dvdnavPrev(); + void dvdnavMouse(); +#endif + + // Pass a command to mplayer by stdin: + void tellmp(const QString & command); + +public: + //! Returns the number of the first chapter in + //! files. In some versions of mplayer is 0, in others 1 + static int firstChapter(); +#if !GENERIC_CHAPTER_SUPPORT + static int dvdFirstChapter(); +#endif + +#ifndef NO_USE_INI_FILES + void changeFileSettingsMethod(QString method); +#endif + +protected: + //! Returns the prefix to keep pausing on slave commands + QString pausing_prefix(); + +protected slots: + void changeCurrentSec(double sec); + void changePause(); + void gotWindowResolution( int w, int h ); + void gotNoVideo(); + void gotVO(QString); + void gotAO(QString); + void gotStartingTime(double); + + void finishRestart(); + void processFinished(); + void fileReachedEnd(); + + void displayMessage(QString text); + void displayScreenshotName(QString filename); + void displayUpdatingFontCache(); + + void streamTitleAndUrlChanged(QString,QString); + + void watchState(Core::State state); + + //! Called when a video has just started to play. + //! This function checks if the codec of video is ffh264 and if + //! the resolution is HD + void checkIfVideoIsHD(); + +#if DELAYED_AUDIO_SETUP_ON_STARTUP + void initAudioTrack(); +#endif +#if NOTIFY_AUDIO_CHANGES + void initAudioTrack(const Tracks &); +#endif +#if NOTIFY_SUB_CHANGES + void initSubtitleTrack(const SubTracks &); + void setSubtitleTrackAgain(const SubTracks &); +#endif + +protected: + void playNewFile(QString file, int seek=-1); + void restartPlay(); + void initPlaying(int seek=-1); + void newMediaPlaying(); + + void startMplayer(QString file, double seek = -1 ); + void stopMplayer(); + +#ifndef NO_USE_INI_FILES + #if !NEW_SETTINGS_MANAGEMENT + bool checkHaveSettingsSaved(QString filename); + void loadMediaInfo(QString filename); + #endif + void saveMediaInfo(); +#endif + + void initializeMenus(); + void updateWidgets(); + + //! Returns true if changing the subscale requires to restart mplayer + bool subscale_need_restart(); + +signals: + void aboutToStartPlaying(); // Signal emited just before to start mplayer + void mediaLoaded(); + void mediaInfoChanged(); + void stateChanged(Core::State state); + void mediaStartPlay(); + void mediaFinished(); // Media has arrived to the end. + void mediaStoppedByUser(); + void showMessage(QString text); + void menusNeedInitialize(); + void widgetsNeedUpdate(); + void videoEqualizerNeedsUpdate(); + void audioEqualizerNeedsUpdate(); + void showTime(double sec); +#ifdef SEEKBAR_RESOLUTION + void positionChanged(int); // To connect a slider +#else + void posChanged(int); // To connect a slider +#endif + void showFrame(int frame); + void needResize(int w, int h); + void noVideo(); + void volumeChanged(int); +#if NOTIFY_SUB_CHANGES + void audioTracksChanged(); +#endif + + //! MPlayer started but finished with exit code != 0 + void mplayerFinishedWithError(int exitCode); + + //! MPlayer didn't started or crashed + void mplayerFailed(QProcess::ProcessError error); + + // Resend signal from mplayerprocess: + void failedToParseMplayerVersion(QString line_with_mplayer_version); + + //! A new line from the mplayer output is available + void logLineAvailable(QString); + +protected: + MplayerProcess * proc; + MplayerWindow * mplayerwindow; + +#ifndef NO_USE_INI_FILES + #if NEW_SETTINGS_MANAGEMENT + FileSettingsBase * file_settings; + #else + QSettings * file_settings; + #endif +#endif + +#ifdef Q_OS_WIN + WinScreenSaver * win_screensaver; +#endif + +private: + // Some variables to proper restart + bool we_are_restarting; + + bool just_loaded_external_subs; + bool just_unloaded_external_subs; + State _state; + bool change_volume_after_unpause; + + QString initial_subtitle; +}; + +#endif diff --git a/plugins/smplayer_plugin/corelib/smplayercore.pro b/plugins/smplayer_plugin/corelib/smplayercore.pro new file mode 100644 index 000000000..5d2fb4e6a --- /dev/null +++ b/plugins/smplayer_plugin/corelib/smplayercore.pro @@ -0,0 +1,57 @@ +TEMPLATE = lib +LANGUAGE = c++ +CONFIG += qt warn_on release staticlib + +INCLUDEPATH = .. +DEPENDOATH = .. + +DEFINES += MINILIB NO_USE_INI_FILES + +HEADERS += ../config.h \ + ../constants.h \ + ../global.h \ + ../helper.h \ + ../subtracks.h \ + ../audiotracks.h \ + ../titletracks.h \ + ../mediadata.h \ + ../mediasettings.h \ + ../preferences.h \ + ../myprocess.h \ + ../mplayerversion.h \ + ../mplayerprocess.h \ + ../infoprovider.h \ + ../desktopinfo.h \ + ../mplayerwindow.h \ + ../core.h \ + smplayercorelib.h + + +SOURCES += ../global.cpp \ + ../helper.cpp \ + ../subtracks.cpp \ + ../audiotracks.cpp \ + ../titletracks.cpp \ + ../mediadata.cpp \ + ../mediasettings.cpp \ + ../preferences.cpp \ + ../myprocess.cpp \ + ../mplayerversion.cpp \ + ../mplayerprocess.cpp \ + ../infoprovider.cpp \ + ../desktopinfo.cpp \ + ../mplayerwindow.cpp \ + ../core.cpp \ + smplayercorelib.cpp + + +unix { + UI_DIR = .ui + MOC_DIR = .moc + OBJECTS_DIR = .obj +} + +win32 { + HEADERS += ../screensaver.h + SOURCES += ../screensaver.cpp +} diff --git a/plugins/smplayer_plugin/corelib/smplayercorelib.cpp b/plugins/smplayer_plugin/corelib/smplayercorelib.cpp new file mode 100644 index 000000000..9d463eead --- /dev/null +++ b/plugins/smplayer_plugin/corelib/smplayercorelib.cpp @@ -0,0 +1,43 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "smplayercorelib.h" +#include "global.h" +#include "preferences.h" +#include "helper.h" +#include + +SmplayerCoreLib::SmplayerCoreLib( QWidget * parent ) + : QObject(parent) +{ + if (Global::pref == 0) { + qWarning("Global::global_init() hasn't been called. Crash comming."); + } + + _mpw = new MplayerWindow(parent); + _core = new Core(_mpw, parent); + + _mpw->setColorKey( Global::pref->color_key ); + + Global::pref->fast_audio_change = Preferences::Enabled; +} + +SmplayerCoreLib::~SmplayerCoreLib() { +}; + +#include "moc_smplayercorelib.cpp" diff --git a/plugins/smplayer_plugin/corelib/smplayercorelib.h b/plugins/smplayer_plugin/corelib/smplayercorelib.h new file mode 100644 index 000000000..18eb4b095 --- /dev/null +++ b/plugins/smplayer_plugin/corelib/smplayercorelib.h @@ -0,0 +1,43 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _SMPLAYERCORELIB_H_ +#define _SMPLAYERCORELIB_H_ + +#include +#include "core.h" +#include "mplayerwindow.h" + +class SmplayerCoreLib : public QObject +{ + Q_OBJECT + +public: + SmplayerCoreLib( QWidget * parent = 0 ); + ~SmplayerCoreLib(); + + Core * core() { return _core; }; + MplayerWindow * mplayerWindow() { return _mpw; }; + +private: + Core * _core; + MplayerWindow * _mpw; +}; + +#endif + diff --git a/plugins/smplayer_plugin/defaultgui.cpp b/plugins/smplayer_plugin/defaultgui.cpp new file mode 100644 index 000000000..349bc9d01 --- /dev/null +++ b/plugins/smplayer_plugin/defaultgui.cpp @@ -0,0 +1,685 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "defaultgui.h" +#include "helper.h" +#include "colorutils.h" +#include "core.h" +#include "global.h" +#include "widgetactions.h" +#include "playlist.h" +#include "mplayerwindow.h" +#include "myaction.h" +#include "images.h" +#include "floatingwidget.h" +#include "toolbareditor.h" +#include "desktopinfo.h" + +#if DOCK_PLAYLIST +#include "playlistdock.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Global; + +DefaultGui::DefaultGui( QWidget * parent, Qt::WindowFlags flags ) + : BaseGuiPlus( parent, flags ) +{ + createStatusBar(); + + connect( this, SIGNAL(timeChanged(QString)), + this, SLOT(displayTime(QString)) ); + connect( this, SIGNAL(frameChanged(int)), + this, SLOT(displayFrame(int)) ); + + connect( this, SIGNAL(cursorNearBottom(QPoint)), + this, SLOT(showFloatingControl(QPoint)) ); + connect( this, SIGNAL(cursorNearTop(QPoint)), + this, SLOT(showFloatingMenu(QPoint)) ); + connect( this, SIGNAL(cursorFarEdges()), + this, SLOT(hideFloatingControls()) ); + + createActions(); + createMainToolBars(); + createControlWidget(); + createControlWidgetMini(); + createFloatingControl(); + createMenus(); + + retranslateStrings(); + + loadConfig(); + + //if (playlist_visible) showPlaylist(true); + + if (pref->compact_mode) { + controlwidget->hide(); + toolbar1->hide(); + toolbar2->hide(); + } +} + +DefaultGui::~DefaultGui() { + saveConfig(); +} + +/* +void DefaultGui::closeEvent( QCloseEvent * ) { + qDebug("DefaultGui::closeEvent"); + + //BaseGuiPlus::closeEvent(e); + qDebug("w: %d h: %d", width(), height() ); +} +*/ + +void DefaultGui::createActions() { + qDebug("DefaultGui::createActions"); + + timeslider_action = createTimeSliderAction(this); + timeslider_action->disable(); + + volumeslider_action = createVolumeSliderAction(this); + volumeslider_action->disable(); + + // Create the time label + time_label_action = new TimeLabelAction(this); + time_label_action->setObjectName("timelabel_action"); + +#if MINI_ARROW_BUTTONS + QList rewind_actions; + rewind_actions << rewind1Act << rewind2Act << rewind3Act; + rewindbutton_action = new SeekingButton(rewind_actions, this); + rewindbutton_action->setObjectName("rewindbutton_action"); + + QList forward_actions; + forward_actions << forward1Act << forward2Act << forward3Act; + forwardbutton_action = new SeekingButton(forward_actions, this); + forwardbutton_action->setObjectName("forwardbutton_action"); +#endif +} + +#if AUTODISABLE_ACTIONS +void DefaultGui::enableActionsOnPlaying() { + qDebug("DefaultGui::enableActionsOnPlaying"); + BaseGuiPlus::enableActionsOnPlaying(); + + timeslider_action->enable(); + volumeslider_action->enable(); +} + +void DefaultGui::disableActionsOnStop() { + qDebug("DefaultGui::disableActionsOnStop"); + BaseGuiPlus::disableActionsOnStop(); + + timeslider_action->disable(); + volumeslider_action->disable(); +} +#endif // AUTODISABLE_ACTIONS + +void DefaultGui::createMenus() { + toolbar_menu = new QMenu(this); + toolbar_menu->addAction(toolbar1->toggleViewAction()); + toolbar_menu->addAction(toolbar2->toggleViewAction()); + optionsMenu->addSeparator(); + optionsMenu->addMenu(toolbar_menu); +} + +QMenu * DefaultGui::createPopupMenu() { + QMenu * m = new QMenu(this); + m->addAction(toolbar1->toggleViewAction()); + m->addAction(toolbar2->toggleViewAction()); + return m; +} + +void DefaultGui::createMainToolBars() { + toolbar1 = new QToolBar( this ); + toolbar1->setObjectName("toolbar1"); + //toolbar1->setMovable(false); + addToolBar(Qt::TopToolBarArea, toolbar1); +#if !USE_CONFIGURABLE_TOOLBARS + toolbar1->addAction(openFileAct); + toolbar1->addAction(openDVDAct); + toolbar1->addAction(openURLAct); + toolbar1->addSeparator(); + toolbar1->addAction(compactAct); + toolbar1->addAction(fullscreenAct); + toolbar1->addSeparator(); + toolbar1->addAction(screenshotAct); + toolbar1->addSeparator(); + toolbar1->addAction(showPropertiesAct); + toolbar1->addAction(showPlaylistAct); + toolbar1->addAction(showPreferencesAct); + toolbar1->addSeparator(); + toolbar1->addAction(playPrevAct); + toolbar1->addAction(playNextAct); + // Test: + //toolbar1->addSeparator(); + //toolbar1->addAction(timeslider_action); + //toolbar1->addAction(volumeslider_action); +#endif + + toolbar2 = new QToolBar( this ); + toolbar2->setObjectName("toolbar2"); + //toolbar2->setMovable(false); + addToolBar(Qt::TopToolBarArea, toolbar2); + + select_audio = new QPushButton( this ); + select_audio->setMenu( audiotrack_menu ); + toolbar2->addWidget(select_audio); + + select_subtitle = new QPushButton( this ); + select_subtitle->setMenu( subtitlestrack_menu ); + toolbar2->addWidget(select_subtitle); + + /* + toolbar1->show(); + toolbar2->show(); + */ + + // Modify toolbars' actions + QAction *tba; + tba = toolbar1->toggleViewAction(); + tba->setObjectName("show_main_toolbar"); + tba->setShortcut(Qt::Key_F5); + + tba = toolbar2->toggleViewAction(); + tba->setObjectName("show_language_toolbar"); + tba->setShortcut(Qt::Key_F6); +} + + +void DefaultGui::createControlWidgetMini() { + qDebug("DefaultGui::createControlWidgetMini"); + + controlwidget_mini = new QToolBar( this ); + controlwidget_mini->setObjectName("controlwidget_mini"); + //controlwidget_mini->setResizeEnabled(false); + controlwidget_mini->setMovable(false); + //addDockWindow(controlwidget_mini, Qt::DockBottom ); + addToolBar(Qt::BottomToolBarArea, controlwidget_mini); + +#if !USE_CONFIGURABLE_TOOLBARS + controlwidget_mini->addAction(playOrPauseAct); + controlwidget_mini->addAction(stopAct); + controlwidget_mini->addSeparator(); + + controlwidget_mini->addAction(rewind1Act); + + controlwidget_mini->addAction(timeslider_action); + + controlwidget_mini->addAction(forward1Act); + + controlwidget_mini->addSeparator(); + + controlwidget_mini->addAction(muteAct ); + + controlwidget_mini->addAction(volumeslider_action); +#endif // USE_CONFIGURABLE_TOOLBARS + + controlwidget_mini->hide(); +} + +void DefaultGui::createControlWidget() { + qDebug("DefaultGui::createControlWidget"); + + controlwidget = new QToolBar( this ); + controlwidget->setObjectName("controlwidget"); + //controlwidget->setResizeEnabled(false); + controlwidget->setMovable(false); + //addDockWindow(controlwidget, Qt::DockBottom ); + addToolBar(Qt::BottomToolBarArea, controlwidget); + +#if !USE_CONFIGURABLE_TOOLBARS + controlwidget->addAction(playAct); + controlwidget->addAction(pauseAndStepAct); + controlwidget->addAction(stopAct); + + controlwidget->addSeparator(); + +#if MINI_ARROW_BUTTONS + controlwidget->addAction( rewindbutton_action ); +#else + controlwidget->addAction(rewind3Act); + controlwidget->addAction(rewind2Act); + controlwidget->addAction(rewind1Act); +#endif + + controlwidget->addAction(timeslider_action); + +#if MINI_ARROW_BUTTONS + controlwidget->addAction( forwardbutton_action ); +#else + controlwidget->addAction(forward1Act); + controlwidget->addAction(forward2Act); + controlwidget->addAction(forward3Act); +#endif + + controlwidget->addSeparator(); + + controlwidget->addAction(fullscreenAct); + controlwidget->addAction(muteAct); + + controlwidget->addAction(volumeslider_action); +#endif // USE_CONFIGURABLE_TOOLBARS + + /* + controlwidget->show(); + */ +} + +void DefaultGui::createFloatingControl() { + // Floating control + floating_control = new FloatingWidget(this); + +#if !USE_CONFIGURABLE_TOOLBARS + floating_control->toolbar()->addAction(playAct); + floating_control->toolbar()->addAction(pauseAct); + floating_control->toolbar()->addAction(stopAct); + floating_control->toolbar()->addSeparator(); + +#if MINI_ARROW_BUTTONS + floating_control->toolbar()->addAction( rewindbutton_action ); +#else + floating_control->toolbar()->addAction(rewind3Act); + floating_control->toolbar()->addAction(rewind2Act); + floating_control->toolbar()->addAction(rewind1Act); +#endif + + floating_control->toolbar()->addAction(timeslider_action); + +#if MINI_ARROW_BUTTONS + floating_control->toolbar()->addAction( forwardbutton_action ); +#else + floating_control->toolbar()->addAction(forward1Act); + floating_control->toolbar()->addAction(forward2Act); + floating_control->toolbar()->addAction(forward3Act); +#endif + + floating_control->toolbar()->addSeparator(); + floating_control->toolbar()->addAction(fullscreenAct); + floating_control->toolbar()->addAction(muteAct); + floating_control->toolbar()->addAction(volumeslider_action); + floating_control->toolbar()->addSeparator(); + floating_control->toolbar()->addAction(time_label_action); + +#endif // USE_CONFIGURABLE_TOOLBARS + +#ifdef Q_OS_WIN + // To make work the ESC key (exit fullscreen) and Ctrl-X (close) in Windows + floating_control->addAction(exitFullscreenAct); + floating_control->addAction(exitAct); +#endif + +#if !USE_CONFIGURABLE_TOOLBARS + floating_control->adjustSize(); +#endif +} + +void DefaultGui::createStatusBar() { + qDebug("DefaultGui::createStatusBar"); + + time_display = new QLabel( statusBar() ); + time_display->setAlignment(Qt::AlignRight); + time_display->setFrameShape(QFrame::NoFrame); + time_display->setText(" 88:88:88 / 88:88:88 "); + time_display->setMinimumSize(time_display->sizeHint()); + + frame_display = new QLabel( statusBar() ); + frame_display->setAlignment(Qt::AlignRight); + frame_display->setFrameShape(QFrame::NoFrame); + frame_display->setText("88888888"); + frame_display->setMinimumSize(frame_display->sizeHint()); + + statusBar()->setAutoFillBackground(TRUE); + + ColorUtils::setBackgroundColor( statusBar(), QColor(0,0,0) ); + ColorUtils::setForegroundColor( statusBar(), QColor(255,255,255) ); + ColorUtils::setBackgroundColor( time_display, QColor(0,0,0) ); + ColorUtils::setForegroundColor( time_display, QColor(255,255,255) ); + ColorUtils::setBackgroundColor( frame_display, QColor(0,0,0) ); + ColorUtils::setForegroundColor( frame_display, QColor(255,255,255) ); + statusBar()->setSizeGripEnabled(FALSE); + + statusBar()->showMessage( tr("Welcome to SMPlayer") ); + statusBar()->addPermanentWidget( frame_display, 0 ); + frame_display->setText( "0" ); + + statusBar()->addPermanentWidget( time_display, 0 ); + time_display->setText(" 00:00:00 / 00:00:00 "); + + time_display->show(); + frame_display->hide(); +} + +void DefaultGui::retranslateStrings() { + BaseGuiPlus::retranslateStrings(); + + toolbar_menu->menuAction()->setText( tr("&Toolbars") ); + toolbar_menu->menuAction()->setIcon( Images::icon("toolbars") ); + + toolbar1->setWindowTitle( tr("&Main toolbar") ); + toolbar1->toggleViewAction()->setIcon(Images::icon("main_toolbar")); + + toolbar2->setWindowTitle( tr("&Language toolbar") ); + toolbar2->toggleViewAction()->setIcon(Images::icon("lang_toolbar")); + + select_audio->setText( tr("Audio") ); + select_subtitle->setText( tr("Subtitle") ); +} + + +void DefaultGui::displayTime(QString text) { + time_display->setText( text ); + time_label_action->setText(text); +} + +void DefaultGui::displayFrame(int frame) { + if (frame_display->isVisible()) { + frame_display->setNum( frame ); + } +} + +void DefaultGui::updateWidgets() { + qDebug("DefaultGui::updateWidgets"); + + BaseGuiPlus::updateWidgets(); + + // Frame counter + frame_display->setVisible( pref->show_frame_counter ); + + panel->setFocus(); +} + +void DefaultGui::aboutToEnterFullscreen() { + qDebug("DefaultGui::aboutToEnterFullscreen"); + + BaseGuiPlus::aboutToEnterFullscreen(); + + // Save visibility of toolbars + fullscreen_toolbar1_was_visible = toolbar1->isVisible(); + fullscreen_toolbar2_was_visible = toolbar2->isVisible(); + + if (!pref->compact_mode) { + //menuBar()->hide(); + //statusBar()->hide(); + controlwidget->hide(); + controlwidget_mini->hide(); + toolbar1->hide(); + toolbar2->hide(); + } +} + +void DefaultGui::aboutToExitFullscreen() { + qDebug("DefaultGui::aboutToExitFullscreen"); + + BaseGuiPlus::aboutToExitFullscreen(); + + floating_control->hide(); + + if (!pref->compact_mode) { + //menuBar()->show(); + //statusBar()->show(); + controlwidget->show(); + + toolbar1->setVisible( fullscreen_toolbar1_was_visible ); + toolbar2->setVisible( fullscreen_toolbar2_was_visible ); + } +} + +void DefaultGui::aboutToEnterCompactMode() { + + BaseGuiPlus::aboutToEnterCompactMode(); + + // Save visibility of toolbars + compact_toolbar1_was_visible = toolbar1->isVisible(); + compact_toolbar2_was_visible = toolbar2->isVisible(); + + //menuBar()->hide(); + //statusBar()->hide(); + controlwidget->hide(); + controlwidget_mini->hide(); + toolbar1->hide(); + toolbar2->hide(); +} + +void DefaultGui::aboutToExitCompactMode() { + BaseGuiPlus::aboutToExitCompactMode(); + + //menuBar()->show(); + //statusBar()->show(); + controlwidget->show(); + + toolbar1->setVisible( compact_toolbar1_was_visible ); + toolbar2->setVisible( compact_toolbar2_was_visible ); + + // Recheck size of controlwidget + resizeEvent( new QResizeEvent( size(), size() ) ); +} + +void DefaultGui::showFloatingControl(QPoint /*p*/) { + qDebug("DefaultGui::showFloatingControl"); + +#if CONTROLWIDGET_OVER_VIDEO + floating_control->setAnimated( pref->floating_control_animated ); + floating_control->setMargin(pref->floating_control_margin); +#ifndef Q_OS_WIN + floating_control->setBypassWindowManager(pref->bypass_window_manager); +#endif + floating_control->showOver(panel, pref->floating_control_width); +#else + if (!controlwidget->isVisible()) { + controlwidget->show(); + } +#endif +} + +void DefaultGui::showFloatingMenu(QPoint /*p*/) { +#if !CONTROLWIDGET_OVER_VIDEO + qDebug("DefaultGui::showFloatingMenu"); + + if (!menuBar()->isVisible()) + menuBar()->show(); +#endif +} + +void DefaultGui::hideFloatingControls() { + qDebug("DefaultGui::hideFloatingControls"); + +#if CONTROLWIDGET_OVER_VIDEO + floating_control->hide(); +#else + if (controlwidget->isVisible()) + controlwidget->hide(); + + if (menuBar()->isVisible()) + menuBar()->hide(); +#endif +} + +void DefaultGui::resizeEvent( QResizeEvent * ) { + /* + qDebug("defaultGui::resizeEvent"); + qDebug(" controlwidget width: %d", controlwidget->width() ); + qDebug(" controlwidget_mini width: %d", controlwidget_mini->width() ); + */ + +#if QT_VERSION < 0x040000 +#define LIMIT 470 +#else +#define LIMIT 570 +#endif + + if ( (controlwidget->isVisible()) && (width() < LIMIT) ) { + controlwidget->hide(); + controlwidget_mini->show(); + } + else + if ( (controlwidget_mini->isVisible()) && (width() > LIMIT) ) { + controlwidget_mini->hide(); + controlwidget->show(); + } +} + +#if USE_MINIMUMSIZE +QSize DefaultGui::minimumSizeHint() const { + return QSize(controlwidget_mini->sizeHint().width(), 0); +} +#endif + + +void DefaultGui::saveConfig() { + qDebug("DefaultGui::saveConfig"); + + QSettings * set = settings; + + set->beginGroup( "default_gui"); + + set->setValue("fullscreen_toolbar1_was_visible", fullscreen_toolbar1_was_visible); + set->setValue("fullscreen_toolbar2_was_visible", fullscreen_toolbar2_was_visible); + set->setValue("compact_toolbar1_was_visible", compact_toolbar1_was_visible); + set->setValue("compact_toolbar2_was_visible", compact_toolbar2_was_visible); + + if (pref->save_window_size_on_exit) { + qDebug("DefaultGui::saveConfig: w: %d h: %d", width(), height()); + set->setValue( "pos", pos() ); + set->setValue( "size", size() ); + } + + set->setValue( "toolbars_state", saveState(Helper::qtVersion()) ); + +#if USE_CONFIGURABLE_TOOLBARS + set->beginGroup( "actions" ); + set->setValue("toolbar1", ToolbarEditor::save(toolbar1) ); + set->setValue("controlwidget", ToolbarEditor::save(controlwidget) ); + set->setValue("controlwidget_mini", ToolbarEditor::save(controlwidget_mini) ); + set->setValue("floating_control", ToolbarEditor::save(floating_control->toolbar()) ); + set->endGroup(); +#endif + + set->endGroup(); +} + +void DefaultGui::loadConfig() { + qDebug("DefaultGui::loadConfig"); + + QSettings * set = settings; + + set->beginGroup( "default_gui"); + + fullscreen_toolbar1_was_visible = set->value("fullscreen_toolbar1_was_visible", fullscreen_toolbar1_was_visible).toBool(); + fullscreen_toolbar2_was_visible = set->value("fullscreen_toolbar2_was_visible", fullscreen_toolbar2_was_visible).toBool(); + compact_toolbar1_was_visible = set->value("compact_toolbar1_was_visible", compact_toolbar1_was_visible).toBool(); + compact_toolbar2_was_visible = set->value("compact_toolbar2_was_visible", compact_toolbar2_was_visible).toBool(); + + if (pref->save_window_size_on_exit) { + QPoint p = set->value("pos", pos()).toPoint(); + QSize s = set->value("size", size()).toSize(); + + if ( (s.height() < 200) && (!pref->use_mplayer_window) ) { + s = pref->default_size; + } + + move(p); + resize(s); + + if (!DesktopInfo::isInsideScreen(this)) { + move(0,0); + qWarning("DefaultGui::loadConfig: window is outside of the screen, moved to 0x0"); + } + } + +#if USE_CONFIGURABLE_TOOLBARS + QList actions_list = findChildren(); + QStringList toolbar1_actions; + toolbar1_actions << "open_file" << "open_dvd" << "open_url" << "separator" << "compact" << "fullscreen" + << "separator" << "screenshot" << "separator" << "show_file_properties" << "show_playlist" + << "show_preferences" << "separator" << "play_prev" << "play_next"; + + QStringList controlwidget_actions; + controlwidget_actions << "play" << "pause_and_frame_step" << "stop" << "separator"; + +#if MINI_ARROW_BUTTONS + controlwidget_actions << "rewindbutton_action"; +#else + controlwidget_actions << "rewind3" << "rewind2" << "rewind1"; +#endif + + controlwidget_actions << "timeslider_action"; + +#if MINI_ARROW_BUTTONS + controlwidget_actions << "forwardbutton_action"; +#else + controlwidget_actions << "forward1" << "forward2" << "forward3"; +#endif + + controlwidget_actions << "separator" << "fullscreen" << "mute" << "volumeslider_action"; + + QStringList controlwidget_mini_actions; + controlwidget_mini_actions << "play_or_pause" << "stop" << "separator" << "rewind1" << "timeslider_action" + << "forward1" << "separator" << "mute" << "volumeslider_action"; + + QStringList floatingcontrol_actions; + floatingcontrol_actions << "play" << "pause" << "stop" << "separator"; + +#if MINI_ARROW_BUTTONS + floatingcontrol_actions << "rewindbutton_action"; +#else + floatingcontrol_actions << "rewind3" << "rewind2" << "rewind1"; +#endif + + floatingcontrol_actions << "timeslider_action"; + +#if MINI_ARROW_BUTTONS + floatingcontrol_actions << "forwardbutton_action"; +#else + floatingcontrol_actions << "forward1" << "forward2" << "forward3"; +#endif + + floatingcontrol_actions << "separator" << "fullscreen" << "mute" << "volumeslider_action" << "separator" << "timelabel_action"; + + set->beginGroup( "actions" ); + ToolbarEditor::load(toolbar1, set->value("toolbar1", toolbar1_actions).toStringList(), actions_list ); + ToolbarEditor::load(controlwidget, set->value("controlwidget", controlwidget_actions).toStringList(), actions_list ); + ToolbarEditor::load(controlwidget_mini, set->value("controlwidget_mini", controlwidget_mini_actions).toStringList(), actions_list ); + ToolbarEditor::load(floating_control->toolbar(), set->value("floating_control", floatingcontrol_actions).toStringList(), actions_list ); + floating_control->adjustSize(); + set->endGroup(); +#endif + + restoreState( set->value( "toolbars_state" ).toByteArray(), Helper::qtVersion() ); + +#if DOCK_PLAYLIST + qDebug("DefaultGui::loadConfig: playlist visible: %d", playlistdock->isVisible()); + qDebug("DefaultGui::loadConfig: playlist position: %d, %d", playlistdock->pos().x(), playlistdock->pos().y()); + qDebug("DefaultGui::loadConfig: playlist size: %d x %d", playlistdock->size().width(), playlistdock->size().height()); +#endif + + set->endGroup(); + + updateWidgets(); +} + +#include "moc_defaultgui.cpp" diff --git a/plugins/smplayer_plugin/defaultgui.h b/plugins/smplayer_plugin/defaultgui.h new file mode 100644 index 000000000..9c7ca5861 --- /dev/null +++ b/plugins/smplayer_plugin/defaultgui.h @@ -0,0 +1,127 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _DEFAULTGUI_H_ +#define _DEFAULTGUI_H_ + +#include "guiconfig.h" +#include "baseguiplus.h" +#include + +class QToolBar; +class QPushButton; +class QResizeEvent; +class MyAction; +class QMenu; +class TimeSliderAction; +class VolumeSliderAction; +class FloatingWidget; +class TimeLabelAction; + +#if MINI_ARROW_BUTTONS +class SeekingButton; +#endif + +class DefaultGui : public BaseGuiPlus +{ + Q_OBJECT + +public: + DefaultGui( QWidget* parent = 0, Qt::WindowFlags flags = 0 ); + ~DefaultGui(); + +#if USE_MINIMUMSIZE + virtual QSize minimumSizeHint () const; +#endif + +public slots: + //virtual void showPlaylist(bool b); + +protected: + virtual void retranslateStrings(); + virtual QMenu * createPopupMenu(); + + void createStatusBar(); + void createMainToolBars(); + void createControlWidget(); + void createControlWidgetMini(); + void createFloatingControl(); + void createActions(); + void createMenus(); + + void loadConfig(); + void saveConfig(); + + virtual void aboutToEnterFullscreen(); + virtual void aboutToExitFullscreen(); + virtual void aboutToEnterCompactMode(); + virtual void aboutToExitCompactMode(); + + virtual void resizeEvent( QResizeEvent * ); + /* virtual void closeEvent( QCloseEvent * ); */ + +protected slots: + virtual void updateWidgets(); + virtual void displayTime(QString text); + virtual void displayFrame(int frame); + + virtual void showFloatingControl(QPoint p); + virtual void showFloatingMenu(QPoint p); + virtual void hideFloatingControls(); + + // Reimplemented: +#if AUTODISABLE_ACTIONS + virtual void enableActionsOnPlaying(); + virtual void disableActionsOnStop(); +#endif + +protected: + QLabel * time_display; + QLabel * frame_display; + + QToolBar * controlwidget; + QToolBar * controlwidget_mini; + + QToolBar * toolbar1; + QToolBar * toolbar2; + + QPushButton * select_audio; + QPushButton * select_subtitle; + + TimeSliderAction * timeslider_action; + VolumeSliderAction * volumeslider_action; + +#if MINI_ARROW_BUTTONS + SeekingButton * rewindbutton_action; + SeekingButton * forwardbutton_action; +#endif + + FloatingWidget * floating_control; + TimeLabelAction * time_label_action; + + QMenu * toolbar_menu; + + int last_second; + + bool fullscreen_toolbar1_was_visible; + bool fullscreen_toolbar2_was_visible; + bool compact_toolbar1_was_visible; + bool compact_toolbar2_was_visible; +}; + +#endif diff --git a/plugins/smplayer_plugin/desktopinfo.cpp b/plugins/smplayer_plugin/desktopinfo.cpp new file mode 100644 index 000000000..4b2353fad --- /dev/null +++ b/plugins/smplayer_plugin/desktopinfo.cpp @@ -0,0 +1,49 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "desktopinfo.h" +#include +#include + +QSize DesktopInfo::desktop_size(QWidget *w) { + QDesktopWidget * dw = QApplication::desktop(); + qDebug("DesktopInfo::desktop_size: primary screen: %d", dw->primaryScreen()); + + QSize s = dw->screen( dw->primaryScreen() )->size(); + + qDebug("DesktopInfo::desktop_size: size of primary screen: %d x %d", s.width(), s.height() ); + //return dw->screen( dw->primaryScreen() )->size(); + + QRect r = dw->screenGeometry(w); + qDebug("DesktopInfo::desktop_size: size of screen: %d x %d", r.width(), r.height() ); + + return QSize(r.width(), r.height() ); +} + +double DesktopInfo::desktop_aspectRatio(QWidget *w) { + QSize s = DesktopInfo::desktop_size(w); + return (double) s.width() / s.height() ; +} + +bool DesktopInfo::isInsideScreen(QWidget *w) { + QDesktopWidget * dw = QApplication::desktop(); + QRect r = dw->screenGeometry(w); + + qDebug("DesktopInfo::isInsideScreen: geometry of screen: x:%d y:%d w:%d h:%d", r.x(), r.y(), r.width(), r.height() ); + return r.contains(w->pos()); +} diff --git a/plugins/smplayer_plugin/desktopinfo.h b/plugins/smplayer_plugin/desktopinfo.h new file mode 100644 index 000000000..357320f9d --- /dev/null +++ b/plugins/smplayer_plugin/desktopinfo.h @@ -0,0 +1,37 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _DESKTOPINFO_H_ +#define _DESKTOPINFO_H_ + +#include + +class QWidget; + +class DesktopInfo +{ +public: + static QSize desktop_size(QWidget *w); + static double desktop_aspectRatio(QWidget *w); + + //! Returns true if the widget is inside the current screen + static bool isInsideScreen(QWidget *w); +}; + +#endif diff --git a/plugins/smplayer_plugin/deviceinfo.cpp b/plugins/smplayer_plugin/deviceinfo.cpp new file mode 100644 index 000000000..95159d944 --- /dev/null +++ b/plugins/smplayer_plugin/deviceinfo.cpp @@ -0,0 +1,128 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "deviceinfo.h" +#include +#include + +#ifdef Q_OS_WIN + +DeviceList DeviceInfo::retrieveDevices(DeviceType type) { + qDebug("DeviceInfo::retrieveDevices: %d", type); + + DeviceList l; + QRegExp rx_device("^(\\d+): (.*)"); + + if (QFile::exists("dxlist.exe")) { + QProcess p; + p.setProcessChannelMode( QProcess::MergedChannels ); + QStringList arg; + if (type == Sound) arg << "-s"; else arg << "-d"; + p.start("dxlist", arg); + + if (p.waitForFinished()) { + QByteArray line; + while (p.canReadLine()) { + line = p.readLine().trimmed(); + qDebug("DeviceInfo::retrieveDevices: '%s'", line.constData()); + if ( rx_device.indexIn(line) > -1 ) { + int id = rx_device.cap(1).toInt(); + QString desc = rx_device.cap(2); + qDebug("DeviceInfo::retrieveDevices: found device: '%d' '%s'", id, desc.toUtf8().constData()); + l.append( DeviceData(id, desc) ); + } + } + } + } + + return l; +} + +DeviceList DeviceInfo::dsoundDevices() { + return retrieveDevices(Sound); +} + +DeviceList DeviceInfo::displayDevices() { + return retrieveDevices(Display); +} + +#else + +DeviceList DeviceInfo::alsaDevices() { + qDebug("DeviceInfo::alsaDevices"); + + DeviceList l; + QRegExp rx_device("^card\\s([0-9]+).*\\[(.*)\\],\\sdevice\\s([0-9]+):"); + + QProcess p; + p.setProcessChannelMode( QProcess::MergedChannels ); + p.setEnvironment( QStringList() << "LC_ALL=C" ); + p.start("aplay", QStringList() << "-l"); + + if (p.waitForFinished()) { + QByteArray line; + while (p.canReadLine()) { + line = p.readLine(); + qDebug("DeviceInfo::alsaDevices: '%s'", line.constData()); + if ( rx_device.indexIn(line) > -1 ) { + QString id = rx_device.cap(1); + id.append("."); + id.append(rx_device.cap(3)); + QString desc = rx_device.cap(2); + qDebug("DeviceInfo::alsaDevices: found device: '%s' '%s'", id.toUtf8().constData(), desc.toUtf8().constData()); + l.append( DeviceData(id, desc) ); + } + } + } else { + qDebug("DeviceInfo::alsaDevices: could not start aplay, error %d", p.error()); + } + + return l; +} + +DeviceList DeviceInfo::xvAdaptors() { + qDebug("DeviceInfo::xvAdaptors"); + + DeviceList l; + QRegExp rx_device("^.*Adaptor #([0-9]+): \"(.*)\""); + + QProcess p; + p.setProcessChannelMode( QProcess::MergedChannels ); + p.setEnvironment( QProcess::systemEnvironment() << "LC_ALL=C" ); + p.start("xvinfo"); + + if (p.waitForFinished()) { + QByteArray line; + while (p.canReadLine()) { + line = p.readLine(); + qDebug("DeviceInfo::xvAdaptors: '%s'", line.constData()); + if ( rx_device.indexIn(line) > -1 ) { + QString id = rx_device.cap(1); + QString desc = rx_device.cap(2); + qDebug("DeviceInfo::xvAdaptors: found adaptor: '%s' '%s'", id.toUtf8().constData(), desc.toUtf8().constData()); + l.append( DeviceData(id, desc) ); + } + } + } else { + qDebug("DeviceInfo::xvAdaptors: could not start xvinfo, error %d", p.error()); + } + + return l; +} + +#endif diff --git a/plugins/smplayer_plugin/deviceinfo.h b/plugins/smplayer_plugin/deviceinfo.h new file mode 100644 index 000000000..c5842d2a6 --- /dev/null +++ b/plugins/smplayer_plugin/deviceinfo.h @@ -0,0 +1,68 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _DEVICEINFO_H_ +#define _DEVICEINFO_H_ + +#include +#include +#include + +class DeviceData { + +public: + DeviceData() {}; + DeviceData(QVariant ID, QString desc) { _id = ID; _desc = desc; }; + ~DeviceData() {}; + + void setID(QVariant ID) { _id = ID; }; + void setDesc(QString desc) { _desc = desc; }; + + QVariant ID() { return _id; }; + QString desc() { return _desc; }; + +private: + QVariant _id; + QString _desc; +}; + + +typedef QList DeviceList; + + +class DeviceInfo { + +public: +#ifdef Q_OS_WIN + static DeviceList dsoundDevices(); + static DeviceList displayDevices(); +#else + static DeviceList alsaDevices(); + static DeviceList xvAdaptors(); +#endif + +protected: +#ifdef Q_OS_WIN + enum DeviceType { Sound = 0, Display = 1 }; + + static DeviceList retrieveDevices(DeviceType type); +#endif +}; + +#endif + diff --git a/plugins/smplayer_plugin/eqslider.cpp b/plugins/smplayer_plugin/eqslider.cpp new file mode 100644 index 000000000..899817918 --- /dev/null +++ b/plugins/smplayer_plugin/eqslider.cpp @@ -0,0 +1,79 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "eqslider.h" +#include +#include +#include +#include "verticaltext.h" + + +EqSlider::EqSlider( QWidget* parent, Qt::WindowFlags f) + : QWidget(parent, f) +{ + setupUi(this); + + _icon->setText( QString::null ); + _slider->setFocusPolicy( Qt::StrongFocus ); + _slider->setTickPosition( QSlider::TicksRight ); + _slider->setTickInterval( 10 ); + _slider->setSingleStep( 1 ); + _slider->setPageStep( 10 ); + + connect( _slider, SIGNAL(valueChanged(int)), + this, SLOT(sliderValueChanged(int)) ); +} + +EqSlider::~EqSlider() { +} + +/* +void EqSlider::languageChange() { +} +*/ + +void EqSlider::setIcon( QPixmap i) { + _icon->setPixmap(i); +} + +const QPixmap * EqSlider::icon() const { + return _icon->pixmap(); +} + +void EqSlider::setLabel( QString s) { + _label->setText(s); +} + +QString EqSlider::label() const { + return _label->text(); +} + +void EqSlider::setValue(int value) { + _slider->setValue(value); + value_label->setNum(value); +} + +int EqSlider::value() const { + return _slider->value(); +} + +void EqSlider::sliderValueChanged(int v) { + emit valueChanged( v ); +} + +#include "moc_eqslider.cpp" diff --git a/plugins/smplayer_plugin/eqslider.h b/plugins/smplayer_plugin/eqslider.h new file mode 100644 index 000000000..0b1b93361 --- /dev/null +++ b/plugins/smplayer_plugin/eqslider.h @@ -0,0 +1,62 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _EQSLIDER_H_ +#define _EQSLIDER_H_ + +#include "ui_eqslider.h" +#include + +class EqSlider : public QWidget, public Ui::EqSlider +{ + Q_OBJECT + Q_PROPERTY(QPixmap icon READ icon WRITE setIcon) + Q_PROPERTY(QString label READ label WRITE setLabel) + Q_PROPERTY(int value READ value WRITE setValue) + +public: + EqSlider( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~EqSlider(); + +public slots: + void setIcon( QPixmap i); + void setLabel( QString s); + void setValue(int value); + +public: + int value() const; + const QPixmap * icon() const; + QString label() const; + + QSlider * sliderWidget() { return _slider; }; + VerticalText * labelWidget() { return _label; }; + QLabel * iconWidget() { return _icon; }; + +signals: + void valueChanged(int); + +protected slots: + void sliderValueChanged(int); + +protected: + /* virtual void languageChange(); */ + +}; + +#endif diff --git a/plugins/smplayer_plugin/eqslider.ui b/plugins/smplayer_plugin/eqslider.ui new file mode 100644 index 000000000..54741bf6a --- /dev/null +++ b/plugins/smplayer_plugin/eqslider.ui @@ -0,0 +1,123 @@ + + EqSlider + + + + 0 + 0 + 68 + 289 + + + + + 0 + + + 0 + + + + + icon + + + Qt::AlignCenter + + + false + + + + + + + 0 + + + 6 + + + + + + 1 + 1 + 0 + 0 + + + + + + + + -100 + + + 100 + + + Qt::Vertical + + + + + + + + + + 1 + 5 + 0 + 0 + + + + QFrame::Box + + + QFrame::Sunken + + + + + + Qt::AlignCenter + + + + + + + + + VerticalText + QWidget +
    verticaltext.h
    +
    +
    + + verticaltext.h + + + + + _slider + valueChanged(int) + value_label + setNum(int) + + + 64 + 156 + + + 36 + 305 + + + + +
    diff --git a/plugins/smplayer_plugin/errordialog.cpp b/plugins/smplayer_plugin/errordialog.cpp new file mode 100644 index 000000000..aa673e141 --- /dev/null +++ b/plugins/smplayer_plugin/errordialog.cpp @@ -0,0 +1,60 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "errordialog.h" +#include "images.h" + +ErrorDialog::ErrorDialog( QWidget* parent, Qt::WindowFlags f ) + : QDialog(parent, f) +{ + setupUi(this); + + icon->setText(""); + icon->setPixmap( Images::icon("warning") ); + + text->setText(""); + toggleLog(false); + + connect( viewlog_button, SIGNAL(toggled(bool)), + this, SLOT(toggleLog(bool)) ); + + layout()->setSizeConstraint(QLayout::SetFixedSize); +} + +ErrorDialog::~ErrorDialog() { +} + +void ErrorDialog::setText(QString error) { + text->setText(error); +} + +void ErrorDialog::setLog(QString log_text) { + log->setPlainText(""); + log->append(log_text); // To move cursor to the end +} + +void ErrorDialog::toggleLog(bool checked) { + log->setVisible(checked); + + if (checked) + viewlog_button->setText(tr("Hide log")); + else + viewlog_button->setText(tr("Show log")); +} + +#include "moc_errordialog.cpp" diff --git a/plugins/smplayer_plugin/errordialog.h b/plugins/smplayer_plugin/errordialog.h new file mode 100644 index 000000000..01f6a767a --- /dev/null +++ b/plugins/smplayer_plugin/errordialog.h @@ -0,0 +1,40 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _ERRORDIALOG_H_ +#define _ERRORDIALOG_H_ + +#include "ui_errordialog.h" + +class ErrorDialog : public QDialog, public Ui::ErrorDialog +{ + Q_OBJECT + +public: + ErrorDialog( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~ErrorDialog(); + +public slots: + void setText(QString error); + void setLog(QString log_text); + +protected slots: + void toggleLog(bool); +}; + +#endif diff --git a/plugins/smplayer_plugin/errordialog.ui b/plugins/smplayer_plugin/errordialog.ui new file mode 100644 index 000000000..940c73d5d --- /dev/null +++ b/plugins/smplayer_plugin/errordialog.ui @@ -0,0 +1,163 @@ + + ErrorDialog + + + + 0 + 0 + 435 + 338 + + + + MPlayer Error + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + 0 + + + 6 + + + + + icon + + + Qt::AlignCenter + + + + + + + + + + 7 + 5 + 0 + 0 + + + + + 400 + 0 + + + + Error + + + true + + + + + + + + + 0 + + + 6 + + + + + Show log + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + true + + + + + + + + + button_box + accepted() + ErrorDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + button_box + rejected() + ErrorDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/smplayer_plugin/extensions.cpp b/plugins/smplayer_plugin/extensions.cpp new file mode 100644 index 000000000..bfeab1d24 --- /dev/null +++ b/plugins/smplayer_plugin/extensions.cpp @@ -0,0 +1,73 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "extensions.h" + +ExtensionList::ExtensionList() : QStringList() +{ +} + +QString ExtensionList::forFilter() { + QString s; + for (int n=0; n < count(); n++) { + s = s + "*." + at(n) + " "; + } + if (!s.isEmpty()) s = " (" + s + ")"; + return s; +} + +QString ExtensionList::forRegExp() { + QString s; + for (int n=0; n < count(); n++) { + if (!s.isEmpty()) s = s + "|"; + s = s + "^" + at(n) + "$"; + } + return s; +} + +Extensions::Extensions() +{ + _video << "avi" << "vfw" << "divx" + << "mpg" << "mpeg" << "m1v" << "m2v" << "mpv" << "dv" << "3gp" + << "mov" << "mp4" << "m4v" << "mqv" + << "dat" << "vcd" + << "ogg" << "ogm" + << "asf" << "wmv" + << "bin" << "iso" << "vob" + << "mkv" << "nsv" << "ram" << "flv" + << "rm" << "swf" + << "ts" << "rmvb" << "dvr-ms" << "m2t" << "m2ts" << "rec"; + + _audio << "mp3" << "ogg" << "wav" << "wma" << "ac3" << "ra" << "ape" << "flac"; + + _subtitles << "srt" << "sub" << "ssa" << "ass" << "idx" << "txt" << "smi" + << "rt" << "utf" << "aqt"; + + _playlist << "m3u" << "m3u8" << "pls"; + + _multimedia = _video; + for (int n = 0; n < _audio.count(); n++) { + if (!_multimedia.contains(_audio[n])) _multimedia << _audio[n]; + } + + _all_playable << _multimedia << _playlist; +} + +Extensions::~Extensions() { +} + diff --git a/plugins/smplayer_plugin/extensions.h b/plugins/smplayer_plugin/extensions.h new file mode 100644 index 000000000..270739f08 --- /dev/null +++ b/plugins/smplayer_plugin/extensions.h @@ -0,0 +1,52 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _EXTENSIONS_H_ +#define _EXTENSIONS_H_ + +#include + +class ExtensionList : public QStringList +{ +public: + ExtensionList(); + + QString forFilter(); + QString forRegExp(); +}; + +class Extensions +{ +public: + Extensions(); + ~Extensions(); + + ExtensionList video() { return _video; }; + ExtensionList audio() { return _audio; }; + ExtensionList playlist() { return _playlist; }; + ExtensionList subtitles() { return _subtitles; }; + ExtensionList multimedia() { return _multimedia; }; + ExtensionList allPlayable() { return _all_playable; }; + +protected: + ExtensionList _video, _audio, _playlist, _subtitles; + ExtensionList _multimedia; //!< video and audio + ExtensionList _all_playable; //!< video, audio and playlist +}; + +#endif diff --git a/plugins/smplayer_plugin/filechooser.cpp b/plugins/smplayer_plugin/filechooser.cpp new file mode 100644 index 000000000..32f14f2ab --- /dev/null +++ b/plugins/smplayer_plugin/filechooser.cpp @@ -0,0 +1,102 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "filechooser.h" + +//#define NO_SMPLAYER_SUPPORT + +#ifndef NO_SMPLAYER_SUPPORT +#include "filedialog.h" +#include "images.h" +#else +#include +#endif + +FileChooser::FileChooser(QWidget * parent) : QWidget(parent) +{ + setupUi(this); + +#ifndef NO_SMPLAYER_SUPPORT + button->setIcon(Images::icon("find")); +#else + button->setIcon(QIcon(":/find")); +#endif + + setDialogType(GetFileName); + setOptions(0); +} + +FileChooser::~FileChooser() { +} + +QLineEdit * FileChooser::lineEdit() { + return line_edit; +} + +QToolButton * FileChooser::toolButton() { + return button; +} + +QString FileChooser::text() const { + return line_edit->text(); +} + +void FileChooser::setText(const QString & text) { + line_edit->setText(text); +} + +void FileChooser::on_button_clicked() { + QString result; + QString f; + + if (dialogType() == GetFileName) { + QFileDialog::Options opts = options(); + if (opts == 0) opts = QFileDialog::DontResolveSymlinks; + +#ifndef NO_SMPLAYER_SUPPORT + result = MyFileDialog::getOpenFileName( +#else + result = QFileDialog::getOpenFileName( +#endif + this, caption(), + line_edit->text(), + filter(), &f, opts ); + } + else + if (dialogType() == GetDirectory) { + QFileDialog::Options opts = options(); + if (opts == 0) opts = QFileDialog::ShowDirsOnly; + +#ifndef NO_SMPLAYER_SUPPORT + result = MyFileDialog::getExistingDirectory( +#else + result = QFileDialog::getExistingDirectory( +#endif + this, caption(), + line_edit->text(), opts ); + } + + if (!result.isEmpty()) { + QString old_file = line_edit->text(); + line_edit->setText(result); + if (old_file != result) emit fileChanged(result); + } +} + +#include "moc_filechooser.cpp" + diff --git a/plugins/smplayer_plugin/filechooser.h b/plugins/smplayer_plugin/filechooser.h new file mode 100644 index 000000000..fd897da23 --- /dev/null +++ b/plugins/smplayer_plugin/filechooser.h @@ -0,0 +1,69 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _FILECHOOSER_H_ +#define _FILECHOOSER_H_ + +#include "ui_filechooser.h" +#include + +class FileChooser : public QWidget, public Ui::FileChooser +{ + Q_OBJECT + Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(QString caption READ caption WRITE setCaption) + Q_PROPERTY(QString filter READ filter WRITE setFilter) + Q_PROPERTY(DialogType dialogType READ dialogType WRITE setDialogType) + Q_PROPERTY(QFileDialog::Options options READ options WRITE setOptions) + +public: + enum DialogType { GetFileName = 0, GetDirectory = 1 }; + + FileChooser( QWidget* parent = 0 ); + ~FileChooser(); + + QLineEdit * lineEdit(); + QToolButton * toolButton(); + + QString text() const; + QString caption() const { return _caption; }; + QString filter() const { return _filter; }; + DialogType dialogType() const { return _type; }; + QFileDialog::Options options() const { return _options; }; + +public slots: + void setText(const QString & text); + void setCaption(const QString & caption) { _caption = caption; }; + void setFilter(const QString & filter) { _filter = filter; }; + void setDialogType( DialogType type) { _type = type; }; + void setOptions( QFileDialog::Options options) { _options = options; }; + +signals: + void fileChanged(QString file); + +protected slots: + virtual void on_button_clicked(); + +protected: + QString _caption; + QString _filter; + DialogType _type; + QFileDialog::Options _options; +}; + +#endif diff --git a/plugins/smplayer_plugin/filechooser.ui b/plugins/smplayer_plugin/filechooser.ui new file mode 100644 index 000000000..896dc759c --- /dev/null +++ b/plugins/smplayer_plugin/filechooser.ui @@ -0,0 +1,29 @@ + + FileChooser + + + + 0 + 0 + 407 + 27 + + + + + 2 + + + 2 + + + + + + + + + + + + diff --git a/plugins/smplayer_plugin/filedialog.cpp b/plugins/smplayer_plugin/filedialog.cpp new file mode 100644 index 000000000..b9d09c163 --- /dev/null +++ b/plugins/smplayer_plugin/filedialog.cpp @@ -0,0 +1,60 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "filedialog.h" +#include + +QString MyFileDialog::getOpenFileName( QWidget * parent, + const QString & caption, + const QString & dir, const QString & filter, + QString * selectedFilter, QFileDialog::Options options ) +{ + return QFileDialog::getOpenFileName( parent, caption, dir, filter, + selectedFilter, options ); +} + +QString MyFileDialog::getExistingDirectory ( QWidget * parent, + const QString & caption, + const QString & dir, + QFileDialog::Options options ) +{ + return QFileDialog::getExistingDirectory( parent, caption, dir, options ); +} + +QString MyFileDialog::getSaveFileName ( QWidget * parent, + const QString & caption, + const QString & dir, + const QString & filter, + QString * selectedFilter, + QFileDialog::Options options ) +{ + return QFileDialog::getSaveFileName( parent, caption, dir, filter, + selectedFilter, options ); +} + +QStringList MyFileDialog::getOpenFileNames ( QWidget * parent, + const QString & caption, + const QString & dir, + const QString & filter, + QString * selectedFilter, + QFileDialog::Options options ) +{ + return QFileDialog::getOpenFileNames( parent, caption, dir, filter, + selectedFilter, options ); +} + diff --git a/plugins/smplayer_plugin/filedialog.h b/plugins/smplayer_plugin/filedialog.h new file mode 100644 index 000000000..a70d4ced8 --- /dev/null +++ b/plugins/smplayer_plugin/filedialog.h @@ -0,0 +1,61 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _FILEDIALOG_H +#define _FILEDIALOG_H + +#include +#include +#include + +class QWidget; + +class MyFileDialog { + +public: + static QString getOpenFileName( QWidget * parent = 0, + const QString & caption = QString(), + const QString & dir = QString(), + const QString & filter = QString(), + QString * selectedFilter = 0, + QFileDialog::Options options = QFileDialog::DontResolveSymlinks ) ; + + static QString getExistingDirectory ( QWidget * parent = 0, + const QString & caption = QString(), + const QString & dir = QString(), + QFileDialog::Options options = QFileDialog::ShowDirsOnly ); + + static QString getSaveFileName ( QWidget * parent = 0, + const QString & caption = QString(), + const QString & dir = QString(), + const QString & filter = QString(), + QString * selectedFilter = 0, + QFileDialog::Options options = QFileDialog::DontResolveSymlinks | + QFileDialog::DontConfirmOverwrite ); + + static QStringList getOpenFileNames ( QWidget * parent = 0, + const QString & caption = QString(), + const QString & dir = QString(), + const QString & filter = QString(), + QString * selectedFilter = 0, + QFileDialog::Options options = QFileDialog::DontResolveSymlinks ); + +}; + +#endif + diff --git a/plugins/smplayer_plugin/filepropertiesdialog.cpp b/plugins/smplayer_plugin/filepropertiesdialog.cpp new file mode 100644 index 000000000..2c7656648 --- /dev/null +++ b/plugins/smplayer_plugin/filepropertiesdialog.cpp @@ -0,0 +1,225 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "filepropertiesdialog.h" +#include +#include +#include +#include +#include "images.h" +#include "infofile.h" + + +FilePropertiesDialog::FilePropertiesDialog( QWidget* parent, Qt::WindowFlags f ) + : QDialog(parent, f) +{ + setupUi(this); + + // Setup buttons + okButton = buttonBox->button(QDialogButtonBox::Ok); + cancelButton = buttonBox->button(QDialogButtonBox::Cancel); + applyButton = buttonBox->button(QDialogButtonBox::Apply); + connect( applyButton, SIGNAL(clicked()), this, SLOT(apply()) ); + + codecs_set = FALSE; + + // Read codec info from InfoReader: + InfoReader *i = InfoReader::obj(); + setCodecs( i->vcList(), i->acList(), i->demuxerList() ); + + retranslateStrings(); +} + +FilePropertiesDialog::~FilePropertiesDialog() { +} + +void FilePropertiesDialog::setMediaData(MediaData md) { + media_data = md; + showInfo(); +} + +void FilePropertiesDialog::showInfo() { + InfoFile info; + info_edit->setText( info.getInfo(media_data) ); +} + +void FilePropertiesDialog::retranslateStrings() { + retranslateUi(this); + + setWindowIcon( Images::icon("logo") ); + + showInfo(); + + // Qt 4.2 doesn't update the buttons' text +#if QT_VERSION < 0x040300 + okButton->setText( tr("OK") ); + cancelButton->setText( tr("Cancel") ); + applyButton->setText( tr("Apply") ); +#endif + +} + +void FilePropertiesDialog::accept() { + qDebug("FilePropertiesDialog::accept"); + + hide(); + setResult( QDialog::Accepted ); + emit applied(); +} + +void FilePropertiesDialog::apply() { + qDebug("FilePropertiesDialog::apply"); + + setResult( QDialog::Accepted ); + emit applied(); +} + +void FilePropertiesDialog::setCodecs(InfoList vc, InfoList ac, InfoList demuxer) +{ + vclist = vc; + aclist = ac; + demuxerlist = demuxer; + + InfoList::iterator it; + + for ( it = vclist.begin(); it != vclist.end(); ++it ) { + vc_listbox->addItem( (*it).name() +" - "+ (*it).desc() ); + } + + for ( it = aclist.begin(); it != aclist.end(); ++it ) { + ac_listbox->addItem( (*it).name() +" - "+ (*it).desc() ); + } + + for ( it = demuxerlist.begin(); it != demuxerlist.end(); ++it ) { + demuxer_listbox->addItem( (*it).name() +" - "+ (*it).desc() ); + } + + codecs_set = TRUE; +} + +void FilePropertiesDialog::setDemuxer(QString demuxer, QString original_demuxer) { + qDebug("FilePropertiesDialog::setDemuxer"); + if (!original_demuxer.isEmpty()) orig_demuxer = original_demuxer; + int pos = find(demuxer, demuxerlist ); + if (pos != -1) demuxer_listbox->setCurrentRow(pos); + + qDebug(" * demuxer: '%s', pos: %d", demuxer.toUtf8().data(), pos ); +} + +QString FilePropertiesDialog::demuxer() { + int pos = demuxer_listbox->currentRow(); + if ( pos < 0 ) + return ""; + else + return demuxerlist[pos].name(); +} + +void FilePropertiesDialog::setVideoCodec(QString vc, QString original_vc) { + qDebug("FilePropertiesDialog::setVideoCodec"); + if (!original_vc.isEmpty()) orig_vc = original_vc; + int pos = find(vc, vclist ); + if (pos != -1) vc_listbox->setCurrentRow(pos); + + qDebug(" * vc: '%s', pos: %d", vc.toUtf8().data(), pos ); +} + +QString FilePropertiesDialog::videoCodec() { + int pos = vc_listbox->currentRow(); + if ( pos < 0 ) + return ""; + else + return vclist[pos].name(); +} + +void FilePropertiesDialog::setAudioCodec(QString ac, QString original_ac) { + qDebug("FilePropertiesDialog::setAudioCodec"); + if (!original_ac.isEmpty()) orig_ac = original_ac; + int pos = find(ac, aclist ); + if (pos != -1) ac_listbox->setCurrentRow(pos); + + qDebug(" * ac: '%s', pos: %d", ac.toUtf8().data(), pos ); +} + +QString FilePropertiesDialog::audioCodec() { + int pos = ac_listbox->currentRow(); + if ( pos < 0 ) + return ""; + else + return aclist[pos].name(); +} + +void FilePropertiesDialog::on_resetDemuxerButton_clicked() { + setDemuxer( orig_demuxer ); +} + +void FilePropertiesDialog::on_resetACButton_clicked() { + setAudioCodec( orig_ac ); +} + +void FilePropertiesDialog::on_resetVCButton_clicked() { + setVideoCodec( orig_vc ); +} + +int FilePropertiesDialog::find(QString s, InfoList &list) { + qDebug("FilePropertiesDialog::find"); + + int n=0; + InfoList::iterator it; + + for ( it = list.begin(); it != list.end(); ++it ) { + //qDebug(" * item: '%s', s: '%s'", (*it).name().toUtf8().data(), s.toUtf8().data()); + if ((*it).name() == s) return n; + n++; + } + return -1; +} + +void FilePropertiesDialog::setMplayerAdditionalArguments(QString args) { + mplayer_args_edit->setText(args); +} + +QString FilePropertiesDialog::mplayerAdditionalArguments() { + return mplayer_args_edit->text(); +} + +void FilePropertiesDialog::setMplayerAdditionalVideoFilters(QString s) { + mplayer_vfilters_edit->setText(s); +} + +QString FilePropertiesDialog::mplayerAdditionalVideoFilters() { + return mplayer_vfilters_edit->text(); +} + +void FilePropertiesDialog::setMplayerAdditionalAudioFilters(QString s) { + mplayer_afilters_edit->setText(s); +} + +QString FilePropertiesDialog::mplayerAdditionalAudioFilters() { + return mplayer_afilters_edit->text(); +} + +// Language change stuff +void FilePropertiesDialog::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QDialog::changeEvent(e); + } +} + +#include "moc_filepropertiesdialog.cpp" diff --git a/plugins/smplayer_plugin/filepropertiesdialog.h b/plugins/smplayer_plugin/filepropertiesdialog.h new file mode 100644 index 000000000..d77963d00 --- /dev/null +++ b/plugins/smplayer_plugin/filepropertiesdialog.h @@ -0,0 +1,91 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _FILEPROPERTIESDIALOG_H_ +#define _FILEPROPERTIESDIALOG_H_ + +#include "ui_filepropertiesdialog.h" +#include "inforeader.h" +#include "mediadata.h" + +class QPushButton; + +class FilePropertiesDialog : public QDialog, public Ui::FilePropertiesDialog +{ + Q_OBJECT + +public: + FilePropertiesDialog( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~FilePropertiesDialog(); + + void setMediaData(MediaData md); + + void setDemuxer(QString demuxer, QString original_demuxer=""); + QString demuxer(); + + void setVideoCodec(QString vc, QString original_vc=""); + QString videoCodec(); + + void setAudioCodec(QString ac, QString original_ac=""); + QString audioCodec(); + + void setMplayerAdditionalArguments(QString args); + QString mplayerAdditionalArguments(); + + void setMplayerAdditionalVideoFilters(QString s); + QString mplayerAdditionalVideoFilters(); + + void setMplayerAdditionalAudioFilters(QString s); + QString mplayerAdditionalAudioFilters(); + +public slots: + void accept(); // Reimplemented to send a signal + void apply(); + +signals: + void applied(); + +protected slots: + virtual void on_resetDemuxerButton_clicked(); + virtual void on_resetACButton_clicked(); + virtual void on_resetVCButton_clicked(); + +protected: + // Call it as soon as possible + void setCodecs(InfoList vc, InfoList ac, InfoList demuxer); + bool hasCodecsList() { return codecs_set; }; + + int find(QString s, InfoList &list); + void showInfo(); + +protected: + virtual void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + +private: + bool codecs_set; + InfoList vclist, aclist, demuxerlist; + QString orig_demuxer, orig_ac, orig_vc; + MediaData media_data; + + QPushButton * okButton; + QPushButton * cancelButton; + QPushButton * applyButton; +}; + +#endif diff --git a/plugins/smplayer_plugin/filepropertiesdialog.ui b/plugins/smplayer_plugin/filepropertiesdialog.ui new file mode 100644 index 000000000..2473871f6 --- /dev/null +++ b/plugins/smplayer_plugin/filepropertiesdialog.ui @@ -0,0 +1,506 @@ + + Ricardo Villalba + FilePropertiesDialog + + + + 0 + 0 + 502 + 455 + + + + SMPlayer - File properties + + + true + + + + 9 + + + 6 + + + + + 0 + + + + &Information + + + + 6 + + + 6 + + + + + true + + + + + + + + &Demuxer + + + + 6 + + + 6 + + + + + &Select the demuxer that will be used for this file: + + + false + + + demuxer_listbox + + + + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 241 + 41 + + + + + + + + &Reset + + + + + + + + + + &Video codec + + + + 6 + + + 6 + + + + + &Select the video codec: + + + false + + + vc_listbox + + + + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 241 + 41 + + + + + + + + &Reset + + + + + + + + + + A&udio codec + + + + 6 + + + 6 + + + + + &Select the audio codec: + + + false + + + ac_listbox + + + + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 241 + 41 + + + + + + + + &Reset + + + + + + + + + + &MPlayer options + + + + 9 + + + 6 + + + + + Additional Options for MPlayer + + + + 9 + + + 6 + + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + Qt::AlignVCenter + + + false + + + + + + + 0 + + + 6 + + + + + &Options: + + + false + + + mplayer_args_edit + + + + + + + + + + + + + 7 + 0 + 0 + 0 + + + + QFrame::HLine + + + QFrame::Sunken + + + Qt::Horizontal + + + + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + Qt::AlignVCenter + + + false + + + + + + + 0 + + + 6 + + + + + V&ideo filters: + + + false + + + mplayer_vfilters_edit + + + + + + + + + + + + + 7 + 0 + 0 + 0 + + + + QFrame::HLine + + + QFrame::Sunken + + + Qt::Horizontal + + + + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + + + Qt::AlignVCenter + + + false + + + + + + + 0 + + + 6 + + + + + Audio &filters: + + + false + + + mplayer_afilters_edit + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + tabWidget + info_edit + buttonBox + demuxer_listbox + resetDemuxerButton + vc_listbox + resetVCButton + ac_listbox + resetACButton + mplayer_args_edit + mplayer_vfilters_edit + mplayer_afilters_edit + + + + + buttonBox + accepted() + FilePropertiesDialog + accept() + + + 267 + 468 + + + 267 + 246 + + + + + buttonBox + rejected() + FilePropertiesDialog + reject() + + + 267 + 468 + + + 267 + 246 + + + + + diff --git a/plugins/smplayer_plugin/filesettings.cpp b/plugins/smplayer_plugin/filesettings.cpp new file mode 100644 index 000000000..422031f0e --- /dev/null +++ b/plugins/smplayer_plugin/filesettings.cpp @@ -0,0 +1,88 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "filesettings.h" +#include "mediasettings.h" +#include +#include + +FileSettings::FileSettings(QString directory) : FileSettingsBase(directory) +{ + my_settings = new QSettings(directory + "/smplayer_files.ini", QSettings::IniFormat); +} + +FileSettings::~FileSettings() { + delete my_settings; +} + +QString FileSettings::filenameToGroupname(const QString & filename) { + QString s = filename; + s = s.replace('/', '_'); + s = s.replace('\\', '_'); + s = s.replace(':', '_'); + s = s.replace('.', '_'); + s = s.replace(' ', '_'); + + QFileInfo fi(filename); + if (fi.exists()) { + s += "_" + QString::number( fi.size() ); + } + + return s; +} + +bool FileSettings::existSettingsFor(QString filename) { + qDebug("FileSettings::existSettingsFor: '%s'", filename.toUtf8().constData()); + + QString group_name = filenameToGroupname(filename); + + qDebug("FileSettings::existSettingsFor: group_name: '%s'", group_name.toUtf8().constData()); + + my_settings->beginGroup( group_name ); + bool saved = my_settings->value("saved", false).toBool(); + my_settings->endGroup(); + + return saved; +} + +void FileSettings::loadSettingsFor(QString filename, MediaSettings & mset) { + qDebug("FileSettings::loadSettingsFor: '%s'", filename.toUtf8().constData()); + + QString group_name = filenameToGroupname(filename); + + qDebug("FileSettings::loadSettingsFor: group_name: '%s'", group_name.toUtf8().constData()); + + mset.reset(); + my_settings->beginGroup( group_name ); + mset.load(my_settings); + my_settings->endGroup(); +} + +void FileSettings::saveSettingsFor(QString filename, MediaSettings & mset) { + qDebug("FileSettings::saveSettingsFor: '%s'", filename.toUtf8().constData()); + + QString group_name = filenameToGroupname(filename); + + qDebug("FileSettings::saveSettingsFor: group_name: '%s'", group_name.toUtf8().constData()); + + my_settings->beginGroup( group_name ); + my_settings->setValue("saved", true); + mset.save(my_settings); + my_settings->endGroup(); +} + diff --git a/plugins/smplayer_plugin/filesettings.h b/plugins/smplayer_plugin/filesettings.h new file mode 100644 index 000000000..a1d742834 --- /dev/null +++ b/plugins/smplayer_plugin/filesettings.h @@ -0,0 +1,45 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _FILESETTINGS_H_ +#define _FILESETTINGS_H_ + +#include "filesettingsbase.h" + +class QSettings; + +class FileSettings : public FileSettingsBase +{ +public: + FileSettings(QString directory); + virtual ~FileSettings(); + + virtual bool existSettingsFor(QString filename); + + virtual void loadSettingsFor(QString filename, MediaSettings & mset); + + virtual void saveSettingsFor(QString filename, MediaSettings & mset); + + static QString filenameToGroupname(const QString & filename); + +private: + QSettings * my_settings; +}; + +#endif + diff --git a/plugins/smplayer_plugin/filesettingsbase.cpp b/plugins/smplayer_plugin/filesettingsbase.cpp new file mode 100644 index 000000000..3ed78bf6d --- /dev/null +++ b/plugins/smplayer_plugin/filesettingsbase.cpp @@ -0,0 +1,20 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "filesettingsbase.h" + diff --git a/plugins/smplayer_plugin/filesettingsbase.h b/plugins/smplayer_plugin/filesettingsbase.h new file mode 100644 index 000000000..d83fe004c --- /dev/null +++ b/plugins/smplayer_plugin/filesettingsbase.h @@ -0,0 +1,43 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _FILESETTINGS_BASE_H_ +#define _FILESETTINGS_BASE_H_ + +#include + +class MediaSettings; + +class FileSettingsBase +{ +public: + FileSettingsBase(QString directory) { output_directory = directory; }; + virtual ~FileSettingsBase() {}; + + virtual bool existSettingsFor(QString filename) = 0; + + virtual void loadSettingsFor(QString filename, MediaSettings & mset) = 0; + + virtual void saveSettingsFor(QString filename, MediaSettings & mset) = 0; + +protected: + QString output_directory; +}; + +#endif + diff --git a/plugins/smplayer_plugin/filesettingshash.cpp b/plugins/smplayer_plugin/filesettingshash.cpp new file mode 100644 index 000000000..961006125 --- /dev/null +++ b/plugins/smplayer_plugin/filesettingshash.cpp @@ -0,0 +1,102 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "filesettingshash.h" +#include "mediasettings.h" +#include "osparser.h" // hash function +#include +#include +#include + +FileSettingsHash::FileSettingsHash(QString directory) : FileSettingsBase(directory) +{ + base_dir = directory + "/file_settings"; +} + +FileSettingsHash::~FileSettingsHash() { +} + + +QString FileSettingsHash::configFile(const QString & filename, QString * output_dir) { + QString res; + + QString hash = OSParser::calculateHash(filename); + if (!hash.isEmpty()) { + if (output_dir != 0) (*output_dir) = hash[0]; + res = base_dir +"/"+ hash[0] +"/"+ hash + ".ini"; + } + return res; +} + +bool FileSettingsHash::existSettingsFor(QString filename) { + qDebug("FileSettingsHash::existSettingsFor: '%s'", filename.toUtf8().constData()); + + QString config_file = configFile(filename); + + qDebug("FileSettingsHash::existSettingsFor: config_file: '%s'", config_file.toUtf8().constData()); + + return QFile::exists(config_file); +} + +void FileSettingsHash::loadSettingsFor(QString filename, MediaSettings & mset) { + qDebug("FileSettings::loadSettingsFor: '%s'", filename.toUtf8().constData()); + + QString config_file = configFile(filename); + + qDebug("FileSettingsHash::loadSettingsFor: config_file: '%s'", config_file.toUtf8().constData()); + + mset.reset(); + + if ((!config_file.isEmpty()) && (QFile::exists(config_file))) { + QSettings settings(config_file, QSettings::IniFormat); + + settings.beginGroup("file_settings"); + mset.load(&settings); + settings.endGroup(); + } +} + +void FileSettingsHash::saveSettingsFor(QString filename, MediaSettings & mset) { + qDebug("FileSettingsHash::saveSettingsFor: '%s'", filename.toUtf8().constData()); + + QString output_dir; + QString config_file = configFile(filename, &output_dir); + + qDebug("FileSettingsHash::saveSettingsFor: config_file: '%s'", config_file.toUtf8().constData()); + qDebug("FileSettingsHash::saveSettingsFor: output_dir: '%s'", output_dir.toUtf8().constData()); + + if (!config_file.isEmpty()) { + QDir d(base_dir); + if (!d.exists(output_dir)) { + if (!d.mkpath(output_dir)) { + qWarning("FileSettingsHash::saveSettingsFor: can't create directory '%s'", QString(base_dir + "/" + output_dir).toUtf8().constData()); + return; + } + } + + QSettings settings(config_file, QSettings::IniFormat); + + /* settings.setValue("filename", filename); */ + + settings.beginGroup("file_settings"); + mset.save(&settings); + settings.endGroup(); + settings.sync(); + } +} + diff --git a/plugins/smplayer_plugin/filesettingshash.h b/plugins/smplayer_plugin/filesettingshash.h new file mode 100644 index 000000000..7375fa15e --- /dev/null +++ b/plugins/smplayer_plugin/filesettingshash.h @@ -0,0 +1,42 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _FILESETTINGS_HASH_H_ +#define _FILESETTINGS_HASH_H_ + +#include "filesettingsbase.h" + +class FileSettingsHash : public FileSettingsBase +{ +public: + FileSettingsHash(QString directory); + virtual ~FileSettingsHash(); + + virtual bool existSettingsFor(QString filename); + + virtual void loadSettingsFor(QString filename, MediaSettings & mset); + + virtual void saveSettingsFor(QString filename, MediaSettings & mset); + +private: + QString configFile(const QString & filename, QString * output_dir = 0); + QString base_dir; +}; + +#endif + diff --git a/plugins/smplayer_plugin/findsubtitles/filedownloader/filedownloader.cpp b/plugins/smplayer_plugin/findsubtitles/filedownloader/filedownloader.cpp new file mode 100644 index 000000000..702516c34 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/filedownloader/filedownloader.cpp @@ -0,0 +1,110 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Based on the Qt network/http example */ + +#include "filedownloader.h" +#include +#include + +FileDownloader::FileDownloader(QWidget *parent) : QProgressDialog(parent) +{ + setMinimumDuration(0); + + http = new QHttp(this); + + connect(http, SIGNAL(requestFinished(int, bool)), + this, SLOT(httpRequestFinished(int, bool))); + connect(http, SIGNAL(dataReadProgress(int, int)), + this, SLOT(updateDataReadProgress(int, int))); + connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), + this, SLOT(readResponseHeader(const QHttpResponseHeader &))); + connect(this, SIGNAL(canceled()), this, SLOT(cancelDownload())); + + setWindowTitle(tr("Downloading...")); +} + +FileDownloader::~FileDownloader() { + //qDebug("FileDownloader::~FileDownloader"); + delete http; +} + +void FileDownloader::setProxy(QNetworkProxy proxy) { + http->abort(); + http->setProxy(proxy); + + qDebug("FileDownloader::setProxy: host: '%s' port: %d type: %d", + proxy.hostName().toUtf8().constData(), proxy.port(), proxy.type()); +} + +void FileDownloader::download(QUrl url) { + QHttp::ConnectionMode mode = url.scheme().toLower() == "https" ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp; + http->setHost(url.host(), mode, url.port() == -1 ? 0 : url.port()); + + if (!url.userName().isEmpty()) + http->setUser(url.userName(), url.password()); + + http_request_aborted = false; + http_get_id = http->get(url.path(), &buffer); + + setLabelText(tr("Downloading %1").arg(url.toString())); +} + +void FileDownloader::cancelDownload() { + http_request_aborted = true; + http->abort(); +} + +void FileDownloader::httpRequestFinished(int request_id, bool error) { + qDebug("FileDownloader::httpRequestFinished: request_id %d, error %d", request_id, error); + + if (request_id != http_get_id) return; + + if (http_request_aborted) { + hide(); + return; + } + + hide(); + + if (error) { + emit downloadFailed(http->errorString()); + } else { + emit downloadFinished(buffer.data()); + } +} + +void FileDownloader::readResponseHeader(const QHttpResponseHeader &responseHeader) { + if (responseHeader.statusCode() != 200) { + emit downloadFailed(responseHeader.reasonPhrase()); + http_request_aborted = true; + hide(); + http->abort(); + return; + } +} + +void FileDownloader::updateDataReadProgress(int bytes_read, int total_bytes) { + if (http_request_aborted) return; + + setMaximum(total_bytes); + setValue(bytes_read); +} + +#include "moc_filedownloader.cpp" + diff --git a/plugins/smplayer_plugin/findsubtitles/filedownloader/filedownloader.h b/plugins/smplayer_plugin/findsubtitles/filedownloader/filedownloader.h new file mode 100644 index 000000000..09f574107 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/filedownloader/filedownloader.h @@ -0,0 +1,62 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Based on the Qt network/http example */ + +#ifndef _FILEDOWNLOADER_H_ +#define _FILEDOWNLOADER_H_ + +#include +#include +#include +#include + +class QHttp; +class QHttpResponseHeader; + +class FileDownloader : public QProgressDialog +{ + Q_OBJECT + +public: + FileDownloader(QWidget *parent = 0); + ~FileDownloader(); + + void setProxy(QNetworkProxy proxy); + +public slots: + void download(QUrl url); + void cancelDownload(); + +signals: + void downloadFinished(const QByteArray & buffer); + void downloadFailed(const QString & reason); + +private slots: + void httpRequestFinished(int request_id, bool error); + void readResponseHeader(const QHttpResponseHeader &responseHeader); + void updateDataReadProgress(int bytes_read, int total_bytes); + +private: + QHttp * http; + int http_get_id; + bool http_request_aborted; + QBuffer buffer; +}; + +#endif diff --git a/plugins/smplayer_plugin/findsubtitles/filedownloader/filedownloader.pro b/plugins/smplayer_plugin/findsubtitles/filedownloader/filedownloader.pro new file mode 100644 index 000000000..da0e55736 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/filedownloader/filedownloader.pro @@ -0,0 +1,5 @@ +HEADERS += filedownloader.h +SOURCES += filedownloader.cpp main.cpp + +QT += network + diff --git a/plugins/smplayer_plugin/findsubtitles/filedownloader/main.cpp b/plugins/smplayer_plugin/findsubtitles/filedownloader/main.cpp new file mode 100644 index 000000000..30b931165 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/filedownloader/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2004-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Alternatively you may (at +** your option) use any later version of the GNU General Public +** License if such license has been publicly approved by Trolltech ASA +** (or its successors, if any) and the KDE Free Qt Foundation. In +** addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.2, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. If +** you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech, as the sole +** copyright holder for Qt Designer, grants users of the Qt/Eclipse +** Integration plug-in the right for the Qt/Eclipse Integration to +** link to functionality provided by Qt Designer and its related +** libraries. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly +** granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include + +#include "filedownloader.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + FileDownloader w; + w.show(); + w.download(QUrl("http://smplayer.berlios.de/downloads.php?tr_lang=es")); + return w.exec(); +} diff --git a/plugins/smplayer_plugin/findsubtitles/findsubtitles.pro b/plugins/smplayer_plugin/findsubtitles/findsubtitles.pro new file mode 100644 index 000000000..2818f422b --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/findsubtitles.pro @@ -0,0 +1,70 @@ +TEMPLATE = app +LANGUAGE = C++ + +CONFIG += qt warn_on release + +QT += network xml + +INCLUDEPATH += .. +DEPENDPATH += .. + +HEADERS += simplehttp.h \ + osparser.h \ + ../filechooser.h \ + ../languages.h \ + findsubtitleswindow.h + +SOURCES += simplehttp.cpp \ + osparser.cpp \ + ../filechooser.cpp \ + ../languages.cpp \ + findsubtitleswindow.cpp \ + main.cpp + +FORMS += ../filechooser.ui findsubtitleswindow.ui + +DEFINES += NO_SMPLAYER_SUPPORT DOWNLOAD_SUBS + +contains( DEFINES, DOWNLOAD_SUBS ) { + INCLUDEPATH += filedownloader quazip + DEPENDPATH += filedownloader quazip + + HEADERS += filedownloader.h subchooserdialog.h + SOURCES += filedownloader.cpp subchooserdialog.cpp + + FORMS += subchooserdialog.ui + + HEADERS += crypt.h \ + ioapi.h \ + quazip.h \ + quazipfile.h \ + quazipfileinfo.h \ + quazipnewinfo.h \ + unzip.h \ + zip.h + + SOURCES += ioapi.c \ + quazip.cpp \ + quazipfile.cpp \ + quazipnewinfo.cpp \ + unzip.c \ + zip.c + + LIBS += -lz + + win32 { + INCLUDEPATH += c:\development\zlib-1.2.3 + LIBS += -Lc:\development\zlib-1.2.3 + } +} + +unix { + UI_DIR = .ui + MOC_DIR = .moc + OBJECTS_DIR = .obj +} + +win32 { + CONFIG += console +} + diff --git a/plugins/smplayer_plugin/findsubtitles/findsubtitleswindow.cpp b/plugins/smplayer_plugin/findsubtitles/findsubtitleswindow.cpp new file mode 100644 index 000000000..74e7e86f7 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/findsubtitleswindow.cpp @@ -0,0 +1,591 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "findsubtitleswindow.h" +#include "simplehttp.h" +#include "osparser.h" +#include "languages.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DOWNLOAD_SUBS +#include "filedownloader.h" +#include "subchooserdialog.h" +#include "quazip.h" +#include "quazipfile.h" +#include +#include +#endif + +#define COL_LANG 0 +#define COL_NAME 1 +#define COL_FORMAT 2 +#define COL_FILES 3 +#define COL_DATE 4 +#define COL_USER 5 + +FindSubtitlesWindow::FindSubtitlesWindow( QWidget * parent, Qt::WindowFlags f ) + : QDialog(parent,f) +{ + setupUi(this); + + set = 0; // settings + + subtitles_for_label->setBuddy(file_chooser->lineEdit()); + + progress->hide(); + + connect( file_chooser, SIGNAL(fileChanged(QString)), + this, SLOT(setMovie(QString)) ); + connect( file_chooser->lineEdit(), SIGNAL(textChanged(const QString &)), + this, SLOT(updateRefreshButton()) ); + + connect( refresh_button, SIGNAL(clicked()), + this, SLOT(refresh()) ); + + connect( download_button, SIGNAL(clicked()), + this, SLOT(download()) ); + + /* + connect( language_filter, SIGNAL(editTextChanged(const QString &)), + this, SLOT(applyFilter(const QString &)) ); + */ + connect( language_filter, SIGNAL(activated(int)), + this, SLOT(applyCurrentFilter()) ); + + table = new QStandardItemModel(this); + table->setColumnCount(COL_USER + 1); + + proxy_model = new QSortFilterProxyModel(this); + proxy_model->setSourceModel(table); + proxy_model->setFilterKeyColumn(COL_LANG); + proxy_model->setFilterRole(Qt::UserRole); + + view->setModel(proxy_model); + view->setRootIsDecorated(false); + view->setSortingEnabled(true); + view->setAlternatingRowColors(true); + view->header()->setSortIndicator(COL_LANG, Qt::AscendingOrder); + view->setEditTriggers(QAbstractItemView::NoEditTriggers); + view->setContextMenuPolicy( Qt::CustomContextMenu ); + + connect(view, SIGNAL(activated(const QModelIndex &)), + this, SLOT(itemActivated(const QModelIndex &)) ); + connect(view->selectionModel(), SIGNAL(currentChanged(const QModelIndex &,const QModelIndex &)), + this, SLOT(currentItemChanged(const QModelIndex &,const QModelIndex &)) ); + + connect(view, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(showContextMenu(const QPoint &)) ); + + downloader = new SimpleHttp(this); + + connect( downloader, SIGNAL(downloadFailed(QString)), + this, SLOT(showError(QString)) ); + connect( downloader, SIGNAL(downloadFinished(QByteArray)), + this, SLOT(downloadFinished()) ); + connect( downloader, SIGNAL(downloadFinished(QByteArray)), + this, SLOT(parseInfo(QByteArray)) ); + connect( downloader, SIGNAL(stateChanged(int)), + this, SLOT(updateRefreshButton()) ); + + connect( downloader, SIGNAL(connecting(QString)), + this, SLOT(connecting(QString)) ); + connect( downloader, SIGNAL(dataReadProgress(int, int)), + this, SLOT(updateDataReadProgress(int, int)) ); + +#ifdef DOWNLOAD_SUBS + include_lang_on_filename = true; + + file_downloader = new FileDownloader(this); + file_downloader->setModal(true); + connect( file_downloader, SIGNAL(downloadFailed(QString)), + this, SLOT(showError(QString)), Qt::QueuedConnection ); + connect( file_downloader, SIGNAL(downloadFinished(const QByteArray &)), + this, SLOT(archiveDownloaded(const QByteArray &)), Qt::QueuedConnection ); +#endif + + // Actions + downloadAct = new QAction(this); + downloadAct->setEnabled(false); + connect( downloadAct, SIGNAL(triggered()), this, SLOT(download()) ); + + copyLinkAct = new QAction(this); + copyLinkAct->setEnabled(false); + connect( copyLinkAct, SIGNAL(triggered()), this, SLOT(copyLink()) ); + + context_menu = new QMenu(this); + context_menu->addAction(downloadAct); + context_menu->addAction(copyLinkAct); + + retranslateStrings(); + + language_filter->setCurrentIndex(0); +} + +FindSubtitlesWindow::~FindSubtitlesWindow() { + if (set) saveSettings(); +} + +void FindSubtitlesWindow::setSettings(QSettings * settings) { + set = settings; + loadSettings(); +} + +void FindSubtitlesWindow::setProxy(QNetworkProxy proxy) { + downloader->abort(); + downloader->setProxy(proxy); + +#ifdef DOWNLOAD_SUBS + file_downloader->setProxy(proxy); +#endif + + qDebug("FindSubtitlesWindow::setProxy: host: '%s' port: %d type: %d", + proxy.hostName().toUtf8().constData(), proxy.port(), proxy.type()); +} + +void FindSubtitlesWindow::retranslateStrings() { + retranslateUi(this); + + QStringList labels; + labels << tr("Language") << tr("Name") << tr("Format") + << tr("Files") << tr("Date") << tr("Uploaded by"); + + table->setHorizontalHeaderLabels( labels ); + + // Language combobox + //int language_index = language_filter->currentIndex(); + QString current_language = language_filter->itemData(language_filter->currentIndex()).toString(); + language_filter->clear(); + + QMap l = Languages::list(); + QMapIterator i(l); + while (i.hasNext()) { + i.next(); + language_filter->addItem( i.value() + " (" + i.key() + ")", i.key() ); + } + language_filter->model()->sort(0); + language_filter->insertItem( 0, tr("All"), "*" ); + //language_filter->setCurrentIndex(language_index); + language_filter->setCurrentIndex(language_filter->findData(current_language)); + +#if QT_VERSION < 0x040300 + QPushButton * close_button = buttonBox->button(QDialogButtonBox::Close); + close_button->setText( tr("Close") ); +#endif + + // Actions + downloadAct->setText( tr("&Download") ); + copyLinkAct->setText( tr("&Copy link to clipboard") ); +} + +void FindSubtitlesWindow::setMovie(QString filename) { + qDebug("FindSubtitlesWindow::setMovie: '%s'", filename.toLatin1().constData()); + + if (filename == last_file) { + return; + } + + file_chooser->setText(filename); + table->setRowCount(0); + + QString hash = OSParser::calculateHash(filename); + if (hash.isEmpty()) { + qWarning("FindSubtitlesWindow::setMovie: hash invalid. Doing nothing."); + } else { + QString link = "http://www.opensubtitles.org/search/sublanguageid-all/moviehash-" + hash + "/simplexml"; + qDebug("FindSubtitlesWindow::setMovie: link: '%s'", link.toLatin1().constData()); + downloader->download(link); + last_file = filename; + } +} + +void FindSubtitlesWindow::refresh() { + last_file = ""; + setMovie(file_chooser->text()); +} + +void FindSubtitlesWindow::updateRefreshButton() { + QString file = file_chooser->lineEdit()->text(); + bool enabled = ( (!file.isEmpty()) && (QFile::exists(file)) && + (downloader->state()==QHttp::Unconnected) ); + refresh_button->setEnabled(enabled); +} + +void FindSubtitlesWindow::currentItemChanged(const QModelIndex & current, const QModelIndex & /*previous*/) { + qDebug("FindSubtitlesWindow::currentItemChanged: row: %d, col: %d", current.row(), current.column()); + download_button->setEnabled(current.isValid()); + downloadAct->setEnabled(current.isValid()); + copyLinkAct->setEnabled(current.isValid()); +} + +void FindSubtitlesWindow::applyFilter(const QString & filter) { + proxy_model->setFilterWildcard(filter); +} + +void FindSubtitlesWindow::applyCurrentFilter() { + //proxy_model->setFilterWildcard(language_filter->currentText()); + QString filter = language_filter->itemData( language_filter->currentIndex() ).toString(); + applyFilter(filter); +} + +void FindSubtitlesWindow::setLanguage(const QString & lang) { + int idx = language_filter->findData(lang); + if (idx < 0) idx = 0; + language_filter->setCurrentIndex(idx); +} + +QString FindSubtitlesWindow::language() { + int idx = language_filter->currentIndex(); + return language_filter->itemData(idx).toString(); +} + +void FindSubtitlesWindow::showError(QString error) { + QMessageBox::information(this, tr("Error"), + tr("Download failed: %1.") + .arg(error)); +} + +void FindSubtitlesWindow::connecting(QString host) { + status->setText( tr("Connecting to %1...").arg(host) ); +} + +void FindSubtitlesWindow::updateDataReadProgress(int done, int total) { + qDebug("FindSubtitlesWindow::updateDataReadProgress: %d, %d", done, total); + + status->setText( tr("Downloading...") ); + + if (!progress->isVisible()) progress->show(); + progress->setMaximum(total); + progress->setValue(done); +} + +void FindSubtitlesWindow::downloadFinished() { + status->setText( tr("Done.") ); + progress->setMaximum(1); + progress->setValue(0); + progress->hide(); +} + +void FindSubtitlesWindow::parseInfo(QByteArray xml_text) { + OSParser osparser; + bool ok = osparser.parseXml(xml_text); + + table->setRowCount(0); + + QMap language_list = Languages::list(); + + if (ok) { + QList l = osparser.subtitleList(); + for (int n=0; n < l.count(); n++) { + + QString title_name = l[n].movie; + if (!l[n].releasename.isEmpty()) { + title_name += " - " + l[n].releasename; + } + + QStandardItem * i_name = new QStandardItem(title_name); + i_name->setData( l[n].link ); + #if QT_VERSION < 0x040400 + i_name->setToolTip( l[n].link ); + #endif + + QStandardItem * i_lang = new QStandardItem(l[n].language); + i_lang->setData(l[n].iso639, Qt::UserRole); + #if QT_VERSION < 0x040400 + i_lang->setToolTip(l[n].iso639); + #endif + if (language_list.contains(l[n].iso639)) { + i_lang->setText( language_list[ l[n].iso639 ] ); + } + + table->setItem(n, COL_LANG, i_lang); + table->setItem(n, COL_NAME, i_name); + table->setItem(n, COL_FORMAT, new QStandardItem(l[n].format)); + table->setItem(n, COL_FILES, new QStandardItem(l[n].files)); + table->setItem(n, COL_DATE, new QStandardItem(l[n].date)); + table->setItem(n, COL_USER, new QStandardItem(l[n].user)); + + } + status->setText( tr("%1 files available").arg(l.count()) ); + applyCurrentFilter(); + + qDebug("sort column: %d", view->header()->sortIndicatorSection()); + qDebug("sort indicator: %d", view->header()->sortIndicatorOrder()); + + table->sort( view->header()->sortIndicatorSection(), + view->header()->sortIndicatorOrder() ); + } else { + status->setText( tr("Failed to parse the received data.") ); + } + + view->resizeColumnToContents(COL_NAME); +} + +void FindSubtitlesWindow::itemActivated(const QModelIndex & index ) { + qDebug("FindSubtitlesWindow::itemActivated: row: %d, col %d", proxy_model->mapToSource(index).row(), proxy_model->mapToSource(index).column()); + + QString download_link = table->item(proxy_model->mapToSource(index).row(), COL_NAME)->data().toString(); + + qDebug("FindSubtitlesWindow::itemActivated: download link: '%s'", download_link.toLatin1().constData()); + +#ifdef DOWNLOAD_SUBS + file_downloader->download( QUrl(download_link) ); + file_downloader->show(); +#else + QDesktopServices::openUrl( QUrl(download_link) ); +#endif +} + +void FindSubtitlesWindow::download() { + qDebug("FindSubtitlesWindow::download"); + if (view->currentIndex().isValid()) { + itemActivated(view->currentIndex()); + } +} + +void FindSubtitlesWindow::copyLink() { + qDebug("FindSubtitlesWindow::copyLink"); + if (view->currentIndex().isValid()) { + const QModelIndex & index = view->currentIndex(); + QString download_link = table->item(proxy_model->mapToSource(index).row(), COL_NAME)->data().toString(); + qDebug("FindSubtitlesWindow::copyLink: link: '%s'", download_link.toLatin1().constData()); + qApp->clipboard()->setText(download_link); + } +} + +void FindSubtitlesWindow::showContextMenu(const QPoint & pos) { + qDebug("FindSubtitlesWindow::showContextMenu"); + + context_menu->move( view->viewport()->mapToGlobal(pos) ); + context_menu->show(); +} + +// Language change stuff +void FindSubtitlesWindow::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QWidget::changeEvent(e); + } +} + +#ifdef DOWNLOAD_SUBS +void FindSubtitlesWindow::archiveDownloaded(const QByteArray & buffer) { + qDebug("FindSubtitlesWindow::archiveDownloaded"); + + QString temp_dir = QDir::tempPath(); + if (!temp_dir.endsWith("/")) temp_dir += "/"; + + QTemporaryFile file(temp_dir + "archive_XXXXXX.zip"); + file.setAutoRemove(false); + + qDebug("FindSubtitlesWindow::archiveDownloaded: a temporary file will be saved in folder '%s'", temp_dir.toUtf8().constData()); + + if (file.open()) { + QString filename = file.fileName(); + file.write( buffer ); + file.close(); + + qDebug("FindSubtitlesWindow::archiveDownloaded: file saved as: %s", filename.toUtf8().constData()); + + /* + QMessageBox::information(this, tr("Downloaded"), tr("File saved as %1").arg(filename)); + return; + */ + + status->setText(tr("Temporary file %1").arg(filename)); + + QString lang = "unknown"; + QString extension = "unknown"; + if (view->currentIndex().isValid()) { + const QModelIndex & index = view->currentIndex(); + lang = table->item(proxy_model->mapToSource(index).row(), COL_LANG)->data(Qt::UserRole).toString(); + extension = table->item(proxy_model->mapToSource(index).row(), COL_FORMAT)->text(); + } + + QFileInfo fi(file_chooser->text()); + QString output_name = fi.completeBaseName(); + if (include_lang_on_filename) output_name += "_"+ lang; + output_name += "." + extension; + + if (!uncompressZip(filename, fi.absolutePath(), output_name)) { + status->setText(tr("Download failed")); + } + file.remove(); + } + else { + qWarning("FindSubtitlesWindow::archiveDownloaded: can't write temporary file"); + QMessageBox::warning(this, tr("Error saving file"), + tr("It wasn't possible to save the downloaded\n" + "file in folder %1\n" + "Please check the permissions of that folder.").arg(temp_dir)); + } +} + + +bool FindSubtitlesWindow::uncompressZip(const QString & filename, const QString & output_path, const QString & preferred_output_name) { + qDebug("FindSubtitlesWindow::uncompressZip: zip file '%s', output_path '%s', save subtitle as '%s'", + filename.toUtf8().constData(), output_path.toUtf8().constData(), + preferred_output_name.toUtf8().constData()); + + QuaZip zip(filename); + + if (!zip.open(QuaZip::mdUnzip)) { + qWarning("FindSubtitlesWindow::uncompressZip: open zip failed: %d", zip.getZipError()); + return false; + } + + zip.setFileNameCodec("IBM866"); + qDebug("FindSubtitlesWindow::uncompressZip: %d entries", zip.getEntriesCount()); + qDebug("FindSubtitlesWindow::uncompressZip: global comment: '%s'", zip.getComment().toUtf8().constData()); + + QStringList sub_files; + QuaZipFileInfo info; + + for (bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) { + if (!zip.getCurrentFileInfo(&info)) { + qWarning("FindSubtitlesWindow::uncompressZip: getCurrentFileInfo(): %d\n", zip.getZipError()); + return false; + } + qDebug("FindSubtitlesWindow::uncompressZip: file '%s'", info.name.toUtf8().constData()); + if (QFileInfo(info.name).suffix() != "nfo") sub_files.append(info.name); + } + + qDebug("FindSubtitlesWindow::uncompressZip: list of subtitle files:"); + for (int n=0; n < sub_files.count(); n++) { + qDebug("FindSubtitlesWindow::uncompressZip: subtitle file %d '%s'", n, sub_files[n].toUtf8().constData()); + } + + if (sub_files.count() == 1) { + // If only one file, just extract it + QString output_name = output_path +"/"+ preferred_output_name; + if (extractFile(zip, sub_files[0], output_name )) { + status->setText(tr("Subtitle saved as %1").arg(preferred_output_name)); + emit subtitleDownloaded(output_name); + } else { + return false; + } + } else { + // More than one file + SubChooserDialog d(this); + + for (int n=0; n < sub_files.count(); n++) { + d.addFile(sub_files[n]); + } + + if (d.exec() == QDialog::Rejected) return false; + + QStringList files_to_extract = d.selectedFiles(); + int extracted_count = 0; + for (int n=0; n < files_to_extract.count(); n++) { + QString file = files_to_extract[n]; + bool ok = extractFile(zip, file, output_path +"/"+ file); + qDebug("FindSubtitlesWindow::uncompressZip: extracted %s ok: %d", file.toUtf8().constData(), ok); + if (ok) extracted_count++; + } + status->setText(tr("%1 subtitle(s) extracted","", extracted_count).arg(extracted_count)); + if (extracted_count > 0) { + emit subtitleDownloaded( output_path +"/"+ files_to_extract[0] ); + } + } + + zip.close(); + return true; +} + +bool FindSubtitlesWindow::extractFile(QuaZip & zip, const QString & filename, const QString & output_name) { + qDebug("FindSubtitlesWindow::extractFile: '%s', save as '%s'", filename.toUtf8().constData(), output_name.toUtf8().constData()); + + if (QFile::exists(output_name)) { + if (QMessageBox::question(this, tr("Overwrite?"), + tr("The file %1 already exits, overwrite?").arg(output_name), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) + { + return false; + } + } + + if (!zip.setCurrentFile(filename)) { + qDebug("FindSubtitlesWindow::extractFile: can't select file %s", filename.toUtf8().constData()); + return false; + } + + // Saving + char c; + QuaZipFile file(&zip); + QFile out(output_name); + + if (!file.open(QIODevice::ReadOnly)) { + qWarning("FindSubtitlesWindow::extractFile: can't open file for reading: %d", file.getZipError()); + return false; + } + + if (out.open(QIODevice::WriteOnly)) { + // Slow like hell (on GNU/Linux at least), but it is not my fault. + // Not ZIP/UNZIP package's fault either. + // The slowest thing here is out.putChar(c). + while(file.getChar(&c)) out.putChar(c); + out.close(); + + file.close(); + } else { + qWarning("FindSubtitlesWindow::extractFile: can't open %s for writing", output_name.toUtf8().constData()); + return false; + } + + return true; +} + +#endif + +void FindSubtitlesWindow::saveSettings() { + qDebug("FindSubtitlesWindow::saveSettings"); + + set->beginGroup("findsubtitles"); + + set->setValue("language", language()); +#ifdef DOWNLOAD_SUBS + set->setValue("include_lang_on_filename", includeLangOnFilename()); +#endif + + set->endGroup(); +} + +void FindSubtitlesWindow::loadSettings() { + qDebug("FindSubtitlesWindow::loadSettings"); + + set->beginGroup("findsubtitles"); + + setLanguage( set->value("language", language()).toString() ); +#ifdef DOWNLOAD_SUBS + setIncludeLangOnFilename( set->value("include_lang_on_filename", includeLangOnFilename()).toBool() ); +#endif + + set->endGroup(); +} + +#include "moc_findsubtitleswindow.cpp" + diff --git a/plugins/smplayer_plugin/findsubtitles/findsubtitleswindow.h b/plugins/smplayer_plugin/findsubtitles/findsubtitleswindow.h new file mode 100644 index 000000000..800ca3864 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/findsubtitleswindow.h @@ -0,0 +1,123 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _FINDSUBTITLESWINDOW_H_ +#define _FINDSUBTITLESWINDOW_H_ + +#include "ui_findsubtitleswindow.h" +#include + +class SimpleHttp; +class QStandardItemModel; +class QSortFilterProxyModel; +class QModelIndex; +class QMenu; +class QAction; +class QSettings; + +#ifdef DOWNLOAD_SUBS +class FileDownloader; +class QBuffer; +class QuaZip; +#endif + +class FindSubtitlesWindow : public QDialog, public Ui::FindSubtitlesWindow +{ + Q_OBJECT + +public: + FindSubtitlesWindow( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~FindSubtitlesWindow(); + + void setProxy(QNetworkProxy proxy); + QString language(); +#ifdef DOWNLOAD_SUBS + bool includeLangOnFilename() { return include_lang_on_filename; }; +#endif + + void setSettings(QSettings * settings); + QSettings * settings() { return set; }; + +public slots: + void setMovie(QString filename); + void setLanguage(const QString & lang); + void refresh(); + void download(); + void copyLink(); +#ifdef DOWNLOAD_SUBS + void setIncludeLangOnFilename(bool b) { include_lang_on_filename = b; }; +#endif + +protected slots: + void applyFilter(const QString & filter); + void applyCurrentFilter(); + + void showError(QString error); + void connecting(QString host); + void updateDataReadProgress(int done, int total); + void downloadFinished(); + + void updateRefreshButton(); + + void parseInfo(QByteArray xml_text); + + void itemActivated(const QModelIndex & index ); + void currentItemChanged(const QModelIndex & current, const QModelIndex & previous); + + void showContextMenu(const QPoint & pos); + +#ifdef DOWNLOAD_SUBS + void archiveDownloaded(const QByteArray & buffer); +#endif + +protected: + virtual void retranslateStrings(); + virtual void changeEvent(QEvent * event); + + void saveSettings(); + void loadSettings(); + +#ifdef DOWNLOAD_SUBS +signals: + void subtitleDownloaded(const QString & filename); + +protected: + bool uncompressZip(const QString & filename, const QString & output_path, const QString & preferred_output_name); + bool extractFile(QuaZip & zip, const QString & filename, const QString & output_name); +#endif + +protected: + SimpleHttp * downloader; + QStandardItemModel * table; + QSortFilterProxyModel * proxy_model; + QString last_file; + + QMenu * context_menu; + QAction * downloadAct; + QAction * copyLinkAct; + +#ifdef DOWNLOAD_SUBS + FileDownloader * file_downloader; + bool include_lang_on_filename; +#endif + + QSettings * set; +}; + +#endif + diff --git a/plugins/smplayer_plugin/findsubtitles/findsubtitleswindow.ui b/plugins/smplayer_plugin/findsubtitles/findsubtitleswindow.ui new file mode 100644 index 000000000..6bd839d33 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/findsubtitleswindow.ui @@ -0,0 +1,203 @@ + + FindSubtitlesWindow + + + + 0 + 0 + 649 + 385 + + + + Find Subtitles + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + &Subtitles for + + + + + + + + + + + + + + + 0 + + + 6 + + + + + &Language: + + + language_filter + + + + + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + &Refresh + + + + + + + false + + + &Download + + + + + + + + + 0 + + + 6 + + + + + + 7 + 5 + 0 + 0 + + + + QFrame::Panel + + + QFrame::Sunken + + + + + + + + + + + 5 + 0 + 0 + 0 + + + + 0 + + + false + + + Qt::Horizontal + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + FileChooser + QLineEdit +
    filechooser.h
    +
    +
    + + file_chooser + view + language_filter + refresh_button + download_button + buttonBox + + + + + buttonBox + rejected() + FindSubtitlesWindow + close() + + + 334 + 380 + + + 334 + 201 + + + + +
    diff --git a/plugins/smplayer_plugin/findsubtitles/main.cpp b/plugins/smplayer_plugin/findsubtitles/main.cpp new file mode 100644 index 000000000..c20bed010 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/main.cpp @@ -0,0 +1,36 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include "findsubtitleswindow.h" + +int main( int argc, char ** argv ) +{ + QApplication a( argc, argv ); + a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) ); + + QSettings set(QSettings::IniFormat, QSettings::UserScope, "RVM", "findsubtitles"); + + FindSubtitlesWindow w; + w.setSettings(&set); + w.show(); + + return a.exec(); +} + diff --git a/plugins/smplayer_plugin/findsubtitles/osparser.cpp b/plugins/smplayer_plugin/findsubtitles/osparser.cpp new file mode 100644 index 000000000..389ec4f2b --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/osparser.cpp @@ -0,0 +1,107 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "osparser.h" +#include +#include +#include + +OSParser::OSParser() { +} + +OSParser::~OSParser() { +} + +bool OSParser::parseXml(QByteArray text) { + qDebug("OSParser::parseXml: source: '%s'", text.constData()); + + s_list.clear(); + + bool ok = dom_document.setContent(text); + qDebug("OSParser::parseXml: success: %d", ok); + + if (!ok) return false; + + QDomNode root = dom_document.documentElement(); + //qDebug("tagname: '%s'", root.toElement().tagName().toLatin1().constData()); + + QString base_url = root.firstChildElement("base").text(); + //qDebug("base_url: '%s'", base_url.toLatin1().constData()); + + QDomNode child = root.firstChildElement("results"); + if (!child.isNull()) { + //qDebug("items: %s", child.toElement().attribute("items").toLatin1().constData()); + QDomNode subtitle = child.firstChildElement("subtitle"); + while (!subtitle.isNull()) { + //qDebug("tagname: '%s'", subtitle.tagName().toLatin1().constData()); + qDebug("OSParser::parseXml: text: '%s'", subtitle.toElement().text().toLatin1().constData()); + + OSSubtitle sub; + + sub.releasename = subtitle.firstChildElement("releasename").text(); + sub.link = base_url + subtitle.firstChildElement("download").text(); + sub.detail = subtitle.firstChildElement("detail").text(); + sub.date = subtitle.firstChildElement("subadddate").text(); + sub.rating = subtitle.firstChildElement("subrating").text(); + sub.comments = subtitle.firstChildElement("subcomments").text(); + sub.movie = subtitle.firstChildElement("movie").text(); + sub.files = subtitle.firstChildElement("files").text(); + sub.format = subtitle.firstChildElement("format").text(); + sub.language = subtitle.firstChildElement("language").text(); + sub.iso639 = subtitle.firstChildElement("iso639").text(); + sub.user = subtitle.firstChildElement("user").text(); + + s_list.append(sub); + + subtitle = subtitle.nextSiblingElement("subtitle"); + } + } + + return true; +} + +// From the patch by Kamil Dziobek turbos11(at)gmail.com +// (c) Kamil Dziobek turbos11(at)gmail.com | BSD or GPL or public domain +QString OSParser::calculateHash(QString filename) { + QFile file(filename); + + if (!file.exists()) { + qWarning("OSParser:calculateHash: error hashing file. File doesn't exist."); + return QString(); + } + + file.open(QIODevice::ReadOnly); + QDataStream in(&file); + in.setByteOrder(QDataStream::LittleEndian); + quint64 size=file.size (); + quint64 hash=size; + quint64 a; + for(int i = 0; i < 8192; i++) { + in >> a ; hash += a; + }; + file.seek(size-65536); + for(int i = 0; i < 8192; i++) { + in >> a ; hash += a; + }; + + QString hexhash(""); + hexhash.setNum(hash,16); + + return hexhash; +} + diff --git a/plugins/smplayer_plugin/findsubtitles/osparser.h b/plugins/smplayer_plugin/findsubtitles/osparser.h new file mode 100644 index 000000000..d33b11c14 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/osparser.h @@ -0,0 +1,51 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _OSPARSER_H_ +#define _OSPARSER_H_ + +#include +#include +#include +#include + +class OSSubtitle { +public: + QString movie, releasename, link, iso639, language, date; + QString format, comments, detail, rating, files, user; +}; + +class OSParser { + +public: + OSParser(); + ~OSParser(); + + bool parseXml(QByteArray text); + + QList subtitleList() { return s_list; }; + + static QString calculateHash(QString filename); + +protected: + QDomDocument dom_document; + QList s_list; +}; + +#endif + diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/COPYING b/plugins/smplayer_plugin/findsubtitles/quazip/COPYING new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/COPYING.LGPL b/plugins/smplayer_plugin/findsubtitles/quazip/COPYING.LGPL new file mode 100644 index 000000000..2cba2ac74 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/COPYING.LGPL @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/COPYING.readme b/plugins/smplayer_plugin/findsubtitles/quazip/COPYING.readme new file mode 100644 index 000000000..6d9b6e90c --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/COPYING.readme @@ -0,0 +1,29 @@ +-- A kind of "standard" GPL license statement -- +QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package +Copyright (C) 2005-2007 Sergey A. Tachenov + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-- A kind of "standard" GPL license statement ends here -- + +See COPYING file for GPL. + +You are also permitted to use QuaZIP under the terms of LGPL (see +COPYING.LGPL). You are free to choose either license, but please note +that QuaZIP makes use of Qt, which is not licensed under LGPL. So if +you are using Open Source edition of Qt, you therefore MUST use GPL for +your code based on QuaZIP, since it would be also based on Qt in this +case. If you are Qt commercial license owner, then you are free to use +QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/README b/plugins/smplayer_plugin/findsubtitles/quazip/README new file mode 100644 index 000000000..0ac0dd622 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/README @@ -0,0 +1,57 @@ +QuaZIP is the C++ wrapper for the Gilles Vollant's ZIP/UNZIP package +using Trolltech's Qt library. + +It contains original ZIP/UNZIP package C code and therefore depends on +zlib library. + +Also, it depends on Qt 4. + +To comile it on UNIX dialect: + +$ cd quazip +$ qmake +$ make + +You must make sure that: +* You have Qt 4 properly and fully installed (including tools and + headers, not just library) +* "qmake" command runs Qt 4's qmake, not some other version (you'll have + to type full path to qmake otherwise). + +To install compiled static library, just type: + +$ make install + +By default, it installs in /usr/local, but you may change it using + +$ qmake PREFIX=/wherever/you/whant/to/install + +You do not have to compile and install QuaZIP to use it. You can just +(and sometimes it may be the best way) add QuaZIP's source files to your +project and use them. + +See doc/html or, if you do not have a browser, quazip/*.h and +quazip/doc/* files for the more detailed documentation. + +Copyright notice: + +Copyright (C) 2005 Sergey A. Tachenov + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +See COPYING file for the full GPL text. + +Original ZIP package is copyrighted by Gilles Vollant, see +quazip/(un)zip.h files for details. diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/crypt.h b/plugins/smplayer_plugin/findsubtitles/quazip/crypt.h new file mode 100644 index 000000000..82748c571 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/crypt.h @@ -0,0 +1,133 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + (void) pcrc_32_tab; /* avoid "unused parameter" warning */ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) + const char *passwd; /* password string */ + unsigned char *buf; /* where to write header */ + int bufSize; + unsigned long* pkeys; + const unsigned long* pcrc_32_tab; + unsigned long crcForCrypting; +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/ioapi.c b/plugins/smplayer_plugin/findsubtitles/quazip/ioapi.c new file mode 100644 index 000000000..cf29a317f --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/ioapi.c @@ -0,0 +1,184 @@ +/* ioapi.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include +#include +#include + +#include "zlib.h" +#include "ioapi.h" + + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +voidpf ZCALLBACK fopen_file_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +uLong ZCALLBACK fread_file_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK fwrite_file_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK ftell_file_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK fseek_file_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK fclose_file_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK ferror_file_func OF(( + voidpf opaque, + voidpf stream)); + + +voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) + voidpf opaque; + const char* filename; + int mode; +{ + (void) opaque; /* avoid "unused parameter" warning */ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + + +uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + void* buf; + uLong size; +{ + (void) opaque; /* avoid "unused parameter" warning */ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + + +uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + const void* buf; + uLong size; +{ + (void) opaque; /* avoid "unused parameter" warning */ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +long ZCALLBACK ftell_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + (void) opaque; /* avoid "unused parameter" warning */ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + +long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) + voidpf opaque; + voidpf stream; + uLong offset; + int origin; +{ + (void) opaque; /* avoid "unused parameter" warning */ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + fseek((FILE *)stream, offset, fseek_origin); + return ret; +} + +int ZCALLBACK fclose_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + (void) opaque; /* avoid "unused parameter" warning */ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +int ZCALLBACK ferror_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + (void) opaque; /* avoid "unused parameter" warning */ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/ioapi.h b/plugins/smplayer_plugin/findsubtitles/quazip/ioapi.h new file mode 100644 index 000000000..7d457baab --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/ioapi.h @@ -0,0 +1,75 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifndef _ZLIBIOAPI_H +#define _ZLIBIOAPI_H + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + +#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +#define ZCALLBACK CALLBACK +#else +#define ZCALLBACK +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + + + +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) +#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) +#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) +#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) +#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/quazip.cpp b/plugins/smplayer_plugin/findsubtitles/quazip/quazip.cpp new file mode 100644 index 000000000..3f7314a43 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/quazip.cpp @@ -0,0 +1,285 @@ +/* +-- A kind of "standard" GPL license statement -- +QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package +Copyright (C) 2005-2007 Sergey A. Tachenov + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-- A kind of "standard" GPL license statement ends here -- + +See COPYING file for GPL. + +You are also permitted to use QuaZIP under the terms of LGPL (see +COPYING.LGPL). You are free to choose either license, but please note +that QuaZIP makes use of Qt, which is not licensed under LGPL. So if +you are using Open Source edition of Qt, you therefore MUST use GPL for +your code based on QuaZIP, since it would be also based on Qt in this +case. If you are Qt commercial license owner, then you are free to use +QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. + **/ + +#include + +#include "quazip.h" + +QuaZip::QuaZip(): + fileNameCodec(QTextCodec::codecForLocale()), + commentCodec(QTextCodec::codecForLocale()), + mode(mdNotOpen), hasCurrentFile_f(false), zipError(UNZ_OK) +{ +} + +QuaZip::QuaZip(const QString& zipName): + fileNameCodec(QTextCodec::codecForLocale()), + commentCodec(QTextCodec::codecForLocale()), + zipName(zipName), + mode(mdNotOpen), hasCurrentFile_f(false), zipError(UNZ_OK) +{ +} + +QuaZip::~QuaZip() +{ + if(isOpen()) close(); +} + +bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi) +{ + zipError=UNZ_OK; + if(isOpen()) { + qWarning("QuaZip::open(): ZIP already opened"); + return false; + } + switch(mode) { + case mdUnzip: + unzFile_f=unzOpen2(QFile::encodeName(zipName).constData(), ioApi); + if(unzFile_f!=NULL) { + this->mode=mode; + return true; + } else { + zipError=UNZ_OPENERROR; + return false; + } + case mdCreate: + case mdAppend: + case mdAdd: + zipFile_f=zipOpen2(QFile::encodeName(zipName).constData(), + mode==mdCreate?APPEND_STATUS_CREATE: + mode==mdAppend?APPEND_STATUS_CREATEAFTER: + APPEND_STATUS_ADDINZIP, + NULL, + ioApi); + if(zipFile_f!=NULL) { + this->mode=mode; + return true; + } else { + zipError=UNZ_OPENERROR; + return false; + } + default: + qWarning("QuaZip::open(): unknown mode: %d", (int)mode); + return false; + break; + } +} + +void QuaZip::close() +{ + zipError=UNZ_OK; + switch(mode) { + case mdNotOpen: + qWarning("QuaZip::close(): ZIP is not open"); + return; + case mdUnzip: + zipError=unzClose(unzFile_f); + break; + case mdCreate: + case mdAppend: + case mdAdd: + zipError=zipClose(zipFile_f, commentCodec->fromUnicode(comment).constData()); + break; + default: + qWarning("QuaZip::close(): unknown mode: %d", (int)mode); + return; + } + if(zipError==UNZ_OK) mode=mdNotOpen; +} + +void QuaZip::setZipName(const QString& zipName) +{ + if(isOpen()) { + qWarning("QuaZip::setZipName(): ZIP is already open!"); + return; + } + this->zipName=zipName; +} + +int QuaZip::getEntriesCount()const +{ + QuaZip *fakeThis=(QuaZip*)this; // non-const + fakeThis->zipError=UNZ_OK; + if(mode!=mdUnzip) { + qWarning("QuaZip::getEntriesCount(): ZIP is not open in mdUnzip mode"); + return -1; + } + unz_global_info globalInfo; + if((fakeThis->zipError=unzGetGlobalInfo(unzFile_f, &globalInfo))!=UNZ_OK) + return zipError; + return (int)globalInfo.number_entry; +} + +QString QuaZip::getComment()const +{ + QuaZip *fakeThis=(QuaZip*)this; // non-const + fakeThis->zipError=UNZ_OK; + if(mode!=mdUnzip) { + qWarning("QuaZip::getComment(): ZIP is not open in mdUnzip mode"); + return QString(); + } + unz_global_info globalInfo; + QByteArray comment; + if((fakeThis->zipError=unzGetGlobalInfo(unzFile_f, &globalInfo))!=UNZ_OK) + return QString(); + comment.resize(globalInfo.size_comment); + if((fakeThis->zipError=unzGetGlobalComment(unzFile_f, comment.data(), comment.size()))!=UNZ_OK) + return QString(); + return commentCodec->toUnicode(comment); +} + +bool QuaZip::setCurrentFile(const QString& fileName, CaseSensitivity cs) +{ + zipError=UNZ_OK; + if(mode!=mdUnzip) { + qWarning("QuaZip::setCurrentFile(): ZIP is not open in mdUnzip mode"); + return false; + } + if(fileName.isNull()) { + hasCurrentFile_f=false; + return true; + } + // Unicode-aware reimplementation of the unzLocateFile function + if(unzFile_f==NULL) { + zipError=UNZ_PARAMERROR; + return false; + } + if(fileName.length()>MAX_FILE_NAME_LENGTH) { + zipError=UNZ_PARAMERROR; + return false; + } + bool sens; + if(cs==csDefault) { +#ifdef Q_WS_WIN + sens=false; +#else + sens=true; +#endif + } else sens=cs==csSensitive; + QString lower, current; + if(!sens) lower=fileName.toLower(); + hasCurrentFile_f=false; + for(bool more=goToFirstFile(); more; more=goToNextFile()) { + current=getCurrentFileName(); + if(current.isNull()) return false; + if(sens) { + if(current==fileName) break; + } else { + if(current.toLower()==lower) break; + } + } + return hasCurrentFile_f; +} + +bool QuaZip::goToFirstFile() +{ + zipError=UNZ_OK; + if(mode!=mdUnzip) { + qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode"); + return false; + } + zipError=unzGoToFirstFile(unzFile_f); + hasCurrentFile_f=zipError==UNZ_OK; + return hasCurrentFile_f; +} + +bool QuaZip::goToNextFile() +{ + zipError=UNZ_OK; + if(mode!=mdUnzip) { + qWarning("QuaZip::goToFirstFile(): ZIP is not open in mdUnzip mode"); + return false; + } + zipError=unzGoToNextFile(unzFile_f); + hasCurrentFile_f=zipError==UNZ_OK; + if(zipError==UNZ_END_OF_LIST_OF_FILE) zipError=UNZ_OK; + return hasCurrentFile_f; +} + +bool QuaZip::getCurrentFileInfo(QuaZipFileInfo *info)const +{ + QuaZip *fakeThis=(QuaZip*)this; // non-const + fakeThis->zipError=UNZ_OK; + if(mode!=mdUnzip) { + qWarning("QuaZip::getCurrentFileInfo(): ZIP is not open in mdUnzip mode"); + return false; + } + unz_file_info info_z; + QByteArray fileName; + QByteArray extra; + QByteArray comment; + if(info==NULL) return false; + if(!isOpen()||!hasCurrentFile()) return false; + if((fakeThis->zipError=unzGetCurrentFileInfo(unzFile_f, &info_z, NULL, 0, NULL, 0, NULL, 0))!=UNZ_OK) + return false; + fileName.resize(info_z.size_filename); + extra.resize(info_z.size_file_extra); + comment.resize(info_z.size_file_comment); + if((fakeThis->zipError=unzGetCurrentFileInfo(unzFile_f, NULL, + fileName.data(), fileName.size(), + extra.data(), extra.size(), + comment.data(), comment.size()))!=UNZ_OK) + return false; + info->versionCreated=info_z.version; + info->versionNeeded=info_z.version_needed; + info->flags=info_z.flag; + info->method=info_z.compression_method; + info->crc=info_z.crc; + info->compressedSize=info_z.compressed_size; + info->uncompressedSize=info_z.uncompressed_size; + info->diskNumberStart=info_z.disk_num_start; + info->internalAttr=info_z.internal_fa; + info->externalAttr=info_z.external_fa; + info->name=fileNameCodec->toUnicode(fileName); + info->comment=commentCodec->toUnicode(comment); + info->extra=extra; + info->dateTime=QDateTime( + QDate(info_z.tmu_date.tm_year, info_z.tmu_date.tm_mon+1, info_z.tmu_date.tm_mday), + QTime(info_z.tmu_date.tm_hour, info_z.tmu_date.tm_min, info_z.tmu_date.tm_sec)); + return true; +} + +QString QuaZip::getCurrentFileName()const +{ + QuaZip *fakeThis=(QuaZip*)this; // non-const + fakeThis->zipError=UNZ_OK; + if(mode!=mdUnzip) { + qWarning("QuaZip::getCurrentFileName(): ZIP is not open in mdUnzip mode"); + return QString(); + } + if(!isOpen()||!hasCurrentFile()) return QString(); + QByteArray fileName(MAX_FILE_NAME_LENGTH, 0); + if((fakeThis->zipError=unzGetCurrentFileInfo(unzFile_f, NULL, fileName.data(), fileName.size(), + NULL, 0, NULL, 0))!=UNZ_OK) + return QString(); + return fileNameCodec->toUnicode(fileName.constData()); +} diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/quazip.h b/plugins/smplayer_plugin/findsubtitles/quazip/quazip.h new file mode 100644 index 000000000..ced1ea0f1 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/quazip.h @@ -0,0 +1,346 @@ +#ifndef QUA_ZIP_H +#define QUA_ZIP_H + +/* +-- A kind of "standard" GPL license statement -- +QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package +Copyright (C) 2005-2007 Sergey A. Tachenov + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-- A kind of "standard" GPL license statement ends here -- + +See COPYING file for GPL. + +You are also permitted to use QuaZIP under the terms of LGPL (see +COPYING.LGPL). You are free to choose either license, but please note +that QuaZIP makes use of Qt, which is not licensed under LGPL. So if +you are using Open Source edition of Qt, you therefore MUST use GPL for +your code based on QuaZIP, since it would be also based on Qt in this +case. If you are Qt commercial license owner, then you are free to use +QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. + **/ + +#include +#include + +#include "zip.h" +#include "unzip.h" + +#include "quazipfileinfo.h" + +// just in case it will be defined in the later versions of the ZIP/UNZIP +#ifndef UNZ_OPENERROR +// define additional error code +#define UNZ_OPENERROR -1000 +#endif + +/// ZIP archive. +/** \class QuaZip quazip.h + * This class implements basic interface to the ZIP archive. It can be + * used to read table contents of the ZIP archive and retreiving + * information about the files inside it. + * + * You can also use this class to open files inside archive by passing + * pointer to the instance of this class to the constructor of the + * QuaZipFile class. But see QuaZipFile::QuaZipFile(QuaZip*, QObject*) + * for the possible pitfalls. + * + * This class is indended to provide interface to the ZIP subpackage of + * the ZIP/UNZIP package as well as to the UNZIP subpackage. But + * currently it supports only UNZIP. + * + * The use of this class is simple - just create instance using + * constructor, then set ZIP archive file name using setFile() function + * (if you did not passed the name to the constructor), then open() and + * then use different functions to work with it! Well, if you are + * paranoid, you may also wish to call close before destructing the + * instance, to check for errors on close. + * + * You may also use getUnzFile() and getZipFile() functions to get the + * ZIP archive handle and use it with ZIP/UNZIP package API directly. + * + * This class supports localized file names inside ZIP archive, but you + * have to set up proper codec with setCodec() function. By default, + * locale codec will be used, which is probably ok for UNIX systems, but + * will almost certainly fail with ZIP archives created in Windows. This + * is because Windows ZIP programs have strange habit of using DOS + * encoding for file names in ZIP archives. For example, ZIP archive + * with cyrillic names created in Windows will have file names in \c + * IBM866 encoding instead of \c WINDOWS-1251. I think that calling one + * function is not much trouble, but for true platform independency it + * would be nice to have some mechanism for file name encoding auto + * detection using locale information. Does anyone know a good way to do + * it? + **/ +class QuaZip { + public: + /// Useful constants. + enum Constants { + MAX_FILE_NAME_LENGTH=256 /**< Maximum file name length. Taken from + \c UNZ_MAXFILENAMEINZIP constant in + unzip.c. */ + }; + /// Open mode of the ZIP file. + enum Mode { + mdNotOpen, ///< ZIP file is not open. This is the initial mode. + mdUnzip, ///< ZIP file is open for reading files inside it. + mdCreate, ///< ZIP file was created with open() call. + mdAppend, /**< ZIP file was opened in append mode. This refers to + * \c APPEND_STATUS_CREATEAFTER mode in ZIP/UNZIP package + * and means that zip is appended to some existing file + * what is useful when that file contains + * self-extractor code. This is obviously \em not what + * you whant to use to add files to the existing ZIP + * archive. + **/ + mdAdd ///< ZIP file was opened for adding files in the archive. + }; + /// Case sensitivity for the file names. + /** This is what you specify when accessing files in the archive. + * Works perfectly fine with any characters thanks to Qt's great + * unicode support. This is different from ZIP/UNZIP API, where + * only US-ASCII characters was supported. + **/ + enum CaseSensitivity { + csDefault=0, ///< Default for platform. Case sensitive for UNIX, not for Windows. + csSensitive=1, ///< Case sensitive. + csInsensitive=2 ///< Case insensitive. + }; + private: + QTextCodec *fileNameCodec, *commentCodec; + QString zipName; + QString comment; + Mode mode; + union { + unzFile unzFile_f; + zipFile zipFile_f; + }; + bool hasCurrentFile_f; + int zipError; + // not (and will not be) implemented + QuaZip(const QuaZip& that); + // not (and will not be) implemented + QuaZip& operator=(const QuaZip& that); + public: + /// Constructs QuaZip object. + /** Call setName() before opening constructed object. */ + QuaZip(); + /// Constructs QuaZip object associated with ZIP file \a zipName. + QuaZip(const QString& zipName); + /// Destroys QuaZip object. + /** Calls close() if necessary. */ + ~QuaZip(); + /// Opens ZIP file. + /** Argument \a ioApi specifies IO function set for ZIP/UNZIP + * package to use. See unzip.h, zip.h and ioapi.h for details. By + * passing NULL (the default) you just tell package to use the + * default API which works just fine on UNIX platforms. I have tried + * it on win32-g++ platform too and it seems it works fine there + * too, so I see no reason to use win32 IO API included in original + * ZIP/UNZIP package. + * + * ZIP archive file name will be converted to 8-bit encoding using + * Qt's QFile::encodeName() function before passing it to the + * ZIP/UNZIP package API. + * + * Returns \c true if successful, \c false otherwise. + * + * Argument \a mode specifies open mode of the ZIP archive. See Mode + * for details. Note that there is zipOpen2() function in the + * ZIP/UNZIP API which accepts \a globalcomment argument, but it + * does not use it anywhere, so this open() function does not have this + * argument. See setComment() if you need to set global comment. + * + * \note ZIP/UNZIP API open calls do not return error code - they + * just return \c NULL indicating an error. But to make things + * easier, quazip.h header defines additional error code \c + * UNZ_ERROROPEN and getZipError() will return it if the open call + * of the ZIP/UNZIP API returns \c NULL. + **/ + bool open(Mode mode, zlib_filefunc_def *ioApi =NULL); + /// Closes ZIP file. + /** Call getZipError() to determine if the close was successful. */ + void close(); + /// Sets the codec used to encode/decode file names inside archive. + /** This is necessary to access files in the ZIP archive created + * under Windows with non-latin characters in file names. For + * example, file names with cyrillic letters will be in \c IBM866 + * encoding. + **/ + void setFileNameCodec(QTextCodec *fileNameCodec) + {this->fileNameCodec=fileNameCodec;} + /// Sets the codec used to encode/decode file names inside archive. + /** \overload + * Equivalent to calling setFileNameCodec(QTextCodec::codecForName(codecName)); + **/ + void setFileNameCodec(const char *fileNameCodecName) + {fileNameCodec=QTextCodec::codecForName(fileNameCodecName);} + /// Returns the codec used to encode/decode comments inside archive. + QTextCodec* getFileNameCodec()const {return fileNameCodec;} + /// Sets the codec used to encode/decode comments inside archive. + /** This codec defaults to locale codec, which is probably ok. + **/ + void setCommentCodec(QTextCodec *commentCodec) + {this->commentCodec=commentCodec;} + /// Sets the codec used to encode/decode comments inside archive. + /** \overload + * Equivalent to calling setCommentCodec(QTextCodec::codecForName(codecName)); + **/ + void setCommentCodec(const char *commentCodecName) + {commentCodec=QTextCodec::codecForName(commentCodecName);} + /// Returns the codec used to encode/decode comments inside archive. + QTextCodec* getCommentCodec()const {return commentCodec;} + /// Returns the name of the ZIP file. + /** Returns null string if no ZIP file name has been set. + * \sa setZipName() + **/ + QString getZipName()const {return zipName;} + /// Sets the name of the ZIP file. + /** Does nothing if the ZIP file is open. + * + * Does not reset error code returned by getZipError(). + **/ + void setZipName(const QString& zipName); + /// Returns the mode in which ZIP file was opened. + Mode getMode()const {return mode;} + /// Returns \c true if ZIP file is open, \c false otherwise. + bool isOpen()const {return mode!=mdNotOpen;} + /// Returns the error code of the last operation. + /** Returns \c UNZ_OK if the last operation was successful. + * + * Error code resets to \c UNZ_OK every time you call any function + * that accesses something inside ZIP archive, even if it is \c + * const (like getEntriesCount()). open() and close() calls reset + * error code too. See documentation for the specific functions for + * details on error detection. + **/ + int getZipError()const {return zipError;} + /// Returns number of the entries in the ZIP central directory. + /** Returns negative error code in the case of error. The same error + * code will be returned by subsequent getZipError() call. + **/ + int getEntriesCount()const; + /// Returns global comment in the ZIP file. + QString getComment()const; + /// Sets global comment in the ZIP file. + /** Comment will be written to the archive on close operation. + * + * \sa open() + **/ + void setComment(const QString& comment) {this->comment=comment;} + /// Sets the current file to the first file in the archive. + /** Returns \c true on success, \c false otherwise. Call + * getZipError() to get the error code. + **/ + bool goToFirstFile(); + /// Sets the current file to the next file in the archive. + /** Returns \c true on success, \c false otherwise. Call + * getZipError() to determine if there was an error. + * + * Should be used only in QuaZip::mdUnzip mode. + * + * \note If the end of file was reached, getZipError() will return + * \c UNZ_OK instead of \c UNZ_END_OF_LIST_OF_FILE. This is to make + * things like this easier: + * \code + * for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) { + * // do something + * } + * if(zip.getZipError()==UNZ_OK) { + * // ok, there was no error + * } + * \endcode + **/ + bool goToNextFile(); + /// Sets current file by its name. + /** Returns \c true if successful, \c false otherwise. Argument \a + * cs specifies case sensitivity of the file name. Call + * getZipError() in the case of a failure to get error code. + * + * This is not a wrapper to unzLocateFile() function. That is + * because I had to implement locale-specific case-insensitive + * comparison. + * + * Here are the differences from the original implementation: + * + * - If the file was not found, error code is \c UNZ_OK, not \c + * UNZ_END_OF_LIST_OF_FILE (see also goToNextFile()). + * - If this function fails, it unsets the current file rather than + * resetting it back to what it was before the call. + * + * If \a fileName is null string then this function unsets the + * current file and return \c true. Note that you should close the + * file first if it is open! See + * QuaZipFile::QuaZipFile(QuaZip*,QObject*) for the details. + * + * Should be used only in QuaZip::mdUnzip mode. + * + * \sa setFileNameCodec(), CaseSensitivity + **/ + bool setCurrentFile(const QString& fileName, CaseSensitivity cs =csDefault); + /// Returns \c true if the current file has been set. + bool hasCurrentFile()const {return hasCurrentFile_f;} + /// Retrieves information about the current file. + /** Fills the structure pointed by \a info. Returns \c true on + * success, \c false otherwise. In the latter case structure pointed + * by \a info remains untouched. If there was an error, + * getZipError() returns error code. + * + * Should be used only in QuaZip::mdUnzip mode. + * + * Does nothing and returns \c false in any of the following cases. + * - ZIP is not open; + * - ZIP does not have current file; + * - \a info is \c NULL; + * + * In all these cases getZipError() returns \c UNZ_OK since there + * is no ZIP/UNZIP API call. + **/ + bool getCurrentFileInfo(QuaZipFileInfo* info)const; + /// Returns the current file name. + /** Equivalent to calling getCurrentFileInfo() and then getting \c + * name field of the QuaZipFileInfo structure, but faster and more + * convenient. + * + * Should be used only in QuaZip::mdUnzip mode. + **/ + QString getCurrentFileName()const; + /// Returns \c unzFile handle. + /** You can use this handle to directly call UNZIP part of the + * ZIP/UNZIP package functions (see unzip.h). + * + * \warning When using the handle returned by this function, please + * keep in mind that QuaZip class is unable to detect any changes + * you make in the ZIP file state (e. g. changing current file, or + * closing the handle). So please do not do anything with this + * handle that is possible to do with the functions of this class. + * Or at least return the handle in the original state before + * calling some another function of this class (including implicit + * destructor calls and calls from the QuaZipFile objects that refer + * to this QuaZip instance!). So if you have changed the current + * file in the ZIP archive - then change it back or you may + * experience some strange behavior or even crashes. + **/ + unzFile getUnzFile() {return unzFile_f;} + /// Returns \c zipFile handle. + /** You can use this handle to directly call ZIP part of the + * ZIP/UNZIP package functions (see zip.h). Warnings about the + * getUnzFile() function also apply to this function. + **/ + zipFile getZipFile() {return zipFile_f;} +}; + +#endif diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/quazip.pro b/plugins/smplayer_plugin/findsubtitles/quazip/quazip.pro new file mode 100644 index 000000000..9340001b5 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/quazip.pro @@ -0,0 +1,43 @@ +###################################################################### +# Automatically generated by qmake (2.00a) Wed Jun 22 16:57:14 2005 +###################################################################### + +TEMPLATE = lib +CONFIG += qt warn_on +QT -= gui +LIBS += -lz +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += crypt.h \ + ioapi.h \ + quazip.h \ + quazipfile.h \ + quazipfileinfo.h \ + quazipnewinfo.h \ + unzip.h \ + zip.h + +SOURCES += ioapi.c \ + quazip.cpp \ + quazipfile.cpp \ + quazipnewinfo.cpp \ + unzip.c \ + zip.c + +unix { + OBJECTS_DIR=.obj + MOC_DIR=.moc +} + +# UNIX installation + +isEmpty(PREFIX): PREFIX=/usr/local + +unix { + headers.path=$$PREFIX/include/quazip + headers.files=$$HEADERS + target.path=$$PREFIX/lib + INSTALLS += headers target +} diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/quazipfile.cpp b/plugins/smplayer_plugin/findsubtitles/quazip/quazipfile.cpp new file mode 100644 index 000000000..0399d1dbd --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/quazipfile.cpp @@ -0,0 +1,377 @@ +/* +-- A kind of "standard" GPL license statement -- +QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package +Copyright (C) 2005-2007 Sergey A. Tachenov + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-- A kind of "standard" GPL license statement ends here -- + +See COPYING file for GPL. + +You are also permitted to use QuaZIP under the terms of LGPL (see +COPYING.LGPL). You are free to choose either license, but please note +that QuaZIP makes use of Qt, which is not licensed under LGPL. So if +you are using Open Source edition of Qt, you therefore MUST use GPL for +your code based on QuaZIP, since it would be also based on Qt in this +case. If you are Qt commercial license owner, then you are free to use +QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. + **/ + +#include "quazipfile.h" + +using namespace std; + +QuaZipFile::QuaZipFile(): + zip(NULL), internal(true), zipError(UNZ_OK) +{ +} + +QuaZipFile::QuaZipFile(QObject *parent): + QIODevice(parent), zip(NULL), internal(true), zipError(UNZ_OK) +{ +} + +QuaZipFile::QuaZipFile(const QString& zipName, QObject *parent): + QIODevice(parent), internal(true), zipError(UNZ_OK) +{ + zip=new QuaZip(zipName); + Q_CHECK_PTR(zip); +} + +QuaZipFile::QuaZipFile(const QString& zipName, const QString& fileName, + QuaZip::CaseSensitivity cs, QObject *parent): + QIODevice(parent), internal(true), zipError(UNZ_OK) +{ + zip=new QuaZip(zipName); + Q_CHECK_PTR(zip); + this->fileName=fileName; + this->caseSensitivity=cs; +} + +QuaZipFile::QuaZipFile(QuaZip *zip, QObject *parent): + QIODevice(parent), + zip(zip), internal(false), + zipError(UNZ_OK) +{ +} + +QuaZipFile::~QuaZipFile() +{ + if(isOpen()) close(); + if(internal) delete zip; +} + +QString QuaZipFile::getZipName()const +{ + return zip==NULL?QString():zip->getZipName(); +} + +QString QuaZipFile::getActualFileName()const +{ + setZipError(UNZ_OK); + if(zip==NULL||(openMode()&WriteOnly)) return QString(); + QString name=zip->getCurrentFileName(); + if(name.isNull()) + setZipError(zip->getZipError()); + return name; +} + +void QuaZipFile::setZipName(const QString& zipName) +{ + if(isOpen()) { + qWarning("QuaZipFile::setZipName(): file is already open - can not set ZIP name"); + return; + } + if(zip!=NULL&&internal) delete zip; + zip=new QuaZip(zipName); + Q_CHECK_PTR(zip); + internal=true; +} + +void QuaZipFile::setZip(QuaZip *zip) +{ + if(isOpen()) { + qWarning("QuaZipFile::setZip(): file is already open - can not set ZIP"); + return; + } + if(this->zip!=NULL&&internal) delete this->zip; + this->zip=zip; + this->fileName=QString(); + internal=false; +} + +void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs) +{ + if(zip==NULL) { + qWarning("QuaZipFile::setFileName(): call setZipName() first"); + return; + } + if(!internal) { + qWarning("QuaZipFile::setFileName(): should not be used when not using internal QuaZip"); + return; + } + if(isOpen()) { + qWarning("QuaZipFile::setFileName(): can not set file name for already opened file"); + return; + } + this->fileName=fileName; + this->caseSensitivity=cs; +} + +void QuaZipFile::setZipError(int zipError)const +{ + QuaZipFile *fakeThis=(QuaZipFile*)this; // non-const + fakeThis->zipError=zipError; + if(zipError==UNZ_OK) + fakeThis->setErrorString(QString()); + else + fakeThis->setErrorString(tr("ZIP/UNZIP API error %1").arg(zipError)); +} + +bool QuaZipFile::open(OpenMode mode) +{ + return open(mode, NULL); +} + +bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password) +{ + resetZipError(); + if(isOpen()) { + qWarning("QuaZipFile::open(): already opened"); + return false; + } + if(mode&Unbuffered) { + qWarning("QuaZipFile::open(): Unbuffered mode is not supported"); + return false; + } + if((mode&ReadOnly)&&!(mode&WriteOnly)) { + if(internal) { + if(!zip->open(QuaZip::mdUnzip)) { + setZipError(zip->getZipError()); + return false; + } + if(!zip->setCurrentFile(fileName, caseSensitivity)) { + setZipError(zip->getZipError()); + zip->close(); + return false; + } + } else { + if(zip==NULL) { + qWarning("QuaZipFile::open(): zip is NULL"); + return false; + } + if(zip->getMode()!=QuaZip::mdUnzip) { + qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", + (int)mode, (int)zip->getMode()); + return false; + } + if(!zip->hasCurrentFile()) { + qWarning("QuaZipFile::open(): zip does not have current file"); + return false; + } + } + setZipError(unzOpenCurrentFile3(zip->getUnzFile(), method, level, (int)raw, password)); + if(zipError==UNZ_OK) { + setOpenMode(mode); + this->raw=raw; + return true; + } else + return false; + } + qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode); + return false; +} + +bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info, + const char *password, quint32 crc, + int method, int level, bool raw, + int windowBits, int memLevel, int strategy) +{ + zip_fileinfo info_z; + resetZipError(); + if(isOpen()) { + qWarning("QuaZipFile::open(): already opened"); + return false; + } + if((mode&WriteOnly)&&!(mode&ReadOnly)) { + if(internal) { + qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach"); + return false; + } + if(zip==NULL) { + qWarning("QuaZipFile::open(): zip is NULL"); + return false; + } + if(zip->getMode()!=QuaZip::mdCreate&&zip->getMode()!=QuaZip::mdAppend&&zip->getMode()!=QuaZip::mdAdd) { + qWarning("QuaZipFile::open(): file open mode %d incompatible with ZIP open mode %d", + (int)mode, (int)zip->getMode()); + return false; + } + info_z.tmz_date.tm_year=info.dateTime.date().year(); + info_z.tmz_date.tm_mon=info.dateTime.date().month() - 1; + info_z.tmz_date.tm_mday=info.dateTime.date().day(); + info_z.tmz_date.tm_hour=info.dateTime.time().hour(); + info_z.tmz_date.tm_min=info.dateTime.time().minute(); + info_z.tmz_date.tm_sec=info.dateTime.time().second(); + info_z.dosDate = 0; + info_z.internal_fa=(uLong)info.internalAttr; + info_z.external_fa=(uLong)info.externalAttr; + setZipError(zipOpenNewFileInZip3(zip->getZipFile(), + zip->getFileNameCodec()->fromUnicode(info.name).constData(), &info_z, + info.extraLocal.constData(), info.extraLocal.length(), + info.extraGlobal.constData(), info.extraGlobal.length(), + zip->getCommentCodec()->fromUnicode(info.comment).constData(), + method, level, (int)raw, + windowBits, memLevel, strategy, + password, (uLong)crc)); + if(zipError==UNZ_OK) { + writePos=0; + setOpenMode(mode); + this->raw=raw; + if(raw) { + this->crc=crc; + this->uncompressedSize=info.uncompressedSize; + } + return true; + } else + return false; + } + qWarning("QuaZipFile::open(): open mode %d not supported by this function", (int)mode); + return false; +} + +bool QuaZipFile::isSequential()const +{ + return true; +} + +qint64 QuaZipFile::pos()const +{ + if(zip==NULL) { + qWarning("QuaZipFile::pos(): call setZipName() or setZip() first"); + return -1; + } + if(!isOpen()) { + qWarning("QuaZipFile::pos(): file is not open"); + return -1; + } + if(openMode()&ReadOnly) + return unztell(zip->getUnzFile()); + else + return writePos; +} + +bool QuaZipFile::atEnd()const +{ + if(zip==NULL) { + qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first"); + return false; + } + if(!isOpen()) { + qWarning("QuaZipFile::atEnd(): file is not open"); + return false; + } + if(openMode()&ReadOnly) + return unzeof(zip->getUnzFile())==1; + else + return true; +} + +qint64 QuaZipFile::size()const +{ + if(!isOpen()) { + qWarning("QuaZipFile::atEnd(): file is not open"); + return -1; + } + if(openMode()&ReadOnly) + return raw?csize():usize(); + else + return writePos; +} + +qint64 QuaZipFile::csize()const +{ + unz_file_info info_z; + setZipError(UNZ_OK); + if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1; + setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); + if(zipError!=UNZ_OK) + return -1; + return info_z.compressed_size; +} + +qint64 QuaZipFile::usize()const +{ + unz_file_info info_z; + setZipError(UNZ_OK); + if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return -1; + setZipError(unzGetCurrentFileInfo(zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); + if(zipError!=UNZ_OK) + return -1; + return info_z.uncompressed_size; +} + +bool QuaZipFile::getFileInfo(QuaZipFileInfo *info) +{ + if(zip==NULL||zip->getMode()!=QuaZip::mdUnzip) return false; + zip->getCurrentFileInfo(info); + setZipError(zip->getZipError()); + return zipError==UNZ_OK; +} + +void QuaZipFile::close() +{ + resetZipError(); + if(zip==NULL||!zip->isOpen()) return; + if(!isOpen()) { + qWarning("QuaZipFile::close(): file isn't open"); + return; + } + if(openMode()&ReadOnly) + setZipError(unzCloseCurrentFile(zip->getUnzFile())); + else if(openMode()&WriteOnly) + if(isRaw()) setZipError(zipCloseFileInZipRaw(zip->getZipFile(), uncompressedSize, crc)); + else setZipError(zipCloseFileInZip(zip->getZipFile())); + else { + qWarning("Wrong open mode: %d", (int)openMode()); + return; + } + if(zipError==UNZ_OK) setOpenMode(QIODevice::NotOpen); + else return; + if(internal) { + zip->close(); + setZipError(zip->getZipError()); + } +} + +qint64 QuaZipFile::readData(char *data, qint64 maxSize) +{ + setZipError(UNZ_OK); + qint64 bytesRead=unzReadCurrentFile(zip->getUnzFile(), data, (unsigned)maxSize); + if(bytesRead<0) setZipError((int)bytesRead); + return bytesRead; +} + +qint64 QuaZipFile::writeData(const char* data, qint64 maxSize) +{ + setZipError(ZIP_OK); + setZipError(zipWriteInFileInZip(zip->getZipFile(), data, (uint)maxSize)); + if(zipError!=ZIP_OK) return -1; + else { + writePos+=maxSize; + return maxSize; + } +} diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/quazipfile.h b/plugins/smplayer_plugin/findsubtitles/quazip/quazipfile.h new file mode 100644 index 000000000..09af5bcec --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/quazipfile.h @@ -0,0 +1,442 @@ +#ifndef QUA_ZIPFILE_H +#define QUA_ZIPFILE_H + +/* +-- A kind of "standard" GPL license statement -- +QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package +Copyright (C) 2005-2008 Sergey A. Tachenov + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-- A kind of "standard" GPL license statement ends here -- + +See COPYING file for GPL. + +You are also permitted to use QuaZIP under the terms of LGPL (see +COPYING.LGPL). You are free to choose either license, but please note +that QuaZIP makes use of Qt, which is not licensed under LGPL. So if +you are using Open Source edition of Qt, you therefore MUST use GPL for +your code based on QuaZIP, since it would be also based on Qt in this +case. If you are Qt commercial license owner, then you are free to use +QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. + **/ + +#include + +#include "quazip.h" +#include "quazipnewinfo.h" + +/// A file inside ZIP archive. +/** \class QuaZipFile quazipfile.h + * This is the most interesting class. Not only it provides C++ + * interface to the ZIP/UNZIP package, but also integrates it with Qt by + * subclassing QIODevice. This makes possible to access files inside ZIP + * archive using QTextStream or QDataStream, for example. Actually, this + * is the main purpose of the whole QuaZIP library. + * + * You can either use existing QuaZip instance to create instance of + * this class or pass ZIP archive file name to this class, in which case + * it will create internal QuaZip object. See constructors' descriptions + * for details. Writing is only possible with the existing instance. + * + * \section quazipfile-sequential Sequential or random-access? + * + * At the first thought, QuaZipFile has fixed size, the start and the + * end and should be therefore considered random-access device. But + * there is one major obstacle to making it random-access: ZIP/UNZIP API + * does not support seek() operation and the only way to implement it is + * through reopening the file and re-reading to the required position, + * but this is prohibitely slow. + * + * Therefore, QuaZipFile is considered to be a sequential device. This + * has advantage of availability of the ungetChar() operation (QIODevice + * does not implement it properly for non-sequential devices unless they + * support seek()). Disadvantage is a somewhat strange behaviour of the + * size() and pos() functions. This should be kept in mind while using + * this class. + * + **/ +class QuaZipFile: public QIODevice { + Q_OBJECT + private: + QuaZip *zip; + QString fileName; + QuaZip::CaseSensitivity caseSensitivity; + bool raw; + qint64 writePos; + // these two are for writing raw files + ulong uncompressedSize; + quint32 crc; + bool internal; + int zipError; + // these are not supported nor implemented + QuaZipFile(const QuaZipFile& that); + QuaZipFile& operator=(const QuaZipFile& that); + void resetZipError()const {setZipError(UNZ_OK);} + // const, but sets zipError! + void setZipError(int zipError)const; + protected: + /// Implementation of the QIODevice::readData(). + qint64 readData(char *data, qint64 maxSize); + /// Implementation of the QIODevice::writeData(). + qint64 writeData(const char *data, qint64 maxSize); + public: + /// Constructs a QuaZipFile instance. + /** You should use setZipName() and setFileName() or setZip() before + * trying to call open() on the constructed object. + **/ + QuaZipFile(); + /// Constructs a QuaZipFile instance. + /** \a parent argument specifies this object's parent object. + * + * You should use setZipName() and setFileName() or setZip() before + * trying to call open() on the constructed object. + **/ + QuaZipFile(QObject *parent); + /// Constructs a QuaZipFile instance. + /** \a parent argument specifies this object's parent object and \a + * zipName specifies ZIP archive file name. + * + * You should use setFileName() before trying to call open() on the + * constructed object. + * + * QuaZipFile constructed by this constructor can be used for read + * only access. Use QuaZipFile(QuaZip*,QObject*) for writing. + **/ + QuaZipFile(const QString& zipName, QObject *parent =NULL); + /// Constructs a QuaZipFile instance. + /** \a parent argument specifies this object's parent object, \a + * zipName specifies ZIP archive file name and \a fileName and \a cs + * specify a name of the file to open inside archive. + * + * QuaZipFile constructed by this constructor can be used for read + * only access. Use QuaZipFile(QuaZip*,QObject*) for writing. + * + * \sa QuaZip::setCurrentFile() + **/ + QuaZipFile(const QString& zipName, const QString& fileName, + QuaZip::CaseSensitivity cs =QuaZip::csDefault, QObject *parent =NULL); + /// Constructs a QuaZipFile instance. + /** \a parent argument specifies this object's parent object. + * + * \a zip is the pointer to the existing QuaZip object. This + * QuaZipFile object then can be used to read current file in the + * \a zip or to write to the file inside it. + * + * \warning Using this constructor for reading current file can be + * tricky. Let's take the following example: + * \code + * QuaZip zip("archive.zip"); + * zip.open(QuaZip::mdUnzip); + * zip.setCurrentFile("file-in-archive"); + * QuaZipFile file(&zip); + * file.open(QIODevice::ReadOnly); + * // ok, now we can read from the file + * file.read(somewhere, some); + * zip.setCurrentFile("another-file-in-archive"); // oops... + * QuaZipFile anotherFile(&zip); + * anotherFile.open(QIODevice::ReadOnly); + * anotherFile.read(somewhere, some); // this is still ok... + * file.read(somewhere, some); // and this is NOT + * \endcode + * So, what exactly happens here? When we change current file in the + * \c zip archive, \c file that references it becomes invalid + * (actually, as far as I understand ZIP/UNZIP sources, it becomes + * closed, but QuaZipFile has no means to detect it). + * + * Summary: do not close \c zip object or change its current file as + * long as QuaZipFile is open. Even better - use another constructors + * which create internal QuaZip instances, one per object, and + * therefore do not cause unnecessary trouble. This constructor may + * be useful, though, if you already have a QuaZip instance and do + * not want to access several files at once. Good example: + * \code + * QuaZip zip("archive.zip"); + * zip.open(QuaZip::mdUnzip); + * // first, we need some information about archive itself + * QByteArray comment=zip.getComment(); + * // and now we are going to access files inside it + * QuaZipFile file(&zip); + * for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) { + * file.open(QIODevice::ReadOnly); + * // do something cool with file here + * file.close(); // do not forget to close! + * } + * zip.close(); + * \endcode + **/ + QuaZipFile(QuaZip *zip, QObject *parent =NULL); + /// Destroys a QuaZipFile instance. + /** Closes file if open, destructs internal QuaZip object (if it + * exists and \em is internal, of course). + **/ + virtual ~QuaZipFile(); + /// Returns the ZIP archive file name. + /** If this object was created by passing QuaZip pointer to the + * constructor, this function will return that QuaZip's file name + * (or null string if that object does not have file name yet). + * + * Otherwise, returns associated ZIP archive file name or null + * string if there are no name set yet. + * + * \sa setZipName() getFileName() + **/ + QString getZipName()const; + /// Returns a pointer to the associated QuaZip object. + /** Returns \c NULL if there is no associated QuaZip or it is + * internal (so you will not mess with it). + **/ + QuaZip* getZip()const; + /// Returns file name. + /** This function returns file name you passed to this object either + * by using + * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*) + * or by calling setFileName(). Real name of the file may differ in + * case if you used case-insensitivity. + * + * Returns null string if there is no file name set yet. This is the + * case when this QuaZipFile operates on the existing QuaZip object + * (constructor QuaZipFile(QuaZip*,QObject*) or setZip() was used). + * + * \sa getActualFileName + **/ + QString getFileName()const {return fileName;} + /// Returns case sensitivity of the file name. + /** This function returns case sensitivity argument you passed to + * this object either by using + * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*) + * or by calling setFileName(). + * + * Returns unpredictable value if getFileName() returns null string + * (this is the case when you did not used setFileName() or + * constructor above). + * + * \sa getFileName + **/ + QuaZip::CaseSensitivity getCaseSensitivity()const {return caseSensitivity;} + /// Returns the actual file name in the archive. + /** This is \em not a ZIP archive file name, but a name of file inside + * archive. It is not necessary the same name that you have passed + * to the + * QuaZipFile(const QString&,const QString&,QuaZip::CaseSensitivity,QObject*), + * setFileName() or QuaZip::setCurrentFile() - this is the real file + * name inside archive, so it may differ in case if the file name + * search was case-insensitive. + * + * Equivalent to calling getCurrentFileName() on the associated + * QuaZip object. Returns null string if there is no associated + * QuaZip object or if it does not have a current file yet. And this + * is the case if you called setFileName() but did not open the + * file yet. So this is perfectly fine: + * \code + * QuaZipFile file("somezip.zip"); + * file.setFileName("somefile"); + * QString name=file.getName(); // name=="somefile" + * QString actual=file.getActualFileName(); // actual is null string + * file.open(QIODevice::ReadOnly); + * QString actual=file.getActualFileName(); // actual can be "SoMeFiLe" on Windows + * \endcode + * + * \sa getZipName(), getFileName(), QuaZip::CaseSensitivity + **/ + QString getActualFileName()const; + /// Sets the ZIP archive file name. + /** Automatically creates internal QuaZip object and destroys + * previously created internal QuaZip object, if any. + * + * Will do nothing if this file is already open. You must close() it + * first. + **/ + void setZipName(const QString& zipName); + /// Returns \c true if the file was opened in raw mode. + /** If the file is not open, the returned value is undefined. + * + * \sa open(OpenMode,int*,int*,bool,const char*) + **/ + bool isRaw()const {return raw;} + /// Binds to the existing QuaZip instance. + /** This function destroys internal QuaZip object, if any, and makes + * this QuaZipFile to use current file in the \a zip object for any + * further operations. See QuaZipFile(QuaZip*,QObject*) for the + * possible pitfalls. + * + * Will do nothing if the file is currently open. You must close() + * it first. + **/ + void setZip(QuaZip *zip); + /// Sets the file name. + /** Will do nothing if at least one of the following conditions is + * met: + * - ZIP name has not been set yet (getZipName() returns null + * string). + * - This QuaZipFile is associated with external QuaZip. In this + * case you should call that QuaZip's setCurrentFile() function + * instead! + * - File is already open so setting the name is meaningless. + * + * \sa QuaZip::setCurrentFile + **/ + void setFileName(const QString& fileName, QuaZip::CaseSensitivity cs =QuaZip::csDefault); + /// Opens a file for reading. + /** Returns \c true on success, \c false otherwise. + * Call getZipError() to get error code. + * + * \note Since ZIP/UNZIP API provides buffered reading only, + * QuaZipFile does not support unbuffered reading. So do not pass + * QIODevice::Unbuffered flag in \a mode, or open will fail. + **/ + virtual bool open(OpenMode mode); + /// Opens a file for reading. + /** \overload + * Argument \a password specifies a password to decrypt the file. If + * it is NULL then this function behaves just like open(OpenMode). + **/ + bool open(OpenMode mode, const char *password) + {return open(mode, NULL, NULL, false, password);} + /// Opens a file for reading. + /** \overload + * Argument \a password specifies a password to decrypt the file. + * + * An integers pointed by \a method and \a level will receive codes + * of the compression method and level used. See unzip.h. + * + * If raw is \c true then no decompression is performed. + * + * \a method should not be \c NULL. \a level can be \c NULL if you + * don't want to know the compression level. + **/ + bool open(OpenMode mode, int *method, int *level, bool raw, const char *password =NULL); + /// Opens a file for writing. + /** \a info argument specifies information about file. It should at + * least specify a correct file name. Also, it is a good idea to + * specify correct timestamp (by default, current time will be + * used). See QuaZipNewInfo. + * + * Arguments \a password and \a crc provide necessary information + * for crypting. Note that you should specify both of them if you + * need crypting. If you do not, pass \c NULL as password, but you + * still need to specify \a crc if you are going to use raw mode + * (see below). + * + * Arguments \a method and \a level specify compression method and + * level. + * + * If \a raw is \c true, no compression is performed. In this case, + * \a crc and uncompressedSize field of the \a info are required. + * + * Arguments \a windowBits, \a memLevel, \a strategy provide zlib + * algorithms tuning. See deflateInit2() in zlib. + **/ + bool open(OpenMode mode, const QuaZipNewInfo& info, + const char *password =NULL, quint32 crc =0, + int method =Z_DEFLATED, int level =Z_DEFAULT_COMPRESSION, bool raw =false, + int windowBits =-MAX_WBITS, int memLevel =DEF_MEM_LEVEL, int strategy =Z_DEFAULT_STRATEGY); + /// Returns \c true, but \ref quazipfile-sequential "beware"! + virtual bool isSequential()const; + /// Returns current position in the file. + /** Implementation of the QIODevice::pos(). When reading, this + * function is a wrapper to the ZIP/UNZIP unztell(), therefore it is + * unable to keep track of the ungetChar() calls (which is + * non-virtual and therefore is dangerous to reimplement). So if you + * are using ungetChar() feature of the QIODevice, this function + * reports incorrect value until you get back characters which you + * ungot. + * + * When writing, pos() returns number of bytes already written + * (uncompressed unless you use raw mode). + * + * \note Although + * \ref quazipfile-sequential "QuaZipFile is a sequential device" + * and therefore pos() should always return zero, it does not, + * because it would be misguiding. Keep this in mind. + * + * This function returns -1 if the file or archive is not open. + * + * Error code returned by getZipError() is not affected by this + * function call. + **/ + virtual qint64 pos()const; + /// Returns \c true if the end of file was reached. + /** This function returns \c false in the case of error. This means + * that you called this function on either not open file, or a file + * in the not open archive or even on a QuaZipFile instance that + * does not even have QuaZip instance associated. Do not do that + * because there is no means to determine whether \c false is + * returned because of error or because end of file was reached. + * Well, on the other side you may interpret \c false return value + * as "there is no file open to check for end of file and there is + * no end of file therefore". + * + * When writing, this function always returns \c true (because you + * are always writing to the end of file). + * + * Error code returned by getZipError() is not affected by this + * function call. + **/ + virtual bool atEnd()const; + /// Returns file size. + /** This function returns csize() if the file is open for reading in + * raw mode, usize() if it is open for reading in normal mode and + * pos() if it is open for writing. + * + * Returns -1 on error, call getZipError() to get error code. + * + * \note This function returns file size despite that + * \ref quazipfile-sequential "QuaZipFile is considered to be sequential device", + * for which size() should return bytesAvailable() instead. But its + * name would be very misguiding otherwise, so just keep in mind + * this inconsistence. + **/ + virtual qint64 size()const; + /// Returns compressed file size. + /** Equivalent to calling getFileInfo() and then getting + * compressedSize field, but more convenient and faster. + * + * File must be open for reading before calling this function. + * + * Returns -1 on error, call getZipError() to get error code. + **/ + qint64 csize()const; + /// Returns uncompressed file size. + /** Equivalent to calling getFileInfo() and then getting + * uncompressedSize field, but more convenient and faster. See + * getFileInfo() for a warning. + * + * File must be open for reading before calling this function. + * + * Returns -1 on error, call getZipError() to get error code. + **/ + qint64 usize()const; + /// Gets information about current file. + /** This function does the same thing as calling + * QuaZip::getCurrentFileInfo() on the associated QuaZip object, + * but you can not call getCurrentFileInfo() if the associated + * QuaZip is internal (because you do not have access to it), while + * you still can call this function in that case. + * + * File must be open for reading before calling this function. + * + * Returns \c false in the case of an error. + **/ + bool getFileInfo(QuaZipFileInfo *info); + /// Closes the file. + /** Call getZipError() to determine if the close was successful. + **/ + virtual void close(); + /// Returns the error code returned by the last ZIP/UNZIP API call. + int getZipError()const {return zipError;} +}; + +#endif diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/quazipfileinfo.h b/plugins/smplayer_plugin/findsubtitles/quazip/quazipfileinfo.h new file mode 100644 index 000000000..3216d776d --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/quazipfileinfo.h @@ -0,0 +1,73 @@ +#ifndef QUA_ZIPFILEINFO_H +#define QUA_ZIPFILEINFO_H + +/* +-- A kind of "standard" GPL license statement -- +QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package +Copyright (C) 2005-2007 Sergey A. Tachenov + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-- A kind of "standard" GPL license statement ends here -- + +See COPYING file for GPL. + +You are also permitted to use QuaZIP under the terms of LGPL (see +COPYING.LGPL). You are free to choose either license, but please note +that QuaZIP makes use of Qt, which is not licensed under LGPL. So if +you are using Open Source edition of Qt, you therefore MUST use GPL for +your code based on QuaZIP, since it would be also based on Qt in this +case. If you are Qt commercial license owner, then you are free to use +QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. + **/ + +#include +#include + +/// Information about a file inside archive. +/** Call QuaZip::getCurrentFileInfo() or QuaZipFile::getFileInfo() to + * fill this structure. */ +struct QuaZipFileInfo { + /// File name. + QString name; + /// Version created by. + quint16 versionCreated; + /// Version needed to extract. + quint16 versionNeeded; + /// General purpose flags. + quint16 flags; + /// Compression method. + quint16 method; + /// Last modification date and time. + QDateTime dateTime; + /// CRC. + quint32 crc; + /// Compressed file size. + quint32 compressedSize; + /// Uncompressed file size. + quint32 uncompressedSize; + /// Disk number start. + quint16 diskNumberStart; + /// Internal file attributes. + quint16 internalAttr; + /// External file attributes. + quint32 externalAttr; + /// Comment. + QString comment; + /// Extra field. + QByteArray extra; +}; + +#endif diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/quazipnewinfo.cpp b/plugins/smplayer_plugin/findsubtitles/quazip/quazipnewinfo.cpp new file mode 100644 index 000000000..17571f2fc --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/quazipnewinfo.cpp @@ -0,0 +1,59 @@ +/* -- A kind of "standard" GPL license statement -- +QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package +Copyright (C) 2005-2007 Sergey A. Tachenov + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-- A kind of "standard" GPL license statement ends here -- + +See COPYING file for GPL. + +You are also permitted to use QuaZIP under the terms of LGPL (see +COPYING.LGPL). You are free to choose either license, but please note +that QuaZIP makes use of Qt, which is not licensed under LGPL. So if +you are using Open Source edition of Qt, you therefore MUST use GPL for +your code based on QuaZIP, since it would be also based on Qt in this +case. If you are Qt commercial license owner, then you are free to use +QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. +*/ + +#include + +#include "quazipnewinfo.h" + + +QuaZipNewInfo::QuaZipNewInfo(const QString& name): + name(name), dateTime(QDateTime::currentDateTime()), internalAttr(0), externalAttr(0) +{ +} + +QuaZipNewInfo::QuaZipNewInfo(const QString& name, const QString& file): + name(name), internalAttr(0), externalAttr(0) +{ + QFileInfo info(file); + QDateTime lm = info.lastModified(); + if (!info.exists()) + dateTime = QDateTime::currentDateTime(); + else + dateTime = lm; +} + +void QuaZipNewInfo::setFileDateTime(const QString& file) +{ + QFileInfo info(file); + QDateTime lm = info.lastModified(); + if (info.exists()) + dateTime = lm; +} diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/quazipnewinfo.h b/plugins/smplayer_plugin/findsubtitles/quazip/quazipnewinfo.h new file mode 100644 index 000000000..93ff1a2fc --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/quazipnewinfo.h @@ -0,0 +1,109 @@ +#ifndef QUA_ZIPNEWINFO_H +#define QUA_ZIPNEWINFO_H + +/* +-- A kind of "standard" GPL license statement -- +QuaZIP - a Qt/C++ wrapper for the ZIP/UNZIP package +Copyright (C) 2005-2007 Sergey A. Tachenov + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-- A kind of "standard" GPL license statement ends here -- + +See COPYING file for GPL. + +You are also permitted to use QuaZIP under the terms of LGPL (see +COPYING.LGPL). You are free to choose either license, but please note +that QuaZIP makes use of Qt, which is not licensed under LGPL. So if +you are using Open Source edition of Qt, you therefore MUST use GPL for +your code based on QuaZIP, since it would be also based on Qt in this +case. If you are Qt commercial license owner, then you are free to use +QuaZIP as long as you respect either GPL or LGPL for QuaZIP code. + **/ + +#include +#include + +/// Information about a file to be created. +/** This structure holds information about a file to be created inside + * ZIP archive. At least name should be set to something correct before + * passing this structure to + * QuaZipFile::open(OpenMode,const QuaZipNewInfo&,int,int,bool). + **/ +struct QuaZipNewInfo { + /// File name. + /** This field holds file name inside archive, including path relative + * to archive root. + **/ + QString name; + /// File timestamp. + /** This is the last file modification date and time. Will be stored + * in the archive central directory. It is a good practice to set it + * to the source file timestamp instead of archive creating time. Use + * setFileDateTime() or QuaZipNewInfo(const QString&, const QString&). + **/ + QDateTime dateTime; + /// File internal attributes. + quint16 internalAttr; + /// File external attributes. + quint32 externalAttr; + /// File comment. + /** Will be encoded using QuaZip::getCommentCodec(). + **/ + QString comment; + /// File local extra field. + QByteArray extraLocal; + /// File global extra field. + QByteArray extraGlobal; + /// Uncompressed file size. + /** This is only needed if you are using raw file zipping mode, i. e. + * adding precompressed file in the zip archive. + **/ + ulong uncompressedSize; + /// Constructs QuaZipNewInfo instance. + /** Initializes name with \a name, dateTime with current date and + * time. Attributes are initialized with zeros, comment and extra + * field with null values. + **/ + QuaZipNewInfo(const QString& name); + /// Constructs QuaZipNewInfo instance. + /** Initializes name with \a name and dateTime with timestamp of the + * file named \a file. If the \a file does not exists or its timestamp + * is inaccessible (e. g. you do not have read permission for the + * directory file in), uses current date and time. Attributes are + * initialized with zeros, comment and extra field with null values. + * + * \sa setFileDateTime() + **/ + QuaZipNewInfo(const QString& name, const QString& file); + /// Sets the file timestamp from the existing file. + /** Use this function to set the file timestamp from the existing + * file. Use it like this: + * \code + * QuaZipFile zipFile(&zip); + * QFile file("file-to-add"); + * file.open(QIODevice::ReadOnly); + * QuaZipNewInfo info("file-name-in-archive"); + * info.setFileDateTime("file-to-add"); // take the timestamp from file + * zipFile.open(QIODevice::WriteOnly, info); + * \endcode + * + * This function does not change dateTime if some error occured (e. g. + * file is inaccessible). + **/ + void setFileDateTime(const QString& file); +}; + +#endif diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/unzip.c b/plugins/smplayer_plugin/findsubtitles/quazip/unzip.c new file mode 100644 index 000000000..ace7a0883 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/unzip.c @@ -0,0 +1,1601 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + Read unzip.h for more info +*/ + +/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of +compatibility with older software. The following is from the original crypt.c. Code +woven in by Terry Thorsen 1/2003. +*/ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + */ + +/* + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + */ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) + const char *path; + zlib_filefunc_def* pzlib_filefunc_def; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&us.z_filefunc); + else + us.z_filefunc = *pzlib_filefunc_def; + + us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + if (ZSEEK(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (ZSEEK(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info cur_file_infoSaved; + unz_file_info_internal cur_file_info_internalSaved; + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; // offset in file + uLong num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) + unzFile file; + int* method; + int* level; + int raw; + const char* password; +{ + int err=UNZ_OK; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_DEFLATED) && + (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (file, password) + unzFile file; + const char* password; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) + unzFile file; + int* method; + int* level; + int raw; +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern uLong ZEXPORT unzGetOffset (file) + unzFile file; +{ + unz_s* s; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern int ZEXPORT unzSetOffset (file, pos) + unzFile file; + uLong pos; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/unzip.h b/plugins/smplayer_plugin/findsubtitles/quazip/unzip.h new file mode 100644 index 000000000..b247937c8 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/unzip.h @@ -0,0 +1,354 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/zip.c b/plugins/smplayer_plugin/findsubtitles/quazip/zip.c new file mode 100644 index 000000000..13463fe33 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/zip.c @@ -0,0 +1,1221 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.01e, February 12th, 2005 + + 27 Dec 2004 Rolf Kalbermatter + Modification to zipOpen2 to support globalComment retrieval. + + Copyright (C) 1998-2005 Gilles Vollant + + Read zip.h for more info +*/ + + +#include +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] = + " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignement */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + uLong pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralheader; /* size of the central header for cur file */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int encrypt; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; + int crypt_header_size; +#endif +} curfile_info; + +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile_info ci; /* info on the file curretly writing */ + + uLong begin_pos; /* position of the beginning of the zipfile */ + uLong add_position_when_writting_offset; + uLong number_entry; +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif +} zip_internal; + + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(ldi) + linkedlist_datablock_internal* ldi; +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(ll) + linkedlist_data* ll; +{ + ll->first_block = ll->last_block = NULL; +} + +#if 0 // unused +local void free_linkedlist(ll) + linkedlist_data* ll; +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} +#endif + +local int add_data_in_datablock(ll,buf,len) + linkedlist_data* ll; + const void* buf; + uLong len; +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;ifilled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== + Inputs a long in LSB order to the given file + nbByte == 1, 2 or 4 (byte, short or long) +*/ + +local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, uLong x, int nbByte)); +local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong x; + int nbByte; +{ + unsigned char buf[4]; + int n; + for (n = 0; n < nbByte; n++) + { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) + { /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } + + if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte)); +local void ziplocal_putValue_inmemory (dest, x, nbByte) + void* dest; + uLong x; + int nbByte; +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) + { /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } +} + +/****************************************************************************/ + + +local uLong ziplocal_TmzDateToDosDate(ptm,dosDate) + const tm_zip* ptm; + uLong dosDate; +{ + (void) dosDate; /* avoid "unused parameter" warning */ + uLong year = (uLong)ptm->tm_year; + if (year>1980) + year-=1980; + else if (year>80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int ziplocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return ZIP_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return ZIP_ERRNO; + else + return ZIP_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int ziplocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int ziplocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong ziplocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + +/************************************************************/ +extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def) + const char *pathname; + int append; + zipcharpc* globalcomment; + zlib_filefunc_def* pzlib_filefunc_def; +{ + zip_internal ziinit; + zip_internal* zi; + int err=ZIP_OK; + + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&ziinit.z_filefunc); + else + ziinit.z_filefunc = *pzlib_filefunc_def; + + ziinit.filestream = (*(ziinit.z_filefunc.zopen_file)) + (ziinit.z_filefunc.opaque, + pathname, + (append == APPEND_STATUS_CREATE) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + + if (ziinit.filestream == NULL) + return NULL; + ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writting_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + + zi = (zip_internal*)ALLOC(sizeof(zip_internal)); + if (zi==NULL) + { + ZCLOSE(ziinit.z_filefunc,ziinit.filestream); + return NULL; + } + + /* now we add file in a zipfile */ +# ifndef NO_ADDFILEINEXISTINGZIP + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) + { + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory */ + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry; + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + uLong size_comment; + + central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream); + if (central_pos==0) + err=ZIP_ERRNO; + + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((number_entry_CD!=number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* zipfile global comment length */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((central_pos0) + { + ziinit.globalcomment = ALLOC(size_comment+1); + if (ziinit.globalcomment) + { + size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment); + ziinit.globalcomment[size_comment]=0; + } + } + + byte_before_the_zipfile = central_pos - + (offset_central_dir+size_central_dir); + ziinit.add_position_when_writting_offset = byte_before_the_zipfile; + + { + uLong size_central_dir_to_read = size_central_dir; + size_t buf_size = SIZEDATA_INDATABLOCK; + void* buf_read = (void*)ALLOC(buf_size); + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir + byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + while ((size_central_dir_to_read>0) && (err==ZIP_OK)) + { + uLong read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this) + err=ZIP_ERRNO; + + if (err==ZIP_OK) + err = add_data_in_datablock(&ziinit.central_dir,buf_read, + (uLong)read_this); + size_central_dir_to_read-=read_this; + } + TRYFREE(buf_read); + } + ziinit.begin_pos = byte_before_the_zipfile; + ziinit.number_entry = number_entry_CD; + + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + } + + if (globalcomment) + { + *globalcomment = ziinit.globalcomment; + } +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + + if (err != ZIP_OK) + { +# ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + TRYFREE(zi); + return NULL; + } + else + { + *zi = ziinit; + return (zipFile)zi; + } +} + +extern zipFile ZEXPORT zipOpen (pathname, append) + const char *pathname; + int append; +{ + return zipOpen2(pathname,append,NULL,NULL); +} + +extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; + int raw; + int windowBits; + int memLevel; + int strategy; + const char* password; + uLong crcForCrypting; +{ + zip_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + +# ifdef NOCRYPT + if (password != NULL) + return ZIP_PARAMERROR; +# endif + + if (file == NULL) + return ZIP_PARAMERROR; + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; + + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); + } + + zi->ci.flag = 0; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if ((level==2)) + zi->ci.flag |= 4; + if ((level==1)) + zi->ci.flag |= 6; + if (password != NULL) + zi->ci.flag |= 1; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.encrypt = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ; + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + + size_extrafield_global + size_comment; + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); + + ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); + ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4); + + for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(comment+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + /* write the local header */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2); + + if ((err==ZIP_OK) && (size_filename>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) + err = ZIP_ERRNO; + + if ((err==ZIP_OK) && (size_extrafield_local>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local) + !=size_extrafield_local) + err = ZIP_ERRNO; + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + if (windowBits>0) + windowBits = -windowBits; + + err = deflateInit2(&zi->ci.stream, level, + Z_DEFLATED, windowBits, memLevel, strategy); + + if (err==Z_OK) + zi->ci.stream_initialised = 1; + } +# ifndef NOCRYPT + zi->ci.crypt_header_size = 0; + if ((err==Z_OK) && (password != NULL)) + { + unsigned char bufHead[RAND_HEAD_LEN]; + unsigned int sizeHead; + zi->ci.encrypt = 1; + zi->ci.pcrc_32_tab = get_crc_table(); + /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ + + sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); + zi->ci.crypt_header_size = sizeHead; + + if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) + err = ZIP_ERRNO; + } +# endif + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; + int raw; +{ + return zipOpenNewFileInZip3 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; +{ + return zipOpenNewFileInZip2 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0); +} + +local int zipFlushWriteBuffer(zi) + zip_internal* zi; +{ + int err=ZIP_OK; + + if (zi->ci.encrypt != 0) + { +#ifndef NOCRYPT + uInt i; + int t; + for (i=0;ici.pos_in_buffered_data;i++) + zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, + zi->ci.buffered_data[i],t); +#endif + } + if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) + !=zi->ci.pos_in_buffered_data) + err = ZIP_ERRNO; + zi->ci.pos_in_buffered_data = 0; + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (file, buf, len) + zipFile file; + const void* buf; + unsigned len; +{ + zip_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.stream.next_in = (void*)buf; + zi->ci.stream.avail_in = len; + zi->ci.crc32 = crc32(zi->ci.crc32,buf,len); + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + + if(err != ZIP_OK) + break; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + for (i=0;ici.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + } + + return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32) + zipFile file; + uLong uncompressed_size; + uLong crc32; +{ + zip_internal* zi; + uLong compressed_size; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + if (zipFlushWriteBuffer(zi)==ZIP_ERRNO) + err = ZIP_ERRNO; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + err=deflateEnd(&zi->ci.stream); + zi->ci.stream_initialised = 0; + } + + if (!zi->ci.raw) + { + crc32 = (uLong)zi->ci.crc32; + uncompressed_size = (uLong)zi->ci.stream.total_in; + } + compressed_size = (uLong)zi->ci.stream.total_out; +# ifndef NOCRYPT + compressed_size += zi->ci.crypt_header_size; +# endif + + ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20, + compressed_size,4); /*compr size*/ + if (zi->ci.stream.data_type == Z_ASCII) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); + ziplocal_putValue_inmemory(zi->ci.central_header+24, + uncompressed_size,4); /*uncompr size*/ + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, + (uLong)zi->ci.size_centralheader); + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); + if (ZSEEK(zi->z_filefunc,zi->filestream, + zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ + + if (err==ZIP_OK) /* compressed size, unknown */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); + + if (ZSEEK(zi->z_filefunc,zi->filestream, + cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipCloseFileInZip (file) + zipFile file; +{ + return zipCloseFileInZipRaw (file,0,0); +} + +extern int ZEXPORT zipClose (file, global_comment) + zipFile file; + const char* global_comment; +{ + zip_internal* zi; + int err = 0; + uLong size_centraldir = 0; + uLong centraldir_pos_inzip; + uInt size_global_comment; + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + +#ifndef NO_ADDFILEINEXISTINGZIP + if (global_comment==NULL) + global_comment = zi->globalcomment; +#endif + if (global_comment==NULL) + size_global_comment = 0; + else + size_global_comment = (uInt)strlen(global_comment); + + centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream, + ldi->data,ldi->filled_in_this_block) + !=ldi->filled_in_this_block ) + err = ZIP_ERRNO; + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_datablock(zi->central_dir.first_block); + + if (err==ZIP_OK) /* Magic End */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* size of the central directory */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the + starting disk number */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream, + (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); + + if (err==ZIP_OK) /* zipfile comment length */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); + + if ((err==ZIP_OK) && (size_global_comment>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream, + global_comment,size_global_comment) != size_global_comment) + err = ZIP_ERRNO; + + if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0) + if (err == ZIP_OK) + err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(zi->globalcomment); +#endif + TRYFREE(zi); + + return err; +} diff --git a/plugins/smplayer_plugin/findsubtitles/quazip/zip.h b/plugins/smplayer_plugin/findsubtitles/quazip/zip.h new file mode 100644 index 000000000..acacce83b --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/quazip/zip.h @@ -0,0 +1,235 @@ +/* zip.h -- IO for compress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow creates .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + For uncompress .zip file, look at unzip.h + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.html for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _zip_H +#define _zip_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. +*/ + +/* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte +*/ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) +*/ + + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw)); + +/* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCtypting)); + +/* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCtypting : crc of file to compress (needed for crypting) + */ + + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const void* buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, + uLong uncompressed_size, + uLong crc32)); +/* + Close the current file in the zipfile, for fiel opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip_H */ diff --git a/plugins/smplayer_plugin/findsubtitles/simplehttp.cpp b/plugins/smplayer_plugin/findsubtitles/simplehttp.cpp new file mode 100644 index 000000000..683ae92e0 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/simplehttp.cpp @@ -0,0 +1,73 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "simplehttp.h" +#include + +SimpleHttp::SimpleHttp( QObject * parent ) : QHttp(parent) +{ + connect( this, SIGNAL(requestFinished(int, bool)), + this, SLOT(httpRequestFinished(int, bool)) ); + + connect( this, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), + this, SLOT(readResponseHeader(const QHttpResponseHeader &)) ); +} + +SimpleHttp::~SimpleHttp() { +} + +void SimpleHttp::download(const QString & url) { + downloaded_text.clear(); + + QUrl u(url); + setHost( u.host() ); + http_get_id = get( u.path() ); + + emit connecting(u.host()); +} + +void SimpleHttp::readResponseHeader(const QHttpResponseHeader &responseHeader) { + qDebug("SimpleHttp::readResponseHeader: statusCode: %d", responseHeader.statusCode()); + + if (responseHeader.statusCode() == 301) { + QString new_url = responseHeader.value("Location"); + qDebug("SimpleHttp::readResponseHeader: Location: '%s'", new_url.toLatin1().constData()); + download(new_url); + } + else + if (responseHeader.statusCode() != 200) { + qDebug("SimpleHttp::readResponseHeader: error: '%s'", responseHeader.reasonPhrase().toLatin1().constData()); + emit downloadFailed(responseHeader.reasonPhrase()); + abort(); + } +} + +void SimpleHttp::httpRequestFinished(int request_id, bool error) { + qDebug("SimpleHttp::httpRequestFinished: %d, %d", request_id, error); + + if (request_id != http_get_id) return; + + downloaded_text += readAll(); + + if (!downloaded_text.isEmpty()) { + emit downloadFinished(downloaded_text); + } +} + +#include "moc_simplehttp.cpp" + diff --git a/plugins/smplayer_plugin/findsubtitles/simplehttp.h b/plugins/smplayer_plugin/findsubtitles/simplehttp.h new file mode 100644 index 000000000..a94d585cb --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/simplehttp.h @@ -0,0 +1,52 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _SIMPLEHTTP_H_ +#define _SIMPLEHTTP_H_ + +#include + +class QHttp; +class QHttpResponseHeader; + +class SimpleHttp : public QHttp +{ + Q_OBJECT + +public: + SimpleHttp( QObject* parent = 0 ); + ~SimpleHttp(); + + void download(const QString & url); + +signals: + void connecting(QString host); + void downloadFinished(QByteArray downloaded_text); + void downloadFailed(QString error); + +protected slots: + void readResponseHeader(const QHttpResponseHeader &responseHeader); + void httpRequestFinished(int request_id, bool error); + +protected: + QByteArray downloaded_text; + int http_get_id; +}; + +#endif + diff --git a/plugins/smplayer_plugin/findsubtitles/subchooserdialog.cpp b/plugins/smplayer_plugin/findsubtitles/subchooserdialog.cpp new file mode 100644 index 000000000..1d587dc5c --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/subchooserdialog.cpp @@ -0,0 +1,108 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "subchooserdialog.h" + +static Qt::CheckState CurItemCheckState = Qt::Unchecked; + +SubChooserDialog::SubChooserDialog(QWidget * parent, Qt::WindowFlags f) + : QDialog(parent, f ) +{ + setupUi(this); + + listWidget->setSelectionMode(QAbstractItemView::NoSelection); + + connect(selectAll, SIGNAL(clicked(bool)), this, SLOT(selectAllClicked(bool))); + connect(selectNone, SIGNAL(clicked(bool)), this, SLOT(selectNoneClicked(bool))); + connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(listItemClicked(QListWidgetItem*))); + connect(listWidget, SIGNAL(itemPressed(QListWidgetItem*)), this, SLOT(listItemPressed(QListWidgetItem*))); +} + +SubChooserDialog::~SubChooserDialog() +{ + +} + +void SubChooserDialog::selectAllClicked(bool) { + for (int k = 0; k < listWidget->count(); k++) + listWidget->item(k)->setCheckState(Qt::Checked); + + listWidget->setFocus(); +} + +void SubChooserDialog::selectNoneClicked(bool) { + for (int k = 0; k < listWidget->count(); k++) + listWidget->item(k)->setCheckState(Qt::Unchecked); + + listWidget->setFocus(); +} + +void SubChooserDialog::listItemClicked(QListWidgetItem* item) { + if (item->checkState() == CurItemCheckState) + { + //Clicked on the list item (not checkbox) + if (item->checkState() == Qt::Checked) + { + item->setCheckState(Qt::Unchecked); + } + else + item->setCheckState(Qt::Checked); + } + + //else - clicked on the checkbox itself, do nothing +} + +void SubChooserDialog::listItemPressed(QListWidgetItem* item) { + CurItemCheckState = item->checkState(); +} + +void SubChooserDialog::addFile(QString filename) { + QListWidgetItem* item = new QListWidgetItem(listWidget); + item->setText(filename); + item->setCheckState(Qt::Unchecked); +} + +QStringList SubChooserDialog::selectedFiles() { + QStringList files; + + for (int n = 0; n < listWidget->count(); n++) { + QListWidgetItem * i = listWidget->item(n); + if (i && i->checkState() == Qt::Checked) { + files.append(i->text()); + } + } + + return files; +} + +void SubChooserDialog::retranslateStrings() { + retranslateUi(this); +} + +// Language change stuff +void SubChooserDialog::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QDialog::changeEvent(e); + } +} + +#include "moc_subchooserdialog.cpp" + diff --git a/plugins/smplayer_plugin/findsubtitles/subchooserdialog.h b/plugins/smplayer_plugin/findsubtitles/subchooserdialog.h new file mode 100644 index 000000000..0b6de3a26 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/subchooserdialog.h @@ -0,0 +1,47 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _SUBCHOOSERDIALOG_H_ +#define _SUBCHOOSERDIALOG_H_ + +#include +#include "ui_subchooserdialog.h" + +class SubChooserDialog : public QDialog, public Ui::SubChooserDialog +{ + Q_OBJECT + +public: + SubChooserDialog( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~SubChooserDialog(); + + void addFile(QString filename); + QStringList selectedFiles(); + +protected: + virtual void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + +protected slots: + void selectAllClicked(bool); + void selectNoneClicked(bool); + void listItemClicked(QListWidgetItem* item); + void listItemPressed(QListWidgetItem* item); +}; + +#endif diff --git a/plugins/smplayer_plugin/findsubtitles/subchooserdialog.ui b/plugins/smplayer_plugin/findsubtitles/subchooserdialog.ui new file mode 100644 index 000000000..7ad3d6556 --- /dev/null +++ b/plugins/smplayer_plugin/findsubtitles/subchooserdialog.ui @@ -0,0 +1,148 @@ + + SubChooserDialog + + + + 0 + 0 + 370 + 329 + + + + Subtitle selection + + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + Qt::AlignVCenter + + + true + + + + + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::NoEditTriggers + + + QAbstractItemView::MultiSelection + + + QListView::ListMode + + + true + + + true + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Select All + + + + + + + Select None + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + SubChooserDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + SubChooserDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/smplayer_plugin/floatingwidget.cpp b/plugins/smplayer_plugin/floatingwidget.cpp new file mode 100644 index 000000000..029a19a13 --- /dev/null +++ b/plugins/smplayer_plugin/floatingwidget.cpp @@ -0,0 +1,138 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "floatingwidget.h" +#include +#include +#include + +FloatingWidget::FloatingWidget( QWidget * parent ) + : QWidget( parent, Qt::Window | Qt::FramelessWindowHint | + Qt::WindowStaysOnTopHint ) +{ + setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); + + tb = new QToolBar; + tb->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); + + QHBoxLayout *layout = new QHBoxLayout; + layout->setSpacing(2); + layout->setMargin(2); + layout->addWidget(tb); + + setLayout(layout); + + _margin = 0; + _animated = false; + animation_timer = new QTimer(this); + animation_timer->setInterval(2); + connect( animation_timer, SIGNAL(timeout()), this, SLOT(animate()) ); + + connect( &auto_hide_timer, SIGNAL(timeout()), + this, SLOT(checkUnderMouse()) ); + setAutoHide(true); +} + +FloatingWidget::~FloatingWidget() { +} + +#ifndef Q_OS_WIN +void FloatingWidget::setBypassWindowManager(bool b) { + if (b) { + setWindowFlags(windowFlags() | Qt::X11BypassWindowManagerHint); + } + else { + setWindowFlags(windowFlags() & ~Qt::X11BypassWindowManagerHint); + } +} +#endif + +void FloatingWidget::setAutoHide(bool b) { + auto_hide = b; + + if (b) + auto_hide_timer.start(5000); + else + auto_hide_timer.stop(); +} + + +void FloatingWidget::showOver(QWidget * widget, int size, Place place) { + qDebug("FloatingWidget::showOver"); + + int w = widget->width() * size / 100; + int h = height(); + resize( w, h ); + + //qDebug("widget x: %d, y: %d, h: %d, w: %d", widget->x(), widget->y(), widget->width(), widget->height()); + + int x = (widget->width() - width() ) / 2; + int y; + if (place == Top) + y = 0 + _margin; + else + y = widget->height() - height() - _margin; + + QPoint p = widget->mapToGlobal(QPoint(x, y)); + + //qDebug("FloatingWidget::showOver: x: %d, y: %d, w: %d, h: %d", x, y, w, h); + //qDebug("FloatingWidget::showOver: global x: %d global y: %d", p.x(), p.y()); + move(p); + + if (isAnimated()) { + Movement m = Upward; + if (place == Top) m = Downward; + showAnimated(p, m); + } else { + show(); + } +} + +void FloatingWidget::showAnimated(QPoint final_position, Movement movement) { + current_movement = movement; + final_y = final_position.y(); + + if (movement == Upward) { + current_y = final_position.y() + height(); + } else { + current_y = final_position.y() - height(); + } + + move(x(), current_y); + show(); + + animation_timer->start(); +} + +void FloatingWidget::animate() { + if (current_y == final_y) { + animation_timer->stop(); + } else { + if (current_movement == Upward) current_y--; else current_y++; + move(x(), current_y); + } +} + +void FloatingWidget::checkUnderMouse() { + if (auto_hide) { + //qDebug("FloatingWidget::checkUnderMouse"); + if ((isVisible()) && (!underMouse())) hide(); + } +} + +#include "moc_floatingwidget.cpp" diff --git a/plugins/smplayer_plugin/floatingwidget.h b/plugins/smplayer_plugin/floatingwidget.h new file mode 100644 index 000000000..a847f2dcf --- /dev/null +++ b/plugins/smplayer_plugin/floatingwidget.h @@ -0,0 +1,78 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _FLOATING_WIDGET_H_ +#define _FLOATING_WIDGET_H_ + +#include +#include + +class QToolBar; + +class FloatingWidget : public QWidget +{ + Q_OBJECT + +public: + enum Place { Top = 0, Bottom = 1 }; + enum Movement { Upward = 0, Downward = 1 }; + + FloatingWidget(QWidget * parent = 0); + ~FloatingWidget(); + + //! Show the floating widget over the specified widget. + void showOver(QWidget * widget, int size = 100, Place place = Bottom); + + void showAnimated(QPoint final_position, Movement movement); + + QToolBar * toolbar() { return tb; }; + + bool isAnimated() { return _animated; }; + bool autoHide() { return auto_hide; }; + int margin() { return _margin; }; + +public slots: + void setAnimated(bool b) { _animated = b; }; + void setAutoHide(bool b); + void setMargin(int margin) { _margin = margin; }; +#ifndef Q_OS_WIN + void setBypassWindowManager(bool b); +#endif + +protected: + QToolBar * tb; + +private slots: + void animate(); + void checkUnderMouse(); + +private: + // Animation variables + bool _animated; + QTimer * animation_timer; + int final_y; + int current_y; + Movement current_movement; + + bool auto_hide; + QTimer auto_hide_timer; + + int _margin; +}; + +#endif diff --git a/plugins/smplayer_plugin/global.cpp b/plugins/smplayer_plugin/global.cpp new file mode 100644 index 000000000..480a31298 --- /dev/null +++ b/plugins/smplayer_plugin/global.cpp @@ -0,0 +1,96 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "global.h" +#include "preferences.h" + +#ifndef MINILIB + +#include "constants.h" +#include +#include "translator.h" +#include "paths.h" +#include +#include + +QSettings * Global::settings = 0; +Preferences * Global::pref = 0; +Translator * Global::translator = 0; + +using namespace Global; + +void Global::global_init(const QString & config_path) { + qDebug("global_init"); + + // Translator + translator = new Translator(); + + // settings + if (!config_path.isEmpty()) { + Paths::setConfigPath(config_path); + } + + if (Paths::iniPath().isEmpty()) { + settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, + QString(COMPANY), QString(PROGRAM) ); + } else { + QString filename = Paths::iniPath() + "/smplayer.ini"; + settings = new QSettings( filename, QSettings::IniFormat ); + qDebug("global_init: config file: '%s'", filename.toUtf8().data()); + + } + + // Preferences + pref = new Preferences(); +} + +void Global::global_end() { + qDebug("global_end"); + + // delete + delete pref; + pref = 0; + + delete settings; + delete translator; +} + +#else + +Preferences * Global::pref = 0; + +using namespace Global; + +void Global::global_init() { + qDebug("global_init"); + + // Preferences + pref = new Preferences(); +} + +void Global::global_end() { + qDebug("global_end"); + + // delete + delete pref; + pref = 0; +} + +#endif // MINILIB + diff --git a/plugins/smplayer_plugin/global.h b/plugins/smplayer_plugin/global.h new file mode 100644 index 000000000..cb2b12dcf --- /dev/null +++ b/plugins/smplayer_plugin/global.h @@ -0,0 +1,66 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _GLOBAL_H_ +#define _GLOBAL_H_ + +#include + +// Some global objects + +#ifndef MINILIB + +class QSettings; +class Preferences; +class Translator; + +namespace Global { + + //! Read and store application settings + extern QSettings * settings; + + //! Prefences + extern Preferences * pref; + + //! Translator (for changing language) + extern Translator * translator; + + + void global_init(const QString & config_path); + void global_end(); + +}; + +#else + +class Preferences; + +namespace Global { + //! Prefences + extern Preferences * pref; + + void global_init(); + void global_end(); + +}; + +#endif // MINILIB + +#endif + diff --git a/plugins/smplayer_plugin/guiconfig.h b/plugins/smplayer_plugin/guiconfig.h new file mode 100644 index 000000000..8cda88e4d --- /dev/null +++ b/plugins/smplayer_plugin/guiconfig.h @@ -0,0 +1,92 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _GUICONFIG_H_ +#define _GUICONFIG_H_ + + +// CONTROLWIDGET_OVER_VIDEO +// if set to 1, the controlwidget will be shown in fullscreen +// *over* the video (not moving the video) when the user move the mouse +// to the bottom area of the screen. + +#define CONTROLWIDGET_OVER_VIDEO 1 + + +// DOCK_PLAYLIST +// if 1, the playlist will be docked in the main window, instead +// of being a top level window + +#define DOCK_PLAYLIST 1 + + +// AUTODISABLE_ACTIONS +// if set to 1, some actions will be disabled if they are not needed + +#define AUTODISABLE_ACTIONS 1 + + +// MINI_ARROW_BUTTONS +// if set to 1, the GUI will use a popup menu for arrow buttons + +#define MINI_ARROW_BUTTONS 1 + + +// ALLOW_CHANGE_STYLESHEET +// if 1, the app stylesheet can be changed + +#define ALLOW_CHANGE_STYLESHEET 1 + + +// Allow to use multiple shortcuts for actions + +#define USE_MULTIPLE_SHORTCUTS 1 + + +// USE_SHORTCUTGETTER +// if 1, a new dialog will be used to ask the user for a +// keyshortcut. + +#define USE_SHORTCUTGETTER 1 + + +// USE_INFOPROVIDER +// if 1, the playlist will read info about the files when they are added +// to the list. +// It's slow but allows the user to see the length and even the name of +// a mp3 song. + +#define USE_INFOPROVIDER 1 + + +// USE_CONFIGURABLE_TOOLBARS +// if 1, the toolbars (and controlbars) are saved to the config file +// so the user can modify them. + +#define USE_CONFIGURABLE_TOOLBARS 1 + + +// USE_DOCK_TOPLEVEL_EVENT +// if 1, the topLevelChanged from QDockWidget will be use to know +// if the playlist has been docked or undocked + +#define USE_DOCK_TOPLEVEL_EVENT 0 + + +#endif + diff --git a/plugins/smplayer_plugin/helper.cpp b/plugins/smplayer_plugin/helper.cpp new file mode 100644 index 000000000..c6386a9d5 --- /dev/null +++ b/plugins/smplayer_plugin/helper.cpp @@ -0,0 +1,256 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "helper.h" + +#include +#include +#include +#include +#include +#include +#include "config.h" + +#ifdef Q_OS_WIN +#include // For the screensaver stuff +#endif + +#if EXTERNAL_SLEEP +#include +#else +#include +#endif + + +#if !EXTERNAL_SLEEP +class Sleeper : public QThread +{ +public: + static void sleep(unsigned long secs) {QThread::sleep(secs);} + static void msleep(unsigned long msecs) { + //qDebug("sleeping..."); + QThread::msleep(msecs); + //qDebug("finished"); + } + static void usleep(unsigned long usecs) {QThread::usleep(usecs);} +}; +#endif + +/* +QString Helper::dvdForPref(const QString & dvd_id, int title) { + return QString("DVD_%1_%2").arg(dvd_id).arg(title); +} +*/ + +QString Helper::formatTime(int secs) { + int t = secs; + int hours = (int) t / 3600; + t -= hours*3600; + int minutes = (int) t / 60; + t -= minutes*60; + int seconds = t; + + QString tf; + return tf.sprintf("%02d:%02d:%02d",hours,minutes,seconds); +} + +QString Helper::timeForJumps(int secs) { + int minutes = (int) secs / 60; + int seconds = secs % 60; + + if (minutes==0) { + return QObject::tr("%1 second(s)", "", seconds).arg(seconds); + } else { + if (seconds==0) + return QObject::tr("%1 minute(s)", "", minutes).arg(minutes); + else { + QString m = QObject::tr("%1 minute(s)", "", minutes).arg(minutes); + QString s = QObject::tr("%1 second(s)", "", seconds).arg(seconds); + return QObject::tr("%1 and %2").arg(m).arg(s); + } + } +} + +#ifdef Q_OS_WIN +// This function has been copied (and modified a little bit) from Scribus (program under GPL license): +// http://docs.scribus.net/devel/util_8cpp-source.html#l00112 +QString Helper::shortPathName(QString long_path) { + if ((QSysInfo::WindowsVersion >= QSysInfo::WV_NT) && (QFile::exists(long_path))) { + QString short_path = long_path; + + const int max_path = 4096; + WCHAR shortName[max_path]; + + QString nativePath = QDir::convertSeparators(long_path); + int ret = GetShortPathNameW((LPCWSTR) nativePath.utf16(), shortName, max_path); + if (ret != ERROR_INVALID_PARAMETER && ret < MAX_PATH) + short_path = QString::fromUtf16((const ushort*) shortName); + + return short_path; + } else { + return long_path; + } +} + +/* +void Helper::setScreensaverEnabled(bool b) { + qDebug("Helper::setScreensaverEnabled: %d", b); + + if (b) { + // Activate screensaver + SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, true, 0, SPIF_SENDWININICHANGE); + SystemParametersInfo( SPI_SETLOWPOWERACTIVE, 1, NULL, 0); + SystemParametersInfo( SPI_SETPOWEROFFACTIVE, 1, NULL, 0); + } else { + SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, false, 0, SPIF_SENDWININICHANGE); + SystemParametersInfo( SPI_SETLOWPOWERACTIVE, 0, NULL, 0); + SystemParametersInfo( SPI_SETPOWEROFFACTIVE, 0, NULL, 0); + } +} +*/ +#endif + +void Helper::msleep(int ms) { +#if EXTERNAL_SLEEP + //qDebug("Helper::msleep: %d (using usleep)", ms); + usleep(ms*1000); +#else + //qDebug("Helper::msleep: %d (using QThread::msleep)", ms); + Sleeper::msleep( ms ); +#endif +} + +QString Helper::changeSlashes(QString filename) { + // Only change if file exists (it's a local file) + if (QFileInfo(filename).exists()) + return filename.replace('/', '\\'); + else + return filename; +} + +QString Helper::dvdSplitFolder(QString dvd_url) { + qDebug("Helper::dvdSplitFolder: '%s'", dvd_url.toUtf8().data()); + QRegExp s("^dvd://(\\d+):(.*)", Qt::CaseInsensitive); + if (s.indexIn(dvd_url)!=-1) { + return s.cap(2); + } else { + return QString::null; + } +} + +int Helper::dvdSplitTitle(QString dvd_url) { + qDebug("Helper::dvdSplitTitle: '%s'", dvd_url.toUtf8().data()); + QRegExp s("^dvd://(\\d+)(.*)", Qt::CaseInsensitive); + if (s.indexIn(dvd_url)!=-1) { + return s.cap(1).toInt(); + } else { + return -1; + } +} + + +bool Helper::directoryContainsDVD(QString directory) { + //qDebug("Helper::directoryContainsDVD: '%s'", directory.latin1()); + + QDir dir(directory); + QStringList l = dir.entryList(); + bool valid = FALSE; + for (int n=0; n < l.count(); n++) { + //qDebug(" * entry %d: '%s'", n, l[n].toUtf8().data()); + if (l[n].toLower() == "video_ts") valid = TRUE; + } + + return valid; +} + +int Helper::qtVersion() { + QRegExp rx("(\\d+)\\.(\\d+)\\.(\\d+)"); + QString v(qVersion()); + + int r = 0; + + if (rx.indexIn(v) > -1) { + int n1 = rx.cap(1).toInt(); + int n2 = rx.cap(2).toInt(); + int n3 = rx.cap(3).toInt(); + r = n1 * 1000 + n2 * 100 + n3; + } + + qDebug("Helper::qtVersion: %d", r); + + return r; +} + +QString Helper::equalizerListToString(AudioEqualizerList values) { + double v0 = (double) values[0].toInt() / 10; + double v1 = (double) values[1].toInt() / 10; + double v2 = (double) values[2].toInt() / 10; + double v3 = (double) values[3].toInt() / 10; + double v4 = (double) values[4].toInt() / 10; + double v5 = (double) values[5].toInt() / 10; + double v6 = (double) values[6].toInt() / 10; + double v7 = (double) values[7].toInt() / 10; + double v8 = (double) values[8].toInt() / 10; + double v9 = (double) values[9].toInt() / 10; + QString s = QString::number(v0) + ":" + QString::number(v1) + ":" + + QString::number(v2) + ":" + QString::number(v3) + ":" + + QString::number(v4) + ":" + QString::number(v5) + ":" + + QString::number(v6) + ":" + QString::number(v7) + ":" + + QString::number(v8) + ":" + QString::number(v9); + + return s; +} + +QStringList Helper::searchForConsecutiveFiles(const QString & initial_file) { + qDebug("Helper::searchForConsecutiveFiles: initial_file: '%s'", initial_file.toUtf8().constData()); + + QStringList files_to_add; + + QFileInfo fi(initial_file); + QString basename = fi.completeBaseName(); + QString extension = fi.suffix(); + QString path = fi.absolutePath(); + + QRegExp rx("^.*(\\d+)"); + + if ( rx.indexIn(basename) > -1) { + int digits = rx.cap(1).length(); + int current_number = rx.cap(1).toInt(); + + //qDebug("Helper::searchForConsecutiveFiles: filename ends with a number (%s)", rx.cap(1).toUtf8().constData()); + qDebug("Helper::searchForConsecutiveFiles: filename ends with a number (%d)", current_number); + qDebug("Helper::searchForConsecutiveFiles: trying to find consecutive files"); + + QString template_name = path + "/" + basename.left(basename.length() - digits); + //qDebug("BaseGui::newMediaLoaded: name without digits: '%s'", template_name.toUtf8().constData()); + + current_number++; + QString next_name = template_name + QString("%1").arg(current_number, digits, 10, QLatin1Char('0')) +"."+ extension; + qDebug("Helper::searchForConsecutiveFiles: looking for '%s'", next_name.toUtf8().constData()); + + while (QFile::exists(next_name)) { + qDebug("Helper::searchForConsecutiveFiles: '%s' exists, added to the list", next_name.toUtf8().constData()); + files_to_add.append(next_name); + current_number++; + next_name = template_name + QString("%1").arg(current_number, digits, 10, QLatin1Char('0')) +"."+ extension; + qDebug("Helper::searchForConsecutiveFiles: looking for '%s'", next_name.toUtf8().constData()); + } + } + + return files_to_add; +} diff --git a/plugins/smplayer_plugin/helper.h b/plugins/smplayer_plugin/helper.h new file mode 100644 index 000000000..831de43bc --- /dev/null +++ b/plugins/smplayer_plugin/helper.h @@ -0,0 +1,71 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _HELPER_H_ +#define _HELPER_H_ + +#include +#include +#include "audioequalizerlist.h" + +#ifdef Q_OS_WIN +#include "config.h" +#endif + +class Helper { + +public: + + // Format a time (hh:mm:ss) + static QString formatTime(int secs); + + static QString timeForJumps(int secs); + + // Give a name for config (group name) based on dvd id + /* static QString dvdForPref(const QString & dvd_id, int title); */ + +#ifdef Q_OS_WIN + static QString shortPathName(QString long_path); + + //! Enable or disables the screensaver + /* static void setScreensaverEnabled(bool b); */ +#endif + + static void msleep(int ms); + + //! Change filenames like "C:/Program Files/" to "C:\Program Files\" + static QString changeSlashes(QString filename); + + static QString dvdSplitFolder(QString dvd_url); + static int dvdSplitTitle(QString dvd_url); + + static bool directoryContainsDVD(QString directory); + + //! Returns an int with the version number of Qt at run-time. + //! If version is 4.3.2 it returns 40302. + static int qtVersion(); + + //! Returns a string to be passed to mplayer with the audio equalizer + //! values. + static QString equalizerListToString(AudioEqualizerList values); + + static QStringList searchForConsecutiveFiles(const QString & initial_file); +}; + +#endif diff --git a/plugins/smplayer_plugin/icons-png/Thumbs.db b/plugins/smplayer_plugin/icons-png/Thumbs.db new file mode 100644 index 000000000..16aad7fa1 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/Thumbs.db differ diff --git a/plugins/smplayer_plugin/icons-png/angle.png b/plugins/smplayer_plugin/icons-png/angle.png new file mode 100644 index 000000000..d8864f704 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/angle.png differ diff --git a/plugins/smplayer_plugin/icons-png/aspect.png b/plugins/smplayer_plugin/icons-png/aspect.png new file mode 100644 index 000000000..e08d71d84 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/aspect.png differ diff --git a/plugins/smplayer_plugin/icons-png/audio_channels.png b/plugins/smplayer_plugin/icons-png/audio_channels.png new file mode 100644 index 000000000..648c7533c Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/audio_channels.png differ diff --git a/plugins/smplayer_plugin/icons-png/audio_equalizer.png b/plugins/smplayer_plugin/icons-png/audio_equalizer.png new file mode 100644 index 000000000..8911d1c57 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/audio_equalizer.png differ diff --git a/plugins/smplayer_plugin/icons-png/audio_filters.png b/plugins/smplayer_plugin/icons-png/audio_filters.png new file mode 100644 index 000000000..a310c9cae Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/audio_filters.png differ diff --git a/plugins/smplayer_plugin/icons-png/audio_track.png b/plugins/smplayer_plugin/icons-png/audio_track.png new file mode 100644 index 000000000..3d7ac1cd7 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/audio_track.png differ diff --git a/plugins/smplayer_plugin/icons-png/background.png b/plugins/smplayer_plugin/icons-png/background.png new file mode 100644 index 000000000..befe614c3 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/background.png differ diff --git a/plugins/smplayer_plugin/icons-png/bola.xcf b/plugins/smplayer_plugin/icons-png/bola.xcf new file mode 100644 index 000000000..d09554eeb Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/bola.xcf differ diff --git a/plugins/smplayer_plugin/icons-png/brightness.png b/plugins/smplayer_plugin/icons-png/brightness.png new file mode 100644 index 000000000..96a9f5047 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/brightness.png differ diff --git a/plugins/smplayer_plugin/icons-png/cdda.png b/plugins/smplayer_plugin/icons-png/cdda.png new file mode 100644 index 000000000..3afaea6e2 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/cdda.png differ diff --git a/plugins/smplayer_plugin/icons-png/cdrom_drive.png b/plugins/smplayer_plugin/icons-png/cdrom_drive.png new file mode 100644 index 000000000..396b81dd4 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/cdrom_drive.png differ diff --git a/plugins/smplayer_plugin/icons-png/chapter.png b/plugins/smplayer_plugin/icons-png/chapter.png new file mode 100644 index 000000000..19b027229 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/chapter.png differ diff --git a/plugins/smplayer_plugin/icons-png/cl_help.png b/plugins/smplayer_plugin/icons-png/cl_help.png new file mode 100644 index 000000000..d578a9399 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/cl_help.png differ diff --git a/plugins/smplayer_plugin/icons-png/close.png b/plugins/smplayer_plugin/icons-png/close.png new file mode 100644 index 000000000..7cb985935 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/close.png differ diff --git a/plugins/smplayer_plugin/icons-png/compact.png b/plugins/smplayer_plugin/icons-png/compact.png new file mode 100644 index 000000000..454446f8b Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/compact.png differ diff --git a/plugins/smplayer_plugin/icons-png/conflict.png b/plugins/smplayer_plugin/icons-png/conflict.png new file mode 100644 index 000000000..700530438 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/conflict.png differ diff --git a/plugins/smplayer_plugin/icons-png/contrast.png b/plugins/smplayer_plugin/icons-png/contrast.png new file mode 100644 index 000000000..9ae6745f1 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/contrast.png differ diff --git a/plugins/smplayer_plugin/icons-png/contributors.png b/plugins/smplayer_plugin/icons-png/contributors.png new file mode 100644 index 000000000..58378b148 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/contributors.png differ diff --git a/plugins/smplayer_plugin/icons-png/copy.png b/plugins/smplayer_plugin/icons-png/copy.png new file mode 100644 index 000000000..9d6928fab Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/copy.png differ diff --git a/plugins/smplayer_plugin/icons-png/delete.png b/plugins/smplayer_plugin/icons-png/delete.png new file mode 100644 index 000000000..9fd544eb6 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/delete.png differ diff --git a/plugins/smplayer_plugin/icons-png/down.png b/plugins/smplayer_plugin/icons-png/down.png new file mode 100644 index 000000000..279ad21a2 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/down.png differ diff --git a/plugins/smplayer_plugin/icons-png/dvd.png b/plugins/smplayer_plugin/icons-png/dvd.png new file mode 100644 index 000000000..8c92fa5fa Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/dvd.png differ diff --git a/plugins/smplayer_plugin/icons-png/dvd_drive.png b/plugins/smplayer_plugin/icons-png/dvd_drive.png new file mode 100644 index 000000000..98fee075a Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/dvd_drive.png differ diff --git a/plugins/smplayer_plugin/icons-png/dvd_hd.png b/plugins/smplayer_plugin/icons-png/dvd_hd.png new file mode 100644 index 000000000..381ad938a Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/dvd_hd.png differ diff --git a/plugins/smplayer_plugin/icons-png/equalizer.png b/plugins/smplayer_plugin/icons-png/equalizer.png new file mode 100644 index 000000000..20906eb30 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/equalizer.png differ diff --git a/plugins/smplayer_plugin/icons-png/exit.png b/plugins/smplayer_plugin/icons-png/exit.png new file mode 100644 index 000000000..6ad33b023 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/exit.png differ diff --git a/plugins/smplayer_plugin/icons-png/faq.png b/plugins/smplayer_plugin/icons-png/faq.png new file mode 100644 index 000000000..9fe765266 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/faq.png differ diff --git a/plugins/smplayer_plugin/icons-png/find.png b/plugins/smplayer_plugin/icons-png/find.png new file mode 100644 index 000000000..ed2376215 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/find.png differ diff --git a/plugins/smplayer_plugin/icons-png/flecha.xcf b/plugins/smplayer_plugin/icons-png/flecha.xcf new file mode 100644 index 000000000..517285a4b Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/flecha.xcf differ diff --git a/plugins/smplayer_plugin/icons-png/flip.png b/plugins/smplayer_plugin/icons-png/flip.png new file mode 100644 index 000000000..7776ce70c Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/flip.png differ diff --git a/plugins/smplayer_plugin/icons-png/forward10m.png b/plugins/smplayer_plugin/icons-png/forward10m.png new file mode 100644 index 000000000..a51b1750d Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/forward10m.png differ diff --git a/plugins/smplayer_plugin/icons-png/forward10s.png b/plugins/smplayer_plugin/icons-png/forward10s.png new file mode 100644 index 000000000..55822c06f Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/forward10s.png differ diff --git a/plugins/smplayer_plugin/icons-png/forward1m.png b/plugins/smplayer_plugin/icons-png/forward1m.png new file mode 100644 index 000000000..3fda0b2f5 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/forward1m.png differ diff --git a/plugins/smplayer_plugin/icons-png/fullscreen.png b/plugins/smplayer_plugin/icons-png/fullscreen.png new file mode 100644 index 000000000..c31058c92 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/fullscreen.png differ diff --git a/plugins/smplayer_plugin/icons-png/gamma.png b/plugins/smplayer_plugin/icons-png/gamma.png new file mode 100644 index 000000000..90ad051a2 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/gamma.png differ diff --git a/plugins/smplayer_plugin/icons-png/hue.png b/plugins/smplayer_plugin/icons-png/hue.png new file mode 100644 index 000000000..45a7dd692 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/hue.png differ diff --git a/plugins/smplayer_plugin/icons-png/info.png b/plugins/smplayer_plugin/icons-png/info.png new file mode 100644 index 000000000..e3c8adb6e Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/info.png differ diff --git a/plugins/smplayer_plugin/icons-png/input_devices.png b/plugins/smplayer_plugin/icons-png/input_devices.png new file mode 100644 index 000000000..81ef713c7 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/input_devices.png differ diff --git a/plugins/smplayer_plugin/icons-png/instance1.png b/plugins/smplayer_plugin/icons-png/instance1.png new file mode 100644 index 000000000..f90848721 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/instance1.png differ diff --git a/plugins/smplayer_plugin/icons-png/instance2.png b/plugins/smplayer_plugin/icons-png/instance2.png new file mode 100644 index 000000000..097c412c4 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/instance2.png differ diff --git a/plugins/smplayer_plugin/icons-png/keyboard.png b/plugins/smplayer_plugin/icons-png/keyboard.png new file mode 100644 index 000000000..85eacf57d Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/keyboard.png differ diff --git a/plugins/smplayer_plugin/icons-png/license.png b/plugins/smplayer_plugin/icons-png/license.png new file mode 100644 index 000000000..cdb53ed6f Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/license.png differ diff --git a/plugins/smplayer_plugin/icons-png/logo.png b/plugins/smplayer_plugin/icons-png/logo.png new file mode 100644 index 000000000..befe614c3 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/logo.png differ diff --git a/plugins/smplayer_plugin/icons-png/logs.png b/plugins/smplayer_plugin/icons-png/logs.png new file mode 100644 index 000000000..ca2ed110f Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/logs.png differ diff --git a/plugins/smplayer_plugin/icons-png/minus.png b/plugins/smplayer_plugin/icons-png/minus.png new file mode 100644 index 000000000..47f4ef30d Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/minus.png differ diff --git a/plugins/smplayer_plugin/icons-png/mirror.png b/plugins/smplayer_plugin/icons-png/mirror.png new file mode 100644 index 000000000..a4f9b1059 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/mirror.png differ diff --git a/plugins/smplayer_plugin/icons-png/monitor.png b/plugins/smplayer_plugin/icons-png/monitor.png new file mode 100644 index 000000000..54f62c2f9 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/monitor.png differ diff --git a/plugins/smplayer_plugin/icons-png/mouse.png b/plugins/smplayer_plugin/icons-png/mouse.png new file mode 100644 index 000000000..e44f58672 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/mouse.png differ diff --git a/plugins/smplayer_plugin/icons-png/mute.png b/plugins/smplayer_plugin/icons-png/mute.png new file mode 100644 index 000000000..bfc847cf2 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/mute.png differ diff --git a/plugins/smplayer_plugin/icons-png/next.png b/plugins/smplayer_plugin/icons-png/next.png new file mode 100644 index 000000000..c3b360b26 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/next.png differ diff --git a/plugins/smplayer_plugin/icons-png/ok.png b/plugins/smplayer_plugin/icons-png/ok.png new file mode 100644 index 000000000..13ba71d56 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/ok.png differ diff --git a/plugins/smplayer_plugin/icons-png/ontop.png b/plugins/smplayer_plugin/icons-png/ontop.png new file mode 100644 index 000000000..d651b72a6 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/ontop.png differ diff --git a/plugins/smplayer_plugin/icons-png/open.png b/plugins/smplayer_plugin/icons-png/open.png new file mode 100644 index 000000000..e34d6180f Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/open.png differ diff --git a/plugins/smplayer_plugin/icons-png/open_playlist.png b/plugins/smplayer_plugin/icons-png/open_playlist.png new file mode 100644 index 000000000..779ec5e0b Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/open_playlist.png differ diff --git a/plugins/smplayer_plugin/icons-png/openfolder.png b/plugins/smplayer_plugin/icons-png/openfolder.png new file mode 100644 index 000000000..0ed1f21b5 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/openfolder.png differ diff --git a/plugins/smplayer_plugin/icons-png/osd.png b/plugins/smplayer_plugin/icons-png/osd.png new file mode 100644 index 000000000..af90940d7 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/osd.png differ diff --git a/plugins/smplayer_plugin/icons-png/pause.png b/plugins/smplayer_plugin/icons-png/pause.png new file mode 100644 index 000000000..7bc65fb05 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/pause.png differ diff --git a/plugins/smplayer_plugin/icons-png/play.png b/plugins/smplayer_plugin/icons-png/play.png new file mode 100644 index 000000000..ea3673798 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/play.png differ diff --git a/plugins/smplayer_plugin/icons-png/play_pause.png b/plugins/smplayer_plugin/icons-png/play_pause.png new file mode 100644 index 000000000..170157bb2 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/play_pause.png differ diff --git a/plugins/smplayer_plugin/icons-png/playlist.png b/plugins/smplayer_plugin/icons-png/playlist.png new file mode 100644 index 000000000..779ec5e0b Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/playlist.png differ diff --git a/plugins/smplayer_plugin/icons-png/plus.png b/plugins/smplayer_plugin/icons-png/plus.png new file mode 100644 index 000000000..ade93b9bf Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/plus.png differ diff --git a/plugins/smplayer_plugin/icons-png/pref_advanced.png b/plugins/smplayer_plugin/icons-png/pref_advanced.png new file mode 100644 index 000000000..3c31b733e Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/pref_advanced.png differ diff --git a/plugins/smplayer_plugin/icons-png/pref_associations.png b/plugins/smplayer_plugin/icons-png/pref_associations.png new file mode 100644 index 000000000..87bb5380f Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/pref_associations.png differ diff --git a/plugins/smplayer_plugin/icons-png/pref_devices.png b/plugins/smplayer_plugin/icons-png/pref_devices.png new file mode 100644 index 000000000..dbb8a6f59 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/pref_devices.png differ diff --git a/plugins/smplayer_plugin/icons-png/pref_general.png b/plugins/smplayer_plugin/icons-png/pref_general.png new file mode 100644 index 000000000..725d827e1 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/pref_general.png differ diff --git a/plugins/smplayer_plugin/icons-png/pref_gui.png b/plugins/smplayer_plugin/icons-png/pref_gui.png new file mode 100644 index 000000000..0d685bb1f Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/pref_gui.png differ diff --git a/plugins/smplayer_plugin/icons-png/pref_performance.png b/plugins/smplayer_plugin/icons-png/pref_performance.png new file mode 100644 index 000000000..166aabd37 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/pref_performance.png differ diff --git a/plugins/smplayer_plugin/icons-png/pref_subtitles.png b/plugins/smplayer_plugin/icons-png/pref_subtitles.png new file mode 100644 index 000000000..eb7261aa2 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/pref_subtitles.png differ diff --git a/plugins/smplayer_plugin/icons-png/prefs.png b/plugins/smplayer_plugin/icons-png/prefs.png new file mode 100644 index 000000000..c8012e194 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/prefs.png differ diff --git a/plugins/smplayer_plugin/icons-png/previous.png b/plugins/smplayer_plugin/icons-png/previous.png new file mode 100644 index 000000000..2b72874e7 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/previous.png differ diff --git a/plugins/smplayer_plugin/icons-png/qt.png b/plugins/smplayer_plugin/icons-png/qt.png new file mode 100644 index 000000000..b9e456cc8 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/qt.png differ diff --git a/plugins/smplayer_plugin/icons-png/repeat.png b/plugins/smplayer_plugin/icons-png/repeat.png new file mode 100644 index 000000000..f903268e7 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/repeat.png differ diff --git a/plugins/smplayer_plugin/icons-png/resize_window.png b/plugins/smplayer_plugin/icons-png/resize_window.png new file mode 100644 index 000000000..fed63ecec Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/resize_window.png differ diff --git a/plugins/smplayer_plugin/icons-png/rewind10m.png b/plugins/smplayer_plugin/icons-png/rewind10m.png new file mode 100644 index 000000000..f192e0f14 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/rewind10m.png differ diff --git a/plugins/smplayer_plugin/icons-png/rewind10s.png b/plugins/smplayer_plugin/icons-png/rewind10s.png new file mode 100644 index 000000000..49b144278 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/rewind10s.png differ diff --git a/plugins/smplayer_plugin/icons-png/rewind1m.png b/plugins/smplayer_plugin/icons-png/rewind1m.png new file mode 100644 index 000000000..e85203327 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/rewind1m.png differ diff --git a/plugins/smplayer_plugin/icons-png/rotate.png b/plugins/smplayer_plugin/icons-png/rotate.png new file mode 100644 index 000000000..9d636827c Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/rotate.png differ diff --git a/plugins/smplayer_plugin/icons-png/saturation.png b/plugins/smplayer_plugin/icons-png/saturation.png new file mode 100644 index 000000000..28e751a7b Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/saturation.png differ diff --git a/plugins/smplayer_plugin/icons-png/save.png b/plugins/smplayer_plugin/icons-png/save.png new file mode 100644 index 000000000..e91ca4b74 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/save.png differ diff --git a/plugins/smplayer_plugin/icons-png/screenshot.png b/plugins/smplayer_plugin/icons-png/screenshot.png new file mode 100644 index 000000000..5d0c38fb1 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/screenshot.png differ diff --git a/plugins/smplayer_plugin/icons-png/shuffle.png b/plugins/smplayer_plugin/icons-png/shuffle.png new file mode 100644 index 000000000..3b470bbbb Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/shuffle.png differ diff --git a/plugins/smplayer_plugin/icons-png/speaker.png b/plugins/smplayer_plugin/icons-png/speaker.png new file mode 100644 index 000000000..0b4305b18 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/speaker.png differ diff --git a/plugins/smplayer_plugin/icons-png/speed.png b/plugins/smplayer_plugin/icons-png/speed.png new file mode 100644 index 000000000..585622d0a Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/speed.png differ diff --git a/plugins/smplayer_plugin/icons-png/stereo_mode.png b/plugins/smplayer_plugin/icons-png/stereo_mode.png new file mode 100644 index 000000000..58e0e573e Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/stereo_mode.png differ diff --git a/plugins/smplayer_plugin/icons-png/stop.png b/plugins/smplayer_plugin/icons-png/stop.png new file mode 100644 index 000000000..e7e43478b Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/stop.png differ diff --git a/plugins/smplayer_plugin/icons-png/sub.png b/plugins/smplayer_plugin/icons-png/sub.png new file mode 100644 index 000000000..ff57a8832 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/sub.png differ diff --git a/plugins/smplayer_plugin/icons-png/title.png b/plugins/smplayer_plugin/icons-png/title.png new file mode 100644 index 000000000..2720aee1f Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/title.png differ diff --git a/plugins/smplayer_plugin/icons-png/toolbars.png b/plugins/smplayer_plugin/icons-png/toolbars.png new file mode 100644 index 000000000..b95968796 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/toolbars.png differ diff --git a/plugins/smplayer_plugin/icons-png/translators.png b/plugins/smplayer_plugin/icons-png/translators.png new file mode 100644 index 000000000..127709e43 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/translators.png differ diff --git a/plugins/smplayer_plugin/icons-png/type_audio.png b/plugins/smplayer_plugin/icons-png/type_audio.png new file mode 100644 index 000000000..d1919234d Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/type_audio.png differ diff --git a/plugins/smplayer_plugin/icons-png/type_cdda.png b/plugins/smplayer_plugin/icons-png/type_cdda.png new file mode 100644 index 000000000..99539cd37 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/type_cdda.png differ diff --git a/plugins/smplayer_plugin/icons-png/type_dvd.png b/plugins/smplayer_plugin/icons-png/type_dvd.png new file mode 100644 index 000000000..b16b95ec0 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/type_dvd.png differ diff --git a/plugins/smplayer_plugin/icons-png/type_unknown.png b/plugins/smplayer_plugin/icons-png/type_unknown.png new file mode 100644 index 000000000..cbb914865 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/type_unknown.png differ diff --git a/plugins/smplayer_plugin/icons-png/type_url.png b/plugins/smplayer_plugin/icons-png/type_url.png new file mode 100644 index 000000000..31e5c26b2 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/type_url.png differ diff --git a/plugins/smplayer_plugin/icons-png/type_vcd.png b/plugins/smplayer_plugin/icons-png/type_vcd.png new file mode 100644 index 000000000..99539cd37 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/type_vcd.png differ diff --git a/plugins/smplayer_plugin/icons-png/type_video.png b/plugins/smplayer_plugin/icons-png/type_video.png new file mode 100644 index 000000000..ac61bd5dd Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/type_video.png differ diff --git a/plugins/smplayer_plugin/icons-png/unload.png b/plugins/smplayer_plugin/icons-png/unload.png new file mode 100644 index 000000000..619f4dfc2 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/unload.png differ diff --git a/plugins/smplayer_plugin/icons-png/up.png b/plugins/smplayer_plugin/icons-png/up.png new file mode 100644 index 000000000..ed770eb16 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/up.png differ diff --git a/plugins/smplayer_plugin/icons-png/url.png b/plugins/smplayer_plugin/icons-png/url.png new file mode 100644 index 000000000..a7ea68856 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/url.png differ diff --git a/plugins/smplayer_plugin/icons-png/url_big.png b/plugins/smplayer_plugin/icons-png/url_big.png new file mode 100644 index 000000000..a9e8db94d Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/url_big.png differ diff --git a/plugins/smplayer_plugin/icons-png/vcd.png b/plugins/smplayer_plugin/icons-png/vcd.png new file mode 100644 index 000000000..3afaea6e2 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/vcd.png differ diff --git a/plugins/smplayer_plugin/icons-png/video_filters.png b/plugins/smplayer_plugin/icons-png/video_filters.png new file mode 100644 index 000000000..5d96aeda0 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/video_filters.png differ diff --git a/plugins/smplayer_plugin/icons-png/video_size.png b/plugins/smplayer_plugin/icons-png/video_size.png new file mode 100644 index 000000000..0eb43a115 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/video_size.png differ diff --git a/plugins/smplayer_plugin/icons-png/volume.png b/plugins/smplayer_plugin/icons-png/volume.png new file mode 100644 index 000000000..81d23e70e Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/volume.png differ diff --git a/plugins/smplayer_plugin/icons-png/warning.png b/plugins/smplayer_plugin/icons-png/warning.png new file mode 100644 index 000000000..f0b875fd5 Binary files /dev/null and b/plugins/smplayer_plugin/icons-png/warning.png differ diff --git a/plugins/smplayer_plugin/icons.qrc b/plugins/smplayer_plugin/icons.qrc new file mode 100644 index 000000000..b252ec1d0 --- /dev/null +++ b/plugins/smplayer_plugin/icons.qrc @@ -0,0 +1,110 @@ + + + icons-png/aspect.png + icons-png/background.png + icons-png/brightness.png + icons-png/cdda.png + icons-png/cdrom_drive.png + icons-png/chapter.png + icons-png/close.png + icons-png/compact.png + icons-png/conflict.png + icons-png/contrast.png + icons-png/copy.png + icons-png/delete.png + icons-png/down.png + icons-png/dvd.png + icons-png/dvd_drive.png + icons-png/dvd_hd.png + icons-png/exit.png + icons-png/forward10m.png + icons-png/forward10s.png + icons-png/forward1m.png + icons-png/fullscreen.png + icons-png/gamma.png + icons-png/hue.png + icons-png/info.png + icons-png/input_devices.png + icons-png/keyboard.png + icons-png/logo.png + icons-png/logs.png + icons-png/minus.png + icons-png/monitor.png + icons-png/mouse.png + icons-png/mute.png + icons-png/ok.png + icons-png/open.png + icons-png/openfolder.png + icons-png/pause.png + icons-png/play.png + icons-png/play_pause.png + icons-png/playlist.png + icons-png/plus.png + icons-png/pref_advanced.png + icons-png/pref_devices.png + icons-png/pref_general.png + icons-png/pref_gui.png + icons-png/pref_performance.png + icons-png/pref_subtitles.png + icons-png/prefs.png + icons-png/previous.png + icons-png/saturation.png + icons-png/save.png + icons-png/screenshot.png + icons-png/shuffle.png + icons-png/speaker.png + icons-png/speed.png + icons-png/stop.png + icons-png/sub.png + icons-png/unload.png + icons-png/up.png + icons-png/url.png + icons-png/vcd.png + icons-png/volume.png + icons-png/next.png + icons-png/repeat.png + icons-png/resize_window.png + icons-png/rewind10m.png + icons-png/rewind10s.png + icons-png/rewind1m.png + icons-png/title.png + icons-png/type_audio.png + icons-png/type_cdda.png + icons-png/type_dvd.png + icons-png/type_unknown.png + icons-png/type_url.png + icons-png/type_vcd.png + icons-png/type_video.png + icons-png/url_big.png + icons-png/pref_associations.png + icons-png/translators.png + icons-png/contributors.png + icons-png/license.png + icons-png/faq.png + icons-png/qt.png + icons-png/instance1.png + icons-png/instance2.png + icons-png/equalizer.png + icons-png/audio_equalizer.png + icons-png/audio_filters.png + icons-png/video_filters.png + icons-png/video_size.png + icons-png/audio_channels.png + icons-png/open_playlist.png + icons-png/audio_track.png + icons-png/toolbars.png + icons-png/ontop.png + icons-png/stereo_mode.png + icons-png/cl_help.png + icons-png/osd.png + icons-png/angle.png + icons-png/rotate.png + icons-png/warning.png + icons-png/find.png + icons-png/flip.png + icons-png/mirror.png + mpcgui/mpc_toolbar.png + mpcgui/mpc_mono.png + mpcgui/mpc_stereo.png + + diff --git a/plugins/smplayer_plugin/images.cpp b/plugins/smplayer_plugin/images.cpp new file mode 100644 index 000000000..a8908f8cc --- /dev/null +++ b/plugins/smplayer_plugin/images.cpp @@ -0,0 +1,116 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define COMPAT_WITH_OLD_ICONS 1 + +#include "images.h" +#include "global.h" +#include "preferences.h" +#include "paths.h" + +#include + +using namespace Global; + +QString Images::filename(const QString & name, bool png) { + QString filename = name; + + if (filename.endsWith("_small")) { + filename = filename.replace("_small", ""); + } + + if (png) filename += ".png"; + + return filename; +} + +QPixmap Images::loadIcon(const QString & icon_name) { + QPixmap p; + + if (!pref->iconset.isEmpty()) { + QString filename = Paths::configPath() + "/themes/" + pref->iconset + "/" + icon_name; + if (!QFile::exists(filename)) { + filename = Paths::themesPath() + "/" + pref->iconset + "/" + icon_name; + } + //qDebug("Images::loadIcon: filename: '%s'", filename.toUtf8().data()); + + if (QFile::exists(filename)) { + p.load( filename ); + } + } + + return p; +} + +QPixmap Images::icon(QString name, int size, bool png) { + bool small = false; + + if (name.endsWith("_small")) { + small = true; + } + + QString icon_name = Images::filename(name,png); + + QPixmap p = Images::loadIcon( icon_name ); + bool ok = !p.isNull(); + +#if COMPAT_WITH_OLD_ICONS + if (!ok) { + if ( (name.startsWith("r")) || + (name.startsWith("t")) || + (name.startsWith("n")) ) + { + QString icon_name = Images::filename("x"+name,png); + p = Images::loadIcon( icon_name ); + ok = !p.isNull(); + } + } +#endif + + if (!ok) { + p = QPixmap(":/icons-png/" + icon_name); + ok = !p.isNull(); + } + + if (ok) { + if (small) { + p = resize(&p); + } + if (size!=-1) { + p = resize(&p,size); + } + } else { + //qWarning("Images2::icon: icon '%s' not found", name.toUtf8().data()); + } + + return p; +} + +QPixmap Images::resize(QPixmap *p, int size) { + return QPixmap::fromImage( (*p).toImage().scaled(size,size,Qt::IgnoreAspectRatio,Qt::SmoothTransformation) ); +} + +QPixmap Images::flip(QPixmap *p) { + return QPixmap::fromImage( (*p).toImage().mirrored(true, false) ); +} + +QPixmap Images::flippedIcon(QString name, int size, bool png) { + QPixmap p = icon(name, size, png); + p = flip(&p); + return p; +} diff --git a/plugins/smplayer_plugin/images.h b/plugins/smplayer_plugin/images.h new file mode 100644 index 000000000..6d8f9f422 --- /dev/null +++ b/plugins/smplayer_plugin/images.h @@ -0,0 +1,46 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _IMAGES_H_ +#define _IMAGES_H_ + +#include +#include + +/* Warning: don't use this until global->preferences is created! */ +class Images +{ + +public: + static QPixmap icon(QString name, int size=-1, bool png = true); + static QPixmap flippedIcon(QString name, int size=-1, bool png = true); + + static QPixmap resize(QPixmap *p, int size=20); + static QPixmap flip(QPixmap *p); + +private: + //! Return the filename for the icon + static QString filename(const QString & name, bool png); + + //! Try to load an icon. \a icon_name is the filename of the + //! icon without path. Return a null pixmap if loads fails. + static QPixmap loadIcon(const QString & icon_name); +}; + +#endif + diff --git a/plugins/smplayer_plugin/infofile.cpp b/plugins/smplayer_plugin/infofile.cpp new file mode 100644 index 000000000..775c966a0 --- /dev/null +++ b/plugins/smplayer_plugin/infofile.cpp @@ -0,0 +1,219 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "infofile.h" +#include +#include +#include "helper.h" +#include "constants.h" + + +InfoFile::InfoFile() { + row = 0; +} + +InfoFile::~InfoFile() { +} + +QString InfoFile::getInfo(MediaData md) { + QString s; + + // General + QFileInfo fi(md.filename); + + QString icon; + switch (md.type) { + case TYPE_FILE : if (md.novideo) + icon = "type_audio.png"; + else + icon = "type_video.png"; + break; + case TYPE_DVD : icon = "type_dvd.png"; break; + case TYPE_VCD : icon = "type_vcd.png"; break; + case TYPE_AUDIO_CD : icon = "type_vcd.png"; break; + case TYPE_STREAM : icon = "type_url.png"; break; + default : icon = "type_unknown.png"; + } + icon = " "; + + if (md.type == TYPE_DVD) { + s += title( icon + "dvd://" + QString::number(Helper::dvdSplitTitle(md.filename) ) ); + } else { + s += title( icon + md.displayName() ); + } + + s += openPar( tr("General") ); + if (fi.exists()) { + //s += addItem( tr("Path"), fi.dirPath() ); + s += addItem( tr("File"), fi.absoluteFilePath() ); + s += addItem( tr("Size"), tr("%1 KB (%2 MB)").arg(fi.size()/1024) + .arg(fi.size()/1048576) ); + } else { + QString url = md.filename; + if (url.endsWith(IS_PLAYLIST_TAG)) { + url = url.remove( QRegExp(IS_PLAYLIST_TAG_RX) ); + } + s += addItem( tr("URL"), url ); + } + s += addItem( tr("Length"), Helper::formatTime((int)md.duration) ); + s += addItem( tr("Demuxer"), md.demuxer ); + s += closePar(); + + // Clip info + QString c; + if (!md.clip_name.isEmpty()) c+= addItem( tr("Name"), md.clip_name ); + if (!md.clip_artist.isEmpty()) c+= addItem( tr("Artist"), md.clip_artist ); + if (!md.clip_author.isEmpty()) c+= addItem( tr("Author"), md.clip_author ); + if (!md.clip_album.isEmpty()) c+= addItem( tr("Album"), md.clip_album ); + if (!md.clip_genre.isEmpty()) c+= addItem( tr("Genre"), md.clip_genre ); + if (!md.clip_date.isEmpty()) c+= addItem( tr("Date"), md.clip_date ); + if (!md.clip_track.isEmpty()) c+= addItem( tr("Track"), md.clip_track ); + if (!md.clip_copyright.isEmpty()) c+= addItem( tr("Copyright"), md.clip_copyright ); + if (!md.clip_comment.isEmpty()) c+= addItem( tr("Comment"), md.clip_comment ); + if (!md.clip_software.isEmpty()) c+= addItem( tr("Software"), md.clip_software ); + if (!md.stream_title.isEmpty()) c+= addItem( tr("Stream title"), md.stream_title ); + if (!md.stream_url.isEmpty()) c+= addItem( tr("Stream URL"), md.stream_url ); + + if (!c.isEmpty()) { + s += openPar( tr("Clip info") ); + s += c; + s += closePar(); + } + + // Video info + if (!md.novideo) { + s += openPar( tr("Video") ); + s += addItem( tr("Resolution"), QString("%1 x %2").arg(md.video_width).arg(md.video_height) ); + s += addItem( tr("Aspect ratio"), QString::number(md.video_aspect) ); + s += addItem( tr("Format"), md.video_format ); + s += addItem( tr("Bitrate"), tr("%1 kbps").arg(md.video_bitrate / 1000) ); + s += addItem( tr("Frames per second"), md.video_fps ); + s += addItem( tr("Selected codec"), md.video_codec ); + s += closePar(); + } + + // Audio info + s += openPar( tr("Initial Audio Stream") ); + s += addItem( tr("Format"), md.audio_format ); + s += addItem( tr("Bitrate"), tr("%1 kbps").arg(md.audio_bitrate / 1000) ); + s += addItem( tr("Rate"), tr("%1 Hz").arg(md.audio_rate) ); + s += addItem( tr("Channels"), QString::number(md.audio_nch) ); + s += addItem( tr("Selected codec"), md.audio_codec ); + s += closePar(); + + // Audio Tracks + if (md.audios.numItems() > 0) { + s += openPar( tr("Audio Streams") ); + row++; + s += openItem(); + s += "" + tr("#", "Info for translators: this is a abbreviation for number") + "" + + tr("Language") + "" + tr("Name") +"" + + tr("ID", "Info for translators: this is a identification code") + ""; + s += closeItem(); + for (int n = 0; n < md.audios.numItems(); n++) { + row++; + s += openItem(); + QString lang = md.audios.itemAt(n).lang(); + if (lang.isEmpty()) lang = "<"+tr("empty")+">"; + QString name = md.audios.itemAt(n).name(); + if (name.isEmpty()) name = "<"+tr("empty")+">"; + s += QString("%1%2%3%4") + .arg(n).arg(lang).arg(name) + .arg(md.audios.itemAt(n).ID()); + s += closeItem(); + } + s += closePar(); + } + + // Subtitles + if (md.subs.numItems() > 0) { + s += openPar( tr("Subtitles") ); + row++; + s += openItem(); + s += "" + tr("#", "Info for translators: this is a abbreviation for number") + "" + + tr("Type") + "" + + tr("Language") + "" + tr("Name") +"" + + tr("ID", "Info for translators: this is a identification code") + ""; + s += closeItem(); + for (int n = 0; n < md.subs.numItems(); n++) { + row++; + s += openItem(); + QString t; + switch (md.subs.itemAt(n).type()) { + case SubData::File: t = "FILE_SUB"; break; + case SubData::Vob: t = "VOB"; break; + default: t = "SUB"; + } + QString lang = md.subs.itemAt(n).lang(); + if (lang.isEmpty()) lang = "<"+tr("empty")+">"; + QString name = md.subs.itemAt(n).name(); + if (name.isEmpty()) name = "<"+tr("empty")+">"; + /* + s += QString("%1%2%3%4%5") + .arg(n).arg(t).arg(lang).arg(name) + .arg(md.subs.itemAt(n).ID()); + */ + s += "" + QString::number(n) + "" + t + + "" + lang + "" + name + + "" + QString::number(md.subs.itemAt(n).ID()) + ""; + s += closeItem(); + } + s += closePar(); + } + + return s; +} + +QString InfoFile::title(QString text) { + return "

    " + text + "

    "; +} + +QString InfoFile::openPar(QString text) { + return "

    " + text + "

    " + ""; +} + +QString InfoFile::closePar() { + row = 0; + return "
    "; +} + +QString InfoFile::openItem() { + if (row % 2 == 1) + return ""; + else + return ""; +} + +QString InfoFile::closeItem() { + return ""; +} + +QString InfoFile::addItem( QString tag, QString value ) { + row++; + return openItem() + + "" + tag + "" + + "" + value + "" + + closeItem(); +} + + +inline QString InfoFile::tr( const char * sourceText, const char * comment, int n ) { + return QCoreApplication::translate("InfoFile", sourceText, comment, QCoreApplication:: CodecForTr, n ); +} + diff --git a/plugins/smplayer_plugin/infofile.h b/plugins/smplayer_plugin/infofile.h new file mode 100644 index 000000000..4a36b90d5 --- /dev/null +++ b/plugins/smplayer_plugin/infofile.h @@ -0,0 +1,49 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _INFOFILE_H_ +#define _INFOFILE_H_ + +#include "mediadata.h" +#include + +class InfoFile +{ + +public: + InfoFile(); + ~InfoFile(); + + QString getInfo(MediaData md); + +protected: + QString title(QString text); + QString openPar(QString text); + QString closePar(); + QString openItem(); + QString closeItem(); + + QString addItem( QString tag, QString value ); + + int row; + +private: + inline QString tr( const char * sourceText, const char * comment = 0, int n = -1 ); +}; + +#endif diff --git a/plugins/smplayer_plugin/infoprovider.cpp b/plugins/smplayer_plugin/infoprovider.cpp new file mode 100644 index 000000000..84049c7ae --- /dev/null +++ b/plugins/smplayer_plugin/infoprovider.cpp @@ -0,0 +1,56 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "infoprovider.h" +#include "global.h" +#include "preferences.h" +#include "mplayerprocess.h" +#include + +MediaData InfoProvider::getInfo(QString mplayer_bin, QString filename) { + qDebug("InfoProvider::getInfo: %s", filename.toUtf8().data()); + + MplayerProcess proc; + + QFileInfo fi(mplayer_bin); + if (fi.exists() && fi.isExecutable() && !fi.isDir()) { + mplayer_bin = fi.absoluteFilePath(); + } + + proc.addArgument(mplayer_bin); + proc.addArgument("-identify"); + proc.addArgument("-frames"); + proc.addArgument("0"); + proc.addArgument("-vo"); + proc.addArgument("null"); + proc.addArgument("-ao"); + proc.addArgument("null"); + proc.addArgument(filename); + + proc.start(); + if (!proc.waitForFinished()) { + qWarning("InfoProvider::getInfo: process didn't finish. Killing it..."); + proc.kill(); + } + + return proc.mediaData(); +} + +MediaData InfoProvider::getInfo(QString filename) { + return getInfo( Global::pref->mplayer_bin, filename ); +} diff --git a/plugins/smplayer_plugin/infoprovider.h b/plugins/smplayer_plugin/infoprovider.h new file mode 100644 index 000000000..a18d8fb22 --- /dev/null +++ b/plugins/smplayer_plugin/infoprovider.h @@ -0,0 +1,40 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//! Reads info about a file (resolution, length...) + +#ifndef _INFOPROVIDER_H_ +#define _INFOPROVIDER_H_ + +#include +#include "mediadata.h" + +class InfoProvider +{ + +public: + //! Gets info about the specified filename. + static MediaData getInfo(QString mplayer_bin, QString filename); + + //! Gets info about the specified filename. The mplayer executable will be + // obtained from the global preferences. + static MediaData getInfo(QString filename); +}; + +#endif + diff --git a/plugins/smplayer_plugin/inforeader.cpp b/plugins/smplayer_plugin/inforeader.cpp new file mode 100644 index 000000000..0fe9a627d --- /dev/null +++ b/plugins/smplayer_plugin/inforeader.cpp @@ -0,0 +1,286 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "inforeader.h" +#include +#include +#include + +#include "helper.h" +#include "global.h" +#include "preferences.h" +#include "mplayerversion.h" + +#if USE_QPROCESS +#include +#else +#include "myprocess.h" +#endif + +using namespace Global; + +#define NOME 0 +#define VO 1 +#define AO 2 +#define DEMUXER 3 +#define VC 4 +#define AC 5 + +InfoReader * InfoReader::static_obj = 0; + +InfoReader * InfoReader::obj() { + if (!static_obj) { + static_obj = new InfoReader( pref->mplayer_bin ); + static_obj->getInfo(); + } + return static_obj; +} + +InfoReader::InfoReader( QString mplayer_bin, QObject * parent ) + : QObject(parent) +{ + mplayerbin = mplayer_bin; + +#if USE_QPROCESS + proc = new QProcess(this); + proc->setProcessChannelMode( QProcess::MergedChannels ); +#else + proc = new MyProcess(this); + + connect( proc, SIGNAL(lineAvailable(QByteArray)), + this, SLOT(readLine(QByteArray)) ); +#endif +} + +InfoReader::~InfoReader() { +} + +void InfoReader::getInfo() { + waiting_for_key = TRUE; + vo_list.clear(); + ao_list.clear(); + demuxer_list.clear(); + mplayer_svn = -1; + + run("-identify -vo help -ao help -demuxer help -vc help -ac help"); + + //list(); +} + +void InfoReader::list() { + qDebug("InfoReader::list"); + + InfoList::iterator it; + + qDebug(" vo_list:"); + for ( it = vo_list.begin(); it != vo_list.end(); ++it ) { + qDebug( "driver: '%s', desc: '%s'", (*it).name().toUtf8().data(), (*it).desc().toUtf8().data()); + } + + qDebug(" ao_list:"); + for ( it = ao_list.begin(); it != ao_list.end(); ++it ) { + qDebug( "driver: '%s', desc: '%s'", (*it).name().toUtf8().data(), (*it).desc().toUtf8().data()); + } + + qDebug(" demuxer_list:"); + for ( it = demuxer_list.begin(); it != demuxer_list.end(); ++it ) { + qDebug( "demuxer: '%s', desc: '%s'", (*it).name().toUtf8().data(), (*it).desc().toUtf8().data()); + } + + qDebug(" vc_list:"); + for ( it = vc_list.begin(); it != vc_list.end(); ++it ) { + qDebug( "codec: '%s', desc: '%s'", (*it).name().toUtf8().data(), (*it).desc().toUtf8().data()); + } + + qDebug(" ac_list:"); + for ( it = ac_list.begin(); it != ac_list.end(); ++it ) { + qDebug( "codec: '%s', desc: '%s'", (*it).name().toUtf8().data(), (*it).desc().toUtf8().data()); + } + +} + +static QRegExp rx_vo_key("^ID_VIDEO_OUTPUTS"); +static QRegExp rx_ao_key("^ID_AUDIO_OUTPUTS"); +static QRegExp rx_demuxer_key("^ID_DEMUXERS"); +static QRegExp rx_ac_key("^ID_AUDIO_CODECS"); +static QRegExp rx_vc_key("^ID_VIDEO_CODECS"); + +static QRegExp rx_driver("\\t(.*)\\t(.*)"); +static QRegExp rx_demuxer("^\\s+([A-Z,a-z,0-9]+)\\s+(\\d+)\\s+(\\S.*)"); +static QRegExp rx_codec("^([A-Z,a-z,0-9]+)\\s+([A-Z,a-z,0-9]+)\\s+([A-Z,a-z,0-9]+)\\s+(\\S.*)"); + +void InfoReader::readLine(QByteArray ba) { +#if COLOR_OUTPUT_SUPPORT + QString line = Helper::stripColorsTags(QString::fromLocal8Bit(ba)); +#else + QString line = QString::fromLocal8Bit(ba); +#endif + + qDebug("InfoReader::readLine: line: '%s'", line.toUtf8().data()); + //qDebug("waiting_for_key: %d", waiting_for_key); + + if (!waiting_for_key) { + if ( rx_driver.indexIn(line) > -1 ) { + QString name = rx_driver.cap(1); + QString desc = rx_driver.cap(2); + qDebug("InfoReader::readLine: found driver: '%s' '%s'", name.toUtf8().data(), desc.toUtf8().data()); + if (reading_type==VO) { + vo_list.append( InfoData(name, desc) ); + } + else + if (reading_type==AO) { + ao_list.append( InfoData(name, desc) ); + } + else + qWarning("InfoReader::readLine: Unknown type! Ignoring"); + } + else + if ( rx_demuxer.indexIn(line) > -1 ) { + QString name = rx_demuxer.cap(1); + QString desc = rx_demuxer.cap(3); + qDebug("InfoReader::readLine: found demuxer: '%s' '%s'", name.toUtf8().data(), desc.toUtf8().data()); + demuxer_list.append( InfoData(name, desc) ); + } + else + if ( rx_codec.indexIn(line) > -1 ) { + QString name = rx_codec.cap(1); + QString desc = rx_codec.cap(4); + qDebug("InfoReader::readLine: found codec: '%s' '%s'", name.toUtf8().data(), desc.toUtf8().data()); + if (reading_type==VC) { + vc_list.append( InfoData(name, desc) ); + } + else + if (reading_type==AC) { + ac_list.append( InfoData(name, desc) ); + } + else + qWarning("InfoReader::readLine: Unknown type! Ignoring"); + } + } + + if ( rx_vo_key.indexIn(line) > -1 ) { + reading_type = VO; + waiting_for_key = FALSE; + qDebug("InfoReader::readLine: found key: vo"); + } + + if ( rx_ao_key.indexIn(line) > -1 ) { + reading_type = AO; + waiting_for_key = FALSE; + qDebug("InfoReader::readLine: found key: ao"); + } + + if ( rx_demuxer_key.indexIn(line) > -1 ) { + reading_type = DEMUXER; + waiting_for_key = FALSE; + qDebug("InfoReader::readLine: found key: demuxer"); + } + + if ( rx_ac_key.indexIn(line) > -1 ) { + reading_type = AC; + waiting_for_key = FALSE; + qDebug("InfoReader::readLine: found key: ac"); + } + + if ( rx_vc_key.indexIn(line) > -1 ) { + reading_type = VC; + waiting_for_key = FALSE; + qDebug("InfoReader::readLines: found key: vc"); + } + + if (line.startsWith("MPlayer ")) { + mplayer_svn = MplayerVersion::mplayerVersion(line); + } +} + +#if USE_QPROCESS +bool InfoReader::run(QString options) { + qDebug("InfoReader::run: '%s'", options.toUtf8().data()); + qDebug("InfoReader::run: using QProcess"); + + if (proc->state() == QProcess::Running) { + qWarning("InfoReader::run: process already running"); + return false; + } + + QStringList args = options.split(" "); + + proc->start(mplayerbin, args); + if (!proc->waitForStarted()) { + qWarning("InfoReader::run: process can't start!"); + return false; + } + + //Wait until finish + if (!proc->waitForFinished()) { + qWarning("InfoReader::run: process didn't finish. Killing it..."); + proc->kill(); + } + + qDebug("InfoReader::run : terminating"); + + QByteArray ba; + while (proc->canReadLine()) { + ba = proc->readLine(); + ba.replace("\n", ""); + ba.replace("\r", ""); + readLine( ba ); + } + + return true; +} +#else +bool InfoReader::run(QString options) { + qDebug("InfoReader::run: '%s'", options.toUtf8().data()); + qDebug("InfoReader::run: using myprocess"); + + if (proc->isRunning()) { + qWarning("InfoReader::run: process already running"); + return false; + } + + proc->clearArguments(); + + proc->addArgument(mplayerbin); + + QStringList args = options.split(" "); + QStringList::Iterator it = args.begin(); + while( it != args.end() ) { + proc->addArgument( (*it) ); + ++it; + } + + proc->start(); + if (!proc->waitForStarted()) { + qWarning("InfoReader::run: process can't start!"); + return false; + } + + //Wait until finish + if (!proc->waitForFinished()) { + qWarning("InfoReader::run: process didn't finish. Killing it..."); + proc->kill(); + } + + qDebug("InfoReader::run : terminating"); + + return true; +} +#endif + +#include "moc_inforeader.cpp" diff --git a/plugins/smplayer_plugin/inforeader.h b/plugins/smplayer_plugin/inforeader.h new file mode 100644 index 000000000..ded58c8e2 --- /dev/null +++ b/plugins/smplayer_plugin/inforeader.h @@ -0,0 +1,109 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _INFOREADER_H_ +#define _INFOREADER_H_ + +#include +#include + +#define USE_QPROCESS 1 + +#if USE_QPROCESS +class QProcess; +#else +class MyProcess; +#endif + +class InfoData { + +public: + InfoData() {}; + InfoData( QString name, QString desc) { + _name = name; + _desc = desc; + }; + ~InfoData() {}; + + void setName(QString name) { _name = name; }; + void setDesc(QString desc) { _desc = desc; }; + + QString name() { return _name; }; + QString desc() { return _desc; }; + +private: + QString _name, _desc; +}; + + +typedef QList InfoList; + + +class InfoReader : QObject { + Q_OBJECT + +public: + InfoReader( QString mplayer_bin, QObject * parent = 0 ); + ~InfoReader(); + + void getInfo(); + + InfoList voList() { return vo_list; }; + InfoList aoList() { return ao_list; }; + InfoList demuxerList() { return demuxer_list; }; + InfoList vcList() { return vc_list; }; + InfoList acList() { return ac_list; }; + + int mplayerVersion() { return mplayer_svn; }; + + //! Returns an InfoReader objects. If it didn't exist before, one + //! is created and getInfo() is called. + static InfoReader * obj(); + +protected slots: + virtual void readLine(QByteArray); + +protected: + bool run(QString options); + void list(); + +protected: +#if USE_QPROCESS + QProcess * proc; +#else + MyProcess * proc; +#endif + QString mplayerbin; + + InfoList vo_list; + InfoList ao_list; + InfoList demuxer_list; + InfoList vc_list; + InfoList ac_list; + + int mplayer_svn; + +private: + bool waiting_for_key; + int reading_type; + + static InfoReader * static_obj; +}; + +#endif diff --git a/plugins/smplayer_plugin/input.conf b/plugins/smplayer_plugin/input.conf new file mode 100644 index 000000000..e847738a7 --- /dev/null +++ b/plugins/smplayer_plugin/input.conf @@ -0,0 +1,70 @@ +## prevent mplayer from messing up our shortcuts + +RIGHT invalid_command +LEFT invalid_command +DOWN invalid_command +UP invalid_command +PGUP invalid_command +PGDWN invalid_command +- invalid_command ++ invalid_command +ESC invalid_command +ENTER invalid_command +SPACE pausing_keep invalid_command +HOME invalid_command +END invalid_command +> invalid_command +< invalid_command +INS invalid_command +DEL invalid_command +[ invalid_command +] invalid_command +{ invalid_command +} invalid_command +BS invalid_command +TAB invalid_command +. invalid_command +# invalid_command +@ invalid_command +! invalid_command +9 invalid_command +/ invalid_command +0 invalid_command +* invalid_command +1 invalid_command +2 invalid_command +3 invalid_command +4 invalid_command +5 invalid_command +6 invalid_command +7 invalid_command +8 invalid_command +a invalid_command +b invalid_command +c invalid_command +d invalid_command +e invalid_command +F invalid_command +f invalid_command +g invalid_command +h invalid_command +i invalid_command +j invalid_command +k invalid_command +l invalid_command +m invalid_command +n invalid_command +o invalid_command +p invalid_command +q invalid_command +r invalid_command +s invalid_command +t invalid_command +T invalid_command +u invalid_command +v invalid_command +w invalid_command +x invalid_command +y invalid_command +z invalid_command +S invalid_command diff --git a/plugins/smplayer_plugin/inputdvddirectory.cpp b/plugins/smplayer_plugin/inputdvddirectory.cpp new file mode 100644 index 000000000..056cd72af --- /dev/null +++ b/plugins/smplayer_plugin/inputdvddirectory.cpp @@ -0,0 +1,58 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "inputdvddirectory.h" + +#include +#include "filedialog.h" + +InputDVDDirectory::InputDVDDirectory( QWidget* parent, Qt::WindowFlags f ) + : QDialog(parent, f) +{ + setupUi(this); +} + +InputDVDDirectory::~InputDVDDirectory() { +} + +void InputDVDDirectory::setFolder(QString folder) { + dvd_directory_edit->setText( folder ); +} + +QString InputDVDDirectory::folder() { + return dvd_directory_edit->text(); +} + +void InputDVDDirectory::on_searchButton_clicked() { + QString s = MyFileDialog::getExistingDirectory( + this, tr("Choose a directory"), + dvd_directory_edit->text() ); + /* + QString s = QFileDialog::getOpenFileName( + dvd_directory_edit->text(), + "*.*", this, + "select_dvd_device_dialog", + tr("Choose a directory or iso file") ); + */ + + if (!s.isEmpty()) { + dvd_directory_edit->setText(s); + } +} + +#include "moc_inputdvddirectory.cpp" diff --git a/plugins/smplayer_plugin/inputdvddirectory.h b/plugins/smplayer_plugin/inputdvddirectory.h new file mode 100644 index 000000000..b7bafdae7 --- /dev/null +++ b/plugins/smplayer_plugin/inputdvddirectory.h @@ -0,0 +1,40 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _INPUTDVDDIRECTORY_H_ +#define _INPUTDVDDIRECTORY_H_ + +#include "ui_inputdvddirectory.h" + +class InputDVDDirectory : public QDialog, public Ui::InputDVDDirectory +{ + Q_OBJECT + +public: + InputDVDDirectory( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~InputDVDDirectory(); + + void setFolder(QString folder); + QString folder(); + +protected slots: + void on_searchButton_clicked(); +}; + + +#endif diff --git a/plugins/smplayer_plugin/inputdvddirectory.ui b/plugins/smplayer_plugin/inputdvddirectory.ui new file mode 100644 index 000000000..143492031 --- /dev/null +++ b/plugins/smplayer_plugin/inputdvddirectory.ui @@ -0,0 +1,167 @@ + + InputDVDDirectory + + + + 0 + 0 + 586 + 140 + + + + SMPlayer - Play a DVD from a folder + + + true + + + + 9 + + + 6 + + + + + + 7 + 5 + 0 + 0 + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + + + Qt::AlignVCenter + + + true + + + + + + + 0 + + + 6 + + + + + + 7 + 0 + 0 + 0 + + + + + + + + Choose a directory... + + + + + + + + + + 7 + 0 + 0 + 0 + + + + QFrame::HLine + + + QFrame::Sunken + + + Qt::Horizontal + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + + + + buttonBox + accepted() + InputDVDDirectory + accept() + + + 468 + 185 + + + 286 + 132 + + + + + buttonBox + rejected() + InputDVDDirectory + reject() + + + 468 + 185 + + + 286 + 132 + + + + + diff --git a/plugins/smplayer_plugin/inputmplayerversion.cpp b/plugins/smplayer_plugin/inputmplayerversion.cpp new file mode 100644 index 000000000..d37b7d830 --- /dev/null +++ b/plugins/smplayer_plugin/inputmplayerversion.cpp @@ -0,0 +1,57 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "inputmplayerversion.h" +#include "mplayerversion.h" +#include +#include + +InputMplayerVersion::InputMplayerVersion( QWidget* parent, Qt::WindowFlags f ) + : QDialog(parent, f) +{ + setupUi(this); +} + +InputMplayerVersion::~InputMplayerVersion() { +} + +void InputMplayerVersion::setVersionFromOutput(QString text) { + orig_string->setText(text); +} + +void InputMplayerVersion::setVersion(int current_version) { + int index = 0; + + if (current_version == MPLAYER_1_0_RC2_SVN) index = 1; + else + if (current_version > MPLAYER_1_0_RC2_SVN) index = 2; + + version_combo->setCurrentIndex(index); +} + +int InputMplayerVersion::version() { + int r = -1; + switch (version_combo->currentIndex()) { + case 0 : r = MPLAYER_1_0_RC1_SVN; break; // rc1 or older + case 1 : r = MPLAYER_1_0_RC2_SVN; break; // rc2 + case 2 : r = 25844; break; // last svn at the moment of writing this + } + return r; +} + +#include "moc_inputmplayerversion.cpp" diff --git a/plugins/smplayer_plugin/inputmplayerversion.h b/plugins/smplayer_plugin/inputmplayerversion.h new file mode 100644 index 000000000..9e2ba4905 --- /dev/null +++ b/plugins/smplayer_plugin/inputmplayerversion.h @@ -0,0 +1,38 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _INPUTMPLAYERVERSION_H_ +#define _INPUTMPLAYERVERSION_H_ + +#include "ui_inputmplayerversion.h" + +class InputMplayerVersion : public QDialog, public Ui::InputMplayerVersion +{ + Q_OBJECT + +public: + InputMplayerVersion( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~InputMplayerVersion(); + + void setVersion(int current_version); + int version(); + + void setVersionFromOutput(QString text); +}; + +#endif diff --git a/plugins/smplayer_plugin/inputmplayerversion.ui b/plugins/smplayer_plugin/inputmplayerversion.ui new file mode 100644 index 000000000..d761363f8 --- /dev/null +++ b/plugins/smplayer_plugin/inputmplayerversion.ui @@ -0,0 +1,166 @@ + + Ricardo Villalba + InputMplayerVersion + + + + 0 + 0 + 458 + 199 + + + + SMPlayer - Enter the MPlayer version + + + + 9 + + + 6 + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Version reported by MPlayer: + + + + + + + true + + + + + + + Qt::Vertical + + + + 20 + 31 + + + + + + + + 0 + + + 6 + + + + + Please, &select the correct version: + + + version_combo + + + + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + InputMplayerVersion + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + InputMplayerVersion + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/smplayer_plugin/inputurl.cpp b/plugins/smplayer_plugin/inputurl.cpp new file mode 100644 index 000000000..2b8e6a83f --- /dev/null +++ b/plugins/smplayer_plugin/inputurl.cpp @@ -0,0 +1,78 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "inputurl.h" +#include "images.h" + +InputURL::InputURL( QWidget* parent, Qt::WindowFlags f ) + : QDialog(parent, f) +{ + setupUi(this); + + url_icon->setPixmap( Images::icon("url_big") ); + url_edit->setFocus(); + + playlist_check->setWhatsThis( + tr("If this option is checked, the URL will be treated as a playlist: " + "it will be opened as text and will play the URLs in it.") ); + + connect(url_edit, SIGNAL(currentIndexChanged(int)), this, SLOT(indexChanged())); + connect(playlist_check, SIGNAL(stateChanged(int)), this, SLOT(playlistChanged(int))); +} + +InputURL::~InputURL() { +} + +void InputURL::setURL(QString url, bool is_playlist) { + url_edit->addItem(url, is_playlist); +} + +QString InputURL::url() { + return url_edit->currentText(); +} + +void InputURL::setPlaylist(bool b) { + playlist_check->setChecked(b); + /* + int pos = url_edit->currentIndex(); + url_edit->setItemData(pos, b); + */ +} + +bool InputURL::isPlaylist() { + return playlist_check->isChecked(); +} + +void InputURL::indexChanged(void) { + int pos = url_edit->currentIndex(); + if (url_edit->itemText(pos) == url_edit->currentText()) { + playlist_check->setChecked( url_edit->itemData(pos).toBool() ); + } +} + +void InputURL::playlistChanged(int state) { + /* + int pos = url_edit->currentIndex(); + if (url_edit->itemText(pos) == url_edit->currentText()) { + bool is_playlist = (state == Qt::Checked); + url_edit->setItemIcon( pos, is_playlist ? Images::icon("playlist") : QIcon() ); + } + */ +} + +#include "moc_inputurl.cpp" diff --git a/plugins/smplayer_plugin/inputurl.h b/plugins/smplayer_plugin/inputurl.h new file mode 100644 index 000000000..da5bcab07 --- /dev/null +++ b/plugins/smplayer_plugin/inputurl.h @@ -0,0 +1,44 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _INPUTURL_H_ +#define _INPUTURL_H_ + +#include "ui_inputurl.h" +#include + +class InputURL : public QDialog, public Ui::InputURL +{ + Q_OBJECT + +public: + InputURL( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~InputURL(); + + void setURL(QString url, bool is_playlist); + QString url(); + + void setPlaylist(bool b); + bool isPlaylist(); + +protected slots: + void indexChanged(); + void playlistChanged(int); +}; + +#endif diff --git a/plugins/smplayer_plugin/inputurl.ui b/plugins/smplayer_plugin/inputurl.ui new file mode 100644 index 000000000..f79bd628e --- /dev/null +++ b/plugins/smplayer_plugin/inputurl.ui @@ -0,0 +1,156 @@ + + InputURL + + + + 0 + 0 + 608 + 126 + + + + SMPlayer - Enter URL + + + + 9 + + + 6 + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + It's a &playlist + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + 6 + + + 0 + + + + + &URL: + + + url_edit + + + + + + + true + + + + 0 + 0 + + + + + + + + + + + + + :/icons-png/url_big.png + + + + + + + url_edit + playlist_check + buttonBox + + + + + + + buttonBox + accepted() + InputURL + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + InputURL + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/smplayer_plugin/languages.cpp b/plugins/smplayer_plugin/languages.cpp new file mode 100644 index 000000000..bf6555e3c --- /dev/null +++ b/plugins/smplayer_plugin/languages.cpp @@ -0,0 +1,283 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "languages.h" + +QMap Languages::list() { + QMap l; + + l["aa"] = tr("Afar"); + l["ab"] = tr("Abkhazian"); + l["ae"] = tr("Avestan"); + l["af"] = tr("Afrikaans"); + l["ak"] = tr("Akan"); + l["am"] = tr("Amharic"); + l["an"] = tr("Aragonese"); + l["ar"] = tr("Arabic"); + l["as"] = tr("Assamese"); + l["av"] = tr("Avaric"); + l["ay"] = tr("Aymara"); + l["az"] = tr("Azerbaijani"); + l["ba"] = tr("Bashkir"); + l["be"] = tr("Belarusian"); + l["bg"] = tr("Bulgarian"); + l["bh"] = tr("Bihari"); + l["bi"] = tr("Bislama"); + l["bm"] = tr("Bambara"); + l["bn"] = tr("Bengali"); + l["bo"] = tr("Tibetan"); + l["br"] = tr("Breton"); + l["bs"] = tr("Bosnian"); + l["ca"] = tr("Catalan"); + l["ce"] = tr("Chechen"); + l["co"] = tr("Corsican"); + l["cr"] = tr("Cree"); + l["cs"] = tr("Czech"); + l["cu"] = tr("Church"); + l["cv"] = tr("Chuvash"); + l["cy"] = tr("Welsh"); + l["da"] = tr("Danish"); + l["de"] = tr("German"); + l["dv"] = tr("Divehi"); + l["dz"] = tr("Dzongkha"); + l["ee"] = tr("Ewe"); + l["el"] = tr("Greek"); + l["en"] = tr("English"); + l["eo"] = tr("Esperanto"); + l["es"] = tr("Spanish"); + l["et"] = tr("Estonian"); + l["eu"] = tr("Basque"); + l["fa"] = tr("Persian"); + l["ff"] = tr("Fulah"); + l["fi"] = tr("Finnish"); + l["fj"] = tr("Fijian"); + l["fo"] = tr("Faroese"); + l["fr"] = tr("French"); + l["fy"] = tr("Frisian"); + l["ga"] = tr("Irish"); + l["gd"] = tr("Gaelic"); + l["gl"] = tr("Galician"); + l["gn"] = tr("Guarani"); + l["gu"] = tr("Gujarati"); + l["gv"] = tr("Manx"); + l["ha"] = tr("Hausa"); + l["he"] = tr("Hebrew"); + l["hi"] = tr("Hindi"); + l["ho"] = tr("Hiri"); + l["hr"] = tr("Croatian"); + l["ht"] = tr("Haitian"); + l["hu"] = tr("Hungarian"); + l["hy"] = tr("Armenian"); + l["hz"] = tr("Herero"); + l["ch"] = tr("Chamorro"); + l["ia"] = tr("Interlingua"); + l["id"] = tr("Indonesian"); + l["ie"] = tr("Interlingue"); + l["ig"] = tr("Igbo"); + l["ii"] = tr("Sichuan"); + l["ik"] = tr("Inupiaq"); + l["io"] = tr("Ido"); + l["is"] = tr("Icelandic"); + l["it"] = tr("Italian"); + l["iu"] = tr("Inuktitut"); + l["ja"] = tr("Japanese"); + l["jv"] = tr("Javanese"); + l["ka"] = tr("Georgian"); + l["kg"] = tr("Kongo"); + l["ki"] = tr("Kikuyu"); + l["kj"] = tr("Kuanyama"); + l["kk"] = tr("Kazakh"); + l["kl"] = tr("Greenlandic"); + l["km"] = tr("Khmer"); + l["kn"] = tr("Kannada"); + l["ko"] = tr("Korean"); + l["kr"] = tr("Kanuri"); + l["ks"] = tr("Kashmiri"); + l["ku"] = tr("Kurdish"); + l["kv"] = tr("Komi"); + l["kw"] = tr("Cornish"); + l["ky"] = tr("Kirghiz"); + l["la"] = tr("Latin"); + l["lb"] = tr("Luxembourgish"); + l["lg"] = tr("Ganda"); + l["li"] = tr("Limburgan"); + l["ln"] = tr("Lingala"); + l["lo"] = tr("Lao"); + l["lt"] = tr("Lithuanian"); + l["lu"] = tr("Luba-Katanga"); + l["lv"] = tr("Latvian"); + l["mg"] = tr("Malagasy"); + l["mh"] = tr("Marshallese"); + l["mi"] = tr("Maori"); + l["mk"] = tr("Macedonian"); + l["ml"] = tr("Malayalam"); + l["mn"] = tr("Mongolian"); + l["mo"] = tr("Moldavian"); + l["mr"] = tr("Marathi"); + l["ms"] = tr("Malay"); + l["mt"] = tr("Maltese"); + l["my"] = tr("Burmese"); + l["na"] = tr("Nauru"); + l["nb"] = trUtf8("Bokmål"); + l["nd"] = tr("Ndebele"); + l["ne"] = tr("Nepali"); + l["ng"] = tr("Ndonga"); + l["nl"] = tr("Dutch"); + l["nn"] = tr("Norwegian"); + l["no"] = tr("Norwegian"); + l["nr"] = tr("Ndebele"); + l["nv"] = tr("Navajo"); + l["ny"] = tr("Chichewa"); + l["oc"] = tr("Occitan"); + l["oj"] = tr("Ojibwa"); + l["om"] = tr("Oromo"); + l["or"] = tr("Oriya"); + l["os"] = tr("Ossetian"); + l["pa"] = tr("Panjabi"); + l["pi"] = tr("Pali"); + l["pl"] = tr("Polish"); + l["ps"] = tr("Pushto"); + l["pt"] = tr("Portuguese"); + l["qu"] = tr("Quechua"); + l["rm"] = tr("Romansh"); + l["rn"] = tr("Rundi"); + l["ro"] = tr("Romanian"); + l["ru"] = tr("Russian"); + l["rw"] = tr("Kinyarwanda"); + l["sa"] = tr("Sanskrit"); + l["sc"] = tr("Sardinian"); + l["sd"] = tr("Sindhi"); + l["se"] = tr("Sami"); + l["sg"] = tr("Sango"); + l["si"] = tr("Sinhala"); + l["sk"] = tr("Slovak"); + l["sl"] = tr("Slovenian"); + l["sm"] = tr("Samoan"); + l["sn"] = tr("Shona"); + l["so"] = tr("Somali"); + l["sq"] = tr("Albanian"); + l["sr"] = tr("Serbian"); + l["ss"] = tr("Swati"); + l["st"] = tr("Sotho"); + l["su"] = tr("Sundanese"); + l["sv"] = tr("Swedish"); + l["sw"] = tr("Swahili"); + l["ta"] = tr("Tamil"); + l["te"] = tr("Telugu"); + l["tg"] = tr("Tajik"); + l["th"] = tr("Thai"); + l["ti"] = tr("Tigrinya"); + l["tk"] = tr("Turkmen"); + l["tl"] = tr("Tagalog"); + l["tn"] = tr("Tswana"); + l["to"] = tr("Tonga"); + l["tr"] = tr("Turkish"); + l["ts"] = tr("Tsonga"); + l["tt"] = tr("Tatar"); + l["tw"] = tr("Twi"); + l["ty"] = tr("Tahitian"); + l["ug"] = tr("Uighur"); + l["uk"] = tr("Ukrainian"); + l["ur"] = tr("Urdu"); + l["uz"] = tr("Uzbek"); + l["ve"] = tr("Venda"); + l["vi"] = tr("Vietnamese"); + l["vo"] = trUtf8("Volapük"); + l["wa"] = tr("Walloon"); + l["wo"] = tr("Wolof"); + l["xh"] = tr("Xhosa"); + l["yi"] = tr("Yiddish"); + l["yo"] = tr("Yoruba"); + l["za"] = tr("Zhuang"); + l["zh"] = tr("Chinese"); + l["zu"] = tr("Zulu"); + + return l; +} + +QMap Languages::translations() { + QMap m; + m["ar_SY"] = tr("Arabic"); + m["bg"] = tr("Bulgarian"); + m["ca"] = tr("Catalan"); + m["cs"] = tr("Czech"); + m["de"] = tr("German"); + m["el_GR"] = tr("Greek"); + m["en_US"] = tr("English"); + m["es"] = tr("Spanish"); + m["eu"] = tr("Basque"); + m["fi"] = tr("Finnish"); + m["fr"] = tr("French"); + m["gl"] = tr("Galician"); + m["hu"] = tr("Hungarian"); + m["it"] = tr("Italian"); + m["ja"] = tr("Japanese"); + m["ka"] = tr("Georgian"); + m["ko"] = tr("Korean"); + m["ku"] = tr("Kurdish"); + m["mk"] = tr("Macedonian"); + m["nl"] = tr("Dutch"); + m["pl"] = tr("Polish"); + m["pt_BR"] = tr("Portuguese - Brazil"); + m["pt_PT"] = tr("Portuguese - Portugal"); + m["ro_RO"] = tr("Romanian"); + m["ru_RU"] = tr("Russian"); + m["sk"] = tr("Slovak"); + m["sl_SI"] = tr("Slovenian"); + m["sr"] = tr("Serbian"); + m["sv"] = tr("Swedish"); + m["tr"] = tr("Turkish"); + m["uk_UA"] = tr("Ukrainian"); + m["zh_CN"] = tr("Simplified-Chinese"); + m["zh_TW"] = tr("Traditional Chinese"); + + return m; +} + +QMap Languages::encodings() { + QMap l; + + l["Unicode"] = tr("Unicode"); + l["UTF-8"] = tr("UTF-8"); + l["ISO-8859-1"] = tr("Western European Languages"); + l["ISO-8859-15"] = tr("Western European Languages with Euro"); + l["ISO-8859-2"] = tr("Slavic/Central European Languages"); + l["ISO-8859-3"] = tr("Esperanto, Galician, Maltese, Turkish"); + l["ISO-8859-4"] = tr("Old Baltic charset"); + l["ISO-8859-5"] = tr("Cyrillic"); + l["ISO-8859-6"] = tr("Arabic"); + l["ISO-8859-7"] = tr("Modern Greek"); + l["ISO-8859-9"] = tr( "Turkish"); + l["ISO-8859-13"] = tr( "Baltic"); + l["ISO-8859-14"] = tr( "Celtic"); + l["ISO-8859-8"] = tr( "Hebrew charsets"); + l["KOI8-R"] = tr( "Russian"); + l["KOI8-U/RU"] = tr( "Ukrainian, Belarusian"); + l["CP936"] = tr( "Simplified Chinese charset"); + l["BIG5"] = tr( "Traditional Chinese charset"); + l["SHIFT-JIS"] = tr( "Japanese charsets"); + l["CP949"] = tr( "Korean charset"); + l["CP874"] = tr( "Thai charset"); + l["CP1251"] = tr( "Cyrillic Windows"); + l["CP1250"] = tr( "Slavic/Central European Windows"); + l["CP1256"] = tr( "Arabic Windows"); + + return l; +} + +#include "moc_languages.cpp" diff --git a/plugins/smplayer_plugin/languages.h b/plugins/smplayer_plugin/languages.h new file mode 100644 index 000000000..c204bb424 --- /dev/null +++ b/plugins/smplayer_plugin/languages.h @@ -0,0 +1,41 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _LANGUAGES_H_ +#define _LANGUAGES_H_ + +#include +#include + +class Languages : public QObject +{ + Q_OBJECT + +public: + + //! Returns the ISO_639-1 language list + static QMap list(); + + //! Returns the list of translations available + static QMap translations(); + + static QMap encodings(); +}; + +#endif + diff --git a/plugins/smplayer_plugin/languages/list.txt b/plugins/smplayer_plugin/languages/list.txt new file mode 100644 index 000000000..64768c52d --- /dev/null +++ b/plugins/smplayer_plugin/languages/list.txt @@ -0,0 +1,164 @@ +aa Afar +ab Abkhazian +af Afrikaans +am Amharic +ar Arabic +as Assamese +ay Aymara +az Azerbaijani + +ba Bashkir +be Byelorussian +bg Bulgarian +bh Bihari +bi Bislama +bn Bengali; Bangla +bo Tibetan +br Breton + +ca Catalan +co Corsican +cs Czech +cy Welsh + +da Danish +de German +dz Bhutani + +el Greek +en English +eo Esperanto +es Spanish +et Estonian +eu Basque + +fa Persian +fi Finnish +fj Fiji +fo Faroese +fr French +fy Frisian + +ga Irish +gd Scots Gaelic +gl Galician +gn Guarani +gu Gujarati + +ha Hausa +he Hebrew (formerly iw) +hi Hindi +hr Croatian +hu Hungarian +hy Armenian + +ia Interlingua +id Indonesian (formerly in) +ie Interlingue +ik Inupiak +is Icelandic +it Italian +iu Inuktitut + +ja Japanese +jw Javanese + +ka Georgian +kk Kazakh +kl Greenlandic +km Cambodian +kn Kannada +ko Korean +ks Kashmiri +ku Kurdish +ky Kirghiz + +la Latin +ln Lingala +lo Laothian +lt Lithuanian +lv Latvian, Lettish + +mg Malagasy +mi Maori +mk Macedonian +ml Malayalam +mn Mongolian +mo Moldavian +mr Marathi +ms Malay +mt Maltese +my Burmese + +na Nauru +ne Nepali +nl Dutch +no Norwegian + +oc Occitan +om (Afan) Oromo +or Oriya + +pa Punjabi +pl Polish +ps Pashto, Pushto +pt Portuguese + +qu Quechua + +rm Rhaeto-Romance +rn Kirundi +ro Romanian +ru Russian +rw Kinyarwanda + +sa Sanskrit +sd Sindhi +sg Sangho +sh Serbo-Croatian +si Sinhalese +sk Slovak +sl Slovenian +sm Samoan +sn Shona +so Somali +sq Albanian +sr Serbian +ss Siswati +st Sesotho +su Sundanese +sv Swedish +sw Swahili + +ta Tamil +te Telugu +tg Tajik +th Thai +ti Tigrinya +tk Turkmen +tl Tagalog +tn Setswana +to Tonga +tr Turkish +ts Tsonga +tt Tatar +tw Twi + +ug Uighur +uk Ukrainian +ur Urdu +uz Uzbek + +vi Vietnamese +vo Volapuk + +wo Wolof + +xh Xhosa + +yi Yiddish (formerly ji) +yo Yoruba + +za Zhuang +zh Chinese +zu Zulu diff --git a/plugins/smplayer_plugin/languages/main.cpp b/plugins/smplayer_plugin/languages/main.cpp new file mode 100644 index 000000000..40bc6e166 --- /dev/null +++ b/plugins/smplayer_plugin/languages/main.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + +int main( int argc, char ** argv ) +{ + QFile file("list.txt"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + return -1; + + QRegExp rx("^([a-zA-Z]+) ([a-zA-Z\\-]+)"); + + QString line; + while (!file.atEnd()) { + line = QString(file.readLine()).simplified(); + if (!line.isEmpty()) { + //qDebug("%s", line.toLatin1().constData()); + if (rx.indexIn(line) > -1) { + QString s1 = rx.cap(1); + QString s2 = rx.cap(2); + //qDebug("code: %s, language: %s", s1.toLatin1().constData(), s2.toLatin1().constData()); + printf("\tl[\"%s\"] = tr(\"%s\");\n", s1.toLatin1().constData(), s2.toLatin1().constData()); + } + } + } + file.close(); + + return 0; +} + diff --git a/plugins/smplayer_plugin/languages/process_list.pro b/plugins/smplayer_plugin/languages/process_list.pro new file mode 100644 index 000000000..28dcadcbf --- /dev/null +++ b/plugins/smplayer_plugin/languages/process_list.pro @@ -0,0 +1 @@ +SOURCES += main.cpp diff --git a/plugins/smplayer_plugin/logwindow.cpp b/plugins/smplayer_plugin/logwindow.cpp new file mode 100644 index 000000000..c0efee41a --- /dev/null +++ b/plugins/smplayer_plugin/logwindow.cpp @@ -0,0 +1,144 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "logwindow.h" +#include +#include "filedialog.h" +#include +#include +#include +#include +#include + +#include "images.h" + +LogWindow::LogWindow( QWidget* parent ) + : QWidget(parent, Qt::Window ) +{ + setupUi(this); + + browser->setFont( QFont("fixed") ); + + retranslateStrings(); +} + +LogWindow::~LogWindow() { +} + +/* +QTextEdit * LogWindow::editor() { + return browser; +} +*/ + +void LogWindow::retranslateStrings() { + retranslateUi(this); + + saveButton->setText(""); + copyButton->setText(""); + + saveButton->setIcon( Images::icon("save") ); + copyButton->setIcon( Images::icon("copy") ); + + setWindowIcon( Images::icon("logo") ); +} + + +void LogWindow::setText(QString log) { + browser->setPlainText(log); +} + +QString LogWindow::text() { + return browser->toPlainText(); +} + +void LogWindow::setHtml(QString text) { + browser->setHtml(text); +} + +QString LogWindow::html() { + return browser->toHtml(); +} + +void LogWindow::clear() { + browser->clear(); +} + +void LogWindow::appendText(QString text) { + browser->moveCursor(QTextCursor::End); + browser->insertPlainText(text); +} + +void LogWindow::appendHtml(QString text) { + browser->moveCursor(QTextCursor::End); + browser->insertHtml(text); +} + +void LogWindow::on_copyButton_clicked() { + browser->selectAll(); + browser->copy(); +} + +void LogWindow::on_saveButton_clicked() { + QString s = MyFileDialog::getSaveFileName( + this, tr("Choose a filename to save under"), + "", tr("Logs") +" (*.log *.txt)" ); + + if (!s.isEmpty()) { + if (QFileInfo(s).exists()) { + int res =QMessageBox::question( this, + tr("Confirm overwrite?"), + tr("The file already exists.\n" + "Do you want to overwrite?"), + QMessageBox::Yes, + QMessageBox::No, + QMessageBox::NoButton); + if (res == QMessageBox::No ) { + return; + } + } + + QFile file( s ); + if ( file.open( QIODevice::WriteOnly ) ) { + QTextStream stream( &file ); + stream << browser->toPlainText(); + file.close(); + } else { + // Error opening file + qDebug("LogWindow::save: error saving file"); + QMessageBox::warning ( this, + tr("Error saving file"), + tr("The log couldn't be saved"), + QMessageBox::Ok, + QMessageBox::NoButton, + QMessageBox::NoButton ); + + } + } +} + +// Language change stuff +void LogWindow::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QWidget::changeEvent(e); + } +} + +#include "moc_logwindow.cpp" diff --git a/plugins/smplayer_plugin/logwindow.h b/plugins/smplayer_plugin/logwindow.h new file mode 100644 index 000000000..633b0f43f --- /dev/null +++ b/plugins/smplayer_plugin/logwindow.h @@ -0,0 +1,57 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _LOGWINDOW_H_ +#define _LOGWINDOW_H_ + +#include "ui_logwindowbase.h" + +class QTextEdit; + +class LogWindow : public QWidget, public Ui::LogWindowBase +{ + Q_OBJECT + +public: + LogWindow( QWidget* parent = 0); + ~LogWindow(); + + void setText(QString log); + QString text(); + + void setHtml(QString text); + QString html(); + + void clear(); + + void appendText(QString text); + void appendHtml(QString text); + + /* QTextEdit * editor(); */ + +protected: + virtual void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + +protected slots: + void on_copyButton_clicked(); + void on_saveButton_clicked(); +}; + + +#endif diff --git a/plugins/smplayer_plugin/logwindowbase.ui b/plugins/smplayer_plugin/logwindowbase.ui new file mode 100644 index 000000000..682fb5bb0 --- /dev/null +++ b/plugins/smplayer_plugin/logwindowbase.ui @@ -0,0 +1,108 @@ + + Ricardo Villalba + LogWindowBase + + + + 0 + 0 + 615 + 541 + + + + Log Window + + + + 11 + + + 6 + + + + + true + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 191 + 21 + + + + + + + + Save + + + Save + + + + + + + Copy to clipboard + + + Copy to clipboard + + + + + + + Close + + + &Close + + + + + + + + + + + + closeButton + clicked() + LogWindowBase + close() + + + 20 + 20 + + + 20 + 20 + + + + + diff --git a/plugins/smplayer_plugin/main.cpp b/plugins/smplayer_plugin/main.cpp new file mode 100644 index 000000000..6600e921d --- /dev/null +++ b/plugins/smplayer_plugin/main.cpp @@ -0,0 +1,271 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include + +#include "smplayer.h" +#include "global.h" +#include "helper.h" +#include "paths.h" + +#include + +#define USE_LOCKS 1 +#if USE_LOCKS +#ifdef USE_QXT +#define USE_QXT_LOCKS 1 +#endif // USE_QXT +#endif // USE_LOCKS + +#if USE_LOCKS && USE_QXT_LOCKS +#include +#endif + +using namespace Global; + +BaseGui * basegui_instance = 0; + +void myMessageOutput( QtMsgType type, const char *msg ) { + static QStringList saved_lines; + static QString orig_line; + static QString line2; + static QRegExp rx_log; + + if (pref) { + if (!pref->log_smplayer) return; + rx_log.setPattern(pref->log_filter); + } else { + rx_log.setPattern(".*"); + } + + line2.clear(); + + orig_line = QString::fromUtf8(msg); + + switch ( type ) { + case QtDebugMsg: + if (rx_log.indexIn(orig_line) > -1) { + #ifndef NO_DEBUG_ON_CONSOLE + fprintf( stderr, "Debug: %s\n", orig_line.toLocal8Bit().data() ); + #endif + line2 = orig_line; + } + break; + case QtWarningMsg: + #ifndef NO_DEBUG_ON_CONSOLE + fprintf( stderr, "Warning: %s\n", orig_line.toLocal8Bit().data() ); + #endif + line2 = "WARNING: " + orig_line; + break; + case QtFatalMsg: + #ifndef NO_DEBUG_ON_CONSOLE + fprintf( stderr, "Fatal: %s\n", orig_line.toLocal8Bit().data() ); + #endif + line2 = "FATAL: " + orig_line; + abort(); // deliberately core dump + case QtCriticalMsg: + #ifndef NO_DEBUG_ON_CONSOLE + fprintf( stderr, "Critical: %s\n", orig_line.toLocal8Bit().data() ); + #endif + line2 = "CRITICAL: " + orig_line; + break; + } + + if (line2.isEmpty()) return; + + line2 = "["+ QTime::currentTime().toString() +"] "+ line2; + + if (basegui_instance) { + if (!saved_lines.isEmpty()) { + // Send saved lines first + for (int n=0; n < saved_lines.count(); n++) { + basegui_instance->recordSmplayerLog(saved_lines[n]); + } + saved_lines.clear(); + } + basegui_instance->recordSmplayerLog(line2); + } else { + // GUI is not created yet, save lines for later + saved_lines.append(line2); + } +} + +#if USE_LOCKS +#if USE_QXT_LOCKS +bool create_lock(QFile * f, QxtFileLock * lock) { + bool success = false; + if (f->open(QIODevice::ReadWrite)) { + if (lock->lock()) { + f->write("smplayer lock file"); + success = true; + } + } + if (!success) f->close(); + return success; +} + +void clean_lock(QFile * f, QxtFileLock * lock) { + qDebug("main: clean_lock: %s", f->fileName().toUtf8().data()); + lock->unlock(); + f->close(); + f->remove(); +} +#else +void remove_lock(QString lock_file) { + if (QFile::exists(lock_file)) { + qDebug("main: remove_lock: %s", lock_file.toUtf8().data()); + QFile::remove(lock_file); + } +} +#endif +#endif + +class MyApplication : public QApplication +{ +public: + MyApplication ( int & argc, char ** argv ) : QApplication(argc, argv) {}; + virtual void commitData ( QSessionManager & /*manager*/ ) { + // Nothing to do, let the application to close + } +}; + +int main( int argc, char ** argv ) +{ + MyApplication a( argc, argv ); + //a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) ); + + // Sets the config path + QString config_path; + +#ifdef PORTABLE_APP + config_path = a.applicationDirPath(); +#else + // If a smplayer.ini exists in the app path, will use that path + // for the config file by default + if (QFile::exists( a.applicationDirPath() + "/smplayer.ini" ) ) { + config_path = a.applicationDirPath(); + qDebug("main: using existing %s", QString(config_path + "/smplayer.ini").toUtf8().data()); + } +#endif + + QStringList args = a.arguments(); + int pos = args.indexOf("-config-path"); + if ( pos != -1) { + if (pos+1 < args.count()) { + pos++; + config_path = args[pos]; + // Delete from list + args.removeAt(pos); + args.removeAt(pos-1); + } else { + printf("Error: expected parameter for -config-path\r\n"); + return SMPlayer::ErrorArgument; + } + } + + qInstallMsgHandler( myMessageOutput ); + +#if USE_LOCKS + //setIniPath will be set later in global_init, but we need it here + if (!config_path.isEmpty()) Paths::setConfigPath(config_path); + + QString lock_file = Paths::iniPath() + "/smplayer_init.lock"; + qDebug("main: lock_file: %s", lock_file.toUtf8().data()); + +#if USE_QXT_LOCKS + QFile f(lock_file); + QxtFileLock write_lock(&f, 0x10, 30, QxtFileLock::WriteLock); + + bool lock_ok = create_lock(&f, &write_lock); + + if (!lock_ok) { + //lock failed + qDebug("main: lock failed"); + + // Wait 10 secs max. + int n = 100; + while ( n > 0) { + Helper::msleep(100); // wait 100 ms + //if (!QFile::exists(lock_file)) break; + if (create_lock(&f, &write_lock)) break; + n--; + if ((n % 10) == 0) qDebug("main: waiting %d...", n); + } + // Continue startup + } +#else + if (QFile::exists(lock_file)) { + qDebug("main: %s exists, waiting...", lock_file.toUtf8().data()); + // Wait 10 secs max. + int n = 100; + while ( n > 0) { + Helper::msleep(100); // wait 100 ms + if (!QFile::exists(lock_file)) break; + n--; + if ((n % 10) == 0) qDebug("main: waiting %d...", n); + } + remove_lock(lock_file); + } else { + // Create lock file + QFile f(lock_file); + if (f.open(QIODevice::WriteOnly)) { + f.write("smplayer lock file"); + f.close(); + } else { + qWarning("main: can't open %s for writing", lock_file.toUtf8().data()); + } + + } +#endif // USE_QXT_LOCKS +#endif // USE_LOCKS + + SMPlayer * smplayer = new SMPlayer(config_path); + SMPlayer::ExitCode c = smplayer->processArgs( args ); + if (c != SMPlayer::NoExit) { +#if USE_LOCKS +#if USE_QXT_LOCKS + clean_lock(&f, &write_lock); +#else + remove_lock(lock_file); +#endif +#endif + return c; + } + + basegui_instance = smplayer->gui(); + a.connect(smplayer->gui(), SIGNAL(quitSolicited()), &a, SLOT(quit())); + smplayer->start(); + +#if USE_LOCKS +#if USE_QXT_LOCKS + clean_lock(&f, &write_lock); +#else + remove_lock(lock_file); +#endif +#endif + + int r = a.exec(); + + basegui_instance = 0; + delete smplayer; + + return r; +} + diff --git a/plugins/smplayer_plugin/mediadata.cpp b/plugins/smplayer_plugin/mediadata.cpp new file mode 100644 index 000000000..7fb0d179a --- /dev/null +++ b/plugins/smplayer_plugin/mediadata.cpp @@ -0,0 +1,149 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mediadata.h" +#include +#include + + +MediaData::MediaData() { + reset(); +} + +MediaData::~MediaData() { +} + +void MediaData::reset() { + filename=""; + dvd_id=""; + type = TYPE_UNKNOWN; + duration=0; + + novideo = FALSE; + + video_width=0; + video_height=0; + video_aspect= (double) 4/3; + + videos.clear(); + audios.clear(); + titles.clear(); + + subs.clear(); + +#if GENERIC_CHAPTER_SUPPORT + chapters = 0; +#else + //chapters=0; + //angles=0; + + mkv_chapters=0; +#endif + + initialized=false; + + // Clip info; + clip_name = ""; + clip_artist = ""; + clip_author = ""; + clip_album = ""; + clip_genre = ""; + clip_date = ""; + clip_track = ""; + clip_copyright = ""; + clip_comment = ""; + clip_software = ""; + + stream_title = ""; + stream_url = ""; + + // Other data + demuxer=""; + video_format=""; + audio_format=""; + video_bitrate=0; + video_fps=""; + audio_bitrate=0; + audio_rate=0; + audio_nch=0; + video_codec=""; + audio_codec=""; +} + +QString MediaData::displayName() { + if (!clip_name.isEmpty()) return clip_name; + else + if (!stream_title.isEmpty()) return stream_title; + + QFileInfo fi(filename); + if (fi.exists()) + return fi.fileName(); // filename without path + else + return filename; +} + + +void MediaData::list() { + qDebug("MediaData::list"); + + qDebug(" filename: '%s'", filename.toUtf8().data()); + qDebug(" duration: %f", duration); + + qDebug(" video_width: %d", video_width); + qDebug(" video_height: %d", video_height); + qDebug(" video_aspect: %f", video_aspect); + + qDebug(" type: %d", type); + qDebug(" novideo: %d", novideo); + qDebug(" dvd_id: '%s'", dvd_id.toUtf8().data()); + + qDebug(" initialized: %d", initialized); + +#if GENERIC_CHAPTER_SUPPORT + qDebug(" chapters: %d", chapters); +#else + qDebug(" mkv_chapters: %d", mkv_chapters); +#endif + + qDebug(" Subs:"); + subs.list(); + + qDebug(" Videos:"); + videos.list(); + + qDebug(" Audios:"); + audios.list(); + + qDebug(" Titles:"); + titles.list(); + + //qDebug(" chapters: %d", chapters); + //qDebug(" angles: %d", angles); + + qDebug(" demuxer: '%s'", demuxer.toUtf8().data() ); + qDebug(" video_format: '%s'", video_format.toUtf8().data() ); + qDebug(" audio_format: '%s'", audio_format.toUtf8().data() ); + qDebug(" video_bitrate: %d", video_bitrate ); + qDebug(" video_fps: '%s'", video_fps.toUtf8().data() ); + qDebug(" audio_bitrate: %d", audio_bitrate ); + qDebug(" audio_rate: %d", audio_rate ); + qDebug(" audio_nch: %d", audio_nch ); + qDebug(" video_codec: '%s'", video_codec.toUtf8().data() ); + qDebug(" audio_codec: '%s'", audio_codec.toUtf8().data() ); +} + diff --git a/plugins/smplayer_plugin/mediadata.h b/plugins/smplayer_plugin/mediadata.h new file mode 100644 index 000000000..be8dd4c10 --- /dev/null +++ b/plugins/smplayer_plugin/mediadata.h @@ -0,0 +1,115 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MEDIADATA_H_ +#define _MEDIADATA_H_ + +/* Here we store some volatile info about the file we need to remember */ + +#include "tracks.h" +#include "subtracks.h" +#include "titletracks.h" +#include "config.h" + +#include +#include + + +// Types of media + +#define TYPE_UNKNOWN -1 +#define TYPE_FILE 0 +#define TYPE_DVD 1 +#define TYPE_STREAM 2 +#define TYPE_VCD 3 +#define TYPE_AUDIO_CD 4 + +class MediaData { + +public: + MediaData(); + virtual ~MediaData(); + + virtual void reset(); + + QString filename; + double duration; + + //Resolution of the video + int video_width; + int video_height; + double video_aspect; + + int type; // file, dvd... + QString dvd_id; + + bool novideo; // Only audio + + bool initialized; + + void list(); + + Tracks videos; + Tracks audios; + TitleTracks titles; // for DVDs + + SubTracks subs; + +#if GENERIC_CHAPTER_SUPPORT + int chapters; +#else + //int chapters, angles; // for DVDs + + // Matroshka chapters + int mkv_chapters; +#endif + + // Clip info + QString clip_name; + QString clip_artist; + QString clip_author; + QString clip_album; + QString clip_genre; + QString clip_date; + QString clip_track; + QString clip_copyright; + QString clip_comment; + QString clip_software; + + QString stream_title; + QString stream_url; + + + // Other data not really useful for us, + // just to show info to the user. + QString demuxer; + QString video_format; + QString audio_format; + int video_bitrate; + QString video_fps; + int audio_bitrate; + int audio_rate; + int audio_nch; // channels? + QString video_codec; + QString audio_codec; + + /*QString info();*/ + QString displayName(); +}; + +#endif diff --git a/plugins/smplayer_plugin/mediasettings.cpp b/plugins/smplayer_plugin/mediasettings.cpp new file mode 100644 index 000000000..f2162063e --- /dev/null +++ b/plugins/smplayer_plugin/mediasettings.cpp @@ -0,0 +1,424 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mediasettings.h" +#include "preferences.h" +#include "global.h" +#include + +using namespace Global; + +MediaSettings::MediaSettings() { + reset(); +} + +MediaSettings::~MediaSettings() { +} + +void MediaSettings::reset() { + current_sec = 0; + //current_sub_id = SubNone; + current_sub_id = NoneSelected; + current_video_id = NoneSelected; + current_audio_id = NoneSelected; + current_title_id = NoneSelected; + current_chapter_id = NoneSelected; + current_angle_id = NoneSelected; + + aspect_ratio_id = AspectAuto; + + //fullscreen = FALSE; + volume = pref->initial_volume; + mute = false; + external_subtitles = ""; + external_audio = ""; + sub_delay=0; + audio_delay=0; + sub_pos = pref->initial_sub_pos; // 100% by default + sub_scale = pref->initial_sub_scale; + sub_scale_ass = pref->initial_sub_scale_ass; + + brightness = pref->initial_brightness; + contrast = pref->initial_contrast; + gamma = pref->initial_gamma; + hue = pref->initial_hue; + saturation = pref->initial_saturation; + + audio_equalizer = pref->initial_audio_equalizer; + + speed = 1.0; + + phase_filter = false; + current_denoiser = NoDenoise; + deblock_filter = false; + dering_filter = false; + noise_filter = false; + postprocessing_filter = pref->initial_postprocessing; + upscaling_filter = false; + + //current_deinterlacer = NoDeinterlace; + current_deinterlacer = pref->initial_deinterlace; + +#if NEW_ASPECT_CODE + add_letterbox = false; +#else + letterbox = NoLetterbox; + panscan_filter = ""; + crop_43to169_filter = ""; +#endif + + karaoke_filter = false; + extrastereo_filter = false; + volnorm_filter = pref->initial_volnorm; + + audio_use_channels = pref->initial_audio_channels; //ChDefault; // (0) + stereo_mode = pref->initial_stereo_mode; //Stereo; // (0) + + panscan_factor = pref->initial_panscan_factor; // 1.0; + + starting_time = -1; // Not set yet. + + rotate = NoRotate; + flip = false; + mirror = false; + + is264andHD = false; + + forced_demuxer=""; + forced_video_codec=""; + forced_audio_codec=""; + + original_demuxer=""; + original_video_codec=""; + original_audio_codec=""; + + mplayer_additional_options=""; + mplayer_additional_video_filters=""; + mplayer_additional_audio_filters=""; + + win_width=400; + win_height=300; +} + +double MediaSettings::win_aspect() { + return (double) win_width / win_height; +} + + +#if NEW_ASPECT_CODE +double MediaSettings::aspectToNum(Aspect aspect) { + double asp; + + switch (aspect) { + case MediaSettings::AspectNone: asp = 0; break; + case MediaSettings::Aspect43: asp = (double) 4 / 3; break; + case MediaSettings::Aspect169: asp = (double) 16 / 9; break; + case MediaSettings::Aspect149: asp = (double) 14 / 9; break; + case MediaSettings::Aspect1610: asp = (double) 16 / 10; break; + case MediaSettings::Aspect54: asp = (double) 5 / 4; break; + case MediaSettings::Aspect235: asp = 2.35; break; + case MediaSettings::Aspect11: asp = 1; break; + case MediaSettings::AspectAuto: asp = win_aspect(); break; + default: asp = win_aspect(); + qWarning("MediaSettings::aspectToNum: invalid aspect: %d", aspect); + } + + return asp; +} + +QString MediaSettings::aspectToString(Aspect aspect) { + QString asp_name; + + switch (aspect) { + case MediaSettings::AspectNone: asp_name = QObject::tr("disabled", "aspect_ratio"); break; + case MediaSettings::Aspect43: asp_name = "4:3"; break; + case MediaSettings::Aspect169: asp_name = "16:9"; break; + case MediaSettings::Aspect149: asp_name = "14:9"; break; + case MediaSettings::Aspect1610: asp_name = "16:10"; break; + case MediaSettings::Aspect54: asp_name = "5:4"; break; + case MediaSettings::Aspect235: asp_name = "2.35:1"; break; + case MediaSettings::Aspect11: asp_name = "1:1"; break; + case MediaSettings::AspectAuto: asp_name = QObject::tr("auto", "aspect_ratio"); break; + default: asp_name = QObject::tr("unknown", "aspect_ratio"); + } + + return asp_name; +} +#endif + +void MediaSettings::list() { + qDebug("MediaSettings::list"); + + qDebug(" current_sec: %f", current_sec); + qDebug(" current_sub_id: %d", current_sub_id); + qDebug(" current_video_id: %d", current_video_id); + qDebug(" current_audio_id: %d", current_audio_id); + qDebug(" current_title_id: %d", current_title_id); + qDebug(" current_chapter_id: %d", current_chapter_id); + qDebug(" current_angle_id: %d", current_angle_id); + + qDebug(" aspect_ratio_id: %d", aspect_ratio_id); + //qDebug(" fullscreen: %d", fullscreen); + qDebug(" volume: %d", volume); + qDebug(" mute: %d", mute); + qDebug(" external_subtitles: '%s'", external_subtitles.toUtf8().data()); + qDebug(" external_audio: '%s'", external_audio.toUtf8().data()); + qDebug(" sub_delay: %d", sub_delay); + qDebug(" audio_delay: %d", sub_delay); + qDebug(" sub_pos: %d", sub_pos); + qDebug(" sub_scale: %f", sub_scale); + qDebug(" sub_scale_ass: %f", sub_scale_ass); + + qDebug(" brightness: %d", brightness); + qDebug(" contrast: %d", contrast); + qDebug(" gamma: %d", gamma); + qDebug(" hue: %d", hue); + qDebug(" saturation: %d", saturation); + + qDebug(" speed: %f", speed); + + qDebug(" phase_filter: %d", phase_filter); + qDebug(" current_denoiser: %d", current_denoiser); + qDebug(" deblock_filter: %d", deblock_filter); + qDebug(" dering_filter: %d", dering_filter); + qDebug(" noise_filter: %d", noise_filter); + qDebug(" postprocessing_filter: %d", postprocessing_filter); + qDebug(" upscaling_filter: %d", upscaling_filter); + + qDebug(" current_deinterlacer: %d", current_deinterlacer); +#if NEW_ASPECT_CODE + qDebug(" add_letterbox: %d", add_letterbox); +#else + qDebug(" letterbox: %d", letterbox); + qDebug(" panscan_filter: '%s'", panscan_filter.toUtf8().data()); + qDebug(" crop_43to169_filter: '%s'", crop_43to169_filter.toUtf8().data()); +#endif + qDebug(" karaoke_filter: %d", karaoke_filter); + qDebug(" extrastereo_filter: %d", extrastereo_filter); + qDebug(" volnorm_filter: %d", volnorm_filter); + + qDebug(" audio_use_channels: %d", audio_use_channels); + qDebug(" stereo_mode: %d", stereo_mode); + + qDebug(" panscan_factor: %f", panscan_factor); + + qDebug(" rotate: %d", rotate); + qDebug(" flip: %d", flip); + qDebug(" mirror: %d", mirror); + + qDebug(" forced_demuxer: '%s'", forced_demuxer.toUtf8().data()); + qDebug(" forced_video_codec: '%s'", forced_video_codec.toUtf8().data()); + qDebug(" forced_audio_codec: '%s'", forced_video_codec.toUtf8().data()); + + qDebug(" original_demuxer: '%s'", original_demuxer.toUtf8().data()); + qDebug(" original_video_codec: '%s'", original_video_codec.toUtf8().data()); + qDebug(" original_audio_codec: '%s'", original_video_codec.toUtf8().data()); + + qDebug(" mplayer_additional_options: '%s'", mplayer_additional_options.toUtf8().data()); + qDebug(" mplayer_additional_video_filters: '%s'", mplayer_additional_video_filters.toUtf8().data()); + qDebug(" mplayer_additional_audio_filters: '%s'", mplayer_additional_audio_filters.toUtf8().data()); + + qDebug(" win_width: %d", win_width); + qDebug(" win_height: %d", win_height); + qDebug(" win_aspect(): %f", win_aspect()); + + qDebug(" starting_time: %f", starting_time); + qDebug(" is264andHD: %d", is264andHD); +} + +#ifndef NO_USE_INI_FILES +void MediaSettings::save(QSettings * set) { + qDebug("MediaSettings::save"); + + //QSettings * set = settings; + + /*set->beginGroup( "mediasettings" );*/ + + set->setValue( "current_sec", current_sec ); + set->setValue( "current_sub_id", current_sub_id ); + set->setValue( "current_video_id", current_video_id ); + set->setValue( "current_audio_id", current_audio_id ); + set->setValue( "current_title_id", current_title_id ); + set->setValue( "current_chapter_id", current_chapter_id ); + set->setValue( "current_angle_id", current_angle_id ); + + set->setValue( "aspect_ratio", aspect_ratio_id ); + //set->setValue( "fullscreen", fullscreen ); + set->setValue( "volume", volume ); + set->setValue( "mute", mute ); + set->setValue( "external_subtitles", external_subtitles ); + set->setValue( "external_audio", external_audio ); + set->setValue( "sub_delay", sub_delay); + set->setValue( "audio_delay", audio_delay); + set->setValue( "sub_pos", sub_pos); + set->setValue( "sub_scale", sub_scale); + set->setValue( "sub_scale_ass", sub_scale_ass); + + set->setValue( "brightness", brightness); + set->setValue( "contrast", contrast); + set->setValue( "gamma", gamma); + set->setValue( "hue", hue); + set->setValue( "saturation", saturation); + + set->setValue("audio_equalizer", audio_equalizer ); + + set->setValue( "speed", speed); + + set->setValue( "phase_filter", phase_filter); + set->setValue( "current_denoiser", current_denoiser); + set->setValue( "deblock_filter", deblock_filter); + set->setValue( "dering_filter", dering_filter); + set->setValue( "noise_filter", noise_filter); + set->setValue( "postprocessing_filter", postprocessing_filter); + set->setValue( "upscaling_filter", upscaling_filter); + + set->setValue( "current_deinterlacer", current_deinterlacer); +#if NEW_ASPECT_CODE + set->setValue( "add_letterbox", add_letterbox ); +#else + set->setValue( "letterbox", letterbox ); + set->setValue( "panscan_filter", panscan_filter); + set->setValue( "crop_43to169_filter", crop_43to169_filter); +#endif + set->setValue( "karaoke_filter", karaoke_filter); + set->setValue( "extrastereo_filter", extrastereo_filter); + set->setValue( "volnorm_filter", volnorm_filter); + + set->setValue( "audio_use_channels", audio_use_channels); + set->setValue( "stereo_mode", stereo_mode); + + set->setValue( "panscan_factor", panscan_factor); + + set->setValue( "rotate", rotate ); + set->setValue( "flip", flip); + set->setValue( "mirror", mirror); + + set->setValue( "forced_demuxer", forced_demuxer); + set->setValue( "forced_video_codec", forced_video_codec); + set->setValue( "forced_audio_codec", forced_audio_codec); + + set->setValue( "original_demuxer", original_demuxer); + set->setValue( "original_video_codec", original_video_codec); + set->setValue( "original_audio_codec", original_audio_codec); + + set->setValue( "mplayer_additional_options", mplayer_additional_options); + set->setValue( "mplayer_additional_video_filters", mplayer_additional_video_filters); + set->setValue( "mplayer_additional_audio_filters", mplayer_additional_audio_filters); + + set->setValue( "win_width", win_width ); + set->setValue( "win_height", win_height ); + + set->setValue( "starting_time", starting_time ); + + set->setValue( "is264andHD", is264andHD ); + + /*set->endGroup();*/ +} + +void MediaSettings::load(QSettings * set) { + qDebug("MediaSettings::load"); + + //QSettings * set = settings; + + /*set->beginGroup( "mediasettings" );*/ + + current_sec = set->value( "current_sec", current_sec).toDouble(); + current_sub_id = set->value( "current_sub_id", current_sub_id ).toInt(); + current_video_id = set->value( "current_video_id", current_video_id ).toInt(); + current_audio_id = set->value( "current_audio_id", current_audio_id ).toInt(); + current_title_id = set->value( "current_title_id", current_title_id ).toInt(); + current_chapter_id = set->value( "current_chapter_id", current_chapter_id ).toInt(); + current_angle_id = set->value( "current_angle_id", current_angle_id ).toInt(); + + aspect_ratio_id = set->value( "aspect_ratio", aspect_ratio_id ).toInt(); + //fullscreen = set->value( "fullscreen", fullscreen ).toBool(); + volume = set->value( "volume", volume ).toInt(); + mute = set->value( "mute", mute ).toBool(); + external_subtitles = set->value( "external_subtitles", external_subtitles ).toString(); + external_audio = set->value( "external_audio", external_audio ).toString(); + sub_delay = set->value( "sub_delay", sub_delay).toInt(); + audio_delay = set->value( "audio_delay", audio_delay).toInt(); + sub_pos = set->value( "sub_pos", sub_pos).toInt(); + sub_scale = set->value( "sub_scale", sub_scale).toDouble(); + sub_scale_ass = set->value( "sub_scale_ass", sub_scale_ass).toDouble(); + + brightness = set->value( "brightness", brightness).toInt(); + contrast = set->value( "contrast", contrast).toInt(); + gamma = set->value( "gamma", gamma).toInt(); + hue = set->value( "hue", hue).toInt(); + saturation = set->value( "saturation", saturation).toInt(); + + audio_equalizer = set->value("audio_equalizer", audio_equalizer ).toList(); + + speed = set->value( "speed", speed ).toDouble(); + + phase_filter = set->value( "phase_filter", phase_filter ).toBool(); + current_denoiser = set->value( "current_denoiser", current_denoiser).toInt(); + deblock_filter = set->value( "deblock_filter", deblock_filter).toBool(); + dering_filter = set->value( "dering_filter", dering_filter).toBool(); + noise_filter = set->value( "noise_filter", noise_filter).toBool(); + postprocessing_filter = set->value( "postprocessing_filter", postprocessing_filter).toBool(); + upscaling_filter = set->value( "upscaling_filter", upscaling_filter).toBool(); + + current_deinterlacer = set->value( "current_deinterlacer", current_deinterlacer ).toInt(); +#if NEW_ASPECT_CODE + add_letterbox = set->value( "add_letterbox", add_letterbox ).toBool(); +#else + letterbox = (LetterboxType) set->value( "letterbox", letterbox ).toInt(); + panscan_filter = set->value( "panscan_filter", panscan_filter).toString(); + crop_43to169_filter = set->value( "crop_43to169_filter", crop_43to169_filter).toString(); +#endif + karaoke_filter = set->value( "karaoke_filter", karaoke_filter).toBool(); + extrastereo_filter = set->value( "extrastereo_filter", extrastereo_filter).toBool(); + volnorm_filter = set->value( "volnorm_filter", volnorm_filter).toBool(); + + audio_use_channels = set->value( "audio_use_channels", audio_use_channels).toInt(); + stereo_mode = set->value( "stereo_mode", stereo_mode).toInt(); + + panscan_factor = set->value( "panscan_factor", panscan_factor).toDouble(); + + rotate = set->value( "rotate", rotate).toInt(); + flip = set->value( "flip", flip).toBool(); + mirror = set->value( "mirror", mirror).toBool(); + + forced_demuxer = set->value( "forced_demuxer", forced_demuxer).toString(); + forced_video_codec = set->value( "forced_video_codec", forced_video_codec).toString(); + forced_audio_codec = set->value( "forced_audio_codec", forced_audio_codec).toString(); + + original_demuxer = set->value( "original_demuxer", original_demuxer).toString(); + original_video_codec = set->value( "original_video_codec", original_video_codec).toString(); + original_audio_codec = set->value( "original_audio_codec", original_audio_codec).toString(); + + mplayer_additional_options = set->value( "mplayer_additional_options", mplayer_additional_options).toString(); + mplayer_additional_video_filters = set->value( "mplayer_additional_video_filters", mplayer_additional_video_filters).toString(); + mplayer_additional_audio_filters = set->value( "mplayer_additional_audio_filters", mplayer_additional_audio_filters).toString(); + + win_width = set->value( "win_width", win_width ).toInt(); + win_height = set->value( "win_height", win_height ).toInt(); + + starting_time = set->value( "starting_time", starting_time ).toDouble(); + + is264andHD = set->value( "is264andHD", is264andHD ).toBool(); + + /*set->endGroup();*/ + + // ChDefault not used anymore + if (audio_use_channels == ChDefault) audio_use_channels = ChStereo; +} + +#endif // NO_USE_INI_FILES diff --git a/plugins/smplayer_plugin/mediasettings.h b/plugins/smplayer_plugin/mediasettings.h new file mode 100644 index 000000000..47ca2f4cf --- /dev/null +++ b/plugins/smplayer_plugin/mediasettings.h @@ -0,0 +1,177 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MEDIASETTINGS_H_ +#define _MEDIASETTINGS_H_ + + +/* Settings the user has set for this file, and that we need to */ +/* restore the video after a restart */ + +#include +#include +#include "config.h" +#include "audioequalizerlist.h" + +class QSettings; + +class MediaSettings { + +public: + enum Denoise { NoDenoise = 0, DenoiseNormal = 1, DenoiseSoft = 2 }; +#if NEW_ASPECT_CODE + enum Aspect { AspectAuto = 1, Aspect43 = 2, Aspect54 = 3, Aspect149 = 4, + Aspect169 = 5, Aspect1610 = 6, Aspect235 = 7, Aspect11 = 8, + AspectNone = 0 }; +#else + enum Aspect { AspectAuto = 1, Aspect43 = 2, Aspect169 = 3, Aspect235 = 4, + Aspect43Letterbox = 5, Aspect43Panscan = 6, + Aspect43To169 = 7, Aspect149 = 8, Aspect1610 = 9, + Aspect54 = 10, Aspect169Letterbox = 11 }; + enum LetterboxType { NoLetterbox = 0, Letterbox_43 = 1, Letterbox_169 = 2 }; +#endif + enum Deinterlace { NoDeinterlace = 0, L5 = 1, Yadif = 2, LB = 3, + Yadif_1 = 4, Kerndeint = 5 }; + enum AudioChannels { ChDefault = 0, ChStereo = 2, ChSurround = 4, + ChFull51 = 6 }; + enum StereoMode { Stereo = 0, Left = 1, Right = 2 }; + + enum Rotate { NoRotate = -1, Clockwise_flip = 0, Clockwise = 1, + Counterclockwise = 2, Counterclockwise_flip = 3 }; + + enum IDs { NoneSelected = -1000, SubNone = 90000 }; + + MediaSettings(); + virtual ~MediaSettings(); + + virtual void reset(); + + double current_sec; + int current_sub_id; + + int current_video_id; + int current_audio_id; + + int current_title_id; + int current_chapter_id; + int current_angle_id; + + int aspect_ratio_id; + + //bool fullscreen; + + int volume; + bool mute; + + int brightness, contrast, gamma, hue, saturation; + + AudioEqualizerList audio_equalizer; + + QString external_subtitles; + QString external_audio; // external audio file + + int sub_delay; + int audio_delay; + + // Subtitles position (0-100) + int sub_pos; + double sub_scale; + double sub_scale_ass; + + double speed; // Speed of playback: 1.0 = normal speed + + int current_deinterlacer; + +#if NEW_ASPECT_CODE + bool add_letterbox; +#else + LetterboxType letterbox; // Force letterbox + QString panscan_filter; + QString crop_43to169_filter; +#endif + + // Filters in menu + bool phase_filter; + int current_denoiser; + bool deblock_filter; + bool dering_filter; + bool noise_filter; + bool postprocessing_filter; + bool upscaling_filter; //!< Software scaling + + bool karaoke_filter; + bool extrastereo_filter; + bool volnorm_filter; + + int audio_use_channels; + int stereo_mode; + + double panscan_factor; // mplayerwindow zoom + + int rotate; + bool flip; //!< Flip image + bool mirror; //!< Mirrors the image on the Y axis. + + // This a property of the video and it should be + // in mediadata, but we have to save it to preserve + // this data among restarts. + double starting_time; // Some videos don't start at 0 + + //! The codec of the video is ffh264 and it's high definition + bool is264andHD; + + // Advanced settings + QString forced_demuxer; + QString forced_video_codec; + QString forced_audio_codec; + + // A copy of the original values, so we can restore them. + QString original_demuxer; + QString original_video_codec; + QString original_audio_codec; + + // Options to mplayer (for this file only) + QString mplayer_additional_options; + QString mplayer_additional_video_filters; + QString mplayer_additional_audio_filters; + + // Some things that were before in mediadata + // They can vary, because of filters, so better here + + //Resolution used by mplayer + //Can be bigger that video resolution + //because of the aspect ratio or expand filter + int win_width; + int win_height; + double win_aspect(); + +#if NEW_ASPECT_CODE + //! Returns the aspect as a double. Returns 0 if aspect == AspectNone. + double aspectToNum(Aspect aspect); + static QString aspectToString(Aspect aspect); +#endif + + void list(); + +#ifndef NO_USE_INI_FILES + void save(QSettings * set); + void load(QSettings * set); +#endif +}; + +#endif diff --git a/plugins/smplayer_plugin/minigui.cpp b/plugins/smplayer_plugin/minigui.cpp new file mode 100644 index 000000000..7f523de8f --- /dev/null +++ b/plugins/smplayer_plugin/minigui.cpp @@ -0,0 +1,276 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "minigui.h" +#include "widgetactions.h" +#include "floatingwidget.h" +#include "myaction.h" +#include "mplayerwindow.h" +#include "global.h" +#include "helper.h" +#include "toolbareditor.h" +#include "desktopinfo.h" + +#include +#include + +using namespace Global; + +MiniGui::MiniGui( QWidget * parent, Qt::WindowFlags flags ) + : BaseGuiPlus( parent, flags ) +{ + createActions(); + createControlWidget(); + createFloatingControl(); + + connect( this, SIGNAL(cursorNearBottom(QPoint)), + this, SLOT(showFloatingControl(QPoint)) ); + + connect( this, SIGNAL(cursorFarEdges()), + this, SLOT(hideFloatingControl()) ); + + statusBar()->hide(); + + retranslateStrings(); + + loadConfig(); + + if (pref->compact_mode) { + controlwidget->hide(); + } +} + +MiniGui::~MiniGui() { + saveConfig(); +} + +void MiniGui::createActions() { + timeslider_action = createTimeSliderAction(this); + timeslider_action->disable(); + +#if USE_VOLUME_BAR + volumeslider_action = createVolumeSliderAction(this); + volumeslider_action->disable(); +#endif + + time_label_action = new TimeLabelAction(this); + time_label_action->setObjectName("timelabel_action"); + + connect( this, SIGNAL(timeChanged(QString)), + time_label_action, SLOT(setText(QString)) ); +} + + +void MiniGui::createControlWidget() { + controlwidget = new QToolBar( this ); + controlwidget->setObjectName("controlwidget"); + controlwidget->setMovable(true); + controlwidget->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); + addToolBar(Qt::BottomToolBarArea, controlwidget); + +#if !USE_CONFIGURABLE_TOOLBARS + controlwidget->addAction(playOrPauseAct); + controlwidget->addAction(stopAct); + controlwidget->addSeparator(); + controlwidget->addAction(timeslider_action); + controlwidget->addSeparator(); + controlwidget->addAction(fullscreenAct); + controlwidget->addAction(muteAct); + +#if USE_VOLUME_BAR + controlwidget->addAction(volumeslider_action); +#endif + +#endif // USE_CONFIGURABLE_TOOLBARS +} + +void MiniGui::createFloatingControl() { + // Floating control + floating_control = new FloatingWidget(this); + +#if !USE_CONFIGURABLE_TOOLBARS + floating_control->toolbar()->addAction(playOrPauseAct); + floating_control->toolbar()->addAction(stopAct); + floating_control->toolbar()->addSeparator(); + floating_control->toolbar()->addAction(timeslider_action); + floating_control->toolbar()->addSeparator(); + floating_control->toolbar()->addAction(fullscreenAct); + floating_control->toolbar()->addAction(muteAct); +#if USE_VOLUME_BAR + floating_control->toolbar()->addAction(volumeslider_action); +#endif + + floating_control->adjustSize(); +#endif // USE_CONFIGURABLE_TOOLBARS +} + +void MiniGui::retranslateStrings() { + BaseGuiPlus::retranslateStrings(); + + controlwidget->setWindowTitle( tr("Control bar") ); +} + +#if AUTODISABLE_ACTIONS +void MiniGui::enableActionsOnPlaying() { + BaseGuiPlus::enableActionsOnPlaying(); + + timeslider_action->enable(); +#if USE_VOLUME_BAR + volumeslider_action->enable(); +#endif +} + +void MiniGui::disableActionsOnStop() { + BaseGuiPlus::disableActionsOnStop(); + + timeslider_action->disable(); +#if USE_VOLUME_BAR + volumeslider_action->disable(); +#endif +} +#endif // AUTODISABLE_ACTIONS + +void MiniGui::aboutToEnterFullscreen() { + BaseGuiPlus::aboutToEnterFullscreen(); + + if (!pref->compact_mode) { + controlwidget->hide(); + } +} + +void MiniGui::aboutToExitFullscreen() { + BaseGuiPlus::aboutToExitFullscreen(); + + floating_control->hide(); + + if (!pref->compact_mode) { + statusBar()->hide(); + controlwidget->show(); + } +} + +void MiniGui::aboutToEnterCompactMode() { + BaseGuiPlus::aboutToEnterCompactMode(); + + controlwidget->hide(); +} + +void MiniGui::aboutToExitCompactMode() { + BaseGuiPlus::aboutToExitCompactMode(); + + statusBar()->hide(); + + controlwidget->show(); +} + +void MiniGui::showFloatingControl(QPoint /*p*/) { +#ifndef Q_OS_WIN + floating_control->setBypassWindowManager(pref->bypass_window_manager); +#endif + floating_control->setAnimated( pref->floating_control_animated ); + floating_control->setMargin(pref->floating_control_margin); + floating_control->showOver(panel, + pref->floating_control_width, + FloatingWidget::Bottom); +} + +void MiniGui::hideFloatingControl() { + floating_control->hide(); +} + +#if USE_MINIMUMSIZE +QSize MiniGui::minimumSizeHint() const { + return QSize(controlwidget->sizeHint().width(), 0); +} +#endif + + +void MiniGui::saveConfig() { + QSettings * set = settings; + + set->beginGroup( "mini_gui"); + + if (pref->save_window_size_on_exit) { + qDebug("MiniGui::saveConfig: w: %d h: %d", width(), height()); + set->setValue( "pos", pos() ); + set->setValue( "size", size() ); + } + + set->setValue( "toolbars_state", saveState(Helper::qtVersion()) ); + +#if USE_CONFIGURABLE_TOOLBARS + set->beginGroup( "actions" ); + set->setValue("controlwidget", ToolbarEditor::save(controlwidget) ); + set->setValue("floating_control", ToolbarEditor::save(floating_control->toolbar()) ); + set->endGroup(); +#endif + + set->endGroup(); +} + +void MiniGui::loadConfig() { + QSettings * set = settings; + + set->beginGroup( "mini_gui"); + + if (pref->save_window_size_on_exit) { + QPoint p = set->value("pos", pos()).toPoint(); + QSize s = set->value("size", size()).toSize(); + + if ( (s.height() < 200) && (!pref->use_mplayer_window) ) { + s = pref->default_size; + } + + move(p); + resize(s); + + if (!DesktopInfo::isInsideScreen(this)) { + move(0,0); + qWarning("MiniGui::loadConfig: window is outside of the screen, moved to 0x0"); + } + } + +#if USE_CONFIGURABLE_TOOLBARS + QList actions_list = findChildren(); + QStringList controlwidget_actions; + controlwidget_actions << "play_or_pause" << "stop" << "separator" << "timeslider_action" << "separator" + << "fullscreen" << "mute" << "volumeslider_action"; + + QStringList floatingcontrol_actions; + floatingcontrol_actions << "play_or_pause" << "stop" << "separator" << "timeslider_action" << "separator" + << "fullscreen" << "mute"; +#if USE_VOLUME_BAR + floatingcontrol_actions << "volumeslider_action"; +#endif + + floatingcontrol_actions << "separator" << "timelabel_action"; + + set->beginGroup( "actions" ); + ToolbarEditor::load(controlwidget, set->value("controlwidget", controlwidget_actions).toStringList(), actions_list ); + ToolbarEditor::load(floating_control->toolbar(), set->value("floating_control", floatingcontrol_actions).toStringList(), actions_list ); + floating_control->adjustSize(); + set->endGroup(); +#endif + + restoreState( set->value( "toolbars_state" ).toByteArray(), Helper::qtVersion() ); + + set->endGroup(); +} + +#include "moc_minigui.cpp" + diff --git a/plugins/smplayer_plugin/minigui.h b/plugins/smplayer_plugin/minigui.h new file mode 100644 index 000000000..db9dd7b64 --- /dev/null +++ b/plugins/smplayer_plugin/minigui.h @@ -0,0 +1,83 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MINI_GUI_H_ +#define _MINI_GUI_H_ + +#include "baseguiplus.h" +#include "guiconfig.h" + +#define USE_VOLUME_BAR 1 + +class TimeSliderAction; +class VolumeSliderAction; +class TimeLabelAction; +class FloatingWidget; +class QToolBar; + +class MiniGui : public BaseGuiPlus +{ + Q_OBJECT + +public: + MiniGui( QWidget* parent = 0, Qt::WindowFlags flags = 0 ); + ~MiniGui(); + +#if USE_MINIMUMSIZE + virtual QSize minimumSizeHint () const; +#endif + +protected slots: + void showFloatingControl(QPoint p); + void hideFloatingControl(); + + // Reimplemented: +#if AUTODISABLE_ACTIONS + virtual void enableActionsOnPlaying(); + virtual void disableActionsOnStop(); +#endif + +protected: + virtual void retranslateStrings(); + + void createActions(); + void createControlWidget(); + void createFloatingControl(); + + void loadConfig(); + void saveConfig(); + + // Reimplemented + virtual void aboutToEnterFullscreen(); + virtual void aboutToExitFullscreen(); + virtual void aboutToEnterCompactMode(); + virtual void aboutToExitCompactMode(); + +protected: + QToolBar * controlwidget; + + FloatingWidget * floating_control; + + TimeSliderAction * timeslider_action; +#if USE_VOLUME_BAR + VolumeSliderAction * volumeslider_action; +#endif + TimeLabelAction * time_label_action; +}; + +#endif diff --git a/plugins/smplayer_plugin/mpcgui/mpc_mono.png b/plugins/smplayer_plugin/mpcgui/mpc_mono.png new file mode 100644 index 000000000..9a11dad63 Binary files /dev/null and b/plugins/smplayer_plugin/mpcgui/mpc_mono.png differ diff --git a/plugins/smplayer_plugin/mpcgui/mpc_stereo.png b/plugins/smplayer_plugin/mpcgui/mpc_stereo.png new file mode 100644 index 000000000..08fd16c29 Binary files /dev/null and b/plugins/smplayer_plugin/mpcgui/mpc_stereo.png differ diff --git a/plugins/smplayer_plugin/mpcgui/mpc_toolbar.png b/plugins/smplayer_plugin/mpcgui/mpc_toolbar.png new file mode 100644 index 000000000..fad457b8d Binary files /dev/null and b/plugins/smplayer_plugin/mpcgui/mpc_toolbar.png differ diff --git a/plugins/smplayer_plugin/mpcgui/mpcgui.cpp b/plugins/smplayer_plugin/mpcgui/mpcgui.cpp new file mode 100644 index 000000000..b0ab409e5 --- /dev/null +++ b/plugins/smplayer_plugin/mpcgui/mpcgui.cpp @@ -0,0 +1,472 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2008 matt_ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mpcgui.h" +#include "mpcstyles.h" +#include "widgetactions.h" +#include "floatingwidget.h" +#include "myaction.h" +#include "mplayerwindow.h" +#include "global.h" +#include "helper.h" +#include "toolbareditor.h" +#include "desktopinfo.h" +#include "colorutils.h" + +#include +#include +#include +#include +#include + +using namespace Global; + + +MpcGui::MpcGui( QWidget * parent, Qt::WindowFlags flags ) + : BaseGuiPlus( parent, flags ) +{ + createActions(); + createControlWidget(); + createStatusBar(); + + connect( this, SIGNAL(cursorNearBottom(QPoint)), + this, SLOT(showFloatingControl(QPoint)) ); + + connect( this, SIGNAL(cursorFarEdges()), + this, SLOT(hideFloatingControl()) ); + + retranslateStrings(); + + loadConfig(); + + if (pref->compact_mode) { + controlwidget->hide(); + timeslidewidget->hide(); + } +} + +MpcGui::~MpcGui() { + saveConfig(); +} + +void MpcGui::createActions() { + timeslider_action = createTimeSliderAction(this); + timeslider_action->disable(); + timeslider_action->setCustomStyle( new MpcTimeSlideStyle() ); + +#if USE_VOLUME_BAR + volumeslider_action = createVolumeSliderAction(this); + volumeslider_action->disable(); + volumeslider_action->setCustomStyle( new MpcVolumeSlideStyle() ); + volumeslider_action->setFixedSize( QSize(50,18) ); + volumeslider_action->setTickPosition( QSlider::NoTicks ); +#endif + + time_label_action = new TimeLabelAction(this); + time_label_action->setObjectName("timelabel_action"); + + connect( this, SIGNAL(timeChanged(QString)), + time_label_action, SLOT(setText(QString)) ); +} + + +void MpcGui::createControlWidget() { + controlwidget = new QToolBar( this ); + controlwidget->setObjectName("controlwidget"); + controlwidget->setMovable(false); + controlwidget->setAllowedAreas(Qt::BottomToolBarArea); + controlwidget->addAction(playAct); + controlwidget->addAction(pauseAct); + controlwidget->addAction(stopAct); + controlwidget->addSeparator(); + controlwidget->addAction(rewind3Act); + controlwidget->addAction(rewind1Act); + controlwidget->addAction(forward1Act); + controlwidget->addAction(forward3Act); + controlwidget->addSeparator(); + controlwidget->addAction(frameStepAct); + controlwidget->addSeparator(); + + QLabel* pLabel = new QLabel(this); + pLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding)); + controlwidget->addWidget(pLabel); + + controlwidget->addAction(muteAct); + controlwidget->addAction(volumeslider_action); + + timeslidewidget = new QToolBar( this ); + timeslidewidget->setObjectName("timeslidewidget"); + timeslidewidget->addAction(timeslider_action); + timeslidewidget->setMovable(false); + + QColor SliderColor = palette().color(QPalette::Window); + QColor SliderBorderColor = palette().color(QPalette::Dark); + setIconSize( QSize( 16 , 16 ) ); + + addToolBar(Qt::BottomToolBarArea, controlwidget); + addToolBarBreak(Qt::BottomToolBarArea); + addToolBar(Qt::BottomToolBarArea, timeslidewidget); + + controlwidget->setStyle(new MpcToolbarStyle() ); + timeslidewidget->setStyle(new MpcToolbarStyle() ); + + statusBar()->show(); +} + +void MpcGui::retranslateStrings() { + BaseGuiPlus::retranslateStrings(); + + controlwidget->setWindowTitle( tr("Control bar") ); + + setupIcons(); +} + +#if AUTODISABLE_ACTIONS +void MpcGui::enableActionsOnPlaying() { + BaseGuiPlus::enableActionsOnPlaying(); + + timeslider_action->enable(); +#if USE_VOLUME_BAR + volumeslider_action->enable(); +#endif +} + +void MpcGui::disableActionsOnStop() { + BaseGuiPlus::disableActionsOnStop(); + + timeslider_action->disable(); +#if USE_VOLUME_BAR + volumeslider_action->disable(); +#endif +} +#endif // AUTODISABLE_ACTIONS + +void MpcGui::aboutToEnterFullscreen() { + BaseGuiPlus::aboutToEnterFullscreen(); + + if (!pref->compact_mode) { + controlwidget->hide(); + timeslidewidget->hide(); + statusBar()->hide(); + } +} + +void MpcGui::aboutToExitFullscreen() { + BaseGuiPlus::aboutToExitFullscreen(); + + if (!pref->compact_mode) { + controlwidget->show(); + statusBar()->show(); + timeslidewidget->show(); + } +} + +void MpcGui::aboutToEnterCompactMode() { + BaseGuiPlus::aboutToEnterCompactMode(); + + controlwidget->hide(); + timeslidewidget->hide(); + statusBar()->hide(); +} + +void MpcGui::aboutToExitCompactMode() { + BaseGuiPlus::aboutToExitCompactMode(); + + statusBar()->show(); + controlwidget->show(); + timeslidewidget->show(); +} + +void MpcGui::showFloatingControl(QPoint /*p*/) { +} + +void MpcGui::hideFloatingControl() { +} + +#if USE_mpcMUMSIZE +QSize MpcGui::mpcmumSizeHint() const { + return QSize(controlwidget->sizeHint().width(), 0); +} +#endif + + +void MpcGui::saveConfig() { + QSettings * set = settings; + + set->beginGroup( "mpc_gui"); + + if (pref->save_window_size_on_exit) { + qDebug("MpcGui::saveConfig: w: %d h: %d", width(), height()); + set->setValue( "pos", pos() ); + set->setValue( "size", size() ); + } + + set->setValue( "toolbars_state", saveState(Helper::qtVersion()) ); + +/* +#if USE_CONFIGURABLE_TOOLBARS + set->beginGroup( "actions" ); + set->setValue("controlwidget", ToolbarEditor::save(controlwidget) ); + set->endGroup(); +#endif +*/ + + set->endGroup(); +} + +void MpcGui::loadConfig() { + QSettings * set = settings; + + set->beginGroup( "mpc_gui"); + + if (pref->save_window_size_on_exit) { + QPoint p = set->value("pos", pos()).toPoint(); + QSize s = set->value("size", size()).toSize(); + + if ( (s.height() < 200) && (!pref->use_mplayer_window) ) { + s = pref->default_size; + } + + move(p); + resize(s); + + if (!DesktopInfo::isInsideScreen(this)) { + move(0,0); + qWarning("MpcGui::loadConfig: window is outside of the screen, moved to 0x0"); + } + } + + restoreState( set->value( "toolbars_state" ).toByteArray(), Helper::qtVersion() ); + + set->endGroup(); +} + +void MpcGui::setupIcons() { + playAct->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(0,0,16,16) ); + playOrPauseAct->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(0,0,16,16) ); + pauseAct->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(16,0,16,16) ); + pauseAndStepAct->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(16,0,16,16) ); + stopAct->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(32,0,16,16) ); + rewind3Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(64,0,16,16) ); + rewind2Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(80,0,16,16) ); + rewind1Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(80,0,16,16) ); + forward1Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(96,0,16,16) ); + forward2Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(96,0,16,16) ); + forward3Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(112,0,16,16) ); + frameStepAct->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(144,0,16,16) ); + muteAct->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(192,0,16,16) ); + + pauseAct->setCheckable(true); + playAct->setCheckable(true); + stopAct->setCheckable(true); + connect( muteAct, SIGNAL(toggled(bool)), + this, SLOT(muteIconChange(bool)) ); + + connect( core , SIGNAL(mediaInfoChanged()), + this, SLOT(updateAudioChannels()) ); + + connect( core , SIGNAL(stateChanged(Core::State)), + this, SLOT(iconChange(Core::State)) ); +} + +void MpcGui::iconChange(Core::State state) { + playAct->blockSignals(true); + pauseAct->blockSignals(true); + stopAct->blockSignals(true); + + if( state == Core::Paused ) + { + playAct->setChecked(false); + pauseAct->setChecked(true); + stopAct->setChecked(false); + } + if( state == Core::Playing ) + { + playAct->setChecked(true); + pauseAct->setChecked(false); + stopAct->setChecked(false); + } + if( state == Core::Stopped ) + { + playAct->setChecked(false); + pauseAct->setChecked(false); + stopAct->setChecked(false); + } + + playAct->blockSignals(false); + pauseAct->blockSignals(false); + stopAct->blockSignals(false); +} + +void MpcGui::muteIconChange(bool b) { + if( sender() == muteAct ) + { + if(!b) { + muteAct->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(192,0,16,16) ); + } else { + muteAct->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(208,0,16,16) ); + } + } + +} + + +void MpcGui::createStatusBar() { + + // remove frames around statusbar items + statusBar()->setStyleSheet("QStatusBar::item { border: 0px solid black }; "); + + // emulate mono/stereo display from mpc + audiochannel_display = new QLabel( statusBar() ); + audiochannel_display->setContentsMargins(0,0,0,0); + audiochannel_display->setAlignment(Qt::AlignRight); + audiochannel_display->setPixmap( QPixmap(":/mpcgui/mpc_stereo.png") ); + audiochannel_display->setMinimumSize(audiochannel_display->sizeHint()); + audiochannel_display->setMaximumSize(audiochannel_display->sizeHint()); + audiochannel_display->setPixmap( QPixmap("") ); + + time_display = new QLabel( statusBar() ); + time_display->setAlignment(Qt::AlignRight); + time_display->setText(" 88:88:88 / 88:88:88 "); + time_display->setMinimumSize(time_display->sizeHint()); + time_display->setContentsMargins(15,2,1,1); + + frame_display = new QLabel( statusBar() ); + frame_display->setAlignment(Qt::AlignRight); + frame_display->setText("88888888"); + frame_display->setMinimumSize(frame_display->sizeHint()); + frame_display->setContentsMargins(15,2,1,1); + + statusBar()->setAutoFillBackground(TRUE); + + ColorUtils::setBackgroundColor( statusBar(), QColor(0,0,0) ); + ColorUtils::setForegroundColor( statusBar(), QColor(255,255,255) ); + ColorUtils::setBackgroundColor( time_display, QColor(0,0,0) ); + ColorUtils::setForegroundColor( time_display, QColor(255,255,255) ); + ColorUtils::setBackgroundColor( frame_display, QColor(0,0,0) ); + ColorUtils::setForegroundColor( frame_display, QColor(255,255,255) ); + ColorUtils::setBackgroundColor( audiochannel_display, QColor(0,0,0) ); + ColorUtils::setForegroundColor( audiochannel_display, QColor(255,255,255) ); + statusBar()->setSizeGripEnabled(FALSE); + + + + statusBar()->addPermanentWidget( frame_display, 0 ); + frame_display->setText( "0" ); + + statusBar()->addPermanentWidget( time_display, 0 ); + time_display->setText(" 00:00:00 / 00:00:00 "); + + statusBar()->addPermanentWidget( audiochannel_display, 0 ); + + time_display->show(); + frame_display->hide(); + + connect( this, SIGNAL(timeChanged(QString)), + this, SLOT(displayTime(QString)) ); + + connect( this, SIGNAL(frameChanged(int)), + this, SLOT(displayFrame(int)) ); + + connect( this, SIGNAL(cursorNearBottom(QPoint)), + this, SLOT(showFullscreenControls()) ); + + connect( this, SIGNAL(cursorFarEdges()), + this, SLOT(hideFullscreenControls()) ); +} + +void MpcGui::displayTime(QString text) { + time_display->setText( text ); + time_label_action->setText(text ); +} + +void MpcGui::displayFrame(int frame) { + if (frame_display->isVisible()) { + frame_display->setNum( frame ); + } +} + +void MpcGui::updateAudioChannels() { + if( core->mdat.audio_nch == 1 ) { + audiochannel_display->setPixmap( QPixmap(":/mpcgui/mpc_mono.png") ); + } + else { + audiochannel_display->setPixmap( QPixmap(":/mpcgui/mpc_stereo.png") ); + } +} + +void MpcGui::showFullscreenControls() { + + if(pref->fullscreen && controlwidget->isHidden() && timeslidewidget->isHidden() && + !pref->compact_mode ) + { + controlwidget->show(); + timeslidewidget->show(); + statusBar()->show(); + } +} + +void MpcGui::hideFullscreenControls() { + + if(pref->fullscreen && controlwidget->isVisible() && timeslidewidget->isVisible() ) + { + controlwidget->hide(); + timeslidewidget->hide(); + statusBar()->hide(); + } +} + +void MpcGui::setJumpTexts() { + rewind1Act->change( tr("-%1").arg(Helper::timeForJumps(pref->seeking1)) ); + rewind2Act->change( tr("-%1").arg(Helper::timeForJumps(pref->seeking2)) ); + rewind3Act->change( tr("-%1").arg(Helper::timeForJumps(pref->seeking3)) ); + + forward1Act->change( tr("+%1").arg(Helper::timeForJumps(pref->seeking1)) ); + forward2Act->change( tr("+%1").arg(Helper::timeForJumps(pref->seeking2)) ); + forward3Act->change( tr("+%1").arg(Helper::timeForJumps(pref->seeking3)) ); + + if (qApp->isLeftToRight()) { + rewind1Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(80,0,16,16) ); + rewind2Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(80,0,16,16) ); + rewind3Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(64,0,16,16) ); + + forward1Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(96,0,16,16) ); + forward2Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(96,0,16,16) ); + forward3Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(112,0,16,16) ); + + } else { + rewind1Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(96,0,16,16) ); + rewind2Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(96,0,16,16) ); + rewind3Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(112,0,16,16) ); + + forward1Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(80,0,16,16) ); + forward2Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(80,0,16,16) ); + forward3Act->setIcon( QPixmap(":/mpcgui/mpc_toolbar.png").copy(64,0,16,16) ); + } +} + +void MpcGui::updateWidgets() { + + BaseGui::updateWidgets(); + + // Frame counter + frame_display->setVisible( pref->show_frame_counter ); +} + +#include "moc_mpcgui.cpp" + diff --git a/plugins/smplayer_plugin/mpcgui/mpcgui.h b/plugins/smplayer_plugin/mpcgui/mpcgui.h new file mode 100644 index 000000000..c3bcb388c --- /dev/null +++ b/plugins/smplayer_plugin/mpcgui/mpcgui.h @@ -0,0 +1,101 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2008 matt_ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MPC_GUI_H_ +#define _MPC_GUI_H_ + +#include "baseguiplus.h" +#include "guiconfig.h" + +#define USE_VOLUME_BAR 1 + +class TimeSliderAction; +class VolumeSliderAction; +class TimeLabelAction; +class FloatingWidget; +class QToolBar; + +class MpcGui : public BaseGuiPlus +{ + Q_OBJECT + +public: + MpcGui( QWidget* parent = 0, Qt::WindowFlags flags = 0 ); + ~MpcGui(); + +#if USE_MPCMUMSIZE + virtual QSize mpcmumSizeHint () const; +#endif + +protected slots: + void showFloatingControl(QPoint p); + void hideFloatingControl(); + void muteIconChange(bool b); + void iconChange(Core::State state); + void updateAudioChannels(); + + void displayTime(QString text); + void displayFrame(int frame); + void showFullscreenControls(); + void hideFullscreenControls(); + void setJumpTexts(); + void updateWidgets(); + + // Reimplemented: +#if AUTODISABLE_ACTIONS + virtual void enableActionsOnPlaying(); + virtual void disableActionsOnStop(); +#endif + +protected: + virtual void retranslateStrings(); + + void createActions(); + void createControlWidget(); + void createFloatingControl(); + void createStatusBar(); + + void setupIcons(); + + void loadConfig(); + void saveConfig(); + + // Reimplemented + virtual void aboutToEnterFullscreen(); + virtual void aboutToExitFullscreen(); + virtual void aboutToEnterCompactMode(); + virtual void aboutToExitCompactMode(); + +protected: + QToolBar* controlwidget; + QToolBar* timeslidewidget; + + QLabel * audiochannel_display; + QLabel * time_display; + QLabel * frame_display; + + FloatingWidget * floating_control; + + TimeSliderAction * timeslider_action; +#if USE_VOLUME_BAR + VolumeSliderAction * volumeslider_action; +#endif + TimeLabelAction * time_label_action; +}; + +#endif diff --git a/plugins/smplayer_plugin/mpcgui/mpcstyles.cpp b/plugins/smplayer_plugin/mpcgui/mpcstyles.cpp new file mode 100644 index 000000000..add347018 --- /dev/null +++ b/plugins/smplayer_plugin/mpcgui/mpcstyles.cpp @@ -0,0 +1,239 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2008 matt_ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mpcstyles.h" + +#include +#include +#include +#include + + +void +MpcToolbarStyle::drawControl(ControlElement control, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const +{ + if(control == CE_ToolBar) + { + if (const QStyleOptionToolBar *toolbar = qstyleoption_cast(option)) { + QRect rect = option->rect; + + if( toolbar->toolBarArea == Qt::BottomToolBarArea && + toolbar->positionOfLine == QStyleOptionToolBar::End ) + { + painter->setPen(QPen(option->palette.light().color())); + painter->drawLine(rect.topLeft().x(), + rect.topLeft().y(), + rect.topRight().x(), + rect.topRight().y()); + + painter->setPen(QPen(option->palette.light().color())); + painter->drawLine(rect.topLeft().x(), + rect.topLeft().y(), + rect.bottomLeft().x(), + rect.bottomLeft().y()); + + painter->setPen(QPen(option->palette.dark().color())); + painter->drawLine(rect.topRight().x(), + rect.topRight().y(), + rect.bottomRight().x(), + rect.bottomRight().y()); + + } + else if( toolbar->toolBarArea == Qt::BottomToolBarArea && + toolbar->positionOfLine == QStyleOptionToolBar::Beginning ) + { + painter->setPen(QPen(option->palette.light().color())); + painter->drawLine(rect.topLeft().x(), + rect.topLeft().y(), + rect.bottomLeft().x(), + rect.bottomLeft().y()); + + painter->setPen(QPen(option->palette.dark().color())); + painter->drawLine(rect.topRight().x(), + rect.topRight().y(), + rect.bottomRight().x(), + rect.bottomRight().y()); + + painter->setPen(QPen(option->palette.dark().color())); + painter->drawLine(rect.bottomLeft().x(), + rect.bottomLeft().y(), + rect.bottomRight().x(), + rect.bottomRight().y()); + } + else + { + QWindowsStyle::drawControl(control,toolbar, painter, widget); + } + } + } + else + { + QWindowsStyle::drawControl(control,option, painter, widget); + } +} + +// draw custom slider + handle for volume widget +void MpcVolumeSlideStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + QPainter *p, const QWidget *widget) const +{ + if( cc == CC_Slider ) + { + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget); + QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget); + + if ((slider->subControls & SC_SliderGroove) && groove.isValid()) { + + p->setPen(slider->palette.shadow().color()); + if (slider->orientation == Qt::Horizontal) { + static QPoint points[3] = { + QPoint(groove.x() , groove.y() + slider->rect.height() ), + QPoint(groove.x() + groove.width() -2 , groove.y() + slider->rect.height() ), + QPoint(groove.x() + groove.width() -2 , groove.y() ), + }; + QPen oldPen = p->pen(); + + p->setPen(slider->palette.dark().color()); + p->drawLine(QPoint(points[0].x(), points[0].y() -2 ),QPoint(points[2].x(), points[2].y())); + + QPoint b[3] = { QPoint(points[0].x(),points[0].y()-1), QPoint(points[1].x()-1, points[1].y()-1), QPoint(points[2].x()-1,points[2].y()) }; + p->setPen(slider->palette.light().color()); + p->drawPolyline(b, 3); + p->setPen(oldPen); + } + } + + + if (slider->subControls & SC_SliderTickmarks) { + QStyleOptionSlider tmpSlider = *slider; + tmpSlider.subControls = SC_SliderTickmarks; + QCommonStyle::drawComplexControl(cc, &tmpSlider, p, widget); + } + + if (slider->subControls & SC_SliderHandle) { + const QColor c0 = slider->palette.shadow().color(); + const QColor c1 = slider->palette.dark().color(); + // const QColor c2 = g.button(); + const QColor c3 = slider->palette.midlight().color(); + const QColor c4 = slider->palette.light().color(); + QBrush handleBrush; + + if (slider->state & State_Enabled) { + handleBrush = slider->palette.color(QPalette::Button); + } else { + handleBrush = QBrush(slider->palette.color(QPalette::Button), + Qt::Dense4Pattern); + } + + + int x = handle.x() , y = handle.y(), + wi = handle.width() - 2, he = slider->rect.height(); + + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + + Qt::BGMode oldMode = p->backgroundMode(); + p->setBackgroundMode(Qt::OpaqueMode); + qDrawWinButton(p, QRect(x, y, wi, he), slider->palette, false, + &handleBrush); + p->setBackgroundMode(oldMode); + + } + } + } + else + { + QWindowsStyle::drawComplexControl(cc,opt,p,widget); + } +} + +// draw custom slider + handle for timeslide widget +void MpcTimeSlideStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + QPainter *p, const QWidget *widget) const +{ + if( cc == CC_Slider ) + { + if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { + QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget); + QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget); + + if ((slider->subControls & SC_SliderGroove) && groove.isValid()) { + if (slider->orientation == Qt::Horizontal) { + int x = groove.x() + 2; + int y = slider->rect.height() / 2 - 4; + int w = groove.width() - 4; + int h = 7; + qDrawShadeRect (p,x,y,w,h, slider->palette, true,1,0, + &slider->palette.brush(QPalette::Light)); + } + } + + + if (slider->subControls & SC_SliderTickmarks) { + QStyleOptionSlider tmpSlider = *slider; + tmpSlider.subControls = SC_SliderTickmarks; + QCommonStyle::drawComplexControl(cc, &tmpSlider, p, widget); + } + + if (slider->subControls & SC_SliderHandle) { + const QColor c0 = slider->palette.shadow().color(); + const QColor c1 = slider->palette.dark().color(); + // const QColor c2 = g.button(); + const QColor c3 = slider->palette.midlight().color(); + const QColor c4 = slider->palette.light().color(); + QBrush handleBrush; + + if (slider->state & State_Enabled) { + handleBrush = slider->palette.color(QPalette::Button); + } else { + handleBrush = QBrush(slider->palette.color(QPalette::Button), + Qt::Dense4Pattern); + } + + + int x = handle.x() , y = handle.y() + 1, + wi = 13, he = 14; + + if (slider->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*slider); + fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } + + Qt::BGMode oldMode = p->backgroundMode(); + p->setBackgroundMode(Qt::OpaqueMode); + qDrawWinPanel(p, QRect(x, y, wi, he), slider->palette, false, + &handleBrush); + qDrawShadeRect (p, QRect(x+2,y+3, wi-4, he-6), slider->palette, true,1,0, + &slider->palette.brush(QPalette::Light)); + p->setBackgroundMode(oldMode); + } + } + } + else + { + QWindowsStyle::drawComplexControl(cc,opt,p,widget); + } +} + diff --git a/plugins/smplayer_plugin/mpcgui/mpcstyles.h b/plugins/smplayer_plugin/mpcgui/mpcstyles.h new file mode 100644 index 000000000..aac756f7e --- /dev/null +++ b/plugins/smplayer_plugin/mpcgui/mpcstyles.h @@ -0,0 +1,58 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2008 matt_ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MPC_STYLES_H_ +#define _MPC_STYLES_H_ + +#include +#include + +enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; + +class MpcToolbarStyle : public QWindowsStyle +{ + Q_OBJECT + +public: + MpcToolbarStyle() {}; + void drawControl(ControlElement control, const QStyleOption *option, + QPainter *painter, const QWidget *widget) const; +}; + +class MpcTimeSlideStyle : public QWindowsStyle +{ + Q_OBJECT + +public: + MpcTimeSlideStyle() {}; + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + QPainter *p, const QWidget *widget) const; +}; + +class MpcVolumeSlideStyle : public QWindowsStyle +{ + Q_OBJECT + +public: + MpcVolumeSlideStyle() {}; + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + QPainter *p, const QWidget *widget) const; +}; + + +#endif diff --git a/plugins/smplayer_plugin/mplayerprocess.cpp b/plugins/smplayer_plugin/mplayerprocess.cpp new file mode 100644 index 000000000..bd74ade51 --- /dev/null +++ b/plugins/smplayer_plugin/mplayerprocess.cpp @@ -0,0 +1,756 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mplayerprocess.h" +#include +#include +#include + +#include "global.h" +#include "preferences.h" +#include "mplayerversion.h" +#include "helper.h" + +using namespace Global; + +MplayerProcess::MplayerProcess(QObject * parent) : MyProcess(parent) +{ +#if NOTIFY_SUB_CHANGES + qRegisterMetaType("SubTracks"); +#endif + +#if NOTIFY_AUDIO_CHANGES + qRegisterMetaType("Tracks"); +#endif + + connect( this, SIGNAL(lineAvailable(QByteArray)), + this, SLOT(parseLine(QByteArray)) ); + + connect( this, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(processFinished(int,QProcess::ExitStatus)) ); + + connect( this, SIGNAL(error(QProcess::ProcessError)), + this, SLOT(gotError(QProcess::ProcessError)) ); + + notified_mplayer_is_running = false; + last_sub_id = -1; + mplayer_svn = -1; // Not found yet +} + +MplayerProcess::~MplayerProcess() { +} + +bool MplayerProcess::start() { + md.reset(); + notified_mplayer_is_running = false; + last_sub_id = -1; + mplayer_svn = -1; // Not found yet + received_end_of_file = false; + +#if NOTIFY_SUB_CHANGES + subs.clear(); + subtitle_info_received = false; + subtitle_info_changed = false; +#endif + +#if NOTIFY_AUDIO_CHANGES + audios.clear(); + audio_info_changed = false; +#endif + +#if GENERIC_CHAPTER_SUPPORT + dvd_current_title = -1; +#endif + + MyProcess::start(); + return waitForStarted(); +} + +void MplayerProcess::writeToStdin(QString text) { + if (isRunning()) { + //qDebug("MplayerProcess::writeToStdin"); + write( text.toLocal8Bit() + "\n"); + } else { + qWarning("MplayerProcess::writeToStdin: process not running"); + } +} + +static QRegExp rx_av("^[AV]: *([0-9,:.-]+)"); +static QRegExp rx_frame("^[AV]:.* (\\d+)\\/.\\d+");// [0-9,.]+"); +static QRegExp rx("^(.*)=(.*)"); +#if !NOTIFY_AUDIO_CHANGES +static QRegExp rx_audio_mat("^ID_AID_(\\d+)_(LANG|NAME)=(.*)"); +#endif +static QRegExp rx_video("^ID_VID_(\\d+)_(LANG|NAME)=(.*)"); +static QRegExp rx_title("^ID_DVD_TITLE_(\\d+)_(LENGTH|CHAPTERS|ANGLES)=(.*)"); +static QRegExp rx_winresolution("^VO: \\[(.*)\\] (\\d+)x(\\d+) => (\\d+)x(\\d+)"); +static QRegExp rx_ao("^AO: \\[(.*)\\]"); +static QRegExp rx_paused("^ID_PAUSED"); +#if !CHECK_VIDEO_CODEC_FOR_NO_VIDEO +static QRegExp rx_novideo("^Video: no video"); +#endif +static QRegExp rx_cache("^Cache fill:.*"); +static QRegExp rx_create_index("^Generating Index:.*"); +static QRegExp rx_play("^Starting playback..."); +static QRegExp rx_connecting("^Connecting to .*"); +static QRegExp rx_resolving("^Resolving .*"); +static QRegExp rx_screenshot("^\\*\\*\\* screenshot '(.*)'"); +static QRegExp rx_endoffile("^Exiting... \\(End of file\\)|^ID_EXIT=EOF"); +static QRegExp rx_mkvchapters("\\[mkv\\] Chapter (\\d+) from"); +static QRegExp rx_aspect2("^Movie-Aspect is ([0-9,.]+):1"); +static QRegExp rx_fontcache("^\\[ass\\] Updating font cache|^\\[ass\\] Init"); + +// VCD +static QRegExp rx_vcd("^ID_VCD_TRACK_(\\d+)_MSF=(.*)"); + +// Audio CD +static QRegExp rx_cdda("^ID_CDDA_TRACK_(\\d+)_MSF=(.*)"); + + +//Subtitles +static QRegExp rx_subtitle("^ID_(SUBTITLE|FILE_SUB|VOBSUB)_ID=(\\d+)"); +static QRegExp rx_sid("^ID_(SID|VSID)_(\\d+)_(LANG|NAME)=(.*)"); +static QRegExp rx_subtitle_file("^ID_FILE_SUB_FILENAME=(.*)"); + +// Audio +#if NOTIFY_AUDIO_CHANGES +static QRegExp rx_audio("^ID_AUDIO_ID=(\\d+)"); +static QRegExp rx_audio_info("^ID_AID_(\\d+)_(LANG|NAME)=(.*)"); +#endif + +//Clip info +static QRegExp rx_clip_name("^ (name|title): (.*)", Qt::CaseInsensitive); +static QRegExp rx_clip_artist("^ artist: (.*)", Qt::CaseInsensitive); +static QRegExp rx_clip_author("^ author: (.*)", Qt::CaseInsensitive); +static QRegExp rx_clip_album("^ album: (.*)", Qt::CaseInsensitive); +static QRegExp rx_clip_genre("^ genre: (.*)", Qt::CaseInsensitive); +static QRegExp rx_clip_date("^ (creation date|year): (.*)", Qt::CaseInsensitive); +static QRegExp rx_clip_track("^ track: (.*)", Qt::CaseInsensitive); +static QRegExp rx_clip_copyright("^ copyright: (.*)", Qt::CaseInsensitive); +static QRegExp rx_clip_comment("^ comment: (.*)", Qt::CaseInsensitive); +static QRegExp rx_clip_software("^ software: (.*)", Qt::CaseInsensitive); + +static QRegExp rx_stream_title("^.* StreamTitle='(.*)';StreamUrl='(.*)';"); + + +void MplayerProcess::parseLine(QByteArray ba) { + //qDebug("MplayerProcess::parseLine: '%s'", ba.data() ); + + QString tag; + QString value; + +#if COLOR_OUTPUT_SUPPORT + QString line = Helper::stripColorsTags(QString::fromLocal8Bit(ba)); +#else + QString line = QString::fromLocal8Bit(ba); +#endif + + // Parse A: V: line + //qDebug("%s", line.toUtf8().data()); + if (rx_av.indexIn(line) > -1) { + double sec = rx_av.cap(1).toDouble(); + //qDebug("cap(1): '%s'", rx_av.cap(1).toUtf8().data() ); + //qDebug("sec: %f", sec); + +#if NOTIFY_SUB_CHANGES + if (notified_mplayer_is_running) { + if (subtitle_info_changed) { + qDebug("MplayerProcess::parseLine: subtitle_info_changed"); + subtitle_info_changed = false; + subtitle_info_received = false; + emit subtitleInfoChanged(subs); + } + if (subtitle_info_received) { + qDebug("MplayerProcess::parseLine: subtitle_info_received"); + subtitle_info_received = false; + emit subtitleInfoReceivedAgain(subs); + } + } +#endif + +#if NOTIFY_AUDIO_CHANGES + if (notified_mplayer_is_running) { + if (audio_info_changed) { + qDebug("MplayerProcess::parseLine: audio_info_changed"); + audio_info_changed = false; + emit audioInfoChanged(audios); + } + } +#endif + + if (!notified_mplayer_is_running) { + qDebug("MplayerProcess::parseLine: starting sec: %f", sec); +#if GENERIC_CHAPTER_SUPPORT + if ( (md.chapters <= 0) && (dvd_current_title > 0) && + (md.titles.find(dvd_current_title) != -1) ) + { + int idx = md.titles.find(dvd_current_title); + md.chapters = md.titles.itemAt(idx).chapters(); + qDebug("MplayerProcess::parseLine: setting chapters to %d", md.chapters); + } +#endif + +#if CHECK_VIDEO_CODEC_FOR_NO_VIDEO + // Another way to find out if there's no video + if (md.video_codec.isEmpty()) { + md.novideo = true; + emit receivedNoVideo(); + } +#endif + + emit receivedStartingTime(sec); + emit mplayerFullyLoaded(); + + emit receivedCurrentFrame(0); // Ugly hack: set the frame counter to 0 + + notified_mplayer_is_running = true; + } + + emit receivedCurrentSec( sec ); + + // Check for frame + if (rx_frame.indexIn(line) > -1) { + int frame = rx_frame.cap(1).toInt(); + //qDebug(" frame: %d", frame); + emit receivedCurrentFrame(frame); + } + } + else { + // Emulates mplayer version in Ubuntu: + //if (line.startsWith("MPlayer 1.0rc1")) line = "MPlayer 2:1.0~rc1-0ubuntu13.1 (C) 2000-2006 MPlayer Team"; + + emit lineAvailable(line); + + // Parse other things + qDebug("MplayerProcess::parseLine: '%s'", line.toUtf8().data() ); + + // Screenshot + if (rx_screenshot.indexIn(line) > -1) { + QString shot = rx_screenshot.cap(1); + qDebug("MplayerProcess::parseLine: screenshot: '%s'", shot.toUtf8().data()); + emit receivedScreenshot( shot ); + } + else + + // End of file + if (rx_endoffile.indexIn(line) > -1) { + qDebug("MplayerProcess::parseLine: detected end of file"); + if (!received_end_of_file) { + // In case of playing VCDs or DVDs, maybe the first title + // is not playable, so the GUI doesn't get the info about + // available titles. So if we received the end of file + // first let's pretend the file has started so the GUI can have + // the data. + if ( !notified_mplayer_is_running) { + emit mplayerFullyLoaded(); + } + + //emit receivedEndOfFile(); + // Send signal once the process is finished, not now! + received_end_of_file = true; + } + } + else + + // Window resolution + if (rx_winresolution.indexIn(line) > -1) { + /* + md.win_width = rx_winresolution.cap(4).toInt(); + md.win_height = rx_winresolution.cap(5).toInt(); + md.video_aspect = (double) md.win_width / md.win_height; + */ + + int w = rx_winresolution.cap(4).toInt(); + int h = rx_winresolution.cap(5).toInt(); + + emit receivedVO( rx_winresolution.cap(1) ); + emit receivedWindowResolution( w, h ); + //emit mplayerFullyLoaded(); + } + else + +#if !CHECK_VIDEO_CODEC_FOR_NO_VIDEO + // No video + if (rx_novideo.indexIn(line) > -1) { + md.novideo = TRUE; + emit receivedNoVideo(); + //emit mplayerFullyLoaded(); + } + else +#endif + + // Pause + if (rx_paused.indexIn(line) > -1) { + emit receivedPause(); + } + + // Stream title + if (rx_stream_title.indexIn(line) > -1) { + QString s = rx_stream_title.cap(1); + QString url = rx_stream_title.cap(2); + qDebug("MplayerProcess::parseLine: stream_title: '%s'", s.toUtf8().data()); + qDebug("MplayerProcess::parseLine: stream_url: '%s'", url.toUtf8().data()); + md.stream_title = s; + md.stream_url = url; + emit receivedStreamTitleAndUrl( s, url ); + } + +#if NOTIFY_SUB_CHANGES + // Subtitles + if ((rx_subtitle.indexIn(line) > -1) || (rx_sid.indexIn(line) > -1) || (rx_subtitle_file.indexIn(line) > -1)) { + int r = subs.parse(line); + subtitle_info_received = true; + subtitle_info_changed = ((r == SubTracks::SubtitleAdded) || (r == SubTracks::SubtitleChanged)); + } +#endif + +#if NOTIFY_AUDIO_CHANGES + // Audio + if (rx_audio.indexIn(line) > -1) { + int ID = rx_audio.cap(1).toInt(); + qDebug("MplayerProcess::parseLine: ID_AUDIO_ID: %d", ID); + if (audios.find(ID) == -1) audio_info_changed = true; + audios.addID( ID ); + } + + if (rx_audio_info.indexIn(line) > -1) { + int ID = rx_audio_info.cap(1).toInt(); + QString lang = rx_audio_info.cap(3); + QString t = rx_audio_info.cap(2); + qDebug("MplayerProcess::parseLine: Audio: ID: %d, Lang: '%s' Type: '%s'", + ID, lang.toUtf8().data(), t.toUtf8().data()); + + int idx = audios.find(ID); + if (idx == -1) { + qDebug("MplayerProcess::parseLine: audio %d doesn't exist, adding it", ID); + + audio_info_changed = true; + if ( t == "NAME" ) + audios.addName(ID, lang); + else + audios.addLang(ID, lang); + } else { + qDebug("MplayerProcess::parseLine: audio %d exists, modifing it", ID); + + if (t == "NAME") { + //qDebug("MplayerProcess::parseLine: name of audio %d: %s", ID, audios.itemAt(idx).name().toUtf8().constData()); + if (audios.itemAt(idx).name() != lang) { + audio_info_changed = true; + audios.addName(ID, lang); + } + } else { + //qDebug("MplayerProcess::parseLine: language of audio %d: %s", ID, audios.itemAt(idx).lang().toUtf8().constData()); + if (audios.itemAt(idx).lang() != lang) { + audio_info_changed = true; + audios.addLang(ID, lang); + } + } + } + } +#endif + + // The following things are not sent when the file has started to play + // (or if sent, smplayer will ignore anyway...) + // So not process anymore, if video is playing to save some time + if (notified_mplayer_is_running) { + return; + } + + if ( (mplayer_svn == -1) && (line.startsWith("MPlayer ")) ) { + mplayer_svn = MplayerVersion::mplayerVersion(line); + qDebug("MplayerProcess::parseLine: MPlayer SVN: %d", mplayer_svn); + if (mplayer_svn <= 0) { + qWarning("MplayerProcess::parseLine: couldn't parse mplayer version!"); + emit failedToParseMplayerVersion(line); + } + } + +#if !NOTIFY_SUB_CHANGES + // Subtitles + if (rx_subtitle.indexIn(line) > -1) { + md.subs.parse(line); + } + else + if (rx_sid.indexIn(line) > -1) { + md.subs.parse(line); + } + else + if (rx_subtitle_file.indexIn(line) > -1) { + md.subs.parse(line); + } +#endif + // AO + if (rx_ao.indexIn(line) > -1) { + emit receivedAO( rx_ao.cap(1) ); + } + else + +#if !NOTIFY_AUDIO_CHANGES + // Matroska audio + if (rx_audio_mat.indexIn(line) > -1) { + int ID = rx_audio_mat.cap(1).toInt(); + QString lang = rx_audio_mat.cap(3); + QString t = rx_audio_mat.cap(2); + qDebug("MplayerProcess::parseLine: Audio: ID: %d, Lang: '%s' Type: '%s'", + ID, lang.toUtf8().data(), t.toUtf8().data()); + + if ( t == "NAME" ) + md.audios.addName(ID, lang); + else + md.audios.addLang(ID, lang); + } + else +#endif + + // Video tracks + if (rx_video.indexIn(line) > -1) { + int ID = rx_video.cap(1).toInt(); + QString lang = rx_video.cap(3); + QString t = rx_video.cap(2); + qDebug("MplayerProcess::parseLine: Video: ID: %d, Lang: '%s' Type: '%s'", + ID, lang.toUtf8().data(), t.toUtf8().data()); + + if ( t == "NAME" ) + md.videos.addName(ID, lang); + else + md.videos.addLang(ID, lang); + } + else + + // Matroshka chapters + if (rx_mkvchapters.indexIn(line)!=-1) { + int c = rx_mkvchapters.cap(1).toInt(); + qDebug("MplayerProcess::parseLine: mkv chapters: %d", c); +#if GENERIC_CHAPTER_SUPPORT + if ((c+1) > md.chapters) { + md.chapters = c+1; + qDebug("MplayerProcess::parseLine: chapters set to: %d", md.chapters); + } +#else + if ((c+1) > md.mkv_chapters) { + md.mkv_chapters = c+1; + qDebug("MplayerProcess::parseLine: mkv_chapters set to: %d", md.mkv_chapters); + } +#endif + } + else + + // VCD titles + if (rx_vcd.indexIn(line) > -1 ) { + int ID = rx_vcd.cap(1).toInt(); + QString length = rx_vcd.cap(2); + //md.titles.addID( ID ); + md.titles.addName( ID, length ); + } + else + + // Audio CD titles + if (rx_cdda.indexIn(line) > -1 ) { + int ID = rx_cdda.cap(1).toInt(); + QString length = rx_cdda.cap(2); + double duration = 0; + QRegExp r("(\\d+):(\\d+):(\\d+)"); + if ( r.indexIn(length) > -1 ) { + duration = r.cap(1).toInt() * 60; + duration += r.cap(2).toInt(); + } + md.titles.addID( ID ); + /* + QString name = QString::number(ID) + " (" + length + ")"; + md.titles.addName( ID, name ); + */ + md.titles.addDuration( ID, duration ); + } + else + + // DVD titles + if (rx_title.indexIn(line) > -1) { + int ID = rx_title.cap(1).toInt(); + QString t = rx_title.cap(2); + + if (t=="LENGTH") { + double length = rx_title.cap(3).toDouble(); + qDebug("MplayerProcess::parseLine: Title: ID: %d, Length: '%f'", ID, length); + md.titles.addDuration(ID, length); + } + else + if (t=="CHAPTERS") { + int chapters = rx_title.cap(3).toInt(); + qDebug("MplayerProcess::parseLine: Title: ID: %d, Chapters: '%d'", ID, chapters); + md.titles.addChapters(ID, chapters); + } + else + if (t=="ANGLES") { + int angles = rx_title.cap(3).toInt(); + qDebug("MplayerProcess::parseLine: Title: ID: %d, Angles: '%d'", ID, angles); + md.titles.addAngles(ID, angles); + } + } + else + + // Catch cache messages + if (rx_cache.indexIn(line) > -1) { + emit receivedCacheMessage(line); + } + else + + // Creating index + if (rx_create_index.indexIn(line) > -1) { + emit receivedCreatingIndex(line); + } + else + + // Catch connecting message + if (rx_connecting.indexIn(line) > -1) { + emit receivedConnectingToMessage(line); + } + else + + // Catch resolving message + if (rx_resolving.indexIn(line) > -1) { + emit receivedResolvingMessage(line); + } + else + + // Aspect ratio for old versions of mplayer + if (rx_aspect2.indexIn(line) > -1) { + md.video_aspect = rx_aspect2.cap(1).toDouble(); + qDebug("MplayerProcess::parseLine: md.video_aspect set to %f", md.video_aspect); + } + else + + // Clip info + + //QString::trimmed() is used for removing leading and trailing whitespaces + //Some .mp3 files contain tags with starting and ending whitespaces + //Unfortunately MPlayer gives us leading and trailing whitespaces, Winamp for example doesn't show them + + // Name + if (rx_clip_name.indexIn(line) > -1) { + QString s = rx_clip_name.cap(2).trimmed(); + qDebug("MplayerProcess::parseLine: clip_name: '%s'", s.toUtf8().data()); + md.clip_name = s; + } + else + + // Artist + if (rx_clip_artist.indexIn(line) > -1) { + QString s = rx_clip_artist.cap(1).trimmed(); + qDebug("MplayerProcess::parseLine: clip_artist: '%s'", s.toUtf8().data()); + md.clip_artist = s; + } + else + + // Author + if (rx_clip_author.indexIn(line) > -1) { + QString s = rx_clip_author.cap(1).trimmed(); + qDebug("MplayerProcess::parseLine: clip_author: '%s'", s.toUtf8().data()); + md.clip_author = s; + } + else + + // Album + if (rx_clip_album.indexIn(line) > -1) { + QString s = rx_clip_album.cap(1).trimmed(); + qDebug("MplayerProcess::parseLine: clip_album: '%s'", s.toUtf8().data()); + md.clip_album = s; + } + else + + // Genre + if (rx_clip_genre.indexIn(line) > -1) { + QString s = rx_clip_genre.cap(1).trimmed(); + qDebug("MplayerProcess::parseLine: clip_genre: '%s'", s.toUtf8().data()); + md.clip_genre = s; + } + else + + // Date + if (rx_clip_date.indexIn(line) > -1) { + QString s = rx_clip_date.cap(2).trimmed(); + qDebug("MplayerProcess::parseLine: clip_date: '%s'", s.toUtf8().data()); + md.clip_date = s; + } + else + + // Track + if (rx_clip_track.indexIn(line) > -1) { + QString s = rx_clip_track.cap(1).trimmed(); + qDebug("MplayerProcess::parseLine: clip_track: '%s'", s.toUtf8().data()); + md.clip_track = s; + } + else + + // Copyright + if (rx_clip_copyright.indexIn(line) > -1) { + QString s = rx_clip_copyright.cap(1).trimmed(); + qDebug("MplayerProcess::parseLine: clip_copyright: '%s'", s.toUtf8().data()); + md.clip_copyright = s; + } + else + + // Comment + if (rx_clip_comment.indexIn(line) > -1) { + QString s = rx_clip_comment.cap(1).trimmed(); + qDebug("MplayerProcess::parseLine: clip_comment: '%s'", s.toUtf8().data()); + md.clip_comment = s; + } + else + + // Software + if (rx_clip_software.indexIn(line) > -1) { + QString s = rx_clip_software.cap(1).trimmed(); + qDebug("MplayerProcess::parseLine: clip_software: '%s'", s.toUtf8().data()); + md.clip_software = s; + } + else + + if (rx_fontcache.indexIn(line) > -1) { + //qDebug("MplayerProcess::parseLine: updating font cache"); + emit receivedUpdatingFontCache(); + } + else + + // Catch starting message + /* + pos = rx_play.indexIn(line); + if (pos > -1) { + emit mplayerFullyLoaded(); + } + */ + + //Generic things + if (rx.indexIn(line) > -1) { + tag = rx.cap(1); + value = rx.cap(2); + //qDebug("MplayerProcess::parseLine: tag: %s, value: %s", tag.toUtf8().data(), value.toUtf8().data()); + +#if !NOTIFY_AUDIO_CHANGES + // Generic audio + if (tag == "ID_AUDIO_ID") { + int ID = value.toInt(); + qDebug("MplayerProcess::parseLine: ID_AUDIO_ID: %d", ID); + md.audios.addID( ID ); + } + else +#endif + + // Video + if (tag == "ID_VIDEO_ID") { + int ID = value.toInt(); + qDebug("MplayerProcess::parseLine: ID_VIDEO_ID: %d", ID); + md.videos.addID( ID ); + } + else + if (tag == "ID_LENGTH") { + md.duration = value.toDouble(); + qDebug("MplayerProcess::parseLine: md.duration set to %f", md.duration); + } + else + if (tag == "ID_VIDEO_WIDTH") { + md.video_width = value.toInt(); + qDebug("MplayerProcess::parseLine: md.video_width set to %d", md.video_width); + } + else + if (tag == "ID_VIDEO_HEIGHT") { + md.video_height = value.toInt(); + qDebug("MplayerProcess::parseLine: md.video_height set to %d", md.video_height); + } + else + if (tag == "ID_VIDEO_ASPECT") { + md.video_aspect = value.toDouble(); + if ( md.video_aspect == 0.0 ) { + // I hope width & height are already set. + md.video_aspect = (double) md.video_width / md.video_height; + } + qDebug("MplayerProcess::parseLine: md.video_aspect set to %f", md.video_aspect); + } + else + if (tag == "ID_DVD_DISC_ID") { + md.dvd_id = value; + qDebug("MplayerProcess::parseLine: md.dvd_id set to '%s'", md.dvd_id.toUtf8().data()); + } + else + if (tag == "ID_DEMUXER") { + md.demuxer = value; + } + else + if (tag == "ID_VIDEO_FORMAT") { + md.video_format = value; + } + else + if (tag == "ID_AUDIO_FORMAT") { + md.audio_format = value; + } + else + if (tag == "ID_VIDEO_BITRATE") { + md.video_bitrate = value.toInt(); + } + else + if (tag == "ID_VIDEO_FPS") { + md.video_fps = value; + } + else + if (tag == "ID_AUDIO_BITRATE") { + md.audio_bitrate = value.toInt(); + } + else + if (tag == "ID_AUDIO_RATE") { + md.audio_rate = value.toInt(); + } + else + if (tag == "ID_AUDIO_NCH") { + md.audio_nch = value.toInt(); + } + else + if (tag == "ID_VIDEO_CODEC") { + md.video_codec = value; + } + else + if (tag == "ID_AUDIO_CODEC") { + md.audio_codec = value; + } +#if GENERIC_CHAPTER_SUPPORT + else + if (tag == "ID_CHAPTERS") { + md.chapters = value.toInt(); + } + else + if (tag == "ID_DVD_CURRENT_TITLE") { + dvd_current_title = value.toInt(); + } +#endif + } + } +} + +// Called when the process is finished +void MplayerProcess::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { + qDebug("MplayerProcess::processFinished: exitCode: %d, status: %d", exitCode, (int) exitStatus); + // Send this signal before the endoffile one, otherwise + // the playlist will start to play next file before all + // objects are notified that the process has exited. + emit processExited(); + if (received_end_of_file) emit receivedEndOfFile(); +} + +void MplayerProcess::gotError(QProcess::ProcessError error) { + qDebug("MplayerProcess::gotError: %d", (int) error); +} + +#include "moc_mplayerprocess.cpp" diff --git a/plugins/smplayer_plugin/mplayerprocess.h b/plugins/smplayer_plugin/mplayerprocess.h new file mode 100644 index 000000000..9b603e7be --- /dev/null +++ b/plugins/smplayer_plugin/mplayerprocess.h @@ -0,0 +1,116 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MPLAYERPROCESS_H_ +#define _MPLAYERPROCESS_H_ + +#include +#include "myprocess.h" +#include "mediadata.h" +#include "config.h" + +#define NOTIFY_SUB_CHANGES 1 +#define NOTIFY_AUDIO_CHANGES 1 + +class QStringList; + +class MplayerProcess : public MyProcess +{ + Q_OBJECT + +public: + MplayerProcess(QObject * parent = 0); + ~MplayerProcess(); + + bool start(); + void writeToStdin(QString text); + + MediaData mediaData() { return md; }; + +signals: + void processExited(); + void lineAvailable(QString line); + + void receivedCurrentSec(double sec); + void receivedCurrentFrame(int frame); + void receivedPause(); + void receivedWindowResolution(int,int); + void receivedNoVideo(); + void receivedVO(QString); + void receivedAO(QString); + void receivedEndOfFile(); + void mplayerFullyLoaded(); + void receivedStartingTime(double sec); + + void receivedCacheMessage(QString); + void receivedCreatingIndex(QString); + void receivedConnectingToMessage(QString); + void receivedResolvingMessage(QString); + void receivedScreenshot(QString); + void receivedUpdatingFontCache(); + + void receivedStreamTitleAndUrl(QString,QString); + + void failedToParseMplayerVersion(QString line_with_mplayer_version); + +#if NOTIFY_SUB_CHANGES + //! Emitted if a new subtitle has been added or an old one changed + void subtitleInfoChanged(const SubTracks &); + + //! Emitted when subtitle info has been received but there wasn't anything new + void subtitleInfoReceivedAgain(const SubTracks &); +#endif +#if NOTIFY_AUDIO_CHANGES + //! Emitted if a new audio track been added or an old one changed + void audioInfoChanged(const Tracks &); +#endif + +protected slots: + void parseLine(QByteArray ba); + void processFinished(int exitCode, QProcess::ExitStatus exitStatus); + void gotError(QProcess::ProcessError); + +private: + bool notified_mplayer_is_running; + bool received_end_of_file; + + MediaData md; + + int last_sub_id; + + int mplayer_svn; + +#if NOTIFY_SUB_CHANGES + SubTracks subs; + + bool subtitle_info_received; + bool subtitle_info_changed; +#endif + +#if NOTIFY_AUDIO_CHANGES + Tracks audios; + bool audio_info_changed; +#endif + +#if GENERIC_CHAPTER_SUPPORT + int dvd_current_title; +#endif +}; + + +#endif diff --git a/plugins/smplayer_plugin/mplayerversion.cpp b/plugins/smplayer_plugin/mplayerversion.cpp new file mode 100644 index 000000000..cba29a056 --- /dev/null +++ b/plugins/smplayer_plugin/mplayerversion.cpp @@ -0,0 +1,128 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mplayerversion.h" +#include "global.h" +#include "preferences.h" + +#include + +using namespace Global; + +int MplayerVersion::mplayerVersion(QString string) { + //static QRegExp rx_mplayer_revision("^MPlayer (\\S+)-SVN-r(\\d+)-(.*)"); + static QRegExp rx_mplayer_revision("^MPlayer (.*)-r(\\d+)(.*)"); + static QRegExp rx_mplayer_version("^MPlayer ([a-z,0-9,.]+)-(.*)"); +#ifndef Q_OS_WIN + static QRegExp rx_mplayer_version_ubuntu("^MPlayer (\\d):(\\d)\\.(\\d)~(.*)"); +#endif + + int mplayer_svn = 0; + +#ifdef Q_OS_WIN + // Hack to recognize mplayer 1.0rc2 from CCCP: + if (string.startsWith("MPlayer CCCP ")) { + string.remove("CCCP "); + qDebug("MplayerVersion::mplayerVersion: removing CCCP: '%s'", string.toUtf8().data()); + } +#else + // Hack to recognize mplayer 1.0rc1 from Ubuntu: + if (rx_mplayer_version_ubuntu.indexIn(string) > -1) { + int v1 = rx_mplayer_version_ubuntu.cap(2).toInt(); + int v2 = rx_mplayer_version_ubuntu.cap(3).toInt(); + QString rest = rx_mplayer_version_ubuntu.cap(4); + //qDebug("%d - %d - %d", rx_mplayer_version_ubuntu.cap(1).toInt(), v1 , v2); + string = QString("MPlayer %1.%2%3").arg(v1).arg(v2).arg(rest); + qDebug("MplayerVersion::mplayerVersion: line converted to '%s'", string.toUtf8().data()); + } +#endif + + if (rx_mplayer_revision.indexIn(string) > -1) { + mplayer_svn = rx_mplayer_revision.cap(2).toInt(); + qDebug("MplayerVersion::mplayerVersion: MPlayer SVN revision found: %d", mplayer_svn); + } + else + if (rx_mplayer_version.indexIn(string) > -1) { + QString version = rx_mplayer_version.cap(1); + qDebug("MplayerVersion::mplayerVersion: MPlayer version found: %s", version.toUtf8().data()); + mplayer_svn = 0; + if (version == "1.0rc2") mplayer_svn = MPLAYER_1_0_RC2_SVN; + else + if (version == "1.0rc1") mplayer_svn = MPLAYER_1_0_RC1_SVN; + else qWarning("MplayerVersion::mplayerVersion: unknown MPlayer version"); + } + + if (pref) { + pref->mplayer_detected_version = mplayer_svn; + } + + return mplayer_svn; +} + +bool MplayerVersion::isMplayerAtLeast(int mplayer_svn, int svn_revision) { + qDebug("MplayerVersion::isMplayerAtLeast: comparing %d with %d", svn_revision, mplayer_svn); + + if (mplayer_svn == -1) { + qWarning("MplayerVersion::isMplayerAtLeast: no version found!"); + } + else + if (mplayer_svn == 0) { + qWarning("MplayerVersion::isMplayerAtLeast: version couldn't be parsed!"); + } + + if (mplayer_svn <= 0) { + qWarning("MplayerVersion::isMplayerAtLeast: assuming that the mplayer version is less than %d", svn_revision); + return false; + } + + return (mplayer_svn >= svn_revision); +} + +bool MplayerVersion::isMplayerAtLeast(int svn_revision) { + if (pref->mplayer_detected_version >= MPLAYER_1_0_RC1_SVN) { + // SVN version seems valid + if (pref->mplayer_user_supplied_version != -1) { + qDebug("MplayerVersion::isMplayerAtLeast: using the parsed svn version from mplayer output"); + qDebug("MplayerVersion::isMplayerAtLeast: and clearing the previously user supplied version"); + pref->mplayer_user_supplied_version = -1; + } + return isMplayerAtLeast(pref->mplayer_detected_version, svn_revision); + } + else + if (pref->mplayer_user_supplied_version != -1) { + qDebug("MplayerVersion::isMplayerAtLeast: no parsed version, using user supplied version"); + return isMplayerAtLeast(pref->mplayer_user_supplied_version, svn_revision); + } + else { + qWarning("MplayerVersion::isMplayerAtLeast: there's no parsed version nor user supplied version!"); + return isMplayerAtLeast(pref->mplayer_detected_version, svn_revision); + } +} + +QString MplayerVersion::toString(int svn_revision) { + QString version; + + switch (svn_revision) { + case MPLAYER_1_0_RC1_SVN: version = QString("1.0rc1"); break; + case MPLAYER_1_0_RC2_SVN: version = QString("1.0rc2"); break; + default : version = QString("SVN r%1").arg(svn_revision); + } + + return version; +} + diff --git a/plugins/smplayer_plugin/mplayerversion.h b/plugins/smplayer_plugin/mplayerversion.h new file mode 100644 index 000000000..c252a212b --- /dev/null +++ b/plugins/smplayer_plugin/mplayerversion.h @@ -0,0 +1,43 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MPLAYERVERSION_H_ +#define _MPLAYERVERSION_H_ + +#include + +#define MPLAYER_1_0_RC1_SVN 20372 +#define MPLAYER_1_0_RC2_SVN 24722 + +class MplayerVersion { +public: + + //! Parses the mplayer svn version from the string and returns it. + //! If the parsing fails, returns 0 + static int mplayerVersion(QString string); + + //! Returns true if svn_revision is equal or greater than mplayer_svn + static bool isMplayerAtLeast(int mplayer_svn, int svn_revision); + + static bool isMplayerAtLeast(int svn_revision); + + static QString toString(int mplayer_svn); +}; + +#endif + diff --git a/plugins/smplayer_plugin/mplayerwindow.cpp b/plugins/smplayer_plugin/mplayerwindow.cpp new file mode 100644 index 000000000..feed58361 --- /dev/null +++ b/plugins/smplayer_plugin/mplayerwindow.cpp @@ -0,0 +1,501 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mplayerwindow.h" +#include "global.h" +#include "desktopinfo.h" +#include "colorutils.h" + +#ifndef MINILIB +#include "images.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if DELAYED_RESIZE +#include +#endif + +Screen::Screen(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f ) +{ + setMouseTracking(TRUE); + setFocusPolicy( Qt::NoFocus ); + setMinimumSize( QSize(0,0) ); + +#if NEW_MOUSE_CHECK_POS + mouse_last_position = QPoint(0,0); +#else + cursor_pos = QPoint(0,0); + last_cursor_pos = QPoint(0,0); +#endif + + QTimer *timer = new QTimer(this); + connect( timer, SIGNAL(timeout()), this, SLOT(checkMousePos()) ); +#if NEW_MOUSE_CHECK_POS + timer->start(500); +#else + timer->start(2000); +#endif + + // Change attributes + setAttribute(Qt::WA_NoSystemBackground); + //setAttribute(Qt::WA_StaticContents); + //setAttribute( Qt::WA_OpaquePaintEvent ); + setAttribute(Qt::WA_PaintOnScreen); + setAttribute(Qt::WA_PaintUnclipped); + //setAttribute(Qt::WA_PaintOutsidePaintEvent); +} + +Screen::~Screen() { +} + +void Screen::paintEvent( QPaintEvent * e ) { + //qDebug("Screen::paintEvent"); + QPainter painter(this); + painter.eraseRect( e->rect() ); + //painter.fillRect( e->rect(), QColor(255,0,0) ); +} + +#if NEW_MOUSE_CHECK_POS +void Screen::checkMousePos() { + //qDebug("Screen::checkMousePos"); + QPoint pos = mapFromGlobal(QCursor::pos()); + + if (mouse_last_position != pos) { + setCursor(QCursor(Qt::ArrowCursor)); + } else { + setCursor(QCursor(Qt::BlankCursor)); + } + mouse_last_position = pos; +} +#else +void Screen::checkMousePos() { + //qDebug("Screen::checkMousePos"); + + if ( cursor_pos == last_cursor_pos ) { + //qDebug(" same pos"); + if (cursor().shape() != Qt::BlankCursor) { + //qDebug(" hiding mouse cursor"); + setCursor(QCursor(Qt::BlankCursor)); + } + } else { + last_cursor_pos = cursor_pos; + } +} + +void Screen::mouseMoveEvent( QMouseEvent * e ) { + //qDebug("Screen::mouseMoveEvent"); + //qDebug(" pos: x: %d y: %d", e->pos().x(), e->pos().y() ); + cursor_pos = e->pos(); + + if (cursor().shape() != Qt::ArrowCursor) { + //qDebug(" showing mouse cursor" ); + setCursor(QCursor(Qt::ArrowCursor)); + } +} +#endif + +/* ---------------------------------------------------------------------- */ + +MplayerLayer::MplayerLayer(QWidget* parent, Qt::WindowFlags f) + : Screen(parent, f) +{ +#if REPAINT_BACKGROUND_OPTION + repaint_background = true; +#endif + playing = false; +} + +MplayerLayer::~MplayerLayer() { +} + +#if REPAINT_BACKGROUND_OPTION +void MplayerLayer::setRepaintBackground(bool b) { + qDebug("MplayerLayer::setRepaintBackground: %d", b); + repaint_background = b; +} + +void MplayerLayer::paintEvent( QPaintEvent * e ) { + //qDebug("MplayerLayer::paintEvent: allow_clearing: %d", allow_clearing); + if (repaint_background || !playing) { + //qDebug("MplayerLayer::paintEvent: painting"); + Screen::paintEvent(e); + } +} +#endif + +void MplayerLayer::playingStarted() { + qDebug("MplayerLayer::playingStarted"); + repaint(); + playing = true; +} + +void MplayerLayer::playingStopped() { + qDebug("MplayerLayer::playingStopped"); + playing = false; + repaint(); +} + +/* ---------------------------------------------------------------------- */ + +MplayerWindow::MplayerWindow(QWidget* parent, Qt::WindowFlags f) + : Screen(parent, f) , allow_video_movement(false) +{ + offset_x = 0; + offset_y = 0; + zoom_factor = 1.0; + + setAutoFillBackground(true); + ColorUtils::setBackgroundColor( this, QColor(0,0,0) ); + + mplayerlayer = new MplayerLayer( this ); + mplayerlayer->setAutoFillBackground(TRUE); + + logo = new QLabel( mplayerlayer ); + logo->setAutoFillBackground(TRUE); +#if QT_VERSION >= 0x040400 + logo->setAttribute(Qt::WA_NativeWindow); // Otherwise the logo is not visible in Qt 4.4 +#else + logo->setAttribute(Qt::WA_PaintOnScreen); // Fixes the problem if compiled with Qt < 4.4 +#endif + ColorUtils::setBackgroundColor( logo, QColor(0,0,0) ); + + QVBoxLayout * mplayerlayerLayout = new QVBoxLayout( mplayerlayer ); + mplayerlayerLayout->addWidget( logo, 0, Qt::AlignHCenter | Qt::AlignVCenter ); + + aspect = (double) 4 / 3; + monitoraspect = 0; + + setSizePolicy( QSizePolicy::Expanding , QSizePolicy::Expanding ); + setFocusPolicy( Qt::StrongFocus ); + + installEventFilter(this); + mplayerlayer->installEventFilter(this); + //logo->installEventFilter(this); + +#if DELAYED_RESIZE + resize_timer = new QTimer(this); + resize_timer->setSingleShot(true); + resize_timer->setInterval(50); + connect( resize_timer, SIGNAL(timeout()), this, SLOT(resizeLater()) ); +#endif + + retranslateStrings(); +} + +MplayerWindow::~MplayerWindow() { +} + +#if USE_COLORKEY +void MplayerWindow::setColorKey( QColor c ) { + ColorUtils::setBackgroundColor( mplayerlayer, c ); +} +#endif + +void MplayerWindow::retranslateStrings() { + //qDebug("MplayerWindow::retranslateStrings"); +#ifndef MINILIB + logo->setPixmap( Images::icon("background") ); +#endif +} + +void MplayerWindow::showLogo( bool b) +{ + if (b) logo->show(); else logo->hide(); +} + +/* +void MplayerWindow::changePolicy() { + setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Preferred ); +} +*/ + +void MplayerWindow::setResolution( int w, int h) +{ + video_width = w; + video_height = h; + + //mplayerlayer->move(1,1); + updateVideoWindow(); +} + + +void MplayerWindow::resizeEvent( QResizeEvent * /* e */) +{ + /*qDebug("MplayerWindow::resizeEvent: %d, %d", + e->size().width(), e->size().height() );*/ + +#if !DELAYED_RESIZE + offset_x = 0; + offset_y = 0; + + updateVideoWindow(); + setZoom(zoom_factor); +#else + resize_timer->start(); +#endif +} + +#if DELAYED_RESIZE +void MplayerWindow::resizeLater() { + offset_x = 0; + offset_y = 0; + + updateVideoWindow(); + setZoom(zoom_factor); +} +#endif + +void MplayerWindow::setMonitorAspect(double asp) { + monitoraspect = asp; +} + +void MplayerWindow::setAspect( double asp) { + aspect = asp; + if (monitoraspect!=0) { + aspect = aspect / monitoraspect * DesktopInfo::desktop_aspectRatio(this); + } + updateVideoWindow(); +} + + +void MplayerWindow::updateVideoWindow() +{ + //qDebug("MplayerWindow::updateVideoWindow"); + + //qDebug("aspect= %f", aspect); + + int w_width = size().width(); + int w_height = size().height(); + + int w = w_width; + int h = w_height; + int x = 0; + int y = 0; + + if (aspect != 0) { + int pos1_w = w_width; + int pos1_h = w_width / aspect + 0.5; + + int pos2_h = w_height; + int pos2_w = w_height * aspect + 0.5; + + //qDebug("pos1_w: %d, pos1_h: %d", pos1_w, pos1_h); + //qDebug("pos2_w: %d, pos2_h: %d", pos2_w, pos2_h); + + if (pos1_h <= w_height) { + //qDebug("Pos1!"); + w = pos1_w; + h = pos1_h; + + y = (w_height - h) /2; + } else { + //qDebug("Pos2!"); + w = pos2_w; + h = pos2_h; + + x = (w_width - w) /2; + } + } + + mplayerlayer->move(x,y); + mplayerlayer->resize(w, h); + + orig_x = x; + orig_y = y; + orig_width = w; + orig_height = h; + + //qDebug( "w_width: %d, w_height: %d", w_width, w_height); + //qDebug("w: %d, h: %d", w,h); +} + + +void MplayerWindow::mouseReleaseEvent( QMouseEvent * e) { + qDebug( "MplayerWindow::mouseReleaseEvent" ); + + if (e->button() == Qt::LeftButton) { + e->accept(); + emit leftClicked(); + } + else + if (e->button() == Qt::MidButton) { + e->accept(); + emit middleClicked(); + } + else + if (e->button() == Qt::XButton1) { + e->accept(); + emit xbutton1Clicked(); + } + else + if (e->button() == Qt::XButton2) { + e->accept(); + emit xbutton2Clicked(); + } + else + if (e->button() == Qt::RightButton) { + e->accept(); + //emit rightButtonReleased( e->globalPos() ); + emit rightClicked(); + } + else { + e->ignore(); + } +} + +void MplayerWindow::mouseDoubleClickEvent( QMouseEvent * e ) { + if (e->button() == Qt::LeftButton) { + e->accept(); + emit doubleClicked(); + } else { + e->ignore(); + } +} + +void MplayerWindow::wheelEvent( QWheelEvent * e ) { + qDebug("MplayerWindow::wheelEvent: delta: %d", e->delta()); + e->accept(); + + if (e->orientation() == Qt::Vertical) { + if (e->delta() >= 0) + emit wheelUp(); + else + emit wheelDown(); + } else { + qDebug("MplayerWindow::wheelEvent: horizontal event received, doing nothing"); + } +} + +bool MplayerWindow::eventFilter( QObject * /*watched*/, QEvent * event ) { + //qDebug("MplayerWindow::eventFilter"); + + if ( (event->type() == QEvent::MouseMove) || + (event->type() == QEvent::MouseButtonRelease) ) + { + QMouseEvent *mouse_event = static_cast(event); + + if (event->type() == QEvent::MouseMove) { + emit mouseMoved(mouse_event->pos()); + } + } + + return false; +} + +QSize MplayerWindow::sizeHint() const { + //qDebug("MplayerWindow::sizeHint"); + return QSize( video_width, video_height ); +} + +QSize MplayerWindow::minimumSizeHint () const { + return QSize(0,0); +} + +void MplayerWindow::setOffsetX( int d) { + offset_x = d; + mplayerlayer->move( orig_x + offset_x, mplayerlayer->y() ); +} + +int MplayerWindow::offsetX() { return offset_x; } + +void MplayerWindow::setOffsetY( int d) { + offset_y = d; + mplayerlayer->move( mplayerlayer->x(), orig_y + offset_y ); +} + +int MplayerWindow::offsetY() { return offset_y; } + +void MplayerWindow::setZoom( double d) { + zoom_factor = d; + offset_x = 0; + offset_y = 0; + + int x = orig_x; + int y = orig_y; + int w = orig_width; + int h = orig_height; + + if (zoom_factor != 1.0) { + w = w * zoom_factor; + h = h * zoom_factor; + + // Center + x = (width() - w) / 2; + y = (height() -h) / 2; + } + + mplayerlayer->move(x,y); + mplayerlayer->resize(w,h); +} + +double MplayerWindow::zoom() { return zoom_factor; } + +void MplayerWindow::moveLayer( int offset_x, int offset_y ) { + int x = mplayerlayer->x(); + int y = mplayerlayer->y(); + + mplayerlayer->move( x + offset_x, y + offset_y ); +} + +void MplayerWindow::moveLeft() { + if ((allow_video_movement) || (mplayerlayer->x()+mplayerlayer->width() > width() )) + moveLayer( -16, 0 ); +} + +void MplayerWindow::moveRight() { + if ((allow_video_movement) || ( mplayerlayer->x() < 0 )) + moveLayer( +16, 0 ); +} + +void MplayerWindow::moveUp() { + if ((allow_video_movement) || (mplayerlayer->y()+mplayerlayer->height() > height() )) + moveLayer( 0, -16 ); +} + +void MplayerWindow::moveDown() { + if ((allow_video_movement) || ( mplayerlayer->y() < 0 )) + moveLayer( 0, +16 ); +} + +void MplayerWindow::incZoom() { + setZoom( zoom_factor + ZOOM_STEP ); +} + +void MplayerWindow::decZoom() { + double zoom = zoom_factor - ZOOM_STEP; + if (zoom < ZOOM_MIN) zoom = ZOOM_MIN; + setZoom( zoom ); +} + +// Language change stuff +void MplayerWindow::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QWidget::changeEvent(e); + } +} + +#include "moc_mplayerwindow.cpp" diff --git a/plugins/smplayer_plugin/mplayerwindow.h b/plugins/smplayer_plugin/mplayerwindow.h new file mode 100644 index 000000000..7b66ca626 --- /dev/null +++ b/plugins/smplayer_plugin/mplayerwindow.h @@ -0,0 +1,212 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef MPLAYERWINDOW_H +#define MPLAYERWINDOW_H + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "config.h" + +class QWidget; +class QLabel; +class QKeyEvent; +class QTimer; + +#define ZOOM_STEP 0.05 +#define ZOOM_MIN 0.5 + +#define DELAYED_RESIZE 0 +#define NEW_MOUSE_CHECK_POS 1 + +//! Screen is a widget that hides the mouse cursor after some seconds if not moved. + +class Screen : public QWidget +{ + Q_OBJECT + +public: + Screen(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~Screen(); + +protected: +#if !NEW_MOUSE_CHECK_POS + virtual void mouseMoveEvent( QMouseEvent * e ); +#endif + virtual void paintEvent ( QPaintEvent * e ); + +protected slots: + virtual void checkMousePos(); + +private: +#if NEW_MOUSE_CHECK_POS + QPoint mouse_last_position; +#else + QPoint cursor_pos, last_cursor_pos; +#endif +}; + +//! MplayerLayer can be instructed to not delete the background. + +class MplayerLayer : public Screen +{ + Q_OBJECT + +public: + MplayerLayer(QWidget* parent = 0, Qt::WindowFlags f = 0); + ~MplayerLayer(); + +#if REPAINT_BACKGROUND_OPTION + //! If b is true, the background of the widget will be repainted as usual. + /*! Otherwise the background will not repainted when a video is playing. */ + void setRepaintBackground(bool b); + + //! Return true if repainting the background is allowed. + bool repaintBackground() { return repaint_background; }; +#endif + +public slots: + //! Should be called when a file has started. + /*! It's needed to know if the background has to be cleared or not. */ + void playingStarted(); + //! Should be called when a file has stopped. + void playingStopped(); + +#if REPAINT_BACKGROUND_OPTION +protected: + virtual void paintEvent ( QPaintEvent * e ); +#endif + +private: +#if REPAINT_BACKGROUND_OPTION + bool repaint_background; +#endif + bool playing; +}; + + +class MplayerWindow : public Screen +{ + Q_OBJECT + +public: + MplayerWindow( QWidget* parent = 0, Qt::WindowFlags f = 0); + ~MplayerWindow(); + + void showLogo( bool b); + + MplayerLayer * videoLayer() { return mplayerlayer; }; + + void setResolution( int w, int h); + void setAspect( double asp); + void setMonitorAspect(double asp); + void updateVideoWindow(); + +#if USE_COLORKEY + void setColorKey(QColor c); +#endif + + void setOffsetX( int ); + int offsetX(); + + void setOffsetY( int ); + int offsetY(); + + void setZoom( double ); + double zoom(); + + void allowVideoMovement(bool b) { allow_video_movement = b; }; + bool isVideoMovementAllowed() { return allow_video_movement; }; + + virtual QSize sizeHint () const; + virtual QSize minimumSizeHint() const; + + virtual bool eventFilter( QObject * watched, QEvent * event ); + +public slots: + void moveLeft(); + void moveRight(); + void moveUp(); + void moveDown(); + void incZoom(); + void decZoom(); + +#if DELAYED_RESIZE +protected slots: + void resizeLater(); +#endif + +protected: + virtual void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + + virtual void resizeEvent( QResizeEvent * e); + virtual void mouseReleaseEvent( QMouseEvent * e); + virtual void mouseDoubleClickEvent( QMouseEvent * e ); + virtual void wheelEvent( QWheelEvent * e ); + void moveLayer( int offset_x, int offset_y ); + +signals: + //void rightButtonReleased( QPoint p ); + void doubleClicked(); + void leftClicked(); + void rightClicked(); + void middleClicked(); + void xbutton1Clicked(); // first X button + void xbutton2Clicked(); // second X button + void keyPressed(QKeyEvent * e); + void wheelUp(); + void wheelDown(); + void mouseMoved(QPoint); + +protected: + int video_width, video_height; + double aspect; + double monitoraspect; + + MplayerLayer * mplayerlayer; + QLabel * logo; + + // Zoom and moving + int offset_x, offset_y; + double zoom_factor; + + // Original pos and dimensions of the mplayerlayer + // before zooming or moving + int orig_x, orig_y; + int orig_width, orig_height; + + bool allow_video_movement; + +#if DELAYED_RESIZE + QTimer * resize_timer; +#endif +}; + + +#endif + diff --git a/plugins/smplayer_plugin/myaction.cpp b/plugins/smplayer_plugin/myaction.cpp new file mode 100644 index 000000000..7daa9b659 --- /dev/null +++ b/plugins/smplayer_plugin/myaction.cpp @@ -0,0 +1,101 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "myaction.h" +#include + +MyAction::MyAction ( QObject * parent, const char * name, bool autoadd ) + : QAction(parent) +{ + //qDebug("MyAction::MyAction: name: '%s'", name); + setObjectName(name); + if (autoadd) addActionToParent(); +} + + +MyAction::MyAction( QObject * parent, bool autoadd ) + : QAction(parent) +{ + //qDebug("MyAction::MyAction: QObject, bool"); + if (autoadd) addActionToParent(); +} + +MyAction::MyAction(const QString & text, QKeySequence accel, + QObject * parent, const char * name, bool autoadd ) + : QAction(parent) +{ + setObjectName(name); + setText(text); + setShortcut(accel); + if (autoadd) addActionToParent(); +} + +MyAction::MyAction(QKeySequence accel, QObject * parent, const char * name, + bool autoadd ) + : QAction(parent) +{ + setObjectName(name); + setShortcut(accel); + if (autoadd) addActionToParent(); +} + +MyAction::~MyAction() { +} + +void MyAction::addActionToParent() { + if (parent()) { + if (parent()->inherits("QWidget")) { + QWidget *w = static_cast (parent()); + w->addAction(this); + } + } +} + +void MyAction::change(const QIcon & icon, const QString & text) { + setIcon( icon ); + change(text); +} + +void MyAction::change(const QString & text ) { + setText( text ); + + QString accel_text = shortcut().toString(); + + QString s = text; + s.replace("&",""); + if (!accel_text.isEmpty()) { + setToolTip( s + " ("+ accel_text +")"); + setIconText( s ); + } + + /* + if (text.isEmpty()) { + QString s = menuText; + s = s.replace("&",""); + setText( s ); + + if (!accel_text.isEmpty()) + setToolTip( s + " ("+ accel_text +")"); + } else { + setText( text ); + if (!accel_text.isEmpty()) + setToolTip( text + " ("+ accel_text +")"); + } + */ +} + diff --git a/plugins/smplayer_plugin/myaction.h b/plugins/smplayer_plugin/myaction.h new file mode 100644 index 000000000..6de77b944 --- /dev/null +++ b/plugins/smplayer_plugin/myaction.h @@ -0,0 +1,60 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MYACTION_H_ +#define _MYACTION_H_ + +#include +#include +#include +#include + +class MyAction : public QAction +{ + +public: + //! Creates a new MyAction with name \a name. If \a autoadd is true + //! the action will be added to the parent + MyAction ( QObject * parent, const char * name, bool autoadd = true ); + + //! Creates a new MyAction. If \a autoadd is true + //! the action will be added to the parent + MyAction ( QObject * parent, bool autoadd = true ); + + MyAction ( const QString & text, QKeySequence accel, + QObject * parent, const char * name = "", + bool autoadd = true ); + + MyAction ( QKeySequence accel, QObject * parent, + const char * name = "", bool autoadd = true ); + + ~MyAction(); + + //! Change the icon and text of the action. + void change(const QIcon & icon, const QString & text ); + + //! Change the text of the action. + void change(const QString & text); + +protected: + //! Checks if the parent is a QWidget and adds the action to it. + void addActionToParent(); +}; + +#endif + diff --git a/plugins/smplayer_plugin/myactiongroup.cpp b/plugins/smplayer_plugin/myactiongroup.cpp new file mode 100644 index 000000000..9fe0b3418 --- /dev/null +++ b/plugins/smplayer_plugin/myactiongroup.cpp @@ -0,0 +1,117 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "myactiongroup.h" +#include +#include +#include + +MyActionGroupItem::MyActionGroupItem(QObject * parent, MyActionGroup *group, + const char * name, + int data, bool autoadd) + : MyAction(parent, name, autoadd) +{ + setData(data); + setCheckable(true); + if (group) group->addAction(this); +} + +MyActionGroupItem::MyActionGroupItem(QObject * parent, MyActionGroup *group, + const QString & text, + const char * name, + int data, bool autoadd) + : MyAction(parent, name, autoadd) +{ + setData(data); + setText(text); + setCheckable(true); + if (group) group->addAction(this); +} + + +MyActionGroup::MyActionGroup( QObject * parent ) : QActionGroup(parent) +{ + setExclusive(true); + connect( this, SIGNAL(triggered(QAction *)), + this, SLOT(itemTriggered(QAction *)) ); +} + +void MyActionGroup::setChecked(int ID) { + //qDebug("MyActionGroup::setChecked: ID: %d", ID); + + QList l = actions(); + for (int n=0; n < l.count(); n++) { + if ( (!l[n]->isSeparator()) && (l[n]->data().toInt() == ID) ) { + l[n]->setChecked(true); + return; + } + } +} + +int MyActionGroup::checked() { + QAction * a = checkedAction(); + if (a) + return a->data().toInt(); + else + return -1; +} + +void MyActionGroup::uncheckAll() { + QList l = actions(); + for (int n=0; n < l.count(); n++) { + l[n]->setChecked(false); + } +} + +void MyActionGroup::setActionsEnabled(bool b) { + QList l = actions(); + for (int n=0; n < l.count(); n++) { + l[n]->setEnabled(b); + } +} + +void MyActionGroup::clear(bool remove) { + while (actions().count() > 0) { + QAction * a = actions()[0]; + if (a) { + removeAction(a); + if (remove) a->deleteLater(); + } + } +} + +void MyActionGroup::itemTriggered(QAction *a) { + qDebug("MyActionGroup::itemTriggered: '%s'", a->objectName().toUtf8().data()); + int value = a->data().toInt(); + + qDebug("MyActionGroup::itemTriggered: ID: %d", value); + + emit activated(value); +} + +void MyActionGroup::addTo(QWidget *w) { + w->addActions( actions() ); +} + +void MyActionGroup::removeFrom(QWidget *w) { + for (int n=0; n < actions().count(); n++) { + w->removeAction( actions()[n] ); + } +} + +#include "moc_myactiongroup.cpp" diff --git a/plugins/smplayer_plugin/myactiongroup.h b/plugins/smplayer_plugin/myactiongroup.h new file mode 100644 index 000000000..7247e31bf --- /dev/null +++ b/plugins/smplayer_plugin/myactiongroup.h @@ -0,0 +1,90 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MYACTIONGROUP_H_ +#define _MYACTIONGROUP_H_ + +#include +#include +#include "myaction.h" + +class MyActionGroup; + +//! This class makes easy to create actions for MyActionGroup + +class MyActionGroupItem : public MyAction +{ +public: + //! Creates a new item. + /*! \a group is the group where the action will be added, \a data is + the ID of the item. If \autoadd is true the action will be added to + the parent (if it's a QWidget), so the shortcut could work. */ + MyActionGroupItem( QObject * parent, MyActionGroup *group, + const char * name, int data, bool autoadd = true ); + + //! Creates a new item. + /*! \a text is the text that the item will have. */ + MyActionGroupItem( QObject * parent, MyActionGroup *group, + const QString & text, const char * name, + int data, bool autoadd = true ); +}; + +class QAction; + +//! MyActionGroup makes easier to create exclusive menus based on items +//! with an integer data. + + +class MyActionGroup : public QActionGroup +{ + Q_OBJECT + +public: + MyActionGroup ( QObject * parent ); + + //! Looks for the item which ID is \a ID and checks it + void setChecked(int ID); + + //! Returns the ID of the item checked or -1 if none + //! is checked + int checked(); + + //! Remove all items. If \a remove is true the actions are also deleted. + void clear(bool remove); + + //! Enable or disable all actions in the group + void setActionsEnabled(bool); + + //! Adds all actions to the widget + void addTo(QWidget *); + + //! Remove all actions from the widget + void removeFrom(QWidget *); + + //! unchecks all items + void uncheckAll(); + +signals: + //! Emitted when an item has been checked + void activated(int); + +protected slots: + void itemTriggered(QAction *); +}; + +#endif diff --git a/plugins/smplayer_plugin/myclient.cpp b/plugins/smplayer_plugin/myclient.cpp new file mode 100644 index 000000000..153a85079 --- /dev/null +++ b/plugins/smplayer_plugin/myclient.cpp @@ -0,0 +1,119 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "myclient.h" +#include +#include +#include +#include + +MyClient::MyClient(quint16 port, QObject * parent) : QObject(parent) +{ + qDebug("MyClient::MyClient"); + + this->port = port; + timeout = 200; + + socket = new QTcpSocket(this); +} + +MyClient::~MyClient() { + delete socket; +} + +QString MyClient::readLine() { + QString line; + + int n = 0; + while (!socket->canReadLine() && n < 5) { + //qDebug("Bytes available: %d", (int) socket->bytesAvailable()); + socket->waitForReadyRead( timeout ); + n++; + } + if (socket->canReadLine()) { + line = QString::fromUtf8(socket->readLine()); + line.remove( QRegExp("[\r\n]") ); + qDebug("MyClient::readLine: '%s'", line.toUtf8().data()); + } + + return line; +} + +void MyClient::writeLine(QString l) { + socket->write( l.toUtf8() ); + socket->flush(); + socket->waitForBytesWritten( timeout ); +} + +bool MyClient::openConnection() { + socket->connectToHost( QHostAddress::LocalHost, port, QIODevice::ReadWrite); + if (!socket->waitForConnected( timeout )) return false; // Can't connect + + QString line = readLine(); + if (!line.startsWith("SMPlayer")) return false; + qDebug("MyClient::sendFiles: connected to a SMPlayer instance!"); + + line = readLine(); // Read help message + + return true; +} + + +bool MyClient::sendFiles( const QStringList & files, bool addToPlaylist) { + QString line; + + writeLine("open_files_start\r\n"); + line = readLine(); + if (!line.startsWith("OK")) return false; + + for (int n=0; n < files.count(); n++) { + writeLine("open_files " + files[n] + "\r\n"); + line = readLine(); + if (!line.startsWith("OK")) return false; + } + + if (!addToPlaylist) + writeLine("open_files_end\r\n"); + else + writeLine("add_files_end\r\n"); + + writeLine("quit\r\n"); + + do { + line = readLine(); + } while (!line.isNull()); + + + socket->disconnectFromHost(); + socket->waitForDisconnected( timeout ); + + return true; +} + +bool MyClient::sendAction( const QString & action ) { + QString line; + + writeLine("f " + action + "\r\n"); + line = readLine(); + if (!line.startsWith("OK")) return false; + + socket->disconnectFromHost(); + socket->waitForDisconnected( timeout ); + + return true; +} diff --git a/plugins/smplayer_plugin/myclient.h b/plugins/smplayer_plugin/myclient.h new file mode 100644 index 000000000..9f4e2e960 --- /dev/null +++ b/plugins/smplayer_plugin/myclient.h @@ -0,0 +1,63 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MYCLIENT_H_ +#define _MYCLIENT_H_ + +#include + +class QTextStream; +class QTcpSocket; + + +//! MyClient communicates with other running instances. + +/*! + It can be used to know if there's another instance of smplayer running. + It also allows to send the file(s) that the user wants to open to + the other instance. +*/ + +class MyClient : public QObject +{ +public: + MyClient(quint16 port, QObject * parent = 0); + ~MyClient(); + + //! Sets the maximum time that should wait in the waitFor... functions. + void setTimeOut(int ms) { timeout = ms; }; + int timeOut() { return timeout; }; + + //! Return true if it can open a connection to another instance. + bool openConnection(); + //! Send the list of files to the other instance. Return true on success. + bool sendFiles( const QStringList & files, bool addToPlaylist = false); + //! Pass an action (pause, fullscreen...) to GUI. + bool sendAction( const QString & action ); + +protected: + QString readLine(); + void writeLine(QString); + +private: + quint16 port; + QTcpSocket * socket; + int timeout; +}; + +#endif diff --git a/plugins/smplayer_plugin/mycombobox.cpp b/plugins/smplayer_plugin/mycombobox.cpp new file mode 100644 index 000000000..ba88024c0 --- /dev/null +++ b/plugins/smplayer_plugin/mycombobox.cpp @@ -0,0 +1,61 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mycombobox.h" + +MyComboBox::MyComboBox( QWidget * parent ) : QComboBox(parent) +{ +} + +MyComboBox::~MyComboBox() +{ +} + +void MyComboBox::setCurrentText( const QString & text ) { + int i = findText(text); + if (i != -1) + setCurrentIndex(i); + else if (isEditable()) + setEditText(text); + else + setItemText(currentIndex(), text); +} + +void MyComboBox::insertStringList( const QStringList & list, int index ) { + insertItems((index < 0 ? count() : index), list); +} + + + +MyFontComboBox::MyFontComboBox( QWidget * parent ) : QFontComboBox(parent) +{ +} + +MyFontComboBox::~MyFontComboBox() +{ +} + +void MyFontComboBox::setCurrentText( const QString & text ) { + int i = findText(text); + if (i != -1) + setCurrentIndex(i); + else if (isEditable()) + setEditText(text); + else + setItemText(currentIndex(), text); +} diff --git a/plugins/smplayer_plugin/mycombobox.h b/plugins/smplayer_plugin/mycombobox.h new file mode 100644 index 000000000..2fedb5c20 --- /dev/null +++ b/plugins/smplayer_plugin/mycombobox.h @@ -0,0 +1,48 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MYCOMBOBOX_H_ +#define _MYCOMBOBOX_H_ + +#include +#include + +//! This class adds some Qt 3 compatibility functions which don't have a +//! direct equivalent in Qt 4. + +class MyComboBox : public QComboBox +{ +public: + MyComboBox( QWidget * parent = 0 ); + ~MyComboBox(); + + void setCurrentText ( const QString & text ); + void insertStringList ( const QStringList & list, int index = -1 ); +}; + + +class MyFontComboBox : public QFontComboBox +{ +public: + MyFontComboBox( QWidget * parent = 0 ); + ~MyFontComboBox(); + + void setCurrentText ( const QString & text ); +}; + +#endif diff --git a/plugins/smplayer_plugin/myprocess.cpp b/plugins/smplayer_plugin/myprocess.cpp new file mode 100644 index 000000000..d0d82c2a9 --- /dev/null +++ b/plugins/smplayer_plugin/myprocess.cpp @@ -0,0 +1,171 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "myprocess.h" + +#ifdef Q_OS_WIN + +#if QT_VERSION < 0x040300 +#define USE_TEMP_FILE 1 +#else +#define USE_TEMP_FILE 0 +#endif + +#else +#define USE_TEMP_FILE 0 +#endif + + +MyProcess::MyProcess(QObject * parent) : QProcess(parent) +{ + clearArguments(); + setProcessChannelMode( QProcess::MergedChannels ); + +#if USE_TEMP_FILE + temp_file.open(); // Create temporary file + QString filename = temp_file.fileName(); + setStandardOutputFile( filename ); + qDebug("MyProcess::MyProcess: temporary file: %s", filename.toUtf8().data()); + temp_file.close(); + + //connect(&temp_file, SIGNAL(readyRead()), this, SLOT(readTmpFile()) ); + connect(&timer, SIGNAL(timeout()), this, SLOT(readTmpFile()) ); +#else + connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOut()) ); +#endif + + connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(procFinished()) ); +} + +void MyProcess::clearArguments() { + program = ""; + arg.clear(); +} + +bool MyProcess::isRunning() { + return (state() == QProcess::Running); +} + +void MyProcess::addArgument(const QString & a) { + if (program.isEmpty()) { + program = a; + } else { + arg.append(a); + } +} + +QStringList MyProcess::arguments() { + QStringList l = arg; + l.prepend(program); + return l; +} + +void MyProcess::start() { + remaining_output.clear(); + + QProcess::start(program, arg); + +#if USE_TEMP_FILE + //bool r = temp_file.open(QIODevice::ReadOnly); + bool r = temp_file.open(); + timer.start(50); + qDebug("MyProcess::start: r: %d", r); +#endif +} + +void MyProcess::readStdOut() { + genericRead( readAllStandardOutput() ); +} + + +void MyProcess::readTmpFile() { + genericRead( temp_file.readAll() ); +} + +void MyProcess::genericRead(QByteArray buffer) { + QByteArray ba = remaining_output + buffer; + int start = 0; + int from_pos = 0; + int pos = canReadLine(ba, from_pos); + + //qDebug("MyProcess::read: pos: %d", pos); + while ( pos > -1 ) { + // Readline + //QByteArray line = ba.left(pos); + QByteArray line = ba.mid(start, pos-start); + //ba = ba.mid(pos+1); + from_pos = pos + 1; +#ifdef Q_OS_WIN + if ((from_pos < ba.size()) && (ba.at(from_pos)=='\n')) from_pos++; +#endif + start = from_pos; + + emit lineAvailable(line); + + pos = canReadLine(ba, from_pos); + } + + remaining_output = ba.mid(from_pos); +} + +int MyProcess::canReadLine(const QByteArray & ba, int from) { + int pos1 = ba.indexOf('\n', from); + int pos2 = ba.indexOf('\r', from); + + //qDebug("MyProcess::canReadLine: pos2: %d", pos2); + + if ( (pos1 == -1) && (pos2 == -1) ) return -1; + + int pos = pos1; + if ( (pos1 != -1) && (pos2 != -1) ) { + /* + if (pos2 == (pos1+1)) pos = pos2; // \r\n + else + */ + if (pos1 < pos2) pos = pos1; else pos = pos2; + } else { + if (pos1 == -1) pos = pos2; + else + if (pos2 == -1) pos = pos1; + } + + return pos; +} + +/*! +Do some clean up, and be sure that all output has been read. +*/ +void MyProcess::procFinished() { + qDebug("MyProcess::procFinished"); + +#if !USE_TEMP_FILE + qDebug("MyProcess::procFinished: Bytes available: %ld", bytesAvailable()); + if ( bytesAvailable() > 0 ) readStdOut(); +#else + timer.stop(); + + qDebug("MyProcess::procFinished: Bytes available: %ld", temp_file.bytesAvailable()); + if ( temp_file.bytesAvailable() > 0 ) readTmpFile(); + qDebug("MyProcess::procFinished: Bytes available: %ld", temp_file.bytesAvailable()); + + temp_file.close(); +#endif +} + +#include "moc_myprocess.cpp" diff --git a/plugins/smplayer_plugin/myprocess.h b/plugins/smplayer_plugin/myprocess.h new file mode 100644 index 000000000..f173bdd20 --- /dev/null +++ b/plugins/smplayer_plugin/myprocess.h @@ -0,0 +1,79 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MY_PROCESS_H_ +#define _MY_PROCESS_H_ + +#include +#include +#include + +//! MyProcess is a specialized QProcess designed to properly work with mplayer. + +/*! + It can split the mplayer status line into lines. + It also provides some Qt 3 like functions like addArgument(). + + There are two working modes, controlled by the USE_TEMP_FILE define. + If USE_TEMP_FILE is 1 it will send the output of mplayer to a temporary + file, and then it will be read from it. Otherwise it will read from + standard ouput as usual. +*/ + +class MyProcess : public QProcess +{ + Q_OBJECT + +public: + MyProcess ( QObject * parent = 0 ); + + void addArgument(const QString & a); //!< Add an argument + + void clearArguments(); //!< Clear the list of arguments + QStringList arguments(); //!< Return the list of arguments + + void start(); //!< Start the process + bool isRunning(); //!< Return true if the process is running + +signals: + //! Emitted when there's a line available + void lineAvailable(QByteArray ba); + +protected slots: + void readStdOut(); //!< Called for reading from standard output + void readTmpFile(); //!< Called for reading from the temp file + void procFinished(); //!< Called when the process has finished + +protected: + //! Return true if it's possible to read an entire line. + /*! @param from specifies the position to begin. */ + int canReadLine(const QByteArray & ba, int from = 0); + //! Called from readStdOut() and readTmpFile() to do all the work + void genericRead(QByteArray buffer); + +private: + QString program; + QStringList arg; + + QByteArray remaining_output; + + QTemporaryFile temp_file; + QTimer timer; +}; + +#endif diff --git a/plugins/smplayer_plugin/myserver.cpp b/plugins/smplayer_plugin/myserver.cpp new file mode 100644 index 000000000..1e67ab71a --- /dev/null +++ b/plugins/smplayer_plugin/myserver.cpp @@ -0,0 +1,157 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "myserver.h" +#include "version.h" +#include +#include + +Connection::Connection(QTcpSocket * s) +{ + socket = s; + + //connect(s, SIGNAL(disconnected()), this, SLOT(deleteLater())); + connect(s, SIGNAL(readyRead()), this, SLOT(readData())); + + sendText(QString("SMPlayer %1").arg(smplayerVersion())); + sendText("Type help for a list of commands"); +} + +Connection::~Connection() { + delete socket; +} + +void Connection::sendText(QString l) { + qDebug("Connection::sendText: '%s'", l.toUtf8().data()); + + socket->write( l.toUtf8() + "\r\n" ); + socket->flush(); +} + +void Connection::readData() { + while (socket->canReadLine()) { + QString l = QString::fromUtf8( socket->readLine() ); + l.remove( QRegExp("[\r\n]") ); + parseLine( l ); + } +} + +void Connection::parseLine(QString str) { + qDebug("Connection::parseLine: '%s'", str.toUtf8().data()); + + QRegExp rx_open("^open (.*)"); + QRegExp rx_open_files("(^open_files|^add_files) (.*)"); + QRegExp rx_function("^(function|f) (.*)"); + + + if (str.toLower() == "hello") { + sendText(QString("Hello, this is SMPlayer %1").arg(smplayerVersion())); + } + else + if (str.toLower() == "help") { + sendText("Available commands:"); + sendText(" help"); + sendText(" quit"); + sendText(" list functions"); + sendText(" function [function_name]"); + sendText(" f [function_name]"); + sendText(" open [file]"); + } + else + if (str.toLower() == "quit") { + sendText("Goodbye"); + socket->disconnectFromHost(); + } + else + if (str.toLower() == "list functions") { + for (int n=0; n < actions_list.count(); n++) { + sendText( actions_list[n] ); + } + } + else + if (rx_open.indexIn(str) > -1) { + QString file = rx_open.cap(1); + qDebug("Connection::parseLine: asked to open '%s'", file.toUtf8().data()); + sendText("OK, file sent to GUI"); + emit receivedOpen(file); + } + else + if ( (str.toLower() == "open_files_start") || + (str.toLower() == "add_files_start") ) + { + files_to_open.clear(); + sendText("OK, send first file"); + } + else + if ( (str.toLower() == "open_files_end") || + (str.toLower() == "add_files_end") ) + { + qDebug("Connection::parseLine: files_to_open:"); + for (int n=0; n < files_to_open.count(); n++) + qDebug("Connection::parseLine: %d: '%s'", n, files_to_open[n].toUtf8().data()); + sendText("OK, sending files to GUI"); + + if (str.toLower() == "open_files_end") + emit receivedOpenFiles(files_to_open); + else + emit receivedAddFiles(files_to_open); + } + else + if (rx_open_files.indexIn(str) > -1) { + QString file = rx_open_files.cap(2); + qDebug("Connection::parseLine: file: '%s'", file.toUtf8().data()); + files_to_open.append(file); + sendText("OK, file received"); + } + else + if (rx_function.indexIn(str) > -1) { + QString function = rx_function.cap(2).toLower(); + qDebug("Connection::parseLine: asked to process function '%s'", function.toUtf8().data()); + sendText("OK, function sent to GUI"); + emit receivedFunction(function); + } + else { + sendText("Unknown command"); + } +} + + +MyServer::MyServer( QObject * parent ) : QTcpServer(parent) +{ + connect(this, SIGNAL(newConnection()), this, SLOT(newConnection_slot())); +} + +bool MyServer::listen( quint16 port ) { + return QTcpServer::listen(QHostAddress::LocalHost, port); +} + +void MyServer::newConnection_slot() { + Connection * c = new Connection( nextPendingConnection() ); + c->setActionsList( actionsList() ); + + connect(c, SIGNAL(receivedOpen(QString)), + this, SIGNAL(receivedOpen(QString))); + connect(c, SIGNAL(receivedOpenFiles(QStringList)), + this, SIGNAL(receivedOpenFiles(QStringList))); + connect(c, SIGNAL(receivedAddFiles(QStringList)), + this, SIGNAL(receivedAddFiles(QStringList))); + connect(c, SIGNAL(receivedFunction(QString)), + this, SIGNAL(receivedFunction(QString))); +} + +#include "moc_myserver.cpp" diff --git a/plugins/smplayer_plugin/myserver.h b/plugins/smplayer_plugin/myserver.h new file mode 100644 index 000000000..4298954fa --- /dev/null +++ b/plugins/smplayer_plugin/myserver.h @@ -0,0 +1,110 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MYSERVER_H_ +#define _MYSERVER_H_ + +#include +#include +#include + +//! Connection holds a connection from MyServer to a client. + +/*! + Connection objects are created by MyServer every time a new + connection is made. + It reads the text sent by the client, parses it, respond, and send + signals to the server to report client requests. + This class is for private use by MyServer. +*/ + +class Connection : public QObject +{ + Q_OBJECT + +public: + Connection(QTcpSocket * s); + ~Connection(); + + void setActionsList(QStringList l) { actions_list = l; }; + QStringList actionsList() { return actions_list; }; + +signals: + void receivedOpen(QString); + void receivedOpenFiles(QStringList); + void receivedAddFiles(QStringList); + void receivedFunction(QString); + +protected slots: + void readData(); + +protected: + void sendText(QString l); + void parseLine(QString str); + +private: + QTcpSocket * socket; + QStringList actions_list; + QStringList files_to_open; +}; + +//! MyServer listens a port and waits for connections from other instances. + +/*! + MyServer will listen the specified port and will send signals + when another instance request something. +*/ + +class MyServer : public QTcpServer +{ + Q_OBJECT + +public: + MyServer( QObject * parent = 0 ); + + //! Tells the server to listen for incoming connections on port \a port. + bool listen( quint16 port ); + + //! Sets the list of actions. + //! The list is printed when the client requests it. + void setActionsList(QStringList l) { actions_list = l; }; + + //! Returns the list of actions. + QStringList actionsList() { return actions_list; }; + +signals: + //! Emitted when the client request to open a new file. + void receivedOpen(QString); + + //! Emitted when the client request to open a list of files. + void receivedOpenFiles(QStringList); + + //! Emitted when the client request to add a list of files to the playlist. + void receivedAddFiles(QStringList); + + //! Emitted when the client request to perform an action. + void receivedFunction(QString); + +protected slots: + void newConnection_slot(); + +private: + QStringList actions_list; +}; + +#endif diff --git a/plugins/smplayer_plugin/myslider.cpp b/plugins/smplayer_plugin/myslider.cpp new file mode 100644 index 000000000..008091e1a --- /dev/null +++ b/plugins/smplayer_plugin/myslider.cpp @@ -0,0 +1,184 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Trolltech ASA + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "myslider.h" + +#include +#include + +#if CODE_FOR_CLICK == 0 +#include +#endif + +#if CODE_FOR_CLICK == 1 +#include +#include +#endif + + +MySlider::MySlider( QWidget * parent ) : QSlider(parent) +{ + setOrientation( Qt::Horizontal ); +} + +MySlider::~MySlider() { +} + +#if CODE_FOR_CLICK == 1 +// Function copied from qslider.cpp +inline int MySlider::pick(const QPoint &pt) const +{ + return orientation() == Qt::Horizontal ? pt.x() : pt.y(); +} + +#if QT_VERSION < 0x040300 +// Function copied from qslider.cpp and modified to make it compile +void MySlider::initStyleOption(QStyleOptionSlider *option) const +{ + if (!option) + return; + + option->initFrom(this); + option->subControls = QStyle::SC_None; + option->activeSubControls = QStyle::SC_None; + option->orientation = orientation(); + option->maximum = maximum(); + option->minimum = minimum(); + option->tickPosition = (QSlider::TickPosition) tickPosition(); + option->tickInterval = tickInterval(); + option->upsideDown = (orientation() == Qt::Horizontal) ? + (invertedAppearance() != (option->direction == Qt::RightToLeft)) + : (!invertedAppearance()); + option->direction = Qt::LeftToRight; // we use the upsideDown option instead + option->sliderPosition = sliderPosition(); + option->sliderValue = value(); + option->singleStep = singleStep(); + option->pageStep = pageStep(); + if (orientation() == Qt::Horizontal) + option->state |= QStyle::State_Horizontal; +} +#endif + +// Function copied from qslider.cpp and modified to make it compile +int MySlider::pixelPosToRangeValue(int pos) const +{ + QStyleOptionSlider opt; + initStyleOption(&opt); + QRect gr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this); + QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); + int sliderMin, sliderMax, sliderLength; + + if (orientation() == Qt::Horizontal) { + sliderLength = sr.width(); + sliderMin = gr.x(); + sliderMax = gr.right() - sliderLength + 1; + } else { + sliderLength = sr.height(); + sliderMin = gr.y(); + sliderMax = gr.bottom() - sliderLength + 1; + } + return QStyle::sliderValueFromPosition(minimum(), maximum(), pos - sliderMin, + sliderMax - sliderMin, opt.upsideDown); +} + +// Based on code from qslider.cpp +void MySlider::mousePressEvent( QMouseEvent * e ) { + if (e->button() == Qt::LeftButton) { + QStyleOptionSlider opt; + initStyleOption(&opt); + const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); + const QPoint center = sliderRect.center() - sliderRect.topLeft(); + // to take half of the slider off for the setSliderPosition call we use the center - topLeft + + if (!sliderRect.contains(e->pos())) { + e->accept(); + + setSliderPosition(pixelPosToRangeValue(pick(e->pos() - center))); + triggerAction(SliderMove); + setRepeatAction(SliderNoAction); + } else { + QSlider::mousePressEvent(e); + } + } else { + QSlider::mousePressEvent(e); + } +} + +#endif // CODE_FOR_CLICK == 1 + + +#if CODE_FOR_CLICK == 2 +void MySlider::mousePressEvent( QMouseEvent * e ) { + // Swaps middle button click with left click + if (e->button() == Qt::LeftButton) { + QMouseEvent ev2(QEvent::MouseButtonRelease, e->pos(), e->globalPos(), Qt::MidButton, Qt::MidButton, e->modifiers()); + QSlider::mousePressEvent(&ev2); + } + else + if (e->button() == Qt::MidButton) { + QMouseEvent ev2(QEvent::MouseButtonRelease, e->pos(), e->globalPos(), Qt::LeftButton, Qt::LeftButton, e->modifiers()); + QSlider::mousePressEvent(&ev2); + } + else { + QSlider::mousePressEvent(e); + } +} +#endif // CODE_FOR_CLICK == 2 + + +#if CODE_FOR_CLICK == 0 +void MySlider::mousePressEvent( QMouseEvent * e ) { + // FIXME: + // The code doesn't work well with right to left layout, + // so it's disabled. + if (qApp->isRightToLeft()) { + QSlider::mousePressEvent(e); + return; + } + + int range = maximum()-minimum(); + int pos = (e->x() * range) / width(); + //qDebug( "width: %d x: %d", width(), e->x()); + //qDebug( "range: %d pos: %d value: %d", range, pos, value()); + + // Calculate how many positions takes the slider handle + int metric = qApp->style()->pixelMetric( QStyle::PM_SliderLength ); + double one_tick_pixels = (double) width() / range; + int slider_handle_positions = (int) (metric / one_tick_pixels); + + /* + qDebug("metric: %d", metric ); + qDebug("one_tick_pixels :%f", one_tick_pixels); + qDebug("width() :%d", width()); + qDebug("slider_handle_positions: %d", slider_handle_positions); + */ + + if (abs(pos - value()) > slider_handle_positions) { + setValue(pos); + emit sliderMoved( pos ); + } else { + QSlider::mousePressEvent(e); + } +} +#endif + +#include "moc_myslider.cpp" + diff --git a/plugins/smplayer_plugin/myslider.h b/plugins/smplayer_plugin/myslider.h new file mode 100644 index 000000000..6f15b046f --- /dev/null +++ b/plugins/smplayer_plugin/myslider.h @@ -0,0 +1,52 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Trolltech ASA + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#ifndef _MYSLIDER_H_ +#define _MYSLIDER_H_ + +#include +#include "config.h" + +#define CODE_FOR_CLICK 1 // 0 = old code, 1 = code copied from QSlider, 2 = button swap + +class QTimer; + +class MySlider : public QSlider +{ + Q_OBJECT + +public: + MySlider( QWidget * parent ); + ~MySlider(); + +protected: + void mousePressEvent ( QMouseEvent * event ); +#if CODE_FOR_CLICK == 1 + inline int pick(const QPoint &pt) const; + int pixelPosToRangeValue(int pos) const; +#if QT_VERSION < 0x040300 + void initStyleOption(QStyleOptionSlider *option) const; +#endif +#endif +}; + +#endif + diff --git a/plugins/smplayer_plugin/mytablewidget.cpp b/plugins/smplayer_plugin/mytablewidget.cpp new file mode 100644 index 000000000..9357266d3 --- /dev/null +++ b/plugins/smplayer_plugin/mytablewidget.cpp @@ -0,0 +1,85 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mytablewidget.h" +#include + +#define BE_VERBOSE 0 + +MyTableWidget::MyTableWidget( QWidget * parent ) : QTableWidget(parent) +{ +} + +MyTableWidget::MyTableWidget( int rows, int columns, QWidget * parent ) + : QTableWidget(rows, columns, parent) +{ +} + +QTableWidgetItem * MyTableWidget::getItem(int row, int column, bool * existed ) { +#if BE_VERBOSE + qDebug("MyTableWidget::getItem: %d, %d", row, column); +#endif + QTableWidgetItem * i = item(row, column); + if (existed != 0) *existed = (i!=0); // Returns if the item already existed or not + if (i != 0) return i; else return createItem(column); +} + +QTableWidgetItem * MyTableWidget::createItem(int /*col*/) { +#if BE_VERBOSE + qDebug("MyTableWidget::createItem"); +#endif + QTableWidgetItem * i = new QTableWidgetItem(); + i->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); + return i; +} + +void MyTableWidget::setText(int row, int column, const QString & text ) { +#if BE_VERBOSE + qDebug("MyTableWidget::setText: %d, %d", row, column); +#endif + bool existed; + QTableWidgetItem * i = getItem(row, column, &existed); + i->setText(text); + if (!existed) setItem(row, column, i); +} + +QString MyTableWidget::text(int row, int column) { +#if BE_VERBOSE + qDebug("MyTableWidget::text: %d, %d", row, column); +#endif + return getItem(row, column)->text(); +} + +void MyTableWidget::setIcon(int row, int column, const QIcon & icon ) { +#if BE_VERBOSE + qDebug("MyTableWidget::setIcon %d, %d", row, column); +#endif + bool existed; + QTableWidgetItem * i = getItem(row, column, &existed); + i->setIcon(icon); + if (!existed) setItem(row, column, i); +} + +QIcon MyTableWidget::icon(int row, int column) { + return getItem(row, column)->icon(); +} + +bool MyTableWidget::isSelected(int row, int column) { + return getItem(row, column)->isSelected(); +} + diff --git a/plugins/smplayer_plugin/mytablewidget.h b/plugins/smplayer_plugin/mytablewidget.h new file mode 100644 index 000000000..71ed65420 --- /dev/null +++ b/plugins/smplayer_plugin/mytablewidget.h @@ -0,0 +1,48 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _MYTABLEWIDGET_H_ +#define _MYTABLEWIDGET_H_ + +#include +#include + +class QTableWidgetItem; + +class MyTableWidget : public QTableWidget +{ +public: + MyTableWidget ( QWidget * parent = 0 ); + MyTableWidget ( int rows, int columns, QWidget * parent = 0 ); + + QTableWidgetItem * getItem(int row, int column, bool * existed = 0 ); + + void setText(int row, int column, const QString & text ); + QString text(int row, int column); + + void setIcon(int row, int column, const QIcon & icon ); + QIcon icon(int row, int column); + + bool isSelected(int row, int column); + +protected: + virtual QTableWidgetItem * createItem(int col); + +}; + +#endif diff --git a/plugins/smplayer_plugin/paths.cpp b/plugins/smplayer_plugin/paths.cpp new file mode 100644 index 000000000..c7008aac3 --- /dev/null +++ b/plugins/smplayer_plugin/paths.cpp @@ -0,0 +1,157 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "paths.h" +#include +#include +#include +#include +#include + +#ifndef Q_OS_WIN +#include +#endif + +QString Paths::app_path; +QString Paths::config_path; + +void Paths::setAppPath(QString path) { + app_path = path; +} + +QString Paths::appPath() { + return app_path; +} + +QString Paths::dataPath() { +#ifdef DATA_PATH + QString path = QString(DATA_PATH); + if (!path.isEmpty()) + return path; + else + return appPath(); +#else + return appPath(); +#endif +} + +QString Paths::translationPath() { +#ifdef TRANSLATION_PATH + QString path = QString(TRANSLATION_PATH); + if (!path.isEmpty()) + return path; + else + return appPath() + "/translations"; +#else + return appPath() + "/translations"; +#endif +} + +QString Paths::docPath() { +#ifdef DOC_PATH + QString path = QString(DOC_PATH); + if (!path.isEmpty()) + return path; + else + return appPath() + "/docs"; +#else + return appPath() + "/docs"; +#endif +} + +QString Paths::themesPath() { +#ifdef THEMES_PATH + QString path = QString(THEMES_PATH); + if (!path.isEmpty()) + return path; + else + return appPath() + "/themes"; +#else + return appPath() + "/themes"; +#endif +} + +QString Paths::shortcutsPath() { +#ifdef SHORTCUTS_PATH + QString path = QString(SHORTCUTS_PATH); + if (!path.isEmpty()) + return path; + else + return appPath() + "/shortcuts"; +#else + return appPath() + "/shortcuts"; +#endif +} + +QString Paths::qtTranslationPath() { + return QLibraryInfo::location(QLibraryInfo::TranslationsPath); +} + +QString Paths::doc(QString file, QString locale) { + if (locale.isEmpty()) { + locale = QLocale::system().name(); + } + + QString f = docPath() + "/" + locale + "/" + file; + qDebug("Helper:doc: checking '%s'", f.toUtf8().data()); + if (QFile::exists(f)) return f; + + if (locale.indexOf(QRegExp("_[A-Z]+")) != -1) { + locale.replace(QRegExp("_[A-Z]+"), ""); + f = docPath() + "/" + locale + "/" + file; + qDebug("Helper:doc: checking '%s'", f.toUtf8().data()); + if (QFile::exists(f)) return f; + } + + f = docPath() + "/en/" + file; + return f; +} + +void Paths::setConfigPath(QString path) { + config_path = path; +} + +QString Paths::configPath() { + if (!config_path.isEmpty()) { + return config_path; + } else { +#ifdef PORTABLE_APP + return appPath(); +#else + #ifndef Q_OS_WIN + const char * XDG_CONFIG_HOME = getenv("XDG_CONFIG_HOME"); + if (XDG_CONFIG_HOME!=NULL) { + qDebug("Paths::configPath: XDG_CONFIG_HOME: %s", XDG_CONFIG_HOME); + return QString(XDG_CONFIG_HOME) + "/smplayer"; + } + else + return QDir::homePath() + "/.config/smplayer"; + #else + return QDir::homePath() + "/.smplayer"; + #endif +#endif + } +} + +QString Paths::iniPath() { + return configPath(); +} + +QString Paths::subtitleStyleFile() { + return configPath() + "/styles.ass"; +} diff --git a/plugins/smplayer_plugin/paths.h b/plugins/smplayer_plugin/paths.h new file mode 100644 index 000000000..41322ac6b --- /dev/null +++ b/plugins/smplayer_plugin/paths.h @@ -0,0 +1,55 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PATHS_H_ +#define _PATHS_H_ + +#include + +class Paths { + +public: + + static void setAppPath(QString path); + static QString appPath(); + + static QString dataPath(); + static QString translationPath(); + static QString docPath(); + static QString themesPath(); + static QString shortcutsPath(); + static QString qtTranslationPath(); + static QString doc(QString file, QString locale = QString::null); + + //! Forces to use a different path for the config files + static void setConfigPath(QString path); + + //! Return the path where smplayer should save its config files + static QString configPath(); + + //! Obsolete. Just returns configPath() + static QString iniPath(); + + static QString subtitleStyleFile(); + +private: + static QString app_path; + static QString config_path; +}; + +#endif diff --git a/plugins/smplayer_plugin/playlist.cpp b/plugins/smplayer_plugin/playlist.cpp new file mode 100644 index 000000000..9022aca0f --- /dev/null +++ b/plugins/smplayer_plugin/playlist.cpp @@ -0,0 +1,1326 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "playlist.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mytablewidget.h" +#include "myaction.h" +#include "filedialog.h" +#include "helper.h" +#include "images.h" +#include "preferences.h" +#include "version.h" +#include "global.h" +#include "core.h" +#include "extensions.h" +#include "guiconfig.h" +#include "playlistpreferences.h" + +#include + +#if USE_INFOPROVIDER +#include "infoprovider.h" +#endif + +#define DRAG_ITEMS 0 + +#define COL_PLAY 0 +#define COL_NAME 1 +#define COL_TIME 2 + +using namespace Global; + + +Playlist::Playlist( Core *c, QWidget * parent, Qt::WindowFlags f) + : QWidget(parent,f) +{ + save_playlist_in_config = true; + recursive_add_directory = false; +#ifdef Q_OS_WIN + automatically_get_info = false; +#else + automatically_get_info = true; +#endif + play_files_from_start = true; + + modified = false; + + core = c; + playlist_path = ""; + latest_dir = ""; + + createTable(); + createActions(); + createToolbar(); + + connect( core, SIGNAL(mediaFinished()), this, SLOT(playNext()), Qt::QueuedConnection ); + connect( core, SIGNAL(mediaLoaded()), this, SLOT(getMediaInfo()) ); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget( listView ); + layout->addWidget( toolbar ); + setLayout(layout); + + clear(); + + retranslateStrings(); + +#if !DOCK_PLAYLIST + setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding ); + adjustSize(); +#else + //setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Expanding ); + //setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); + setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); +#endif + + setAcceptDrops(true); + setAttribute(Qt::WA_NoMousePropagation); + + // Random seed + QTime t; + t.start(); + srand( t.hour() * 3600 + t.minute() * 60 + t.second() ); + + loadSettings(); + + // Save config every 5 minutes. + save_timer = new QTimer(this); + connect( save_timer, SIGNAL(timeout()), this, SLOT(maybeSaveSettings()) ); + save_timer->start( 5 * 60000 ); +} + +Playlist::~Playlist() { + saveSettings(); +} + +void Playlist::setModified(bool mod) { + qDebug("Playlist::setModified: %d", mod); + + modified = mod; + emit modifiedChanged(modified); +} + +void Playlist::createTable() { + listView = new MyTableWidget( 0, COL_TIME + 1, this); + listView->setObjectName("playlist_table"); + listView->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); + listView->setSelectionBehavior(QAbstractItemView::SelectRows); + listView->setSelectionMode(QAbstractItemView::ExtendedSelection); + listView->setContextMenuPolicy( Qt::CustomContextMenu ); + listView->setShowGrid(false); + listView->setSortingEnabled(false); + //listView->setAlternatingRowColors(true); + listView->horizontalHeader()->setResizeMode(QHeaderView::Interactive); + listView->horizontalHeader()->setResizeMode(COL_NAME, QHeaderView::Stretch); + /* + listView->horizontalHeader()->setResizeMode(COL_TIME, QHeaderView::ResizeToContents); + listView->horizontalHeader()->setResizeMode(COL_PLAY, QHeaderView::ResizeToContents); + */ + listView->setIconSize( Images::icon("ok_small").size() ); + +#if DRAG_ITEMS + listView->setSelectionMode(QAbstractItemView::SingleSelection); + listView->setDragEnabled(true); + listView->setAcceptDrops(true); + listView->setDropIndicatorShown(true); + listView->setDragDropMode(QAbstractItemView::InternalMove); +#endif + + connect( listView, SIGNAL(cellActivated(int,int)), + this, SLOT(itemDoubleClicked(int)) ); +} + +void Playlist::createActions() { + openAct = new MyAction(this, "pl_open", false); + connect( openAct, SIGNAL(triggered()), this, SLOT(load()) ); + + saveAct = new MyAction(this, "pl_save", false); + connect( saveAct, SIGNAL(triggered()), this, SLOT(save()) ); + + playAct = new MyAction(this, "pl_play", false); + connect( playAct, SIGNAL(triggered()), this, SLOT(playCurrent()) ); + + nextAct = new MyAction(Qt::Key_N /*Qt::Key_Greater*/, this, "pl_next", false); + connect( nextAct, SIGNAL(triggered()), this, SLOT(playNext()) ); + + prevAct = new MyAction(Qt::Key_P /*Qt::Key_Less*/, this, "pl_prev", false); + connect( prevAct, SIGNAL(triggered()), this, SLOT(playPrev()) ); + + moveUpAct = new MyAction(this, "pl_move_up", false); + connect( moveUpAct, SIGNAL(triggered()), this, SLOT(upItem()) ); + + moveDownAct = new MyAction(this, "pl_move_down", false); + connect( moveDownAct, SIGNAL(triggered()), this, SLOT(downItem()) ); + + repeatAct = new MyAction(this, "pl_repeat", false); + repeatAct->setCheckable(true); + + shuffleAct = new MyAction(this, "pl_shuffle", false); + shuffleAct->setCheckable(true); + + preferencesAct = new MyAction(this, "pl_preferences", false); + connect( preferencesAct, SIGNAL(triggered()), this, SLOT(editPreferences()) ); + + // Add actions + addCurrentAct = new MyAction(this, "pl_add_current", false); + connect( addCurrentAct, SIGNAL(triggered()), this, SLOT(addCurrentFile()) ); + + addFilesAct = new MyAction(this, "pl_add_files", false); + connect( addFilesAct, SIGNAL(triggered()), this, SLOT(addFiles()) ); + + addDirectoryAct = new MyAction(this, "pl_add_directory", false); + connect( addDirectoryAct, SIGNAL(triggered()), this, SLOT(addDirectory()) ); + + // Remove actions + removeSelectedAct = new MyAction(this, "pl_remove_selected", false); + connect( removeSelectedAct, SIGNAL(triggered()), this, SLOT(removeSelected()) ); + + removeAllAct = new MyAction(this, "pl_remove_all", false); + connect( removeAllAct, SIGNAL(triggered()), this, SLOT(removeAll()) ); + + // Edit + editAct = new MyAction(this, "pl_edit", false); + connect( editAct, SIGNAL(triggered()), this, SLOT(editCurrentItem()) ); +} + +void Playlist::createToolbar() { + toolbar = new QToolBar(this); + toolbar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); + + toolbar->addAction(openAct); + toolbar->addAction(saveAct);; + toolbar->addSeparator(); + + add_menu = new QMenu( this ); + add_menu->addAction(addCurrentAct); + add_menu->addAction(addFilesAct ); + add_menu->addAction(addDirectoryAct); + + add_button = new QToolButton( this ); + add_button->setMenu( add_menu ); + add_button->setPopupMode(QToolButton::InstantPopup); + + remove_menu = new QMenu( this ); + remove_menu->addAction(removeSelectedAct); + remove_menu->addAction(removeAllAct); + + remove_button = new QToolButton( this ); + remove_button->setMenu( remove_menu ); + remove_button->setPopupMode(QToolButton::InstantPopup); + + toolbar->addWidget(add_button); + toolbar->addWidget(remove_button); + + toolbar->addSeparator(); + toolbar->addAction(playAct); + toolbar->addSeparator(); + toolbar->addAction(prevAct); + toolbar->addAction(nextAct); + toolbar->addSeparator(); + toolbar->addAction(repeatAct); + toolbar->addAction(shuffleAct); + toolbar->addSeparator(); + toolbar->addAction(moveUpAct); + toolbar->addAction(moveDownAct); + toolbar->addSeparator(); + toolbar->addAction(preferencesAct); + + // Popup menu + popup = new QMenu(this); + popup->addAction(playAct); + popup->addAction(removeSelectedAct); + popup->addAction(editAct); + + connect( listView, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(showPopup(const QPoint &)) ); +} + +void Playlist::retranslateStrings() { + listView->setHorizontalHeaderLabels( QStringList() << " " << + tr("Name") << tr("Length") ); + + openAct->change( Images::icon("open"), tr("&Load") ); + saveAct->change( Images::icon("save"), tr("&Save") ); + + playAct->change( tr("&Play") ); + + nextAct->change( tr("&Next") ); + prevAct->change( tr("Pre&vious") ); + + if (qApp->isLeftToRight()) { + playAct->setIcon( Images::icon("play") ); + nextAct->setIcon( Images::icon("next") ); + prevAct->setIcon( Images::icon("previous") ); + } else { + playAct->setIcon( Images::flippedIcon("play") ); + nextAct->setIcon( Images::flippedIcon("next") ); + prevAct->setIcon( Images::flippedIcon("previous") ); + } + + moveUpAct->change( Images::icon("up"), tr("Move &up") ); + moveDownAct->change( Images::icon("down"), tr("Move &down") ); + + repeatAct->change( Images::icon("repeat"), tr("&Repeat") ); + shuffleAct->change( Images::icon("shuffle"), tr("S&huffle") ); + + preferencesAct->change( Images::icon("prefs"), tr("Preferences") ); + + // Add actions + addCurrentAct->change( tr("Add ¤t file") ); + addFilesAct->change( tr("Add &file(s)") ); + addDirectoryAct->change( tr("Add &directory") ); + + // Remove actions + removeSelectedAct->change( tr("Remove &selected") ); + removeAllAct->change( tr("Remove &all") ); + + // Edit + editAct->change( tr("&Edit") ); + + // Tool buttons + add_button->setIcon( Images::icon("plus") ); + add_button->setToolTip( tr("Add...") ); + remove_button->setIcon( Images::icon("minus") ); + remove_button->setToolTip( tr("Remove...") ); + + // Icon + setWindowIcon( Images::icon("logo", 64) ); + setWindowTitle( tr( "SMPlayer - Playlist" ) ); +} + +void Playlist::list() { + qDebug("Playlist::list"); + + PlaylistItemList::iterator it; + for ( it = pl.begin(); it != pl.end(); ++it ) { + qDebug( "filename: '%s', name: '%s' duration: %f", + (*it).filename().toUtf8().data(), (*it).name().toUtf8().data(), + (*it).duration() ); + } +} + +void Playlist::updateView() { + qDebug("Playlist::updateView"); + + listView->setRowCount( pl.count() ); + + //QString number; + QString name; + QString time; + + for (int n=0; n < pl.count(); n++) { + name = pl[n].name(); + if (name.isEmpty()) name = pl[n].filename(); + time = Helper::formatTime( (int) pl[n].duration() ); + + //listView->setText(n, COL_POS, number); + qDebug("Playlist::updateView: name: '%s'", name.toUtf8().data()); + listView->setText(n, COL_NAME, name); + listView->setText(n, COL_TIME, time); + + if (pl[n].played()) { + listView->setIcon(n, COL_PLAY, Images::icon("ok_small") ); + } else { + listView->setIcon(n, COL_PLAY, QPixmap() ); + } + } + //listView->resizeColumnsToContents(); + listView->resizeColumnToContents(COL_PLAY); + listView->resizeColumnToContents(COL_TIME); + + setCurrentItem(current_item); + + //adjustSize(); +} + +void Playlist::setCurrentItem(int current) { + QIcon play_icon; + if (qApp->isLeftToRight()) { + play_icon = Images::icon("play"); + } else { + play_icon = Images::flippedIcon("play"); + } + + int old_current = current_item; + current_item = current; + + if ((current_item > -1) && (current_item < pl.count())) { + pl[current_item].setPlayed(TRUE); + } + + if ( (old_current >= 0) && (old_current < listView->rowCount()) ) { + listView->setIcon(old_current, COL_PLAY, QPixmap() ); + } + + if ( (current_item >= 0) && (current_item < listView->rowCount()) ) { + listView->setIcon(current_item, COL_PLAY, play_icon ); + } + //if (current_item >= 0) listView->selectRow(current_item); + if (current_item >= 0) { + listView->clearSelection(); + listView->setCurrentCell( current_item, 0); + } +} + +void Playlist::clear() { + pl.clear(); + + listView->clearContents(); + listView->setRowCount(0); + + setCurrentItem(0); + + setModified( false ); +} + +int Playlist::count() { + return pl.count(); +} + +bool Playlist::isEmpty() { + return pl.isEmpty(); +} + +void Playlist::addItem(QString filename, QString name, double duration) { + qDebug("Playlist::addItem: '%s'", filename.toUtf8().data()); + + #ifdef Q_OS_WIN + filename = Helper::changeSlashes(filename); + #endif + + // Test if already is in the list + bool exists = FALSE; + PlaylistItemList::iterator it; + for ( it = pl.begin(); it != pl.end(); ++it ) { + if ( (*it).filename() == filename ) { + exists = TRUE; + break; + } + } + + if (!exists) { + if (name.isEmpty()) { + QFileInfo fi(filename); + if (fi.exists()) { + // Local file + name = fi.fileName(); //fi.baseName(TRUE); + } else { + // Stream + name = filename; + } + } + pl.append( PlaylistItem(filename, name, duration) ); + //setModified( true ); // Better set the modified on a higher level + } else { + qDebug(" Not added. File already in the list"); + } +} + +void Playlist::load_m3u(QString file) { + qDebug("Playlist::load_m3u"); + + bool utf8 = (QFileInfo(file).suffix().toLower() == "m3u8"); + + QRegExp m3u_id("^#EXTM3U|^#M3U"); + QRegExp info("^#EXTINF:(.*),(.*)"); + + QFile f( file ); + if ( f.open( QIODevice::ReadOnly ) ) { + playlist_path = QFileInfo(file).path(); + + clear(); + QString filename=""; + QString name=""; + double duration=0; + + QTextStream stream( &f ); + + if (utf8) + stream.setCodec("UTF-8"); + else + stream.setCodec(QTextCodec::codecForLocale()); + + QString line; + while ( !stream.atEnd() ) { + line = stream.readLine(); // line of text excluding '\n' + qDebug( " * line: '%s'", line.toUtf8().data() ); + if (m3u_id.indexIn(line)!=-1) { + //#EXTM3U + // Ignore line + } + else + if (info.indexIn(line)!=-1) { + duration = info.cap(1).toDouble(); + name = info.cap(2); + qDebug(" * name: '%s', duration: %f", name.toUtf8().data(), duration ); + } + else + if (line.startsWith("#")) { + // Comment + // Ignore + } else { + filename = line; + QFileInfo fi(filename); + if (fi.exists()) { + filename = fi.absoluteFilePath(); + } + if (!fi.exists()) { + if (QFileInfo( playlist_path + "/" + filename).exists() ) { + filename = playlist_path + "/" + filename; + } + } + addItem( filename, name, duration ); + name=""; + duration = 0; + } + } + f.close(); + list(); + updateView(); + + setModified( false ); + + startPlay(); + } +} + +void Playlist::load_pls(QString file) { + qDebug("Playlist::load_pls"); + + playlist_path = QFileInfo(file).path(); + + QSettings set(file, QSettings::IniFormat); + set.beginGroup( "playlist"); + + if (set.status() == QSettings::NoError) { + clear(); + QString filename; + QString name; + double duration; + + int num_items = set.value("NumberOfEntries", 0).toInt(); + + for (int n=0; n < num_items; n++) { + filename = set.value("File"+QString::number(n+1), "").toString(); + name = set.value("Title"+QString::number(n+1), "").toString(); + duration = (double) set.value("Length"+QString::number(n+1), 0).toInt(); + + QFileInfo fi(filename); + if (fi.exists()) { + filename = fi.absoluteFilePath(); + } + if (!fi.exists()) { + if (QFileInfo( playlist_path + "/" + filename).exists() ) { + filename = playlist_path + "/" + filename; + } + } + addItem( filename, name, duration ); + } + } + + set.endGroup(); + + list(); + updateView(); + + setModified( false ); + + if (set.status() == QSettings::NoError) startPlay(); +} + +bool Playlist::save_m3u(QString file) { + qDebug("Playlist::save_m3u: '%s'", file.toUtf8().data()); + + QString dir_path = QFileInfo(file).path(); + if (!dir_path.endsWith("/")) dir_path += "/"; + + #ifdef Q_OS_WIN + dir_path = Helper::changeSlashes(dir_path); + #endif + + qDebug(" * dirPath: '%s'", dir_path.toUtf8().data()); + + bool utf8 = (QFileInfo(file).suffix().toLower() == "m3u8"); + + QFile f( file ); + if ( f.open( QIODevice::WriteOnly ) ) { + QTextStream stream( &f ); + + if (utf8) + stream.setCodec("UTF-8"); + else + stream.setCodec(QTextCodec::codecForLocale()); + + QString filename; + + stream << "#EXTM3U" << "\n"; + stream << "# Playlist created by SMPlayer " << smplayerVersion() << " \n"; + + PlaylistItemList::iterator it; + for ( it = pl.begin(); it != pl.end(); ++it ) { + filename = (*it).filename(); + #ifdef Q_OS_WIN + filename = Helper::changeSlashes(filename); + #endif + stream << "#EXTINF:"; + stream << (*it).duration() << ","; + stream << (*it).name() << "\n"; + // Try to save the filename as relative instead of absolute + if (filename.startsWith( dir_path )) { + filename = filename.mid( dir_path.length() ); + } + stream << filename << "\n"; + } + f.close(); + + setModified( false ); + return true; + } else { + return false; + } +} + + +bool Playlist::save_pls(QString file) { + qDebug("Playlist::save_pls: '%s'", file.toUtf8().data()); + + QString dir_path = QFileInfo(file).path(); + if (!dir_path.endsWith("/")) dir_path += "/"; + + #ifdef Q_OS_WIN + dir_path = Helper::changeSlashes(dir_path); + #endif + + qDebug(" * dirPath: '%s'", dir_path.toUtf8().data()); + + QSettings set(file, QSettings::IniFormat); + set.beginGroup( "playlist"); + + QString filename; + + PlaylistItemList::iterator it; + for ( int n=0; n < pl.count(); n++ ) { + filename = pl[n].filename(); + #ifdef Q_OS_WIN + filename = Helper::changeSlashes(filename); + #endif + + // Try to save the filename as relative instead of absolute + if (filename.startsWith( dir_path )) { + filename = filename.mid( dir_path.length() ); + } + + set.setValue("File"+QString::number(n+1), filename); + set.setValue("Title"+QString::number(n+1), pl[n].name()); + set.setValue("Length"+QString::number(n+1), (int) pl[n].duration()); + } + + set.setValue("NumberOfEntries", pl.count()); + set.setValue("Version", 2); + + set.endGroup(); + + set.sync(); + + bool ok = (set.status() == QSettings::NoError); + if (ok) setModified( false ); + + return ok; +} + + +void Playlist::load() { + if (maybeSave()) { + Extensions e; + QString s = MyFileDialog::getOpenFileName( + this, tr("Choose a file"), + lastDir(), + tr("Playlists") + e.playlist().forFilter()); + + if (!s.isEmpty()) { + latest_dir = QFileInfo(s).absolutePath(); + + if (QFileInfo(s).suffix().toLower() == "pls") + load_pls(s); + else + load_m3u(s); + } + } +} + +bool Playlist::save() { + Extensions e; + QString s = MyFileDialog::getSaveFileName( + this, tr("Choose a filename"), + lastDir(), + tr("Playlists") + e.playlist().forFilter()); + + if (!s.isEmpty()) { + // If filename has no extension, add it + if (QFileInfo(s).suffix().isEmpty()) { + s = s + ".m3u"; + } + if (QFileInfo(s).exists()) { + int res = QMessageBox::question( this, + tr("Confirm overwrite?"), + tr("The file %1 already exists.\n" + "Do you want to overwrite?").arg(s), + QMessageBox::Yes, + QMessageBox::No, + QMessageBox::NoButton); + if (res == QMessageBox::No ) { + return false; + } + } + latest_dir = QFileInfo(s).absolutePath(); + + if (QFileInfo(s).suffix().toLower() == "pls") + return save_pls(s); + else + return save_m3u(s); + + } else { + return false; + } +} + +bool Playlist::maybeSave() { + if (!isModified()) return true; + + int res = QMessageBox::question( this, + tr("Playlist modified"), + tr("There are unsaved changes, do you want to save the playlist?"), + QMessageBox::Yes, + QMessageBox::No, + QMessageBox::Cancel); + + switch (res) { + case QMessageBox::No : return true; // Discard changes + case QMessageBox::Cancel : return false; // Cancel operation + default : return save(); + } +} + +void Playlist::playCurrent() { + int current = listView->currentRow(); + if (current > -1) { + playItem(current); + } +} + +void Playlist::itemDoubleClicked(int row) { + qDebug("Playlist::itemDoubleClicked: row: %d", row ); + playItem(row); +} + +void Playlist::showPopup(const QPoint & pos) { + qDebug("Playlist::showPopup: x: %d y: %d", pos.x(), pos.y() ); + + if (!popup->isVisible()) { + popup->move( listView->viewport()->mapToGlobal(pos) ); + popup->show(); + } +} + +void Playlist::startPlay() { + // Start to play + if ( shuffleAct->isChecked() ) + playItem( chooseRandomItem() ); + else + playItem(0); +} + +void Playlist::playItem( int n ) { + qDebug("Playlist::playItem: %d (count:%d)", n, pl.count()); + + if ( (n >= pl.count()) || (n < 0) ) { + qDebug("Playlist::playItem: out of range"); + emit playlistEnded(); + return; + } + + qDebug(" playlist_path: '%s'", playlist_path.toUtf8().data() ); + + QString filename = pl[n].filename(); + QString filename_with_path = playlist_path + "/" + filename; + + if (!filename.isEmpty()) { + //pl[n].setPlayed(TRUE); + setCurrentItem(n); + if (play_files_from_start) + core->open(filename, 0); + else + core->open(filename); + } + +} + +void Playlist::playNext() { + qDebug("Playlist::playNext"); + + if (shuffleAct->isChecked()) { + // Shuffle + int chosen_item = chooseRandomItem(); + if (chosen_item == -1) { + clearPlayedTag(); + if (repeatAct->isChecked()) chosen_item = chooseRandomItem(); + } + playItem( chosen_item ); + } else { + bool finished_list = (current_item+1 >= pl.count()); + if (finished_list) clearPlayedTag(); + + if ( (repeatAct->isChecked()) && (finished_list) ) { + playItem(0); + } else { + playItem( current_item+1 ); + } + } +} + +void Playlist::playPrev() { + qDebug("Playlist::playPrev"); + if (current_item > 0) { + playItem( current_item-1 ); + } else { + if (pl.count() > 1) playItem( pl.count() -1 ); + } +} + +void Playlist::getMediaInfo() { + qDebug("Playlist:: getMediaInfo"); + + QString filename = core->mdat.filename; + double duration = core->mdat.duration; + QString name = core->mdat.clip_name; + QString artist = core->mdat.clip_artist; + + #ifdef Q_OS_WIN + filename = Helper::changeSlashes(filename); + #endif + + if (name.isEmpty()) { + QFileInfo fi(filename); + if (fi.exists()) { + // Local file + name = fi.fileName(); + } else { + // Stream + name = filename; + } + } + if (!artist.isEmpty()) name = artist + " - " + name; + + int pos=0; + PlaylistItemList::iterator it; + for ( it = pl.begin(); it != pl.end(); ++it ) { + if ( (*it).filename() == filename ) { + if ((*it).duration()<1) { + if (!name.isEmpty()) { + (*it).setName(name); + } + (*it).setDuration(duration); + //setModified( true ); + } + else + // Edited name (sets duration to 1) + if ((*it).duration()==1) { + (*it).setDuration(duration); + //setModified( true ); + } + setCurrentItem(pos); + } + pos++; + } + updateView(); +} + +// Add current file to playlist +void Playlist::addCurrentFile() { + qDebug("Playlist::addCurrentFile"); + if (!core->mdat.filename.isEmpty()) { + addItem( core->mdat.filename, "", 0 ); + getMediaInfo(); + } +} + +void Playlist::addFiles() { + QStringList files = MyFileDialog::getOpenFileNames( + this, tr("Select one or more files to open"), + lastDir(), + tr("All files") +" (*.*)" ); + + if (files.count()!=0) addFiles(files); +} + +void Playlist::addFiles(QStringList files, AutoGetInfo auto_get_info) { + qDebug("Playlist::addFiles"); + +#if USE_INFOPROVIDER + bool get_info = (auto_get_info == GetInfo); + if (auto_get_info == UserDefined) { + get_info = automatically_get_info; + } + + MediaData data; + setCursor(Qt::WaitCursor); +#endif + + QStringList::Iterator it = files.begin(); + while( it != files.end() ) { +#if USE_INFOPROVIDER + if ( (get_info) && (QFile::exists((*it))) ) { + data = InfoProvider::getInfo( (*it) ); + addItem( (*it), data.displayName(), data.duration ); + //updateView(); + //qApp->processEvents(); + } else { + addItem( (*it), "", 0 ); + } +#else + addItem( (*it), "", 0 ); +#endif + + if (QFile::exists(*it)) { + latest_dir = QFileInfo((*it)).absolutePath(); + } + + ++it; + } +#if USE_INFOPROVIDER + unsetCursor(); +#endif + updateView(); + + qDebug( "Playlist::addFiles: latest_dir: '%s'", latest_dir.toUtf8().constData() ); +} + +void Playlist::addFile(QString file, AutoGetInfo auto_get_info) { + addFiles( QStringList() << file, auto_get_info ); +} + +void Playlist::addDirectory() { + QString s = MyFileDialog::getExistingDirectory( + this, tr("Choose a directory"), + lastDir() ); + + if (!s.isEmpty()) { + addDirectory(s); + latest_dir = s; + } +} + +void Playlist::addOneDirectory(QString dir) { + QStringList filelist; + + Extensions e; + QRegExp rx_ext(e.multimedia().forRegExp()); + rx_ext.setCaseSensitivity(Qt::CaseInsensitive); + + QStringList dir_list = QDir(dir).entryList(); + + QString filename; + QStringList::Iterator it = dir_list.begin(); + while( it != dir_list.end() ) { + filename = dir; + if (filename.right(1)!="/") filename += "/"; + filename += (*it); + QFileInfo fi(filename); + if (!fi.isDir()) { + if (rx_ext.indexIn(fi.suffix()) > -1) { + filelist << filename; + } + } + ++it; + } + addFiles(filelist); +} + +void Playlist::addDirectory(QString dir) { + addOneDirectory(dir); + + if (recursive_add_directory) { + QFileInfoList dir_list = QDir(dir).entryInfoList(QStringList() << "*", QDir::AllDirs | QDir::NoDotAndDotDot); + for (int n=0; n < dir_list.count(); n++) { + if (dir_list[n].isDir()) { + qDebug("Playlist::addDirectory: adding directory: %s", dir_list[n].filePath().toUtf8().data()); + addDirectory(dir_list[n].filePath()); + } + } + } +} + +// Remove selected items +void Playlist::removeSelected() { + qDebug("Playlist::removeSelected"); + + int first_selected = -1; + int number_previous_item = 0; + + for (int n=0; n < listView->rowCount(); n++) { + if (listView->isSelected(n, 0)) { + qDebug(" row %d selected", n); + pl[n].setMarkForDeletion(TRUE); + number_previous_item++; + if (first_selected == -1) first_selected = n; + } + } + + PlaylistItemList::iterator it; + for ( it = pl.begin(); it != pl.end(); ++it ) { + if ( (*it).markedForDeletion() ) { + qDebug("Remove '%s'", (*it).filename().toUtf8().data()); + it = pl.erase(it); + it--; + setModified( true ); + } + } + + + if (first_selected < current_item) { + current_item -= number_previous_item; + } + + if (isEmpty()) setModified(false); + updateView(); + + if (first_selected >= listView->rowCount()) + first_selected = listView->rowCount() - 1; + + if ( ( first_selected > -1) && ( first_selected < listView->rowCount() ) ) { + listView->clearSelection(); + listView->setCurrentCell( first_selected, 0); + //listView->selectRow( first_selected ); + } +} + +void Playlist::removeAll() { + /* + pl.clear(); + updateView(); + setModified( false ); + */ + clear(); +} + +void Playlist::clearPlayedTag() { + PlaylistItemList::iterator it; + for ( it = pl.begin(); it != pl.end(); ++it ) { + (*it).setPlayed(FALSE); + } + updateView(); +} + +int Playlist::chooseRandomItem() { + qDebug( "Playlist::chooseRandomItem"); + QList fi; //List of not played items (free items) + + int n=0; + PlaylistItemList::iterator it; + for ( it = pl.begin(); it != pl.end(); ++it ) { + if (! (*it).played() ) fi.append(n); + n++; + } + + qDebug(" * free items: %d", fi.count() ); + + if (fi.count()==0) return -1; // none free + + qDebug(" * items: "); + for (int i=0; i < fi.count(); i++) { + qDebug(" * item: %d", fi[i]); + } + + int selected = (int) ((double) fi.count() * rand()/(RAND_MAX+1.0)); + qDebug(" * selected item: %d (%d)", selected, fi[selected]); + return fi[selected]; +} + +void Playlist::swapItems(int item1, int item2 ) { + PlaylistItem it1 = pl[item1]; + pl[item1] = pl[item2]; + pl[item2] = it1; + setModified( true ); +} + + +void Playlist::upItem() { + qDebug("Playlist::upItem"); + + int current = listView->currentRow(); + qDebug(" currentRow: %d", current ); + + if (current >= 1) { + swapItems( current, current-1 ); + if (current_item == (current-1)) current_item = current; + else + if (current_item == current) current_item = current-1; + updateView(); + listView->clearSelection(); + listView->setCurrentCell( current-1, 0); + } +} + +void Playlist::downItem() { + qDebug("Playlist::downItem"); + + int current = listView->currentRow(); + qDebug(" currentRow: %d", current ); + + if ( (current > -1) && (current < (pl.count()-1)) ) { + swapItems( current, current+1 ); + if (current_item == (current+1)) current_item = current; + else + if (current_item == current) current_item = current+1; + updateView(); + listView->clearSelection(); + listView->setCurrentCell( current+1, 0); + } +} + +void Playlist::editCurrentItem() { + int current = listView->currentRow(); + if (current > -1) editItem(current); +} + +void Playlist::editItem(int item) { + QString current_name = pl[item].name(); + if (current_name.isEmpty()) current_name = pl[item].filename(); + + bool ok; + QString text = QInputDialog::getText( this, + tr("Edit name"), + tr("Type the name that will be displayed in the playlist for this file:"), + QLineEdit::Normal, + current_name, &ok ); + if ( ok && !text.isEmpty() ) { + // user entered something and pressed OK + pl[item].setName(text); + + // If duration == 0 the name will be overwritten! + if (pl[item].duration()<1) pl[item].setDuration(1); + updateView(); + + setModified( true ); + } +} + +void Playlist::editPreferences() { + PlaylistPreferences d(this); + + d.setDirectoryRecursion(recursive_add_directory); + d.setAutoGetInfo(automatically_get_info); + d.setSavePlaylistOnExit(save_playlist_in_config); + d.setPlayFilesFromStart(play_files_from_start); + + if (d.exec() == QDialog::Accepted) { + recursive_add_directory = d.directoryRecursion(); + automatically_get_info = d.autoGetInfo(); + save_playlist_in_config = d.savePlaylistOnExit(); + play_files_from_start = d.playFilesFromStart(); + } +} + +// Drag&drop +void Playlist::dragEnterEvent( QDragEnterEvent *e ) { + qDebug("Playlist::dragEnterEvent"); + + if (e->mimeData()->hasUrls()) { + e->acceptProposedAction(); + } +} + +void Playlist::dropEvent( QDropEvent *e ) { + qDebug("Playlist::dropEvent"); + + QStringList files; + + if (e->mimeData()->hasUrls()) { + QList l = e->mimeData()->urls(); + QString s; + for (int n=0; n < l.count(); n++) { + if (l[n].isValid()) { + qDebug("Playlist::dropEvent: scheme: '%s'", l[n].scheme().toUtf8().data()); + if (l[n].scheme() == "file") + s = l[n].toLocalFile(); + else + s = l[n].toString(); + /* + qDebug(" * '%s'", l[n].toString().toUtf8().data()); + qDebug(" * '%s'", l[n].toLocalFile().toUtf8().data()); + */ + qDebug("Playlist::dropEvent: file: '%s'", s.toUtf8().data()); + files.append(s); + } + } + } + + + QStringList only_files; + for (int n = 0; n < files.count(); n++) { + if ( QFileInfo( files[n] ).isDir() ) { + addDirectory( files[n] ); + } else { + only_files.append( files[n] ); + } + } + addFiles( only_files ); +} + + +void Playlist::hideEvent( QHideEvent * ) { + emit visibilityChanged(false); +} + +void Playlist::showEvent( QShowEvent * ) { + emit visibilityChanged(true); +} + +void Playlist::closeEvent( QCloseEvent * e ) { + saveSettings(); + e->accept(); +} + + +void Playlist::maybeSaveSettings() { + qDebug("Playlist::maybeSaveSettings"); + if (isModified()) saveSettings(); +} + +void Playlist::saveSettings() { + qDebug("Playlist::saveSettings"); + + QSettings * set = settings; + + set->beginGroup( "playlist"); + + set->setValue( "repeat", repeatAct->isChecked() ); + set->setValue( "shuffle", shuffleAct->isChecked() ); + + set->setValue( "auto_get_info", automatically_get_info ); + set->setValue( "recursive_add_directory", recursive_add_directory ); + set->setValue( "save_playlist_in_config", save_playlist_in_config ); + set->setValue( "play_files_from_start", play_files_from_start ); + +#if !DOCK_PLAYLIST + set->setValue( "size", size() ); +#endif + set->setValue( "latest_dir", latest_dir ); + + set->endGroup(); + + if (save_playlist_in_config) { + //Save current list + set->beginGroup( "playlist_contents"); + + set->setValue( "count", (int) pl.count() ); + for ( int n=0; n < pl.count(); n++ ) { + set->setValue( QString("item_%1_filename").arg(n), pl[n].filename() ); + set->setValue( QString("item_%1_duration").arg(n), pl[n].duration() ); + set->setValue( QString("item_%1_name").arg(n), pl[n].name() ); + } + set->setValue( "current_item", current_item ); + set->setValue( "modified", modified ); + + set->endGroup(); + } +} + +void Playlist::loadSettings() { + qDebug("Playlist::loadSettings"); + + QSettings * set = settings; + + set->beginGroup( "playlist"); + + repeatAct->setChecked( set->value( "repeat", repeatAct->isChecked() ).toBool() ); + shuffleAct->setChecked( set->value( "shuffle", shuffleAct->isChecked() ).toBool() ); + + automatically_get_info = set->value( "auto_get_info", automatically_get_info ).toBool(); + recursive_add_directory = set->value( "recursive_add_directory", recursive_add_directory ).toBool(); + save_playlist_in_config = set->value( "save_playlist_in_config", save_playlist_in_config ).toBool(); + play_files_from_start = set->value( "play_files_from_start", play_files_from_start ).toBool(); + +#if !DOCK_PLAYLIST + resize( set->value("size", size()).toSize() ); +#endif + + latest_dir = set->value( "latest_dir", latest_dir ).toString(); + + set->endGroup(); + + if (save_playlist_in_config) { + //Load latest list + set->beginGroup( "playlist_contents"); + + int count = set->value( "count", 0 ).toInt(); + QString filename, name; + double duration; + for ( int n=0; n < count; n++ ) { + filename = set->value( QString("item_%1_filename").arg(n), "" ).toString(); + duration = set->value( QString("item_%1_duration").arg(n), -1 ).toDouble(); + name = set->value( QString("item_%1_name").arg(n), "" ).toString(); + addItem( filename, name, duration ); + } + setCurrentItem( set->value( "current_item", -1 ).toInt() ); + setModified( set->value( "modified", false ).toBool() ); + updateView(); + + set->endGroup(); + } +} + +QString Playlist::lastDir() { + QString last_dir = latest_dir; + if (last_dir.isEmpty()) last_dir = pref->latest_dir; + return last_dir; +} + +// Language change stuff +void Playlist::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QWidget::changeEvent(e); + } +} + +#include "moc_playlist.cpp" diff --git a/plugins/smplayer_plugin/playlist.h b/plugins/smplayer_plugin/playlist.h new file mode 100644 index 000000000..bb995d1ba --- /dev/null +++ b/plugins/smplayer_plugin/playlist.h @@ -0,0 +1,224 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _PLAYLIST_H_ +#define _PLAYLIST_H_ + +#include +#include +#include + +class PlaylistItem { + +public: + PlaylistItem() { _filename=""; _name=""; _duration=0; + _played = FALSE; _deleted=FALSE; }; + PlaylistItem(QString filename, QString name, double duration) { + _filename = filename; _name = name; _duration = duration; + _played = FALSE; _deleted = FALSE; }; + ~PlaylistItem() {}; + + void setFilename(QString filename) { _filename = filename; }; + void setName(QString name) { _name = name; }; + void setDuration(double duration) { _duration = duration; }; + void setPlayed(bool b) { _played = b; }; + void setMarkForDeletion(bool b) { _deleted = b; }; + + QString filename() { return _filename; }; + QString name() { return _name; }; + double duration() { return _duration; }; + bool played() { return _played; }; + bool markedForDeletion() { return _deleted; }; + +private: + QString _filename, _name; + double _duration; + bool _played, _deleted; +}; + +class MyTableWidget; +class QToolBar; +class MyAction; +class Core; +class QMenu; +class QSettings; +class QToolButton; +class QTimer; + +class Playlist : public QWidget +{ + Q_OBJECT + +public: + enum AutoGetInfo { NoGetInfo = 0, GetInfo = 1, UserDefined = 2 }; + + Playlist( Core *c, QWidget * parent = 0, Qt::WindowFlags f = Qt::Window ); + ~Playlist(); + + void clear(); + void list(); + int count(); + bool isEmpty(); + + bool isModified() { return modified; }; + +public slots: + void addItem(QString filename, QString name, double duration); + + // Start playing, from item 0 if shuffle is off, or from + // a random item otherwise + void startPlay(); + + void playItem(int n); + + virtual void playNext(); + virtual void playPrev(); + + virtual void removeSelected(); + virtual void removeAll(); + + virtual void addCurrentFile(); + virtual void addFiles(); + virtual void addDirectory(); + + virtual void addFile(QString file, AutoGetInfo auto_get_info = UserDefined); + virtual void addFiles(QStringList files, AutoGetInfo auto_get_info = UserDefined); + + // Adds a directory, no recursive + virtual void addOneDirectory(QString dir); + + // Adds a directory, maybe with recursion (depends on user config) + virtual void addDirectory(QString dir); + + void editPreferences(); + + virtual bool maybeSave(); + virtual void load(); + virtual bool save(); + + virtual void load_m3u(QString file); + virtual bool save_m3u(QString file); + + virtual void load_pls(QString file); + virtual bool save_pls(QString file); + + virtual void getMediaInfo(); + + void setModified(bool); + +/* +public: + MyAction * playPrevAct() { return prevAct; }; + MyAction * playNextAct() { return nextAct; }; +*/ + +signals: + void playlistEnded(); + void visibilityChanged(bool visible); + void modifiedChanged(bool); + +protected: + void updateView(); + void setCurrentItem(int current); + void clearPlayedTag(); + int chooseRandomItem(); + void swapItems(int item1, int item2 ); + QString lastDir(); + +protected slots: + virtual void playCurrent(); + virtual void itemDoubleClicked(int row); + virtual void showPopup(const QPoint & pos); + virtual void upItem(); + virtual void downItem(); + virtual void editCurrentItem(); + virtual void editItem(int item); + + virtual void saveSettings(); + virtual void loadSettings(); + + virtual void maybeSaveSettings(); + +protected: + void createTable(); + void createActions(); + void createToolbar(); + +protected: + void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + virtual void dragEnterEvent( QDragEnterEvent * ) ; + virtual void dropEvent ( QDropEvent * ); + virtual void hideEvent ( QHideEvent * ); + virtual void showEvent ( QShowEvent * ); + virtual void closeEvent( QCloseEvent * e ); + +protected: + typedef QList PlaylistItemList; + PlaylistItemList pl; + int current_item; + + QString playlist_path; + QString latest_dir; + + Core * core; + QMenu * add_menu; + QMenu * remove_menu; + QMenu * popup; + + MyTableWidget * listView; + + QToolBar * toolbar; + QToolButton * add_button; + QToolButton * remove_button; + + MyAction * openAct; + MyAction * saveAct; + MyAction * playAct; + MyAction * prevAct; + MyAction * nextAct; + MyAction * repeatAct; + MyAction * shuffleAct; + MyAction * preferencesAct; + + MyAction * moveUpAct; + MyAction * moveDownAct; + MyAction * editAct; + + MyAction * addCurrentAct; + MyAction * addFilesAct; + MyAction * addDirectoryAct; + + MyAction * removeSelectedAct; + MyAction * removeAllAct; + +private: + bool modified; + QTimer * save_timer; + + //Preferences + bool recursive_add_directory; + bool automatically_get_info; + bool save_playlist_in_config; + bool play_files_from_start; +}; + + +#endif + diff --git a/plugins/smplayer_plugin/playlistdock.cpp b/plugins/smplayer_plugin/playlistdock.cpp new file mode 100644 index 000000000..6209e259e --- /dev/null +++ b/plugins/smplayer_plugin/playlistdock.cpp @@ -0,0 +1,52 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "playlistdock.h" +#include + +PlaylistDock::PlaylistDock(QWidget * parent, Qt::WindowFlags flags) + : QDockWidget(parent, flags) +{ + //setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Expanding ); + setAcceptDrops(true); // Fix for Qt 4.4, otherwise the playlist doesn't accept drops... +} + +PlaylistDock::~PlaylistDock() { +} + +void PlaylistDock::closeEvent( QCloseEvent * e ) { + qDebug("PlaylistDock::closeEvent"); + emit closed(); + e->accept(); +} + +#if QT_VERSION < 0x040300 +void PlaylistDock::showEvent( QShowEvent * /* event */ ) { + qDebug("PlaylistDock::showEvent"); + emit visibilityChanged(true); +} + +void PlaylistDock::hideEvent( QHideEvent * /* event */ ) { + qDebug("PlaylistDock::hideEvent"); + emit visibilityChanged(false); +} +#endif + + +#include "moc_playlistdock.cpp" + diff --git a/plugins/smplayer_plugin/playlistdock.h b/plugins/smplayer_plugin/playlistdock.h new file mode 100644 index 000000000..591192b76 --- /dev/null +++ b/plugins/smplayer_plugin/playlistdock.h @@ -0,0 +1,47 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PLAYLIST_DOCK_H_ +#define _PLAYLIST_DOCK_H_ + +#include +#include "guiconfig.h" + +class PlaylistDock : public QDockWidget +{ + Q_OBJECT + +public: + PlaylistDock ( QWidget * parent = 0, Qt::WindowFlags flags = 0 ); + ~PlaylistDock(); + +signals: + void closed(); +#if QT_VERSION < 0x040300 + void visibilityChanged(bool visible); +#endif + +protected: + virtual void closeEvent( QCloseEvent * e ); +#if QT_VERSION < 0x040300 + virtual void showEvent ( QShowEvent * event ); + virtual void hideEvent ( QHideEvent * event ); +#endif +}; + +#endif diff --git a/plugins/smplayer_plugin/playlistpreferences.cpp b/plugins/smplayer_plugin/playlistpreferences.cpp new file mode 100644 index 000000000..1ad5a6e51 --- /dev/null +++ b/plugins/smplayer_plugin/playlistpreferences.cpp @@ -0,0 +1,82 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "playlistpreferences.h" + +PlaylistPreferences::PlaylistPreferences( QWidget* parent, Qt::WindowFlags f ) + : QDialog(parent, f) +{ + setupUi(this); + //setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + layout()->setSizeConstraint(QLayout::SetFixedSize); + //adjustSize(); + + recursive_check->setWhatsThis( + tr("Check this option if you want that adding a directory will also " + "add the files in subdirectories recursively. Otherwise only the " + "files in the selected directory will be added.")); + + getinfo_check->setWhatsThis( + tr("Check this option to inquire the files to be added to the playlist " + "for some info. That allows to show the title name (if available) and " + "length of the files. Otherwise this info won't be available until " + "the file is actually played. Beware: this option can be slow, " + "specially if you add many files.")); +} + +PlaylistPreferences::~PlaylistPreferences() { +} + +void PlaylistPreferences::setDirectoryRecursion(bool b) { + recursive_check->setChecked(b); +} + +bool PlaylistPreferences::directoryRecursion() { + return recursive_check->isChecked(); +} + +void PlaylistPreferences::setAutoGetInfo(bool b) { + getinfo_check->setChecked(b); +} + +bool PlaylistPreferences::autoGetInfo() { + return getinfo_check->isChecked(); +} + +void PlaylistPreferences::setSavePlaylistOnExit(bool b) { + autosave_on_exit_check->setChecked(b); +} + +bool PlaylistPreferences::savePlaylistOnExit() { + return autosave_on_exit_check->isChecked(); +} + +void PlaylistPreferences::setPlayFilesFromStart(bool b) { + play_from_start_check->setChecked(b); +} + +bool PlaylistPreferences::playFilesFromStart() { + return play_from_start_check->isChecked(); +} + +QSize PlaylistPreferences::sizeHint () const { + return QSize(580,200); +} + +#include "moc_playlistpreferences.cpp" + diff --git a/plugins/smplayer_plugin/playlistpreferences.h b/plugins/smplayer_plugin/playlistpreferences.h new file mode 100644 index 000000000..c9f2544ef --- /dev/null +++ b/plugins/smplayer_plugin/playlistpreferences.h @@ -0,0 +1,48 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PLAYLISTPREFERENCES_H_ +#define _PLAYLISTPREFERENCES_H_ + +#include "ui_playlistpreferences.h" + +class PlaylistPreferences : public QDialog, public Ui::PlaylistPreferences +{ + Q_OBJECT + +public: + PlaylistPreferences( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~PlaylistPreferences(); + + void setDirectoryRecursion(bool b); + bool directoryRecursion(); + + void setAutoGetInfo(bool b); + bool autoGetInfo(); + + void setSavePlaylistOnExit(bool b); + bool savePlaylistOnExit(); + + void setPlayFilesFromStart(bool b); + bool playFilesFromStart(); + + virtual QSize sizeHint () const; +}; + +#endif + diff --git a/plugins/smplayer_plugin/playlistpreferences.ui b/plugins/smplayer_plugin/playlistpreferences.ui new file mode 100644 index 000000000..790277b73 --- /dev/null +++ b/plugins/smplayer_plugin/playlistpreferences.ui @@ -0,0 +1,104 @@ + + PlaylistPreferences + + + + 0 + 0 + 466 + 144 + + + + Playlist - Preferences + + + + 9 + + + 6 + + + + + &Play files from start + + + + + + + &Add files in directories recursively + + + + + + + Automatically get &info about files added + + + + + + + &Save copy of playlist on exit + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + PlaylistPreferences + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + PlaylistPreferences + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/smplayer_plugin/prefadvanced.cpp b/plugins/smplayer_plugin/prefadvanced.cpp new file mode 100644 index 000000000..870abd996 --- /dev/null +++ b/plugins/smplayer_plugin/prefadvanced.cpp @@ -0,0 +1,553 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "prefadvanced.h" +#include "images.h" +#include "preferences.h" +#include +#include + +PrefAdvanced::PrefAdvanced(QWidget * parent, Qt::WindowFlags f) + : PrefWidget(parent, f ) +{ + setupUi(this); + +#ifndef Q_OS_WIN + shortnames_check->hide(); +#endif + +#if !USE_COLORKEY + colorkey_label->hide(); + colorkey_view->hide(); + changeButton->hide(); +#endif + +#if !REPAINT_BACKGROUND_OPTION + repaint_video_background_check->hide(); +#endif + + // Monitor aspect + monitoraspect_combo->addItem("Auto"); + monitoraspect_combo->addItem("4:3"); + monitoraspect_combo->addItem("16:9"); + monitoraspect_combo->addItem("5:4"); + monitoraspect_combo->addItem("16:10"); + + retranslateStrings(); +} + +PrefAdvanced::~PrefAdvanced() +{ +} + +QString PrefAdvanced::sectionName() { + return tr("Advanced"); +} + +QPixmap PrefAdvanced::sectionIcon() { + return Images::icon("pref_advanced"); +} + + +void PrefAdvanced::retranslateStrings() { + retranslateUi(this); + + monitor_aspect_icon->setPixmap( Images::icon("monitor") ); + + monitoraspect_combo->setItemText(0, tr("Auto") ); + + int proxy_type_item = proxy_type_combo->currentIndex(); + proxy_type_combo->clear(); + proxy_type_combo->addItem( tr("Http"), QNetworkProxy::HttpProxy); + proxy_type_combo->addItem( tr("Socks5"), QNetworkProxy::Socks5Proxy); + proxy_type_combo->setCurrentIndex(proxy_type_item); + + createHelp(); +} + +void PrefAdvanced::setData(Preferences * pref) { + setMonitorAspect( pref->monitor_aspect ); + +#if REPAINT_BACKGROUND_OPTION + setRepaintVideoBackground( pref->repaint_video_background ); +#endif + setUseMplayerWindow( pref->use_mplayer_window ); + setMplayerAdditionalArguments( pref->mplayer_additional_options ); + setMplayerAdditionalVideoFilters( pref->mplayer_additional_video_filters ); + setMplayerAdditionalAudioFilters( pref->mplayer_additional_audio_filters ); +#if USE_COLORKEY + setColorKey( pref->color_key ); +#endif + setPreferIpv4( pref->prefer_ipv4 ); + setUseIdx( pref->use_idx ); + setUseCorrectPts( pref->use_correct_pts ); + setActionsToRun( pref->actions_to_run ); + + setLogMplayer( pref->log_mplayer ); + setLogSmplayer( pref->log_smplayer ); + setLogFilter( pref->log_filter ); + + setSaveMplayerLog( pref->autosave_mplayer_log ); + setMplayerLogName( pref->mplayer_log_saveto ); + + setUseShortNames( pref->use_short_pathnames ); + + // Proxy + setUseProxy( pref->use_proxy ); + setProxyHostname( pref->proxy_host ); + setProxyPort( pref->proxy_port ); + setProxyUsername( pref->proxy_username ); + setProxyPassword( pref->proxy_password ); + setProxyType( pref->proxy_type ); +} + +void PrefAdvanced::getData(Preferences * pref) { + requires_restart = false; + +#if REPAINT_BACKGROUND_OPTION + repaint_video_background_changed = false; +#endif + + monitor_aspect_changed = false; +#if USE_COLORKEY + colorkey_changed = false; +#endif + pref->prefer_ipv4 = preferIpv4(); + TEST_AND_SET(pref->use_idx, useIdx()); + TEST_AND_SET(pref->use_correct_pts, useCorrectPts()); + pref->actions_to_run = actionsToRun(); + + if (pref->monitor_aspect != monitorAspect()) { + pref->monitor_aspect = monitorAspect(); + monitor_aspect_changed = true; + requires_restart = true; + } + +#if REPAINT_BACKGROUND_OPTION + if (pref->repaint_video_background != repaintVideoBackground()) { + pref->repaint_video_background = repaintVideoBackground(); + repaint_video_background_changed = true; + } +#endif + + TEST_AND_SET(pref->use_mplayer_window, useMplayerWindow()); + TEST_AND_SET(pref->mplayer_additional_options, mplayerAdditionalArguments()); + TEST_AND_SET(pref->mplayer_additional_video_filters, mplayerAdditionalVideoFilters()); + TEST_AND_SET(pref->mplayer_additional_audio_filters, mplayerAdditionalAudioFilters()); +#if USE_COLORKEY + if (pref->color_key != colorKey()) { + pref->color_key = colorKey(); + colorkey_changed = true; + requires_restart = true; + } +#endif + pref->log_mplayer = logMplayer(); + pref->log_smplayer = logSmplayer(); + pref->log_filter = logFilter(); + pref->autosave_mplayer_log = saveMplayerLog(); + pref->mplayer_log_saveto = mplayerLogName(); + + pref->use_short_pathnames = useShortNames(); + + // Proxy + proxy_changed = ( (pref->use_proxy != useProxy()) || + (pref->proxy_host != proxyHostname()) || + (pref->proxy_port != proxyPort()) || + (pref->proxy_username != proxyUsername()) || + (pref->proxy_password != proxyPassword()) || + (pref->proxy_type != proxyType()) ); + + pref->use_proxy = useProxy(); + pref->proxy_host = proxyHostname(); + pref->proxy_port = proxyPort(); + pref->proxy_username = proxyUsername(); + pref->proxy_password = proxyPassword(); + pref->proxy_type = proxyType(); +} + +void PrefAdvanced::setMonitorAspect(QString asp) { + if (asp.isEmpty()) + monitoraspect_combo->setCurrentIndex( 0 ); + else + monitoraspect_combo->setCurrentText(asp); + //monitoraspect_combo->setEditText(asp); +} + +QString PrefAdvanced::monitorAspect() { + if (monitoraspect_combo->currentIndex() == 0 ) + return ""; + else + return monitoraspect_combo->currentText(); +} + +#if REPAINT_BACKGROUND_OPTION +void PrefAdvanced::setRepaintVideoBackground(bool b) { + repaint_video_background_check->setChecked(b); +} + +bool PrefAdvanced::repaintVideoBackground() { + return repaint_video_background_check->isChecked(); +} +#endif + +void PrefAdvanced::setUseMplayerWindow(bool v) { + mplayer_use_window_check->setChecked(v); +} + +bool PrefAdvanced::useMplayerWindow() { + return mplayer_use_window_check->isChecked(); +} + +void PrefAdvanced::setUseShortNames(bool b) { + shortnames_check->setChecked(b); +} + +bool PrefAdvanced::useShortNames() { + return shortnames_check->isChecked(); +} + +void PrefAdvanced::setMplayerAdditionalArguments(QString args) { + mplayer_args_edit->setText(args); +} + +QString PrefAdvanced::mplayerAdditionalArguments() { + return mplayer_args_edit->text(); +} + +void PrefAdvanced::setMplayerAdditionalVideoFilters(QString s) { + mplayer_vfilters_edit->setText(s); +} + +QString PrefAdvanced::mplayerAdditionalVideoFilters() { + return mplayer_vfilters_edit->text(); +} + +void PrefAdvanced::setMplayerAdditionalAudioFilters(QString s) { + mplayer_afilters_edit->setText(s); +} + +QString PrefAdvanced::mplayerAdditionalAudioFilters() { + return mplayer_afilters_edit->text(); +} + +#if USE_COLORKEY +void PrefAdvanced::setColorKey(unsigned int c) { + QString color = QString::number(c, 16); + while (color.length() < 6) color = "0"+color; + colorkey_view->setText( "#" + color ); +} + +unsigned int PrefAdvanced::colorKey() { + QString c = colorkey_view->text(); + if (c.startsWith("#")) c = c.mid(1); + + bool ok; + unsigned int color = c.toUInt(&ok, 16); + + if (!ok) + qWarning("PrefAdvanced::colorKey: cannot convert color to uint"); + + qDebug("PrefAdvanced::colorKey: color: %s", QString::number(color,16).toUtf8().data() ); + + return color; +} +#endif + +void PrefAdvanced::setPreferIpv4(bool b) { + if (b) + ipv4_button->setChecked(true); + else + ipv6_button->setChecked(true); +} + +bool PrefAdvanced::preferIpv4() { + return ipv4_button->isChecked(); +} + +void PrefAdvanced::setUseIdx(bool b) { + idx_check->setChecked(b); +} + +bool PrefAdvanced::useIdx() { + return idx_check->isChecked(); +} + +void PrefAdvanced::setUseCorrectPts(bool b) { + correct_pts_check->setChecked(b); +} + +bool PrefAdvanced::useCorrectPts() { + return correct_pts_check->isChecked(); +} + +void PrefAdvanced::setActionsToRun(QString actions) { + actions_to_run_edit->setText(actions); +} + +QString PrefAdvanced::actionsToRun() { + return actions_to_run_edit->text(); +} + +void PrefAdvanced::on_changeButton_clicked() { + //bool ok; + //int color = colorkey_view->text().toUInt(&ok, 16); + QColor color( colorkey_view->text() ); + QColor c = QColorDialog::getColor ( color, this ); + if (c.isValid()) { + //colorkey_view->setText( QString::number( c.rgb(), 16 ) ); + colorkey_view->setText( c.name() ); + } +} + +// Log options +void PrefAdvanced::setLogMplayer(bool b) { + log_mplayer_check->setChecked(b); +} + +bool PrefAdvanced::logMplayer() { + return log_mplayer_check->isChecked(); +} + +void PrefAdvanced::setLogSmplayer(bool b) { + log_smplayer_check->setChecked(b); +} + +bool PrefAdvanced::logSmplayer() { + return log_smplayer_check->isChecked(); +} + +void PrefAdvanced::setLogFilter(QString filter) { + log_filter_edit->setText(filter); +} + +QString PrefAdvanced::logFilter() { + return log_filter_edit->text(); +} + + +void PrefAdvanced::setSaveMplayerLog(bool b) { + log_mplayer_save_check->setChecked(b); +} + +bool PrefAdvanced::saveMplayerLog() { + return log_mplayer_save_check->isChecked(); +} + +void PrefAdvanced::setMplayerLogName(QString filter) { + log_mplayer_save_name->setText(filter); +} + +QString PrefAdvanced::mplayerLogName() { + return log_mplayer_save_name->text(); +} + +void PrefAdvanced::setUseProxy(bool b) { + use_proxy_check->setChecked(b); +} + +bool PrefAdvanced::useProxy() { + return use_proxy_check->isChecked(); +} + +void PrefAdvanced::setProxyHostname(QString host) { + proxy_hostname_edit->setText(host); +} + +QString PrefAdvanced::proxyHostname() { + return proxy_hostname_edit->text(); +} + +void PrefAdvanced::setProxyPort(int port) { + proxy_port_spin->setValue(port); +} + +int PrefAdvanced::proxyPort() { + return proxy_port_spin->value(); +} + +void PrefAdvanced::setProxyUsername(QString username) { + proxy_username_edit->setText(username); +} + +QString PrefAdvanced::proxyUsername() { + return proxy_username_edit->text(); +} + +void PrefAdvanced::setProxyPassword(QString password) { + proxy_password_edit->setText(password); +} + +QString PrefAdvanced::proxyPassword() { + return proxy_password_edit->text(); +} + +void PrefAdvanced::setProxyType(int type) { + int index = proxy_type_combo->findData(type); + if (index == -1) index = 0; + proxy_type_combo->setCurrentIndex(index); +} + +int PrefAdvanced::proxyType() { + int index = proxy_type_combo->currentIndex(); + return proxy_type_combo->itemData(index).toInt(); +} + + +void PrefAdvanced::createHelp() { + clearHelp(); + + addSectionTitle(tr("Advanced")); + + setWhatsThis(monitoraspect_combo, tr("Monitor aspect"), + tr("Select the aspect ratio of your monitor.") ); + + setWhatsThis(mplayer_use_window_check, tr("Run MPlayer in its own window"), + tr("If you check this option, the MPlayer video window won't be " + "embedded in SMPlayer's main window but instead it will use its " + "own window. Note that mouse and keyboard events will be handled " + "directly by MPlayer, that means key shortcuts and mouse clicks " + "probably won't work as expected when the MPlayer window has the " + "focus.") ); + + setWhatsThis(idx_check, tr("Rebuild index if needed"), + tr("Rebuilds index of files if no index was found, allowing seeking. " + "Useful with broken/incomplete downloads, or badly created files. " + "This option only works if the underlying media supports " + "seeking (i.e. not with stdin, pipe, etc).
    " + "Note: the creation of the index may take some time.") ); + + setWhatsThis(correct_pts_check, tr("Correct pts"), + tr("Switches MPlayer to an experimental mode where timestamps for " + "video frames are calculated differently and video filters which " + "add new frames or modify timestamps of existing ones are " + "supported. The more accurate timestamps can be visible for " + "example when playing subtitles timed to scene changes with the " + "SSA/ASS library enabled. Without correct pts the subtitle timing " + "will typically be off by some frames. This option does not work " + "correctly with some demuxers and codecs.") ); + +#ifdef Q_OS_WIN + setWhatsThis(shortnames_check, tr("Pass short filenames (8+3) to MPlayer"), + tr("Currently MPlayer can't open filenames which contains characters " + "outside the local codepage. Checking this option will make " + "SMPlayer to pass to MPlayer the short version of the filenames, " + "and thus it will able to open them.") ); +#endif + +#if REPAINT_BACKGROUND_OPTION + setWhatsThis(repaint_video_background_check, + tr("Repaint the background of the video window"), + tr("Checking this option may reduce flickering, but it also might " + "produce that the video won't be displayed properly.") ); +#endif + +#if USE_COLORKEY + setWhatsThis(colorkey_view, tr("Colorkey"), + tr("If you see parts of the video over any other window, you can " + "change the colorkey to fix it. Try to select a color close to " + "black.") ); +#endif + + setWhatsThis(actions_to_run_edit, tr("Actions list"), + tr("Here you can specify a list of actions which will be " + "run every time a file is opened. You'll find all available " + "actions in the key shortcut editor in the Keyboard and mouse " + "section. The actions must be separated by spaces. Checkable " + "actions can be followed by true or false to " + "enable or disable the action.") +"
    "+ + tr("Example:") +" auto_zoom compact true
    " + + tr("Limitation: the actions are run only when a file is opened and " + "not when the mplayer process is restarted (e.g. you select an " + "audio or video filter).") ); + + addSectionTitle(tr("Options for MPlayer")); + + setWhatsThis(mplayer_args_edit, tr("Options"), + tr("Here you can type options for MPlayer. Write them separated " + "by spaces.") ); + + setWhatsThis(mplayer_vfilters_edit, tr("Video filters"), + tr("Here you can add video filters for MPlayer. Write them separated " + "by commas. Don't use spaces!") ); + + setWhatsThis(mplayer_afilters_edit, tr("Audio filters"), + tr("Here you can add audio filters for MPlayer. Write them separated " + "by commas. Don't use spaces!") ); + + addSectionTitle(tr("Network")); + + setWhatsThis(ipv4_button, tr("IPv4"), + tr("Use IPv4 on network connections. Falls back on IPv6 automatically.")); + + setWhatsThis(ipv6_button, tr("IPv6"), + tr("Use IPv6 on network connections. Falls back on IPv4 automatically.")); + + setWhatsThis(use_proxy_check, tr("Enable proxy"), + tr("Enable/disable the use of the proxy.") ); + + setWhatsThis(proxy_hostname_edit, tr("Host"), + tr("The host name of the proxy.") ); + + setWhatsThis(proxy_port_spin, tr("Port"), + tr("The port of the proxy.") ); + + setWhatsThis(proxy_username_edit, tr("Username"), + tr("If the proxy requires authentication, this sets the username.") ); + + setWhatsThis(proxy_password_edit, tr("Password"), + tr("The password for the proxy. Warning: the password will be saved " + "as plain text in the configuration file.") ); + + setWhatsThis(proxy_type_combo, tr("Type"), + tr("Select the proxy type to be used.") ); + + addSectionTitle(tr("Logs")); + + setWhatsThis(log_smplayer_check, tr("Log SMPlayer output"), + tr("If this option is checked, SMPlayer will store the debugging " + "messages that SMPlayer outputs " + "(you can see the log in Options -> View logs -> SMPlayer). " + "This information can be very useful for the developer in case " + "you find a bug." ) ); + + setWhatsThis(log_mplayer_check, tr("Log MPlayer output"), + tr("If checked, SMPlayer will store the output of MPlayer " + "(you can see it in Options -> View logs -> MPlayer). " + "In case of problems this log can contain important information, " + "so it's recommended to keep this option checked.") ); + + setWhatsThis(log_mplayer_save_check, tr("Autosave MPlayer log"), + tr("If this option is checked, the MPlayer log will be saved to the " + "specified file every time a new file starts to play. " + "It's intended for external applications, so they can get " + "info about the file you're playing.") ); + + setWhatsThis(log_mplayer_save_name, tr("Autosave MPlayer log filename"), + tr("Enter here the path and filename that will be used to save the " + "MPlayer log.") ); + + setWhatsThis(log_filter_edit, tr("Filter for SMPlayer logs"), + tr("This option allows to filter the SMPlayer messages that will " + "be stored in the log. Here you can write any regular expression.
    " + "For instance: ^Core::.* will display only the lines " + "starting with Core::") ); + +} + +#include "moc_prefadvanced.cpp" diff --git a/plugins/smplayer_plugin/prefadvanced.h b/plugins/smplayer_plugin/prefadvanced.h new file mode 100644 index 000000000..38d2c7774 --- /dev/null +++ b/plugins/smplayer_plugin/prefadvanced.h @@ -0,0 +1,152 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFADVANCED_H_ +#define _PREFADVANCED_H_ + +#include "ui_prefadvanced.h" +#include "prefwidget.h" +#include "config.h" + +class Preferences; + +class PrefAdvanced : public PrefWidget, public Ui::PrefAdvanced +{ + Q_OBJECT + +public: + PrefAdvanced( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefAdvanced(); + + virtual QString sectionName(); + virtual QPixmap sectionIcon(); + + // Pass data to the dialog + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + +#if REPAINT_BACKGROUND_OPTION + bool repaintVideoBackgroundChanged() { return repaint_video_background_changed; }; +#endif + bool monitorAspectChanged() { return monitor_aspect_changed; }; +#if USE_COLORKEY + bool colorkeyChanged() { return colorkey_changed; }; +#endif + + bool proxyChanged() { return proxy_changed; }; + +protected: + virtual void createHelp(); + + // Advanced + void setMonitorAspect(QString asp); + QString monitorAspect(); + +#if REPAINT_BACKGROUND_OPTION + void setRepaintVideoBackground(bool b); + bool repaintVideoBackground(); +#endif + + void setUseMplayerWindow(bool v); + bool useMplayerWindow(); + + // Windows only: pass to mplayer short filenames (8+3) + void setUseShortNames(bool b); + bool useShortNames(); + + void setMplayerAdditionalArguments(QString args); + QString mplayerAdditionalArguments(); + + void setMplayerAdditionalVideoFilters(QString s); + QString mplayerAdditionalVideoFilters(); + + void setMplayerAdditionalAudioFilters(QString s); + QString mplayerAdditionalAudioFilters(); + +#if USE_COLORKEY + void setColorKey(unsigned int c); + unsigned int colorKey(); +#endif + + void setPreferIpv4(bool b); + bool preferIpv4(); + + void setUseIdx(bool); + bool useIdx(); + + void setUseCorrectPts(bool b); + bool useCorrectPts(); + + void setActionsToRun(QString actions); + QString actionsToRun(); + + // Log options + void setLogMplayer(bool b); + bool logMplayer(); + + void setLogSmplayer(bool b); + bool logSmplayer(); + + void setLogFilter(QString filter); + QString logFilter(); + + void setSaveMplayerLog(bool b); + bool saveMplayerLog(); + + void setMplayerLogName(QString filter); + QString mplayerLogName(); + + // Proxy + void setUseProxy(bool b); + bool useProxy(); + + void setProxyHostname(QString host); + QString proxyHostname(); + + void setProxyPort(int port); + int proxyPort(); + + void setProxyUsername(QString username); + QString proxyUsername(); + + void setProxyPassword(QString password); + QString proxyPassword(); + + void setProxyType(int type); + int proxyType(); + +protected: + virtual void retranslateStrings(); + +protected slots: + void on_changeButton_clicked(); + +private: +#if REPAINT_BACKGROUND_OPTION + bool repaint_video_background_changed; +#endif + bool monitor_aspect_changed; +#if USE_COLORKEY + bool colorkey_changed; +#endif + bool proxy_changed; +}; + +#endif diff --git a/plugins/smplayer_plugin/prefadvanced.ui b/plugins/smplayer_plugin/prefadvanced.ui new file mode 100644 index 000000000..e12d2971b --- /dev/null +++ b/plugins/smplayer_plugin/prefadvanced.ui @@ -0,0 +1,865 @@ + + PrefAdvanced + + + + 0 + 0 + 511 + 466 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + &Advanced + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + icon + + + false + + + + + + + &Monitor aspect: + + + false + + + monitoraspect_combo + + + + + + + + 0 + 0 + + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 190 + 21 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + &Run MPlayer in its own window + + + + + + + Rebuild &index if needed + + + + + + + C&orrect PTS + + + + + + + &Pass short filenames (8+3) to MPlayer + + + + + + + Repaint the backgroun&d of the video window + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + true + + + actions_to_run_edit + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Colorkey: + + + false + + + colorkey_view + + + + + + + + 0 + 0 + + + + + + + + C&hange... + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 131 + 21 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 489 + 20 + + + + + + + + + Options for MP&layer + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + Qt::AlignVCenter + + + false + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Options: + + + false + + + mplayer_args_edit + + + + + + + + + + + + + 0 + 0 + + + + QFrame::HLine + + + QFrame::Sunken + + + Qt::Horizontal + + + + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + Qt::AlignVCenter + + + false + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + V&ideo filters: + + + false + + + mplayer_vfilters_edit + + + + + + + + + + + + + 0 + 0 + + + + QFrame::HLine + + + QFrame::Sunken + + + Qt::Horizontal + + + + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + + + Qt::AlignVCenter + + + false + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Audio &filters: + + + false + + + mplayer_afilters_edit + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Network + + + + + + Network Connection + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + IPv&4 + + + + + + + IPv&6 + + + + + + + + + + Proxy + + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + true + + + + + + + &Enable proxy + + + + + + + false + + + + + + &Host: + + + proxy_hostname_edit + + + + + + + + + + &Port: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + proxy_port_spin + + + + + + + 65535 + + + + + + + &Username: + + + proxy_username_edit + + + + + + + + + + Pa&ssword: + + + proxy_password_edit + + + + + + + QLineEdit::Password + + + + + + + &Type: + + + proxy_type_combo + + + + + + + + + + Qt::Horizontal + + + + 261 + 20 + + + + + + + + + + + + + + Qt::Vertical + + + + 458 + 31 + + + + + + + + + Lo&gs + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Log &SMPlayer output + + + + + + + Log MPlayer &output + + + + + + + A&utosave MPlayer log to file + + + + + + + false + + + + + + + + 0 + 0 + + + + QFrame::HLine + + + QFrame::Sunken + + + Qt::Horizontal + + + + + + + This option is mainly intended for debugging the application. + + + false + + + + + + + &Filter for SMPlayer logs: + + + false + + + log_filter_edit + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + MyComboBox + QComboBox +
    mycombobox.h
    +
    +
    + + advanced_tab + monitoraspect_combo + mplayer_use_window_check + idx_check + correct_pts_check + shortnames_check + repaint_video_background_check + actions_to_run_edit + colorkey_view + changeButton + mplayer_args_edit + mplayer_vfilters_edit + mplayer_afilters_edit + ipv4_button + ipv6_button + use_proxy_check + proxy_hostname_edit + proxy_port_spin + proxy_username_edit + proxy_password_edit + proxy_type_combo + log_smplayer_check + log_mplayer_check + log_mplayer_save_check + log_mplayer_save_name + log_filter_edit + + + + + log_mplayer_save_check + toggled(bool) + log_mplayer_save_name + setEnabled(bool) + + + 249 + 180 + + + 249 + 212 + + + + + use_proxy_check + toggled(bool) + proxy_container + setEnabled(bool) + + + 239 + 90 + + + 239 + 179 + + + + +
    diff --git a/plugins/smplayer_plugin/prefassociations.cpp b/plugins/smplayer_plugin/prefassociations.cpp new file mode 100644 index 000000000..711da2ce3 --- /dev/null +++ b/plugins/smplayer_plugin/prefassociations.cpp @@ -0,0 +1,228 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + prefassociations.cpp + Handles file associations in Windows + Author: Florin Braghis (florin@libertv.ro) +*/ + + +#include "prefassociations.h" +#include "images.h" +#include +#include +#include +#include "winfileassoc.h" +#include "extensions.h" + +static Qt::CheckState CurItemCheckState = Qt::Unchecked; + + +PrefAssociations::PrefAssociations(QWidget * parent, Qt::WindowFlags f) +: PrefWidget(parent, f ) +{ + setupUi(this); + + connect(selectAll, SIGNAL(clicked(bool)), this, SLOT(selectAllClicked(bool))); + connect(selectNone, SIGNAL(clicked(bool)), this, SLOT(selectNoneClicked(bool))); + connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(listItemClicked(QListWidgetItem*))); + connect(listWidget, SIGNAL(itemPressed(QListWidgetItem*)), this, SLOT(listItemPressed(QListWidgetItem*))); + +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA) + { + //Hide Select None - One cannot restore an association in Vista. Go figure. + selectNone->hide(); + //QPushButton* lpbButton = new QPushButton("Launch Program Defaults", this); + //hboxLayout->addWidget(lpbButton); + //connect(lpbButton, SIGNAL(clicked(bool)), this, SLOT(launchAppDefaults())); + } +#endif + + Extensions e; + for (int n=0; n < e.multimedia().count(); n++) { + addItem( e.multimedia()[n] ); + } + // Add the playlist extensions + for (int n=0; n < e.playlist().count(); n++) { + addItem( e.playlist()[n] ); + } + retranslateStrings(); +} + +PrefAssociations::~PrefAssociations() +{ + +} + +void PrefAssociations::selectAllClicked(bool) +{ + for (int k = 0; k < listWidget->count(); k++) + listWidget->item(k)->setCheckState(Qt::Checked); + listWidget->setFocus(); +} + +void PrefAssociations::selectNoneClicked(bool) +{ + + for (int k = 0; k < listWidget->count(); k++) + listWidget->item(k)->setCheckState(Qt::Unchecked); + listWidget->setFocus(); +} + +void PrefAssociations::listItemClicked(QListWidgetItem* item) +{ + if (!(item->flags() & Qt::ItemIsEnabled)) + return; + + if (item->checkState() == CurItemCheckState) + { + //Clicked on the list item (not checkbox) + if (item->checkState() == Qt::Checked) + { + item->setCheckState(Qt::Unchecked); + } + else + item->setCheckState(Qt::Checked); + } + + //else - clicked on the checkbox itself, do nothing +} + +void PrefAssociations::listItemPressed(QListWidgetItem* item) +{ + CurItemCheckState = item->checkState(); +} + +void PrefAssociations::addItem(QString label) +{ + QListWidgetItem* item = new QListWidgetItem(listWidget); + item->setText(label); +} + +void PrefAssociations::refreshList() +{ + m_regExtensions.clear(); + WinFileAssoc ().GetRegisteredExtensions(Extensions().multimedia(), m_regExtensions); + + for (int k = 0; k < listWidget->count(); k++) + { + QListWidgetItem* pItem = listWidget->item(k); + if (pItem) + { + pItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + + if (m_regExtensions.contains(pItem->text())) + { + pItem->setCheckState(Qt::Checked); + //Don't allow de-selection in windows VISTA if extension is registered. + //VISTA doesn't seem to support extension 'restoration' in the API. +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA) { + pItem->setFlags(0); + } +#endif + } + else + { + pItem->setCheckState(Qt::Unchecked); + } + + } + } +} + +void PrefAssociations::setData(Preferences * ) +{ + refreshList(); +} + +int PrefAssociations::ProcessAssociations(QStringList& current, QStringList& old) +{ + WinFileAssoc RegAssoc; + + QStringList toRestore; + + //Restore unselected associations + foreach(const QString& ext, old) + { + if (!current.contains(ext)) + toRestore.append(ext); + } + + RegAssoc.RestoreFileAssociations(toRestore); + return RegAssoc.CreateFileAssociations(current); +} + +void PrefAssociations::getData(Preferences *) +{ + QStringList extensions; + + for (int k = 0; k < listWidget->count(); k++) + { + QListWidgetItem* pItem = listWidget->item(k); + if (pItem && pItem->checkState() == Qt::Checked) + extensions.append(pItem->text()); + } + + int processed = ProcessAssociations(extensions, m_regExtensions); + + if (processed != extensions.count()) + { + QMessageBox::warning(this, tr("Warning"), + tr("Not all files could be associated. Please check your " + "security permissions and retry."), QMessageBox::Ok); + } + + refreshList(); //Useless when OK is pressed... How to detect if apply or ok is pressed ? +} + +QString PrefAssociations::sectionName() { + return tr("File Types"); +} + +QPixmap PrefAssociations::sectionIcon() { + return Images::icon("pref_associations"); +} + +void PrefAssociations::retranslateStrings() { + + retranslateUi(this); + createHelp(); +} + +void PrefAssociations::createHelp() { + + clearHelp(); + + setWhatsThis(selectAll, tr("Select all"), + tr("Check all file types in the list")); + + setWhatsThis(selectNone, tr("Select none"), + tr("Uncheck all file types in the list")); + + setWhatsThis(listWidget, tr("List of file types"), + tr("Check the media file extensions you would like SMPlayer to handle. " + "When you click Apply, the checked files will be associated with " + "SMPlayer. If you uncheck a media type, the file association will " + "be restored.") + + tr(" Note: (Restoration doesn't work on Windows Vista).")); +} + +#include "moc_prefassociations.cpp" + diff --git a/plugins/smplayer_plugin/prefassociations.h b/plugins/smplayer_plugin/prefassociations.h new file mode 100644 index 000000000..7cad45955 --- /dev/null +++ b/plugins/smplayer_plugin/prefassociations.h @@ -0,0 +1,69 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + prefassociations.h + Handles file associations in Windows + Author: Florin Braghis (florin@libertv.ro) +*/ + +#ifndef _PREFASSOCIATIONS_H_ +#define _PREFASSOCIATIONS_H_ + +#include "ui_prefassociations.h" +#include "prefwidget.h" + +class Preferences; + +class PrefAssociations : public PrefWidget, public Ui::PrefAssociations +{ + Q_OBJECT + +public: + PrefAssociations( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefAssociations(); + + virtual QString sectionName(); + virtual QPixmap sectionIcon(); + + // Pass data to the dialog + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + + void addItem(QString label); + + int ProcessAssociations(QStringList& current, QStringList& old); + void refreshList(); + +protected: + QStringList m_regExtensions; +protected: + virtual void createHelp(); + +protected: + virtual void retranslateStrings(); + +public slots: + void selectAllClicked(bool); + void selectNoneClicked(bool); + void listItemClicked(QListWidgetItem* item); + void listItemPressed(QListWidgetItem* item); +}; + +#endif diff --git a/plugins/smplayer_plugin/prefassociations.ui b/plugins/smplayer_plugin/prefassociations.ui new file mode 100644 index 000000000..f1a62e08d --- /dev/null +++ b/plugins/smplayer_plugin/prefassociations.ui @@ -0,0 +1,112 @@ + + PrefAssociations + + + + 0 + 0 + 531 + 489 + + + + + 0 + + + 0 + + + + + 0 + + + + File types + + + + 9 + + + 6 + + + + + Media files handled by SMPlayer: + + + Qt::AlignVCenter + + + true + + + + + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::NoEditTriggers + + + QAbstractItemView::MultiSelection + + + QListView::ListMode + + + true + + + true + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + + 311 + 20 + + + + + + + + Select All + + + + + + + Select None + + + + + + + + + + + + + + diff --git a/plugins/smplayer_plugin/prefdrives.cpp b/plugins/smplayer_plugin/prefdrives.cpp new file mode 100644 index 000000000..e4a2905f8 --- /dev/null +++ b/plugins/smplayer_plugin/prefdrives.cpp @@ -0,0 +1,137 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "prefdrives.h" +#include "images.h" +#include "preferences.h" + +#include +#include +#include + +#ifdef Q_OS_WIN +#include + +bool isCDDevice(QString drive) { + if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT) { + unsigned int r = GetDriveTypeW((LPCWSTR) drive.utf16()); + qDebug("isCDDevice: '%s' r: %d", drive.toUtf8().data(), r); + return (r == DRIVE_CDROM); + } else { + //Win98 + return true; + } +} + +#endif + +PrefDrives::PrefDrives(QWidget * parent, Qt::WindowFlags f) + : PrefWidget(parent, f ) +{ + setupUi(this); + + // DVD device combo + // In windows, insert the drives letters +#ifdef Q_OS_WIN + QFileInfoList list = QDir::drives(); + for (int n = 0; n < list.size(); n++) { + QString s = list[n].filePath(); + if (isCDDevice(s)) { + if (s.endsWith("/")) s = s.remove( s.length()-1,1); + dvd_device_combo->addItem( s ); + cdrom_device_combo->addItem( s ); + } + } +#else + QDir dev_dir("/dev"); + QStringList devices = dev_dir.entryList( QStringList() << "dvd*" << "cdrom*" << "cdrw*" << "sr*" << "cdrecorder*", + QDir::Files | QDir::System | QDir::Readable); + for (int n=0; n < devices.count(); n++) { + QString device_name = "/dev/" + devices[n]; + qDebug("PrefDrives::PrefDrives: device found: '%s'", device_name.toUtf8().constData()); + dvd_device_combo->addItem(device_name); + cdrom_device_combo->addItem(device_name); + } +#endif + + retranslateStrings(); +} + +PrefDrives::~PrefDrives() +{ +} + +QString PrefDrives::sectionName() { + return tr("Drives"); +} + +QPixmap PrefDrives::sectionIcon() { + return Images::icon("pref_devices"); +} + + +void PrefDrives::retranslateStrings() { + retranslateUi(this); + + cdrom_drive_icon->setPixmap( Images::icon("cdrom_drive") ); + dvd_drive_icon->setPixmap( Images::icon("dvd_drive") ); + + createHelp(); +} + +void PrefDrives::setData(Preferences * pref) { + setDVDDevice( pref->dvd_device ); + setCDRomDevice( pref->cdrom_device ); +} + +void PrefDrives::getData(Preferences * pref) { + requires_restart = false; + + pref->dvd_device = dvdDevice(); + pref->cdrom_device = cdromDevice(); +} + +void PrefDrives::setDVDDevice( QString dir ) { + dvd_device_combo->setCurrentText( dir ); +} + +QString PrefDrives::dvdDevice() { + return dvd_device_combo->currentText(); +} + +void PrefDrives::setCDRomDevice( QString dir ) { + cdrom_device_combo->setCurrentText( dir ); +} + +QString PrefDrives::cdromDevice() { + return cdrom_device_combo->currentText(); +} + +void PrefDrives::createHelp() { + clearHelp(); + + setWhatsThis(cdrom_device_combo, tr("CD device"), + tr("Choose your CDROM device. It will be used to play " + "VCDs and Audio CDs.") ); + + setWhatsThis(dvd_device_combo, tr("DVD device"), + tr("Choose your DVD device. It will be used to play DVDs.") ); +} + +#include "moc_prefdrives.cpp" diff --git a/plugins/smplayer_plugin/prefdrives.h b/plugins/smplayer_plugin/prefdrives.h new file mode 100644 index 000000000..dfcf3ad4c --- /dev/null +++ b/plugins/smplayer_plugin/prefdrives.h @@ -0,0 +1,57 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFDRIVES_H_ +#define _PREFDRIVES_H_ + +#include "ui_prefdrives.h" +#include "prefwidget.h" + +class Preferences; + +class PrefDrives : public PrefWidget, public Ui::PrefDrives +{ + Q_OBJECT + +public: + PrefDrives( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefDrives(); + + virtual QString sectionName(); + virtual QPixmap sectionIcon(); + + // Pass data to the dialog + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + +protected: + virtual void createHelp(); + + void setDVDDevice( QString dir ); + QString dvdDevice(); + + void setCDRomDevice( QString dir ); + QString cdromDevice(); + +protected: + virtual void retranslateStrings(); +}; + +#endif diff --git a/plugins/smplayer_plugin/prefdrives.ui b/plugins/smplayer_plugin/prefdrives.ui new file mode 100644 index 000000000..c6a4ac63a --- /dev/null +++ b/plugins/smplayer_plugin/prefdrives.ui @@ -0,0 +1,254 @@ + + PrefDrives + + + + 0 + 0 + 531 + 489 + + + + + 0 + + + 0 + + + + + 0 + + + + Drives + + + + 9 + + + 6 + + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + Qt::AlignVCenter + + + true + + + + + + + 0 + + + 6 + + + + + icon + + + false + + + + + + + 0 + + + 6 + + + + + Select your &CD device: + + + false + + + cdrom_device_combo + + + + + + + + 5 + 0 + 0 + 0 + + + + true + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 366 + 70 + + + + + + + + + + + 7 + 0 + 0 + 0 + + + + QFrame::HLine + + + QFrame::Sunken + + + Qt::Horizontal + + + + + + + 0 + + + 6 + + + + + icon + + + false + + + + + + + 0 + + + 6 + + + + + Select your &DVD device: + + + false + + + dvd_device_combo + + + + + + + + 5 + 0 + 0 + 0 + + + + true + + + false + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 355 + 70 + + + + + + + + + + Qt::Vertical + + + + 231 + 171 + + + + + + + + + + + + + + MyComboBox + QComboBox +
    mycombobox.h
    +
    +
    + + tabWidget + cdrom_device_combo + dvd_device_combo + + + +
    diff --git a/plugins/smplayer_plugin/preferences.cpp b/plugins/smplayer_plugin/preferences.cpp new file mode 100644 index 000000000..2e5cbf81c --- /dev/null +++ b/plugins/smplayer_plugin/preferences.cpp @@ -0,0 +1,1197 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "preferences.h" +#include "global.h" +#include "paths.h" +#include "mediasettings.h" +#include "recents.h" +#include "urlhistory.h" + +#include +#include +#include +#include +#include +#include + +using namespace Global; + +Preferences::Preferences() { + history_recents = new Recents; + history_urls = new URLHistory; + + reset(); + +#ifndef NO_USE_INI_FILES + load(); +#endif +} + +Preferences::~Preferences() { +#ifndef NO_USE_INI_FILES + save(); +#endif + + delete history_recents; + delete history_urls; +} + +void Preferences::reset() { + /* ******* + General + ******* */ + +#ifdef Q_OS_WIN + mplayer_bin= "mplayer/mplayer.exe"; +#else + mplayer_bin = "mplayer"; +#endif + + vo = ""; + ao = ""; + + // On Windows Vista set vo to gl:yuv=2:force-pbo:ati-hack as default +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA) { + vo = "gl:yuv=2:force-pbo:ati-hack,"; + } +#endif + + screenshot_directory=""; +#ifndef PORTABLE_APP + if (QFile::exists(Paths::configPath() + "/screenshots")) { + screenshot_directory = Paths::configPath() + "/screenshots"; + } +#endif + + dont_remember_media_settings = false; + dont_remember_time_pos = false; + + audio_lang = ""; + subtitle_lang = ""; + + use_direct_rendering = false; + use_double_buffer = true; + disable_screensaver = true; + use_soft_video_eq = false; + use_slices = true; + autoq = 6; + add_blackborders_on_fullscreen = false; + + use_soft_vol = false; + softvol_max = 110; // 110 = default value in mplayer + use_scaletempo = Detect; + dont_change_volume = false; + use_hwac3 = false; + use_audio_equalizer = true; + use_volume_option = Detect; + + loop = false; + osd = None; + + file_settings_method = "normal"; // Possible values: normal & hash + + + /* *************** + Drives (CD/DVD) + *************** */ + + dvd_device = ""; + cdrom_device = ""; + +#ifndef Q_OS_WIN + // Try to set default values + if (QFile::exists("/dev/dvd")) dvd_device = "/dev/dvd"; + if (QFile::exists("/dev/cdrom")) cdrom_device = "/dev/cdrom"; +#endif + +#ifdef Q_OS_WIN + enable_audiocd_on_windows = false; +#endif + + vcd_initial_title = 2; // Most VCD's start at title #2 + + + /* *********** + Performance + *********** */ + + priority = AboveNormal; // Option only for windows + frame_drop = true; + hard_frame_drop = false; + autosync = false; + autosync_factor = 100; + + h264_skip_loop_filter = LoopEnabled; + HD_height = 720; + + // MPlayer 1.0rc1 require restart, new versions don't + fast_audio_change = Detect; +#if !SMART_DVD_CHAPTERS + fast_chapter_change = false; +#endif + + threads = 1; + + cache_for_files = 2000; + cache_for_streams = 1000; + cache_for_dvds = 0; // not recommended to use cache for dvds + cache_for_vcds = 1000; + cache_for_audiocds = 1000; + + + /* ********* + Subtitles + ********* */ + + font_file = ""; + font_name = ""; + use_fontconfig = false; + subcp = "ISO-8859-1"; + use_enca = false; + enca_lang = QString(QLocale::system().name()).section("_",0,0); + font_autoscale = 1; + subfuzziness = 1; + autoload_sub = true; + +#ifdef Q_OS_WIN + use_ass_subtitles = false; +#else + use_ass_subtitles = true; +#endif + + ass_line_spacing = 0; + + use_closed_caption_subs = false; + use_forced_subs_only = false; + + subtitles_on_screenshots = false; + + use_new_sub_commands = Detect; + change_sub_scale_should_restart = Detect; + + // ASS styles + // Nothing to do, default values are given in + // AssStyles constructor + + freetype_support = true; + + + /* ******** + Advanced + ******** */ + +#if USE_ADAPTER + adapter = -1; +#endif + +#if USE_COLORKEY + color_key = 0x020202; +#endif + + use_mplayer_window = false; + + monitor_aspect=""; // Autodetect + + use_idx = false; + + mplayer_additional_options=""; + mplayer_additional_video_filters=""; + mplayer_additional_audio_filters=""; + + log_mplayer = true; + log_smplayer = true; + log_filter = ".*"; + + //mplayer log autosaving + autosave_mplayer_log = false; + mplayer_log_saveto = ""; + //mplayer log autosaving end + +#if REPAINT_BACKGROUND_OPTION + // "Repaint video background" in the preferences dialog + #ifndef Q_OS_WIN + repaint_video_background = false; + #else + repaint_video_background = true; + #endif +#endif + + use_edl_files = true; + + prefer_ipv4 = true; + + use_short_pathnames = false; + + change_video_equalizer_on_startup = true; + + use_pausing_keep_force = true; + + use_correct_pts = false; + + actions_to_run = ""; + + + /* ********* + GUI stuff + ********* */ + + fullscreen = false; + start_in_fullscreen = false; + compact_mode = false; + stay_on_top = NeverOnTop; + size_factor = 100; // 100% + + resize_method = Always; + +#if STYLE_SWITCHING + style=""; +#endif + + show_frame_counter = FALSE; + show_motion_vectors = false; + + mouse_left_click_function = ""; + mouse_right_click_function = "show_context_menu"; + mouse_double_click_function = "fullscreen"; + mouse_middle_click_function = "mute"; + mouse_xbutton1_click_function = ""; + mouse_xbutton2_click_function = ""; + wheel_function = Seeking; + + seeking1 = 10; + seeking2 = 60; + seeking3 = 10*60; + seeking4 = 30; + + update_while_seeking = false; +#if ENABLE_DELAYED_DRAGGING + time_slider_drag_delay = 100; +#endif + + language = ""; + iconset = ""; + + balloon_count = 5; + +#ifdef Q_OS_WIN + restore_pos_after_fullscreen = true; +#else + restore_pos_after_fullscreen = false; +#endif + + save_window_size_on_exit = true; + + close_on_finish = false; + + default_font = ""; + + pause_when_hidden = false; + + allow_video_movement = false; + + gui = "DefaultGui"; + +#if USE_MINIMUMSIZE + gui_minimum_width = 0; // 0 == disabled +#endif + default_size = QSize(580, 440); + +#if ALLOW_TO_HIDE_VIDEO_WINDOW_ON_AUDIO_FILES + hide_video_window_on_audio_files = true; +#endif + + report_mplayer_crashes = true; + +#if REPORT_OLD_MPLAYER + reported_mplayer_is_old = false; +#endif + + auto_add_to_playlist = true; + add_to_playlist_consecutive_files = false; + + + /* *********** + Directories + *********** */ + + latest_dir = QDir::homePath(); + last_dvd_directory=""; + + + /* ************** + Initial values + ************** */ + + initial_sub_scale = 5; + initial_sub_scale_ass = 1; + initial_volume = 40; + initial_contrast = 0; + initial_brightness = 0; + initial_hue = 0; + initial_saturation = 0; + initial_gamma = 0; + + initial_audio_equalizer << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; + + initial_panscan_factor = 1.0; + initial_sub_pos = 100; // 100% + + initial_postprocessing = false; + initial_volnorm = false; + + initial_deinterlace = MediaSettings::NoDeinterlace; + + initial_audio_channels = MediaSettings::ChDefault; + initial_stereo_mode = MediaSettings::Stereo; + + initial_audio_track = 1; + initial_subtitle_track = 1; + + + /* ************ + MPlayer info + ************ */ + + mplayer_detected_version = -1; //None version parsed yet + mplayer_user_supplied_version = -1; + + + /* ********* + Instances + ********* */ + +#ifdef Q_OS_WIN + // Some people reported smplayer doesn't start with this option enabled + // So now it's disabled by default on Windows + use_single_instance = false; +#else + use_single_instance = true; +#endif + use_autoport = true; + connection_port = 8000; + autoport = 0; + + + /* **************** + Floating control + **************** */ + + floating_control_margin = 0; + floating_control_width = 100; //100 % + floating_control_animated = true; + floating_display_in_compact_mode = false; +#ifndef Q_OS_WIN + bypass_window_manager = true; +#endif + + + /* ***** + Proxy + ***** */ + + use_proxy = false; + proxy_type = QNetworkProxy::HttpProxy; + proxy_host = ""; + proxy_port = 0; + proxy_username = ""; + proxy_password = ""; + + + /* ******* + History + ******* */ + + history_recents->clear(); + history_urls->clear(); +} + +#ifndef NO_USE_INI_FILES +void Preferences::save() { + qDebug("Preferences::save"); + + QSettings * set = settings; + + + /* ******* + General + ******* */ + + set->beginGroup( "general"); + + set->setValue("mplayer_bin", mplayer_bin); + set->setValue("driver/vo", vo); + set->setValue("driver/ao", ao); + + set->setValue("screenshot_directory", screenshot_directory); + + set->setValue("dont_remember_media_settings", dont_remember_media_settings); + set->setValue("dont_remember_time_pos", dont_remember_time_pos); + + set->setValue("audio_lang", audio_lang); + set->setValue("subtitle_lang", subtitle_lang); + + set->setValue("use_direct_rendering", use_direct_rendering); + set->setValue("use_double_buffer", use_double_buffer); + set->setValue("disable_screensaver", disable_screensaver); + set->setValue("use_soft_video_eq", use_soft_video_eq); + set->setValue("use_slices", use_slices ); + set->setValue("autoq", autoq); + set->setValue("add_blackborders_on_fullscreen", add_blackborders_on_fullscreen); + + set->setValue("use_soft_vol", use_soft_vol); + set->setValue("softvol_max", softvol_max); + set->setValue("use_scaletempo", use_scaletempo); + set->setValue("dont_change_volume", dont_change_volume ); + set->setValue("use_hwac3", use_hwac3 ); + set->setValue("use_audio_equalizer", use_audio_equalizer ); + set->setValue("use_volume_option", use_volume_option); + + set->setValue("loop", loop); + set->setValue("osd", osd); + + set->setValue("file_settings_method", file_settings_method); + + set->endGroup(); // general + + + /* *************** + Drives (CD/DVD) + *************** */ + + set->beginGroup( "drives"); + + set->setValue("dvd_device", dvd_device); + set->setValue("cdrom_device", cdrom_device); + +#ifdef Q_OS_WIN + set->setValue("enable_audiocd_on_windows", enable_audiocd_on_windows); +#endif + + set->setValue("vcd_initial_title", vcd_initial_title); + + set->endGroup(); // drives + + + /* *********** + Performance + *********** */ + + set->beginGroup( "performance"); + + set->setValue("priority", priority); + set->setValue("frame_drop", frame_drop); + set->setValue("hard_frame_drop", hard_frame_drop); + set->setValue("autosync", autosync); + set->setValue("autosync_factor", autosync_factor); + + set->setValue("h264_skip_loop_filter", h264_skip_loop_filter); + set->setValue("HD_height", HD_height); + + set->setValue("fast_audio_change", fast_audio_change); +#if !SMART_DVD_CHAPTERS + set->setValue("fast_chapter_change", fast_chapter_change); +#endif + + set->setValue("threads", threads); + + set->setValue("cache_for_files", cache_for_files); + set->setValue("cache_for_streams", cache_for_streams); + set->setValue("cache_for_dvds", cache_for_dvds); + set->setValue("cache_for_vcds", cache_for_vcds); + set->setValue("cache_for_audiocds", cache_for_audiocds); + + set->endGroup(); // performance + + + /* ********* + Subtitles + ********* */ + + set->beginGroup("subtitles"); + + set->setValue("font_file", font_file); + set->setValue("font_name", font_name); + + set->setValue("use_fontconfig", use_fontconfig); + set->setValue("subcp", subcp); + set->setValue("use_enca", use_enca); + set->setValue("enca_lang", enca_lang); + set->setValue("font_autoscale", font_autoscale); + set->setValue("subfuzziness", subfuzziness); + set->setValue("autoload_sub", autoload_sub); + + set->setValue("use_ass_subtitles", use_ass_subtitles); + set->setValue("ass_line_spacing", ass_line_spacing); + set->setValue("use_closed_caption_subs", use_closed_caption_subs); + set->setValue("use_forced_subs_only", use_forced_subs_only); + + set->setValue("subtitles_on_screenshots", subtitles_on_screenshots); + + set->setValue("use_new_sub_commands", use_new_sub_commands); + set->setValue("change_sub_scale_should_restart", change_sub_scale_should_restart); + + // ASS styles + ass_styles.save(set); + + set->setValue("freetype_support", freetype_support); + + set->endGroup(); // subtitles + + + /* ******** + Advanced + ******** */ + + set->beginGroup( "advanced"); + +#if USE_ADAPTER + set->setValue("adapter", adapter); +#endif + +#if USE_COLORKEY + set->setValue("color_key", QString::number(color_key,16)); +#endif + + set->setValue("use_mplayer_window", use_mplayer_window); + + set->setValue("monitor_aspect", monitor_aspect); + + set->setValue("use_idx", use_idx); + + set->setValue("mplayer_additional_options", mplayer_additional_options); + set->setValue("mplayer_additional_video_filters", mplayer_additional_video_filters); + set->setValue("mplayer_additional_audio_filters", mplayer_additional_audio_filters); + + set->setValue("log_mplayer", log_mplayer); + set->setValue("log_smplayer", log_smplayer); + set->setValue("log_filter", log_filter); + + //mplayer log autosaving + set->setValue("autosave_mplayer_log", autosave_mplayer_log); + set->setValue("mplayer_log_saveto", mplayer_log_saveto); + //mplayer log autosaving end + +#if REPAINT_BACKGROUND_OPTION + set->setValue("repaint_video_background", repaint_video_background); +#endif + + set->setValue("use_edl_files", use_edl_files); + + set->setValue("prefer_ipv4", prefer_ipv4); + + set->setValue("use_short_pathnames", use_short_pathnames); + + set->setValue("change_video_equalizer_on_startup", change_video_equalizer_on_startup); + + set->setValue("use_pausing_keep_force", use_pausing_keep_force); + + set->setValue("use_correct_pts", use_correct_pts); + + set->setValue("actions_to_run", actions_to_run); + + set->endGroup(); // advanced + + + /* ********* + GUI stuff + ********* */ + + set->beginGroup("gui"); + + set->setValue("fullscreen", fullscreen); + set->setValue("start_in_fullscreen", start_in_fullscreen); + + set->setValue("compact_mode", compact_mode); + set->setValue("stay_on_top", (int) stay_on_top); + set->setValue("size_factor", size_factor); + set->setValue("resize_method", resize_method); + +#if STYLE_SWITCHING + set->setValue("style", style); +#endif + + set->setValue("show_frame_counter", show_frame_counter); + set->setValue("show_motion_vectors", show_motion_vectors); + + set->setValue("mouse_left_click_function", mouse_left_click_function); + set->setValue("mouse_right_click_function", mouse_right_click_function); + set->setValue("mouse_double_click_function", mouse_double_click_function); + set->setValue("mouse_middle_click_function", mouse_middle_click_function); + set->setValue("mouse_xbutton1_click_function", mouse_xbutton1_click_function); + set->setValue("mouse_xbutton2_click_function", mouse_xbutton2_click_function); + set->setValue("wheel_function", wheel_function); + + set->setValue("seeking1", seeking1); + set->setValue("seeking2", seeking2); + set->setValue("seeking3", seeking3); + set->setValue("seeking4", seeking4); + + set->setValue("update_while_seeking", update_while_seeking); +#if ENABLE_DELAYED_DRAGGING + set->setValue("time_slider_drag_delay", time_slider_drag_delay); +#endif + + set->setValue("language", language); + set->setValue("iconset", iconset); + + set->setValue("balloon_count", balloon_count); + + set->setValue("restore_pos_after_fullscreen", restore_pos_after_fullscreen); + set->setValue("save_window_size_on_exit", save_window_size_on_exit); + + set->setValue("close_on_finish", close_on_finish); + + set->setValue("default_font", default_font); + + set->setValue("pause_when_hidden", pause_when_hidden); + + set->setValue("allow_video_movement", allow_video_movement); + + set->setValue("gui", gui); + +#if USE_MINIMUMSIZE + set->setValue("gui_minimum_width", gui_minimum_width); +#endif + set->setValue("default_size", default_size); + +#if ALLOW_TO_HIDE_VIDEO_WINDOW_ON_AUDIO_FILES + set->setValue("hide_video_window_on_audio_files", hide_video_window_on_audio_files); +#endif + + set->setValue("report_mplayer_crashes", report_mplayer_crashes); + +#if REPORT_OLD_MPLAYER + set->setValue("reported_mplayer_is_old", reported_mplayer_is_old); +#endif + + set->setValue("auto_add_to_playlist", auto_add_to_playlist); + set->setValue("add_to_playlist_consecutive_files", add_to_playlist_consecutive_files); + + set->endGroup(); // gui + + + /* *********** + Directories + *********** */ + + set->beginGroup( "directories"); + set->setValue("latest_dir", latest_dir); + set->setValue("last_dvd_directory", last_dvd_directory); + set->endGroup(); // directories + + + /* ************** + Initial values + ************** */ + + set->beginGroup( "defaults"); + + set->setValue("initial_sub_scale", initial_sub_scale); + set->setValue("initial_sub_scale_ass", initial_sub_scale_ass); + set->setValue("initial_volume", initial_volume); + set->setValue("initial_contrast", initial_contrast); + set->setValue("initial_brightness", initial_brightness); + set->setValue("initial_hue", initial_hue); + set->setValue("initial_saturation", initial_saturation); + set->setValue("initial_gamma", initial_gamma); + + set->setValue("initial_audio_equalizer", initial_audio_equalizer); + + set->setValue("initial_panscan_factor", initial_panscan_factor); + set->setValue("initial_sub_pos", initial_sub_pos); + + set->setValue("initial_volnorm", initial_volnorm); + set->setValue("initial_postprocessing", initial_postprocessing); + + set->setValue("initial_deinterlace", initial_deinterlace); + + set->setValue("initial_audio_channels", initial_audio_channels); + set->setValue("initial_stereo_mode", initial_stereo_mode); + + set->setValue("initial_audio_track", initial_audio_track); + set->setValue("initial_subtitle_track", initial_subtitle_track); + + set->endGroup(); // defaults + + + /* ************ + MPlayer info + ************ */ + + set->beginGroup( "mplayer_info"); + set->setValue("mplayer_detected_version", mplayer_detected_version); + set->setValue("mplayer_user_supplied_version", mplayer_user_supplied_version); + set->endGroup(); // mplayer_info + + + /* ********* + Instances + ********* */ + + set->beginGroup("instances"); + set->setValue("use_single_instance", use_single_instance); + set->setValue("connection_port", connection_port); + set->setValue("use_autoport", use_autoport); + set->setValue("temp/autoport", autoport); + set->endGroup(); // instances + + + /* **************** + Floating control + **************** */ + + set->beginGroup("floating_control"); + set->setValue("margin", floating_control_margin); + set->setValue("width", floating_control_width); + set->setValue("animated", floating_control_animated); + set->setValue("display_in_compact_mode", floating_display_in_compact_mode); +#ifndef Q_OS_WIN + set->setValue("bypass_window_manager", bypass_window_manager); +#endif + set->endGroup(); // floating_control + + + /* ***** + Proxy + ***** */ + + set->beginGroup("proxy"); + set->setValue("use_proxy", use_proxy); + set->setValue("proxy_type", proxy_type); + set->setValue("host", proxy_host); + set->setValue("port", proxy_port); + set->setValue("username", proxy_username); + set->setValue("password", proxy_password); + set->endGroup(); // proxy + + + /* ******* + History + ******* */ + + set->beginGroup("history"); + set->setValue("recents", history_recents->toStringList()); + set->setValue("recents/max_items", history_recents->maxItems()); + set->setValue("urls", history_urls->toStringList()); + set->setValue("urls/max_items", history_urls->maxItems()); + set->endGroup(); // history + + set->sync(); +} + +void Preferences::load() { + qDebug("Preferences::load"); + + QSettings * set = settings; + + + /* ******* + General + ******* */ + + set->beginGroup( "general"); + + mplayer_bin = set->value("mplayer_bin", mplayer_bin).toString(); + vo = set->value("driver/vo", vo).toString(); + ao = set->value("driver/ao", ao).toString(); + + screenshot_directory = set->value("screenshot_directory", screenshot_directory).toString(); + + dont_remember_media_settings = set->value("dont_remember_media_settings", dont_remember_media_settings).toBool(); + dont_remember_time_pos = set->value("dont_remember_time_pos", dont_remember_time_pos).toBool(); + + audio_lang = set->value("audio_lang", audio_lang).toString(); + subtitle_lang = set->value("subtitle_lang", subtitle_lang).toString(); + + use_direct_rendering = set->value("use_direct_rendering", use_direct_rendering).toBool(); + use_double_buffer = set->value("use_double_buffer", use_double_buffer).toBool(); + disable_screensaver = set->value("disable_screensaver", disable_screensaver).toBool(); + use_soft_video_eq = set->value("use_soft_video_eq", use_soft_video_eq).toBool(); + use_slices = set->value("use_slices", use_slices ).toBool(); + autoq = set->value("autoq", autoq).toInt(); + add_blackborders_on_fullscreen = set->value("add_blackborders_on_fullscreen", add_blackborders_on_fullscreen).toBool(); + + use_soft_vol = set->value("use_soft_vol", use_soft_vol).toBool(); + softvol_max = set->value("softvol_max", softvol_max).toInt(); + use_scaletempo = (OptionState) set->value("use_scaletempo", use_scaletempo).toInt(); + dont_change_volume = set->value("dont_change_volume", dont_change_volume ).toBool(); + use_hwac3 = set->value("use_hwac3", use_hwac3 ).toBool(); + use_audio_equalizer = set->value("use_audio_equalizer", use_audio_equalizer ).toBool(); + use_volume_option = (OptionState) set->value("use_volume_option", use_volume_option).toInt(); + + loop = set->value("loop", loop).toBool(); + osd = set->value("osd", osd).toInt(); + + file_settings_method = set->value("file_settings_method", file_settings_method).toString(); + + set->endGroup(); // general + + + /* *************** + Drives (CD/DVD) + *************** */ + + set->beginGroup( "drives"); + + dvd_device = set->value("dvd_device", dvd_device).toString(); + cdrom_device = set->value("cdrom_device", cdrom_device).toString(); + +#ifdef Q_OS_WIN + enable_audiocd_on_windows = set->value("enable_audiocd_on_windows", enable_audiocd_on_windows).toBool(); +#endif + + vcd_initial_title = set->value("vcd_initial_title", vcd_initial_title ).toInt(); + + set->endGroup(); // drives + + + /* *********** + Performance + *********** */ + + set->beginGroup( "performance"); + + priority = set->value("priority", priority).toInt(); + frame_drop = set->value("frame_drop", frame_drop).toBool(); + hard_frame_drop = set->value("hard_frame_drop", hard_frame_drop).toBool(); + autosync = set->value("autosync", autosync).toBool(); + autosync_factor = set->value("autosync_factor", autosync_factor).toInt(); + + h264_skip_loop_filter = (H264LoopFilter) set->value("h264_skip_loop_filter", h264_skip_loop_filter).toInt(); + HD_height = set->value("HD_height", HD_height).toInt(); + + fast_audio_change = (OptionState) set->value("fast_audio_change", fast_audio_change).toInt(); +#if !SMART_DVD_CHAPTERS + fast_chapter_change = set->value("fast_chapter_change", fast_chapter_change).toBool(); +#endif + + threads = set->value("threads", threads).toInt(); + + cache_for_files = set->value("cache_for_files", cache_for_files).toInt(); + cache_for_streams = set->value("cache_for_streams", cache_for_streams).toInt(); + cache_for_dvds = set->value("cache_for_dvds", cache_for_dvds).toInt(); + cache_for_vcds = set->value("cache_for_vcds", cache_for_vcds).toInt(); + cache_for_audiocds = set->value("cache_for_audiocds", cache_for_audiocds).toInt(); + + set->endGroup(); // performance + + + /* ********* + Subtitles + ********* */ + + set->beginGroup("subtitles"); + + font_file = set->value("font_file", font_file).toString(); + font_name = set->value("font_name", font_name).toString(); + + use_fontconfig = set->value("use_fontconfig", use_fontconfig).toBool(); + subcp = set->value("subcp", subcp).toString(); + use_enca = set->value("use_enca", use_enca).toBool(); + enca_lang = set->value("enca_lang", enca_lang).toString(); + font_autoscale = set->value("font_autoscale", font_autoscale).toInt(); + subfuzziness = set->value("subfuzziness", subfuzziness).toInt(); + autoload_sub = set->value("autoload_sub", autoload_sub).toBool(); + + use_ass_subtitles = set->value("use_ass_subtitles", use_ass_subtitles).toBool(); + ass_line_spacing = set->value("ass_line_spacing", ass_line_spacing).toInt(); + + use_closed_caption_subs = set->value("use_closed_caption_subs", use_closed_caption_subs).toBool(); + use_forced_subs_only = set->value("use_forced_subs_only", use_forced_subs_only).toBool(); + + subtitles_on_screenshots = set->value("subtitles_on_screenshots", subtitles_on_screenshots).toBool(); + + use_new_sub_commands = (OptionState) set->value("use_new_sub_commands", use_new_sub_commands).toInt(); + change_sub_scale_should_restart = (OptionState) set->value("change_sub_scale_should_restart", change_sub_scale_should_restart).toInt(); + + // ASS styles + ass_styles.load(set); + + freetype_support = set->value("freetype_support", freetype_support).toBool(); + + set->endGroup(); // subtitles + + + /* ******** + Advanced + ******** */ + + set->beginGroup( "advanced"); + +#if USE_ADAPTER + adapter = set->value("adapter", adapter).toInt(); +#endif + +#if USE_COLORKEY + bool ok; + QString color = set->value("color_key", QString::number(color_key,16)).toString(); + unsigned int temp_color_key = color.toUInt(&ok, 16); + if (ok) + color_key = temp_color_key; + //color_key = set->value("color_key", color_key).toInt(); +#endif + + use_mplayer_window = set->value("use_mplayer_window", use_mplayer_window).toBool(); + + monitor_aspect = set->value("monitor_aspect", monitor_aspect).toString(); + + use_idx = set->value("use_idx", use_idx).toBool(); + + mplayer_additional_options = set->value("mplayer_additional_options", mplayer_additional_options).toString(); + mplayer_additional_video_filters = set->value("mplayer_additional_video_filters", mplayer_additional_video_filters).toString(); + mplayer_additional_audio_filters = set->value("mplayer_additional_audio_filters", mplayer_additional_audio_filters).toString(); + + log_mplayer = set->value("log_mplayer", log_mplayer).toBool(); + log_smplayer = set->value("log_smplayer", log_smplayer).toBool(); + log_filter = set->value("log_filter", log_filter).toString(); + + //mplayer log autosaving + autosave_mplayer_log = set->value("autosave_mplayer_log", autosave_mplayer_log).toBool(); + mplayer_log_saveto = set->value("mplayer_log_saveto", mplayer_log_saveto).toString(); + //mplayer log autosaving end + +#if REPAINT_BACKGROUND_OPTION + repaint_video_background = set->value("repaint_video_background", repaint_video_background).toBool(); +#endif + + use_edl_files = set->value("use_edl_files", use_edl_files).toBool(); + + prefer_ipv4 = set->value("prefer_ipv4", prefer_ipv4).toBool(); + + use_short_pathnames = set->value("use_short_pathnames", use_short_pathnames).toBool(); + + use_pausing_keep_force = set->value("use_pausing_keep_force", use_pausing_keep_force).toBool(); + + use_correct_pts = set->value("use_correct_pts", use_correct_pts).toBool(); + + actions_to_run = set->value("actions_to_run", actions_to_run).toString(); + + set->endGroup(); // advanced + + + /* ********* + GUI stuff + ********* */ + + set->beginGroup("gui"); + + fullscreen = set->value("fullscreen", fullscreen).toBool(); + start_in_fullscreen = set->value("start_in_fullscreen", start_in_fullscreen).toBool(); + + compact_mode = set->value("compact_mode", compact_mode).toBool(); + stay_on_top = (Preferences::OnTop) set->value("stay_on_top", (int) stay_on_top).toInt(); + size_factor = set->value("size_factor", size_factor).toInt(); + resize_method = set->value("resize_method", resize_method).toInt(); + +#if STYLE_SWITCHING + style = set->value("style", style).toString(); +#endif + + show_frame_counter = set->value("show_frame_counter", show_frame_counter).toBool(); + show_motion_vectors = set->value("show_motion_vectors", show_motion_vectors).toBool(); + + mouse_left_click_function = set->value("mouse_left_click_function", mouse_left_click_function).toString(); + mouse_right_click_function = set->value("mouse_right_click_function", mouse_right_click_function).toString(); + mouse_double_click_function = set->value("mouse_double_click_function", mouse_double_click_function).toString(); + mouse_middle_click_function = set->value("mouse_middle_click_function", mouse_middle_click_function).toString(); + mouse_xbutton1_click_function = set->value("mouse_xbutton1_click_function", mouse_xbutton1_click_function).toString(); + mouse_xbutton2_click_function = set->value("mouse_xbutton2_click_function", mouse_xbutton2_click_function).toString(); + wheel_function = set->value("wheel_function", wheel_function).toInt(); + + seeking1 = set->value("seeking1", seeking1).toInt(); + seeking2 = set->value("seeking2", seeking2).toInt(); + seeking3 = set->value("seeking3", seeking3).toInt(); + seeking4 = set->value("seeking4", seeking4).toInt(); + + update_while_seeking = set->value("update_while_seeking", update_while_seeking).toBool(); +#if ENABLE_DELAYED_DRAGGING + time_slider_drag_delay = set->value("time_slider_drag_delay", time_slider_drag_delay).toInt(); +#endif + + language = set->value("language", language).toString(); + iconset= set->value("iconset", iconset).toString(); + + balloon_count = set->value("balloon_count", balloon_count).toInt(); + + restore_pos_after_fullscreen = set->value("restore_pos_after_fullscreen", restore_pos_after_fullscreen).toBool(); + save_window_size_on_exit = set->value("save_window_size_on_exit", save_window_size_on_exit).toBool(); + + close_on_finish = set->value("close_on_finish", close_on_finish).toBool(); + + default_font = set->value("default_font", default_font).toString(); + + pause_when_hidden = set->value("pause_when_hidden", pause_when_hidden).toBool(); + + allow_video_movement = set->value("allow_video_movement", allow_video_movement).toBool(); + + gui = set->value("gui", gui).toString(); + +#if USE_MINIMUMSIZE + gui_minimum_width = set->value("gui_minimum_width", gui_minimum_width).toInt(); +#endif + default_size = set->value("default_size", default_size).toSize(); + +#if ALLOW_TO_HIDE_VIDEO_WINDOW_ON_AUDIO_FILES + hide_video_window_on_audio_files = set->value("hide_video_window_on_audio_files", hide_video_window_on_audio_files).toBool(); +#endif + + report_mplayer_crashes = set->value("report_mplayer_crashes", report_mplayer_crashes).toBool(); + +#if REPORT_OLD_MPLAYER + reported_mplayer_is_old = set->value("reported_mplayer_is_old", reported_mplayer_is_old).toBool(); +#endif + + auto_add_to_playlist = set->value("auto_add_to_playlist", auto_add_to_playlist).toBool(); + add_to_playlist_consecutive_files = set->value("add_to_playlist_consecutive_files", add_to_playlist_consecutive_files).toBool(); + + set->endGroup(); // gui + + + /* *********** + Directories + *********** */ + + set->beginGroup( "directories"); + latest_dir = set->value("latest_dir", latest_dir).toString(); + last_dvd_directory = set->value("last_dvd_directory", last_dvd_directory).toString(); + set->endGroup(); // directories + + + /* ************** + Initial values + ************** */ + + set->beginGroup( "defaults"); + + initial_sub_scale = set->value("initial_sub_scale", initial_sub_scale).toDouble(); + initial_sub_scale_ass = set->value("initial_sub_scale_ass", initial_sub_scale_ass).toDouble(); + initial_volume = set->value("initial_volume", initial_volume).toInt(); + initial_contrast = set->value("initial_contrast", initial_contrast).toInt(); + initial_brightness = set->value("initial_brightness", initial_brightness).toInt(); + initial_hue = set->value("initial_hue", initial_hue).toInt(); + initial_saturation = set->value("initial_saturation", initial_saturation).toInt(); + initial_gamma = set->value("initial_gamma", initial_gamma).toInt(); + + initial_audio_equalizer = set->value("initial_audio_equalizer", initial_audio_equalizer).toList(); + + initial_panscan_factor = set->value("initial_panscan_factor", initial_panscan_factor).toDouble(); + initial_sub_pos = set->value("initial_sub_pos", initial_sub_pos).toInt(); + + initial_volnorm = set->value("initial_volnorm", initial_volnorm).toBool(); + initial_postprocessing = set->value("initial_postprocessing", initial_postprocessing).toBool(); + + initial_deinterlace = set->value("initial_deinterlace", initial_deinterlace).toInt(); + + initial_audio_channels = set->value("initial_audio_channels", initial_audio_channels).toInt(); + initial_stereo_mode = set->value("initial_stereo_mode", initial_stereo_mode).toInt(); + + initial_audio_track = set->value("initial_audio_track", initial_audio_track).toInt(); + initial_subtitle_track = set->value("initial_subtitle_track", initial_subtitle_track).toInt(); + + set->endGroup(); // defaults + + + /* ************ + MPlayer info + ************ */ + + set->beginGroup( "mplayer_info"); + mplayer_detected_version = set->value("mplayer_detected_version", mplayer_detected_version).toInt(); + mplayer_user_supplied_version = set->value("mplayer_user_supplied_version", mplayer_user_supplied_version).toInt(); + set->endGroup(); // mplayer_info + + + /* ********* + Instances + ********* */ + + set->beginGroup("instances"); + use_single_instance = set->value("use_single_instance", use_single_instance).toBool(); + connection_port = set->value("connection_port", connection_port).toInt(); + use_autoport = set->value("use_autoport", use_autoport).toBool(); + autoport = set->value("temp/autoport", autoport).toInt(); + set->endGroup(); // instances + + + /* **************** + Floating control + **************** */ + + set->beginGroup("floating_control"); + floating_control_margin = set->value("margin", floating_control_margin).toInt(); + floating_control_width = set->value("width", floating_control_width).toInt(); + floating_control_animated = set->value("animated", floating_control_animated).toBool(); + floating_display_in_compact_mode = set->value("display_in_compact_mode", floating_display_in_compact_mode).toBool(); +#ifndef Q_OS_WIN + bypass_window_manager = set->value("bypass_window_manager", bypass_window_manager).toBool(); +#endif + set->endGroup(); // floating_control + + + /* ***** + Proxy + ***** */ + + set->beginGroup("proxy"); + use_proxy = set->value("use_proxy", use_proxy).toBool(); + proxy_type = set->value("proxy_type", proxy_type).toInt(); + proxy_host = set->value("host", proxy_host).toString(); + proxy_port = set->value("port", proxy_port).toInt(); + proxy_username = set->value("username", proxy_username).toString(); + proxy_password = set->value("password", proxy_password).toString(); + set->endGroup(); // proxy + + + /* ******* + History + ******* */ + + set->beginGroup("history"); + history_recents->fromStringList( set->value("recents", history_recents->toStringList()).toStringList() ); + history_recents->setMaxItems( set->value("recents/max_items", history_recents->maxItems()).toInt() );; + history_urls->fromStringList( set->value("urls", history_urls->toStringList()).toStringList() ); + history_urls->setMaxItems( set->value("urls/max_items", history_urls->maxItems()).toInt() );; + set->endGroup(); // history +} + +#endif // NO_USE_INI_FILES + +double Preferences::monitor_aspect_double() { + qDebug("Preferences::monitor_aspect_double"); + + QRegExp exp("(\\d+)[:/](\\d+)"); + if (exp.indexIn( monitor_aspect ) != -1) { + int w = exp.cap(1).toInt(); + int h = exp.cap(2).toInt(); + qDebug(" monitor_aspect parsed successfully: %d:%d", w, h); + return (double) w/h; + } + + bool ok; + double res = monitor_aspect.toDouble(&ok); + if (ok) { + qDebug(" monitor_aspect parsed successfully: %f", res); + return res; + } else { + qDebug(" warning: monitor_aspect couldn't be parsed!"); + qDebug(" monitor_aspect set to 0"); + return 0; + } +} diff --git a/plugins/smplayer_plugin/preferences.h b/plugins/smplayer_plugin/preferences.h new file mode 100644 index 000000000..5edc51758 --- /dev/null +++ b/plugins/smplayer_plugin/preferences.h @@ -0,0 +1,423 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _PREFERENCES_H_ +#define _PREFERENCES_H_ + +/* Global settings */ + +#include +#include +#include +#include "config.h" +#include "audioequalizerlist.h" +#include "assstyles.h" + +class Recents; +class URLHistory; + +class Preferences { + +public: + enum OSD { None = 0, Seek = 1, SeekTimer = 2, SeekTimerTotal = 3 }; + enum OnTop { NeverOnTop = 0, AlwaysOnTop = 1, WhilePlayingOnTop = 2 }; + enum Resize { Never = 0, Always = 1, Afterload = 2 }; + enum Priority { Realtime = 0, High = 1, AboveNormal = 2, Normal = 3, + BelowNormal = 4, Idle = 5 }; + enum WheelFunction { Seeking = 0, Volume = 1, Zoom = 2, DoNothing = 3, + ChangeSpeed = 4 }; + enum OptionState { Detect = -1, Disabled = 0, Enabled = 1 }; + enum H264LoopFilter { LoopDisabled = 0, LoopEnabled = 1, LoopDisabledOnHD = 2 }; + + Preferences(); + virtual ~Preferences(); + + virtual void reset(); + +#ifndef NO_USE_INI_FILES + void save(); + void load(); +#endif + + double monitor_aspect_double(); + + + + /* ******* + General + ******* */ + + QString mplayer_bin; + QString vo; // video output + QString ao; // audio output + + QString screenshot_directory; + + // SMPlayer will remember all media settings for all videos. + // This options allow to disable it: + bool dont_remember_media_settings; // Will not remember anything + bool dont_remember_time_pos; // Will not remember time pos + + QString audio_lang; // Preferred audio language + QString subtitle_lang; // Preferred subtitle language + + // Video + bool use_direct_rendering; + bool use_double_buffer; + bool disable_screensaver; + bool use_soft_video_eq; + bool use_slices; + int autoq; //!< Postprocessing quality + bool add_blackborders_on_fullscreen; + + // Audio + bool use_soft_vol; + int softvol_max; + OptionState use_scaletempo; + bool dont_change_volume; // Don't change volume on startup + bool use_hwac3; // -afm hwac3 + bool use_audio_equalizer; + OptionState use_volume_option; //!< Use -volume in command line + + // Misc + bool loop; //!< Loop. If true repeat the file + int osd; + + QString file_settings_method; //!< Method to be used for saving file settings + + + /* *************** + Drives (CD/DVD) + *************** */ + + QString dvd_device; + QString cdrom_device; + +#ifdef Q_OS_WIN + bool enable_audiocd_on_windows; +#endif + + int vcd_initial_title; + + + /* *********** + Performance + *********** */ + + int priority; + bool frame_drop; + bool hard_frame_drop; + bool autosync; + int autosync_factor; + + H264LoopFilter h264_skip_loop_filter; + int HD_height; //!< An HD is a video which height is equal or greater than this. + + OptionState fast_audio_change; // If activated, not restart mplayer +#if !SMART_DVD_CHAPTERS + bool fast_chapter_change; +#endif + + int threads; //!< number of threads to use for decoding (-lavdopts threads <1-8>) + + int cache_for_files; + int cache_for_streams; + int cache_for_dvds; + int cache_for_vcds; + int cache_for_audiocds; + + + /* ********* + Subtitles + ********* */ + + QString font_file; + QString font_name; + bool use_fontconfig; + QString subcp; // -subcp + bool use_enca; + QString enca_lang; + int font_autoscale; // -subfont-autoscale + int subfuzziness; + bool autoload_sub; + + bool use_ass_subtitles; + int ass_line_spacing; + + bool use_closed_caption_subs; + bool use_forced_subs_only; + + bool subtitles_on_screenshots; + + //! Use the new sub_vob, sub_demux and sub_file commands + //! instead of sub_select + OptionState use_new_sub_commands; + OptionState change_sub_scale_should_restart; + + // ASS styles + AssStyles ass_styles; + + //! If false, options requiring freetype won't be used + bool freetype_support; + + + /* ******** + Advanced + ******** */ + +#if USE_ADAPTER + int adapter; //Screen for overlay. If -1 it won't be used. +#endif + +#if USE_COLORKEY + unsigned int color_key; +#endif + + bool use_mplayer_window; + + QString monitor_aspect; + + bool use_idx; //!< Use -idx + + // Let the user pass options to mplayer + QString mplayer_additional_options; + QString mplayer_additional_video_filters; + QString mplayer_additional_audio_filters; + + // Logs + bool log_mplayer; + bool log_smplayer; + QString log_filter; + + //mplayer log autosaving + bool autosave_mplayer_log; + QString mplayer_log_saveto; + //mplayer log autosaving end + +#if REPAINT_BACKGROUND_OPTION + //! If true, mplayerlayer erases its background + bool repaint_video_background; +#endif + + //! If true it will autoload edl files with the same name of the file + //! to play + bool use_edl_files; + + //! Preferred connection method: ipv4 or ipv6 + bool prefer_ipv4; + + //! Windows only. If true, smplayer will pass short filenames to mplayer. + //! To workaround a bug in mplayer. + bool use_short_pathnames; + + //! If false, -brightness, -contrast and so on, won't be passed to + //! mplayer. It seems that some graphic cards don't support those options. + bool change_video_equalizer_on_startup; + + //! If true, smplayer will use the prefix pausing_keep_force to keep + //! the pause on slave commands. This experimental prefix was added + //! in mplayer svn r27665. + bool use_pausing_keep_force; + + bool use_correct_pts; //!< Pass -correct-pts to mplayer + + QString actions_to_run; //!< List of actions to run every time a video loads. + + + /* ********* + GUI stuff + ********* */ + + bool fullscreen; + bool start_in_fullscreen; + bool compact_mode; + OnTop stay_on_top; + int size_factor; + + int resize_method; //!< Mainwindow resize method + +#if STYLE_SWITCHING + QString style; //!< SMPlayer look +#endif + bool show_frame_counter; + bool show_motion_vectors; + + // Function of mouse buttons: + QString mouse_left_click_function; + QString mouse_right_click_function; + QString mouse_double_click_function; + QString mouse_middle_click_function; + QString mouse_xbutton1_click_function; + QString mouse_xbutton2_click_function; + int wheel_function; + + // Configurable seeking + int seeking1; // By default 10s + int seeking2; // By default 1m + int seeking3; // By default 10m + int seeking4; // For mouse wheel, by default 30s + + bool update_while_seeking; +#if ENABLE_DELAYED_DRAGGING + int time_slider_drag_delay; +#endif + + QString language; + QString iconset; + + //! Number of times to show the balloon remembering that the program + //! is still running in the system tray. + int balloon_count; + + //! If true, the position of the main window will be saved before + //! entering in fullscreen and will restore when going back to + //! window mode. + bool restore_pos_after_fullscreen; + + bool save_window_size_on_exit; + + //! Close the main window when a file or playlist finish + bool close_on_finish; + + QString default_font; + + //!< Pause the current file when the main window is not visible + bool pause_when_hidden; + + //!< Allow frre movement of the video window + bool allow_video_movement; + + QString gui; //!< The name of the GUI to use + +#if USE_MINIMUMSIZE + int gui_minimum_width; +#endif + QSize default_size; // Default size of the main window + +#if ALLOW_TO_HIDE_VIDEO_WINDOW_ON_AUDIO_FILES + bool hide_video_window_on_audio_files; +#endif + + bool report_mplayer_crashes; + +#if REPORT_OLD_MPLAYER + bool reported_mplayer_is_old; +#endif + + bool auto_add_to_playlist; //!< Add files to open to playlist + bool add_to_playlist_consecutive_files; + + + /* *********** + Directories + *********** */ + + QString latest_dir; //!< Directory of the latest file loaded + QString last_dvd_directory; + + + /* ************** + Initial values + ************** */ + + double initial_sub_scale; + double initial_sub_scale_ass; + int initial_volume; + int initial_contrast; + int initial_brightness; + int initial_hue; + int initial_saturation; + int initial_gamma; + + AudioEqualizerList initial_audio_equalizer; + + //! Default value for panscan (1.0 = no zoom) + double initial_panscan_factor; + + //! Default value for position of subtitles on screen + //! 100 = 100% at the bottom + int initial_sub_pos; + + bool initial_postprocessing; //!< global postprocessing filter + bool initial_volnorm; + + int initial_deinterlace; + + int initial_audio_channels; + int initial_stereo_mode; + + int initial_audio_track; + int initial_subtitle_track; + + + /* ************ + MPlayer info + ************ */ + + int mplayer_detected_version; //!< Latest version of mplayer parsed + + //! Version of mplayer supplied by the user which will be used if + //! the version can't be parsed from mplayer output + int mplayer_user_supplied_version; + + + /* ********* + Instances + ********* */ + + bool use_single_instance; + int connection_port; // Manual port + bool use_autoport; + int autoport; // Port automatically chosen by Qt + + + /* **************** + Floating control + **************** */ + + int floating_control_margin; + int floating_control_width; + bool floating_control_animated; + bool floating_display_in_compact_mode; +#ifndef Q_OS_WIN + bool bypass_window_manager; +#endif + + + /* ***** + Proxy + ***** */ + + bool use_proxy; + int proxy_type; + QString proxy_host; + int proxy_port; + QString proxy_username; + QString proxy_password; + + + /* ******* + History + ******* */ + + Recents * history_recents; + URLHistory * history_urls; +}; + +#endif diff --git a/plugins/smplayer_plugin/preferencesdialog.cpp b/plugins/smplayer_plugin/preferencesdialog.cpp new file mode 100644 index 000000000..bfc74cb72 --- /dev/null +++ b/plugins/smplayer_plugin/preferencesdialog.cpp @@ -0,0 +1,221 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "preferencesdialog.h" + +#include "prefwidget.h" +#include "prefgeneral.h" +#include "prefdrives.h" +#include "prefinterface.h" +#include "prefperformance.h" +#include "prefinput.h" +#include "prefsubtitles.h" +#include "prefadvanced.h" +#include "prefplaylist.h" + +#if USE_ASSOCIATIONS +#include "prefassociations.h" +#endif + +#include "preferences.h" + +#include +#include + +#include "images.h" + +PreferencesDialog::PreferencesDialog(QWidget * parent, Qt::WindowFlags f) + : QDialog(parent, f ) +{ + setupUi(this); + + // Setup buttons + okButton = buttonBox->button(QDialogButtonBox::Ok); + cancelButton = buttonBox->button(QDialogButtonBox::Cancel); + applyButton = buttonBox->button(QDialogButtonBox::Apply); + helpButton = buttonBox->button(QDialogButtonBox::Help); + connect( applyButton, SIGNAL(clicked()), this, SLOT(apply()) ); + connect( helpButton, SIGNAL(clicked()), this, SLOT(showHelp()) ); + + + setWindowIcon( Images::icon("logo") ); + + help_window = new QTextBrowser(this); + help_window->setWindowFlags(Qt::Window); + help_window->resize(300, 450); + //help_window->adjustSize(); + help_window->setWindowTitle( tr("SMPlayer - Help") ); + help_window->setWindowIcon( Images::icon("logo") ); + + page_general = new PrefGeneral; + addSection( page_general ); + + page_drives = new PrefDrives; + addSection( page_drives ); + + page_performance = new PrefPerformance; + addSection( page_performance ); + + page_subtitles = new PrefSubtitles; + addSection( page_subtitles ); + + page_interface = new PrefInterface; + addSection( page_interface ); + + page_input = new PrefInput; + addSection( page_input ); + + page_playlist = new PrefPlaylist; + addSection( page_playlist ); + +#if USE_ASSOCIATIONS + page_associations = new PrefAssociations; + addSection(page_associations); +#endif + + page_advanced = new PrefAdvanced; + addSection( page_advanced ); + + sections->setCurrentRow(General); + + //adjustSize(); + retranslateStrings(); +} + +PreferencesDialog::~PreferencesDialog() +{ +} + +void PreferencesDialog::showSection(Section s) { + qDebug("PreferencesDialog::showSection: %d", s); + + sections->setCurrentRow(s); +} + +void PreferencesDialog::retranslateStrings() { + retranslateUi(this); + + for (int n=0; n < pages->count(); n++) { + PrefWidget * w = (PrefWidget*) pages->widget(n); + sections->item(n)->setText( w->sectionName() ); + sections->item(n)->setIcon( w->sectionIcon() ); + } + + if (help_window->isVisible()) { + // Makes the help to retranslate + showHelp(); + } + + help_window->setWindowTitle( tr("SMPlayer - Help") ); + + // Qt 4.2 doesn't update the buttons' text +#if QT_VERSION < 0x040300 + okButton->setText( tr("OK") ); + cancelButton->setText( tr("Cancel") ); + applyButton->setText( tr("Apply") ); + helpButton->setText( tr("Help") ); +#endif +} + +void PreferencesDialog::accept() { + hide(); + help_window->hide(); + setResult( QDialog::Accepted ); + emit applied(); +} + +void PreferencesDialog::apply() { + setResult( QDialog::Accepted ); + emit applied(); +} + +void PreferencesDialog::reject() { + hide(); + help_window->hide(); + setResult( QDialog::Rejected ); + + setResult( QDialog::Accepted ); +} + +void PreferencesDialog::addSection(PrefWidget *w) { + QListWidgetItem *i = new QListWidgetItem( w->sectionIcon(), w->sectionName() ); + sections->addItem( i ); + pages->addWidget(w); +} + +void PreferencesDialog::setData(Preferences * pref) { + page_general->setData(pref); + page_drives->setData(pref); + page_interface->setData(pref); + page_performance->setData(pref); + page_input->setData(pref); + page_subtitles->setData(pref); + page_advanced->setData(pref); + page_playlist->setData(pref); + +#if USE_ASSOCIATIONS + page_associations->setData(pref); +#endif +} + +void PreferencesDialog::getData(Preferences * pref) { + page_general->getData(pref); + page_drives->getData(pref); + page_interface->getData(pref); + page_performance->getData(pref); + page_input->getData(pref); + page_subtitles->getData(pref); + page_advanced->getData(pref); + page_playlist->getData(pref); + +#if USE_ASSOCIATIONS + page_associations->getData(pref); +#endif +} + +bool PreferencesDialog::requiresRestart() { + bool need_restart = page_general->requiresRestart(); + if (!need_restart) need_restart = page_drives->requiresRestart(); + if (!need_restart) need_restart = page_interface->requiresRestart(); + if (!need_restart) need_restart = page_performance->requiresRestart(); + if (!need_restart) need_restart = page_input->requiresRestart(); + if (!need_restart) need_restart = page_subtitles->requiresRestart(); + if (!need_restart) need_restart = page_advanced->requiresRestart(); + if (!need_restart) need_restart = page_playlist->requiresRestart(); + + return need_restart; +} + +void PreferencesDialog::showHelp() { + PrefWidget * w = (PrefWidget*) pages->currentWidget(); + help_window->setHtml( w->help() ); + help_window->show(); + help_window->raise(); +} + +// Language change stuff +void PreferencesDialog::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QDialog::changeEvent(e); + } +} + +#include "moc_preferencesdialog.cpp" diff --git a/plugins/smplayer_plugin/preferencesdialog.h b/plugins/smplayer_plugin/preferencesdialog.h new file mode 100644 index 000000000..8b22d2846 --- /dev/null +++ b/plugins/smplayer_plugin/preferencesdialog.h @@ -0,0 +1,114 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFERENCESDIALOG_H_ +#define _PREFERENCESDIALOG_H_ + +#include "ui_preferencesdialog.h" + +/* +#ifdef Q_OS_WIN +#define USE_ASSOCIATIONS 1 +#endif +*/ + +class QTextBrowser; +class QPushButton; + +class PrefWidget; +class PrefGeneral; +class PrefDrives; +class PrefPerformance; +class PrefSubtitles; +class PrefInterface; +class PrefInput; +class PrefAdvanced; +class PrefPlaylist; +class PrefAssociations; + +class Preferences; + + +class PreferencesDialog : public QDialog, public Ui::PreferencesDialog +{ + Q_OBJECT + +public: + enum Section { General=0, Drives=1, Performance=2, + Subtitles=3, Gui=4, Mouse=5, Advanced=6, Associations=7 }; + + PreferencesDialog( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PreferencesDialog(); + + PrefGeneral * mod_general() { return page_general; }; + PrefInterface * mod_interface() { return page_interface; }; + PrefInput * mod_input() { return page_input; }; + PrefAdvanced * mod_advanced() { return page_advanced; }; + + void addSection(PrefWidget *w); + + // Pass data to the standard dialogs + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + + // Return true if the mplayer process should be restarted. + bool requiresRestart(); + +public slots: + void showSection(Section s); + + virtual void accept(); // Reimplemented to send a signal + virtual void reject(); + +signals: + void applied(); + +protected: + virtual void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + +protected slots: + void apply(); + void showHelp(); + +protected: + PrefGeneral * page_general; + PrefDrives * page_drives; + PrefPerformance * page_performance; + PrefSubtitles * page_subtitles; + PrefInterface * page_interface; + PrefInput * page_input; + PrefPlaylist * page_playlist; + PrefAdvanced * page_advanced; + +#if USE_ASSOCIATIONS + PrefAssociations* page_associations; +#endif + + QTextBrowser * help_window; + +private: + QPushButton * okButton; + QPushButton * cancelButton; + QPushButton * applyButton; + QPushButton * helpButton; +}; + +#endif diff --git a/plugins/smplayer_plugin/preferencesdialog.ui b/plugins/smplayer_plugin/preferencesdialog.ui new file mode 100644 index 000000000..10b175fb5 --- /dev/null +++ b/plugins/smplayer_plugin/preferencesdialog.ui @@ -0,0 +1,118 @@ + + PreferencesDialog + + + + 0 + 0 + 532 + 425 + + + + SMPlayer - Preferences + + + + 9 + + + 6 + + + + + + 7 + 5 + 0 + 0 + + + + -1 + + + + + + + + 3 + 7 + 0 + 0 + + + + + 150 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + sections + currentRowChanged(int) + pages + setCurrentIndex(int) + + + 145 + 202 + + + 372 + 231 + + + + + buttonBox + accepted() + PreferencesDialog + accept() + + + 259 + 401 + + + 259 + 212 + + + + + buttonBox + rejected() + PreferencesDialog + reject() + + + 259 + 401 + + + 259 + 212 + + + + + diff --git a/plugins/smplayer_plugin/prefgeneral.cpp b/plugins/smplayer_plugin/prefgeneral.cpp new file mode 100644 index 000000000..36eca9fcd --- /dev/null +++ b/plugins/smplayer_plugin/prefgeneral.cpp @@ -0,0 +1,891 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "prefgeneral.h" +#include "preferences.h" +#include "filedialog.h" +#include "images.h" +#include "mediasettings.h" +#include "paths.h" + +#if USE_ALSA_DEVICES || USE_DSOUND_DEVICES +#include "deviceinfo.h" +#endif + +PrefGeneral::PrefGeneral(QWidget * parent, Qt::WindowFlags f) + : PrefWidget(parent, f ) +{ + setupUi(this); + + mplayerbin_edit->setDialogType(FileChooser::GetFileName); + screenshot_edit->setDialogType(FileChooser::GetDirectory); + + // Read driver info from InfoReader: + InfoReader * i = InfoReader::obj(); + vo_list = i->voList(); + ao_list = i->aoList(); + +#if USE_DSOUND_DEVICES + dsound_devices = DeviceInfo::dsoundDevices(); +#endif + +#if USE_ALSA_DEVICES + alsa_devices = DeviceInfo::alsaDevices(); +#endif +#if USE_XV_ADAPTORS + xv_adaptors = DeviceInfo::xvAdaptors(); +#endif + + // Channels combo + channels_combo->addItem( "2", MediaSettings::ChStereo ); + channels_combo->addItem( "4", MediaSettings::ChSurround ); + channels_combo->addItem( "6", MediaSettings::ChFull51 ); + + connect(vo_combo, SIGNAL(currentIndexChanged(int)), + this, SLOT(vo_combo_changed(int))); + connect(ao_combo, SIGNAL(currentIndexChanged(int)), + this, SLOT(ao_combo_changed(int))); + + retranslateStrings(); +} + +PrefGeneral::~PrefGeneral() +{ +} + +QString PrefGeneral::sectionName() { + return tr("General"); +} + +QPixmap PrefGeneral::sectionIcon() { + return Images::icon("pref_general"); +} + +void PrefGeneral::retranslateStrings() { + retranslateUi(this); + + initial_volume_label->setNum( initial_volume_slider->value() ); + + channels_combo->setItemText(0, tr("2 (Stereo)") ); + channels_combo->setItemText(1, tr("4 (4.0 Surround)") ); + channels_combo->setItemText(2, tr("6 (5.1 Surround)") ); + + int deinterlace_item = deinterlace_combo->currentIndex(); + deinterlace_combo->clear(); + deinterlace_combo->addItem( tr("None"), MediaSettings::NoDeinterlace ); + deinterlace_combo->addItem( tr("Lowpass5"), MediaSettings::L5 ); + deinterlace_combo->addItem( tr("Yadif (normal)"), MediaSettings::Yadif ); + deinterlace_combo->addItem( tr("Yadif (double framerate)"), MediaSettings::Yadif_1 ); + deinterlace_combo->addItem( tr("Linear Blend"), MediaSettings::LB ); + deinterlace_combo->addItem( tr("Kerndeint"), MediaSettings::Kerndeint ); + deinterlace_combo->setCurrentIndex(deinterlace_item); + + int filesettings_method_item = filesettings_method_combo->currentIndex(); + filesettings_method_combo->clear(); + filesettings_method_combo->addItem( tr("one ini file"), "normal"); + filesettings_method_combo->addItem( tr("multiple ini files"), "hash"); + filesettings_method_combo->setCurrentIndex(filesettings_method_item); + + updateDriverCombos(); + + // Icons + /* + resize_window_icon->setPixmap( Images::icon("resize_window") ); + volume_icon->setPixmap( Images::icon("speaker") ); + */ + + mplayerbin_edit->setCaption(tr("Select the mplayer executable")); +#ifdef Q_OS_WIN + mplayerbin_edit->setFilter(tr("Executables") +" (*.exe)"); +#else + mplayerbin_edit->setFilter(tr("All files") +" (*)"); +#endif + screenshot_edit->setCaption(tr("Select a directory")); + + preferred_desc->setText( + tr("Here you can type your preferred language for the audio " + "and subtitle streams. When a media with multiple audio or " + "subtitle streams is found, SMPlayer will try to use your " + "preferred language. This only will work with media that offer " + "info about the language of audio and subtitle streams, like DVDs " + "or mkv files.
    These fields accept regular expressions. " + "Example: es|esp|spa will select the track if it matches with " + "es, esp or spa.")); + + createHelp(); +} + +void PrefGeneral::setData(Preferences * pref) { + setMplayerPath( pref->mplayer_bin ); + setScreenshotDir( pref->screenshot_directory ); + + QString vo = pref->vo; + if (vo.isEmpty()) { +#ifdef Q_OS_WIN + vo = "directx,"; +#else + vo = "xv,"; +#endif + } + setVO( vo ); + + QString ao = pref->ao; +#ifndef Q_OS_WIN + if (ao.isEmpty()) ao = "alsa,"; +#endif + setAO( ao ); + + setRememberSettings( !pref->dont_remember_media_settings ); + setRememberTimePos( !pref->dont_remember_time_pos ); + setFileSettingsMethod( pref->file_settings_method ); + setAudioLang( pref->audio_lang ); + setSubtitleLang( pref->subtitle_lang ); + setAudioTrack( pref->initial_audio_track ); + setSubtitleTrack( pref->initial_subtitle_track ); + setCloseOnFinish( pref->close_on_finish ); + setPauseWhenHidden( pref->pause_when_hidden ); + + setEq2( pref->use_soft_video_eq ); + setUseAudioEqualizer( pref->use_audio_equalizer ); + setSoftVol( pref->use_soft_vol ); + setAc3DTSPassthrough( pref->use_hwac3 ); + setInitialVolNorm( pref->initial_volnorm ); + setAmplification( pref->softvol_max ); + setInitialPostprocessing( pref->initial_postprocessing ); + setInitialDeinterlace( pref->initial_deinterlace ); + setInitialZoom( pref->initial_panscan_factor ); + setDirectRendering( pref->use_direct_rendering ); + setDoubleBuffer( pref->use_double_buffer ); + setUseSlices( pref->use_slices ); + setStartInFullscreen( pref->start_in_fullscreen ); + setDisableScreensaver( pref->disable_screensaver ); + setBlackbordersOnFullscreen( pref->add_blackborders_on_fullscreen ); + setAutoq( pref->autoq ); + + setInitialVolume( pref->initial_volume ); + setDontChangeVolume( pref->dont_change_volume ); + setUseVolume( pref->use_volume_option ); + setAudioChannels( pref->initial_audio_channels ); + setScaleTempoFilter( pref->use_scaletempo ); +} + +void PrefGeneral::getData(Preferences * pref) { + requires_restart = false; + filesettings_method_changed = false; + + if (pref->mplayer_bin != mplayerPath()) { + requires_restart = true; + pref->mplayer_bin = mplayerPath(); + + qDebug("PrefGeneral::getData: mplayer binary has changed, getting version number"); + // Forces to get info from mplayer to update version number + InfoReader i( pref->mplayer_bin ); + i.getInfo(); + // Update the drivers list at the same time + //setDrivers( i.voList(), i.aoList() ); + } + + TEST_AND_SET(pref->screenshot_directory, screenshotDir()); + TEST_AND_SET(pref->vo, VO()); + TEST_AND_SET(pref->ao, AO()); + + bool dont_remember_ms = !rememberSettings(); + TEST_AND_SET(pref->dont_remember_media_settings, dont_remember_ms); + bool dont_remember_time = !rememberTimePos(); + TEST_AND_SET(pref->dont_remember_time_pos, dont_remember_time); + if (pref->file_settings_method != fileSettingsMethod()) { + pref->file_settings_method = fileSettingsMethod(); + filesettings_method_changed = true; + } + + pref->audio_lang = audioLang(); + pref->subtitle_lang = subtitleLang(); + + pref->initial_audio_track = audioTrack(); + pref->initial_subtitle_track = subtitleTrack(); + + pref->close_on_finish = closeOnFinish(); + pref->pause_when_hidden = pauseWhenHidden(); + + TEST_AND_SET(pref->use_soft_video_eq, eq2()); + TEST_AND_SET(pref->use_soft_vol, softVol()); + TEST_AND_SET(pref->use_audio_equalizer, useAudioEqualizer()); + TEST_AND_SET(pref->use_hwac3, Ac3DTSPassthrough()); + pref->initial_volnorm = initialVolNorm(); + TEST_AND_SET(pref->softvol_max, amplification()); + pref->initial_postprocessing = initialPostprocessing(); + pref->initial_deinterlace = initialDeinterlace(); + pref->initial_panscan_factor = initialZoom(); + TEST_AND_SET(pref->use_direct_rendering, directRendering()); + TEST_AND_SET(pref->use_double_buffer, doubleBuffer()); + TEST_AND_SET(pref->use_slices, useSlices()); + pref->start_in_fullscreen = startInFullscreen(); + TEST_AND_SET(pref->disable_screensaver, disableScreensaver()); + if (pref->add_blackborders_on_fullscreen != blackbordersOnFullscreen()) { + pref->add_blackborders_on_fullscreen = blackbordersOnFullscreen(); + if (pref->fullscreen) requires_restart = true; + } + TEST_AND_SET(pref->autoq, autoq()); + + pref->initial_volume = initialVolume(); + pref->dont_change_volume = dontChangeVolume(); + pref->use_volume_option = useVolume(); + pref->initial_audio_channels = audioChannels(); + TEST_AND_SET(pref->use_scaletempo, scaleTempoFilter()); +} + +void PrefGeneral::updateDriverCombos() { + int vo_current = vo_combo->currentIndex(); + int ao_current = ao_combo->currentIndex(); + + vo_combo->clear(); + ao_combo->clear(); + + QString vo; + for ( int n = 0; n < vo_list.count(); n++ ) { + vo = vo_list[n].name(); +#ifdef Q_OS_WIN + if ( vo == "directx" ) { + vo_combo->addItem( "directx (" + tr("fast") + ")", "directx" ); + vo_combo->addItem( "directx (" + tr("slow") + ")", "directx:noaccel" ); + } + else +#else + /* + if (vo == "xv") vo_combo->addItem( "xv (" + tr("fastest") + ")", vo); + else + */ +#if USE_XV_ADAPTORS + if ((vo == "xv") && (!xv_adaptors.isEmpty())) { + vo_combo->addItem(vo, vo); + for (int n=0; n < xv_adaptors.count(); n++) { + vo_combo->addItem( "xv (" + xv_adaptors[n].ID().toString() + " - " + xv_adaptors[n].desc() + ")", + "xv:adaptor=" + xv_adaptors[n].ID().toString() ); + } + } + else +#endif // USE_XV_ADAPTORS +#endif + if (vo == "x11") vo_combo->addItem( "x11 (" + tr("slow") + ")", vo); + else + if (vo == "gl") { + vo_combo->addItem( vo, vo); + vo_combo->addItem( "gl (" + tr("fast") + ")", "gl:yuv=2:force-pbo"); + vo_combo->addItem( "gl (" + tr("fast - ATI cards") + ")", "gl:yuv=2:force-pbo:ati-hack"); + vo_combo->addItem( "gl (yuv)", "gl:yuv=3"); + } + else + if (vo == "gl2") { + vo_combo->addItem( vo, vo); + vo_combo->addItem( "gl2 (yuv)", "gl2:yuv=3"); + } + else + if (vo == "null" || vo == "png" || vo == "jpeg" || vo == "gif89a" || + vo == "tga" || vo == "pnm" || vo == "md5sum" ) + { + ; // Nothing to do + } + else + vo_combo->addItem( vo, vo ); + } + vo_combo->addItem( tr("User defined..."), "user_defined" ); + + QString ao; + for ( int n = 0; n < ao_list.count(); n++) { + ao = ao_list[n].name(); + ao_combo->addItem( ao, ao ); +#if USE_ALSA_DEVICES + if ((ao == "alsa") && (!alsa_devices.isEmpty())) { + for (int n=0; n < alsa_devices.count(); n++) { + ao_combo->addItem( "alsa (" + alsa_devices[n].ID().toString() + " - " + alsa_devices[n].desc() + ")", + "alsa:device=hw=" + alsa_devices[n].ID().toString() ); + } + } +#endif +#if USE_DSOUND_DEVICES + if ((ao == "dsound") && (!dsound_devices.isEmpty())) { + for (int n=0; n < dsound_devices.count(); n++) { + ao_combo->addItem( "dsound (" + dsound_devices[n].ID().toString() + " - " + dsound_devices[n].desc() + ")", + "dsound:device=" + dsound_devices[n].ID().toString() ); + } + } +#endif + } + ao_combo->addItem( tr("User defined..."), "user_defined" ); + + vo_combo->setCurrentIndex( vo_current ); + ao_combo->setCurrentIndex( ao_current ); +} + +void PrefGeneral::setMplayerPath( QString path ) { + mplayerbin_edit->setText( path ); +} + +QString PrefGeneral::mplayerPath() { + return mplayerbin_edit->text(); +} + +void PrefGeneral::setScreenshotDir( QString path ) { + screenshot_edit->setText( path ); +} + +QString PrefGeneral::screenshotDir() { + return screenshot_edit->text(); +} + +void PrefGeneral::setVO( QString vo_driver ) { + int idx = vo_combo->findData( vo_driver ); + if (idx != -1) { + vo_combo->setCurrentIndex(idx); + } else { + vo_combo->setCurrentIndex(vo_combo->findData("user_defined")); + vo_user_defined_edit->setText(vo_driver); + } + vo_combo_changed(vo_combo->currentIndex()); +} + +void PrefGeneral::setAO( QString ao_driver ) { + int idx = ao_combo->findData( ao_driver ); + if (idx != -1) { + ao_combo->setCurrentIndex(idx); + } else { + ao_combo->setCurrentIndex(ao_combo->findData("user_defined")); + ao_user_defined_edit->setText(ao_driver); + } + ao_combo_changed(ao_combo->currentIndex()); +} + +QString PrefGeneral::VO() { + QString vo = vo_combo->itemData(vo_combo->currentIndex()).toString(); + if (vo == "user_defined") { + vo = vo_user_defined_edit->text(); + if (vo.isEmpty()) { + vo = vo_combo->itemData(0).toString(); + qDebug("PrefGeneral::VO: user defined vo is empty, using %s", vo.toUtf8().constData()); + } + } + return vo; +} + +QString PrefGeneral::AO() { + QString ao = ao_combo->itemData(ao_combo->currentIndex()).toString(); + if (ao == "user_defined") { + ao = ao_user_defined_edit->text(); + if (ao.isEmpty()) { + ao = ao_combo->itemData(0).toString(); + qDebug("PrefGeneral::AO: user defined ao is empty, using %s", ao.toUtf8().constData()); + } + } + return ao; +} + +void PrefGeneral::setRememberSettings(bool b) { + remember_all_check->setChecked(b); + //rememberAllButtonToggled(b); +} + +bool PrefGeneral::rememberSettings() { + return remember_all_check->isChecked(); +} + +void PrefGeneral::setRememberTimePos(bool b) { + remember_time_check->setChecked(b); +} + +bool PrefGeneral::rememberTimePos() { + return remember_time_check->isChecked(); +} + +void PrefGeneral::setFileSettingsMethod(QString method) { + int index = filesettings_method_combo->findData(method); + if (index < 0) index = 0; + filesettings_method_combo->setCurrentIndex(index); +} + +QString PrefGeneral::fileSettingsMethod() { + return filesettings_method_combo->itemData(filesettings_method_combo->currentIndex()).toString(); +} + +void PrefGeneral::setAudioLang(QString lang) { + audio_lang_edit->setText(lang); +} + +QString PrefGeneral::audioLang() { + return audio_lang_edit->text(); +} + +void PrefGeneral::setSubtitleLang(QString lang) { + subtitle_lang_edit->setText(lang); +} + +QString PrefGeneral::subtitleLang() { + return subtitle_lang_edit->text(); +} + +void PrefGeneral::setAudioTrack(int track) { + audio_track_spin->setValue(track); +} + +int PrefGeneral::audioTrack() { + return audio_track_spin->value(); +} + +void PrefGeneral::setSubtitleTrack(int track) { + subtitle_track_spin->setValue(track); +} + +int PrefGeneral::subtitleTrack() { + return subtitle_track_spin->value(); +} + +void PrefGeneral::setCloseOnFinish(bool b) { + close_on_finish_check->setChecked(b); +} + +bool PrefGeneral::closeOnFinish() { + return close_on_finish_check->isChecked(); +} + +void PrefGeneral::setPauseWhenHidden(bool b) { + pause_if_hidden_check->setChecked(b); +} + +bool PrefGeneral::pauseWhenHidden() { + return pause_if_hidden_check->isChecked(); +} + + +void PrefGeneral::setEq2(bool b) { + eq2_check->setChecked(b); +} + +bool PrefGeneral::eq2() { + return eq2_check->isChecked(); +} + +void PrefGeneral::setSoftVol(bool b) { + softvol_check->setChecked(b); +} + +bool PrefGeneral::softVol() { + return softvol_check->isChecked(); +} + +void PrefGeneral::setUseAudioEqualizer(bool b) { + audio_equalizer_check->setChecked(b); +} + +bool PrefGeneral::useAudioEqualizer() { + return audio_equalizer_check->isChecked(); +} + +void PrefGeneral::setAc3DTSPassthrough(bool b) { + hwac3_check->setChecked(b); +} + +bool PrefGeneral::Ac3DTSPassthrough() { + return hwac3_check->isChecked(); +} + +void PrefGeneral::setInitialVolNorm(bool b) { + volnorm_check->setChecked(b); +} + +bool PrefGeneral::initialVolNorm() { + return volnorm_check->isChecked(); +} + +void PrefGeneral::setInitialPostprocessing(bool b) { + postprocessing_check->setChecked(b); +} + +bool PrefGeneral::initialPostprocessing() { + return postprocessing_check->isChecked(); +} + +void PrefGeneral::setInitialDeinterlace(int ID) { + int pos = deinterlace_combo->findData(ID); + if (pos != -1) { + deinterlace_combo->setCurrentIndex(pos); + } else { + qWarning("PrefGeneral::setInitialDeinterlace: ID: %d not found in combo", ID); + } +} + +int PrefGeneral::initialDeinterlace() { + if (deinterlace_combo->currentIndex() != -1) { + return deinterlace_combo->itemData( deinterlace_combo->currentIndex() ).toInt(); + } else { + qWarning("PrefGeneral::initialDeinterlace: no item selected"); + return 0; + } +} + +void PrefGeneral::setInitialZoom(double v) { + zoom_spin->setValue(v); +} + +double PrefGeneral::initialZoom() { + return zoom_spin->value(); +} + +void PrefGeneral::setDirectRendering(bool b) { + direct_rendering_check->setChecked(b); +} + +bool PrefGeneral::directRendering() { + return direct_rendering_check->isChecked(); +} + +void PrefGeneral::setDoubleBuffer(bool b) { + double_buffer_check->setChecked(b); +} + +bool PrefGeneral::doubleBuffer() { + return double_buffer_check->isChecked(); +} + +void PrefGeneral::setUseSlices(bool b) { + use_slices_check->setChecked(b); +} + +bool PrefGeneral::useSlices() { + return use_slices_check->isChecked(); +} + +void PrefGeneral::setAmplification(int n) { + softvol_max_spin->setValue(n); +} + +int PrefGeneral::amplification() { + return softvol_max_spin->value(); +} + +void PrefGeneral::setInitialVolume(int v) { + initial_volume_slider->setValue(v); +} + +int PrefGeneral::initialVolume() { + return initial_volume_slider->value(); +} + +void PrefGeneral::setAudioChannels(int ID) { + int pos = channels_combo->findData(ID); + if (pos != -1) { + channels_combo->setCurrentIndex(pos); + } else { + qWarning("PrefGeneral::setAudioChannels: ID: %d not found in combo", ID); + } +} + +int PrefGeneral::audioChannels() { + if (channels_combo->currentIndex() != -1) { + return channels_combo->itemData( channels_combo->currentIndex() ).toInt(); + } else { + qWarning("PrefGeneral::audioChannels: no item selected"); + return 0; + } +} + +void PrefGeneral::setDontChangeVolume(bool b) { + change_volume_check->setChecked(!b); +} + +bool PrefGeneral::dontChangeVolume() { + return !change_volume_check->isChecked(); +} + +void PrefGeneral::setUseVolume(Preferences::OptionState value) { + use_volume_combo->setState(value); +} + +Preferences::OptionState PrefGeneral::useVolume() { + return use_volume_combo->state(); +} + +void PrefGeneral::setStartInFullscreen(bool b) { + start_fullscreen_check->setChecked(b); +} + +bool PrefGeneral::startInFullscreen() { + return start_fullscreen_check->isChecked(); +} + +void PrefGeneral::setDisableScreensaver(bool b) { + screensaver_check->setChecked(b); +} + +bool PrefGeneral::disableScreensaver() { + return screensaver_check->isChecked(); +} + +void PrefGeneral::setBlackbordersOnFullscreen(bool b) { + blackborders_on_fs_check->setChecked(b); +} + +bool PrefGeneral::blackbordersOnFullscreen() { + return blackborders_on_fs_check->isChecked(); +} + +void PrefGeneral::setAutoq(int n) { + autoq_spin->setValue(n); +} + +int PrefGeneral::autoq() { + return autoq_spin->value(); +} + +void PrefGeneral::setScaleTempoFilter(Preferences::OptionState value) { + scaletempo_combo->setState(value); +} + +Preferences::OptionState PrefGeneral::scaleTempoFilter() { + return scaletempo_combo->state(); +} + +void PrefGeneral::vo_combo_changed(int idx) { + qDebug("PrefGeneral::vo_combo_changed: %d", idx); + bool visible = (vo_combo->itemData(idx).toString() == "user_defined"); + vo_user_defined_edit->setShown(visible); + vo_user_defined_edit->setFocus(); +} + +void PrefGeneral::ao_combo_changed(int idx) { + qDebug("PrefGeneral::ao_combo_changed: %d", idx); + bool visible = (ao_combo->itemData(idx).toString() == "user_defined"); + ao_user_defined_edit->setShown(visible); + ao_user_defined_edit->setFocus(); +} + +void PrefGeneral::createHelp() { + clearHelp(); + + addSectionTitle(tr("General")); + + setWhatsThis(mplayerbin_edit, tr("MPlayer executable"), + tr("Here you must specify the mplayer " + "executable that SMPlayer will use.
    " + "SMPlayer requires at least MPlayer 1.0rc1 (although a recent " + "revision from SVN is highly recommended).") + "
    " + + tr("If this setting is wrong, SMPlayer won't be able to play " + "anything!") + ""); + + setWhatsThis(screenshot_edit, tr("Screenshots folder"), + tr("Here you can specify a folder where the screenshots taken by " + "SMPlayer will be stored. If this field is empty the " + "screenshot feature will be disabled.") ); + + + setWhatsThis(remember_all_check, tr("Remember settings"), + tr("Usually SMPlayer will remember the settings for each file you " + "play (audio track selected, volume, filters...). Disable this " + "option if you don't like this feature.") ); + + setWhatsThis(remember_time_check, tr("Remember time position"), + tr("If you check this option, SMPlayer will remember the last position " + "of the file when you open it again. This option works only with " + "regular files (not with DVDs, CDs, URLs...).") ); + + setWhatsThis(filesettings_method_combo, tr("Method to store the file settings"), + tr("This option allows to change the way the file settings would be " + "stored. The following options are available:") +"
    • " + + tr("one ini file: the settings for all played files will be " + "saved in a single ini file (%1)").arg(QString(""+Paths::iniPath()+"/smplayer.ini")) + "
    • " + + tr("multiple ini files: one ini file will be used for each played file. " + "Those ini files will be saved in the folder %1").arg(QString(""+Paths::iniPath()+"/file_settings")) + "
    " + + tr("The latter method could be faster if there is info for a lot of files.") ); + + setWhatsThis(close_on_finish_check, tr("Close when finished"), + tr("If this option is checked, the main window will be automatically " + "closed when the current file/playlist finishes.") ); + + setWhatsThis(pause_if_hidden_check, tr("Pause when minimized"), + tr("If this option is enabled, the file will be paused when the " + "main window is hidden. When the window is restored, playback " + "will be resumed.") ); + + // Video tab + addSectionTitle(tr("Video")); + + setWhatsThis(vo_combo, tr("Video output driver"), + tr("Select the video output driver. %1 provides the best performance.") +#ifdef Q_OS_WIN + .arg("directx") +#else + .arg("xv") +#endif + ); + + setWhatsThis(postprocessing_check, tr("Enable postprocessing by default"), + tr("Postprocessing will be used by default on new opened files.") ); + + setWhatsThis(autoq_spin, tr("Postprocessing quality"), + tr("Dynamically changes the level of postprocessing depending on the " + "available spare CPU time. The number you specify will be the " + "maximum level used. Usually you can use some big number.") ); + + setWhatsThis(deinterlace_combo, tr("Deinterlace by default"), + tr("Select the deinterlace filter that you want to be used for new " + "videos opened.") ); + + setWhatsThis(zoom_spin, tr("Default zoom"), + tr("This option sets the default zoom which will be used for " + "new videos.") ); + + setWhatsThis(eq2_check, tr("Software video equalizer"), + tr("You can check this option if video equalizer is not supported by " + "your graphic card or the selected video output driver.
    " + "Note: this option can be incompatible with some video " + "output drivers.") ); + + setWhatsThis(direct_rendering_check, tr("Direct rendering"), + tr("If checked, turns on direct rendering (not supported by all " + "codecs and video outputs)
    " + "Warning: May cause OSD/SUB corruption!") ); + + setWhatsThis(double_buffer_check, tr("Double buffering"), + tr("Double buffering fixes flicker by storing two frames in memory, " + "and displaying one while decoding another. If disabled it can " + "affect OSD negatively, but often removes OSD flickering.") ); + + setWhatsThis(use_slices_check, tr("Draw video using slices"), + tr("Enable/disable drawing video by 16-pixel height slices/bands. " + "If disabled, the whole frame is drawn in a single run. " + "May be faster or slower, depending on video card and available " + "cache. It has effect only with libmpeg2 and libavcodec codecs.") ); + + setWhatsThis(start_fullscreen_check, tr("Start videos in fullscreen"), + tr("If this option is checked, all videos will start to play in " + "fullscreen mode.") ); + + setWhatsThis(blackborders_on_fs_check, tr("Add black borders on fullscreen"), + tr("If this option is enabled, black borders will be added to the " + "image in fullscreen mode. This allows subtitles to be displayed " + "on the black borders.") /* + "
    " + + tr("This option will be ignored if MPlayer uses its own window, as " + "some video drivers (like gl) are already able to display the " + "subtitles automatically in the black borders.") */ ); + + setWhatsThis(screensaver_check, tr("Disable screensaver"), + tr("Check this option to disable the screensaver while playing.
    " + "The screensaver will enabled again when play finishes.") + //+ tr("
    Note: This option works only in X11 and Windows.") + ); + + // Audio tab + addSectionTitle(tr("Audio")); + + setWhatsThis(ao_combo, tr("Audio output driver"), + tr("Select the audio output driver.") +#ifndef Q_OS_WIN + + " " + + tr("%1 is the recommended one. Try to avoid %2 and %3, they are slow " + "and can have an impact on performance.") + .arg("alsa") + .arg("esd") + .arg("arts") +#endif + ); + + setWhatsThis(audio_equalizer_check, tr("Enable the audio equalizer"), + tr("Check this option if you want to use the audio equalizer.") ); + + setWhatsThis(hwac3_check, tr("AC3/DTS pass-through S/PDIF"), + tr("Uses hardware AC3 passthrough") ); + + setWhatsThis(channels_combo, tr("Channels by default"), + tr("Requests the number of playback channels. MPlayer " + "asks the decoder to decode the audio into as many channels as " + "specified. Then it is up to the decoder to fulfill the " + "requirement. This is usually only important when playing " + "videos with AC3 audio (like DVDs). In that case liba52 does " + "the decoding by default and correctly downmixes the audio " + "into the requested number of channels. " + "Note: This option is honored by codecs (AC3 only), " + "filters (surround) and audio output drivers (OSS at least).") ); + + setWhatsThis(scaletempo_combo, tr("High speed playback without altering pitch"), + tr("Allows to change the playback speed without altering pitch. " + "Requires at least MPlayer dev-SVN-r24924.") ); + + setWhatsThis(softvol_check, tr("Software volume control"), + tr("Check this option to use the software mixer, instead of " + "using the sound card mixer.") ); + + setWhatsThis(softvol_max_spin, tr("Max. Amplification"), + tr("Sets the maximum amplification level in percent (default: 110). " + "A value of 200 will allow you to adjust the volume up to a " + "maximum of double the current level. With values below 100 the " + "initial volume (which is 100%) will be above the maximum, which " + "e.g. the OSD cannot display correctly.") ); + + setWhatsThis(volnorm_check, tr("Volume normalization by default"), + tr("Maximizes the volume without distorting the sound.") ); + + setWhatsThis(change_volume_check, tr("Change volume"), + tr("If checked, SMPlayer will remember the volume for every file " + "and will restore it when played again. For new files the default " + "volume will be used.") ); + + setWhatsThis(use_volume_combo, tr("Change volume just before playing"), + tr("If this option is checked the initial volume will be set just " + "before playback starts. This avoids a loud volume on startup. " + "Requires at least MPlayer SVN r27872.")); + + setWhatsThis(initial_volume_slider, tr("Default volume"), + tr("Sets the initial volume that new files will use.") ); + + + addSectionTitle(tr("Preferred audio and subtitles")); + + setWhatsThis(audio_lang_edit, tr("Preferred audio language"), + tr("Here you can type your preferred language for the audio streams. " + "When a media with multiple audio streams is found, SMPlayer will " + "try to use your preferred language.
    " + "This only will work with media that offer info about the language " + "of the audio streams, like DVDs or mkv files.
    " + "This field accepts regular expressions. Example: es|esp|spa " + "will select the audio track if it matches with es, " + "esp or spa.") ); + + setWhatsThis(subtitle_lang_edit, tr("Preferred subtitle language"), + tr("Here you can type your preferred language for the subtitle stream. " + "When a media with multiple subtitle streams is found, SMPlayer will " + "try to use your preferred language.
    " + "This only will work with media that offer info about the language " + "of the subtitle streams, like DVDs or mkv files.
    " + "This field accepts regular expressions. Example: es|esp|spa " + "will select the subtitle stream if it matches with es, " + "esp or spa.") ); + + setWhatsThis(audio_track_spin, tr("Audio track"), + tr("Specifies the default audio track which will be used when playing " + "new files. If the track doesn't exist, the first one will be used. " + "
    Note: the \"preferred audio language\" has " + "preference over this option.") ); + + setWhatsThis(subtitle_track_spin, tr("Subtitle track"), + tr("Specifies the default subtitle track which will be used when " + "playing new files. If the track doesn't exist, the first one " + "will be used.
    Note: the \"preferred subtitle " + "language\" has preference over this option.") ); + +} + +#include "moc_prefgeneral.cpp" diff --git a/plugins/smplayer_plugin/prefgeneral.h b/plugins/smplayer_plugin/prefgeneral.h new file mode 100644 index 000000000..31ce2ba03 --- /dev/null +++ b/plugins/smplayer_plugin/prefgeneral.h @@ -0,0 +1,190 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFGENERAL_H_ +#define _PREFGENERAL_H_ + +#include "ui_prefgeneral.h" +#include "prefwidget.h" +#include "inforeader.h" +#include "deviceinfo.h" +#include "preferences.h" + +#ifdef Q_OS_WIN +#define USE_DSOUND_DEVICES 1 +#else +#define USE_ALSA_DEVICES 1 +#define USE_XV_ADAPTORS 1 +#endif + +class PrefGeneral : public PrefWidget, public Ui::PrefGeneral +{ + Q_OBJECT + +public: + PrefGeneral( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefGeneral(); + + // Return the name of the section + virtual QString sectionName(); + // Return the icon of the section + virtual QPixmap sectionIcon(); + + // Pass data to the dialog + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + + bool fileSettingsMethodChanged() { return filesettings_method_changed; }; + +protected: + virtual void createHelp(); + + // Tab General + void setMplayerPath( QString path ); + QString mplayerPath(); + + void setScreenshotDir( QString path ); + QString screenshotDir(); + + void setVO( QString vo_driver ); + QString VO(); + + void setAO( QString ao_driver ); + QString AO(); + + void setRememberSettings(bool b); + bool rememberSettings(); + + void setRememberTimePos(bool b); + bool rememberTimePos(); + + void setFileSettingsMethod(QString method); + QString fileSettingsMethod(); + + void setAudioLang(QString lang); + QString audioLang(); + + void setSubtitleLang(QString lang); + QString subtitleLang(); + + void setAudioTrack(int track); + int audioTrack(); + + void setSubtitleTrack(int track); + int subtitleTrack(); + + void setCloseOnFinish(bool b); + bool closeOnFinish(); + + void setPauseWhenHidden(bool b); + bool pauseWhenHidden(); + + // Tab video and audio + void setEq2(bool b); + bool eq2(); + + void setStartInFullscreen(bool b); + bool startInFullscreen(); + + void setDisableScreensaver(bool b); + bool disableScreensaver(); + + void setBlackbordersOnFullscreen(bool b); + bool blackbordersOnFullscreen(); + + void setAutoq(int n); + int autoq(); + + void setSoftVol(bool b); + bool softVol(); + + void setUseAudioEqualizer(bool b); + bool useAudioEqualizer(); + + void setAc3DTSPassthrough(bool b); + bool Ac3DTSPassthrough(); + + void setInitialVolNorm(bool b); + bool initialVolNorm(); + + void setInitialPostprocessing(bool b); + bool initialPostprocessing(); + + void setInitialDeinterlace(int ID); + int initialDeinterlace(); + + void setInitialZoom(double v); + double initialZoom(); + + void setDirectRendering(bool b); + bool directRendering(); + + void setDoubleBuffer(bool b); + bool doubleBuffer(); + + void setUseSlices(bool b); + bool useSlices(); + + void setAmplification(int n); + int amplification(); + + void setInitialVolume(int v); + int initialVolume(); + + void setDontChangeVolume(bool b); + bool dontChangeVolume(); + + // Use -volume option + void setUseVolume(Preferences::OptionState value); + Preferences::OptionState useVolume(); + + void setAudioChannels(int ID); + int audioChannels(); + + void setScaleTempoFilter(Preferences::OptionState value); + Preferences::OptionState scaleTempoFilter(); + +protected slots: + void vo_combo_changed(int); + void ao_combo_changed(int); + +protected: + virtual void retranslateStrings(); + void updateDriverCombos(); + + InfoList vo_list; + InfoList ao_list; + +#if USE_DSOUND_DEVICES + DeviceList dsound_devices; +#endif + +#if USE_ALSA_DEVICES + DeviceList alsa_devices; +#endif +#if USE_XV_ADAPTORS + DeviceList xv_adaptors; +#endif + +private: + bool filesettings_method_changed; +}; + +#endif diff --git a/plugins/smplayer_plugin/prefgeneral.ui b/plugins/smplayer_plugin/prefgeneral.ui new file mode 100644 index 000000000..fd18454f2 --- /dev/null +++ b/plugins/smplayer_plugin/prefgeneral.ui @@ -0,0 +1,1464 @@ + + PrefGeneral + + + + 0 + 0 + 460 + 571 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + &General + + + + + + Paths + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Select the &MPlayer executable: + + + false + + + mplayerbin_edit + + + + + + + + + + &Folder for storing screenshots: + + + false + + + screenshot_edit + + + + + + + + + + + + + Media settings + + + + + + &Remember settings for all files (audio track, subtitles...) + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 61 + + + + + + + + false + + + + 0 + 0 + + + + Remember &time position + + + + + + + + + false + + + &Store settings in + + + filesettings_method_combo + + + + + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + &Close when finished playback + + + + + + + &Pause when minimized + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 438 + 51 + + + + + + + + + &Video + + + + + + + + Ou&tput driver: + + + false + + + vo_combo + + + + + + + + 0 + 0 + + + + false + + + + + + + + + + Qt::Horizontal + + + + 81 + 20 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Enable postprocessing by default + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + &Quality: + + + false + + + autoq_spin + + + + + + + 1 + + + 6 + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Dei&nterlace by default: + + + deinterlace_combo + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Default &zoom: + + + zoom_spin + + + + + + + 0.500000000000000 + + + 10.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + Use s&oftware video equalizer + + + + + + + D&irect rendering + + + + + + + Dou&ble buffering + + + + + + + Dra&w video using slices + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + Start videos in &fullscreen + + + + + + + &Add black borders on fullscreen + + + + + + + Disable &screensaver + + + + + + + Qt::Vertical + + + + 438 + 41 + + + + + + + + + A&udio + + + + + + + + Ou&tput driver: + + + false + + + ao_combo + + + + + + + + 0 + 0 + + + + false + + + + + + + + + + Qt::Horizontal + + + + 81 + 20 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + &Enable the audio equalizer + + + + + + + &AC3/DTS pass-through S/PDIF + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + C&hannels by default: + + + channels_combo + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + High speed &playback without altering pitch + + + scaletempo_combo + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Volume + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Use s&oftware volume control + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + false + + + Ma&x. Amplification: + + + false + + + softvol_max_spin + + + + + + + false + + + 10 + + + 10000 + + + + + + + + + Volume &normalization by default + + + + + + + &Change volume on every file + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + false + + + Change volume just before p&laying + + + use_volume_combo + + + + + + + false + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + false + + + &Default volume: + + + false + + + initial_volume_slider + + + + + + + false + + + 100 + + + Qt::Horizontal + + + + + + + false + + + 0 + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 438 + 41 + + + + + + + + + Preferre&d audio and subtitles + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + true + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 6 + + + 6 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + &Audio: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + audio_lang_edit + + + + + + + + + + Su&btitles: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + subtitle_lang_edit + + + + + + + Preferred language: + + + + + + + + + Qt::Horizontal + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 6 + + + 6 + + + + + 1 + + + 99 + + + + + + + Audi&o: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + audio_track_spin + + + + + + + &Subtitle: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + subtitle_track_spin + + + + + + + Qt::Horizontal + + + + 151 + 20 + + + + + + + + Qt::Horizontal + + + + 151 + 20 + + + + + + + + 1 + + + + + + + Or choose a track number: + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + FileChooser + QLineEdit +
    filechooser.h
    +
    + + TristateCombo + QComboBox +
    tristatecombo.h
    +
    +
    + + general_tab + mplayerbin_edit + screenshot_edit + remember_all_check + remember_time_check + filesettings_method_combo + close_on_finish_check + pause_if_hidden_check + vo_combo + vo_user_defined_edit + postprocessing_check + autoq_spin + deinterlace_combo + zoom_spin + eq2_check + direct_rendering_check + double_buffer_check + use_slices_check + start_fullscreen_check + blackborders_on_fs_check + screensaver_check + ao_combo + ao_user_defined_edit + audio_equalizer_check + hwac3_check + channels_combo + scaletempo_combo + softvol_check + softvol_max_spin + volnorm_check + change_volume_check + use_volume_combo + initial_volume_slider + audio_lang_edit + subtitle_lang_edit + audio_track_spin + subtitle_track_spin + + + + + softvol_check + toggled(bool) + softvol_max_spin + setEnabled(bool) + + + 124 + 256 + + + 504 + 256 + + + + + softvol_check + toggled(bool) + amplification_label + setEnabled(bool) + + + 124 + 256 + + + 405 + 256 + + + + + remember_all_check + toggled(bool) + remember_time_check + setEnabled(bool) + + + 280 + 323 + + + 293 + 355 + + + + + change_volume_check + toggled(bool) + default_volume_label + setEnabled(bool) + + + 211 + 342 + + + 305 + 344 + + + + + change_volume_check + toggled(bool) + initial_volume_slider + setEnabled(bool) + + + 118 + 341 + + + 431 + 345 + + + + + change_volume_check + toggled(bool) + initial_volume_label + setEnabled(bool) + + + 231 + 349 + + + 524 + 341 + + + + + initial_volume_slider + valueChanged(int) + initial_volume_label + setNum(int) + + + 463 + 338 + + + 515 + 338 + + + + + change_volume_check + toggled(bool) + use_volume_label + setEnabled(bool) + + + 124 + 143 + + + 277 + 176 + + + + + change_volume_check + toggled(bool) + use_volume_combo + setEnabled(bool) + + + 124 + 143 + + + 534 + 176 + + + + + remember_all_check + toggled(bool) + filesettings_method_label + setEnabled(bool) + + + 229 + 233 + + + 93 + 298 + + + + + remember_all_check + toggled(bool) + filesettings_method_combo + setEnabled(bool) + + + 229 + 233 + + + 181 + 298 + + + + +
    diff --git a/plugins/smplayer_plugin/prefinput.cpp b/plugins/smplayer_plugin/prefinput.cpp new file mode 100644 index 000000000..d5b5cf5d0 --- /dev/null +++ b/plugins/smplayer_plugin/prefinput.cpp @@ -0,0 +1,289 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "prefinput.h" +#include "images.h" +#include "preferences.h" +#include "config.h" +#include "guiconfig.h" + +PrefInput::PrefInput(QWidget * parent, Qt::WindowFlags f) + : PrefWidget(parent, f ) +{ + setupUi(this); + + retranslateStrings(); +} + +PrefInput::~PrefInput() +{ +} + +QString PrefInput::sectionName() { + return tr("Keyboard and mouse"); +} + +QPixmap PrefInput::sectionIcon() { + return Images::icon("input_devices"); +} + +void PrefInput::createMouseCombos() { + left_click_combo->clear(); + right_click_combo->clear(); + double_click_combo->clear(); + middle_click_combo->clear(); + xbutton1_click_combo->clear(); + xbutton2_click_combo->clear(); + + left_click_combo->addItem( tr("None"), "" ); + left_click_combo->addItem( tr("Play"), "play" ); + left_click_combo->addItem( tr("Play / Pause"), "play_or_pause" ); + left_click_combo->addItem( tr("Pause"), "pause" ); + left_click_combo->addItem( tr("Pause / Frame step"), "pause_and_frame_step" ); + left_click_combo->addItem( tr("Stop"), "stop" ); + left_click_combo->addItem( tr("Go backward (short)"), "rewind1" ); + left_click_combo->addItem( tr("Go backward (medium)"), "rewind2" ); + left_click_combo->addItem( tr("Go backward (long)"), "rewind3" ); + left_click_combo->addItem( tr("Go forward (short)"), "forward1" ); + left_click_combo->addItem( tr("Go forward (medium)"), "forward2" ); + left_click_combo->addItem( tr("Go forward (long)"), "forward3" ); + left_click_combo->addItem( tr("Increase volume"), "increase_volume" ); + left_click_combo->addItem( tr("Decrease volume"), "decrease_volume" ); + left_click_combo->addItem( tr("Fullscreen"), "fullscreen" ); + left_click_combo->addItem( tr("Compact"), "compact" ); + left_click_combo->addItem( tr("Screenshot"), "screenshot" ); + left_click_combo->addItem( tr("Always on top"), "on_top_always" ); + left_click_combo->addItem( tr("Never on top"), "on_top_never" ); + left_click_combo->addItem( tr("On top while playing"), "on_top_while_playing" ); + left_click_combo->addItem( tr("Mute"), "mute" ); + left_click_combo->addItem( tr("OSD - Next level"), "next_osd" ); + left_click_combo->addItem( tr("Playlist"), "show_playlist" ); + left_click_combo->addItem( tr("Reset zoom"), "reset_zoom" ); + left_click_combo->addItem( tr("Exit fullscreen"), "exit_fullscreen" ); + left_click_combo->addItem( tr("Normal speed"), "normal_speed" ); + left_click_combo->addItem( tr("Frame counter"), "frame_counter" ); + left_click_combo->addItem( tr("Preferences"), "show_preferences" ); + left_click_combo->addItem( tr("Double size"), "toggle_double_size" ); + left_click_combo->addItem( tr("Show video equalizer"), "video_equalizer" ); + left_click_combo->addItem( tr("Show audio equalizer"), "audio_equalizer" ); + left_click_combo->addItem( tr("Show context menu"), "show_context_menu" ); +#if DVDNAV_SUPPORT + left_click_combo->addItem( tr("Activate option in DVD menus"), "dvdnav_mouse" ); +#endif + + // Copy to other combos + for (int n=0; n < left_click_combo->count(); n++) { + double_click_combo->addItem( left_click_combo->itemText(n), + left_click_combo->itemData(n) ); + + right_click_combo->addItem( left_click_combo->itemText(n), + left_click_combo->itemData(n) ); + + middle_click_combo->addItem( left_click_combo->itemText(n), + left_click_combo->itemData(n) ); + + xbutton1_click_combo->addItem( left_click_combo->itemText(n), + left_click_combo->itemData(n) ); + + xbutton2_click_combo->addItem( left_click_combo->itemText(n), + left_click_combo->itemData(n) ); + } +} + +void PrefInput::retranslateStrings() { + int wheel_function = wheel_function_combo->currentIndex(); + + retranslateUi(this); + + keyboard_icon->setPixmap( Images::icon("keyboard") ); + mouse_icon->setPixmap( Images::icon("mouse") ); + + // Mouse function combos + int mouse_left = left_click_combo->currentIndex(); + int mouse_right = right_click_combo->currentIndex(); + int mouse_double = double_click_combo->currentIndex(); + int mouse_middle = middle_click_combo->currentIndex(); + int mouse_xclick1 = xbutton1_click_combo->currentIndex(); + int mouse_xclick2 = xbutton2_click_combo->currentIndex(); + + createMouseCombos(); + + left_click_combo->setCurrentIndex(mouse_left); + right_click_combo->setCurrentIndex(mouse_right); + double_click_combo->setCurrentIndex(mouse_double); + middle_click_combo->setCurrentIndex(mouse_middle); + xbutton1_click_combo->setCurrentIndex(mouse_xclick1); + xbutton2_click_combo->setCurrentIndex(mouse_xclick2); + + wheel_function_combo->clear(); + wheel_function_combo->addItem( tr("No function"), Preferences::DoNothing ); + wheel_function_combo->addItem( tr("Media seeking"), Preferences::Seeking ); + wheel_function_combo->addItem( tr("Volume control"), Preferences::Volume ); + wheel_function_combo->addItem( tr("Zoom video"), Preferences::Zoom ); + wheel_function_combo->addItem( tr("Change speed"), Preferences::ChangeSpeed ); + wheel_function_combo->setCurrentIndex(wheel_function); + +#if !USE_SHORTCUTGETTER + actioneditor_desc->setText( + tr("Here you can change any key shortcut. To do it double click or " + "start typing over a shortcut cell. Optionally you can also save " + "the list to share it with other people or load it in another " + "computer.") ); +#endif + + createHelp(); +} + +void PrefInput::setData(Preferences * pref) { + setLeftClickFunction( pref->mouse_left_click_function ); + setRightClickFunction( pref->mouse_right_click_function ); + setDoubleClickFunction( pref->mouse_double_click_function ); + setMiddleClickFunction( pref->mouse_middle_click_function ); + setXButton1ClickFunction( pref->mouse_xbutton1_click_function ); + setXButton2ClickFunction( pref->mouse_xbutton2_click_function ); + setWheelFunction( pref->wheel_function ); +} + +void PrefInput::getData(Preferences * pref) { + requires_restart = false; + + pref->mouse_left_click_function = leftClickFunction(); + pref->mouse_right_click_function = rightClickFunction(); + pref->mouse_double_click_function = doubleClickFunction(); + pref->mouse_middle_click_function = middleClickFunction(); + pref->mouse_xbutton1_click_function = xButton1ClickFunction(); + pref->mouse_xbutton2_click_function = xButton2ClickFunction(); + pref->wheel_function = wheelFunction(); +} + +/* +void PrefInput::setActionsList(QStringList l) { + left_click_combo->insertStringList( l ); + double_click_combo->insertStringList( l ); +} +*/ + +void PrefInput::setLeftClickFunction(QString f) { + int pos = left_click_combo->findData(f); + if (pos == -1) pos = 0; //None + left_click_combo->setCurrentIndex(pos); +} + +QString PrefInput::leftClickFunction() { + return left_click_combo->itemData( left_click_combo->currentIndex() ).toString(); +} + +void PrefInput::setRightClickFunction(QString f) { + int pos = right_click_combo->findData(f); + if (pos == -1) pos = 0; //None + right_click_combo->setCurrentIndex(pos); +} + +QString PrefInput::rightClickFunction() { + return right_click_combo->itemData( right_click_combo->currentIndex() ).toString(); +} + +void PrefInput::setDoubleClickFunction(QString f) { + int pos = double_click_combo->findData(f); + if (pos == -1) pos = 0; //None + double_click_combo->setCurrentIndex(pos); +} + +QString PrefInput::doubleClickFunction() { + return double_click_combo->itemData( double_click_combo->currentIndex() ).toString(); +} + +void PrefInput::setMiddleClickFunction(QString f) { + int pos = middle_click_combo->findData(f); + if (pos == -1) pos = 0; //None + middle_click_combo->setCurrentIndex(pos); +} + +QString PrefInput::middleClickFunction() { + return middle_click_combo->itemData( middle_click_combo->currentIndex() ).toString(); +} + +void PrefInput::setXButton1ClickFunction(QString f) { + int pos = xbutton1_click_combo->findData(f); + if (pos == -1) pos = 0; //None + xbutton1_click_combo->setCurrentIndex(pos); +} + +QString PrefInput::xButton1ClickFunction() { + return xbutton1_click_combo->itemData( xbutton1_click_combo->currentIndex() ).toString(); +} + +void PrefInput::setXButton2ClickFunction(QString f) { + int pos = xbutton2_click_combo->findData(f); + if (pos == -1) pos = 0; //None + xbutton2_click_combo->setCurrentIndex(pos); +} + +QString PrefInput::xButton2ClickFunction() { + return xbutton2_click_combo->itemData( xbutton2_click_combo->currentIndex() ).toString(); +} + +void PrefInput::setWheelFunction(int function) { + int d = wheel_function_combo->findData(function); + if (d < 0) d = 0; + wheel_function_combo->setCurrentIndex( d ); +} + +int PrefInput::wheelFunction() { + return wheel_function_combo->itemData(wheel_function_combo->currentIndex()).toInt(); +} + +void PrefInput::createHelp() { + clearHelp(); + + addSectionTitle(tr("Keyboard")); + + setWhatsThis(actions_editor, tr("Shortcut editor"), + tr("This table allows you to change the key shortcuts of most " + "available actions. Double click or press enter on a item, or " + "press the Change shortcut button to enter in the " + "Modify shortcut dialog. There are two ways to change a " + "shortcut: if the Capture button is on then just " + "press the new key or combination of keys that you want to " + "assign for the action (unfortunately this doesn't work for all " + "keys). If the Capture button is off " + "then you could enter the full name of the key.") ); + + addSectionTitle(tr("Mouse")); + + setWhatsThis(left_click_combo, tr("Left click"), + tr("Select the action for left click on the mouse.") ); + + setWhatsThis(double_click_combo, tr("Double click"), + tr("Select the action for double click on the mouse.") ); + + setWhatsThis(middle_click_combo, tr("Middle click"), + tr("Select the action for middle click on the mouse.") ); + + setWhatsThis(xbutton1_click_combo, tr("X Button 1"), + tr("Select the action for the X button 1.") ); + + setWhatsThis(xbutton2_click_combo, tr("X Button 2"), + tr("Select the action for the X button 2.") ); + + setWhatsThis(wheel_function_combo, tr("Wheel function"), + tr("Select the action for the mouse wheel.") ); +} + +#include "moc_prefinput.cpp" diff --git a/plugins/smplayer_plugin/prefinput.h b/plugins/smplayer_plugin/prefinput.h new file mode 100644 index 000000000..1d94e41a9 --- /dev/null +++ b/plugins/smplayer_plugin/prefinput.h @@ -0,0 +1,78 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFINPUT_H_ +#define _PREFINPUT_H_ + +#include "ui_prefinput.h" +#include "prefwidget.h" +#include + +class Preferences; + +class PrefInput : public PrefWidget, public Ui::PrefInput +{ + Q_OBJECT + +public: + PrefInput( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefInput(); + + virtual QString sectionName(); + virtual QPixmap sectionIcon(); + + // Pass data to the dialog + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + + // Pass action's list to dialog + /* void setActionsList(QStringList l); */ + +protected: + virtual void createHelp(); + + void createMouseCombos(); + + void setLeftClickFunction(QString f); + QString leftClickFunction(); + + void setRightClickFunction(QString f); + QString rightClickFunction(); + + void setDoubleClickFunction(QString f); + QString doubleClickFunction(); + + void setMiddleClickFunction(QString f); + QString middleClickFunction(); + + void setXButton1ClickFunction(QString f); + QString xButton1ClickFunction(); + + void setXButton2ClickFunction(QString f); + QString xButton2ClickFunction(); + + void setWheelFunction(int function); + int wheelFunction(); + +protected: + virtual void retranslateStrings(); +}; + +#endif diff --git a/plugins/smplayer_plugin/prefinput.ui b/plugins/smplayer_plugin/prefinput.ui new file mode 100644 index 000000000..321bf1535 --- /dev/null +++ b/plugins/smplayer_plugin/prefinput.ui @@ -0,0 +1,466 @@ + + PrefInput + + + + 0 + 0 + 571 + 549 + + + + + 0 + + + 6 + + + + + 0 + + + + &Keyboard + + + + 6 + + + 6 + + + + + 0 + + + 6 + + + + + icon + + + false + + + + + + + + 7 + 5 + 0 + 0 + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + Qt::AlignVCenter + + + true + + + + + + + + + + 7 + 7 + 0 + 0 + + + + + + + + + &Mouse + + + + 9 + + + 6 + + + + + Button functions: + + + false + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 161 + 20 + + + + + + + + + 7 + 0 + 0 + 0 + + + + + + + + &Double click + + + false + + + double_click_combo + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 161 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 161 + 20 + + + + + + + + M&iddle click + + + middle_click_combo + + + + + + + + + + Qt::Horizontal + + + + 161 + 20 + + + + + + + + X Button &1 + + + xbutton1_click_combo + + + + + + + Qt::Horizontal + + + + 161 + 20 + + + + + + + + + + + X Button &2 + + + xbutton2_click_combo + + + + + + + + 7 + 0 + 0 + 0 + + + + QFrame::HLine + + + QFrame::Sunken + + + Qt::Horizontal + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + &Left click + + + false + + + left_click_combo + + + + + + + 0 + + + 6 + + + + + icon + + + false + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + + 0 + + + 6 + + + + + &Wheel function: + + + false + + + wheel_function_combo + + + + + + + + 7 + 0 + 0 + 0 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 121 + 31 + + + + + + + + + + + 7 + 0 + 0 + 0 + + + + + + + + &Right click + + + false + + + right_click_combo + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 161 + 20 + + + + + + + + + 7 + 0 + 0 + 0 + + + + + + + + + + + + + MyComboBox + QComboBox +
    mycombobox.h
    +
    + + ActionsEditor + QWidget +
    actionseditor.h
    +
    +
    + + input_tab + left_click_combo + double_click_combo + right_click_combo + middle_click_combo + xbutton1_click_combo + xbutton2_click_combo + wheel_function_combo + + + +
    diff --git a/plugins/smplayer_plugin/prefinterface.cpp b/plugins/smplayer_plugin/prefinterface.cpp new file mode 100644 index 000000000..58b9079b7 --- /dev/null +++ b/plugins/smplayer_plugin/prefinterface.cpp @@ -0,0 +1,598 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "prefinterface.h" +#include "images.h" +#include "preferences.h" +#include "paths.h" +#include "config.h" +#include "languages.h" +#include "recents.h" + +#include +#include +#include + +PrefInterface::PrefInterface(QWidget * parent, Qt::WindowFlags f) + : PrefWidget(parent, f ) +{ + setupUi(this); + /* volume_icon->hide(); */ + + // Style combo +#if !STYLE_SWITCHING + style_label->hide(); + style_combo->hide(); +#else + style_combo->addItem( "" ); + style_combo->addItems( QStyleFactory::keys() ); +#endif + + // Icon set combo + iconset_combo->addItem( "Default" ); + + // User + QDir icon_dir = Paths::configPath() + "/themes"; + qDebug("icon_dir: %s", icon_dir.absolutePath().toUtf8().data()); + QStringList iconsets = icon_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + for (int n=0; n < iconsets.count(); n++) { + iconset_combo->addItem( iconsets[n] ); + } + // Global + icon_dir = Paths::themesPath(); + qDebug("icon_dir: %s", icon_dir.absolutePath().toUtf8().data()); + iconsets = icon_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + for (int n=0; n < iconsets.count(); n++) { + if (iconset_combo->findText( iconsets[n] ) == -1) { + iconset_combo->addItem( iconsets[n] ); + } + } + + connect(single_instance_check, SIGNAL(toggled(bool)), + this, SLOT(changeInstanceImages())); + +#ifdef Q_OS_WIN + floating_bypass_wm_check->hide(); +#endif + + retranslateStrings(); +} + +PrefInterface::~PrefInterface() +{ +} + +QString PrefInterface::sectionName() { + return tr("Interface"); +} + +QPixmap PrefInterface::sectionIcon() { + return Images::icon("pref_gui"); +} + +void PrefInterface::createLanguageCombo() { + QMap m = Languages::translations(); + + // Language combo + QDir translation_dir = Paths::translationPath(); + QStringList languages = translation_dir.entryList( QStringList() << "*.qm"); + QRegExp rx_lang("smplayer_(.*)\\.qm"); + language_combo->clear(); + language_combo->addItem( tr("") ); + for (int n=0; n < languages.count(); n++) { + if (rx_lang.indexIn(languages[n]) > -1) { + QString l = rx_lang.cap(1); + QString text = l; + if (m.contains(l)) text = m[l] + " ("+l+")"; + language_combo->addItem( text, l ); + } + } +} + +void PrefInterface::retranslateStrings() { + int mainwindow_resize = mainwindow_resize_combo->currentIndex(); + int timeslider_pos = timeslider_behaviour_combo->currentIndex(); + + retranslateUi(this); + + mainwindow_resize_combo->setCurrentIndex(mainwindow_resize); + timeslider_behaviour_combo->setCurrentIndex(timeslider_pos); + + // Icons + resize_window_icon->setPixmap( Images::icon("resize_window") ); + /* volume_icon->setPixmap( Images::icon("speaker") ); */ + + changeInstanceImages(); + + // Seek widgets + seek1->setLabel( tr("&Short jump") ); + seek2->setLabel( tr("&Medium jump") ); + seek3->setLabel( tr("&Long jump") ); + seek4->setLabel( tr("Mouse &wheel jump") ); + + if (qApp->isLeftToRight()) { + seek1->setIcon( Images::icon("forward10s") ); + seek2->setIcon( Images::icon("forward1m") ); + seek3->setIcon( Images::icon("forward10m") ); + } else { + seek1->setIcon( Images::flippedIcon("forward10s") ); + seek2->setIcon( Images::flippedIcon("forward1m") ); + seek3->setIcon( Images::flippedIcon("forward10m") ); + } + seek4->setIcon( Images::icon("mouse", seek1->icon()->width()) ); + + // Language combo + int language_item = language_combo->currentIndex(); + createLanguageCombo(); + language_combo->setCurrentIndex( language_item ); + + // Iconset combo + iconset_combo->setItemText( 0, tr("Default") ); + +#if STYLE_SWITCHING + style_combo->setItemText( 0, tr("Default") ); +#endif + + int gui_index = gui_combo->currentIndex(); + gui_combo->clear(); + gui_combo->addItem( tr("Default GUI"), "DefaultGUI"); + gui_combo->addItem( tr("Mini GUI"), "MiniGUI"); + gui_combo->addItem( tr("Mpc GUI"), "MpcGUI"); + gui_combo->setCurrentIndex(gui_index); + + floating_width_label->setNum(floating_width_slider->value()); + floating_margin_label->setNum(floating_margin_slider->value()); + + createHelp(); +} + +void PrefInterface::setData(Preferences * pref) { + setLanguage( pref->language ); + setIconSet( pref->iconset ); + + setResizeMethod( pref->resize_method ); + setSaveSize( pref->save_window_size_on_exit ); + setUseSingleInstance(pref->use_single_instance); + setServerPort(pref->connection_port); + setUseAutoPort(pref->use_autoport); + setRecentsMaxItems(pref->history_recents->maxItems()); + + setSeeking1(pref->seeking1); + setSeeking2(pref->seeking2); + setSeeking3(pref->seeking3); + setSeeking4(pref->seeking4); + + setUpdateWhileDragging(pref->update_while_seeking); + + setDefaultFont(pref->default_font); + +#if STYLE_SWITCHING + setStyle( pref->style ); +#endif + + setGUI(pref->gui); + + setFloatingAnimated(pref->floating_control_animated); + setFloatingWidth(pref->floating_control_width); + setFloatingMargin(pref->floating_control_margin); + setDisplayFloatingInCompactMode(pref->floating_display_in_compact_mode); +#ifndef Q_OS_WIN + setFloatingBypassWindowManager(pref->bypass_window_manager); +#endif +} + +void PrefInterface::getData(Preferences * pref) { + requires_restart = false; + language_changed = false; + iconset_changed = false; + recents_changed = false; + port_changed = false; + style_changed = false; + + if (pref->language != language()) { + pref->language = language(); + language_changed = true; + qDebug("PrefInterface::getData: chosen language: '%s'", pref->language.toUtf8().data()); + } + + if (pref->iconset != iconSet()) { + pref->iconset = iconSet(); + iconset_changed = true; + } + + pref->resize_method = resizeMethod(); + pref->save_window_size_on_exit = saveSize(); + + pref->use_single_instance = useSingleInstance(); + if (pref->connection_port != serverPort()) { + pref->connection_port = serverPort(); + port_changed = true; + } + + if (pref->use_autoport != useAutoPort()) { + pref->use_autoport = useAutoPort(); + port_changed = true; + } + + if (pref->history_recents->maxItems() != recentsMaxItems()) { + pref->history_recents->setMaxItems( recentsMaxItems() ); + recents_changed = true; + } + + pref->seeking1 = seeking1(); + pref->seeking2 = seeking2(); + pref->seeking3 = seeking3(); + pref->seeking4 = seeking4(); + + pref->update_while_seeking = updateWhileDragging(); + + pref->default_font = defaultFont(); + +#if STYLE_SWITCHING + if ( pref->style != style() ) { + pref->style = style(); + style_changed = true; + } +#endif + + pref->gui = GUI(); + + pref->floating_control_animated = floatingAnimated(); + pref->floating_control_width = floatingWidth(); + pref->floating_control_margin = floatingMargin(); + pref->floating_display_in_compact_mode = displayFloatingInCompactMode(); +#ifndef Q_OS_WIN + pref->bypass_window_manager = floatingBypassWindowManager(); +#endif +} + +void PrefInterface::setLanguage(QString lang) { + if (lang.isEmpty()) { + language_combo->setCurrentIndex(0); + } + else { + int pos = language_combo->findData(lang); + if (pos != -1) + language_combo->setCurrentIndex( pos ); + else + language_combo->setCurrentText(lang); + } +} + +QString PrefInterface::language() { + if (language_combo->currentIndex()==0) + return ""; + else + return language_combo->itemData( language_combo->currentIndex() ).toString(); +} + +void PrefInterface::setIconSet(QString set) { + if (set.isEmpty()) + iconset_combo->setCurrentIndex(0); + else + iconset_combo->setCurrentText(set); +} + +QString PrefInterface::iconSet() { + if (iconset_combo->currentIndex()==0) + return ""; + else + return iconset_combo->currentText(); +} + +void PrefInterface::setResizeMethod(int v) { + mainwindow_resize_combo->setCurrentIndex(v); +} + +int PrefInterface::resizeMethod() { + return mainwindow_resize_combo->currentIndex(); +} + +void PrefInterface::setSaveSize(bool b) { + save_size_check->setChecked(b); +} + +bool PrefInterface::saveSize() { + return save_size_check->isChecked(); +} + + +void PrefInterface::setStyle(QString style) { + if (style.isEmpty()) + style_combo->setCurrentIndex(0); + else + style_combo->setCurrentText(style); +} + +QString PrefInterface::style() { + if (style_combo->currentIndex()==0) + return ""; + else + return style_combo->currentText(); +} + +void PrefInterface::setGUI(QString gui_name) { + int i = gui_combo->findData(gui_name); + if (i < 0) i=0; + gui_combo->setCurrentIndex(i); +} + +QString PrefInterface::GUI() { + return gui_combo->itemData(gui_combo->currentIndex()).toString(); +} + +void PrefInterface::setUseSingleInstance(bool b) { + single_instance_check->setChecked(b); + //singleInstanceButtonToggled(b); +} + +bool PrefInterface::useSingleInstance() { + return single_instance_check->isChecked(); +} + +void PrefInterface::setServerPort(int port) { + server_port_spin->setValue(port); +} + +int PrefInterface::serverPort() { + return server_port_spin->value(); +} + +void PrefInterface::setUseAutoPort(bool b) { + automatic_port_button->setChecked(b); + manual_port_button->setChecked(!b); +} + +bool PrefInterface::useAutoPort() { + return automatic_port_button->isChecked(); +} + +void PrefInterface::setRecentsMaxItems(int n) { + recents_max_items_spin->setValue(n); +} + +int PrefInterface::recentsMaxItems() { + return recents_max_items_spin->value(); +} + +void PrefInterface::setSeeking1(int n) { + seek1->setTime(n); +} + +int PrefInterface::seeking1() { + return seek1->time(); +} + +void PrefInterface::setSeeking2(int n) { + seek2->setTime(n); +} + +int PrefInterface::seeking2() { + return seek2->time(); +} + +void PrefInterface::setSeeking3(int n) { + seek3->setTime(n); +} + +int PrefInterface::seeking3() { + return seek3->time(); +} + +void PrefInterface::setSeeking4(int n) { + seek4->setTime(n); +} + +int PrefInterface::seeking4() { + return seek4->time(); +} + +void PrefInterface::setUpdateWhileDragging(bool b) { + if (b) + timeslider_behaviour_combo->setCurrentIndex(0); + else + timeslider_behaviour_combo->setCurrentIndex(1); +} + +bool PrefInterface::updateWhileDragging() { + return (timeslider_behaviour_combo->currentIndex() == 0); +} + +void PrefInterface::setDefaultFont(QString font_desc) { + default_font_edit->setText(font_desc); +} + +QString PrefInterface::defaultFont() { + return default_font_edit->text(); +} + +void PrefInterface::on_changeFontButton_clicked() { + QFont f = qApp->font(); + + if (!default_font_edit->text().isEmpty()) { + f.fromString(default_font_edit->text()); + } + + bool ok; + f = QFontDialog::getFont( &ok, f, this); + + if (ok) { + default_font_edit->setText( f.toString() ); + } +} + +void PrefInterface::changeInstanceImages() { + if (single_instance_check->isChecked()) + instances_icon->setPixmap( Images::icon("instance1") ); + else + instances_icon->setPixmap( Images::icon("instance2") ); +} + +// Floating tab +void PrefInterface::setFloatingAnimated(bool b) { + floating_animated_check->setChecked(b); +} + +bool PrefInterface::floatingAnimated() { + return floating_animated_check->isChecked(); +} + +void PrefInterface::setFloatingWidth(int percentage) { + floating_width_slider->setValue(percentage); +} + +int PrefInterface::floatingWidth() { + return floating_width_slider->value(); +} + +void PrefInterface::setFloatingMargin(int pixels) { + floating_margin_slider->setValue(pixels); +} + +int PrefInterface::floatingMargin() { + return floating_margin_slider->value(); +} + +void PrefInterface::setDisplayFloatingInCompactMode(bool b) { + floating_compact_check->setChecked(b); +} + +bool PrefInterface::displayFloatingInCompactMode() { + return floating_compact_check->isChecked(); +} + +#ifndef Q_OS_WIN +void PrefInterface::setFloatingBypassWindowManager(bool b) { + floating_bypass_wm_check->setChecked(b); +} + +bool PrefInterface::floatingBypassWindowManager() { + return floating_bypass_wm_check->isChecked(); +} +#endif + +void PrefInterface::createHelp() { + clearHelp(); + + addSectionTitle(tr("Interface")); + + setWhatsThis(mainwindow_resize_combo, tr("Autoresize"), + tr("The main window can be resized automatically. Select the option " + "you prefer.") ); + + setWhatsThis(save_size_check, tr("Remember position and size"), + tr("If you check this option, the position and size of the main " + "window will be saved and restored when you run SMPlayer again.") ); + + setWhatsThis(recents_max_items_spin, tr("Recent files"), + tr("Select the maximum number of items that will be shown in the " + "Open->Recent files submenu. If you set it to 0 that " + "menu won't be shown at all.") ); + + setWhatsThis(language_combo, tr("Language"), + tr("Here you can change the language of the application.") ); + + setWhatsThis(iconset_combo, tr("Icon set"), + tr("Select the icon set you prefer for the application.") ); + + setWhatsThis(style_combo, tr("Style"), + tr("Select the style you prefer for the application.") ); + + setWhatsThis(gui_combo, tr("GUI"), + tr("Select the GUI you prefer for the application. Currently " + "there are two available: Default GUI and Mini GUI.
    " + "The Default GUI provides the traditional GUI, with the " + "toolbar and control bar. The Mini GUI provides a " + "more simple GUI, without toolbar and a control bar with few " + "buttons.
    " + "Note: this option will take effect the next " + "time you run SMPlayer.") ); + + setWhatsThis(changeFontButton, tr("Default font"), + tr("You can change here the application's font.") ); + + addSectionTitle(tr("Seeking")); + + setWhatsThis(seek1, tr("Short jump"), + tr("Select the time that should be go forward or backward when you " + "choose the %1 action.").arg(tr("short jump")) ); + + setWhatsThis(seek2, tr("Medium jump"), + tr("Select the time that should be go forward or backward when you " + "choose the %1 action.").arg(tr("medium jump")) ); + + setWhatsThis(seek3, tr("Long jump"), + tr("Select the time that should be go forward or backward when you " + "choose the %1 action.").arg(tr("long jump")) ); + + setWhatsThis(seek4, tr("Mouse wheel jump"), + tr("Select the time that should be go forward or backward when you " + "move the mouse wheel.") ); + + setWhatsThis(timeslider_behaviour_combo, tr("Behaviour of time slider"), + tr("Select what to do when dragging the time slider.") ); + + addSectionTitle(tr("Instances")); + + setWhatsThis(single_instance_check, + tr("Use only one running instance of SMPlayer"), + tr("Check this option if you want to use an already running instance " + "of SMPlayer when opening other files.") ); + + setWhatsThis(automatic_port_button, tr("Automatic port"), + tr("SMPlayer needs to listen to a port to receive commands from other " + "instances. If you select this option, a port will be " + "automatically chosen.") ); + + setWhatsThis(server_port_spin, tr("Manual port"), + tr("SMPlayer needs to listen to a port to receive commands from other " + "instances. You can change the port in case the default one is " + "used by another application.") ); + + manual_port_button->setWhatsThis( server_port_spin->whatsThis() ); + + addSectionTitle(tr("Floating control")); + + setWhatsThis(floating_animated_check, tr("Animated"), + tr("If this option is enabled, the floating control will appear " + "with an animation.") ); + + setWhatsThis(floating_width_slider, tr("Width"), + tr("Specifies the width of the control (as a percentage).") ); + + setWhatsThis(floating_margin_slider, tr("Margin"), + tr("This option sets the number of pixels that the floating control " + "will be away from the bottom of the screen. Useful when the " + "screen is a TV, as the overscan might prevent the control to be " + "visible.") ); + + setWhatsThis(floating_compact_check, tr("Display in compact mode too"), + tr("If this option is enabled, the floating control will appear " + "in compact mode too. Warning: the floating control has not been " + "designed for compact mode and it might not work properly.") ); + +#ifndef Q_OS_WIN + setWhatsThis(floating_bypass_wm_check, tr("Bypass window manager"), + tr("If this option is checked, the control is displayed bypassing the " + "window manager. Disable this option if the floating control " + "doesn't work well with your window manager.") ); +#endif +} + +#include "moc_prefinterface.cpp" diff --git a/plugins/smplayer_plugin/prefinterface.h b/plugins/smplayer_plugin/prefinterface.h new file mode 100644 index 000000000..402ff6bbf --- /dev/null +++ b/plugins/smplayer_plugin/prefinterface.h @@ -0,0 +1,135 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFINTERFACE_H_ +#define _PREFINTERFACE_H_ + +#include "ui_prefinterface.h" +#include "prefwidget.h" + +class Preferences; + +class PrefInterface : public PrefWidget, public Ui::PrefInterface +{ + Q_OBJECT + +public: + PrefInterface( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefInterface(); + + virtual QString sectionName(); + virtual QPixmap sectionIcon(); + + // Pass data to the dialog + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + + bool languageChanged() { return language_changed; }; + bool iconsetChanged() { return iconset_changed; }; + bool recentsChanged() { return recents_changed; }; + bool styleChanged() { return style_changed; }; + bool serverPortChanged() { return port_changed; }; + +protected: + virtual void createHelp(); + void createLanguageCombo(); + + void setLanguage(QString lang); + QString language(); + + void setIconSet(QString set); + QString iconSet(); + + void setResizeMethod(int v); + int resizeMethod(); + + void setSaveSize(bool b); + bool saveSize(); + + void setGUI(QString gui_name); + QString GUI(); + + void setStyle(QString style); + QString style(); + + void setUseSingleInstance(bool b); + bool useSingleInstance(); + + void setServerPort(int port); + int serverPort(); + + void setUseAutoPort(bool b); + bool useAutoPort(); + + void setRecentsMaxItems(int n); + int recentsMaxItems(); + + void setSeeking1(int n); + int seeking1(); + + void setSeeking2(int n); + int seeking2(); + + void setSeeking3(int n); + int seeking3(); + + void setSeeking4(int n); + int seeking4(); + + void setUpdateWhileDragging(bool); + bool updateWhileDragging(); + + void setDefaultFont(QString font_desc); + QString defaultFont(); + + // Floating tab + void setFloatingAnimated(bool b); + bool floatingAnimated(); + + void setFloatingWidth(int percentage); + int floatingWidth(); + + void setFloatingMargin(int pixels); + int floatingMargin(); + + void setDisplayFloatingInCompactMode(bool b); + bool displayFloatingInCompactMode(); + +#ifndef Q_OS_WIN + void setFloatingBypassWindowManager(bool b); + bool floatingBypassWindowManager(); +#endif + +protected slots: + void on_changeFontButton_clicked(); + void changeInstanceImages(); + +protected: + virtual void retranslateStrings(); + +private: + bool language_changed; + bool iconset_changed; + bool recents_changed; + bool style_changed; + bool port_changed; +}; + +#endif diff --git a/plugins/smplayer_plugin/prefinterface.ui b/plugins/smplayer_plugin/prefinterface.ui new file mode 100644 index 000000000..df44975f9 --- /dev/null +++ b/plugins/smplayer_plugin/prefinterface.ui @@ -0,0 +1,1018 @@ + + PrefInterface + + + + 0 + 0 + 497 + 491 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + &Interface + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Main window + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + TextLabel + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Auto&resize: + + + mainwindow_resize_combo + + + + + + + + 0 + 0 + + + + + Never + + + + + Whenever it's needed + + + + + Only after loading a new video + + + + + + + + R&emember position and size + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Recent files + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Ma&x. items + + + false + + + recents_max_items_spin + + + + + + + 0 + + + 20 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 6 + + + 6 + + + + + L&anguage: + + + false + + + language_combo + + + + + + + Ico&n set: + + + false + + + iconset_combo + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + + + + St&yle: + + + false + + + style_combo + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &GUI + + + gui_combo + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Default font: + + + + + + + true + + + + + + + &Change... + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Seeking + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Behaviour of time slider: + + + timeslider_behaviour_combo + + + + + + + + 0 + 0 + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + + + + Qt::Horizontal + + + + 81 + 25 + + + + + + + + + + + Ins&tances + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + TextLabel + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Use only one running instance of SMPlayer + + + + + + + false + + + Port to listen + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + &Automatic + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Manual + + + + + + + false + + + 65535 + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 270 + 31 + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Floating control + + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + true + + + + + + + &Animated + + + + + + + + + &Width: + + + floating_width_slider + + + + + + + 100 + + + Qt::Horizontal + + + + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + + &Margin: + + + floating_margin_slider + + + + + + + 80 + + + Qt::Horizontal + + + + + + + QFrame::Panel + + + QFrame::Sunken + + + 0 + + + + + + + + + Display in &compact mode too + + + + + + + &Bypass window manager + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + MyComboBox + QComboBox +
    mycombobox.h
    +
    + + SeekWidget + QWidget +
    seekwidget.h
    +
    +
    + + tabWidget + mainwindow_resize_combo + save_size_check + recents_max_items_spin + language_combo + iconset_combo + style_combo + gui_combo + default_font_edit + changeFontButton + timeslider_behaviour_combo + single_instance_check + automatic_port_button + manual_port_button + server_port_spin + floating_animated_check + floating_width_slider + floating_margin_slider + floating_compact_check + floating_bypass_wm_check + + + + + manual_port_button + toggled(bool) + server_port_spin + setEnabled(bool) + + + 124 + 170 + + + 109 + 126 + + + + + single_instance_check + toggled(bool) + port_groupbox + setEnabled(bool) + + + 319 + 49 + + + 317 + 222 + + + + + floating_width_slider + valueChanged(int) + floating_width_label + setNum(int) + + + 222 + 154 + + + 411 + 156 + + + + + floating_margin_slider + valueChanged(int) + floating_margin_label + setNum(int) + + + 272 + 204 + + + 480 + 150 + + + + +
    diff --git a/plugins/smplayer_plugin/prefperformance.cpp b/plugins/smplayer_plugin/prefperformance.cpp new file mode 100644 index 000000000..ad930ed1d --- /dev/null +++ b/plugins/smplayer_plugin/prefperformance.cpp @@ -0,0 +1,313 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "prefperformance.h" +#include "images.h" +#include "global.h" +#include "preferences.h" + +using namespace Global; + +PrefPerformance::PrefPerformance(QWidget * parent, Qt::WindowFlags f) + : PrefWidget(parent, f ) +{ + setupUi(this); + + // Priority is only for windows, so we disable for other systems +#ifndef Q_OS_WIN + priority_group->hide(); +#endif + +#if SMART_DVD_CHAPTERS + fast_chapter_check->hide(); +#endif + + retranslateStrings(); +} + +PrefPerformance::~PrefPerformance() +{ +} + +QString PrefPerformance::sectionName() { + return tr("Performance"); +} + +QPixmap PrefPerformance::sectionIcon() { + return Images::icon("pref_performance"); +} + + +void PrefPerformance::retranslateStrings() { + int priority = priority_combo->currentIndex(); + int loop_filter = loopfilter_combo->currentIndex(); + + retranslateUi(this); + + loopfilter_combo->clear(); + loopfilter_combo->addItem( tr("Enabled"), Preferences::LoopEnabled ); + loopfilter_combo->addItem( tr("Skip (always)"), Preferences::LoopDisabled ); + loopfilter_combo->addItem( tr("Skip only on HD videos"), Preferences::LoopDisabledOnHD ); + + priority_combo->setCurrentIndex(priority); + loopfilter_combo->setCurrentIndex(loop_filter); + + createHelp(); +} + +void PrefPerformance::setData(Preferences * pref) { + setCacheForFiles( pref->cache_for_files ); + setCacheForStreams( pref->cache_for_streams ); + setCacheForDVDs( pref->cache_for_dvds ); + setCacheForAudioCDs( pref->cache_for_audiocds ); + setCacheForVCDs( pref->cache_for_vcds ); + + setPriority( pref->priority ); + setFrameDrop( pref->frame_drop ); + setHardFrameDrop( pref->hard_frame_drop ); + setSkipLoop( pref->h264_skip_loop_filter ); + setAutoSyncActivated( pref->autosync ); + setAutoSyncFactor( pref->autosync_factor ); +#if !SMART_DVD_CHAPTERS + setFastChapterSeeking( pref->fast_chapter_change ); +#endif + setFastAudioSwitching( pref->fast_audio_change ); + setThreads( pref->threads ); +} + +void PrefPerformance::getData(Preferences * pref) { + requires_restart = false; + + TEST_AND_SET(pref->cache_for_files, cacheForFiles()); + TEST_AND_SET(pref->cache_for_streams, cacheForStreams()); + TEST_AND_SET(pref->cache_for_dvds, cacheForDVDs()); + TEST_AND_SET(pref->cache_for_audiocds, cacheForAudioCDs()); + TEST_AND_SET(pref->cache_for_vcds, cacheForVCDs()); + + TEST_AND_SET(pref->priority, priority()); + TEST_AND_SET(pref->frame_drop, frameDrop()); + TEST_AND_SET(pref->hard_frame_drop, hardFrameDrop()); + TEST_AND_SET(pref->h264_skip_loop_filter, skipLoop()); + TEST_AND_SET(pref->autosync, autoSyncActivated()); + TEST_AND_SET(pref->autosync_factor, autoSyncFactor()); +#if !SMART_DVD_CHAPTERS + TEST_AND_SET(pref->fast_chapter_change, fastChapterSeeking()); +#endif + pref->fast_audio_change = fastAudioSwitching(); + TEST_AND_SET(pref->threads, threads()); +} + +void PrefPerformance::setCacheForFiles(int n) { + cache_files_spin->setValue(n); +} + +int PrefPerformance::cacheForFiles() { + return cache_files_spin->value(); +} + +void PrefPerformance::setCacheForStreams(int n) { + cache_streams_spin->setValue(n); +} + +int PrefPerformance::cacheForStreams() { + return cache_streams_spin->value(); +} + +void PrefPerformance::setCacheForDVDs(int n) { + cache_dvds_spin->setValue(n); +} + +int PrefPerformance::cacheForDVDs() { + return cache_dvds_spin->value(); +} + +void PrefPerformance::setCacheForAudioCDs(int n) { + cache_cds_spin->setValue(n); +} + +int PrefPerformance::cacheForAudioCDs() { + return cache_cds_spin->value(); +} + +void PrefPerformance::setCacheForVCDs(int n) { + cache_vcds_spin->setValue(n); +} + +int PrefPerformance::cacheForVCDs() { + return cache_vcds_spin->value(); +} + +void PrefPerformance::setPriority(int n) { + priority_combo->setCurrentIndex(n); +} + +int PrefPerformance::priority() { + return priority_combo->currentIndex(); +} + +void PrefPerformance::setFrameDrop(bool b) { + framedrop_check->setChecked(b); +} + +bool PrefPerformance::frameDrop() { + return framedrop_check->isChecked(); +} + +void PrefPerformance::setHardFrameDrop(bool b) { + hardframedrop_check->setChecked(b); +} + +bool PrefPerformance::hardFrameDrop() { + return hardframedrop_check->isChecked(); +} + +void PrefPerformance::setSkipLoop(Preferences::H264LoopFilter value) { + loopfilter_combo->setCurrentIndex(loopfilter_combo->findData(value)); +} + +Preferences::H264LoopFilter PrefPerformance::skipLoop() { + return (Preferences::H264LoopFilter) loopfilter_combo->itemData(loopfilter_combo->currentIndex()).toInt(); +} + +void PrefPerformance::setAutoSyncFactor(int factor) { + autosync_spin->setValue(factor); +} + +int PrefPerformance::autoSyncFactor() { + return autosync_spin->value(); +} + +void PrefPerformance::setAutoSyncActivated(bool b) { + autosync_check->setChecked(b); +} + +bool PrefPerformance::autoSyncActivated() { + return autosync_check->isChecked(); +} + +#if !SMART_DVD_CHAPTERS +void PrefPerformance::setFastChapterSeeking(bool b) { + fast_chapter_check->setChecked(b); +} + +bool PrefPerformance::fastChapterSeeking() { + return fast_chapter_check->isChecked(); +} +#endif + +void PrefPerformance::setFastAudioSwitching(Preferences::OptionState value) { + fast_audio_combo->setState(value); +} + +Preferences::OptionState PrefPerformance::fastAudioSwitching() { + return fast_audio_combo->state(); +} + +void PrefPerformance::setThreads(int v) { + threads_spin->setValue(v); +} + +int PrefPerformance::threads() { + return threads_spin->value(); +} + +void PrefPerformance::createHelp() { + clearHelp(); + + addSectionTitle(tr("Performance")); + + // Performance tab +#ifdef Q_OS_WIN + setWhatsThis(priority_combo, tr("Priority"), + tr("Set process priority for mplayer according to the predefined " + "priorities available under Windows.
    " + "Warning: Using realtime priority can cause system lockup.")); +#endif + + setWhatsThis(framedrop_check, tr("Allow frame drop"), + tr("Skip displaying some frames to maintain A/V sync on slow systems." ) ); + + setWhatsThis(hardframedrop_check, tr("Allow hard frame drop"), + tr("More intense frame dropping (breaks decoding). " + "Leads to image distortion!") ); + + setWhatsThis(threads_spin, tr("Threads for decoding"), + tr("Sets the number of threads to use for decoding. Only for " + "MPEG-1/2 and H.264") ); + + setWhatsThis(loopfilter_combo, tr("Skip loop filter"), + tr("This option allows to skips the loop filter (AKA deblocking) " + "during H.264 decoding. " + "Since the filtered frame is supposed to be used as reference " + "for decoding dependent frames this has a worse effect on quality " + "than not doing deblocking on e.g. MPEG-2 video. But at least for " + "high bitrate HDTV this provides a big speedup with no visible " + "quality loss.") +"
    "+ + tr("Possible values:") +"
    " + + tr("Enabled: the loop filter is not skipped")+"
    "+ + tr("Skip (always): the loop filter is skipped no matter the " + "resolution of the video")+"
    "+ + tr("Skip only on HD videos: the loop filter will be " + "skipped only on videos which height is %1 or " + "greater.").arg(pref->HD_height) +"
    " ); + + setWhatsThis(autosync_check, tr("Audio/video auto synchronization"), + tr("Gradually adjusts the A/V sync based on audio delay " + "measurements.") ); + + setWhatsThis(fast_audio_combo, tr("Fast audio track switching"), + tr("Possible values:
    " + "Yes: it will try the fastest method " + "to switch the audio track (it might not work with some formats).
    " + "No: the MPlayer process will be restarted whenever you " + "change the audio track.
    " + "Auto: SMPlayer will decide what to do according to the " + "MPlayer version." ) ); + +#if !SMART_DVD_CHAPTERS + setWhatsThis(fast_chapter_check, tr("Fast seek to chapters in dvds"), + tr("If checked, it will try the fastest method to seek to chapters " + "but it might not work with some discs.") ); +#endif + + addSectionTitle(tr("Cache")); + + setWhatsThis(cache_files_spin, tr("Cache for files"), + tr("This option specifies how much memory (in kBytes) to use when " + "precaching a file.") ); + + setWhatsThis(cache_streams_spin, tr("Cache for streams"), + tr("This option specifies how much memory (in kBytes) to use when " + "precaching a URL.") ); + + setWhatsThis(cache_dvds_spin, tr("Cache for DVDs"), + tr("This option specifies how much memory (in kBytes) to use when " + "precaching a DVD.
    Warning: Seeking might not work " + "properly (including chapter switching) when using a cache for DVDs.") ); + + setWhatsThis(cache_cds_spin, tr("Cache for audio CDs"), + tr("This option specifies how much memory (in kBytes) to use when " + "precaching an audio CD.") ); + + setWhatsThis(cache_vcds_spin, tr("Cache for VCDs"), + tr("This option specifies how much memory (in kBytes) to use when " + "precaching a VCD.") ); +} + +#include "moc_prefperformance.cpp" diff --git a/plugins/smplayer_plugin/prefperformance.h b/plugins/smplayer_plugin/prefperformance.h new file mode 100644 index 000000000..bc4f9a4c9 --- /dev/null +++ b/plugins/smplayer_plugin/prefperformance.h @@ -0,0 +1,96 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFPERFORMANCE_H_ +#define _PREFPERFORMANCE_H_ + +#include "ui_prefperformance.h" +#include "prefwidget.h" + +#include "preferences.h" +#include "config.h" + +class PrefPerformance : public PrefWidget, public Ui::PrefPerformance +{ + Q_OBJECT + +public: + PrefPerformance( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefPerformance(); + + virtual QString sectionName(); + virtual QPixmap sectionIcon(); + + // Pass data to the dialog + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + +protected: + virtual void createHelp(); + + void setCacheForFiles(int n); + int cacheForFiles(); + + void setCacheForStreams(int n); + int cacheForStreams(); + + void setCacheForDVDs(int n); + int cacheForDVDs(); + + void setCacheForAudioCDs(int n); + int cacheForAudioCDs(); + + void setCacheForVCDs(int n); + int cacheForVCDs(); + + void setPriority(int n); + int priority(); + + void setFrameDrop(bool b); + bool frameDrop(); + + void setHardFrameDrop(bool b); + bool hardFrameDrop(); + + void setSkipLoop(Preferences::H264LoopFilter value); + Preferences::H264LoopFilter skipLoop(); + + void setAutoSyncFactor(int factor); + int autoSyncFactor(); + + void setAutoSyncActivated(bool b); + bool autoSyncActivated(); + +#if !SMART_DVD_CHAPTERS + void setFastChapterSeeking(bool b); + bool fastChapterSeeking(); +#endif + + void setFastAudioSwitching(Preferences::OptionState value); + Preferences::OptionState fastAudioSwitching(); + + void setThreads(int v); + int threads(); + +protected: + virtual void retranslateStrings(); +}; + +#endif diff --git a/plugins/smplayer_plugin/prefperformance.ui b/plugins/smplayer_plugin/prefperformance.ui new file mode 100644 index 000000000..53fb69fe8 --- /dev/null +++ b/plugins/smplayer_plugin/prefperformance.ui @@ -0,0 +1,749 @@ + + PrefPerformance + + + + 0 + 0 + 454 + 591 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + &Performance + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Priority + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Select the priority for the MPlayer process. + + + false + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Priorit&y: + + + false + + + priority_combo + + + + + + + + realtime + + + + + high + + + + + abovenormal + + + + + normal + + + + + belownormal + + + + + idle + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 201 + 21 + + + + + + + + + + + + + &Allow frame drop + + + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + threads_spin + + + + + + + 1 + + + 8 + + + 1 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + H.264 + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Loop &filter + + + loopfilter_combo + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Synchronization + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Audio/&video auto synchronization + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 31 + + + + + + + + false + + + Fact&or: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + autosync_spin + + + + + + + false + + + 1 + + + 1000 + + + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Fast audio track switching + + + fast_audio_combo + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Fast &seek to chapters in dvds + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + &Cache + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + KB + + + + + + + Qt::Horizontal + + + + 211 + 27 + + + + + + + + KB + + + + + + + KB + + + + + + + 100000 + + + + + + + Cache for &DVDs: + + + cache_dvds_spin + + + + + + + Setting a cache may improve performance on slow media + + + false + + + + + + + Cache for &local files: + + + cache_files_spin + + + + + + + Cache for &streams: + + + cache_streams_spin + + + + + + + Qt::Horizontal + + + + 211 + 27 + + + + + + + + Qt::Horizontal + + + + 211 + 20 + + + + + + + + KB + + + + + + + 100000 + + + + + + + 100000 + + + + + + + Qt::Vertical + + + + 20 + 351 + + + + + + + + Cache for &audio CDs: + + + cache_cds_spin + + + + + + + 100000 + + + + + + + KB + + + + + + + Qt::Horizontal + + + + 221 + 27 + + + + + + + + 100000 + + + + + + + Cache for &VCDs: + + + cache_vcds_spin + + + + + + + Qt::Horizontal + + + + 201 + 27 + + + + + + + + + + + + + TristateCombo + QComboBox +
    tristatecombo.h
    +
    +
    + + tabWidget + priority_combo + framedrop_check + hardframedrop_check + threads_spin + loopfilter_combo + autosync_check + autosync_spin + fast_audio_combo + fast_chapter_check + cache_files_spin + cache_streams_spin + cache_dvds_spin + cache_cds_spin + cache_vcds_spin + + + + + autosync_check + toggled(bool) + factor_label + setEnabled(bool) + + + 270 + 381 + + + 90 + 416 + + + + + autosync_check + toggled(bool) + autosync_spin + setEnabled(bool) + + + 270 + 381 + + + 147 + 416 + + + + +
    diff --git a/plugins/smplayer_plugin/prefplaylist.cpp b/plugins/smplayer_plugin/prefplaylist.cpp new file mode 100644 index 000000000..d5b3bddd6 --- /dev/null +++ b/plugins/smplayer_plugin/prefplaylist.cpp @@ -0,0 +1,92 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "prefplaylist.h" +#include "preferences.h" +#include "images.h" + +PrefPlaylist::PrefPlaylist(QWidget * parent, Qt::WindowFlags f) + : PrefWidget(parent, f ) +{ + setupUi(this); + + createHelp(); +} + +PrefPlaylist::~PrefPlaylist() +{ +} + +QString PrefPlaylist::sectionName() { + return tr("Playlist"); +} + +QPixmap PrefPlaylist::sectionIcon() { + return Images::icon("playlist"); +} + +void PrefPlaylist::retranslateStrings() { + retranslateUi(this); + createHelp(); +} + +void PrefPlaylist::setData(Preferences * pref) { + setAutoAddFilesToPlaylist( pref->auto_add_to_playlist ); + setAddConsecutiveFiles( pref->add_to_playlist_consecutive_files ); +} + +void PrefPlaylist::getData(Preferences * pref) { + requires_restart = false; + + pref->auto_add_to_playlist = autoAddFilesToPlaylist(); + pref->add_to_playlist_consecutive_files = addConsecutiveFiles(); +} + +void PrefPlaylist::setAutoAddFilesToPlaylist(bool b) { + auto_add_to_playlist_check->setChecked(b); +} + +bool PrefPlaylist::autoAddFilesToPlaylist() { + return auto_add_to_playlist_check->isChecked(); +} + +void PrefPlaylist::setAddConsecutiveFiles(bool b) { + add_consecutive_files_check->setChecked(b); +} + +bool PrefPlaylist::addConsecutiveFiles() { + return add_consecutive_files_check->isChecked(); +} + + +void PrefPlaylist::createHelp() { + clearHelp(); + + setWhatsThis(auto_add_to_playlist_check, tr("Automatically add files to playlist"), + tr("If this option is enabled, every time a file is opened, SMPlayer " + "will first clear the playlist and then add the file to it. In " + "case of DVDs, CDs and VCDs, all titles in the disc will be added " + "to the playlist.") ); + + setWhatsThis(add_consecutive_files_check, tr("Add consecutive files"), + tr("If this option is enabled, SMPlayer will look for consecutive " + "files (e.g. video_1.avi, video_2.avi...) and if found, they'll be " + "added to the playlist.") ); +} + +#include "moc_prefplaylist.cpp" diff --git a/plugins/smplayer_plugin/prefplaylist.h b/plugins/smplayer_plugin/prefplaylist.h new file mode 100644 index 000000000..cf49f35fd --- /dev/null +++ b/plugins/smplayer_plugin/prefplaylist.h @@ -0,0 +1,57 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFPLAYLIST_H_ +#define _PREFPLAYLIST_H_ + +#include "ui_prefplaylist.h" +#include "prefwidget.h" + +class Preferences; + +class PrefPlaylist : public PrefWidget, public Ui::PrefPlaylist +{ + Q_OBJECT + +public: + PrefPlaylist( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefPlaylist(); + + virtual QString sectionName(); + virtual QPixmap sectionIcon(); + + // Pass data to the dialog + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + +protected: + virtual void createHelp(); + + void setAutoAddFilesToPlaylist(bool b); + bool autoAddFilesToPlaylist(); + + void setAddConsecutiveFiles(bool b); + bool addConsecutiveFiles(); + +protected: + virtual void retranslateStrings(); +}; + +#endif diff --git a/plugins/smplayer_plugin/prefplaylist.ui b/plugins/smplayer_plugin/prefplaylist.ui new file mode 100644 index 000000000..ef11ce443 --- /dev/null +++ b/plugins/smplayer_plugin/prefplaylist.ui @@ -0,0 +1,116 @@ + + PrefPlaylist + + + + 0 + 0 + 376 + 367 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + &Playlist + + + + + + &Automatically add files to playlist + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + false + + + + 0 + 0 + + + + Add &consecutive files + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + auto_add_to_playlist_check + toggled(bool) + add_consecutive_files_check + setEnabled(bool) + + + 224 + 56 + + + 237 + 87 + + + + + diff --git a/plugins/smplayer_plugin/prefsubtitles.cpp b/plugins/smplayer_plugin/prefsubtitles.cpp new file mode 100644 index 000000000..97c788a9a --- /dev/null +++ b/plugins/smplayer_plugin/prefsubtitles.cpp @@ -0,0 +1,496 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "prefsubtitles.h" +#include "images.h" +#include "preferences.h" +#include "paths.h" +#include "assstyles.h" +#include "filedialog.h" +#include "languages.h" + +#include + +PrefSubtitles::PrefSubtitles(QWidget * parent, Qt::WindowFlags f) + : PrefWidget(parent, f ) +{ + setupUi(this); + + ttf_font_edit->setDialogType(FileChooser::GetFileName); +#ifdef Q_OS_WIN + ttf_font_edit->setOptions(QFileDialog::DontUseNativeDialog); +#endif + + connect( style_border_style_combo, SIGNAL(currentIndexChanged(int)), + this, SLOT(checkBorderStyleCombo(int)) ); + + retranslateStrings(); +} + +PrefSubtitles::~PrefSubtitles() +{ +} + +QString PrefSubtitles::sectionName() { + return tr("Subtitles"); +} + +QPixmap PrefSubtitles::sectionIcon() { + return Images::icon("pref_subtitles"); +} + + +void PrefSubtitles::retranslateStrings() { + int font_autoscale_item = font_autoscale_combo->currentIndex(); + int font_autoload_item = font_autoload_combo->currentIndex(); + + retranslateUi(this); + + font_autoscale_combo->setCurrentIndex(font_autoscale_item); + font_autoload_combo->setCurrentIndex(font_autoload_item); + + // Encodings combo + //int font_encoding_item = font_encoding_combo->currentIndex(); + QString current_encoding = fontEncoding(); + QString current_enca_lang = encaLang(); + font_encoding_combo->clear(); + enca_lang_combo->clear(); + + QMap l = Languages::encodings(); + QMapIterator i(l); + while (i.hasNext()) { + i.next(); + font_encoding_combo->addItem( i.value() + " (" + i.key() + ")", i.key() ); + } + l = Languages::list(); i = l; + while (i.hasNext()) { + i.next(); + enca_lang_combo->addItem( i.value() + " (" + i.key() + ")", i.key() ); + } + font_encoding_combo->model()->sort(0); + enca_lang_combo->model()->sort(0); + //font_encoding_combo->setCurrentIndex(font_encoding_item); + setFontEncoding(current_encoding); + setEncaLang(current_enca_lang); + + sub_pos_label->setNum( sub_pos_slider->value() ); + + ttf_font_edit->setCaption(tr("Choose a ttf file")); + ttf_font_edit->setFilter(tr("Truetype Fonts") + " (*.ttf)"); + + // Ass styles + int alignment_item = style_alignment_combo->currentIndex(); + style_alignment_combo->clear(); + style_alignment_combo->addItem(tr("Left", "horizontal alignment"), 1); + style_alignment_combo->addItem(tr("Centered", "horizontal alignment"), 2); + style_alignment_combo->addItem(tr("Right", "horizontal alignment"), 3); + style_alignment_combo->setCurrentIndex(alignment_item); + + int valignment_item = style_valignment_combo->currentIndex(); + style_valignment_combo->clear(); + style_valignment_combo->addItem(tr("Bottom", "vertical alignment")); + style_valignment_combo->addItem(tr("Middle", "vertical alignment")); + style_valignment_combo->addItem(tr("Top", "vertical alignment")); + style_valignment_combo->setCurrentIndex(valignment_item); + + int borderstyle_item = style_border_style_combo->currentIndex(); + style_border_style_combo->clear(); + style_border_style_combo->addItem(tr("Outline", "border style"), 1); + style_border_style_combo->addItem(tr("Opaque box", "border style"), 3); + style_border_style_combo->setCurrentIndex(borderstyle_item); + + createHelp(); +} + +void PrefSubtitles::setData(Preferences * pref) { + setFontName( pref->font_name ); + setFontFile( pref->font_file ); + setUseFontconfig( pref->use_fontconfig ); + setFontAutoscale( pref->font_autoscale ); + setFontTextscale( pref->initial_sub_scale ); + setAssFontScale( pref->initial_sub_scale_ass ); + setAutoloadSub( pref->autoload_sub ); + setFontFuzziness( pref->subfuzziness ); + setFontEncoding( pref->subcp ); + setUseEnca( pref->use_enca ); + setEncaLang( pref->enca_lang ); + setUseFontASS( pref->use_ass_subtitles ); + setAssLineSpacing( pref->ass_line_spacing ); + setSubPos( pref->initial_sub_pos ); + setSubtitlesOnScreenshots( pref->subtitles_on_screenshots ); + setFreetypeSupport( pref->freetype_support ); + + // Load ass styles + style_font_combo->setCurrentText(pref->ass_styles.fontname); + style_size_spin->setValue(pref->ass_styles.fontsize); + style_text_color_button->setColor(pref->ass_styles.primarycolor); + style_border_color_button->setColor(pref->ass_styles.backcolor); + style_bold_check->setChecked(pref->ass_styles.bold); + style_italic_check->setChecked(pref->ass_styles.italic); + style_alignment_combo->setCurrentIndex(style_alignment_combo->findData(pref->ass_styles.halignment)); + style_valignment_combo->setCurrentIndex(pref->ass_styles.valignment); + style_border_style_combo->setCurrentIndex(style_border_style_combo->findData(pref->ass_styles.borderstyle)); + style_outline_spin->setValue(pref->ass_styles.outline); + style_shadow_spin->setValue(pref->ass_styles.shadow); + style_marginl_spin->setValue(pref->ass_styles.marginl); + style_marginr_spin->setValue(pref->ass_styles.marginr); + style_marginv_spin->setValue(pref->ass_styles.marginv); +} + +void PrefSubtitles::getData(Preferences * pref) { + requires_restart = false; + + TEST_AND_SET(pref->font_name, fontName()); + TEST_AND_SET(pref->font_file, fontFile()); + TEST_AND_SET(pref->use_fontconfig, useFontconfig()); + TEST_AND_SET(pref->font_autoscale, fontAutoscale()); + pref->initial_sub_scale = fontTextscale(); + pref->initial_sub_scale_ass = assFontScale(); + TEST_AND_SET(pref->autoload_sub, autoloadSub()); + TEST_AND_SET(pref->subfuzziness, fontFuzziness()); + TEST_AND_SET(pref->subcp, fontEncoding()); + TEST_AND_SET(pref->use_enca, useEnca()); + TEST_AND_SET(pref->enca_lang, encaLang()); + TEST_AND_SET(pref->use_ass_subtitles, useFontASS()); + TEST_AND_SET(pref->ass_line_spacing, assLineSpacing()); + pref->initial_sub_pos = subPos(); + TEST_AND_SET(pref->subtitles_on_screenshots, subtitlesOnScreenshots()); + TEST_AND_SET(pref->freetype_support, freetypeSupport()); + + // Save ass styles + TEST_AND_SET(pref->ass_styles.fontname, style_font_combo->currentText()); + TEST_AND_SET(pref->ass_styles.fontsize, style_size_spin->value()); + TEST_AND_SET(pref->ass_styles.primarycolor, style_text_color_button->color().rgb()); + TEST_AND_SET(pref->ass_styles.backcolor, style_border_color_button->color().rgb()); + TEST_AND_SET(pref->ass_styles.bold, style_bold_check->isChecked()); + TEST_AND_SET(pref->ass_styles.italic, style_italic_check->isChecked()); + TEST_AND_SET(pref->ass_styles.halignment, style_alignment_combo->itemData(style_alignment_combo->currentIndex()).toInt()); + TEST_AND_SET(pref->ass_styles.valignment, style_valignment_combo->currentIndex()); + TEST_AND_SET(pref->ass_styles.borderstyle, style_border_style_combo->itemData(style_border_style_combo->currentIndex()).toInt()); + TEST_AND_SET(pref->ass_styles.outline, style_outline_spin->value()); + TEST_AND_SET(pref->ass_styles.shadow, style_shadow_spin->value()); + TEST_AND_SET(pref->ass_styles.marginl, style_marginl_spin->value()); + TEST_AND_SET(pref->ass_styles.marginr, style_marginr_spin->value()); + TEST_AND_SET(pref->ass_styles.marginv, style_marginv_spin->value()); + + pref->ass_styles.exportStyles( Paths::subtitleStyleFile() ); +} + +void PrefSubtitles::checkBorderStyleCombo( int index ) { + bool b = (index == 0); + style_outline_spin->setEnabled(b); + style_shadow_spin->setEnabled(b); + style_outline_label->setEnabled(b); + style_shadow_label->setEnabled(b); +} + + +void PrefSubtitles::setFontName(QString font_name) { + fontCombo->setCurrentText(font_name); +} + +QString PrefSubtitles::fontName() { + return fontCombo->currentText(); +} + +void PrefSubtitles::setFontFile(QString font_file) { + ttf_font_edit->setText( font_file ); +} + +QString PrefSubtitles::fontFile() { + return ttf_font_edit->text(); +} + + +void PrefSubtitles::setUseFontconfig(bool b) { + system_font_button->setChecked(b); + ttf_font_button->setChecked(!b); +} + +bool PrefSubtitles::useFontconfig() { + return system_font_button->isChecked(); +} + +void PrefSubtitles::setFontAutoscale(int n) { + font_autoscale_combo->setCurrentIndex(n); +} + +int PrefSubtitles::fontAutoscale() { + return font_autoscale_combo->currentIndex(); +} + +void PrefSubtitles::setFontTextscale(double n) { + font_text_scale_spin->setValue(n); +} + +double PrefSubtitles::fontTextscale() { + return font_text_scale_spin->value(); +} + +void PrefSubtitles::setAssFontScale(double n) { + ass_font_scale_spin->setValue(n); +} + +double PrefSubtitles::assFontScale() { + return ass_font_scale_spin->value(); +} + +void PrefSubtitles::setAutoloadSub(bool v) { + font_autoload_check->setChecked(v); +} + +bool PrefSubtitles::autoloadSub() { + return font_autoload_check->isChecked(); +} + +void PrefSubtitles::setFontEncoding(QString s) { + int i = font_encoding_combo->findData(s); + font_encoding_combo->setCurrentIndex(i); +} + +QString PrefSubtitles::fontEncoding() { + int index = font_encoding_combo->currentIndex(); + return font_encoding_combo->itemData(index).toString(); +} + +void PrefSubtitles::setEncaLang(QString s) { + int i = enca_lang_combo->findData(s); + enca_lang_combo->setCurrentIndex(i); +} + +QString PrefSubtitles::encaLang() { + int index = enca_lang_combo->currentIndex(); + return enca_lang_combo->itemData(index).toString(); +} + +void PrefSubtitles::setUseEnca(bool b) { + use_enca_check->setChecked(b); +} + +bool PrefSubtitles::useEnca() { + return use_enca_check->isChecked(); +} + +void PrefSubtitles::setSubPos(int pos) { + sub_pos_slider->setValue(pos); +} + +int PrefSubtitles::subPos() { + return sub_pos_slider->value(); +} + +void PrefSubtitles::setUseFontASS(bool v) { + ass_subs_button->setChecked(v); + normal_subs_button->setChecked(!v); +} + +bool PrefSubtitles::useFontASS() { + return ass_subs_button->isChecked(); +} + +void PrefSubtitles::setFontFuzziness(int n) { + font_autoload_combo->setCurrentIndex(n); +} + +int PrefSubtitles::fontFuzziness() { + return font_autoload_combo->currentIndex(); +} + +void PrefSubtitles::setSubtitlesOnScreenshots(bool b) { + subtitles_on_screeshots_check->setChecked(b); +} + +bool PrefSubtitles::subtitlesOnScreenshots() { + return subtitles_on_screeshots_check->isChecked(); +} + +void PrefSubtitles::setAssLineSpacing(int spacing) { + ass_line_spacing_spin->setValue(spacing); +} + +int PrefSubtitles::assLineSpacing() { + return ass_line_spacing_spin->value(); +} + +void PrefSubtitles::on_ass_subs_button_toggled(bool b) { + if (b) + stackedWidget->setCurrentIndex(1); + else + stackedWidget->setCurrentIndex(0); +} + +void PrefSubtitles::setFreetypeSupport(bool b) { + freetype_check->setChecked(b); +} + +bool PrefSubtitles::freetypeSupport() { + return freetype_check->isChecked(); +} + +void PrefSubtitles::on_freetype_check_toggled(bool b) { + qDebug("PrefSubtitles:on_freetype_check_toggled: %d", b); + if (!b) { + ass_subs_button->setChecked(false); + normal_subs_button->setChecked(true); + } +} + +void PrefSubtitles::createHelp() { + clearHelp(); + + addSectionTitle(tr("Subtitles")); + + setWhatsThis(font_autoload_combo, tr("Autoload"), + tr("Select the subtitle autoload method.") ); + + setWhatsThis(font_autoload_check, tr("Select first available subtitle"), + tr("If there are one or more subtitle tracks available, one of them " + "will be automatically selected, usually the first one, although if " + "one of them matches the user's preferred language that one will " + "be used instead.") ); + + setWhatsThis(font_encoding_combo, tr("Default subtitle encoding"), + tr("Select the encoding which will be used for subtitle files " + "by default.") ); + + setWhatsThis(use_enca_check, tr("Try to autodetect for this language"), + tr("When this option is on, the encoding of the subtitles will be " + "tried to be autodetected for the given language. " + "It will fall back to the default encoding if the autodetection " + "fails. This option requires a MPlayer compiled with ENCA " + "support.") ); + + setWhatsThis(enca_lang_combo, tr("Subtitle language"), + tr("Select the language for which you want the encoding to be guessed " + "automatically.") ); + + setWhatsThis(subtitles_on_screeshots_check, + tr("Include subtitles on screenshots"), + tr("If this option is checked, the subtitles will appear in the " + "screenshots. Note: it may cause some troubles sometimes." ) ); + + setWhatsThis(freetype_check, tr("Freetype support"), + tr("You should normally not disable this option. Do it only if your " + "MPlayer is compiled without freetype support. " + "Disabling this option could make that subtitles won't work " + "at all!") ); + + addSectionTitle(tr("Font")); + + setWhatsThis(normal_subs_button, tr("Enable normal subtitles"), + tr("Click this button to select the normal/traditional subtitles. " + "This kind of subtitles can only display white subtitles.")); + + setWhatsThis(ass_subs_button, tr("Enable SSA/ASS subtitles"), + tr("Click this button to enable the new SSA/ASS library. " + "This allows to display subtitles with multiple colors, fonts...")); + + addSectionTitle(tr("Normal subtitles")); + + setWhatsThis(ttf_font_edit, tr("TTF font"), + tr("Here you can select a ttf font to be used for the subtitles. " + "Usually you'll find a lot of ttf fonts in %1") +#ifdef Q_OS_WIN + .arg("C:\\Windows\\Fonts\\") +#else + .arg("/usr/X11R6/lib/X11/fonts/truetype/") +#endif + ); + + setWhatsThis(fontCombo, tr("System font"), + tr("Here you can select a system font to be used for the subtitles " + "and OSD. Note: requires a MPlayer with fontconfig support.") ); + + setWhatsThis(font_autoscale_combo, tr("Autoscale"), + tr("Select the subtitle autoscaling method.") ); + + QString scale_note = tr("This option does NOT change the size of the " + "subtitles in the current video. To do so, use the options " + "Size+ and Size- in the subtitles menu."); + + setWhatsThis(font_text_scale_spin, tr("Default scale"), + tr("This option specifies the default font scale for normal " + "subtitles which will be used for new opened files.") +"
    "+ + scale_note); + + setWhatsThis(sub_pos_slider, tr("Subtitle position"), + tr("This option specifies the position of the subtitles over the " + "video window. 100 means the bottom, while 0 means " + "the top." ) ); + + addSectionTitle(tr("SSA/ASS subtitles")); + + setWhatsThis(ass_font_scale_spin, tr("Default scale"), + tr("This option specifies the default font scale for SSA/ASS " + "subtitles which will be used for new opened files.") +"
    "+ + scale_note); + + setWhatsThis(ass_line_spacing_spin, tr("Line spacing"), + tr("This specifies the spacing that will be used to separate " + "multiple lines. It can have negative values.") ); + + setWhatsThis(style_font_combo, tr("Font"), + tr("Select the font for the subtitles.") ); + + setWhatsThis(style_size_spin, tr("Size"), + tr("The size in pixels.") ); + + setWhatsThis(style_bold_check, tr("Bold"), + tr("If checked, the text will be displayed in bold.") ); + + setWhatsThis(style_italic_check, tr("Italic"), + tr("If checked, the text will be displayed in italic.") ); + + setWhatsThis(style_text_color_button, tr("Text color"), + tr("Select the color for the text of the subtitles.") ); + + setWhatsThis(style_border_color_button, tr("Border color"), + tr("Select the color for the border of the subtitles.") ); + + setWhatsThis(style_marginl_spin, tr("Left margin"), + tr("Specifies the left margin in pixels.") ); + + setWhatsThis(style_marginr_spin, tr("Right margin"), + tr("Specifies the right margin in pixels.") ); + + setWhatsThis(style_marginv_spin, tr("Vertical margin"), + tr("Specifies the vertical margin in pixels.") ); + + setWhatsThis(style_alignment_combo, tr("Horizontal alignment"), + tr("Specifies the horizontal alignment. Possible values are " + "left, centered and right.") ); + + setWhatsThis(style_valignment_combo, tr("Vertical alignment"), + tr("Specifies the vertical alignment. Possible values: " + "bottom, middle and top.") ); + + setWhatsThis(style_border_style_combo, tr("Border style"), + tr("Specifies the border style. Possible values: outline " + "and opaque box.") ); + + setWhatsThis(style_outline_spin, tr("Outline"), + tr("If border style is set to outline, this option specifies " + "the width of the outline around the text in pixels.") ); + + setWhatsThis(style_shadow_spin, tr("Shadow"), + tr("If border style is set to outline, this option specifies " + "the depth of the drop shadow behind the text in pixels.") ); +} + +#include "moc_prefsubtitles.cpp" diff --git a/plugins/smplayer_plugin/prefsubtitles.h b/plugins/smplayer_plugin/prefsubtitles.h new file mode 100644 index 000000000..2bc5ab473 --- /dev/null +++ b/plugins/smplayer_plugin/prefsubtitles.h @@ -0,0 +1,108 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFSUBTITLES_H_ +#define _PREFSUBTITLES_H_ + +#include "ui_prefsubtitles.h" +#include "prefwidget.h" + +class Preferences; +class Encodings; + +class PrefSubtitles : public PrefWidget, public Ui::PrefSubtitles +{ + Q_OBJECT + +public: + PrefSubtitles( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefSubtitles(); + + virtual QString sectionName(); + virtual QPixmap sectionIcon(); + + // Pass data to the dialog + void setData(Preferences * pref); + + // Apply changes + void getData(Preferences * pref); + +protected: + virtual void createHelp(); + + void setFontName(QString font_name); + QString fontName(); + + void setFontFile(QString font_file); + QString fontFile(); + + void setUseFontconfig(bool b); + bool useFontconfig(); + + void setFontAutoscale(int n); + int fontAutoscale(); + + void setFontTextscale(double n); + double fontTextscale(); + + void setAssFontScale(double n); + double assFontScale(); + + void setAutoloadSub(bool v); + bool autoloadSub(); + + void setFontEncoding(QString s); + QString fontEncoding(); + + void setUseEnca(bool v); + bool useEnca(); + + void setEncaLang(QString s); + QString encaLang(); + + void setSubPos(int pos); + int subPos(); + + void setUseFontASS(bool v); + bool useFontASS(); + + void setAssLineSpacing(int spacing); + int assLineSpacing(); + + void setFontFuzziness(int n); + int fontFuzziness(); + + void setSubtitlesOnScreenshots(bool b); + bool subtitlesOnScreenshots(); + + void setFreetypeSupport(bool b); + bool freetypeSupport(); + +protected slots: + void on_ass_subs_button_toggled(bool b); + void on_freetype_check_toggled(bool b); + void checkBorderStyleCombo( int index ); + +protected: + virtual void retranslateStrings(); + +private: + Encodings * encodings; +}; + +#endif diff --git a/plugins/smplayer_plugin/prefsubtitles.ui b/plugins/smplayer_plugin/prefsubtitles.ui new file mode 100644 index 000000000..260bddeed --- /dev/null +++ b/plugins/smplayer_plugin/prefsubtitles.ui @@ -0,0 +1,1321 @@ + + PrefSubtitles + + + + 0 + 0 + 534 + 469 + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + &Subtitles + + + + 6 + + + + + Autoload + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + Au&toload subtitles files (*.srt, *.sub...): + + + false + + + font_autoload_combo + + + + + + + S&elect first available subtitle + + + + + + + + Same name as movie + + + + + All subs containing movie name + + + + + All subs in directory + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 131 + 21 + + + + + + + + + + + Encoding + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + &Default subtitle encoding: + + + false + + + font_encoding_combo + + + + + + + + 0 + 0 + + + + false + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 161 + 31 + + + + + + + + + + 0 + + + + + Try to a&utodetect for this language: + + + + + + + false + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + &Include subtitles on screenshots + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + Freet&ype support + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + &Font and colors + + + + + + Enable &normal subtitles + + + true + + + true + + + + + + + Enable SSA/&ASS subtitles + + + true + + + true + + + + + + + Qt::Horizontal + + + + 291 + 20 + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + 0 + + + + + + + Font + + + + 4 + + + 4 + + + 4 + + + 4 + + + 6 + + + 6 + + + + + false + + + + + + + false + + + + 0 + 0 + + + + + + + + Select the font which will be used for subtitles (and OSD): + + + false + + + + + + + S&ystem font: + + + + + + + Qt::Horizontal + + + + 121 + 20 + + + + + + + + &TTF font: + + + + + + + + + + Size + + + + 4 + + + 4 + + + 4 + + + 4 + + + 6 + + + 6 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + A&utoscale: + + + false + + + font_autoscale_combo + + + + + + + + No autoscale + + + + + Proportional to movie height + + + + + Proportional to movie width + + + + + Proportional to movie diagonal + + + + + + + + Qt::Horizontal + + + + 71 + 20 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + 0.200000000000000 + + + + + + + Default s&cale: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + font_text_scale_spin + + + + + + + + + + Position + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Default &position of the subtitles on screen + + + Qt::AlignVCenter + + + true + + + sub_pos_slider + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + 0 + + + 100 + + + 1 + + + Qt::Horizontal + + + + + + + 0 + + + false + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Top + + + false + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 131 + 20 + + + + + + + + Bottom + + + false + + + + + + + + + + + + Qt::Vertical + + + + 490 + 31 + + + + + + + + + + + + + + Defa&ult scale: + + + ass_font_scale_spin + + + + + + + + 0 + 0 + + + + 100.000000000000000 + + + 0.200000000000000 + + + + + + + Qt::Horizontal + + + + 121 + 20 + + + + + + + + &Line spacing: + + + ass_line_spacing_spin + + + + + + + -20 + + + 20 + + + + + + + + + true + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + true + + + + + + + Font + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + + + + + + + + + Si&ze: + + + style_size_spin + + + + + + + + 0 + 0 + + + + 1 + + + 10 + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 60 + 20 + + + + + + + + Bol&d + + + + + + + &Italic + + + + + + + + + + + + Colors + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + &Text: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + style_text_color_button + + + + + + + + + + + + + + &Border: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + style_border_color_button + + + + + + + + + + + + + + + + + Margins + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + L&eft: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + style_marginl_spin + + + + + + + + + + &Right: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + style_marginr_spin + + + + + + + + + + Verti&cal: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + style_marginv_spin + + + + + + + + + + Qt::Horizontal + + + + 101 + 25 + + + + + + + + + + + Alignment + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + &Horizontal: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + style_alignment_combo + + + + + + + + + + &Vertical: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + style_valignment_combo + + + + + + + + + + + + + + + Border st&yle: + + + style_border_style_combo + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &Outline: + + + style_outline_spin + + + + + + + 0 + + + 4 + + + 0 + + + + + + + Shado&w: + + + style_shadow_spin + + + + + + + 4 + + + + + + + + + + + + Qt::Vertical + + + + 479 + 20 + + + + + + + + + + + + + + + + + FileChooser + QLineEdit +
    filechooser.h
    +
    + + MyFontComboBox + QFontComboBox +
    mycombobox.h
    +
    + + SelectColorButton + QPushButton +
    selectcolorbutton.h
    +
    +
    + + subtitles_tab + font_autoload_combo + font_autoload_check + font_encoding_combo + use_enca_check + enca_lang_combo + subtitles_on_screeshots_check + normal_subs_button + ass_subs_button + ttf_font_button + ttf_font_edit + system_font_button + fontCombo + font_autoscale_combo + font_text_scale_spin + ass_font_scale_spin + ass_line_spacing_spin + style_font_combo + style_size_spin + style_bold_check + style_italic_check + style_text_color_button + style_border_color_button + style_marginl_spin + style_marginr_spin + style_marginv_spin + style_alignment_combo + style_valignment_combo + style_border_style_combo + style_outline_spin + style_shadow_spin + + + + + ttf_font_button + toggled(bool) + ttf_font_edit + setEnabled(bool) + + + 83 + 114 + + + 273 + 114 + + + + + system_font_button + toggled(bool) + fontCombo + setEnabled(bool) + + + 74 + 138 + + + 264 + 138 + + + + + use_enca_check + toggled(bool) + enca_lang_combo + setEnabled(bool) + + + 118 + 245 + + + 258 + 245 + + + + + sub_pos_slider + valueChanged(int) + sub_pos_label + setNum(int) + + + 260 + 353 + + + 496 + 353 + + + + +
    diff --git a/plugins/smplayer_plugin/prefwidget.cpp b/plugins/smplayer_plugin/prefwidget.cpp new file mode 100644 index 000000000..95e86f3e6 --- /dev/null +++ b/plugins/smplayer_plugin/prefwidget.cpp @@ -0,0 +1,70 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "prefwidget.h" +#include + +PrefWidget::PrefWidget(QWidget * parent, Qt::WindowFlags f ) + : QWidget(parent, f) +{ + requires_restart = false; + help_message = ""; +} + +PrefWidget::~PrefWidget() { +} + +QString PrefWidget::sectionName() { + return QString(); +} + +QPixmap PrefWidget::sectionIcon() { + return QPixmap(); +} + +void PrefWidget::addSectionTitle(const QString & title) { + help_message += "

    "+title+"

    "; +} + +void PrefWidget::setWhatsThis( QWidget *w, const QString & title, + const QString & text) +{ + w->setWhatsThis(text); + help_message += ""+title+"
    "+text+"

    "; + + w->setToolTip( ""+ text +"" ); +} + +void PrefWidget::clearHelp() { + help_message = "

    " + sectionName() + "

    "; +} + +void PrefWidget::createHelp() { +} + +// Language change stuff +void PrefWidget::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QWidget::changeEvent(e); + } +} + +void PrefWidget::retranslateStrings() { +} diff --git a/plugins/smplayer_plugin/prefwidget.h b/plugins/smplayer_plugin/prefwidget.h new file mode 100644 index 000000000..76e75d01e --- /dev/null +++ b/plugins/smplayer_plugin/prefwidget.h @@ -0,0 +1,67 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _PREFWIDGET_H_ +#define _PREFWIDGET_H_ + +#include +#include +#include + + +#define TEST_AND_SET( Pref, Dialog ) \ + if ( Pref != Dialog ) { Pref = Dialog; requires_restart = TRUE; } + +class QEvent; + +class PrefWidget : public QWidget +{ + +public: + PrefWidget(QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~PrefWidget(); + + // Return the name of the section + virtual QString sectionName(); + + virtual QPixmap sectionIcon(); + + // Return true if the changes made require to restart the mplayer + // process. Should be call just after the changes have been applied. + virtual bool requiresRestart() { return requires_restart; }; + + virtual QString help() { return help_message; }; + +protected: + virtual void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + + // Help + void addSectionTitle(const QString & title); + void setWhatsThis( QWidget *w, const QString & title, const QString & text); + void clearHelp(); + + virtual void createHelp(); + + bool requires_restart; + +private: + QString help_message; +}; + +#endif diff --git a/plugins/smplayer_plugin/recents.cpp b/plugins/smplayer_plugin/recents.cpp new file mode 100644 index 000000000..2fce22ac5 --- /dev/null +++ b/plugins/smplayer_plugin/recents.cpp @@ -0,0 +1,81 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "recents.h" + +Recents::Recents() +{ + l.clear(); + max_items = 10; +} + +Recents::~Recents() { +} + +void Recents::clear() { + l.clear(); +} + +int Recents::count() { + return l.count(); +} + +void Recents::setMaxItems(int n_items) { + max_items = n_items; + fromStringList(l); +} + +void Recents::addItem(QString s) { + qDebug("Recents::addItem: '%s'", s.toUtf8().data()); + + int pos = l.indexOf(s); + if (pos != -1) l.removeAt(pos); + l.prepend(s); + + if (l.count() > max_items) l.removeLast(); +} + +QString Recents::item(int n) { + return l[n]; +} + +void Recents::list() { + qDebug("Recents::list"); + + for (int n=0; n < l.count(); n++) { + qDebug(" * item %d: '%s'", n, l[n].toUtf8().constData() ); + } +} + +void Recents::fromStringList(QStringList list) { + l.clear(); + + int max = list.count(); + if (max_items < max) max = max_items; + + //qDebug("max_items: %d, count: %d max: %d", max_items, l.count(), max); + + for (int n = 0; n < max; n++) { + l.append( list[n] ); + } +} + +QStringList Recents::toStringList() { + return l; +} + diff --git a/plugins/smplayer_plugin/recents.h b/plugins/smplayer_plugin/recents.h new file mode 100644 index 000000000..96e869bdc --- /dev/null +++ b/plugins/smplayer_plugin/recents.h @@ -0,0 +1,51 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _RECENTS_H_ +#define _RECENTS_H_ + +#include + +class Recents +{ + +public: + Recents(); + virtual ~Recents(); + + virtual void clear(); + + virtual void addItem(QString s); + virtual QString item(int n); + + virtual int count(); + + virtual void setMaxItems(int n_items); + virtual int maxItems() { return max_items; }; + + virtual void fromStringList(QStringList list); + virtual QStringList toStringList(); + + virtual void list(); + +protected: + int max_items; + QStringList l; +}; + +#endif diff --git a/plugins/smplayer_plugin/screensaver.cpp b/plugins/smplayer_plugin/screensaver.cpp new file mode 100644 index 000000000..76deb31c6 --- /dev/null +++ b/plugins/smplayer_plugin/screensaver.cpp @@ -0,0 +1,61 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "screensaver.h" +#include +#include + +WinScreenSaver::WinScreenSaver() { + lowpower = poweroff = screensaver = 0; + state_saved = false; +} + +WinScreenSaver::~WinScreenSaver() { +} + +void WinScreenSaver::disable() { + qDebug("WinScreenSaver::disable"); + + if (!state_saved) { + SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT, 0, &lowpower, 0); + SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0, &poweroff, 0); + SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0, &screensaver, 0); + state_saved = true; + } + + qDebug("WinScreenSaver::disable: lowpower: %d", lowpower); + qDebug("WinScreenSaver::disable: poweroff: %d", poweroff); + qDebug("WinScreenSaver::disable: screensaver: %d", screensaver); + + if (lowpower != 0) SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0); + if (poweroff != 0) SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0); + if (screensaver != 0) SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0); +} + +void WinScreenSaver::restore() { + qDebug("WinScreenSaver::restore"); + + if (state_saved) { + if (lowpower != 0) SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, lowpower, NULL, 0); + if (poweroff != 0) SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, poweroff, NULL, 0); + if (screensaver != 0) SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, screensaver, NULL, 0); + } else { + qWarning("WinScreenSaver::restore: screensaver can't be restored"); + } +} + diff --git a/plugins/smplayer_plugin/screensaver.h b/plugins/smplayer_plugin/screensaver.h new file mode 100644 index 000000000..2ede40b96 --- /dev/null +++ b/plugins/smplayer_plugin/screensaver.h @@ -0,0 +1,38 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//! This class disables and restores the windows screensaver + +#ifndef _WINSCREENSAVER_H_ +#define _WINSCREENSAVER_H_ + +class WinScreenSaver +{ +public: + WinScreenSaver(); + ~WinScreenSaver(); + + void disable(); + void restore(); + +private: + int lowpower, poweroff, screensaver; + bool state_saved; +}; + +#endif diff --git a/plugins/smplayer_plugin/seekwidget.cpp b/plugins/smplayer_plugin/seekwidget.cpp new file mode 100644 index 000000000..b63c51224 --- /dev/null +++ b/plugins/smplayer_plugin/seekwidget.cpp @@ -0,0 +1,60 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "seekwidget.h" +#include +#include + +SeekWidget::SeekWidget( QWidget* parent, Qt::WindowFlags f) + : QWidget(parent, f) +{ + setupUi(this); + time_edit->setDisplayFormat("mm:ss"); +} + +SeekWidget::~SeekWidget() { +} + +void SeekWidget::setIcon(QPixmap icon) { + _image->setText(""); + _image->setPixmap(icon); +} + +const QPixmap * SeekWidget::icon() const { + return _image->pixmap(); +} + +void SeekWidget::setLabel(QString text) { + _label->setText(text); +} + +QString SeekWidget::label() const { + return _label->text(); +} + +void SeekWidget::setTime(int secs) { + QTime t; + time_edit->setTime(t.addSecs(secs)); +} + +int SeekWidget::time() const { + QTime t = time_edit->time(); + return (t.minute() * 60) + t.second(); +} + +#include "moc_seekwidget.cpp" diff --git a/plugins/smplayer_plugin/seekwidget.h b/plugins/smplayer_plugin/seekwidget.h new file mode 100644 index 000000000..e5fcf7c16 --- /dev/null +++ b/plugins/smplayer_plugin/seekwidget.h @@ -0,0 +1,48 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _SEEKWIDGET_H_ +#define _SEEKWIDGET_H_ + +#include "ui_seekwidget.h" +#include +#include + +class SeekWidget : public QWidget, public Ui::SeekWidget +{ + Q_OBJECT + Q_PROPERTY(QPixmap icon READ icon WRITE setIcon) + Q_PROPERTY(QString label READ label WRITE setLabel) + Q_PROPERTY(int time READ time WRITE setTime) + +public: + SeekWidget( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~SeekWidget(); + + int time() const; + const QPixmap * icon() const; + QString label() const; + +public slots: + void setIcon(QPixmap icon); + void setLabel(QString text); + void setTime(int secs); + +}; + +#endif diff --git a/plugins/smplayer_plugin/seekwidget.ui b/plugins/smplayer_plugin/seekwidget.ui new file mode 100644 index 000000000..d6d7a00ed --- /dev/null +++ b/plugins/smplayer_plugin/seekwidget.ui @@ -0,0 +1,73 @@ + + SeekWidget + + + + 0 + 0 + 292 + 31 + + + + + 0 + + + 0 + + + + + icon + + + false + + + + + + + + 7 + 5 + 0 + 0 + + + + label + + + false + + + time_edit + + + + + + + + + + + + + + + + + + + diff --git a/plugins/smplayer_plugin/selectcolorbutton.cpp b/plugins/smplayer_plugin/selectcolorbutton.cpp new file mode 100644 index 000000000..b8477d1eb --- /dev/null +++ b/plugins/smplayer_plugin/selectcolorbutton.cpp @@ -0,0 +1,83 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "selectcolorbutton.h" +#include "colorutils.h" +#include + +#ifdef Q_OS_WIN +#include +#include +#endif + +SelectColorButton::SelectColorButton( QWidget * parent ) + : QPushButton(parent) +{ + connect(this, SIGNAL(clicked()), this, SLOT(selectColor())); + +#ifdef Q_OS_WIN + ignore_change_event = false; +#endif +} + +SelectColorButton::~SelectColorButton() { +} + +void SelectColorButton::setColor(QColor c) { + _color = c; + +#ifdef Q_OS_WIN + QString current_style = qApp->style()->objectName(); + qDebug("SelectColorButton::setColor: current style name: %s", current_style.toUtf8().constData()); + + ignore_change_event = true; + + if ((current_style.startsWith("windowsxp")) || (current_style.startsWith("windowsvista"))) { + setStyleSheet( "border-width: 1px; border-style: solid; border-color: #000000; background: #" + ColorUtils::colorToRRGGBB(_color.rgb()) + ";"); + } else { + setStyleSheet(""); + ColorUtils::setBackgroundColor( this, _color ); + } + + ignore_change_event = false; +#else + //setAutoFillBackground(true); + ColorUtils::setBackgroundColor( this, _color ); +#endif +} + +void SelectColorButton::selectColor() { + QColor c = QColorDialog::getColor( _color, 0 ); + if (c.isValid()) { + setColor( c ); + } +} + +#ifdef Q_OS_WIN +void SelectColorButton::changeEvent(QEvent *e) { + + QPushButton::changeEvent(e); + + if ((e->type() == QEvent::StyleChange) && (!ignore_change_event)) { + setColor( color() ); + } + +} +#endif + +#include "moc_selectcolorbutton.cpp" diff --git a/plugins/smplayer_plugin/selectcolorbutton.h b/plugins/smplayer_plugin/selectcolorbutton.h new file mode 100644 index 000000000..67df36810 --- /dev/null +++ b/plugins/smplayer_plugin/selectcolorbutton.h @@ -0,0 +1,52 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _SELECTCOLORBUTTON_H_ +#define _SELECTCOLORBUTTON_H_ + +#include + +class SelectColorButton : public QPushButton +{ + Q_OBJECT + +public: + SelectColorButton ( QWidget * parent = 0 ); + ~SelectColorButton(); + + QColor color() { return _color;} ; + +public slots: + void setColor(QColor c); + +private slots: + void selectColor(); + +private: + QColor _color; + +#ifdef Q_OS_WIN + bool ignore_change_event; + +protected: + virtual void changeEvent ( QEvent * event ) ; +#endif +}; + +#endif + diff --git a/plugins/smplayer_plugin/shortcutgetter.cpp b/plugins/smplayer_plugin/shortcutgetter.cpp new file mode 100644 index 000000000..bfcd1d5fe --- /dev/null +++ b/plugins/smplayer_plugin/shortcutgetter.cpp @@ -0,0 +1,428 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + Note: The ShortcutGetter class is taken from the source code of Edyuk + (http://www.edyuk.org/), from file 3rdparty/qcumber/qshortcutdialog.cpp + + Copyright (C) 2006 FullMetalCoder + License: GPL + + I've just made a little few changes on it. +*/ + + +/**************************************************************************** +** +** Copyright (C) 2006 FullMetalCoder +** +** This file is part of the Edyuk project (beta version) +** +** This file may be used under the terms of the GNU General Public License +** version 2 as published by the Free Software Foundation and appearing in the +** file GPL.txt included in the packaging of this file. +** +** Notes : Parts of the project are derivative work of Trolltech's QSA library +** or Trolltech's Qt4 framework but, unless notified, every single line of code +** is the work of the Edyuk team or a contributor. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + + +#include "shortcutgetter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 1 + +static QHash keyMap; + +static void initKeyMap() +{ + if ( !keyMap.isEmpty() ) + return; + + /* + I'm a bit unsure about these one... + */ + keyMap[Qt::Key_Escape] = "Escape"; + keyMap[Qt::Key_Return] = "Return"; + keyMap[Qt::Key_Enter] = "Enter"; + keyMap[Qt::Key_Insert] = "Ins"; + keyMap[Qt::Key_Delete] = "Delete"; + keyMap[Qt::Key_Home] = "Home"; + keyMap[Qt::Key_End] = "End"; + keyMap[Qt::Key_Left] = "Left"; + keyMap[Qt::Key_Up] = "Up"; + keyMap[Qt::Key_Right] = "Right"; + keyMap[Qt::Key_Down] = "Down"; + keyMap[Qt::Key_PageUp] = "PgUp"; + keyMap[Qt::Key_PageDown] = "PgDown"; + keyMap[Qt::Key_CapsLock] = "CapsLock"; + keyMap[Qt::Key_NumLock] = "NumLock"; + keyMap[Qt::Key_ScrollLock] = "ScrollLock"; + + /* + These one are quite sure... + */ + keyMap[Qt::Key_F1] = "F1"; + keyMap[Qt::Key_F2] = "F2"; + keyMap[Qt::Key_F3] = "F3"; + keyMap[Qt::Key_F4] = "F4"; + keyMap[Qt::Key_F5] = "F5"; + keyMap[Qt::Key_F6] = "F6"; + keyMap[Qt::Key_F7] = "F7"; + keyMap[Qt::Key_F8] = "F8"; + keyMap[Qt::Key_F9] = "F9"; + keyMap[Qt::Key_F10] = "F10"; + keyMap[Qt::Key_F11] = "F11"; + keyMap[Qt::Key_F12] = "F12"; + keyMap[Qt::Key_F13] = "F13"; + keyMap[Qt::Key_F14] = "F14"; + keyMap[Qt::Key_F15] = "F15"; + keyMap[Qt::Key_F16] = "F16"; + keyMap[Qt::Key_F17] = "F17"; + keyMap[Qt::Key_F18] = "F18"; + keyMap[Qt::Key_F19] = "F19"; + keyMap[Qt::Key_F20] = "F20"; + keyMap[Qt::Key_F21] = "F21"; + keyMap[Qt::Key_F22] = "F22"; + keyMap[Qt::Key_F23] = "F23"; + keyMap[Qt::Key_F24] = "F24"; + keyMap[Qt::Key_F25] = "F25"; + keyMap[Qt::Key_F26] = "F26"; + keyMap[Qt::Key_F27] = "F27"; + keyMap[Qt::Key_F28] = "F28"; + keyMap[Qt::Key_F29] = "F29"; + keyMap[Qt::Key_F30] = "F30"; + keyMap[Qt::Key_F31] = "F31"; + keyMap[Qt::Key_F32] = "F32"; + keyMap[Qt::Key_F33] = "F33"; + keyMap[Qt::Key_F34] = "F34"; + keyMap[Qt::Key_F35] = "F35"; + + keyMap[Qt::Key_Exclam] = "!"; + keyMap[Qt::Key_QuoteDbl] = "\""; + keyMap[Qt::Key_NumberSign] = "-"; + keyMap[Qt::Key_Dollar] = "$"; + keyMap[Qt::Key_Percent] = "%"; + keyMap[Qt::Key_Ampersand] = "&"; + keyMap[Qt::Key_Apostrophe] = "\'"; + keyMap[Qt::Key_ParenLeft] = "("; + keyMap[Qt::Key_ParenRight] = ")"; + keyMap[Qt::Key_Asterisk] = "*"; + keyMap[Qt::Key_Plus] = "+"; + keyMap[Qt::Key_Comma] = ","; + keyMap[Qt::Key_Minus] = "-"; + keyMap[Qt::Key_Period] = "Period"; + keyMap[Qt::Key_Slash] = "/"; + + keyMap[Qt::Key_0] = "0"; + keyMap[Qt::Key_1] = "1"; + keyMap[Qt::Key_2] = "2"; + keyMap[Qt::Key_3] = "3"; + keyMap[Qt::Key_4] = "4"; + keyMap[Qt::Key_5] = "5"; + keyMap[Qt::Key_6] = "6"; + keyMap[Qt::Key_7] = "7"; + keyMap[Qt::Key_8] = "8"; + keyMap[Qt::Key_9] = "9"; + + keyMap[Qt::Key_Colon] = ":"; + keyMap[Qt::Key_Semicolon] = ";"; + keyMap[Qt::Key_Less] = "<"; + keyMap[Qt::Key_Equal] = "="; + keyMap[Qt::Key_Greater] = ">"; + keyMap[Qt::Key_Question] = "?"; + keyMap[Qt::Key_At] = "@"; + + keyMap[Qt::Key_A] = "A"; + keyMap[Qt::Key_B] = "B"; + keyMap[Qt::Key_C] = "C"; + keyMap[Qt::Key_D] = "D"; + keyMap[Qt::Key_E] = "E"; + keyMap[Qt::Key_F] = "F"; + keyMap[Qt::Key_G] = "G"; + keyMap[Qt::Key_H] = "H"; + keyMap[Qt::Key_I] = "I"; + keyMap[Qt::Key_J] = "J"; + keyMap[Qt::Key_K] = "K"; + keyMap[Qt::Key_L] = "L"; + keyMap[Qt::Key_M] = "M"; + keyMap[Qt::Key_N] = "N"; + keyMap[Qt::Key_O] = "O"; + keyMap[Qt::Key_P] = "P"; + keyMap[Qt::Key_Q] = "Q"; + keyMap[Qt::Key_R] = "R"; + keyMap[Qt::Key_S] = "S"; + keyMap[Qt::Key_T] = "T"; + keyMap[Qt::Key_U] = "U"; + keyMap[Qt::Key_V] = "V"; + keyMap[Qt::Key_W] = "W"; + keyMap[Qt::Key_X] = "X"; + keyMap[Qt::Key_Y] = "Y"; + keyMap[Qt::Key_Z] = "Z"; + + keyMap[Qt::Key_BracketLeft] = "["; + keyMap[Qt::Key_Backslash] = "\\"; + keyMap[Qt::Key_BracketRight] = "]"; + + keyMap[Qt::Key_Underscore] = "_"; + keyMap[Qt::Key_BraceLeft] = "{"; + keyMap[Qt::Key_Bar] = "|"; + keyMap[Qt::Key_BraceRight] = "}"; + keyMap[Qt::Key_AsciiTilde] = "~"; + + // Added by rvm: + keyMap[Qt::Key_Space] = "Space"; + keyMap[Qt::Key_Backspace] = "Backspace"; + keyMap[Qt::Key_MediaPlay] = "Media Play"; + keyMap[Qt::Key_MediaStop] = "Media Stop"; + keyMap[Qt::Key_MediaPrevious] = "Media Previous"; + keyMap[Qt::Key_MediaNext] = "Media Next"; + keyMap[Qt::Key_MediaRecord] = "Media Record"; + keyMap[Qt::Key_MediaLast] = "Media Last"; // doesn't work? + keyMap[Qt::Key_VolumeUp] = "Volume Up"; + keyMap[Qt::Key_VolumeDown] = "Volume Down"; + keyMap[Qt::Key_VolumeMute] = "Volume Mute"; + keyMap[Qt::Key_Back] = "Back"; + keyMap[Qt::Key_Forward] = "Forward"; + keyMap[Qt::Key_Stop] = "Stop"; +} + +static QString keyToString(int k) +{ + if ( k == Qt::Key_Shift || k == Qt::Key_Control || k == Qt::Key_Meta || + k == Qt::Key_Alt || k == Qt::Key_AltGr ) + return QString::null; + + initKeyMap(); + + return keyMap[k]; +} + +#else + +static QString keyToString(int k) +{ + if ( k == Qt::Key_Shift || k == Qt::Key_Control || k == Qt::Key_Meta || + k == Qt::Key_Alt || k == Qt::Key_AltGr ) + return QString::null; + + return QKeySequence(k).toString(); +} + +#endif + +static QStringList modToString(Qt::KeyboardModifiers k) +{ + //qDebug("modToString: k: %x", (int) k); + + QStringList l; + + if ( k & Qt::ShiftModifier ) + l << "Shift"; + if ( k & Qt::ControlModifier ) + l << "Ctrl"; + if ( k & Qt::AltModifier ) + l << "Alt"; + if ( k & Qt::MetaModifier ) + l << "Meta"; + if ( k & Qt::GroupSwitchModifier ) + ; + if ( k & Qt::KeypadModifier ) + ; + + return l; +} + + +ShortcutGetter::ShortcutGetter(QWidget *parent) : QDialog(parent) +{ + setWindowTitle(tr("Modify shortcut")); + + + QVBoxLayout *vbox = new QVBoxLayout(this); + vbox->setMargin(2); + vbox->setSpacing(4); + + QLabel *l = new QLabel(this); + l->setText(tr("Press the key combination you want to assign")); + vbox->addWidget(l); + + leKey = new QLineEdit(this); + + leKey->installEventFilter(this); + vbox->addWidget(leKey); + + // Change by rvm: use a QDialogButtonBox instead of QPushButtons + // and add a clear button + setCaptureKeyboard(true); + QDialogButtonBox * buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok | + QDialogButtonBox::Cancel | + QDialogButtonBox::Reset ); + QPushButton * clearbutton = buttonbox->button(QDialogButtonBox::Reset); + clearbutton->setText( tr("Clear") ); + + QPushButton * captureButton = new QPushButton(tr("Capture"), this); + captureButton->setToolTip( tr("Capture keystrokes") ); + captureButton->setCheckable( captureKeyboard() ); + captureButton->setChecked( captureKeyboard() ); + connect(captureButton, SIGNAL(toggled(bool)), + this, SLOT(setCaptureKeyboard(bool))); + + + buttonbox->addButton(captureButton, QDialogButtonBox::ActionRole); + + connect( buttonbox, SIGNAL(accepted()), this, SLOT(accept()) ); + connect( buttonbox, SIGNAL(rejected()), this, SLOT(reject()) ); + connect( clearbutton, SIGNAL(clicked()), leKey, SLOT(clear()) ); + vbox->addWidget(buttonbox); +} + +void ShortcutGetter::setCaptureKeyboard(bool b) { + capture = b; + leKey->setReadOnly(b); + leKey->setFocus(); +} + + +QString ShortcutGetter::exec(const QString& s) +{ + bStop = false; + leKey->setText(s); + + if ( QDialog::exec() == QDialog::Accepted ) + return leKey->text(); + + return QString(); +} + +bool ShortcutGetter::event(QEvent *e) +{ + if (!capture) return QDialog::event(e); + + + QString key; + QStringList mods; + QKeyEvent *k = static_cast(e); + + switch ( e->type() ) + { + case QEvent::KeyPress : + + if ( bStop ) + { + lKeys.clear(); + bStop = false; + } + + key = keyToString(k->key()); + mods = modToString(k->modifiers()); + + //qDebug("event: key.count: %d, mods.count: %d", key.count(), mods.count()); + + if ( key.count() || mods.count() ) + { + + if ( key.count() && !lKeys.contains(key) ) + lKeys << key; + + foreach ( key, mods ) + if ( !lKeys.contains(key) ) + lKeys << key; + + } else { + key = k->text(); + + if ( !lKeys.contains(key) ) + lKeys << key; + } + + setText(); + break; + + case QEvent::KeyRelease : + + bStop = true; + break; + + /* + case QEvent::ShortcutOverride : + leKey->setText("Shortcut override"); + break; + */ + + default: + return QDialog::event(e); + break; + } + + return true; +} + +bool ShortcutGetter::eventFilter(QObject *o, QEvent *e) +{ + if (!capture) return QDialog::eventFilter(o, e); + + if ( e->type() == QEvent::KeyPress || + e->type() ==QEvent::KeyRelease ) + return event(e); + else + return QDialog::eventFilter(o, e); +} + +void ShortcutGetter::setText() +{ + QStringList seq; + + if ( lKeys.contains("Shift") ) + seq << "Shift"; + + if ( lKeys.contains("Ctrl") ) + seq << "Ctrl"; + + if ( lKeys.contains("Alt") ) + seq << "Alt"; + + if ( lKeys.contains("Meta") ) + seq << "Meta"; + + foreach ( QString s, lKeys ) { + //qDebug("setText: s: '%s'", s.toUtf8().data()); + if ( s != "Shift" && s != "Ctrl" + && s != "Alt" && s != "Meta" ) + seq << s; + } + + leKey->setText(seq.join("+")); + //leKey->selectAll(); +} + +#include "moc_shortcutgetter.cpp" diff --git a/plugins/smplayer_plugin/shortcutgetter.h b/plugins/smplayer_plugin/shortcutgetter.h new file mode 100644 index 000000000..d794fb93c --- /dev/null +++ b/plugins/smplayer_plugin/shortcutgetter.h @@ -0,0 +1,61 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + Note: The ShortcutGetter class is taken from the source code of Edyuk + (http://www.edyuk.org) + + Copyright (C) 2006 FullMetalCoder + License: GPL +*/ + + +#ifndef _SHORTCUTGETTER_H_ +#define _SHORTCUTGETTER_H_ + +#include + +class QLineEdit; + +class ShortcutGetter : public QDialog +{ + Q_OBJECT + +public: + ShortcutGetter(QWidget *parent = 0); + + QString exec(const QString& s); + +protected slots: + void setCaptureKeyboard(bool b); + +protected: + bool captureKeyboard() { return capture; }; + + bool event(QEvent *e); + bool eventFilter(QObject *o, QEvent *e); + void setText(); + +private: + bool bStop; + QLineEdit *leKey; + QStringList lKeys; + bool capture; +}; + +#endif diff --git a/plugins/smplayer_plugin/shortcuts/default.keys b/plugins/smplayer_plugin/shortcuts/default.keys new file mode 100644 index 000000000..774b3dc04 --- /dev/null +++ b/plugins/smplayer_plugin/shortcuts/default.keys @@ -0,0 +1,193 @@ +open_file Ctrl+F +open_directory +open_playlist +open_vcd +open_audio_cd +open_dvd +open_dvd_folder +open_url Ctrl+U +close Ctrl+X +clear_recents +play +play_or_pause Media Play +pause Space +pause_and_frame_step +stop Media Stop +frame_step . +rewind1 Left +rewind2 Down +rewind3 PgDown +forward1 Right +forward2 Up +forward3 PgUp +repeat +jump_to Ctrl+J +normal_speed Backspace +halve_speed { +double_speed } +dec_speed [ +inc_speed ] +dec_speed_4 +inc_speed_4 +dec_speed_1 +inc_speed_1 +fullscreen F +compact Ctrl+C +video_equalizer Ctrl+E +screenshot S +video_preview +flip +mirror +postprocessing +autodetect_phase +deblock +dering +add_noise +add_letterbox +upscaling +audio_equalizer +mute M +decrease_volume 9, / +increase_volume 0, * +dec_audio_delay - +inc_audio_delay + +load_audio_file +unload_audio_file +extrastereo_filter +karaoke_filter +volnorm_filter +load_subs +unload_subs +dec_sub_delay Z +inc_sub_delay X +dec_sub_pos R +inc_sub_pos T +dec_sub_scale Shift+R +inc_sub_scale Shift+T +dec_sub_step G +inc_sub_step Y +use_ass_lib +use_closed_caption +use_forced_subs_only +show_find_sub_dialog +upload_subtitles +show_playlist Ctrl+L +show_file_properties Ctrl+I +frame_counter +motion_vectors +show_preferences Ctrl+P +show_mplayer_log Ctrl+M +show_smplayer_log Ctrl+S +faq +cl_options +tips +about_qt +about_smplayer +play_next > +play_prev < +move_up Alt+Up +move_down Alt+Down +move_left Alt+Left +move_right Alt+Right +inc_zoom E +dec_zoom W +reset_zoom Shift+E +auto_zoom Shift+W +zoom_169 Shift+A +zoom_235 Shift+S +exit_fullscreen Esc +next_osd O +dec_contrast 1 +inc_contrast 2 +dec_brightness 3 +inc_brightness 4 +dec_hue 5 +inc_hue 6 +dec_saturation 7 +inc_saturation 8 +dec_gamma +inc_gamma +next_video +next_audio H +next_subtitle J +next_chapter @ +prev_chapter ! +toggle_double_size Ctrl+D +reset_video_equalizer +reset_audio_equalizer +show_context_menu +next_aspect A +osd_none +osd_seek +osd_timer +osd_total +denoise_none +denoise_normal +denoise_soft +size_50 +size_75 +size_100 Ctrl+1 +size_125 +size_150 +size_175 +size_200 Ctrl+2 +size_300 +size_400 +deinterlace_none +deinterlace_l5 +deinterlace_yadif0 +deinterlace_yadif1 +deinterlace_lb +deinterlace_kern +channels_stereo +channels_surround +channels_ful51 +stereo +left_channel +right_channel +aspect_detect +aspect_4:3 +aspect_5:4 +aspect_14:9 +aspect_16:9 +aspect_16:10 +aspect_2.35:1 +aspect_1:1 +aspect_none +rotate_none +rotate_clockwise_flip +rotate_clockwise +rotate_counterclockwise +rotate_counterclockwise_flip +on_top_always +on_top_never +on_top_playing +dvdnav_up Shift+Up +dvdnav_down Shift+Down +dvdnav_left Shift+Left +dvdnav_right Shift+Right +dvdnav_menu Shift+Return +dvdnav_select Return +dvdnav_prev Shift+Esc +dvdnav_mouse +quit +show_tray_icon +restore/hide +pl_open +pl_save +pl_play +pl_next N +pl_prev P +pl_move_up +pl_move_down +pl_repeat +pl_shuffle +pl_preferences +pl_add_current +pl_add_files +pl_add_directory +pl_remove_selected +pl_remove_all +pl_edit +show_main_toolbar F5 +show_language_toolbar F6 diff --git a/plugins/smplayer_plugin/shortcuts/sda.keys b/plugins/smplayer_plugin/shortcuts/sda.keys new file mode 100644 index 000000000..4b88b68be --- /dev/null +++ b/plugins/smplayer_plugin/shortcuts/sda.keys @@ -0,0 +1,175 @@ +open_file Ctrl+F +open_directory Shift+F +open_playlist Ctrl+P +open_vcd Ctrl+V +open_audio_cd Ctrl+M +open_dvd Ctrl+D +open_dvd_folder Shift+D +open_url Shift+O +close Q +clear_recents +play +play_or_pause P +pause +pause_and_frame_step O +stop Esc +frame_step +rewind1 Left +rewind2 PgUp +rewind3 Home +forward1 Right +forward2 PgDown +forward3 End +repeat +jump_to J +normal_speed \ +halve_speed Ctrl+[ +double_speed Ctrl+] +dec_speed [ +inc_speed ] +dec_speed_4 Shift+{ +inc_speed_4 Shift+} +dec_speed_1 +inc_speed_1 +fullscreen Alt+Return +compact Tab +video_equalizer V +screenshot S +on_top F3 +flip ^ +postprocessing ! +autodetect_phase @ +deblock # +dering $ +add_noise ~ +add_letterbox ` +upscaling % +audio_equalizer E +mute M +decrease_volume - +increase_volume = +dec_audio_delay ; +inc_audio_delay ' +load_audio_file X +unload_audio_file Ctrl+X +extrastereo_filter ) +karaoke_filter ( +volnorm_filter * +load_subs L +unload_subs Ctrl+L +dec_sub_delay Ctrl+; +inc_sub_delay Ctrl+' +dec_sub_pos Ctrl+F11 +inc_sub_pos Ctrl+F12 +dec_sub_scale F11 +inc_sub_scale F12 +dec_sub_step Alt+Left +inc_sub_step Alt+Right +use_ass_lib U +use_closed_caption Ctrl+U +use_forced_subs_only Shift+U +show_find_sub_dialog +upload_subtitles +show_playlist Space +show_file_properties Return +frame_counter F +motion_vectors G +show_preferences F2 +show_mplayer_log F9 +show_smplayer_log F10 +faq +cl_options F1 +tips +about_qt +about_smplayer +play_next Down +play_prev Up +move_up Ctrl+Up +move_down Ctrl+Down +move_left Ctrl+Left +move_right Ctrl+Right +inc_zoom Z +dec_zoom Shift+Z +reset_zoom Ctrl+Z +exit_fullscreen +next_osd +dec_contrast 1 +inc_contrast 2 +dec_brightness 3 +inc_brightness 4 +dec_hue 5 +inc_hue 6 +dec_saturation 7 +inc_saturation 8 +dec_gamma 9 +inc_gamma 0 +next_audio T +next_subtitle Ctrl+T +next_chapter / +prev_chapter . +toggle_double_size Ctrl+Return +reset_video_equalizer Shift+E +reset_audio_equalizer Ctrl+E +show_context_menu Shift+F10 +osd_none Ctrl+Backspace +osd_seek Shift+Backspace +osd_timer +osd_total Backspace +denoise_none Ctrl+N +denoise_normal N +denoise_soft Shift+N +size_50 Ctrl+5 +size_75 Ctrl+7 +size_100 Ctrl+0 +size_125 +size_150 Ctrl+1 +size_175 +size_200 Ctrl+2 +size_300 Ctrl+3 +size_400 Ctrl+4 +deinterlace_none Ctrl+I +deinterlace_l5 +deinterlace_yadif0 Shift+I +deinterlace_yadif1 I +deinterlace_lb +deinterlace_kern +channels_stereo Ctrl+C +channels_surround Shift+C +channels_ful51 C +stereo Ctrl+A +left_channel A +right_channel Shift+A +aspect_detect Ctrl+W +aspect_4:3 Shift+W +aspect_5:4 +aspect_14:9 +aspect_16:9 W +aspect_16:10 +aspect_2.35:1 +aspect_none +rotate_none Ctrl+R +rotate_clockwise R +rotate_counterclockwise Shift+R +rotate_clockwise_flip +rotate_counterclockwise_flip +quit Ctrl+Q +show_tray_icon F4 +restore/hide H +pl_open Ctrl+O +pl_save Ctrl+S +pl_play Shift+P +pl_next Shift+Down +pl_prev Shift+Up +pl_move_up Alt+Up +pl_move_down Alt+Down +pl_repeat F7 +pl_shuffle F8 +pl_preferences Shift+F2 +pl_add_current Shift+Ins +pl_add_files Ins +pl_add_directory Ctrl+Ins +pl_remove_selected Del +pl_remove_all Ctrl+Del +pl_edit Shift+Del +show_main_toolbar F5 +show_language_toolbar F6 diff --git a/plugins/smplayer_plugin/smplayer.cpp b/plugins/smplayer_plugin/smplayer.cpp new file mode 100644 index 000000000..b691d14bc --- /dev/null +++ b/plugins/smplayer_plugin/smplayer.cpp @@ -0,0 +1,339 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "smplayer.h" +#include "defaultgui.h" +#include "minigui.h" +#include "mpcgui.h" +#include "global.h" +#include "paths.h" +#include "translator.h" +#include "version.h" +#include "constants.h" +#include "myclient.h" +#include "clhelp.h" + +#include +#include + +#include + +#ifdef Q_OS_WIN +#if USE_ASSOCIATIONS +#include "extensions.h" +#include "winfileassoc.h" //required for Uninstall +#endif +#endif + + +using namespace Global; + +SMPlayer::SMPlayer(const QString & config_path, QObject * parent ) + : QObject(parent) +{ + main_window = 0; + gui_to_use = "DefaultGui"; + + Paths::setAppPath( qApp->applicationDirPath() ); + +#ifndef PORTABLE_APP + if (config_path.isEmpty()) createConfigDirectory(); +#endif + global_init(config_path); + + // Application translations + translator->load( pref->language ); + showInfo(); +} + +SMPlayer::~SMPlayer() { + if (main_window != 0) delete main_window; + global_end(); +} + +BaseGui * SMPlayer::gui() { + if (main_window == 0) { + // Changes to app path, so smplayer can find a relative mplayer path + QDir::setCurrent(Paths::appPath()); + qDebug("SMPlayer::gui: changed working directory to app path"); + qDebug("SMPlayer::gui: current directory: %s", QDir::currentPath().toUtf8().data()); + + if (gui_to_use.toLower() == "minigui") + main_window = new MiniGui(0); + else + if (gui_to_use.toLower() == "mpcgui") + main_window = new MpcGui(0); + else + main_window = new DefaultGui(0); + } + return main_window; +} + +SMPlayer::ExitCode SMPlayer::processArgs(QStringList args) { + qDebug("SMPlayer::processArgs: arguments: %d", args.count()); + for (int n = 0; n < args.count(); n++) { + qDebug("SMPlayer::processArgs: %d = %s", n, args[n].toUtf8().data()); + } + + + QString action; // Action to be passed to running instance + int close_at_end = -1; // -1 = not set, 1 = true, 0 false + int start_in_fullscreen = -1; + bool show_help = false; + + if (!pref->gui.isEmpty()) gui_to_use = pref->gui; + bool add_to_playlist = false; + + bool is_playlist = false; + +#ifdef Q_OS_WIN + if (args.contains("-uninstall")){ +#if USE_ASSOCIATIONS + //Called by uninstaller. Will restore old associations. + WinFileAssoc RegAssoc; + Extensions exts; + QStringList regExts; + RegAssoc.GetRegisteredExtensions(exts.multimedia(), regExts); + RegAssoc.RestoreFileAssociations(regExts); + printf("Restored associations\n"); +#endif + return NoError; + } +#endif + + for (int n = 1; n < args.count(); n++) { + QString argument = args[n]; + + if (argument == "-send-action") { + if (n+1 < args.count()) { + n++; + action = args[n]; + } else { + printf("Error: expected parameter for -send-action\r\n"); + return ErrorArgument; + } + } + else + if (argument == "-actions") { + if (n+1 < args.count()) { + n++; + actions_list = args[n]; + } else { + printf("Error: expected parameter for -actions\r\n"); + return ErrorArgument; + } + } + else + if (argument == "-sub") { + if (n+1 < args.count()) { + n++; + QString file = args[n]; + if (QFile::exists(file)) { + subtitle_file = QFileInfo(file).absoluteFilePath(); + } else { + printf("Error: file '%s' doesn't exists\r\n", file.toUtf8().constData()); + } + } else { + printf("Error: expected parameter for -sub\r\n"); + return ErrorArgument; + } + } + else + if (argument == "-playlist") { + is_playlist = true; + } + else + if ((argument == "--help") || (argument == "-help") || + (argument == "-h") || (argument == "-?") ) + { + show_help = true; + } + else + if (argument == "-close-at-end") { + close_at_end = 1; + } + else + if (argument == "-no-close-at-end") { + close_at_end = 0; + } + else + if (argument == "-fullscreen") { + start_in_fullscreen = 1; + } + else + if (argument == "-no-fullscreen") { + start_in_fullscreen = 0; + } + else + if (argument == "-add-to-playlist") { + add_to_playlist = true; + } + else + if (argument == "-mini" || argument == "-minigui") { + gui_to_use = "MiniGui"; + } + else + if (argument == "-mpcgui") { + gui_to_use = "MpcGui"; + } + else + if (argument == "-defaultgui") { + gui_to_use = "DefaultGui"; + } + else { + // File + if (QFile::exists( argument )) { + argument = QFileInfo(argument).absoluteFilePath(); + } + if (is_playlist) { + argument = argument + IS_PLAYLIST_TAG; + is_playlist = false; + } + files_to_play.append( argument ); + } + } + + if (show_help) { + printf("%s\n", CLHelp::help().toLocal8Bit().data()); + return NoError; + } + + qDebug("SMPlayer::processArgs: files_to_play: count: %d", files_to_play.count() ); + for (int n=0; n < files_to_play.count(); n++) { + qDebug("SMPlayer::processArgs: files_to_play[%d]: '%s'", n, files_to_play[n].toUtf8().data()); + } + + + if (pref->use_single_instance) { + // Single instance + int port = pref->connection_port; + if (pref->use_autoport) port = pref->autoport; + + MyClient *c = new MyClient(port); + //c->setTimeOut(1000); + qDebug("SMPlayer::processArgs: trying to connect to port %d", port); + + if (c->openConnection()) { + qDebug("SMPlayer::processArgs: found another instance"); + + if (!action.isEmpty()) { + if (c->sendAction(action)) { + qDebug("SMPlayer::processArgs: action passed successfully to the running instance"); + } else { + printf("Error: action couldn't be passed to the running instance"); + return NoAction; + } + } + else + if (!files_to_play.isEmpty()) { + if (c->sendFiles(files_to_play, add_to_playlist)) { + qDebug("SMPlayer::processArgs: files sent successfully to the running instance"); + qDebug("SMPlayer::processArgs: exiting."); + } else { + qDebug("SMPlayer::processArgs: files couldn't be sent to another instance"); + } + } + + return NoError; + + } else { + if (!action.isEmpty()) { + printf("Error: no running instance found\r\n"); + return NoRunningInstance; + } + } + } + + if (!pref->default_font.isEmpty()) { + QFont f; + f.fromString(pref->default_font); + qApp->setFont(f); + } + + if (close_at_end != -1) { + pref->close_on_finish = close_at_end; + } + + if (start_in_fullscreen != -1) { + pref->start_in_fullscreen = start_in_fullscreen; + } + + return SMPlayer::NoExit; +} + +void SMPlayer::start() { + if (!gui()->startHidden() || !files_to_play.isEmpty() ) gui()->show(); + if (!files_to_play.isEmpty()) { + if (!subtitle_file.isEmpty()) gui()->setInitialSubtitle(subtitle_file); + gui()->openFiles(files_to_play); + } + + if (!actions_list.isEmpty()) { + if (files_to_play.isEmpty()) { + gui()->runActions(actions_list); + } else { + gui()->runActionsLater(actions_list); + } + } +} + +#ifndef PORTABLE_APP +void SMPlayer::createConfigDirectory() { + // Create smplayer config directory + if (!QFile::exists(Paths::configPath())) { + QDir d; + if (!d.mkdir(Paths::configPath())) { + qWarning("SMPlayer::createConfigDirectory: can't create %s", Paths::configPath().toUtf8().data()); + } + QString s = Paths::configPath() + "/screenshots"; + if (!d.mkdir(s)) { + qWarning("SMPlayer::createHomeDirectory: can't create %s", s.toUtf8().data()); + } + } +} +#endif + +void SMPlayer::showInfo() { + QString s = QObject::tr("This is SMPlayer v. %1 running on %2") + .arg(smplayerVersion()) +#ifdef Q_OS_LINUX + .arg("Linux") +#else +#ifdef Q_OS_WIN + .arg("Windows") +#else + .arg("Other OS") +#endif +#endif + ; + + printf("%s\n", s.toLocal8Bit().data() ); + qDebug("%s", s.toUtf8().data() ); + qDebug("Compiled with Qt v. %s, using %s", QT_VERSION_STR, qVersion()); + + qDebug(" * application path: '%s'", Paths::appPath().toUtf8().data()); + qDebug(" * data path: '%s'", Paths::dataPath().toUtf8().data()); + qDebug(" * translation path: '%s'", Paths::translationPath().toUtf8().data()); + qDebug(" * doc path: '%s'", Paths::docPath().toUtf8().data()); + qDebug(" * themes path: '%s'", Paths::themesPath().toUtf8().data()); + qDebug(" * shortcuts path: '%s'", Paths::shortcutsPath().toUtf8().data()); + qDebug(" * config path: '%s'", Paths::configPath().toUtf8().data()); + qDebug(" * ini path: '%s'", Paths::iniPath().toUtf8().data()); + qDebug(" * file for subtitles' styles: '%s'", Paths::subtitleStyleFile().toUtf8().data()); + qDebug(" * current path: '%s'", QDir::currentPath().toUtf8().data()); +} diff --git a/plugins/smplayer_plugin/smplayer.h b/plugins/smplayer_plugin/smplayer.h new file mode 100644 index 000000000..6732c8ca2 --- /dev/null +++ b/plugins/smplayer_plugin/smplayer.h @@ -0,0 +1,56 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _SMPLAYER_H_ +#define _SMPLAYER_H_ + +#include +#include +#include +#include "basegui.h" + +class SMPlayer : public QObject +{ +public: + enum ExitCode { ErrorArgument = -3, NoAction = -2, NoRunningInstance = -1, NoError = 0, NoExit = 1 }; + + SMPlayer(const QString & config_path = QString::null, QObject * parent = 0); + ~SMPlayer(); + + //! Process arguments. If ExitCode != NoExit the application must be exited. + ExitCode processArgs(QStringList args); + + BaseGui * gui(); + + void start(); + +private: +#ifndef PORTABLE_APP + void createConfigDirectory(); +#endif + void showInfo(); + + BaseGui * main_window; + + QStringList files_to_play; + QString subtitle_file; + QString actions_list; //!< Actions to be run on startup + QString gui_to_use; +}; + +#endif diff --git a/plugins/smplayer_plugin/smplayer.ico b/plugins/smplayer_plugin/smplayer.ico new file mode 100644 index 000000000..bab3eb3ac Binary files /dev/null and b/plugins/smplayer_plugin/smplayer.ico differ diff --git a/plugins/smplayer_plugin/smplayer.pro b/plugins/smplayer_plugin/smplayer.pro new file mode 100644 index 000000000..523c9588f --- /dev/null +++ b/plugins/smplayer_plugin/smplayer.pro @@ -0,0 +1,336 @@ +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin debug + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(smplayer_plugin) + +HEADERS += ../PluginInterface.h \ + SMPlayerPlugin.h +SOURCES += SMPlayerPlugin.cpp + +#=============================================================================== +QT += network xml + + +RESOURCES = icons.qrc + +INCLUDEPATH += findsubtitles videopreview mpcgui +DEPENDPATH += findsubtitles videopreview mpcgui + +#DEFINES += USE_QXT + +DEFINES += DOWNLOAD_SUBS + +HEADERS += guiconfig.h \ + config.h \ + constants.h \ + version.h \ + global.h \ + paths.h \ + helper.h \ + colorutils.h \ + translator.h \ + subtracks.h \ + tracks.h \ + titletracks.h \ + extensions.h \ + desktopinfo.h \ + myprocess.h \ + mplayerversion.h \ + mplayerprocess.h \ + infoprovider.h \ + mplayerwindow.h \ + mediadata.h \ + audioequalizerlist.h \ + mediasettings.h \ + assstyles.h \ + preferences.h \ + filesettingsbase.h \ + filesettings.h \ + filesettingshash.cpp \ + images.h \ + inforeader.h \ + deviceinfo.h \ + recents.h \ + urlhistory.h \ + core.h \ + logwindow.h \ + infofile.h \ + seekwidget.h \ + mytablewidget.h \ + shortcutgetter.h \ + actionseditor.h \ + filechooser.h \ + preferencesdialog.h \ + mycombobox.h \ + tristatecombo.h \ + languages.h \ + selectcolorbutton.h \ + prefwidget.h \ + prefgeneral.h \ + prefdrives.h \ + prefinterface.h \ + prefperformance.h \ + prefinput.h \ + prefsubtitles.h \ + prefadvanced.h \ + prefplaylist.h \ + filepropertiesdialog.h \ + playlist.h \ + playlistpreferences.h \ + playlistdock.h \ + verticaltext.h \ + eqslider.h \ + videoequalizer.h \ + audioequalizer.h \ + myslider.h \ + timeslider.h \ + inputdvddirectory.h \ + inputurl.h \ + myaction.h \ + myactiongroup.h \ + myserver.h \ + myclient.h \ + filedialog.h \ + inputmplayerversion.h \ + about.h \ + errordialog.h \ + timedialog.h \ + findsubtitles/simplehttp.h \ + findsubtitles/osparser.h \ + findsubtitles/findsubtitleswindow.h \ + videopreview/videopreview.h \ + videopreview/videopreviewconfigdialog.h \ + basegui.h \ + baseguiplus.h \ + floatingwidget.h \ + widgetactions.h \ + toolbareditor.h \ + defaultgui.h \ + minigui.h \ + mpcgui/mpcgui.h \ + mpcgui/mpcstyles.h \ + smplayer.h \ + clhelp.h + + +SOURCES += version.cpp \ + global.cpp \ + paths.cpp \ + helper.cpp \ + colorutils.cpp \ + translator.cpp \ + subtracks.cpp \ + tracks.cpp \ + titletracks.cpp \ + extensions.cpp \ + desktopinfo.cpp \ + myprocess.cpp \ + mplayerversion.cpp \ + mplayerprocess.cpp \ + infoprovider.cpp \ + mplayerwindow.cpp \ + mediadata.cpp \ + mediasettings.cpp \ + assstyles.cpp \ + preferences.cpp \ + filesettingsbase.cpp \ + filesettings.cpp \ + filesettingshash.cpp \ + images.cpp \ + inforeader.cpp \ + deviceinfo.cpp \ + recents.cpp \ + urlhistory.cpp \ + core.cpp \ + logwindow.cpp \ + infofile.cpp \ + seekwidget.cpp \ + mytablewidget.cpp \ + shortcutgetter.cpp \ + actionseditor.cpp \ + filechooser.cpp \ + preferencesdialog.cpp \ + mycombobox.cpp \ + tristatecombo.cpp \ + languages.cpp \ + selectcolorbutton.cpp \ + prefwidget.cpp \ + prefgeneral.cpp \ + prefdrives.cpp \ + prefinterface.cpp \ + prefperformance.cpp \ + prefinput.cpp \ + prefsubtitles.cpp \ + prefadvanced.cpp \ + prefplaylist.cpp \ + filepropertiesdialog.cpp \ + playlist.cpp \ + playlistpreferences.cpp \ + playlistdock.cpp \ + verticaltext.cpp \ + eqslider.cpp \ + videoequalizer.cpp \ + audioequalizer.cpp \ + myslider.cpp \ + timeslider.cpp \ + inputdvddirectory.cpp \ + inputurl.cpp \ + myaction.cpp \ + myactiongroup.cpp \ + myserver.cpp \ + myclient.cpp \ + filedialog.cpp \ + inputmplayerversion.cpp \ + about.cpp \ + errordialog.cpp \ + timedialog.cpp \ + findsubtitles/simplehttp.cpp \ + findsubtitles/osparser.cpp \ + findsubtitles/findsubtitleswindow.cpp \ + videopreview/videopreview.cpp \ + videopreview/videopreviewconfigdialog.cpp \ + basegui.cpp \ + baseguiplus.cpp \ + floatingwidget.cpp \ + widgetactions.cpp \ + toolbareditor.cpp \ + defaultgui.cpp \ + minigui.cpp \ + mpcgui/mpcgui.cpp \ + mpcgui/mpcstyles.cpp \ + clhelp.cpp \ + smplayer.cpp + +#libqxt +contains(DEFINES, USE_QXT) { + CONFIG += qxt + QXT += core +} + +FORMS = inputdvddirectory.ui logwindowbase.ui filepropertiesdialog.ui \ + eqslider.ui seekwidget.ui inputurl.ui \ + preferencesdialog.ui prefgeneral.ui prefdrives.ui prefinterface.ui \ + prefperformance.ui prefinput.ui prefsubtitles.ui prefadvanced.ui \ + prefplaylist.ui \ + about.ui inputmplayerversion.ui errordialog.ui timedialog.ui \ + playlistpreferences.ui filechooser.ui \ + findsubtitles/findsubtitleswindow.ui \ + videopreview/videopreviewconfigdialog.ui + +TRANSLATIONS = translations/smplayer_es.ts translations/smplayer_de.ts \ + translations/smplayer_sk.ts translations/smplayer_it.ts \ + translations/smplayer_fr.ts translations/smplayer_zh_CN.ts \ + translations/smplayer_ru_RU.ts translations/smplayer_hu.ts \ + translations/smplayer_en_US.ts translations/smplayer_pl.ts \ + translations/smplayer_ja.ts translations/smplayer_nl.ts \ + translations/smplayer_uk_UA.ts translations/smplayer_pt_BR.ts \ + translations/smplayer_ka.ts translations/smplayer_cs.ts \ + translations/smplayer_bg.ts translations/smplayer_tr.ts \ + translations/smplayer_sv.ts translations/smplayer_sr.ts \ + translations/smplayer_zh_TW.ts translations/smplayer_ro_RO.ts \ + translations/smplayer_pt_PT.ts translations/smplayer_el_GR.ts \ + translations/smplayer_fi.ts translations/smplayer_ko.ts \ + translations/smplayer_mk.ts translations/smplayer_eu.ts \ + translations/smplayer_ca.ts translations/smplayer_sl_SI.ts \ + translations/smplayer_ar_SY.ts translations/smplayer_ku.ts \ + translations/smplayer_gl.ts + +contains( DEFINES, DOWNLOAD_SUBS ) { + INCLUDEPATH += findsubtitles/filedownloader findsubtitles/quazip + DEPENDPATH += findsubtitles/filedownloader findsubtitles/quazip + + HEADERS += filedownloader.h subchooserdialog.h + SOURCES += filedownloader.cpp subchooserdialog.cpp + + FORMS += subchooserdialog.ui + + HEADERS += crypt.h \ + ioapi.h \ + quazip.h \ + quazipfile.h \ + quazipfileinfo.h \ + quazipnewinfo.h \ + unzip.h \ + zip.h + + SOURCES += ioapi.c \ + quazip.cpp \ + quazipfile.cpp \ + quazipnewinfo.cpp \ + unzip.c \ + zip.c + + LIBS += -lz + + win32 { + INCLUDEPATH += c:\development\zlib-1.2.3 + LIBS += -Lc:\development\zlib-1.2.3 + } +} + +unix { + UI_DIR = .ui + MOC_DIR = .moc + OBJECTS_DIR = .obj + + DEFINES += DATA_PATH=$(DATA_PATH) + DEFINES += DOC_PATH=$(DOC_PATH) + DEFINES += TRANSLATION_PATH=$(TRANSLATION_PATH) + DEFINES += THEMES_PATH=$(THEMES_PATH) + DEFINES += SHORTCUTS_PATH=$(SHORTCUTS_PATH) + #DEFINES += NO_DEBUG_ON_CONSOLE + + #DEFINES += KDE_SUPPORT + #INCLUDEPATH += /opt/kde3/include/ + #LIBS += -lkio -L/opt/kde3/lib/ + + #contains( DEFINES, KDE_SUPPORT) { + # HEADERS += mysystemtrayicon.h + # SOURCES += mysystemtrayicon.cpp + #} + + #HEADERS += prefassociations.h winfileassoc.h + #SOURCES += prefassociations.cpp winfileassoc.cpp + #FORMS += prefassociations.ui +} + +win32 { + HEADERS += screensaver.h + SOURCES += screensaver.cpp + + !contains( DEFINES, PORTABLE_APP ) { + DEFINES += USE_ASSOCIATIONS + } + + contains( DEFINES, USE_ASSOCIATIONS ) { + HEADERS += prefassociations.h winfileassoc.h + SOURCES += prefassociations.cpp winfileassoc.cpp + FORMS += prefassociations.ui + } + + contains(TEMPLATE,vcapp) { + LIBS += ole32.lib user32.lib + } else { + LIBS += libole32 + } + + RC_FILE = smplayer.rc + DEFINES += NO_DEBUG_ON_CONSOLE +# debug { +# CONFIG += console +# } +} + diff --git a/plugins/smplayer_plugin/smplayer.rc b/plugins/smplayer_plugin/smplayer.rc new file mode 100644 index 000000000..7a7bd24a1 --- /dev/null +++ b/plugins/smplayer_plugin/smplayer.rc @@ -0,0 +1,2 @@ +IDI_ICON1 ICON DISCARDABLE "smplayer.ico" +IDI_ICON2 ICON DISCARDABLE "smplayer_associations.ico" diff --git a/plugins/smplayer_plugin/smplayer_associations.ico b/plugins/smplayer_plugin/smplayer_associations.ico new file mode 100644 index 000000000..c4749ef53 Binary files /dev/null and b/plugins/smplayer_plugin/smplayer_associations.ico differ diff --git a/plugins/smplayer_plugin/subtracks.cpp b/plugins/smplayer_plugin/subtracks.cpp new file mode 100644 index 000000000..b5b77fbb1 --- /dev/null +++ b/plugins/smplayer_plugin/subtracks.cpp @@ -0,0 +1,247 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "subtracks.h" +#include "mediasettings.h" +#include + +SubTracks::SubTracks() { + index = 0; +} + + +SubTracks::~SubTracks() { +} + +void SubTracks::clear() { + subs.clear(); +} + +void SubTracks::add( SubData::Type t, int ID ) { + SubData d; + d.setType(t); + d.setID(ID); + + subs.append(d); +} + +void SubTracks::list() { + for (unsigned int n=0; n < subs.count(); n++) { + qDebug("SubTracks::list: item %d: type: %d ID: %d lang: '%s' name: '%s' filename: '%s'", + n, subs[n].type(), subs[n].ID(), subs[n].lang().toUtf8().data(), + subs[n].name().toUtf8().data(), subs[n].filename().toUtf8().data() ); + } +} + +void SubTracks::listNames() { + for (unsigned int n=0; n < subs.count(); n++) { + qDebug("SubTracks::list: item %d: '%s'", + n, subs[n].displayName().toUtf8().data() ); + } +} + +int SubTracks::numItems() { + return subs.count(); +} + +bool SubTracks::existsItemAt(int n) { + return ((n > 0) && (n < numItems())); +} + +int SubTracks::findLang(QString expr) { + qDebug( "SubTracks::findLang: '%s'", expr.toUtf8().data()); + QRegExp rx( expr ); + + int res_id = -1; + + for (int n=0; n < numItems(); n++) { + qDebug("SubTracks::findLang: lang #%d '%s'", n, + subs[n].lang().toUtf8().data()); + if (rx.indexIn( subs[n].lang() ) > -1) { + qDebug("SubTracks::findLang: found preferred lang!"); + res_id = n; + break; + } + } + + return res_id; +} + +// Return first subtitle or the user preferred (if found) +// or none if there's no subtitles +int SubTracks::selectOne(QString preferred_lang, int default_sub) { + int sub = MediaSettings::SubNone; + + if (numItems() > 0) { + sub = 0; // First subtitle + if (existsItemAt(default_sub)) { + sub = default_sub; + } + + // Check if one of the subtitles is the user preferred. + if (!preferred_lang.isEmpty()) { + int res = findLang( preferred_lang ); + if (res != -1) sub = res; + } + } + return sub; +} + +int SubTracks::find( SubData::Type t, int ID ) { + for (unsigned int n=0; n < subs.count(); n++) { + if ( ( subs[n].type() == t ) && ( subs[n].ID() == ID ) ) { + return n; + } + } + qDebug("SubTracks::find: item type: %d, ID: %d doesn't exist", t, ID); + return -1; +} + +SubData SubTracks::findItem( SubData::Type t, int ID ) { + SubData sub; + int n = find(t,ID); + if ( n != -1 ) + return subs[n]; + else + return sub; +} + +SubData SubTracks::itemAt( int n ) { + if (n >= 0 && n < subs.count()) { + return subs[n]; + } else { + qWarning("SubTracks::itemAt: %d out of range!", n); + qWarning("SubTracks::itemAt: returning an empty sub to avoid a crash"); + qWarning("SubTracks::itemAt: this shouldn't happen, report a bug if you see this"); + + SubData empty_sub; + return empty_sub; + } +} + +bool SubTracks::changeLang( SubData::Type t, int ID, QString lang ) { + int f = find(t,ID); + if (f == -1) return false; + + subs[f].setLang(lang); + return true; +} + +bool SubTracks::changeName( SubData::Type t, int ID, QString name ) { + int f = find(t,ID); + if (f == -1) return false; + + subs[f].setName(name); + return true; +} + +bool SubTracks::changeFilename( SubData::Type t, int ID, QString filename ) { + int f = find(t,ID); + if (f == -1) return false; + + subs[f].setFilename(filename); + return true; +} + +int SubTracks::parse(QString text) { + qDebug("SubTracks::parse: '%s'", text.toUtf8().data()); + + ParseResult result = SubtitleUnchanged; + + QRegExp rx_subtitle("^ID_(SUBTITLE|FILE_SUB|VOBSUB)_ID=(\\d+)"); + QRegExp rx_sid("^ID_(SID|VSID)_(\\d+)_(LANG|NAME)=(.*)"); + QRegExp rx_subtitle_file("^ID_FILE_SUB_FILENAME=(.*)"); + + if (rx_subtitle.indexIn(text) > -1) { + int ID = rx_subtitle.cap(2).toInt(); + QString type = rx_subtitle.cap(1); + + SubData::Type t; + if (type == "FILE_SUB") t = SubData::File; + else + if (type == "VOBSUB") t = SubData::Vob; + else + t = SubData::Sub; + + if (find(t, ID) > -1) { + qWarning("SubTracks::parse: subtitle type: %d, ID: %d already exists!", t, ID); + } else { + add(t,ID); + + result = SubtitleAdded; + } + } + else + if (rx_sid.indexIn(text) > -1) { + int ID = rx_sid.cap(2).toInt(); + QString value = rx_sid.cap(4); + QString attr = rx_sid.cap(3); + QString type = rx_sid.cap(1); + + SubData::Type t = SubData::Sub; + if (type == "VSID") t = SubData::Vob; + + if (find(t, ID) == -1) { + qWarning("SubTracks::parse: subtitle type: %d, ID: %d doesn't exist!", t, ID); + } else { + if (attr=="NAME") + changeName(t,ID, value); + else + changeLang(t,ID, value); + + result = SubtitleChanged; + } + } + else + if (rx_subtitle_file.indexIn(text) > -1) { + QString file = rx_subtitle_file.cap(1); + if ( subs.count() > 0 ) { + int last = subs.count() -1; + if (subs[last].type() == SubData::File) { + subs[last].setFilename( file ); + + result = SubtitleChanged; + } + } + } + + return result; +} + +/* +void SubTracks::test() { + process("ID_SUBTITLE_ID=0"); + process("ID_SID_0_NAME=Arabic"); + process("ID_SID_0_LANG=ara"); + process("ID_SUBTITLE_ID=1"); + process("ID_SID_1_NAME=Catalan"); + process("ID_SID_1_LANG=cat"); + + process("ID_VOBSUB_ID=0"); + process("ID_VSID_0_LANG=en"); + process("ID_VOBSUB_ID=1"); + process("ID_VSID_1_LANG=fr"); + + process("ID_FILE_SUB_ID=1"); + process("ID_FILE_SUB_FILENAME=./lost313_es.sub"); + + list(); + listNames(); +} +*/ diff --git a/plugins/smplayer_plugin/subtracks.h b/plugins/smplayer_plugin/subtracks.h new file mode 100644 index 000000000..76304bfce --- /dev/null +++ b/plugins/smplayer_plugin/subtracks.h @@ -0,0 +1,117 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _SUBTRACKS_H_ +#define _SUBTRACKS_H_ + +#include +#include +#include + +class SubData +{ + +public: + enum Type { None = -1, Vob = 0, Sub = 1, File = 2 }; + + SubData() { _ID=-1; _lang=""; _name=""; _filename=""; _type = None; }; + ~SubData() {}; + + void setType( Type t ) { _type = t; }; + void setID(int id) { _ID = id; }; + void setLang(QString lang) { _lang = lang; }; + void setName(QString name) { _name = name; }; + void setFilename(QString f) { _filename = f; }; + + Type type() { return _type; }; + int ID() { return _ID; }; + QString lang() { return _lang; }; + QString name() { return _name; }; + QString filename() { return _filename; }; + + QString displayName() { + QString dname=""; + + if (!_name.isEmpty()) { + dname = _name; + } + else + if (!_lang.isEmpty()) { + dname = _lang; + } + else + if (!_filename.isEmpty()) { + QFileInfo f(_filename); + dname = f.fileName(); + } + else + dname = QString::number(_ID); + + return dname; + }; + +protected: + Type _type; + int _ID; + QString _lang; + QString _name; + QString _filename; +}; + +typedef QList SubList; + + +class SubTracks +{ +public: + enum ParseResult { SubtitleUnchanged = 0, SubtitleAdded = 1, SubtitleChanged = 2 }; + + SubTracks(); + ~SubTracks(); + + void clear(); + int find( SubData::Type t, int ID ); + + void add( SubData::Type t, int ID ); + bool changeLang( SubData::Type t, int ID, QString lang ); + bool changeName( SubData::Type t, int ID, QString name ); + bool changeFilename( SubData::Type t, int ID, QString filename ); + + int numItems(); + bool existsItemAt(int n); + + SubData itemAt(int n); + SubData findItem( SubData::Type t, int ID ); + + int findLang(QString expr); + int selectOne(QString preferred_lang, int default_sub=0); + + //! Parses a line from mplayer output with subtitle info + int parse(QString text); + + void list(); + void listNames(); + /* void test(); */ + +protected: + SubList subs; + int index; +}; + +#endif diff --git a/plugins/smplayer_plugin/testcorelib/test.cpp b/plugins/smplayer_plugin/testcorelib/test.cpp new file mode 100644 index 000000000..41c258ebd --- /dev/null +++ b/plugins/smplayer_plugin/testcorelib/test.cpp @@ -0,0 +1,109 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "test.h" +#include "smplayercorelib.h" +#include "helper.h" +#include "global.h" +#include +#include +#include +#include "timeslider.h" +#include + +#include + +Gui::Gui( QWidget * parent, Qt::WindowFlags flags ) + : QMainWindow(parent, flags) +{ + smplayerlib = new SmplayerCoreLib(this); + core = smplayerlib->core(); + setCentralWidget(smplayerlib->mplayerWindow()); + + QAction * openAct = new QAction( tr("&Open..."), this); + connect( openAct, SIGNAL(triggered()), this, SLOT(open()) ); + + QAction * closeAct = new QAction( tr("&Close"), this); + connect( closeAct, SIGNAL(triggered()), this, SLOT(close()) ); + + QMenu * open_menu = menuBar()->addMenu( tr("&Open") ); + open_menu->addAction(openAct); + open_menu->addAction(closeAct); + + QAction * playAct = new QAction( tr("&Play/Pause"), this); + playAct->setShortcut( Qt::Key_Space ); + connect( playAct, SIGNAL(triggered()), + core, SLOT(play_or_pause()) ); + + QAction * stopAct = new QAction( tr("&Stop"), this); + connect( stopAct, SIGNAL(triggered()), + core, SLOT(stop()) ); + + QMenu * play_menu = menuBar()->addMenu( tr("&Play") ); + play_menu->addAction(playAct); + play_menu->addAction(stopAct); + + + TimeSlider * time_slider = new TimeSlider(this); + connect( time_slider, SIGNAL(posChanged(int)), + core, SLOT(goToPos(int)) ); + connect( core, SIGNAL(posChanged(int)), + time_slider, SLOT(setPos(int)) ); + + QToolBar * control = new QToolBar( tr("Control"), this); + control->addAction(playAct); + control->addAction(stopAct); + control->addSeparator(); + control->addWidget(time_slider); + + addToolBar(Qt::BottomToolBarArea, control); +} + +Gui::~Gui() { +} + +void Gui::closeEvent( QCloseEvent * event ) { + core->stop(); + event->accept(); +} + +void Gui::open() { + QString f = QFileDialog::getOpenFileName( this, tr("Open file") ); + + if (!f.isEmpty()) { + core->open(f); + } +} + +int main( int argc, char ** argv ) { + QApplication a( argc, argv ); + a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) ); + + Helper::setAppPath( qApp->applicationDirPath() ); + Global::global_init(); + + Gui * w = new Gui(); + w->show(); + + int r = a.exec(); + Global::global_end(); + + return r; +} + +#include "moc_test.cpp" diff --git a/plugins/smplayer_plugin/testcorelib/test.h b/plugins/smplayer_plugin/testcorelib/test.h new file mode 100644 index 000000000..0c88d3a37 --- /dev/null +++ b/plugins/smplayer_plugin/testcorelib/test.h @@ -0,0 +1,49 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _TEST_H_ +#define _TEST_H_ + +#include + +class MplayerWindow; +class SmplayerCoreLib; +class Core; + +class Gui : public QMainWindow +{ + Q_OBJECT + +public: + Gui( QWidget * parent = 0, Qt::WindowFlags flags = 0 ); + ~Gui(); + +public slots: + void open(); + +protected: + virtual void closeEvent( QCloseEvent * event ); + +private: + MplayerWindow * mpw; + Core * core; + SmplayerCoreLib * smplayerlib; +}; + +#endif + diff --git a/plugins/smplayer_plugin/testcorelib/test.pro b/plugins/smplayer_plugin/testcorelib/test.pro new file mode 100644 index 000000000..1c48f80ad --- /dev/null +++ b/plugins/smplayer_plugin/testcorelib/test.pro @@ -0,0 +1,25 @@ +TEMPLATE = app +LANGUAGE = C++ + +CONFIG += qt warn_on release + +DEFINES += MINILIB NO_USE_INI_FILES +INCLUDEPATH += ../corelib .. +DEPENDPATH += .. + +HEADERS = myslider.h timeslider.h test.h +SOURCES = myslider.cpp timeslider.cpp test.cpp + +#SOURCES = test2.cpp + +LIBS += -L../corelib -L../corelib/release -lsmplayercore + +unix { + UI_DIR = .ui + MOC_DIR = .moc + OBJECTS_DIR = .obj +} + +win32 { + CONFIG += console +} diff --git a/plugins/smplayer_plugin/testcorelib/test2.cpp b/plugins/smplayer_plugin/testcorelib/test2.cpp new file mode 100644 index 000000000..312d5d99e --- /dev/null +++ b/plugins/smplayer_plugin/testcorelib/test2.cpp @@ -0,0 +1,33 @@ + +#include "smplayercorelib.h" +#include "global.h" +#include "helper.h" +#include "preferences.h" + +#include + +int main( int argc, char ** argv ) { + QApplication a( argc, argv ); + a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) ); + + Helper::setAppPath( qApp->applicationDirPath() ); + Global::global_init(); + + Global::pref->vo = "x11"; + + SmplayerCoreLib * player1 = new SmplayerCoreLib; + player1->mplayerWindow()->show(); + player1->mplayerWindow()->resize(624,352); + player1->core()->openFile("video1.avi"); + + SmplayerCoreLib * player2 = new SmplayerCoreLib; + + player2->mplayerWindow()->show(); + player2->mplayerWindow()->resize(624,352); + player2->core()->openFile("video2.avi"); + + int r = a.exec(); + Global::global_end(); + + return r; +} diff --git a/plugins/smplayer_plugin/timedialog.cpp b/plugins/smplayer_plugin/timedialog.cpp new file mode 100644 index 000000000..e0c2bb66a --- /dev/null +++ b/plugins/smplayer_plugin/timedialog.cpp @@ -0,0 +1,52 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "timedialog.h" + +TimeDialog::TimeDialog( QWidget* parent, Qt::WindowFlags f ) + : QDialog(parent, f) +{ + setupUi(this); + + time_edit->setDisplayFormat("H:mm:ss"); +} + +TimeDialog::~TimeDialog() { +} + +void TimeDialog::setTime(int seconds) { + QTime t; + time_edit->setTime(t.addSecs(seconds)); +} + +int TimeDialog::time() { + QTime t; + return t.secsTo(time_edit->time()); +} + +void TimeDialog::setMaximumTime( int seconds ) { + QTime t; + time_edit->setMaximumTime(t.addSecs(seconds)); +} + +int TimeDialog::maximumTime() { + QTime t; + return t.secsTo(time_edit->maximumTime()); +} + +#include "moc_timedialog.cpp" diff --git a/plugins/smplayer_plugin/timedialog.h b/plugins/smplayer_plugin/timedialog.h new file mode 100644 index 000000000..7ea5f74a6 --- /dev/null +++ b/plugins/smplayer_plugin/timedialog.h @@ -0,0 +1,40 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _TIMEDIALOG_H_ +#define _TIMEDIALOG_H_ + +#include "ui_timedialog.h" + +class TimeDialog : public QDialog, public Ui::TimeDialog +{ + Q_OBJECT + +public: + TimeDialog( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~TimeDialog(); + + int time(); + int maximumTime(); + +public slots: + void setTime(int seconds); + void setMaximumTime( int seconds ); +}; + +#endif diff --git a/plugins/smplayer_plugin/timedialog.ui b/plugins/smplayer_plugin/timedialog.ui new file mode 100644 index 000000000..98debb7f0 --- /dev/null +++ b/plugins/smplayer_plugin/timedialog.ui @@ -0,0 +1,126 @@ + + TimeDialog + + + + 0 + 0 + 195 + 91 + + + + SMPlayer - Seek + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + &Jump to: + + + Qt::AlignCenter + + + time_edit + + + + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + TimeDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TimeDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/plugins/smplayer_plugin/timeslider.cpp b/plugins/smplayer_plugin/timeslider.cpp new file mode 100644 index 000000000..290fa21dd --- /dev/null +++ b/plugins/smplayer_plugin/timeslider.cpp @@ -0,0 +1,146 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "timeslider.h" + +#include +#include + +#define DEBUG 0 + +TimeSlider::TimeSlider( QWidget * parent ) : MySlider(parent) +{ + dont_update = FALSE; + setMinimum(0); +#ifdef SEEKBAR_RESOLUTION + setMaximum(SEEKBAR_RESOLUTION); +#else + setMaximum(100); +#endif + + setFocusPolicy( Qt::NoFocus ); + setSizePolicy( QSizePolicy::Expanding , QSizePolicy::Fixed ); + + connect( this, SIGNAL( sliderPressed() ), this, SLOT( stopUpdate() ) ); + connect( this, SIGNAL( sliderReleased() ), this, SLOT( resumeUpdate() ) ); + connect( this, SIGNAL( sliderReleased() ), this, SLOT( mouseReleased() ) ); + connect( this, SIGNAL( valueChanged(int) ), this, SLOT( valueChanged_slot(int) ) ); +#if ENABLE_DELAYED_DRAGGING + connect( this, SIGNAL(draggingPos(int) ), this, SLOT(checkDragging(int)) ); + + last_pos_to_send = -1; + timer = new QTimer(this); + connect( timer, SIGNAL(timeout()), this, SLOT(sendDelayedPos()) ); + timer->start(200); +#endif +} + +TimeSlider::~TimeSlider() { +} + +void TimeSlider::stopUpdate() { + #if DEBUG + qDebug("TimeSlider::stopUpdate"); + #endif + dont_update = TRUE; +} + +void TimeSlider::resumeUpdate() { + #if DEBUG + qDebug("TimeSlider::resumeUpdate"); + #endif + dont_update = FALSE; +} + +void TimeSlider::mouseReleased() { + #if DEBUG + qDebug("TimeSlider::mouseReleased"); + #endif + emit posChanged( value() ); +} + +void TimeSlider::valueChanged_slot(int v) { + #if DEBUG + qDebug("TimeSlider::changedValue_slot: %d", v); + #endif + + // Only to make things clear: + bool dragging = dont_update; + if (!dragging) { + if (v!=position) { + #if DEBUG + qDebug(" emitting posChanged"); + #endif + emit posChanged(v); + } + } else { + #if DEBUG + qDebug(" emitting draggingPos"); + #endif + emit draggingPos(v); + } +} + +#if ENABLE_DELAYED_DRAGGING +void TimeSlider::setDragDelay(int d) { + qDebug("TimeSlider::setDragDelay: %d", d); + timer->setInterval(d); +} + +int TimeSlider::dragDelay() { + return timer->interval(); +} + +void TimeSlider::checkDragging(int v) { + qDebug("TimeSlider::checkDragging: %d", v); + last_pos_to_send = v; +} + +void TimeSlider::sendDelayedPos() { + if (last_pos_to_send != -1) { + qDebug("TimeSlider::sendDelayedPos: %d", last_pos_to_send); + emit delayedDraggingPos(last_pos_to_send); + last_pos_to_send = -1; + } +} +#endif + +void TimeSlider::setPos(int v) { + #if DEBUG + qDebug("TimeSlider::setPos: %d", v); + qDebug(" dont_update: %d", dont_update); + #endif + + if (v!=pos()) { + if (!dont_update) { + position = v; + setValue(v); + } + } +} + +int TimeSlider::pos() { + return position; +} + +void TimeSlider::wheelEvent( QWheelEvent * e ) { + e->ignore(); +} + + +#include "moc_timeslider.cpp" diff --git a/plugins/smplayer_plugin/timeslider.h b/plugins/smplayer_plugin/timeslider.h new file mode 100644 index 000000000..854f51814 --- /dev/null +++ b/plugins/smplayer_plugin/timeslider.h @@ -0,0 +1,72 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _TIMESLIDER_H_ +#define _TIMESLIDER_H_ + +#include "myslider.h" +#include "config.h" + +class TimeSlider : public MySlider +{ + Q_OBJECT + +public: + TimeSlider( QWidget * parent ); + ~TimeSlider(); + +public slots: + virtual void setPos(int); // Don't use setValue! + virtual int pos(); +#if ENABLE_DELAYED_DRAGGING + void setDragDelay(int); + int dragDelay(); +#endif + +signals: + void posChanged(int); + void draggingPos(int); +#if ENABLE_DELAYED_DRAGGING + //! Emitted with a few ms of delay + void delayedDraggingPos(int); +#endif + +protected slots: + void stopUpdate(); + void resumeUpdate(); + void mouseReleased(); + void valueChanged_slot(int); +#if ENABLE_DELAYED_DRAGGING + void checkDragging(int); + void sendDelayedPos(); +#endif + + virtual void wheelEvent( QWheelEvent * e ); + +private: + bool dont_update; + int position; + +#if ENABLE_DELAYED_DRAGGING + int last_pos_to_send; + QTimer * timer; +#endif +}; + +#endif + diff --git a/plugins/smplayer_plugin/titletracks.cpp b/plugins/smplayer_plugin/titletracks.cpp new file mode 100644 index 000000000..755bb5444 --- /dev/null +++ b/plugins/smplayer_plugin/titletracks.cpp @@ -0,0 +1,88 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "titletracks.h" + +TitleTracks::TitleTracks() { + clear(); +} + +TitleTracks::~TitleTracks() { +} + +void TitleTracks::clear() { + tm.clear(); +} + +void TitleTracks::addName(int ID, QString name) { + tm[ID].setName(name); + tm[ID].setID(ID); +} + +void TitleTracks::addDuration(int ID, double duration) { + tm[ID].setDuration(duration); + tm[ID].setID(ID); +} + +void TitleTracks::addChapters(int ID, int n) { + tm[ID].setChapters(n); + tm[ID].setID(ID); +} + +void TitleTracks::addAngles(int ID, int n) { + tm[ID].setAngles(n); + tm[ID].setID(ID); +} + +void TitleTracks::addID(int ID) { + tm[ID].setID(ID); +} + + +int TitleTracks::numItems() { + return tm.count(); +} + +bool TitleTracks::existsItemAt(int n) { + return ((n > 0) && (n < numItems())); +} + +TitleData TitleTracks::itemAt(int n) { + return tm.values()[n]; +} + +TitleData TitleTracks::item(int ID) { + return tm[ID]; +} + +int TitleTracks::find(int ID) { + for (int n=0; n < numItems(); n++) { + if (itemAt(n).ID() == ID) return n; + } + return -1; +} + +void TitleTracks::list() { + QMapIterator i(tm); + while (i.hasNext()) { + i.next(); + TitleData d = i.value(); + qDebug("TitleTracks::list: item %d: ID: %d name: '%s' duration %f chapters: %d angles: %d", + i.key(), d.ID(), d.name().toUtf8().constData(), d.duration(), d.chapters(), d.angles() ); + } +} diff --git a/plugins/smplayer_plugin/titletracks.h b/plugins/smplayer_plugin/titletracks.h new file mode 100644 index 000000000..bccc4bf01 --- /dev/null +++ b/plugins/smplayer_plugin/titletracks.h @@ -0,0 +1,98 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _TITLETRACKS_H_ +#define _TITLETRACKS_H_ + +#include +#include "helper.h" + +/* Class to store info about DVD titles */ + +class TitleData { + +public: + TitleData() { _name = ""; _duration = 0; _ID = -1; _chapters = 0; _angles = 0; }; + ~TitleData() {}; + + void setName( const QString & n ) { _name = n; }; + void setDuration( double d ) { _duration = d; }; + void setChapters( int n ) { _chapters = n; }; + void setAngles( int n ) { _angles = n; }; + void setID( int id ) { _ID = id; }; + + QString name() const { return _name; }; + double duration() const { return _duration; }; + int chapters() const { return _chapters; }; + int angles() const { return _angles; }; + int ID() const { return _ID; }; + + QString displayName() const { + QString dname = ""; + + if (!_name.isEmpty()) { + dname = _name; + } + else + dname = QString::number(_ID); + + if (_duration > 0) { + dname += " ("+ Helper::formatTime( (int) _duration ) +")"; + } + + return dname; + }; + +protected: + QString _name; + double _duration; + int _chapters; + int _angles; + + int _ID; +}; + + +class TitleTracks { + +public: + TitleTracks(); + ~TitleTracks(); + + void clear(); + void list(); + + void addName(int ID, QString name); + void addDuration(int ID, double duration); + void addChapters(int ID, int n); + void addAngles(int ID, int n); + void addID(int ID); + + int numItems(); + bool existsItemAt(int n); + + TitleData itemAt(int n); + TitleData item(int ID); + int find(int ID); + +protected: + typedef QMap TitleMap; + TitleMap tm; +}; + +#endif diff --git a/plugins/smplayer_plugin/toolbareditor.cpp b/plugins/smplayer_plugin/toolbareditor.cpp new file mode 100644 index 000000000..ec1338b00 --- /dev/null +++ b/plugins/smplayer_plugin/toolbareditor.cpp @@ -0,0 +1,79 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "toolbareditor.h" + +QStringList ToolbarEditor::save(QWidget * w) { + qDebug("ToolbarEditor::save: '%s'", w->objectName().toUtf8().data()); + + QList list = w->actions(); + QStringList o; + QAction * action; + + for (int n = 0; n < list.count(); n++) { + action = static_cast (list[n]); + if (action->isSeparator()) { + o << "separator"; + } + else + if (!action->objectName().isEmpty()) { + o << action->objectName(); + } + else + qWarning("ToolbarEditor::save: unknown action at pos %d", n); + } + + return o; +} + +void ToolbarEditor::load(QWidget *w, QStringList l, QList actions_list) +{ + qDebug("ToolbarEditor::load: '%s'", w->objectName().toUtf8().data()); + + QAction * action; + + for (int n = 0; n < l.count(); n++) { + qDebug("ToolbarEditor::load: loading action %s", l[n].toUtf8().data()); + + if (l[n] == "separator") { + qDebug("ToolbarEditor::load: adding separator"); + QAction * sep = new QAction(w); + sep->setSeparator(true); + w->addAction(sep); + } else { + action = findAction(l[n], actions_list); + if (action) { + w->addAction(action); + } else { + qWarning("ToolbarEditor::load: action %s not found", l[n].toUtf8().data()); + } + } + } +} + +QAction * ToolbarEditor::findAction(QString s, QList actions_list) { + QAction * action; + + for (int n = 0; n < actions_list.count(); n++) { + action = static_cast (actions_list[n]); + if (action->objectName() == s) return action; + } + + return 0; +} + diff --git a/plugins/smplayer_plugin/toolbareditor.h b/plugins/smplayer_plugin/toolbareditor.h new file mode 100644 index 000000000..68863894f --- /dev/null +++ b/plugins/smplayer_plugin/toolbareditor.h @@ -0,0 +1,43 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _TOOLBAR_EDITOR_H_ +#define _TOOLBAR_EDITOR_H_ + +#include +#include +#include +#include + +class ToolbarEditor +{ +public: + + //! Save the widget's list of actions into a QStringList + static QStringList save(QWidget *w); + + //! Added to the widget the actions specified in l. actions_list is + //! the list of all available actions + static void load(QWidget *w, QStringList l, QList actions_list); + +protected: + static QAction * findAction(QString s, QList actions_list); +}; + +#endif + diff --git a/plugins/smplayer_plugin/tracks.cpp b/plugins/smplayer_plugin/tracks.cpp new file mode 100644 index 000000000..6ebe7a187 --- /dev/null +++ b/plugins/smplayer_plugin/tracks.cpp @@ -0,0 +1,98 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tracks.h" +#include + +Tracks::Tracks() { + clear(); +} + +Tracks::~Tracks() { +} + +void Tracks::clear() { + tm.clear(); +} + +void Tracks::addLang(int ID, QString lang) { + tm[ID].setLang(lang); + tm[ID].setID(ID); +} + +void Tracks::addName(int ID, QString name) { + tm[ID].setName(name); + tm[ID].setID(ID); +} + +void Tracks::addID(int ID) { + tm[ID].setID(ID); +} + + +int Tracks::numItems() { + return tm.count(); +} + +bool Tracks::existsItemAt(int n) { + return ((n > 0) && (n < numItems())); +} + +TrackData Tracks::itemAt(int n) { + return tm.values()[n]; +} + +TrackData Tracks::item(int ID) { + return tm[ID]; +} + +int Tracks::find(int ID) { + for (int n=0; n < numItems(); n++) { + if (itemAt(n).ID() == ID) return n; + } + return -1; +} + +int Tracks::findLang(QString expr) { + qDebug( "Tracks::findLang: '%s'", expr.toUtf8().data()); + QRegExp rx( expr ); + + int res_id = -1; + + for (int n=0; n < numItems(); n++) { + qDebug("Tracks::findLang: lang #%d '%s'", n, itemAt(n).lang().toUtf8().data()); + if (rx.indexIn( itemAt(n).lang() ) > -1) { + qDebug("Tracks::findLang: found preferred lang!"); + res_id = itemAt(n).ID(); + break; + } + } + + return res_id; +} + +void Tracks::list() { + QMapIterator i(tm); + while (i.hasNext()) { + i.next(); + TrackData d = i.value(); + qDebug("Tracks::list: item %d: ID: %d lang: '%s' name: '%s'", + i.key(), d.ID(), d.lang().toUtf8().constData(), d.name().toUtf8().constData() ); + } +} + diff --git a/plugins/smplayer_plugin/tracks.h b/plugins/smplayer_plugin/tracks.h new file mode 100644 index 000000000..000235131 --- /dev/null +++ b/plugins/smplayer_plugin/tracks.h @@ -0,0 +1,101 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _TRACKS_H_ +#define _TRACKS_H_ + +#include +#include + +/* Class to store info about video/audio tracks */ + +class TrackData { + +public: + + TrackData() { _lang = ""; _name = "";_ID = -1; }; + ~TrackData() {}; + + void setLang( const QString & l ) { _lang = l; }; + void setName( const QString & n ) { _name = n; }; + void setID( int id ) { _ID = id; }; + + QString lang() const { return _lang; }; + QString name() const { return _name; }; + int ID() const { return _ID; }; + + QString displayName() const { + QString dname=""; + + if (!_name.isEmpty()) { + dname = _name; + if (!_lang.isEmpty()) { + dname += " ["+ _lang + "]"; + } + } + else + if (!_lang.isEmpty()) { + dname = _lang; + } + else + dname = QString::number(_ID); + + return dname; + } + +protected: + + /* Language code: es, en, etc. */ + QString _lang; + + /* spanish, english... */ + QString _name; + + int _ID; +}; + + +class Tracks { + +public: + + Tracks(); + ~Tracks(); + + void clear(); + void list(); + + void addLang(int ID, QString lang); + void addName(int ID, QString name); + void addID(int ID); + + int numItems(); + bool existsItemAt(int n); + + TrackData itemAt(int n); + TrackData item(int ID); + int find(int ID); + + int findLang(QString expr); + +protected: + typedef QMap TrackMap; + TrackMap tm; +}; + +#endif diff --git a/plugins/smplayer_plugin/translations/smplayer_ar_SY.ts b/plugins/smplayer_plugin/translations/smplayer_ar_SY.ts new file mode 100644 index 000000000..8991d02f9 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_ar_SY.ts @@ -0,0 +1,7238 @@ + + + + About + + + Version: %1 + الأصدار :%1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + GNU General Public License قام بتعريب البرناج محمد نورحاج عمر ,الرنامج مجاني و خاضع لأتفاقية البرامج المجانيــة + + + + The following people have contributed with translations: + المساهمين في عملية ترجمة المشغل + + + + German + German + + + + Slovak + Slovak + + + + Italian + Italian + + + + French + French + + + + %1, %2 and %3 + %1, %2 and %3 + + + + Simplified-Chinese + Simplified-Chinese + + + + Russian + Russian + + + + %1 and %2 + %1 and %2 + + + + Hungarian + Hungarian + + + + Polish + Polish + + + + Japanese + Japanese + + + + Dutch + Dutch + + + + Ukrainian + Ukrainian + + + + Portuguese - Brazil + Portuguese - Brazil + + + + Georgian + Georgian + + + + Czech + Georgian + + + + Bulgarian + Bulgarian + + + + Turkish + Turkish + + + + Swedish + Swedish + + + + Serbian + Serbian + + + + Traditional Chinese + Traditional Chinese + + + + Romanian + Romanian + + + + Portuguese - Portugal + Portuguese - Portugal + + + + Greek + Greek + + + + Finnish + انتهى + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + SMPlayer حول مشغل + + + + &Info + معلومات + + + + icon + الايقونة + + + + &Contributions + المساهمات + + + + &Translators + المرجمين + + + + &License + الأتفاقيــة + + + + Visit our web for updates: + قم بزيارة الموقع من اجل التحديثات : + + + + Get help in our forum: + لأي مساعدة قم بزيارة المنتدى + + + + You can support SMPlayer by making a donation. + بأمكانك دعم المشغل عن طريق التبرع + + + + More info + معلومات اضافية + + + + Korean + Korean + + + + Macedonian + Macedonian + + + + Basque + Basque + + + + Using MPlayer %1 + %1 MPlayer استخدام + + + + Catalan + Catalan + + + + Portable Edition + الاصدار المحمول + + + + Using Qt %1 (compiled with Qt %2) + Using Qt %1 (compiled with Qt %2) + + + + Slovenian + Slovenian + + + + Arabic + + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + الأسم + + + + Description + الوصف + + + + Shortcut + الأختصار + + + + &Save + حفظ + + + + &Load + تحميل + + + + Key files + مفاتيح الملفات + + + + Choose a filename + اختيار اسم ملف + + + + Confirm overwrite? + تأكيد الأستبدال + + + + The file %1 already exists. +Do you want to overwrite? + + الملف %1 موجود مسبقا ًهل تريد استبداله ؟ + + + + Choose a file + اختر ملفا + + + + Error + خطـــأ + + + + The file couldn't be saved + لا يمكن حفظ الملف + + + + The file couldn't be loaded + لا يمكن تحميل الملف + + + + &Change shortcut... + تغيير الأختصــار + + + + AudioEqualizer + + + Audio Equalizer + موازن الصوت + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + تطبيق + + + + &Reset + الأفتراضي + + + + &Set as default values + تعيين القيم الأفتراضية + + + + Use the current values as default values for new videos. + استخدام القيم الحالية كقيم افتراضية للفيديو + + + + Set all controls to zero. + تعيين كل ازرار التحكم الى الصفر + + + + Information + معلومات + + + + The current values have been stored to be used as default. + القيمة الحالية تم حفظها لكي تستخدم كقيمة افتراضية + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer تقريــر + + + + SMPlayer - smplayer log + SMPlayer - smplayer تقـريــر + + + + &Open + فتــح + + + + &Play + تشغيل + + + + &Video + فيديو + + + + &Audio + صوت + + + + &Subtitles + الترجمات + + + + &Browse + استعراض + + + + Op&tions + اعــدادات + + + + &Help + مساعدة + + + + &File... + ملـف . + + + + D&irectory... + المسار + + + + &Playlist... + قائمــة التشغيل + + + + &DVD from drive + من قرصDVD + + + + D&VD from folder... + من مجلد D&VD + + + + &URL... + رابط انترنت + + + + &Clear + ازالة + + + + &Recent files + الملفات المشغلة مؤخرا + + + + P&lay + تشغيل + + + + &Pause + ايقاف مؤقت + + + + &Stop + ايقاف + + + + &Frame step + خطوة للأمام + + + + &Normal speed + سرعة عادية + + + + &Halve speed + نصف السرعة + + + + &Double speed + سرعة مزدوجة + + + + Speed &-10% + &-10% تسريع الى + + + + Speed &+10% + &+10% تسريع الى + + + + Sp&eed + تسريع + + + + &Repeat + اعادة + + + + &Fullscreen + ملء الشاشة + + + + &Compact mode + النمط المضغوط + + + + Si&ze + الحجم + + + + 4:3 &Letterbox + 4:3 & + + + + 16:9 L&etterbox + 16:9 + + + + 4:3 &Panscan + 4:3 + + + + 4:3 &to 16:9 + 4:3 &to 16:9 + + + + &Aspect ratio + نسبة الطول الى الارتفاع الحقيقية + + + + &None + بلا + + + + &Lowpass5 + تمرير منخفض + + + + Linear &Blend + شفاف و عاتم + + + + &Deinterlace + Deinterlace + + + + &Postprocessing + معالجة موضوعية + + + + &Autodetect phase + اكتشاف تلقائب + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + اضافة ضجيج + + + + F&ilters + الفلاتر + + + + &Equalizer + الموازن + + + + &Screenshot + الصور الملتقطة + + + + S&tay on top + البقاء في الأعلى + + + + &Extrastereo + ستيريو اضافي + + + + &Karaoke + كاريوكي + + + + &Filters + الفلاتر + + + + &Stereo + ستيريو + + + + &4.0 Surround + &4.0 محيط + + + + &5.1 Surround + &5.1 محيط + + + + &Channels + القنــوات + + + + &Left channel + الجهة اليسرى + + + + &Right channel + الجهة اليمنى + + + + &Stereo mode + نمط الستيريو + + + + &Mute + كتم الصوت + + + + Volume &- + خفض الصوت &- + + + + Volume &+ + رفع الصوت &+ + + + + &Delay - + تأخير - + + + + D&elay + + تقديم + + + + + &Select + تحديد + + + + &Load... + تحميل + + + + Delay &- + تأخير - + + + + Delay &+ + تقديم + + + + + &Up + أعلى + + + + &Down + اسفل + + + + &Title + العنوان + + + + &Chapter + المقطع + + + + &Angle + الفصل + + + + &Playlist + قائمة التشغيل + + + + &Show frame counter + اظهار عدد الشرائح + + + + &Disabled + معطل + + + + &Seek bar + شريط التمرير + + + + &Time + الوقت + + + + Time + T&otal time + الوقت + الوقت الكلي + + + + &OSD + &OSD + + + + &View logs + اظهار التقرير + + + + P&references + أعـــدادات + + + + About &Qt + &Qt حــول + + + + About &SMPlayer + SMPlayer حول مشغل + + + + <empty> + فارغ + + + + Video + الفيديو + + + + Audio + الصوت + + + + Playlists + قوائم التشغيل + + + + All files + كل الملفات + + + + Choose a file + اختر ملفا + + + + SMPlayer - Information + SMPlayer - معلومات + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + مشغل الاقراص الليزرية غير معد بعد +ستظهر نافذة اعدادا ت الاقراص الليزرية الآن + + + + Choose a directory + اختر مسارا ً + + + + Subtitles + الترجمــات + + + + About Qt + Qt حول + + + + Playing %1 + %1 تشغيل + + + + Pause + ايقاف مؤقت + + + + Stop + ايقاف + + + + Play / Pause + تشغيل /ايقاف مؤقت + + + + Pause / Frame step + ايقاف مؤقت/خطوة للأمام + + + + U&nload + الغاء تحميل + + + + V&CD + فيديو سي دي + + + + C&lose + اغلاق + + + + View &info and properties... + اظهار المعلومات و الخصائص + + + + Zoom &- + تبعيد &- + + + + Zoom &+ + تقريب &+ + + + + &Reset + الأفتراضي + + + + Move &left + التحريك لليسار + + + + Move &right + التحريك لليمين + + + + Move &up + التحريك للأعلى + + + + Move &down + التحريك للأسفل + + + + &Pan && scan + تقريب و فحص + + + + &Previous line in subtitles + الجملة السابقة في الترجمة + + + + N&ext line in subtitles + الجملة التالية في الترجمة + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + (2)انقاص الدرجة + + + + Inc volume (2) + (2)رفع الدرجة + + + + Exit fullscreen + الخروج من وضع ملء الشاشة + + + + OSD - Next level + OSD - المرحلة التالية + + + + Dec contrast + انقاص التعتيم + + + + Inc contrast + رفع التعتيم + + + + Dec brightness + انقاص التبهيت + + + + Inc brightness + رفع التبهيت + + + + Dec hue + انقاص الشكل + + + + Inc hue + رفع الشكل + + + + Dec saturation + انقاص الإشباع + + + + Dec gamma + انقاص اشعة غاما + + + + Next audio + الصوت التالي + + + + Next subtitle + الترجمة التالية + + + + Next chapter + المقطع التالي + + + + Previous chapter + المقطع السابق + + + + Inc saturation + زيادة الأشباع + + + + Inc gamma + زيادة اشعة غاما + + + + &Load external file... + تحميل ملف خارجي + + + + &Kerndeint + Kerndeint + + + + &Yadif (normal) + Yadif قياسي + + + + Y&adif (double framerate) + Y&adif ترميز مرتفع + + + + &Next + التالي + + + + Pre&vious + السابق + + + + Volume &normalization + قياسات مستوى الصوت + + + + &Audio CD + قرص اوديو + + + + Denoise nor&mal + ألغاء ضجة قياسي + + + + Denoise &soft + ألغاء ضجة ناعم + + + + Denoise o&ff + ايقاف الغاء الضجة + + + + Use SSA/&ASS library + SSA/&ASS استخدام مكتبة + + + + Flip i&mage + قلب الصورة + + + + &Toggle double size + تعيين ضعف الحجم + + + + S&ize - + انقاص الحجم - + + + + Si&ze + + زيادة الحجم + + + + + Add &black borders + اضافة حدود سودا ء + + + + Soft&ware scaling + القياس البرمجي + + + + &FAQ + حول + + + + Visualize &motion vectors + المؤثرات & موجهات الحركة + + + + &Command line options + اعدادات موجه الأوامر + + + + SMPlayer command line options + اعدادات موجه اوامر المشغل + + + + Enable &closed caption + تمكين النوافذ المغلقة + + + + &Forced subtitles only + اجبار الترجمات فقط + + + + Reset video equalizer + اعادة موازن الفيديو الى الافتراضي + + + + MPlayer has finished unexpectedly. + بشكل غير متوقع MPlayer تم اغلاق + + + + Exit code: %1 + %1 كود الخروج + + + + MPlayer failed to start. + MPlayer فشل قي بدء + + + + Please check the MPlayer path in preferences. + في الاعدادات MPlayer قم بتفحص مسار + + + + MPlayer has crashed. + MPlayer ضرر في + + + + See the log for more info. + شاهد التقرير لمزيد من المعلومات + + + + &Rotate + أستدارة + + + + &Off + بلا + + + + &Rotate by 90 degrees clockwise and flip + استدارة ب90 درجة بإتجاه عقارب الساعة والقلب + + + + Rotate by 90 degrees &clockwise + استدارة ب90 درجة بإتجاه عقارب الساعة + + + + Rotate by 90 degrees counterclock&wise + استدارة ب90 درجة بعكس إتجاه عقارب الساعة + + + + Rotate by 90 degrees counterclockwise and &flip + استدارة ب90 درجة بعكس إتجاه عقارب الساعةو القلب + + + + &Jump to... + الأنتقال إلى + + + + Show context menu + اظهار القائمة اليمنى + + + + Multimedia + الوسائط الأعلامية + + + + E&qualizer + الموازن + + + + Reset audio equalizer + اعادة موازن الصوت الى الأفتراضي + + + + Find subtitles on &OpenSubtitles.org... + OpenSubtitles.org أيجاد الترجمة على موقع + + + + Upload su&btitles to OpenSubtitles.org... + OpenSubtitles.org رفع الترجمات الى + + + + &Tips + معلومات + + + + &Auto + تلقائي + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + المسار + + + + &Track + audio + المسار + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + ما زال يعمل هناSMPlayer مشغل + + + + S&how icon in system tray + اظهار الأيقونة قرب الساعة + + + + &Hide + أخفاء + + + + &Restore + أستعادة + + + + &Quit + أغلاق + + + + Playlist + قائمــة التشغيل + + + + Core + + + Brightness: %1 + %1 السطوع + + + + Contrast: %1 + %1 التغميق + + + + Gamma: %1 + %1 ألوان غاما + + + + Hue: %1 + %1 الشكل + + + + Saturation: %1 + %1 الإشباع + + + + Volume: %1 + %1 درجة الصوت + + + + Zoom: %1 + %1 التقريب + + + + Font scale: %1 + %1 حجم الخط + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + تعريب محمد نور SMPlayer + + + + Audio + الصوت + + + + Subtitle + الترجمة + + + + &Main toolbar + ادوات القائمــة + + + + &Language toolbar + لغة القوائم + + + + &Toolbars + القــوائم + + + + EqSlider + + + icon + الأيقونة + + + + ErrorDialog + + + Hide log + اخفاء التقرير + + + + Show log + اظهار التقرير + + + + MPlayer Error + MPlayer اخطاء + + + + icon + الأيقونة + + + + Error + خطأ + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + خصائص الملف + + + + &Information + معلومات + + + + &Demuxer + الخالط + + + + &Select the demuxer that will be used for this file: + حدد خالطا ً ليتم استخدامه مع الملف + + + + &Reset + اعادة الافتراضي + + + + &Video codec + كوديك الفيديو + + + + &Select the video codec: + حدد كوديك الفيديو + + + + A&udio codec + كوديك الصوت + + + + &Select the audio codec: + حدد كوديك الصوت + + + + &MPlayer options + MPlayer اعدادات + + + + Additional Options for MPlayer + MPlayer أعدادات اضافية لــ + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + من هنا يمكك اضافة اعدادات اضافية +اكتبهم منفصلات بـ بالمساحات الفارغة +مثال : قلب-بدون صوت + + + + &Options: + أعدادات + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + بأمكانك أيضا ًاضافة كوديك فيديو اضافي +افصلهم عن طرسق اضافة ""و لا تستخدم المسطرة + +scale=512:-2,eq2=1.1 مثال + + + + V&ideo filters: + فلاتر الفيديو + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + و فلاتر الصوت الأخيرة تعمل كفلاتر الفيديو +و طريقتها مثل طريقة فلاتر الفيديو + + + + Audio &filters: + فلاتر الصوت + + + + OK + حسنا + + + + Cancel + إلغــاء + + + + Apply + تطبيـق + + + + FindSubtitlesWindow + + + Language + اللغـــة + + + + Name + الأسم + + + + Format + الصيغة + + + + Files + الملفــات + + + + Date + التاريخ + + + + Uploaded by + رفعت عن طريق + + + + All + الكل + + + + Close + اغلاق + + + + &Download + تحميل + + + + &Copy link to clipboard + نسخ الرابط الى الذاكرة المؤقتة + + + + Error + خطأ + + + + Download failed: %1. + %1. فشل تحميل + + + + Connecting to %1... + %1... الأتصــال بــ + + + + Downloading... + يتم التحميل + + + + Done. + تـــم + + + + %1 files available + %1 الملفات المتوفرة + + + + Failed to parse the received data. + فشل في قراءة البيانات المتلقاة + + + + Find Subtitles + ايجاد الترجمات + + + + &Subtitles for + ترجمة من اجل + + + + &Language: + اللغــة + + + + &Refresh + تحديث + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + عــام + + + + Size + الحجم + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + المسار + + + + Length + المدة + + + + Demuxer + الخالط + + + + Name + الأسم + + + + Artist + المؤدي + + + + Author + المالك + + + + Album + الألبوم + + + + Genre + الصنف + + + + Date + التاريخ + + + + Track + المسار + + + + Copyright + الحقوق + + + + Comment + تعليق + + + + Software + البرنامج + + + + Clip info + معلومات المقطع + + + + Video + الفيديو + + + + Resolution + الأبعاد + + + + Aspect ratio + نسبة الطول للعرض + + + + Format + الصيغة + + + + Bitrate + معدل الترميز + + + + %1 kbps + %1 kbps + + + + Frames per second + الشرائح بأجزاء الثانية + + + + Selected codec + الكوديك المحدد + + + + Initial Audio Stream + جدول الصوت السمعي + + + + Rate + الترميز + + + + %1 Hz + %1 Hz + + + + Channels + القنوات + + + + Audio Streams + الجداول السمعية + + + + Language + اللغــة + + + + empty + فارغ + + + + Subtitles + الترجمــات + + + + Type + النوع + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + جدول العناوين + + + + Stream URL + جدول المسار + + + + File + ملف + + + + InputDVDDirectory + + + Choose a directory + أختر مسارا ً + + + + SMPlayer - Play a DVD from a folder + من مجلد DVD تشغيل + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + VIDEO_TS and AUDIO_TS بأمكانك تشغيل فيديو الدي في دي من قرصك الصلب بأستعراض المجلد + + + + Choose a directory... + أختر مسارا + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + MPlayer أدخال اصدار + + + + SMPlayer couldn't identify the MPlayer version you're using. + الذي تستخدمه MPlayer المشغل لم يستطع تحديد اصدار + + + + Version reported by MPlayer: + MPlayer تقريرالاصدار من + + + + Please, &select the correct version: + قم بتحديد الأصدار الصحيح + + + + 1.0rc1 or older + 1.0rc1 or older + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Greater than 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + ادخل مسار + + + + &URL: + المسار + + + + It's a &playlist + إنها قائمة تشغيل + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + اذا قمت بتحديد هذا المربع سيعتبرها المشغل كقائمة تشغيل و سيفتح لك قائمة تشغيل في ملف نصي و انت ستشغلها كما تود + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + العربية + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + + + + + Welsh + + + + + Danish + + + + + German + + + + + Greek + + + + + English + + + + + Esperanto + + + + + Spanish + + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + + + + + Faroese + + + + + French + + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + + + + + Inuktitut + + + + + Japanese + + + + + Javanese + + + + + Georgian + + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + + + + + Portuguese + + + + + Quechua + + + + + Romanian + + + + + Russian + + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + + + + + Sundanese + + + + + Swedish + + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + + + + + Portuguese - Portugal + + + + + Simplified-Chinese + + + + + Traditional Chinese + + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + + + + + Western European Languages with Euro + + + + + Slavic/Central European Languages + + + + + Esperanto, Galician, Maltese, Turkish + + + + + Old Baltic charset + + + + + Cyrillic + + + + + Modern Greek + + + + + Baltic + + + + + Celtic + + + + + Hebrew charsets + + + + + Ukrainian, Belarusian + + + + + Simplified Chinese charset + + + + + Traditional Chinese charset + + + + + Japanese charsets + + + + + Korean charset + + + + + Thai charset + + + + + Cyrillic Windows + + + + + Slavic/Central European Windows + + + + + Arabic Windows + Windowsعربي + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + اختر اسم للملف لحفظه في الأسفل + + + + Confirm overwrite? + تأكيد الأستبدال؟ + + + + The file already exists. +Do you want to overwrite? + الملف موجود مسبقا +هل تريد استبداله؟ + + + + Error saving file + خطأ في حفظ الملف + + + + The log couldn't be saved + لا يمكن حفظ التقرير + + + + Logs + التقارير + + + + LogWindowBase + + + Log Window + نافذة التقرير + + + + Save + حفظ + + + + Copy to clipboard + نسخ + + + + &Close + اغلاق + + + + Close + أغلاق + + + + MiniGui + + + Control bar + شريط التحكم + + + + MpcGui + + + Control bar + + + + + -%1 + + + + + +%1 + + + + + Playlist + + + Name + الأسم + + + + Length + المدة + + + + &Play + تشغيل + + + + &Edit + تحرير + + + + Playlists + قوائم التشغيل + + + + Choose a file + اختر ملف + + + + Choose a filename + اختر اسم ملف + + + + Confirm overwrite? + تأكيد الاستبدال + + + + The file %1 already exists. +Do you want to overwrite? + الملف %1 موجود مسبقا +هل تريد أستبداله؟ + + + + All files + كل الملفـــات + + + + Select one or more files to open + حدد ملف او اكثر لفتحه + + + + Choose a directory + اختر مسارا ً + + + + Edit name + تحرير الأسم + + + + Type the name that will be displayed in the playlist for this file: + اكتب الأسم الذي تريده أن يظهر في قائمة تشغيل الملف + + + + &Load + تحميل + + + + &Save + حفظ + + + + &Next + التالي + + + + Pre&vious + السابق + + + + Move &up + النقل للاعلى + + + + Move &down + النقل للأسفل + + + + &Repeat + اعادة تشغيل + + + + S&huffle + S&huffle + + + + Add &current file + اضافة الملفات الحالية + + + + Add &file(s) + اضافة ملفــ(ات + + + + Add &directory + اضافة مسار + + + + Remove &selected + ازالة المحدد + + + + Remove &all + ازالــة الكل + + + + SMPlayer - Playlist + SMPlayer -قائمة تشغيل + + + + Add... + اضافة + + + + Remove... + ازالة + + + + Playlist modified + تعــديل قائمة التشغيل + + + + There are unsaved changes, do you want to save the playlist? + هناك تغييرات غير محفوظة هل تريد حفظ قائمة التشغيل ؟ + + + + Preferences + أعـــدادات + + + + PlaylistPreferences + + + Playlist - Preferences + اعدادات قائمة التشغيل + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + حدد الخيار الذي تريد اضافته الى المسار و اضافته ايضا الى الملفات بشكل تكراري و في غير حالة الملفات المحددة في المسار سيتم اضافتها حصرا + + + + &Add files in directories recursively + اضافة الملفات بشكل تكراري + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + حدد هذا الخيار لإستفسار الملفات لكي تضاف إلى قائمة التشغيل لبعض المعلومات. الذي يسمح لأظهار اسم العنوان (إذا توفر) وطول الملفات. ما عدا ذلك هذه المعلومات لن تكون متوفرة حتى يشغل الملف. ملاحظة: هذا الخيار يمكن أَن يكون بطيئ، خصوصاً إذا أضيف العديد من الملفات. + + + + Automatically get &info about files added + احضار المعلومات تلقائيا عن الملفات المضافة + + + + &Save copy of playlist on exit + حفظ نسخة من قائمة التشغيل عند الخروج + + + + &Play files from start + تشغيل الملف من البدايــة + + + + PrefAdvanced + + + Advanced + متقدم + + + + Auto + تلقائي + + + + &Advanced + متقدم + + + + icon + ايقونة + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + +MPlayer.بامكانك هنا اضافة اعدادات اضافية لـاكتبهم بشكل منفصل عن المساحات +Example: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + You can also pass additional video filters.(new line)Separate them with ",". Do not use spaces!(new line)Example: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + And finally audio filters. Same rule as for video filters.(new line)Example: resample=44100:0:0,volnorm + + + + Log MPlayer output + MPlayer مكان حفظ تقارير + + + + Log SMPlayer output + SMPlayer مكان حفظ تقارير + + + + This option is mainly intended for debugging the application. + هذا الخيارمهم بشكل رئيسي لتنقيح التطبيق. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + تأشير هذا الأعداد ربما يسبب وميضا , و ربما يقوم بأنتاج فيديو لا يظهر أيضا ً + + + + Filter for SMPlayer logs + SMPlayer تقرير فلاتر + + + + &Monitor aspect: + مراقب الشاشة + + + + &Run MPlayer in its own window + الخاصة MPlayer تشغيل في نافذة + + + + &Options: + اعدادات + + + + V&ideo filters: + فلاتر الفيــديو + + + + Audio &filters: + فلاتــر الصوت + + + + &Colorkey: + مفاتيح الألــوان + + + + Log &SMPlayer output + SMPlayer مكان حفظ تقارير + + + + &Filter for SMPlayer logs: + SMPlayer تقارير فلاتر + + + + C&hange... + تغيير + + + + Logs + تقارير + + + + Log MPlayer &output + MPlayer مكان حفظ تقارير + + + + Options for MP&layer + MP&layer اعدادات لــ + + + + Autosave MPlayer log + MPlayer حفظ تلقائي لتقارير + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + Autosave MPlayer log filename + MPlayer حفظ تلقائي لتقارير + + + + Enter here the path and filename that will be used to save the MPlayer log. + ادخل هنا مسار و اسم الملف الذي سيستخدم لحفظ التقارير + + + + A&utosave MPlayer log to file + MPlayer حفظ تلقائي لتقارير + + + + Pass short filenames (8+3) to MPlayer + MPlayer تمرير اسماء الملفات القصيرة لــ + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + لا يمكن حاليا ً للمشغل تشغيل اسم الملف الذي يحتوي كودات صفحات + + + + &Pass short filenames (8+3) to MPlayer + MPlayer تمرير اسماء الملفات القصيرة لــ + + + + Monitor aspect + مراقب الشاشة + + + + Select the aspect ratio of your monitor. + حدد قياسات ابعاد شاشتك + + + + Run MPlayer in its own window + في نافذته الخاصة MPlayer تشغيل + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + Colorkey + مفاتيح الألوان + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + في حال رؤية اجزاء من الفيديو من اي نافذة اخرى بأمكانك تغيير مفاتيح الألوان لأصلاحها جرب اللون المحدد لأغلاق الفوارغ + + + + Options for MPlayer + MPlayer اعدادات + + + + Options + اعدادات + + + + Here you can type options for MPlayer. Write them separated by spaces. + بأمكانك هنا كتابة اعدادت المشغل ,اكتبهم بشكل منفصل + + + + Video filters + فلاتر الفيديو + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + بأمكانك هنا اضافة فلاتر الفيديو للمشغل اكتبهم بشكل منفصل بأستخدام - لا تستخدم المساحات الفارغة + + + + Audio filters + فلاتر الصوت + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + بأمكانك من هنا اضافة فلاتر الصوت اكتبهم بأستخدام - لا تستخدم المساحات الفارغة + + + + Repaint the background of the video window + إصبغ خلفية نافذة الفيديو + + + + Repaint the backgroun&d of the video window + إصبغ خلفية نافذة الفيديو + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + تحـــذير + + + + Not all files could be associated. Please check your security permissions and retry. + ليس كل الملفات يمكن ربطها قم بتحديد مستوى الأمان ثم حاول مجددا + + + + File Types + اتواع الملفات + + + + Select all + تحديد الكل + + + + Check all file types in the list + تأشير كل انواع الملفات في القائمة + + + + Uncheck all file types in the list + الغاء تأشير كل الملفات في القائمة + + + + List of file types + قائمة انواع الملفات + + + + File types + انواع الملفات + + + + Media files handled by SMPlayer: + SMPlayer قائمة الصيغ المدعومة من + + + + Select All + تحديد الكل + + + + Select None + عدم تحديد شيء + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + قم بتحديد الملفات التي ترغب أن تعمل مع هذا المشغل ,عند الضغط على تطبيق سيتم ربط الملفات المحددة بالمشغل + + + + Select none + عدم تحديد شيء + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + (sp)<b>ملاحظة:</b> ( Windows Vistaالأستعادة لا تعمل مع). + + + + PrefDrives + + + Drives + الأقراص + + + + icon + + + + + CD device + CD جهاز اقراص الـ + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + لتشغيل ملفات الفيديو سي دي او اقراص الأوديو CDROM حدد جهاز أقراص + + + + DVD device + DVD قرص + + + + Choose your DVD device. It will be used to play DVDs. + DVD حدد جهاز أقراص الــ + + + + Select your &CD device: + &CD حدد جهاز أقراص الــ + + + + Select your &DVD device: + &DVD حدد جهاز أقراص الــ + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + المشغل لا يقوم بتحديد أي جهاز اقراص افتراضيا لذا قبل أن تقوم بتشغيل اي قرص قم بتحديد الأعدادات + + + + PrefGeneral + + + General + عــام + + + + &General + عــام + + + + Paths + المسارات + + + + Media settings + اعدادات الصيغ + + + + Start videos in fullscreen + بدء الفيديو بوضع ملء الشاشة + + + + Disable screensaver + تعطيل شاشة التوقف + + + + Select the mplayer executable + mplayer حدد الملف التنفيذي لــ + + + + Executables + ملفات تنفيذية + + + + All files + كـــل الملفـــات + + + + Select a directory + حــدد مسار + + + + MPlayer executable + MPlayer ملف تنفيذي + + + + Screenshots folder + مجلد الصور الملتقطة + + + + Video output driver + مشغل مخرج الفيديو + + + + Audio output driver + مشغل مخارج الصوت + + + + Select the audio output driver. + حدد مشغل مخارج الصوت + + + + Remember settings + قم بتذكر الأعدادات + + + + Preferred audio language + لغة الصوت المرغوبة + + + + Preferred subtitle language + لغة الترجمة المرغوبة + + + + Software video equalizer + موازن الفيديو + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + + + + If this option is checked, all videos will start to play in fullscreen mode. + في حال تأشير هذا الخيار كل ملفات الفيديو سيتم تشغيلها بوضع ملء الشاشة + + + + Software volume control + اداة التحكم بدرجة الصوت + + + + Check this option to use the software mixer, instead of using the sound card mixer. + حدد هذا الخيار في حال استخدامك لبرنامج خلط للصوت بدلا من استخدام خالط صوت كرت الصوت + + + + Postprocessing quality + جودة دقة المعالجة + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + تغيير سرعة المعالجة اعتمادا ً على اوقات سرعة المعالج المتوفرة + + + + Change volume + تغيير الصوت + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + في حال تأشير هذا الخيار سيتم تذكر درجة الصوت في كل ملف مشغل + + + + 0 + 0 + + + + &Change volume on every file + تغيير الصوت لكل ملف + + + + Select the &MPlayer executable: + MPlayer حدد الملف التنفيذي لمشغل + + + + &Folder for storing screenshots: + ملف حفظ الصور الملتقطة + + + + &Audio: + الصوت + + + + &Remember settings for all files (audio track, subtitles...) + تذكر الأعدادات لكل الملفات /مسارات الصوت -الترجمات-مقاطع الفيديو .....الخ + + + + Su&btitles: + الترجمــات + + + + &Quality: + الجــودة + + + + Start videos in &fullscreen + بدء الفيديو في وضع ملء الشاشة + + + + Disable &screensaver + تعطيل شاشة التوقف + + + + &Default volume: + درجة الصوت الافتراضية + + + + Use s&oftware volume control + استخدام درجة الصوت الرئيسة + + + + Ma&x. Amplification: + حد التكبير الأعلى + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS pass-through S/PDIF + + + + Direct rendering + معالجة مباشرة + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + في حال تأشير الخيار سيتم تشغيل المعالجة المباشرة /لا تدعم جميع انواع الكوديكو مخارج الفيديو + + + + Double buffering + اكتشاف مضاعف + + + + D&irect rendering + معالجة مباشرة + + + + Dou&ble buffering + معالجة مضاعفة + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + المعالجة المضاعفة هي حفظ اكثر من ثانيتين للأمام من الفيديو في الذاكرة لكي و اظهارها بعد تحليل غيرها لضمان صورة ادق بدون أي توقف بسبب سوء المعالجة + + + + &Enable postprocessing by default + تمكين المعالجة الأفتراضية + + + + Volume &normalization by default + موازنة الفيديو أفتراضيا ً + + + + Close when finished + الأغلاق عند الأنتهاء + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + المشغل سيتهي نفسه تلقائيا بعد انتها التشغيل من الملف الحالي او قائمة التشغيل + + + + 2 (Stereo) + مخرجان ستيريو + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + القنوات افتراضيا + + + + &Pause when minimized + ايقاف مؤقت عند التصغير + + + + Pause when minimized + ايقاف مؤقت عند التصغير + + + + Enable postprocessing by default + تمكين الأفتراضيات + + + + Max. Amplification + حد التكبير الأقصى + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Volume normalization by default + موازنة الفيديو افتراضيا + + + + Maximizes the volume without distorting the sound. + رفع درجة الصوت بدون التأثير على جودته + + + + Default volume + الصةت الأفتراضي + + + + Sets the initial volume that new files will use. + تعيين درجة الصوت التي سيستخدمها المشغل للملفات عامة + + + + Channels by default + القنوات افتراضيا + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + Uses hardware AC3 passthrough + AC3 استخدام معالج الهاردوير + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + Postprocessing will be used by default on new opened files. + المعالجة ستستخدم افتراضيا عند فتح الملفات + + + + Audio track + مسار الصوت + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + تحديد افتراضيات مسار الصوت الذي سيستخدم عند تشغيل ملفات جديدة ,في حال لم يوجد الملف سيتم استخدام اول ملف <br><b>ملاحظة:</b> the <i>"لغة الصوت المرغوبة"</i> لديها اعدادات على هذا الخيار + + + + Subtitle track + مسار الترجمــة + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + لتعيين مسار الترجمة الافتراضي الذي سيستخدم عند تشغيل ملفات جديدة ,في حال لم يتم ايجاد المسار سيتم تشغيل اول مسار سيستخدم + + + + Or choose a track number: + او استخدام رقم مسار + + + + Audi&o: + الصـوت + + + + Preferred language: + اللغــة المرغــوبة + + + + Preferre&d audio and subtitles + الترجمة و الصــوت المرغوبان + + + + &Subtitle: + الترجمــة + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Here it goes an explanation text>(new line)For translators: don't translate this text, it will be replaced with another one at runtime. + + + + High speed &playback without altering pitch + اعادة تشغيل عالية السرعة بدون تعديل اي درجة + + + + High speed playback without altering pitch + اعادة تشغيل عالية السرعة بدون تعديل اي درجة + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + MPlayer dev-SVN-r24924. تمكين التعديل بسرعة التشغيل يتطلب وجود على الأقل + + + + Change volume just before playing + تغيير درجة الصوت قبل التشغيل + + + + &Video + فيديو + + + + Use s&oftware video equalizer + استخدام معالج الفيديو من كرت الشاشة + + + + A&udio + الصوت + + + + Volume + الدرجة + + + + Video + الفيديو + + + + Audio + الصوت + + + + Preferred audio and subtitles + الصوت و الترجمة المرغوبان + + + + None + بلا + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif قياسي + + + + Yadif (double framerate) + Yadif شريحة مضاعفة + + + + Linear Blend + مزيج خطي + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Dei&nterlace by default + + + + Deinterlace by default + Dei&nterlace by default + + + + Select the deinterlace filter that you want to be used for new videos opened. + Select the deinterlace filter that you want to be used for new videos opened. + + + + Remember time position + تذكر موقع الوقت + + + + Remember &time position + تذكر موقع الوقت المشغل + + + + Change volume just before p&laying + تغيير درجة الصوت قبل التشغيل + + + + Enable the audio equalizer + تمكين موازن الصوت + + + + Check this option if you want to use the audio equalizer. + تمكين هذا الخيار اذا اردت ان تستخدم موازن الصوت + + + + &Enable the audio equalizer + تمكين موازن الصوت + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + لوحة المفاتيح و المؤشر + + + + &Keyboard + لوحة المفاتيح + + + + icon + + + + + &Mouse + المؤشر + + + + Button functions: + اعدادات الازرار + + + + Media seeking + تمرير الصيغ + + + + Volume control + درجة الصوت + + + + Zoom video + تكبير الفيديو + + + + None + بلا + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + بأمكانك من هنا تغيير اختصارات الازرار للمشغل لفعل هذا نقرة مزدوجة على الامر ثم ضغط زر الاختصار + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + بأمكانك من هنا تغيير اختصارات الازرار للمشغل لفعل هذا نقرة مزدوجة على الامر ثم ضغط زر الاختصار + + + + &Left click + النقرة اليسرى + + + + &Double click + نقرة مزدوجة + + + + &Wheel function: + اعدادات الزر الاوسط للماوس + + + + Shortcut editor + محرر الأختصارات + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + Left click + الزر الأيسر + + + + Select the action for left click on the mouse. + حدد خيار للزر الأيسر للماوس + + + + Double click + نقرة مزدوجة + + + + Select the action for double click on the mouse. + حدد خيار للنقرة المزدوجة للماوس + + + + Wheel function + اعدادات الزر الاوسط للماوس الدولاب + + + + Select the action for the mouse wheel. + حدد خيار للزر الاوسط للماوس الدولاب + + + + Play + تشغيل + + + + Pause + ايقاف مؤقت + + + + Stop + ايقاف + + + + Fullscreen + ملء الشاشة + + + + Compact + نمط مضغوط + + + + Screenshot + اخذ صورة + + + + On top + في المقدمة + + + + Mute + كتم الصوت + + + + Frame counter + عداد الشرائح + + + + Reset zoom + اعادة افتراضية التكبير + + + + Exit fullscreen + الخروج من وضع ملء الشاشة + + + + Double size + حجم مضاعف + + + + Play / Pause + تشغيل /ايقاف مؤقت + + + + Pause / Frame step + ايقاف مؤقت/ خطوة للشريحة التالية + + + + Playlist + قائمة التشغيل + + + + Preferences + أعدادات + + + + No function + لا يوجد اعداد + + + + Change speed + تغيير السرعة + + + + Normal speed + سرعة افتراضية + + + + Keyboard + لوحة المفاتيح + + + + Mouse + الماوس + + + + Middle click + نقرة الزر الاوسط للماوس + + + + Select the action for middle click on the mouse. + حدد خيار لنقرة الزر الاوسط + + + + M&iddle click + نقرة الزر الاوسط + + + + X Button &1 + X Button &1 + + + + X Button &2 + X Button &2 + + + + Go backward (short) + الذهاب للخلف /فترة قصيرة + + + + Go backward (medium) + الذهاب للخلف /متوسط + + + + Go backward (long) + الذهاب للخلف/طويل + + + + Go forward (short) + الذهاب للأمام /فترة قصيرة + + + + Go forward (medium) + الذهاب للأمام /فترة متوسطة + + + + Go forward (long) + الذهاب للأمام /فترة طويلة + + + + OSD - Next level + OSD - المرحلة التالية + + + + Show context menu + اظهار القائمة اليمنى + + + + &Right click + نقرة بالزر اليمين + + + + Increase volume + زيادة ارتفاع الصوت + + + + Decrease volume + انقاص درجة الصوت + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + الواجهـــة + + + + <Autodetect> + اكتشاف تلقائي + + + + Default + الأفتراضي + + + + &Interface + الواجهة + + + + Never + أبدا ً + + + + Whenever it's needed + عند الحاجة + + + + Only after loading a new video + فقط بعد تحميل فيديو جديد + + + + Recent files + الملفات المشغلة مؤخرا + + + + Language + اللغـــات + + + + Here you can change the language of the application. + من هنا تستطيع اختيار اللغة التي تريد + + + + &Short jump + انتقال قصير + + + + &Medium jump + انتقال متوسط + + + + &Long jump + أنتقال طويل + + + + Mouse &wheel jump + انتقال بدولاب الماوس + + + + &Use only one running instance of SMPlayer + استخدام نافذة واحدة فقط من المشغل + + + + Ma&x. items + اقصى حد لللعناصر + + + + St&yle: + السمة + + + + Ico&n set: + مجموعة الايقونات + + + + L&anguage: + اللغـــة + + + + Main window + النافذة الرئيسية + + + + Auto&resize: + تحجيم تلقائي + + + + R&emember position and size + تذكر الموقع و الحجم + + + + Default font: + الخط الأفتراضي + + + + &Change... + تغيير + + + + &Behaviour of time slider: + طريقة شريط تمرير الوقت + + + + Seek to position while dragging + تمرير للموقع حيث تم السحب + + + + Seek to position when released + تمرير للسحب حيث تم التحرير + + + + TextLabel + علامة نص + + + + &Seeking + تمرير + + + + Ins&tances + الحالات + + + + Autoresize + تحجيم تلقائي + + + + The main window can be resized automatically. Select the option you prefer. + النافذة الرئيسية لا يمكن تحجيمها تلقائيا حدد الاعداد الذي ترغب + + + + Remember position and size + تذكر الموقع و الحجم + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + في حال تأشير هذا الخيار الموقع و الحجم في النافذة الرئيسية سيتم حفظهما و استعادتهما عند تشغيلهما مرة اخرى + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + حدد عدد العناصر الأقصىالتي تود أن تظهر في قائمة الملفات المشغلة مؤخرا فس حال وضعت 0 فهذا معناه تعطيل القائمة + + + + Icon set + مجموعة الأيقونات + + + + Select the icon set you prefer for the application. + حدد مجموعة الأيقونات التي ترغب بها + + + + Style + السمة + + + + Select the style you prefer for the application. + حدد السمة التي ترغب بها للمشغل + + + + Default font + الخط الأفتراضي + + + + You can change here the application's font. + بأمكانك تغيير خط التطبيق من هنا + + + + Seeking + تمرير + + + + Short jump + انتقال قصير + + + + Select the time that should be go forward or backward when you choose the %1 action. + %1 حدد الوقت الذي يجب ان يذهب الى الامام او الخلف عند اختيار + + + + short jump + أنتقال قصير + + + + Medium jump + أنتقال متوسط + + + + medium jump + أنتقال متوسط + + + + Long jump + أنتقال طويل + + + + long jump + أنتقال طويل + + + + Mouse wheel jump + انتقال بزر دولاب الماوس + + + + Select the time that should be go forward or backward when you move the mouse wheel. + حدد الوقت الذي تريده للذهاب الى الامام او الخلف او الخلفية عند تحريك مؤشر الماوس الأوسك + + + + Behaviour of time slider + نمط شريط تمرير الوقت + + + + Select what to do when dragging the time slider. + حدد ما الذي تريد ان تسحبه الى شريط تمرير الوقت + + + + Instances + حالات النوافذ + + + + Use only one running instance of SMPlayer + استخدام نافذة تشغيل واحدة للمشغل + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + حدد الاعداد الذي تريد يستخدم كملف موجود في حالة بدء المشغل عند بدء تشغيل ملفات اخرى + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + Default GUI + Default GUI + + + + Mini GUI + Mini GUI + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + &GUI + &GUI + + + + Automatic port + منفذ تلقائي + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + Manual port + منفذ يدوي + + + + Port to listen + منفذ للاستماع + + + + &Automatic + تلقائي + + + + &Manual + يدوي + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + أعـــدادات + + + + &Performance + أعـــدادات + + + + Priority + الأولويـــة + + + + Select the priority for the MPlayer process. + حدد أولوية تشغيل البرنامج + + + + realtime + الوقت الحقيقي + + + + high + مرتفع + + + + abovenormal + فوق العادي + + + + normal + عادي + + + + belownormal + أقل من عادي + + + + idle + ضعيف + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Setting a cache may improve performance on slow media + + + + Allow frame drop + تمكين اسقاط الشرائح + + + + Synchronization + التزامن + + + + Audio/video auto synchronization + التزامن التلقائي لــ الفيديو / الصوت + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + تعيين اولوية المعالج وفقا للأولويات المعرفة الممكنة في النظام<br><b>ملاحظة:</b> استخدام اولوية الوقت الحقيقي ربما يجمد النظام. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + على الأجهزة البطيئة A/V sync تخطي عرض بعض الشرائح لمعالجة + + + + Allow hard frame drop + تمكين اسقاط الشرائح الصعبة + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + المزيد من شاشات العرض يؤدي الى تشويه الصورة + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Gradually adjusts the A/V sync based on audio delay measurements. + + + + Priorit&y: + الأولوية + + + + &Allow frame drop + تمكين اسقاط الشريحة + + + + Allow &hard frame drop (can lead to image distortion) + تمكين اسقاط الشرائح الصعبة + + + + Audio/&video auto synchronization + تزامن تلقائي لــ الفيديو /الصوت + + + + Fact&or: + العامل + + + + &Fast audio track switching + تبديل سريع لمسار الصوت + + + + Fast &seek to chapters in dvds + تمرير سريع بين الفصول في الديفدي + + + + Fast audio track switching + تبديل سريع لمسار الصوت + + + + Fast seek to chapters in dvds + تمرير سريع بين الفصول في الديفدي + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + Skip loop filter + تخطي فلتر الاعادة + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + Cache for files + معالج الملفات + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + الاعداد يحدد كم تستهلك من الذاكرة عند استخدام الذاكرة الوسيطة ملف ما + + + + Cache for streams + معالجة الجداول + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + الاعداد يحدد كم تستهلك من الذاكرة عند استخدام الذاكرة الوسيطة رابط ما + + + + Cache for DVDs + DVDs معالجة الــ + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + DVD الاعداد يحدد كم تستهلك من الذاكرة عند استخدام الذاكرة الوسيطة لتشغيل قرص + + + + &Cache + المعالج + + + + Cache for &DVDs: + DVD معالجة الــ + + + + Cache for &local files: + معالجة الملفات العامة + + + + Cache for &streams: + معالجة الملفات الدفعية + + + + Enabled + تمكين + + + + Skip (always) + تخطي /دائما + + + + Skip only on HD videos + HD تخطي فقط على فيديو من نوع + + + + Loop &filter + فلتر الأعادة + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + Possible values: + القيم المحتملة + + + + <b>Enabled</b>: the loop filter is not skipped + فلتر الأعادة غير متخطى <b>تمكين</b> + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + فلتر الأعادة سيتخطى مهما كانت أبعاد الفيديو <b>التخطي دائما</b> + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + فلتر الاعادة سيقوم بتخطي الفيديو الاعلى من %1 او اكثر <b> HDتخطي فقط فيديو من نوع</b>: + + + + Cache + المعالج + + + + Cache for audio CDs + معالج اقراص الاوديو + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + الاعداد يحدد كم تستهلك من الذاكرة عند استخدام الذاكرة الوسيطة لقرص اوديو مشغل + + + + Cache for &audio CDs: + معالج اقراص الاوديو + + + + Cache for VCDs + VCDs معلج اقراص الفيديو + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + VCD. الاعداد يحدد كم تستهلك من الذاكرة عند استخدام الذاكرة الوسيطة لــ + + + + Cache for &VCDs: + VCDs: معالج لــ + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + الترجمات + + + + Choose a ttf file + اختر خط + + + + Truetype Fonts + خطوط تروتايب + + + + &Subtitles + الترجمات + + + + Autoload + تحميل تلقائي + + + + Same name as movie + اسم الملف كأسم الفيلم + + + + All subs containing movie name + كل الترجمات تحتوي اسم الفيلم + + + + All subs in directory + كل الترجمات في المسار + + + + Position + الموقع + + + + 0 + 0 + + + + Top + الاعلى + + + + Bottom + المؤخرة + + + + Font + الخط + + + + Select the font which will be used for subtitles (and OSD): + حدد الخط الذي تريد استخدامه في الترجمات + + + + Size + الحجم + + + + No autoscale + تحجيم تلقائي + + + + Proportional to movie height + نسبي إلى إرتفاع الفيلم + + + + Proportional to movie width + نسبي إلى عرض الفيلم + + + + Proportional to movie diagonal + نسبي إلى قطر الفيلم + + + + Subtitle position + موقع الترجمة + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + الاعداد يقوم بتحديد موقع الترجمة فوق نافذة الفيديو + + + + Au&toload subtitles files (*.srt, *.sub...): + (*.srt, *.sub...): تحميل تلقائي لملفات الترجمة + + + + S&elect first available subtitle + حدد اول ترجمة متوفرة + + + + &Default subtitle encoding: + اعداد ترميز الترجمة + + + + Default &position of the subtitles on screen + الموقع الافتراضي للترجمة في الشاشة + + + + &Include subtitles on screenshots + اظهار الترجمة في الصور الملتقطة + + + + &TTF font: + &TTF خــط + + + + S&ystem font: + خـــط النظام + + + + A&utoscale: + القياس التلقائي + + + + Select first available subtitle + حدد اول ترجمة متوفرة + + + + Default subtitle encoding + ترميز الترجمة الافتراضي + + + + Include subtitles on screenshots + احتواء الترجمة في الصور الملتقطة + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + في حال تأشير هذا الخيار الترجمة ستظهر في الصور الملتقطة ,/احيانا هذا الخيار يسبب مشاكل + + + + TTF font + TTF خط تروتايب + + + + System font + خط النظام + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + OSD. من هنا بأمكانك تحديد خط النظام الذي سيستخدم في نصوص الترجمة و + + + + Autoscale + قياس تلقائي + + + + Text color + لون النص + + + + Select the color for the text of the subtitles. + حدد لون نصوص الترجمة + + + + Border color + لون الحدود + + + + Select the color for the border of the subtitles. + حدد لون من اجل حدود الترجمة + + + + Select the subtitle autoload method. + حدد طبقة ترجمة تلقائية التحميل + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + اذا لم يوجد المزيد من مسارات الترجمة المتوفرة سيتم تحديد احداها تلقائيا و اكثر الوقت يكون الاول و ايضا في حالة التطابق مع اعدادات لغة المستخدم + + + + Select the subtitle autoscaling method. + حدد طبقة الترجمة تلقائية القياس + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + + + + + Middle + vertical alignment + + + + + Top + vertical alignment + + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - مساعدة + + + + OK + حسنا + + + + Cancel + إلغــاء + + + + Apply + تطبيق + + + + Help + مساعدة + + + + SMPlayer - Preferences + SMPlayer - أعدادات + + + + QObject + + + will show this message and then will exit. + ستظهر هذه الرسالة ثم يغلق البرنامج + + + + the main window will be closed when the file/playlist finishes. + نافذة المشغل ستغلق بعد انتهاء تشغيل العناصر في قائمة التشغيل + + + + This is SMPlayer v. %1 running on %2 + This is SMPlayer v. %1 running on %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + media + media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + في حال وجود نافذة اخرى تعمل الملفات سوف تضاف الى قائمة تشغيل النوافذ و في حال عدم وجود اي نوافذ سيتم تجاهل هذا الخيار و سيتم فتح الملفات في ناذة جديدة + + + + the main window won't be closed when the file/playlist finishes. + النافذة الرئيسية لا يمكن اغلاقها عند انتهاء تشغيل الملف او قائمة التشغيل + + + + the video will be played in fullscreen mode. + سيتم تشغيل الفيديو في وضع ملْ الشاشة + + + + the video will be played in window mode. + سيتم تشغيل الفيديو في وضع النافذة + + + + Enqueue in SMPlayer + SMPlayer اضافة في + + + + opens the mini gui instead of the default one. + opens the mini gui instead of the default one. + + + + Restores the old associations and cleans up the registry. + استعادة اللواحق القديمة للتشغيل و تنظيف مدخلات التسجيل + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + Usage: + الأستخدام + + + + directory + المسار + + + + action_name + اسم-الأعداد + + + + action_list + قائمة-الاعدادات + + + + opens the default gui. + الأفتراضي gui. فتح + + + + subtitle_file + ملف-الترجمة + + + + specifies the subtitle file to be loaded for the first video. + حدد ملف الترجمة الذي سيتم تشغيله مع اول فيديو + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + + + + + label + + + + + ShortcutGetter + + + Modify shortcut + اصلاح الأختصار + + + + Clear + مسح + + + + Press the key combination you want to assign + حدد مفتاح المجموعة الذي تريد أن تخصيصه + + + + Capture + التقـــاط + + + + Capture keystrokes + ازرار الألتقـــاط + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + + + + + Select None + + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer -تمرير + + + + &Jump to: + الأنتقال إلى + + + + TristateCombo + + + Auto + تلقائي + + + + Yes + نعم + + + + No + لا + + + + VideoEqualizer + + + Contrast + المقارنة + + + + Brightness + السطوع + + + + Hue + الشكل + + + + Saturation + الإشباع + + + + Gamma + الوان غاما + + + + &Reset + الأفتراضي + + + + &Set as default values + تعيين القيم الأفتراضية + + + + Use the current values as default values for new videos. + استخدام القيم الافتراضية للفيديو الجديد + + + + Set all controls to zero. + تعيين جميع الادوات الى الصفر + + + + Video Equalizer + موازن الفيديو + + + + Information + معلومات + + + + The current values have been stored to be used as default. + القيمة الحالية تم تخزينها لأستخدامها افتراضيا + + + + VideoPreview + + + Video preview + + + + + Cancel + + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + + + + + The file couldn't be saved + + + + + Error + + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + + + + + %1 Hz + + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + درجة الصوت + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_bg.ts b/plugins/smplayer_plugin/translations/smplayer_bg.ts new file mode 100644 index 000000000..8f8649f81 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_bg.ts @@ -0,0 +1,7213 @@ + + + + About + + + Version: %1 + Версия: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Тази програма е с отворен код; вие можете да я разпространявате, променяте и допълвате под GNU лиценза. + + + + The following people have contributed with translations: + + + + + German + Немски + + + + Slovak + Словашки + + + + Italian + Италиански + + + + French + Френски + + + + %1, %2 and %3 + + + + + Simplified-Chinese + Опростен китайски + + + + Russian + Руски + + + + %1 and %2 + + + + + Hungarian + Унгарски + + + + Polish + Полски + + + + Japanese + Японски + + + + Dutch + Нидерландски + + + + Ukrainian + Украйнски + + + + Portuguese - Brazil + + + + + Georgian + Грузински + + + + Czech + Чешки + + + + Bulgarian + Български + + + + Turkish + Турски + + + + Swedish + Шведски + + + + Serbian + Сръбски + + + + Traditional Chinese + Традиционен китайски + + + + Romanian + + + + + Portuguese - Portugal + + + + + Greek + Гръцки + + + + Finnish + Фински + + + + <b>%1</b>: %2 + + + + + <b>%1</b> (%2) + + + + + About SMPlayer + Относно SMPlayer + + + + &Info + + + + + icon + + + + + &Contributions + + + + + &Translators + + + + + &License + + + + + Visit our web for updates: + + + + + Get help in our forum: + + + + + You can support SMPlayer by making a donation. + + + + + More info + + + + + Korean + + + + + Macedonian + + + + + Basque + + + + + Using MPlayer %1 + + + + + Catalan + + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + Арабски + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Име + + + + Description + Описание + + + + Shortcut + Пряк път + + + + &Save + &Запис + + + + &Load + &Зареждане + + + + Key files + Ключови файлове + + + + Choose a filename + Избор на име на файла + + + + Confirm overwrite? + Презапис? + + + + The file %1 already exists. +Do you want to overwrite? + Файлът %1 вече съществува. +Искате ли да бъде презаписан? + + + + Choose a file + Избор на файл + + + + Error + Грешка + + + + The file couldn't be saved + Файлът не може да бъде запазен + + + + The file couldn't be loaded + Файлът не може да бъде зареден + + + + &Change shortcut... + + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + &Възстановяване + + + + &Set as default values + &Задаване като стандартни + + + + Use the current values as default values for new videos. + Използване като стандартни за нови филми. + + + + Set all controls to zero. + Задаване на всичко до нула. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + &File... + &Файл... + + + + D&irectory... + &Директория... + + + + &Playlist... + &Списък за изпълнение... + + + + V&CD + V&CD + + + + &DVD from drive + &DVD от устройство + + + + D&VD from folder... + D&VD от папка... + + + + &URL... + &URL... + + + + P&lay + &Изпълнение + + + + &Pause + &Пауза + + + + &Stop + &Стоп + + + + &Frame step + &Кадър напред + + + + Play / Pause + Изпълнение / Пауза + + + + Pause / Frame step + Пауза + + + + &Repeat + &Повторение + + + + &Normal speed + &Нормална скорост + + + + &Halve speed + &Скорост наполовина + + + + &Double speed + &Двойна скорост + + + + Speed &-10% + Скорост &-10% + + + + Speed &+10% + Скорост &+10% + + + + Sp&eed + &Скорост + + + + &Fullscreen + &На цял екран + + + + &Compact mode + &Компактен режим + + + + &Equalizer + &Изравнител + + + + &Screenshot + &Снимка на екрана + + + + S&tay on top + &Положение отгоре + + + + &Postprocessing + &Postprocessing + + + + &Autodetect phase + &Автооткриване на фазата + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + Добавяне на &шум + + + + F&ilters + &Филтри + + + + &Mute + &Заглушаване + + + + Volume &- + Сила на звука &- + + + + Volume &+ + Сила на звука &+ + + + + &Delay - + &Забавяне - + + + + D&elay + + &Забавяне + + + + + &Extrastereo + &Екстрастерео + + + + &Karaoke + &Караоке + + + + &Filters + &Филтри + + + + &Load... + &Зареждане... + + + + U&nload + &Освобождаване + + + + Delay &- + Забавяне &- + + + + Delay &+ + Забавяне &+ + + + + &Up + &Нагоре + + + + &Down + &Надолу + + + + &Playlist + &Списък за изпълнение + + + + &Show frame counter + &Показване на брояча на кадри + + + + P&references + &Настройки + + + + &View logs + &Показване на дневниците + + + + About &Qt + Относно &Qt + + + + About &SMPlayer + Относно &SMplayer + + + + &Open + &Отваряне + + + + &Play + &Изпълнение + + + + &Video + &Видео + + + + &Audio + &Аудио + + + + &Subtitles + &Субтитри + + + + &Browse + &Преглед + + + + Op&tions + &Настройки + + + + &Help + &Помощ + + + + &Recent files + &Последни файлове + + + + &Clear + &Изчистване + + + + Si&ze + &Размер + + + + &Aspect ratio + &Картина + + + + &Deinterlace + &Корекция на картина + + + + 4:3 &Letterbox + 4:3 &Широкоекранен + + + + 16:9 L&etterbox + 16:9 &Широкоекранен + + + + 4:3 &Panscan + 4:3 &Пълноекранен + + + + 4:3 &to 16:9 + 4:3 &към 16:9 + + + + &None + &Няма + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Linear &Blend + + + + &Channels + &Канали + + + + &Stereo mode + &Стерео режим + + + + &Stereo + &Стерео + + + + &4.0 Surround + &4.0 Съраунд + + + + &5.1 Surround + &5.1 Съраунд + + + + &Left channel + &Ляв канал + + + + &Right channel + &Десен канал + + + + &Select + &Избор + + + + &Title + &Заглавие + + + + &Chapter + &Глава + + + + &Angle + &Наклон + + + + &OSD + &OSD + + + + &Disabled + &Забранен + + + + &Seek bar + &Лента за търсене + + + + &Time + &Време + + + + Time + T&otal time + Време + &Общо време + + + + SMPlayer - mplayer log + SMPlayer - mplayer дневник + + + + SMPlayer - smplayer log + SMPlayer - smplayer дневник + + + + <empty> + <празно> + + + + Video + Видео + + + + Audio + Аудио + + + + Playlists + Списъци за изпълнение + + + + All files + Всички файлове + + + + Choose a file + Избор на файл + + + + SMPlayer - Information + SMPlayer -Информация + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD устройствата все още не са настроени. +Тук вие можете да го направите. + + + + Choose a directory + Избор на директория + + + + Subtitles + Субтитри + + + + About Qt + Относно Qt + + + + Playing %1 + Изпълнява се %1 + + + + Pause + Пауза + + + + Stop + Стоп + + + + C&lose + &Затваряне + + + + View &info and properties... + Показване на &информация... + + + + Zoom &- + Намаляване &- + + + + Zoom &+ + Увеличаване &+ + + + + &Reset + &Възстановяване + + + + Move &left + Преместване &наляво + + + + Move &right + Преместване &надясно + + + + Move &up + Преместване &нагоре + + + + Move &down + Преместване &надолу + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Предишен ред от субтитрите + + + + N&ext line in subtitles + &Следващ ред от субтитрите + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Нам. на звука (2) + + + + Inc volume (2) + Увел на звука (2) + + + + Exit fullscreen + Изход от цял екран + + + + OSD - Next level + OSD - Следващо ниво + + + + Dec contrast + Нам на контраста + + + + Inc contrast + Увел на контраста + + + + Dec brightness + Нам на яркостта + + + + Inc brightness + Увел на яркостта + + + + Dec hue + Нам на нюанса + + + + Inc hue + Увел на нюанса + + + + Dec saturation + Нам на наситеността + + + + Dec gamma + Увел на наситеността + + + + Next audio + Следващ аудио файл + + + + Next subtitle + Следващи субтитри + + + + Next chapter + Следваща глава + + + + Previous chapter + Предишна глава + + + + Inc saturation + Увел на наситеността + + + + Inc gamma + Увел на гамата + + + + &Load external file... + + + + + &Kerndeint + + + + + &Yadif (normal) + + + + + Y&adif (double framerate) + + + + + &Next + &Следващ + + + + Pre&vious + &Предишен + + + + Volume &normalization + + + + + &Audio CD + + + + + Denoise nor&mal + + + + + Denoise &soft + + + + + Denoise o&ff + + + + + Use SSA/&ASS library + + + + + Flip i&mage + + + + + &Toggle double size + + + + + S&ize - + + + + + Si&ze + + + + + + Add &black borders + + + + + Soft&ware scaling + + + + + &FAQ + + + + + Visualize &motion vectors + + + + + &Command line options + + + + + SMPlayer command line options + + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &Файл + + + + &Track + audio + &Файл + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer все още работи + + + + S&how icon in system tray + &Показване на икона в системния панел + + + + &Hide + &Скриване + + + + &Restore + &Възстановяване + + + + &Quit + &Изход + + + + Playlist + Списък за изпълнение + + + + Core + + + Brightness: %1 + Яркост: %1 + + + + Contrast: %1 + Контраст: %1 + + + + Gamma: %1 + Гама: %1 + + + + Hue: %1 + Нюанс: %1 + + + + Saturation: %1 + Наситеност: %1 + + + + Volume: %1 + Сила на звука: %1 + + + + Zoom: %1 + Мащаб: %1 + + + + Font scale: %1 + + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Добре дошли в SMPlayer + + + + &Main toolbar + &Главна лента + + + + &Language toolbar + &Езикова лента + + + + &Toolbars + &Ленти + + + + Audio + Аудио + + + + Subtitle + Субтитри + + + + EqSlider + + + icon + икона + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + + + + + Error + Грешка + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Настройки на файла + + + + &Information + &Информация + + + + &Demuxer + &Разпределител + + + + &Select the demuxer that will be used for this file: + &Изберете разпределителят, които ще бъде използван за този файл: + + + + &Reset + &Възстановяване + + + + &Video codec + &Видео кодек + + + + &Select the video codec: + &Изберете видео кодек: + + + + A&udio codec + &Аудио кодек + + + + &Select the audio codec: + &Изберете аудио кодек: + + + + &MPlayer options + &MPlayer настройки + + + + Additional Options for MPlayer + Допълнителни настройки на MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Тук можете да добавяте допълнителни команди. +Отделете ги с интервали. +Пример: -flip -nosound + + + + &Options: + &Настройки: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Вие също можете да добавяте допълнителни видео филтри. +Отделете ги с ",". Не използвайте интервали! +Пример: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + &Видео филтри: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Вие също можете да добавяте и аудио филтри. +Правилото е същото като за видео филтрите. +Пример: resample=44100:0:0,volnorm + + + + Audio &filters: + &Аудио филтри: + + + + OK + + + + + Cancel + + + + + Apply + + + + + FindSubtitlesWindow + + + Language + Език + + + + Name + Име + + + + Format + Формат + + + + Files + + + + + Date + Дата + + + + Uploaded by + + + + + All + + + + + Close + + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Грешка + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Грешка при запис на файла + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Общи + + + + Size + Размер + + + + %1 KB (%2 MB) + %1 КБ (%2 МБ) + + + + URL + URL + + + + Length + Дължина + + + + Demuxer + Разпределител + + + + Name + Име + + + + Artist + Изпълнител + + + + Author + Автор + + + + Album + Албум + + + + Genre + Жанр + + + + Date + Дата + + + + Track + Файл + + + + Copyright + Авторско право + + + + Comment + Коментар + + + + Software + Софтуер + + + + Clip info + Информация за клипа + + + + Video + Видео + + + + Resolution + Разделителна способност + + + + Aspect ratio + Съотношение + + + + Format + Формат + + + + Bitrate + Скорост + + + + %1 kbps + %1 kbps + + + + Frames per second + Кадри в секунда + + + + Selected codec + Избран кодек + + + + Initial Audio Stream + Първоначален аудио поток + + + + Rate + Честота + + + + %1 Hz + %1 Хц + + + + Channels + Канали + + + + Audio Streams + Аудио потоци + + + + Language + Език + + + + empty + празно + + + + Subtitles + Субтитри + + + + Type + Тип + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Име на потока + + + + Stream URL + URL на потока + + + + File + + + + + InputDVDDirectory + + + Choose a directory + Избор на директория + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Изпълнение на DVD от папка + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Вие можете да изпълните dvd от вашия харддиск. Просто изберете папката, която съдържа директориите VIDEO_TS и AUDIO_TS. + + + + Choose a directory... + Избор на директория... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + + + + + &URL: + + + + + It's a &playlist + + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + Арабски + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + Български + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + Чешки + + + + Welsh + + + + + Danish + + + + + German + Немски + + + + Greek + Гръцки + + + + English + Английски + + + + Esperanto + + + + + Spanish + Испански + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + Фински + + + + Faroese + + + + + French + Френски + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + Унгарски + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + Италиански + + + + Inuktitut + + + + + Japanese + Японски + + + + Javanese + + + + + Georgian + Грузински + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + Нидерландски + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + Полски + + + + Portuguese + + + + + Quechua + + + + + Romanian + + + + + Russian + Руски + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + Словашки + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + Сръбски + + + + Sundanese + + + + + Swedish + Шведски + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Турски + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + Украйнски + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + + + + + Portuguese - Portugal + + + + + Simplified-Chinese + Опростен китайски + + + + Traditional Chinese + Традиционен китайски + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Западни европейски езици + + + + Western European Languages with Euro + Западни европейски езици с Евро + + + + Slavic/Central European Languages + Славянски/Централна Европа + + + + Esperanto, Galician, Maltese, Turkish + Есперанто, Галисийски, Малтийски, Турски + + + + Old Baltic charset + Стар Балтийски + + + + Cyrillic + Кирилица + + + + Modern Greek + Модерен гръцки + + + + Baltic + Балтийски + + + + Celtic + Келтски + + + + Hebrew charsets + Еврейски + + + + Ukrainian, Belarusian + Украйнски, Беларуски + + + + Simplified Chinese charset + Опростен Китайски + + + + Traditional Chinese charset + Традиционен Китайски + + + + Japanese charsets + Японски + + + + Korean charset + Корейски + + + + Thai charset + Тайски + + + + Cyrillic Windows + Кирилица Windows + + + + Slavic/Central European Windows + Славянски/Централна Европа Windows + + + + Arabic Windows + + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Изберете име на файла + + + + Confirm overwrite? + Презапис? + + + + The file already exists. +Do you want to overwrite? + Файлът вече съществува. +Искате ли да бъде презаписан? + + + + Error saving file + Грешка при запис на файла + + + + The log couldn't be saved + Дневникът не може да бъде запазен + + + + Logs + Дневници + + + + LogWindowBase + + + Log Window + Прозорец на дневника + + + + Save + Запис + + + + Copy to clipboard + Копиране в системния буфер + + + + Close + Затваряне + + + + &Close + &Затваряне + + + + MiniGui + + + Control bar + + + + + MpcGui + + + Control bar + + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Име + + + + Length + Дължина + + + + &Play + &Изпълнение + + + + &Edit + &Редактиране + + + + Playlists + Списъци за изпълнение + + + + Choose a file + Избор на файл + + + + Choose a filename + Избор на име на файла + + + + Confirm overwrite? + Презапис? + + + + The file %1 already exists. +Do you want to overwrite? + Файлът %1 вече съществува.Искате ли да бъде презаписан? + + + + All files + Всички файлове + + + + Select one or more files to open + Изберете един или повече файлове за отваряне + + + + Choose a directory + Избор на директория + + + + Edit name + Редактиране на име + + + + Type the name that will be displayed in the playlist for this file: + Напишете име, което ще бъде показано в списъка за изпълнение: + + + + &Load + &Зареждане + + + + &Save + &Запис + + + + &Next + &Следващ + + + + Pre&vious + &Предишен + + + + Move &up + Премести &нагоре + + + + Move &down + Премести &надолу + + + + &Repeat + &Повторение + + + + S&huffle + &Разбъркано подреждане + + + + Add &current file + Добавяне на &текущия файл + + + + Add &file(s) + Добавяне на &файл(ове) + + + + Add &directory + Добавяне на &директория + + + + Remove &selected + &Премахване на избраните + + + + Remove &all + Премахване на &всички + + + + Add... + Добавяне... + + + + Remove... + Премахване... + + + + SMPlayer - Playlist + SMPlayer - Списък за изпълнение + + + + Playlist modified + Списъкът за изпълнение е променен + + + + There are unsaved changes, do you want to save the playlist? + Има незапазени промени, искате ли да запазите списъка? + + + + Preferences + + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + + + + + Auto + + + + + &Advanced + + + + + icon + икона + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Тук можете да добавяте допълнителни команди. +Отделете ги с интервали. +Пример: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Вие също можете да добавяте допълнителни видео филтри. +Отделете ги с ",". Не използвайте интервали! +Пример: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Вие също можете да добавяте и аудио филтри. +Правилото е същото като за видео филтрите. +Пример: resample=44100:0:0,volnorm + + + + Log MPlayer output + Разрешаване на дневник за MPlayer + + + + Log SMPlayer output + Разрешаване на дневник за SMPlayer + + + + This option is mainly intended for debugging the application. + Тази опция е планирана за остраняване на грешки в програмата. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Ако отметнете тази опция може да намалите треперенето, но също и може видеото да не се показва правилно. + + + + Filter for SMPlayer logs + + + + + &Monitor aspect: + + + + + &Run MPlayer in its own window + + + + + &Options: + &Настройки: + + + + V&ideo filters: + &Видео филтри: + + + + Audio &filters: + &Аудио филтри: + + + + &Colorkey: + + + + + Log &SMPlayer output + + + + + &Filter for SMPlayer logs: + + + + + C&hange... + + + + + Logs + + + + + Log MPlayer &output + + + + + Options for MP&layer + + + + + Autosave MPlayer log + + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Тип + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + + + + + Select all + + + + + Check all file types in the list + + + + + Uncheck all file types in the list + + + + + List of file types + + + + + File types + + + + + Media files handled by SMPlayer: + + + + + Select All + + + + + Select None + + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + Select none + + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + Дискове + + + + icon + икона + + + + CD device + + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + + + + + DVD device + + + + + Choose your DVD device. It will be used to play DVDs. + + + + + Select your &CD device: + + + + + Select your &DVD device: + + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + Общи + + + + &General + + + + + Paths + Пътища + + + + Media settings + Настройки + + + + Preferred audio and subtitles + Предпочитани аудио и субтитри + + + + Video + Видео + + + + Start videos in fullscreen + Стартиране на филмите на цял екран + + + + Disable screensaver + Изключване на скрийнсейвър + + + + Audio + Аудио + + + + Select the mplayer executable + Избор на mplayer изпълним файл + + + + Executables + Изпълними файлове + + + + All files + Всички файлове + + + + Select a directory + Избор на директория + + + + MPlayer executable + + + + + Screenshots folder + + + + + Video output driver + + + + + Audio output driver + + + + + Select the audio output driver. + Избор на аудио драйвер. + + + + Remember settings + + + + + Preferred audio language + + + + + Preferred subtitle language + + + + + Software video equalizer + + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Можете да разрешите тази опция ако видео изравняването не се поддържа от вашата видеокарта или избрания видео драйвер.<br><b>Забележка:</b> тази опция може да не е съвместима с някои видео драйвери. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Ако тази опция е активна, smplayer ще пуска всички файлове на цял екран. + + + + Software volume control + + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Тази опция служи за използване на софтуерно миксиране, вместо това на звуковата карта. + + + + Postprocessing quality + + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Динамична промяна на нивото на postprocessing в зависимост от CPU-то. Номерът, който изберете, ще бъде максимална граница. + + + + Change volume + + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + 0 + 0 + + + + &Change volume on every file + + + + + Select the &MPlayer executable: + + + + + &Folder for storing screenshots: + + + + + &Audio: + + + + + &Remember settings for all files (audio track, subtitles...) + + + + + Su&btitles: + + + + + &Quality: + + + + + Start videos in &fullscreen + + + + + Disable &screensaver + + + + + &Default volume: + + + + + Use s&oftware volume control + + + + + Ma&x. Amplification: + + + + + &AC3/DTS pass-through S/PDIF + + + + + Direct rendering + + + + + Double buffering + + + + + D&irect rendering + + + + + Dou&ble buffering + + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + &Enable postprocessing by default + + + + + Volume &normalization by default + + + + + Close when finished + + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + + + + + 4 (4.0 Surround) + + + + + 6 (5.1 Surround) + + + + + C&hannels by default: + + + + + &Pause when minimized + + + + + Pause when minimized + + + + + Enable postprocessing by default + + + + + Max. Amplification + + + + + AC3/DTS pass-through S/PDIF + + + + + Volume normalization by default + + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + + + + + Audi&o: + + + + + Preferred language: + + + + + Preferre&d audio and subtitles + + + + + &Subtitle: + + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + &Видео + + + + Use s&oftware video equalizer + + + + + A&udio + + + + + Volume + Сила на звука + + + + None + + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + + + + + &Keyboard + + + + + icon + икона + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Тук може да променяте клавишите на клавиатурата. За да го направите кликнете двойно и натиснете бутон. Също можете да запазите този списък и да го споделяте с познати. + + + + &Mouse + + + + + Button functions: + Функции на бутоните: + + + + Media seeking + Търсене на медия + + + + Volume control + Контрол на звука + + + + Zoom video + + + + + None + Няма + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + + + + + &Double click + + + + + &Wheel function: + + + + + Shortcut editor + + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + + + + + Select the action for left click on the mouse. + + + + + Double click + + + + + Select the action for double click on the mouse. + + + + + Wheel function + + + + + Select the action for the mouse wheel. + + + + + Play + + + + + Pause + Пауза + + + + Stop + Стоп + + + + Fullscreen + + + + + Compact + + + + + Screenshot + + + + + Mute + + + + + Frame counter + + + + + Reset zoom + + + + + Exit fullscreen + Изход от цял екран + + + + Double size + + + + + Play / Pause + Изпълнение / Пауза + + + + Pause / Frame step + Пауза + + + + Playlist + Списък за изпълнение + + + + Preferences + + + + + No function + + + + + Change speed + + + + + Normal speed + + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - Следващо ниво + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Интерфейс + + + + <Autodetect> + <Автооткриване> + + + + Default + Стандартни + + + + &Interface + + + + + Seeking + Търсене + + + + Never + Никога + + + + Whenever it's needed + Винаги когато е необходимо + + + + Only after loading a new video + Само след зареждането на ново видео + + + + Recent files + Последни файлове + + + + Language + Език + + + + Here you can change the language of the application. + + + + + &Short jump + + + + + &Medium jump + + + + + &Long jump + + + + + Mouse &wheel jump + + + + + &Use only one running instance of SMPlayer + + + + + Ma&x. items + + + + + St&yle: + + + + + Ico&n set: + + + + + L&anguage: + + + + + Main window + + + + + Auto&resize: + + + + + R&emember position and size + + + + + Default font: + + + + + &Change... + + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + + + + + &Seeking + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Производителност + + + + &Performance + + + + + Priority + Приоритет + + + + Select the priority for the MPlayer process. + Изберете приоритета за MPlayer. + + + + realtime + реално време + + + + high + високо + + + + abovenormal + наднормалното + + + + normal + нормално + + + + belownormal + поднормалното + + + + idle + без + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Задаването на кеш може да подобри производителността при бавни файлове + + + + Allow frame drop + Разрешаване на frame drop + + + + Synchronization + Синхронизация + + + + Audio/video auto synchronization + Автоматично Аудио/Видео синхронизиране + + + + Fast audio track switching + Бързо автоматично превключване на песни + + + + Fast seek to chapters in dvds + Бързо търсене на отделните глави в DVD-та + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Задаване на приоритета на mplayer според тези налични в Windows.<br><b>ВНИМАНИЕ:</b> Използването на реално време може да причини забив на системата. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Прескачане показването на някои кадри, за да се поддържа A/V синхронизирането на слаби машини. + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Интензивен frame drop. Води до изкривяване на картината! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Постепенно нагласява A/V синхронизирането базирано на измерванията на аудио забавянето. + + + + Priorit&y: + + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + + + + + Fact&or: + + + + + &Fast audio track switching + + + + + Fast &seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + + + + + Cache for &DVDs: + + + + + Cache for &local files: + + + + + Cache for &streams: + + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Списък за изпълнение + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Субтитри + + + + Choose a ttf file + Избор на ttf файл + + + + Truetype Fonts + Truetype шрифтове + + + + &Subtitles + &Субтитри + + + + Autoload + Автозареждане + + + + Select first available subtitle + Избор на първите налични субтитри + + + + Same name as movie + Същото име като филма + + + + All subs containing movie name + Всички субтитри, съдържащи името на филма + + + + All subs in directory + Всички субтитри в директорията + + + + Position + Позиция + + + + 0 + 0 + + + + Top + Отгоре + + + + Bottom + Отдолу + + + + Include subtitles on screenshots + Включи субтитрите в снимките на екрана + + + + Font + Шрифт + + + + Select the font which will be used for subtitles (and OSD): + Избор на шрифта, който ще бъде използван за субтитри (и OSD): + + + + Size + Размер + + + + No autoscale + Без Автомащабиране + + + + Proportional to movie height + Пропорционално на височината на филма + + + + Proportional to movie width + Пропорционално на ширината на филма + + + + Proportional to movie diagonal + Пропорционално на диагонала на филма + + + + Subtitle position + + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Тази настройка определя позицията на субтитрите върху видео прозореца.<i>100</i>означава отдолу, докато <i>0</i> означава отгоре. + + + + Au&toload subtitles files (*.srt, *.sub...): + + + + + S&elect first available subtitle + + + + + &Default subtitle encoding: + + + + + Default &position of the subtitles on screen + + + + + &Include subtitles on screenshots + + + + + &TTF font: + + + + + S&ystem font: + + + + + A&utoscale: + + + + + Default subtitle encoding + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + + + + + Middle + vertical alignment + + + + + Top + vertical alignment + + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + + + + + OK + + + + + Cancel + + + + + Apply + + + + + Help + + + + + SMPlayer - Preferences + SMPlayer - Настройки + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + + the main window won't be closed when the file/playlist finishes. + + + + + the video will be played in fullscreen mode. + + + + + the video will be played in window mode. + + + + + Enqueue in SMPlayer + + + + + opens the mini gui instead of the default one. + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + Usage: + + + + + directory + + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + %1 minute(s) + + + + + + + %1 and %2 + + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + икона + + + + label + надпис + + + + ShortcutGetter + + + Modify shortcut + + + + + Clear + + + + + Press the key combination you want to assign + + + + + Capture + + + + + Capture keystrokes + + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + + + + + Select None + + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + + + + + Yes + + + + + No + + + + + VideoEqualizer + + + Contrast + Контраст + + + + Brightness + Яркост + + + + Hue + Нюанс + + + + Saturation + Наситеност + + + + Gamma + Гама + + + + &Reset + &Възстановяване + + + + &Set as default values + &Задаване като стандартни + + + + Use the current values as default values for new videos. + Използване като стандартни за нови филми. + + + + Set all controls to zero. + Задаване на всичко до нула. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Грешка при запис на файла + + + + The file couldn't be saved + Файлът не може да бъде запазен + + + + Error + Грешка + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Хц + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Сила на звука + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_ca.ts b/plugins/smplayer_plugin/translations/smplayer_ca.ts new file mode 100644 index 000000000..20ce38cf7 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_ca.ts @@ -0,0 +1,7239 @@ + + + + About + + + Version: %1 + Versió: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Això és programari lliure; podeu redistribuir-lo i/o modificar-lo segons els termes de la llicència GNU - General Public License publicada per la Free Software Foundation; ja sigui la versió 2 de la llicència o ,segons us sembli, qualsevol versió posterior. + + + + The following people have contributed with translations: + Han col·laborat amb les traduccions: + + + + German + Alemany + + + + Slovak + Eslovac + + + + Italian + Italià + + + + French + Francès + + + + %1, %2 and %3 + %1, %2 i %3 + + + + Simplified-Chinese + Xinès simplificat + + + + Russian + Rus + + + + %1 and %2 + %1 i %2 + + + + Hungarian + Hongarès + + + + Polish + Polonès + + + + Japanese + Japonès + + + + Dutch + Holandès + + + + Ukrainian + Ucranià + + + + Portuguese - Brazil + Portuguès - Brasil + + + + Georgian + Georgià + + + + Czech + Txec + + + + Bulgarian + Búlgar + + + + Turkish + Turc + + + + Swedish + Suec + + + + Serbian + Serbi + + + + Traditional Chinese + Xinès tradicional + + + + Romanian + Romanès + + + + Portuguese - Portugal + Portuguès - Portugal + + + + Greek + Grec + + + + Finnish + Finès + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Quant a SMPlayer + + + + &Info + &Informació + + + + icon + icona + + + + &Contributions + &Contribucions + + + + &Translators + &Traductors + + + + &License + &Llicència + + + + Visit our web for updates: + Trobareu actualitzacions a la web: + + + + Get help in our forum: + Si necessiteu ajuda acudiu als fòrums: + + + + You can support SMPlayer by making a donation. + Podeu donar suport a SMPlayer fent una donació. + + + + More info + Més informació + + + + Korean + Coreà + + + + Macedonian + Macedoni + + + + Basque + Basc + + + + Using MPlayer %1 + S'està usant MPlayer %1 + + + + Catalan + Català + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + Àrab + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Nom + + + + Description + Descripció + + + + Shortcut + Drecera + + + + &Save + &Desa + + + + &Load + &Carrega + + + + Key files + Fitxers clau + + + + Choose a filename + Escolliu un nom de fitxer + + + + Confirm overwrite? + Voleu sobreescriure'l? + + + + The file %1 already exists. +Do you want to overwrite? + El fitxer %1 ja existeix. +El voleu sobreescriure? + + + + Choose a file + Escolliu un fitxer + + + + Error + Error + + + + The file couldn't be saved + No s'ha pogut desar el fitxer + + + + The file couldn't be loaded + No s'ha pogut carregar el fitxer + + + + &Change shortcut... + &Canvia la drecera... + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + &Reinicia + + + + &Set as default values + E&stableix com a valors per defecte + + + + Use the current values as default values for new videos. + Usa els valors actuals pels vídeos nous. + + + + Set all controls to zero. + Estableix tots els controls a zero. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - registre de mplayer + + + + SMPlayer - smplayer log + SMPlayer - registre de smplayer + + + + &Open + &Obre + + + + &Play + &Reprodueix + + + + &Video + &Vídeo + + + + &Audio + À&udio + + + + &Subtitles + &Subtítols + + + + &Browse + &Navega + + + + Op&tions + O&pcions + + + + &Help + &Ajuda + + + + &File... + &Fitxer... + + + + D&irectory... + D&irectori... + + + + &Playlist... + &Llista de reproducció... + + + + &DVD from drive + &DVD des de fitxer + + + + D&VD from folder... + D&VD des de directori... + + + + &URL... + &URL... + + + + &Clear + &Esborrar + + + + &Recent files + Fitxers &recents + + + + P&lay + Repro&dueix + + + + &Pause + &Pausa + + + + &Stop + &Atura + + + + &Frame step + Pas de &fotograma + + + + &Normal speed + Velocitat &normal + + + + &Halve speed + Velocitat &Halve + + + + &Double speed + Velocitat &doble + + + + Speed &-10% + Velocitat &-10% + + + + Speed &+10% + Velocitat &+10% + + + + Sp&eed + V&elocitat + + + + &Repeat + &Repeteix + + + + &Fullscreen + Panta&lla completa + + + + &Compact mode + Mode &compacte + + + + Si&ze + &Mida + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &to 16:9 + + + + &Aspect ratio + Relació d'&aspecte + + + + &None + &Cap + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + &Barreja lineal + + + + &Deinterlace + &Deinterlace + + + + &Postprocessing + &Postprocessat + + + + &Autodetect phase + Fase de detecció &automàtica + + + + &Deblock + &Desbloqueja + + + + De&ring + De&ring + + + + Add n&oise + Afegeix s&oroll + + + + F&ilters + F&iltres + + + + &Equalizer + &Equalitzador + + + + &Screenshot + C&aptura de pantalla + + + + S&tay on top + &Sempre visible + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtres + + + + &Stereo + &Estèreo + + + + &4.0 Surround + Surround &4.0 + + + + &5.1 Surround + Surround &5.1 + + + + &Channels + &Canals + + + + &Left channel + Canal &esquera + + + + &Right channel + Canal &dret + + + + &Stereo mode + Mode e&stèreo + + + + &Mute + &Mut + + + + Volume &- + Volum &- + + + + Volume &+ + Volum &+ + + + + &Delay - + Retar&d - + + + + D&elay + + R&ertard + + + + + &Select + &Selecciona + + + + &Load... + &Carrega... + + + + Delay &- + Retard &- + + + + Delay &+ + Retard &+ + + + + &Up + A&munt + + + + &Down + A&vall + + + + &Title + &Títol + + + + &Chapter + &Capítol + + + + &Angle + &Angle + + + + &Playlist + Llista de re&producció + + + + &Show frame counter + Mo&stra el contador de fotogrames + + + + &Disabled + &Desactivat + + + + &Seek bar + Barra de &cerca + + + + &Time + &Temps + + + + Time + T&otal time + Temps + temps t&otal + + + + &OSD + &OSD + + + + &View logs + Mostra els r&egistres + + + + P&references + P&referències + + + + About &Qt + Quant a &Qt + + + + About &SMPlayer + Quant a &SMPlayer + + + + <empty> + <buit> + + + + Video + Vídeo + + + + Audio + Àudio + + + + Playlists + Llistes de reproducció + + + + All files + Tots els fitxers + + + + Choose a file + Escolliu un fitxer + + + + SMPlayer - Information + SMPlayer - Informació + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Encara no s'han configurat les unitats de CDROM / DVD. +Ara us apareixerà el diàleg de configuració i podreu fer-ho. + + + + Choose a directory + Escolliu un directori + + + + Subtitles + Subtítols + + + + About Qt + Quant a Qt + + + + Playing %1 + Reproduint %1 + + + + Pause + Pausa + + + + Stop + Atura + + + + Play / Pause + Reprodueix / Pausa + + + + Pause / Frame step + Pausa / Pas de fotograma + + + + U&nload + Ta&nca + + + + V&CD + V&CD + + + + C&lose + &Tanca + + + + View &info and properties... + Mostra &informació i propietats... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Reinicia + + + + Move &left + Mou a l'&esquerra + + + + Move &right + Mou a la &dreta + + + + Move &up + Mou &amunt + + + + Move &down + Mou a&vall + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Línia anterior de subtítols + + + + N&ext line in subtitles + Pròxima línia d&els subtítols + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Dec volum (2) + + + + Inc volume (2) + Inc volum (2) + + + + Exit fullscreen + Surt de pantalla completa + + + + OSD - Next level + OSD - Nivell següent + + + + Dec contrast + Dec contrast + + + + Inc contrast + Inc contrast + + + + Dec brightness + Dec brillantor + + + + Inc brightness + Inc brillantor + + + + Dec hue + Dec hue + + + + Inc hue + Inc hue + + + + Dec saturation + Dec saturació + + + + Dec gamma + Dec gamma + + + + Next audio + Següent àudio + + + + Next subtitle + Següent subtítol + + + + Next chapter + Següent capítol + + + + Previous chapter + Capítol anterior + + + + Inc saturation + Inc saturació + + + + Inc gamma + Inc gamma + + + + &Load external file... + &Carrega un fitxer extern... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normal) + + + + Y&adif (double framerate) + Y&adif (doble taxa de refresc de fotogrames) + + + + &Next + &Següent + + + + Pre&vious + &Anterior + + + + Volume &normalization + &Normalització del volum + + + + &Audio CD + CD d'&àudio + + + + Denoise nor&mal + Atenuació de so nor&mal + + + + Denoise &soft + Atenuació de so &suau + + + + Denoise o&ff + A&tenuació de so desactivada + + + + Use SSA/&ASS library + Usa la llibreria SSA/&ASS + + + + Flip i&mage + Rota la i&matge + + + + &Toggle double size + &Commuta a mida doble + + + + S&ize - + M&ida - + + + + Si&ze + + Mi&da + + + + + Add &black borders + Afegeix &vores negres + + + + Soft&ware scaling + &Escalat per programari + + + + &FAQ + &PMF + + + + Visualize &motion vectors + Mostra els &vectors de moviment + + + + &Command line options + &Opcions de la línia d'ordres + + + + SMPlayer command line options + Opcions de la línia d'ordres de SMPlayer + + + + Enable &closed caption + &Habilita el títol tancat + + + + &Forced subtitles only + Només els subtítols &forçosos + + + + Reset video equalizer + Reinicia els equalitzadors de vídeo + + + + MPlayer has finished unexpectedly. + MPlayer ha acabat inesperadament. + + + + Exit code: %1 + Codi de sortida: %1 + + + + MPlayer failed to start. + La inicialització de MPlayer ha fallat. + + + + Please check the MPlayer path in preferences. + Si us plau, comproveu el camí de MPlayer a preferències. + + + + MPlayer has crashed. + MPlayer ha fallat. + + + + See the log for more info. + Mireu al registre per més informació. + + + + &Rotate + Gi&ra + + + + &Off + &Inactiu + + + + &Rotate by 90 degrees clockwise and flip + &Gira 90 graus en sentit horari i inverteix + + + + Rotate by 90 degrees &clockwise + Gira 90 graus en sentit &horari + + + + Rotate by 90 degrees counterclock&wise + Gira 90 graus en sentit &antihorari + + + + Rotate by 90 degrees counterclockwise and &flip + Gira 90 graus en sentit antihorari i i&nverteix + + + + &Jump to... + &Salta a... + + + + Show context menu + Mostra el menú contextual + + + + Multimedia + Multimèdia + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + Pis&ta + + + + &Track + audio + Pis&ta + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + Encara s'està executant l'SMPlayer + + + + S&how icon in system tray + &Mostra la icona a la safata del sistema + + + + &Hide + &Amaga + + + + &Restore + &Restaura + + + + &Quit + &Surt + + + + Playlist + Llista de reproducció + + + + Core + + + Brightness: %1 + Brillantor: %1 + + + + Contrast: %1 + Contrast: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Hue: %1 + + + + Saturation: %1 + Saturació: %1 + + + + Volume: %1 + Volum: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + Mida de lletra: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Benvingut a SMPlayer + + + + Audio + Àudio + + + + Subtitle + Subtítol + + + + &Main toolbar + Barra d'eines &principal + + + + &Language toolbar + Barra d'eines d'&idioma + + + + &Toolbars + &Barres d'eines + + + + EqSlider + + + icon + icona + + + + ErrorDialog + + + Hide log + Amaga el registre + + + + Show log + Mostra el registre + + + + MPlayer Error + Error de MPlayer + + + + icon + icona + + + + Error + Error + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Propietats de fitxer + + + + &Information + &Informació + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Selecciona el demuxer que s'usarà per aquest fitxer: + + + + &Reset + &Reinicia + + + + &Video codec + Còdec de &vídeo + + + + &Select the video codec: + &Seleccioneu el còdec de vídeo: + + + + A&udio codec + Còdec d'à&udio + + + + &Select the audio codec: + &Seleccioneu el còdec d'àudio: + + + + &MPlayer options + Opcions de &MPlayer + + + + Additional Options for MPlayer + Opcions addicionals de MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aquí podeu passar opcions extra a MPlayer. +Escriviu-les separades per espais. +Exemple: -flip -nposound + + + + &Options: + &Opcions: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + També podeu passar filtres de vídeo addicionals. +Separeu-les amb ",". No useu espais! +Exemple: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + Filtres de &vídeo: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + I finalment filtres d'àudio. Apliqueu les mateixes regles que pels filtres de vídeo. +Exemple: resample=44100:0:0,volnorm + + + + Audio &filters: + &Filtres d'àudio: + + + + OK + D'acord + + + + Cancel + Cancel·la + + + + Apply + Aplica + + + + FindSubtitlesWindow + + + Language + Idioma + + + + Name + Nom + + + + Format + Format + + + + Files + + + + + Date + Data + + + + Uploaded by + + + + + All + + + + + Close + Tanca + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Error + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + S'ha produït un error en desar el fitxer + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + General + + + + Size + Mida + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Duració + + + + Demuxer + Demuxer + + + + Name + Nom + + + + Artist + Artista + + + + Author + Autor + + + + Album + Àlbum + + + + Genre + Gènere + + + + Date + Data + + + + Track + Pista + + + + Copyright + Copyright + + + + Comment + Comment + + + + Software + Programari + + + + Clip info + Informació del clip + + + + Video + Vídeo + + + + Resolution + Resolució + + + + Aspect ratio + Relació d'aspecte + + + + Format + Format + + + + Bitrate + Taxa de bits + + + + %1 kbps + %1 kbps + + + + Frames per second + Fotogrames per segon + + + + Selected codec + Còdec seleccionat + + + + Initial Audio Stream + Flux de dades d'àudio inicial + + + + Rate + Velocitat + + + + %1 Hz + %1 Hz + + + + Channels + Canals + + + + Audio Streams + Flux de dades d'àudio + + + + Language + Idioma + + + + empty + buit + + + + Subtitles + Subtítols + + + + Type + Tipus + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Títol de flux de dades + + + + Stream URL + Flux de dades de URL + + + + File + Fitxer + + + + InputDVDDirectory + + + Choose a directory + Escolliu un directori + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Reproduir un DVD des d'un fitxer + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Podeu reproduir un dvd des del disc dur. Seleccioneu la carpeta que conté els directoris VIDEO_TS i AUDIO_TS. + + + + Choose a directory... + Escolliu un directori... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Introduïu la versió de MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + l'SMPlayer no ha pogut identificar la versió de MPlayer que esteu usant. + + + + Version reported by MPlayer: + Versió indicada per MPlayer: + + + + Please, &select the correct version: + Si us plau, &seleccioneu la versió correcta: + + + + 1.0rc1 or older + 1.0rc1 o anteriors + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Més recent que 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Introduïu la URL + + + + &URL: + &URL: + + + + It's a &playlist + És una &llista de reproducció + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Si aquesta opció està activada, es tractarà la URL com una llista de reproducció: s'obrirà com a text i es reproduiran les URL que conté. + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + Àrab + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + Búlgar + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + Català + + + + Corsican + + + + + Czech + Txec + + + + Welsh + + + + + Danish + + + + + German + Alemany + + + + Greek + Grec + + + + English + Anglès + + + + Esperanto + + + + + Spanish + Espanyol + + + + Estonian + + + + + Basque + Basc + + + + Persian + + + + + Finnish + Finès + + + + Faroese + + + + + French + Francès + + + + Frisian + + + + + Irish + + + + + Galician + Gallec + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + Hongarès + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + Italià + + + + Inuktitut + + + + + Japanese + Japonès + + + + Javanese + + + + + Georgian + Georgià + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + Coreà + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + Macedoni + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + Holandès + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + Polonès + + + + Portuguese + + + + + Quechua + + + + + Romanian + Romanès + + + + Russian + Rus + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + Eslovac + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + Serbi + + + + Sundanese + + + + + Swedish + Suec + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Turc + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + Ucranià + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + Portuguès - Brasil + + + + Portuguese - Portugal + Portuguès - Portugal + + + + Simplified-Chinese + Xinès simplificat + + + + Traditional Chinese + Xinès tradicional + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Llengües de l'oest d'Europa + + + + Western European Languages with Euro + Llengües de l'oest d'Europa amb l'Euro + + + + Slavic/Central European Languages + Llengües eslaves/de l'Europa central + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Gallec, Maltès, Turc + + + + Old Baltic charset + Codi de caràcters de l'antic Bàltic + + + + Cyrillic + Ciril·lic + + + + Modern Greek + Grec modern + + + + Baltic + Bàltic + + + + Celtic + Celta + + + + Hebrew charsets + Codi de caràcters Hebreu + + + + Ukrainian, Belarusian + Ucranià, Bielorús + + + + Simplified Chinese charset + Codi de caràcters de xinès simplificat + + + + Traditional Chinese charset + Codi de caràcters de xinès tradicional + + + + Japanese charsets + Codi de caràcters japonès + + + + Korean charset + Codi de caràcters Coreà + + + + Thai charset + Codi de caràcters Tailandès + + + + Cyrillic Windows + Finestres ciríl·liques + + + + Slavic/Central European Windows + Finestres eslaves/de l'Europa Central + + + + Arabic Windows + Finestres Aràbigues + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Escolliu el nom del fitxer a desar + + + + Confirm overwrite? + Voleu sobreescriure'l? + + + + The file already exists. +Do you want to overwrite? + El fitxer ja existeix. +El voleu sobreescriure? + + + + Error saving file + S'ha produït un error en desar el fitxer + + + + The log couldn't be saved + No s'ha pogut desar el registre + + + + Logs + Registres + + + + LogWindowBase + + + Log Window + Finestra de registre + + + + Save + Desa + + + + Copy to clipboard + Copia al porta-retalls + + + + &Close + &Tanca + + + + Close + Tanca + + + + MiniGui + + + Control bar + Barra de control + + + + MpcGui + + + Control bar + Barra de control + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nom + + + + Length + Duració + + + + &Play + &Reprodueix + + + + &Edit + &Edita + + + + Playlists + Llistes de reproducció + + + + Choose a file + Escolliu un fitxer + + + + Choose a filename + Escolliu un nom de fitxer + + + + Confirm overwrite? + Voleu sobreescriure'l? + + + + The file %1 already exists. +Do you want to overwrite? + El fitxer %1 ja existeix.El voleu sobreescriure? + + + + All files + Tots els fitxers + + + + Select one or more files to open + Seleccioneu el/s fitxers a obrir + + + + Choose a directory + Escolliu un directori + + + + Edit name + Editeu el nom + + + + Type the name that will be displayed in the playlist for this file: + Escriviu el nom que es mostrarà en la llista de reproducció per aquest fitxer: + + + + &Load + &Carrega + + + + &Save + &Desa + + + + &Next + &Següent + + + + Pre&vious + An&terior + + + + Move &up + Mou &Amunt + + + + Move &down + Mou a&vall + + + + &Repeat + &Repeteix + + + + S&huffle + A&leatori + + + + Add &current file + Afegeix el fitxer a&ctual + + + + Add &file(s) + Afegeix &fitxer(s) + + + + Add &directory + Afegeix &directori + + + + Remove &selected + Esborra els &seleccionats + + + + Remove &all + Esborra'ls &tots + + + + SMPlayer - Playlist + SMPlayer - llista de reproducció + + + + Add... + Afegeix... + + + + Remove... + Esborra... + + + + Playlist modified + Llista de reproducció modificada + + + + There are unsaved changes, do you want to save the playlist? + Hi ha canvis que no s'han desat. Voleu desar la llista de reproducció? + + + + Preferences + Preferències + + + + PlaylistPreferences + + + Playlist - Preferences + Llista de reproducció - Preferències + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Activeu aquesta opció si voleu que quan afegiu un directori s'afegeixin els fitxers dels subdirectoris recursivament. Altament només s'afegiran els fitxers del directori seleccionat. + + + + &Add files in directories recursively + &Afegir fitxers en directoris recursivament + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Afegiu aquesta opció per sol·licitar alguna informació als fitxers afegits a la llista de reproducció. Això us permetrà mostrar el títol (si està disponible) i la mida dels fitxers. Altrament aquesta informació no estarà disponible a menys que el fitxer s'estigui reproduint. Compte: aquesta opció pot ser lenta, especialment si afegiu molts fitxers. + + + + Automatically get &info about files added + Prendre &informació automàticament quan s'afegeixen fitxers + + + + &Save copy of playlist on exit + &Desa una còpia de la llista de reproducció en sortir + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + Avançat + + + + Auto + Auto + + + + &Advanced + &Avançat + + + + icon + icona + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aquí podeu passar opcions extra a MPlayer. +Escriviu-les separades per espais. +Exemple: -flip -nposound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + També podeu passar filtres de vídeo addicionals. +Separeu-los amb ",". No useu espais! +Exemple: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + I finalment filtres d'àudio. Apliqueu les mateixes regles que pels filtres de vídeo. +Exemple: resample=44100:0:0,volnorm + + + + Log MPlayer output + Sortida del registre de MPlayer + + + + Log SMPlayer output + Sortida del registre de SMPlayer + + + + This option is mainly intended for debugging the application. + Aquesta opció serveix bàsicament per depurar l'aplicació. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Si s'activa aquesta opció pot ser que es redueixi el flickering, però també pot causar una visualització incorrecta del vídeo. + + + + Filter for SMPlayer logs + Filtre els registres de SMPlayer + + + + &Monitor aspect: + Aspecte del moni&tor: + + + + &Run MPlayer in its own window + &Executa MPlayer en la pròpia finestra + + + + &Options: + &Opcions: + + + + V&ideo filters: + Filtres de &vídeo: + + + + Audio &filters: + &Filtres d'àudio: + + + + &Colorkey: + Codis de colo&rs: + + + + Log &SMPlayer output + &Sortida del registre de SMPlayer + + + + &Filter for SMPlayer logs: + &Filtre els registres de SMPlayer: + + + + C&hange... + &Canvia... + + + + Logs + Registres + + + + Log MPlayer &output + S&ortida del registre de MPlayer + + + + Options for MP&layer + Opcions de MP&layer + + + + Autosave MPlayer log + Desa automàticament el registre de MPlayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Si s'activa aquesta opció, el registre de MPlayer es desarà en el fitxer especificat cada vegada que es comenci a reproduir un fitxer. És útil per aplicacions externes, de manera que puguin obtenir informació del fitxer que s'està reproduint. + + + + Autosave MPlayer log filename + Nom del fitxer al que escriu el registre automàtic de MPlayer + + + + Enter here the path and filename that will be used to save the MPlayer log. + Introduïu el camí i el nom del fitxer que s'usarà per desar el registre de MPlayer. + + + + A&utosave MPlayer log to file + Desa a&utomàticament el registre al fitxer + + + + Pass short filenames (8+3) to MPlayer + Passa noms de fitxer curts (8+3) a MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + l'MPlayer no pot obrir noms de fitxers que continguin caràcters fora del codi de pàgina local. Activant aquesta opció permetreu que SMPlayer passi a MPlayer la versió curta del nom dels fitxers, per tal que els pugui obrir. + + + + &Pass short filenames (8+3) to MPlayer + &Passa noms de fitxer curts (8+3) a MPlayer + + + + Monitor aspect + Aspecte de monitor + + + + Select the aspect ratio of your monitor. + Seleccioneu la relació d'aspecte del vostre monitor. + + + + Run MPlayer in its own window + Executa MPlayer en la seva pròpia finestra + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Si activeu aquesta opció, la finestra de vídeo de MPlayer no s'incrustarà en la finestra principal de SMPlayer, sinó que usarà la seva pròpia finestra. Noteu que MPlayer suportarà directament les ordres de teclat i del ratolí, de manera que les dreceres i els clics del ratolí no funcionaran com se suposa quan la finestra de SMPlayer està activada. + + + + Colorkey + Codis de colors + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Si veieu parts del vídeo sobre una altra finestra, podeu canviar els codis de colors per arreglar-ho. Intenteu seleccionar un color que tendeixi al negre. + + + + Options for MPlayer + Opcions de MPlayer + + + + Options + Opcions + + + + Here you can type options for MPlayer. Write them separated by spaces. + Aquí podeu escriure opcions per a MPlayer. Escriviu-les separades per espais. + + + + Video filters + Filtres de vídeo + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Aquí podeu afegir filtres per MPlayer. Escriviu-los separats per comes. No useu espais! + + + + Audio filters + Filtres d'àudio + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Aquí podeu afegir filtres d'àudio per MPlayer. Escriviu-los separats per comes. No useu espais! + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Si no es troba cap índex de fitxers en reconstrueix un, permetent la cerca. És útil en descàrregues incompletes/trencades, o fitxers mal generats. Aquesta opció només funciona si el suport final permet la cerca (per exemple. no amb stdin, pipe, etc)<br> Nota: la creació dels índex pot tardar una estona. + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Tipus + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Avís + + + + Not all files could be associated. Please check your security permissions and retry. + No s'han pogut associar tots els fitxers. Si us plau, comproveu els permisos de seguretat i torneu-ho a intentar. + + + + File Types + Tipus de fitxers + + + + Select all + Selecciona-ho tot + + + + Check all file types in the list + Comprova tots els tipus de fitxers de la llista + + + + Uncheck all file types in the list + No seleccionis els tipus de fitxers de la llista + + + + List of file types + Llista dels tipus de fitxers + + + + File types + Tipus de fitxers + + + + Media files handled by SMPlayer: + Tipus de fitxers gestionats per SMPlayer: + + + + Select All + Selecciona'ls tots + + + + Select None + No en seleccionis cap + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Comproveu les extensions de fitxers que voleu que SMPlayer gestioni. Quan feu clic a Aplica, els fitxers seleccionats s'associaran a SMPlayer. Si desfeu la selecció d'una extensió, l'associació de fitxers es restaurarà. + + + + Select none + No en seleccionis cap + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Nota:</b> (LA restauració no funciona amb Windows Vista). + + + + PrefDrives + + + Drives + Unitats + + + + icon + icones + + + + CD device + unitats de CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Seleccioneu la vostra unitat de CDROM. S'usarà per reproduir VCDs i CDs d'àudio. + + + + DVD device + unitat de DVD + + + + Choose your DVD device. It will be used to play DVDs. + Seleccioneu la vostra unitat de DVD. S'usarà per reproduir DVDs. + + + + Select your &CD device: + Seleccioneu la vostra unitat de &CD: + + + + Select your &DVD device: + Seleccioneu la vostra unitat de &DVD: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer no escull cap unitat de CDROM o DVD per defecte. Abans que pugueu reproduir un CD o un DVD heu de seleccionar les unitats que voleu utilitzar (poden ser la mateixa). + + + + PrefGeneral + + + General + General + + + + &General + &General + + + + Paths + Camins + + + + Media settings + Paràmetres dels suports + + + + Start videos in fullscreen + Comença els vídeos a pantalla completa + + + + Disable screensaver + Desactiva l'estalvi de pantalla + + + + Select the mplayer executable + Selecciona l'executable de mplayer + + + + Executables + Executables + + + + All files + Tots els fitxers + + + + Select a directory + Selecciona un directori + + + + MPlayer executable + Executable Mplayer + + + + Screenshots folder + Directori de captures de pantalla + + + + Video output driver + Controlador de vídeo de sortida + + + + Audio output driver + Controlador d'àudio de sortida + + + + Select the audio output driver. + Seleccioneu el controlador d'àudio de sortida. + + + + Remember settings + Recorda els paràmetres + + + + Preferred audio language + Idioma d'àudio preferit + + + + Preferred subtitle language + Idioma preferit pels subtítols + + + + Software video equalizer + Programari equalitzador de vídeo + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Podeu marcar aquesta opció si la vostra tarja gràfica o el controlador de vídeo seleccionats no tenen suport per l'equalitzador de vídeo.<br><b>Nota:</b> aquesta opció pot no ser compatible amb alguns controladors de sortida de vídeo. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Si activeu aquesta opció, tots els vídeos iniciaran la seva reproducció en mode de pantalla completa. + + + + Software volume control + Programari de control del volum + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Marqueu aquesta opció per usar el programari mesclador, enlloc d'usar el mesclador de la tarja de so. + + + + Postprocessing quality + Qualitat de postprocessat + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Canvia el nivell de postprocessat depenent del temps de CPU disponible. El nombre que especifiqueu serà el nivell màxim usat. Normalment podeu usar un nombre gran. + + + + Change volume + Canvia el volum + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Si ho seleccioneu, SMPlayer recordarà el volum de reproducció per cada fitxer i el restablirà quan el torneu a reproduir. Pels fitxers nous s'usarà el valor per defecte. + + + + 0 + 0 + + + + &Change volume on every file + &Canvia el volum a cada fitxer + + + + Select the &MPlayer executable: + Seleccioneu l'&MPlayer executable: + + + + &Folder for storing screenshots: + Directori &on desar les captures de pantalla: + + + + &Audio: + &Àudio: + + + + &Remember settings for all files (audio track, subtitles...) + &Recorda les preferències per tots els fitxers (pistes d'àudio, subtítols...) + + + + Su&btitles: + Su&btítols: + + + + &Quality: + &Qualitat: + + + + Start videos in &fullscreen + Comença els vídeos a pantalla &completa + + + + Disable &screensaver + Desactiva l'e&stalvi de pantalla + + + + &Default volume: + Volu&m per defecte: + + + + Use s&oftware volume control + Usa el &programari de control del volum + + + + Ma&x. Amplification: + Amplificació mà&xima: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS a través de S/PDIF + + + + Direct rendering + Renderitzat directe + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Si l'activeu, s'activarà el renderitzat directe (no suportat per tots els còdecs ni les sortides de vídeo)<br><b>AVÍS:<br>Pot produir corrupció OSD/SUB! + + + + Double buffering + Dobla la memòria intermèdia + + + + D&irect rendering + Renderitzat d&irecte + + + + Dou&ble buffering + Do&bla la memòria intermèdia + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Doblar la memòria intermèdia arregla el fliker en desar dos fotogrames en memòria, i mostrar-ne un mentre se'n descodifica un altre. Si es desactiva pot afectar OSD negativament, però habitualment elimina el flickering de OSD. + + + + &Enable postprocessing by default + &Habilita el postprocessat per defecte + + + + Volume &normalization by default + &Normalitza el volum per defecte + + + + Close when finished + Tanca en acabar + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Si s'activa aquesta opció, la finestra principal es tanca automàticament quan la llista de reproducció/fitxer actual acaben. + + + + 2 (Stereo) + 2 (Estèreo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + Canals per defect&e: + + + + &Pause when minimized + &Pausa en minimitzar + + + + Pause when minimized + Pausa en minimitzar + + + + Enable postprocessing by default + Habilita el postprocessat per defecte + + + + Max. Amplification + Amplificació màxima + + + + AC3/DTS pass-through S/PDIF + AC3/DTS a través de S/PDIF + + + + Volume normalization by default + Normalitza el volum per defecte + + + + Maximizes the volume without distorting the sound. + Maximitza el volum sense distorsionar el so. + + + + Default volume + Volum per defecte + + + + Sets the initial volume that new files will use. + Estableix el volum inicial pels fitxers nous. + + + + Channels by default + Canals per defecte + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Selecciona el nivell d'amplificació màxima per defecte (per defecte: 100). Un valor de 200 us permetrà ajustar el volum fins a un màxim del doble del volum actual. Amb valors per sota de 100 del volum inicial (que és 100%) serà per sota del màxim, que pot fer que OSD no es mostri correctament. + + + + Uses hardware AC3 passthrough + Usa maquinari AC3 passthrough + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Pregunta el nombre de canals de reproducció. MPlayer demana al descodificador que descodifiqui l'àudio en tants canals com els especificats. Llavors el descodificador decideix si pot o no satisfer el requeriment. Això normalment només és important en la reproducció de vídeos amb àudio AC3 (com DVDs). En aquest cas liba52 fa la descodificació per defecte i mescla l'àudio en el nombre de canals requerits. NOTA: Aquesta opció és facilitada pels codecs (només AC3), filtres (surround) i controladors de sortida d'àudio (OSS com a mínim). + + + + Postprocessing will be used by default on new opened files. + S'utilitzarà el postprocessat per defecte en obrir fitxers nous. + + + + Audio track + Pista d'àudio + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Especifica la pista d'àudio per defecte en reproduir fitxers nous. Si la pista no existeix s'usarà la primera.<br><b>Nota:</b> l'<i>idioma d'àudio preferit</i> té preferència sobre aquesta opció. + + + + Subtitle track + Pista de subtítol + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Especifica la pista de subtítol per defecte en reproduir fitxers nous. Si la pista no existeix s'usarà la primera.<br><b>Nota:</b> l'<i>idioma de subtítol preferit</i> té preferència sobre aquesta opció. + + + + Or choose a track number: + O escolliu un número de pista: + + + + Audi&o: + Àudi&o: + + + + Preferred language: + Idioma preferit: + + + + Preferre&d audio and subtitles + I&dioma preferit per àudio i subtítols + + + + &Subtitle: + &Subtítols: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aquí podeu escriure la vostra llengua preferida pels subtítols. Quan es trobi un suport amb multiples cadenes d'àudio o de subtítols, smplayer intentarà usar la vostra llengua preferida.<br>Això només funcionarà amb suports que ofereixen informació sobre la llengua de les pistes d'àudio i de subtítols, com DVDs o fitxers mkv.<br>Aquest camp accepta expressions regulars. Per exemple: <b>es|esp|spa</b> seleccionarà la pista de subtítols si coincideix amb <i>es</i>, <i>esp</i> o <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + Alta velocitat de reproducció sense alteració de p&itch + + + + High speed playback without altering pitch + Alta velocitat de reproducció sense alteració de pitch + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Permet canviar la velocitat de reproducció sense alterar el pitch. Requereix com a mínim MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Canvia el volum just abans de reproduir + + + + &Video + &Vídeo + + + + Use s&oftware video equalizer + Usa el &programari d'equalitzador de vídeo + + + + A&udio + À&udio + + + + Volume + Volum + + + + Video + Vídeo + + + + Audio + Àudio + + + + Preferred audio and subtitles + Idioma preferit per àudio i subtítols + + + + None + Cap + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normal) + + + + Yadif (double framerate) + Yadif (doble taxa de refresc de fotogrames) + + + + Linear Blend + Barreja lineal + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Dei&nterlace per defecte: + + + + Deinterlace by default + Deinterlace per defecte + + + + Select the deinterlace filter that you want to be used for new videos opened. + Seleccioneu el filtre de deinterlace que voleu usar pels nous vídeos que obriu. + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Teclat i ratolí + + + + &Keyboard + &Teclat + + + + icon + icona + + + + &Mouse + &Ratolí + + + + Button functions: + Funcions de botons: + + + + Media seeking + Cerca de suports + + + + Volume control + Control de volum + + + + Zoom video + Zomm del vídeo + + + + None + Cap + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aquí podeu canviar qualsevol tecla de drecera. Per fer-ho feu doble clic o premeu enter sobre una cel·la de drecera. Opcionalment també podeu desar la llista per compartir-la amb altres persones o carregar-la en un altre equip. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aquí podeu canviar qualsevol tecla de drecera. Per fer-ho feu doble clic o premeu enter sobre una cel·la de drecera. Opcionalment també podeu desar la llista per compartir-la amb altres persones o carregar-la en un altre equip. + + + + &Left click + &Clic esquerra + + + + &Double click + &Doble clic + + + + &Wheel function: + &Funció de la roda: + + + + Shortcut editor + Editor de dreceres + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Aquesta taula us permetrà canviar les tecles de drecera de la majoria d'accions disponibles. Feu doble clic o premeu enter en un element, o premeu el botó <b>Canvia drecera</b> per entrar en el diàleg <i>Modifica drecera</i>. Hi ha dues maneres de canviar una drecera: si el botó <b>Captura</b> està activat, llavors només heu de prémer la nova tecla o combinació de tecles que voleu assignar per l'acció (desafortunadament, això no funciona per totes les tecles). Si el botó <b>Captura</b> està desactivat, llavors podeu introduir el nom sencer de la tecla. + + + + Left click + Clic esquerra + + + + Select the action for left click on the mouse. + Seleccioneu l'acció quan feu clic esquerra amb el ratolí. + + + + Double click + Doble clic + + + + Select the action for double click on the mouse. + Seleccioneu l'acció quan feu doble clic amb el ratolí. + + + + Wheel function + Funció de la roda + + + + Select the action for the mouse wheel. + Seleccioneu l'acció per la roda del ratolí. + + + + Play + Reprodueix + + + + Pause + Pausa + + + + Stop + Atura + + + + Fullscreen + Pantalla completa + + + + Compact + Compacte + + + + Screenshot + Captura de pantalla + + + + On top + A sobre + + + + Mute + Mut + + + + Frame counter + Contador de fotogrames + + + + Reset zoom + Reinicia el zoom + + + + Exit fullscreen + Surt de pantalla completa + + + + Double size + Mida doble + + + + Play / Pause + Reprodueix / Pausa + + + + Pause / Frame step + Pausa / Pas de fotograma + + + + Playlist + Llista de reproducció + + + + Preferences + Preferències + + + + No function + Sense funció + + + + Change speed + Canvia la velocitat + + + + Normal speed + Velocitat normal + + + + Keyboard + Teclat + + + + Mouse + Ratolí + + + + Middle click + Clic amb el botó del mig + + + + Select the action for middle click on the mouse. + Seleccioneu l'acció quan feu clic al mig del ratolí. + + + + M&iddle click + Clic al m&ig + + + + X Button &1 + Botó X &1 + + + + X Button &2 + Botó X &2 + + + + Go backward (short) + Enrera (curt) + + + + Go backward (medium) + Enrera (mig) + + + + Go backward (long) + Enrera (llarg) + + + + Go forward (short) + Endavant (curt) + + + + Go forward (medium) + Endavant (mig) + + + + Go forward (long) + Endavant (llarg) + + + + OSD - Next level + OSD - nivell següent + + + + Show context menu + Mostra el menú contextual + + + + &Right click + Clic &dret + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Interfície + + + + <Autodetect> + <detecció automàtica> + + + + Default + Per defecte + + + + &Interface + &Interfície + + + + Never + Mai + + + + Whenever it's needed + Quan calgui + + + + Only after loading a new video + Només després de carregar un vídeo nou + + + + Recent files + Fitxers recents + + + + Language + Idioma + + + + Here you can change the language of the application. + Aquí podeu canviar la llengua de l'aplicació. + + + + &Short jump + &Salt curt + + + + &Medium jump + Salt &mitjà + + + + &Long jump + Salt &llarg + + + + Mouse &wheel jump + Salt amb la &roda del ratolí + + + + &Use only one running instance of SMPlayer + &Usa només una instància de SMPlayer + + + + Ma&x. items + Mà&x. elements + + + + St&yle: + Est&il: + + + + Ico&n set: + Estableix ico&na: + + + + L&anguage: + &Llengua: + + + + Main window + Finestra principal + + + + Auto&resize: + Canvia la mida &automàticament: + + + + R&emember position and size + R&ecorda la posició i mida + + + + Default font: + Lletra per defecte: + + + + &Change... + &Canvia... + + + + &Behaviour of time slider: + &Comportament de la barra de temps: + + + + Seek to position while dragging + Mou la posició en arrossegar + + + + Seek to position when released + Mou a la posició en deixar anar + + + + TextLabel + Etiquetatext + + + + &Seeking + &Cerca + + + + Ins&tances + Ins&tàncies + + + + Autoresize + Canvia la mida automàticament + + + + The main window can be resized automatically. Select the option you prefer. + Es pot canviar la mida de la finestra principal automàticament. Seleccioneu l'opció que preferiu. + + + + Remember position and size + Recorda la posició i la mida + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Si seleccioneu aquesta opció, la posició i la mida de la finestra principal es desaran i es recuperaran que torneu a executar SMPlayer. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Seleccioneu el nombre màxim d'elements que es mostren al submenú <b>Obre->Fitxers recents</b>. Si hi escriviu 0, el menú no es mostrarà. + + + + Icon set + Estableix icona + + + + Select the icon set you prefer for the application. + Seleccioneu la icona que voleu per l'aplicació. + + + + Style + Estil + + + + Select the style you prefer for the application. + Seleccioneu l'estil que preferiu per l'aplicació. + + + + Default font + Lletra per defecte + + + + You can change here the application's font. + Aquí podeu canviar la lletra de l'aplicació per defecte. + + + + Seeking + S'està cercant + + + + Short jump + Salt curt + + + + Select the time that should be go forward or backward when you choose the %1 action. + Seleccioneu el temps que a desplaçar endavant o enrera que seleccioneu l'acció %1. + + + + short jump + salt curt + + + + Medium jump + Salt mitjà + + + + medium jump + salt mitjà + + + + Long jump + Salt llarg + + + + long jump + salt llarg + + + + Mouse wheel jump + Salt amb la roda del ratolí + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Seleccioneu el temps a desplaçar endavant o enrera quan moveu la roda del ratolí. + + + + Behaviour of time slider + Comportament de la barra de desplaçament + + + + Select what to do when dragging the time slider. + Seleccioneu què fer en arrossegar la barra de desplaçament. + + + + Instances + Instàncies + + + + Use only one running instance of SMPlayer + Useu només una instància en execució de SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Seleccioneu aquesta opció si voleu usar una instància ja en execució de SMPlayer en obrir altres fitxers. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer ha d'estar a l'escolta d'un port per rebre ordres d'altres instàncies. Podeu canviar el port en cas que la que el que hi hagi per defecte estigui sent usat per una altra aplicació. + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Rendiment + + + + &Performance + &Rendiment + + + + Priority + Prioritat + + + + Select the priority for the MPlayer process. + Seleccioneu la prioritat per procés de MPlayer. + + + + realtime + realtime + + + + high + alt + + + + abovenormal + per sobre del normal + + + + normal + normal + + + + belownormal + per sota del normal + + + + idle + idle + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Seleccionant una memòria de cau podeu millorar el rendiment dels suports lents + + + + Allow frame drop + Accepta deixar anar marc + + + + Synchronization + Sincronització + + + + Audio/video auto synchronization + Sincronització automàtica de àudio/vídeo + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Selecciona la prioritat del procés de MPlayer d'acord amb les prioritats disponibles en Windows.<br><b>AVÍS:</b> L'ús de prioritat en temps real pot fer que el sistema es pengi. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Omet mostrar alguns marcs per mantenir la sincronització A/V en sistemes lents. + + + + Allow hard frame drop + Permet deixar anar marcs dors + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Deixa anar el marc més intensament (trenca la descodificació). Tendeix a distorsionar la imatge! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Ajusta gradualment la sincronització de A/V basant-se en mesures de retard d'àudio. + + + + Priorit&y: + &Prioritat: + + + + &Allow frame drop + &Permet deixar anar el marc + + + + Allow &hard frame drop (can lead to image distortion) + Permet deixar anar el marc f&ortament (pot provacar la distorsió de la imatge) + + + + Audio/&video auto synchronization + Sincronització automàtica d'àudio/&vídeo + + + + Fact&or: + Fact&or: + + + + &Fast audio track switching + &Commutació ràpida de piestes d'àudio + + + + Fast &seek to chapters in dvds + &Cerca ràpida pels capítols en dvds + + + + Fast audio track switching + Commutació ràpida de piestes d'àudio + + + + Fast seek to chapters in dvds + Cerca ràpida pels capítols en dvds + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Si es selecciona, intentarà el mètode més ràpid de cerca per capítols, però pot ser que no funcioni amb alguns discos. + + + + Skip loop filter + Omet el filtre de repetició + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Valors possibles:<br> <b>Sí</b>: intentarà el mètode més ràpid per canviar la pista d'àudio (pot no funcionar amb alguns formats).<br> <b>No</b>: el procés MPlayer es reiniciarà quan canvieu la pista d'àudio.<br> <b>Auto</b>: SMPlayer decidirà el comportament en funció de la versió de MPlayer. + + + + Cache for files + Memòria de cau pels fitxers + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Aquesta opció especifica quanta memòria de cau (en KBytes) usar quan es precarregui un fitxer. + + + + Cache for streams + Memòria de cau per fluxos de dades + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Aquesta opció especifica quanta memòria de cau (en KBytes) s'usarà quan es precarregui una URL. + + + + Cache for DVDs + Memòria de cau per DVDs + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Aquesta opció especifica quanta memòria de cau (en KBytes) s'usarà en precarrgar un DVD.<br><b>Avís:</b> La cerca pot no funcionar correctament (incloent el canvi de capítols) quan s'usi una memòria de cau per DVDs. + + + + &Cache + &Memòria de cau + + + + Cache for &DVDs: + Memòria de cau per &DVDs: + + + + Cache for &local files: + Memòria de cau per fitxers &locals: + + + + Cache for &streams: + Memòria de cau per &fluxos de dades: + + + + Enabled + Habilitat + + + + Skip (always) + Omet (sempre) + + + + Skip only on HD videos + Omet només en vídeos HD + + + + Loop &filter + &Filtre de repetició + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Aquesta opció permet ometre el filtre de repetició (AKA desbloqueig) durant la descodificació H.264. Com que els fotogrames se suposa que s'usen com a referència per descodificar els fotogrames dependents això té un efecte desastrós en la qualitat, en comptes del desbloqueig en vídeos MPEG-2. En canvi, per HDTV amb alta velocitat de transmissió produeix un gran increment de velocitat sense pèrdua de qualitat visible. + + + + Possible values: + Valors possibles: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Habilitat</b>: no s'omet el filtre de repetició + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Omet (sempre)</b>: el filtre de repetició s'omet independentment de la resolució del vídeo + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Omet només en vídeos HD</b>: el filtre de repetició s'ometrà només en vídeos de longitud %1 o major. + + + + Cache + Memòria de cau + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Llista de reproducció + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + Llista de re&producció + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Subtítols + + + + Choose a ttf file + Escolliu un fitxer ttf + + + + Truetype Fonts + Lletres Truetype + + + + &Subtitles + &Subtítols + + + + Autoload + Càrrega automàtica + + + + Same name as movie + El mateix nom que la pel·lícula + + + + All subs containing movie name + Tots els subtítols que continguin el nom de la pel·lícula + + + + All subs in directory + Tots els subtítols d'un directori + + + + Position + Posició + + + + 0 + 0 + + + + Top + A dalt + + + + Bottom + A baix + + + + Font + Lletra + + + + Select the font which will be used for subtitles (and OSD): + Seleccioneu el tipus de lletra dels subtítols (i OSD): + + + + Size + Mida + + + + No autoscale + No escalable automàticament + + + + Proportional to movie height + Proporcional a l'altura del vídeo + + + + Proportional to movie width + Proporcional a l'amplada del vídeo + + + + Proportional to movie diagonal + Proporcional a la diagonal de la pel·lícula + + + + Subtitle position + Posició dels subtítols + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Aquesta opció especifica la posició dels subtítols sobre la pantalla de vídeo.<i>100</i> significa a baix, mentre que <i>0</i> significa a dalt. + + + + Au&toload subtitles files (*.srt, *.sub...): + Carrega &automàticament fitxers (*.srt, *.sub...): + + + + S&elect first available subtitle + S&elecciona el primer subtítol disponible + + + + &Default subtitle encoding: + &Codificació de subtítols per defecte: + + + + Default &position of the subtitles on screen + &Posició per defecte dels subtítols en la pantalla + + + + &Include subtitles on screenshots + &Inclou els subtítols en les captures de pantalla + + + + &TTF font: + Lletra &TTF: + + + + S&ystem font: + Lletra del &sistema: + + + + A&utoscale: + &Escalat automàtic: + + + + Select first available subtitle + Seleccioneu el primer subtítol disponible + + + + Default subtitle encoding + Codificació per defecte del subtítol + + + + Include subtitles on screenshots + Inclou els subtítols en les captures de pantalla + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Si aquesta opció està activada, els subtítols apareixeran en les captures de pantalla. Nota: pot causar problemes algunes vegades. + + + + TTF font + Lletra TTF + + + + System font + Tipus de lletra del sistema + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Aquí podeu seleccionar un tipus de lletra pel sistema que s'usarà en subtítols i OSD. <b>Nota:</b> requereix una versió de MPlayer amb suport per fontconfig. + + + + Autoscale + Escalable automàticament + + + + Text color + Color del text + + + + Select the color for the text of the subtitles. + Selecciona el color pel text i els subtítols. + + + + Border color + Color de la vora + + + + Select the color for the border of the subtitles. + Selecciona el color de la vora dels subtítols. + + + + Select the subtitle autoload method. + Selecciona el mètode de càrrega automàtica de subtítols. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Si hi ha un o més pistes de subtítols disponibles, una d'elles se seleccionarà automàticament, normalment la primera, tot i que si una d'elles coincideix amb la preferida de l'usuari se seleccionarà aquesta última. + + + + Select the subtitle autoscaling method. + Selecciona el mètode d'autoescalat automàtic de subtítols. + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + A baix + + + + Middle + vertical alignment + + + + + Top + vertical alignment + A dalt + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Ajuda + + + + OK + D'acord + + + + Cancel + Cancel·la + + + + Apply + Aplica + + + + Help + Ajuda + + + + SMPlayer - Preferences + SMPlayer - Preferències + + + + QObject + + + will show this message and then will exit. + es mostrarà aquest missatge i després es tancarà. + + + + the main window will be closed when the file/playlist finishes. + la finestra principal es tancarà quan acabi el fitxer/llista de reproducció. + + + + This is SMPlayer v. %1 running on %2 + Això és l'SMPlayer v. %1 executant-se en %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + intenta connectar-se amb una altra instància en execució i enviar-li l'acció especificada. Per exemple: -send-action pause S'ignoraran la resta d'opcions (si n'hi ha) i l'aplicació es tancarà. Es tornarà 0 si acaba amb èxit i -1 si falla. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list és una llista d'accions separades per espais. Després de carregar el fitxer (si n'hi ha cap), s'executaran les accions en el mateix ordre que les hagueu introduït. Podeu passar true o false com un paràmetre en les accions comprovables. + + + + media + suports + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + si s'està executant una altra instància, el suport s'afegirà a la llista de reproducció de la instància en execució. Si no hi ha altres instàncies, aquesta opció no es considerarà i els fitxers s'obriran en una nova instància. + + + + the main window won't be closed when the file/playlist finishes. + la finestra principal no es tancarà quan acabi el fitxer/llista de reproducció. + + + + the video will be played in fullscreen mode. + el vídeo es reproduirà en mode de pantalla completa. + + + + the video will be played in window mode. + el vídeo es reproduirà en mode de finestra. + + + + Enqueue in SMPlayer + Posa a la cua de SMPlayer + + + + opens the mini gui instead of the default one. + obre la interfície gràfica mínima enlloc de la per defecte. + + + + Restores the old associations and cleans up the registry. + Restaura les associacions i esborra el registre. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'suport' és qualsevol tipus de fitxer que pot obrir SMPlayer. Pot ser un fitxer local, un DVD (p.e. dvd://1), un flux de dades d'internet (p.e. mms://....) o una llista de reproducció local en format m3u o pls. Si s'usa la opció -playlist, SMPlayer passarà l'opció -playlist a MPlayer, per tal que MPlayer s'encarregui de la llista de reproducció, enlloc de SMPlayer. + + + + Usage: + Us: + + + + directory + directori + + + + action_name + nom_de_l'acció + + + + action_list + llista_d'accions + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + %1 i %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + icona + + + + label + etiqueta + + + + ShortcutGetter + + + Modify shortcut + Modifica la drecera + + + + Clear + Esborra + + + + Press the key combination you want to assign + Premeu la combinació de tecles que voleu assignar + + + + Capture + Captura + + + + Capture keystrokes + Captura la pulsació de tecles + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + Selecciona'ls tots + + + + Select None + No en seleccionis cap + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Cerca + + + + &Jump to: + &Salta a: + + + + TristateCombo + + + Auto + Auto + + + + Yes + + + + + No + No + + + + VideoEqualizer + + + Contrast + Contrast + + + + Brightness + Brillantor + + + + Hue + Hue + + + + Saturation + Saturació + + + + Gamma + Gamma + + + + &Reset + &Reinicia + + + + &Set as default values + E&stableix com a valors per defecte + + + + Use the current values as default values for new videos. + Usa els valors actuals pels vídeos nous. + + + + Set all controls to zero. + Estableix tots els controls a zero. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + Cancel·la + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + S'ha produït un error en desar el fitxer + + + + The file couldn't be saved + No s'ha pogut desar el fitxer + + + + Error + Error + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Per defecte + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Volum + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_cs.ts b/plugins/smplayer_plugin/translations/smplayer_cs.ts new file mode 100644 index 000000000..b8ffaab0e --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_cs.ts @@ -0,0 +1,7587 @@ + + + + About + + + Version: %1 + Verze: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Tento program je svobodný software, který můžete šířit a modifikovat dle licence GNU General Public License publikovanou nadací Free Software Foundation od verze 2, případně vyšší. + + + + The following people have contributed with translations: + Tito lidé přispěli překladem do uvedené lokalizace: + + + + German + Německá + + + + Slovak + Slovenská + + + + Italian + Italská + + + + French + Francouzská + + + + %1, %2 and %3 + %1, %2 a %3 + + + + Simplified-Chinese + Zjednodušená Čínská + + + + Russian + Ruská + + + + %1 and %2 + %1 a %2 + + + + Hungarian + Maďarská + + + + Polish + Polská + + + + Japanese + Japonská + + + + Dutch + Holandská + + + + Ukrainian + Ukrajinská + + + + Portuguese - Brazil + Portugalská - Brazílie + + + + Georgian + Gruzínská + + + + Czech + Česká + + + + Bulgarian + Bulharská + + + + Turkish + Turecká + + + + Swedish + Švédská + + + + Serbian + Srbská + + + + Traditional Chinese + Tradiční Čínská + + + + Romanian + Rumunská + + + + Portuguese - Portugal + Portugalská + + + + Greek + Řecká + + + + Finnish + Finská + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + O SMPlayeru + + + + &Info + &Obecné + + + + icon + ikona + + + + &Contributions + Při&spívající + + + + &Translators + &Překladatelé + + + + &License + &Licence + + + + Visit our web for updates: + Pro novější verze, navštivte náš web: + + + + Get help in our forum: + Pomoc najdete na fóru: + + + + You can support SMPlayer by making a donation. + Můžete podpořit SMPlayer peněžním darem. + + + + More info + Další informace + + + + Korean + Korejská + + + + Macedonian + Makedonská + + + + Basque + Baskská + + + + Using MPlayer %1 + Používá MPlayer %1 + + + + Catalan + Katalánská + + + + Portable Edition + Přenosná edice + + + + Using Qt %1 (compiled with Qt %2) + Používá Qt %1 (přeloženo s Qt %2) + + + + Slovenian + Slovinská + + + + Arabic + Arabská + + + + Kurdish + Kurdská + + + + Galician + Haličská + + + + The following people have contributed with patches (see the changelog for details): + Tito lidé přispěli opravami kódu (viz changelog): + + + + If there's any omission, please report. + Byl-li někdo vynechán, ozvěte se. + + + + SMPlayer logo by %1 + Logo SMPlayeru od %1 + + + + %1, %2, %3 and %4 + %1, %2, %3 a %4 + + + + %1, %2, %3, %4 and %5 + %1, %2, %3, %4 a %5 + + + + ActionsEditor + + + Name + Název + + + + Description + Popis + + + + Shortcut + Zkratka + + + + &Save + &Uložit + + + + &Load + &Načíst + + + + Key files + Soubory zkratek + + + + Choose a filename + Zvolte název souboru k uložení + + + + Confirm overwrite? + Opravdu přepsat? + + + + The file %1 already exists. +Do you want to overwrite? + Soubor %1 již existuje. +Opravdu jej chcete přepsat? + + + + Error + Chyba + + + + The file couldn't be saved + Tento soubor nemůže být uložen + + + + Choose a file + Zvolte soubor k načtení + + + + The file couldn't be loaded + Tento soubor nemůže být načten + + + + &Change shortcut... + &Změnit zkratku... + + + + AudioEqualizer + + + Audio Equalizer + Zvukový ekvalizér + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Použít + + + + &Reset + &Obnovit + + + + &Set as default values + Použít jako &výchozí + + + + Use the current values as default values for new videos. + Použít dané hodnoty jako výchozí pro nová videa. + + + + Set all controls to zero. + Nastavit všechny ovládací prvky na nulu. + + + + Information + Informace + + + + The current values have been stored to be used as default. + Dané hodnoty byly uloženy jako výchozí. + + + + BaseGui + + + &File... + &Soubor... + + + + D&irectory... + &Adresář... + + + + &Playlist... + &Playlist... + + + + &DVD from drive + &DVD z mechaniky + + + + D&VD from folder... + D&VD z adresáře... + + + + &URL... + &URL... + + + + P&lay + Př&ehrát + + + + &Pause + &Pozastavit + + + + &Stop + &Zastavit + + + + &Frame step + &Krokovat snímky + + + + Play / Pause + Spustit / Pozastavit + + + + Pause / Frame step + Pozastavit / Krokovat snímky + + + + &Repeat + &Opakovat + + + + &Normal speed + &Normální rychlost + + + + &Halve speed + &Poloviční rychlost + + + + &Double speed + &Dvojnásobná rychlost + + + + Speed &-10% + Rychlost &-10% + + + + Speed &+10% + Rychlost &+10% + + + + Sp&eed + &Rychlost + + + + &Fullscreen + &Celá obrazovka + + + + &Compact mode + &Kompaktní mód + + + + &Equalizer + &Ekvalizér + + + + &Screenshot + &Snímek obrazovky + + + + S&tay on top + &Vždy nahoře + + + + &Postprocessing + &Postprocessing + + + + &Autodetect phase + &Autodetekce fáze + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + Přidat š&um + + + + F&ilters + F&iltry + + + + &Mute + &Ztlumit + + + + Volume &- + Hlasitost &- + + + + Volume &+ + Hlasitost &+ + + + + &Delay - + Zp&oždění - + + + + D&elay + + Z&poždění + + + + + &Extrastereo + &Extra Stereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtry + + + + &Load... + &Načíst... + + + + Delay &- + Zpoždění &- + + + + Delay &+ + Zpoždění &+ + + + + &Up + N&ahoru + + + + &Down + &Dolů + + + + &Playlist + &Playlist + + + + &Show frame counter + &Zobrazit počítadlo snímků + + + + P&references + &Nastavení + + + + &View logs + Zobrazit &logy + + + + About &Qt + O &Qt + + + + About &SMPlayer + O &SMplayeru + + + + &Open + &Otevřít + + + + &Play + &Přehrát + + + + &Video + &Video + + + + &Audio + &Audio + + + + &Subtitles + &Titulky + + + + &Browse + Navi&gace + + + + Op&tions + &Možnosti + + + + &Help + &Nápověda + + + + &Recent files + &Naposledy otevřené + + + + &Clear + &Vyčistit + + + + Si&ze + Ve&likost + + + + &Aspect ratio + Po&měr stran + + + + &Deinterlace + Odstranění p&rokládání + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &na 16:9 + + + + &None + Žá&dné + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Linear &Blend + + + + &Track + &Stopa + + + + &Channels + &Kanály + + + + &Stereo mode + &Stereo mód + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Left channel + &Levý kanál + + + + &Right channel + &Pravý kanál + + + + &Select + &Vybrat + + + + &Title + &Titul + + + + &Chapter + &Kapitola + + + + &Angle + Ú&hel + + + + &OSD + &OSD + + + + &Disabled + &Vypnuto + + + + &Seek bar + &Ukazatel pozice + + + + &Time + Č&as + + + + Time + T&otal time + Čas + &Celkový čas + + + + SMPlayer - mplayer log + SMPlayer - mplayer log + + + + SMPlayer - smplayer log + SMPlayer - smplayer log + + + + <empty> + <prázdné> + + + + Video + Video + + + + Audio + Audio + + + + Playlists + Playlisty + + + + All files + Všechny soubory + + + + Choose a file + Zvolte soubor + + + + SMPlayer - Information + SMplayer - informace + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Mechaniky CDROM / DVD nejsou nastaveny. +Bude zobrazeno konfigurační okno. + + + + Choose a directory + Zvolte adresář + + + + Subtitles + Titulky + + + + About Qt + O Qt + + + + Playing %1 + Přehrávám %1 + + + + Pause + Pozastaveno + + + + Stop + Zastaveno + + + + U&nload + &Uvolnit + + + + V&CD + V&CD + + + + C&lose + &Zavřít + + + + View &info and properties... + Zobrazit &info a vlastnosti... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Reset + + + + Move &left + Posunout do&leva + + + + Move &right + Posunout dop&rava + + + + Move &up + Posunout &nahoru + + + + Move &down + Posunout &dolů + + + + &Previous line in subtitles + &Předešlý řádek tutulků + + + + N&ext line in subtitles + Da&lší řádek titulků + + + + &Pan && scan + P&an && scan + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Hlasitost - (2) + + + + Inc volume (2) + Hlasitost + (2) + + + + Exit fullscreen + Ukončit režim celé obrazovky + + + + OSD - Next level + OSD - Přepni zobrazení + + + + Dec contrast + Kontrast - + + + + Inc contrast + Kontrast + + + + + Dec brightness + Jas - + + + + Inc brightness + Jas + + + + + Dec hue + Odstín - + + + + Inc hue + Odstín + + + + + Dec saturation + Sytost - + + + + Dec gamma + Gamma - + + + + Next audio + Další audio stopa + + + + Next subtitle + Další titulky + + + + Next chapter + Další kapitola + + + + Previous chapter + Předešlá kapitola + + + + Inc saturation + Sytost + + + + + Inc gamma + Gamma + + + + + &Load external file... + Načíst e&xterní soubor... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normalní) + + + + Y&adif (double framerate) + Y&adif (dvojitý počet snímků/s) + + + + &Next + &Další + + + + Pre&vious + Před&chozí + + + + Volume &normalization + &Normalizace hlasitosti + + + + &Audio CD + Zvuk&ové CD + + + + Denoise nor&mal + &Normální odstranění šumu + + + + Denoise &soft + &Měkké odstranění šumu + + + + Denoise o&ff + N&eodstraňovat šum + + + + Use SSA/&ASS library + Použít &SSA/ASS knihovnu + + + + Flip i&mage + Převrátit o&braz + + + + &Toggle double size + Dvoji&tá velikost + + + + S&ize - + Zvě&tšit + + + + Si&ze + + Z&menšit + + + + Add &black borders + Přidat &okraje + + + + Soft&ware scaling + Softwarové &roztažení + + + + &FAQ + &FAQ + + + + Visualize &motion vectors + Zobrazit &pohybové vektory + + + + &Command line options + &Argumenty příkazového řádku + + + + SMPlayer command line options + Argumenty příkazového řádku + + + + Enable &closed caption + &Closed caption titulky + + + + &Forced subtitles only + Pouze &vynucené titulky + + + + Reset video equalizer + Vynulovat video-ekvalizér + + + + MPlayer has finished unexpectedly. + MPlayer skončil chybou. + + + + Exit code: %1 + Návratová hodnota: %1 + + + + MPlayer failed to start. + Nelze spustit MPlayer. + + + + Please check the MPlayer path in preferences. + Zkontrolujte cestu k MPlayeru v nastavení. + + + + MPlayer has crashed. + MPlayer havaroval. + + + + See the log for more info. + Více informací je v logu. + + + + &Rotate + &Otočit + + + + &Off + &Vypnuto + + + + &Rotate by 90 degrees clockwise and flip + Otočit dopr&ava a převrátit + + + + Rotate by 90 degrees &clockwise + Otočit dop&rava + + + + Rotate by 90 degrees counterclock&wise + Otočit do&leva + + + + Rotate by 90 degrees counterclockwise and &flip + Otočit dol&eva a převrátit + + + + &Jump to... + &Na pozici... + + + + Show context menu + Zobraz kontextové menu + + + + Multimedia + Multimédia + + + + E&qualizer + &Ekvalizér + + + + Reset audio equalizer + Vynulovat audio-ekvalizér + + + + Find subtitles on &OpenSubtitles.org... + Vyhledat titulky na &OpenSubtitiles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Poslat &titulky na OpenSubtitles.org... + + + + &Tips + &Tipy + + + + &Auto + &Auto + + + + Speed -&4% + R&ychlost -4% + + + + &Speed +4% + Ry&chlost +4% + + + + Speed -&1% + Rych&lost -1% + + + + S&peed +1% + Rychl&ost +1% + + + + Scree&n + Obra&zovka + + + + &Default + &Výchozí + + + + Mirr&or image + &Zrcadlit obraz + + + + Next video + Další video stopa + + + + &Track + video + S&topa + + + + &Track + audio + S&topa + + + + Warning - Using old MPlayer + Varování - Použit starý MPlayer + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + Nainstalovaná verze MPlayeru (%1) je zastaralá. SMPlayer nebude pracovat správně: ne všechna nastavení budou funkční, výběr titulků může selhat, ... + + + + Please, update your MPlayer. + Prosím, updatujte si MPlayer. + + + + (This warning won't be displayed anymore) + (Toto varování dále nebude zobrazeno) + + + + Next aspect ratio + Další poměr stran + + + + &Auto zoom + &Auto zoom + + + + Auto zoom for &16:9 + Auto zoom na &16:9 + + + + Auto zoom for &2.35:1 + Auto zoom na &2.35:1 + + + + Pre&view... + &Náhled... + + + + Zoom for &16:9 + Zoom na &16:9 + + + + Zoom for &2.35:1 + Zoom na &2.35:1 + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer zde stále běží + + + + S&how icon in system tray + Zo&brazit ikonu v systémové liště + + + + &Hide + &Skrýt + + + + &Restore + &Obnovit + + + + &Quit + &Konec + + + + Playlist + Playlist + + + + Core + + + Brightness: %1 + Jas: %1 + + + + Contrast: %1 + Kontrast: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Odstín: %1 + + + + Saturation: %1 + Saturace: %1 + + + + Volume: %1 + Hlasitost: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + Velikost písma: %1 + + + + Aspect ratio: %1 + Poměr stran: %1 + + + + Updating the font cache. This may take some seconds... + Obnovuji paměť fontů. Může to chvíli trvat... + + + + DefaultGui + + + Welcome to SMPlayer + Vítá vás SMPlayer + + + + &Main toolbar + &Hlavní lišta + + + + &Language toolbar + &Jazyková lišta + + + + &Toolbars + Nás&trojové lišty + + + + Audio + Audio + + + + Subtitle + Titulky + + + + EqSlider + + + icon + ikona + + + + ErrorDialog + + + Hide log + Schovat log + + + + Show log + Zobrazit log + + + + MPlayer Error + Chyba MPlayeru + + + + icon + ikona + + + + Error + Chyba + + + + FileDownloader + + + Downloading... + Stahuji... + + + + Downloading %1 + Stahuji %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Vlastnosti souboru + + + + &Information + &Informace + + + + &Demuxer + &Dekodér + + + + &Select the demuxer that will be used for this file: + &Vyberte dekodér, který bude použit pro tento soubor: + + + + &Reset + &Původní + + + + &Video codec + &Video kodek + + + + &Select the video codec: + &Vyberte video kodek: + + + + A&udio codec + A&udio kodek + + + + &Select the audio codec: + &Vyberte audio kodek: + + + + &MPlayer options + &Nastavení MPlayeru + + + + Additional Options for MPlayer + Přídavné volby pro MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Zde můžete zadat extra volby pro MPlayer. +Oddělujte je mezerami. +Příklad: -flip -nosound + + + + &Options: + &Volby: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Můžete použít další video filtry. +Oddělujte je čárkou (","), nepoužívejte mezery! +Příklad: scale=512:-2;eq2=1.1 + + + + V&ideo filters: + V&ideo filtry: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + A nakonec audio filtry. Stejná pravidla jako pro video filtry. +Příklad: resample=44100:0:0,volnorm + + + + Audio &filters: + Audio &filtry: + + + + OK + OK + + + + Cancel + Storno + + + + Apply + Použít + + + + FindSubtitlesWindow + + + Language + Jazyk + + + + Name + Název + + + + Format + Formát + + + + Files + Soubory + + + + Date + Datum + + + + Uploaded by + Vložil + + + + All + Všechny + + + + Close + Zavřít + + + + &Download + &Stáhnout + + + + &Copy link to clipboard + Z&kopírovat do schránky + + + + Error + Chyba + + + + Download failed: %1. + Stahování selhalo: %1. + + + + Connecting to %1... + Připojování k %1... + + + + Downloading... + Stahuji... + + + + Done. + Dokončeno. + + + + %1 files available + %1 souborů ke stažení + + + + Failed to parse the received data. + Nelze přečíst přijatá data. + + + + Find Subtitles + Hledat titulky + + + + &Subtitles for + &Titulky pro + + + + &Language: + &Jazyk: + + + + &Refresh + &Obnovit + + + + Subtitle saved as %1 + Titulky uloženy jako %1 + + + + %1 subtitle(s) extracted + + %1 titulky + %1 titulky + %1 titulků + + + + + Overwrite? + Přepsat? + + + + The file %1 already exits, overwrite? + Soubor %1 již existuje, přepsat? + + + + Error saving file + Chyba při ukládání souboru + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Nelze uložit stažený soubor +do adresáře %1. +Zkontrolujte přístupová práva. + + + + Download failed + Stahování selhalo + + + + Temporary file %1 + Dočasný soubor %1 + + + + InfoFile + + + General + Obecné + + + + Size + Velikost + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Délka + + + + Demuxer + Dekodér + + + + Name + Název + + + + Artist + Umělec + + + + Author + Autor + + + + Album + Album + + + + Genre + Žánr + + + + Date + Datum + + + + Track + Stopa + + + + Copyright + Copyright + + + + Comment + Komentář + + + + Software + Software + + + + Clip info + Informace o klipu + + + + Video + Video + + + + Resolution + Rozlišení + + + + Aspect ratio + Poměr stran + + + + Format + Formát + + + + Bitrate + Datový tok + + + + %1 kbps + %1 kbps + + + + Frames per second + Snímků za sekundu + + + + Selected codec + Vybraný kodek + + + + Initial Audio Stream + Výchozí audio stopa + + + + Rate + Frekvence + + + + %1 Hz + %1 Hz + + + + Channels + Kanály + + + + Audio Streams + Audio stopy + + + + Language + Jazyk + + + + empty + prázdný + + + + Subtitles + Titulky + + + + Type + Typ + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + + + + + Stream title + Název streamu + + + + Stream URL + Adresa streamu + + + + File + Soubor + + + + InputDVDDirectory + + + Choose a directory + Zvolit adresář + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Přehrát DVD z adresáře + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Můžete spustit DVD z adresáře na disku. Vyberte adresář, který obsahuje složky VIDEO_TS a AUDIO_TS. + + + + Choose a directory... + Zvolit adresář... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Zadejte verzi MPlayeru + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer nemohl identifikovat verzi nainstalovaného MPlayeru. + + + + Version reported by MPlayer: + Verze oznámená MPlayerem: + + + + Please, &select the correct version: + Prosím, &vyberte správnou verzi: + + + + 1.0rc1 or older + 1.0rc1 nebo starší + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Vyšší než 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Zadejte URL + + + + &URL: + &URL: + + + + It's a &playlist + Je to &playlist + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Poku je tato volba zaškrtnuta, URL bude brán jako playlist: bude otevřen jako text a URL v něm přehrány. + + + + Languages + + + Afar + Afarština + + + + Abkhazian + Abcházština + + + + Afrikaans + Afrikánština + + + + Amharic + Amharština + + + + Arabic + Arabština + + + + Assamese + Ásámština + + + + Aymara + Ajmarština + + + + Azerbaijani + Ázerbájdžánština + + + + Bashkir + Baskirština + + + + Byelorussian + Běloruština + + + + Bulgarian + Bulharština + + + + Bihari + Bihárština + + + + Bislama + Bislamština + + + + Bengali + Bengálština + + + + Tibetan + Tibetština + + + + Breton + Bretonština + + + + Catalan + Katalánština + + + + Corsican + Korsičtina + + + + Czech + Čeština + + + + Welsh + Velština + + + + Danish + Dánština + + + + German + Němčina + + + + Bhutani + Bhútánština + + + + Greek + Řečtina + + + + English + Angličtina + + + + Esperanto + Esperanto + + + + Spanish + Španělština + + + + Estonian + Estonština + + + + Basque + Baskičtina + + + + Persian + Perština + + + + Finnish + Finština + + + + Fiji + Fidžijština + + + + Faroese + Faerština + + + + French + Francouzština + + + + Frisian + Fríština + + + + Irish + Irština + + + + Scots + Skotština + + + + Galician + Gaelština + + + + Guarani + Guaraní + + + + Gujarati + Gudžarátština + + + + Hausa + Hauština + + + + Hebrew + Hebrejština + + + + Hindi + Hindština + + + + Croatian + Chorvatština + + + + Hungarian + Maďarština + + + + Armenian + Arménština + + + + Interlingua + Interlingua + + + + Indonesian + Indonéština + + + + Interlingue + Interlingue + + + + Inupiak + Inupiak + + + + Icelandic + Islandština + + + + Italian + Italština + + + + Inuktitut + Inuktitut + + + + Japanese + Japonština + + + + Javanese + Javánština + + + + Georgian + Gruzínština + + + + Kazakh + Kazaština + + + + Greenlandic + Grónština + + + + Cambodian + Kambodžština + + + + Kannada + Kannadština + + + + Korean + Korejština + + + + Kashmiri + Kašmírština + + + + Kurdish + Kurdština + + + + Kirghiz + Kyrgyzština + + + + Latin + Latina + + + + Lingala + Lingala + + + + Laothian + Laoština + + + + Lithuanian + Litevština + + + + Latvian + Lotyština + + + + Malagasy + Malgaština + + + + Maori + Maorština + + + + Macedonian + Makedonština + + + + Malayalam + Malajálamština + + + + Mongolian + Mongolština + + + + Moldavian + Moldavština + + + + Marathi + Maráthí + + + + Malay + Malajština + + + + Maltese + Maltština + + + + Burmese + Barmština + + + + Nauru + Naurština + + + + Nepali + Nepálština + + + + Dutch + Holandština + + + + Norwegian + Norština + + + + Occitan + Okcitánština + + + + Oriya + Urijština + + + + Punjabi + Pandžábština + + + + Polish + Polština + + + + Pashto + Paštština + + + + Portuguese + Portugalština + + + + Quechua + Kečujština + + + + Kirundi + Kirundi + + + + Romanian + Rumunština + + + + Russian + Ruština + + + + Kinyarwanda + Rwandština + + + + Sanskrit + Sánskrt + + + + Sindhi + Sindhština + + + + Sangho + Sangoština + + + + Sinhalese + Sinhálština + + + + Slovak + Slovenština + + + + Slovenian + Slovinština + + + + Samoan + Samojština + + + + Shona + Šonština + + + + Somali + Somálština + + + + Albanian + Albánština + + + + Serbian + Srbština + + + + Siswati + Siswati + + + + Sesotho + Sotština + + + + Sundanese + Sundština + + + + Swedish + Švédština + + + + Swahili + Svahilština + + + + Tamil + Tamilština + + + + Telugu + Telugština + + + + Tajik + Tádžičtina + + + + Thai + Thajština + + + + Tigrinya + Tigriňa + + + + Turkmen + Turkmenština + + + + Tagalog + Tagalština + + + + Setswana + Čvanština + + + + Tonga + Tonžština + + + + Turkish + Turečtina + + + + Tsonga + Tsonga + + + + Tatar + Tatarština + + + + Twi + Ťviština + + + + Uighur + Ujgurština + + + + Ukrainian + Ukrajinština + + + + Urdu + Urdština + + + + Uzbek + Uzbečtina + + + + Vietnamese + Vietnamština + + + + Wolof + Volofština + + + + Xhosa + Xhoština + + + + Yiddish + Jidiš + + + + Yoruba + Jorubština + + + + Zhuang + Čuangština + + + + Chinese + Čínština + + + + Zulu + Zulština + + + + Portuguese - Brazil + Portugalština - Brazílie + + + + Portuguese - Portugal + Portugalština - Portugalsko + + + + Simplified-Chinese + Zjednodušená Čínština + + + + Traditional Chinese + Tradiční Čínština + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + Západoevropské jazyky + + + + Western European Languages with Euro + Západoevropské jazyky s Euro + + + + Slavic/Central European Languages + Středoevropské jazyky + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galicijština, Maltština, Turečtina + + + + Old Baltic charset + Staré baltské kódování + + + + Cyrillic + Cyrilice + + + + Modern Greek + Moderní řečtina + + + + Baltic + Baltské + + + + Celtic + Keltské + + + + Hebrew charsets + Hebrejské znaky + + + + Ukrainian, Belarusian + Ukrajinské, Běloruské + + + + Simplified Chinese charset + Zjednodušené čínské znaky + + + + Traditional Chinese charset + Tradiční čínské znaky + + + + Japanese charsets + Japonské znaky + + + + Korean charset + Korejské znaky + + + + Thai charset + Thajské znaky + + + + Cyrillic Windows + Cyrilice Windows + + + + Slavic/Central European Windows + Středoevropské Windows + + + + Arabic Windows + Arabské Windows + + + + Rhaeto-Romance + Rétorománština + + + + Serbo-Croatian + Srbochorvatština + + + + Volapük + Volapük + + + + Avestan + Avestánština + + + + Akan + Akanština + + + + Aragonese + Aragonština + + + + Avaric + Avarština + + + + Belarusian + Běloruština + + + + Bambara + Bambarština + + + + Bosnian + Bosenština + + + + Chechen + Čečenština + + + + Cree + Kríjština + + + + Church + Staroslověnština + + + + Chuvash + Čuvašština + + + + Divehi + Divehi + + + + Dzongkha + Dzongkha + + + + Ewe + Eweština + + + + Fulah + Fula + + + + Fijian + Fidžijština + + + + Gaelic + Gaelská Irština + + + + Manx + Manština + + + + Hiri + Hiri + + + + Haitian + Haitština + + + + Herero + Hererština + + + + Chamorro + Chamorro + + + + Igbo + Igbo + + + + Sichuan + Yi + + + + Inupiaq + Inupiaq + + + + Ido + Ido + + + + Kongo + Konžtina + + + + Kikuyu + Kikujština + + + + Kuanyama + Kuanyama + + + + Khmer + Kmérština + + + + Kanuri + Kanurijština + + + + Komi + Komijština + + + + Cornish + Kornština + + + + Luxembourgish + Lucemburština + + + + Ganda + Lugandština + + + + Limburgan + Limburština + + + + Lao + Laoština + + + + Luba-Katanga + Lubština + + + + Marshallese + Maršálština + + + + Bokmål + Bokmål + + + + Ndebele + Ndebelština + + + + Ndonga + Ndonga + + + + Navajo + Navažština + + + + Chichewa + Čičevština + + + + Ojibwa + Odžibvejština + + + + Oromo + Oromština + + + + Ossetian + Osetština + + + + Panjabi + Pandžábština + + + + Pali + Páli + + + + Pushto + Paštština + + + + Romansh + Rétorománština + + + + Rundi + Kirundština + + + + Sardinian + Sardština + + + + Sami + Samojština + + + + Sango + Sangština + + + + Sinhala + Sinhalština + + + + Swati + Swati + + + + Sotho + Jihosotština + + + + Tswana + Tswanština + + + + Tahitian + Tahitština + + + + Venda + Luvendština + + + + Volapük + Volapük + + + + Walloon + Valonština + + + + LogWindow + + + Choose a filename to save under + Uložit jako + + + + Confirm overwrite? + Opravdu přepsat? + + + + The file already exists. +Do you want to overwrite? + Soubor již existuje. +Chcete jej opravdu přepsat? + + + + Error saving file + Chyba při ukládání souboru + + + + The log couldn't be saved + Log nemohl být uložen + + + + Logs + Logy + + + + LogWindowBase + + + Log Window + Log + + + + Save + Uložit + + + + Copy to clipboard + Zkopírovat do schránky + + + + Close + Zavřít + + + + &Close + &Zavřít + + + + MiniGui + + + Control bar + Ovládací panel + + + + MpcGui + + + Control bar + Ovládací panel + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Název + + + + Length + Délka + + + + &Play + &Přehrát + + + + &Edit + &Upravit + + + + Playlists + Playlisty + + + + Choose a file + Otevřít soubor + + + + Choose a filename + Uložit jako + + + + Confirm overwrite? + Opravdu přepsat? + + + + The file %1 already exists. +Do you want to overwrite? + Soubor %1 již existuje. +Opravdu jej chcete přepsat? + + + + All files + Všechny soubory + + + + Select one or more files to open + Výberte soubory k načtení + + + + Choose a directory + Přidat adresář + + + + Edit name + Změnit název + + + + Type the name that will be displayed in the playlist for this file: + Zadejte název, pod kterým bude soubor zobrazován v seznamu: + + + + &Load + N&ačíst + + + + &Save + &Uložit + + + + &Next + &Další + + + + Pre&vious + &Předchozí + + + + Move &up + Posunout &nahoru + + + + Move &down + Posunout &dolů + + + + &Repeat + &Opakovat + + + + S&huffle + Ná&hodně + + + + Add &current file + Přida&t stávající soubor + + + + Add &file(s) + Přidat &soubor(y) + + + + Add &directory + Přidat ad&resář + + + + Remove &selected + Odebrat o&značené + + + + Remove &all + Odebrat &vše + + + + Add... + Přidat... + + + + Remove... + Odebrat... + + + + SMPlayer - Playlist + SMPlayer - Playlist + + + + Playlist modified + Playlist změněn + + + + There are unsaved changes, do you want to save the playlist? + Byly provedeny změny, chcete je uložit do playlistu? + + + + Preferences + Nastavení + + + + PlaylistPreferences + + + Playlist - Preferences + Playlist - Nastavení + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Zaškrtněte tuto volbu, poud chcete po přídání adresáře také rekurzivně přidat všechny podadresáře. Jinak se přidají pouze soubory ve vybraném adresáři. + + + + &Add files in directories recursively + Přidávat adresáře &rekurzivně + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Zaškrtněte tuto volbu pro načtení informací o přidávaných souborech. To umožní zobrazit název titulu (pokud je obsažen) a délku přehrávání souboru. Jinak se tato informace zobrazí až se soubor začne přehrávat. Pozor: může způsobit zpomalení, obzvláště při velkém množství souborů. + + + + Automatically get &info about files added + Automaticky načítat &informace o souborech + + + + &Save copy of playlist on exit + &Uložit kopii playlistu při ukončení + + + + &Play files from start + &Přehrát soubory od začátku + + + + PrefAdvanced + + + Advanced + Pokročilé + + + + Auto + Auto + + + + &Advanced + &Pokročilé + + + + icon + ikona + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Zde můžete zadat extra volby pro MPlayer. +Oddělujte je mezerami. +Příklad: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Můžete použít další video filtry. +Oddělujte je čárkou (","), nepoužívejte mezery! +Příklad: scale=512:-2;eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + A nakonec audio filtry. Stejná pravidla jako pro video filtry. +Příklad: resample=44100:0:0,volnorm + + + + Log MPlayer output + Logovat výstup MPlayeru + + + + Log SMPlayer output + Logovat výstup SMPlayeru + + + + This option is mainly intended for debugging the application. + Tato možnost je určena pro ladění aplikace. + + + + &MPlayer language + Jazyk &MPlayeru + + + + SMPlayer needs to read and parse the output of MPlayer and sometimes it relies on English text. If you are using a MPlayer translated into another language, then you need to change the texts that SMPlayer looks for. (Technically you should enter regular expressions)<br><br> +The drop-down lists may provide already made regular expression for several languages. + SMPlayer potřebuje číst a zpracovávat výstup z MPlayeru a někdy (....). Pokuď používáte MPlayer přeložený do jiného jazyka, potom budete potřebovat změnit texty po kterých se SMPlayer dívá. (Technicky by si měl zadat standartní výraz)<br><br> +Vysouvací menu by mělo poskytnout standartní možnosti pro několik jazyků. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Zaškrtnutím této volby můžete zmenšit blikání, ale také se výstupní video nemusí zobrazovat správně. + + + + If checked, smplayer will store the output of mplayer (you can see it in <b>Options->View logs->mplayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Pokud je zatrženo, SMPlayer bude ukládat hlášení MPlayeru (lze vidět v <b> Možnosti -> Zobrazit logy -> mplayer<b>). Vpřípadě problémů log obsahuje důležité informace, takže se doporučuje tuto možnost mít povolenou. + + + + If this option is checked, smplayer will store the debugging messages that smplayer outputs (you can see the log in <b>Options->View logs->smplayer</b>). This information can be very useful for the developer in case you find a bug. + Pokud je zatrženo, SMPlayer bude ukládat zprávy SMPlayeru (lze vidět v <b> Možnosti -> Zobrazit logy -> smplayer<b>). Tyto informace jsou velice použitelné pro vývojáře k nalezení chyb. + + + + Filter for SMPlayer logs + Filtr pro logy SMPlayeru + + + + This option allows to filter the smplayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Tato možnost povolí filtrování zpráv SMPlayeru které jsou ukládány do logu. Můžete zadat rugulární výraz. Například: <i>^Core::.*</i> zobrazí pouze řádky začínající <i>Core::</i> + + + + &Monitor aspect: + Poměr stran &monitoru: + + + + &Run MPlayer in its own window + Sp&ustit MPlayer ve vlastním okně + + + + &Options: + &Možnosti: + + + + V&ideo filters: + V&ideo filtry: + + + + Audio &filters: + Audio &filtry: + + + + &Colorkey: + &Klíčovací barva: + + + + Log &SMPlayer output + Logovat výstup &SMPlayeru + + + + &Filter for SMPlayer logs: + &Filtr pro logy SMPlayeru: + + + + &End of file: + Kon&ec souboru: + + + + &No video: + &Bez videa: + + + + C&hange... + &Změnit... + + + + Autosave MPlayer log + Automaticky ukládat log MPlayeru + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Zaškrtnutím této volby se log MPlayeru uloží vždy při spuštění přehrávání nového souboru. Vhodné pro externí aplikace, které potřebují zjistit informace o právě přehrávaném souboru. + + + + Autosave MPlayer log filename + Soubor pro automatické ukládání logu MPlayeru + + + + Enter here the path and filename that will be used to save the MPlayer log. + Zadejte cestu, kam se má ukládat log MPlayeru. + + + + Logs + Logy + + + + Log MPlayer &output + Logovat výstup &MPlayeru + + + + A&utosave MPlayer log to file + A&utomaticky ukládat log MPlayeru + + + + Options for MP&layer + Nastavení MP&layeru + + + + Pass short filenames (8+3) to MPlayer + Předávat MPlayeru krátké názvy souborů (8+3) + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + MPlayer v současnosti nedokáže otevřít soubory, jejichž jména obsahují znaky jiné než lokální kódové stránky. Zaškrtnutím této volby donutíte SMPlayer, aby MPlayeru posílal krátké názvy souborů a MPlayer tak byl schopen tyto soubory otevřít. + + + + &Pass short filenames (8+3) to MPlayer + &Předávat MPlayeru krátké názvy souborů (8+3) + + + + Monitor aspect + Poměr stran monitoru + + + + Select the aspect ratio of your monitor. + Vyberte poměr stran svého monitoru. + + + + Run MPlayer in its own window + Spustit MPlayer ve vlastním okně + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Zaškrtnutím této možnosti se nebude výstup MPlayeru integrovat do hlavního okna SMPlayeru, ale bude mít své vlastní okno. Události z klávesnice a myši budou spravovány přímo MPlayerem, takže klávesové zkratky a akce myši nejspíše nebudou fungovat jak mají, pokud okno MPlayeru ztratí focus. + + + + Colorkey + Klíčovací barva + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Vidíte-li části videa vykresleny přes jiná okna, můžete změnit klíčovací barvu. Zkuste barvy podobné černé. + + + + Options for MPlayer + Nastavení MPlayeru + + + + Options + Nastavení + + + + Here you can type options for MPlayer. Write them separated by spaces. + Zde můžete zadat nastavení pro MPlayer. Oddělujte je mezerami. + + + + Video filters + Video filtry + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Zde můžete přidávat video filtry pro MPlayer. Oddělujte je čárkami. Nepoužívejte mezery! + + + + Audio filters + Audio filtry + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Zde můžete přidávat audio filtry pro MPlayer. Oddělujte je čárkami. Nepoužívejte mezery! + + + + Repaint the background of the video window + Překreslit pozadí videa + + + + Repaint the backgroun&d of the video window + Překreslit poza&dí videa + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Použít připojení přes IPv4. Při neúspěchu se použije IPv6. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Použít připojení přes IPv6. Při neúspěchu se použije IPv4. + + + + Network Connection + Síťové připojení + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + Lo&gy + + + + Rebuild index if needed + Opravit index, je-li potřeba + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Opravit index u souborů, kde nebyl nalezen index a umožnit tak seekování. Užitečné v případě nefunkčních/nekompletních nebo špatně vytvořených souborů. Tato volba funguje jen tehdy, když médium podporuje seekování (např. ne stdin, pipe, atd.).<br> Poznámka: vytvoření indexu může chvíli trvat. + + + + Rebuild &index if needed + Opravit &index, je-li potřeba + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Je-li tato volba zaškrtnuta, SMPlayer bude ukládat ladící informace (log je přístupný přes <b>Nastavení -> Zobrazit logy -> SMPlayer</b>). Tyto informace jsou velmi přínosné pro vývojáře v případě, že naleznete chybu v programu. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Je-li tato volba zaškrtnuta, SMPlayer bude ukládat ladící informace MPlayeru (log je přístupný přes <b>Nastavení -> Zobrazit logy -> MPlayer</b>). Tyto informace jsou velmi přínosné pro řešení problémů, je doporučeno nechat volbu zaškrtnutou. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Toto nastavení umožňuje filtrovat informace SMPlayeru, které se logují. Můžete použít regulární výrazy. <br>Například: <i>^Core::.*</i> zobrazí pouze řádky začínající <i>Core::</i> + + + + Correct pts + Opravit PTS + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Přepne MPlayer do experimentálního módu, který počítá časová razítka videa jiným způsobem a je možné použít filtry, které přidávají snimky nebo modifikují časová razítka. Přesnější výpočty časových razítek jsou viditelné například při přehrávání filmů s titulky časovanými podle změn ve scéně přes SSA/ASS knihovnu. Bez správného pts budou titulky většinou zobrazeny o několik snímků mimo. Tato možnost nefunguje správně s některými kodeky. + + + + Proxy + Proxy + + + + Enable proxy + Povolit proxy + + + + Enable/disable the use of the proxy. + Povolí/zakáže použití proxy. + + + + Host + Server + + + + The host name of the proxy. + Název proxy serveru. + + + + Port + Port + + + + The port of the proxy. + Port na proxy serveru. + + + + Username + Uživatelské jméno + + + + If the proxy requires authentication, this sets the username. + Pokud proxy server vyžaduje autentifikaci, použije se toto jméno. + + + + Password + Heslo + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + Heslo pro připojení k proxy. Varování: heslo bude uloženo v konfiguračním souboru jako čistý text. + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + Můžete nastavit proxy pro přístup k internetu (v současnosti pouze pro stažení titulků). + + + + &Enable proxy + Povolit pro&xy + + + + &Host: + Se&rver: + + + + &Port: + &Port: + + + + &Username: + &Uživatelské jméno: + + + + Pa&ssword: + H&eslo: + + + + C&orrect PTS + &Opravit PTS + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + Typ + + + + Select the proxy type to be used. + Vyberte typ proxy serveru. + + + + &Type: + &Typ: + + + + Actions list + Seznam akcí + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + Zde můžete zadat seznam <i>akcí</i>, které se provedou vždy při otevření souboru. Možné akce najdete v editoru klávesových zkratek v sekci <b>Klávesnice a myš</b>. Akce oddělujte mezerami. Akce se stavem mohou být následovány slovy <i>true</i> nebo <i>false</i> pro povolení nebo zakázání dané akce. + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + Omezení: akce jsou spuštěny pouze při otevření souboru, ne při restartu MPlayeru (např. při přepnutí filtru). + + + + Network + Síť + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + Sp&ustit následující akce při každém otevření souboru. Oddělujte mezerou: + + + + &Network + &Síť + + + + Example: + Příklad: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + Opravit index u souborů, kde nebyl nalezen index a umožnit tak seekování. Užitečné v případě nefunkčních/nekompletních nebo špatně vytvořených souborů. Tato volba funguje jen tehdy, když médium podporuje seekování (např. ne stdin, pipe, atd.).<br> <b>Poznámka:</b> vytvoření indexu může chvíli trvat. + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + Heslo pro připojení k proxy. <b>Varování:</b> heslo bude uloženo v konfiguračním souboru jako čistý text. + + + + PrefAssociations + + + Warning + Varování + + + + Not all files could be associated. Please check your security permissions and retry. + Nepodařilo se přiřadit všechny soubory. Ověřte přístupová práva a zkuste to znovu. + + + + File Types + Typy souborů + + + + Select all + Vybrat vše + + + + Check all file types in the list + Označit všechny soubory na seznamu + + + + Uncheck all file types in the list + Odznačit všechny soubory na seznamu + + + + List of file types + Seznam typů souborů + + + + File types + Typy souborů + + + + Media files handled by SMPlayer: + Multimediální soubory otevírané SMPlayerem: + + + + Select All + Vybrat vše + + + + Select None + Nevybrat žádné + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Zkontrolujte příponu multimediálního souboru, který chcete otevírat SMPlayerem. Až kliknete na Použít, všechny označené soubory budou přiřazeny SMPlayeru. Pokuď odznačíte typ souboru, přiřazení bude obnoveno. + + + + Select none + Nevybrat žádné + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Poznámka:</b> (Obnovení nefunguje ve Windows Vista). + + + + PrefDrives + + + Drives + Mechaniky + + + + icon + ikona + + + + CD device + CD mechanika + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Zvolte CD-ROM mechaniku. Bude použita pro přehrávání VCD a Audio CD. + + + + DVD device + DVD mechanika + + + + Choose your DVD device. It will be used to play DVDs. + Zvolte DVD mechaniku. Bude použita pro přehrávání DVD. + + + + Select your &CD device: + Zvolte &CD mechaniku: + + + + Select your &DVD device: + Zvolte &DVD mechaniku: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer si sám neumí vybrat CD-ROM ani DVD mechaniku. Před tím, než je možno CD nebo DVD přehrát, musíte vybrat mechaniku, ze které se budou data číst (mohou být stejné). + + + + PrefGeneral + + + General + Obecné + + + + &General + &Obecné + + + + Paths + Cesty + + + + Output drivers + Výstupní ovladače + + + + Media settings + Nastavení médií + + + + Preferred audio and subtitles + Preferovaný jazyk filmu + + + + Video + Video + + + + Start videos in fullscreen + Spouštět videa v režimu celé obrazovky + + + + Disable screensaver + Zakázat spořič obrazovky + + + + Audio + Audio + + + + Select the mplayer executable + Výberte spustitelný soubor MPlayeru + + + + Executables + Spustitelné soubory + + + + All files + Všechny soubory + + + + Select a directory + Výberte adresář + + + + MPlayer executable + program MPlayer + + + + Here you must specify the mplayer executable that smplayer will use.<br>smplayer requires at least mplayer 1.0rc1 (svn recommended).<br><b>If this setting is wrong, smplayer won't be able to play anything!</b> + Zde musí být nastaven spustitelný soubor MPlayeru který SMplayer bude používat. <br> SMplayer potřebuje MPlayer alespoň ve verzi 1.0rc1 (doporučeno SVN). <br><b> Pokud bude tato položka špatně nastavena, SMplayer nebude moct nic přehrát!</b> + + + + Screenshots folder + Adresář snímků obrazovky + + + + Here you can specify a folder where the screenshots taken by smplayer will be stored. If this field is empty the screenshot feature will be disabled. + Zde můžete nastavit adresář do kterého se budou ukládat uložené snímky. Pokud není adresář nastaven, nebude tato funkce povolena. + + + + Video output driver + Ovladač videa + + + + Select the video output driver. Usually xv (linux) and directx (windows) provide the best performance. + Výběr výstupního video ovladače. Většinou xv (linux) a directx (windows) poskytují nejvyšší výkon. + + + + Audio output driver + Zvukový ovladač + + + + Select the audio output driver. + Výbberte výstupní audio ovladač. + + + + Remember settings + Pamatovat nastavení + + + + Usually smplayer will remember the settings for each file you play (audio track selected, volume, filters...). Uncheck this option if you don't like this feature. + Většinou si SMPlayer pamatuje nastavení pro každý přehrávaný soubor (volba zvukové stopy, hlasitost, filtry...). Zrušením této volby nebude tuto možnost používat. + + + + If you check this option, smplayer will play all files from the beginning. + Povolení této možnosti bude SMplayer přehrávat všechny soubory od začátku. + + + + Preferred audio language + Preferovaný jazyk zvukové stopy + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, smplayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Zde lze zvolit preferovaný jazyk audio stopy. Pokud je ve videu nalezeno více audio stop, SMPlayer zkusí použít tento jazyk. <br> Toto funguje pouze v případě že je v mediu přístupná informace o jazyce v audio stopě, jako jsou DVD nebo mkv soubory. <br> Toto políčko akceptuje regulární výrazy. Například: <b>es|esp|spa</b> bude vybírat audio stopu odpovídající <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + Preferred subtitle language + Preferovaný jazyk titulků + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, smplayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Zde lze zvolit preferovaný jazyk titulků. Pokud je ve videu nalezeno více titulků, SMPlayer zkusí použít tento jazyk. <br> Toto funguje pouze v případě že je v mediu přístupná informace o jazyce v titulcích, jako jsou DVD nebo mkv soubory. <br> Toto políčko akceptuje regulární výrazy. Například: <b>es|esp|spa</b> bude vybírat titulky odpovídající <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + Software video equalizer + Softwarový video ekvalizér + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Tuto možnost můžete využít pokud není video equalizér podporován vaší grafickou kartou nebo vybraným výstupním video ovladačem. <br><b>Poznámka:</b> tato možnost může být nekompatibilní s některýmy výstupními video ovladači. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Je-li zaškrtnuto, všechna videa budou přehrána v režimu celé obrazovky. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes.<br><b>Note:</b> This option works only in X11 and Windows. + Tato možnost zakáže šetřič obrazovky během přehrávání. <br> Šetřič obrazovky bude znovu povolen po ukončení přehrávání. <br><b> Poznámka: Toto lze použít pouze v systémech X11 a Windows. + + + + Software volume control + Softwarové nastavení hlasitosti + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Tato volba umožní použít softwarový mixér namísto mixéru zvukové karty. + + + + Postprocessing quality + Kvalita postprocessingu + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Dynamicky mění úroveň postprocessingu podle vytížení procesoru. Zadané číslo udává maximální úroveň, která může být použita. Většinou je možné zadat nějaké vysoké číslo. + + + + Change volume + Změnit hlasitost + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Je-li zaškrtnuto, SMPlayer si bude pamatovat hlasitost pro každý soubor a při opětovném přehrání ji obnoví. Pro nové soubory použije výchozí hlasitost. + + + + 0 + 0 + + + + &Change volume on every file + &Změnit hlasitost pro každý soubor + + + + Select the &MPlayer executable: + Zvolte spustitelný soubor &MPlayeru: + + + + &Folder for storing screenshots: + &Adresář pro ukládání snímků obrazovky: + + + + V&ideo: + O&braz: + + + + &Audio: + &Audio: + + + + &Remember settings for all files (audio track, subtitles...) + Pamat&ovat si nastavení pro všechny soubory (zvukové stopy, titulky...) + + + + Su&btitles: + T&itulky: + + + + &Quality: + &Kvalita: + + + + Start videos in &fullscreen + Spouštět videa v režimu celé &obrazovky + + + + Disable &screensaver + Zakázat &spořič obrazovky + + + + &Default volume: + &Výchozí hlasitost: + + + + Use s&oftware volume control + Používat s&oftwarové ovladání hlasitosti + + + + Ma&x. Amplification: + Ma&x. zesílení: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS pass-through S/PDIF + + + + Direct rendering + Direct rendering + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Je-li zaškrtnuto, zapne přímé vykreslování (není podporováno všemi kodeky a video výstupy)<br><b>VAROVÁNÍ:</b> Může způsobit deformaci OSD/titulků! + + + + Double buffering + Double buffering + + + + D&irect rendering + D&irect rendering + + + + Dou&ble buffering + Dou&ble buffering + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Dvojité bufferování řeší blikání obrazu ukládáním dvou snímků do paměti a zobrazovaním jednoho během dekodování dalšího. Je-li vypnuto, může negativně ovlivnit OSD, ale často odstraní blikání OSD. + + + + &Enable postprocessing by default + Implicitně zapnout postproc&essing + + + + Volume &normalization by default + Implicitně &normalizovat hlasitost + + + + Close when finished + Zavřít po skončení přehrávání + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Je-li tato volba zaškrtnuta, hlavní okno bude po dokončení přehrávání aktuálního souboru/playlistu automaticky zavřeno. + + + + &Close when finished + &Zavřít po dokončení přehrávání + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + Výc&hozích kanálů: + + + + &Pause when minimized + &Pozastavit při minimalizaci + + + + Pause when minimized + Pozastavit při minimalizaci + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, play will be resumed. + Pokuď je tato volba zapnuta, soubor bude pozastaven při skrytí hlavního okna. Až bude okno obnoveno, přehrávání bude pokračovat. + + + + Enable postprocessing by default + Implicitně zapnout postprocessing + + + + Max. Amplification + Max. zesílení + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Volume normalization by default + Implicitně normalizovat hlasitost + + + + Maximizes the volume without distorting the sound. + Zvýší hlasitost beze ztráty kvality zvuku. + + + + Default volume + Výchozí hlasitost + + + + Sets the initial volume that new files will use. + Nastaví počáteční hlasitost pro nově přehrávané soubory. + + + + Channels by default + Výchozích kanálů + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Nastaví maximální úroveň zesílení v procentech (výchozí: 110). Hodnota 200 dovoluje upravit hlasitost až na dvojnásobek aktuálního maxima. S hodnotami hlasitosti pod 100 (což je 100%), bude výchozí hlasitost nad maximem, což např. OSD nezobrazí správně. + + + + Uses hardware AC3 passthrough + Použije hardwarový AC3 výstup + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Zažádá o daný počet kanálů pro přehrávání. MPlayer požádá dekodér o použití tohoto počtu kanálů. Dekodér pak může, ale nemusí všechny kanály použít. Toto nastavení je většinou důležité pouze pro videa s AC3 stopou (DVD). V tom případě pak liba52 provádí dekódování a správně převede zvuk na požadovaný počet kanálů. POZNÁMKA: Toto nastavení respektují kodeky (pouze AC3), filtry (surround) a výstupní ovladače zvuku (minimálně OSS). + + + + Postprocessing will be used by default on new opened files. + Postprocessing bude implicitně použit na nově otevřené soubory. + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Zde můžete zadat preferovaný jazyk audio stopy nebo titulků. Pokud médium obsahuje více audio stop nebo titulků, SMPlayer zkusí zvolit preferované jazyky. Toto nastavení funguje pouze pro média, která poskytují informace o zvukových stopách a titulcích, jako DVD nebo soubory mkv.<br>Tato pole akceptují regulární výrazy. Příklad: <b>es|esp|spa</b> vybere stopu, pokud odpovídá jménu <i>es</i>, <i>esp</i> nebo <i>spa</i>. + + + + High speed playback without altering pitch + Rychlé přehrávání beze změny výšky zvuku + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Umožňuje rychlé přehrávání beze změny výšky tónu. Vyžaduje MPlayer verze dev-SVN-r24924 nebo vyšší. + + + + Audio track + Zvuková stopa + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Určuje, která zvuková stopa se má použít při přehrávání nových souborů. Pokud taková neexistuje, vybere se první.<br> <b>Poznámka:</b> <i>"preferovaný jazyk zvukové stopy"</i> má přednost před tímto nastavením. + + + + Subtitle track + Titulky + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Určuje, které titulky se mají použít při přehrávání nových souborů. Pokud takové neexistují, vyberou se první.<br> <b>Poznámka:</b> <i>"preferovaný jazyk titulků"</i> má přednost před tímto nastavením. + + + + High speed &playback without altering pitch + Rychlé &přehrávání beze změny výšky zvuku + + + + Preferre&d audio and subtitles + Preferovaný &jazyk filmu + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + . + + + + Preferred language: + Preferovaný jazyk: + + + + Audi&o: + Audi&o: + + + + &Subtitle: + &Titulky: + + + + Or choose a track number: + Nebo vyberte číslo stopy: + + + + Change volume just before playing + Změnit hlasitost před přehráváním + + + + &Video + &Video + + + + Use s&oftware video equalizer + Použít so&ftwarový ekvalizér videa + + + + A&udio + A&udio + + + + Volume + Hlasitost + + + + None + Vypnuto + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normální) + + + + Yadif (double framerate) + Yadif (dvojitý počet snímků) + + + + Linear Blend + Linear Blend + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Výchozí odstraně&ní prokládání: + + + + Deinterlace by default + Výchozí odstranění prokládání + + + + Select the deinterlace filter that you want to be used for new videos opened. + Vyberte filtr k odstranění prokládání, který se má použít pro nově otevřené soubory. + + + + Remember time position + Pamatovat si pozici filmu + + + + Remember &time position + Pamatova&t si pozici filmu + + + + Change volume just before p&laying + Změnit h&lasitost před přehráváním + + + + Enable the audio equalizer + Povolit audio-ekvalizér + + + + Check this option if you want to use the audio equalizer. + Zaškrtněte, pokud chcete použít audio-ekvalizér. + + + + &Enable the audio equalizer + Povolit audio-&ekvalizér + + + + Draw video using slices + Vykreslovat video pomocí proužků + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Zapne vykreslování videa pomocí proužků o výšce 16 pixelů. V opačném případě se vykreslí celý snímek najednou. Může to být rychlejší nebo pomalejší v závislosti na grafické kartě a vyrovnávací paměti. Toto nastavení má význam pouze ve spojitosti s libmpeg2 a libavcodec knihovnami. + + + + Dra&w video using slices + Vy&kreslovat video pomocí proužků + + + + &Close when finished playback + &Zavřít po skončení přehrávání + + + + fast + rychlý + + + + slow + pomalý + + + + fast - ATI cards + rychlý - ATi karty + + + + User defined... + Vlastní... + + + + Default zoom + Výchozí zoom + + + + This option sets the default zoom which will be used for new videos. + Toto nastavení určuje výchozí zoom pro nová videa. + + + + Default &zoom: + Výchozí &zoom: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Zde zadejte, který MPlayer má SMPlayer použít.<br> SMPlayer potřebuje minimálně MPlayer 1.0rc1 (dostatečně nová verze z SVN je vysoce doporučována). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Pokud je toto nastavení chybné, SMPlayer nic nepřehraje! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Zde můžete nastavit adresář pro uložení snímků obrazovky pořízené SMPlayerem. Pokud necháte pole prázdné, pořizování snímků bude vypnuto. + + + + Select the video output driver. %1 provides the best performance. + Vyberte výstupní ovladač videa. %1 poskytuje nejlepší výkon. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + Doporučujeme ovladač %1. Vyhněte se %2 a %3, jsou pomalé a mohou mít dopad na výkon. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + SMPlayer si může pamatovat nastavení pro každý soubor, který přehráváte (vybraná audio stopa, hlasitost, filtry, ...). Odškrtněte tuto volbu, pokud to není žádoucí. + + + + If you check this option, SMPlayer will play all files from the beginning. + Je-li tato volba zaškrtnuna, SMPlayer přehrává všechny soubory od počátku. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Je-li tato položka zaškrtnuta, přehrávání bude pozastaveno, pokud se hlavní okno minimalizuje. Při obnovení okna se přehrávání opět pustí. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Zaškrtněte tuto položku a spořič obrazovky bude zakázán po dobu přehrávání.<br> Spořič bude opět povolen po skončení přehrávání. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Zde můžete zadat preferovaný jazyk audio stopy. Pokud médium obsahuje více audio stop, SMPlayer zkusí zvolit preferované jazyky. Toto nastavení funguje pouze pro média, která poskytují informace o zvukových stopách, jako DVD nebo soubory mkv.<br>Toto pole akceptuje regulární výrazy. Příklad: <b>es|esp|spa</b> vybere stopu, pokud odpovídá jménu <i>es</i>, <i>esp</i> nebo <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Zde můžete zadat preferovaný jazyk titulků. Pokud médium obsahuje více titulků, SMPlayer zkusí zvolit preferované jazyky. Toto nastavení funguje pouze pro média, která poskytují informace o titulcích, jako DVD nebo soubory mkv.<br>Toto pole akceptuje regulární výrazy. Příklad: <b>es|esp|spa</b> vybere stopu, pokud odpovídá jménu <i>es</i>, <i>esp</i> nebo <i>spa</i>. + + + + Ou&tput driver: + Výs&tupní ovladač: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Je-li toto nastavení zapnuto, výchozí hlasitost se nastaví před přehráváním. Takto lze předejít vysoké hlasitosti při startu. Vyžaduje minimálně MPlayer SVN r27872. + + + + Add black borders on fullscreen + Přidat černé okraje v režimu celé obrazovky + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Je-li tato položka zaškrtnuta, v režimu celé obrazovky se k filmu přidají černé okraje. To umožňuje zobrazovat titulky v těchto okrajích namísto ve filmu. + + + + &Add black borders on fullscreen + Přid&at černé okraje v režimu celé obrazovky + + + + one ini file + v jednom ini souboru + + + + multiple ini files + ve více ini souborech + + + + Method to store the file settings + Metoda uložení nastavení souborů + + + + This option allows to change the way the file settings would be stored. The following options are available: + Toto nastavení ovlivňuje typ ukládání nastavení souborů. Je možné použít následující možnosti: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>jeden ini soubor</b>: nastavení všech souborů bude uloženo v jediném ini souboru (%1) + + + + The latter method could be faster if there is info for a lot of files. + Druhá metoda může být rychlejší, pokud se nejedná o mnoho souborů. + + + + &Store settings in + Uložit na&stavení + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>více souborů</b>: jeden ini soubor bude použit pro každý z přehraných souborů. Tyto soubory budou uloženy v adresáři %1 + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + Zaškrtnete-li tuto volbu, SMPlayer si uloží pozici naposledy otevřeného souboru a při dalším otevření od ní začne. Funguje pouze pro běžné soubory (nikoli DVD, CD, URL, ...). + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + Je-li zaškrtnuto, zapne přímé vykreslování (není podporováno všemi kodeky a video výstupy)<br><b>Varování:</b> Může způsobit deformaci OSD/titulků! + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Zažádá o daný počet kanálů pro přehrávání. MPlayer požádá dekodér o použití tohoto počtu kanálů. Dekodér pak může, ale nemusí všechny kanály použít. Toto nastavení je většinou důležité pouze pro videa s AC3 stopou (DVD). V tom případě pak liba52 provádí dekódování a správně převede zvuk na požadovaný počet kanálů. <b>Poznámka:</b> Toto nastavení respektují kodeky (pouze AC3), filtry (surround) a výstupní ovladače zvuku (minimálně OSS). + + + + PrefInput + + + Keyboard and mouse + Klávesnice a myš + + + + &Keyboard + &Klávesnice + + + + icon + ikona + + + + &Mouse + &Myš + + + + Button functions: + Funkce tlačítek: + + + + Media seeking + Seekování média + + + + Volume control + Ovládání hlasitosti + + + + Zoom video + Přiblížit video + + + + None + Žádná + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Zde můžete změnit každou klávesovou zkratku. Pro změnu dvakrát klikněte nebo stiskněte enter nad buňkou zkratky. Také můžete seznam uložit a sdílet ho s ostatními lidmi nebo ho načíst v jiném počítači. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Zde můžete změnit každou klávesovou zkratku. Pro změnu dvakrát klikněte nebo začněte psát nad buňkou zkratky. Také můžete seznam uložit a sdílet ho s ostatními lidmi nebo ho načíst v jiném počítači. + + + + &Left click + &Levý klik + + + + &Double click + &Dvojitý klik + + + + &Wheel function: + &Funkce kolečka: + + + + Shortcut editor + Editor zkratek + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Tato tabulka dovoluje změnit klávesové zkratky pro většinu dostupných akcí. Dvojitím kliknutím, stisknutím enter na položce nebo stisknutím <b>Změnit zkratku</b> otevřete dialog <i>Upravit zkratku</i>. Existují dvě cesty jak změnit zkratku: je-li tlačítko <b>Zaznamenat</b> v stisknutém stavu, stiskněte kombinaci kláves, kterou chcete přiřadit dané akci (bohužel nefunguje pro všechny klávesy). Není-li tlačítko <b>Zaznamenat</b> stisknuté, můžete zadat celé jméno klávesy. + + + + Left click + Levý klik + + + + Select the action for left click on the mouse. + Zvolte akci pro levý klik myši. + + + + Double click + Dvojitý klik + + + + Select the action for double click on the mouse. + Zvolte akci pro dvojitý klik myši. + + + + Wheel function + Funkce kolečka + + + + Select the action for the mouse wheel. + Zvolte akci pro kolečko myši. + + + + Play + Přehrát + + + + Play / Pause + Přehrát / Pozastavit + + + + Pause + Pozastavit + + + + Pause / Frame step + Pozastavit / Krokovat snímky + + + + Stop + Zastavit + + + + Fullscreen + Celá obrazovka + + + + Compact + Kompaktní mód + + + + Screenshot + Snímek obrazovky + + + + On top + Vždy nahoře + + + + Mute + Ztlumit + + + + Playlist + Playlist + + + + Frame counter + Počítadlo snímků + + + + Preferences + Nastavení + + + + Reset zoom + Základní zoom + + + + Exit fullscreen + Ukončit režim celé obrazovky + + + + Double size + Dvojitá velikost + + + + No function + Bez funkce + + + + Change speed + Změnit rychlost + + + + Normal speed + Normální rychlost + + + + Keyboard + Klávesnice + + + + Mouse + Myš + + + + Middle click + Střední klik + + + + Select the action for middle click on the mouse. + Zvolte akci pro střední klik myši. + + + + M&iddle click + Střední kl&ik + + + + X Button &1 + Tlačítko X &1 + + + + X Button &2 + Tlačítko X &2 + + + + Go backward (short) + Jít zpět (krátce) + + + + Go backward (medium) + Jít zpět (středně) + + + + Go backward (long) + Jít zpět (dlouze) + + + + Go forward (short) + Jít vpřed (krátce) + + + + Go forward (medium) + Jít vpřed (středně) + + + + Go forward (long) + Jít vpřed (dlouze) + + + + OSD - Next level + OSD - Další zobrazení + + + + Show context menu + Zobrazit kontextové menu + + + + &Right click + P&ravý klik + + + + Increase volume + Zvýšit hlasitost + + + + Decrease volume + Snížit hlasitost + + + + X Button 1 + Tlačítko X 1 + + + + Select the action for the X button 1. + Zvolte akci pro tlačítko X 1. + + + + X Button 2 + Tlačítko X 2 + + + + Select the action for the X button 2. + Zvolte akci pro tlačítko X 2. + + + + Show video equalizer + Zobrazit video-ekvalizér + + + + Show audio equalizer + Zobrazit audio-ekvalizér + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Rozhraní + + + + <Autodetect> + <Detekovat> + + + + Default + Výchozí + + + + &Interface + &Rozhraní + + + + Seeking + Seekování + + + + Never + Nikdy + + + + Whenever it's needed + Kdykoli je potřeba + + + + Only after loading a new video + Pouze při načítání nového videa + + + + Recent files + Nedávné soubory + + + + Language + Jazyk + + + + Here you can change the language of the application. + Zde můžete změnit jazyk aplikace. + + + + Instances + Instance + + + + &Short jump + &Krátký skok + + + + &Medium jump + Stř&ední skok + + + + &Long jump + D&louhý skok + + + + Mouse &wheel jump + Skok &kolečka myši + + + + &Use only one running instance of SMPlayer + Po&užívat pouze jednu běžící instanci SMPlayeru + + + + Ma&x. items + Ma&x. počet položek + + + + St&yle: + St&yl: + + + + Ico&n set: + Sada iko&n: + + + + L&anguage: + J&azyk: + + + + Main window + Hlavní okno + + + + Auto&resize: + Automaticky změnit &velikost: + + + + R&emember position and size + Zapamatovat pozici a v&elikost + + + + Default font: + Výchozí font: + + + + &Change... + &Změnit... + + + + &Behaviour of time slider: + &Chování posuvníku: + + + + Seek to position while dragging + Jdi na pozici při přesouvání + + + + Seek to position when released + Jdi na pozici po puštění + + + + TextLabel + TextLabel + + + + &Seeking + &Seekování + + + + Ins&tances + Ins&tance + + + + Autoresize + Automatická změna velikosti + + + + The main window can be resized automatically. Select the option you prefer. + Hlavní okno se může samo roztahovat. Vyberte nastavení, které preferujete. + + + + Remember position and size + Zapamatovat si pozici a velikost + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Zaškrtnete-li tuto možnost, pozice a velikost hlavního okna se uloží a aplikuje při příštím spuštění SMPlayeru. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Vyberte maximální počet položek, které se zobrazí v nabídce <b>Otevřít -> Nedávné soubory</b>. Nastavíte-li hodnotu na 0, nabídka se nezobrazí. + + + + Icon set + Sada ikon + + + + Select the icon set you prefer for the application. + Vyberte sadu ikon, které preferujete. + + + + Style + Styl + + + + Select the style you prefer for the application. + Vyberte styl, který preferujete. + + + + Default font + Výchozí font + + + + You can change here the application's font. + Zde můžete změnit font aplikace. + + + + Short jump + Krátký skok + + + + Select the time that should be go forward or backward when you choose the %1 action. + Vyberte velikost skoku dopředu nebo dozadu, vyberete-li akci %1. + + + + short jump + krátký skok + + + + Medium jump + Střední skok + + + + medium jump + střední skok + + + + Long jump + Dlouhý skok + + + + long jump + dlouhý skok + + + + Mouse wheel jump + Skok kolečka myši + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Vyberte velikost skoku dopředu nebo dozadu, vyberete-li akci pro kolečko myši. + + + + Behaviour of time slider + Chování posuvníku + + + + Select what to do when dragging the time slider. + Zvolte chování při použití posuvníku. + + + + Use only one running instance of SMPlayer + Používat pouze jednu běžící instanci SMPlayeru + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Zaškrtněte tuto možnost, chcete-li použít již běžící instanci SMPlayeru pro otevření dalšího souboru. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer poslouchá na daném portu, aby mohl komunikovat s ostatními instancemi. Můžete nastavit číslo portu, pokud je již obsazen. + + + + Default GUI + Výchozí GUI + + + + Mini GUI + Mini GUI + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Vyberte GUI, které preferujete. V současnosti existují dvě: Výchozí GUI a Mini GUI.<br><b>Výchozí GUI</b> poskytuje tradiční GUI s ovládacími panely a prvky. <b>Mini GUI</b> poskytuje jednodušší GUI bez ovládacích panelů a prvků, pouze s několika tlačítky.<br><b>Poznámka:</b> toto nastavení se projeví při příštím spuštění SMPlayeru. + + + + &GUI + &GUI + + + + Automatic port + Automaticky nastavený port + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer poslouchá na daném portu, aby mohl komunikovat s ostatními instancemi. Vyberete-li tuto možnost, port bude zvolen automaticky. + + + + Manual port + Manuálně nastavený port + + + + Port to listen + Naslouchat na portu + + + + &Automatic + &Automaticky + + + + &Manual + &Manuálně + + + + Floating control + Plovoucí ovládání + + + + Animated + Animovat + + + + If this option is enabled, the floating control will appear with an animation. + Je-li tato možnost povolena, plovoucí ovládání se vysune s animací. + + + + Width + Šířka + + + + Specifies the width of the control (as a percentage). + Určuje šířku ovládacího prvku (v procentech). + + + + Margin + Odstup + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + Toto nastavení určuje počet pixelů mezi plovoucím ovládáním a spodním okrajem obrazovky. Vhodné, pokud se jedná o TV obrazovku, jelikož overscan může ořezat ovládací prvky. + + + + Display in compact mode too + Zobrazit i v kompaktním módu + + + + If this option is enabled, the floating control will appear in compact mode too. Warning: the floating control has not been designed for compact mode and it might not work properly. + Je-li tato možnost zaškrtnuta, plovoucí ovládání bude zobrazeno také v kompaktním módu. Varování: plovoucí ovládání není primárně určeno pro kompaktní mód a nemusí pracovat správně. + + + + Bypass window manager + Obejít správce oken + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + Je-li tato možnost zaškrtnuta, plovoucí ovládání obejde správce oken. Použijte, pokud má plovoucí ovládání problém se správcem oken. + + + + &Floating control + &Plovoucí ovládání + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + Plovoucí ovládání se objeví v režimu celé obrazovky, posunete-li kurzor myši ke spodnímu okraji obrazovky. + + + + &Animated + A&nimovat + + + + &Width: + Šířk&a: + + + + 0 + 0 + + + + &Margin: + &Odstup: + + + + Display in &compact mode too + Zobrazit také v &kompaktním módu + + + + &Bypass window manager + Obejít sp&rávce oken + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + Je-li tato možnost zaškrtnuta, plovoucí ovládání bude zobrazeno také v kompaktním módu. <b>Varování:</b> plovoucí ovládání není primárně určeno pro kompaktní mód a nemusí pracovat správně. + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Výkon + + + + &Performance + &Výkon + + + + Priority + Priorita + + + + Select the priority for the MPlayer process. + Zvolte prioritu pro proces MPlayeru. + + + + realtime + reálný čas + + + + high + vysoká + + + + abovenormal + vyšší + + + + normal + normální + + + + belownormal + nižší + + + + idle + nízká + + + + Cache + Cache + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Nastavením vyrovnávací paměti lze zvýšit výkon přehrávání z pomalých médií + + + + Allow frame drop + Povolit vypuštění snímku + + + + Synchronization + Synchronizace + + + + Audio/video auto synchronization + Automatická synchronizace zvuku a obrazu + + + + Fast audio track switching + Rychlé přepínání audio stop + + + + Fast seek to chapters in dvds + Rychlé přeskakování kapitol u DVD + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Nastavení priority pro proces MPlayeru pod Windows .<br><b>VAROVÁNÍ:</b> Použití priority reálného času může způsobit zablokování systému. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Přeskočí zobrazování některých snímků potřebných pro A/V synchronizaci na pomalých systémech. + + + + Allow hard frame drop + Povolit tvrdé vypuštění snímku + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Intenzivnější vypouštění snímků (přeruší dekódování). Způsobuje zkreslení obrazu! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Postupně mění A/V synchronizaci podle zpoždění zvuku. + + + + Priorit&y: + Priorit&a: + + + + &Allow frame drop + Povolit &vypuštění snímku + + + + Allow &hard frame drop (can lead to image distortion) + Povolit &tvrdé vypuštění snímku (může vést ke zkreslení obrazu) + + + + Audio/&video auto synchronization + Automatická synchronizace &zvuku a obrazu + + + + Fact&or: + Fakt&or: + + + + &Fast audio track switching + &Rychlé přepínání zvukových stop + + + + Fast &seek to chapters in dvds + Rychlé &přepínání kapitol na DVD + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Je-li zaškrtnuto, použije se nejrychlejší metoda přepínání kapitol, ale nemusí správně fungovat pro všechny disky. + + + + Skip loop filter + Přeskočit filtr smyček + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Možné hodnoty:<br> <b>Ano</b>: použije nejrychlejší metodu přepínání zvukových stop (nemusí fungovat se všemi formáty).<br> <b>Ne</b>: MPlayer se restartuje při každé změně zvukové stopy.<br> <b>Auto</b>: SMPlayer určí metodu podle verze MPlayeru. + + + + Cache for files + Cache pro soubory + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Určuje, kolik paměti (v kB) se použije pro dopředné čtení souborů. + + + + Cache for streams + Cache pro streamy + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Určuje, kolik paměti (v kB) se použije pro dopředné čtení URL. + + + + Cache for DVDs + Cache pro DVD + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Určuje, kolik paměti (v kB) se použije pro dopředné čtení DVD.<br> <b>Varování:</b> Posouvání (včetně přepínání kapitol) nemusí fungovat správně. + + + + H.264 + H.264 + + + + &Cache + &Cache + + + + Cache for &DVDs: + Cache pro &DVD: + + + + Cache for &local files: + Cache pro s&oubory: + + + + Cache for &streams: + Cache pro &streamy: + + + + Enabled + Povolen + + + + Skip (always) + Přeskočit (vždy) + + + + Skip only on HD videos + Přeskočit u HD videí + + + + Loop &filter + &Filtr smyček + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Toto nastavení umožňuje přeskočit filtr smyčky (loop filter, deblocking) při přehrávání H.264. Jelikož filtrované snímky se používají jako reference pro další závislé snímky, má tato možnost vyšší doapd na kvalitu než např. u MPEG-2. Ale dosáhne se tak mnohem vyšší propustnosti HDTV videa za poměrně malého snížení kvality. + + + + Possible values: + Možné hodnoty: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Povolen</b>: filtr smyčky se nebude přeskakovat + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Přeskočit (vždy)</b>: filtr smyčky se přeskočí při jakémkoli rozlišení videa + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Přeskočit u HD videí</b>: filtr smyčky se přeskočí pouze u videí, jejichž výška přesáhne %1. + + + + Cache for audio CDs + Cache pro audio CD + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Určuje, kolik paměti (v kB) se použije pro dopředné čtení audio CD. + + + + Cache for &audio CDs: + Cache pro &audio CD: + + + + Cache for VCDs + Cache pro VCD + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Určuje, kolik paměti (v kB) se použije pro dopředné čtení VCD. + + + + Cache for &VCDs: + Cache pro &VCD: + + + + Threads for decoding + Počet vláken pro dekódování + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Nastavte počet vláken pro dekódování. Pouze pro MPEG-1/2 a H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + Počet v&láken pro dekódování (pouze MPEG-1/2 a H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + Nastavení priority pro proces MPlayeru pod Windows .<br><b>Varování:</b> Použití priority reálného času může způsobit zablokování systému. + + + + PrefPlaylist + + + Playlist + Playlist + + + + Automatically add files to playlist + Automaticky přidávat soubory + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Je-li tato položka zaškrtnuta, při každém otevření souboru se playlist smaže a daný soubor se do něj přidá. V případě DVD, CD a VCD se do playlistu přidají všechny tituly na daném disku. + + + + Add consecutive files + Přidávat sekvence souborů + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Je-li tato položka zaškrtnuta, SMPlayer vyhledá sekvence souborů (např. video_1.avi, video_2.avi, ...) a najde-li nějakou, přidá ji do playlistu. + + + + &Playlist + &Playlist + + + + &Automatically add files to playlist + &Automaticky přidávat soubory + + + + Add &consecutive files + Přidávat sekven&ce souborů + + + + PrefSubtitles + + + Subtitles + Titulky + + + + Choose a ttf file + Vyberte ttf soubor + + + + Truetype Fonts + Fonty TrueType + + + + &Subtitles + &Titulky + + + + Autoload + Automatické načítání + + + + Same name as movie + Stejný název jako videosoubor + + + + All subs containing movie name + Všechny titulky obsahující název videosouboru + + + + All subs in directory + Všechny titulky v adresáři + + + + Position + Pozice + + + + 0 + 0 + + + + Top + Nahoře + + + + Bottom + Dole + + + + Include subtitles on screenshots + Ponechat titulky ve snímcích obrazovky + + + + &Font + &Písmo + + + + Font + Font + + + + Select the font which will be used for subtitles (and OSD): + Výberte font, který bude použit pro titulky (a OSD): + + + + Size + Velikost + + + + No autoscale + Neměnit + + + + Proportional to movie height + Podle výšky obrazu + + + + Proportional to movie width + Podle šířky obrazu + + + + Proportional to movie diagonal + Podle úhlopříčky obrazu + + + + The new SSA/ASS library will provide nice styled subtitles for external SSA/ASS subtitles files and Matroska tracks. But it will be used too for rendering other formats like SUB and SRT files. + Nová SSA/ASS knihovna poskytuje pěkný styl titulků pro externí SSA/ASS soubory titulků a Matroska stopy. Bude také ovšem použita pro zobrazování ostatních formátů souborů jako SUB a SRT. + + + + Use SSA/ASS library for subtitle rendering + Použít SSA/ASS knihovnu pro renderování titulků + + + + Here you can override styles for SSA/ASS subtitles. It can be also used for fine-tuning the rendering of SRT and SUB subtitles by the SSA/ASS library. Example: <b>Bold=1,Outline=2,Shadow=4</b> + Zde můžete přepsat styly pro SSA/ASS titulky. Také to může být použito pro doladění zobrazování titulků SRT a SUB s SSA/ASS knihovnou. Příklad: <b>Tlusté=1,Podtržené=2,Stínované=4</b> + + + + Subtitle position + Pozice titulků + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Tato možnost určuje pozici titulků v okně s videem. Hodnota <i>100</i> znamená úplně dole a hodnota <i>0</i> znamená úplně nahoře. + + + + SSA/ASS styles + Styly SSA/ASS + + + + Au&toload subtitles files (*.srt, *.sub...): + Au&tomaticky načítat titulky (*.srt, *.sub, ...): + + + + S&elect first available subtitle + Zvolit první d&ostupné titulky + + + + &Default subtitle encoding: + Výchozí kó&dování titulků: + + + + Default &position of the subtitles on screen + Výchozí &pozice titulků na obrazovce + + + + &Include subtitles on screenshots + Ponechat t&itulky ve snímcích obrazovky + + + + &TTF font: + Font &TTF: + + + + S&ystem font: + S&ystémový font: + + + + A&utoscale: + A&utomaticky měnit: + + + + &Use SSA/ASS library for subtitle rendering + Po&užít SSA/ASS knihovnu pro zobrazení titulků + + + + &Text color: + Barva &textu: + + + + &Border color: + &Barva okrajů: + + + + St&yles: + St&yly: + + + + Select first available subtitle + Zvolit první dostupné titulky + + + + Default subtitle encoding + Výchozí kódování titulků + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Je-li tato možnost zaškrtnuta, titulky se objeví také ve snímcích obrazovky. Poznámka: někdy může způsobit problémy. + + + + TTF font + Font TTF + + + + System font + Systémový font + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Zde můžete nastavit systémový font pro vykreslení titulků a OSD. <b>Poznámka:</b> vyžaduje MPlayer s podporou fontconfig. + + + + Autoscale + Velikost + + + + Text color + Barva textu + + + + Select the color for the text of the subtitles. + Vyberte barvu písma titulků. + + + + Border color + Barva okraje + + + + Select the color for the border of the subtitles. + Vyberte barvu okraje písma titulků. + + + + Select the subtitle autoload method. + Vyberte typ automatického načítání titulků. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Je-li dostupno více titulků, vyberou se první z nich. Pokud je ovšem upřednostňován nějaký jazyk titulků zkusí se vybrat tento. + + + + Select the subtitle autoscaling method. + Vyberte metodu automatického zvětšování titulků. + + + + Select the encoding which will be used for subtitle files by default. + Vyberte výchozí kódování pro zobrazení titulků. + + + + Try to autodetect for this language + Detekovat kódování pro daný jazyk + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Je-li tato možnost zaškrtnuta, kódování titulků se pro daný jazyk detekuje. Nepovede-li se určit kódování, použije se výchozí nastavení. Toto funguje pouze pro MPlayer přeložený s podporou ENCA. + + + + Subtitle language + Jazyk titulků + + + + Select the language for which you want the encoding to be guessed automatically. + Vyberte jazyk, pro který se má detekovat kódování. + + + + Encoding + Kódování + + + + Try to a&utodetect for this language: + Detekovat &kódování pro daný jazyk: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Zde můžete nastavit ttf font pro vykreslení titulků. Tyto fonty by měly být v %1 + + + + Outline + Okraj + + + + Select the font for the subtitles. + Vyberte font pro titulky. + + + + The size in pixels. + Velikost v pixelech. + + + + Bold + Tučně + + + + If checked, the text will be displayed in <b>bold</b>. + Je-li zaškrtnuto, text bude zobrazen <b>tučně</b>. + + + + Italic + Kurzívou + + + + If checked, the text will be displayed in <i>italic</i>. + Je-li zaškrtnuto, text bude zobrazen <i>kurzívou</i>. + + + + Left margin + Levý okraj + + + + Specifies the left margin in pixels. + Určuje odstup od levého okraje v pixelech. + + + + Right margin + Pravý okraj + + + + Specifies the right margin in pixels. + Určuje odstup od pravého okraje v pixelech. + + + + Vertical margin + Svislé okraje + + + + Specifies the vertical margin in pixels. + Určuje vertikální odstup v pixelech. + + + + Horizontal alignment + Vodorovné zarovnání + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + Určuje vodorovné zarovnání. Možné hodnoty jsou doleva, na střed a doprava. + + + + Vertical alignment + Svislé zarovnání + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + Určuje svislé zarovnání. Možné hodnoty jsou: dolů, na střed a nahoru. + + + + Border style + Styl okraje + + + + Specifies the border style. Possible values: outline and opaque box. + Určuje styl okraje. Možné hodnoty: obrys a podklad. + + + + Shadow + Stín + + + + Si&ze: + Ve&likost: + + + + Bol&d + Tuč&ně + + + + &Italic + &Kurzívou + + + + Colors + Barvy + + + + &Text: + &Text: + + + + &Border: + &Okraje: + + + + Margins + Odstupy + + + + L&eft: + L&evý: + + + + &Right: + P&ravý: + + + + Verti&cal: + Vert&ikální: + + + + Alignment + Zarovnání + + + + &Horizontal: + &Horizontálně: + + + + &Vertical: + &Vertikálně: + + + + Border st&yle: + St&yl okrajů: + + + + &Outline: + O&brys: + + + + Shado&w: + &Stín: + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + Následující nastavení ovlivňuje vykreslování nestylovaných titulků (srt, sub, ...). + + + + Left + horizontal alignment + Doleva + + + + Centered + horizontal alignment + Na střed + + + + Right + horizontal alignment + Doprava + + + + Bottom + vertical alignment + Dolů + + + + Middle + vertical alignment + Na střed + + + + Top + vertical alignment + Nahoru + + + + Outline + border style + Obrys + + + + Opaque box + border style + Podklad + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + Je-li styl okraje nastaven na <i>obrys</i>, toto nastavení ovlivní jeho šířku (v pixelech). + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + Je-li styl okraje nastaven na <i>obrys</i>, toto nastavení ovlivní hloubku vrženého stínu (v pixelech). + + + + Enable normal subtitles + Použít normální titulky + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + Stiskněte toto tlačítko pro použití normálních/tradičních titulků. Takové titulky se zobrazují pouze bílou barvou. + + + + Enable SSA/ASS subtitles + Použít SSA/ASS titulky + + + + Normal subtitles + Normální titulky + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + Toto nastavení NEZMĚNÍ velikost titulků v právě běžícím videu. K tomu je potřeba použít tlačítka <i>Velikost+</i> a <i>Velikost-</i> v menu Titulky. + + + + Default scale + Výchozí měřítko + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + Toto nastavení ovlivní výchozí velikost normálních titulků, která se použije pro nově otevřené soubory. + + + + SSA/ASS subtitles + SSA/ASS titulky + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + Toto nastavení ovlivňuje výchozí velikost písma pro SSA/ASS titulky, které se použije pro nově otevřené soubory. + + + + Line spacing + Prokládání řádků + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + Tato hodnota určuje vzdálenost mezi jednotlivými řádky titulků. Můžete zadat i zápornou hodnotu. + + + + &Font and colors + &Písmo a barvy + + + + Enable &normal subtitles + Použít nor&mální titulky + + + + Enable SSA/&ASS subtitles + Použít SSA/&ASS titulky + + + + Default s&cale: + Výchozí v&elikost: + + + + Defa&ult scale: + Výchozí v&elikost: + + + + &Line spacing: + Prok&ládání řádků: + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + Stiskněte toto tlačítko pro použití SSA/ASS titulků. Takové titulky je možné vykreslit danou abrvou nebo písmem... + + + + Freetype support + Podpora freetype + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + Tato volba by většinou měla zůstat povolena. Použijte ji pouze v případě, že je MPlayer přeložen s podporou freetype. <b>Zakázáním této položky mohou titulky přestat fungovat!</b> + + + + Freet&ype support + Podpora freet&ype + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + Je-li tato možnost zaškrtnuta, titulky se objeví také ve snímcích obrazovky. <b>Poznámka:</b> někdy může způsobit problémy. + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Nápověda + + + + OK + OK + + + + Cancel + Storno + + + + Apply + Použít + + + + Help + Nápověda + + + + SMPlayer - Preferences + SMPlayer - Nastavení + + + + QObject + + + 1 second + 1 sekunda + + + + %1 seconds + %1 sekund + + + + 1 minute + 1 minuta + + + + 1 minute and 1 second + 1 minuta a 1 sekunda + + + + 1 minute and %1 seconds + 1 minuta a %1 sekund + + + + %1 minutes + %1 minut + + + + %1 minutes and 1 second + %1 minut a 1 sekunda + + + + %1 minutes and %2 seconds + %1 minut and %2 sekund + + + + will show this message and then will exit. + zobrazí tuto zprávu a skončí. + + + + the main window will be closed when the file/playlist finishes. + po skončení přehrávání se hlavní okno ukončí. + + + + This is SMPlayer v. %1 running on %2 + Tohle je SMPlayer v. %1 běžící na systému %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + pokusí se připojit k další běžící instanci a poslat zadanou akci. Příklad: -send-action pause. Další příkazy (jsou-li zadány) se ignorují a aplikace se ukončí. Návratová hodnota je 0 při správném ukončení a -1 při chybě. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + seznam_akcí je seznam akcí oddělených mezerami. Akce budou spuštěny ihned po načtení souboru (je-li zadán) ve stejném pořadí, jako byly zadány. Pro akce se stavem je možné přidat parametr true nebo false. Příklad: -actions "fullscreen compact true". Ubozovky jsou nezbytné tehdy, chcete-li zadat více akcí. + + + + media + média + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + běží-li již další instance, médium bude přidáno do playlistu této instance. Pokud žádná jiná instance neběží, parametr bude ignorován a soubory budou otevřeny v instanci nové. + + + + specifies the directory for the configuration file (smplayer.ini). + specifikuje adresář, kde je uložen konfigurační soubor (smplayer.ini). + + + + the main window won't be closed when the file/playlist finishes. + hlavní okno nebude zavřeno při ukončení přehrávání souboru/playlistu. + + + + the video will be played in fullscreen mode. + video se bude přehrávat v režimu celé obrazovky. + + + + the video will be played in window mode. + video se bude přehrávat v okně. + + + + opens the mini gui instead of the default one. + použije Mini GUI namísto výchozího. + + + + Enqueue in SMPlayer + Zařadit do SMPlayeru + + + + Restores the old associations and cleans up the registry. + Obnoví původní přiřazení a vyčistí registry. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'média' jsou jakýkoli soubor, který SMPlayer umí otevřít. Může to být soubor na disku, DVD (např. dvd://1), internetový stream (např. mms://...) nebo playlist ve formátu m3u nebo pls. Použijete-li parametr -playlist, SMPlayer přepošle tento parametr MPlayeru, který se o playlist postará sám (playlist se tak nedostane do SMPlayeru). + + + + Usage: + Použití: + + + + directory + adresář + + + + action_name + jméno_akce + + + + action_list + seznam_akcí + + + + opens the default gui. + použije výchozí GUI. + + + + subtitle_file + soubor_s_titulky + + + + specifies the subtitle file to be loaded for the first video. + určuje, který soubor s titulky se má použít pro přehrávané video. + + + + %1 second(s) + + %1 sekunda + %1 sekundy + %1 sekund + + + + + %1 minute(s) + + %1 minuta + %1 minuty + %1 minut + + + + + %1 and %2 + %1 a %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + určuje adresář, kam si má SMPlayer ukládat nastavení (smplayer.ini, smplayer_files.ini, ...) + + + + disabled + aspect_ratio + vypnuto + + + + auto + aspect_ratio + auto + + + + unknown + aspect_ratio + neznámý + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + chyba API ZIPu/UNZIPu č. %1 + + + + SeekWidget + + + icon + ikona + + + + label + popis + + + + ShortcutGetter + + + Modify shortcut + Změnit zkratku + + + + Clear + Smazat + + + + Press the key combination you want to assign + Stiskněte kombinaci kláves, kterou chcete přiřadit + + + + Capture + Zaznamenat + + + + Capture keystrokes + Zaznamenat stisky kláves + + + + SubChooserDialog + + + Subtitle selection + Výběr titulků + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Tento archiv obsahuje více titulků. Vyberte, které chcete extrahovat. + + + + Select All + Vybrat všechny + + + + Select None + Nevybrat žádné + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Pozice + + + + &Jump to: + &Jdi na: + + + + TristateCombo + + + Auto + Auto + + + + Yes + Ano + + + + No + Ne + + + + VideoEqualizer + + + Contrast + Kontrast + + + + Brightness + Jas + + + + Hue + Odstín + + + + Saturation + Sytost + + + + Gamma + Gamma + + + + &Reset + &Vynulovat + + + + &Set as default values + &Nastavit jako výchozí hodnoty + + + + Use the current values as default values for new videos. + Použít stávající hodnoty jako výchozí pro nová videa. + + + + Set all controls to zero. + Nastavit všechny ovládací prvky na nulu. + + + + Video Equalizer + Video-ekvalizér + + + + Information + Informace + + + + The current values have been stored to be used as default. + Aktuální hodnoty byly uloženy jako výchozí. + + + + VideoPreview + + + Video preview + Náhled na video + + + + Cancel + Storno + + + + Generated by SMPlayer + Vytvořeno SMPlayerem + + + + Creating thumbnails... + Vytvářím miniatury... + + + + File: %1 + Soubor: %1 + + + + Size: %1 MB + Velikost: %1 MB + + + + Resolution: %1 x %2 + Rozlišení: %1 x %2 + + + + Length: %1 + Délka: %1 + + + + Save file + Uložit do souboru + + + + Images (*.png *.jpg) + Obrázky (*.png *.jpg) + + + + Error saving file + Chyba při ukládání souboru + + + + The file couldn't be saved + Tento soubor nemůže být uložen + + + + Error + Chyba + + + + The following error has occurred while creating the thumbnails: + Při vytváření miniatur došlo k následující chybě: + + + + The temporary directory (%1) can't be created + Nelze vytvořit dočasný adresář (%1) + + + + The mplayer process didn't run + Nešlo spustit MPlayer + + + + Resolution: %1x%2 + Rozlišení: %1x%2 + + + + Video format: %1 + Formát videa: %1 + + + + Frames per second: %1 + Snímků za sekundu: %1 + + + + Aspect ratio: %1 + Poměr stran: %1 + + + + Video bitrate: %1 kbps + Rychlost videa: %1 kbps + + + + Audio bitrate: %1 kbps + Rychlost audia: %1 kbps + + + + Audio rate: %1 Hz + Vzorkování zvuku: %1 Hz + + + + The file %1 can't be loaded + Nelze načíst soubor %1 + + + + No filename + Nezadáno jméno souboru + + + + The mplayer process didn't start while trying to get info about the video + Nešlo spustit MPlayer pro získání informací o videu + + + + The length of the video is 0 + Video nulové délky + + + + The file %1 doesn't exist + Soubor %1 neexistuje + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Výchozí + + + + Video Preview + Náhled na video + + + + &File: + &Soubor: + + + + &Columns: + S&loupců: + + + + &Rows: + Řá&dků: + + + + Add playing time to thumbnails + Vložit čas do miniatur + + + + &Aspect ratio: + &Poměr stran: + + + + &Seconds to skip at the beginnning: + Přeskočit prvních <i>n</i> &sekund: + + + + &Maximum width: + &Maximální šířka: + + + + The preview will be created for the video you specify here. + Vytvořit náhled pro zde uvedené video. + + + + The thumbnails will be arranged on a table. + Miniatury se zarovnají do tabulky. + + + + This option specifies the number of columns of the table. + Tato možnost určuje počet sloupců tabulky. + + + + This option specifies the number of rows of the table. + Tato možnost určuje počet řádků tabulky. + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + Zaškrtnete-li tuto možnost, v rohu miniatur se zobrazí příslušný čas přehrávání. + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + Je-li poměr stran videa nevhodný, můžete zde nastavit jiný. + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + Počátek videa je většinou vyplněn prázdnými snímky. Je proto vhodné prvních několik sekund přeskočit. Zde můžete nastavit počet sekund, které se mají přeskočit. + + + + This option specifies the maximum width in pixels that the generated preview image will have. + Tato možnost určuje maximální šířku generovaného náhledu v pixelech. + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Hlasitost + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_de.ts b/plugins/smplayer_plugin/translations/smplayer_de.ts new file mode 100644 index 000000000..3d4100a7c --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_de.ts @@ -0,0 +1,7399 @@ + + + + + About + + + Version: %1 + Version: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Dieses Programm ist freie Software; Sie können es weitergeben und/oder es unter den Bedingungen der allgemeinen GNU Lizenz verändern, wie es durch die Free Software-Foundation festgelegt wurde; entweder Version 2 der Lizenz, oder (nach ihrer Wahl) eine neuere Version. + + + + The following people have contributed with translations: + Die folgenden Leute haben an der Übersetzung mitgewirkt: + + + + German + Deutsch + + + + Slovak + Slowakisch + + + + Italian + Italienisch + + + + French + Französisch + + + + %1, %2 and %3 + %1, %2 und %3 + + + + Simplified-Chinese + Vereinfachtes Chinesisch + + + + Russian + Russisch + + + + %1 and %2 + %1 und %2 + + + + Hungarian + Ungarisch + + + + Polish + Polnisch + + + + Japanese + Japanisch + + + + Dutch + Niederländisch + + + + Ukrainian + Ukrainisch + + + + Portuguese - Brazil + Portugiesisch - Brasilien + + + + Georgian + Georgisch + + + + Czech + Tschechisch + + + + Bulgarian + Bulgarisch + + + + Turkish + Türkisch + + + + Swedish + Schwedisch + + + + Serbian + Serbisch + + + + Traditional Chinese + Traditionelles Chinesisch + + + + Romanian + Romanisch + + + + Portuguese - Portugal + Portugiesisch - Portugal + + + + Greek + Griechisch + + + + Finnish + Finnisch + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Über SMPlayer + + + + &Info + &Info + + + + icon + Icon + + + + &Contributions + &Mitwirkende + + + + &Translators + &Übersetzer + + + + &License + &Lizenz + + + + Visit our web for updates: + Besuchen sie unser Web für Updates: + + + + Get help in our forum: + Holen Sie sich Hilfe in unserem Forum: + + + + You can support SMPlayer by making a donation. + Sie können SMPlayer durch eine Spende unterstützen. + + + + More info + Mehr Info + + + + Korean + Koreanisch + + + + Macedonian + Mazedonisch + + + + Basque + Baskisch + + + + Using MPlayer %1 + Unter Einsatz von MPlayer %1 + + + + Catalan + Katalanisch + + + + Portable Edition + Portable Edition + + + + Using Qt %1 (compiled with Qt %2) + Unter Einsatz von Qt %1 (Kompiliert mit Qt %2) + + + + Slovenian + Slowenisch + + + + Arabic + Arabisch + + + + Kurdish + Kurdisch + + + + Galician + Galizisch + + + + The following people have contributed with patches (see the changelog for details): + Die folgenden Leute haben mit Patches mitgewirkt (für Details siehe Changelog): + + + + If there's any omission, please report. + Wenn es irgendeine Nichtberücksichtigung gibt, bitte melden. + + + + SMPlayer logo by %1 + SMPlayer Logo von %1 + + + + %1, %2, %3 and %4 + %1, %2, %3 und %4 + + + + %1, %2, %3, %4 and %5 + %1, %2, %3, %4 und %5 + + + + ActionsEditor + + + Name + Name + + + + Description + Beschreibung + + + + Shortcut + Tastaturkurzbefehl + + + + &Save + &Speichern + + + + &Load + &Laden + + + + Key files + Kurzbefehl-Dateien + + + + Choose a filename + Dateinamen auswählen + + + + Confirm overwrite? + Überschreiben bestätigen ? + + + + The file %1 already exists. +Do you want to overwrite? + Die Datei %1 existiert bereits. +Überschreiben ? + + + + Choose a file + Datei auswählen + + + + Error + Fehler + + + + The file couldn't be saved + Die Datei konnte nicht gespeichert werden + + + + The file couldn't be loaded + Die Datei konnte nicht geladen werden + + + + &Change shortcut... + &Tastaturkurzbefehl ändern... + + + + AudioEqualizer + + + Audio Equalizer + Audio Equalizer + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62,50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Übernehmen + + + + &Reset + &Reset + + + + &Set as default values + &Als Standard Wert einstellen + + + + Use the current values as default values for new videos. + Die jetzigen Werte als Standardwerte für neue Videos. + + + + Set all controls to zero. + Alle Steuerungen auf Null. + + + + Information + Information + + + + The current values have been stored to be used as default. + Die aktuellen Werte wurden als Standard gespeichert. + + + + BaseGui + + + &File... + &Datei... + + + + D&irectory... + V&erzeichnis... + + + + &Playlist... + &Abspiellisten... + + + + &DVD from drive + &DVD im Laufwerk + + + + D&VD from folder... + D&VD Ordner... + + + + &URL... + &URL... + + + + P&lay + &Wiedergabe + + + + &Pause + &Pause + + + + &Stop + &Stop + + + + &Frame step + &Bildlauf + + + + &Repeat + &Wiederholen + + + + &Normal speed + &Normale Geschwindigkeit + + + + &Halve speed + &Halbe Geschwindigkeit + + + + &Double speed + &Doppelte Geschwindigkeit + + + + Speed &-10% + Geschwindigkeit &-10% + + + + Speed &+10% + Geschwindigkeit &+10% + + + + Sp&eed + &Geschwindigkeit + + + + &Fullscreen + &Vollbild + + + + &Compact mode + &Kompaktmodus + + + + &Equalizer + &Equalizer + + + + &Screenshot + &Bildschirmfoto + + + + S&tay on top + &Immer im Vordergrund + + + + &Postprocessing + &Nachbearbeitung + + + + &Autodetect phase + &Automatisch + + + + &Deblock + &Deblocking + + + + De&ring + De&ringing + + + + Add n&oise + &Rauschen hinzufügen + + + + F&ilters + F&ilter + + + + &Mute + &Stumm + + + + Volume &- + Leiser &- + + + + Volume &+ + Lauter &+ + + + + &Delay - + &Delay - + + + + D&elay + + D&elay + + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filter + + + + &Load... + &Laden... + + + + Delay &- + Delay &- + + + + Delay &+ + Delay &+ + + + + &Up + &Hoch + + + + &Down + &Runter + + + + &Playlist + &Abspielliste + + + + &Show frame counter + &Anzahl der Einzelbilder anzeigen + + + + P&references + &Einstellungen + + + + &View logs + &Logs einsehen + + + + About &Qt + Über &Qt + + + + About &SMPlayer + Über &SMPlayer + + + + &Open + &Öffnen + + + + &Play + &Wiedergabe + + + + &Video + &Video + + + + &Audio + &Audio + + + + &Subtitles + &Untertitel + + + + &Browse + &Navigation + + + + Op&tions + &Optionen + + + + &Help + &Hilfe + + + + &Recent files + &Neueste Dateien + + + + &Clear + &Löschen + + + + Si&ze + &Größe + + + + &Aspect ratio + &Aspect Ratio + + + + &Deinterlace + &Deinterlacing + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Pan && Scan + + + + 4:3 &to 16:9 + 4:3 &zu 16:9 + + + + &None + &Keine + + + + &Lowpass5 + &Tiefpass(filter)5 + + + + Linear &Blend + &Lineare Überblendung + + + + &Channels + &Kanäle + + + + &Stereo mode + &Stereo Mode + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Left channel + &Linker Kanal + + + + &Right channel + &Rechter Kanal + + + + &Select + &Auswahl + + + + &Title + &Titel + + + + &Chapter + &Kapitel + + + + &Angle + &Blickwinkel + + + + &OSD + &OSD + + + + &Disabled + &Ausgeschaltet + + + + &Seek bar + &Zeitleiste + + + + &Time + &Zeit + + + + Time + T&otal time + Zeit + Zeit t&otal + + + + SMPlayer - mplayer log + SMPlayer - mplayer log + + + + SMPlayer - smplayer log + SMPlayer - smplayer log + + + + <empty> + <leer> + + + + Video + Video + + + + Audio + Audio + + + + Playlists + Abspiellisten + + + + All files + Alle Dateien + + + + Choose a file + Datei wählen + + + + SMPlayer - Information + SMPlayer - Information + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Die CDROM /DVD Laufwerke wurden nocht nicht konfiguriert. +Das kann im folgenden Konfigurationsdialog gemacht werden. + + + + Choose a directory + Verzeichnis auswählen + + + + Subtitles + Untertitel + + + + About Qt + Über Qt + + + + Playing %1 + Wiedergabe %1 + + + + Pause + Pause + + + + Stop + Stop + + + + Play / Pause + Wiedergabe / Pause + + + + Pause / Frame step + Pause / Bildlauf + + + + U&nload + &Entladen + + + + V&CD + V&CD + + + + C&lose + &Schließen + + + + View &info and properties... + Ansicht &Info und Eigenschaften... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Reset + + + + Move &left + &Nach links bewegen + + + + Move &right + &Nach rechts bewegen + + + + Move &up + &Hoch bewegen + + + + Move &down + &Runter bewegen + + + + &Pan && scan + &Pan && Scan + + + + &Previous line in subtitles + &Vorherige Untertitelzeile + + + + N&ext line in subtitles + &Nächste Untertitelzeile + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Leiser (2) + + + + Inc volume (2) + Lauter (2) + + + + Exit fullscreen + Vollbild beenden + + + + OSD - Next level + OSD - Nächste Stufe + + + + Dec contrast + Kontrast - + + + + Inc contrast + Kontrast + + + + + Dec brightness + Helligkeit - + + + + Inc brightness + Helligkeit + + + + + Dec hue + Farbe - + + + + Inc hue + Farbe + + + + + Dec saturation + Sättigung - + + + + Dec gamma + Gamma - + + + + Next audio + Nächste Audiodatei + + + + Next subtitle + Nächster Untertitel + + + + Next chapter + Nächstes Kapitel + + + + Previous chapter + Vorheriges Kapitel + + + + Inc saturation + Sättigung + + + + + Inc gamma + Gamma + + + + + &Load external file... + &Externe Datei laden... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (Normal) + + + + Y&adif (double framerate) + Y&adif (Doppelte Framerate) + + + + &Next + &Nächster + + + + Pre&vious + &Vorheriger + + + + Volume &normalization + Lautstärke &normalisieren + + + + &Audio CD + &Audio CD + + + + Denoise nor&mal + &Rauschfilter normal + + + + Denoise &soft + &Rauschfilter soft + + + + Denoise o&ff + &Rauschfilter aus + + + + Use SSA/&ASS library + Benutze SSA/&ASS Programmbibliothek + + + + Flip i&mage + &Bild spiegeln + + + + &Toggle double size + &Doppelte Größe schalten + + + + S&ize - + &Größe - + + + + Si&ze + + &Größe + + + + + Add &black borders + &Schwarze Rahmen hinzufügen + + + + Soft&ware scaling + &Software Skalierung + + + + &FAQ + &Häufig gestellte Fragen + + + + Visualize &motion vectors + Visualisiere &Bewegungsvektoren + + + + &Command line options + &Kommandozeilenoptionen + + + + SMPlayer command line options + SMPlayer Kommandozeilenoptionen + + + + Enable &closed caption + &Optionale Untertitel (closed caption) aktivieren + + + + &Forced subtitles only + &Nur erzwungene Untertitel (Forced subtitles) + + + + Reset video equalizer + Reset Video Equalizer + + + + MPlayer has finished unexpectedly. + MPlayer wurde unerwartet beendet. + + + + Exit code: %1 + Exit code: %1 + + + + MPlayer failed to start. + MPlayer konnte nicht gestartet werden. + + + + Please check the MPlayer path in preferences. + Pfad von MPlayer in den Einstellungen überprüfen. + + + + MPlayer has crashed. + MPlayer ist abgestürzt. + + + + See the log for more info. + Siehe Logdatei für mehr Infos. + + + + &Rotate + &Rotieren + + + + &Off + &Aus + + + + &Rotate by 90 degrees clockwise and flip + &Rotieren im Uhrzeigersinn um 90 Grad und spiegeln + + + + Rotate by 90 degrees &clockwise + &Rotieren im Uhrzeigersinn um 90 Grad + + + + Rotate by 90 degrees counterclock&wise + &Rotieren um 90 Grad entgegen dem Uhrzeigersinn + + + + Rotate by 90 degrees counterclockwise and &flip + &Rotieren um 90 Grad entgegen dem Uhrzeigersinn und spiegeln + + + + &Jump to... + &Sprung zu ... + + + + Show context menu + Kontextmenü anzeigen + + + + Multimedia + Multimedia + + + + E&qualizer + E&qualizer + + + + Reset audio equalizer + Reset Audio Equalizer + + + + Find subtitles on &OpenSubtitles.org... + Untertitel suchen bei &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + &Untertitel hochladen bei OpenSubtitles.org... + + + + &Tips + &Tipps + + + + &Auto + &Auto + + + + Speed -&4% + Geschwindigkeit -&4% + + + + &Speed +4% + &Geschwindigkeit +4% + + + + Speed -&1% + Geschwindigkeit -&1% + + + + S&peed +1% + &Geschwindigkeit +1% + + + + Scree&n + &Bildschirm + + + + &Default + &Standard + + + + Mirr&or image + Mirr&or image + + + + Next video + Nächstes Video + + + + &Track + video + &Spur + + + + &Track + audio + &Spur + + + + Warning - Using old MPlayer + Warnung - Veraltete Version von MPlayer + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + Die installierte Version von MPlayer (%1) auf diesen System ist veraltet. SMPlayer arbeitet mit dieser Version unzureichend: einige Optionen funktionieren nicht, Auswahl der Untertitel ist eventuell nicht möglich... + + + + Please, update your MPlayer. + Bitte MPlayer aktualisieren. + + + + (This warning won't be displayed anymore) + (Diese Warnung wird nicht mehr angezeigt) + + + + Next aspect ratio + Nächster Aspect Ratio + + + + &Auto zoom + &Automatischer Zoom + + + + Auto zoom for &16:9 + Automatischer Zoom für &16:9 + + + + Auto zoom for &2.35:1 + Automatischer Zoom für &2.35:1 + + + + Zoom for &16:9 + Zoom für &16:9 + + + + Zoom for &2.35:1 + Zoom für &2.35:1 + + + + Pre&view... + &Vorschau... + + + + &Always + &Immer + + + + &Never + &Niemals + + + + While &playing + &Während des Abspielens + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer läuft noch hier + + + + S&how icon in system tray + &Icon im Sytem-Tray zeigen + + + + &Hide + &Ausblenden + + + + &Restore + &Wiederherstellen + + + + &Quit + &Beenden + + + + Playlist + Abspielliste + + + + Core + + + Brightness: %1 + Helligkeit: %1 + + + + Contrast: %1 + Kontrast: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Farbe: %1 + + + + Saturation: %1 + Sättigung: %1 + + + + Volume: %1 + Lautstärke: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + Schriftart Skalierung: %1 + + + + Aspect ratio: %1 + Aspect Ratio: %1 + + + + Updating the font cache. This may take some seconds... + Aktualisierung des Schriftart-Cache. Dies kann einige Sekunden dauern ... + + + + DefaultGui + + + Welcome to SMPlayer + Willkommen im SMPlayer + + + + Audio + Audio + + + + Subtitle + Untertitel + + + + &Main toolbar + &Hauptsymbolleiste + + + + &Language toolbar + &Symbolleiste für Sprachen + + + + &Toolbars + &Symbolleisten + + + + EqSlider + + + icon + Icon + + + + ErrorDialog + + + Hide log + Log ausblenden + + + + Show log + Log anzeigen + + + + MPlayer Error + MPlayer Fehler + + + + icon + Icon + + + + Error + Fehler + + + + FileDownloader + + + Downloading... + Herunterladen... + + + + Downloading %1 + Herunterladen %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Datei-Eigenschaften + + + + &Information + &Information + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Auswahl Demuxer, der auf die Datei angewendet wird: + + + + &Reset + &Reset + + + + &Video codec + &Video-Codec + + + + &Select the video codec: + &Auswahl Video-Codec: + + + + A&udio codec + A&udio-Codec + + + + &Select the audio codec: + &Auswahl Audio-Codec: + + + + &MPlayer options + &MPlayer Optionen + + + + Additional Options for MPlayer + Zusätzliche Optionen für MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Hier können zusätzliche mplayer-Optionen angeben werden. +Angaben werden durch Leerzeichen getrennt . +Beispiel: -flip -nosound + + + + &Options: + &Optionen: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Zusätzliche Angaben für Videofilter. +Angaben werden durch "," gerennt. +Keine Leerzeichen verwenden! Beispiel: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + &Videofilter: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Audiofilter. +Regeln wie bei den Videofiltern. +Beispiel: resample=44100:0:0,volnorm + + + + Audio &filters: + &Audiofilter: + + + + OK + OK + + + + Cancel + Abbrechen + + + + Apply + Übernehmen + + + + FindSubtitlesWindow + + + Language + Sprache + + + + Name + Name + + + + Format + Format + + + + Files + Dateien + + + + Date + Datum + + + + Uploaded by + Hochgeladen von + + + + All + Alles + + + + Close + Schließen + + + + &Download + &Download + + + + &Copy link to clipboard + &Link zum Clipboard kopieren + + + + Error + Fehler + + + + Download failed: %1. + Download fehlgeschlagen: %1. + + + + Connecting to %1... + Verbindung zu %1... + + + + Downloading... + Herunterladen... + + + + Done. + Erledigt. + + + + %1 files available + %1 Dateien verfügbar + + + + Failed to parse the received data. + Fehler beim Parsen der empfangenen Daten. + + + + Find Subtitles + Suche Untertitel + + + + &Subtitles for + &Untertitel für + + + + &Language: + &Sprache: + + + + &Refresh + &Aktualisieren + + + + Subtitle saved as %1 + Untertitel gespeichert als %1 + + + + %1 subtitle(s) extracted + + %1 Untertitel extrahiert + %1 Untertitel extrahiert + + + + + Overwrite? + Überschreiben? + + + + The file %1 already exits, overwrite? + Die Datei %1 existiert bereits, überschreiben? + + + + Error saving file + Fehler beim Speichern der Datei + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Es war nicht möglich, die heruntergeladene Datei +im Order %1 zu speichern +Bitte die Berechtigung für den Ordner überprüfen + + + + Download failed + Download fehlgeschlagen + + + + Temporary file %1 + Temporäre Datei %1 + + + + InfoFile + + + General + Allgemein + + + + Size + Größe + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Dauer + + + + Demuxer + Demuxer + + + + Name + Name + + + + Artist + Künstler + + + + Author + Autor + + + + Album + Album + + + + Genre + Genre + + + + Date + Datum + + + + Track + Track + + + + Copyright + Urheberrecht + + + + Comment + Kommentar + + + + Software + Software + + + + Clip info + Clip Info + + + + Video + Video + + + + Resolution + Auflösung + + + + Aspect ratio + Aspect Ratio + + + + Format + Format + + + + Bitrate + Bitrate + + + + %1 kbps + %1 kbps + + + + Frames per second + Bilder pro Sekunde + + + + Selected codec + Verwendeter Codec + + + + Initial Audio Stream + Startwert Audio Stream + + + + Rate + Samplingrate + + + + %1 Hz + %1 Hz + + + + Channels + Kanäle + + + + Audio Streams + Audio Stream + + + + Language + Sprache + + + + empty + leer + + + + Subtitles + Untertitel + + + + Type + Typ + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Streamtitel + + + + Stream URL + Stream URL + + + + File + Datei + + + + InputDVDDirectory + + + Choose a directory + Verzeichnis auswählen + + + + SMPlayer - Play a DVD from a folder + SMPlayer -Wiedergabe DVD aus einem Ordner + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Wiedergabe der DVD, kann auch von der Festplatte erfolgen. +Auswahl des Ordners, der das VIDEO_TS und das AUDIO_TS Verzeichnis enthält. + + + + Choose a directory... + Verzeichnis auswählen... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Eingabe der MPlayer Version + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer konnte nicht die verwendetet MPlayer Version identifizieren. + + + + Version reported by MPlayer: + Auskunft der eigenen Version von MPlayer: + + + + Please, &select the correct version: + &Bitte die richtige Version wählen: + + + + 1.0rc1 or older + 1.0rc1 oder älter + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Jünger als 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Eingabe URL + + + + &URL: + &URL: + + + + It's a &playlist + &Es ist ein Abspielliste + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Wenn diese Option aktiviert ist, werden URLS in die Abspielliste mit einbezogen, als Text dargestellt und abgespielt. + + + + Languages + + + Afar + Afar + + + + Abkhazian + Abchasisch + + + + Afrikaans + Afrikaans + + + + Amharic + Amharisch + + + + Arabic + Arabisch + + + + Assamese + Assamese + + + + Aymara + Aymara + + + + Azerbaijani + Aserbaidschanisch + + + + Bashkir + Baschkirisch + + + + Byelorussian + Belorussisch + + + + Bulgarian + Bulgarisch + + + + Bihari + Bihari + + + + Bislama + Bislama + + + + Bengali + Bengalisch + + + + Tibetan + Tibetisch + + + + Breton + Bretonisch + + + + Catalan + Katalanisch + + + + Corsican + Korsisch + + + + Czech + Tschechisch + + + + Welsh + Kymrisch + + + + Danish + Dänisch + + + + German + Deutsch + + + + Bhutani + Bhutani + + + + Greek + Griechisch + + + + English + Englisch + + + + Esperanto + Esperanto + + + + Spanish + Spanisch + + + + Estonian + Estnisch + + + + Basque + Baskisch + + + + Persian + Persisch + + + + Finnish + Finnisch + + + + Fiji + Fidschi + + + + Faroese + Färöisch + + + + French + Französisch + + + + Frisian + Friesisch + + + + Irish + Irisch + + + + Scots + Schottisch + + + + Galician + Galizisch + + + + Guarani + Guarani + + + + Gujarati + Gujarati + + + + Hausa + Haussa + + + + Hebrew + Hebräisch + + + + Hindi + Hindi + + + + Croatian + Kroatisch + + + + Hungarian + Ungarisch + + + + Armenian + Armenisch + + + + Interlingua + Interlingua + + + + Indonesian + Bahasa Indonesia + + + + Interlingue + Interlingue + + + + Inupiak + Inupik + + + + Icelandic + Isländisch + + + + Italian + Italienisch + + + + Inuktitut + Inuktitut + + + + Japanese + Japanisch + + + + Javanese + Javanisch + + + + Georgian + Georgisch + + + + Kazakh + Kasachisch + + + + Greenlandic + Grönländisch + + + + Cambodian + Kambodschanisch + + + + Kannada + Kannada + + + + Korean + Koreanisch + + + + Kashmiri + Kashmiri + + + + Kurdish + Kurdisch + + + + Kirghiz + Kirgisisch + + + + Latin + Latein + + + + Lingala + Lingala + + + + Laothian + Laotisch + + + + Lithuanian + Litauisch + + + + Latvian + Lettisch + + + + Malagasy + Malagassi + + + + Maori + Maori + + + + Macedonian + Mazedonisch + + + + Malayalam + Malayalam + + + + Mongolian + Mongolisch + + + + Moldavian + Moldauisch + + + + Marathi + Marathi + + + + Malay + Malaiisch + + + + Maltese + Maltesisch + + + + Burmese + Burmesisch + + + + Nauru + Nauruanisch + + + + Nepali + Nepali + + + + Dutch + Niederländisch + + + + Norwegian + Norwegisch + + + + Occitan + Okzitanisch + + + + Oriya + Oriya + + + + Punjabi + Pandschabi + + + + Polish + Polnisch + + + + Pashto + Paschtunisch + + + + Portuguese + Portugiesisch + + + + Quechua + Quechua + + + + Kirundi + Kirundi + + + + Romanian + Romanisch + + + + Russian + Russisch + + + + Kinyarwanda + Kinyarwanda + + + + Sanskrit + Sanskrit + + + + Sindhi + Sindhi + + + + Sangho + Sangho + + + + Sinhalese + Singhalesisch + + + + Slovak + Slowakisch + + + + Slovenian + Slowenisch + + + + Samoan + Samoanisch + + + + Shona + Shona + + + + Somali + Somali + + + + Albanian + Albanisch + + + + Serbian + Serbisch + + + + Siswati + Siswati + + + + Sesotho + Sesotho + + + + Sundanese + Sundanesisch + + + + Swedish + Schwedisch + + + + Swahili + Suaheli + + + + Tamil + Tamilisch + + + + Telugu + Telugu + + + + Tajik + Tadschikisch + + + + Thai + Thailändisch + + + + Tigrinya + Tigrinnisch + + + + Turkmen + Turkmenisch + + + + Tagalog + Tagalog + + + + Setswana + Setswana + + + + Tonga + Tongaisch + + + + Turkish + Türkisch + + + + Tsonga + Tsonga + + + + Tatar + Tatarisch + + + + Twi + Twi + + + + Uighur + Uigurisch + + + + Ukrainian + Ukrainisch + + + + Urdu + Urdu + + + + Uzbek + Usbekisch + + + + Vietnamese + Vietnamesisch + + + + Wolof + Wolof + + + + Xhosa + Xhosa + + + + Yiddish + Jiddisch + + + + Yoruba + Yoruba + + + + Zhuang + Zhuang + + + + Chinese + Chinesisch + + + + Zulu + Zulu + + + + Portuguese - Brazil + Portugiesisch - Brasilien + + + + Portuguese - Portugal + Portugiesisch - Portugal + + + + Simplified-Chinese + Vereinfachtes Chinesisch + + + + Traditional Chinese + Traditionelles Chinesisch + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + West-Europäische Sprachen + + + + Western European Languages with Euro + West-Europäische Sprachen mit Euro + + + + Slavic/Central European Languages + Slavische/Zentral-Europäische Sprachen + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galicisch, Maltesisch, Türkisch + + + + Old Baltic charset + Alte Baltische Zeichenkodierung + + + + Cyrillic + Kyrillisch + + + + Modern Greek + Modern Griechisch + + + + Baltic + Baltisch + + + + Celtic + Celtic + + + + Hebrew charsets + Hebräische Zeichkodierung + + + + Ukrainian, Belarusian + Ukrainisch, Weißrussisch + + + + Simplified Chinese charset + Vereinfachte Chinesische Zeichenkodierung + + + + Traditional Chinese charset + Traditionelle Chinesische Zeichnenkodierung + + + + Japanese charsets + Japanische Zeichenkodierung + + + + Korean charset + Koreanische Zeichenkodierung + + + + Thai charset + Thailändische Zeichenkodierung + + + + Cyrillic Windows + Kyrillisch Windows + + + + Slavic/Central European Windows + Slavisch/Zentral-Europäisches Windows + + + + Arabic Windows + Arabisches Windows + + + + Rhaeto-Romance + Rhaetoromanisch + + + + Serbo-Croatian + Serbokroatisch + + + + Volapük + Volapük + + + + Avestan + Avestan + + + + Akan + Akan + + + + Aragonese + Aragonese + + + + Avaric + Avaric + + + + Belarusian + Belarusian + + + + Bambara + Bambara + + + + Bosnian + Bosnian + + + + Chechen + Chechen + + + + Cree + Cree + + + + Church + Church + + + + Chuvash + Chuvash + + + + Divehi + Divehi + + + + Dzongkha + Dzongkha + + + + Ewe + Ewe + + + + Fulah + Fulah + + + + Fijian + Fijian + + + + Gaelic + Gaelic + + + + Manx + Manx + + + + Hiri + Hiri + + + + Haitian + Haitian + + + + Herero + Herero + + + + Chamorro + Chamorro + + + + Igbo + Igbo + + + + Sichuan + Sichuan + + + + Inupiaq + Inupiaq + + + + Ido + Ido + + + + Kongo + Kongo + + + + Kikuyu + Kikuyu + + + + Kuanyama + Kuanyama + + + + Khmer + Khmer + + + + Kanuri + Kanuri + + + + Komi + Komi + + + + Cornish + Cornish + + + + Luxembourgish + Luxemburgisch + + + + Ganda + Ganda + + + + Limburgan + Limburgan + + + + Lao + Lao + + + + Luba-Katanga + Luba-Katanga + + + + Marshallese + Marshallese + + + + Bokmål + Bokmål + + + + Ndebele + Ndebele + + + + Ndonga + Ndonga + + + + Navajo + Navajo + + + + Chichewa + Chichewa + + + + Ojibwa + Ojibwa + + + + Oromo + Oromo + + + + Ossetian + Ossetian + + + + Panjabi + Panjabi + + + + Pali + Pali + + + + Pushto + Pushto + + + + Romansh + Romansh + + + + Rundi + Rundi + + + + Sardinian + Sardinian + + + + Sami + Sami + + + + Sango + Sangho + + + + Sinhala + Sinhala + + + + Swati + Swati + + + + Sotho + Sotho + + + + Tswana + Tswana + + + + Tahitian + Tahitian + + + + Venda + Venda + + + + Volapük + Volapük + + + + Walloon + Walloon + + + + LogWindow + + + Choose a filename to save under + Wähle Dateinamen für speichern unter + + + + Confirm overwrite? + Überschreiben bestätigen ? + + + + The file already exists. +Do you want to overwrite? + Die Datei existiert bereits. +Überschreiben ? + + + + Error saving file + Fehler beim Speichern der Datei + + + + The log couldn't be saved + Log-Datei konnte nicht gespeichert werden + + + + Logs + Logs + + + + LogWindowBase + + + Log Window + Log Window + + + + Save + Speichern + + + + Copy to clipboard + Kopiere zum Clipboard + + + + Close + Schließen + + + + &Close + &Schließen + + + + MiniGui + + + Control bar + Kontrollregler + + + + MpcGui + + + Control bar + Kontrollregler + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Name + + + + Length + Dauer + + + + Choose a file + Datei auswählen + + + + Choose a filename + Dateinamen auswählen + + + + Confirm overwrite? + Überschreiben bestätigen ? + + + + Select one or more files to open + Auswahl von einer, oder mehrerer Dateien, zum Öffnen + + + + Choose a directory + Verzeichnis auswählen + + + + The file %1 already exists. +Do you want to overwrite? + Die Datei %1 existiert bereits. +Überschreiben ? + + + + Edit name + Name bearbeiten + + + + Type the name that will be displayed in the playlist for this file: + Den Dateinamen schreiben, wie er in der Abspielliste angezeigt werden soll: + + + + &Play + &Wiedergabe + + + + &Edit + &Bearbeiten + + + + Playlists + Abspiellisten + + + + All files + Alle Dateien + + + + &Load + &Laden + + + + &Save + &Speichern + + + + &Next + &Nächster + + + + Pre&vious + &Vorheriger + + + + Move &up + &Hoch bewegen + + + + Move &down + &Runter bewegen + + + + &Repeat + &Wiederholen + + + + S&huffle + &Zufall + + + + Add &current file + &Aktuelle Datei hinzufügen + + + + Add &file(s) + &Datei(en) hinzufügen + + + + Add &directory + &Verzeichnis hinzufügen + + + + Remove &selected + &Ausgewählte Datei entfernen + + + + Remove &all + &Alles entfernen + + + + Add... + Hinzufügen... + + + + Remove... + Entfernen... + + + + SMPlayer - Playlist + SMPlayer - Abspielliste + + + + Playlist modified + Abspielliste geändert + + + + There are unsaved changes, do you want to save the playlist? + Ungesicherte Änderungen, soll die Abspielliste gespeichert werden ? + + + + Preferences + Einstellungen + + + + PlaylistPreferences + + + Playlist - Preferences + Abspielliste - Einstellungen + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Mit dieser Option werden Dateien auch in Unterverzeichnissen rekursiv hinzugefügt. Ansonsten nur zum ausgewählten Verzeichnis. + + + + &Add files in directories recursively + &Dateien rekursiv in Verzeichnisse einfügen + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Diese Option erlaubt Infos anzuzeigen in der Abspielliste zu den hinzugefügten Dateien. Dies erlaubt die Anzeige der Titel Name (wenn verfügbar) und die Länge der Dateien. Andernfalls werden diese Informationen nicht zur Verfügung stehen, bis die Datei tatsächlich gespielt wird. Achtung: Diese Option kann langsam sein, speziell bei vielen Dateien. + + + + Automatically get &info about files added + &Automatische Infos über alle hinzugefügten Dateien erhalten + + + + &Save copy of playlist on exit + &Speichere Kopie der Abspielliste beim Beenden + + + + &Play files from start + &Wiedergabe der Dateien von Anfang an + + + + PrefAdvanced + + + Advanced + Erweitert + + + + Auto + Auto + + + + &Advanced + &Erweitert + + + + icon + Icon + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Hier können zusätzliche mplayer-Optionen angeben werden. +Angaben werden durch Leerzeichen getrennt . +Beispiel: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Zusätzliche Angaben für Videofilter. +Angaben werden durch "," gerennt. Keine Leerzeichen verwenden! +Beispiel: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Audiofilter. +Regeln wie bei den Videofiltern. +Beispiel: resample=44100:0:0,volnorm + + + + Log MPlayer output + Log mplayer Ausgabe + + + + Log SMPlayer output + Log SMPlayer Ausgabe + + + + This option is mainly intended for debugging the application. + Diese Option ist hauptsächlich zum Austesten der Anwendung. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Aktivieren der Option kann Flackern/Flimmern verringern, aber es könnte auch sein, dass das Video nicht mehr ordentlich dargestellt wird. + + + + Filter for SMPlayer logs + Filter für SMPlayer Logs + + + + &Monitor aspect: + &Seitenverhältnis: + + + + &Run MPlayer in its own window + &Wiedergabe im Mplayer-Fenster + + + + &Options: + &Optionen: + + + + V&ideo filters: + &Videofilter: + + + + Audio &filters: + &Audiofilter: + + + + &Colorkey: + &Farbschlüssel: + + + + Log &SMPlayer output + Log &SMPlayer Ausgabe + + + + &Filter for SMPlayer logs: + &Filter für SMPlayer Logs: + + + + C&hange... + &Ändern… + + + + Logs + Logs + + + + Log MPlayer &output + &Log MPlayer Ausgabe + + + + Options for MP&layer + &Optionen für Mplayer + + + + Autosave MPlayer log + MPlayer Log automatisch speichern + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Mit dieser Option wird MPlayer Log in die angegebene Datei gespeichert, jedesmal wenn eine neue Datei abgespielt wird. Es ist gedacht für externe Anwendungen, die Informationen über die abgespielte Datei erhalten können. + + + + Autosave MPlayer log filename + MPlayer Log Dateiname automatisch speichern + + + + Enter here the path and filename that will be used to save the MPlayer log. + Eingabe Pfadangabe und Dateiname, zur Speicherung der Mplayer Log-Datei. + + + + A&utosave MPlayer log to file + &Automatisches speichern von MPlayer Log zu Datei + + + + Pass short filenames (8+3) to MPlayer + Kurze Dateinamen (8+3) an MPlayer weiter leiten + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Gegenwärtig kann MPlayer keine Dateinamen öffnen, die Charaktere außerhalb des lokalen Zeichensatzes enthalten. SMplayer leitet mit dieser Option, die Version der kurzen Dateinamen an MPlayer weiter und er wird auf diese Art in der Lage sein, sie auch zu öffnen. + + + + &Pass short filenames (8+3) to MPlayer + &Kurze Dateinamen (8+3) an MPlayer weiter leiten + + + + Monitor aspect + Seitenverhältnis + + + + Select the aspect ratio of your monitor. + Auswahl Aspect Ratio des Monitors. + + + + Run MPlayer in its own window + Wiedergabe im MPlayer-Fenster + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Mit dieser Option wird das MPlayer-Fenster nicht im SMPlayer-Fenster eingebettet, sondern die Ausgabe erfolgt direkt über MPlayer. Maus und Tastatur werden direkt von MPlayer abgefragt, SMPlayer Tastaturkurz- und Maus-Tasten Befehle werden wahrscheinlich nicht funktionieren, wenn das MPlayer-Fenster den Fokus hat. + + + + Colorkey + Farbschlüssel + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Wenn Teile des Videos über ein Fenster hinaus verschoben sind, kann der Fehler mit Änderungen des Farbschlüssels behoben werden. Versuche eine Farbe in Richtung Schwarz. + + + + Options for MPlayer + Optionen für MPlayer + + + + Options + Optionen + + + + Here you can type options for MPlayer. Write them separated by spaces. + Hier können Optionen für MPlayer hinzugefügt werden. Optionen seperat schreiben mit Freizeichen. + + + + Video filters + Videofilter + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Hier können Videofilter für MPlayer hinzugefügt werden. Kommandos seperat schreiben. Keine Freizeichen! + + + + Audio filters + Audiofilter + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Hier können Audiofilter für MPlayer hinzugefügt werden. Kommandos seperat schreiben. Keine Freizeichen! + + + + Repaint the background of the video window + Hintergrund vom Videofenster ausfüllen + + + + Repaint the backgroun&d of the video window + &Hintergrund vom Videofenster ausfüllen + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Benutze IPv4 Netzwerk-Verbindungen. Fällt automatisch auf IPv6 zurück. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Benutze IPv6 Netzwerk-Verbindungen. Fällt automatisch auf IPv4 zurück. + + + + Network Connection + Netzwerk-Verbindung + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + Lo&gs + + + + Rebuild index if needed + Index neu erstellen falls benötigt + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Baut Index der Datei wiederauf, mit der Erlaubnis zu suchen, wenn kein Index gefunden wurde. Nützlich bei unvollstänigen/defekten Downloads, oder schlecht erstellten Dateien. Die Option funktioniert nur wenn das eigentliche Media Suchfunktionen unterstützt (nicht mit stdin,pipe, etc).<br> Hinweis:Erstellen von einem Index kann einige Zeit dauern. + + + + Rebuild &index if needed + &Index neu erstellen falls benötigt + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Die Ausgabeinformationen von Mplayer kann optinoal von SMPlayer gespeichert werden (Hier zu finden <b>Optionen -> Logs einsehen -> MPlayer</b>). Die Information kann für Entwickler nützlich sein, wenn ein Fehler gefunden wird. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Die Ausgabeinformationen von Mplayer kann optinoal von SMPlayer gespeichert werden (Hier zu finden <b>Optionen -> Logs einsehen -> MPlayer</b>). In Problemfällen können die Logs wichtige Informationen enthalten, daher wird diese Option empfohlen. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Optional können Nachrichten von SMPlayer gefiltert werden. Hier kann man irgendeinen regelulärer Ausdruck schreiben.<br>Zum Beispiel: <i>^Core::.*</i> Nur Zeilen werden dargestellt, beginned mit <i>Core::</i> + + + + Correct pts + Korrigiere PTS + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Schaltet MPlayer in einen experimentellen Modus, Zeitstempel für Video-Frames werden anders berechnet und Video-Filter, die neue Frames hinzufügen, oder bestehende Zeitstempel verändern, werden unterstützt. Die genaueren Zeitstempel werden sichtbar, zum Beispiel bei der Wiedergabe von Untertiteln mittels SSA / ASS-Bibliothek, terminiert auf Szenenwechsel. Ohne korrektes PTS, Untertitel Timing funktioniert nicht bei einigen Bildern. Diese Option arbeitet nicht richtig mit einigen Demuxern und Codecs. + + + + Proxy + Proxy + + + + Enable proxy + Aktiviere Proxy + + + + Enable/disable the use of the proxy. + Aktiviere/deaktiviere Verwendung des Proxy. + + + + Host + Host + + + + The host name of the proxy. + Der Hostname des Proxy. + + + + Port + Port + + + + The port of the proxy. + Der Port des Proxy. + + + + Username + Benutzername + + + + If the proxy requires authentication, this sets the username. + Wenn der Proxy eine Authentifizierung erfordert, hier den Benutzernamen eingeben. + + + + Password + Passwort + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + Das Passwort für den Proxy-Server. Achtung: Das Passwort wird als Nur-Text-Format in der Konfigurationsdatei gespeichert. + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + Proxy für Internet-Verbindungen (derzeit nur für Untertitel-Download). + + + + &Enable proxy + &Aktiviere Proxy + + + + &Host: + &Host: + + + + &Port: + &Port: + + + + &Username: + &Benutzername: + + + + Pa&ssword: + Pa&sswort: + + + + C&orrect PTS + &Korrigiere PTS + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + Typ + + + + Select the proxy type to be used. + Auswahl des anzuwendenden Proxy-Typs. + + + + &Type: + &Typ: + + + + Actions list + Aktionsliste + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + Hier wird eine Liste der <i>Aktionen</i> spezifiziert, die jedes mal ausgeführt werden, wenn eine Datei gestartet wird. Alle Aktionen stehen im Tastaturkurzbefehl Editor, im Bereich <b>Tastatur and Maus</b>. Aktionen müssen durch Leerzeichen getrennt sein. Mit <i>wahr</i> oder <i>falsch</i> werden Aktionen aktiviert, oder deaktiviert. + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + Einschränkung: Die Aktionen starten nur, wenn eine Datei geladen worden ist, nicht wenn der MPlayer neu gestartet wird. (z. B. Auswahl Audio-oder Video-Filter) + + + + Network + Netzwerk + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + &Immer wenn eine Datei geöffnet wird, starten folgende Aktionen. Aktionen werden per Leerzeichen von einander getrennt: + + + + &Network + &Netzwerk + + + + Example: + Beispiel: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + Baut Index der Datei wiederauf, mit der Erlaubnis zu suchen, wenn kein Index gefunden wurde. Nützlich bei unvollstänigen/defekten Downloads, oder schlecht erstellten Dateien. Die Option funktioniert nur wenn das eigentliche Media Suchfunktionen unterstützt (nicht mit stdin,pipe, etc).<br> Hinweis:Erstellen von einem Index kann einige Zeit dauern. + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + Das Passwort für den Proxy-Server. Achtung: Das Passwort wird als Nur-Text-Format in der Konfigurationsdatei gespeichert. + + + + PrefAssociations + + + Warning + Warnung + + + + Not all files could be associated. Please check your security permissions and retry. + Nicht alle Dateitypen konnten assoziiert werden. Bitte die Sicheheitseinstellungen üperprüfen und erneut versuchen. + + + + File Types + Dateitypen + + + + Select all + Alles auswählen + + + + Check all file types in the list + Aktivieren aller Dateitypen in der Liste + + + + Uncheck all file types in the list + Deaktivieren aller Dateitypen in der Liste + + + + List of file types + Liste der Dateitypen + + + + File types + Dateitypen + + + + Media files handled by SMPlayer: + Mediadateien die von SMPlayer verarbeitet werden: + + + + Select All + Alles auswählen + + + + Select None + Nichts auswählen + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Aktivieren der Mediadateien, die mit SMPlayer assoziiert werden sollen. Anwenden anklicken, assoziiert die aktivierten Dateien mit SMPlayer. Deaktivierte Dateien werden wiederhergestellt. + + + + Select none + Nichts auswählen + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Hinweis:</b> (Wiederherstellung funktioniert nicht mit Windows Vista). + + + + PrefDrives + + + Drives + Laufwerke + + + + icon + Icon + + + + CD device + CD Laufwerk + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + CDROM Lauwerk auswählen. Erforderlich zum Abspielen von VCDs und Audio CDs. + + + + DVD device + DVD Laufwerk + + + + Choose your DVD device. It will be used to play DVDs. + DVD Laufwerk auswählen. Erforderlich zum Abspielen von DVDs. + + + + Select your &CD device: + &CD Laufwerk auswählen: + + + + Select your &DVD device: + &DVD Laufwerk auswählen: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer wählt kein CDROM, oder DVD Lauwerk als Standard aus. Bevor eine Wiedergabe erfolgt, müssen die Laufwerke bestimmt werden (können beides die gleichen sein). + + + + PrefGeneral + + + General + Allgemein + + + + &General + &Allgemein + + + + Paths + Pfade + + + + Media settings + Media-Einstellungen + + + + Preferred audio and subtitles + Bevorzugter Ton und Untertitel + + + + Video + Video + + + + Start videos in fullscreen + Starte Video im Vollbildmodus + + + + Disable screensaver + Bilschirmschoner abschalten + + + + Audio + Audio + + + + AC3/DTS pass-through S/PDIF + AC3/DTS über S/PDIF + + + + Select the mplayer executable + mplayer (*.exe) auswählen + + + + Executables + Ausführbare Datei + + + + All files + Alle Dateien + + + + Select a directory + Verzeichnis auswählen + + + + MPlayer executable + Ausführbare Mplayer-Datei + + + + Screenshots folder + Order Bilschirmfotos + + + + Video output driver + Video-Ausgabetreiber + + + + Audio output driver + Audio-Ausgabetreiber + + + + Select the audio output driver. + Audioausgabe Treiber wählen. + + + + Remember settings + Einstellungen beibehalten + + + + Preferred audio language + Bevorzugte Audio-Sprache + + + + Preferred subtitle language + Bevorzugte Untertitel-Sprache + + + + Software video equalizer + Software Video Equalizer + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Option, falls der Video-Equalizer die Grafikkarte, oder den Video-Ausgabe Treiber nicht unterstützt.<br><b>Hinweis:</b> Die Option kann inkompatibel zu einigen Video-Ausgabe Treibern sein. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Mit dieser Option erfolgt die Wiedergabe von smplayer im Vollbild-Modus. + + + + Software volume control + Software Lautstärkenkontrolle + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Optional kann der Software-Mixer anstelle des Karten-Mixers eingestellt werden. + + + + Postprocessing quality + Qualität der Nachbearbeitung + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Ändert dynamisch das Niveau der Nachbearbeitung, abhängig von der vorhandenen freien CPU Zeit. Die spezifizierte Zahl, ist das maximale benutzte Niveau. Normalerweise kann irgendeine grosse Zahl angeben werden. + + + + Change volume + Lautstärke ändern + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Falls aktiviert, erinnert sich SMPlayer an die Lautstärke für jede Datei und stellt sie wieder her, sobald die Datei gespielt wird. Für neue Dateien gilt die Standard-Lautstärke. + + + + 0 + 0 + + + + &Change volume on every file + &Lautstärke für jede Datei ändern + + + + Select the &MPlayer executable: + &Die ausführbare Mplayer-Datei auswählen: + + + + &Folder for storing screenshots: + &Verzeichnis für Bilschirmfotos: + + + + &Audio: + &Audio: + + + + &Remember settings for all files (audio track, subtitles...) + &Einstellungen für alle Dateien beibehalten (Audiospur, Untertitel...) + + + + Su&btitles: + &Untertitel: + + + + &Quality: + &Qualität: + + + + Start videos in &fullscreen + &Starte Video im Vollbildmodus + + + + Disable &screensaver + &Bilschirmschoner abschalten + + + + &Default volume: + &Standard Lautstärke: + + + + Use s&oftware volume control + &Benutze Software-Lautstärkeregelung + + + + Ma&x. Amplification: + &Max. Verstärker: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS über S/PDIF + + + + Direct rendering + Direktes Rendern + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Diese Option aktiviert direktes Rendern (wird nicht von allen Video-Codecs und Video-Ausgaben unterstützt)<br><b>WARNUNG:</b> Eventuelle OSD/SUB Fehler! + + + + Double buffering + Doppelpufferung + + + + D&irect rendering + &Direktes Rendern + + + + Dou&ble buffering + &Doppelpufferung + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Doppelpufferung verhindert Flackern, indem zwei Bilder zwischen gespeichert werden, eins wird dekodiert, das andere angezeigt .Falls abgeschaltet, kannes sich negativ im OSD auswirken, aber meistens entfernt es Flackern im OSD. + + + + &Enable postprocessing by default + &Nachbearbeitung als Standard aktivieren + + + + Volume &normalization by default + Lautstärke &normalisieren als Standard + + + + Close when finished + Schließen, wenn beendet + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Wenn diese Option aktiviert ist, wird das Hauptfenster automatisch geschlossen, wenn die aktuelle Datei/Abspielliste beendet ist. + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + &Kanäle als Standard: + + + + &Pause when minimized + &Pause wenn minimiert + + + + Pause when minimized + Pause wenn minimiert + + + + Enable postprocessing by default + Nachbearbeitung als Standard aktivieren + + + + Max. Amplification + Max. Verstärker + + + + Volume normalization by default + Lautstärke normalisieren als Standard + + + + Maximizes the volume without distorting the sound. + Laustärke maximieren, ohne den Ton zu verzerren. + + + + Default volume + Standard Lautstärke + + + + Sets the initial volume that new files will use. + Ausgangslautstärke für neue Dateien festlegen. + + + + Channels by default + Kanäle als Standard + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Stellt das maximale Verstärker-Niveau ein (Standard: 100). Ein Wert von 200 erlaubt , die Standard Lautstärke bis zu einem verdoppelten Maximum zu justieren. Mit Werten unter 100, ist die Anfangslautstärke (die 100% ist), über dem Maximum, das z.B. OSD nicht richtig anzeigen kann. + + + + Uses hardware AC3 passthrough + Benutze Hardware AC3 Durchlauf + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Anfrage der Anzahl von Playback Kanälen. Mplayer fragt den Decoder, den Ton in die angebenen Anzahl der Känäle zu decodieren. Damit sind die Bedingungen für den Decoder erfüllt. Das ist hauptsächlich wichtig, bei Videos mit AC3 Ton (meist DVD). In diesem Fall decodiert liba52 und sorgt für den korrekten Downmix der Kanäle, wie angefordert. Hinweis: Diese Option wird ermöglicht durch AC3 Codecs, Filter für Surround, und Audio-Ausgabe-Treibern (mindestens OSS). + + + + Postprocessing will be used by default on new opened files. + Nachbearbeitung als Standard für neu geöffnete Dateien. + + + + Audio track + Audiospur + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Spezifiziert die Standard Audiospur, die bei neuen Dateien abgespielt wird. Falls die Spur nicht existiert, wird die erste Spur gewählt. <br><b>Hinweis:</b> die <i> "bevorzugte Audiosprache"</i> hat Vorrang vor dieser Option. + + + + Subtitle track + Untertitelspur + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Spezifiziert die Standard Untertitelspur, die bei neuen Dateien abgespielt wird. Falls die Spur nicht existiert, wird die erste Spur gewählt. <br><b>Hinweis:</b> die <i> "bevorzugte Untertitelsprache"</i> hat Vorrang vor dieser Option. + + + + Or choose a track number: + Oder eine Tracknummer wählen: + + + + Audi&o: + Audi&o: + + + + Preferred language: + Bevorzugte Sprache: + + + + Preferre&d audio and subtitles + &Bevorzugter Ton und Untertitel + + + + &Subtitle: + &Untertitel: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Hier kann die bevorzugte Sprache der Tonspur und Untertitel gewählt werden. Bei Medien mit mehreren Tonspuren, oder Untertiteln, wird SMPlayer versuchen die bevorzugte Sprache zu benutzen. Das funktioniert nur mit Medien die eine Info über die Tonspuren und Untertitel bereit stellen, wie DVDs oder mkv-Dateien.<br>Das Feld akzeptiert normale Ausdrücke. Beispiel: <b>es|esp|spa</b> die Tonspur mit folgender Info wird ausgewählt <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + High speed &playback without altering pitch + &Hochgeschwindigkeitswiedergabe ohne Anhebung der Tonhöhe + + + + High speed playback without altering pitch + Hochgeschwindigkeitswiedergabe ohne Anhebung der Tonhöhe + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Ermöglicht eine Änderung der Abspielgeschwindigkeit ohne Anhebung der Tonhöhe. +Benötigt mindestens MPlayer dev SVN - r24924. + + + + Change volume just before playing + Änderung der Lautstärke kurz vor der Wiedergabe + + + + &Video + &Video + + + + Use s&oftware video equalizer + Benutze S&oftware-Video-Equalizer + + + + A&udio + A&udio + + + + Volume + Lautstärke + + + + None + Nichts + + + + Lowpass5 + Tiefpass(filter)5 + + + + Yadif (normal) + Yadif (normal) + + + + Yadif (double framerate) + Yadif (Doppelte Framerate) + + + + Linear Blend + Lineare Überblendung + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + &Deinterlacing als Standard: + + + + Deinterlace by default + Deinterlacing als Standard + + + + Select the deinterlace filter that you want to be used for new videos opened. + Auswahl des Deinterlacing Filter, zum Öffnen von neuen Videos. + + + + Remember time position + Zeitposition beibehalten + + + + Remember &time position + &Zeitposition beibehalten + + + + Change volume just before p&laying + &Änderung der Lautstärke kurz vor der Wiedergabe + + + + Enable the audio equalizer + Audio Equalizer akitivieren + + + + Check this option if you want to use the audio equalizer. + Diese Option aktivieren um den Audio Equalizer zu benutzen. + + + + &Enable the audio equalizer + &Audio Equalizer aktivieren + + + + Draw video using slices + Video anzeigen mit Modus Slices + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Ein-/ Ausschalten des Modus - Slices (16 Pixel Macroblockgruppen). Wenn deaktiviert wird das Bild in einem Durchgang angezeigt. Abhängig von der Grafikkarte und Cache kann dieser Modus schneller oder langsamer sein. Gilt nur für libmpeg2 und libavcodec-Codecs. + + + + Dra&w video using slices + &Video anzeigen mit Modus Slices + + + + &Close when finished playback + &Schließen wenn die Wiedergabe beendet ist + + + + fast + schnell + + + + slow + langsam + + + + fast - ATI cards + schnell - ATI Karten + + + + User defined... + Benutzerdefiniert... + + + + Default zoom + Zoom Standard + + + + This option sets the default zoom which will be used for new videos. + Diese Option setzt den Standard Zoom, der bei neuen Videos angewendet wird. + + + + Default &zoom: + &Standard Zoom: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Hier muß die ausführbare MPlayer-Datei angegeben werden, die von SMPlayer gebraucht wird. <br>SMPlayer benötigt mindestens MPlayer 1.0rc1 (Auch eine aktuelle SVN Version ist empfohlen). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Wenn diese Einstellungen falsch sind, funktioniert SMPlayer nicht! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Hier wird der Order zur Speicherung der Bildschirmfotos festgelegt. Ohne Eingabe wird die Funktion abgeschaltet. + + + + Select the video output driver. %1 provides the best performance. + Auswahl der Video-Ausgabetreiber. %1 liefert die beste Leistung. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 ist der Empfohlene. Zu vermeiden gilt %2 und %3, beide sind langsam und können negative Auswirkungen auf die Leistung haben. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + Normalerweise erinnert sich SMPlayer an die EInstellungen für jede Datei die abgespielt wurde (die gewählte Audio-Spur, Lautstärke, Filter ...). Falls dieses Feature nicht gewünscht wird, kann die Option deaktiviert werden. + + + + If you check this option, SMPlayer will play all files from the beginning. + Mit dieser Option erfolgt die SMplayer Wiedergabe aller Dateien immer von Anfang an. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Ist diese Option aktiviert, wird die Datei pausieren, wenn das Hauptfenster verdeckt ist. Ist das Hauptfenster wieder hergestellt, wird das Abspielen fortgesetzt. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Optional kann der Bildschirmschoner während der Wiedergabe deaktiviert werden.<br>Der Bildschirmschoner wird nach Beendigung der Wiedergabe reaktiviert. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Hier kann die bevorzugte Sprache der Tonspur gewählt werden.Bei Medien mit mehreren Tonspuren,wird Smplayer versuchen die bevorzugte Sprache zu benutzen.Das funktioniert nur mit Medien die eine Info über die Tonspuren bereit stellen, wie DVDs oder mkv-Dateien.<br>Das Feld akzeptiert normale Ausdrücke. Beispiel: <b>es|esp|spa</b> die Tonspur mit folgender Info wird ausgewählt <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Hier kann die bevorzugte Sprache der Untertitel gewählt werden. Bei Medien mit mehreren Untertiteln, wird SMPlayer versuchen die bevorzugte Untertielsprache zu benutzen. Das funktioniert nur mit Medien die eine Info über die Untertitel bereit stellen, wie DVDs oder MKV-Dateien.<br>Das Feld akzeptiert normale Ausdrücke. Beispiel: <b>es|esp|spa</b> der Untertitel mit folgender Info wird ausgewählt <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + Ou&tput driver: + &Ausgabe Gerätetreiber: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Ist diese Option aktiviert, wird die Anfangslautstärke kurz vor der Wiedergabe bestimmt. Dadurch wird eine laute Wiedergabe beim Start vermieden. Benötigt mindestens MPlayer SVN-r27872. + + + + Add black borders on fullscreen + Schwarze Rahmen im Vollbildmodus hinzufügen + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Wenn diese Option aktiviert ist, werden schwarze Ränder im Vollbildmodus dem Bild hinzugefügt. Untertitel werden auf dem schwarzen Rand angezeigt. + + + + &Add black borders on fullscreen + &Schwarze Rahmen im Vollbildmodus hinzufügen + + + + one ini file + eine INI-Datei + + + + multiple ini files + mehrere INI-Dateien + + + + Method to store the file settings + Methode zum Speichern der Datei-Einstellungen + + + + This option allows to change the way the file settings would be stored. The following options are available: + Diese Option ermöglicht die Art zu ändern, wie die Datei-Einstellungen gespeichert werden. Die folgenden Optionen stehen zur Verfügung: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>eine INI-Datei</b>: die Einstellungen für alle wiedergegeben Dateien werden in einer einzigen INI-Datei gespeichert (%1) + + + + The latter method could be faster if there is info for a lot of files. + Zweitere Methode könnte schneller sein, wenn es sich um Informationen von vielen Dateien handelt. + + + + &Store settings in + &Speichere Einstellungen in + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>mehrere INI-Dateien</b>: eine INI-Datei wird für jede wiedergegebene Datei. Diese INI-Dateien werden in den Ordner gespeichert %1 + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + Bei aktivierter Option, wird sich SMPlayer an die letzte Position der Datei erinnern, wenn sie erneut abgespielt wird. Diese Option funktioniert nur mit regulären Dateien (nicht mit DVDs, CDs, URLs ...). + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + Diese Option aktiviert direktes Rendern (wird nicht von allen Video-Codecs und Video-Ausgaben unterstützt)<br><b>WARNUNG:</b> Eventuelle OSD/SUB Fehler! + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Anfrage der Anzahl von Playback Kanälen. Mplayer fragt den Decoder, den Ton in die angebenen Anzahl der Känäle zu decodieren. Damit sind die Bedingungen für den Decoder erfüllt. Das ist hauptsächlich wichtig, bei Videos mit AC3 Ton (meist DVD). In diesem Fall decodiert liba52 und sorgt für den korrekten Downmix der Kanäle, wie angefordert. Hinweis: Diese Option wird ermöglicht durch AC3 Codecs, Filter für Surround, und Audio-Ausgabe-Treibern (mindestens OSS). + + + + PrefInput + + + Keyboard and mouse + Tastatur und Maus + + + + None + Nichts + + + + &Keyboard + &Tastatur + + + + icon + Icon + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Hier kann jeder Tastaturkurzbefehl geändert werden. Doppelklick, oder direktes editieren, in dem Eingabefeld des Tastaturkurzbefehls. Optional kann die Liste zur Weitergabe gespeichert und auf einem anderen Computer weiterverwendet werden. + + + + &Mouse + &Maus + + + + Button functions: + Tasten-Funktion: + + + + Media seeking + Media Positionierung + + + + Volume control + Kontrolle Lautstärke + + + + Zoom video + Zoom Video + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Hier kann jeder Tastaturkurzbefehl geändert werden. Doppelklick, oder direktes editieren, in dem Eingabefeld des Tastaturkurzbefehls. Optional kann die Liste zur Weitergabe gespeichert und auf einem anderen Computer weiterverwendet werden. + + + + &Left click + &Click links + + + + &Double click + &Doppel Click + + + + &Wheel function: + &(Maus) Rad-Funktion: + + + + Shortcut editor + Tastaturkurzbefehl Editor + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + In dieser Tabelle können die Tastaurkurzbefehle geändert werden. Doppelklick oder Enter auf einem Begriff, oder drücken der <b>Tastaturkurzbefehl ändern</b> Taste, um in den <i>Tastaurkurzbefehl modifizieren<i> Modus zu gelangen. Es gibt zwei Wege den Kurzbefehl zu änder: Mit der <b> Erfassen<b> Taste und der anschließenden Eingabe durch die Tastatur (leider funktioniert das nicht bei allen Tasten). Ist die<b> Erfassen<b> Taste ohne Funktion, wird die Kombination eingetippt. + + + + Left click + Click links + + + + Select the action for left click on the mouse. + Auswahl der Aktion, oder links Click mit der Maus. + + + + Double click + Doppel Click + + + + Select the action for double click on the mouse. + Aktion für Doppel Click der Maus auswählen. + + + + Wheel function + (Maus) Rad-Funktion + + + + Select the action for the mouse wheel. + Aktion für (Maus) Rad auswählen. + + + + Play + Wiedergabe + + + + Pause + Pause + + + + Stop + Stop + + + + Fullscreen + Vollbild + + + + Compact + Kompakt + + + + Screenshot + Bildschirmfoto + + + + On top + Auf höchster Position + + + + Mute + Stumm + + + + Frame counter + Einzelbild Zähler + + + + Reset zoom + Reset Zoom + + + + Exit fullscreen + Vollbild beenden + + + + Double size + Doppelte Größe + + + + Play / Pause + Wiedergabe / Pause + + + + Pause / Frame step + Pause / Bildlauf + + + + Playlist + Abspielliste + + + + Preferences + Einstellungen + + + + No function + Keine Funktion + + + + Change speed + Geschwindigkeit ändern + + + + Normal speed + Normale Geschwindigkeit + + + + Keyboard + Tastatur + + + + Mouse + Maus + + + + Middle click + Click Mitte + + + + Select the action for middle click on the mouse. + Auswahl der Mausaktion für Click Mitte. + + + + M&iddle click + &Click mitte + + + + X Button &1 + X Taste &1 + + + + X Button &2 + X Taste &2 + + + + Go backward (short) + Gehe rückwärts (kurz) + + + + Go backward (medium) + Gehe rückwärts (medium) + + + + Go backward (long) + Gehe rückwärts (lang) + + + + Go forward (short) + Gehe vorwärts (kurz) + + + + Go forward (medium) + Gehe vorwärts (medium) + + + + Go forward (long) + Gehe vorwärts (lang) + + + + OSD - Next level + OSD - Nächste Stufe + + + + Show context menu + Kontextmenü anzeigen + + + + &Right click + &Click rechts + + + + Increase volume + Lautstärke erhöhen + + + + Decrease volume + Lautstärke reduzieren + + + + X Button 1 + X Taste 1 + + + + Select the action for the X button 1. + Aktion für X Taste 1 auswählen. + + + + X Button 2 + X Taste 2 + + + + Select the action for the X button 2. + Aktion für X Taste 2 auswählen. + + + + Show video equalizer + Video Equalizer anzeigen + + + + Show audio equalizer + Audio Equalizer anzeigen + + + + Always on top + Immer im Vordergrund + + + + Never on top + Niemals im Vordergrund + + + + On top while playing + Während des Abspielens im Vordergrund + + + + PrefInterface + + + Interface + Interface + + + + <Autodetect> + <Automatisch> + + + + Default + Standard + + + + &Interface + &Interface + + + + Seeking + Positionierung + + + + Recent files + Neueste Dateien + + + + Never + Niemals + + + + Whenever it's needed + Wann immer es benötigt wird + + + + Only after loading a new video + Erst nach dem Laden eines neuen Videos + + + + Language + Sprache + + + + Here you can change the language of the application. + Hier kann die Sprache des Programms geändert werden. + + + + Instances + Prozesse + + + + &Short jump + &Kleiner Sprung + + + + &Medium jump + &Normaler Sprung + + + + &Long jump + &Langer Sprung + + + + Mouse &wheel jump + &Sprung per Mausrad + + + + &Use only one running instance of SMPlayer + &Nur einen laufenden SMPlayer-Prozess verwenden + + + + Ma&x. items + &Max. Stücke + + + + St&yle: + &Stil: + + + + Ico&n set: + &Iconsatz: + + + + L&anguage: + &Sprache: + + + + Main window + Hauptfenster + + + + Auto&resize: + &Automatische Größenveränderung: + + + + R&emember position and size + &Position und Größe beibehalten + + + + Default font: + Standard Schriftart: + + + + &Change... + &Ändern... + + + + &Behaviour of time slider: + &Verhalten des Zeit - Schiebereglers: + + + + Seek to position while dragging + Positionierung in der Bewegung anstreben + + + + Seek to position when released + Positionierung erst anstreben wenn freigegeben + + + + TextLabel + TextKennzeichnung + + + + &Seeking + &Positionierung + + + + Ins&tances + &Prozesse + + + + Autoresize + Automatische Größenveränderung + + + + The main window can be resized automatically. Select the option you prefer. + Das Hauptfenster kann automatisch redimensioniert werden. Auswahl der bevorzugten Optionen. + + + + Remember position and size + Position und Größe beibehalten + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Mit dieser Option wird die Position und Größe des Hauptfensters gespeichert und bei einem erneuten Start von SMPlayer wieder hergestellt. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Auswahl der maximalen Einträge die in dem <b>Öffnen->Neueste Dateien</b> Untermenü angezeigt werden. Bei null wird das Menü überhaupt nicht angezeigt. + + + + Icon set + Iconsatz + + + + Select the icon set you prefer for the application. + Auswahl des bevorzugten Iconsatzes für das Programm. + + + + Style + Stil + + + + Select the style you prefer for the application. + Auswahl des bevorzugten Stils für das Programm. + + + + Default font + Standard Schriftart + + + + You can change here the application's font. + Hier kann die Schriftart des Programms geändert werden. + + + + Short jump + Kleiner Sprung + + + + Select the time that should be go forward or backward when you choose the %1 action. + Zeitbestimmung für Vorwärts, oder Rückwärts, bei Auswahl %1 Aktion. + + + + short jump + kleiner Sprung + + + + Medium jump + Normaler Sprung + + + + medium jump + normaler Sprung + + + + Long jump + Langer Sprung + + + + long jump + langer Sprung + + + + Mouse wheel jump + Sprung per Mausrad + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Zeitbestimmung für Vorwärts, oder Rückwärts per Mausrad. + + + + Behaviour of time slider + Verhalten des Zeit - Schiebereglers + + + + Select what to do when dragging the time slider. + Auswahl der Aktion bei Benutzung des Zeit-Schiebereglers. + + + + Use only one running instance of SMPlayer + Nur einen laufenden SMPlayer-Prozess verwenden + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Mit dieser Option wird festgelegt, das die laufende Instanz von SMPlayer, beim Öffnen von anderen Dateien verwenden wird. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer muß einen Port abfragen, um Befehle von einer anderen Instanz zu bekommen. Der Port kann geändert werden, falls der Standard Port von einem anderen Programm benutzt wird. + + + + Default GUI + Standard GUI + + + + Mini GUI + Mini GUI + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Auswahl der GUI für Anwendungen. Derzeit sind zwei verfügbar. Standard GUI und Mini GUI. <br>Die <b>Standard GUI</b> bietet die traditionelle GUI, mit Symbolleiste und Kontrollbar. Die <b>Mini GUI</b> bietet eine einfache GUI, ohne Symbolleiste und eine Steuerleiste mit wenigen Buttons.<br><b>Hinweis:</b>Diese Option wird erst nach einem Neustart aktiv. + + + + &GUI + &GUI + + + + Automatic port + Port automatisch + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer muss einen Port abfragen, um Befehle von anderen Prozessen zu erhalten. Mit dieser Option wird der Port automatisch gewählt. + + + + Manual port + Port manuell + + + + Port to listen + Abzufragender Port + + + + &Automatic + &Automatisch + + + + &Manual + &Manuell + + + + Floating control + Schwebendes Kontrollelement + + + + Animated + Animiert + + + + If this option is enabled, the floating control will appear with an animation. + Bei aktivierter Option wird das schwebende Kontrollelement animiert dargestellt. + + + + Width + Breite + + + + Specifies the width of the control (as a percentage). + Gibt die Breite des Kontrollelements an (als Prozentsatz). + + + + Margin + Begrenzung + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + Optionale Anzahl der Pixel, für den Abstand zum unteren Bildschirmrand, des schwebenden Kontollelements. Nützlich, wenn der Bildschirm ein TV ist, Overscan könnte verhindern das die Kontrolle sichtbar ist. + + + + Display in compact mode too + Ebenfalls Darstellung im Kompaktmodus + + + + If this option is enabled, the floating control will appear in compact mode too. Warning: the floating control has not been designed for compact mode and it might not work properly. + Bei aktivierter Option, wird das schwebende Kontrollelement im Kompaktmodus dargestellt. Warnung : Das schwebende Kontrollelement wurde nicht für den Kompaktmodus designed und wird wahrscheinlich nicht richtig funktionieren. + + + + Bypass window manager + Bypass Window Manager + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + MIt dieser Option , wird das Kontrollelement unter Umgehung des Window Managers dargestellt. Deaktivieren der Option, bei nicht funktionieren, der schwebenden Kontrollelemente. + + + + &Floating control + &Schwebendes Kontrollelement + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + Das schwebende Kontrollelement wird per Mausbewegung am unteren Ende des Bildschirms, bei Vollbild aktiviert. + + + + &Animated + &Animiert + + + + &Width: + &Breite: + + + + 0 + 0 + + + + &Margin: + &Begrenzung: + + + + Display in &compact mode too + &Ebenfalls Darstellung im Kompaktmodus + + + + &Bypass window manager + &Bypass Window Manager + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + Bei aktivierter Option, wird das schwebende Kontrollelement im Kompaktmodus dargestellt. Warnung : Das schwebende Kontrollelement wurde nicht für den Kompaktmodus designed und wird wahrscheinlich nicht richtig funktionieren. + + + + Mpc GUI + Mpc GUI + + + + PrefPerformance + + + Performance + Leistungsverhalten + + + + &Performance + &Leistungsverhalten + + + + Priority + Priorität + + + + Select the priority for the MPlayer process. + Auswahl der Prozessorpriorität für mplayer. + + + + realtime + Realzeit + + + + high + Hoch + + + + abovenormal + Über Normal + + + + normal + Normal + + + + belownormal + Niedrig + + + + idle + Leerlauf + + + + Cache + Cache + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Einstellung des Cachespeichers, kann Leistungsverhalten auf langsamen Systemen verbessern + + + + Allow frame drop + Überspringen von Bildern erlauben + + + + Synchronization + Synchronisation + + + + Audio/video auto synchronization + Automatische Audio/Video Synchronisation + + + + Fast audio track switching + Schneller Tonspurwechsel + + + + Fast seek to chapters in dvds + Schnelle Suche in DVD-Kapiteln + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Festlegen der Prozessorpriorität gemäß der Verfügbarkeit unter Windows.<br><b>WARNUNG:</b>Echtzeitpriorität kann das System blockieren. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Überspringen einiger Einzelbilder, um A/V Synchronisation auf langsamen Systemen zu gewährleisten. + + + + Allow hard frame drop + Verstärktes überspringen von Bildern erlauben + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Intensive Einzelbildersprünge (Brüche beim Dekodieren) . Führt zu Bildverzerrungen! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Justiert stufenweise die A/V Synchronisierung, die auf Audioverzögerungen (Delay) basiert. + + + + Priorit&y: + &Priorität: + + + + &Allow frame drop + &Überspringen von Bildern erlauben + + + + Allow &hard frame drop (can lead to image distortion) + &Verstärktes überspringen von Bildern erlauben. (Kann zu Bildverzerrungen führen) + + + + Audio/&video auto synchronization + &Automatische Audio/Video Synchronisation + + + + Fact&or: + &Faktor: + + + + &Fast audio track switching + &Schneller Tonspurwechsel + + + + Fast &seek to chapters in dvds + &Schnelle Suche in DVD-Kapiteln + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Mit dieser Option wird die schnellste Methode zum Suchen der Kapitel gewählt, aber es funktioniert nicht mit allen Discs. + + + + Skip loop filter + Loop Filter übergehen + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Mögliche Werte:<br> <b> Ja </ b>: wird versuchen die schnellste Methode zum Wechseln des Audio-Tracks zu finden (evt funktioniert es nicht, mit einigen Formaten).<br> <b> Nein </ b>: der Mplayer Prozeß startet erneut, wenn der Audio-Track gewechselt wird.<br> <b> Automatisch </ b>: SMPlayer wird entscheiden was zu tun ist, je nach MPlayer Version. + + + + Cache for files + Cache für Dateien + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Diese Option gibt an, wie viel Speicher (in kByte), beim Precaching einer Datei, verwendet wird. + + + + Cache for streams + Cache für Streams + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Diese Option gibt an, wie viel Speicher (in kByte), beim Precaching einer URL, verwendet wird. + + + + Cache for DVDs + Cache für DVDs + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Diese Option gibt an, wie viel Speicher (in kByte), beim Precaching von DVDs, verwendet wird.<br><b>Warnung:</b> Suchen wird eventuell nicht funktionieren (inklusive Kapitelsprünge), wenn Cache für DVDs aktiviert ist. + + + + &Cache + &Cache + + + + Cache for &DVDs: + Cache für &DVDs: + + + + Cache for &local files: + Cache für &locale Dateien: + + + + Cache for &streams: + Cache für &Streams: + + + + Enabled + Eingeschaltet + + + + Skip (always) + Überspringen (immer) + + + + Skip only on HD videos + Überspringen nur bei HD Videos + + + + Loop &filter + Loop &Filter + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Übergeht den Loop Filter (AKA Deblocking) während der H.264 Decodierung. Da bei den gefilterten Einzelbildern davon ausgegeangen wird, dass sie als Referenz für das Entschlüsseln von abhängigen Einzelbildern verwendet werden, hat dies eine schlechtere Wirkung auf die Qualität , als nicht zu deblocken bei z.B MPEG-2 Videos. Aber zumindest bei HDTV, mit hohen Bitraten, ergiebt sich eine große Beschleunigung ohne sichtbaren Qualitätsverlust. + + + + Possible values: + Mögliche Werte: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Eingeschaltet</b>: der Loop Filter wird nicht ausgelassen + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Überspringen (immer)</b>: Der Loop Filter wird ausgelassen, unabhängig von der Videoauflösung + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Überspringen nur bei HD Videos</b>: der Loop Filter wird nur ausgelassen bei Videos, deren Höhe %1, oder größer ist. + + + + Cache for audio CDs + Cache für Audio CDs + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Diese Option gibt an, wieviel Speicher (in kBytes), bei Precaching für Audio-CD, verwendet wird. + + + + Cache for &audio CDs: + Cache für &Audio CDs: + + + + Cache for VCDs + Cache für VCDs + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Diese Option gibt an, wie viel Speicher (in kByte), beim Precaching von VCDs, verwendet wird. + + + + Cache for &VCDs: + Cache für &VCDs: + + + + Threads for decoding + Threads zur Dekodierung + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Legt die Anzahl der Threads zur Dekodierung fest. Nur für MPEG-1 / 2 und H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Threads zur Dekodierung (MPEG-1/2 and H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + Festlegen der Prozessorpriorität gemäß der Verfügbarkeit unter Windows.<br><b>WARNUNG:</b>Echtzeitpriorität kann das System blockieren. + + + + PrefPlaylist + + + Playlist + Abspielliste + + + + Automatically add files to playlist + Dateien automatisch zur Abspielliste hinzugügen + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Wenn diese Option aktiviert ist, wird SMPlayer jedes Mal wenn eine Datei geöffnet wird, die Wiedergabeliste leeren und dann erst die Datei hinzufügen. Bei DVDs, CDs und VCDs werden alle Dateien der Disc hinzugefügt. + + + + Add consecutive files + Aufeinander folgende Dateien hinzufügen + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Wenn diese Option aktiviert ist, wird SMPlayer aufeinander folgende Dateien suchen (z. B. video_1.avi, video_2.avi ...) und zur Abspielliste hinzugefügen, wenn Dateien gefunden wurden. + + + + &Playlist + &Abspielliste + + + + &Automatically add files to playlist + &Dateien automatisch zur Abspielliste hinzugügen + + + + Add &consecutive files + &Aufeinander folgende Dateien hinzufügen + + + + PrefSubtitles + + + Subtitles + Untertitel + + + + Choose a ttf file + TTF-Datei wählen + + + + Truetype Fonts + Truetype Schriftarten (*.ttf) + + + + &Subtitles + &Untertitel + + + + Autoload + Automatisch laden + + + + Select first available subtitle + Den ersten vorhandenen Untertitel auswählen + + + + Same name as movie + Filmtitel als Name + + + + All subs containing movie name + Alle Untertitel die Filmnamen enthalten + + + + All subs in directory + Alle Untertitel im Verzeichnis + + + + Position + Position + + + + 0 + 0 + + + + Top + Höchste Position + + + + Bottom + Niedrigste Position + + + + Include subtitles on screenshots + Untertitel miteinbeziehen auf Bidschirmfotos + + + + Font + Schriftart + + + + Select the font which will be used for subtitles (and OSD): + Auswahl der Schriftart für Untertitel (und OSD): + + + + Size + Größe + + + + No autoscale + Keine automatische Skalierung + + + + Proportional to movie height + Proportional zu Filmhöhe + + + + Proportional to movie width + Proportional zur Fimbreite + + + + Proportional to movie diagonal + Proportional zur Filmdiagonale + + + + Subtitle position + Position der Untertitel + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Diese Option bestimmt die Position der Untertitel über dem Videofenster.<i>100</i> bedeutet Unten (Buttom), während <i>0</i> Oben (Top) bedeutet. + + + + Au&toload subtitles files (*.srt, *.sub...): + &Untertitel automatisch laden (*.srt,*.sub...): + + + + S&elect first available subtitle + &Den ersten vorhandenen Untertitel auswählen + + + + &Default subtitle encoding: + &Standard Untertitel Encodierung: + + + + Default &position of the subtitles on screen + &Standard Position der Untertitel auf dem Bildschirm + + + + &Include subtitles on screenshots + &Untertitel auf Bidschirmfotos miteinbeziehen + + + + &TTF font: + &TTF Schriftart: + + + + S&ystem font: + &System-Schriftart: + + + + A&utoscale: + &Automatische Skalierung: + + + + Default subtitle encoding + Standard Untertitel Encodierung + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Mit dieser Option werden Untertitel in Bildschirmfotos übernommen. Hinweis : Das kann manchmal zu Schwierigkeiten führen. + + + + TTF font + TTF Schriftart + + + + System font + System-Schriftart + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Auswahl der Systemschriftt für Untertitel und OSD. +<b>Hinweis:</b> Erfordert MPlayer mit fontconfig Support. + + + + Autoscale + Automatische Skalierung + + + + Text color + Textfarbe + + + + Select the color for the text of the subtitles. + Auswahl Textfarbe der Untertitel. + + + + Border color + Rahmenfarbe + + + + Select the color for the border of the subtitles. + Auswahl Rahmenfarbe Untertitel. + + + + Select the subtitle autoload method. + Auswahl der Methode zum automatischen Laden der Untertitel. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Wenn mehr als eine Untertitelspur zur Verfügung steht, wird automatisch die erste gewählt, es sei denn eine andere Einstellung wurde vom Anwender festgelegt. + + + + Select the subtitle autoscaling method. + Auswahl der Untertitel - Autoskalierungsmethode. + + + + Select the encoding which will be used for subtitle files by default. + Auswahl der Standard Untertiteldateien - Enkodierung. + + + + Try to autodetect for this language + Versuche die Sprache automatisch zu erkennen + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Bei aktivierter Option, wird versucht die Kodierung der Untertitel automatisch zu erkennen. Sollte dies nicht gelingen, wird zurück auf Standard gesetzt. Diese Option erfordert einen MPlayer mit ENCA Unterstützung. + + + + Subtitle language + Untertitelsprache + + + + Select the language for which you want the encoding to be guessed automatically. + Sprachauswahl für die automatische Erkennung der Kodierung. + + + + Encoding + Enkodierung + + + + Try to a&utodetect for this language: + &Versuche die Sprache automatisch zu erkennen: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Auswahl der TTF Schriftart für Untertitel. Normalerweise befinden sich viele TTF Schriftarten in %1 + + + + Outline + Kontur + + + + Select the font for the subtitles. + Auswahl der Schriftart für die Untertitel. + + + + The size in pixels. + Die Größe in Pixel. + + + + Bold + Bold + + + + If checked, the text will be displayed in <b>bold</b>. + Wenn diese Option aktiviert ist, wird der Text in <b>bold</b> angezeigt. + + + + Italic + Italic + + + + If checked, the text will be displayed in <i>italic</i>. + Wenn diese Option aktiviert ist, wird der Text in <i>italic</i> angezeigt. + + + + Left margin + Begrenzung links + + + + Specifies the left margin in pixels. + Spezifiziert den linken Rand in Pixeln. + + + + Right margin + Begrenzung rechts + + + + Specifies the right margin in pixels. + Spezifiziert den rechten Rand in Pixeln. + + + + Vertical margin + Vertikale Begrenzung + + + + Specifies the vertical margin in pixels. + Spezifiziert den vertikalen Abstand in Pixeln. + + + + Horizontal alignment + Horizontale Ausrichtung + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + Spezifiziert die horizontale Ausrichtung. Mögliche Werte sind links, zentriert und rechts. + + + + Vertical alignment + Vertikale Ausrichtung + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + Spezifiziert die vertikale Ausrichtung. Mögliche Werte: unten, Mitte und oben. + + + + Border style + Rahmenstil + + + + Specifies the border style. Possible values: outline and opaque box. + Spezifiziert den Rahmenstil. Mögliche Werte: Kontur und undurchsichtiges Feld. + + + + Shadow + Schatten + + + + Si&ze: + &Größe: + + + + Bol&d + Bol&d + + + + &Italic + &Italic + + + + Colors + Farben + + + + &Text: + &Text: + + + + &Border: + &Rahmen: + + + + Margins + Begrenzungen + + + + L&eft: + &Links: + + + + &Right: + &Rechts: + + + + Verti&cal: + Verti&kal: + + + + Alignment + Ausrichtung + + + + &Horizontal: + &Horizontal: + + + + &Vertical: + &Vertikal: + + + + Border st&yle: + &Rahmenstil: + + + + &Outline: + &Kontur: + + + + Shado&w: + &Schatten: + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + Die folgenden Optionen definieren den Stil für non-styled Untertitel. (srt, sub...). + + + + Left + horizontal alignment + Links + + + + Centered + horizontal alignment + Zentriert + + + + Right + horizontal alignment + Rechts + + + + Bottom + vertical alignment + Niedrigste Position + + + + Middle + vertical alignment + Mitte + + + + Top + vertical alignment + Höchste Position + + + + Outline + border style + Kontur + + + + Opaque box + border style + Undurchlässig + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + Wenn der Rahmenstil auf <i>Kontur</ i> gesetzt wurde, diese Option gibt die Breite in Pixel rund um den Text an. + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + Wenn der Rahmenstil auf <i>Kontur</ i> gesetzt wurde, diese Option gibt die Tiefe der Schatten hinter dem Text in Pixel an. + + + + Enable normal subtitles + Aktivieren von normalen Untertiteln + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + Klick auf diese Schaltfläche ermöglicht normale / herkömmliche Untertitel zu wählen. Diese können nur in weiß dargestellt werden. + + + + Enable SSA/ASS subtitles + Aktiviere SSA/ASS Untertitel + + + + Normal subtitles + Normale Untertitel + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + Diese Option ändert nicht die Größe der Untertitel im aktuellen Video. Dazu die Optionen <i>Größe +</i> und <i>Size-</i> im Untertitelmenü anwenden. + + + + Default scale + Standard Skalierung + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + Diese Option spezifiziert die Skalierung, der Standard Schriftart bei normalen Untertiteln, welche bei neu geöffneten Dateien angewendet wird. + + + + SSA/ASS subtitles + SSA/ASS Untertitel + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + Diese Option spezifiziert die Skalierung der Standard Schriftart, bei SSA/AAS Untertiteln, welche bei neu geöffneten Dateien angewendet wird. + + + + Line spacing + Zeilenabstand + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + Bestimmung des Zeilenabstands. Kann negative Werte enthalten. + + + + &Font and colors + &Schriftart und Farben + + + + Enable &normal subtitles + &Aktivieren von normalen Untertiteln + + + + Enable SSA/&ASS subtitles + Aktiviere SSA/&ASS Untertitel + + + + Default s&cale: + &Standard Skalierung: + + + + Defa&ult scale: + &Standard Skalierung: + + + + &Line spacing: + &Zeilenabstand: + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + Klick auf diese Schaltfläche, aktiviert die neue SSA / ASS-Bibliothek. Diese erlaubt die Anzeige der Untertitel mit mehreren Farben, Schriftarten, ... + + + + Freetype support + Freetype Unterstützung + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + Normalerweise sollte diese Option nicht deaktiviert werden. Als Ausnahme gilt, wenn MPlayer ohne Freetype Unterstützung kompiliert wurde. <b>Deaktivierung dieser Option verhindert korrekte Untertitel Unterstützung!</b> + + + + Freet&ype support + Freet&ype Unterstützung + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + Mit dieser Option werden Untertitel in Bildschirmfotos übernommen. <b>Hinweis:</b> Das kann manchmal zu Schwierigkeiten führen. + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Hilfe + + + + OK + OK + + + + Cancel + Abbrechen + + + + Apply + Übernehmen + + + + Help + Hilfe + + + + SMPlayer - Preferences + SMPlayer - Einstellungen + + + + QObject + + + This is SMPlayer v. %1 running on %2 + Das ist SMPlayer v.%1 running on %2 + + + + the main window will be closed when the file/playlist finishes. + Das Hauptfenster wird geschlossen wenn die Datei/Abspielliste benendet ist. + + + + will show this message and then will exit. + Zeigt diesen Hinweis und wird beendet. + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + versucht, eine Beziehung zu einem anderen laufenden Prozeß herzustellen und zu ihm die spezifizierte Aktionen zu schicken. Beispiel: -action pause Die restlichen Optionen (falls vorhanden) werden ignoriert und die Anwendung beendet. Der Status bringt 0 für Erfolg oder -1 für Ausfall zurück. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list ist eine Liste der Aktionen, die durch Leerzeichen (Space) getrennt werden. Die Aktionen werden gleich nach dem Laden der Datei (falls vorhanden) in dem Auftrag durchgeführt, der zuvor eingetragen wurde. Für wählbare Aktionen kann true (wahr) oder false (falsch) als Parameter angegeben werden. Beispiel: -actions "fullscreen compact true". Anführungsstriche müßen bei mehr als einer Aktion gesetzt werden. + + + + media + Media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + Falls ein weiterer Prozess läuft, Medien werden dort in die Playlist eingefügt. Läuft kein weiterer Prozess, die Option wird ingnoriert und Dateien werden mit einem neuen Prozess geöffnet. + + + + the main window won't be closed when the file/playlist finishes. + Das Hauptfenster wird geschlossen wenn die Datei/Abspielliste benendet ist. + + + + the video will be played in fullscreen mode. + das Video wird im Vollbildmodus abgespielt. + + + + the video will be played in window mode. + das Video wird im Fenstermodus abgespielt. + + + + Enqueue in SMPlayer + Einreihen in SMPlayer + + + + opens the mini gui instead of the default one. + Öffnet die Mini-Gui, anstelle der Standard-Gui. + + + + Restores the old associations and cleans up the registry. + Stellt die alten Zuordnungen wieder her und bereinigt die Registry. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'Media' ist jede Art von Datei die SMPlayer öffnen kann. Das kann eine lokale Datei sein, eine DVD (e.g. dvd://1), ein Internetstream (e.g. mms://....) oder eine lokale Abspielliste im Format m3u. Wenn die Option Abspielliste in Gebrach ist, das heißt SMPlayer gibt die Abspiellisten-Option an MPlayer weiter, MPlayer verarbeitet die Abspielliste, nicht SMPlayer. + + + + Usage: + Anwendung: + + + + directory + Verzeichnis + + + + action_name + Aktion_Name + + + + action_list + Aktion_Liste + + + + opens the default gui. + Öffnet die Standard GUI. + + + + subtitle_file + Untertitel_Datei + + + + specifies the subtitle file to be loaded for the first video. + Spezifiziert die zu ladende Untertiteldatei für das erste Video. + + + + %1 second(s) + + %1 Sekunde(n) + %1 Sekunden + + + + + %1 minute(s) + + %1 Minute(n) + %1 Minuten + + + + + %1 and %2 + %1 und %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + Spezifiziert das Verzeichnis, wo SMPlayer die eigenen Konfigurationsdateien speichert (smplayer.ini, smplayer_files.ini...) + + + + disabled + aspect_ratio + Ausgeschaltet + + + + auto + aspect_ratio + Auto + + + + unknown + aspect_ratio + Unbekannt + + + + opens the mpc gui. + öffnet die MPC GUI. + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + ZIP/UNZIP API Fehler %1 + + + + SeekWidget + + + icon + Icon + + + + label + Kennzeichnung + + + + ShortcutGetter + + + Modify shortcut + Tastaturkurzbefehl modifizieren + + + + Clear + Löschen + + + + Press the key combination you want to assign + Tastenkombination betätigen, die zugewiesen werden soll + + + + Capture + Erfassen + + + + Capture keystrokes + Tastenanschläge erfassen + + + + SubChooserDialog + + + Subtitle selection + Auswahl Untertitel + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Das Archiv beinhaltet mehr als eine Untertiteldatei. Bitte wählen, welche extrahiert werden soll. + + + + Select All + Alles auswählen + + + + Select None + Nichts auswählen + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Positionierung + + + + &Jump to: + &Sprung zu: + + + + TristateCombo + + + Auto + Auto + + + + Yes + Ja + + + + No + Nein + + + + VideoEqualizer + + + Contrast + Kontrast + + + + Brightness + Helligkeit + + + + Hue + Farbe + + + + Saturation + Sättigung + + + + Gamma + Gamma + + + + &Reset + &Reset + + + + &Set as default values + &Als Standard Wert einstellen + + + + Use the current values as default values for new videos. + Die jetzigen Werte als Standardwerte für neue Videos. + + + + Set all controls to zero. + Alle Steuerungen auf Null. + + + + Video Equalizer + Video Equalizer + + + + Information + Information + + + + The current values have been stored to be used as default. + Die aktuellen Werte wurden als Standard gespeichert. + + + + VideoPreview + + + Video preview + Video Vorschau + + + + Cancel + Abbrechen + + + + Generated by SMPlayer + Generiert durch SMPlayer + + + + Creating thumbnails... + Kreieren von Vorschaubildern ... + + + + File: %1 + Datei: %1 + + + + Size: %1 MB + Größe: %1 MB + + + + Resolution: %1 x %2 + Auflösung: %1 x %2 + + + + Length: %1 + Dauer: %1 + + + + Save file + Datei speichern + + + + Images (*.png *.jpg) + Bilder (*.png *.jpg) + + + + Error saving file + Fehler beim Speichern der Datei + + + + The file couldn't be saved + Die Datei konnte nicht gespeichert werden + + + + Error + Fehler + + + + The following error has occurred while creating the thumbnails: + Folgende Fehler ist aufgetreten während der Erstellung der Vorschaubilder: + + + + The temporary directory (%1) can't be created + Das temporäre Verzeichnis (%1) kann nicht erstellt werden + + + + The mplayer process didn't run + Der MPlayer-Prozess läuft nicht + + + + Resolution: %1x%2 + Auflösung: %1 x %2 + + + + Video format: %1 + Videoformat: %1 + + + + Frames per second: %1 + Bilder pro Sekunde: %1 + + + + Aspect ratio: %1 + Aspect Ratio: %1 + + + + Video bitrate: %1 kbps + Video Bitrate: %1 kbps + + + + Audio bitrate: %1 kbps + Audio Bitrate: %1 kbps + + + + Audio rate: %1 Hz + Audiorate: %1 Hz + + + + The file %1 can't be loaded + Die Datei %1 kann nicht geladen werden + + + + No filename + Kein Dateiname + + + + The mplayer process didn't start while trying to get info about the video + Bei dem Versuch Infos über das Video zu bekommen, konnte der MPLayer Prozess nicht starten + + + + The length of the video is 0 + Die Dauer des Videos ist 0 + + + + The file %1 doesn't exist + Die Datei %1 existiert nicht + + + + Images + Bilder + + + + No info + Keine Info + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + Video Bitrate: %1 kbps + + + + Audio bitrate: %1 + Audio Bitrate: %1 kbps + + + + Audio rate: %1 + Audiorate: %1 Hz + + + + VideoPreviewConfigDialog + + + Default + Standard + + + + Video Preview + Video Vorschau + + + + &File: + &Datei: + + + + &Columns: + &Spalten: + + + + &Rows: + &Reihen: + + + + Add playing time to thumbnails + Abspielzeit den Vorschaubildern hinzufügen + + + + &Aspect ratio: + &Aspect Ratio: + + + + &Seconds to skip at the beginnning: + &Sekunden die am Anfang übersprungen werden: + + + + &Maximum width: + &Maximale Breite: + + + + The preview will be created for the video you specify here. + Die Vorschau wird für das ausgewählte Video erstellt. + + + + The thumbnails will be arranged on a table. + Die Vorschaubilder werden auf einer Bildebene arrangiert. + + + + This option specifies the number of columns of the table. + Diese Option ergibt die Anzahl der Spalten auf der Bildebene. + + + + This option specifies the number of rows of the table. + Diese Option ergibt die Anzahl der Zeilen auf der Bildebene. + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + Bei aktivierter Option wird die Abspielzeit zu jedem Vorschaubild angezeigt. + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + Wenn das Seitenverhältnis des Videos falsch ist, kann hier ein anderer Wert spezifiziert werden. + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + Normalerweise sind die ersten Bilder schwarz, so ist es eine gute Idee einige Sekunden am Anfang des Videos zu überspringen. Diese Option ermöglicht es zu spezifizieren, wie viele Sekunden übersprungen werden. + + + + This option specifies the maximum width in pixels that the generated preview image will have. + Diese Option gibt die maximale Breite in Pixel, für das zu erstellende Vorschaubild an. + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + Einige Bilder werden aus dem Video extrahiert um die Vorschau zu generieren. PNG ergibt vielleicht bessere Qualität. + + + + Add playing &time to thumbnails + &Abspielzeit den Vorschaubildern hinzufügen + + + + &Extract frames as + &Extrahiere Bilder als + + + + Enter here the DVD device or a folder with a DVD image. + Eingabe DVD Laufwerk, oder einen Ordner mit einem DVD-Image. + + + + &DVD device: + &DVD Laufwerk: + + + + VolumeSliderAction + + + Volume + Lautstärke + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_el_GR.ts b/plugins/smplayer_plugin/translations/smplayer_el_GR.ts new file mode 100644 index 000000000..834754a6e --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_el_GR.ts @@ -0,0 +1,7220 @@ + + + + About + + + Version: %1 + Έκδοση: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Το πρόγραμμα αυτό είναι ελεύθερο λογισμικό; μπορείτε να το αναδιανείμετε και/ή να το αλλάξετε σύμφωνα με τους όρους της GNU Γενικής δημόσια Άδειας όπως εκδόθηκε από τόν Ελεύθερου Λογισμικού Οργανισμό είτε με άδεια τύπου 2, είτε (κατ' επιλογήν σας) οποιασδήποτε μετέπειτα μεταβολής της. + + + + The following people have contributed with translations: + + + + + German + + + + + Slovak + + + + + Italian + + + + + French + + + + + %1, %2 and %3 + %1, %2 και %3 + + + + Simplified-Chinese + + + + + Russian + + + + + %1 and %2 + %1 και %2 + + + + Hungarian + + + + + Polish + + + + + Japanese + + + + + Dutch + + + + + Ukrainian + + + + + Portuguese - Brazil + + + + + Georgian + + + + + Czech + + + + + Bulgarian + + + + + Turkish + + + + + Swedish + + + + + Serbian + + + + + Traditional Chinese + + + + + Romanian + + + + + Portuguese - Portugal + + + + + Greek + Ελληνικά + + + + Finnish + + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + + + + + About SMPlayer + Περί SMPlayer + + + + &Info + + + + + icon + εικόνα + + + + &Contributions + + + + + &Translators + + + + + &License + + + + + Visit our web for updates: + + + + + Get help in our forum: + + + + + You can support SMPlayer by making a donation. + + + + + More info + + + + + Korean + + + + + Macedonian + + + + + Basque + + + + + Using MPlayer %1 + + + + + Catalan + + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Όνομα + + + + Description + Περιγραφή + + + + Shortcut + Συντόμευση + + + + &Save + &Σώσε + + + + &Load + &Άνοιξε + + + + Key files + Κλειδί αρχείου + + + + Choose a filename + Επιλέξτε αρχείο + + + + Confirm overwrite? + Επιβεβαιώνετε επαν-εγγραφή? + + + + The file %1 already exists. +Do you want to overwrite? + Το αρχείο %1 υπάρχει ήδη. +Θέλετε να γράψετε άλλο πάνω του? + + + + Choose a file + Επιλέξτε αρχείο + + + + Error + Σφάλμα + + + + The file couldn't be saved + Το αρχείο δεν δύνατο να σωθεί + + + + The file couldn't be loaded + Το αρχείο δεν δύναται να φορτωθεί + + + + &Change shortcut... + Α&λλαγή συντόμευσης... + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + &Άκυρο + + + + &Set as default values + &Ρύθμιση σαν αρχικών τιμών + + + + Use the current values as default values for new videos. + Χρήση τρεχουσών ρυθμίσεων για τα νέα βίντεο. + + + + Set all controls to zero. + Αποθήκευση όλων των ρυθμίσεων σε μηδέν. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer καταγραφή + + + + SMPlayer - smplayer log + SMPlayer - smplayer καταγραφή + + + + &Open + &Άνοιξε + + + + &Play + &Παίξε + + + + &Video + &Εικόνα + + + + &Audio + &Ήχος + + + + &Subtitles + &Υπότιτλοι + + + + &Browse + &Περιήγηση + + + + Op&tions + &Επιλογές + + + + &Help + &Βοήθεια + + + + &File... + &Αρχείο... + + + + D&irectory... + &Κατάλογο... + + + + &Playlist... + &Λίστα... + + + + &DVD from drive + DVD από &συσκευή + + + + D&VD from folder... + DVD από &Κατάλογο... + + + + &URL... + &URL... + + + + &Clear + &Καθάρισε + + + + &Recent files + &Πρόσφατα αρχεία + + + + P&lay + &Παίξε + + + + &Pause + &Παύση + + + + &Stop + &Στοπ + + + + &Frame step + &Πλαισίου βήμα + + + + &Normal speed + &Κανονική ταχύτης + + + + &Halve speed + &Μισή ταχύτης + + + + &Double speed + &Διπλή ταχύτης + + + + Speed &-10% + Ταχύτης &-10% + + + + Speed &+10% + Ταχύτης &+10% + + + + Sp&eed + Τα&χύτης + + + + &Repeat + &Επανάληψη + + + + &Fullscreen + &Οθόνη πλήρη + + + + &Compact mode + &Συμπαγής μορφή + + + + Si&ze + &Μέγεθος + + + + 4:3 &Letterbox + &4:3 Φάκελος + + + + 16:9 L&etterbox + &16:9 Φάκελος + + + + 4:3 &Panscan + &4:3 Αναμόρφωση + + + + 4:3 &to 16:9 + &4:3 σε 16:9 + + + + &Aspect ratio + &Λόγος διάστασης + + + + &None + &Ουδέν + + + + &Lowpass5 + &Φίλτροχαμηλών5 + + + + Linear &Blend + &Γραμμών μίξη + + + + &Deinterlace + &Αποσύμπλεξη + + + + &Postprocessing + &Προεπεξεργασία + + + + &Autodetect phase + &Αυτοεπιλογή στιγμιότυπου + + + + &Deblock + &Μη-φραγή + + + + De&ring + + + + + Add n&oise + Πρόσθεση &θορύβου + + + + F&ilters + &Φίλτρα + + + + &Equalizer + &Ισοσταθμιστής + + + + &Screenshot + &Στιγμιότυπο + + + + S&tay on top + &Μείνε κορυφή + + + + &Extrastereo + &Εξτρα_στέρεο + + + + &Karaoke + &Καραόκε + + + + &Filters + &Φίλτρα + + + + &Stereo + &Στέρεο + + + + &4.0 Surround + &4.0 Περιβάλλον + + + + &5.1 Surround + &5.1 Περιβάλλον + + + + &Channels + &Κανάλια + + + + &Left channel + &Ζερβό κανάλι + + + + &Right channel + &Δεξί κανάλι + + + + &Stereo mode + &Στέρεο μορφή + + + + &Mute + &Σίγαση + + + + Volume &- + Ένταση &- + + + + Volume &+ + Ένταση &+ + + + + &Delay - + &Καθυστέρηση - + + + + D&elay + + &Καθυστέρηση + + + + + &Select + &Επιλέξτε + + + + &Load... + &Άνοιξε... + + + + Delay &- + Καθυστέρηση &- + + + + Delay &+ + Καθυστέρηση &+ + + + + &Up + &Πάνω + + + + &Down + &Κάτω + + + + &Title + &Τίτλος + + + + &Chapter + &Κεφάλαιο + + + + &Angle + &Γωνία + + + + &Playlist + &Λίστα κοματιών + + + + &Show frame counter + &Δείξε μετρητή πλαισίων + + + + &Disabled + &Απενεργοποίηση + + + + &Seek bar + &Αναζήτηση + + + + &Time + &Χρόνος + + + + Time + T&otal time + Χρόνος + &Συνολικό χρόνο + + + + &OSD + &ΟSD + + + + &View logs + &Δες καταγραφή + + + + P&references + &Επιλογές + + + + About &Qt + &Περί Qt + + + + About &SMPlayer + &Περί SMPlayer + + + + <empty> + + + + + Video + Εικόνα + + + + Audio + Ήχος + + + + Playlists + Λίστα κοματιών + + + + All files + Όλα τα αρχεία + + + + Choose a file + Επιλέξτε αρχείο + + + + SMPlayer - Information + SMPlayer - Πληροφορίες + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD οδηγοί δεν καθορίστηκαν ακόμη. +Ο διάλογος καθορισμού θα εμφανιστεί, ώστε να προχωρήσετε. + + + + Choose a directory + Επιλέξτε κατάλογο + + + + Subtitles + Υπότιτλοι + + + + About Qt + Περί Qt + + + + Playing %1 + Παίζει %1 + + + + Pause + Παύση + + + + Stop + Στοπ + + + + Play / Pause + Παίξε / Παύση + + + + Pause / Frame step + Παύση / Πλαίσιο βήμα + + + + U&nload + &Ξεφόρτωσε + + + + V&CD + V&CD + + + + C&lose + &Κλείσε + + + + View &info and properties... + &Δες πληροφορίες... + + + + Zoom &- + Μεγένθυνε &- + + + + Zoom &+ + Μεγένθυνε &+ + + + + &Reset + &Άκυρο + + + + Move &left + Μετακίνηση &αριστερά + + + + Move &right + Μετακίνηση &δεξιά + + + + Move &up + Μετακίνηση &πάνω + + + + Move &down + Μετακίνηση &κάτω + + + + &Pan && scan + &Ανα && μόρφωση + + + + &Previous line in subtitles + &Προηγούμενη γραμμή υποτίτλων + + + + N&ext line in subtitles + &Επόμενη γραμμή υποτίτλων + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Μεί έντασης (2) + + + + Inc volume (2) + Αύξ έντασης (2) + + + + Exit fullscreen + Έχοδος πλήρους οθόνης + + + + OSD - Next level + OSD - Επόμενο επίπεδο + + + + Dec contrast + Μείω αντίθεση + + + + Inc contrast + Αύξ αντίθεση + + + + Dec brightness + Μείω φωτεινότης + + + + Inc brightness + Αύξ φωτεινότης + + + + Dec hue + Μείω χρώμα + + + + Inc hue + Αύξ χρώμα + + + + Dec saturation + Μείω saturation + + + + Dec gamma + Μείω γάμα + + + + Next audio + Επόμενο κομάτι + + + + Next subtitle + Επόμενος υπότιτλος + + + + Next chapter + Επόμενο κεφάλαιο + + + + Previous chapter + Προηγούμενο κεφάλαιο + + + + Inc saturation + Αύξ κορεσμού + + + + Inc gamma + Αύξ γάμα + + + + &Load external file... + &Φόρτωση εξωτερικού αρχείου... + + + + &Kerndeint + + + + + &Yadif (normal) + &Yadif (κανονικό) + + + + Y&adif (double framerate) + Y&adif (διπλή ροή πλαισίων) + + + + &Next + &Επόμενο + + + + Pre&vious + &Προηγούμενο + + + + Volume &normalization + &Ένταση μεσαία + + + + &Audio CD + &Ήχου CD + + + + Denoise nor&mal + &Μείωση θορύβου κανονική + + + + Denoise &soft + &Μείωση θορύβου ελάχιστη + + + + Denoise o&ff + &Μείωση θορύβου εκτός + + + + Use SSA/&ASS library + &Χρήση SSA/ASS εργαλείων + + + + Flip i&mage + &Ανάποδη εικόνα + + + + &Toggle double size + &Ενναλαγή διπλού μεγέθους + + + + S&ize - + + + + + Si&ze + + + + + + Add &black borders + + + + + Soft&ware scaling + + + + + &FAQ + + + + + Visualize &motion vectors + + + + + &Command line options + + + + + SMPlayer command line options + + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &Αρχείο + + + + &Track + audio + &Αρχείο + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer ακόμη τρέχει εδώ + + + + S&how icon in system tray + &Δείξε εικόνα στην γραμμή εργαλείων + + + + &Hide + &Κρύψου + + + + &Restore + &Επανέφερε + + + + &Quit + &Κλείσε + + + + Playlist + Λίστα + + + + Core + + + Brightness: %1 + Φωτεινό: %1 + + + + Contrast: %1 + Αντίθεση: %1 + + + + Gamma: %1 + Γάμα: %1 + + + + Hue: %1 + Χρώμα: %1 + + + + Saturation: %1 + Κορεσμός: %1 + + + + Volume: %1 + Ένταση: %1 + + + + Zoom: %1 + Μεγέθυνση: %1 + + + + Font scale: %1 + + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Καλώς ήρθατε στον SMPlayer + + + + Audio + Ήχος + + + + Subtitle + Υπότιτλοι + + + + &Main toolbar + &Μπάρα εργασίας + + + + &Language toolbar + &Επιλογή γλώσσας + + + + &Toolbars + &Επιλογές + + + + EqSlider + + + icon + εικόνα + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + εικόνα + + + + Error + Σφάλμα + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Αρχείο περιγραφή + + + + &Information + &Πληροφορίες + + + + &Demuxer + &Αποκωδικοποιητής + + + + &Select the demuxer that will be used for this file: + &Επιλέξτε αποκωδικοποιητή για χρήση με το αρχείο: + + + + &Reset + &Άκυρο + + + + &Video codec + &Εικόνα codec + + + + &Select the video codec: + &Επιλέξτε βίντεο codec: + + + + A&udio codec + &Ήχου codec + + + + &Select the audio codec: + &Επιλέξτε ήχου codec: + + + + &MPlayer options + &ΜPlayer επιλογές + + + + Additional Options for MPlayer + Επιπλέον Επιλογές του MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Εδώ μπορείτε να ορίσετε έξτρα επιλογές στον MPlayer. +Γράφετε χωριστές με ενδιάμεσα κενά. +Παράδειγμα: -flip -nosound + + + + &Options: + &Επιλογές: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Μπορείτε να επιλέξετε επιπλέον βίντεο φιλτρα. +Χωρίστε τα με ",". Όχι χρήση κενού εδώ! +Παράδειγμα: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + &Βίντεο φίλτρα: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Τελικά φίλτρα ήχου. Ίδιος κανών με φίλτρα βίντεο. +Παράδειγμα: resample=44100:0:0,volnorm + + + + Audio &filters: + &Ήχου φίλτρα: + + + + OK + ΟΚ + + + + Cancel + Άκυρο + + + + Apply + Εφαρμογή + + + + FindSubtitlesWindow + + + Language + Γλώσσα/Language + + + + Name + Όνομα + + + + Format + Μορφή + + + + Files + + + + + Date + Ημέρα + + + + Uploaded by + + + + + All + + + + + Close + Κλείσε + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Σφάλμα + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Σφάλμα αποθήκευσης αρχείου + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Γενικά + + + + Size + Μέγεθος + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Μήκος + + + + Demuxer + Αποκωδικοποιητής + + + + Name + Όνομα + + + + Artist + Καλιτέχνης + + + + Author + Εκδότης + + + + Album + Άλμπουμ + + + + Genre + Γένος + + + + Date + Ημέρα + + + + Track + Αρ. κοματιού + + + + Copyright + Πνευματικά δικαιώματα + + + + Comment + Σημείωση + + + + Software + Λογισμικό + + + + Clip info + Κλιπ πληροφορίες + + + + Video + Βίντεο + + + + Resolution + Ανάλυση + + + + Aspect ratio + Λόγος διαστάσεων + + + + Format + Μορφή + + + + Bitrate + Ανάλυση + + + + %1 kbps + %1 kbps + + + + Frames per second + Πλαίσια ανά δεύτερο + + + + Selected codec + Επιλεγμένος κωδικοποιητής + + + + Initial Audio Stream + Αρχική Ήχου Εκπομπή + + + + Rate + Ρυθμός + + + + %1 Hz + %1 Hz + + + + Channels + Κανάλια + + + + Audio Streams + Ήχου Εκπομπή + + + + Language + Γλώσσα/Language + + + + empty + άδειο + + + + Subtitles + Υπότιτλοι + + + + Type + τύπος + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Εκπομπής τίτλος + + + + Stream URL + Εκπομπής URL + + + + File + Αρχείο + + + + InputDVDDirectory + + + Choose a directory + Επιλέξτε κατάλογο + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Παίζει DVD από κατάλογο + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Μπορείτε να παίξετε dvd από τον σκληρό δίσκο. Απλώς επιλέξτε τον κατάλογο που περιέχει τους καταλόγους VIDEO_TS και AUDIO_TS. + + + + Choose a directory... + Επιλέξτε κατάλογο... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Εισαγωγή URL + + + + &URL: + &URL: + + + + It's a &playlist + &Είναι λίστα κοματιών + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Αν επιλεχθεί, το URL θα χρησιμοποιηθεί σαν λίστα κοματιών: θα ανοιχτεί σαν txt μορφή και θα παιχτούν τα URLs που περιέχει. + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + + + + + Welsh + + + + + Danish + + + + + German + + + + + Greek + Ελληνικά + + + + English + + + + + Esperanto + + + + + Spanish + + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + + + + + Faroese + + + + + French + + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + + + + + Inuktitut + + + + + Japanese + + + + + Javanese + + + + + Georgian + + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + + + + + Portuguese + + + + + Quechua + + + + + Romanian + + + + + Russian + + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + + + + + Sundanese + + + + + Swedish + + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + + + + + Portuguese - Portugal + + + + + Simplified-Chinese + + + + + Traditional Chinese + + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Δυτικής Ευρώπης γλώσσες + + + + Western European Languages with Euro + Δυτικής Ευρώπης γλώσσες με Ευρώ + + + + Slavic/Central European Languages + + + + + Esperanto, Galician, Maltese, Turkish + + + + + Old Baltic charset + + + + + Cyrillic + + + + + Modern Greek + Ελληνικά + + + + Baltic + + + + + Celtic + + + + + Hebrew charsets + + + + + Ukrainian, Belarusian + + + + + Simplified Chinese charset + + + + + Traditional Chinese charset + + + + + Japanese charsets + + + + + Korean charset + + + + + Thai charset + + + + + Cyrillic Windows + + + + + Slavic/Central European Windows + + + + + Arabic Windows + + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Επιλέξτε όνομα αρχείου για αποθήκευση + + + + Confirm overwrite? + Επιβεβαιώνετε επαν-εγγραφή? + + + + The file already exists. +Do you want to overwrite? + Το αρχείο υπάρχει ήδη. +Θέλετε να γράψετε άλλο πάνω του? + + + + Error saving file + Σφάλμα αποθήκευσης αρχείου + + + + The log couldn't be saved + Η καταγραφή δεν αποθηκεύτηκε + + + + Logs + Καταγραφές + + + + LogWindowBase + + + Log Window + Καταγραφής Παράθυρο + + + + Save + Σώσε + + + + Copy to clipboard + Αντιγραφή στο πρόχειρο + + + + &Close + &Κλείσε + + + + Close + Κλείσε + + + + MiniGui + + + Control bar + + + + + MpcGui + + + Control bar + + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Όνομα + + + + Length + Μήκος + + + + &Play + &Παίξε + + + + &Edit + &Άλλαξε + + + + Playlists + Λίστες + + + + Choose a file + Επιλέξτε αρχείο + + + + Choose a filename + Επιλέξτε όνομα αρχείου + + + + Confirm overwrite? + Επιβεβαιώνετε επαν-εγγραφή? + + + + The file %1 already exists. +Do you want to overwrite? + Το αρχείο %1 υπάρχει ήδη. +Θέλετε να γράψετε άλλο πάνω του? + + + + All files + Όλα τα αρχεία + + + + Select one or more files to open + Επιλέξτε ένα ή περισσότερα αρχεία + + + + Choose a directory + Επιλέξτε κατάλογο + + + + Edit name + Αλλαγή ονόματος + + + + Type the name that will be displayed in the playlist for this file: + Γράψτε το όνομα με το οποίο θα εμφανίζεται στην λίστα το αρχείο: + + + + &Load + &Φόρτωση + + + + &Save + &Σώσε + + + + &Next + &Επόμενο + + + + Pre&vious + &Προηγούμενο + + + + Move &up + &Πάνω μετακίνηση + + + + Move &down + &Κάτω μετακίνηση + + + + &Repeat + &Επανάληψη + + + + S&huffle + &Τυχαία + + + + Add &current file + &Πρόσθεση τρέχον αρχείο + + + + Add &file(s) + &Πρόσθεση αρχείου(-ων) + + + + Add &directory + &Πρόσθεση καταλόγου + + + + Remove &selected + &Αφαίρεση επιλεγμένου + + + + Remove &all + Αφαίρεση &όλων + + + + SMPlayer - Playlist + SMPlayer - Λίστα κομματιών + + + + Add... + Πρόσθεσε... + + + + Remove... + Αφαίρεσε... + + + + Playlist modified + Λίστα άλλαξε + + + + There are unsaved changes, do you want to save the playlist? + Υπάρχουν αλλαγές σε εκκρεμότητα, θέλετε να αποθηκεύσετε την λίστα? + + + + Preferences + + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + Προχωρημένα + + + + Auto + Αυτόματα + + + + &Advanced + &Προχωρημένα + + + + icon + εικόνα + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Εδώ μπορείτε να ορίσετε έξτρα επιλογές στον MPlayer. +Γράφετε χωριστές με ενδιάμεσα κενά. +Παράδειγμα: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Μπορείτε να επιλέξετε επιπλέον βίντεο φιλτρα. +Χωρίστε τα με ",". Όχι χρήση κενού εδώ! +Παράδειγμα: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Τελικά φίλτρα ήχου. Ίδιος κανών με φίλτρα βίντεο. +Παράδειγμα: resample=44100:0:0,volnorm + + + + Log MPlayer output + Καταγραφή εξόδου MPlayer + + + + Log SMPlayer output + Καταγραφή εξόδου SMPlayer + + + + This option is mainly intended for debugging the application. + Η επιλογή προορίζεται για αποσφαλμάτωση της εφαρμογής. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Ελληνικά :Ο έλεγχος αυτής της επιλογής μπορεί να μειώσει το τρεμούλιασμα, αλλά πιθανόν το βίντεο δεν θα επιδειχθεί κατάλληλα. + + + + Filter for SMPlayer logs + Φίλτρο για SMPlayer καταγραφές + + + + &Monitor aspect: + + + + + &Run MPlayer in its own window + &Τρέξε MPlayer σε δικό του παράθυρο + + + + &Options: + &Επιλογές: + + + + V&ideo filters: + &Βίντεο φίλτρα: + + + + Audio &filters: + &Ήχου φίλτρα: + + + + &Colorkey: + &Χρώμα: + + + + Log &SMPlayer output + &Καταγραφή εξόδου SMPlayer + + + + &Filter for SMPlayer logs: + &Φίλτρο για SMPlayer καταγραφές: + + + + C&hange... + &Αλλαγή... + + + + Logs + Καταγραφές + + + + Log MPlayer &output + + + + + Options for MP&layer + + + + + Autosave MPlayer log + + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + τύπος + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + + + + + Select all + + + + + Check all file types in the list + + + + + Select none + + + + + Uncheck all file types in the list + + + + + List of file types + + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + File types + + + + + Media files handled by SMPlayer: + + + + + Select All + + + + + Select None + + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + Συσκευές + + + + icon + εικόνα + + + + CD device + CD συσκευή + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Επιλέξτε την CD συσκευή σας. Θα χρησιμοποιηθεί για παίξιμο VCDs και Ήχου CDs. + + + + DVD device + DVD συσκευή + + + + Choose your DVD device. It will be used to play DVDs. + Επιλέξτε την DVD συσκευή σας. Θα χρησιμοποιηθεί για παίξιμο DVD. + + + + Select your &CD device: + Επιλέξτε την &CD συσκευή: + + + + Select your &DVD device: + Επιλέξτε την &DVD συσκευή: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + Γενικά + + + + &General + &Γενικά + + + + Paths + Διαδρομές + + + + Media settings + Αρχείων Ρυθμίσεις + + + + Preferred audio and subtitles + Προτιμητέος ήχος και υπότιτλοι + + + + Video + Βίντεο + + + + Start videos in fullscreen + Έναρξη βίντεο σε πλήρη οθόνη + + + + Disable screensaver + Απενεργοποίηση προστασίας οθόνης + + + + Audio + Ήχος + + + + Select the mplayer executable + Επιλέξτε mplayer εκκινήσιμο + + + + Executables + Εκκινήσιμα + + + + All files + Όλα τα αρχεία + + + + Select a directory + Επιλέξτε κατάλογο + + + + MPlayer executable + MPlayer εκκινήσιμο + + + + Screenshots folder + Στιγμιοτύπων κατάλογος + + + + Video output driver + Εικόνας εξόδου οδηγός + + + + Audio output driver + Ήχος εξόδου οδηγός + + + + Select the audio output driver. + Επιλέξτε οδηγό ήχο εξόδου. + + + + Remember settings + Ενθύμηση ρυθμίσεων + + + + Preferred audio language + Προτιμητέα γλώσσα ήχου + + + + Preferred subtitle language + Προτιμητέα γλώσσα υποτίτλων + + + + Software video equalizer + Ψηφιακός ισοσταθμιστής εικόνας + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + + + + + If this option is checked, all videos will start to play in fullscreen mode. + Αν επιλέξετε ναι, όλα τα βίντεο θα ξεκινούν με πλήρη οθόνη. + + + + Software volume control + Έλεγχος έντασης + + + + Check this option to use the software mixer, instead of using the sound card mixer. + + + + + Postprocessing quality + Προεπεξεργασίας ποιότητα + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Δυναμικά αλλάζει το επίπεδο ανάλογα με το διαθέσιμο ελεύθερο χρόνο ΚΜΕ. Ο αριθμός που διευκρινίζετε θα είναι το ανώτατο χρησιμοποιούμενο όριο. Συνήθως μπορείτε να χρησιμοποιήσετε κάποιο μεγάλο αριθμό. + + + + Change volume + Αλλαγή έντασης + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Αν επιλεγεί,ο SMPlayer θα θυμάται την ένταση κάθε κομματιού και θα παίζει με αυτήν. Για νέα αρχεία θα χρησιμοποιείται η αρχική ρύθμιση έντασης. + + + + 0 + 0 + + + + &Change volume on every file + &Αλλαγή έντασης σε κάθε αρχείο + + + + Select the &MPlayer executable: + &Επιλέξτε την MPlayer εφαρμογή: + + + + &Folder for storing screenshots: + &Κατάλογος αποθήκευσης στιγμιοτύπων: + + + + &Audio: + &Ήχος: + + + + &Remember settings for all files (audio track, subtitles...) + &Κράτα τις ρυθμίσεις για όλα τα αρχεία (θέση κομματιού, υπότιτλοι...) + + + + Su&btitles: + &Υπότιτλοι: + + + + &Quality: + &Ποιότητα: + + + + Start videos in &fullscreen + Έναρξη βίντεο σε &πλήρη οθόνη + + + + Disable &screensaver + Απενεργοποίηση προστασίας &οθόνης + + + + &Default volume: + &Αρχική ένταση: + + + + Use s&oftware volume control + &Χρήση ψηφιακού ρυθμιστή έντασης + + + + Ma&x. Amplification: + &Μέγιστη Ενίσχυση: + + + + &AC3/DTS pass-through S/PDIF + &ΑC3/DTS διαπερατό S/PDIF + + + + Direct rendering + Άμεση επεξεργασία + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Εάν ελέγχεται, ανοίγει την άμεση σύζευξη (που δεν υποστηρίζεται από όλα τα codecs και τα αποτελέσματα εικόνας )<br><b>ΠΡΟΕΙΔΟΠΟΙΗΣΗ:</b>Ίσως γίνει αιτία OSD/SUB σφαλμάτων! + + + + Double buffering + Διπλό buffer + + + + D&irect rendering + &Απευθείας render + + + + Dou&ble buffering + &Διπλό buffer + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Η διπλή αποθήκευση καθορίζει το τρεμούλιασμα με την αποθήκευση δύο πλαισίων στη μνήμη, και την επίδειξη μιας αποκωδικοποιώντας το επόμενο. Εάν τίθεται εκτός λειτουργίας μπορεί να έχει δυσμενείς επιπτώσεις σε OSD, αλλά συχνά αφαιρεί το τρεμούλιασμα OSD. + + + + &Enable postprocessing by default + &Προεπεξεργασία εξ' ορισμού ενεργή + + + + Volume &normalization by default + &Κανονικοποίηση έντασης εξ' ορισμού + + + + Close when finished + Κλείσε αφού τελειώσει + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Εάν αυτή η επιλογή τσεκαριστεί, το κύριο παράθυρο θα κλείσει αυτόματα όταν τελειώνει το τρέχον αρχείο/λίστα. + + + + 2 (Stereo) + 2 (Στέρεο) + + + + 4 (4.0 Surround) + 4 (4.0 Περιβάλλον) + + + + 6 (5.1 Surround) + 6 (5.1 Περιβάλλον) + + + + C&hannels by default: + &Κανάλια αρχικά: + + + + &Pause when minimized + &Παύση στην μίκρυνση + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Pause when minimized + + + + + Enable postprocessing by default + + + + + Postprocessing will be used by default on new opened files. + + + + + Max. Amplification + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + AC3/DTS pass-through S/PDIF + + + + + Uses hardware AC3 passthrough + + + + + Volume normalization by default + + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Preferre&d audio and subtitles + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + Preferred language: + + + + + Audi&o: + + + + + &Subtitle: + + + + + Or choose a track number: + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + &Εικόνα + + + + Use s&oftware video equalizer + + + + + A&udio + + + + + Volume + Ένταση + + + + None + Ουδέν + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Πληκτρολόγιο και ποντίκι + + + + &Keyboard + &Πληκτρολόγιο + + + + icon + εικόνα + + + + &Mouse + &Ποντίκι + + + + Button functions: + Συντομεύσεις πληκτρολογίου: + + + + Media seeking + Ψάχνει αρχεία + + + + Volume control + Ένταση ρύθμιση + + + + Zoom video + Μεγέθυνση εικόνας + + + + None + Ουδέν + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Εδώ μπορείτε να αλλάξετε οποιαδήποτε συντόμευση πληκτρολογίου. Για να γίνει κάντε διπλό χτύπημα ή εισάγετε κελί συντόμευσης. Προαιρετικά μπορείτε επίσης να σώσετε τον κατάλογο για να το μοιραστείτε με άλλους ανθρώπους ή να το φορτώσετε σε έναν άλλο υπολογιστή. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Εδώ μπορείτε να αλλάξετε οποιαδήποτε συντόμευση πληκτρολογίου. Για να γίνει κάντε διπλό χτύπημα ή εισάγετε κελί συντόμευσης. Προαιρετικά μπορείτε επίσης να σώσετε τον κατάλογο για να το μοιραστείτε με άλλους ανθρώπους ή να το φορτώσετε σε έναν άλλο υπολογιστή. + + + + &Left click + &Αριστ κλικ + + + + &Double click + &Διπλό κλικ + + + + &Wheel function: + &Τροχού λειτουργία: + + + + Play + + + + + Play / Pause + Παίξε / Παύση + + + + Pause + Παύση + + + + Pause / Frame step + Παύση / Πλαίσιο βήμα + + + + Stop + Στοπ + + + + Fullscreen + + + + + Compact + + + + + Screenshot + + + + + Mute + + + + + Playlist + Λίστα + + + + Frame counter + + + + + Preferences + + + + + Reset zoom + + + + + Exit fullscreen + Έχοδος πλήρους οθόνης + + + + Double size + + + + + Shortcut editor + + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + + + + + Select the action for left click on the mouse. + + + + + Double click + + + + + Select the action for double click on the mouse. + + + + + Wheel function + + + + + Select the action for the mouse wheel. + + + + + No function + + + + + Change speed + + + + + Normal speed + + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - Επόμενο επίπεδο + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Διάδραση + + + + <Autodetect> + <Αυτόματη επιλογή> + + + + Default + Αρχικό + + + + &Interface + &Διεπαφή + + + + Seeking + Ψάχνει + + + + Never + Ποτέ + + + + Whenever it's needed + Όταν απαιτείται + + + + Only after loading a new video + Μόνο μετά την φόρτωση νέου βίντεο + + + + Recent files + Πρόσφατα αρχεία + + + + Language + Γλώσσα/Language + + + + Here you can change the language of the application. + Εδώ αλλάζετε την γλώσσα της εφαρμογής. + + + + Instances + Περιπτώσεις + + + + &Short jump + &Μικρό άλμα + + + + &Medium jump + &Μεσαίο άλμα + + + + &Long jump + &Μεγάλο άλμα + + + + Mouse &wheel jump + &Τροχός ποντίκι άλμα + + + + &Use only one running instance of SMPlayer + &Χρήση μόνο ενός ενεργού SMPlayer + + + + Ma&x. items + &Μέγιστα, θέματα + + + + St&yle: + &Στυλ: + + + + Ico&n set: + &Εικόνες σετ: + + + + L&anguage: + &Γλώσσα: + + + + Main window + Κύριο παράθυρο + + + + Auto&resize: + &Αυτόματη διάσταση: + + + + R&emember position and size + &Θυμήσου θέση και μέγεθος + + + + Default font: + Καθορισμένη γραμματοσειρά: + + + + &Change... + &Αλλαγή... + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + + + + + &Seeking + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Απόδοση + + + + &Performance + &Απόδοση + + + + Priority + Προτεραιότητα + + + + Select the priority for the MPlayer process. + Επιλέξτε προτεραιότητα MPlayer λειτουργίας. + + + + realtime + πλήρη + + + + high + υψηλή + + + + abovenormal + αυξημένη + + + + normal + κανονική + + + + belownormal + μειωμένη + + + + idle + χαμηλή + + + + Cache + Μνήμη + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Αν καθορίσετε μέγεθος μνήμης ίσως βελτιώσετε την απόδοση + + + + Allow frame drop + Επιτρέπει μείωση πλαισίων + + + + Synchronization + Συγχρονισμός + + + + Audio/video auto synchronization + Ήχου/Εικόνα αυτό συγχρονισμός + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Ρυθμίστε την προτεραιότητα του mplayer στα Windows.<br><b>WARNING:</b> Χρήση προτεραιότητας αληθινού χρόνου μπορεί να κλειδώσει το σύστημα. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Προσπέραση εμφάνισης λίγων πλαισίων για να διατηρηθεί Ηχ/Εικ συγχρονισμός σε αργά συστήματα. + + + + Allow hard frame drop + Επιτρέπει προσπέραση πλαισίων + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Εντονότερη μείωση πλαισίων (χαλάει την αποκωδικοποίηση). Οδηγεί σε διαστρέβλωση εικόνας! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Βαθμιαία ρυθμίζει συγχρονισμό Ηχ/Εικ βάσει μετρήσεων ήχου. + + + + Priorit&y: + &Προτεραιότης: + + + + &Allow frame drop + &Πλαισίων μείωση επιτρέπει + + + + Allow &hard frame drop (can lead to image distortion) + &Μεγάλη πλαισίων μείωση επιτρέπει (ίσως διαστρεβλώσει την εικόνα) + + + + Audio/&video auto synchronization + &Ήχου/εικόνας αυτόματος συγχρονισμός + + + + Fact&or: + &Συντελεστής: + + + + &Fast audio track switching + &Γρήγορη εναλλαγή τραγουδιών + + + + Fast &seek to chapters in dvds + &Ψάχνει γρήγορα κεφάλαια σε dvd + + + + Skip loop filter + + + + + Fast audio track switching + + + + + Fast seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + + + + + Cache for &DVDs: + + + + + Cache for &local files: + + + + + Cache for &streams: + + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Λίστα + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Λίστα κοματιών + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Υπότιτλοι + + + + Choose a ttf file + Επιλέξτε αρχείο ttf + + + + Truetype Fonts + Truetype Γραμματοσειρά + + + + &Subtitles + &Υπότιτλοι + + + + Autoload + Αυτόματη φόρτωση + + + + Same name as movie + Ίδιο όνομα όπως η ταινία + + + + All subs containing movie name + Όλοι οι υπότιτλοι που περιέχουν το όνομα της ταινίας + + + + All subs in directory + Όλοι οι υπότιτλοι σε ένα κατάλογο + + + + Position + Θέση + + + + 0 + 0 + + + + Top + Άνω + + + + Bottom + Κάτω + + + + Font + Γραμματοσειρά + + + + Select the font which will be used for subtitles (and OSD): + Επιλέξτε γραμματοσειρά για υπότιτλους (και OSD): + + + + Size + Μέγεθος + + + + No autoscale + Όχι αυτόματη μεγέθυνση + + + + Proportional to movie height + Ανάλογα με ύψος ταινίας + + + + Proportional to movie width + Ανάλογα με πλάτος ταινίας + + + + Proportional to movie diagonal + Ανάλογα με διαγώνιο ταινίας + + + + Subtitle position + Υποτίτλων θέση + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Ηεπιλογή ρυθμίζει την θέση των υποτίτλων στο παράθυρο. <i>100</i> εννοει το κατώτατο σημείο, ενώ <i>0</i> σημαίνει την κορυφή. + + + + Au&toload subtitles files (*.srt, *.sub...): + &Αυτόματη φόρτωση υποτίτλων (*.srt, *.sub...): + + + + S&elect first available subtitle + &Επέλεξε πρώτον υπότιτλο + + + + &Default subtitle encoding: + &Αρχική γραμματοσειρά υποτίτλων: + + + + Default &position of the subtitles on screen + &Αρχική θέση υποτίτλων στην οθόνη + + + + &Include subtitles on screenshots + &Εμφάνιση υποτίτλων στα στιγμιότυπα + + + + &TTF font: + &ΤΤF γραμματοσειρά: + + + + S&ystem font: + &Σύστημα γραμματοσειρά: + + + + A&utoscale: + &Αυτόματο μέγεθος: + + + + Select first available subtitle + + + + + Default subtitle encoding + + + + + Include subtitles on screenshots + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + Κάτω + + + + Middle + vertical alignment + + + + + Top + vertical alignment + Άνω + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Βοήθεια + + + + OK + ΟΚ + + + + Cancel + Άκυρο + + + + Apply + Εφαρμογή + + + + Help + Βοήθεια + + + + SMPlayer - Preferences + SMPlayer - Προτιμήσεις + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + Είναι ο SMPlayer v. %1 ενεργό για %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + + the main window won't be closed when the file/playlist finishes. + + + + + the video will be played in fullscreen mode. + + + + + the video will be played in window mode. + + + + + Enqueue in SMPlayer + + + + + opens the mini gui instead of the default one. + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + Usage: + + + + + directory + + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + εικόνα + + + + label + επιγραφή + + + + ShortcutGetter + + + Modify shortcut + + + + + Clear + Καθαρισμός + + + + Press the key combination you want to assign + Ρυθμίστε τις συντομεύσεις που επιθυμείτε + + + + Capture + Αρπαγή + + + + Capture keystrokes + Αρπαγής συντομεύσεις + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + + + + + Select None + + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + Αυτόματα + + + + Yes + + + + + No + + + + + VideoEqualizer + + + Contrast + Αντίθεση + + + + Brightness + Φωτεινότης + + + + Hue + Χρώμα + + + + Saturation + Κορεσμός + + + + Gamma + Γάμα + + + + &Reset + &Άκυρο + + + + &Set as default values + &Ρύθμιση σαν αρχικών τιμών + + + + Use the current values as default values for new videos. + Χρήση τρεχουσών ρυθμίσεων για τα νέα βίντεο. + + + + Set all controls to zero. + Αποθήκευση όλων των ρυθμίσεων σε μηδέν. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + Άκυρο + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Σφάλμα αποθήκευσης αρχείου + + + + The file couldn't be saved + Το αρχείο δεν δύνατο να σωθεί + + + + Error + Σφάλμα + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Αρχικό + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Ένταση + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_en_US.ts b/plugins/smplayer_plugin/translations/smplayer_en_US.ts new file mode 100644 index 000000000..c6eff7e17 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_en_US.ts @@ -0,0 +1,7196 @@ + + + + About + + + Version: %1 + + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + + + + The following people have contributed with translations: + + + + + German + + + + + Slovak + + + + + Italian + + + + + French + + + + + %1, %2 and %3 + + + + + Simplified-Chinese + + + + + Russian + + + + + %1 and %2 + %1 and %2 + + + + Hungarian + + + + + Polish + + + + + Japanese + + + + + Dutch + + + + + Ukrainian + + + + + Portuguese - Brazil + + + + + Georgian + + + + + Czech + + + + + Bulgarian + + + + + Turkish + + + + + Swedish + + + + + Serbian + + + + + Traditional Chinese + + + + + Romanian + + + + + Portuguese - Portugal + + + + + Greek + + + + + Finnish + + + + + <b>%1</b>: %2 + + + + + <b>%1</b> (%2) + + + + + About SMPlayer + + + + + &Info + + + + + icon + + + + + &Contributions + + + + + &Translators + + + + + &License + + + + + Visit our web for updates: + + + + + Get help in our forum: + + + + + You can support SMPlayer by making a donation. + + + + + More info + + + + + Korean + + + + + Macedonian + + + + + Basque + + + + + Using MPlayer %1 + + + + + Catalan + + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + + + + + Description + + + + + Shortcut + + + + + &Save + + + + + &Load + + + + + Key files + + + + + Choose a filename + + + + + Confirm overwrite? + + + + + The file %1 already exists. +Do you want to overwrite? + + + + + Choose a file + + + + + Error + + + + + The file couldn't be saved + + + + + The file couldn't be loaded + + + + + &Change shortcut... + + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + + + + + &Set as default values + + + + + Use the current values as default values for new videos. + + + + + Set all controls to zero. + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + + + + + SMPlayer - smplayer log + + + + + &Open + + + + + &Play + + + + + &Video + + + + + &Audio + + + + + &Subtitles + + + + + &Browse + + + + + Op&tions + + + + + &Help + + + + + &File... + + + + + D&irectory... + + + + + &Playlist... + + + + + &DVD from drive + + + + + D&VD from folder... + + + + + &URL... + + + + + &Clear + + + + + &Recent files + + + + + P&lay + + + + + &Pause + + + + + &Stop + + + + + &Frame step + + + + + &Normal speed + + + + + &Halve speed + + + + + &Double speed + + + + + Speed &-10% + + + + + Speed &+10% + + + + + Sp&eed + + + + + &Repeat + + + + + &Fullscreen + + + + + &Compact mode + + + + + Si&ze + + + + + 4:3 &Letterbox + + + + + 16:9 L&etterbox + + + + + 4:3 &Panscan + + + + + 4:3 &to 16:9 + + + + + &Aspect ratio + + + + + &None + + + + + &Lowpass5 + + + + + Linear &Blend + + + + + &Deinterlace + + + + + &Postprocessing + + + + + &Autodetect phase + + + + + &Deblock + + + + + De&ring + + + + + Add n&oise + + + + + F&ilters + + + + + &Equalizer + + + + + &Screenshot + + + + + S&tay on top + + + + + &Extrastereo + + + + + &Karaoke + + + + + &Filters + + + + + &Stereo + + + + + &4.0 Surround + + + + + &5.1 Surround + + + + + &Channels + + + + + &Left channel + + + + + &Right channel + + + + + &Stereo mode + + + + + &Mute + + + + + Volume &- + + + + + Volume &+ + + + + + &Delay - + + + + + D&elay + + + + + + &Select + + + + + &Load... + + + + + Delay &- + + + + + Delay &+ + + + + + &Up + + + + + &Down + + + + + &Title + + + + + &Chapter + + + + + &Angle + + + + + &Playlist + + + + + &Show frame counter + + + + + &Disabled + + + + + &Seek bar + + + + + &Time + + + + + Time + T&otal time + + + + + &OSD + + + + + &View logs + + + + + P&references + + + + + About &Qt + + + + + About &SMPlayer + + + + + <empty> + + + + + Video + + + + + Audio + + + + + Playlists + + + + + All files + + + + + Choose a file + + + + + SMPlayer - Information + + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + + + + + Choose a directory + + + + + Subtitles + + + + + About Qt + + + + + Playing %1 + + + + + Pause + + + + + Stop + + + + + Play / Pause + + + + + Pause / Frame step + + + + + U&nload + + + + + V&CD + + + + + C&lose + + + + + View &info and properties... + + + + + Zoom &- + + + + + Zoom &+ + + + + + &Reset + + + + + Move &left + + + + + Move &right + + + + + Move &up + + + + + Move &down + + + + + &Pan && scan + + + + + &Previous line in subtitles + + + + + N&ext line in subtitles + + + + + -%1 + + + + + +%1 + + + + + Dec volume (2) + + + + + Inc volume (2) + + + + + Exit fullscreen + + + + + OSD - Next level + + + + + Dec contrast + + + + + Inc contrast + + + + + Dec brightness + + + + + Inc brightness + + + + + Dec hue + + + + + Inc hue + + + + + Dec saturation + + + + + Dec gamma + + + + + Next audio + + + + + Next subtitle + + + + + Next chapter + + + + + Previous chapter + + + + + Inc saturation + + + + + Inc gamma + + + + + &Load external file... + + + + + &Kerndeint + + + + + &Yadif (normal) + + + + + Y&adif (double framerate) + + + + + &Next + + + + + Pre&vious + + + + + Volume &normalization + + + + + &Audio CD + + + + + Denoise nor&mal + + + + + Denoise &soft + + + + + Denoise o&ff + + + + + Use SSA/&ASS library + + + + + Flip i&mage + + + + + &Toggle double size + + + + + S&ize - + + + + + Si&ze + + + + + + Add &black borders + + + + + Soft&ware scaling + + + + + &FAQ + + + + + Visualize &motion vectors + + + + + &Command line options + + + + + SMPlayer command line options + + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + + + + + &Track + audio + + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + + + + + S&how icon in system tray + + + + + &Hide + + + + + &Restore + + + + + &Quit + + + + + Playlist + + + + + Core + + + Brightness: %1 + + + + + Contrast: %1 + + + + + Gamma: %1 + + + + + Hue: %1 + + + + + Saturation: %1 + + + + + Volume: %1 + + + + + Zoom: %1 + + + + + Font scale: %1 + + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + + + + + Audio + + + + + Subtitle + + + + + &Main toolbar + + + + + &Language toolbar + + + + + &Toolbars + + + + + EqSlider + + + icon + + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + + + + + Error + + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + + + + + &Information + + + + + &Demuxer + + + + + &Select the demuxer that will be used for this file: + + + + + &Reset + + + + + &Video codec + + + + + &Select the video codec: + + + + + A&udio codec + + + + + &Select the audio codec: + + + + + &MPlayer options + + + + + Additional Options for MPlayer + + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + + &Options: + + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + + + V&ideo filters: + + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + + + + + Audio &filters: + + + + + OK + + + + + Cancel + + + + + Apply + + + + + FindSubtitlesWindow + + + Language + + + + + Name + + + + + Format + + + + + Files + + + + + Date + + + + + Uploaded by + + + + + All + + + + + Close + + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + %1 subtitle extracted + %1 subtitles extracted + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + + + + + Size + + + + + %1 KB (%2 MB) + + + + + URL + + + + + Length + + + + + Demuxer + + + + + Name + + + + + Artist + + + + + Author + + + + + Album + + + + + Genre + + + + + Date + + + + + Track + + + + + Copyright + + + + + Comment + + + + + Software + + + + + Clip info + + + + + Video + + + + + Resolution + + + + + Aspect ratio + + + + + Format + + + + + Bitrate + + + + + %1 kbps + + + + + Frames per second + + + + + Selected codec + + + + + Initial Audio Stream + + + + + Rate + + + + + %1 Hz + + + + + Channels + + + + + Audio Streams + + + + + Language + + + + + empty + + + + + Subtitles + + + + + Type + + + + + ID + Info for translators: this is a identification code + + + + + # + Info for translators: this is a abbreviation for number + + + + + Stream title + + + + + Stream URL + + + + + File + + + + + InputDVDDirectory + + + Choose a directory + + + + + SMPlayer - Play a DVD from a folder + + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + + + + + Choose a directory... + + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + + + + + &URL: + + + + + It's a &playlist + + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + + + + + Welsh + + + + + Danish + + + + + German + + + + + Greek + + + + + English + + + + + Esperanto + + + + + Spanish + + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + + + + + Faroese + + + + + French + + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + + + + + Inuktitut + + + + + Japanese + + + + + Javanese + + + + + Georgian + + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + + + + + Portuguese + + + + + Quechua + + + + + Romanian + + + + + Russian + + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + + + + + Sundanese + + + + + Swedish + + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + + + + + Portuguese - Portugal + + + + + Simplified-Chinese + + + + + Traditional Chinese + + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + + + + + Western European Languages with Euro + + + + + Slavic/Central European Languages + + + + + Esperanto, Galician, Maltese, Turkish + + + + + Old Baltic charset + + + + + Cyrillic + + + + + Modern Greek + + + + + Baltic + + + + + Celtic + + + + + Hebrew charsets + + + + + Ukrainian, Belarusian + + + + + Simplified Chinese charset + + + + + Traditional Chinese charset + + + + + Japanese charsets + + + + + Korean charset + + + + + Thai charset + + + + + Cyrillic Windows + + + + + Slavic/Central European Windows + + + + + Arabic Windows + + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + + + + + Confirm overwrite? + + + + + The file already exists. +Do you want to overwrite? + + + + + Error saving file + + + + + The log couldn't be saved + + + + + Logs + + + + + LogWindowBase + + + Log Window + + + + + Save + + + + + Copy to clipboard + + + + + &Close + + + + + Close + + + + + MiniGui + + + Control bar + + + + + MpcGui + + + Control bar + + + + + -%1 + + + + + +%1 + + + + + Playlist + + + Name + + + + + Length + + + + + &Play + + + + + &Edit + + + + + Playlists + + + + + Choose a file + + + + + Choose a filename + + + + + Confirm overwrite? + + + + + The file %1 already exists. +Do you want to overwrite? + + + + + All files + + + + + Select one or more files to open + + + + + Choose a directory + + + + + Edit name + + + + + Type the name that will be displayed in the playlist for this file: + + + + + &Load + + + + + &Save + + + + + &Next + + + + + Pre&vious + + + + + Move &up + + + + + Move &down + + + + + &Repeat + + + + + S&huffle + + + + + Add &current file + + + + + Add &file(s) + + + + + Add &directory + + + + + Remove &selected + + + + + Remove &all + + + + + SMPlayer - Playlist + + + + + Add... + + + + + Remove... + + + + + Playlist modified + + + + + There are unsaved changes, do you want to save the playlist? + + + + + Preferences + + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + + + + + Auto + + + + + &Advanced + + + + + icon + + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + + + + + Log MPlayer output + + + + + Log SMPlayer output + + + + + This option is mainly intended for debugging the application. + + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + + + + + Filter for SMPlayer logs + + + + + &Monitor aspect: + + + + + &Run MPlayer in its own window + + + + + &Options: + + + + + V&ideo filters: + + + + + Audio &filters: + + + + + &Colorkey: + + + + + Log &SMPlayer output + + + + + &Filter for SMPlayer logs: + + + + + C&hange... + + + + + Logs + + + + + Log MPlayer &output + + + + + Options for MP&layer + + + + + Autosave MPlayer log + + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + + + + + Select all + + + + + Check all file types in the list + + + + + Uncheck all file types in the list + + + + + List of file types + + + + + File types + + + + + Media files handled by SMPlayer: + + + + + Select All + + + + + Select None + + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + Select none + + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + + + + + icon + + + + + CD device + + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + + + + + DVD device + + + + + Choose your DVD device. It will be used to play DVDs. + + + + + Select your &CD device: + + + + + Select your &DVD device: + + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + + + + + &General + + + + + Paths + + + + + Media settings + + + + + Start videos in fullscreen + + + + + Disable screensaver + + + + + Select the mplayer executable + + + + + Executables + + + + + All files + + + + + Select a directory + + + + + MPlayer executable + + + + + Screenshots folder + + + + + Video output driver + + + + + Audio output driver + + + + + Select the audio output driver. + + + + + Remember settings + + + + + Preferred audio language + + + + + Preferred subtitle language + + + + + Software video equalizer + + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + + + + + If this option is checked, all videos will start to play in fullscreen mode. + + + + + Software volume control + + + + + Check this option to use the software mixer, instead of using the sound card mixer. + + + + + Postprocessing quality + + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + + + + + Change volume + + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + 0 + + + + + &Change volume on every file + + + + + Select the &MPlayer executable: + + + + + &Folder for storing screenshots: + + + + + &Audio: + + + + + &Remember settings for all files (audio track, subtitles...) + + + + + Su&btitles: + + + + + &Quality: + + + + + Start videos in &fullscreen + + + + + Disable &screensaver + + + + + &Default volume: + + + + + Use s&oftware volume control + + + + + Ma&x. Amplification: + + + + + &AC3/DTS pass-through S/PDIF + + + + + Direct rendering + + + + + Double buffering + + + + + D&irect rendering + + + + + Dou&ble buffering + + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + &Enable postprocessing by default + + + + + Volume &normalization by default + + + + + Close when finished + + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + + + + + 4 (4.0 Surround) + + + + + 6 (5.1 Surround) + + + + + C&hannels by default: + + + + + &Pause when minimized + + + + + Pause when minimized + + + + + Enable postprocessing by default + + + + + Max. Amplification + + + + + AC3/DTS pass-through S/PDIF + + + + + Volume normalization by default + + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + + + + + Audi&o: + + + + + Preferred language: + + + + + Preferre&d audio and subtitles + + + + + &Subtitle: + + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + + + + + Use s&oftware video equalizer + + + + + A&udio + + + + + Volume + + + + + Video + + + + + Audio + + + + + Preferred audio and subtitles + + + + + None + + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + + + + + &Keyboard + + + + + icon + + + + + &Mouse + + + + + Button functions: + + + + + Media seeking + + + + + Volume control + + + + + Zoom video + + + + + None + + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + + + + + &Double click + + + + + &Wheel function: + + + + + Shortcut editor + + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + + + + + Select the action for left click on the mouse. + + + + + Double click + + + + + Select the action for double click on the mouse. + + + + + Wheel function + + + + + Select the action for the mouse wheel. + + + + + Play + + + + + Pause + + + + + Stop + + + + + Fullscreen + + + + + Compact + + + + + Screenshot + + + + + Mute + + + + + Frame counter + + + + + Reset zoom + + + + + Exit fullscreen + + + + + Double size + + + + + Play / Pause + + + + + Pause / Frame step + + + + + Playlist + + + + + Preferences + + + + + No function + + + + + Change speed + + + + + Normal speed + + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + + + + + <Autodetect> + + + + + Default + + + + + &Interface + + + + + Never + + + + + Whenever it's needed + + + + + Only after loading a new video + + + + + Recent files + + + + + Language + + + + + Here you can change the language of the application. + + + + + &Short jump + + + + + &Medium jump + + + + + &Long jump + + + + + Mouse &wheel jump + + + + + &Use only one running instance of SMPlayer + + + + + Ma&x. items + + + + + St&yle: + + + + + Ico&n set: + + + + + L&anguage: + + + + + Main window + + + + + Auto&resize: + + + + + R&emember position and size + + + + + Default font: + + + + + &Change... + + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + + + + + &Seeking + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Seeking + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + + + + + &Performance + + + + + Priority + + + + + Select the priority for the MPlayer process. + + + + + realtime + + + + + high + + + + + abovenormal + + + + + normal + + + + + belownormal + + + + + idle + + + + + KB + + + + + Setting a cache may improve performance on slow media + + + + + Allow frame drop + + + + + Synchronization + + + + + Audio/video auto synchronization + + + + + Skip displaying some frames to maintain A/V sync on slow systems. + + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + + + + + Gradually adjusts the A/V sync based on audio delay measurements. + + + + + Priorit&y: + + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + + + + + Fact&or: + + + + + &Fast audio track switching + + + + + Fast &seek to chapters in dvds + + + + + Fast audio track switching + + + + + Fast seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + + + + + Cache for &DVDs: + + + + + Cache for &local files: + + + + + Cache for &streams: + + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + + + + + Choose a ttf file + + + + + Truetype Fonts + + + + + &Subtitles + + + + + Autoload + + + + + Same name as movie + + + + + All subs containing movie name + + + + + All subs in directory + + + + + Position + + + + + 0 + + + + + Top + + + + + Bottom + + + + + Font + + + + + Select the font which will be used for subtitles (and OSD): + + + + + Size + + + + + No autoscale + + + + + Proportional to movie height + + + + + Proportional to movie width + + + + + Proportional to movie diagonal + + + + + Subtitle position + + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + + + + + Au&toload subtitles files (*.srt, *.sub...): + + + + + S&elect first available subtitle + + + + + &Default subtitle encoding: + + + + + Default &position of the subtitles on screen + + + + + &Include subtitles on screenshots + + + + + &TTF font: + + + + + S&ystem font: + + + + + A&utoscale: + + + + + Select first available subtitle + + + + + Default subtitle encoding + + + + + Include subtitles on screenshots + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + + + + + Middle + vertical alignment + + + + + Top + vertical alignment + + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + + + + + OK + + + + + Cancel + + + + + Apply + + + + + Help + + + + + SMPlayer - Preferences + + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + + the main window won't be closed when the file/playlist finishes. + + + + + the video will be played in fullscreen mode. + + + + + the video will be played in window mode. + + + + + Enqueue in SMPlayer + + + + + opens the mini gui instead of the default one. + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + Usage: + + + + + directory + + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + %1 second + %1 seconds + + + + + %1 minute(s) + + %1 minute + %1 minutes + + + + + %1 and %2 + %1 and %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + + + + + label + + + + + ShortcutGetter + + + Modify shortcut + + + + + Clear + + + + + Press the key combination you want to assign + + + + + Capture + + + + + Capture keystrokes + + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + + + + + Select None + + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + + + + + Yes + + + + + No + + + + + VideoEqualizer + + + Contrast + + + + + Brightness + + + + + Hue + + + + + Saturation + + + + + Gamma + + + + + &Reset + + + + + &Set as default values + + + + + Use the current values as default values for new videos. + + + + + Set all controls to zero. + + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + + + + + The file couldn't be saved + + + + + Error + + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + + + + + %1 Hz + + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_es.ts b/plugins/smplayer_plugin/translations/smplayer_es.ts new file mode 100644 index 000000000..0deebf531 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_es.ts @@ -0,0 +1,7399 @@ + + + + + About + + + Version: %1 + Versión: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Este programa es Software Libre; usted puede redistribuirlo y/o modificarlo bajo los términos de la "GNU General Public License" como lo publica la "FSF Free Software Foundation", o (a su elección) de cualquier versión posterior. + + + + The following people have contributed with translations: + Las siguientes personas han contribuido con traducciones: + + + + German + Alemán + + + + Slovak + Eslovaco + + + + Italian + Italiano + + + + French + Francés + + + + %1, %2 and %3 + %1, %2 y %3 + + + + Simplified-Chinese + Chino simplificado + + + + Russian + Ruso + + + + %1 and %2 + %1 y %2 + + + + Hungarian + Húngaro + + + + Polish + Polaco + + + + Japanese + Japonés + + + + Dutch + Holandés + + + + Ukrainian + Ucraniano + + + + Portuguese - Brazil + Portugués - Brasil + + + + Georgian + Georgiano + + + + Czech + Checo + + + + Bulgarian + Búlgaro + + + + Turkish + Turco + + + + Swedish + Sueco + + + + Serbian + Serbio + + + + Traditional Chinese + Chino tradicional + + + + Romanian + Rumano + + + + Portuguese - Portugal + Portugués - Portugal + + + + Greek + Griego + + + + Finnish + Finés + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Acerca de SMPlayer + + + + &Info + &Información + + + + icon + icon + + + + &Contributions + &Contribuciones + + + + &Translators + &Traductores + + + + &License + &Licencia + + + + Visit our web for updates: + Visita nuestra web para conseguir actualizaciones: + + + + Get help in our forum: + Consigue ayuda en nuestro foro: + + + + You can support SMPlayer by making a donation. + Puedes apoyar el desarrollo de SMPlayer haciendo una donación. + + + + More info + Más información + + + + Korean + Coreano + + + + Macedonian + Macedonio + + + + Basque + Vasco + + + + Using MPlayer %1 + Usando MPlayer %1 + + + + Catalan + Catalán + + + + Portable Edition + Edición Portable + + + + Using Qt %1 (compiled with Qt %2) + Usando Qt %1 (compilado con Qt %2) + + + + Slovenian + Esloveno + + + + Arabic + Árabe + + + + Kurdish + Kurdo + + + + Galician + Gallego + + + + The following people have contributed with patches (see the changelog for details): + Las siguientes personas han contribuido con parches (ver el changelog para más detalles): + + + + If there's any omission, please report. + Si hay alguna omisión, repórtalo. + + + + SMPlayer logo by %1 + Logo del SMPlayer por %1 + + + + %1, %2, %3 and %4 + %1, %2, %3 y %4 + + + + %1, %2, %3, %4 and %5 + %1, %2, %3, %4 y %5 + + + + ActionsEditor + + + Name + Nombre + + + + Description + Descripción + + + + Shortcut + Atajo + + + + &Save + &Grabar + + + + &Load + &Cargar + + + + Key files + Ficheros de atajos + + + + Choose a filename + Elige un fichero + + + + Confirm overwrite? + ¿Confirmar sobreescribir? + + + + The file %1 already exists. +Do you want to overwrite? + El fichero %1 ya existe. +¿Quieres sobreescribirlo? + + + + Choose a file + Elige un fichero + + + + Error + Error + + + + The file couldn't be saved + El fichero no se ha podido grabar + + + + The file couldn't be loaded + El fichero no se ha podido cargar + + + + &Change shortcut... + &Modificar atajo... + + + + AudioEqualizer + + + Audio Equalizer + Ecualizador de Audio + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Aplicar + + + + &Reset + &Reiniciar + + + + &Set as default values + &Usar como valores por defecto + + + + Use the current values as default values for new videos. + Usa los valores actuales como valores por defecto para los nuevos vídeos. + + + + Set all controls to zero. + Pone todos los controles a cero. + + + + Information + Información + + + + The current values have been stored to be used as default. + Los valores actuales se han guardado y se usarán como valores predeterminados. + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer log + + + + SMPlayer - smplayer log + SMPlayer - smplayer log + + + + &Open + A&brir + + + + &Play + &Reproducir + + + + &Video + &Vídeo + + + + &Audio + A&udio + + + + &Subtitles + &Subtítulos + + + + &Browse + &Navegar + + + + Op&tions + &Opciones + + + + &Help + &Ayuda + + + + &File... + &Fichero... + + + + D&irectory... + D&irectorio... + + + + &Playlist... + &Lista de reproducción... + + + + &DVD from drive + &DVD desde unidad lectora + + + + D&VD from folder... + D&VD desde una carpeta... + + + + &URL... + &URL... + + + + &Clear + &Borrar + + + + &Recent files + Ficheros &recientes + + + + P&lay + &Reproducir + + + + &Pause + &Pausa + + + + &Stop + &Detener + + + + &Frame step + &Avanzar fotograma + + + + &Normal speed + Velocidad &normal + + + + &Halve speed + &Reducir a la mitad + + + + &Double speed + &Doblar + + + + Speed &-10% + Velocidad &-10% + + + + Speed &+10% + Velocidad &+10% + + + + Sp&eed + &Velocidad + + + + &Repeat + R&epetir + + + + &Fullscreen + &Pantalla completa + + + + &Compact mode + &Modo compacto + + + + Si&ze + &Tamaño + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &a 16:9 + + + + &Aspect ratio + Relación de &aspecto + + + + &None + &Ninguno + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Linear &Blend + + + + &Deinterlace + &Desentrelazado + + + + &Postprocessing + &Postprocesado + + + + &Autodetect phase + &Autodetección de fase + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + Añadir r&uido + + + + F&ilters + &Filtros + + + + &Equalizer + &Ecualizador + + + + &Screenshot + &Captura + + + + S&tay on top + E&ncima de todas las ventanas + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtros + + + + &Stereo + E&stéreo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Canales + + + + &Left channel + Canal &izquierdo + + + + &Right channel + Canal &derecho + + + + &Stereo mode + &Modo estéreo + + + + &Mute + &Silenciar + + + + Volume &- + Volumen &- + + + + Volume &+ + Volumen &+ + + + + &Delay - + &Retrasar - + + + + D&elay + + R&etrasar + + + + + &Select + &Seleccionar + + + + &Load... + &Cargar... + + + + Delay &- + Retrasar &- + + + + Delay &+ + Retrasar &+ + + + + &Up + &Arriba + + + + &Down + A&bajo + + + + &Title + &Título + + + + &Chapter + &Capítulo + + + + &Angle + &Ángulo + + + + &Playlist + &Lista de reproducción + + + + &Show frame counter + &Mostrar contador de imágenes + + + + &Disabled + &Desactivado + + + + &Seek bar + &Barra de progreso + + + + &Time + &Tiempo + + + + Time + T&otal time + Tiempo + Tiempo t&otal + + + + &OSD + &OSD + + + + &View logs + &Ver logs + + + + P&references + P&referencias + + + + About &Qt + Acerca de &Qt + + + + About &SMPlayer + Acerca de &SMPlayer + + + + <empty> + <vacío> + + + + Video + Vídeo + + + + Audio + Audio + + + + Playlists + Listas de reproducción + + + + All files + Todos los ficheros + + + + Choose a file + Elige un fichero + + + + SMPlayer - Information + SMPlayer - Información + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Las unidades de CDROM / DVD no han sido configuradas. +Se mostrará a continuación el diálogo de configuración. + + + + Choose a directory + Elige un directorio + + + + Subtitles + Subtítulos + + + + About Qt + Acerca de Qt + + + + Playing %1 + Reproduciendo %1 + + + + Pause + Pausa + + + + Stop + Stop + + + + Play / Pause + Reproducir / Pausa + + + + Pause / Frame step + Pausa / Avanzar fotograma + + + + U&nload + &Descargar + + + + V&CD + V&CD + + + + C&lose + C&errar + + + + View &info and properties... + Ver &información y propiedades... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Reiniciar + + + + Move &left + Desplazar &izquierda + + + + Move &right + Desplazar &derecha + + + + Move &up + Desplazar &arriba + + + + Move &down + Desplazar a&bajo + + + + &Pan && scan + Pan && &scan + + + + &Previous line in subtitles + Ir a línea a&nterior + + + + N&ext line in subtitles + Ir a línea &posterior + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Bajar volumen (2) + + + + Inc volume (2) + Subir volumen (2) + + + + Exit fullscreen + Salir de pantalla completa + + + + OSD - Next level + OSD - Siguiente nivel + + + + Dec contrast + Bajar contraste + + + + Inc contrast + Subir contraste + + + + Dec brightness + Bajar brillo + + + + Inc brightness + Subir brillo + + + + Dec hue + Bajar tono + + + + Inc hue + Subir tono + + + + Dec saturation + Bajar saturación + + + + Dec gamma + Bajar gamma + + + + Next audio + Siguiente audio + + + + Next subtitle + Siguiente subtítulo + + + + Next chapter + Siguiente capítulo + + + + Previous chapter + Capítulo anterior + + + + Inc saturation + Subir saturación + + + + Inc gamma + Subir gamma + + + + &Load external file... + C&argar archivo externo... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normal) + + + + Y&adif (double framerate) + Y&adif (doble framerate) + + + + &Next + S&iguiente + + + + Pre&vious + A&nterior + + + + Volume &normalization + &Normalización de volumen + + + + &Audio CD + CD de &audio + + + + Denoise nor&mal + Quitar ruido nor&mal + + + + Denoise &soft + Quitar ruido &suave + + + + Denoise o&ff + Quitar ruido desactivad&o + + + + Use SSA/&ASS library + &Usar la librería SSA/ASS + + + + Flip i&mage + Imagen &boca abajo + + + + &Toggle double size + &Tamaño normal / tamaño doble + + + + S&ize - + &Tamaño - + + + + Si&ze + + Ta&maño + + + + + Add &black borders + Añadir &bordes negros + + + + Soft&ware scaling + Escalado por soft&ware + + + + &FAQ + Preguntas &frecuentes + + + + Visualize &motion vectors + Vi&sualizar vectores de movimiento + + + + &Command line options + &Opciones para la línea de comandos + + + + SMPlayer command line options + Opciones para la línea de comandos de SMPlayer + + + + Enable &closed caption + Activar subtítulos para sordos (close capt&ion) + + + + &Forced subtitles only + Mostrar sólo subtítulos &forzados + + + + Reset video equalizer + Reiniciar el ecualizador de vídeo + + + + MPlayer has finished unexpectedly. + MPlayer ha finalizado inesperadamente. + + + + Exit code: %1 + Código de salida: %1 + + + + MPlayer failed to start. + El MPlayer no se ha ejecutado. + + + + Please check the MPlayer path in preferences. + Verifica la ruta al ejecutable del MPlayer en preferencias. + + + + MPlayer has crashed. + El MPlayer ha fallado. + + + + See the log for more info. + Mira el log para más información. + + + + &Rotate + &Girar + + + + &Off + &Desactivado + + + + &Rotate by 90 degrees clockwise and flip + &Girar 90 grados en el sentido de las agujas del reloj y darle la vuelta + + + + Rotate by 90 degrees &clockwise + Girar 90 &grados en el sentido de las agujas del reloj + + + + Rotate by 90 degrees counterclock&wise + Girar 90 grados en el sentido &contrario a las agujas del reloj + + + + Rotate by 90 degrees counterclockwise and &flip + Girar 90 grados en el sentido contrario a las agujas del reloj y darle la &vuelta + + + + &Jump to... + &Saltar a... + + + + Show context menu + Mostrar menú contextual + + + + Multimedia + Multimedia + + + + E&qualizer + Ec&ualizador + + + + Reset audio equalizer + Reiniciar el ecualizador de audio + + + + Find subtitles on &OpenSubtitles.org... + Buscar subtítulos en &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Subi&r subtítulos a OpenSubtitles.org... + + + + &Tips + &Consejos + + + + &Auto + &Auto + + + + Speed -&4% + Velocidad -&4% + + + + &Speed +4% + &Velocidad +4% + + + + Speed -&1% + Velocidad -&1% + + + + S&peed +1% + V&elocidad +1% + + + + Scree&n + Pa&ntalla + + + + &Default + Por &defecto + + + + Mirr&or image + Espe&jo + + + + Next video + Siguiente pista de vídeo + + + + &Track + video + P&ista + + + + &Track + audio + &Pista + + + + Warning - Using old MPlayer + Aviso - Usando un MPlayer anticuado + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + La versión del MPlayer (%1) que tienes instalada en tu sistema es obsoleta. SMPlayer no puede funcionar correctamente con esta versión: algunas opciones no funcionarán, la selección de subtítulos puede fallar... + + + + Please, update your MPlayer. + Por favor, actualiza el MPlayer. + + + + (This warning won't be displayed anymore) + (Este aviso no volverá a aparecer) + + + + Next aspect ratio + Siguiente relación de aspecto + + + + &Auto zoom + Auto &zoom + + + + Auto zoom for &16:9 + Auto zoom para &16:9 + + + + Auto zoom for &2.35:1 + Auto zoom para &2.35:1 + + + + Zoom for &16:9 + Zoom para &16:9 + + + + Zoom for &2.35:1 + Zoom para &2.35:1 + + + + Pre&view... + &Vista previa... + + + + &Always + &Siempre + + + + &Never + &Nunca + + + + While &playing + Durante la &reproducción + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer sigue funcionando aquí + + + + S&how icon in system tray + I&cono en la bandeja del sistema + + + + &Hide + &Ocultar + + + + &Restore + &Restaurar + + + + &Quit + &Salir + + + + Playlist + Lista de reproducción + + + + Core + + + Brightness: %1 + Brillo: %1 + + + + Contrast: %1 + Contraste: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Tono: %1 + + + + Saturation: %1 + Saturación: %1 + + + + Volume: %1 + Volumen: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + Escala del tipo de letra: %1 + + + + Aspect ratio: %1 + Relación de aspecto: %1 + + + + Updating the font cache. This may take some seconds... + Actualizando la caché de tipos de letra. Esto puede llevar algunos segundos... + + + + DefaultGui + + + Welcome to SMPlayer + Bienvenido a SMPlayer + + + + Audio + Audio + + + + Subtitle + Subtítulo + + + + &Main toolbar + Barra &principal + + + + &Language toolbar + Barra de &idioma + + + + &Toolbars + &Barras de herramientas + + + + EqSlider + + + icon + icon + + + + ErrorDialog + + + Hide log + Ocultar log + + + + Show log + Mostrar log + + + + MPlayer Error + Error de MPlayer + + + + icon + icon + + + + Error + Error + + + + FileDownloader + + + Downloading... + Descargando... + + + + Downloading %1 + Descargando %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Propiedades del fichero + + + + &Information + &Información + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Selecciona el demuxer que se usará para este fichero: + + + + &Reset + &Reiniciar + + + + &Video codec + Códec de &vídeo + + + + &Select the video codec: + &Selecciona el códec de vídeo: + + + + A&udio codec + Códec de a&udio + + + + &Select the audio codec: + &Selecciona el códec de audio: + + + + &MPlayer options + Opciones para el &MPlayer + + + + Additional Options for MPlayer + Opciones Adicionales para el MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aquí puedes pasar opciones extra al MPlayer. +Escríbelas separadas por espacios. +Ejemplo: -flip -nosound + + + + &Options: + &Opciones: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + También puedes pasar filtros de vídeo adicionales. +Sepáralos con ",". ¡No uses espacios! +Ejemplo: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + Filtros de víd&eo: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Y finalmente los filtros de audio. Misma norma que para los filtros de audio. +Ejemplo: resample=44100:0:0,volnorm + + + + Audio &filters: + &Filtros de audio: + + + + OK + Aceptar + + + + Cancel + Cancelar + + + + Apply + Aplicar + + + + FindSubtitlesWindow + + + Language + Idioma + + + + Name + Nombre + + + + Format + Formato + + + + Files + Ficheros + + + + Date + Fecha + + + + Uploaded by + Subido por + + + + All + Todos + + + + Close + Cerrar + + + + &Download + &Descargar + + + + &Copy link to clipboard + &Copiar enlace al portapapeles + + + + Error + Error + + + + Download failed: %1. + La descarga ha fallado: %1. + + + + Connecting to %1... + Conectando con %1... + + + + Downloading... + Descargando... + + + + Done. + Hecho. + + + + %1 files available + %1 ficheros disponibles + + + + Failed to parse the received data. + No se ha podido interpretar los datos recibidos. + + + + Find Subtitles + Buscar Subtítulos + + + + &Subtitles for + &Subtítulos para + + + + &Language: + &Idioma: + + + + &Refresh + &Refrescar + + + + Subtitle saved as %1 + Subtítulo grabado como %1 + + + + %1 subtitle(s) extracted + + %1 subtítulo extraido + %1 subtítulos extraidos + + + + + Overwrite? + ¿Sobreescribir? + + + + The file %1 already exits, overwrite? + El fichero %1 ya existe, ¿sobreescribir? + + + + Error saving file + Error al grabar el fichero + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + No se ha podido guardar el fichero descargado +en la carpeta %1 +Por favor verifica los permisos de esa carpeta. + + + + Download failed + La descarga ha fallado + + + + Temporary file %1 + Fichero temporal %1 + + + + InfoFile + + + General + General + + + + Size + Tamaño + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Duración + + + + Demuxer + Demuxer + + + + Name + Nombre + + + + Artist + Artista + + + + Author + Autor + + + + Album + Álbum + + + + Genre + Género + + + + Date + Fecha + + + + Track + Pista + + + + Copyright + Copyright + + + + Comment + Comentario + + + + Software + Software + + + + Clip info + Información del clip + + + + Video + Vídeo + + + + Resolution + Resolución + + + + Aspect ratio + Relación de aspecto + + + + Format + Formato + + + + Bitrate + Tasa de bits + + + + %1 kbps + %1 kbps + + + + Frames per second + Imágenes por segundo + + + + Selected codec + Códec seleccionado + + + + Initial Audio Stream + Pista de audio inicial + + + + Rate + Tasa + + + + %1 Hz + %1 Hz + + + + Channels + Canales + + + + Audio Streams + Pistas de audio + + + + Language + Idioma + + + + empty + vacío + + + + Subtitles + Subtítulos + + + + Type + Tipo + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + + + + + Stream title + Título del stream + + + + Stream URL + URL del stream + + + + File + Fichero + + + + InputDVDDirectory + + + Choose a directory + Elige un directorio + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Reproducir un DVD desde una carpeta + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Es posible reproducir un dvd desde el disco duro. Simplemente selecciona la carpeta que contiene los directorios VIDEO_TS y AUDIO_TS. + + + + Choose a directory... + Elegir un directorio... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Introduce la versión de MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer no ha podido identificar la version de MPlayer que estás usando. + + + + Version reported by MPlayer: + Versión mostrada por MPlayer: + + + + Please, &select the correct version: + Por favor, &selecciona la versión correcta: + + + + 1.0rc1 or older + 1.0rc1 o anterior + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Más nueva que 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Introduce una URL + + + + &URL: + &URL: + + + + It's a &playlist + Es una &lista de reproducción + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Si esta opción está activada, la URL será tratada como una lista de reproducción: se abrirá como texto y se reproducirán las URLs que se encuentren. + + + + Languages + + + Afar + Afar + + + + Abkhazian + Abjaso + + + + Afrikaans + Afrikaans + + + + Amharic + Amárico + + + + Arabic + Árabe + + + + Assamese + Asamés + + + + Aymara + Aimara + + + + Azerbaijani + Azerí + + + + Bashkir + Baskir + + + + Byelorussian + Bielorruso + + + + Bulgarian + Búlgaro + + + + Bihari + Bhojpurí + + + + Bislama + Bislama + + + + Bengali + Bengalí + + + + Tibetan + Tibetano + + + + Breton + Bretón + + + + Catalan + Catalán + + + + Corsican + Corso + + + + Czech + Checo + + + + Welsh + Galés + + + + Danish + Danés + + + + German + Alemán + + + + Bhutani + Dzongkha + + + + Greek + Griego + + + + English + Inglés + + + + Esperanto + Esperanto + + + + Spanish + Español + + + + Estonian + Estonio + + + + Basque + Vasco + + + + Persian + Persa + + + + Finnish + Finés + + + + Fiji + Fijiano + + + + Faroese + Feroés + + + + French + Francés + + + + Frisian + Frisón + + + + Irish + Irlandés + + + + Scots + Escocés + + + + Galician + Gallego + + + + Guarani + Guaraní + + + + Gujarati + Guyaratí + + + + Hausa + Hausa + + + + Hebrew + Hebreo + + + + Hindi + Hindi + + + + Croatian + Croata + + + + Hungarian + Húngaro + + + + Armenian + Armenio + + + + Interlingua + Interlingua + + + + Indonesian + Indonesio + + + + Interlingue + Occidental + + + + Inupiak + Inupiaq + + + + Icelandic + Islandés + + + + Italian + Italiano + + + + Inuktitut + Inuktitut + + + + Japanese + Japonés + + + + Javanese + Javanés + + + + Georgian + Georgiano + + + + Kazakh + Kazajo + + + + Greenlandic + Groenlandés + + + + Cambodian + Camboyano + + + + Kannada + Canarés + + + + Korean + Coreano + + + + Kashmiri + Cachemiro + + + + Kurdish + Kurdo + + + + Kirghiz + Kirguís + + + + Latin + Latín + + + + Lingala + Lingala + + + + Laothian + Lao + + + + Lithuanian + Lituano + + + + Latvian + Letón + + + + Malagasy + Malgache + + + + Maori + Maorí + + + + Macedonian + Macedonio + + + + Malayalam + Malayalam + + + + Mongolian + Mongol + + + + Moldavian + Moldavo + + + + Marathi + Maratí + + + + Malay + Malayo + + + + Maltese + Maltés + + + + Burmese + Birmano + + + + Nauru + Nauruano + + + + Nepali + Nepalí + + + + Dutch + Holandés + + + + Norwegian + Noruego + + + + Occitan + Occitano + + + + Oriya + Oriya + + + + Punjabi + Panyabí + + + + Polish + Polaco + + + + Pashto + Pastú + + + + Portuguese + Portugués + + + + Quechua + Quechua + + + + Kirundi + Kirundi + + + + Romanian + Rumano + + + + Russian + Ruso + + + + Kinyarwanda + Ruandés + + + + Sanskrit + Sánscrito + + + + Sindhi + Sindhi + + + + Sangho + Sango + + + + Sinhalese + Cingalés + + + + Slovak + Eslovaco + + + + Slovenian + Esloveno + + + + Samoan + Samoano + + + + Shona + Shona + + + + Somali + Somalí + + + + Albanian + Albanés + + + + Serbian + Serbio + + + + Siswati + Suazi + + + + Sesotho + Sesotho + + + + Sundanese + Sundanés + + + + Swedish + Sueco + + + + Swahili + Suajili + + + + Tamil + Tamil + + + + Telugu + Telugú + + + + Tajik + Tayiko + + + + Thai + Tailandés + + + + Tigrinya + Tigriña + + + + Turkmen + Turcomano + + + + Tagalog + Tagalo + + + + Setswana + Setsuana + + + + Tonga + Tongano + + + + Turkish + Turco + + + + Tsonga + Tsonga + + + + Tatar + Tártaro + + + + Twi + Twi + + + + Uighur + Uigur + + + + Ukrainian + Ucraniano + + + + Urdu + Urdu + + + + Uzbek + Uzbeko + + + + Vietnamese + Vietnamita + + + + Wolof + Wolof + + + + Xhosa + Xhosa + + + + Yiddish + Yídish + + + + Yoruba + Yoruba + + + + Zhuang + Chuan + + + + Chinese + Chino + + + + Zulu + Zulú + + + + Portuguese - Brazil + Portugués - Brasil + + + + Portuguese - Portugal + Portugués - Portugal + + + + Simplified-Chinese + Chino simplificado + + + + Traditional Chinese + Chino tradicional + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + Occidental + + + + Western European Languages with Euro + Occidental con euro + + + + Slavic/Central European Languages + Eslavo/Centroeuropeo + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Gallego, Maltés, Turco + + + + Old Baltic charset + Báltico antiguo + + + + Cyrillic + Cirílico + + + + Modern Greek + Griego moderno + + + + Baltic + Báltico + + + + Celtic + Céltico + + + + Hebrew charsets + Hebreo + + + + Ukrainian, Belarusian + Ucraniano, Belaruso + + + + Simplified Chinese charset + Chino simplificado + + + + Traditional Chinese charset + Chino tradicional + + + + Japanese charsets + Japonés + + + + Korean charset + Coreano + + + + Thai charset + Thai + + + + Cyrillic Windows + Cirílico Windows + + + + Slavic/Central European Windows + Eslavo/Centroeuropeo Windows + + + + Arabic Windows + Árabe Windows + + + + Rhaeto-Romance + Retorrománico + + + + Serbo-Croatian + Serbocroata + + + + Volapük + Volapük + + + + Avestan + + + + + Akan + + + + + Aragonese + Aragonés + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + Checheno + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + Gaélico + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + Tahitiano + + + + Venda + + + + + Volapük + Volapük + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Elige el nombre de fichero + + + + Confirm overwrite? + ¿Confirmar sobreescribir? + + + + The file already exists. +Do you want to overwrite? + El fichero ya existe. +¿Quieres sobreescribirlo? + + + + Error saving file + Error al grabar el fichero + + + + The log couldn't be saved + No se ha podido grabar el fichero log + + + + Logs + Logs + + + + LogWindowBase + + + Log Window + Log Window + + + + Save + Guardar + + + + Copy to clipboard + Copiar al portapapeles + + + + Close + Cerrar + + + + &Close + &Cerrar + + + + MiniGui + + + Control bar + Barra de control + + + + MpcGui + + + Control bar + Barra de control + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nombre + + + + Length + Duración + + + + Choose a file + Elige un fichero + + + + Choose a filename + Elige un fichero + + + + Confirm overwrite? + ¿Confirmar sobreescribir? + + + + Select one or more files to open + Selecciona uno o más ficheros + + + + Choose a directory + Elige un directorio + + + + The file %1 already exists. +Do you want to overwrite? + El fichero %1 ya existe. +¿Quieres sobreescribirlo? + + + + Edit name + Editar nombre + + + + Type the name that will be displayed in the playlist for this file: + Teclea el nombre que se mostrará en la lista para este fichero: + + + + &Play + &Reproducir + + + + &Edit + &Editar + + + + Playlists + Listas de reproducción + + + + All files + Todos los ficheros + + + + &Load + &Cargar + + + + &Save + &Grabar + + + + &Next + &Siguiente + + + + Pre&vious + &Anterior + + + + Move &up + &Bajar + + + + Move &down + &Subir + + + + &Repeat + R&epetir + + + + S&huffle + &Desordenar + + + + Add &current file + Añadir fichero &actual + + + + Add &file(s) + Añadir &fichero(s) + + + + Add &directory + Añadir &directorio + + + + Remove &selected + Borrar &selección + + + + Remove &all + Borrar &todo + + + + SMPlayer - Playlist + SMPlayer - Lista de reproducción + + + + Add... + Añadir... + + + + Remove... + Borrar... + + + + Playlist modified + Lista de reproducción modificada + + + + There are unsaved changes, do you want to save the playlist? + Hay cambios sin guardar, ¿quieres grabar la lista de reproducción? + + + + Preferences + Preferencias + + + + PlaylistPreferences + + + Playlist - Preferences + Lista de reproducción - Preferencias + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Marca esta opción si quieres que al añadir un directorio se añadan los ficheros de los subdirectorios recursivamente. De lo contrario sólo se añadirán los ficheros del directorio seleccionado. + + + + &Add files in directories recursively + &Añadir los ficheros de los directorios recursivamente + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Marca esta opción para obtener información sobre los ficheros que serán añadidos a la lista. Esto permite mostrar el título (si está disponible) y la duración de los ficheros. De lo contrario esta información no estará disponible hasta que el fichero sea reproducido. Cuidado: esta opción puede ser lenta, especialmente si se añaden muchos ficheros. + + + + Automatically get &info about files added + &Obtener información automáticamente de los ficheros añadidos + + + + &Save copy of playlist on exit + &Guardar copia de la lista de reproducción al salir + + + + &Play files from start + &Reproducir ficheros desde el principio + + + + PrefAdvanced + + + Advanced + Avanzado + + + + Auto + Auto + + + + &Advanced + &Avanzado + + + + icon + icon + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aquí puedes pasar opciones extra al MPlayer. +Escríbelas separadas por espacios. +Ejemplo: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + También puedes pasar filtros de vídeo adicionales. +Sepáralos con ",". ¡No uses espacios! +Ejemplo: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Y finalmente los filtros de audio. Misma norma que para los filtros de audio. +Ejemplo: resample=44100:0:0,volnorm + + + + Log MPlayer output + Guardar los textos de la salida del MPlayer + + + + Log SMPlayer output + Guardar los textos de la salida del SMPlayer + + + + This option is mainly intended for debugging the application. + Esta opción es principalmente para depurar la aplicación. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Marcando esta opción se pueden reducir los parpadeos, pero también podría pasar que el vídeo no se mostrase correctamente. + + + + Filter for SMPlayer logs + Filtro para los logs del SMPlayer + + + + &Monitor aspect: + Relación de aspecto del &monitor: + + + + &Run MPlayer in its own window + E&jecutar el MPlayer en su propia ventana + + + + &Options: + &Opciones: + + + + V&ideo filters: + Filtros de &vídeo: + + + + Audio &filters: + &Filtros de audio: + + + + &Colorkey: + &Colorkey: + + + + Log &SMPlayer output + Guardar los textos de la salida del &SMPlayer + + + + &Filter for SMPlayer logs: + &Filtro para los logs del SMPlayer: + + + + C&hange... + Cam&biar... + + + + Logs + Logs + + + + Log MPlayer &output + Guardar los text&os de la salida del MPlayer + + + + Options for MP&layer + Opciones para el MP&layer + + + + Autosave MPlayer log + Guardar automáticamente los textos de salida de MPlayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Si esta opción está marcada, los textos de salida del MPlayer se guardarán en el fichero especificado cada vez que comience la reproducción de un fichero. La opción está pensada para programas externos de modo que puedan obtener información sobre el fichero en reproducción. + + + + Autosave MPlayer log filename + Nombre de fichero para los logs del MPlayer + + + + Enter here the path and filename that will be used to save the MPlayer log. + Introduce la ruta completa para el fichero que se usará para guardar los textos de salida del MPlayer. + + + + A&utosave MPlayer log to file + Guardar a&utomáticamente los textos de salida de MPlayer en un fichero + + + + Pass short filenames (8+3) to MPlayer + Pasar nombres cortos (8+3) a MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Actualmente MPlayer no puede abrir ficheros cuyo nombre contengan caracteres fuera de la página de códigos local. Activando esta opción SMPlayer pasará a MPlayer la versión corta de los nombres, y por tanto podrá abrirlos. + + + + &Pass short filenames (8+3) to MPlayer + &Pasar nombres cortos (8+3) a MPlayer + + + + Monitor aspect + Relación de aspecto del monitor + + + + Select the aspect ratio of your monitor. + Selecciona la relación de aspecto del monitor. + + + + Run MPlayer in its own window + Ejecutar el MPlayer en su propia ventana + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Si marcas esta opción, la ventana de vídeo de MPlayer no será empotrada en la ventana principal de SMPlayer, sino que usará la suya propia. Ten en cuenta que en este caso los eventos del ratón y teclado serán procesados directamente por MPlayer, lo que significa que los atajos de teclado y clicks del ratón probablemente no funcionarán del modo esperado cuando la ventana de MPlayer esté en primer plano. + + + + Colorkey + Colorkey + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Si ves partes del vídeo sobre otra ventana puedes cambiar el colorkey para solucionarlo. Intenta seleccionar un color cercano al negro. + + + + Options for MPlayer + Opciones para el MPlayer + + + + Options + Opciones + + + + Here you can type options for MPlayer. Write them separated by spaces. + Aquí puedes teclear opciones para el MPlayer. Deben ir separadas por espacios. + + + + Video filters + Filtros de vídeo + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Aquí puedes añadir filtros de vídeo para el MPlayer. Deben separarse por comas, ¡no uses espacios! + + + + Audio filters + Filtros de audio + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Aquí puedes añadir filtros de audio para el MPlayer. Deben separarse por comas, ¡no uses espacios! + + + + Repaint the background of the video window + Redibujar el fondo de la ventana de vídeo + + + + Repaint the backgroun&d of the video window + Redibujar el fondo de la ve&ntana de vídeo + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Usa IPv4 en conexiones a redes. Si falla, usa IPv6 automáticamente. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Usa IPv6 en conexiones a redes. Si falla, usa IPv4 automáticamente. + + + + Network Connection + Conexión a redes + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + Lo&gs + + + + Rebuild index if needed + Reconstruir un índice si es necesario + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Reconstruye el índice de los archivos en los que no se encuentra, permitiendo búsquedas. Es útil con descargas rotas/incompletas, o archivos que están mal creados. Esta opción solo funciona si el medio soporta búsquedas (p.e. no con stdin, pipe, etc).<br>Nota: la creación del índice puede llevar algún tiempo. + + + + Rebuild &index if needed + &Reconstruir un índice si es necesario + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Si esta opción está marcada, SMPlayer almacenará los mensajes de depuración que emite (puedes verlos en <b>Opciones -> Ver logs -> SMPlayer</b>). Esta información puede ser muy útil para el programador en caso de que encuentres algún bug. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Si está marcada, SMPlayer almacenará la salida del MPlayer (la puedes ver en <b>Opciones -> Ver logs -> MPlayer</b>). En caso de problemas este log puede contener información importante, por tanto es recomendable mantener activada esta opción. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Esta opción permite filtrar los mensajes que se almacenarán en el log. Aquí puedes escribir cualquier expresión regular.<br>Por ejemplo: <i>^Core::.*</i> mostrará sólo las líneas que comiencen por <i>Core::</i> + + + + Correct pts + Corregir pts + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Cambia MPlayer a un modo experimental en el que las marcas de tiempo para las imágenes de vídeo se calculan de una forma diferente y se soportan los filtros de vídeo que añaden nuevas imágenes o modifican las marcas de tiempo de los existentes. Se pueden ver las marcas de tiempo mas precisas por ejemplo cuando se reproducen subtítulos sincronizados a cambios de escena con la librería SSA/ASS activada. Sin corrección de pts seguramente la sincronización irá desplazada algunas imágenes. Esta opción no funciona correctamente con algunos demuxers y codecs. + + + + Proxy + Proxy + + + + Enable proxy + Activar proxy + + + + Enable/disable the use of the proxy. + Activa o desactiva el proxy. + + + + Host + Host + + + + The host name of the proxy. + El nombre del host del proxy. + + + + Port + Puerto + + + + The port of the proxy. + El puerto del proxy. + + + + Username + Nombre de usuario + + + + If the proxy requires authentication, this sets the username. + Si el proxy necesita autentificación, aquí se puede introducir el nombre de usuario. + + + + Password + Contraseña + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + La contraseña para el proxy. Advertencia: la contraseña se guardará como texto plano en el fichero de configuración. + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + Puedes establecer un proxy para las conexiones a internet (actualmente sólo se usan para descarga de subtítulos). + + + + &Enable proxy + Acti&var proxy + + + + &Host: + &Host: + + + + &Port: + &Puerto: + + + + &Username: + &Nombre de usuario: + + + + Pa&ssword: + &Contraseña: + + + + C&orrect PTS + C&orregir PTS + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + Tipo + + + + Select the proxy type to be used. + Selecciona el tipo de proxy que se usará. + + + + &Type: + &Tipo: + + + + Actions list + Lista de acciones + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + Aquí puedes especificar una lista de <i>acciones</i> que se ejecutarán cada vez que se abra un fichero. Encontrarás las acciones disponibles en el editor de atajos en la sección <b>Teclado y ratón</b>. Las acciones deben separarse con espacios. Aquellas acciones que se pueden activar o desactivar pueden ir seguidas de <i>true</i> o <i>false</i>. + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + Limitación: las acciones se ejecutan sólo cuando un fichero se abre, pero no cuando el proceso del mplayer es reiniciado (por ejemplo al seleccionar un filtro de audio o vídeo). + + + + Network + Redes + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + Ejec&utar las siguientes acciones cada vez que se abra un fichero. Las acciones deben estar separadas por espacios: + + + + &Network + R&edes + + + + Example: + Ejemplo: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + Reconstruye el índice de los archivos en los que no se encuentra, permitiendo búsquedas. Es útil con descargas rotas/incompletas, o archivos que están mal creados. Esta opción solo funciona si el medio soporta búsquedas (p.e. no con stdin, pipe, etc).<br><b>Nota:</b> la creación del índice puede llevar algún tiempo. + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + La contraseña para el proxy. <b>Advertencia:</b> la contraseña se guardará como texto plano en el fichero de configuración. + + + + PrefAssociations + + + Warning + Advertencia + + + + Not all files could be associated. Please check your security permissions and retry. + No todos los ficheros han podido ser asociados. Verifica los permisos de seguridad y reinténtalo. + + + + File Types + Tipos de ficheros + + + + Select all + Seleccionar todos + + + + Check all file types in the list + Marca todos los tipos de ficheros de la lista + + + + Uncheck all file types in the list + Desmarca todos los tipos de ficheros de la lista + + + + List of file types + Lista de tipos de ficheros + + + + File types + Tipos de ficheros + + + + Media files handled by SMPlayer: + Ficheros controlados por SMPlayer: + + + + Select All + Seleccionar todos + + + + Select None + No seleccionar ninguno + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Marca los tipos de ficheros que deseas que SMPlayer controle. Cuando pulses en Aplicar, los ficheros marcados serán asociados a SMPlayer. Si desmarcas un tipo de fichero, se recuperará la asociación previa. + + + + Select none + No seleccionar ninguno + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Nota:</b> (No es posible recuperar las asociaciones previas en Windows Vista). + + + + PrefDrives + + + Drives + Unidades de disco + + + + icon + icon + + + + CD device + Dispositivo CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Selecciona tu dispositivo CDROM. Se usará para reproducir VCDs y CDs de audio. + + + + DVD device + Dispositivo DVD + + + + Choose your DVD device. It will be used to play DVDs. + Selecciona tu dispositivo DVD. Se usará para reproducir DVDs. + + + + Select your &CD device: + Selecciona tu dispositivo &CD: + + + + Select your &DVD device: + Selecciona tu dispositivo &DVD: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer no escoge ninguna unidad de CDROM o DVD por defecto. Por tanto antes de que puedas reproducir un CD o DVD debes seleccionar las unidades que deseas usar (pueden ser la misma). + + + + PrefGeneral + + + General + General + + + + &General + &General + + + + Paths + Trayectorias + + + + Media settings + Opciones para los ficheros + + + + Preferred audio and subtitles + Audio y subtítulos preferidos + + + + Video + Vídeo + + + + Start videos in fullscreen + Comenzar los vídeos a pantalla completa + + + + Disable screensaver + Desactivar salvapantallas + + + + Audio + Audio + + + + AC3/DTS pass-through S/PDIF + Pasar AC3/DTS por S/PDIF + + + + Select the mplayer executable + Selecciona el ejecutable del mplayer + + + + Executables + Ejecutables + + + + All files + Todos los ficheros + + + + Select a directory + Seleccionar un directorio + + + + MPlayer executable + Ejecutable del MPlayer + + + + Screenshots folder + Carpeta para las capturas de pantalla + + + + Video output driver + Driver de salida de vídeo + + + + Audio output driver + Driver de salida de audio + + + + Select the audio output driver. + Selecciona el driver de audio. + + + + Remember settings + Recordar opciones + + + + Preferred audio language + Idioma preferido para el audio + + + + Preferred subtitle language + Idioma preferido para los subtítulos + + + + Software video equalizer + Ecualizador de vídeo por software + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Puedes marcar esta opción si tu tarjeta gráfica o el driver de vídeo no tienen soporte para ecualizador de vídeo.<br><b>Nota:</b> esta opción puede ser incompatible con algunos drivers de vídeo. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Si esta opción está marcada, todos los vídeos comenzarán a reproducirse a pantalla completa. + + + + Software volume control + Control de volumen por software + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Marca esta opción para usar el mezclador por software, en lugar del mezclador de la tarjeta de sonido. + + + + Postprocessing quality + Calidad del postprocesado + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Cambia dinámicamente el nivel de postprocesado dependiendo del tiempo de CPU disponible. El número que especifique será el mínimo nivel usado. Normalmente puede usar un número grande. + + + + Change volume + Cambiar volumen + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Si la opción está marcada, SMPlayer recordará el volumen de cada archivo y lo recuperará cuando se reproduzca otra vez. Para archivos nuevos se usará el volumen por defecto. + + + + 0 + 0 + + + + &Change volume on every file + Ca&mbiar el volumen en cada archivo + + + + Select the &MPlayer executable: + Selecciona el ejecutable del &MPlayer: + + + + &Folder for storing screenshots: + &Carpeta donde se guardarán las capturas de pantalla: + + + + &Audio: + &Audio: + + + + &Remember settings for all files (audio track, subtitles...) + &Recordar las opciones para cada vídeo (pista de audio, subtítulos...) + + + + Su&btitles: + Sub&títulos: + + + + &Quality: + &Calidad: + + + + Start videos in &fullscreen + Comen&zar los vídeos a pantalla completa + + + + Disable &screensaver + Desactivar &salvapantallas + + + + &Default volume: + Volumen por &defecto: + + + + Use s&oftware volume control + Usar control de volumen por s&oftware + + + + Ma&x. Amplification: + Má&x. amplificación: + + + + &AC3/DTS pass-through S/PDIF + &Pasar AC3/DTS por S/PDIF + + + + Direct rendering + Renderizado directo + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Si está marcado, activa el renderizado directo (no está soportado por todos los codecs y salidas de vídeo)<br><b>AVISO:</b> ¡Puede causar corrupción en el OSD y subtítulos! + + + + Double buffering + Doble buffer + + + + D&irect rendering + Renderizado d&irecto + + + + Dou&ble buffering + Do&ble buffer + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + El doble buffer soluciona los problemas de parpadeo almacenando dos imáenes en memoria y mostrando una mientras decodifica la otra. Puede afectar al OSD negativamente, pero a menudo elimina el parpadeo del OSD. + + + + &Enable postprocessing by default + &Activar el postprocesado por defecto + + + + Volume &normalization by default + &Normalización de volumen por defecto + + + + Close when finished + Cerrar al acabar la reproducción + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Si esta opción está marcada, la ventana principal se cerrará automáticamente cuando el fichero o lista de reproducción llegue al final. + + + + 2 (Stereo) + 2 (Estéreo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + Cana&les por defecto: + + + + &Pause when minimized + &Pausar al minimizar + + + + Pause when minimized + Pausar al minimizar + + + + Enable postprocessing by default + Activar el postprocesado por defecto + + + + Max. Amplification + Máx. amplificación + + + + Volume normalization by default + Normalización de volumen por defecto + + + + Maximizes the volume without distorting the sound. + Aumenta el volumen sin distorsionar el sonido. + + + + Default volume + Volumen por defecto + + + + Sets the initial volume that new files will use. + Establece el volumen inicial que tendrán los nuevos ficheros. + + + + Channels by default + Canales por defecto + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Fija el nivel máximo de amplificación en porcentaje (por defecto: 110). Un valor de 200 le permitirá ajustar el volumen hasta un máximo del doble del nivel actual. Con valores por debajo de 100 el volumen inicial (que es el 100%) estará por debajo del máximo, p.e. el OSD no se mostrará correctamente. + + + + Uses hardware AC3 passthrough + Usar pasarela hardware AC3 + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Cambia el número de canales de reproducción. MPlayer pide al decodificador que decodifique el audio en tantos canales como se hayan especificado. Entonces depende del decodificador cumplir con la petición. Normalmente sólo es importante cuando se reproducen vídeos con audio AC3 (como los DVDs). En ese caso la liba52 realiza la decodificación por defecto y mezcla correctamente el audio en el número de canales que se han pedido. NOTA: Esta opción es respetada por los codecs (AC3 solo), filtros (surround) y controladores de audio (al menos OSS). + + + + Postprocessing will be used by default on new opened files. + El postprocesado será usado por defecto en los nuevos ficheros que se abran. + + + + Audio track + Pista de audio + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Especifica la pista de audio por defecto para los nuevos ficheros. Si la pista no existe, se usará la primera. <br><b>Nota:</b> la opción <i>"idioma de audio preferido"</i> tiene preferencia sobre esta opción. + + + + Subtitle track + Pista de subtítulos + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Especifica la pista de subtítulos por defecto para los nuevos ficheros. Si la pista no existe, se usará la primera. <br><b>Nota:</b> la opción <i>"idioma de subtítulos preferido"</i> tiene preferencia sobre esta opción. + + + + Or choose a track number: + O selecciona un número de pista: + + + + Audi&o: + Aud&io: + + + + Preferred language: + Idioma preferido: + + + + Preferre&d audio and subtitles + Audio y subtítulos pre&feridos + + + + &Subtitle: + &Subtítulo: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aquí puedes introducir el idioma preferido para el audio y subtítulos. Cuando se reproduzca un vídeo con múltiples audios o subtítulos, SMPlayer intentará usar tu idioma preferido. Esto sólo funcionará con medios que ofrezcan información sobre los idiomas del audio o subtítulos, como los DVDs o ficheros mkv.<br>Este campo acepta expresiones regulares. Ejemplo: <b>es|esp|spa</b> seleccionará la pista si coincide con <i>es</i>, <i>esp</i> o <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + High speed &playback without altering pitch + No alterar el &tono en reproducción a mayor velocidad + + + + High speed playback without altering pitch + No alterar el tono en reproducción a mayor velocidad + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Permite cambiar la velocidad de reproducción sin cambiar el tono. Require al menos MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Cambiar el volumen justo antes de empezar la reproducción + + + + &Video + &Vídeo + + + + Use s&oftware video equalizer + Usar &ecualizador de vídeo por software + + + + A&udio + A&udio + + + + Volume + Volumen + + + + None + Ninguno + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normal) + + + + Yadif (double framerate) + Yadif (doble framerate) + + + + Linear Blend + Linear Blend + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + &Desentrelazado por defecto: + + + + Deinterlace by default + Desentrelazado por defecto + + + + Select the deinterlace filter that you want to be used for new videos opened. + Selecciona el filtro de desentrelazado que se usará por defecto para los nuevos vídeos. + + + + Remember time position + Recordar por donde se quedó el vídeo + + + + Remember &time position + Recordar por do&nde se quedó el vídeo + + + + Change volume just before p&laying + &Cambiar el volumen justo antes de empezar la reproducción + + + + Enable the audio equalizer + Activar el ecualizador de audio + + + + Check this option if you want to use the audio equalizer. + Marca esta opción para poder usar el ecualizador de audio. + + + + &Enable the audio equalizer + Activar el &ecualizador de audio + + + + Draw video using slices + Dibujar el vídeo por bandas + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Activa o desactiva el dibujado de vídeo por bandas/rebanadas de altura de 16-pixels. Si se desactiva, se dibujará la imagen entera de una pasada. Puede ser más rápido o más lento, dependiendo de la tarjeta gráfica y de la caché disponible. Sólo tiene efecto con los codecs libmpeg2 y libavcodec. + + + + Dra&w video using slices + Dibujar el vídeo &por bandas + + + + &Close when finished playback + Cerrar al acabar &la reproducción + + + + fast + rápido + + + + slow + lento + + + + fast - ATI cards + rápido - tarjetas ATI + + + + User defined... + Definido por el usuario... + + + + Default zoom + Zoom por defecto + + + + This option sets the default zoom which will be used for new videos. + Esta opción establece el zoom por defecto que se usará para los nuevos vídeos. + + + + Default &zoom: + &Zoom por defecto: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Aquí debes especificar el ejecutable del mplayer que será usado por el SMPlayer.<br>SMPlayer requiere al menos MPlayer 1.0rc1 (aunque se recomienda una revisión reciente del SVN). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Si esta opción es incorrecta, ¡smplayer no será capaz de reproducir nada! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Aquí puedes especificar la carpeta donde se guardarán las capturas de pantalla. Si dejas el campo vacío no se realizarán capturas de pantalla. + + + + Select the video output driver. %1 provides the best performance. + Selecciona el driver de vídeo. %1 proporciona el mejor rendimiento. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + Se recomienda usar %1. Intenta evitar %2 y %3 ya que son lentos y pueden tener un impacto en el rendimiento. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + Normalmente SMPlayer recordará las opciones para cada fichero que reproduzcas (la pista de audio seleccionada, el volumen, los filtros...). Desmarca esta opción si no te gusta que haga esto. + + + + If you check this option, SMPlayer will play all files from the beginning. + Si marcas esta opción, SMPlayer reproducirá todos los ficheros desde el principio. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Si esta opción está activada, el fichero se pondrá en pausa cuando la ventana principal sea minimizada. Una vez que la ventana vuelva a ser visible, la reproducción continuará. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Marca esta opción para desactivar el salvapantallas durante la reproducción.<br>El salvapantallas se volverá a activar cuando la reproducción acabe. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aquí puedes introducir el idioma preferido para la pista de audio. Cuando se reproduzca un vídeo con múltiples pistas de audio, SMPlayer intentará usar tu idioma preferido.<br>Esto sólo funcionará con medios que ofrezcan información sobre los idiomas de las pistas de audio, como los DVDs o ficheros mkv.<br>Este campo acepta expresiones regulares. Ejemplo: <b>es|esp|spa</b> seleccionará la pista de audio si coincide con <i>es</i>, <i>esp</i> o <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aquí puedes introducir el idioma preferido para los subtítulos. Cuando se reproduzca un vídeo con múltiples subtítulos, SMPlayer intentará usar tu idioma preferido.<br>Esto sólo funcionará con medios que ofrezcan información sobre los idiomas de los subtítulos, como los DVDs o ficheros mkv.<br>Este campo acepta expresiones regulares. Ejemplo: <b>es|esp|spa</b> seleccionará el subtítulo si coincide con <i>es</i>, <i>esp</i> o <i>spa</i>. + + + + Ou&tput driver: + D&river de salida: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Si esta opción está activada, el volumen inicial se establecerá justo antes de empezar la reproducción. Esto evita que el volumen esté muy alto durante un momento al empezar la reproducción. Requiere al menos MPlayer SVN r27872. + + + + Add black borders on fullscreen + Añadir bordes negros en modo pantalla completa + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Si se activa esta opción, se añadirán bordes negros a la imagen en modo de pantalla completa. Esto permite que los subtítulos aparezcan en los bordes negros. + + + + &Add black borders on fullscreen + Añadir bordes &negros en modo pantalla completa + + + + one ini file + un único fichero ini + + + + multiple ini files + múltiples ficheros ini + + + + Method to store the file settings + Método para guardar las opciones de los ficheros + + + + This option allows to change the way the file settings would be stored. The following options are available: + Esta opción permite cambiar el modo en que se guardarán las opciones de los ficheros. Están disponibles las siguientes opciones: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>un único fichero ini</b>: las opciones de todos los ficheros que se reproduzcan se guardarán en un único fichero ini (%1) + + + + The latter method could be faster if there is info for a lot of files. + El último método puede ser más rápido si hay guardada información de muchos ficheros. + + + + &Store settings in + Guardar las opcione&s en + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>múltiples ficheros ini</b>: se usará un fichero ini por cada fichero reproducido. Estos ficheros ini se guardarán en la carpeta %1 + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + Si se marca esta opción, SMPlayer recordará la última posición del fichero cuando lo abras de nuevo. Sólo funciona con ficheros normales (no con DVDs, CDs, URLs...). + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + Si está marcado, activa el renderizado directo (no está soportado por todos los codecs y salidas de vídeo)<br><b>Aviso:</b> ¡Puede causar corrupción en el OSD y subtítulos! + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Cambia el número de canales de reproducción. MPlayer pide al decodificador que decodifique el audio en tantos canales como se hayan especificado. Entonces depende del decodificador cumplir con la petición. Normalmente sólo es importante cuando se reproducen vídeos con audio AC3 (como los DVDs). En ese caso la liba52 realiza la decodificación por defecto y mezcla correctamente el audio en el número de canales que se han pedido. <b>Nota:</b> Esta opción es respetada por los codecs (AC3 solo), filtros (surround) y controladores de audio (al menos OSS). + + + + PrefInput + + + Keyboard and mouse + Teclado y ratón + + + + &Keyboard + &Teclado + + + + icon + icon + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aquí puedes cambiar los atajos de teclado. Para hacerlo haz doble click o empieza a escribir sobre un atajo. Opcionalmente también puedes guardar la lista para compartirla con otras personas o usarla en otro ordenador. + + + + &Mouse + &Ratón + + + + Button functions: + Funciones de los botones: + + + + Media seeking + Desplazarse por el medio + + + + Volume control + Controlar el volumen + + + + Zoom video + Hacer zoom en el vídeo + + + + None + Ninguna + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aquí puedes cambiar los atajos de teclado. Para hacerlo haz doble click o pulsa intro sobre un atajo. Opcionalmente también puedes guardar la lista para compartirla con otras personas o usarla en otro ordenador. + + + + &Left click + &Botón izquierdo + + + + &Double click + &Doble click + + + + &Wheel function: + &Función de la rueda: + + + + Shortcut editor + Editor de atajos + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Esta tabla te permite cambiar los atajos del teclado para la mayoría de las acciones disponibles. Haz doble click o pulsa intro sobre una acción, o pulsa el botón <b>Modificar atajo</b> para abrir el diálogo <i>Modificar atajo</i>. Hay dos maneras de cambiar un atajo: si el botón <b>Capturar</b> está activado, entonces simplemente presiona la nueva tecla o combinación de teclas que desees asignar para la acción (desafortunadamente no funciona con todas las teclas). Si el botón <b>Capturar</b> está desactivado entonces puedes teclear el nombre completo de la tecla. + + + + Left click + Botón izquierdo + + + + Select the action for left click on the mouse. + Selecciona la acción para el botón izquierdo del ratón. + + + + Double click + Doble click + + + + Select the action for double click on the mouse. + Selecciona la acción para el doble click del ratón. + + + + Wheel function + Función de la rueda + + + + Select the action for the mouse wheel. + Selecciona la acción para la rueda del ratón. + + + + Play + Reproducir + + + + Pause + Pausa + + + + Stop + Stop + + + + Fullscreen + Pantalla completa + + + + Compact + Modo compacto + + + + Screenshot + Captura de pantalla + + + + On top + Encima de todas las ventanas + + + + Mute + Silenciar + + + + Frame counter + Contador de imágenes + + + + Reset zoom + Quitar zoom + + + + Exit fullscreen + Salir de pantalla completa + + + + Double size + Tamaño doble + + + + Play / Pause + Reproducir / Pausa + + + + Pause / Frame step + Pausa / Avanzar fotograma + + + + Playlist + Lista de reproducción + + + + Preferences + Preferencias + + + + No function + Sin función + + + + Change speed + Cambiar velocidad + + + + Normal speed + Velocidad normal + + + + Keyboard + Teclado + + + + Mouse + Ratón + + + + Middle click + Botón central + + + + Select the action for middle click on the mouse. + Selecciona la acción para el botón central del ratón. + + + + M&iddle click + Botón &central + + + + X Button &1 + X Button &1 + + + + X Button &2 + X Button &2 + + + + Go backward (short) + Retroceso corto + + + + Go backward (medium) + Retroceso medio + + + + Go backward (long) + Retroceso largo + + + + Go forward (short) + Avance corto + + + + Go forward (medium) + Avance medio + + + + Go forward (long) + Avance largo + + + + OSD - Next level + OSD - Siguiente nivel + + + + Show context menu + Mostrar menú contextual + + + + &Right click + Botón de&recho + + + + Increase volume + Subir volumen + + + + Decrease volume + Bajar volumen + + + + X Button 1 + X Button 1 + + + + Select the action for the X button 1. + Selecciona la acción para el X button 1. + + + + X Button 2 + X Button 2 + + + + Select the action for the X button 2. + Selecciona la acción para el X button 2. + + + + Show video equalizer + Mostrar ecualizador de vídeo + + + + Show audio equalizer + Mostrar ecualizador de audio + + + + Always on top + Siempre encima de todas las ventanas + + + + Never on top + Nunca encima de todas las ventanas + + + + On top while playing + Encima de todas las ventana durante la reproducción + + + + PrefInterface + + + Interface + Interfaz + + + + <Autodetect> + <Autodetectar> + + + + Default + Por defecto + + + + &Interface + &Interfaz + + + + Seeking + Búsqueda + + + + Never + Nunca + + + + Whenever it's needed + Siempre que sea necesario + + + + Only after loading a new video + Sólo después de cargar un nuevo vídeo + + + + Recent files + Ficheros recientes + + + + Language + Idioma + + + + Here you can change the language of the application. + Aquí puedes cambiar el idioma del programa. + + + + Instances + Instancias + + + + &Short jump + &Salto corto + + + + &Medium jump + Salto &medio + + + + &Long jump + Salto &largo + + + + Mouse &wheel jump + &Rueda del ratón + + + + &Use only one running instance of SMPlayer + &Usar sólo una única instancia de SMPlayer + + + + Ma&x. items + Má&x. entradas + + + + St&yle: + Estil&o: + + + + Ico&n set: + Juego de ico&nos: + + + + L&anguage: + I&dioma: + + + + Main window + Ventana principal + + + + Auto&resize: + Ajuste automático del &tamaño: + + + + R&emember position and size + R&ecordar la posición y el tamaño + + + + Default font: + Tipo de letra por defecto: + + + + &Change... + &Cambiar... + + + + &Behaviour of time slider: + Desli&zador del tiempo: + + + + Seek to position while dragging + Ir a la posición mientras se arrastra + + + + Seek to position when released + Ir a la posición al soltarlo + + + + TextLabel + TextLabel + + + + &Seeking + &Búsqueda + + + + Ins&tances + Inst&ancias + + + + Autoresize + Ajuste automático del tamaño + + + + The main window can be resized automatically. Select the option you prefer. + La ventana principal puede cambiar de tamaño automáticamente. Selecciona la opción que prefieras. + + + + Remember position and size + Recordar la posición y el tamaño + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Si marcas esta opción, se guardará la posición y el tamaño de la ventana principal y se recuperarán cuando abras SMPlayer más tarde. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Selecciona el máximo número de elementos que se mostrarán en el submenú <b>Abrir->Ficheros recientes</b>. Si lo pones a 0 el menú no aparecerá. + + + + Icon set + Juego de iconos + + + + Select the icon set you prefer for the application. + Selecciona el juego de iconos que prefieras para el programa. + + + + Style + Estilo + + + + Select the style you prefer for the application. + Selecciona el estilo que prefieras para el programa. + + + + Default font + Tipo de letra por defecto + + + + You can change here the application's font. + Aquí puedes cambiar el tipo de letra del programa. + + + + Short jump + Salto corto + + + + Select the time that should be go forward or backward when you choose the %1 action. + Selecciona el tiempo que se avanzará o retrocederá cuando selecciones la acción %1. + + + + short jump + salto corto + + + + Medium jump + Salto medio + + + + medium jump + salto medio + + + + Long jump + Salto largo + + + + long jump + salto largo + + + + Mouse wheel jump + Salto por la rueda del ratón + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Selecciona el tiempo que se avanzará o retrocederá cuando muevas la rueda del ratón. + + + + Behaviour of time slider + Deslizador del tiempo + + + + Select what to do when dragging the time slider. + Selecciona qué hacer mientras se arrastra el deslizador. + + + + Use only one running instance of SMPlayer + Usar sólo una única instancia de SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Marca esta opción si quieres usar una misma instancia de SMPlayer para todos los ficheros que abras. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer necesita un puerto para recibir órdenes de otras instancias. Aquí puedes cambiarlo en caso de que el puerto predeterminado ya esté siendo usado por otro programa. + + + + Default GUI + GUI predeterminado + + + + Mini GUI + GUI Mini + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Selecciona el GUI que prefieras para el programa. Actualmente hay dos disponibles: el GUI predeterminado y el GUI mini.<br>El <b>GUI predeterminado</b> provee el GUI tradicional, con la barra de herramientas y la barra de control. El <b>GUI mini</b> provee un GUI más simple, sin barra de herramientas y con una barra de control con muy pocos botones.<br><b>Nota:</b> esta opción no tomará efecto hasta que no ejecutes SMPlayer otra vez. + + + + &GUI + &GUI + + + + Automatic port + Puerto automático + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer necesita un puerto para recibir órdenes de otras instancias. Si seleccionas esta opción, se eligirá un puerto de forma automática. + + + + Manual port + Puerto manual + + + + Port to listen + Puerto al que escuchar + + + + &Automatic + &Automático + + + + &Manual + &Manual + + + + Floating control + Control flotante + + + + Animated + Animado + + + + If this option is enabled, the floating control will appear with an animation. + Si se activa esta opción, el control flotante aparecerá por medio de una animación. + + + + Width + Ancho + + + + Specifies the width of the control (as a percentage). + Especifica el ancho del control (porcentaje del ancho de la pantalla). + + + + Margin + Margen + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + Esta opción establece el número de píxeles que el control flotante se alejará del borde inferior de la pantalla. Útil cuando la pantalla es un televisor, ya que el overscan puede evitar que el control se vea totalmente. + + + + Display in compact mode too + Mostrar también en modo compacto + + + + If this option is enabled, the floating control will appear in compact mode too. Warning: the floating control has not been designed for compact mode and it might not work properly. + Si se activa esta opción, el control flotante aparecerá también en modo compacto. Advertencia: el control flotante no se ha diseñado para el modo compacto y podría no funcionar correctamente. + + + + Bypass window manager + Saltar el gestor de ventanas + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + Si se activa esta opción, el control será mostrado en pantalla por su cuenta, sin contar con el gestor de ventanas. Desactiva esta opción si el control flotante no funciona correctamente con tu gestor de ventanas. + + + + &Floating control + Control &flotante + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + El control flotante aparece en el modo de pantalla completa cuando se mueve el ratón a la parte inferior de la pantalla. + + + + &Animated + A&nimado + + + + &Width: + Anch&o: + + + + 0 + 0 + + + + &Margin: + &Margen: + + + + Display in &compact mode too + Mostrar también en modo &compacto + + + + &Bypass window manager + &Saltar el gestor de ventanas + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + Si se activa esta opción, el control flotante aparecerá también en modo compacto. <b>Advertencia:</b> el control flotante no se ha diseñado para el modo compacto y podría no funcionar correctamente. + + + + Mpc GUI + GUI Mpc + + + + PrefPerformance + + + Performance + Rendimiento + + + + &Performance + &Rendimiento + + + + Priority + Prioridad + + + + Select the priority for the MPlayer process. + Selecciona la prioridad con la que se ejecutará el MPlayer. + + + + realtime + realtime + + + + high + high + + + + abovenormal + abovenormal + + + + normal + normal + + + + belownormal + belownormal + + + + idle + idle + + + + Cache + Caché + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Usar una caché puede mejorar el rendimiento en medios lentos + + + + Allow frame drop + Permitir saltar fotogramas + + + + Synchronization + Sincronización + + + + Audio/video auto synchronization + Sincronización automática de audio y vídeo + + + + Fast audio track switching + Cambio rápido de pista de audio + + + + Fast seek to chapters in dvds + Selección rápida de capítulos en dvds + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Establece la prioridad del proceso del mplayer según las prioridades disponibles en Windows.<br><b>ADVERTENCIA:</b> Usar la prioridad realtime puede causar el cuelgue del sistema. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Se salta la representación de algunas imágenes para mantener la sincronización audio/vídeo en sistemas lentos. + + + + Allow hard frame drop + Permitir saltar aún más fotogramas + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Salto mayor de imágenes (puede romper la decodificación). ¡Puede corromper la imagen! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Ajusta gradualmente la sincronización audio/vídeo basada en medidas de retardo de audio. + + + + Priorit&y: + Priorida&d: + + + + &Allow frame drop + &Permitir saltar fotogramas + + + + Allow &hard frame drop (can lead to image distortion) + Permitir saltar aún más &fotogramas (puede corromper la imagen) + + + + Audio/&video auto synchronization + Sincronización automática de audio y &vídeo + + + + Fact&or: + Fact&or: + + + + &Fast audio track switching + Cambio rápido de pista de &audio + + + + Fast &seek to chapters in dvds + &Selección rápida de capítulos en dvds + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Si la opción está marcada se intentará usar el método más rápido para buscar capítulos pero puede no funcionar con algunos discos. + + + + Skip loop filter + Saltar el filtro de bucle + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Posibles valores:<br> <b>Sí</b>: intentará usar el método más rápido para cambiar la pista de audio (puede no funcionar con algunos formatos).<br> <b>No</b>: el proceso del MPlayer será reiniciado cada vez que se cambie el audio.<br> <b>Auto</b>: SMPlayer decidirá qué hacer dependiendo de la versión del MPlayer. + + + + Cache for files + Caché para ficheros locales + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Esta opción especifica cuanta memoria se usará (en kBytes) cuando se rellene la caché para reproducir un fichero. + + + + Cache for streams + Caché para streams + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Esta opción especifica cuanta memoria se usará (en kBytes) cuando se rellene la caché para reproducir una URL. + + + + Cache for DVDs + Caché para DVDs + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Esta opción especifica cuanta memoria se usará (en kBytes) cuando se rellene la caché para reproducir un DVD.<br><b>Advertencia:</b> Puede que la búsqueda no funcione correctamente (incluyendo la selección de capítulos) si se usa una caché para DVDs. + + + + &Cache + &Caché + + + + Cache for &DVDs: + Caché para &DVDs: + + + + Cache for &local files: + Caché para ficheros &locales: + + + + Cache for &streams: + Caché para &streams: + + + + Enabled + Activado + + + + Skip (always) + Saltar (siempre) + + + + Skip only on HD videos + Saltar sólo en vídeos en alta definición + + + + Loop &filter + Filtro de buc&le + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Esta opción permite saltar el filtro de bucle (desbloqueo) durante la decodificación H.264. Como se supone que el fotograma filtrado debe usarse como referencia para decodificar fotogramas dependientes, esto tiene un efecto peor en la calidad que no hacer el desbloqueo en p.e. vídeo MPEG-2. Pero al menos para ficheros HDTV con una alta tasa de bits produce una gran aceleración sin una visible pérdida de calidad. + + + + Possible values: + Posibles valores: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Activado</b>: no se saltará el filtro de bucle + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Saltar (siempre)</b>: el filtro de bucle se saltará, sin importar el tamaño del vídeo + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Saltar sólo en vídeos en alta definición</b>: el filtro de bucle se saltará sólo en aquellos vídeos cuya altura sea %1 o superior. + + + + Cache for audio CDs + Caché para CDs de audio + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Esta opción especifica cuanta memoria se usará (en kBytes) cuando se rellene la caché para reproducir un CD de audio. + + + + Cache for &audio CDs: + Caché para CDs de &audio: + + + + Cache for VCDs + Caché para VCDs + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Esta opción especifica cuanta memoria se usará (en kBytes) cuando se rellene la caché para reproducir un VCD. + + + + Cache for &VCDs: + Caché para &VCDs: + + + + Threads for decoding + Hilos para la decodificación + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Establece el número de hilos que se usarán en la decodificación. Sólo para MPEG-1/2 y H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Hilos para la decodificación (sólo MPEG-1/2 y H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + Establece la prioridad del proceso del mplayer según las prioridades disponibles en Windows.<br><b>Advertencia:</b> Usar la prioridad realtime puede causar el cuelgue del sistema. + + + + PrefPlaylist + + + Playlist + Lista de reproducción + + + + Automatically add files to playlist + Añadir automáticamente ficheros a la lista de reproducción + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Si esta opción está activada, cada vez que se abra un fichero, SMPlayer borrará la lista de reproducción y añadirá el fichero a la lista. En caso de DVDs, CDs y VCDs, se añadirán todos los títulos del disco. + + + + Add consecutive files + Añadir ficheros consecutivos + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Si está opción está activada, SMPlayer buscará ficheros consecutivos (video_1.avi, video_2.avi...) y si los encuentra se añadirán a la lista. + + + + &Playlist + &Lista de reproducción + + + + &Automatically add files to playlist + &Añadir automáticamente ficheros a la lista de reproducción + + + + Add &consecutive files + Añadir ficheros &consecutivos + + + + PrefSubtitles + + + Subtitles + Subtítulos + + + + Choose a ttf file + Elige un fichero ttf + + + + Truetype Fonts + Fuentes Truetype + + + + &Subtitles + &Subtítulos + + + + Autoload + Autocargar + + + + Select first available subtitle + Seleccionar el primer subtítulo disponible + + + + Same name as movie + De igual nombre que el vídeo + + + + All subs containing movie name + Todos los que contengan el nombre del vídeo + + + + All subs in directory + Todos los subtítulos del directorio + + + + Position + Posición + + + + 0 + 0 + + + + Top + Arriba + + + + Bottom + Abajo + + + + Include subtitles on screenshots + Incluir subtítulos en las capturas de pantalla + + + + Font + Tipo de letra + + + + Select the font which will be used for subtitles (and OSD): + Selecciona el tipo de letra que se usará para los subtítulos (y OSD): + + + + Size + Tamaño + + + + No autoscale + No autoescalar + + + + Proportional to movie height + Proporcional a la altura del vídeo + + + + Proportional to movie width + Proporcional a la anchura del vídeo + + + + Proportional to movie diagonal + Proporcional a la diagonal del vídeo + + + + Subtitle position + Posición de los subtítulos + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Esta opción especifica la posición de los subtítulos en la ventana de vídeo. <i>100</i> es abajo del todo, mientras que <i>0</i> es la parte más alta. + + + + Au&toload subtitles files (*.srt, *.sub...): + A&utocargar ficheros de subtítulos (*.srt, *.sub...): + + + + S&elect first available subtitle + S&eleccionar el primer subtítulo disponible + + + + &Default subtitle encoding: + &Codificación de los subtítulos: + + + + Default &position of the subtitles on screen + &Posición por defecto de los subtítulos en la pantalla + + + + &Include subtitles on screenshots + &Incluir subtítulos en las capturas de pantalla + + + + &TTF font: + &Fuente ttf: + + + + S&ystem font: + Fuente del s&istema: + + + + A&utoscale: + A&utoescalar: + + + + Default subtitle encoding + Codificación de los subtítulos + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Si marcas esta opción, los subtítulos aparecerán también en las capturas de pantalla. Nota: esta opción podría causar algún problema. + + + + TTF font + Fuente ttf + + + + System font + Fuente del sistema + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Aquí puedes seleccionar un tipo de letra del systema para los subtítulos y OSD. <b>Nota:</b> requiere un MPlayer compilado con fontconfig. + + + + Autoscale + Autoescalar + + + + Text color + Color del texto + + + + Select the color for the text of the subtitles. + Selecciona el color del texto de los subtítulos. + + + + Border color + Color del borde + + + + Select the color for the border of the subtitles. + Selecciona el color del borde de los subtítulos. + + + + Select the subtitle autoload method. + Selecciona el método de carga automática de los subtítulos. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Si hay uno o más subtítulos disponibles, uno de ellos será seleccionado de forma automática, normalmente el primero, aunque si alguno de ellos se corresponde con el idioma preferido por el usuario se usará ese en su lugar. + + + + Select the subtitle autoscaling method. + Selecciona el método de escalado automático de los subtítulos. + + + + Select the encoding which will be used for subtitle files by default. + Selecciona la codificación por defecto que se usará para ficheros de subtítulos. + + + + Try to autodetect for this language + Intentar autodetección + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Cuando esta opción está activada, se intentará autodetectar la codificación para el idioma seleccionado. Si la autodetección falla se usará la codificación por defecto. Esta opción require un MPlayer compilado con soporte para ENCA. + + + + Subtitle language + Idioma de los subtítulos + + + + Select the language for which you want the encoding to be guessed automatically. + Selecciona el idioma para el que quieres que se realice autodetección de la codificación. + + + + Encoding + Codificación + + + + Try to a&utodetect for this language: + Intentar &autodetección para: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Aquí puedes seleccionar un tipo de letra ttf para los subtítulos. Normalmente encontrarás ficheros ttf en %1 + + + + Outline + Contorno + + + + Select the font for the subtitles. + Selecciona el tipo de letra para los subtítulos. + + + + The size in pixels. + El tamaño en píxeles. + + + + Bold + Negrita + + + + If checked, the text will be displayed in <b>bold</b>. + Si se activa, el texto se mostrará en <b>negrita</b>. + + + + Italic + Cursiva + + + + If checked, the text will be displayed in <i>italic</i>. + Si se activa, el texto se mostrará en <i>cursiva</i>. + + + + Left margin + Margen izquierdo + + + + Specifies the left margin in pixels. + Especifica el margen izquierdo en píxeles. + + + + Right margin + Margen derecho + + + + Specifies the right margin in pixels. + Especifica el margen derecho en píxeles. + + + + Vertical margin + Margen vertical + + + + Specifies the vertical margin in pixels. + Especifica el margen vertical en píxeles. + + + + Horizontal alignment + Alineación horizontal + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + Especifica la alineación horizontal. Los posibles valores son izquierda, centrado y derecha. + + + + Vertical alignment + Alineación vertical + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + Especifica la alineación vertical. Los posibles valores son abajo, en medio y arriba. + + + + Border style + Estilo del borde + + + + Specifies the border style. Possible values: outline and opaque box. + Especifica el estilo del borde. Posibles valores: contorno y opaco. + + + + Shadow + Sombra + + + + Si&ze: + T&amaño: + + + + Bol&d + Ne&grita + + + + &Italic + &Cursiva + + + + Colors + Colores + + + + &Text: + T&exto: + + + + &Border: + &Borde: + + + + Margins + Márgenes + + + + L&eft: + &Izquierdo: + + + + &Right: + &Derecho: + + + + Verti&cal: + Ve&rtical: + + + + Alignment + Alineación + + + + &Horizontal: + &Horizontal: + + + + &Vertical: + &Vertical: + + + + Border st&yle: + Esti&lo del borde: + + + + &Outline: + C&ontorno: + + + + Shado&w: + So&mbra: + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + Las siguientes opciones permiten definir el estilo que se usará para subtítulos sin estilo (srt, sub...). + + + + Left + horizontal alignment + Izquierda + + + + Centered + horizontal alignment + Centrado + + + + Right + horizontal alignment + Derecha + + + + Bottom + vertical alignment + Abajo + + + + Middle + vertical alignment + En medio + + + + Top + vertical alignment + Arriba + + + + Outline + border style + Contorno + + + + Opaque box + border style + Opaco + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + Si el estilo del borde está establecido en <i>contorno</i>, esta opción especifica el ancho del contorno alrededor del texto en píxeles. + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + Si el estilo del borde está establecido en <i>contorno</i>, esta opción especifica la profundidad de la sombra tras el texto en píxeles. + + + + Enable normal subtitles + Activar subtítulos normales + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + Pulsa este botón para seleccionar los subtítulos normales/tradicionales. Este tipo de subtítulos sólo pueden mostrar subtítulos de color blanco. + + + + Enable SSA/ASS subtitles + Activar subtítulos SSA/ASS + + + + Normal subtitles + Subtítulos normales + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + Esta opción NO cambia el tamaño de los subtítulos del vídeo actual. Para hacerlo, usa las opciones <i>Tamaño+</i> y <i>Tamaño-</i> del menú subtítulos. + + + + Default scale + Escala predeterminada + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + Esta opción especifica la escala predeterminada para los subtítulos normales que será usada al reproducir los nuevos vídeos que se abran. + + + + SSA/ASS subtitles + Subtítulos SSA/ASS + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + Esta opción especifica la escala predeterminada para los subtítulos SSA/ASS que será usada al reproducir los nuevos vídeos que se abran. + + + + Line spacing + Espaciado entre líneas + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + Esta opción especifica el espacio que se usará para separar múltiples líneas. Puede tener valores negativos. + + + + &Font and colors + &Tipo de letra y colores + + + + Enable &normal subtitles + Activar subtítulos &normales + + + + Enable SSA/&ASS subtitles + Activar subtítulos SSA/&ASS + + + + Default s&cale: + Es&cala predeterminada: + + + + Defa&ult scale: + Escala &predeterminada: + + + + &Line spacing: + Espaciado entre &líneas: + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + Pulsa este botón para activar la nueva librería SSA/ASS. Permite mostrar subtítulos de múltiples colores, tipos de letra... + + + + Freetype support + Soporte para Freetype + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + Normalmente no deberías desactivar esta opción. Hazlo solamente si tu MPlayer se ha compilado sin soporte para freetype. <b>¡Desactivar esta opción puede hacer que los subtítulos no funcionen en absoluto!</b> + + + + Freet&ype support + Soporte para Freet&ype + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + Si marcas esta opción, los subtítulos aparecerán también en las capturas de pantalla. <b>Nota:</b> esta opción podría causar algún problema. + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Ayuda + + + + OK + Aceptar + + + + Cancel + Cancelar + + + + Apply + Aplicar + + + + Help + Ayuda + + + + SMPlayer - Preferences + SMPlayer - Preferencias + + + + QObject + + + will show this message and then will exit. + mostrará este mensaje. + + + + the main window will be closed when the file/playlist finishes. + la ventana principal se cerrará cuando el fichero/lista de reproducción llege al final. + + + + This is SMPlayer v. %1 running on %2 + SMPlayer v. %1 ejecutándose en %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + intenta realizar una conexión con otra instancia del programa, y le enviará la acción especificada. Ejemplo: -send-action pause. El resto de opciones (si hay) se ignorarán y el programa finalizará. Retornará 0 si todo va bien o -1 si se produce algún fallo. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + lista_de_acciones es una lista de acciones separada por espacios. Las acciones se ejecutarán justo después de cargar el fichero (si se especifica alguno) en el mismo orden en que se han introducido. Para aquellas acciones que se pueden activar o desactivar, se puede pasar true o false como parámetro. Ejemplo: -actions "fullscreen compact true". Las comillas son necesarias si se pasa más de una acción. + + + + media + medio + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + si hay otra instancia en ejecución, los ficheros se añadirán a la lista de reproducción de esa instancia. Si no hay ninguna otra instancia, esta opción será ignorada y los ficheros se abrirán en una nueva instancia. + + + + the main window won't be closed when the file/playlist finishes. + la ventana principal no se cerrará cuando el fichero/lista de reproducción llege al final. + + + + the video will be played in fullscreen mode. + el vídeo se reproducirá a pantalla completa. + + + + the video will be played in window mode. + el vídeo se reproducirá en una ventana. + + + + Enqueue in SMPlayer + Agregar a la lista de reproducción de SMPlayer + + + + opens the mini gui instead of the default one. + abre el mini gui en lugar del normal. + + + + Restores the old associations and cleans up the registry. + Recupera las asociaciones anteriores y limpia el registro. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'medio' es cualquier tipo de archivo que SMPlayer pueda abrir. Puede ser un fichero local, un DVD (p.e. dvd://1), un stream de internet (p.e mms://....) o una lista de reproducción local en formato m3u o pls. Si se usa la opción -playlist, SMPlayer pasará la opción -playlist a MPlayer, por tanto será MPlayer quien controle la lista de reproducción, y no SMPlayer. + + + + Usage: + Modo de uso: + + + + directory + directorio + + + + action_name + nombre_de_acción + + + + action_list + lista_de_acciones + + + + opens the default gui. + abre el gui predeterminado. + + + + subtitle_file + fichero_de_subtítulos + + + + specifies the subtitle file to be loaded for the first video. + especifica el fichero de subtítulos que se cargará junto al primer vídeo. + + + + %1 second(s) + + %1 segundo + %1 segundos + + + + + %1 minute(s) + + %1 minuto + %1 minutos + + + + + %1 and %2 + %1 y %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + especifica el directorio donde smplayer guardará sus ficheros de configuración (smplayer.ini, smplayer_files.ini...) + + + + disabled + aspect_ratio + desactivado + + + + auto + aspect_ratio + auto + + + + unknown + aspect_ratio + desconocido + + + + opens the mpc gui. + abre el gui mpc. + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + Error %1 del API ZIP/UNZIP + + + + SeekWidget + + + icon + icon + + + + label + label + + + + ShortcutGetter + + + Modify shortcut + Modificar atajo + + + + Clear + Limpiar + + + + Press the key combination you want to assign + Pulsa la combinación de teclas que deseas asignar + + + + Capture + Capturar + + + + Capture keystrokes + Capturar las pulsaciones del teclado + + + + SubChooserDialog + + + Subtitle selection + Selección de subtítulos + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Este archivo contiene más de un subtítulo. Por favor elige aquellos que desees extraer. + + + + Select All + Seleccionar todos + + + + Select None + No seleccionar ninguno + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Saltar + + + + &Jump to: + &Saltar a: + + + + TristateCombo + + + Auto + Auto + + + + Yes + + + + + No + No + + + + VideoEqualizer + + + Contrast + Contraste + + + + Brightness + Brillo + + + + Hue + Tono + + + + Saturation + Saturación + + + + Gamma + Gamma + + + + &Reset + &Reiniciar + + + + &Set as default values + &Usar como valores por defecto + + + + Use the current values as default values for new videos. + Usa los valores actuales como valores por defecto para los nuevos vídeos. + + + + Set all controls to zero. + Pone todos los controles a cero. + + + + Video Equalizer + Ecualizador de Vídeo + + + + Information + Información + + + + The current values have been stored to be used as default. + Los valores actuales se han guardado y se usarán como valores predeterminados. + + + + VideoPreview + + + Video preview + Vista previa del vídeo + + + + Cancel + Cancelar + + + + Generated by SMPlayer + Generado por SMPlayer + + + + Creating thumbnails... + Creando miniaturas... + + + + File: %1 + Fichero: %1 + + + + Size: %1 MB + Tamaño: %1 MB + + + + Resolution: %1 x %2 + Resolución: %1 x %2 + + + + Length: %1 + Duración: %1 + + + + Save file + Guardar fichero + + + + Images (*.png *.jpg) + Imágenes (*.png *.jpg) + + + + Error saving file + Error al grabar el fichero + + + + The file couldn't be saved + El fichero no se ha podido grabar + + + + Error + Error + + + + The following error has occurred while creating the thumbnails: + Se ha producido el siguiente error mientras se creaban las miniaturas: + + + + The temporary directory (%1) can't be created + No se ha podido crear el directorio temporal (%1) + + + + The mplayer process didn't run + El proceso del mplayer no se ejecutó + + + + Resolution: %1x%2 + Resolución: %1x%2 + + + + Video format: %1 + Formato de vídeo: %1 + + + + Frames per second: %1 + Imágenes por segundo: %1 + + + + Aspect ratio: %1 + Relación de aspecto: %1 + + + + Video bitrate: %1 kbps + Tasa de bits del vídeo: %1 kbps + + + + Audio bitrate: %1 kbps + Tasa de bits del audio: %1 kbps + + + + Audio rate: %1 Hz + Tasa de audio: %1 Hz + + + + The file %1 can't be loaded + No se ha podido cargar el fichero %1 + + + + No filename + No hay fichero + + + + The mplayer process didn't start while trying to get info about the video + El proceso del mplayer no se ejecutó al intentar obtener información sobre el vídeo + + + + The length of the video is 0 + La duración del vídeo es 0 + + + + The file %1 doesn't exist + El fichero %1 no existe + + + + Images + Imágenes + + + + No info + Sin información + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + Tasa de bits del vídeo: %1 + + + + Audio bitrate: %1 + Tasa de audio: %1 + + + + Audio rate: %1 + Tasa de audio: %1 + + + + VideoPreviewConfigDialog + + + Default + Por defecto + + + + Video Preview + Vista previa del vídeo + + + + &File: + &Fichero: + + + + &Columns: + &Columnas: + + + + &Rows: + F&ilas: + + + + Add playing time to thumbnails + Añadir tiempo de reproducción a las imágenes + + + + &Aspect ratio: + Relación de &aspecto: + + + + &Seconds to skip at the beginnning: + &Segundos a saltar al principio: + + + + &Maximum width: + Tamaño &máximo: + + + + The preview will be created for the video you specify here. + La vista previa se creará del vídeo especificado aquí. + + + + The thumbnails will be arranged on a table. + Las imágenes en miniatura se mostrarán en una tabla. + + + + This option specifies the number of columns of the table. + Esta opción especifica el número de columnas de la tabla. + + + + This option specifies the number of rows of the table. + Esta opción especifica el número de filas de la tabla. + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + Si marcas esta opción, se añadirán a las imágenes en miniatura el tiempo de reproducción. + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + En caso de que la relación de aspecto de vídeo sea errónea, puedes seleccionar aquí una diferente. + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + Normalmente los primeros fotogramas son negros, por tanto es una buena idea saltarse unos cuantos segundos al inicio del vídeo. Esta opción permite especificar cuantos segundos se saltarán. + + + + This option specifies the maximum width in pixels that the generated preview image will have. + Esta opción especifica la anchura máxima en píxeles que tendrá la vista previa. + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + Para crear la vista previa se extraerán unos cuantos fotogramas. Aquí puedes elegir el formato de imagen que se usará para esos fotogramas. El formato PNG puede dar mejor calidad. + + + + Add playing &time to thumbnails + Añadir &tiempo de reproducción a las imágenes + + + + &Extract frames as + &Extraer imágenes en formato + + + + &DVD device or directory with DVD image: + &Dispositivo DVD o directorio con una imagen DVD: + + + + Enter here the DVD device or a folder with a DVD image. + Introduce aquí el dispositivo DVD o un directorio con una imagen de DVD. + + + + &DVD device: + &Dispositivo DVD: + + + + VolumeSliderAction + + + Volume + Volumen + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_eu.ts b/plugins/smplayer_plugin/translations/smplayer_eu.ts new file mode 100644 index 000000000..534948d2a --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_eu.ts @@ -0,0 +1,7230 @@ + + + + About + + + Version: %1 + Bertsioa: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Programa hau software librea da: berau zabaldu eta/edo eraldatu dezakezu Free Software Foundation-ek argitaratutako GNU lizentzia publiko orokorraren baldintzetan; edo lizentziaren 2. bertsioan, edo (zure aukeran) edozein bertsio berriagoan. + + + + The following people have contributed with translations: + Hurrengo jendeak itzulpnekin lagundu du: + + + + German + Alemana + + + + Slovak + Eslobiera + + + + Italian + Italiera + + + + French + Frantsesa + + + + %1, %2 and %3 + %1, %2 eta %3 + + + + Simplified-Chinese + Txinatar-soildua + + + + Russian + Errusiera + + + + %1 and %2 + %1 eta %2 + + + + Hungarian + Hungariera + + + + Polish + Poloniera + + + + Japanese + Japoniera + + + + Dutch + Herbeheretar + + + + Ukrainian + Ukraniera + + + + Portuguese - Brazil + Potugesa - Brasil + + + + Georgian + Georgiera + + + + Czech + Txekiera + + + + Bulgarian + Bulgariera + + + + Turkish + Turkiera + + + + Swedish + Suediera + + + + Serbian + Serbiera + + + + Traditional Chinese + Txinatar-tradizionala + + + + Romanian + Errumaniera + + + + Portuguese - Portugal + Potugesa - Portugal + + + + Greek + Grekoa + + + + Finnish + Finlandiera + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b>Ez (%2) + + + + About SMPlayer + SMPlyaer buruz + + + + &Info + &Informazioa + + + + icon + ikonoa + + + + &Contributions + &Laguntzaileak + + + + &Translators + &Itxultzaileak + + + + &License + &Lizentzia + + + + Visit our web for updates: + Joan gure webgunera eguneraketa bila: + + + + Get help in our forum: + Laguntza eskuratu gure foroetan: + + + + You can support SMPlayer by making a donation. + SMPlyaer lagundu dezakezu dohaitza bat egiten. + + + + More info + Informazio gehiago + + + + Korean + Koreera + + + + Macedonian + + + + + Basque + Euskara + + + + Using MPlayer %1 + + + + + Catalan + Katalaniera + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + Arabikoa + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Izena + + + + Description + Azalpena + + + + Shortcut + Laster-tekla + + + + &Save + &Gorde + + + + &Load + &Kargatu + + + + Key files + Gako fitxategiak + + + + Choose a filename + Hautatu fitxategi izena + + + + Confirm overwrite? + Gainidazketa berretsi? + + + + The file %1 already exists. +Do you want to overwrite? + %1 fitxategia abdago dagoeneko. +Gainidatzi nahi duzu? + + + + Choose a file + Hautatu fitxategi bat + + + + Error + Errorea + + + + The file couldn't be saved + Fitxategia ezin da gorde + + + + The file couldn't be loaded + Fitxategia ezin da kargatu + + + + &Change shortcut... + &Aldatu laster-tekla... + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + + + + + &Set as default values + &Lehenetsiriko balioak bezala ezarri + + + + Use the current values as default values for new videos. + Erabili uneko balioak lehenetsiriko balioak bezala bideo berrientzat. + + + + Set all controls to zero. + Ezarri kontrol guztiak zerora. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer erregistroa + + + + SMPlayer - smplayer log + SMPlayer - smplayer erregistroa + + + + &Open + &Ireki + + + + &Play + Erre&produzitu + + + + &Video + &Bideoa + + + + &Audio + &Audioa + + + + &Subtitles + A&zpitituluak + + + + &Browse + A&rakatu + + + + Op&tions + Au&kerak + + + + &Help + &Laguntza + + + + &File... + &Fitxategia... + + + + D&irectory... + D&irektorioa... + + + + &Playlist... + Erre&produkzio zerrenda... + + + + &DVD from drive + &DVD gailutik + + + + D&VD from folder... + D&VD karpetatik... + + + + &URL... + &URLa... + + + + &Clear + &Garbitu + + + + &Recent files + &Azken fitxategiak + + + + P&lay + &Erreproduzitu + + + + &Pause + &Pausatu + + + + &Stop + &Gelditu + + + + &Frame step + &Marko aurrerapena + + + + &Normal speed + Abiadura &normala + + + + &Halve speed + Abiadura &erdia + + + + &Double speed + Abiadura &bikoitza + + + + Speed &-10% + &-10% abiadura + + + + Speed &+10% + &+10% abiadura + + + + Sp&eed + A&biadura + + + + &Repeat + E&rrepikatu + + + + &Fullscreen + &Pantaila-osoa + + + + &Compact mode + Modu &konpaktoa + + + + Si&ze + Tamai&na + + + + 4:3 &Letterbox + 4:3 &Gutunontzi + + + + 16:9 L&etterbox + 16:9 G&utunontzi + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 16:9-&ra + + + + &Aspect ratio + &Itxura erlazioa + + + + &None + &Batez + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Na&haste linearra + + + + &Deinterlace + &Elkar deslotu + + + + &Postprocessing + &Postprozesuan + + + + &Autodetect phase + &Autoantzeman fasea + + + + &Deblock + &Desbloketu + + + + De&ring + + + + + Add n&oise + Gehitu s&oinua + + + + F&ilters + &Iragazkiak + + + + &Equalizer + &Ekualizatzailea + + + + &Screenshot + &Pantaila-argazkia + + + + S&tay on top + Man&tendu goian + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Iragazkiak + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Ingurunea + + + + &5.1 Surround + &5.1 Ingurunea + + + + &Channels + &Kanalak + + + + &Left channel + &Ezker kanala + + + + &Right channel + E&skuin kanala + + + + &Stereo mode + &Stereo modua + + + + &Mute + &Mututu + + + + Volume &- + Bolumena &- + + + + Volume &+ + Bolumena &+ + + + + &Delay - + A&tzerapena - + + + + D&elay + + At&zerapena + + + + + &Select + &Hautatu + + + + &Load... + &Kargatu... + + + + Delay &- + Atzerapena &- + + + + Delay &+ + Atzerapena &+ + + + + &Up + &Gora + + + + &Down + &Behera + + + + &Title + &Izenburura + + + + &Chapter + &Kapitulua + + + + &Angle + &Anguloa + + + + &Playlist + Erre&produkzio-zerrenda + + + + &Show frame counter + Ikusi &marko kontatzailea + + + + &Disabled + &Ezgaiturik + + + + &Seek bar + &Aurrerapen-barra + + + + &Time + &Denbora + + + + Time + T&otal time + Denbora + Denbora guz&tira + + + + &OSD + &OSD + + + + &View logs + &Ikusi erregistroak + + + + P&references + H&obespenak + + + + About &Qt + &QT-ri buruz + + + + About &SMPlayer + &SMPlyaer buruz + + + + <empty> + <hutsik> + + + + Video + Bideoa + + + + Audio + Audioa + + + + Playlists + Erreprodukzio-zerrendak + + + + All files + Fitxategi guztiak + + + + Choose a file + Hautatu fitxategi bat + + + + SMPlayer - Information + SMPlayer - Argibideak + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD gailurik ez dago konfiguraturik oraindik. +Konfigurazio morroia ikusko da orain, egin ahal izan dezazun. + + + + Choose a directory + Hautatu direktorio bat + + + + Subtitles + Azpititutluak + + + + About Qt + QT-ri buruz + + + + Playing %1 + %1 erreproduzitzen + + + + Pause + Pausatu + + + + Stop + Gelditu + + + + Play / Pause + Erreproduzitu / Pausatu + + + + Pause / Frame step + Pausa / Marko bat haurrera + + + + U&nload + Des&kargatu + + + + V&CD + V&CD + + + + C&lose + I&txi + + + + View &info and properties... + Ikusi informazio eta &propietateak... + + + + Zoom &- + Zooma &- + + + + Zoom &+ + Zooma &+ + + + + &Reset + Be&rezarri + + + + Move &left + Mugitu e&zkerrera + + + + Move &right + Mugitu e&skuinera + + + + Move &up + Mugitu &gora + + + + Move &down + Mugitu &behera + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + Azpititutuluetako &aurreko lerroa + + + + N&ext line in subtitles + Azpititutuluetako &hurrengo lerroa + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Dec bolumena (2) + + + + Inc volume (2) + Sar bolumena (2) + + + + Exit fullscreen + Irten pantaila-osotik + + + + OSD - Next level + OSD - Hurrengo maila + + + + Dec contrast + Dec kontrastea + + + + Inc contrast + Inc kontrastea + + + + Dec brightness + Dec disdira + + + + Inc brightness + Inc disdira + + + + Dec hue + Dec �bardura + + + + Inc hue + Inc �bardura + + + + Dec saturation + Dec saturazioa + + + + Dec gamma + Dec gamma + + + + Next audio + Hurrengo audioa + + + + Next subtitle + Hurrengo azpititulua + + + + Next chapter + Hurrengo kapitulua + + + + Previous chapter + Aurreko kapitulua + + + + Inc saturation + Inc saturazioa + + + + Inc gamma + Inc gamma + + + + &Load external file... + &Kargatu kanpo fitxategia... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normala) + + + + Y&adif (double framerate) + Y&adif (marko-tasa bikoitza) + + + + &Next + Hurre&ngoa + + + + Pre&vious + A&urrekoa + + + + Volume &normalization + Bolumen &normalizazioa + + + + &Audio CD + &Audio CDa + + + + Denoise nor&mal + Soinua kendu nor&mala + + + + Denoise &soft + Soinua kendu &suabea + + + + Denoise o&ff + Soinua kendu e&zgaitua + + + + Use SSA/&ASS library + Erabili SSA/&ASS liburutegia + + + + Flip i&mage + Biratu i&rudia + + + + &Toggle double size + &Txandakatu tamaina bikoitza + + + + S&ize - + T&amaina - + + + + Si&ze + + Ta&maina + + + + + Add &black borders + Gehitu ertz &beltzak + + + + Soft&ware scaling + Soft&ware eskalatzea + + + + &FAQ + &FAQ + + + + Visualize &motion vectors + Ikusi &filma bektoreak + + + + &Command line options + &Komando lerroko aukerak + + + + SMPlayer command line options + SMPlayer-en komando lerroko aukerak + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + Pis&ta + + + + &Track + audio + Pis&ta + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPLyaer martxan dago + + + + S&how icon in system tray + I&kusi ikonoa sistema-barran + + + + &Hide + &Ezkutatu + + + + &Restore + &Berezarri + + + + &Quit + Ama&itu + + + + Playlist + Erreprodukzio-zerrenda + + + + Core + + + Brightness: %1 + Disdira: %1 + + + + Contrast: %1 + Kontrastea: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Nabardura: %1 + + + + Saturation: %1 + Saturazioa: %1 + + + + Volume: %1 + Bolumena: %1 + + + + Zoom: %1 + Zooma: %1 + + + + Font scale: %1 + Letra-tipo eskala: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Ongietorri SMPlayer-era + + + + Audio + Audioa + + + + Subtitle + Azpititulua + + + + &Main toolbar + Tresna-barra &orokorra + + + + &Language toolbar + &Hizkuntz tresna-barra + + + + &Toolbars + &Tresna-barrak + + + + EqSlider + + + icon + ikonoa + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + ikonoa + + + + Error + Errorea + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Fitxategi propietateak + + + + &Information + &Argibideak + + + + &Demuxer + &Demultiplexatzailea + + + + &Select the demuxer that will be used for this file: + &Hautatu fitxategi honekin erabiliko den demultiplexatzailea: + + + + &Reset + &Garbitu + + + + &Video codec + &Bideo codec-a + + + + &Select the video codec: + &Hautatu bideo kodeka: + + + + A&udio codec + A&udio kodeka + + + + &Select the audio codec: + &Hautatu audio kodeka: + + + + &MPlayer options + &MPlayer aukerak + + + + Additional Options for MPlayer + MPlayer-en aukera gehigarriak + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Hemen aukera gehigarriak bnidali diezakiokezu MPlyer-i. +Zuirunez bereizirik idatzi. +Adibidez: -flip -nosound + + + + &Options: + &Aukerak: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Bideo iragazki gehigarriak ere bidali diezazkiokezu. +Bereizi itzazu "." bidez. Ez erabili zuriunerik +Adibidez: scale=512:-2.eq2=1.1 + + + + V&ideo filters: + B&ideo iragazkiak: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Baita ere audio iragazkiak. Bideo iragazkien arau berdinekin. +Adibidea: resample=44100:0:0,volnorm + + + + Audio &filters: + Audio ira&gazkiak: + + + + OK + Ados + + + + Cancel + Utzi + + + + Apply + Ezarri + + + + FindSubtitlesWindow + + + Language + Hizkuntza + + + + Name + Izena + + + + Format + Formatua + + + + Files + + + + + Date + Data + + + + Uploaded by + + + + + All + + + + + Close + Itxi + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Errorea + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Errorea fitxategia gordetzerakoan + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Orokorra + + + + Size + Tamaina + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URLa + + + + Length + Iraupena + + + + Demuxer + Demultiplexatzailea + + + + Name + Izena + + + + Artist + Artista + + + + Author + Egilea + + + + Album + Albuma + + + + Genre + Generoa + + + + Date + Data + + + + Track + Pista + + + + Copyright + Kopiatze-eskubideak + + + + Comment + Iruzkina + + + + Software + Softwarea + + + + Clip info + Klip argibideak + + + + Video + Bideoa + + + + Resolution + Erresoluzioa + + + + Aspect ratio + Itxura erlazioa + + + + Format + Formatua + + + + Bitrate + Bit-tasa + + + + %1 kbps + %1 kbps + + + + Frames per second + Marko segunduko + + + + Selected codec + Hautatutako kodeka + + + + Initial Audio Stream + Hasierako audio korrontea + + + + Rate + Erlazioa + + + + %1 Hz + %1 Hz + + + + Channels + Kanalak + + + + Audio Streams + Audio korrontea + + + + Language + Hizkuntza + + + + empty + hutsa + + + + Subtitles + Azpititutluak + + + + Type + Mota + + + + ID + Info for translators: this is a identification code + ID-a + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Korronte fitxategia + + + + Stream URL + Korronte URLa + + + + File + Fitxategia + + + + InputDVDDirectory + + + Choose a directory + Hautatu direktorio bat + + + + SMPlayer - Play a DVD from a folder + SMPlyaer - DVD bat karpeta batetatik erreproduzitu + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + DVD bat zure diska gogorretik erreproduzitu dezakezu. Hautatu VIDEO_TS eta AUDIO_TS direktorioak dituen direktorioa. + + + + Choose a directory... + Hautatu direktorio bat... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Idatzi MPlayer bertsioa + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer ez da erabiltzen duzun MPlayer bertsioa antzemateko gai. + + + + Version reported by MPlayer: + MPlayer-ek dioen bertsioa: + + + + Please, &select the correct version: + Mesedez hautatu &bertsio zuzena: + + + + 1.0rc1 or older + 1.0rc1 edo zaharragoa + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + 1.0rc2 baino berriagoa + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - sar URLa + + + + &URL: + &URLa: + + + + It's a &playlist + Erre&produkzio-zerrenda bat da + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Aukera hau hautaturik badago erreprodukzio-zerrenda bat bezala erabiliko da: testu bat bezala deskargatu eta barruko URLak erreproduzituko ditu. + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + Arabikoa + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + Bulgariera + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + Katalaniera + + + + Corsican + + + + + Czech + Txekiera + + + + Welsh + + + + + Danish + + + + + German + Alemana + + + + Greek + Grekoa + + + + English + Ingelesa + + + + Esperanto + + + + + Spanish + Gaztelania + + + + Estonian + + + + + Basque + Euskara + + + + Persian + + + + + Finnish + Finlandiera + + + + Faroese + + + + + French + Frantsesa + + + + Frisian + + + + + Irish + + + + + Galician + Galiziera + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + Hungariera + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + Italiera + + + + Inuktitut + + + + + Japanese + Japoniera + + + + Javanese + + + + + Georgian + Georgiera + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + Koreera + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + Herbeheretar + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + Poloniera + + + + Portuguese + + + + + Quechua + + + + + Romanian + Errumaniera + + + + Russian + Errusiera + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + Eslobiera + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + Serbiera + + + + Sundanese + + + + + Swedish + Suediera + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Turkiera + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + Ukraniera + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + Potugesa - Brasil + + + + Portuguese - Portugal + Potugesa - Portugal + + + + Simplified-Chinese + Txinatar-soildua + + + + Traditional Chinese + Txinatar-tradizionala + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Europa ekialdeko hizkuntzak + + + + Western European Languages with Euro + Europa ekialdeko hizkuntzak euroarekin + + + + Slavic/Central European Languages + Europa eslabiar/erdialdeko hizkuntzak + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galiziera, Maltera, Turkiera + + + + Old Baltic charset + Karaktere-joko baltiko zaharra + + + + Cyrillic + Zirilikoa + + + + Modern Greek + Greziar modernoa + + + + Baltic + Baltikoa + + + + Celtic + Zeltikoa + + + + Hebrew charsets + Hebrear karkatere-jokoa + + + + Ukrainian, Belarusian + Ukaniarra, Bielousiarra + + + + Simplified Chinese charset + Karaktere-joko txinatar soildua + + + + Traditional Chinese charset + Karaktere-joko txinatar tradizionala + + + + Japanese charsets + Karaktere-joko japoniarra + + + + Korean charset + Karaktere-joko korearra + + + + Thai charset + Karaktere-joko tailandesa + + + + Cyrillic Windows + Windows zirilikoa + + + + Slavic/Central European Windows + Windows Eslabiar/Erdialdeko europarra + + + + Arabic Windows + Windows Arabiarra + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Hor gordetzeko fitxategi izen bat hautatu + + + + Confirm overwrite? + Gainidazketa berretsi? + + + + The file already exists. +Do you want to overwrite? + Fitxategia badago dagoeneko.Gainidatzi nahi duzu? + + + + Error saving file + Errorea fitxategia gordetzerakoan + + + + The log couldn't be saved + Erregistroa ezin da gorde + + + + Logs + Erregistroak + + + + LogWindowBase + + + Log Window + Erregistro leihoa + + + + Save + Gorde + + + + Copy to clipboard + Kopiatu arbelara + + + + &Close + I&txi + + + + Close + Itxi + + + + MiniGui + + + Control bar + Kontrol-barra + + + + MpcGui + + + Control bar + Kontrol-barra + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Izena + + + + Length + Iraupena + + + + &Play + Erre&produzitu + + + + &Edit + &Editatu + + + + Playlists + Erreprodukzio-zerrendak + + + + Choose a file + Hautatu fitxategi bat + + + + Choose a filename + Hautatu fitxategi izen bat + + + + Confirm overwrite? + Gainidazketa berretsi? + + + + The file %1 already exists. +Do you want to overwrite? + %1 fitxategia abdago dagoeneko.Gainidatzi nahi duzu? + + + + All files + Fitxategi guztiak + + + + Select one or more files to open + Hautatu irekitzeko fitxategi bat edo gehiago + + + + Choose a directory + Hautatu direktorio bat + + + + Edit name + Editatu izena + + + + Type the name that will be displayed in the playlist for this file: + Idatzi fitxategi honentzat erreprodukzio-zerrendan ikusiko den izena: + + + + &Load + &Kargatu + + + + &Save + &Gorde + + + + &Next + &hurrengoa + + + + Pre&vious + Au&rrekoa + + + + Move &up + Mugitu &gora + + + + Move &down + Mugitu &behera + + + + &Repeat + E&rrepikatu + + + + S&huffle + Na&hasi + + + + Add &current file + Gehitu &uneko fitxategia + + + + Add &file(s) + Gehitu &fitxategia(k) + + + + Add &directory + Gehitu &direktorioa + + + + Remove &selected + Ezabatu &hautaturikoa + + + + Remove &all + Ezabatu &guztiak + + + + SMPlayer - Playlist + SMPlayer - Erreprodukzio zerrenda + + + + Add... + Gehitu... + + + + Remove... + Ezbatu... + + + + Playlist modified + Erreprodukzio-zerrenda eraldatua + + + + There are unsaved changes, do you want to save the playlist? + Gorde gabeko aldaketak daude, erreprodukzio zerrenda ezabatu nahi al duzu? + + + + Preferences + Hobespenak + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + Aurreratua + + + + Auto + Automatikoa + + + + &Advanced + &Aurreratua + + + + icon + ikonoa + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Hemen aukera gehigarriak bidali diezakiokezu MPlyer-i. +Zuirunez bereizirik idatzi. +Adibidez: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Bideo iragazki gehigarriak ere bidali diezazkiokezu. +Bereizi itzazu "." bidez. Ez erabili zuriunerik +Adibidez: scale=512:-2.eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Baita ere audio iragazkiak. Bideo iragazkien arau berdinekin. +Adibidea: resample=44100:0:0,volnorm + + + + Log MPlayer output + Erregistratu MPlayer irteera + + + + Log SMPlayer output + Erregistratu SMPlayer irteera + + + + This option is mainly intended for debugging the application. + Aukera hau aplikazio arazpenerako ipinia izan da nagusiki. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Aukera hau hautatuaz dir-dira gutxitu dezakezu, baina bideo beahr bezala ez bistaratzea egin dezake. + + + + Filter for SMPlayer logs + SMPlyaer erregistroen iragazkia + + + + &Monitor aspect: + &Monitore itxura: + + + + &Run MPlayer in its own window + &Abiarazi MPlayer bere leihoan + + + + &Options: + &Aukerak: + + + + V&ideo filters: + B&ideo iragazkiak: + + + + Audio &filters: + Audio ira&gazkiak: + + + + &Colorkey: + &Koloregakoa: + + + + Log &SMPlayer output + Erregistratu &SMPlayer irteera + + + + &Filter for SMPlayer logs: + SMPlyaer erregistroen &iragazkia: + + + + C&hange... + A&ldatu... + + + + Logs + Erregistroak + + + + Log MPlayer &output + Erregistratu MPlayer &irteera + + + + Options for MP&layer + MP&layer aukerak + + + + Autosave MPlayer log + MPlayer erregistroa automatikoki gorde + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Aukera hau hautaturik badago MPlayer erregistroa ezarritako fitxategian gordeko da fitxategi berri bat erreproduzitzen hasten den bakoitzean. Hau kanpo aplikazioentzat da beraiek erreproduzitzen ari zaren fitxategiaren informazioa izan dezaten. + + + + Autosave MPlayer log filename + Automatikoki gorde MPlayer erregistro fitxategi-izena + + + + Enter here the path and filename that will be used to save the MPlayer log. + Idatzi hemen MPlayer erregistroak gordetzeko erabiliko den bide eta fitxategia. + + + + A&utosave MPlayer log to file + A&utomatikoki gorde MPlayer erregistro fitxategi-izena + + + + Pass short filenames (8+3) to MPlayer + Bidali fitxategi izen laburrak (8+3) MPlyaer-i + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Oraingoz MPlayer-ek ezin du orrialde-kode lokaletik kanpoko karaktererik duen fitxategirik erreproduzitu. Auekra hau hautatuaz SMPlayer-k MPlayer-i fitxategi izneen brtsio laburra bidaliko dio eta hauek irekitzeko gai izan beharko zen. + + + + &Pass short filenames (8+3) to MPlayer + &Bidali fitxategi izen laburrak (8+3) MPlyaer-i + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Berreraiki fitxategi indizea aurkitzen ez bada, saltoak egiteko aukera emanaz. ERabilgarria hondaturiko/amaitugabeko deskarga edo gaizki eratutako fitxategientzat. Auekra honek euskarriak saltoak egitea onartzen badu bakarrik dago erabilgarri (adib ez sarrera estandarrean, tutu, ...)<br>Oharra: Indize sorrerak denbora bat har dezake. + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Mota + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Abusia + + + + Not all files could be associated. Please check your security permissions and retry. + Ez dira fitxategi guztiak ezarri. Mesedez egaztatu segurtasun baimeank eta berriz saiatu. + + + + File Types + Fitxategi motak + + + + Select all + Hautatu guztiak + + + + Check all file types in the list + Egiaztatu zerrendako fitxategi mota guztiak + + + + Uncheck all file types in the list + Ez egiaztatu zerendako fitxategi mota guztiak + + + + List of file types + Fitxategi mota zerrenda + + + + File types + Fitxategi motak + + + + Media files handled by SMPlayer: + SMPlayer-ek kudeatzen dituen euskarri fitxategiak: + + + + Select All + Hautatu guztiak + + + + Select None + Hautatu batez + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + SMPlayer-ek kudeatze nahi duzun fitxategi hedapenak egiaztatu. Ezarri sakatzean egiaztatuko fitxategiak SMPlayer-ekin lotuko dira. Euskarri fitxategi bat desmarkatuaz fitxategi lotura berezarriko da. + + + + Select none + Hautatu batez + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Oharra:</b> (berrezartzea ez dabil Windows Vista-pean). + + + + PrefDrives + + + Drives + Kontrolatzaileak + + + + icon + ikonoa + + + + CD device + CD gailua + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Hautatu zure CDROM gailua. VCD eta Audio CD-ak erreproduzitzeko erabiliko da. + + + + DVD device + DVD gailua + + + + Choose your DVD device. It will be used to play DVDs. + Hautatu DVD gailua. DVD-ak ereproduzitzeko erabiliko da. + + + + Select your &CD device: + Hautatu &CD gailua: + + + + Select your &DVD device: + Hautatu &DVD gailua: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer-ek ez du CDROM edo DVD gailurik hautatzen lehenespenez. Beraz CD edo DVD bat erreproduzitu ahal izateko erabili nahi dituzun gailuak ezarri behar dituzu (berdina izan daitezke). + + + + PrefGeneral + + + General + Orokorra + + + + &General + &Orokorra + + + + Paths + Bideak + + + + Media settings + Euskarri ezarpenak + + + + Start videos in fullscreen + Hasi bideoak pantaila-osoan + + + + Disable screensaver + Ezgaitu pantaila-babeslea + + + + Select the mplayer executable + Hautatu mplayer exekutagarria + + + + Executables + Exekutagarriak + + + + All files + Fitxategi guztiak + + + + Select a directory + Hautatu direktorio bat + + + + MPlayer executable + MPlayer exekutagarria + + + + Screenshots folder + Pantaila-argazki karpeta + + + + Video output driver + Bideo irteera kontrolatzailea + + + + Audio output driver + Audio irteera kontrolatzailea + + + + Select the audio output driver. + Hautatu audio irteera kontrolatzailea. + + + + Remember settings + Gogogrratu ezarpenak + + + + Preferred audio language + Hobetsiriko audio hizkuntza + + + + Preferred subtitle language + Hobetsiriko azpititutlu hizkuntza + + + + Software video equalizer + Software bideo ekualizadorea + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Auekra hau hautatu dezakezu zure txartel edo hautatutako bideo kontrolatzaileak ez badu bideo ekualizatzailea onartzen.<br><b>Oharra:</b> aukea hau zenbait bideo irteerakontrolatzailerekin bateraezina izan daiteke. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Aukera hau hautaturik dagoenean bideo guztiak pantaila-oso moduan erreproduzituko dira. + + + + Software volume control + Software bolumen kontrola + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Aukera hau hatutatu soinu txartelarena beharrean software nahaslea erabiltzeko. + + + + Postprocessing quality + Postprodukzio kalitatea + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Postprodukzio dinamiko aldaketak erabilgarri dagoen CPU denbora librearen araberakoak dira. Ezarritako zenbakiak erabiliko den maila altuena. Normalean zenbaki handi bat erabili dezakezu. + + + + Change volume + Aldatu bolumena + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + MArkaturik abdago SMPlayer-ek fitxategio bakoitzeko bolumena gogoratu dezake berriz erreproduzitzea berrezartzeko. Fitxategi berrientzat bolumen lehenetsia erabiliko da. + + + + 0 + 0 + + + + &Change volume on every file + &Aldatu bolumena fitxategi bakoitzean + + + + Select the &MPlayer executable: + Hautatu &MPlayer exekutagarria: + + + + &Folder for storing screenshots: + &Pantaila-argazkiak gordetzeko karpeta: + + + + &Audio: + &Audioa: + + + + &Remember settings for all files (audio track, subtitles...) + &Gogoratu fitxatgi guztien ezarpenak (audio pista, azpitituluak...) + + + + Su&btitles: + Az&pititutluak: + + + + &Quality: + &Kalitatea: + + + + Start videos in &fullscreen + Hasi bideoak &pantaila-osoan + + + + Disable &screensaver + Ezgaitu &pantaila-babeslea + + + + &Default volume: + &Lehenetsiriko bolumena: + + + + Use s&oftware volume control + Erabili s&oftware bidezko bolumen kontrola + + + + Ma&x. Amplification: + Ge&h. anplifikazioa: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS S/PDIF bidez + + + + Direct rendering + Errenderizazio zuzena + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Hautatua badago errenderizaio zuzena (ez dute bideo irteera eta kodek guztiek onatzen)<br><b>ABISUA:</b> OSD/SUB hondatzea eragin dezake! + + + + Double buffering + Buferreratze bikoitza + + + + D&irect rendering + Errender&izazio zuzena + + + + Dou&ble buffering + &Buferreratze bikoitza + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Buferreratze bikoitzak dir-dir arazoak konpontzen ditu memorian bi marko gorde eta bat dekodetzen den bitartean bestea bistaratzen. Ezgaituaz gero OSD-en oker eragin dezake, baina hala ere OSD dir-dira konpontzen du. + + + + &Enable postprocessing by default + Gaitu postprozesatz&ea lehenespen bezala + + + + Volume &normalization by default + Bolumen &normalizazioa lehenespen bezala + + + + Close when finished + Itxi amaitzean + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Aukera hau gaizean leiho nagusia automatikoki itxiko da fitxategia/erreprodukzi-zerrenda amaitzean. + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4(4.0 Ingurunea) + + + + 6 (5.1 Surround) + 6(5.1 Ingurunea) + + + + C&hannels by default: + Le&henetsiriko kanalak: + + + + &Pause when minimized + &Pausatu txikitzean + + + + Pause when minimized + Pausatu txikitzean + + + + Enable postprocessing by default + Gaitu postprozesatzea lehenespen bezala + + + + Max. Amplification + Geh. anplifikazioa + + + + AC3/DTS pass-through S/PDIF + AC3/DTS S/PDIF bidez + + + + Volume normalization by default + Bolumen normalizazioa lehenespen bezala + + + + Maximizes the volume without distorting the sound. + Soinua hondfatu gabe bolumena guztiz igotzen du. + + + + Default volume + Lehenetsiriko bolumena + + + + Sets the initial volume that new files will use. + Fitxategi berriekin erabiliko bolumena ezartzen du. + + + + Channels by default + Lehenetsiriko kanalak + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Ezarri gehienezko anplifikazio maila portzentaia (lehenetsia: 110). 200-eko balio batek bolumena uneko mailaren bikoitzera igo ahal izango duzu. 100-etik beherako balioekin hasierako bolumena (%100 dena) mugatik gora egongo da, eta adibidez OSD ezingo da behar bezala bistarazi. + + + + Uses hardware AC3 passthrough + Erabiltzailearen AC3 hardwarearen bidez + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Erreprodukzio kanal kopuru eskaera. MPlayer-ek deskodetzaileari audioa ezarri bezainbeste kaneltan dekodetzea eskatuko dio. Orduan dekodetzaileak eskaera betetzen saiatuko da. Hau normalea AC3 audioa duten bideoak (DVDak antzera) erreproduzitzean bakarrik da garrantzitsua. Kasu honetan liba52-k dekodetzea egingo du eta audioa eskatutako kanal kopuruan bereiziko du. OHARRA: Aukera hau codec (AC3 bakarrik), iragazkia (inguratzea) eta audio irteera kontrolatzaileak (OSS behintzat) lortzen dute. + + + + Postprocessing will be used by default on new opened files. + Posprozesatzea erabiliko da irekitzen diren fitxategi berriekin. + + + + Audio track + Audio pista + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Fitxategi berriak erreproduzitzean erabiliko den lehenetsiriko audio pista ezartzen du. Pista ez badago, lehenengoa erabiliko da. <br><b>Oharra:</b><i>"hobetsiriko audio hizkuntza"</i> aukera lehenesten da honen aurreran. + + + + Subtitle track + Azpititutlu pista + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Fitxategi berriak erreproduzitzean erabiliko den lehenetsiriko azpitulu pista ezartzen du. Pista ez badago, lehenengoa erabiliko da. <br><b>Oharra:</b><i>"hobetsiriko azpititulu hizkuntza"</i> aukera lehenesten da honen aurreran. + + + + Or choose a track number: + Edo hautatu pista zenbakia: + + + + Audi&o: + Audi&oa: + + + + Preferred language: + Hiobetsiriko hizkuntza: + + + + Preferre&d audio and subtitles + Hobe&tsiriko audio eta azpitituluak + + + + &Subtitle: + A&zpititutluak: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Hemen audio eta azpititulu korronteentzat hobetsiriko hizkuntza zehaztu dezakezu. Azpititulu edo audio korronte anitz dituen euskarri bat aurkitzean, smplayer hobetsiriko hizkuntza erabiltzen saiatuko da.<br>Honek, DVD-ak edo mkv fitxategiak bezala, azpititulu eta audio korronteei buruz informazioa eskeintzen duten euskarriekin funtzionatuko du.<br>Eremu hoek espresio erregularrak onartzen ditu. Adibidez <b>es|esp|spa</b> erabiliaz <i>es</i>, <i>esp</i> edo <i>spa</i>-rekin parekatzen den korrontea erabiliko da. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + Abiadura handiko erre&produkzioa tonua aldatu gabe + + + + High speed playback without altering pitch + Abiadura handiko erreprodukzioa tonua aldatu gabe + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Erreprodukzio abiasura tonua aldatu gabe aldatzeko auekra ematen du. Behintzat MPlyaer dev-SVN-r24924 behar du. + + + + Change volume just before playing + Aldatu bolumena erreproduzitzen hasi aurretik + + + + &Video + &Bideoa + + + + Use s&oftware video equalizer + S&oftware bideo ekualizadorea erabili + + + + A&udio + A&udioa + + + + Volume + Bolumena + + + + Video + Bideoa + + + + Audio + Audioa + + + + Preferred audio and subtitles + + + + + None + Batez + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Teklatu eta sagua + + + + &Keyboard + Te&klatua + + + + icon + ikonoa + + + + &Mouse + &Sagua + + + + Button functions: + Botoi funtzioak: + + + + Media seeking + Euskarri saltoak + + + + Volume control + Bolumen kontrola + + + + Zoom video + Bideo zoom-a + + + + None + Batez + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Hemen edozein laster-tekla aldatu dezakezu. Egiteko klik bikoitza egin edo enter sakatu laster-tekla gelaxka bateta. Aukeran zerrenda gode dezakezu beste jendearekin partekatu edo beste ordenagailu batetan kargatzeko. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Hemen edozein laster-tekla aldatu dezakezu. Egiteko klik bikoitza egin edo idazten hasi laster-tekla gelaxka bateta. Aukeran zerrenda gode dezakezu beste jendearekin partekatu edo beste ordenagailu batetan kargatzeko. + + + + &Left click + E&zker klik + + + + &Double click + Klik &bikoitza + + + + &Wheel function: + &Gurpil funtzioa: + + + + Shortcut editor + Laster-tekla editorea + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Taula honek ekintza arruntenentzat laster-teklak aldatzeko auekra ematen dizu. Enter sakatu edo klik bikoitza egin elementu batetan edo <b>Aldatu laster-marka</b> botoia sakatu <i>Eraldatu laster-marka</i> leihoan. Bi modu daude laster-markak aldatzeko: <b>Kapturatu</b> botoia gaituriok badago ezarri nahi duzun tekla konbinazio berria sakatu (zoritxarrez honek ez du tekla guztiekin funtzionatzen). <b>Kapturatu</b> botoia ezgaiturik badago teklaren izen osoa sar dezakezu. + + + + Left click + Ezker klik + + + + Select the action for left click on the mouse. + Haudatu saguaren ezkerreko botoiaren ekintza. + + + + Double click + Klik bikoitza + + + + Select the action for double click on the mouse. + Hauatu saguaren klik-bikoitz ekintza. + + + + Wheel function + Gurpil funtzioa + + + + Select the action for the mouse wheel. + Hautatu sagu gurpilaren ekintza. + + + + Play + Erreproduzitu + + + + Pause + Pausatu + + + + Stop + Gelditu + + + + Fullscreen + Pantaila-osoa + + + + Compact + Kompaktoa + + + + Screenshot + Pantaila-argazkia + + + + On top + Goian + + + + Mute + Mututu + + + + Frame counter + Marko kontatzailea + + + + Reset zoom + Zooma berrezarri + + + + Exit fullscreen + Utzi pantaila-osoa + + + + Double size + Tamaina bikoitza + + + + Play / Pause + Erreprduzitu / Pausatu + + + + Pause / Frame step + Pasuatu / Marko bat aurrera + + + + Playlist + Erreprodukzio-zerrenda + + + + Preferences + Hobespenak + + + + No function + Funtziorik ez + + + + Change speed + Aldatu abiadura + + + + Normal speed + Abidura arrunta + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - Hurrengo maila + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Interfazea + + + + <Autodetect> + <Autoantzeman> + + + + Default + Lehenetsia + + + + &Interface + &Interfazea + + + + Never + Inoiz + + + + Whenever it's needed + Beharrezkoa denean + + + + Only after loading a new video + Bideo berri bat kargatzean bakarrik + + + + Recent files + Azken fitxategiak + + + + Language + Hizkuntza + + + + Here you can change the language of the application. + Hemen aplikazioaren hizkuntza aldatu dezakezu. + + + + &Short jump + Saltu &laburra + + + + &Medium jump + SAlto &ertaina + + + + &Long jump + Salto &luzea + + + + Mouse &wheel jump + Sagu &gurpil saltoa + + + + &Use only one running instance of SMPlayer + Martxan SMPlayer instalazi bat bakarrik &erabili + + + + Ma&x. items + Ge&hi. elementuak + + + + St&yle: + Est&iloa: + + + + Ico&n set: + Iko&no jokoa: + + + + L&anguage: + &Hizkuntza: + + + + Main window + Leiho nagusia + + + + Auto&resize: + Autmoatikoki &tamianaz aldatu: + + + + R&emember position and size + G&ogoratu kokalekua eta tamaina + + + + Default font: + Lehenetsiriko letra-tipoa: + + + + &Change... + &Aldatu... + + + + &Behaviour of time slider: + Denbora graduatzalearen &portamoldea: + + + + Seek to position while dragging + Joan kokalekura arrastratzean + + + + Seek to position when released + Joan kokalekua askatzean + + + + TextLabel + TestuEtiketa + + + + &Seeking + &Bilatzen + + + + Ins&tances + Ins&tntzia + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Seeking + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Performantzia + + + + &Performance + &Performantzia + + + + Priority + Lehentasuna + + + + Select the priority for the MPlayer process. + Hautatu SMPlayer prozesuaren lehentasuna. + + + + realtime + Denbora-errealean + + + + high + altua + + + + abovenormal + arruntetik gora + + + + normal + arrunta + + + + belownormal + arruntetik behera + + + + idle + gelditua + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Cache bat ezartzeak euskarri geldoen performatzia hobetuko du + + + + Allow frame drop + Onartu marko baztertzea + + + + Synchronization + Sinkronizazioa + + + + Audio/video auto synchronization + Audio/bideo auto-sinkronizazioa + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Mplayer-en prozusu lehnetasuna ezarri Windowspean aurre-ezarrita lehentasun eskuragrrien artean.<br><b>OHARRA:</b> DEnbora-errealeko lehentasuna erabiltzeak sistema geldotzea egin dezake. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Zenbait markoren bistaratzea baztertu sistema geldoetan A/B sinkronizazioa mantentzeko. + + + + Allow hard frame drop + Onartu marko baztertze gogorra + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + MArko baztertze handiagoa (dekodetzea apurtzen). Irudi distotsioa egin dezake! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Gradualki dohitu A/B sinkronia audio atzerapenean oinarriturik. + + + + Priorit&y: + Le&hentasuna: + + + + &Allow frame drop + &onartu marko baztertzea + + + + Allow &hard frame drop (can lead to image distortion) + Onartu marko baztertze &handia (irudi distortsioa sor dezake) + + + + Audio/&video auto synchronization + Audio/&Bideo auto-sinkronizazioa + + + + Fact&or: + Fakt&orea: + + + + &Fast audio track switching + Audio pista aldaketa az&karra + + + + Fast &seek to chapters in dvds + Kapituluetara &joate azkarra dvd-etan + + + + Fast audio track switching + Audio pista aldaketa azkarra + + + + Fast seek to chapters in dvds + Kapituluetara salto azkarra dvd-etan + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Hautatua dagoenean kapituluetara salto egiteko metodo azkarrena erabilzen saiatuko da, baina ez du disko guztiekin funtzionatuko. + + + + Skip loop filter + Saltatu begizta iragazkia + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + Fitxategien cache-a + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Aukera hone fitxategiak aurrekatxeatzean erabiliko den memoria kopurua ezarten du (kBytetan). + + + + Cache for streams + Kooronte katxea + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Aukera hone URLak aurrekatxeatzeane rbailiko den memoria kopurua ezarten du (kBytetan). + + + + Cache for DVDs + DVD katxea + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Aukera honek DVD bat aurre-katxeazean erabiliko den memoria kopurua (kBytetan) ezartzen du.<br><b>Oharra:</b> saltoak agian ez dute funtzionatuko (kapitulu aldaketa barne) DVDekin katxea erabiltzean. + + + + &Cache + &Katxea + + + + Cache for &DVDs: + &DVDen katxea: + + + + Cache for &local files: + Fitxategi &lokalen katxea: + + + + Cache for &streams: + &Korronteen katxea: + + + + Enabled + Gaiturik + + + + Skip (always) + Salto egin (beti) + + + + Skip only on HD videos + Salto egin HD bideoetan bakarrik + + + + Loop &filter + Begiazta i&ragazkia + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + Auekrako balioak: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Gaiturik</b>: adabaki iragazkia ez da baztertuko + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Baztertu (beti)</b>: begizta iragazkia baztertu egingo da bideo erresoluzioa begiratu gabe + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Baztertu HD bideoetan bakarrik</b>: begizta iragazkiak %1 edo handiagoak diren bideoetan bakarrik baztertuko da. + + + + Cache + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Erreprodukzio-zerrenda + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + Erre&produkzio-zerrenda + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Azpitituluak + + + + Choose a ttf file + Hautatu ttf fitxategi bat + + + + Truetype Fonts + Truetype letra-tipoak + + + + &Subtitles + A&zpitituluak + + + + Autoload + Autokargatu + + + + Same name as movie + Filmaren izen berdina + + + + All subs containing movie name + Azpititulu guztiek filmaren izena dute + + + + All subs in directory + Direktorioko azpititulu guztiak + + + + Position + Kokalekua + + + + 0 + 0 + + + + Top + Goian + + + + Bottom + Behean + + + + Font + Letra-tipoa + + + + Select the font which will be used for subtitles (and OSD): + Hautatu azpitituluetan (eta OSD-en) erabiliko den letra-tipoa: + + + + Size + Tamaina + + + + No autoscale + Ez autoeskalatu + + + + Proportional to movie height + Filma altueraren erlazioan + + + + Proportional to movie width + Filma zabaleraren erlazioan + + + + Proportional to movie diagonal + Filma diagonalaren erlazioan + + + + Subtitle position + Azpititutlu kokapena + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Aukera honek azpitituluek bideo leihoan artzen duten kokapena ezatzem da. <i>100</i>-ek behean san nahi du eta <i>0</i> erabiltzeak goikaldean. + + + + Au&toload subtitles files (*.srt, *.sub...): + Au&tomatikoki kargatu azpititulu fitxategiak (*,srt, *.sub...): + + + + S&elect first available subtitle + Hautatu l&ehenengo azpititulu erabilgarria + + + + &Default subtitle encoding: + Lehenetsiriko azpititulu ko&deketa: + + + + Default &position of the subtitles on screen + Azpitituluen &pantailako lehenetsiriko kokapena + + + + &Include subtitles on screenshots + &Txertatu azpitituluak pantaila-argazkietan + + + + &TTF font: + &TTF letra-tipoa: + + + + S&ystem font: + S&istema letra-tipoa: + + + + A&utoscale: + A&utoeskalatu: + + + + Select first available subtitle + + + + + Default subtitle encoding + + + + + Include subtitles on screenshots + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + Behean + + + + Middle + vertical alignment + + + + + Top + vertical alignment + Goian + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Laguntza + + + + OK + Ados + + + + Cancel + Utzi + + + + Apply + Ezarri + + + + Help + Laguntza + + + + SMPlayer - Preferences + SMPlayer - Hobespenak + + + + QObject + + + will show this message and then will exit. + mezu hau erakutsi eta irten egingo da. + + + + the main window will be closed when the file/playlist finishes. + leiho nagusia itxi egingo da fitxategia/erreprodukzio zerrenda amaitzean. + + + + This is SMPlayer v. %1 running on %2 + SMPlayer %1 bertsioa %2-n abiarazia + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + martxan dagoen beste instantzi batetara konexio bat sortu eta ezarritako ekintza bidali. Adibidez: -send-action pause erabiltzean beste aukera guztiak (batenbat balego) baztertu eta aplikazioa itxi egingo da. 0 itzultzen du arrkasta kasuan edo1 errore kasuan. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + eknitza_zerrenda zuriunez bereiziriko ekintza zerrenda bat da. Eknitzak fitxategia kargatu ondoren (batenbat balego) exekutatuko dira zuk sartutako orden berdinean. Ekintza hautagarrietan egia ala gezurra parametro gisa bidali dezakezu. Adibidez_ -actions "fullscreen compact true". Gakotxak beharrezkoak dira ekintza bat baino gehiago bidaltzeko. + + + + media + euskarria + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + Beste instantzia bat abiarazirik badago euskarri instantzia horren errepodukzio-zerrendan gehituko da. Beste instantziarik ez badago, aukera hau baztertu egingo da eta istantzia berri batetan irekiko dira fitxategiak. + + + + the main window won't be closed when the file/playlist finishes. + leiho nagusia ez da itxiko fitxategia/erreprodukzio-zerrenda amaitzean. + + + + the video will be played in fullscreen mode. + bideoa pantaila-oso moduan erreproduzituko da. + + + + the video will be played in window mode. + bideoa leiho moduan erreproduzituko da. + + + + Enqueue in SMPlayer + SMPlayer hilaran ipini + + + + opens the mini gui instead of the default one. + Interfaze txikia irekitzen du lehenetsirikoaren ordez. + + + + Restores the old associations and cleans up the registry. + Fitxategi asoziazio zaharrak berrrezarri eta registroa garbitu. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'euskarria' SMPlayer-ek ireki dezakeen edo fitxategi mota da. Fitxategi lokal bat izan daiteke, DVD bat (adib dvd://1), internet korronte bat (adib. mms://...) edo erreprodukzio-zerrenda lokal bat m2u edo pls formatuan. -paylist zerrenda erabiltzean SMPlayer-ek -playlist aukera MPlayer-eri pasatzen dio hark kudea dezan erreprodukzio-zerrenda SMPlayerek ordez. + + + + Usage: + Erabilea: + + + + directory + direktorioa + + + + action_name + ekintza_izena + + + + action_list + ekintza_zerrenda + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + %1 minute(s) + + + + + + + %1 and %2 + %1 eta %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + ikonoa + + + + label + etiketa + + + + ShortcutGetter + + + Modify shortcut + Eraldatu laster-tekla + + + + Clear + Garbitu + + + + Press the key combination you want to assign + Sakatu ezarri nahi duzun konbinazioa + + + + Capture + Kaptura + + + + Capture keystrokes + Kapturatu tekla-sakatzea + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + Hautatu guztiak + + + + Select None + Hautatu batez + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + Automatikoa + + + + Yes + Bai + + + + No + Ez + + + + VideoEqualizer + + + Contrast + Kontrastea + + + + Brightness + Disdira + + + + Hue + �bardura + + + + Saturation + Saturazioa + + + + Gamma + Gamma + + + + &Reset + Be&rezarri + + + + &Set as default values + &Lehenetsiriko balioak bezala ezarri + + + + Use the current values as default values for new videos. + Erabili uneko balioak lehenetsiriko balioak bezala bideo berrientzat. + + + + Set all controls to zero. + Ezarri kontrol guztiak zerora. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + Utzi + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Errorea fitxategia gordetzerakoan + + + + The file couldn't be saved + Fitxategia ezin da gorde + + + + Error + Errorea + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Lehenetsia + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Bolumena + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_fi.ts b/plugins/smplayer_plugin/translations/smplayer_fi.ts new file mode 100644 index 000000000..4f5e182c5 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_fi.ts @@ -0,0 +1,7209 @@ + + + + About + + + Version: %1 + Versio: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + + + The following people have contributed with translations: + Seuraavat henkilöt ovat auttaneet käännöksillään: + + + + German + Saksa + + + + Slovak + Slovakki + + + + Italian + Italia + + + + French + Ranska + + + + %1, %2 and %3 + %1, %2 ja %3 + + + + Simplified-Chinese + Yksinkertaistettu kiina + + + + Russian + Venäjä + + + + %1 and %2 + %1 ja %2 + + + + Hungarian + Unkari + + + + Polish + Puola + + + + Japanese + Japani + + + + Dutch + Hollanti + + + + Ukrainian + Ukraina + + + + Portuguese - Brazil + Brasiljanportugali + + + + Georgian + Georgia + + + + Czech + Tsekki + + + + Bulgarian + Bulgaria + + + + Turkish + Turkki + + + + Swedish + Ruotsi + + + + Serbian + Serbia + + + + Traditional Chinese + Perinteinen kiina + + + + Romanian + Romania + + + + Portuguese - Portugal + Portugali + + + + Greek + Kreikka + + + + Finnish + Suomi + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Tietoa SMPlayeristä + + + + &Info + &Tietoa + + + + icon + kuvake + + + + &Contributions + &Avustukset + + + + &Translators + &Kääntäjät + + + + &License + &Lisenssi + + + + Visit our web for updates: + Vieraile sivuillamme hakeaksesi päivityksiä: + + + + Get help in our forum: + Hae apua keskustelupalstaltamme: + + + + You can support SMPlayer by making a donation. + Voit tukea SMPlayeriä lahjoittamalla. + + + + More info + Lisää tietoa + + + + Korean + + + + + Macedonian + + + + + Basque + + + + + Using MPlayer %1 + + + + + Catalan + + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + Arabialainen + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Nimi + + + + Description + Kuvaus + + + + Shortcut + Oikotie + + + + &Save + &Tallenna + + + + &Load + &Lataa + + + + Key files + Avain tiedostot + + + + Choose a filename + Valitse tiedoston nimi + + + + Confirm overwrite? + Hyväksy ylikirjoitus? + + + + The file %1 already exists. +Do you want to overwrite? + Tiedosto %1 on jo olemassa +Haluatko ylikirjoittaa sen? + + + + Choose a file + Valitse tiedosto + + + + Error + Virhe + + + + The file couldn't be saved + Tiedostoa ei pystytty tallentamaan + + + + The file couldn't be loaded + Tiedostoa ei pystytty lataamaan + + + + &Change shortcut... + &Vaihda oikotie... + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + &Palauta + + + + &Set as default values + + + + + Use the current values as default values for new videos. + + + + + Set all controls to zero. + Aseta kaikki kontrollit nollille. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayerin loki + + + + SMPlayer - smplayer log + SMPlayer - smplayerin loki + + + + &Open + &Avaa + + + + &Play + &Toista + + + + &Video + &Kuva + + + + &Audio + &Ääni + + + + &Subtitles + &Tekstitys + + + + &Browse + &Selaa + + + + Op&tions + As&etukset + + + + &Help + &Apua + + + + &File... + &Tiedosto... + + + + D&irectory... + H&akemisto... + + + + &Playlist... + &Soittolista... + + + + &DVD from drive + &DVD asemasta + + + + D&VD from folder... + D&VD kansiosta... + + + + &URL... + &URL... + + + + &Clear + &Tyhjennä + + + + &Recent files + &Viimeaikaiset tiedostot + + + + P&lay + T&oista + + + + &Pause + &Tauko + + + + &Stop + &Pysäytä + + + + &Frame step + + + + + &Normal speed + &Normaali nopeus + + + + &Halve speed + &Puolikas nopeus + + + + &Double speed + &Kaksinkertainen nopeus + + + + Speed &-10% + Nopeus &-10% + + + + Speed &+10% + Nopeus &+10% + + + + Sp&eed + No&peus + + + + &Repeat + &Toisto + + + + &Fullscreen + &Kokoruutu + + + + &Compact mode + &Kompakti tila + + + + Si&ze + Ko&ko + + + + 4:3 &Letterbox + 4:3 &Postilaatikko + + + + 16:9 L&etterbox + 16:9 P&ostilaatikko + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 -&> 16:9 + + + + &Aspect ratio + &Kuvasuhde + + + + &None + &Ei mitään + + + + &Lowpass5 + + + + + Linear &Blend + + + + + &Deinterlace + + + + + &Postprocessing + + + + + &Autodetect phase + + + + + &Deblock + + + + + De&ring + + + + + Add n&oise + Lisää m&elua + + + + F&ilters + S&uodattimet + + + + &Equalizer + &Taajuuskorjain + + + + &Screenshot + &Kuvankaappaus + + + + S&tay on top + P&ysy päällinmäisenä + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Suodattimet + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Kanavat + + + + &Left channel + &Vasen kanava + + + + &Right channel + &Oikea kanava + + + + &Stereo mode + &Stereo tila + + + + &Mute + &Hiljennä + + + + Volume &- + Volyymi &- + + + + Volume &+ + Volyymi &+ + + + + &Delay - + &Hyppää taaksepäin + + + + D&elay + + H&yppää eteenpäin + + + + &Select + &Valitse + + + + &Load... + &Lataa... + + + + Delay &- + Hyppää &taaksepäin + + + + Delay &+ + Hyppää &eteenpäin + + + + &Up + &Ylös + + + + &Down + &Alas + + + + &Title + &Otsikko + + + + &Chapter + &Kappale + + + + &Angle + &Kuvakulma + + + + &Playlist + &Soittolista + + + + &Show frame counter + &Näytä ruutujen laskija + + + + &Disabled + &Ei käytössä + + + + &Seek bar + &Sijainti + + + + &Time + &Aika + + + + Time + T&otal time + Aika + K&okonais aika + + + + &OSD + &OSD + + + + &View logs + &Selaa lokeja + + + + P&references + A&setukset + + + + About &Qt + Tietoa &Qt:stä + + + + About &SMPlayer + Tietoa &SMPlayerstä + + + + <empty> + <tyhjä> + + + + Video + Kuva + + + + Audio + Ääni + + + + Playlists + Soittolistat + + + + All files + Kaikki tiedostot + + + + Choose a file + Valitse tiedosto + + + + SMPlayer - Information + SMPlayer - Tietoa + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD asemia ei ole vielä asetettu. +Asetus ikkuna näytetäään, että voit tehdä sen. + + + + Choose a directory + Valitse kansio + + + + Subtitles + Tekstitykset + + + + About Qt + Tietoa Qt:stä + + + + Playing %1 + Toistaa %1 + + + + Pause + Tauko + + + + Stop + Pysäytä + + + + Play / Pause + Toisto / Tauko + + + + Pause / Frame step + + + + + U&nload + P&oista käytöstä + + + + V&CD + V&CD + + + + C&lose + S&ulje + + + + View &info and properties... + Katso t&ietoja... + + + + Zoom &- + Zoomaus &- + + + + Zoom &+ + Zoomaus &+ + + + + &Reset + &Palauta + + + + Move &left + Siirrä &vasemmalle + + + + Move &right + Siirrä &oikealle + + + + Move &up + Siirrä &ylös + + + + Move &down + Siirrä &alas + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Edellinen rivi tekstityksessä + + + + N&ext line in subtitles + S&euraava rivi tekstityksessä + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Vähennä volyymiä (2) + + + + Inc volume (2) + Kasvata volyymiä (2) + + + + Exit fullscreen + Poistu kokoruudusta + + + + OSD - Next level + OSD - Seuraava taso + + + + Dec contrast + Vähennä kontrastia + + + + Inc contrast + Kasvata kontrastia + + + + Dec brightness + Vähennä kirkkautta + + + + Inc brightness + Kasvata kirkkautta + + + + Dec hue + Värisävy - + + + + Inc hue + Värisävy + + + + + Dec saturation + Vähennä kyllästyneisyyttä + + + + Dec gamma + Vähennä gammaa + + + + Next audio + + + + + Next subtitle + Seuraava tekstitys + + + + Next chapter + Seuraava kappale + + + + Previous chapter + Edellinen kappale + + + + Inc saturation + Kasvata kyllästyneisyyttä + + + + Inc gamma + Kasvata gammaa + + + + &Load external file... + &Lataa ulkopuolinen tiedosto... + + + + &Kerndeint + + + + + &Yadif (normal) + &Yadif (normaali) + + + + Y&adif (double framerate) + Y&adif (kaksinkertainen kehysnopeus) + + + + &Next + &Seuraava + + + + Pre&vious + Ede&llinen + + + + Volume &normalization + Volyymin &normalisointi + + + + &Audio CD + &Ääni CD + + + + Denoise nor&mal + + + + + Denoise &soft + + + + + Denoise o&ff + + + + + Use SSA/&ASS library + Käytä SSA/&ASS kirjastoa + + + + Flip i&mage + Käännä k&uvaa + + + + &Toggle double size + + + + + S&ize - + K&oko - + + + + Si&ze + + Ko&ko + + + + + Add &black borders + Lisää &mustat reunat + + + + Soft&ware scaling + + + + + &FAQ + &UKK + + + + Visualize &motion vectors + + + + + &Command line options + + + + + SMPlayer command line options + + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &Kappale + + + + &Track + audio + &Kappale + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer on viellä käynnissä + + + + S&how icon in system tray + N&äytä ikoni ilmoitusalueella + + + + &Hide + &Piilota + + + + &Restore + &Palauta + + + + &Quit + &Poistu + + + + Playlist + Soittolista + + + + Core + + + Brightness: %1 + Kirkkaus: %1 + + + + Contrast: %1 + Kontrasti: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Sävy: %1 + + + + Saturation: %1 + Kyllästyneisyys: %1 + + + + Volume: %1 + Volyymi: %1 + + + + Zoom: %1 + Zoomaus: %1 + + + + Font scale: %1 + + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Tervetuloa SMPlayeriin + + + + Audio + Ääni + + + + Subtitle + Tekstitys + + + + &Main toolbar + &Päätyökalupalkki + + + + &Language toolbar + &Kielityökalupalkki + + + + &Toolbars + &Työkalupalkit + + + + EqSlider + + + icon + kuvake + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + kuvake + + + + Error + Virhe + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Tiedoston tiedot + + + + &Information + &Tietoja + + + + &Demuxer + &Demukseri + + + + &Select the demuxer that will be used for this file: + &Valitse demukseri mitä käytetään tälle tiedostolle: + + + + &Reset + &Palauta + + + + &Video codec + &Kuva kodekki + + + + &Select the video codec: + &Valitse kuva kodekki: + + + + A&udio codec + Ä&äni kodekki + + + + &Select the audio codec: + &Valitse ääni kodekki: + + + + &MPlayer options + &MPlayerin asetukset + + + + Additional Options for MPlayer + Lisäasetukset MPlayerille + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Täällä voit lisätä ylimääräisiä valintoja MPlayeriin. +Erota ne välilyönnillä. +Esimerkki: -flip -nosound + + + + &Options: + &Asetukset: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Voit myös lisätä ylimääräisiä kuvan suotimia. +Erota ne ",":llä. Älä käytä välilyöntiä! +Esimerkki: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + K&uvan suodattimet: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Ja viimeiseksi äänen suotimet. Sama sääntö kuin kuvan suotimissa. +Esimerkki: resample=44100:0:0,volnorm + + + + Audio &filters: + Äänen &suodattimet: + + + + OK + OK + + + + Cancel + Hylkää + + + + Apply + Hyväksy + + + + FindSubtitlesWindow + + + Language + Kieli + + + + Name + Nimi + + + + Format + Formaatti + + + + Files + + + + + Date + Päivämäärä + + + + Uploaded by + + + + + All + + + + + Close + Sulje + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Virhe + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Virhe tallennettaessa tiedostoa + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Yleiset + + + + Size + Koko + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + + + + + Length + Pituus + + + + Demuxer + Demukseri + + + + Name + Nimi + + + + Artist + Artisti + + + + Author + Tekijä + + + + Album + Albumi + + + + Genre + Genre + + + + Date + Päivämäärä + + + + Track + Kappale + + + + Copyright + Tekijänoikeudet + + + + Comment + Kommentti + + + + Software + Ohjelmisto + + + + Clip info + Tietoja raidasta + + + + Video + Kuva + + + + Resolution + Resoluutio + + + + Aspect ratio + Kuvasuhde + + + + Format + Formaatti + + + + Bitrate + Bittinopeus + + + + %1 kbps + %1 kbps + + + + Frames per second + Ruutuja per sekuntti + + + + Selected codec + Valittu kodekki + + + + Initial Audio Stream + + + + + Rate + + + + + %1 Hz + %1 Hz + + + + Channels + Kanavat + + + + Audio Streams + Ääni virrat + + + + Language + Kieli + + + + empty + tyhjä + + + + Subtitles + Tekstitykset + + + + Type + Tyyppi + + + + ID + Info for translators: this is a identification code + + + + + # + Info for translators: this is a abbreviation for number + + + + + Stream title + Verkkolähetyksen otsikko + + + + Stream URL + Verkkolähetyksen osoite + + + + File + Tiedosto + + + + InputDVDDirectory + + + Choose a directory + Valitse kansio + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Toisto DVD tiedostosta + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Pystyt toistamaan dvdn kiintolevyltäsi. Valitse ainoastaan kansio joka sisältää VIDEO_TS ja AUDIO_TS hakemistot. + + + + Choose a directory... + Valitse kansio... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Syötä URL + + + + &URL: + &URL: + + + + It's a &playlist + Se on &soittolista + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Jos tämä vaihtoehto on valittu, osoitetta käsitellään soittolistana: se aukaistaan tekstinä ja siitä soitetaan osoitteet mitkä se sisältää. + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + Arabialainen + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + Bulgaria + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + Tsekki + + + + Welsh + + + + + Danish + + + + + German + Saksa + + + + Greek + Kreikka + + + + English + Englanti + + + + Esperanto + + + + + Spanish + Espanja + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + Suomi + + + + Faroese + + + + + French + Ranska + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + Unkari + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + Italia + + + + Inuktitut + + + + + Japanese + Japani + + + + Javanese + + + + + Georgian + Georgia + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + Hollanti + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + Puola + + + + Portuguese + + + + + Quechua + + + + + Romanian + Romania + + + + Russian + Venäjä + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + Slovakki + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + Serbia + + + + Sundanese + + + + + Swedish + Ruotsi + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Turkki + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + Ukraina + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + Brasiljanportugali + + + + Portuguese - Portugal + Portugali + + + + Simplified-Chinese + Yksinkertaistettu kiina + + + + Traditional Chinese + Perinteinen kiina + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Länsieurooppalainen + + + + Western European Languages with Euro + Länsieurooppalainen euroilla + + + + Slavic/Central European Languages + Slaavilainen/Keskieurooppalainen + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, galicialainen, maltalainen, turkkilainen + + + + Old Baltic charset + + + + + Cyrillic + Kyrillinen + + + + Modern Greek + Moderni kreikka + + + + Baltic + Balttilainen + + + + Celtic + Kelttiläinen + + + + Hebrew charsets + Heprea + + + + Ukrainian, Belarusian + Ukraina, valkovenäjä + + + + Simplified Chinese charset + Yksinkertaistettu kiina + + + + Traditional Chinese charset + Perinteinen kiina + + + + Japanese charsets + Japani + + + + Korean charset + Korea + + + + Thai charset + Thai + + + + Cyrillic Windows + Kyrillinen Windows + + + + Slavic/Central European Windows + Slaavilainen/Keskieurooppalainen Windows + + + + Arabic Windows + Arabialainen Windows + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Valitse nimi tallennettavalle tiedostolle + + + + Confirm overwrite? + Hyväksy ylikirjoitus? + + + + The file already exists. +Do you want to overwrite? + Tiedosto on jo olemassa. +Haluatko ylikirjoittaa sen? + + + + Error saving file + Virhe tallennettaessa tiedostoa + + + + The log couldn't be saved + Lokia ei pystytty tallentamaan + + + + Logs + Lokit + + + + LogWindowBase + + + Log Window + Loki ikkuna + + + + Save + Tallenna + + + + Copy to clipboard + Kopio leikepöydälle + + + + &Close + &Sulje + + + + Close + Sulje + + + + MiniGui + + + Control bar + Kontrolli palkki + + + + MpcGui + + + Control bar + Kontrolli palkki + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nimi + + + + Length + Pituus + + + + &Play + &Toista + + + + &Edit + &Muokkaa + + + + Playlists + Soittolistat + + + + Choose a file + Valitse tiedosto + + + + Choose a filename + Valitse tiedoston nimi + + + + Confirm overwrite? + Hyväksy ylikirjoitus? + + + + The file %1 already exists. +Do you want to overwrite? + Tiedosto %1 on jo olemassaHaluatko ylikirjoittaa sen? + + + + All files + Kaikki tiedostot + + + + Select one or more files to open + Valitse yksi tai useampi tiedostoa avattavaksi + + + + Choose a directory + Valitse kansio + + + + Edit name + Muokkaa nimeä + + + + Type the name that will be displayed in the playlist for this file: + Valitse nimi joka näkyy soittolistalla tälle tiedostolle: + + + + &Load + &Lataa + + + + &Save + &Tallenna + + + + &Next + &Seuraava + + + + Pre&vious + Ede&llinen + + + + Move &up + Siirrä &ylös + + + + Move &down + Siirrä &alas + + + + &Repeat + &Toisto + + + + S&huffle + S&atunnainjärjestys + + + + Add &current file + Lisää &nykyinen tiedosto + + + + Add &file(s) + Lisää &tiedosto(t) + + + + Add &directory + Lisää &kansio + + + + Remove &selected + Poista &valitut + + + + Remove &all + Poista &kaikki + + + + SMPlayer - Playlist + SMPlayer - Soittolista + + + + Add... + Lisää... + + + + Remove... + Poista... + + + + Playlist modified + Soittolistaa muokattu + + + + There are unsaved changes, do you want to save the playlist? + Täällä on tallentamattomia muutoksia, haluatko tallentaa soittolistan? + + + + Preferences + Asetukset + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + Kehittyneet + + + + Auto + Auto + + + + &Advanced + &Kehittyneet + + + + icon + kuvake + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Täällä voit lisätä ylimääräisiä valintoja MPlayeriin.Erota ne välilyönnillä.Esimerkki: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Voit myös lisätä ylimääräisiä kuvan suotimia.Erota ne ",":llä. Älä käytä välilyöntiä!Esimerkki: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Ja viimeiseksi äänen suotimet. Sama sääntö kuin kuvan suotimissa.Esimerkki: resample=44100:0:0,volnorm + + + + Log MPlayer output + Kirjoita lokiin MPlayerin tuloste + + + + Log SMPlayer output + Kirjoita lokiin SMPlayerin tuloste + + + + This option is mainly intended for debugging the application. + Tämä valinta on tarkoitettu pääasiassa vianjäljitykseen. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + + + + + Filter for SMPlayer logs + Suodatin SMPlayerin lokeille + + + + &Monitor aspect: + + + + + &Run MPlayer in its own window + &Aja MPlayer omassa ikkunassa + + + + &Options: + &Asetukset: + + + + V&ideo filters: + K&uvan suodattimet: + + + + Audio &filters: + Äänen &suodattimet: + + + + &Colorkey: + &Värikoodi: + + + + Log &SMPlayer output + Kirjoita lokiin &SMPlayerin tuloste + + + + &Filter for SMPlayer logs: + &Suodin SMPlayerin lokeille: + + + + C&hange... + M&uuta... + + + + Logs + Lokit + + + + Log MPlayer &output + Kirjoita lokiin MPlayerin &tuloste + + + + Options for MP&layer + Asetukset MP&layerille + + + + Autosave MPlayer log + Tallenna automaattisesti MPlayerin loki + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + Tallenna automaattisesti MPlayerin loki nimellä + + + + Enter here the path and filename that will be used to save the MPlayer log. + Kirjoita tähän polku ja tiedostonnimi mitä käytetään MPlayerin lokin tallentamiseen. + + + + A&utosave MPlayer log to file + T&allenna automaattisesti MPlayerin loki tiedostoon + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Tyyppi + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Varoitus + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + Tiedostotyypit + + + + Select all + Valitse kaikki + + + + Check all file types in the list + Valitse kaikki tiedostotyypit listasta + + + + Uncheck all file types in the list + Poista kaikki valinnat listalla + + + + List of file types + Lista tiedostotyypeistä + + + + File types + Tiedostotyypit + + + + Media files handled by SMPlayer: + + + + + Select All + Valitse kaikki + + + + Select None + Älä valitse mitään + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + Select none + Älä valitse mitään + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + Asemat + + + + icon + kuvake + + + + CD device + CD asema + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Valitse CDROM asemasi. Sitä käytetään VCD:n ja ääni CD:n toistamiseen. + + + + DVD device + DVD asema + + + + Choose your DVD device. It will be used to play DVDs. + Valitse DVD asemasi. Sitä käytetään DVD:n toistamiseen. + + + + Select your &CD device: + Valitse &CD asemasi: + + + + Select your &DVD device: + Valistse &DVD asemasi: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + Yleiset + + + + &General + &Yleiset + + + + Paths + Polut + + + + Media settings + + + + + Video + Kuva + + + + Start videos in fullscreen + Toista videot kokoruudussa + + + + Disable screensaver + + + + + Audio + Ääni + + + + Select the mplayer executable + + + + + Executables + + + + + All files + Kaikki tiedostot + + + + Select a directory + Valitse kansio + + + + MPlayer executable + + + + + Screenshots folder + Kansio kuvankaappauksille + + + + Video output driver + + + + + Audio output driver + + + + + Select the audio output driver. + + + + + Remember settings + + + + + Preferred audio language + + + + + Preferred subtitle language + + + + + Software video equalizer + + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + + + + + If this option is checked, all videos will start to play in fullscreen mode. + + + + + Software volume control + + + + + Check this option to use the software mixer, instead of using the sound card mixer. + + + + + Postprocessing quality + + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + + + + + Change volume + Muuta volyymiä + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + 0 + + + + + &Change volume on every file + &Muuta volyymi jokaiselle tiedostolle + + + + Select the &MPlayer executable: + + + + + &Folder for storing screenshots: + &Kansio minne kuvankaappaukset tallennetaan: + + + + &Audio: + &Ääni: + + + + &Remember settings for all files (audio track, subtitles...) + + + + + Su&btitles: + Te&kstitykset: + + + + &Quality: + &Laatu: + + + + Start videos in &fullscreen + Toista videot &kokoruudussa + + + + Disable &screensaver + + + + + &Default volume: + &Oletus volyymi: + + + + Use s&oftware volume control + + + + + Ma&x. Amplification: + + + + + &AC3/DTS pass-through S/PDIF + + + + + Direct rendering + + + + + Double buffering + + + + + D&irect rendering + + + + + Dou&ble buffering + + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + &Enable postprocessing by default + + + + + Volume &normalization by default + + + + + Close when finished + Sulje kun valmis + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + + + + + 4 (4.0 Surround) + + + + + 6 (5.1 Surround) + + + + + C&hannels by default: + + + + + &Pause when minimized + &Tauko kun pienennetty + + + + Pause when minimized + + + + + Enable postprocessing by default + + + + + Max. Amplification + + + + + AC3/DTS pass-through S/PDIF + + + + + Volume normalization by default + + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + + + + + Audi&o: + Ään&i: + + + + Preferred language: + + + + + Preferre&d audio and subtitles + + + + + &Subtitle: + &Tekstitys: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + &Kuva + + + + Use s&oftware video equalizer + + + + + A&udio + Ä&äni + + + + Volume + Volyymi + + + + Preferred audio and subtitles + + + + + None + Ei mitään + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Näppäimistö ja hiiri + + + + &Keyboard + &Näppäimistö + + + + icon + kuvake + + + + &Mouse + &Hiiri + + + + Button functions: + Painikkeiden funktiot: + + + + Media seeking + + + + + Volume control + + + + + Zoom video + Zoomaa videota + + + + None + Ei mitään + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + &Vasen napsautus + + + + &Double click + &Kaksois napsautus + + + + &Wheel function: + + + + + Shortcut editor + + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + Vasen napsautus + + + + Select the action for left click on the mouse. + + + + + Double click + Kaksois napsautus + + + + Select the action for double click on the mouse. + + + + + Wheel function + + + + + Select the action for the mouse wheel. + + + + + Play + Toista + + + + Pause + Tauko + + + + Stop + Pysäytä + + + + Fullscreen + Kokoruutu + + + + Compact + Kompakti + + + + Screenshot + Kuvankaappaus + + + + On top + Päällä + + + + Mute + Hiljennä + + + + Frame counter + Ruutujen laskija + + + + Reset zoom + Palauta zoom + + + + Exit fullscreen + Poistu kokoruudusta + + + + Double size + Kaksinkertainen koko + + + + Play / Pause + Toisto / Tauko + + + + Pause / Frame step + + + + + Playlist + Soittolista + + + + Preferences + Asetukset + + + + No function + Ei toimintoa + + + + Change speed + Muuta nopeutta + + + + Normal speed + Normaali nopeus + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - Seuraava taso + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Käyttöliittymä + + + + <Autodetect> + <Automaattinen tunnistus> + + + + Default + Oletus + + + + &Interface + &Käyttöliittymä + + + + Never + Ei ikinä + + + + Whenever it's needed + + + + + Only after loading a new video + + + + + Recent files + Viimeaikaiset tiedostot + + + + Language + Kieli + + + + Here you can change the language of the application. + + + + + &Short jump + &Lyhyt hyppy + + + + &Medium jump + &Normaali hyppy + + + + &Long jump + &Pitkä hyppy + + + + Mouse &wheel jump + + + + + &Use only one running instance of SMPlayer + + + + + Ma&x. items + + + + + St&yle: + Ty&yli: + + + + Ico&n set: + Kuvak&e tyyli: + + + + L&anguage: + K&ieli: + + + + Main window + Pää ikkuna + + + + Auto&resize: + + + + + R&emember position and size + + + + + Default font: + Oletus kirjasin: + + + + &Change... + &Muuta... + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + + + + + &Seeking + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Seeking + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Suorituskyky + + + + &Performance + &Suorituskyky + + + + Priority + Tärkeys + + + + Select the priority for the MPlayer process. + + + + + realtime + + + + + high + korkea + + + + abovenormal + yli normaalin + + + + normal + normaali + + + + belownormal + alle normaalin + + + + idle + + + + + KB + Kt + + + + Setting a cache may improve performance on slow media + + + + + Allow frame drop + + + + + Synchronization + + + + + Audio/video auto synchronization + + + + + Skip displaying some frames to maintain A/V sync on slow systems. + + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + + + + + Gradually adjusts the A/V sync based on audio delay measurements. + + + + + Priorit&y: + Tärke&ys: + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + + + + + Fact&or: + + + + + &Fast audio track switching + + + + + Fast &seek to chapters in dvds + + + + + Fast audio track switching + + + + + Fast seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + &Välimuisti + + + + Cache for &DVDs: + Välimuisti &DVD:lle: + + + + Cache for &local files: + Välimuisti &paikallisille tiedostoille: + + + + Cache for &streams: + Välimuisti &verkkolähetyksille: + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Soittolista + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Soittolista + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Tekstitykset + + + + Choose a ttf file + Valitse ttf tiedosto + + + + Truetype Fonts + Truetype kirjaisimet + + + + &Subtitles + &Tekstitykset + + + + Autoload + Automaattinen lataus + + + + Same name as movie + Sama nimi kuin elokuvalla + + + + All subs containing movie name + Kaikki tekstitykset jotka sisältävät elokuvan nimen + + + + All subs in directory + Kaikki tekstitykset hakemistossa + + + + Position + Sijainti + + + + 0 + + + + + Top + Ylhäällä + + + + Bottom + Alhaalla + + + + Font + Kirjasin + + + + Select the font which will be used for subtitles (and OSD): + Valitse kirjasin jota käytetään tekstityksissä (ja OSD:ssä): + + + + Size + Koko + + + + No autoscale + Ei automaattista skaalausta + + + + Proportional to movie height + Suhteellinen elokuvan korkeuteen + + + + Proportional to movie width + Suhteellinen elokuvan leveyteen + + + + Proportional to movie diagonal + + + + + Subtitle position + Tekstityksen sijainti + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + + + + + Au&toload subtitles files (*.srt, *.sub...): + La&taa automaattisesti teksitys tiedostot (*.srt, *.sub...): + + + + S&elect first available subtitle + V&alitse ensimmäisenä saatavilla oleva tekstitys + + + + &Default subtitle encoding: + &Oletus teksityksen merkkikoodaus: + + + + Default &position of the subtitles on screen + Tekstityksen &oletus sijainti näytöllä + + + + &Include subtitles on screenshots + &Sisällytä tekstitykset kuvankaappauksissa + + + + &TTF font: + &TTF kirjasin: + + + + S&ystem font: + J&ärjestelmän kirjasin: + + + + A&utoscale: + A&utomaattinen skaalaus: + + + + Select first available subtitle + + + + + Default subtitle encoding + + + + + Include subtitles on screenshots + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + Alhaalla + + + + Middle + vertical alignment + + + + + Top + vertical alignment + Ylhäällä + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Apua + + + + OK + OK + + + + Cancel + Hylkää + + + + Apply + Hyväksy + + + + Help + Apua + + + + SMPlayer - Preferences + SMPlayer - Asetukset + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + + the main window won't be closed when the file/playlist finishes. + + + + + the video will be played in fullscreen mode. + + + + + the video will be played in window mode. + + + + + Enqueue in SMPlayer + + + + + opens the mini gui instead of the default one. + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + Usage: + + + + + directory + + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + %1 ja %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + kuvake + + + + label + + + + + ShortcutGetter + + + Modify shortcut + Muokkaa oikotietä + + + + Clear + Tyhjennä + + + + Press the key combination you want to assign + + + + + Capture + + + + + Capture keystrokes + + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + Valitse kaikki + + + + Select None + Älä valitse mitään + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + Auto + + + + Yes + Kyllä + + + + No + Ei + + + + VideoEqualizer + + + Contrast + Kontrasti + + + + Brightness + Kirkkaus + + + + Hue + Sävy + + + + Saturation + Kyllästyneisyys + + + + Gamma + Gamma + + + + &Reset + &Palauta + + + + &Set as default values + + + + + Use the current values as default values for new videos. + + + + + Set all controls to zero. + Aseta kaikki kontrollit nollille. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + Hylkää + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Virhe tallennettaessa tiedostoa + + + + The file couldn't be saved + Tiedostoa ei pystytty tallentamaan + + + + Error + Virhe + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Oletus + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Volyymi + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_fr.ts b/plugins/smplayer_plugin/translations/smplayer_fr.ts new file mode 100644 index 000000000..73402eaa2 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_fr.ts @@ -0,0 +1,7245 @@ + + + + About + + + Version: %1 + Version : %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Ce programme est un logiciel libre: vous pouvez le redistribuer et/ou le modifier selon les termes de la "GNU General Public License", tels que publiés par la "Free Software Foundation"; soit la version 2 de cette licence ou (à votre choix) toute version ultérieure. Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE, ni explicite ni implicite; sans même les garanties de commercialisation ou d'adaptation dans un but spécifique. Se référer à la "GNU General Public License" pour plus de détails. Vous devriez avoir reçu une copie de la "GNU General Public License" en même temps que ce programme; sinon, écrivez a la "Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA". + + + + The following people have contributed with translations: + Ces personnes suivantes ont contribués pour la traduction : + + + + German + + + + + Slovak + + + + + Italian + + + + + French + Français + + + + %1, %2 and %3 + %1, %2 et %3 + + + + Simplified-Chinese + Chinois simplifié + + + + Russian + + + + + %1 and %2 + %1 et %2 + + + + Hungarian + + + + + Polish + + + + + Japanese + + + + + Dutch + + + + + Ukrainian + + + + + Portuguese - Brazil + + + + + Georgian + + + + + Czech + + + + + Bulgarian + + + + + Turkish + + + + + Swedish + + + + + Serbian + + + + + Traditional Chinese + + + + + Romanian + + + + + Portuguese - Portugal + + + + + Greek + + + + + Finnish + + + + + <b>%1</b>: %2 + <b>%1</b> : %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + A propos de SMPlayer + + + + &Info + &Information + + + + icon + Icône + + + + &Contributions + &Contributions + + + + &Translators + &Traducteurs + + + + &License + &Licence + + + + Visit our web for updates: + Visitez notre site pour les mises à jour : + + + + Get help in our forum: + Obtenez de l'aide sur notre forum : + + + + You can support SMPlayer by making a donation. + Vous pouvez supporter SMPlayer faisant un don. + + + + More info + Plus d'information + + + + Korean + + + + + Macedonian + Macédonien + + + + Basque + + + + + Using MPlayer %1 + Utilisant MPlayer %1 + + + + Catalan + + + + + Portable Edition + Edition portable + + + + Using Qt %1 (compiled with Qt %2) + Utilise Qt %1 (compilé avec Qt %2) + + + + Slovenian + + + + + Arabic + + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + Les personnes suivantes ont contribués avec leurs mises à jour (voir le journal des changements pour plus de détails) : + + + + If there's any omission, please report. + N'hésitez pas à faire un report si vous avez eu le moindre problème. + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Nom + + + + Description + Description + + + + Shortcut + Raccourci + + + + &Save + &Enregistrer + + + + &Load + &Charger + + + + Key files + Fichiers *.key + + + + Choose a filename + Choisir un nom de fichier + + + + Confirm overwrite? + Confirmer l'écrasement ? + + + + The file %1 already exists. +Do you want to overwrite? + Le fichier %1 existe déjà. +Voulez-vous l'écraser ? + + + + Choose a file + Choisir un fichier + + + + Error + Erreur + + + + The file couldn't be saved + Ce fichier n'a pas pu être sauvegardé + + + + The file couldn't be loaded + Ce fichier n'a pas pu être chargé + + + + &Change shortcut... + &Changer le raccourci... + + + + AudioEqualizer + + + Audio Equalizer + Equaliseur audio + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Appliquer + + + + &Reset + &Réinitialiser + + + + &Set as default values + Choi&sir en tant que valeur par défaut + + + + Use the current values as default values for new videos. + Utiliser les valeurs actuelles comme valeurs par défaut pour les nouvelles vidéos. + + + + Set all controls to zero. + Mettre tous les contrôles à zéro. + + + + Information + Information + + + + The current values have been stored to be used as default. + Les valeurs courantes ont été stockées pour être utilisées par défaut. + + + + BaseGui + + + &File... + &Fichier... + + + + D&irectory... + Doss&ier... + + + + &Playlist... + &Liste de lecture... + + + + &DVD from drive + &DVD depuis un lecteur + + + + D&VD from folder... + D&VD depuis un dossier... + + + + &URL... + &URL... + + + + P&lay + &Lecture + + + + &Pause + &Pause + + + + &Stop + &Stop + + + + &Frame step + &Image par image + + + + &Repeat + &Répéter + + + + &Normal speed + &Vitesse normale + + + + &Halve speed + &Vitesse /2 + + + + &Double speed + &Vitesse x2 + + + + Speed &-10% + Vitesse &-10% + + + + Speed &+10% + Vitesse &+10% + + + + Sp&eed + &Vitesse + + + + &Fullscreen + &Plein écran + + + + &Compact mode + &Mode compact + + + + &Equalizer + &Equaliseur + + + + &Screenshot + &Capturer écran + + + + S&tay on top + Res&ter au premier plan + + + + &Postprocessing + &Post-traitement + + + + &Autodetect phase + &Autodétection de la phase + + + + &Deblock + &De-blocking + + + + De&ring + De-&ringing + + + + Add n&oise + Ajouter &bruit + + + + F&ilters + &Filtres + + + + &Mute + &Muet + + + + Volume &- + Volume &- + + + + Volume &+ + Volume &+ + + + + &Delay - + &Délai - + + + + D&elay + + D&élai + + + + + &Extrastereo + &Extra Stéréo + + + + &Karaoke + &Karaoké + + + + &Filters + &Filtres + + + + &Load... + &Charger... + + + + Delay &- + Délai &- + + + + Delay &+ + Délai &+ + + + + &Up + &Haut + + + + &Down + &Bas + + + + &Playlist + &Liste de lecture + + + + &Show frame counter + Compteur d'image&s + + + + P&references + P&références + + + + &View logs + &Journaux + + + + About &Qt + A propos de &Qt + + + + About &SMPlayer + A propos de &SMPlayer + + + + &Open + &Ouvrir + + + + &Play + &Lire + + + + &Video + &Vidéo + + + + &Audio + &Audio + + + + &Subtitles + &Sous-titrage + + + + &Browse + &Navigation + + + + Op&tions + Op&tions + + + + &Help + A&ide + + + + &Recent files + &Fichiers récents + + + + &Clear + &Effacer + + + + Si&ze + T&aille + + + + &Aspect ratio + &Aspect ratio + + + + &Deinterlace + &Désentrelacement + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &à 16:9 + + + + &None + Aucu&n + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Linear &Blend + + + + &Channels + &Canaux + + + + &Stereo mode + &Mode Stéréo + + + + &Stereo + &Stéréo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Left channel + &Canal gauche + + + + &Right channel + Canal &droit + + + + &Select + &Sélectionner + + + + &Title + &Titre + + + + &Chapter + &Chapitre + + + + &Angle + &Angle + + + + &OSD + &OSD + + + + &Disabled + &Désactivé + + + + &Seek bar + &Barre de navigation + + + + &Time + &Durée + + + + Time + T&otal time + Durée + Durée t&otale + + + + SMPlayer - mplayer log + Journal MPlayer + + + + SMPlayer - smplayer log + Journal SMPlayer + + + + <empty> + <vide> + + + + Video + Vidéo + + + + Audio + Audio + + + + Playlists + Listes de lecture + + + + All files + Tous les fichiers + + + + Choose a file + Choisir un fichier + + + + SMPlayer - Information + SMPlayer - Information + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Les lecteurs CD/DVD ne sont pas encore configurés. +La boîte de dialogue de configuration va s'afficher pour que vous le fassiez maintenant. + + + + Choose a directory + Choisir un dossier + + + + Subtitles + Sous-titres + + + + About Qt + A propos de Qt + + + + Playing %1 + Lecture de %1 + + + + Pause + Pause + + + + Stop + Stop + + + + Play / Pause + Lecture / Pause + + + + Pause / Frame step + Pause / Saut d'images + + + + U&nload + Déchar&ger + + + + V&CD + V&CD + + + + C&lose + F&ermer + + + + View &info and properties... + Propr&iétés du fichier... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Réinitialiser + + + + Move &left + A&ller à gauche + + + + Move &right + Aller à d&roite + + + + Move &up + &Monter + + + + Move &down + &Descendre + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + Ligne &précédente + + + + N&ext line in subtitles + Ligne suivant&e + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Volume - (2) + + + + Inc volume (2) + Volume + (2) + + + + Exit fullscreen + Sortir du mode plein écran + + + + OSD - Next level + OSD - Niveau suivant + + + + Dec contrast + Constrate - + + + + Inc contrast + Constrate + + + + + Dec brightness + Luminosité - + + + + Inc brightness + Luminosité + + + + + Dec hue + Ton - + + + + Inc hue + Ton - + + + + Dec saturation + Saturation - + + + + Dec gamma + Gamma - + + + + Next audio + Audio suivant + + + + Next subtitle + Sous-titre suivant + + + + Next chapter + Chapitre suivant + + + + Previous chapter + Chapitre précédent + + + + Inc saturation + Saturation + + + + + Inc gamma + Gamma + + + + + &Load external file... + &Charger fichier extérieur... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normal) + + + + Y&adif (double framerate) + Y&adif (taux d'images double) + + + + &Next + &Suivant + + + + Pre&vious + &Précédent + + + + Volume &normalization + &Normalisation du volume + + + + &Audio CD + CD &Audio + + + + Denoise nor&mal + Débruité nor&mal + + + + Denoise &soft + Débruité &léger + + + + Denoise o&ff + P&as de débruité + + + + Use SSA/&ASS library + Utiliser la librairie SSA/&ASS + + + + Flip i&mage + Inverser l'i&mage + + + + &Toggle double size + &Fixer en taille double + + + + S&ize - + Ta&ille - + + + + Si&ze + + Ta&ille + + + + + Add &black borders + Ajout de &bordures noires + + + + Soft&ware scaling + Bascule lo&giciel + + + + &FAQ + &FAQ + + + + Visualize &motion vectors + Visualiser vecteurs &motion + + + + &Command line options + Options ligne de &commande + + + + SMPlayer command line options + Options de ligne de commande de SMPlayer + + + + Enable &closed caption + A&ctiver la légende fermée + + + + &Forced subtitles only + Seulement les sous-titres &forcés + + + + Reset video equalizer + Réinitialiser l'équaliseur vidéo + + + + MPlayer has finished unexpectedly. + MPlayer s'est mal terminé. + + + + Exit code: %1 + Code de sortie : %1 + + + + MPlayer failed to start. + MPlayer ne s'est pas lancé. + + + + Please check the MPlayer path in preferences. + Veuillez vérifier votre chemin MPlayer dans les préférences. + + + + MPlayer has crashed. + MPlayer a craché. + + + + See the log for more info. + Regardez le journal pour plus d'info. + + + + &Rotate + &Rotation + + + + &Off + &Arrêt + + + + &Rotate by 90 degrees clockwise and flip + &Rotation de 90 degrès vers la droite et flip + + + + Rotate by 90 degrees &clockwise + Rotation de 90 degrès ver&s la droite + + + + Rotate by 90 degrees counterclock&wise + Rotation de 90 degrès vers la &gauche + + + + Rotate by 90 degrees counterclockwise and &flip + Rotation de 90 degrès vers la gauche et &flip + + + + &Jump to... + &Sauter à... + + + + Show context menu + Montrer le menu contexte + + + + Multimedia + Multimédia + + + + E&qualizer + E&qualiseur + + + + Reset audio equalizer + Réinitialiser l'équaliseur vidéo + + + + Find subtitles on &OpenSubtitles.org... + Trouver des sous-titres sur &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Envoyer des sous-titres sur OpenSu&btitles.org... + + + + &Tips + &Astuces + + + + &Auto + &Auto + + + + Speed -&4% + Vitesse -&4% + + + + &Speed +4% + &Vitesse +4% + + + + Speed -&1% + Vitesse -&1% + + + + S&peed +1% + V&itesse +1% + + + + Scree&n + I&mage + + + + &Default + &Défaut + + + + Mirr&or image + Image mir&oir + + + + Next video + Prochaine vidéo + + + + &Track + video + &Piste + + + + &Track + audio + &Piste + + + + Warning - Using old MPlayer + Attention : vieille version de MPlayer utilisée + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + La version de MPlayer (%1) installée sur votre système est obselète. De ce fait, SMPlayer ne peut pas fonctionner correctement : certaines options ainsi que le sous-titrage peuvent ne pas fonctionner... + + + + Please, update your MPlayer. + Veuillez mettre à jour votre version de MPlayer. + + + + (This warning won't be displayed anymore) + (Cette alerte n'apparaitra plus) + + + + Next aspect ratio + Aspect ratio suivant + + + + &Auto zoom + &Autozoom + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer fonctionne toujours + + + + S&how icon in system tray + Icône dans la barre de tâc&hes + + + + &Hide + Cac&her + + + + &Restore + &Restaurer + + + + &Quit + &Quitter + + + + Playlist + Liste de lecture + + + + Core + + + Brightness: %1 + Luminosité : %1 + + + + Contrast: %1 + Contraste : %1 + + + + Gamma: %1 + Gamma : %1 + + + + Hue: %1 + Ton : %1 + + + + Saturation: %1 + Saturation : %1 + + + + Volume: %1 + Volume : %1 + + + + Zoom: %1 + Zoom : %1 + + + + Font scale: %1 + Echelle de police : %1 + + + + Aspect ratio: %1 + Aspect ratio : %1 + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Bienvenue dans SMPlayer + + + + Audio + Audio + + + + Subtitle + Sous-titres + + + + &Main toolbar + Barre d'outils pri&ncipale + + + + &Language toolbar + Barre de &langues + + + + &Toolbars + &Barre d'outils + + + + EqSlider + + + icon + Icône + + + + ErrorDialog + + + Hide log + Cacher le journal + + + + Show log + Voir le journal + + + + MPlayer Error + Erreur MPlayer + + + + icon + Icône + + + + Error + Erreur + + + + FileDownloader + + + Downloading... + Téléchargement en cours... + + + + Downloading %1 + Téléchargement en cours %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Propriétés du fichier + + + + &Information + &Information + + + + &Demuxer + &Démultiplexeur + + + + &Select the demuxer that will be used for this file: + &Sélectionnez le démultiplexeur qui sera utilisé pour ce fichier : + + + + &Reset + &Réinitialiser + + + + &Video codec + Codec &vidéo + + + + &Select the video codec: + &Sélectionnez le codec vidéo : + + + + A&udio codec + Codec a&udio + + + + &Select the audio codec: + &Sélectionnez le codec audio : + + + + &MPlayer options + Options &Mplayer + + + + Additional Options for MPlayer + Options additionnelles pour MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Extra-options de MPlayer. +Celles-ci doivent être séparées d'un espace. +Exemple : -flip -nosound + + + + &Options: + &Options : + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Vous pouvez aussi passer des filtres vidéo supplémentaires. +Séparez les par ",". N'utilisez pas d'espace ! +Exemple : scale=512:-2,eq2=1.1 + + + + V&ideo filters: + Filtres V&idéo : + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Pour les filtres audios, même régle que pour les filtres vidéo. +Exemple : resample=44100:0:0,volnorm + + + + Audio &filters: + &Filtres audio : + + + + OK + OK + + + + Cancel + Annuler + + + + Apply + Appliquer + + + + FindSubtitlesWindow + + + Language + Langue + + + + Name + Nom + + + + Format + Format + + + + Files + Fichiers + + + + Date + Date + + + + Uploaded by + Envoyé par + + + + All + Tous + + + + Close + Fermer + + + + &Download + &Téléchargement + + + + &Copy link to clipboard + &Copier dans le presse papier + + + + Error + Erreur + + + + Download failed: %1. + Téléchargement échoué : %1. + + + + Connecting to %1... + Connexion à %1... + + + + Downloading... + Téléchargement... + + + + Done. + Effectué. + + + + %1 files available + %1 fichiers disponibles + + + + Failed to parse the received data. + Impossible de comprendre les données reçues. + + + + Find Subtitles + Trouver un sous-titrage + + + + &Subtitles for + &Sous-titrage pour + + + + &Language: + &Langues : + + + + &Refresh + &Rafraichir + + + + Subtitle saved as %1 + Sous-titres sauvegardés : %1 + + + + %1 subtitle(s) extracted + + %1 sous-titre(s) extrait(s) + %1 sous-titre(s) extrait(s) + + + + + Overwrite? + Ecraser ? + + + + The file %1 already exits, overwrite? + Le fichier %1 existe déjà, l'écraser ? + + + + Error saving file + Erreur lors de la sauvegarde + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Il n'a pas été possible de sauvegarder +le fichier dans le dossier %1 +Veuillez vérifier les droits sur ce dossier. + + + + Download failed + Téléchargement échoué + + + + Temporary file %1 + Fichier temporaire %1 + + + + InfoFile + + + General + Général + + + + Size + Taille + + + + %1 KB (%2 MB) + %1 Ko (%2 Mo) + + + + URL + URL + + + + Length + Durée + + + + Demuxer + Démultiplexeur + + + + Name + Nom + + + + Artist + Artiste + + + + Author + Auteur + + + + Album + Album + + + + Genre + Genre + + + + Date + Date + + + + Track + Piste + + + + Copyright + Copyrights + + + + Comment + Commentaire + + + + Software + Logiciel + + + + Clip info + Informations sur le fichier + + + + Video + Vidéo + + + + Resolution + Résolution + + + + Aspect ratio + Aspect ratio + + + + Format + Format + + + + Bitrate + Débit + + + + %1 kbps + %1 kbps + + + + Frames per second + Images par seconde + + + + Selected codec + Codec sélectionné + + + + Initial Audio Stream + Flux audio initial + + + + Rate + Taux + + + + %1 Hz + %1 Hz + + + + Channels + Canaux + + + + Audio Streams + Flux audio + + + + Language + Langue + + + + empty + vide + + + + Subtitles + Sous-titres + + + + Type + Type + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Titre du Stream + + + + Stream URL + URL du Stream + + + + File + Fichier + + + + InputDVDDirectory + + + Choose a directory + Choisissez un dossier + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Lire un DVD depuis un dossier + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Vous pouvez lire un DVD depuis le disque dur. Selectionnez le dossier contenant VIDEO_TS et AUDIO_TS. + + + + Choose a directory... + Choisissez un dossier... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Entrer la version de MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer n'a pas pu identifier la version de MPlayer utilisée. + + + + Version reported by MPlayer: + Version identifiée par MPlayer : + + + + Please, &select the correct version: + Veuillez &sélectionner la bonne version : + + + + 1.0rc1 or older + 1.0rc1 ou plus ancien + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Plus récent que 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Entrez une URL + + + + &URL: + &URL : + + + + It's a &playlist + &Liste de lecture + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Si cette option est cochée, l'URL sera traitée comme une liste de lecture : celà l'ouvrira en tant que texte et jouera les URLs dedans. + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + + + + + Welsh + + + + + Danish + + + + + German + + + + + Greek + + + + + English + + + + + Esperanto + + + + + Spanish + + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + + + + + Faroese + + + + + French + Français + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + + + + + Inuktitut + + + + + Japanese + + + + + Javanese + + + + + Georgian + + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + + + + + Portuguese + + + + + Quechua + + + + + Romanian + + + + + Russian + + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + + + + + Sundanese + + + + + Swedish + + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + + + + + Portuguese - Portugal + + + + + Simplified-Chinese + + + + + Traditional Chinese + + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + + + + + Western European Languages with Euro + + + + + Slavic/Central European Languages + + + + + Esperanto, Galician, Maltese, Turkish + + + + + Old Baltic charset + + + + + Cyrillic + + + + + Modern Greek + + + + + Baltic + + + + + Celtic + + + + + Hebrew charsets + + + + + Ukrainian, Belarusian + + + + + Simplified Chinese charset + + + + + Traditional Chinese charset + + + + + Japanese charsets + + + + + Korean charset + + + + + Thai charset + + + + + Cyrillic Windows + + + + + Slavic/Central European Windows + + + + + Arabic Windows + + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Choisissez un nom de fichier pour sauver + + + + Confirm overwrite? + Confirmer écrasement ? + + + + The file already exists. +Do you want to overwrite? + Le fichier existe déjà. +Voulez-vous le remplacer ? + + + + Error saving file + Erreur lors de la sauvegarde + + + + The log couldn't be saved + Le fichier de log n'a pas pu être sauvegardé + + + + Logs + Logs + + + + LogWindowBase + + + Log Window + Log Window + + + + Save + Sauver + + + + Copy to clipboard + Copier dans le presse papier + + + + Close + Fermer + + + + &Close + &Fermer + + + + MiniGui + + + Control bar + Barre de contrôle + + + + MpcGui + + + Control bar + Barre de contrôle + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nom + + + + Length + Durée + + + + Choose a file + Choisir un fichier + + + + Choose a filename + Choisir un nom de fichier + + + + Confirm overwrite? + Confirmer remplacement ? + + + + Select one or more files to open + Selectionner un ou plusieurs fichiers à ouvrir + + + + Choose a directory + Selectionner un dossier + + + + The file %1 already exists. +Do you want to overwrite? + Le fichier %1 existe déjà. +Voulez vous l'écraser? + + + + Edit name + Editer le nom + + + + Type the name that will be displayed in the playlist for this file: + Tapez le nom qui sera affiché dans la playlist pour ce fichier : + + + + &Play + &Lire + + + + &Edit + &Editer + + + + Playlists + Listes de lecture + + + + All files + Tous les fichiers + + + + &Load + &Charger + + + + &Save + &Enregistrer + + + + &Next + &Suivant + + + + Pre&vious + &Précédent + + + + Move &up + &Monter + + + + Move &down + &Descendre + + + + &Repeat + &Répéter + + + + S&huffle + &Aléatoire + + + + Add &current file + Ajouter le fichier &courant + + + + Add &file(s) + Ajout de &fichier(s) + + + + Add &directory + Ajout d'un &dossier + + + + Remove &selected + Effacer la &sélection + + + + Remove &all + &Tout supprimer + + + + SMPlayer - Playlist + SMPlayer - Liste de lecture + + + + Add... + Ajouter... + + + + Remove... + Supprimer... + + + + Playlist modified + Playlist modifiée + + + + There are unsaved changes, do you want to save the playlist? + Des changements ont été faits dans cette liste de lecture, voulez-vous enregistrer ? + + + + Preferences + Préférences + + + + PlaylistPreferences + + + Playlist - Preferences + Liste de lecture - Préférences + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Sélectionnez cette option si vous voulez ajouter un répertoire qui ajoutera récursivement les fichiers des sous-répertoires. Autrement, seulement les fichiers des dossiers sélectionnées seront ajoutés. + + + + &Add files in directories recursively + &Ajouter des fichiers de dossiers de façon récursive + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Cochez cette option pour montrer le titre (si disponible) et la taille des fichiers. Autrement si l'information ne sera pas affichée lorsque le fichier est joué. Attention, cela peut ralentir le système, surtout si vous avez ajouté beaucoup de fichiers. + + + + Automatically get &info about files added + Obtenir automatiquement des &informations à propos des fichiers ajoutés + + + + &Save copy of playlist on exit + &Sauvegarder une copie de la liste de lecture à chaque fermeture + + + + &Play files from start + &Jouer ces fichiers par le début + + + + PrefAdvanced + + + Advanced + Avancé + + + + Auto + Auto + + + + &Advanced + &Avancé + + + + icon + Icône + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Extra-options de MPlayer. +Celles-ci doivent être séparées d'un espace. +Exemple : -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Vous pouvez aussi passer des filtres vidéo supplémentaires. +Séparez les par ",". N'utilisez pas d'espace ! +Exemple : scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Pour les filtres audios, même régle que pour les filtres vidéo. +Exemple : resample=44100:0:0,volnorm + + + + Log MPlayer output + Log de sortie MPlayer + + + + Log SMPlayer output + Log de sortie SMPlayer + + + + This option is mainly intended for debugging the application. + Cette option est principalement utile pour le débuggage. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Cocher cette option peut réduire le "flickering", cependant, la vidéo peut ne pas s'afficher correctement. + + + + Filter for SMPlayer logs + Filtres pour les logs de SMPlayer + + + + &Monitor aspect: + Aspect &moniteur : + + + + &Run MPlayer in its own window + Lance&r MPlayer dans sa propre fenêtre + + + + &Options: + &Options : + + + + V&ideo filters: + Filtres V&idéo : + + + + Audio &filters: + &Filtres audio : + + + + &Colorkey: + &Clé de couleur : + + + + Log &SMPlayer output + Log de sortie &SMPlayer + + + + &Filter for SMPlayer logs: + &Filtre pour les logs de SMPlayer : + + + + C&hange... + C&hanger... + + + + Logs + Journaux + + + + Log MPlayer &output + Journal MPlayer &sortie + + + + Options for MP&layer + Options pour MP&layer + + + + Autosave MPlayer log + Sauvegarde automatique du journal MPlayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Si cette option est cochée, le journal de MPlayer sera sauvegardé dans un fichier spécifié à chaque fois qu'un nouveau fichier est joué. Cette option est principalement conçue pour les applications extérieurs afini qu'elles puissent obtenir des informations sur le fichier joué. + + + + Autosave MPlayer log filename + Sauvegarde automatique du du nom du journal MPlayer + + + + Enter here the path and filename that will be used to save the MPlayer log. + Entrez ici le chemin et le nom du fichier qui seront utilisé pour le journal de MPlayer. + + + + A&utosave MPlayer log to file + Sa&uvegarde automatique du journal MPlayer + + + + Pass short filenames (8+3) to MPlayer + Envoyer les noms courts des fichiers (8+3) à MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Actuellement MPlayer ne peut pas ouvrir les fichiers contenant trop de caractères. En cochant cette optique, SMPlayer passera à MPlayer la version courte des noms de fichiers and sera de ce fait capable de les ouvrir. + + + + &Pass short filenames (8+3) to MPlayer + Envoyer les noms courts des fichiers (8+3) à M&Player + + + + Monitor aspect + Aspect moniteur + + + + Select the aspect ratio of your monitor. + Sélectionnez le ratio aspect de votre moniteur. + + + + Run MPlayer in its own window + Lancer MPlayer dans sa propre fenêtre + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Si vous cochez cette option, la fenêtre vidéo de MPlayer ne sera pas attachée à la fenêtre principale de SMPlayer mais sera dans sa propre fenêtre. Notez que les évenements de la souris et du clavier seront alors directement dédiés au commande MPlayer. Cela ve dire que les raccourcis ne vont pas marcher sauf si la fenêtre de MPlayer est sélectionnée. + + + + Colorkey + Clé de couleur + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Si vous voyez les parties de la vidéo dans d'autres fenêtres, vous pouvez changer la clé couleur pour réparer cela. Essayez de sélectionner une couleur proche du noir. + + + + Options for MPlayer + Options pour MPlayer + + + + Options + Options + + + + Here you can type options for MPlayer. Write them separated by spaces. + Ici, vous pouvez écrire les options pour MPlayer. Ecrivez les séparées d'un espace. + + + + Video filters + Filtres vidéo + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Ici, vous pouvez ajouter les filtres vidéos pour MPlayer. Ecrivez les séparés d'une virgule. N'utilisez pas les espaces ! + + + + Audio filters + Filtres audio + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Ici, vous pouvez ajouter les filtres audios pour MPlayer. Ecrivez les séparés d'une virgule. N'utilisez pas les espaces ! + + + + Repaint the background of the video window + Repeindre le fond de la fenêtre de la vidéo + + + + Repaint the backgroun&d of the video window + Repeindre le fon&d de la fenêtre de la vidéo + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Utiliser l'IPv4 sur les connexions réseaux et non l'IPv6. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Utiliser l'IPv6 sur les connexions réseaux et non l'IPv4. + + + + Network Connection + Connexion réseau + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + &Journaux + + + + Rebuild index if needed + Reconstruire l'index si besoin + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Reconstruit l'index des fichiers si aucun index a été trouvé, permettant la recherche. Très utile pour les fichiers cassés ou incomplets ou mal créés. Cette option ne marche que si le media supporte la recherche (par exemple sans stdin, pipe, etc). <br>Note : la création d'index peut prendre un certain temps. + + + + Rebuild &index if needed + Reconstruire l'&index si besoin + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + Activer le proxy + + + + Enable/disable the use of the proxy. + Activer/Désactiver le proxy. + + + + Host + Hôte + + + + The host name of the proxy. + Le nom du proxy hôte. + + + + Port + + + + + The port of the proxy. + Le port du proxy. + + + + Username + Identifiant + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + Activ&er le proxy + + + + &Host: + &Hôte : + + + + &Port: + &Port : + + + + &Username: + &Identifiant : + + + + Pa&ssword: + Mot de p&asse : + + + + C&orrect PTS + + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + Type + + + + Select the proxy type to be used. + Sélectionnez le type de proxy à utiliser. + + + + &Type: + &Type : + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Attention + + + + Not all files could be associated. Please check your security permissions and retry. + Certains fichiers ne peuvent être associés. Vérifiez les droits de ceux-ci et réessayez. + + + + File Types + Types de fichier + + + + Select all + Tous les sélectionner + + + + Check all file types in the list + Vérifier tous les types de fichier dans la liste + + + + Uncheck all file types in the list + Ne plus vérifier tous les types de fichiers dans la liste + + + + List of file types + Liste des types de fichiers + + + + File types + Types de fichiers + + + + Media files handled by SMPlayer: + Fichiers associés à SMPlayer : + + + + Select All + Tous les sélectionner + + + + Select None + Sélectionner aucun + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Vérifier les formats de fichiers que vous voulez associer à SMPlayer. Lorsque vous cliquez sur "Appliquer", les fichiers vérifiés seront associés à SMPlayer. Si vous souhaitez ne plus vérifier le type de fichier, alors l'association de ce fichier sera restaurée. + + + + Select none + Sélectionner aucun + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Note :</b> (La restauration ne marche pas sous Windows Vista). + + + + PrefDrives + + + Drives + Lecteurs + + + + icon + Icône + + + + CD device + Lecteur CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Choississez votre lecteur CD. Il sera utilisé pour lire les VCDs et CDs Audio. + + + + DVD device + Lecteur DVD + + + + Choose your DVD device. It will be used to play DVDs. + Choississez votre lecteur DVD. Il sera utilisé pour lire les DVDs. + + + + Select your &CD device: + Sélectionnez le lecteur &CD : + + + + Select your &DVD device: + Sélectionnez le lecteur &DVD : + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer ne choisit pas de lecteurs de CD ou DVD lui-même. De ce fait, avant de lire un CD/DVD, veuillez sélectionner votre/vos lecteur(s) (ils peuvent être les mêmes). + + + + PrefGeneral + + + General + Général + + + + &General + &Général + + + + Paths + Chemins + + + + Media settings + Configurations du média + + + + Preferred audio and subtitles + Audio et sous-titres préférés + + + + Video + Vidéo + + + + Start videos in fullscreen + Lancer les vidéos en plein écran + + + + Disable screensaver + Désactiver l'écran de veille + + + + Audio + Audio + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Select the mplayer executable + Séléctionnez l'éxécutable MPlayer + + + + Executables + Exécutables + + + + All files + Tous les fichiers + + + + Select a directory + Choisir un dossier + + + + MPlayer executable + Executable MPlayer + + + + Screenshots folder + Dossier des captures d'écran + + + + Video output driver + Pilote de sortie vidéo + + + + Audio output driver + Pilote de sortie Audio + + + + Select the audio output driver. + Sélectionnez le pilote de sortie audio. + + + + Remember settings + Configurations de rappel + + + + Preferred audio language + Langage préféré pour l'audio + + + + Preferred subtitle language + Langage préféré pour le sous-titrage + + + + Software video equalizer + Equaliseur vidéo logiciel + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Vous pouvez sélectionner cette option si l'égaliseur n'est pas supporté par votre carte graphique ou le driver de sortie vidéo sélectionné.<br><b>Note :</b> cette option peut être incompatible avec certains pilotes de sortie vidéo. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Si cette option est sélectionnée, toutes les vidéos seront lancées en plein écran. + + + + Software volume control + Contrôle volume logiciel + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Sélectionnez cette option pour utiliser le mixeur logiciel au lieu du mixeur matériel. + + + + Postprocessing quality + Qualité post-traitement + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Changer dynamiquement le niveau de post-traitement selon la charge CPU disponible. Le nombre spécifié sera le niveau maximum. Généralement, vous pouvez choisir de grands nombres. + + + + Change volume + Changer volume + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Si coché, SMPlayer se rappelera du volume pour chaque fichier, et le restaurera. Pour les nouveaux fichiers, le volume par défaut sera utilisé. + + + + 0 + 0 + + + + &Change volume on every file + &Changer le volume sur chaque fichier + + + + Select the &MPlayer executable: + Selectionner l'exécutable de &MPlayer : + + + + &Folder for storing screenshots: + &Dossier stockant les captures d'écran : + + + + &Audio: + &Audio : + + + + &Remember settings for all files (audio track, subtitles...) + &Se rappeler de la configuration de chaque fichier (piste audio, sous-titres, ...) + + + + Su&btitles: + Sous-&titres : + + + + &Quality: + &Qualité : + + + + Start videos in &fullscreen + Toujours lancer les vidéos en &plein écran + + + + Disable &screensaver + Désactiver l'écran de &veille + + + + &Default volume: + Volume par &défaut : + + + + Use s&oftware volume control + Utiliser le contrôle de volume &logiciel + + + + Ma&x. Amplification: + Amplification Ma&x. : + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS pass-through S/PDIF + + + + Direct rendering + Rendering direct + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Si cochée, cette option met le rendering direct (non supportée par tous les codecs ou sorties de vidéos)<br><b>Attention :</br> Peut causer des corruptions OSD/SBUB ! + + + + Double buffering + Double buffering + + + + D&irect rendering + Rendering d&irect + + + + Dou&ble buffering + Dou&ble buffering + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Double buffering fixe le clignotement en stockant deux images en mémoire, et en affiche une pendant que l'autre est en train d'être décodée. Si désactivé, cela peut affecter l'OSD, mais généralement cela supprime les clignotements. + + + + &Enable postprocessing by default + &Utiliser le post-traitement par défaut + + + + Volume &normalization by default + &Normalisation du volume par défaut + + + + Close when finished + Fermer l'application lorsque media est fini de lire + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Si cette option est cochée, la fenêtre principale sera automatiquement fermée lorsque le fichier ou la liste de lecture sera fin(e). + + + + 2 (Stereo) + 2 (Stéréo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + Canau&x par défaut : + + + + &Pause when minimized + &Pause lorsque l'application est réduite + + + + Pause when minimized + Mettre en pause lorsque l'application est minimisée + + + + Enable postprocessing by default + Activer le post-traitement par défaut + + + + Max. Amplification + Amplification Max + + + + Volume normalization by default + Normalisation du volume par défaut + + + + Maximizes the volume without distorting the sound. + Maximise le volume sans distordre le son. + + + + Default volume + Volume par défaut + + + + Sets the initial volume that new files will use. + Règle le volume initial dont les nouveaux fichiers utiliseront. + + + + Channels by default + Canaux par défaut + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Règle le niveau d'amplification maximum en pourcentage (défault : 110). La valeur de 200 vous autorisera d'augmenter le volume au double du niveau actuel. Avec des valeurs comme 100, le volume initial (qui est de 100%) sera au dessus du maximum, que par exemple le OSE ne peut pas afficher correctement. + + + + Uses hardware AC3 passthrough + Utilise le hardware AC3 passthrough + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Définit le nombre de canaux audio à utiliser. (défaut : 2). MPlayer demande au décodeur dedécoder l’audio sur le nombre requis de canaux. Maintenant c’est au décodeur de satisfaire cette demande. Généralement, c’est important seulement pour la lecture des vidéos avec de l’audio AC-3(comme les DVDs). Dans ce cas liba52 fait le décodage pardéfaut et fusionne correctementl’audio dans le nombre requis de canaux. NOTE: Cette option est comprise par les codecs (AC-3 uniquement), filtres (surround) et pilotes de sortie audio (OSS au moins). + + + + Postprocessing will be used by default on new opened files. + Le post-traitement sera utilisé par défaut sur les nouveaux fichiers ouverts. + + + + Audio track + Piste audio + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Specifie la piste audio par défaut qui sera utilisée quand les nouveaux fichiers seront joués. Si la piste n'existe pas, le premier sera joué. +<br><b>Note : </b> le <i>langage audio préféré</li> est prioritaire à cette option. + + + + Subtitle track + Piste de sous-titrage + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Specifie la piste de sous-titrage par défaut qui sera utilisée quand les nouveaux fichiers seront joués. Si la piste n'existe pas, le premier sera joué. +<br><b>Note : </b> le <i>langage audio préféré</li> est prioritaire à cette option. + + + + Or choose a track number: + Ou choisir le nombre de la piste : + + + + Audi&o: + Audi&o : + + + + Preferred language: + Langue préférée : + + + + Preferre&d audio and subtitles + Au&dio et sous-titres préférés + + + + &Subtitle: + &Sous-titrage : + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Ici, vous pouvez choisir votre langue préférée pour l'audio et le sous-titrage du stream. Quand un média est trouvé avec un ou plusieurs audio ou sous-titres, SMPlayer essayera d'utiliser votre langue préférée. Ceci marche uniquement lorsqu'un média propose assez d'informations à propos de l'audio ou du sous-titrage, comme les DVDs ou fichiers .mkv. Ces champs acceptent les expresssions régulières. Exemple : <b>es|esp|spa</b> sélectionnera la piste qui comprend <i>es</i>, <i>esp</i> ou <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Aucune information pour le moment> +Aucune information pour le moment. + + + + High speed &playback without altering pitch + Jouer ra&pidement en arrière sans altérer le pitch + + + + High speed playback without altering pitch + Jouer rapidement en arrière sans altérer le pitch + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Permet de changer la vitesse de lecture en arrière sans altérer le pitch. Pour cela, MPlayer dev-SVN-r24924 est requis. + + + + Change volume just before playing + Change le volume juste avant de jouer + + + + &Video + &Vidéo + + + + Use s&oftware video equalizer + Utiliser l'équaliseur l&ogiciel vidéo + + + + A&udio + A&udio + + + + Volume + Volume + + + + None + Aucun + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normal) + + + + Yadif (double framerate) + Yadif (double framerate) + + + + Linear Blend + Linear Blend + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Désentrecro&iser par défaut : + + + + Deinterlace by default + Désentrecroiser par défaut + + + + Select the deinterlace filter that you want to be used for new videos opened. + Sélectionnez le filtre de désentrecroisement pour les nouvelles vidéos ouvertes. + + + + Remember time position + Se rappeler de la position dans le temps + + + + Remember &time position + Se rappeler de la position dans le &temps + + + + Change volume just before p&laying + Changer le vo&lume just avant de jouer + + + + Enable the audio equalizer + Activer l'équaliseur audio + + + + Check this option if you want to use the audio equalizer. + Cochez cette option si vous désirez utiliser l'équaliseur audio. + + + + &Enable the audio equalizer + Activ&er l'équaliseur audio + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + Rapide + + + + slow + Lent + + + + fast - ATI cards + Rapide - Carte ATI + + + + User defined... + Utilisateur défini... + + + + Default zoom + Zoom par défaut + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + &Zoom par défaut : + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 est recommandé. Essayez d'éviter %2 et %3, ils sont lents et peuvent avoir un impact sur les performances. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + Pilote de sor&tie : + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Clavier et Souris + + + + &Keyboard + &Clavier + + + + icon + Icône + + + + &Mouse + &Souris + + + + Button functions: + Fontions des boutons : + + + + Media seeking + Navigation dans le média + + + + Volume control + Contrôle du volume + + + + Zoom video + Zoom vidéo + + + + None + Aucun + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Vous pouvez changer n'importe quel raccourci clavier. Pour se faire, double-cliquez ou appuyez sur "entrée" en appuyant sur la combinaison de touches. Ajouté à celà, vous pouvez aussi sauvegarder la liste pour la partager avec d'autres personnes ou la charger sur un autre ordinateur. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Vous pouvez changer n'importe quel raccourci clavier. Pour se faire, double-cliquez ou appuyez sur "entrée" en appuyant sur la combinaison de touches. Ajouté à celà, vous pouvez aussi sauvegarder la liste pour la partager avec d'autres personnes ou la charger sur un autre ordinateur. + + + + &Left click + Clic &gauche + + + + &Double click + &Double-clic + + + + &Wheel function: + Fonction de la &molette : + + + + Shortcut editor + Editeur de raccourcis + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Cette table vous permet de changer les raccourcis clé de la plupart des actions disponibles. Double-clicquez ou appuyez sur entrer sur un élément, ou pressez sur bouton <b>Changer raccourci</b> pour entrer sur la fenêtre <i>Modifier raccourci</i>. Il y a deux façons de changer un raccourci : si le bouton <b>Capturer</b> est actif alors pressez juste sur une nouvelle touche ou combinaison de touches que vous voulez assigner pour l'action (malheureusement cela ne marche pas pour toutes les touches). Si le boutton <b>Capturer</b> est inactif, alors vous pourrez entrer le nom entier de la touche. + + + + Left click + Clic gauche + + + + Select the action for left click on the mouse. + Sélectionner l'action pour le clic gauche de la souris. + + + + Double click + Double-clic + + + + Select the action for double click on the mouse. + Sélectionner l'action pour le double-clic de la souris. + + + + Wheel function + Fonction de la molette + + + + Select the action for the mouse wheel. + Sélectionner l'action de de la molette. + + + + Play + Lecture + + + + Pause + Pause + + + + Stop + Stop + + + + Fullscreen + Plein écran + + + + Compact + Compact + + + + Screenshot + Capturer écran + + + + On top + Premier plan + + + + Mute + Muet + + + + Frame counter + Compteur d'images + + + + Reset zoom + Réinitialiser zoom + + + + Exit fullscreen + Sortir du mode plein écran + + + + Double size + Double taille + + + + Play / Pause + Lecture / Pause + + + + Pause / Frame step + Pause / Saut d'images + + + + Playlist + Liste de lecture + + + + Preferences + Préférences + + + + No function + Aucune fonction + + + + Change speed + Changer la vitesse + + + + Normal speed + Vitesse normale + + + + Keyboard + Clavier + + + + Mouse + Souris + + + + Middle click + Bouton central + + + + Select the action for middle click on the mouse. + Choisir l'action pour le bouton central de la souris. + + + + M&iddle click + Clic m&ilieu + + + + X Button &1 + X Bouton &1 + + + + X Button &2 + X Bouton &2 + + + + Go backward (short) + Retour court + + + + Go backward (medium) + Retour moyen + + + + Go backward (long) + Retour long + + + + Go forward (short) + Avant court + + + + Go forward (medium) + Avant moyen + + + + Go forward (long) + Avant long + + + + OSD - Next level + OSD - Niveau suivant + + + + Show context menu + Montrer le menu contexte + + + + &Right click + Clic d&roit + + + + Increase volume + Augmenter le volume + + + + Decrease volume + Diminuer le volume + + + + X Button 1 + X Bouton 1 + + + + Select the action for the X button 1. + Sélectionnez l'action pour l'X bouton 1. + + + + X Button 2 + X Bouton 2 + + + + Select the action for the X button 2. + Sélectionnez l'action pour l'X bouton 2. + + + + Show video equalizer + Montrer l'équaliseur vidéo + + + + Show audio equalizer + Montrer l'équaliseur audio + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Interface + + + + <Autodetect> + <Autodétection> + + + + Default + Défaut + + + + &Interface + &Interface + + + + Seeking + Navigation + + + + Never + Jamais + + + + Whenever it's needed + Si nécessaire + + + + Only after loading a new video + Seulement après le chargement d'une nouvelle vidéo + + + + Recent files + Fichiers récents + + + + Language + Langue + + + + Here you can change the language of the application. + Ici, vous pouvez changer la langue de l'application. + + + + Instances + Instances + + + + &Short jump + Saut &court + + + + &Medium jump + Saut &moyen + + + + &Long jump + Saut &long + + + + Mouse &wheel jump + Saut de la &molette + + + + &Use only one running instance of SMPlayer + &Utiliser qu'une seule instance de SMPlayer + + + + Ma&x. items + Nombre ma&ximum + + + + St&yle: + St&yle : + + + + Ico&n set: + Icô&ne : + + + + L&anguage: + L&angue : + + + + Main window + Fenêtre principale + + + + Auto&resize: + &Redimension automatique : + + + + R&emember position and size + S&e rappeler de la position et de la taille + + + + Default font: + Police par défaut : + + + + &Change... + &Changer... + + + + &Behaviour of time slider: + &Comportement de l'ascenseur temps : + + + + Seek to position while dragging + Recherche une position en en déplacant le curseur + + + + Seek to position when released + Recherche la position quand c'est fini + + + + TextLabel + Label Texte + + + + &Seeking + &Recherche + + + + Ins&tances + Ins&tances + + + + Autoresize + Ajuster automatiquement + + + + The main window can be resized automatically. Select the option you prefer. + La fenêtre principale peut être redimensionnée automatiquement. Choississez l'option que vous préférez. + + + + Remember position and size + Se rappeler de la position et de la taille + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Si vous avez coché cette option, la position et la taille de la fenêtre principale seront sauvegardées et restaurées lorsque vous lancerez à nouveau SMPlayer. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Sélectionner le nombre maximum de fichiers montrés dans le menu <b>Ouvrir -> Fichiers récents</b>. Si vous sélectionnez 0 alors le menu ne sera pas montré. + + + + Icon set + Choix des icônes + + + + Select the icon set you prefer for the application. + Sélectionnez le pack d'icônes que vous préférez pour cette application. + + + + Style + Style + + + + Select the style you prefer for the application. + Sélectionnez le style que vous préférez pour l'application. + + + + Default font + Police par défaut + + + + You can change here the application's font. + Vous pouvez changer ici la police de l'application. + + + + Short jump + Léger saut + + + + Select the time that should be go forward or backward when you choose the %1 action. + Sélectionnez le temps que "avancé" et "reculé" doivent effectués lorsque vous choississez l'action %1. + + + + short jump + saut léger + + + + Medium jump + Saut moyen + + + + medium jump + saut moyen + + + + Long jump + Saut long + + + + long jump + saut long + + + + Mouse wheel jump + Saut de la molette + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Sélectionnez le tempsSélectionnez le temps que "avancé" et "reculé" doivent effectués lorsque vous bougez la molette. + + + + Behaviour of time slider + Comportement de la barre de temps + + + + Select what to do when dragging the time slider. + Sélectionnez ce qui doit être fait lorsque la barre de temps est déplacée. + + + + Use only one running instance of SMPlayer + Utiliser qu'une seule instance pour SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Cochez cette option si vous voulez utiliser qu'une seule instance de SMPlayer. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer a besoin d'écouter les ports pour recevoir les commandes venant de d'autres instances. Vous pouvez changer le port dans le cas où celui par défaut est déjà utilisé par une autre application. + + + + Default GUI + GUI par défaut + + + + Mini GUI + Mini GUI + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Sélectionnez le GUI que vous préférez pour l'application. Actuellement, il y a deux possibilités : Soit le GUI par défaut soit le mini GUI.<br>Le <b>GUI par défaut</b> offre les traditionnelles options avec la barre d'outils et la barre de contrôle. Le <b>Mini GUI</b> offre une interface plus simple, sans les barres d'outils et de contrôles et comprend peu de boutons.<br><b>Note :</b> cette option prendra effet après rechargement de SMPlayer. + + + + &GUI + &GUI + + + + Automatic port + Port automatique + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayers a besoin d'écouter un port pour recevoir les commandes venant de d'autres instances. Si vous sélectionnez cette option, le port sera automatiquement choisi. + + + + Manual port + Port manuel + + + + Port to listen + Port à écouter + + + + &Automatic + &Automatique + + + + &Manual + &Manuel + + + + Floating control + + + + + Animated + Animé + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + Largeur + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + &Animé + + + + &Width: + Lar&geur : + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Performance + + + + &Performance + &Performance + + + + Priority + Priorité + + + + Select the priority for the MPlayer process. + Sélectionnez la priorité du processus MPlayer. + + + + realtime + Temps réel + + + + high + Haut + + + + abovenormal + Au dessus de la normale + + + + normal + Normal + + + + belownormal + Au dessous de la normale + + + + idle + Inactif + + + + Cache + Cache + + + + KB + Ko + + + + Setting a cache may improve performance on slow media + Régler le cache peut améliorer les performances sur les médias lents + + + + Allow frame drop + Activer le saut d'images + + + + Synchronization + Synchronisation + + + + Audio/video auto synchronization + Synchronisation auto audio/video + + + + Fast audio track switching + Changement rapide de pistes audio + + + + Fast seek to chapters in dvds + Sauts de chapitres rapides dans les DVD + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Définir la priorité du processus pour MPlayer.<br><b>ATTENTION :</b> "Temps réel" peut conduire à un blocage du système. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Sauter des images pour conserver la synchronisation Audio/Vidéo sur les systèmes lents. + + + + Allow hard frame drop + Accorder le saut des images erronées + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Saut d'images intense (destructif). Induit des distorsions d'images ! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Ajustement graduel de la synchronisation A/V basé sur les mesures de délai audio. + + + + Priorit&y: + Priori&té : + + + + &Allow frame drop + Permettre le s&aut d'images + + + + Allow &hard frame drop (can lead to image distortion) + Autoriser le saut d'images plus &fort (peut conduire à des distorsions) + + + + Audio/&video auto synchronization + Synchronisation auto audio/&video + + + + Fact&or: + Facte&ur : + + + + &Fast audio track switching + &Changement rapide de pistes audio + + + + Fast &seek to chapters in dvds + &Sauts de chapitres rapides dans les DVD + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Si cette option est cochée, SMPlayer essayera la plus rapide méthode pour rechercher les chapitres mais ne devraient pas marcher avec certains disques. + + + + Skip loop filter + Passer le filtre de boucle + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Valeurs possibles :<br> <b>Oui</b> : Cela essayera la méthode la plus rapide pour alterner la piste audio (cela peut ne pas marcher avec certains formats).<br><b>Non</b> : Le processus de MPlayer se rechargera lorsque vous changez de piste audio.<br> <b>Auto</b> : SMPlayer décidera de lui-même quoi choisir en fonction de la version de MPlayer. + + + + Cache for files + Cache pour les fichiers + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Cette option définit la taille de la mémoire (en ko) prise lors de la précache d'un fichier. + + + + Cache for streams + Cache pour les flux + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Cette option définit la taille de la mémoire (en ko) prise lors de la précache d'une URL. + + + + Cache for DVDs + Cache pour les DVDs + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Cette option définit la taille de la mémoire (en ko) prise lors de la précache d'un DVD. .<br><b>Attention :</b> cette option risque de mal fonctionner. + + + + &Cache + &Cache + + + + Cache for &DVDs: + Cache pour les &DVDs : + + + + Cache for &local files: + Cache pour les fichiers &locaux : + + + + Cache for &streams: + Cache pour le&s flux : + + + + Enabled + Activé + + + + Skip (always) + Passer (toujours) + + + + Skip only on HD videos + Passer seulement sur les vidéos HD + + + + Loop &filter + &Filtre de boucle + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Cette option permet de passer le filtre boucle (alias "deblocking") durant le décodage H.264. Depuis que les filtrées sont supposées être utilisées comme référence pour le décodage des images dépendantes, cela a un pire effet sur la qualité que ne pas utiliser le "deblocking" comme par exemple sur les vidéos MPEG-2. Mais au moins pour les vidéos HDTV à haut débit, cela permet d'avoir une montée en vitesse sans aucune perte de qualité visible. + + + + Possible values: + Valeurs possible : + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Activé<b/> : le filtre boucle ne passera pas + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Passer (toujours)</b> : le fltre boucle passera sans se préoccuper de la résolution de la vidéo + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Passer seulement si vidéos HD</b> : le filtre boucle passera seulement sur les vidéos ayant une largeur de %1 ou plus. + + + + Cache for audio CDs + Cache pour les CDs audios + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Cette option spécifie combien de mémoire (en Ko) doit être réservée pour précacher un CD Audio. + + + + Cache for &audio CDs: + Cache pour les CDs &audios : + + + + Cache for VCDs + Cache pour les VCDs + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Cette option spécifie la quantité de mémoire (en Ko) à utiliser pour précacher un VCD. + + + + Cache for &VCDs: + Cache pour les &VCDs : + + + + Threads for decoding + Threads pour le décodage + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Fixe le nombre de threads pour le décodage. Seulement pour MPEG-1/2 et H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Threads pour le décodage (Seulement pour MPEG-1/2 et H.264) : + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Liste de lecture + + + + Automatically add files to playlist + Ajouter automatiquement les fichiers à la liste de lecture + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + Ajouter consécutivement les fichiers + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Liste de lecture + + + + &Automatically add files to playlist + &Ajouter automatiquement les fichiers à la liste de lecture + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Sous-titres + + + + Choose a ttf file + Choisir un fichier ttf + + + + Truetype Fonts + Polices truetype + + + + &Subtitles + &Sous-titres + + + + Autoload + Chargement automatique + + + + Select first available subtitle + Selectionner le premier sous-titre disponible + + + + Same name as movie + Même nom que la vidéo + + + + All subs containing movie name + Tous les sous-titres contenant le nom de la vidéo + + + + All subs in directory + Tous les sous-titres du dossier + + + + Position + Position + + + + 0 + 0 + + + + Top + Haut + + + + Bottom + Bas + + + + Include subtitles on screenshots + Inclure les sous-titres sur les captures d'écran + + + + Font + Police + + + + Select the font which will be used for subtitles (and OSD): + Sélectionner la police des sous-titres (et OSD) : + + + + Size + Taille + + + + No autoscale + Pas d'échelle automatique + + + + Proportional to movie height + Proportionnel à la hauteur du film + + + + Proportional to movie width + Proportionnel à la largeur du film + + + + Proportional to movie diagonal + Proportionnel à la diagonale du film + + + + Subtitle position + Position du sous-titrage + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Cette option spécifie la position des sous-titres par rapport à la fenêtre. <i>100</i> veut dire le bas, et <i>0</i> le haut. + + + + Au&toload subtitles files (*.srt, *.sub...): + &Charger automatiquement les sous-titrages (*.srt, *.sub...) : + + + + S&elect first available subtitle + S&electionner le premier sous-titrage disponible + + + + &Default subtitle encoding: + Encodage par d&éfaut des sous-titres : + + + + Default &position of the subtitles on screen + &Position par défaut des sous-titres sur l'écran + + + + &Include subtitles on screenshots + &Inclure les sous-titres sur les captures d'écran + + + + &TTF font: + Police &TTF : + + + + S&ystem font: + Police du s&ystème : + + + + A&utoscale: + Echelle a&utomatique : + + + + Default subtitle encoding + Encodage par défaut des sous-titres + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Si vous cochez cette option, les sous-titres apparaîtront dans les captures d'images. Note : cela peut des fois poser problèmes. + + + + TTF font + Police TTF + + + + System font + Police de l'OS + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Ici, vous pouvez sélectionner la police du système pour être utilisée en sous-titrage et OSD. <b>Note :</b> ceci requiert un MPlayer avec le support de fontconfig. + + + + Autoscale + Echelle automatique + + + + Text color + Couleur du texte + + + + Select the color for the text of the subtitles. + Sélectionnez la couleur de texte des sous-titres. + + + + Border color + Couleur de la bordure + + + + Select the color for the border of the subtitles. + Sélectionnez la couleur de bordure des sous-titres. + + + + Select the subtitle autoload method. + Sélectionnez la méthode de préchargement des sous-titres. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + S'il y a un ou plusieurs sous-titres disponible, l'un d'eux sera automatiquement sélectionné, généralement le premier sauf si l'un d'eux correspond au langage préférencié de l'utilsateur. + + + + Select the subtitle autoscaling method. + Sélectionnez la méthode d'échelle automatique des sous-titres. + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + Bas + + + + Middle + vertical alignment + + + + + Top + vertical alignment + Haut + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Aide + + + + OK + OK + + + + Cancel + Annuler + + + + Apply + Appliquer + + + + Help + Aide + + + + SMPlayer - Preferences + SMPlayer - Préférences + + + + QObject + + + This is SMPlayer v. %1 running on %2 + SMPlayer v. %1 fonctionnant sur %2 + + + + the main window will be closed when the file/playlist finishes. + la fenêtre principale sera fermée lorsque le fichier ou la liste de lecture sera fini(e). + + + + will show this message and then will exit. + montrera un message et quittera. + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + essaye de faire une connexion avec une autre instance et lui envoie l'action spécifiée. Exemple : -action pause Le reste des options (s'il y en a) seront ignorés et l'application quittera. Cela retournera 0 si succès, et -1 si erreur. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list est une liste d'actions séparées par des espaces. Ces actions seront exécutées juste après le fichier dans l'ordre dans lequel vous l'avez tapé. Pour les actions cochables, vous pouvez écrire "true" ou "false" en tant que paramètre. Exemple : -actions "fullscreen compact true". Les guillemets sont nécessaires si vous écrivez plus d'une action. + + + + media + Media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + Si une autre instance est en cours, le media sera ajouté à la liste de lecture de l'instance. Si il n'y a pas d'autre instance, l'option sera ignorée et les fichiers seront ouverts dans la nouvelle instance. + + + + the main window won't be closed when the file/playlist finishes. + la fenêtre principale ne se fermera pas lorsque le fichier ou la liste de lecture sera fini(e). + + + + the video will be played in fullscreen mode. + la video sera lue en plein écran. + + + + the video will be played in window mode. + la vidéo sera lue en mode fenêtre. + + + + Enqueue in SMPlayer + En queue dans SMPlayer + + + + opens the mini gui instead of the default one. + ouvre la mini-interface au lieu de celle par défaut. + + + + Restores the old associations and cleans up the registry. + Restaure les vieilles associations et nettoie le registre. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' est n'importe quel fichier que SMPlayer peut ouvrir. Cela peut être un fichier local, un DVD (ex : dvd://1), un stream internet (ex : mms://....) ou une liste de lecture locale au format m3u ou pls. Si l'option "-playlist" est utilisée, cela veut dire que SMPlayer donnera l'option "-playlist" à MPlayer, alors MPlayer comprendra la liste de lecture, non pas SMPlayer. + + + + Usage: + Usage : + + + + directory + Dossier + + + + action_name + nom_action + + + + action_list + liste_action + + + + opens the default gui. + ouvre le GUI par défaut. + + + + subtitle_file + fichier_soustitre + + + + specifies the subtitle file to be loaded for the first video. + spécifie le fichier sous-titre qui doit être chargé pour la première vidéo. + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + %1 et %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + désactivé + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + Icône + + + + label + Label + + + + ShortcutGetter + + + Modify shortcut + Modifier raccourci + + + + Clear + Effacer + + + + Press the key combination you want to assign + Appuyez sur la combinaison de touches que vous voulez assigner + + + + Capture + Capturer + + + + Capture keystrokes + Enregistrer les frappes clavier + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + Tous les sélectionner + + + + Select None + Sélectionner aucun + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Recherche + + + + &Jump to: + &Sauter à : + + + + TristateCombo + + + Auto + Auto + + + + Yes + Oui + + + + No + Non + + + + VideoEqualizer + + + Contrast + Contraste + + + + Brightness + Luminosité + + + + Hue + Ton + + + + Saturation + Saturation + + + + Gamma + Gamma + + + + &Reset + &Reset + + + + &Set as default values + Choi&sir en tant que valeur par défaut + + + + Use the current values as default values for new videos. + Utiliser les valeurs actuelles comme valeurs par défaut pour les nouvelles vidéos. + + + + Set all controls to zero. + Mettre tous les contrôles à zéro. + + + + Video Equalizer + Equaliseur vidéo + + + + Information + Information + + + + The current values have been stored to be used as default. + Les valeurs courantes ont été stockées pour être utilisées par défaut. + + + + VideoPreview + + + Video preview + + + + + Cancel + Annuler + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Erreur lors de la sauvegarde + + + + The file couldn't be saved + Ce fichier n'a pas pu être sauvegardé + + + + Error + Erreur + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + Aspect ratio : %1 + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Défaut + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Volume + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_gl.ts b/plugins/smplayer_plugin/translations/smplayer_gl.ts new file mode 100644 index 000000000..c84d53355 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_gl.ts @@ -0,0 +1,7329 @@ + + + + About + + + Version: %1 + Versión: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Este programa é software libre así que pode redistribuilo e/ou modificalo baixo os termos da GNU General Public Licese tal é como a publica a Free Software Foundation, tanto na súa versión 2 coma nas seguintes, a súa bontade. + + + + The following people have contributed with translations: + As seguintes persoas contribuiron con traducións: + + + + German + Alemán + + + + Slovak + Eslovaco + + + + Italian + Italiano + + + + French + Francés + + + + %1, %2 and %3 + %1, %2 e %3 + + + + Simplified-Chinese + Chinés Simplificado + + + + Russian + Ruso + + + + %1 and %2 + %1 e %2 + + + + Hungarian + Húngaro + + + + Polish + Polaco + + + + Japanese + Xaponés + + + + Dutch + Neerlandés + + + + Ukrainian + Ucraíno + + + + Portuguese - Brazil + Portugués do Brasil + + + + Georgian + Xeorxiano + + + + Czech + Checo + + + + Bulgarian + Bulgaro + + + + Turkish + Turco + + + + Swedish + Sueco + + + + Serbian + Serbio + + + + Traditional Chinese + Chinés Tradicional + + + + Romanian + Romanés + + + + Portuguese - Portugal + Portugués do Portugal + + + + Greek + Grego + + + + Finnish + Finés + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Sobre do SMPlayer + + + + &Info + &Info + + + + icon + Icona + + + + &Contributions + &Contribucións + + + + &Translators + &Traducións + + + + &License + &Licenza + + + + Visit our web for updates: + Visite a web parta actualizacións: + + + + Get help in our forum: + Obteña axuda no foro: + + + + You can support SMPlayer by making a donation. + Pode axudar a que se sega densenvolvendo o SMPlayer facendo unha doazón. + + + + More info + Máis información + + + + Korean + Coreano + + + + Macedonian + Macedonio + + + + Basque + Éuscaro + + + + Using MPlayer %1 + Usando MPlayer %1 + + + + Catalan + Catalán + + + + Portable Edition + Edición Portatil + + + + Using Qt %1 (compiled with Qt %2) + Usando Qt %1 (compilado con Qt %2) + + + + Slovenian + Esloveno + + + + Arabic + Árabe + + + + Kurdish + Curdo + + + + Galician + Galego + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Nome + + + + Description + Descripción + + + + Shortcut + Atallo + + + + &Save + &Gravar + + + + &Load + &Cargar + + + + Key files + Ficheiros de atallos + + + + Choose a filename + Escolla o nome do ficheiro + + + + Confirm overwrite? + Quere sobreescribir? + + + + The file %1 already exists. +Do you want to overwrite? + O ficheiro %1 xa existe. +Seguro que quere sobreescribilo? + + + + Choose a file + Escolla un nome para o ficheiro + + + + Error + Erro + + + + The file couldn't be saved + Non se pode gravar o ficheiro + + + + The file couldn't be loaded + Non se puido cargar o ficheiro + + + + &Change shortcut... + &Cambiar Atallo... + + + + AudioEqualizer + + + Audio Equalizer + Equalizador de Audio + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Aplicar + + + + &Reset + &Restaurar + + + + &Set as default values + &Empregar coma valores predefinidos + + + + Use the current values as default values for new videos. + Emprega os valores actuais coma os valores predefinidos para os novos vídeos. + + + + Set all controls to zero. + Poñer tódolos controis a cero. + + + + Information + Información + + + + The current values have been stored to be used as default. + Gravaronse os valores actuais para empregalos como por defecto. + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - rexistro de mplayer + + + + SMPlayer - smplayer log + SMPlayer - rexistro de smplayer + + + + &Open + &Abrir + + + + &Play + &Reproducir + + + + &Video + &Vídeo + + + + &Audio + &Audio + + + + &Subtitles + Sub&títulos + + + + &Browse + &Navegar + + + + Op&tions + &Configuracións + + + + &Help + &Axuda + + + + &File... + &Ficheiro... + + + + D&irectory... + &Cartafol... + + + + &Playlist... + &Lista de Reprodución... + + + + &DVD from drive + &DVD dende Lector + + + + D&VD from folder... + D&VD dende Cartafol... + + + + &URL... + &URL... + + + + &Clear + &Limpar + + + + &Recent files + Ficheiros Rec&entes + + + + P&lay + &Reproducir + + + + &Pause + &Pausa + + + + &Stop + &Parar + + + + &Frame step + &Avanzar Fotograma + + + + &Normal speed + Velocidade &Normal + + + + &Halve speed + &Reducir á Metade + + + + &Double speed + &Dobrar a Velocidade + + + + Speed &-10% + Velocidade &-10% + + + + Speed &+10% + Velocidade &+10% + + + + Sp&eed + &Velocidade + + + + &Repeat + Re&petir + + + + &Fullscreen + &Pantalla Completa + + + + &Compact mode + &Modo Compacto + + + + Si&ze + &Tamaño + + + + 4:3 &Letterbox + Formatod e Axuste &4:3 + + + + 16:9 L&etterbox + Formato de Axuste 1&6:9 + + + + 4:3 &Panscan + &Panscan 4:3 + + + + 4:3 &to 16:9 + De 4:3 &a 16:9 + + + + &Aspect ratio + &Proporcións de Aspecto + + + + &None + &Ningún + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + &Mestura Linear + + + + &Deinterlace + &Desntralazar + + + + &Postprocessing + &Postprocesado + + + + &Autodetect phase + &Autodetección de Fase + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + Engadir &Ruido + + + + F&ilters + &Filtros + + + + &Equalizer + &Ecualizador + + + + &Screenshot + &Captura + + + + S&tay on top + &Manter Enriba + + + + &Extrastereo + &Extra-estéreo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtros + + + + &Stereo + E&stéreo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Canles + + + + &Left channel + Canle &Esquerda + + + + &Right channel + Canle &Dereita + + + + &Stereo mode + Modo Es&téreo + + + + &Mute + &Silenciar + + + + Volume &- + Volume &- + + + + Volume &+ + Volume &+ + + + + &Delay - + &Atrasar + + + + D&elay + + Atras&o + + + + + &Select + &Escoller + + + + &Load... + &Cargar... + + + + Delay &- + Atraso &- + + + + Delay &+ + Atraso &+ + + + + &Up + Poñer En&riba + + + + &Down + Poñer Em&baixo + + + + &Title + &Título + + + + &Chapter + &Capítulo + + + + &Angle + &Ángulo + + + + &Playlist + &Lista de Reprodución + + + + &Show frame counter + &Contador de Fotogramas + + + + &Disabled + &Desactivado + + + + &Seek bar + &Barra de Procura + + + + &Time + &Tempo + + + + Time + T&otal time + Tempo + Tempo &Total + + + + &OSD + &OSD + + + + &View logs + Ver &Rexistros + + + + P&references + &Configuracións + + + + About &Qt + Sobre de &Qt + + + + About &SMPlayer + Sobre do &SMPlayer + + + + <empty> + <vacío> + + + + Video + Vídeo + + + + Audio + Audio + + + + Playlists + Listas de reprodución + + + + All files + Tódolos Ficheiros + + + + Choose a file + Escolla un Ficheiro + + + + SMPlayer - Information + SMPlayer - Información + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + As unidades de CDROM / DVD ainda non foron configuradas. +Vaise mostrar o diálogo de configuración agora para que o poida facer. + + + + Choose a directory + Escolla un Cartafol + + + + Subtitles + Subtítulos + + + + About Qt + Sobre de Qt + + + + Playing %1 + Reproducindo %1 + + + + Pause + Pausa + + + + Stop + Parar + + + + Play / Pause + Preproducir / Pausa + + + + Pause / Frame step + Pausa / Avanzar Fotograma + + + + U&nload + &Descargar + + + + V&CD + V&CD + + + + C&lose + &Pechar + + + + View &info and properties... + Ver &Información e Propiedades... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Reiniciar + + + + Move &left + Mover cara á &Esquerda + + + + Move &right + Mover cara á &Dereita + + + + Move &up + Desprazar cara a &Riba + + + + Move &down + Desparazar cara a &Abaixo + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + Liña &Anterior + + + + N&ext line in subtitles + Liña &Seguinte + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Baixar Volume (2) + + + + Inc volume (2) + Aumentar Volume (2) + + + + Exit fullscreen + Saír da Pantalla Completa + + + + OSD - Next level + OSD - Seguiente nivel + + + + Dec contrast + Baixar Contraste + + + + Inc contrast + Aumentar Contraste + + + + Dec brightness + Baixar Brillo + + + + Inc brightness + Aumentar Brillo + + + + Dec hue + Baixar Tonalidade + + + + Inc hue + Aumentar Tonalidade + + + + Dec saturation + Baixar Saturación + + + + Dec gamma + Baixar Gamma + + + + Next audio + Audio Seguinte + + + + Next subtitle + Subtítulo Seguinte + + + + Next chapter + Seguinte Capítulo + + + + Previous chapter + Capítulo Anterior + + + + Inc saturation + Aumentar Saturación + + + + Inc gamma + Aumentar Gamma + + + + &Load external file... + Cargar un Ficheiro E&xterno... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normal) + + + + Y&adif (double framerate) + Y&adif (framerate dobre) + + + + &Next + &Seguinte + + + + Pre&vious + &Anterior + + + + Volume &normalization + &Normalización do Volume + + + + &Audio CD + &Audio CD + + + + Denoise nor&mal + Reducir Ruido &Normal + + + + Denoise &soft + Reducir Ruido &Suave + + + + Denoise o&ff + Reducir Ruido &Desactivado + + + + Use SSA/&ASS library + Emprega-la Librería SSA/&ASS + + + + Flip i&mage + Imaxe &Invertida + + + + &Toggle double size + &Conmutar Tamaño Dobre + + + + S&ize - + Tamaño &- + + + + Si&ze + + Tamaño &+ + + + + Add &black borders + Engadir &Bordes Negros + + + + Soft&ware scaling + Dimensionado de Soft&ware + + + + &FAQ + Preguntas &Frecuentes + + + + Visualize &motion vectors + Visualizar &vectores de animación + + + + &Command line options + Configuracións da Liña de &Comandos + + + + SMPlayer command line options + Liña de comandos de SMPlayer + + + + Enable &closed caption + Activar subtítulos para &xordos + + + + &Forced subtitles only + Mostrar só os subtítulos &forzados + + + + Reset video equalizer + Redefinir o ecualizador de video + + + + MPlayer has finished unexpectedly. + O MPlayer rematou inesperadamente. + + + + Exit code: %1 + Código de saída: %1 + + + + MPlayer failed to start. + Falla ó iniciar o MPlayer. + + + + Please check the MPlayer path in preferences. + Asegúrese de que nas Configuración a rota ó MPlayer está correctamente. + + + + MPlayer has crashed. + Fallou o MPlayer. + + + + See the log for more info. + Comprobe o rexistro para obter máis información. + + + + &Rotate + &Virar + + + + &Off + &Desactivado + + + + &Rotate by 90 degrees clockwise and flip + Virar 90º no sentido horario e darlle a &volta + + + + Rotate by 90 degrees &clockwise + Virar 90º en sentido &horario + + + + Rotate by 90 degrees counterclock&wise + Virar 90º en sentido &antihorario + + + + Rotate by 90 degrees counterclockwise and &flip + Virar 90º en sentido anti&horario e darlle a volta + + + + &Jump to... + &Ir a... + + + + Show context menu + Mostrar o menú de contexto + + + + Multimedia + Multimedia + + + + E&qualizer + &Ecualizador + + + + Reset audio equalizer + Restaurar o ecualizador de son + + + + Find subtitles on &OpenSubtitles.org... + Procurar Subtítulos ee &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Enviar subtítulos a &OpenSubtitles.org... + + + + &Tips + &Consellos + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Mirr&or image + + + + + Scree&n + + + + + &Auto + + + + + &Default + + + + + Next video + + + + + &Track + video + &Pista + + + + &Track + audio + &Pista + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + O SMPlayer inda se está a executar + + + + S&how icon in system tray + &Mostrar a icona na área de notificacións + + + + &Hide + &Agochar + + + + &Restore + &Restaurar + + + + &Quit + &Saír + + + + Playlist + Lista de Reprodución + + + + Core + + + Brightness: %1 + Brillo: %1 + + + + Contrast: %1 + Contraste. %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Tonalidade: %1 + + + + Saturation: %1 + Saturación; %1 + + + + Volume: %1 + Volume: %1 + + + + Zoom: %1 + Ampliación: %1 + + + + Font scale: %1 + Escala da Tipografía: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Benvido ó SMPlayer + + + + Audio + Audio + + + + Subtitle + Subtítulo + + + + &Main toolbar + Barra &Principal + + + + &Language toolbar + Ferramentas da &Lingua + + + + &Toolbars + &Barra de Ferramentas + + + + EqSlider + + + icon + icona + + + + ErrorDialog + + + Hide log + Agochar rexistro + + + + Show log + Mostrar rexistro + + + + MPlayer Error + Erro do MPlayer + + + + icon + icona + + + + Error + Erro + + + + FileDownloader + + + Downloading... + Descargando... + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Propidedades de ficheiro + + + + &Information + &Información + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Escolla o demuxer que queira empregar para este ficheiro: + + + + &Reset + &Reiniciar + + + + &Video codec + Codec de &Video + + + + &Select the video codec: + &Escolla o Codec de Vídeo: + + + + A&udio codec + Codec de &Audio + + + + &Select the audio codec: + &Escolla o Codec de Audio: + + + + &MPlayer options + Configuracións do &MPlayer + + + + Additional Options for MPlayer + Opcións Extra do MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Pode introducir aquí configuracións extra do MPlayer. +Escríbaas separadas por espazos. +Por exemplo: -flip -nosound + + + + &Options: + &Configuracións: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Pode pasar filtros de vídeo adicionais. +Sepáreos con ",". Non empregue espazos! +Por exemplo: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + Filtros de V&ídeo: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + E dinalmento filtros de audio. As regras son as mesmas que para os filtros de video. +Por exemplo: resample=44100:0:0,volnorm + + + + Audio &filters: + Filtros de Au&dio: + + + + OK + Aceptar + + + + Cancel + Cancelar + + + + Apply + Aplicar + + + + FindSubtitlesWindow + + + Language + Lingua + + + + Name + Nome + + + + Format + Formato + + + + Files + Ficheiros + + + + Date + Data + + + + Uploaded by + Enviado por + + + + All + Todos + + + + Close + Pechar + + + + &Download + &Descargando + + + + &Copy link to clipboard + &Copiar a Ligazón no Portaretallos + + + + Error + Erro + + + + Download failed: %1. + Descarga fallida: %1. + + + + Connecting to %1... + Conectando con %1... + + + + Downloading... + Descargando... + + + + Done. + Feito. + + + + %1 files available + %1 ficheiros dispoñibles + + + + Failed to parse the received data. + Houbo un erro ó analizar os datos recibidos. + + + + Find Subtitles + Procurar Subtítulos + + + + &Subtitles for + &Subtítulos para + + + + &Language: + &Lingua: + + + + &Refresh + &Anovar + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Non se puido gravar o ficheiro + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Xeral + + + + Size + Tamaño + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Duración + + + + Demuxer + Demuxer + + + + Name + Nome + + + + Artist + Artista + + + + Author + Autor + + + + Album + Álbum + + + + Genre + Xénero + + + + Date + Data + + + + Track + Pista + + + + Copyright + Copyright + + + + Comment + Comentario + + + + Software + Software + + + + Clip info + Información do clip + + + + Video + Video + + + + Resolution + Resolución + + + + Aspect ratio + Ratio de Aspecto + + + + Format + Formato + + + + Bitrate + Bitrate + + + + %1 kbps + %1 kbps + + + + Frames per second + Fotogramas por segundo + + + + Selected codec + Codec escollido + + + + Initial Audio Stream + Pista de audio inicial + + + + Rate + Calidade + + + + %1 Hz + %1 Hz + + + + Channels + Canles + + + + Audio Streams + Fluxos de Audio + + + + Language + Lingua + + + + empty + baleiro + + + + Subtitles + Subtitulos + + + + Type + Tipo + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Título do Fluxo + + + + Stream URL + URL do Fluxo + + + + File + Ficheiro + + + + InputDVDDirectory + + + Choose a directory + Escolla un cartafol + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Reproducir un DVD dende un cartafol + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Pode reproducir un DVD dende o disco duro. Soamente ten que escoller o cartafol onde se atopan os ficheiros VIDEO_TS e AUDIO_TS. + + + + Choose a directory... + Escoller un Cartafol... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Introduza a versión do MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + O SMPlayer non deu identificado a versión do MPlayer que está a usar. + + + + Version reported by MPlayer: + Versión que o MPlayer dá: + + + + Please, &select the correct version: + &Escolla a versión correcta: + + + + 1.0rc1 or older + 1.0rc1 ou máis vella + + + + 1.0rc2 + 1.0RC2 + + + + Greater than 1.0rc2 + Máis nova ca 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Introduza unha URL + + + + &URL: + &URL: + + + + It's a &playlist + É unha lista de re&produción + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Marcando esta opción a URL será tratada coma se for unha lista de reprodución, abrirase coma texto e tocarase tódalas URLs existentes. + + + + Languages + + + Afar + Afar + + + + Abkhazian + Abzaxio + + + + Afrikaans + Afrikaans + + + + Amharic + Amárico + + + + Arabic + Árabe + + + + Assamese + Assamese + + + + Aymara + Aimara + + + + Azerbaijani + Acerbaixano + + + + Bashkir + Bashkir + + + + Byelorussian + Bierloruso + + + + Bulgarian + Búlgaro + + + + Bihari + Bihari + + + + Bislama + Bislama + + + + Bengali + Bengalí + + + + Tibetan + Tibetano + + + + Breton + Bretón + + + + Catalan + Catalán + + + + Corsican + Corso + + + + Czech + Checo + + + + Welsh + Galés + + + + Danish + Danés + + + + German + Alemán + + + + Bhutani + Butaní + + + + Greek + Grego + + + + English + Inglés + + + + Esperanto + Esperanto + + + + Spanish + Español + + + + Estonian + Estonio + + + + Basque + Éuscaro + + + + Persian + Persa + + + + Finnish + Finés + + + + Fiji + Fidxi + + + + Faroese + Feroés + + + + French + Francés + + + + Frisian + Frisón + + + + Irish + Irlandés + + + + Scots + Escocés (Scots) + + + + Galician + Galego + + + + Guarani + Guaraní + + + + Gujarati + Guzerate + + + + Hausa + Hausa + + + + Hebrew + Hebreo + + + + Hindi + Hindi + + + + Croatian + Croata + + + + Hungarian + Húngaro + + + + Armenian + Armenio + + + + Interlingua + Interlingua + + + + Indonesian + Indonesio + + + + Interlingue + Interlingua + + + + Inupiak + Inupiak + + + + Icelandic + Islandés + + + + Italian + Italiano + + + + Inuktitut + Inuktitut + + + + Japanese + Xaponés + + + + Javanese + Xavanés + + + + Georgian + Xeorxiano + + + + Kazakh + Casaco + + + + Greenlandic + Groenlandés + + + + Cambodian + Cambodiano + + + + Kannada + Canará + + + + Korean + Coreano + + + + Kashmiri + Caxemira + + + + Kurdish + Curdo + + + + Kirghiz + Quirguís + + + + Latin + Latín + + + + Lingala + Lingala + + + + Laothian + Laociano + + + + Lithuanian + Lituano + + + + Latvian + Letón + + + + Malagasy + Malgasi + + + + Maori + Maorí + + + + Macedonian + Macedonio + + + + Malayalam + Malayalam + + + + Mongolian + Mongol + + + + Moldavian + Moldavo + + + + Marathi + Marathi + + + + Malay + Malaio + + + + Maltese + Maltés + + + + Burmese + Burmese + + + + Nauru + Nauru + + + + Nepali + Nepalí + + + + Dutch + Neerlandés + + + + Norwegian + Noruegués + + + + Occitan + Ocitano + + + + Oriya + Oriya + + + + Punjabi + Punjabi + + + + Polish + Polaco + + + + Pashto + Pashto + + + + Portuguese + Portugués + + + + Quechua + Quechua + + + + Kirundi + Kirundi + + + + Romanian + Romanés + + + + Russian + Ruso + + + + Kinyarwanda + Ruanda + + + + Sanskrit + Sánscrito + + + + Sindhi + Sindhi + + + + Sangho + Sangho + + + + Sinhalese + Cingalés + + + + Slovak + Eslovaco + + + + Slovenian + Esloveno + + + + Samoan + Samoés + + + + Shona + Shona + + + + Somali + Somalí + + + + Albanian + Albanés + + + + Serbian + Serbio + + + + Siswati + Siswati + + + + Sesotho + Sesotho + + + + Sundanese + Sundanés + + + + Swedish + Sueco + + + + Swahili + Suahili + + + + Tamil + Tamil + + + + Telugu + Telugu + + + + Tajik + Taxico + + + + Thai + Tai + + + + Tigrinya + Tigrinya + + + + Turkmen + Turcomano + + + + Tagalog + Tagalog + + + + Setswana + Setswana + + + + Tonga + Tonga + + + + Turkish + Turco + + + + Tsonga + Tsonga + + + + Tatar + Tártaro + + + + Twi + Twi + + + + Uighur + Uighur + + + + Ukrainian + Ucraino + + + + Urdu + Urdu + + + + Uzbek + Uzbeco + + + + Vietnamese + Vietnamita + + + + Wolof + Wolof + + + + Xhosa + Xhosa + + + + Yiddish + Yiddish + + + + Yoruba + Yoruba + + + + Zhuang + Zhuang + + + + Chinese + Chinés + + + + Zulu + Zulu + + + + Portuguese - Brazil + Portugués do Brasil + + + + Portuguese - Portugal + Portugués do Portugal + + + + Simplified-Chinese + Chinés Simplificado + + + + Traditional Chinese + Chinés Tradicional + + + + Unicode + Unicoide + + + + UTF-8 + UTF-8 + + + + Western European Languages + Linguas da Europa Occidental + + + + Western European Languages with Euro + Linguas Europeas Occidentais con Euro + + + + Slavic/Central European Languages + Linguas Europeas Centrais e Eslavas + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galego, Maltés, Turco + + + + Old Baltic charset + Caracteres Bálticos Antigos + + + + Cyrillic + Cirílico + + + + Modern Greek + Grego Moderno + + + + Baltic + Báltico + + + + Celtic + Céltico + + + + Hebrew charsets + Caracteres Hebreos + + + + Ukrainian, Belarusian + Ucraino, Bierloruso + + + + Simplified Chinese charset + Caracteres do Chinés Simplificado + + + + Traditional Chinese charset + Caracteres do Chinés Tradicional + + + + Japanese charsets + Caracteres Xaponeses + + + + Korean charset + Caracteres Coreanos + + + + Thai charset + Caracteres Tailandeses + + + + Cyrillic Windows + Cirílico Windows + + + + Slavic/Central European Windows + Europeo Central ou Eslavo, Windows + + + + Arabic Windows + Árabe, Windows + + + + Rhaeto-Romance + Reto-Románico + + + + Serbo-Croatian + Serbocroata + + + + Volapük + Volapük + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Escolla un nome de ficheiro para gravar + + + + Confirm overwrite? + Quere sobreescribirlo? + + + + The file already exists. +Do you want to overwrite? + Xa existe este ficheiro, Quere sobreescribilo? + + + + Error saving file + Non se puido gravar o ficheiro + + + + The log couldn't be saved + Non se puido gravar o rexistro + + + + Logs + Rexistros + + + + LogWindowBase + + + Log Window + Fiestra de Rexistro + + + + Save + Gravar + + + + Copy to clipboard + Copiar ó Portaretallos + + + + &Close + &Pechar + + + + Close + Pechar + + + + MiniGui + + + Control bar + Barra de control + + + + MpcGui + + + Control bar + Barra de control + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nome + + + + Length + Duración + + + + &Play + &Reproducir + + + + &Edit + &Editar + + + + Playlists + Listas de Reprodución + + + + Choose a file + Escolla un Ficheiro + + + + Choose a filename + Escolla un Nome de Ficheiro + + + + Confirm overwrite? + Quere Sobreescribir? + + + + The file %1 already exists. +Do you want to overwrite? + O ficheiro %1 xa existe. +Seguro que quere sobreescribilo? + + + + All files + Tódolos Ficheiros + + + + Select one or more files to open + Escolla Un ou Máis Ficheiros para Abrir + + + + Choose a directory + Escolla un Cartafol + + + + Edit name + Editar Nome + + + + Type the name that will be displayed in the playlist for this file: + Teclee o nome que se mostrara na lista de resprodución para este ficheiro: + + + + &Load + &Cargar + + + + &Save + &Gravar + + + + &Next + &Seguinte + + + + Pre&vious + An&terior + + + + Move &up + Su&bir + + + + Move &down + Bai&xar + + + + &Repeat + &Repetir + + + + S&huffle + Me&sturar + + + + Add &current file + Engadri-lo Ficheiro &Actual + + + + Add &file(s) + Engadir &Ficheiro + + + + Add &directory + Engadir &Cartafol + + + + Remove &selected + Elimina-lo &Escollido + + + + Remove &all + Eliminar &Todo + + + + SMPlayer - Playlist + SMPlayer - Lista de Reprodución + + + + Add... + Engadir... + + + + Remove... + Eliminar... + + + + Playlist modified + Lista de Reprodución Modificada + + + + There are unsaved changes, do you want to save the playlist? + Hai cambios que non se gravaron. Quere gravar a lista de reprodución? + + + + Preferences + Preferencias + + + + PlaylistPreferences + + + Playlist - Preferences + Lista de Reprodución - Preferencias + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Marcando esta opción permite que ó engadir un cartafol se procure en tódolos cartafoles que haxa dentro e se engada o seu contido. De non a marcar, só se engaden os ficheiros que aparezan no cartafol principal. + + + + &Add files in directories recursively + &Engadir os Ficheiros dos Cartafoles + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Marque esta opción para engadir á lista de reprodución a información sobre dos ficheiros. Isto permite que se mostre o título, sempre que estea dispoñible, e a duración dos ficheiros. No caso contrario esta información non vai estar dispoñible. Teña en conta que esta operación pode ser retrasada, especialmente no caso de que se engada moitos ficheiros. + + + + Automatically get &info about files added + Obter &Iformación Sobre dos Ficheiros Engadidos Automaticamente + + + + &Save copy of playlist on exit + &Gravar unha Copia da Lista de Reprodución ó Saír + + + + &Play files from start + Reproducir Ficheiros do &Inicio + + + + PrefAdvanced + + + Advanced + Avanzado + + + + Auto + Automático + + + + &Advanced + &Avanzado + + + + icon + Icona + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aquí pode introducir opcións extra para o MPlayer. +Escríbaas separadas con espazos. +Exemplo: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Pode introducir tamén filtros de video extra. +Sepáreos con ",". Non empregue espazos! +Exemplo: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + E finalmente os filtros de audio. As mesmas regras ca nos videos. +Exemplo: resample=44100:0:0,volnorm + + + + Log MPlayer output + Saída do MPlayer + + + + Log SMPlayer output + Rexistro de Saída do SMPlayer + + + + This option is mainly intended for debugging the application. + Esta opción está pensada para depurar a aplicacións. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Activando esta opción hase reducir o cintileo, mai tamén poida que o video non se mostre correctamente. + + + + Filter for SMPlayer logs + Filtro para os rexistros do SMPlayer + + + + &Monitor aspect: + Aspecto do &Monitor: + + + + &Run MPlayer in its own window + &Iniciar o MPlayer nunha Fiestra de Seu + + + + &Options: + &Configuracións: + + + + V&ideo filters: + Filtros de víd&eo: + + + + Audio &filters: + Filtros de &Audio: + + + + &Colorkey: + &Conxunto de cores: + + + + Log &SMPlayer output + Rexistro de Saída do &SMPlayer + + + + &Filter for SMPlayer logs: + &Filtro para os rexistros do SMPlayer: + + + + C&hange... + Ca&mbiar... + + + + Logs + Rexistros + + + + Log MPlayer &output + Rexistro de &Saídas do MPlayer + + + + Options for MP&layer + Configuracións do MP&layer + + + + Autosave MPlayer log + Gravado Automático do Rexistro de MPlayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + No caso de marcar esta opción o rexistro do MPlayer gravarase a un ficheiro que se especifique cada verz que se comeze a reproducir un novo ficheiro. Está destinado ás aplicacións externas que queiran obter información acerca do que está a reproducir. + + + + Autosave MPlayer log filename + Gravar Automáticamente o Nome do Rexistro de MPlayer + + + + Enter here the path and filename that will be used to save the MPlayer log. + Introduza aquí a dirección e o nome do ficheiro para garda-los rexistros do MPlayer. + + + + A&utosave MPlayer log to file + G&ravado Automático do Rexistro de MPlayer + + + + Pass short filenames (8+3) to MPlayer + Pasar nomes de ficheiros curtos (8+3) ó MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Actualmenete o MPLayer non he quen de abrir ficheirows que conteñan caractes que non pertenzan ó código local. Marque esta opción se quere que SMPlayer lle pase ó MPLayer a versión reducida dos nomes para que este os dea aberto. + + + + &Pass short filenames (8+3) to MPlayer + &Pasar nomes de ficheiros curtos (8+3) ó MPlayer + + + + Monitor aspect + Aspecto do Monitor + + + + Select the aspect ratio of your monitor. + Escolla o ratio de aspecto do seu monitor. + + + + Run MPlayer in its own window + Executar o MPlayer nunha fiestra de seu + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Se marca esta opción a fiestra de video do MPLayer non se incrusta dentro da interface principal do SMPlayer senón que emprega a súa propia fiestra. Entenda que o rato e o teclado serán dirixidos directamente por MPlayer, isto é, que os atallos e os xestos do rato non van traballar como espera cando a fiestra do MPlayer estea en primeiro plano. + + + + Colorkey + Conxunto de Cores + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Se ves partes do video por riba doutra fiestra pode cambiar o espazo de cores para solventalo. Intenta escoller unha cor preto do negro. + + + + Options for MPlayer + Configuracións do MPlayer + + + + Options + Configuracións + + + + Here you can type options for MPlayer. Write them separated by spaces. + Pode engadir opcións para o MPlayer aquí. Teñen que ir separadas por espazos. + + + + Video filters + Filtros de vídeo + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Pode engadir filtros de video para o MPlayer aquí. Escríbaos separados por comas e on use espazos! + + + + Audio filters + Filtro de Audio + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Pode engadir filtros de audio para o MPlayer aquí. Escríbaos separados por comas e on use espazos! + + + + Repaint the background of the video window + Redebuxar o fondo da fiestra de video + + + + Repaint the backgroun&d of the video window + Redebuxar o &fondo da xanela de video + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Rebuild index if needed + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Recontrúe o índice de ficheiros no caso de que non se atope, permitindo a procura. é útil para descargas incompletas, escangalladas ou mal creadas. Esta opción só funciona se o medio permite a procura (p.ex. non con stdin, pipe...).<br>Nota: a creación do índice pode levar algún tempo. + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Rebuild &index if needed + + + + + Lo&gs + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Tipo + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Advertencia + + + + Not all files could be associated. Please check your security permissions and retry. + Non se deu asociado tódolos ficheiros. Comprobe os permisos de seguridade e probe de novo. + + + + File Types + Tipo de Ficheiro + + + + Select all + Escoller Todo + + + + Check all file types in the list + Marcar tódolos ficheiros da lista + + + + Uncheck all file types in the list + Deseleccionar tódolos ficheiros da lista + + + + List of file types + Lista do tipo de ficheiros + + + + File types + Tipo de ficheiros + + + + Media files handled by SMPlayer: + Ficheiros manexados polo SMPlayer: + + + + Select All + Escoller Todo + + + + Select None + Deseleccionar Todo + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Marque as extensións de ficheiro que queira que SMPlayer manexe. Cando prema en Aplicar automáticamente asociaranse esas extensións co SMPlayer. No caso de que desmarque unh tipo de medio restablecerase a asociación previa. + + + + Select none + Non escoller nada + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Nota:</b> (A Restauración non funciona en Windows Vista). + + + + PrefDrives + + + Drives + Dispositivos + + + + icon + Icona + + + + CD device + Dispositivo de CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Escolla o dispositivo de CD-Rom. Empregarase para reproducir VCDs e Audio CDs. + + + + DVD device + Dispositivo de DVD + + + + Choose your DVD device. It will be used to play DVDs. + Escolla o dispositivo de DVD. Será empregado para reproducir DVDs. + + + + Select your &CD device: + Escolla o seu dispositivo de &CD: + + + + Select your &DVD device: + Escolla o seu dispositivo de &DVD: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + O SMPlayer non escolle o dispositivo de CD ou DVD. Logo, para reproducir CD / DVD ten que escoller o dispositivo a empregar, que pode se-lo mesmo. + + + + PrefGeneral + + + General + Xeral + + + + &General + &Xeral + + + + Paths + Rotas + + + + Media settings + Configuración dos medios + + + + Start videos in fullscreen + Comezar vídeos en pantalla completa + + + + Disable screensaver + Desactivar o salvapantallas + + + + Select the mplayer executable + Escolla o executable do MPlayer + + + + Executables + Executables + + + + All files + Tódolos ficheiros + + + + Select a directory + Escolla un cartafol + + + + MPlayer executable + Executable do MPlayer + + + + Screenshots folder + Cartafol de capturas de pantallas + + + + Video output driver + Controlado da saída de vídeo + + + + Audio output driver + Controlador de saída de son + + + + Select the audio output driver. + Escolla o controlador de saída de son. + + + + Remember settings + Gravar as configuracións + + + + Preferred audio language + Lingua preferida do son + + + + Preferred subtitle language + Lingua dos subtítulos preferida + + + + Software video equalizer + Software de ecualización de vídeo + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Pode marcar esta opción se a ecualización de vídeo se a súa tarxeta gráfica non atura a ecualización de video ou se o controlador de vídeo de saída tampouco o fai.<br><b>Nota:</b> esta opción pode ser incompatible con algúns controladores de saída de vídeo. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Se marca esta opción tódolos vídeos comezaran a se reproducir en modo de pantalla completa. + + + + Software volume control + Software de control de volume + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Marque esta opción se quere empregar o mesturador de son, no canto de usar o mesturador da tarxeta de xon. + + + + Postprocessing quality + Calidade postprocesado + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Altera dinamicamente os niveis de postprocesado dependento do espazo dispoñible na CPU. O número especifica o máximo nivel empregado. Xeralmente, pode empregar un número maior. + + + + Change volume + Cambiar volume + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Se marca esta opción, o SMPlayer recordará o volumen para cada ficheiro e restaurarao cando se repoduza de novo. Para ficheiros novos emprégase o volume predefinido. + + + + 0 + 0 + + + + &Change volume on every file + &Cambiar volume para cada ficheiro + + + + Select the &MPlayer executable: + Escolla o exectuable &MPlayer: + + + + &Folder for storing screenshots: + &Cartafol para gravar as capturas: + + + + &Audio: + &Audio: + + + + &Remember settings for all files (audio track, subtitles...) + &Lembrar configuracións para tódolos ficheiros (pistas de audio, subtítulos...) + + + + Su&btitles: + Sub&títulos: + + + + &Quality: + &Calidade: + + + + Start videos in &fullscreen + Comezar vídes en &pantalla completa + + + + Disable &screensaver + Desactivar &salvapantallas + + + + &Default volume: + &Volume Predefinido: + + + + Use s&oftware volume control + Empregar Controlde Volume por &Software + + + + Ma&x. Amplification: + Amplificación &Máx.: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS com pasaxe S/PDIF + + + + Direct rendering + Renderizado directo + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Se marca esta opción, activase o procesado directo (non tódolas saídas de codec e audio soportan a opción)<br><b>ADVERTENCIA:</b> Pode causa-la corrupción de OSD/SUB! + + + + Double buffering + Dobre buffering + + + + D&irect rendering + Renderizado &Directo + + + + Dou&ble buffering + Dob&re Buffering + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + O dobre buffer soluciona as fluctuación xa que alamacena dous fotogramas na memoria e mostra un namentres descodifica outro. Como se desactive ha afectar negativamente ó OSD, mais habitualmente elimina as oscilacións OSD. + + + + &Enable postprocessing by default + &Activar postprocesado por defecto + + + + Volume &normalization by default + &Normalización de volume por defecto + + + + Close when finished + Pechar ó rematar + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Se marca esta opción, a fiestra principal ha ser pechada automáticamente cando se remate de reproducir o ficheiro ou alista de reprodución que se estea a reproducir. + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + &Canles por defecto: + + + + &Pause when minimized + &Pausar ó minimizar + + + + Pause when minimized + Pausar ó minimizar + + + + Enable postprocessing by default + Activa-lo postprocesado por defecto + + + + Max. Amplification + Máx. Amplificación + + + + AC3/DTS pass-through S/PDIF + AC3/DTS oasaxe a S/PDIF + + + + Volume normalization by default + Normalización do volume por defecto + + + + Maximizes the volume without distorting the sound. + Maximiza o volume sen distorsionar o son. + + + + Default volume + Volume por defecto + + + + Sets the initial volume that new files will use. + Define o volume inicial para novos ficheiros. + + + + Channels by default + Canles por defecto + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Establece o máximo nivel de amplificación, en tanto por cento (predefinido: 110). Un valor de 200 significa que está axustando o volume ó dobre do actual. Con valores por baixo de 100 veces o valor incial, que é o 100%, estará por debaixo do máximo, p.ex o OSD non se mostrará correctamente. + + + + Uses hardware AC3 passthrough + Usar a pasaxe de software AC3 + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Solicita o número de reproducións por canle. MPlayer solicitalle ó descodificador que descodifique o audio en tantas canles coma se especificaran. Logo depende do descodificador cumprir coa petición. Normalmente só é importante esta opción cando se reproducen vídeos con audio AC3, coma os DVDs. Neste caso a liba52 realiza a descodificación por defecto e mestura correctamente o audio co número de canles que se pediu. NOTA: Esta opción só é respectada polos codecs (só AC3), filtros (surround) e controladores de audios (polo menos OSS). + + + + Postprocessing will be used by default on new opened files. + Empregarase postprocesado por defecto para os novos ficheiros abertos . + + + + Audio track + Pist de audio + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Especifica a pista de audio que será empregada ó reproducir ficheiros. Se non existe a pista. logo usarase a primeira. <br><b>Nota:</b> a preferencia <i>"lingua de audio preferida"</i> manda sobre desta opción. + + + + Subtitle track + Pista de subtítulo + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Especifica a pista de subtitulos que se ha de empregar cando se reproduzan novos ficheiros. Se non existe a pista empregarase a primeira. <br><b>Nota:</b> a preferencia <i>"lingua de audio preferida"</i> manda sobre desta opción. + + + + Or choose a track number: + Ou escolla un número de pista: + + + + Audi&o: + Aaaau&dio: + + + + Preferred language: + Lingua preferido: + + + + Preferre&d audio and subtitles + Audio e subtítulos &preferidos + + + + &Subtitle: + &Subtítulo: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Pode introducir aquí a lingua preferida para o son e so subtítulos. Cando se reproduza un vídeo con múltiples audios e subtítulos SMPlayer ha intentar escoller o seu idioma preferido. Isto só funcionar con medio que ofrezan información sobre dos idiomas do audio ou os subtítulos, coma os DVDs ou ficheiros mkv.<br>Este campo acepta expresións regulares. Exemplo:<b>gl|glg</b> escolla a pista se cadra con <i>gl</i> ou <i>glg</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + Re&producir en alta velocidade sen alterar a densidade + + + + High speed playback without altering pitch + Reproducir en alta velocidade sen alterar a densidade + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Permite alterar a velocidade de reprodución sen altera-la densidade. É necesario o MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Cambia o volume xusto antes de empezar a reproducir + + + + &Video + &Vídeo + + + + Use s&oftware video equalizer + Empregar a ecualización por software de &vídeo + + + + A&udio + &Audio + + + + Volume + Volume + + + + Video + Vídeo + + + + Audio + Audio + + + + Preferred audio and subtitles + Audio e subtítulos preferidos + + + + None + Ningún + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normal) + + + + Yadif (double framerate) + Yadif (double framerate) + + + + Linear Blend + Mistura linear + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Desentre&lazar por defecto: + + + + Deinterlace by default + Desentralar por defecto + + + + Select the deinterlace filter that you want to be used for new videos opened. + Escolla o filtro para desentralazar os vídeos que se abran novos. + + + + Remember time position + Lembrar a posición no tempo + + + + Remember &time position + Lembrar a &posición no tempo + + + + Change volume just before p&laying + Cambia o vol&ume antes de reproducir + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Close when finished playback + + + + + Dra&w video using slices + + + + + &Enable the audio equalizer + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Teclado e rato + + + + &Keyboard + &Teclado + + + + icon + Icona + + + + &Mouse + &Rato + + + + Button functions: + Funcións do botón: + + + + Media seeking + Descolocación polo audio/video + + + + Volume control + Control do Volume + + + + Zoom video + Zoom de Video + + + + None + Nigún + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aquí pode cambiar calquera atallo de teclado. Para facelo faga dobre clic e prema enter enriba da celda. Saiba que pode gardar esla lista e compartila con outra xente ou cargala noutro ordenador. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aquí pode cargar calquera atallo de teclado. Para facelo prema dúas veces ou comece a escribir enriba dunha cela. Saiba que pode gravar esta lista para compartila ou cargala noutro ordenador. + + + + &Left click + &Clic Esquerdo + + + + &Double click + &Dobre Clic + + + + &Wheel function: + Fucións da &Roda do Rato: + + + + Shortcut editor + Editor de Atallos + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Esta táboa permítelle trocar os atallos para as accións máis relevantes. Faga dobre clicl ou prema enter sobre dun elemento, ou prema no botón de <b>Trocar atallo</b> para que lle apareza o diálogo <i>Modificar atallo</i>. Hai dúas maneiras de cambiar un atallo: se está activo o botón de <b>Capturar</b> logo prema a nova combinación de teclas a usar para esa acción (desafortunadamente, isto non funciona para tódalas teclas); se o botón de <b>Captura</b> está desactivado pode introducir manualmente o nome da tecla. + + + + Left click + Clic Esquerdo + + + + Select the action for left click on the mouse. + Escolla acción para o clic co botón esquerdo do rato. + + + + Double click + Dobre Clic + + + + Select the action for double click on the mouse. + Escolla unha acción para o dobre clic no rato. + + + + Wheel function + Función da roda do rato + + + + Select the action for the mouse wheel. + Escolla unha acción para a roda do rato. + + + + Play + Reproducir + + + + Pause + Pausar + + + + Stop + Parar + + + + Fullscreen + Pantalla Completa + + + + Compact + Compacto + + + + Screenshot + Captura de Pantalla + + + + On top + Enriba + + + + Mute + Silenciar + + + + Frame counter + Contador de fotogramas + + + + Reset zoom + Reiniciar o zoom + + + + Exit fullscreen + Saír do Modo de Pantalla Completo + + + + Double size + Tamaño Dobre + + + + Play / Pause + Reproducir/Pausar + + + + Pause / Frame step + Pausa/Avanzar Fotograma + + + + Playlist + Lista de Reprodución + + + + Preferences + Preferencias + + + + No function + Sen Funcións + + + + Change speed + Modificar Velocidade + + + + Normal speed + Velocidade Normal + + + + Keyboard + Teclado + + + + Mouse + Rato + + + + Middle click + Clic no Medio + + + + Select the action for middle click on the mouse. + Escolla a acción para o clic no botón central do rato. + + + + M&iddle click + Clic &Central + + + + X Button &1 + Botón X &1 + + + + X Button &2 + Botón X &2 + + + + Go backward (short) + Retroceder (curto) + + + + Go backward (medium) + Retrodecer (normal) + + + + Go backward (long) + Retroceder (longo) + + + + Go forward (short) + Avanzar (curto) + + + + Go forward (medium) + Avanzar (normal) + + + + Go forward (long) + Avanzar (longo) + + + + OSD - Next level + OSD - Proximo Nivel + + + + Show context menu + Mostrar Menú de Contexto + + + + &Right click + Clic &Dereito + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Interface + + + + <Autodetect> + <Autodetectar> + + + + Default + Predefinido + + + + &Interface + &Interface + + + + Never + Nunca + + + + Whenever it's needed + Cando se precise + + + + Only after loading a new video + Só despois de cargar un novo vídeo + + + + Recent files + Ficheiros recentes + + + + Language + Lingua + + + + Here you can change the language of the application. + Pode cambiar a lingua da aplicación aquí. + + + + &Short jump + &Salto curto + + + + &Medium jump + &Salto mediano + + + + &Long jump + &Salto longo + + + + Mouse &wheel jump + Salto coa &roda do rato + + + + &Use only one running instance of SMPlayer + &Empregar só unha instancia de SMPlayer + + + + Ma&x. items + Má&x. Obxectos + + + + St&yle: + E&stilo: + + + + Ico&n set: + Tema de &Iconas: + + + + L&anguage: + &Lingua: + + + + Main window + Fiestra Principal + + + + Auto&resize: + Auto&redimensionar: + + + + R&emember position and size + &Recorda-la posición e tamaño + + + + Default font: + Tipografía predefinida: + + + + &Change... + &Cambiar... + + + + &Behaviour of time slider: + &Comportamento do control de &tempo: + + + + Seek to position while dragging + Procura-la posición ó arrastar + + + + Seek to position when released + Procurar posición ó soltar + + + + TextLabel + EtiquetadeTexto + + + + &Seeking + &Procurar + + + + Ins&tances + Inst&ancias + + + + Autoresize + Redimensionar automáticamente + + + + The main window can be resized automatically. Select the option you prefer. + A fiestra principal pode ser redimensionada automáticamente. Escolla a opción que prefira. + + + + Remember position and size + Recordar a posición e o tamaño + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Se marca esta opción, hase gravar a posición e tamaño da fiestra principal e restaurados cando se abra de novo o SMPlayer. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Escolla o número máximo de obxectos a ser mostrados en <b>Ficheiros Recentes</b>. Se define 0 non se mostra o submenú. + + + + Icon set + Tema de Iconas + + + + Select the icon set you prefer for the application. + Escolla o tema de iconas que prefire para esta aplicación. + + + + Style + Estilo + + + + Select the style you prefer for the application. + Escolla o estilo que prefire para a aplicación. + + + + Default font + Tipografía predefinida + + + + You can change here the application's font. + Aquí pode cambiar o tipo de letra da aplicación. + + + + Seeking + Procura + + + + Short jump + Salto curto + + + + Select the time that should be go forward or backward when you choose the %1 action. + EScolla os intervalos de tempo a ser empregado cando aplique a acción %1. + + + + short jump + salto curto + + + + Medium jump + Salto Mediano + + + + medium jump + salto mediano + + + + Long jump + Salto Longo + + + + long jump + salto longo + + + + Mouse wheel jump + Avanze coa roda do rato + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Escolla os intervalos de tempo a ser empregado cando mova a roda do rato. + + + + Behaviour of time slider + Comportamento do control de tempo + + + + Select what to do when dragging the time slider. + Escolla o que debe acontecer ó arrastrar o controlador de tempo. + + + + Instances + Instancias + + + + Use only one running instance of SMPlayer + Use só unha instancie do SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Marque esta opción se quere empregar unha instancia xa existende SMPlayer cando abra outros ficheiros. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer necesita escoitar un porto para recivir ordes doutras instancias. Pode mudar este porto no caso de que o predefinido xa estea collido por outra aplicación. + + + + Default GUI + Interface Predefinida + + + + Mini GUI + Interface Reducida + + + + GUI + Interface + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Escolla a interface que prefire para a aplicación. Existen dous tipos: Predefinido ou Reducida. <br> A <b>Interface Predefinida</b> é a interface tradicional con barra de ferramentes e barra de control. A <b>Interface Reducida</b> é máis sinxela, sen barra de ferramentas e cunha barra de control con menos botóns.<br><b>Nota: esta opción só comeza a funcionar tras reiniciar o SMPlayer. + + + + &GUI + &Interface + + + + Automatic port + Porto automático + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer necesita un porto para recibir ordes doutras instancias. Se escolle esta opción, abrirase un porto automaticamente. + + + + Manual port + Porto Manual + + + + Port to listen + Porto a empregar + + + + &Automatic + &Automático + + + + &Manual + &Manual + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Rendemento + + + + &Performance + &Rendemento + + + + Priority + Prioridade + + + + Select the priority for the MPlayer process. + Escolla a prioridade dos procesos de MPlayer. + + + + realtime + tempo real + + + + high + alta + + + + abovenormal + por riba do normal + + + + normal + normal + + + + belownormal + por baixo do normal + + + + idle + desocupado + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Dispoñer cun caché pode mellorar o rendemento ó reproducir medio lentos + + + + Allow frame drop + Permitir que se salten fotogramas + + + + Synchronization + Sincronización + + + + Audio/video auto synchronization + Sincronización automática de autio e vídeo + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Establece a prioridade para MPlayer segundo as prioridades dispoñibles baixo Windows.<br><b>ADVERTENCIA:</b> Empregar a prioridade en tempo real pode provocar que se bloquee o sistema. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Saltar algúns fotogramas para manter a sincronización A/V en sistemas lentos. + + + + Allow hard frame drop + Permitir o slato brusco de fotogramas + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Unha perda de fotogramas intensa quebra a descodificación. Leva a que se distorsione a imaxe! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Axustar gradualmente a sincronización A/V baseandose en cálculos do atraso de audio. + + + + Priorit&y: + &Prioridade: + + + + &Allow frame drop + &Permitir saltar fotogramas + + + + Allow &hard frame drop (can lead to image distortion) + Permitir saltar fotogramas &bruscamente (pode levar a que se distorsione a imaxe) + + + + Audio/&video auto synchronization + Sincronización automática do audio e o &vídeo + + + + Fact&or: + Fact&or: + + + + &Fast audio track switching + &Mudanza rápida da pista de audio + + + + Fast &seek to chapters in dvds + Escolla &rápida de capítulos en DVDs + + + + Fast audio track switching + Mudanza rápida da pista de son + + + + Fast seek to chapters in dvds + Escolla rápida de capítulos nos DVDs + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + De se marcar intentarase o método máis rápido para procurar capítulos mais poida que non funcione con algúns discos. + + + + Skip loop filter + Ignorar os filtros loop + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Posibles valores: <br><b>Si</b>: Intentará o método máis rápido para cambiar a pista de son (poid que non funcione con algúns formatos).<br> <b>Non</b>: o proceso MPlayer reiniciarase cando cambie de pista de son. <br> <b> Automatica </b>: SMPlayer decide que facer segundo a versión que empregue do MPlayer. + + + + Cache for files + Cahé de ficheiros + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Esta opción especifica canta memoria, en kBytes, emprega cando pon en caché un ficheiro. + + + + Cache for streams + Caché para fluxos + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Esta opción especifica canta memoria, en kBytes, emprega cando poña en caché unha URL. + + + + Cache for DVDs + Caché para DVDs + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Esta opción especifica canta memoria, en kBytes, emprega cando poña en caché un DVD.<br><b>Advertencia:</b>A procura pode non funcionar correctamente, incluíndo cambiar de capítulo, ó empregar o caché para DVDs. + + + + &Cache + &Caché + + + + Cache for &DVDs: + Caché para &DVDs: + + + + Cache for &local files: + Caché para ficheiros &locais: + + + + Cache for &streams: + Caché para &fluxos: + + + + Enabled + Activado + + + + Skip (always) + Ignorar (sempre) + + + + Skip only on HD videos + Ignorar só en vídeos HD + + + + Loop &filter + Filtro de &loop + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Esta opción permite ignorar o filtro loop (tamén chamado deblocking) durante a descodificación H.264. Xa que se supón que o fotograma filtrado é empregado como referencia para a descodificación de fotogramas isto ten un efecto peor ca non facer deblocking. p.ex. vídeos MPEG-2. Polo menos, pata vídeos HDTV de alto bitrate isto ofrece unha maior velocidade sen efecto de perda aparente. + + + + Possible values: + Posibles valores: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Activado</b>: filtro loop non ignorado + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Ignorar (sempre)</b>: o filtro loop ignórase independentemente da resolución do vídeo + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Ignorar só en vídeo HD</b>: o filtro loop ignorarase só en videos con tamaños por riba dos %1. + + + + Cache + Caché + + + + Cache for audio CDs + Caché para Audio CDs + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Esta opción especifica a cantidade de memoria (en kBytes) que se ha de empregar para por no caché un audio CD. + + + + Cache for &audio CDs: + Caché para &Audio CDs: + + + + Cache for VCDs + Caché para VCDs + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Esta opción especifica canta memoria, en Kbytes, se emprega para por no caché un VCD. + + + + Cache for &VCDs: + Caché para &VCDs: + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Lista de Reprodución + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Lista de Reprodución + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Subtítulos + + + + Choose a ttf file + Escolla un ficheiro ttf + + + + Truetype Fonts + Tipografías TrueType + + + + &Subtitles + &Subtítulos + + + + Autoload + Autocargar + + + + Same name as movie + Gravar o nome coma a película + + + + All subs containing movie name + Tódolos dubtitulos que conteñan o nome da película + + + + All subs in directory + Tódolos subtítulos no cartafol + + + + Position + Posición + + + + 0 + 0 + + + + Top + Enriba + + + + Bottom + Enbaixo + + + + Font + Tipografía + + + + Select the font which will be used for subtitles (and OSD): + Escolla a tipografía para a cal quere escoller os subtítulos e mailo OSD: + + + + Size + Tamaño + + + + No autoscale + Sen autoescalado + + + + Proportional to movie height + Proporcional ó alto da película + + + + Proportional to movie width + Proporcional ó ancho da película + + + + Proportional to movie diagonal + Proporcional á diagonal da película + + + + Subtitle position + Posición do subtítulos + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Esta opción especifica a posición dos subtítulos por riba da fiestra de vídeo. <i>100</i> signofica no fondo e inversamente <i>0</i> quere dicir na cima. + + + + Au&toload subtitles files (*.srt, *.sub...): + Auto&cargar ficheiros de subtítulos (*.srt, *.sub...): + + + + S&elect first available subtitle + &Escolla o primeiro subtítulos dispoñible + + + + &Default subtitle encoding: + &Condificación de subtítulo predefinida: + + + + Default &position of the subtitles on screen + &Posición predefinida dos subtitulos na pantalla + + + + &Include subtitles on screenshots + &Incluír subtítulos nas capturas de pantall + + + + &TTF font: + Tipografía &TTF: + + + + S&ystem font: + Tipografía de &Sistema: + + + + A&utoscale: + &Autoescalado: + + + + Select first available subtitle + Escolla o primeiro subtítulos dispoñible + + + + Default subtitle encoding + Codificación de subtítulos predefinido + + + + Include subtitles on screenshots + Incluír subtitulos nas capturas + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Se marca esta opción ps subtítulos aparecen nas capturas de pantalla. Nota: poida que cause problemas algunhas veces. + + + + TTF font + Tipografía TTF + + + + System font + Tipografía do sistema + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Pode escollar aquí a tipografía de sistema que quere empregar nos subtítulos e mais na OSD. <b>Nota:</b> necesita que MPlayer conte con soporte fontconfig. + + + + Autoscale + Autoescalado + + + + Text color + Cor de texto + + + + Select the color for the text of the subtitles. + Escolla a caro para o texto dos subtítulos. + + + + Border color + Borde ca dor + + + + Select the color for the border of the subtitles. + Escolla o cor do borde dos subtítulos. + + + + Select the subtitle autoload method. + Escolla o método de autocargado de subtítulos. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Se hai un o máis pistas de subtítulos dispoñibles hase de escoller unha automaticamente, xeralmente a primeira, inda que se algunha cadra coa lingua predefinida do usuario ha ser escollida preferentemente. + + + + Select the subtitle autoscaling method. + Escolla o métido de autoescalado de subtítulos. + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + Enbaixo + + + + Middle + vertical alignment + + + + + Top + vertical alignment + Enriba + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Axuda + + + + OK + Aceptar + + + + Cancel + Cancelar + + + + Apply + Aplicar + + + + Help + Axuda + + + + SMPlayer - Preferences + SMPlayer - Preferencias + + + + QObject + + + will show this message and then will exit. + mostrará esta mensaxe e logo sairá. + + + + the main window will be closed when the file/playlist finishes. + a fiestra principal pecharase cando o ficheiro ou a lista de reprodución remate. + + + + This is SMPlayer v. %1 running on %2 + Este é o SMPlayer v. %1 executandose en %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + intenta conectarse a outra unstancia e enviarlle a acción especificada. Exemplo: send-action pause O resto das opción, no caso de que houber, serán ignoradas e a aplicación rematará. Ha de devolver 0 se todo foi ben ou -1 se houbo un fallo. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list é unha lista de acción separadas por espazos. As accións executaranse xusto despois de que se carga o ficheiro, se houber, na mesma orde na que se introduciron. Para accións comprobables pode introducir true ou false coma parámetros. Exemplo: -actions "fullscreen compact true" . As comiñas son necesarias en caso de que introduza máis dunha acción. + + + + media + medios + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + os medios engadiranse á lista de reprodución de existir outra instancia en execuón. No caso contrario, esta opción ignorarase e os ficheiros serán abertos noutra instancia do programa. + + + + the main window won't be closed when the file/playlist finishes. + a fiestra princiapal non será pechada ó concluír o ficheiro ou lista de reprodución. + + + + the video will be played in fullscreen mode. + o video ha de se reproducir en pantalla completa. + + + + the video will be played in window mode. + o video ha ser reproducido en modo de fiestra. + + + + Enqueue in SMPlayer + Poñer na Lista do SMPlayer + + + + opens the mini gui instead of the default one. + abre o modo reducido non canto do normal. + + + + Restores the old associations and cleans up the registry. + Restaura as asociacións antigas e limpa o rexistro. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + un medio é calquera tipo de ficheiro que o SMPlayer sexa quen de reproducir. Pode ser tanto un ficheiro local, un DV (p.ex dvd://1) coma un fluxo procedente da internet así como un ficheiro m3u ou pls. No caso de que se empregada a opción -playlist o SMPlayer pasaralle a opción -playlist ó MPlayer para que a xestione este, e non SMPlayer. + + + + Usage: + Uso: + + + + directory + cartafol + + + + action_name + nome_acción + + + + action_list + lista_acción + + + + opens the default gui. + abre a GUI Prefedinida. + + + + subtitle_file + ficheiro_de_subtítulos + + + + specifies the subtitle file to be loaded for the first video. + especifica o ficheiro de subtítulos para que cargue co primeiro video. + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + %1 e %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + icona + + + + label + etiqueta + + + + ShortcutGetter + + + Modify shortcut + Modificar Atallo + + + + Clear + Limpar + + + + Press the key combination you want to assign + Prema a combinación de teclas que quere rexistrar + + + + Capture + Capturar + + + + Capture keystrokes + Capturar teclas de atallo + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + Escoller Todo + + + + Select None + Deseleccionar Todo + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Procura + + + + &Jump to: + &Ir a: + + + + TristateCombo + + + Auto + Automático + + + + Yes + Si + + + + No + Non + + + + VideoEqualizer + + + Contrast + Contraste + + + + Brightness + Brillo + + + + Hue + Tonalidade + + + + Saturation + Saturación + + + + Gamma + Gamma + + + + &Reset + &Reiniciar + + + + &Set as default values + &Empregar como valores predefinidos + + + + Use the current values as default values for new videos. + Usa os valores actuais coma valores por defecto para os novos vídeos. + + + + Set all controls to zero. + Poñer tódolos controis a cero. + + + + Video Equalizer + Ecualizador de Vídeo + + + + Information + Información + + + + The current values have been stored to be used as default. + Os valores actuais acaban de ser gravado para seren empregados por defecto. + + + + VideoPreview + + + Video preview + + + + + Cancel + Cancelar + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Non se puido gravar o ficheiro + + + + The file couldn't be saved + Non se pode gravar o ficheiro + + + + Error + Erro + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Predefinido + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Volume + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_hu.ts b/plugins/smplayer_plugin/translations/smplayer_hu.ts new file mode 100644 index 000000000..b2e29ce1d --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_hu.ts @@ -0,0 +1,7367 @@ + + + + About + + + Version: %1 + Verzió: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Ez a program egy szabad szoftver; a Free Software Foundation által kiadott GNU General Public License 2. vagy (igény szerint) bármely újabb verziójának feltételei alapján terjeszthető és/vagy módosítható. + + + + The following people have contributed with translations: + A következő emberek járultak hozzá fordításokkal: + + + + German + Német + + + + Slovak + Szlovák + + + + Italian + Olasz + + + + French + Francia + + + + %1, %2 and %3 + %1, %2 és %3 + + + + Simplified-Chinese + Egyszerűsített kínai + + + + Russian + Orosz + + + + %1 and %2 + %1 és %2 + + + + Hungarian + Magyar + + + + Polish + Lengyel + + + + Japanese + Japán + + + + Dutch + Holland + + + + Ukrainian + Ukrán + + + + Portuguese - Brazil + Portugál - Brazil + + + + Georgian + Grúz + + + + Czech + Csehszlovák + + + + Bulgarian + Bolgár + + + + Turkish + Török + + + + Swedish + Svéd + + + + Serbian + Szerb + + + + Traditional Chinese + Hagyományos kínai + + + + Romanian + Román + + + + Portuguese - Portugal + Portugál + + + + Greek + Görög + + + + Finnish + Finn + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + SMPlayer névjegye + + + + &Info + &Infó + + + + icon + ikon + + + + &Contributions + &Hozzájárulók + + + + &Translators + &Fordítók + + + + &License + &Licensz + + + + Visit our web for updates: + Látogassa meg az oldalunkat frissítésekért: + + + + Get help in our forum: + Kérjen segítséget a fórumunkban: + + + + You can support SMPlayer by making a donation. + Támogathatja az SMPlayert adománnyal. + + + + More info + Több információ + + + + Korean + Koreai + + + + Macedonian + Macedón + + + + Basque + Baszk + + + + Using MPlayer %1 + Használt MPlayer: %1 + + + + Catalan + Katalán + + + + Portable Edition + Hordozható változat + + + + Using Qt %1 (compiled with Qt %2) + Használt Qt: %1 (fordítva Qt %2-l) + + + + Slovenian + Szlovén + + + + Arabic + Arab + + + + Kurdish + Kurd + + + + Galician + Galíciai + + + + The following people have contributed with patches (see the changelog for details): + Néhány ember, aki patchekkel járultak hozzá (lásd a változások listáját): + + + + If there's any omission, please report. + Ha valaki hiányzik, kérem jelezze. + + + + SMPlayer logo by %1 + Az SMPlayer logót %1 készítette + + + + %1, %2, %3 and %4 + %1, %2, %3 és %4 + + + + %1, %2, %3, %4 and %5 + %1, %2, %3, %4 és %5 + + + + ActionsEditor + + + Name + Név + + + + Description + Leírás + + + + Shortcut + Gyorsgomb + + + + &Save + &Mentés + + + + &Load + &Betölt + + + + Key files + Kulcsfájlok + + + + Choose a filename + Válasszon egy fájlnevet + + + + Confirm overwrite? + Valóban felülírja? + + + + The file %1 already exists. +Do you want to overwrite? + %1 fájl már létezik. +Valóban felül akarja írni? + + + + Choose a file + Válasszon egy fájlt + + + + Error + Hiba + + + + The file couldn't be saved + A fájlt nem lehetett menteni + + + + The file couldn't be loaded + A fájlt nem lehetett betölteni + + + + &Change shortcut... + Gyorsgomb &cseréje... + + + + AudioEqualizer + + + Audio Equalizer + Hang kiegyenlítő + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Alkalmaz + + + + &Reset + Ala&phelyzet + + + + &Set as default values + Beállítá&s alapértéknek + + + + Use the current values as default values for new videos. + A jelenlegi értékek használata, mint alapérték az új videókhoz. + + + + Set all controls to zero. + Minden vezérlő nullára állítása. + + + + Information + Információ + + + + The current values have been stored to be used as default. + A jelenlegi értékek el lettek mentve alapértelmezettnek. + + + + BaseGui + + + &File... + &Fájl... + + + + D&irectory... + &Könyvtár... + + + + &Playlist... + Lejátszási li&sta... + + + + &DVD from drive + &DVD lejátszás + + + + D&VD from folder... + D&VD lejátszás könyvtárból... + + + + &URL... + &URL... + + + + P&lay + Le&játszás + + + + &Pause + &Szünet + + + + &Stop + &Megállít + + + + &Frame step + &Képkocka léptetés + + + + &Repeat + &Ismétlés + + + + &Normal speed + &Normál sebesség + + + + &Halve speed + &Fél sebesség + + + + &Double speed + &Dupla sebesség + + + + Speed &-10% + Sebesség&-10% + + + + Speed &+10% + Sebesség &+10% + + + + Sp&eed + &Sebesség + + + + &Fullscreen + &Teljes képernyő + + + + &Compact mode + &Kompakt mód + + + + &Equalizer + &Kiegyenlítő (EQ) + + + + &Screenshot + &Pillanatkép + + + + S&tay on top + Mindig &felül + + + + &Postprocessing + &Utófeldolgozás + + + + &Autodetect phase + &Automatikus fázis érzékelés + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + N&oise hozzáadása + + + + F&ilters + S&zűrők + + + + &Mute + &Némítás + + + + Volume &- + Hangerő &- + + + + Volume &+ + Hangerő &+ + + + + &Delay - + K&ésleltetés - + + + + D&elay + + Ké&sleltetés + + + + + &Extrastereo + &Extra sztereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Szűrők + + + + &Load... + &Betöltés... + + + + Delay &- + Késleltetés &- + + + + Delay &+ + Késleltetés &+ + + + + &Up + &Fel + + + + &Down + &Le + + + + &Playlist + Lejátszási l&ista + + + + &Show frame counter + &Képkocka számláló megjelenítése + + + + P&references + &Beállítások + + + + &View logs + &Naplók megjelenítése + + + + About &Qt + &Qt névjegye + + + + About &SMPlayer + &SMPlayer névjegye + + + + &Open + &Megnyitás + + + + &Play + &Lejátszás + + + + &Video + &Videó + + + + &Audio + &Hang + + + + &Subtitles + &Feliratok + + + + &Browse + &Tallózás + + + + Op&tions + &Opciók + + + + &Help + &Segítség + + + + &Recent files + &Utoljára megnyitott fájlok + + + + &Clear + &Ürítés + + + + Si&ze + &Méret + + + + &Aspect ratio + &Méretarány + + + + &Deinterlace + &Deinterlace + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &-> 16:9 + + + + &None + &Nincs + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Lineáris &keverés + + + + &Channels + &Csatornák + + + + &Stereo mode + &Sztereó mód + + + + &Stereo + &Sztereó + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Left channel + &Bal csatorna + + + + &Right channel + &Jobb csatorna + + + + &Select + &Kiválaszt + + + + &Title + &Cím + + + + &Chapter + &Fejezet + + + + &Angle + &Szög + + + + &OSD + &OSD + + + + &Disabled + &Kikapcsolva + + + + &Seek bar + &Keresősáv + + + + &Time + &Idő + + + + Time + T&otal time + Idő + &Teljes idő + + + + SMPlayer - mplayer log + SMPlayer - MPlayer napló + + + + SMPlayer - smplayer log + SMPlayer - SMPlayer napló + + + + <empty> + <üres> + + + + Video + Videó + + + + Audio + Hang + + + + Playlists + Lejátszási listák + + + + All files + Minden fájl + + + + Choose a file + Válasszon egy fájlt + + + + SMPlayer - Information + SMPlayer - Információ + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + A CDROM / DVD meghajtó nincs még beállítva. +A beállító panel megjelenik most, állítsa be az eszközöket. + + + + Choose a directory + Válasszon egy könyvtárat + + + + Subtitles + Feliratok + + + + About Qt + Qt névjegye + + + + Playing %1 + %1 lejátszása + + + + Pause + Szünet + + + + Stop + Megállítás + + + + Play / Pause + Lejátszás / Szünet + + + + Pause / Frame step + Szünet / Képkocka léptetés + + + + U&nload + &Kiürítés + + + + V&CD + V&CD + + + + C&lose + Be&zár + + + + View &info and properties... + &Információk és tulajdonságok megjelenítése... + + + + Zoom &- + Kicsinyítés &- + + + + Zoom &+ + Nagyítás &+ + + + + &Reset + Ala&phelyzet + + + + Move &left + Mozgatás &balra + + + + Move &right + Mozgatás &jobbra + + + + Move &up + Mozgatás &felfelé + + + + Move &down + Mozgatás &lefelé + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Előző sor a feliratban + + + + N&ext line in subtitles + &Következő sor a feliratban + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Kevesebb hangerő (2) + + + + Inc volume (2) + Több hangerő (2) + + + + Exit fullscreen + Kilépés a teljes képernyőből + + + + OSD - Next level + OSD - Következő szint + + + + Dec contrast + Kevesebb kontraszt + + + + Inc contrast + Több kontraszt + + + + Dec brightness + Kevesebb fényerő + + + + Inc brightness + Több fényerő + + + + Dec hue + Kevesebb telítettség + + + + Inc hue + Több telítettség + + + + Dec saturation + Kevesebb telítettség + + + + Dec gamma + Kevesebb gamma + + + + Next audio + Következő hang + + + + Next subtitle + Következő felirat + + + + Next chapter + Következő fejezet + + + + Previous chapter + Előző fejezet + + + + Inc saturation + Több telítettség + + + + Inc gamma + Több gamma + + + + &Load external file... + &Külső fájl betöltése... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normál) + + + + Y&adif (double framerate) + Y&adif (dupla képkockaszám) + + + + &Next + &Következő + + + + Pre&vious + &Előző + + + + Volume &normalization + Hangerő &normalizálás + + + + &Audio CD + &Hanglemez + + + + Denoise nor&mal + Denoise nor&mál + + + + Denoise &soft + Denoise &lágy + + + + Denoise o&ff + Denoise &ki + + + + Use SSA/&ASS library + SSA/&ASS könyvtár használata + + + + Flip i&mage + Kép &tükrözése + + + + &Toggle double size + &Dupla méretre vált + + + + S&ize - + &Méret - + + + + Si&ze + + Mé&ret + + + + + Add &black borders + &Fekete szegélyek hozzáadása + + + + Soft&ware scaling + Szoft&veres méretezés + + + + &FAQ + &GYIK + + + + Visualize &motion vectors + Mo&zgásvektorok mutatása + + + + &Command line options + &Parancssori opciók + + + + SMPlayer command line options + SMPlayer parancssori opciók + + + + Enable &closed caption + Feliratok gyengén &hallóknak + + + + &Forced subtitles only + Csak &kényszerített feliratok + + + + Reset video equalizer + Video kiegyenlítő (EQ) alaphelyzet + + + + MPlayer has finished unexpectedly. + Az MPlayer váratlanul leállt. + + + + Exit code: %1 + Visszatérési érték: %1 + + + + MPlayer failed to start. + Az MPlayer nem tudott elindulni. + + + + Please check the MPlayer path in preferences. + Ellenőrizze az MPlayer elérési útvonalát a beállításokban. + + + + MPlayer has crashed. + Az MPlayer összeomlott. + + + + See the log for more info. + Több információért nézze meg a naplót. + + + + &Rotate + &Forgatás + + + + &Off + &Ki + + + + &Rotate by 90 degrees clockwise and flip + &Forgatás 90 fokkal jobbra és tükrözés + + + + Rotate by 90 degrees &clockwise + Forgatás 90 fokkal &jobbra + + + + Rotate by 90 degrees counterclock&wise + Forgatás 90 fokkal &balra + + + + Rotate by 90 degrees counterclockwise and &flip + Forgatás 90 fokkal balra és &tükrözés + + + + &Jump to... + &Ugrás... + + + + Show context menu + Helyi menü mutatása + + + + Multimedia + Multimédia + + + + E&qualizer + Han&gszínszabályzó + + + + Reset audio equalizer + Hang kiegyenlítő alaphelyzet + + + + Find subtitles on &OpenSubtitles.org... + Feliratok keresése az &OpenSubtitles.org-on... + + + + Upload su&btitles to OpenSubtitles.org... + Feliratok feltöltése az OpenSu&btitles.org-ra... + + + + &Tips + &Tippek + + + + &Auto + &Auto + + + + Speed -&4% + Sebesség -&4% + + + + &Speed +4% + Sebesség +&4% + + + + Speed -&1% + Sebesség -&1% + + + + S&peed +1% + Sebesség +&1% + + + + Scree&n + Képer&nyő + + + + &Default + &Alapértelmezés + + + + Mirr&or image + Tükr&özés + + + + Next video + Következő videó + + + + &Track + video + &Sáv + + + + &Track + audio + &Hangsáv + + + + Warning - Using old MPlayer + Figyelem - Régi MPlayer használata + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + A feltelepített %1 verziójú MPlayer elavult. Az SMPlayer nem tud vele jól együttműködni: egyes opciók nem fognak működni, felirat kiválasztás hibás lehet... + + + + Please, update your MPlayer. + Kérem frissítse az MPlayert. + + + + (This warning won't be displayed anymore) + (Ez a figyelmeztetés többet nem jelenik meg) + + + + Next aspect ratio + Következő méretarány + + + + &Auto zoom + &Auto nagyítás + + + + Zoom for &16:9 + Nagyítás &16:9-hez + + + + Zoom for &2.35:1 + Nagyítás &2.35:1-hez + + + + Pre&view... + Elő&nézet... + + + + &Always + &Mindig + + + + &Never + &Soha + + + + While &playing + &Lejátszás közben + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer még mindig fut itt + + + + S&how icon in system tray + Tálca&ikon megjelenítése + + + + &Hide + &Elrejt + + + + &Restore + &Visszaállít + + + + &Quit + &Kilépés + + + + Playlist + Lejátszási lista + + + + Core + + + Brightness: %1 + Fényerő: %1 + + + + Contrast: %1 + Kontraszt: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Színárnyalat: %1 + + + + Saturation: %1 + Telítettség: %1 + + + + Volume: %1 + Hangerő: %1 + + + + Zoom: %1 + Nagyítás: %1 + + + + Font scale: %1 + Betű méret: %1 + + + + Aspect ratio: %1 + Méretarány: %1 + + + + Updating the font cache. This may take some seconds... + Betűkészlet gyorsítótár frissítése. Eltarthat pár másodpercig... + + + + DefaultGui + + + Welcome to SMPlayer + Az SMPlayer üdvözli Önt + + + + Audio + Hang + + + + Subtitle + Felirat + + + + &Main toolbar + &Fő eszköztár + + + + &Language toolbar + &Nyelvi eszköztár + + + + &Toolbars + &Eszköztárak + + + + EqSlider + + + icon + ikon + + + + ErrorDialog + + + Hide log + Napló elrejtése + + + + Show log + Napló mutatása + + + + MPlayer Error + MPlayer hiba + + + + icon + ikon + + + + Error + Hiba + + + + FileDownloader + + + Downloading... + Letöltés... + + + + Downloading %1 + %1 letöltése + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Fájltulajdonságok + + + + &Information + &Információ + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Válassza ki a demuxert, amit ehhez a fájlhoz használni fog: + + + + &Reset + Ala&phelyzet + + + + &Video codec + &Videó kodek + + + + &Select the video codec: + Vála&ssza ki a videó kodeket: + + + + A&udio codec + H&ang kodek + + + + &Select the audio codec: + &Válassza ki a hang kodeket: + + + + &MPlayer options + &MPlayer opciók + + + + Additional Options for MPlayer + További opciók az MPlayernek + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Itt kell megadnia az extra opciókat az MPlayernek. +Írja őket szóközzel elválasztva. +Például: -flip -nosound + + + + &Options: + &Opciók: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Itt tud további videó szűrőket hozzáadni. +Írja őket ","-vel elválasztva. Ne használja a szóközt! +Például: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + V&ideó szűrők: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + És végül hang szűrők. Hasonló módon mint a videó szűrők. +Például: resample=44100:0:0,volnorm + + + + Audio &filters: + Ha&ng szűrők: + + + + OK + OK + + + + Cancel + Mégsem + + + + Apply + Alkalmaz + + + + FindSubtitlesWindow + + + Language + Nyelv + + + + Name + Név + + + + Format + Formátum + + + + Files + Fájlok + + + + Date + Dátum + + + + Uploaded by + Feltöltötte + + + + All + Mind + + + + Close + Bezár + + + + &Download + &Letöltés + + + + &Copy link to clipboard + &Hivatkozás másolása vágólapra + + + + Error + Hiba + + + + Download failed: %1. + Letöltési hiba: %1. + + + + Connecting to %1... + Kapcsolódás %1-hoz... + + + + Downloading... + Letöltés... + + + + Done. + Kész. + + + + %1 files available + %1 fájl érhető el + + + + Failed to parse the received data. + Hiba az érkezett adatok olvasása közben. + + + + Find Subtitles + Feliratok keresése + + + + &Subtitles for + &Feliratok - + + + + &Language: + Ny&elv: + + + + &Refresh + F&rissítés + + + + Subtitle saved as %1 + Felirat elmentve %1 néven + + + + %1 subtitle(s) extracted + + %1 felirat kicsomagolva + + + + + Overwrite? + Felülírja? + + + + The file %1 already exits, overwrite? + %1 fájl már létezik, felül akarja írni? + + + + Error saving file + Hiba a fájl mentése közben + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Nem sikerült elmenteni a letöltött fájlt a %1 könyvtárba. Ellenőrizze a könyvtár jogosultságait. + + + + Download failed + Letöltés sikertelen + + + + Temporary file %1 + Átmeneti fájl: %1 + + + + InfoFile + + + General + Általános + + + + Size + Méret + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Hossz + + + + Demuxer + Demuxer + + + + Name + Név + + + + Artist + Előadó + + + + Author + Szerző + + + + Album + Album + + + + Genre + Műfaj + + + + Date + Dátum + + + + Track + Sáv + + + + Copyright + Copyright + + + + Comment + Megjegyzés + + + + Software + Szoftver + + + + Clip info + Klipp infó + + + + Video + Videó + + + + Resolution + Felbontás + + + + Aspect ratio + Méretarány + + + + Format + Formátum + + + + Bitrate + Bitráta + + + + %1 kbps + %1 kbps + + + + Frames per second + Képkocka / másodperc + + + + Selected codec + Kiválasztott kodek + + + + Initial Audio Stream + Elsődleges hang adatfolyam + + + + Rate + Érték + + + + %1 Hz + %1 Hz + + + + Channels + Csatornák + + + + Audio Streams + Hang adatfolyamok + + + + Language + Nyelv + + + + empty + üres + + + + Subtitles + Feliratok + + + + Type + Típus + + + + ID + Info for translators: this is a identification code + Azonosító + + + + # + Info for translators: this is a abbreviation for number + + + + + Stream title + Adatfolyam címe + + + + Stream URL + Adatfolyam URL + + + + File + Fájl + + + + InputDVDDirectory + + + Choose a directory + Válasszon egy könyvtárat + + + + SMPlayer - Play a DVD from a folder + SMPlayer - DVD lejátszása egy könyvtárból + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Egy DVD-t lejátszhat a merevlemezéről is. Ehhez válassza ki azt a könyvtárat, amelyben a VIDEO_TS és AUDIO_TS alkönyvtárak találhatók. + + + + Choose a directory... + Könyvtár választás... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Adja meg az MPlayer verzióját + + + + SMPlayer couldn't identify the MPlayer version you're using. + Az SMPlayer nem tudta azonosítani a használt MPlayer verziót. + + + + Version reported by MPlayer: + MPlayer által jelentett verzió: + + + + Please, &select the correct version: + &Válassza ki a helyes verziót: + + + + 1.0rc1 or older + 1.0rc1 vagy régebbi + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + 1.0rc2-nél újabb + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - URL megadása + + + + &URL: + &URL: + + + + It's a &playlist + Ez egy le&játszási lista + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Ha ezt az opciót bejelöli, az URL lejátszási listaként lesz kezelve: szövegként lesz megnyitva és a benne lévő URLek lesznek lejátszva. + + + + Languages + + + Afar + Afar + + + + Abkhazian + Abház + + + + Afrikaans + Afrikaans + + + + Amharic + Amhara + + + + Arabic + Arab + + + + Assamese + Asszámi + + + + Aymara + Ajmara + + + + Azerbaijani + Azeri + + + + Bashkir + Baskír + + + + Byelorussian + Belarusz + + + + Bulgarian + Bolgár + + + + Bihari + Bhojpuri + + + + Bislama + Bislama + + + + Bengali + Bengáli + + + + Tibetan + Tibeti + + + + Breton + Breton + + + + Catalan + Katalán + + + + Corsican + Korzikai + + + + Czech + Cseh + + + + Welsh + Wales-i + + + + Danish + Dán + + + + German + Német + + + + Bhutani + Bhutani + + + + Greek + Görög + + + + English + Angol + + + + Esperanto + Eszperantó + + + + Spanish + Spanyol + + + + Estonian + Észt + + + + Basque + Baszk + + + + Persian + Perzsa + + + + Finnish + Finn + + + + Fiji + Fidzsi + + + + Faroese + Feröeri + + + + French + Francia + + + + Frisian + Fríz + + + + Irish + Ír + + + + Scots + Scots + + + + Galician + Galíciai + + + + Guarani + Guarani + + + + Gujarati + Gujarati + + + + Hausa + Hausa + + + + Hebrew + Héber + + + + Hindi + Hindi + + + + Croatian + Horvát + + + + Hungarian + Magyar + + + + Armenian + Örmény + + + + Interlingua + Interlingva + + + + Indonesian + Indonéz + + + + Interlingue + Interlingua + + + + Inupiak + Inupiak + + + + Icelandic + Izlandi + + + + Italian + Olasz + + + + Inuktitut + Inuktitut + + + + Japanese + Japán + + + + Javanese + Jávai + + + + Georgian + Grúz + + + + Kazakh + Kazah + + + + Greenlandic + Grönlandi + + + + Cambodian + Khmer + + + + Kannada + Kannada + + + + Korean + Koreai + + + + Kashmiri + Kasmiri + + + + Kurdish + Kurd + + + + Kirghiz + Kirgiz + + + + Latin + Latin + + + + Lingala + Lingala + + + + Laothian + Laoszi + + + + Lithuanian + Litván + + + + Latvian + Lett + + + + Malagasy + Malagas + + + + Maori + Maori + + + + Macedonian + Macedón + + + + Malayalam + Malajálam + + + + Mongolian + Mongol + + + + Moldavian + Moldáv + + + + Marathi + Maráthi + + + + Malay + Maláj + + + + Maltese + Máltai + + + + Burmese + Burmai + + + + Nauru + Nauru + + + + Nepali + Nepáli + + + + Dutch + Holland + + + + Norwegian + Norvég + + + + Occitan + Okcitán + + + + Oriya + Orija + + + + Punjabi + Pandzsábi + + + + Polish + Lengyel + + + + Pashto + Pastu + + + + Portuguese + Portugál + + + + Quechua + Kecsua + + + + Kirundi + Kirundi + + + + Romanian + Román + + + + Russian + Orosz + + + + Kinyarwanda + Kinyarvanda + + + + Sanskrit + Szanszkrit + + + + Sindhi + Szindhi + + + + Sangho + Sango + + + + Sinhalese + Szingaléz + + + + Slovak + Szlovák + + + + Slovenian + Szlovén + + + + Samoan + Szamoai + + + + Shona + Sona + + + + Somali + Szomáli + + + + Albanian + Albán + + + + Serbian + Szerb + + + + Siswati + Siswati + + + + Sesotho + Sesotho + + + + Sundanese + Szudánéz + + + + Swedish + Svéd + + + + Swahili + Szuahéli + + + + Tamil + Tamil + + + + Telugu + Telugu + + + + Tajik + Tadzsik + + + + Thai + Thaiföldi + + + + Tigrinya + Tigrinya + + + + Turkmen + Türkmén + + + + Tagalog + Tagalog + + + + Setswana + Setswana + + + + Tonga + Tongai + + + + Turkish + Török + + + + Tsonga + Conga + + + + Tatar + Tatár + + + + Twi + Twi + + + + Uighur + Ujgur + + + + Ukrainian + Ukrán + + + + Urdu + Urdu + + + + Uzbek + Üzbég + + + + Vietnamese + Vietnami + + + + Wolof + Wolof + + + + Xhosa + Xhosza + + + + Yiddish + Jiddis + + + + Yoruba + Joruba + + + + Zhuang + Dzsuang + + + + Chinese + Kínai + + + + Zulu + Zulu + + + + Portuguese - Brazil + Portugál - Brazil + + + + Portuguese - Portugal + Portugál + + + + Simplified-Chinese + Egyszerűsített kínai + + + + Traditional Chinese + Hagyományos kínai + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + Nyugat-európai nyelvek + + + + Western European Languages with Euro + Nyugat-európai nyelvek euróval + + + + Slavic/Central European Languages + Szláv/közép-európai nyelvek + + + + Esperanto, Galician, Maltese, Turkish + Eszperantó, galíciai, máltai, török + + + + Old Baltic charset + Régi baltikumi kódolás + + + + Cyrillic + Cirill + + + + Modern Greek + Modern görög + + + + Baltic + Balti + + + + Celtic + Kelta + + + + Hebrew charsets + Héber kódolás + + + + Ukrainian, Belarusian + Ukrán, belarusz + + + + Simplified Chinese charset + Egyszerűsített kínai kódolás + + + + Traditional Chinese charset + Hagyományos kínai kódolás + + + + Japanese charsets + Japán kódolás + + + + Korean charset + Koreai kódolás + + + + Thai charset + Thai kódolás + + + + Cyrillic Windows + Windows cirill + + + + Slavic/Central European Windows + Windows szláv/közép-európai + + + + Arabic Windows + Windows arab + + + + Rhaeto-Romance + Rétoromán + + + + Serbo-Croatian + Szerbhorvát + + + + Volapük + Volapük + + + + Avestan + Avesztai + + + + Akan + Akan + + + + Aragonese + Aragóniai + + + + Avaric + Avar + + + + Belarusian + Belarusz + + + + Bambara + Bambara + + + + Bosnian + Bosnyák + + + + Chechen + Csecsen + + + + Cree + Krí + + + + Church + Egyházi szláv + + + + Chuvash + Csuvas + + + + Divehi + Divehi + + + + Dzongkha + Dzongkha + + + + Ewe + Eve + + + + Fulah + Ful + + + + Fijian + Fidzsi + + + + Gaelic + Kelta + + + + Manx + Manx + + + + Hiri + Hiri-motu + + + + Haitian + Haiti kreol + + + + Herero + Herero + + + + Chamorro + Csamorro + + + + Igbo + Igbo + + + + Sichuan + Szecsuán + + + + Inupiaq + Inupiak + + + + Ido + Ido + + + + Kongo + Kongo + + + + Kikuyu + Kikuju + + + + Kuanyama + Kuanyama + + + + Khmer + Khmer + + + + Kanuri + Kanuri + + + + Komi + Komi + + + + Cornish + Korn + + + + Luxembourgish + Luxemburgi + + + + Ganda + Ganda + + + + Limburgan + Limburgi + + + + Lao + Lao + + + + Luba-Katanga + Luba-katanga + + + + Marshallese + Marshall-szigeteki + + + + Bokmål + Bokmal + + + + Ndebele + Ndebele + + + + Ndonga + Ndonga + + + + Navajo + Navaho + + + + Chichewa + Csicseva + + + + Ojibwa + Ozsibva + + + + Oromo + Oromo + + + + Ossetian + Oszét + + + + Panjabi + Pandzsábi + + + + Pali + Páli + + + + Pushto + Pasto + + + + Romansh + Rétoromán + + + + Rundi + Rundi + + + + Sardinian + Szárd + + + + Sami + Lapp + + + + Sango + Szango + + + + Sinhala + Szimhala + + + + Swati + Szvázi + + + + Sotho + Szoto + + + + Tswana + Csvana + + + + Tahitian + Tahiti + + + + Venda + Venda + + + + Volapük + Volapük + + + + Walloon + Vallon + + + + LogWindow + + + Choose a filename to save under + Válasszon egy fájlnevet a mentéshez + + + + Confirm overwrite? + Valóban felülírja? + + + + The file already exists. +Do you want to overwrite? + A fájl már létezik. +Valóban felül akarja írni? + + + + Error saving file + Hiba a fájl mentése közben + + + + The log couldn't be saved + A napló mentése nem sikerült + + + + Logs + Naplók + + + + LogWindowBase + + + Log Window + Napló ablak + + + + Save + Mentés + + + + Copy to clipboard + Másolás a vágólapra + + + + Close + Bezár + + + + &Close + &Bezár + + + + MiniGui + + + Control bar + Vezérlősáv + + + + MpcGui + + + Control bar + Vezérlősáv + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Név + + + + Length + Hossz + + + + Choose a file + Válasszon egy fájlt + + + + Choose a filename + Válasszon egy fájlnevet + + + + Confirm overwrite? + Valóban felülírja? + + + + Select one or more files to open + Válasszon ki egy vagy több megnyitandó fájlt + + + + Choose a directory + Válasszon egy könyvtárat + + + + The file %1 already exists. +Do you want to overwrite? + %1 fájl már létezik. +Valóban felül akarja írni? + + + + Edit name + Név szerkesztése + + + + Type the name that will be displayed in the playlist for this file: + Írjon be egy nevet ami a lejátszási listában meg lesz jelenítve ehhez a fájlhoz: + + + + &Play + &Lejátszás + + + + &Edit + &Szerkesztés + + + + Playlists + Lejátszási listák + + + + All files + Minden fájl + + + + &Load + &Betöltés + + + + &Save + &Mentés + + + + &Next + &Következő + + + + Pre&vious + &Előző + + + + Move &up + Mozgatás &felfelé + + + + Move &down + Mozgatás &lefelé + + + + &Repeat + &Ismétlés + + + + S&huffle + K&everés + + + + Add &current file + &Jelenlegi fájl hozzáadása + + + + Add &file(s) + Fájl(ok) &hozzáadása + + + + Add &directory + &Könyvtár hozzáadása + + + + Remove &selected + Ki&választott eltávolítása + + + + Remove &all + &Mind eltávolítása + + + + SMPlayer - Playlist + SMPlayer - Lejátszási lista + + + + Add... + Hozzáadás... + + + + Remove... + Eltávolítás... + + + + Playlist modified + Lejátszási lista módosítva + + + + There are unsaved changes, do you want to save the playlist? + Vannak el nem mentett változások, el akarja menteni a listát? + + + + Preferences + Beállítások + + + + PlaylistPreferences + + + Playlist - Preferences + Lejátszási lista - Beállítások + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Ha bejelöli, akkor egy könyvtár hozzáadásakor az alkönyvtárakban található fájlok is hozzá lesznek adva. Máskülönben csak a kijelölt könyvtárban lévő fájlok lesznek hozzáadva. + + + + &Add files in directories recursively + &Fájlok rekurzív hozzáadása könyvtárakból + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Jelölje be a fájl információk olvasásához hozzáadáskor. Ezzel megjeleníthető a cím (ha elérhető) és a fájlok hossza. Máskülönben ez az információ nem lesz elérhető a fájl lejátszásáig. Figyelem: ez az opció lassulást okozhat, különösen sok fájl hozzáadásakor. + + + + Automatically get &info about files added + Automatikos &infó kérés a hozzáadott fájlokról + + + + &Save copy of playlist on exit + &Lejátszási lista mentése kilépéskor + + + + &Play files from start + &Fájlok lejátszása az elejétől + + + + PrefAdvanced + + + Advanced + Bővített + + + + Auto + Auto + + + + &Advanced + &Bővített + + + + icon + ikon + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Itt küldhet további opciókat az MPlayer-hez +Írja őket szóközzel elválasztva. +Például: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Itt tud további videó szűrőket hozzáadni. +Írja őket ","-vel elválasztva. Ne használja a szóközt! +Például: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Audio szűrők. Hasonló módon mint a videó szűrők. +Például: resample=44100:0:0,volnorm + + + + Log MPlayer output + MPlayer kimenet naplózása + + + + Log SMPlayer output + SMPlayer kimenet naplózása + + + + This option is mainly intended for debugging the application. + Ez az opció főleg az alkalmazás hibakereséséhez szükséges. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Ennek az opciónak a bejelölése csökkentheti a vibrálást, de a videó hibás megjelenítését okozhatja. + + + + Filter for SMPlayer logs + Szűrő az SMPlayer naplókhoz + + + + &Monitor aspect: + &Monitor képarány: + + + + &Run MPlayer in its own window + &MPlayer futtatása saját ablakban + + + + &Options: + &Opciók: + + + + V&ideo filters: + V&ideó szűrők: + + + + Audio &filters: + Ha&ng szűrők: + + + + &Colorkey: + &Színkód: + + + + Log &SMPlayer output + &SMPlayer kimenet naplózása + + + + &Filter for SMPlayer logs: + S&zűrő az SMPlayer naplókhoz: + + + + C&hange... + &Csere... + + + + Logs + Naplók + + + + Log MPlayer &output + MPl&ayer kimenet naplózása + + + + Options for MP&layer + MP&layer opciók + + + + Autosave MPlayer log + MPlayer napló automatikus mentése + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Ezen opció bejelölésével az MPlayer napló minden új fájl lejátszásakor a megadott fájlba lesz mentve. Külső alkalmazások ily mód információt szerezhetnek az épp lejátszott fájlról. + + + + Autosave MPlayer log filename + Automatikusan mentett MPlayer napló fájlnév + + + + Enter here the path and filename that will be used to save the MPlayer log. + Adja meg az elérési utat és a fájlnevet az MPlayer napló mentéséhez. + + + + A&utosave MPlayer log to file + MPlayer napló a&utomatikus mentése fájlba + + + + Pass short filenames (8+3) to MPlayer + Rövid fájlnevek (8+3) küldése az MPlayernek + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Jelenleg az MPlayer nem képes megnyitni a helyi kódlapban nem szereplő karaktereket tartalmazó fájlneveket. Ezen opció bejelölésével az SMPlayer a fájlnevek rövid változatát küldi el az MPlayernek, így képes lesz megnyitni őket. + + + + &Pass short filenames (8+3) to MPlayer + &Rövid fájlnevek (8+3) küldése az MPlayernek + + + + Monitor aspect + Monitor képarány + + + + Select the aspect ratio of your monitor. + Válassza ki a monitora képarányát. + + + + Run MPlayer in its own window + MPlayer futtatása saját ablakban + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Ezen opció bejelölésével az MPlayer ablak nem lesz beágyazva az SMPlayer főablakába, hanem független ablakban fog futni. Az egér és billentyűparancsokat közvetlenül az MPlayer fogja kezelni, ez azt jelenti, hogy a gyorsgombok és az egérkattintások valószínűleg nem fognak megfelelően működni ha az MPlayer ablak van fókuszban. + + + + Colorkey + Színkód + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Ha a videó egyes részei bármely más ablakon láthatók, akkor megváltoztathatja a színkódot ennek kiküszöbölésére. Próbáljon feketéhez közeli színt választani. + + + + Options for MPlayer + MPlayer opciók + + + + Options + Opciók + + + + Here you can type options for MPlayer. Write them separated by spaces. + Itt adhat meg opciókat az MPlayernek. Írja őket szóközzel elválasztva. + + + + Video filters + Videó szűrők + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Itt tud további videó szűrőket hozzáadni az MPlayernek. Írja őket ","-vel elválasztva. Ne használja a szóközt! + + + + Audio filters + Hang szűrők + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Itt tud további hang szűrőket hozzáadni az MPlayernek. Írja őket ","-vel elválasztva. Ne használja a szóközt! + + + + Repaint the background of the video window + Videóablak hátterének újrafestése + + + + Repaint the backgroun&d of the video window + Vi&deóablak hátterének újrafestése + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + IPv4 használata hálózati kapcsolatokhoz. Automatikus visszalépés IPv6-ra. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + IPv6 használata hálózati kapcsolatokhoz. Automatikus visszalépés IPv4-re. + + + + Network Connection + Hálózati kapcsolat + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + &Naplók + + + + Rebuild index if needed + Index újjáépítése, ha szükséges + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Újraépíti a fájlok inxexét ha az nem található, ezzel lehetővé téve a keresést. Hasznos sérült/nem teljes letöltéseknél vagy hibásan készített fájloknál. Ez az opció csak akkor működik ha az adott média támogatja a keresést (pl. stdin, pipe, stb. nem). <br> Megjegyzés: az index létrehozása időt vehet igénybe. + + + + Rebuild &index if needed + &Index újjáépítése, ha szükséges + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Ha ezt bejelöli, az SMPlayer rögzíteni fogja a debug üzeneteket (napló megtekinthető itt: <b>Opciók -> Naplók megjelenítése -> SMPplayer</b>). Ez az információ nagyon hasznos lehet a fejlesztőnek a hibakeresésben. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Ha bejelöli, az SMPlayer rögzíti az MPlayer kimenetét (megtekinthető itt: <b>Opciók -> Naplók megjelenítése -> MPlayer</b>). Probléma esetén fontos információkat tartalmazhat, ezért érdemes ezt az opciót bejelölni. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Ez az opció lehetővé teszi a naplóban rögzített SMPlayer üzenetek szűrését. Ide írhat bármilyen szabályos kifejezést.Például <i>^Core::.*</i> esetén csak a <i>Core::</i> kezdetű sorok lesznek megjelenítve + + + + Correct pts + PTS korrigálása + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Az MPlayert egy kísérleti módba kapcsolja, amelyben a képkockák időcímkéi máshogyan számítódnak és támogatva lesznek az új képkockákat hozzáadó vagy a meglévők időcímkéit módosító videó szűrők. A pontosabb időcímkék észlelhetők például jelenetváltáshoz időzített feliratok lejátszásakor engedélyezett SSA/ASS könyvtárral. Korrekt PTS nélkül a felirat időzítése általában eltérhet néhány képkockával. Ez az opció nem működik helyesen néhány demuxerrel és kodekkel. + + + + Proxy + Proxy + + + + Enable proxy + Proxy használata + + + + Enable/disable the use of the proxy. + Engedélyezi/tiltja a proxy használatát. + + + + Host + Cím + + + + The host name of the proxy. + A proxy címe. + + + + Port + Port + + + + The port of the proxy. + A proxy portja. + + + + Username + Felhasználói név + + + + If the proxy requires authentication, this sets the username. + Ha a proxy azonosítást igényel, itt megadhatja a felhasználói nevet. + + + + Password + Jelszó + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + A proxy jelszava. Figyelem: a jelszó egyszerű szövegként lesz elmentve a konfigurációs fájlba. + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + Megadhatja az internetkapcsolathoz használt proxyt (jelenleg csak feliratok letöltéshez). + + + + &Enable proxy + Proxy &használata + + + + &Host: + &Cím: + + + + &Port: + &Port: + + + + &Username: + &Felhasználói név: + + + + Pa&ssword: + Jel&szó: + + + + C&orrect PTS + PTS k&orrigálása + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + Típus + + + + Select the proxy type to be used. + Válassza ki a használandó proxy típust. + + + + &Type: + &Típus: + + + + Actions list + Művelet lista + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + Itt megadhatja azon <i>műveletek</i> listáját, amelyek minden fájl megnyitásakor végrehajtódnak. Az elérhető műveletek listáját megtalálja a gyorsgomb szerkesztő <b>Billentyűzet és egér</b> részében. A műveleteket szóközzel kell elválasztani. A kapcsolható műveleteket követheti <i>true</i> vagy <i>false</i> a művelet engedélyezéshez vagy tiltáshoz. + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + Korlátozás: a műveletek csak fájl megnyitásakor futnak le és nem az mplayer folyamat újraindításakor (pl. ha más hang vagy videó szűrőt választ ki). + + + + Network + Hálózat + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + A következő műveletek f&uttatása minden fájl megnyitásakor. A műveleteket szóközzel kell elválasztani: + + + + &Network + &Hálózat + + + + Example: + Példa: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + Újjáépíti a fájlok indexét, ha az nem található, ezzel lehetővé téve a keresést. Hasznos sérült/nem teljes letöltéseknél vagy hibásan készített fájloknál. Ez az opció csak akkor működik, ha az adott média támogatja a keresést (pl. stdin, pipe, stb. esetén nem). <br> <b>Megjegyzés:</b> az index létrehozása időt vehet igénybe. + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + A proxy jelszava. <b>Figyelem:</b> a jelszó egyszerű szövegként lesz elmentve a konfigurációs fájlba. + + + + PrefAssociations + + + Warning + Figyelem + + + + Not all files could be associated. Please check your security permissions and retry. + Nem sikerült minden fájlt társítani. Ellenőrizze a jogosultságokat és próbálja újra. + + + + File Types + Fájltípusok + + + + Select all + Mindet kijelöli + + + + Check all file types in the list + Minden fájltípus kijelölése a listán + + + + Uncheck all file types in the list + Minden kijelölés törlése a listán + + + + List of file types + Fájltípusok listája + + + + File types + Fájltípusok + + + + Media files handled by SMPlayer: + SMPlayer által kezelt média fájlok: + + + + Select All + Mindet kijelöli + + + + Select None + Minden kijelölés törlése + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Jelölje be az SMPlayerrel kezelni kívánt kiterjesztéseket. Az Alkalmaz gombra kattintva a bejelölt típusok társítva lesznek az SMPlayerrel. Ha töröl egy kijelölést az eredeti társítás lesz visszaállítva. + + + + Select none + Minden kijelölés törlése + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Megjegyzés:</b> (A visszaállítás nem működik Windows Vista alatt). + + + + PrefDrives + + + Drives + Meghajtók + + + + icon + ikon + + + + CD device + CD eszköz + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Válassza ki a CD-ROM eszközt. Ez lesz használva a VCD és a Hanglemezek lejátszásához. + + + + DVD device + DVD eszköz + + + + Choose your DVD device. It will be used to play DVDs. + Válassza ki a DVD-ROM eszközt. Ez lesz használva a DVD lemezek lejátszásához. + + + + Select your &CD device: + Válassza ki a &CD eszközt: + + + + Select your &DVD device: + Válassza ki a &DVD eszközt: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + Az SMPlayer alapértelmezés szerint nem választ CD-ROM vagy DVD eszközt. Ezért mielőtt CD-t vagy DVD-t játszana le, ki kell választani a használni kívánt eszközöket (lehet ugyanaz). + + + + PrefGeneral + + + General + Általános + + + + &General + &Általános + + + + Paths + Elérési utak + + + + Media settings + Média beállítások + + + + Preferred audio and subtitles + Preferált hang és feliratok + + + + Video + Videó + + + + Start videos in fullscreen + Videók indítása teljes képernyős módban + + + + Disable screensaver + Képernyőkímélő kikapcsolása + + + + Audio + Hang + + + + Select the mplayer executable + Válassza ki az MPlayer futtatható fájlt + + + + Executables + Futtathatók + + + + All files + Minden fájl + + + + Select a directory + Válasszon egy könyvtárat + + + + MPlayer executable + MPlayer futtatható állománya + + + + Screenshots folder + Pillanatképek könyvtára + + + + Video output driver + Videó kimeneti meghajtó + + + + Audio output driver + Hang kimeneti meghajtó + + + + Select the audio output driver. + Válasszon hang kimeneti meghajtót. + + + + Remember settings + Beállítások megjegyzése + + + + Preferred audio language + Preferált hang nyelv + + + + Preferred subtitle language + Preferált felirat nyelv + + + + Software video equalizer + Szoftveres videó kiegyenlítő + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Jelölje be ezt az opciót ha a videó kiegyenlítő (EQ) nem támogatott a grafikus kártyája vagy a kiválasztott kimeneti meghajtó által.<br><b>Megjegyzés:</b> ez az opció nem kompatibilis néhány videó kimeneti meghajtóval. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Ha ezt az opciót bejelöli minden videó teljes képernyős módban lesz lejátszva. + + + + Software volume control + Szoftveres hangerőszabályzó + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Az opció bejelölésével szoftveres keverő lesz használva a hangkártya keverője helyett. + + + + Postprocessing quality + Utófeldolgozás minőség + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Az utófeldolgozás szint dinamikus váltása az elérhető CPU időtől függően. A megadott szám lesz a maximálisan használt szint. Általában használható nagy szám is. + + + + Change volume + Hangerő váltás + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Ha bejelöli az SMPlayer megpróbálja megjegyezni a hangerőt minden fájlhoz és visszaállítja, ha az újra lejátszásra kerül. Az új fájlokhoz az alapértelmezett hangerő lesz használva. + + + + 0 + 0 + + + + &Change volume on every file + &Hangerő váltása minden fájlnál + + + + Select the &MPlayer executable: + A futtatható &MPlayer állomány kiválasztása: + + + + &Folder for storing screenshots: + &Pillanatképek könyvtára: + + + + &Audio: + &Hang: + + + + &Remember settings for all files (audio track, subtitles...) + &Jegyezze meg a beállításokat az összes fájlhoz (hangsáv, feliratok...) + + + + Su&btitles: + &Feliratok: + + + + &Quality: + &Minőség: + + + + Start videos in &fullscreen + Videók indítása &teljes képernyős módban + + + + Disable &screensaver + &Képernyőkímélő kikapcsolása + + + + &Default volume: + &Alapértelmezett hangerő: + + + + Use s&oftware volume control + &Szoftveres hangerőszabályzó használata + + + + Ma&x. Amplification: + Ma&ximális erősítés: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS átengedés S/PDIF-en + + + + Direct rendering + Hardveres gyorsítás + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Ha bejelöli bekapcsolja a hardveres gyorsítást (nem támogatja minden kodek és videó kimenet)<br><b>FIGYELEM:</b> OSD/SUB hibát okozhat! + + + + Double buffering + Dupla bufferelés + + + + D&irect rendering + Hardveres &gyorsítás + + + + Dou&ble buffering + Dupla &bufferelés + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + A dupla bufferelés javítja a vibrálást úgy, hogy két képkockát tárol a memóriában, és amíg az egyiket megjeleníti, a másikat dekódolja. Ha kikapcsolja, az negatívan befolyásolhatja az OSD-t, de gyakran megszünteti az OSD vibrálást. + + + + &Enable postprocessing by default + Utófeldolgozás &bekapcsolása alapból + + + + Volume &normalization by default + Hangerő &normalizálás alapból + + + + Close when finished + Befejezés után bezár + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Ha ezt az opciót bejelöli, a főablak automatikusan bezáródik, ha az aktuális fájl/lejátszási lista véget ér. + + + + 2 (Stereo) + 2 (Sztereó) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + &Pause when minimized + &Szünet kis méretnél + + + + C&hannels by default: + &Alapértelmezett csatornák: + + + + Pause when minimized + Szünet kis méretnél + + + + Enable postprocessing by default + Utófeldolgozás bekapcsolása alapból + + + + Max. Amplification + Maximális erősítés + + + + AC3/DTS pass-through S/PDIF + AC3/DTS átengedés S/PDIF-en + + + + Volume normalization by default + Hangerő normalizálás alapból + + + + Maximizes the volume without distorting the sound. + Maximalizálja a hangerőt a hang torzítása nélkül. + + + + Default volume + Alap hangerő + + + + Sets the initial volume that new files will use. + Kezdeti hangerő, ami új fájloknál használva lesz. + + + + Channels by default + Alap csatornák + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Beállítja a maximális erősítést százalékban (alap: 110). 200-as érték esetén a hangerő maximum az alapérték kétszereséig növelhető. 100-nál kisebb értékek esetén az alap hangerő (ami 100%) a maximum felett lesz, amit pl. az OSD nem képes helyesen megjeleníteni. + + + + Uses hardware AC3 passthrough + Hardveres AC3 átengedés használata + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Lejátszási csatornák számának kérése. Az MPlayer a dekódert a hang megadott számú csatornára dekódolására kéri. A kérés teljesítése a dekóderen múlik. Ez általában csak AC3 hagkódolású videók (pl. DVD-k) lejátszásánál fontos. Abban az esetben liba52 végzi a dekódolást alapértelmezés szerint és helyesen lekeveri a hangot a kért szám csatornára. MEGJEGYZÉS: Ez az opció vonatkozik kodekekre (csak AC3), szűrőkre (surround) és hang kimeneti meghajtókra (OSS legalább is). + + + + Postprocessing will be used by default on new opened files. + Utófeldolgozás használata alapból az újonnan megnyitott fájlokon. + + + + Audio track + Hangsáv + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Meghatározza az alap hangsávot új fájlok lejátszásánál. Ha a hangsáv nem létezik akkor az első lesz használva.<br><b>Megjegyzés:</b> a <i>"preferált hang nyelv"</i> felülbírálja ezt az opciót. + + + + Subtitle track + Feliratsáv + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Meghatározza az alap feliratsávot új fájlok lejátszásánál. Ha a alapfeliratsáv nem létezik akkor az első lesz használva.<br><b>Megjegyzés:</b> a <i>preferált felirat nyelv"</i> felülbírálja ezt az opciót. + + + + Or choose a track number: + Vagy válasszon sávot: + + + + Audi&o: + Ha&ng: + + + + Preferred language: + Preferált nyelv: + + + + Preferre&d audio and subtitles + Prefe&rált hang és felirat + + + + &Subtitle: + &Felirat: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Itt megadhatja a preferált nyelvet a hang és a feliratsávokhoz. Amennyiben egy média több hang vagy feliratsávot tartalmaz, az SMPlayer megpróbálja használni a preferált nyelvet.<br>Ez csak akkor fog működni, ha a média tartalmaz információt a hang és feliratsávok nyelvéről, mint a DVD vagy mkv fájlok.<br>Ez a mező szabályos kifejezéseket fogad el. Például: <b>es|esp|spa</b> kiválasztja a sávokat, amelyek egyeznek ezekkel: <i>es</i>, <i>esp</i> vagy <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Here it goes an explanation text>For translators: don't translate this text, it will be replaced with another one at runtime. + + + + High speed &playback without altering pitch + Gyors &visszajátszás, hangmagasság változása nélkül + + + + High speed playback without altering pitch + Gyors visszajátszás, hangmagasság változása nélkül + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Lehetőséget nyújt a visszajátszási sebesség változtatására a hangmagasság változása nélkül. Legalább MPlayer dev-SVN-r24924 szükséges. + + + + Change volume just before playing + Hangerő változtatása közvetlenül a lejátszás előtt + + + + &Video + &Videó + + + + Use s&oftware video equalizer + Sz&oftveres videó kiegyenlítő használata + + + + A&udio + Ha&ng + + + + Volume + Hangerő + + + + None + Nincs + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normál) + + + + Yadif (double framerate) + Yadif (dupla képkockaszám) + + + + Linear Blend + Lineáris keverés + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Alap dei&nterlace: + + + + Deinterlace by default + Alap deinterlace + + + + Select the deinterlace filter that you want to be used for new videos opened. + Válassza ki az újonnan megnyitott fájlokhoz használandó deinterlace szűrőt. + + + + Remember time position + Időpozíció megjegyzése + + + + Remember &time position + Időpozíció &megjegyzése + + + + Change volume just before p&laying + Hangerő változtatása közvetlenül a &lejátszás előtt + + + + Enable the audio equalizer + Hang kiegyenlítő engedélyezése + + + + Check this option if you want to use the audio equalizer. + Jelölje be ezt az opciót, ha szeretné használni a hang kiegyenlítőt. + + + + &Enable the audio equalizer + Hang kiegyenlítő &engedélyezése + + + + Draw video using slices + Videó rajzolása szeletek használatával + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Engedélyezi/tiltja a videó 16 pixel magasságú szeletenkénti rajzolását. Ha ki van kapcsolva, az egész képkocka egy menetben kerül rajzolásra. A videokártyától és elérhető gyorsítótártól függően gyorsabb vagy lassabb lehet. Csak libmpeg2 és libavcodec kodekek esetén van hatása. + + + + Dra&w video using slices + &Videó rajzolása szeletek használatával + + + + &Close when finished playback + Lejátszás &befejezése után bezár + + + + fast + gyors + + + + slow + lassú + + + + fast - ATI cards + gyors - ATI kártyák + + + + User defined... + Saját beállítás... + + + + Default zoom + Alap nagyítás + + + + This option sets the default zoom which will be used for new videos. + Itt beállíthatja az új videóknál használt alapértelmezett nagyítást. + + + + Default &zoom: + Alap &nagyítás: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Itt kell beállítania a futtatható MPlayer fájlt amit az SMPlayer használni fog.<br>Az SMPlayer legalább 1.0rc1-es MPlayert igényel (bár egy friss SVN verzió ajánlott). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Ha ez a beállítás hibás, az SMPlayer semmit nem fog tudni lejátszani! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Itt lehet megadni a könyvtárat ahol az SMPlayer a készített pillanatképeket tárolja. Ha ez a mező üresen marad a pillanatkép funkció le lesz tiltva. + + + + Select the video output driver. %1 provides the best performance. + Válassza ki a videó kimeneti meghajtót. A %1 biztosítja a legjobb teljesítményt. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + A %1 az ajánlott. Próbálja elkerülni a %2 és %3 meghajtókat, lassúak és hatással lehetnek a teljesítményre. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + Az SMPlayer megjegyzi a beállításokat minden általa lejátszott fájlhoz (kiválasztott hangsáv, hangerő, szűrők...). Kapcsolja ki ezt az opciót, ha nem kívánja ezt a funkciót. + + + + If you check this option, SMPlayer will play all files from the beginning. + Ha ezt az opciót bejelöli, minden fájl lejátszása az elejéről lesz kezdve. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Ezen opció bekapcsolásával a lejátszás szünetelni fog, ha a főablakot lekicsinyíti. Az ablak visszaállításakor a lejátszás folytatódik. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Jelölje be a képernyőkímélő lejátszás közbeni tiltásához.<br>A képernyőkímélő a lejátszás végeztével engedélyezve lesz. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Itt megadhatja a preferált nyelvet a hangsávokhoz. Amennyiben egy média több hangsávot tartalmaz, az SMPlayer megpróbálja használni a preferált nyelvet.<br>Ez csak akkor fog működni, ha a média tartalmaz információt a hangsávok nyelvéről, mint a DVD vagy mkv fájlok.<br>Ez a mező szabályos kifejezéseket fogad el. Például: <b>es|esp|spa</b> kiválasztja a hangsávokat, amelyek egyeznek ezekkel: <i>es</i>, <i>esp</i> vagy <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Itt megadhatja a preferált nyelvet a feliratokhoz. Amennyiben egy média több feliratot tartalmaz, az SMPlayer megpróbálja használni a preferált nyelvet.<br>Ez csak akkor fog működni, ha a média tartalmaz információt a feliratok nyelvéről, mint a DVD vagy mkv fájlok.<br>Ez a mező szabályos kifejezéseket fogad el. Például: <b>es|esp|spa</b> kiválasztja a feliratokat, amelyek egyeznek ezekkel: <i>es</i>, <i>esp</i> vagy <i>spa</i>. + + + + Ou&tput driver: + Kimene&ti meghajtó: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Ha ez be van jelölve, a hangerő a lejátszás kezdete előtt lesz beállítva. Ezzel elkerülhető a magas hangerő a kezdésnél. Legalább MPlayer SVN r27872-t igényel. + + + + Add black borders on fullscreen + Fekete szegélyek hozzáadása teljes képernyős módban + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Ezen opció bekapcsolásával szegélyek lesznek hozzáadva a teljes képernyős képhez. Ez lehetővé teszi a feliratok megjelenítését a fekete szegélyeken. + + + + &Add black borders on fullscreen + Fekete szegélyek hozzá&adása teljes képernyős módban + + + + one ini file + egy ini fájl + + + + multiple ini files + több ini fájl + + + + Method to store the file settings + A fájl beállítások tárolásának módja + + + + This option allows to change the way the file settings would be stored. The following options are available: + Ez az opció lehetővé teszi a fájl beállítások tárolásmódjának megváltoztatását. Lehetőségek a következők: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>egy ini fájl</b>: minden lejátszott fájl beállításai egyetlen ini fájlba lesznek mentve (%1) + + + + The latter method could be faster if there is info for a lot of files. + Az utóbbi módszer gyorsabb lehet, ha sok fájlról van tárolt információ. + + + + &Store settings in + Beállítá&sok tárolása + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>több ini fájl</b>: minden lejátszott fájlhoz külön ini fájl készül. Az ini fájlok a %1 könyvtárba lesznek elmentve + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + Ha bejelöli ezt az opciót, az SMPlayer emlékezni fog a fájl utolsó pozíciójára ha legközelebb megnyitja. Ez az opció csak hagyományos fájlokkal működik (DVDk, CDk, URLek... esetén nem). + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + Ha bejelöli, bekapcsolja a hardveres gyorsítást (nem támogatja minden kodek és videó kimenet)<br><b>Figyelem:</b> OSD/felirat hibát okozhat! + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Lejátszási csatornák számának kérése. Az MPlayer a dekódert a hang megadott számú csatornára dekódolására kéri. A kérés teljesítése a dekóderen múlik. Ez általában csak AC3 hangú videók (pl. DVD-k) lejátszásánál fontos. Abban az esetben liba52 végzi a dekódolást alapértelmezés szerint és helyesen lekeveri a hangot a kért számú csatornára. <b>Megjegyzés</b>: Ez az opció vonatkozik kodekekre (csak AC3), szűrőkre (surround) és hang kimeneti meghajtókra (OSS legalább is). + + + + PrefInput + + + Keyboard and mouse + Billentyűzet és egér + + + + &Keyboard + &Billentyűzet + + + + icon + ikon + + + + &Mouse + &Egér + + + + Button functions: + Gomb műveletek: + + + + Media seeking + Média léptetés + + + + Volume control + Hangerő szabályzó + + + + Zoom video + Videó nagyítás + + + + None + Nincs + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Itt tud bármilyen billentyűparancsot megváltoztatni. Ehhez kattintson duplán vagy nyomja le az entert a gyorsgomb cellán. Opcionálisan akár le is tudja menteni a listát és megoszthatja más emberekkel vagy betöltheti egy másik gépen. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Itt tud bármilyen billentyűparancsot megváltoztatni. Ehhez kattintson duplán vagy kezdjen írni a gyorsgomb cellán. Opcionálisan akár le is tudja menteni a listát és megoszthatja más emberekkel vagy betöltheti egy másik gépen. + + + + &Left click + &Bal kattintás + + + + &Double click + &Dupla kattintás + + + + &Wheel function: + &Görgő funkció: + + + + Shortcut editor + Gyorsgomb szerkesztő + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Ebben a táblázatban megváltoztathatja a legtöbb művelethez rendelt gyorsgombokat. Kattintson duplán vagy nyomjon entert egy bejegyzésen, vagy nyomja meg a <b>Gyorsgomb cseréje</b> gombot a <i>Gyorsgomb módosítása</i> ablakba lépéshez. Két módon lehet egy gyorsgombot megváltoztatni: ha a <b>Rögzítés</b> gomb be van nyomva akkor egyszerűen nyomja meg az új gombot vagy gomb kombinációt amit a parancshoz kíván társítani (sajnos ez nem minden gombbal működik). Ha a <b>Rögzítés</b> gomb nincs benyomva akkor beírhatja a gomb teljes nevét. + + + + Left click + Bal kattintás + + + + Select the action for left click on the mouse. + Válassza ki a bal kattintáshoz rendelendő funkciót. + + + + Double click + Dupla kattintás + + + + Select the action for double click on the mouse. + Válassza ki a dupla kattintáshoz rendelendő funkciót. + + + + Wheel function + Görgő funkció + + + + Select the action for the mouse wheel. + Válassza ki az egérgörgőhöz rendelendő funkciót. + + + + Play + Lejátszás + + + + Pause + Szünet + + + + Stop + Megállítás + + + + Fullscreen + Teljes képernyő + + + + Compact + Kompakt + + + + Screenshot + Pillanatkép + + + + On top + Legfelül + + + + Mute + Némítás + + + + Frame counter + Képkocka számláló + + + + Reset zoom + Nagyítás visszaállítása + + + + Exit fullscreen + Kilépés a teljes képernyőből + + + + Double size + Dupla méret + + + + Play / Pause + Lejátszás / Szünet + + + + Pause / Frame step + Szünet / Képkocka léptetés + + + + Playlist + Lejátszási lista + + + + Preferences + Beállítások + + + + No function + Nincs funkció + + + + Change speed + Sebesség változtatás + + + + Normal speed + Normál sebesség + + + + Keyboard + Billentyűzet + + + + Mouse + Egér + + + + Middle click + Középső kattintás + + + + Select the action for middle click on the mouse. + Válassza ki a középső kattintáshoz rendelendő funkciót. + + + + M&iddle click + Középső katt&intás + + + + X Button &1 + X gomb &1 + + + + X Button &2 + X gomb &2 + + + + Go backward (short) + Vissza (rövid) + + + + Go backward (medium) + Vissza (közép) + + + + Go backward (long) + Vissza (hosszú) + + + + Go forward (short) + Előre (rövid) + + + + Go forward (medium) + Előre (közép) + + + + Go forward (long) + Előre (hosszú) + + + + OSD - Next level + OSD - Következő szint + + + + Show context menu + Helyi menü mutatása + + + + &Right click + &Jobb kattintás + + + + Increase volume + Hangerő növelése + + + + Decrease volume + Hangerő csökkentése + + + + X Button 1 + X gomb 1 + + + + Select the action for the X button 1. + Válassza ki az X gomb 1-hez rendelendő műveletet. + + + + X Button 2 + X gomb 2 + + + + Select the action for the X button 2. + Válassza ki az X gomb 2-höz rendelendő műveletet. + + + + Show video equalizer + Videó kiegyenlítő megjelenítése + + + + Show audio equalizer + Hang kiegyenlítő megjelenítése + + + + Always on top + Mindig legfelül + + + + Never on top + Sosem legfelül + + + + On top while playing + Lejátszás közben legfelül + + + + PrefInterface + + + Interface + Felület + + + + <Autodetect> + <Automatikus> + + + + Default + Alapértelmezett + + + + &Interface + &Felület + + + + Seeking + Keresés + + + + Never + Soha + + + + Whenever it's needed + Valahányszor ha szükséges + + + + Only after loading a new video + Csak egy új videó betöltése után + + + + Recent files + Utoljára megnyított fájlok + + + + Language + Nyelv + + + + Here you can change the language of the application. + Itt tudja megváltoztatni az alkalmazás nyelvét. + + + + Instances + Példányok + + + + &Short jump + &Rövid ugrás + + + + &Medium jump + &Közepes ugrás + + + + &Long jump + &Hosszú ugrás + + + + Mouse &wheel jump + Ugrás egér&görgővel + + + + &Use only one running instance of SMPlayer + &Csak egy SMPlayer példány használata + + + + Ma&x. items + Ma&x. elemek + + + + St&yle: + St&ílus: + + + + Ico&n set: + Ik&onkészlet: + + + + L&anguage: + Ny&elv: + + + + Main window + Főablak + + + + Auto&resize: + Automatikus &méretezés: + + + + R&emember position and size + Pozíció és mér&et megjegyzése + + + + Default font: + Alapértelmezett betűtípus: + + + + &Change... + &Cserél... + + + + &Behaviour of time slider: + Idő csúszka &viselkedése: + + + + Seek to position while dragging + Pozícióhoz ugrás húzás közben + + + + Seek to position when released + Pozícióhoz ugrás elengedéskor + + + + TextLabel + SzövegCímke + + + + &Seeking + Kere&sés + + + + Ins&tances + Példá&nyok + + + + Autoresize + Automata méretezés + + + + The main window can be resized automatically. Select the option you prefer. + A főablak automatikusan átméretezhető. Válassza ki a preferált opciót. + + + + Remember position and size + Pozíció és méret megjegyzése + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Ha bejelöli, a főablak pozíciója és mérete elmentésre kerül és vissza lesz állítva az SMPlayer következő futtatásakor. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Válassza ki a <b>Megnyitás->Utoljára megnyitott fájlok</b> almenüben megjelenített elemek maximális számát. Ha 0 értéket ad meg, a menü nem jelenik meg. + + + + Icon set + Ikonkészlet + + + + Select the icon set you prefer for the application. + Válassza ki az Önnek tetsző ikonkészletet az alkalmazáshoz. + + + + Style + Stílus + + + + Select the style you prefer for the application. + Válassza ki az Önnek tetsző stílust az alkalmazáshoz. + + + + Default font + Alap betűtípus + + + + You can change here the application's font. + Itt megváltoztathatja az alkalmazás betűtípusát. + + + + Short jump + Rövid ugrás + + + + Select the time that should be go forward or backward when you choose the %1 action. + Válassza ki az előre/hátra ugrás idejét a következő művelethez: %1. + + + + short jump + rövid ugrás + + + + Medium jump + Közepes ugrás + + + + medium jump + közepes ugrás + + + + Long jump + Hosszú ugrás + + + + long jump + hosszú ugrás + + + + Mouse wheel jump + Ugrás egérgörgővel + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Válassza ki az előre/hátra ugrás idejét az egérgörgő használata esetén. + + + + Behaviour of time slider + Idő csúszka viselkedése + + + + Select what to do when dragging the time slider. + Válassza ki, mi történjen az idő csúszka húzásakor. + + + + Use only one running instance of SMPlayer + Csak egy SMPlayer példány használata + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Jelölje be, ha egy már futó SMPlayer példányt kíván használni más fájlok megnyitásához. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + Az SMPlayernek figyelnie kell egy portot hogy parancsokat kaphasson más példányoktól. Megváltoztathatja a portot ha az alapértelmezettet más alkalmazás használja. + + + + Default GUI + Alap felület + + + + Mini GUI + Mini felület + + + + GUI + Felület + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Válassza ki a használni kívánt felületet. Jelenleg kétféle érhető el: Az Alap felület és a Mini felület.<br>Az <b>alap felület</b> hagyományos felületet nyújt, eszköztárral és vezérlősávval. A <b>Mini felület</b> egy egyszerűbb felületet nyújt, eszköztár nélkül és kevesebb gombbal a vezérlősávon.<br><b>Megjegyzés:</b> ez az opció az SMPlayer következő futtatásakor lép életbe. + + + + &GUI + &Felület + + + + Automatic port + Automatikus port + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + Az SMPlayernek figyelnie kell egy portot hogy parancsokat kaphasson más példányoktól. Ezen opció használatával automatikusan lesz kiválasztva egy port. + + + + Manual port + Kézi port + + + + Port to listen + Figyelendő port + + + + &Automatic + &Automatikus + + + + &Manual + &Kézi + + + + Floating control + Lebegő vezérlősáv + + + + Animated + Animált + + + + If this option is enabled, the floating control will appear with an animation. + Ha bejelöli, a lebegő vezérlősáv animálva jelenik meg. + + + + Width + Szélesség + + + + Specifies the width of the control (as a percentage). + Meghatározza a vezérlő szélességét (százalékban). + + + + Margin + Margó + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + Ez az opció meghatározza, hogy a lebegő vezérlősáv hány pixel távolságra legyen a képernyő aljától. Hasznos, ha a képernyő egy TV, mivel a kép alja lelóghat a képernyőről. + + + + Display in compact mode too + Megjelenítés kompakt módban is + + + + If this option is enabled, the floating control will appear in compact mode too. Warning: the floating control has not been designed for compact mode and it might not work properly. + Ha ez az opció engedélyezve van, a lebegő vezérlősáv kompakt módban is megjelenik. Figyelem: a lebegő vezérlősáv nem a kompakt módhoz lett tervezve, ezért hibásan működhet. + + + + Bypass window manager + Ablakkezelő megkerülése + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + Ha ez az opció be van jelölve, a vezérlősáv az ablakkezelőt megkerülve jelenik meg. Tiltsa le ezt az opciót, ha a lebegő vezérlősáv nem működik jól az ablakkezelőjével. + + + + &Floating control + &Lebegő vezérlősáv + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + A lebegő vezérlősáv teljes képernyős módban jelenik meg, ha a kurzort a képernyő aljára mozgatja. + + + + &Animated + &Animált + + + + &Width: + &Szélesség: + + + + 0 + 0 + + + + &Margin: + &Margó: + + + + Display in &compact mode too + Megjelenítés &kompakt módban is + + + + &Bypass window manager + A&blakkezelő megkerülése + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + Ha ez az opció engedélyezve van, a lebegő vezérlősáv kompakt módban is megjelenik. <b>Figyelem:</b> a lebegő vezérlősáv nem a kompakt módhoz lett tervezve, ezért hibásan működhet. + + + + Mpc GUI + MPC felület + + + + PrefPerformance + + + Performance + Teljesítmény + + + + &Performance + &Teljesítmény + + + + Priority + Prioritás + + + + Select the priority for the MPlayer process. + Válasszon egy prioritást az MPlayer folyamathoz. + + + + realtime + valós idejű + + + + high + magas + + + + abovenormal + normál feletti + + + + normal + normál + + + + belownormal + normál alatti + + + + idle + tétlen + + + + Cache + Gyorsítótár + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Gyorsítótár beállítása növelheti a teljesítményt lassú média esetén + + + + Allow frame drop + Kép eldobás engedélyezése + + + + Synchronization + Szinkronizáció + + + + Audio/video auto synchronization + Automatikus hang/videó szinkronizálás + + + + Fast audio track switching + Gyors hangsávváltás + + + + Fast seek to chapters in dvds + Gyors léptetés a fejezetekhez DVD-ken + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Állítsa be az MPlayer folyamat prioritását a Windowsban meghatározott prioritásoknak megfelelően.<br><b>Figyelem:</b> A valósidejű prioritás használata rendszerlefagyást okozhat. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Néhány képkocka elhagyása az A/V szinkron megtartásához lassú rendszereken. + + + + Allow hard frame drop + Engedélyezi a durva kép eldobást + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Intenzívebb képdobás (rontja a dekódolást). Képtorzuláshoz vezet! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Fokozatosan igazítja az A/V szinkront a mért hang késleltetés alapján. + + + + Priorit&y: + Pr&ioritás: + + + + &Allow frame drop + &Engedélyezi a képeldobást + + + + Allow &hard frame drop (can lead to image distortion) + Engedélyezi a &durva kép eldobást (a kép torzulásához vezethet) + + + + Audio/&video auto synchronization + Automatikus hang/&videó szinkronizálás + + + + Fact&or: + Té&nyező: + + + + &Fast audio track switching + &Gyors hangsávváltás + + + + Fast &seek to chapters in dvds + Gyors &léptetés a fejezetekhez DVD-ken + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Ha bejelöli, a leggyorsabb módszerrel lesz megkísérelve a fejezet léptetés, de néhány lemeznél nem működik. + + + + Skip loop filter + Hurokszűrő kihagyása + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Lehetséges értékek:<br> <b>Igen</b>: hangsávváltás a leggyorsabb módszerrel (néhány formátumnál nem működik).<br> <b>Nem</b>: az MPlayer folyamat újraindul minden hangsávváltáskor.<br> <b>Auto</b>: az SMPlayer dönti el az MPlayer verzió alapján. + + + + Cache for files + Fájl gyorsítótár + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Ez az opció határozza meg, mennyi memória legyen használva fájlok buffereléséhez (kBájtban). + + + + Cache for streams + Adatfolyam gyorsítótár + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Ez az opció határozza meg, mennyi memória legyen használva URL-ek buffereléséhez (kBájtban). + + + + Cache for DVDs + DVD gyorsítótár + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Ez az opció határozza meg, mennyi memória (kBájtban) legyen használva DVDk buffereléséhez.<br><b>Figyelem:</b> Előfordulhat, hogy a keresés (illetve a fejezetváltás) nem fog megfelelően működni DVD gyorsítótár használatakor. + + + + &Cache + &Gyorsítótár + + + + Cache for &DVDs: + &DVD gyorsítótár: + + + + Cache for &local files: + &Helyi fájl gyorsítótár: + + + + Cache for &streams: + &Adatfolyam gyorsítótár: + + + + Enabled + Engedélyezve + + + + Skip (always) + Kihagy (mindig) + + + + Skip only on HD videos + Kihagyás HD videó esetén + + + + Loop &filter + Hurok&szűrő + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Ez az opció lehetővé teszi a hurokszűrő (deblocking) kihagyását H.264 dekódoláskor. Mivel a szűrt képkocka a referencia a tőle függő képkockák dekódolásához, ezért ez rosszabb hatással van a minőségre, mint a deblocking kihagyása pl. MPEG-2 videón. De legalább magas bitrátájú HDTV esetén ez nagy sebességnövekedést ad látható minőségromlás nélkül. + + + + Possible values: + Lehetséges értékek: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Engedélyezve</b>: a hurokszűrő nincs kihagyva + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Kihagy (mindig)</b>: a hurokszűrő a videó felbontásától függetlenül kihagyva + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Kihagyás HD videó esetén</b>: a hurokszűrő csak %1 vagy nagyobb magasságú videók esetén lesz kihagyva. + + + + Cache for audio CDs + Audió CD gyorsítótár + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Ez az opció határozza meg, mennyi memória legyen használva audió CD-k buffereléséhez (kBájtban). + + + + Cache for &audio CDs: + Audió &CD gyorsítótár: + + + + Cache for VCDs + VCD gyorsítótár + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Ez az opció határozza meg, mennyi memória legyen használva VCD-k buffereléséhez (kBájtban). + + + + Cache for &VCDs: + &VCD gyorsítótár: + + + + Threads for decoding + Dekódolási szálak + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Beállítja a dekódoláshoz használt szálak számát. Csak MPEG-1/2 és H.264 esetén + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Dekódolási szálak (csak MPEG-1/2 és H.264 esetén): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + Állítsa be az MPlayer folyamat prioritását a Windowsban meghatározott prioritásoknak megfelelően.<br><b>Figyelem:</b> A valós idejű prioritás használata rendszerlefagyást okozhat. + + + + PrefPlaylist + + + Playlist + Lejátszási lista + + + + Automatically add files to playlist + Fájlok automatikus hozzáadása a lejátszási listához + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Ha ez az opció engedélyezve van, egy fájl megnyitásakor az SMPlayer törli a lejátszási listát és hozzáadja a fájlt. DVDk, CDk és VCDk esetén a lemezen található minden szám hozzá lesz adva. + + + + Add consecutive files + Soron következő fájok hozzáadása + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Ha ez az opció engedélyezve van, az SMPlayer soron következő fájlokat keres (pl. video_1.avi, video_2.avi...) és ha talál, hozzáadja őket a lejátszási listához. + + + + &Playlist + Lejátszási l&ista + + + + &Automatically add files to playlist + Fájlok &automatikus hozzáadása a lejátszási listához + + + + Add &consecutive files + Soron &következő fájok hozzáadása + + + + PrefSubtitles + + + Subtitles + Feliratok + + + + Choose a ttf file + Válasszon egy TTF fájlt + + + + Truetype Fonts + Truetype fontok (*.ttf) + + + + &Subtitles + &Feliratok + + + + Autoload + Automatikus betöltés + + + + Same name as movie + A filmmel azonos névvel + + + + All subs containing movie name + Minden felirat, amely tartalmazza a film nevét + + + + All subs in directory + Minden felirat a könyvtárban + + + + Position + Pozíció + + + + 0 + 0 + + + + Top + Fent + + + + Bottom + Lent + + + + Include subtitles on screenshots + Feliratok beépítése a pillanatképekbe + + + + Font + Betűtípus + + + + Select the font which will be used for subtitles (and OSD): + Válasszon egy betűtípust a feliratokhoz (és OSD-hez ): + + + + Size + Méret + + + + No autoscale + Nincs automatikus méretezés + + + + Proportional to movie height + A film magasságához megfelelő + + + + Proportional to movie width + A film szélességéhez megfelelő + + + + Proportional to movie diagonal + A film átlójához megfelelő + + + + Subtitle position + Felirat pozíciója + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Ez az opció meghatározza a felirat pozícióját a videó ablakban. <i>100</i> az alját, míg <i>0</i> a tetejét jelenti. + + + + Au&toload subtitles files (*.srt, *.sub...): + Feliratfájlok au&tomatikus betöltése (*.srt, *.sub...): + + + + S&elect first available subtitle + Az első &elérhető felirat kiválasztása + + + + &Default subtitle encoding: + &Alapértelmezett felirat kódolás: + + + + Default &position of the subtitles on screen + A feliratok alapértelmezett &pozíciója a képernyőn + + + + &Include subtitles on screenshots + &Feliratok beépítése a pillanatképekbe + + + + &TTF font: + &TTF betűtípus: + + + + S&ystem font: + &Rendszer betűtípus: + + + + A&utoscale: + A&utomatikus méret: + + + + Select first available subtitle + Az első elérhető felirat kiválasztása + + + + Default subtitle encoding + Alapértelmezett felirat kódolás + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Ha ez az opció be van jelölve, a feliratok meg fognak jelenni a pillanatképeken. Megjegyzés: néha gondot okozhat. + + + + TTF font + TTF betűtípus + + + + System font + Rendszer betűtípus + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Itt kiválaszthatja a feliratokhoz és OSD-hez használt rendszer betűtípust. <b>Megjegyzés:</b> fontconfig-ot támogató MPlayer szükséges. + + + + Autoscale + Automatikus méret + + + + Text color + Szöveg színe + + + + Select the color for the text of the subtitles. + Válassza ki a felirat szöveg színét. + + + + Border color + Szegély szín + + + + Select the color for the border of the subtitles. + Válassza ki a felirat szegély színét. + + + + Select the subtitle autoload method. + Válassza ki a felirat automata betöltés módját. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Ha egy vagy több feliratsáv érhető el, akkor automatikusan ki lesz választva az egyik, általában az első, bár ha valamelyik egyezik a felhasználó preferált nyelvével, akkor az lesz használva. + + + + Select the subtitle autoscaling method. + Válassza ki a felirat automata méretezés módját. + + + + Select the encoding which will be used for subtitle files by default. + Válassza ki a felirat fájlokhoz használt alapértelmezett kódolást. + + + + Try to autodetect for this language + Automatikus felismerés ehhez a nyelvhez + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Ha ez az opció aktív, a feliratok kódolásának megállapítása az adott nyelvhez lesz megpróbálva. Ha az automatikus felismerés sikertelen, az alap kódolás lesz használva. Ez az opció ENCA támogatással fordított MPlayert igényel. + + + + Subtitle language + Felirat nyelve + + + + Select the language for which you want the encoding to be guessed automatically. + Válassza ki az automatikus kódolás megállapításhoz használt nyelvet. + + + + Encoding + Kódolás + + + + Try to a&utodetect for this language: + A&utomatikus felismerés ehhez a nyelvhez: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Itt kiválaszthatja a feliratokhoz használt TTF betűtípust. Általában sok TTF betűtípust találhat itt: %1 + + + + Outline + Körvonal + + + + Select the font for the subtitles. + Válassza ki a betűtípust a feliratokhoz. + + + + The size in pixels. + A méret pixelben. + + + + Bold + Félkövér + + + + If checked, the text will be displayed in <b>bold</b>. + Ha bejelöli, a szöveg <b>félkövéren<b> jelenik meg. + + + + Italic + Dőlt + + + + If checked, the text will be displayed in <i>italic</i>. + Ha bejelöli, a szöveg <i>dőlten<i> jelenik meg. + + + + Left margin + Bal margó + + + + Specifies the left margin in pixels. + Beállítja a bal margót pixelekben. + + + + Right margin + Jobb margó + + + + Specifies the right margin in pixels. + Beállítja a jobb margót pixelekben. + + + + Vertical margin + Függőleges margó + + + + Specifies the vertical margin in pixels. + Beállítja a függőleges margót pixelekben. + + + + Horizontal alignment + Vízszintes igazítás + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + Beállítja a vízszintes igazítást. Lehetséges értékek: bal, közép és jobb. + + + + Vertical alignment + Függőleges igazítás + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + Beállítja a függőleges igazítást. Lehetséges értékek: lent, középen és fent. + + + + Border style + Szegély stílus + + + + Specifies the border style. Possible values: outline and opaque box. + Meghatározza a szegély stílusát. Lehetséges értékek: körvonal és átlátszatlan doboz. + + + + Shadow + Árnyék + + + + Si&ze: + &Méret: + + + + Bol&d + Fé&lkövér + + + + &Italic + Dő&lt + + + + Colors + Színek + + + + &Text: + &Szöveg: + + + + &Border: + Sze&gély: + + + + Margins + Margók + + + + L&eft: + &Bal: + + + + &Right: + &Jobb: + + + + Verti&cal: + Fü&ggőleges: + + + + Alignment + Igazítás + + + + &Horizontal: + Ví&zszintes: + + + + &Vertical: + &Függőleges: + + + + Border st&yle: + Szegély stíl&us: + + + + &Outline: + Kör&vonal: + + + + Shado&w: + Ár&nyék: + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + A következő opciók lehetővé teszik a nem stílusos feliratokhoz (srt, sub...) használt stílus megadását. + + + + Left + horizontal alignment + Bal + + + + Centered + horizontal alignment + Közép + + + + Right + horizontal alignment + Jobb + + + + Bottom + vertical alignment + Lent + + + + Middle + vertical alignment + Közép + + + + Top + vertical alignment + Fent + + + + Outline + border style + Körvonal + + + + Opaque box + border style + Átlátszatlan doboz + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + Ha a szegély stílusa <i>körvonal</i>, ez az opció meghatározza a szöveg körüli körvonal vastagságát pixelekben. + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + Ha a szegély stílusa <i>körvonal</i>, ez az opció meghatározza a szöveg mögötti árnyék mélységét pixelekben. + + + + Enable normal subtitles + Normál feliratok engedélyezése + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + Kattintson erre a gombra a normál/hagyományos feliratok kiválasztásához. Az ilyen feliratok csak fehér szöveget tudnak megjeleníteni. + + + + Enable SSA/ASS subtitles + SSA/ASS feliratok engedélyezése + + + + Normal subtitles + Normál feliratok + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + Ez az opció NEM változtatja meg a feliratok méretét a jelenlegi videóban. Ahhoz használja a <i>Méret+</i> és <i>Méret-</i> parancsokat a felirat menüben. + + + + Default scale + Alap méret + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + Ez az opció meghatározza a normál feliratokhoz használt alap betűméretet újonnan megnyitott fájloknál. + + + + SSA/ASS subtitles + SSA/ASS feliratok + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + Ez az opció meghatározza az SSA/ASS feliratokhoz használt alap betűméretet újonnan megnyitott fájloknál. + + + + Line spacing + Sorköz + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + Meghatározza a sorokat elválasztó távolságot. Negatív érték is használható. + + + + &Font and colors + &Betűtípus és színek + + + + Enable &normal subtitles + &Normál feliratok engedélyezése + + + + Enable SSA/&ASS subtitles + SSA/&ASS feliratok engedélyezése + + + + Default s&cale: + Alap &méret: + + + + Defa&ult scale: + Ala&p &méret: + + + + &Line spacing: + So&rköz: + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + Kattintson erre a gombra az új SSA/ASS könyvtár engedélyezéséhez. Ez lehetővé teszi a feliratok megjelenítését több színnel, betűtípussal... + + + + Freetype support + Freetype támogatás + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + Általában nem ajánlott letiltani ezt az opciót, kivéve ha az MPlayerje freetype támogatás nélkül lett fordítva. <b>Az opció letiltásával előfordulhat, hogy a feliratok egyáltalán nem fognak működni!</b> + + + + Freet&ype support + Freet&ype támogatás + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + Ha ez az opció be van jelölve, a feliratok meg fognak jelenni a pillanatképeken. <b>Megjegyzés:</b> néha gondot okozhat. + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Súgó + + + + OK + OK + + + + Cancel + Mégsem + + + + Apply + Alkalmaz + + + + Help + Súgó + + + + SMPlayer - Preferences + SMPlayer - Beállítások + + + + QObject + + + will show this message and then will exit. + megjeleníti ezt az üzenetet és kilép. + + + + the main window will be closed when the file/playlist finishes. + a főablak bezáródik, ha a fájl/lejátszási lista véget ért. + + + + This is SMPlayer v. %1 running on %2 + Ez az SMPlayer v. %1 ami %2 -n fut + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + megpróbál kapcsolódni egy másik futó példányhoz és elküldeni neki a megadott műveletet. Példa: -send-action pause A többi opció (ha van) figyelmen kívül lesz hagyva és az alkalmazás kilép. Siker esetén 0-t, hiba esetén -1-t ad vissza. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list szóközökkel elválasztott műveletek listája. A műveletek a fájl (ha van) betöltése után kerülnek végrehajtásra a megadott sorrendben. Váltható műveletekhez true vagy false küldhető paraméterként. Példa: -actions "fullscreen compact true". Idézőjelek szükségesek ha egynél több paramétert küld. + + + + media + média + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + ha fut másik példány, a média annak a példánynak a lejátszási listájába kerül. Ha nincs másik példány, ez az opció figyelmen kívül lesz hagyva és a fájl új példányban nyílik meg. + + + + the main window won't be closed when the file/playlist finishes. + a főablak nem zárul be, ha a fájl/lejátszási lista véget ér. + + + + the video will be played in fullscreen mode. + a videó teljes képernyős módban lesz lejátszva. + + + + the video will be played in window mode. + a videó ablakos módban lesz lejátszva. + + + + Enqueue in SMPlayer + Sorba állítás az SMPlayerben + + + + opens the mini gui instead of the default one. + a Mini felületet nyitja meg az Alap helyett. + + + + Restores the old associations and cleans up the registry. + Visszaállítja a régi társításokat és kitakarítja a regisztrációs adatbázist. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' bármely fájl amit az SMPlayer meg tud nyitni. Lehet egy helyi fájl, egy DVD (pl. dvd://1), egy internet adatfolyam (pl. mms://....) vagy egy helyi lejátszási lista m3u vagy pls formátumban. Ha a -playlist opció van használva, azt jelenti hogy az SMPlayer átadja a -playlist opciót az MPlayernek, így az MPlayer fogja kezelni a listát az SMPlayer helyett. + + + + Usage: + Használat: + + + + directory + könyvtár + + + + action_name + művelet_név + + + + action_list + művelet_lista + + + + opens the default gui. + megnyitja az Alap felületet. + + + + subtitle_file + felirat_fájl + + + + specifies the subtitle file to be loaded for the first video. + meghatározza az első videóhoz betöltendő felirat fájlt. + + + + %1 second(s) + + %1 másodperc + + + + + %1 minute(s) + + %1 perc + + + + + %1 and %2 + %1 és %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + meghatározza a könyvtárat ahol az SMPlayer a konfigurációs fájljait (smplayer.ini, smplayer_files.ini...) tárolni fogja + + + + disabled + aspect_ratio + tiltva + + + + auto + aspect_ratio + auto + + + + unknown + aspect_ratio + ismeretlen + + + + opens the mpc gui. + megnyitja az MPC felületet. + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + ZIP/UNZIP API hiba %1 + + + + SeekWidget + + + icon + ikon + + + + label + címke + + + + ShortcutGetter + + + Modify shortcut + Gyorsgomb módosítása + + + + Clear + Töröl + + + + Press the key combination you want to assign + Nyomja le a billentyűkombinációt a hozzárendeléshez + + + + Capture + Rögzítés + + + + Capture keystrokes + Lenyomott billentyűk rögzítése + + + + SubChooserDialog + + + Subtitle selection + Felirat kiválasztás + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Ez az archívum több feliratfájlt tartalmaz. Válassza ki a kicsomagolandókat. + + + + Select All + Mindet kijelöli + + + + Select None + Minden kijelölés törlése + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Keresés + + + + &Jump to: + &Ugrás: + + + + TristateCombo + + + Auto + Auto + + + + Yes + Igen + + + + No + Nem + + + + VideoEqualizer + + + Contrast + Kontraszt + + + + Brightness + Fényerő + + + + Hue + Színárnyalat + + + + Saturation + Telítettség + + + + Gamma + Gamma + + + + &Reset + Ala&phelyzet + + + + &Set as default values + Beállítá&s alapértéknek + + + + Use the current values as default values for new videos. + A jelenlegi értékek használata mint alapérték az új videókhoz. + + + + Set all controls to zero. + Minden vezérlő nullára állítása. + + + + Video Equalizer + Videó kiegyenlítő + + + + Information + Információ + + + + The current values have been stored to be used as default. + A jelenlegi értékek el lettek mentve alapértelmezettnek. + + + + VideoPreview + + + Video preview + Videó előnézet + + + + Cancel + Mégsem + + + + Generated by SMPlayer + SMPlayerrel generálva + + + + Creating thumbnails... + Bélyegképek létrehozása... + + + + Size: %1 MB + Méret: %1 MB + + + + Length: %1 + Hossz: %1 + + + + Save file + Fájl mentése + + + + Images (*.png *.jpg) + Képek (*.png *.jpg) + + + + Error saving file + Hiba a fájl mentése közben + + + + The file couldn't be saved + A fájlt nem lehetett menteni + + + + Error + Hiba + + + + The following error has occurred while creating the thumbnails: + A következő hiba lépett fel a bélyegképek létrehozása közben: + + + + The temporary directory (%1) can't be created + Az átmeneti könyvtár (%1) nem hozható létre + + + + The mplayer process didn't run + Az mplayer folyamat nem futott + + + + Resolution: %1x%2 + Felbontás: %1x%2 + + + + Video format: %1 + Videó formátum: %1 + + + + Frames per second: %1 + Képkocka / másodperc: %1 + + + + Aspect ratio: %1 + Méretarány: %1 + + + + Video bitrate: %1 kbps + Videó bitráta: %1 kbps + + + + Audio bitrate: %1 kbps + Hang bitráta: %1 kbps + + + + Audio rate: %1 Hz + Hang mintavételezés: %1 Hz + + + + The file %1 can't be loaded + A %1 fájl nem lehet betölteni + + + + No filename + Nincs fájlnév + + + + The mplayer process didn't start while trying to get info about the video + Az mplayer folyamat nem indult el a videó információinak lekérdezése közben + + + + The length of the video is 0 + A videó hossza 0 + + + + The file %1 doesn't exist + %1 fájl nem létezik + + + + Images + Képek + + + + No info + Nincs információ + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + Videó bitráta: %1 + + + + Audio bitrate: %1 + Hang bitráta: %1 + + + + Audio rate: %1 + Hang mintavételezés: %1 + + + + VideoPreviewConfigDialog + + + Default + Alapértelmezett + + + + Video Preview + Videó előnézet + + + + &File: + &Fájl: + + + + &Columns: + &Oszlopok: + + + + &Rows: + &Sorok: + + + + Add playing time to thumbnails + Lejátszási idő hozzáadása a bélegképekhez + + + + &Aspect ratio: + &Méretarány: + + + + &Seconds to skip at the beginnning: + &Kezdésnél kihagyandó másodpercek: + + + + &Maximum width: + &Maximális szélesség: + + + + The preview will be created for the video you specify here. + Az itt megadott videóról fog előnézet készülni. + + + + The thumbnails will be arranged on a table. + A bélyegképek táblázatba lesznek rendezve. + + + + This option specifies the number of columns of the table. + Ez az opció meghatározza a táblázat oszlopainak számát. + + + + This option specifies the number of rows of the table. + Ez az opció meghatározza a táblázat sorainak számát. + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + Ha bejelöli ezt az opciót, a lejátszási idő megjelenik minden bélyegkép alján. + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + Ha a videó méretaránya hibás, itt megadhat egy másikat. + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + Általában az első képkockák feketék, ezért ajánlott pár másodpercet kihagyni a videó elejéről. Ez az opció lehetővé teszi a kihagyandó másodpercek számának megadását. + + + + This option specifies the maximum width in pixels that the generated preview image will have. + Ez az opció meghatározza a generált előnézeti kép maximális szélességét pixelekben. + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + Az előnézet létrehozásához néhány képkocka ki lesz bontva a videóból. Itt kiválaszthatja a kibontott képkockák képformátumát. A PNG jobb minőséget eredményezhet. + + + + Add playing &time to thumbnails + Lejá&tszási idő hozzáadása a bélyegképekhez + + + + &Extract frames as + &Képkockák kibontása mint + + + + Enter here the DVD device or a folder with a DVD image. + Adja meg itt a DVD eszközt vagy egy könyvtárat a DVD képfájllal. + + + + &DVD device: + &DVD eszköz: + + + + VolumeSliderAction + + + Volume + Hangerő + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_it.ts b/plugins/smplayer_plugin/translations/smplayer_it.ts new file mode 100644 index 000000000..4043080e6 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_it.ts @@ -0,0 +1,7293 @@ + + + + About + + + Version: %1 + Versione: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Questo programma è free software; è possibile modificarlo e/o ridistribuirlo sotto i termini della licenza GNU General Public License come indicato dalla Free Software Foundation; sia la versione 2 della licenza, o (a vostra scelta) ogni successiva versione. + + + + The following people have contributed with translations: + Le seguenti persone hanno contribuito con le traduzioni: + + + + German + Tedesco + + + + Slovak + Slovacco + + + + Italian + Italiano + + + + French + Francese + + + + %1, %2 and %3 + %1, %2 e %3 + + + + Simplified-Chinese + Cinese semplificato + + + + Russian + Russo + + + + %1 and %2 + %1 e %2 + + + + Hungarian + Ungherese + + + + Polish + Polacco + + + + Japanese + Giapponese + + + + Dutch + Olandese + + + + Ukrainian + Ucraino + + + + Portuguese - Brazil + Portoghese (Brasile) + + + + Georgian + Georgiano + + + + Czech + Ceco + + + + Bulgarian + Bulgaro + + + + Turkish + Turco + + + + Swedish + Svedese + + + + Serbian + Serbo + + + + Traditional Chinese + Cinese tradizionale + + + + Romanian + Romeno + + + + Portuguese - Portugal + Portoghese (Portogallo) + + + + Greek + Greco + + + + Finnish + Finlandese + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Informazioni su SMPlayer + + + + &Info + &Informazioni + + + + icon + icona + + + + &Contributions + &Contributi + + + + &Translators + &Traduttori + + + + &License + &Licenza + + + + Visit our web for updates: + Visita il nostro sito per aggiornamenti: + + + + Get help in our forum: + Cerca aiuto nel nostro forum: + + + + You can support SMPlayer by making a donation. + Puoi sostenere SMPlayer con una donazione. + + + + More info + Maggiori informazioni + + + + Korean + Coreano + + + + Macedonian + Macedone + + + + Basque + Basco + + + + Using MPlayer %1 + MPlayer %1 in uso + + + + Catalan + Catalano + + + + Portable Edition + Edizione portabile + + + + Using Qt %1 (compiled with Qt %2) + Qt %1 in uso (compilato con Qt %2) + + + + Slovenian + Sloveno + + + + Arabic + Arabo + + + + Kurdish + Curdo + + + + Galician + Galiziano + + + + The following people have contributed with patches (see the changelog for details): + Le seguenti persone hanno contribuito con patch (vedi il changelog per i dettagli): + + + + If there's any omission, please report. + Se vi sono delle mancanze, per favore segnalare. + + + + SMPlayer logo by %1 + Logo di SMPlayer creato da %1 + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Nome + + + + Description + Descrizione + + + + Shortcut + Scorciatoia + + + + &Save + &Salva + + + + &Load + &Apri + + + + Key files + File chiave + + + + Choose a filename + Scegli il nome del file + + + + Confirm overwrite? + Confermi sovrascrittura? + + + + The file %1 already exists. +Do you want to overwrite? + Il file %1 esiste già. +Vuoi sovrascriverlo? + + + + Choose a file + Scegli un file + + + + Error + Errore + + + + The file couldn't be saved + Non è stato possibile salvare il file + + + + The file couldn't be loaded + Non è stato possibile caricare il file + + + + &Change shortcut... + &Cambia scorciatoia... + + + + AudioEqualizer + + + Audio Equalizer + Equalizzatore Audio + + + + 31.25 Hz + 31,25 Hz + + + + 62.50 Hz + 62,50 Hz + + + + 125.0 Hz + 125,0 Hz + + + + 250.0 Hz + 250,0 Hz + + + + 500.0 Hz + 500,0 Hz + + + + 1.000 kHz + 1,000 kHz + + + + 2.000 kHz + 2,000 kHz + + + + 4.000 kHz + 4,000 kHz + + + + 8.000 kHz + 8,000 kHz + + + + 16.00 kHz + 16,00 kHz + + + + &Apply + &Applica + + + + &Reset + &Reset + + + + &Set as default values + &Salva come valori predefiniti + + + + Use the current values as default values for new videos. + Usa i valori correnti come valori predefiniti per i nuovi video. + + + + Set all controls to zero. + Metti a zero tutti i controlli + + + + Information + Informazioni + + + + The current values have been stored to be used as default. + I valori correnti sono stati salvati come predefiniti. + + + + BaseGui + + + &File... + &File... + + + + D&irectory... + C&artella... + + + + &Playlist... + Lista di ri&produzione... + + + + &DVD from drive + &DVD dall'unità + + + + D&VD from folder... + D&VD da una cartella... + + + + &URL... + &URL... + + + + P&lay + &Riproduci + + + + &Pause + &Pausa + + + + &Stop + &Stop + + + + &Frame step + Avanza per &fotogramma + + + + &Repeat + &Ripeti + + + + &Normal speed + Velocità &normale + + + + &Halve speed + &Dimezza velocità + + + + &Double speed + &Raddoppia velocità + + + + Speed &-10% + Velocità &-10% + + + + Speed &+10% + Velocità &+10% + + + + Sp&eed + V&elocità + + + + &Fullscreen + T&utto schermo + + + + &Compact mode + Modalità &compatta + + + + &Equalizer + &Equalizzatore + + + + &Screenshot + &Schermata + + + + S&tay on top + Tieni s&opra le altre + + + + &Postprocessing + &Postprocessing + + + + &Autodetect phase + &Autodetect della fase + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + Aggiungi r&umore + + + + F&ilters + &Filtri + + + + &Mute + &Muto + + + + Volume &- + Volume &- + + + + Volume &+ + Volume &+ + + + + &Delay - + &Ritardo - + + + + D&elay + + R&itardo + + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtri + + + + &Load... + &Apri... + + + + Delay &- + Ritardo &- + + + + Delay &+ + Ritardo &+ + + + + &Up + &Sù + + + + &Down + G&iù + + + + &Playlist + &Lista di riproduzione + + + + &Show frame counter + Mostra &contatore fotogrammi + + + + P&references + P&referenze + + + + &View logs + &Vedi log + + + + About &Qt + Informazioni &Qt + + + + About &SMPlayer + Informazioni su &SMPlayer + + + + &Open + &Apri + + + + &Play + &Riproduci + + + + &Video + &Video + + + + &Audio + &Audio + + + + &Subtitles + &Sottotitoli + + + + &Browse + S&foglia + + + + Op&tions + &Opzioni + + + + &Help + A&iuto + + + + &Recent files + File &recenti + + + + &Clear + &Pulisci + + + + Si&ze + Grande&zza + + + + &Aspect ratio + Rapporto d'&aspetto + + + + &Deinterlace + &Deinterlaccia + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &a 16:9 + + + + &None + &Nessuno + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + &Blend Lineare + + + + &Channels + &Canali + + + + &Stereo mode + Modo &stereo + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Left channel + Canale &Sinistro + + + + &Right channel + Canale &Destro + + + + &Select + &Seleziona + + + + &Title + &Titolo + + + + &Chapter + &Capitolo + + + + &Angle + &Angolo + + + + &OSD + &OSD + + + + &Disabled + &Disabilitato + + + + &Seek bar + &Barra di ricerca + + + + &Time + &Tempo + + + + Time + T&otal time + T&empo + Tempo totale + + + + SMPlayer - mplayer log + SMPlayer - Log di mplayer + + + + SMPlayer - smplayer log + SMPlayer - Log di smplayer + + + + <empty> + <vuoto> + + + + Video + Video + + + + Audio + Audio + + + + Playlists + Liste di riproduzione + + + + All files + Tutti i file + + + + Choose a file + Scegli un file + + + + SMPlayer - Information + SMPlayer - Informazioni + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Le unità CDROM / DVD non sono ancora configurate. +Si aprirà ora il dialogo di configurazione, in modo che tu possa farlo. + + + + + Choose a directory + Scegli una cartella + + + + Subtitles + Sottotitoli + + + + About Qt + Informazioni Qt + + + + Playing %1 + In riproduzione %1 + + + + Pause + Pausa + + + + Stop + Stop + + + + Play / Pause + Riproduci / Pausa + + + + Pause / Frame step + Pausa / Per fotogramma + + + + U&nload + &Rimuovi + + + + V&CD + V&CD + + + + C&lose + C&hiudi + + + + View &info and properties... + &Informazioni e proprietà... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Reset + + + + Move &left + Muovi a &sinistra + + + + Move &right + Muovi a &destra + + + + Move &up + Manda &su + + + + Move &down + Manda &giù + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + Linea &precedente nei sottotitoli + + + + N&ext line in subtitles + Linea succ&essiva nei sottotitoli + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Abbassa volume (2) + + + + Inc volume (2) + Alza volume (2) + + + + Exit fullscreen + Esci da tutto schermo + + + + OSD - Next level + OSD - Livello successivo + + + + Dec contrast + Diminuisci contrasto + + + + Inc contrast + Aumenta contrasto + + + + Dec brightness + Diminuisci luminosità + + + + Inc brightness + Aumenta luminosità + + + + Dec hue + Diminuisci tonalità + + + + Inc hue + Aumenta tonalità + + + + Dec saturation + Diminuisci saturazione + + + + Dec gamma + Diminuisci gamma + + + + Next audio + Audio successivo + + + + Next subtitle + Sottotitoli successivi + + + + Next chapter + Capitolo successivo + + + + Previous chapter + Capitolo precedente + + + + Inc saturation + Aumenta saturazione + + + + Inc gamma + Aumenta gamma + + + + &Load external file... + Apri file &esterno... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normale) + + + + Y&adif (double framerate) + Y&adif (framerate doppio) + + + + &Next + &Prossimo + + + + Pre&vious + P&recedente + + + + Volume &normalization + &Normalizzazione volume + + + + &Audio CD + CD &Audio + + + + Denoise nor&mal + Denoise nor&male + + + + Denoise &soft + Denoise &moderato + + + + Denoise o&ff + &Nessun denoise + + + + Use SSA/&ASS library + Usa la libreria SSA/&ASS + + + + Flip i&mage + Ribalta i&mmagine + + + + &Toggle double size + &Grandezza doppia + + + + S&ize - + G&randezza - + + + + Si&ze + + G&randezza + + + + + Add &black borders + Aggiungi &bordi neri + + + + Soft&ware scaling + Scalatura soft&ware + + + + &FAQ + &FAQ + + + + Visualize &motion vectors + Visualizza vettori di &movimento + + + + &Command line options + Opzioni a linea di &comando + + + + SMPlayer command line options + Opzioni a linea di comando per SMPlayer + + + + Enable &closed caption + Abilita &closed caption + + + + &Forced subtitles only + Solo sottotitoli &forzati + + + + Reset video equalizer + Reinizializza equalizzatore video + + + + MPlayer has finished unexpectedly. + MPlayer si è fermato inaspettatamente. + + + + Exit code: %1 + Codice di uscita: %1 + + + + MPlayer failed to start. + MPlayer non è riuscito a partire. + + + + Please check the MPlayer path in preferences. + Controlla il percorso dell'eseguibile MPlayer nelle preferenze. + + + + MPlayer has crashed. + MPlayer è andato in crash. + + + + See the log for more info. + Controlla i log per maggiori informazioni. + + + + &Rotate + &Ruota + + + + &Off + &Disattivo + + + + &Rotate by 90 degrees clockwise and flip + &Ruota di 90° in senso orario e ribalta + + + + Rotate by 90 degrees &clockwise + Ruota di 90° in senso &orario + + + + Rotate by 90 degrees counterclock&wise + Ruota di 90° in senso &antiorario + + + + Rotate by 90 degrees counterclockwise and &flip + Ruota di 90° in senso antiorario e &ribalta + + + + &Jump to... + &Salta a... + + + + Show context menu + Mostra menù contestuale + + + + Multimedia + Multimedia + + + + E&qualizer + E&qualizzatore + + + + Reset audio equalizer + Reinizializza equalizzatore audio + + + + Find subtitles on &OpenSubtitles.org... + Trova sottotitoli su &Opensubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + &Upload sottotitoli su Opensubtitles.org... + + + + &Tips + Suggerimen&ti + + + + &Auto + &Automatico + + + + Speed -&4% + Velocità -&4% + + + + &Speed +4% + Velocità +&4% + + + + Speed -&1% + Velocità -&1% + + + + S&peed +1% + Velocità &+1% + + + + Scree&n + Sche&rmo + + + + &Default + &Predefinito + + + + Mirr&or image + Specc&hia immagine + + + + Next video + Prossimo video + + + + &Track + video + &Traccia + + + + &Track + audio + &Traccia + + + + Warning - Using old MPlayer + Attenzione - Vecchio MPlayer in uso + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + La versione di MPlayer (%1) installata su questo sistema è obsoleta, SMPlayer non può funzionare bene con essa: alcune opzioni non andranno, la selezione dei sottotitoli potrebbe non riuscire... + + + + Please, update your MPlayer. + Per favore, aggiorna MPlayer. + + + + (This warning won't be displayed anymore) + (Questo avviso non sarà mostrato di nuovo) + + + + Next aspect ratio + Successivo rapporto d'aspetto + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + A&nteprima + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer è ancora in esecuzione + + + + S&how icon in system tray + M&ostra icona nella barra di sistema + + + + &Hide + &Nascondi + + + + &Restore + &Ripristina + + + + &Quit + &Esci + + + + Playlist + Lista di riproduzione + + + + Core + + + Brightness: %1 + Luminosità: %1 + + + + Contrast: %1 + Contrasto: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Tonalità: %1 + + + + Saturation: %1 + Saturazione: %1 + + + + Volume: %1 + Volume: %1 + + + + Zoom: %1 + Zoom %1 + + + + Font scale: %1 + Scalatura carattere: %1 + + + + Aspect ratio: %1 + Rapporto d'aspetto: %1 + + + + Updating the font cache. This may take some seconds... + Aggiornamento della cache dei font. Può richiedere alcuni secondi... + + + + DefaultGui + + + Welcome to SMPlayer + Benvenuto in SMPlayer + + + + Audio + Audio + + + + Subtitle + Sottotitoli + + + + &Main toolbar + Barra strumenti &principale + + + + &Language toolbar + Barra strumenti per le &lingue + + + + &Toolbars + Barre s&trumenti + + + + EqSlider + + + icon + icona + + + + ErrorDialog + + + Hide log + Nascondi log + + + + Show log + Mostra log + + + + MPlayer Error + Errore MPlayer + + + + icon + icona + + + + Error + Errore + + + + FileDownloader + + + Downloading... + Scaricamento... + + + + Downloading %1 + Scaricamento %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Proprietà del file + + + + &Information + &Informazioni + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + & Selezionare il demuxer che sarà usato per questo file: + + + + &Reset + &Reset + + + + &Video codec + Codec &video + + + + &Select the video codec: + &Selezionare il codec video: + + + + A&udio codec + Codec a&udio + + + + &Select the audio codec: + &Selezionare il codec audio: + + + + &MPlayer options + Opzioni &MPlayer + + + + Additional Options for MPlayer + Opzioni addizionali per MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Qui si possono passare opzioni extra a MPlayer. +Scriverle separate da spazi. +Esempio: -flip -nosound + + + + &Options: + &Opzioni: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Puoi attivare filtri video addizionali. +Separali con ",". Non usare spazi! +Esempio: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + Filtri v&ideo: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + E, per finire, i filtri audio. Stesse regole che per i filtri video. +Esempio:resample=44100:0:0,volnorm + + + + Audio &filters: + &Filtri audio: + + + + OK + OK + + + + Cancel + Cancella + + + + Apply + Applica + + + + FindSubtitlesWindow + + + Language + Lingua + + + + Name + Nome + + + + Format + Formato + + + + Files + Files + + + + Date + Data + + + + Uploaded by + Caricato da + + + + All + Tutti + + + + Close + Chiudi + + + + &Download + &Scarica + + + + &Copy link to clipboard + &Copia link negli appunti + + + + Error + Errore + + + + Download failed: %1. + Scaricamento fallito: %1 + + + + Connecting to %1... + Connessione a %1... + + + + Downloading... + Scaricamento... + + + + Done. + Fatto. + + + + %1 files available + %1 file disponibili + + + + Failed to parse the received data. + Lettura dei dati ricevuti fallita. + + + + Find Subtitles + Trova sottotitoli + + + + &Subtitles for + &Sottotitoli per + + + + &Language: + &Lingua: + + + + &Refresh + Aggio&rna + + + + Subtitle saved as %1 + Sottotitoli salvati come %1 + + + + %1 subtitle(s) extracted + + %1 sottotitolo estratto + %1 sottotitoli estratti + + + + + Overwrite? + Sovrascrivi? + + + + The file %1 already exits, overwrite? + Il file %1 esiste già, sovrascrivere? + + + + Error saving file + Errore durante il salvataggio del file + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Non è stato possibile salvare il file scaricato +nella directory %1 +Controllarne i relativi permessi. + + + + Download failed + Download fallito + + + + Temporary file %1 + File temporaneo %1 + + + + InfoFile + + + General + Generale + + + + Size + Dimensione + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Durata + + + + Demuxer + Demuxer + + + + Name + Nome + + + + Artist + Artista + + + + Author + Autore + + + + Album + Álbum + + + + Genre + Genere + + + + Date + Data + + + + Track + Traccia + + + + Copyright + Copyright + + + + Comment + Commento + + + + Software + Software + + + + Clip info + Informazioni + + + + Video + Video + + + + Resolution + Risoluzione + + + + Aspect ratio + Rapporto d'aspetto + + + + Format + Formato + + + + Bitrate + Bitrate + + + + %1 kbps + %1 kbps + + + + Frames per second + Frame al secondo + + + + Selected codec + Codec Selezionato + + + + Initial Audio Stream + Flusso Audio Iniziale + + + + Rate + Frequenza campionamento + + + + %1 Hz + %1 Hz + + + + Channels + Canali + + + + Audio Streams + Flussi Audio + + + + Language + Lingua + + + + empty + vuoto + + + + Subtitles + Sottotitoli + + + + Type + Tipo + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + + + + + Stream title + Titolo flusso + + + + Stream URL + URL flusso + + + + File + File + + + + InputDVDDirectory + + + Choose a directory + Scegli una cartella + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Riproduci un DVD da una cartella + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Si può riprodurre un dvd direttamente dal disco. Selezionare semplicemente la cartella che contiene VIDEO_TS e AUDIO_TS. + + + + Choose a directory... + Scegli una cartella... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Inserisci la versione di MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer non è riuscito a identificare la versione di MPlayer in uso. + + + + Version reported by MPlayer: + MPlayer riporta la versione: + + + + Please, &select the correct version: + &Selezionare la versione corretta: + + + + 1.0rc1 or older + 1.0rc1 o precedente + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + 1.0rc2 o successiva + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Digita URL + + + + &URL: + &URL: + + + + It's a &playlist + È una &lista di riproduzione + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Selezionando questa opzione, l'URL sarà trattata come una lista di riproduzione: sarà aperto come testo e verranno riprodotti gli URL contenuti. + + + + Languages + + + Afar + Afar + + + + Abkhazian + Abcasa + + + + Afrikaans + Afrikaans + + + + Amharic + Aramaico + + + + Arabic + Arabo + + + + Assamese + Assamese + + + + Aymara + Aymara + + + + Azerbaijani + Azerbaijano + + + + Bashkir + Baškira + + + + Byelorussian + Bielorusso + + + + Bulgarian + Bulgaro + + + + Bihari + + + + + Bislama + Bislama + + + + Bengali + Bengalese + + + + Tibetan + Tibetano + + + + Breton + Bretone + + + + Catalan + Catalano + + + + Corsican + Corso + + + + Czech + Ceco + + + + Welsh + Scozzese + + + + Danish + Danese + + + + German + Tedesco + + + + Bhutani + Bhutano + + + + Greek + Greco + + + + English + Inglese + + + + Esperanto + Esperanto + + + + Spanish + Spagnolo + + + + Estonian + Estone + + + + Basque + Basco + + + + Persian + Persiano + + + + Finnish + Finlandese + + + + Fiji + Fijiano + + + + Faroese + Faroese + + + + French + Francese + + + + Frisian + Frisone + + + + Irish + Irlandese + + + + Scots + Scozzese + + + + Galician + Galiziano + + + + Guarani + Guaraní + + + + Gujarati + Gujarati + + + + Hausa + Hausa + + + + Hebrew + Ebreo + + + + Hindi + Hindi + + + + Croatian + Croato + + + + Hungarian + Ungherese + + + + Armenian + Armeno + + + + Interlingua + Interlingua + + + + Indonesian + Indonesiano + + + + Interlingue + Occidental / Interlingue + + + + Icelandic + Islandese + + + + Italian + Italiano + + + + Inuktitut + Inuktitut + + + + Japanese + Giapponese + + + + Javanese + Giavanese + + + + Georgian + Georgiano + + + + Kazakh + Kazaco + + + + Greenlandic + Groenlandese + + + + Cambodian + Cambogiano + + + + Kannada + Kannada + + + + Korean + Coreano + + + + Kashmiri + + + + + Kurdish + Curdo + + + + Kirghiz + Kirghiso + + + + Latin + Latino + + + + Lingala + Lingala + + + + Laothian + Laotiano + + + + Lithuanian + Lituano + + + + Latvian + Lettone + + + + Malagasy + Malgascia + + + + Maori + Māori + + + + Macedonian + Macedone + + + + Malayalam + Malayalam + + + + Mongolian + Mongolo + + + + Moldavian + Moldavo + + + + Marathi + Marathi + + + + Malay + + + + + Maltese + Maltese + + + + Burmese + Birmana + + + + Nauru + Nauruana + + + + Nepali + Nepalese + + + + Dutch + Olandese + + + + Norwegian + Norvegese + + + + Occitan + Occitano + + + + Oriya + + + + + Polish + Polacco + + + + Pashto + Pashtun + + + + Portuguese + Portoghese + + + + Quechua + + + + + Romanian + Romeno + + + + Russian + Russo + + + + Kinyarwanda + + + + + Sanskrit + Sanscrito + + + + Sindhi + + + + + Slovak + Slovacco + + + + Slovenian + Sloveno + + + + Samoan + Samoano + + + + Shona + + + + + Somali + Somalo + + + + Albanian + Albanese + + + + Serbian + Serbo + + + + Sundanese + Sudanese + + + + Swedish + Svedese + + + + Swahili + Swahili + + + + Tamil + Tamil + + + + Telugu + Telugu + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + Turkmeno + + + + Tagalog + Tagalog + + + + Tonga + + + + + Turkish + Turco + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + Ucraino + + + + Urdu + + + + + Uzbek + Uzbeko + + + + Vietnamese + Vietnamita + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + Cinese + + + + Zulu + + + + + Portuguese - Brazil + Portoghese (Brasile) + + + + Portuguese - Portugal + Portoghese (Portogallo) + + + + Simplified-Chinese + Cinese semplificato + + + + Traditional Chinese + Cinese tradizionale + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + Lingue Europa Occidentale + + + + Western European Languages with Euro + Lingue Europa Occidentale con Euro + + + + Slavic/Central European Languages + Slavo/Lingue Europa Centrale + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galiziano, Maltese, Turco + + + + Old Baltic charset + Vecchio set di caratteri Baltico + + + + Cyrillic + Cirillico + + + + Modern Greek + Greco Moderno + + + + Baltic + Baltico + + + + Celtic + Cetico + + + + Hebrew charsets + Set di caratteri Ebraico + + + + Ukrainian, Belarusian + Ucraino, Bielorusso + + + + Simplified Chinese charset + Set di caratteri Cinese Semplificato + + + + Traditional Chinese charset + Set di caratteri Cinese Tradizionale + + + + Japanese charsets + Set di caratteri Giapponese + + + + Korean charset + Set di caratteri Coreano + + + + Thai charset + Set di Caratteri Thai + + + + Cyrillic Windows + Cirillico per Windows + + + + Slavic/Central European Windows + Slavo/Lingue Europa Centrale per Windows + + + + Arabic Windows + Arabo per Windows + + + + Serbo-Croatian + Serbo-croato + + + + Avestan + + + + + Akan + + + + + Aragonese + Aragonese + + + + Avaric + + + + + Belarusian + Bielorusso + + + + Bambara + + + + + Bosnian + Bosniaca + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + Ido + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + Volapük + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Scegli il nome del file + + + + Confirm overwrite? + Confermi sovrascrittura? + + + + The file already exists. +Do you want to overwrite? + il file esiste già. +Vuoi sovrascriverlo? + + + + Error saving file + Errore durante il salvataggio del file + + + + The log couldn't be saved + Non è stato possibile salvare il log + + + + Logs + Log + + + + LogWindowBase + + + Log Window + Finestra Log + + + + Save + Salva + + + + Copy to clipboard + Copia negli appunti + + + + Close + Chiudi + + + + &Close + &Chiudi + + + + MiniGui + + + Control bar + Barra dei controlli + + + + MpcGui + + + Control bar + Barra dei controlli + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nome + + + + Length + Durata + + + + Choose a file + Scegli un file + + + + Choose a filename + Scegli il nome del file + + + + Confirm overwrite? + Confermi sovrascrittura? + + + + Select one or more files to open + Selezionare uno o più file da aprire + + + + Choose a directory + Scegli una cartella + + + + The file %1 already exists. +Do you want to overwrite? + Il file %1 esiste già. +Vuoi sovrascriverlo? + + + + Edit name + Modifica nome + + + + Type the name that will be displayed in the playlist for this file: + Inserisci il nome per questo file che sarà visualizzato nella lista di riproduzione: + + + + &Play + &Riproduci + + + + &Edit + &Modifica + + + + Playlists + Liste di riproduzione + + + + All files + Tutti i file + + + + &Load + &Apri + + + + &Save + &Salva + + + + &Next + &Prossimo + + + + Pre&vious + P&recedente + + + + Move &up + Manda &su + + + + Move &down + Manda &giù + + + + &Repeat + &Ripeti + + + + S&huffle + Riproduzione &Casuale + + + + Add &current file + Aggiungi il file &corrente + + + + Add &file(s) + Aggiungi &file + + + + Add &directory + Aggiungi c&artella + + + + Remove &selected + R&imuovi selezionati + + + + Remove &all + Ri&muovi tutti + + + + SMPlayer - Playlist + SMPlayer - Lista di riproduzione + + + + Add... + Aggiungi... + + + + Remove... + Rimuovi... + + + + Playlist modified + Lista di riproduzione modificata + + + + There are unsaved changes, do you want to save the playlist? + Ci sono modifiche non salvate. Vuoi salvare la lista di riproduzione? + + + + Preferences + Preferenze + + + + PlaylistPreferences + + + Playlist - Preferences + Lista di riproduzione - Preferenze + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Selezionare questa opzione se si vuole che, aggiungendo una cartella, vengano aggiunti ricorsivamente anche i file presenti nelle sottocartelle. Altrimenti solo i file presenti nella cartella saranno aggiunti. + + + + &Add files in directories recursively + &Aggiungi ricorsivamente i file nelle cartelle + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Selezionare questa opzione per estrarre alcune informazioni dai file aggiunti alla lista di riproduzione. Questo permette di visualizzare il titolo (se disponibile) e la durata dei file, altrimenti le stesse informazioni non saranno disponibili fino al momento dell'effettiva riproduzione dei file stessi. Attenzione: questa opzione può rivelarsi molto lenta, soprattutto aggiungendo molti file. + + + + Automatically get &info about files added + &Estrarre automaticamente informazioni dai file aggiunti + + + + &Save copy of playlist on exit + &Salva una copia della lista di riproduzione in uscita + + + + &Play files from start + &Riproduci file dall'inizio + + + + PrefAdvanced + + + Advanced + Avanzate + + + + Auto + Automatico + + + + &Advanced + &Avanzate + + + + icon + icona + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Qui è possibile passare opzioni addizionali a MPlayer. +Scriverle separate da spazi. +Esempio: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + È possibile anche passare dei filtri video addizionali. +Separarli con ",". Non usare spazi! +Esempio: resize=512:384,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + E infine i filtri audio. Stessa regola dei filtri video. +Esempio: resample=44100:0:0,volnorm + + + + Log MPlayer output + Registra l'output di MPlayer + + + + Log SMPlayer output + Registra l'output di SMPlayer + + + + This option is mainly intended for debugging the application. + Questa opzione è pensata principalmente per scopi di debug. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Selezionare questa opzione può ridurre lo sfarfallio, ma può anche produrre una errata riproduzione video. + + + + Filter for SMPlayer logs + Filtri per i log di SMPlayer + + + + &Monitor aspect: + Rapporto del &monitor: + + + + &Run MPlayer in its own window + &Esegui MPlayer nella sua finestra + + + + &Options: + &Opzioni: + + + + V&ideo filters: + Filtri v&ideo: + + + + Audio &filters: + &Filtri audio: + + + + &Colorkey: + &Colorkey: + + + + Log &SMPlayer output + Salva l'output di &SMPlayer + + + + &Filter for SMPlayer logs: + &Filtri per i log di SMPlayer: + + + + C&hange... + C&ambia... + + + + Logs + Log + + + + Log MPlayer &output + &Salva l'output di MPlayer + + + + Options for MP&layer + Opzioni per MP&layer + + + + Autosave MPlayer log + Salva automaticamente l'output di MPlayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Selezionando questa opzione, l'output di MPlayer verrà salvato automaticamente nel file specificato ogni volta che viene riprodotto un nuovo file.Utile per applicazioni esterne, per avere informazioni sul file in riproduzione. + + + + Autosave MPlayer log filename + Nome del file di log di MPlayer + + + + Enter here the path and filename that will be used to save the MPlayer log. + Inserire nome e percorso del file che verrà usato come log di MPlayer. + + + + A&utosave MPlayer log to file + Salva au&tomaticamente l'output di MPlayer su file + + + + Pass short filenames (8+3) to MPlayer + Fornisci nomi di file DOS (8+3) a MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Attualmente MPlayer non è in grado di aprire file il cui nome contiene caratteri non supportati dal sistema. Selezionando questa opzione, SMPlayer passerà a MPlayer la versione DOS del nome del file, e sarà quindi in grado di aprirlo. + + + + &Pass short filenames (8+3) to MPlayer + &Fornisci nomi di file DOS (8+3) a MPlayer + + + + Monitor aspect + Rapporto del Monitor + + + + Select the aspect ratio of your monitor. + Selezionare il rapporto d'aspetto del monitor in uso. + + + + Run MPlayer in its own window + Esegui MPlayer nella sua finestra + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Selezionando questa opzione, la finestra di MPlayer non sarà contenuta in quella di SMPlayer. Eventi da mouse e tastiera saranno gestiti direttamente da MPlayer, quindi le opzioni in preferenze potrebbero non funzionare. + + + + Colorkey + Colorkey + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Se si visualizzano parti del video al di sopra di altre finestre, si può cambiare la colorkey. Provare a selezionare un colore vicino al nero. + + + + Options for MPlayer + Opzioni per MPlayer + + + + Options + Opzioni + + + + Here you can type options for MPlayer. Write them separated by spaces. + Qui si possono passare opzioni a MPlayer. Scriverle separate da spazi. + + + + Video filters + Filtri video + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Qui si possono aggiungere filtri video a MPlayer. Scrivili separati da virgole. Non usare spazi! + + + + Audio filters + Filtri audio + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Qui si possono aggiungere filtri audio a MPlayer. Scrivili separati da virgole. Non usare spazi! + + + + Repaint the background of the video window + Ridisegna lo sfondo della finestra video + + + + Repaint the backgroun&d of the video window + Ridisegna lo sfon&do della finestra video + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Utilizza IPv4 per le connessioni di rete. Ripiega su IPv6 automaticamente. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Utilizza IPv6 per le connessioni alla rete. Ripiega su IPv4 automaticamente. + + + + Network Connection + + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + Lo&g + + + + Rebuild index if needed + Ricostruisci l'indice se necessario + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Ricostruisce l'indice dei file se non ne viene trovato uno, permettendo le ricerche temporali. Utile con download corrotti/incompleti o file creati male. Questa opzione funziona solo se il tipo di file supporta le ricerche temporali (ad es. no stdin, pipe etc.) <br>Nota: la creazione dell'indice può richiedere un certo tempo. + + + + Rebuild &index if needed + Ricostruisci l'&indice se necessario + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Se questa opzione è selezionata, SMPlayer salverà i messaggi di debug (puoi visualizzarlo in <b>Opzioni->Vedi log->SMPlayer</b>). Queste informazioni possono essere utili per gli sviluppatori nel caso si trovi un bug. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Se selezionata, SMPlayer salverà l'output di MPlayer (puoi visualizzarlo in <b>Opzioni->Vedi log->MPlayer</b>). In caso di problemi, questo log può contenere informazioni importanti, si raccomanda quindi di tenere selezionata questa opzione. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Questa opzione permette di filtrare i messaggi di SMPlayer che saranno salvati nel log. Potete inserire qualsiasi espressione regolare. <br>Per esempio: <i>^Core::.*</i> mostrerà solo le linee che iniziano con <i>Core::</i> + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Applica una modalità sperimentale di MPlayer dove i timestamp per i fotogrammi video sono calcolati in modo differente e sono supportati i filtri video che aggiungono fotogrammi o modificano i timestamp di quelli presenti. Timestamp più precisi possono vedersi per esempio quando si riproducono sottotitoli temporizzati ai cambi di scena con la libreria SSA/ASS abilitata. Senza correct pts la temporizzazione dei sottotitoli sarà tipicamente spostata di qualche fotogramma. Questa opzione non funzionerà correttamente con alcuni demuxer e codec. + + + + Proxy + Proxy + + + + Enable proxy + Abilita proxy + + + + Enable/disable the use of the proxy. + Abilita/disabilita l'uso del proxy. + + + + Host + Host + + + + The host name of the proxy. + Il nome host del proxy. + + + + Port + Porta + + + + The port of the proxy. + La porta del proxy. + + + + Username + Nome utente + + + + If the proxy requires authentication, this sets the username. + Se il proxy richiede l'autenticazione, qui si stabilisce il nome utente. + + + + Password + Password + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + È possibile impostare un proxy per le connessioni internet (usato al momento solo per il download dei sottotitoli). + + + + &Enable proxy + &Abilita proxy + + + + &Host: + &Host: + + + + &Port: + &Porta: + + + + &Username: + &Nome utente: + + + + Pa&ssword: + Pa&ssword: + + + + C&orrect PTS + + + + + Http + HTTP + + + + Socks5 + + + + + Type + Tipo + + + + Select the proxy type to be used. + Seleziona il tipo di proxy da usare. + + + + &Type: + &Tipo: + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + Rete + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + &Rete + + + + Example: + Esempio: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + La password per il proxy. <b>Attenzione:</b> la password verrà salvata come testo semplice nel file di configurazione. + + + + PrefAssociations + + + Warning + Attenzione + + + + Not all files could be associated. Please check your security permissions and retry. + Non tutti i file sono stati associati. Controlla i permessi e riprova. + + + + File Types + Tipi di file + + + + Select all + Seleziona tutti + + + + Check all file types in the list + Seleziona tutti i tipi di file della lista + + + + Uncheck all file types in the list + Deseleziona tutti i tipi di file della lista + + + + List of file types + Lista dei tipi di file + + + + File types + Tipi di file + + + + Media files handled by SMPlayer: + File multimediali associati a SMPlayer: + + + + Select All + Seleziona tutti + + + + Select None + Nessuna selezione + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Selezionare le estensioni che si vogliono associare a SMPlayer. Cliccando su Applica, i file selezionati saranno associati a SMPlayer. Deselezionando una estensione, l'associazione al file sarà annullata. + + + + Select none + Nessuna selezione + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + (sp)<b>Nota:</b> (Non funziona in Windows Vista). + + + + PrefDrives + + + Drives + Dispositivi + + + + icon + icona + + + + CD device + Dispositivo CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Scegli il dispositivo CDROM. Sarà usato per riprodurre VCD e CD audio. + + + + DVD device + Dispositivo DVD + + + + Choose your DVD device. It will be used to play DVDs. + Scegli il dispositivo DVD. Sarà usato per riprodurre DVD. + + + + Select your &CD device: + Seleziona il dispositivo &CD: + + + + Select your &DVD device: + Seleziona il dispositivo &DVD: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + Attualmente SMPlayer non trova automaticamente i dispositivi CDROM e DVD. Devi quindi selezionare qui i tuoi dispositivi (possono essere lo stesso). + + + + PrefGeneral + + + General + Generale + + + + &General + &Generale + + + + Paths + Percorsi + + + + Media settings + Impostazioni media + + + + Preferred audio and subtitles + Audio e sottotitoli preferiti + + + + Video + Video + + + + Start videos in fullscreen + Riproduci video a tutto schermo + + + + Disable screensaver + Disabilita salvaschermo + + + + Audio + Audio + + + + AC3/DTS pass-through S/PDIF + AC3/DTS in uscita su S/PDIF + + + + Select the mplayer executable + Seleziona eseguibile mplayer + + + + Executables + Eseguibili + + + + All files + Tutti i file + + + + Select a directory + Seleziona una cartella + + + + MPlayer executable + Eseguibile MPlayer + + + + Screenshots folder + Cartella per gli screenshot + + + + Video output driver + Driver di uscita video + + + + Audio output driver + Driver di uscita audio + + + + Select the audio output driver. + Seleziona il driver di uscita audio. + + + + Remember settings + Ricorda opzioni + + + + Preferred audio language + Lingua audio preferita + + + + Preferred subtitle language + Lingua preferita per i sottotitoli + + + + Software video equalizer + Equalizzatore video software + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Seleziona questa opzione se l'equalizzatore video non è supportato dalla scheda grafica o dal driver video selezionato.<br><b>Attenzione:</b> questa opzione può essere incompatibile con alcuni driver video. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Se selezioni questa opzione, tutti i video partiranno a tutto schermo. + + + + Software volume control + Controllo volume software + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Seleziona questa opzione per usare il mixer software, invece di quello della scheda audio. + + + + Postprocessing quality + Qualità di postprocessing + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Cambia dinamicamente il livello di postprocessing a seconda del tempo di CPU disponibile. Il numero che specifichi sarà il massimo livello usato. Normalmente si possono usare numeri molto grandi. + + + + Change volume + Cambia volume + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Se selezionato, SMPlayer ricorderà il volume di ogni file e lo ripristinerà ogni volta che il file verrà riprodotto. Per i nuovi file verrà usato il volume predefinito. + + + + 0 + 0 + + + + &Change volume on every file + &Cambia volume ad ogni file + + + + Select the &MPlayer executable: + Seleziona l'eseguibile &MPlayer: + + + + &Folder for storing screenshots: + &Cartella per gli screenshot: + + + + &Audio: + &Audio: + + + + &Remember settings for all files (audio track, subtitles...) + &Ricorda le impostazioni per tutti i file (traccia audio, sottotitoli...) + + + + Su&btitles: + S&ottotitoli: + + + + &Quality: + &Qualità: + + + + Start videos in &fullscreen + &Riproduci video a tutto schermo + + + + Disable &screensaver + Disabilita &salvaschermo + + + + &Default volume: + Volume pre&definito: + + + + Use s&oftware volume control + Usa controllo del volume s&oftware + + + + Ma&x. Amplification: + Ma&ssima amplificazione: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS in uscita su S/PDIF + + + + Direct rendering + Rendering diretto + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Se selezionato, abilita il direct rendering (non supportato da tutti i codec e output video)<br><b>ATTENZIONE:</b>Può corrompere l'OSD e i sottotitoli! + + + + Double buffering + Doppio buffering + + + + D&irect rendering + Rendering d&iretto + + + + Dou&ble buffering + Doppio &buffering + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Il doppio buffering previene lo sfarfallio salvando due frame in memoria e mostrandone uno mentre decodifica l'altro. Se disabilitato può influenzare negativamente l'OSD, ma spesso ne rimuove lo sfarfallio. + + + + &Enable postprocessing by default + Abilita il &postprocessing + + + + Volume &normalization by default + Volume &normalizzato in modo predefinito + + + + Close when finished + Chiudi alla fine + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Selezionando questa opzione, la finestra principale verrà chiusa alla fine del file/della lista di riproduzione. + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + C&anali predefiniti: + + + + &Pause when minimized + &Pausa se minimizzato + + + + Pause when minimized + Pausa se minimizzato + + + + Enable postprocessing by default + Abilita postprocessing per default + + + + Max. Amplification + Massima amplificazione + + + + Volume normalization by default + Volume normalizzato per default + + + + Maximizes the volume without distorting the sound. + Massimizza il volume senza distorcere il suono. + + + + Default volume + Volume predefinito + + + + Sets the initial volume that new files will use. + Volume iniziale per i nuovi file. + + + + Channels by default + Canali predefiniti + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Massimo livello di amplificazione in percentuale (predefinito:110). Un valoredi 200 permetterà di alzare il volume fino a un massimo del doppio del livello corrente. Con valori inderiori a 100 il volume iniziale (che è al 100%) sarà sotto il massimo, per cui, ad esempio, l'OSD non verrà mostrato correttamente. + + + + Uses hardware AC3 passthrough + Usa AC3 su uscita hardware + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Richiede il massimo numero di canali audio. MPlayer riprodurrà l'audio con il numero di canali specificati (se possibile). Normalmente questa opzione è rilevante riproducendo video con audio AC3 (tipo DVD). In questo caso liba52 si occuperà di scalare l'audio nel numero di canali richiesto. NOTA: Questa opzione vale per i codec (solo AC3), i filtri (surround) e driver audio (almeno OSS). + + + + Postprocessing will be used by default on new opened files. + Il postprocessing sarà usato nei nuovi file aperti. + + + + Audio track + Traccia audio + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Specifica la traccia audio usata per riprodurre nuovi file. Se la traccia non esiste, sarà riprodotta la prima disponibile. <br><b>Nota:</b> l'opzione <i>"lingua audio preferita"</i> ha la precedenza su questa. + + + + Subtitle track + Traccia sottotitoli + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Specifica la traccia sottotitoli usata per riprodurre nuovi file. Se la traccia non esiste, sarà riprodotta la prima disponibile. <br><b>Nota:</b> l'opzione <i>"lingua sottotitoli preferita"</i> ha la precedenza su questa. + + + + Or choose a track number: + O scegli un numero di traccia: + + + + Audi&o: + Audi&o: + + + + Preferred language: + Lingua preferita: + + + + Preferre&d audio and subtitles + Audio e &sottotitoli preferiti + + + + &Subtitle: + &Sottotitoli: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Qui puoi inserire la lingua preferita per l'audio e i sottotitoli. Quando viene trovato un media con audio o sottotitoli multipli, SMPlayer proverà a usare la lingua preferita.<br>Questo funzionerà solo con media che offrono informazioni sulla lingua dell'audio o dei sottotitoli, come i DVD o i file mkv.<br> Questo campo accetta espressioni regolari. Ad esempio: lt;b>es|esp|spa</b> selezionerà il sottotitolo che combacia con <i>es</i>, <i>esp</i> o <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + Ri&produzione ad alta velocità senza alterazione del pitch + + + + High speed playback without altering pitch + Riproduzione ad alta velocità senza alterazione del pitch + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Permette di cambiare la velocità di riproduzione senza alterare il pitch. Richiede almeno MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Cambia il volume appena prima di iniziare la riproduzione + + + + &Video + &Video + + + + Use s&oftware video equalizer + Usa equalizzatore video s&oftware + + + + A&udio + A&udio + + + + Volume + Volume + + + + None + Nessuno + + + + Lowpass5 + LowPass5 + + + + Yadif (normal) + Yadif (normale) + + + + Yadif (double framerate) + Yadif (doppio frame rate) + + + + Linear Blend + Linear Blend + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Dei&nterlacciamento predefinito: + + + + Deinterlace by default + Deinterlacciamento predefinito + + + + Select the deinterlace filter that you want to be used for new videos opened. + Selezionare il filtro di deinterlacciamento predefinito. + + + + Remember time position + Ricorda posizione temporale + + + + Remember &time position + Ricorda posizione &temporale + + + + Change volume just before p&laying + Cambia il volume &appena prima di iniziare la riproduzione + + + + Enable the audio equalizer + Abilita equalizzatore audio + + + + Check this option if you want to use the audio equalizer. + Seleziona questa opzione se vuoi usare l'equalizzatore audio. + + + + &Enable the audio equalizer + Abilita &equalizzatore audio + + + + Draw video using slices + Disegno del video a striscie + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Abilita/disabilita il disegno del video a strisce/bande alte 16 pixel. Quando disabilitato lintero fotogramma viene disegnato tutto in una volta, ciò può essere più veloce o più lento, a secondo della scheda video e della cache disponibile. Ha effetto solo con i codec libmpeg2 e libavcodec. + + + + Dra&w video using slices + &Disegno del video a striscie + + + + &Close when finished playback + &Chiudi quando termina la riproduzione + + + + fast + veloce + + + + slow + lento + + + + fast - ATI cards + veloce - schede ATI + + + + User defined... + Definito dall'utente... + + + + Default zoom + Zoom predefinito + + + + This option sets the default zoom which will be used for new videos. + Questa opzione imposta lo zoom predefinito che sarà usato per i nuovi video. + + + + Default &zoom: + &Zoom predefinito: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Qui è necessario specificare l'eseguibile mplayer che SMPlayer userà.<br>SMPlayer richiede almeno MPlayer 1.0rc1 (tuttavia una più recente versione proveniente da SVN è raccomandata). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Se questa impostazione è errata, SMPlayer non sarà in grado di riprodurre qualsiasi cosa! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Qui puoi specificare una cartella dove salvare gli screenshot. Se il campo è vuoto, la cattura degli screenshot sarà disabilitata. + + + + Select the video output driver. %1 provides the best performance. + Seleziona il driver di uscita video. %1 dà prestazioni migliori. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 è quello raccomandato. Cerca di evitare %2 e %3, sono lenti e possono influenzare le prestazioni. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + Normalmente SMPlayer ricorderà le opzioni per ogni file (traccia audio selezionata, volume, filtri...). Deselezionare l'opzione se non si gradisce questa caratteristica. + + + + If you check this option, SMPlayer will play all files from the beginning. + Se deselezioni questa opzione, SMPlayer riprodurrà tutti i file dall'inizio. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Con questa opzione abilitata, la riproduzione andrà in pausa quando la finestra è minimizzata. La riproduzione riprenderà ripristinando la finestra. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Seleziona questa opzione per disabilitare lo screensaver.<br>Sarà poi riattivato alla fine della riproduzione. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Qui puoi inserire la lingua preferita per i flussi audio. Quando viene trovato un media con flussi audio multipli, SMPlayer proverà a usare la lingua preferita.<br>Questo funzionerà solo con media che offrono informazioni sulla lingua dei flussi audio, come i DVD o i file mkv.<br> Questo campo accetta espressioni regolari. Ad esempio: lt;b>es|esp|spa</b> selezionerà la traccia audio che combacia con <i>es</i>, <i>esp</i> o <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + Driver di &uscita: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Se questa opzione è abilitata il volume iniziale sarà impostato un momento prima che la riproduzione inizi, evitando un alto volume all'avvio. Richiede almeno MPlayer SVN r27872. + + + + Add black borders on fullscreen + Aggiungi bordi neri nella modalità a pieno schermo + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Con questa opzione abilitata, dei bordi neri saranno aggiunti all'immagine nella modalità a pieno schermo. Questo permette ai sottotitoli di venire visualizzati sui bordi neri. + + + + &Add black borders on fullscreen + &Aggiungi bordi neri nella modalità a pieno schermo + + + + one ini file + un singolo file ini + + + + multiple ini files + multipli file ini + + + + Method to store the file settings + Metodo per il salvataggio delle impostazioni associate ai file + + + + This option allows to change the way the file settings would be stored. The following options are available: + Questa opzione permette di cambiare il modo in cui le impostazioni sui file vengono salvate. Le seguenti opzioni sono disponibili: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>un singolo file ini</b>: le impostazioni per tutti i file riprodotti saranno salvati in un singolo file ini (%1) + + + + The latter method could be faster if there is info for a lot of files. + L'ultimo metodo potrebbe essere più veloce nel caso siano presenti molti file. + + + + &Store settings in + &Salvataggio impostazioni in + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>multipli file ini</b>: un file ini sarà usato per ogni file riprodotto. Questi file ini saranno salvati nella cartella %1 + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + Se si seleziona questa opzione, SMPlayer ricorderà la precedente posizione del file quando verrà aperto nuovamente. Questa possibilità è disponibile solamente con i normali file (non con DVD, CD, URL...). + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Tastiera e mouse + + + + &Keyboard + &Tastiera + + + + icon + icona + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Qui è possibile cambiare le scorciatoie da tastiera. Per farlo, fare doppio clic o scrivere nella cella corrispondente. Opzionalmente, salvare la lista per condividerla con altre persone o utilizzarla su un altro computer. + + + + &Mouse + &Mouse + + + + Button functions: + Funzione pulsanti: + + + + Media seeking + Ricerca nel file + + + + Volume control + Controllo volume + + + + Zoom video + Zoom video + + + + None + Nessuno + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Qui puoi cambiare le scorciatoie da tastiera. Per farlo, fai doppio click o scrivi nella cella corrispondente. Opzionalmente, puoi salvare la lista per condividerla con altre persone o utilizzarla su un altro computer. + + + + &Left click + Clic &sinistro + + + + &Double click + &Doppio clic + + + + &Wheel function: + Funzione &rotella mouse: + + + + Shortcut editor + Editor delle scorciatoie + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Questa tabella permette di cambiare le scorciatoie da tastiera. Fare doppio click, premere Invio o premere il bottone <b>Cambia scorciatoia</b> su un elemento per attivare il dialogo <i>Modifica scorciatoia</i>. Ci sono due modi per modificare una scorciatoia: se il bottone <b>Cattura</b> è attivato, basta premere il nuovo tasto (o combinazione di tasti) da assegnare all'azione (sfortunatamente ciò non funziona con tutti i tasti). Se il bottone <b>Cattura</b> è disattivato puoi inserire manualmente il nome del tasto. + + + + Left click + Clic sinistro + + + + Select the action for left click on the mouse. + Selezionare l'azione per il clic sinistro del mouse. + + + + Double click + Doppio clic + + + + Select the action for double click on the mouse. + Selezionare l'azione per il doppio clic del mouse. + + + + Wheel function + Funzione rotellina + + + + Select the action for the mouse wheel. + Selezionare l'azione per la rotellina del mouse. + + + + Play + Riproduci + + + + Pause + Pausa + + + + Stop + Stop + + + + Fullscreen + Tutto schermo + + + + Compact + Compatto + + + + Screenshot + Schermata + + + + On top + In alto + + + + Mute + Muto + + + + Frame counter + Contatore fotogrammi + + + + Reset zoom + Reinizializza zoom + + + + Exit fullscreen + Esci da tutto schermo + + + + Double size + Grandezza doppia + + + + Play / Pause + Riproduci / Pausa + + + + Pause / Frame step + Pausa / Per fotogramma + + + + Playlist + Lista di riproduzione + + + + Preferences + Preferenze + + + + No function + Nessuna funzione + + + + Change speed + Cambia velocità + + + + Normal speed + Velocità normale + + + + Keyboard + Tastiera + + + + Mouse + Mouse + + + + Middle click + Clic centrale + + + + Select the action for middle click on the mouse. + Selezionare l'azione per il clic centrale del mouse. + + + + M&iddle click + Cl&ic centrale + + + + X Button &1 + Pulsante X &1 + + + + X Button &2 + Pulsante X &2 + + + + Go backward (short) + Vai indietro (corto) + + + + Go backward (medium) + Vai indietro (medio) + + + + Go backward (long) + Vai indietro (lungo) + + + + Go forward (short) + Vai avanti (corto) + + + + Go forward (medium) + Vai avanti (medio) + + + + Go forward (long) + Vai avanti (lungo) + + + + OSD - Next level + OSD - Livello successivo + + + + Show context menu + Mostra menù contestuale + + + + &Right click + Clic dest&ro + + + + Increase volume + Alza volume + + + + Decrease volume + Abbassa volume + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + Mostra equalizzatore video + + + + Show audio equalizer + Mostra equalizzatore audio + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Interfaccia + + + + <Autodetect> + <Automatico> + + + + Default + Predefinito + + + + &Interface + &Interfaccia + + + + Seeking + Ricerca + + + + Never + Mai + + + + Whenever it's needed + Quando è necessario + + + + Only after loading a new video + Solo dopo aver aperto in nuovo video + + + + Recent files + File recenti + + + + Language + Lingua + + + + Here you can change the language of the application. + Qui è possibile modificare la lingua dell'applicazione. + + + + Instances + Istanze + + + + &Short jump + Salto &corto + + + + &Medium jump + Salto &medio + + + + &Long jump + Salto &lungo + + + + Mouse &wheel jump + Salto &rotellina + + + + &Use only one running instance of SMPlayer + &Usa una sola istanza di SMPlayer + + + + Ma&x. items + Numero massimo di &elementi + + + + St&yle: + St&ile: + + + + Ico&n set: + Set ico&ne: + + + + L&anguage: + Lingu&a: + + + + Main window + Finestra principale + + + + Auto&resize: + Scalatu&ra automatica: + + + + R&emember position and size + Ricorda posizione &e dimensione + + + + Default font: + Carattere predefinito: + + + + &Change... + &Cambia... + + + + &Behaviour of time slider: + Comportamenro della &barra temporale: + + + + Seek to position while dragging + Cerca posizione mentre trascini + + + + Seek to position when released + Cerca posizione al rilascio + + + + TextLabel + Etichetta testo + + + + &Seeking + &Ricerca + + + + Ins&tances + Is&tanze + + + + Autoresize + Scalatura automatica + + + + The main window can be resized automatically. Select the option you prefer. + La finestra principale può essere scalata automaticamente. Selezionare l'opzione preferita. + + + + Remember position and size + Ricorda posizione e dimensione + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Selezionando questa opzione, posizione e grandezza della finestra principale saranno salvate e riutilizzate successivamente. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Selezionare il massimo numero di elementi che saranno mostrati nel sottomenù <b>Apri->File recenti</b>. Un valore di 0 disabiliterà tale sottomenù. + + + + Icon set + Set icone + + + + Select the icon set you prefer for the application. + Selezionare il set di icone preferito. + + + + Style + Stile + + + + Select the style you prefer for the application. + Selezionare lo stile preferito. + + + + Default font + Carattere predefinito + + + + You can change here the application's font. + Qui puoi modificare il carattere dell'applicazione. + + + + Short jump + Salto corto + + + + Select the time that should be go forward or backward when you choose the %1 action. + Selezionare il salto temporale in avanto o indietro alla scelta della'azione %1. + + + + short jump + salto corto + + + + Medium jump + Salto medio + + + + medium jump + salto medio + + + + Long jump + Salto lungo + + + + long jump + salto lungo + + + + Mouse wheel jump + Salto rotellina + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Selezionare il salto temporale in avanti o indietro al movimento della rotellina del mouse. + + + + Behaviour of time slider + Comportamenro della barra temporale + + + + Select what to do when dragging the time slider. + Selezionare l'azione per il trascinamento della barra temporale. + + + + Use only one running instance of SMPlayer + Usa una sola istanza di SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Selezionare questa opzione se si vuole usare una istanza di SMPlayer già esistente all'apertura di nuovi file. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer deve essere in ascolto su una porta per ricevere comandi da altre istanza. Puoi cambiare la porta predefinita in caso essa sia in uso da parte di un'altra applicazione. + + + + Default GUI + Interfaccia predefinita + + + + Mini GUI + Interfaccia minimale + + + + GUI + Interfaccia + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Selezionare l'interfaccia preferita per l'applicazione. Attualmente ce ne sono disponibili due: predefinita e minimale.<br>L'<b>interfaccia predefinita</b> fornisce ina interfaccia tradizionale, con la barra degli strumenti e di controllo. L'<b>interfaccia minimale</b> fornisce una interfaccia più semplice, senza barra degli strumenti e con la barra di controllo con meno bottoni.<br><b>Nota:</b> questa opzione avrà effetto al prossimo riavvio. + + + + &GUI + &Interfaccia + + + + Automatic port + Porta automatica + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer deve essere in ascolto su una porta per ricevere comandi da altre istanze. Selezionando questa opzione, ne sarà scelta una automaticamente. + + + + Manual port + Porta manuale + + + + Port to listen + Porta in ascolto + + + + &Automatic + &Automatico + + + + &Manual + &Manuale + + + + Floating control + Controllo fluttuante + + + + Animated + Animato + + + + If this option is enabled, the floating control will appear with an animation. + Con questa opzione attiva, il controllo fluttuante farà la sua comparsa con una animazione. + + + + Width + Larghezza + + + + Specifies the width of the control (as a percentage). + Specifica la larghezza del controlloo (in percentuale). + + + + Margin + Margine + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + L' opzione imposta il numero di pixel che il controllo fluttuante sarà distante dal fondo dello schermo. Utile se lo schermo è una TV, dato che l' overscan potrebbe impedire al controllo di rendersi visibile. + + + + Display in compact mode too + Visualizza anche nella modalità compatta + + + + Bypass window manager + Bypassa il window manager + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + Con questa opzione abilitata, il controllo è visualizzato bypassando il window manager. Disabilita questa opzione se il controllo fluttuante non lavora bene con il window manager usato. + + + + &Floating control + &Controllo fluttuante + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + Il controllo fluttante compare nella modalità a schermo pieno quando il mouse tocca il fondo dello schermo. + + + + &Animated + &Animato + + + + &Width: + &Larghezza: + + + + 0 + 0 + + + + &Margin: + &Margine: + + + + Display in &compact mode too + Visualizza anche in modalità &compatta + + + + &Bypass window manager + &Bypassa il window manager + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + Se questa opzione è abilitata, il controllo fluttuante apparirà anche nella modalità compatta. <b>Fare attenzione</b>: il controllo fluttuante non è stato progettato per la modalità compatta e potrebbe non lavorare in modo appropriato. + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Prestazioni + + + + &Performance + &Prestazioni + + + + Priority + Priorità + + + + Select the priority for the MPlayer process. + Selezionare la priorità del processo MPlayer. + + + + realtime + tempo reale + + + + high + alta + + + + abovenormal + sopra al normale + + + + normal + normale + + + + belownormal + sotto al normale + + + + idle + idle + + + + Cache + Cache + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Usare una cache può migliorare il rendimento nei media lenti + + + + Allow frame drop + Permetti scarto fotogrammi + + + + Synchronization + Sincronia + + + + Audio/video auto synchronization + Sincronia automatica di audio e video + + + + Fast audio track switching + Cambio rapido della traccia audio + + + + Fast seek to chapters in dvds + Selezione rapida dei capitoli nei DVD + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Definisce la priorità per mplayer a seconda delle priorità predefinite disponibili in Windows. <br><b>ATTENZIONE:</b> Usare la priorità realtime può causare il blocco del sistema. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Salta alcuni frame per mantenere la sincronia Audio/Video su sistemi lenti. + + + + Allow hard frame drop + Permetti alto scarto fotogrammi + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Salto di frame molto intenso. Causa immagini distorte! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Aggiusta gradualmente la sincronia Audio/Video basandosi sulla misura del ritardo audio. + + + + Priorit&y: + Priori&tà: + + + + &Allow frame drop + Permetti sc&arto fotogrammi + + + + Allow &hard frame drop (can lead to image distortion) + &Permetti alto scarto fotogrammi (può corrompere l'immagine) + + + + Audio/&video auto synchronization + Sincronia automatica di audio e &video + + + + Fact&or: + Fatt&ore: + + + + &Fast audio track switching + Cambio &rapido della traccia audio + + + + Fast &seek to chapters in dvds + &Selezione rapida dei capitoli nei DVD + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Se selezionata, si proverà il metodo più veloce di ricerca dei capitoli, ma può non funzionare con alcuni dischi. + + + + Skip loop filter + Salta filtro loop + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Possibili valori: :<br> <b>Si</b>: si proverà il metodo più veloce per cambiare la traccia audio (può non funzionare conalcuni formati).<br> <b>No</b>: MPlayer verrà fatto ripartire ogni volta che si cambia la traccia audio.<br> <b>Automatico</b>: SMPlayer applicherà una delle altre due opzioni in base alla versione di MPlayer. + + + + Cache for files + Cache per i file + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Questa opzione specifica quanta memoria (in kByte) usare in fase di precaching di un file. + + + + Cache for streams + Cache per i flussi + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Questa opzione specifica quanta memoria (in kByte) usare in fase di precaching di una URL. + + + + Cache for DVDs + Cache per i DVD + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Questa opzione specifica quanta memoria (in kByte) usare in fase di precaching di un DVD.<br><b>Attenzione:</b> La ricerca temporale potrebbe non funzionare correttamente (insieme al cambio capitolo) usando la cache per un DVD. + + + + &Cache + &Cache + + + + Cache for &DVDs: + Cache per i &DVD: + + + + Cache for &local files: + Cache per i file &locali: + + + + Cache for &streams: + Cache per i flu&ssi: + + + + Enabled + Abilitato + + + + Skip (always) + Salta (sempre) + + + + Skip only on HD videos + Salta solo per i video HD + + + + Loop &filter + &Filtro loop + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Questa opzione permette di saltare il filtro loop (conosciuto anche come deblocking) durante la riproduzione di file H.264. Dal momento che il frame filtrato è usato come riferimento per i frame che da esso dipendono, questo ha un brutto effetto sulla qualità, ad esempio nei video MPEG-2. Ma almeno su HDTV ad alto bitrate, si potrà avere maggiore velocità senza perdita visibile di qualità. + + + + Possible values: + Possibili valori: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Abilitato</b>: il filtro loop non viene saltato + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Salta (sempre)</b>: il filtro loop viene saltato senza tener conto della risoluzione video + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Salta solo per i video HD</b>: il filtro loop viene saltato solo su video la cui altezza è maggiore o uguale di %1. + + + + Cache for audio CDs + Cache per audio CD + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Questa opzione specifica quanta memoria (in kByte) usare in fase di precaching di un CD audio. + + + + Cache for &audio CDs: + Cache per &audio CD: + + + + Cache for VCDs + Cache per i VCD + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Questa opzione specifica quanta memoria (in kByte) usare in fase di precaching di un VCD. + + + + Cache for &VCDs: + Cache per i &VCD: + + + + Threads for decoding + Thread per la decodifica + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Imposta il numero di thread da usare per la decodifica. Solo per MPEG-1/2 e H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + Numero di &thread per la decodifica (solo MPEG-1/2 e H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Lista di riproduzione + + + + Automatically add files to playlist + Automaticamente aggiungi file alla lista di riproduzione + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Abilitando questa opzione, ogni volta un file viene aperto, SMPlayer pulirà prima la lista di riproduzione e poi vi aggiungerà il file. In caso di DVD, CD e VCD, tutti i titoli del disco entreranno nella lista di riproduzione. + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Abilitando questa opzione, SMPlayer cercherà una successione di file (es. video_1.avi, video_2.avi...) e, trovati, saranno aggiunti alla lista di riproduzione. + + + + &Playlist + &Lista di riproduzione + + + + &Automatically add files to playlist + &Automaticamente aggiungi file alla lista di riproduzione + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Sottotitoli + + + + Choose a ttf file + Scegli un file TTF + + + + Truetype Fonts + Caratteri Truetype + + + + &Subtitles + &Sottotitoli + + + + Autoload + Apertura automatica + + + + Select first available subtitle + Selezionare i primi sottotitoli disponibili + + + + Same name as movie + Stesso nome del video + + + + All subs containing movie name + Tutti quelli che contengono il nome del video + + + + All subs in directory + Tutti i sottotitoli della cartella + + + + Position + Posizione + + + + 0 + 0 + + + + Top + in alto + + + + Bottom + in basso + + + + Include subtitles on screenshots + Includi sottotitoli negli screenshot + + + + Font + Carattere + + + + Select the font which will be used for subtitles (and OSD): + Selezionare il tipo di carattere che si userà per i sottotitoli (e OSD): + + + + Size + Dimensione + + + + No autoscale + Nessuna scalatura automatica + + + + Proportional to movie height + Proporzionale all'altezza del video + + + + Proportional to movie width + Proporzionale alla larghezza del video + + + + Proportional to movie diagonal + Proporzionale alla diagonale del video + + + + Subtitle position + Posizione dei sottotitoli + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Questa opzione specifica la posizione dei sottotitoli nella finestra. <i>100</i> significa in basso, mentre <i>0</i> significa in alto. + + + + Au&toload subtitles files (*.srt, *.sub...): + Au&tocarica sottotitoli (*.srt, *.sub...): + + + + S&elect first available subtitle + S&eleziona i primi sottotitoli disponibili + + + + &Default subtitle encoding: + &Codifica dei sottotitoli: + + + + Default &position of the subtitles on screen + Posizione &predefinita dei sottotitoli + + + + &Include subtitles on screenshots + &Includi sottotitoli negli screenshot + + + + &TTF font: + Font &TTF: + + + + S&ystem font: + Font di s&istema: + + + + A&utoscale: + Scalatura a&utomatica: + + + + Default subtitle encoding + Codifica dei sottotitoli + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Selezionando questa opzione, i sottotitoli appariranno negli screenshot. Nota: può a volte causare problemi. + + + + TTF font + Font TTF + + + + System font + Font di sistema + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Qui si possono selezionare i caratteri di sistema da usare per i sottotitoli e l'OSD. <b>Nota:</b> richiede MPlayer con supporto a fontconfig. + + + + Autoscale + Scalatura automatica + + + + Text color + Colore del testo + + + + Select the color for the text of the subtitles. + Selezionare il colore per il testo dei sottotitoli. + + + + Border color + Colore del bordo + + + + Select the color for the border of the subtitles. + Selezionare il colore per i bordi dei sottotitoli. + + + + Select the subtitle autoload method. + Selezionare il metodo di caricamento automatico dei sottotitoli. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Se ci sono una o più tracce di sottotitoli disponibili, una di esse sarà selezionata automaticamente, normalmente la prima. a meno che una di esse non corrisponda alla lingua preferita dall'utente, nel qual caso sarà usata quella. + + + + Select the subtitle autoscaling method. + Selezionare il metodo di scalatura automatica dei sottotitoli. + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + La dimensione in pixel. + + + + Bold + Grassetto + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + Corsivo + + + + If checked, the text will be displayed in <i>italic</i>. + Se attivato, il testo sarà visualizzato in <i>corsivo</i>. + + + + Left margin + Margine sinistro + + + + Specifies the left margin in pixels. + Specifica il margine sinistro in numero di pixel. + + + + Right margin + Margine destro + + + + Specifies the right margin in pixels. + Specifica il margine destro in numero di pixel. + + + + Vertical margin + Margine verticale + + + + Specifies the vertical margin in pixels. + Specifica il margine verticale in numero di pixel. + + + + Horizontal alignment + Allineamento orizzontale + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + Specifica l'allineamento orizzontale. Possibili valori: sinistra, centrato e destra. + + + + Vertical alignment + Allineamento verticale + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + Specifica l'allineamento verticale. Possibili valori: in basso, al centro, in alto. + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + &Grassetto + + + + &Italic + &Corsivo + + + + Colors + Colori + + + + &Text: + &Testo: + + + + &Border: + &Bordo: + + + + Margins + Margini + + + + L&eft: + &Sinistro: + + + + &Right: + &Destro: + + + + Verti&cal: + &Verticale: + + + + Alignment + Allineamento + + + + &Horizontal: + &Orizzontale: + + + + &Vertical: + &Verticale; + + + + Border st&yle: + S&tile bordo: + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + a sinistra + + + + Centered + horizontal alignment + centrato + + + + Right + horizontal alignment + a destra + + + + Bottom + vertical alignment + in basso + + + + Middle + vertical alignment + medio + + + + Top + vertical alignment + in alto + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + Abilita sottotitoli SSA/ASS + + + + Normal subtitles + Normali sottotitoli + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + Questa opzione NON cambia la dimensione dei sottotitoli nel video corrente, per farlo, usa l'opzione <i>Grandezza+</i> e <i>Grandezza-</i> del menù sottotitoli. + + + + Default scale + Scalatura predefinita + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + Sottotitoli SSA/ASS + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + &Caratteri e colori + + + + Enable &normal subtitles + Abilita &normali sottotitoli + + + + Enable SSA/&ASS subtitles + &Abilita sottotitoli SSA/ASS + + + + Default s&cale: + S&calatura predefinita: + + + + Defa&ult scale: + Scalat&ura predefinita: + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + Supporto Freetype + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + Normalmente non dovresti disabilitare questa opzione, a me no che la tua versione di MPlayer sia priva del supporto freetype. <b>Disabilitando questa opzione potresti rendere i sottotitoli totalmente non funzionanti!</b> + + + + Freet&ype support + Supporto Freet&ype + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Aiuto + + + + OK + OK + + + + Cancel + Annulla + + + + Apply + Applica + + + + Help + Aiuto + + + + SMPlayer - Preferences + SMPlayer - Preferenze + + + + QObject + + + will show this message and then will exit. + mostrerà questo messaggio e uscirà. + + + + the main window will be closed when the file/playlist finishes. + la finestra principale sarà chiusa alla fine della riproduzione del file/lista di riproduzione. + + + + This is SMPlayer v. %1 running on %2 + SMPlayer versione %1 in esecuzione su %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + prova a stabilire una connessione ad un altra istanza e a mandare il comando specificato. Esempio: -send-action pause Tutto il resto (se presente) verrà ignorato e l'applicazione terminerà. Ritorna 0 in caso di successo o -1 in caso di fallimento. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list è una lista di opzioni separate da spazi. Le azioni saranno eseguite subito dopo il caricamento di un file (se richiesto), nello stesso ordine di immissione. Per le azioni a scelta si possono passare true o false come parametri. Esempio: -actions "fullscreen compact true". Le doppie virgolette sono necessarie in caso si passi più di una azione. + + + + media + media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + Se è presente un altra istanza, il file sarà aggiunto alla lista di riproduzione di quella istanza, altrimenti questa opzione verrà ignorata e il file verrà aperto in una nuova istanza. + + + + the main window won't be closed when the file/playlist finishes. + la finestra principale non verrà chiusa alla fine della riproduzione. + + + + the video will be played in fullscreen mode. + il video verrà riprodotto a schermo intero. + + + + the video will be played in window mode. + il video verrà riprodotto nella finestra. + + + + Enqueue in SMPlayer + Accoda in SMPlayer + + + + opens the mini gui instead of the default one. + apre la mini interfaccia invece di quella predefinita. + + + + Restores the old associations and cleans up the registry. + Ristabilisce la vecchie associazioni e ripulisce il registro. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' è qualsiasi tipo di file che SMPlayer è in grado di riprodurre. Può essere un file locale, un DVD (per es. dvd://1), uno stream internet (per es. mms://....) o una lista di riproduzione locale in formato m3u. Se si usa l'opzione -playlist, questa sarà passata a MPlayer che si occuperà di gestirla. + + + + Usage: + Uso: + + + + directory + cartella + + + + action_name + action_name + + + + action_list + action_list + + + + opens the default gui. + Apre l'interfaccia predefinita. + + + + subtitle_file + subtitle_file + + + + specifies the subtitle file to be loaded for the first video. + specifica il file dei sottotitoli da caricare per il primo video. + + + + %1 second(s) + + %1 secondo + %1 secondi + + + + + %1 minute(s) + + %1 minuto + %1 minuti + + + + + %1 and %2 + %1 e %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + specifica la directory dove smplayer salverà i suoi file di configurazione (smplayer.ini, smplayer_files.ini...) + + + + disabled + aspect_ratio + disabilitato + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + sconosciuto + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + icona + + + + label + etichetta + + + + ShortcutGetter + + + Modify shortcut + Modifica scorciatoia + + + + Clear + Pulisci + + + + Press the key combination you want to assign + Esegui la combinazione che vuoi assegnare + + + + Capture + Cattura + + + + Capture keystrokes + Cattura combinazione di tasti + + + + SubChooserDialog + + + Subtitle selection + Selezione sottotitoli + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Questo archivio contiene più di un file per i sottotitoli. Selezionarne uno per l'estrazione. + + + + Select All + Seleziona tutti + + + + Select None + Nessuna selezione + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Cerca + + + + &Jump to: + &Salta a: + + + + TristateCombo + + + Auto + Automatico + + + + Yes + + + + + No + No + + + + VideoEqualizer + + + Contrast + Contrasto + + + + Brightness + Luminosità + + + + Hue + Tonalità + + + + Saturation + Saturazione + + + + Gamma + Gamma + + + + &Reset + &Reset + + + + &Set as default values + Salva come valori predefiniti + + + + Use the current values as default values for new videos. + Usa i valori correnti come valori predefiniti per i nuovi video. + + + + Set all controls to zero. + Metti a zero tutti i controlli + + + + Video Equalizer + Equalizzatore Video + + + + Information + Informazioni + + + + The current values have been stored to be used as default. + I valori correnti sono stati salvati come predefiniti. + + + + VideoPreview + + + Video preview + Anteprima video + + + + Cancel + Annulla + + + + Generated by SMPlayer + Generato da SMPlayer + + + + Creating thumbnails... + + + + + Size: %1 MB + Dimensione: %1 MB + + + + Length: %1 + Durata: %1 + + + + Save file + Salva file + + + + Images (*.png *.jpg) + Immagini (*.png *.jpg) + + + + Error saving file + Errore durante il salvataggio del file + + + + The file couldn't be saved + Non è stato possibile salvare il file + + + + Error + Errore + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + La directory temporanea (%1) non può esssere creata + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + Risoluzione: %1x%2 + + + + Video format: %1 + Formato video: %1 + + + + Frames per second: %1 + Fotogrammi al secondo: %1 + + + + Aspect ratio: %1 + Rapporto d'aspetto + + + + The file %1 can't be loaded + Il file %1 non può essere caricato + + + + No filename + Nessun nome file + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Predefinito + + + + Video Preview + Anteprima video + + + + &File: + &File: + + + + &Columns: + &Colonne: + + + + &Rows: + &Righe: + + + + &Aspect ratio: + Rapporto d'&aspetto + + + + &Seconds to skip at the beginnning: + &Secondi da saltare all'inizio: + + + + &Maximum width: + &Larghezza massima: + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Volume + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_ja.ts b/plugins/smplayer_plugin/translations/smplayer_ja.ts new file mode 100644 index 000000000..6be0c9041 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_ja.ts @@ -0,0 +1,7379 @@ + + + + About + + + Version: %1 + バージョン: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + このプログラムはフリー ソフトウェアです。Free Software Foundation によって発行されている GNU General Public License の version 2、または (オプションで) すべてのより後のバージョンのどちらかの条件の下で再配布できます。 + + + + The following people have contributed with translations: + 以下の方々に翻訳のご貢献をいただきました: + + + + German + ドイツ語 + + + + Slovak + スロバキア語 + + + + Italian + イタリア語 + + + + French + フランス語 + + + + %1, %2 and %3 + %1、%2 および %3 + + + + Simplified-Chinese + 簡体字中国語 + + + + Russian + ロシア語 + + + + %1 and %2 + %1 と %2 + + + + Hungarian + ハンガリー語 + + + + Polish + ポーランド語 + + + + Japanese + 日本語 + + + + Dutch + オランダ語 + + + + Ukrainian + ウクライナ語 + + + + Portuguese - Brazil + ポルトガル語 - ブラジル + + + + Georgian + グルジア語 + + + + Czech + チェコ語 + + + + Bulgarian + ブルガリア語 + + + + Turkish + トルコ語 + + + + Swedish + スウェーデン語 + + + + Serbian + セルビア語 + + + + Traditional Chinese + 繁体字中国語 + + + + Romanian + ルーマニア語 + + + + Portuguese - Portugal + ポルトガル語 - ポルトガル + + + + Greek + ギリシャ語 + + + + Finnish + フィンランド語 + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + SMPlayer のバージョン情報 + + + + &Info + 情報(&I) + + + + icon + icon + + + + &Contributions + 貢献(&C) + + + + &Translators + 翻訳者(&T) + + + + &License + ライセンス(&L) + + + + Visit our web for updates: + 更新のためにウェブを訪問する: + + + + Get help in our forum: + フォーラムで手助けを得る: + + + + You can support SMPlayer by making a donation. + 寄付によって SMPlayer をサポートできます。 + + + + More info + さらなる情報 + + + + Korean + 韓国語 + + + + Macedonian + マケドニア語 + + + + Basque + バスク語 + + + + Using MPlayer %1 + MPlayer %1 を使用しています + + + + Catalan + カタロニア語 + + + + Portable Edition + ポータブル エディション + + + + Using Qt %1 (compiled with Qt %2) + Qt %1 を使用しています (Qt %2 でコンパイルされています) + + + + Slovenian + スロベニア語 + + + + Arabic + アラビア語 + + + + Kurdish + クルド語 + + + + Galician + ガリシア語 + + + + The following people have contributed with patches (see the changelog for details): + 以下の方々にパッチのご貢献をいただきました (詳細は変更点ログをご覧ください): + + + + If there's any omission, please report. + 何か欠落がある場合は、ご報告ください。 + + + + SMPlayer logo by %1 + SMPlayer のロゴ: %1 + + + + %1, %2, %3 and %4 + %1、%2、%3 および %4 + + + + %1, %2, %3, %4 and %5 + %1、%2、%3、%4 および %5 + + + + ActionsEditor + + + Name + 名前 + + + + Description + 説明 + + + + Shortcut + ショートカット + + + + &Save + 保存(&S) + + + + &Load + 読み込み(&L) + + + + Key files + キー ファイル + + + + Choose a filename + ファイル名の選択 + + + + Confirm overwrite? + 上書きを確認しますか? + + + + The file %1 already exists. +Do you want to overwrite? + ファイル %1 はすでに存在します。 +上書きしますか? + + + + Choose a file + ファイルの選択 + + + + Error + エラー + + + + The file couldn't be saved + ファイルは保存できませんでした + + + + The file couldn't be loaded + ファイルは読み込めませんでした + + + + &Change shortcut... + ショートカットの変更(&C)... + + + + AudioEqualizer + + + Audio Equalizer + オーディオ イコライザー + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + 適用(&A) + + + + &Reset + リセット(&R) + + + + &Set as default values + 既定値として設定(&S) + + + + Use the current values as default values for new videos. + 新しいビデオの既定値として現在の値を使用します。 + + + + Set all controls to zero. + すべてのコントロールを 0 に設定します。 + + + + Information + 情報 + + + + The current values have been stored to be used as default. + 現在の値は既定としての使用に格納されています。 + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer のログ + + + + SMPlayer - smplayer log + SMPlayer - smplayer のログ + + + + &Open + 開く(&O) + + + + &Play + 再生(&P) + + + + &Video + ビデオ(&V) + + + + &Audio + オーディオ(&A) + + + + &Subtitles + 字幕(&S) + + + + &Browse + 参照(&B) + + + + Op&tions + オプション(&T) + + + + &Help + ヘルプ(&H) + + + + &File... + ファイル(&F)... + + + + D&irectory... + ディレクトリ(&I)... + + + + &Playlist... + プレイリスト(&P)... + + + + &DVD from drive + ドライブからの DVD(&D) + + + + D&VD from folder... + フォルダーからの DVD(&V)... + + + + &URL... + URL(&U)... + + + + &Clear + クリア(&C) + + + + &Recent files + 最近使ったファイル(&R) + + + + P&lay + 再生(&L) + + + + &Pause + 一時停止(&P) + + + + &Stop + 停止(&S) + + + + &Frame step + コマ送り(&F) + + + + &Normal speed + 通常の速度(&N) + + + + &Halve speed + 半分の速度(&H) + + + + &Double speed + 倍の速度(&D) + + + + Speed &-10% + 速度 -10%(&-) + + + + Speed &+10% + 速度 +10%(&+) + + + + Sp&eed + 速度(&E) + + + + &Repeat + 繰り返し(&R) + + + + &Fullscreen + 全画面表示(&F) + + + + &Compact mode + コンパクト モード(&C) + + + + Si&ze + サイズ(&Z) + + + + 4:3 &Letterbox + 4:3 レターボックス(&L) + + + + 16:9 L&etterbox + 16:9 レターボックス(&E) + + + + 4:3 &Panscan + 4:3 パンスキャン(&P) + + + + 4:3 &to 16:9 + 4:3 から 16:9 へ(&T) + + + + &Aspect ratio + アスペクト比(&A) + + + + &None + なし(&N) + + + + &Lowpass5 + Lowpass5(&L) + + + + Linear &Blend + リニア ブレンド(&B) + + + + &Deinterlace + インターレース解除(&D) + + + + &Postprocessing + 後処理(&P) + + + + &Autodetect phase + 位相の自動検出(&A) + + + + &Deblock + ブロック除去(&D) + + + + De&ring + リング除去(&R) + + + + Add n&oise + ノイズの追加(&O) + + + + F&ilters + フィルター(&I) + + + + &Equalizer + イコライザー(&E) + + + + &Screenshot + スクリーンショット(&S) + + + + S&tay on top + 常に手前に表示(&T) + + + + &Extrastereo + エクストラステレオ(&E) + + + + &Karaoke + カラオケ(&K) + + + + &Filters + フィルター(&F) + + + + &Stereo + ステレオ(&S) + + + + &4.0 Surround + 4.0 サラウンド(&4) + + + + &5.1 Surround + 5.1 サラウンド(&5) + + + + &Channels + チャンネル(&C) + + + + &Left channel + 左チャンネル(&L) + + + + &Right channel + 右チャンネル(&R) + + + + &Stereo mode + ステレオ モード(&S) + + + + &Mute + ミュート(&M) + + + + Volume &- + 音量 -(&-) + + + + Volume &+ + 音量 +(&+) + + + + &Delay - + 遅延 -(&D) + + + + D&elay + + 遅延 +(&E) + + + + &Select + 選択(&S) + + + + &Load... + 読み込み(&L)... + + + + Delay &- + 遅延 -(&-) + + + + Delay &+ + 遅延 +(&+) + + + + &Up + 上へ(&U) + + + + &Down + 下へ(&D) + + + + &Title + タイトル(&T) + + + + &Chapter + チャプター(&C) + + + + &Angle + 角度(&A) + + + + &Playlist + プレイリスト(&P) + + + + &Show frame counter + フレーム カウンターの表示(&S) + + + + &Disabled + 無効(&D) + + + + &Seek bar + シーク バー(&S) + + + + &Time + 時間(&T) + + + + Time + T&otal time + 時間 + 全体の時間(&O) + + + + &OSD + OSD(&O) + + + + &View logs + ログの表示(&V) + + + + P&references + 環境設定(&R) + + + + About &Qt + Qt のバージョン情報(&Q) + + + + About &SMPlayer + SMPlayer のバージョン情報(&S) + + + + <empty> + <空> + + + + Video + ビデオ + + + + Audio + オーディオ + + + + Playlists + プレイリスト + + + + All files + すべてのファイル + + + + Choose a file + ファイルの選択 + + + + SMPlayer - Information + SMPlayer - 情報 + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD ドライブはまだ構成されていません。 +構成ダイアログは今すぐ表示されますので、それができます。 + + + + Choose a directory + ディレクトリを選択します + + + + Subtitles + 字幕 + + + + About Qt + Qt のバージョン情報 + + + + Playing %1 + %1 を再生中 + + + + Pause + 一時停止 + + + + Stop + 停止 + + + + Play / Pause + 再生 / 一時停止 + + + + Pause / Frame step + 一時停止 / コマ送り + + + + U&nload + 読み込み解除(&N) + + + + V&CD + VCD(&C) + + + + C&lose + 閉じる(&L) + + + + View &info and properties... + 情報とプロパティの表示(&I)... + + + + Zoom &- + 縮小(&-) + + + + Zoom &+ + 拡大(&+) + + + + &Reset + リセット(&R) + + + + Move &left + 左へ移動(&L) + + + + Move &right + 右へ移動(&R) + + + + Move &up + 上へ移動(&U) + + + + Move &down + 下へ移動(&D) + + + + &Pan && scan + パン アンド スキャン(&P) + + + + &Previous line in subtitles + 字幕の前の行(&P) + + + + N&ext line in subtitles + 字幕の次の行(&E) + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + 音量を下げる (2) + + + + Inc volume (2) + 音量を上げる (2) + + + + Exit fullscreen + 全画面表示の終了 + + + + OSD - Next level + OSD - 次のレベル + + + + Dec contrast + コントラストを下げる + + + + Inc contrast + コントラストを上げる + + + + Dec brightness + 明るさを下げる + + + + Inc brightness + 明るさを上げる + + + + Dec hue + 色合いを下げる + + + + Inc hue + 色合いを上げる + + + + Dec saturation + 鮮やかさを下げる + + + + Dec gamma + ガンマを下げる + + + + Next audio + 次のオーディオ + + + + Next subtitle + 次の字幕 + + + + Next chapter + 次のチャプター + + + + Previous chapter + 前のチャプター + + + + Inc saturation + 鮮やかさを上げる + + + + Inc gamma + ガンマを上げる + + + + &Load external file... + 外部のファイルを読み込む(&L)... + + + + &Kerndeint + Kerndeint(&K) + + + + &Yadif (normal) + Yadif (通常)(&Y) + + + + Y&adif (double framerate) + Yadif (ダブル フレームレート)(&A) + + + + &Next + 次へ(&N) + + + + Pre&vious + 前へ(&V) + + + + Volume &normalization + 音量の通常化(&N) + + + + &Audio CD + オーディオ CD(&A) + + + + Denoise nor&mal + ノイズ除去 通常(&M) + + + + Denoise &soft + ノイズ除去 ソフト(&S) + + + + Denoise o&ff + ノイズ除去 オフ(&F) + + + + Use SSA/&ASS library + SSA/ASS ライブラリの使用(&A) + + + + Flip i&mage + イメージを垂直に反転(&M) + + + + &Toggle double size + 倍のサイズを切り替え(&T) + + + + S&ize - + サイズ -(&I) + + + + Si&ze + + サイズ +(&Z) + + + + Add &black borders + 黒枠の追加(&B) + + + + Soft&ware scaling + ソフトウェア スケール(&W) + + + + &FAQ + FAQ(&F) + + + + Visualize &motion vectors + モーション ベクターの視覚化(&M) + + + + &Command line options + コマンド ライン オプション(&C) + + + + SMPlayer command line options + SMPlayer のコマンド ライン オプション + + + + Enable &closed caption + クローズド キャプションを有効にする(&C) + + + + &Forced subtitles only + 強制された字幕のみ(&F) + + + + Reset video equalizer + ビデオ イコライザーのリセット + + + + MPlayer has finished unexpectedly. + MPlayer は予期せず終了しています。 + + + + Exit code: %1 + 終了コード: %1 + + + + MPlayer failed to start. + MPlayer が起動に失敗しました。 + + + + Please check the MPlayer path in preferences. + 環境設定で MPlayer のパスをチェックしてください。 + + + + MPlayer has crashed. + MPlayer はクラッシュしています。 + + + + See the log for more info. + さらなる情報はログをご覧ください。 + + + + &Rotate + 回転(&R) + + + + &Off + オフ(&O) + + + + &Rotate by 90 degrees clockwise and flip + 90 度時計回りに回転して垂直に反転(&R) + + + + Rotate by 90 degrees &clockwise + 90 度時計回りに回転(&C) + + + + Rotate by 90 degrees counterclock&wise + 90 度反時計回りに回転(&W) + + + + Rotate by 90 degrees counterclockwise and &flip + 90 度反時計回りに回転して垂直に反転(&F) + + + + &Jump to... + ジャンプ(&J)... + + + + Show context menu + コンテキスト メニューの表示 + + + + Multimedia + マルチメディア + + + + E&qualizer + イコライザー(&Q) + + + + Reset audio equalizer + オーディオ イコライザーのリセット + + + + Find subtitles on &OpenSubtitles.org... + OpenSubtitles.org から字幕を検索(&O)... + + + + Upload su&btitles to OpenSubtitles.org... + OpenSubtitles.org へ字幕をアップロード(&B)... + + + + &Tips + ヒント(&T) + + + + &Auto + 自動(&A) + + + + Speed -&4% + 速度 -4%(&4) + + + + &Speed +4% + 速度 +4%(&S) + + + + Speed -&1% + 速度 -1%(&1) + + + + S&peed +1% + 速度 +1%(&P) + + + + Scree&n + 画面(&N) + + + + &Default + 既定(&D) + + + + Mirr&or image + イメージを水平に反転(&O) + + + + Next video + 次のビデオ + + + + &Track + video + トラック(&T) + + + + &Track + audio + トラック(&T) + + + + Warning - Using old MPlayer + 警告 - 古い MPlayer を使用しています + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + お使いのシステムにインストールされている MPlayer のバージョン (%1) は古いです。SMPlayer はよく動作できません: いくつかのオプションは動作しません、字幕の選択は失敗する可能性があります... + + + + Please, update your MPlayer. + お使いの MPlayer を更新してください。 + + + + (This warning won't be displayed anymore) + (この警告はこれ以上表示されません) + + + + Next aspect ratio + 次のアスペクト比 + + + + &Auto zoom + オート ズーム(&A) + + + + Zoom for &16:9 + 16:9 用にズーム(&1) + + + + Zoom for &2.35:1 + 2.35:1 用にズーム(&2) + + + + Pre&view... + プレビュー(&V)... + + + + &Always + 常に(&A) + + + + &Never + しない(&N) + + + + While &playing + 再生中(&P) + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer はまだここで実行しています + + + + S&how icon in system tray + システム トレイにアイコンを表示(&H) + + + + &Hide + 非表示(&H) + + + + &Restore + 復元(&R) + + + + &Quit + 終了(&Q) + + + + Playlist + プレイリスト + + + + Core + + + Brightness: %1 + 明るさ: %1 + + + + Contrast: %1 + コントラスト: %1 + + + + Gamma: %1 + ガンマ: %1 + + + + Hue: %1 + 色合い: %1 + + + + Saturation: %1 + 鮮やかさ: %1 + + + + Volume: %1 + 音量: %1 + + + + Zoom: %1 + 拡大率: %1 + + + + Font scale: %1 + フォント スケール: %1 + + + + Aspect ratio: %1 + アスペクト比: %1 + + + + Updating the font cache. This may take some seconds... + フォント キャッシュを更新しています。これには数秒かかる可能性があります... + + + + DefaultGui + + + Welcome to SMPlayer + SMPlayer へようこそ + + + + Audio + オーディオ + + + + Subtitle + 字幕 + + + + &Main toolbar + メイン ツール バー(&M) + + + + &Language toolbar + 言語ツール バー(&L) + + + + &Toolbars + ツール バー(&T) + + + + EqSlider + + + icon + icon + + + + ErrorDialog + + + Hide log + ログを非表示にする + + + + Show log + ログの表示 + + + + MPlayer Error + MPlayer のエラー + + + + icon + icon + + + + Error + エラー + + + + FileDownloader + + + Downloading... + ダウンロード中... + + + + Downloading %1 + %1 をダウンロードしています + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - ファイルのプロパティ + + + + &Information + 情報(&I) + + + + &Demuxer + デミュクサー(&D) + + + + &Select the demuxer that will be used for this file: + このファイルに使用されるデミュクサーを選択します(&S): + + + + &Reset + リセット(&R) + + + + &Video codec + ビデオ コーデック(&V) + + + + &Select the video codec: + ビデオ コーデックを選択します(&S): + + + + A&udio codec + オーディオ コーデック(&U) + + + + &Select the audio codec: + オーディオ コーデックを選択します(&S): + + + + &MPlayer options + MPlayer のオプション(&M) + + + + Additional Options for MPlayer + MPlayer の追加オプション + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + ここでは MPlayer への追加オプションを渡すことができます。 +スペースで区切って書き込みます。 +例: -flip -nosound + + + + &Options: + オプション(&O): + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + 追加ビデオ フィルターも渡すことができます。 +"," で区切ります。スペースを使用しません! +例: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + ビデオ フィルター(&I): + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + そして最後はオーディオ フィルターです。ビデオ フィルターと同じ規則です。 +例: resample=44100:0:0,volnorm + + + + Audio &filters: + オーディオ フィルター(&F): + + + + OK + OK + + + + Cancel + キャンセル + + + + Apply + 適用 + + + + FindSubtitlesWindow + + + Language + 言語 + + + + Name + 名前 + + + + Format + フォーマット + + + + Files + ファイル + + + + Date + 日付 + + + + Uploaded by + アップロード者 + + + + All + すべて + + + + Close + 閉じる + + + + &Download + ダウンロード(&D) + + + + &Copy link to clipboard + クリップボードへリンクをコピー(&C) + + + + Error + エラー + + + + Download failed: %1. + ダウンロードが失敗しました: %1。 + + + + Connecting to %1... + %1 へ接続しています... + + + + Downloading... + ダウンロードしています... + + + + Done. + 完了しました。 + + + + %1 files available + %1 個のファイルが利用可能です + + + + Failed to parse the received data. + 受信されたデータの解析に失敗しました。 + + + + Find Subtitles + 字幕の検索 + + + + &Subtitles for + 検索するファイル(&S) + + + + &Language: + 言語(&L): + + + + &Refresh + 更新(&R) + + + + Subtitle saved as %1 + 字幕が %1 として保存されました + + + + %1 subtitle(s) extracted + + %1 個の字幕が展開されました + + + + + Overwrite? + 上書きしますか? + + + + The file %1 already exits, overwrite? + ファイル %1 はすでに存在します、上書きしますか? + + + + Error saving file + ファイルの保存エラー + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + フォルダー %1 にダウンロードされたファイルを +保存することができませんでした +そのフォルダの権限をチェックしてください。 + + + + Download failed + ダウンロードが失敗しました + + + + Temporary file %1 + 一時ファイル %1 + + + + InfoFile + + + General + 全般 + + + + Size + サイズ + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + 長さ + + + + Demuxer + デミュクサー + + + + Name + 名前 + + + + Artist + アーティスト + + + + Author + 作者 + + + + Album + アルバム + + + + Genre + ジャンル + + + + Date + 日付 + + + + Track + トラック + + + + Copyright + 著作権 + + + + Comment + コメント + + + + Software + ソフトウェア + + + + Clip info + クリップ情報 + + + + Video + ビデオ + + + + Resolution + 解像度 + + + + Aspect ratio + アスペクト比 + + + + Format + フォーマット + + + + Bitrate + ビットレート + + + + %1 kbps + %1 kbps + + + + Frames per second + フレーム パー セコンド + + + + Selected codec + 選択されたコーデック + + + + Initial Audio Stream + 初期オーディオ ストリーム + + + + Rate + + + + + %1 Hz + %1 Hz + + + + Channels + チャンネル + + + + Audio Streams + オーディオ ストリーム + + + + Language + 言語 + + + + empty + + + + + Subtitles + 字幕 + + + + Type + 種類 + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + 番号 + + + + Stream title + ストリームのタイトル + + + + Stream URL + ストリームの URL + + + + File + ファイル + + + + InputDVDDirectory + + + Choose a directory + ディレクトリを選択します + + + + SMPlayer - Play a DVD from a folder + SMPlayer - フォルダーから DVD を再生 + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + お使いのハード ディスクから dvd を再生できます。VIDEO_TS および AUDIO_TS ディレクトリを含むフォルダーを選択します。 + + + + Choose a directory... + ディレクトリの選択... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - MPlayer のバージョンを入力 + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer は使用中の MPlayer のバージョンを識別できませんでした。 + + + + Version reported by MPlayer: + MPlayer によって報告されたバージョン: + + + + Please, &select the correct version: + 正しいバージョンを選択してください(&S): + + + + 1.0rc1 or older + 1.0rc1 以前 + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + 1.0rc2 より上 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - URL の入力 + + + + &URL: + URL(&U): + + + + It's a &playlist + プレイリストです(&P) + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + このオプションがチェックされている場合、URL はプレイリストとして処理されます: テキストとして開かれてそれにある URL を再生します。 + + + + Languages + + + Afar + アファル語 + + + + Abkhazian + アブハズ語 + + + + Afrikaans + アフリカーンス語 + + + + Amharic + アムハラ語 + + + + Arabic + アラビア語 + + + + Assamese + アッサム語 + + + + Aymara + アイマラ語 + + + + Azerbaijani + アゼルバイジャン語 + + + + Bashkir + バシキール語 + + + + Byelorussian + ベラルーシ語 + + + + Bulgarian + ブルガリア語 + + + + Bihari + ビハール語 + + + + Bislama + ビスラマ語 + + + + Bengali + ベンガル語 + + + + Tibetan + チベット語 + + + + Breton + ブルトン語 + + + + Catalan + カタロニア語 + + + + Corsican + コルシカ語 + + + + Czech + チェコ語 + + + + Welsh + ウェールズ語 + + + + Danish + デンマーク語 + + + + German + ドイツ語 + + + + Bhutani + ゾンカ語 + + + + Greek + ギリシャ語 + + + + English + 英語 + + + + Esperanto + エスペラント語 + + + + Spanish + スペイン語 + + + + Estonian + エストニア語 + + + + Basque + バスク語 + + + + Persian + ペルシア語 + + + + Finnish + フィンランド語 + + + + Fiji + フィジー語 + + + + Faroese + フェロー語 + + + + French + フランス語 + + + + Frisian + フリジア語 + + + + Irish + アイルランド語 + + + + Scots + スコットランド語 + + + + Galician + ガリシア語 + + + + Guarani + グアラーニ + + + + Gujarati + グジャラート語 + + + + Hausa + ハウサ語 + + + + Hebrew + ヘブライ語 + + + + Hindi + ヒンディー語 + + + + Croatian + クロアチア語 + + + + Hungarian + ハンガリー語 + + + + Armenian + アルメニア語 + + + + Interlingua + インターリングア + + + + Indonesian + インドネシア語 + + + + Interlingue + インターリング + + + + Inupiak + イヌピアック語 + + + + Icelandic + アイスランド語 + + + + Italian + イタリア語 + + + + Inuktitut + イヌイット語 + + + + Japanese + 日本語 + + + + Javanese + ジャワ語 + + + + Georgian + グルジア語 + + + + Kazakh + カザフ語 + + + + Greenlandic + グリーンランド語 + + + + Cambodian + カンボジア語 + + + + Kannada + カンナダ + + + + Korean + 韓国語 + + + + Kashmiri + カシミール語 + + + + Kurdish + クルド語 + + + + Kirghiz + キルギス語 + + + + Latin + ラテン語 + + + + Lingala + リンガラ語 + + + + Laothian + ラオス語 + + + + Lithuanian + リトアニア語 + + + + Latvian + ラトビア語 + + + + Malagasy + マダガスカル語 + + + + Maori + マオリ語 + + + + Macedonian + マケドニア語 + + + + Malayalam + マラヤーラム語 + + + + Mongolian + モンゴル語 + + + + Moldavian + モルドバ語 + + + + Marathi + マラーティー語 + + + + Malay + マレー語 + + + + Maltese + マルタ語 + + + + Burmese + ビルマ語 + + + + Nauru + ナウル語 + + + + Nepali + ネパール語 + + + + Dutch + オランダ語 + + + + Norwegian + ノルウェー語 + + + + Occitan + オキタン語 + + + + Oriya + オーリア語 + + + + Punjabi + パンジャブ語 + + + + Polish + ポーランド語 + + + + Pashto + パシュト語 + + + + Portuguese + ポルトガル語 + + + + Quechua + ケチュア語 + + + + Kirundi + キルンディ語 + + + + Romanian + ルーマニア語 + + + + Russian + ロシア語 + + + + Kinyarwanda + キニャーワンダ語 + + + + Sanskrit + サンスクリット語 + + + + Sindhi + シンディー語 + + + + Sangho + サンゴ語 + + + + Sinhalese + シンハラ語 + + + + Slovak + スロバキア語 + + + + Slovenian + スロベニア語 + + + + Samoan + サモア語 + + + + Shona + ショナ語 + + + + Somali + ソマリ語 + + + + Albanian + アルバニア語 + + + + Serbian + セルビア語 + + + + Siswati + シスワティ語 + + + + Sesotho + セソト語 + + + + Sundanese + スンダン語 + + + + Swedish + スウェーデン語 + + + + Swahili + スワヒリ語 + + + + Tamil + タミル語 + + + + Telugu + テルグ語 + + + + Tajik + タジク語 + + + + Thai + タイ語 + + + + Tigrinya + ティグリニャ語 + + + + Turkmen + トルクメン語 + + + + Tagalog + タガログ語 + + + + Setswana + セツワナ語 + + + + Tonga + トンガ語 + + + + Turkish + トルコ語 + + + + Tsonga + ツォンガ語 + + + + Tatar + タタール語 + + + + Twi + トウィ語 + + + + Uighur + ウイグル語 + + + + Ukrainian + ウクライナ語 + + + + Urdu + ウルドゥー語 + + + + Uzbek + ウズベク語 + + + + Vietnamese + ベトナム語 + + + + Wolof + ウォロフ語 + + + + Xhosa + コサ語 + + + + Yiddish + イディッシュ語 + + + + Yoruba + ヨルバ語 + + + + Zhuang + チワン語 + + + + Chinese + 中国語 + + + + Zulu + ズールー語 + + + + Portuguese - Brazil + ポルトガル語 - ブラジル + + + + Portuguese - Portugal + ポルトガル語 - ポルトガル + + + + Simplified-Chinese + 簡体字中国語 + + + + Traditional Chinese + 繁体字中国語 + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + 西ヨーロッパ言語 + + + + Western European Languages with Euro + ユーロ地域の西ヨーロッパ言語 + + + + Slavic/Central European Languages + スラブ語/中央ヨーロッパ言語 + + + + Esperanto, Galician, Maltese, Turkish + エスペラント語、ガリシア語、マルタ語、トルコ語 + + + + Old Baltic charset + 古バルト語文字セット + + + + Cyrillic + キリル言語 + + + + Modern Greek + 現代ギリシャ語 + + + + Baltic + バルト語 + + + + Celtic + ケルト語 + + + + Hebrew charsets + ヘブライ語文字セット + + + + Ukrainian, Belarusian + ウクライナ語、ベラルーシ語 + + + + Simplified Chinese charset + 簡体字中国語文字セット + + + + Traditional Chinese charset + 繁体字中国語文字セット + + + + Japanese charsets + 日本語文字セット + + + + Korean charset + 韓国語文字セット + + + + Thai charset + タイ語文字セット + + + + Cyrillic Windows + キリル言語 Windows + + + + Slavic/Central European Windows + スラブ語/中央ヨーロッパ Windows + + + + Arabic Windows + アラビア語 Windows + + + + Rhaeto-Romance + レト・ロマン語 + + + + Serbo-Croatian + セルボクロアチア語 + + + + Volapük + ヴォラピュク語 + + + + Avestan + アヴェスター語 + + + + Akan + アカン語 + + + + Aragonese + アラゴン語 + + + + Avaric + アヴァル語 + + + + Belarusian + ベラルーシ語 + + + + Bambara + バンバラ語 + + + + Bosnian + ボスニア語 + + + + Chechen + チェチェン語 + + + + Cree + クリー語 + + + + Church + 教会語 + + + + Chuvash + チュヴァシ語 + + + + Divehi + ディベヒ語 + + + + Dzongkha + ゾンカ語 + + + + Ewe + エウェ語 + + + + Fulah + フラニ語 + + + + Fijian + フィジー語 + + + + Gaelic + ゲール語 + + + + Manx + マン島語 + + + + Hiri + ヒリ語 + + + + Haitian + ハイチ語 + + + + Herero + ヘレロ語 + + + + Chamorro + チャモロ語 + + + + Igbo + イボ語 + + + + Sichuan + 四川語 + + + + Inupiaq + イヌピア語 + + + + Ido + イド語 + + + + Kongo + コンゴ語 + + + + Kikuyu + キクユ語 + + + + Kuanyama + クアニャマ語 + + + + Khmer + クメール語 + + + + Kanuri + カヌリ語 + + + + Komi + コミ語 + + + + Cornish + コーンウォール語 + + + + Luxembourgish + ルクセンブルク語 + + + + Ganda + ガンダ語 + + + + Limburgan + リンブルフ語 + + + + Lao + ラオ語 + + + + Luba-Katanga + ルバ・カタンガ語 + + + + Marshallese + マーシャル語 + + + + Bokmål + ブークモール + + + + Ndebele + ンデベレ語 + + + + Ndonga + ンドンガ語 + + + + Navajo + ナバホ語 + + + + Chichewa + チチェワ語 + + + + Ojibwa + オジブウェー語 + + + + Oromo + オロモ語 + + + + Ossetian + オセット語 + + + + Panjabi + パンジャビ語 + + + + Pali + パーリ語 + + + + Pushto + パシュトー語 + + + + Romansh + ロマンシュ語 + + + + Rundi + ルンディ語 + + + + Sardinian + サルディーニャ語 + + + + Sami + サーミ語 + + + + Sango + サンゴ語 + + + + Sinhala + シンハラ語 + + + + Swati + スワティ語 + + + + Sotho + ソト語 + + + + Tswana + ツワナ語 + + + + Tahitian + タヒチ語 + + + + Venda + ヴェンダ語 + + + + Volapük + ヴォラピュク語 + + + + Walloon + ワロン語 + + + + LogWindow + + + Choose a filename to save under + 下に保存するファイル名の選択 + + + + Confirm overwrite? + 上書きを確認しますか? + + + + The file already exists. +Do you want to overwrite? + ファイルはすでに存在します。 +上書きしますか? + + + + Error saving file + ファイルの保存エラー + + + + The log couldn't be saved + ログは保存できませんでした + + + + Logs + ログ + + + + LogWindowBase + + + Log Window + ログ ウィンドウ + + + + Save + 保存 + + + + Copy to clipboard + クリップボードへコピー + + + + Close + 閉じる + + + + &Close + 閉じる(&C) + + + + MiniGui + + + Control bar + コントロール バー + + + + MpcGui + + + Control bar + コントロール バー + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + 名前 + + + + Length + 長さ + + + + &Play + 再生(&P) + + + + &Edit + 編集(&E) + + + + Playlists + プレイリスト + + + + Choose a file + ファイルの選択 + + + + Choose a filename + ファイル名の選択 + + + + Confirm overwrite? + 上書きを確認しますか? + + + + The file %1 already exists. +Do you want to overwrite? + ファイル %1 はすでに存在します。 +上書きしますか? + + + + All files + すべてのファイル + + + + Select one or more files to open + 1 つ以上の開くファイルを選択します + + + + Choose a directory + ディレクトリを選択します + + + + Edit name + 名前の編集 + + + + Type the name that will be displayed in the playlist for this file: + このファイルのプレイリストに表示される名前を入力します: + + + + &Load + 読み込み(&L) + + + + &Save + 保存(&S) + + + + &Next + 次へ(&N) + + + + Pre&vious + 前へ(&V) + + + + Move &up + 上へ移動(&U) + + + + Move &down + 下へ移動(&D) + + + + &Repeat + 繰り返し(&R) + + + + S&huffle + シャッフル(&H) + + + + Add &current file + 現在のファイルを追加(&C) + + + + Add &file(s) + ファイルの追加(&F) + + + + Add &directory + ディレクトリの追加(&D) + + + + Remove &selected + 選択済みの削除(&S) + + + + Remove &all + すべて削除(&A) + + + + SMPlayer - Playlist + SMPlayer - プレイリスト + + + + Add... + 追加... + + + + Remove... + 削除... + + + + Playlist modified + プレイリストが変更されました + + + + There are unsaved changes, do you want to save the playlist? + 未保存の変更があります、プレイリストを保存しますか? + + + + Preferences + 環境設定 + + + + PlaylistPreferences + + + Playlist - Preferences + プレイリスト - 環境設定 + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + ディレクトリの追加が再帰的にサブディレクトリのファイルも追加することがよい場合はこのオプションをチェックします。でなければ選択されたディレクトリのファイルのみ追加されます。 + + + + &Add files in directories recursively + 再帰的にディレクトリのファイルを追加する(&A) + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + いくつかの情報をプレイリストに追加されるファイルに問い合わせるにはこのオプションをチェックします。それはファイルのタイトル名 (利用可能なら) と長さの表示を許可します。でなければこの情報はファイルが実際に再生されるまで利用できません。用心: このオプションは特に多くのファイルを追加する場合、低速になることがあります。 + + + + Automatically get &info about files added + 自動的に追加されるファイルについての情報を取得する(&I) + + + + &Save copy of playlist on exit + 終了時にプレイリストのコピーを保存する(&S) + + + + &Play files from start + 開始からファイルを再生する(&P) + + + + PrefAdvanced + + + Advanced + 詳細設定 + + + + Auto + 自動 + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + このオプションのチェックはちらつきを減少させる可能性がありますが、ビデオが適切に表示されなくなることを生む可能性もあります。 + + + + Log MPlayer output + MPlayer の出力を記録します + + + + Log SMPlayer output + SMPlayer の出力を記録します + + + + Filter for SMPlayer logs + SMPlayer のログのフィルター + + + + &Advanced + 詳細設定(&A) + + + + icon + icon + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + ここでは MPlayer への追加オプションを渡すことができます。 +スペースで区切って書き込みます。 +例: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + 追加ビデオ フィルターも渡すことができます。 +"," で区切ります。スペースを使用しません! +例: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + そして最後はオーディオ フィルターです。ビデオ フィルターと同じ規則です。 +例: resample=44100:0:0,volnorm + + + + This option is mainly intended for debugging the application. + このオプションは主にアプリケーションのデバッグが対象です。 + + + + &Monitor aspect: + モニターのアスペクト(&M): + + + + &Run MPlayer in its own window + 独自のウィンドウで MPlayer を実行する(&R) + + + + &Options: + オプション(&O): + + + + V&ideo filters: + ビデオ フィルター(&I): + + + + Audio &filters: + オーディオ フィルター(&F): + + + + &Colorkey: + カラーキー(&C): + + + + Log &SMPlayer output + SMPlayer の出力を記録する(&S) + + + + &Filter for SMPlayer logs: + SMPlayer のログのフィルター(&F): + + + + C&hange... + 変更(&H)... + + + + Logs + ログ + + + + Log MPlayer &output + MPlayer の出力を記録する(&O) + + + + Options for MP&layer + MPlayer のオプション(&L) + + + + Autosave MPlayer log + MPlayer のログを自動保存する + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + このオプションがチェックされている場合、MPlayer のログは新しいファイルが再生を開始するごとに指定されたファイルへ保存されます。外部のアプリケーションに意図されています、なので再生しているファイルについての情報を取得できます。 + + + + Autosave MPlayer log filename + MPlayer のログのファイル名を自動保存する + + + + Enter here the path and filename that will be used to save the MPlayer log. + MPlayer のログを保存するのに使用されるパスとファイル名をここに入力します。 + + + + A&utosave MPlayer log to file + ファイルへ MPlayer のログを自動保存する(&U) + + + + Pass short filenames (8+3) to MPlayer + MPlayer へ短いファイル名 (8+3) を渡す + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + 現在 MPlayer はローカル コードページ外の文字を含むファイル名を開くことができません。このオプションのチェックは SMPlayer にファイル名の短いバージョンを MPlayer へ渡させ、こうして開けるようになります。 + + + + &Pass short filenames (8+3) to MPlayer + MPlayer へ短いファイル名 (8+3) を渡す(&P) + + + + Monitor aspect + モニターのアスペクト + + + + Select the aspect ratio of your monitor. + モニターのアスペクト比を選択します。 + + + + Run MPlayer in its own window + 独自のウィンドウで MPlayer を実行する + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + このオプションをチェックすると、MPlayer のビデオ ウィンドウは SMPlayer のメイン ウィンドウに埋め込まれず代わりに独自のウィンドウを使用します。マウスとキーボードのイベントは MPlayer によって直接ハンドルされ、それがキー ショートカットとマウス クリックがおそらく MPlayer のウィンドウにフォーカスがあるとき予期したとおり動作しないことに注意します。 + + + + Colorkey + カラーキー + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + 何かその他のウィンドウを超えてビデオの部分が見える場合は、修正するのにカラーキーを変更できます。黒に近い色の選択を試行します。 + + + + Options for MPlayer + MPlayer のオプション + + + + Options + オプション + + + + Here you can type options for MPlayer. Write them separated by spaces. + ここでは MPlayer のオプションを入力できます。スペースで区切って書き込みます。 + + + + Video filters + ビデオ フィルター + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + ここでは MPlayer のビデオ フィルターを追加できます。コンマで区切って書き込みます。スペースを使用しません! + + + + Audio filters + オーディオ フィルター + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + ここでは MPlayer のオーディオ フィルターを追加できます。コンマで区切って書き込みます。スペースを使用しません! + + + + Repaint the background of the video window + ビデオ ウィンドウの背景を再描画する + + + + Repaint the backgroun&d of the video window + ビデオ ウィンドウの背景を再描画する(&D) + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + ネットワーク接続に IPv4 を使用します。自動的に IPv6 に頼ります。 + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + ネットワーク接続に IPv6 を使用します。自動的に IPv4 に頼ります。 + + + + Network Connection + ネットワーク接続 + + + + IPv&4 + IPv4(&4) + + + + IPv&6 + IPv6(&6) + + + + Lo&gs + ログ(&G) + + + + Rebuild index if needed + 必要ならインデックスを再構築する + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + インデックスが見つからなかった場合はファイルのインデックスを再構築し、シークを許可します。破損した/未完了のダウンロード、または不良に作成されたファイルに有用です。このオプションは基礎となるメディアがシークをサポートする場合のみ動作します (すなわち stdin、pipe、などを持たないもの)。<br> 注意: インデックスの作成には時間がかかる可能性があります。 + + + + Rebuild &index if needed + 必要ならインデックスを再構築する(&I) + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + このオプションがチェックされている場合、SMPlayer は SMPlayer が出力するデバッグ メッセージ (<b>オプション -> ログの表示 -> SMPlayer</b> でログをご覧になれます) を格納します。この情報はバグを見つける場合に開発者に非常に有用です。 + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + チェックされている場合、SMPlayer は MPlayer の出力 (<b>オプション -> ログの表示 -> MPlayer</b> でご覧になれます) を格納します。問題の場合にこのログは重要な情報を含むことがあるので、このオプションのチェックを維持することが推奨されます。 + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + このオプションはログに格納される SMPlayer のメッセージのフィルターを許可します。ここでは何か正規表現を書き込むことができます。<br>例: <i>^Core::.*</i> は <i>Core::</i> で始まる行のみ表示します + + + + Correct pts + pts を修正する + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + ビデオ フレームのタイムスタンプが異なって計算され新しいフレームを追加するか既存のものを変更するビデオ フィルターがサポートされている実験的なモードへ MPlayer を切り替えます。より正確なタイムスタンプはたとえば SSA/ASS ライブラリが有効でシーンの変更に合わせられた字幕を再生するときに可視にできます。pts の修正なしでは字幕のタイミングが通常いくつかのフレームでオフになります。このオプションはいくつかのデミュクサーとコーデックでは動作しません。 + + + + Proxy + プロキシ + + + + Enable proxy + プロキシを有効にする + + + + Enable/disable the use of the proxy. + プロキシの使用を有効/無効にします。 + + + + Host + ホスト + + + + The host name of the proxy. + プロキシのホスト名です。 + + + + Port + ポート + + + + The port of the proxy. + プロキシのポートです。 + + + + Username + ユーザー名 + + + + If the proxy requires authentication, this sets the username. + プロキシが認証を必要とする場合、これはユーザー名を設定します。 + + + + Password + パスワード + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + プロキシのパスワードです。警告: パスワードは構成ファイルにプレーン テキストとして保存されます。 + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + インターネット接続のプロキシを設定できます (現在は字幕のダウンロードのみに使用されます)。 + + + + &Enable proxy + プロキシを有効にする(&E) + + + + &Host: + ホスト(&H): + + + + &Port: + ポート(&P): + + + + &Username: + ユーザー名(&U): + + + + Pa&ssword: + パスワード(&S): + + + + C&orrect PTS + PTS を修正する(&O) + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + 種類 + + + + Select the proxy type to be used. + 使用されるプロキシの種類を選択します。 + + + + &Type: + 種類(&T): + + + + Actions list + 動作の一覧 + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + ここではファイルが開かれるごとに実行される<i>動作</i>の一覧を指定できます。<b>[キーボードとマウス]</b> セクションのキー ショートカット エディターですべての利用可能な動作が見つかります。動作はスペースで区切られる必要があります。チェック可能な動作は動作を有効または無効にするのに <i>true</i> または <i>false</i> で追従できます。 + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + 制限: 動作はファイルが開かれたときのみで mplayer プロセスが再起動されたとき (例: オーディオまたはビデオ フィルターの選択) には実行されません。 + + + + Network + ネットワーク + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + ファイルが開かれるごとに以下の動作を実行します。動作はスペースで区切られる必要があります(&U): + + + + &Network + ネットワーク(&N) + + + + Example: + 例: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + インデックスが見つからなかった場合はファイルのインデックスを再構築し、シークを許可します。破損した/未完了のダウンロード、または不良に作成されたファイルに有用です。このオプションは基礎となるメディアがシークをサポートする (すなわち stdin、pipe、などがない) 場合のみ動作します。<br> <b>注意:</b> インデックスの作成には時間がかかる可能性があります。 + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + プロキシのパスワードです。<b>警告:</b> パスワードは構成ファイルにプレーン テキストとして保存されます。 + + + + PrefAssociations + + + Warning + 警告 + + + + Not all files could be associated. Please check your security permissions and retry. + すべてのファイルは関連付けできませんでした。セキュリティの許可をチェックして再試行してください。 + + + + File Types + ファイルの種類 + + + + Select all + すべて選択 + + + + Check all file types in the list + 一覧のすべてのファイルの種類をチェックします + + + + Uncheck all file types in the list + 一覧のすべてのファイルの種類をチェック解除します + + + + List of file types + ファイルの種類の一覧 + + + + File types + ファイルの種類 + + + + Media files handled by SMPlayer: + SMPlayer によってハンドルされるメディア ファイル: + + + + Select All + すべて選択 + + + + Select None + 選択しない + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + SMPlayer にハンドルさせたいメディア ファイルの拡張子をチェックします。[適用] をクリックすると、チェックされたファイルは SMPlayer に関連付けされます。メディアの種類をチェック解除すると、ファイルの関連付けは復元されます。 + + + + Select none + 選択しない + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>注意:</b> (復元は Windows Vista では動作しません)。 + + + + PrefDrives + + + Drives + ドライブ + + + + CD device + CD デバイス + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + お使いの CDROM デバイスを選択します。VCD とオーディオ CD の再生に使用されます。 + + + + DVD device + DVD デバイス + + + + Choose your DVD device. It will be used to play DVDs. + お使いの DVD デバイスを選択します。DVD の再生に使用されます。 + + + + icon + icon + + + + Select your &CD device: + お使いの CD デバイスを選択します(&C): + + + + Select your &DVD device: + お使いの DVD デバイスを選択します(&D): + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer が既定では CDROM または DVD デバイスを選択しません。なので実際に CD または DVD を再生する前に使用したいデバイスを選択する必要があります (同じにできます)。 + + + + PrefGeneral + + + General + 全般 + + + + Select the mplayer executable + mplayer 実行ファイルの選択 + + + + Executables + 実行ファイル + + + + All files + すべてのファイル + + + + Select a directory + ディレクトリを選択します + + + + MPlayer executable + MPlayer 実行ファイル + + + + Screenshots folder + スクリーンショット フォルダー + + + + Video output driver + ビデオの出力ドライバー + + + + Audio output driver + オーディオの出力ドライバー + + + + Select the audio output driver. + オーディオの出力ドライバーを選択します。 + + + + Remember settings + 設定を記憶する + + + + Preferred audio language + オーディオの優先言語 + + + + Preferred subtitle language + 字幕の優先言語 + + + + Software video equalizer + ソフトウェアのビデオ イコライザー + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + ビデオ イコライザーがお使いのグラフィック カードまたは選択されたビデオの出力ドライバーによってサポートされていない場合このオプションをチェックできます。<br><b>注意:</b> このオプションはいくつかのビデオの出力ドライバーとは互換性がないことがあります。 + + + + Postprocessing quality + 後処理の品質 + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + 利用可能なスペア CPU 時間次第で後処理のレベルを動的に変更します。指定する番号は使用される最大レベルになります。通常いくらかの大きい番号を使用できます。 + + + + Start videos in fullscreen + 全画面表示でビデオを開始する + + + + If this option is checked, all videos will start to play in fullscreen mode. + このオプションがチェックされている場合、すべてのビデオは全画面表示モードで開始されます。 + + + + Disable screensaver + スクリーンセーバーを無効にする + + + + Software volume control + ソフトウェアのボリューム コントロール + + + + Check this option to use the software mixer, instead of using the sound card mixer. + サウンド カード ミキサーを使用する代わりに、ソフトウェア ミキサーを使用するにはこのオプションをチェックします。 + + + + &General + 全般(&G) + + + + Paths + パス + + + + Media settings + メディアの設定 + + + + Preferred audio and subtitles + 優先オーディオおよび字幕 + + + + Video + ビデオ + + + + Audio + オーディオ + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Change volume + 音量の変更 + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + チェックされている場合、SMPlayer はそれぞれのファイルの音量を記憶して再び再生されるときに復元します。新しいファイルには既定の音量が使用されます。 + + + + 0 + 0 + + + + &Change volume on every file + それぞれのファイルで音量を変更する(&C) + + + + Select the &MPlayer executable: + MPlayer 実行ファイルを選択します(&M): + + + + &Folder for storing screenshots: + スクリーンショットを格納するフォルダー(&F): + + + + &Audio: + オーディオ(&A): + + + + &Remember settings for all files (audio track, subtitles...) + すべてのファイルの設定を記憶する (オーディオ トラック、字幕...)(&R) + + + + Su&btitles: + 字幕(&B): + + + + &Quality: + 品質(&Q): + + + + Start videos in &fullscreen + 全画面表示でビデオを開始する(&F) + + + + Disable &screensaver + スクリーンセーバーを無効にする(&S) + + + + &Default volume: + 既定の音量(&D): + + + + Use s&oftware volume control + ソフトウェアのボリューム コントロールを使用する(&O) + + + + Ma&x. Amplification: + 最大増幅(&X): + + + + &AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF(&A) + + + + Direct rendering + 直接描画 + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + チェックされている場合、直接描画をオンにします (すべてのコーデックとビデオ出力によってはサポートされていません)<br><b>警告:</b> OSD/SUB の破損を引き起こす可能性があります! + + + + Double buffering + ダブル バッファー + + + + D&irect rendering + 直接描画(&R) + + + + Dou&ble buffering + ダブル バッファー(&B) + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + ダブル バッファーはメモリに 2 つのフレームが格納されるのと、別のデコード中の表示によるちらつきを修正します。無効である場合は OSD を悪化させることがありますが、大抵 OSD のちらつきを削除します。 + + + + &Enable postprocessing by default + 既定で後処理を有効にする(&E) + + + + Volume &normalization by default + 既定での音量の通常化(&N) + + + + Close when finished + 完了時に閉じる + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + このオプションがチェックされている場合、メイン ウィンドウは現在のファイル/プレイリストの完了時に自動的に閉じられます。 + + + + 2 (Stereo) + 2 (ステレオ) + + + + 4 (4.0 Surround) + 4 (4.0 サラウンド) + + + + 6 (5.1 Surround) + 6 (5.1 サラウンド) + + + + C&hannels by default: + 既定でのチャンネル(&H): + + + + &Pause when minimized + 最小化時に一時停止する(&P) + + + + Pause when minimized + 最小化時に一時停止する + + + + Enable postprocessing by default + 既定で後処理を有効にする + + + + Max. Amplification + 最大増幅 + + + + Volume normalization by default + 既定での音量の通常化 + + + + Maximizes the volume without distorting the sound. + サウンドの歪曲なしで音量を最大化します。 + + + + Default volume + 既定の音量 + + + + Sets the initial volume that new files will use. + 新しいファイルが使用する初期音量を設定します。 + + + + Channels by default + 既定でのチャンネル + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + パーセントで最大増幅レベルを設定します (既定: 110)。200 の値は最大で現在のレベルの倍へ音量を上方調整するのを許可します。100 より下の値では初期音量 (100%) がたとえば OSD を正しく表示できない、最大より上になります。 + + + + Uses hardware AC3 passthrough + ハードウェア AC3 passthrough を使用します + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + 再生チャンネルの数を要求します。MPlayer は指定されただけの数のチャンネルにオーディオをデコードするようデコーダーに要求します。次に要求が満たされるのはデコーダー次第です。これは通常 AC3 オーディオ (DVD のような) でビデオを再生するときのみ重要です。その場合は liba52 が既定でデコードして要求されたチャンネルの数にオーディオをダウンミックスします。注意: このオプションはコーデック (AC3 のみ)、フィルター (サラウンド) およびオーディオの出力ドライバー (少なくとも OSS) によって尊重されています。 + + + + Postprocessing will be used by default on new opened files. + 後処理は新しく開かれるファイルに既定で使用されます。 + + + + Audio track + オーディオ トラック + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + 新しいファイルの再生時に使用される既定のオーディオ トラックを指定します。トラックが存在しない場合、最初のものが使用されます。<br><b>注意:</b> <i>"オーディオの優先言語"</i>はこのオプションを超えて優先されます。 + + + + Subtitle track + 字幕トラック + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + 新しいファイルの再生時に使用される既定の字幕トラックを指定します。トラックが存在しない場合、最初のものが使用されます。<br><b>注意:</b> <i>"字幕の優先言語"</i>はこのオプションを超えて優先されます。 + + + + Or choose a track number: + またはトラック番号を選択します: + + + + Audi&o: + オーディオ(&O): + + + + Preferred language: + 優先言語: + + + + Preferre&d audio and subtitles + 優先オーディオおよび字幕(&D) + + + + &Subtitle: + 字幕(&S): + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + ここではオーディオおよび字幕ストリームの優先言語を入力できます。複数のオーディオまたは字幕ストリームのあるメディアが見つかると、SMPlayer は優先言語の使用を試行します。これは DVD か mkv ファイルのような、オーディオおよび字幕ストリームの言語についての情報を提供するメディアでのみ動作します。<br>これらの欄は正規表現を受け入れます。例: <b>es|esp|spa</b> は <i>es</i>、<i>esp</i> または <i>spa</i> に一致する場合トラックを選択します。 + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + ピッチの変化なしの高速再生(&P) + + + + High speed playback without altering pitch + ピッチの変化なしの高速再生 + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + ピッチの変化なしの再生速度の変更を許可します。少なくとも MPlayer dev-SVN-r24924 を必要とします。 + + + + Change volume just before playing + 再生の直前に音量を変更する + + + + &Video + ビデオ(&V) + + + + Use s&oftware video equalizer + ソフトウェアのビデオ イコライザーを使用する(&O) + + + + A&udio + オーディオ(&U) + + + + Volume + 音量 + + + + None + なし + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (通常) + + + + Yadif (double framerate) + Yadif (ダブル フレームレート) + + + + Linear Blend + リニア ブレンド + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + 既定でのインターレース解除(&N): + + + + Deinterlace by default + 既定でのインターレース解除 + + + + Select the deinterlace filter that you want to be used for new videos opened. + 開かれる新しいビデオに使用したいインターレース解除フィルターを選択します。 + + + + Remember time position + 時間の位置を記憶する + + + + Remember &time position + 時間の位置を記憶する(&T) + + + + Change volume just before p&laying + 再生の直前に音量を変更する(&L) + + + + Enable the audio equalizer + オーディオ イコライザーを有効にする + + + + Check this option if you want to use the audio equalizer. + オーディオ イコライザーを使用したい場合はこのオプションをチェックします。 + + + + &Enable the audio equalizer + オーディオ イコライザーを有効にする(&E) + + + + Draw video using slices + スライスを使用してビデオを描画する + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + 16 ピクセル高のスライス/バンドによるビデオの描画を有効/無効にします。無効である場合、フレーム全体は単一の実行で描画されます。高速になるか低速になるかは、ビデオ カードと利用可能なキャッシュ次第です。libmpeg2 および libavcodec コーデックでのみ影響があります。 + + + + Dra&w video using slices + スライスを使用してビデオを描画する(&W) + + + + &Close when finished playback + 再生の完了時に閉じる(&C) + + + + fast + 高速 + + + + slow + 低速 + + + + fast - ATI cards + 高速 - ATI カード + + + + User defined... + ユーザー定義... + + + + Default zoom + 既定の拡大率 + + + + This option sets the default zoom which will be used for new videos. + このオプションは新しいビデオに使用される既定の拡大率を設定します。 + + + + Default &zoom: + 既定の拡大率(&Z): + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + ここでは SMPlayer が使用する mplayer 実行ファイルを指定する必要があります。<br>SMPlayer は少なくとも MPlayer 1.0rc1 を必要とします (しかし SVN からの最近のリビジョンは強く推奨されます)。 + + + + If this setting is wrong, SMPlayer won't be able to play anything! + この設定が間違っている場合、SMPlayer は何も再生することができません! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + ここでは SMPlayer によって取得されるスクリーンショットが格納されるフォルダーを指定できます。この欄が空である場合はスクリーンショット機能は無効になります。 + + + + Select the video output driver. %1 provides the best performance. + ビデオの出力ドライバーを選択します。%1 は最高のパフォーマンスを供給します。 + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 は推奨されるものです。%2 と %3 の回避を試行します、低速でパフォーマンスに衝撃を与えることがあります。 + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + 通常 SMPlayer は再生するファイルごとに設定 (選択されたオーディオ トラック、音量、フィルター...) を記憶します。この機能がお好みでない場合はこの機能を無効にします。 + + + + If you check this option, SMPlayer will play all files from the beginning. + このオプションをチェックすると、SMPlayer はすべてのファイルを最初から再生します。 + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + このオプションが有効である場合、ファイルはメイン ウィンドウが非表示であるときに一時停止されます。ウィンドウが復元されると、再生は再開されます。 + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + 再生中にスクリーンセーバーを無効にするにはこのオプションをチェックします。<br>スクリーンセーバーは再生の完了時に再び有効になります。 + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + ここではオーディオ ストリームの優先言語を入力できます。複数のオーディオ ストリームのあるメディアが見つかると、SMPlayer は優先言語の使用を試行します。<br>これは DVD または mkv ファイルのような、オーディオ ストリームの言語についての情報を提供するメディアでのみ動作します。<br>この欄は正規表現を受け入れます。例: <b>es|esp|spa</b> は <i>es</i>、<i>esp</i> または <i>spa</i> に一致する場合にオーディオ トラックを選択します。 + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + ここでは字幕ストリームの優先言語を入力できます。複数の字幕ストリームのあるメディアが見つかると、SMPlayer は優先言語の使用を試行します。<br>これは DVD または mkv ファイルのような、字幕ストリームの言語についての情報を提供するメディアでのみ動作します。<br>この欄は正規表現を受け入れます。例: <b>es|esp|spa</b> は <i>es</i>、<i>esp</i> または <i>spa</i> に一致する場合に字幕ストリームを選択します。 + + + + Ou&tput driver: + 出力ドライバー(&T): + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + このオプションがチェックされている場合初期音量は再生が開始する直前に設定されます。これは起動時の大きな音量を回避します。少なくとも MPlayer SVN r27872 を必要とします。 + + + + Add black borders on fullscreen + 全画面表示で黒枠を表示する + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + このオプションが有効である場合、黒枠は全画面モードでイメージに追加されます。これは字幕が黒枠上に表示されるのを許可します。 + + + + &Add black borders on fullscreen + 全画面表示で黒枠を表示する(&A) + + + + one ini file + 1 つの ini ファイル + + + + multiple ini files + 複数の ini ファイル + + + + Method to store the file settings + ファイルの設定を格納する方法 + + + + This option allows to change the way the file settings would be stored. The following options are available: + このオプションはファイルの設定が格納される方法の変更を許可します。以下のオプションが利用可能です: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>1 つの ini ファイル</b>: すべての再生されるファイルの設定は単一の ini ファイル (%1) に保存されます + + + + The latter method could be faster if there is info for a lot of files. + 後者の方法は多くのファイルの情報がある場合に高速になることがあります。 + + + + &Store settings in + 設定を格納する場所(&S) + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>複数の ini ファイル</b>: 1 つの ini ファイルは再生されるファイルごとに使用されます。それらの ini ファイルはフォルダ %1 に保存されます + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + このオプションをチェックすると、SMPlayer は再び開いたときにファイルの最後の位置を記憶します。このオプションは通常のファイル (DVD、CD、URL... でない) でのみ動作します。 + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + チェックされている場合、直接描画をオンにします (すべてのコーデックとビデオ出力によってはサポートされていません)<br><b>警告:</b> OSD/SUB の破損を引き起こす可能性があります! + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + 再生チャンネルの数を要求します。MPlayer は指定されただけの数のチャンネルにオーディオをデコードするようデコーダーに要求します。次に要求が満たされるのはデコーダー次第です。これは通常 AC3 オーディオ (DVD のような) でビデオを再生するときのみ重要です。その場合は liba52 が既定でデコードして要求されたチャンネルの数にオーディオをダウンミックスします。<b>注意:</b> このオプションはコーデック (AC3 のみ)、フィルター (サラウンド) およびオーディオの出力ドライバー (少なくとも OSS) によって尊重されています。 + + + + PrefInput + + + Keyboard and mouse + キーボードとマウス + + + + None + なし + + + + &Keyboard + キーボード(&K) + + + + icon + icon + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + ここではすべてのショートカットを変更できます。それにはショートカット セルの上でダブル クリックまたは入力を開始します。また任意にその他の人または別のコンピューターで読み込みおよび共有するのに一覧を保存できます。 + + + + &Mouse + マウス(&M) + + + + Button functions: + ボタンの機能: + + + + Media seeking + メディアのシーク + + + + Volume control + ボリューム コントロール + + + + Zoom video + ビデオの拡大と縮小 + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + ここではすべてのショートカットを変更できます。それにはショートカット セルの上でダブル クリックまたは enter を押します。また任意にその他の人または別のコンピューターでの読み込みおよび共有するのに一覧を保存できます。 + + + + &Left click + 左クリック(&L) + + + + &Double click + ダブル クリック(&D) + + + + &Wheel function: + ホイール機能(&W): + + + + Shortcut editor + ショートカット エディター + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + この表は利用可能な動作のキー ショートカットの変更を許可します。<i>ショートカットの変更</i> ダイアログに入るにはアイテムでダブルクリックするか enter を押すか、<b>ショートカットの変更</b> ボタンを押します。ショートカットを変更する 2 つの方法があります: <b>キャプチャ</b> ボタンがオンの場合は次に動作に割り当てしたい新しいキーまたはキーの組み合わせを押します。<b>キャプチャ</b> ボタンがオフの場合は次にキーのフル ネームを入力できます。 + + + + Left click + 左クリック + + + + Select the action for left click on the mouse. + マウスの左クリックの動作を選択します。 + + + + Double click + ダブル クリック + + + + Select the action for double click on the mouse. + マウスのダブル クリックの動作を選択します。 + + + + Wheel function + ボタンの機能 + + + + Select the action for the mouse wheel. + マウス ホイールの動作を選択します。 + + + + Play + 再生 + + + + Pause + 一時停止 + + + + Stop + 停止 + + + + Fullscreen + 全画面表示 + + + + Compact + コンパクト + + + + Screenshot + スクリーンショット + + + + On top + 常に手前 + + + + Mute + ミュート + + + + Frame counter + フレーム カウンター + + + + Reset zoom + 拡大と縮小のリセット + + + + Exit fullscreen + 全画面表示の終了 + + + + Double size + 倍のサイズ + + + + Play / Pause + 再生 / 一時停止 + + + + Pause / Frame step + 一時停止 / コマ送り + + + + Playlist + プレイリスト + + + + Preferences + 環境設定 + + + + No function + 機能なし + + + + Change speed + 速度の変更 + + + + Normal speed + 通常の速度 + + + + Keyboard + キーボード + + + + Mouse + マウス + + + + Middle click + ミドル クリック + + + + Select the action for middle click on the mouse. + マウスのミドル クリックの動作を選択します。 + + + + M&iddle click + ミドル クリック(&I) + + + + X Button &1 + X ボタン 1(&1) + + + + X Button &2 + X ボタン 2(&2) + + + + Go backward (short) + 戻る (短) + + + + Go backward (medium) + 戻る (中) + + + + Go backward (long) + 戻る (長) + + + + Go forward (short) + 進む (短) + + + + Go forward (medium) + 進む (中) + + + + Go forward (long) + 進む (長) + + + + OSD - Next level + OSD - 次のレベル + + + + Show context menu + コンテキスト メニューの表示 + + + + &Right click + 右クリック(&R) + + + + Increase volume + 音量を上げる + + + + Decrease volume + 音量を下げる + + + + X Button 1 + X ボタン 1 + + + + Select the action for the X button 1. + X ボタン 1 の動作を選択します。 + + + + X Button 2 + X ボタン 2 + + + + Select the action for the X button 2. + X ボタン 2 の動作を選択します。 + + + + Show video equalizer + ビデオ イコライザーの表示 + + + + Show audio equalizer + オーディオ イコライザーの表示 + + + + Always on top + 常に手前に表示 + + + + Never on top + 手前に表示しない + + + + On top while playing + 再生中に手前に表示 + + + + PrefInterface + + + Interface + インターフェイス + + + + <Autodetect> + <自動検出> + + + + Default + 既定 + + + + Language + 言語 + + + + &Interface + インターフェイス(&I) + + + + Seeking + シーク + + + + Recent files + 最近使ったファイル + + + + Never + しない + + + + Whenever it's needed + 必要ならいつも + + + + Only after loading a new video + 新しいビデオの読み込み後のみ + + + + Here you can change the language of the application. + ここではアプリケーションの言語を変更できます。 + + + + Instances + インスタンス + + + + &Short jump + 短いジャンプ(&S) + + + + &Medium jump + 中ジャンプ(&M) + + + + &Long jump + 長いジャンプ(&L) + + + + Mouse &wheel jump + マウス ホイール ジャンプ(&W) + + + + &Use only one running instance of SMPlayer + 実行中の SMPlayer のインスタンスを 1 つのみ使用する(&U) + + + + Ma&x. items + アイテムの最大数(&X) + + + + St&yle: + スタイル(&Y): + + + + Ico&n set: + アイコン セット(&N): + + + + L&anguage: + 言語(&A): + + + + Main window + メイン ウィンドウ + + + + Auto&resize: + サイズの自動変更(&R): + + + + R&emember position and size + 位置とサイズを記憶する(&E) + + + + Default font: + 既定のフォント: + + + + &Change... + 変更(&C)... + + + + &Behaviour of time slider: + タイム スライダーの挙動(&B): + + + + Seek to position while dragging + ドラッグ中に位置へシークする + + + + Seek to position when released + 解放されたときに位置へシークする + + + + TextLabel + TextLabel + + + + &Seeking + シーク(&S) + + + + Ins&tances + 実行(&T) + + + + Autoresize + サイズの自動変更 + + + + The main window can be resized automatically. Select the option you prefer. + メイン ウィンドウは自動的にリサイズできます。お好みのオプションを選択します。 + + + + Remember position and size + 位置とサイズを記憶する + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + このオプションをチェックすると、メイン ウィンドウの位置とサイズは保存され再び SMPlayer を実行するときに復元されます。 + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + <b>開く->最近使ったファイル</b> サブメニューに表示されるアイテムの最大数を選択します。0 へ設定するとそのメニューはまったく表示されません。 + + + + Icon set + アイコン セット + + + + Select the icon set you prefer for the application. + アプリケーションのお好みのアイコン セットを選択します。 + + + + Style + スタイル + + + + Select the style you prefer for the application. + アプリケーションのお好みのスタイルを選択します。 + + + + Default font + 既定のフォント + + + + You can change here the application's font. + アプリケーションのフォントをここで変更できます。 + + + + Short jump + 短いジャンプ + + + + Select the time that should be go forward or backward when you choose the %1 action. + %1動作を選択するときに進むか戻る時間を選択します。 + + + + short jump + 短いジャンプ + + + + Medium jump + 中ジャンプ + + + + medium jump + 中ジャンプ + + + + Long jump + 長いジャンプ + + + + long jump + 長いジャンプ + + + + Mouse wheel jump + マウス ホイール ジャンプ + + + + Select the time that should be go forward or backward when you move the mouse wheel. + マウス ホイールを動かすときに進むか戻る時間を選択します。 + + + + Behaviour of time slider + タイム スライダーの挙動 + + + + Select what to do when dragging the time slider. + タイム スライダーのドラッグ時に何をするかを選択します。 + + + + Use only one running instance of SMPlayer + 実行中の SMPlayer のインスタンスを 1 つのみ使用する + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + その他のファイルを開くときにすでに実行中の SMPlayer のインスタンスを使用したい場合はこのオプションをチェックします。 + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer はその他のインスタンスからコマンドを受信するのにポートの聴取を必要とします。既定のものが別のアプリケーションによって使用されている場合はポートを変更できます。 + + + + Default GUI + デフォルト GUI + + + + Mini GUI + ミニ GUI + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + アプリケーションのお好みの GUI を選択します。現在 [デフォルト GUI] と [ミニ GUI] の 2 つがあります。<br>[<b>デフォルト GUI</b>] はツール バーとコントロール バーのある、伝統的な GUI を供給します。<b>[ミニ GUI]</b> は数個のボタンのあるツール バーとコントロール バーのない、よりシンプルな GUI を供給します。<br><b>注意:</b> このオプションは次の SMPlayer を実行する時間に影響します。 + + + + &GUI + GUI(&G) + + + + Automatic port + 自動ポート + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer はその他のインスタンスからコマンドを受信するのにポートの聴取を必要とします。このオプションを選択すると、ポートは自動的に選択されます。 + + + + Manual port + 手動ポート + + + + Port to listen + 聴取するポート + + + + &Automatic + 自動(&A) + + + + &Manual + 手動(&M) + + + + Floating control + フローティング コントロール + + + + Animated + アニメーション + + + + If this option is enabled, the floating control will appear with an animation. + このオプションが有効である場合、フローティング コントロールはアニメーション付きで表示されます。 + + + + Width + + + + + Specifies the width of the control (as a percentage). + コントロールの幅を指定します (パーセンテージ)。 + + + + Margin + 余白 + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + このオプションはフローティング コントロールが画面の下から離れるピクセルの数を設定します。オーバースキャンがコントロールが可視になるのを防止する可能性があるので、画面が TV であるときに有用です。 + + + + Display in compact mode too + コンパクト モードでも表示する + + + + If this option is enabled, the floating control will appear in compact mode too. Warning: the floating control has not been designed for compact mode and it might not work properly. + このオプションが有効である場合、フローティング コントロールはコンパクト モードでも表示されます。警告: フローティング コントロールはコンパクト モード用にデザインされておらず適切に動作しない可能性があります。 + + + + Bypass window manager + ウィンドウ マネージャーを通過する + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + このオプションがチェックされている場合、コントロールはウィンドウ マネージャーを通過して表示されます。フローティング コントロールがお使いのウィンドウ マネージャーでよく動作しない場合はこのオプションを無効にします。 + + + + &Floating control + フローティング コントロール(&F) + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + フローティング コントロールは全画面モードでマウスが画面の下へ動かされると表示されます。 + + + + &Animated + アニメーション(&A) + + + + &Width: + 幅(&W): + + + + 0 + 0 + + + + &Margin: + 余白(&M): + + + + Display in &compact mode too + コンパクト モードでも表示する(&C) + + + + &Bypass window manager + ウィンドウ マネージャーを通過する(&B) + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + このオプションが有効である場合、フローティング コントロールはコンパクト モードでも表示されます。<b>警告:</b> フローティング コントロールはコンパクト モード用にデザインされておらず適切に動作しない可能性があります。 + + + + Mpc GUI + Mpc GUI + + + + PrefPerformance + + + Performance + パフォーマンス + + + + Priority + 優先度 + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Windows 下で利用可能な所定の優先度に従って mplayer のプロセス優先度を設定します。<br><b>警告:</b> リアルタイム優先度の使用はシステム ロックアップを引き起こすことがあります。 + + + + Cache + キャッシュ + + + + Allow frame drop + フレーム ドロップを許可する + + + + Skip displaying some frames to maintain A/V sync on slow systems. + いくつかのフレームの表示をスキップして遅いシステムでの A/V 同期を維持させます。 + + + + Allow hard frame drop + ハード フレーム ドロップを許可する + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + より強烈なフレーム ドロップです (デコードが破損します)。イメージの歪曲の原因となります! + + + + Audio/video auto synchronization + オーディオ/ビデオの自動同期化 + + + + Gradually adjusts the A/V sync based on audio delay measurements. + 徐々にオーディオの遅延測定を基準にして A/V 同期を調整します。 + + + + &Performance + パフォーマンス(&P) + + + + Select the priority for the MPlayer process. + MPlayer プロセスの優先度を選択します。 + + + + realtime + realtime + + + + high + high + + + + abovenormal + abovenormal + + + + normal + normal + + + + belownormal + belownormal + + + + idle + idle + + + + KB + KB + + + + Setting a cache may improve performance on slow media + キャッシュの設定は遅いメディアでのパフォーマンスを向上させる可能性があります + + + + Synchronization + 同期化 + + + + Fast audio track switching + オーディオ トラックの高速切り替え + + + + Fast seek to chapters in dvds + dvd のチャプターへ高速シークする + + + + Priorit&y: + 優先度(&Y): + + + + &Allow frame drop + フレーム ドロップを許可する(&A) + + + + Allow &hard frame drop (can lead to image distortion) + ハード フレーム ドロップを許可する (イメージの歪曲の原因となることがあります)(&H) + + + + Audio/&video auto synchronization + オーディオ/ビデオの自動同期化(&V) + + + + Fact&or: + 要因(&O): + + + + &Fast audio track switching + オーディオ トラックの高速切り替え(&F) + + + + Fast &seek to chapters in dvds + dvd のチャプターへ高速シークする(&S) + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + チェックされている場合、チャプターへのシークに最速の方法を試行しますがいくつかのディスクでは動作しない可能性があります。 + + + + Skip loop filter + ループ フィルターをスキップする + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + 可能な値:<br> <b>はい</b>: オーディオ トラックの切り替えに最速の方法を試行します (いくつかのフォーマットでは動作しない可能性があります).<br> <b>いいえ</b>: MPlayer プロセスはオーディオ トラックの切り替え時にいつも再起動されます。<br> <b>自動</b>: SMPlayer は MPlayer バージョンによってどうするかを決定します。 + + + + Cache for files + ファイルのキャッシュ + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + このオプションはファイルのプリキャッシュ時に使用するメモリ (k バイト) を指定します。 + + + + Cache for streams + ストリームのキャッシュ + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + このオプションは URL のプリキャッシュ時に使用するメモリ (k バイト) を指定します。 + + + + Cache for DVDs + DVD のキャッシュ + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + このオプションは DVD のプリキャッシュ時に使用するメモリ (k バイト) を指定します。<br><b>警告:</b> シークは DVD のキャッシュの使用時に適切に動作しない可能性があります (チャプターの切り替えを含む)。 + + + + &Cache + キャッシュ(&C) + + + + Cache for &DVDs: + DVD のキャッシュ(&D): + + + + Cache for &local files: + ローカル ファイルのキャッシュ(&L): + + + + Cache for &streams: + ストリームのキャッシュ(&S): + + + + Enabled + 有効 + + + + Skip (always) + スキップする (常に) + + + + Skip only on HD videos + HD ビデオでのみスキップする + + + + Loop &filter + ループ フィルター(&F) + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + このオプションは H.264 のデコード中のループ フィルター (別名ブロック除去) のスキップを許可します。フィルターされたフレームは依存するフレームのデコードの参照として使用されると推量されるのでこれには MPEG-2 ビデオなどでブロック解除をしないより品質に悪い影響があります。しかし少なくとも高ビットレート HDTV にはこれは可視の品質低下なしで大きな高速化を供給します。 + + + + Possible values: + 可能な値: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>有効</b>: ループ フィルターはスキップされません + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>スキップする (常に)</b>: ループ フィルターはビデオの解像度の問題なしでスキップされます + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>HD ビデオでのみスキップする</b>: ループ フィルターは高さが %1 以上のビデオでのみスキップされます。 + + + + Cache for audio CDs + オーディオ CD のキャッシュ + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + このオプションはオーディオ CD のプリキャッシュ時に使用するメモリ (k バイト) を指定します。 + + + + Cache for &audio CDs: + オーディオ CD のキャッシュ(&A): + + + + Cache for VCDs + VCD のキャッシュ + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + このオプションは VCD のプリキャッシュ時に使用するメモリ (k バイト) を指定します。 + + + + Cache for &VCDs: + VCD のキャッシュ(&V): + + + + Threads for decoding + デコードのスレッド + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + デコードに使用するスレッドの数を設定します。MPEG-1/2 および H.264 専用です + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + デコードのスレッド (MPEG-1/2 および H.264 のみ)(&T): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + Windows 下で利用可能な所定の優先度に従って mplayer のプロセス優先度を設定します。<br><b>警告:</b> リアルタイム優先度の使用はシステム ロックアップを引き起こすことがあります。 + + + + PrefPlaylist + + + Playlist + プレイリスト + + + + Automatically add files to playlist + 自動的にファイルをプレイリストに追加する + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + このオプションが有効である場合、毎回ファイルが開かれるごとに、SMPlayer はまずプレイリストをクリアして次にファイルを追加します。DVD、CD、および VCD の場合は、ディスクのすべてのタイトルがプレイリストに追加されます。 + + + + Add consecutive files + 連番ファイルを追加する + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + このオプションが有効である場合、SMPlayer は連番ファイル (例: video_1.avi、video_2.avi...) を検索し見つかった場合、プレイリストに追加されます。 + + + + &Playlist + プレイリスト(&P) + + + + &Automatically add files to playlist + 自動的にファイルをプレイリストに追加する(&A) + + + + Add &consecutive files + 連番ファイルを追加する(&C) + + + + PrefSubtitles + + + Subtitles + 字幕 + + + + Choose a ttf file + ttf ファイルの選択 + + + + Truetype Fonts + Truetype フォント + + + + Subtitle position + 字幕の位置 + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + このオプションはビデオ ウィンドウ上の字幕の位置を指定します。<i>100</i> は最下を意味し、<i>0</i> は最上を意味します。 + + + + &Subtitles + 字幕(&S) + + + + Autoload + 自動読み込み + + + + Select first available subtitle + 利用可能な字幕をまず選択する + + + + Same name as movie + ムービーと同じ名前 + + + + All subs containing movie name + ムービーの名前を含むすべての字幕 + + + + All subs in directory + ディレクトリ内のすべての字幕 + + + + Position + 位置 + + + + 0 + 0 + + + + Top + 先頭へ + + + + Bottom + 末尾へ + + + + Include subtitles on screenshots + スクリーンショットに字幕を含める + + + + Font + フォント + + + + Select the font which will be used for subtitles (and OSD): + 字幕 (と OSD) に使用するフォントを選択します: + + + + Size + サイズ + + + + No autoscale + オートスケールなし + + + + Proportional to movie height + ムービーの高さに比例する + + + + Proportional to movie width + ムービーの幅に比例する + + + + Proportional to movie diagonal + ムービーの対角線に比例する + + + + Au&toload subtitles files (*.srt, *.sub...): + 字幕ファイル (*.srt、*.sub...) を自動読み込みする(&T): + + + + S&elect first available subtitle + 最初に利用可能な字幕を選択する(&E) + + + + &Default subtitle encoding: + 既定の字幕エンコード(&D): + + + + Default &position of the subtitles on screen + 既定の画面上の字幕の位置(&P) + + + + &Include subtitles on screenshots + スクリーンショットに字幕を含める(&I) + + + + &TTF font: + TTF フォント(&T): + + + + S&ystem font: + システム フォント(&Y): + + + + A&utoscale: + オートスケール(&U): + + + + Default subtitle encoding + 既定の字幕エンコード + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + このオプションがチェックされている場合、字幕はスクリーンショットに表示されます。注意: ときどきいくつかのトラブルを引き起こします。 + + + + TTF font + TTF フォント + + + + System font + システム フォント + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + ここでは字幕と OSD に使用されるシステム フォントを選択できます。<b>注意:</b> fontconfig サポートのある MPlayer を必要とします。 + + + + Autoscale + オートスケール + + + + Text color + テキストの色 + + + + Select the color for the text of the subtitles. + 字幕のテキストの色を選択します。 + + + + Border color + 枠の色 + + + + Select the color for the border of the subtitles. + 字幕の枠の色を選択します。 + + + + Select the subtitle autoload method. + 字幕の自動読み込みの方法を選択します。 + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + 1 つより多くの利用可能な字幕トラックがある場合、それらの 1 つが自動的に選択され、通常は最初の 1 つですが、それらの 1 つがユーザーの優先言語に一致する場合はその 1 つが代わりに使用されます。 + + + + Select the subtitle autoscaling method. + 字幕のオートスケールの方法を選択します。 + + + + Select the encoding which will be used for subtitle files by default. + 既定で字幕ファイルに使用されるエンコードを選択します。 + + + + Try to autodetect for this language + この言語の自動検出を試行する + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + このオプションがオンだと、字幕のエンコードは与えられた言語の自動検出に試行されます。自動検出が失敗する場合は既定のエンコードに戻ります。このオプションは ENCA サポートとコンパイルされた MPlayer を必要とします。 + + + + Subtitle language + 字幕の言語 + + + + Select the language for which you want the encoding to be guessed automatically. + 自動的に推測させたいエンコードの言語を選択します。 + + + + Encoding + エンコード + + + + Try to a&utodetect for this language: + この言語の自動検出を試行する(&U): + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + ここでは字幕に使用される ttf フォントを選択できます。通常 %1 でたくさんの ttf フォントが見つかります + + + + Outline + アウトライン + + + + Select the font for the subtitles. + 字幕のフォントを選択します。 + + + + The size in pixels. + ピクセルでのサイズです。 + + + + Bold + 太字 + + + + If checked, the text will be displayed in <b>bold</b>. + チェックされている場合、テキストは<b>太字</b>で表示されます。 + + + + Italic + 斜体 + + + + If checked, the text will be displayed in <i>italic</i>. + チェックされている場合、テキストは<i>斜体</i>で表示されます。 + + + + Left margin + 左の余白 + + + + Specifies the left margin in pixels. + ピクセルで左の余白を指定します。 + + + + Right margin + 右の余白 + + + + Specifies the right margin in pixels. + ピクセルで右の余白を指定します。 + + + + Vertical margin + 垂直の余白 + + + + Specifies the vertical margin in pixels. + ピクセルで垂直の余白を指定します。 + + + + Horizontal alignment + 水平の配置 + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + 水平の配置を指定します。可能な値は左、中央および右です。 + + + + Vertical alignment + 垂直の配置 + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + 垂直の配置を指定します。可能な値: 下、中央および上。 + + + + Border style + 枠のスタイル + + + + Specifies the border style. Possible values: outline and opaque box. + 枠のスタイルを指定します。可能な値: アウトラインおよび不透明ボックス。 + + + + Shadow + + + + + Si&ze: + サイズ(&Z): + + + + Bol&d + 太字(&D) + + + + &Italic + 斜体(&I) + + + + Colors + + + + + &Text: + テキスト(&T): + + + + &Border: + 枠(&B): + + + + Margins + 余白 + + + + L&eft: + 左(&E): + + + + &Right: + 右(&R): + + + + Verti&cal: + 垂直(&C): + + + + Alignment + 配置 + + + + &Horizontal: + 水平(&H): + + + + &Vertical: + 垂直(&V): + + + + Border st&yle: + 枠のスタイル(&Y): + + + + &Outline: + アウトライン(&O): + + + + Shado&w: + 影(&W): + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + 以下のオプションは非スタイル化済みの字幕 (srt、sub...) に使用されるスタイルの定義を許可します。 + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + 中央 + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + + + + + Middle + vertical alignment + 中央 + + + + Top + vertical alignment + + + + + Outline + border style + アウトライン + + + + Opaque box + border style + 不透明ボックス + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + 枠のスタイルが<i>アウトライン</i>へ設定されている場合、このオプションはピクセルでテキストの周りのアウトラインの幅を指定します。 + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + 枠のスタイルが<i>アウトライン</i>へ設定されている場合、このオプションはピクセルでテキストの後ろのドロップ シャドウの深さを指定します。 + + + + Enable normal subtitles + 通常の字幕を有効にする + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + 通常の/伝統的な字幕を選択するにはこのボタンをクリックします。この類の字幕は白い字幕のみ表示できます。 + + + + Enable SSA/ASS subtitles + SSA/ASS 字幕を有効にする + + + + Normal subtitles + 通常の字幕 + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + このオプションは現在のビデオの字幕のサイズを変更しません。そうするには、字幕メニューからオプション <i>サイズ +</i> および <i>サイズ -</i> を使用します。 + + + + Default scale + 既定のスケール + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + このオプションは新しく開かれるファイルに使用される通常の字幕の既定のフォント スケールを指定します。 + + + + SSA/ASS subtitles + SSA/ASS 字幕 + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + このオプションは新しく開かれるファイルに使用される SSA/ASS 字幕の既定のフォント スケールを指定します。 + + + + Line spacing + 行間 + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + これは複数の行の区切りに使用される間を指定します。負の値にできます。 + + + + &Font and colors + フォントと色(&F) + + + + Enable &normal subtitles + 通常の字幕を有効にする(&N) + + + + Enable SSA/&ASS subtitles + SSA/ASS 字幕を有効にする(&A) + + + + Default s&cale: + 既定のスケール(&C): + + + + Defa&ult scale: + 既定のスケール(&U): + + + + &Line spacing: + 行間(&L): + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + 新しい SSA/ASS ライブラリを有効にするにはこのボタンをクリックします。これは複数の色、フォント... のある字幕の表示を許可します。 + + + + Freetype support + Freetype サポート + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + 通常はこのオプションを無効にしません。お使いの MPlayer が freetype サポートなしでコンパイルされている場合のみしてください。<b>このオプションを無効にすると字幕が全く動作しなくなります!</b> + + + + Freet&ype support + Freetype サポート(&Y) + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + このオプションがチェックされている場合、字幕はスクリーンショットに表示されます。<b>注意:</b> ときどきいくつかのトラブルを引き起こします。 + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - ヘルプ + + + + OK + OK + + + + Cancel + キャンセル + + + + Apply + 適用 + + + + Help + ヘルプ + + + + SMPlayer - Preferences + SMPlayer - 環境設定 + + + + QObject + + + will show this message and then will exit. + このメッセージを表示して次に終了します。 + + + + the main window will be closed when the file/playlist finishes. + メイン ウィンドウはファイル/プレイリストの完了時に閉じられます。 + + + + This is SMPlayer v. %1 running on %2 + これは %2 で実行中の SMPlayer v. %1 です + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + 別の実行中のインスタンスへの接続と指定された動作の送信を試行します。例: -send-action pause 残りのオプションは (あれば) 無視されてアプリケーションは終了します。成功時には 0 または 失敗時には -1 を返します。 + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + [動作の一覧] はスペースで区切られる動作の一覧です。動作は入力したのと同じ順序でファイル (あれば) の読み込み直後に実行されます。チェック可能な動作にはパラメーターとして true または false を渡すことができます。例: -actions "fullscreen compact true"。引用符は 1 つより多くの動作を渡す場合に必要です。 + + + + media + メディア + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + 別の実行中のインスタンスがある場合、メディアはそのインスタンスのプレイリストに追加されます。その他のインスタンスがない場合、このオプションは無視されてファイルは新しいインスタンスで開かれます。 + + + + the main window won't be closed when the file/playlist finishes. + メイン ウィンドウはファイル/プレイリストの完了時に閉じられません。 + + + + the video will be played in fullscreen mode. + ビデオは全画面モードで再生されます。 + + + + the video will be played in window mode. + ビデオはウィンドウ モードで再生されます。 + + + + Enqueue in SMPlayer + SMPlayer でエンキュー + + + + opens the mini gui instead of the default one. + 既定のものの代わりにミニ gui を開きます。 + + + + Restores the old associations and cleans up the registry. + 古い関連付けを復元してレジストリをクリーンアップします。 + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'メディア' はあらゆる SMPlayer が開けるファイルです。ローカル ファイル、DVD (例: dvd://1)、インターネット ストリーム (例: mms://....) または m3u または pls フォーマットのローカル プレイリストにできます。 -playlist オプションが使用されている場合、それは SMPlayer ではなく、MPlayer がプレイリストをハンドルするように、SMPlayer が MPlayer へ -playlist オプションを渡すことを意味します。 + + + + Usage: + 使用法: + + + + directory + ディレクトリ + + + + action_name + 動作名 + + + + action_list + 動作の一覧 + + + + opens the default gui. + デフォルト gui を開きます。 + + + + subtitle_file + subtitle_file + + + + specifies the subtitle file to be loaded for the first video. + 最初のビデオに読み込まれる字幕ファイルを指定します。 + + + + %1 second(s) + + %1 秒 + + + + + %1 minute(s) + + %1 分 + + + + + %1 and %2 + %1 と %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + smplayer が構成ファイル (smplayer.ini、smplayer_files.ini...) を格納するディレクトリを指定します + + + + disabled + aspect_ratio + 無効 + + + + auto + aspect_ratio + 自動 + + + + unknown + aspect_ratio + 不明 + + + + opens the mpc gui. + mpc gui を開きます。 + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + ZIP/UNZIP API エラー %1 + + + + SeekWidget + + + icon + icon + + + + label + label + + + + ShortcutGetter + + + Modify shortcut + ショートカットの変更 + + + + Clear + クリア + + + + Press the key combination you want to assign + 割り当てたいキーの組み合わせを押します + + + + Capture + キャプチャ + + + + Capture keystrokes + キーストロークのキャプチャ + + + + SubChooserDialog + + + Subtitle selection + 字幕の選択 + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + このアーカイブは 1 個以上の字幕ファイルを含みます。展開したいものを選択してください。 + + + + Select All + すべて選択 + + + + Select None + 選択しない + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - シーク + + + + &Jump to: + ジャンプ先(&J): + + + + TristateCombo + + + Auto + 自動 + + + + Yes + はい + + + + No + いいえ + + + + VideoEqualizer + + + Contrast + コントラスト + + + + Brightness + 明るさ + + + + Hue + 色合い + + + + Saturation + 鮮やかさ + + + + Gamma + ガンマ + + + + &Reset + リセット(&R) + + + + &Set as default values + 既定値として設定(&S) + + + + Use the current values as default values for new videos. + 新しいビデオの既定値として現在の値を使用します。 + + + + Set all controls to zero. + すべてのコントロールを 0 に設定します。 + + + + Video Equalizer + ビデオ イコライザー + + + + Information + 情報 + + + + The current values have been stored to be used as default. + 現在の値は既定としての使用に格納されています。 + + + + VideoPreview + + + Video preview + ビデオのプレビュー + + + + Cancel + キャンセル + + + + Generated by SMPlayer + Generated by SMPlayer + + + + Creating thumbnails... + サムネイルを作成しています... + + + + File: %1 + ファイル: %1 + + + + Size: %1 MB + サイズ: %1 MB + + + + Resolution: %1 x %2 + 解像度: %1 x %2 + + + + Length: %1 + 長さ: %1 + + + + Save file + ファイルの保存 + + + + Images (*.png *.jpg) + イメージ (*.png *.jpg) + + + + Error saving file + ファイルの保存エラー + + + + The file couldn't be saved + ファイルは保存できませんでした + + + + Error + エラー + + + + The following error has occurred while creating the thumbnails: + サムネイルの作成中に以下のエラーが発生しました: + + + + The temporary directory (%1) can't be created + 一時ディレクトリ (%1) は作成できません + + + + The mplayer process didn't run + mplayer プロセスが実行しませんでした + + + + Resolution: %1x%2 + 解像度: %1x%2 + + + + Video format: %1 + ビデオのフォーマット: %1 + + + + Frames per second: %1 + フレーム パー セコンド: %1 + + + + Aspect ratio: %1 + アスペクト比: %1 + + + + Video bitrate: %1 kbps + ビデオのビットレート: %1 kbps + + + + Audio bitrate: %1 kbps + オーディオのビットレート: %1 kbps + + + + Audio rate: %1 Hz + オーディオ レート: %1 Hz + + + + The file %1 can't be loaded + ファイル %1 は読み込めません + + + + No filename + ファイル名なし + + + + The mplayer process didn't start while trying to get info about the video + mplayer プロセスはビデオについての情報の取得の試行中に起動しませんでした + + + + The length of the video is 0 + ビデオの長さが 0 です + + + + The file %1 doesn't exist + ファイル %1 が存在しません + + + + Images + イメージ + + + + No info + 情報なし + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + ビデオのビットレート: %1 + + + + Audio bitrate: %1 + オーディオのビットレート: %1 + + + + Audio rate: %1 + オーディオ レート: %1 + + + + VideoPreviewConfigDialog + + + Default + 既定 + + + + Video Preview + ビデオのプレビュー + + + + &File: + ファイル(&F): + + + + &Columns: + 列(&C): + + + + &Rows: + 行(&R): + + + + Add playing time to thumbnails + 再生時間をサムネイルに追加する + + + + &Aspect ratio: + アスペクト比(&A): + + + + &Seconds to skip at the beginnning: + 最初にスキップする秒(&S): + + + + &Maximum width: + 最大幅(&M): + + + + The preview will be created for the video you specify here. + プレビューはここで指定するビデオ用に作成されます。 + + + + The thumbnails will be arranged on a table. + サムネイルは表に配置されます。 + + + + This option specifies the number of columns of the table. + このオプションは表の列の数を指定します。 + + + + This option specifies the number of rows of the table. + このオプションは表の行の数を指定します。 + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + このオプションをチェックすると、再生時間はそれぞれのサムネイルの下に表示されます。 + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + ビデオのアスペクト比が間違っている場合、ここで異なったものを指定できます。 + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + 通常最初のフレームは黒なので、ビデオの最初の数秒をスキップするといいかもしれません。このオプションは何秒スキップされるかの指定を許可します。 + + + + This option specifies the maximum width in pixels that the generated preview image will have. + このオプションは生成されるプレビュー イメージの最大幅をピクセルで指定します。 + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + いくつかのフレームはプレビューを作成するためにビデオから抽出されます。ここでは抽出されるフレームのイメージ フォーマットを選択できます。PNG が高品質でしょう。 + + + + Add playing &time to thumbnails + 再生時間をサムネイルに追加する(&T) + + + + &Extract frames as + フォーマット(&E) + + + + Enter here the DVD device or a folder with a DVD image. + DVD デバイスか DVD イメージのあるフォルダーをここに入力します。 + + + + &DVD device: + DVD デバイス(&D): + + + + VolumeSliderAction + + + Volume + 音量 + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_ka.ts b/plugins/smplayer_plugin/translations/smplayer_ka.ts new file mode 100644 index 000000000..4af2aaf56 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_ka.ts @@ -0,0 +1,7207 @@ + + + + About + + + Version: %1 + ვერსია: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + ეს პროგრამა წარმოადგენს თავისუფალ პროგრამულ უზრუნველყოფას; თქვენ შეგიძლიათ გაავრცელოთ ის და/ან შეცვალოთ ის Free Software Foundation ფონდის მიერ გამოქვეყნებული GNU GPL ლიცენზიაში გათვალისწინებული წესების მიხედვით; როგორც ლიცენზიის მეორე ვერსიით, ასევე (თქვენი გადაწყვეტილებით) ნებისმიერი უფრო ახალი ვერსიით. + + + + The following people have contributed with translations: + + + + + German + გერმანული + + + + Slovak + სლოვაკური + + + + Italian + იტალიური + + + + French + ფრანგული + + + + %1, %2 and %3 + + + + + Simplified-Chinese + გამარტივებული ჩინური + + + + Russian + რუსული + + + + %1 and %2 + + + + + Hungarian + უნგრული + + + + Polish + პოლონური + + + + Japanese + იაპონური + + + + Dutch + ჰოლანდიური + + + + Ukrainian + უკრაინული + + + + Portuguese - Brazil + + + + + Georgian + ქართული + + + + Czech + ჩეხური + + + + Bulgarian + + + + + Turkish + თურქული + + + + Swedish + + + + + Serbian + + + + + Traditional Chinese + + + + + Romanian + + + + + Portuguese - Portugal + + + + + Greek + + + + + Finnish + + + + + <b>%1</b>: %2 + + + + + <b>%1</b> (%2) + + + + + About SMPlayer + SMPlayer-ის შესახებ + + + + &Info + + + + + icon + + + + + &Contributions + + + + + &Translators + + + + + &License + + + + + Visit our web for updates: + + + + + Get help in our forum: + + + + + You can support SMPlayer by making a donation. + + + + + More info + + + + + Korean + + + + + Macedonian + + + + + Basque + + + + + Using MPlayer %1 + + + + + Catalan + + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + არაბული + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + დასახელება + + + + Description + + + + + Shortcut + + + + + &Save + შენა&ხვა + + + + &Load + ჩა&ტვირთვა + + + + Key files + + + + + Choose a filename + აირჩიეთ ფაილის სახელი + + + + Confirm overwrite? + დავადასტუროთ შეცვლა? + + + + The file %1 already exists. +Do you want to overwrite? + ფაილი %1 უკვე არსებობს. +გსურთ მისი შეცვლა? + + + + Choose a file + აირჩიეთ ფაილი + + + + Error + + + + + The file couldn't be saved + + + + + The file couldn't be loaded + + + + + &Change shortcut... + + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + &საწყისი პარამეტრები + + + + &Set as default values + ნაგულის&ხმებად შენახვა + + + + Use the current values as default values for new videos. + მიმდინარე მნიშვნელობების ახალი ვიფდეოებისთვის გამოყენება. + + + + Set all controls to zero. + ყველაფრის ნორმალიზება. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + &File... + &ფაილი... + + + + D&irectory... + დ&ირექტორია... + + + + &Playlist... + რე&პერტუარი... + + + + &DVD from drive + &DVD ამძრავიდან + + + + D&VD from folder... + D&VD დასტიდან... + + + + &URL... + &URL... + + + + P&lay + და&კვრა + + + + &Pause + &პაუზა + + + + &Stop + &გაჩერება + + + + &Frame step + კადრული ბი&ჯი + + + + &Repeat + გამეო&რება + + + + &Normal speed + &ნორმალური სიჩქარე + + + + &Halve speed + ნა&ხევარი სიჩქარე + + + + &Double speed + &ორმაგი სიჩქარე + + + + Speed &-10% + სიჩქარე &-10% + + + + Speed &+10% + სიჩქარე &+10% + + + + Sp&eed + სი&ჩქარე + + + + &Fullscreen + მთელს ეკრან&ზე + + + + &Compact mode + &კომპაქტური რეჟიმი + + + + &Equalizer + &ეკვალაიზერი + + + + &Screenshot + ეკრანი&ს ანაბეჭდი + + + + S&tay on top + &ყოველთვის ზემოდან + + + + &Postprocessing + &შემდგომი დამუშავება + + + + &Autodetect phase + ფაზის &ავტოამოცნობა + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + &ხმაურის დამატება + + + + F&ilters + ფ&ილტრები + + + + &Mute + გა&ჩუმება + + + + Volume &- + ხმა &- + + + + Volume &+ + ხმა &+ + + + + &Delay - + &დაყოვნება - + + + + D&elay + + და&ყოვნება + + + + + &Extrastereo + &ექსტრასტერეო + + + + &Karaoke + &კარაოკე + + + + &Filters + &ფილტრები + + + + &Load... + ჩა&ტვირთვა... + + + + Delay &- + დაყოვნება &- + + + + Delay &+ + დაყოვნება &+ + + + + &Up + &ზევით + + + + &Down + &ქვევით + + + + &Playlist + რე&პერტუარი + + + + &Show frame counter + კადრების მ&თვლელის ჩვენება + + + + P&references + პა&რამეტრები + + + + &View logs + &ჟურნალების ჩვენება + + + + About &Qt + &Qt-ს შესახებ + + + + About &SMPlayer + &SMPlayer-ის შესახებ + + + + &Open + &გახსნა + + + + &Play + და&კვრა + + + + &Video + &ვიდეო + + + + &Audio + &აუდიო + + + + &Subtitles + &სუბტიტრები + + + + &Browse + &ნუსხა + + + + Op&tions + პარამე&ტრები + + + + &Help + და&ხმარება + + + + &Recent files + &წინა ფაილები + + + + &Clear + &გასუფთავება + + + + Si&ze + &ზომა + + + + &Aspect ratio + &ფარდობა + + + + &Deinterlace + &დეინტერლაცია + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 -> 16:9-&ზე + + + + &None + &არაა + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + სწრფივი &შერევა + + + + &Channels + არ&ხები + + + + &Stereo mode + &სტერეორეჟიმი + + + + &Stereo + &სტერეო + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Left channel + მარ&ცხენა არცი + + + + &Right channel + მარ&ჯვენა არხი + + + + &Select + ა&რჩევა + + + + &Title + &სათაური + + + + &Chapter + &თავი + + + + &Angle + &კუთხე + + + + &OSD + &OSD + + + + &Disabled + გათი&შულია + + + + &Seek bar + გადა&სვლის ზოლი + + + + &Time + &დრო + + + + Time + T&otal time + დრო + &ჯამური დრო + + + + SMPlayer - mplayer log + SMPlayer - mplayer-ის ჟურნალი + + + + SMPlayer - smplayer log + SMPlayer - smplayer-ის ჟურნალი + + + + <empty> + <ცარიელია> + + + + Video + ვიდეო + + + + Audio + აუდიო + + + + Playlists + რეპერტუარები + + + + All files + ყველა ფაილი + + + + Choose a file + აირჩიეთ ფაილი + + + + SMPlayer - Information + SMPlayer - ინფორმაცია + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD ამძრავები ჯერ არ არის გამართული.(new line)კონფიგურაციის დიალოგი ახლა გამოჩნდება, შეგიძლიათ გამართოთ ისინი. + + + + Choose a directory + აირჩიეთ დასტა + + + + Subtitles + სუბტიტრები + + + + About Qt + Qt-ს შესახებ + + + + Playing %1 + ვუკრავ %1-ს + + + + Pause + პაუზა + + + + Stop + შეჩერება + + + + Play / Pause + დაკვრა / პაუზა + + + + Pause / Frame step + პაუზა / კადრული ბიჯი + + + + U&nload + &გამოტვირთვა + + + + V&CD + + + + + C&lose + + + + + View &info and properties... + + + + + Zoom &- + + + + + Zoom &+ + + + + + &Reset + &საწყისი პარამეტრები + + + + Move &left + + + + + Move &right + + + + + Move &up + &ზევით აწევა + + + + Move &down + &ქვევით ჩაწევა + + + + &Pan && scan + + + + + &Previous line in subtitles + + + + + N&ext line in subtitles + + + + + -%1 + + + + + +%1 + + + + + Dec volume (2) + + + + + Inc volume (2) + + + + + Exit fullscreen + + + + + OSD - Next level + + + + + Dec contrast + + + + + Inc contrast + + + + + Dec brightness + + + + + Inc brightness + + + + + Dec hue + + + + + Inc hue + + + + + Dec saturation + + + + + Dec gamma + + + + + Next audio + + + + + Next subtitle + + + + + Next chapter + + + + + Previous chapter + + + + + Inc saturation + + + + + Inc gamma + + + + + &Load external file... + + + + + &Kerndeint + + + + + &Yadif (normal) + + + + + Y&adif (double framerate) + + + + + &Next + &შემდეგი + + + + Pre&vious + &წინა + + + + Volume &normalization + + + + + &Audio CD + + + + + Denoise nor&mal + + + + + Denoise &soft + + + + + Denoise o&ff + + + + + Use SSA/&ASS library + + + + + Flip i&mage + + + + + &Toggle double size + + + + + S&ize - + + + + + Si&ze + + + + + + Add &black borders + + + + + Soft&ware scaling + + + + + &FAQ + + + + + Visualize &motion vectors + + + + + &Command line options + + + + + SMPlayer command line options + + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &ჩანაწერი + + + + &Track + audio + &ჩანაწერი + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + + + + + S&how icon in system tray + + + + + &Hide + + + + + &Restore + + + + + &Quit + + + + + Playlist + რეპერტუარი + + + + Core + + + Brightness: %1 + სიკაშკაშე: %1 + + + + Contrast: %1 + კონტრასტი: %1 + + + + Gamma: %1 + გამა: %1 + + + + Hue: %1 + ტონი: %1 + + + + Saturation: %1 + ინტენსივობა: %1 + + + + Volume: %1 + ხმა: %1 + + + + Zoom: %1 + + + + + Font scale: %1 + + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + მოგესალმებათ SMPlayer + + + + Audio + აუდიო + + + + Subtitle + სუბტიტრები + + + + &Main toolbar + &ძირითადი პანელი + + + + &Language toolbar + ენის პა&ნელი + + + + &Toolbars + &ინსრუმენტთა პანელები + + + + EqSlider + + + icon + ხატულა + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + + + + + Error + + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + + + + + &Information + + + + + &Demuxer + &დემულტიპლექსორი + + + + &Select the demuxer that will be used for this file: + აირჩიეთ ამ ფაილის დემულტიპლექ&სორი: + + + + &Reset + &საწყისი პარამეტრები + + + + &Video codec + &ვიდეო კოდეკი + + + + &Select the video codec: + აირ&ჩიეთ ვიდეო კოდეკი: + + + + A&udio codec + ა&უდიო კოდეკი + + + + &Select the audio codec: + აირჩიეთ აუდიო &კოდეკი: + + + + &MPlayer options + &MPlayer-ის პარამეტრები + + + + Additional Options for MPlayer + + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + + &Options: + &პარამეტრები: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + აგრეთქე შეგიძლიათ დამატებითი ვიდეოფილრების მითითება. +გამოყავით ისინი "," სიმბოლოს საშუალებით. არ გამოტოვოთ ადგილი! +მაგალითი: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + ვ&იდეოფილტრები: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + და ბოლოს - აუდიოფილრტრები. იგივე წესით როგორც ვიდეოფილრები. +მაგალითი: resample=44100:0:0,volnorm + + + + Audio &filters: + აუდიო&ფილტრები: + + + + OK + + + + + Cancel + + + + + Apply + + + + + FindSubtitlesWindow + + + Language + + + + + Name + დასახელება + + + + Format + + + + + Files + + + + + Date + + + + + Uploaded by + + + + + All + + + + + Close + + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + შეცდომა ფაილის შენახვისას + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + ძირითადი + + + + Size + ზომა + + + + %1 KB (%2 MB) + %1 კბ (%2 მბ) + + + + URL + URL + + + + Length + ხანგრძლივობა + + + + Demuxer + დემულტიპლექსორი + + + + Name + დასახელება + + + + Artist + შემსრულებელი + + + + Author + ავტორი + + + + Album + ალბომი + + + + Genre + ჟანრი + + + + Date + თარიღი + + + + Track + ჩანაწერი + + + + Copyright + საავტორო უფლებები + + + + Comment + კომენტარი + + + + Software + პროგრამა + + + + Clip info + ინფორმაცია - კლიპი + + + + Video + ვიდეო + + + + Resolution + გარჩევადობა + + + + Aspect ratio + თანაფარდობა + + + + Format + ფორმატი + + + + Bitrate + ბიტური სიხშირე + + + + %1 kbps + %1 კბწმ + + + + Frames per second + კადრი წამში + + + + Selected codec + არჩეული კოდეკი + + + + Initial Audio Stream + საწყისი აუდიონაკადი + + + + Rate + სიხშირე + + + + %1 Hz + %1 ჰც + + + + Channels + არხები + + + + Audio Streams + აუდიონაკადები + + + + Language + ენა + + + + empty + ცარიელია + + + + Subtitles + სუბტიტრები + + + + Type + ტიპი + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + + + + + Stream URL + + + + + File + + + + + InputDVDDirectory + + + Choose a directory + აირჩიეთ დირექტორია + + + + SMPlayer - Play a DVD from a folder + SMPlayer - დაუკარით DVD დასტიდან + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + თქვენ შეგიძლიათ გაუშვათ dvd თქვენი მყარი დისკიდან. უბრალოდ აირჩიეთ დასტა რომელიც შეიცვს VIDEO_TS და AUDIO_TS დირექტორიებს. + + + + Choose a directory... + აირჩიეთ დირექტორია... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + + + + + &URL: + + + + + It's a &playlist + + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + არაბული + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + ჩეხური + + + + Welsh + + + + + Danish + + + + + German + გერმანული + + + + Greek + + + + + English + ინგლისური + + + + Esperanto + + + + + Spanish + ესპანური + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + + + + + Faroese + + + + + French + ფრანგული + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + უნგრული + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + იტალიური + + + + Inuktitut + + + + + Japanese + იაპონური + + + + Javanese + + + + + Georgian + ქართული + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + ჰოლანდიური + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + პოლონური + + + + Portuguese + + + + + Quechua + + + + + Romanian + + + + + Russian + რუსული + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + სლოვაკური + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + + + + + Sundanese + + + + + Swedish + + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + თურქული + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + უკრაინული + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + + + + + Portuguese - Portugal + + + + + Simplified-Chinese + გამარტივებული ჩინური + + + + Traditional Chinese + + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + დასავლეთევროპული ენები + + + + Western European Languages with Euro + დასავლეთევროპული ენები ევროს მხარდაჭერით + + + + Slavic/Central European Languages + სლავური/ცენტრალურევროპული ენები + + + + Esperanto, Galician, Maltese, Turkish + ესპერანტო, გალიციური, მალტური, თურქული + + + + Old Baltic charset + ძველი ბალტიური სიმბოლოების ნაკრები + + + + Cyrillic + კირილიცა + + + + Modern Greek + თანამედროვე ბერძნული + + + + Baltic + ბალტიური + + + + Celtic + კელტური + + + + Hebrew charsets + ებრაულ სიმბოლოთა ნაკრები + + + + Ukrainian, Belarusian + უკრაინული, ბელორუსული + + + + Simplified Chinese charset + გამარტივებული ჩინურის სიმბოლოთა ნაკრები + + + + Traditional Chinese charset + ტრადიციული ჩინურის სიმბოლოთა ნაკრები + + + + Japanese charsets + იაპონურ სიმბოლოთა ნაკრები + + + + Korean charset + კორეულ სიმბოლოთა ნაკრები + + + + Thai charset + ტაილანდურ სიმბოლოთა ნაკრები + + + + Cyrillic Windows + Windows-ის კირილიცა + + + + Slavic/Central European Windows + Windows-ის სლავური/დენტრალურევროპული + + + + Arabic Windows + + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + აირჩიეთ ჩასაწერი ფაილის სახელი + + + + Confirm overwrite? + დავადასტუროთ შეცვლა? + + + + The file already exists. +Do you want to overwrite? + ფაილი უკვე არსებობს. +გსურთ მისი შეცვლა? + + + + Error saving file + შეცდომა ფაილის შენახვისას + + + + The log couldn't be saved + ჟურნალის შენახვა ვერ მოხერხდა + + + + Logs + ჟურნალები + + + + LogWindowBase + + + Log Window + ჟურნალის ფანჯარა + + + + Save + შენახვა + + + + Copy to clipboard + გაცვლის ბუფერში შენახვა + + + + Close + დაკეტვა + + + + &Close + და&კეტვა + + + + MiniGui + + + Control bar + + + + + MpcGui + + + Control bar + + + + + -%1 + + + + + +%1 + + + + + Playlist + + + Name + დასახელება + + + + Length + ხანგრძლივობა + + + + &Play + და&კვრა + + + + &Edit + რ&ედაქტირება + + + + Playlists + რეპერტუარები + + + + Choose a file + აირჩიეთ ფაილი + + + + Choose a filename + აირჩიეთ ფაილის სახელი + + + + Confirm overwrite? + დავადასტუროთ შეცვლა? + + + + The file %1 already exists. +Do you want to overwrite? + ფაილი %1 უკვე არსებობს. +გსურთ მისი შეცვლა? + + + + All files + ყველა ფაილი + + + + Select one or more files to open + გასახსნელად აირჩიეთ ერთი ან რამოდენიმე ფაილი + + + + Choose a directory + აირჩიეთ დირექტორია + + + + Edit name + სახელის რედაქტირება + + + + Type the name that will be displayed in the playlist for this file: + შეიყვანეთ სახელი რომელიც იქნება გამოსახული რეპერტუარიში ამ ფაილისთვის: + + + + &Load + ჩა&ტვირთვა + + + + &Save + შენა&ხვა + + + + &Next + &შემდეგი + + + + Pre&vious + &წინა + + + + Move &up + &ზევით აწევა + + + + Move &down + &ქვევით ჩაწევა + + + + &Repeat + გამეო&რება + + + + S&huffle + არე&ვა + + + + Add &current file + &მიმდინარე ფაილის დამატება + + + + Add &file(s) + &ფაილ(ებ)ის დამატება + + + + Add &directory + &დირექტორიის დამატება + + + + Remove &selected + ა&რჩეულის ამოღება + + + + Remove &all + ყველ&ას ამოღება + + + + SMPlayer - Playlist + SMPlayer - რეპერტუარი + + + + Add... + დამატება... + + + + Remove... + ამოღება... + + + + Playlist modified + + + + + There are unsaved changes, do you want to save the playlist? + + + + + Preferences + + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + დამატებითი + + + + Auto + + + + + &Advanced + + + + + icon + ხატულა + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + აგრეთქე შეგიძლიათ დამატებითი ვიდეოფილრების მითითება. +გამოყავით ისინი "," სიმბოლოს საშუალებით. არ გამოტოვოთ ადგილი! +მაგალითი: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + და ბოლოს - აუდიოფილრტრები. იგივე წესით როგორც ვიდეოფილრები. +მაგალითი: resample=44100:0:0,volnorm + + + + Log MPlayer output + + + + + Log SMPlayer output + + + + + This option is mainly intended for debugging the application. + ეს პარამეტრი ძირითადად განკუთვნილია პროგრამის გამართვისათვის. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + + + + + Filter for SMPlayer logs + + + + + &Monitor aspect: + + + + + &Run MPlayer in its own window + + + + + &Options: + &პარამეტრები: + + + + V&ideo filters: + ვ&იდეოფილტრები: + + + + Audio &filters: + აუდიო&ფილტრები: + + + + &Colorkey: + + + + + Log &SMPlayer output + + + + + &Filter for SMPlayer logs: + + + + + C&hange... + + + + + Logs + + + + + Log MPlayer &output + + + + + Options for MP&layer + + + + + Autosave MPlayer log + + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + + + + + Select all + + + + + Check all file types in the list + + + + + Uncheck all file types in the list + + + + + List of file types + + + + + File types + + + + + Media files handled by SMPlayer: + + + + + Select All + + + + + Select None + + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + Select none + + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + ამძრავები + + + + icon + ხატულა + + + + CD device + + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + + + + + DVD device + + + + + Choose your DVD device. It will be used to play DVDs. + + + + + Select your &CD device: + + + + + Select your &DVD device: + + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + ძირითადი + + + + &General + + + + + Paths + გეზები + + + + Media settings + მედიაპარამეტრები + + + + Preferred audio and subtitles + უპირატესი აუდიო და სუბტიტრები + + + + Video + ვიდეო + + + + Start videos in fullscreen + ვიდეოს მთელს ეკრანზე გაშვება + + + + Disable screensaver + ეკრანმზოგის გათიშვა + + + + Audio + აუდიო + + + + Select the mplayer executable + აირჩიეთ mplayer-ის გაშვებადი ფაილი + + + + Executables + გაშვებადი ფაილები + + + + All files + ყველა ფაილი + + + + Select a directory + აირჩიეთ დირექტორია + + + + MPlayer executable + + + + + Screenshots folder + + + + + Video output driver + + + + + Audio output driver + + + + + Select the audio output driver. + აირჩიეთ აუდიოგამომყვანის დრაივერი + + + + Remember settings + + + + + Preferred audio language + + + + + Preferred subtitle language + + + + + Software video equalizer + + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + თქვენ შეგიძლიათ მონიშნოთ ეს პარამეტრი თუ თქვენს გრაფიკულ დაფას ან გამომყვან დრაივერს არ აქვს ვიდეოეკვალაიზერი.<br><b>შენიშვნა:</b> ეს პარამეტრში შეიძლება არათავსებადი აღმოჩნდეს ზოგიერთ გამომყვან დრაივერთან. + + + + If this option is checked, all videos will start to play in fullscreen mode. + თუ ეს პარამეტრი მონიშნულია, მაშინ ყველა ვიდეო გაიშვებს სრულეკრანიან რეჟიმში. + + + + Software volume control + + + + + Check this option to use the software mixer, instead of using the sound card mixer. + მონიშნეთ ეს პარამეტრი აუდიოდაფის მიქშერის მაგივრად პროგრამული მიქშერის გამოსაყენებლად. + + + + Postprocessing quality + + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + დინამიურად ცვლის შემდგომი დამუშავების დონეს პროცესორის დატვირთვის მიხედვით. თქვენს მიერ მითითებული რიცხვი იქნება მაქსიმალური დონე. როგორც წესი უთითებენ რაღაც დიდ რიცხვს. + + + + Change volume + + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + 0 + 0 + + + + &Change volume on every file + + + + + Select the &MPlayer executable: + + + + + &Folder for storing screenshots: + + + + + &Audio: + + + + + &Remember settings for all files (audio track, subtitles...) + + + + + Su&btitles: + + + + + &Quality: + + + + + Start videos in &fullscreen + + + + + Disable &screensaver + + + + + &Default volume: + + + + + Use s&oftware volume control + + + + + Ma&x. Amplification: + + + + + &AC3/DTS pass-through S/PDIF + + + + + Direct rendering + + + + + Double buffering + + + + + D&irect rendering + + + + + Dou&ble buffering + + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + &Enable postprocessing by default + + + + + Volume &normalization by default + + + + + Close when finished + + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + + + + + 4 (4.0 Surround) + + + + + 6 (5.1 Surround) + + + + + C&hannels by default: + + + + + &Pause when minimized + + + + + Pause when minimized + + + + + Enable postprocessing by default + + + + + Max. Amplification + + + + + AC3/DTS pass-through S/PDIF + + + + + Volume normalization by default + + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + + + + + Audi&o: + + + + + Preferred language: + + + + + Preferre&d audio and subtitles + + + + + &Subtitle: + + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + &ვიდეო + + + + Use s&oftware video equalizer + + + + + A&udio + + + + + Volume + ხმა + + + + None + + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + + + + + &Keyboard + + + + + icon + ხატულა + + + + &Mouse + + + + + Button functions: + ღილაკების ფუნქციები: + + + + Media seeking + გადასვლები მატარებელში + + + + Volume control + ხმის მართვა + + + + Zoom video + + + + + None + არაა + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + + + + + &Double click + + + + + &Wheel function: + + + + + Shortcut editor + + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + + + + + Select the action for left click on the mouse. + + + + + Double click + + + + + Select the action for double click on the mouse. + + + + + Wheel function + + + + + Select the action for the mouse wheel. + + + + + Play + + + + + Pause + პაუზა + + + + Stop + შეჩერება + + + + Fullscreen + + + + + Compact + + + + + Screenshot + + + + + Mute + + + + + Frame counter + + + + + Reset zoom + + + + + Exit fullscreen + + + + + Double size + + + + + Play / Pause + დაკვრა / პაუზა + + + + Pause / Frame step + პაუზა / კადრული ბიჯი + + + + Playlist + რეპერტუარი + + + + Preferences + + + + + No function + + + + + Change speed + + + + + Normal speed + + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + ინტერფეისი + + + + <Autodetect> + <ავტომატური> + + + + Default + ნაგულისხმები + + + + &Interface + + + + + Seeking + გადასვლა + + + + Never + არასდროს + + + + Whenever it's needed + როდესაც საჭიროა + + + + Only after loading a new video + მხოლოდ ახალი ვიდეოს ჩატვირთვისას + + + + Recent files + წინა ფაილები + + + + Language + + + + + Here you can change the language of the application. + + + + + &Short jump + + + + + &Medium jump + + + + + &Long jump + + + + + Mouse &wheel jump + + + + + &Use only one running instance of SMPlayer + + + + + Ma&x. items + + + + + St&yle: + + + + + Ico&n set: + + + + + L&anguage: + + + + + Main window + + + + + Auto&resize: + + + + + R&emember position and size + + + + + Default font: + + + + + &Change... + + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + + + + + &Seeking + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + წარმადობა + + + + &Performance + + + + + Priority + პრიორიტეტი + + + + Select the priority for the MPlayer process. + + + + + realtime + რეალურ დროში + + + + high + მაღალი + + + + abovenormal + ნორმალურზე მაღალი + + + + normal + ნორმალური + + + + belownormal + ნორმალურზე მცირე + + + + idle + ყრუ + + + + KB + კბ + + + + Setting a cache may improve performance on slow media + ბუფერის მითითებამ შეიძლება გააუმჯობესოს წარმადობა ნელ მატარებლებზე + + + + Allow frame drop + კადრების გამოტოვება + + + + Synchronization + სინქრონიზება + + + + Audio/video auto synchronization + აუდიო/ვიდეოს ავტო სინქრონიზება + + + + Fast audio track switching + ხმის ჩანაწერის სწრაფი გადართვა + + + + Fast seek to chapters in dvds + თავებს შორის სწრაფი გადასვლა dvdებში + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + აირჩიოთ mplayer-ის პრიორიტეტი Windows-ში წინასწარ განსაზღვრული მნიშნელობებიდან.<br><b>ყურადღება:</b> რეალური დროის პრიორიტეტის გამოყენებამ შეიძლება გამოიწვიოს სისტემის უმოქმედობა. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + ზოგიერთი კადრის გამოტოვება A/V სინქრონიზაციის ნელ სისტემებზე შესანარჩუნებლად. + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + კადრების უფრო ინტენსიური გამოტოვება (არღვევს დეკოდირებას). ამახინჯებს გამოსახულებას! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + ნაბიჯნაბიჯ არეგულირებს A/V სინქრონიზაციას ხმის დაყოვნებების გაზომვით. + + + + Priorit&y: + + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + + + + + Fact&or: + + + + + &Fast audio track switching + + + + + Fast &seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + + + + + Cache for &DVDs: + + + + + Cache for &local files: + + + + + Cache for &streams: + + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + რე&პერტუარი + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + სუბტიტრები + + + + Choose a ttf file + აირჩიეთ ttf ფაილი + + + + Truetype Fonts + Truetype შრიფტები + + + + &Subtitles + &სუბტიტრები + + + + Autoload + ავტოჩატვირთვა + + + + Same name as movie + იგივე სახელი რაც ფილმს აქვს + + + + All subs containing movie name + ყველა სუბტიტრი რომელიც შეიცავს ფილმის სახელს + + + + All subs in directory + ყველა სუბტიტრი დირექტორიაში + + + + Position + + + + + 0 + 0 + + + + Top + + + + + Bottom + + + + + Include subtitles on screenshots + სუბტიტრების ეკრანის ანაბეჭდებში ჩვენება + + + + Font + შრიფტი + + + + Select the font which will be used for subtitles (and OSD): + აირჩიეთ შრიფტი რომელიც გამოყენებული იქნება სუბტიტრებისთვის (და OSD-თვის): + + + + Size + ზომა + + + + No autoscale + ავტომასშტაბირების გარეშე + + + + Proportional to movie height + ფილმის სიმაღლის პროპორციული + + + + Proportional to movie width + ფილმის სიგრძის პროპორციული + + + + Proportional to movie diagonal + ფილმის დიაგონალის პროპორციული + + + + Subtitle position + + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + + + + + Au&toload subtitles files (*.srt, *.sub...): + + + + + S&elect first available subtitle + + + + + &Default subtitle encoding: + + + + + Default &position of the subtitles on screen + + + + + &Include subtitles on screenshots + + + + + &TTF font: + + + + + S&ystem font: + + + + + A&utoscale: + + + + + Select first available subtitle + + + + + Default subtitle encoding + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + + + + + Middle + vertical alignment + + + + + Top + vertical alignment + + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + + + + + OK + + + + + Cancel + + + + + Apply + + + + + Help + + + + + SMPlayer - Preferences + SMPlayer - პარამეტრები + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + + the main window won't be closed when the file/playlist finishes. + + + + + the video will be played in fullscreen mode. + + + + + the video will be played in window mode. + + + + + Enqueue in SMPlayer + + + + + opens the mini gui instead of the default one. + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + Usage: + + + + + directory + + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + %1 minute(s) + + + + + + + %1 and %2 + + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + ხატულა + + + + label + დასახელება + + + + ShortcutGetter + + + Modify shortcut + + + + + Clear + + + + + Press the key combination you want to assign + + + + + Capture + + + + + Capture keystrokes + + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + + + + + Select None + + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + + + + + Yes + + + + + No + + + + + VideoEqualizer + + + Contrast + კონტრასტი + + + + Brightness + სიკაშკაშე + + + + Hue + ტონი + + + + Saturation + ინტენსივობა + + + + Gamma + გამა + + + + &Reset + &საწყისი პარამეტრები + + + + &Set as default values + ნაგულის&ხმებად შენახვა + + + + Use the current values as default values for new videos. + მიმდინარე მნიშვნელობების ახალი ვიფდეოებისთვის გამოყენება. + + + + Set all controls to zero. + ყველაფრის ნორმალიზება. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + შეცდომა ფაილის შენახვისას + + + + The file couldn't be saved + + + + + Error + + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + + + + + %1 Hz + + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + ხმა + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_ko.ts b/plugins/smplayer_plugin/translations/smplayer_ko.ts new file mode 100644 index 000000000..0cef7d0d3 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_ko.ts @@ -0,0 +1,7233 @@ + + + + About + + + Version: %1 + 버전: %1 + + + + Visit our web for updates: + + + + + Get help in our forum: + + + + + You can support SMPlayer by making a donation. + + + + + More info + + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + 이 프로그램은 자유 소프트웨어입니다. 자유 소프트웨어 재단에서 배포되는 GNU 일반 공중 사용 허가서(2판 이상)에 의해 자유롭게 수정하고/하거나 재배포할 수 있습니다. + + + + The following people have contributed with translations: + + + + + German + 독일어 + + + + Slovak + 슬로바키아어 + + + + Italian + 이탈리아어 + + + + French + 프랑스어 + + + + %1, %2 and %3 + %1, %2, %3 + + + + Simplified-Chinese + 중국어(간체) + + + + Russian + 러시아어 + + + + %1 and %2 + %1, %2 + + + + Hungarian + 헝가리어 + + + + Polish + 폴란드어 + + + + Japanese + 일본어 + + + + Dutch + 네덜란드어 + + + + Ukrainian + 우크라이나어 + + + + Portuguese - Brazil + 포르투갈어(브라질) + + + + Georgian + 그루지야어 + + + + Czech + 체코어 + + + + Bulgarian + 불가리아어 + + + + Turkish + 터키어 + + + + Swedish + 스웨덴어 + + + + Serbian + 세르비아어 + + + + Traditional Chinese + 중국어(번체) + + + + Romanian + 루마니아어 + + + + Portuguese - Portugal + 포르투갈어(포르투갈) + + + + Greek + 그리스어 + + + + Finnish + 핀란드어 + + + + Korean + + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + + + + + About SMPlayer + SMPlayer에 대하여 + + + + &Info + + + + + icon + 아이콘 + + + + &Contributions + + + + + &Translators + + + + + &License + + + + + Macedonian + + + + + Basque + 바스크어 + + + + Using MPlayer %1 + + + + + Catalan + 카탈루냐어 + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + 아랍어 + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + 이름 + + + + Description + 설명 + + + + Shortcut + 바로가기 + + + + &Save + 저장하기(&S) + + + + &Load + 불러오기(&L) + + + + Key files + 키 파일 + + + + Choose a filename + 파일 선택 + + + + Confirm overwrite? + 덮어쓰시겠습니까? + + + + The file %1 already exists. +Do you want to overwrite? + "%1" 파일은 이미 존재합니다. +덮어쓰시겠습니까? + + + + Choose a file + 파일 선택 + + + + Error + 오류 + + + + The file couldn't be saved + 파일 저장에 실패하였습니다 + + + + The file couldn't be loaded + 파일 열기에 실패하였습니다 + + + + &Change shortcut... + 단축키 변경(&C)... + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + 초기화(&R) + + + + &Set as default values + 기본값으로 설정하기(&S) + + + + Use the current values as default values for new videos. + 다른 영상에서도 현재 설정값을 기본으로 지정합니다. + + + + Set all controls to zero. + 모두 0으로 설정합니다. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer 기록 + + + + SMPlayer - smplayer log + SMPlayer - smplayer 기록 + + + + &Open + 열기(&O) + + + + &Play + 재생(&P) + + + + &Video + 영상(&V) + + + + &Audio + 음성(&A) + + + + &Subtitles + 자막(&S) + + + + &Browse + 찾아보기(&B) + + + + Op&tions + 옵션(&T) + + + + &Help + 도움말(&H) + + + + &File... + 파일(&F)... + + + + D&irectory... + 폴더(&I)... + + + + &Playlist... + 재생 목록(&P)... + + + + &DVD from drive + 드라이브로부터 &DVD + + + + D&VD from folder... + 폴더로부터 &DVD... + + + + &URL... + &URL... + + + + &Clear + 지우기(&C) + + + + &Recent files + 최근에 재생한 파일(&R) + + + + P&lay + 재생(&L) + + + + &Pause + 일시 정지(&P) + + + + &Stop + 정지(&S) + + + + &Frame step + 프레임 스텝(&F) + + + + &Normal speed + 보통 속도로 재생(&N) + + + + &Halve speed + 0.5배속으로 재생(&H) + + + + &Double speed + 2배속으로 재생(&D) + + + + Speed &-10% + 속도 10% 감소(&-) + + + + Speed &+10% + 속도 10% 증가(&+) + + + + Sp&eed + 재생 속도(&E) + + + + &Repeat + 반복(&R) + + + + &Fullscreen + 전체 화면(&F) + + + + &Compact mode + 간결히 보기(&C) + + + + Si&ze + 크기(&Z) + + + + 4:3 &Letterbox + 4:3 가로에 맞춤(&L) + + + + 16:9 L&etterbox + 16:9 가로에 맞춤(&E) + + + + 4:3 &Panscan + 4:3 세로에 맞춤(&P) + + + + 4:3 &to 16:9 + 4:3에서 16:9로(&T) + + + + &Aspect ratio + 가로세로비(&A) + + + + &None + 없음(&N) + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + 선형 섞기(&B) + + + + &Deinterlace + 디인터레이스(&D) + + + + &Postprocessing + 후처리(&P) + + + + &Autodetect phase + 상태 자동 감지(&A) + + + + &Deblock + 영상 깨짐 제거(&D) + + + + De&ring + 고리 모양 제거(&R) + + + + Add n&oise + 영상 노이즈 넣기(&O) + + + + F&ilters + 필터(&I) + + + + &Equalizer + 이퀄라이저(&E) + + + + &Screenshot + 스크린샷(&S) + + + + S&tay on top + 항상 위(&T) + + + + &Extrastereo + 엑스트라스테레오(&E) + + + + &Karaoke + 반주(&K) + + + + &Filters + 필터(&F) + + + + &Stereo + 스테레오(&S) + + + + &4.0 Surround + &4.0 서라운드 + + + + &5.1 Surround + &5.1 서라운드 + + + + &Channels + 채널(&C) + + + + &Left channel + 좌측 채널(&L) + + + + &Right channel + 우측 채널(&R) + + + + &Stereo mode + 스테레오 모드(&S) + + + + &Mute + 음소거(&M) + + + + Volume &- + 볼륨 감소(&-) + + + + Volume &+ + 볼륨 증가(&+) + + + + &Delay - + 지연 감소(&D) + + + + D&elay + + 지연 증가(&E) + + + + &Select + 선택(&S) + + + + &Load... + 불러오기(&L)... + + + + Delay &- + 지연 감소(&-) + + + + Delay &+ + 지연 증가(&+) + + + + &Up + 위로(&U) + + + + &Down + 아래로(&D) + + + + &Title + 제목(&T) + + + + &Chapter + 장(&C) + + + + &Angle + 시점(&A) + + + + &Playlist + 재생 목록(&P) + + + + &Show frame counter + 프레임 카운터 보기(&S) + + + + &Disabled + 없음(&D) + + + + &Seek bar + 찾기 막대(&S) + + + + &Time + 시간(&T) + + + + Time + T&otal time + 시간 및 총 시간(&O) + + + + &OSD + &OSD + + + + &View logs + 기록 파일 보기(&V) + + + + P&references + 환경 설정(&R) + + + + About &Qt + &Qt에 대하여 + + + + About &SMPlayer + &SMPlayer에 대하여 + + + + <empty> + (비어 있음) + + + + Video + 동영상 파일 + + + + Audio + 오디오 파일 + + + + Playlists + 재생 목록 + + + + All files + 모든 파일 + + + + Choose a file + 파일을 선택하십시요 + + + + SMPlayer - Information + SMPlayer - 정보 + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CD-ROM 및 DVD 드라이브가 지정되지 않았습니다. +드라이브 설정을 위한 대화 상자가 표시될 것입니다. + + + + Choose a directory + 폴더 선택 + + + + Subtitles + 자막 + + + + About Qt + Qt에 대하여 + + + + Playing %1 + %1 재생 중 + + + + Pause + 일시 정지 + + + + Stop + 정지됨 + + + + Play / Pause + 재생 / 일시 정지 + + + + Pause / Frame step + 일시 정지 / 프레임 스텝 + + + + U&nload + 언로드(&N) + + + + V&CD + 비디오 &CD + + + + C&lose + 닫기(&L) + + + + View &info and properties... + 정보 및 속성 보기(&I)... + + + + Zoom &- + 축소 (&-) + + + + Zoom &+ + 확대 (&+) + + + + &Reset + 초기화(&R) + + + + Move &left + 왼쪽으로 이동(&L) + + + + Move &right + 오른쪽으로 이동(&R) + + + + Move &up + 위로 이동(&U) + + + + Move &down + 아래로 이동(&D) + + + + &Pan && scan + 화면 비율 맞추기(&P) + + + + &Previous line in subtitles + 이전 자막 줄(&P) + + + + N&ext line in subtitles + 다음 자막 줄(&E) + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + 음량 감소 (2) + + + + Inc volume (2) + 음량 증가 (2) + + + + Exit fullscreen + 전체 화면 나가기 + + + + OSD - Next level + OSD - 다음 + + + + Dec contrast + 대비 감소 + + + + Inc contrast + 대비 증가 + + + + Dec brightness + 밝기 감소 + + + + Inc brightness + 밝기 증가 + + + + Dec hue + 색조 감소 + + + + Inc hue + 색조 증가 + + + + Dec saturation + 채도 감소 + + + + Dec gamma + 감마 감소 + + + + Next audio + 다음 오디오 + + + + Next subtitle + 다음 자막 + + + + Next chapter + 다음 장 + + + + Previous chapter + 이전 장 + + + + Inc saturation + 채도 증가 + + + + Inc gamma + 감마 증가 + + + + &Load external file... + 외부 파일 불러오기(&L)... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (일반) + + + + Y&adif (double framerate) + Y&adif (2배 프레임률) + + + + &Next + 다음(&N) + + + + Pre&vious + 이전(&V) + + + + Volume &normalization + 음량 노멀라이즈(&N) + + + + &Audio CD + 오디오 CD(&A) + + + + Denoise nor&mal + 일반 노이즈 제거(&M) + + + + Denoise &soft + 부드러운 노이즈 제거(&S) + + + + Denoise o&ff + 노이즈 제거 없음(&F) + + + + Use SSA/&ASS library + SSA/&ASS 라이브러리 사용 + + + + Flip i&mage + 이미지 뒤집기(&M) + + + + &Toggle double size + 보통/2배 크기 전환(&T) + + + + S&ize - + 작게(&-) + + + + Si&ze + + 크게(&+) + + + + Add &black borders + + + + + Soft&ware scaling + + + + + Visualize &motion vectors + + + + + &FAQ + + + + + &Command line options + + + + + SMPlayer command line options + + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + 트랙(&T) + + + + &Track + audio + 트랙(&T) + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer가 실행 중입니다 + + + + S&how icon in system tray + 시스템 트레이에 아이콘 보이기(&H) + + + + &Hide + 숨기기(&H) + + + + &Restore + 복원(&R) + + + + &Quit + 종료(&Q) + + + + Playlist + 재생 목록 + + + + Core + + + Brightness: %1 + 밝기: %1 + + + + Contrast: %1 + 대비: %1 + + + + Gamma: %1 + 감마: %1 + + + + Hue: %1 + 색조: %1 + + + + Saturation: %1 + 채도: %1 + + + + Volume: %1 + 음량: %1 + + + + Zoom: %1 + 배율: %1 + + + + Font scale: %1 + + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + SMPlayer 사용자님, 환영합니다 + + + + Audio + 오디오 + + + + Subtitle + 자막 + + + + &Main toolbar + 기본 도구 모음(&M) + + + + &Language toolbar + 언어 도구 모음(&L) + + + + &Toolbars + 도구 모음(&T) + + + + EqSlider + + + icon + 아이콘 + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + 아이콘 + + + + Error + 오류 + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - 파일 속성 + + + + &Information + 정보(&I) + + + + &Demuxer + 디멀티플렉서(&D) + + + + &Select the demuxer that will be used for this file: + 이 파일에 사용될 디멀티플렉서를 선택하십시요(&S): + + + + &Reset + 초기화(&R) + + + + &Video codec + 영상 코덱(&V) + + + + &Select the video codec: + 영상 코덱을 선택하십시요(&S): + + + + A&udio codec + 오디오 코덱(&U) + + + + &Select the audio codec: + 오디오 코덱을 선택하십시요(&S): + + + + &MPlayer options + &MPlayer 옵션 + + + + Additional Options for MPlayer + MPlayer 추가 옵션 + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + 이 칸에서 MPlayer에 전달할 추가 옵션을 선택할 수 있습니다. +공백으로 구분하여 입력하십시요. +(예: -flip -nosound) + + + + &Options: + 옵션(&O): + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + 추가 영상 필터를 적용할 수 있습니다. +쉼표(,)로 구분합니다. 띄어쓰기를 삽입하지 마십시요. +(예: scale=52:-2,eq2=1.1) + + + + V&ideo filters: + 영상 필터(&I): + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + 오디오 필터도 적용할 수 있습니다. 쉼표로 구분합니다. +(예: resample=44100:0:0,volnorm) + + + + Audio &filters: + 오디오 필터(&F): + + + + OK + 확인 + + + + Cancel + 취소 + + + + Apply + 적용 + + + + FindSubtitlesWindow + + + Language + 언어 + + + + Name + 이름 + + + + Format + 형식 + + + + Files + + + + + Date + 날짜 + + + + Uploaded by + + + + + All + + + + + Close + 닫기 + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + 오류 + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + 파일 저장 오류 + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + 일반 + + + + Size + 크기 + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + 길이 + + + + Demuxer + 디멀티플렉서 + + + + Name + 이름 + + + + Artist + 아티스트 + + + + Author + 제작자 + + + + Album + 앨범 + + + + Genre + 장르 + + + + Date + 날짜 + + + + Track + 트랙 + + + + Copyright + 저작권 + + + + Comment + 주석 + + + + Software + 소프트웨어 + + + + Clip info + 클립 정보 + + + + Video + 영상 + + + + Resolution + 해상도 + + + + Aspect ratio + 가로세로비 + + + + Format + 형식 + + + + Bitrate + 비트레이트 + + + + %1 kbps + %1 kbps + + + + Frames per second + 초당 프레임 수 + + + + Selected codec + 선택된 코덱 + + + + Initial Audio Stream + 초기 오디오 스트림 + + + + Rate + 레이트 + + + + %1 Hz + %1 Hz + + + + Channels + 채널 + + + + Audio Streams + 오디오 스트림 + + + + Language + 언어 + + + + empty + (없음) + + + + Subtitles + 자막 + + + + Type + 형식 + + + + ID + Info for translators: this is a identification code + 식별 번호 + + + + # + Info for translators: this is a abbreviation for number + 번호 + + + + Stream title + 스트림 제목 + + + + Stream URL + 스트림 URL + + + + File + 파일 + + + + InputDVDDirectory + + + Choose a directory + 폴더를 선택하십시요 + + + + SMPlayer - Play a DVD from a folder + SMPlayer - 폴더로부터 DVD 재생 + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + 하드 디스크에 저장된 DVD도 재생할 수 있습니다. VIDEO_TS 및 AUDIO_TS 폴더를 포함하는 상위 폴더를 지정하십시요. + + + + Choose a directory... + 찾아보기... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - URL 입력 + + + + &URL: + &URL: + + + + It's a &playlist + 재생 목록(&P) + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + 이 옵션을 선택하면, URL은 재생 목록으로 취급되어 해당 파일 내용에 있는 다른 URL들이 재생됩니다. + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + 아랍어 + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + 불가리아어 + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + 카탈루냐어 + + + + Corsican + + + + + Czech + 체코어 + + + + Welsh + + + + + Danish + + + + + German + 독일어 + + + + Greek + 그리스어 + + + + English + 영어 + + + + Esperanto + + + + + Spanish + 스페인어 + + + + Estonian + + + + + Basque + 바스크어 + + + + Persian + + + + + Finnish + 핀란드어 + + + + Faroese + + + + + French + 프랑스어 + + + + Frisian + + + + + Irish + + + + + Galician + 갈리시아어 + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + 헝가리어 + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + 이탈리아어 + + + + Inuktitut + + + + + Japanese + 일본어 + + + + Javanese + + + + + Georgian + 그루지야어 + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + 네덜란드어 + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + 폴란드어 + + + + Portuguese + + + + + Quechua + + + + + Romanian + 루마니아어 + + + + Russian + 러시아어 + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + 슬로바키아어 + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + 세르비아어 + + + + Sundanese + + + + + Swedish + 스웨덴어 + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + 터키어 + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + 우크라이나어 + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + 포르투갈어(브라질) + + + + Portuguese - Portugal + 포르투갈어(포르투갈) + + + + Simplified-Chinese + 중국어(간체) + + + + Traditional Chinese + 중국어(번체) + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + 서유럽어 + + + + Western European Languages with Euro + 서유럽어 (유로 기호 사용) + + + + Slavic/Central European Languages + 슬라브어/중앙 유럽어 + + + + Esperanto, Galician, Maltese, Turkish + 에스페란토/갈리시아어/몰타어/터키어 + + + + Old Baltic charset + 발트어 문자집합 + + + + Cyrillic + 키릴 문자 + + + + Modern Greek + 현대 그리스어 + + + + Baltic + 발트어 + + + + Celtic + 켈트어 + + + + Hebrew charsets + 히브리어 문자집합 + + + + Ukrainian, Belarusian + 우크라이나어/벨로루시어 + + + + Simplified Chinese charset + 중국어 간체 문자집합 + + + + Traditional Chinese charset + 중국어 번체 문자집합 + + + + Japanese charsets + 일본어 문자집합 + + + + Korean charset + 한국어 만자집합 + + + + Thai charset + 태국어 문자집합 + + + + Cyrillic Windows + 키릴 문자 (윈도우) + + + + Slavic/Central European Windows + 슬라브어/중앙 유럽어 (윈도우) + + + + Arabic Windows + 아랍어 (윈도우) + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + 저장할 폴더를 선택하십시요 + + + + Confirm overwrite? + 덮어쓰시겠습니까? + + + + The file already exists. +Do you want to overwrite? + 파일이 이미 존재합니다. +덮어쓰시겠습니까? + + + + Error saving file + 파일 저장 오류 + + + + The log couldn't be saved + 기록 파일 저장에 실패하였습니다 + + + + Logs + 기록 파일 + + + + LogWindowBase + + + Log Window + 기록 파일 + + + + Save + 저장 + + + + Copy to clipboard + 클립보드로 복사 + + + + &Close + 닫기(&C) + + + + Close + 닫기 + + + + MiniGui + + + Control bar + 조절 막대 + + + + MpcGui + + + Control bar + 조절 막대 + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + 이름 + + + + Length + 길이 + + + + &Play + 재생(&P) + + + + &Edit + 편집(&E) + + + + Playlists + 재생 목록 + + + + Choose a file + 파일 선택 + + + + Choose a filename + 파일 선택 + + + + Confirm overwrite? + 덮어쓰시겠습니까? + + + + The file %1 already exists. +Do you want to overwrite? + "%1" 파일은 이미 존재합니다.덮어쓰시겠습니까? + + + + All files + 모든 파일 + + + + Select one or more files to open + 열 파일을 선택하십시요 + + + + Choose a directory + 폴더를 선택하십시요 + + + + Edit name + 이름 편집 + + + + Type the name that will be displayed in the playlist for this file: + 재생 목록에 표시될 파일의 이름을 입력하십시요: + + + + &Load + 불러오기(&L) + + + + &Save + 저장하기(&S) + + + + &Next + 다음(&N) + + + + Pre&vious + 이전(&V) + + + + Move &up + 위로 이동(&U) + + + + Move &down + 아래로 이동(&D) + + + + &Repeat + 반복(&R) + + + + S&huffle + 순서 섞기(&H) + + + + Add &current file + 현재 파일을 추가(&C) + + + + Add &file(s) + 파일 추가(&F) + + + + Add &directory + 폴더 추가(&D) + + + + Remove &selected + 이 항목 제거(&S) + + + + Remove &all + 모두 제거(&A) + + + + SMPlayer - Playlist + SMPlayer - 재생 목록 + + + + Add... + 추가... + + + + Remove... + 제거... + + + + Playlist modified + 재생 목록 수정됨 + + + + There are unsaved changes, do you want to save the playlist? + 저장되지 않은 변경 사항이 있습니다. 재생 목록을 저장하시겠습니까? + + + + Preferences + 환경 설정 + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + 고급 + + + + Auto + 자동 + + + + &Advanced + 고급(&A) + + + + icon + 아이콘 + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + 이 칸에서 MPlayer에 전달할 추가 옵션을 선택할 수 있습니다. +공백으로 구분하여 입력하십시요.(예: -flip -nosound) + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + 추가 영상 필터를 적용할 수 있습니다. +쉼표(,)로 구분합니다. 띄어쓰기를 삽입하지 마십시요. +(예: scale=52:-2,eq2=1.1) + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + 오디오 필터도 적용할 수 있습니다. 쉼표로 구분합니다. +(예: resample=44100:0:0,volnorm) + + + + Log MPlayer output + MPlayer 출력 기록하기 + + + + Log SMPlayer output + SMPlayer 출력 기록하기 + + + + This option is mainly intended for debugging the application. + 이 옵션은 프로그램을 디버그하는 것에 목적을 두고 있습니다. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + 이 옵션을 선택하면 깜빡임을 해소할 수도 있지만, 영상이 정상적으로 재생되지 않을 수도 있습니다. + + + + Filter for SMPlayer logs + SMPlayer 기록 필터 + + + + &Monitor aspect: + 모니터 가로세로비(&M): + + + + &Run MPlayer in its own window + MPlayer를 별도의 창에서 실행(&R) + + + + &Options: + 옵션(&O): + + + + V&ideo filters: + 영상 필터(&I): + + + + Audio &filters: + 오디오 필터(&F): + + + + &Colorkey: + 컬러키(&C): + + + + Log &SMPlayer output + SMPlayer 출력 기록하기(&S) + + + + &Filter for SMPlayer logs: + SMPlayer 기록 필터(&F): + + + + C&hange... + 변경(&H)... + + + + Logs + 기록 파일 + + + + Log MPlayer &output + MPlayer 출력 기록하기(&O) + + + + Options for MP&layer + MPlayer 옵션(&L) + + + + Autosave MPlayer log + MPlayer 기록 파일 자동 저장 + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + 이 옵션이 선택되면, MPlayer 기록은 새로운 파일이 재생되기 시작할 때마다 파일에 저장됩니다. 이 기능은 다른 프로그램들이 재생되고 있는 파일에 대한 정보를 알 수 있도록 하기 위하여 제공됩니다. + + + + Autosave MPlayer log filename + MPlayer 기록 파일명 자동 저장 + + + + Enter here the path and filename that will be used to save the MPlayer log. + MPlayer 기록 파일을 저장할 경로와 파일명을 입력하십시요. + + + + A&utosave MPlayer log to file + MPlayer 기록을 파일에 자동 저장(&U) + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + 인덱스가 없을 경우 지점 이동을 위해 파일의 인덱스를 재구성합니다. 깨지거나 완료되지 않은 다운로드, 혹은 올바르지 않게 생성된 파일에 대해 유용하니다. 이 옵션은 미디어가 지점 이동을 지원하는 경우(표준 입력이나 파이프 등은 안 됩니다)에만 적용됩니다.<br> 주의: 인덱스 생성에는 약간의 시간이 소요됩니다. + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + 형식 + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + 경고 + + + + Not all files could be associated. Please check your security permissions and retry. + 하나 이상의 파일 형식 연결에 실패하였습니다. 충분한 권한이 있는지 확인하십시요. + + + + File Types + 파일 형식 + + + + Select all + 모두 선택 + + + + Check all file types in the list + 목록에 있는 모든 파일 형식을 선택 + + + + Uncheck all file types in the list + 목록에 있는 모든 파일 형식에서 선택을 해제 + + + + List of file types + 파일 형식 목록 + + + + File types + 파일 형식 + + + + Media files handled by SMPlayer: + SMPlayer와 연결되는 미디어 파일: + + + + Select All + 모두 선택 + + + + Select None + 모두 선택 해제 + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + SMPlayer와 연결하고 싶은 미디어 파일에 선택하십시요. 적용 버튼을 누르면 해당 파일 형식들이 SMPlayer와 연결되게 됩니다. 선택을 해제하면, 파일 형식과 원래 연결되었던 프로그램과 다시 연결됩니다. + + + + Select none + 모두 선택 해제 + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + 드라이브 + + + + icon + 아이콘 + + + + CD device + CD 드라이브 장치 + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + CD-ROM 드라이브를 선택하십시요. 비디오 및 오디오 CD를 재생하는 데 사용됩니다. + + + + DVD device + DVD 드라이브 장치 + + + + Choose your DVD device. It will be used to play DVDs. + DVD 드라이브를 선택하십시요. DVD 재생에 사용됩니다. + + + + Select your &CD device: + &CD 드라이브: + + + + Select your &DVD device: + &DVD 드라이브: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + 일반 + + + + &General + 일반(&G) + + + + Paths + 경로 + + + + Media settings + 미디어 설정 + + + + Video + 영상 + + + + Start videos in fullscreen + 전체 화면에서 동영상 시작 + + + + Disable screensaver + 화면 보호기 비활성화 + + + + Audio + 오디오 + + + + Select the mplayer executable + MPlayer 실행 파일 선택 + + + + Executables + 실행 파일 + + + + All files + 모든 파일 + + + + Select a directory + 폴더 선택 + + + + MPlayer executable + MPlayer 실행 파일 + + + + Screenshots folder + 스크린샷 폴더 + + + + Video output driver + 영상 출력 드라이버 + + + + Audio output driver + 오디오 출력 드라이버 + + + + Select the audio output driver. + 오디오 출력 드라이버를 선택하십시요. + + + + Remember settings + 설정 기억하기 + + + + Preferred audio language + 사용할 오디오 언어 + + + + Preferred subtitle language + 사용할 자막 언어 + + + + Software video equalizer + 소프트웨어 영상 이퀄라이저 + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + 만약 그래픽 카드나 영상 출력 드라이버에 의해 영상 이퀄라이저가 지원되지 않는 경우, 이 옵션을 선택할 수 있습니다.<br><b>주의:</b> 이 옵션은 일부 영상 출력 드라이버와는 호환되지 않을 수 있습니다. + + + + If this option is checked, all videos will start to play in fullscreen mode. + 만약 이 옵션이 선택되면, 모든 동영상은 전체 화면에서 재생이 시작될 것입니다. + + + + Software volume control + 소프트웨어 음량 조절 + + + + Check this option to use the software mixer, instead of using the sound card mixer. + 이 옵션을 선택하면 사운드 카드의 믹서 대신 소프트웨어 믹서를 사용합니다. + + + + Postprocessing quality + 후처리 품질 + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + 사용할 수 있는 CPU 시간을 고려하여 후처리의 품질을 동적으로 결정합니다. 여기에 입력하는 숫자는 최대 품질이 될 것입니다. 실제 품질은 동적으로 결정되므로, 조금 큰 수를 설정해도 좋습니다. + + + + Change volume + 음량 바꾸기 + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + 이 옵션을 선택하면, SMPlayer는 모든 파일에 사용된 음량을 기억하고 다시 재생될 때 그 음량을 사용합니다. 새로운 파일에 대해서는 기본 음량이 사용됩니다. + + + + 0 + 0 + + + + &Change volume on every file + 모든 파일의 음량 바꾸기(&C) + + + + Select the &MPlayer executable: + &MPlayer 실행 파일을 선택하십시요: + + + + &Folder for storing screenshots: + 스크린샷을 저장할 폴더(&F): + + + + &Audio: + 오디오(&A): + + + + &Remember settings for all files (audio track, subtitles...) + 모든 파일에 대한 설정(선택된 오디오 트랙, 자막 등)을 기억(&R) + + + + Su&btitles: + 자막(&B): + + + + &Quality: + 품질(&Q): + + + + Start videos in &fullscreen + 전체 화면에서 동영상 시작(&F) + + + + Disable &screensaver + 화면 보호기 비활성화(&S) + + + + &Default volume: + 기본 음량(&D): + + + + Use s&oftware volume control + 소프트웨어 음량 조절 사용(&O) + + + + Ma&x. Amplification: + 최대 음량 확대(&X): + + + + &AC3/DTS pass-through S/PDIF + S/PDIF 통과 &AC3/DTS + + + + Direct rendering + 직접 렌더링 + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + 만약 선택하면, 직접 렌더링 기능을 사용합니다. (모든 코덱과 영상 출력 드라이버가 지원하지는 않음)<br><b>경고:</b> OSD 및 자막 오류를 일으킬 수 있습니다! + + + + Double buffering + 더블 버퍼링 + + + + D&irect rendering + 직접 렌더링(&I) + + + + Dou&ble buffering + 더블 버퍼링(&B) + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + 더블 버퍼링은 메모리 상에 프레임 2개를 저장하고 하나를 디코드하는 동안 하나를 표시함으로써 깜빡임을 해소합니다. 만약 비활성화되면 OSD에 좋지 않은 영향을 끼칠 수 있지만, OSD 깜빡임을 해소합니다. + + + + &Enable postprocessing by default + 후처리 기본으로 활성화(&E) + + + + Volume &normalization by default + 기본으로 음량 노멀라이즈(&N) + + + + Close when finished + 재생이 끝나면 닫기 + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + 이 옵션이 선택되면, 현재 파일이나 재생 목록이 끝날 때 창이 자동으로 닫힙니다. + + + + 2 (Stereo) + 2개 (스테레오) + + + + 4 (4.0 Surround) + 4개 (4.0 서라운드) + + + + 6 (5.1 Surround) + 6개 (5.1 서라운드) + + + + C&hannels by default: + 기본 채널 수(&H): + + + + &Pause when minimized + 최소화할 때 일시 정지(&P) + + + + Pause when minimized + 최소화할 때 일시 정지 + + + + Enable postprocessing by default + 후처리 기본으로 활성화 + + + + Max. Amplification + 최대 음량 확대 + + + + AC3/DTS pass-through S/PDIF + S/PDIF 통과 AC3/DTS + + + + Volume normalization by default + 기본으로 음량 노멀라이즈 + + + + Maximizes the volume without distorting the sound. + 소리에 왜곡 없이 음량을 최대화합니다. + + + + Default volume + 기본 음량 + + + + Sets the initial volume that new files will use. + 새로운 파일이 기본값으로 사용할 초기 음량을 설정합니다. + + + + Channels by default + 기본 채널 수 + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + 백분율 단위로 최대 음량을 설정하십시요 (기본값: 110). 200을 입력하면 음량을 최대 현재의 2배까지로 조정할 수 있게 해 줍니다. 100 미만의 값은 초기 음량(=100%)이 최대값을 초과하도록 하므로, OSD가 제대로 표시할 수 없습니다. + + + + Uses hardware AC3 passthrough + 하드웨어 AC3 통과 사용 + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + 최대 재생 채널의 개수입니다. MPlayer는 디코더에 오디오를 여기서 지정된 채널 수로 디코드하라고 요청합니다. 그 이후의 과정은 디코더에 달려 있습니다. 이 옵션은 AC3 오디오를 지닌 동영상(예를 들어 DVD)에서만 중요합니다. 그러한 경우 liba52가 기본적으로 디코딩을 수행하여 오디오를 요청된 채널 수대로 하향 믹스합니다. 주의: 이 옵션은 AC3 코덱과 필터(서라운드) 및 오디오 출력 드라이버(최소 OSS)에 의해서만 존중됩니다. + + + + Postprocessing will be used by default on new opened files. + 후처리는 새로 열린 파일에 대해 기본적으로 사용됩니다. + + + + Audio track + 오디오 트랙 + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + 새로운 파일을 재생할 때 사용될 기본 오디오 트랙을 지정합니다. 만약 해당하는 트랙이 존재하지 않으면, 첫 트랙이 사용될 것입니다.<br><b>주의:</b> "사용할 오디오 언어" 옵션이 이 옵션보다 우선적으로 적용됩니다. + + + + Subtitle track + 자막 트랙 + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + 새로운 파일을 재생할 때 사용될 기본 자막 트랙을 지정합니다. 만약 해당하는 트랙이 존재하지 않으면, 첫 트랙이 사용될 것입니다.<br><b>주의:</b> "사용할 자막 언어" 옵션이 이 옵션보다 우선적으로 적용됩니다. + + + + Or choose a track number: + 또는 트랙 번호를 지정하십시요: + + + + Audi&o: + 오디오(&O): + + + + Preferred language: + 사용할 언어: + + + + Preferre&d audio and subtitles + 사용할 오디오 및 자막(&D) + + + + &Subtitle: + 자막(&S): + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + 오디오 및 자막 스트림에 사용할 언어를 지정할 수 있습니다. 만약 사용할 수 있는 오디오 또는 자막 스트림이 여러 개인 경우, SMPlayer는 여기서 지정된 언어를 사용하려고 시도합니다.<br>이 옵션은 DVD나 mkv 파일과 같이 오디오와 자막 스트림의 언어에 대한 정보가 주어지는 미디어 파일에 대해서만 적용됩니다.<br>이 칸에는 정규 표현식을 입력할 수 있습니다. 예를 들어, <b>ko|kr|kor</b>은 <i>ko</i>, <i>kr</i> 및 <i>kor</i>에 대응되는 오디오 트랙을 선택하게 합니다. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + . + + + + High speed &playback without altering pitch + 음조를 변경하지 않고 고속 재생(&P) + + + + High speed playback without altering pitch + 음조를 변경하지 않고 고속 재생 + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + 재생 속도를 음조의 변경 없이 바꿀 수 있도록 합니다. 최소 MPlayer dev-SVN-r24924 버전을 필요로 합니다. + + + + Change volume just before playing + + + + + &Video + 영상(&V) + + + + Use s&oftware video equalizer + + + + + A&udio + + + + + Volume + 음량 + + + + Preferred audio and subtitles + + + + + None + 없음 + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + 키보드 및 마우스 + + + + &Keyboard + 키보드(&K) + + + + icon + 아이콘 + + + + &Mouse + 마우스(&M) + + + + Button functions: + 버튼 기능: + + + + Media seeking + 미디어 지점 이동 + + + + Volume control + 음량 조절 + + + + Zoom video + 영상 확대 + + + + None + 없음 + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + 단축키를 변경할 수 있습니다. 단축키를 변경하려면, 단축키 칸을 두 번 클릭하거나 엔터 키를 누릅니다. 필요하다면, 다른 사람과 공유하거나 다른 컴퓨터로 옮기기 위해 목록을 파일로 저장할 수 있습니다. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + 단축키를 변경할 수 있습니다. 단축키를 변경하려면, 단축키 칸을 두 번 클릭하거나 새 단축키를 누릅니다. 필요하다면, 다른 사람과 공유하거나 다른 컴퓨터로 옮기기 위해 목록을 파일로 저장할 수 있습니다. + + + + &Left click + 왼쪽 클릭(&L) + + + + &Double click + 두 번 클릭(&D) + + + + &Wheel function: + 휠 기능(&W): + + + + Shortcut editor + 단축키 편집기 + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + 이 표는 대부분의 동작에 대한 단축키를 지정하게 해줍니다. 두 번 클릭하거나 엔터 키 혹은 <b>단축키 변경</b> 버튼을 눌러서 <i>단축키 변경</i> 대화 상자에 진입하십시요. 단축키를 변경하는 방법은 <b>입력</b> 버튼을 눌러서 변경할 수 있습니다. 버튼이 눌려진 상태에서는 동작에 배정할 새로운 키 혹은 키 조합을 입력하여 단축키를 변경할 수 있습니다 (모든 키에 대해 동작하지는 않습니다). 만약 <b>입력</b> 버튼이 눌려진 상태가 아니면 키의 전체 이름을 입력하여 단축키를 변경할 수 있습니다. + + + + Left click + 왼쪽 클릭 + + + + Select the action for left click on the mouse. + 왼쪽 클릭에 배정할 동작을 선택하십시요. + + + + Double click + 두 번 클릭 + + + + Select the action for double click on the mouse. + 두 번 클릭에 배정할 동작을 선택하십시요. + + + + Wheel function + 휠 기능 + + + + Select the action for the mouse wheel. + 마우스의 휠에 배정할 동작을 선택하십시요. + + + + Play + 재생 + + + + Pause + 일시 정지 + + + + Stop + 정지 + + + + Fullscreen + 전체 화면 + + + + Compact + 간결히 보기 + + + + Screenshot + 스크린샷 + + + + On top + 항상 위 켜기/끄기 + + + + Mute + 음소거 + + + + Frame counter + 프레임 카운터 + + + + Reset zoom + 배율 초기화 + + + + Exit fullscreen + 전체 화면 나가기 + + + + Double size + 보통/2배 크기 전환 + + + + Play / Pause + 재생 / 일시 정지 + + + + Pause / Frame step + 일시 정지 / 프레임 스텝 + + + + Playlist + 재생 목록 + + + + Preferences + 환경 설정 + + + + No function + 기능 없음 + + + + Change speed + 속도 바꾸기 + + + + Normal speed + + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - 다음 + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + 인터페이스 + + + + <Autodetect> + (자동 감지) + + + + Default + 기본 + + + + &Interface + 인터페이스(&I) + + + + Seeking + 지점 이동 + + + + Never + 하지 않음 + + + + Whenever it's needed + 필요할 때 + + + + Only after loading a new video + 새 동영상을 불러온 후에 + + + + Recent files + 최근에 재생한 파일 + + + + Language + 언어 + + + + Here you can change the language of the application. + 프로그램에서 사용하는 언어를 변경할 수 있습니다. + + + + Instances + 인스턴스 + + + + &Short jump + 짧게 건너뛰기(&S) + + + + &Medium jump + 중간 건너뛰기(&M) + + + + &Long jump + 길게 건너뛰기(&L) + + + + Mouse &wheel jump + 마우스 휠로 건너뛰기(&W) + + + + &Use only one running instance of SMPlayer + SMPlayer에서 인스턴스 한 개만 사용(&U) + + + + Ma&x. items + 최대 항목 수(&X) + + + + St&yle: + 스타일(&Y): + + + + Ico&n set: + 아이콘 셋(&N): + + + + L&anguage: + 언어(&A): + + + + Main window + + + + + Auto&resize: + 자동 크기 바꾸기(&R): + + + + R&emember position and size + 창 위치 및 크기 기억(&E) + + + + Default font: + 기본 글꼴: + + + + &Change... + 변경(&C)... + + + + TextLabel + + + + + &Seeking + + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + 성능 + + + + &Performance + 성능(&P) + + + + Priority + 우선 순위 + + + + Select the priority for the MPlayer process. + MPlayer 프로세스에 대한 우선 순위를 선택하십시요. + + + + realtime + 실시간 + + + + high + 높음 + + + + abovenormal + 보통 이상 + + + + normal + 보통 + + + + belownormal + 보통 이하 + + + + idle + 매우 낮음 + + + + Cache + 캐시 + + + + KB + KB + + + + Setting a cache may improve performance on slow media + 캐시를 설정하면 느린 미디어에서 성능 향상을 기대할 수 있습니다 + + + + Allow frame drop + 프레임 드롭 허용 + + + + Synchronization + 동기화 + + + + Audio/video auto synchronization + 오디오와 영상 자동으로 동기화 + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + MPlayer 프로세스를 윈도우에서 사용 가능한 우선 순위값으로 설정합니다.<br><b>경고:</b> 실시간 우선 순위를 사용하는 경우 시스템이 멈출 수 있습니다. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + 오디오와 영상을 맞추기 위해 느린 시스템에서 일부 프레임을 건너뜁니다. + + + + Allow hard frame drop + 강제 프레임 드롭 허용 + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + 더 강제적인 프레임 드롭(디코딩 끊기)을 적용합니다. 이미지 왜곡을 가져올 수 있습니다! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + 오디오 지연 측정값을 기반으로 오디오와 영상 동기화를 단계적으로 조정합니다. + + + + Priorit&y: + 우선 순위(&Y): + + + + &Allow frame drop + 프레임 드롭 허용(&A) + + + + Allow &hard frame drop (can lead to image distortion) + 강제 프레임 드롭 허용(&H) - 이미지 왜곡 가능성 있음 + + + + Audio/&video auto synchronization + 오디오와 영상 자동으로 동기화(&V) + + + + Fact&or: + 계수(&O): + + + + &Fast audio track switching + 빠른 오디오 트랙 변경(&F) + + + + Fast &seek to chapters in dvds + 빠른 DVD 장 찾기(&S) + + + + Fast audio track switching + 빠른 오디오 트랙 변경 + + + + Fast seek to chapters in dvds + 빠른 DVD 장 찾기 + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + 만약 선택되면, 장을 이동하는 가장 빠른 방법을 시도하지만, 일부 디스크에서는 작동하지 않을 수 있습니다. + + + + Skip loop filter + 반복 필터 무시 + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + 사용할 수 있는 값:<br> <b>예</b>: 오디오 트랙을 변경하는 가장 빠른 방법을 사용합니다 (일부 형식에서는 지원되지 않습니다).<br> <b>아니요</b>: MPlayer 프로세스를 오디오 트랙이 바뀔 때마다 다시 시작합니다.<br> <b>자동</b>: SMPlayer가 MPlayer의 버전에 따라 자동으로 결정합니다. + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + Loop &filter + + + + + &Cache + + + + + Cache for &DVDs: + + + + + Cache for &local files: + + + + + Cache for &streams: + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + 재생 목록 + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + 재생 목록(&P) + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + 자막 + + + + Choose a ttf file + TTF 파일을 선택하십시요 + + + + Truetype Fonts + 트루타입 글꼴 + + + + &Subtitles + 자막(&S) + + + + Autoload + 자동으로 불러오기 + + + + Same name as movie + 동영상과 같은 이름 + + + + All subs containing movie name + 동영상의 이름을 포함하는 모든 자막 + + + + All subs in directory + 폴더에 있는 모든 자막 + + + + Position + 위치 + + + + 0 + 0 + + + + Top + + + + + Bottom + 아래 + + + + Font + 글꼴 + + + + Select the font which will be used for subtitles (and OSD): + 자막과 OSD에서 사용될 글꼴을 선택하십시요: + + + + Size + 크기 + + + + No autoscale + 본래 크기 유지 + + + + Proportional to movie height + 영상 세로 길이에 어울림 + + + + Proportional to movie width + 영상 가로 길이에 어울림 + + + + Proportional to movie diagonal + 영상 대각선 길이에 어울림 + + + + Subtitle position + 자막 위치 + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + 이 옵션은 영상 창에서 자막의 위치를 결정합니다. 가장 아래는 <i>100</i>이며, 가장 위는 <i>0</i>을 사용하여 지정합니다. + + + + Au&toload subtitles files (*.srt, *.sub...): + 자막 파일(*.srt, *.sub...) 자동으로 불러오기(&T): + + + + S&elect first available subtitle + 사용 가능한 첫 자막 파일 선택(&E) + + + + &Default subtitle encoding: + 기본 자막 인코딩(&D): + + + + Default &position of the subtitles on screen + 자막의 기본 위치(&P) + + + + &Include subtitles on screenshots + 스크린샷에 자막 포함(&I) + + + + &TTF font: + &TTF 글꼴: + + + + S&ystem font: + 시스템 글꼴(&Y): + + + + A&utoscale: + 크기 맞춤(&U): + + + + Select first available subtitle + + + + + Default subtitle encoding + + + + + Include subtitles on screenshots + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + 아래 + + + + Middle + vertical alignment + + + + + Top + vertical alignment + + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - 도움말 + + + + OK + 확인 + + + + Cancel + 취소 + + + + Apply + 적용 + + + + Help + 도움말 + + + + SMPlayer - Preferences + SMPlayer - 환경 설정 + + + + QObject + + + will show this message and then will exit. + 이 메시지를 표시하고 종료합니다. + + + + the main window will be closed when the file/playlist finishes. + 파일이나 재생 목록이 끝나면 창이 닫힙니다. + + + + This is SMPlayer v. %1 running on %2 + SMPlayer 버전 %1 - %2에서 실행 중 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + 다른 실행 중인 인스턴스에 연결을 시도하고 명시된 동작을 지시합니다. (예: -send-action pause) 다른 옵션이 있을 경우 무시되며 프로그램은 종료합니다. 프로그램은 성공시 0, 실패시 -1을 반환합니다. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list는 띄어쓰기로 구분되는 동작의 목록입니다. 이 동작들은 파일을 불러온 직후에 입력된 순서대로 실행됩니다. 선택 지정할 수 있는 동작은 참(true) 혹은 거짓(false)을 매개 변수로 넘길 수 있습니다. (예: -actions "fullscreen compact true") 하나 이상의 동작을 지정할 경우에는 양쪽 끝에 쌍따옴표(")를 달아 주어야 합니다. + + + + media + 미디어 + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + 만약 다른 인스턴스가 실행 중이면, 미디어는 해당 인스턴스의 재생 목록에 자동으로 추가됩니다. 다른 인스턴스가 없으면, 이 옵션은 무시되며 파일은 새로운 인스턴스에서 열립니다. + + + + the main window won't be closed when the file/playlist finishes. + 파일이나 재생 목록이 끝나도 창이 닫히지 않습니다. + + + + the video will be played in fullscreen mode. + 동영상이 전체 화면에서 재생됩니다. + + + + the video will be played in window mode. + 동영상이 창에서 재생됩니다. + + + + Enqueue in SMPlayer + SMPlayer 재생 목록에 추가 + + + + opens the mini gui instead of the default one. + 기본 GUI 대신 소형 GUI를 사용합니다. + + + + directory + + + + + action_name + + + + + action_list + + + + + Usage: + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + 아이콘 + + + + label + 레이블 + + + + ShortcutGetter + + + Modify shortcut + 단축키 변경 + + + + Clear + 지우기 + + + + Press the key combination you want to assign + 배정하고 싶은 키 조합을 누르십시요 + + + + Capture + 입력 + + + + Capture keystrokes + 키 입력하기 + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + 모두 선택 + + + + Select None + 모두 선택 해제 + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + 자동 + + + + Yes + + + + + No + 아니요 + + + + VideoEqualizer + + + Contrast + 대비 + + + + Brightness + 밝기 + + + + Hue + 색조 + + + + Saturation + 채도 + + + + Gamma + 감마 + + + + &Reset + 초기화(&R) + + + + &Set as default values + 기본값으로 설정하기(&S) + + + + Use the current values as default values for new videos. + 다른 영상에서도 현재 설정값을 기본으로 지정합니다. + + + + Set all controls to zero. + 모두 0으로 설정합니다. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + 취소 + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + 파일 저장 오류 + + + + The file couldn't be saved + 파일 저장에 실패하였습니다 + + + + Error + 오류 + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + 기본 + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + 음량 + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_ku.ts b/plugins/smplayer_plugin/translations/smplayer_ku.ts new file mode 100644 index 000000000..999d5d8ee --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_ku.ts @@ -0,0 +1,7328 @@ + + + + About + + + Version: %1 + Versiyon: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Ev bername nivîsbariyek azad e; bin lîsansa giştî ya GNU hûn dikarin wê biguherînin, belav bikin. Weşan ji aliyê Free Software Foundation; guhertoya 2 ya lîsansê an jî guhertoyek nûtir. + + + + The following people have contributed with translations: + Mirovên li jêr bi wergêriyê piştgirî dan: + + + + German + Elmanî + + + + Slovak + + + + + Italian + Îtalyanî + + + + French + Fransî + + + + %1, %2 and %3 + %1, %2 û %3 + + + + Simplified-Chinese + Simplified-Chinese + + + + Russian + Rusî + + + + %1 and %2 + %1 û %2 + + + + Hungarian + Macarî + + + + Polish + Polish + + + + Japanese + Japonî + + + + Dutch + Dutch + + + + Ukrainian + Ukrainian + + + + Portuguese - Brazil + Portegîz - Brazil + + + + Georgian + Georgian + + + + Czech + Czech + + + + Bulgarian + Bulgarî + + + + Turkish + Tirkî + + + + Swedish + Swêdî + + + + Serbian + Sirbî + + + + Traditional Chinese + Çîniya Gelerî + + + + Romanian + Romanî + + + + Portuguese - Portugal + Portuguese - Portugal + + + + Greek + Yewnanî + + + + Finnish + Finnish + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Dermafê SMPlayer + + + + &Info + &Agahî + + + + icon + îcon + + + + &Contributions + &Piştgirî + + + + &Translators + &Wergêr + + + + &License + &Lîsans + + + + Visit our web for updates: + Ji rojanekirinê herin malpera me: + + + + Get help in our forum: + Ji foruma me alîkarî bistîne: + + + + You can support SMPlayer by making a donation. + Bi alîkariyên pereyî hûn dikarin piştgirî bidin SMPlayer. + + + + More info + Agahiya Zêdetir + + + + Korean + Kareyî + + + + Macedonian + Macedonian + + + + Basque + Basque + + + + Using MPlayer %1 + MPlayer bi kar tîne %1 + + + + Catalan + Catalan + + + + Portable Edition + Guhertoya Portatîf + + + + Using Qt %1 (compiled with Qt %2) + Qt bi kar tîne %1 (compiled with Qt %2) + + + + Slovenian + Slovenî + + + + Arabic + Erebî + + + + Kurdish + Kurdîsh - Kurdî + + + + Galician + Galician + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Name + + + + Description + Ravekirin + + + + Shortcut + Kurterê + + + + &Save + &tomar bike + + + + &Load + &Bar bike + + + + Key files + Pelên Şîfreyê + + + + Choose a filename + Navê pelê hilbijêrin + + + + Confirm overwrite? + Bila li ser binivîse? + + + + The file %1 already exists. +Do you want to overwrite? + Pela %1 ji xwe heye. +Tu dixwazî li ser binivîsî? + + + + Choose a file + Pelek Hilbijêre + + + + Error + Çewtî + + + + The file couldn't be saved + Pel nehat tomarkirin + + + + The file couldn't be loaded + Pel nehat barkirin + + + + &Change shortcut... + &Kurteryan biguhere... + + + + AudioEqualizer + + + Audio Equalizer + Ekolayzira Deng + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 250.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Bisepîne + + + + &Reset + &Vegerîne Destpêkê + + + + &Set as default values + &Nirxek rast mîheng bike + + + + Use the current values as default values for new videos. + Ji bo vîdyoyên nû nirxên heyî bi kar bîne. + + + + Set all controls to zero. + Hemû kontrolan bike sifir. + + + + Information + Agahî + + + + The current values have been stored to be used as default. + Nirxên heyî wekî nirxên bixweber hat tomar kirin. + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer log + + + + SMPlayer - smplayer log + SMPlayer - smplayer log + + + + &Open + &Veke + + + + &Play + &Bilîze + + + + &Video + &Vîdyo + + + + &Audio + &Deng + + + + &Subtitles + &Binnivîs + + + + &Browse + &Bibîne + + + + Op&tions + Ve&bijêrk + + + + &Help + &Alikarî + + + + &File... + &Pel... + + + + D&irectory... + C&ih... + + + + &Playlist... + &Lîsteya Lêdanê... + + + + &DVD from drive + &Ji ajokerê DVD + + + + D&VD from folder... + D&VD Ji peldankê... + + + + &URL... + &URL... + + + + &Clear + &Paqij bike + + + + &Recent files + &Pelên Dawîn + + + + P&lay + B&ilîze + + + + &Pause + &Raweste + + + + &Stop + &Bisekine + + + + &Frame step + &Frame step + + + + &Normal speed + &Leza Normal + + + + &Halve speed + &Lezê bike nîvî + + + + &Double speed + &Leza duqet + + + + Speed &-10% + Lez &-10% + + + + Speed &+10% + Lez &+10% + + + + Sp&eed + Le&z + + + + &Repeat + &Dubare + + + + &Fullscreen + &Dîmender Tijî + + + + &Compact mode + &Moda Kompakt + + + + Si&ze + Mezi&nahî + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &li 16:9 + + + + &Aspect ratio + &Mezinahiya Dîmenê + + + + &None + &Ne yek jî + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Linear &Blend + + + + &Deinterlace + &Deinterlace + + + + &Postprocessing + &Piştîxebatkirinê + + + + &Autodetect phase + &Astê bixweber nas ike + + + + &Deblock + &Asê neke + + + + De&ring + De&ring + + + + Add n&oise + Xîrecir lê& zêdeke + + + + F&ilters + F&îltre + + + + &Equalizer + &Ekolayzir + + + + &Screenshot + &WêneKişandin + + + + S&tay on top + Li& pêş bimîne + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Fîltre + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Qenal + + + + &Left channel + &Qenala çepê + + + + &Right channel + &Qenala rastê + + + + &Stereo mode + &Moda Stereo + + + + &Mute + &Bêdeng + + + + Volume &- + Deng &- + + + + Volume &+ + Deng &+ + + + + &Delay - + &Dereng - + + + + D&elay + + D&ereng + + + + + &Select + &Hilbijêre + + + + &Load... + &Bar bike... + + + + Delay &- + Dereng &- + + + + Delay &+ + Dereng &+ + + + + &Up + &jor + + + + &Down + &Jêr + + + + &Title + &Sernav + + + + &Chapter + &Beş + + + + &Angle + &Angle + + + + &Playlist + &Lîsteya Lêdanê + + + + &Show frame counter + &Hejmarkera dîmenê nîşan bide + + + + &Disabled + &Neçalak + + + + &Seek bar + &Darika lêgerînê + + + + &Time + &Dem + + + + Time + T&otal time + Dem+D&ema Giştî + + + + &OSD + &OSD + + + + &View logs + &Logan binêre + + + + P&references + V&ebijêrk + + + + About &Qt + Dermafê &Qt + + + + About &SMPlayer + Dermafê &SMPlayer + + + + <empty> + <vala> + + + + Video + Vîdyo + + + + Audio + Deng + + + + Playlists + Lîsteya Lêdanê + + + + All files + Hemû Pel + + + + Choose a file + Pelek Hilbijêre + + + + SMPlayer - Information + SMPlayer - Agahî + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Ajokerên CDROM / DVD hê nehatine mîhengkirin. +Niha wê peyama mîhengkirinê xuya bibe û hûn dikarên mîheng bikin. + + + + Choose a directory + Cihek Hilbijêre + + + + Subtitles + Binnivîs + + + + About Qt + Dermafê Qt + + + + Playing %1 + Lê Dide %1 + + + + Pause + Raweste + + + + Stop + Bisekine + + + + Play / Pause + Bilîze / Raweste + + + + Pause / Frame step + Raweste / Sekna Dîmenê + + + + U&nload + B&ar neke + + + + V&CD + V&CD + + + + C&lose + Bi&gire + + + + View &info and properties... + Agahî û &taybetiyan bibîne... + + + + Zoom &- + Dûr bibe &- + + + + Zoom &+ + Nêzik bibe &+ + + + + &Reset + &Vegerîne Destpêkê + + + + Move &left + Veguheze &çep + + + + Move &right + Veguheze &rast + + + + Move &up + Veguheze &jor + + + + Move &down + Veguheze &jêr + + + + &Pan && scan + &Bejing && Lênêrîn + + + + &Previous line in subtitles + &Rêzikek berê ya binnivîsê + + + + N&ext line in subtitles + R&êzikek pêş ya binnivîsê + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Dengê Kêmke (2) + + + + Inc volume (2) + Dengê zêdeke (2) + + + + Exit fullscreen + Ji dîmender tijî derkeve + + + + OSD - Next level + OSD - Next level + + + + Dec contrast + Kontrastê Kêmke + + + + Inc contrast + Kontrastê Zêdeke + + + + Dec brightness + Brightness Kêmke + + + + Inc brightness + Brightness Zêdeke + + + + Dec hue + Hue kêmke + + + + Inc hue + Hue zêdeke + + + + Dec saturation + Saturasyonê Kêmke + + + + Dec gamma + Gammayê Kêmke + + + + Next audio + Dengê piştî + + + + Next subtitle + Binnivîsa piştî + + + + Next chapter + Beşa piştî + + + + Previous chapter + Beşa berê + + + + Inc saturation + Saturasyonê zêdeke + + + + Inc gamma + Gammayê zêdeke + + + + &Load external file... + &Pelek derveyî barke... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normal) + + + + Y&adif (double framerate) + &Yadif (normal) + + + + &Next + &Ya piştî + + + + Pre&vious + Ya b&erê + + + + Volume &normalization + Normalkirina &Dengê + + + + &Audio CD + &CDya Dengê + + + + Denoise nor&mal + Denoise nor&mal + + + + Denoise &soft + Denoise &soft + + + + Denoise o&ff + Denoise o&ff + + + + Use SSA/&ASS library + Arşîva SSA/&ASS bi kar bîne + + + + Flip i&mage + Wêneyê b&izivirîne + + + + &Toggle double size + &Toggle du caran mezin + + + + S&ize - + M&ezinahî - + + + + Si&ze + + M&ezinahî + + + + + Add &black borders + Kêlekên reş &lê zêdeke + + + + Soft&ware scaling + Soft&ware scaling + + + + &FAQ + &Pirsên pir tên pirsîn + + + + Visualize &motion vectors + Visualize &motion vectors + + + + &Command line options + &Vebijêrka rêzika fermanan + + + + SMPlayer command line options + SMPlayer vebijêrka rêzika fermanan + + + + Enable &closed caption + Enable &closed caption + + + + &Forced subtitles only + &Forced subtitles only + + + + Reset video equalizer + Ekolayzira vîdyoyê bike wekî destpêkê + + + + MPlayer has finished unexpectedly. + MPlayer bi awayekî nedihat hêvîkirin xelas kir. + + + + Exit code: %1 + Koda derketinê: %1 + + + + MPlayer failed to start. + MPlayer destpê nekir. + + + + Please check the MPlayer path in preferences. + Di vebijêrkê de cihê MPlayer kontrol bike. + + + + MPlayer has crashed. + MPlayerê lê xist. + + + + See the log for more info. + Ji bo agahiya zêdetir logê bibîne. + + + + &Rotate + &Bizivirîne + + + + &Off + &Girtî + + + + &Rotate by 90 degrees clockwise and flip + &Aliyê saetê de 90 derece bizivirîne and flip + + + + Rotate by 90 degrees &clockwise + Aliyê saetê de 90 derece &bizivirîne + + + + Rotate by 90 degrees counterclock&wise + &Aliyê berevajiyê saetê de 90 derece bizivirîne + + + + Rotate by 90 degrees counterclockwise and &flip + &Aliyê berevajiyê saetê de 90 derece bizivirîne and flip + + + + &Jump to... + &Here li... + + + + Show context menu + Show context menu + + + + Multimedia + Multimedia + + + + E&qualizer + E&kolayzir + + + + Reset audio equalizer + Ekolayzira dengê bike wekî destpêkê + + + + Find subtitles on &OpenSubtitles.org... + Binnivîs bibîne li &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Li OpenSubtitles.org bi&nnivîs barke... + + + + &Tips + &Tips + + + + &Auto + &Bixweber + + + + Speed -&4% + Lez -&4% + + + + &Speed +4% + &Lez +4% + + + + Speed -&1% + Lez -&1% + + + + S&peed +1% + L&ez +1% + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &Hêman + + + + &Track + audio + &Hêman + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer li vir hê dixebite + + + + S&how icon in system tray + S&how icon in system tray + + + + &Hide + &Veşêre + + + + &Restore + &Vegerîne Destpêkê + + + + &Quit + &Derkeve + + + + Playlist + Lîsteya Lêdanê + + + + Core + + + Brightness: %1 + Brightness: %1 + + + + Contrast: %1 + Contrast: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Hue: %1 + + + + Saturation: %1 + Saturation: %1 + + + + Volume: %1 + Deng: %1 + + + + Zoom: %1 + Nêzik: 1 + + + + Font scale: %1 + Mezinahiya nivîsê: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Bi xêr hatî SMplayerê + + + + Audio + Deng + + + + Subtitle + Binnivîs + + + + &Main toolbar + &Darika Amûran a Bingehîn + + + + &Language toolbar + &Darikê Amûran a Zimên + + + + &Toolbars + &Darikên Amûran + + + + EqSlider + + + icon + îcon + + + + ErrorDialog + + + Hide log + Log veşêre + + + + Show log + Log nîşan bide + + + + MPlayer Error + MPlayer Çewtî + + + + icon + îcon + + + + Error + Çewtî + + + + FileDownloader + + + Downloading... + Dadixe... + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Taybetiyên pelê + + + + &Information + &Agahî + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Ji bo ku vê pelê de bê bikaranîn demuxer hilbijêre: + + + + &Reset + &Bike wekî destpêkê + + + + &Video codec + &Kodeka Vîdyoyê + + + + &Select the video codec: + &Kodeka vîdyoyê hilbijêre: + + + + A&udio codec + Ko&deka Dengê + + + + &Select the audio codec: + &Kodeka dengê hilbijêre: + + + + &MPlayer options + &MPlayer vebijêrk + + + + Additional Options for MPlayer + Ji bo MPlayer vebijêrkên pêvek + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Here you can pass extra options to MPlayer.(new line) +Write them separated by spaces.(new line) +Example: -flip -nosound + + + + &Options: + &Vebijêrk: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + You can also pass additional video filters.(new line) +Separate them with ",". Do not use spaces!(new line) +Example: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + Fîltreyên V&îdyoyê: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + And finally audio filters. Same rule as for video filters.(new line) +Example: resample=44100:0:0,volnorm + + + + Audio &filters: + Fîltreyên &dengê: + + + + OK + Temam + + + + Cancel + Betal + + + + Apply + Bisepîne + + + + FindSubtitlesWindow + + + Language + Ziman + + + + Name + Nav + + + + Format + Format + + + + Files + Pel + + + + Date + Dîrok + + + + Uploaded by + Kê bar kir + + + + All + Hemû + + + + Close + Bigire + + + + &Download + &Daxe + + + + &Copy link to clipboard + &Girêdanê ji ber bigire + + + + Error + Çewtî + + + + Download failed: %1. + Daxistin têk çû: %1. + + + + Connecting to %1... + Tê girêdan bi %1... + + + + Downloading... + Dadixe... + + + + Done. + Qediya. + + + + %1 files available + %1 pel amade ye + + + + Failed to parse the received data. + Failed to parse the received data. + + + + Find Subtitles + Binnivîs Bibîne + + + + &Subtitles for + &Binnivîs ji bo + + + + &Language: + &Ziman: + + + + &Refresh + &Nû bike + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Tomarkirinê de çewtî + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Giştî + + + + Size + Mezinahî + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Dirêjahî + + + + Demuxer + Demuxer + + + + Name + Nav + + + + Artist + Stranbêj + + + + Author + Nivîskar + + + + Album + Albûm + + + + Genre + Cure + + + + Date + Dîrok + + + + Track + Hêman + + + + Copyright + Lîsans + + + + Comment + Nirxandin + + + + Software + Nivîsbarî + + + + Clip info + Agahiya Klîpê + + + + Video + Vîdyo + + + + Resolution + Resolution + + + + Aspect ratio + Mezinahiya Dîmenê + + + + Format + Format + + + + Bitrate + Bitrate + + + + %1 kbps + %1 kbps + + + + Frames per second + Dîmena her çirkeyê de + + + + Selected codec + Kodek Hilbijêre + + + + Initial Audio Stream + Initial Audio Stream + + + + Rate + Stêr + + + + %1 Hz + %1 Hz + + + + Channels + Qenal + + + + Audio Streams + Audio Streams + + + + Language + Ziman + + + + empty + vala + + + + Subtitles + Binnivîs + + + + Type + Cure + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Sernavê Stream + + + + Stream URL + URLya Stream + + + + File + Pel + + + + InputDVDDirectory + + + Choose a directory + Cih Hilbijêre + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Ji peldankek DVD bilezîne + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Hûn dikarin ji harddîskê DVD tamaşe bikin. Tenê peldanka ku tê de VIDEO_TS û AUDIO_TS hene, hilbijêrin. + + + + Choose a directory... + Cihek hilbijêre... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Guhertoya MPlayerê têkevin + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMplayerê guhertoya we ya MPlayerê nas nekir. + + + + Version reported by MPlayer: + Guhertiya ji aliyê MPlayerê ve hat raporkirin: + + + + Please, &select the correct version: + Ji kerema xw re, guhertoya rast &hilbijêrin: + + + + 1.0rc1 or older + 1.0rc1 an jî kevintir + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Ji 1.0r2 mezintir + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - URL têkeve + + + + &URL: + &URL: + + + + It's a &playlist + Ev &lîsteyek lêdanê ye + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Ger hûn vê hilbijêrin, ev URL wê wekî lîsteya lêdanê bê hesibandin: wê wekî text bê vekirin û URLyên tê de bilezîne. + + + + Languages + + + Afar + Afar + + + + Abkhazian + Abkhazian + + + + Afrikaans + Afrikaans + + + + Amharic + Amharic + + + + Arabic + Arabic + + + + Assamese + Assamese + + + + Aymara + Aymara + + + + Azerbaijani + Azerbaijani + + + + Bashkir + Bashkir + + + + Byelorussian + Byelorussian + + + + Bulgarian + Bulgarian + + + + Bihari + Bihari + + + + Bislama + Bislama + + + + Bengali + Bengali + + + + Tibetan + Tibetan + + + + Breton + Breton + + + + Catalan + Catalan + + + + Corsican + Corsican + + + + Czech + Czech + + + + Welsh + Welsh + + + + Danish + Danish + + + + German + Elmanî + + + + Bhutani + Bhutani + + + + Greek + Yewnanî + + + + English + English - Îngîlîzî + + + + Esperanto + Esperanto + + + + Spanish + Spanish + + + + Estonian + Estonian + + + + Basque + Basque + + + + Persian + Persian + + + + Finnish + Finnish + + + + Fiji + Fiji + + + + Faroese + Faroese + + + + French + French + + + + Frisian + Frisian + + + + Irish + Irish + + + + Scots + Scots + + + + Galician + Galician + + + + Guarani + Guarani + + + + Gujarati + Gujarati + + + + Hausa + Hausa + + + + Hebrew + Hebrew + + + + Hindi + Hindi + + + + Croatian + Croatian + + + + Hungarian + Hungarian + + + + Armenian + Armenian + + + + Interlingua + Interlingua + + + + Indonesian + Indonesian + + + + Interlingue + Interlingue + + + + Inupiak + Inupiak + + + + Icelandic + Icelandic + + + + Italian + Italian + + + + Inuktitut + Inuktitut + + + + Japanese + Japanese + + + + Javanese + Javanese + + + + Georgian + Georgian + + + + Kazakh + Kazakh + + + + Greenlandic + Greenlandic + + + + Cambodian + Cambodian + + + + Kannada + Kannada + + + + Korean + Korean + + + + Kashmiri + Kashmiri + + + + Kurdish + Kurdîsh - Kurdî + + + + Kirghiz + Kirghiz + + + + Latin + Latin + + + + Lingala + Lingala + + + + Laothian + Laothian + + + + Lithuanian + Lithuanian + + + + Latvian + Latvian + + + + Malagasy + Malagasy + + + + Maori + Maori + + + + Macedonian + Macedonian + + + + Malayalam + Malayalam + + + + Mongolian + Mongolian + + + + Moldavian + Moldavian + + + + Marathi + Marathi + + + + Malay + Malay + + + + Maltese + Maltese + + + + Burmese + Burmese + + + + Nauru + Nauru + + + + Nepali + Nepali + + + + Dutch + Dutch + + + + Norwegian + Norwecî + + + + Occitan + Occitan + + + + Oriya + Oriya + + + + Punjabi + Punjabi + + + + Polish + Polish + + + + Pashto + Pashto + + + + Portuguese + Portuguese + + + + Quechua + Quechua + + + + Kirundi + Kirundi + + + + Romanian + Romanî + + + + Russian + Rusî + + + + Kinyarwanda + Kinyarwanda + + + + Sanskrit + Sanskrit + + + + Sindhi + Sindhi + + + + Sangho + Sangho + + + + Sinhalese + Sinhalese + + + + Slovak + Slovak + + + + Slovenian + Slovenian + + + + Samoan + Samoan + + + + Shona + Shona + + + + Somali + Somali + + + + Albanian + Albanian + + + + Serbian + Serbian + + + + Siswati + Siswati + + + + Sesotho + Sesotho + + + + Sundanese + Sundanese + + + + Swedish + Swedish + + + + Swahili + Swahili + + + + Tamil + Tamil + + + + Telugu + Telugu + + + + Tajik + Tajik + + + + Thai + Thai + + + + Tigrinya + Tigrinya + + + + Turkmen + Turkmen + + + + Tagalog + Tagalog + + + + Setswana + Setswana + + + + Tonga + Tonga + + + + Turkish + Tirkî + + + + Tsonga + Tsonga + + + + Tatar + Tatar + + + + Twi + Twi + + + + Uighur + Uighur + + + + Ukrainian + Ukrainian + + + + Urdu + Urdu + + + + Uzbek + Uzbek + + + + Vietnamese + Vietnamese + + + + Wolof + Wolof + + + + Xhosa + Xhosa + + + + Yiddish + Yiddish + + + + Yoruba + Yoruba + + + + Zhuang + Zhuang + + + + Chinese + Chinese + + + + Zulu + Zulu + + + + Portuguese - Brazil + Portuguese - Brazil + + + + Portuguese - Portugal + Portuguese - Portugal + + + + Simplified-Chinese + Simplified-Chinese + + + + Traditional Chinese + Traditional Chinese + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + Western European Languages + + + + Western European Languages with Euro + Western European Languages with Euro + + + + Slavic/Central European Languages + Slavic/Central European Languages + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galician, Maltese, Turkish + + + + Old Baltic charset + Old Baltic charset + + + + Cyrillic + Cyrillic + + + + Modern Greek + Modern Greek + + + + Baltic + Baltic + + + + Celtic + Celtic + + + + Hebrew charsets + Hebrew charsets + + + + Ukrainian, Belarusian + Ukrainian, Belarusian + + + + Simplified Chinese charset + Simplified Chinese charset + + + + Traditional Chinese charset + Traditional Chinese charset + + + + Japanese charsets + Japanese charsets + + + + Korean charset + Korean charset + + + + Thai charset + Thai charset + + + + Cyrillic Windows + Cyrillic Windows + + + + Slavic/Central European Windows + Slavic/Central European Windows + + + + Arabic Windows + Arabic Windows + + + + Rhaeto-Romance + Rhaeto-Romance + + + + Serbo-Croatian + Serbo-Croatian + + + + Volapük + Volapük + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Ji bo tomarkirinê navê pelê hilbijêrin + + + + Confirm overwrite? + Sernivîsandinê erê bike? + + + + The file already exists. +Do you want to overwrite? + Pel jixwe heye. +Tu dixwazî biguherînî? + + + + Error saving file + Tomarkirinê de çewtî + + + + The log couldn't be saved + Log nehat tomarkirin + + + + Logs + Log + + + + LogWindowBase + + + Log Window + Paceya log + + + + Save + Tomar bike + + + + Copy to clipboard + Ji ber bigire + + + + &Close + &Bigire + + + + Close + Bigire + + + + MiniGui + + + Control bar + Darika Kontrolê + + + + MpcGui + + + Control bar + Darika Kontrolê + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nav + + + + Length + Dirêjahî + + + + &Play + &Bilîze + + + + &Edit + &Biguhere + + + + Playlists + Lîsteya Lêdanê + + + + Choose a file + Pelek Hilbijêre + + + + Choose a filename + Navê pelê hilbijêre + + + + Confirm overwrite? + Guhertinê erê bike? + + + + The file %1 already exists. +Do you want to overwrite? + Pela 1 jixwe heye +Tu dixwazî biguherî? + + + + All files + Hemû pel + + + + Select one or more files to open + Ji bo vekirinê pelek an jî zêdetir pel hilbijêrin + + + + Choose a directory + Cihek hilbijêre + + + + Edit name + Nav biguhere + + + + Type the name that will be displayed in the playlist for this file: + Ji bo vê pelê navek binivîse ku di lîsteya lêdanê de bê dîtin: + + + + &Load + &Bar bike + + + + &Save + &Tomar Bike + + + + &Next + &Ya Piştî + + + + Pre&vious + Ya &berê + + + + Move &up + Veguheze &jor + + + + Move &down + Veguheze &jêr + + + + &Repeat + &Dubare + + + + S&huffle + Çawa&lêhato + + + + Add &current file + Pela &heyî lê zêdeke + + + + Add &file(s) + Pelan &lê zêdeke + + + + Add &directory + Cihek &lê zêdeke + + + + Remove &selected + Yê &nîşankirî jê bibe + + + + Remove &all + Hemûyan &jê bibe + + + + SMPlayer - Playlist + SMPlayer - Lîsteya Lêdanê + + + + Add... + Lê zêdeke... + + + + Remove... + Rake... + + + + Playlist modified + Lîsteya lêdanê hat sererastkirin + + + + There are unsaved changes, do you want to save the playlist? + Guhertinên tomarnekirî hene, tu dixwazî lîsteyê tomar bikî? + + + + Preferences + Vebijêrk + + + + PlaylistPreferences + + + Playlist - Preferences + Lîsteya Lêdanê - Vebijêrk + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + &Add files in directories recursively + &Pelê di peldankê de bi nûkirin lê zêde bike + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + Automatically get &info about files added + Dermafê pelê lê hatine zêdekirin bixweber &agahî bistîne + + + + &Save copy of playlist on exit + &Ber derketinê re nimûneyekê lîsteyê bistîne + + + + &Play files from start + &Pelan ji destpêkê bide destpêkirin + + + + PrefAdvanced + + + Advanced + Pêşketî + + + + Auto + Bixweber + + + + &Advanced + &Pêşketî + + + + icon + îcon + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + + + + Log MPlayer output + Log derketiya MPlayer + + + + Log SMPlayer output + Log derketiya SMPlayer + + + + This option is mainly intended for debugging the application. + This option is mainly intended for debugging the application. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + + + + Filter for SMPlayer logs + Ji bo logên SMPlayer fîltre + + + + &Monitor aspect: + &Mezinahiya monitorê: + + + + &Run MPlayer in its own window + &Mplayerê di paeya wê xwe de bixebitîne + + + + &Options: + &Vebijêrk: + + + + V&ideo filters: + Fîltreyên V&îdyoyê: + + + + Audio &filters: + Fîltreyên D&eng: + + + + &Colorkey: + &Colorkey: + + + + Log &SMPlayer output + Log &derketiya SMPlayer + + + + &Filter for SMPlayer logs: + &Ji bo logên SMPlayer fîltre: + + + + C&hange... + G&uhertin... + + + + Logs + Log + + + + Log MPlayer &output + Log MPlayer &output + + + + Options for MP&layer + Vebijêrkên MP&layer + + + + Autosave MPlayer log + Logên MPlayer bixweber tomarke + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + Autosave MPlayer log filename + Navê pelên MPlayer bixweber tomarke + + + + Enter here the path and filename that will be used to save the MPlayer log. + Enter here the path and filename that will be used to save the MPlayer log. + + + + A&utosave MPlayer log to file + A&utosave MPlayer log to file + + + + Pass short filenames (8+3) to MPlayer + Pass short filenames (8+3) to MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + &Pass short filenames (8+3) to MPlayer + &Pass short filenames (8+3) to MPlayer + + + + Monitor aspect + Mezinahiya Monîtorê + + + + Select the aspect ratio of your monitor. + Mezinahiya monitora xwe hilbijêrin. + + + + Run MPlayer in its own window + MPlayerê di paeya wê xwe de bixebitînin + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + Colorkey + Colorkey + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + Options for MPlayer + Vebijêrkên MPlayer + + + + Options + Vebijêrk + + + + Here you can type options for MPlayer. Write them separated by spaces. + Li vir hûn dikarin vebijêrkên MPlayer sererast bikin. Bi valahiyê ji hev veqetînin. + + + + Video filters + Fîltreyên Vîdyoyê + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Li vir hûn dikarin fîltreyên vîdyoyê li MPlayerê zêde bikin. Bi vîrgûlan ji hev veqetînin. Valahî bi kar neynin! + + + + Audio filters + Fîltreyên Deng + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Li vir hûn dikarin fîltreyên dengê li MPlayerê zêde bikin. Bi vîrgûlan ji hev veqetînin. Valahî bi kar neynin! + + + + Repaint the background of the video window + Repaint the background of the video window + + + + Repaint the backgroun&d of the video window + Repaint the backgroun&d of the video window + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + Network Connection + Girêdana Înternetê + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + Lo&gs + + + + Rebuild index if needed + Ger pêwist be ji nû ve ava bike + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + + + + Rebuild &index if needed + Ger pêwist be &indexê ji nû ve ava bike + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Cure + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Hişyarî + + + + Not all files could be associated. Please check your security permissions and retry. + Not all files could be associated. Destûra xwe ya ewlehiyê kontrol bikin û dîsa bieribînin. + + + + File Types + Cureyên Pelan + + + + Select all + Hemûyan Hilbijêre + + + + Check all file types in the list + Hemû cureyên pelan di lîsteyê de nîşan bike + + + + Uncheck all file types in the list + Nîşana hemû cureyên pelan di lîsteyê de rake + + + + List of file types + Lîsteya cureyan + + + + File types + Cureyên pelan + + + + Media files handled by SMPlayer: + Media files handled by SMPlayer: + + + + Select All + Hemûyan Hilbijêre + + + + Select None + Tu tişt hilnebijêre + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + Select none + Tu tişt hilnebijêre + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + PrefDrives + + + Drives + Ajoker + + + + icon + îcon + + + + CD device + Amûra CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + CDROM hilbijêre. Ev ji bo lêdana VD û Dyên dengê bê bikaranîn. + + + + DVD device + Amûra DVD + + + + Choose your DVD device. It will be used to play DVDs. + Amûra DVD hilbijêre. Wê ji bo lêdana DVDyan bê bikaranîn. + + + + Select your &CD device: + Amûra xwe ya &CD hilbijêre: + + + + Select your &DVD device: + Amûra xwe ya &DVD hilbijêre: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMplayer bixweber tu amûrê CDROM û DVD hilnabijêre. Lewma beriya lêdana wan amûrên ku hûn dixwazin hilbijêrin (arina dikarin wek hev bin). + + + + PrefGeneral + + + General + Giştî + + + + &General + &Giştî + + + + Paths + Cih + + + + Media settings + Vebijêrkên Media + + + + Start videos in fullscreen + Vîdyoyan dîmender tijî bide destpêkirin + + + + Disable screensaver + Dîmenparêzê neçalak bike + + + + Select the mplayer executable + Select the mplayer executable + + + + Executables + Executables + + + + All files + Hemû Pel + + + + Select a directory + Cihek Hilbijêre + + + + MPlayer executable + MPlayer executable + + + + Screenshots folder + Peldanka wêneyên kişandî + + + + Video output driver + Ajokerê derketinê ya vîdyoyê + + + + Audio output driver + Ajokerê derketinê ya deng + + + + Select the audio output driver. + Select the audio output driver. + + + + Remember settings + Mîhengan bi bîr bîne + + + + Preferred audio language + Preferred audio language + + + + Preferred subtitle language + Zimanê binnivîsan + + + + Software video equalizer + Software video equalizer + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + + + + If this option is checked, all videos will start to play in fullscreen mode. + If this option is checked, all videos will start to play in fullscreen mode. + + + + Software volume control + Kontrola deng a nivîsbarê + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Check this option to use the software mixer, instead of using the sound card mixer. + + + + Postprocessing quality + Postprocessing quality + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + + + + Change volume + Deng biguherîne + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + 0 + 0 + + + + &Change volume on every file + &Ji bo hemû pelan dengê biguhere + + + + Select the &MPlayer executable: + Select the &MPlayer executable: + + + + &Folder for storing screenshots: + &Peldank ji bo tomarkirina wêneyên kişandî: + + + + &Audio: + &Deng: + + + + &Remember settings for all files (audio track, subtitles...) + &Mîhengan bi bîr bîne ji bo hemû pelan(Hêmanên dengê, binnivîs...) + + + + Su&btitles: + Bin&nivîs: + + + + &Quality: + &Quality: + + + + Start videos in &fullscreen + Vîdyoyan &dîmender tijî bide destpêkirin + + + + Disable &screensaver + &Dîmanparêz neçalak bike + + + + &Default volume: + &Dengê bixweber: + + + + Use s&oftware volume control + Kontrola dengê ya &nivîsbarê bi kar bîne + + + + Ma&x. Amplification: + Ma&x. Amplification: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS pass-through S/PDIF + + + + Direct rendering + Direct rendering + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + + + + Double buffering + Double buffering + + + + D&irect rendering + D&irect rendering + + + + Dou&ble buffering + Dou&ble buffering + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + &Enable postprocessing by default + &Enable postprocessing by default + + + + Volume &normalization by default + Volume &normalization by default + + + + Close when finished + Dema xelasbû bigire + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + Qe&nalên bixweber: + + + + &Pause when minimized + &Dema biçûkbû rawestîne + + + + Pause when minimized + Dema biçûkbû rawestîne + + + + Enable postprocessing by default + Enable postprocessing by default + + + + Max. Amplification + Max. Amplification + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Volume normalization by default + Volume normalization by default + + + + Maximizes the volume without distorting the sound. + Maximizes the volume without distorting the sound. + + + + Default volume + Dengê Bixweber + + + + Sets the initial volume that new files will use. + Sets the initial volume that new files will use. + + + + Channels by default + Qenalên bixweber + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + Uses hardware AC3 passthrough + Uses hardware AC3 passthrough + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + Postprocessing will be used by default on new opened files. + Postprocessing will be used by default on new opened files. + + + + Audio track + Hêmanê Deng + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + Subtitle track + Hêmanê Binnivîs + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + Or choose a track number: + Or choose a track number: + + + + Audi&o: + Audi&o: + + + + Preferred language: + Zimanê Bijartî: + + + + Preferre&d audio and subtitles + Deng û binnivîsa &bijartî + + + + &Subtitle: + &Binnivîs: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + High speed &playback without altering pitch + High speed &playback without altering pitch + + + + High speed playback without altering pitch + High speed playback without altering pitch + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Change volume just before playing + + + + &Video + &Vîdyo + + + + Use s&oftware video equalizer + Use s&oftware video equalizer + + + + A&udio + De&ng + + + + Volume + Deng + + + + Video + Vîdyo + + + + Audio + Deng + + + + Preferred audio and subtitles + Deng û binnivîsa bijartî + + + + None + Ne yek jî + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normal) + + + + Yadif (double framerate) + Yadif (double framerate) + + + + Linear Blend + Linear Blend + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Dei&nterlace by default: + + + + Deinterlace by default + Deinterlace by default + + + + Select the deinterlace filter that you want to be used for new videos opened. + Select the deinterlace filter that you want to be used for new videos opened. + + + + Remember time position + Pozîsyonê bi bîr bîne + + + + Remember &time position + Pozîsyona &demê bi bîr bîne + + + + Change volume just before p&laying + Tam beriya l&êdanê dengê biguhere + + + + Enable the audio equalizer + Ekolayzirê çalak bike + + + + Check this option if you want to use the audio equalizer. + Check this option if you want to use the audio equalizer. + + + + &Enable the audio equalizer + &Ekolayzira dengê çalak bike + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + &Close when finished playback + + + + + Dra&w video using slices + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Klavye û Mişk + + + + &Keyboard + &Klavye + + + + icon + îcon + + + + &Mouse + &Mişk + + + + Button functions: + Fonksiyona Bişkojkan: + + + + Media seeking + Media seeking + + + + Volume control + Kontrlola Deng + + + + Zoom video + Vîdyoyê nêzik bike + + + + None + Ne yek jî + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Li vir hûn dikarinhemû kurterêyan biguherînin. Ji bê vê yekê ot bitikin. Her wiha hûn dikarin vê lîsteyê tomar bikî û di komputerek din de dîsa bar bikî. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Li vir hûn dikarinhemû kurterêyan biguherînin. Ji bê vê yekê ot bitikin. Her wiha hûn dikarin vê lîsteyê tomar bikî û di komputerek din de dîsa bar bikî. + + + + &Left click + &Çep tikandin + + + + &Double click + &Cot tikandin + + + + &Wheel function: + &Fonksiyona Tekerê: + + + + Shortcut editor + Edîtora Kurterêyan + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + Left click + Çep tikandin + + + + Select the action for left click on the mouse. + Ji bo bişkoşk çep a mişkê sepanek hilbijêrin. + + + + Double click + Cot tikandin + + + + Select the action for double click on the mouse. + Ji bo cot-tikandina mişkê sepanek hilbijêrin. + + + + Wheel function + Fonksiyona Tekerê + + + + Select the action for the mouse wheel. + Ji bo tekerê mişkê sepanek hilbijêrin. + + + + Play + Bilîze + + + + Pause + Raweste + + + + Stop + Bisekine + + + + Fullscreen + Dîmender tijî + + + + Compact + Kompakt + + + + Screenshot + Wêne bikişîne + + + + On top + Her dem li ser + + + + Mute + Bêdeng + + + + Frame counter + Hejmarkera Dîmenan + + + + Reset zoom + Zoomê etal bike + + + + Exit fullscreen + Ji dîmender tijî derkeve + + + + Double size + Mezinahiya duqet + + + + Play / Pause + Bilîze / Raweste + + + + Pause / Frame step + Raweste / Sekna Dîmen + + + + Playlist + Lîsteya Lêdanê + + + + Preferences + Vebijêrk + + + + No function + Tu fonksiyon tune + + + + Change speed + Lezê biguhere + + + + Normal speed + Leza normal + + + + Keyboard + Klavye + + + + Mouse + Mişk + + + + Middle click + Tikandina navincî + + + + Select the action for middle click on the mouse. + Ji bo tikandina navincî ya mişkê xebatek hilbijêre. + + + + M&iddle click + T&ikandina navincî + + + + X Button &1 + X Bişkojk &1 + + + + X Button &2 + X Bişkojk &2 + + + + Go backward (short) + Here paş (kurt) + + + + Go backward (medium) + Here paş (navincî) + + + + Go backward (long) + Here paş (dirêj) + + + + Go forward (short) + Here pêş (kurt) + + + + Go forward (medium) + Here pêş (navincî) + + + + Go forward (long) + Here pêş (dirêj) + + + + OSD - Next level + OSD - Asta piştî + + + + Show context menu + Menûya context nîşan bide + + + + &Right click + &Rast tikandin + + + + Increase volume + Deng Zêdeke + + + + Decrease volume + Deng Kêmke + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Navrû + + + + <Autodetect> + <Autodetect> + + + + Default + Bixweber + + + + &Interface + &Navrû + + + + Never + Tu caran + + + + Whenever it's needed + Kengê pêwist be + + + + Only after loading a new video + enê piştî barkirina vîdyoyek nû + + + + Recent files + Pelên berê + + + + Language + Ziman + + + + Here you can change the language of the application. + Li vir hûn dikarin zimanê bernameyê biguherînin. + + + + &Short jump + &Hilavêtina kurt + + + + &Medium jump + &Hilavêtina navincî + + + + &Long jump + &Hilavêtina dirêj + + + + Mouse &wheel jump + Hilavêtina &tekera mişkê + + + + &Use only one running instance of SMPlayer + &Tenê yek paeya SMPlayer bi kar bîne + + + + Ma&x. items + Ma&x. hêman + + + + St&yle: + St&îl: + + + + Ico&n set: + Seta îco&n: + + + + L&anguage: + Z&iman: + + + + Main window + Paceya Bingehîn + + + + Auto&resize: + Mezinahiya &bixweber: + + + + R&emember position and size + Mezinahî û pozîsyonê &bi bîr bîne + + + + Default font: + Fonta bixweber: + + + + &Change... + &Biguhere... + + + + &Behaviour of time slider: + &Tevgera time slider: + + + + Seek to position while dragging + Seek to position while dragging + + + + Seek to position when released + Seek to position when released + + + + TextLabel + TextLabel + + + + &Seeking + &Seeking + + + + Ins&tances + Ins&tances + + + + Autoresize + Mezinahiya bixweber + + + + The main window can be resized automatically. Select the option you prefer. + Paceya bingehîn dikare bixweber bê guhertin. Vebijêrka hûn dixwazin hilbijêrin. + + + + Remember position and size + Pozîsyon û meinahiyê bi bîr bîne + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Ger hûn vê hilbijêrin, dema we SMPlayer girt û vekir wê pozîsyon û mezinahî wekî xwe bimîne. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + Icon set + Seta îkonan + + + + Select the icon set you prefer for the application. + Seta îkonên ku hûn dixwazin hilbijêrin. + + + + Style + Stîl + + + + Select the style you prefer for the application. + Stîla ku hûn dixwazin hilbijêrin. + + + + Default font + Fonta bixweber + + + + You can change here the application's font. + Hûn dikarin fonta bernameyê biguherin. + + + + Seeking + Seeking + + + + Short jump + Hilavêtina kurt + + + + Select the time that should be go forward or backward when you choose the %1 action. + Hilbijêrin ka dema xebata %1 hat meşandin wê çiqas ber bi pêş an jî paş bê çûn. + + + + short jump + hilavêtina kurt + + + + Medium jump + Hilavêtina navincî + + + + medium jump + hilavêtina navincî + + + + Long jump + hilavêtina dirêj + + + + long jump + hilavêtina dirêj + + + + Mouse wheel jump + hilavêtina tekera mişkê + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Hilbijêrin ka dema tekera mişkê hat bikaranîn wê çiqas ber bi pêş an jî paş bê çûn. + + + + Behaviour of time slider + Tevgera time slider + + + + Select what to do when dragging the time slider. + Select what to do when dragging the time slider. + + + + Instances + Instances + + + + Use only one running instance of SMPlayer + Bila tenê yek SMPlayer bimeşe + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Hilbijêrin ka dema pelek nû hat vekirin wê SMPlayera heyî çi bike. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + Default GUI + GUI a bixweber + + + + Mini GUI + GUI ya biçûk + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + &GUI + &GUI + + + + Automatic port + Automatic port + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + Manual port + Manual port + + + + Port to listen + Port to listen + + + + &Automatic + &Bixweber + + + + &Manual + &Bi destî + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Performans + + + + &Performance + &Performans + + + + Priority + Giringî + + + + Select the priority for the MPlayer process. + Ji bo xebaa MPlayer giringiyê hilbijêre. + + + + realtime + demarast + + + + high + bilind + + + + abovenormal + ji normal zêdetir + + + + normal + normal + + + + belownormal + ji normalê kêmtir + + + + idle + idle + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Mîhengkirina pêşbellekê heye ku performansa mediayên hêdî lez bike + + + + Allow frame drop + Allow frame drop + + + + Synchronization + Synchronization + + + + Audio/video auto synchronization + Audio/video auto synchronization + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Skip displaying some frames to maintain A/V sync on slow systems. + + + + Allow hard frame drop + Allow hard frame drop + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + More intense frame dropping (breaks decoding). Leads to image distortion! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Gradually adjusts the A/V sync based on audio delay measurements. + + + + Priorit&y: + Girin&gî: + + + + &Allow frame drop + &Allow frame drop + + + + Allow &hard frame drop (can lead to image distortion) + Allow &hard frame drop (can lead to image distortion) + + + + Audio/&video auto synchronization + Bixweber senkronîzasyona Deng/&vîdyo + + + + Fact&or: + Fact&or: + + + + &Fast audio track switching + &Fast audio track switching + + + + Fast &seek to chapters in dvds + Fast &seek to chapters in dvds + + + + Fast audio track switching + Fast audio track switching + + + + Fast seek to chapters in dvds + Fast seek to chapters in dvds + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + Skip loop filter + Skip loop filter + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + Cache for files + Ji pelan pêşbellekkirin + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + Cache for streams + Cache for streams + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + Cache for DVDs + Cache ji bo DVD + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + &Cache + &Cache + + + + Cache for &DVDs: + Cache ji bo &DVD: + + + + Cache for &local files: + Cache ji bo &pelên heremî: + + + + Cache for &streams: + Cache for &streams: + + + + Enabled + Çalak + + + + Skip (always) + Derbasbe (her tim) + + + + Skip only on HD videos + Derbasbe, tenê vîdyoyên HD + + + + Loop &filter + Loop &filter + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + Possible values: + Possible values: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Enabled</b>: the loop filter is not skipped + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + Cache + Pêşbellek + + + + Cache for audio CDs + Cache ji bo CDyên dengê + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + Cache for &audio CDs: + Cache for &audio CDs: + + + + Cache for VCDs + Cache ji bo VCD + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + Cache for &VCDs: + Pêşbellek ji bo &VCDs: + + + + Threads for decoding + Threads for decoding + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Lîsteya Lêdanê + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Lîsteya Lêdanê + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Binnivîs + + + + Choose a ttf file + Pelekî ttf hilbijêre + + + + Truetype Fonts + Fontên Truetype + + + + &Subtitles + &Binnivîs + + + + Autoload + Bixweber barke + + + + Same name as movie + Bi heman navê vîdyoyê + + + + All subs containing movie name + Hemû binnivîsên bi navê vîdyoyê + + + + All subs in directory + Hemû binnivîsên di peldankê de + + + + Position + Pozîsyon + + + + 0 + 0 + + + + Top + Serî + + + + Bottom + Jêr + + + + Font + Font + + + + Select the font which will be used for subtitles (and OSD): + Ji bo binnivîsan fonta nivîsê hilbijêre (û OSD): + + + + Size + Mezinahî + + + + No autoscale + Mezinahiya bixweber tune + + + + Proportional to movie height + Li gor bilindahiya vîdyoyê + + + + Proportional to movie width + Li gor firehiya vîdyoyê + + + + Proportional to movie diagonal + Li gor dûrahiya quncên vîdyoyê + + + + Subtitle position + Pozîsyona binnivîsê + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Ev vebijêrk pozîsyona binnivîsan diguhere. Wateya <i>100</i> herî jêr, wateya <i>0</i> jî herî jor e. + + + + Au&toload subtitles files (*.srt, *.sub...): + Binnivîsan bi&xweber barke (*.srt, *.sub...): + + + + S&elect first available subtitle + Binnivîsa yekemîn a derbasdar hi&lbijêre + + + + &Default subtitle encoding: + &Kodkirina bixweber a binnivîsan: + + + + Default &position of the subtitles on screen + &Pozîsyona bixweber a binnivîsan + + + + &Include subtitles on screenshots + &Bila binnivîs li ser wêneyên kişandî hebin + + + + &TTF font: + &TTF font: + + + + S&ystem font: + Fonata p&ergalê: + + + + A&utoscale: + Mezinahiya b&ixweber: + + + + Select first available subtitle + Binnivîsa derbasdar a yekem hilnijêre + + + + Default subtitle encoding + Kodkirina bixweber a binnivîsan + + + + Include subtitles on screenshots + Bila binnivîs li ser wêneyên kişandî bê dîtin + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Ger ev vebijêrk bê hilbijartin wê li ser wêneyên kişandî binnivîs bên xuyakirin. Agahî: arina dikare pirsgirêk derkeve. + + + + TTF font + Fontên TTF + + + + System font + Fontên Pergalê + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + Autoscale + Mezinahiya bixweber + + + + Text color + Rengê Nivîsê + + + + Select the color for the text of the subtitles. + Rengê teksta binnivîsan hilbijêre. + + + + Border color + Rengê kêlekan + + + + Select the color for the border of the subtitles. + Rengê kêlekên teksta binnivîsan hilbijêre. + + + + Select the subtitle autoload method. + Metoda barkirina bixweber a binnivîsan hilbijêre. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + Select the subtitle autoscaling method. + Metoda mezinahiya bixweber hilbijrin. + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + Jêr + + + + Middle + vertical alignment + + + + + Top + vertical alignment + Serî + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Alîkarî + + + + OK + Erê + + + + Cancel + Betal + + + + Apply + Bisepîne + + + + Help + Alîkarî + + + + SMPlayer - Preferences + SMPlayer - Vebijêrk + + + + QObject + + + will show this message and then will exit. + wê vê peyamê nîşan bide û derkeve. + + + + the main window will be closed when the file/playlist finishes. + paeya mak piştî xelasbûna pelê/Lîsteyê wê bê girtin. + + + + This is SMPlayer v. %1 running on %2 + Ev SMPlayer e v. %1 dixebite ser %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + media + media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + the main window won't be closed when the file/playlist finishes. + paeya mak piştî xelasbûna pelê/Lîsteyê wê neyê girtin. + + + + the video will be played in fullscreen mode. + wê vîdyo di moda dîmender tijî bê lîstin. + + + + the video will be played in window mode. + vîdyo wê di moda paeyê de bê lîstin. + + + + Enqueue in SMPlayer + Enqueue in SMPlayer + + + + opens the mini gui instead of the default one. + opens the mini gui instead of the default one. + + + + Restores the old associations and cleans up the registry. + Restores the old associations and cleans up the registry. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + Usage: + Bikaranîn: + + + + directory + ih + + + + action_name + navê_xebat + + + + action_list + lîsteya_xebatê + + + + opens the default gui. + opens the default gui. + + + + subtitle_file + pela_binnivîsê + + + + specifies the subtitle file to be loaded for the first video. + specifies the subtitle file to be loaded for the first video. + + + + %1 second(s) + + + + + + + %1 minute(s) + + + + + + + %1 and %2 + %1 û %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + îcon + + + + label + beş + + + + ShortcutGetter + + + Modify shortcut + Kurterêyan Sererastke + + + + Clear + Paqij + + + + Press the key combination you want to assign + Pêl kombînasyona bişkojkên dixwazî bike + + + + Capture + Capture + + + + Capture keystrokes + Capture keystrokes + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + Hemûyan Hilbijêre + + + + Select None + Tu tişt hilnebijêre + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - lêgerîn + + + + &Jump to: + &Here li: + + + + TristateCombo + + + Auto + Bixweber + + + + Yes + Erê + + + + No + Na + + + + VideoEqualizer + + + Contrast + Kontrast + + + + Brightness + Brightness + + + + Hue + Hue + + + + Saturation + Saturation + + + + Gamma + Gamma + + + + &Reset + &Vegerîne Despêkê + + + + &Set as default values + &Bike nirxên bixweber + + + + Use the current values as default values for new videos. + Nirxên heyî bike nirxên bixweber ên vîdyoyên nû. + + + + Set all controls to zero. + Hemû kontrolan bike sifir. + + + + Video Equalizer + Ekolayzira Vîdyoyê + + + + Information + Agahî + + + + The current values have been stored to be used as default. + Nirxên heyî wekî nirxên bixweber hate tomarkirin. + + + + VideoPreview + + + Video preview + + + + + Cancel + Betal + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Tomarkirinê de çewtî + + + + The file couldn't be saved + Pel nehat tomarkirin + + + + Error + Çewtî + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Bixweber + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Deng + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_mk.ts b/plugins/smplayer_plugin/translations/smplayer_mk.ts new file mode 100644 index 000000000..13423c602 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_mk.ts @@ -0,0 +1,7213 @@ + + + + About + + + Version: %1 + Верзија: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Оваа програма е слободен софтвер; можете да ја редистрибуирате и/или модифицирате под условите на GNU генералната јавна лиценца издадена од фондацијата за слободен софтвер; или верзија 2 (по ваш избор) или било која подоцнежна верзија. + + + + The following people have contributed with translations: + Следниве луѓе придонесле со преводи: + + + + German + Германски + + + + Slovak + Словачки + + + + Italian + Италијански + + + + French + Француски + + + + %1, %2 and %3 + %1, %2 и %3 + + + + Simplified-Chinese + Едноставен-Кинески + + + + Russian + Руски + + + + %1 and %2 + %1 и %2 + + + + Hungarian + Унгарски + + + + Polish + Полски + + + + Japanese + Јапонски + + + + Dutch + Холандски + + + + Ukrainian + Украински + + + + Portuguese - Brazil + Португалски - Бразил + + + + Georgian + Грузиски + + + + Czech + Чешки + + + + Bulgarian + Бугарски + + + + Turkish + Турски + + + + Swedish + Шведски + + + + Serbian + Српски + + + + Traditional Chinese + Традиционален Кинески + + + + Romanian + Романски + + + + Portuguese - Portugal + Португалски - Португалија + + + + Greek + Грчки + + + + Finnish + Фински + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + За SMPlayer + + + + &Info + &Информација + + + + icon + Икона + + + + &Contributions + &Придонесувачи + + + + &Translators + &Преведувачи + + + + &License + &Лиценца + + + + Visit our web for updates: + Посете ја нашата веб страна за надградби: + + + + Get help in our forum: + Добијте помош на нашиот форум: + + + + You can support SMPlayer by making a donation. + Можете да го подржите SMPlayer со давање на донација. + + + + More info + Повеќе информации + + + + Korean + Корејски + + + + Macedonian + Македонски + + + + Basque + Баскијски + + + + Using MPlayer %1 + + + + + Catalan + Каталонски + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + Арапски + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Име + + + + Description + Опис + + + + Shortcut + Кратенка + + + + &Save + &Зачувај + + + + &Load + &Внеси + + + + Key files + Клучни датотеки + + + + Choose a filename + Одберете име на датотека + + + + Confirm overwrite? + Потврдете пребришување? + + + + The file %1 already exists. +Do you want to overwrite? + Датотеката %1 веќе постои.Дали сакате да ја пребришете? + + + + Choose a file + Одберете датотека + + + + Error + Грешка + + + + The file couldn't be saved + Датотеката не можеше да биде зачувана + + + + The file couldn't be loaded + Датотеката не можеше да биде внесена + + + + &Change shortcut... + &Промени кратенка... + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + &Ресетирај + + + + &Set as default values + &Постави како основни вредности + + + + Use the current values as default values for new videos. + Користи ги сегашните вредности како основни вредности за нови видеа. + + + + Set all controls to zero. + Постави ги сите контроли на нула. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer запис + + + + SMPlayer - smplayer log + SMPlayer - smplayer запис + + + + &Open + &Отвори + + + + &Play + &Пушти + + + + &Video + &Видео + + + + &Audio + &Звук + + + + &Subtitles + &Титлови + + + + &Browse + &Пребарај + + + + Op&tions + &Опции + + + + &Help + &Помош + + + + &File... + &Датотека... + + + + D&irectory... + &Папка... + + + + &Playlist... + &Листа за пуштање... + + + + &DVD from drive + &DVD од уред + + + + D&VD from folder... + &DVD од папка... + + + + &URL... + &URL... + + + + &Clear + &Исчисти + + + + &Recent files + &Скорашни датотеки + + + + P&lay + &Пушти + + + + &Pause + &Пауза + + + + &Stop + &Стоп + + + + &Frame step + &Стапка на рамката + + + + &Normal speed + &Нормална брзина + + + + &Halve speed + &Дупло поспоро + + + + &Double speed + &Дупло побрзо + + + + Speed &-10% + Брзина &-10% + + + + Speed &+10% + Брзина &+10% + + + + Sp&eed + &Брзина + + + + &Repeat + &Повтори + + + + &Fullscreen + &Цел екран + + + + &Compact mode + &Компактен мод + + + + Si&ze + &Големина + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &до 16:9 + + + + &Aspect ratio + &Пропорција на видео + + + + &None + &Ниедно + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + + + + + &Deinterlace + + + + + &Postprocessing + &Постпроцесирање + + + + &Autodetect phase + + + + + &Deblock + &Деблокирај + + + + De&ring + + + + + Add n&oise + Додај &шум + + + + F&ilters + &Филтри + + + + &Equalizer + &Изедначувач + + + + &Screenshot + &Слика од екран + + + + S&tay on top + &Остани на врв + + + + &Extrastereo + + + + + &Karaoke + &Караоке + + + + &Filters + &Филтри + + + + &Stereo + &Стерео + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Канали + + + + &Left channel + &Лев канал + + + + &Right channel + &Десен канал + + + + &Stereo mode + &Стерео мод + + + + &Mute + &Занеми + + + + Volume &- + Гласност &- + + + + Volume &+ + Гласност &+ + + + + &Delay - + &Каснење - + + + + D&elay + + &Каснење + + + + + &Select + &Одберете + + + + &Load... + &Вчитај... + + + + Delay &- + Одложи &- + + + + Delay &+ + Одложи &+ + + + + &Up + &Горе + + + + &Down + &Надоле + + + + &Title + &Наслов + + + + &Chapter + &Поглавје + + + + &Angle + &Агол + + + + &Playlist + &Листа за пуштање + + + + &Show frame counter + &Прикажи бројач на рамки + + + + &Disabled + &Оневозможено + + + + &Seek bar + &Лента за барање + + + + &Time + &Време + + + + Time + T&otal time + Време + &вкупно време + + + + &OSD + &OSD + + + + &View logs + &Види записници + + + + P&references + &Поставувања + + + + About &Qt + За &Qt + + + + About &SMPlayer + За &SMPlayer + + + + <empty> + <празно> + + + + Video + Видео + + + + Audio + Звук + + + + Playlists + Листи за пуштање + + + + All files + Сите датотеки + + + + Choose a file + Одберете датотека + + + + SMPlayer - Information + SMPlayer - Информација + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + + + + + Choose a directory + Одберете папка + + + + Subtitles + Титлови + + + + About Qt + За Qt + + + + Playing %1 + Пуштам %1 + + + + Pause + Пауза + + + + Stop + Стоп + + + + Play / Pause + Пушти / Пауза + + + + Pause / Frame step + Пауза / Рамка по рамка + + + + U&nload + &Извади + + + + V&CD + V&CD + + + + C&lose + &Затвори + + + + View &info and properties... + Види ја &информацијата и својствата... + + + + Zoom &- + Зум &- + + + + Zoom &+ + Зум &+ + + + + &Reset + &Ресетирај + + + + Move &left + Премести &лево + + + + Move &right + Премести &десно + + + + Move &up + Премести &горе + + + + Move &down + Премести &долу + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Претходна линија во титлови + + + + N&ext line in subtitles + &Следна линија во титлови + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + + + + + Inc volume (2) + + + + + Exit fullscreen + Излези од цел екран + + + + OSD - Next level + OSD - Следно ниво + + + + Dec contrast + + + + + Inc contrast + + + + + Dec brightness + + + + + Inc brightness + + + + + Dec hue + + + + + Inc hue + + + + + Dec saturation + + + + + Dec gamma + + + + + Next audio + + + + + Next subtitle + Следни титлови + + + + Next chapter + Следно поглавје + + + + Previous chapter + Претходно поглавје + + + + Inc saturation + + + + + Inc gamma + + + + + &Load external file... + + + + + &Kerndeint + + + + + &Yadif (normal) + + + + + Y&adif (double framerate) + + + + + &Next + &Следно + + + + Pre&vious + &Претходно + + + + Volume &normalization + &Нормализација на гласност + + + + &Audio CD + + + + + Denoise nor&mal + + + + + Denoise &soft + + + + + Denoise o&ff + + + + + Use SSA/&ASS library + Користи SSA/&ASS библиотека + + + + Flip i&mage + Преврти &слика + + + + &Toggle double size + + + + + S&ize - + &Големина - + + + + Si&ze + + &Големина + + + + + Add &black borders + + + + + Soft&ware scaling + + + + + &FAQ + &ЧПП + + + + Visualize &motion vectors + + + + + &Command line options + + + + + SMPlayer command line options + Опции во командната линија за SMPlayer + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &Нумера + + + + &Track + audio + &Нумера + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer веќе работи тука + + + + S&how icon in system tray + &Прикажи икона во системска лента + + + + &Hide + &Скриј + + + + &Restore + &Врати + + + + &Quit + &Откажи + + + + Playlist + Листа за пуштање + + + + Core + + + Brightness: %1 + Светлина: %1 + + + + Contrast: %1 + Контраст: %1 + + + + Gamma: %1 + Гама: %1 + + + + Hue: %1 + Нијанса: %1 + + + + Saturation: %1 + Заситување: %1 + + + + Volume: %1 + Гласност: %1 + + + + Zoom: %1 + Зум: %1 + + + + Font scale: %1 + Големина на фонт: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Добредојдовте во SMPlayer + + + + Audio + Звук + + + + Subtitle + Титлови + + + + &Main toolbar + &Главен алатник + + + + &Language toolbar + &Алатник за јазик + + + + &Toolbars + &Алатници + + + + EqSlider + + + icon + Икона + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + + + + + Error + Грешка + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Својства на датотеката + + + + &Information + &Информации + + + + &Demuxer + &Мултиплексор + + + + &Select the demuxer that will be used for this file: + &Одберете го мултиплексорот кој ќе биде користен за оваа датотека: + + + + &Reset + &Ресетирај + + + + &Video codec + &Видео кодек + + + + &Select the video codec: + &Одберете го видео кодекот: + + + + A&udio codec + &Звучен кодек + + + + &Select the audio codec: + &Одберете го звучниот кодек: + + + + &MPlayer options + &MPlayer опции + + + + Additional Options for MPlayer + Додатни опции за MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Овде можете да префрлувате додатни опции до MPlayer. +Напишете ги оделени со празни места. +Пример: -flip -nosound + + + + &Options: + &Опции: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Исто така моќете да префрлувате додатни видео филтри. +Оделете ги со ",". Не користете празни места! +Пример: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + &Видео филтри: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + И конечно звучни фитри. Истото правило како за видео филтри. +Пример: resample=44100:0:0,volnorm + + + + Audio &filters: + Звучни &филтри: + + + + OK + Во ред + + + + Cancel + Откажи + + + + Apply + Примени + + + + FindSubtitlesWindow + + + Language + Јазик + + + + Name + Име + + + + Format + Формат + + + + Files + + + + + Date + Датум + + + + Uploaded by + + + + + All + + + + + Close + Затвори + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Грешка + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Грешка при зачувување на датотеката + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Генерално + + + + Size + Големина + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Должина + + + + Demuxer + Мултиплексор + + + + Name + Име + + + + Artist + Изведувач + + + + Author + Автор + + + + Album + Албум + + + + Genre + Жанр + + + + Date + Датум + + + + Track + Нумера + + + + Copyright + Авторско право + + + + Comment + Коментар + + + + Software + Софтвер + + + + Clip info + Информација за клипот + + + + Video + Видео + + + + Resolution + Резолуција + + + + Aspect ratio + Пропорција на видеото + + + + Format + Формат + + + + Bitrate + Брзина на битови + + + + %1 kbps + %1 kbps + + + + Frames per second + Рамки во секунда + + + + Selected codec + Одбран кодек + + + + Initial Audio Stream + Почетен звучен поток + + + + Rate + Стапка + + + + %1 Hz + %1 Hz + + + + Channels + Канали + + + + Audio Streams + Звучни потоци + + + + Language + Јазик + + + + empty + празно + + + + Subtitles + Титлови + + + + Type + Тип + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Име на потокот + + + + Stream URL + URL на поток + + + + File + Датотека + + + + InputDVDDirectory + + + Choose a directory + Одберете папка + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Пушти DVD од папка + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Можете да пуштите DVD од вашиот тврд диск. Само одберете ја папката што ги содржи VIDEO_TS и AUDIO_TS папките. + + + + Choose a directory... + Одберете папка... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Внесете ја верзијата на MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer не можеше да ја идентификува верзијата на MPlayer која ја користите. + + + + Version reported by MPlayer: + Верзија објавена од MPlayer: + + + + Please, &select the correct version: + Ве молиме, &одберете ја точната верзија: + + + + 1.0rc1 or older + 1.0rc1 или постара + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Поголема од 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Внесете URL + + + + &URL: + &URL: + + + + It's a &playlist + Е &листа за пуштање + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + доколку оваа опција е одбрана, URL-то ќе биде сметано како листа за пуштање: ќе биде отворено како текст и ќе ги пушти URL-та кои се во него. + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + Арапски + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + Бугарски + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + Каталонски + + + + Corsican + + + + + Czech + Чешки + + + + Welsh + + + + + Danish + + + + + German + Германски + + + + Greek + Грчки + + + + English + Англиски + + + + Esperanto + + + + + Spanish + Шпански + + + + Estonian + + + + + Basque + Баскијски + + + + Persian + + + + + Finnish + Фински + + + + Faroese + + + + + French + Француски + + + + Frisian + + + + + Irish + + + + + Galician + Галски + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + Унгарски + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + Италијански + + + + Inuktitut + + + + + Japanese + Јапонски + + + + Javanese + + + + + Georgian + Грузиски + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + Корејски + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + Македонски + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + Холандски + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + Полски + + + + Portuguese + + + + + Quechua + + + + + Romanian + Романски + + + + Russian + Руски + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + Словачки + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + Српски + + + + Sundanese + + + + + Swedish + Шведски + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Турски + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + Украински + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + Португалски - Бразил + + + + Portuguese - Portugal + Португалски - Португалија + + + + Simplified-Chinese + Едноставен-Кинески + + + + Traditional Chinese + Традиционален Кинески + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Западно европси јазици + + + + Western European Languages with Euro + Западно европски јазици со Евро + + + + Slavic/Central European Languages + Словенски/Централно европски јазици + + + + Esperanto, Galician, Maltese, Turkish + Есперанто, Галски, Малтешки, Турски + + + + Old Baltic charset + Старо балтичка листа на карактери + + + + Cyrillic + Кирилица + + + + Modern Greek + Модерен Грчки + + + + Baltic + Балтички + + + + Celtic + Келтски + + + + Hebrew charsets + Хебрејска листа на карактери + + + + Ukrainian, Belarusian + Украински, Белоруски + + + + Simplified Chinese charset + Едноставна Кинеска листа на карактери + + + + Traditional Chinese charset + Традиционално Кинеска листа на карактери + + + + Japanese charsets + Јапонска листа на карактери + + + + Korean charset + Корејска листа на карактери + + + + Thai charset + Тајландска листа на карактери + + + + Cyrillic Windows + Кирилица Windows + + + + Slavic/Central European Windows + Словенски/Централно европски Windows + + + + Arabic Windows + Арапски Windows + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Внесете го името на датотеката за зачувување + + + + Confirm overwrite? + Потврдете пребришување? + + + + The file already exists. +Do you want to overwrite? + Датотеката веќе постои. +Дали сакате да ја пребришете? + + + + Error saving file + Грешка при зачувување на датотеката + + + + The log couldn't be saved + Извештајот не можеше да биде зачуван + + + + Logs + Извештаи + + + + LogWindowBase + + + Log Window + Прозорец за извештај + + + + Save + Зачувај + + + + Copy to clipboard + Копирај на табла за исечоци + + + + &Close + &Затвори + + + + Close + Затвори + + + + MiniGui + + + Control bar + Лента за контрола + + + + MpcGui + + + Control bar + Лента за контрола + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Име + + + + Length + Должина + + + + &Play + &Пушти + + + + &Edit + &Уреди + + + + Playlists + Листи за пуштање + + + + Choose a file + Одберете датотека + + + + Choose a filename + Одберете име на датотека + + + + Confirm overwrite? + Потврдете пребришување? + + + + The file %1 already exists. +Do you want to overwrite? + Датотеката %1 веќе постои. +Дали сакате да ја пребришете? + + + + All files + Сите датотеки + + + + Select one or more files to open + Одберете една или повеќе датотеки за отварање + + + + Choose a directory + Одберете папка + + + + Edit name + Уредете го името + + + + Type the name that will be displayed in the playlist for this file: + Внесете го името кое ќе биде прикажано во листата за пуштање за оваа датотека: + + + + &Load + &Внеси + + + + &Save + &Зачувај + + + + &Next + &Следно + + + + Pre&vious + &Претходно + + + + Move &up + Оди &нагоре + + + + Move &down + Оди &доле + + + + &Repeat + &Повтори + + + + S&huffle + &Измешај + + + + Add &current file + Додај &сегашна датотека + + + + Add &file(s) + Додај &датотека/и + + + + Add &directory + Додај &папка + + + + Remove &selected + Отстрани ги &одбраните + + + + Remove &all + Отстрани ги &сите + + + + SMPlayer - Playlist + SMPlayer - Листа за пуштање + + + + Add... + Додај... + + + + Remove... + Отстрани... + + + + Playlist modified + Листата за пуштање е модифицирана + + + + There are unsaved changes, do you want to save the playlist? + Постојат незачувани промени, дали сакате да ја зачувате листата за пуштање? + + + + Preferences + + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + Напредно + + + + Auto + Автоматски + + + + &Advanced + &Автоматски + + + + icon + икона + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Овде можете да предавате додатни опции до MPlayer. +Напишете ги оделени со празно место. +Пример: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Исто така можете да предавате додатни видео филтри. +Оделете ги со ",". Не користете празни места! +Пример: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + И конечно звучни филтри. Истото правило како за видео филтри. +Пример: resample=44100:0:0,volnorm + + + + Log MPlayer output + Запишувај го излезот на MPlayer + + + + Log SMPlayer output + Запишувај го излезот на SMPlayer + + + + This option is mainly intended for debugging the application. + Оваа опција е главно наменета за дебагирање на апликацијата. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Одбирањето на оваа опција може да го намали трепкањето, но исто така може и да предизвика видеото да не биде прикажано како што треба. + + + + Filter for SMPlayer logs + Филтер за записниците на SMPlayer + + + + &Monitor aspect: + Формат на &мониторот: + + + + &Run MPlayer in its own window + &Пушти го MPlayer во свој прозорец + + + + &Options: + &Опции: + + + + V&ideo filters: + &Видео филтри: + + + + Audio &filters: + Звучни &филтри: + + + + &Colorkey: + &Мапа на боја: + + + + Log &SMPlayer output + Запишувај го излезот на &SMPlayer + + + + &Filter for SMPlayer logs: + &Филтер за записници на SMPlayer: + + + + C&hange... + &Измени... + + + + Logs + Записи + + + + Log MPlayer &output + Запишувај го &излезот на MPlayer + + + + Options for MP&layer + Опции за &MPlayer + + + + Autosave MPlayer log + Автоматски зачувај го записот на MPlayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + &Автоматски зачувај го MPlayer записот во датотека + + + + Pass short filenames (8+3) to MPlayer + Предади кратки имиња на датотеки(8+3) до MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + За сега MPlayer не може да отвара датотеки кои содржат карактери кои ги нема во локалниот енкодинг. Одбирање на оваа опција ќе направи SMPlayer да му предаде на MPlayer кратки верзии на имињата на датотеките, со што ќе може да ги отвори. + + + + &Pass short filenames (8+3) to MPlayer + &Предади кратки имиња на датотеки(8+3) до MPlayer + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Тип + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Предупредување + + + + Not all files could be associated. Please check your security permissions and retry. + Не можеше да се создаде асоцијација на сите датотеки. Ве молиме проверете ги вашите безбедностни дозволи и пробајте повторно. + + + + File Types + Типови на датотеки + + + + Select all + Одбери ги сите + + + + Check all file types in the list + Одберете ги сите дататочни типови во листата + + + + Uncheck all file types in the list + Одизберете ги сите дататочни типови во листата + + + + List of file types + Листа на датотечни типови + + + + File types + Типови на датотеки + + + + Media files handled by SMPlayer: + Медиа датотеки отварани од SMPlayer: + + + + Select All + Одбери ги Сите + + + + Select None + Одберете Ниедно + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Одберете ги датотечните екстензии за медиа кои сакате SMPlayer да ги отвара. Кога ќе кликнете Примени, одбраните датотеки ќе бидат отварани со SMPlayer, кога ќе одизберете медиа тип, асоцијацијата на датотеката ќе биде вратена. + + + + Select none + Одбери ниедно + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Напомена:</b> (Реставрацијата не работи на Windows Vista). + + + + PrefDrives + + + Drives + Уреди + + + + icon + икона + + + + CD device + CD уред + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Одберете го вашиот CDROM уред. Тој ќе биде користен за пуштање на VCD и Аудио CD-иња. + + + + DVD device + DVD уред + + + + Choose your DVD device. It will be used to play DVDs. + Одберете го вашиот DVD уред. Тој ќе биде користен за пуштање на DVD-иња. + + + + Select your &CD device: + Одберете го вашиот &CD уред: + + + + Select your &DVD device: + Одберете го вашиот &DVD уред: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer не одбира CDROM или DVD уреди. Така што пред да можете да пуштите CD или DVD морате да ги одберете уредите кои што сакате да ги користите (може да биде истиот уред). + + + + PrefGeneral + + + General + Генерално + + + + &General + &Генерално + + + + Paths + Патеки + + + + Media settings + Поставувања за медиуми + + + + Start videos in fullscreen + Пушти видеа на цел екран + + + + Disable screensaver + Оневозможи чувар на екранот + + + + Select the mplayer executable + Одберете ја mplayer извршната датотека + + + + Executables + Извршни датотеки + + + + All files + Сите датотеки + + + + Select a directory + Одберете папка + + + + MPlayer executable + MPlayer извршна датотека + + + + Screenshots folder + Папка со слики од екран + + + + Video output driver + Излезен драјвер за видео + + + + Audio output driver + Излезен драјвер за звук + + + + Select the audio output driver. + Одберете го излезниот драјвер за звук. + + + + Remember settings + Зачувај поставувања + + + + Preferred audio language + Префериран јазик на говор + + + + Preferred subtitle language + Префериран јазик на титлови + + + + Software video equalizer + Софтверски видео изедначувач + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + + + + + If this option is checked, all videos will start to play in fullscreen mode. + Доколку оваа опција е одбрана, сите видеа ќе се пуштаат на цел екран. + + + + Software volume control + Софтверска контрола на гласност + + + + Check this option to use the software mixer, instead of using the sound card mixer. + + + + + Postprocessing quality + Квалитет на постпроцесирање + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + + + + + Change volume + Промени гласност + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + 0 + 0 + + + + &Change volume on every file + &Промени гласност на секоја датотека + + + + Select the &MPlayer executable: + Одберете ја &MPlayer извршната датотека: + + + + &Folder for storing screenshots: + &Папка за зачувување на слики од екран: + + + + &Audio: + &Звук: + + + + &Remember settings for all files (audio track, subtitles...) + &Зачувај поставувања за сите датотеки ( звучни нумери, титлови...) + + + + Su&btitles: + &Титлови: + + + + &Quality: + &Квалитет: + + + + Start videos in &fullscreen + Пушти видеа на цел &екран + + + + Disable &screensaver + Оневозможи чувар на &екранот + + + + &Default volume: + &Стандардна гласност: + + + + Use s&oftware volume control + Користи &софтверска контрола на гласност + + + + Ma&x. Amplification: + &Мак&с. Засилување: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS pass-through S/PDIF + + + + Direct rendering + Директно рендерирање + + + + Double buffering + + + + + D&irect rendering + &Директно рендерирање + + + + Dou&ble buffering + + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + &Enable postprocessing by default + + + + + Volume &normalization by default + + + + + Close when finished + Затвори кога видеото ќе заврши + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + 2 (Стерео) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + &Канали стандардно: + + + + &Pause when minimized + &Паузирај кога е минимизирано + + + + Pause when minimized + Паузирај кога е минимизирано + + + + Enable postprocessing by default + + + + + Max. Amplification + Макс. Засилување + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Volume normalization by default + + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + Стандардна гласност + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + + + + + Audi&o: + &Звук: + + + + Preferred language: + Префериран јазик: + + + + Preferre&d audio and subtitles + + + + + &Subtitle: + &Титлови: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + &Видео + + + + Use s&oftware video equalizer + + + + + A&udio + + + + + Volume + Гласност + + + + Video + Видео + + + + Audio + Звук + + + + Preferred audio and subtitles + + + + + None + Нема + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Тастатура и глушец + + + + &Keyboard + &Тастатура + + + + icon + икона + + + + &Mouse + &Глушец + + + + Button functions: + Функции на копчето: + + + + Media seeking + + + + + Volume control + Контрола на гласност + + + + Zoom video + Зумирај видео + + + + None + Нема + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + &Лев клик + + + + &Double click + &Двоен клик + + + + &Wheel function: + Функција на &тркалцето: + + + + Shortcut editor + Уредувач на кратенки + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + Лев клик + + + + Select the action for left click on the mouse. + + + + + Double click + Двоен клик + + + + Select the action for double click on the mouse. + + + + + Wheel function + Функција на тркалцето + + + + Select the action for the mouse wheel. + + + + + Play + Пушти + + + + Pause + Пауза + + + + Stop + Стоп + + + + Fullscreen + На цел екран + + + + Compact + Компактно + + + + Screenshot + Слика на екран + + + + On top + На врв + + + + Mute + Занеми + + + + Frame counter + Бројач на рамки + + + + Reset zoom + Ресетирај зум + + + + Exit fullscreen + Излези од цел екран + + + + Double size + + + + + Play / Pause + Пушти / Пауза + + + + Pause / Frame step + Пауза / Рамка по рамка + + + + Playlist + Листа за пуштање + + + + Preferences + + + + + No function + + + + + Change speed + + + + + Normal speed + + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - Следно ниво + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Интерфејс + + + + <Autodetect> + <Автоматски> + + + + Default + Основен + + + + &Interface + &Интерфејс + + + + Never + Никогаш + + + + Whenever it's needed + Кога е потребно + + + + Only after loading a new video + Само по вчитување на ново видео + + + + Recent files + Скорашни датотеки + + + + Language + Јазик + + + + Here you can change the language of the application. + Овде може да го промените јазикот на апликацијата. + + + + &Short jump + &Краток скок + + + + &Medium jump + &Среден скок + + + + &Long jump + &Долг скок + + + + Mouse &wheel jump + Скок со &тралцето на глушецот + + + + &Use only one running instance of SMPlayer + &Користи само еден прозорец на SMPlayer + + + + Ma&x. items + &Највеќе предмети + + + + St&yle: + &Стил: + + + + Ico&n set: + &Икони: + + + + L&anguage: + &Јазик: + + + + Main window + Главен прозорец + + + + Auto&resize: + Автоматски &смени големина: + + + + R&emember position and size + &Зачувај позиција и големина + + + + Default font: + Основен фонт: + + + + &Change... + &Промени... + + + + &Behaviour of time slider: + &Однесување на лизгачот за време: + + + + Seek to position while dragging + Барај до позиција при влечење + + + + Seek to position when released + Барај до позиција кога е пуштено + + + + TextLabel + Ознака на текст + + + + &Seeking + &Барање + + + + Ins&tances + &Инстанци + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Seeking + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Перформанси + + + + &Performance + &Перформанси + + + + Priority + Приоритет + + + + Select the priority for the MPlayer process. + Одберете го приоритетот на MPlayer процесот. + + + + realtime + во вистинско време + + + + high + високо + + + + abovenormal + над нормално + + + + normal + нормално + + + + belownormal + под нормално + + + + idle + Неактивен + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Поставување на кеш може да ги подобри перформансите со спори медиуми + + + + Allow frame drop + + + + + Synchronization + Синхронизација + + + + Audio/video auto synchronization + + + + + Skip displaying some frames to maintain A/V sync on slow systems. + + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + + + + + Gradually adjusts the A/V sync based on audio delay measurements. + + + + + Priorit&y: + &Приоритет: + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + + + + + Fact&or: + &Фактор: + + + + &Fast audio track switching + + + + + Fast &seek to chapters in dvds + + + + + Fast audio track switching + + + + + Fast seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + Кеш за датотеки + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + Кеш за потоци + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + Кеш за DVD-иња + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + &Кеш + + + + Cache for &DVDs: + Кеш за &DVD-иња: + + + + Cache for &local files: + Кеш за &локални датотеки: + + + + Cache for &streams: + Кеш за &потоци: + + + + Enabled + Овозможено + + + + Skip (always) + Прескокни (секогаш) + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + Возможни вредности: + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Листа за пуштање + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Листа за пуштање + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Титлови + + + + Choose a ttf file + Одберете ttf датотека + + + + Truetype Fonts + Truetype фонтови + + + + &Subtitles + &Титлови + + + + Autoload + Автоматски вчитај + + + + Same name as movie + Исто име како филмот + + + + All subs containing movie name + Сите титлови кои го содржат името на филмот + + + + All subs in directory + Сите титлови во папката + + + + Position + Позиција + + + + 0 + 0 + + + + Top + Горе + + + + Bottom + Долу + + + + Font + Фонт + + + + Select the font which will be used for subtitles (and OSD): + Одберете го фонтот кој ќе биде користен за титлови ( и OSD): + + + + Size + Големина + + + + No autoscale + Без автоматска промена на големината + + + + Proportional to movie height + Пропорцијонално со висината на филмот + + + + Proportional to movie width + Пропорцијонално со ширината на филмот + + + + Proportional to movie diagonal + Пропорцјонално со дијагоналата на филмот + + + + Subtitle position + + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + + + + + Au&toload subtitles files (*.srt, *.sub...): + + + + + S&elect first available subtitle + + + + + &Default subtitle encoding: + + + + + Default &position of the subtitles on screen + + + + + &Include subtitles on screenshots + &Вклучи титлови на слики од екранот + + + + &TTF font: + &TTF фонт: + + + + S&ystem font: + &Системски фонт: + + + + A&utoscale: + + + + + Select first available subtitle + + + + + Default subtitle encoding + + + + + Include subtitles on screenshots + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + Долу + + + + Middle + vertical alignment + + + + + Top + vertical alignment + Горе + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Помош + + + + OK + Во ред + + + + Cancel + Откажи + + + + Apply + Примени + + + + Help + Помош + + + + SMPlayer - Preferences + SMPlayer - Поставувања + + + + QObject + + + will show this message and then will exit. + ќе ја прикаже оваа порака и потоа ќе се исклучи. + + + + the main window will be closed when the file/playlist finishes. + главниот прозорец ќе биде затворен кога датотеката/листата за пуштање ќе заврши. + + + + This is SMPlayer v. %1 running on %2 + Ова е SMPlayer в.%1 која работи на %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + се обидува да се поврзе со друг прозорец и да му ја испрати специфираната акција. Пример: -send-action pause Останатите опции (доколку ги има) ќе бидат игнорирани и апликацијата ќе се исклучи. Ќе испрати 0 за успех или -1 за неуспех. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list е листа на акции одделени со празно место. Акциите ќе бидат извршени откако ќе внесете датотека (доколку има) во истиот редослед кои сте го внесле. За променливи акции можете да дефинирате точно или неточно како параметар. Пример -actions "fullscreen compact true". Наводници се неопходни доколку имате повеќе од една акција. + + + + media + медиум + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + доколку работи уште еден прозорец, датотеката ќе биде додадена на листата на тој прозорец. Доколку не работи друг прозорец, оваа опција ќе биде игнорирана и датотеките ќе бидат отворени во нов прозорец. + + + + the main window won't be closed when the file/playlist finishes. + главниот прозорец нема да биде затворен кога датотеката/листата за пуштање ќе заврши. + + + + the video will be played in fullscreen mode. + видеото ќе биде пуштено на цел екран. + + + + the video will be played in window mode. + видеото ќе биде пуштено во прозорец. + + + + Enqueue in SMPlayer + Стави во ред за пуштање во SMPlayer + + + + opens the mini gui instead of the default one. + го отвара минијатурниот интерфејс наместо основното. + + + + Restores the old associations and cleans up the registry. + Ги враќа старите асоцијации и го чисти регистарот. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + "медиум" е тип на датотека која SMPlayer може да ја отвори. Тоа може да биде локална датотека, DVD (пр. dvd://1), интернет поток (пр. mms://....) или локална листа за пуштање доколку -playlist опцијата е користена, тоа значи дека SMPlayer же ја предаде опцијата на MPlayer, така што MPlayer ќе се справи со листата, а не SMPlayer. + + + + Usage: + Користење: + + + + directory + папка + + + + action_name + име_на_акцијата + + + + action_list + листа_на_акции + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + %1 и %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + Икона + + + + label + Ознака + + + + ShortcutGetter + + + Modify shortcut + Модифицирај кратенка + + + + Clear + Исчисти + + + + Press the key combination you want to assign + Притиснете ја комбинацијата на копчиња која сакате да ја доделите + + + + Capture + Сними + + + + Capture keystrokes + Сними притискања + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + Одбери ги Сите + + + + Select None + Одберете Ниедно + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + Автоматски + + + + Yes + Да + + + + No + Не + + + + VideoEqualizer + + + Contrast + Контраст + + + + Brightness + Светлина + + + + Hue + Нијанса + + + + Saturation + Заситување + + + + Gamma + Гама + + + + &Reset + &Ресетирај + + + + &Set as default values + &Постави како основни вредности + + + + Use the current values as default values for new videos. + Користи ги сегашните вредности како основни вредности за нови видеа. + + + + Set all controls to zero. + Постави ги сите контроли на нула. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + Откажи + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Грешка при зачувување на датотеката + + + + The file couldn't be saved + Датотеката не можеше да биде зачувана + + + + Error + Грешка + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Основен + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Гласност + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_nl.ts b/plugins/smplayer_plugin/translations/smplayer_nl.ts new file mode 100644 index 000000000..8abd53a03 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_nl.ts @@ -0,0 +1,7642 @@ + + + + About + + + Version: %1 + Versie: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Dit programma is vrije software; u mag het verspreiden en/of wijzigen onder de voorwaarden van de GNU Algemene Publieke Licentie, zoals uitgegeven door de Free Software Foundation; ofwel versie 2 van de Licentie, of (naar keuze) een latere versie. + + + + Some people have helped with their contributions: + Sommige mensen hebben geholpen met hun bijdragen: + + + + SMPlayer logo + SMPlayer logo + + + + file associations for Windows + bestandsassociaties voor Windows + + + + manpage for linux + manpage voor Linux + + + + support for colored console output + ondersteuning voor gekleurde consoleuitvoer + + + + icon for file associations + pictogram voor bestandsassociaties + + + + patch for file associations + patch voor bestandsassociaties + + + + The following people have contributed with translations: + Deze mensen hebben bijgedragen door vertalingen te schrijven: + + + + German + Duits + + + + Slovak + Slowaaks + + + + Italian + Italiaans + + + + French + Frans + + + + %1, %2 and %3 + %1, %2 en %3 + + + + Simplified-Chinese + Vereenvoudigd Chinees + + + + Russian + Russisch + + + + %1 and %2 + %1 en %2 + + + + Hungarian + Hongaars + + + + Polish + Pools + + + + Japanese + Japans + + + + Dutch + Nederlands + + + + Ukrainian + Oekraïens + + + + Portuguese - Brazil + Portugees - Brazilië + + + + Georgian + Georgisch + + + + Czech + Tsjechisch + + + + Bulgarian + Bulgaars + + + + Turkish + Turks + + + + Swedish + Zweeds + + + + Serbian + Servisch + + + + Traditional Chinese + Traditioneel Chinees + + + + Romanian + Roemeens + + + + Portuguese - Portugal + Portugees - Portugal + + + + Greek + Grieks + + + + Finnish + Fins + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Over SMPlayer + + + + &Info + &Info + + + + icon + pictogram + + + + &Contributions + &Bijdragen + + + + &Translators + &Vertalers + + + + &License + &Licentie + + + + Visit our web for updates: + Bezoek onze website voor updates: + + + + Get help in our forum: + Krijg hulp via ons forum: + + + + You can support SMPlayer by making a donation. + U kunt SMPlayer steunen door te doneren. + + + + More info + Meer informatie + + + + Korean + Koreaans + + + + Macedonian + Macedonisch + + + + Basque + Baskisch + + + + Using MPlayer %1 + Gebruik makend van MPlayer %1 + + + + Catalan + Catalaans + + + + Portable Edition + Draagbare editie + + + + Using Qt %1 (compiled with Qt %2) + Gebruik makend van Qt %1 (gecompileerd met Qt %2) + + + + Slovenian + Sloveens + + + + Arabic + Arabisch + + + + Kurdish + Koerdisch + + + + Galician + Galicisch + + + + The following people have contributed with patches (see the changelog for details): + Dezemensen hebben bijgedragen met patches (zie de changelog voor details): + + + + If there's any omission, please report. + Als er iemand ontbreekt, rapporteer het dan. + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Naam + + + + Description + Omschrijving + + + + Shortcut + Sneltoets + + + + &Save + Op&slaan + + + + &Load + &Laden + + + + Key files + Sleutelbestanden + + + + Choose a filename + Kies een bestandsnaam + + + + Confirm overwrite? + Bevestig overschrijven? + + + + The file %1 already exists. +Do you want to overwrite? + Het bestand %1 bestaat al. +Wilt u het overschrijven? + + + + Choose a file + Kies een bestand + + + + Error + Foutmelding + + + + The file couldn't be saved + Het bestand kon niet worden opgeslagen + + + + The file couldn't be loaded + Het bestand kon niet worden geladen + + + + &Change shortcut... + &Sneltoets wijzigen... + + + + AudioEqualizer + + + Audio Equalizer + Audio-equalizer + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + Toep&assen + + + + &Reset + &Resetten + + + + &Set as default values + Als &standaardwaarden instellen + + + + Use the current values as default values for new videos. + Gebruik de huidige waarden als standaardwaarden voor nieuwe video's. + + + + Set all controls to zero. + Stel alle besturingselementen op nul in. + + + + Information + Informatie + + + + The current values have been stored to be used as default. + De huidige waarden werden opgeslagen om als standaard gebruikt te worden. + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer log + + + + SMPlayer - smplayer log + SMPlayer - smplayer log + + + + &Open + &Openen + + + + &Play + Afs&pelen + + + + &Video + &Video + + + + &Audio + &Audio + + + + &Subtitles + O&ndertiteling + + + + &Browse + &Bladeren + + + + Op&tions + Op&ties + + + + &Help + &Help + + + + &File... + &Bestand... + + + + D&irectory... + &Map... + + + + &Playlist... + Afs&peellijst... + + + + &DVD from drive + &DVD vanaf station + + + + D&VD from folder... + D&VD vanuit map... + + + + &URL... + &URL... + + + + &Clear + &Leegmaken + + + + &Recent files + &Recente bestanden + + + + P&lay + Afspe&len + + + + &Pause + &Pauzeren + + + + &Stop + &Stoppen + + + + &Frame step + &Frame stap + + + + &Normal speed + &Normale snelheid + + + + &Halve speed + &Halve snelheid + + + + &Double speed + &Dubbele snelheid + + + + Speed &-10% + Snelheid &-10% + + + + Speed &+10% + Snelheid &+10% + + + + Sp&eed + Sn&elheid + + + + &Repeat + He&rhalen + + + + &Fullscreen + Beeld&vullend + + + + &Compact mode + &Compacte modus + + + + Si&ze + &Grootte + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &naar 16:9 + + + + &Aspect ratio + &Aspectverhouding + + + + &None + &Geen + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Lineaire &Blend + + + + &Deinterlace + &Deinterlace + + + + &Postprocessing + &Nabewerking + + + + &Autodetect phase + &Automatische fasedetectie + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + N&oise toevoegen + + + + F&ilters + F&ilters + + + + &Equalizer + &Equalizer + + + + &Screenshot + &Schermafdruk + + + + S&tay on top + Venster &bovenaan houden + + + + &Track + &Spoor + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filters + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Kanalen + + + + &Left channel + &Linkerkanaal + + + + &Right channel + &Rechterkanaal + + + + &Stereo mode + &Stereomodus + + + + &Mute + De&mpen + + + + Volume &- + Volume &- + + + + Volume &+ + Volume &+ + + + + &Delay - + &Vertraging - + + + + D&elay + + V&ertraging + + + + + &Select + &Kiezen + + + + &Load... + &Laden... + + + + Delay &- + Vertraging &- + + + + Delay &+ + Vertraging &+ + + + + &Up + &Omhoog + + + + &Down + O&mlaag + + + + &Title + &Titel + + + + &Chapter + &Hoofdstuk + + + + &Angle + Hoek (&angle) + + + + &Playlist + &Afspeellijst + + + + &Show frame counter + &Frameteller weergeven + + + + &Disabled + Uitgeschakel&d + + + + &Seek bar + &Zoekbalk + + + + &Time + &Tijd + + + + Time + T&otal time + Tijd + T&otale tijd + + + + &OSD + &OSD + + + + &View logs + Logs weerge&ven + + + + P&references + Voo&rkeuren + + + + About &Qt + Over &Qt + + + + About &SMPlayer + Over &SMPlayer + + + + <empty> + <leeg> + + + + Video + Video + + + + Audio + Audio + + + + Playlists + Afspeellijsten + + + + All files + Alle bestanden + + + + Choose a file + Kies een bestand + + + + SMPlayer - Information + SMPlayer - Informatie + + + + Choose a directory + Kies een map + + + + Subtitles + Ondertiteling + + + + About Qt + Over Qt + + + + Playing %1 + Afspelen van %1 + + + + Pause + Pauze + + + + Stop + Stop + + + + Play / Pause + Afspelen / Pauzeren + + + + Pause / Frame step + Pauze / Frame stap + + + + U&nload + O&ntladen + + + + V&CD + V&CD + + + + C&lose + S&luiten + + + + View &info and properties... + &Informatie en eigenschappen weergeven... + + + + Zoom &- + Uitzoomen &- + + + + Zoom &+ + Inzoomen &+ + + + + &Reset + He&rstellen + + + + Move &left + Naar &links verplaatsen + + + + Move &right + Naar &rechts verplaatsen + + + + Move &up + Naar &omhoog verplaatsen + + + + Move &down + Naar bene&den verplaatsen + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Vorige regel in ondertiteling + + + + N&ext line in subtitles + Volg&ende regel in ondertiteling + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Volume zachter (2) + + + + Inc volume (2) + Volume luider (2) + + + + Exit fullscreen + Beeldvullend verlaten + + + + OSD - Next level + OSD - Volgende niveau + + + + Dec contrast + Contrast verlagen + + + + Inc contrast + Contrast verhogen + + + + Dec brightness + Helderheid verlagen + + + + Inc brightness + Helderheid verhogen + + + + Dec hue + Tint verlagen + + + + Inc hue + Tint verhogen + + + + Dec saturation + Verzadiging verlagen + + + + Dec gamma + Gamma verlagen + + + + Next audio + Volgend audiospoor + + + + Next subtitle + Volgende ondertitel + + + + Next chapter + Volgend hoofdstuk + + + + Previous chapter + Vorig hoofdstuk + + + + Inc saturation + Verzadiging verhogen + + + + Inc gamma + Gamma verhogen + + + + &Load external file... + Extern bestand &laden... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normaal) + + + + Y&adif (double framerate) + Y&adif (dubbele framerate) + + + + &Next + Volge&nde + + + + Pre&vious + &Vorige + + + + Volume &normalization + Volume&normalisatie + + + + &Audio CD + &Audio-CD + + + + Denoise nor&mal + Denoise nor&maal + + + + Denoise &soft + Denoise &zacht + + + + Denoise o&ff + Denoise &uit + + + + Use SSA/&ASS library + Gebruik SSA/&ASS-bibliotheek + + + + Flip i&mage + A&fbeelding spiegelen + + + + &Toggle double size + Dubbele grootte aan/ui&t + + + + S&ize - + Verkle&inen + + + + Si&ze + + Ver&groten + + + + Add &black borders + &Zwarte randen toevoegen + + + + Soft&ware scaling + Soft&warematig schalen + + + + &FAQ + Vaakgestelde vragen (&FAQ) + + + + Visualize &motion vectors + &Bewegingsvectoren visualiseren + + + + &Command line options + &Commandoregel-opties + + + + SMPlayer command line options + SMPlayer commandoregel-opties + + + + Enable &closed caption + Ondertiteling voor sle&chthorenden activeren + + + + &Forced subtitles only + Alleen ge&forceerde ondertiteling + + + + Reset video equalizer + Video-equalizer herstellen + + + + MPlayer has finished unexpectedly. + MPlayer is onverwachts beëindigd. + + + + Exit code: %1 + Afsluitcode: %1 + + + + MPlayer failed to start. + MPlayer kon niet gestart worden. + + + + Please check the MPlayer path in preferences. + Controleer het MPlayer pad in voorkeuren. + + + + MPlayer has crashed. + MPlayer is gecrashed. + + + + See the log for more info. + Zie het log voor meer info. + + + + &Rotate + D&raaien + + + + &Off + &Uit + + + + &Rotate by 90 degrees clockwise and flip + 90 graden &rechtsom draaien en spiegelen + + + + Rotate by 90 degrees &clockwise + 90 graden r&echtsom draaien + + + + Rotate by 90 degrees counterclock&wise + 90 graden &linksom draaien + + + + Rotate by 90 degrees counterclockwise and &flip + 90 graden l&inksom draaien en spiegelen + + + + &Jump to... + Sp&ring naar... + + + + Show context menu + Contekstmenu tonen + + + + Multimedia + Multimedia + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + De CDROM- / DVD-stations zijn nog niet geconfigureerd. +Het configuratievenster zal nu worden weergegeven, zodat u dit nu kunt doen. + + + + E&qualizer + E&qualizer + + + + Reset audio equalizer + Audio-equalizer resetten + + + + Find subtitles on &OpenSubtitles.org... + Ondertitels zoeken op &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Ondertitels uploaden naar OpenSu&btitles.org... + + + + &Tips + &Tips + + + + &Auto + &Automatisch + + + + Speed -&4% + Snelheid -&4% + + + + &Speed +4% + &Snelheid +4% + + + + Speed -&1% + Snelheid -&1% + + + + S&peed +1% + S&nelheid +1% + + + + Scree&n + Scher&m + + + + &Default + Stan&daard + + + + Mirr&or image + Afbeelding spi&egelen + + + + Next video + Volgende video + + + + &Track + video + &Spoor + + + + &Track + audio + &Spoor + + + + Warning - Using old MPlayer + Waarschuwing - Oude MPlayer + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + De versie van MPlayer (%1) op uw systeem is verouderd. SMPlayer kan er niet goed mee werken: sommige opties zullen niet werken, ondertitels selecteren kan mislukken... + + + + Please, update your MPlayer. + Werk uw MPlayer a.u.b. bij. + + + + (This warning won't be displayed anymore) + (Deze waarschuwing zal niet meer worden weergegeven) + + + + Next aspect ratio + Volgende aspectverhouding + + + + &Auto zoom + &Automatisch zoomen + + + + Auto zoom for &16:9 + Automatisch zoomen voor &16:9 + + + + Auto zoom for &2.35:1 + Automatisch zoomen voor &2.35:1 + + + + Pre&view... + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer draait hier nog steeds + + + + S&how icon in system tray + Pictogram in systeemvak &tonen + + + + &Hide + &Verbergen + + + + &Restore + &Herstellen + + + + &Quit + &Afsluiten + + + + Playlist + Afspeellijst + + + + Core + + + Brightness: %1 + Helderheid: %1 + + + + Contrast: %1 + Contrast: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Tint: %1 + + + + Saturation: %1 + Verzadiging: %1 + + + + Volume: %1 + Volume: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + Lettertype-schaal: %1 + + + + disabled + aspect_ratio + Uitgeschakeld + + + + auto + aspect_ratio + automatisch + + + + Aspect ratio: %1 + Aspectverhouding: %1 + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Welkom bij SMPlayer + + + + Audio + Audio + + + + Subtitle + Ondertiteling + + + + &Main toolbar + &Hoofdwerkbalk + + + + &Language toolbar + &Taalwerkbalk + + + + &Toolbars + &Werkbalken + + + + EqSlider + + + icon + pictogram + + + + ErrorDialog + + + Hide log + Log verbergen + + + + Show log + Log tonen + + + + MPlayer Error + MPlayer foutmelding + + + + icon + pictogram + + + + Error + Foutmelding + + + + FileDownloader + + + Downloading... + Bezig met downloaden... + + + + Downloading %1 + %1 downloaden + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Bestandseigenschappen + + + + &Information + &Informatie + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Kies de demuxer die voor dit bestand gebruikt moet worden: + + + + &Reset + &Herstellen + + + + &Video codec + &Video codec + + + + &Select the video codec: + &Kies de video codec: + + + + A&udio codec + A&udio codec + + + + &Select the audio codec: + &Kies de audio codec: + + + + &MPlayer options + &MPlayer opties + + + + Additional Options for MPlayer + Extra opties voor MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Hier kunt u extra opties aan MPlayer meegeven. +Schrijf ze gescheiden door spaties. +Voorbeeld: -flip -nosound + + + + &Options: + &Opties: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + U kunt ook extra videofilters meegeven. +De videofilters moeten van elkaar gescheiden worden door ",". Gebruik geen spaties! +Voorbeeld: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + V&ideofilters: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + En tot slot audiofilters. Dezelfde regel als voor videofilters. +Voorbeeld: resample=44100:0:0,volnorm + + + + Audio &filters: + Audio&filters: + + + + OK + OK + + + + Cancel + Annuleren + + + + Apply + Toepassen + + + + FindSubtitlesWindow + + + Language + Taal + + + + Name + Naam + + + + Format + Indeling + + + + Files + Bestanden + + + + Date + Datum + + + + Uploaded by + Geupload door + + + + All + Alles + + + + Close + Sluiten + + + + &Download + &Downloaden + + + + &Copy link to clipboard + Link naar klembord &kopiëren + + + + Error + Foutmelding + + + + Download failed: %1. + Downloaden mislukt: %1. + + + + Connecting to %1... + Verbinden met %1... + + + + Downloading... + Bezig met downloaden... + + + + Done. + Klaar. + + + + %1 files available + %1 bestanden beschikbaar + + + + Failed to parse the received data. + Gedownloade gegevens verwerken mislukt. + + + + Find Subtitles + Ondertitels zoeken + + + + &Subtitles for + Ondertitel&s voor + + + + &Language: + Taa&l: + + + + &Refresh + Ve&rnieuwen + + + + Subtitle saved as %1 + Ondertitel opgeslagen als %1 + + + + %1 subtitle(s) extracted + + %1 ondertitel uitgepakt + %1 ondertitels uitgepakt + + + + + Overwrite? + Overschrijven? + + + + The file %1 already exits, overwrite? + Het bestand %1 bestaat al, wilt u het overschrijven? + + + + Error saving file + Fout bij opslaan van het bestand + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Het was niet mogelijk om het gedownload bestand +in de map %1 op te slaan +Controleer a.u.b. de toegangsrechten van die map. + + + + Download failed + Downloaden mislukt + + + + Temporary file %1 + Tijdelijk bestand %1 + + + + InfoFile + + + General + Algemeen + + + + Size + Grootte + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Lengte + + + + Demuxer + Demuxer + + + + Name + Naam + + + + Artist + Artiest + + + + Author + Auteur + + + + Album + Album + + + + Genre + Genre + + + + Date + Datum + + + + Track + Nummer + + + + Copyright + Auteursrecht + + + + Comment + Opmerking + + + + Software + Software + + + + Clip info + Clip info + + + + Video + Video + + + + Resolution + Resolutie + + + + Aspect ratio + Aspectverhouding + + + + Format + Indeling + + + + Bitrate + Bitrate + + + + %1 kbps + %1 kbps + + + + Frames per second + Frames per seconde + + + + Selected codec + Geselecteerde codec + + + + Initial Audio Stream + Oorspronkelijk Audiospoor + + + + Rate + Rate + + + + %1 Hz + %1 Hz + + + + Channels + Kanalen + + + + Audio Streams + Audiosporen + + + + Language + Taal + + + + empty + leeg + + + + Subtitles + Ondertiteling + + + + Type + Type + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Stream-titel + + + + Stream URL + Stream URL + + + + File + Bestand + + + + InputDVDDirectory + + + Choose a directory + Kies een map + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Speel een DVD vanuit een map + + + + Choose a directory... + Kies een map... + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + U kunt een DVD vanaf uw harde schijf afspelen. Kies hiervoor de map die de submappen VIDEO_TS en AUDIO_TS bevat. + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Voer uw MPlayer versie in + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer kon de MPlayer versie die u gebruikt niet bepalen. + + + + Version reported by MPlayer: + Versie gerapporteerd door MPlayer: + + + + Please, &select the correct version: + Kie&s de correcte versie: + + + + 1.0rc1 or older + 1.0rc1 of ouder + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Hoger dan 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - URL invoeren + + + + &URL: + &URL: + + + + It's a &playlist + Het is een afs&peellijst + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Als deze optie is aangevinkt, dan zal de URL als een playlist worden behandeld: het zal worden geopend als een tekstbestand en de URL's in het tekstbestand zullen worden afgespeeld. + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + Afrikaans + + + + Amharic + + + + + Arabic + Arabisch + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + Bulgaars + + + + Bihari + + + + + Bislama + + + + + Bengali + Bengaals + + + + Tibetan + Tibetaans + + + + Breton + Bretoens + + + + Catalan + Catalaans + + + + Corsican + Corsicaans + + + + Czech + Tsjechisch + + + + Welsh + Welsh + + + + Danish + Deens + + + + German + Duits + + + + Greek + Grieks + + + + English + Engels + + + + Esperanto + Esperanto + + + + Spanish + Spaans + + + + Estonian + Ests + + + + Basque + Baskisch + + + + Persian + Perzisch + + + + Finnish + Fins + + + + Fiji + Fiji + + + + Faroese + + + + + French + Frans + + + + Frisian + Fries + + + + Irish + Iers + + + + Galician + Galicisch + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + Hebreeuws + + + + Hindi + Hindi + + + + Croatian + Kroatisch + + + + Hungarian + Hongaars + + + + Armenian + Armeens + + + + Interlingua + + + + + Indonesian + Indonesisch + + + + Interlingue + + + + + Icelandic + + + + + Italian + Italiaans + + + + Inuktitut + + + + + Japanese + Japans + + + + Javanese + + + + + Georgian + Georgisch + + + + Kazakh + Kazachs + + + + Greenlandic + Groenlands + + + + Cambodian + Cambodiaans + + + + Kannada + + + + + Korean + Koreaans + + + + Kashmiri + + + + + Kurdish + Koerdisch + + + + Kirghiz + + + + + Latin + Latijns + + + + Lingala + Lingala + + + + Lithuanian + Litouws + + + + Latvian + Lets + + + + Malagasy + + + + + Maori + Maori + + + + Macedonian + Macedonisch + + + + Malayalam + + + + + Mongolian + Mongools + + + + Moldavian + Moldavisch + + + + Marathi + + + + + Malay + + + + + Maltese + Maltees + + + + Burmese + Burmees + + + + Nauru + + + + + Nepali + + + + + Dutch + Nederlands + + + + Norwegian + Noors + + + + Occitan + Occitaans + + + + Oriya + + + + + Polish + Pools + + + + Portuguese + Portugees + + + + Quechua + + + + + Kirundi + Kirundi + + + + Romanian + Roemeens + + + + Russian + Russisch + + + + Kinyarwanda + + + + + Sanskrit + Sanskriet + + + + Sindhi + + + + + Slovak + Slowaaks + + + + Slovenian + Sloveens + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + Albanees + + + + Serbian + Servisch + + + + Sundanese + Soedanees + + + + Swedish + Zweeds + + + + Swahili + Swahili + + + + Tamil + Tamil + + + + Telugu + + + + + Tajik + + + + + Thai + Thais + + + + Tigrinya + + + + + Turkmen + Turkmeens + + + + Tagalog + + + + + Tonga + + + + + Turkish + Turks + + + + Tsonga + + + + + Tatar + Tataars + + + + Twi + + + + + Uighur + Oeigoers + + + + Ukrainian + Oekraïens + + + + Urdu + + + + + Uzbek + Oezbeeks + + + + Vietnamese + Viëtnamees + + + + Wolof + + + + + Xhosa + + + + + Yiddish + Jiddish + + + + Yoruba + + + + + Zhuang + + + + + Chinese + Chinees + + + + Zulu + Zoeloe + + + + Portuguese - Brazil + Portugees - Brazilië + + + + Portuguese - Portugal + Portugees - Portugal + + + + Simplified-Chinese + Vereenvoudigd Chinees + + + + Traditional Chinese + Traditioneel Chinees + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + West-Europese talen + + + + Western European Languages with Euro + West-Europese talen met Euro-teken + + + + Slavic/Central European Languages + Slavische/Centraal-Europese talen + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galicisch, Maltees, Turks + + + + Old Baltic charset + Oud-Baltisch karakterset + + + + Cyrillic + Cyrillisch + + + + Modern Greek + Modern Grieks + + + + Baltic + Baltisch + + + + Celtic + Keltisch + + + + Hebrew charsets + Hebreeuwse karaktersets + + + + Ukrainian, Belarusian + Oekraïens, Wit-Russisch + + + + Simplified Chinese charset + Vereenvoudigd Chinese karakterset + + + + Traditional Chinese charset + Traditioneel Chinese karakterset + + + + Japanese charsets + Japanse karaktersets + + + + Korean charset + Koreaanse karakterset + + + + Thai charset + Thaise karakterset + + + + Cyrillic Windows + Cyrillisch Windows + + + + Slavic/Central European Windows + Slavisch/Centraal-Europees Windows + + + + Arabic Windows + Arabisch Windows + + + + Rhaeto-Romance + Rhetroromaans + + + + Serbo-Croatian + Servo-Kroatisch + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Kies een bestandsnaam waaronder opgeslagen moet worden + + + + Confirm overwrite? + Bevestig overschrijven? + + + + The file already exists. +Do you want to overwrite? + Het bestand bestaat al. +Wilt u het overschrijven? + + + + Error saving file + Fout bij opslaan van het bestand + + + + The log couldn't be saved + Het logbestand kon niet worden opgeslagen + + + + Logs + Logs + + + + LogWindowBase + + + Log Window + Logvenster + + + + Save + Opslaan + + + + Copy to clipboard + Naar klembord kopiëren + + + + Close + Sluiten + + + + &Close + &Sluiten + + + + MiniGui + + + Control bar + Controlebalk + + + + MpcGui + + + Control bar + Controlebalk + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Naam + + + + Length + Lengte + + + + &Play + Afs&pelen + + + + &Edit + B&ewerken + + + + Playlists + Afspeellijsten + + + + Choose a file + Kies een bestand + + + + Choose a filename + Kies een bestandsnaam + + + + Confirm overwrite? + Bevestig overschrijven? + + + + The file %1 already exists. +Do you want to overwrite? + Het bestand %1 bestaat al. +Wilt u het overschrijven? + + + + All files + Alle bestanden + + + + Select one or more files to open + Kies één of meerdere bestanden om te openen + + + + Choose a directory + Kies een map + + + + Edit name + Naam bewerken + + + + Type the name that will be displayed in the playlist for this file: + Voer de naam in die in de afspeellijst voor dit bestand moet worden weergegeven: + + + + &Load + &Laden + + + + &Save + &Opslaan + + + + &Next + &Volgende + + + + Pre&vious + V&orige + + + + Move &up + &Omhoog verplaatsen + + + + Move &down + O&mlaag verplaatsen + + + + &Repeat + &Herhalen + + + + S&huffle + &Willekeurig + + + + Add &current file + &Huidig bestand toevoegen + + + + Add &file(s) + &Bestand(en) toevoegen + + + + Add &directory + &Map toevoegen + + + + Remove &selected + Verwijder &geselecteerd + + + + Remove &all + Verwijder &alles + + + + SMPlayer - Playlist + SMPlayer - Afspeellijst + + + + Add... + Toevoegen... + + + + Remove... + Verwijderen... + + + + Playlist modified + Afspeellijst aangepast + + + + There are unsaved changes, do you want to save the playlist? + Er zijn niet-opgeslagen wijzigingen, wilt u de afspeellijst opslaan? + + + + Preferences + Voorkeuren + + + + PlaylistPreferences + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Vink deze optie aan als u wilt dat wanneer er een map wordt toegevoegd ook de bestanden in de submappen ervan toegevoegd worden. Anders worden alleen de bestanden in de geselecteerde map toegevoegd. + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Vink deze optie aan als u meer informatie van de bestanden in de afspeellijst wilt. U kunt hierdoor de titel, naam (indien beschikbaar) en de lengte van de bestanden zien. Anders zal deze informatie niet beschikbaar zijn totdat het bestand effectief wordt afgespeeld. Pas op: deze optie kan traag werken, vooral als u veel bestanden toevoegd. + + + + Playlist - Preferences + Afspeellijst - Voorkeuren + + + + &Add files in directories recursively + Best&anden in map recursief toevoegen + + + + Automatically get &info about files added + Automatisch &informatie verkrijgen over de toegevoegde bestanden + + + + &Save copy of playlist on exit + Kopie van afspeelijst op&slaan bij afsluiten + + + + &Play files from start + Bestanden vanaf o&pstarten afspelen + + + + PrefAdvanced + + + Advanced + Geavanceerd + + + + Auto + Automatisch + + + + &Advanced + Ge&avanceerd + + + + icon + pictogram + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Hier kunt u extra opties aan MPlayer meegeven. +Schrijf ze gescheiden door spaties. +Voorbeeld: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + U kunt ook extra videofilters meegeven. +Ze moeten van elkaar gescheiden worden door ",". Gebruik geen spaties! +Voorbeeld: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + En tot slot audiofilters. Dezelfde regel als voor videofilters. +Voorbeeld: resample=44100:0:0,volnorm + + + + Log MPlayer output + MPlayer uitvoer loggen + + + + Log SMPlayer output + SMPlayer uitvoer loggen + + + + This option is mainly intended for debugging the application. + Deze optie is vooral bedoeld om het programma te debuggen. + + + + &MPlayer language + &MPlayer taal + + + + SMPlayer needs to read and parse the output of MPlayer and sometimes it relies on English text. If you are using a MPlayer translated into another language, then you need to change the texts that SMPlayer looks for. (Technically you should enter regular expressions)<br><br> +The drop-down lists may provide already made regular expression for several languages. + SMPlayer moet de uitvoer van MPlayer lezen en verwerken en daardoor is SMPlayer afhankelijk van Engelse tekst. Indien er gebruik gemaakt wordt van een anderstalige MPlayer moeten de onderstaande teksten worden gewijzigd. (Technisch gesproken kunt u het beste reguliere expressies invoeren)<br /><br /> +De drop-down lijsten kunnen al reguliere expressies voor bepaalde talen bevatten. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Deze optie aanvinken kan flikkering verminderen, maar het kan ook een foutieve weergave van de video veroorzaken. + + + + If checked, smplayer will store the output of mplayer (you can see it in <b>Options->View logs->mplayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Vink deze optie aan om de uitvoer van mplayer op te slaan (u kunt de uitvoer bekijken via <b>Opties->Bekijk logs->mplayer</b>). In het geval van problemen kan deze log belangrijke informatie bevatten, dus het wordt aanbevolen om deze optie aan te vinken. + + + + If this option is checked, smplayer will store the debugging messages that smplayer outputs (you can see the log in <b>Options->View logs->smplayer</b>). This information can be very useful for the developer in case you find a bug. + Vink deze optie aan om de debugberichten van smplayer op te slaan (u kunt de berichten bekijken via <b>Opties->Bekijk logs->smplayer</b>). Deze informatie kan heel nuttig zijn voor de ontwikkelaar indien u tegen bugs aanloopt. + + + + Filter for SMPlayer logs + Filter voor SMPlayer logs + + + + This option allows to filter the smplayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Met deze optie kunt u de smplayer berichten filteren die in het log worden opgeslagen. U kunt hier eender welke reguliere expressie neerzetten.<br>Bijvoorbeeld: <i>^Core::.*</i> zal alleen regels tonen die beginnen met <i>Core::</i> + + + + &Monitor aspect: + &Monitor aspect: + + + + &Run MPlayer in its own window + &Laat MPlayer videobestanden in een eigen venster afspelen + + + + &Options: + &Opties: + + + + V&ideo filters: + V&ideofilters: + + + + Audio &filters: + Audio&filters: + + + + &Colorkey: + &Kleursleutel: + + + + Log &SMPlayer output + &SMPlayer uitvoer loggen + + + + &Filter for SMPlayer logs: + &Filter voor SMPlayer logs: + + + + &End of file: + &Einde van bestand: + + + + &No video: + &Geen video: + + + + C&hange... + &Wijzigen... + + + + Logs + Logs + + + + Log MPlayer &output + &MPlayer uitvoer loggen + + + + Options for MP&layer + Opties voor MP&layer + + + + Autosave MPlayer log + MPlayer log automatisch opslaan + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Als deze optie is aangevinkt, dan zal elke keer als er een bestand begint te spelen het MPlayer-log worden opgeslagen in het opgegeven bestand. Het is bedoelt voor externe toepassingen, zodat het informatie kan krijgen over het bestand dat u afspeelt. + + + + Autosave MPlayer log filename + Bestandsnaam voor automatisch opgeslagen MPlayer log + + + + Enter here the path and filename that will be used to save the MPlayer log. + Voer hier het pad en bestandsnaam in dat gebruikt zal worden om het MPlayer log op te slaan. + + + + A&utosave MPlayer log to file + MPlayer log a&utomatisch in bestand opslaan + + + + Pass short filenames (8+3) to MPlayer + Korte bestandsnamen (8+3) aan MPlayer doorgeven + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + MPlayer kan momenteel geen bestanden openen die karakters bevatten die buiten de lokale codepage vallen. Door deze optie aan te vinken zal SMPlayer de korte versie van de bestandsnamen aan MPlayer doorgeven, en zal ze zodoende kunnen openen. + + + + &Pass short filenames (8+3) to MPlayer + &Korte bestandsnamen (8+3) aan MPlayer doorgeven + + + + Monitor aspect + Monitor aspect + + + + Select the aspect ratio of your monitor. + Kies de aspectverhouding van uw monitor. + + + + Run MPlayer in its own window + MPlayer in eigen venster uitvoeren + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Als u deze optie aanvinkt, zal het MPlayer videovenster niet in het hoofdvenster van SMPlayer worden ingebed, maar in plaats daarvan een eigen venster gebruiken. Merk op dat toetsenbord- en muishandelingen rechtstreeks door MPlayer zullen worden afgehandeld, dit betekent dat sneltoetsen en muisklikken waarschijnlijk niet zullen werken zoals verwacht zodra het MPlayer-venster de focus heeft. + + + + Colorkey + Kleursleutel + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Als u delen van de video over een ander venster heen ziet, dan kunt u de kleursleutel wijzigen om het te corrigeren. Probeer een kleur te kiezen die dicht bij zwart ligt. + + + + Options for MPlayer + Opties voor MPlayer + + + + Options + Opties + + + + Here you can type options for MPlayer. Write them separated by spaces. + Hier kunt u opties voor MPlayer intypen. Schrijf ze gescheiden door spaties. + + + + Video filters + Videofilters + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Hier kunt u videofilters voor MPlayer toevoegen. Schrijf ze gescheiden door komma's. Gebruik geen spaties! + + + + Audio filters + Audio filters + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Hier kunt u audiofilters voor MPlayer toevoegen. Schrijf ze gescheiden door komma's. Gebruik geen spaties! + + + + MPlayer language + MPlayer taal + + + + End of file + Einde van bestand + + + + Select or type a regular expression for 'End of file' + Kies of typ een reguliere expressie voor 'Einde van bestand' + + + + No video + Geen video + + + + Select or type a regular expression for 'No video' + Kies of typ een reguliere expressie voor 'Geen video' + + + + Repaint the background of the video window + Repaint uitvoeren op de achtergrond van het videovenster + + + + Repaint the backgroun&d of the video window + Repaint uitvoeren op de achtergron&d van het videovenster + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + IPv4 op netwerkverbindingen gebruiken. Valt automatisch terug op IPv6. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + IPv6 op netwerkverbindingen gebruiken. Valt automatisch terug op IPv4. + + + + Network Connection + Netwerkverbinding + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + Lo&gs + + + + Rebuild index if needed + Index herbouwen indien nodig + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Herbouwt bestandsindex indien geen index werd gevonden, hierdoor wordt zoeken mogelijk gemaakt. Handig bij onderbroken/niet complete downloads, of slecht gemaakte bestanden. De optie werkt alleen als de onderliggende media zoeken ondersteunt (d.w.z. niet met stdin, pipe, etc).<br>Let op: het aanmaken van de index kan enige tijd duren. + + + + Rebuild &index if needed + &Index herbouwen indien nodig + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Vink deze optie aan om de debugberichten van SMPlayer op te slaan (u kunt de berichten bekijken via <b>Opties->Bekijk logs->SMPlayer</b>). Deze informatie kan heel nuttig zijn voor de ontwikkelaar indien u tegen bugs aanloopt. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Vink deze optie aan om de uitvoer van MPlayer op te slaan (u kunt de uitvoer bekijken via <b>Opties->Bekijk logs->MPlayer</b>). In het geval van problemen kan deze log belangrijke informatie bevatten, dus het wordt aanbevolen om deze optie aan te vinken. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Met deze optie kunt u de smplayer berichten filteren die in het log worden opgeslagen. U kunt hier eender welke reguliere expressie neerzetten.<br>Bijvoorbeeld: <i>^Core::.*</i> zal alleen regels tonen die beginnen met <i>Core::</i> + + + + Correct pts + Correcte pts + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Schakeld MPlayer naar een experimentele modus over waar tijdstempels voor videoframes anders worden berekend en videofilters die nieuwe frames toevoegen of tijdstempels van bestaande wijzigen worden ondersteund. De meer accurate tijdstempels kunnen zichtbaar zijn wanneer er bijvoorbeeld ondertitels zijn getimed naar scènes met de SSA/ASS-bibliotheek ingeschakeld. Zonder correcte pts zal de timing van ondertitels een paar frames fout zitten. Deze optie werkt niet correct met enkele demuxers en codecs. + + + + Proxy + Proxy + + + + Enable proxy + Proxy inschakelen + + + + Enable/disable the use of the proxy. + Het gebruik van een proxy in-/uitschakelen. + + + + Host + Host + + + + The host name of the proxy. + De hostnaam van de proxy. + + + + Port + Poort + + + + The port of the proxy. + De poort van de proxy. + + + + Username + Gebruikersnaam + + + + If the proxy requires authentication, this sets the username. + Indien de proxy authentificatie nodig heeft stelt dit de gebruikersnaam in. + + + + Password + Wachtwoord + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + Het wachtwoord voor de proxy. Waarschuwing: het wachtwoord zal als gewone tekst worden opgeslagen in het configuratiebestand. + + + + Pro&xy + Pro&xy + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + U kunt een proxy voor internetverbindingen instellen (momenteel alleen gebruikt voor het downloaden van ondertitels). + + + + &Enable proxy + Proxy inschak&elen + + + + &Host: + &Host: + + + + &Port: + &Poort: + + + + &Username: + Gebr&uikersnaam: + + + + Pa&ssword: + Wa&chtwoord: + + + + C&orrect PTS + C&orrecte PTS + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + Type + + + + Select the proxy type to be used. + Selecteer het te gebruiken type proxy. + + + + &Type: + &Type: + + + + Actions list + Actielijst + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + Hier kunt u een lijst <i>acties</i> instellen die zullen worden uitgevoerd elke keer een bestand wordt geopend. U kunt alle beschikbare acties vinden in de sneltoetsbewerker in de sectie <b>Toetsenbord en muis</b>. De acties moeten worden gescheiden door spaties. Aanvinkbare acties kunnen worden gevolgd door <i>true</i> of <i>false</i> om de actie in- of uit te schakelen. + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + Beperking: de acties worden alleen uitgevoerd wanneer een bestand wordt geopend en niet als mplayer wordt herstart (als u bijv. een audio- of videofilter kiest). + + + + Network + Netwerk + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + Volgende actie &uitvoeren elke keer een bestand geopend wordt. De acties moeten worden gescheiden met spaties: + + + + &Network + &Netwerk + + + + Example: + Voorbeeld: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Waarschuwing + + + + Not all files could be associated. Please check your security permissions and retry. + Niet alle bestanden konden worden geassocieerd. Controleer uw beveiligingsinstellingen en probeer opnieuw. + + + + File Types + Bestandstypen + + + + Select all + Alles selecteren + + + + Check all file types in the list + Alle bestandstypen in de lijst aanvinken + + + + Uncheck all file types in the list + Alle bestandstypen in de lijst uitvinken + + + + List of file types + Bestandstypenlijst + + + + File types + Bestandstypen + + + + Media files handled by SMPlayer: + Mediabestanden die met SMPlayer worden afgespeeld: + + + + Select All + Alles selecteren + + + + Select None + Niets selecteren + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Vink de mediabestandsextensies aan waarvan u wilt dat ze met SMPlayer worden afgespeeld. Zodra u op Toepassen klikt, zullen de aangevinkte bestanden met SMPlayer worden geassocieerd. Als u een mediatype uitvinkt, zal de bestandsassociatie worden hersteld. + + + + Select none + Niets selecteren + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Let op:</b> (Herstellen werkt niet onder Windows Vista). + + + + PrefDrives + + + Drives + Stations + + + + icon + pictogram + + + + CD device + CD-apparaat + + + + DVD device + DVD-apparaat + + + + Choose your DVD device. It will be used to play DVDs. + Kies het DVD-apparaat. Het zal gebruikt worden om DVD-films af te spelen. + + + + Select your &CD device: + Kies &CD-apparaat: + + + + Select your &DVD device: + Kies &DVD-apparaat: + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Kies het CDROM-apparaat. Het zal gebruikt worden om Video CD's (VCD's) en Audio-CD's af te spelen. + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer kiest standaard geen CDROM- of DVD-stations. Dus voordat u een CD of DVD kunt afspelen, moet u de te gebruiken apparaten selecteren (ze kunnen gelijk zijn). + + + + PrefGeneral + + + General + Algemeen + + + + &General + Al&gemeen + + + + Paths + Paden + + + + Output drivers + Uitvoerdrivers + + + + Media settings + Media-instellingen + + + + Preferred audio and subtitles + Audio- en ondertiteling-voorkeuren + + + + Video + Video + + + + Start videos in fullscreen + Video's beeldvullend starten + + + + Disable screensaver + Schermbeveiliging uitschakelen + + + + Audio + Audio + + + + Select the mplayer executable + Kies het mplayer uitvoerbaar bestand + + + + Executables + Uitvoerbare bestanden (executables) + + + + All files + Alle bestanden + + + + Select a directory + Kies een map + + + + MPlayer executable + MPlayer uitvoerbaar bestand + + + + Here you must specify the mplayer executable that smplayer will use.<br>smplayer requires at least mplayer 1.0rc1 (svn recommended).<br><b>If this setting is wrong, smplayer won't be able to play anything!</b> + Hier moet u het mplayer uitvoerbaar bestand kiezen dat smplayer zal gebruiken.<br />smplayer vereist ten minste mplayer 1.0rc1 (svn aanbevolen)<br /><b>Als deze instelling onjuist is, dan zal smplayer niets kunnen afspelen!</b> + + + + Screenshots folder + Map voor schermafdrukken + + + + Here you can specify a folder where the screenshots taken by smplayer will be stored. If this field is empty the screenshot feature will be disabled. + Hier kunt u een map instellen waar de schermafdrukken die door smplayer genomen worden bewaard kunnen worden. Als dit veld leeg is zal de schermafdruk-functionaliteit worden uitgeschakeld. + + + + Video output driver + Video-uitvoer driver + + + + Select the video output driver. Usually xv (linux) and directx (windows) provide the best performance. + Kies de video-uitvoer driver. Doorgaans leveren xv (linux) en directx (windows) de beste prestaties. + + + + Audio output driver + Audio-uitvoer driver + + + + Select the audio output driver. + Kies de audio-uitvoer driver. + + + + Remember settings + Instellingen onthouden + + + + Usually smplayer will remember the settings for each file you play (audio track selected, volume, filters...). Uncheck this option if you don't like this feature. + Normaalgesproken onthoudt smplayer de instellingen voor elk bestand dat u afspeelt (geselecteerde audiospoor, volume, filters...). Vink deze optie uit als u geen gebruik wilt maken van deze mogelijkheid. + + + + If you check this option, smplayer will play all files from the beginning. + Als u deze optie aanvinkt, dan zal SMPlayer alle bestanden vanaf het begin afspelen. + + + + Preferred audio language + Taalvoorkeur voor audiosporen + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, smplayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Hier kunt u een voorkeurstaal instellen voor audiosporen. Wanneer een mediabestand met meerdere audiosporen wordt gevonden, dan zal smplayer proberen om uw voorkeurstaal te gebruiken.<br>Dit werkt alleen bij mediabestanden die informatie bieden over de taal van de audiosporen, zoals DVD's of MKV-bestanden.<br>Dit veld accepteert reguliere expressies. Voorbeeld: <b>es|esp|spa</b> zal het audiospoor selecteren indien het overeenkomt met <i>es</i>, <i>esp</i> of <i>spa</i>. + + + + Preferred subtitle language + Taalvoorkeur voor ondertiteling + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, smplayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Hier kunt u een voorkeurstaal instellen voor ingebedde ondertiteling. Wanneer een mediabestand met meerdere ondertiteling-streams wordt gevonden, dan zal smplayer proberen om uw voorkeurstaal te gebruiken.<br>Dit werkt alleen bij mediabestanden die informatie bieden over de taal van de ondertiteling-streams, zoals DVD's of MKV-bestanden.<br>Dit veld accepteert reguliere expressies. Voorbeeld: <b>es|esp|spa</b> zal het ondertiteling-spoor selecteren indien het overeenkomt met <i>es</i>, <i>esp</i> of <i>spa</i>. + + + + Software video equalizer + Softwarematige video-equalizer + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + U kunt deze optie aanvinken als de video-equalizer niet wordt ondersteund door uw grafische kaart of door de geselecteerde video-uitvoer driver.<br /><b>Let op:</b> deze optie kan incompatibel zijn met sommige video-uitvoer drivers. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Als u deze optie aanvinkt, dan zullen alle videobestanden starten in beeldvullende modus. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes.<br><b>Note:</b> This option works only in X11 and Windows. + Vink deze optie aan om de schermbeveiliging uit te schakelen tijdens het afspelen.<br />De schermbeveiliging zal weer worden ingeschakeld zodra het afspelen is voltooid.<br /><b>Let op:</b> Deze optie werkt alleen in X11 en Windows. + + + + Software volume control + Softwarematige volumeregeling + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Vink deze optie aan om de software mixer te gebruiken, in plaats van de geluidskaart mixer. + + + + Postprocessing quality + Kwaliteit van nabewerking + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Wijzigt dynamisch het niveau van nabewerking, afhankelijk van de beschikbare processortijd. Het getal dat u instelt zal het maximum niveau zijn dat gebruikt zal worden. Gewoonlijk kunt u een groot nummer gebruiken. + + + + Change volume + Volume aanpassen + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Als deze optie is aangevinkt, dan zal SMPlayer het geluidsniveau van elk bestand onthouden. Voor nieuwe bestanden wordt het standaard geluidsniveau gebruikt. + + + + 0 + 0 + + + + &Change volume on every file + &Volume bij elk bestand wijzigen + + + + Select the &MPlayer executable: + Kies het &MPlayer uitvoerbaar bestand: + + + + &Folder for storing screenshots: + Map om scherma&fdrukken in op te slaan: + + + + V&ideo: + V&ideo: + + + + &Audio: + &Audio: + + + + &Remember settings for all files (audio track, subtitles...) + Instellingen voo&r alle bestanden onthouden (audiospoor, ondertiteling...) + + + + Su&btitles: + &Ondertiteling: + + + + &Quality: + K&waliteit: + + + + Start videos in &fullscreen + Videobestanden beel&vullend starten + + + + Disable &screensaver + &Schermbeveiliging uitschakelen + + + + &Default volume: + Stan&daard volume: + + + + Use s&oftware volume control + Gebruikt s&oftwarematige volumeregeling + + + + Ma&x. Amplification: + Ma&x. versterking: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS pass-through S/PDIF + + + + Direct rendering + Direct rendering + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Indien aangevinkt, schakelt het 'direct rendering' in (wordt niet ondersteund door alle codecs en video-uitvoer drivers)<br /><b>WAARSCHUWING:</b> Veroorzaakt mogelijk OSD/SUB corruptie! + + + + Double buffering + Dubbel bufferen + + + + D&irect rendering + D&irect rendering + + + + Dou&ble buffering + Du&bbel bufferen + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + 'Dubbel bufferen' verwijdert flikkering door twee frames in het geheugen te plaatsen, en slechts één frame weer te geven terwijl het andere gedecodeerd wordt. Als deze optie is uitgeschakeld kan het OSD negatief beïnvloed worden, maar vaak elimineert het flikkering van het OSD. + + + + &Enable postprocessing by default + &Nabewerking standaard inschakelen + + + + Volume &normalization by default + Volume standaard &normaliseren + + + + Close when finished + Sluiten na afloop + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Als deze optie is aangevinkt, dan zal het hoofdvenster automatisch gesloten worden wanneer het huidige bestand of de huidige afspeellijst is afgelopen. + + + + &Close when finished + &Sluiten na afloop + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + &Standaard kanalen: + + + + &Pause when minimized + &Pauzeer indien geminimaliseerd + + + + Pause when minimized + Pauzeer indien geminimaliseerd + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, play will be resumed. + Als deze optie is geactiveerd, zal het bestand worden gepauzeerd als het hoofdscherm wordt verborgen. Zodra het venster wordt hersteld, zal het afspelen worden voortgezet. + + + + Enable postprocessing by default + Nabewerking standaard inschakelen + + + + Postprocessing will be used by default on new opened files. + Standaard zal nabewerking worden gebruikt bij nieuw geopende bestanden. + + + + Max. Amplification + Max. versterking + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Stelt het maximum versterkingsniveau in procenten in (standaard: 110). Met een waarde van 200 kunt u het volume aanpassen tot en met een maximum van het dubbele van het huidige niveau. Met waarden onder de 100 zal het beginvolume (wat 100% is) boven het maximum liggen, dat bijv. de OSD niet correct kan weergeven. + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Uses hardware AC3 passthrough + Gebruikt hardwarematige AC3 pass-through + + + + Volume normalization by default + Volume standaard normaliseren + + + + Maximizes the volume without distorting the sound. + Maximaliseert het volume zonder het geluid te vervormen. + + + + Default volume + Standaardvolume + + + + Sets the initial volume that new files will use. + Stelt het beginvolume in dat voor nieuwe bestanden zal worden gebruikt. + + + + Channels by default + Standaard kanalen + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Vraagt om het aantal weergavekanalen. MPlayer vraagt aan de decoder om de audio in evenveel kanalen te decoderen als is opgegeven. Daarna is het aan de decoder om de vereiste te vervullen. Dit is normaal gesproken alleen belangrijk bij het afspelen van video's met AC3 audio (zoals DVD's). In dat geval doet liba52 standaard al het decodeerwerk en reduceert de audio op de juiste wijze naar het verzochte aantal kanalen. LET OP: Deze optie wordt gehonoreerd door codecs (alleen AC3), filters (surround), en stuurprogramma's voor audio-uitvoer (in elk geval OSS). + + + + Audio track + Audiospoor + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Specificeert het standaard audiospoor dat bij het afspelen van nieuwe bestanden moet worden gebruikt. Als het spoor niet bestaat, zal de eerste worden gebruikt. <br><b>Let op:</b> de <i>"voorkeurstaal voor audiosporen"</i> heeft voorrang boven deze optie. + + + + Subtitle track + Ondertiteling-spoor + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Specificeert het standaard ondertitel-spoor dat bij het afspelen van nieuwe bestanden moet worden gebruikt. Als het spoor niet bestaat, zal de eerste worden gebruikt. <br><b>Let op:</b> de <i>"voorkeurstaal voor ondertiteling"</i> heeft voorrang boven deze optie. + + + + Or choose a track number: + Of kies het spoornummer: + + + + Audi&o: + Audi&o: + + + + Preferred language: + Voorkeurstaal: + + + + Preferre&d audio and subtitles + Au&dio- en ondertiteling-voorkeuren + + + + &Subtitle: + &Ondertiteling: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Hier kunt u uw voorkeurstaal voor audio- en ondertiteling-streams opgeven. Zodra een media met meerdere audio- of ondertiteling-streams wordt gevonden, zal SMPlayer proberen om uw voorkeurstaal te gebruiken. Dit werkt alleen met media dat info biedt over de talen van audio- en ondertiteling-stromen, zoals DVD's of MKV-bestanden.<br>Deze velden accepteren reguliere expressies. Voorbeeld: <b>es|esp|spa</b> zal het spoor kiezen als het overeenkomt met <i>es</i>, <i>esp</i> of <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + High speed &playback without altering pitch + Snel afs&pelen zonder toonhoogte te veranderen + + + + High speed playback without altering pitch + Snel afspelen zonder toonhoogte te veranderen + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Hiermee kunt u de afspeelsnelheid wijzigen zonder de toonhoogte te veranderen. Vereist minimaal MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Volume vlak voor het afspelen wijzigen + + + + If this option is checked the initial volume will be set by using the <i>-volume</i> option in MPlayer.<br> <b>WARNING: THE OFFICIAL MPLAYER DOESN'T HAVE THAT <i>-volume</i> OPTION, YOU NEED A PATCHED ONE, OTHERWISE MPLAYER WILL FAIL AND WON'T PLAY ANYTHING.</b> + Als deze optie is aangevinkt zal het beginvolume worden ingesteld met behulp van de <i>-volume</i> optie van MPlayer.<br> <b>WAARSCHUWING: DE OFFICIËLE MPLAYER HEEFT DIE <i>-volume</i> OPTIE NIET, U HEBT EEN GEPATCHTE NODIG, ANDERS ZAL MPLAYER NIET STARTEN EN ZAL ER NIKS WORDEN AFGESPEELD.</b> + + + + &Video + &Video + + + + Use s&oftware video equalizer + Gebruik s&oftwarematige video-equalizer + + + + A&udio + A&udio + + + + Volume + Volume + + + + None + Geen + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normaal) + + + + Yadif (double framerate) + Yadif (dubbele framerate) + + + + Linear Blend + Lineaire Blend + + + + Kerndeint + Kerndeint + + + + Deinterlace by default + Standaard deinterlace + + + + Select the deinterlace filter that you want to be used for new videos opened. + Selecteer de deinterlacefilter die u wilt gebruiken voor nieuw geopende video's. + + + + Dei&nterlace by default: + Standaard dei&nterlace: + + + + Remember time position + Tijdpositie onthouden + + + + Remember &time position + &Tijdpositie onthouden + + + + Change volume just before p&laying + Volume aanpassen juist voor het afspe&len + + + + Enable the audio equalizer + Audio-equalizer inschakelen + + + + Check this option if you want to use the audio equalizer. + Vink deze optie aan als u de audio-equalizer wilt gebruiken. + + + + &Enable the audio equalizer + Audio-&equalizer inschakelen + + + + Draw video using slices + Video tekenen met slices + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Het tekenen van een video met 16 pixels hoge schijven/banden inschakelen/uitschakelen. Indien uitgeschakeld zal het hele frame getekend worden in één keer. Kan sneller of trager zijn, afhankelijk van de videokaart en beschikbare cache. Dit heeft alleen effect met de codecs libmpeg2 en libavcodec. + + + + Dra&w video using slices + Video te&kenen met slices + + + + &Close when finished playback + &Sluiten wanneer klaar met afspelen + + + + fast + snel + + + + slow + traag + + + + fastest + snelst + + + + fast - ATI cards + snel - ATI-kaarten + + + + User defined... + Gebruikersgedefinieerd... + + + + Default zoom + Standaard zoom + + + + This option sets the default zoom which will be used for new videos. + Deze optie stelt de standaard zoom in die voor nieuwe video's zal worden gebruikt. + + + + Default &zoom: + Standaard &zoom: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Hier moet u het mplayer uitvoerbaar bestand kiezen dat SMPlayer zal gebruiken.<br />SMPlayer vereist ten minste MPlayer 1.0rc1 (hoewel een recente svn-versie aanbevolen is). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Als deze instelling fout is, zal SMPlayer niet in staat zijn iets af te spelen! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Hier kunt u een map instellen waar de schermafdrukken die door SMPlayer genomen worden bewaard kunnen worden. Als dit veld leeg is zal de schermafdruk-functionaliteit worden uitgeschakeld. + + + + Select the video output driver. %1 provides the best performance. + Kies de video-uitvoer driver. %1 levert de beste prestaties. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 wordt aangeraden. Probeer %2 en %3 te vermijden, ze zijn traag en kunnen een impact hebben op de prestaties. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + Normaalgesproken onthoudt SMPlayer de instellingen voor elk bestand dat u afspeelt (geselecteerde audiospoor, volume, filters...). Vink deze optie uit als u geen gebruik wilt maken van deze mogelijkheid. + + + + If you check this option, SMPlayer will play all files from the beginning. + Als u deze optie aanvinkt, dan zal SMPlayer alle bestanden vanaf het begin afspelen. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Als deze optie is geactiveerd, zal het bestand worden gepauzeerd als het hoofdscherm wordt verborgen. Zodra het venster wordt hersteld, zal het afspelen worden voortgezet. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Vink deze optie aan om de schermbeveiliging uit te schakelen tijdens het afspelen.<br>De schermbeveiliging zal weer worden ingeschakeld zodra het afspelen is voltooid. + + + + If this option is checked the initial volume will be set by using the <i>-volume</i> option in MPlayer. + Als u deze optie aanvinkt zal het begin volume worden ingesteld door de optie <i>-volume</i> in MPlayer. + + + + WARNING: THE OFFICIAL MPLAYER DOESN'T HAVE THAT <i>-volume</i> OPTION, YOU NEED A PATCHED ONE, OTHERWISE MPLAYER WILL FAIL AND WON'T PLAY ANYTHING. + WAARSCHUWING: DE OFFICIËLE MPLAYER HEEFT DEZE OPTIE <i>-volume</i> NIET, U HEEFT EEN GEPATCHTE VERSIE NODIG, ANDERS ZAL MPLAYER NIETS AFSPELEN. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Hier kunt u een voorkeurstaal instellen voor audiosporen. Wanneer een mediabestand met meerdere audiosporen wordt gevonden, dan zal SMPlayer proberen om uw voorkeurstaal te gebruiken.<br>Dit werkt alleen bij mediabestanden die informatie bieden over de taal van de audiosporen, zoals DVD's of MKV-bestanden.<br>Dit veld accepteert reguliere expressies. Voorbeeld: <b>es|esp|spa</b> zal het audiospoor selecteren indien het overeenkomt met <i>es</i>, <i>esp</i> of <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Hier kunt u een voorkeurstaal instellen voor ingebedde ondertiteling. Wanneer een mediabestand met meerdere ondertiteling-streams wordt gevonden, dan zal SMPlayer proberen om uw voorkeurstaal te gebruiken.<br>Dit werkt alleen bij mediabestanden die informatie bieden over de taal van de ondertiteling-streams, zoals DVD's of MKV-bestanden.<br>Dit veld accepteert reguliere expressies. Voorbeeld: <b>es|esp|spa</b> zal het ondertiteling-spoor selecteren indien het overeenkomt met <i>es</i>, <i>esp</i> of <i>spa</i>. + + + + Ou&tput driver: + Ui&tvoerdriver: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Indien deze optie is aangevinkt zal het volume worden ingesteld juist voor het afspelen start. Dit voorkomt een hoog volume tijdens het starten. U heeft hiervoor tenminste MPlayer SVN r27872 nodig. + + + + Add black borders on fullscreen + Zwarte randen aan volledig scherm toevoegen + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Als deze optie is geactiveerd, zullen zwarte randen aan de afbeelding worden toegevoegd in volledig scherm. Hierdoor kunnen ondertitels op de zwarte randen getoond worden. + + + + &Add black borders on fullscreen + Zw&arte randen aan volledig scherm toevoegen + + + + one ini file + één ini-bestand + + + + multiple ini files + meerdere ini-bestanden + + + + Method to store the file settings + Methode om bestandsinstellingen op te slaan + + + + This option allows to change the way the file settings would be stored. The following options are available: + Met deze optie kan u de manier waarop de bestandsinstellingen worden opgeslagen veranderen. De volgende opties zijn beschikbaar: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>één ini-bestand</b>: de instellingen voor alle afgespeelde bestanden worden opgeslagen in één bestand (%1) + + + + The latter method could be faster if there is info for a lot of files. + De laatste mogenlijkheid kan sneller zijn als er veel bestanden moeten worden bijgehouden. + + + + &Store settings in + Instellingen op&slaan in + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>meerdere ini-bestanden</b>: één ini-bestand wordt gebruikt voor elk afgespeeld bestand. Deze ini-bestanden worden opgeslagen in de map %1 + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Toetsenbord en muis + + + + &Keyboard + &Toetsenbord + + + + icon + pictogram + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Hier kunt u elke sneltoets wijzigen. Doe dit door op de betreffende cel te dubbelklikken of over de sneltoets-cel beginnen met typen. Optioneel kunt u uw sneltoetsen-configuratie opslaan zodat u het met andere mensen kan delen of zodat u het op een andere computer kan inladen. + + + + &Mouse + &Muis + + + + Button functions: + Toetsfuncties: + + + + Media seeking + Media zoeken + + + + Volume control + Volumeregeling + + + + Zoom video + Video zoomen + + + + None + Geen + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Hier kunt u elke sneltoets wijzigen. Doe dit door op de betreffende cel te dubbelklikken of op de sneltoets-cel op Enter te drukken. Optioneel kunt u uw sneltoetsen-configuratie opslaan zodat u het met andere mensen kan delen of zodat u het op een andere computer kan inladen. + + + + &Left click + &Linker muisklik + + + + &Double click + &Dubbelklik + + + + &Wheel function: + &Wielfunctie: + + + + Shortcut editor + Sneltoetsen-editor + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + In deze tabel kunt u de sneltoetsen van de meeste beschikbare acties wijzigen. Dubbelklik of druk op Enter op een item, of klik op de knop <b>Sneltoets wijzigen</b> om het in het <i>Sneltoets aanpassen</i>-venter in te voeren. Er zijn twee manieren om een sneltoets te wijzigen: als de <b>Opvangen</b>-knop aan staat, druk dan gewoon op de nieuwe toets of toetsencombinatie die u aan de geselecteerde actie wilt toewijzen (dit werkt helaas niet met alle toetsen). Als de <b>Opvangen</b>-knop uitstaat, dan kunt u de volledige naam van de toets invoeren. + + + + Left click + Linker-klik + + + + Select the action for left click on the mouse. + Kies de actie voor linker muisklik. + + + + Double click + Dubbelklik + + + + Select the action for double click on the mouse. + Kies de actie voor dubbele muisklik. + + + + Wheel function + Wielfunctie + + + + Select the action for the mouse wheel. + Kies de actie voor het muiswiel. + + + + Play + Afspelen + + + + Pause + Pauze + + + + Stop + Stop + + + + Fullscreen + Beeldvullend + + + + Compact + Compact + + + + Screenshot + Schermafdruk + + + + On top + Bovenop + + + + Mute + Dempen + + + + Frame counter + Frameteller + + + + Reset zoom + Zoom herstellen + + + + Exit fullscreen + Beeldvullend verlaten + + + + Double size + Dubbele grootte + + + + Play / Pause + Afspelen / Pauzeren + + + + Pause / Frame step + Pauze / Frame stap + + + + Playlist + Afspeellijst + + + + Preferences + Voorkeuren + + + + No function + Geen functie + + + + Change speed + Snelheid wijzigen + + + + Show equalizer + Equalizer weergeven + + + + Normal speed + Normale snelheid + + + + Keyboard + Toetsenbord + + + + Mouse + Muis + + + + Middle click + Middel-klik + + + + Select the action for middle click on the mouse. + Kies de actie voor middelste muisklik. + + + + Go backward (short) + Ga terug (kort) + + + + Go backward (medium) + Ga terug (medium) + + + + Go backward (long) + Ga terug (lang) + + + + Go forward (short) + Ga vooruit (kort) + + + + Go forward (medium) + Ga vooruit (medium) + + + + Go forward (long) + Ga vooruit (lang) + + + + OSD - Next level + OSD - Volgende niveau + + + + Show context menu + Contekstmenu tonen + + + + M&iddle click + Mi&ddel-klik + + + + X Button &1 + X knop &1 + + + + X Button &2 + X knop &2 + + + + &Right click + &Rechter muisklik + + + + Increase volume + Volume verhogen + + + + Decrease volume + Volume verlagen + + + + X Button 1 + X knop 1 + + + + Select the action for the X button 1. + Selecteer de actie voor X knop 1. + + + + X Button 2 + X knop 2 + + + + Select the action for the X button 2. + Selecteer de actie voor X knop 2. + + + + Show video equalizer + Video-equalizer tonen + + + + Show audio equalizer + Audio-equalizer tonen + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Interface + + + + <Autodetect> + <Automatisch detecteren> + + + + Default + Standaard + + + + &Interface + &Interface + + + + Seeking + Zoeken + + + + Never + Nooit + + + + Whenever it's needed + Indien nodig + + + + Only after loading a new video + Alleen na laden van een nieuw videobestand + + + + Recent files + Recente bestanden + + + + Language + Taal + + + + Here you can change the language of the application. + Hier kunt u de taal van het programma aanpassen. + + + + Instances + Instanties + + + + &Short jump + &Korte sprong + + + + &Medium jump + &Middellange sprong + + + + &Long jump + &Lange sprong + + + + Mouse &wheel jump + Muis&wiel sprong + + + + &Use only one running instance of SMPlayer + Gebr&uik slechts één draaiende instantie van SMPlayer + + + + Ma&x. items + Ma&x. items + + + + St&yle: + &Stijl: + + + + Ico&n set: + Pictogramme&n-set: + + + + L&anguage: + T&aal: + + + + Main window + Hoofdvenster + + + + Auto&resize: + Automatisch he&rschalen: + + + + R&emember position and size + Positi&e en grootte onthouden + + + + Default font: + Standaardlettertype: + + + + &Change... + &Wijzigen... + + + + &Behaviour of time slider: + &Gedrag van tijdschuif: + + + + Seek to position while dragging + Tijdens slepen naar positie zoeken + + + + Seek to position when released + Na loslaten naar positie zoeken + + + + TextLabel + TextLabel + + + + &Seeking + &Zoeken + + + + Ins&tances + Ins&tanties + + + + Autoresize + Automatisch herschalen + + + + The main window can be resized automatically. Select the option you prefer. + Het hoofdvenster kan automatisch worden geschaald. Kies de gewenste optie. + + + + Remember position and size + Positie en grootte onthouden + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Als u deze optie aanvinkt, zullen de positie en de grootte van het hoofdvenster worden opgeslagen en worden hersteld zodra u SMPlayer weer start. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Kies het maximum aantal items dat in het <b>Openen -> Recente bestanden</b> submenu zal worden weergegeven. Als u het op 0 instelt, wordt het menu niet weergegeven. + + + + Icon set + Pictogrammen-set + + + + Select the icon set you prefer for the application. + Kies de pictogrammen-set die u voor de toepassing wilt gebruiken. + + + + Style + Stijl + + + + Select the style you prefer for the application. + Kies de stijl die u voor de toepassing wilt gebruiken. + + + + Default font + Standaardlettertype + + + + You can change here the application's font. + U kunt hier het lettertype van de toepassing wijzigen. + + + + Short jump + Korte sprong + + + + Select the time that should be go forward or backward when you choose the %1 action. + Kies de tijd waarmee vooruit of achteruit gesprongen moet worden als u de %1-actie kiest. + + + + short jump + korte sprong + + + + Medium jump + Middellange sprong + + + + medium jump + middellange sprong + + + + Long jump + Lange sprong + + + + long jump + lange sprong + + + + Mouse wheel jump + Muiswiel sprong + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Kies de tijd waarmee vooruit of achteruit gesprongen moet worden als u het muiswiel beweegt. + + + + Behaviour of time slider + Gedrag van tijdschuif + + + + Select what to do when dragging the time slider. + Kies wat er bij het slepen van de tijdschuif moet gebeuren. + + + + Use only one running instance of SMPlayer + Slechts één draaiende instantie van SMPlayer gebruiken + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Vink deze optie aan indien u bij het openen van andere bestanden een reeds draaiende instantie van SMPlayer wilt gebruiken. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer moet naar een poort luisteren om commando's van andere instanties te kunnen ontvangen. U kunt deze poort wijzigen voor het geval dat de standaardpoort door een andere toepassing wordt gebruikt. + + + + Default GUI + Standaard GUI + + + + Mini GUI + Mini GUI + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Selecteer de GUI die u in het programma wilt. Momenteel zijn er twee beschikbaar: Standaard GUI en Mini GUI. <br>De <b>Standaard GUI</b> is een traditionele interface met werbalken. De <b>Mini GUI</b> is eenvoudiger, zonder werkbalken en met maar een paar knoppen. <br><b>Merk op:</b> deze optie zal pas effect hebben de volgende keer dat u SMPlayer gebruikt. + + + + &GUI + &GUI + + + + (this option requires to restart SMPlayer) + (voor deze optie moet u SMPlayer herstarten) + + + + Automatic port + Automatische poort + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer moet naar een poort luisteren om commando's van anderen te ontvangen. Als u deze optie selecteert zal er automatisch een poort gekozen worden. + + + + Manual port + Handmatige poort + + + + Port to listen + Te beluisteren poort + + + + &Automatic + &Automatisch + + + + &Manual + &Handmatig + + + + Floating control + Drijvende controle + + + + Animated + Geanimeerd + + + + If this option is enabled, the floating control will appear with an animation. + Indien deze optie is ingeschakeld zal de drijvende controle met een animatie verschijnen. + + + + Width + Breedte + + + + Specifies the width of the control (as a percentage). + Stelt de breedte van de controle in (als percentage). + + + + Margin + Marge + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + Drij&vende controle + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + De drijvende controle verschijnt in het volledig scherm wanneer de muis wordt verplaatst naar de onderkant van het scherm. + + + + &Animated + Ge&animeerd + + + + &Width: + Breed&te: + + + + 0 + 0 + + + + &Margin: + &Marge: + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Prestaties + + + + &Performance + &Prestaties + + + + Priority + Prioriteit + + + + Select the priority for the MPlayer process. + Kies de prioriteit van het MPlayer proces. + + + + realtime + realtime + + + + high + hoog + + + + abovenormal + hoger dan normaal + + + + normal + normaal + + + + belownormal + lager dan normaal + + + + idle + idle + + + + Cache + Cache + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Een cache instellen kan de prestaties van trage media verbeteren + + + + Allow frame drop + Framedrops toestaan + + + + Synchronization + Synchronisatie + + + + Audio/video auto synchronization + Automatische audio/video synchronisatie + + + + Fast audio track switching + Snel wisselen van audiospoor + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Prioriteit van het mplayer proces instellen volgens de vooraf gedefinieerde prioriteiten die onder Windows beschikbaar zijn.<br><b>WAARSCHUWING:</b> Gebruik van realtime prioriteit kan het systeem laten vastlopen. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Weergeven van sommige frames overslaan om A/V sync te behouden op trage systemen. + + + + Allow hard frame drop + Harde framedrops toestaan + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Intenser framedroppen (onderbreekt decodering). Leidt tot beeldvervorming! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Geleidelijk A/V sync bijstellen, gebaseerd op gemeten audio-vertaging. + + + + Priorit&y: + Pr&ioriteit: + + + + &Allow frame drop + &Framedrops toestaan + + + + Allow &hard frame drop (can lead to image distortion) + &Harde framedrops toestaan (kan leiden tot beeldvervorming) + + + + Audio/&video auto synchronization + Automatische audio/&video synchronisatie + + + + Fact&or: + Fact&or: + + + + &Fast audio track switching + &Snel wisselen van audiospoor + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Indien aangevinkt, zal het proberen de snelste methode te gebruiken om naar hoofdstukken te zoeken, maar het is mogelijk dat dit met sommige schijven niet werkt. + + + + Skip loop filter + Loopfilter overslaan + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Mogelijke waarden:<br> <b>Ja</b>: het zal proberen de snelste methode voor het wisselen van het audiospoor te gebruiken (het werkt mogelijk niet met bepaalde indelingen).<br> <b>Nee</b>: het MPlayer proces zal worden herstart zodra u van audiospoor wisselt.<br> <b>Automatisch</b>: SMPlayer beslist zelf wat het doet, afhankelijk van de MPlayer versie. + + + + Cache for files + Bestandscache + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Deze optie bepaalt hoeveel geheugen (in kBytes) gebruikt moet worden bij het bufferen van een bestand. + + + + Cache for streams + Streamcache + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Deze optie bepaalt hoeveel geheugen (in kBytes) gebruikt moet worden bij het bufferen van een URL. + + + + Cache for DVDs + DVD-cache + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Deze optie bepaalt hoeveel geheugen (in kBytes) gebruikt moet worden bij het bufferen van een DVD.<br><b>Waarschuwing:</b> Het is mogelijk dat zoeken niet correct werkt (inclusief wisselen van hoofdstuk) indien er een buffer voor DVD's wordt gebruikt.. + + + + &Cache + &Cache + + + + Cache for &DVDs: + &DVD-cache: + + + + Cache for &local files: + &Locale bestandscache: + + + + Cache for &streams: + &Streamcache: + + + + Enabled + Geactiveerd + + + + Skip (always) + Overslaan (altijd) + + + + Skip only on HD videos + Alleen bij HD video's overslaan + + + + Loop &filter + Loop&filter + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Met deze optie kunt u tijdens het decoderen van H.264 media het loopfilter overslaan (ook deblocking genoemd). Omdat het gefilterde frame eigenlijk gebruikt zou worden als vergelijkingsmateriaal voor het decoderen van afhankelijke frames, heeft dit een slechter effect op de kwaliteit dan het niet toepassen van deblocking op bijv. MPEG-2 video. Maar voor HDTV met een hoge bitrate biedt dit in elk geval wel een grote snelheidswinst zonder zichtbaar kwaliteitsverlies. + + + + Possible values: + Mogelijke waarden: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Geactiveerd</b>: het loopfilter wordt niet overgeslagen + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Overslaan (altijd)</b>: het loopfilter wordt overgeslagen, ongeacht de resolutie van de video + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Alleen bij HD video's overslaan</b>: het loopfilter wordt alleen overgeslagen bij video's waarvan de hoogte %1 of groter is. + + + + Fast seek to chapters in dvds + Snel zoeken naar hoofdstukken in DVD's + + + + Fast &seek to chapters in dvds + Snel &zoeken naar hoofdstukken in DVD's + + + + Cache for audio CDs + Audio CD-cache + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Deze optie bepaalt hoeveel geheugen (in kBytes) gebruikt moet worden bij het bufferen van een audio CD. + + + + Cache for &audio CDs: + &Audio CD-cache: + + + + Cache for VCDs + VCD-cache + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Deze optie bepaalt hoeveel geheugen (in kBytes) gebruikt moet worden bij het bufferen van een VCD. + + + + Cache for &VCDs: + &VCD-cache: + + + + Threads for decoding + Threads voor decoderen + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Stelt het aantal threads in gebruikt voor het decoderen. Alleen voor MPEG-1/2 en H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Threads voor decoderen (alleen MPEG-1/2 en H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Afspeellijst + + + + Automatically add files to playlist + Automatisch bestanden aan de afspeellijst toevoegen + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Als deze optie is aangevinkt, zal er elke keer als een bestand geopend wordt, SMPlayer eerst de afspeellijst wissen en dan bestanden eraan toevoegen. In geval van DVD's, Cd's of VCD's, worden alle titels op de schijf toegevoegd aan de afspeellijst. + + + + Add consecutive files + Bij elkaar horende bestanden toevoegen + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Als deze optie is aangevinkt zal SMPlayer zoeken naar bij elkaar horende bestanden (bijv. video_1.avi, video_2.avi...) en indien gevonden, toevoegen aan de afspeellijst. + + + + &Playlist + &Afspeellijst + + + + &Automatically add files to playlist + &Automatisch bestanden aan de afspeellijst toevoegen + + + + Add &consecutive files + Bij &elkaar horende bestanden toevoegen + + + + PrefSubtitles + + + Subtitles + Ondertiteling + + + + Choose a ttf file + Kies een TTF-bestand + + + + Truetype Fonts + Truetype Lettertypen + + + + &Subtitles + O&ndertiteling + + + + Autoload + Automatisch laden + + + + Select first available subtitle + Kies eerst beschikbare ondertiteling + + + + Same name as movie + Dezelfde naam als film + + + + All subs containing movie name + Alle ondertitelingen die de filmnaam bevatten + + + + All subs in directory + Alle ondertitelingen in map + + + + Position + Plaatsing + + + + 0 + 0 + + + + Top + Bovenaan + + + + Bottom + Onderaan + + + + Include subtitles on screenshots + Ondertiteling weergeven op schermafdrukken + + + + &Font + &Lettertype + + + + Font + Lettertype + + + + Select the font which will be used for subtitles (and OSD): + Kies het lettertype dat gebruikt moet worden voor ondertiteling (en OSD): + + + + Size + Grootte + + + + No autoscale + Niet automatisch schalen + + + + Proportional to movie height + Evenredig met hoogte van film + + + + Proportional to movie width + Evenredig met breedte van film + + + + Proportional to movie diagonal + Evenredig met diagonaal van film + + + + The new SSA/ASS library will provide nice styled subtitles for external SSA/ASS subtitles files and Matroska tracks. But it will be used too for rendering other formats like SUB and SRT files. + De nieuwe SSA/ASS-bibliotheek biedt mooi vormgegeven ondertitelingen voor externe SSA/ASS ondertiteling-bestanden en Matroska-sporen. Maar het kan ook gebruikt worden voor het weergeven van andere indelingen zoals SUB en SRT-bestanden. + + + + Use SSA/ASS library for subtitle rendering + Gebruik SSA/ASS-bibliotheek voor ondertiteling-weergave + + + + Here you can override styles for SSA/ASS subtitles. It can be also used for fine-tuning the rendering of SRT and SUB subtitles by the SSA/ASS library. Example: <b>Bold=1,Outline=2,Shadow=4</b> + Hier kunt u de stijlen voor SSA/ASS ondertiteling aanpassen. Het kan ook gebruikt worden voor de fijnafstelling van de weergave van SRT of SUB-ondertiteling door de SSA/ASS-bibliotheek. Voorbeeld: <b>Bold=1,Outline=2,Shadow=4</b> + + + + Subtitle position + Ondertitel-positie + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Deze optie bepaalt de positie van de ondertiteling op het afspeelvenster. <i>100</i> betekent onderaan en <i>0</i> betekent bovenaan. + + + + SSA/ASS styles + SSA/ASS stijlen + + + + Au&toload subtitles files (*.srt, *.sub...): + Au&tomatisch ondertitelingsbestanden laden (*.srt, *.sub...): + + + + S&elect first available subtitle + &Kies eerste beschikbare ondertiteling + + + + &Default subtitle encoding: + &Standaard ondertiteling-codering: + + + + Default &position of the subtitles on screen + Standaard&positie voor ondertiteling op het scherm + + + + &Include subtitles on screenshots + Ondert&iteling weergeven op schermafdrukken + + + + &TTF font: + &TTF-lettertype: + + + + S&ystem font: + S&ysteemlettertype: + + + + A&utoscale: + A&utomatisch schalen: + + + + &Use SSA/ASS library for subtitle rendering + &Gebruik SSA/ASS-bibliotheek voor ondertiteling-weergave + + + + &Text color: + &Tekstkleur: + + + + &Border color: + &Randkleur: + + + + St&yles: + St&ijlen: + + + + Default scale for normal subtitles + Standaardschaal voor normale ondertiteling + + + + This option specifies the default font scale for normal (white) subtitles which will be used for new videos. + Deze optie bepaalt de standaard lettertypegrootte voor normale (witte) ondertiteling, deze zal gebruikt worden voor nieuwe video's. + + + + Default scale for SSA/ASS subtitles + Standaardschaal voor SSA/ASS ondertiteling + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new videos. + Deze optie bepaalt de standaard lettertypegrootte voor SSA/ASS) ondertiteling, deze zal gebruikt worden voor nieuwe video's. + + + + Default s&cale for normal subtitles: + Standaards&chaal voor normale ondertiteling: + + + + Default sc&ale for SSA/ASS subtitles: + Standaardsch&aal voor SSA/ASS ondertiteling: + + + + SSA/ASS &library + SSA/ASS-bib&liotheek + + + + Default subtitle encoding + Standaard ondertitel-codering + + + + Select the encoding which will be used for subtitle files. + Kies de codering die voor ondertiteling-bestanden zal worden gebruikt. + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Als deze optie is aangevinkt, zal de ondertiteling in de schermafdrukken worden weergegeven. Let op: het kan soms problemen opleveren. + + + + TTF font + TTF-lettertype + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in <i>%1</i>. + Hier kunt u een TTF-lettertype kiezen om voor de ondertiteling te gebruiken. U vindt doorgaans veel TTF-lettertypen in <i>%1</i>. + + + + System font + Systeemlettertype + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Hier kunt u een systeemlettertype opgeven dat voor de ondertiteling en de OSD gebruikt zal worden. <b>Let op:</b> vereist een MPlayer met fontconfig-ondersteuning. + + + + Autoscale + Automatisch schalen + + + + SSA/ASS library + SSA/ASS-bibliotheek + + + + Check this option to activate the SSA/ASS library. It provides nicer subtitles, so it's a good idea to do it. + Vink deze optie aan om de SSA/ASS-bibliotheek te activeren. Het biedt mooiere ondertiteling, dus is het een goed idee om te doen. + + + + Text color + Tekstkleur + + + + Select the color for the text of the subtitles. + Kies de tekstkleur van de ondertiteling. + + + + Border color + Randkleur + + + + Select the color for the border of the subtitles. + Kies de randkleur van de ondertiteling. + + + + Select the subtitle autoload method. + Kies de methode voor automatisch laden van de ondertiteling. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Als er één of meer ondertiteling-sporen beschikbaar zijn, zal één daarvan automatisch worden geselecteerd, doorgaans de eerste, maar als één daarvan overeenkomt met de voorkeurstaal van de gebruiker dan zal die daarvoor in de plaats worden gebruikt. + + + + Select the subtitle autoscaling method. + Kies de methode voor automatisch schalen van de ondertiteling. + + + + Select the encoding which will be used for subtitle files by default. + Selecteer de codering die standaard voor ondertitelbestanden zal worden gebruikt. + + + + Try to autodetect for this language + Probeer te autodetecteren voor deze taal + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Als deze optie aan staat zal de codering voor ondertitels geprobeerd te worden geautodetecteerd voor de gegeven taal. Het zal terugvallen naar standaard codering als dit niet lukt. Deze optie vereist een MPlayer die is gecompileerd met ondersteuning voor ENCA. + + + + Subtitle language + Taal van ondertitel + + + + Select the language for which you want the encoding to be guessed automatically. + Selecteer de taal waarvan u wilt dat de codering automatisch voor wordt gegokt. + + + + Encoding + Codering + + + + Try to a&utodetect for this language: + A&utomatisch proberen te detecteren voor deze taal: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Hier kan u een ttf-lettertype selecteren voor de ondertitels. Normaal zal u veel ttf-lettertypes vinden in %1 + + + + Outline + Uitlijning + + + + Select the font for the subtitles. + Selecteer het lettertype voor de ondertitels. + + + + The size in pixels. + De grootte in pixels. + + + + Bold + Vet + + + + If checked, the text will be displayed in <b>bold</b>. + Indien aangevinkt zal de tekst <b>vet</b> worden weergegeven. + + + + Italic + Cursief + + + + If checked, the text will be displayed in <i>italic</i>. + Indien aangevinkt zal de tekst <i>cursief</i> worden weergegeven. + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + Ve&t + + + + &Italic + C&ursief + + + + Colors + Kleuren + + + + &Text: + &Tekst: + + + + &Border: + Ran&d: + + + + Margins + Marges + + + + L&eft: + L&inks: + + + + &Right: + &Rechts: + + + + Verti&cal: + Verti&caal: + + + + Alignment + + + + + &Horizontal: + &Horizontaal: + + + + &Vertical: + &Vericaal: + + + + Border st&yle: + Randsti&jl: + + + + &Outline: + &Uitlijning: + + + + Shado&w: + Schadu&w: + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + Hier kunt u een TTF-lettertype kiezen om voor de ondertiteling te gebruiken. U vindt doorgaans veel TTF-lettertypen in <i>%1</i>. + + + + Left + horizontal alignment + Links + + + + Centered + horizontal alignment + Gecentreerd + + + + Right + horizontal alignment + Rechts + + + + Bottom + vertical alignment + Onderaan + + + + Middle + vertical alignment + Midden + + + + Top + vertical alignment + Bovenaan + + + + Outline + border style + Uitlijning + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + Ondersteuning voor Freet&ype + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Help + + + + OK + OK + + + + Cancel + Annuleren + + + + Apply + Toepassen + + + + Help + Help + + + + SMPlayer - Preferences + SMPlayer - Voorkeuren + + + + QObject + + + 1 second + 1 seconde + + + + %1 seconds + %1 seconden + + + + %1 minutes + %1 minuten + + + + %1 minutes and %2 seconds + %1 minuten en %2 seconden + + + + 1 minute + 1 minuut + + + + 1 minute and 1 second + 1 minuut en 1 seconde + + + + 1 minute and %1 seconds + 1 minuut en %1 seconden + + + + %1 minutes and 1 second + %1 minuten en 1 seconde + + + + will show this message and then will exit. + zal dit bericht tonen en daarna sluiten. + + + + the main window will be closed when the file/playlist finishes. + het hoofdvenster zal na afloop van het bestand of de afspeellijst worden afgesloten. + + + + This is SMPlayer v. %1 running on %2 + Dit is SMPlayer v. %1 draaiend op %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + probeert een verbinding met een andere draaiende instantie te maken en er de opgegeven actie heen te sturen. Voorbeeld: -send-action pause; De rest van de opties (indien die er zijn) zullen worden genegeerd en het programma zal worden afgesloten. De functie geeft 0 terug indien gelukt of -1 indien mislukt. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list is een lijst van acties, gescheiden door spaties. De acties zullen direct na het laden van het bestand (indien die er is) uitgevoerd worden in de volgorde waarin ze werden ingevoerd. Voor aan/uitschakelbare acties kunt u de parameter true of false meegegeven worden. Voorbeeld: -actions "fullscreen compact true". Aanhalingstekens zijn nodig indien meer dan één actie wordt meegegeven. + + + + media + media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + Als er een andere instantie draait, zal de media worden toegevoegd aan de afspeellijst van die instantie. Als er geen andere instantie draait, zal deze optie worden genegeerd en worden de bestanden geopend in een nieuwe instantie. + + + + specifies the directory for the configuration file (smplayer.ini). + specificeert de map met het configuratiebestand (smplayer.ini). + + + + the main window won't be closed when the file/playlist finishes. + het hoofdvenster zal na afloop van het bestand of de afspeellijst niet worden afgesloten. + + + + the video will be played in fullscreen mode. + de video zal in beeldvullende modus worden afgespeeld. + + + + the video will be played in window mode. + de video zal in venstermodus worden afgespeeld. + + + + Enqueue in SMPlayer + Aan SMPlayer-wachtrij toevoegen + + + + opens the mini gui instead of the default one. + opent de mini-GUI in plaats van de standaard GUI. + + + + Restores the old associations and cleans up the registry. + Herstelt de oude associaties en ruimt de registry op. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' is elk soort bestand dat SMPlayer kan openen. Het kan een lokaal bestand zijn, een DVD (bijv. dvd://1), een internet stream (bijv. mms://...) of een lokale afspeellijst in M3U- of PLS-indeling. Als de -playlist optie wordt gebruikt, dan betekent dat dat SMPlayer de -playlist optie aan MPlayer doorgeeft, dus de afspeellijst zal door MPlayer worden geladen, niet door SMPlayer. + + + + Usage: + Gebruik: + + + + directory + map + + + + action_name + action_name + + + + action_list + action_list + + + + opens the default gui. + opent de standaard gui. + + + + subtitle_file + ondertitel_bestand + + + + specifies the subtitle file to be loaded for the first video. + specifieert het te laden ondertitelbestand voor de eerste video. + + + + %1 second(s) + + %1 seconde + %1 seconden + + + + + %1 minute(s) + + %1 minuut + %1 minuten + + + + + %1 and %2 + %1 en %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + stelt de map in waar smplayer zijn configuratiebestanden opslaat (smplayer.ini, smplayer_files.ini...) + + + + disabled + aspect_ratio + uitgeschakeld + + + + auto + aspect_ratio + automatisch + + + + unknown + aspect_ratio + onbekend + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + ZIP/UNZIP API-fout %1 + + + + SeekWidget + + + icon + pictogram + + + + label + label + + + + ShortcutGetter + + + Modify shortcut + Sneltoets aanpassen + + + + Clear + Leegmaken + + + + Press the key combination you want to assign + Druk de toetsencombinatie in die u wilt toewijzen + + + + Capture + Opvangen + + + + Capture keystrokes + Toetsencombinaties opvangen + + + + SubChooserDialog + + + Subtitle selection + Ondertitelselectie + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Dit archief bevat meer dan één ondertitelbestand. Kies a.u.b. diegenen die u wilt uitpakken. + + + + Select All + Alles selecteren + + + + Select None + Niets selecteren + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Zoeken + + + + &Jump to: + Sp&ringen naar: + + + + TristateCombo + + + Auto + Automatisch + + + + Yes + Ja + + + + No + Nee + + + + VideoEqualizer + + + Contrast + Contrast + + + + Brightness + Helderheid + + + + Hue + Tint + + + + Saturation + Verzadiging + + + + Gamma + Gamma + + + + &Reset + &Herstellen + + + + &Set as default values + Als &standaardwaarden instellen + + + + Use the current values as default values for new videos. + Gebruik de huidige waarden als standaardwaarden voor nieuwe video's. + + + + Set all controls to zero. + Stel alle besturingselementen op nul in. + + + + Video Equalizer + Video-equalizer + + + + Information + Informatie + + + + The current values have been stored to be used as default. + De huidige waarden werden opgeslagen om als standaard gebruikt te worden. + + + + VideoPreview + + + Video preview + + + + + Cancel + Annuleren + + + + Generated by SMPlayer + + + + + The length of the video is 0 + + + + + The temporary directory (%1) can't be created + + + + + Creating thumbnails... + + + + + The file %1 doesn't exist + + + + + Error + Foutmelding + + + + The following error has occurred while creating the thumbnails: + + + + + The mplayer process didn't run + + + + + The file %1 can't be loaded + + + + + Size: %1 MB + + + + + Resolution: %1x%2 + + + + + Length: %1 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + Aspectverhouding: %1 + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + Save file + + + + + Error saving file + Fout bij opslaan van het bestand + + + + The file couldn't be saved + Het bestand kon niet worden opgeslagen + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Standaard + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + Add playing &time to thumbnails + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Volume + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_pl.ts b/plugins/smplayer_plugin/translations/smplayer_pl.ts new file mode 100644 index 000000000..6533161e7 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_pl.ts @@ -0,0 +1,7343 @@ + + + + About + + + Version: %1 + Wersja: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Ten program jest Wolnym Oprogramowaniem; możesz go redystrybuować i/lub modyfikować na warunkach GNU General Public License wydanej przez Free Software Foundation; albo wersja 2 licencji, lub (twój wybór) każdą późniejszą wersję. + + + + The following people have contributed with translations: + Udział w tłumaczeniu mają: + + + + German + German + + + + Slovak + Slovak + + + + Italian + Italian + + + + French + French + + + + %1, %2 and %3 + %1, %2 i %3 + + + + Simplified-Chinese + Simplified-Chinese + + + + Russian + Russian + + + + %1 and %2 + %1 i %2 + + + + Hungarian + Hungarian + + + + Polish + Polish + + + + Japanese + Japanese + + + + Dutch + Dutch + + + + Ukrainian + Ukrainian + + + + Portuguese - Brazil + Portuguese - Brazil + + + + Georgian + Georgian + + + + Czech + Czech + + + + Bulgarian + Bulgarian + + + + Turkish + Turkish + + + + Swedish + Swedish + + + + Serbian + Serbian + + + + Traditional Chinese + Traditional Chinese + + + + Romanian + Romanian + + + + Portuguese - Portugal + Portuguese - Portugal + + + + Greek + Greek + + + + Finnish + Finnish + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + O SMPlayer + + + + &Info + &Informacja + + + + icon + ikona + + + + &Contributions + &Wkład + + + + &Translators + &Tłumacze + + + + &License + &Licencja + + + + Visit our web for updates: + Aktualizacja na naszej stronie: + + + + Get help in our forum: + Pomoc na naszym forum: + + + + You can support SMPlayer by making a donation. + Możesz wspomóc SMPlayer przez dotację. + + + + More info + Więcej informacji + + + + Korean + Korean + + + + Macedonian + Macedonian + + + + Basque + Basque + + + + Using MPlayer %1 + Używa MPlayera %1 + + + + Catalan + Catalan + + + + Portable Edition + Wersja przenośna (Portable) + + + + Using Qt %1 (compiled with Qt %2) + Używa Qt %1 (kompilowany z Qt %2) + + + + Slovenian + Slovenian + + + + Arabic + Arabic + + + + Kurdish + Kurdish + + + + Galician + Galician + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Nazwa + + + + Description + Opis + + + + Shortcut + Klawisz skrótu + + + + &Save + &Zapisz + + + + &Load + &Wczytaj + + + + Key files + Pliki Key + + + + Choose a filename + Wybierz nazwę pliku + + + + Confirm overwrite? + Nadpisać? + + + + The file %1 already exists. +Do you want to overwrite? + Plik %1 istnieje +Nadpisać go? + + + + Choose a file + Wybierz plik + + + + Error + Błąd + + + + The file couldn't be saved + Plik nie może zostać zapisany + + + + The file couldn't be loaded + Plik nie może zostać wczytany + + + + &Change shortcut... + &Zmień klawisz skrótu... + + + + AudioEqualizer + + + Audio Equalizer + Korektor audio + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Zatwierdź + + + + &Reset + &Resetuj + + + + &Set as default values + &Ustaw wartości jako domyślne + + + + Use the current values as default values for new videos. + Użyj aktualnych wartości jako domyślnych dla nowych plików wideo. + + + + Set all controls to zero. + Ustaw wszystkie suwaki na zero. + + + + Information + Informacja + + + + The current values have been stored to be used as default. + Aktualne wartości zostaną przechowane aby mogły być użyte jako domyślne. + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer log + + + + SMPlayer - smplayer log + SMPlayer - smplayer log + + + + &Open + &Otwórz + + + + &Play + &Odtwarzanie + + + + &Video + &Wideo + + + + &Audio + &Audio + + + + &Subtitles + &Napisy + + + + &Browse + &Przeglądaj + + + + Op&tions + Op&cje + + + + &Help + &Pomoc + + + + &File... + &Plik ... + + + + D&irectory... + K&atalog... + + + + &Playlist... + &Lista odtwarzania... + + + + &DVD from drive + &DVD z napędu + + + + D&VD from folder... + D&VD z katalogu... + + + + &URL... + &URL... + + + + &Clear + &Wyczyść + + + + &Recent files + &Ostatnio otwierane pliki + + + + P&lay + O&dtwarzaj + + + + &Pause + &Pauza + + + + &Stop + &Stop + + + + &Frame step + &Krok + + + + &Normal speed + &Normala prędkość + + + + &Halve speed + &Połowa prędkości + + + + &Double speed + &Podwójna prędkość + + + + Speed &-10% + Prędkość &-10% + + + + Speed &+10% + Prędkość &+10% + + + + Sp&eed + &Prędkość + + + + &Repeat + &Powtarzaj + + + + &Fullscreen + &Pełny ekran + + + + &Compact mode + &Ukryj menu i przyciski + + + + Si&ze + Ro&zmiar + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &do 16:9 + + + + &Aspect ratio + &Współczynnik proporcji + + + + &None + &Brak + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Liniowy &Mieszany + + + + &Deinterlace + &Usuwanie przeplotu + + + + &Postprocessing + &Przetwarzanie końcowe + + + + &Autodetect phase + &Autodetekcja fazy + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + &Dodaj szum + + + + F&ilters + F&iltry + + + + &Equalizer + &Korektor + + + + &Screenshot + &Zrzut ekranu + + + + S&tay on top + Z&awsze na wierzchu + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtry + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Kanały + + + + &Left channel + &Lewy kanał + + + + &Right channel + &Prawy kanał + + + + &Stereo mode + &Tryb stereo + + + + &Mute + &Wycisz + + + + Volume &- + Ciszej &- + + + + Volume &+ + Głośniej &+ + + + + &Delay - + &Opóźnij audio - + + + + D&elay + + P&rzyśpiesz audio + + + + + &Select + &Wybierz + + + + &Load... + &Wczytaj... + + + + Delay &- + Opóźnij napisy &- + + + + Delay &+ + Przyśpiesz napisy &+ + + + + &Up + &Przesuń napisy w górę + + + + &Down + &Przesuń napisy w dół + + + + &Title + &Tytuł + + + + &Chapter + &Rozdział + + + + &Angle + &Kąt widzenia + + + + &Playlist + &Lista odtwarzania + + + + &Show frame counter + &Pokaż licznik klatek + + + + &Disabled + &Wyłączone + + + + &Seek bar + &Pasek wyszukiwania + + + + &Time + &Czas + + + + Time + T&otal time + Czas +C&ałkowity czas + + + + &OSD + &OSD + + + + &View logs + &Pokaż logi + + + + P&references + &Ustawienia + + + + About &Qt + O &Qt + + + + About &SMPlayer + O &SMPlayer + + + + <empty> + <brak> + + + + Video + Wideo + + + + Audio + Audio + + + + Playlists + Listy odtwarzania + + + + All files + Wszystkie pliki + + + + Choose a file + Wybierz plik + + + + SMPlayer - Information + SMPlayer - Informacje + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD nie jest jeszcze skonfigurowany. +Zobaczysz zaraz dialog konfiguracji i możesz dokonać ustaweń. + + + + Choose a directory + Wybierz katalog + + + + Subtitles + Napisy + + + + About Qt + O... Qt + + + + Playing %1 + Odtwarzanie %1 + + + + Pause + Pauza + + + + Stop + Stop + + + + Play / Pause + Odtwarzaj / Pauza + + + + Pause / Frame step + Pauza / Krok + + + + U&nload + W&yładuj + + + + V&CD + V&CD + + + + C&lose + Z&amknij + + + + View &info and properties... + Pokaż &informację i właściwości... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Reset + + + + Move &left + Przesuń w &lewo + + + + Move &right + Przesuń w &prawo + + + + Move &up + Przesuń w &górę + + + + Move &down + Przesuń w &dół + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Poprzedni wiersz napisów + + + + N&ext line in subtitles + N&astępny wiersz napisów + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Zmniejsz głośność (2) + + + + Inc volume (2) + Zwiększ głośność (2) + + + + Exit fullscreen + Wyjdź z pełnego ekranu + + + + OSD - Next level + OSD-następny poziom + + + + Dec contrast + Zmniejsz kontrast + + + + Inc contrast + Zwiększ kontrast + + + + Dec brightness + Zmniejsz jasność + + + + Inc brightness + Zwiększ jasność + + + + Dec hue + Zmniejsz odcień + + + + Inc hue + Zwiększ odcień + + + + Dec saturation + Zmniejsz saturację + + + + Dec gamma + Zmniejsz gamma + + + + Next audio + Następne audio + + + + Next subtitle + Następne napisy + + + + Next chapter + Następny rozdział + + + + Previous chapter + Poprzedni rozdział + + + + Inc saturation + Zwiększ saturację + + + + Inc gamma + Zwiększ gamma + + + + &Load external file... + &Wczytaj zewnętrzny plik... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normalny) + + + + Y&adif (double framerate) + Y&adif (podwójna szybkość klatek) + + + + &Next + &Następny + + + + Pre&vious + Pop&rzedni + + + + Volume &normalization + Normalizacja &głośności + + + + &Audio CD + &Audio CD + + + + Denoise nor&mal + Normalne &odszumianie + + + + Denoise &soft + Programowe &odszumianie + + + + Denoise o&ff + Wyłączone &odszumianie + + + + Use SSA/&ASS library + Użyj biblioteki SSA/&ASS + + + + Flip i&mage + Odwróć &obraz + + + + &Toggle double size + &Przełącz na podwójny rozmiar + + + + S&ize - + R&ozmiar - + + + + Si&ze + + R&ozmiar + + + + + Add &black borders + Dodaj &czarne obramowanie + + + + Soft&ware scaling + &Programowe skalowanie + + + + &FAQ + &FAQ + + + + Visualize &motion vectors + &Pokaż wektory ruchu + + + + &Command line options + &Opcje wiersza poleceń + + + + SMPlayer command line options + Opcje wiersza poleceń SMPlayera + + + + Enable &closed caption + Włącz funkcję &napisów na ekranie + + + + &Forced subtitles only + &Tylko wymuszone napisy + + + + Reset video equalizer + Resetuj korektor wideo + + + + MPlayer has finished unexpectedly. + MPlayer nieoczekiwanie zakończył pracę. + + + + Exit code: %1 + Kod wyjścia: %1 + + + + MPlayer failed to start. + Błąd uruchomienia MPlayera. + + + + Please check the MPlayer path in preferences. + Proszę sprawdź w ustawieniach ścieżkę do programu MPlayer. + + + + MPlayer has crashed. + MPlayer uległ uszkodzeniu. + + + + See the log for more info. + Więcej informacji-zobacz log. + + + + &Rotate + &Obrót + + + + &Off + &Wyłączony + + + + &Rotate by 90 degrees clockwise and flip + &Obróć o 90 stopni w kierunku obrotu wskazówek zegara i odwróć obraz + + + + Rotate by 90 degrees &clockwise + &Obróć o 90 stopni w kierunku obrotu wskazówek zegara + + + + Rotate by 90 degrees counterclock&wise + Obróć o 90 stopni przeciwnie do kierunku obrotu wskazówek &zegara + + + + Rotate by 90 degrees counterclockwise and &flip + Obróć o 90 stopni przeciwnie do kierunku obrotu wskazówek &zegara i odwróć obraz + + + + &Jump to... + &Skocz do... + + + + Show context menu + Pokaż menu kontekstowe + + + + Multimedia + Multimedia + + + + E&qualizer + &Korektor + + + + Reset audio equalizer + Resetuj korektor audio + + + + Find subtitles on &OpenSubtitles.org... + Znajdź napisy w &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Wyślij &napisy do OpenSubtitles.org... + + + + &Tips + &Wskazówki + + + + &Auto + &Auto + + + + Speed -&4% + Prędkość -&4% + + + + &Speed +4% + &Prędkość +4% + + + + Speed -&1% + Prędkość -&1% + + + + S&peed +1% + &Prędkość +1% + + + + Scree&n + Ekra&n + + + + &Default + &Domyślne + + + + Mirr&or image + Odbi&cie lustrzane + + + + Next video + Następne wideo + + + + &Track + video + &Ścieżka + + + + &Track + audio + &Ścieżka + + + + Warning - Using old MPlayer + Uwaga - Używasz starej wersji MPlayera + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + Wersja MPlayera (%1) zainstalowana w systemie jest przestarzała. SMPlayer nie będzie dobrze pracował: kilka opcji nie zadziała, na przykład wybór napisów... + + + + Please, update your MPlayer. + Proszę zaktualizuj MPlayera. + + + + (This warning won't be displayed anymore) + (Ostrzeżenie to nie wyświetli się ponownie) + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer nadal działa + + + + S&how icon in system tray + P&okaż ikonę w tacce systemowej + + + + &Hide + &Ukryj + + + + &Restore + &Przywróć + + + + &Quit + &Wyjdź + + + + Playlist + Lista odtwarzania + + + + Core + + + Brightness: %1 + Jasność: %1 + + + + Contrast: %1 + Kontrast: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Odcień: %1 + + + + Saturation: %1 + Nasycenie: %1 + + + + Volume: %1 + Głośność: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + Skala czcionki: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Witaj w SMPlayer + + + + Audio + Audio + + + + Subtitle + Napisy + + + + &Main toolbar + &Główny pasek narzędzi + + + + &Language toolbar + &Pasek wyboru języka dla napisów i ścieżki audio + + + + &Toolbars + &Paski narzędzi + + + + EqSlider + + + icon + ikona + + + + ErrorDialog + + + Hide log + Ukryj log + + + + Show log + Pokaż log + + + + MPlayer Error + Błąd programu MPlayer + + + + icon + ikona + + + + Error + Błąd + + + + FileDownloader + + + Downloading... + Pobieranie... + + + + Downloading %1 + Pobieranie %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Ustawienia pliku + + + + &Information + &Informacja + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Wybierz demuxer, dla tego pliku: + + + + &Reset + &Resetuj + + + + &Video codec + &Kodek Wideo + + + + &Select the video codec: + &Wybierz Kodek Wideo: + + + + A&udio codec + &Kodek Audio + + + + &Select the audio codec: + &Wybierz Kodek Audio: + + + + &MPlayer options + &Opcje MPlayera + + + + Additional Options for MPlayer + Dodatkowe opcje MPlayera + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Tu możesz wpisać dodatkowe opcje MPlayera. +Wpisz oddzielając spacją. +Przykład: -flip -nosound + + + + &Options: + &Opcje: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Dodatkowe opcje filtrów wideo. +Wpisz oddzielając przecinkiem ",". Nie używaj spacji! +Przykład: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + F&iltry Wideo: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Opcje dla filtrów audio. Takie same zasady jak dla filtrów wideo. +Przykład: resample=44100:0:0,volnorm + + + + Audio &filters: + Filtry &Audio: + + + + OK + OK + + + + Cancel + Anuluj + + + + Apply + Zatwierdź + + + + FindSubtitlesWindow + + + Language + Język + + + + Name + Nazwa + + + + Format + Format + + + + Files + Pliki + + + + Date + Data + + + + Uploaded by + Wysłane przez + + + + All + Wszystko + + + + Close + Zamknij + + + + &Download + &Pobieranie + + + + &Copy link to clipboard + &Kopiuj link do schowka + + + + Error + Błąd + + + + Download failed: %1. + Błąd pobierania: %1. + + + + Connecting to %1... + Łączenie do %1... + + + + Downloading... + Pobieranie... + + + + Done. + Wykonano. + + + + %1 files available + %1 dostępnych plików + + + + Failed to parse the received data. + Błąd analizy przyjętych danych. + + + + Find Subtitles + Znajdź napisy + + + + &Subtitles for + &Napisy dla + + + + &Language: + &Język: + + + + &Refresh + &Odśwież + + + + Subtitle saved as %1 + Napisy zapisano jako %1 + + + + %1 subtitle(s) extracted + + %1 napisy(ów) wypakowano + %1 napisy(ów) wypakowano + %1 napisy(ów) wypakowano + + + + + Overwrite? + Nadpisać? + + + + The file %1 already exits, overwrite? + Plik %1 już istnieje, nadpisać go? + + + + Error saving file + Błąd zapisu pliku + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Nie można było zapisać pobranego +pliku w folderze %1 +Proszę sprawdź uprawnienia tego folderu. + + + + Download failed + Błąd pobierania + + + + Temporary file %1 + Plik tymczasowy %1 + + + + InfoFile + + + General + Ogólne + + + + Size + Rozmiar + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Długość + + + + Demuxer + Demuxer + + + + Name + Nazwa + + + + Artist + Artysta + + + + Author + Autor + + + + Album + Album + + + + Genre + Gatunek + + + + Date + Data + + + + Track + Track + + + + Copyright + Copyright + + + + Comment + Komentarz + + + + Software + Oprogramowanie + + + + Clip info + Info o klipie + + + + Video + Wideo + + + + Resolution + Rozdzielczość + + + + Aspect ratio + Współczynnik proporcji + + + + Format + Format + + + + Bitrate + Bitrate + + + + %1 kbps + %1 kbps + + + + Frames per second + Ramek na sekundę + + + + Selected codec + Użyty dekoder + + + + Initial Audio Stream + Początkowy strumień audio + + + + Rate + Tempo + + + + %1 Hz + %1 Hz + + + + Channels + Kanały + + + + Audio Streams + Strumienie audio + + + + Language + Język + + + + empty + brak + + + + Subtitles + Napisy + + + + Type + Typ + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Nazwa strumienia + + + + Stream URL + URL strumienia + + + + File + Plik + + + + InputDVDDirectory + + + Choose a directory + Wybierz katalog + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Odtwórz DVD z katalogu + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Możesz odtwarzać DVD z dysku. +Wybierz katalog, w którym jest VIDEO_TS i AUDIO_TS. + + + + Choose a directory... + Wybierz katalog ... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Wpisz wersję MPlayera + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer nie potrafi zidentyfikować używanej wersji MPlayera. + + + + Version reported by MPlayer: + Wersja zgłoszona przez MPlayer: + + + + Please, &select the correct version: + Proszę &wybrać poprawną wersję: + + + + 1.0rc1 or older + 1.0rc1 lub starsza + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Wyższa niż 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Wprowadź URL + + + + &URL: + &URL: + + + + It's a &playlist + To jest &lista odtwarzania + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Jeśli ta opcja jest zaznaczona, URL będzie traktowany jako lista odtwarzania: będzie otwarty jako tekst i z tego odtwarzany URL. + + + + Languages + + + Afar + Afar + + + + Abkhazian + Abkhazian + + + + Afrikaans + Afrikaans + + + + Amharic + Amharic + + + + Arabic + Arabic + + + + Assamese + Assamese + + + + Aymara + Aymara + + + + Azerbaijani + Azerbaijani + + + + Bashkir + Bashkir + + + + Byelorussian + Byelorussian + + + + Bulgarian + Bulgarian + + + + Bihari + Bihari + + + + Bislama + Bislama + + + + Bengali + Bengali + + + + Tibetan + Tibetan + + + + Breton + Breton + + + + Catalan + Catalan + + + + Corsican + Corsican + + + + Czech + Czech + + + + Welsh + Welsh + + + + Danish + Danish + + + + German + German + + + + Bhutani + Bhutani + + + + Greek + Greek + + + + English + English + + + + Esperanto + + + + + Spanish + Spanish + + + + Estonian + + + + + Basque + Basque + + + + Persian + Persian + + + + Finnish + Finnish + + + + Fiji + Fiji + + + + Faroese + Faroese + + + + French + French + + + + Frisian + Frisian + + + + Irish + Irish + + + + Scots + Scots + + + + Galician + Galician + + + + Guarani + Guarani + + + + Gujarati + Gujarati + + + + Hausa + Hausa + + + + Hebrew + Hebrew + + + + Hindi + Hindi + + + + Croatian + Croatian + + + + Hungarian + Hungarian + + + + Armenian + Armenian + + + + Interlingua + Interlingua + + + + Indonesian + Indonesian + + + + Interlingue + Interlingue + + + + Inupiak + Inupiak + + + + Icelandic + Icelandic + + + + Italian + Italian + + + + Inuktitut + Inuktitut + + + + Japanese + Japanese + + + + Javanese + Javanese + + + + Georgian + Georgian + + + + Kazakh + Kazakh + + + + Greenlandic + Greenlandic + + + + Cambodian + Cambodian + + + + Kannada + Kannada + + + + Korean + Korean + + + + Kashmiri + Kashmiri + + + + Kurdish + Kurdish + + + + Kirghiz + Kirghiz + + + + Latin + Latin + + + + Lingala + Lingala + + + + Laothian + Laothian + + + + Lithuanian + Lithuanian + + + + Latvian + Latvian + + + + Malagasy + Malagasy + + + + Maori + Maori + + + + Macedonian + Macedonian + + + + Malayalam + Malayalam + + + + Mongolian + Mongolian + + + + Moldavian + Moldavian + + + + Marathi + Marathi + + + + Malay + Malay + + + + Maltese + Maltese + + + + Burmese + Burmese + + + + Nauru + Nauru + + + + Nepali + Nepali + + + + Dutch + Dutch + + + + Norwegian + Norwegian + + + + Occitan + Occitan + + + + Oriya + Oriya + + + + Punjabi + Punjabi + + + + Polish + Polish + + + + Pashto + Pashto + + + + Portuguese + Portuguese + + + + Quechua + Quechua + + + + Kirundi + Kirundi + + + + Romanian + Romanian + + + + Russian + Russian + + + + Kinyarwanda + Kinyarwanda + + + + Sanskrit + Sanskrit + + + + Sindhi + Sindhi + + + + Sangho + Sangho + + + + Sinhalese + Sinhalese + + + + Slovak + Slovak + + + + Slovenian + Slovenian + + + + Samoan + Samoan + + + + Shona + Shona + + + + Somali + Somali + + + + Albanian + Albanian + + + + Serbian + Serbian + + + + Siswati + Siswati + + + + Sesotho + Sesotho + + + + Sundanese + Sundanese + + + + Swedish + Swedish + + + + Swahili + Swahili + + + + Tamil + Tamil + + + + Telugu + Telugu + + + + Tajik + Tajik + + + + Thai + Thai + + + + Tigrinya + Tigrinya + + + + Turkmen + Turkmen + + + + Tagalog + Tagalog + + + + Setswana + Setswana + + + + Tonga + Tonga + + + + Turkish + Turkish + + + + Tsonga + Tsonga + + + + Tatar + Tatar + + + + Twi + Twi + + + + Uighur + Uighur + + + + Ukrainian + Ukrainian + + + + Urdu + Urdu + + + + Uzbek + Uzbek + + + + Vietnamese + Vietnamese + + + + Wolof + Wolof + + + + Xhosa + Xhosa + + + + Yiddish + Yiddish + + + + Yoruba + Yoruba + + + + Zhuang + Zhuang + + + + Chinese + Chinese + + + + Zulu + Zulu + + + + Portuguese - Brazil + Portuguese - Brazil + + + + Portuguese - Portugal + Portuguese - Portugal + + + + Simplified-Chinese + Simplified-Chinese + + + + Traditional Chinese + Traditional Chinese + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + Western European Languages + + + + Western European Languages with Euro + Western European Languages with Euro + + + + Slavic/Central European Languages + Slavic/Central European Languages + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galician, Maltese, Turkish + + + + Old Baltic charset + Old Baltic charset + + + + Cyrillic + Cyrylica + + + + Modern Greek + Modern Greek + + + + Baltic + Baltic + + + + Celtic + Celtic + + + + Hebrew charsets + Hebrew charsets + + + + Ukrainian, Belarusian + Ukrainian, Belarusian + + + + Simplified Chinese charset + Simplified Chinese charset + + + + Traditional Chinese charset + Traditional Chinese charset + + + + Japanese charsets + Japanese charsets + + + + Korean charset + Korean charset + + + + Thai charset + Thai charset + + + + Cyrillic Windows + Cyrillic Windows + + + + Slavic/Central European Windows + Slavic/Central European Windows + + + + Arabic Windows + Arabic Windows + + + + Rhaeto-Romance + Rhaeto-Romance + + + + Serbo-Croatian + Serbo-Croatian + + + + Volapük + Volapük + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Wybierz plik do zapisania + + + + Confirm overwrite? + Zatwierdzić nadpisanie? + + + + The file already exists. +Do you want to overwrite? + Plik już istnieje. +Czy chcesz go nadpisać? + + + + Error saving file + Błąd zapisu pliku + + + + The log couldn't be saved + Log nie mógł zostać zapisany + + + + Logs + Logi + + + + LogWindowBase + + + Log Window + Okno logu + + + + Save + Zapisz + + + + Copy to clipboard + Kopiuj do schowka + + + + Close + Zamknij + + + + &Close + &Zamknij + + + + MiniGui + + + Control bar + Pasek kontroli + + + + MpcGui + + + Control bar + Pasek kontroli + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nazwa + + + + Length + Długość + + + + Choose a file + Wybierz plik + + + + Choose a filename + Wybierz nazwę pliku + + + + Confirm overwrite? + Potwierdź nadpisanie? + + + + Select one or more files to open + Wybierz jeden lub więcej plików do otwarcia + + + + Choose a directory + Wybierz katalog + + + + The file %1 already exists. +Do you want to overwrite? + Plik %1 istnieje +Nadpisać go? + + + + Edit name + Edytuj nazwę + + + + Type the name that will be displayed in the playlist for this file: + Wpisz nową nazwę dla tego pliku, która będzie wyświetlana w liście +odtwarzania : + + + + &Play + &Odtwarzaj + + + + &Edit + &Edytuj + + + + Playlists + Listy odtwarzania + + + + All files + Wszystkie pliki + + + + &Load + &Wczytaj + + + + &Save + &Zapisz + + + + &Next + &Następny + + + + Pre&vious + Pop&rzedni + + + + Move &up + Przesuń w &górę + + + + Move &down + Przesuń w &dół + + + + &Repeat + &Powtarzaj + + + + S&huffle + T&asuj + + + + Add &current file + Dodaj &bieżący plik + + + + Add &file(s) + Dodaj &plik(i) + + + + Add &directory + Dodaj &katalog + + + + Remove &selected + Usuń &zaznaczony + + + + Remove &all + Usuń &wszystko + + + + SMPlayer - Playlist + SMPlayer-lista odtwarzania + + + + Add... + Dodaj... + + + + Remove... + Usuń... + + + + Playlist modified + Lista odtwarzania zmodyfikowana + + + + There are unsaved changes, do you want to save the playlist? + Tu są niezapisane zmiany, czy chcesz zapisać listę odtwarzania? + + + + Preferences + Preferencje + + + + PlaylistPreferences + + + Playlist - Preferences + Lista odtwarzania - Preferencje + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Zaznacz tę opcję jeśli chcesz, żeby do dodawanych katalogów zostały także dodane rekursywnie pliki w podkatalogach. W innym wypadku zostaną dodane tylko pliki w zaznaczonych katalogach . + + + + &Add files in directories recursively + &Dodaj rekursywnie pliki i katalogi + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Zaznacz tę opcję jeśli chcesz zasięgnąć informacji o plikach dodanych do listy odtwarzania, uwzględniając nazwę (jeśli dostępna) i długość plików. W przeciwnym razie informacje te nie będą dostępne dopóki plik jest odtwarzany. Uwaga: opcja ta jest bardzo wolna, zwłaszcza, gdy dodasz dużo plików. + + + + Automatically get &info about files added + Automatycznie pobierz &informację o dodanych plikach + + + + &Save copy of playlist on exit + &Zapisz przy wyjściu kopię listy odtwarzania + + + + &Play files from start + &Odtwarzaj pliki od początku + + + + PrefAdvanced + + + Advanced + Zaawansowane + + + + Auto + Auto + + + + &Advanced + &Zaawansowane + + + + icon + ikona + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Tu możesz wpisać dodatkowe opcje MPlayera. +Wpisz oddzielając spacją. +Przykład: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Dodatkowe opcje filtrów wideo. +Wpisz oddzielając przecinkiem ",". Nie używaj spacji! +Przykład: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Opcje dla filtrów audio. Takie same zasady jak dla filtrów wideo. +Przykład: resample=44100:0:0, + + + + Log MPlayer output + Komunikaty wyjściowe MPlayera + + + + Log SMPlayer output + Komunikaty wyjściowe SMPlayera + + + + This option is mainly intended for debugging the application. + Ta opcja jest przeznaczona głównie do debugowania programu. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Zaznaczenie tej opcji może zredukować migotanie, ale jednocześnie może spowodować, że obraz wideo nie będzie poprawnie wyświetlany. + + + + Filter for SMPlayer logs + Filtr logów SMPlayera + + + + &Monitor aspect: + &Rozmiar ekranu: + + + + &Run MPlayer in its own window + &Uruchom MPlayer w oddzielnym oknie + + + + &Options: + &Opcje: + + + + V&ideo filters: + F&iltry Wideo: + + + + Audio &filters: + Filtry &Audio: + + + + &Colorkey: + &Kolor tła okna głównego: + + + + Log &SMPlayer output + Komunikaty &wyjściowe SMPlayera + + + + &Filter for SMPlayer logs: + &Filtr logów SMPlayera: + + + + C&hange... + Z&mień... + + + + Logs + Logi + + + + Log MPlayer &output + Komunikaty &wyjściowe MPlayera + + + + Options for MP&layer + Opcje &MPlayera + + + + Autosave MPlayer log + Autozapis logu MPlayera + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Jeśli ta opcja jest zaznaczona, log MPlayera zostanie zapisany do sprecyzowanego pliku przy każdym uruchomieniu odtwarzania nowego pliku. Jest to przeznaczone dla zewnętrznych aplikacji, tak więc możesz pobrać informację o odtwarzanym pliku. + + + + Autosave MPlayer log filename + Autozapis nazwy pliku logu MPlayera + + + + Enter here the path and filename that will be used to save the MPlayer log. + Wpisz tutaj ścieżkę i nazwę pliku, której użyjesz do zapisania logu MPlayera. + + + + A&utosave MPlayer log to file + A&utozapis logu MPlayera do pliku + + + + Pass short filenames (8+3) to MPlayer + Pomiń krótkie nazwy plików (8+3) dla MPlayera + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Obecnie MPlayer nie potrafi otworzyć nazw plików zawierających znaki poza lokalnym kodowaniem. Zaznaczenie tej opcji spowoduje pominięcie przez SMPlayer krótkich nazw plików dla MPlayera, a więc będzie on zdolny do ich otwarcia. + + + + &Pass short filenames (8+3) to MPlayer + &Pomiń krótkie nazwy plików (8+3) dla MPlayera + + + + Monitor aspect + Współczynnik proporcji monitora + + + + Select the aspect ratio of your monitor. + Wybierz współczynnik proporcji swojego monitora. + + + + Run MPlayer in its own window + Uruchom MPlayer w oddzielnym oknie + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Zaznaczenie tej opcji spowoduje, że obraz z MPlayera nie będzie osadzony w głównym oknie SMPlayera, tylko będzie wyświetlany w swoim własnym oknie. Należy zauważyć, że zdarzenia wysyłane przez klawiaturę i myszkę będą obsługiwane bezpośrednio przez MPlayera, co oznacza, że skróty klawiaturowe i kliknięcia myszki nie będą działały zgodnie z oczekiwaniem, w przypadku, gdy aktywne będzie okno MPlayera. + + + + Colorkey + Kolor tła okna głównego + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Jeśli widzisz część wideo nad innym oknem, możesz to naprawić zmieniając kolor tła okna głównego. Spróbuj wybrać kolor bliski czarnemu. + + + + Options for MPlayer + Opcje MPlayera + + + + Options + Opcje + + + + Here you can type options for MPlayer. Write them separated by spaces. + Tutaj możesz wpisać opcje MPlayera. Wpisz oddzielając je spacją. + + + + Video filters + Filtry wideo + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Tutaj możesz dodać filtry wideo dla MPlayera. Wpisz oddzielając je przecinkiem. Nie używaj spacji! + + + + Audio filters + Filtry audio + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Tutaj możesz dodać filtry audio dla MPlayera. Wpisz oddzielając je przecinkiem. Nie używaj spacji! + + + + Repaint the background of the video window + Odśwież tło okna wideo + + + + Repaint the backgroun&d of the video window + Odśwież &tło okna wideo + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Użyj IPv4 dla połączenia sieciowego. Automatycznie przejdź na IPv4. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Użyj IPv6 dla połączenia sieciowego. Automatycznie przejdź na IPv6. + + + + Network Connection + Połączenie sieciowe + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + &Logi + + + + Rebuild index if needed + Jeżeli zajdzie potrzeba przebuduj index + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Przebuduj indeks plików jeśli go nie znaleziono, uwzględniając wyszukiwanie. Opcja przydatna przy uszkodzonych, niekompletnych pobieraniach, lub niepoprawnym tworzeniu plików. Działa tylko jeśli odpowiednie media obsługują wyszukiwanie (np. nie z stdin, pipe, itp).<br>Notka: tworzenie indeksu może trochę potrwać. + + + + Rebuild &index if needed + Jeżeli zajdzie potrzeba przebuduj &index + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Jeśli ta opcja jest zaznaczona, SMPlayer będzie pamiętał komunikaty debugowania (możesz zobaczyć te komunikaty klikając <b>Opcje->Pokaż logi->SMPlayer</b>). Ta informacja będzie bardzo przydatna dla programisty jeśli znajdziesz błąd w programie. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Jeśli opcja jest zaznaczona, SMPlayer będzie pamiętał komunikaty z mplayera (możesz zobaczyć te komunikaty klikając <b>Opcje->Pokaż logi->MPlayer</b>). W przypadku problemów ten komunikat będzie miał bardzo ważne informacje, więc zaleca się włączyć tę opcję. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Ta opcja pozwala filtrować komunikaty wyjściowe które będą zapamiętane w logu. Wpisz tutaj wyrażenie regularne. <br>Na przykład wpisanie: <i>^Core::.*</i> pokaże tylko linie zaczynające się od <i>Core::</i> + + + + Correct pts + Korekta pts + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Przełącza MPlayer w tryb eksperymentalny gdzie znaczniki czasu dla klatek wideo są przeliczane niejednakowo i filtry wideo, które dodają nowe ramki lub modyfikują znaczniki czasu w już istniejących, są obsługiwane. Więcej dokładnych znaczników czasu będzie można zobaczyć np. gdy odtwarzasz a napisy w scenie zmieniają się z biblioteką SSA/ASS. Bez korekty pts synchronizacja napisów zostanie wyłączona, przez niektóre ramki Opcja ta nie działa poprawnie z niektórymi kodekami i demuxerami. + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Typ + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Uwaga + + + + Not all files could be associated. Please check your security permissions and retry. + Nie wszystkie pliki mogą zostać skojarzone. Sprawdź swoje uprawnienia dostępu do systemu plików i spróbuj ponownie. + + + + File Types + Rodzaj plików + + + + Select all + Wybierz wszystko + + + + Check all file types in the list + Zaznacz wszystkie rodzaje plików z listy + + + + Uncheck all file types in the list + Odznacz wszystkie rodzaje plików z listy + + + + List of file types + Lista rodzaju plików + + + + File types + Rodzaj plików + + + + Media files handled by SMPlayer: + Rodzaj plików obsługiwanych przez SMPlayer: + + + + Select All + Wybierz wszystko + + + + Select None + Nie wybieraj nic + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Zaznacz rozszerzenia plików, które ma obsługiwać SMPlayer. Gdy naciśniesz Ok, zaznaczone pliki zostaną skojarzone z SMPlayerem. Jeśli odznaczysz nośnik, skojarzenie plików zostanie przywrócone. + + + + Select none + Nie wybieraj nic + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <br>Notka:</b> (Przywrócenie nie działa w Windows Vista). + + + + PrefDrives + + + Drives + Napędy + + + + icon + ikona + + + + CD device + Napęd CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Wybierz napęd CD. Będzie on użyty do odtwarzania płyt VCD oraz CD. + + + + DVD device + Napęd DVD + + + + Choose your DVD device. It will be used to play DVDs. + Wybierz napęd DVD. Będzie on użyty do odtwarzania DVD. + + + + Select your &CD device: + Wybierz napęd &CD: + + + + Select your &DVD device: + Wybierz napęd &DVD: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + Domyślnie SMPlayer nie wybiera żadnego napędu CDROM lub DVD. Dlatego przed odtwarzaniem CD lub DVD powinieneś wybrać napęd, który chcesz użyć (mogą być te same). + + + + PrefGeneral + + + General + Główne + + + + &General + &Główne + + + + Paths + Ścieżka + + + + Media settings + Ustawienia mediów + + + + Preferred audio and subtitles + Preferowana ścieżka dźwiękowa i napisy + + + + Video + Wideo + + + + Start videos in fullscreen + Start odtwarzania na pełnym ekranie + + + + Disable screensaver + Zablokuj wygaszacz ekranu + + + + Audio + Audio + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Select the mplayer executable + Wybierz plik wykonywalny mplayera + + + + Executables + Wykonywalne + + + + All files + Wszystkie pliki + + + + Select a directory + Wybierz katalog + + + + MPlayer executable + Plik wykonywalny MPlayera + + + + Screenshots folder + Folder dla zrzutów ekranu + + + + Video output driver + Strerownik wyjściowy wideo + + + + Audio output driver + Sterownik wyjściowy audio + + + + Select the audio output driver. + Wybierz sterownik wyjściowy audio. + + + + Remember settings + Zapamiętaj ustawienia + + + + Preferred audio language + Preferowany język audio + + + + Preferred subtitle language + Preferowany język napisów + + + + Software video equalizer + Programowy korektor wideo + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Zaznacz tę opcję jeśli korektor wideo nie jest obsługiwany przez twoją kartę graficzną lub wybrany sterownik wyjściowy wideo.<br><b>Notka:</b>ta opcja nie jest kompatybilna z niektórymi sterownikami wideo. + + + + Postprocessing quality + Jakość przetwarzania końcowego + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Dynamiczne zmiany przetwarzania końcowego (postprocessing) zależne są od dostępnej wolnej mocy obliczeniowej procesora (CPU). Poziom który ustawisz będzie maksymalny w użyciu. Zwykle można ustawić trochę wyższą wartość. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Gdy ta opcja jest zaznaczona wszystkie pliki wideo będą odtwarzane w trybie pełnego ekranu. + + + + Software volume control + Programowa kontrola głośności + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Zaznacz tę opcję aby użyć programowego miksera, zamiast miksera karty muzycznej. + + + + Change volume + Zmień głośność + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Zaznaczenie tej opcji spowoduje, że SMPlayer zapamięta głośność dla każdego pliku i przywróci ją przy jego ponownym odtwarzaniu . Dla nowych plików używana będzie głośność domyślna. + + + + 0 + 0 + + + + &Change volume on every file + &Zmień głośność dla każdego pliku + + + + Select the &MPlayer executable: + Wybierz plik wykonywalny &MPlayera: + + + + &Folder for storing screenshots: + &Katalog dla zrzutów ekranu: + + + + &Audio: + &Audio: + + + + &Remember settings for all files (audio track, subtitles...) + &Zapamiętaj ustawienia dla wszystkich plików (ścieżki audio, napisy...) + + + + Su&btitles: + Na&pisy: + + + + &Quality: + &Jakość: + + + + Start videos in &fullscreen + Start odtwarzania na &pełnym ekranie + + + + Disable &screensaver + Zablokuj &wygaszacz ekranu + + + + &Default volume: + &Domyślna głośność: + + + + Use s&oftware volume control + Użyj &programowej regulacji głośności + + + + Ma&x. Amplification: + Ma&ksymalne wzmocnienie: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS pass-through S/PDIF + + + + Direct rendering + Bezpośredni rendering + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Jeśli jest zaznaczony, zmienisz na bezpośredni rendering (nie obsługiwane z wszystkimi kodekami i wyjściem wideo)<br><b>UWAGA:</b> Może spowodować uszkodzenie OSD/SUB! + + + + Double buffering + Podwójne buforowanie + + + + D&irect rendering + B&ezpośredni rendering + + + + Dou&ble buffering + P&odwójne buforowanie + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Podwójne buforowanie redukuje migotanie przez przechowywanie dwóch klatek w pamięci, i wyświetlanie jednej podczas dekodowania drugiej. Jeśli jest to wyłączone może oddziaływać negatywnie na OSD, ale często usuwa jego migotanie. + + + + &Enable postprocessing by default + &Włącz domyślnie przetwarzanie końcowe + + + + Volume &normalization by default + Domyślna &normalizacja głośności + + + + Close when finished + Zamknij program gdy zakończy odtwarzanie + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Jeśli ta opcja jest zaznaczona, okno główne automatycznie zamknie się po zakończeniu bieżącego pliku/listy odtwarzania. + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + &Standardowo kanały: + + + + &Pause when minimized + &Pauza gdy minimalizujesz + + + + Pause when minimized + Pauza gdy minimalizujesz + + + + Enable postprocessing by default + Włącz domyślne przetwarzanie końcowe + + + + Max. Amplification + Maksymalne wzmocnienie + + + + Volume normalization by default + Domyślna normalizacja głośności + + + + Maximizes the volume without distorting the sound. + Zwiększ głośność bez zniekształcenia dźwięku. + + + + Default volume + Domyślna głośność + + + + Sets the initial volume that new files will use. + Ustaw początkową głośność dla nowych plików. + + + + Channels by default + Domyślnie kanały + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Ustaw maksymalny poziom wzmocnienia w procentach (domyślnie: 110). Wartość 200 pozwoli wyregulować głośność do maksymalnie podwójnego bieżącego poziomu. Z wartościami poniżej 100 początkowa głośność (która wynosi 100%) będzie powyżej maksimum, której np. OSD nie wyświetli poprawnie. + + + + Uses hardware AC3 passthrough + Użyj sprzętowego przejścia AC3 (AC3 passthrough) + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Prośba o ilość kanałów odtwarzania. MPlayer pyta dekoder na jak wiele przewidzianych kanałów dekodować audio. Następnie żądanie to zostaje wykonane przez dekoder. Jest to istotne tylko gdy odtwarzane jest wideo z audio AC3 (takie jak DVD). W takim przypadku domyślnie dekoduje liba52 i poprawnie miksuje audio do wymaganych kanałów. NOTKA: Opcja ta działa tylko z kodekami (tylko AC3), filtrami (surround) i sterownikami wyjściowymi audio (co najmniej OSS). + + + + Postprocessing will be used by default on new opened files. + Przetwarzanie końcowe będzie użyte domyślnie dla nowo otwartych plików. + + + + Audio track + Ścieżka audio + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Określa domyślną ścieżkę audio, która będzie używana gdy odtwarzasz nowe pliki. Jeśli ścieżka nie istnieje, użyta zostanie pierwsza. <br><b>Notka:</b> to <i>"preferowany język audio"</i> ma pierwszeństwo nad tą opcją. + + + + Subtitle track + Ścieżka napisów + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Określa domyślną ścieżkę napisów, która będzie używana gdy odtwarzasz nowe pliki. Jeśli ścieżka nie istnieje, użyta zostanie pierwsza. <br><b>Notka:</b> to <i>"preferowany język napisów"</i> ma pierwszeństwo nad tą opcją. + + + + Or choose a track number: + Lub wybierz numer ścieżki: + + + + Audi&o: + &Audio: + + + + Preferred language: + Preferowany język: + + + + Preferre&d audio and subtitles + Preferowana &ścieżka dźwiękowa i napisy + + + + &Subtitle: + &Napisy: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Tutaj możesz ustawić preferowany język napisów i ścieżki dźwiękowej. Jeśli SMPlayer wykryje więcej niż jedną ścieżkę dźwiękową lub z napisami, spróbuje użyć preferowanej. Ta funkcja działa tylko z mediami, które podają informację o ścieżkach dźwiękowych i z napisami, takie jak DVD i pliki mkv.<br>To pole akceptuje regularne wyrażenia. Na przykład: <b>es|esp|spa</b> będzie dobierać ścieżkę odpowiadającą <i>es</i>, <i>esp</i> lub <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Tutaj wchodzi wyjaśniający tekst> +Do tłumaczy: nie tłumacz tego tekstu, będzie on zastąpiony innym w czasie pracy programu. + + + + High speed &playback without altering pitch + Wysoka prędkość &odtwarzania bez zmieniania skoku + + + + High speed playback without altering pitch + Wysoka prędkość odtwarzania bez zmieniania skoku + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Pozwól na zmianę prędkości odtwarzania bez zmieniania skoku. Wymagany MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Zmień prędkość tylko przed odtwarzaniem + + + + &Video + &Wideo + + + + Use s&oftware video equalizer + Użyj &programowego korektora wideo + + + + A&udio + A&udio + + + + Volume + Głośność + + + + None + Nic + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normalny) + + + + Yadif (double framerate) + Yadif (podwójna szybkość klatek) + + + + Linear Blend + Liniowy mieszany + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + &Domyślne usuwanie przeplotu: + + + + Deinterlace by default + Domyślne usuwanie przeplotu + + + + Select the deinterlace filter that you want to be used for new videos opened. + Wybierz filtr usuwania przeplotu dla nowo otwieranych plików wideo. + + + + Remember time position + Zapamiętaj pozycję czasu + + + + Remember &time position + Zapamiętaj &pozycję czasu + + + + Change volume just before p&laying + Zmień prędkość tylko przed &odtwarzaniem + + + + Enable the audio equalizer + Włącz korektor audio + + + + Check this option if you want to use the audio equalizer. + Zaznacz tę opcję jeśli chcesz użyć korektora audio. + + + + &Enable the audio equalizer + &Włącz korektor audio + + + + Draw video using slices + Rysuj obraz wideo używając segmentów + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Włącz/wyłącz rysowanie obrazu wideo przez 16 pikselową wysokość segmentów/pasm. Jeśli wyłączone, cała ramka jest rysowana w pojedyńczym przebiegu. Może to być szybsze lub wolniejsze w zależności od karty wideo i dostępnej pamięci podręcznej. Ma to efekt tylko z kodekami libmpeg2 i libavcodecs. + + + + Dra&w video using slices + &Rysuj obraz wideo używając segmentów + + + + &Close when finished playback + &Zamknij kiedy skończył odtwarzanie + + + + fast + szybko + + + + slow + powoli + + + + fast - ATI cards + szybko - karty ATI + + + + User defined... + Określone przez użytkownika... + + + + Default zoom + Domyślny zoom + + + + This option sets the default zoom which will be used for new videos. + Opcja ta ustawia domyślnie zoom dla nowych plików wideo. + + + + Default &zoom: + Domyślny &zoom: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Tutaj musisz podać plik wykonywalny mplayera.<br>Minimalna wymagana wersja to 1.0rc1 (rekomendowana wersja SVN). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Jeśli opcja ta jest zła, SMPlayer nie będzie w stanie odtworzyć niczego! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Tutaj podajesz katalog, w którym będą zapisywane zrzuty ekranu wykonane przez SMPlayer. Jeśli zostawisz to pole puste opcja zrzutów ekranu będzie wyłączona. + + + + Select the video output driver. %1 provides the best performance. + Wybierz sterownik wyjściowy wideo. %1 dają najlepszą wydajność. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 jest rekomendowany. Spróbuj ominąć %2 i %3, są one wolne i mają wpływ na wydajność. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + Zwykle SMPlayer pamięta ustawienia dla każdego odtwarzanego pliku (wybranej ścieżki audio, głośności, fitrów...). Odznacz tę opcję aby tego nie robił. + + + + If you check this option, SMPlayer will play all files from the beginning. + Gdy ta opcja jest zaznaczona, SMPlayer będzie odtwarzał wszystkie pliki od początku. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Jeśli opcja ta jest włączona i okno główne jest ukryte, plik zostanie zapauzowany. Gdy okno główne zostanie przywrócone, nastąpi wznowienie odtwarzania. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Zaznacz tę opcję aby wyłączyć wygaszacz ekranu podczas odtwarzania.<br>Wygaszacz ekranu będzie uruchomiony ponownie po zakończonym odtwarzaniu. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Tutaj możesz ustawić preferowany język ścieżki dźwiękowej. Jeśli SMPlayer wykryje więcej niż jedną ścieżkę dźwiękową spróbuje użyć preferowanej.<br>Ta funkcja działa tylko z mediami, które podają informację o ścieżkach dźwiękowych, takie jak DVD lub pliki mkv.<br>To pole akceptuje regularne wyrażenia. Na przykład: <b>es|esp|spa</b> będzie dobierać ścieżkę dźwiękową odpowiadającą <i>es</i>, <i>esp</i> lub <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Tutaj możesz ustawić preferowany język napisów. Jeśli SMPlayer wykryje więcej niż jedną ścieżkę z napisami, spróbuje użyć preferowanej.<br>Ta funkcja działa tylko z mediami, które podają informację o ścieżkach napisów takie jak DVD lub pliki mkv.<br>To pole akceptuje regularne wyrażenia. Na przykład: <b>es|esp|spa</b> będzie dobierać ścieżkę napisów odpowiadającą <i>es</i>, <i>esp</i> lub <i>spa</i>. + + + + Ou&tput driver: + &Sterownik wyjściowy: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Klawiatura i myszka + + + + &Keyboard + &Klawiatura + + + + icon + ikona + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Tutaj możesz zmienić każdy klawisz skrótu. Aby to zrobić kliknij dwa razy w polu klawisza skrótu i przyporządkuj mu klawisz klawiatury. Dodatkowo możesz także zapisać listę, aby podzielić się nią z innymi lub wykorzystać na innym komputerze. + + + + &Mouse + &Myszka + + + + Button functions: + Funkcje przycisku: + + + + Media seeking + Pasek postępu odtwarzania + + + + Volume control + Kontrola głośności + + + + Zoom video + Zoom wideo + + + + None + Nic + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Tutaj możesz zmienić każdy klawisz skrótu. Aby to zrobić kliknij dwa razy w polu klawisza skrótu i przyporządkuj mu klawisz klawiatury. Dodatkowo możesz także zapisać listę aby podzielić się nią z innymi lub wykorzystać na innym komputerze. + + + + &Left click + &Lewy przycisk + + + + &Double click + &Dwuklik lewego przycisku + + + + &Wheel function: + &Funkcje kółka: + + + + Shortcut editor + Edytor skrótów klawiszowych + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Tabela ta pozwala zmienić klawisz skrótu dla każdej dostępnej funkcji. Kliknij dwa razu lub wciśnij enter na pozycję, lub wybierz <b>Zmień klawisz skrótu</b> w dialogu <i>Modyfikuj klawisz skrótu</i>. Istnieją dwie metody zmiany klawisza skrótu: przez funkcję <b>Przechwycenie</b> po prostu naciśnij nowy klawisz lub ich kombinację, której chcesz przypisać odpowiednią funkcję (niestety nie działa to z wszystkimi klawiszami). Jeśli przycisk <b>Przechwycenie</b> jest wyłączony wtedy możesz wpisać pełną nazwę klawisza. + + + + Left click + Lewy przycisk + + + + Select the action for left click on the mouse. + Wybierz funkcję dla lewego przycisku myszki. + + + + Double click + Dwuklik lewego przycisku + + + + Select the action for double click on the mouse. + Wybierz funkcję dla dwukliku lewego przycisku. + + + + Wheel function + Funkcje kółka + + + + Select the action for the mouse wheel. + Wybierz funkcję dla kółka myszki. + + + + Play + Odtwarzaj + + + + Pause + Pauza + + + + Stop + Stop + + + + Fullscreen + Pełny ekran + + + + Compact + Ukryj menu i przyciski + + + + Screenshot + Zrzut ekranu + + + + On top + Na wierzchu + + + + Mute + Wycisz + + + + Frame counter + Licznik klatek + + + + Reset zoom + Resetuj zoom + + + + Exit fullscreen + Wyjdź z pełnego ekranu + + + + Double size + Podwójny rozmiar + + + + Play / Pause + Odtwarzaj / Pauza + + + + Pause / Frame step + Pauza / Krok + + + + Playlist + Lista odtwarzania + + + + Preferences + Preferencje + + + + No function + Bez funkcji + + + + Change speed + Zmień prędkość + + + + Normal speed + Normalna prędkość + + + + Keyboard + Klawiatura + + + + Mouse + Myszka + + + + Middle click + Środkowy przycisk + + + + Select the action for middle click on the mouse. + Wybierz funkcję dla środkowego przycisku myszki. + + + + M&iddle click + &Środkowy przycisk + + + + X Button &1 + X Button &1 + + + + X Button &2 + X Button &2 + + + + Go backward (short) + Do tyłu (mało) + + + + Go backward (medium) + Do tyłu (średnio) + + + + Go backward (long) + Do tyłu (dużo) + + + + Go forward (short) + Do przodu (mało) + + + + Go forward (medium) + Do przodu (średnio) + + + + Go forward (long) + Do przodu (dużo) + + + + OSD - Next level + OSD-następny poziom + + + + Show context menu + Pokaż menu kontekstowe + + + + &Right click + &Prawy przycisk + + + + Increase volume + Zwiększ głośność + + + + Decrease volume + Zmniejsz głośność + + + + X Button 1 + Przycisk X 1 + + + + Select the action for the X button 1. + Wybierz funkcję dla przycisku X 1. + + + + X Button 2 + Przycisk X 2 + + + + Select the action for the X button 2. + Wybierz funkcję dla przycisku X 2. + + + + Show video equalizer + Pokaż korektor wideo + + + + Show audio equalizer + Pokaż korektor audio + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Interfejs + + + + <Autodetect> + <Autodetekcja> + + + + Default + Domyślne + + + + &Interface + &Interfejs + + + + Seeking + Wyszukiwanie + + + + Recent files + Ostanio otwarte pliki + + + + Never + Nigdy + + + + Whenever it's needed + Jeżeli jest taka potrzeba + + + + Only after loading a new video + Tylko po załadowaniu nowego filmu + + + + Language + Język + + + + Here you can change the language of the application. + Tutaj można zmienić język programu. + + + + Instances + Przypadki + + + + &Short jump + &Mały skok + + + + &Medium jump + &Średni skok + + + + &Long jump + &Duży skok + + + + Mouse &wheel jump + Skok &kółka myszki + + + + &Use only one running instance of SMPlayer + &Użyj tylko jednej uruchomionej kopii programu SMPlayer + + + + Ma&x. items + Ma&x. pozycji + + + + St&yle: + St&yle: + + + + Ico&n set: + Wybie&rz ikony: + + + + L&anguage: + J&ęzyk: + + + + Main window + Główne okno + + + + Auto&resize: + Automatyczna &zmiana rozmiaru: + + + + R&emember position and size + Z&apamietaj pozycję i rozmiar + + + + Default font: + Domyślna czcionka: + + + + &Change... + &Zmień... + + + + &Behaviour of time slider: + &Zachowanie suwaka czasu: + + + + Seek to position while dragging + Wyszukaj pozycję podczas przeciągania + + + + Seek to position when released + Wyszukaj pozycję podczas zwalniania + + + + TextLabel + TextLabel + + + + &Seeking + &Wyszukiwanie + + + + Ins&tances + &Przypadki + + + + Autoresize + Automatyczna zmiana rozmiaru + + + + The main window can be resized automatically. Select the option you prefer. + Okno główne może być zmieniane automatycznie. Wybierz opcję, którą preferujesz. + + + + Remember position and size + Zapamiętaj pozycję i rozmiar + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Jeśli zaznaczysz tę opcję, pozycja i rozmiar okna głównego zostanie zapisana i przywrócona, gdy ponownie uruchomisz SMPlayer. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Wybierz maksymalną ilość pozycji, które zostaną pokazane w podmenu <b>Otwórz->Ostatnio otwierane pliki</b>. Jeśli ustawisz 0, menu nie pokaże nic. + + + + Icon set + Kolekcja ikon + + + + Select the icon set you prefer for the application. + Wybierz kolekcję ikon dla programu. + + + + Style + Styl + + + + Select the style you prefer for the application. + Wybierz styl dla programu. + + + + Default font + Domyślna czcionka + + + + You can change here the application's font. + Tutaj możesz zmienić czcionkę programu. + + + + Short jump + Mały skok + + + + Select the time that should be go forward or backward when you choose the %1 action. + Wybierz czas, który powinien upłynąć do przodu lub do tyłu gdy wybierzesz %1. + + + + short jump + mały skok + + + + Medium jump + Średni skok + + + + medium jump + średni skok + + + + Long jump + Duży skok + + + + long jump + duży skok + + + + Mouse wheel jump + Skok kółka myszki + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Wybierz czas, który powinien upłynąć do przodu lub do tyłu podczas ruchu kółkiem myszki. + + + + Behaviour of time slider + Zachowanie suwaka czasu + + + + Select what to do when dragging the time slider. + Zdecyduj co zrobić gdy przesuwasz suwak czasu. + + + + Use only one running instance of SMPlayer + Użyj tylko jednej uruchomionej kopii programu SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Zaznacz tę opcję, jeśli chcesz otwierać inne pliki przez aktualnie uruchomioną kopię programu SMPlayer. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer wymaga portu nasłuchu w celu otrzymywania komend od innych przypadków. Możesz zmienić port w wypadku gdy port domyślny używany jest przez inny program. + + + + Default GUI + Domyślne GUI + + + + Mini GUI + Mini GUI + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Wybierz graficzny interfejs użytkownika (GUI). Obecnie są do wyboru dwa: Domyślne GUI i Mini GUI.<br> <b>Domyślne GUI</b> dostarcza tradycyjny interfejs z paskiem narzędzi i kontroli. <b>Mini GUI</b> dostarcza prostrzy interfejs pozbawiony paska narzędzi i kontroli.<br><b>Notka:</b>opcja ta wymaga ponownego uruchomienia SMPlayera. + + + + &GUI + &GUI + + + + Automatic port + Port automatycznie + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer wymaga portu nasłuchu w celu otrzymywania komend od innych przypadków. Jeśli zaznaczysz tę opcję, port zostanie wybrany automatycznie. + + + + Manual port + Port ręcznie + + + + Port to listen + Port nasłuchu + + + + &Automatic + &Automatycznie + + + + &Manual + &Ręcznie + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Wydajność + + + + &Performance + &Wydajność + + + + Priority + Priorytet + + + + Select the priority for the MPlayer process. + Wybierz priorytet dla MPlayera. + + + + realtime + realtime + + + + high + wysoki + + + + abovenormal + poniżej normalego + + + + normal + normalny + + + + belownormal + powyżej normalnego + + + + idle + bezczynny + + + + Cache + Bufor + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Ustawienie bufora może polepszyć odtwarzanie na wolnych napędach + + + + Allow frame drop + Pozwól na pomijanie klatek + + + + Synchronization + Synchronizacja + + + + Audio/video auto synchronization + Automatyczna synchronizacja Audio/Wideo + + + + Fast audio track switching + Szybkie przełączanie ścieżek audio + + + + Fast seek to chapters in dvds + Szybkie szukanie rozdziałów w dvd + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Ustaw priorytet procesu mplayera zgodnie z hierarchią wartości pod Windows.<br><b>UWAGA:</b>Użycie najwyższego priorytetu może być przyczyną niestabilności systemu. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Wybranie tej opcji powoduje pomijanie wyświetlania niektórych klatek aby utrzymać synchronizację A/V na słabszym sprzęcie. + + + + Allow hard frame drop + Mocne pomijanie klatek + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Wybranie tej opcji powoduje mocne pomijanie klatek (błędy w dekodowaniu obrazu). Może to powodować zniekształcenia obrazu! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Stopniowa regulacja synchronizacji A/V bazująca na pomiarach opóźnień. + + + + Priorit&y: + P&riorytet: + + + + &Allow frame drop + &Pozwól na pomijanie klatek + + + + Allow &hard frame drop (can lead to image distortion) + Mocne &pomijanie klatek (może spowodować niestabilność wyświetlania) + + + + Audio/&video auto synchronization + Automatyczna synchronizacja Audio/&Wideo + + + + Fact&or: + Współ&czynnik: + + + + &Fast audio track switching + &Szybkie przełączanie ścieżek audio + + + + Fast &seek to chapters in dvds + Szybkie &szukanie rozdziałów w dvd + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Jeśli jest zaznaczone to spróbuje użyć szybszej metody wyszukiwania rozdziałów, jednak może to nie działać z niektórymi dyskami. + + + + Skip loop filter + Pomiń filtr loop + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Możliwe wartości:<br> <b>Tak</b>: będzie próbować szybszej metody przełączania ścieżek audio (może nie działać z niektórymi formatami).<br> <b>Nie</b>: proces MPlayera zostanie zrestartowany kiedykolwiek zmienisz ścieżkę audio.<br> <b>Auto</b>: SMPlayer będzie decydował co robić zależnie od wersji MPlayera. + + + + Cache for files + Bufor dla plików + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Ta opcja określa ile pamięci (w KB) należy użyć dla buforowania pliku. + + + + Cache for streams + Bufor dla strumieni + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Ta opcja określa ile pamięci (w KB) należy użyć dla buforowania URL. + + + + Cache for DVDs + Bufor dla DVD + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Ta opcja określa ile pamięci (w KB) należy użyć dla buforowania DVD.<br><b>Uwaga:</b> Przewijanie może nie działać poprawnie (włączając przełączanie rozdziałów) podczas używania bufora dla DVD. + + + + &Cache + &Bufor + + + + Cache for &DVDs: + Bufor dla &DVD: + + + + Cache for &local files: + Bufor dla &lokalnych plików: + + + + Cache for &streams: + Bufor dla &strumieni: + + + + Enabled + Włączone + + + + Skip (always) + Pomiń (zawsze) + + + + Skip only on HD videos + Pomiń tylko przy wideo DVD + + + + Loop &filter + Filtr &loop + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Ta opcja pozwala pominąć filtr loop (AKA debloking) przy dekodowaniu h264. Ponieważ odfiltrowanie klatek przypuszczalnie używa się do dekodowania zależnych klatek ma to gorszy efekt na jakość niż brak funkcji deblocking np. na wideo MPEG-2. Ale przynajmniej dla wysokiego bitrate HDTV zapewnia to duże przyspieszenie bez żadnej widocznej utratu jakości. + + + + Possible values: + Dopuszczalne wartości: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Włączone</b>: filtr loop nie jest pominięty + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Pomiń (zawsze)</b>: filtr loop jest pominięty w kwestii rozdzielczości wideo + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Pomiń tylko przy wideo HD</b>: filtr loop będzie pominięty tylko przy wideo, których wysokość jest większa niż %1. + + + + Cache for audio CDs + Bufor dla audio CD + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Opcja ta precyzuje ile pamięci (w kb) należy użyć dla buforowania audio CD. + + + + Cache for &audio CDs: + Bufor dla &audio CD: + + + + Cache for VCDs + Bufor dla VCD + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Opcja ta precyzuje ile pamięci (w kb) należy użyć dla buforowania VCD. + + + + Cache for &VCDs: + Bufor dla &VCD: + + + + Threads for decoding + Wątki dekodowania + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Ustaw ilość wątków dekodowania. Tylko dla MPEG-1/2 i H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Wątki dekodowania (tylko dla MPEG-1/2 i H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Lista odtwarzania + + + + Automatically add files to playlist + Automatycznie dodaj pliki do listy odtwarzania + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Jesli opcja ta jest włączona, zawsze gdy zostanie otwarty plik, SMPlayer najpierw wyczyści listę odtwarzania i doda do niej ten plik. W przypadku DVD, CD, VCD, wszystkie tytuły z dysku zostaną dodane do listy odtwarzania. + + + + Add consecutive files + Dodaj kolejne pliki + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Jesli opcja ta jest włączona, SMPlayer będzie szukał kolejnych plików (np. video_1.avi, video_2.avi...) i jeśli znajdzie, doda je do listy odtwarzania. + + + + &Playlist + &Lista odtwarzania + + + + &Automatically add files to playlist + &Automatycznie dodaj pliki do listy odtwarzania + + + + Add &consecutive files + Dodaj &kolejne pliki + + + + PrefSubtitles + + + Subtitles + Napisy + + + + Choose a ttf file + Wybierz TTF - plik + + + + Truetype Fonts + Czcionki truetyp + + + + &Subtitles + &Napisy + + + + Autoload + Autoładowanie + + + + Select first available subtitle + Wybierz pierwsze dostępne napisy + + + + Same name as movie + Taka sama nazwa jak film + + + + All subs containing movie name + Wszystkie napisy zawierające nazwę filmu + + + + All subs in directory + Wszystkie napisy w katalogu + + + + Position + Pozycja + + + + 0 + 0 + + + + Top + Góra + + + + Bottom + Dół + + + + Include subtitles on screenshots + Dołącz napisy w zrzucie ekranu + + + + Font + Czcionka + + + + Select the font which will be used for subtitles (and OSD): + Wybierz czcionkę dla napisów (oraz OSD): + + + + Size + Rozmiar + + + + No autoscale + Bez autoskalowania + + + + Proportional to movie height + Proporcjonalnie do wysokości + + + + Proportional to movie width + Proporcjonalnie do szerokości + + + + Proportional to movie diagonal + Proporcjonalnie do przekątnej filmu + + + + Subtitle position + Pozycja napisów + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Ta opcja określa pozycję napisów w wyświetlanym filmie. <i>100</i> napisy na dole filmu, a <i>0</i> napisy na górze. + + + + Au&toload subtitles files (*.srt, *.sub...): + Au&tomatycznie ładuj napisy (*.srt, *.sub...): + + + + S&elect first available subtitle + W&ybierz piewsze dostępne napisy + + + + &Default subtitle encoding: + &Domyślne kodowanie napisów: + + + + Default &position of the subtitles on screen + Domyślna &pozycja napisów na ekranie + + + + &Include subtitles on screenshots + &Dołącz napisy w zrzucie ekranu + + + + &TTF font: + &Czcionka TTF: + + + + S&ystem font: + Cz&cionka systemowa: + + + + A&utoscale: + A&utoskalowanie: + + + + Default subtitle encoding + Domyślne kodowanie napisów + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Jeśli opcja ta jest zaznaczona, napisy pojawią się w zrzucie ekranu. Notka: czasami może powodować problemy. + + + + TTF font + Czcionka TTF + + + + System font + Czcionka systemowa + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Tutaj możesz wybrać czcionkę systemową dla napisów i OSD. <b>Notka:</b> wymaga MPlayera z obsługą ustawień czcionki. + + + + Autoscale + Autoskalowanie + + + + Text color + Kolor tekstu + + + + Select the color for the text of the subtitles. + Wybierz kolor tekstu napisów. + + + + Border color + Kolor obwódki + + + + Select the color for the border of the subtitles. + Wybierz kolor obwódki napisów. + + + + Select the subtitle autoload method. + Wybierz napisy metodą autoładowania. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Jeśli dostępne jest kilka ścieżek napisów, jedna z nich zostanie wybrana automatycznie, zwykle pierwsza. Jednak, gdy jedna z nich odpowiada preferowanemu językowi użytkownika, wtedy to ona zostanie użyta. + + + + Select the subtitle autoscaling method. + Wybierz napisy metodą autoskalowania. + + + + Select the encoding which will be used for subtitle files by default. + Wybierz kodowanie, które zostanie użyte jako domyślne dla plików napisów. + + + + Try to autodetect for this language + Spróbuj autodetekcji dla tego języka + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Jeśli opcja ta jest zaznaczona, kodowanie dla ustalonych napisów zostanie wykryte automatycznie. Gdy autodetekcja nie powiedzie się, kodowanie powróci do domyślnego. Opcja ta wymaga MPlayera kompilowanego z obsługą ENCA. + + + + Subtitle language + Język napisów + + + + Select the language for which you want the encoding to be guessed automatically. + Wybierz język, dla którego chcesz aby kodowanie zostało wykryte automatycznie. + + + + Encoding + Kodowanie + + + + Try to a&utodetect for this language: + Spróbuj &autodetekcji dla tego języka: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Tutaj możesz wybrać czcionkę ttf dla napisów. Dużą ilość czcionek ttf znajdziesz w <i>%1</i> + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + Dół + + + + Middle + vertical alignment + + + + + Top + vertical alignment + Góra + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Pomoc + + + + OK + OK + + + + Cancel + Anuluj + + + + Apply + Zatwierdź + + + + Help + Pomoc + + + + SMPlayer - Preferences + SMPlayer - Ustawienia + + + + QObject + + + will show this message and then will exit. + pokaże się ta wiadomość a następnie zostanie zamknięty. + + + + the main window will be closed when the file/playlist finishes. + okno główne zostanie zamknięte, gdy zakończy się plik/lista odtwarzania. + + + + This is SMPlayer v. %1 running on %2 + To jest SMPlayer v. %1 uruchomiony na %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + próby wykonania połączenia z inną uruchomioną kopią programu i wysłania do niej określonej operacji. Na przykład: -action pause. Reszta opcji (jeśli są) będą ignorowane i program zostanie zamknięty. Będzie zwracać 0 w przypadku powodzenia lub -1 przy niepowodzeniu. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list to lista poleceń oddzielonych spacją. Polecenia będą po prostu wykonywane po załadowaniu pliku (jeśli jest), we wpisanej wcześniej kolejności. Dla skontrolowanych poleceń możesz pominąć prawdę lub fałsz jako parametr. Na przykład: -actions "fullscreen compact true". Cudzysłowy są niezbędne w przypadku pominięcia więcej niż jednego polecenia. + + + + media + media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + jeśli uruchomiona jest inna kopia programu, media zostaną dodane do jej listy odtwarzania. Jeśli nie ma innej kopii programu, opcja ta jest ignorowana i pliki zostaną otwarte w nowej kopii programu. + + + + the main window won't be closed when the file/playlist finishes. + gdy zakończy się plik/lista odtwarzania okno główne nie zostanie zamknięte. + + + + the video will be played in fullscreen mode. + wideo będzie odtwarzane w trybie pełnego ekranu. + + + + the video will be played in window mode. + wideo będzie odtwarzane w trybie wyświetlania obrazu w oknie. + + + + Enqueue in SMPlayer + Kolejkuj w SMPlayer + + + + opens the mini gui instead of the default one. + otwórz mini gui zamiast domyślnego. + + + + Restores the old associations and cleans up the registry. + Przywróć poprzednie skojarzenia i wyczyść rejestr. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' to każdy plik, który SMPlayer jest w stanie otworzyć. Może to być plik lokalny, DVD (n.p. dvd://1), strumień internetowy (n.p. mms://1) lub lista odtwarzania w formacie m3u lub pls. Jeśli opcja -playlist jest użyta, oznacza to, że SMPlayer przeniesie opcję -playlist do MPlayera, więc MPlayer obsłuży listę odtwarzania. + + + + Usage: + Użycie: + + + + directory + katalog + + + + action_name + nazwa_działania + + + + action_list + lista_działań + + + + opens the default gui. + otwórz domyślne gui. + + + + subtitle_file + plik_napisów + + + + specifies the subtitle file to be loaded for the first video. + określ plik napisów, które zostaną wczytane dla pierwszego plku wideo. + + + + %1 second(s) + + %1 sekund (a,y) + %1 sekund (a,y) + %1 sekund (a,y) + + + + + %1 minute(s) + + %1 minut (a,y) + %1 minut (a,y) + %1 minut (a,y) + + + + + %1 and %2 + %1 i %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + ZIP/UNZIP API błąd %1 + + + + SeekWidget + + + icon + ikona + + + + label + etykieta + + + + ShortcutGetter + + + Modify shortcut + Modyfikuj klawisz skrótu + + + + Clear + Wyczyść + + + + Press the key combination you want to assign + Naciśnij kombinację klawiszy, które chcesz wyznaczyć + + + + Capture + Przechwycenie + + + + Capture keystrokes + Przechwycenie naciśnięć klawiszy + + + + SubChooserDialog + + + Subtitle selection + Wybór napisów + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + To archiwum zawiera wimecej niż jeden plik napisów. Proszę wybrać jeden, który chcesz wypakować. + + + + Select All + Wybierz wszystko + + + + Select None + Nie wybieraj nic + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Wyszukiwanie + + + + &Jump to: + &Skocz do: + + + + TristateCombo + + + Auto + Auto + + + + Yes + Tak + + + + No + Nie + + + + VideoEqualizer + + + Contrast + Kontrast + + + + Brightness + Jasność + + + + Hue + Odcień + + + + Saturation + Nasycenie + + + + Gamma + Gamma + + + + &Reset + &Wyzeruj + + + + &Set as default values + &Ustaw wartości jako domyślne + + + + Use the current values as default values for new videos. + Użyj aktualnych wartości jako domyślnych dla nowych plików wideo. + + + + Set all controls to zero. + Ustaw wszystkie suwaki na zero. + + + + Video Equalizer + Korektor wideo + + + + Information + Informacja + + + + The current values have been stored to be used as default. + Aktualne wartości zostaną przechowane aby mogły być użyte jako domyślne. + + + + VideoPreview + + + Video preview + + + + + Cancel + Anuluj + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Błąd zapisu pliku + + + + The file couldn't be saved + Plik nie może zostać zapisany + + + + Error + Błąd + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Domyślne + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Głośność + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_pt_BR.ts b/plugins/smplayer_plugin/translations/smplayer_pt_BR.ts new file mode 100644 index 000000000..0c82e18da --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_pt_BR.ts @@ -0,0 +1,7210 @@ + + + + About + + + Version: %1 + Versão: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Este programa é software livre, você pode redistribui-lo e/ou modificá-lo de acordo com os termos da Licença Pública Geral GNU que é publicado pela Free Software Foundation; seja na versão 2 dessa licença, ou (a sua escolha) em qualquer versão posterior. + + + + The following people have contributed with translations: + + + + + German + Alemão + + + + Slovak + Eslovênio + + + + Italian + Italiano + + + + French + Francês + + + + %1, %2 and %3 + + + + + Simplified-Chinese + Chinês Simplificado + + + + Russian + Russo + + + + %1 and %2 + + + + + Hungarian + Hungaro + + + + Polish + Polonês + + + + Japanese + Japonês + + + + Dutch + Holandês + + + + Ukrainian + Ucraniano + + + + Portuguese - Brazil + Português do Brasil + + + + Georgian + Georgiano + + + + Czech + Tcheco + + + + Bulgarian + Bulgaro + + + + Turkish + Turco + + + + Swedish + Sueco + + + + Serbian + Sérvio + + + + Traditional Chinese + Chinês Tradicional + + + + Romanian + Romeno + + + + Portuguese - Portugal + Português de Portugal + + + + Greek + Grego + + + + Finnish + Finlandês + + + + <b>%1</b>: %2 + + + + + <b>%1</b> (%2) + + + + + About SMPlayer + Sobre o SMPlayer + + + + &Info + + + + + icon + + + + + &Contributions + + + + + &Translators + + + + + &License + + + + + Visit our web for updates: + + + + + Get help in our forum: + + + + + You can support SMPlayer by making a donation. + + + + + More info + + + + + Korean + + + + + Macedonian + + + + + Basque + + + + + Using MPlayer %1 + + + + + Catalan + + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + Árabe + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Nome + + + + Description + Descrição + + + + Shortcut + Atalho + + + + &Save + &Gravar + + + + &Load + &Abrir + + + + Key files + Arquivos chaves + + + + Choose a filename + Escolhar um nome de arquivo + + + + Confirm overwrite? + Confirma a sobregravação? + + + + The file %1 already exists. +Do you want to overwrite? + O arquivo %1 já existe. +Você quer sobregravá-lo? + + + + Choose a file + Escolhar um arquivo + + + + Error + Erro + + + + The file couldn't be saved + O arquivo não pode ser salvo + + + + The file couldn't be loaded + O arquivo não pode ser carregado + + + + &Change shortcut... + + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + &Resetar + + + + &Set as default values + Definir como valor &padrão + + + + Use the current values as default values for new videos. + Usar os valores atuais como padrão para novos vídeos. + + + + Set all controls to zero. + Definir todos os controles como zero. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer log + + + + SMPlayer - smplayer log + SMPlayer - SMPlayer log + + + + &Open + &Abrir + + + + &Play + &Reproduzir + + + + &Video + &Vídeo + + + + &Audio + Áu&dio + + + + &Subtitles + &Legendas + + + + &Browse + &Navegar + + + + Op&tions + &Opções + + + + &Help + &Ajuda + + + + &File... + &Arquivo... + + + + D&irectory... + D&iretório... + + + + &Playlist... + Lista de &reprodução... + + + + &DVD from drive + &DVD do drive + + + + D&VD from folder... + D&VD de um diretório... + + + + &URL... + &URL... + + + + &Clear + &Limpar + + + + &Recent files + &Arquivos recentes + + + + P&lay + &Reproduzir + + + + &Pause + &Pausar + + + + &Stop + &Parar + + + + &Frame step + Avanço de &quadro + + + + &Normal speed + &Velocidade Normal + + + + &Halve speed + &Metade da velocidade + + + + &Double speed + Velocidade &Dupla + + + + Speed &-10% + Velocidade &-10% + + + + Speed &+10% + Velocidade &+10% + + + + Sp&eed + Vel&ocidade + + + + &Repeat + &Repetir + + + + &Fullscreen + &Tela cheia + + + + &Compact mode + &Modo compacto + + + + Si&ze + &Tamanho + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &para 16:9 + + + + &Aspect ratio + &Relação de tamanho + + + + &None + &Nenhum + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Linear &Blend + + + + &Deinterlace + &Desentrelaçar + + + + &Postprocessing + &Postprocessing + + + + &Autodetect phase + &Autodetectar fase + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + Adicionar r&uido + + + + F&ilters + F&iltros + + + + &Equalizer + &Equalizador + + + + &Screenshot + &Screenshot + + + + S&tay on top + Man&ter no topo + + + + &Extrastereo + &Extrastéreo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtros + + + + &Stereo + E&stéreo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Canais + + + + &Left channel + Canal &Esquerdo + + + + &Right channel + Canal &Direito + + + + &Stereo mode + &Modo estéreo + + + + &Mute + &Silêncio + + + + Volume &- + Volume &- + + + + Volume &+ + Volume &+ + + + + &Delay - + &Atraso - + + + + D&elay + + A&traso + + + + + &Select + &Selecionar + + + + &Load... + &Carregar... + + + + Delay &- + Atraso &- + + + + Delay &+ + Atraso &+ + + + + &Up + &Acima + + + + &Down + A&baixo + + + + &Title + &Título + + + + &Chapter + &Capítulo + + + + &Angle + Â&ngulo + + + + &Playlist + &Lista de reprodução + + + + &Show frame counter + &Mostrar contador de quadros + + + + &Disabled + &Desativado + + + + &Seek bar + &Barra de procura + + + + &Time + &Tempo + + + + Time + T&otal time + Tempo + T&empo Total + + + + &OSD + &OSD + + + + &View logs + &Ver logs + + + + P&references + P&referências + + + + About &Qt + Sobre o &Qt + + + + About &SMPlayer + Sobre o &SMPlayer + + + + <empty> + <vazio> + + + + Video + Vídeo + + + + Audio + Áudio + + + + Playlists + Lista de reprodução + + + + All files + Todos os arquivos + + + + Choose a file + Escolha um arquivo + + + + SMPlayer - Information + SMPlayer - Informações + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Os drives de CDRom / DVD não estão configurados ainda. +O diálogo de configuração será aberto agora, e você poderá faze-lo. + + + + Choose a directory + Escolha um diretório + + + + Subtitles + Legendas + + + + About Qt + Sobre Qt + + + + Playing %1 + Reproduzindo %1 + + + + Pause + Pausar + + + + Stop + Parar + + + + Play / Pause + Reproduzir / Pausar + + + + Pause / Frame step + Pausar / Pulo de quadro + + + + U&nload + &Descarregar + + + + V&CD + V&CD + + + + C&lose + F&echar + + + + View &info and properties... + Ver &informações e propriedades... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Resetar + + + + Move &left + Mover &esquerda + + + + Move &right + Mover &direita + + + + Move &up + Mover para ci&ma + + + + Move &down + Mover para &baixo + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + Linha &prévia nas legendas + + + + N&ext line in subtitles + &Próxima linha nas legendas + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Reduzir volume (2) + + + + Inc volume (2) + Aumentar volume (2) + + + + Exit fullscreen + Sair de tela cheia + + + + OSD - Next level + OSD - Próximo nível + + + + Dec contrast + Reduzir contraste + + + + Inc contrast + Aumentar contraste + + + + Dec brightness + Reduzir brilho + + + + Inc brightness + Aumentar brilho + + + + Dec hue + Reduzir matiz + + + + Inc hue + Aumentar matiz + + + + Dec saturation + Reduzir Saturação + + + + Dec gamma + Reduzir gamma + + + + Next audio + Próximo áudio + + + + Next subtitle + Proxima legenda + + + + Next chapter + Próximo capítulo + + + + Previous chapter + Capítulo prévio + + + + Inc saturation + Aumentar saturação + + + + Inc gamma + Aumentar gamma + + + + &Load external file... + &Carregar arquivo externo... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif + + + + Y&adif (double framerate) + Y&adif (dupla velocidade) + + + + &Next + &Próximo + + + + Pre&vious + Pré&vio + + + + Volume &normalization + &Normalização do volume + + + + &Audio CD + CD de áu&dio + + + + Denoise nor&mal + + + + + Denoise &soft + + + + + Denoise o&ff + + + + + Use SSA/&ASS library + + + + + Flip i&mage + + + + + &Toggle double size + + + + + S&ize - + + + + + Si&ze + + + + + + Add &black borders + + + + + Soft&ware scaling + + + + + &FAQ + + + + + Visualize &motion vectors + + + + + &Command line options + + + + + SMPlayer command line options + + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &Trilha + + + + &Track + audio + &Trilha + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer continua sendo executado aqui + + + + S&how icon in system tray + &Mostrar icone ao painel do sistema + + + + &Hide + &Esconder + + + + &Restore + &Restaurar + + + + &Quit + &Sair + + + + Playlist + Lista de Reprodução + + + + Core + + + Brightness: %1 + Brilho: %1 + + + + Contrast: %1 + Contraste: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Matiz: %1 + + + + Saturation: %1 + Saturação: %1 + + + + Volume: %1 + Volume: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Bemvindo ao SMPlayer + + + + Audio + Áudio + + + + Subtitle + Legenda + + + + &Main toolbar + Barra de Ferramentas &Principal + + + + &Language toolbar + Barra de Ferramentas de &Linguagem + + + + &Toolbars + & Barras de Ferramentas + + + + EqSlider + + + icon + + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + + + + + Error + Erro + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - propriedades do arquivo + + + + &Information + &Informação + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Selecione o demuxer que será usado para este arquivo: + + + + &Reset + &Resetar + + + + &Video codec + &Video codec + + + + &Select the video codec: + &Selecionar o codec de vídeo: + + + + A&udio codec + Codec de Á&udio + + + + &Select the audio codec: + &Selecione o codec de áudio: + + + + &MPlayer options + Opções do &MPlayer + + + + Additional Options for MPlayer + Opções adicionais para o MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + + &Options: + &Opções: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + + + V&ideo filters: + Filtro&s de Vídeo: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + + + + + Audio &filters: + &Filtros de áudio: + + + + OK + + + + + Cancel + + + + + Apply + + + + + FindSubtitlesWindow + + + Language + Língua + + + + Name + Nome + + + + Format + Formato + + + + Files + + + + + Date + Data + + + + Uploaded by + + + + + All + + + + + Close + + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Erro + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Erro ao gravar o arquivo + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Geral + + + + Size + Tamanho + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Duração + + + + Demuxer + Demuxer + + + + Name + Nome + + + + Artist + Artista + + + + Author + Autor + + + + Album + Álbum + + + + Genre + Gênero + + + + Date + Data + + + + Track + Trilha + + + + Copyright + Copyright + + + + Comment + Comentário + + + + Software + Software + + + + Clip info + Informações do clip + + + + Video + Vídeo + + + + Resolution + Resolução + + + + Aspect ratio + Relação de tamanho + + + + Format + Formato + + + + Bitrate + Taxa de bits + + + + %1 kbps + %1 kbps + + + + Frames per second + Quadros por segundo + + + + Selected codec + Codec selecionado + + + + Initial Audio Stream + Fluxo de vídeo inicial + + + + Rate + Taxa + + + + %1 Hz + %1 Hz + + + + Channels + Canais + + + + Audio Streams + Faixas de áudio + + + + Language + Língua + + + + empty + vazio + + + + Subtitles + Legendas + + + + Type + Tipo + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Título da faixa + + + + Stream URL + URL da faixa + + + + File + + + + + InputDVDDirectory + + + Choose a directory + Escolha um diretório + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Reproduzir um DVD a partir de um diretório + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Você pode reproduzir um DVD de seu HD. Apenas selecione o diretório que contém as pastas VIDEO_TS e AUDIO_TS. + + + + Choose a directory... + Escolhar um diretório... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + + + + + &URL: + + + + + It's a &playlist + + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + Árabe + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + Bulgaro + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + Tcheco + + + + Welsh + + + + + Danish + + + + + German + Alemão + + + + Greek + Grego + + + + English + Inglês + + + + Esperanto + + + + + Spanish + Espanhol + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + Finlandês + + + + Faroese + + + + + French + Francês + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + Hungaro + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + Italiano + + + + Inuktitut + + + + + Japanese + Japonês + + + + Javanese + + + + + Georgian + Georgiano + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + Holandês + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + Polonês + + + + Portuguese + + + + + Quechua + + + + + Romanian + Romeno + + + + Russian + Russo + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + Eslovênio + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + Sérvio + + + + Sundanese + + + + + Swedish + Sueco + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Turco + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + Ucraniano + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + Português do Brasil + + + + Portuguese - Portugal + Português de Portugal + + + + Simplified-Chinese + Chinês Simplificado + + + + Traditional Chinese + Chinês Tradicional + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Línguas do Oeste Europeu + + + + Western European Languages with Euro + Línguas do Oeste Europeu com Euro + + + + Slavic/Central European Languages + Línguas Centro-Européias e Eslavas + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galício, Maltês, Turco + + + + Old Baltic charset + Antigo Charset Báltico + + + + Cyrillic + Cirílico + + + + Modern Greek + Grego Moderno + + + + Baltic + Báltico + + + + Celtic + Celta + + + + Hebrew charsets + Charsets Hebreus + + + + Ukrainian, Belarusian + Ucraniano, Bielorusso + + + + Simplified Chinese charset + Charset Chinês Simplificado + + + + Traditional Chinese charset + Charset Chinês Tradicional + + + + Japanese charsets + Charset Japonês + + + + Korean charset + Charset Coreano + + + + Thai charset + Charset Tailandês + + + + Cyrillic Windows + Windows Cirílico + + + + Slavic/Central European Windows + Windows Europa Central e Eslavo + + + + Arabic Windows + + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Escolha com que nome o arquivo será gravado + + + + Confirm overwrite? + Confirma a sobregravação? + + + + The file already exists. +Do you want to overwrite? + Este arquivo já existe. +Você quer sobregravá-lo? + + + + Error saving file + Erro ao gravar o arquivo + + + + The log couldn't be saved + O arquivo de log não pode ser gravado + + + + Logs + Logs + + + + LogWindowBase + + + Log Window + Janela de Log + + + + Save + Gravar + + + + Copy to clipboard + Copiar para a área de transferência + + + + Close + Fechar + + + + &Close + &Fechar + + + + MiniGui + + + Control bar + + + + + MpcGui + + + Control bar + + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nome + + + + Length + Duração + + + + &Play + &Reproduzir + + + + &Edit + &Editar + + + + Playlists + Lista de reprodução + + + + Choose a file + Escolhar um arquivo + + + + Choose a filename + Escolhar um nome de arquivo + + + + Confirm overwrite? + Confirma a sobregravação? + + + + The file %1 already exists. +Do you want to overwrite? + Este arquivo já existe. +Você quer sobregravá-lo? + + + + All files + Todos os arquivos + + + + Select one or more files to open + Selecione um ou mais arquivos para abrir + + + + Choose a directory + Escolhar um diretório + + + + Edit name + Editar o nome + + + + Type the name that will be displayed in the playlist for this file: + Digite o nome que será usado na lista de reprodução para este arquivo: + + + + &Load + &Carregar + + + + &Save + &Gravar + + + + &Next + &Próximo + + + + Pre&vious + Pré&vios + + + + Move &up + Mover &acima + + + + Move &down + Mover a&baixo + + + + &Repeat + &Repetir + + + + S&huffle + &Aleatório + + + + Add &current file + Adicionar arquivo &atual + + + + Add &file(s) + Adicionar a&rquivo(s) + + + + Add &directory + Adicionar &diretório + + + + Remove &selected + Remover &selecionado + + + + Remove &all + Remover &tudos + + + + SMPlayer - Playlist + SMPlayer - Lista de Reprodução + + + + Add... + Adicionar... + + + + Remove... + Remover... + + + + Playlist modified + Lista de reprodução modificada + + + + There are unsaved changes, do you want to save the playlist? + Existe modificações não salvas, você gostaria de gravar a lista de reprodução? + + + + Preferences + + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + Avançado + + + + Auto + + + + + &Advanced + &Avançado + + + + icon + icone + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aqui você pode passar opções extras para o MPlayer. +Escreva-as separadas por espaços. +Exemplo; -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Você pode também passar filtros adicionais de video. +Separados com ".". Não use espaços! +Exemplo: scale=512:-2.eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + E finalmente filtros de áudio. As mesmas regras dos filtros de video. +Exemplo: resample=44100:0:0.volnorm + + + + Log MPlayer output + Saída de log do MPlayer + + + + Log SMPlayer output + Saída de log do SMPlayer + + + + This option is mainly intended for debugging the application. + Esta opção é usada principalmente para o debugging da aplicação. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Marcando essa opção poderá reduzir a cintilação, mas poderá também produzir um vídeo não adequado para exibição. + + + + Filter for SMPlayer logs + + + + + &Monitor aspect: + + + + + &Run MPlayer in its own window + + + + + &Options: + &Opções: + + + + V&ideo filters: + Filtro&s de Vídeo: + + + + Audio &filters: + &Filtros de áudio: + + + + &Colorkey: + + + + + Log &SMPlayer output + + + + + &Filter for SMPlayer logs: + + + + + C&hange... + + + + + Logs + + + + + Log MPlayer &output + + + + + Options for MP&layer + + + + + Autosave MPlayer log + + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Tipo + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + + + + + Select all + + + + + Check all file types in the list + + + + + Uncheck all file types in the list + + + + + List of file types + + + + + File types + + + + + Media files handled by SMPlayer: + + + + + Select All + + + + + Select None + + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + Select none + + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + Drives + + + + icon + icone + + + + CD device + + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + + + + + DVD device + + + + + Choose your DVD device. It will be used to play DVDs. + + + + + Select your &CD device: + + + + + Select your &DVD device: + + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + Geral + + + + &General + + + + + Paths + Caminhos + + + + Media settings + Ajustes da mídia + + + + Preferred audio and subtitles + Legenda e áudio preferenciais + + + + Video + Vídeo + + + + Start videos in fullscreen + Iniciar os vídeos em tela cheia + + + + Disable screensaver + Desativar salva telas + + + + Audio + Áudio + + + + AC3/DTS pass-through S/PDIF + AC3/DTS passando via S/PDIF + + + + Select the mplayer executable + Selecione o executável do mplayer + + + + Executables + Executáveis + + + + All files + Todos os arquivos + + + + Select a directory + Selecione um diretório + + + + MPlayer executable + + + + + Screenshots folder + + + + + Video output driver + + + + + Audio output driver + + + + + Select the audio output driver. + Selecione um driver de saída de áudio. + + + + Remember settings + + + + + Preferred audio language + + + + + Preferred subtitle language + + + + + Software video equalizer + + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Você pode escolher esse opção a equalização de vídeo não é suportada por sua placa de vídeo ou pelo driver de saída de vídeo selecionado. <br><b>Observação:</b> esta opção pode ser incompatível com alguns drivers de saída de vídeo. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Se esta opção for escolhida, todos os vídeos serão reproduzidos no modo de tela cheia. + + + + Software volume control + + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Escolha essa opção para usar um mixer por software, ao invés de usar o mixer da placa de som. + + + + Postprocessing quality + + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Muda dinamicamente o nivel de pós-processamento dependendo da disponibilidade de tempo na CPU. O número que você especificar será o máximo nível usado. Geralmente você pode usar números grandes. + + + + Change volume + + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + 0 + 0 + + + + &Change volume on every file + + + + + Select the &MPlayer executable: + + + + + &Folder for storing screenshots: + + + + + &Audio: + + + + + &Remember settings for all files (audio track, subtitles...) + + + + + Su&btitles: + + + + + &Quality: + + + + + Start videos in &fullscreen + + + + + Disable &screensaver + + + + + &Default volume: + + + + + Use s&oftware volume control + + + + + Ma&x. Amplification: + + + + + &AC3/DTS pass-through S/PDIF + + + + + Direct rendering + + + + + Double buffering + + + + + D&irect rendering + + + + + Dou&ble buffering + + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + &Enable postprocessing by default + + + + + Volume &normalization by default + + + + + Close when finished + + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + + + + + 4 (4.0 Surround) + + + + + 6 (5.1 Surround) + + + + + C&hannels by default: + + + + + &Pause when minimized + + + + + Pause when minimized + + + + + Enable postprocessing by default + + + + + Max. Amplification + + + + + Volume normalization by default + + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + + + + + Audi&o: + + + + + Preferred language: + + + + + Preferre&d audio and subtitles + + + + + &Subtitle: + + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + &Vídeo + + + + Use s&oftware video equalizer + + + + + A&udio + + + + + Volume + Volume + + + + None + + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Teclado e mouse + + + + &Keyboard + &Teclado + + + + icon + icone + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aqui você pode modificar qualquer atalho de teclado. Para fazê-lo de um duplo clique ou digite sobre uma célula de atalho. Opcionalmente grave a lista e compartilhe com outras pessoas ou carregue em outro computador. + + + + &Mouse + &Mouse + + + + Button functions: + Botão de função: + + + + Media seeking + Procurar na mídia + + + + Volume control + Controle de volume + + + + Zoom video + Zoom vídeo + + + + None + Nenhum + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + + + + + &Double click + + + + + &Wheel function: + + + + + Shortcut editor + + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + + + + + Select the action for left click on the mouse. + + + + + Double click + + + + + Select the action for double click on the mouse. + + + + + Wheel function + + + + + Select the action for the mouse wheel. + + + + + Play + + + + + Pause + Pausar + + + + Stop + Parar + + + + Fullscreen + + + + + Compact + + + + + Screenshot + + + + + Mute + + + + + Frame counter + + + + + Reset zoom + + + + + Exit fullscreen + Sair de tela cheia + + + + Double size + + + + + Play / Pause + Reproduzir / Pausar + + + + Pause / Frame step + Pausar / Pulo de quadro + + + + Playlist + Lista de Reprodução + + + + Preferences + + + + + No function + + + + + Change speed + + + + + Normal speed + + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - Próximo nível + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Interface + + + + <Autodetect> + <Autodetectar> + + + + Default + Padrão + + + + &Interface + + + + + Seeking + Procurando + + + + Never + Nunca + + + + Whenever it's needed + Sempre que necessário + + + + Only after loading a new video + Apenas após carregar um novo vídeo + + + + Recent files + Arquivos recentes + + + + Language + Língua + + + + Here you can change the language of the application. + + + + + &Short jump + + + + + &Medium jump + + + + + &Long jump + + + + + Mouse &wheel jump + + + + + &Use only one running instance of SMPlayer + + + + + Ma&x. items + + + + + St&yle: + + + + + Ico&n set: + + + + + L&anguage: + + + + + Main window + + + + + Auto&resize: + + + + + R&emember position and size + + + + + Default font: + + + + + &Change... + + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + + + + + &Seeking + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Performance + + + + &Performance + + + + + Priority + Prioridade + + + + Select the priority for the MPlayer process. + Selecionar a prioridade para o processo do MPlayer. + + + + realtime + tempo real + + + + high + alto + + + + abovenormal + acima do normal + + + + normal + normal + + + + belownormal + abaixo do normal + + + + idle + baixo + + + + Cache + Cachê + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Selecionando um cache pode melhorar a performance em mídia lenta + + + + Allow frame drop + Permitir eliminação de quadros + + + + Synchronization + Sincronização + + + + Audio/video auto synchronization + Sincronização de áudio/vídeo automática + + + + Fast audio track switching + Troca de trilha de áudio rápida + + + + Fast seek to chapters in dvds + Busca rápida de capítulos em DVDs + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Definir a prioridade do processo do mplayer de acordo com as prioridades definidas pelo Windows.<br><b>AVISO:</b> Usar prioridade tempo real pode causar o travamento do sistema. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Descartar a exibição de alguns quadros para manter a sincronia A/V em sistemas lentos. + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Descarte de quadros mais intenso (quebra decodificação). Pode gerar distorção da imagem! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Gradualmente ajusta o sincronismo A/V baseado na medida de atraso de áudios. + + + + Priorit&y: + + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + + + + + Fact&or: + + + + + &Fast audio track switching + + + + + Fast &seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + + + + + Cache for &DVDs: + + + + + Cache for &local files: + + + + + Cache for &streams: + + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Lista de reprodução + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Legendas + + + + Choose a ttf file + Escolha um arquivo ttf + + + + Truetype Fonts + Fontes TrueType + + + + &Subtitles + &Legendas + + + + Autoload + Autocarregar + + + + Select first available subtitle + Selecione a primeira legenda disponível + + + + Same name as movie + O mesmo nome do filme + + + + All subs containing movie name + Todos as legendas contendo o nome do filme + + + + All subs in directory + Todas as legendas no diretório + + + + Position + Posição + + + + 0 + 0 + + + + Top + Acima + + + + Bottom + Abaixo + + + + Include subtitles on screenshots + Incluir legendas nos screenshots + + + + Font + Fontes + + + + Select the font which will be used for subtitles (and OSD): + Selecione qual fonte será usada nas legendas (e OSD): + + + + Size + Tamanho + + + + No autoscale + Sem autoescala + + + + Proportional to movie height + Proporcional à altura do filme + + + + Proportional to movie width + Proporcional à largura do filme + + + + Proportional to movie diagonal + Proporcional ao tamanho da diagonal + + + + Subtitle position + + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Esta opção especifica a posição das legendas sobre a janela de vídeo. <i>100</i> significa a parte de baixo, enquanto <i>0</i> significa a parte de cima. + + + + Au&toload subtitles files (*.srt, *.sub...): + + + + + S&elect first available subtitle + + + + + &Default subtitle encoding: + + + + + Default &position of the subtitles on screen + + + + + &Include subtitles on screenshots + + + + + &TTF font: + + + + + S&ystem font: + + + + + A&utoscale: + + + + + Default subtitle encoding + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + + + + + Middle + vertical alignment + + + + + Top + vertical alignment + + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + + + + + OK + + + + + Cancel + + + + + Apply + + + + + Help + + + + + SMPlayer - Preferences + SMPlayer - Preferências + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + + the main window won't be closed when the file/playlist finishes. + + + + + the video will be played in fullscreen mode. + + + + + the video will be played in window mode. + + + + + Enqueue in SMPlayer + + + + + opens the mini gui instead of the default one. + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + Usage: + + + + + directory + + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + icone + + + + label + rótulo + + + + ShortcutGetter + + + Modify shortcut + + + + + Clear + + + + + Press the key combination you want to assign + + + + + Capture + + + + + Capture keystrokes + + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + + + + + Select None + + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + + + + + Yes + + + + + No + + + + + VideoEqualizer + + + Contrast + Contraste + + + + Brightness + Brilho + + + + Hue + Matiz + + + + Saturation + Saturação + + + + Gamma + Gamma + + + + &Reset + &Resetar + + + + &Set as default values + Definir como valor &padrão + + + + Use the current values as default values for new videos. + Usar os valores atuais como padrão para novos vídeos. + + + + Set all controls to zero. + Definir todos os controles como zero. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Erro ao gravar o arquivo + + + + The file couldn't be saved + O arquivo não pode ser salvo + + + + Error + Erro + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Volume + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_pt_PT.ts b/plugins/smplayer_plugin/translations/smplayer_pt_PT.ts new file mode 100644 index 000000000..badbb8152 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_pt_PT.ts @@ -0,0 +1,7383 @@ + + + + About + + + Version: %1 + Versão: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Este programa é um software livre; pode ser distribuido e/ou modificado sob os termos da GNU General Public License conforme publicada pela Free Software Foundation; tanto na versão 2 ou , em alternativa, qualquer uma mais recente. + + + + The following people have contributed with translations: + As seguintes pessoas contribuiram com traduções: + + + + German + Alemão + + + + Slovak + Eslovaco + + + + Italian + Italiano + + + + French + Francês + + + + %1, %2 and %3 + %1, %2 e %3 + + + + Simplified-Chinese + Chinês Simplificado + + + + Russian + Russo + + + + %1 and %2 + %1 e %2 + + + + Hungarian + Húngaro + + + + Polish + Polaco + + + + Japanese + Japonês + + + + Dutch + Holandês + + + + Ukrainian + Ucraniano + + + + Portuguese - Brazil + Português - Brasil + + + + Georgian + Georgiano + + + + Czech + Checo + + + + Bulgarian + Búlgaro + + + + Turkish + Turco + + + + Swedish + Sueco + + + + Serbian + Sérvio + + + + Traditional Chinese + Chinês Tradicional + + + + Romanian + Romeno + + + + Portuguese - Portugal + Português - Portugal + + + + Greek + Grego + + + + Finnish + Finlândes + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Sobre SMPlayer + + + + &Info + &Info + + + + icon + ícone + + + + &Contributions + &Contribuições + + + + &Translators + &Tradutores + + + + &License + &Licença + + + + Visit our web for updates: + Visite a web para actualizações: + + + + Get help in our forum: + Obtenha ajuda no forum: + + + + You can support SMPlayer by making a donation. + Pode ajudar no desenvolvimento do SMPlayer fazendo uma doação. + + + + More info + Mais informação + + + + Korean + Coreano + + + + Macedonian + Macedónio + + + + Basque + Basco + + + + Using MPlayer %1 + Usando MPlayer %1 + + + + Catalan + Catalão + + + + Portable Edition + Edição Portátil + + + + Using Qt %1 (compiled with Qt %2) + Usando Qt %1 (compilado com Qt %2) + + + + Slovenian + Esloveno + + + + Arabic + Árabe + + + + Kurdish + Curdo + + + + Galician + Galego + + + + The following people have contributed with patches (see the changelog for details): + As seguintes pessoas contribuiram com correcções (veja o changelog para detalhes): + + + + If there's any omission, please report. + Se encontrar alguma omissão, reporte-a. + + + + SMPlayer logo by %1 + Logo SMPlayer de %1 + + + + %1, %2, %3 and %4 + %1, %2, %3 e %4 + + + + %1, %2, %3, %4 and %5 + %1, %2, %3, %4 e %5 + + + + ActionsEditor + + + Name + Nome + + + + Description + Descrição + + + + Shortcut + Atalho + + + + &Save + &Gravar + + + + &Load + &Carregar + + + + Key files + Ficheiros de atalhos + + + + Choose a filename + Escolha o nome do ficheiro + + + + Confirm overwrite? + Confirma substituição? + + + + The file %1 already exists. +Do you want to overwrite? + O ficheiro %1 já existe. +Deseja substituí-lo? + + + + Choose a file + Escolha um ficheiro + + + + Error + Erro + + + + The file couldn't be saved + O ficheiro não pôde ser gravado + + + + The file couldn't be loaded + O ficheiro não pôde ser carregado + + + + &Change shortcut... + &Alterar atalho... + + + + AudioEqualizer + + + Audio Equalizer + Equalizador Áudio + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Aplicar + + + + &Reset + &Repor + + + + &Set as default values + &Definir como valores padrão + + + + Use the current values as default values for new videos. + Usar os valores actuais como padrão para os novos vídeos. + + + + Set all controls to zero. + Definir todos os controles a zero. + + + + Information + Informações + + + + The current values have been stored to be used as default. + Os valores actuais foram guardados para serem usados como padrão. + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer log + + + + SMPlayer - smplayer log + SMPlayer - smplayer log + + + + &Open + A&brir + + + + &Play + Re&produzir + + + + &Video + &Vídeo + + + + &Audio + &Áudio + + + + &Subtitles + Legenda&s + + + + &Browse + &Navegar + + + + Op&tions + &Opções + + + + &Help + &Ajuda + + + + &File... + &Ficheiro... + + + + D&irectory... + D&irectório... + + + + &Playlist... + &Lista de reprodução... + + + + &DVD from drive + &DVD a partir do leitor + + + + D&VD from folder... + D&VD a partir de uma pasta... + + + + &URL... + &URL... + + + + &Clear + &Limpar + + + + &Recent files + Ficheiros &recentes + + + + P&lay + &Reproduzir + + + + &Pause + &Pausa + + + + &Stop + &Stop + + + + &Frame step + &Avançar frame + + + + &Normal speed + Velocidade &normal + + + + &Halve speed + &Reduzir a metade + + + + &Double speed + &Dobro da velocidade + + + + Speed &-10% + Velocidade &-10% + + + + Speed &+10% + Velocidade &+10% + + + + Sp&eed + &Velocidade + + + + &Repeat + R&epetir + + + + &Fullscreen + &Ecrã Completo + + + + &Compact mode + &Modo compacto + + + + Si&ze + &Tamanho + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &a 16:9 + + + + &Aspect ratio + Tamanho do &Vídeo + + + + &None + &Nenhum + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + &Mistura Linear + + + + &Deinterlace + &Desentrelaçar + + + + &Postprocessing + &Pós-processamento + + + + &Autodetect phase + &Auto detecção de fase + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + Adicionar r&uído + + + + F&ilters + &Filtros + + + + &Equalizer + &Equalizador + + + + &Screenshot + &Captura + + + + S&tay on top + &Manter em cima + + + + &Extrastereo + &Extraestéreo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtros + + + + &Stereo + E&stéreo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Canais + + + + &Left channel + Canal &esquerdo + + + + &Right channel + Canal &direito + + + + &Stereo mode + &Modo estéreo + + + + &Mute + &Silenciar + + + + Volume &- + Volume &- + + + + Volume &+ + Volume &+ + + + + &Delay - + &Atraso - + + + + D&elay + + A&traso + + + + + &Select + &Seleccionar + + + + &Load... + &Carregar... + + + + Delay &- + Atraso &- + + + + Delay &+ + Atraso &+ + + + + &Up + &Para cima + + + + &Down + P&ara baixo + + + + &Title + &Título + + + + &Chapter + &Capítulo + + + + &Angle + &Ângulo + + + + &Playlist + &Lista de reprodução + + + + &Show frame counter + &Mostrar contador de frames + + + + &Disabled + &Desactivado + + + + &Seek bar + &Barra de procura + + + + &Time + &Tempo + + + + Time + T&otal time + Tempo + Tempo t&otal + + + + &OSD + &OSD + + + + &View logs + &Ver logs + + + + P&references + P&referências + + + + About &Qt + Sobre &Qt + + + + About &SMPlayer + Sobre &SMPlayer + + + + <empty> + <vazio> + + + + Video + Vídeo + + + + Audio + Áudio + + + + Playlists + Listas de reprodução + + + + All files + Todos os ficheiros + + + + Choose a file + Escolha um ficheiro + + + + SMPlayer - Information + SMPlayer - Informação + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + As unidades de CDROM / DVD ainda não foram configuradas. +O diálogo de configuração irá ser mostrado agora, para que o possa fazer. + + + + Choose a directory + Escolha um directório + + + + Subtitles + Legendas + + + + About Qt + Sobre Qt + + + + Playing %1 + Reproduzindo %1 + + + + Pause + Pausa + + + + Stop + Stop + + + + Play / Pause + Reproduzir / Pausa + + + + Pause / Frame step + Pausa / Avançar frame + + + + U&nload + &Descarregar + + + + V&CD + V&CD + + + + C&lose + F&echar + + + + View &info and properties... + Ver &informação e propriedades... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Repor + + + + Move &left + Mover para a &esquerda + + + + Move &right + Mover para a &direita + + + + Move &up + Mover para &cima + + + + Move &down + Mover para &baixo + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Linha anterior + + + + N&ext line in subtitles + L&inha seguinte + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Diminuir volume (2) + + + + Inc volume (2) + Aumentar volume (2) + + + + Exit fullscreen + Sair do Modo de Ecrã Completo + + + + OSD - Next level + OSD - Próximo Nível + + + + Dec contrast + Diminuir contraste + + + + Inc contrast + Aumentar contraste + + + + Dec brightness + Diminuir brilho + + + + Inc brightness + Aumentar brilho + + + + Dec hue + Diminuir tonalidade + + + + Inc hue + Aumentar tonalidade + + + + Dec saturation + Diminuir saturação + + + + Dec gamma + Diminuir gamma + + + + Next audio + Áudio seguinte + + + + Next subtitle + Legenda seguinte + + + + Next chapter + Capítulo seguinte + + + + Previous chapter + Capítulo anterior + + + + Inc saturation + Aumentar saturação + + + + Inc gamma + Aumentar gamma + + + + &Load external file... + Carregar ficheiro e&xterno... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normal) + + + + Y&adif (double framerate) + Y&adif (double framerate) + + + + &Next + &Próximo + + + + Pre&vious + &Anterior + + + + Volume &normalization + &Normalização de volume + + + + &Audio CD + CD &Áudio + + + + Denoise nor&mal + Reduzir ruído nor&mal + + + + Denoise &soft + Reduzir ruído &suavemente + + + + Denoise o&ff + Reduzir ruído - &Desligado + + + + Use SSA/&ASS library + Usar bibliotecas SSA/&ASS + + + + Flip i&mage + Inverter i&magem + + + + &Toggle double size + Articular &Tamanho duplo + + + + S&ize - + Tamanho (&-) + + + + Si&ze + + Tamanho (&+) + + + + Add &black borders + Adicionar &contornos negros + + + + Soft&ware scaling + Dimensionamento de soft&ware + + + + &FAQ + &FAQ + + + + Visualize &motion vectors + Visualizar vectores de ani&mação + + + + &Command line options + Opções de linha de &comandos + + + + SMPlayer command line options + Opções da linha de comandos do SMPlayer + + + + Enable &closed caption + Activar legenda fe&chada + + + + &Forced subtitles only + &Forçar apenas legendas + + + + Reset video equalizer + Repor equalizador vídeo + + + + MPlayer has finished unexpectedly. + MPlayer terminou abruptamente. + + + + Exit code: %1 + Código de saída: %1 + + + + MPlayer failed to start. + Falha ao iniciar MPlayer. + + + + Please check the MPlayer path in preferences. + Por favor verifique o caminho do MPlayer em Preferências. + + + + MPlayer has crashed. + MPlayer crashou. + + + + See the log for more info. + Veja o log para mais informações. + + + + &Rotate + &Rodar + + + + &Off + Desligad&o + + + + &Rotate by 90 degrees clockwise and flip + &Rodar 90º no sentido horário e inverter + + + + Rotate by 90 degrees &clockwise + &Rodar 90º no sentido horário + + + + Rotate by 90 degrees counterclock&wise + Rodar 90º no sentido &anti-horário + + + + Rotate by 90 degrees counterclockwise and &flip + Rodar 90º no sentido anti-horário e inver&ter + + + + &Jump to... + &Ir para... + + + + Show context menu + Mostrar menu de contexto + + + + Multimedia + Multimedia + + + + E&qualizer + E&qualizador + + + + Reset audio equalizer + Repor equalizador áudio + + + + Find subtitles on &OpenSubtitles.org... + Encontrar legendas em &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Enviar le&gendas para &OpenSubtitles.org... + + + + &Tips + &Dicas + + + + &Auto + &Auto + + + + Speed -&4% + Velocidade -&4% + + + + &Speed +4% + Velocidade -&4% + + + + Speed -&1% + Velocidade -&4% + + + + S&peed +1% + Velocidade -&4% + + + + Scree&n + E&crã + + + + &Default + &Padrão + + + + Mirr&or image + Mirr&or + + + + Next video + Próximo vídeo + + + + &Track + video + &Faixa + + + + &Track + audio + &Faixa + + + + Warning - Using old MPlayer + Aviso - Usando MPlayer antigo + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + A versão MPlayer (%1) instalada no sistema é obsoleta. SMPlayer não funcionará correctamente: algumas opções não funcionam, legendas podem falhar... + + + + Please, update your MPlayer. + Por favor actualiza o MPlayer. + + + + (This warning won't be displayed anymore) + (Este aviso não será apresentado novamente) + + + + Next aspect ratio + Próximo tamanho de vídeo + + + + &Auto zoom + &Auto zoom + + + + Auto zoom for &16:9 + Auto zoom para &16:9 + + + + Auto zoom for &2.35:1 + Auto zoom para&2.35:1 + + + + Zoom for &16:9 + Zoom para &16:9 + + + + Zoom for &2.35:1 + Zoom para&2.35:1 + + + + Pre&view... + Pré-&visualizar... + + + + &Always + &Sempre + + + + &Never + &Nunca + + + + While &playing + Ao re&produzir + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer ainda está em execução + + + + S&how icon in system tray + &Mostrar ícone na área de notificação + + + + &Hide + &Ocultar + + + + &Restore + &Restaurar + + + + &Quit + &Sair + + + + Playlist + Lista de reprodução + + + + Core + + + Brightness: %1 + Brilho: %1 + + + + Contrast: %1 + Contraste: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Tonalidade: %1 + + + + Saturation: %1 + Saturação: %1 + + + + Volume: %1 + Volume: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + Escala de fontes:%1 + + + + Aspect ratio: %1 + Tamanho de vídeo : %1 + + + + Updating the font cache. This may take some seconds... + Actualizando cache de fontes. Pode demorar alguns segundos... + + + + DefaultGui + + + Welcome to SMPlayer + Bem-Vindo ao SMPlayer + + + + Audio + Áudio + + + + Subtitle + Legenda + + + + &Main toolbar + Barra &principal + + + + &Language toolbar + Barra de &idioma + + + + &Toolbars + &Barras de ferramentas + + + + EqSlider + + + icon + ícone + + + + ErrorDialog + + + Hide log + Ocultar log + + + + Show log + Mostrar log + + + + MPlayer Error + Erro de Mplayer + + + + icon + ícone + + + + Error + Erro + + + + FileDownloader + + + Downloading... + Transferindo... + + + + Downloading %1 + Transferindo %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Propriedades do ficheiro + + + + &Information + &Informação + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Seleccione o demuxer a ser utilizado neste ficheiro: + + + + &Reset + &Repor + + + + &Video codec + Codec de &vídeo + + + + &Select the video codec: + &Seleccione o codec de vídeo: + + + + A&udio codec + Codec de á&udio + + + + &Select the audio codec: + &Seleccione o codec de áudio: + + + + &MPlayer options + Opções do &MPlayer + + + + Additional Options for MPlayer + Opções Adicionais para o MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aqui pode passar opções extra ao MPlayer. +Deve escrevê-las separadas por espaços. +Exemplo: -flip -nosound + + + + &Options: + &Opções: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Também pode passar filtros de vídeo adicionais. +Separe-os com ",". Não utilizar espaços! +Exemplo: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + Filtros de v&ídeo: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + E finalmente os filtros de áudio. Mesma regra utilizada nos filtros de vídeo. +Exemplo: resample=44100:0:0,volnorm + + + + Audio &filters: + &Filtros de áudio: + + + + OK + OK + + + + Cancel + Cancelar + + + + Apply + Aplicar + + + + FindSubtitlesWindow + + + Language + Idioma + + + + Name + Nome + + + + Format + Formato + + + + Files + Ficheiros + + + + Date + Data + + + + Uploaded by + Enviado por + + + + All + Todos + + + + Close + Fechar + + + + &Download + &Transferência + + + + &Copy link to clipboard + &Copiar ligação para Área de Transferência + + + + Error + Erro + + + + Download failed: %1. + Transferência falhada:%1. + + + + Connecting to %1... + Ligando a %1... + + + + Downloading... + Transferindo... + + + + Done. + Feito. + + + + %1 files available + %1 ficheiro disponível + + + + Failed to parse the received data. + Falha ao analisar os dados recebidos. + + + + Find Subtitles + Encontrar Legendas + + + + &Subtitles for + &Legendas para + + + + &Language: + &Idioma: + + + + &Refresh + &Refrescar + + + + Subtitle saved as %1 + Legenda gravada como %1 + + + + %1 subtitle(s) extracted + + %1 legenda extraída + %1 legendas extraídas + + + + + Overwrite? + Substituir? + + + + The file %1 already exits, overwrite? + O ficheiro %1 já existe, substituir? + + + + Error saving file + Erro ao gravar o ficheiro + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Não foi possível gravar o ficheiro transferido +na pasta %1 +Verifique as permissões de escrita da pasta. + + + + Download failed + Falha ao transferir + + + + Temporary file %1 + Ficheiro temporário %1 + + + + InfoFile + + + General + Geral + + + + Size + Tamanho + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Duração + + + + Demuxer + Demuxer + + + + Name + Nome + + + + Artist + Artista + + + + Author + Autor + + + + Album + Álbum + + + + Genre + Género + + + + Date + Data + + + + Track + Faixa + + + + Copyright + Copyright + + + + Comment + Comentário + + + + Software + Software + + + + Clip info + Informação do clip + + + + Video + Vídeo + + + + Resolution + Resolução + + + + Aspect ratio + Tamanho do Vídeo + + + + Format + Formato + + + + Bitrate + Taxa de bits + + + + %1 kbps + %1 kbps + + + + Frames per second + Frames por segundo + + + + Selected codec + Codec seleccionado + + + + Initial Audio Stream + Faixa de áudio inicial + + + + Rate + Taxa + + + + %1 Hz + %1 Hz + + + + Channels + Canais + + + + Audio Streams + Faixas de áudio + + + + Language + Idioma + + + + empty + vazio + + + + Subtitles + Legendas + + + + Type + Tipo + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Título do Stream + + + + Stream URL + URL do Stream + + + + File + Ficheiro + + + + InputDVDDirectory + + + Choose a directory + Escolha um directório + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Reproduzir um DVD a partir de uma pasta + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Pode reproduzir um dvd a partir do seu disco rígido. Simplemente seleccione a pasta que contém os directórios VIDEO_TS e AUDIO_TS. + + + + Choose a directory... + Escolha um directório... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Introduza a versão do MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + O SMPlayer não conseguiu identificar a versão do MPlayer. + + + + Version reported by MPlayer: + Versão relatada por MPlayer: + + + + Please, &select the correct version: + Por favor, &seleccione a versão correcta: + + + + 1.0rc1 or older + 1.0rc1 ou mais recente + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Superior à 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Introduza URL + + + + &URL: + &URL: + + + + It's a &playlist + É uma lista de re&produção + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Se esta opção estiver seleccionada, a URL será tratada como uma lista de reprodução: será aberta como texto e irá tocar as URLs existentes. + + + + Languages + + + Afar + Afar + + + + Abkhazian + Abkhazian + + + + Afrikaans + Africano + + + + Amharic + Amharic + + + + Arabic + Árabe + + + + Assamese + Assamese + + + + Aymara + Aymara + + + + Azerbaijani + Azerbaijani + + + + Bashkir + Bashkir + + + + Byelorussian + Bielorusso + + + + Bulgarian + Búlgaro + + + + Bihari + Bihari + + + + Bislama + Bislama + + + + Bengali + Bengali + + + + Tibetan + Tibetano + + + + Breton + Breton + + + + Catalan + Catalão + + + + Corsican + Corsican + + + + Czech + Checo + + + + Welsh + Galês + + + + Danish + Dinamarquês + + + + German + Alemão + + + + Bhutani + Bhutani + + + + Greek + Grego + + + + English + Inglês + + + + Esperanto + Esperanto + + + + Spanish + Espanhol + + + + Estonian + Estónio + + + + Basque + Basco + + + + Persian + Persa + + + + Finnish + Finlândes + + + + Fiji + Fiji + + + + Faroese + Faroese + + + + French + Francês + + + + Frisian + Frisian + + + + Irish + Irlândes + + + + Scots + Scots + + + + Galician + Galego + + + + Guarani + Guarani + + + + Gujarati + Gujarati + + + + Hausa + Hausa + + + + Hebrew + Hebreu + + + + Hindi + Hindi + + + + Croatian + Croata + + + + Hungarian + Húngaro + + + + Armenian + Armeniano + + + + Interlingua + Interlingua + + + + Indonesian + Indonês + + + + Interlingue + Interlingue + + + + Inupiak + Inupiak + + + + Icelandic + Islândes + + + + Italian + Italiano + + + + Inuktitut + Inuktitut + + + + Japanese + Japonês + + + + Javanese + Javanese + + + + Georgian + Georgiano + + + + Kazakh + Kazakh + + + + Greenlandic + Greenlandic + + + + Cambodian + Cambodjano + + + + Kannada + Canadiano + + + + Korean + Coreano + + + + Kashmiri + Kashmiri + + + + Kurdish + Curdo + + + + Kirghiz + Kirghiz + + + + Latin + Latino + + + + Lingala + Lingala + + + + Laothian + Laothian + + + + Lithuanian + Lituano + + + + Latvian + Letão + + + + Malagasy + Malagasy + + + + Maori + Maori + + + + Macedonian + Macedónio + + + + Malayalam + Malayalam + + + + Mongolian + Mongolês + + + + Moldavian + Moldavo + + + + Marathi + Marathi + + + + Malay + Malay + + + + Maltese + Maltês + + + + Burmese + Burmese + + + + Nauru + Nauru + + + + Nepali + Nepalês + + + + Dutch + Holandês + + + + Norwegian + Norueguês + + + + Occitan + Occitan + + + + Oriya + Oriya + + + + Punjabi + Punjabi + + + + Polish + Polaco + + + + Pashto + Pashto + + + + Portuguese + Português + + + + Quechua + Quechua + + + + Kirundi + Kirundi + + + + Romanian + Romeno + + + + Russian + Russo + + + + Kinyarwanda + Kinyarwanda + + + + Sanskrit + Sanskrit + + + + Sindhi + Sindhi + + + + Sangho + Sangho + + + + Sinhalese + Sangho + + + + Slovak + Eslovaco + + + + Slovenian + Esloveno + + + + Samoan + Samoano + + + + Shona + Shona + + + + Somali + Somali + + + + Albanian + Albanês + + + + Serbian + Sérvio + + + + Siswati + Siswati + + + + Sesotho + Sesotho + + + + Sundanese + Sundanese + + + + Swedish + Sueco + + + + Swahili + Swahili + + + + Tamil + Tamil + + + + Telugu + Telugu + + + + Tajik + Tajik + + + + Thai + Thai + + + + Tigrinya + Tigrinya + + + + Turkmen + Turkmen + + + + Tagalog + Tagalog + + + + Setswana + Setswana + + + + Tonga + Tonga + + + + Turkish + Turco + + + + Tsonga + Tsonga + + + + Tatar + Tatar + + + + Twi + Twi + + + + Uighur + Uighur + + + + Ukrainian + Ucraniano + + + + Urdu + Urdu + + + + Uzbek + Uzbek + + + + Vietnamese + Vietnamita + + + + Wolof + Wolof + + + + Xhosa + Xhosa + + + + Yiddish + Yiddish + + + + Yoruba + Yoruba + + + + Zhuang + Zhuang + + + + Chinese + Chinês + + + + Zulu + Zulu + + + + Portuguese - Brazil + Português - Brasil + + + + Portuguese - Portugal + Português - Portugal + + + + Simplified-Chinese + Chinês Simplificado + + + + Traditional Chinese + Chinês Tradicional + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + Ocidental + + + + Western European Languages with Euro + Ocidental com euro + + + + Slavic/Central European Languages + Eslavo/Centro-Europeu + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galego, Maltês, Turco + + + + Old Baltic charset + Báltico antigo + + + + Cyrillic + Cirílico + + + + Modern Greek + Grego moderno + + + + Baltic + Báltico + + + + Celtic + Céltico + + + + Hebrew charsets + Hebreu + + + + Ukrainian, Belarusian + Ucraniano, Bielo-Russo + + + + Simplified Chinese charset + Chinês simplificado + + + + Traditional Chinese charset + Chinês tradicional + + + + Japanese charsets + Japonês + + + + Korean charset + Coreano + + + + Thai charset + Thai + + + + Cyrillic Windows + Windows cirílico + + + + Slavic/Central European Windows + Eslavo/Centro-Europeu Windows + + + + Arabic Windows + Windows Arábico + + + + Rhaeto-Romance + Rhaeto-Romance + + + + Serbo-Croatian + Sérvio-Croata + + + + Volapük + Volapük + + + + Avestan + Avestan + + + + Akan + Akan + + + + Aragonese + Aragonese + + + + Avaric + Avaric + + + + Belarusian + Bielorusso + + + + Bambara + Bambara + + + + Bosnian + Bósnio + + + + Chechen + Tcheceno + + + + Cree + Cree + + + + Church + Church + + + + Chuvash + Chuvash + + + + Divehi + Divehi + + + + Dzongkha + Dzongkha + + + + Ewe + Ewe + + + + Fulah + Fulah + + + + Fijian + Fijian + + + + Gaelic + Gaélico + + + + Manx + Manx + + + + Hiri + Hiri + + + + Haitian + Haitiano + + + + Herero + Herero + + + + Chamorro + Chamorro + + + + Igbo + Igbo + + + + Sichuan + Sichuan + + + + Inupiaq + Inupiaq + + + + Ido + Ido + + + + Kongo + Kongo + + + + Kikuyu + Kikuyu + + + + Kuanyama + Kuanyama + + + + Khmer + Khmer + + + + Kanuri + Kanuri + + + + Komi + Komi + + + + Cornish + Cornish + + + + Luxembourgish + Luxembourgish + + + + Ganda + Ganda + + + + Limburgan + Limburgan + + + + Lao + Lao + + + + Luba-Katanga + Luba-Katanga + + + + Marshallese + Marshallese + + + + Bokmål + Bokmål + + + + Ndebele + Ndebele + + + + Ndonga + Ndonga + + + + Navajo + Navajo + + + + Chichewa + Chichewa + + + + Ojibwa + Ojibwa + + + + Oromo + Oromo + + + + Ossetian + Ossetian + + + + Panjabi + Panjabi + + + + Pali + Pali + + + + Pushto + Pushto + + + + Romansh + Romansh + + + + Rundi + Rundi + + + + Sardinian + Sardinian + + + + Sami + Sami + + + + Sango + Sango + + + + Sinhala + Sinhala + + + + Swati + Swati + + + + Sotho + Sotho + + + + Tswana + Tswana + + + + Tahitian + Tahitian + + + + Venda + Venda + + + + Volapük + Volapük + + + + Walloon + Walloon + + + + LogWindow + + + Choose a filename to save under + Escolha o nome do ficheiro + + + + Confirm overwrite? + Confirma substituição? + + + + The file already exists. +Do you want to overwrite? + O ficheiro já existe. +Deseja substituí-lo? + + + + Error saving file + Erro ao gravar o ficheiro + + + + The log couldn't be saved + Não foi possível gravar o log + + + + Logs + Logs + + + + LogWindowBase + + + Log Window + Janela de Log + + + + Save + Gravar + + + + Copy to clipboard + Copiar para a área de transferência + + + + Close + Fechar + + + + &Close + &Fechar + + + + MiniGui + + + Control bar + Barra de controle + + + + MpcGui + + + Control bar + Barra de controlo + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nome + + + + Length + Duração + + + + &Play + &Reproduzir + + + + &Edit + &Editar + + + + Playlists + Listas de reprodução + + + + Choose a file + Escolha um ficheiro + + + + Choose a filename + Escolha um nome de ficheiro + + + + Confirm overwrite? + Confirma substituição? + + + + The file %1 already exists. +Do you want to overwrite? + O ficheiro %1 já existe. +Deseja substituí-lo? + + + + All files + Todos os ficheiros + + + + Select one or more files to open + Seleccione um ou mais ficheiros a abrir + + + + Choose a directory + Escolha um directório + + + + Edit name + Editar nome + + + + Type the name that will be displayed in the playlist for this file: + Escreva o nome que este ficheiro irá ter na lista de reprodução: + + + + &Load + &Carregar + + + + &Save + &Gravar + + + + &Next + &Próximo + + + + Pre&vious + &Anterior + + + + Move &up + Para &cima + + + + Move &down + Para &baixo + + + + &Repeat + &Repetir + + + + S&huffle + A&leatório + + + + Add &current file + Adicionar ficheiro a&ctual + + + + Add &file(s) + Adicionar &ficheiro(s) + + + + Add &directory + Adicionar &directório + + + + Remove &selected + Remover &selecção + + + + Remove &all + Remover &tudo + + + + SMPlayer - Playlist + SMPlayer - Lista de reprodução + + + + Add... + Adicionar... + + + + Remove... + Remover... + + + + Playlist modified + Lista de reprodução modificada + + + + There are unsaved changes, do you want to save the playlist? + Existem alterações não guardadas, deseja gravar a lista de reprodução? + + + + Preferences + Preferências + + + + PlaylistPreferences + + + Playlist - Preferences + Lista de reprodução - Preferências + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Seleccione esta opção se pretende adicionar um directório e sub directórios serão também adicionados). Caso contrário,apenas os ficheiros do directório principal serão adicionados. + + + + &Add files in directories recursively + &Adicionar ficheiros dos directórios + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Seleccione esta opção para adicionar à lista de reprodução as informações constantes do ficheiro. Isto permiter-lhe-á mostrar o título (se existente) e a duração dos ficheiros. Caso contrário, esta informação não estará disponível. Tenha em conta que esta operação pode ser demorada, principalmente se adicionar muitos ficheiros. + + + + Automatically get &info about files added + Obter automaticamente &informações sobre os ficheiros adicionados + + + + &Save copy of playlist on exit + &Gravar cópia da lista de reprodução ao sair + + + + &Play files from start + Reproduzir ficheiros do &Início + + + + PrefAdvanced + + + Advanced + Avançado + + + + Auto + Automático + + + + &Advanced + &Avançado + + + + icon + ícone + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aqui pode passar opções extra ao MPlayer. +Escrevê-las separadas por espaços. +Exemplo: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Também pode passar filtros de vídeo adicionais. +Separe-os com ",". Não utilizar espaços! +Exemplo: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + E finalmente os filtros de áudio. Mesma regra utilizada nos filtros de vídeo. +Exemplo: resample=44100:0:0,volnorm + + + + Log MPlayer output + Gravar logs de saída do MPlayer + + + + Log SMPlayer output + Guardar os logs de saída do SMPlayer + + + + This option is mainly intended for debugging the application. + Esta opção é principalmente para depurar (debugging) a aplicação. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Seleccionando esta opção pode reduzir a cintilação, mas também pode fazer com que o vídeo não seja mostrado correctamente. + + + + Filter for SMPlayer logs + Filtro para os logs do SMPlayer + + + + &Monitor aspect: + Aspecto do &Monitor: + + + + &Run MPlayer in its own window + Executa&r o MPlayer na sua janela + + + + &Options: + &Opções: + + + + V&ideo filters: + Filtros de víd&eo: + + + + Audio &filters: + &Filtros de áudio: + + + + &Colorkey: + &Conjunto de cores: + + + + Log &SMPlayer output + Guardar os logs de saída do &SMPlayer + + + + &Filter for SMPlayer logs: + &Filtro para os logs do SMPlayer: + + + + C&hange... + Al&terar... + + + + Logs + Logs + + + + Log MPlayer &output + Guardar os l&ogs de saída do MPlayer + + + + Options for MP&layer + Opções do MP&layer + + + + Autosave MPlayer log + Gravar automaticamente logs do Mplayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Se esta opção for estiver seleccionada, os logs do MPlayer serão gravados no ficheiro especificado de cada vez que um novo ficheiro seja reproduzido. Servirá para aplicações externas obterem informações sobre o ficheiro reproduzido. + + + + Autosave MPlayer log filename + Gravar automaticamente logs do Mplayer + + + + Enter here the path and filename that will be used to save the MPlayer log. + Introduza aqui o caminho e o nome do ficheiro para gravar logs do MPlayer. + + + + A&utosave MPlayer log to file + Gravar logs a&utomaticamente para o ficheiro + + + + Pass short filenames (8+3) to MPlayer + Passar nome de ficheiros curtos (8+3) para o MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Actualmente o MPlayer não abre ficheiros que contenham caracteres fora do código local. Ao seleccionar esta opção fará com que o SMPlayer direccione para o MPlayer uma versão abreviada dos ficheiros e assim já os conseguirá abrir. + + + + &Pass short filenames (8+3) to MPlayer + &Passar nome de ficheiros curtos (8+3) para o MPlayer + + + + Monitor aspect + Aspecto do Monitor + + + + Select the aspect ratio of your monitor. + Seleccione o rácio do seu monitor. + + + + Run MPlayer in its own window + Executar o MPlayer na sua janela + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Seleccionando esta opção,a janela do MPlayer não será integrada na janela principal do SMPlayer mas sim na sua própria. Note que o rato e o teclado serão geridos directamente pelo MPlayer, o que significa que as teclas de atalho não deverão funcionar correctamente. + + + + Colorkey + Conjunto de cores + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Se verificar que existem partes do vídeo noutra janela, pode modificar o conjunto de cores para reparar. Tente uma cor próxima de preto. + + + + Options for MPlayer + Opções do MPlayer + + + + Options + Opções + + + + Here you can type options for MPlayer. Write them separated by spaces. + Aqui pode digitar opções para o MPlayer. Escreva-as separadas por espaços. + + + + Video filters + Filtros de vídeo + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Aqui pode adicionar filtros vídeo para o MPlayer.Escreva-as separadas por vírgulas. Não use espaços! + + + + Audio filters + Filtros de áudio + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Aqui pode adicionar filtros áudio para o MPlayer.Escreva-as separadas por vírgulas. Não use espaços! + + + + Repaint the background of the video window + Redesenhar o fundo da janela de vídeo + + + + Repaint the backgroun&d of the video window + Redesenhar o fun&do da janela de vídeo + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Usar IPv4 nas ligações de rede. Retorna a IPv6 automaticamente. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Usar IPv6 nas ligações de rede. Retorna a IPv4 automaticamente. + + + + Network Connection + Ligação à Rede + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + Lo&gs + + + + Rebuild index if needed + Reconstruir índice, se necessário + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Reconstrói índice de ficheiros se nenhum índice for encontrado, permitindo procura. Útil com transferências corrompidas/incompletas ou ficheiros mal criados. Esta opção só funciona se o vídeo subjacente suportar busca (i.e., não com stdin, pipe, etc.). <br> Nota: a criação do índice pode levar algum tempo. + + + + Rebuild &index if needed + Reconstruir índ&ice, se necessário + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Se esta opção estiver seleccionada, o SMPlayer irá guardar as mensagens de depuração que o software emite (pode visualizar o log em <b>Opções->Ver logs->SMPlayer</b>). Esta informação poderá ser útil para o programador no caso de encontrar um problema. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Se seleccionada, o SMPlayer irá guardar a informação de saída do MPlayer (pode visualizá-la em<b> Opções->Ver logs->MPlayer</b>). Em caso de problemas, este log pode conter informação importante, por isso recomenda-se manter a opção activa. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Esta opção permite filtrar as mensagens do smplayer que vão ser guardadas no log. Aqui pode escrever uma expressão regular. <br>Por exemplo: <i>^Core::.*</i> irá mostrar somente as linhas que começem com <i>Core::</i> + + + + Correct pts + Corrigir pts + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Muda MPlayer para o modo experimental em que as timestamps para frames de vídeo são calculadas de forma diferente, pois que os filtros de vídeo adicionam novas frames ou modificam as existentes, se possível. As timestamps mais precisas podem ser vistas ao mostras legendas temporizadas que alterem as bibliotecas SSA/ASS activadas. Sem os correctos pts, esta legendas poderão sair das imagens em algumas cenas. Esta opção não funciona correctamente com alguns demuxers e codecs. + + + + Proxy + Proxy + + + + Enable proxy + Activar proxy + + + + Enable/disable the use of the proxy. + Activar/Desactivar uso de proxy. + + + + Host + Host + + + + The host name of the proxy. + Nome host de proxy. + + + + Port + Porta + + + + The port of the proxy. + Porta de proxy. + + + + Username + Nom de utilizador + + + + If the proxy requires authentication, this sets the username. + Se a proxy requer autenticação, isto define o nome de utilizador. + + + + Password + Palavra-passe + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + Senha de proxy. Aviso: a senha será gravada como texto simples, no ficheiro de configurações. + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + Pode definir o proxy para ligações internet (actualmente só pode ser usado para transferir legendas). + + + + &Enable proxy + &Activar proxy + + + + &Host: + &Host: + + + + &Port: + &Porta: + + + + &Username: + Nom de &Utilizador: + + + + Pa&ssword: + Se&nha: + + + + C&orrect PTS + C&orrigir PTS + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + Tipo + + + + Select the proxy type to be used. + Seleccione o tipo de proxy a ser usada. + + + + &Type: + &Tipo: + + + + Actions list + Lista de acções + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + Aqui pode especificar uma lista de <i>acções</i> que serão executadas cada vez que um ficheiro for aberto. Poderá encontrar as acções disponíveis no editor de atalhos na secção <b>Teclado e Rato</b>. As acções têm que estar separadas por espaços e podem anteceder <i>true</i> ou <i>false</i> para as activar ou desactivar. + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + Limitações: as acções só serão executadas quando o ficheiro for aberto e não ao reiniciar o MPlayer (ex: ao seleccionar um filtro áudio ou vídeo). + + + + Network + Rede + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + Exec&utar a acção seguinte de cada vez que um ficheiro for aberto. As acções devem estar separadas por espaços: + + + + &Network + &Repor + + + + Example: + Exemplo: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + Reconstrói índice de ficheiros se nenhum for encontrado, permitindo a procura. Útil com transferências corrompidas/incompletas ou ficheiros mal criados. Esta opção só funciona se o vídeo subjacente suportar busca (i.e., não com stdin, pipe, etc.). <br> <b>Nota:</b> a criação do índice pode levar algum tempo. + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + Palavra-passe de proxy. <b>Aviso:</b> a senha será gravada como texto simples, no ficheiro de configurações. + + + + PrefAssociations + + + Warning + Aviso + + + + Not all files could be associated. Please check your security permissions and retry. + Nem todos os ficheiros foram associados, Verifique as permissões de segurança e tente novamente. + + + + File Types + Tipo de ficheiros + + + + Select all + Seleccionar todos + + + + Check all file types in the list + Marcar todos os tipos de ficheiros da lista + + + + Uncheck all file types in the list + Desmarcar todos os tipos de ficheiros da lista + + + + List of file types + Lista do tipo de ficheiros + + + + File types + Tipo de ficheiros + + + + Media files handled by SMPlayer: + Ficheiros geridos pelo SMPlayer: + + + + Select All + Seleccionar todos + + + + Select None + Desmarcar todos + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Seleccione as extensões dos ficheiros que pretende que sejam controlados pelo SMPlayer. Ao aplicar, todos os ficheiros marcados serão associados ao SMPlayer. Se desmarcar algum tipo, a associação será restaurada. + + + + Select none + Não seleccionar nada + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Nota:</b> (Restauro não funciona no Windows Vista). + + + + PrefDrives + + + Drives + Unidades + + + + icon + ícone + + + + CD device + Dispositivo de CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Escolha a unidade de CD-Rom. Será utilizada para reproduzir VCDs e Audio CDs. + + + + DVD device + Dispositivo de DVD + + + + Choose your DVD device. It will be used to play DVDs. + Escolha a unidade DVD. Será utilizada para reproduzir DVDs. + + + + Select your &CD device: + Seleccione o seu dispositivo &CD: + + + + Select your &DVD device: + Seleccione o seu dispositivo &DVD: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + O SMPlayer não escolhe os dispositivos CD ou DVD. Assim, para reproduzir um CD / DVD, deve seleccionar o dispositivo a utilizar que poderá até ser o mesmo. + + + + PrefGeneral + + + General + Geral + + + + &General + &Geral + + + + Paths + Caminhos + + + + Media settings + Definições de vídeo + + + + Preferred audio and subtitles + Áudio e legendas preferidas + + + + Video + Vídeo + + + + Start videos in fullscreen + Iniciar vídeos em modo de ecrã completo + + + + Disable screensaver + Desactivar protecção de ecrã + + + + Audio + Áudio + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Select the mplayer executable + Seleccione o executável do mplayer + + + + Executables + Executáveis + + + + All files + Todos os ficheiros + + + + Select a directory + Seleccione um directório + + + + MPlayer executable + Executável do mplayer + + + + Screenshots folder + Pasta para capturas de ecrã + + + + Video output driver + Controlador de saída vídeo + + + + Audio output driver + Controlador de saída áudio + + + + Select the audio output driver. + Seleccione o controlador de saída áudio. + + + + Remember settings + Lembrar definições + + + + Preferred audio language + Idioma preferido para áudio + + + + Preferred subtitle language + Idioma preferido para legendas + + + + Software video equalizer + Equalizador de vídeo por software + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Pode marcar esta opção se o equalizador de vídeo não for suportado pela sua placa gráfica ou controlador de vídeo.<br><b>Nota:</b> esta opção poder ser incompatível com alguns controladores de saída vídeo. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Se esta opção estiver seleccionada, todos os vídeos serão iniciados em modo de ecrã completo. + + + + Software volume control + Controle de volume por software + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Seleccione esta opção para utilizar o misturador por software, em vez de utilizar o misturador da placa de som. + + + + Postprocessing quality + Qualidade Pós-processamento + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Altera dinâmicamente o nível de pós-processamento dependendo do tempo de CPU disponível. O número especificado é o nível máximo a utilizar. Normalmente pode escolher um número elevado. + + + + Change volume + Alterar volume + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Se seleccionada, o SMPlayer irá lembrar-se do volume definido para cada ficheiro sendo este restaurado ao reproduzir novamente o ficheiro. Para novos ficheiros será usado o volume padrão. + + + + 0 + 0 + + + + &Change volume on every file + Alterar volume em &cada ficheiro + + + + Select the &MPlayer executable: + Seleccionar o executável do &MPlayer: + + + + &Folder for storing screenshots: + Pasta para &armazenar capturas: + + + + &Audio: + &Áudio: + + + + &Remember settings for all files (audio track, subtitles...) + Lemb&rar definições para todos os ficheiros (faixa de áudio, legendas...) + + + + Su&btitles: + Lege&ndas: + + + + &Quality: + &Qualidade: + + + + Start videos in &fullscreen + Iniciar vídeos em modo de ecrã &completo + + + + Disable &screensaver + De&sactivar protecção de ecrã + + + + &Default volume: + Volume &Padrão: + + + + Use s&oftware volume control + Utilizar controle de volume por s&oftware + + + + Ma&x. Amplification: + Ma&x. Amplificação: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS com passagem S/PDIF + + + + Direct rendering + Processamento directo + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Se seleccionada, activa o processamento directo (não é suportado por todos os codecs vídeo e áudio)<br><b>AVISO:</b> Pode causar corrupção OSD/SUB ! + + + + Double buffering + Buffer duplo + + + + D&irect rendering + Processamento d&irecto + + + + Dou&ble buffering + &Buffer duplo + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Buffer duplo armazena dois frames em memória e mostra um enquanto descodifica outro. Se desactivado, pode afectar negativamente o OSD. + + + + &Enable postprocessing by default + Activar pós-proc&essamento como padrão + + + + Volume &normalization by default + &Normalização de volume como padrão + + + + Close when finished + Fechar ao terminar + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Se esta opção estiver seleccionada, a janela principal será automaticamente fechada ao terminar o ficheiro/lista de reprodução actual. + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + Ca&nais padrão: + + + + &Pause when minimized + &Pausar ao minimizar + + + + Pause when minimized + Pausar ao minimizar + + + + Enable postprocessing by default + Activar pós-processamento como padrão + + + + Max. Amplification + Max. Amplificação + + + + Volume normalization by default + Normalização de volume padrão + + + + Maximizes the volume without distorting the sound. + Maximiza o volume sem distorcer o som. + + + + Default volume + Volume padrão + + + + Sets the initial volume that new files will use. + Define o volume inicial para novos ficheiros. + + + + Channels by default + Canais padrão + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Define a amplificação máxima em percentagem (padrão: 110). Um valor de 200 permiter-lhe-á ajustar o volume para um valor que, no máximo, será o dobro do actual. Para valores inferiores a 0, o OSD não será mostrado correctamente. + + + + Uses hardware AC3 passthrough + Usar passagem de hardware AC3 + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Pede o número de canais de reprodução. MPlayer tentará descodificar o áudio no número de canais especificados. Depois, depende do descodificador preencher o requesito. Isto só será importante ao reproduzir vídeos com áudio AC3 (e.g. DVDs). Nestes casos, liba52 descodificará e corrigirá o áudio no número de canais especificados. NOTA: Esta opção apenas será aceite pelos codecs AC3, pelos filtros surround e pelos drivers de saída áudio OSS. + + + + Postprocessing will be used by default on new opened files. + Pós-processamento será usado como padrão, em novos ficheiros. + + + + Audio track + Faixas áudio + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Especifica as faixas áudio a serem usadas ao reproduzir novos ficheiros. Se a faixa não existir, será usada a primeira.<br><b>Nota:</b> the <i>"Idioma preferencial áudio"</i> tem prioridade sobre esta opção. + + + + Subtitle track + Faixa de legendas + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Especifica as faixas de legendas a serem usadas ao reproduzir novos ficheiros. Se a faixa não existir, será usada a primeira.<br><b>Nota:</b> the <i>"Idioma preferencial de legendas"</i> tem prioridade sobre esta opção. + + + + Or choose a track number: + Ou escolha o número de faixa: + + + + Audi&o: + Áudi&o: + + + + Preferred language: + Idioma preferido: + + + + Preferre&d audio and subtitles + Áudio e legen&das preferidas + + + + &Subtitle: + Legenda&s: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aqui pode digitar o idioma preferencial para streams áudio e legendas. Quando um ficheiro com múltiplas legendas ou streams de áudio forem encontradas, SMPlayer tentará usar o seu idioma preferido. Apenas funciona com ficheiros que ofereçam informação sobre os idiomas ou legendas, como por exemplo DVDs ou MKVs.<br>Estes ficheiros aceitam expressões regulares. Exemplo: <b>es|esp|spa</b> seleccionará as faixas que coincidam com <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + High speed &playback without altering pitch + Re&produzir em alta velocidade sem alterar a densidade + + + + High speed playback without altering pitch + Reproduzir em alta velocidade sem alterar a densidade + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Permite alterar a velocidade de reprodução sem alterar a densidade. Necessário MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Alterar volume antes de reproduzir + + + + &Video + &Vídeo + + + + Use s&oftware video equalizer + Utilizar equalizador de víde&o por software + + + + A&udio + Á&udio + + + + Volume + Volume + + + + None + Nenhum + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normal) + + + + Yadif (double framerate) + Yadif (double framerate) + + + + Linear Blend + Mistura linear + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Dese&ntrelaçar como padrão: + + + + Deinterlace by default + Desentrelaçar como padrão + + + + Select the deinterlace filter that you want to be used for new videos opened. + Seleccione o filtro para desentrelaçar, para novos videos abertos. + + + + Remember time position + Lembrar posição temporal + + + + Remember &time position + Lembrar posição &temporal + + + + Change volume just before p&laying + Alterar vo&lume antes de reproduzir + + + + Enable the audio equalizer + Activar equalizador áudio + + + + Check this option if you want to use the audio equalizer. + Seleccione esta opção para usar o equalizador áudio. + + + + &Enable the audio equalizer + Activar &equalizador áudio + + + + Draw video using slices + Criar vídeo em partes + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Activar/Desactivar criação de vídeo em partes de 16 pixeis. Se desactivado, toda a frame será criada numa só vez. A velocidade vai depender da placa de vídeo e cache disponível. Apenas afecta os codecs libmpeg2 e libavcodec. + + + + Dra&w video using slices + Criar vídeo em &partes + + + + &Close when finished playback + Fe&char ao terminar repetição + + + + fast + rápido + + + + slow + lento + + + + fast - ATI cards + rápido - placas ATI + + + + User defined... + Definido pelo utilizador... + + + + Default zoom + Zoom Padrão + + + + This option sets the default zoom which will be used for new videos. + Esta opção define o zoom padrão para os novos vídeos. + + + + Default &zoom: + &Zoom Padrão: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Aqui deve especificar o executável mplayer que o SMPlayer iá usar.<br>O SMPlayer requer, no mínimo, Mplayer 1.0rc1, embora uma versão mais recente seja altamente recomendada). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Se esta definição estiver errada, o SMPlayer não reproduzirá nada! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Aqui pode especificar uma pasta onde as capturas serão guardadas. Se o campo ficar em branco, a função de Captura ficará desactivada. + + + + Select the video output driver. %1 provides the best performance. + Seleccione o driver de saída de vídeo. %1 fornece o melhor desempenho. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 é o recomendado. Tente evitar %2 e %3, pois são lentos e podem ter impacto no desempenho. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + Normalmente smplayer irá lembrar-se das definições para cada ficheiro que reproduza (faixa de áudio, volume, filtros...). Desmarque esta opção se não desejar esta funcionalidade. + + + + If you check this option, SMPlayer will play all files from the beginning. + Se seleccionar esta opção, o SMPlayer reproduzirá os ficheiros do início. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Se esta opção estiver activa, o ficheiro será pausado ao esconder a janela principal. Quando restaurar a janela, a reprodução continuará. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Seleccione esta opção para desactivar a protecção de ecrã ao reproduzir.<br>A protecção de ecrã será activada ao terminar a reprodução. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aqui pode introduzir o idioma preferido para a faixa de áudio. Quando um vídeo com múltiplas faixas de áudio é encontrado, smplayer tentará usar o seu idioma preferido.<br>Isto só será possível com vídeos que ofereçam informação acerca do idioma das faixas de áudio,tal como DVDs ou ficheiros mkv<br> Este campo aceita expressões regulares. Exemplo: <b>es|esp|spa</b> seleccionará a pista de áudio se coincide com <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aqui pode introduzir o idioma preferido para as legendas. Quando um vídeo com múltiplas legendas for encontrado, smplayer tentará usar o seu idioma preferido.<br>Isto só será possível com vídeos que ofereçam informação acerca do idioma das legendas, tal como DVDs ou ficheiros mkv.<br> Este campo aceita expressões regulares. Exemplo: <b>es|esp|spa</b> seleccionará a legenda se coincide com <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + Ou&tput driver: + Con&troladores de saída: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Se marcar esta opção o volume inicial será definido antes de começar a reprodução, evitando um volume elevado no início. Requer, no mínimo MPlayer SVN r27872. + + + + Add black borders on fullscreen + Adicionar contornos negros em ecrã completo + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Se activar esta opção, as margens negras serão adicionadas às imagens no modo de ecrã completo. Isto permite que as legendas sejam apresentadas nessas margens. + + + + &Add black borders on fullscreen + &Adicionar contornos negros em ecrã completo + + + + one ini file + um ficheiro ini + + + + multiple ini files + múltiplos ficheiros ini + + + + Method to store the file settings + Método para gravar as definições do ficheiro + + + + This option allows to change the way the file settings would be stored. The following options are available: + Esta opção permite-lhe alterar a maneira como as definições do ficheiro devem ser gravadas. Estão disponíveis as seguintes opções: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>um ficheiro ini</b>:as definições para todos os ficheiros reproduzidos, serão gravados num único ficheiro (%1) + + + + The latter method could be faster if there is info for a lot of files. + O 2º método será mais rápido se existir informação sobre diversos ficheiros. + + + + &Store settings in + &Gravar definições em + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>múltiplos ficheiros ini</b>:um ficheiro ini para cada ficheiro. Estes ficheiros serão gravados na pasta %1 + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + Se marcar esta opção, o SMPlayer irá lembrar-se da posição temporal do ficheiro na próxima vez que for aberto. Esta opção apenas funciona com ficheiros regulares ( não com DVDs, CDs, URLs...). + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + Se seleccionada, activa o processamento directo (não é suportado por todos os codecs vídeo e áudio)<br><b>Aviso:</b> Pode causar corrupção OSD/SUB ! + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Pede o número de canais de reprodução. O MPlayer tentará descodificar o áudio no número de canais especificados. Depois, depende do descodificador preencher o requisito. Isto só será importante ao reproduzir vídeos com áudio AC3 (como DVDs). Nestes casos, liba52 descodificará e corrigirá o áudio no número de canais especificados. <b>Nota</b>: Esta opção apenas será aceite pelos codecs AC3, pelos filtros surround e pelos drivers de saída áudio OSS. + + + + PrefInput + + + Keyboard and mouse + Teclado e rato + + + + &Keyboard + &Teclado + + + + icon + ícone + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aqui pode alterar os atalhos de teclado. Para tal, faça duplo clique ou começe a escrever sobre um atalho. Opcionalmente também pode gravar a lista para partilhá-la com outras pessoas ou utilizá-la noutro computador. + + + + &Mouse + &Rato + + + + Button functions: + Funções do botão: + + + + Media seeking + Procura + + + + Volume control + Controle de volume + + + + Zoom video + Zoom vídeo + + + + None + Nenhum + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aqui pode alterar qualquer tecla de atalho. Para tal, faça duplo clique ou pressione enter em cima da célula. Opcionalmente pode gravar esta lista e partilhá-la com outros utilizadores ou carregá-la noutro computador. + + + + &Left click + Cli&que esquerdo + + + + &Double click + &Duplo clique + + + + &Wheel function: + Fun&ções da roda do rato: + + + + Shortcut editor + Editor de atalhos + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Esta tabela permite-lhe alterar as teclas de atalho para as opções mais comuns. Faça duplo clique ou pressione ENTER num item, ou pressione<b>Alterar atalho</b>para ir a<i>Modificar atalho</i>. Existem duas maneiras para alterar um atalho:se o botão <b>Captura</b> estiver On, introduza uma nova tecla ou uma conbinação que pretende registarpara a acção (não funciona com todas as teclas). Se se o botão <b>Captura</b> estiver Off deve então introduzir o nome completo da tecla. + + + + Left click + Clique esquerdo + + + + Select the action for left click on the mouse. + Seleccione uma acção para o clique esquerdo no rato. + + + + Double click + Duplo clique + + + + Select the action for double click on the mouse. + Seleccione uma acção para o duplo clique no rato. + + + + Wheel function + Função da roda do rato + + + + Select the action for the mouse wheel. + Seleccione uma acção para a roda do rato. + + + + Play + Reproduzir + + + + Pause + Pausa + + + + Stop + Parar + + + + Fullscreen + Ecrã Completo + + + + Compact + Compacto + + + + Screenshot + Captura de ecrã + + + + On top + Em cima + + + + Mute + Silenciar + + + + Frame counter + Contador de frames + + + + Reset zoom + Repor zoom + + + + Exit fullscreen + Sair do Modo de Ecrã Completo + + + + Double size + Tamanho duplo + + + + Play / Pause + Reproduzir / Pausa + + + + Pause / Frame step + Pausa / Avançar frame + + + + Playlist + Lista de reprodução + + + + Preferences + Preferências + + + + No function + Sem funções + + + + Change speed + Alterar volume + + + + Normal speed + Velocidade normal + + + + Keyboard + Teclado + + + + Mouse + Rato + + + + Middle click + Clique no meio + + + + Select the action for middle click on the mouse. + Seleccione uma acção para o clique no meio do rato. + + + + M&iddle click + Cli&que no meio + + + + X Button &1 + Botão X &1 + + + + X Button &2 + Botão X &2 + + + + Go backward (short) + Retroceder (curto) + + + + Go backward (medium) + Retroceder (normal) + + + + Go backward (long) + Retroceder (longo) + + + + Go forward (short) + Avançar (curto) + + + + Go forward (medium) + Avançar (normal) + + + + Go forward (long) + Avançar (longo) + + + + OSD - Next level + OSD - Próximo Nível + + + + Show context menu + Mostrar menu de contexto + + + + &Right click + Clique di&reito + + + + Increase volume + Aumentar volume + + + + Decrease volume + Diminuir volume + + + + X Button 1 + X Botão 1 + + + + Select the action for the X button 1. + Seleccione uma acção para X Botão 1. + + + + X Button 2 + X Botão 2 + + + + Select the action for the X button 2. + Seleccione uma acção para X Botão 2. + + + + Show video equalizer + Mostrar equalizador de vídeo + + + + Show audio equalizer + Mostrar equalizador de áudio + + + + Always on top + Sempre no topo + + + + Never on top + Nunca no topo + + + + On top while playing + No topo ao reproduzir + + + + PrefInterface + + + Interface + Interface + + + + <Autodetect> + <Autor> + + + + Default + Padrão + + + + &Interface + &Interface + + + + Seeking + Procura + + + + Never + Nunca + + + + Whenever it's needed + Sempre que necessário + + + + Only after loading a new video + Só depois de carregar novo vídeo + + + + Recent files + Ficheiros recentes + + + + Language + Idioma + + + + Here you can change the language of the application. + Aqui pode mudar o idioma da aplicação. + + + + &Short jump + Avanço &Curto + + + + &Medium jump + Avanço &Médio + + + + &Long jump + Avanço &Longo + + + + Mouse &wheel jump + Avanço através da &roda do rato + + + + &Use only one running instance of SMPlayer + &Usar apenas uma instância do SMPlayer + + + + Ma&x. items + Itens Má&ximos + + + + St&yle: + Est&ilo: + + + + Ico&n set: + Co&njunto de ícones: + + + + L&anguage: + Idiom&a: + + + + Main window + Janela principal + + + + Auto&resize: + Redimensiona&r automaticamente: + + + + R&emember position and size + L&embrar posição e tamanho de vídeo + + + + Default font: + Fonte padrão: + + + + &Change... + &Alterar... + + + + &Behaviour of time slider: + Comportamento do controle d&e tempo: + + + + Seek to position while dragging + Procurar posicão ao arrastar + + + + Seek to position when released + Buscar posição ao largar + + + + TextLabel + Rótulo de texto + + + + &Seeking + &Procurar + + + + Ins&tances + Ins&tâncias + + + + Autoresize + Redimensionar automaticamente + + + + The main window can be resized automatically. Select the option you prefer. + A janela principal pode ser redimensionada automaticamente. Seleccione a opção que preferir. + + + + Remember position and size + Lembrar posição e tamanho de vídeo + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Se seleccionar esta opção, a posição e o tamanho da janela principal serão gravados e restaurados quando executar novamente o SMPlayer. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Seleccione o número máximo de itens a serem mostrados em<b>Ficheiros Recentes</b>. Se definir 0, o menu não será mostrado. + + + + Icon set + Conjunto de ícones + + + + Select the icon set you prefer for the application. + Seleccione o conjunto de ícones que prefere para a aplicação. + + + + Style + Estilo + + + + Select the style you prefer for the application. + Seleccione o estilo que prefere para a aplicação. + + + + Default font + Fonte padrão + + + + You can change here the application's font. + Pode alterar aqui o tipo de fonte da aplicação. + + + + Short jump + Avanço Curto + + + + Select the time that should be go forward or backward when you choose the %1 action. + Seleccione os intervalos de tempo a serem usados quando selecciona a acção %1. + + + + short jump + avanço curto + + + + Medium jump + Avanço Médio + + + + medium jump + avanço médio + + + + Long jump + Avanço Longo + + + + long jump + avanço longo + + + + Mouse wheel jump + Avanço através da roda do rato + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Seleccione os intervalos de tempo a serem usados quando move a roda do rato. + + + + Behaviour of time slider + Comportamento do controle de tempo + + + + Select what to do when dragging the time slider. + Seleccione o que deve acontecer ao arrastar o controlador de tempo. + + + + Instances + Instâncias + + + + Use only one running instance of SMPlayer + Use apenas uma instância do SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Seleccione esta opção se pretende usar a instância do SMPlayer em execução, ao abrir outros ficheiros. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer precisa escutar uma porta para receber comandos de outras instâncias. Você pode alterar a porta, caso o padrão seja usado por outra aplicação. + + + + Default GUI + GUI Padrão + + + + Mini GUI + Mini GUI + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Seleccione o GUI que prefere para a aplicação. Actualmente existem 2 tipos: Padrão ou Mini Gui.<br>O<b>GUI padrão</b> é o tradicional, com Barra de Ferramentas e Barra de Controlo. O<b>Mini GUI</b> é mais simples, sem Barra de Ferramentas e uma Barra de Controlo com menos botões.<br><b>Nota:</b> esta opção só terá efeito após reiniciar o SMPlayer. + + + + &GUI + &GUI + + + + Automatic port + Porta Automática + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer precisa listar uma porta para receber comandos de outras instâncias. Se seleccionar esta opção, a porta será escolhida automaticamente. + + + + Manual port + Porta Manual + + + + Port to listen + Porta para receber + + + + &Automatic + &Automático + + + + &Manual + &Manual + + + + Floating control + Controlo flutuante + + + + Animated + Animação + + + + If this option is enabled, the floating control will appear with an animation. + Se a opção estiver activa, o controlo flutuante aparecerá com uma animação. + + + + Width + Largura + + + + Specifies the width of the control (as a percentage). + Especifica a largura do controlo ( como percentagem). + + + + Margin + Margem + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + Esta opção define o número de pixeis de afastamento do controlo flutuante em relação ao inferior do ecrã. Útil quando o ecrã for uma TV, permitindo assim a correcta visualização do controlo. + + + + Display in compact mode too + Apresentar também em modo compacto + + + + If this option is enabled, the floating control will appear in compact mode too. Warning: the floating control has not been designed for compact mode and it might not work properly. + Se esta opção estiver activa, o controlo flutuante também aparecerá no modo compacto. Aviso: Esta funcionalidade não foi desenvolvida para este método e poderá não funcionar correctamente. + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + Se esta opção estiver marcada, o controlo será apresentado ignorando o gestor de janelas. Desactive esta opção se o controle não funcionar correctamente com o seu gestor de janelas. + + + + &Floating control + Controlo &Flutuante + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + O controlo flutuante aparece no modo de ecrã completo se mover o rato para o inferior do ecrã. + + + + &Animated + &Animação + + + + &Width: + &Largura: + + + + 0 + 0 + + + + &Margin: + &Margem: + + + + Display in &compact mode too + Apresentar também em modo &compacto + + + + &Bypass window manager + &Ignorar gestor de janelas + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + Se esta opção estiver activa, o controlo flutuante aparecerá também no modo compacto. <b>Aviso:</b> Esta funcionalidade não foi desenvolvida para este método e poderá não funcionar correctamente. + + + + Mpc GUI + Mpc GUI + + + + PrefPerformance + + + Performance + Desempenho + + + + &Performance + Desem&penho + + + + Priority + Prioridade + + + + Select the priority for the MPlayer process. + Seleccione a prioridade do processo MPlayer. + + + + realtime + tempo real + + + + high + alta + + + + abovenormal + acima do normal + + + + normal + normal + + + + belownormal + abaixo do normal + + + + idle + desocupado + + + + Cache + Cache + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Definir uma cache pode melhorar o desempenho em vídeos lentos + + + + Allow frame drop + Permitir saltar frames + + + + Synchronization + Sincronização + + + + Audio/video auto synchronization + Sincronizaçao automática áudio/vídeo + + + + Fast audio track switching + Mudança rápida da faixa de áudio + + + + Fast seek to chapters in dvds + Selecção rápida de capítulos em dvds + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Estabelece a prioridade do processo mplayer de acordo com as prioridades disponíveis no Windows.<br><b>AVISO:</b> Usar a prioridade tempo real pode bloquear o sistema. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Saltar alguns frames para manter a sincronização A/V em sistemas lentos. + + + + Allow hard frame drop + Permitir saltar frames abruptamente + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Perda de frames mais intensa (quebra a descodificação). Leva à distorção da imagem! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Ajusta a sincronização A/V gradualmente baseado em cálculos do atraso áudio. + + + + Priorit&y: + Prior&idade: + + + + &Allow frame drop + Permitir s&altar frames + + + + Allow &hard frame drop (can lead to image distortion) + Permitir saltar frames a&bruptamente (pode levar a distorção da imagem) + + + + Audio/&video auto synchronization + Sincronizaçao automática áudio/&vídeo + + + + Fact&or: + Fact&or: + + + + &Fast audio track switching + Mudança r&ápida da faixa de áudio + + + + Fast &seek to chapters in dvds + Selecção rápida de cap&ítulos em dvds + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Se seleccionada, tentará o método mais rápido para procurar capítulos mas poderá não funcionar com alguns discos. + + + + Skip loop filter + Ignorar filtros loop + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Valores possíveis: <br> <b> Sim </b>: ele tentará o método mais rápido para alternar a faixa de áudio (pode não funcionar com alguns formatos). <br> <b> Não </b>: o processo MPlayer será reiniciado sempre que você altera a faixa de áudio. <br> <b> Automatica </b>: SMPlayer decidirá o que fazer, de acordo com para a versão MPlayer. + + + + Cache for files + Cahe para ficheiros + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Esta opção especifica a quantidade de memória (em kBytes) a ser usado ao pôr em cache um ficheiro. + + + + Cache for streams + Cache para streams + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Esta opção especifica a quantidade de memória (em kBytes) a ser usada ao pôr em cache uma URL. + + + + Cache for DVDs + Cahe para DVDs + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Esta opção especifica a quantidade de memória (em kBytes) a ser usada ao pôr em cache um DVD. <br> <b> AVISO: </b> Procura pode não funcionar correctamente (incluindo alterar capítulo) ao usar cache para DVDs. + + + + &Cache + &Cache + + + + Cache for &DVDs: + Cahe para &DVDs: + + + + Cache for &local files: + Cache para ficheiros &locais: + + + + Cache for &streams: + Cache para &streams: + + + + Enabled + Activado + + + + Skip (always) + Ignorar (sempre) + + + + Skip only on HD videos + Ignorar apenas em vídeos HD + + + + Loop &filter + &Filtro de loop + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Esta opção permite ignorar o filtro loop (AKA deblocking) durante a descodificação H.264. Desde que a frame filtrada deve ser usada como referência para descodificação de frames dependentes, acontece um efeito pior na qualidade comparativamente ao deblocking. ex.: vídeo MPEG-2. Mas pelo menos para uma taxa de bits HDTV, fornece uma grande velocidade sem perda de qualidade visível. + + + + Possible values: + Valores possiveis: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Activado</b>: filtro loop não ignorado + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b> Ignorar (sempre) </b>: o filtro loop é ignorado independentemente da resolução de vídeo + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b> Ignorar apenasvídeos no disco rígido</b>: o filtro loop será ignorado apenas em vídeos em que altura é %1 ou maior. + + + + Cache for audio CDs + Cache para CDs Áudio + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Esta opção especifica a quantidade de memória (em KB) a usar, para carregar em cache um CD Áudio. + + + + Cache for &audio CDs: + Cache para CDs &Áudio: + + + + Cache for VCDs + Cache para VCDs + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Esta opção especifica a quantidade de memória (em KB) a usar, para carregar em cache um VCD. + + + + Cache for &VCDs: + Cache para &VCDs: + + + + Threads for decoding + Threads para descodificação + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Define o número de threads a usar para descodificação. Só para MPEG-1/2 e H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Threads para descodificação (só MPEG-1/2 e H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + Estabelece a prioridade do processo mplayer de acordo com as prioridades disponíveis no Windows.<br><b>Aviso:</b> Usar a prioridade tempo real pode bloquear o sistema. + + + + PrefPlaylist + + + Playlist + Lista de reprodução + + + + Automatically add files to playlist + Adicionar, automaticamente, os ficheiros à lista de reprodução + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Se esta opção estiver activa, de cada vez que abrir um ficheiro, o SMPlayer irá limpar a lista de reprodução e só depois o adicionará a esta. No caso de DVDs, CDs e VCDs, os títulos do disco serão adicionados à lista de reprodução. + + + + Add consecutive files + Adicionar ficheiros consecutivamente + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Se esta opção estiver activa, o SMPlayer irá procurar os ficheiros consecutivos(e.g. video_1.avi, video_2.avi...) e se forem encontrados, serão adicionados à lista de reprodução. + + + + &Playlist + &Lista de reprodução + + + + &Automatically add files to playlist + &Adicionar, automaticamente, os ficheiros à lista de reprodução + + + + Add &consecutive files + Adicionar fi&cheiros consecutivamente + + + + PrefSubtitles + + + Subtitles + Legendas + + + + Choose a ttf file + Escolha um ficheiro ttf + + + + Truetype Fonts + Fontes Truetype + + + + &Subtitles + &Legendas + + + + Autoload + Carregar automaticamente + + + + Select first available subtitle + Seleccionar a primeira legenda disponível + + + + Same name as movie + Mesmo nome que o filme + + + + All subs containing movie name + Todas as legendas contendo o nome do filme + + + + All subs in directory + Todas as legendas no directório + + + + Position + Posição + + + + 0 + 0 + + + + Top + Topo + + + + Bottom + Fundo + + + + Include subtitles on screenshots + Incluir legendas nas capturas de ecrã + + + + Font + Fonte + + + + Select the font which will be used for subtitles (and OSD): + Seleccione a fonte para usar em legendas (e OSD): + + + + Size + Tamanho + + + + No autoscale + Sem auto-escala + + + + Proportional to movie height + Proporcional à altura do filme + + + + Proportional to movie width + Proporcional à largura do filme + + + + Proportional to movie diagonal + Proporcional à diagonal do filme + + + + Subtitle position + Posição das legendas + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Esta opção especifica a posição das legendas sobre a janela de vídeo. <i>100</i> é o fundo, enquanto <i>0</i> é o topo. + + + + Au&toload subtitles files (*.srt, *.sub...): + Carregar au&tomaticamente ficheiros de legendas(*.srt, *.sub...): + + + + S&elect first available subtitle + S&eleccione a primeira legenda disponível + + + + &Default subtitle encoding: + Co&dificação padrão para legendas: + + + + Default &position of the subtitles on screen + Posição &padrão para legendas do ecrã + + + + &Include subtitles on screenshots + &Incluir legendas nas capturas de ecrã + + + + &TTF font: + Fonte &TTF: + + + + S&ystem font: + F&onte do sistema: + + + + A&utoscale: + A&uto-escala: + + + + Default subtitle encoding + Codificação padrão das legendas + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Se esta opção estiver seleccionada, as legendas irão aparecer nas capturas. NOTA: pode causar alguns problemas. + + + + TTF font + Fonte TTF + + + + System font + Fonte do sistema + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Aqui você pode seleccionar uma fonte de sistema para ser usada em legendas e OSD. <b> Nota: </b> requer MPlayer com suporte para configuração de fontes. + + + + Autoscale + Auto-escala + + + + Text color + Cor do texto + + + + Select the color for the text of the subtitles. + Seleccione a cor para o texto das legendas. + + + + Border color + Cor do limite + + + + Select the color for the border of the subtitles. + Selecione a cor das margens das legendas. + + + + Select the subtitle autoload method. + Selecione o método de carregamento automatico do subtítulo. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Se houver um ou mais faixas do subtítulo disponíveis, uma delas será automaticamente seleccionada, geralmente a primeiro mas, se uma delas corresponder ao idioma preferencial do utilizador esta será a utilizada. + + + + Select the subtitle autoscaling method. + Selecione o método de auto-escalamento do subtítulo. + + + + Select the encoding which will be used for subtitle files by default. + Seleccione a codificação padrão a usar em ficheiros de legendas. + + + + Try to autodetect for this language + Tentar detecção automática para este idioma + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Se activar esta opção, a codificação de legendas tentará detectar o idioma escolhido, voltando para a codificação padrão se a primeira falhar. Esta opção requer que o MPlayer tenha sido compilado com suporte ENCA. + + + + Subtitle language + Idioma das Legendas + + + + Select the language for which you want the encoding to be guessed automatically. + Seleccione o idioma para o qual a codificação será detectada automáticamente. + + + + Encoding + Codificação + + + + Try to a&utodetect for this language: + Tentar detecção a&utomática para este idioma: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Aqui você pode seleccionar a fonte TTF para ser usada nas legendas. Geralmente, você encontrará muitas fontes em <i> %1 </i> + + + + Outline + Linha externa + + + + Select the font for the subtitles. + Seleccione a fonte para as legendas. + + + + The size in pixels. + O tamanho em pixéis. + + + + Bold + Negrito + + + + If checked, the text will be displayed in <b>bold</b>. + Se marcada, o texto será exibido em <b>Negrito</b>. + + + + Italic + Ítálico + + + + If checked, the text will be displayed in <i>italic</i>. + Se marcada, o texto será exibido em <b>Ítálico</b>. + + + + Left margin + Margem esquerda + + + + Specifies the left margin in pixels. + Especifica a margem esquerda em pixéis. + + + + Right margin + Margem direita + + + + Specifies the right margin in pixels. + Especifica a margem direita em pixéis. + + + + Vertical margin + Margem vertical + + + + Specifies the vertical margin in pixels. + Especifica a margem vertical em pixéis. + + + + Horizontal alignment + Alinhamento horizontal + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + Especifica o alinhamento horizontal. Valores possíveis: esquerda, centrado e direita. + + + + Vertical alignment + Alinhamento vertical + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + Especifica o alinhamento vertical. Valores possíveis: inferior, central e superior. + + + + Border style + Estilo de contornos + + + + Specifies the border style. Possible values: outline and opaque box. + Especifica o estilo dos contornos. Valores possíveis: linha esterna ou opaco. + + + + Shadow + Sombra + + + + Si&ze: + &Tamanho: + + + + Bol&d + Negri&to + + + + &Italic + &Ítálico + + + + Colors + Cores + + + + &Text: + &Texto: + + + + &Border: + &Contornos: + + + + Margins + Margens + + + + L&eft: + &Esquerda: + + + + &Right: + &Direita: + + + + Verti&cal: + Verti&cal: + + + + Alignment + Alinhamento + + + + &Horizontal: + &Horizontal: + + + + &Vertical: + &Vertical: + + + + Border st&yle: + Estilo de conto&rnos: + + + + &Outline: + Lin&ha externa: + + + + Shado&w: + Som&bra: + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + As seguintes opções permitem-lhe definir o estilo para as legendas sem estilo (srt,sub...). + + + + Left + horizontal alignment + Esquerda + + + + Centered + horizontal alignment + Centrado + + + + Right + horizontal alignment + Direita + + + + Bottom + vertical alignment + Inferior + + + + Middle + vertical alignment + Central + + + + Top + vertical alignment + Superior + + + + Outline + border style + Linha externa + + + + Opaque box + border style + Opaca + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + Se o contorno estiver definido como <i>linha externa</i>, esta opção especifica a largura da linha em volta do texto. + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + Se o contorno estiver definido como <i>linha externa</i>, esta opção especifica a profundidade da sombra atrás do texto. + + + + Enable normal subtitles + Activar legendas normais + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + Clique neste botão para seleccionar legendas tradicionais. Esta opção apenas exibe as legendas em branco, sem qualquer efeito. + + + + Enable SSA/ASS subtitles + Activar legendas SSA/ASS + + + + Normal subtitles + Legendas normais + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + Esta opção não altera o tamanho das legendas no vídeo actual. Para o fazer, use as opções <i>Tamanho+</i> e <i>Tamanho-</i> no menu de legendas. + + + + Default scale + Escala padrão + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + Esta opção especifica a escala de fontes padrão para legendas normais, que serão utilizadas para novos vídeos abertos. + + + + SSA/ASS subtitles + Legendas SSA/ASS + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + Esta opção especifica a escala de fontes padrão para legendas SSA/ASS que serão utilizadas para novos vídeos abertos. + + + + Line spacing + Espaçamento entre linhas + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + Isto especifica o espaçamento que será usado para a separação de múltiplas linhas. Pode assumir valores negativos. + + + + &Font and colors + &Fontes e cores + + + + Enable &normal subtitles + Activar legendas &normais + + + + Enable SSA/&ASS subtitles + Activar legendas SS&A/ASS + + + + Default s&cale: + Es&cala padrão: + + + + Defa&ult scale: + Escala pa&drão: + + + + &Line spacing: + Espaçamento entre &linhas: + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + Clique neste botão para activar as novas bibliotecas SSA/ASS. Isto permite-lhe exibir legendas com múltiplas fontes, cores... + + + + Freetype support + Suporte Freetype + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + De um modo geral, não deve desactivar esta opção. Faça-o apenas se o MPlayer for compilado sem suporte freetype.<b>Desabilitar esta opção pode implicar a não exibição das legendas!</b> + + + + Freet&ype support + Suporte Freet&ype + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + Se esta opção estiver seleccionada, as legendas irão aparecer nas capturas. <b>Nota:</b>pode causar alguns problemas. + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Ajuda + + + + OK + OK + + + + Cancel + Cancelar + + + + Apply + Aplicar + + + + Help + Ajuda + + + + SMPlayer - Preferences + SMPlayer - Preferências + + + + QObject + + + will show this message and then will exit. + irá mostrar esta mensagem e sairá. + + + + the main window will be closed when the file/playlist finishes. + a janela principal será fechada ao terminar o ficheiro/lista de reprodução. + + + + This is SMPlayer v. %1 running on %2 + SMPlayer v.%1 executando em %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + tenta fazer uma ligação a outra instância em execução enviando-lhe uma acção específica. Exemplo:-send-action pause. O resto das opções(se existentes) serão ignoradas e a aplicação encerrará. Retornará o valor 0 em caso de sucesso e -1 se falhar. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list é uma lista de acções separadas por espaços. As acções serão executadas após carregar o ficheiro (se existente) na mesma ordem que introduzir. Para acções verificáveis, você pode passar verdadeiro ou falso como parâmetro. Exemplo:-actions "fullscreen compact true". Aspas serão necessárias se quiser passar mais que uma acção. + + + + media + media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + se exister outra instância em execução, o vídeo será adicionado à lista de reprodução. Caso contrário, esta opção será ignorada e os ficheiros serão abertos numa nova instância. + + + + the main window won't be closed when the file/playlist finishes. + a janela principal não será fechada ao terminar o ficheiro/lista de reprodução. + + + + the video will be played in fullscreen mode. + o vídeo será reproduzido em ecrã completo. + + + + the video will be played in window mode. + o vídeo será reproduzido em modo de janela. + + + + Enqueue in SMPlayer + Enqueue no SMPlayer + + + + opens the mini gui instead of the default one. + abre o mini ecrã ao invés do padrão. + + + + Restores the old associations and cleans up the registry. + Restaura as associações antigas e limpa o registo. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + media é qualquer tipo de ficheiro que o SMPlayer consiga abrir. Pode ser um ficheiro local, um DVD (e.g. dvd://1), um stream Internet (e.g. mms://....) ou uma lista de reprodução local no formato m3u ou pls. Se a opção -lista de reprodução for usada, isto significa que o SMPlayer passará estas opções para o MPlayer, de modo a que este faça a getão da mesma, ao invés do SMPlayer. + + + + Usage: + Uso: + + + + directory + directório + + + + action_name + nome_acção + + + + action_list + lista_acção + + + + opens the default gui. + abre o GUI Padrão. + + + + subtitle_file + ficheiro de legendas + + + + specifies the subtitle file to be loaded for the first video. + especifica o ficheiro de legendas a ser carregado para o primeiro vídeo. + + + + %1 second(s) + + %1 segundo + %1 segundos + + + + + %1 minute(s) + + %1 minuto + %1 minutos + + + + + %1 and %2 + %1 e %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + especifica o directório aonde o smplayer gravará os ficheiros de configuração (smplayer.ini, smplayer_files.ini...) + + + + disabled + aspect_ratio + desactivado + + + + auto + aspect_ratio + auto + + + + unknown + aspect_ratio + desconhecido + + + + opens the mpc gui. + abre o mpc gui. + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + Erro ZIP/UNZIP API %1 + + + + SeekWidget + + + icon + ícone + + + + label + editora + + + + ShortcutGetter + + + Modify shortcut + Modificar atalho + + + + Clear + Limpar + + + + Press the key combination you want to assign + Indique a combinação de teclas que pretende registar + + + + Capture + Capturar + + + + Capture keystrokes + Capturar teclas de atalho + + + + SubChooserDialog + + + Subtitle selection + Selecção de legendas + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Este arquivo contém mais que 1 ficheiro de legendas. Por favor, escolha o que quer extrair. + + + + Select All + Seleccionar todos + + + + Select None + Desmarcar todos + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Procura + + + + &Jump to: + &Ir para: + + + + TristateCombo + + + Auto + Automático + + + + Yes + Sim + + + + No + Não + + + + VideoEqualizer + + + Contrast + Contraste + + + + Brightness + Brilho + + + + Hue + Tonalidade + + + + Saturation + Saturação + + + + Gamma + Gamma + + + + &Reset + &Repor + + + + &Set as default values + &Usar como padrão + + + + Use the current values as default values for new videos. + Usa os valores actuais como valores padrão para novos vídeos. + + + + Set all controls to zero. + Colocar todos os controles a zero. + + + + Video Equalizer + Equalizador de Vídeo + + + + Information + Informações + + + + The current values have been stored to be used as default. + Os valores actuais foram guardados para serem usados como padrão. + + + + VideoPreview + + + Video preview + Pré-visualizar vídeo + + + + Cancel + Cancelar + + + + Generated by SMPlayer + Gerado por SMPlayer + + + + Creating thumbnails... + Criando miniaturas... + + + + Size: %1 MB + Tamanho: %1 MB + + + + Length: %1 + Duração: %1 + + + + Save file + Guardar ficheiro + + + + Images (*.png *.jpg) + Imagens (*.png *.jpg) + + + + Error saving file + Erro ao gravar o ficheiro + + + + The file couldn't be saved + O ficheiro não pôde ser gravado + + + + Error + Erro + + + + The following error has occurred while creating the thumbnails: + Ocorreu o seguinte erro ao criar as miniaturas: + + + + The temporary directory (%1) can't be created + O directório temporário (%1) não pôde ser criado + + + + The mplayer process didn't run + O processo mplayer não foi executado + + + + Resolution: %1x%2 + Resolução: %1x%2 + + + + Video format: %1 + Formato Vídeo: %1 + + + + Frames per second: %1 + Frames por segundo: %1 + + + + Aspect ratio: %1 + Tamanho de vídeo : %1 + + + + Video bitrate: %1 kbps + Taxa de bits vídeo: %1 kbps + + + + Audio bitrate: %1 kbps + Taxa de bits áudio: %1 kbps + + + + Audio rate: %1 Hz + Taxa áudio : %1 Hz + + + + The file %1 can't be loaded + O ficheiro %1 não foi carregado + + + + No filename + Sem nome + + + + The mplayer process didn't start while trying to get info about the video + O processo mplayer não foi iniciado ao tentar obter informações sobre o vídeo + + + + The length of the video is 0 + A duração do vídeo é 0 + + + + The file %1 doesn't exist + O ficheiro %1 não existe + + + + Images + Imagens + + + + No info + Sem info + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + Taxa de bits vídeo: %1 + + + + Audio bitrate: %1 + Taxa de bits áudio : %1 + + + + Audio rate: %1 + Taxa áudio : %1 + + + + VideoPreviewConfigDialog + + + Default + Padrão + + + + Video Preview + Pré-visualizar vídeo + + + + &File: + &Ficheiro: + + + + &Columns: + &Colunas: + + + + &Rows: + &Linhas: + + + + Add playing time to thumbnails + Adicionar duração às miniaturas + + + + &Aspect ratio: + Tamanho do &Vídeo: + + + + &Seconds to skip at the beginnning: + &Segundos a saltar no início: + + + + &Maximum width: + Largura &Máxima: + + + + The preview will be created for the video you specify here. + A visualização será criada para o vídeo que especificar aqui. + + + + The thumbnails will be arranged on a table. + As miniaturas serão arranjadas numa tabela. + + + + This option specifies the number of columns of the table. + Esta opção especifica o número de colunas por tabela. + + + + This option specifies the number of rows of the table. + Esta opção especifica o número de linhas por tabela. + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + Se marcar esta opção, o tempo de reprodução será apresentado no fundo de cada miniatura. + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + Se o tamanho do vídeo estiver errado, aqui pode especificar um diferente. + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + Normalmente as primeiras frames são pretas, logo é uma boa idéia saltar alguns segundos no início de cada vídeo. Esta opção permite-lhe especificar quantos segundo serão ignorados. + + + + This option specifies the maximum width in pixels that the generated preview image will have. + Esta opção especifica a largura máxima dos pixeis que a imagem gerada terá. + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + Algumas frames serão extraídas do vídeo de modo a criar a pré-visualização. Aqui pode escolher o formato da imagem para as frames extraídas. PNG poderá fornecer uma melhor qualidade. + + + + Add playing &time to thumbnails + Adicionar &tempo de reprodução às miniaturas + + + + &Extract frames as + &Extrair frames como + + + + Enter here the DVD device or a folder with a DVD image. + Introduza aqui o dispositivo DVD ou a pasta com a imagem DVD. + + + + &DVD device: + Dispositivo de &DVD: + + + + VolumeSliderAction + + + Volume + Volume + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_ro_RO.ts b/plugins/smplayer_plugin/translations/smplayer_ro_RO.ts new file mode 100644 index 000000000..44158707f --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_ro_RO.ts @@ -0,0 +1,7305 @@ + + + + About + + + Version: %1 + Versiunea: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Acest program este un produs de tip "free software": poate fi redistribuit și/sau modificat respectând termenii licenței GNU GPL și publicată de către fundația 'Free Software Foundation"; fie versiunea 2 a licenței fie (la alegere) orice versiune ulterioară. + + + + The following people have contributed with translations: + Următorii oameni au contribuit cu traduceri: + + + + German + Germană + + + + Slovak + Slovacă + + + + Italian + Italiană + + + + French + Franceză + + + + %1, %2 and %3 + %1, %2 şi %3 + + + + Simplified-Chinese + Chineză-simplificată + + + + Russian + Rusă + + + + %1 and %2 + %1 şi %2 + + + + Hungarian + Maghiară + + + + Polish + Poloneză + + + + Japanese + Japoneză + + + + Dutch + Olandeză + + + + Ukrainian + Ucraineană + + + + Portuguese - Brazil + Portugheză - Brazilia + + + + Georgian + Georgiană + + + + Czech + Cehă + + + + Bulgarian + Bulgară + + + + Turkish + Turcă + + + + Swedish + Suedeză + + + + Serbian + Sârbă + + + + Traditional Chinese + Chineză Tradiţională + + + + Romanian + Română + + + + Portuguese - Portugal + Portugheză - Portugalia + + + + Greek + Greacă + + + + Finnish + Finlandeză + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Despre SMPlayer + + + + &Info + &Info + + + + icon + Iconiță + + + + &Contributions + &Colaboratori + + + + &Translators + &Traducători + + + + &License + &Licență + + + + Visit our web for updates: + Vizitați situl nostru web pentru actualizări: + + + + Get help in our forum: + Obțineți ajutor pe forumul nostru: + + + + You can support SMPlayer by making a donation. + Puteți susţine SMPlayer făcând o donație. + + + + More info + Informații suplimentare + + + + Korean + Coreană + + + + Macedonian + Macedoneană + + + + Basque + Bască + + + + Using MPlayer %1 + Se folosește MPlayer r%1 + + + + Catalan + Catalană + + + + Portable Edition + Ediția Portabilă + + + + Using Qt %1 (compiled with Qt %2) + S-a folosit Qt %1 (compilat cu Qt %2) + + + + Slovenian + Slovenă + + + + Arabic + Arabă + + + + Kurdish + Kurdă + + + + Galician + Galițiană + + + + The following people have contributed with patches (see the changelog for details): + Persoanele următoare au contribuit la corectarea și îmbunătățirea programului (consultați jurnalul modificărilor pentru detalii): + + + + If there's any omission, please report. + Dacă există omisiuni, vă rugăm să anunțați. + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Nume + + + + Description + Descriere + + + + Shortcut + Acces rapid + + + + &Save + &Salvare + + + + &Load + Î&ncărcare + + + + Key files + Fișiere taste + + + + Choose a filename + Alegere nume fișier + + + + Confirm overwrite? + Confirmați suprascrierea? + + + + The file %1 already exists. +Do you want to overwrite? + Fișierul %1 există deja.Doriți să-l suprascrieți? + + + + Choose a file + Alegere fișier + + + + Error + Eroare + + + + The file couldn't be saved + Fișierul nu aputut fi salvat + + + + The file couldn't be loaded + Fișierul nu a putut fi încărcat + + + + &Change shortcut... + &Modificare acces rapid... + + + + AudioEqualizer + + + Audio Equalizer + Egalizor grafic audio + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + V&alidare + + + + &Reset + &Resetare + + + + &Set as default values + &Selectare ca valoari implicite + + + + Use the current values as default values for new videos. + Folosirea valorilor curente ca valori implicite pentru fișierele video noi. + + + + Set all controls to zero. + Aducerea butoanele de control la zero. + + + + Information + Informații + + + + The current values have been stored to be used as default. + Valorile curente au fost memorate pentru a fi folosite ca valori implicite. + + + + BaseGui + + + SMPlayer - mplayer log + Jurnal SMPlayer - mplayer + + + + SMPlayer - smplayer log + Jurnal SMPlayer - smplayer + + + + &Open + &Deschide + + + + &Play + Re&dare + + + + &Video + &Video + + + + &Audio + &Audio + + + + &Subtitles + &Subtitrare + + + + &Browse + &Navigare + + + + Op&tions + Opți&uni + + + + &Help + &Ajutor + + + + &File... + &Fișier... + + + + D&irectory... + D&irector... + + + + &Playlist... + &Listă de titluri... + + + + &DVD from drive + Citire &DVD din DVDROM + + + + D&VD from folder... + Citire D&VD din fișier... + + + + &URL... + &URL... + + + + &Clear + Ș&tergere listă + + + + &Recent files + Fișiere deschise &recent + + + + P&lay + Re&dare + + + + &Pause + &Pauză + + + + &Stop + &Stop + + + + &Frame step + &Frecvență cadre + + + + &Normal speed + Viteză &Normală + + + + &Halve speed + R&elanti + + + + &Double speed + Viteză D&ublă + + + + Speed &-10% + Viteză &-10% + + + + Speed &+10% + Viteză &+10% + + + + Sp&eed + Vit&eză + + + + &Repeat + &Repetare + + + + &Fullscreen + &Fullscreen + + + + &Compact mode + Mod &Compact + + + + Si&ze + &Dimensiune + + + + 4:3 &Letterbox + 4:3 &Compact + + + + 16:9 L&etterbox + 16:9 _C&ompact + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 î&n 16:9 + + + + &Aspect ratio + Raport &aspect + + + + &None + Fă&ră + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Amestec &Liniar + + + + &Deinterlace + &Deîntrețesere + + + + &Postprocessing + &Postprocesare + + + + &Autodetect phase + &Autodetectare fază + + + + &Deblock + &Filtru buclă + + + + De&ring + + + + + Add n&oise + Adăugare &zgomot + + + + F&ilters + F&iltre + + + + &Equalizer + &Egalizor + + + + &Screenshot + &Captură_ecran + + + + S&tay on top + &Fixat deasupra + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtre + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Canale + + + + &Left channel + Canal &Stânga + + + + &Right channel + Canal &Dreapta + + + + &Stereo mode + Mod &Stereo + + + + &Mute + &Mute + + + + Volume &- + Volum &- + + + + Volume &+ + Volum &+ + + + + &Delay - + Întâ&rziere - + + + + D&elay + + Întâr&ziere + + + + + &Select + &Selectare + + + + &Load... + Î&ncărcare... + + + + Delay &- + Întârziere &- + + + + Delay &+ + Întârziere &+ + + + + &Up + &Sus + + + + &Down + &Jos + + + + &Title + &Titlu + + + + &Chapter + &Capitol + + + + &Angle + &Unghi + + + + &Playlist + &Listă titluri + + + + &Show frame counter + &Arată contor cadre + + + + &Disabled + &Inactivat + + + + &Seek bar + &Bară căutare + + + + &Time + &Durată + + + + Time + T&otal time + D&urată + Durată totală + + + + &OSD + &OSD + + + + &View logs + &Arhivă jurnale + + + + P&references + P&referințe + + + + About &Qt + Despre &Qt + + + + About &SMPlayer + Despre &SMPlayer + + + + <empty> + <gol> + + + + Video + Video + + + + Audio + Audio + + + + Playlists + Liste_titluri + + + + All files + Toate fișierele + + + + Choose a file + Alegere fișier + + + + SMPlayer - Information + SMPlayer - Informații + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Driverele pentru CDROM/DVD nu sunt configurate încă. +O fereastră de dialog va fi afișată pentru a putea face configurarea. + + + + Choose a directory + Alegere director + + + + Subtitles + Subtitrări + + + + About Qt + Despre Qt + + + + Playing %1 + Redare %1 + + + + Pause + Pauză + + + + Stop + Stop + + + + Play / Pause + Redare / Pauză + + + + Pause / Frame step + Pauză / Pas cadre + + + + U&nload + + + + + V&CD + V&CD + + + + C&lose + Înch&ide fereastra + + + + View &info and properties... + Consultați &informații și proprietăți... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Resetare + + + + Move &left + Deplasare la &stânga + + + + Move &right + Deplasare la &dreapta + + + + Move &up + Deplasare în s&us + + + + Move &down + Deplasare în &jos + + + + &Pan && scan + + + + + &Previous line in subtitles + &Linia anterioară a subtitrării + + + + N&ext line in subtitles + &Următoarea linie a subtitrării + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Reducere volum (2) + + + + Inc volume (2) + Creștere volum (2) + + + + Exit fullscreen + Ieșire mod fullscreen + + + + OSD - Next level + OSD - Nivel următor + + + + Dec contrast + Reducere contrast + + + + Inc contrast + Creștere contrast + + + + Dec brightness + Reducere strălucire + + + + Inc brightness + Creștere strălucire + + + + Dec hue + Reducere culoare + + + + Inc hue + Creştere culoare + + + + Dec saturation + Reducere saturație + + + + Dec gamma + Reducere gamma + + + + Next audio + Coloana sonoră următoare + + + + Next subtitle + Următoarea subtitrare + + + + Next chapter + Capitol următor + + + + Previous chapter + Capitol anterior + + + + Inc saturation + Creștere saturație + + + + Inc gamma + Creștere gamma + + + + &Load external file... + Î&ncărcare fișier extern... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normal) + + + + Y&adif (double framerate) + Y&adif (frecvență cadre dublă) + + + + &Next + &Următorul + + + + Pre&vious + A&nteriorul + + + + Volume &normalization + &Normalizare volum + + + + &Audio CD + CD &Audio + + + + Denoise nor&mal + Înlăturare zgomot - nor&mal + + + + Denoise &soft + Înlăturare zgomot - &ușor + + + + Denoise o&ff + Înlăturare zgomot - inac&tivat + + + + Use SSA/&ASS library + Utilizează biblioteca SSA/&ASS + + + + Flip i&mage + I&magine răsturnată + + + + &Toggle double size + + + + + S&ize - + D&imensiune - + + + + Si&ze + + Di&mensiune + + + + + Add &black borders + Adăugare &benzi negre + + + + Soft&ware scaling + Scalare Soft&ware + + + + &FAQ + &FAQ + + + + Visualize &motion vectors + Vizualizare vectori de &mișcare + + + + &Command line options + Opțiuni linie de &comandă + + + + SMPlayer command line options + Opțiuni linie de comandă pentru SMPlayer + + + + Enable &closed caption + Activare subtitrare pentru &handicap auditiv + + + + &Forced subtitles only + Doar subtitrarea &forțată + + + + Reset video equalizer + Refacere valori implicite egalizor video + + + + MPlayer has finished unexpectedly. + MPlayer s-a închis inexplicabil. + + + + Exit code: %1 + Cod de eroare: %1 + + + + MPlayer failed to start. + MPlayer nu a putut porni. + + + + Please check the MPlayer path in preferences. + Verificați calea pentru MPlayer în Preferințe. + + + + MPlayer has crashed. + MPlayer s-a oprit. + + + + See the log for more info. + Pentru mai multe informații consulați jurnalul. + + + + &Rotate + &Rotire + + + + &Off + &Oprit + + + + &Rotate by 90 degrees clockwise and flip + &Rotire 90 de grade în sensul acelor de ceas, cu întoarcere + + + + Rotate by 90 degrees &clockwise + Rotire 90 de grade în sensul acelor de &ceas + + + + Rotate by 90 degrees counterclock&wise + Rotire 90 de grade în sens &trigonometric + + + + Rotate by 90 degrees counterclockwise and &flip + Rotire 90 de grade în sens trigonometric cu î&ntoarcere + + + + &Jump to... + Sal&t la ... + + + + Show context menu + Afișare meniu contextual + + + + Multimedia + Multimedia + + + + E&qualizer + E&galizor grafic + + + + Reset audio equalizer + Resetarea egalizorului audio + + + + Find subtitles on &OpenSubtitles.org... + Căutarea subtitrărilor în paginile &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Transmiteți su&btitrări către OpenSubtitles.org... + + + + &Tips + &Sfaturi practice + + + + &Auto + &Auto + + + + Speed -&4% + Viteză -&4% + + + + &Speed +4% + &Viteză +4% + + + + Speed -&1% + Viteză -&1% + + + + S&peed +1% + Vite&ză +1% + + + + Scree&n + Ecra&n + + + + &Default + &Implicit + + + + Mirr&or image + Imagine în &oglindă + + + + Next video + Următorul fișier video + + + + &Track + video + Fișier &video + + + + &Track + audio + C&oloană_sonoră + + + + Warning - Using old MPlayer + Atenționare - Acum folosiți o versiune MPlayer veche + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + Versiunea pentru MPlayer (%1) pe care o aveți instalată în sistem este depășită. SMPlayer nu poate funcționa bine cu această versiune: unele opțiuni nu vor funcționa, selectarea subtitrărikor poate eșua... + + + + Please, update your MPlayer. + Actualizați versiunea pentru MPlayer. + + + + (This warning won't be displayed anymore) + (Această atenționare nu va mai fi afișată) + + + + Next aspect ratio + Următorul format imagine + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer încă funcționează de aici + + + + S&how icon in system tray + A&fișează iconiță în system tray + + + + &Hide + &Ascunde + + + + &Restore + &Restaurare_fereastră + + + + &Quit + Î&nchide program + + + + Playlist + Listă_Titluri + + + + Core + + + Brightness: %1 + Luminozitate: %1 + + + + Contrast: %1 + Contrast: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Culoare: %1 + + + + Saturation: %1 + Saturație: %1 + + + + Volume: %1 + Volum: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + Mărime caractere: %1 + + + + Aspect ratio: %1 + Format imagine: %1 + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Bun venit la SMPlayer + + + + Audio + Audio + + + + Subtitle + Subtitrare + + + + &Main toolbar + &Bară_principală unelte + + + + &Language toolbar + Bară_unelte &limbă + + + + &Toolbars + B&are de unelte + + + + EqSlider + + + icon + Iconiță + + + + ErrorDialog + + + Hide log + Ascunde jurnalul + + + + Show log + Afișează jurnalul + + + + MPlayer Error + Eroare MPlayer + + + + icon + Iconiță + + + + Error + Eroare + + + + FileDownloader + + + Downloading... + Se descarcă... + + + + Downloading %1 + Se descarcă %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Proprietăți fișier + + + + &Information + &Informații + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + &Selectare demuxer care va fi utilizat pentru acest fișier: + + + + &Reset + &Valori_implicite + + + + &Video codec + Codec &video + + + + &Select the video codec: + &Selectare codec video: + + + + A&udio codec + Codec a&udio + + + + &Select the audio codec: + &Selectare codec audio: + + + + &MPlayer options + Opțiuni &MPlayer + + + + Additional Options for MPlayer + Opțiuni suplimentare pentru MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aici se pot adăuga opțiuni suplimentare pentru MPlayer.Opțiunile trebuie separate prin spații.Exemplu: -flip nosound + + + + &Options: + &Opțiuni: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Puteți introduce filtre video suplimentare. +Separați-le prin ",".Nu utilizați spații! +Exemplu: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + Filtre V&ideo: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Și, în sfârșit, filtrele audio. +Se folosesc aceleași reguli ca pentru filtrele video.Exemplu: resample=44100:0:0,volnorm + + + + Audio &filters: + &Filtre audio: + + + + OK + Închide + + + + Cancel + Renunțare + + + + Apply + Validare + + + + FindSubtitlesWindow + + + Language + Limbă + + + + Name + Nume + + + + Format + Format + + + + Files + Fișiere + + + + Date + Data + + + + Uploaded by + Încărcat de către + + + + All + Toate + + + + Close + Închide + + + + &Download + &Descărcare + + + + &Copy link to clipboard + &Copiere legătură pe clipboard + + + + Error + Eroare + + + + Download failed: %1. + Descărcare eșuată: %1. + + + + Connecting to %1... + Conectare la %1... + + + + Downloading... + Se descarcă... + + + + Done. + Operație terminată. + + + + %1 files available + %1 fișiere disponibile + + + + Failed to parse the received data. + Transferul datelor recepționate a eșuat. + + + + Find Subtitles + Căutare subtitrări + + + + &Subtitles for + &Subtitrări pentru + + + + &Language: + &Limba: + + + + &Refresh + &Reîncărcare + + + + Subtitle saved as %1 + Subtitrare salvată ca %1 + + + + %1 subtitle(s) extracted + + %1 subtitrări extrase + + + + + + Overwrite? + Scrieți peste? + + + + The file %1 already exits, overwrite? + Fișierul %1 există, scrieți peste el? + + + + Error saving file + Eroare la salvarea fișierului + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Nu a fost posibilă salvarea fișierului +descărcat în directorul %1 +Verificați permisiunile acelui director. + + + + Download failed + Descărcare eșuată + + + + Temporary file %1 + Fișier %1 temporar + + + + InfoFile + + + General + General + + + + Size + Dimensiune + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Durată + + + + Demuxer + Demuxer + + + + Name + Nume + + + + Artist + Artist + + + + Author + Autor + + + + Album + Album + + + + Genre + Gen + + + + Date + Dată + + + + Track + Coloană sonoră + + + + Copyright + Licență + + + + Comment + Comentariu + + + + Software + Software + + + + Clip info + Informații Clip + + + + Video + Video + + + + Resolution + Rezoluție + + + + Aspect ratio + Raport aspect + + + + Format + Format + + + + Bitrate + Viteză_transfer + + + + %1 kbps + %1 kbps + + + + Frames per second + Cadre pe secundă + + + + Selected codec + Codec-ul selectat + + + + Initial Audio Stream + + + + + Rate + + + + + %1 Hz + %1 Hz + + + + Channels + + + + + Audio Streams + + + + + Language + Limbă + + + + empty + gol + + + + Subtitles + Subtitrări + + + + Type + Tipul + + + + ID + Info for translators: this is a identification code + Cod Identificare + + + + # + Info for translators: this is a abbreviation for number + Nr. + + + + Stream title + + + + + Stream URL + + + + + File + Fișier + + + + InputDVDDirectory + + + Choose a directory + Alegere director + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Încărcare DVD dintr-un director + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Puteți reda un dvd de pe hard disc.Selectați directorul care conține fișierele VIDEO_TS și AUDIO_TS. + + + + Choose a directory... + Alegere director... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Introduceți versiunea pentru MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer nu a putut determina versiunea pentru MPlayer pe care o folosiți. + + + + Version reported by MPlayer: + Versiunea raportată de către MPlayer: + + + + Please, &select the correct version: + Vă rugăm &selectați versiunea corectă: + + + + 1.0rc1 or older + 1.0rc1 sau mai veche + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Mai nouă decât 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Introduceți URL + + + + &URL: + &UR: + + + + It's a &playlist + Este o &listă de titluri + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Dacă această opțiune este selectată atunci URL va fi tratat ca o listă de titluri: va fi deschis ca text și va reda adresele URL din listă. + + + + Languages + + + Afar + + + + + Abkhazian + Abhază + + + + Afrikaans + Afrikaans + + + + Amharic + Amharică + + + + Arabic + Arabă + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + Azerbaijană + + + + Bashkir + + + + + Byelorussian + Bielorusă + + + + Bulgarian + Bulgară + + + + Bihari + + + + + Bislama + + + + + Bengali + Bengaleză + + + + Tibetan + Tibetană + + + + Breton + Bretonă + + + + Catalan + Catalană + + + + Corsican + Corsicană + + + + Czech + Cehă + + + + Welsh + Galeză + + + + Danish + Daneză + + + + German + Germană + + + + Greek + Greacă + + + + English + Engleză + + + + Esperanto + Esperanto + + + + Spanish + Spaniolă + + + + Estonian + Estoniană + + + + Basque + Bască + + + + Persian + Farsi + + + + Finnish + Finlandeză + + + + Fiji + Fijiană + + + + Faroese + Faroeză + + + + French + Franceză + + + + Frisian + Frisiană + + + + Irish + Irlandeză + + + + Scots + Scoțiană joasă (Scots) + + + + Galician + Galițiană + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + Ebraică + + + + Hindi + Hindusă + + + + Croatian + Croată + + + + Hungarian + Maghiară + + + + Armenian + Armeană + + + + Interlingua + + + + + Indonesian + Indoneziană + + + + Interlingue + + + + + Icelandic + Islandeză + + + + Italian + Italiană + + + + Inuktitut + + + + + Japanese + Japoneză + + + + Javanese + Javaneză + + + + Georgian + Georgiană + + + + Kazakh + Cazacă + + + + Greenlandic + Groenlandeză + + + + Cambodian + Khmeră + + + + Kannada + Kanadeză + + + + Korean + Coreană + + + + Kashmiri + Kashmiriană + + + + Kurdish + Kurdă + + + + Kirghiz + Chirghiză + + + + Latin + Latină + + + + Lingala + Lingala + + + + Laothian + Laoțiană + + + + Lithuanian + Lituaniană + + + + Latvian + Letonă + + + + Malagasy + Malgașă + + + + Maori + Maori + + + + Macedonian + Macedoneană + + + + Malayalam + + + + + Mongolian + Mongolă + + + + Moldavian + Moldovenească + + + + Marathi + Marathi + + + + Malay + Malaeziană + + + + Maltese + Malteză + + + + Burmese + Birmaneză + + + + Nauru + Nauruan + + + + Nepali + Nepaleză + + + + Dutch + Olandeză + + + + Norwegian + Norvegiană + + + + Occitan + Occitană (Provensală) + + + + Oriya + + + + + Punjabi + Punjabi + + + + Polish + Poloneză + + + + Pashto + Paștună + + + + Portuguese + Portugheză + + + + Quechua + Quechua + + + + Kirundi + Kirundi + + + + Romanian + Română + + + + Russian + Rusă + + + + Kinyarwanda + Kinyarwanda + + + + Sanskrit + Sanscrită + + + + Sindhi + + + + + Slovak + Slovacă + + + + Slovenian + Slovenă + + + + Samoan + + + + + Shona + + + + + Somali + Somaleză + + + + Albanian + Albaneză + + + + Serbian + Sârbă + + + + Sundanese + Sundaneză (Basa Sunda) + + + + Swedish + Suedeză + + + + Swahili + Swahili + + + + Tamil + Tamilă + + + + Telugu + + + + + Tajik + + + + + Thai + Tailandeză + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Turcă + + + + Tsonga + + + + + Tatar + Tătară + + + + Twi + + + + + Uighur + + + + + Ukrainian + Ucraineană + + + + Urdu + Urdu + + + + Uzbek + Uzbecă + + + + Vietnamese + Vietnameză + + + + Wolof + + + + + Xhosa + + + + + Yiddish + Idiș + + + + Yoruba + + + + + Zhuang + + + + + Chinese + Chineză + + + + Zulu + Zulu + + + + Portuguese - Brazil + Portugheză - Brazilia + + + + Portuguese - Portugal + Portugheză - Portugalia + + + + Simplified-Chinese + Chineză simplificată + + + + Traditional Chinese + Chineză tradițională + + + + Unicode + Unicod + + + + UTF-8 + UTF-8 + + + + Western European Languages + Limbi Vest Europene + + + + Western European Languages with Euro + Limbi Vest Europene cu Euro + + + + Slavic/Central European Languages + Limbi Slave/Central Europene + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galițiană, Malteză, Turcă + + + + Old Baltic charset + Caractere Vechi Baltice + + + + Cyrillic + Alfabet Chirilic + + + + Modern Greek + Greacă Modernă + + + + Baltic + Baltică + + + + Celtic + Celtă + + + + Hebrew charsets + Alfabet Ebraic + + + + Ukrainian, Belarusian + Ucraineană, Belarusă + + + + Simplified Chinese charset + Alfabet Chinez Simplificat + + + + Traditional Chinese charset + Alfabet Chinez Tradițional + + + + Japanese charsets + Alfabet Japonez + + + + Korean charset + Alfabet Corean + + + + Thai charset + Alfabet Tailandez + + + + Cyrillic Windows + Alfabet Chirilic Windows + + + + Slavic/Central European Windows + Alfabet Slavon/Central European Windows + + + + Arabic Windows + Alfabet Arab Windows + + + + Rhaeto-Romance + Rhaeto-Romance + + + + Serbo-Croatian + Sârbo-croat + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Alegere nume fișier de salvat + + + + Confirm overwrite? + Se confirmă suprascrierea? + + + + The file already exists. +Do you want to overwrite? + Un fișier cu același nume există deja. +Se dorește suprascrierea lui? + + + + Error saving file + Eroare la salvarea fișierului + + + + The log couldn't be saved + Jurnalul nu a putut fi salvat + + + + Logs + Arhivă jurnale + + + + LogWindowBase + + + Log Window + Fereastră Jurnal + + + + Save + Salvare + + + + Copy to clipboard + Copiere pe clipboard + + + + Close + Închide + + + + &Close + În&chide + + + + MiniGui + + + Control bar + Bară de control + + + + MpcGui + + + Control bar + Bară de control + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Nume + + + + Length + Durată + + + + &Play + &Redare + + + + &Edit + &Editare + + + + Playlists + Liste_Titluri + + + + Choose a file + Alegere fișier + + + + Choose a filename + Alegere nume fișier + + + + Confirm overwrite? + Confirmați suprascrierea? + + + + The file %1 already exists. +Do you want to overwrite? + Fișierul %1 există. +Doriți suprascrierea? + + + + All files + Toate fișierele + + + + Select one or more files to open + Selectați unul sau mai multe fișiere pentru a le deschide + + + + Choose a directory + Alegere director + + + + Edit name + Editare nume + + + + Type the name that will be displayed in the playlist for this file: + Tastați numele care va fi afișat în Listă pentru acest fișier: + + + + &Load + Î&ncărcare + + + + &Save + &Salvare + + + + &Next + &Următorul + + + + Pre&vious + Ant&eriorul + + + + Move &up + Mutare în s&us + + + + Move &down + Mutare în &jos + + + + &Repeat + &Repetare + + + + S&huffle + A&leator + + + + Add &current file + Adăugare fișier &curent + + + + Add &file(s) + Adăugare &fișier(e) + + + + Add &directory + Adăugare &director + + + + Remove &selected + Ștergeți &selecția + + + + Remove &all + Ştergeţi &tot + + + + SMPlayer - Playlist + SMPlayer - Listă _titluri + + + + Add... + Adăugare... + + + + Remove... + Înlăturare... + + + + Playlist modified + Listă_titluri modificată + + + + There are unsaved changes, do you want to save the playlist? + Există modificări nesalvate, doriți să salvați lista? + + + + Preferences + Opțiuni Preferate + + + + PlaylistPreferences + + + Playlist - Preferences + Listă de titluri - Opțiuni preferate + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Selectați această opțiune dacă doriți ca prin adăugarea unui director să se adauge recursiv și fișierele și subdirectoarele conținute. Dacă nu este selectată această opțiune se vor adăuga doar fișierle din directorul selectat. + + + + &Add files in directories recursively + &Adăugarea recursivă a fișerelor din directoare + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Selectați această opțiune dacă doriți să se caute informații despre titlurile pe care doriți să le adăugați în lista de titluri. Aceasta permite afișarea numele (dacă este disponibil) și lungimea fișierelor. Dacă nu este selectată opțiunea aceste informații nu vor fi accesibile decât atunci când este redat fișierul respectiv. Atenționare: această opțiune poate fi de durată, mai ales dacă adăugați multe fișiere. + + + + Automatically get &info about files added + Achiziționare automată de &informații despre fișierele adăugate + + + + &Save copy of playlist on exit + &Salvează o copie a listei la închiderea programului + + + + &Play files from start + &Redare fișiere de la început + + + + PrefAdvanced + + + Advanced + Opțiuni_avansate + + + + Auto + Automat + + + + &Advanced + Opțiuni_&Avansate + + + + icon + Iconiță + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Aici se pot introduce opțiuni suplimentare pentru MPlayer. +Opțiunile se vor scrie separate de spații. +Exemplu: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Puteți introduce filtre video suplimentare. +Opțiunile se vor separa prin "," (virgulă).Nu se utilizează spații! +Exemplu: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Filtre audio.Se folosesc aceleași reguli ca la filtrele video. +Exemplu: resample=44100:0:0,volnorm + + + + Log MPlayer output + Înscrie în jurnal datele furnizate de MPlayer + + + + Log SMPlayer output + Înscrie în jurnal datele furnizate de SMPlayer + + + + This option is mainly intended for debugging the application. + Această opțiune se adresează în principal depanării aplicației. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Selectarea acestei opțiuni va reduce tremurul imaginii, dar, totodată poate produce afișarea incorectă a fișierului video. + + + + Filter for SMPlayer logs + Filtrare date înscrise în jurnalul SMPlayer + + + + &Monitor aspect: + Aspect &monitor: + + + + &Run MPlayer in its own window + &Rulează MPlayer în fereastra proprie + + + + &Options: + &Opțiuni: + + + + V&ideo filters: + Filtre V&ideo: + + + + Audio &filters: + &Filtre audio: + + + + &Colorkey: + &Cod_Culoare: + + + + Log &SMPlayer output + Înscrie în jurnal datele furnizate de &SMPlayer + + + + &Filter for SMPlayer logs: + &Filtrare date înscrise în jurnalul SMPlayer: + + + + C&hange... + M&odificare... + + + + Logs + Arhivă jurnale + + + + Log MPlayer &output + Jurnal MPlayer &ieșire + + + + Options for MP&layer + Opțiuni pentru MP&layer + + + + Autosave MPlayer log + Salvare automată jurnal MPlayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Dacă va fi selectată această opțiune, jurnalul MPlayer va fi salvat în fișierul specificat de fiecare dată când se redă un nou fișier media. Este destinat aplicațiilor externe, astfel încât aceste programe să poată obține informații despre fișierele media pe care le redați. + + + + Autosave MPlayer log filename + Nume fișier jurnal MPlayer salvare automată + + + + Enter here the path and filename that will be used to save the MPlayer log. + Introduceți calea și numele fișierului care va fi folosit pentru salvarea jurnalului MPlayer. + + + + A&utosave MPlayer log to file + Salvare a&utomată jurnal MPlayer în fișier + + + + Pass short filenames (8+3) to MPlayer + Transmite nume scurte de fișier (8+3) către MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + Versiunea curentă de MPlayer nu poate deschide fișiere al căror nume conține un număr mare de caractere. Bifând această opțiune va face ca SMPlayer să transmită către MPlayer versiunea scurtă a numelor fișierelor și astfel va fi posibil să le deschidă. + + + + &Pass short filenames (8+3) to MPlayer + &Transmite nume scurte de fișier (8+3) către MPlayer + + + + Monitor aspect + Aspect monitor + + + + Select the aspect ratio of your monitor. + Selectați dimensiunile monitorului. + + + + Run MPlayer in its own window + Rulează MPlayer în fereastra proprie + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Dacă selectați această opțiune, fereastra video MPlayer nu va fi încastrată în fereastra principală SMPlayer ci se va folosi fereastra proprie. De observat că mausul și tastatura vor fi interpretate direct de MPlayer, aceasta înseamnă că tastele de acces rapid și acțiunile mausului nu vor funcționa ca atunci când fereastra SMPlayer era activă. + + + + Colorkey + cheie de culoare + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Dacă observați porțiuni din video suprapuse peste oricare alte ferestre, puteți modifica cheia de culoare pentru a îndrepta acest lucru. Încercați să selectați o culoare apropiată de negru. + + + + Options for MPlayer + Opțiuni pentru MPlayer + + + + Options + Opțiuni + + + + Here you can type options for MPlayer. Write them separated by spaces. + Aici puteți introduce opțiunile pentru MPlayer. Scrieți-le separate de spații. + + + + Video filters + Filtre video + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Aici puteți adăuga filtre video pentru MPlayer. Scrieți-le separate de virgulă. Nu utilizați spații! + + + + Audio filters + Filtre audio + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Aici puteți adăuga filtre audio pentru MPlayer. Scrieți-le separate de virgulă. Nu utilizați spații! + + + + Repaint the background of the video window + Refacerea culorii de fond a ferestrei de redare + + + + Repaint the backgroun&d of the video window + Refacerea culorii de fon&d a ferestrei de redare + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Se va folosi protocolul IPv4 pentru conectarea în rețea. Dacă nu este corect se va folosi implicit protocolul IPv6. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Se va folosi protocolul IPv6 pentru conectarea în rețea. Dacă nu este corect se va folosi implicit protocolul IPv4. + + + + Network Connection + Conexiune rețea + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + &Jurnale + + + + Rebuild index if needed + Refacere index dacă este necesar + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Refacerea indexului fișierelor dacă nu a fost găsit niciun index, pentru a permite căutarea. Opțiune utilă pentru desărcări incomplete/cu erori, sau cu fișiere create greșit. Această opțiune funcționează doar dacă fișierul media vizat suportă căutare (nu va lucra cu stdin, pipe, etc.).</br> Notă: crearea indexului este o operațiune de durată. + + + + Rebuild &index if needed + Refacere &index dacă este necesar + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Dacă este selectată această opțiune, SMPlayer va stoca mesajele de depanare (puteți vedea jurnalul în <b>Opțiuni -> Afișare jurnale -> SMPlayer</b>). Aceste informații pot fi foarte utile dezvoltatorilor, în caz că descoperiți o eroare de programare. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Dacă este selectată această opțiune, SMPlayer va stoca mesajele pe care le emite MPlayer (puteți consulta jurnalul la <b>Opțiuni -> Afișare jurnale -> MPlayer</b>). În cazul unor probleme acest jurnal poate conține informații importante, prin urmare, este recomandat să păstrați această opțiune selectată. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Această vă permite să selectați mesajele SMPlayer care vor fi stocate în jurnal. Aici puteți scrie orice tip de expresie regulată. <br>De exemplu: <i>^Core::.*</i> va afișa doar liniile care încep cu <i>Core::</i> + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + Proxy + + + + Enable proxy + Activare proxi + + + + Enable/disable the use of the proxy. + Activează sau dezactivează folosirea proxi. + + + + Host + Gazdă + + + + The host name of the proxy. + Numele gazdă pentru proxi. + + + + Port + Port + + + + The port of the proxy. + Portul pentru proxy. + + + + Username + Nume utilizator + + + + If the proxy requires authentication, this sets the username. + Dacă proxy este cu autentificare, această opțiune cofigurează numele de utilizator. + + + + Password + Parolă + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + Parola pentru proxy. Atenționare: parola va fi salvată în clar în fișierul de configurare. + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + Puteți configura un proxy pentru conectarea la Internet (deocamdată este folosit doar pentru descărcarea subtitrărilor). + + + + &Enable proxy + Activar&e proxy + + + + &Host: + &Gazdă: + + + + &Port: + &Port: + + + + &Username: + Nume &utilizator: + + + + Pa&ssword: + Paro&lă: + + + + C&orrect PTS + + + + + Http + Http + + + + Socks5 + + + + + Type + Tip + + + + Select the proxy type to be used. + Selectați tipul de proxi ce va fi folosit. + + + + &Type: + &Tip: + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Atenționare + + + + Not all files could be associated. Please check your security permissions and retry. + Nu toate fișierele pot fi asociate. Verificați permisiunile de securitate și încercați din nou. + + + + File Types + Tipuri Fișiere + + + + Select all + Toate Selectate + + + + Check all file types in the list + Bifarea tuturor tipurilor de fișiere din listă + + + + Uncheck all file types in the list + Debifarea tuturor tipurilor de fișiere din listă + + + + List of file types + Lista tipurilor de fișiere + + + + File types + Tipuri fișiere + + + + Media files handled by SMPlayer: + Fișiere media manipulate de SMPlayer: + + + + Select All + Toate Selectate + + + + Select None + Niciunul Selectat + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Bifați fișierele media pe care doriți să le manipuleze SMPlayer. După ce apăsați butonul Validare, fișierele bifate vor fi asociate cu SMPlayer. Dacă debifați un tip de fișier media, se va reface asocierea implicită a fișierului. + + + + Select none + Niciunul Selectat + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + (sp)<b>Notă:</b>(Restaurarea nu funcționează pentru Windows Vista). + + + + PrefDrives + + + Drives + Drivere + + + + icon + Iconiță + + + + CD device + Dispozitiv CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Alegeți dispozitivul CDROM. Acesta va fi folosit pentru redarea VCD și CD Audio. + + + + DVD device + Dispozitiv DVD + + + + Choose your DVD device. It will be used to play DVDs. + Alegere dispozitiv DVD. Acesta va fi folosit pentru redarea DVD. + + + + Select your &CD device: + Selectare dispozitiv redare &CD: + + + + Select your &DVD device: + Selectare dispozitiv redare &DVD: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer nu alege implicit orice dispozitiv CDROM sau DVDROM. Așa că înainte de a reda efectiv un CD sau DVD trebuie să selectați dispozitivele pe care doriți să le utilizați ( poate fi același dispozitiv ). + + + + PrefGeneral + + + General + Opțiuni_Generale + + + + &General + Opțiuni_&Generale + + + + Paths + Selectare căi + + + + Media settings + Reglaje media + + + + Preferred audio and subtitles + Opțiuni preferate pentru sonor și subtitrări + + + + Video + Video + + + + Start videos in fullscreen + Redare fișier video în mod fullscreen + + + + Disable screensaver + Dezactivare economizor ecran + + + + Audio + Audio + + + + AC3/DTS pass-through S/PDIF + AC3/DTS direcționat către S/PDIF + + + + Select the mplayer executable + Selectare executabil mplayer + + + + Executables + Executabile + + + + All files + Toate fișierele + + + + Select a directory + Selectare director + + + + MPlayer executable + Executabil MPlayer + + + + Screenshots folder + Director capturi de ecran + + + + Video output driver + Driver ieșire video + + + + Audio output driver + Driver ieșire audio + + + + Select the audio output driver. + Selectare driver ieșire audio. + + + + Remember settings + Memorare reglaje + + + + Preferred audio language + Limbă preferată coloană sonoră + + + + Preferred subtitle language + Limbă preferată pentru subtitrări + + + + Software video equalizer + Egalizor video software + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Se poate selecta această opțiune dacă egalizorul video nu este suportat de placa grafică sau de driverul de ieșire video.<br><b>Atenție:</b> această opțiune poate fi incompatibilă cu unele drivere de ieșire video. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Selectarea acestei opțiuni va indica redarea fișierelor video în mod fullscreen. + + + + Software volume control + Control volum software + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Selectați aceasta opțiune pentru a folosi mixerul software, în locul mixerului plăcii de sunet. + + + + Postprocessing quality + Calitate posprocesare + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Modificarea dinamică a nivelului postprocesării funcție de încărcarea CPU. Numărul specificat va reprezenta valoarea maximă a nivelului folosit. + + + + Change volume + Modificare volum + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Dacă este selectată această opțiune atunci SMPlayer va memora nivelul volumului pentru toate fișierele redate și va folosi aceste valori când fișierele respective vor fi redate din nou. Pentru fișiere noi se va utiliza valoarea implicită a volumului. + + + + 0 + 0 + + + + &Change volume on every file + &Modifică volumul pentru fiecare fișier + + + + Select the &MPlayer executable: + Selectarea executabilului &MPlayer: + + + + &Folder for storing screenshots: + &Director pentru stocarea capturilor de ecran: + + + + &Audio: + &Audio: + + + + &Remember settings for all files (audio track, subtitles...) + Memorare &reglaje pentru toate tipurile de fișiere (coloană sonoră, subtitrare...) + + + + Su&btitles: + Su&btitrări: + + + + &Quality: + Ca&litatea: + + + + Start videos in &fullscreen + Redare video în mod &fullscreen + + + + Disable &screensaver + Dezactivare e&conomizor ecran + + + + &Default volume: + &Volum implicit: + + + + Use s&oftware volume control + Folosire control volum prin s&oftware + + + + Ma&x. Amplification: + Valoare ma&ximă amplificare: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS direcţionat către S/PDIF + + + + Direct rendering + Randare directă + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Selectarea acestei opțiuni va porni randarea directă (funcția nu este suportată de toate codecurile și ieșirile video)<br><b>ATENȚIONARE:</b>Această funcție poate duce la coruperea OSD/SUB! + + + + Double buffering + Mărime dublă buffer + + + + D&irect rendering + Randare d&irectă + + + + Dou&ble buffering + Mărime du&blă buffer + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Alocarea unei mărimi duble pentru buffer va înlătura efectul de clipire a imaginii prin stocarea a două cadre în memorie și va afișa una în timp ce cealaltă este decodată. Dacă nu este selectată această opțiune se poate înfluența în mod negativ OSD (afișarea mesajelor pe imagine), dar de cele mai multe ori înlătură efectul de clipire a acestor mesaje. + + + + &Enable postprocessing by default + &Activare implicită postprocesare + + + + Volume &normalization by default + &Normalizare implicită volum + + + + Close when finished + Închide după terminare + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Dacă această opțiune este selectată, fereastra principală se va închide automat după redarea fișierului/listei de titluri. + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + C&anale implicite: + + + + &Pause when minimized + &Pauză la minimizare + + + + Pause when minimized + Pauză la minimizare + + + + Enable postprocessing by default + Activare postprocesare implicită + + + + Max. Amplification + Amplificare maximă + + + + Volume normalization by default + Normalizare implicită volum + + + + Maximizes the volume without distorting the sound. + Mărire volumul fără a distorsiona sunetul. + + + + Default volume + Volum implicit + + + + Sets the initial volume that new files will use. + Stabilire volum inițial folosit pentru noile fișiere. + + + + Channels by default + Canale implicite + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Stabilirea nivelului maxim de amplificare în procente (implicit: 110). O valoare de 200 vă va permite ajustarea volumului până la o valoare maximă egală cu dublul valorii curente. Pentru o valoare sub 100 volumul inițial (care este 100%) va fi peste valoarea maximă, iar în acest caz, de exemplu, OSD nu îl va afișa corect. + + + + Uses hardware AC3 passthrough + Utilizare procesare AC3 hardware + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Cererea număruli de canale de redare. MPlayer cere decodorului să decodeze coloana sonoră în numărul de canale specificat. Apoi este treaba decodorului să realezeze acest lucru. Acest lucru este, de regulă, important numai atunci când se redau fișiere video cu coloana sonoră codată cu AC3 (precum DVD). În acst caz liba52 realizează implicit decodarea și mixează corect sunetul în numărul de canale specificat. NOTĂ: Această opțiune este îndeplinită de codecuri (doar AC3), filtre (surround) și driverele audio de ieșire (OSS cel puțin). + + + + Postprocessing will be used by default on new opened files. + Postprocesarea va fi utilizată implicit pentru noile fișiere. + + + + Audio track + Coloană sonoră + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Specifică coloana sonoră implicită ce va fi folosită la redarea fișierelor nou încărcate. Dacă nu există coloana sonoră selectată va fi folosită prima coloană sonoră disponibilă. <br><b>Notă:</b> <i> "limba preferată coloană sonoră"</i> va fi preferată în detrimentul acestei opțiuni. + + + + Subtitle track + Pistă subtitrări + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Specifică pista cu subtitrarea implicită ce va fi folosită când se vor reda fișiere noi. Dacă pista nu există, va fi folosită prima pistă disponibilă. <br> <b>Notă:</b> opțiunea <i> " limba preferată pentru subtitrare" </i> va fi preferată în detrimentul acestei opțiuni. + + + + Or choose a track number: + Sau alegeți un număr de pistă: + + + + Audi&o: + C&oloană Sonoră: + + + + Preferred language: + Limbă preferată: + + + + Preferre&d audio and subtitles + Opțiuni prefera&te pentru sonor și subtitrări + + + + &Subtitle: + &Subtitrare: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aici se poate tasta limba preferată pentru subtitrare și pentru coloana sonoră. Când un fișier mediea cu multiple coloane sonore și subtitrări este găsit, SMPlayer va încerca să folosească limba dumneavoastră preferată. Această opțiune funcționează doar cu acele fișiere media care oferă informații despre limba coloanei sonore și a subtitrării, precum DVD-urile sau fișierele în format mkv.<br>Aceste căsuțe acceptă expresii obișnuite. Exemplu: <b>es|esp|spa</b> va selecta pista care corespunde cu <i>es</i>, <i>esp</i> sau <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + <Here it goes an explanation text> + + + + + High speed &playback without altering pitch + &Redare rapidă fără alterarea timbrului sunetului + + + + High speed playback without altering pitch + Redare rapidă fără alterarea timbrului sunetului + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Vă permite modificarea vitezei de redare fără a altera timbrul sunetului. Opțiunea are nevoie de MPlayer versiunea dev-svn-r24924. + + + + Change volume just before playing + Modfificare volum înainte de redare + + + + &Video + &Video + + + + Use s&oftware video equalizer + Utilizare egalizor video s&oftware + + + + A&udio + A&udio + + + + Volume + Volum + + + + None + Nimic + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normal) + + + + Yadif (double framerate) + Yadif (frecfență cadre dublă) + + + + Linear Blend + Amestec liniar + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Deî&ntrețesere implicită: + + + + Deinterlace by default + Deîntrețesere implicită + + + + Select the deinterlace filter that you want to be used for new videos opened. + Selectați filtrul de deîntrețesere pe care doriți să îl folosiți pentru fișierele video deschise în viitor. + + + + Remember time position + Memorarea timpului scurs + + + + Remember &time position + Memorarea &timpului scurs + + + + Change volume just before p&laying + Modificarea vo&lumului chiar înainte de redare + + + + Enable the audio equalizer + Activare egalizor audio + + + + Check this option if you want to use the audio equalizer. + Bifați această opțiune dacă doriți să utilizați egalizorul audio. + + + + &Enable the audio equalizer + Activare &egalizor audio + + + + Draw video using slices + Creare imagine din benzi + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Activează/dezactivează crearea imaginii din benzi late de 16 pixeli. Dacă este dezactivată opțiunea, întregul cadru este creat dintr-o singură mișcare. Poate fi mai rapid sau mai lent funcție de placa video și de câtă memorie cache este disponibilă. Are efect doar cu codecurile libmpeg2 și libavcodec. + + + + Dra&w video using slices + C&reare imagine din benzi + + + + &Close when finished playback + În&chide după încheierea redării + + + + fast + repede + + + + slow + lent + + + + fast - ATI cards + repede - plăci ATI + + + + User defined... + Definit de utilizator... + + + + Default zoom + Mărire implicită + + + + This option sets the default zoom which will be used for new videos. + Această opțiune configurează nivelul implicit de mărire ce va fi folosit la redarea fișierelor video viitoare. + + + + Default &zoom: + &Mărire implicită: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Aici trebuie să precizați versiunea executabilului pentru mplayer pe care îl va folosi SMPlayer. <br>SMPlayer are nevoie de cel puțin versiunea 1.0rc1 pentru MPlayer (dar o versiune mai nouă este mult mai recomandată). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Dacă această opțiune este aleasă greșit, SMPlayer nu va putea reda nimic! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Aici puteți preciza directorul în care vor fi stocate capturile de ecran realizate cu SMPlayer. Dacă acest câmp este gol, funcția de captură de ecran nu va fi activă. + + + + Select the video output driver. %1 provides the best performance. + Selectați driverul de ieșie video. %1 asigură cele mai bune performanțe. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 este opțiunea recomandată. Încercați să evitați alegerea opțiunilor %2 și %3, acestea sunt lente și pot avea impact negativ asupra performanțelor. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + Implicit SMPlayer va reține opțiunile alese pentru fiecare fișier multimedia pe care îl redați (pista audio selectată, volumul, filtrele, ...). Dezactivați această opțiune, dacă nu vă place această caracteristică. + + + + If you check this option, SMPlayer will play all files from the beginning. + Dacă selectați aceasta opțiune, SMPlayer va reda toate fișierele de la începutul lor. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Dacă este selectată această opțiune, se va face pauză în redarea fișierului când fereastra principală a programului este ascunsă. La restaurarea ferestrei redarea fișierului va fi reluată. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Selectați această opțiune pentru a dezactiva economizorul de ecran când se redă un fișier multimedia. <br>Economizorul de ecran se va activa din nou după ce se va termina redarea fișierului. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aici puteți selecta limba preferată pentru coloana sonoră. Când este găsit un fișier multimedia care conține mai multe coloane sonore, SMPlayer va încerca să folosească limba preferată.<br>Această optiune este valabilă doar pentru fișiere multimedia care oferă informații despre limba coloanelor sonore, precum DVD-urile sau fișierele în format mkv.<br>Câmpul acceptă expresii regulate. Exemplu: expresia <b>es|esp|spa</b> va determina alegerea coloanei sonore care corespunde abrevierilor <i>es</i>, <i>esp</i> sau <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Aici puteți selecta limba preferată pentru subtitrare. Când este găsit un fișier multimedia care oferă fisiere de subtitrare în mai multe limbi, SMPlayer va încerca să folosească limba preferată.<br>Această opțiune nu funcționează decât cu fișierele multimedia care oferă informații despre fișierele cu subtitrări, precum DVD-uri sau fișiere mkv.<br>Acest câmp acceptă expresii regulate. Exemplu: expresia <b>es|esp|spa</b> va determina selectarea subtitrării care corespunde abrevierilor <i>es</i>, <i>esp</i> sau <i>spa</i>. + + + + Ou&tput driver: + D&river ieșire: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Dacă este selectată această opțiune volumul inițial va fi selectat chiar înainte de a începe redarea. Astfel se evită redarea la volum mare la început. Opțiunea aceasta are nevoie cel puțin de versiunea MPlayer SVN r27872. + + + + Add black borders on fullscreen + Adăugare benzi negre în mod fullscreen + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Dacă este selectată această opțiune, se vor adăuga niște benzi negre la imagine în modul de afișare fullscreen. Astfel se permite afișarea subtitrării pe benzile negre. + + + + &Add black borders on fullscreen + &Adăugare benzi negre în mod fullscreen + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Tastatură și maus + + + + &Keyboard + &Tastatură + + + + icon + Iconiță + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aici se pot modifica tastele pentru acces rapid.Pentru a face acest lucru executați clic dublu sau tastați peste celula în care se menționează tipul de acces rapid.Opțional se poate salva lista pentru a o împărtăși cu prietenii sau pentru folosirea în alt caculator. + + + + &Mouse + &Maus + + + + Button functions: + Funcții butoane: + + + + Media seeking + Căutare media + + + + Volume control + Control volum + + + + Zoom video + Zoom video + + + + None + Nimic + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Aici se pot modifica tastele pentru acces rapid.Pentru a face acest lucru executați clic dublu sau tastați peste celula în care se menționează tipul de acces rapid. Opțional se poate salva lista pentru a o împărtăși cu prietenii sau pentru folosirea în alt caculator. + + + + &Left click + Clic &stânga + + + + &Double click + &Dublu clic + + + + &Wheel function: + Funcții &rotiță: + + + + Shortcut editor + Editor acces rapid + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Acest tabel vă permite modificarea tastelor de acces rapid pentru cele mai multe dintre acțiunile disponibile. Efectuați dublu clic sau apăsați tasta Enter pe un articol, sau apăsați butonul <b>Modificare acces rapid ...</b> pentru a intra în meniul dialog <i>Modificare taste de acces rapid</i>. Sunt două modalități de schimbare a tastelor de acces rapid: dacă butonul <b>Captură</b> este activ atunci apăsați noua combinație de taste pe care doriți să o desemnați pentru acțiunea selectată (din nefericire această posibilitate nu este funcțională pentru toate tastele). Dacă butonul <b>Captură </b> nu este activ atunci ați putea introduce numele întreg al tastei. + + + + Left click + Clic stânga + + + + Select the action for left click on the mouse. + Selectare acțiune pentru clic stânga cu mausul. + + + + Double click + Dublu clic + + + + Select the action for double click on the mouse. + Selectare acțiune pentru dublu clic cu mausul. + + + + Wheel function + Funcție rotiță + + + + Select the action for the mouse wheel. + Selectare acțiune pentru rotiță maus. + + + + Play + Redare + + + + Pause + Pauză + + + + Stop + Stop + + + + Fullscreen + Fullscreen + + + + Compact + Compact + + + + Screenshot + Captură_ecran + + + + On top + Deasupra + + + + Mute + Mute + + + + Frame counter + Contor cadre + + + + Reset zoom + Reset zoom + + + + Exit fullscreen + Ieșire mod fullscreen + + + + Double size + Dimensiune dublă + + + + Play / Pause + Redare / Pauză + + + + Pause / Frame step + Pauză / Pas cadre + + + + Playlist + Listă de Titluri + + + + Preferences + Opțiuni Preferate + + + + No function + Nici o funcție + + + + Change speed + Modificare viteză + + + + Normal speed + Viteză Normală + + + + Keyboard + Tastatură + + + + Mouse + Maus + + + + Middle click + Clic buton mijloc + + + + Select the action for middle click on the mouse. + Selectați acțiunea pentru apăsarea butonului de mijloc al mausului. + + + + M&iddle click + Cl&ic buton mijloc + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + Salt scurt înapoi + + + + Go backward (medium) + Salt mediu înapoi + + + + Go backward (long) + Salt lung înapoi + + + + Go forward (short) + Salt scurt înainte + + + + Go forward (medium) + Salt mediu înainte + + + + Go forward (long) + Salt lung înainte + + + + OSD - Next level + OSD - Nivel următor + + + + Show context menu + Afișare meniu contextual + + + + &Right click + Clic d&reapta maus + + + + Increase volume + Mai tare + + + + Decrease volume + Mai încet + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + Afișare egalizor video + + + + Show audio equalizer + Afișare egalizor audio + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Interfață + + + + <Autodetect> + <Autodetectare> + + + + Default + Valori implicite + + + + &Interface + &Interfață + + + + Seeking + Căutare + + + + Never + Niciodată + + + + Whenever it's needed + Oricând este nevoie + + + + Only after loading a new video + Numai la încăcarea unui fișier video nou + + + + Recent files + Fișiere recente + + + + Language + Limbă + + + + Here you can change the language of the application. + Aici puteți modifica limba pentru aplicație. + + + + Instances + Sesiuni + + + + &Short jump + &Salt scurt + + + + &Medium jump + Salt &mediu + + + + &Long jump + Salt &lung + + + + Mouse &wheel jump + Salt cu &rotiță maus + + + + &Use only one running instance of SMPlayer + Folosește o sing&ură sesiune pornită pentru SMPlayer + + + + Ma&x. items + Ma&ximum de articole + + + + St&yle: + St&il: + + + + Ico&n set: + Set iconi&țe: + + + + L&anguage: + Lim&bă: + + + + Main window + Fereastra principală + + + + Auto&resize: + &Redimensionare automată: + + + + R&emember position and size + M&emorare poziție și mărime + + + + Default font: + Caractere implicite: + + + + &Change... + &Modificare... + + + + &Behaviour of time slider: + &Comportament reglaj timp: + + + + Seek to position while dragging + Căutare până la poziție când se face tragere + + + + Seek to position when released + Căutare până la poziție când se eliberează mausul + + + + TextLabel + Etichetă_Text + + + + &Seeking + &Căutare + + + + Ins&tances + &Sesiuni + + + + Autoresize + Redimensionare automată + + + + The main window can be resized automatically. Select the option you prefer. + Fereastra principală poate fi redimensionată automat. Selectați opțiunea preferată. + + + + Remember position and size + Memorează poziția și dimensiunea + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Dacă selectați această opțiune, poziția și dimensiunea ferestrei principale vor fi salvate și restaurate când porniți din nou SMPlayer. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Selectați numărul maxim de linii ce vor fi afișate în submeniul <b>Deschide->Fișiere deschise recent</b>. Dacă selectați 0 atunci meniul nu va fi deloc afișat. + + + + Icon set + Set iconițe + + + + Select the icon set you prefer for the application. + Selectați setul de iconițe preferat pentru aplicație. + + + + Style + Stil + + + + Select the style you prefer for the application. + Selectați stilul preferat pentru aplicație. + + + + Default font + Caractere implicite + + + + You can change here the application's font. + Aici puteți selecta caracterele folosite de aplicație. + + + + Short jump + Salt scurt + + + + Select the time that should be go forward or backward when you choose the %1 action. + Seletați intervalul de timp pentru derulare înainte sau înapoi când alegeți acțiunea %1 . + + + + short jump + salt scurt + + + + Medium jump + Salt mediu + + + + medium jump + salt mediu + + + + Long jump + Salt lung + + + + long jump + salt lung + + + + Mouse wheel jump + Salt cu rotiță mouse + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Seletați intervalul de timp pentru derulare înainte sau înapoi când acționați rotița mausului. + + + + Behaviour of time slider + Comportament reglaj timp + + + + Select what to do when dragging the time slider. + Selectați ce se întâmplă când acționați potențiometrul linar al reglajului de timp. + + + + Use only one running instance of SMPlayer + Foloseşte o singură sesiune pornită pentru SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Selectați această opțiune dacă doriți să folosiți o sesiune deja deschisă a lui SMPlayer când deschideți și alte fișiere. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer are nevoie să asculte un anume port pentru a recepționa comenzi de la alte sesiuni. Puteți schimba portul în cazul în care cel implicit este utilizat de altă aplicație. + + + + Default GUI + Interfață grafică implicită + + + + Mini GUI + Interfață grafică redusă + + + + GUI + Interfață grafică + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Selectați interfața grafică pe care o preferați pentru SMPlayer. În acest moment există două tipuri: „Interfața grafică implicită” și „Interfața grafică redusă”.<br> <b>Interfața grafică implicită</b> este o interfață grafică obișnuită, cu bare de unelete și de control. <b>Interfața grafică redusă</b> este u interfață grafică mai simplă, fără bară de unelte și cu mai puține butoane în bara de control.<br><b>Notă:</b>După alegerea opțiunii dorite trebuie să reporniți aplicația SMPlayer pentru ca modificările să se facă simțite. + + + + &GUI + &Interfață grafică + + + + Automatic port + Detectare automată port + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer are nevoie să asculte un anume port pentru a recepționa comenzi de la alte sesiuni. Dacă selectați această opțiune portul va fi ales automat. + + + + Manual port + Detectare manuală port + + + + Port to listen + Portul de ascultat + + + + &Automatic + &Automat + + + + &Manual + &Manual + + + + Floating control + Butoane de control pe imagine + + + + Animated + Animație + + + + If this option is enabled, the floating control will appear with an animation. + Dacă este activată această opțiune, butoanele de control de pe imagine vor apărea animate. + + + + Width + Lățime + + + + Specifies the width of the control (as a percentage). + Specifică lățimea butoanelor de control de pe imagine (în procente). + + + + Margin + Margine + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + Această opțiune stabilește distanța butoanelor de control de pe imagine față de margine inferioară a ecranului, în număr de pixeli. Această opțiune este utilă mai ales atunci când ecranul este un televizor, pentru că în acest caz butoanele nu vor fi vizibile fără stabilirea unei valori adecvate pentru această opțiune. + + + + Display in compact mode too + Afișare și în mod compact + + + + If this option is enabled, the floating control will appear in compact mode too. Warning: the floating control has not been designed for compact mode and it might not work properly. + Dacă este selectată această opțiune, butoanele de control de pe imagine vor fi afișate și în mod compact. Atenționare: butoanele de control de pe imagine nu au fost concepute să funcționeze și în mod compact și din această cauză este posibil să nu funcționeze corect. + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + &Butoane de control pe imagine + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + Butoanele de control de pe imagine apar în mod fullscreen când mausul este mișcat în partea inferioară a ercranului. + + + + &Animated + &Animație + + + + &Width: + &Lățime: + + + + 0 + 0 + + + + &Margin: + &Margine: + + + + Display in &compact mode too + Afișare și în mod &compact + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Caracteristici + + + + &Performance + &Caracteristici + + + + Priority + Prioritate + + + + Select the priority for the MPlayer process. + Selectare priorități pentru procesele MPlayer. + + + + realtime + timp_real + + + + high + înaltă + + + + abovenormal + peste_normal + + + + normal + normal + + + + belownormal + sub_normal + + + + idle + inactiv + + + + Cache + Cache + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Setarea cache-ului poate îmbunătății performanțele pentru fișiere media lente + + + + Allow frame drop + Permite programului să renunțe la unele cadre + + + + Synchronization + Sincronizare + + + + Audio/video auto synchronization + Sincronizare automată Audio/Video + + + + Fast audio track switching + Comutare rapidă a coloanei sonore + + + + Fast seek to chapters in dvds + Căutare rapidă a capitolelor în dvd + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Selectare priorități pentru procesele mplayer în concordanță cu prioritățile implicite disponibile sub Windows.<br><b>ATENŢIONARE:</b>Folosirea priorității "în timp real" poate duce la blocarea sistemului. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Se sare peste afișarea unor cadre pentru a menține sincronizarea A/V pe sisteme lente. + + + + Allow hard frame drop + Permite programului să renunțe la mai multe cadre + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Omiterea mai multor cadre (strică decodarea). Conduce la distorsionarea imaginii! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Ajustare graduală a sincronizării A/V prin măsurarea întârzierii audio. + + + + Priorit&y: + Pri&oritate: + + + + &Allow frame drop + &Permite renunțarea la unele cadre + + + + Allow &hard frame drop (can lead to image distortion) + P&ermite renunțarea la mai multe cadre (poate duce la imagini distorsionate) + + + + Audio/&video auto synchronization + Sincronizare automată Audio/&Video + + + + Fact&or: + Fact&or: + + + + &Fast audio track switching + &Comutare rapidă a coloanei sonore + + + + Fast &seek to chapters in dvds + Cău&tare rapidă a capitolelor în dvd + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Dacă este selectată această opţiune, programul va încerca să aplice cea mai rapidă metodă de căutare a capitolelor, dar pentru anumite discuri poate să nu funcționeze. + + + + Skip loop filter + Omitere filtru buclă + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Valori posibile:<br> <b>Yes</b>: va încerca metoada cea mai rapidă pentru comutarea pistelor audio (este posibil să nu funcționeze pentru anumite formate), <br> <b>No</b>: procesul MPlayer va fi repornit de câte ori schimbați pista audio, <br> <b>Auto </b>: SMPlayer va decide cum va proceda, funcție de versiunea MPlayer. + + + + Cache for files + Cache pentru fișiere + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Această opțiune stabilește câtă memorie (în kBytes) se va folosi la încărcarea unui fișier în cache. + + + + Cache for streams + Cache pentru URL + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Această opțiune stabilește câtă memorie (în kBytes) se va folosi pentru cache la redarea unui fișier video de pe internet. + + + + Cache for DVDs + Cache pentru DVD + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Această opțiune stabilește câtă memorie (în kBytes) se va folosii la încărcarea în cache a DVD-urilor.<br><b>Atenţie:</b>Este posibil ca funcția de căutare să nu mai funcționeze corect (inclusiv căutarea capitolelor) când se folosește încărcarea în cache a DVD-urilor. + + + + &Cache + &Cache + + + + Cache for &DVDs: + Cache pentru &DVD: + + + + Cache for &local files: + Cache pentru fișiere &locale: + + + + Cache for &streams: + Cache pentru &streams (URL): + + + + Enabled + Activat + + + + Skip (always) + Omitere (întotdeauna) + + + + Skip only on HD videos + Omitere doar pentru video HD + + + + Loop &filter + &Filtru buclă + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Această opțiune permite omiterea filtrului buclă (cunoscut și sub numele deblocking) în timpul decodării H.264. Deoarece cadrele filtrate cu acest filtru se presupune că sunt luate ca referință pentru decodarea cadrelor dependente, eliminarea filtrului are un efect de înrăutățire a calității, față de cazul în care nu se folosește deblocking de exemplu pentru fișiere video de tip MPEG-2. Dar cel puțin pentru fișierele video de tip HDTV această procedură oferă o îmbunătățire vizibilă a vitezei fără pierderi de calitate vizibile. + + + + Possible values: + Valori posibile: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Activat</b>: filtrul buclă nu se omite + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Omitere (întotdeauna)</b>: filtrul buclă este omis indiferent de rezoluția fișierului video + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Omitere doar pentru video HD</b>: filtrul buclă se va omite doar pentru fișierele video definiție este %1 sau mai mare. + + + + Cache for audio CDs + Cache pentru CD-uri audio + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Această opțiune stabilește câtă memorie (în kBytes) se va folosi la pre-încărcarea unui CD în cache. + + + + Cache for &audio CDs: + C&ache pentru CD-uri audio: + + + + Cache for VCDs + Cache pentru VCD + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Această opțiune stabilește câtă memorie (în kBytes) se va folosi la pre-încărcarea unui VCD în cache. + + + + Cache for &VCDs: + Cache pentru &VCD: + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Listă redare + + + + Automatically add files to playlist + Adăugare automată a fișierelor la lista de redare + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Dacă este selectată aceasta opțiune, de fiecare dată când este deschis un fișier, SMPlayer va șterge lista de redare si va adăuga fișierul deschis la listă. În cazul DVD-urilor, CD-urilor și VCD-urilor se vor adăuga toate titlurile de pe disc la lista de redare. + + + + Add consecutive files + Adăugarea fișierelor consecutive + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Dacă este selectată aceasta opțiune, SMPlayer va căuta fișiere multimedia consecutive (de exemplu video_1.avi, video_2.avi...) și dacă sunt găsite, acestea vor fi adăugate la lista de redare. + + + + &Playlist + &Listă de redare + + + + &Automatically add files to playlist + &Adăugare automată a fișierelor la lista de redare + + + + Add &consecutive files + Adăugarea fișierelor &consecutive + + + + PrefSubtitles + + + Subtitles + Subtitrări + + + + Choose a ttf file + Alegere fișier ttf + + + + Truetype Fonts + Caractere Truetype + + + + &Subtitles + &Subtitrare + + + + Autoload + Încărcare automată + + + + Select first available subtitle + Selectați prima subtitrare disponibilă + + + + Same name as movie + Același nume ca și filmul + + + + All subs containing movie name + Subtitrările care conțin numele filmului + + + + All subs in directory + Toate subtitrările din director + + + + Position + Poziționare + + + + 0 + 0 + + + + Top + Sus + + + + Bottom + Jos + + + + Include subtitles on screenshots + Include subtitrarea în captura de ecran + + + + Font + Caractere + + + + Select the font which will be used for subtitles (and OSD): + Selectarea caracterelor ce vor fi folosite pentru subtitrări (și OSD): + + + + Size + Dimensiune + + + + No autoscale + Fără autoscalare + + + + Proportional to movie height + Proporțională cu înălțimea filmului + + + + Proportional to movie width + Proporțională cu lățimea filmului + + + + Proportional to movie diagonal + Proporțională cu diagonala filmului + + + + Subtitle position + Poziție subtitrare + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Această opțiune specifică poziția subtitrării pe ecran. <i>100</i> reprezintă partea de jos, în timp ce <i>0</i> reprezintă partea de sus a ecranului. + + + + Au&toload subtitles files (*.srt, *.sub...): + Încărcare au&tomată fișiere subtitrări (*.srt, *.sub...): + + + + S&elect first available subtitle + S&electează prima subtitrare disponibilă + + + + &Default subtitle encoding: + Co&dificarea implicită subtitrare: + + + + Default &position of the subtitles on screen + &Poziționarea implicită a subtitrării pe ecran + + + + &Include subtitles on screenshots + &Include subtitrarea în captura de ecran + + + + &TTF font: + Caractere &TTF: + + + + S&ystem font: + Caractere imp&licite ale sistemului: + + + + A&utoscale: + A&utoscalare: + + + + Default subtitle encoding + Codificarea implicită pentru subtitrare + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Dacă această opțiune este selectată atunci subtitrarea va apărea în captura de ecran. De notat că uneori această opțiune poate cauza probleme. + + + + TTF font + Caractere TTF + + + + System font + Caractere sistem + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Aici puteți selecta un set de caractere ale sistemului pentru a le folosi pentru subtitrări și pentru afișajul de pe ecran (OSD). <b>De reținut:</b> este nevoie de o versiune MPlayer care să ofere suport pentru configurarea caracterelor. + + + + Autoscale + Autoscalare + + + + Text color + Culoare text + + + + Select the color for the text of the subtitles. + Selectați culoarea textului folosit pentru subtitrare. + + + + Border color + Culoare bandă + + + + Select the color for the border of the subtitles. + Selectați culoarea benzii pe care este scrisă subtitrarea. + + + + Select the subtitle autoload method. + Selectați metoda de încărcare automată a subtitrării. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Dacă există una sau mai multe subtitrări disponibile, una dintre ele va fi selectată automat, de regulă aceasta este prima, dar dacă una din ele corespunde preferințelor utilizatorului referitoare la limba subtitrării atunci va fi folosită aceasta. + + + + Select the subtitle autoscaling method. + Selectați metoda de autoscalare a subtitrării. + + + + Select the encoding which will be used for subtitle files by default. + Selectați codarea care va fi folosită implicit pentru fișierele de subtitrări. + + + + Try to autodetect for this language + Pentru această limbă se va înceca autodetectarea + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Când este activată această opțiune, se va încerca autodetectarea codării pentru subtitrare pentru limba selectată. Dacă autodetectarea eșuează se va folosi codarea implicită a programului. Această opțiune are nevoie de MPlayer compilat cu suport ENCA. + + + + Subtitle language + Limbă subtitrare + + + + Select the language for which you want the encoding to be guessed automatically. + Selectați limba pentru care doriți să se facă detectarea automată a codării. + + + + Encoding + Codare + + + + Try to a&utodetect for this language: + Încercați a&utodetectarea pentru această limbă: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Aici puteți selecta un caracter de tip ttf pentru a fi folosit pentru subtitrare. De regulă veți găsi multe caractere în format ttf în %1 + + + + Outline + Contur + + + + Select the font for the subtitles. + Seletați caracterele pentru subtitrări. + + + + The size in pixels. + Dimensiunea în pixeli. + + + + Bold + Aldine + + + + If checked, the text will be displayed in <b>bold</b>. + Dacă este selectată aceasta opțiune textul va fi afișat cu <b>aldine</b>. + + + + Italic + Italice + + + + If checked, the text will be displayed in <i>italic</i>. + Dacă este selectată aceasta opțiune textul va fi afișat cu <b>italice</b>. + + + + Left margin + Limita stânga + + + + Specifies the left margin in pixels. + Specifică limita din stânga în pixeli. + + + + Right margin + Limita dreapta + + + + Specifies the right margin in pixels. + Specifică limita din dreapta în pixeli. + + + + Vertical margin + Limita verticală + + + + Specifies the vertical margin in pixels. + Specifică limita pe verticală în pixeli. + + + + Horizontal alignment + Aliniere pe orizontală + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + Specifică alinierea pe orizontală. Valorile posibile sunt stânga, centru și dreapta. + + + + Vertical alignment + Aliniere pe verticală + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + Specifică alinierea pe verticală. Valorile posibile sunt jos, mijloc și sus. + + + + Border style + Stil chenar + + + + Specifies the border style. Possible values: outline and opaque box. + Specifică stilul chenarului. Valorile posibile sunt contur și bandă opacă. + + + + Shadow + Umbră + + + + Si&ze: + Di&mensiune: + + + + Bol&d + Al&dine + + + + &Italic + &Italice + + + + Colors + Culori + + + + &Text: + &Text: + + + + &Border: + C&henar: + + + + Margins + Limite + + + + L&eft: + Stân&ga: + + + + &Right: + D&reapta: + + + + Verti&cal: + Verti&cală: + + + + Alignment + Aliniere + + + + &Horizontal: + &Orizontală: + + + + &Vertical: + &Verticală: + + + + Border st&yle: + Sti&l chenar: + + + + &Outline: + Co&ntur: + + + + Shado&w: + &Umbră: + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + Următoarele opțiuni vă permit să definiți stillul pentru subtitrările fără stil (srt, sub, ...). + + + + Left + horizontal alignment + Stânga + + + + Centered + horizontal alignment + Centrat + + + + Right + horizontal alignment + Dreapta + + + + Bottom + vertical alignment + Jos + + + + Middle + vertical alignment + Mijloc + + + + Top + vertical alignment + Sus + + + + Outline + border style + Contur + + + + Opaque box + border style + Bandă opacă + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + Dacă stilul selectat este <i>contur</i>, atunci această opțiune specifică lățimea conturului din jurul textului, în pixeli. + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + Dacă stilul selectat este <i>contur</i>, atunci această opțiune specifică nivelul de umbrire din spatele textului, în pixeli. + + + + Enable normal subtitles + Activare subtitrare normală + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + Apăsati acest buton pentru a selecta afișarea normală/tradițională a subtitrărilor. În acest mod textul subtitrărilor va fi doar de culoare albă. + + + + Enable SSA/ASS subtitles + Activare subtitrări SSA/ASS + + + + Normal subtitles + Subtitrare normală + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + Această opțiune NU modifică mărimea subtitrării pentru fișierul video curent. Pentru a realiza acest lucru folosiți opțiunile <i>Dimensiune+</i> și <i>Dimensiune-</i> din meniul subtitrări. + + + + Default scale + Mărime implicită + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + Această opțiune specifică mărimea implicită pentru caracterele subtitrărilor normale, ce va fi folosită pentru fișierele nou deschise. + + + + SSA/ASS subtitles + Subtitrări SSA/ASS + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + Această opțiune specifică scara implicită pentru caracterele subtitrărilor SSA/ASS, ce va fi folosită pentru fișierele nou deschise. + + + + Line spacing + Separare linii + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + Această opțiune specifică modul de separare folosit în cazul liniilor multiple. Poate lua valori negative. + + + + &Font and colors + C&aractere și culori + + + + Enable &normal subtitles + Activare subtitrare &normală + + + + Enable SSA/&ASS subtitles + Activare subtitrări SSA/&ASS + + + + Default s&cale: + &Mărime implicită: + + + + Defa&ult scale: + Mărim&e implicită: + + + + &Line spacing: + Separare &linii: + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + Apăsați acest buton pentru a activa noua bibliotecă SSA/ASS. Aceasta vă va permite să afișati subtitrări cu mai multe culori, caractere... + + + + Freetype support + Suport caractere freetype + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + În mod normal nu trebuie să dezactivați această opțiune. Puteți face acest lucru doar dacă MPlayer este compilat fără suport pentru caractere freetype. <b>Dezactivarea acestei opțiuni poate duce la imposibilitatea afișării subtitrării!</b> + + + + Freet&ype support + Suport caractere freet&ype + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + Ajutor - SMPlayer + + + + OK + OK + + + + Cancel + Renunţare + + + + Apply + Validare + + + + Help + Ajutor + + + + SMPlayer - Preferences + SMPlayer - Opţiuni_Preferate + + + + QObject + + + This is SMPlayer v. %1 running on %2 + Acesta este SMPlayer v. %1 rulând pe %2 + + + + the main window will be closed when the file/playlist finishes. + fereastra principală se va închide când lista de titluri a ost epuizată. + + + + will show this message and then will exit. + va afişa conţinutul acestui mesaj. + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + încearcă să stabilească legătura cu altă sesiune care şi să trimită către aceasta comanda specificată. Exemplu: -action pause Restul opţiunilor (dacă există) vor fi ignorate şi aplicaţia se va închide. Se va returna 0 în caz de reuşită şi -1 în caz de eşec. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + listă_acţiuni este o enumerare de acţiuni (comenzi) separate de spaţii. Comenzile vor fi executate imediat după încărcarea fişierului media (dacă există vreunul) în aceeaşi ordine în care au fost scrise. Pentru comenzile ce pot fi bifate se pot pune ca parametrii true sau false. Exemplu: -actions "fullscreen compact true". Ghilimelele sunt necesare în cazul în care scrieţi mai mult de o acţiune (comandă). + + + + media + tip_media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + dacă este o altă sesiune deschisă, fişierul media va fi adăugat la lista de titluri a acelei sesiuni. Dacă nu este altă sesiune deschisă această opţiune va fi ignorată şi fişiele vor fi deschise într-o nouă sesiune. + + + + the main window won't be closed when the file/playlist finishes. + fereastra principală nu se va închide după ce fişierul sau lista se termină. + + + + the video will be played in fullscreen mode. + fişierul video va fi redat pe tot ecranul. + + + + the video will be played in window mode. + fişierul video va fi redat în fereastra principală. + + + + Enqueue in SMPlayer + Listă de aşteptare în SMPlayer + + + + opens the mini gui instead of the default one. + deschide interfaţa în miniatură în locul celei implicite. + + + + Restores the old associations and cleans up the registry. + Restaurează vechile asocieri şi curăţă regiştrii. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' reprezintă orice tip de fișier pe care SMPlayer îl poate deschide. Poate fi un fișier local, un DVD (ex. dvd://1), o transmisie de internet (ex. mms://...) sau o listă de titluri locală în format m3u sau pls. Dacă este folosită opțiunea -playlist înseamnă că SMPlayer va transfera opțiunea -playlist către MPlayer, astfel MPlayer va gestiona lista de titluri și nu SMPlayer. + + + + Usage: + Utilizare: + + + + directory + director + + + + action_name + + + + + action_list + + + + + opens the default gui. + deschide interfața grafică implicită. + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + specifică fișierul ce conține subtitrarea ce va fi încărcat pentru primul film. + + + + %1 second(s) + + %1 secundă + %1 secunde + + + + + %1 minute(s) + + %1 minut + %1 minute + + + + + %1 and %2 + %1 și %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + specifică directorul în care smplayer va memora fișierele sale de configurare (smplayer.ini, smplayer_files.ini...) + + + + disabled + aspect_ratio + dezactivat + + + + auto + aspect_ratio + automat + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + Eroare API ZIP/UNZIP %1 + + + + SeekWidget + + + icon + Iconiţă + + + + label + etichetă + + + + ShortcutGetter + + + Modify shortcut + Modificare acces rapid + + + + Clear + Ștergere + + + + Press the key combination you want to assign + Acționați combinația de taste pe care doriți să o alocați + + + + Capture + Captură + + + + Capture keystrokes + Combinație taste captură + + + + SubChooserDialog + + + Subtitle selection + Selecție subtitrare + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Această arhivă conține mai mult de un fișier de subtitrare. Alegeți subtitrarea pe care doriți să o extrageți. + + + + Select All + Selectați tot + + + + Select None + Niciunul selectat + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Derulare + + + + &Jump to: + &Salt la: + + + + TristateCombo + + + Auto + Automat + + + + Yes + Da + + + + No + Nu + + + + VideoEqualizer + + + Contrast + Contrast + + + + Brightness + Strălucire + + + + Hue + Culoare + + + + Saturation + Saturație + + + + Gamma + Gamma + + + + &Reset + &Valori_implicite + + + + &Set as default values + &Selectează ca valoari implicite + + + + Use the current values as default values for new videos. + Folosire valori curente ca valori implicite pentru fișiere video noi. + + + + Set all controls to zero. + Selectează butoanele de control la zero. + + + + Video Equalizer + Egalizor video + + + + Information + Informații + + + + The current values have been stored to be used as default. + Valorile curente au fost memorate pentru a fi folosite ca valori implicite. + + + + VideoPreview + + + Video preview + + + + + Cancel + + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Eroare la salvarea fișierului + + + + The file couldn't be saved + Fișierul nu aputut fi salvat + + + + Error + Eroare + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + Format imagine: %1 + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Valori implicite + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Volum + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_ru_RU.ts b/plugins/smplayer_plugin/translations/smplayer_ru_RU.ts new file mode 100644 index 000000000..bc49c0967 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_ru_RU.ts @@ -0,0 +1,7396 @@ + + + + + About + + + Version: %1 + Версия: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Это свободное программное обеспечение; Вы можете распространять и/или изменять его, руководствуясь 2-ой или (на ваше усмотрение) более поздней версией GNU General Public License опубликованной Free Software Foundation. + + + + The following people have contributed with translations: + Следующие люди внесли вклад своими переводами: + + + + German + Немецкий + + + + Slovak + Словацкий + + + + Italian + Итальянский + + + + French + Французский + + + + %1, %2 and %3 + %1, %2 и %3 + + + + Simplified-Chinese + Упрощённый китайский + + + + Russian + Русский + + + + %1 and %2 + %1 и %2 + + + + Hungarian + Венгерский + + + + Polish + Польский + + + + Japanese + Японский + + + + Dutch + Немецкий + + + + Ukrainian + Украинский + + + + Portuguese - Brazil + Португальский (Бразилия) + + + + Georgian + Грузинский + + + + Czech + Чешский + + + + Bulgarian + Болгарский + + + + Turkish + Турецкий + + + + Swedish + Шведский + + + + Serbian + Сербский + + + + Traditional Chinese + Китайский традиционный + + + + Romanian + Румынский + + + + Portuguese - Portugal + Португальский (Португалия) + + + + Greek + Греческий + + + + Finnish + Финский + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Об SMPlayer + + + + &Info + &Информация + + + + icon + значок + + + + &Contributions + &Участие в разработке + + + + &Translators + Пере&водчики + + + + &License + &Лицензия + + + + Visit our web for updates: + Посетить наш сайт для обновлений: + + + + Get help in our forum: + Получить помощь на форуме: + + + + You can support SMPlayer by making a donation. + Вы можете поддержать SMPlayer путём пожертвования. + + + + More info + Дополнительная информация + + + + Korean + Корейский + + + + Macedonian + Македонский + + + + Basque + Баскский + + + + Using MPlayer %1 + Используется MPlayer %1 + + + + Catalan + Каталонский + + + + Portable Edition + Переносной вариант + + + + Using Qt %1 (compiled with Qt %2) + Используется Qt %1 (cкомпилировано с Qt %2) + + + + Slovenian + Словенский + + + + Arabic + Арабский + + + + Kurdish + Курдский + + + + Galician + Галийский + + + + The following people have contributed with patches (see the changelog for details): + Следующие люди внесли вклад своими патчами (смотрите список изменений для подробностей): + + + + If there's any omission, please report. + Пожалуйста, сообщите в случае каких-либо упущений. + + + + SMPlayer logo by %1 + Иконка SMPlayer от %1 + + + + %1, %2, %3 and %4 + %1, %2, %3 и %4 + + + + %1, %2, %3, %4 and %5 + %1, %2, %3, %4 и %5 + + + + ActionsEditor + + + Name + Имя + + + + Description + Описание + + + + Shortcut + Горячая клавиша + + + + &Save + &Сохранить + + + + &Load + &Загрузить + + + + Key files + Горячие клавиши + + + + Choose a filename + Выберите имя файла + + + + Confirm overwrite? + Перезаписать? + + + + The file %1 already exists. +Do you want to overwrite? + Файл %1 существует. +Перезаписать? + + + + Choose a file + Выбрать файл + + + + Error + Ошибка + + + + The file couldn't be saved + Файл не может быть сохранен + + + + The file couldn't be loaded + Файл не может быть загружен + + + + &Change shortcut... + Изменить &сочетание клавиш... + + + + AudioEqualizer + + + Audio Equalizer + Аудиоэквалайзер + + + + 31.25 Hz + 31.25 Гц + + + + 62.50 Hz + 62.50 Гц + + + + 125.0 Hz + 125.0 Гц + + + + 250.0 Hz + 250.0 Гц + + + + 500.0 Hz + 500.0 Гц + + + + 1.000 kHz + 1.000 кГц + + + + 2.000 kHz + 2.000 кГц + + + + 4.000 kHz + 4.000 кГц + + + + 8.000 kHz + 8.000 кГц + + + + 16.00 kHz + 16.00 кГц + + + + &Apply + &Применить + + + + &Reset + Сб&рос + + + + &Set as default values + Сохранить как &значения по умолчанию + + + + Use the current values as default values for new videos. + Использовать данные настройки по умолчанию для новых файлов. + + + + Set all controls to zero. + Установить все значения в ноль. + + + + Information + Информация + + + + The current values have been stored to be used as default. + Текущие параметры были сохранены как используемые по умолчанию. + + + + BaseGui + + + &File... + &Файл... + + + + D&irectory... + Ката&лог... + + + + &Playlist... + &Список... + + + + &DVD from drive + DVD с &привода + + + + D&VD from folder... + DVD из &каталога... + + + + &URL... + А&дрес... + + + + P&lay + &Воспроизведение + + + + &Pause + &Пауза + + + + &Stop + &Стоп + + + + &Frame step + По&кадрово + + + + &Repeat + Пов&торить + + + + &Normal speed + &Нормальная скорость + + + + &Halve speed + &Половинная скорость + + + + &Double speed + &Удвоенная скорость + + + + Speed &-10% + Скорос&ть –10% + + + + Speed &+10% + Скорост&ь +10% + + + + Sp&eed + Ск&орость + + + + &Fullscreen + Н&а весь экран + + + + &Compact mode + &Компактный режим + + + + &Equalizer + &Эквалайзер + + + + &Screenshot + С&нимок экрана + + + + S&tay on top + Повер&х других окон + + + + &Postprocessing + &Постобработка + + + + &Autodetect phase + &Автоопределение фазы + + + + &Deblock + Смазывание границ &квадратов + + + + De&ring + Удаление к&раевых артефактов + + + + Add n&oise + Добавление &шума + + + + F&ilters + Ф&ильтры + + + + &Mute + Выключит&ь звук + + + + Volume &- + Г&ромкость – + + + + Volume &+ + Гр&омкость + + + + + &Delay - + &Задержка – + + + + D&elay + + З&адержка + + + + + &Extrastereo + &Расширенное стерео + + + + &Karaoke + &Караоке (подавление голоса) + + + + &Filters + &Фильтры + + + + &Load... + Загрузить из &файла... + + + + Delay &- + &Задержка – + + + + Delay &+ + З&адержка + + + + + &Up + В&верх + + + + &Down + В&низ + + + + &Playlist + &Список воспроизведения + + + + &Show frame counter + Показать счетчик &кадров + + + + P&references + &Настройки + + + + &View logs + Смотреть от&чёты + + + + About &Qt + &О Qt + + + + About &SMPlayer + О&б SMPlayer + + + + &Open + &Открыть + + + + &Play + Вос&произведение + + + + &Video + &Видео + + + + &Audio + &Звук + + + + &Subtitles + &Субтитры + + + + &Browse + О&бзор + + + + Op&tions + &Настройки + + + + &Help + Сп&равка + + + + &Recent files + Посл&едние файлы + + + + &Clear + О&чистить + + + + Si&ze + &Размер видео + + + + &Aspect ratio + &Соотношение сторон + + + + &Deinterlace + &Удаление "гребёнки" + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &к 16:9 + + + + &None + &Ничего + + + + &Lowpass5 + Lowpass&5 + + + + Linear &Blend + Линейное &смешивание + + + + &Channels + &Каналы + + + + &Stereo mode + &Стерео режим + + + + &Stereo + &Стерео + + + + &4.0 Surround + &4.0 окружение + + + + &5.1 Surround + &5.1 окружение + + + + &Left channel + &Левый канал + + + + &Right channel + &Правый канал + + + + &Select + Вы&брать + + + + &Title + &Заголовок + + + + &Chapter + &Глава + + + + &Angle + &Ракурс + + + + &OSD + &Вид OSD + + + + &Disabled + Запре&щено + + + + &Seek bar + &Прогресс + + + + &Time + &Время + + + + Time + T&otal time + Время / О&бщее время + + + + SMPlayer - mplayer log + SMPlayer – отчёт mplayer + + + + SMPlayer - smplayer log + SMPlayer – отчёт smplayer + + + + <empty> + <ничего> + + + + Video + Видео + + + + Audio + Звук + + + + Playlists + Список + + + + All files + Все файлы + + + + Choose a file + Выбрать файл + + + + SMPlayer - Information + SMPlayer – Информация + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Приводы CD/DVD еще не настроены. +Вы сможете сделать это в диалоге настроек этих устройст. + + + + Choose a directory + Выбрать каталог + + + + Subtitles + Субтитры + + + + About Qt + О Qt + + + + Playing %1 + Воспроизводится %1 + + + + Pause + Пауза + + + + Stop + Стоп + + + + Play / Pause + Воспроизведение / Пауза + + + + Pause / Frame step + Пауза / Покадровый просмотр + + + + U&nload + В&ыгрузить + + + + V&CD + &Видео CD + + + + C&lose + &Закрыть + + + + View &info and properties... + Ин&формация и параметры... + + + + Zoom &- + Ув&еличение – + + + + Zoom &+ + &Увеличение + + + + + &Reset + Сб&рос + + + + Move &left + Переместить в&лево + + + + Move &right + Переместить в&право + + + + Move &up + Переместить в&верх + + + + Move &down + Переместить в&низ + + + + &Pan && scan + &Панорама вручную + + + + &Previous line in subtitles + &Предыдущая фраза + + + + N&ext line in subtitles + С&ледующая фраза + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Уменьшить громкость (2) + + + + Inc volume (2) + Увеличить громкость (2) + + + + Exit fullscreen + Выйти из поноэкранного режима + + + + OSD - Next level + OSD – Следующая фраза + + + + Dec contrast + Уменьшить контраст + + + + Inc contrast + Повысить контраст + + + + Dec brightness + Уменьшить яркость + + + + Inc brightness + Повысит яркость + + + + Dec hue + Оттенок вперёд + + + + Inc hue + Оттенок назад + + + + Dec saturation + Уменьшить насыщенность + + + + Dec gamma + Уменьшить гамму + + + + Next audio + Следующая звуковая дорожка + + + + Next subtitle + Следующая фраза + + + + Next chapter + Следующий раздел + + + + Previous chapter + Предыдущий раздел + + + + Inc saturation + Повысить насыщенность + + + + Inc gamma + Повысить гамму + + + + &Load external file... + За&грузить из файла... + + + + &Kerndeint + &Адаптивное (mplayer) + + + + &Yadif (normal) + Yadif (&обычный) + + + + Y&adif (double framerate) + Yadif (2× &частота кадров) + + + + &Next + С&ледующий + + + + Pre&vious + П&редыдущий + + + + Volume &normalization + &Нормализация звука + + + + &Audio CD + &Аудио CD + + + + Denoise nor&mal + Убрать шумы – &обычный + + + + Denoise &soft + Убрать шумы – &мягкий + + + + Denoise o&ff + Убрать шумы – &выключено + + + + Use SSA/&ASS library + &Использовать SSA/ASS + + + + Flip i&mage + П&еревернуть картинку + + + + &Toggle double size + &Двойной размер + + + + S&ize - + Р&азмер – + + + + Si&ze + + Ра&змер + + + + + Add &black borders + Добавить &чёрные полосы + + + + Soft&ware scaling + Про&граммное масштабирование + + + + &FAQ + FAQ (Ч&АВО) + + + + Visualize &motion vectors + Векторы &движения + + + + &Command line options + Опции командной &строки + + + + SMPlayer command line options + Опции командной строки SMPlayer + + + + Enable &closed caption + &Скрытые субтитры + + + + &Forced subtitles only + &Только форсированные + + + + Reset video equalizer + Сброс видеоэквалайзера + + + + MPlayer has finished unexpectedly. + Неожиданное завершение MPlayer. + + + + Exit code: %1 + Код ошибки: %1 + + + + MPlayer failed to start. + Ошибка запуска MPlayer. + + + + Please check the MPlayer path in preferences. + Провертье путь к MPlayer в настройках. + + + + MPlayer has crashed. + Сбой MPlayer. + + + + See the log for more info. + Смотрите отчёт для подробной информации. + + + + &Rotate + По&ворот + + + + &Off + О&тключен + + + + &Rotate by 90 degrees clockwise and flip + На 90° по часовой стрелке с &отражением + + + + Rotate by 90 degrees &clockwise + На 90° &по часовой стрелке + + + + Rotate by 90 degrees counterclock&wise + На 90° п&ротив часовой стрелки + + + + Rotate by 90 degrees counterclockwise and &flip + На 90° против часовой &стрелки с отражением + + + + &Jump to... + П&ерейти к... + + + + Show context menu + Показать контестное меню + + + + Multimedia + Мультимедиа + + + + E&qualizer + &Эквалайзер + + + + Reset audio equalizer + Сброс аудиоэквалайзера + + + + Find subtitles on &OpenSubtitles.org... + П&оиск субтитров на OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Загрузить су&бтитры на OpenSubtitles.org... + + + + &Tips + &Подсказки + + + + &Auto + &Авто + + + + Speed -&4% + Скор&ость –4% + + + + &Speed +4% + Скоро&сть +4% + + + + Speed -&1% + &Скорость –1% + + + + S&peed +1% + С&корость +1% + + + + Scree&n + &Экран + + + + &Default + По &умолчанию + + + + Mirr&or image + &Зеркальное изображение + + + + Next video + Следующий видеофайл + + + + &Track + video + &Дорожка + + + + &Track + audio + &Дорожка + + + + Warning - Using old MPlayer + Предупреждение: Используется старая версия MPlayer + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + Установленная в вашей системе версия MPlayer (%1) устарела. SMPlayer не может работать с ней достаточно хорошо: некотрые опции не будут работать, выбор субтитров может вызывать ошибку... + + + + Please, update your MPlayer. + Пожалуйста, обновите ваш MPlayer. + + + + (This warning won't be displayed anymore) + (Это предупреждение больше не будет показано) + + + + Next aspect ratio + Следующее соотношение сторон + + + + &Auto zoom + &Автоувеличение + + + + Auto zoom for &16:9 + Автоувеличение для &16:9 + + + + Auto zoom for &2.35:1 + Автоувеличение для &2.35:1 + + + + Zoom for &16:9 + Увеличение для &16:9 + + + + Zoom for &2.35:1 + Увеличение для &2.35:1 + + + + Pre&view... + Предпрос&мотр... + + + + &Always + &Всегда наверху + + + + &Never + &Отключено + + + + While &playing + При про&игрывании + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer всё ещё запущен + + + + S&how icon in system tray + &Значок в системном лотке + + + + &Hide + &Убрать + + + + &Restore + &Восстановить + + + + &Quit + В&ыход + + + + Playlist + Список + + + + Core + + + Brightness: %1 + Яркость: %1 + + + + Contrast: %1 + Контрастность: %1 + + + + Gamma: %1 + Гамма: %1 + + + + Hue: %1 + Оттенок: %1 + + + + Saturation: %1 + Насыщенность: %1 + + + + Volume: %1 + Громкость: %1 + + + + Zoom: %1 + Увеличение: %1 + + + + Font scale: %1 + Масштаб шрифта: %1 + + + + Aspect ratio: %1 + Соотношение сторон: %1 + + + + Updating the font cache. This may take some seconds... + Обновление кэша шрифтов. Это может занять несколько секунд... + + + + DefaultGui + + + Welcome to SMPlayer + Добро пожаловать в SMPlayer + + + + Audio + Звук + + + + Subtitle + Субтитры + + + + &Main toolbar + &Главная панель + + + + &Language toolbar + &Языковая панель + + + + &Toolbars + &Панели + + + + EqSlider + + + icon + значок + + + + ErrorDialog + + + Hide log + Скрыть отчёт + + + + Show log + Показать отчёт + + + + MPlayer Error + Ошибка MPlayer + + + + icon + значок + + + + Error + Ошибка + + + + FileDownloader + + + Downloading... + Загрузка... + + + + Downloading %1 + Загрузка %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer – Параметры файла + + + + &Information + &Информация + + + + &Demuxer + &Демультиплексор + + + + &Select the demuxer that will be used for this file: + В&ыберите демультиплексор для воспроизведения этого файла: + + + + &Reset + Сб&рос + + + + &Video codec + В&идео + + + + &Select the video codec: + Вы&берите видео кодек: + + + + A&udio codec + А&удио + + + + &Select the audio codec: + Выб&ерите аудио кодек: + + + + &MPlayer options + Настройки &MPlayer + + + + Additional Options for MPlayer + Дополнительные параметры Mplayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Здесь можно указать дополнительные параметры для MPlayer. +Указывайте их, разделяя пробелами. +Например: -flip -nosound + + + + &Options: + &Настройки: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Также Вы можете передать дополнительные фильтры видео. +Разделяйте их запятой. Не используйте пробелы! +Пример: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + &Видео фильтры: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Аудио фильтры. Используются аналогично видео фильтрам. +Пример: resample=44100:0:0,volnorm + + + + Audio &filters: + Аудио &фильтры: + + + + OK + OK + + + + Cancel + Отмена + + + + Apply + Применить + + + + FindSubtitlesWindow + + + Language + Язык + + + + Name + Имя + + + + Format + Формат + + + + Files + Файлы + + + + Date + Дата + + + + Uploaded by + Загружено + + + + All + Все + + + + Close + Закрыть + + + + &Download + &Загрузить + + + + &Copy link to clipboard + &Копировать ссылку в буфер обмена + + + + Error + Ошибка + + + + Download failed: %1. + Ошибка загузки: %1. + + + + Connecting to %1... + Соединение с %1... + + + + Downloading... + Загрузка... + + + + Done. + Завершено. + + + + %1 files available + %1 файлов доступно + + + + Failed to parse the received data. + Ошибка обработки полученных данных. + + + + Find Subtitles + Найти субтитры + + + + &Subtitles for + &Субтитры для + + + + &Language: + &Язык: + + + + &Refresh + &Обновить + + + + Subtitle saved as %1 + Субтиры сохранены как %1 + + + + %1 subtitle(s) extracted + + %1 субтитр(а,ов) извлечено + + + + + + + Overwrite? + Перезаписать? + + + + The file %1 already exits, overwrite? + Файл %1 существует, перезаписать? + + + + Error saving file + Ошибка сохранения файла + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Не удалось сохранить загруженный +файл в каталоге %1 +Проверьте права на этот каталог. + + + + Download failed + Ошибка загрузки + + + + Temporary file %1 + Временный файл %1 + + + + InfoFile + + + General + Основная информация + + + + Size + Размер + + + + %1 KB (%2 MB) + %1 КБ (%2 МБ) + + + + URL + Адрес + + + + Length + Продолжительность + + + + Demuxer + Демультиплексор + + + + Name + Имя + + + + Artist + Исполнитель + + + + Author + Автор + + + + Album + Альбом + + + + Genre + Жанр + + + + Date + Дата + + + + Track + Дорожка + + + + Copyright + Авторское право + + + + Comment + Примечание + + + + Software + Программа + + + + Clip info + Информация о клипе + + + + Video + Видео + + + + Resolution + Разрешение экрана + + + + Aspect ratio + Соотношение сторон + + + + Format + Формат + + + + Bitrate + Битрейт + + + + %1 kbps + %1 кб/с + + + + Frames per second + Кадров в секунду + + + + Selected codec + Выбранный кодек + + + + Initial Audio Stream + Звуковая дорожка по умолчанию + + + + Rate + Частота + + + + %1 Hz + %1 Гц + + + + Channels + Каналы + + + + Audio Streams + Звуковые дорожки + + + + Language + Язык + + + + empty + ничего + + + + Subtitles + Субтитры + + + + Type + Тип + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + + + + + Stream title + Название потока + + + + Stream URL + Адрес потока + + + + File + Файл + + + + InputDVDDirectory + + + Choose a directory + Выбрать каталог + + + + SMPlayer - Play a DVD from a folder + SMPlayer – Воспроизвести DVD из каталога + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Вы можете открыть DVD с жесткого диска. Выберите каталог, содержащий VIDEO_TS и AUDIO_TS. + + + + Choose a directory... + Обзор... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer – укажите версию MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer не может определить используемую вами версию MPlayer. + + + + Version reported by MPlayer: + Версия, полученная от MPlayer: + + + + Please, &select the correct version: + Пожалуйста, &выберите правильную версию: + + + + 1.0rc1 or older + 1.0rc1 или старше + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Выше чем 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer – укажите адрес + + + + &URL: + &Адрес: + + + + It's a &playlist + &Cписок воспроизведения + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Если опция отмечена, адрес будет воспринят как список: он будет открыть как текст и будут воспроизведены адреса из него. + + + + Languages + + + Afar + Все + + + + Abkhazian + Абхазский + + + + Afrikaans + Африкаанс + + + + Amharic + Амхарский + + + + Arabic + Арабский + + + + Assamese + Ассамский + + + + Aymara + Аймара + + + + Azerbaijani + Азербайджанский + + + + Bashkir + Башкирский + + + + Byelorussian + Белорусский + + + + Bulgarian + Болгарский + + + + Bihari + Бихари + + + + Bislama + Бислама + + + + Bengali + Бенгальский + + + + Tibetan + Тибетский + + + + Breton + Бретонский + + + + Catalan + Каталонский + + + + Corsican + Корсиканский + + + + Czech + Чешский + + + + Welsh + Валлийский + + + + Danish + Датский + + + + German + Немецкий + + + + Bhutani + Бутанский + + + + Greek + Греческий + + + + English + Английский + + + + Esperanto + Эсперанто + + + + Spanish + Испанский + + + + Estonian + Эстонский + + + + Basque + Баскский + + + + Persian + Персидский + + + + Finnish + Финский + + + + Fiji + Фиджи + + + + Faroese + Фарерский + + + + French + Французский + + + + Frisian + Фризский + + + + Irish + Ирландский + + + + Scots + Шотландский + + + + Galician + Галийский + + + + Guarani + Гуарани + + + + Gujarati + Гуджарати + + + + Hausa + Хауса + + + + Hebrew + Иврит + + + + Hindi + Хинди + + + + Croatian + Хорватский + + + + Hungarian + Венгерский + + + + Armenian + Армянский + + + + Interlingua + Интерлингва + + + + Indonesian + Индонезийский + + + + Interlingue + Интерлингва + + + + Inupiak + Эскимосский + + + + Icelandic + Ирландский + + + + Italian + Итальянский + + + + Inuktitut + Инуктитут + + + + Japanese + Японский + + + + Javanese + Яванский + + + + Georgian + Грузинский + + + + Kazakh + Казахский + + + + Greenlandic + Гренландский + + + + Cambodian + Камбоджийский + + + + Kannada + Каннада + + + + Korean + Корейский + + + + Kashmiri + Кашмирский + + + + Kurdish + Курдский + + + + Kirghiz + Киргизский + + + + Latin + Латинский + + + + Lingala + Лингала + + + + Laothian + Лаосский + + + + Lithuanian + Литовский + + + + Latvian + Латвийский + + + + Malagasy + Малагасийский + + + + Maori + Маори + + + + Macedonian + Македонский + + + + Malayalam + Малаялам + + + + Mongolian + Монгольский + + + + Moldavian + Молдавский + + + + Marathi + Маратхи + + + + Malay + Малайский + + + + Maltese + Мальтийский + + + + Burmese + Бирманский + + + + Nauru + Науру + + + + Nepali + Непальский + + + + Dutch + Немецкий + + + + Norwegian + Норвежский + + + + Occitan + Окситанский + + + + Oriya + Ория + + + + Punjabi + Панджаби + + + + Polish + Польский + + + + Pashto + Пашто + + + + Portuguese + Португальский + + + + Quechua + Кечуа + + + + Kirundi + Кирунди + + + + Romanian + Румынский + + + + Russian + Русский + + + + Kinyarwanda + Киньяруанда + + + + Sanskrit + Санскрит + + + + Sindhi + Синдхи + + + + Sangho + Санго + + + + Sinhalese + Сингальский + + + + Slovak + Словацкий + + + + Slovenian + Словенский + + + + Samoan + Тонга + + + + Shona + Шона + + + + Somali + Сомалийский + + + + Albanian + Албанский + + + + Serbian + Сербский + + + + Siswati + Сисвати + + + + Sesotho + Сесото + + + + Sundanese + Суданский + + + + Swedish + Шведский + + + + Swahili + Суахили + + + + Tamil + Тамил + + + + Telugu + Телугу + + + + Tajik + Таджикский + + + + Thai + Тайский + + + + Tigrinya + Тиграи + + + + Turkmen + Туркменский + + + + Tagalog + Тагальский + + + + Setswana + Сетсвана + + + + Tonga + Тонга + + + + Turkish + Турецкий + + + + Tsonga + Тсонга + + + + Tatar + Татарский + + + + Twi + Тви + + + + Uighur + Уйгурский + + + + Ukrainian + Украинский + + + + Urdu + Урду + + + + Uzbek + Узбекский + + + + Vietnamese + Вьетнамский + + + + Wolof + Волоф + + + + Xhosa + Коса + + + + Yiddish + Идиш + + + + Yoruba + Йоруба + + + + Zhuang + Чжуан + + + + Chinese + Китайский + + + + Zulu + Зулусский + + + + Portuguese - Brazil + Португальский (Бразилия) + + + + Portuguese - Portugal + Португальский (Португалия) + + + + Simplified-Chinese + Китайский упрощённый + + + + Traditional Chinese + Китайский традиционный + + + + Unicode + Юникод + + + + UTF-8 + UTF-8 + + + + Western European Languages + Восточноевропейская + + + + Western European Languages with Euro + Восточноевропейская с Евро + + + + Slavic/Central European Languages + Славянская/центральноевропейская + + + + Esperanto, Galician, Maltese, Turkish + Эсперанто, Галисийская, Мальтийская, Турецкая + + + + Old Baltic charset + Старая Балтийская + + + + Cyrillic + Кириллица + + + + Modern Greek + Греческая новая + + + + Baltic + Балтийская + + + + Celtic + Кельтская + + + + Hebrew charsets + Иврит + + + + Ukrainian, Belarusian + Украинская, Белорусская + + + + Simplified Chinese charset + Китайская упрощенная + + + + Traditional Chinese charset + Китайская традиционная + + + + Japanese charsets + Японская + + + + Korean charset + Корейская + + + + Thai charset + Тайская + + + + Cyrillic Windows + Кириллица Windows + + + + Slavic/Central European Windows + Славянская/центральноевропейская Windows + + + + Arabic Windows + Арабская Windows + + + + Rhaeto-Romance + Ретророманский + + + + Serbo-Croatian + Сербско-хорватский + + + + Volapük + Волапюк + + + + Avestan + Авестийский + + + + Akan + Акан + + + + Aragonese + Арагонский + + + + Avaric + Аварский + + + + Belarusian + Белорусский + + + + Bambara + Бамана + + + + Bosnian + Боснийский + + + + Chechen + Чеченский + + + + Cree + Кри + + + + Church + Церковный + + + + Chuvash + Чувашский + + + + Divehi + Мальдивский + + + + Dzongkha + Дзонг-кэ + + + + Ewe + Эве + + + + Fulah + Фула + + + + Fijian + Фиджийский + + + + Gaelic + Гойдельский + + + + Manx + Мэнский + + + + Hiri + Хири-моту + + + + Haitian + Гаитянский + + + + Herero + Гереро + + + + Chamorro + Чаморро + + + + Igbo + Игбо + + + + Sichuan + Сычуаньский + + + + Inupiaq + Инуитский + + + + Ido + Идо + + + + Kongo + Конго + + + + Kikuyu + Кикуйю + + + + Kuanyama + Кваньяма + + + + Khmer + Кхмерский + + + + Kanuri + Канури + + + + Komi + Коми + + + + Cornish + Корнский + + + + Luxembourgish + Люксембургский + + + + Ganda + Луганда + + + + Limburgan + Лимбургский + + + + Lao + Лаосский + + + + Luba-Katanga + Луба-Катанга + + + + Marshallese + Маршалльский + + + + Bokmål + Букмол + + + + Ndebele + Ндебеле + + + + Ndonga + Ндонга + + + + Navajo + Навахо + + + + Chichewa + Ньянджа + + + + Ojibwa + Оджибва + + + + Oromo + Оромо + + + + Ossetian + Осетинский + + + + Panjabi + Панджаби + + + + Pali + Пали + + + + Pushto + Пушту + + + + Romansh + Романшский + + + + Rundi + Рунди + + + + Sardinian + Сардинский + + + + Sami + Саамский + + + + Sango + Санго + + + + Sinhala + Сингальский + + + + Swati + Свати + + + + Sotho + Сесото + + + + Tswana + Тсвана + + + + Tahitian + Таитянский + + + + Venda + Венда + + + + Volapük + Волапюк + + + + Walloon + Валлонский + + + + LogWindow + + + Choose a filename to save under + Выберите имя файла для сохранения + + + + Confirm overwrite? + Перезаписать? + + + + The file already exists. +Do you want to overwrite? + Файл существует. +Перезаписать? + + + + Error saving file + Ошибка сохранения файла + + + + The log couldn't be saved + Невозможно сохранить отчёт + + + + Logs + Отчёты + + + + LogWindowBase + + + Log Window + Окно отчёта + + + + Save + Сохранить + + + + Copy to clipboard + Копировать в буфер обмена + + + + Close + Закрыть + + + + &Close + &Закрыть + + + + MiniGui + + + Control bar + Панель управления + + + + MpcGui + + + Control bar + Панель управления + + + + -%1 + –%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Имя + + + + Length + Продолжительность + + + + &Play + Воспро&изведение + + + + &Edit + &Редактировать + + + + Playlists + Список + + + + Choose a file + Выбрать файл + + + + Choose a filename + Выберите имя файла + + + + Confirm overwrite? + Перезаписать? + + + + The file %1 already exists. +Do you want to overwrite? + Файл %1 существует. +Перезаписать? + + + + All files + Все файлы + + + + Select one or more files to open + Выберите один или более файлов + + + + Choose a directory + Выбрать каталог + + + + Edit name + Изменить имя + + + + Type the name that will be displayed in the playlist for this file: + Введите имя, которое будет соответствовать в списке этому файлу: + + + + &Load + &Загрузить + + + + &Save + &Сохранить + + + + &Next + С&ледующий + + + + Pre&vious + П&редыдущий + + + + Move &up + Переместить в&верх + + + + Move &down + Переместить в&низ + + + + &Repeat + Пов&торить + + + + S&huffle + Пере&мешать + + + + Add &current file + Добавить &текущий файл + + + + Add &file(s) + Добавить &файл(ы) + + + + Add &directory + Добавить &каталог + + + + Remove &selected + Убрать в&ыбранные + + + + Remove &all + Убрать в&се + + + + SMPlayer - Playlist + SMPlayer – Список + + + + Add... + Добавить... + + + + Remove... + Убрать... + + + + Playlist modified + Список воспроизведения изменен + + + + There are unsaved changes, do you want to save the playlist? + Есть несохранённые изменения, желаете сохранить список воспроизведения? + + + + Preferences + Настройки + + + + PlaylistPreferences + + + Playlist - Preferences + Список – Настройки + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Выберите эту опцию, если вы хотите, чтобы при добавлении каталога подкаталоги тоже добавлялись рекурсивно. Иначе будут добавлены только файлы из текущего каталога. + + + + &Add files in directories recursively + &Добавлять файлы из каталогов рекурсивно + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Выберите эту опцию, чтобы извлечь из добавляемых в список файлов некоторую информацию. Это позволяет отображать имя (если доступно) и информацию о файлах. Иначе эта информация не будет доступна, пока файл не начнёт воспроизводиться. Будьте осторожны: эта опция может замедлить работу, особенно при большом количестве добавляемых файлов. + + + + Automatically get &info about files added + Автоматически получать &сведения о добавляемых файлах + + + + &Save copy of playlist on exit + Сохранять &копию списка воспроизведения при выходе + + + + &Play files from start + &Воспроизводить файлы при запуске + + + + PrefAdvanced + + + Advanced + Дополнительно + + + + Auto + Авто + + + + &Advanced + &Дополнительно + + + + icon + значок + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Здесь можно указать дополнительные параметры для MPlayer. +Указывайте их разделяя пробелами. +Например: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Также Вы можете передать дополнительные фильтры видео. +Разделять запятой. Не использовать пробелы! +Пример: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Аудио фильтры. Используются аналогично фильтрам видео. +Пример: resample=44100:0:0,volnorm + + + + Log MPlayer output + Отчёт вывода MPlayer + + + + Log SMPlayer output + Отчёт вывода SMPlayer + + + + This option is mainly intended for debugging the application. + Эти настройки в основном необходимы для отладки приложения. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Использование этого параметра может убрать мерцание изображения, однако при этом возможно, неверное отображение видео. + + + + Filter for SMPlayer logs + Фильтр для отчётов SMPlayer + + + + &Monitor aspect: + &Соотношение сторон монитора: + + + + &Run MPlayer in its own window + &Запускать MPlayer в отдельном окне + + + + &Options: + &Настройки: + + + + V&ideo filters: + &Видео фильтры: + + + + Audio &filters: + &Аудио фильтры: + + + + &Colorkey: + &Код цвета: + + + + Log &SMPlayer output + Отчёт &вывода SMPlayer + + + + &Filter for SMPlayer logs: + &Фильтры отчётов SMPlayer: + + + + C&hange... + Из&менить... + + + + Logs + Отчёты + + + + Log MPlayer &output + Отчёт выво&да MPlayer + + + + Options for MP&layer + &Настройки MPlayer + + + + Autosave MPlayer log + Автосохраниение отчёта MPlayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Если отмечено, отчёт MPlayer будет сохранён в специальный файл каждый раз, когда начнётся воспроизведение нового файла. Это может требоваться для внешних приложений, которые получают информацию о воспроизводимом файле. + + + + Autosave MPlayer log filename + Автосохранение имени файла отчёта MPlayer + + + + Enter here the path and filename that will be used to save the MPlayer log. + Введите путь и имя файла, используемого для сохранения отчёта MPlayer. + + + + A&utosave MPlayer log to file + &Автосохранение отчёта MPlayer в файл + + + + Pass short filenames (8+3) to MPlayer + Передавать MPlayer-у короткие (8+3) имена + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + В настоящее время MPlayer не может открывать файлы с именами, содержащими символы вне текущей кодовой таблицы. Выбор этой опции укажет SMPlayer-у передавать MPlayer-у короткие имена файлов, чтобы тот мог открыть их. + + + + &Pass short filenames (8+3) to MPlayer + Передавать MPlayer-у &короткие (8+3) имена + + + + Monitor aspect + Соотношение сторон монитора + + + + Select the aspect ratio of your monitor. + Выберите соотношение сторон монитора. + + + + Run MPlayer in its own window + Запускать MPlayer в отдельном окне + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + При выборе этой опциии окно MPlayer не будет встроено в главное окно SMPlayer, а будет использовать своё собственное окно. Обратите внимание, что события клавиатуры и мыши будут переданы непосредственно MPlayer, что означает, что назначенные горячие клавиши и события мыши могут не работать как нужно, если окно MPlayer находится в фокусе. + + + + Colorkey + Код цвета + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Если вы видете, некоторые части видео на других окнах, вы можете изменить код цвета чтобы исправить это. Попытайтесь выбрать цвет близкий к чёрному. + + + + Options for MPlayer + Настройки MPlayer + + + + Options + Настройки + + + + Here you can type options for MPlayer. Write them separated by spaces. + Здесь можно ввести параметры MPlayer, разделяя их пробелами. + + + + Video filters + Видеофильтры + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Здесь можно добавить видеофильтры, используемые MPlayer. Перечислите их, разделяя запятыми. Не используйте пробелы! + + + + Audio filters + Аудио фильтры + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Здесь можно добавить аудиофильтры, используемые MPlayer. Перечислите их, разделяя запятыми. Не используйте пробелы! + + + + Repaint the background of the video window + Перерисовывать фон окна с видео + + + + Repaint the backgroun&d of the video window + Пере&рисовывать фон окна воспроизведения + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Использовать IPv4 для сетевых соединений. При ошибках переходит на IPv6 автоматически. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Использовать IPv6 для сетевых соединений. При ошибках переходит на IPv4 автоматически. + + + + Network Connection + Сетевое соединение + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + &Отчёты + + + + Rebuild index if needed + Перестроить индекс, если необходимо + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Перестраивает индекс в файлах, в которых индекс не найден, позволяя перематывать их. Полезно для недогруженных/неполных или плохо созданных файлов. Опция работает только если мультимедиа поддерживает перемотку (т.е. не с stdin, pipe, и др). Примечание: создание индекса может занять некоторое время. + + + + Rebuild &index if needed + Перестроить &индекс, если необходимо + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Если эта опция отмечена, SMPlayer сохранит отладочные сообщения в выводе SMPlayer (их можно увидеть в <b>Настройка -> Смотреть отчёты -> SMPlayer</b>). Эта информация может быть полезна разработчикам, если вы нашли баг. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Если выбрано, SMPlayer будет сохранять сообщения MPlayer (их можно просмотреть в <b>Настройки -> Смотреть отчёты -> MPlayer</b>). Отчёты могут содержать важную информацию о возникших проблемах, поэтому рекомендуется включить эту опцию. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Эта опция позволяет фильтровать сообщения SMPlayer, которые сохраняются в отчёте. Здесь вы можете записать любое регулярное выражение. <br>Для примера: <i>^Core::.*</i> будет отображать только строки, начинающиеся с <i>Core::</i> + + + + Correct pts + Точные метки времени + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Переключает MPlayer в экспериментальный режим, в котором тайминг видео кадров рассчитываются независимо, и тем самым поддерживаются видео фильтры, добавляющие новые кадры или меняющие тайминг существующих. Более точный тайминг может быть заметен, например, при воспроизведении с опцией −ass субтитров, привязанных к смене сцены, Без −correct−pts тайминг субтитров, как правило, будет отключен некоторыми кадрами. С некоторыми демультиплексорами и кодеками эта опция работает некорректно. + + + + Proxy + Прокси + + + + Enable proxy + Включить прокси + + + + Enable/disable the use of the proxy. + Включит/отключить использование прокси. + + + + Host + Хост + + + + The host name of the proxy. + Имя хоста прокси. + + + + Port + Порт + + + + The port of the proxy. + Порт прокси. + + + + Username + Имя пользователя + + + + If the proxy requires authentication, this sets the username. + Если прокси требует аутентификации, укажите имя пользователя. + + + + Password + Пароль + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + Пароль для прокси. Внимание: пароль будет сохранён в виде текста в конфигурационном файле. + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + Вы можете указать прокси для интернет-соединений (пока используется только для загрузки субтитров). + + + + &Enable proxy + &Включить прокси + + + + &Host: + &Хост: + + + + &Port: + &Порт: + + + + &Username: + &Имя пользователя + + + + Pa&ssword: + &Пароль + + + + C&orrect PTS + Точные &метки времени + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + Тип + + + + Select the proxy type to be used. + Выберите тип прокси, который будет использоваться. + + + + &Type: + &Тип: + + + + Actions list + Список действий + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + Здесь вы можете определить список <i>actions</i> - действий, которые будут выполняться каждый раз при открывании файла. Список всех возможных действий вы можете найти в разделе <b>Устройства ввода</b> диалога настроек. Все действия должны быть разделены пробелами. Включаемые/отключаемые действия могут иметь последующий параметр <i>true</i> или <i>false</i> для включения или отключения действия. + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + Ограничение: действия запускаются только при открывании файла, но не при перезапуске процесса mplayer (например, выборе аудио или видео фильра). + + + + Network + Сеть + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + &Выполнять следующие действия при открывании файла. Действия должны разделяться пробелами: + + + + &Network + &Сеть + + + + Example: + Пример: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + Перестраивает индекс в файлах, в которых индекс не найден, позволяя перематывать их. Полезно для недогруженных/неполных или плохо созданных файлов. Опция работает только если мультимедиа поддерживает перемотку (т.е. не с stdin, pipe, и др). <br> <b>Примечание:</b> создание индекса может занять некоторое время. + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + Пароль для прокси. <b>Внимание:</b> пароль будет сохранён в виде текста в конфигурационном файле. + + + + PrefAssociations + + + Warning + Внимание + + + + Not all files could be associated. Please check your security permissions and retry. + Не все файлы могут быть ассоциированы. Проверье свои права и попытайтесь снова. + + + + File Types + Типы файлов + + + + Select all + Выбрать все + + + + Check all file types in the list + Выбраь все типы файлов в списке + + + + Uncheck all file types in the list + Ничего не выбирать в списке + + + + List of file types + Список типов файлов + + + + File types + Типы файлов + + + + Media files handled by SMPlayer: + Медиа файлы, ассоциированные с SMPlayer: + + + + Select All + Выбрать все + + + + Select None + Ничего не выбирать + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Отметьте типы файлов, которые хотите связать с SMPlayer. После нажатия Применить, отмеченные типы файлов будут ассоциированы с SMPlayer. Если убрать отметку, файловая ассоциация будет восстановлена. + + + + Select none + Ничего не выбирать + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + (sp)<b>Примечание:</b> (Восстановление ассоциаций не работает в Windows Vista). + + + + PrefDrives + + + Drives + Устройства + + + + icon + значок + + + + CD device + CD устройство + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Выберите CD привод. Он будет использоваться для воспроизведения видео и аудио CD. + + + + DVD device + DVD устройство + + + + Choose your DVD device. It will be used to play DVDs. + Выберите ваш DVD привод. Он будет использоваться для воспроизведения DVD. + + + + Select your &CD device: + Выберите ваш CD &привод: + + + + Select your &DVD device: + Выберите ваш DVD п&ривод: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer не выбирает устройства CDROM или DVD по умолчанию. Поэтому чтобы воспроизводить CD или DVD, выберите устройства, которые вы хотите использовать (они могут быть одним и тем же устройством). + + + + PrefGeneral + + + General + Основные + + + + &General + &Основные + + + + Paths + Пути + + + + Media settings + Настройки мультимедиа + + + + Preferred audio and subtitles + Предпочитаемые звуковая дорожка и субтитры + + + + Video + Видео + + + + Start videos in fullscreen + Открывать видео на весь экран + + + + Disable screensaver + Подавить хранитель экрана + + + + Audio + Звук + + + + Select the mplayer executable + Выбрать исполняемый файл mplayer + + + + Executables + Пути + + + + All files + Все файлы + + + + Select a directory + Выбрать каталог + + + + MPlayer executable + Исполняемый файл MPlayer + + + + Screenshots folder + Каталог снимков + + + + Video output driver + Устройство вывода видео + + + + Audio output driver + Устройство вывода аудио + + + + Select the audio output driver. + Выберите устройство вывода для аудио. + + + + Remember settings + Запомнить настройки + + + + Preferred audio language + Предпочитаемый язык звуковой дорожки + + + + Preferred subtitle language + Предпочитаемый язык субтитров + + + + Software video equalizer + Программный видеоэквалайзер + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Вы можете попробовать эту опцию, если видеоэквалайзер не поддерживается вашей видео-картой, или выбранным драйвером вывода видео.<br><b>Обратите внимание:</b>эта опция несовместима с некоторыми драйверами вывода видео. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Если эта опция выбрана, всё видео будет стартовать в полноэкранном режиме. + + + + Software volume control + Програмное управление громкостью + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Попробуйте эту опцию для использования программного микшера вместо аппаратного. + + + + Postprocessing quality + Качество постобработки + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Динамическое изменение степени постпроцессинга в зависимости от количества свободного процессорного времени. Указанное вами число будет соответствовать максимальному уровню. + + + + Change volume + Управление громкостью + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Если выбрано, то SMPlayer будет запоминать громкость каждого воспроизводимого файла и восстанавливать ее при повторном воспроизведении. Для новых файлов будет использоваться уровень громкости, принятый по умолчанию. + + + + 0 + 0 + + + + &Change volume on every file + &Изменять громкость для каждого файла + + + + Select the &MPlayer executable: + Укажите исполняемый &файл MPlayer: + + + + &Folder for storing screenshots: + Каталог для &снимков экрана: + + + + &Audio: + &Звук: + + + + &Remember settings for all files (audio track, subtitles...) + За&поминать настройки всех файлов (звук, субтитры...) + + + + Su&btitles: + Суб&титры: + + + + &Quality: + Ка&чество: + + + + Start videos in &fullscreen + Запускать видео на весь экр&ан + + + + Disable &screensaver + Подавить &хранитель экрана + + + + &Default volume: + &Громкость по умолчанию: + + + + Use s&oftware volume control + Использовать програ&ммное управление громкостью + + + + Ma&x. Amplification: + Ма&кс. увеличение: + + + + &AC3/DTS pass-through S/PDIF + AC3/DTS &через S/PDIF + + + + Direct rendering + Прямой рендеринг + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Если выбрано - включен прямой рендеринг (поддерживается не всеми кодеками и модулями видео вывода)<br><b>ВНИМАНИЕ:</b> Могут возникнуть проблемы с OSD/субтитрами! + + + + Double buffering + Двойная буферизация + + + + D&irect rendering + Прямой рен&деринг + + + + Dou&ble buffering + Двойная &буферизация + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Двойная буферизация исправляет мерцание кадров благодаря тому, что в память загружается два кадра и, при отображении одного, обрабатывается следующий. Выключение этого параметра может негативно сказаться на OSD. + + + + &Enable postprocessing by default + Разрешить &постобработку по умолчанию + + + + Volume &normalization by default + Разрешить &нормализацию громкости по умолчанию + + + + Close when finished + Закрыть по окончании воспроизведения + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Если выбрано, то главное окно будет автоматически закрыто по окончании воспроизведения файла или списка. + + + + 2 (Stereo) + 2 (Стерео) + + + + 4 (4.0 Surround) + 4 (4.0 окружение) + + + + 6 (5.1 Surround) + 6 (5.1 окружение) + + + + C&hannels by default: + Каналы по &умолчанию: + + + + &Pause when minimized + Пауза при &минимизации + + + + Pause when minimized + Пауза при минимизации + + + + Enable postprocessing by default + Включить постобработку по умолчанию + + + + Max. Amplification + Макс. усиление + + + + AC3/DTS pass-through S/PDIF + AC3/DTS через S/PDIF + + + + Volume normalization by default + Нормализация громкости по умолчанию + + + + Maximizes the volume without distorting the sound. + Увеличивает громкость без искажений звука. + + + + Default volume + Громкость по умолчанию + + + + Sets the initial volume that new files will use. + Устанавливает начальную громкость для новых файлов. + + + + Channels by default + Каналы по умолчанию + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Устанавливает максимальное усиление в процентах (по умолчанию 110). Значение 200 увеличит громкость до уровня, превышающего текущий вдвое. При значениях ниже 100 начальная грокость (100%) будет выше максимума, т.е. OSD будет показывать некорректную информацию. + + + + Uses hardware AC3 passthrough + Использовать AC3 через S/PDIF выход звуковой карты + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Запрашивает количество каналов воспроизведения. MPlayer просит декодер декодировать звук в указанное количество каналов. Выполнение задачи ложится на плечи декодера. Обычно это требуется только при воспроизведении видео с AC3 звуком (например DVD). В этом случае liba52 выполняет декодирование как обычно и корректно сводит аудио в запрошенное количество каналов. ПРИМЕЧАНИЕ: Эта опция учитывается кодеками (AC3), фильтрами (окружение) и драверами вывода звука (как минимум OSS). + + + + Postprocessing will be used by default on new opened files. + Постобработка будет использована для новых открытых файлов. + + + + Audio track + Аудио дорожка + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Указывает аудио дорожку по умолчанию, используемую по умолчанию для новых файлов. Если дорожка не существует, будет использована первая. <br><b>Примечание:</b> опция <i>предпочитаемый язык</i> более приоритетна. + + + + Subtitle track + Дорожка субтитров + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Указывает дорожку субтитров по умолчанию, используемую по умолчанию для новых файлов. Если дорожка не существует, будет использована первая. <br><b>Примечание:</b> опция <i>"Предпочительный язык субтитров</i> более приоритетна. + + + + Or choose a track number: + Или указать номер дорожки: + + + + Audi&o: + Ауди&о: + + + + Preferred language: + Выбрать предпочитаемый язык: + + + + Preferre&d audio and subtitles + &Языковая дорожка и субтитры + + + + &Subtitle: + Су&бтитры: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Здесь вы можете указать предпочитаемый язык для аудио и субтитров. Если проигрываемый фильм содержит субтитры и аудио на разных языках, то smplayer будет использовать те из них, которые соответствуют вашим предпочтениям.<br>Все сказанное верно для тех типов данных мультимедиа, которые содержат информацию о языке аудиодорожек и субтитров, таких как DVD или mkv.<br>Также можно использовать регулярные выражения. Например: <b>es|esp|spa</b> означает, что будут выбраны аудиодорожки и субтитры содержащие в названии языка <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + Высоко&скоростное воспроизведение без питч-эффекта + + + + High speed playback without altering pitch + Высокоскоростное воспроизведение без питч-эффекта + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Позволяет изменить скорость воспроизведения без питч-эффекта. Требует как минимум версию MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Изменять громкость непосредственно перед проигрыванием + + + + &Video + &Видео + + + + Use s&oftware video equalizer + Использовать программный видео&эквалайзер + + + + A&udio + &Звук + + + + Volume + Громкость + + + + None + Ничего + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (обычный) + + + + Yadif (double framerate) + Yadif (2× частота кадров) + + + + Linear Blend + Линейное смешивание + + + + Kerndeint + Адаптивное (mplayer) + + + + Dei&nterlace by default: + &Удаление "гребёнки" по умолчанию: + + + + Deinterlace by default + Удаление "гребёнки" по умолчанию + + + + Select the deinterlace filter that you want to be used for new videos opened. + Выберите фильтр деинтерлейсинга (удаление "гребёнки"), который вы хотите использовать по умолчанию для новых видеофайлов. + + + + Remember time position + Помнить позицию + + + + Remember &time position + Помнить п&озицию + + + + Change volume just before p&laying + Изменять громкость непосредственно &перед проигрыванием + + + + Enable the audio equalizer + Включить аудиоэквалайзер + + + + Check this option if you want to use the audio equalizer. + Отметьте эту опцию, если хотите использовать аудиоэквалайзер. + + + + &Enable the audio equalizer + Включить &аудиоэквалайзер + + + + Draw video using slices + Отрисовывать видео с использованием слоёв + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Включает/отключает отрисовку видео слоями/полосами по 16-пикселов высотой, вместо отрисовки целого кадра за один проход. Может быть быстрее или медленнее, в зависимости от видео карты и доступного кеша. Полезно только с кодеками libmpeg2 и libavcodec. + + + + Dra&w video using slices + Отри&совывать видео с использованием слоёв + + + + &Close when finished playback + &Закрыть по окончании воспроизведения + + + + fast + быстро + + + + slow + медленно + + + + fast - ATI cards + быстро – видеокарты ATI + + + + User defined... + Определено пользователем... + + + + Default zoom + Увеличение по умолчанию + + + + This option sets the default zoom which will be used for new videos. + Эта опция устанавливает увеличение по умолчанию для новых видеофайлов. + + + + Default &zoom: + У&величение по умолчанию: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Здесь вы должны указать исполняемый файл mplayer, который будет использовать SMPlayer.<br>для SMPlayer необходим как минимум MPlayer 1.0rc1 (хотя рекомендуются последние ревизии из SVN). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Если эта опция указана неправильно, SMPlayer не сможет ничего воспроизвести! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Здесь вы можете указать каталог, куда SMPlayer будет сохранять снимки экрана. Если это поле пустое, возможность сохранения скриншотов будет отключена. + + + + Select the video output driver. %1 provides the best performance. + Выберите устройство вывода изображения на экран. %1 обеспечивает максимальную производительность. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + Рекомендуется %1. Постарайтесь исключить %2 и %3, они медленные и могут ухудшить производительность. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + По умолчанию SMPlayer запоминает настройки каждого воспроизводимого файла (звуковая дорожка, громкость, фильтры...). Отключите эту опцию, если она вам не нравится. + + + + If you check this option, SMPlayer will play all files from the beginning. + Если вы отметите эту опцию, SMPlayer будет проигрывать все файлы с начала. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + При включении этой опции, файл будет поставлен на паузу при минимизации главного окна. После восстановления окна воспроизведение продолжится. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Отметьте эту опцию, чтобы отключить хранитель экрана во время воспроизведения.<br> Он будет включен свнова по окончанию воспроизведения. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Здесь вы можете указать предпочитаемый язык для звуковых дорожек. Если воспроизводимое видео содержит несколько звуковых дорожек, то SMPlayer будет использовать ту из них, которая соответствует вашим предпочтениям.<br>Все сказанное верно для тех типов данных мультимедиа, которые содержат информацию о языке звуковых дорожек, таких как DVD или mkv.<br>Также можно использовать регулярные выражения. Например: <b>es|esp|spa</b> означает, что будет выбрана звуковая дорожка содержащая в названии языка <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Здесь вы можете указать предпочитаемый язык для субтитров. Если проигрываемый фильм содержит субтитры на разных языках, то SMPlayer будет использовать те из них, которые соответствуют вашим предпочтениям.<br>Все сказанное верно для тех типов данных мультимедиа, которые содержат информацию о языке субтитров, таких как DVD или mkv.<br>Также можно использовать регулярные выражения. Например: <b>es|esp|spa</b> означает, что будут выбраны субтитры содержащие в названии языка <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + Ou&tput driver: + Устройство &вывода: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Если эта опция отмечена, начальная громкость будет установлена до начала проигрывания. Это предупреждает скачок громкости при старте. Требует как минимум MPlayer SVN r27872. + + + + Add black borders on fullscreen + Добавить чёрные полосы в полноэкранном режиме + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Если эта опция включена, в полноэкранном режиме к изображению будут добавлены чёрные полосы. Это позволяет отображать на них субтитры. + + + + &Add black borders on fullscreen + Добавить &чёрные полосы в полноэкранном режиме + + + + one ini file + один общий ini файл + + + + multiple ini files + отдельные ini файлы + + + + Method to store the file settings + Метод сохранения настроек файлов + + + + This option allows to change the way the file settings would be stored. The following options are available: + Эта опция позволяет изменить способ сохранения настроек файлов. Доступны следующие варианты: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>один общий ini файл</b>: настройки для всех воспроизводимых файлов будут сохраняться в одном общем ini файле (%1) + + + + The latter method could be faster if there is info for a lot of files. + Следующий метод может быть быстрее, если уже сохранены настройки большого количества файлов. + + + + &Store settings in + Со&хранять настройки в + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>отдельные ini файлы,<b/>: для каждого воспроизводимого файла будет использоваться свой ini файл. Все ini файлы будут сохранены в каталог %1 + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + Если вы отметите эту опцию, SMPlayer будет запоминать последнюю позицию файла, когда вы снова его откроете. Эта опция работаеттолько с обычными файлами (не с DVD, CD или сетевыми адресами...). + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + Если выбрано – включается прямой рендеринг (поддерживается не всеми кодеками и модулями видео вывода)<br><b>ВНИМАНИЕ:</b> Могут возникнуть проблемы с OSD/субтитрами! + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Запрашивает количество каналов воспроизведения. MPlayer просит декодер декодировать звук в указанное количество каналов. Выполнение задачи ложится на плечи декодера. Обычно это требуется только при воспроизведении видео с AC3 звуком (например DVD). В этом случае liba52 выполняет декодирование как обычно и корректно сводит аудио в запрошенное количество каналов. <b>ПРИМЕЧАНИЕ</b>: Эта опция учитывается кодеками (AC3), фильтрами (окружение) и драверами вывода звука (как минимум OSS). + + + + PrefInput + + + Keyboard and mouse + Устройства ввода + + + + &Keyboard + &Клавиатура + + + + icon + значок + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Здесь можно изменить настройки горячих клавиш. Чтобы сделать это, дважды кликните мышкой или нажмите клавишу в необходимой ячейке. Вы можете сохранить список горячих клавиш, чтобы им могли воспользоваться другие люди или вы сами на другом компьютере. + + + + &Mouse + &Мышь + + + + Button functions: + Функции кнопки: + + + + Media seeking + Прокрутка + + + + Volume control + Регулятор громкости + + + + Zoom video + Увеличение + + + + None + Ничего + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Здесь можно изменить настройки горячих клавиш. Чтобы сделать это, дважды щёлкните мышкой или нажмите клавишу в необходимой ячейке. Вы можете сохранить список горячих клавиш, чтобы им могли воспользоваться другие люди или вы сами на другом компьютере. + + + + &Left click + &Левый клик + + + + &Double click + &Двойной щелчок + + + + &Wheel function: + &Функция колеса: + + + + Shortcut editor + Редактор сочетаний клавиш + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Эта таблица позволяет изменить сочетания клавиш для различных действий. Двойной клик или нажатие ввода на выбранном пункте или нажатие кнопки <b>Изменить</b> вызовет диалог <i>Изменить горячую клавишу</i>. Есть два способа изменить сочетание клавиш: если кнопка <b>Захват</b> нажата - просто нажать нужную комбинацию клавиш (работает не для всех клавиш). Если кнопка <b>Захват</b> отжата, можно просто вписать полное название комбинации клавиш. + + + + Left click + Левый клик + + + + Select the action for left click on the mouse. + Выбрать действие для левого клика мыши. + + + + Double click + Двойной клик + + + + Select the action for double click on the mouse. + Выбрать действие для двойного клика мыши. + + + + Wheel function + Функция колеса + + + + Select the action for the mouse wheel. + Выбрать действие для функции колеса. + + + + Play + Воспроизведение + + + + Pause + Пауза + + + + Stop + Стоп + + + + Fullscreen + Полный экран + + + + Compact + Компактно + + + + Screenshot + Снимок экрана + + + + On top + Поверх всех окон + + + + Mute + Приглушение + + + + Frame counter + Счётчик кадров + + + + Reset zoom + Сбросить увеличение + + + + Exit fullscreen + Выйти из поноэкранного режима + + + + Double size + Двойной размер + + + + Play / Pause + Воспроизведение / Пауза + + + + Pause / Frame step + Пауза / Покадровый просмотр + + + + Playlist + Список + + + + Preferences + Настройки + + + + No function + Нет функции + + + + Change speed + Изменить скорость + + + + Normal speed + Нормальная скорость + + + + Keyboard + Клавиатура + + + + Mouse + Мышь + + + + Middle click + Средний клик + + + + Select the action for middle click on the mouse. + Выбрать действие для среднего клика мыши. + + + + M&iddle click + С&редний клик + + + + X Button &1 + Доп. кнопка &1 + + + + X Button &2 + Доп. кнопка &2 + + + + Go backward (short) + Назад (малый интервал) + + + + Go backward (medium) + Назад (средний интервал) + + + + Go backward (long) + Назад (длинный интервал) + + + + Go forward (short) + Вперёд (короткий интервал) + + + + Go forward (medium) + Вперёд (средний интервал) + + + + Go forward (long) + Вперёд (длинный интервал) + + + + OSD - Next level + OSD – Следующий уровень + + + + Show context menu + Показать контестное меню + + + + &Right click + &Правый клик + + + + Increase volume + Увеличить громкость + + + + Decrease volume + Уменьшить громкость + + + + X Button 1 + Доп. кнопка 1 + + + + Select the action for the X button 1. + Выбрать действие для доп. кнопки 1. + + + + X Button 2 + Доп. кнопка 2 + + + + Select the action for the X button 2. + Выбрать действие для доп. кнопки 1. + + + + Show video equalizer + Показать видеоэквалайзер + + + + Show audio equalizer + Показать аудиоэквалайзер + + + + Always on top + Всегда наверху + + + + Never on top + Никогда наверху + + + + On top while playing + Наверху во время воспроизведения + + + + PrefInterface + + + Interface + Внешний вид + + + + <Autodetect> + <Автоопределение> + + + + Default + По умолчанию + + + + &Interface + &Интерфейс + + + + Seeking + Поиск + + + + Recent files + Последние файлы + + + + Never + Никогда + + + + Whenever it's needed + Когда это нужно + + + + Only after loading a new video + Только для нового видео + + + + Language + Язык + + + + Here you can change the language of the application. + Здесь можно изменить язык приложения. + + + + Instances + Экземпляры + + + + &Short jump + &Маленький интервал + + + + &Medium jump + &Средний интервал + + + + &Long jump + &Длинный интервал + + + + Mouse &wheel jump + Интервал при перемотке мы&шью + + + + &Use only one running instance of SMPlayer + Запускать только о&дну копию SMPlayer + + + + Ma&x. items + &Количество пунктов в меню + + + + St&yle: + &Стиль: + + + + Ico&n set: + Набор &значков: + + + + L&anguage: + &Язык: + + + + Main window + Главное окно + + + + Auto&resize: + Автоматически изменять &размер: + + + + R&emember position and size + Запоминать пози&цию и размер + + + + Default font: + Шрифт по умолчанию: + + + + &Change... + &Изменить... + + + + &Behaviour of time slider: + &Переходить в позицию указателя: + + + + Seek to position while dragging + Во время перемотки мышью + + + + Seek to position when released + После отпускания кнопки мыши + + + + TextLabel + Текстовая метка + + + + &Seeking + &Перемотка + + + + Ins&tances + &Экземпляры + + + + Autoresize + Автоматический размер + + + + The main window can be resized automatically. Select the option you prefer. + Главное окно может изменять размер автоматически. Выберите предпочтительную настройку. + + + + Remember position and size + Запоминать позицию и размер + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Если настройка выбрана, позиция и размер видео будут сохранены и восстановлены при следующем запуске SMPlayer. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Выберите максимальное количество элементов в подменю <b>Открыть->Последние файлы</b>. При значении 0 меню не будет показано вообще. + + + + Icon set + Набор значков + + + + Select the icon set you prefer for the application. + Выберите предпочитаемый для приложения набор значков. + + + + Style + Стиль + + + + Select the style you prefer for the application. + Выберите предпочитаемый стиль приложения. + + + + Default font + Шрифт по умолчанию + + + + You can change here the application's font. + Здесь можно изменить шрифт приложения. + + + + Short jump + Маленький интервал + + + + Select the time that should be go forward or backward when you choose the %1 action. + Выберите время перемотки вперёд или назад при выборе действия %1. + + + + short jump + маленький интервал + + + + Medium jump + Средний интервал + + + + medium jump + средний интервал + + + + Long jump + Длинный интервал + + + + long jump + длинный интервал + + + + Mouse wheel jump + Интервал перемотки колесом мыши + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Выберите время перемотки вперёд или назад при вращении колеса мыши. + + + + Behaviour of time slider + Поведение временной полосы прокрутки + + + + Select what to do when dragging the time slider. + Выберите поведение при перетаскивании ползунка прокрутки. + + + + Use only one running instance of SMPlayer + Использовать только одну копию SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Выберите эту опцию, если хотите использовать уже запущенную копию SMPlayer при открытии новых файлов. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer требует прослушивания порта для получения команд от других экземпляров. Если значение по умолчанию используется другим приложением, вы можете изменить его. + + + + Default GUI + По умолчанию + + + + Mini GUI + Мини интерфейс + + + + GUI + Интерфейс + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Выберите предпочитаемый для приложения интерфейс. На текущий момент их доступно два: интерфейс по умолчанию и мини интерфейс.<br> <b>Интерфейс по умолчанию</b> представляет собой обычный интерфейс, с панелью инструментов и панелью управления с несколькими кнопками. <br><b>Замечание:</b> для изменения этой настройки необходим перезапуск SMPlayer. + + + + &GUI + &Интерфейс + + + + Automatic port + Порт автоматически + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer требует прослушивания порта для получения команд от других экземпляров. Если вы отметите эту опцию, порт будет выбран автоматически. + + + + Manual port + Указание порта вручную + + + + Port to listen + Порт для прослушивания + + + + &Automatic + &Автоматически + + + + &Manual + &Вручную + + + + Floating control + Плавающая панель + + + + Animated + Анимировать + + + + If this option is enabled, the floating control will appear with an animation. + Если эта опция отмечена, плавающая панель управления будет появляться с анимацией. + + + + Width + Ширина + + + + Specifies the width of the control (as a percentage). + Определяет ширину панели (в процентах). + + + + Margin + Отступ + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + Эта опция устанавливает количество пикселов, на которое плавающая панель будет отступать от низа экрана. Полезно когда экраном является телевизор, и картинка увеличена, таким образом предотвращается случай, когда плавающая панель будет невидима. + + + + Display in compact mode too + Отображать также в компактном режиме + + + + If this option is enabled, the floating control will appear in compact mode too. Warning: the floating control has not been designed for compact mode and it might not work properly. + Если эта опция отмечена, плавающая панель управления будет появляться также и в компактном режиме. Внимание: плавающая панель не разрабатывалась для компактного режима и может работать некорректно. + + + + Bypass window manager + Обход менеджера окон + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + Если эта опция отмечена, панель управления будет отображаться в обход менеджера окон. Отключите эту опцию, если панель управления работает некорректно с вашим оконным менеджером. + + + + &Floating control + П&лавающая панель + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + Плавающая панель управления появляется в полноэкранном режиме, когда указатель мыши перемещается к низу экрана. + + + + &Animated + &Анимировать + + + + &Width: + &Ширина: + + + + 0 + 0 + + + + &Margin: + &Отступ: + + + + Display in &compact mode too + Отображать также в &компактном режиме + + + + &Bypass window manager + &Обход менеджера окон + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + Если эта опция отмечена, плавающая панель управления будет появляться также и в компактном режиме.<b> Внимание:</b> плавающая панель не разрабатывалась для компактного режима и может работать некорректно. + + + + Mpc GUI + MPC интерфейс + + + + PrefPerformance + + + Performance + Быстродействие + + + + &Performance + &Быстродействие + + + + Priority + Приоритет + + + + Select the priority for the MPlayer process. + Укажите приоритет процесса для MPlayer. + + + + realtime + реальное время + + + + high + высокий + + + + abovenormal + выше обычного + + + + normal + обычный + + + + belownormal + ниже обычного + + + + idle + низкий + + + + Cache + Кэш + + + + KB + Кб + + + + Setting a cache may improve performance on slow media + Установки кэша могут улучшить или ухудшить быстродействие + + + + Allow frame drop + Допускать выпадение кадров + + + + Synchronization + Синхронизация + + + + Audio/video auto synchronization + Автосинхронизация звука/видео + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Утсновите приоритет mplayer как стандартный для Windows..<br><b>ОСТОРОЖНО:</b> Использование приоритета реального времени может сильно замедлить работу системы. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Пропускать кадры для поддержки аудио/видео синхронизации. + + + + Allow hard frame drop + Допускать жесткое выпадение кадров + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Более жесткое пропускание кадров (рваное воспроизведение). Приводит к искажению картинки! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Плавная аудио/видео синхронизация, основанная на изменении длины звуковой дорожки. + + + + Priorit&y: + П&риоритет: + + + + &Allow frame drop + &Допускать выпадение кадров + + + + Allow &hard frame drop (can lead to image distortion) + Допускать &жесткое выпадение кадров (изображение может исказиться) + + + + Audio/&video auto synchronization + Автоматическая син&хронизация изображения и звука + + + + Fact&or: + По&казатель: + + + + &Fast audio track switching + &Быстрое переключение звуковых дорожек + + + + Fast &seek to chapters in dvds + Быстрый &поиск по главам на DVD + + + + Fast audio track switching + Быстрое переключение звуковых дорожек + + + + Fast seek to chapters in dvds + Быстрый поиск по главам на DVD + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Если отмечено, SMPlayer попытается использовать более быстрый метод для поиска по главам, но эта опция может не работать с некоторыми дисками. + + + + Skip loop filter + Пропустить петелевой фильтр + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Возможные значения: <br> <b>Да</b>: будет использован наиболее быстрый метод переключения аудио дорожек (может не работать с некоторыми форматами).<br> <b>Нет</b>: процесс MPlayer будет перезапущен при изменении звуковой дорожки.<br> <b>Авто</b>: SMPlayer решит самостоятельно, основываясь на версии MPlayer. + + + + Cache for files + Кэширование файлов + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Эта опция определяет количество памяти (в кБайтах), используетмых для предварительного кэширования файлов. + + + + Cache for streams + Кэширование потоков + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Эта опция определяет количество памяти (в кБайтах), используетмых для предварительного кэширования URL. + + + + Cache for DVDs + Кэшировать DVD + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Эта опция определяет количество памяти (в кБайтах), используетмых для предварительного кэширования DVD.<br><b>Внимание:</b> Перемотка может работать неправильно (в том числе и обзор глав) при использовании кэширования DVD. + + + + &Cache + &Кэш + + + + Cache for &DVDs: + &Кэш DVD: + + + + Cache for &local files: + Кэш локальных &файлов: + + + + Cache for &streams: + Кэш &потоков: + + + + Enabled + Включено + + + + Skip (always) + Пропускать (всегда) + + + + Skip only on HD videos + Пропускать только для HD видео + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Эта опция позволяет пропускать фильр loop (он же debloking) во время декодирования H.264. Поскольку фильтрованный кадр предполагается использовать в качестве ссылки для декодирования зависимых кадров, то качество, например, у MPEG-2, будет хуже, чем если бы deblocking не производился вообще. Но, как минимум, для HDTV с высоким битрейтом это даёт значительный прирост производительности без видимой потери качества. + + + + Possible values: + Возможные значения: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Включено</b>: фильтр loop не пропускается + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Пропускать (всегда)</b>: фильтр loop не применяется вне зависимости от разрешения видео + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Включено</b>: фильтр loop пропускается только для видео с высотой картинки %1 или выше. + + + + Loop &filter + Петелевой &фильтр + + + + Cache for audio CDs + Кэшировть аудио CD + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Эта опция определяет количество памяти (в кБайтах), используетмых для предварительного кэширования аудио CD. + + + + Cache for &audio CDs: + Кэш &аудио CD: + + + + Cache for VCDs + Кэшировать видео CD + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Эта опция определяет количество памяти (в кБайтах), используетмых для предварительного кэширования видео CD. + + + + Cache for &VCDs: + Кэш &видео CD: + + + + Threads for decoding + Потоки декодирования + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Установите количество потоков для декодирования. Только для MPEG-1/2 и H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Потоков декодирования (только для MPEG-1/2 и H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + Устанавливает приоритет процесса mplayer согласно предопределённым приоритам, доступным для Windows.<br><b>Внимание:</b> Использование приоритета реального времени может сильно замедлить работу системы. + + + + PrefPlaylist + + + Playlist + Список + + + + Automatically add files to playlist + Автоматически добавлять файлы в список + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Если эта опция отмечена, каждый раз при открытии файла, SMPlayer будет первым делом очищать список и затем добавлять файл в него. Касательно DVD, CD и VCD, все заголовки на диске будут добавлены в плейлист. + + + + Add consecutive files + Добавлять последующие файлы + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Если эта опция отмечена, SMPlayer будет искать последующие файлы (вроде video_1.avi, video_2.avi...) и добавлять найденные в список. + + + + &Playlist + &Список воспроизведения + + + + &Automatically add files to playlist + &Автоматически добавлять файлы в список + + + + Add &consecutive files + Добавлять &последующие файлы + + + + PrefSubtitles + + + Subtitles + Субтитры + + + + Choose a ttf file + Выбрать TTF файл + + + + Truetype Fonts + Шрифты Truetype + + + + &Subtitles + &Субтитры + + + + Autoload + Автозагрузка + + + + Same name as movie + С тем же именем, что и у фильма + + + + All subs containing movie name + Подключать субтитры содержащие название фильма + + + + All subs in directory + Все субтитры каталога + + + + Position + Позиция + + + + 0 + 0 + + + + Top + Верх + + + + Bottom + Низ + + + + Font + Шрифт + + + + Select the font which will be used for subtitles (and OSD): + Выберите шрифт для субтитров (и OSD): + + + + Size + Размер + + + + No autoscale + Без автомасштабирования + + + + Proportional to movie height + Пропорциональко высоте клипа + + + + Proportional to movie width + Пропорционально ширине клипа + + + + Proportional to movie diagonal + Пропорционально диагонали клипа + + + + Subtitle position + Расположение субтитров + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Этот параметр определяет положение субтитров относительно окна. <i>100</i> означает низ, <i>0</i> – верх. + + + + Au&toload subtitles files (*.srt, *.sub...): + &Автозагрузка субтитров (*.srt, *.sub...): + + + + S&elect first available subtitle + Загружать &первые доступные субтитры + + + + &Default subtitle encoding: + &Кодировка субтитров по умолчанию: + + + + Default &position of the subtitles on screen + По&ложение субтитров на экране по умолчанию + + + + &Include subtitles on screenshots + &Сохранять субтиры на снимках экрана + + + + &TTF font: + TTF шри&фт: + + + + S&ystem font: + &Системный шрифт: + + + + A&utoscale: + А&втомасштабирование: + + + + Select first available subtitle + Выберите первые доступные субтитры + + + + Default subtitle encoding + Кодировка субтитров по умолчанию + + + + Include subtitles on screenshots + Сохранять субтиры на снимках экрана + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Если выбрано, субтитры будут появляться на снимках экрана. Заметка: иногда это может вызвать некоторые проблемы. + + + + TTF font + TTF шрифт + + + + System font + Системный шрифт + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Зесь можно выбрать системный шрифт как шрифт по умолчанию для субтитров и OSD. <b>Заметка:</b> требуется MPlayer с поддержкой fontconfig. + + + + Autoscale + Автомасштабирование + + + + Text color + Цвет текста + + + + Select the color for the text of the subtitles. + Выберите цвет текста субтитров. + + + + Border color + Цвет кромки + + + + Select the color for the border of the subtitles. + Выберите цвет кромки субтитров. + + + + Select the subtitle autoload method. + Выберите метод автозагрузки субтитров. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Если доступно более одной дорожки субтитров, одна из них будет автоматически выбрана, обычно первая, хотя если одна из дорожек удовлетворяет выбранному пользоватлем предпочтительному языку, то будет выбрана именно она. + + + + Select the subtitle autoscaling method. + Выберите метод автозагрузки субтитров. + + + + Select the encoding which will be used for subtitle files by default. + Выберите кодировку, которая будет использована для файлов субтитров по умолчанию. + + + + Try to autodetect for this language + Автоматически определить для языка + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Если опция отмечена, будет произведена попытка автоматически определить кодировку для указанного языка. При ошибке будет использована кодировка по умолчанию. Опция требует MPlayer, скомпилированный с поддержкой ENCA. + + + + Subtitle language + Язык субтитров + + + + Select the language for which you want the encoding to be guessed automatically. + Выберите язык, для которого будет производиться автоматическое определение кодировки субтитров. + + + + Encoding + Кодировка + + + + Try to a&utodetect for this language: + А&втоматически определить для языка + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Здесь можно выбрать ttf шрифт, используемый субтитрами. Обычно вы можете найти большое количество ttf шрифтов в %1 + + + + Outline + Контур + + + + Select the font for the subtitles. + Выберите шрифт для субтитров. + + + + The size in pixels. + Размер в пикселах. + + + + Bold + Жирный + + + + If checked, the text will be displayed in <b>bold</b>. + Если отмечено, текст будет отображаться <b>жирным</b>. + + + + Italic + Наклонный + + + + If checked, the text will be displayed in <i>italic</i>. + Если отмечено, текст будет отображаться <b>наклонным</b>. + + + + Left margin + Поле слева + + + + Specifies the left margin in pixels. + Определяет размер поля слева в пикселах. + + + + Right margin + Поле справа + + + + Specifies the right margin in pixels. + Определяет размер поля справа в пикселах. + + + + Vertical margin + Вертикальное поле + + + + Specifies the vertical margin in pixels. + Определяет размер поля по вертикали в пикселах. + + + + Horizontal alignment + Выравнивание по горизонтали + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + Определяет тип выравнивания по горизонтали. Возможные значения – слева, по центру и справа. + + + + Vertical alignment + Выравнивание по вертикали + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + Определяет тип выравнивания по вертикали. Возможные значения – снизу, по середине и сверху. + + + + Border style + Стиль границы + + + + Specifies the border style. Possible values: outline and opaque box. + Определяет стиль границы. Возможные значения: контур и непрозрачный + + + + Shadow + Тень + + + + Si&ze: + &Размер: + + + + Bol&d + &Жирный + + + + &Italic + &Наклонный + + + + Colors + Цвета + + + + &Text: + &Текст: + + + + &Border: + Грани&ца: + + + + Margins + Поля + + + + L&eft: + С&лева: + + + + &Right: + С&права: + + + + Verti&cal: + По &вертикали: + + + + Alignment + Выравнивание: + + + + &Horizontal: + &Горизонтальное + + + + &Vertical: + Верти&кальное: + + + + Border st&yle: + &Стиль границы: + + + + &Outline: + К&онтур: + + + + Shado&w: + Т&ень: + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + Следующие опции позволяют вам определить стиль, который будет использован для нестилизованных субтитров (srt, sub...). + + + + Left + horizontal alignment + Слева + + + + Centered + horizontal alignment + По центру + + + + Right + horizontal alignment + Справа + + + + Bottom + vertical alignment + Снизу + + + + Middle + vertical alignment + По середине + + + + Top + vertical alignment + Сверху + + + + Outline + border style + Контур + + + + Opaque box + border style + Непрозрачный + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + Если стиль границы установлен в <i>контур</i>, эта опция определяет ширину контура вокруг текста в пикселах. + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + Если стиль границы установлен в <i>непрозрачный</i>, эта опция определяет длину тени за текстом в пикселах. + + + + Enable normal subtitles + Включить нормальные субтитры + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + Нажмите эту кнопку, чтобы выбрать нормальные/традиционные субтитры. Этот вид субтитров может отображать только белые субтитры. + + + + Enable SSA/ASS subtitles + Включить SSA/ASS субтитры + + + + Normal subtitles + Нормальные субтитры + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + Эта опция не изменяет размер субтитров для текущего видео. Чтобы сделать это, используйте опции <i>Размер +</i> и <i>Размер –</i> в меню субтитров. + + + + Default scale + Увеличение по умолчанию + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + Эта опция определяет размер шрифта по умолчанию для нормальных субтитров, которое будет использовано для новых видеофайлов. + + + + SSA/ASS subtitles + SSA/ASS субтитры + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + Эта настройка определяет размер шрифта для субтиров SSA/ASS, который будет использоваться для новых видеофайлов. + + + + Line spacing + Междустрочный интервал + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + Здесь указывается интервал, который будет использоваться для разделения строк. Он может иметь отрицательные значения. + + + + &Font and colors + &Шрифт и цвета + + + + Enable &normal subtitles + Включить нор&мальные субтитры + + + + Enable SSA/&ASS subtitles + Включить SSA/ASS субтитр&ы + + + + Default s&cale: + &Увеличение по умолчанию: + + + + Defa&ult scale: + Увели&чение по умолчанию: + + + + &Line spacing: + Междустрочный &интервал: + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + Нажмите эту кнопку, чтобы выбрать новую библиотеку SSA/ASS. Это позволяет использовать субтитры с разными цветами, шрифтами... + + + + Freetype support + Поддержка Freetype + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + Обычно вы можете не отключать эту опцию. Делайт это только если MPlayer собран без поддержки freetype. <b>Отключение этой опции может привести к неработоспособности субтитров вообще!</b> + + + + Freet&ype support + Под&держка Freetype + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + Если выбрано, субтитры будут появляться на снимках экрана.<b> Примечание:</b> иногда это может вызвать некоторые проблемы. + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer – Помощь + + + + OK + OK + + + + Cancel + Отмена + + + + Apply + Применить + + + + Help + Помощь + + + + SMPlayer - Preferences + SMPlayer – Настройки + + + + QObject + + + the main window will be closed when the file/playlist finishes. + главное окно будет закрыто после окончания воспроизведения. + + + + will show this message and then will exit. + будет показанно это сообщение, после чего приложение закроется. + + + + This is SMPlayer v. %1 running on %2 + SMPlayer v. %1 запущен в %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + пытается соединиться с другим запущенным экземпляром и послать ему заданное действие. Пример: -send-action pause Остальные параметры (если есть) будут игнорироваться и приложение будет закрыто. При успешном выполнении задачи возвращается 0, или 1 в обратном случае. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list – это список действий разделенный пробелами. Эти действия будут выполняться после загрузки файла в заданной вами последовательности. Для действий с переменными значениями можно использовать true или false в качестве параметров. Например: -actions "fullscreen compact true". Кавычки необходимы в случае, если используется более одного действия. + + + + media + media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + Если уже запущен экземпляр программы ,то файлы мультимедиа будут добавлены в существующий список. Если же нет – опция будет проигнорирована и файлы будут открыты в новом экземпляре. + + + + the main window won't be closed when the file/playlist finishes. + Главное окно не будет закрыто, по окончании файла/списка. + + + + the video will be played in fullscreen mode. + Видео будет воспроизведиться в полноэкранном режиме. + + + + the video will be played in window mode. + Видео будет воспроизводиться в оконном режиме. + + + + Enqueue in SMPlayer + Добавить в SMPlayer + + + + opens the mini gui instead of the default one. + Открывает мини GUI вместо стандартного. + + + + Restores the old associations and cleans up the registry. + Восстанавливает старые ассоциации и очищает реестр. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' – любой вид файла, который может открыть SMPlayer. Это может быть локальный файл, DVD (т.е. dvd://1), интернет-поток (т.е. mms://...) или локальный список (плейлист) в формате m3u или pls. Если используется опция -playlist, это означает, что SMPlayer передаст эту опцию MPlayer-у и её воспримет он, а не SMPlayer. + + + + Usage: + Использование: + + + + directory + каталог + + + + action_name + имя_действия + + + + action_list + список_действий + + + + opens the default gui. + открывает интерфейс по умолчанию. + + + + subtitle_file + файл_субтитров + + + + specifies the subtitle file to be loaded for the first video. + Указывает файл субтитров, который будет загружен для первого видеофайла. + + + + %1 second(s) + + %1 секунда + %1 секунды + %1 секунд + + + + + %1 minute(s) + + %1 минута + %1 минуты + %1 минут + + + + + %1 and %2 + %1 и %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + определяет каталог, в котором smplayer будет сохранять свои конфигурационные файлы (smplayer.ini, smplayer_files.ini...) + + + + disabled + aspect_ratio + отключено + + + + auto + aspect_ratio + авто + + + + unknown + aspect_ratio + неизвестно + + + + opens the mpc gui. + открывает интерфейс mpc. + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + Ошибка ZIP/UNZIP API %1 + + + + SeekWidget + + + icon + значок + + + + label + метка + + + + ShortcutGetter + + + Modify shortcut + Изменить сочетание клавиш + + + + Press the key combination you want to assign + Нажмите клавиши, сочетание которых вы хотите использовать + + + + Clear + Очистить + + + + Capture + Захват + + + + Capture keystrokes + Горячая клавиша снимка с экрана + + + + SubChooserDialog + + + Subtitle selection + Выбор субтитров + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Этот архив содержит более одного файла субтиров. Выберите необходимый вам для распаковки. + + + + Select All + Выбрать все + + + + Select None + Ничего не выбирать + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer – Перемотка + + + + &Jump to: + &Перейти к: + + + + TristateCombo + + + Auto + Авто + + + + Yes + Да + + + + No + Нет + + + + VideoEqualizer + + + Contrast + Контрастность + + + + Brightness + Яркость + + + + Hue + Оттенок + + + + Saturation + Насыщенность + + + + Gamma + Гамма + + + + &Reset + Сб&рос + + + + &Set as default values + &Установки по умолчанию + + + + Use the current values as default values for new videos. + Использовать данные настройки по умолчанию для новых файлов. + + + + Set all controls to zero. + Установить все значения в ноль. + + + + Video Equalizer + Видеоэквалайзер + + + + Information + Информация + + + + The current values have been stored to be used as default. + Текущие параметры были сохранены как используемые по умолчанию. + + + + VideoPreview + + + Video preview + Предпросмотр видео + + + + Cancel + Отмена + + + + Generated by SMPlayer + Сгенерировано SMPlayer-ом + + + + Creating thumbnails... + Создание миниатюр... + + + + File: %1 + Файл: %1 + + + + Size: %1 MB + Размер: %1 MB + + + + Resolution: %1 x %2 + Разрешение: %1 x %2 + + + + Length: %1 + Продолжительность: %1 + + + + Save file + Сохранить файл + + + + Images (*.png *.jpg) + Изображения (*.png *.jpg) + + + + Error saving file + Ошибка сохранения файла + + + + The file couldn't be saved + Файл не может быть сохранен + + + + Error + Ошибка + + + + The following error has occurred while creating the thumbnails: + При создании миниатюр произошла следующая ошибка: + + + + The temporary directory (%1) can't be created + Не удалось создать временную папку (%1) + + + + The mplayer process didn't run + Процесс mplayer не был запущен + + + + Resolution: %1x%2 + Разрешение: %1x%2 + + + + Video format: %1 + Формат видео: %1 + + + + Frames per second: %1 + Кадров в секунду: %1 + + + + Aspect ratio: %1 + Соотношение сторон: %1 + + + + Video bitrate: %1 kbps + Видео битрейт: %1 кбит/с + + + + Audio bitrate: %1 kbps + Аудио битрейт: %1 кбит/с + + + + Audio rate: %1 Hz + Частота выборки аудио: %1 Гц + + + + The file %1 can't be loaded + Не удалось загрузить файл %1 + + + + No filename + Не указано имя файла + + + + The mplayer process didn't start while trying to get info about the video + Процесс mplayer не был запущен при получении информации о видео + + + + The length of the video is 0 + Длительность видео 0 + + + + The file %1 doesn't exist + Файл %1 не существует + + + + Images + Изображения + + + + No info + Нет информации + + + + %1 kbps + %1 кб/с + + + + %1 Hz + %1 Гц + + + + Video bitrate: %1 + Видео битрейт: %1 + + + + Audio bitrate: %1 + Аудио битрейт: %1 + + + + Audio rate: %1 + Частота выборки аудио: %1 + + + + VideoPreviewConfigDialog + + + Default + По умолчанию + + + + Video Preview + Предпросмотр + + + + &File: + &Файл: + + + + &Columns: + Стол&бцы: + + + + &Rows: + Стро&ки: + + + + Add playing time to thumbnails + Добавить время на миниатюрах + + + + &Aspect ratio: + &Соотношение сторон: + + + + &Seconds to skip at the beginnning: + Время &первой миниатюры: + + + + &Maximum width: + &Максимальная ширина: + + + + The preview will be created for the video you specify here. + Окно предпросмотра будет создано для указанного здесь файла. + + + + The thumbnails will be arranged on a table. + Миниатюры будут сгруппированы в таблицу. + + + + This option specifies the number of columns of the table. + Эта опция определяет столбцов в таблице. + + + + This option specifies the number of rows of the table. + Эта опция определяет количество строк в таблице. + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + Если вы отметите эту опцию, время будет отображаться внизу каждой миниатюры. + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + Если соотношение сторон видео неправильное, здесь можно указать другое. + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + Обычно первые кадры чёрные, поэтому неплохой идеей будет пропустить несколько секунд в начале видео. Эта опция определяет, сколько секунд будет пропущено. + + + + This option specifies the maximum width in pixels that the generated preview image will have. + Эта опция указывает максимальную ширину в пикселах, которую будет иметь сгенерированное изображение. + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + Некоторые кадры будут извлечены из видео для создания миниатюр. Здесь вы можете выбрать формат извлекаемых изображений. PNG может дать лучшее качество. + + + + Add playing &time to thumbnails + Добавить& время на миниатюрах + + + + &Extract frames as + Извлечь кадры &как + + + + Enter here the DVD device or a folder with a DVD image. + Укажите здесь устройство DVD или каталог с образом DVD. + + + + &DVD device: + Устройст&во DVD: + + + + VolumeSliderAction + + + Volume + Громкость + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_sk.ts b/plugins/smplayer_plugin/translations/smplayer_sk.ts new file mode 100644 index 000000000..9c5c8b57b --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_sk.ts @@ -0,0 +1,7240 @@ + + + + About + + + Version: %1 + Verzia: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Tento program je slobodný software: možete ho redistribuovať a/alebo modifikovať za podmienok licencie GPL verzia 2. + + + + The following people have contributed with translations: + Ľudia, ktorí pomohli s prekladom: + + + + German + Nemecky + + + + Slovak + Slovensky + + + + Italian + Taliansky + + + + French + Francúzsky + + + + %1, %2 and %3 + %1, %2 a %3 + + + + Simplified-Chinese + Zjednodušená čínština + + + + Russian + Rusky + + + + %1 and %2 + %1 a %2 + + + + Hungarian + Maďarsky + + + + Polish + Poľsky + + + + Japanese + Japonsky + + + + Dutch + Holandsky + + + + Ukrainian + Ukrainsky + + + + Portuguese - Brazil + Portugalská Brazílčina + + + + Georgian + Gruzínsky + + + + Czech + Česky + + + + Bulgarian + Bulharsky + + + + Turkish + Turecky + + + + Swedish + Švédsky + + + + Serbian + Srbsky + + + + Traditional Chinese + Tradičná Čínština + + + + Romanian + Rumunsky + + + + Portuguese - Portugal + Portugalská Portugalčina + + + + Greek + Grécky + + + + Finnish + Fínsky + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + O SMPlayer + + + + &Info + &Info + + + + icon + ikona + + + + &Contributions + &Príspevok kódom + + + + &Translators + &Preklad + + + + &License + &Licencia + + + + Visit our web for updates: + Navštívte našu stránku pre aktualizácie: + + + + Get help in our forum: + Nájdite pomoc v našom fóre: + + + + You can support SMPlayer by making a donation. + Môžete podporiť SMPlayer darom. + + + + More info + Viac informácií + + + + Korean + Kórejsky + + + + Macedonian + Macedónsky + + + + Basque + Baskicky + + + + Using MPlayer %1 + Používa MPlayer %1 + + + + Catalan + Katalánsky + + + + Portable Edition + Prenosná edícia + + + + Using Qt %1 (compiled with Qt %2) + Používa Qt %1 (skompilované s Qt %2) + + + + Slovenian + Slovinsky + + + + Arabic + Arabsky + + + + Kurdish + + + + + Galician + Haličsky + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Meno + + + + Description + Popis + + + + Shortcut + Skratka + + + + &Save + &Uložiť + + + + &Load + &Načítať + + + + Key files + Klávesové skratky + + + + Choose a filename + Vybrať názov súboru + + + + Confirm overwrite? + Potvrdiť prepísanie? + + + + The file %1 already exists. +Do you want to overwrite? + Súbor %1 už existuje. +Chcete ho prepísať? + + + + Choose a file + Vybrať súbor + + + + Error + Chyba + + + + The file couldn't be saved + Súbor nemôže byť uložený + + + + The file couldn't be loaded + Súbor nemože byť načítaný + + + + &Change shortcut... + &Zmeniť odkaz... + + + + AudioEqualizer + + + Audio Equalizer + Audio ekvalizér + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + &Použiť + + + + &Reset + &Resetovať + + + + &Set as default values + &Nastaviť ako štandardné hodnoty + + + + Use the current values as default values for new videos. + Použije aktuálne nastavenie ako štandardné hodnoty pre nové videá. + + + + Set all controls to zero. + Vynulovať všetky nastavenia ekvalizéru. + + + + Information + Informácie + + + + The current values have been stored to be used as default. + Aktuálne hodnoty boli uložené a budú použité ako štandardné. + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer log + + + + SMPlayer - smplayer log + SMPlayer - smplayer log + + + + &Open + &Otvoriť + + + + &Play + &Prehrať + + + + &Video + &Video + + + + &Audio + &Zvuk + + + + &Subtitles + &Titulky + + + + &Browse + &Navigácia + + + + Op&tions + &Možnosti + + + + &Help + &Pomoc + + + + &File... + &Súbor... + + + + D&irectory... + &Adresár... + + + + &Playlist... + &Playlist... + + + + &DVD from drive + &DVD z disku + + + + D&VD from folder... + D&VD z adresáru na disku... + + + + &URL... + &URL... + + + + &Clear + &Vyčistiť zoznam + + + + &Recent files + &Naposledy otvorené súbory + + + + P&lay + &Prehraj + + + + &Pause + &Pauza + + + + &Stop + &Zastav + + + + &Frame step + &Krokovanie obrazu + + + + &Normal speed + &Normálna rýchlosť + + + + &Halve speed + &Polovičná rýchlosť + + + + &Double speed + &Dvojnásobná rýchlosť + + + + Speed &-10% + Rýchlosť &-10% + + + + Speed &+10% + Rýchlosť &+10% + + + + Sp&eed + &Rýchlosť + + + + &Repeat + &Opakovať + + + + &Fullscreen + &Celá obrazovka + + + + &Compact mode + &Kompaktný mód + + + + Si&ze + Veľ&kosť + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Pan Scan + + + + 4:3 &to 16:9 + 4:3 &na 16:9 + + + + &Aspect ratio + &Pomer strán + + + + &None + &Žiadne + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Linear &Blend + + + + &Deinterlace + &Deinterlace + + + + &Postprocessing + &Postprocessing + + + + &Autodetect phase + &Autodetekcia fázy + + + + &Deblock + &Deblocking + + + + De&ring + De&ringing + + + + Add n&oise + &Pridať šum + + + + F&ilters + &Filtre + + + + &Equalizer + &Ekvalizér + + + + &Screenshot + &Snímok obrazovky + + + + S&tay on top + U&držiavať navrchu + + + + &Extrastereo + &Extra stereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtre + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Kanály + + + + &Left channel + &Ľavý kanál + + + + &Right channel + &Pravý kanál + + + + &Stereo mode + S&tereo mód + + + + &Mute + &Stíšiť + + + + Volume &- + Hlasitosť &- + + + + Volume &+ + Hlasitosť &+ + + + + &Delay - + &Oneskorenie - + + + + D&elay + + O&neskorenie + + + + + &Select + &Výber + + + + &Load... + &Načítať... + + + + Delay &- + Oneskorenie &- + + + + Delay &+ + Oneskorenie &+ + + + + &Up + Posunúť &vyššie + + + + &Down + Posunúť &nižsie + + + + &Title + &Titul + + + + &Chapter + &Kapitola + + + + &Angle + &Uhol pohľadu + + + + &Playlist + Play&list + + + + &Show frame counter + Zobraziť &počítadlo obrázkov + + + + &Disabled + &Zakázať + + + + &Seek bar + &Posuvník + + + + &Time + &Čas + + + + Time + T&otal time + Čas + c&elkový čas + + + + &OSD + &OSD + + + + &View logs + &Zobraziť logy + + + + P&references + &Nastavenia + + + + About &Qt + O &Qt + + + + About &SMPlayer + O &SMPlayer + + + + <empty> + <prázdny> + + + + Video + Video + + + + Audio + Zvuk + + + + Playlists + Playlist + + + + All files + Všetky súbory + + + + Choose a file + Vybrať súbor 1 + + + + SMPlayer - Information + SMPlayer - Informácie + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Zariadenie CD / DVD ešte nebolo nakonfigurované. +Môžete to urobiť teraz v nasledujúcom dialógu. + + + + Choose a directory + Vybrať adresár 2 + + + + Subtitles + Titulky + + + + About Qt + O Qt + + + + Playing %1 + Prehrávam %1 + + + + Pause + Pauza + + + + Stop + Zastav + + + + Play / Pause + Prehrať / Pauza + + + + Pause / Frame step + Pauza / Krokovanie obrazu + + + + U&nload + &Uvoľniť + + + + V&CD + V&CD + + + + C&lose + Z&atvoriť + + + + View &info and properties... + Zobraziť &informácie a vlastnosti... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Reset + + + + Move &left + Posunúť vľ&avo + + + + Move &right + Posunúť v&pravo + + + + Move &up + Posunúť &vyššie + + + + Move &down + Posunúť &nižšie + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Predchádzajúci riadok titulkov + + + + N&ext line in subtitles + &Nasledujúci riadok titulkov + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Znížiť hlasitosť (2) + + + + Inc volume (2) + Zvýšiť hlasitosť (2) + + + + Exit fullscreen + Ukončiť režim celej obrazovky + + + + OSD - Next level + OSD - ďalšia úroveň + + + + Dec contrast + Znížiť kontrast + + + + Inc contrast + Zvýšiť kontrast + + + + Dec brightness + Znínžiť jas + + + + Inc brightness + Zvýšiť jas + + + + Dec hue + Znížiť odtieť + + + + Inc hue + Zvýšiť odtieň + + + + Dec saturation + Znížiť saturáciu + + + + Dec gamma + Znížiť gammu + + + + Next audio + Ďalšia zvuková stopa + + + + Next subtitle + Ďalšie titulky + + + + Next chapter + Ďalšia kapitola + + + + Previous chapter + Predchádzajúca kapitola + + + + Inc saturation + Zvýšiť saturáciu + + + + Inc gamma + Zvýšiť gammu + + + + &Load external file... + &Načítať externý súbor... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normálne) + + + + Y&adif (double framerate) + Y&adif (dvojnásobný framerate) + + + + &Next + Ďa&lší + + + + Pre&vious + Pre&dchádzajúci + + + + Volume &normalization + &Normalizácia hlasitosti + + + + &Audio CD + &Audio CD + + + + Denoise nor&mal + Denoise nor&mal + + + + Denoise &soft + Denoise &jemné + + + + Denoise o&ff + Denoise &vypnuté + + + + Use SSA/&ASS library + Použiť SSA/&ASS knižnicu + + + + Flip i&mage + Prevrátiť &obraz + + + + &Toggle double size + Prepnúť na &dvojnásobnú veľkosť + + + + S&ize - + Z&menšiť + + + + Si&ze + + Z&väčšiť + + + + Add &black borders + Pridať čierne &pásy + + + + Soft&ware scaling + Soft&warové škálovanie + + + + &FAQ + &FAQ - často kladené otázky + + + + Visualize &motion vectors + Zobraziť pohyb &vektorov + + + + &Command line options + Parametre &príkazového riadku + + + + SMPlayer command line options + Parametre príkazového riakdu pre SMPlayer + + + + Enable &closed caption + Zapnúť &closed caption + + + + &Forced subtitles only + &Iba vynútené titulky + + + + Reset video equalizer + Resetovať video ekvalizér + + + + MPlayer has finished unexpectedly. + MPlayer neočakávane skončil. + + + + Exit code: %1 + + + + + MPlayer failed to start. + MPlayer sa nepodarilo spustiť. + + + + Please check the MPlayer path in preferences. + Skontrolujte, prosím, nastavenie cesty pre MPlayer v nastaveniach. + + + + MPlayer has crashed. + MPlayer spadol. + + + + See the log for more info. + Pre viac informácií sa pozrite do záznamu. + + + + &Rotate + &Otočenie + + + + &Off + &Vypnúť + + + + &Rotate by 90 degrees clockwise and flip + &Otočiť o 90 stupňov v smere hodín a prevrátiť + + + + Rotate by 90 degrees &clockwise + Otočiť o 90 s&tupňov v smere hodín + + + + Rotate by 90 degrees counterclock&wise + Otočiť o 90 stupňov pro&ti hodinám + + + + Rotate by 90 degrees counterclockwise and &flip + Otočiť o 90 stupňov prot&i hodinám a prevrátiť + + + + &Jump to... + &Prejsť na... + + + + Show context menu + Zobraziť kontextové menu + + + + Multimedia + Multimédiá + + + + E&qualizer + &Ekvalizér + + + + Reset audio equalizer + Resetovať audio ekvalizér + + + + Find subtitles on &OpenSubtitles.org... + Nájsť titulky na &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + Nahrať &titulky na OpenSubtitles.org... + + + + &Tips + &Tipy + + + + &Auto + &Auto + + + + Speed -&4% + Rýchlosť -&4% + + + + &Speed +4% + &Rýchlosť +4% + + + + Speed -&1% + Rýchlosť -&1% + + + + S&peed +1% + Rý&chlosť +1% + + + + Scree&n + &Obrazovka + + + + &Default + Š&tandardné + + + + Mirr&or image + &Zrkadlový obraz + + + + Next video + + + + + &Track + video + &Stopa + + + + &Track + audio + &Stopa + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer je stále spustený + + + + S&how icon in system tray + Zobraziť ikonu v &systémovej lište + + + + &Hide + &Skryť + + + + &Restore + &Obnoviť + + + + &Quit + &Koniec + + + + Playlist + Playlist + + + + Core + + + Brightness: %1 + Jas: %1 + + + + Contrast: %1 + Kontrast: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Odtieň: %1 + + + + Saturation: %1 + Saturácia: %1 + + + + Volume: %1 + Hlasitosť: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + Mierka písma: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Vitajte v programe SMPlayer + + + + Audio + Zvuk + + + + Subtitle + Titulky + + + + &Main toolbar + &Hlavný panel + + + + &Language toolbar + Panel &jazykov + + + + &Toolbars + &Panely + + + + EqSlider + + + icon + ikona + + + + ErrorDialog + + + Hide log + Skryť záznam + + + + Show log + Zobraziť záznam + + + + MPlayer Error + Chyba MPlayera + + + + icon + ikona + + + + Error + Chyba + + + + FileDownloader + + + Downloading... + Sťahujem... + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - vlastnosti súboru + + + + &Information + &Informácie + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + Vyberte &demuxer, ktorý bude použitý pre tento súbor: + + + + &Reset + &Reset + + + + &Video codec + &Video kódek + + + + &Select the video codec: + &Vyberte video kódek: + + + + A&udio codec + &Audio kódek + + + + &Select the audio codec: + &Vyberte audio kódek: + + + + &MPlayer options + &MPlayer možnosti + + + + Additional Options for MPlayer + Ďalšie možnosti pre MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Extra parametre pre MPlayer +Píšte ich oddelené medzerami +Príklad: -flip -nosound + + + + &Options: + &Možnosti: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Prídavné video filtre. +Píšte ich oddelené čiarkou "?". Nepoužívajte medzery! +Príklad: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + V&ideo filtre: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Prídavné audio filtre. +Píšte ich oddelené čiarkou "?". Nepoužívajte medzery! +Príklad: resample=44100:0:0,volnorm + + + + Audio &filters: + Audio &filtre: + + + + OK + OK + + + + Cancel + Zrušiť + + + + Apply + Použiť + + + + FindSubtitlesWindow + + + Language + Jazyk + + + + Name + Názov + + + + Format + Formát + + + + Files + Súbory + + + + Date + Dátum + + + + Uploaded by + Nahrané + + + + All + Všetky + + + + Close + Zatvoriť + + + + &Download + &Stiahnuť + + + + &Copy link to clipboard + &Kopírovať odkaz do schránky + + + + Error + Chyba + + + + Download failed: %1. + Zlyhalo sťahovanie: %1. + + + + Connecting to %1... + Pripájam sa k %1... + + + + Downloading... + Sťahujem... + + + + Done. + Hotovo. + + + + %1 files available + %1 dostupných súborov + + + + Failed to parse the received data. + + + + + Find Subtitles + Nájsť titulky + + + + &Subtitles for + &Titulky pre + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Chyba pri ukladaní súboru + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Hlavné + + + + Size + Veľkosť + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Dĺžka + + + + Demuxer + Demuxer + + + + Name + Meno + + + + Artist + Umelec + + + + Author + Autor + + + + Album + Album + + + + Genre + Typ + + + + Date + Dátum + + + + Track + Stopa + + + + Copyright + Copyright + + + + Comment + Komentár + + + + Software + Software + + + + Clip info + Informácie o klipe + + + + Video + Video + + + + Resolution + Rozlíšenie + + + + Aspect ratio + Pomer strán + + + + Format + Formát + + + + Bitrate + Bitový tok + + + + %1 kbps + %1 kbps + + + + Frames per second + Obrázkov za sekundu + + + + Selected codec + Použitý kódek + + + + Initial Audio Stream + Zvuková stopa + + + + Rate + Frekvencia + + + + %1 Hz + %1 Hz + + + + Channels + Kanály + + + + Audio Streams + Zvukové stopy + + + + Language + Jazyk + + + + empty + prázdny + + + + Subtitles + Titulky + + + + Type + Typ + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + Názov streamu + + + + Stream URL + URL streamu + + + + File + Súbor + + + + InputDVDDirectory + + + Choose a directory + Vybrať adresár + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Prehrať DVD z adresára na disku + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Môžete prehrávať DVD uložené vo vašom počítači. Stačí vybrať adresár obsahujúci adresáre VIDEO_TS a AUDIO_TS. + + + + Choose a directory... + Vybrať adresár... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Vložte URL + + + + &URL: + &URL: + + + + It's a &playlist + Je to &playlist + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + URL bude považovaná za playlist. Otvorí sa ako text a budú sa prehrávať jednotlivé URL z nej. + + + + Languages + + + Afar + Afarsky + + + + Abkhazian + + + + + Afrikaans + Afrikaansky + + + + Amharic + + + + + Arabic + Arabsky + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + Azerbajdžánsky + + + + Bashkir + + + + + Byelorussian + Bielorusky + + + + Bulgarian + Bulharsky + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + Katalánsky + + + + Corsican + + + + + Czech + Česky + + + + Welsh + + + + + Danish + + + + + German + Nemecky + + + + Greek + Grécky + + + + English + Anglicky + + + + Esperanto + Esperantsky + + + + Spanish + Španielsky + + + + Estonian + Estónsky + + + + Basque + Baskicky + + + + Persian + + + + + Finnish + Fínsky + + + + Faroese + + + + + French + Francúzsky + + + + Frisian + + + + + Irish + + + + + Galician + Haličsky + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + Maďarsky + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + Taliansky + + + + Inuktitut + + + + + Japanese + Japonsky + + + + Javanese + + + + + Georgian + Gruzínsky + + + + Kazakh + Kazašsky + + + + Greenlandic + Grónsky + + + + Kannada + + + + + Korean + Kórejsky + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + Macedónsky + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + Holandsky + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + Poľsky + + + + Portuguese + + + + + Quechua + + + + + Romanian + Rumunsky + + + + Russian + Rusky + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + Slovensky + + + + Slovenian + Slovinsky + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + Srbsky + + + + Sundanese + + + + + Swedish + Švédsky + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Turecky + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + Ukrajinsky + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + Portugalská Brazílčina + + + + Portuguese - Portugal + Portugalská Portugalčina + + + + Simplified-Chinese + Zjednodušená čínština + + + + Traditional Chinese + Tradičná Čínština + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Západné Európske jazyky + + + + Western European Languages with Euro + Západné Európske jazyky s Euro + + + + Slavic/Central European Languages + Slovanské/Stredo-Európske jazyky + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galicisch, Maltesisch, Turecky + + + + Old Baltic charset + Staré Baltické kódovanie + + + + Cyrillic + Cyrilika + + + + Modern Greek + Moderná Gréčtina + + + + Baltic + Baltic + + + + Celtic + Keltština + + + + Hebrew charsets + Hebrejská znaková sada + + + + Ukrainian, Belarusian + Ukrajinsky, Bielorusky + + + + Simplified Chinese charset + Znaková sada zjednodušenej Čínštiny + + + + Traditional Chinese charset + Znakova sada tradičnej Čínštiny + + + + Japanese charsets + Japonská znaková sada + + + + Korean charset + Kórejská znaková sada + + + + Thai charset + Thajsky + + + + Cyrillic Windows + Cyrilika - Windows + + + + Slavic/Central European Windows + Slovanské/Stredo-Európske jazyky - Windows + + + + Arabic Windows + Arabsky - Windows + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Vyberte súbor, do ktorého sa uloží log + + + + Confirm overwrite? + Potvrdiť prepísanie? + + + + The file already exists. +Do you want to overwrite? + Súbor už existuje +Chcete ho prepísať? + + + + Error saving file + Chyba pri ukladaní súboru + + + + The log couldn't be saved + Log nemôže byť uložený + + + + Logs + Logy + + + + LogWindowBase + + + Log Window + Logovacie okno + + + + Save + Uložiť + + + + Copy to clipboard + Skopírovať do schránky + + + + Close + Zatvoriť + + + + &Close + &Zatvoriť + + + + MiniGui + + + Control bar + Ovládací panel + + + + MpcGui + + + Control bar + Ovládací panel + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Názov + + + + Length + Dĺžka + + + + Choose a file + Vybrať súbor + + + + Choose a filename + Vybrať názov súboru + + + + Confirm overwrite? + Potvrdiť prepísanie? + + + + Select one or more files to open + Vyberte jeden alebo viac súborov na otvorenie + + + + Choose a directory + Vybrať adresár + + + + The file %1 already exists. +Do you want to overwrite? + Súbor %1 už existuje. +Chcete ho prepísať? + + + + Edit name + Zmeniť názov + + + + Type the name that will be displayed in the playlist for this file: + Napíšte názov, ktorý bude zobrazený v zozname pre tento súbor: + + + + &Play + &Prehrať + + + + &Edit + &Upraviť + + + + Playlists + Zoznam + + + + All files + Všetky súbory + + + + &Load + &Načítať + + + + &Save + &Uložiť + + + + &Next + Ďa&lší + + + + Pre&vious + Pre&dchádzajúci + + + + Move &up + Posunúť &vyššie + + + + Move &down + Posunúť &nižšie + + + + &Repeat + &Opakovať + + + + S&huffle + &Náhodný výber + + + + Add &current file + &Pridať aktuálny súbor + + + + Add &file(s) + Pridať &súbor(y) + + + + Add &directory + Pridať &adresár + + + + Remove &selected + &Odstrániť vybrané + + + + Remove &all + Odstrániť &všetky + + + + SMPlayer - Playlist + SMPlayer - Playlist + + + + Add... + Pridať... + + + + Remove... + Odstrániť... + + + + Playlist modified + Playlist zmenený + + + + There are unsaved changes, do you want to save the playlist? + Vykonané zmeny v playliste, chcete uložiť playlist? + + + + Preferences + Nastavenia + + + + PlaylistPreferences + + + Playlist - Preferences + Playlist - Nastavenia + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + Rozšírené + + + + Auto + Automaticky + + + + &Advanced + &Rozšírené + + + + icon + ikona + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Extra parametre pre MPlayer. +Píšte ich oddelené medzerou +Príklad: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Ďalšie video filtre. +Oddeľujte ich čiarkami ",". Nepoužívajte medzery +Príklad: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Zvukové filtre. Rovnaké pravidlá ako pre video filtre. +Príklad: resample=44100:0:0,volnorm + + + + Log MPlayer output + Logovať výstup programu MPlayer + + + + Log SMPlayer output + Logovať výstup programu SMPlayer + + + + This option is mainly intended for debugging the application. + Táto možnosť je používaná pre odhaľovanie chýb v aplikácií. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Zaškrtnutím tejto možnosti môžete znížiť blikanie obrazu, ale môže to spôsobiť, že video nebude zobrazené správne. + + + + Filter for SMPlayer logs + Filter pre logy programu SMPlayer + + + + &Monitor aspect: + Pomer strán &monitoru: + + + + &Run MPlayer in its own window + &Spustiť MPlayer vo vlastnom okne + + + + &Options: + &Možnosti: + + + + V&ideo filters: + V&ideo filtre: + + + + Audio &filters: + Audio &filtre: + + + + &Colorkey: + &Farba: + + + + Log &SMPlayer output + Logovať výstup programu &SMPlayer + + + + &Filter for SMPlayer logs: + &Filter pre SMPlayer logy: + + + + C&hange... + &Zmeniť... + + + + Logs + Logy + + + + Log MPlayer &output + Logovať výstup programu &MPlayer + + + + Options for MP&layer + Možnosti pre &MPlayer + + + + Autosave MPlayer log + Automaticky ukladať logy MPlayeru + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Log programu MPlayer zapíše do určeného súboru vždy, keď sa spustí prehrávanie súboru. Je to užitočné pre externé programy, ktoré môžu takto dostať informáciu o aktuálne prehrávanom súbore. + + + + Autosave MPlayer log filename + Súbore pre automatické ukladanie + + + + Enter here the path and filename that will be used to save the MPlayer log. + Zadajte cestu a názov súboru, kam sa budú ukladať logy programu MPlayer. + + + + A&utosave MPlayer log to file + Automaticky &ukladať logy do súboru + + + + Pass short filenames (8+3) to MPlayer + Podsúvaj MPlayeru krátke názvy súborov (8+3) + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + MPlayer momentálne nevie otvárať súbory, ktoré v názve obsahujú znaky mimo lokálnu kódovú stránku. Použitie tejto možnosti zaistí podsúvanie krátkych názvov súborov, ktoré zaistia ich otvorenie. + + + + &Pass short filenames (8+3) to MPlayer + Použi &krátke názvy súborou (8+3) pre MPlayer + + + + Monitor aspect + Pomer strán monitoru + + + + Select the aspect ratio of your monitor. + Vyberte pomer strán vášho monitoru. + + + + Run MPlayer in its own window + Spúšťať MPlayer vo vlastnom okne + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Pokiaľ nebol nájdený index súboru, vytvorí sa nový, ktorý povolí posuv vo videu. Užitočné pri poškodených/nekompletných stiahnutých súboroch, alebo pre zle vytvorených súboroch. Neumožňuje však posuv pri médiách nepodporujúcich posuv (stdin, rúra, ...).<br> Poznámka: vytvorenie indexu môže trvať pár minút. + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Typ + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Varovanie + + + + Not all files could be associated. Please check your security permissions and retry. + Všetky súbory nebudú asociované. Prosím skontrolujte prístupové práva a skúste znovu. + + + + File Types + Typy súborov + + + + Select all + Vybrať všetky + + + + Check all file types in the list + Označ všetky typy v zozname + + + + Uncheck all file types in the list + Zruš označenie všetkých typov v zozname + + + + List of file types + Zoznam typov + + + + File types + Prípony + + + + Media files handled by SMPlayer: + Typy súborov otvárané programom SMPlayer: + + + + Select All + Vybrať všetky + + + + Select None + Nevybrať žiadne + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Skontrolujte typy súborov, ktoré chcete otvárať programom SMPlayer. Kliknutím na tlačítko "Použiť" zmeníte asociáciu všetkých označených typov. Odznačením niektorej položky obnovíte pôvodnú asociáciu. + + + + Select none + Nevybrať žiadne + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Poznámka:</b> (Obnovenie nefunguje v systéme Windows Vista). + + + + PrefDrives + + + Drives + Zariadenia + + + + icon + ikona + + + + CD device + CD zariadenie + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Vyberte vaše CD-ROM zariadenie. Bude použité pre prehrávanie Video CD a Audio CD. + + + + DVD device + DVD zariadenie + + + + Choose your DVD device. It will be used to play DVDs. + Vyberte vaše DVD-ROM zariadenie. Bude použité pre prehrávanie DVD diskov. + + + + Select your &CD device: + Vyberte vaše &CD zariadenie: + + + + Select your &DVD device: + Vyberte vaše &DVD zariadenie: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer momentálne nerobí autodetekciu CD alebo DVD zariadení. Ak chcete prehrávať CD alebo DVD disky, musíte najprv vybrať vaše zariadenia (môžu byť použité tie isté). + + + + PrefGeneral + + + General + Hlavné + + + + &General + &Hlavné + + + + Paths + Umiestnenia + + + + Media settings + Nastavenia médií + + + + Preferred audio and subtitles + Preferovaná zvuková stopa a titulky + + + + Video + Video + + + + Start videos in fullscreen + Prehrávať video v režime celej obrazovky + + + + Disable screensaver + Zakázať šetrič obrazovky + + + + Audio + Zvuk + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Select the mplayer executable + Umiestnenie programu mplayer + + + + Executables + Súbory + + + + All files + Všetky súbory + + + + Select a directory + Vyberte adresár + + + + MPlayer executable + Umiestnenie programu MPlayer + + + + Screenshots folder + Adresár pre umiestnenie snímkov + + + + Video output driver + Výstupné video zariadenie + + + + Audio output driver + Výstupné zvukové zariadenie + + + + Select the audio output driver. + Výstupné zvukové zariadenie (alsa, oss, nas).<br>Viacej možností získate príkazom <code>mplayer -ao help</code>. + + + + Remember settings + Zapamätať nastavenia + + + + Preferred audio language + Preferovaný jazyk zvukovej stopy + + + + Preferred subtitle language + Prefoerovaný jazyk s titulkami + + + + Software video equalizer + Softwarový video ekvalizér + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Použite túto možnosť, ak video ekvalizér nie je podporovaný vašou grafickou kartou, alebo výstupným video zariadením.<br><b>Poznámka</b> táto možnosť može byť nekompatibilná s niektorými výstupnými video zariadeniami. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Ak použijete túto možnosť, všetky videá budú spúšťané v režime celej obrazovky. + + + + Software volume control + Softwarové ovládanie hlasitosti + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Použi softwarový mixér miesto mixéru zvukovej karty. + + + + Postprocessing quality + Kvalita postprocessingu + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Dynamická zmena úrovne postprocessingu závislá na vyťažení procesoru. Veľkosť ktorú určíte bude maximálna veľkosť. Bežne môžete použiť vysoké nastavenie. + + + + Change volume + Zmeniť hlasitosť + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + SMPlayer si bude pamätať nastavenie hlasitosti pre každý otvorený súbor a pri opätovnom prehrávaní súboru nastaví túto hlasitosť. Pre súbory otvorené prvý krát sa použije štandardná hlasitosť. + + + + 0 + 0 + + + + &Change volume on every file + &Zmeniť hlasitosť pri každom súbore + + + + Select the &MPlayer executable: + Umiestnenie programu &MPlayer: + + + + &Folder for storing screenshots: + &Adresár pre ukladanie snímkov: + + + + &Audio: + &Zvuk: + + + + &Remember settings for all files (audio track, subtitles...) + &Pamätaj nastavenie všetkých súborov (zvuková stopa, titulky, čas...) + + + + Su&btitles: + T&itulky: + + + + &Quality: + &Kvalita: + + + + Start videos in &fullscreen + Prehrávať video v režime &celej obrazovky + + + + Disable &screensaver + Zakázať šetrič &obrazovky + + + + &Default volume: + Štandardná &hlasitosť: + + + + Use s&oftware volume control + Použi &softwarové ovládanie hlasitosti + + + + Ma&x. Amplification: + Ma&x. amplifikácia: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS pass-through S/PDIF + + + + Direct rendering + Priamy rendering + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Zapnutie priameho renderingu. Nie je podporované všetkými kódekmi a grafickými výstupmi. <br><b>Upozornenie:</b> môže spôsobovať zlé zobrazenie OSD/titulkov! + + + + Double buffering + Dvojitý zásobník (double buffer) + + + + D&irect rendering + &Priamy rendering + + + + Dou&ble buffering + &Dvojitý zásobník + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Dvojitý zásobník (double buffer) redukuje blikanie medzi prepínaním dvoch obrázkov v pamäti a zobrazením jedného, pričom druhý sa dekóduje. Ak je táto možnosť zakázaná, môže niekedy spôsobiť blikanie OSD/titulkov. + + + + &Enable postprocessing by default + Štandardne použiť &postprocessing + + + + Volume &normalization by default + Štandardne použiť &normalizáciu hlasitosti + + + + Close when finished + Zatvoriť pri skončení prehrávania + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Po skončení prehrávania aktuálneho súboru/playlistu za zatvorí okno programu SMPlayer. + + + + 2 (Stereo) + 2 (stereo) + + + + 4 (4.0 Surround) + 4 (4.0 surround) + + + + 6 (5.1 Surround) + 6 (5.1 surround) + + + + C&hannels by default: + Štandardný počet &kanálov: + + + + &Pause when minimized + &Pozastaviť prehrávanie pri minimalizovaní + + + + Pause when minimized + Pozastaviť prehrávanie pri minimalizovaní hlavného okna + + + + Enable postprocessing by default + Štandardne použiť postprocessing + + + + Max. Amplification + Max. amplifikácia + + + + Volume normalization by default + Štandardne použiť normalizáciu hlasitosti + + + + Maximizes the volume without distorting the sound. + Maximalizácia hlasitosti bez poškodenia zvuku. + + + + Default volume + Štandardná hlasitosť + + + + Sets the initial volume that new files will use. + Nastaví počiatočnú úroveň hlasitosti, ktorú novo prehrávané video použije. + + + + Channels by default + Štandardný počet kanálov + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Nastavuje maximálnu úroveň amplifikácie v percentách (štandardne: 110). Hodnota 200 povolí zdvihnúť hlasitosť na dvojnásobok. S hodnotami nižšími ako 100 bude počiatočná hlasitosť (ktorá je 100%) vyššia ako je maximum, čo spôsobí nesprávne zobrazenie OSD. + + + + Uses hardware AC3 passthrough + Použi hardwarové AC3 passthrough + + + + Postprocessing will be used by default on new opened files. + Postprocessing bude štandardne použitý na všetky otvorené súbory. + + + + Audio track + Zvuková stopa + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Určuje štandardnú zvukovú stopu, ktorá bude použitá pri prehrávaní nového súboru. Ak daná stopa neexistuje, použije sa prvá nájdená.<br><b>Poznámka:</b> "Preferovaná zvuková stopa" má prednosť pred touto možnosťou. + + + + Subtitle track + Titulky + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Určuje štandardný jazyk titulkov, ktoré budú použité pri prehrávaní nového súboru. Ak dané titulky neexistujú, použijú sa prvé nájdené.<br><b>Poznámka:</b> "Preferovaný jazyk titulkov" má prednosť pred touto možnosťou. + + + + Or choose a track number: + Alebo vyberte číslo stopy: + + + + Audi&o: + &Zvuk: + + + + Preferred language: + Preferovaný jazyk: + + + + Preferre&d audio and subtitles + &Preferovaný zvuk a titulky + + + + &Subtitle: + &Titulky: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Nastavenie preferovaného jazyka pre zvukové stopy a titulky. Ak je vybrané médium s viacerými zvukovými stopami a titulkami, SMPlayer bude používať nastavený jazyk. Toto nastavenie bude fungovať iba s médiami, ktoré majú informácie o zvukových stopách a titulkoch, ako napríklad DVD alebo mkv súbory.<br>Akceptované sú regulárne výrazy.<br>Príklad: <b>sk|cs|en</b> použije slovenskú zvukovú stopu. Ak nebude nájdená, použije sa česká zvuková stopa. Ak nebude nájdená ani česká, použije sa anglická zvuková stopa. Ak nebude nájdená ani anglická zvuková stopa, použije sa prvá zvuková stopa na médiu. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + Rýchle &prehrávanie bez zmeny výšky + + + + High speed playback without altering pitch + Rýchle prehrávanie bez zmeny výšky + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Povolí zmenu rýchlosti prehrávania bez zmeny výšky. Potrebuje minimálne MPlayer dev-SVN-r24924.<br><b>Poznámka:</b> parameter "scaletempo". + + + + Change volume just before playing + Zmeniť hlasitosť ešte pred prehrávaním + + + + &Video + &Obraz + + + + Use s&oftware video equalizer + &Použi softwarový video ekvalizér + + + + A&udio + &Zvuk + + + + Volume + Hlasitosť + + + + None + Žiadny + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Klávesnica a myš + + + + &Keyboard + &Klávesnica + + + + icon + ikona + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Zmena klávesových skratiek. V stĺpci skratky dopíšte do vybranej bunky skratku. Môžete uložiť zoznam skratiek do súboru a poslať svojim známym, alebo použiť tento súbor na inom počítači. + + + + &Mouse + &Myš + + + + Button functions: + Funkcie tlačítok: + + + + Media seeking + Stredný posuv + + + + Volume control + Ovládanie hlasitosti + + + + Zoom video + Zväčšiť/zmenšiť video + + + + None + Žiadny + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Zmena klávesových skratiek. V stĺpci skratky dopíšte do vybranej bunky skratku. Môžete uložiť zoznam skratiek do súboru a poslať svojim známym, alebo použiť tento súbor na inom počítači. + + + + &Left click + Ľavý k&lik + + + + &Double click + &Dvoj klik + + + + &Wheel function: + Funkcia &koliečka: + + + + Shortcut editor + Editor skratiek + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Pomocou tejto tabuľky môžete zmeniť klávesovú skratku často používaných akcií. Dvojklik, ENTER alebo talčítko "Zmeniť odkaz..." na vybranej položke otvorí dialóg "Zmeniť skatku".<br> + Sú dve možnosti zmeny skratky: ak je stlačené tlačítko "Zachytiť", tak stlačením požadovanej kombinácie kláves vytvoríte novú skratku. Ak tlačítko "Zachytiť" nie je stlačené, môžete slovne napísať klávesovú skratku. + + + + Left click + Ľavý klik + + + + Select the action for left click on the mouse. + Vyberte akciu pre kliknutie ľavým tlačítkom myši. + + + + Double click + Dvoj klik + + + + Select the action for double click on the mouse. + Vyberte akciu pre dvojklik ľavým tlačítkom myši. + + + + Wheel function + Funkcia koliečka + + + + Select the action for the mouse wheel. + Vyberte akciu pre potočenie koliečkom na myši. + + + + Play + Prehrať + + + + Pause + Pauza + + + + Stop + Zastav + + + + Fullscreen + Celá obrazovka + + + + Compact + Kompaktný mód + + + + Screenshot + Snímok obrazovky + + + + On top + Udržiavať navrchu + + + + Mute + Stíšiť + + + + Frame counter + Počítadlo obrázkov + + + + Reset zoom + Reset zoom + + + + Exit fullscreen + Ukončiť režim celej obrazovky + + + + Double size + Dvojnásobná veľkosť + + + + Play / Pause + Prehrať / Pauza + + + + Pause / Frame step + Pauza / Krokovanie obrazu + + + + Playlist + Playlist + + + + Preferences + Nastavenia + + + + No function + Žiadna funkcia + + + + Change speed + Zmeniť rýchlosť + + + + Normal speed + Normálna rýchlosť + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - ďalšia úroveň + + + + Show context menu + Zobraziť kontextové menu + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Rozhranie + + + + <Autodetect> + <Automatická detekcia> + + + + Default + Štandardné + + + + &Interface + &Rozhranie + + + + Seeking + Posuv + + + + Never + Nikdy + + + + Whenever it's needed + Kedykoľvek to bude nutné + + + + Only after loading a new video + Iba pri načítaní videa + + + + Recent files + Posledné použité súbory + + + + Language + Jazyk + + + + Here you can change the language of the application. + Zmena jazyka v aplikácií. + + + + Instances + Inštancie + + + + &Short jump + &Krátky posuv + + + + &Medium jump + &Stredný posuv + + + + &Long jump + &Dlhý posuv + + + + Mouse &wheel jump + Posuv koliečkom &myši + + + + &Use only one running instance of SMPlayer + Vždy iba &jedna inštancia programu SMPlayer + + + + Ma&x. items + Ma&x. položiek + + + + St&yle: + Š&týl: + + + + Ico&n set: + &Sada ikon: + + + + L&anguage: + &Jazyk: + + + + Main window + Hlavné okno + + + + Auto&resize: + Automatická zmena &veľkosti: + + + + R&emember position and size + &Zapamätať pozíciu a veľkosť + + + + Default font: + Štandardné písmo: + + + + &Change... + &Zmeniť... + + + + &Behaviour of time slider: + Chovanie časového &posuvníka: + + + + Seek to position while dragging + Zmeniť pozíciu počas ťahania + + + + Seek to position when released + Zmeniť pozíciu po uvoľnení + + + + TextLabel + + + + + &Seeking + &Posuv + + + + Ins&tances + &Inštancie + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Výkon + + + + &Performance + &Výkon + + + + Priority + Priorita + + + + Select the priority for the MPlayer process. + Priorita procesu MPlayer. + + + + realtime + najvyššia + + + + high + vysoká + + + + abovenormal + viac ako normálna + + + + normal + normálna + + + + belownormal + nižšia ako normálna + + + + idle + nízka + + + + Cache + Cache + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Cache zvýši výkon na pomalých médiách + + + + Allow frame drop + Preskakovanie snímkov + + + + Synchronization + Synchronizácia + + + + Audio/video auto synchronization + Automatická synchronizácia obrazu a zvuku + + + + Fast audio track switching + Rýchle prepínanie zvukových stôp + + + + Fast seek to chapters in dvds + Rýchly posuv v kapitolách na DVD + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Nastavuje prioritu programu mplayer podobne ako sú preddefinované priority vo Windowse.<br><b>Upozornenie:</b> použite najvyššej priority môže spôsobiť zablokovanie systému. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Preskakovanie niektorých snímkov na pomalých systémoch pre udržanie synchronizáciu obrazu a zvuku. + + + + Allow hard frame drop + Povoliť časté preskakovanie snímkov + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Intenzívnejšie preskakovanie snímkov. Spôsobuje nesprávne dekódovanie a výstupný obraz môže byť deformovaný! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Postupné prispôsobenie synchronizácie obrazu a zvuku založené na meraní zvukovej odchýlky. + + + + Priorit&y: + &Priorita: + + + + &Allow frame drop + &Povoliť preskakovanie snímkov + + + + Allow &hard frame drop (can lead to image distortion) + Povoliť časté p&reskakovanie (môže vytvárať skreslený obraz) + + + + Audio/&video auto synchronization + &Zvuková/obrazová automatická synchronizácia + + + + Fact&or: + Fa&ktor: + + + + &Fast audio track switching + Rýchle prepínanie &zvukových stôp + + + + Fast &seek to chapters in dvds + Rýchly posuv v &kapitolách na DVD + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Najrýchlejšia metóda prepínania kapitol, ale nemusí fungovať s niektorými DVD diskami. + + + + Skip loop filter + Vynechať loop filter + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Možnosti:<br><b>Áno</b>: skúsi použiť najrýchlejšiu metódu zmeny zvukovej stopy (nemusí fungovať s niektorými formátmi).<br><b>Nie</b>: proces MPlayer bude reštartovaný vždy po zmene zvukovej stopy.<br><b>Auto</b>: SMPlayer sa rozhodne sám na základe verzie programu MPlayer. + + + + Cache for files + Vyrovnávacia pamäť pre súbory + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Aké množstvo pamäte (v kBytoch) sa použije ako vyrovnávacia pamäť pre súbor. + + + + Cache for streams + Vyrovnávacia pamäť pre prúdy + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Aké množstvo pamäte (v kBytoch) sa použije ako vyrovnávacia pamäť pre URL. + + + + Cache for DVDs + Vyrovnávacia pamäť pre DVD + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Aké množstvo pamäte (v kBytoch) sa použije ako vyrovnávacia pamäť pre DVD.<br><b>Upozornenie</b>: Posuv a prepínanie kapitol na DVD nemusí pri použítí vyrovnávacej pamäte fungovať správne. + + + + &Cache + &Vyrovnávacia pamäť + + + + Cache for &DVDs: + Vyrovnávacia pamäť pre &DVD: + + + + Cache for &local files: + Vyrovnávacia pamäť pre lokálne &súbory: + + + + Cache for &streams: + Vyrovnávacia pamäť pre &prúdy: + + + + Enabled + Povolený + + + + Skip (always) + Vynechať (vždy) + + + + Skip only on HD videos + Vynechať iba pri HD videu + + + + Loop &filter + &Loop filter + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Vynechanie loop filtru (tzv. deblocking) počas dekódovanie H.264. + + + + Possible values: + Možnosti: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Povolený</b>: loop filter nebude vynechaný + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Vynechať (vždy)</b>: loop filter bude vynechaný a nezáleží na rozlíšení vida + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Vynechať iba pri HD videu</b>: loop filter bude vynechaní iba pri videu, ktorého výška je %1 alebo vyššia. + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Playlist + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + Play&list + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Titulky + + + + Choose a ttf file + Vybrať TTF súbor + + + + Truetype Fonts + Truetype fonty (*.ttf) + + + + &Subtitles + &Titulky + + + + Autoload + Automatické načítanie + + + + Select first available subtitle + Vybrať prvé možné titulky + + + + Same name as movie + Rovnaké ako názov filmu + + + + All subs containing movie name + Všetky titulky obsahujúce názov filmu + + + + All subs in directory + Všetky titulky v adresári + + + + Position + Pozícia + + + + 0 + 0 + + + + Top + Navrchu + + + + Bottom + Naspodu + + + + Include subtitles on screenshots + Zobraziť titulky na snímkoch obrazovky + + + + Font + Písmo + + + + Select the font which will be used for subtitles (and OSD): + Font, ktorý bude použitý pre titulky (a OSD): + + + + Size + Veľkosť + + + + No autoscale + Žiadne automatické škálovanie + + + + Proportional to movie height + Proporcionálne k výške videa + + + + Proportional to movie width + Proporcionálne k šírke videa + + + + Proportional to movie diagonal + Proporcionálne k diagonále videa + + + + Subtitle position + Pozícia titulkov + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Toto nastavenie špcifikuje pozíciu titulkov v okne s videom. <i>100</i> znamená úplne naspodu, <i>0</i> úplne navrchu. + + + + Au&toload subtitles files (*.srt, *.sub...): + &Automatické načítanie titulkov (*.srt, *.sub, ...): + + + + S&elect first available subtitle + Vybrať &prvé možné titulky + + + + &Default subtitle encoding: + Štandardné &kódovanie titulkov: + + + + Default &position of the subtitles on screen + Štandardná &pozícia titulkov na obrazovke + + + + &Include subtitles on screenshots + Zobraziť titulky na &snímkoch obrazovky + + + + &TTF font: + &TTF písmo: + + + + S&ystem font: + Sy&stémové písmo: + + + + A&utoscale: + Automatické š&kálovanie: + + + + Default subtitle encoding + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + Naspodu + + + + Middle + vertical alignment + + + + + Top + vertical alignment + Navrchu + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Pomoc + + + + OK + OK + + + + Cancel + Zrušiť + + + + Apply + Použiť + + + + Help + Pomoc + + + + SMPlayer - Preferences + SMPlayer - Nastavenia + + + + QObject + + + will show this message and then will exit. + zobrazí túto správau a potom skončí. + + + + the main window will be closed when the file/playlist finishes. + hlavné okno programu bude zotvorené po skončení prehrávania aktuálneho súboru/playlistu. + + + + This is SMPlayer v. %1 running on %2 + Toto je SMPlayer v. %1 spustená na %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + skúsiť pripojenie na spustenú inštanciu a vyžiadať vykonanie určenej akcie.<br>Príklad: -send-action pause<br>Ostatné parametre (ak nejaké boli zadané) budú ignorované a aplikácia skončí. Jej návratová hodnota bude 0 pri úspešnom poslaní príkazu, alebo -1 pri výskyte chyby. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + Ak už je spustená jedna inštancia programu, médium bude pridané do playlistu. Ak nie je spustená žiadna inštancia, tento parameter bude ignorovaný a médiá (súbory) budú otvorené v novej inštancii. + + + + the main window won't be closed when the file/playlist finishes. + hlavné okno programu nebude zotvorené po skončení prehrávania aktuálneho súboru/playlistu. + + + + the video will be played in fullscreen mode. + video bude prehrávané v režime celej obrazovky. + + + + the video will be played in window mode. + video bude prehrávané v okne. + + + + Enqueue in SMPlayer + Zaradiť do playlistu SMPlayeru + + + + opens the mini gui instead of the default one. + otvoriť minimálne GUI mesto štandardného rozhrania. + + + + Restores the old associations and cleans up the registry. + Obnoviť predchádzajúcu asociáciu a odstrániť záznamy z registra. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'médium' je akýkoľvek súbor alebo zariadenie, ktoré dokáže SMPlayer otvoriť. Môže to byť lokálny súbor, DVD, DVD uložené na disku (napr. dvd://1), internetový prúd (napr: mms://), lokálny playlist vo formáte m3u alebo pls. Ak je použitý parameter -playlist, znamená to, že SMPlayer podsunie parameter -playlist MPlayeru a ten bude pracovať s týmto playlistom, nie SMPlayer. + + + + Usage: + Použitie: + + + + directory + adresár + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + + + %1 minute(s) + + + + + + + + + %1 and %2 + %1 a %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + ikona + + + + label + popis + + + + ShortcutGetter + + + Modify shortcut + Zmeniť skratku + + + + Clear + Vyčistiť + + + + Press the key combination you want to assign + Stlačte kombináciu kláves, ktorú chcete priradiť danej akcii + + + + Capture + Zachytiť + + + + Capture keystrokes + Zachytiť stlačenie kláves + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + Vybrať všetky + + + + Select None + Nevybrať žiadne + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + Automaticky + + + + Yes + Áno + + + + No + Nie + + + + VideoEqualizer + + + Contrast + Kontrast + + + + Brightness + Jas + + + + Hue + Odtieň + + + + Saturation + Saturácia + + + + Gamma + Gamma + + + + &Reset + &Reset + + + + &Set as default values + &Nastaviť ako štandardnú hodnotu + + + + Use the current values as default values for new videos. + Použije aktuálne nastavenie ako štandardné hodnoty pre nové videá. + + + + Set all controls to zero. + Vynulovať všetky nastavenia ekvalizéru. + + + + Video Equalizer + + + + + Information + Informácie + + + + The current values have been stored to be used as default. + Aktuálne hodnoty boli uložené a budú použité ako štandardné. + + + + VideoPreview + + + Video preview + + + + + Cancel + Zrušiť + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Chyba pri ukladaní súboru + + + + The file couldn't be saved + Súbor nemôže byť uložený + + + + Error + Chyba + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Štandardné + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Hlasitosť + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_sl_SI.ts b/plugins/smplayer_plugin/translations/smplayer_sl_SI.ts new file mode 100644 index 000000000..f1e9167bd --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_sl_SI.ts @@ -0,0 +1,7204 @@ + + + + About + + + Version: %1 + Verzija: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + + + + The following people have contributed with translations: + + + + + German + + + + + Slovak + + + + + Italian + + + + + French + + + + + %1, %2 and %3 + + + + + Simplified-Chinese + + + + + Russian + + + + + %1 and %2 + + + + + Hungarian + + + + + Polish + + + + + Japanese + + + + + Dutch + + + + + Ukrainian + + + + + Portuguese - Brazil + + + + + Georgian + + + + + Czech + + + + + Bulgarian + + + + + Turkish + + + + + Swedish + + + + + Serbian + + + + + Traditional Chinese + + + + + Romanian + + + + + Portuguese - Portugal + + + + + Greek + + + + + Finnish + + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + O SMPlayer-ju + + + + &Info + &Informacije + + + + icon + ikona + + + + &Contributions + + + + + &Translators + + + + + &License + + + + + Visit our web for updates: + + + + + Get help in our forum: + + + + + You can support SMPlayer by making a donation. + + + + + More info + + + + + Korean + + + + + Macedonian + + + + + Basque + + + + + Using MPlayer %1 + + + + + Catalan + + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + Slovenski + + + + Arabic + + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Ime + + + + Description + Opis + + + + Shortcut + Bližnjica + + + + &Save + &Shrani + + + + &Load + &Odpri + + + + Key files + Ključna datoteka + + + + Choose a filename + Izberi datoteko + + + + Confirm overwrite? + Zares prepišem? + + + + The file %1 already exists. +Do you want to overwrite? + Datoteka %1 že obstaja.Ali jo prepišem? + + + + Choose a file + Izberi datoteko + + + + Error + Napaka + + + + The file couldn't be saved + Datoteke ni bilo mogoče shraniti + + + + The file couldn't be loaded + Datoteke ni bilo mogoče shraniti + + + + &Change shortcut... + &Spremeni bližnjico... + + + + AudioEqualizer + + + Audio Equalizer + Zvočni izenačevalnik + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + &Uporabi + + + + &Reset + &Ponastavi + + + + &Set as default values + &Shrani kot privzete vrednosti + + + + Use the current values as default values for new videos. + Shrani kot privzete vrednosti. + + + + Set all controls to zero. + Vse nastavitve resetiraj na ničlo. + + + + Information + Informacije + + + + The current values have been stored to be used as default. + Trenutne nastavite so shranjene kot privzete. + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer konzola + + + + SMPlayer - smplayer log + SMPlayer - smplayer konzola + + + + &Open + &Odpri + + + + &Play + &Predvajaj + + + + &Video + &Video + + + + &Audio + &Avdio + + + + &Subtitles + Po&dnapisi + + + + &Browse + &Izberi + + + + Op&tions + &Nastavitve + + + + &Help + Po&moč + + + + &File... + &Datoteko... + + + + D&irectory... + Map&o... + + + + &Playlist... + &Predvajalni se&znam... + + + + &DVD from drive + &DVD z pogona + + + + D&VD from folder... + D&VD iz datoteke... + + + + &URL... + &URL... + + + + &Clear + Počis&ti + + + + &Recent files + &Nedavne datoteke + + + + P&lay + Pr&edvajaj + + + + &Pause + &Pavziraj + + + + &Stop + &Ustavi + + + + &Frame step + &Predvajanje po slikah + + + + &Normal speed + &Normalno predvajanje + + + + &Halve speed + &Polovična hitrost + + + + &Double speed + &Dvojna hitrost + + + + Speed &-10% + Hitrost &-10% + + + + Speed &+10% + Hitrost &+10% + + + + Sp&eed + HIt&rost + + + + &Repeat + &Ponovi + + + + &Fullscreen + &Čez cel zaslon + + + + &Compact mode + &Komapktni način + + + + Si&ze + Vel&ikost + + + + 4:3 &Letterbox + 4:3 &Široko + + + + 16:9 L&etterbox + 16:9 Š&iroko + + + + 4:3 &Panscan + 4:3 &Približano + + + + 4:3 &to 16:9 + 4:3 &v 16:9 + + + + &Aspect ratio + &Razmerje slike + + + + &None + &Nobeden + + + + &Lowpass5 + &Nizki prehod + + + + Linear &Blend + Linearno &Pojemanje + + + + &Deinterlace + &Prepletanje + + + + &Postprocessing + &Poprocesiranje + + + + &Autodetect phase + &Samodejno zaznaj fazo + + + + &Deblock + &Deblokiraj + + + + De&ring + De&ring + + + + Add n&oise + Dodaj &šum + + + + F&ilters + F&iltri + + + + &Equalizer + &Izenačevalnik + + + + &Screenshot + &Zajem slike + + + + S&tay on top + O&stani na vrhu + + + + &Extrastereo + &Razširjeni stereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filtri + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Kanali + + + + &Left channel + &Levi kanal + + + + &Right channel + &Desni kanal + + + + &Stereo mode + &Stereo način + + + + &Mute + &Tiho + + + + Volume &- + Zvok &- + + + + Volume &+ + Zvok &+ + + + + &Delay - + &Zakasni - + + + + D&elay + + Zakas&ni + + + + + &Select + &Izberi + + + + &Load... + &Odpri podnapis... + + + + Delay &- + Zakasni &- + + + + Delay &+ + Zakasni &+ + + + + &Up + &Gor + + + + &Down + &Dol + + + + &Title + &Naslov + + + + &Chapter + &Odsek + + + + &Angle + &Kot + + + + &Playlist + &Predvajalni seznam + + + + &Show frame counter + &Prikaži število sličic + + + + &Disabled + &Onemogočeno + + + + &Seek bar + &Časovna premica + + + + &Time + &Čas predvajanja + + + + Time + T&otal time + Čas predvajanja + Ča&s celotne datoeke + + + + &OSD + &OSD + + + + &View logs + &Odpri dnevnik delovanja + + + + P&references + Na&stavitve + + + + About &Qt + O &Qt + + + + About &SMPlayer + O &SMPlayer + + + + <empty> + <prazno> + + + + Video + Video + + + + Audio + Avdio + + + + Playlists + Predvajalni seznami + + + + All files + Vse datoteke + + + + Choose a file + Izberi datoteko + + + + SMPlayer - Information + SMPlayer - Informacije + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD enote še niso nastavljene. +Prikazalo se bo okno, kjer boste to lahko storili. + + + + Choose a directory + Izberi mapo + + + + Subtitles + Podnapisi + + + + About Qt + O Qt + + + + Playing %1 + Predvajam %1 + + + + Pause + Pavziraj + + + + Stop + Ustavi + + + + Play / Pause + Predvajaj / Pavziraj + + + + Pause / Frame step + Pavziraj / Skoči sliko naprej + + + + U&nload + Spro&sti datoteko + + + + V&CD + V&CD + + + + C&lose + Z&apri + + + + View &info and properties... + Poglej &informacije in parametre... + + + + Zoom &- + Povečava &- + + + + Zoom &+ + Povečava &+ + + + + &Reset + &&Ponastavi + + + + Move &left + Pomakni &levo + + + + Move &right + Pomakni &desno + + + + Move &up + Pomakni &gor + + + + Move &down + Pomakni &dol + + + + &Pan && scan + &Približaj + + + + &Previous line in subtitles + &Prejšnja vrstica v podnapisih + + + + N&ext line in subtitles + Nas&lednja vrstica v podnapisih + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Zmanjšaj glasnost (2) + + + + Inc volume (2) + Povečaj glasnost (2) + + + + Exit fullscreen + Izhod iz celega zaslona + + + + OSD - Next level + OSD - Naslednja stopnja + + + + Dec contrast + Pomanjšaj kontrast + + + + Inc contrast + Povečaj kontrast + + + + Dec brightness + Zmanjšaj svetlost + + + + Inc brightness + Povečaj svetlost + + + + Dec hue + Zmanjšaj barvitost + + + + Inc hue + Povečaj barvitost + + + + Dec saturation + Zmanjšaj saturacijo + + + + Dec gamma + Zmanjšaj gamo + + + + Next audio + Naslednja zvočna sled + + + + Next subtitle + Naslednji podnapis + + + + Next chapter + Naslednje poglavje + + + + Previous chapter + Prejšnje poglavje + + + + Inc saturation + Povečaj saturacijo + + + + Inc gamma + Povečaj gamo + + + + &Load external file... + &Naloži zunanjo datoteko... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normalno) + + + + Y&adif (double framerate) + Y&adif (dvojna hitrost sličic) + + + + &Next + &Naslednje + + + + Pre&vious + Prej&šnje + + + + Volume &normalization + Normalizacija &jakosti zvoka + + + + &Audio CD + &Avdio CD + + + + Denoise nor&mal + Odstranjevanje šu&ma (normalno) + + + + Denoise &soft + Odstranjevanje šu&ma (majhno) + + + + Denoise o&ff + Odstranjevanje šu&ma (izključeno) + + + + Use SSA/&ASS library + Uporabi SSA/&ASS rutino + + + + Flip i&mage + Obrni &sliko + + + + &Toggle double size + &Preklopi dvojno velikost + + + + S&ize - + V&elikost - + + + + Si&ze + + Vel&ikost + + + + + Add &black borders + Dodaj &črno obrobo + + + + Soft&ware scaling + Prog&ramsko lestvičenje + + + + &FAQ + &Pogosta vprašanja + + + + Visualize &motion vectors + Prikaži &vektorje pomikanja + + + + &Command line options + &Ukazi za zagon z ukazne lupine + + + + SMPlayer command line options + SMPlayer ukazi ukazne lupine + + + + Enable &closed caption + Omogoči z&aprte podnapise + + + + &Forced subtitles only + &Prikaži samo vsiljene podnapise + + + + Reset video equalizer + Ponastavi video izenačevalnik + + + + MPlayer has finished unexpectedly. + MPlayer se je nepričakovano zaprl. + + + + Exit code: %1 + Koda napake: %1 + + + + MPlayer failed to start. + MPlayer se ni uspešno zagnal. + + + + Please check the MPlayer path in preferences. + Prosim preverite nastavitve Mplayer predvajalnika in njegove poti. + + + + MPlayer has crashed. + MPlayer se je nasilno zaprl. + + + + See the log for more info. + Poglej si dnevnik delovanja za več informacij. + + + + &Rotate + &Rotiraj + + + + &Off + &Onemogoči + + + + &Rotate by 90 degrees clockwise and flip + &Obrni za 90 stopinj v smeri ure in obrni na glavo + + + + Rotate by 90 degrees &clockwise + Obrni za 90 stopinj v &smeri ure + + + + Rotate by 90 degrees counterclock&wise + Obrni za 90 stopinj v obratni &smeri ure + + + + Rotate by 90 degrees counterclockwise and &flip + &Obrni za 90 stopinj v obratni smeri ure in obrni na glavo + + + + &Jump to... + &Skoči na... + + + + Show context menu + Pokaži povezovalni meni + + + + Multimedia + Multimedija + + + + E&qualizer + I&zenačevalnik + + + + Reset audio equalizer + Ponastavi avdio izenačevalnik + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &Sledi + + + + &Track + audio + &Sledi + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer je še vedno zagnan + + + + S&how icon in system tray + Po&kaži ikono v sistemskem pladnju + + + + &Hide + &Skrij + + + + &Restore + O&bnovi + + + + &Quit + &Izhod + + + + Playlist + Predvajalni seznam + + + + Core + + + Brightness: %1 + Svetlost: %1 + + + + Contrast: %1 + Kontrast: %1 + + + + Gamma: %1 + Gama: %1 + + + + Hue: %1 + Barvitost: %1 + + + + Saturation: %1 + Saturacija: %1 + + + + Volume: %1 + Glasnost: %1 + + + + Zoom: %1 + Povečava: %1 + + + + Font scale: %1 + Razmerje pisave: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Dobrodošli v SMPlayer predvajalniku + + + + Audio + Avdio + + + + Subtitle + Podnapis + + + + &Main toolbar + &Glavna orodna vrstica + + + + &Language toolbar + &Vrstica z jeziki + + + + &Toolbars + &Orodne vrstice + + + + EqSlider + + + icon + ikona + + + + ErrorDialog + + + Hide log + Skrij dnevnik + + + + Show log + Pokaži dnevnik + + + + MPlayer Error + MPlayer Napaka + + + + icon + ikona + + + + Error + Napaka + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Lastnosti datoteke + + + + &Information + &Informacije + + + + &Demuxer + &Zabojnik + + + + &Select the demuxer that will be used for this file: + + + + + &Reset + + + + + &Video codec + + + + + &Select the video codec: + + + + + A&udio codec + + + + + &Select the audio codec: + + + + + &MPlayer options + + + + + Additional Options for MPlayer + + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + + &Options: + + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + + + V&ideo filters: + + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + + + + + Audio &filters: + + + + + OK + V redu + + + + Cancel + Prekliči + + + + Apply + Uporabi + + + + FindSubtitlesWindow + + + Language + + + + + Name + Ime + + + + Format + + + + + Files + + + + + Date + + + + + Uploaded by + + + + + All + + + + + Close + Zapri + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Napaka + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Napaka pri shranjevanju datoteke + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Splošno + + + + Size + + + + + %1 KB (%2 MB) + + + + + URL + + + + + Length + Dolžina + + + + Demuxer + + + + + Name + Ime + + + + Artist + + + + + Author + + + + + Album + + + + + Genre + + + + + Date + + + + + Track + + + + + Copyright + + + + + Comment + + + + + Software + + + + + Clip info + + + + + Video + Video + + + + Resolution + + + + + Aspect ratio + + + + + Format + + + + + Bitrate + + + + + %1 kbps + + + + + Frames per second + + + + + Selected codec + + + + + Initial Audio Stream + + + + + Rate + + + + + %1 Hz + + + + + Channels + + + + + Audio Streams + + + + + Language + + + + + empty + + + + + Subtitles + Podnapisi + + + + Type + + + + + ID + Info for translators: this is a identification code + + + + + # + Info for translators: this is a abbreviation for number + + + + + Stream title + + + + + Stream URL + + + + + File + + + + + InputDVDDirectory + + + Choose a directory + Izberi mapo + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Predvajaj DVD iz datoteke + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + DVD lahko predvajajš tudi z diska tako da izbereš mapi VIDEO_TS in AUDIO_TS. + + + + Choose a directory... + Izberi mapo... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer -Vnesite MPlayer verzijo + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Vnesi URL + + + + &URL: + &URL: + + + + It's a &playlist + To je &predvajalni seznam + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Če izberet to opcije bo URL tretiran ko t predvajalni seznam; odprt bo kot besedilna datoteka v kateri so URL-ji do datotek. + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + + + + + Welsh + + + + + Danish + + + + + German + + + + + Greek + + + + + English + + + + + Esperanto + + + + + Spanish + + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + + + + + Faroese + + + + + French + + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + + + + + Inuktitut + + + + + Japanese + + + + + Javanese + + + + + Georgian + + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + + + + + Portuguese + + + + + Quechua + + + + + Romanian + + + + + Russian + + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + + + + + Slovenian + Slovenski + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + + + + + Sundanese + + + + + Swedish + + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + + + + + Portuguese - Portugal + + + + + Simplified-Chinese + + + + + Traditional Chinese + + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + + + + + Western European Languages with Euro + + + + + Slavic/Central European Languages + + + + + Esperanto, Galician, Maltese, Turkish + + + + + Old Baltic charset + + + + + Cyrillic + + + + + Modern Greek + + + + + Baltic + + + + + Celtic + + + + + Hebrew charsets + + + + + Ukrainian, Belarusian + + + + + Simplified Chinese charset + + + + + Traditional Chinese charset + + + + + Japanese charsets + + + + + Korean charset + + + + + Thai charset + + + + + Cyrillic Windows + + + + + Slavic/Central European Windows + + + + + Arabic Windows + + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Izberi datoteko v katero naj shranim + + + + Confirm overwrite? + Zares prepišem? + + + + The file already exists. +Do you want to overwrite? + Datoteka že obstaja. +Ali jo prepišem? + + + + Error saving file + Napaka pri shranjevanju datoteke + + + + The log couldn't be saved + Datoteke ni bilo mogoče shraniti + + + + Logs + Konzolni izpisi + + + + LogWindowBase + + + Log Window + Okno z dnevnikom + + + + Save + Shrani + + + + Copy to clipboard + Kopiraj na odložišče + + + + &Close + &Zapri + + + + Close + Zapri + + + + MiniGui + + + Control bar + Nadzorna vrstica + + + + MpcGui + + + Control bar + Nadzorna vrstica + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Ime + + + + Length + Dolžina + + + + &Play + &Predvajaj + + + + &Edit + &Uredi + + + + Playlists + Predvajalni seznami + + + + Choose a file + Izberi datoteko + + + + Choose a filename + Izberi datoteko + + + + Confirm overwrite? + Zares prepišem? + + + + The file %1 already exists. +Do you want to overwrite? + Datoteka %1 že obstaja.Ali jo prepišem? + + + + All files + Vse datoteke + + + + Select one or more files to open + Izberi eno ali več datotek za odpiranje + + + + Choose a directory + Izberi mapo + + + + Edit name + Uredi ime + + + + Type the name that will be displayed in the playlist for this file: + Izberite ime ki po prikazano v predvajalnem seznamu za to datoteko: + + + + &Load + &Odpri + + + + &Save + &Shrani + + + + &Next + &Naslednje + + + + Pre&vious + Prej&šnje + + + + Move &up + Premakni &gor + + + + Move &down + Premakni &dol + + + + &Repeat + &Ponovi + + + + S&huffle + Ra&zmeči + + + + Add &current file + Dodaj &trenutno datoteko + + + + Add &file(s) + Dodaj &datoteko/e + + + + Add &directory + Dodaj &mapo + + + + Remove &selected + Odstrani &izbrane + + + + Remove &all + Odstrani &vse + + + + SMPlayer - Playlist + SMPlayer - Predvajalni seznam + + + + Add... + Dodaj... + + + + Remove... + Odstrani... + + + + Playlist modified + Predvajalni seznam spremenjen + + + + There are unsaved changes, do you want to save the playlist? + Imate neshranjene spremembe, ali želite shrani te spremembe? + + + + Preferences + Nastavitve + + + + PlaylistPreferences + + + Playlist - Preferences + Predvjalni seznam - Nastavitve + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Izberi to opcijo če želiš, da se naložijo tudi taoteke iz poddirektorijev. V nasprotnem primeru se bodo naložile samo datoteke v trenutno izbranem direktoriju. + + + + &Add files in directories recursively + &Dodaj datoteke v direktorijih rekruzivno + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + Samodejno pridobi &informacije o dodanih datotekah + + + + &Save copy of playlist on exit + &Shrani kopijo predvajalnega seznam ob izhodu + + + + &Play files from start + &Predvajaj datoteke od začetka + + + + PrefAdvanced + + + Advanced + + + + + Auto + Samodejno + + + + &Advanced + + + + + icon + ikona + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + + + + + Log MPlayer output + + + + + Log SMPlayer output + + + + + This option is mainly intended for debugging the application. + + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + + + + + Filter for SMPlayer logs + + + + + &Monitor aspect: + + + + + &Run MPlayer in its own window + + + + + &Options: + + + + + V&ideo filters: + + + + + Audio &filters: + + + + + &Colorkey: + + + + + Log &SMPlayer output + + + + + &Filter for SMPlayer logs: + + + + + C&hange... + + + + + Logs + Konzolni izpisi + + + + Log MPlayer &output + + + + + Options for MP&layer + + + + + Autosave MPlayer log + + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + + + + + Select all + + + + + Check all file types in the list + + + + + Uncheck all file types in the list + + + + + List of file types + + + + + File types + + + + + Media files handled by SMPlayer: + + + + + Select All + + + + + Select None + + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + Select none + + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + Pogoni + + + + icon + ikona + + + + CD device + CD naprava + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Izberite CDROM napravo. Uporabljena bo za predvajanje VCD-jev in Avdio CD-jev. + + + + DVD device + DVD naprava + + + + Choose your DVD device. It will be used to play DVDs. + Izberite DVD napravo. Uporabljena bo za predvajanje DVD-jev. + + + + Select your &CD device: + Izberite &CD napravo: + + + + Select your &DVD device: + Izberite &DVD napravo: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer ne izbere nobene CDROM ali DVD naprave samodejno. Zato preden lahko predvajate vsebino, to storite sami. Imeni naprav so lahko enaki. + + + + PrefGeneral + + + General + Splošno + + + + &General + &Splošno + + + + Paths + Poti + + + + Media settings + + + + + Start videos in fullscreen + + + + + Disable screensaver + + + + + Select the mplayer executable + + + + + Executables + + + + + All files + Vse datoteke + + + + Select a directory + + + + + MPlayer executable + + + + + Screenshots folder + + + + + Video output driver + + + + + Audio output driver + + + + + Select the audio output driver. + + + + + Remember settings + + + + + Preferred audio language + + + + + Preferred subtitle language + + + + + Software video equalizer + Programski video izenačevalnik + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + + + + + If this option is checked, all videos will start to play in fullscreen mode. + + + + + Software volume control + + + + + Check this option to use the software mixer, instead of using the sound card mixer. + + + + + Postprocessing quality + + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + + + + + Change volume + + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + 0 + + + + + &Change volume on every file + + + + + Select the &MPlayer executable: + + + + + &Folder for storing screenshots: + + + + + &Audio: + + + + + &Remember settings for all files (audio track, subtitles...) + + + + + Su&btitles: + + + + + &Quality: + + + + + Start videos in &fullscreen + + + + + Disable &screensaver + + + + + &Default volume: + + + + + Use s&oftware volume control + + + + + Ma&x. Amplification: + + + + + &AC3/DTS pass-through S/PDIF + + + + + Direct rendering + + + + + Double buffering + + + + + D&irect rendering + + + + + Dou&ble buffering + + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + &Enable postprocessing by default + + + + + Volume &normalization by default + + + + + Close when finished + + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + + + + + 4 (4.0 Surround) + + + + + 6 (5.1 Surround) + + + + + C&hannels by default: + + + + + &Pause when minimized + + + + + Pause when minimized + + + + + Enable postprocessing by default + + + + + Max. Amplification + + + + + AC3/DTS pass-through S/PDIF + + + + + Volume normalization by default + Privzeta normalizacija jakosti zvoka + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + + + + + Audi&o: + + + + + Preferred language: + + + + + Preferre&d audio and subtitles + + + + + &Subtitle: + + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + &Video + + + + Use s&oftware video equalizer + Uporabi pr&ogramski video izenačevalnik + + + + A&udio + + + + + Volume + Glasnost + + + + Video + Video + + + + Audio + Avdio + + + + Preferred audio and subtitles + + + + + None + + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + + + + + &Keyboard + + + + + icon + ikona + + + + &Mouse + + + + + Button functions: + + + + + Media seeking + + + + + Volume control + + + + + Zoom video + + + + + None + + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + + + + + &Double click + + + + + &Wheel function: + + + + + Shortcut editor + + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + + + + + Select the action for left click on the mouse. + + + + + Double click + + + + + Select the action for double click on the mouse. + + + + + Wheel function + + + + + Select the action for the mouse wheel. + + + + + Play + + + + + Pause + Pavziraj + + + + Stop + Ustavi + + + + Fullscreen + + + + + Compact + + + + + Screenshot + + + + + Mute + + + + + Frame counter + + + + + Reset zoom + + + + + Exit fullscreen + Izhod iz celega zaslona + + + + Double size + + + + + Play / Pause + Predvajaj / Pavziraj + + + + Pause / Frame step + Pavziraj / Skoči sliko naprej + + + + Playlist + Predvajalni seznam + + + + Preferences + Nastavitve + + + + No function + + + + + Change speed + + + + + Normal speed + Normalna hitrost + + + + Keyboard + Tipkovnica + + + + Mouse + Miška + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - Naslednja stopnja + + + + Show context menu + Pokaži povezovalni meni + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + + + + + <Autodetect> + + + + + Default + + + + + &Interface + + + + + Never + + + + + Whenever it's needed + + + + + Only after loading a new video + + + + + Recent files + + + + + Language + + + + + Here you can change the language of the application. + + + + + &Short jump + + + + + &Medium jump + + + + + &Long jump + + + + + Mouse &wheel jump + + + + + &Use only one running instance of SMPlayer + + + + + Ma&x. items + + + + + St&yle: + + + + + Ico&n set: + + + + + L&anguage: + + + + + Main window + + + + + Auto&resize: + + + + + R&emember position and size + + + + + Default font: + + + + + &Change... + + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + + + + + &Seeking + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Seeking + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + + + + + &Performance + + + + + Priority + + + + + Select the priority for the MPlayer process. + + + + + realtime + + + + + high + + + + + abovenormal + + + + + normal + + + + + belownormal + + + + + idle + + + + + KB + + + + + Setting a cache may improve performance on slow media + + + + + Allow frame drop + + + + + Synchronization + + + + + Audio/video auto synchronization + + + + + Skip displaying some frames to maintain A/V sync on slow systems. + + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + + + + + Gradually adjusts the A/V sync based on audio delay measurements. + + + + + Priorit&y: + + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + + + + + Fact&or: + + + + + &Fast audio track switching + + + + + Fast &seek to chapters in dvds + + + + + Fast audio track switching + + + + + Fast seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + + + + + Cache for &DVDs: + + + + + Cache for &local files: + + + + + Cache for &streams: + + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Predvajalni seznam + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Predvajalni seznam + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Podnapisi + + + + Choose a ttf file + + + + + Truetype Fonts + + + + + &Subtitles + Po&dnapisi + + + + Autoload + + + + + Same name as movie + + + + + All subs containing movie name + + + + + All subs in directory + + + + + Position + + + + + 0 + + + + + Top + + + + + Bottom + + + + + Font + + + + + Select the font which will be used for subtitles (and OSD): + + + + + Size + + + + + No autoscale + + + + + Proportional to movie height + + + + + Proportional to movie width + + + + + Proportional to movie diagonal + + + + + Subtitle position + + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + + + + + Au&toload subtitles files (*.srt, *.sub...): + + + + + S&elect first available subtitle + + + + + &Default subtitle encoding: + + + + + Default &position of the subtitles on screen + + + + + &Include subtitles on screenshots + + + + + &TTF font: + + + + + S&ystem font: + + + + + A&utoscale: + + + + + Select first available subtitle + + + + + Default subtitle encoding + + + + + Include subtitles on screenshots + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + + + + + Middle + vertical alignment + + + + + Top + vertical alignment + + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Pomoč + + + + OK + OK + + + + Cancel + Prekliči + + + + Apply + Uporabi + + + + Help + Pomoč + + + + SMPlayer - Preferences + SMPlayer - Nastavitve + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + + the main window won't be closed when the file/playlist finishes. + + + + + the video will be played in fullscreen mode. + + + + + the video will be played in window mode. + + + + + Enqueue in SMPlayer + + + + + opens the mini gui instead of the default one. + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + Usage: + Uporaba: + + + + directory + mapa + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + + + + %1 minute(s) + + + + + + + + + + %1 and %2 + + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + ikona + + + + label + oznaka + + + + ShortcutGetter + + + Modify shortcut + Spremeni bližnjico + + + + Clear + Počisti + + + + Press the key combination you want to assign + Prtisnite kombinacijo tipk, ki jih želite določiti + + + + Capture + Zajemi + + + + Capture keystrokes + Zajemi kombinacijo tipk + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + + + + + Select None + + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Pomk + + + + &Jump to: + &Skoči na: + + + + TristateCombo + + + Auto + Samodejno + + + + Yes + Da + + + + No + Ne + + + + VideoEqualizer + + + Contrast + Kontrast + + + + Brightness + Svetlost + + + + Hue + Barvitost + + + + Saturation + Saturacija + + + + Gamma + Gama + + + + &Reset + &Ponastavi + + + + &Set as default values + &Shrani kot privzete vrednosti + + + + Use the current values as default values for new videos. + Shrani kot privzete vrednosti. + + + + Set all controls to zero. + Vse nastavitve resetiraj na ničlo. + + + + Video Equalizer + Video Izenačevalnik + + + + Information + Informacije + + + + The current values have been stored to be used as default. + Trenutne nastavite so shranjene kot privzete. + + + + VideoPreview + + + Video preview + + + + + Cancel + Prekliči + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Napaka pri shranjevanju datoteke + + + + The file couldn't be saved + Datoteke ni bilo mogoče shraniti + + + + Error + Napaka + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + + + + + %1 Hz + + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Glasnost + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_sr.ts b/plugins/smplayer_plugin/translations/smplayer_sr.ts new file mode 100644 index 000000000..77fbcc3f4 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_sr.ts @@ -0,0 +1,7208 @@ + + + + About + + + Version: %1 + Верзија %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Овај програм је бесплатан софтвер; можете га редистрибуирати и/или модификовати под условима GNU GPL лиценце објављене од стране Фондације Слободног Софтвера, било да је верзија 2 лиценце или било која наредна верзија. + + + + The following people have contributed with translations: + + + + + German + Немачки + + + + Slovak + Словачки + + + + Italian + Италијански + + + + French + Француски + + + + %1, %2 and %3 + + + + + Simplified-Chinese + Упрошћени-Кинески + + + + Russian + Руски + + + + %1 and %2 + + + + + Hungarian + Мађарски + + + + Polish + Пољски + + + + Japanese + Јапански + + + + Dutch + Холандски + + + + Ukrainian + Украински + + + + Portuguese - Brazil + + + + + Georgian + Грузијски + + + + Czech + Чешки + + + + Bulgarian + Бугарски + + + + Turkish + Турски + + + + Swedish + Шведски + + + + Serbian + Српски + + + + Traditional Chinese + + + + + Romanian + + + + + Portuguese - Portugal + + + + + Greek + Грчки + + + + Finnish + Фински + + + + <b>%1</b>: %2 + + + + + <b>%1</b> (%2) + + + + + About SMPlayer + О SMPlayer-у + + + + &Info + + + + + icon + + + + + &Contributions + + + + + &Translators + + + + + &License + + + + + Visit our web for updates: + + + + + Get help in our forum: + + + + + You can support SMPlayer by making a donation. + + + + + More info + + + + + Korean + + + + + Macedonian + + + + + Basque + + + + + Using MPlayer %1 + + + + + Catalan + + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + Арапски + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Име + + + + Description + Опис + + + + Shortcut + Пречица + + + + &Save + &Save + + + + &Load + &Load + + + + Key files + Кључни фајлови + + + + Choose a filename + Изабери име фајла + + + + Confirm overwrite? + Потврди преписивање? + + + + The file %1 already exists. +Do you want to overwrite? + Фајл %1 већ постоји +Да ли желите да га препишеш? + + + + Choose a file + Изабери фајл + + + + Error + Грешка + + + + The file couldn't be saved + Фајл не може да се сачува + + + + The file couldn't be loaded + Фајл не може да се учита + + + + &Change shortcut... + + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + &Ресетуј + + + + &Set as default values + &Постави основне вредности + + + + Use the current values as default values for new videos. + Користи тренутно вредности као основне за нове видео фајлове. + + + + Set all controls to zero. + Постави све контроле на нула. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer лог + + + + SMPlayer - smplayer log + SMPlayer - smplayer лог + + + + &Open + &Отвори + + + + &Play + &Пусти + + + + &Video + &Видео + + + + &Audio + &Аудио + + + + &Subtitles + &Превод + + + + &Browse + &Изабери + + + + Op&tions + Оп&ције + + + + &Help + &Помоћ + + + + &File... + &Фајл... + + + + D&irectory... + Д&иректоријум... + + + + &Playlist... + &Плејлиста... + + + + &DVD from drive + &DVD са уређаја + + + + D&VD from folder... + D&VD из фолдера... + + + + &URL... + &Интернет адреса... + + + + &Clear + &Обриши + + + + &Recent files + &Отварани фајлови + + + + P&lay + П&усти + + + + &Pause + &Пауза + + + + &Stop + &Заустави + + + + &Frame step + &Фрејм по фрејм + + + + &Normal speed + &Нормална брзина + + + + &Halve speed + &Дупло спорије + + + + &Double speed + &Дупло брже + + + + Speed &-10% + Брзина &-10% + + + + Speed &+10% + Брзина &+10% + + + + Sp&eed + Бр&зина + + + + &Repeat + &Понављај + + + + &Fullscreen + &Цео екран + + + + &Compact mode + &Компактан облик + + + + Si&ze + Ве&личина + + + + 4:3 &Letterbox + 4:3 &Коверат + + + + 16:9 L&etterbox + 16:9 К&оверат + + + + 4:3 &Panscan + 4:3 &Панскен + + + + 4:3 &to 16:9 + 4:3 &to 16:9 + + + + &Aspect ratio + &Задржи однос + + + + &None + &Искључено + + + + &Lowpass5 + &Нископропусни5 + + + + Linear &Blend + Линеарност &Мешање + + + + &Deinterlace + &Уклони линије + + + + &Postprocessing + &Постпроцес + + + + &Autodetect phase + &Аутодетектовање фазе + + + + &Deblock + &Деблокирање + + + + De&ring + Де&прстеновање + + + + Add n&oise + Додај ш&ум + + + + F&ilters + Ф&илтри + + + + &Equalizer + &Еквилајзер + + + + &Screenshot + &Сликај екран + + + + S&tay on top + О&стани на врху + + + + &Extrastereo + &Есктрастерео + + + + &Karaoke + &Караоке + + + + &Filters + &Филтри + + + + &Stereo + &Стерео + + + + &4.0 Surround + &4,0 Тоне + + + + &5.1 Surround + &5,1 Tone + + + + &Channels + &Канали + + + + &Left channel + &Леви канал + + + + &Right channel + &Десни канал + + + + &Stereo mode + &Врста стереа + + + + &Mute + &Искључи тон + + + + Volume &- + Јачина &- + + + + Volume &+ + Јачина &+ + + + + &Delay - + &Кашњење + + + + D&elay + + П&редњачење + + + + &Select + &Изабери + + + + &Load... + &Учитај... + + + + Delay &- + Кашњење & + + + + Delay &+ + Предњачење & + + + + &Up + &Горе + + + + &Down + &Доле + + + + &Title + &Језик + + + + &Chapter + &Поглавље + + + + &Angle + &Угао + + + + &Playlist + &Плејлиста + + + + &Show frame counter + &Прикажи бројач фрејмова + + + + &Disabled + &Искључено + + + + &Seek bar + &Бар за тражење + + + + &Time + &Време + + + + Time + T&otal time + Време + У&купно време + + + + &OSD + &OSD + + + + &View logs + &Види логове + + + + P&references + П&одешавања + + + + About &Qt + О &Qt + + + + About &SMPlayer + О &SMPlayer-у + + + + <empty> + + + + + Video + Видео + + + + Audio + Аудио + + + + Playlists + Плејлиста + + + + All files + Сви фајлови + + + + Choose a file + Изабери фајл + + + + SMPlayer - Information + SMPlayer - информација + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD нису конфигурисани +Дијалог за конфигурисање ће сада бити приказан, +па можеш сада да конфигуришеш уређаје. + + + + Choose a directory + Изабери директоријум + + + + Subtitles + Превод + + + + About Qt + О Qt-у + + + + Playing %1 + Тренутно пушта %1 + + + + Pause + Паузирај + + + + Stop + Заустави + + + + Play / Pause + Пусти / Паузирај + + + + Pause / Frame step + Пауза / Фрејм по фрејм + + + + U&nload + Од&читај + + + + V&CD + V&CD + + + + C&lose + З&атвори + + + + View &info and properties... + Погледај &инфо и карактеристике... + + + + Zoom &- + Зум &- + + + + Zoom &+ + Зум &+ + + + + &Reset + &Ресетуј + + + + Move &left + Помери &лево + + + + Move &right + Помери &десно + + + + Move &up + Помери &горе + + + + Move &down + Помери &доле + + + + &Pan && scan + &Пан && скен + + + + &Previous line in subtitles + &Претходна линије у преводу + + + + N&ext line in subtitles + С&ледећа линија у преводу + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Смањи тон (2) + + + + Inc volume (2) + Појачај тон (2) + + + + Exit fullscreen + Искључи опцију Цео Екран + + + + OSD - Next level + OSD - Следећи ниво + + + + Dec contrast + Смањи контраст + + + + Inc contrast + Повећај Контраст + + + + Dec brightness + Смањи осветљај + + + + Inc brightness + Повећај осветљај + + + + Dec hue + Смањи боју + + + + Inc hue + Појачај боју + + + + Dec saturation + Смањи засићење + + + + Inc saturation + Повећај засићење + + + + Dec gamma + Смањи гама + + + + Inc gamma + Повећај гама + + + + Next audio + Следећи аудио фајл + + + + Next subtitle + Следећи превод + + + + Next chapter + Следеће поглавље + + + + Previous chapter + Претходно поглавље + + + + &Load external file... + + + + + &Kerndeint + + + + + &Yadif (normal) + + + + + Y&adif (double framerate) + + + + + &Next + &Следећа + + + + Pre&vious + Прет&ходна + + + + Volume &normalization + + + + + &Audio CD + + + + + Denoise nor&mal + + + + + Denoise &soft + + + + + Denoise o&ff + + + + + Use SSA/&ASS library + + + + + Flip i&mage + + + + + &Toggle double size + + + + + S&ize - + + + + + Si&ze + + + + + + Add &black borders + + + + + Soft&ware scaling + + + + + &FAQ + + + + + Visualize &motion vectors + + + + + &Command line options + + + + + SMPlayer command line options + + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &Изабери аудио + + + + &Track + audio + &Изабери аудио + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer овде и даље ради + + + + S&how icon in system tray + П&рикажи икону у систем треју + + + + &Hide + &Сакри + + + + &Restore + &Покажи + + + + &Quit + &Искључи + + + + Playlist + Плејлиста + + + + Core + + + Brightness: %1 + Осветљај: %1 + + + + Contrast: %1 + Контраст: %1 + + + + Gamma: %1 + Гама: %1 + + + + Hue: %1 + Боја: %1 + + + + Saturation: %1 + Засићеност: %1 + + + + Volume: %1 + Јачина тона: %1 + + + + Zoom: %1 + Зум: %1 + + + + Font scale: %1 + + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Добродошли у SMPlayer + + + + Audio + Аудио + + + + Subtitle + Превод + + + + &Main toolbar + &Главни алатке + + + + &Language toolbar + &Алатке за језик + + + + &Toolbars + &Алатке + + + + EqSlider + + + icon + икона + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + + + + + Error + Грешка + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Карактеристике фајла + + + + &Information + &Информација + + + + &Demuxer + &Демултиплексер + + + + &Select the demuxer that will be used for this file: + &Изабери демултиплексер за овај фајл: + + + + &Reset + &Ресетуј + + + + &Video codec + &Видео кодек + + + + &Select the video codec: + &Изабери видео кодек: + + + + A&udio codec + А&удио кодек + + + + &Select the audio codec: + &Изабери аудио кодек: + + + + &MPlayer options + &Опције MPlayer-а + + + + Additional Options for MPlayer + Додатне опције за MPLayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + + &Options: + &Опције: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + + + V&ideo filters: + В&идео филтри: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + + + + + Audio &filters: + Аудио &филтри: + + + + OK + + + + + Cancel + + + + + Apply + + + + + FindSubtitlesWindow + + + Language + Језик + + + + Name + Име + + + + Format + Формат + + + + Files + + + + + Date + Датум + + + + Uploaded by + + + + + All + + + + + Close + + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Грешка + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Грешка при чувању фајла + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Опште + + + + Size + Величина + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + Интернет адреса + + + + Length + Дужина + + + + Demuxer + Демултиплексер + + + + Name + Име + + + + Artist + Уметник + + + + Author + Аутор + + + + Album + Албум + + + + Genre + Жанр + + + + Date + Датум + + + + Track + Снимак + + + + Copyright + Права копирања + + + + Comment + Коментар + + + + Software + Софтвер + + + + Clip info + Информација о снимку + + + + Video + Видео + + + + Resolution + Резолуција + + + + Aspect ratio + Пропорција + + + + Format + Формат + + + + Bitrate + Брзина протока + + + + %1 kbps + %1 kbps + + + + Frames per second + Фрејмова по секунди + + + + Selected codec + Изабран кодек + + + + Initial Audio Stream + Почетни аудио стрим + + + + Rate + Однос + + + + %1 Hz + %1 Hz + + + + Channels + Канали + + + + Audio Streams + Аудио стримови + + + + Language + Језик + + + + empty + празно + + + + Subtitles + Превод + + + + Type + Тип + + + + ID + Info for translators: this is a identification code + 891983 + + + + # + Info for translators: this is a abbreviation for number + 1 + + + + Stream title + Име стрима + + + + Stream URL + Интернет адреса стрима + + + + File + + + + + InputDVDDirectory + + + Choose a directory + Изабери директоријум + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Пусти DVD из фолдера + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Можеш да пушташ DVD из фолдера. Само изабери фолдер у коме су VIDEO_TS и AUDIO_TS фолдери. + + + + Choose a directory... + Изабери фолдер... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + + + + + &URL: + + + + + It's a &playlist + + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + Арапски + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + Бугарски + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + Чешки + + + + Welsh + + + + + Danish + + + + + German + Немачки + + + + Greek + Грчки + + + + English + Енглески + + + + Esperanto + + + + + Spanish + Шпански + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + Фински + + + + Faroese + + + + + French + Француски + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + Мађарски + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + Италијански + + + + Inuktitut + + + + + Japanese + Јапански + + + + Javanese + + + + + Georgian + Грузијски + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + Холандски + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + Пољски + + + + Portuguese + + + + + Quechua + + + + + Romanian + + + + + Russian + Руски + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + Словачки + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + Српски + + + + Sundanese + + + + + Swedish + Шведски + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Турски + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + Украински + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + + + + + Portuguese - Portugal + + + + + Simplified-Chinese + Упрошћени-Кинески + + + + Traditional Chinese + + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Западно Европски Језици + + + + Western European Languages with Euro + Западно Европски Језици са Евро Знаком + + + + Slavic/Central European Languages + Словенски/Централно Европски Језици + + + + Esperanto, Galician, Maltese, Turkish + Есперанто, Галски, Малтезе, Турски + + + + Old Baltic charset + Стари Балтички сет карактера + + + + Cyrillic + Ћирилица + + + + Modern Greek + Модерни Грчки + + + + Baltic + Балтички + + + + Celtic + Келтски + + + + Hebrew charsets + Хебрејски сет карактера + + + + Ukrainian, Belarusian + Украински, Белоруски + + + + Simplified Chinese charset + Упрошћени Кинески сет карактера + + + + Traditional Chinese charset + Традиционални Кинески сет карактера + + + + Japanese charsets + Јапански сет карактера + + + + Korean charset + Корејски сет карактера + + + + Thai charset + Тајландски сет карактера + + + + Cyrillic Windows + Ћирилица Windows + + + + Slavic/Central European Windows + Словенски/Централно Европски Windows + + + + Arabic Windows + + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Изабери има под којим ћеш да сачуваш + + + + Confirm overwrite? + Потврди преписивање? + + + + The file already exists. +Do you want to overwrite? + Фајл постоји +Да ли желиш да га препишеш? + + + + Error saving file + Грешка при чувању фајла + + + + The log couldn't be saved + Лог не може да се сачува + + + + Logs + Логови + + + + LogWindowBase + + + Log Window + Прозор за логове + + + + Save + Сачувај + + + + Copy to clipboard + Копирај у клипборд + + + + Close + Затвори + + + + &Close + &Затвори + + + + MiniGui + + + Control bar + + + + + MpcGui + + + Control bar + + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Име + + + + Length + Дужина + + + + &Play + &Пусти + + + + &Edit + &Едитуј + + + + Playlists + Плејлиста + + + + Choose a file + Изабери фајл + + + + Choose a filename + Изабери име фајла + + + + Confirm overwrite? + Потврди преписивање? + + + + The file %1 already exists. +Do you want to overwrite? + Фајл %1 постоји. +Да ли желиш да га препишеш? + + + + All files + Сви фајлови + + + + Select one or more files to open + Изабери један или више фајлова да отвориш + + + + Choose a directory + Изабери фолдер + + + + Edit name + Едитуј име + + + + Type the name that will be displayed in the playlist for this file: + Откуцај име које ће бити приказано у плејлисти за овај фајл: + + + + &Load + &Учитај + + + + &Save + &Сачувај + + + + &Next + &Следећа + + + + Pre&vious + Прет&ходна + + + + Move &up + Помери &горе + + + + Move &down + Помери &доле + + + + &Repeat + &Понављај + + + + S&huffle + Н&асумично + + + + Add &current file + Додај &тренутни фајл + + + + Add &file(s) + Додај &фајл(ове) + + + + Add &directory + Додај &фолдер + + + + Remove &selected + Уклони &селектоване + + + + Remove &all + Уклони &све + + + + SMPlayer - Playlist + SMPlayer - Плејлиста + + + + Add... + Додај... + + + + Remove... + Уклони... + + + + Playlist modified + Плејлиста је модификована + + + + There are unsaved changes, do you want to save the playlist? + Несачуване промене, да ли желиш да сачуваш плејлисту? + + + + Preferences + + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + Напредне опције + + + + Auto + + + + + &Advanced + + + + + icon + икона + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Овде можеш да ставиш додатне опције за MPlayer. +Пиши их са размаком. +Пример: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Можеш такође да ставиш додатне филтре +Раздвоји их са ",". Не користи размак! +Пример: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + И коначно аудио филтри. Исто важи као и за видео филтре +Пример: resample=44100:0:0,volnorm + + + + Log MPlayer output + Логуј излаз MPlayer-a + + + + Log SMPlayer output + Логуј излаз SMplayer-a + + + + This option is mainly intended for debugging the application. + Ова опција служи са дебаговање апликације. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Штиклирање ове опције може да се редукује треперење, али такође може да се деси да се видео не прикаже ваљано. + + + + Filter for SMPlayer logs + + + + + &Monitor aspect: + + + + + &Run MPlayer in its own window + + + + + &Options: + &Опције: + + + + V&ideo filters: + В&идео филтри: + + + + Audio &filters: + Аудио &филтри: + + + + &Colorkey: + + + + + Log &SMPlayer output + + + + + &Filter for SMPlayer logs: + + + + + C&hange... + + + + + Logs + + + + + Log MPlayer &output + + + + + Options for MP&layer + + + + + Autosave MPlayer log + + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Тип + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + + + + + Select all + + + + + Check all file types in the list + + + + + Uncheck all file types in the list + + + + + List of file types + + + + + File types + + + + + Media files handled by SMPlayer: + + + + + Select All + + + + + Select None + + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + Select none + + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + Уређаји + + + + icon + икона + + + + CD device + + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + + + + + DVD device + + + + + Choose your DVD device. It will be used to play DVDs. + + + + + Select your &CD device: + + + + + Select your &DVD device: + + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + Опште + + + + &General + + + + + Paths + Путање + + + + Media settings + Опције медија + + + + Preferred audio and subtitles + Жељени аудио стрим и превод + + + + Video + Видео + + + + Start videos in fullscreen + Стартуј видео на целом екрану + + + + Disable screensaver + Онемогући чувара екрана + + + + Audio + Аудио + + + + Select the mplayer executable + Изабери извршну датотеку за MPlayer + + + + Executables + Извршне датотеке + + + + All files + Сви фајлови + + + + Select a directory + Изабери фолдер + + + + MPlayer executable + + + + + Screenshots folder + + + + + Video output driver + + + + + Audio output driver + + + + + Select the audio output driver. + Изабери излазни аудио драјвер. + + + + Remember settings + + + + + Preferred audio language + + + + + Preferred subtitle language + + + + + Software video equalizer + + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Штиклирај ову опцију ако видео еквилајзер није подржан твојом графичком картицом или изабраним излазним видео драјвером <br><b>Упозорење:</b> ова опција може бити некомпатибилна са неким графичким картицама. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Ако је ова опција штиклирана, све ће бити пуштано на целом екрану. + + + + Software volume control + + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Штиклирај ову опцију да би користио софтверски миксер, уместо миксера звучне картице. + + + + Postprocessing quality + + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Динамички мења ниво постпроцесирања у зависности од слободног времена процесора. Број који ставиш ће бити највећи могући који ће се користити. Обично можеш да се користи неки велики број. + + + + Change volume + + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + 0 + 0 + + + + &Change volume on every file + + + + + Select the &MPlayer executable: + + + + + &Folder for storing screenshots: + + + + + &Audio: + + + + + &Remember settings for all files (audio track, subtitles...) + + + + + Su&btitles: + + + + + &Quality: + + + + + Start videos in &fullscreen + + + + + Disable &screensaver + + + + + &Default volume: + + + + + Use s&oftware volume control + + + + + Ma&x. Amplification: + + + + + &AC3/DTS pass-through S/PDIF + + + + + Direct rendering + + + + + Double buffering + + + + + D&irect rendering + + + + + Dou&ble buffering + + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + &Enable postprocessing by default + + + + + Volume &normalization by default + + + + + Close when finished + + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + + + + + 4 (4.0 Surround) + + + + + 6 (5.1 Surround) + + + + + C&hannels by default: + + + + + &Pause when minimized + + + + + Pause when minimized + + + + + Enable postprocessing by default + + + + + Max. Amplification + + + + + AC3/DTS pass-through S/PDIF + + + + + Volume normalization by default + + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + + + + + Audi&o: + + + + + Preferred language: + + + + + Preferre&d audio and subtitles + + + + + &Subtitle: + + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + &Видео + + + + Use s&oftware video equalizer + + + + + A&udio + + + + + Volume + Јачина тона + + + + None + + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + + + + + &Keyboard + + + + + icon + икона + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Овде можеш да промениш било коју пречицу на тастатури. Можеш дуплим кликом или куцањем преко ћелије пречице. Опционо можеш да сачуваш листу и да је учиташ на другом неком рачунару. + + + + &Mouse + + + + + Button functions: + Функције дугмета: + + + + Media seeking + Тражење кроз медијум + + + + Volume control + Контрола тона + + + + Zoom video + + + + + None + Ништа + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + + + + + &Double click + + + + + &Wheel function: + + + + + Shortcut editor + + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + + + + + Select the action for left click on the mouse. + + + + + Double click + + + + + Select the action for double click on the mouse. + + + + + Wheel function + + + + + Select the action for the mouse wheel. + + + + + Play + + + + + Pause + Паузирај + + + + Stop + Заустави + + + + Fullscreen + + + + + Compact + + + + + Screenshot + + + + + Mute + + + + + Frame counter + + + + + Reset zoom + + + + + Exit fullscreen + Искључи опцију Цео Екран + + + + Double size + + + + + Play / Pause + Пусти / Паузирај + + + + Pause / Frame step + Пауза / Фрејм по фрејм + + + + Playlist + Плејлиста + + + + Preferences + + + + + No function + + + + + Change speed + + + + + Normal speed + + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - Следећи ниво + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Интерфејс + + + + <Autodetect> + <Autodetect> + + + + Default + Основно + + + + &Interface + + + + + Seeking + Тражење + + + + Never + Никад + + + + Whenever it's needed + Кад год је потребно + + + + Only after loading a new video + Само после учитавања новог видеа + + + + Recent files + Отварани фајлови + + + + Language + Језик + + + + Here you can change the language of the application. + + + + + &Short jump + + + + + &Medium jump + + + + + &Long jump + + + + + Mouse &wheel jump + + + + + &Use only one running instance of SMPlayer + + + + + Ma&x. items + + + + + St&yle: + + + + + Ico&n set: + + + + + L&anguage: + + + + + Main window + + + + + Auto&resize: + + + + + R&emember position and size + + + + + Default font: + + + + + &Change... + + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + + + + + &Seeking + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Перформансе + + + + &Performance + + + + + Priority + Приоритет + + + + Select the priority for the MPlayer process. + Изабери приоритет за MPlayer процес. + + + + realtime + реално време + + + + high + високо + + + + abovenormal + изнаднормале + + + + normal + нормално + + + + belownormal + исподнормале + + + + idle + слободно време + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Подешавање кеша може да побпљша перформасе на спорим мидијима + + + + Allow frame drop + Допусти испадање фрејмова + + + + Synchronization + Синхронизација + + + + Audio/video auto synchronization + Аудио/Видео аутоматска синхронизација + + + + Fast audio track switching + Брза промена аудиа + + + + Fast seek to chapters in dvds + Брзо тражење поглавља у dvd-јевима + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Постави приоритет процеса за mplayer према предефинисаним приоритетима у Windows-u.<br><b>ПАЖЊА:</b> Употреба realtime приорите може да заглави систем. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Прексочи приказивање неких фрејмова да би задржао Аудио/Видео синхронизацију на спорим системима. + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Интензивније испадање фрејмова (прекида/квари декодовање). Доводи до изобличења слике! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Постепено подешавање Аудио/Видео синхронизације базирано на мерењу аудио кашњења. + + + + Priorit&y: + + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + + + + + Fact&or: + + + + + &Fast audio track switching + + + + + Fast &seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + + + + + Cache for &DVDs: + + + + + Cache for &local files: + + + + + Cache for &streams: + + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Плејлиста + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + Превод + + + + Choose a ttf file + Изабери ttf фајл + + + + Truetype Fonts + Truetype фонтови + + + + &Subtitles + &Превод + + + + Autoload + Аутоматско учитавање + + + + Select first available subtitle + Изабери први доступан превод + + + + Same name as movie + Исто име као и видео фајл + + + + All subs containing movie name + Сви преводи садрже име видео фајла + + + + All subs in directory + Сви преводи у фолдеру + + + + Position + Позиција + + + + 0 + 0 + + + + Top + Врх + + + + Bottom + Дно + + + + Include subtitles on screenshots + Превод видљив на сликама екрана + + + + Font + Фонт + + + + Select the font which will be used for subtitles (and OSD): + Изабери фонт који ће бити коришћен за превод (и OSD): + + + + Size + Величина + + + + No autoscale + Без аутоматске величине + + + + Proportional to movie height + Пропорционално са висином видеа + + + + Proportional to movie width + Пропорционално са ширином видеа + + + + Proportional to movie diagonal + Пропорционално са дијагоналом видеа + + + + Subtitle position + + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Ова опција одређује место превода на екрану. <i>100</i> значи на дну, док <i>0</i> значи на врху. + + + + Au&toload subtitles files (*.srt, *.sub...): + + + + + S&elect first available subtitle + + + + + &Default subtitle encoding: + + + + + Default &position of the subtitles on screen + + + + + &Include subtitles on screenshots + + + + + &TTF font: + + + + + S&ystem font: + + + + + A&utoscale: + + + + + Default subtitle encoding + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + + + + + Middle + vertical alignment + + + + + Top + vertical alignment + + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + + + + + OK + + + + + Cancel + + + + + Apply + + + + + Help + + + + + SMPlayer - Preferences + SMPlayer - Опције + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + + the main window won't be closed when the file/playlist finishes. + + + + + the video will be played in fullscreen mode. + + + + + the video will be played in window mode. + + + + + Enqueue in SMPlayer + + + + + opens the mini gui instead of the default one. + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + Usage: + + + + + directory + + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + %1 minute(s) + + + + + + + %1 and %2 + + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + икона + + + + label + назив + + + + ShortcutGetter + + + Modify shortcut + + + + + Clear + + + + + Press the key combination you want to assign + + + + + Capture + + + + + Capture keystrokes + + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + + + + + Select None + + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + + + + + Yes + + + + + No + + + + + VideoEqualizer + + + Contrast + Контраст + + + + Brightness + Осветљај + + + + Hue + Боја + + + + Saturation + Засићеност + + + + Gamma + Гама + + + + &Reset + &Ресетуј + + + + &Set as default values + &Постави основне вредности + + + + Use the current values as default values for new videos. + Користи тренутно вредности као основне за нове видео фајлове. + + + + Set all controls to zero. + Постави све контроле на нула. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Грешка при чувању фајла + + + + The file couldn't be saved + Фајл не може да се сачува + + + + Error + Грешка + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Јачина тона + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_sv.ts b/plugins/smplayer_plugin/translations/smplayer_sv.ts new file mode 100644 index 000000000..7ee1e479d --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_sv.ts @@ -0,0 +1,7211 @@ + + + + About + + + Version: %1 + Version: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Detta program är gratis. Du får sprida det och/eller ändra det enligt GNU General Public License utgiven av Free Software Foundation; antingen version två av licensen eller (om du så vill) en senare version. + + + + The following people have contributed with translations: + + + + + German + tyska + + + + Slovak + slovakiska + + + + Italian + italienska + + + + French + franska + + + + %1, %2 and %3 + + + + + Simplified-Chinese + Förenklad kinesiska + + + + Russian + Ryska + + + + %1 and %2 + + + + + Hungarian + ungerska + + + + Polish + polska + + + + Japanese + japanska + + + + Dutch + holländska + + + + Ukrainian + ukrainska + + + + Portuguese - Brazil + + + + + Georgian + georgiska + + + + Czech + tjeckiska + + + + Bulgarian + bulgariska + + + + Turkish + Turkiska + + + + Swedish + svenska + + + + Serbian + serbiska + + + + Traditional Chinese + traditionell kinesiska + + + + Romanian + + + + + Portuguese - Portugal + + + + + Greek + grekiska + + + + Finnish + finska + + + + <b>%1</b>: %2 + + + + + <b>%1</b> (%2) + + + + + About SMPlayer + Om SMPlayer + + + + &Info + + + + + icon + + + + + &Contributions + + + + + &Translators + + + + + &License + + + + + Visit our web for updates: + + + + + Get help in our forum: + + + + + You can support SMPlayer by making a donation. + + + + + More info + + + + + Korean + + + + + Macedonian + + + + + Basque + + + + + Using MPlayer %1 + + + + + Catalan + + + + + Portable Edition + + + + + Using Qt %1 (compiled with Qt %2) + + + + + Slovenian + + + + + Arabic + Arabiska + + + + Kurdish + + + + + Galician + + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + Namn + + + + Description + Beskrivning + + + + Shortcut + Kortkommando + + + + &Save + &Spara + + + + &Load + &Öppna + + + + Key files + Nyckelfiler + + + + Choose a filename + Välj ett filnamn + + + + Confirm overwrite? + Bekräfta överskrivning? + + + + The file %1 already exists. +Do you want to overwrite? + Filen %1 finns redan. +Vill du skriva över den? + + + + Choose a file + Välj en fil + + + + Error + Fel + + + + The file couldn't be saved + Filen kunde inte sparas + + + + The file couldn't be loaded + Filen kunde inte öppnas + + + + &Change shortcut... + + + + + AudioEqualizer + + + Audio Equalizer + + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + + + + + &Reset + &Återställ + + + + &Set as default values + &Ange som standardvärden + + + + Use the current values as default values for new videos. + Använd aktuella värden som standardvärden för nya videor. + + + + Set all controls to zero. + Nollställ alla kontroller. + + + + Information + + + + + The current values have been stored to be used as default. + + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - mplayer-logg + + + + SMPlayer - smplayer log + SMPlayer - smplayer-logg + + + + &Open + &Öppna + + + + &Play + &Spela upp + + + + &Video + &Video + + + + &Audio + &Ljud + + + + &Subtitles + &Undertexter + + + + &Browse + &Bläddra + + + + Op&tions + &Inställningar + + + + &Help + &Hjälp + + + + &File... + &Filer ... + + + + D&irectory... + &Mapp ... + + + + &Playlist... + &Spellista ... + + + + &DVD from drive + &DVD från enhet + + + + D&VD from folder... + D&VD från mapp ... + + + + &URL... + &Webbadress ... + + + + &Clear + &Töm + + + + &Recent files + &Tidigare filer + + + + P&lay + &Spela upp + + + + &Pause + &Paus + + + + &Stop + S&topp + + + + &Frame step + St&ega + + + + &Normal speed + &Normal hastighet + + + + &Halve speed + &Halv hastighet + + + + &Double speed + &Dubbel hastighet + + + + Speed &-10% + Hastighet &-10% + + + + Speed &+10% + Hastighet &+10% + + + + Sp&eed + &Hastighet + + + + &Repeat + &Upprepa + + + + &Fullscreen + &Helskärm + + + + &Compact mode + &Kompakt läge + + + + Si&ze + S&torlek + + + + 4:3 &Letterbox + 4:3 &Brevlåda + + + + 16:9 L&etterbox + 16:9 B&revlåda + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &till 16:9 + + + + &Aspect ratio + &Bildformat + + + + &None + &Ingen + + + + &Lowpass5 + &Lågpass5 + + + + Linear &Blend + Linear &Blend + + + + &Deinterlace + &Deinterlace + + + + &Postprocessing + &Efterbehandling + + + + &Autodetect phase + &Autodetektera phase + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + Lägg till n&oise + + + + F&ilters + F&ilter + + + + &Equalizer + &Equalizer + + + + &Screenshot + &Skärmdump + + + + S&tay on top + &Alltid överst + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Filter + + + + &Stereo + &Stereo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Channels + &Kanaler + + + + &Left channel + &Vänster kanal + + + + &Right channel + &Höger kanal + + + + &Stereo mode + S&tereoläge + + + + &Mute + &Ljud av + + + + Volume &- + Volym &- + + + + Volume &+ + Volym &+ + + + + &Delay - + &Fördröjning - + + + + D&elay + + F&ördröjning + + + + + &Select + &Välj + + + + &Load... + &Öppna ... + + + + Delay &- + Fördröjning &- + + + + Delay &+ + Fördröjning &+ + + + + &Up + &Upp + + + + &Down + &Ner + + + + &Title + &Titel + + + + &Chapter + &Kapitel + + + + &Angle + &Vinkel + + + + &Playlist + &Spellista + + + + &Show frame counter + Visa &bildräknare + + + + &Disabled + &Inaktiverad + + + + &Seek bar + &Förloppsindikator + + + + &Time + &Tid + + + + Time + T&otal time + Tid + T&otal tid + + + + &OSD + Vis&a på skärmen (OSD) + + + + &View logs + Visa &loggar + + + + P&references + &Inställningar + + + + About &Qt + Om &Qt + + + + About &SMPlayer + Om &SMPlayer + + + + <empty> + <tom> + + + + Video + Video + + + + Audio + Ljud + + + + Playlists + Spellistor + + + + All files + Alla filer + + + + Choose a file + Välj en fil + + + + SMPlayer - Information + SMPlayer - Information + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Enheterna för cdrom/dvd är inte konfigurerade än. +Nu visas konfigurationsdialogen så att du kan göra detta. + + + + Choose a directory + Välj en mapp + + + + Subtitles + Undertexter + + + + About Qt + Om Qt + + + + Playing %1 + Spelar upp %1 + + + + Pause + Paus + + + + Stop + Stopp + + + + Play / Pause + Spela upp/Paus + + + + Pause / Frame step + Paus/Stegning + + + + U&nload + &Stäng + + + + V&CD + V&CD + + + + C&lose + &Stäng + + + + View &info and properties... + Visa i&nfo och egenskaper ... + + + + Zoom &- + Zoom &- + + + + Zoom &+ + Zoom &+ + + + + &Reset + &Återställ + + + + Move &left + Flytta till &vänster + + + + Move &right + Flytta till &höger + + + + Move &up + Flytta &uppåt + + + + Move &down + Flytta &nedåt + + + + &Pan && scan + &Pan && scan + + + + &Previous line in subtitles + &Föregående rad + + + + N&ext line in subtitles + N&ästa rad + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Sänk vol (2) + + + + Inc volume (2) + Höj vol (2) + + + + Exit fullscreen + Avsluta helskärm + + + + OSD - Next level + OSD - nästa nivå + + + + Dec contrast + Minska kontrast + + + + Inc contrast + Öka kontrast + + + + Dec brightness + Minska ljusstyrka + + + + Inc brightness + Öka ljusstyrka + + + + Dec hue + Minska nyans + + + + Inc hue + Öka nyans + + + + Dec saturation + Minska färgmättnad + + + + Dec gamma + Minska gamma + + + + Next audio + Nästa ljudfil + + + + Next subtitle + Nästa undertext + + + + Next chapter + Nästa kapitel + + + + Previous chapter + Föregående kapitel + + + + Inc saturation + Öka färgmättnad + + + + Inc gamma + Öka gamma + + + + &Load external file... + &Öppna extern fil... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normal) + + + + Y&adif (double framerate) + Y&adif (dubbel framerate) + + + + &Next + &Nästa + + + + Pre&vious + &Föregående + + + + Volume &normalization + + + + + &Audio CD + + + + + Denoise nor&mal + + + + + Denoise &soft + + + + + Denoise o&ff + + + + + Use SSA/&ASS library + + + + + Flip i&mage + + + + + &Toggle double size + + + + + S&ize - + + + + + Si&ze + + + + + + Add &black borders + + + + + Soft&ware scaling + + + + + &FAQ + + + + + Visualize &motion vectors + + + + + &Command line options + + + + + SMPlayer command line options + + + + + Enable &closed caption + + + + + &Forced subtitles only + + + + + Reset video equalizer + + + + + MPlayer has finished unexpectedly. + + + + + Exit code: %1 + + + + + MPlayer failed to start. + + + + + Please check the MPlayer path in preferences. + + + + + MPlayer has crashed. + + + + + See the log for more info. + + + + + &Rotate + + + + + &Off + + + + + &Rotate by 90 degrees clockwise and flip + + + + + Rotate by 90 degrees &clockwise + + + + + Rotate by 90 degrees counterclock&wise + + + + + Rotate by 90 degrees counterclockwise and &flip + + + + + &Jump to... + + + + + Show context menu + + + + + Multimedia + + + + + E&qualizer + + + + + Reset audio equalizer + + + + + Find subtitles on &OpenSubtitles.org... + + + + + Upload su&btitles to OpenSubtitles.org... + + + + + &Tips + + + + + &Auto + + + + + Speed -&4% + + + + + &Speed +4% + + + + + Speed -&1% + + + + + S&peed +1% + + + + + Scree&n + + + + + &Default + + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + &Spår + + + + &Track + audio + &Spår + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer är fortfarande i gång + + + + S&how icon in system tray + Visa i&kon i Meddelandefältet + + + + &Hide + &Dölj + + + + &Restore + &Återställ + + + + &Quit + &Avsluta + + + + Playlist + Spellista + + + + Core + + + Brightness: %1 + Ljusstyrka: %1 + + + + Contrast: %1 + Kontrast: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + Nyans: %1 + + + + Saturation: %1 + Färgmättnad: %1 + + + + Volume: %1 + Volym: %1 + + + + Zoom: %1 + Zoom: %1 + + + + Font scale: %1 + + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + Välkommen till SMPlayer + + + + Audio + Ljud + + + + Subtitle + Undertext + + + + &Main toolbar + &Huvudverktygsfält + + + + &Language toolbar + &Språkverktygsfält + + + + &Toolbars + &Verktygsfält + + + + EqSlider + + + icon + ikon + + + + ErrorDialog + + + Hide log + + + + + Show log + + + + + MPlayer Error + + + + + icon + + + + + Error + Fel + + + + FileDownloader + + + Downloading... + + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Filegenskaper + + + + &Information + &Information + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + Välj &demuxer för denna fil: + + + + &Reset + &Återställ + + + + &Video codec + Video&codec + + + + &Select the video codec: + Välj v&ideocodec: + + + + A&udio codec + &Ljudcodec + + + + &Select the audio codec: + Välj lj&udcodec: + + + + &MPlayer options + Alternativ för &SMPlayer + + + + Additional Options for MPlayer + Ytterligare alternativ för MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + + + + + &Options: + &Alternativ: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + + + + + V&ideo filters: + V&ideofilter: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Och slutligen ljudfilter. Samma regel som för videofilter. +Exempel: resample=44100:0:0,volnorm + + + + Audio &filters: + Ljud&filter: + + + + OK + + + + + Cancel + + + + + Apply + + + + + FindSubtitlesWindow + + + Language + Språk (Language) + + + + Name + Namn + + + + Format + Format + + + + Files + + + + + Date + Datum + + + + Uploaded by + + + + + All + + + + + Close + + + + + &Download + + + + + &Copy link to clipboard + + + + + Error + Fel + + + + Download failed: %1. + + + + + Connecting to %1... + + + + + Downloading... + + + + + Done. + + + + + %1 files available + + + + + Failed to parse the received data. + + + + + Find Subtitles + + + + + &Subtitles for + + + + + &Language: + + + + + &Refresh + + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + Fel vid sparande av fil + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + Allmänt + + + + Size + Storlek + + + + %1 KB (%2 MB) + %1 kB (%2 MB) + + + + URL + Webbadress + + + + Length + Längd + + + + Demuxer + Demuxer + + + + Name + Namn + + + + Artist + Artist + + + + Author + Skapare + + + + Album + Album + + + + Genre + Genre + + + + Date + Datum + + + + Track + Spår + + + + Copyright + Copyright + + + + Comment + Kommentar + + + + Software + Mjukvara + + + + Clip info + Klippinfo + + + + Video + Video + + + + Resolution + Upplösning + + + + Aspect ratio + Bildformat + + + + Format + Format + + + + Bitrate + Bitar/sek + + + + %1 kbps + %1 kbps + + + + Frames per second + Bildrutor/sekund + + + + Selected codec + Vald codec + + + + Initial Audio Stream + Initialljudström + + + + Rate + Frekvens + + + + %1 Hz + %1 Hz + + + + Channels + Kanaler + + + + Audio Streams + Ljudströmmar + + + + Language + Språk (Language) + + + + empty + tom + + + + Subtitles + Undertext + + + + Type + Typ + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + Nr + + + + Stream title + Strömtitel + + + + Stream URL + Ström-URL + + + + File + + + + + InputDVDDirectory + + + Choose a directory + Välj en mapp + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Spela upp en DVD från en mapp + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Du kan spela upp en dvd från din hårddisk. Välj bara den mapp som innehåller mapparna VIDEO_TS och AUDIO_TS. + + + + Choose a directory... + Välj en mapp ... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + + + + + SMPlayer couldn't identify the MPlayer version you're using. + + + + + Version reported by MPlayer: + + + + + Please, &select the correct version: + + + + + 1.0rc1 or older + + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + + + + + InputURL + + + SMPlayer - Enter URL + + + + + &URL: + + + + + It's a &playlist + + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + + + + + Languages + + + Afar + + + + + Abkhazian + + + + + Afrikaans + + + + + Amharic + + + + + Arabic + Arabiska + + + + Assamese + + + + + Aymara + + + + + Azerbaijani + + + + + Bashkir + + + + + Bulgarian + bulgariska + + + + Bihari + + + + + Bislama + + + + + Bengali + + + + + Tibetan + + + + + Breton + + + + + Catalan + + + + + Corsican + + + + + Czech + tjeckiska + + + + Welsh + + + + + Danish + + + + + German + tyska + + + + Greek + grekiska + + + + English + Engelska + + + + Esperanto + + + + + Spanish + Spanska + + + + Estonian + + + + + Basque + + + + + Persian + + + + + Finnish + finska + + + + Faroese + + + + + French + franska + + + + Frisian + + + + + Irish + + + + + Galician + + + + + Guarani + + + + + Gujarati + + + + + Hausa + + + + + Hebrew + + + + + Hindi + + + + + Croatian + + + + + Hungarian + ungerska + + + + Armenian + + + + + Interlingua + + + + + Indonesian + + + + + Interlingue + + + + + Icelandic + + + + + Italian + italienska + + + + Inuktitut + + + + + Japanese + japanska + + + + Javanese + + + + + Georgian + georgiska + + + + Kazakh + + + + + Greenlandic + + + + + Kannada + + + + + Korean + + + + + Kashmiri + + + + + Kurdish + + + + + Kirghiz + + + + + Latin + + + + + Lingala + + + + + Lithuanian + + + + + Latvian + + + + + Malagasy + + + + + Maori + + + + + Macedonian + + + + + Malayalam + + + + + Mongolian + + + + + Moldavian + + + + + Marathi + + + + + Malay + + + + + Maltese + + + + + Burmese + + + + + Nauru + + + + + Nepali + + + + + Dutch + holländska + + + + Norwegian + + + + + Occitan + + + + + Oriya + + + + + Polish + polska + + + + Portuguese + + + + + Quechua + + + + + Romanian + + + + + Russian + Ryska + + + + Kinyarwanda + + + + + Sanskrit + + + + + Sindhi + + + + + Slovak + slovakiska + + + + Slovenian + + + + + Samoan + + + + + Shona + + + + + Somali + + + + + Albanian + + + + + Serbian + serbiska + + + + Sundanese + + + + + Swedish + svenska + + + + Swahili + + + + + Tamil + + + + + Telugu + + + + + Tajik + + + + + Thai + + + + + Tigrinya + + + + + Turkmen + + + + + Tagalog + + + + + Tonga + + + + + Turkish + Turkiska + + + + Tsonga + + + + + Tatar + + + + + Twi + + + + + Uighur + + + + + Ukrainian + ukrainska + + + + Urdu + + + + + Uzbek + + + + + Vietnamese + + + + + Wolof + + + + + Xhosa + + + + + Yiddish + + + + + Yoruba + + + + + Zhuang + + + + + Chinese + + + + + Zulu + + + + + Portuguese - Brazil + + + + + Portuguese - Portugal + + + + + Simplified-Chinese + Förenklad kinesiska + + + + Traditional Chinese + traditionell kinesiska + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + Västeuropeiska språk + + + + Western European Languages with Euro + Västeuropeiska språk med euro + + + + Slavic/Central European Languages + Slaviska/Centraleuropeiska språk + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, galiciska, maltesiska, turkiska + + + + Old Baltic charset + Gammal baltisk teckenuppsättning + + + + Cyrillic + Kyrilliska + + + + Modern Greek + Modern grekiska + + + + Baltic + Baltiska + + + + Celtic + Keltiska + + + + Hebrew charsets + Hebreisk teckenuppsättning + + + + Ukrainian, Belarusian + Ukrainska, vitryska + + + + Simplified Chinese charset + Förenklad kinesiska + + + + Traditional Chinese charset + Traditionell kinesiska + + + + Japanese charsets + Japansk teckenuppsättning + + + + Korean charset + Koreansk teckenuppsättning + + + + Thai charset + Thailändsk teckenuppsättning + + + + Cyrillic Windows + Kyrillisk Windows + + + + Slavic/Central European Windows + Slavisk/Centraleuropeisk Windows + + + + Arabic Windows + + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Välj filnamn att spara som + + + + Confirm overwrite? + Bekräfta ersättning? + + + + The file already exists. +Do you want to overwrite? + Filen finns redan. +Vill du skriva över den? + + + + Error saving file + Fel vid sparande av fil + + + + The log couldn't be saved + Loggen kunde inte sparas + + + + Logs + Loggar + + + + LogWindowBase + + + Log Window + Loggfönster + + + + Save + Spara + + + + Copy to clipboard + Kopiera till Urklipp + + + + Close + Stäng + + + + &Close + &Stäng + + + + MiniGui + + + Control bar + + + + + MpcGui + + + Control bar + + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Namn + + + + Length + Längd + + + + &Play + &Spela upp + + + + &Edit + &Redigera + + + + Playlists + Spellistor + + + + Choose a file + Välj en fil + + + + Choose a filename + Välj ett filnamn + + + + Confirm overwrite? + Bekräfta ersättning? + + + + The file %1 already exists. +Do you want to overwrite? + Filen %1 finns redan. +Vill du skriva över den? + + + + All files + Alla filer + + + + Select one or more files to open + Markera en eller flera filer att öppna + + + + Choose a directory + Välj en mapp + + + + Edit name + Redigera namn + + + + Type the name that will be displayed in the playlist for this file: + Skriv in det namn som ska visas i spellistan för denna fil: + + + + &Load + &Öppna + + + + &Save + &Spara + + + + &Next + &Nästa + + + + Pre&vious + &Föregående + + + + Move &up + Flytta &upp + + + + Move &down + Flytta &ner + + + + &Repeat + &Upprepa + + + + S&huffle + &Blanda + + + + Add &current file + Lägg till &aktuell fil + + + + Add &file(s) + Lägg till &fil(er) + + + + Add &directory + Lägg till &mapp + + + + Remove &selected + Ta bort &markerade + + + + Remove &all + Ta bort &alla + + + + SMPlayer - Playlist + SMPlayer - Spellista + + + + Add... + Lägg till ... + + + + Remove... + Ta bort ... + + + + Playlist modified + Spellistan ändrad + + + + There are unsaved changes, do you want to save the playlist? + Det finns ändringar som inte sparats. Vill du spara spellistan? + + + + Preferences + + + + + PlaylistPreferences + + + Playlist - Preferences + + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + + + + + &Save copy of playlist on exit + + + + + &Play files from start + + + + + PrefAdvanced + + + Advanced + Avancerat + + + + Auto + + + + + &Advanced + &Avancerat + + + + icon + ikon + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Här kan du ange extra alternativ för MPlayer. +Skilj dem åt med mellanslag. +Exempel: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Du kan också ange ytterligare videofilter. +Skilj dem med ",". Använd inte mellanslag! +Exempel: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Och slutligen ljudfilter. Samma regel som för videofilter. +Exempel: resample=44100:0:0,volnorm + + + + Log MPlayer output + Logga output från MPLayer + + + + Log SMPlayer output + Logga output från SMPlayer + + + + This option is mainly intended for debugging the application. + Detta alternativ är huvudsakligen tänkt för att avbuggning av programmet. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Detta alternativ kan minska flimmer, but det skulle också kunna göra så att videon inte visas på rätt sätt. + + + + Filter for SMPlayer logs + + + + + &Monitor aspect: + + + + + &Run MPlayer in its own window + + + + + &Options: + &Alternativ: + + + + V&ideo filters: + V&ideofilter: + + + + Audio &filters: + Ljud&filter: + + + + &Colorkey: + + + + + Log &SMPlayer output + + + + + &Filter for SMPlayer logs: + + + + + C&hange... + + + + + Logs + + + + + Log MPlayer &output + + + + + Options for MP&layer + + + + + Autosave MPlayer log + + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + + + + + Select the aspect ratio of your monitor. + + + + + Run MPlayer in its own window + + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + + + + + Options + + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + + + + + Rebuild index if needed + + + + + Rebuild &index if needed + + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Typ + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + + + + + Select all + + + + + Check all file types in the list + + + + + Uncheck all file types in the list + + + + + List of file types + + + + + File types + + + + + Media files handled by SMPlayer: + + + + + Select All + + + + + Select None + + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + Select none + + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + + + + + PrefDrives + + + Drives + Enheter + + + + icon + ikon + + + + CD device + + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + + + + + DVD device + + + + + Choose your DVD device. It will be used to play DVDs. + + + + + Select your &CD device: + + + + + Select your &DVD device: + + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + Allmänt + + + + &General + + + + + Paths + Sökvägar + + + + Media settings + Inställningar för media + + + + Preferred audio and subtitles + Standardspråk - tal och undertexter + + + + Video + Video + + + + Start videos in fullscreen + Starta video i helskärmsläge + + + + Disable screensaver + Inaktivera skärmsläckare + + + + Audio + Ljud + + + + AC3/DTS pass-through S/PDIF + AC3/DTS pass-through S/PDIF + + + + Select the mplayer executable + Markera mplayers programfil + + + + Executables + Program + + + + All files + Alla filer + + + + Select a directory + Välj en mapp + + + + MPlayer executable + + + + + Screenshots folder + + + + + Video output driver + + + + + Audio output driver + + + + + Select the audio output driver. + Välj drivrutin för ljudoutput. + + + + Remember settings + + + + + Preferred audio language + + + + + Preferred subtitle language + + + + + Software video equalizer + + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Välj detta alternativ om ditt grafikkort inte stöder equalizer för video eller den valda drivrutinen för video. <br><b>OBS:</b> Detta alternativ kan vara inkompatibelt med vissa drivrutiner för video-output. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Om du markerar detta alternativ så spelas all video upp i helskärmsläge. + + + + Software volume control + + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Använd detta alternativ om du vill använda ett mjukvarubasat mixerbord i stället för det i ljudkortet. + + + + Postprocessing quality + + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Ändrar dynamiskt nivån på efterbehandlingen beroende på tillgänglig CPU-tid. Den siffra du anger bestämmer den maximala nivån. Vanligen kan du använda något högt tal. + + + + Change volume + + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + 0 + 0 + + + + &Change volume on every file + + + + + Select the &MPlayer executable: + + + + + &Folder for storing screenshots: + + + + + &Audio: + + + + + &Remember settings for all files (audio track, subtitles...) + + + + + Su&btitles: + + + + + &Quality: + + + + + Start videos in &fullscreen + + + + + Disable &screensaver + + + + + &Default volume: + + + + + Use s&oftware volume control + + + + + Ma&x. Amplification: + + + + + &AC3/DTS pass-through S/PDIF + + + + + Direct rendering + + + + + Double buffering + + + + + D&irect rendering + + + + + Dou&ble buffering + + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + &Enable postprocessing by default + + + + + Volume &normalization by default + + + + + Close when finished + + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + + + + + 4 (4.0 Surround) + + + + + 6 (5.1 Surround) + + + + + C&hannels by default: + + + + + &Pause when minimized + + + + + Pause when minimized + + + + + Enable postprocessing by default + + + + + Max. Amplification + + + + + Volume normalization by default + + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + + + + + Sets the initial volume that new files will use. + + + + + Channels by default + + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + + + + + Audio track + + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + + + + + Audi&o: + + + + + Preferred language: + + + + + Preferre&d audio and subtitles + + + + + &Subtitle: + + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + + + + + &Video + &Video + + + + Use s&oftware video equalizer + + + + + A&udio + + + + + Volume + Volym + + + + None + + + + + Lowpass5 + + + + + Yadif (normal) + + + + + Yadif (double framerate) + + + + + Linear Blend + + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + + + + + Remember &time position + + + + + Change volume just before p&laying + + + + + Enable the audio equalizer + + + + + Check this option if you want to use the audio equalizer. + + + + + &Enable the audio equalizer + + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + + + + + User defined... + + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Tangentbord och mus + + + + &Keyboard + &Tangentbord + + + + icon + ikon + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Här kan du ändra kortkommandon. Dubbelklicka eller börja skriva över ett kortkommandofält. Du kan också spara listan och dela med dig av den till andra användare eller datorer. + + + + &Mouse + &Mus + + + + Button functions: + Knappfunktioner: + + + + Media seeking + Snabbspolning + + + + Volume control + Volymkontroll + + + + Zoom video + Zooma video + + + + None + Ingen + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + + + + + &Double click + + + + + &Wheel function: + + + + + Shortcut editor + + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + + + + + Select the action for left click on the mouse. + + + + + Double click + + + + + Select the action for double click on the mouse. + + + + + Wheel function + + + + + Select the action for the mouse wheel. + + + + + Play + + + + + Pause + Paus + + + + Stop + Stopp + + + + Fullscreen + + + + + Compact + + + + + Screenshot + + + + + Mute + + + + + Frame counter + + + + + Reset zoom + + + + + Exit fullscreen + Avsluta helskärm + + + + Double size + + + + + Play / Pause + Spela upp/Paus + + + + Pause / Frame step + Paus/Stegning + + + + Playlist + Spellista + + + + Preferences + + + + + No function + + + + + Change speed + + + + + Normal speed + + + + + Keyboard + + + + + Mouse + + + + + Middle click + + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + + + + + Go backward (medium) + + + + + Go backward (long) + + + + + Go forward (short) + + + + + Go forward (medium) + + + + + Go forward (long) + + + + + OSD - Next level + OSD - nästa nivå + + + + Show context menu + + + + + &Right click + + + + + Increase volume + + + + + Decrease volume + + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Gränssnitt + + + + <Autodetect> + <Autodetektera> + + + + Default + Standard + + + + &Interface + + + + + Seeking + Sökning + + + + Never + Aldrig + + + + Whenever it's needed + När det behövs + + + + Only after loading a new video + Endast när ny video öppnats + + + + Recent files + Tidigare + + + + Language + Språk (Language) + + + + Here you can change the language of the application. + + + + + &Short jump + + + + + &Medium jump + + + + + &Long jump + + + + + Mouse &wheel jump + + + + + &Use only one running instance of SMPlayer + + + + + Ma&x. items + + + + + St&yle: + + + + + Ico&n set: + + + + + L&anguage: + + + + + Main window + + + + + Auto&resize: + + + + + R&emember position and size + + + + + Default font: + + + + + &Change... + + + + + &Behaviour of time slider: + + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + + + + + &Seeking + + + + + Ins&tances + + + + + Autoresize + + + + + The main window can be resized automatically. Select the option you prefer. + + + + + Remember position and size + + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + + + + + Select the icon set you prefer for the application. + + + + + Style + + + + + Select the style you prefer for the application. + + + + + Default font + + + + + You can change here the application's font. + + + + + Short jump + + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + + + + + Medium jump + + + + + medium jump + + + + + Long jump + + + + + long jump + + + + + Mouse wheel jump + + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + + + + + Select what to do when dragging the time slider. + + + + + Instances + + + + + Use only one running instance of SMPlayer + + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + + + + + Mini GUI + + + + + GUI + + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + + + + + Automatic port + + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + + + + + Port to listen + + + + + &Automatic + + + + + &Manual + + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Prestanda + + + + &Performance + + + + + Priority + Prioritering + + + + Select the priority for the MPlayer process. + Ange prioritet för MPlayer-processen. + + + + realtime + realtid + + + + high + hög + + + + abovenormal + över normal + + + + normal + normal + + + + belownormal + under normal + + + + idle + inaktiv + + + + Cache + Cache + + + + KB + kB + + + + Setting a cache may improve performance on slow media + En cache kan förbättra prestanda för långsamma media. + + + + Allow frame drop + Tillåt 'frame drop' + + + + Synchronization + Synkronisering + + + + Audio/video auto synchronization + Autosynkronisering av ljud/video + + + + Fast audio track switching + Snabbt byte av ljudspår + + + + Fast seek to chapters in dvds + Snabbsökning till kapitel på DVD + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Ange processprioritering för MPlayer enligt de fördefinierade prioriteter tillgängliga under Windows.<br><b>VARNING:</b> Realtidsprioritet kan låsa systemet helt. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Strunta i att visa vissa bildrutor för att bibehålla bild-ljudsynkroniseringen på långsamma system. + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Hoppar över ännu fler bildrutor. Leder till distortion av bilden! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Anpassar gradvis ljud-bildsynkroniseringen baserat på mätningar av ljudfördröjning. + + + + Priorit&y: + + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + + + + + Fact&or: + + + + + &Fast audio track switching + + + + + Fast &seek to chapters in dvds + + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + + + + + Cache for &DVDs: + + + + + Cache for &local files: + + + + + Cache for &streams: + + + + + Enabled + + + + + Skip (always) + + + + + Skip only on HD videos + + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache for audio CDs + + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + + + + + Cache for VCDs + + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + + + + + Threads for decoding + + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + &Spellista + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + + + + + Choose a ttf file + Välj en TTF-fil + + + + Truetype Fonts + TrueType-teckensnitt + + + + &Subtitles + &Undertexter + + + + Autoload + Autoöppna + + + + Select first available subtitle + Välj första tillgängliga undertext + + + + Same name as movie + Samma namn som filmen + + + + All subs containing movie name + Alla texter som innehåller filmnamnet + + + + All subs in directory + Alla undertexter i mappen + + + + Position + Position + + + + 0 + 0 + + + + Top + Uppe + + + + Bottom + Nere + + + + Include subtitles on screenshots + Inkludera undertext i skärmdump + + + + Font + Teckensnitt + + + + Select the font which will be used for subtitles (and OSD): + Välj teckensnitt för undertexter (och meddelanden på skärmen): + + + + Size + Storlek + + + + No autoscale + Ej autoskala + + + + Proportional to movie height + Proportionell mot filmhöjd + + + + Proportional to movie width + Proportionell mot filmbredd + + + + Proportional to movie diagonal + Proportionell mot diagonalen + + + + Subtitle position + + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Detta alternativ anger position för undertexterna i videofönstret. <i>100</i> betyder längst ner, medan <i>0</i> betyder längst upp. + + + + Au&toload subtitles files (*.srt, *.sub...): + + + + + S&elect first available subtitle + + + + + &Default subtitle encoding: + + + + + Default &position of the subtitles on screen + + + + + &Include subtitles on screenshots + + + + + &TTF font: + + + + + S&ystem font: + + + + + A&utoscale: + + + + + Default subtitle encoding + + + + + TTF font + + + + + System font + + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + + + + + Text color + + + + + Select the color for the text of the subtitles. + + + + + Border color + + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + + + + + Middle + vertical alignment + + + + + Top + vertical alignment + + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + + + + + OK + + + + + Cancel + + + + + Apply + + + + + Help + + + + + SMPlayer - Preferences + SMPlayer - Inställningar + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + + + + + the main window won't be closed when the file/playlist finishes. + + + + + the video will be played in fullscreen mode. + + + + + the video will be played in window mode. + + + + + Enqueue in SMPlayer + + + + + opens the mini gui instead of the default one. + + + + + Restores the old associations and cleans up the registry. + + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + + + + + Usage: + + + + + directory + + + + + action_name + + + + + action_list + + + + + opens the default gui. + + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + + %1 minute(s) + + + + + + + + %1 and %2 + + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + ikon + + + + label + etikett + + + + ShortcutGetter + + + Modify shortcut + + + + + Clear + + + + + Press the key combination you want to assign + + + + + Capture + + + + + Capture keystrokes + + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + + + + + Select None + + + + + TimeDialog + + + SMPlayer - Seek + + + + + &Jump to: + + + + + TristateCombo + + + Auto + + + + + Yes + + + + + No + + + + + VideoEqualizer + + + Contrast + Kontrast + + + + Brightness + Ljusstyrka + + + + Hue + Nyans + + + + Saturation + Färgmättnad + + + + Gamma + Gamma + + + + &Reset + &Återställ + + + + &Set as default values + &Ange som standardvärden + + + + Use the current values as default values for new videos. + Använd aktuella värden som standardvärden för nya videor. + + + + Set all controls to zero. + Nollställ alla kontroller. + + + + Video Equalizer + + + + + Information + + + + + The current values have been stored to be used as default. + + + + + VideoPreview + + + Video preview + + + + + Cancel + + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Fel vid sparande av fil + + + + The file couldn't be saved + Filen kunde inte sparas + + + + Error + Fel + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Volym + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_tr.ts b/plugins/smplayer_plugin/translations/smplayer_tr.ts new file mode 100644 index 000000000..ffaa4beb4 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_tr.ts @@ -0,0 +1,7339 @@ + + + + About + + + Version: %1 + Sürüm: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Bu ücretsiz bir yazılımdır; "Free Software Foundation" tarafından yayınlanan GNU lisansının -isteğinize bağlı olarak- 2. veya daha ileriki bir sürümünün koşullarını gözeterek çoğaltabilir ve/veya değiştirebilirsiniz. + + + + The following people have contributed with translations: + Çevirileriyle katkıda bulunanlar: + + + + German + Almanca + + + + Slovak + Slovakça + + + + Italian + İtalyanca + + + + French + Fransızca + + + + %1, %2 and %3 + %1, %2 ve %3 + + + + Simplified-Chinese + Basitleştirilmiş Çince + + + + Russian + Rusça + + + + %1 and %2 + %1 ve %2 + + + + Hungarian + Macarca + + + + Polish + Lehçe + + + + Japanese + Japonca + + + + Dutch + Felemenkçe + + + + Ukrainian + Ukraynaca + + + + Portuguese - Brazil + Brezilya Portegizcesi + + + + Georgian + Gürcüce + + + + Czech + Çekçe + + + + Bulgarian + Bulgarca + + + + Turkish + Türkçe + + + + Swedish + İsveççe + + + + Serbian + Sırpça + + + + Traditional Chinese + Geleneksel Çince + + + + Romanian + Romence + + + + Portuguese - Portugal + Portekiz Portegizcesi + + + + Greek + Yunanca + + + + Finnish + Fince + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + SMPlayer hakkında + + + + &Info + B&ilgi + + + + icon + simge + + + + &Contributions + Katk&ılar + + + + &Translators + &Çevirmenler + + + + &License + &Lisans + + + + Visit our web for updates: + Güncellemeler için sayfamızı ziyaret edin: + + + + Get help in our forum: + Aradığınız yardımı forumumuzda bulun: + + + + You can support SMPlayer by making a donation. + Bağışta bulunarak SmPlayer'ı destekleyebilirsiniz. + + + + More info + Daha fazla bilgi + + + + Korean + Korece + + + + Macedonian + Makedonca + + + + Basque + Baskça + + + + Using MPlayer %1 + Mplayer'ı kullanıyor %1 + + + + Catalan + Katalanca + + + + Portable Edition + Taşınabilir Sürüm + + + + Using Qt %1 (compiled with Qt %2) + Qt'yi kullanıyor %1(Qt ile derlendi %2) + + + + Slovenian + Slovence + + + + Arabic + Arapça + + + + Kurdish + Kürtçe + + + + Galician + Galiçyaca + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + İsim + + + + Description + Tanım + + + + Shortcut + Kısayol + + + + &Save + &Kaydet + + + + &Load + &Yükle + + + + Key files + Anahtar dosyaları + + + + Choose a filename + Bir dosya ismi seçin + + + + Confirm overwrite? + Üstüne yazmayı onaylıyor musunuz? + + + + The file %1 already exists. +Do you want to overwrite? + %1 dosyası zaten var. +Üstüne yazmak istiyor musunuz? + + + + Error + Hata + + + + The file couldn't be saved + Dosya kaydedilemedi + + + + Choose a file + Bir dosya seçin + + + + The file couldn't be loaded + Dosya yüklenemedi + + + + &Change shortcut... + Kısa&yolu değiştirin... + + + + AudioEqualizer + + + Audio Equalizer + Ses Dengeleyici + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.000 kHz + + + + &Apply + &Uygula + + + + &Reset + &Sıfırla + + + + &Set as default values + &Varsayılan yap + + + + Use the current values as default values for new videos. + Bu değerleri tüm yeni videolar için kullan. + + + + Set all controls to zero. + Tüm kontrolleri sıfırla. + + + + Information + Bilgi + + + + The current values have been stored to be used as default. + Hali hazırdaki değerler varsayılan değerler olarak kaydedildi. + + + + BaseGui + + + &File... + Dosy&a... + + + + D&irectory... + &Klasör... + + + + &Playlist... + Oynatma &Listesi... + + + + V&CD + V&CD + + + + &DVD from drive + &DVD + + + + D&VD from folder... + D&VD'yi klasörden aç... + + + + &URL... + &URL... + + + + C&lose + &Kapat + + + + P&lay + &Oynat + + + + &Pause + Du&raklat + + + + &Stop + &Durdur + + + + &Frame step + &Bir kare ilerle + + + + Play / Pause + Oynat / Duraklat + + + + Pause / Frame step + Duraklat / Bir kare ilerle + + + + &Repeat + &Tekrarla + + + + &Normal speed + &Normal Hızda + + + + &Halve speed + &Yarı Hızda + + + + &Double speed + İki ka&t hızlı + + + + Speed &-10% + %10 Yava&şlat + + + + Speed &+10% + %10 Hı&zlandır + + + + Sp&eed + &Hız + + + + &Fullscreen + Tam &ekran + + + + &Compact mode + &Büyük ekran + + + + &Equalizer + &Eşitleyici + + + + &Screenshot + Ekran görüntü&sü + + + + S&tay on top + Her zaman &üstte + + + + Zoom &- + Uzaklaştır &- + + + + Zoom &+ + Yakınlaştır &+ + + + + &Reset + &Sıfırla + + + + Move &left + Sol&a taşı + + + + Move &right + &Sağa taşı + + + + Move &up + &Yukarı taşı + + + + Move &down + &Aşağı taşı + + + + &Postprocessing + &Ardişlem + + + + &Autodetect phase + &Aşamayı otomatik olarak bul + + + + &Deblock + &Döngü + + + + De&ring + De&ring + + + + Add n&oise + N&oise ekle + + + + F&ilters + F&iltreler + + + + &Mute + &Sessiz + + + + Volume &- + Ses &- + + + + Volume &+ + Ses &+ + + + + &Delay - + İler&i al - + + + + D&elay + + &Geri al + + + + + &Extrastereo + &Extrastereo + + + + &Karaoke + &Karaoke + + + + &Filters + &Süzgeçler + + + + &Load... + &Yükle... + + + + U&nload + &Kaldır + + + + Delay &- + İler&i al - + + + + Delay &+ + &Geri al + + + + + &Up + Y&ukarı + + + + &Down + A&şağı + + + + &Playlist + &Oynatma listesi + + + + View &info and properties... + &Bilgi ve özelliklere bak... + + + + &Show frame counter + Kare &sayacını göster + + + + P&references + &Özellikler + + + + &View logs + Kay&ıtlara bak + + + + About &Qt + &Qt Hakkında + + + + About &SMPlayer + &SMPlayer Hakkında + + + + &Open + &Aç + + + + &Play + &Oynat + + + + &Video + V&ideo + + + + &Audio + &Ses + + + + &Subtitles + Alt &yazı + + + + &Browse + &Gezin + + + + Op&tions + S&eçenekler + + + + &Help + &Yardım + + + + &Recent files + &Son açılanlar + + + + &Clear + &Temizle + + + + Si&ze + &Boyut + + + + &Aspect ratio + En/boy or&anı + + + + &Deinterlace + &Görüntü ayrıştırma + + + + &Pan && scan + &Pan && scan + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &to 16:9 + + + + &None + &Hiçbiri + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Linear &Blend + + + + &Channels + &Kanallar + + + + &Stereo mode + &Stereo modu + + + + &Stereo + &Steryo + + + + &4.0 Surround + &4.0 Surround + + + + &5.1 Surround + &5.1 Surround + + + + &Left channel + &Sol kanal + + + + &Right channel + &Sağ kanal + + + + &Select + &Seç + + + + &Title + &Başlık + + + + &Chapter + &Bölüm + + + + &Angle + &Açı + + + + &OSD + &OSD + + + + &Disabled + &Devredışı + + + + &Seek bar + G&ezinme çubuğu + + + + &Time + &Süre + + + + Time + T&otal time + Süre + T&oplam süre + + + + SMPlayer - mplayer log + SMPlayer - mplayer kaydı + + + + SMPlayer - smplayer log + SMPlayer - smplayer kaydı + + + + <empty> + <boş> + + + + Video + Video + + + + Audio + Ses + + + + Playlists + Oynatma listesi + + + + All files + Tüm dosyalar + + + + Choose a file + Bir dosya seçin + + + + SMPlayer - Information + SMPlayer - Bilgi + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD cihazları henüz yapılandırılmadı. +Tamama bastığınızda ayarları yapabileceğiniz ekran açılacak. + + + + Choose a directory + Bir klasör seçin + + + + Subtitles + Alt yazılar + + + + About Qt + Qt Hakkında + + + + Playing %1 + %1'i oynatıyor + + + + Pause + Duraklat + + + + Stop + Durdur + + + + &Previous line in subtitles + Bir &önceki satır + + + + N&ext line in subtitles + Bir &sonraki satır + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Sesi kıs (2) + + + + Inc volume (2) + Sesi yükselt (2) + + + + Exit fullscreen + Tam ekrandan çık + + + + OSD - Next level + OSD - Sonraki seviye + + + + Dec contrast + Zıtlığı azalt + + + + Inc contrast + Zıtlığı arttır + + + + Dec brightness + Parlaklığı azalt + + + + Inc brightness + Barlaklığı arttır + + + + Dec hue + Renk tonunu azalt + + + + Inc hue + Renk tonunu arttır + + + + Dec saturation + Doygunluğu azalt + + + + Dec gamma + Gamayı azalt + + + + Next audio + Bir sonraki ses + + + + Next subtitle + Bir sonraki alt yazı + + + + Next chapter + Bir sonraki bölüm + + + + Previous chapter + Bir önceki bölüm + + + + Inc saturation + Doygunluğu arttır + + + + Inc gamma + Gamayı arttır + + + + &Load external file... + Harici dosya yük&le... + + + + &Kerndeint + &Kerndeint + + + + &Yadif (normal) + &Yadif (normal) + + + + Y&adif (double framerate) + &Yadif (kare sayısını ikiye katla) + + + + &Next + &Sonraki + + + + Pre&vious + &Önceki + + + + Volume &normalization + Ses &normalleştirme + + + + &Audio CD + &Müzik CD'si + + + + Denoise nor&mal + Nor&mal denoise + + + + Denoise &soft + Hafif denoi&se + + + + Denoise o&ff + Denois&e kapalı + + + + Use SSA/&ASS library + SSA/&ASS kütüphanesini kullan + + + + Flip i&mage + Görüntüyü ters &çevir + + + + &Toggle double size + İ&ki katı büyüt + + + + S&ize - + &Boyut - + + + + Si&ze + + B&oyut + + + + + Add &black borders + &Çerçeve ekle + + + + Soft&ware scaling + Ya&zılım derecelendirme + + + + &FAQ + &SSS + + + + Visualize &motion vectors + Devini&m vektörünü canlandır + + + + &Command line options + Komut satırı se&çenekleri + + + + SMPlayer command line options + SmPlayer komut satırı seçenekleri + + + + Enable &closed caption + &Closed caption'ı etkinleştir + + + + &Forced subtitles only + Sadece zorunlu alt yaz&ılar + + + + Reset video equalizer + Video eşitleyiciyi sıfırla + + + + MPlayer has finished unexpectedly. + MPlayer beklenmeyen bir şekilde kapandı. + + + + Exit code: %1 + Çıkış kodu: %1 + + + + MPlayer failed to start. + MPlayer başlatılamadı. + + + + Please check the MPlayer path in preferences. + Lütfen seçeneklerden MPlayer'ın konumunu kontrol edin. + + + + MPlayer has crashed. + MPlayer çöktü. + + + + See the log for more info. + Daha fazla bilgi için kayıt dosyasına bakınız. + + + + &Rotate + Döndü&r + + + + &Off + &Kapalı + + + + &Rotate by 90 degrees clockwise and flip + Saat yönünde 90 derece döndür ve ters çevi&r + + + + Rotate by 90 degrees &clockwise + Saat yönünde 90 dere&ce döndür + + + + Rotate by 90 degrees counterclock&wise + Saat yönünün tersinde 90 derece d&öndür + + + + Rotate by 90 degrees counterclockwise and &flip + Saat yönünün tersinde 90 derece &döndür ve ters çevir + + + + &Jump to... + &Atla... + + + + Show context menu + İçerik menüsünü göster + + + + Multimedia + Çoklu ortam + + + + E&qualizer + Den&geleyici + + + + Reset audio equalizer + Ses dengeleyiciyi sıfırla + + + + Find subtitles on &OpenSubtitles.org... + &OpenSubtitles.org'dan alt yazı bul... + + + + Upload su&btitles to OpenSubtitles.org... + &OpenSubtitles.org'a alt yazı yükle... + + + + &Tips + İpu&çları + + + + &Auto + Otom&atik + + + + Speed -&4% + Hız -&4% + + + + &Speed +4% + Hı&z +4% + + + + Speed -&1% + Hız -&1% + + + + S&peed +1% + &Hız +1% + + + + Scree&n + Ekra&n + + + + &Default + Varsa&yılan + + + + Mirr&or image + Ayna yan&sısı + + + + Next video + Bir sonraki video + + + + &Track + video + &İz + + + + &Track + audio + &İz + + + + Warning - Using old MPlayer + Uyarı - MPlayer'ın eski bir sürümünü kullanıyorsunuz + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + Sisteminizde yüklü olan MPlayer (%1) sürümü eski. SMPlayer bu sürümle düzgün çalışamaz: bazı seçenekler çalışmayacaktır. Ayrıca alt yazı seçimi başarısız olabilir... + + + + Please, update your MPlayer. + Lütfen MPlayer'ı güncelleyiniz. + + + + (This warning won't be displayed anymore) + (Bu uyarı bir daha gösterilmeyecektir) + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer zaten çalışıyor + + + + S&how icon in system tray + Simgeyi sistem tablasında &göster + + + + &Hide + &Gizle + + + + &Restore + Ge&ri yükle + + + + &Quit + &Çıkış + + + + Playlist + Oynatma listesi + + + + Core + + + Brightness: %1 + Parlaklık: %1 + + + + Contrast: %1 + Zıtlık: %1 + + + + Gamma: %1 + Gama: %1 + + + + Hue: %1 + Renk tonu: %1 + + + + Saturation: %1 + Doygunluk: %1 + + + + Volume: %1 + Ses: %1 + + + + Zoom: %1 + Yakınlık: %1 + + + + Font scale: %1 + Font ölçeği: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + SMPlayer'a Hoş Geldiniz + + + + &Main toolbar + &Ana araç çubuğu + + + + &Language toolbar + &Dil araç çubuğu + + + + &Toolbars + &Araç çubukları + + + + Audio + Ses + + + + Subtitle + Alt yazı + + + + EqSlider + + + icon + Simge + + + + ErrorDialog + + + Hide log + Kaydı sakla + + + + Show log + Kaydı göster + + + + MPlayer Error + MPlayer hatası + + + + icon + simge + + + + Error + Hata + + + + FileDownloader + + + Downloading... + İndiriyor... + + + + Downloading %1 + %1'i indiriyor + + + + FilePropertiesDialog + + + OK + Tamam + + + + Cancel + İptal + + + + Apply + Uygula + + + + SMPlayer - File properties + SMPlayer - Dosya özellikleri + + + + &Information + &Bilgi + + + + &Demuxer + &Demuxer + + + + &Select the demuxer that will be used for this file: + Bu do&sya için kullanılacak demuxer'ı seçin: + + + + &Reset + &Sıfırla + + + + &Video codec + &Video kodlayıcısı + + + + &Select the video codec: + Video kodlayıcısını &seçin: + + + + A&udio codec + &Ses kodlayıcısı + + + + &Select the audio codec: + &Ses kodlayıcısını seçin: + + + + &MPlayer options + &MPlayer seçenekleri + + + + Additional Options for MPlayer + Mplayer için Ek Özellikler + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Burada mplayer'a fazladan özellikler ekleyebilirsiniz. +Özellikler arasında boşluk bırakmayı unutmayın. +Örnek: -flip -nosound + + + + &Options: + &Seçenekler: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + İlave video süzgeçleri de ekleyebilirsiniz. +Süzgeçleri "," ile ayırın. Boşluk kullanmayın! +Örnek: scale=512:-2,eq2=1 + + + + V&ideo filters: + V&ideo süzgeçleri: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Ve son olarak ses süzgeçleri. Video süzgeçlerinde geçerli olan kurallar burada da geçerli. +Örnek: resample=44100:0:0,volnorm + + + + Audio &filters: + Ses &süzgeçleri: + + + + FindSubtitlesWindow + + + Language + Dil + + + + Name + İsim + + + + Format + Biçim + + + + Files + Dosyalar + + + + Date + Tarih + + + + Uploaded by + Yükleyen + + + + All + Hepsi + + + + Close + Kapat + + + + &Download + İn&dir + + + + &Copy link to clipboard + Bağlantıyı panoya &kopyala + + + + Error + Hata + + + + Download failed: %1. + İndirme başarısız: %1. + + + + Connecting to %1... + %1'e bağlanıyor... + + + + Downloading... + İndiriyor... + + + + Done. + Bitti. + + + + %1 files available + %1 dosya kaldı + + + + Failed to parse the received data. + Alınan bilgi ayrıştırılamadı. + + + + Find Subtitles + Alt yazı Bul + + + + &Subtitles for + &Bunun için bul + + + + &Language: + Di&l: + + + + &Refresh + Yen&ile + + + + Subtitle saved as %1 + Alt yazı %1 olarak kaydedildi + + + + %1 subtitle(s) extracted + + %1 alt yazı genişletildi + + + + + + Overwrite? + Üstüne yazmak istiyor musunuz? + + + + The file %1 already exits, overwrite? + %1 zaten var, üstüne yazmak istiyor musunuz? + + + + Error saving file + Dosyayı kaydederken hata oluştu + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + %1 klasörüne +indirilen dosya kaydedilemedi +Lütfen bu klasöre yazma izniniz olup olmadığını kontrol edin. + + + + Temporary file %1 + + + + + Download failed + + + + + InfoFile + + + General + Genel + + + + Size + Boyut + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + Süre + + + + Demuxer + Demuxer + + + + Name + İsim + + + + Artist + Oyuncu + + + + Author + Yazar + + + + Album + Albüm + + + + Genre + Tür + + + + Date + Tarih + + + + Track + Parça + + + + Copyright + Telif Hakkı + + + + Comment + Yorum + + + + Software + Yazılım + + + + Clip info + Parça hakkında bilgi + + + + Video + Video + + + + Resolution + Çözünürlük + + + + Aspect ratio + En/Boy Oranı + + + + Format + Biçim + + + + Bitrate + Bitrate + + + + %1 kbps + Saniyede %1 kb + + + + Frames per second + Kare/saniye + + + + Selected codec + Seçilen kodlayıcı + + + + Initial Audio Stream + İlk Ses Akışı + + + + Rate + Oran + + + + %1 Hz + %1 Hz + + + + Channels + Kanallar + + + + Audio Streams + Ses Akımları + + + + # + Info for translators: this is a abbreviation for number + # + + + + Language + Dil + + + + ID + Info for translators: this is a identification code + ID + + + + empty + boş + + + + Subtitles + Alt yazılar + + + + Type + Tür + + + + Stream title + Yayının başlığı + + + + Stream URL + Yayının URL'si + + + + File + Dosya + + + + InputDVDDirectory + + + Choose a directory + Bir klasör seçin + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Sabit diskteki DVD'yi oynat + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Sabit diskinizde bulunan bir DVD'yi oynatabilirsiniz. VIDEO_TS ve AUDIO_TS klasörlerini içeren klasörü seçmeniz yeterli. + + + + Choose a directory... + Bir klasör seçin... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - MPlayer sürümünüzü girin + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer kullandığınız MPlayer sürümünü tanımlayamadı. + + + + Version reported by MPlayer: + MPlayer tarafından bildirilen sürüm: + + + + Please, &select the correct version: + Lütfen doğru &sürümü seçiniz: + + + + 1.0rc1 or older + 1.0rc1 veya daha eski + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + 1.0rc2'den daha yeni + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - URL'yi girin + + + + &URL: + &URL: + + + + It's a &playlist + Bu bir oyna&tma listesi + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Bu seçeneği işaretlerseniz, URL bir oynatma listesi olarak kabul edilecek: metin olarak açılacak ve içindeki URL'leri oynatmak için kullanılacak. + + + + Languages + + + Afar + Afar + + + + Abkhazian + Abhazca + + + + Afrikaans + Afrikaanca + + + + Amharic + Habeşçe + + + + Arabic + Arapça + + + + Assamese + Assamca + + + + Aymara + Aymaraca + + + + Azerbaijani + Azerice + + + + Bashkir + Başkırca + + + + Byelorussian + Beyaz Rusça + + + + Bulgarian + Bulgarca + + + + Bihari + Biharca + + + + Bislama + Bislama + + + + Bengali + Bengalce + + + + Tibetan + Tibetçe + + + + Breton + Bretonca + + + + Catalan + Katalanca + + + + Corsican + Korsikaca + + + + Czech + Çekçe + + + + Welsh + Galce + + + + Danish + Danca + + + + German + Almanca + + + + Bhutani + Butanca + + + + Greek + Yunanca + + + + English + İngilizce + + + + Esperanto + Esperanto + + + + Spanish + İspanyolca + + + + Estonian + Estonca + + + + Basque + Baskça + + + + Persian + Farsça + + + + Finnish + Fince + + + + Fiji + Fijice + + + + Faroese + Faroece + + + + French + Fransızca + + + + Frisian + Frizce + + + + Irish + İrlandaca + + + + Scots + İskoçça + + + + Galician + Galiçyaca + + + + Guarani + Guaranice + + + + Gujarati + Gujaratice + + + + Hausa + Hausa + + + + Hebrew + İbranice + + + + Hindi + Hintçe + + + + Croatian + Hırvatça + + + + Hungarian + Macarca + + + + Armenian + Ermenice + + + + Interlingua + Interlingua + + + + Indonesian + Endonezce + + + + Interlingue + Interlingue + + + + Inupiak + Inupiak + + + + Icelandic + İzlandaca + + + + Italian + İtalyanca + + + + Inuktitut + Inuktitut + + + + Japanese + Japonca + + + + Javanese + Cavaca + + + + Georgian + Gürcüce + + + + Kazakh + Kazakça + + + + Greenlandic + Grönlandca + + + + Cambodian + Kamboçyaca + + + + Kannada + Kannada + + + + Korean + Korece + + + + Kashmiri + Kaşmirce + + + + Kurdish + Kürtçe + + + + Kirghiz + Kırgızca + + + + Latin + Latince + + + + Lingala + Lingala + + + + Laothian + Laothian + + + + Lithuanian + Litvanyaca + + + + Latvian + Letonca + + + + Malagasy + Malagasy + + + + Maori + Maorice + + + + Macedonian + Makedonca + + + + Malayalam + Malayalam + + + + Mongolian + Moğolca + + + + Moldavian + Moldovaca + + + + Marathi + Marathi + + + + Malay + Malay + + + + Maltese + Maltaca + + + + Burmese + Birmanca + + + + Nauru + Nauru + + + + Nepali + Nepalce + + + + Dutch + Felemenkçe + + + + Norwegian + Norveççe + + + + Occitan + Occitan + + + + Oriya + Oriya + + + + Punjabi + Pencapça + + + + Polish + Lehçe + + + + Pashto + Peştuca + + + + Portuguese + Portegizce + + + + Quechua + Quechua + + + + Kirundi + Kirundi + + + + Romanian + Romence + + + + Russian + Rusça + + + + Kinyarwanda + Kinyarwanda + + + + Sanskrit + Sanskritçe + + + + Sindhi + Sintçe + + + + Sangho + Sangho + + + + Sinhalese + Sinhalese + + + + Slovak + Slovakça + + + + Slovenian + Slovence + + + + Samoan + Samoaca + + + + Shona + Shona + + + + Somali + Somalice + + + + Albanian + Arnavutça + + + + Serbian + Sırpça + + + + Siswati + Siswati + + + + Sesotho + Sesotho + + + + Sundanese + Sundanese + + + + Swedish + İsveççe + + + + Swahili + Savahilice + + + + Tamil + Tamilce + + + + Telugu + Telugu + + + + Tajik + Tacikçe + + + + Thai + Tayca + + + + Tigrinya + Tigrinya + + + + Turkmen + Türkmence + + + + Tagalog + Tagalog + + + + Setswana + Tsvanaca + + + + Tonga + Tongaca + + + + Turkish + Türkçe + + + + Tsonga + Tsonga + + + + Tatar + Tatarca + + + + Twi + Twi + + + + Uighur + Uygurca + + + + Ukrainian + Ukraynaca + + + + Urdu + Urduca + + + + Uzbek + Özbekçe + + + + Vietnamese + Vietnamca + + + + Wolof + Wolof + + + + Xhosa + Xhosa + + + + Yiddish + Yiddiş + + + + Yoruba + Yoruba + + + + Zhuang + Zhuang + + + + Chinese + Çince + + + + Zulu + Zuluca + + + + Portuguese - Brazil + Brezilya Portegizcesi + + + + Portuguese - Portugal + Portekiz Portegizcesi + + + + Simplified-Chinese + Basitleştirilmiş Çince + + + + Traditional Chinese + Geleneksel Çince + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + Batı Avrupa Dilleri + + + + Western European Languages with Euro + Batı Avrupa Dilleri (€ içeren) + + + + Slavic/Central European Languages + Slav/Orta Avrupa Dilleri + + + + Esperanto, Galician, Maltese, Turkish + Esperanto, Galiçyaca, Maltaca, Türkçe + + + + Old Baltic charset + Eski Baltık Alfabesi + + + + Cyrillic + Kiril Alfabesi + + + + Modern Greek + Çağdaş Yunanca + + + + Baltic + Baltık Alfabesi + + + + Celtic + Keltçe + + + + Hebrew charsets + İbranice + + + + Ukrainian, Belarusian + Ukraynaca, Beyaz Rusça + + + + Simplified Chinese charset + Basitleştirilmiş Çin Alfabesi + + + + Traditional Chinese charset + Geleneksel Çin Alfabesi + + + + Japanese charsets + Japon Alfabesi + + + + Korean charset + Kore Alfabesi + + + + Thai charset + Tay Alfabesi + + + + Cyrillic Windows + Kiril Alfabesi Windows + + + + Slavic/Central European Windows + Slav/Orta Avrupa Windows + + + + Arabic Windows + Arapça Windows + + + + Rhaeto-Romance + Rhaeto-Romance + + + + Serbo-Croatian + Sırp-Hırvatça + + + + Volapük + Volapük + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + Kayıt dosyası için bir isim seçin + + + + Confirm overwrite? + Üstüne yazmayı onaylıyor musunuz? + + + + The file already exists. +Do you want to overwrite? + Dosya zaten var. +Üstüne yazmak istiyor musunuz? + + + + Error saving file + Dosyayı kaydederken hata oluştu + + + + The log couldn't be saved + Kayıt bilgisi kaydedilemedi + + + + Logs + Kayıtlar + + + + LogWindowBase + + + Log Window + Kayıt Penceresi + + + + Save + Kaydet + + + + Copy to clipboard + Panoya kopyala + + + + Close + Kapat + + + + &Close + &Kapat + + + + MiniGui + + + Control bar + Denetim çubuğu + + + + MpcGui + + + Control bar + Denetim çubuğu + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + İsim + + + + Length + Süre + + + + &Play + &Oynat + + + + &Edit + &Düzelt + + + + Playlists + Oynatma Listeleri + + + + Choose a file + Bir dosya seçin + + + + Choose a filename + Bir dosya ismi seçin + + + + Confirm overwrite? + Üstüne yazmayı onaylıyor musunuz? + + + + The file %1 already exists. +Do you want to overwrite? + %1 dosyası zaten var. +Üstüne yazmak istiyor musunuz? + + + + All files + Tüm dosyalar + + + + Select one or more files to open + Açmak üzere bir veya daha fazla dosya seçin + + + + Choose a directory + Bir klasör seçin + + + + Edit name + İsmi değiştirin + + + + Type the name that will be displayed in the playlist for this file: + Bu dosyanın oynatma listesinde gösterileceği ismi yazın: + + + + &Load + &Yükle + + + + &Save + &Kaydet + + + + &Next + &Sonraki + + + + Pre&vious + &Önceki + + + + Move &up + &Yukarı taşı + + + + Move &down + &Aşağı taşı + + + + &Repeat + &Tekrarla + + + + S&huffle + &Karışık + + + + Add &current file + &Hâlihazır dosyayı ekle + + + + Add &file(s) + &Dosya(ları) ekle + + + + Add &directory + &Klasör ekle + + + + Remove &selected + &Seçiliyi kaldır + + + + Remove &all + &Hepsini kaldır + + + + Add... + Ekle... + + + + Remove... + Kaldır... + + + + SMPlayer - Playlist + SMPlayer - Oynatma listesi + + + + Playlist modified + Oynatma listesi değiştirildi + + + + There are unsaved changes, do you want to save the playlist? + Kaydedilmemiş değişiklikler var. Oynatma listesini kaydetmek ister misiniz? + + + + Preferences + Seçenekler + + + + PlaylistPreferences + + + Playlist - Preferences + Oynatma listesi - Seçenekler + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Eğer bir klasörü eklediğinizde alt klasörlerdeki dosyaların da özyinelice eklenmesini istiyorsanız bu seçeneği işaretleyin. Aksi halde sadece seçtiğiniz klasördeki dosyalar eklenecek. + + + + &Add files in directories recursively + Bu klasördeki dosy&aları özyinelice ekle + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Eğer SMPlayer'ın eklenecek dosyalar hakkında bilgi edinmesini istiyorsanız işaretleyin. Bu seçenek -bulunuyorsa- dosyanın başlığını ve süresini göstermeye yarar. Aksi halde dosya oynatılmaya başlanmadan bu bilgiler edinilemeyecek. Uyarı: Özellikle çok dosya eklediğinizde bu özellik bilgisayarınızı yavaşlatabilir. + + + + Automatically get &info about files added + Eklenen dosyalar hakkında otomatik olarak bilgi ed&in + + + + &Save copy of playlist on exit + Çıkışta oynatma liste&sinin bir kopyasını kaydet + + + + &Play files from start + Videoyu oynatmaya &baştan başla + + + + PrefAdvanced + + + Advanced + Gelişmiş + + + + Auto + Otomatik + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Bu seçeneği işaretlemek görüntüdeki titremeyi azaltabilir, fakat videonun bozuk görüntülenmesine de yol açabilir. + + + + Log MPlayer output + MPlayer çıktısının kaydını tut + + + + Log SMPlayer output + SMPlayer çıktısının kaydını tut + + + + Filter for SMPlayer logs + SMPlayer kayıtları için süzgeç + + + + &Advanced + &Gelişmiş + + + + icon + simge + + + + &Monitor aspect: + Ekra&n en/boy oranı: + + + + &Run MPlayer in its own window + MPlayer'ı kendi penceresinde çalıştı&r + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Burada mplayer'a fazladan özellikler ekleyebilirsiniz. +Özellikler arasında boşluk bırakmayı unutmayın. +Örnek: -flip -nosound + + + + &Options: + &Seçenekler: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + İlave video süzgeçleri de ekleyebilirsiniz. +Süzgeçleri "," ile ayırın. Boşluk kullanmayın! +Örnek: scale=512:-2,eq2=1 + + + + V&ideo filters: + V&ideo süzgeçleri: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Ve son olarak ses süzgeçleri. Video süzgeçlerinde geçerli olan kurallar burada da geçerli. +Örnek: resample=44100:0:0,volnorm + + + + Audio &filters: + Ses &süzgeçleri: + + + + &Colorkey: + Renk anahtar&ı: + + + + C&hange... + De&ğiştir... + + + + Log &SMPlayer output + &SMPlayer çıktısının kaydını tut + + + + This option is mainly intended for debugging the application. + Bu seçenek esas olarak hata ayıklama amaçlıdır. + + + + &Filter for SMPlayer logs: + SMPlayer kayıtları için s&üzgeç: + + + + Logs + Kayıtlar + + + + Log MPlayer &output + MPlayer çıktısının kaydını t&ut + + + + Options for MP&layer + MP&layer seçenekleri + + + + Autosave MPlayer log + MPlayer kaydını otomatik olarak kaydet + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Bu seçeneği işaretlerseniz, yeni bir dosyanın oynamaya başladığı her seferde MPlayer kaydı belirlenen dosyaya kaydedilecek. Bu seçenek, harici uygulamaların oynatılan dosya hakkında bilgi edinmesini sağlayacaktır. + + + + Autosave MPlayer log filename + MPlayer kaydının dosya ismini otomatik olarak kaydet + + + + Enter here the path and filename that will be used to save the MPlayer log. + MPlayer kaydının tutulacağı dosyanın klasör yolunu ve adını yazın. + + + + A&utosave MPlayer log to file + MPlayer kaydını &otomatik olarak dosyaya kaydet + + + + Pass short filenames (8+3) to MPlayer + Kısa (8+3) dosya adlarını MPlayer'a aktar + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + MPlayer yerel kod sayfası dışından karakterler içeren dosya isimlerini açamaz. Bu seçeneği işaretlerseniz SMPlayer MPlayer'a dosya isimlerinin kısa halini aktararak MPlayer tarafından açılmalarını sağlayacak. + + + + &Pass short filenames (8+3) to MPlayer + Kısa (8+3) dosya adlarını M&Player'a aktar + + + + Monitor aspect + Ekran en-boy oranı + + + + Select the aspect ratio of your monitor. + Ekranınızın en boy oranını seçiniz. + + + + Run MPlayer in its own window + MPlayer'ı kendi penceresinde çalıştır + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Eğer bunu seçerseniz MPlayer video penceresi SMPlayer'ın ana penceresine gömülmek yerine kendi penceresini kullanacak. Bu seçenek seçiliyken, fare ve klavye tuşları için atadığınız kısa yollar SMPlayer seçeneklerinde belirlediğiniz gibi değil MPlayer'a uygun olarak çalışacağı için kısayolların kullanımı beklediğiniz gibi olmayacaktır. + + + + Colorkey + Renk anahtarı + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Eğer diğer pencereler üzerinde oynattığınız videodan parçalar görüyorsanız, bu durumu düzeltmek için renk anahtarını değiştirebilirsiniz. Siyaha yakın renkler seçmeyi deneyin. + + + + Options for MPlayer + MPlayer seçenekleri + + + + Options + Seçenekler + + + + Here you can type options for MPlayer. Write them separated by spaces. + Burada MPlayer için seçenekler hazırlayabilirsiniz. Seçenekleri aralarında boşluk bırakarak yazınız. + + + + Video filters + Video süzgeçleri + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Burada MPlayer'a video süzgeçleri ekleyebilirsiniz. Süzgeçleri virgülle ayırınız. Aralarında boşluk bırakmayınız! + + + + Audio filters + Ses süzgeçleri + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Burada MPlayer'a ses süzgeçleri ekleyebilirsiniz. Süzgeçleri virgülle ayırınız. Aralarında boşluk bırakmayınız! + + + + Repaint the background of the video window + Video penceresinin artalanını yeniden boya + + + + Repaint the backgroun&d of the video window + Vi&deo penceresinin artalanını yeniden boya + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Ağ bağlantılarında IPv4'ü kullan. Otomatik olarak IPv6'ya başvurur. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Ağ bağlantılarında IPv6'yı kullan. Otomatik olarak IPv4'e başvurur. + + + + Network Connection + Ağ bağlantıları + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Lo&gs + &Kayıtlar + + + + Rebuild index if needed + Gerektiğinde dizini yeniden oluştur + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Eğer hazırda bir dizin bulunmuyorsa, gezinmeye izin verecek şekilde dosya dizinini yeniden oluşturur. Bozuk/tamamlanmamış dosya indirmelerinde veya yanlış oluşturulmuş dosyaların izlenmesine yarar. Bu seçenek, dosyaya temel teşkil eden ortam gezinmeye destek veriyorsa çalışır (stdin, pipe, vs ile çalışmaz).<br>. Not: dizinin oluşturulması uzun sürebilir. + + + + Rebuild &index if needed + Gerektiğinde d&izini yeniden oluştur + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Bunu seçerseniz, SMPlayer sadece SMPlayer çıktısı olan hata düzeltme mesajlarını kaydeder (kaydı, <b>Seçenekler -> Kayıtlara bak -> SMPlayer</b>'da görebilirsiniz). Programda bir hata bulmanız durumunda, bu bilgi geliştiriciye hatayı çözmede yardımcı olabilir. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Bunu seçerseniz, SMPlayer sadece MPlayer çıktısı olan hata düzeltme mesajlarını kaydeder (kaydı, <b>Seçenekler -> Kayıtlara bak -> MPlayer</b>'da görebilirsiniz). Bu kayıt programda çıkabilecek sorunların çözülmesi için gerekli önemli bilgileri içerebileceği için seçili tutmanızı tavsiye ediyoruz. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Bu seçenek kaydı tutlacak SMPlayer mesajlarının süzülmesini sağlar. <br>Örnek: <i>^Core::.*</i> yazarsanız sadece <i>Core::</i>'la başlayan satırlar görüntülenir.> + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + Tür + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + Uyarı + + + + Not all files could be associated. Please check your security permissions and retry. + Tüm dosyalar ilişkilendirilemedi. Lütfen güvenlik izinlerinizi kontrol edip tekrar deneyin. + + + + File Types + Dosya Türleri + + + + Select all + Hepsini seç + + + + Check all file types in the list + Listedeki tüm dosya türlerini işaretle + + + + Uncheck all file types in the list + Listeki tüm dosyalardan işaretlemeyi kaldır + + + + List of file types + Dosya türleri listesi + + + + File types + Dosya türleri + + + + Media files handled by SMPlayer: + SMPlayer'la açılan ortam dosyaları: + + + + Select All + Hepsini Seç + + + + Select None + Hiçbirini Seçme + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + SMPlayer tarafından açılmasını istediğinizi dosya türlerini seçiniz. Uygula'ya tıkladığınızda, seçtiğiniz dosyalar SMPlayer'la ilişkilendirilecek. Eğer işareti kaldırırsanız, dosyanın ilişkilendirmesi de eski haline getirilecek. + + + + Select none + Hiçbirini seçme + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + (sp)<b>Not:</b> (Eski haline getirme Windows Vista'da çalışmaz). + + + + PrefDrives + + + Drives + Sürücüler + + + + CD device + CD sürücü + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + CDROM sürücünüzü seçiniz. Bu sürücü VCD ve Müzik CD'lerinin oynatılmasında kullanılacak. + + + + DVD device + DVD sürücü + + + + Choose your DVD device. It will be used to play DVDs. + DVD sürücünüzü seçiniz. Bu sürücü DVD'lerin oynatılmasında kullanılacak. + + + + icon + simge + + + + Select your &CD device: + &CD sürücünüzü seçiniz: + + + + Select your &DVD device: + &DVD sürücünüzü seçiniz: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer otomatik olarak CDROM veya DVD sürücü seçmez. Bu yüzden, CD veya DVD oynatmak istiyorsanız kullanacağınız sürücüyü seçmeniz gerekir (her ikisi için aynı sürücüyü seçilebilir). + + + + PrefGeneral + + + General + Genel + + + + Select the mplayer executable + Çalıştırılabilir mplayer dosyasını seçin + + + + Executables + Çalıştırılabilirler + + + + All files + Tüm dosyalar + + + + Select a directory + Bir klasör seçin + + + + MPlayer executable + Çalıştırılabilir MPlayer dosyası + + + + Screenshots folder + Yakalanan ekran görüntülerinin klasörü + + + + Video output driver + Video çıktısı sürücüsü + + + + Audio output driver + Ses çıktısı sürücüsü + + + + Select the audio output driver. + Ses çıktısı içim sürücü seçin. + + + + Remember settings + Ayarları hatırla + + + + Preferred audio language + Tercih edilen ses dili + + + + Preferred subtitle language + Tercih edilen alt yazı dili + + + + Software video equalizer + Yazılım video dengeleyici + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Eğer video eşitleyici özelliği ekran kartınız veya seçtiğiniz video çıktısı sürücüsü tarafından desteklenmiyorsa bu seçeneği işaretleyin.<br><b>Not:</b> Bu seçenek bazı video çıktısı sürücüleri ile uyumsuzluk gösterebilir. + + + + Postprocessing quality + Ardişlem kalitesi + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Atıl işlemci gücüne bağlı olarak önişlem seviyesini değiştir. Belirlediğiniz sayı en yüksek seviye kabul edilecektir. Genellikle büyük bir sayı seçebilirsiniz. + + + + Start videos in fullscreen + Videoları tam ekran başlat + + + + If this option is checked, all videos will start to play in fullscreen mode. + Bu seçeneği işaretlerseniz, videolar tam ekran olarak açılacak. + + + + Disable screensaver + Ekran koruyucuyu devredışı bırak + + + + Software volume control + Yazılım ses kontrolü + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Eğer ses kartı tabanlı değil yazılım tabanlı karıştırıcı (mixer) kullanıyorsanız bu seçeneği işaretleyin. + + + + &General + &Genel + + + + Paths + Yollar + + + + Media settings + Ortam ayarları + + + + Preferred audio and subtitles + Tercih edilen ses ve alt yazılar + + + + Video + Video + + + + Audio + Ses + + + + AC3/DTS pass-through S/PDIF + AC3/DTS'den S/PDIF'ye düzgeçiş + + + + Change volume + Sesi değiştir + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Bunu seçerseniz, SMPlayer tüm dosyalar için tercih edilen ses düzeyini hatırlayacak ve dosyayı tekrar açtığınızda sesi bu düzeye getirecek. İlk kez açılan dosyalar için varsayılan ses düzeyi kullanılacaktır. + + + + 0 + 0 + + + + &Change volume on every file + &Her dosya için farklı ses düzeyi + + + + Select the &MPlayer executable: + Çalıştırılabilir &MPlayer dosyasını seçin: + + + + &Folder for storing screenshots: + Yakalan ekran görüntülerinin tutulacağı &klasör: + + + + &Audio: + &Ses: + + + + &Remember settings for all files (audio track, subtitles...) + &Tüm dosyalar için ayarları hatırla (ses izi, alt yazı...) + + + + Su&btitles: + &Alt yazılar: + + + + &Quality: + &Kalite: + + + + Start videos in &fullscreen + Videoları tam ekran &başlat + + + + Disable &screensaver + &Ekran koruyucuyu devredışı bırak + + + + &Default volume: + Varsayılan ses &düzeyi: + + + + Use s&oftware volume control + Yazılıma bağlı ses kontr&olü kullan + + + + Ma&x. Amplification: + Azami Ku&vvetlendirme: + + + + &AC3/DTS pass-through S/PDIF + &AC3/DTS'den S/PDIF'ye düzgeçiş + + + + Direct rendering + Doğrudan oluşturma + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Seçilirse doğrudan kaplamayı etkinleştirir. (tüm kodlayıcılar ve video çıktıları tarafından desteklenmez) <br><b>UYARI:</b> OSD/alt yazı bozulmasına sebep olabilir! + + + + Double buffering + 2 x ara belleğe alma + + + + D&irect rendering + &Doğrudan kaplama + + + + Dou&ble buffering + 2 x ara &belleğe alma + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + 2 x ara belleğe alma hafızada aynı anda iki kare tutarak titremeleri engeller ve bir kareyi gösterirken diğerinin kodunu çözer. Devredışı bırakılırsa OSD'yi olumsuz etkileyebilir. + + + + &Enable postprocessing by default + Ardişl&em her zaman uygulansın + + + + Volume &normalization by default + Ses &normalleştirme her zaman uygulansın + + + + Close when finished + Bittiği zaman kapat + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Bunu seçerseniz, şu an oynatılan dosya/oynatma listesi bittiği zaman programın ana penceresi otomatik olarak kapatılacak. + + + + 2 (Stereo) + 2 (Stereo) + + + + 4 (4.0 Surround) + 4 (4.0 Surround) + + + + 6 (5.1 Surround) + 6 (5.1 Surround) + + + + C&hannels by default: + Varsa&yılı kanallar: + + + + &Pause when minimized + Simge durumuna küçültüldüğünde &duraklat + + + + Pause when minimized + Simge durumuna küçültüldüğünde duraklat + + + + Enable postprocessing by default + Ardişlem her zaman uygulansın + + + + Max. Amplification + Azami Kuvvetlendirme + + + + Volume normalization by default + Ses normalleştirme her zaman uygulansın + + + + Maximizes the volume without distorting the sound. + Sesi bozmadan en yüksek seviyeye getirir. + + + + Default volume + Varsayılan ses düzeyi + + + + Sets the initial volume that new files will use. + Yeni açılan dosyalarda kullanılacak ses düzeyini belirler. + + + + Channels by default + Varsayılı kanallar + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Azami kuvvetlendirme seviyesini belirler (varsayılan: 110). Seviyeyi 200'e getirirseniz sesi şu andaki düzeyin 2 katına getirmeniz mümkün olacaktır. 100'ün altındaki değerlerin seçilmesi başlangıçtaki sesin (%100) azami seviyenin üstünde kalmasına sebep olacaktır ve OSD bu durumda seviyeyi düzgün gösteremez. + + + + Uses hardware AC3 passthrough + Uses hardware AC3 passthrough + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + Postprocessing will be used by default on new opened files. + Yeni açılan dosyalarda ardişlem varsayılı olarak uygulanır. + + + + Audio track + Ses izi + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Yeni açılan dosyaların oynatılmasında kullanılacak varsayılı ses izini belirler. Eğer bu ses izi mevcut değilse, bulunan ilk iz kullanılacaktır. <br><b>Not:</b> <i>"tercih edilen ses dili"</i> kullanılacak ses izini seçmede kullanılır. + + + + Subtitle track + Alt yazı izi + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Yeni açılan dosyaların oynatılmasında kullanılacak varsayılı alt yazı izini belirler. Eğer bu ses izi mevcut değilse, bulunan ilk iz kullanılacaktır. <br><b>Not:</b> <i>"tercih edilen alt yazı dili"</i> kullanılacak alt yazı izini seçmede kullanılır. + + + + Or choose a track number: + Veya bir iz numarası seçiniz: + + + + Audi&o: + S&es: + + + + Preferred language: + Tercih edilen dil: + + + + Preferre&d audio and subtitles + Tercih e&dilen ses ve alt yazılar + + + + &Subtitle: + &Alt yazı: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Burada ses akışları için tercih ettiğiniz dili seçebilirsiniz. Birden fazla ses akışı içeren bir ortam bulunduğunda, SMPlayer tercih edilen dildekini kullanmaya çalışacaktır.<br>Bu özellik sadece ses akışlarının dili hakkında bilgi içeren, DVDler, mkv dosyaları gibi ortamlar için geçerlidir.<br>Diller için alışılagelmiş kısaltmaları kullanabilirsiniz. Örnek: <b>es|esp|spa</b> yazdığınızda SMPlayer mümkünse <i>es</i>, <i>esp</i> veya <i>spa</i> içeren ses izlerini kullanacaktır. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + Ses perdesini &değiştirmeden hızlı oynatma + + + + High speed playback without altering pitch + Ses perdesini değiştirmeden hızlı oynatma + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Oynatma hızının ses perdesi aynıyken değiştirilmesini sağlar.En az MPlayer dev-SVN-r24924 sürümünü gerektirir. + + + + Change volume just before playing + Ses düzeyini oynatmaya başlamadan hemen önce değiştir + + + + &Video + V&ideo + + + + Use s&oftware video equalizer + Yazılım tabanlı vide&o dengeleyici kullan + + + + A&udio + S&es + + + + Volume + Ses + + + + None + Hiçbiri + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (normal) + + + + Yadif (double framerate) + Yadif (2 x kare sayısı) + + + + Linear Blend + Doğrusal karıştırma + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + Varsayıla&n görüntü ayrıştırıcı: + + + + Deinterlace by default + Görüntü ayrıştırma varsayılı + + + + Select the deinterlace filter that you want to be used for new videos opened. + Yeni açılan dosyalarda kullanılacak görüntü ayrıştırma süzgecini seçiniz. + + + + Remember time position + İzlerken kalınan yeri hatırla + + + + Remember &time position + İzlerken kalınan yeri ha&tırla + + + + Change volume just before p&laying + Ses düzeyini oynatmaya baş&lamadan hemen önce değiştir + + + + Enable the audio equalizer + Ses dengeleyiciyi etkinleştir + + + + Check this option if you want to use the audio equalizer. + Ses dengeleyici kullanmak istiyorsanız işaretleyiniz. + + + + &Enable the audio equalizer + Ses dengeleyiciyi &etkinleştir + + + + Draw video using slices + Videoyu kesitler halinde oluşturur + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Videonun 16 piksel yüksekliğinde kesitler kullanılması etkin/edilgin. Edilginken tüm görüntü karesi tek seferde oluşturulur. Ön bellek miktarına ve ekran kartına bağlı olarak daha hızlı veya yavaş olabilir. Sadece libmpeg2 ve libavcodec kodlayıcıları kullanıldığında işe yarar. + + + + Dra&w video using slices + &Videoyu kesitler halinde oluşturur + + + + &Close when finished playback + &Oynatma bittiğinde kapat + + + + fast + hızlı + + + + slow + yavaş + + + + fast - ATI cards + hızlı - ATI kartlar + + + + User defined... + Kullanıcı tarafından belirlenen... + + + + Default zoom + Geçerli yakınlaştırma + + + + This option sets the default zoom which will be used for new videos. + Yeni açılan videolar için kullanılacak geçerli yakınlaştırmayı belirler. + + + + Default &zoom: + Geçerli &yakınlaştırma: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Burada SMPlayer'ın kullanacağı çalıştırılabilir MPlayer dosyasını seçmelisiniz.<br>SMPlayer en azından MPlayer 1.0rc1'e gerek duymaktadır (SVN şiddetle tavsiye edilir). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Bu ayar doğru olmazsa SMPlayer hiçbir dosyayı oynatamaz! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Burada yakaladığınız ekran görüntülerinin tutulacağı klasörü belirleyebilirsiniz. Eğer bir klasör seçmezseniz görüntü yakalama özelliği devredışı bırakılacak. + + + + Select the video output driver. %1 provides the best performance. + Video çıktı sürücüsünü seçiniz. %1 en iy başarımı sağlar. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 tavsiye edilir. %2 ve %3 yavaş oldukları için ve başarım üzerinde olumsuz etkileri olabileceğinden kullanmaktan kaçınınız. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + Smplayer çoğu dosya için belirlediğiniz ayarları (seçilen ses izi, ses, süzgeçler...) hatırlayacaktır. Eğer bu özelliği istemiyorsanız işareti kaldırın. + + + + If you check this option, SMPlayer will play all files from the beginning. + Bu seçeneği işaretlerseniz, dosyalar son kaldıkları yerden değil en baştan itibaren oynatılacak. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Seçilirse, ana pencere gizlendiğinde dosya duraklatılır. Pencere eski boyutuna getirildiğinde oynatma devam eder. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Herhangi bir dosya oynatılırken ekran koruyucuyu devredışı bırakmak için bu seçeneği işaretleyin.<br>Oynatma işlemi bittiğinde ekran koruyucu tekrar çalıştırılacak. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Burada ses akışları için tercih ettiğiniz dili seçebilirsiniz. Birden fazla ses akışı içeren bir ortam bulunduğunda, SMPlayer tercih edilen dildekini kullanmaya çalışacaktır.<br>Bu özellik sadece ses akışlarının dili hakkında bilgi içeren, DVDler, mkv dosyaları gibi ortamlar için geçerlidir.<br>Diller için alışılagelmiş kısaltmaları kullanabilirsiniz. Örnek: <b>es|esp|spa</b> yazdığınızda SMPlayer mümkünse <i>es</i>, <i>esp</i> veya <i>spa</i> içeren ses izlerini kullanacaktır. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Burada alt yazılar için tercih ettiğiniz dili seçebilirsiniz. Birden fazla alt yazı içeren bir ortam bulunduğunda, SMPlayer tercih edilen dildekini kullanmaya çalışacaktır.<br>Bu özellik sadece alt yazıların dili hakkında bilgi içeren, DVDler, mkv dosyaları gibi ortamlar için geçerlidir.<br>Diller için alışılagelmiş kısaltmaları kullanabilirsiniz. Örnek: <b>es|esp|spa</b> yazdığınızda SMPlayer mümkünse <i>es</i>, <i>esp</i> veya <i>spa</i> içeren alt yazıları kullanacaktır. + + + + Ou&tput driver: + &Çıktı sürücüsü: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + Klavye ve fare + + + + None + Hiçbiri + + + + &Keyboard + &Klavye + + + + icon + simge + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Burada, değiştirmek istediğiniz kısayola çift tıklayarak veya üzerine gelip yazmaya başlayarak, tüm kısayolları değiştirebilirsiniz. Ayrıca, hazırladığınız listeyi kaydedip insanlarla paylaşabilir veya başka bir bilgisayarda kullanabilirsiniz. + + + + &Mouse + &Fare + + + + Button functions: + Düğme özellikleri: + + + + Media seeking + Gezinme + + + + Volume control + Ses kontrolü + + + + Zoom video + Videoyu yakınlaştır + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Burada tüm kısayolları değiştirebilirsiniz. Değiştirmek istediğiniz kısayolun kutucuğuna çift tıklayın veya kutucuktayken enter'a basın. İsterseniz kendi hazırladığınız listeyi kaydedip arkadaşlarınızla paylaşabilir veya başka bir bilgisayarda kullanabilirsiniz. + + + + &Left click + So&l tıklama + + + + &Double click + &Çift tıklama + + + + &Wheel function: + Teker ö&zelliği: + + + + Shortcut editor + Kısayol düzenleyici + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Bu tablo neredeyse tüm işlemlerin kısayolları değiştirebilmenize yarar. Değiştirmek istediğiniz kısayolun kutucuğuna çift tıklayın veya kutucuktayken enter'a basın; ya da <b>Kısayolu değiştir</b> düğmesine basınız. Kısayolları değiştirmek için iki yol var: eğer <b>Yakala<b> düğmesi aktifse, klavyede, atamak istediğiniz kısayol tuşlarına basmanız yeterli. Eğer düğme aktif değilse kısayolu kendiniz yazmalısınız. + + + + Left click + Sol tıklama + + + + Select the action for left click on the mouse. + Solla tıklandığında ne yapılacağını seçiniz. + + + + Double click + Çift tıklama + + + + Select the action for double click on the mouse. + Çift tıklandığında ne yapılacağını seçiniz. + + + + Wheel function + Teker özelliği + + + + Select the action for the mouse wheel. + Fare tekerinin ne işe yarayacağını seçiniz. + + + + Play + Oynat + + + + Pause + Duraklat + + + + Stop + Durdur + + + + Fullscreen + Tam ekran + + + + Compact + Temiz ekran + + + + Screenshot + Ekran görüntüsünü yakala + + + + On top + Her zaman üstte + + + + Mute + Sessiz + + + + Frame counter + Kare sayacı + + + + Reset zoom + Yakınlaştırmayı sıfırla + + + + Exit fullscreen + Tam ekrandan çık + + + + Double size + Boyutu ikiye katla + + + + Play / Pause + Oynat / Duraklat + + + + Pause / Frame step + Duraklat / Bir kare ilerle + + + + Playlist + Oynatma listesi + + + + Preferences + Tercihler + + + + No function + Özellik atama + + + + Change speed + Hızı değiştir + + + + Normal speed + Normal hız + + + + Keyboard + Klavye + + + + Mouse + Fare + + + + Middle click + Orta tıklama + + + + Select the action for middle click on the mouse. + Ortayla tıklandığında ne olacağını seçiniz. + + + + M&iddle click + &Orta tıklama + + + + X Button &1 + X Düğmesi &1 + + + + X Button &2 + X Düğmesi &2 + + + + Go backward (short) + Geriye git (kısa) + + + + Go backward (medium) + Geriye git (orta) + + + + Go backward (long) + Geriye git (uzun) + + + + Go forward (short) + İleriye git (kısa) + + + + Go forward (medium) + İleriye git (orta) + + + + Go forward (long) + İleriye git (uzun) + + + + OSD - Next level + OSD - Sonraki seviye + + + + Show context menu + İçerik menüsünü göster + + + + &Right click + Sağ &tıklama + + + + Increase volume + Sesi yükselt + + + + Decrease volume + Sesi düşür + + + + X Button 1 + X Düğmesi 1 + + + + Select the action for the X button 1. + X Düğmesi 1'in ne yapacağın seçiniz. + + + + X Button 2 + X Düğmesi 2 + + + + Select the action for the X button 2. + X Düğmesi 2'nin ne yapacağını seçiniz. + + + + Show video equalizer + Video dengeleyiciyi göster + + + + Show audio equalizer + Ses dengeleyiciyi göster + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + Arayüz + + + + <Autodetect> + <Otomatik> + + + + Default + Geçerli + + + + Language + Dil + + + + &Interface + Aray&üz + + + + Seeking + Gezinme + + + + Recent files + Son açılanlar + + + + Never + Asla + + + + Whenever it's needed + Gerektiğinde + + + + Only after loading a new video + Sadece yeni bir video yüklendiğinde + + + + Here you can change the language of the application. + Burada programın dilini değiştirebilirsiniz. + + + + &Short jump + Kı&sa atlama + + + + &Medium jump + Orta atla&ma + + + + &Long jump + Uzun at&lama + + + + Mouse &wheel jump + Fare &tekeriyle atlama + + + + &Use only one running instance of SMPlayer + Bir tek SMPlayer oluşumu k&ullanılsın + + + + Ma&x. items + &En fazla + + + + St&yle: + St&il: + + + + Ico&n set: + Si&mge seti: + + + + L&anguage: + &Dil: + + + + Main window + Ana pencere + + + + Auto&resize: + Otomatik boyutlandı&rma: + + + + R&emember position and size + Konumu ve boyutu hatırl&a + + + + Default font: + Varsayılan yazıtipi: + + + + &Change... + &Değiştir... + + + + &Behaviour of time slider: + &Gezinme çubuğu nasıl çalışsın?: + + + + Seek to position while dragging + Seek to position while dragging + + + + Seek to position when released + Seek to position when released + + + + TextLabel + YazıEtiketi + + + + &Seeking + &Gezinme + + + + Ins&tances + &Oluşumlar + + + + Autoresize + Otomatik boyutlandırma + + + + The main window can be resized automatically. Select the option you prefer. + Ana pencere otomatik olarak yeniden boyutlandırılır. + + + + Remember position and size + Konumu ve boyutu hatırla + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Seçilirse, ana pencerenin boyutu ve konumu kaydedilir ve SMPlayer tekrar çalıştırıldığında ana pencere bu bilgiye göre düzenlenir. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + <b>Aç->Son açılanlar</b> alt menüsünde gösterilecek en fazla dosya sayısını seçiniz. Eğer 0'ı seçerseniz menü gösterilmez. + + + + Icon set + Simge seti + + + + Select the icon set you prefer for the application. + Uygulama için tercih ettiğiniz simge setini seçiniz. + + + + Style + Stil + + + + Select the style you prefer for the application. + Uygulama için tercih ettiğiniz stili seçiniz. + + + + Default font + Varsayılan yazı tipi + + + + You can change here the application's font. + Burada uygulamanın yazı tipini değiştirebilirsiniz. + + + + Short jump + Kısa atlama + + + + Select the time that should be go forward or backward when you choose the %1 action. + %1'yı seçtiğinizde atlanacak süreyi seçiniz. + + + + short jump + kısa atlama + + + + Medium jump + Orta atlama + + + + medium jump + orta atlama + + + + Long jump + Uzun atlama + + + + long jump + uzun atlama + + + + Mouse wheel jump + Fare tekeriyle atlama + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Fare tekerini hareket ettirdiğinizde atlanacak süreyi seçiniz. + + + + Behaviour of time slider + Gezinme çubuğunun çalışma yöntemi + + + + Select what to do when dragging the time slider. + Gezinme çubuğunu sürüklediğinizde ne olacağını seçiniz. + + + + Instances + Oluşumlar + + + + Use only one running instance of SMPlayer + Bir tek SMPlayer oluşumu kullanılsın + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Eğer yeni bir dosya açıldığında, yeni bir SMPlayer açılmasını istemiyorsanız bu seçeniği işaretleyiniz. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer diğer oluşumlardan komut almak için bir bağlantı noktasını dinlemelidir. Varsayılı olan bağlantı noktasını başka bir uygulama kullanıyorsa değiştirebilirsiniz. + + + + Default GUI + Varsayılan GUI + + + + Mini GUI + Mini GUI + + + + GUI + GUI + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Uygulama için tercih ettiğiniz GUI'yi seçiniz. Şu anda 2 seçenek mevcut: Varsayılan ve Mini.<br><b>Varsayılan GUI</b> araç çubuğu ve kontrol çubuğunu içerir.<b>Mini GUI</b> daha sade bir arayüz sağlar.<br><b>Not:</b> bu seçenek SMPlayer'ı tekrar çalıştırdığınızda etkinleşecektir. + + + + &GUI + &GUI + + + + Automatic port + Otomatik bağlantı noktası + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + Manual port + Kullanıcı tarafından belirlenen bağlantı noktası + + + + Port to listen + Dinlenecek bağlantı noktası + + + + &Automatic + &Otomatik + + + + &Manual + &Kullanıcı tarafından + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + Başarım + + + + Priority + Öncelik + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Windows'da öntanımlı önceliklere göre Mplayer için geçerli olacak işlem önceliğini seçin. +<br><b>Uyarı:<b> Gerçek zamanlı öncelik sisteminizin kitlenmesine yol açabilir. + + + + Cache + Ön bellek + + + + Allow frame drop + Kare es geçmeye izin ver + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Yavaş sistemlerde ses/görüntü uyumunu sağlamak için bazı kareleri atla. + + + + Allow hard frame drop + Yoğun kare es geçme + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Daha yoğun kare es geçme (kod çözmeyi bozar). Görüntünün bozulmasına yol açar! + + + + Audio/video auto synchronization + Otomatik ses/görüntü uyumu + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Ses gecikmesi hesaplamalarına dayanarak, ses/görüntü uyumunu aşama aşama gerçekleştir. + + + + &Performance + &Başarım + + + + Select the priority for the MPlayer process. + Mplayer için geçerli olacak önceliği seçin. + + + + realtime + gerçek zamanlı + + + + high + yüksek + + + + abovenormal + normal üstü + + + + normal + normal + + + + belownormal + normal altı + + + + idle + âtıl + + + + KB + KB + + + + Setting a cache may improve performance on slow media + Ön belleği kullanmak başarımı arttırabilir + + + + Synchronization + Uyum + + + + Fast audio track switching + Ses izini hızlı değiştirebilme + + + + Fast seek to chapters in dvds + DVD bölümlerini hızlı gezinebilme + + + + Priorit&y: + &Öncelik: + + + + &Allow frame drop + K&are es geçmeye izin ver + + + + Allow &hard frame drop (can lead to image distortion) + Yoğun kare es &geçmeye izin ver (görüntünün bozulmasına yol açabilir) + + + + Audio/&video auto synchronization + Otomatik ses/&video uyumu sağlama + + + + Fact&or: + Etk&en: + + + + &Fast audio track switching + &Ses izini hızlı değiştirebilme + + + + Fast &seek to chapters in dvds + &DVD bölümlerini hızlı gezinebilme + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Seçilirse bölümleri gezinebilmek için en hızlı yöntem denenecek. Bazı disklerde çalışmayabilir. + + + + Skip loop filter + Döngü süzgecini atla + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Olası değerler: <br> <b>Evet</b>: Ses izlerini değiştirmek için en hızlı yöntemi dener (bazı biçimlerle çalışmayabilir). <br> <b>Hayır</b>: ses izini her değiştirdiğinizde MPlayer yeniden başlatılır. <br> <b>Otomatik</b>: MPlayer sürümüne göre SMPlayer ne yapılacağına karar verir. + + + + Cache for files + Dosyalar için ön bellek + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Dosyaları ön belleğe almak için ne kadar bellek (kByte olarak) kullanılacağını belirler. + + + + Cache for streams + Akışlar için ön bellek + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + URL'leri ön belleğe almak için ne kadar bellek (kByte olarak) kullanılacağını belirler. + + + + Cache for DVDs + DVD'ler için ön bellek + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + DVD'leri ön belleğe almak için ne kadar bellek (kByte olarak) kullanılacağını belirler.<br><b>Uyarı:</b> DVD'ler için ön bellek kullanıldığı durumda bölümler arasında ve bölüm içinde gezinme düzgün çalışmayabilir. + + + + &Cache + &Ön bellek + + + + Cache for &DVDs: + &DVD'ler için ön bellek: + + + + Cache for &local files: + Bilgisayardaki dosya&lar için ön bellek: + + + + Cache for &streams: + &Akışlar için ön bellek: + + + + Enabled + Etkin + + + + Skip (always) + Atla (her zaman) + + + + Skip only on HD videos + Sadece HD videoları atla + + + + Loop &filter + Döngü &süzgeci + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + H.264 kod çözümü esnasında döngü süzgecinin es geçilmesine izin verir. HDTV'lerde görüntü kaybı olmadan büyük hızlanma sağlar. + + + + Possible values: + Olası değerler: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Etkin</b>: döngü süzgeci es geçilmez + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Atla (her zaman)</b>: döngü süzgeci videonun çözünürlüğü ne olursa olsun es geçilir + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Sadece HD videoları atla</b>: döngü süzgeci sadece %1 veya daha fazla çözünürlükteki videolar için es geçilir. + + + + Cache for audio CDs + Müzik CD'leri için ön bellek + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Müzik CD'lerini ön belleğe almak için ne kadar bellek (kByte olarak) kullanılacağını belirler. + + + + Cache for &audio CDs: + &Müzik CD'leri için ön bellek: + + + + Cache for VCDs + VCD'ler için ön bellek + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + VCD'leri ön belleğe almak için ne kadar bellek (kByte olarak) kullanılacağını belirler. + + + + Cache for &VCDs: + &VCD'ler için ön bellek: + + + + Threads for decoding + Kod çözme dizileri + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Sadece MPEG-1/2 ve H.264 için kod çözmede kullanılacak dizi sayısını belirler + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Kod çözme dizileri (Sadece MPEG-1/2 ve H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + Oynatma listesi + + + + Automatically add files to playlist + Dosyaları otomatik olarak oynatma listesine ekle + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Bunu seçerseniz, her dosya açışınızda SMPlayer önce oynatma listesini temizleyecek ve sonra açtığınız dosyayı listeye ekleyecek. Eğer bir DVD, CD veya VCD açarsanız, diskteki tüm başlıklar oynatma listesine eklenecek. + + + + Add consecutive files + Peşpeşe gelen dosyaları ekle + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Bunu seçerseniz, SMPlayer peşpeşe gelen dosyalar ( video_1.avi, video_2.avi...) varsa, bunları otomatik olarak oynatma listesine ekleyecek. + + + + &Playlist + &Oynatma listesi + + + + &Automatically add files to playlist + Dosyaları &otomatik olarak oynatma listesine ekle + + + + Add &consecutive files + Peşpeşe gelen dosyaları &ekle + + + + PrefSubtitles + + + Subtitles + Alt yazılar + + + + Choose a ttf file + Bir ttf dosyası seçin + + + + Truetype Fonts + Truetype Fontlar + + + + Subtitle position + Alt yazının konumu + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Bu seçenek alt yazıların ekranda bulunacağı yeri belirlemenizi sağlar. En alt için <i>100</i> , en üst için <i>0</i>'ı seçin. + + + + &Subtitles + Alt &yazı + + + + Autoload + Otomatik yükle + + + + Select first available subtitle + Seçeneğe uyan ilk yazıyı kendiliğinden seç + + + + Same name as movie + Filmle aynı isimde + + + + All subs containing movie name + Filmin ismini içeren tüm alt yazılar + + + + All subs in directory + Klasördeki tüm alt yazılar + + + + Position + Konum + + + + 0 + 0 + + + + Top + En üst + + + + Bottom + En alt + + + + Include subtitles on screenshots + Alt yazılar yakalanan ekranlarda gözüksün + + + + Font + Font + + + + Select the font which will be used for subtitles (and OSD): + Alt yazılar (ve OSD) için kullanılacak fontu seçin: + + + + Size + Boyut + + + + No autoscale + Otomatik orantılama yok + + + + Proportional to movie height + Filmin yüksekliğiyle orantılı + + + + Proportional to movie width + Filmin genişliğiyle orantılı + + + + Proportional to movie diagonal + Filmin köşegen uzunluğuyla orantılı + + + + Au&toload subtitles files (*.srt, *.sub...): + Alt yazı dosyalarını otomatik olarak y&ükle (*.srt, *.sub...): + + + + S&elect first available subtitle + S&eçeneğe uyan ilk yazıyı kendiliğinden seç + + + + &Default subtitle encoding: + Varsayılan alt yazı ko&dlaması: + + + + Default &position of the subtitles on screen + Alt yazılar için varsayılan &konum + + + + &Include subtitles on screenshots + Alt yazılar &yakalanan ekranlarda gözüksün + + + + &TTF font: + &TTF yazıtipi: + + + + S&ystem font: + Sistem &yazıtipi: + + + + A&utoscale: + &Otomatik orantılama: + + + + Default subtitle encoding + Varsayılan alt yazı kodlaması + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Bunu seçerseniz alt yazı yakaladığınız ekran görüntülerinde gözükecektir. Not: sorun çıkartabilir. + + + + TTF font + TTF yazıtipi + + + + System font + Sistem yazıtipi + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Burada alt yazılar ve OSD için kullanılacak sistem yazı tipini seçebilirsiniz. <b>Not:</b> fontconfig desteği içeren bir MPlayer gerektirir. + + + + Autoscale + Otomatik orantılama + + + + Text color + Yazı rengi + + + + Select the color for the text of the subtitles. + Alt yazılar için renk seçiniz. + + + + Border color + Kenar rengi + + + + Select the color for the border of the subtitles. + Alt yazı kenarlarının rengini seçiniz. + + + + Select the subtitle autoload method. + Alt yazıları otomatik yükleme yöntemini seçiniz. + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Eğer bir veya daha fazla alt yazı izi mevcutsa, içlerinden biri (genellikle birincisi) otomatik olarak seçilecektir. Eğer izlerden biri kullanıcının tercih ettiği dille uyuşuyorsa o iz seçilecektir. + + + + Select the subtitle autoscaling method. + Alt yazıları orantılamak için kullanılacak yöntemi seçiniz. + + + + Select the encoding which will be used for subtitle files by default. + Alt yazılar için kullanılacak geçerli kodlamayı seçiniz. + + + + Try to autodetect for this language + Bu dil için otomatik olarak bulmaya çalış + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + Bu seçenek etkinken altyazıların kodlaması seçilen dile uygun olarak yapılmaya çalışılacaktır. Eğer başarısız olunursa, varsayılı kodlama kullanılacaktır. Bu seçenek, ENCA desteğiyle derlenmiş bir MPlayer gerektirir. + + + + Subtitle language + Alt yazı dili + + + + Select the language for which you want the encoding to be guessed automatically. + Kodlamanın hangi dil için otomatik olarak tahmin edileceğini seçiniz. + + + + Encoding + Kodlama + + + + Try to a&utodetect for this language: + Bu dil için otomatik olarak b&ulmaya çalış: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Burada alt yazılar için kullanılacak ttf yazıtipini seçebilirsiniz. Genellikle %1'de birçok ttf yazıtipi bulabilirsiniz + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + En alt + + + + Middle + vertical alignment + + + + + Top + vertical alignment + En üst + + + + Outline + border style + + + + + Opaque box + border style + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Outline + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + Shadow + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Yardım + + + + OK + Tamam + + + + Cancel + İptal + + + + Apply + Uygula + + + + Help + Yardım + + + + SMPlayer - Preferences + SMPlayer - Özellikler + + + + QObject + + + will show this message and then will exit. + bu mesajı gösterecek ve çıkacak. + + + + the main window will be closed when the file/playlist finishes. + ana pencere oynatılan dosya/oynatma listesi bittiğinde kapatılacak. + + + + This is SMPlayer v. %1 running on %2 + %2'de çalışan SMPlayer'ın v. %1. sürümü + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + çalışan bir diğer oluşumla bağlantı kurup, oluşumu belirlenen eyleme göndermeye çalışırı. Örnek: -send-action pause Eğer varsa geri kalan seçenekler yok sayılır ve uygulama kapanır. Başarılı olursa 0 başarısız olursa -1. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + eylem_listesi eylemlerin boşlukla ayrıldığı bir listedir. Eylemler bir dosya çalıştırıldığında sizin belirlediğiniz sırayla uygulanmaya başlanır. Kontrol edilebilir eylemler için "true" ve "false"'u parametre olarak kullanabilirsiniz. Örnek: -actions "fullscreen compact true". Birden fazla eylem aktarıyorsanız tırnak işaretleri gerekmektedir. + + + + media + ortam + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + eğer başka bir olulum çalışıyorsa, dosya oluşumun oynatma listesine eklenecektir. Yoksa, bu seçenek yok sayılacak ve dosyalar yeni bir oluşumda açılacaktır. + + + + the main window won't be closed when the file/playlist finishes. + oynatılan dosya/oynatma listesi bittiğinde ana pencere kapatılmayacaktır. + + + + the video will be played in fullscreen mode. + video tam ekran oynatılacaktır. + + + + the video will be played in window mode. + video pencere içinde oynatılacaktır. + + + + Enqueue in SMPlayer + SMPlayer'da kuyruğa ekle + + + + opens the mini gui instead of the default one. + varsayılan GUI yerine mini GUI'yi açar. + + + + Restores the old associations and cleans up the registry. + Eski ilişkilendirmeleri geri getirir ve kayıt defterini temizler. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'ortam' SMPlayer açabileceği herhangi bir dosyadır. Bu bilgisayardaki bir dosya, bir DVD (dvd://1), bir internet akışı (mms://....) veya m3u veya pls biçeminde, bilgisayardaki bir oynatma listesi olabilir. eğer -oynatma listesi seçeneği kullanılırsa, SMPlayer -oynatma listesi seçeneğini MPlayer'a aktaracaktır ve işlem SMPlayer yerine MPlayer tarafından yürütülür. + + + + Usage: + Kullanım: + + + + directory + klasör + + + + action_name + eylem_adı + + + + action_list + eylem_listesi + + + + opens the default gui. + varsayılan GUI'yi açar. + + + + subtitle_file + altyazı_dosyası + + + + specifies the subtitle file to be loaded for the first video. + birinci video için yüklenecek alt yazıyı belirler. + + + + %1 second(s) + + %1 saniye + + + + + + %1 minute(s) + + %1 dakika + + + + + + %1 and %2 + %1 ve %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + ZIP/UNZIP API hatası %1 + + + + SeekWidget + + + icon + simge + + + + label + etiket + + + + ShortcutGetter + + + Modify shortcut + Değiştir + + + + Clear + Temizle + + + + Press the key combination you want to assign + Atamak istediğiniz tuş bileşimine basınız + + + + Capture + Yakala + + + + Capture keystrokes + Basılan tuşları yakala + + + + SubChooserDialog + + + Subtitle selection + Alt yazı seçimi + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Bu arşiv birden fazla alt yazı dosyası içeriyor. Lütfen içlerinden kullanmak istediğinizi seçiniz. + + + + Select All + Hepsini Seç + + + + Select None + Hiçbirini seçme + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Gezin + + + + &Jump to: + &Atla: + + + + TristateCombo + + + Auto + Otomatik + + + + Yes + Evet + + + + No + Hayır + + + + VideoEqualizer + + + Contrast + Zıtlık + + + + Brightness + Parlaklık + + + + Hue + Renk tonu + + + + Saturation + Doygunluk + + + + Gamma + Gama + + + + &Reset + &Sıfırla + + + + &Set as default values + &Varsayılan yap + + + + Use the current values as default values for new videos. + Bu değerleri tüm yeni videolar için kullan. + + + + Set all controls to zero. + Tüm kontrolleri sıfırla. + + + + Video Equalizer + Video Dengeleyici + + + + Information + Bilgi + + + + The current values have been stored to be used as default. + Hali hazırdaki değerler varsayılan değerler olarak kaydedildi. + + + + VideoPreview + + + Video preview + + + + + Cancel + İptal + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + Dosyayı kaydederken hata oluştu + + + + The file couldn't be saved + Dosya kaydedilemedi + + + + Error + Hata + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + Saniyede %1 kb + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + Geçerli + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + Ses + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_uk_UA.ts b/plugins/smplayer_plugin/translations/smplayer_uk_UA.ts new file mode 100644 index 000000000..6ab771db4 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_uk_UA.ts @@ -0,0 +1,7386 @@ + + + + + About + + + Version: %1 + Збірка: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + Це вільне програмне забезпечення; Ви можете поширювати його і/чи модифікувати, керуючись 2 чи (на Ваш розсуд) пізнішою версією GNU General Public License, виданою Free Software Foundation. + + + + The following people have contributed with translations: + Ці люди внесли вклад в переклади: + + + + German + Німецька + + + + Slovak + Словацька + + + + Italian + Італійська + + + + French + Французька + + + + %1, %2 and %3 + %1, %2 та %3 + + + + Simplified-Chinese + Спрощена китайська + + + + Russian + Російська + + + + %1 and %2 + %1 та %2 + + + + Hungarian + Угорська + + + + Polish + Польська + + + + Japanese + Японська + + + + Dutch + Голландська + + + + Ukrainian + Українська + + + + Portuguese - Brazil + Португальська (Бразилія) + + + + Georgian + Грузинська + + + + Czech + Чеська + + + + Bulgarian + Болгарська + + + + Turkish + Турецька + + + + Swedish + Шведська + + + + Serbian + Сербська + + + + Traditional Chinese + Традиційна Китайська + + + + Romanian + Румунська + + + + Portuguese - Portugal + Португальська (Португалія) + + + + Greek + Грецька + + + + Finnish + Фінська + + + + <b>%1</b>: %2 + <b>%1</b>: %2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + Про SMPlayer + + + + &Info + &Інфо + + + + icon + піктограма + + + + &Contributions + &Сприяння + + + + &Translators + &Перекладачі + + + + &License + &Ліцензія + + + + Visit our web for updates: + Завітайте до нас за оновленнями: + + + + Get help in our forum: + Отримайте допомогу на нашому форумі: + + + + You can support SMPlayer by making a donation. + Ви можете підтримати SMPlayer внесками. + + + + More info + Більше інформації + + + + Korean + Корейська + + + + Macedonian + Македонська + + + + Basque + Баскська + + + + Using MPlayer %1 + Використовується MPlayer %1 + + + + Catalan + Каталонська + + + + Portable Edition + Портативна редакція + + + + Using Qt %1 (compiled with Qt %2) + Використовується Qt %1 (зібрано з Qt %2) + + + + Slovenian + Словенська + + + + Arabic + Арабська + + + + Kurdish + Курдська + + + + Galician + Галисійська + + + + The following people have contributed with patches (see the changelog for details): + Наступні люди внесли вклад латками (дивіться changelog для подробиць): + + + + If there's any omission, please report. + Якщо є якісь заперечення, будь ласка, звітуйте. + + + + SMPlayer logo by %1 + Логотип SMPlayer: %1 + + + + %1, %2, %3 and %4 + %1, %2, %3 та %4 + + + + %1, %2, %3, %4 and %5 + %1, %2, %3, %4 та %5 + + + + ActionsEditor + + + Name + Назва + + + + Description + Опис + + + + Shortcut + Комбінація клавіш + + + + &Save + &Зберегти + + + + &Load + За&вантажити + + + + Key files + Файли клавіш + + + + Choose a filename + Виберіть назву файлу + + + + Confirm overwrite? + Перезаписати? + + + + The file %1 already exists. +Do you want to overwrite? + Файл %1 вже існує. +Перезаписати? + + + + Choose a file + Виберіть файл + + + + Error + Помилка + + + + The file couldn't be saved + Файл не може бути збережений + + + + The file couldn't be loaded + Файл не може бути завантажений + + + + &Change shortcut... + &Змінити комбінацію клавіш... + + + + AudioEqualizer + + + Audio Equalizer + Аудіоеквалайзер + + + + 31.25 Hz + 31.25 Гц + + + + 62.50 Hz + 62.50 Гц + + + + 125.0 Hz + 125.0 Гц + + + + 250.0 Hz + 250.0 Гц + + + + 500.0 Hz + 500.0 Гц + + + + 1.000 kHz + 1.000 кГц + + + + 2.000 kHz + 2.000 кГц + + + + 4.000 kHz + 4.000 кГц + + + + 8.000 kHz + 8.000 кГц + + + + 16.00 kHz + 16.00 кГц + + + + &Apply + &Застосувати + + + + &Reset + &Скинути + + + + &Set as default values + &Встановити значення за замовчуванням + + + + Use the current values as default values for new videos. + Використовувати поточні значення як за замовчуванням для нових кліпів. + + + + Set all controls to zero. + Скинути все на нуль. + + + + Information + Інформація + + + + The current values have been stored to be used as default. + Поточні значення збережені, щоб використовуватись за замовчуванням. + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - звіти mplayer + + + + SMPlayer - smplayer log + SMPlayer - звіти smplayer + + + + &Open + &Відкрити + + + + &Play + Від&творити + + + + &Video + &Зображення + + + + &Audio + Зв&ук + + + + &Subtitles + Су&бтитри + + + + &Browse + Ог&ляд + + + + Op&tions + &Налаштування + + + + &Help + До&відка + + + + &File... + &Файл... + + + + D&irectory... + &Тека... + + + + &Playlist... + &Перелік відтворення... + + + + &DVD from drive + &DVD з диску + + + + D&VD from folder... + D&VD з теки... + + + + &URL... + &URL-адреса... + + + + &Clear + &Очистити + + + + &Recent files + Ос&танні файли + + + + P&lay + Від&творення + + + + &Pause + &Призупинити + + + + &Stop + &Зупинити + + + + &Frame step + &Крок кадра + + + + &Normal speed + &Звичайна швидкість + + + + &Halve speed + &Половина швидкості + + + + &Double speed + &Подвійна швидкість + + + + Speed &-10% + Швидкість &-10% + + + + Speed &+10% + Швидкість &+10% + + + + Sp&eed + Шв&идкість + + + + &Repeat + &Повторити + + + + &Fullscreen + Н&а весь екран + + + + &Compact mode + &Стислий режим + + + + Si&ze + Ро&змір + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &до 16:9 + + + + &Aspect ratio + &Співвідношення сторін + + + + &None + &Нічого + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Лінійне &змішування + + + + &Deinterlace + &Деінтерлейсинг + + + + &Postprocessing + &Післяобробка + + + + &Autodetect phase + &Автовизначення фази + + + + &Deblock + &Гаусове розмиття (Deblock) + + + + De&ring + Видалення к&раєвих спотворень (Dering) + + + + Add n&oise + Додати ш&ум + + + + F&ilters + Ф&ільтри + + + + &Equalizer + &Еквалайзер + + + + &Screenshot + Знімок &екрану + + + + S&tay on top + З&алишатись зверху + + + + &Extrastereo + &Розширене стерео + + + + &Karaoke + &Караоке + + + + &Filters + &Фільтри + + + + &Stereo + &Стерео + + + + &4.0 Surround + &4.0 оточення + + + + &5.1 Surround + &5.1 оточення + + + + &Channels + &Канали + + + + &Left channel + &Лівий канал + + + + &Right channel + &Правий канал + + + + &Stereo mode + &Стерео режим + + + + &Mute + &Вимкнути звук + + + + Volume &- + Гучність &- + + + + Volume &+ + Гучність &+ + + + + &Delay - + &Затримка - + + + + D&elay + + З&атримка + + + + + &Select + &Вибрати + + + + &Load... + &Завантажити... + + + + Delay &- + Затримка &- + + + + Delay &+ + Затримка &+ + + + + &Up + В&гору + + + + &Down + В&низ + + + + &Title + &Заголовок + + + + &Chapter + &Розділ + + + + &Angle + &Ракурс + + + + &Playlist + &Перелік відтворення + + + + &Show frame counter + &Показати лічильник кадрів + + + + &Disabled + &Вимкнено + + + + &Seek bar + &Панель пошуку + + + + &Time + &Час + + + + Time + T&otal time + Час + З&агальний час + + + + &OSD + Екранна &індикація + + + + &View logs + &Дивитись звіти + + + + P&references + &Налаштування + + + + About &Qt + Про &Qt + + + + About &SMPlayer + Про &SMPlayer + + + + <empty> + <нічого> + + + + Video + Зображення + + + + Audio + Звук + + + + Playlists + Переліки відтворення + + + + All files + Всі файли + + + + Choose a file + Вибрати файл + + + + SMPlayer - Information + SMPlayer - Інформація + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + Приводи CD/DVD ще не налаштовані. +Ви зможете зробити це у діалозі налаштувань цих пристроїв. + + + + Choose a directory + Вибрати теку + + + + Subtitles + Субтитри + + + + About Qt + Про Qt + + + + Playing %1 + Відтворюється %1 + + + + Pause + Призупинений + + + + Stop + Зупинений + + + + Play / Pause + Відтворити / Призупинити + + + + Pause / Frame step + Призупинка / Крок кадра + + + + U&nload + В&ивантажено + + + + V&CD + V&CD + + + + C&lose + З&акрити + + + + View &info and properties... + Дивитсь &інфо та властивості... + + + + Zoom &- + Масштаб &- + + + + Zoom &+ + Масштаб &+ + + + + &Reset + &Скинути + + + + Move &left + Змістити &ліворуч + + + + Move &right + Змістити &праворуч + + + + Move &up + Змістити &вгору + + + + Move &down + Змістити &вниз + + + + &Pan && scan + &Панорамування + + + + &Previous line in subtitles + &Попередний рядок в субтитрах + + + + N&ext line in subtitles + Н&аступний рядок в субтитрах + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + Зменшення гучності (2) + + + + Inc volume (2) + Збільшення гучності (2) + + + + Exit fullscreen + Вийти з повноекранного режиму + + + + OSD - Next level + Екранна індікація - наступний рівень + + + + Dec contrast + Зменшення контрасту + + + + Inc contrast + Збільшення контрасту + + + + Dec brightness + Зменшення яскравості + + + + Inc brightness + Збільшення яскравості + + + + Dec hue + Зменшення кольору + + + + Inc hue + Збільшення кольору + + + + Dec saturation + Зменшення насиченості + + + + Dec gamma + Зменшення гами + + + + Next audio + Наступне аудіо + + + + Next subtitle + Наступні субтитри + + + + Next chapter + Наступний розділ + + + + Previous chapter + Попередній розділ + + + + Inc saturation + Збільшення насиченості + + + + Inc gamma + Збільшення гами + + + + &Load external file... + &Завантажити зовнішній файл... + + + + &Kerndeint + &Ядерний деінтерлейсер + + + + &Yadif (normal) + &Yadif (простий) + + + + Y&adif (double framerate) + Y&adif (подвійна частота кадрів) + + + + &Next + &Наступний + + + + Pre&vious + Поп&ередній + + + + Volume &normalization + Нормалізація &гучності + + + + &Audio CD + &Звуковий CD + + + + Denoise nor&mal + Усунення шуму (зви&чайний) + + + + Denoise &soft + Усунення шуму (&програмний) + + + + Denoise o&ff + Б&ез усунення шуму + + + + Use SSA/&ASS library + Використовувати бібліотеку SSA/&ASS + + + + Flip i&mage + Повернути з&ображення + + + + &Toggle double size + Перемкнути по&двійний розмір + + + + S&ize - + Р&озмір - + + + + Si&ze + + Ро&змір + + + + + Add &black borders + Додати &чорні границі + + + + Soft&ware scaling + Про&грамне масштабування + + + + &FAQ + &ЧаПи + + + + Visualize &motion vectors + Візуалізувати &вектори руху + + + + &Command line options + &Опції командного рядка + + + + SMPlayer command line options + Опції командного рядка SMPlayer + + + + &Jump to... + &Перейти до... + + + + Enable &closed caption + Увімкнути &субтитри + + + + &Forced subtitles only + Субтитри тільки &примусово + + + + Reset video equalizer + Скинути еквалайзер відео + + + + &Rotate + По&вернути + + + + &Off + &Вимк + + + + &Rotate by 90 degrees clockwise and flip + &90 градусів за годинниковою стрілкою та переворот + + + + Rotate by 90 degrees &clockwise + 90 градусів за &годинниковою стрілкою + + + + Rotate by 90 degrees counterclock&wise + 90 градусів &проти годинникової стрілки + + + + Rotate by 90 degrees counterclockwise and &flip + 90 градусів проти &годинникової стрілки та переворот + + + + MPlayer has finished unexpectedly. + Несподіване завершення MPlayer. + + + + Exit code: %1 + Код виходу: %1 + + + + MPlayer failed to start. + Помилка старту MPlayer. + + + + Please check the MPlayer path in preferences. + Перевірте шлях до MPlayer у налаштуваннях. + + + + MPlayer has crashed. + MPlayer зламався. + + + + See the log for more info. + Дивіться звіт для детальної інформації. + + + + Show context menu + Показати контекстне меню + + + + Multimedia + Мультимедіа + + + + E&qualizer + &Еквалайзер + + + + Reset audio equalizer + Скинути аудіоеквалайзер + + + + Find subtitles on &OpenSubtitles.org... + Шукати субтитри на &OpenSubtitles.org... + + + + Upload su&btitles to OpenSubtitles.org... + &Завантажити субтитри на OpenSubtitles.org... + + + + &Tips + &Підказки + + + + Speed -&4% + Швидкість -&4% + + + + &Speed +4% + Швидкість +&4% + + + + Speed -&1% + Швидкість -&1% + + + + S&peed +1% + Швидкість +&1% + + + + Mirr&or image + Від&дзеркалити зображення + + + + Scree&n + &Екран + + + + &Auto + &Автоматично + + + + &Default + За &замовчуванням + + + + Next video + Наступне відео + + + + &Track + video + &Доріжка + + + + &Track + audio + &Доріжка + + + + Warning - Using old MPlayer + Застереження: використовується старий MPlayer + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + Збірка MPlayer (%1), що встановлена у вашій системі, застаріла. SMPlayer не може вірно працювати з нею: деякі опції не будуть працювати, вибір субтитрів може бути невдалим... + + + + Please, update your MPlayer. + Будь ласка, оновіть ваш MPlayer. + + + + (This warning won't be displayed anymore) + (Це застереження не буде більше показуватись) + + + + Next aspect ratio + Нове співвідношення сторін + + + + &Auto zoom + &Автоматичний масштаб + + + + Auto zoom for &16:9 + Автоматичний масштаб для &16:9 + + + + Auto zoom for &2.35:1 + Автоматичний масштаб для &2.35:1 + + + + Zoom for &16:9 + Масштаб для &16:9 + + + + Zoom for &2.35:1 + Масштаб для &2.35:1 + + + + Pre&view... + &Попередній перегляд... + + + + &Always + &Завжди + + + + &Never + &Ніколи + + + + While &playing + Коли &відтворюється + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer все ще працює тут + + + + S&how icon in system tray + В&ідображати піктограму в системному лотку + + + + &Hide + &Сховати + + + + &Restore + &Відновити + + + + &Quit + &Вихід + + + + Playlist + Перелік відтворення + + + + Core + + + Brightness: %1 + Яскравість: %1 + + + + Contrast: %1 + Контрасність: %1 + + + + Gamma: %1 + Гама: %1 + + + + Hue: %1 + Колір: %1 + + + + Saturation: %1 + Насиченість: %1 + + + + Volume: %1 + Гучність: %1 + + + + Zoom: %1 + Масштаб: %1 + + + + Font scale: %1 + Масштаб шрифта: %1 + + + + Aspect ratio: %1 + Співвідношення сторін: %1 + + + + Updating the font cache. This may take some seconds... + Оновити кеш шрифтів. Це може потребувати декількох секунд... + + + + DefaultGui + + + Welcome to SMPlayer + Ласкаво просимо до SMPlayer + + + + Audio + Звук + + + + Subtitle + Субтитри + + + + &Main toolbar + &Головна панель + + + + &Language toolbar + &Панель мов + + + + &Toolbars + &Панелі + + + + EqSlider + + + icon + піктограма + + + + ErrorDialog + + + Hide log + Сховати звіт + + + + Show log + Показати звіт + + + + MPlayer Error + Помилка MPlayer + + + + icon + піктограма + + + + Error + Помилка + + + + FileDownloader + + + Downloading... + Звантажується... + + + + Downloading %1 + Звантажується %1 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - Властивості файлу + + + + &Information + &Інформація + + + + &Demuxer + &Демультиплексор + + + + &Select the demuxer that will be used for this file: + &Виберіть демультиплексор для цього файлу: + + + + &Reset + Ск&инути + + + + &Video codec + &Відео кодек + + + + &Select the video codec: + &Виберіть відео кодек: + + + + A&udio codec + З&вуковий кодек + + + + &Select the audio codec: + &Виберіть звуковий кодек: + + + + &MPlayer options + Опції &MPlayer + + + + Additional Options for MPlayer + Додаткові опції для MPlayer + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Тут Ви можете передати додаткові опції в MPlayer. +Записуються через пробіли. +Приклад: -flip -nosound + + + + &Options: + &Опції: + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Ви можете також передати додаткові фильтри відео. +Разділяйте їх комою. Не використовуйте пробіли! +Приклад: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + Фільтри в&ідео: + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Фільтри звука. Використовуються так само як фільтри відео. +Приклад: resample=44100:0:0,volnorm + + + + Audio &filters: + Фильтри &звуку: + + + + OK + Гаразд + + + + Cancel + Скасувати + + + + Apply + Застосувати + + + + FindSubtitlesWindow + + + Language + Мова + + + + Name + Назва + + + + Format + Формат + + + + Files + Файли + + + + Date + Дата + + + + Uploaded by + Вивантажено + + + + All + Всі + + + + Close + Закрити + + + + &Download + &Звантажити + + + + &Copy link to clipboard + &Скопіювати посилання до буферу обміну + + + + Error + Помилка + + + + Download failed: %1. + Звантаження невдале: %1. + + + + Connecting to %1... + З'єднуюсь з %1... + + + + Downloading... + Звантажується... + + + + Done. + Виконано. + + + + %1 files available + %1 файлів доступні + + + + Failed to parse the received data. + Неможливо обробити прийняті дані. + + + + Find Subtitles + Пошук субтитрів + + + + &Subtitles for + &Субтитри для + + + + &Language: + &Мова: + + + + &Refresh + &Оновити + + + + Overwrite? + Перезаписати? + + + + The file %1 already exits, overwrite? + Файл %1 вже існує, перезаписати? + + + + Subtitle saved as %1 + Субтитри збережені як %1 + + + + %1 subtitle(s) extracted + + Витягнений %1 субтитр + Витягнені %1 субтитри + Витягнені %1 субтитрів + + + + + Error saving file + Помилка збереження файлу + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + Неможливо зберегти звантажений +файл в теці %1 +Будь ласка, перевірте права доступу до цієї теки. + + + + Download failed + Звантаження невдале + + + + Temporary file %1 + Тимчасовий файл %1 + + + + InfoFile + + + General + Головне + + + + Size + Розмір + + + + %1 KB (%2 MB) + %1 кбайт (%2 Мбайт) + + + + URL + URL-адреса + + + + Length + Тривалість + + + + Demuxer + Демультиплексор + + + + Name + Назва + + + + Artist + Виконавець + + + + Author + Автор + + + + Album + Альбом + + + + Genre + Жанр + + + + Date + Дата + + + + Track + Доріжка + + + + Copyright + Авторське право + + + + Comment + Примітка + + + + Software + Програмне забезпечення + + + + Clip info + Інформація про кліп + + + + Video + Зображення + + + + Resolution + Роздільна здатність + + + + Aspect ratio + Співвідношення сторін + + + + Format + Формат + + + + Bitrate + Швидкість потоку + + + + %1 kbps + %1 кбіт/с + + + + Frames per second + Кадрів за секунду + + + + Selected codec + Вибраний кодек + + + + Initial Audio Stream + Початковий звуковий потік + + + + Rate + Частота + + + + %1 Hz + %1 Гц + + + + Channels + Канали + + + + Audio Streams + Звукові потоки + + + + Language + Мова + + + + empty + нічого + + + + Subtitles + Субтитри + + + + Type + Тип + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + + + + + Stream title + Заголовок потоку + + + + Stream URL + URL-адреса потоку + + + + File + Файл + + + + InputDVDDirectory + + + Choose a directory + Вибрати теку + + + + SMPlayer - Play a DVD from a folder + SMPlayer - Відтворити DVD з теки + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + Ви можете відкрити DVD з жорсткого диску. Виберіть теку, яка містить VIDEO_TS та AUDIO_TS. + + + + Choose a directory... + Виберіть теку... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - Вкажіть версію MPlayer + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer не зміг визначити збірку MPlayer, що використовується. + + + + Version reported by MPlayer: + Вказана MPlayer збірка: + + + + Please, &select the correct version: + Будь ласка, &виберіть правильну збірку: + + + + 1.0rc1 or older + 1.0rc1 чи старіша + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + Більша ніж 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - Введіть URL-адресу + + + + &URL: + &URL-адреса: + + + + It's a &playlist + Це &перелік відтворення + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + Якщо ця опція увімкнена, URL-адреса сприймається як перелік відтворення: буде відкрита як текст та відтворена. + + + + Languages + + + Afar + Афарська + + + + Abkhazian + Абхазька + + + + Afrikaans + Африкаанс + + + + Amharic + Амхарська + + + + Arabic + Арабська + + + + Assamese + Ассамська + + + + Aymara + Аймара + + + + Azerbaijani + Азербайджанська + + + + Bashkir + Башкирська + + + + Byelorussian + Білоруська + + + + Bulgarian + Болгарська + + + + Bihari + Біхарі + + + + Bislama + Біслама + + + + Bengali + Бенгальська + + + + Tibetan + Тібетська + + + + Breton + Бретонська + + + + Catalan + Каталонська + + + + Corsican + Корсіканська + + + + Czech + Чеська + + + + Welsh + Валійська + + + + Danish + Данська + + + + German + Німецька + + + + Bhutani + Бхутані + + + + Greek + Грецька + + + + English + Англійська + + + + Esperanto + Есперанто + + + + Spanish + Іспанська + + + + Estonian + Естонська + + + + Basque + Баскська + + + + Persian + Перська + + + + Finnish + Фінська + + + + Fiji + Фіджі + + + + Faroese + Фарерська + + + + French + Французька + + + + Frisian + Фризька + + + + Irish + Ірландська + + + + Scots + Шотландська + + + + Galician + Галисійська + + + + Guarani + Гуарані + + + + Gujarati + Гуджараті + + + + Hausa + Хауса + + + + Hebrew + Іврит + + + + Hindi + Хінді + + + + Croatian + Хорватська + + + + Hungarian + Угорська + + + + Armenian + Вірменська + + + + Interlingua + Інтерлінгва + + + + Indonesian + Індонезійська + + + + Interlingue + Окциденталь + + + + Inupiak + Інупіак + + + + Icelandic + Ісландська + + + + Italian + Італійська + + + + Inuktitut + Інуктитут + + + + Japanese + Японська + + + + Javanese + Яванська + + + + Georgian + Грузинська + + + + Kazakh + Казахська + + + + Greenlandic + Ґренландська + + + + Cambodian + Камбоджийська + + + + Kannada + Канадська + + + + Korean + Корейська + + + + Kashmiri + Кашмірі + + + + Kurdish + Курдська + + + + Kirghiz + Киргизька + + + + Latin + Латинська + + + + Lingala + Лінгала + + + + Laothian + Лаоська + + + + Lithuanian + Литовська + + + + Latvian + Латвійська + + + + Malagasy + Малагаська + + + + Maori + Маорі + + + + Macedonian + Македонська + + + + Malayalam + Малаялам + + + + Mongolian + Монгольська + + + + Moldavian + Молдавська + + + + Marathi + Маратхі + + + + Malay + Малайска + + + + Maltese + Мальтійська + + + + Burmese + Бірманська + + + + Nauru + Науру + + + + Nepali + Непальська + + + + Dutch + Голландська + + + + Norwegian + Норвезька + + + + Occitan + Окситанська + + + + Oriya + Орія + + + + Punjabi + Панджабі + + + + Polish + Польська + + + + Pashto + Пашто + + + + Portuguese + Португальська + + + + Quechua + Кечуа + + + + Kirundi + Кірунди + + + + Romanian + Румунська + + + + Russian + Російська + + + + Kinyarwanda + Киньяруанда + + + + Sanskrit + Санскріт + + + + Sindhi + Сіндхи + + + + Sangho + Санго + + + + Sinhalese + Сингальська + + + + Slovak + Словацька + + + + Slovenian + Словенська + + + + Samoan + Тонга + + + + Shona + Шона + + + + Somali + Сомалійська + + + + Albanian + Албанська + + + + Serbian + Сербська + + + + Siswati + Сісваті + + + + Sesotho + Сесото + + + + Sundanese + Суданська + + + + Swedish + Шведська + + + + Swahili + Суахілі + + + + Tamil + Таміл + + + + Telugu + Телугу + + + + Tajik + Таджикська + + + + Thai + Тайська + + + + Tigrinya + Тигринья + + + + Turkmen + Туркменська + + + + Tagalog + Тагальська + + + + Setswana + Тсвана + + + + Tonga + Тонга + + + + Turkish + Турецька + + + + Tsonga + Тсонга + + + + Tatar + Татарська + + + + Twi + Тві + + + + Uighur + Уйгурська + + + + Ukrainian + Українська + + + + Urdu + Урду + + + + Uzbek + Узбецька + + + + Vietnamese + В'єтнамська + + + + Wolof + Волоф + + + + Xhosa + Ісікоса + + + + Yiddish + Їдиш + + + + Yoruba + Йоруба + + + + Zhuang + Чжуанська + + + + Chinese + Китайська + + + + Zulu + Зулу + + + + Portuguese - Brazil + Португальська (Бразилія) + + + + Portuguese - Portugal + Португальська (Португалія) + + + + Simplified-Chinese + Спрощена китайська + + + + Traditional Chinese + Традиційна Китайська + + + + Unicode + Юнікод + + + + UTF-8 + UTF-8 + + + + Western European Languages + Східна Європа + + + + Western European Languages with Euro + Східна Європа з Євро + + + + Slavic/Central European Languages + Кирилиця/Центральна Європа + + + + Esperanto, Galician, Maltese, Turkish + Есперанто, Галісійська, Мальтійська, Турецька + + + + Old Baltic charset + Балтійська стара + + + + Cyrillic + Кирилиця + + + + Modern Greek + Грецька нова + + + + Baltic + Балтійська + + + + Celtic + Кельтська + + + + Hebrew charsets + Іврит + + + + Ukrainian, Belarusian + Українська, Білоруська + + + + Simplified Chinese charset + Китайська спрощена + + + + Traditional Chinese charset + Китайська традиційна + + + + Japanese charsets + Японська + + + + Korean charset + Корейська + + + + Thai charset + Тайська + + + + Cyrillic Windows + Кирилиця Windows + + + + Slavic/Central European Windows + Кирилиця/Центральна Європа Windows + + + + Arabic Windows + Арабська Windows + + + + Rhaeto-Romance + Рето-романська + + + + Serbo-Croatian + Сербо-хорватська + + + + Volapük + Волапюк + + + + Avestan + Авестійська + + + + Akan + Аканська + + + + Aragonese + Арагонська + + + + Avaric + Аваріська + + + + Belarusian + Білоруська + + + + Bambara + Бамбара + + + + Bosnian + Боснійська + + + + Chechen + Чеченська + + + + Cree + Крі + + + + Church + Церковна + + + + Chuvash + Чуваська + + + + Divehi + Мальдівійська + + + + Dzongkha + Дзонг-ке + + + + Ewe + Еве + + + + Fulah + Фула + + + + Fijian + Фіджійська + + + + Gaelic + Гельська + + + + Manx + Менська + + + + Hiri + Хірі + + + + Haitian + Гаітійська + + + + Herero + Гереро + + + + Chamorro + Чаморро + + + + Igbo + Ігбо + + + + Sichuan + Сичуанська + + + + Inupiaq + Інупіак + + + + Ido + Ідо + + + + Kongo + Конго + + + + Kikuyu + Кікуйю + + + + Kuanyama + Кваньяма + + + + Khmer + Кхмерська + + + + Kanuri + Канурі + + + + Komi + Комі + + + + Cornish + Корнська + + + + Luxembourgish + Люксембургська + + + + Ganda + Луганда + + + + Limburgan + Лімбурган + + + + Lao + Лаоська + + + + Luba-Katanga + Луба-Катанга + + + + Marshallese + Маршульська + + + + Bokmål + Букмол + + + + Ndebele + Ндебеле + + + + Ndonga + Ндонга + + + + Navajo + Навахо + + + + Chichewa + Чічева + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + Волапюк + + + + Walloon + Валонська + + + + LogWindow + + + Choose a filename to save under + Виберіть назву файлу, з якою необхідно зберегти + + + + Confirm overwrite? + Перезаписати? + + + + The file already exists. +Do you want to overwrite? + Файл існує. +Перезаписати? + + + + Error saving file + Помилка збереження файлу + + + + The log couldn't be saved + Неможливо зберегти звіт + + + + Logs + Звіти + + + + LogWindowBase + + + Log Window + Вікно звіту + + + + Save + Зберегти + + + + Copy to clipboard + Копіювати до буферу обміну + + + + Close + Закрити + + + + &Close + &Закрити + + + + MiniGui + + + Control bar + Панель керування + + + + MpcGui + + + Control bar + Панель керування + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + Name + Назва + + + + Length + Тривалість + + + + &Play + Від&творити + + + + &Edit + &Редагувати + + + + Playlists + Перелік відтворення + + + + Choose a file + Вибрати файл + + + + Choose a filename + Виберіть назву файлу + + + + Confirm overwrite? + Перезаписати? + + + + The file %1 already exists. +Do you want to overwrite? + Файл %1 існує. +Перезаписати? + + + + All files + Всі файли + + + + Select one or more files to open + Виберіть один чи більше файлів + + + + Choose a directory + Вибрати теку + + + + Edit name + Змінити назву + + + + Type the name that will be displayed in the playlist for this file: + Введіть назву, яка буде відображатись у списку для цього файлу: + + + + &Load + &Завантажити + + + + &Save + &Зберегти + + + + &Next + &Наступний + + + + Pre&vious + По&передній + + + + Move &up + Змістити &вгору + + + + Move &down + Змістити &вниз + + + + &Repeat + &Повторювати + + + + S&huffle + П&еремішати + + + + Add &current file + Додати &поточний файл + + + + Add &file(s) + Додати &файл(и) + + + + Add &directory + Додати &теку + + + + Remove &selected + Видалити &вибране + + + + Remove &all + Видалити &все + + + + SMPlayer - Playlist + SMPlayer - Перелік відтворення + + + + Add... + Додати... + + + + Remove... + Видалити... + + + + Playlist modified + Перелік відтворення змінено + + + + There are unsaved changes, do you want to save the playlist? + Зміни в переліку відтворення не збережені! Ви бажаєте зберегти? + + + + Preferences + Налаштування + + + + PlaylistPreferences + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + Виберіть цю опцію, якщо хочете, щоб додавання теки також додавало підтеки рекурсивно. Інакше будуть додані лише файли у вибраній теці. + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + Виберіть цю опцію, щоб витягти з файлів, які будуть додані до переліку програвання, деякі подробиці. Це дозволить показувати назву (якщо наявна) та довжину файлів. Інакше ці подробиці не будуть доступні доки файл не буде дійсно програватися. Пам'ятайте: ця опція може бути повільною, особливо, якщо ви додаєте багато файлів. + + + + Playlist - Preferences + Перелік відтворення - Налаштування + + + + &Add files in directories recursively + &Додати файли в теках рекурсивно + + + + Automatically get &info about files added + Автоматично отримувати &інформацію про додані файли + + + + &Save copy of playlist on exit + &Зберегти копію переліку програвання під час виходу + + + + &Play files from start + Грати файли з &початку + + + + PrefAdvanced + + + Advanced + Додатково + + + + Auto + Автоматично + + + + &Advanced + &Додатково + + + + icon + піктограма + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + Тут Ви можете передати додаткові опції для MPlayer. +Розділяються пробілами. +Приклад: -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + Тут Ви можете передати додаткові фільтри відео. +Разділяти комою. Не використовувати пробіли! +Приклад: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + Фільтри звуку. Використовуються так само як фільтрам відео. +Приклад: resample=44100:0:0,volnorm + + + + Log MPlayer output + Вихідний звіт MPlayer + + + + Log SMPlayer output + Вихідний звіт SMPlayer + + + + This option is mainly intended for debugging the application. + Ці опції, головним чином, потрібні щоб відлагодити програму. + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + Ця опція може зменшити мерехтіння, але може призвести до того, що зображення не буде показане як слід. + + + + Filter for SMPlayer logs + Фильтр для звітів SMPlayer + + + + &Monitor aspect: + Відношення &сторін монітора: + + + + &Run MPlayer in its own window + &Запускати MPlayer у власному вікні + + + + &Options: + &Налаштування: + + + + V&ideo filters: + Фільтри зоб&раження: + + + + Audio &filters: + Фільтри &звуку: + + + + &Colorkey: + &Код кольору: + + + + Log &SMPlayer output + Вести звіт виведення &SMPlayer + + + + &Filter for SMPlayer logs: + &Фільтр для звітів SMPlayer: + + + + C&hange... + З&мінити... + + + + Logs + Звіти + + + + Log MPlayer &output + Вести звіт &вивидення MPlayer + + + + Options for MP&layer + Опції MP&layer + + + + Autosave MPlayer log + Автозбереження звіту MPlayer + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + Якщо увімкнено, звіт MPlayer буде збережено у вказаний файл кожного разу при початку відтворення нового файлу. Це призначається для зовнішніх програм, які таким чином можуть отримати інформацію про файл, що відтворюється. + + + + Autosave MPlayer log filename + Назва файлу для автозбереження звіту MPlayer + + + + Enter here the path and filename that will be used to save the MPlayer log. + Введіть шлях та назву файлу, в який буде збережено звіт MPlayer. + + + + A&utosave MPlayer log to file + А&втозбереження звіту MPlayer в файл + + + + Pass short filenames (8+3) to MPlayer + Передавати короткі назви (8+3) до MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + В даний момент MPlayer не вміє відкривати назви файлів, в яких присутні символи не з місцевої кодової сторінки. Увімкнення цієї опції вкаже SMPlayer передавати до MPlayer коротку версію імен файлів, і тоді їх можна буде відкрити. + + + + &Pass short filenames (8+3) to MPlayer + Передавати &короткі назви (8+3) до MPlayer + + + + Monitor aspect + Відношення сторін монітора + + + + Select the aspect ratio of your monitor. + Виберіть формат зображення Вашого монітора. + + + + Run MPlayer in its own window + Запускати MPlayer у власному вікні + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + Якщо увімкнено, MPlayer буде запущено не у головному вікні SMPlayer, а у власному. Примітка: події клавіатури та миші будуть оброблюватись безпосередньо MPlayer, комбінації клавіш та кліки мишкою будуть працювати не так, як очікується, коли у фокусі вікно MPlayer. + + + + Colorkey + Код кольору + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + Якщо ви бачите частини відео по будь-яких інших вікнах, Ви можете змінити код кольору для виправлення цього. Спробуйте колір, близький до чорного. + + + + Options for MPlayer + Опції для MPlayer + + + + Options + Опції + + + + Here you can type options for MPlayer. Write them separated by spaces. + Тут Ви можете передати опції в MPlayer. Записуються через пробіли. + + + + Video filters + Фільтри відео + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + Тут Ви можете додати відеофільтри для MPlayer. Записуються через коми. Не використовуйте пробіли! + + + + Audio filters + Фильтри звуку + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + Тут Ви можете додати фільтри звуку для MPlayer. Записуються через коми. Не використовуйте пробіли! + + + + Repaint the background of the video window + Перемалювати тло вікна із зображенням + + + + Repaint the backgroun&d of the video window + Перемалювати &тло вікна із зображенням + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + Використовувати IPv4 для мережевих з'єднань. Після помилки перемикати на IPv6 автоматично. + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + Використовувати IPv6 для мережевих з'єднань. Після помилки перемикати на IPv4 автоматично. + + + + Rebuild index if needed + Відновлювати індекс при потребі + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + Відновлювати індекс файлів якщо не знайдено, дозволяючи прокрутку. Корисно при неповно/помилково завантажених чи створених з помилками файлах. Ця опція працює тільки якщо в даному медіа підтримується прокрутка (тобто не stdin, pipe та ін.). Примітка: створення індекса займає деякий час. + + + + Network Connection + Мережеві з'єднання + + + + IPv&4 + IPv&4 + + + + IPv&6 + IPv&6 + + + + Rebuild &index if needed + Відновлювати &індекс при потребі + + + + Lo&gs + &Звіти + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + Якщо увімкнено, SMPlayer зберігатиме повідомлення налагодження (ви можете переглянути звіт в <b>Налаштування -> Дивитись звіти -> SMPlayer</b>). Ця інформація може бути корисною для розробників у випадку, коли ви знайдете помилку. + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + Якщо увімкнено, SMPlayer буде зберігати повідомлення MPlayer (їх можна побачити у <b>Налаштування->Дивитись звіти->mplayer</b>). У випадку проблем ці звіти можут містити важливу інформацію, так що радимо увімкнути. + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + Ця опція дозволяє фільтрувати повідомлення SMPlayer, які будуть збережені у звіті. Тут Ви можете написати будь-який регулярний вираз.<br>Наприклад: <i>^Core::.*</i> відобразить лише рядки, що починаються з <i>Core::</i> + + + + Correct pts + Корегувати pts + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + Перемикає MPlayer в експериментальний режим, в якому мітки часу для відеокадрів обчислюються інакше і підтримуються фільтри відео, що додають нові кадри або змінюють мітки часу існуючих. Більш точні мітки можна побачити, наприклад, коли відтворювані субтитри синхронізовані зі змінами сцен, з увімкненою бібліотекою SSA/ASS. Без корегування pts синхронізація субтитрів буде порушена для деяких кадрів. Ця опція не працюватиме вірно з деякими демультиплексорами та кодеками. + + + + Proxy + Проксі + + + + Enable proxy + Увімкнути проксі + + + + Enable/disable the use of the proxy. + Увімкнути/вимкнути використання проксі. + + + + Host + Сервер + + + + The host name of the proxy. + Назва серверу проксі. + + + + Port + Порт + + + + The port of the proxy. + Порт проксі. + + + + Username + Ім'я користувача + + + + If the proxy requires authentication, this sets the username. + Якщо проксі портебую автентифікації, це встановлює ім'я користувача. + + + + Password + Пароль + + + + The password for the proxy. Warning: the password will be saved as plain text in the configuration file. + Пароль для проксі. Застереження: пароль буде збережений як звичайний текст в файлі налаштувань. + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + Ви можете встановити проксі для мережевих з'єднань (зараз використовується тільки для звантаження субтитрів). + + + + &Enable proxy + &Увімкнути проксі + + + + &Host: + &Сервер: + + + + &Port: + П&орт: + + + + &Username: + &Ім'я користувача: + + + + Pa&ssword: + П&ароль: + + + + C&orrect PTS + &Корегувати PTS + + + + Http + Http + + + + Socks5 + Socks5 + + + + Type + Тип + + + + Select the proxy type to be used. + Виберіть який використовувати тип проксі. + + + + &Type: + &Тип: + + + + Actions list + Перелік дій + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + Тут ви можете визначити перелік <i>дій</i>, які будуть виконані кожного разу як буде відкритий файл. Ви знайдете всі наявні дії в редакторі комбінацій клавіш в розділі <b>Клавіатура та миша</b>. Дії мають бути розділені пробілами. За вибірковими діями можуть слідувати <i>true</i> або <i>false</i>, щоб увімкнути або вимкнути дію. + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + Обмеження: дії виконуються тільки коли файл буде відкритий та не тоді, коли процес mplayer перезапущено (наприклад ви виберете відео чи аудіофільтр). + + + + Network + Мережа + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + &Запустити наступні дії кожного разу як був відкритий файл. Дії мають бути розділені пробілами: + + + + &Network + &Мережа + + + + Example: + Приклад: + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + Відновлювати індекс файлів якщо не знайдено, дозволяючи прокрутку. Корисно при неповно/помилково завантажених чи створених з помилками файлах. Ця опція працює тільки якщо в даному медіа підтримується прокрутка (тобто не stdin, pipe та ін.).<br> <b>Примітка:</b> створення індекса займає деякий час. + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + Пароль для проксі. <b>Застереження:</b> пароль буде збережений як звичайний текст в файлі налаштувань. + + + + PrefAssociations + + + Warning + Попередження + + + + Not all files could be associated. Please check your security permissions and retry. + Неможливо асоціювати жоден файл. Перевірте Ваші права доступу та спробуйте знову. + + + + File Types + Типи файлів + + + + Select all + Вибрати всі + + + + Check all file types in the list + Відмітити всі типи файлів в списку + + + + Uncheck all file types in the list + Зняти відмітки з усіх типів файлів у списку + + + + List of file types + Перелік всіх типів файлів + + + + File types + Типи файлів + + + + Media files handled by SMPlayer: + Файли медіа, які оброблюються SMPlayer: + + + + Select All + Вибрати все + + + + Select None + Не вибирати жодного + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + Відзначте розширення файлів медіа, які ви хочете оброблювати SMPlayer. При застосуванні відзначені файли будуть асоційовані з SMPlayer. Якщо Ви знімете позначку типів медіа, асоціація файлів буде відновлена. + + + + Select none + Не вибирати жодного + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>Примітка:</b> (Відновлення не діє у Windows Vista). + + + + PrefDrives + + + Drives + Диски + + + + icon + піктограма + + + + CD device + Пристрій CD + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + Вкажіть Ваш пристрій CDROM. Це потрібно для програвання звукових та VCD дисків. + + + + DVD device + Пристрій DVD + + + + Choose your DVD device. It will be used to play DVDs. + Вкажіть Ваш пристрій DVD. Це потрібно для програвання DVD. + + + + Select your &CD device: + Виберіть Ваш &CD-пристрій: + + + + Select your &DVD device: + Виберіть Ваш &DVD-пристрій: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer не вибирає жодного CD чи DVD пристрою за замовчуванням. Тому перед відтворенням CD чи DVD Ви повині вказати який пристрій хочете використовувати (це може бути один і той самий). + + + + PrefGeneral + + + General + Головне + + + + &General + &Головне + + + + Paths + Шляхи + + + + Media settings + Налаштування медіа + + + + Start videos in fullscreen + Стартувати відео на повний екран + + + + Disable screensaver + Придушити скринсейвер + + + + Select the mplayer executable + Вкажіть виконуваний файл MPlayer + + + + Executables + Виконувані файли + + + + All files + Всі файли + + + + Select a directory + Виберіть теку + + + + MPlayer executable + Виконуваний файл MPlayer + + + + Screenshots folder + Тека знімків екрану + + + + Video output driver + Пристрій виведення відео + + + + Audio output driver + Пристрій виведення звуку + + + + Select the audio output driver. + Виберіть драйвер виведення звуку. + + + + Remember settings + Запам'ятати налаштування + + + + Preferred audio language + Бажана мова аудіо + + + + Preferred subtitle language + Бажана мова субтитрів + + + + Software video equalizer + Програмний відеоеквалайзер + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + Ви можете спробувати ці опції, якщо відеоеквалайзер не підтримується Вашою відеокартою чи вибраним драйвером виведення відео.<br><b>Примітка:</b> ці опції можуть бути несумісними з деякими драйверами виведення відео. + + + + If this option is checked, all videos will start to play in fullscreen mode. + Якщо Ви виберете цю опцію, всі відеофайли будуть стартувати на весь екран. + + + + Software volume control + Програмне керування гучності + + + + Check this option to use the software mixer, instead of using the sound card mixer. + Перевірте ці опції для використання програмного мікшера замість апаратного мікшера звукової карти. + + + + Postprocessing quality + Якість післяобробки + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Динамічна зміна рівня післяобробки в залежності від вільного процесорного часу. Число, яке Ви вкажете, буде використано як максимальний рівень. Звичайно можна вказати досить велике значення. + + + + Change volume + Змінити гучність + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + Якщо увімнено, SMPlayer буде запам'ятовувати гучність для усіх файлів і відновлюватиме при наступному їх відкритті. Для нових файлів буде використана гучніть за замовчуванням. + + + + 0 + 0 + + + + &Change volume on every file + &Змінити гучність для всіх файлів + + + + Select the &MPlayer executable: + Виберіть виконуваний файл &MPlayer: + + + + &Folder for storing screenshots: + &Тека для збереження знімків екрану: + + + + &Audio: + &Звук: + + + + &Remember settings for all files (audio track, subtitles...) + Запам'ятовувати налаштування для &всіх файлів (звукові доріжки, субтитри...) + + + + Su&btitles: + Су&бтитри: + + + + &Quality: + &Якість: + + + + Start videos in &fullscreen + Стартувати відео на повний &екран + + + + Disable &screensaver + Вимкнути &зберігач екрану + + + + &Default volume: + &Гучність за замовчуванням: + + + + Use s&oftware volume control + Використовувати програмне &керування гучності + + + + Ma&x. Amplification: + Мак&симальне підсилення: + + + + &AC3/DTS pass-through S/PDIF + Передача &AC3/DTS на S/PDIF + + + + Direct rendering + Пряме відтворення + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + Якщо увімкнено, активується пряме відтворення (підтримується не всіми кодеками та пристроями відеовиведення)<br><b>УВАГА:</b> Може пошкодити екранну індикацію та субтитри! + + + + Double buffering + Подвійна буферизація + + + + D&irect rendering + П&ряме відтворення + + + + Dou&ble buffering + Под&війна буферизація + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + Подвійна буферизація виправляє мерехтіння тримаючи два кадри в пам'яті, і відображає один, декодує інший. Якщо вимкнено, може негативно вплинути на екранну індикацію, але, як правило, припиняє її мерехтіння. + + + + &Enable postprocessing by default + &Активувати післяобробку за замовчуванням + + + + Volume &normalization by default + Нормалізація &гучності за замовчуванням + + + + Close when finished + Вийти по закінченню + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + Ця опція активує автоматичний вихід з програми по закінченню відтворення файлу чи переліку. + + + + 2 (Stereo) + 2 (Стерео) + + + + 4 (4.0 Surround) + 4 (4.0 оточення) + + + + 6 (5.1 Surround) + 6 (5.1 оточення) + + + + C&hannels by default: + К&анали за замовчуванням: + + + + &Pause when minimized + &Призупинити при мінімізації + + + + Pause when minimized + Призупинити при мінімізації + + + + Enable postprocessing by default + Увімкнути післяобробку за замовчуванням + + + + Max. Amplification + Максимальне підсилення + + + + AC3/DTS pass-through S/PDIF + Передача AC3/DTS на S/PDIF + + + + Volume normalization by default + Нормалізація гучності за замовчуванням + + + + Maximizes the volume without distorting the sound. + Максимізація гучності без спотворення звуку. + + + + Default volume + Гучність за замовчуванням + + + + Sets the initial volume that new files will use. + Встановити початкову гучність для всіх нових файлів. + + + + Channels by default + Канали за замовчуванням + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + Встановлює максимальний рівень підсилення у відсотках (за замовчуванням: 110). Значення 200 дозволить Вам зільшити гучність вдвічі від поточного значення. Зі значенням менше 100 початкова гучність (тобто 100%) буде вище максимуму, який неправильно відображається екранною індикацією. + + + + Uses hardware AC3 passthrough + Використовувати апаратну передачу AC3 + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. NOTE: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Вказує кількість каналів для відтворення. MPlayer вказує декодеру декодувати звук на вказану кількість каналів. Це виконує сам декодер. Це, як правило, актуально лише для відтворення відео із звуком AC3 (як DVD). В цьому випадку liba52 декодує за замовчуванням та правильно змішує звук в необхідну кількість каналів. ПРИМІТКА: Ця опція лише для кодеку (тільки AC3), фільтрів (розширення оточення) та драйверів виведення звуку (принаймні OSS). + + + + Postprocessing will be used by default on new opened files. + Післяобробка буде використовуватись для всіх нових файлів. + + + + Audio track + Звукова доріжка + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + Задає звукову доріжку, яка буде використовуватись при відкритті нових файлів. Якщо доріжка не існує, буде використано першу. <br><b>Примітка: </b><i>"бажана мова звуку"</i> має перевагу над цією опцією. + + + + Subtitle track + Доріжка субтитрів + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + Задає доріжку субтитрів, яка буде використовуватись при відкритті нових файлів. Якщо доріжка не існує, буде використано першу. <br><b>Примітка: </b><i>"бажана мова субтитрів"</i> має перевагу над цією опцією. + + + + Or choose a track number: + Або виберіть номер доріжки: + + + + Audi&o: + Ауді&о: + + + + Preferred language: + Бажана мова: + + + + Preferre&d audio and subtitles + Бажа&ні звук та субтитри + + + + &Subtitle: + &Субтитри: + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Тут Ви можете вказати бажану мову звуку та субтитрів. Коли буде знайдено медіа з багатодоріжковими звуком чи субтитрами, SMPlayer спробує використовувати Вашу бажану мову. Це працює лише з медіа, які надають інформацію про мову звуку та субтитрів, такі як DVD чи файли mkv. <br>Це поле сприймає регулярні вирази. Наприклад: <b>es|esp|spa</b> вибере доріжку, якщо це відповідно <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + Висока швидкість &відтворення без зміни кроку + + + + High speed playback without altering pitch + Висока швидкість відтворення без зміни кроку + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + Дозволяє змінювати швидкість відтворення без зміни кроку. Потрібен принаймні MPlayer dev-SVN-r24924. + + + + Change volume just before playing + Змініть гучність безпосередньо перед відтворенням + + + + &Video + &Відео + + + + Use s&oftware video equalizer + Використовувати прог&рамний відеоеквалайзер + + + + A&udio + З&вук + + + + Volume + Гучність + + + + None + Нічого + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (простий) + + + + Yadif (double framerate) + Yadif (подвійна частота кадрів) + + + + Linear Blend + Лінійне змішування + + + + Kerndeint + Ядерний деінтерлейсер + + + + Video + Відео + + + + Deinterlace by default + Деінтерлейсинг за замовчуванням + + + + Select the deinterlace filter that you want to be used for new videos opened. + Виберіть фільтр деінтерлейсингу, який буде застосовано до нових відео при відкритті. + + + + Audio + Звук + + + + Preferred audio and subtitles + Бажані звук та субтитри + + + + Dei&nterlace by default: + Деін&терлейсинг за замовчуванням: + + + + Remember time position + Запам'ятати позицію часу + + + + Remember &time position + Запам'ятати &позицію часу + + + + Change volume just before p&laying + Змінити &гучність безпосередньо перед відтворенням + + + + fast + швидко + + + + slow + повільно + + + + fast - ATI cards + швидко - карти ATI + + + + User defined... + Визначені користувачем... + + + + Draw video using slices + Промальовувати відео смугами + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + Ввімкнути/вимкнути промальовування відео смугами, висотою 16 пікселів. Якщо вимкнено, то цілий кадр малюється за раз. Може бути швидше або повільніше, в залежності відеокарти та наявного кешу. Діє лише з кодеками libmpeg2 та libavcodec. + + + + Enable the audio equalizer + Ввімкнути аудіоеквалайзер + + + + Check this option if you want to use the audio equalizer. + Виберіть цю опцію, якщо ви бажаєте використавувати аудіоеквалайзер. + + + + &Close when finished playback + &Вийти по закінченню відтворення + + + + Dra&w video using slices + Промальовувати відео &смугами + + + + &Enable the audio equalizer + &Ввімкнути аудіоеквалайзер + + + + Default zoom + Масштаб за замовчуванням + + + + This option sets the default zoom which will be used for new videos. + Ця опція встановлює масштаб за замовчуванням, який буде застосовуватись для нових відеофайлів. + + + + Default &zoom: + &Масштаб за замовчуванням: + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + Тут Вам потрібно вказати виконуваний файл mplayer, який SMPlayer буде використовувати.<br>SMPlayer потрібна версія mplayer щонайменше 1.0rc1 (рекомендується з svn). + + + + If this setting is wrong, SMPlayer won't be able to play anything! + Якщо ці налаштування невірні, SMPlayer не зможе нічого програти! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + Тут Ви можете вказати теку, куди будуть зберігатися знімки екрану, зроблені SMPlayer. Якщо це поле буде пустим, можливість буде вимкнена. + + + + Select the video output driver. %1 provides the best performance. + Виберіть драйвер виведення відео. %1 забезпечує найкращу швидкодію. + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + %1 рекомендований. Спробуйте прибрати %2 та %3, вони повільні та можуть вплинути на швидкодію. + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + SMPlayer зазвичай запам'ятовує налаштування для кожного файлу (вибрані доріжки, гучність, фільтри...). Вимкніть цю опцію, якщо вам це не подобається. + + + + If you check this option, SMPlayer will play all files from the beginning. + Якщо ви виберете цю опцію, SMPlayer відтворюватиме всі файли з початку. + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + Якщо ця опція увімкнена, файл буде призупинений, коли головне вікно сховане. Коли вікно відновиться, відтворення буде відновлене. + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + Встановіть цю опцію, щоб вимкнути зберігач екрану під час відтворення.<br>Зберігач екрану увімкнеться знову, коли відтворення завершиться. + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Тут Ви можете вказати мову для звукових доріжок. При знаходженні декількох звукових доріжок SMPlayer буде намагатися використовувати вказану Вами мову.<br>Це працює тільки для форматів, які надають інформацію про мови для звукових доріжок, такі як DVD чи mkv файли.<br>Поля приймають регулярні вирази. Приклад: <b>es|esp|spa</b> вибере звукову доріжку, яка відповідатиме <i>es</i>, <i>esp</i> чи <i>spa</i>. + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + Тут Ви можете вказати мову для звукових субтитрів. При знаходженні субтитрів для SMPlayer буде намагатись використати бажану для вас мову.<br>Це працює тільки для форматів, які надають інформацію про мови для субтитрів, такі як DVD чи mkv файли.<br>Поля приймають регулярні вирази. Приклад: <b>es|esp|spa</b> призначить звукову доріжку, яка відповідатиме <i>es</i>, <i>esp</i> чи <i>spa</i>. + + + + Ou&tput driver: + Пристрої &виведення: + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + Якщо увімкнено, початкова гучність буде встановлена прямо перед початком програвання. Це усуне високу гучність на початку. Портебує щонайменш MPlayer SVN r27872. + + + + Add black borders on fullscreen + Додати чорні границі при повному екрані + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + Ящо ця опція увімкнена, границі будуть додані до зображення при повному екрані. Це дозволить відображати субтитри на чорних границях. + + + + &Add black borders on fullscreen + &Додати чорні границі при повному екрані + + + + one ini file + один файл ini + + + + multiple ini files + багато файлів ini + + + + Method to store the file settings + Спосіб збереження файлів налаштувань + + + + This option allows to change the way the file settings would be stored. The following options are available: + Ця опція дозволить змінити спосіб, у який будуть зберігатися файли налаштувань. Доступні наступні опції: + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + <b>один файл ini</b>: налаштування всіх відтворюваних файлів зберігатимуться в одному файлі ini (%1) + + + + The latter method could be faster if there is info for a lot of files. + Останній спосіб може бути швидшим, якщо є інформація для багатьох файлів. + + + + &Store settings in + &Зберігати налаштування у + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + <b>багато файлів ini</b>: буде використано один файл ini для кожного відтворюваного файлу. Ці файли ini будуть збережені у теці %1 + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + Якщо ви виберете цю опцію, SMPlayer пам'ятатиме останнє положення файлу, коли ви відкриєте його знову. Ця опція працює тільки зі звичайними файлами (не з DVD, CD, URL...). + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + Якщо увімкнено, вмикається пряме відтворення (підтримується не всіми кодеками та пристроями відеовиведення)<br><b>Застереження:</b> Може пошкодити екранну індикацію та субтитри! + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + Вказує кількість каналів для відтворення. MPlayer вказує декодеру декодувати звук на вказану кількість каналів. Це виконує сам декодер. Це, як правило, актуально лише для відтворення відео із звуком AC3 (як DVD). В цьому випадку liba52 декодує за замовчуванням та правильно змішує звук в необхідну кількість каналів. <b>Примітка:</b> Ця опція лише для кодеку (тільки AC3), фільтрів (розширення оточення) та драйверів виведення звуку (принаймні OSS). + + + + PrefInput + + + Keyboard and mouse + Клавіатура та миша + + + + &Keyboard + &Клавіатура + + + + icon + піктограма + + + + &Mouse + &Миша + + + + Button functions: + Функції кнопок: + + + + Media seeking + Прокрутка + + + + Volume control + Гучність + + + + Zoom video + Масштаб відео + + + + None + Нічого + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Тут Ви можете змінити будь-яку комбінацію клавіш. Двічі клацніть або натисніть ENTER на чарунку комбінації. Додатково Ви можете зберегти список комбінацій для розповсюдження іншим або завантаження на іншому комп'ютері. + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + Тут Ви можете вказати будь-які комбінації клавіш. Двічі клікніть для введення або почніть вводити комбінацію на чарунку. Також Ви можете зберегти перелік комбінацій для інших або для завантаження на іншому комп'ютері. + + + + &Left click + &Клік лівою + + + + &Double click + &Подвійний клік + + + + &Wheel function: + &Функція колеса: + + + + Shortcut editor + Редактор гарячих клавіш + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + Тут Ви можете змінити будь-яку доступну комбінацію клавіш. Двічі клацніть або натисніть ENTER на чарунку комбінації, чи натисніть кнопку <b>Змінити комбінацію клавіш</b> для введення в діалозі <i>Змінити комбінацію</i>. Є два способи змінити комбінацію: або натиснути кнопку <b>Захоплення</b> і просто натиснути потрібну комбінацію клавіш (нажаль, не працює для всіх клавіш), або просто написати повну назву клавіш. + + + + Left click + Клік лівою + + + + Select the action for left click on the mouse. + Виберіть функцію кліку лівою для мишки. + + + + Double click + Подвійний клік + + + + Select the action for double click on the mouse. + Виберіть функцію подвійного кліку для мишки. + + + + Wheel function + Функція колеса + + + + Select the action for the mouse wheel. + Виберіть функцію колеса для мишки. + + + + Play + Відтворення + + + + Pause + Призупинка + + + + Stop + Стоп + + + + Fullscreen + На весь екран + + + + Compact + Стисло + + + + Screenshot + Знімок екрану + + + + On top + Зверху + + + + Mute + Вимкнути звук + + + + Frame counter + Лічильник кадрів + + + + Reset zoom + Скинути масштаб + + + + Exit fullscreen + Вийти з повноекранного режиму + + + + Double size + Подвійний розмір + + + + Play / Pause + Відтворити / Призупинити + + + + Pause / Frame step + Призупинити / Крок кадра + + + + Playlist + Перелік відтворення + + + + Preferences + Налаштування + + + + No function + Немає функції + + + + Change speed + Змінити швидкість + + + + Normal speed + Звичайна швидкість + + + + Go backward (short) + Крок назад (короткий) + + + + Go backward (medium) + Крок назад (середній) + + + + Go backward (long) + Крок назад (довгий) + + + + Go forward (short) + Крок вперед (короткий) + + + + Go forward (medium) + Крок вперед (середній) + + + + Go forward (long) + Крок вперед (довгий) + + + + OSD - Next level + Екранна індікація - наступний рівень + + + + Keyboard + Клавіатура + + + + Mouse + Миша + + + + Middle click + Середній клік + + + + Select the action for middle click on the mouse. + Виберіть функцію кліку середньою для мишки. + + + + M&iddle click + Се&редній клік + + + + X Button &1 + X кнопка &1 + + + + X Button &2 + X кнопка &2 + + + + Show context menu + Показати контекстне меню + + + + &Right click + &Клік правою + + + + Increase volume + Збільшення гучності + + + + Decrease volume + Зменшення гучності + + + + X Button 1 + X кнопка 1 + + + + Select the action for the X button 1. + Виберіть функцію для "X кнопка 1". + + + + X Button 2 + X кнопка 2 + + + + Select the action for the X button 2. + Виберіть функцію для "X кнопка 2". + + + + Show video equalizer + Показати відеоеквалайзер + + + + Show audio equalizer + Показати аудіоеквалайзер + + + + Always on top + Завжди зверху + + + + Never on top + Ніколи зверху + + + + On top while playing + Зверху коли відтворюється + + + + PrefInterface + + + Interface + Інтерфейс + + + + <Autodetect> + <Автоматичне визначення> + + + + Default + За замовчуванням + + + + &Interface + &Інтерфейс + + + + Recent files + Останні файли + + + + Never + Ніколи + + + + Whenever it's needed + Коли це потрібно + + + + Only after loading a new video + Тільки після відкриття нового відео + + + + Language + Мова + + + + Here you can change the language of the application. + Тут Ви можете змінити мову програми. + + + + &Short jump + &Короткий крок + + + + &Medium jump + &Середній крок + + + + &Long jump + &Довгий крок + + + + Mouse &wheel jump + Крок &колеса миші + + + + &Use only one running instance of SMPlayer + &Активувати віддалене керування SMPlayer + + + + Ma&x. items + Мак&симальний показник + + + + St&yle: + Ст&иль: + + + + Ico&n set: + Встановити пі&ктограми: + + + + L&anguage: + М&ова: + + + + Main window + Головне вікно + + + + Auto&resize: + &Розмір автоматично: + + + + R&emember position and size + З&апам'ятовувати положення та розмір + + + + Default font: + Шрифт за замовчуванням: + + + + &Change... + &Змінити... + + + + &Behaviour of time slider: + &Поведінка повзунка часу: + + + + Seek to position while dragging + Шукати позицію при перетягуванні + + + + Seek to position when released + Шукати позицію після відпускання + + + + TextLabel + Відмітка + + + + &Seeking + &Пошук + + + + Ins&tances + &Екземпляри + + + + Autoresize + Розмір автоматично + + + + The main window can be resized automatically. Select the option you prefer. + Головне вікно може змінювати розмір автоматично. Виберіть бажаний варіант. + + + + Remember position and size + Запам'ятати позицію та розмір + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + Якщо ця опція увімкнена, розмір та позицію головного вікна буде збережено та відновлено при наступному старті SMPlayer. + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + Вкажіть максимальну кількість пунктів, яку буде відображено в підменю <b>Відкрити->Останні файли</b>. Якщо вказано 0, це меню відображатись не буде. + + + + Icon set + Набори піктограм + + + + Select the icon set you prefer for the application. + Виберіть бажані піктограми для програми. + + + + Style + Стиль + + + + Select the style you prefer for the application. + Виберіть бажаний стиль для програми. + + + + Default font + Шрифт за замовчуванням + + + + You can change here the application's font. + Тут Ви можете змінити шрифт програми. + + + + Seeking + Пошук + + + + Short jump + Короткий крок + + + + Select the time that should be go forward or backward when you choose the %1 action. + Вкажіть час для кроку назад чи вперед при виборі дії %1. + + + + short jump + короткий крок + + + + Medium jump + Середній крок + + + + medium jump + середній крок + + + + Long jump + Довгий крок + + + + long jump + довгий крок + + + + Mouse wheel jump + Крок колеса миші + + + + Select the time that should be go forward or backward when you move the mouse wheel. + Вкажіть час для кроку назад чи вперед при прокрутці колеса миші. + + + + Behaviour of time slider + Поведінка повзунка часу + + + + Select what to do when dragging the time slider. + Виберіть дію для переміщення повзунка часу. + + + + Instances + Екземпляри + + + + Use only one running instance of SMPlayer + Використовувати тільки один екземпляр SMPlayer + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + Вкажіть цю опцію, якщо Ви бажаєте використовувати вже існуючий екземпляр SMPlayer, відкриваючи інші файли. + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMPlayer повинен слухати порт для отримання команд від інших процесів. Ви можете змінити порт, якщо він використовується іншою програмою. + + + + Default GUI + Графічний інтерфейс за замовчуванням + + + + Mini GUI + Зменшений графічний інтерфейс + + + + GUI + Графічний інтерфейс + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + Виберіть графічний інтерфейс для програми, якому ви надаєте перевагу. Зараз наявні два: звичайний та міні інтерфейси.<br>Звичайний<b></b> забезпечує традиційні панелі інструментів та керування. <b>Міні</b> забезпечує більш простий інтерфейс без панелів інструментів та з декількома кнопками на панелі керування.<br><b>Примітка:</b> ця опція подіє після наступного запуску SMPlayer. + + + + &GUI + &Графічний інтерфейс + + + + Automatic port + Автоматичний порт + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMPlayer'у необхідно слухати порт, щоб отримувати команди від інших процесів. Якщо ви виберете цю опцію, порт буде вибраний автоматично. + + + + Manual port + Вказаний порт + + + + Port to listen + Порт для прослуховування + + + + &Automatic + &Автоматично + + + + &Manual + В&ручну + + + + Floating control + Виринаюче керування + + + + Animated + Анімоване + + + + If this option is enabled, the floating control will appear with an animation. + Якщо ця опція увімкнена, виринаюче керування з'являтиметься з анімацією. + + + + Width + Ширина + + + + Specifies the width of the control (as a percentage). + Визначає ширину керування (відсотки). + + + + Margin + Поле + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + Ця опція встановлює кількість пікселів, на яку виринаюче керування буде віддалене від низу екрану. Корисно, коли екраном є телевізором, оскільки краї можуть унеможливлювати видимість керування. + + + + Display in compact mode too + Показувати також в стислому режимі + + + + If this option is enabled, the floating control will appear in compact mode too. Warning: the floating control has not been designed for compact mode and it might not work properly. + Якщо опція увімкнена, виринаюче керування з'являтиметься також в стислому режимі. Попередження: виринаюче керування не розраховувалось для стислого режиму і може не працювати вірно. + + + + Bypass window manager + Оминати менеджер вікон + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + Якщо опція увімкнена, керування відображається оминаючи менеджер вікон. Вимкніть цю опції, якщо виринаюче керування працює невірно з вашим менеджером вікон. + + + + &Floating control + &Виринаюче керування + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + Виринаюче керування з'являється в режимі на весь екран, коли мишу пересунути донизу екрану. + + + + &Animated + &Анімоване + + + + &Width: + &Ширина: + + + + 0 + 0 + + + + &Margin: + &Поле: + + + + Display in &compact mode too + Показувати також в &стислому режимі + + + + &Bypass window manager + &Оминати менеджер вікон + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + Якщо опція увімкнена, виринаюче керування з'являтиметься також в стислому режимі. <b>Попередження:</b> виринаюче керування не розраховувалось для стислого режиму і може не працювати вірно. + + + + Mpc GUI + Графічний інтерфейс Mpc + + + + PrefPerformance + + + Performance + Швидкодія + + + + &Performance + &Швидкодія + + + + Priority + Перевага + + + + Select the priority for the MPlayer process. + Вкажіть перевагу процесу MPlayer. + + + + realtime + реальний час + + + + high + висока + + + + abovenormal + вища за звичайну + + + + normal + звичайна + + + + belownormal + нижча за звичайну + + + + idle + низька + + + + KB + Кбайт + + + + Setting a cache may improve performance on slow media + Установки кешу можуть поліпшити чи погіршити швидкодію + + + + Allow frame drop + Допускати випадання кадрів + + + + Synchronization + Синхронізація + + + + Audio/video auto synchronization + Автосинхронізація звука/відео + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + Вкажіть перевагу для процесу mplayer, що доступний для Windows.<br><b>УВАГА:</b> Використання переваги реального часу може заморозити систему. + + + + Skip displaying some frames to maintain A/V sync on slow systems. + Пропускати деякі кадри для забезпечення A/V синхронізації на повільних системах. + + + + Allow hard frame drop + Допускати жорстке випадання кадрів + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + Збільшене випадання кадрів (декодування з перервами). Призводить до спотворення зображення! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + Поступове регулювання A/V синхронізації, основане на розмірах звукових затримок. + + + + Priorit&y: + &Перевага: + + + + &Allow frame drop + &Дозволити випадання кадрів + + + + Allow &hard frame drop (can lead to image distortion) + Дозволитии &жорстке випадання кадрів (може спотворити зображення) + + + + Audio/&video auto synchronization + Автосинхронізація звука/&відео + + + + Fact&or: + Пок&азник: + + + + &Fast audio track switching + &Швидке перемикання звукових доріжок + + + + Fast &seek to chapters in dvds + Швидкий &пошук звукових доріжок + + + + Fast audio track switching + Швидке перемикання звукових доріжок + + + + Fast seek to chapters in dvds + Швидкий пошук глав для DVD + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + Якщо увімкнено, буде використовуватись найшвидший метод для пошуку розділів, але не працює з деякими дисками. + + + + Skip loop filter + Пропустити фільтр петлі + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + Можливі значення:<br> <b>Yes</b>: спроба використати найшвидший метод вибору звукової доріжки (може не працювати на деяких форматах).<br> <b>No</b>: MPlayer буде перезапускатися при кожній зміні звукової доріжки.<br> <b>Auto</b>: SMPlayer вирішить як вчинити відповідно до версії MPlayer. + + + + Cache for files + Кеш для файлів + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + Ця опція вказує (в кілобайтах) скільки пам'яті використовувати для прекешування файлу. + + + + Cache for streams + Кеш для потоків + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + Ця опція вказує (в кілобайтах) скільки пам'яті використовувати для прекешування URL. + + + + Cache for DVDs + Кеш для DVD + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + Ця опція вказує (в кілобайтах) скільки пам'яті використовувати для прекешування DVD.<br><b>Увага:</b> Пошук не може працювати правильно (включаючи перемикання глав) при використанні кешу для DVD. + + + + &Cache + &Кеш + + + + Cache for &DVDs: + Кеш для &DVD: + + + + Cache for &local files: + Кеш для &локальних файлів: + + + + Cache for &streams: + Кеш для &потоків: + + + + Enabled + Увімкнено + + + + Skip (always) + Пропускати (завжди) + + + + Skip only on HD videos + Пропускати лише на HD відео + + + + Loop &filter + &Фільтр петлі + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + Ця опція дозволяє пропустити фільтр петлі (він же deblocking) при декодуванні H.264. Оскільки фільтрація кадрів підтримується для декодування залежних кадрів, це може погіршити якість ніж без виконання deblocking, наприклад MPEG-2 відео. Принаймні, для високого бітрейту HDTV це забезпечує більше прискорення без видимого погіршення якості. + + + + Possible values: + Можливі значення: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>Увімкнено</b>: фільтр петлі не пропускається + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>Пропускати (завжди)</b>: фільт петлі пропущений незалежно від роздільної здатності відео + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>Пропускати лише на HD відео</b>: фільтр петлі буде пропущено тільки для відео з висотою %1 чи більше. + + + + Cache + Кеш + + + + Cache for audio CDs + Кеш для аудіо CD + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + Ця опція вказує (в кілобайтах) скільки пам'яті використовувати для прикешування аудіо CD. + + + + Cache for &audio CDs: + Кеш для &аудіо CD: + + + + Cache for VCDs + Кеш для VCD + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + Ця опція вказує (в кілобайтах) скільки пам'яті використовувати для прекешування VCD. + + + + Cache for &VCDs: + Кеш для &VCD: + + + + Threads for decoding + Потоки для декодування + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + Встановлює кількість потоків, що використовуються для декодування. Тільки для MPEG-1/2 та H.264 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + &Потоки для декодування (тільки для MPEG-1/2 та H.264): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + Вкажіть перевагу для процесу mplayer, що доступний для Windows.<br><b>Застереження:</b> Використання переваги реального часу може заблокувати систему. + + + + PrefPlaylist + + + Playlist + Перелік відтворення + + + + Automatically add files to playlist + Автоматично додавати файли до переліку + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + Якщо опція увімкнена, кожного разу коли відкривається файл, SMPlayer спочатку очистить перелік відтворення, а потім додасть файл до нього. У випадку DVD, CD та VCD всі доріжки диску будуть додані до переліку. + + + + Add consecutive files + Додати послідовні файли + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + Якщо ця опція увімкнена, SMPlayer шукатиме послідовні файли (наприклад video_1.avi, video_2.avi...) та якщо знайде, всі додасть до переліку. + + + + &Playlist + &Перелік відтворення + + + + &Automatically add files to playlist + &Автоматично додавати файли до переліку + + + + Add &consecutive files + Додати &послідовні файли + + + + PrefSubtitles + + + Subtitles + Субтитри + + + + Choose a ttf file + Вибрати ttf файл + + + + Truetype Fonts + Шрифти Truetype + + + + &Subtitles + &Субтитри + + + + Autoload + Автовідкриття + + + + Same name as movie + Така ж назва як і у кліпа + + + + All subs containing movie name + Підключати субтитри, які містять назву кліпу + + + + All subs in directory + Всі субтитри теки + + + + Position + Позиція + + + + 0 + 0 + + + + Top + Верх + + + + Bottom + Низ + + + + Font + Шрифт + + + + Select the font which will be used for subtitles (and OSD): + Виберіть шрифт для субтитрів (та OSD): + + + + Size + Розмір + + + + No autoscale + Без автомасштабування + + + + Proportional to movie height + Пропорційно до висоти кліпу + + + + Proportional to movie width + Пропорційно до ширини кліпу + + + + Proportional to movie diagonal + Пропорційно до діагоналі кліпу + + + + Subtitle position + Позиція субтитрів + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + Ця опція вказує позицію субтитрів на вікні відео. <i>100</i> задає в самому низу, тоді як <i>0</i> задає самий верх. + + + + Au&toload subtitles files (*.srt, *.sub...): + Ав&тозавантаження субтитрів (*.srt, *.sub...): + + + + S&elect first available subtitle + Вибрати &перші доступні субтитри + + + + &Default subtitle encoding: + &Кодування субтитрів за замовчуванням: + + + + Default &position of the subtitles on screen + Позиція субтитрів на &екрані за умовчанням + + + + &Include subtitles on screenshots + &Включати субтитри до знімків екрану + + + + &TTF font: + Шрифт &TTF: + + + + S&ystem font: + С&истемний шрифт: + + + + A&utoscale: + Авто&масштабування: + + + + Select the subtitle autoload method. + Вкажіть метод автозавантаження субтитрів. + + + + Select first available subtitle + Вибрати перші доступні субтитри + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + Якщо один чи більше субтитрів доступні, один з них буде вибраний автоматично, як правило перший, хоча якщо один з них буде відповідати бажаній мові користувача, вона буде використана. + + + + Default subtitle encoding + Кодування субтитрів за замовчуванням + + + + Include subtitles on screenshots + Включати субтитри до знімків екрану + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + Якщо ця опція увімкнена, субтитри буде включено до знімків екрану. Примітка: іноді це може бути незручно. + + + + TTF font + Шрифт TTF + + + + System font + Системний шрифт + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + Ви можете вказати системний шрифт для використання з субтитрами та екранною індикацією. <b>Примітка:</b> потрібен MPlayer з підтримкою fontconfig. + + + + Autoscale + Автомасштабування + + + + Select the subtitle autoscaling method. + Виберіть метод автомасштабування субтитрів. + + + + Text color + Колір тексту + + + + Select the color for the text of the subtitles. + Виберіть колір тексту субтитрів. + + + + Border color + Колір краю + + + + Select the color for the border of the subtitles. + Виберіть колір краю субтитрів. + + + + Select the encoding which will be used for subtitle files by default. + Виберіть кодування, яке буде використовуватись для файлів субтитрів за замовчуванням. + + + + Try to autodetect for this language + Спробувати автоматично визначити для цієї мови + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + При увімкненні цієї опції буде здійснено спробу автоматичного визначення кодування для субтитрів для даної мови. При невдалому автовизначенні кодування буде повернуте за замовчанням. Ця опція потребує версії MPlayer, зібраного з підтримкою ENCA. + + + + Subtitle language + Мова субтитрів + + + + Select the language for which you want the encoding to be guessed automatically. + Вкажіть мову, для якої Ви б хотіли застосовувати автовизначення кодування. + + + + Encoding + Кодування + + + + Try to a&utodetect for this language: + Спробувати а&втовизначення для цієї мови: + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + Тут Ви можете обрати шрифт ttf, який буде використаний для субтитрів. Зазвичай Ви можете знайти багато шрифтів ttf в %1 + + + + Outline + Обрис + + + + Italic + Курсив + + + + Bold + Жирний + + + + Colors + Кольори + + + + Margins + Поля + + + + Alignment + Вирівнювання + + + + Left + horizontal alignment + Ліворуч + + + + Centered + horizontal alignment + Посередині + + + + Right + horizontal alignment + Праворуч + + + + Bottom + vertical alignment + Знизу + + + + Middle + vertical alignment + Посередині + + + + Top + vertical alignment + Зверху + + + + Outline + border style + Обрис + + + + Opaque box + border style + непрозорий прямокутник + + + + Select the font for the subtitles. + Виберіть шрифт для субтитрів. + + + + The size in pixels. + Розмір в пікселях. + + + + If checked, the text will be displayed in <b>bold</b>. + Якщо вибрано, текст буде відображено <b>жирним</b>. + + + + If checked, the text will be displayed in <i>italic</i>. + Якщо вибрано, текст буде відображено <b>курсивом</b>. + + + + Left margin + Відступ ліворуч + + + + Specifies the left margin in pixels. + Визначає відступ ліворуч в пікселях. + + + + Right margin + Відступ праворуч + + + + Specifies the right margin in pixels. + Визначає відступ праворуч в пікселях. + + + + Vertical margin + Відступ по вертикалі + + + + Specifies the vertical margin in pixels. + Визначає відступ по вертикалі в пікселях. + + + + Horizontal alignment + Вирівнювання по горизонталі + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + Визначає вирівнювання по горизонталі. Можливі значення: ліворуч, посередині, праворуч. + + + + Vertical alignment + Вирівнювання по вертикалі + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + Визначає вирівнювання по вертикалі. Можливі значення: знизу, посередині, зверху. + + + + Border style + Стиль обрамлення + + + + Specifies the border style. Possible values: outline and opaque box. + Визначає стиль обрамлення. Можливі значення: обрис, непрозорий прямокутник. + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + Якщо стиль обрамлення встановлений як <i>обрис</i>, ця опція визначає ширину обрамлення навкруги тексту в пікселях. + + + + Shadow + Тінь + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + Якщо стиль обрамлення встановлений як <i>обрис</i>, ця опція визначає глибину тіні, що падає за текстом в пікселях. + + + + Si&ze: + &Розмір: + + + + Bol&d + &Жирний + + + + &Italic + &Курсив + + + + &Text: + &Текст: + + + + &Border: + &Обрамлення: + + + + L&eft: + &Ліворуч: + + + + &Right: + &Праворуч: + + + + Verti&cal: + По &вертикалі: + + + + &Horizontal: + По &горизонталі: + + + + &Vertical: + По вер&тикалі: + + + + Border st&yle: + &Стиль обрамлення: + + + + &Outline: + Об&рис: + + + + Shado&w: + &Тінь: + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + Наступна опція дозволяє вам визначити стиль, що буде використовуватися в нестилізованих субтитрах (srt, sub...). + + + + Enable normal subtitles + Увімкнути звичайні субтитри + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + Натисніть на цю кнопку, щоб вибрати звичайні субтитри. Цей вид субтитрів може відображати тільки білі субтитри. + + + + Enable SSA/ASS subtitles + Увімкнути субтитри SSA/ASS + + + + Normal subtitles + Звичайні субтитри + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + Ця опція НЕ змінює розмір субтитрів в поточному відео. Щоб це зробити, використовуйте опції <i>Розмір+</i> та <i>Розмір-</i> в меню субтитрів. + + + + Default scale + Масштаб за замовчуванням + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + Ця опція визначає масштаб шрифту за замовчуванням для звичайних субтитрів, що буде застосований для нових відкритий файлів. + + + + SSA/ASS subtitles + Субтитри SSA/ASS + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + Ця опція визначає масштаб шрифту за замовчуванням для субтитрів SSA/ASS, що буде застосований для нових відкритий файлів. + + + + Line spacing + Відстань між рядками + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + Це визначає відстань, значення якої буде використано для розділення рядків. Може мати від'ємне значення. + + + + &Font and colors + &Шрифт та кольори + + + + Enable &normal subtitles + Увімкнути &звичайні субтитри + + + + Enable SSA/&ASS subtitles + Увімкнути субтитри &SSA/ASS + + + + Default s&cale: + Ма&сштаб за замовчуванням: + + + + Defa&ult scale: + &Масштаб за замовчуванням: + + + + &Line spacing: + Відстань між &рядками: + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + Натисніть цю кнопку, щоб увімкнути нову бібліотеку SSA/ASS. Це дозволить відображати субтитри з різними кольорами, шрифтами... + + + + Freetype support + Підтримка Freetype + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + Зазвичай вам не слід вимикати цю опцію. Зробіть це лише якщо ваш MPlayer зібраний без підтримки freetype. <b>Вимикання цієї опції може взагалі унеможливити роботу субтитрів!</b> + + + + Freet&ype support + &Підтримка Freetype + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + Якщо ця опція увімкнена, субтитри буде показано у знімках екрану. <b>Примітка:</b> іноді це може створити незручності. + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - Допомога + + + + OK + Гаразд + + + + Cancel + Скасувати + + + + Apply + Застосувати + + + + Help + Допомога + + + + SMPlayer - Preferences + SMPlayer - Налаштування + + + + QObject + + + This is SMPlayer v. %1 running on %2 + Це SMPlayer v. %1 запущений на %2 + + + + the main window will be closed when the file/playlist finishes. + головне вікно закриється, коли скінчиться відтворення файлу чи переліку. + + + + will show this message and then will exit. + відобразити це повідомлення та вийти. + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + спробувати з'єднатися з віддаленою програмою та передати їй вказану дію. Наприклад: -send-action pause. Інша частина опцій (чи іншого) буде знухтувана і програма закриється. Буде повернено 0 при вдалому виконанні чи -1 при помилці. + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list - перелік дій, розділених пробілами. Дії будуть виконані тільки після завантаження файлу (чи іншого) у порядку, вказаному вами. Для перевірки дії Ви можете передати переметр true чи false. Наприклад: -actions "fullscreen compact true". Лапки потрібні, якщо Ви передаєте більше ніж один параметр. + + + + media + media + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + якщо вже працює інший процес, медіа будуть додані до списку відтворення. Якщо не буде ніякого іншого процесу, ця опція нехтується та файли відкриються в новому екземплярі. + + + + the main window won't be closed when the file/playlist finishes. + не закривати головне вікно після закінчення відтворення файлу чи переліку. + + + + the video will be played in fullscreen mode. + відтворювати відео на повний екран. + + + + the video will be played in window mode. + відтворювати відео у віконному режимі. + + + + Enqueue in SMPlayer + Додати в чергу SMPlayer'а + + + + opens the mini gui instead of the default one. + відкрити міні-інтерфейс замість за замовчуванням. + + + + Restores the old associations and cleans up the registry. + Відновити старі асоціації та почистити реєстр. + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + 'media' - це будь-який файл, який SMPlayer може відкрити. Це може бути локальний файл, DVD (нарпиклад dvd://1), інтернет-потік (наприклад mms://....) чи локальний список у форматі m3u чи pls. При використанні опції -playlist SMPlayer передає список до MPlayer, який його і опрацьовує, але не SMPlayer. + + + + Usage: + Використання: + + + + directory + тека + + + + action_name + ім'я_дії + + + + action_list + список_дії + + + + opens the default gui. + відкрити інтерфейс за замовчуванням. + + + + subtitle_file + субтитри_файл + + + + specifies the subtitle file to be loaded for the first video. + визначає файл з субтитрами, що завантажується для першого відео. + + + + %1 second(s) + + %1 секунда + %1 секунди + %1 секунд + + + + + %1 minute(s) + + %1 хвилина + %1 хвилини + %1 хвилин + + + + + %1 and %2 + %1 та %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + визначає теку, де smplayer зберігатиме свої файли налаштувань (smplayer.ini, smplayer_files.ini...) + + + + disabled + aspect_ratio + вимкнено + + + + auto + aspect_ratio + автоматично + + + + unknown + aspect_ratio + невідомо + + + + opens the mpc gui. + відкриває графічний інтерфейс mpc. + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + Помилка ZIP/UNZIP API: %1 + + + + SeekWidget + + + icon + піктограма + + + + label + мітка + + + + ShortcutGetter + + + Modify shortcut + Змінити комбінацію + + + + Press the key combination you want to assign + Натисніть комбінацію клавіш, яку Ви бажаєте задати + + + + Clear + Очистити + + + + Capture + Захопити + + + + Capture keystrokes + Комбінація клавіш захоплення + + + + SubChooserDialog + + + Subtitle selection + Вибір субтитрів + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + Цей архів містить більш ніж один файл субтитрів. Будь ласка, виберіть один, який хочете витягти. + + + + Select All + Вибрати всі + + + + Select None + Не вибирати жодного + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - Пошук + + + + &Jump to: + &Перейти до: + + + + TristateCombo + + + Auto + Авто + + + + Yes + Так + + + + No + Ні + + + + VideoEqualizer + + + Contrast + Контрастність + + + + Brightness + Яскравість + + + + Hue + Колір + + + + Saturation + Насиченість + + + + Gamma + Гама + + + + &Reset + Об&нулити + + + + &Set as default values + &Встановити значення за замовчуванням + + + + Use the current values as default values for new videos. + Використовувати поточні значення як за замовчуванням для нових кліпів. + + + + Set all controls to zero. + Скинути все на нуль. + + + + Video Equalizer + Відеоеквалайзер + + + + Information + Інформація + + + + The current values have been stored to be used as default. + Поточні значення збережені, щоб використовуватись за замовчуванням. + + + + VideoPreview + + + Video preview + Попередній перегляд відео + + + + Cancel + Скасувати + + + + Generated by SMPlayer + Згенеровано SMPlayer + + + + Creating thumbnails... + Створення мініатюр... + + + + Size: %1 MB + Розмір: %1 Мб + + + + Length: %1 + Довжина: %1 + + + + Save file + Зберегти файл + + + + Images (*.png *.jpg) + Зображення (*.png *.jpg) + + + + Error saving file + Помилка збереження файлу + + + + The file couldn't be saved + Файл не може бути збережений + + + + Error + Помилка + + + + The following error has occurred while creating the thumbnails: + Сталася наступна помилка під час створення мініатюр: + + + + The temporary directory (%1) can't be created + Тимчасова тека (%1) не може бути створена + + + + The mplayer process didn't run + Процес mplayer не запустився + + + + Resolution: %1x%2 + Роздільна здатність: %1x%2 + + + + Video format: %1 + Формат відео: %1 + + + + Frames per second: %1 + Кадрів за секунду: %1 + + + + Aspect ratio: %1 + Співвідношення сторін: %1 + + + + Video bitrate: %1 kbps + Бітрейт відео: %1 кбіт/с + + + + Audio bitrate: %1 kbps + Бітрейт аудіо: %1 кбіт/с + + + + Audio rate: %1 Hz + Частота аудіо: %1 Гц + + + + The file %1 can't be loaded + Файл %1 не може бути завантажений + + + + No filename + Немає назви файлу + + + + The mplayer process didn't start while trying to get info about the video + Процес mplayer не запустився під час спроби отримання інформації про відео + + + + The length of the video is 0 + Довжина відео: 0 + + + + The file %1 doesn't exist + Файл %1 не існує + + + + Images + Зображення + + + + No info + Немає інформації + + + + %1 kbps + %1 кбіт/с + + + + %1 Hz + %1 Гц + + + + Video bitrate: %1 + Бітрейт відео: %1 + + + + Audio bitrate: %1 + Бітрейт аудіо: %1 + + + + Audio rate: %1 + Частота аудіо: %1 + + + + VideoPreviewConfigDialog + + + Default + За замовчуванням + + + + Video Preview + Попередній перегляд відео + + + + &File: + &Файл: + + + + &Columns: + &Стовпці: + + + + &Rows: + &Рядки: + + + + Add playing time to thumbnails + Додати час програвання до мініатюри + + + + &Aspect ratio: + &Співвідношення сторін: + + + + &Seconds to skip at the beginnning: + Пропустити &секунд на початку: + + + + &Maximum width: + Найбільша &ширина: + + + + The preview will be created for the video you specify here. + Попередній перегляд буде створено для відео, яке ви вкажете тут. + + + + The thumbnails will be arranged on a table. + Мініатюри будуть розташовані в таблицею. + + + + This option specifies the number of columns of the table. + Ця опція визначає кількість стовпців таблиці. + + + + This option specifies the number of rows of the table. + Ця опція визначає кількість рядків таблиці. + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + Якщо ви виберете цю опцію, час програвання буде відображений знизу кожної мініатюри. + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + Якщо співвідношення сторів відео невірне, ви тут можете визначити інше. + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + Зазвичай перший кадр чорний, тому гарною думкою є пропустити декілька секунд на початку відео. Ця опція дозволяє визначити скільки секунд буде пропущено. + + + + This option specifies the maximum width in pixels that the generated preview image will have. + Ця опція визначає найбільшу ширину в пікселях, що будуть мати створені мініатюри. + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + Деякі кадри будуть витягнені з відео в порядку створення попереднього перегляду. Тут ви можете обрати формат зображення для здобутих кадрів. PNG може дати кращу якість. + + + + Add playing &time to thumbnails + Додати &час програвання до мініатюр + + + + &Extract frames as + Витягнути &кадри як + + + + Enter here the DVD device or a folder with a DVD image. + Введіть пристрій DVD або теку з образом DVD. + + + + &DVD device: + Пристрій &DVD: + + + + VolumeSliderAction + + + Volume + Гучність + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_zh_CN.ts b/plugins/smplayer_plugin/translations/smplayer_zh_CN.ts new file mode 100644 index 000000000..76c99a874 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_zh_CN.ts @@ -0,0 +1,7328 @@ + + + + About + + + Version: %1 + 版本: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + 这个软件是自由软件; 你可以在自由软件基金会发布的 GPL 或 GPL2 或之后版本下修改/重新发布它。 + + + + The following people have contributed with translations: + 以下对翻译有贡献: + + + + German + 德语 + + + + Slovak + 斯洛伐克语 + + + + Italian + 意大利语 + + + + French + 法语 + + + + %1, %2 and %3 + %1,%2和%3 + + + + Simplified-Chinese + 简体中文 + + + + Russian + 俄罗斯语 + + + + %1 and %2 + %1 和 %2 + + + + Hungarian + 匈牙利语 + + + + Polish + 波兰语 + + + + Japanese + 日语 + + + + Dutch + 荷兰语 + + + + Ukrainian + 乌克兰语 + + + + Portuguese - Brazil + 葡萄牙语 - 巴西 + + + + Georgian + 乔治亚语 + + + + Czech + 捷克语 + + + + Bulgarian + 保加利亚语 + + + + Turkish + 土耳其语 + + + + Swedish + 瑞典语 + + + + Serbian + 赛尔维亚语 + + + + Traditional Chinese + 繁体中文 + + + + Romanian + 罗马尼亚语 + + + + Portuguese - Portugal + 葡萄牙语 - 葡萄牙 + + + + Greek + 希腊语 + + + + Finnish + 芬兰语 + + + + <b>%1</b>: %2 + <b>%1</b>:%2 + + + + <b>%1</b> (%2) + <b>%1</b> (%2) + + + + About SMPlayer + 关于 SMPlayer + + + + &Info + 信息(&I) + + + + icon + 图标 + + + + &Contributions + 贡献(&C) + + + + &Translators + 翻译(&T) + + + + &License + 协议(&L) + + + + Visit our web for updates: + 请访问我们的网站获取更新: + + + + Get help in our forum: + 从我们的论坛获取帮助: + + + + You can support SMPlayer by making a donation. + 您可以通过捐赠来支持 SMPlayer。 + + + + More info + 更多信息 + + + + Korean + 朝鲜语 + + + + Macedonian + 马其顿语 + + + + Basque + 巴斯克语 + + + + Using MPlayer %1 + 使用 MPlayer %1 + + + + Catalan + 西班牙语 + + + + Portable Edition + 便携式版本 + + + + Using Qt %1 (compiled with Qt %2) + 便用 Qt %1 (由 Qt %2 编译) + + + + Slovenian + 斯洛文尼亚语 + + + + Arabic + 阿拉伯语 + + + + Kurdish + 库德语 + + + + Galician + 加里西亚语 + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + 名字 + + + + Description + 描述 + + + + Shortcut + 快捷键 + + + + &Save + 保存(&S) + + + + &Load + 加载(&L) + + + + Key files + Key 文件 + + + + Choose a filename + 选择一个文件名 + + + + Confirm overwrite? + 是否覆盖? + + + + The file %1 already exists. +Do you want to overwrite? + 文件 %1 己存在。 +是否覆盖? + + + + Choose a file + 选择一个文件 + + + + Error + 错误 + + + + The file couldn't be saved + 不能保存文件 + + + + The file couldn't be loaded + 不能加载文件 + + + + &Change shortcut... + 修改快捷键(&C)... + + + + AudioEqualizer + + + Audio Equalizer + 音频均衡器 + + + + 31.25 Hz + 31.25 Hz + + + + 62.50 Hz + 62.50 Hz + + + + 125.0 Hz + 125.0 Hz + + + + 250.0 Hz + 250.0 Hz + + + + 500.0 Hz + 500.0 Hz + + + + 1.000 kHz + 1.000 kHz + + + + 2.000 kHz + 2.000 kHz + + + + 4.000 kHz + 4.000 kHz + + + + 8.000 kHz + 8.000 kHz + + + + 16.00 kHz + 16.00 kHz + + + + &Apply + 应用(&A) + + + + &Reset + 重置(&R) + + + + &Set as default values + 设为默认(&S) + + + + Use the current values as default values for new videos. + 将当前值做为新的视频的默认值。 + + + + Set all controls to zero. + 全部置 0。 + + + + Information + 信息 + + + + The current values have been stored to be used as default. + 当前值被保存为默认值。 + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - Mplayer 日志 + + + + SMPlayer - smplayer log + SMPlayer - SMPlayer 日志 + + + + &Open + 打开(&O) + + + + &Play + 播放(&P) + + + + &Video + 视频(&V) + + + + &Audio + 音频(&A) + + + + &Subtitles + 字幕(&S) + + + + &Browse + 浏览(&B) + + + + Op&tions + 选项(&T) + + + + &Help + 帮助(&H) + + + + &File... + 文件(&F)... + + + + D&irectory... + 目录(&I)... + + + + &Playlist... + 播放列表(&P)... + + + + &DVD from drive + 从设备打开 &DVD + + + + D&VD from folder... + 从目录打开 D&VD... + + + + &URL... + &URL... + + + + &Clear + 清空(&C) + + + + &Recent files + 最近打开的文件(&R) + + + + P&lay + 播放(&L) + + + + &Pause + 暂停(&P) + + + + &Stop + 停止(&S) + + + + &Frame step + 单帧步进(&F) + + + + &Normal speed + 常速(&N) + + + + &Halve speed + 半速(&H) + + + + &Double speed + 两倍速(&D) + + + + Speed &-10% + 速度 &-10% + + + + Speed &+10% + 速度 &+10% + + + + Sp&eed + 速度(&E) + + + + &Repeat + 重复(&R) + + + + &Fullscreen + 全屏(&F) + + + + &Compact mode + 简洁模式(&C) + + + + Si&ze + 大小(&Z) + + + + 4:3 &Letterbox + 4:3 &Letterbox + + + + 16:9 L&etterbox + 16:9 L&etterbox + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &to 16:9 + + + + &Aspect ratio + 外观比例(&A) + + + + &None + 无(&N) + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + Linear &Blend + + + + &Deinterlace + 反拉丝(&D) + + + + &Postprocessing + 后期处理(&P) + + + + &Autodetect phase + 自动探测(&A) + + + + &Deblock + &Deblock + + + + De&ring + De&ring + + + + Add n&oise + Add n&oise + + + + F&ilters + 过滤器(&I) + + + + &Equalizer + 均衡器(&E) + + + + &Screenshot + 截图(&S) + + + + S&tay on top + 置顶(&T) + + + + &Extrastereo + 扩展立体声(&E) + + + + &Karaoke + 卡拉O&K + + + + &Filters + 过滤器(&F) + + + + &Stereo + 立体声(&S) + + + + &4.0 Surround + &4.0 环绕 + + + + &5.1 Surround + &5.1 环绕 + + + + &Channels + 声道(&C) + + + + &Left channel + 左声道(&L) + + + + &Right channel + 右声道(&R) + + + + &Stereo mode + 立体声模式(&M) + + + + &Mute + 静音(&M) + + + + Volume &- + 音量 &- + + + + Volume &+ + 音量 &+ + + + + &Delay - + 延时 - (&D) + + + + D&elay + + 延时 + (&E) + + + + &Select + 选择(&S) + + + + &Load... + 加载(&L)... + + + + Delay &- + 延时 &- + + + + Delay &+ + 延时 &+ + + + + &Up + 上移(&U) + + + + &Down + 下移(&D) + + + + &Title + 标题(&T) + + + + &Chapter + 章节(&C) + + + + &Angle + 角度(&A) + + + + &Playlist + 播放列表(&P) + + + + &Show frame counter + 显示帧记数(&S) + + + + &Disabled + 禁用(&D) + + + + &Seek bar + 定位条(&S) + + + + &Time + 时间(&T) + + + + Time + T&otal time + 时间 + 总时间(&O) + + + + &OSD + OSD(&O) + + + + &View logs + 查看日志(&V) + + + + P&references + 首选项(&R) + + + + About &Qt + 关于 &Qt + + + + About &SMPlayer + 关于 &SMPlayer + + + + <empty> + <无> + + + + Video + 视频 + + + + Audio + 音频 + + + + Playlists + 播放列表 + + + + All files + 所有文件 + + + + Choose a file + 选择一个文件 + + + + SMPlayer - Information + SMPlayer - 信息 + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + 还没有设置 CDROM / DVD 设备。 +你可以在下面显现的配置对话框里设置。 + + + + Choose a directory + 选择一个目录 + + + + Subtitles + 字幕 + + + + About Qt + 关于 Qt + + + + Playing %1 + 播放 %1 + + + + Pause + 暂停 + + + + Stop + 停止 + + + + Play / Pause + 播放 / 暂停 + + + + Pause / Frame step + 暂停 / 单帧步进 + + + + U&nload + 卸载(&N) + + + + V&CD + V&CD + + + + C&lose + 关闭(&L) + + + + View &info and properties... + 查看属性和信息(&I)... + + + + Zoom &- + 缩小(&-) + + + + Zoom &+ + 放大(&+) + + + + &Reset + 重置(&R) + + + + Move &left + 左移(&L) + + + + Move &right + 右移(&R) + + + + Move &up + 上移(&U) + + + + Move &down + 下移(&D) + + + + &Pan && scan + 全景浏览(&P) + + + + &Previous line in subtitles + 前一行字幕(&P) + + + + N&ext line in subtitles + 后一行字幕(&E) + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + 减小音量(2) + + + + Inc volume (2) + 增大音量(2) + + + + Exit fullscreen + 退出全屏 + + + + OSD - Next level + OSD - 下一级别 + + + + Dec contrast + 减少对比度 + + + + Inc contrast + 增加对比度 + + + + Dec brightness + 减少亮度 + + + + Inc brightness + 增大亮度 + + + + Dec hue + 减少色调 + + + + Inc hue + 增大色调 + + + + Dec saturation + 减小饱和度 + + + + Dec gamma + 减小 Gamma + + + + Next audio + 下一音轨 + + + + Next subtitle + 下一字幕 + + + + Next chapter + 下一章节 + + + + Previous chapter + 前一章节 + + + + Inc saturation + 增大饱和度 + + + + Inc gamma + 增大 Gamma + + + + &Load external file... + 加载外部音频(&L)... + + + + &Kerndeint + Kerndeint(&K) + + + + &Yadif (normal) + Yadif (一般)(&Y) + + + + Y&adif (double framerate) + Yadif (双倍帧率)(&A) + + + + &Next + 下一个(&N) + + + + Pre&vious + 上一个(&V) + + + + Volume &normalization + 规范化声音(&N) + + + + &Audio CD + 音频 CD(&A) + + + + Denoise nor&mal + 降噪(正常)(&M) + + + + Denoise &soft + 降噪(软件)(&S) + + + + Denoise o&ff + 降噪(关闭)(&F) + + + + Use SSA/&ASS library + 使用 SSA/&ASS 库 + + + + Flip i&mage + 裁剪图像(&M) + + + + &Toggle double size + 切换双倍大小(&T) + + + + S&ize - + 大小 -(&I) + + + + Si&ze + + 大小 + (&Z) + + + + Add &black borders + 加边框(&B) + + + + Soft&ware scaling + 软件缩放(&W) + + + + &FAQ + FAQ(&F) + + + + Visualize &motion vectors + 将运动矢量可视化(&M) + + + + &Command line options + 命令行选项(&C) + + + + SMPlayer command line options + SMPlayer 命令行选项 + + + + Enable &closed caption + 允许已关闭的章节(&C) + + + + &Forced subtitles only + 仅强制字幕(&F) + + + + Reset video equalizer + 重置视频均衡 + + + + MPlayer has finished unexpectedly. + MPlayer 异常退出。 + + + + Exit code: %1 + 退出代码: %1 + + + + MPlayer failed to start. + MPlayer 启动失败。 + + + + Please check the MPlayer path in preferences. + 请检查选项中的 MPlayer 路径的设置。 + + + + MPlayer has crashed. + MPlayer 已经崩溃了. + + + + See the log for more info. + 请查看日志已获得更多信息。 + + + + &Rotate + 旋转(&R) + + + + &Off + 关闭(&O) + + + + &Rotate by 90 degrees clockwise and flip + 顺时针旋转90度并倒置(&R) + + + + Rotate by 90 degrees &clockwise + 顺时针旋转90度(&C) + + + + Rotate by 90 degrees counterclock&wise + 逆时针旋转90度(&W) + + + + Rotate by 90 degrees counterclockwise and &flip + 逆时针旋转90度并倒置(&R) + + + + &Jump to... + 跳转到(&J)... + + + + Show context menu + 显示上下文菜单 + + + + Multimedia + 媒体 + + + + E&qualizer + 均衡器(&Q) + + + + Reset audio equalizer + 重置音频均衡 + + + + Find subtitles on &OpenSubtitles.org... + 在 OpenSubtitles.org 上查找字幕(&O)... + + + + Upload su&btitles to OpenSubtitles.org... + 上传字幕到 OpenSubtitles.org (&B)... + + + + &Tips + 提示(&T) + + + + Speed -&4% + 速度 -4%(&4) + + + + &Speed +4% + 速度 +4%(&S) + + + + Speed -&1% + 速度 -1%(&1) + + + + S&peed +1% + 速度 +1%(&P) + + + + &Auto + 自动(&A) + + + + Scree&n + 屏幕(&N) + + + + &Default + 默认(&D) + + + + Mirr&or image + + + + + Next video + 下一视频 + + + + &Track + video + 音轨(&T) + + + + &Track + audio + 音轨(&T) + + + + Warning - Using old MPlayer + 警告 - 使用旧的 MPlayer + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + 您系统中安装的 MPlayer(%1) 的版本已经过时。SMPlayer 将不能很好工作: 一些选项将失效, 字幕选择可能会失败... + + + + Please, update your MPlayer. + 请更新您的 MPlayer。 + + + + (This warning won't be displayed anymore) + (This warning won't be displayed anymore) + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer 还在运行 + + + + S&how icon in system tray + 在系统托盘里显示图标(&H) + + + + &Hide + 隐藏(&H) + + + + &Restore + 恢复(&R) + + + + &Quit + 退出(&Q) + + + + Playlist + 播放列表 + + + + Core + + + Brightness: %1 + 亮度: %1 + + + + Contrast: %1 + 对比度: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + 色调: %1 + + + + Saturation: %1 + 饱和度: %1 + + + + Volume: %1 + 音量: %1 + + + + Zoom: %1 + 缩放: %1 + + + + Font scale: %1 + 字体比例: %1 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + 欢迎使用 SMPlayer + + + + Audio + 音频 + + + + Subtitle + 字幕 + + + + &Main toolbar + 主工具条(&M) + + + + &Language toolbar + 语言工具条(&L) + + + + &Toolbars + 工具条(&T) + + + + EqSlider + + + icon + 图标 + + + + ErrorDialog + + + Hide log + 隐藏日志 + + + + Show log + 显示日志 + + + + MPlayer Error + MPlayer 错误 + + + + icon + 图标 + + + + Error + 错误 + + + + FileDownloader + + + Downloading... + 下载中... + + + + Downloading %1 + 下载 %1 中 + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - 文件属性 + + + + &Information + 信息(&I) + + + + &Demuxer + 解码器(&D) + + + + &Select the demuxer that will be used for this file: + 选择将被用在这个文件的解码器(&S): + + + + &Reset + 重置(&R) + + + + &Video codec + 视频编码(&V) + + + + &Select the video codec: + 选择视频编码(&S): + + + + A&udio codec + 音频编码(&u) + + + + &Select the audio codec: + 选择音频编码(&S): + + + + &MPlayer options + &Mplayer 选项 + + + + Additional Options for MPlayer + MPlayer 的附加选项 + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + 在这里你可以传递额外的选项给 Mplayer。 +请用空格分隔它们。 +示例 : -flip -nosound + + + + &Options: + 选项(&O): + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + 在这里你可以传递附加的视频过滤器。 +请用 "," 分隔它们。不要使用空格! +示例: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + 视频过滤器(&I): + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + 最后是音频过滤器。和视频过滤器的规则一样。 +示例: resample=44100:0:0,volnorm + + + + Audio &filters: + 音频过滤器(&F): + + + + OK + 确定 + + + + Cancel + 取消 + + + + Apply + 应用 + + + + FindSubtitlesWindow + + + Language + 语言 + + + + Name + 名字 + + + + Format + 格式 + + + + Files + 文件 + + + + Date + 日期 + + + + Uploaded by + 上传者 + + + + All + 全部 + + + + Close + 关闭 + + + + &Download + 下载(&D) + + + + &Copy link to clipboard + 复制到剪贴板(&C) + + + + Error + 错误 + + + + Download failed: %1. + 下载失败: %1。 + + + + Connecting to %1... + 连接到 %1 ... + + + + Downloading... + 下载中... + + + + Done. + 完成。 + + + + %1 files available + %1 个可用文件 + + + + Failed to parse the received data. + 对收到的数据解析失败。 + + + + Find Subtitles + 查找字幕 + + + + &Subtitles for + 字幕用于(&S) + + + + &Language: + 语言(&L): + + + + &Refresh + 刷新(&R) + + + + Subtitle saved as %1 + 字幕被保存为 %1 + + + + %1 subtitle(s) extracted + + %1 个字幕被提取 + + + + + Overwrite? + 是否覆盖? + + + + The file %1 already exits, overwrite? + 文件 %1 己存在,是否覆盖? + + + + Error saving file + 保存文件出错 + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + 无法将己下载的文件保存在目录 %1 中 +请检查目录的权限设置。 + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + 常规 + + + + Size + 大小 + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + 长度 + + + + Demuxer + 解码器 + + + + Name + 名字 + + + + Artist + 艺术家 + + + + Author + 作者 + + + + Album + 专辑 + + + + Genre + 流派 + + + + Date + 日期 + + + + Track + 音轨 + + + + Copyright + 版权 + + + + Comment + 注释 + + + + Software + 软件 + + + + Clip info + 剪辑信息 + + + + Video + 视频 + + + + Resolution + 分辨率 + + + + Aspect ratio + 外观比例 + + + + Format + 格式 + + + + Bitrate + 比特率 + + + + %1 kbps + %1 kbps + + + + Frames per second + 帧每秒 + + + + Selected codec + 选择编码器 + + + + Initial Audio Stream + 初始化音频流 + + + + Rate + 比率 + + + + %1 Hz + %1 Hz + + + + Channels + 声道 + + + + Audio Streams + 音频流 + + + + Language + 语言 + + + + empty + + + + + Subtitles + 字幕 + + + + Type + 类型 + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + 流标题 + + + + Stream URL + 流 URL + + + + File + 文件 + + + + InputDVDDirectory + + + Choose a directory + 选择一个目录 + + + + SMPlayer - Play a DVD from a folder + SMPlayer - 从一个目录播放 DVD + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + 您可以从您的硬盘播放 DVD 。只要选择包含 VIDEO_TS 和 AUDIO_TS 目录的文件夹即可。 + + + + Choose a directory... + 选择一个目录... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - 输入 MPlayer 的版本 + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer 不能确定您使用的 MPlayer 的版本。 + + + + Version reported by MPlayer: + MPlayer 报告的版本: + + + + Please, &select the correct version: + 请选择当前的版本(&S): + + + + 1.0rc1 or older + 10rc1 或更新 + + + + 1.0rc2 + 1.0rc2 + + + + Greater than 1.0rc2 + 比 1.0rc2 更新 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - 输入 URL + + + + &URL: + URL(&U): + + + + It's a &playlist + 这是播放列表(&P) + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + 如果选择这个选项,URL 将会被当作播放列表:它将被当成一个文本文件打开同,然后播放里面的 URL。 + + + + Languages + + + Afar + 阿法尔语 + + + + Abkhazian + 阿布哈西亚语 + + + + Afrikaans + 公用荷兰语 + + + + Amharic + 阿比西尼亚官话 + + + + Arabic + 阿拉伯语 + + + + Assamese + 阿萨姆语 + + + + Aymara + 艾马拉语 + + + + Azerbaijani + 阿塞拜疆语 + + + + Bashkir + 巴什基尔语 + + + + Byelorussian + 白俄罗斯语 + + + + Bulgarian + 保加利亚语 + + + + Bihari + 比哈尔语 + + + + Bislama + 比斯克语 + + + + Bengali + 孟加拉语 + + + + Tibetan + 藏语 + + + + Breton + 布里多尼语 + + + + Catalan + 西班牙语 + + + + Corsican + 科西嘉方言 + + + + Czech + 捷克语 + + + + Welsh + 威尔士语 + + + + Danish + 丹麦语 + + + + German + 德语 + + + + Bhutani + 不丹文 + + + + Greek + 希腊语 + + + + English + 英语 + + + + Esperanto + 世界语 + + + + Spanish + 西班牙语 + + + + Estonian + 爱沙尼亚语 + + + + Basque + 巴斯克语 + + + + Persian + 波斯语 + + + + Finnish + 芬兰语 + + + + Fiji + 斐济语 + + + + Faroese + 法罗人语 + + + + French + 法语 + + + + Frisian + 弗里斯兰语 + + + + Irish + 爱尔兰语 + + + + Scots + 苏格兰语 + + + + Galician + 加里西亚语 + + + + Guarani + 巴拉圭语 + + + + Gujarati + 古吉拉特语 + + + + Hausa + 豪撒语 + + + + Hebrew + 希伯来语 + + + + Hindi + 北印度语 + + + + Croatian + 克罗地亚人语 + + + + Hungarian + 匈牙利语 + + + + Armenian + 亚美尼亚语 + + + + Interlingua + 拉丁国际语 + + + + Indonesian + 印尼语 + + + + Interlingue + 拉丁国际文 + + + + Inupiak + 依奴皮维克文 + + + + Icelandic + 冰岛语 + + + + Italian + 意大利语 + + + + Inuktitut + 爱斯基摩文 + + + + Japanese + 日语 + + + + Javanese + 爪哇语 + + + + Georgian + 乔治亚语 + + + + Kazakh + 哈萨克语 + + + + Greenlandic + 格陵兰语 + + + + Cambodian + 柬埔寨语 + + + + Kannada + 埃纳德语 + + + + Korean + 朝鲜语 + + + + Kashmiri + 克什米尔语 + + + + Kurdish + 库德语 + + + + Kirghiz + 吉尔吉斯语 + + + + Latin + 拉丁语 + + + + Lingala + 林加拉语 + + + + Laothian + 老挝语 + + + + Lithuanian + 立陶宛语 + + + + Latvian + 拉脱维亚语 + + + + Malagasy + 马尔加什语 + + + + Maori + 毛利语 + + + + Macedonian + 马其顿语 + + + + Malayalam + 马拉雅拉姆语 + + + + Mongolian + 蒙古语 + + + + Moldavian + 摩尔达维亚语 + + + + Marathi + 马拉地语 + + + + Malay + 马来语 + + + + Maltese + 马尔他语 + + + + Burmese + 缅甸语 + + + + Nauru + 瑙鲁语 + + + + Nepali + 尼泊尔语 + + + + Dutch + 荷兰语 + + + + Norwegian + 挪威语 + + + + Occitan + 奥西坦文 + + + + Oriya + 奥里雅语 + + + + Punjabi + 旁遮普语 + + + + Polish + 波兰语 + + + + Pashto + 普什图语 + + + + Portuguese + 葡萄牙语 + + + + Quechua + 盖丘亚族语 + + + + Kirundi + 基隆迪语 + + + + Romanian + 罗马尼亚语 + + + + Russian + 俄罗斯语 + + + + Kinyarwanda + 基尼阿万达文 + + + + Sanskrit + 梵文 + + + + Sindhi + 信德语 + + + + Sangho + 相浩 + + + + Sinhalese + 僧伽罗语 + + + + Slovak + 斯洛伐克语 + + + + Slovenian + 斯洛文尼亚语 + + + + Samoan + 萨摩亚语 + + + + Shona + 修纳语 + + + + Somali + 索马里语 + + + + Albanian + 阿尔巴尼亚语 + + + + Serbian + 赛尔维亚语 + + + + Siswati + 西斯瓦提文 + + + + Sesotho + 塞索托语 + + + + Sundanese + 巽他语 + + + + Swedish + 瑞典语 + + + + Swahili + 斯瓦希里语 + + + + Tamil + 坦米尔语 + + + + Telugu + 泰卢固语 + + + + Tajik + 塔吉克语 + + + + Thai + 泰国语 + + + + Tigrinya + 提格里尼亚语 + + + + Turkmen + 土库曼语 + + + + Tagalog + 塔加路族语 + + + + Setswana + 塞兹瓦纳语 + + + + Tonga + 汤加语 + + + + Turkish + 土耳其语 + + + + Tsonga + 聪加语 + + + + Tatar + 鞑靼语 + + + + Twi + 契维语 + + + + Uighur + 维吾尔语 + + + + Ukrainian + 乌克兰语 + + + + Urdu + 乌尔都语 + + + + Uzbek + 乌兹别克语 + + + + Vietnamese + 越南语 + + + + Wolof + 沃洛夫语 + + + + Xhosa + 班图语 + + + + Yiddish + 依地语 + + + + Yoruba + 约鲁巴语 + + + + Zhuang + + + + + Chinese + 中文 + + + + Zulu + 祖鲁语 + + + + Portuguese - Brazil + 葡萄牙语 - 巴西 + + + + Portuguese - Portugal + 葡萄牙语 - 葡萄牙 + + + + Simplified-Chinese + 简体中文 + + + + Traditional Chinese + 繁体中文 + + + + Unicode + Unicode + + + + UTF-8 + UTF-8 + + + + Western European Languages + 西欧语 + + + + Western European Languages with Euro + 西欧语(包括欧盟) + + + + Slavic/Central European Languages + 斯拉夫语 + + + + Esperanto, Galician, Maltese, Turkish + 世界语 + + + + Old Baltic charset + 波罗的海语 + + + + Cyrillic + Cyrillic + + + + Modern Greek + 希腊语 + + + + Baltic + 波罗的海 + + + + Celtic + 凯尔特语 + + + + Hebrew charsets + 希伯来语 + + + + Ukrainian, Belarusian + 乌克兰语 + + + + Simplified Chinese charset + 简体中文 + + + + Traditional Chinese charset + 繁体中文 + + + + Japanese charsets + 日本语 + + + + Korean charset + 韩国语 + + + + Thai charset + 泰国语 + + + + Cyrillic Windows + Cyrillic Windows + + + + Slavic/Central European Windows + 斯拉夫语 + + + + Arabic Windows + 阿拉伯语 + + + + Rhaeto-Romance + 里托罗曼斯语 + + + + Serbo-Croatian + 塞尔维亚克罗地亚语 + + + + Volapük + 沃拉普克语 + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + 选择保存文件名 + + + + Confirm overwrite? + 是否覆盖? + + + + Error saving file + 保存文件出错 + + + + The file already exists. +Do you want to overwrite? + 文件己存在。 +是否覆盖? + + + + The log couldn't be saved + 日志不能被保存 + + + + Logs + 日志 + + + + LogWindowBase + + + Close + 关闭 + + + + Copy to clipboard + 复制到剪贴板 + + + + Log Window + 日志窗口 + + + + Save + 保存 + + + + &Close + 关闭(&C) + + + + MiniGui + + + Control bar + 控制条 + + + + MpcGui + + + Control bar + 控制条 + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + All files + 所有文件 + + + + Choose a directory + 选择一个目录 + + + + Choose a file + 选择一个文件 + + + + Choose a filename + 选择一个文件名 + + + + Confirm overwrite? + 是否覆盖? + + + + &Edit + 编辑(&E) + + + + Edit name + 编辑名字 + + + + Length + 长度 + + + + Name + 名字 + + + + &Play + 播放(&P) + + + + Playlists + 播放列表 + + + + Select one or more files to open + 选择打开一个或多个文件 + + + + The file %1 already exists. +Do you want to overwrite? + 文件 %1 己存在。 +是否覆盖? + + + + Type the name that will be displayed in the playlist for this file: + 给这个文件输入一个显现在播放列表的名字: + + + + &Load + 加载(&L) + + + + &Save + 保存(&S) + + + + &Next + 下一个(&N) + + + + Pre&vious + 上一个(&V) + + + + Move &up + 上移(&U) + + + + Move &down + 下移(&D) + + + + &Repeat + 重复(&R) + + + + S&huffle + 打乱(&H) + + + + Add &current file + 添加当前文件(&C) + + + + Add &file(s) + 添加文件(&F) + + + + Add &directory + 添加目录(&D) + + + + Remove &selected + 移除选中(&S) + + + + Remove &all + 全部移除(&A) + + + + SMPlayer - Playlist + SMPlayer - 播放列表 + + + + Add... + 添加... + + + + Remove... + 移除... + + + + Playlist modified + 播放列表己修改 + + + + There are unsaved changes, do you want to save the playlist? + 有没有保存的修改, 您想保存播放列表吗? + + + + Preferences + 首选项 + + + + PlaylistPreferences + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + 请勾选此选项如果您希望添加一个目录的同时也添加子目录中的文件。否则只有当前目录的文件才会将加入。 + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + 勾选此选项来对加到播放列表的文件获取一些信息。这将可以显示文件名(如果可用的话)和影片长度。否则这些信息只有当文件被播放时才能显示。小心: 这个选项可能很慢,尤其当您添加大量文件的时候。 + + + + Playlist - Preferences + 播放列表 - 首选项 + + + + &Add files in directories recursively + 递归添加目录中的文件(&A) + + + + Automatically get &info about files added + 自动获取添加文件的信息(&I) + + + + &Save copy of playlist on exit + 退出时保存播放列表(&S) + + + + &Play files from start + 在头开始播放文件(&P) + + + + PrefAdvanced + + + Advanced + 高级 + + + + Auto + 自动 + + + + &Advanced + 高级(&A) + + + + icon + 图标 + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + 在这里你可以传递额外的选项给 Mplayer。 +请用空格分隔它们。 +示例 : -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + 在这里你可以传递附加的视频过滤器。 +请用 "," 分隔它们。不要使用空格! +示例: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + 最后是音频过滤器。和视频过滤器的规则一样。 +示例: resample=44100:0:0,volnorm + + + + Log MPlayer output + 记录 MPlayer 的输出 + + + + Log SMPlayer output + 记录 SMPlayer 的输出 + + + + This option is mainly intended for debugging the application. + 此选项主要用于调试。 + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + 选择这个选项可以减少闪烁。但也可能造成视频不能正常显示。 + + + + Filter for SMPlayer logs + 过滤 SMPlayer 的记录 + + + + &Monitor aspect: + 锁定外观(&M): + + + + &Run MPlayer in its own window + 让 Mplayer 在自己的窗口里运行(&R) + + + + &Options: + 选项(&O): + + + + V&ideo filters: + 视频过滤器(&I): + + + + Audio &filters: + 音频过滤器(&F): + + + + &Colorkey: + 颜色代码(&C): + + + + Log &SMPlayer output + 记录 SMPlayer 的输出(&S) + + + + &Filter for SMPlayer logs: + 过滤 SMPlayer 的记录(&F): + + + + C&hange... + 更改(&H)... + + + + Logs + 日志 + + + + Log MPlayer &output + 记录 MPlayer 的输出(&O) + + + + Options for MP&layer + Mplayer 选项(&L) + + + + Autosave MPlayer log + 自动保存 MPlayer 的日志 + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + 如果勾选此选项, 将在每次播放新的文件时保存 MPlayer 的日志到指定的文件。这是为外部应用程序准备的 , 这样它们就可以获得您正在播放的文件的信息。 + + + + Autosave MPlayer log filename + 自动保存 MPlayer 日志的文件名 + + + + Enter here the path and filename that will be used to save the MPlayer log. + 这里输入的路径和文件名将用于保存 MPlayer 的日志。 + + + + A&utosave MPlayer log to file + 自动保存 MPlayer 日志到文件(&U) + + + + Pass short filenames (8+3) to MPlayer + 传递短文件名 (8+3) 给 MPlayer + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + 当前 MPlayer 不能打开文件名中包含本地代码页以外字符的文件。勾选此选项将使 SMPlayer 传递短文件名给 MPlayer, 使 MPlayer 能打开。 + + + + &Pass short filenames (8+3) to MPlayer + 传递短文件名 (8+3) 给 MPlayer (&P) + + + + Monitor aspect + 锁定外观 + + + + Select the aspect ratio of your monitor. + 选择您的显示器的外观比例。 + + + + Run MPlayer in its own window + 让 Mplayer 在自己的窗口里运行 + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + 如果您勾选了这个选项, MPlayer 的视频窗口将不再内嵌在 SMPlayer 的主窗口里, 它将使用自己的独立窗口。注意鼠标和键盘事件将被MPlayer 直接处理, 这意味着快捷键和鼠标点击将不一定有效, 除非焦点在 MPlayer 的窗口上。 + + + + Colorkey + 颜色代码 + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + 如果您发现部分视频出现在别的窗口上, 您可以通知改变 colorkey 来修复它。请选择靠近黑色的颜色。 + + + + Options for MPlayer + Mplayer 的选项 + + + + Options + 选项 + + + + Here you can type options for MPlayer. Write them separated by spaces. + 在这里您可以输入 MPlayer 的选项。请以空格分隔它们。 + + + + Video filters + 视频过滤器 + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + 在这里你可以给 Mplayer 添加视频过滤器。请用逗号分隔它们。不要使用空格! + + + + Audio filters + 音频过滤器 + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + 在这里你可以给 Mplayer 添加音频过滤器。请用逗号分隔它们。不要使用空格! + + + + Repaint the background of the video window + 重绘视频窗口的背景 + + + + Repaint the backgroun&d of the video window + 重绘视频窗口的背景(&D) + + + + IPv4 + IPv4 + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + 使用 IPv4 网络连接。失败后自动使用 IPv6。 + + + + IPv6 + IPv6 + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + 使用 IPv6 网络连接。失败后自动使用 IPv4。 + + + + Network Connection + 网络连接 + + + + IPv&4 + IPv4(&4) + + + + IPv&6 + IPv6(&6) + + + + Lo&gs + 日志(&G) + + + + Rebuild index if needed + 当需要的时候重建索引 + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> Note: the creation of the index may take some time. + 当找不到索引时,就重建媒体的索引使得定位功能生效。对播放那些破损或不完整的下载或创建失败的文件十分有用。这个选项只在背后的媒体支持定义时才有效(例如对标准输入和管道等无效)。<br>注意: 重建索引可能需要一定的时间。 + + + + Rebuild &index if needed + 当需要的时候重建索引(&I) + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + 如果勾选, SMPlayer 将记录 SMPlayer 输出的调试信息 (你可以在<b>选项->查看日志->smplayer</b>查看)。当你找到 bug 时, 对于开发者这将会是非常重要的信息。 + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + 如果勾选, SMPlayer 将记录 MPlayer 的输出 (你可以在<b>选项->查看日志->mplayer</b>查看)。如果出现错误,此记录可能包含重要信息, 所以推荐勾选。 + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + 这个选项允许过滤 SMPlayer 将要记录的日志。这里您可以使用任何正则表达式。<br>示例:<i>^Core::..*</i> 将只记录以 <i>Core::</i> 开头的行 + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + 类型 + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + 警告 + + + + Not all files could be associated. Please check your security permissions and retry. + 并非所有的文件都能被关联。请检查您的安全权限,然后重试。 + + + + File Types + 文件类型 + + + + Select all + 全选 + + + + Check all file types in the list + 勾选列表中的所有文件类型 + + + + Uncheck all file types in the list + 不勾选列表中的所有文件类型 + + + + List of file types + 文件类型列表 + + + + File types + 文件类型 + + + + Media files handled by SMPlayer: + SMPlayer 支持的媒体文件: + + + + Select All + 全选 + + + + Select None + 选择无 + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + 选择您希望 SMPlayer 去关联的媒体文件后缀。当您点击应用后, 选择的文件将被 SMPlayer 关联。如果您取消选择一种媒体类型, 文件关联将被还原。 + + + + Select none + 选择无 + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>注意:</b> (还原在 Windows Vista 中无效)。 + + + + PrefDrives + + + Drives + 设备 + + + + icon + 图标 + + + + CD device + 光驱设备 + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + 选择您的光驱设备。它将用于播放 VCD 和 音频 CD。 + + + + DVD device + DVD 设备 + + + + Choose your DVD device. It will be used to play DVDs. + 选择您的 DVD 设备。它将用于播放 DVD。 + + + + Select your &CD device: + 选择你的 CD 设备(&C): + + + + Select your &DVD device: + 选择你的 DVD 设备(&D): + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + SMPlayer 默认不选择任何 CDROM 或 DVD 设备。所以在播放 CD 或 DVD 前, 您必须选择要使用的设备(它们可以相同)。 + + + + PrefGeneral + + + General + 常规 + + + + &General + 常规(&G) + + + + Paths + 路径 + + + + Media settings + 媒体设置 + + + + Preferred audio and subtitles + 首选的音频和字幕 + + + + Video + 视频 + + + + Start videos in fullscreen + 用全屏播放 + + + + Disable screensaver + 禁用屏保 + + + + Audio + 音频 + + + + AC3/DTS pass-through S/PDIF + AC3/DTS 经由 S/PDIF + + + + Select the mplayer executable + 选择 Mplayer 的可执行文件 + + + + Executables + 可执行 + + + + All files + 所有文件 + + + + Select a directory + 选择一个目录 + + + + MPlayer executable + Mplayer 的可执行文件 + + + + Screenshots folder + 保存截图的目录 + + + + Video output driver + 视频输出驱动 + + + + Audio output driver + 音频输出驱动 + + + + Select the audio output driver. + 选择音频输出驱动。 + + + + Remember settings + 记住设置 + + + + Preferred audio language + 首选音频语言 + + + + Preferred subtitle language + 首选字幕语言 + + + + Software video equalizer + 软件视频均衡 + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + 您可以勾选此选项如果视频均衡器不被您的显卡或选择的输出驱动支持。<br><b>注意:</b>这个选项可能和一些视频输出驱动不兼容。 + + + + If this option is checked, all videos will start to play in fullscreen mode. + 如果勾选此选项, 所有的视频将一开始就使用全屏模式。 + + + + Software volume control + 软件音量控制 + + + + Check this option to use the software mixer, instead of using the sound card mixer. + 勾选这个选项以使用软件混音(不使用声卡混音)。 + + + + Postprocessing quality + 后期处理品质 + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + 动态改变后期处理的级别, 依赖于可用的空闲 CPU 时间. 这个数字说明将被用到的最大级别。通常您可以选用较大的数字。 + + + + Change volume + 改变音量 + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + 如果被选中,SMPlayer 将记住每一个文件的音量并在再次播放时使用。对于新文件将使用默认音量。 + + + + 0 + 0 + + + + &Change volume on every file + 改变所有文件的音量(&C) + + + + Select the &MPlayer executable: + 选择 Mplayer 的可执行文件(&M): + + + + &Folder for storing screenshots: + 保存截图的目录(&F): + + + + &Audio: + 音频(&A): + + + + &Remember settings for all files (audio track, subtitles...) + 记录所有文件的设置 (音轨, 字幕...)(&R) + + + + Su&btitles: + 字幕(&B): + + + + &Quality: + 品质(&Q): + + + + Start videos in &fullscreen + 用全屏播放(&F) + + + + Disable &screensaver + 禁用屏保(&S) + + + + &Default volume: + 默认音量(&D): + + + + Use s&oftware volume control + 使用软件音量控制(&O) + + + + Ma&x. Amplification: + 最大放大(&X): + + + + &AC3/DTS pass-through S/PDIF + AC3/DTS 经由 S/PDIF(&A) + + + + Direct rendering + 直接呈现 + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>WARNING:</b> May cause OSD/SUB corruption! + 如果被选中,将使用直接呈现(direct rendering)(不是所有的编码和输出驱动都支持的)<br><b>警告:</b>可能使 OSD/字幕 出错! + + + + Double buffering + 双倍缓存 + + + + D&irect rendering + 直接呈现(&I) + + + + Dou&ble buffering + 双倍缓存(&B) + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + 双倍缓存通过将双帧存在内存里来解决闪烁的问题, 显现一帧的同时解码另一帧。如果禁用将影响 OSD, 但能消除 OSD 的闪烁。 + + + + &Enable postprocessing by default + 为所有视频启用后期处理(&E) + + + + Volume &normalization by default + 默认音量正常化(&N) + + + + Close when finished + 结束时关闭 + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + 如果选择这个选项,主窗口会在当前文件或播放列表结束后自动关闭。 + + + + 2 (Stereo) + 2 (立体声) + + + + 4 (4.0 Surround) + 4 (4.0 环绕) + + + + 6 (5.1 Surround) + 6 (5.1 环绕) + + + + C&hannels by default: + 默认频道(&H): + + + + &Pause when minimized + 最小化时暂停(&P) + + + + Pause when minimized + 最小化时暂停 + + + + Enable postprocessing by default + 默认打开后期处理 + + + + Postprocessing will be used by default on new opened files. + 后期处理将默认用于新打开的文件。 + + + + Max. Amplification + 最大放大 + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + 设置最大放大级别的百分比(默认: 110)。设成值 200 将允许您调节最大音量到现在的两倍。设成小于100的值后,初始音量(是100%)将超过最大值, 这时 OSD 的显示将不正确。 + + + + Uses hardware AC3 passthrough + 使用硬件 AC3 passthrough + + + + Volume normalization by default + 默认音量正常化 + + + + Maximizes the volume without distorting the sound. + 不扭曲声音的最大音量。 + + + + Default volume + 默认音量 + + + + Sets the initial volume that new files will use. + 设置新的文件要使用的初始音量。 + + + + Channels by default + 默认频道 + + + + Audio track + 音轨 + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + 指定的默认音轨将被用于播放新的文件。如果音轨不存在, 将使用第一个音轨。<br><b>注意:</b><i>“首选音轨语言”</i>的设置将覆盖这个选项。 + + + + Subtitle track + 字幕 + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + 指定的默认字幕将被用于播放新的文件。如果音轨不存在, 将使用第一个音轨。<br><b>注意:</b><i>“首选字幕语言”的设置将覆盖这个选项。 + + + + Or choose a track number: + 选择一个轨道: + + + + Audi&o: + 音频(&O): + + + + Preferred language: + 首选语言: + + + + Preferre&d audio and subtitles + 首选的音频和字幕(&D) + + + + &Subtitle: + 字幕(&S): + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + 这里可以输入您音频和字幕的首选语言。当媒体文件在多个音轨或字幕时, SMPlayer 将尝试您的首选语言。这只在媒体文件提供了音频和字幕的语言信息时才有效, 如 DVD 或 mkv 文件。<br>这些字段接受正则表达式。示例: <b>es|esp|spa</b> 将选择那些匹配 <i>es</i>, <i>esp</i> 或 <i>spa</i>的轨道。 + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + . + + + + High speed &playback without altering pitch + 高速回放, 不改变音调(pitch)(&P) + + + + High speed playback without altering pitch + 高速回放, 不改变音调(pitch) + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + 允许改变高速回放速度。需要至少 MPlayer dev-SVN-r24924。 + + + + Change volume just before playing + 在播放前改变音量 + + + + &Video + 视频(&V) + + + + Use s&oftware video equalizer + 使用软件均衡器(&O) + + + + A&udio + 音频(&U) + + + + Volume + 音量 + + + + None + + + + + Lowpass5 + Lowpass5 + + + + Yadif (normal) + Yadif (正常) + + + + Yadif (double framerate) + Yadif (双倍缓存) + + + + Linear Blend + Linear Blend + + + + Kerndeint + Kerndeint + + + + Dei&nterlace by default: + 默认反拉丝(&N): + + + + Deinterlace by default + 默认反拉丝 + + + + Select the deinterlace filter that you want to be used for new videos opened. + 选择一个应用在所有新打开的视频上的反拉丝过滤器。 + + + + Remember time position + 记录播放的时间位置 + + + + Remember &time position + 记录播放的时间位置(&T) + + + + Change volume just before p&laying + 在播放前改变音量(&L) + + + + Enable the audio equalizer + 启用音频均衡器 + + + + Check this option if you want to use the audio equalizer. + 如果您想使用音频均衡器,请勾选此选项。 + + + + &Enable the audio equalizer + 启用音频均衡器(&E) + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + + + + + fast + + + + + slow + + + + + fast - ATI cards + 快 - ATI 片 + + + + User defined... + 用户自定义... + + + + Default zoom + 默认缩放 + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + 默认缩放(&Z): + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + 这里您必须指定 SMPlayer 要使用的 MPlayer 的可执行文件。<br>SMPlayer 需要至少 1.0rc1 的 MPlayer (推荐 SVN 版)。 + + + + If this setting is wrong, SMPlayer won't be able to play anything! + 如果设置错误, SMPlayer 将不能播放任何文件! + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + 这里你可以设置 SMPlayer 存放截图的目录。如果这里为空,截图功能将被禁用。 + + + + Select the video output driver. %1 provides the best performance. + 选择视频输出驱动。%1 能提供最佳性能。 + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + 默认情况下 SMPlayer 会记录您播放的每一个文件的设置(选择的音轨, 音量, 过滤器...)。如果您不喜欢这个特性, 请不要勾选此选项。 + + + + If you check this option, SMPlayer will play all files from the beginning. + 如果勾选此选项, SMPlayer 将从头播放所有文件。 + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + 如果被勾选,在主窗口隐藏时暂停播放。还原窗口后,播放恢复。 + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + 勾选此选项将在播放时禁用屏保。<br>播放结束后屏保会重新起用。 + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + 这里您可以输入您首选的音频流。当在媒体里发现多个音频流时, SMPlayer 将试图使用您的首选语言。<br>这只在媒体提供语言和音频流信息时有效, 像 DVD 或 mkv 文件。<br>这里支持正则表达式。示例: <b>es|esp|spa</b> 将选择匹配 <i>es</i>, <i>esp</i> 或 <i>spa</i> 的音轨。 + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + 这里您可以输入您首选的字幕。当在媒体里发, 像 DVD 或 mkv 文件。<br>这里支持正则表达式。示例: <b>es|esp|spa</b> 将选择匹配 <i>es</i>, <i>esp</i> 或 <i>spa</i> 的字幕。 + + + + Ou&tput driver: + 输出设备(&T): + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + 键盘和鼠标 + + + + &Keyboard + 键盘(&K) + + + + icon + 图标 + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + 在这里您可以更改任何快捷键。通过在一个快捷键单元格双击或键入来设置。您也可以保存您的设置然后共享给他人或加载别的电脑上的设置。 + + + + &Mouse + 鼠标(&M) + + + + Button functions: + 按键功能: + + + + Media seeking + 媒体定位 + + + + Volume control + 音量控制 + + + + Zoom video + 缩放视频 + + + + None + + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + 在这里您可以更改任何快捷键。通过在一个快捷键单元格双击或键入来设置。您也可以保存您的设置然后共享给他人或加载别的电脑上的设置。 + + + + &Left click + 左击(&L) + + + + &Double click + 双击(&D) + + + + &Wheel function: + 滚轮功能(&W): + + + + Shortcut editor + 快捷键编辑器 + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Left click + 左击 + + + + Select the action for left click on the mouse. + 选择左击的动作。 + + + + Double click + 双击 + + + + Select the action for double click on the mouse. + 选择双击的动作。 + + + + Wheel function + 滚轮功能 + + + + Select the action for the mouse wheel. + 选择鼠标滚轮的动作。 + + + + Play + 播放 + + + + Pause + 暂停 + + + + Stop + 停止 + + + + Fullscreen + 全屏 + + + + Compact + 简洁模式 + + + + Screenshot + 截图 + + + + On top + 置顶 + + + + Mute + 静音 + + + + Frame counter + 帧记数 + + + + Reset zoom + 重设缩放 + + + + Exit fullscreen + 退出全屏 + + + + Double size + 双倍大小 + + + + Play / Pause + 播放 / 暂停 + + + + Pause / Frame step + 暂停 / 单帧步进 + + + + Playlist + 播放列表 + + + + Preferences + 首选项 + + + + No function + 无功能 + + + + Change speed + 改变速度 + + + + Normal speed + 常速 + + + + Keyboard + 键盘 + + + + Mouse + 鼠标 + + + + Middle click + 中击 + + + + Select the action for middle click on the mouse. + 选择中击的动作。 + + + + M&iddle click + 中击(&i) + + + + X Button &1 + X 按键 &1 + + + + X Button &2 + X 按键 &2 + + + + Go backward (short) + 回退(短) + + + + Go backward (medium) + 回退(中) + + + + Go backward (long) + 回退(长) + + + + Go forward (short) + 前进(短) + + + + Go forward (medium) + 前进(中) + + + + Go forward (long) + 前进(长) + + + + OSD - Next level + OSD - 下一级别 + + + + Show context menu + 显示上下文菜单 + + + + &Right click + 右击(&R) + + + + Increase volume + 增大音量 + + + + Decrease volume + 减小音量 + + + + X Button 1 + X 按键 1 + + + + Select the action for the X button 1. + 选择 X 按键 1 的动作。 + + + + X Button 2 + X 按键 2 + + + + Select the action for the X button 2. + 选择 X 按键 2 的动作。 + + + + Show video equalizer + 显示视频均衡 + + + + Show audio equalizer + 显示音频均衡 + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + 杂项 + + + + <Autodetect> + <自动探测> + + + + Default + 默认 + + + + &Interface + 杂项(&I) + + + + Seeking + 定位 + + + + Never + 从不 + + + + Whenever it's needed + 当需要的时候 + + + + Only after loading a new video + 只在新影片加载后 + + + + Recent files + 最近打开的文件 + + + + Language + 语言 + + + + Here you can change the language of the application. + 在这里你可以改变应用程序的语言。 + + + + Instances + 实例 + + + + &Short jump + 短跳跃(&S) + + + + &Medium jump + 跳跃(&M) + + + + &Long jump + 长跳跃(&L) + + + + Mouse &wheel jump + 鼠标滚轮跳跃(&W) + + + + &Use only one running instance of SMPlayer + 只使用一个运行的 SMPlayer 实例(&U) + + + + Ma&x. items + 最大项数(&x) + + + + St&yle: + 风格(&Y): + + + + Ico&n set: + 图标集(&N): + + + + L&anguage: + 语言(&A): + + + + Main window + 主窗口 + + + + Auto&resize: + 自动缩放(&R): + + + + R&emember position and size + 记录播放的时间位置(&E) + + + + Default font: + 默认字体: + + + + &Change... + 修改(&C)... + + + + &Behaviour of time slider: + 时间滑块的行为(&B): + + + + Seek to position while dragging + 拖放时定位到拖放的位置 + + + + Seek to position when released + 在拖放结束后定位到指定位置 + + + + TextLabel + 文本标签 + + + + &Seeking + 定位(&S) + + + + Ins&tances + 实例(&T) + + + + Autoresize + 自动缩放 + + + + The main window can be resized automatically. Select the option you prefer. + 主窗口将自动缩放。请根据您的喜好来勾选这个选项。 + + + + Remember position and size + 记录的位置和大小 + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + 如果您勾选这个选项, 主窗口的位置和大小将被记录, 然后在下一次启动 SMPlayer 时还原。 + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + 选择在 <b>打开->最近使用</b> 子菜单中显示的项的最大数目。如果您将值设为 0 那么这个子菜单将不被显示。 + + + + Icon set + 图标集 + + + + Select the icon set you prefer for the application. + 为应用程序选择您所喜欢的图标集。 + + + + Style + 风格 + + + + Select the style you prefer for the application. + 为应用程序选择您所喜欢的风格。 + + + + Default font + 默认字体 + + + + You can change here the application's font. + 在这里你可以改变应用程序的字体。 + + + + Short jump + 短跳跃 + + + + Select the time that should be go forward or backward when you choose the %1 action. + 选择您执行 %1 后应该前进或回退的时间。 + + + + short jump + 短跳跃 + + + + Medium jump + 跳跃 + + + + medium jump + 跳跃 + + + + Long jump + 长跳跃 + + + + long jump + 长跳跃 + + + + Mouse wheel jump + 鼠标滚轮跳跃 + + + + Select the time that should be go forward or backward when you move the mouse wheel. + 选择您滚动滚轮后应该前进或回退的时间。 + + + + Behaviour of time slider + 时间滑块的行为 + + + + Select what to do when dragging the time slider. + 选择拖动时间滑块的行为。 + + + + Use only one running instance of SMPlayer + 只使用一个运行的 SMPlayer 实例 + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + 选择此选项,如果您希望在打开其它文件时使用已打开的实例进行播放。 + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + SMplayer 需要监听一个端口来接收其它实例发送的命令。您可以改为其它端口,如果默认设置已经被其它程序所使用了。 + + + + Default GUI + 默认界面 + + + + Mini GUI + Mini 界面 + + + + GUI + 界面 + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + 界面(&G) + + + + Automatic port + 自动选择端口 + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + SMplayer 需要监听一个端口来接收其它实例发送的命令。如果您选择这个选项,这个端口将被自动选择。 + + + + Manual port + 手工指定端口 + + + + Port to listen + 监听端口 + + + + &Automatic + 自动(&A) + + + + &Manual + 手工(&M) + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + 首选项 + + + + &Performance + 首选项(&P) + + + + Priority + 优先级 + + + + Select the priority for the MPlayer process. + 选择 MPlayer 进程的优先级。 + + + + realtime + 实时 + + + + high + + + + + abovenormal + 高于标准 + + + + normal + 标准 + + + + belownormal + 低于标准 + + + + idle + 空闲 + + + + Cache + 缓存 + + + + KB + KB + + + + Setting a cache may improve performance on slow media + 设置缓存可以改进播放性能 + + + + Allow frame drop + 允许丢帧 + + + + Synchronization + 同步 + + + + Audio/video auto synchronization + 音频/视频 自动同步 + + + + Fast audio track switching + 快速音轨切换 + + + + Fast seek to chapters in dvds + 在 DVD 里快速定位章节 + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + 为 MPlayer 设置优先级 (根据 Windows 下的命名习惯)。<br><b>警告:</b> 使用实时会将您的系统锁死。 + + + + Skip displaying some frames to maintain A/V sync on slow systems. + 在较慢的系统上, 跳了一些帧来保证 A/V 同步。 + + + + Allow hard frame drop + 允许强制丢帧 + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + 大量帧被跳过(解码错误)。将导致画面变形! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + 根据音频延时来调整 A/V 同步。 + + + + Priorit&y: + 优先级(&Y): + + + + &Allow frame drop + 允许丢帧(&A) + + + + Allow &hard frame drop (can lead to image distortion) + 允许强制丢帧 (可能导致图像变形)(&H) + + + + Audio/&video auto synchronization + 音频/视频 自动同步(&V) + + + + Fact&or: + 因子(&O): + + + + &Fast audio track switching + 快速音轨选择(&F) + + + + Fast &seek to chapters in dvds + 在 DVD 里快速定位章节(&S) + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + 如果勾选这个选项,将尝试用最快的方式定位到章节,但在一些盘片上可能无效。 + + + + Skip loop filter + 忽略循环过滤器 + + + + H.264 + H.264 + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + 可能的值:<br><b>Yes</b>: 将尝试用最快的方式来切换音轨(可能对一些格式无效)。<br><b>No</b>: 当切换音轨时将重启 MPayer 的进程。<br><b>自动</b>: SMPlayer 将根据 MPlayer 的版本来决定使用哪种方式。 + + + + Cache for files + 文件缓存 + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + 这个选项指定使用多少内存(KB为单位)来预存一个文件。 + + + + Cache for streams + 流缓存 + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + 这个选项指定使用多少内存(KB为单位)来预存一个URL。 + + + + Cache for DVDs + DVD 缓存 + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + 这个选项指定使用多少内存(KB为单位)来预存 DVD。<br><b>警告:</b> 对 DVD 使用缓存后定位可能工作异常(包括章节切换)。 + + + + &Cache + 缓存(&C) + + + + Cache for &DVDs: + DVD 缓存(&D): + + + + Cache for &local files: + 本地文件缓存(&L): + + + + Cache for &streams: + 流缓存(&S): + + + + Enabled + 启用 + + + + Skip (always) + 忽略(总是) + + + + Skip only on HD videos + 只忽略 HD 视频 + + + + Loop &filter + 循环过滤器(&F) + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + 可能的值: + + + + <b>Enabled</b>: the loop filter is not skipped + <b>启用</b>: 循环过滤器没有被忽略 + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + <b>忽略(总是)</b>: 总是忽略循环过滤器,不管视频的分辨率 + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + <b>只忽略 HD 视频</b>: 只在高度是%1或更大的视频上忽略循环过滤器。 + + + + Cache for audio CDs + 音频 CD 缓存 + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + 这个选项指定使用多少内存(KB为单位)来预存一个音频 CD。 + + + + Cache for &audio CDs: + 音频 CD 缓存(&A): + + + + Cache for VCDs + VCD 缓存 + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + 这个选项指定使用多少内存(KB为单位)来预存一个 VCD。 + + + + Cache for &VCDs: + VCD 缓存(&V): + + + + Threads for decoding + 解码的线程数 + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + 设置用于解码的线程数。MPEG-1/2 和 H.264 专用 + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + 解码的线程数(&T) (MPEG-1/2 和 H.264 专用): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + 播放列表 + + + + Automatically add files to playlist + 自动向播放列表添加文件 + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + 如果勾选此选项, 每当打开文件的时候, SMPlayer 会先清空播放列表再添加文件。当打开 DVD, CD 或 VCD 时, 碟片里所有的影片将被添加到播放列表。 + + + + Add consecutive files + 添加连续文件 + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + 如果勾选此选项, SMPlayer 将查找并添加连续的文件(例如 video_1.avi, video_2.avi...)。 + + + + &Playlist + 播放列表(&P) + + + + &Automatically add files to playlist + 自动向播放列表添加文件(&A) + + + + Add &consecutive files + 添加连续文件(&C) + + + + PrefSubtitles + + + Subtitles + 字幕 + + + + Choose a ttf file + 选择一个 ttf 文件 + + + + Truetype Fonts + Truetype 字体 + + + + &Subtitles + 字幕(&S) + + + + Autoload + 自动加载 + + + + Select first available subtitle + 选择第一个可用的字幕 + + + + Same name as movie + 和影片同名的字幕 + + + + All subs containing movie name + 所有包含影片名的字幕 + + + + All subs in directory + 目录里的所有字幕 + + + + Position + 位置 + + + + 0 + 0 + + + + Top + 顶部 + + + + Bottom + 底部 + + + + Include subtitles on screenshots + 将字幕包含在截图里 + + + + Font + 字体 + + + + Select the font which will be used for subtitles (and OSD): + 选择字幕 (和 OSD) 的字体: + + + + Size + 大小 + + + + No autoscale + + + + + Proportional to movie height + 相对于影片的高度 + + + + Proportional to movie width + 相对于影片的宽度 + + + + Proportional to movie diagonal + 相对于影片的对角线 + + + + Subtitle position + 字幕位置 + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + 这个选项指定字幕在视频窗口里的位置。<i>100</i>表示底部, <i>0</i>表示顶部。 + + + + Au&toload subtitles files (*.srt, *.sub...): + 自动加载字幕文件 (*.srt, *.sub...)(&T): + + + + S&elect first available subtitle + 选择第一个可用的字幕(&E) + + + + &Default subtitle encoding: + 默认字幕编码(&D): + + + + Default &position of the subtitles on screen + 字幕在屏幕的默认位置(&P) + + + + &Include subtitles on screenshots + 将字幕包含在截图里(&I) + + + + &TTF font: + TTF 字体(&T): + + + + S&ystem font: + 系统字体(&Y): + + + + A&utoscale: + 自适应比例(&U): + + + + Default subtitle encoding + 默认字幕编码 + + + + If this option is checked, the subtitles will appear in the screenshots. Note: it may cause some troubles sometimes. + 如果选择这个选项,字幕将会出现在截图里。注意: 这有时可能会带来一些麻烦。 + + + + TTF font + TTF 字体 + + + + System font + 系统字体 + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + 在这里您可以选择一个用于字幕和 OSD 的系统字体。<b>注意:</b> 需要 MPlayer 有 fontconfig 支持。 + + + + Autoscale + 自适应比例 + + + + Text color + 文本颜色 + + + + Select the color for the text of the subtitles. + 选择用于字幕文本的颜色。 + + + + Border color + 边框颜色 + + + + Select the color for the border of the subtitles. + 选择用于字幕边框的颜色。 + + + + Select the subtitle autoload method. + 选择字幕自动加载方式。 + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + 如果有一个以上的可用字幕, 其中的一个会被自动加载, 一般是第一个, 但如果有和用户首选字幕匹配的,匹配的字幕将被使用。 + + + + Select the subtitle autoscaling method. + 选择字幕自动加载方式。 + + + + Select the encoding which will be used for subtitle files by default. + 请选择字幕文件的默认编码。 + + + + Try to autodetect for this language + 尝试自动检测此语言 + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + 字幕语言 + + + + Select the language for which you want the encoding to be guessed automatically. + 选择您希望自动尝试的编码。 + + + + Encoding + 编码 + + + + Try to a&utodetect for this language: + 尝试自动检测此语言(&U): + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + 在这里您可能选择一个用于字幕的 TTF 字体。通常您可以在 %1 找到很多 TTF 字体 + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + 底部 + + + + Middle + vertical alignment + + + + + Top + vertical alignment + 顶部 + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - 帮助 + + + + OK + 确定 + + + + Cancel + 取消 + + + + Apply + 应用 + + + + Help + 帮助 + + + + SMPlayer - Preferences + SMPlayer - 首选项 + + + + QObject + + + will show this message and then will exit. + 将显现这条信息然后退出。 + + + + the main window will be closed when the file/playlist finishes. + 当文件或播放列表结束时将关闭主窗口。 + + + + This is SMPlayer v. %1 running on %2 + 这是运行在 %2 上的 SMPlayer v. %1 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + 尝试连接到另一个运行着的实例并发送指定的操作。例如: -send-action pause 其它选项(如果有的话)将被忽略,程序将自动退出。它成功将返回0,失败-1。 + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + action_list 是一系列用空格分隔的操作。加载完文件后将马上按您给定的顺序执行这些操作。对于选项操作您可以用 true 或 false 作为参数。例如:-actions "fullscreen compact true"。将有多个操作时引号是必须。 + + + + media + 媒体 + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + 如果另一个实例正在运行, 媒体将加到那个实例的播放列表中。如果没有其它实例, 这个选项将被忽略, 文件将来新的实例中打开。 + + + + the main window won't be closed when the file/playlist finishes. + 主窗口在文件或播放列表结束后不能关闭。 + + + + the video will be played in fullscreen mode. + 视频将在全屏模式中播放。 + + + + the video will be played in window mode. + 视频将在窗口模式中播放。 + + + + Enqueue in SMPlayer + 在 SMPlayer 里排队 + + + + opens the mini gui instead of the default one. + 打开 mini 界面而不是默认界面。 + + + + Restores the old associations and cleans up the registry. + 恢复旧的文件关联并清理注册表。 + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + '媒体'是 SMPlayer 可以打开的任意一种文件格式。它可以是一个本地文件,DVD(例如 dvd://1),流媒体(例如 mms://....) 或一个 m3u 格式的本地播放列表。如果设定了 -playlist,那意味着 SMPlayer 将将 -playlist 这个选项传给 MPlayer,所以处理播放列表的将是 MPlayer 不是 SMPlayer。 + + + + Usage: + 用法: + + + + directory + 目录 + + + + action_name + 动作名称 + + + + action_list + 动作列表 + + + + opens the default gui. + 打开默认界面。 + + + + subtitle_file + 字幕文件 + + + + specifies the subtitle file to be loaded for the first video. + 指定第一个视频的字幕文件。 + + + + %1 second(s) + + %1 秒 + + + + + %1 minute(s) + + %1 分钟 + + + + + %1 and %2 + %1 和 %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + ZIP/UNZIP API 错误 %1 + + + + SeekWidget + + + icon + 图标 + + + + label + 标签 + + + + ShortcutGetter + + + Modify shortcut + 修改快捷键 + + + + Clear + 清空 + + + + Press the key combination you want to assign + 按下您想分配的组合键 + + + + Capture + 捕捉 + + + + Capture keystrokes + 捕捉按键 + + + + SubChooserDialog + + + Subtitle selection + 字幕选择 + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + 此存档文件包含多个字幕文件。请选择一个您要提取的。 + + + + Select All + 全选 + + + + Select None + 不选 + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - 定位 + + + + &Jump to: + 跳转到(&J): + + + + TristateCombo + + + Auto + 自动 + + + + Yes + + + + + No + + + + + VideoEqualizer + + + Brightness + 亮度 + + + + Contrast + 对比度 + + + + Gamma + Gamma + + + + Hue + 色调 + + + + Saturation + 饱和度 + + + + &Reset + 重置(&R) + + + + &Set as default values + 设为默认(&S) + + + + Use the current values as default values for new videos. + 将当前值做为新的视频的默认值。 + + + + Set all controls to zero. + 全部置 0。 + + + + Video Equalizer + 视频均衡器 + + + + Information + 信息 + + + + The current values have been stored to be used as default. + 当前值被保存为默认值。 + + + + VideoPreview + + + Video preview + + + + + Cancel + 取消 + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + 保存文件出错 + + + + The file couldn't be saved + 不能保存文件 + + + + Error + 错误 + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + 默认 + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + 音量 + + + diff --git a/plugins/smplayer_plugin/translations/smplayer_zh_TW.ts b/plugins/smplayer_plugin/translations/smplayer_zh_TW.ts new file mode 100644 index 000000000..aa59ca331 --- /dev/null +++ b/plugins/smplayer_plugin/translations/smplayer_zh_TW.ts @@ -0,0 +1,7308 @@ + + + + About + + + Version: %1 + 版本: %1 + + + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + 這個軟體是自由軟體;你可以在 GPL 或 GPL2 或之後版本下修改/重新發佈它。 + + + + The following people have contributed with translations: + 以下為翻譯的貢獻者 + + + + German + 德文 + + + + Slovak + 斯洛伐克文 + + + + Italian + 意大利文 + + + + French + 法文 + + + + %1, %2 and %3 + %1, %2 和 %3 + + + + Simplified-Chinese + 簡體中文 + + + + Russian + 俄文 + + + + %1 and %2 + %1 和 %2 + + + + Hungarian + 匈牙利文 + + + + Polish + 波蘭文 + + + + Japanese + 日文 + + + + Dutch + 荷蘭文 + + + + Ukrainian + 烏克蘭語 + + + + Portuguese - Brazil + 葡萄牙文 - 巴西 + + + + Georgian + 喬治亞文 + + + + Czech + 捷克文 + + + + Bulgarian + 保加利亞文 + + + + Turkish + 土耳其語 + + + + Swedish + 瑞典文 + + + + Serbian + 塞爾維亞文 + + + + Traditional Chinese + 正體中文 + + + + Romanian + 羅馬尼亞文 + + + + Portuguese - Portugal + 葡萄牙文 - 葡萄牙 + + + + Greek + 希臘文 + + + + Finnish + 芬蘭文 + + + + <b>%1</b>: %2 + + + + + <b>%1</b> (%2) + + + + + About SMPlayer + 關於 SMPlayer + + + + &Info + 資訊(&I) + + + + icon + 圖示 + + + + &Contributions + 貢獻(&C) + + + + &Translators + 翻譯者(&T) + + + + &License + 授權(&L) + + + + Visit our web for updates: + 參觀我們的網站以尋求更新: + + + + Get help in our forum: + 在我們的論壇取得協助: + + + + You can support SMPlayer by making a donation. + 藉由捐獻來支持SMPlayer + + + + More info + 更多資訊 + + + + Korean + 韓文 + + + + Macedonian + 馬其頓文 + + + + Basque + 巴斯克文 + + + + Using MPlayer %1 + 使用 MPlayer %1 + + + + Catalan + 卡達隆尼亞文 + + + + Portable Edition + 可攜式版本 + + + + Using Qt %1 (compiled with Qt %2) + 使用 Qt %1 (以 Qt %2 編譯) + + + + Slovenian + 斯洛維尼亞文 + + + + Arabic + 阿拉伯語 + + + + Kurdish + 庫德文 + + + + Galician + 加里斯亞文 + + + + The following people have contributed with patches (see the changelog for details): + + + + + If there's any omission, please report. + + + + + SMPlayer logo by %1 + + + + + %1, %2, %3 and %4 + + + + + %1, %2, %3, %4 and %5 + + + + + ActionsEditor + + + Name + 名字 + + + + Description + 描述 + + + + Shortcut + 快捷鍵 + + + + &Save + 儲存(&S) + + + + &Load + 載入(&L) + + + + Key files + + + + + Choose a filename + 選擇一個檔名 + + + + Confirm overwrite? + 是否覆寫? + + + + The file %1 already exists. +Do you want to overwrite? + 檔案 %1 己存在。 +是否覆寫? + + + + Choose a file + 選擇一個檔案 + + + + Error + 錯誤 + + + + The file couldn't be saved + 檔案無法儲存 + + + + The file couldn't be loaded + 檔案無法載入 + + + + &Change shortcut... + 改變捷徑 (&C)... + + + + AudioEqualizer + + + Audio Equalizer + 音訊等化器 + + + + 31.25 Hz + + + + + 62.50 Hz + + + + + 125.0 Hz + + + + + 250.0 Hz + + + + + 500.0 Hz + + + + + 1.000 kHz + + + + + 2.000 kHz + + + + + 4.000 kHz + + + + + 8.000 kHz + + + + + 16.00 kHz + + + + + &Apply + 套用(&A) + + + + &Reset + 重設(&R) + + + + &Set as default values + 設為預設值(&S) + + + + Use the current values as default values for new videos. + 將當前值做為新視訊的預設值。 + + + + Set all controls to zero. + 全部設置為零。 + + + + Information + 資訊 + + + + The current values have been stored to be used as default. + 目前的值已被儲存並作為預設的值 + + + + BaseGui + + + SMPlayer - mplayer log + SMPlayer - Mplayer 日誌 + + + + SMPlayer - smplayer log + SMPlayer - SMPlayer 日誌 + + + + &Open + 開啟(&O) + + + + &Play + 播放(&P) + + + + &Video + 視訊(&V) + + + + &Audio + 音訊(&A) + + + + &Subtitles + 字幕(&S) + + + + &Browse + 瀏覽(&B) + + + + Op&tions + 選項(&T) + + + + &Help + 說明(&H) + + + + &File... + 檔案(&F)... + + + + D&irectory... + 目錄(&I)... + + + + &Playlist... + 播放清單(&P)... + + + + &DVD from drive + 從磁碟機開啟 &DVD + + + + D&VD from folder... + 從目錄開啟 D&VD... + + + + &URL... + &URL... + + + + &Clear + 清除(&C) + + + + &Recent files + 最近使用的文件(&R) + + + + P&lay + 播放(&L) + + + + &Pause + 暫停(&P) + + + + &Stop + 停止(&S) + + + + &Frame step + + + + + &Normal speed + 常速(&N) + + + + &Halve speed + 半速(&H) + + + + &Double speed + 兩倍速(&D) + + + + Speed &-10% + 速度 &-10% + + + + Speed &+10% + 速度 &+10% + + + + Sp&eed + 速度(&E) + + + + &Repeat + 重複 (&R) + + + + &Fullscreen + 全螢幕(&F) + + + + &Compact mode + 精簡模式(&C) + + + + Si&ze + 大小(&Z) + + + + 4:3 &Letterbox + 4:3 信箱模式 (&L) + + + + 16:9 L&etterbox + 16:9 信箱模式 (&E) + + + + 4:3 &Panscan + 4:3 &Panscan + + + + 4:3 &to 16:9 + 4:3 &to 16:9 + + + + &Aspect ratio + 外觀比例(&A) + + + + &None + 無(&N) + + + + &Lowpass5 + &Lowpass5 + + + + Linear &Blend + + + + + &Deinterlace + + + + + &Postprocessing + + + + + &Autodetect phase + 自動偵測(&A) + + + + &Deblock + + + + + De&ring + + + + + Add n&oise + 加入雜訊(&O) + + + + F&ilters + 過濾器(&I) + + + + &Equalizer + 等化器(&E) + + + + &Screenshot + 螢幕擷取(&S) + + + + S&tay on top + 置頂(&T) + + + + &Extrastereo + 擴展立體聲(&E) + + + + &Karaoke + 卡拉O&K + + + + &Filters + 過濾器(&F) + + + + &Stereo + 立體聲(&S) + + + + &4.0 Surround + &4.0 環繞 + + + + &5.1 Surround + &5.1 環繞 + + + + &Channels + 聲道(&C) + + + + &Left channel + 左聲道(&L) + + + + &Right channel + 右聲道(&R) + + + + &Stereo mode + 立體聲模式(&S) + + + + &Mute + 静音(&M) + + + + Volume &- + 音量 &- + + + + Volume &+ + 音量 &+ + + + + &Delay - + 延遲 - (&D) + + + + D&elay + + 延遲 + (&E) + + + + &Select + 選擇(&S) + + + + &Load... + 載入(&L)... + + + + Delay &- + 延遲 &- + + + + Delay &+ + 延遲 &+ + + + + &Up + 上移(&U) + + + + &Down + 下移(&D) + + + + &Title + 標題(&T) + + + + &Chapter + 章節(&C) + + + + &Angle + 角度(&A) + + + + &Playlist + 播放清單(&P) + + + + &Show frame counter + 顯示幀計數器(&S) + + + + &Disabled + 停用(&D) + + + + &Seek bar + 定位條(&S) + + + + &Time + 時間(&T) + + + + Time + T&otal time + 時間 + 總時間(&O) + + + + &OSD + &OSD + + + + &View logs + 檢視日誌(&V) + + + + P&references + 偏好設定(&R) + + + + About &Qt + 關於 &Qt + + + + About &SMPlayer + 關於 &SMPlayer + + + + <empty> + <空> + + + + Video + 視訊 + + + + Audio + 音訊 + + + + Playlists + 播放清單 + + + + All files + 所有檔案 + + + + Choose a file + 選擇一個檔案 + + + + SMPlayer - Information + SMPlayer - 資訊 + + + + The CDROM / DVD drives are not configured yet. +The configuration dialog will be shown now, so you can do it. + CDROM / DVD 磁碟尚未設置。 +你可以在下面顯現的配置對話框裡設置。 + + + + Choose a directory + 選擇一個目錄 + + + + Subtitles + 字幕 + + + + About Qt + 關於 Qt + + + + Playing %1 + 播放 %1 + + + + Pause + 暫停 + + + + Stop + 停止 + + + + Play / Pause + 播放 / 暫停 + + + + Pause / Frame step + 暫停 / Frame step + + + + U&nload + 卸載(&N) + + + + V&CD + V&CD + + + + C&lose + 關閉(&L) + + + + View &info and properties... + 檢視資訊和內容(&I)... + + + + Zoom &- + 縮小(&-) + + + + Zoom &+ + 放大(&+) + + + + &Reset + 重設(&R) + + + + Move &left + 左移(&L) + + + + Move &right + 右移(&R) + + + + Move &up + 上移(&U) + + + + Move &down + 下移(&D) + + + + &Pan && scan + &Pan-scan + + + + &Previous line in subtitles + 前一行字幕(&P) + + + + N&ext line in subtitles + 後一行字幕(&E) + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Dec volume (2) + 降低音量(2) + + + + Inc volume (2) + 增加音量(2) + + + + Exit fullscreen + 退出全螢幕 + + + + OSD - Next level + OSD - 下一級别 + + + + Dec contrast + 降低對比度 + + + + Inc contrast + 增加對比度 + + + + Dec brightness + 降低亮度 + + + + Inc brightness + 增加亮度 + + + + Dec hue + 降低色调 + + + + Inc hue + 增加色调 + + + + Dec saturation + 降低飽和度 + + + + Dec gamma + 降低 Gamma + + + + Next audio + 下一音訊 + + + + Next subtitle + 下一字幕 + + + + Next chapter + 下一章節 + + + + Previous chapter + 前一章節 + + + + Inc saturation + 增加飽和度 + + + + Inc gamma + 增加 Gamma + + + + &Load external file... + 載入外部檔案(&L)... + + + + &Kerndeint + + + + + &Yadif (normal) + + + + + Y&adif (double framerate) + + + + + &Next + 下一個(&N) + + + + Pre&vious + 上一個(&V) + + + + Volume &normalization + 音量標準化(&N) + + + + &Audio CD + 音訊 CD (&A) + + + + Denoise nor&mal + 去除雜訊 正常(&m) + + + + Denoise &soft + 去除雜訊 柔化(&s) + + + + Denoise o&ff + 去除雜訊 關閉(&f) + + + + Use SSA/&ASS library + 使用 SSA/ASS 程式庫 + + + + Flip i&mage + 翻轉影像(&m) + + + + &Toggle double size + 切換兩倍大小 (&T) + + + + S&ize - + 大小(&i) - + + + + Si&ze + + 大小(&z) + + + + + Add &black borders + 加黑框(&b) + + + + Soft&ware scaling + 軟體縮放(&w) + + + + &FAQ + &FAQ + + + + Visualize &motion vectors + 視覺動態向量(&m) + + + + &Command line options + 命令列選項(&C) + + + + SMPlayer command line options + SMPlayer 命令列選項 + + + + Enable &closed caption + 啟用已關閉的標題(&c) + + + + &Forced subtitles only + 強制僅出現字幕(&F) + + + + Reset video equalizer + 重設視訊等化器 + + + + MPlayer has finished unexpectedly. + MPlayer 意外地結束 + + + + Exit code: %1 + 結束代碼: %1 + + + + MPlayer failed to start. + MPlayer 啟動失敗 + + + + Please check the MPlayer path in preferences. + 請檢查MPlayer在偏好設定裡的路徑 + + + + MPlayer has crashed. + MPlayer 已經當機 + + + + See the log for more info. + 更多資訊請參閱日誌 + + + + &Rotate + 旋轉(&R) + + + + &Off + 關閉(&O) + + + + &Rotate by 90 degrees clockwise and flip + 順時針方向旋轉90度然後翻轉(&R) + + + + Rotate by 90 degrees &clockwise + 順時針方向旋轉90度(&c) + + + + Rotate by 90 degrees counterclock&wise + 逆時針方向旋轉90度(&w) + + + + Rotate by 90 degrees counterclockwise and &flip + 逆時針方向旋轉90度然後翻轉(&f) + + + + &Jump to... + 跳至(&J)... + + + + Show context menu + 顯示內容功能表 + + + + Multimedia + 多媒體 + + + + E&qualizer + 等化器(&q) + + + + Reset audio equalizer + 重設音訊等化器 + + + + Find subtitles on &OpenSubtitles.org... + 從 &OpenSubtitles.org 尋找字幕... + + + + Upload su&btitles to OpenSubtitles.org... + 上傳字幕到 OpenSubtitles.org... + + + + &Tips + 提示(&T) + + + + &Auto + 自動(&A) + + + + Speed -&4% + 速度 -&4% + + + + &Speed +4% + 速度 +4% (&S) + + + + Speed -&1% + 速度 -&1% + + + + S&peed +1% + 速度 +1% (&p) + + + + Scree&n + 螢幕(&n) + + + + &Default + 預設(&D) + + + + Mirr&or image + + + + + Next video + + + + + &Track + video + 音軌(&T) + + + + &Track + audio + 音軌(&T) + + + + Warning - Using old MPlayer + + + + + The version of MPlayer (%1) installed on your system is obsolete. SMPlayer can't work well with it: some options won't work, subtitle selection may fail... + + + + + Please, update your MPlayer. + + + + + (This warning won't be displayed anymore) + + + + + Next aspect ratio + + + + + &Auto zoom + + + + + Zoom for &16:9 + + + + + Zoom for &2.35:1 + + + + + Pre&view... + + + + + &Always + + + + + &Never + + + + + While &playing + + + + + BaseGuiPlus + + + SMPlayer is still running here + SMPlayer 運行中 + + + + S&how icon in system tray + 在系統閘裡顯示圖示(&H) + + + + &Hide + 隱藏(&H) + + + + &Restore + 恢復(&R) + + + + &Quit + 離開 (&Q) + + + + Playlist + 播放清單 + + + + Core + + + Brightness: %1 + 亮度: %1 + + + + Contrast: %1 + 對比度: %1 + + + + Gamma: %1 + Gamma: %1 + + + + Hue: %1 + 色調: %1 + + + + Saturation: %1 + 飽和度: %1 + + + + Volume: %1 + 音量: %1 + + + + Zoom: %1 + 縮放: %1 + + + + Font scale: %1 + 字體縮放大小 + + + + Aspect ratio: %1 + + + + + Updating the font cache. This may take some seconds... + + + + + DefaultGui + + + Welcome to SMPlayer + 歡迎使用 SMPlayer + + + + Audio + 音訊 + + + + Subtitle + 字幕 + + + + &Main toolbar + 主工具列(&M) + + + + &Language toolbar + 語言工具列(&L) + + + + &Toolbars + 工具列(&T) + + + + EqSlider + + + icon + 圖示 + + + + ErrorDialog + + + Hide log + 隱藏日誌 + + + + Show log + 顯示日誌 + + + + MPlayer Error + MPlayer 錯誤 + + + + icon + 圖示 + + + + Error + 錯誤 + + + + FileDownloader + + + Downloading... + 下載中... + + + + Downloading %1 + + + + + FilePropertiesDialog + + + SMPlayer - File properties + SMPlayer - 檔案內容 + + + + &Information + 資訊(&I) + + + + &Demuxer + 解碼器(&D) + + + + &Select the demuxer that will be used for this file: + 選擇用於這個檔案的解碼器(&S): + + + + &Reset + 重設(&R) + + + + &Video codec + 視訊編碼解碼器(&V) + + + + &Select the video codec: + 選擇視訊編碼解碼器(&S): + + + + A&udio codec + 音訊編碼解碼器(&U) + + + + &Select the audio codec: + 選擇音訊編碼解碼器(&S): + + + + &MPlayer options + &Mplayer 選項 + + + + Additional Options for MPlayer + MPlayer 的額外選項 + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + 在這裡你可以傳遞額外的選項给 Mplayer。 +請用空格分隔它們。 +示例 : -flip -nosound + + + + &Options: + 選項(&O): + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + 在這裡你可以傳遞額外的視訊過濾器。 +請用 "," 分隔它們。不要使用空格! +示例: scale=512:-2,eq2=1.1 + + + + V&ideo filters: + 視訊過濾器(&I): + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + 音訊過濾器。規則和視訊過濾器一樣。 +示例: resample=44100:0:0,volnorm + + + + Audio &filters: + 音訊過濾器(&F): + + + + OK + 確定 + + + + Cancel + 取消 + + + + Apply + 套用 + + + + FindSubtitlesWindow + + + Language + 語言 + + + + Name + 名字 + + + + Format + 格式 + + + + Files + 檔案 + + + + Date + 日期 + + + + Uploaded by + + + + + All + 全部 + + + + Close + 關閉 + + + + &Download + 下載 (&D) + + + + &Copy link to clipboard + 複製連結到剪貼簿(&C) + + + + Error + 錯誤 + + + + Download failed: %1. + 下載失敗: %1. + + + + Connecting to %1... + 連結到 %1... + + + + Downloading... + 下載中... + + + + Done. + 完成 + + + + %1 files available + %1 檔案可用 + + + + Failed to parse the received data. + 無法分析已接收到的資料 + + + + Find Subtitles + 尋找字幕 + + + + &Subtitles for + + + + + &Language: + 語言 (&A) + + + + &Refresh + 更新(&R) + + + + Subtitle saved as %1 + + + + + %1 subtitle(s) extracted + + + + + + + Overwrite? + + + + + The file %1 already exits, overwrite? + + + + + Error saving file + 儲存檔案出錯 + + + + It wasn't possible to save the downloaded +file in folder %1 +Please check the permissions of that folder. + + + + + Download failed + + + + + Temporary file %1 + + + + + InfoFile + + + General + 一般 + + + + Size + 大小 + + + + %1 KB (%2 MB) + %1 KB (%2 MB) + + + + URL + URL + + + + Length + 長度 + + + + Demuxer + 解碼器 + + + + Name + 名字 + + + + Artist + 演出者名稱 + + + + Author + 作者 + + + + Album + 專輯 + + + + Genre + 流派 + + + + Date + 日期 + + + + Track + 音軌 + + + + Copyright + 版權 + + + + Comment + 註解 + + + + Software + 軟體 + + + + Clip info + 素材資訊 + + + + Video + 視訊 + + + + Resolution + 解析度 + + + + Aspect ratio + 外觀比例 + + + + Format + 格式 + + + + Bitrate + 位元率 + + + + %1 kbps + %1 kbps + + + + Frames per second + 幀/秒 + + + + Selected codec + 選擇的編碼解碼器 + + + + Initial Audio Stream + 初始化音訊串流 + + + + Rate + 比率 + + + + %1 Hz + %1 Hz + + + + Channels + 聲道 + + + + Audio Streams + 音訊串流 + + + + Language + 語言 + + + + empty + + + + + Subtitles + 字幕 + + + + Type + 類型 + + + + ID + Info for translators: this is a identification code + ID + + + + # + Info for translators: this is a abbreviation for number + # + + + + Stream title + 串流標題 + + + + Stream URL + 串流 URL + + + + File + 檔案 + + + + InputDVDDirectory + + + Choose a directory + 選取一個目錄 + + + + SMPlayer - Play a DVD from a folder + SMPlayer - 從資料夾裡播放 DVD + + + + You can play a dvd from your hard disc. Just select the folder which contains the VIDEO_TS and AUDIO_TS directories. + 你可以從你的硬碟播放 DVD 。只要選取包含 VIDEO_TS 和 AUDIO_TS 目錄的資料夾即可。 + + + + Choose a directory... + 選取一個目錄... + + + + InputMplayerVersion + + + SMPlayer - Enter the MPlayer version + SMPlayer - 輸入 MPlayer 版本 + + + + SMPlayer couldn't identify the MPlayer version you're using. + SMPlayer 無法識別您使用的 MPlayer 版本 + + + + Version reported by MPlayer: + MPlayer 報告的版本: + + + + Please, &select the correct version: + 請選擇正確的版本(&s): + + + + 1.0rc1 or older + 1.0rc1 或舊的 + + + + 1.0rc2 + + + + + Greater than 1.0rc2 + 大於 1.0rc2 + + + + InputURL + + + SMPlayer - Enter URL + SMPlayer - 輸入 URL + + + + &URL: + + + + + It's a &playlist + 這是播放清單(&p) + + + + If this option is checked, the URL will be treated as a playlist: it will be opened as text and will play the URLs in it. + 如果選取這個選項,則 URL 會被視為一個播放清單: 它將會如同文字開啟然後播放 URLs + + + + Languages + + + Afar + 阿法文 + + + + Abkhazian + 亞布卡薩文 + + + + Afrikaans + 南非荷蘭文 + + + + Amharic + 阿姆哈拉文 + + + + Arabic + 阿拉伯語 + + + + Assamese + 阿薩姆文 + + + + Aymara + 亞摩拉文 + + + + Azerbaijani + 亞塞拜然文 + + + + Bashkir + 巴什喀爾文 + + + + Byelorussian + 白俄羅斯文 + + + + Bulgarian + 保加利亞文 + + + + Bihari + 比哈文 + + + + Bislama + 比斯拉馬文 + + + + Bengali + 孟加拉文 + + + + Tibetan + 藏語 + + + + Breton + 布里敦文 + + + + Catalan + 卡達隆尼亞文 + + + + Corsican + 科西嘉文 + + + + Czech + 捷克文 + + + + Welsh + 威爾斯語 + + + + Danish + 丹麥文 + + + + German + 德文 + + + + Bhutani + 不丹文 + + + + Greek + 希臘文 + + + + English + 英文 + + + + Esperanto + 世界語 + + + + Spanish + 西班牙文 + + + + Estonian + 愛沙尼亞文 + + + + Basque + 巴斯克文 + + + + Persian + 波斯文 + + + + Finnish + 芬蘭文 + + + + Fiji + 斐濟文 + + + + Faroese + 法羅語 + + + + French + 法文 + + + + Frisian + 夫里斯蘭文 + + + + Irish + 愛爾蘭文 + + + + Scots + 蘇格蘭語 + + + + Galician + 加里斯亞文 + + + + Guarani + 瓜拉尼文 + + + + Gujarati + 古吉拉特文 + + + + Hausa + 豪沙文 + + + + Hebrew + 希伯來文 + + + + Hindi + 印度文 + + + + Croatian + 克羅埃西亞文 + + + + Hungarian + 匈牙利文 + + + + Armenian + 亞美尼亞文 + + + + Interlingua + 國際語 + + + + Indonesian + 印尼文 + + + + Interlingue + 國際語(人造語言) + + + + Inupiak + 依奴皮維克文 + + + + Icelandic + 冰島文 + + + + Italian + 意大利文 + + + + Inuktitut + 依奴提圖特文 + + + + Japanese + 日文 + + + + Javanese + 爪哇文 + + + + Georgian + 喬治亞文 + + + + Kazakh + 哈薩克文 + + + + Greenlandic + 格陵蘭文 + + + + Cambodian + 柬埔寨文 + + + + Kannada + 坎那達文 + + + + Korean + 韓文 + + + + Kashmiri + 喀什米爾文 + + + + Kurdish + 庫德文 + + + + Kirghiz + 吉爾吉斯文 + + + + Latin + 拉丁文 + + + + Lingala + 陵加拉文 + + + + Laothian + 寮文 + + + + Lithuanian + 立陶宛文 + + + + Latvian + 拉脫維亞文 + + + + Malagasy + 馬達加斯加文 + + + + Maori + 毛利文 + + + + Macedonian + 馬其頓文 + + + + Malayalam + 馬來亞拉姆文 + + + + Mongolian + 蒙古文 + + + + Moldavian + 摩爾多瓦文 + + + + Marathi + 馬拉提文 + + + + Malay + 馬來文 + + + + Maltese + 馬爾他文 + + + + Burmese + 緬甸文 + + + + Nauru + 諾魯文 + + + + Nepali + 尼泊爾文 + + + + Dutch + 荷蘭文 + + + + Norwegian + 挪威文 + + + + Occitan + 奧西坦文 + + + + Oriya + 歐利亞文 + + + + Punjabi + 旁遮普語 + + + + Polish + 波蘭文 + + + + Pashto + 普什圖文 + + + + Portuguese + 葡萄牙文 + + + + Quechua + 蓋丘亞語 + + + + Kirundi + 科隆地文 + + + + Romanian + 羅馬尼亞文 + + + + Russian + 俄文 + + + + Kinyarwanda + 金揚萬答文 + + + + Sanskrit + 梵文 + + + + Sindhi + 信德語 + + + + Sangho + 桑侯文 + + + + Sinhalese + 僧伽羅語 + + + + Slovak + 斯洛伐克文 + + + + Slovenian + 斯洛維尼亞文 + + + + Samoan + 薩摩亞語 + + + + Shona + 紹納語 + + + + Somali + 索馬利亞文 + + + + Albanian + 阿爾巴尼亞文 + + + + Serbian + 塞爾維亞文 + + + + Siswati + 西斯瓦提文 + + + + Sesotho + 塞索托語 + + + + Sundanese + 巽丹文 + + + + Swedish + 瑞典文 + + + + Swahili + 史瓦西里文 + + + + Tamil + 坦米爾文 + + + + Telugu + 特拉古文 + + + + Tajik + 塔吉克文 + + + + Thai + 泰文 + + + + Tigrinya + 提格里尼亞語 + + + + Turkmen + 土庫曼語 + + + + Tagalog + 他加祿語 + + + + Setswana + 茨瓦納語 + + + + Tonga + 通加語 + + + + Turkish + 土耳其語 + + + + Tsonga + 頌加文 + + + + Tatar + 韃靼文 + + + + Twi + 特維語 + + + + Uighur + 維吾爾文 + + + + Ukrainian + 烏克蘭語 + + + + Urdu + 烏都文 + + + + Uzbek + 烏茲別克文 + + + + Vietnamese + 越南語 + + + + Wolof + 沃洛夫文 + + + + Xhosa + 廓薩文 + + + + Yiddish + 意第緒文 + + + + Yoruba + 優魯巴文 + + + + Zhuang + 壯文 + + + + Chinese + 中文 + + + + Zulu + 祖魯文 + + + + Portuguese - Brazil + 葡萄牙文 - 巴西 + + + + Portuguese - Portugal + 葡萄牙文 - 葡萄牙 + + + + Simplified-Chinese + 簡體中文 + + + + Traditional Chinese + 正體中文 + + + + Unicode + + + + + UTF-8 + + + + + Western European Languages + 西歐語 + + + + Western European Languages with Euro + 西歐 + + + + Slavic/Central European Languages + 斯拉夫/中歐語 + + + + Esperanto, Galician, Maltese, Turkish + 世界語 + + + + Old Baltic charset + 舊波羅的海語字元集 + + + + Cyrillic + 斯拉夫語 + + + + Modern Greek + 現代希臘語 + + + + Baltic + 波羅的海語 + + + + Celtic + 凱爾特語 + + + + Hebrew charsets + 希伯来語字元集 + + + + Ukrainian, Belarusian + 烏克蘭語, 白俄羅斯語 + + + + Simplified Chinese charset + 簡體中文字元集 + + + + Traditional Chinese charset + 正體中文字元集 + + + + Japanese charsets + 日語字元集 + + + + Korean charset + 韓語字元集 + + + + Thai charset + 泰語字元集 + + + + Cyrillic Windows + 斯拉夫語 Windows + + + + Slavic/Central European Windows + + + + + Arabic Windows + + + + + Rhaeto-Romance + 里托羅曼斯文 + + + + Serbo-Croatian + 塞爾維亞克羅埃西亞文 + + + + Volapük + 舒氏世界語 + + + + Avestan + + + + + Akan + + + + + Aragonese + + + + + Avaric + + + + + Belarusian + + + + + Bambara + + + + + Bosnian + + + + + Chechen + + + + + Cree + + + + + Church + + + + + Chuvash + + + + + Divehi + + + + + Dzongkha + + + + + Ewe + + + + + Fulah + + + + + Fijian + + + + + Gaelic + + + + + Manx + + + + + Hiri + + + + + Haitian + + + + + Herero + + + + + Chamorro + + + + + Igbo + + + + + Sichuan + + + + + Inupiaq + + + + + Ido + + + + + Kongo + + + + + Kikuyu + + + + + Kuanyama + + + + + Khmer + + + + + Kanuri + + + + + Komi + + + + + Cornish + + + + + Luxembourgish + + + + + Ganda + + + + + Limburgan + + + + + Lao + + + + + Luba-Katanga + + + + + Marshallese + + + + + Bokmål + + + + + Ndebele + + + + + Ndonga + + + + + Navajo + + + + + Chichewa + + + + + Ojibwa + + + + + Oromo + + + + + Ossetian + + + + + Panjabi + + + + + Pali + + + + + Pushto + + + + + Romansh + + + + + Rundi + + + + + Sardinian + + + + + Sami + + + + + Sango + + + + + Sinhala + + + + + Swati + + + + + Sotho + + + + + Tswana + + + + + Tahitian + + + + + Venda + + + + + Volapük + + + + + Walloon + + + + + LogWindow + + + Choose a filename to save under + 選擇儲存檔名 + + + + Confirm overwrite? + 是否覆寫? + + + + Error saving file + 儲存檔案出錯 + + + + The file already exists. +Do you want to overwrite? + 檔案己存在。 +是否覆寫? + + + + The log couldn't be saved + 日誌無法儲存 + + + + Logs + 日誌 + + + + LogWindowBase + + + Close + 關閉 + + + + Copy to clipboard + 複製到剪貼簿 + + + + Log Window + 日誌視窗 + + + + Save + 儲存 + + + + &Close + 關閉 (&C) + + + + MiniGui + + + Control bar + 控制列 + + + + MpcGui + + + Control bar + 控制列 + + + + -%1 + -%1 + + + + +%1 + +%1 + + + + Playlist + + + All files + 所有檔案 + + + + Choose a directory + 選取一個目錄 + + + + Choose a file + 選取一個檔案 + + + + Choose a filename + 選取一個檔名 + + + + Confirm overwrite? + 是否覆寫? + + + + &Edit + 編輯(&E) + + + + Edit name + 編輯名字 + + + + Length + 長度 + + + + Name + 名字 + + + + &Play + 播放(&P) + + + + Playlists + 播放清單 + + + + Select one or more files to open + 選擇開啟一個或多個檔案 + + + + The file %1 already exists. +Do you want to overwrite? + 檔案 %1 己存在。 +是否覆寫? + + + + Type the name that will be displayed in the playlist for this file: + 給這個檔案輸入一個顯示於播放清單上的名字: + + + + &Load + 載入(&L) + + + + &Save + 儲存(&S) + + + + &Next + 下一個(&N) + + + + Pre&vious + 上一個(&V) + + + + Move &up + 上移(&U) + + + + Move &down + 下移(&D) + + + + &Repeat + 重複 (&R) + + + + S&huffle + 隨機(&H) + + + + Add &current file + 加入目前的檔案(&C) + + + + Add &file(s) + 加入檔案(&F) + + + + Add &directory + 加入目錄(&D) + + + + Remove &selected + 移除已選取的(&S) + + + + Remove &all + 全部移除(&A) + + + + SMPlayer - Playlist + SMPlayer - 播放清單 + + + + Add... + 加入... + + + + Remove... + 移除... + + + + Playlist modified + 播放清單己修改 + + + + There are unsaved changes, do you want to save the playlist? + 修改尚未儲存,您想儲存播放清單嗎? + + + + Preferences + 偏好設定 + + + + PlaylistPreferences + + + Playlist - Preferences + 播放清單 - 偏好 + + + + Check this option if you want that adding a directory will also add the files in subdirectories recursively. Otherwise only the files in the selected directory will be added. + + + + + &Add files in directories recursively + 在目錄中遞迴地加入檔案(&A) + + + + Check this option to inquire the files to be added to the playlist for some info. That allows to show the title name (if available) and length of the files. Otherwise this info won't be available until the file is actually played. Beware: this option can be slow, specially if you add many files. + + + + + Automatically get &info about files added + 自動取得加入檔案的資訊(&i) + + + + &Save copy of playlist on exit + 在離開的時候儲存播放清單 + + + + &Play files from start + 啟動時播放檔案(&P) + + + + PrefAdvanced + + + Advanced + 進階 + + + + Auto + 自動 + + + + &Advanced + 進階(&A) + + + + icon + 圖示 + + + + Run MPlayer in its own window + 讓 Mplayer 在自己的視窗裡運行 + + + + Here you can pass extra options to MPlayer. +Write them separated by spaces. +Example: -flip -nosound + 在這裡你可以傳遞額外的選項给 Mplayer。 +請用空格分隔它們。 +範例 : -flip -nosound + + + + You can also pass additional video filters. +Separate them with ",". Do not use spaces! +Example: scale=512:-2,eq2=1.1 + 在這裡你可以傳遞額外的視訊過濾器。 +請用 "," 分隔它們。不要使用空格! +範例: scale=512:-2,eq2=1.1 + + + + And finally audio filters. Same rule as for video filters. +Example: resample=44100:0:0,volnorm + 音訊過濾器。規則和視訊過濾器一樣。 +範例: resample=44100:0:0,volnorm + + + + Log MPlayer output + 日誌 MPlayer 的輸出 + + + + Log SMPlayer output + 日誌 SMPlayer 的輸出 + + + + This option is mainly intended for debugging the application. + 這個選項主要用於此應用程式的除錯。 + + + + Checking this option may reduce flickering, but it also might produce that the video won't be displayed properly. + 選擇這個選項可以減少閃爍。但也可能造成視訊不能正常顯示。 + + + + Filter for SMPlayer logs + SMPlayer 日誌過濾器 + + + + &Monitor aspect: + 顯示器外觀(&M): + + + + &Run MPlayer in its own window + 於 MPlayer 的視窗執行(&R) + + + + &Options: + 選項(&O): + + + + V&ideo filters: + 視訊過濾器(&I): + + + + Audio &filters: + 音訊過濾器(&F): + + + + &Colorkey: + + + + + Log &SMPlayer output + 日誌 &SMPlayer 的輸出 + + + + &Filter for SMPlayer logs: + SMPlayer 日誌過濾器(&F): + + + + C&hange... + 改變(&H)... + + + + Logs + 日誌 + + + + Log MPlayer &output + 日誌 MPlayer 的輸出(&o) + + + + Options for MP&layer + Mplayer 的選項(&l) + + + + Autosave MPlayer log + 自動儲存MPlayer日誌 + + + + If this option is checked, the MPlayer log will be saved to the specified file every time a new file starts to play. It's intended for external applications, so they can get info about the file you're playing. + + + + + Autosave MPlayer log filename + 自動儲存 MPlayer 日誌檔名 + + + + Enter here the path and filename that will be used to save the MPlayer log. + + + + + A&utosave MPlayer log to file + + + + + Pass short filenames (8+3) to MPlayer + + + + + Currently MPlayer can't open filenames which contains characters outside the local codepage. Checking this option will make SMPlayer to pass to MPlayer the short version of the filenames, and thus it will able to open them. + + + + + &Pass short filenames (8+3) to MPlayer + + + + + Monitor aspect + 顯示器外觀 + + + + Select the aspect ratio of your monitor. + 選擇您的顯示器外觀比例。 + + + + If you check this option, the MPlayer video window won't be embedded in SMPlayer's main window but instead it will use its own window. Note that mouse and keyboard events will be handled directly by MPlayer, that means key shortcuts and mouse clicks probably won't work as expected when the MPlayer window has the focus. + + + + + Colorkey + + + + + If you see parts of the video over any other window, you can change the colorkey to fix it. Try to select a color close to black. + + + + + Options for MPlayer + Mplayer 選項 + + + + Options + 選項 + + + + Here you can type options for MPlayer. Write them separated by spaces. + + + + + Video filters + 視訊過濾器 + + + + Here you can add video filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Audio filters + 音訊過濾器 + + + + Here you can add audio filters for MPlayer. Write them separated by commas. Don't use spaces! + + + + + Repaint the background of the video window + + + + + Repaint the backgroun&d of the video window + + + + + IPv4 + + + + + Use IPv4 on network connections. Falls back on IPv6 automatically. + + + + + IPv6 + + + + + Use IPv6 on network connections. Falls back on IPv4 automatically. + + + + + Network Connection + 網路連結 + + + + IPv&4 + + + + + IPv&6 + + + + + Lo&gs + 日誌(&g) + + + + Rebuild index if needed + 如果需要時重建索引 + + + + Rebuild &index if needed + 如果需要時重建索引(&i) + + + + If this option is checked, SMPlayer will store the debugging messages that SMPlayer outputs (you can see the log in <b>Options -> View logs -> SMPlayer</b>). This information can be very useful for the developer in case you find a bug. + + + + + If checked, SMPlayer will store the output of MPlayer (you can see it in <b>Options -> View logs -> MPlayer</b>). In case of problems this log can contain important information, so it's recommended to keep this option checked. + + + + + This option allows to filter the SMPlayer messages that will be stored in the log. Here you can write any regular expression.<br>For instance: <i>^Core::.*</i> will display only the lines starting with <i>Core::</i> + + + + + Correct pts + + + + + Switches MPlayer to an experimental mode where timestamps for video frames are calculated differently and video filters which add new frames or modify timestamps of existing ones are supported. The more accurate timestamps can be visible for example when playing subtitles timed to scene changes with the SSA/ASS library enabled. Without correct pts the subtitle timing will typically be off by some frames. This option does not work correctly with some demuxers and codecs. + + + + + Proxy + + + + + Enable proxy + + + + + Enable/disable the use of the proxy. + + + + + Host + + + + + The host name of the proxy. + + + + + Port + + + + + The port of the proxy. + + + + + Username + + + + + If the proxy requires authentication, this sets the username. + + + + + Password + + + + + You can set a proxy for internet connections (currently only used for subtitle downloading). + + + + + &Enable proxy + + + + + &Host: + + + + + &Port: + + + + + &Username: + + + + + Pa&ssword: + + + + + C&orrect PTS + + + + + Http + + + + + Socks5 + + + + + Type + 類型 + + + + Select the proxy type to be used. + + + + + &Type: + + + + + Actions list + + + + + Here you can specify a list of <i>actions</i> which will be run every time a file is opened. You'll find all available actions in the key shortcut editor in the <b>Keyboard and mouse</b> section. The actions must be separated by spaces. Checkable actions can be followed by <i>true</i> or <i>false</i> to enable or disable the action. + + + + + Limitation: the actions are run only when a file is opened and not when the mplayer process is restarted (e.g. you select an audio or video filter). + + + + + Network + + + + + R&un the following actions every time a file is opened. The actions must be separated with spaces: + + + + + &Network + + + + + Example: + + + + + Rebuilds index of files if no index was found, allowing seeking. Useful with broken/incomplete downloads, or badly created files. This option only works if the underlying media supports seeking (i.e. not with stdin, pipe, etc).<br> <b>Note:</b> the creation of the index may take some time. + + + + + The password for the proxy. <b>Warning:</b> the password will be saved as plain text in the configuration file. + + + + + PrefAssociations + + + Warning + 警告 + + + + Not all files could be associated. Please check your security permissions and retry. + + + + + File Types + 檔案類型 + + + + Select all + 全選 + + + + Check all file types in the list + 核取清單中所有的檔案類型 + + + + Uncheck all file types in the list + 取消核取在清單中的所有檔案類型 + + + + List of file types + 檔案類型清單 + + + + File types + 檔案類型 + + + + Media files handled by SMPlayer: + SMPlayer 處理的媒體檔案: + + + + Select All + 全選 + + + + Select None + 全部不選 + + + + Check the media file extensions you would like SMPlayer to handle. When you click Apply, the checked files will be associated with SMPlayer. If you uncheck a media type, the file association will be restored. + + + + + Select none + 全部不選 + + + + <b>Note:</b> (Restoration doesn't work on Windows Vista). + <b>注意:</b> (還原無法在 Windows Vista 上使用). + + + + PrefDrives + + + Drives + 磁碟 + + + + icon + 圖示 + + + + CD device + CD 裝置 + + + + Choose your CDROM device. It will be used to play VCDs and Audio CDs. + 選取你的 CDROM 裝置,用其來播放 VCDs 和 音訊 CDs。 + + + + DVD device + DVD 裝置 + + + + Choose your DVD device. It will be used to play DVDs. + 選取你的 DVD 裝置,用其來播放 DVDs。 + + + + Select your &CD device: + 選擇你的 &CD 裝置: + + + + Select your &DVD device: + 選擇你的 &DVD 裝置: + + + + SMPlayer does not choose any CDROM or DVD devices by default. So before you can actually play a CD or DVD you have to select the devices you want to use (they can be the same). + + + + + PrefGeneral + + + General + 一般 + + + + &General + 一般 (&G) + + + + Paths + 路徑 + + + + Media settings + 媒體設定 + + + + Preferred audio and subtitles + 偏好的音訊和字幕 + + + + Video + 視訊 + + + + Start videos in fullscreen + 以全螢幕啟動視訊 + + + + Disable screensaver + 停用螢幕保護程式 + + + + Audio + 音訊 + + + + Select the mplayer executable + 選擇 Mplayer 的可執行檔 + + + + Executables + 可執行 + + + + All files + 所有檔案 + + + + Select a directory + 選擇一個目錄 + + + + MPlayer executable + Mplayer 可執行 + + + + Screenshots folder + 螢幕擷圖資料夾 + + + + Video output driver + 視訊輸出驅動程式 + + + + Audio output driver + 音訊輸出驅動程式 + + + + Select the audio output driver. + 選擇音訊輸出驅動程式。 + + + + Remember settings + 記住設定 + + + + Preferred audio language + 偏好的音訊語言 + + + + Preferred subtitle language + 偏好的字幕語言 + + + + Software video equalizer + 軟體視訊等化器 + + + + You can check this option if video equalizer is not supported by your graphic card or the selected video output driver.<br><b>Note:</b> this option can be incompatible with some video output drivers. + 如果視訊等化器不被您的顯示卡或選擇的輸出驅動程式支持,您可以勾選此選項。<br><b>注意:</b>這個選項可能和一些影像輸出驅動程式不相容。 + + + + If this option is checked, all videos will start to play in fullscreen mode. + 如果勾選此選項,所有的視訊將一開始就使用全螢幕模式。 + + + + Software volume control + 軟體音量控制 + + + + Check this option to use the software mixer, instead of using the sound card mixer. + 勾選這個選項以使用軟體混音(不使用音效卡混音)。 + + + + Postprocessing quality + 後處理品質 + + + + Dynamically changes the level of postprocessing depending on the available spare CPU time. The number you specify will be the maximum level used. Usually you can use some big number. + Dynamically changes the level of postprocessing depending on the available spare CPU time. 這個數字說明將被用到的最大級别。通常您可以選用較大的數字。 + + + + Direct rendering + 直接轉譯 + + + + Double buffering + 雙重緩衝 + + + + Double buffering fixes flicker by storing two frames in memory, and displaying one while decoding another. If disabled it can affect OSD negatively, but often removes OSD flickering. + + + + + Change volume + 改變音量 + + + + If checked, SMPlayer will remember the volume for every file and will restore it when played again. For new files the default volume will be used. + + + + + Select the &MPlayer executable: + 選擇 Mplayer 的可執行檔(&M): + + + + &Folder for storing screenshots: + 儲存螢幕擷圖的資料夾(&F): + + + + &Audio: + 音訊(&A): + + + + &Remember settings for all files (audio track, subtitles...) + 記住所有檔案設定(曲目、字幕...)(&R) + + + + Su&btitles: + 字幕(&b): + + + + &Enable postprocessing by default + + + + + &Quality: + 品質(&Q): + + + + D&irect rendering + 直接轉譯(&i) + + + + Dou&ble buffering + 雙重緩衝(&b) + + + + Start videos in &fullscreen + 以全螢幕啟動視訊(&f) + + + + Disable &screensaver + 停用螢幕保護程式(&s) + + + + &Default volume: + 預設音量(&D) + + + + 0 + 0 + + + + Use s&oftware volume control + 使用軟體音量控制(&o) + + + + Ma&x. Amplification: + 最大增幅(&x): + + + + &AC3/DTS pass-through S/PDIF + + + + + Volume &normalization by default + 預設音量標準化(&n) + + + + &Change volume on every file + + + + + Close when finished + 結束時關閉 + + + + If this option is checked, the main window will be automatically closed when the current file/playlist finishes. + + + + + 2 (Stereo) + 2 (立體聲) + + + + 4 (4.0 Surround) + 4 (4.0 環場音效) + + + + 6 (5.1 Surround) + 6 (5.1 環場音效) + + + + C&hannels by default: + 預設的頻道(&h): + + + + &Pause when minimized + 當最小化時暫停(&P) + + + + Pause when minimized + 當最小化時暫停 + + + + Enable postprocessing by default + + + + + Max. Amplification + 最大增幅 + + + + AC3/DTS pass-through S/PDIF + + + + + Volume normalization by default + 預設音量標準化 + + + + Maximizes the volume without distorting the sound. + + + + + Default volume + 預設音量 + + + + Sets the initial volume that new files will use. + + + + + Channels by default + 預設的頻道 + + + + Sets the maximum amplification level in percent (default: 110). A value of 200 will allow you to adjust the volume up to a maximum of double the current level. With values below 100 the initial volume (which is 100%) will be above the maximum, which e.g. the OSD cannot display correctly. + + + + + Uses hardware AC3 passthrough + + + + + Postprocessing will be used by default on new opened files. + 後處理在新開啟的檔案中會被使用為預設值 + + + + Audio track + 曲目 + + + + Specifies the default audio track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred audio language"</i> has preference over this option. + + + + + Subtitle track + + + + + Specifies the default subtitle track which will be used when playing new files. If the track doesn't exist, the first one will be used. <br><b>Note:</b> the <i>"preferred subtitle language"</i> has preference over this option. + + + + + Or choose a track number: + 或是選擇一個軌道號碼: + + + + Audi&o: + 音訊(&o): + + + + Preferred language: + 偏好的語言: + + + + Preferre&d audio and subtitles + 偏好的音訊和字幕(&d) + + + + &Subtitle: + 字幕(&S): + + + + Here you can type your preferred language for the audio and subtitle streams. When a media with multiple audio or subtitle streams is found, SMPlayer will try to use your preferred language. This only will work with media that offer info about the language of audio and subtitle streams, like DVDs or mkv files.<br>These fields accept regular expressions. Example: <b>es|esp|spa</b> will select the track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + <Here it goes an explanation text> +For translators: don't translate this text, it will be replaced with another one at runtime. + + + + + High speed &playback without altering pitch + + + + + High speed playback without altering pitch + + + + + Allows to change the playback speed without altering pitch. Requires at least MPlayer dev-SVN-r24924. + + + + + Change volume just before playing + 播放前改變音量 + + + + &Video + 視訊(&V) + + + + Use s&oftware video equalizer + 使用軟體視訊等化器(&o) + + + + A&udio + 音訊(&u) + + + + Volume + 音量 + + + + None + + + + + Lowpass5 + + + + + Yadif (normal) + Yadif (正常) + + + + Yadif (double framerate) + + + + + Linear Blend + 線性混合 + + + + Kerndeint + + + + + Dei&nterlace by default: + + + + + Deinterlace by default + + + + + Select the deinterlace filter that you want to be used for new videos opened. + + + + + Remember time position + 記住時間位置 + + + + Remember &time position + 記住時間位置(&t) + + + + Change volume just before p&laying + 播放前改變音量(&l) + + + + Enable the audio equalizer + 啟用音訊等化器 + + + + Check this option if you want to use the audio equalizer. + 如果您想使用音訊等化器,請勾選此選項。 + + + + &Enable the audio equalizer + 啟用音訊等化器(&E) + + + + Draw video using slices + + + + + Enable/disable drawing video by 16-pixel height slices/bands. If disabled, the whole frame is drawn in a single run. May be faster or slower, depending on video card and available cache. It has effect only with libmpeg2 and libavcodec codecs. + + + + + Dra&w video using slices + + + + + &Close when finished playback + 當播放結束後關閉(&C) + + + + fast + + + + + slow + + + + + fast - ATI cards + 快 - ATI cards + + + + User defined... + 使用者定義 + + + + Default zoom + + + + + This option sets the default zoom which will be used for new videos. + + + + + Default &zoom: + + + + + Here you must specify the mplayer executable that SMPlayer will use.<br>SMPlayer requires at least MPlayer 1.0rc1 (although a recent revision from SVN is highly recommended). + + + + + If this setting is wrong, SMPlayer won't be able to play anything! + + + + + Here you can specify a folder where the screenshots taken by SMPlayer will be stored. If this field is empty the screenshot feature will be disabled. + + + + + Select the video output driver. %1 provides the best performance. + + + + + %1 is the recommended one. Try to avoid %2 and %3, they are slow and can have an impact on performance. + + + + + Usually SMPlayer will remember the settings for each file you play (audio track selected, volume, filters...). Disable this option if you don't like this feature. + + + + + If this option is enabled, the file will be paused when the main window is hidden. When the window is restored, playback will be resumed. + + + + + Check this option to disable the screensaver while playing.<br>The screensaver will enabled again when play finishes. + + + + + Here you can type your preferred language for the audio streams. When a media with multiple audio streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the audio streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the audio track if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Here you can type your preferred language for the subtitle stream. When a media with multiple subtitle streams is found, SMPlayer will try to use your preferred language.<br>This only will work with media that offer info about the language of the subtitle streams, like DVDs or mkv files.<br>This field accepts regular expressions. Example: <b>es|esp|spa</b> will select the subtitle stream if it matches with <i>es</i>, <i>esp</i> or <i>spa</i>. + + + + + Ou&tput driver: + + + + + If this option is checked the initial volume will be set just before playback starts. This avoids a loud volume on startup. Requires at least MPlayer SVN r27872. + + + + + Add black borders on fullscreen + + + + + If this option is enabled, black borders will be added to the image in fullscreen mode. This allows subtitles to be displayed on the black borders. + + + + + &Add black borders on fullscreen + + + + + one ini file + + + + + multiple ini files + + + + + Method to store the file settings + + + + + This option allows to change the way the file settings would be stored. The following options are available: + + + + + <b>one ini file</b>: the settings for all played files will be saved in a single ini file (%1) + + + + + The latter method could be faster if there is info for a lot of files. + + + + + &Store settings in + + + + + <b>multiple ini files</b>: one ini file will be used for each played file. Those ini files will be saved in the folder %1 + + + + + If you check this option, SMPlayer will remember the last position of the file when you open it again. This option works only with regular files (not with DVDs, CDs, URLs...). + + + + + If checked, turns on direct rendering (not supported by all codecs and video outputs)<br><b>Warning:</b> May cause OSD/SUB corruption! + + + + + Requests the number of playback channels. MPlayer asks the decoder to decode the audio into as many channels as specified. Then it is up to the decoder to fulfill the requirement. This is usually only important when playing videos with AC3 audio (like DVDs). In that case liba52 does the decoding by default and correctly downmixes the audio into the requested number of channels. <b>Note</b>: This option is honored by codecs (AC3 only), filters (surround) and audio output drivers (OSS at least). + + + + + PrefInput + + + Keyboard and mouse + 鍵盤和滑鼠 + + + + &Keyboard + 鍵盤(&K) + + + + icon + 圖示 + + + + Here you can change any key shortcut. To do it double click or start typing over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + 在這裡您可以更改任何快捷鍵。通過在一個快捷鍵單元格双擊或鍵入來設定。 +您也可以儲存您的設定,然後分享给他人或載入别的電腦上。 + + + + &Mouse + 滑鼠(&M) + + + + Button functions: + 按鈕功能: + + + + Left click + 左擊 + + + + Double click + 雙擊 + + + + Media seeking + 媒體定位 + + + + Volume control + 音量控制 + + + + Zoom video + 縮放視訊 + + + + None + + + + + Here you can change any key shortcut. To do it double click or press enter over a shortcut cell. Optionally you can also save the list to share it with other people or load it in another computer. + + + + + &Left click + 左擊(&L) + + + + &Double click + 雙擊(&D) + + + + &Wheel function: + 滾輪功能(&W): + + + + Shortcut editor + 捷徑編輯器 + + + + This table allows you to change the key shortcuts of most available actions. Double click or press enter on a item, or press the <b>Change shortcut</b> button to enter in the <i>Modify shortcut</i> dialog. There are two ways to change a shortcut: if the <b>Capture</b> button is on then just press the new key or combination of keys that you want to assign for the action (unfortunately this doesn't work for all keys). If the <b>Capture</b> button is off then you could enter the full name of the key. + + + + + Select the action for left click on the mouse. + + + + + Select the action for double click on the mouse. + + + + + Wheel function + 滾輪功能 + + + + Select the action for the mouse wheel. + + + + + Play + 播放 + + + + Pause + 暫停 + + + + Stop + 停止 + + + + Fullscreen + 全螢幕 + + + + Compact + 精簡模式 + + + + Screenshot + 螢幕擷圖 + + + + On top + 頂部 + + + + Mute + 静音 + + + + Frame counter + + + + + Reset zoom + 重設縮放 + + + + Exit fullscreen + 退出全螢幕 + + + + Double size + 兩倍大小 + + + + Play / Pause + 播放 / 暫停 + + + + Pause / Frame step + 暫停 / Frame step + + + + Playlist + 播放清單 + + + + Preferences + 偏好設定 + + + + No function + 無功能 + + + + Change speed + 改變速度 + + + + Normal speed + 正常速度 + + + + Keyboard + 鍵盤 + + + + Mouse + 滑鼠 + + + + Middle click + 中擊 + + + + Select the action for middle click on the mouse. + + + + + M&iddle click + 中擊(&i) + + + + X Button &1 + + + + + X Button &2 + + + + + Go backward (short) + 向後(短) + + + + Go backward (medium) + 向後(中) + + + + Go backward (long) + 向後(長) + + + + Go forward (short) + 向前(短) + + + + Go forward (medium) + 向前(中) + + + + Go forward (long) + 向前(長) + + + + OSD - Next level + OSD - 下一級別 + + + + Show context menu + 顯示內容功能表 + + + + &Right click + 右擊(&R) + + + + Increase volume + 提高音量 + + + + Decrease volume + 降低音量 + + + + X Button 1 + + + + + Select the action for the X button 1. + + + + + X Button 2 + + + + + Select the action for the X button 2. + + + + + Show video equalizer + + + + + Show audio equalizer + + + + + Always on top + + + + + Never on top + + + + + On top while playing + + + + + PrefInterface + + + Interface + 界面 + + + + <Autodetect> + <自動偵測> + + + + Short jump + 短跳躍 + + + + Medium jump + 跳躍 + + + + Long jump + 長跳躍 + + + + Mouse wheel jump + 滑鼠滾輪跳躍 + + + + Default + 預設 + + + + &Interface + 界面(&I) + + + + Seeking + 定位 + + + + Never + 從不 + + + + Whenever it's needed + 當需要的時後 + + + + Only after loading a new video + 只在新影片載入後 + + + + Use only one running instance of SMPlayer + 只使用一個運行的 SMPlayer 實體 + + + + Recent files + 最近使用的檔案 + + + + Language + 語言 + + + + &Short jump + 短跳躍(&S) + + + + &Medium jump + 跳躍(&M) + + + + &Long jump + 長跳躍(&L) + + + + Mouse &wheel jump + 滑鼠滾輪跳躍(&w) + + + + Here you can change the language of the application. + 你可以改變應用程式的語言 + + + + &Use only one running instance of SMPlayer + 只使用一個運行的 SMPlayer 實體(&U) + + + + St&yle: + 樣式(&y): + + + + L&anguage: + 語言 (&a): + + + + Ico&n set: + 圖示集(&n): + + + + Ma&x. items + 最大項目(&x): + + + + Main window + 主視窗 + + + + Auto&resize: + 自動調整大小(&r): + + + + R&emember position and size + 記住位置和大小(&e) + + + + Default font: + 預設字體: + + + + &Change... + 改變(&C)... + + + + &Behaviour of time slider: + 時間滑動軸的行為(&B): + + + + Seek to position while dragging + + + + + Seek to position when released + + + + + TextLabel + 文字標籤 + + + + &Seeking + 定位(&S) + + + + Ins&tances + 實體(&t) + + + + Autoresize + 自動調整大小 + + + + The main window can be resized automatically. Select the option you prefer. + 主視窗可以自動地重新調整大小。選擇你喜歡的選項。 + + + + Remember position and size + 記住位置和大小 + + + + If you check this option, the position and size of the main window will be saved and restored when you run SMPlayer again. + + + + + Select the maximum number of items that will be shown in the <b>Open->Recent files</b> submenu. If you set it to 0 that menu won't be shown at all. + + + + + Icon set + 圖示集 + + + + Select the icon set you prefer for the application. + 選擇你喜歡的圖示集 + + + + Style + 樣式 + + + + Select the style you prefer for the application. + 選擇你喜歡的樣式 + + + + Default font + 預設字體 + + + + You can change here the application's font. + 你可以改變應用程式的自體 + + + + Select the time that should be go forward or backward when you choose the %1 action. + + + + + short jump + 短跳躍 + + + + medium jump + 跳躍 + + + + long jump + 長跳躍 + + + + Select the time that should be go forward or backward when you move the mouse wheel. + + + + + Behaviour of time slider + 時間滑動軸的行為 + + + + Select what to do when dragging the time slider. + + + + + Instances + 實體 + + + + Check this option if you want to use an already running instance of SMPlayer when opening other files. + + + + + SMPlayer needs to listen to a port to receive commands from other instances. You can change the port in case the default one is used by another application. + + + + + Default GUI + 預設圖形使用者介面 (GUI) + + + + Mini GUI + 迷你圖形使用者介面 + + + + GUI + 圖形使用者介面 (GUI) + + + + Select the GUI you prefer for the application. Currently there are two available: Default GUI and Mini GUI.<br>The <b>Default GUI</b> provides the traditional GUI, with the toolbar and control bar. The <b>Mini GUI</b> provides a more simple GUI, without toolbar and a control bar with few buttons.<br><b>Note:</b> this option will take effect the next time you run SMPlayer. + + + + + &GUI + 圖形使用者界面 (&GUI) + + + + Automatic port + 自動的連接埠 + + + + SMPlayer needs to listen to a port to receive commands from other instances. If you select this option, a port will be automatically chosen. + + + + + Manual port + 手動的連接埠 + + + + Port to listen + + + + + &Automatic + 自動(&A) + + + + &Manual + 手動(&M) + + + + Floating control + + + + + Animated + + + + + If this option is enabled, the floating control will appear with an animation. + + + + + Width + + + + + Specifies the width of the control (as a percentage). + + + + + Margin + + + + + This option sets the number of pixels that the floating control will be away from the bottom of the screen. Useful when the screen is a TV, as the overscan might prevent the control to be visible. + + + + + Display in compact mode too + + + + + Bypass window manager + + + + + If this option is checked, the control is displayed bypassing the window manager. Disable this option if the floating control doesn't work well with your window manager. + + + + + &Floating control + + + + + The floating control appears in fullscreen mode when the mouse is moved to the bottom of the screen. + + + + + &Animated + + + + + &Width: + + + + + 0 + 0 + + + + &Margin: + + + + + Display in &compact mode too + + + + + &Bypass window manager + + + + + If this option is enabled, the floating control will appear in compact mode too. <b>Warning:</b> the floating control has not been designed for compact mode and it might not work properly. + + + + + Mpc GUI + + + + + PrefPerformance + + + Performance + 效能 + + + + &Performance + 效能(&P) + + + + Priority + 優先等級 + + + + Select the priority for the MPlayer process. + 選擇 MPlayer 程式的優先等級。 + + + + realtime + 即時 + + + + high + + + + + abovenormal + 高於標準 + + + + normal + 標準 + + + + belownormal + 低於標準 + + + + idle + 閒置 + + + + Cache + 快取 + + + + KB + KB + + + + Setting a cache may improve performance on slow media + 設定快取可以改進播放性能 + + + + Allow frame drop + Allow frame drop + + + + Synchronization + 同步化 + + + + Audio/video auto synchronization + 音訊/視訊 自動同步化 + + + + Fast audio track switching + 快速音軌切換 + + + + Fast seek to chapters in dvds + 在 DVD 裡快速定位章節 + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>WARNING:</b> Using realtime priority can cause system lockup. + 為 MPlayer 設置優先等級 (根據 Windows 下的命名習慣)。<br><b>警告:</b> 使用即時會將您的系统鎖死。 + + + + Skip displaying some frames to maintain A/V sync on slow systems. + 在較慢的系统上,跳過一些幀來保證 A/V 同步。 + + + + Allow hard frame drop + + + + + More intense frame dropping (breaks decoding). Leads to image distortion! + 大量幀被跳過(解碼錯誤)。將導致畫面變形! + + + + Gradually adjusts the A/V sync based on audio delay measurements. + 根據音訊延遲來調整 A/V 同步。 + + + + Priorit&y: + 優先順序(&y): + + + + &Allow frame drop + + + + + Allow &hard frame drop (can lead to image distortion) + + + + + Audio/&video auto synchronization + 音訊/視訊自動同步化(&v) + + + + Fact&or: + 因子(&o): + + + + &Fast audio track switching + 快速音軌切換(&F) + + + + Fast &seek to chapters in dvds + 在 DVD 裡快速定位章節(&s) + + + + If checked, it will try the fastest method to seek to chapters but it might not work with some discs. + + + + + Skip loop filter + + + + + H.264 + + + + + Possible values:<br> <b>Yes</b>: it will try the fastest method to switch the audio track (it might not work with some formats).<br> <b>No</b>: the MPlayer process will be restarted whenever you change the audio track.<br> <b>Auto</b>: SMPlayer will decide what to do according to the MPlayer version. + + + + + Cache for files + 檔案的快取 + + + + This option specifies how much memory (in kBytes) to use when precaching a file. + + + + + Cache for streams + 串流的快取 + + + + This option specifies how much memory (in kBytes) to use when precaching a URL. + + + + + Cache for DVDs + DVD 的快取 + + + + This option specifies how much memory (in kBytes) to use when precaching a DVD.<br><b>Warning:</b> Seeking might not work properly (including chapter switching) when using a cache for DVDs. + + + + + &Cache + 快取(&C) + + + + Cache for &DVDs: + &DVD 的快取: + + + + Cache for &local files: + 本機檔案的快取(&l): + + + + Cache for &streams: + 串流的快取(&s): + + + + Enabled + 啟用 + + + + Skip (always) + 自動跳過 + + + + Skip only on HD videos + 僅在高解析度影片跳過 + + + + Loop &filter + + + + + This option allows to skips the loop filter (AKA deblocking) during H.264 decoding. Since the filtered frame is supposed to be used as reference for decoding dependent frames this has a worse effect on quality than not doing deblocking on e.g. MPEG-2 video. But at least for high bitrate HDTV this provides a big speedup with no visible quality loss. + + + + + Possible values: + 可能值: + + + + <b>Enabled</b>: the loop filter is not skipped + + + + + <b>Skip (always)</b>: the loop filter is skipped no matter the resolution of the video + + + + + <b>Skip only on HD videos</b>: the loop filter will be skipped only on videos which height is %1 or greater. + + + + + Cache for audio CDs + 音訊 CD 的快取 + + + + This option specifies how much memory (in kBytes) to use when precaching an audio CD. + + + + + Cache for &audio CDs: + 音訊 CD 的快取(&a): + + + + Cache for VCDs + VCD 的快取 + + + + This option specifies how much memory (in kBytes) to use when precaching a VCD. + + + + + Cache for &VCDs: + &VCD 的快取: + + + + Threads for decoding + 解碼中的執行緒 + + + + Sets the number of threads to use for decoding. Only for MPEG-1/2 and H.264 + + + + + &Threads for decoding (MPEG-1/2 and H.264 only): + 解碼中的執行緒 (僅 MPEG-1/2 和 H.264)(&T): + + + + Set process priority for mplayer according to the predefined priorities available under Windows.<br><b>Warning:</b> Using realtime priority can cause system lockup. + + + + + PrefPlaylist + + + Playlist + 播放清單 + + + + Automatically add files to playlist + + + + + If this option is enabled, every time a file is opened, SMPlayer will first clear the playlist and then add the file to it. In case of DVDs, CDs and VCDs, all titles in the disc will be added to the playlist. + + + + + Add consecutive files + + + + + If this option is enabled, SMPlayer will look for consecutive files (e.g. video_1.avi, video_2.avi...) and if found, they'll be added to the playlist. + + + + + &Playlist + 播放清單(&P) + + + + &Automatically add files to playlist + + + + + Add &consecutive files + + + + + PrefSubtitles + + + Subtitles + 字幕 + + + + Choose a ttf file + 選取一個 ttf 檔案 + + + + Truetype Fonts + Truetype 字體 + + + + &Subtitles + 字幕(&S) + + + + Autoload + 自動載入 + + + + Select first available subtitle + 選擇第一個可用的字幕 + + + + Same name as movie + 和影片同名的字幕 + + + + All subs containing movie name + 所有包含影片名的字幕 + + + + All subs in directory + 目錄裡的所有字幕 + + + + Position + 位置 + + + + 0 + 0 + + + + Top + 頂部 + + + + Bottom + 底部 + + + + Include subtitles on screenshots + 擷圖包含字幕 + + + + Font + 字體 + + + + Select the font which will be used for subtitles (and OSD): + 選擇字幕 (和 OSD) 的字體: + + + + Size + 大小 + + + + No autoscale + 無自動縮放 + + + + Proportional to movie height + 相對於影片的高度 + + + + Proportional to movie width + 相對於影片的寬度 + + + + Proportional to movie diagonal + 相對於影片的對角線 + + + + Subtitle position + 字幕位置 + + + + This option specifies the position of the subtitles over the video window. <i>100</i> means the bottom, while <i>0</i> means the top. + 這個選項指定字幕在視訊視窗裡的位置。<i>100</i>表示底部, <i>0</i>表示頂部。 + + + + Au&toload subtitles files (*.srt, *.sub...): + 自動載入字幕檔案(*.srt, *.sub...)(&t): + + + + S&elect first available subtitle + 選擇第一個可用的字幕(&e) + + + + &Default subtitle encoding: + 預設的字幕編碼(&D): + + + + Default &position of the subtitles on screen + 螢幕上字幕的預設位置(&p) + + + + &Include subtitles on screenshots + 擷圖包含字幕(&I) + + + + &TTF font: + &TTF 字體: + + + + S&ystem font: + 系統字體(&y): + + + + A&utoscale: + 自動縮放(&u): + + + + Default subtitle encoding + 預設字幕編碼 + + + + TTF font + TTF 字體 + + + + System font + 系統字體 + + + + Here you can select a system font to be used for the subtitles and OSD. <b>Note:</b> requires a MPlayer with fontconfig support. + + + + + Autoscale + 自動縮放 + + + + Text color + 文字色彩 + + + + Select the color for the text of the subtitles. + + + + + Border color + 邊緣色彩 + + + + Select the color for the border of the subtitles. + + + + + Select the subtitle autoload method. + + + + + If there are one or more subtitle tracks available, one of them will be automatically selected, usually the first one, although if one of them matches the user's preferred language that one will be used instead. + + + + + Select the subtitle autoscaling method. + + + + + Select the encoding which will be used for subtitle files by default. + + + + + Try to autodetect for this language + + + + + When this option is on, the encoding of the subtitles will be tried to be autodetected for the given language. It will fall back to the default encoding if the autodetection fails. This option requires a MPlayer compiled with ENCA support. + + + + + Subtitle language + + + + + Select the language for which you want the encoding to be guessed automatically. + + + + + Encoding + + + + + Try to a&utodetect for this language: + + + + + Here you can select a ttf font to be used for the subtitles. Usually you'll find a lot of ttf fonts in %1 + + + + + Outline + + + + + Select the font for the subtitles. + + + + + The size in pixels. + + + + + Bold + + + + + If checked, the text will be displayed in <b>bold</b>. + + + + + Italic + + + + + If checked, the text will be displayed in <i>italic</i>. + + + + + Left margin + + + + + Specifies the left margin in pixels. + + + + + Right margin + + + + + Specifies the right margin in pixels. + + + + + Vertical margin + + + + + Specifies the vertical margin in pixels. + + + + + Horizontal alignment + + + + + Specifies the horizontal alignment. Possible values are left, centered and right. + + + + + Vertical alignment + + + + + Specifies the vertical alignment. Possible values: bottom, middle and top. + + + + + Border style + + + + + Specifies the border style. Possible values: outline and opaque box. + + + + + Shadow + + + + + Si&ze: + + + + + Bol&d + + + + + &Italic + + + + + Colors + + + + + &Text: + + + + + &Border: + + + + + Margins + + + + + L&eft: + + + + + &Right: + + + + + Verti&cal: + + + + + Alignment + + + + + &Horizontal: + + + + + &Vertical: + + + + + Border st&yle: + + + + + &Outline: + + + + + Shado&w: + + + + + The following options allows you to define the style to be used for non-styled subtitles (srt, sub...). + + + + + Left + horizontal alignment + + + + + Centered + horizontal alignment + + + + + Right + horizontal alignment + + + + + Bottom + vertical alignment + 底部 + + + + Middle + vertical alignment + + + + + Top + vertical alignment + 頂部 + + + + Outline + border style + + + + + Opaque box + border style + + + + + If border style is set to <i>outline</i>, this option specifies the width of the outline around the text in pixels. + + + + + If border style is set to <i>outline</i>, this option specifies the depth of the drop shadow behind the text in pixels. + + + + + Enable normal subtitles + + + + + Click this button to select the normal/traditional subtitles. This kind of subtitles can only display white subtitles. + + + + + Enable SSA/ASS subtitles + + + + + Normal subtitles + + + + + This option does NOT change the size of the subtitles in the current video. To do so, use the options <i>Size+</i> and <i>Size-</i> in the subtitles menu. + + + + + Default scale + + + + + This option specifies the default font scale for normal subtitles which will be used for new opened files. + + + + + SSA/ASS subtitles + + + + + This option specifies the default font scale for SSA/ASS subtitles which will be used for new opened files. + + + + + Line spacing + + + + + This specifies the spacing that will be used to separate multiple lines. It can have negative values. + + + + + &Font and colors + + + + + Enable &normal subtitles + + + + + Enable SSA/&ASS subtitles + + + + + Default s&cale: + + + + + Defa&ult scale: + + + + + &Line spacing: + + + + + Click this button to enable the new SSA/ASS library. This allows to display subtitles with multiple colors, fonts... + + + + + Freetype support + + + + + You should normally not disable this option. Do it only if your MPlayer is compiled without freetype support. <b>Disabling this option could make that subtitles won't work at all!</b> + + + + + Freet&ype support + + + + + If this option is checked, the subtitles will appear in the screenshots. <b>Note:</b> it may cause some troubles sometimes. + + + + + PreferencesDialog + + + SMPlayer - Help + SMPlayer - 說明 + + + + OK + 確定 + + + + Cancel + 取消 + + + + Apply + 套用 + + + + Help + 說明 + + + + SMPlayer - Preferences + SMPlayer - 偏好 + + + + QObject + + + will show this message and then will exit. + + + + + the main window will be closed when the file/playlist finishes. + + + + + This is SMPlayer v. %1 running on %2 + 這是 SMPlayer v. %1 運行於 %2 + + + + tries to make a connection to another running instance and send to it the specified action. Example: -send-action pause The rest of options (if any) will be ignored and the application will exit. It will return 0 on success or -1 on failure. + + + + + action_list is a list of actions separated by spaces. The actions will be executed just after loading the file (if any) in the same order you entered. For checkable actions you can pass true or false as parameter. Example: -actions "fullscreen compact true". Quotes are necessary in case you pass more than one action. + + + + + media + 媒體 + + + + if there's another instance running, the media will be added to that instance's playlist. If there's no other instance, this option will be ignored and the files will be opened in a new instance. + 如果另一個實例正在執行, 媒體將加到那個實例的播放清單中。如果沒有其他實例, 這個選項將被忽略, 檔案將會在新的實例中開啟。 + + + + the main window won't be closed when the file/playlist finishes. + 主視窗在檔案或播放清單結束後不關閉。 + + + + the video will be played in fullscreen mode. + 視訊將會在全螢幕模式播放 + + + + the video will be played in window mode. + 視訊將會在視窗模式播放 + + + + Enqueue in SMPlayer + 在 SMPlayer 裡儲入佇列 + + + + opens the mini gui instead of the default one. + 開啟微型圖形使用者界面而不是預設的。 + + + + Restores the old associations and cleans up the registry. + 還原舊的檔案關聯並清除註冊表。 + + + + 'media' is any kind of file that SMPlayer can open. It can be a local file, a DVD (e.g. dvd://1), an Internet stream (e.g. mms://....) or a local playlist in format m3u or pls. If the -playlist option is used, that means that SMPlayer will pass the -playlist option to MPlayer, so MPlayer will handle the playlist, not SMPlayer. + '媒體'是 SMPlayer 可以開啟的任意一種檔案格式。它可以是一個本地檔案,DVD(例如 dvd://1),網際網路串流(例如 mms://....) 或一個 m3u 格式的本地播放清單。如果設定了 -playlist,那意味着 SMPlayer 將將 -playlist 這個選項傳給 MPlayer,所以處理播放清單的將是 MPlayer 不是 SMPlayer。 + + + + Usage: + 用法: + + + + directory + 目錄 + + + + action_name + 動作名稱 + + + + action_list + 動作清單 + + + + opens the default gui. + 開啟預設的圖形使用者界面 + + + + subtitle_file + + + + + specifies the subtitle file to be loaded for the first video. + + + + + %1 second(s) + + + + + + + %1 minute(s) + + + + + + + %1 and %2 + %1 和 %2 + + + + specifies the directory where smplayer will store its configuration files (smplayer.ini, smplayer_files.ini...) + + + + + disabled + aspect_ratio + + + + + auto + aspect_ratio + + + + + unknown + aspect_ratio + + + + + opens the mpc gui. + + + + + QuaZipFile + + + ZIP/UNZIP API error %1 + + + + + SeekWidget + + + icon + 圖示 + + + + label + 標籤 + + + + ShortcutGetter + + + Modify shortcut + 修改捷徑 + + + + Clear + 清除 + + + + Press the key combination you want to assign + 按下你想要的組合鍵 + + + + Capture + 擷取 + + + + Capture keystrokes + 擷取按鍵 + + + + SubChooserDialog + + + Subtitle selection + + + + + This archive contains more than one subtitle file. Please choose the ones you want to extract. + + + + + Select All + 全選 + + + + Select None + 全部不選 + + + + TimeDialog + + + SMPlayer - Seek + SMPlayer - 定位 + + + + &Jump to: + 跳轉到(&J): + + + + TristateCombo + + + Auto + 自動 + + + + Yes + + + + + No + + + + + VideoEqualizer + + + Brightness + 亮度 + + + + Contrast + 對比度 + + + + Gamma + Gamma + + + + Hue + 色調 + + + + Saturation + 飽和度 + + + + &Reset + 重設(&R) + + + + &Set as default values + 設為預設值(&S) + + + + Use the current values as default values for new videos. + 將當前值做為新視訊的預設值。 + + + + Set all controls to zero. + 全部設置為零。 + + + + Video Equalizer + 視訊等化器 + + + + Information + 資訊 + + + + The current values have been stored to be used as default. + 目前的值已被儲存並作為預設的值 + + + + VideoPreview + + + Video preview + + + + + Cancel + 取消 + + + + Generated by SMPlayer + + + + + Creating thumbnails... + + + + + Size: %1 MB + + + + + Length: %1 + + + + + Save file + + + + + Error saving file + 儲存檔案出錯 + + + + The file couldn't be saved + 檔案無法儲存 + + + + Error + 錯誤 + + + + The following error has occurred while creating the thumbnails: + + + + + The temporary directory (%1) can't be created + + + + + The mplayer process didn't run + + + + + Resolution: %1x%2 + + + + + Video format: %1 + + + + + Frames per second: %1 + + + + + Aspect ratio: %1 + + + + + The file %1 can't be loaded + + + + + No filename + + + + + The mplayer process didn't start while trying to get info about the video + + + + + The length of the video is 0 + + + + + The file %1 doesn't exist + + + + + Images + + + + + No info + + + + + %1 kbps + %1 kbps + + + + %1 Hz + %1 Hz + + + + Video bitrate: %1 + + + + + Audio bitrate: %1 + + + + + Audio rate: %1 + + + + + VideoPreviewConfigDialog + + + Default + 預設 + + + + Video Preview + + + + + &File: + + + + + &Columns: + + + + + &Rows: + + + + + &Aspect ratio: + + + + + &Seconds to skip at the beginnning: + + + + + &Maximum width: + + + + + The preview will be created for the video you specify here. + + + + + The thumbnails will be arranged on a table. + + + + + This option specifies the number of columns of the table. + + + + + This option specifies the number of rows of the table. + + + + + If you check this option, the playing time will be displayed at the bottom of each thumbnail. + + + + + If the aspect ratio of the video is wrong, you can specify a different one here. + + + + + Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. This option allows to specify how many seconds will be skipped. + + + + + This option specifies the maximum width in pixels that the generated preview image will have. + + + + + Some frames will be extracted from the video in order to create the preview. Here you can choose the image format for the extracted frames. PNG may give better quality. + + + + + Add playing &time to thumbnails + + + + + &Extract frames as + + + + + Enter here the DVD device or a folder with a DVD image. + + + + + &DVD device: + + + + + VolumeSliderAction + + + Volume + 音量 + + + diff --git a/plugins/smplayer_plugin/translator.cpp b/plugins/smplayer_plugin/translator.cpp new file mode 100644 index 000000000..2419ddf0a --- /dev/null +++ b/plugins/smplayer_plugin/translator.cpp @@ -0,0 +1,63 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "translator.h" +#include "paths.h" +#include +#include +#include + +Translator::Translator() { + qApp->installTranslator( &app_trans ); + qApp->installTranslator( &qt_trans ); +} + +Translator::~Translator() { +} + +bool Translator::loadCatalog(QTranslator & t, QString name, QString locale, QString dir) { + QString s = name + "_" + locale; //.toLower(); + bool r = t.load(s, dir); + if (r) + qDebug("Translator::loadCatalog: successfully loaded %s from %s", s.toUtf8().data(), dir.toUtf8().data()); + else + qDebug("Translator::loadCatalog: can't load %s from %s", s.toUtf8().data(), dir.toUtf8().data()); + return r; +} + +void Translator::load(QString locale) { + if (locale.isEmpty()) { + locale = QLocale::system().name(); + } + + QString trans_path = Paths::translationPath(); + QString qt_trans_path = Paths::qtTranslationPath(); + +#ifdef Q_OS_WIN + // In windows try to load the qt translation from the app path, as + // most users won't have Qt installed. + loadCatalog(qt_trans, "qt", locale, trans_path ); +#else + // In linux try to load it first from app path (in case there's an updated + // translation), if it fails it will try then from the Qt path. + if (! loadCatalog(qt_trans, "qt", locale, trans_path ) ) { + loadCatalog(qt_trans, "qt", locale, qt_trans_path); + } +#endif + loadCatalog(app_trans, "smplayer", locale, trans_path); +} diff --git a/plugins/smplayer_plugin/translator.h b/plugins/smplayer_plugin/translator.h new file mode 100644 index 000000000..cd222d660 --- /dev/null +++ b/plugins/smplayer_plugin/translator.h @@ -0,0 +1,41 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _TRANSLATOR_H_ +#define _TRANSLATOR_H_ + +#include +#include + +class Translator +{ + +public: + Translator(); + ~Translator(); + + void load(QString locale); + +protected: + static bool loadCatalog(QTranslator & t, QString name, QString locale, QString dir); + + QTranslator app_trans; + QTranslator qt_trans; +}; + +#endif diff --git a/plugins/smplayer_plugin/tristatecombo.cpp b/plugins/smplayer_plugin/tristatecombo.cpp new file mode 100644 index 000000000..6c410a142 --- /dev/null +++ b/plugins/smplayer_plugin/tristatecombo.cpp @@ -0,0 +1,58 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "tristatecombo.h" +#include + +TristateCombo::TristateCombo( QWidget * parent ) : QComboBox(parent) +{ + retranslateStrings(); +} + +TristateCombo::~TristateCombo() { +} + +void TristateCombo::retranslateStrings() { + int i = currentIndex(); + + clear(); + addItem( tr("Auto"), Preferences::Detect ); + addItem( tr("Yes"), Preferences::Enabled ); + addItem( tr("No"), Preferences::Disabled ); + + setCurrentIndex(i); +} + +void TristateCombo::setState( Preferences::OptionState v ) { + setCurrentIndex( findData(v) ); +} + +Preferences::OptionState TristateCombo::state() { + return (Preferences::OptionState) itemData( currentIndex() ).toInt(); +} + +// Language change stuff +void TristateCombo::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QComboBox::changeEvent(e); + } +} + +#include "moc_tristatecombo.cpp" diff --git a/plugins/smplayer_plugin/tristatecombo.h b/plugins/smplayer_plugin/tristatecombo.h new file mode 100644 index 000000000..4022b3f1e --- /dev/null +++ b/plugins/smplayer_plugin/tristatecombo.h @@ -0,0 +1,47 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/*! + This class is to replace some QCheckBox with a combo with three possible + values: true, false or autodetect +*/ + +#ifndef _TRISTATE_COMBO_H_ +#define _TRISTATE_COMBO_H_ + +#include +#include "preferences.h" + +class TristateCombo : public QComboBox +{ + Q_OBJECT + +public: + TristateCombo( QWidget * parent = 0 ); + ~TristateCombo(); + + void setState( Preferences::OptionState v ); + Preferences::OptionState state(); + +protected: + virtual void retranslateStrings(); + virtual void changeEvent( QEvent * event ); + +}; + +#endif diff --git a/plugins/smplayer_plugin/urlhistory.cpp b/plugins/smplayer_plugin/urlhistory.cpp new file mode 100644 index 000000000..814d22df9 --- /dev/null +++ b/plugins/smplayer_plugin/urlhistory.cpp @@ -0,0 +1,71 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "urlhistory.h" +#include "constants.h" + +URLHistory::URLHistory() : Recents() +{ +} + +URLHistory::~URLHistory() { +} + +void URLHistory::addUrl(QString url, bool is_playlist) { + qDebug("Recents::addItem: '%s'", url.toUtf8().data()); + + // Delete duplicates + QStringList::iterator iterator = l.begin(); + while (iterator != l.end()) { + QString s = (*iterator); + if (isPlaylist(s)) { + s = s.remove( QRegExp(IS_PLAYLIST_TAG_RX) ); + } + if (s == url) + iterator = l.erase(iterator); + else + iterator++; + } + + // Add new item to list + if (is_playlist) url = url + IS_PLAYLIST_TAG; + l.prepend(url); + + if (l.count() > max_items) l.removeLast(); +} + +void URLHistory::addUrl(QString url) { + bool is_playlist = isPlaylist(url); + if (is_playlist) url = url.remove( QRegExp(IS_PLAYLIST_TAG_RX) ); + addUrl(url, is_playlist); +} + +QString URLHistory::url(int n) { + QString s = l[n]; + if (isPlaylist(n)) s = s.remove( QRegExp(IS_PLAYLIST_TAG_RX) ); + return s; +} + +bool URLHistory::isPlaylist(int n) { + return isPlaylist(l[n]); +} + +bool URLHistory::isPlaylist(QString url) { + return url.endsWith(IS_PLAYLIST_TAG); +} + diff --git a/plugins/smplayer_plugin/urlhistory.h b/plugins/smplayer_plugin/urlhistory.h new file mode 100644 index 000000000..89fd615d8 --- /dev/null +++ b/plugins/smplayer_plugin/urlhistory.h @@ -0,0 +1,44 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _URLHISTORY_H_ +#define _URLHISTORY_H_ + +#include "recents.h" + +class URLHistory : public Recents +{ +public: + URLHistory(); + virtual ~URLHistory(); + + virtual void addUrl(QString url, bool is_playlist); + + //! Adds an URL, autodetects if it's a playlist + virtual void addUrl(QString url); + + //! Returns the URL, without the playlist tag + virtual QString url(int n); + + //! Returns if the item at pos n is a playlist + virtual bool isPlaylist(int n); + + static bool isPlaylist(QString url); +}; + +#endif diff --git a/plugins/smplayer_plugin/version.cpp b/plugins/smplayer_plugin/version.cpp new file mode 100644 index 000000000..b8288eb26 --- /dev/null +++ b/plugins/smplayer_plugin/version.cpp @@ -0,0 +1,35 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "version.h" + +#define USE_SVN_VERSIONS 0 + +#define VERSION "0.6.6 (SVN r2599)" + +#if USE_SVN_VERSIONS +#include "svn_revision.h" +#endif + +QString smplayerVersion() { +#if USE_SVN_VERSIONS + return QString(QString(VERSION) + "+" + QString(SVN_REVISION)); +#else + return QString(VERSION); +#endif +} diff --git a/plugins/smplayer_plugin/version.h b/plugins/smplayer_plugin/version.h new file mode 100644 index 000000000..84e444670 --- /dev/null +++ b/plugins/smplayer_plugin/version.h @@ -0,0 +1,27 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _VERSION_H_ +#define _VERSION_H_ + +#include + +QString smplayerVersion(); + +#endif + diff --git a/plugins/smplayer_plugin/verticaltext.cpp b/plugins/smplayer_plugin/verticaltext.cpp new file mode 100644 index 000000000..eb665ea91 --- /dev/null +++ b/plugins/smplayer_plugin/verticaltext.cpp @@ -0,0 +1,56 @@ +/* + * KMix -- KDE's full featured mini mixer + * + * + * Copyright (C) 2003-2004 Christian Esken + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "verticaltext.h" +#include +#include +/*#include */ + + +VerticalText::VerticalText(QWidget * parent, Qt::WindowFlags f) + : QWidget(parent, f) +{ + resize(20,100 /*parent->height() */ ); + setMinimumSize(20,10); // neccesary for smooth integration into layouts (we only care for the widths). +} + +VerticalText::~VerticalText() { +} + + +void VerticalText::paintEvent ( QPaintEvent * /*event*/ ) { + //kdDebug(67100) << "paintEvent(). height()=" << height() << "\n"; + QPainter paint(this); + paint.rotate(270); + // Fix for bug 72520 + //- paint.drawText(-height()+2,width(),name()); + //+ paint.drawText( -height()+2, width(), QString::fromUtf8(name()) ); + paint.drawText( -height()+2, width(), _label ); +} + +QSize VerticalText::sizeHint() const { + return QSize(20,100); // !! UGLY. Should be reworked +} + +QSizePolicy VerticalText::sizePolicy () const +{ + return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); +} diff --git a/plugins/smplayer_plugin/verticaltext.h b/plugins/smplayer_plugin/verticaltext.h new file mode 100644 index 000000000..e61a33263 --- /dev/null +++ b/plugins/smplayer_plugin/verticaltext.h @@ -0,0 +1,27 @@ +/* Taken from KMix */ +/* Copyright (C) 2003-2004 Christian Esken */ + + +#ifndef VerticalText_h +#define VerticalText_h + +#include +#include + +class VerticalText : public QWidget +{ +public: + VerticalText(QWidget * parent, Qt::WindowFlags f = 0); + ~VerticalText(); + + void setText(QString s) { _label = s; }; + QString text() { return _label; }; + QSize sizeHint() const; + QSizePolicy sizePolicy () const; + +protected: + void paintEvent ( QPaintEvent * event ); + QString _label; +}; + +#endif diff --git a/plugins/smplayer_plugin/videoequalizer.cpp b/plugins/smplayer_plugin/videoequalizer.cpp new file mode 100644 index 000000000..2480ed0b7 --- /dev/null +++ b/plugins/smplayer_plugin/videoequalizer.cpp @@ -0,0 +1,140 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "videoequalizer.h" +#include "eqslider.h" +#include "images.h" +#include "preferences.h" +#include "global.h" +#include +#include +#include + +using namespace Global; + +VideoEqualizer::VideoEqualizer( QWidget* parent, Qt::WindowFlags f) + : QWidget(parent, f) +{ + contrast = new EqSlider(this); + brightness = new EqSlider(this); + hue = new EqSlider(this); + saturation = new EqSlider(this); + gamma = new EqSlider(this); + + QBoxLayout *bl = new QHBoxLayout; //(0, 4, 2); + bl->addWidget(contrast); + bl->addWidget(brightness); + bl->addWidget(hue); + bl->addWidget(saturation); + bl->addWidget(gamma); + + reset_button = new QPushButton( "&Reset", this); + connect( reset_button, SIGNAL(clicked()), this, SLOT(reset()) ); + set_default_button = new QPushButton( "&Set as default values", this ); + connect( set_default_button, SIGNAL(clicked()), this, SLOT(setDefaults()) ); + + QBoxLayout *button_layout = new QVBoxLayout; //(0, 4, 2); + button_layout->addWidget(set_default_button); + button_layout->addWidget(reset_button); + + QBoxLayout *layout = new QVBoxLayout(this); //, 4, 2); + layout->addLayout(bl); + layout->addLayout(button_layout); + + retranslateStrings(); + + adjustSize(); + //setFixedSize( sizeHint() ); +} + +VideoEqualizer::~VideoEqualizer() { +} + +void VideoEqualizer::retranslateStrings() { + setWindowTitle( tr("Video Equalizer") ); + setWindowIcon( Images::icon("logo") ); + + contrast->setLabel( tr("Contrast") ); + contrast->setToolTip( tr("Contrast") ); + contrast->setIcon( Images::icon("contrast") ); + + brightness->setLabel( tr("Brightness") ); + brightness->setToolTip( tr("Brightness") ); + brightness->setIcon( Images::icon("brightness") ); + + hue->setLabel( tr("Hue") ); + hue->setToolTip( tr("Hue") ); + hue->setIcon( Images::icon("hue") ); + + saturation->setLabel( tr("Saturation") ); + saturation->setToolTip( tr("Saturation") ); + saturation->setIcon( Images::icon("saturation") ); + + gamma->setLabel( tr("Gamma") ); + gamma->setToolTip( tr("Gamma") ); + gamma->setIcon( Images::icon("gamma") ); + + reset_button->setText( tr("&Reset") ); + set_default_button->setText( tr("&Set as default values") ); + + // What's this help: + set_default_button->setWhatsThis( + tr("Use the current values as default values for new videos.") ); + + reset_button->setWhatsThis( tr("Set all controls to zero.") ); + +} + +void VideoEqualizer::reset() { + contrast->setValue(0); + brightness->setValue(0); + hue->setValue(0); + saturation->setValue(0); + gamma->setValue(0); +} + +void VideoEqualizer::setDefaults() { + pref->initial_contrast = contrast->value(); + pref->initial_brightness = brightness->value(); + pref->initial_hue = hue->value(); + pref->initial_saturation = saturation->value(); + pref->initial_gamma = gamma->value(); + + QMessageBox::information(this, tr("Information"), + tr("The current values have been stored to be " + "used as default.") ); +} + +void VideoEqualizer::hideEvent( QHideEvent * ) { + emit visibilityChanged(); +} + +void VideoEqualizer::showEvent( QShowEvent * ) { + emit visibilityChanged(); +} + +// Language change stuff +void VideoEqualizer::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QWidget::changeEvent(e); + } +} + +#include "moc_videoequalizer.cpp" diff --git a/plugins/smplayer_plugin/videoequalizer.h b/plugins/smplayer_plugin/videoequalizer.h new file mode 100644 index 000000000..f657eb8eb --- /dev/null +++ b/plugins/smplayer_plugin/videoequalizer.h @@ -0,0 +1,65 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef _VIDEOEQUALIZER_H_ +#define _VIDEOEQUALIZER_H_ + +#include +#include +#include + +class QPushButton; +class EqSlider; + +class VideoEqualizer : public QWidget +{ + Q_OBJECT + +public: + VideoEqualizer( QWidget* parent = 0, Qt::WindowFlags f = Qt::Dialog ); + ~VideoEqualizer(); + + EqSlider * brightness; + EqSlider * contrast; + EqSlider * hue; + EqSlider * saturation; + EqSlider * gamma; + +signals: + void visibilityChanged(); + +public slots: + void reset(); + void setDefaults(); + +protected slots: + virtual void hideEvent( QHideEvent * ); + virtual void showEvent( QShowEvent * ); + +protected: + virtual void retranslateStrings(); + virtual void changeEvent ( QEvent * event ) ; + +protected: + QPushButton * reset_button; + QPushButton * set_default_button; +}; + + +#endif diff --git a/plugins/smplayer_plugin/videopreview/async.diff b/plugins/smplayer_plugin/videopreview/async.diff new file mode 100644 index 000000000..4f126842c --- /dev/null +++ b/plugins/smplayer_plugin/videopreview/async.diff @@ -0,0 +1,309 @@ +Index: videopreview/main.cpp +=================================================================== +--- videopreview/main.cpp (revisin: 2543) ++++ videopreview/main.cpp (copia de trabajo) +@@ -47,11 +47,17 @@ + */ + //vp.setAspectRatio( 2.35 ); + ++#if VIDEOPREVIEW_ASYNC ++ if (vp.showConfigDialog()) { ++ vp.createThumbnails(); ++ return a.exec(); ++ } ++#else + if ( (vp.showConfigDialog()) && (vp.createThumbnails()) ) { + vp.show(); + vp.adjustWindowSize(); + return a.exec(); + } +- ++#endif + return 0; + } +Index: videopreview/videopreview.cpp +=================================================================== +--- videopreview/videopreview.cpp (revisin: 2543) ++++ videopreview/videopreview.cpp (copia de trabajo) +@@ -105,7 +105,15 @@ + my_layout->addWidget(button_box); + setLayout(my_layout); + ++#if VIDEOPREVIEW_ASYNC ++ process = new QProcess(this); ++ connect( process, SIGNAL(finished(int, QProcess::ExitStatus)), ++ this, SLOT(processFinished(int, QProcess::ExitStatus)) ); + ++ connect( this, SIGNAL(finishedOk()), this, SLOT(workFinishedOK()) ); ++ connect( this, SIGNAL(finishedWithError()), this, SLOT(workFinishedWithError()) ); ++#endif ++ + QList r_formats = QImageReader::supportedImageFormats(); + QString read_formats; + for (int n=0; n < r_formats.count(); n++) { +@@ -156,6 +164,132 @@ + return "00000005.jpg"; + } + ++#if VIDEOPREVIEW_ASYNC ++void VideoPreview::createThumbnails() { ++ clearThumbnails(); ++ error_message.clear(); ++ ++ // Initalization ++ VideoInfo i = getInfo(mplayer_bin, prop.input_video); ++ int length = i.length; ++ ++ if (length == 0) { ++ if (error_message.isEmpty()) error_message = tr("The length of the video is 0"); ++ emit finishedWithError(); ++ return; ++ } ++ ++ // Create a temporary directory ++ QDir d(QDir::tempPath()); ++ if (!d.exists(output_dir)) { ++ if (!d.mkpath(output_dir)) { ++ qDebug("VideoPreview::extractImages: error: can't create '%s'", full_output_dir.toUtf8().constData()); ++ error_message = tr("The temporary directory (%1) can't be created").arg(full_output_dir); ++ emit finishedWithError(); ++ return; ++ } ++ } ++ ++ displayVideoInfo(i); ++ ++ // Let's begin ++ run.thumbnail_width = 0; ++ ++ run.num_pictures = prop.n_cols * prop.n_rows; ++ length -= prop.initial_step; ++ run.s_step = length / run.num_pictures; ++ ++ run.current_time = prop.initial_step; ++ ++ canceled = false; ++ progress->setLabelText(tr("Creating thumbnails...")); ++ progress->setRange(0, run.num_pictures-1); ++ ++ run.current_picture = 0; ++ progress->setValue( run.current_picture); ++ ++ if (!runMplayer(run.current_time)) { ++ emit finishedWithError(); ++ } ++} ++ ++void VideoPreview::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { ++ qDebug("VideoPreview::processFinished"); ++ ++ if (exitStatus != QProcess::NormalExit) { ++ emit finishedWithError(); ++ return; ++ } ++ ++ // Continue processing ++ QString frame_picture = full_output_dir + "/" + framePicture(); ++ if (!QFile::exists(frame_picture)) { ++ error_message = tr("The file %1 doesn't exist").arg(frame_picture); ++ emit finishedWithError(); ++ return; ++ } ++ ++#if RENAME_PICTURES ++ QDir d(QDir::tempPath()); ++ QString extension = (extractFormat()==PNG) ? "png" : "jpg"; ++ QString output_file = output_dir + QString("/picture_%1.%2").arg(run.current_time, 8, 10, QLatin1Char('0')).arg(extension); ++ d.rename(output_dir + "/" + framePicture(), output_file); ++#else ++ QString output_file = output_dir + "/" + framePicture(); ++#endif ++ ++ if (!addPicture(QDir::tempPath() +"/"+ output_file, run.current_picture, run.current_time)) { ++ emit finishedWithError(); ++ return; ++ } ++ ++ run.current_time += run.s_step; ++ ++ if (canceled) { ++ emit finishedOk(); ++ return; ++ } ++ ++ // Next picture ++ run.current_picture++; ++ ++ if (run.current_picture >= run.num_pictures) { ++ emit finishedOk(); ++ return; ++ } ++ ++ progress->setValue( run.current_picture); ++ ++ if (!runMplayer(run.current_time)) { ++ emit finishedWithError(); ++ } ++} ++ ++void VideoPreview::workFinishedOK() { ++ qDebug("VideoPreview::workFinishedOK"); ++ ++ show(); ++ adjustWindowSize(); ++ ++ cleanDir(full_output_dir); ++} ++ ++void VideoPreview::workFinishedWithError() { ++ qDebug("VideoPreview::workFinishedWithError"); ++ ++ if (!error_message.isEmpty()) { ++ QMessageBox::critical(this, tr("Error"), ++ tr("The following error has occurred while creating the thumbnails:")+"\n"+ error_message ); ++ } ++ ++ cleanDir(full_output_dir); ++ ++ close(); ++} ++ ++ ++#else // VIDEOPREVIEW_ASYNC ++ + bool VideoPreview::createThumbnails() { + clearThumbnails(); + error_message.clear(); +@@ -244,6 +378,7 @@ + + return true; + } ++#endif // VIDEOPREVIEW_ASYNC + + bool VideoPreview::runMplayer(int seek) { + QStringList args; +@@ -283,6 +418,18 @@ + for (int n = 0; n < args.count(); n++) command = command + args[n] + " "; + qDebug("VideoPreview::runMplayer: command: %s", command.toUtf8().constData()); + ++#if VIDEOPREVIEW_ASYNC ++ #ifdef CD_TO_TEMP_DIR ++ process->setWorkingDirectory(full_output_dir); ++ qDebug("VideoPreview::runMplayer: changing working directory of the process to '%s'", full_output_dir.toUtf8().constData()); ++ #endif ++ process->start(mplayer_bin, args); ++ if (!process->waitForStarted()) { ++ qDebug("VideoPreview::runMplayer: error running process"); ++ error_message = tr("The mplayer process didn't run"); ++ return false; ++ } ++#else // VIDEOPREVIEW_ASYNC + QProcess p; + #ifdef CD_TO_TEMP_DIR + p.setWorkingDirectory(full_output_dir); +@@ -294,6 +441,7 @@ + error_message = tr("The mplayer process didn't run"); + return false; + } ++#endif // VIDEOPREVIEW_ASYNC + + return true; + } +Index: videopreview/videopreview.h +=================================================================== +--- videopreview/videopreview.h (revisin: 2543) ++++ videopreview/videopreview.h (copia de trabajo) +@@ -19,10 +19,16 @@ + #ifndef _VIDEOPREVIEW_H_ + #define _VIDEOPREVIEW_H_ + ++#define VIDEOPREVIEW_ASYNC 0 ++ + #include + #include + #include + ++#if VIDEOPREVIEW_ASYNC ++#include ++#endif ++ + class QProgressDialog; + class QGridLayout; + class QLabel; +@@ -90,7 +96,11 @@ + void setExtractFormat( ExtractFormat format ) { prop.extract_format = format; }; + ExtractFormat extractFormat() { return prop.extract_format; }; + ++#if VIDEOPREVIEW_ASYNC ++ void createThumbnails(); ++#else + bool createThumbnails(); ++#endif + + bool showConfigDialog(); + +@@ -106,8 +116,23 @@ + void cancelPressed(); + void saveImage(); + ++#if VIDEOPREVIEW_ASYNC ++ void processFinished(int exitCode, QProcess::ExitStatus exitStatus); ++ void workFinishedOK(); ++ void workFinishedWithError(); ++ + protected: ++ QProcess * process; ++ ++signals: ++ void finishedOk(); ++ void finishedWithError(); ++#endif ++ ++protected: ++#if !VIDEOPREVIEW_ASYNC + bool extractImages(); ++#endif + bool runMplayer(int seek); + bool addPicture(const QString & filename, int num, int time); + void displayVideoInfo(const VideoInfo & i); +@@ -144,9 +169,19 @@ + ExtractFormat extract_format; + } prop; + ++#if VIDEOPREVIEW_ASYNC + struct { + int thumbnail_width; ++ int num_pictures; ++ int s_step; ++ int current_time; ++ int current_picture; + } run; ++#else ++ struct { ++ int thumbnail_width; ++ } run; ++#endif + + QString last_directory; + QString error_message; +Index: basegui.cpp +=================================================================== +--- basegui.cpp (revisin: 2543) ++++ basegui.cpp (copia de trabajo) +@@ -4022,10 +4022,16 @@ + + video_preview->setMplayerPath(pref->mplayer_bin); + ++#if VIDEOPREVIEW_ASYNC ++ if (video_preview->showConfigDialog()) { ++ video_preview->createThumbnails(); ++ } ++#else + if ( (video_preview->showConfigDialog()) && (video_preview->createThumbnails()) ) { + video_preview->show(); + video_preview->adjustWindowSize(); + } ++#endif + } + + QNetworkProxy BaseGui::userProxy() { diff --git a/plugins/smplayer_plugin/videopreview/main.cpp b/plugins/smplayer_plugin/videopreview/main.cpp new file mode 100644 index 000000000..b1c830bf6 --- /dev/null +++ b/plugins/smplayer_plugin/videopreview/main.cpp @@ -0,0 +1,57 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "videopreview.h" +#include +#include +#include +#include + +int main( int argc, char ** argv ) +{ + QApplication a( argc, argv ); + + QString filename; + + if (a.arguments().count() > 1) { + filename = a.arguments()[1]; + } + + QSettings set(QSettings::IniFormat, QSettings::UserScope, "RVM", "videopreview"); + + VideoPreview vp("mplayer"); + vp.setSettings(&set); + + if (!filename.isEmpty()) + vp.setVideoFile(filename); + + /* + vp.setGrid(4,5); + vp.setMaxWidth(800); + vp.setDisplayOSD(true); + */ + //vp.setAspectRatio( 2.35 ); + + if ( (vp.showConfigDialog()) && (vp.createThumbnails()) ) { + vp.show(); + vp.adjustWindowSize(); + return a.exec(); + } + + return 0; +} diff --git a/plugins/smplayer_plugin/videopreview/videopreview.cpp b/plugins/smplayer_plugin/videopreview/videopreview.cpp new file mode 100644 index 000000000..497497992 --- /dev/null +++ b/plugins/smplayer_plugin/videopreview/videopreview.cpp @@ -0,0 +1,637 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "videopreview.h" +#include "videopreviewconfigdialog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// Workaround for Windows +#ifdef Q_OS_WIN +#define CD_TO_TEMP_DIR 1 +#endif + +#define RENAME_PICTURES 0 + +VideoPreview::VideoPreview(QString mplayer_path, QWidget * parent, Qt::WindowFlags f) : QWidget(parent, f) +{ + setMplayerPath(mplayer_path); + + set = 0; // settings + + prop.input_video.clear(); + prop.dvd_device.clear(); + prop.n_cols = 4; + prop.n_rows = 4; + prop.initial_step = 20; + prop.max_width = 800; + prop.aspect_ratio = 0; + prop.display_osd = true; + prop.extract_format = JPEG; + + output_dir = "smplayer_preview"; + full_output_dir = QDir::tempPath() +"/"+ output_dir; + + progress = new QProgressDialog(this); + progress->setMinimumDuration(0); + connect( progress, SIGNAL(canceled()), this, SLOT(cancelPressed()) ); + + w_contents = new QWidget(this); + QPalette p = w_contents->palette(); + p.setColor(w_contents->backgroundRole(), Qt::white); + w_contents->setPalette(p); + + info = new QLabel(this); + + foot = new QLabel(this); + foot->setAlignment(Qt::AlignRight); + + grid_layout = new QGridLayout; + grid_layout->setSpacing(2); + + QVBoxLayout * l = new QVBoxLayout; + l->setSizeConstraint(QLayout::SetFixedSize); + l->addWidget(info); + l->addLayout(grid_layout); + l->addWidget(foot); + + w_contents->setLayout(l); + + scroll_area = new QScrollArea(this); + scroll_area->setWidgetResizable(true); + scroll_area->setAlignment(Qt::AlignCenter); + scroll_area->setWidget( w_contents ); + + button_box = new QDialogButtonBox(QDialogButtonBox::Close | QDialogButtonBox::Save, Qt::Horizontal, this); + connect( button_box, SIGNAL(rejected()), this, SLOT(close()) ); + connect( button_box->button(QDialogButtonBox::Save), SIGNAL(clicked()), this, SLOT(saveImage()) ); + + QVBoxLayout * my_layout = new QVBoxLayout; + my_layout->addWidget(scroll_area); + my_layout->addWidget(button_box); + setLayout(my_layout); + + retranslateStrings(); + + QList r_formats = QImageReader::supportedImageFormats(); + QString read_formats; + for (int n=0; n < r_formats.count(); n++) { + read_formats.append(r_formats[n]+" "); + } + qDebug("VideoPreview::VideoPreview: supported formats for reading: %s", read_formats.toUtf8().constData()); + + QList w_formats = QImageWriter::supportedImageFormats(); + QString write_formats; + for (int n=0; n < w_formats.count(); n++) { + write_formats.append(w_formats[n]+" "); + } + qDebug("VideoPreview::VideoPreview: supported formats for writing: %s", write_formats.toUtf8().constData()); +} + +VideoPreview::~VideoPreview() { + if (set) saveSettings(); +} + +void VideoPreview::retranslateStrings() { + progress->setWindowTitle(tr("Video preview")); + progress->setCancelButtonText( tr("Cancel") ); + + foot->setText(""+ tr("Generated by SMPlayer") +" (http://smplayer.sf.net)"); +} + +void VideoPreview::setMplayerPath(QString mplayer_path) { + mplayer_bin = mplayer_path; + QFileInfo fi(mplayer_bin); + if (fi.exists() && fi.isExecutable() && !fi.isDir()) { + mplayer_bin = fi.absoluteFilePath(); + } + + qDebug("VideoPreview::setMplayerPath: mplayer_bin: '%s'", mplayer_bin.toUtf8().constData()); +} + +void VideoPreview::setSettings(QSettings * settings) { + set = settings; + loadSettings(); +} + +void VideoPreview::clearThumbnails() { + for (int n=0; n < label_list.count(); n++) { + grid_layout->removeWidget( label_list[n] ); + delete label_list[n]; + } + label_list.clear(); + info->clear(); +} + +QString VideoPreview::framePicture() { + if (prop.extract_format == PNG) + return "00000005.png"; + else + return "00000005.jpg"; +} + +bool VideoPreview::createThumbnails() { + clearThumbnails(); + error_message.clear(); + + button_box->setEnabled(false); + + bool result = extractImages(); + + progress->close(); + + if ((result == false) && (!error_message.isEmpty())) { + QMessageBox::critical(this, tr("Error"), + tr("The following error has occurred while creating the thumbnails:")+"\n"+ error_message ); + } + + button_box->setEnabled(true); + + // Adjust size + //resize( w_contents->sizeHint() ); + + cleanDir(full_output_dir); + return result; +} + +bool VideoPreview::extractImages() { + VideoInfo i = getInfo(mplayer_bin, prop.input_video); + int length = i.length; + + if (length == 0) { + if (error_message.isEmpty()) error_message = tr("The length of the video is 0"); + return false; + } + + // Create a temporary directory + QDir d(QDir::tempPath()); + if (!d.exists(output_dir)) { + if (!d.mkpath(output_dir)) { + qDebug("VideoPreview::extractImages: error: can't create '%s'", full_output_dir.toUtf8().constData()); + error_message = tr("The temporary directory (%1) can't be created").arg(full_output_dir); + return false; + } + } + + displayVideoInfo(i); + + // Let's begin + run.thumbnail_width = 0; + + int num_pictures = prop.n_cols * prop.n_rows; + length -= prop.initial_step; + int s_step = length / num_pictures; + + int current_time = prop.initial_step; + + canceled = false; + progress->setLabelText(tr("Creating thumbnails...")); + progress->setRange(0, num_pictures-1); + progress->show(); + + double aspect_ratio = i.aspect; + if (prop.aspect_ratio != 0) aspect_ratio = prop.aspect_ratio; + + for (int n = 0; n < num_pictures; n++) { + qDebug("VideoPreview::extractImages: getting frame %d of %d...", n+1, num_pictures); + progress->setValue(n); + qApp->processEvents(); + + if (canceled) return false; + + if (!runMplayer(current_time, aspect_ratio)) return false; + + QString frame_picture = full_output_dir + "/" + framePicture(); + if (!QFile::exists(frame_picture)) { + error_message = tr("The file %1 doesn't exist").arg(frame_picture); + return false; + } + +#if RENAME_PICTURES + QString extension = (extractFormat()==PNG) ? "png" : "jpg"; + QString output_file = output_dir + QString("/picture_%1.%2").arg(current_time, 8, 10, QLatin1Char('0')).arg(extension); + d.rename(output_dir + "/" + framePicture(), output_file); +#else + QString output_file = output_dir + "/" + framePicture(); +#endif + + if (!addPicture(QDir::tempPath() +"/"+ output_file, n, current_time)) { + return false; + } + + current_time += s_step; + } + + return true; +} + +bool VideoPreview::runMplayer(int seek, double aspect_ratio) { + QStringList args; + args << "-nosound"; + + if (prop.extract_format == PNG) { + args << "-vo" + #ifdef CD_TO_TEMP_DIR + << "png"; + #else + << "png:outdir="+full_output_dir; + #endif + } else { + args << "-vo" + #ifdef CD_TO_TEMP_DIR + << "jpeg"; + #else + << "jpeg:outdir="+full_output_dir; + #endif + } + + args << "-frames" << "6" << "-ss" << QString::number(seek); + + if (aspect_ratio != 0) { + args << "-aspect" << QString::number(aspect_ratio) << "-zoom"; + } + + if (!prop.dvd_device.isEmpty()) { + args << "-dvd-device" << prop.dvd_device; + } + + /* + if (display_osd) { + args << "-vf" << "expand=osd=1" << "-osdlevel" << "2"; + } + */ + + args << prop.input_video; + + QString command = mplayer_bin + " "; + for (int n = 0; n < args.count(); n++) command = command + args[n] + " "; + qDebug("VideoPreview::runMplayer: command: %s", command.toUtf8().constData()); + + QProcess p; + #ifdef CD_TO_TEMP_DIR + p.setWorkingDirectory(full_output_dir); + qDebug("VideoPreview::runMplayer: changing working directory of the process to '%s'", full_output_dir.toUtf8().constData()); + #endif + p.start(mplayer_bin, args); + if (!p.waitForFinished()) { + qDebug("VideoPreview::runMplayer: error running process"); + error_message = tr("The mplayer process didn't run"); + return false; + } + + return true; +} + + +bool VideoPreview::addPicture(const QString & filename, int num, int time) { + int row = num / prop.n_cols; + int col = num % prop.n_cols; + + qDebug("VideoPreview::addPicture: %d (row: %d col: %d) file: '%s'", num, row, col, filename.toUtf8().constData()); + + QPixmapCache::clear(); + QPixmap picture; + if (!picture.load(filename)) { + qDebug("VideoPreview::addPicture: can't load file"); + error_message = tr("The file %1 can't be loaded").arg(filename); + return false; + } + + if (run.thumbnail_width == 0) { + int spacing = grid_layout->horizontalSpacing() * (prop.n_cols-1); + if (spacing < 0) spacing = 0; + qDebug("VideoPreview::addPicture: spacing: %d", spacing); + run.thumbnail_width = (prop.max_width - spacing) / prop.n_cols; + if (run.thumbnail_width > picture.width()) run.thumbnail_width = picture.width(); + qDebug("VideoPreview::addPicture: thumbnail_width set to %d", run.thumbnail_width); + } + + QPixmap scaled_picture = picture.scaledToWidth(run.thumbnail_width, Qt::SmoothTransformation); + + // Add current time text + if (prop.display_osd) { + QString stime = QTime().addSecs(time).toString("hh:mm:ss"); + QFont font("Arial"); + font.setBold(true); + QPainter painter(&scaled_picture); + painter.setPen( Qt::white ); + painter.setFont(font); + painter.drawText(scaled_picture.rect(), Qt::AlignRight | Qt::AlignBottom, stime); + } + + QLabel * l = new QLabel(this); + label_list.append(l); + l->setPixmap(scaled_picture); + //l->setPixmap(picture); + grid_layout->addWidget(l, row, col); + + return true; +} + +void VideoPreview::displayVideoInfo(const VideoInfo & i) { + // Display info about the video + QTime t = QTime().addSecs(i.length); + + QString aspect = QString::number(i.aspect); + if (fabs(1.77 - i.aspect) < 0.1) aspect = "16:9"; + else + if (fabs(1.33 - i.aspect) < 0.1) aspect = "4:3"; + else + if (fabs(2.35 - i.aspect) < 0.1) aspect = "2.35:1"; + + QString no_info = tr("No info"); + + QString fps = (i.fps==0 || i.fps==1000) ? no_info : QString("%1").arg(i.fps); + QString video_bitrate = (i.video_bitrate==0) ? no_info : tr("%1 kbps").arg(i.video_bitrate/1000); + QString audio_bitrate = (i.audio_bitrate==0) ? no_info : tr("%1 kbps").arg(i.audio_bitrate/1000); + QString audio_rate = (i.audio_rate==0) ? no_info : tr("%1 Hz").arg(i.audio_rate); + + info->setText( + "" + i.filename +"" + "" + "" + "" + "" + "
    " + + tr("Size: %1 MB").arg(i.size / (1024*1024)) + "
    " + + tr("Resolution: %1x%2").arg(i.width).arg(i.height) + "
    " + + tr("Length: %1").arg(t.toString("hh:mm:ss")) + + "
    " + + tr("Video format: %1").arg(i.video_format) + "
    " + + tr("Frames per second: %1").arg(fps) + "
    " + + tr("Aspect ratio: %1").arg(aspect) + //"
    " + + "
    " + + tr("Video bitrate: %1").arg(video_bitrate) + "
    " + + tr("Audio bitrate: %1").arg(audio_bitrate) + "
    " + + tr("Audio rate: %1").arg(audio_rate) + //"
    " + + "
    " + ); + setWindowTitle( tr("Video preview") + " - " + i.filename ); +} + +void VideoPreview::cleanDir(QString directory) { + QStringList filter; + if (prop.extract_format == PNG) { + filter.append("*.png"); + } else { + filter.append("*.jpg"); + } + + QDir d(directory); + QStringList l = d.entryList( filter, QDir::Files, QDir::Unsorted); + + for (int n = 0; n < l.count(); n++) { + qDebug("VideoPreview::cleanDir: deleting '%s'", l[n].toUtf8().constData()); + d.remove(l[n]); + } + qDebug("VideoPreview::cleanDir: removing directory '%s'", directory.toUtf8().constData()); + d.rmpath(directory); +} + +VideoInfo VideoPreview::getInfo(const QString & mplayer_path, const QString & filename) { + VideoInfo i; + + if (filename.isEmpty()) { + error_message = tr("No filename"); + return i; + } + + QFileInfo fi(filename); + if (fi.exists()) { + i.filename = fi.fileName(); + i.size = fi.size(); + } + + QRegExp rx("^ID_(.*)=(.*)"); + + QProcess p; + p.setProcessChannelMode( QProcess::MergedChannels ); + + QStringList args; + args << "-vo" << "null" << "-ao" << "null" << "-frames" << "1" << "-identify" << "-nocache" << "-noquiet" << filename; + + if (!prop.dvd_device.isEmpty()) { + args << "-dvd-device" << prop.dvd_device; + } + + p.start(mplayer_path, args); + + if (p.waitForFinished()) { + QByteArray line; + while (p.canReadLine()) { + line = p.readLine().trimmed(); + qDebug("VideoPreview::getInfo: '%s'", line.constData()); + if (rx.indexIn(line) > -1) { + QString tag = rx.cap(1); + QString value = rx.cap(2); + qDebug("VideoPreview::getInfo: tag: '%s', value: '%s'", tag.toUtf8().constData(), value.toUtf8().constData()); + + if (tag == "LENGTH") i.length = (int) value.toDouble(); + else + if (tag == "VIDEO_WIDTH") i.width = value.toInt(); + else + if (tag == "VIDEO_HEIGHT") i.height = value.toInt(); + else + if (tag == "VIDEO_FPS") i.fps = value.toDouble(); + else + if (tag == "VIDEO_ASPECT") { + i.aspect = value.toDouble(); + if ((i.aspect == 0) && (i.width != 0) && (i.height != 0)) { + i.aspect = (double) i.width / i.height; + } + } + else + if (tag == "VIDEO_BITRATE") i.video_bitrate = value.toInt(); + else + if (tag == "AUDIO_BITRATE") i.audio_bitrate = value.toInt(); + else + if (tag == "AUDIO_RATE") i.audio_rate = value.toInt(); + else + if (tag == "VIDEO_FORMAT") i.video_format = value; + } + } + } else { + qDebug("VideoPreview::getInfo: error: process didn't start"); + error_message = tr("The mplayer process didn't start while trying to get info about the video"); + } + + qDebug("VideoPreview::getInfo: filename: '%s'", i.filename.toUtf8().constData()); + qDebug("VideoPreview::getInfo: resolution: '%d x %d'", i.width, i.height); + qDebug("VideoPreview::getInfo: length: '%d'", i.length); + qDebug("VideoPreview::getInfo: size: '%d'", (int) i.size); + + return i; +} + + +void VideoPreview::saveImage() { + qDebug("VideoPreview::saveImage"); + + // Proposed name + QString proposed_name = last_directory; + QFileInfo fi(prop.input_video); + if (fi.exists()) { + QString extension = (extractFormat()==PNG) ? "png" : "jpg"; + proposed_name += "/"+ fi.completeBaseName() +"_preview."+ extension; + } + + // Formats + QList w_formats = QImageWriter::supportedImageFormats(); + QString write_formats; + for (int n=0; n < w_formats.count(); n++) { + write_formats.append("*."+w_formats[n]+" "); + } + if (write_formats.isEmpty()) { + // Shouldn't happen! + write_formats = "*.png *.jpg"; + } + + QString filename = QFileDialog::getSaveFileName(this, tr("Save file"), + proposed_name, tr("Images") +" ("+ write_formats +")"); + + if (!filename.isEmpty()) { + QPixmap image = QPixmap::grabWidget(w_contents); + if (!image.save(filename)) { + // Failed!!! + qDebug("VideoPreview::saveImage: error saving '%s'", filename.toUtf8().constData()); + QMessageBox::warning(this, tr("Error saving file"), + tr("The file couldn't be saved") ); + } else { + last_directory = QFileInfo(filename).absolutePath(); + } + } +} + +bool VideoPreview::showConfigDialog() { + VideoPreviewConfigDialog d(this); + + d.setVideoFile( videoFile() ); + d.setDVDDevice( DVDDevice() ); + d.setCols( cols() ); + d.setRows( rows() ); + d.setInitialStep( initialStep() ); + d.setMaxWidth( maxWidth() ); + d.setDisplayOSD( displayOSD() ); + d.setAspectRatio( aspectRatio() ); + d.setFormat( extractFormat() ); + + if (d.exec() == QDialog::Accepted) { + setVideoFile( d.videoFile() ); + setDVDDevice( d.DVDDevice() ); + setCols( d.cols() ); + setRows( d.rows() ); + setInitialStep( d.initialStep() ); + setMaxWidth( d.maxWidth() ); + setDisplayOSD( d.displayOSD() ); + setAspectRatio( d.aspectRatio() ); + setExtractFormat(d.format() ); + + return true; + } + + return false; +} + +void VideoPreview::saveSettings() { + qDebug("VideoPreview::saveSettings"); + + set->beginGroup("videopreview"); + + set->setValue("columns", cols()); + set->setValue("rows", rows()); + set->setValue("initial_step", initialStep()); + set->setValue("max_width", maxWidth()); + set->setValue("osd", displayOSD()); + set->setValue("format", extractFormat()); + set->setValue("last_directory", last_directory); + + set->setValue("filename", videoFile()); + set->setValue("dvd_device", DVDDevice()); + + set->endGroup(); +} + +void VideoPreview::loadSettings() { + qDebug("VideoPreview::loadSettings"); + + set->beginGroup("videopreview"); + + setCols( set->value("columns", cols()).toInt() ); + setRows( set->value("rows", rows()).toInt() ); + setInitialStep( set->value("initial_step", initialStep()).toInt() ); + setMaxWidth( set->value("max_width", maxWidth()).toInt() ); + setDisplayOSD( set->value("osd", displayOSD()).toBool() ); + setExtractFormat( (ExtractFormat) set->value("format", extractFormat()).toInt() ); + last_directory = set->value("last_directory", last_directory).toString(); + + setVideoFile( set->value("filename", videoFile()).toString() ); + setDVDDevice( set->value("dvd_device", DVDDevice()).toString() ); + + set->endGroup(); +} + +void VideoPreview::adjustWindowSize() { + qDebug("VideoPreview::adjustWindowSize: window size: %d %d", width(), height()); + qDebug("VideoPreview::adjustWindowSize: scroll_area size: %d %d", scroll_area->width(), scroll_area->height()); + + int diff_width = width() - scroll_area->maximumViewportSize().width(); + int diff_height = height() - scroll_area->maximumViewportSize().height(); + + qDebug("VideoPreview::adjustWindowSize: diff_width: %d diff_height: %d", diff_width, diff_height); + + QSize new_size = w_contents->size() + QSize( diff_width, diff_height); + + qDebug("VideoPreview::adjustWindowSize: new_size: %d %d", new_size.width(), new_size.height()); + + resize(new_size); +} + +void VideoPreview::cancelPressed() { + canceled = true; +} + +// Language change stuff +void VideoPreview::changeEvent(QEvent *e) { + if (e->type() == QEvent::LanguageChange) { + retranslateStrings(); + } else { + QWidget::changeEvent(e); + } +} + +#include "moc_videopreview.cpp" + diff --git a/plugins/smplayer_plugin/videopreview/videopreview.h b/plugins/smplayer_plugin/videopreview/videopreview.h new file mode 100644 index 000000000..81430c6e9 --- /dev/null +++ b/plugins/smplayer_plugin/videopreview/videopreview.h @@ -0,0 +1,163 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _VIDEOPREVIEW_H_ +#define _VIDEOPREVIEW_H_ + +#include +#include +#include + +class QProgressDialog; +class QGridLayout; +class QLabel; +class QScrollArea; +class QDialogButtonBox; +class QSettings; + +class VideoInfo +{ +public: + VideoInfo() { filename.clear(); width = 0; height = 0; length = 0; + size = 0; fps = 0; aspect = 0; video_bitrate = 0; + audio_bitrate = 0; audio_rate = 0; video_format.clear(); }; + ~VideoInfo() {}; + + QString filename; + int width; + int height; + int length; + qint64 size; + double fps; + double aspect; + int video_bitrate; + int audio_bitrate; + int audio_rate; + QString video_format; +}; + +class VideoPreview : public QWidget +{ + Q_OBJECT + +public: + enum ExtractFormat { JPEG = 1, PNG = 2 }; + + VideoPreview(QString mplayer_path, QWidget * parent = 0, Qt::WindowFlags f = 0); + ~VideoPreview(); + + void setMplayerPath(QString mplayer_path); + QString mplayerPath() { return mplayer_bin; }; + + void setVideoFile(QString file) { prop.input_video = file; }; + QString videoFile() { return prop.input_video; }; + + void setDVDDevice(const QString & dvd_device) { prop.dvd_device = dvd_device; }; + QString DVDDevice() { return prop.dvd_device; }; + + void setCols(int cols) { prop.n_cols = cols; }; + int cols() { return prop.n_cols; }; + + void setRows(int rows) { prop.n_rows = rows; }; + int rows() { return prop.n_rows; }; + + void setGrid(int cols, int rows) { prop.n_cols = cols; prop.n_rows = rows; }; + + void setInitialStep(int step) { prop.initial_step = step; }; + int initialStep() { return prop.initial_step; }; + + void setMaxWidth(int w) { prop.max_width = w; }; + int maxWidth() { return prop.max_width; }; + + void setDisplayOSD(bool b) { prop.display_osd = b; }; + bool displayOSD() { return prop.display_osd; }; + + void setAspectRatio(double asp) { prop.aspect_ratio = asp; }; + double aspectRatio() { return prop.aspect_ratio; }; + + void setExtractFormat( ExtractFormat format ) { prop.extract_format = format; }; + ExtractFormat extractFormat() { return prop.extract_format; }; + + bool createThumbnails(); + + bool showConfigDialog(); + + void setSettings(QSettings * settings); + QSettings * settings() { return set; }; + + VideoInfo getInfo(const QString & mplayer_path, const QString & filename); + QString errorMessage() { return error_message; }; + + void adjustWindowSize(); + +protected slots: + void cancelPressed(); + void saveImage(); + +protected: + virtual void retranslateStrings(); + virtual void changeEvent( QEvent * event ); + +protected: + bool extractImages(); + bool runMplayer(int seek, double aspect_ratio); + bool addPicture(const QString & filename, int num, int time); + void displayVideoInfo(const VideoInfo & i); + void cleanDir(QString directory); + void clearThumbnails(); + QString framePicture(); + void saveSettings(); + void loadSettings(); + + QList label_list; + + QGridLayout * grid_layout; + QLabel * info; + QLabel * foot; + QWidget * w_contents; + QScrollArea * scroll_area; + QDialogButtonBox * button_box; + + QString mplayer_bin; + + QString output_dir; + QString full_output_dir; + + QProgressDialog * progress; + bool canceled; + + QSettings * set; + + struct Properties { + QString input_video; + QString dvd_device; + int n_cols, n_rows, initial_step, max_width; + double aspect_ratio; + bool display_osd; + ExtractFormat extract_format; + } prop; + + struct { + int thumbnail_width; + } run; + + QString last_directory; + QString error_message; +}; + +#endif diff --git a/plugins/smplayer_plugin/videopreview/videopreview.pro b/plugins/smplayer_plugin/videopreview/videopreview.pro new file mode 100644 index 000000000..b78c91015 --- /dev/null +++ b/plugins/smplayer_plugin/videopreview/videopreview.pro @@ -0,0 +1,17 @@ +CONFIG += debug + +HEADERS = ../filechooser.h videopreviewconfigdialog.h videopreview.h +SOURCES = ../filechooser.cpp videopreviewconfigdialog.cpp videopreview.cpp main.cpp + +FORMS = ../filechooser.ui videopreviewconfigdialog.ui + +INCLUDEPATH += .. +DEPENDPATH += .. +DEFINES += NO_SMPLAYER_SUPPORT + +unix { + UI_DIR = .ui + MOC_DIR = .moc + OBJECTS_DIR = .obj +} + diff --git a/plugins/smplayer_plugin/videopreview/videopreviewconfigdialog.cpp b/plugins/smplayer_plugin/videopreview/videopreviewconfigdialog.cpp new file mode 100644 index 000000000..fb9bf17c9 --- /dev/null +++ b/plugins/smplayer_plugin/videopreview/videopreviewconfigdialog.cpp @@ -0,0 +1,144 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "videopreviewconfigdialog.h" + +VideoPreviewConfigDialog::VideoPreviewConfigDialog( QWidget* parent, Qt::WindowFlags f ) + : QDialog(parent, f) +{ + setupUi(this); + + connect(filename_edit->lineEdit(), SIGNAL(textChanged(const QString &)), + this, SLOT(filenameChanged(const QString &)) ); + + dvd_device_label->setVisible(false); + dvd_device_edit->setVisible(false); + + aspect_ratio_combo->addItem(tr("Default"), 0); + aspect_ratio_combo->addItem("4:3", (double) 4/3); + aspect_ratio_combo->addItem("16:9", (double) 16/9); + aspect_ratio_combo->addItem("2.35:1", 2.35); + + format_combo->addItem("jpg", VideoPreview::JPEG); + format_combo->addItem("png", VideoPreview::PNG); + + filename_edit->setWhatsThis( tr("The preview will be created for the video you specify here.") ); + dvd_device_edit->setWhatsThis( tr("Enter here the DVD device or a folder with a DVD image.") ); + columns_spin->setWhatsThis( tr("The thumbnails will be arranged on a table.") +" "+ tr("This option specifies the number of columns of the table.") ); + rows_spin->setWhatsThis( tr("The thumbnails will be arranged on a table.") +" "+ tr("This option specifies the number of rows of the table.") ); + osd_check->setWhatsThis( tr("If you check this option, the playing time will be displayed at the bottom of each thumbnail.") ); + aspect_ratio_combo->setWhatsThis( tr("If the aspect ratio of the video is wrong, you can specify a different one here.") ); + initial_step_spin->setWhatsThis( tr("Usually the first frames are black, so it's a good idea to skip some seconds at the beginning of the video. " + "This option allows to specify how many seconds will be skipped.") ); + max_width_spin->setWhatsThis( tr("This option specifies the maximum width in pixels that the generated preview image will have.") ); + format_combo->setWhatsThis( tr("Some frames will be extracted from the video in order to create the preview. Here you can choose " + "the image format for the extracted frames. PNG may give better quality.") ); + + layout()->setSizeConstraint(QLayout::SetFixedSize); +} + +VideoPreviewConfigDialog::~VideoPreviewConfigDialog() { +} + +void VideoPreviewConfigDialog::setVideoFile(const QString & video_file) { + filename_edit->setText(video_file); +} + +QString VideoPreviewConfigDialog::videoFile() { + return filename_edit->text(); +} + +void VideoPreviewConfigDialog::setDVDDevice(const QString & dvd_device) { + dvd_device_edit->setText(dvd_device); +} + +QString VideoPreviewConfigDialog::DVDDevice() { + return dvd_device_edit->text(); +} + +void VideoPreviewConfigDialog::setCols(int cols) { + columns_spin->setValue(cols); +} + +int VideoPreviewConfigDialog::cols() { + return columns_spin->value(); +} + +void VideoPreviewConfigDialog::setRows(int rows) { + rows_spin->setValue(rows); +} + +int VideoPreviewConfigDialog::rows() { + return rows_spin->value(); +} + +void VideoPreviewConfigDialog::setInitialStep(int step) { + initial_step_spin->setValue(step); +} + +int VideoPreviewConfigDialog::initialStep() { + return initial_step_spin->value(); +} + +void VideoPreviewConfigDialog::setMaxWidth(int w) { + max_width_spin->setValue(w); +} + +int VideoPreviewConfigDialog::maxWidth() { + return max_width_spin->value(); +} + +void VideoPreviewConfigDialog::setDisplayOSD(bool b) { + osd_check->setChecked(b); +} + +bool VideoPreviewConfigDialog::displayOSD() { + return osd_check->isChecked(); +} + +void VideoPreviewConfigDialog::setAspectRatio(double asp) { + int idx = aspect_ratio_combo->findData(asp); + if (idx < 0) idx = 0; + aspect_ratio_combo->setCurrentIndex(idx); +} + +double VideoPreviewConfigDialog::aspectRatio() { + int idx = aspect_ratio_combo->currentIndex(); + return aspect_ratio_combo->itemData(idx).toDouble(); +} + +void VideoPreviewConfigDialog::setFormat(VideoPreview::ExtractFormat format) { + int idx = format_combo->findData(format); + if (idx < 0) idx = 0; + format_combo->setCurrentIndex(idx); +} + +VideoPreview::ExtractFormat VideoPreviewConfigDialog::format() { + int idx = format_combo->currentIndex(); + return (VideoPreview::ExtractFormat) format_combo->itemData(idx).toInt(); +} + +void VideoPreviewConfigDialog::filenameChanged(const QString & text) { + qDebug("VideoPreviewConfigDialog::filenameChanged"); + + bool b = text.startsWith("dvd:"); + dvd_device_label->setVisible(b); + dvd_device_edit->setVisible(b); +} + +#include "moc_videopreviewconfigdialog.cpp" diff --git a/plugins/smplayer_plugin/videopreview/videopreviewconfigdialog.h b/plugins/smplayer_plugin/videopreview/videopreviewconfigdialog.h new file mode 100644 index 000000000..d8e7d5984 --- /dev/null +++ b/plugins/smplayer_plugin/videopreview/videopreviewconfigdialog.h @@ -0,0 +1,64 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _VIDEOPREVIEWCONFIGDIALOG_H_ +#define _VIDEOPREVIEWCONFIGDIALOG_H_ + +#include "ui_videopreviewconfigdialog.h" +#include "videopreview.h" + +class VideoPreviewConfigDialog : public QDialog, public Ui::VideoPreviewConfigDialog +{ + Q_OBJECT + +public: + VideoPreviewConfigDialog( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + ~VideoPreviewConfigDialog(); + + void setVideoFile(const QString & video_file); + QString videoFile(); + + void setDVDDevice(const QString & dvd_device); + QString DVDDevice(); + + void setCols(int cols); + int cols(); + + void setRows(int rows); + int rows(); + + void setInitialStep(int step); + int initialStep(); + + void setMaxWidth(int w); + int maxWidth(); + + void setDisplayOSD(bool b); + bool displayOSD(); + + void setAspectRatio(double asp); + double aspectRatio(); + + void setFormat(VideoPreview::ExtractFormat format); + VideoPreview::ExtractFormat format(); + +protected slots: + void filenameChanged(const QString &); +}; + +#endif diff --git a/plugins/smplayer_plugin/videopreview/videopreviewconfigdialog.ui b/plugins/smplayer_plugin/videopreview/videopreviewconfigdialog.ui new file mode 100644 index 000000000..dd67945f3 --- /dev/null +++ b/plugins/smplayer_plugin/videopreview/videopreviewconfigdialog.ui @@ -0,0 +1,349 @@ + + VideoPreviewConfigDialog + + + + 0 + 0 + 428 + 340 + + + + Video Preview + + + + + + + + &File: + + + filename_edit + + + + + + + + + + + + + + &DVD device: + + + dvd_device_edit + + + + + + + + + + + + + + &Columns: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + columns_spin + + + + + + + 1 + + + 10 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + &Rows: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + rows_spin + + + + + + + 1 + + + + + + + + + Add playing &time to thumbnails + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + + + &Aspect ratio: + + + aspect_ratio_combo + + + + + + + + + + Qt::Horizontal + + + + 101 + 20 + + + + + + + + + + + + &Seconds to skip at the beginnning: + + + initial_step_spin + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + &Maximum width: + + + max_width_spin + + + + + + + 100 + + + 2000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + + + &Extract frames as + + + format_combo + + + + + + + + + + Qt::Horizontal + + + + 71 + 23 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + FileChooser + QLineEdit +
    filechooser.h
    +
    +
    + + filename_edit + dvd_device_edit + columns_spin + rows_spin + osd_check + aspect_ratio_combo + initial_step_spin + max_width_spin + format_combo + buttonBox + + + + + buttonBox + accepted() + VideoPreviewConfigDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + VideoPreviewConfigDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
    diff --git a/plugins/smplayer_plugin/widgetactions.cpp b/plugins/smplayer_plugin/widgetactions.cpp new file mode 100644 index 000000000..dfed4fc14 --- /dev/null +++ b/plugins/smplayer_plugin/widgetactions.cpp @@ -0,0 +1,247 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "widgetactions.h" +#include "colorutils.h" +#include + +#if MINI_ARROW_BUTTONS +#include +#endif + +MyWidgetAction::MyWidgetAction( QWidget * parent ) + : QWidgetAction(parent) +{ + custom_style = 0; + custom_stylesheet = ""; +} + +MyWidgetAction::~MyWidgetAction() { +} + +void MyWidgetAction::enable() { + propagate_enabled(true); +} + +void MyWidgetAction::disable() { + propagate_enabled(false); +} + +void MyWidgetAction::propagate_enabled(bool b) { + QList l = createdWidgets(); + for (int n=0; n < l.count(); n++) { + TimeSlider *s = (TimeSlider*) l[n]; + s->setEnabled(b);; + } + setEnabled(b); +} + + +TimeSliderAction::TimeSliderAction( QWidget * parent ) + : MyWidgetAction(parent) +{ +#if ENABLE_DELAYED_DRAGGING + drag_delay = 200; +#endif +} + +TimeSliderAction::~TimeSliderAction() { +} + +void TimeSliderAction::setPos(int v) { + QList l = createdWidgets(); + for (int n=0; n < l.count(); n++) { + TimeSlider *s = (TimeSlider*) l[n]; + bool was_blocked= s->blockSignals(true); + s->setPos(v); + s->blockSignals(was_blocked); + } +} + +int TimeSliderAction::pos() { + QList l = createdWidgets(); + if (l.count() >= 1) { + TimeSlider *s = (TimeSlider*) l[0]; + return s->pos(); + } else { + return -1; + } +} + +#if ENABLE_DELAYED_DRAGGING +void TimeSliderAction::setDragDelay(int d) { + drag_delay = d; + + QList l = createdWidgets(); + for (int n=0; n < l.count(); n++) { + TimeSlider *s = (TimeSlider*) l[n]; + s->setDragDelay(drag_delay); + } +} + +int TimeSliderAction::dragDelay() { + return drag_delay; +} +#endif + +QWidget * TimeSliderAction::createWidget ( QWidget * parent ) { + TimeSlider *t = new TimeSlider(parent); + t->setEnabled( isEnabled() ); + + if (custom_style) t->setStyle(custom_style); + if (!custom_stylesheet.isEmpty()) t->setStyleSheet(custom_stylesheet); + + connect( t, SIGNAL(posChanged(int)), + this, SIGNAL(posChanged(int)) ); + connect( t, SIGNAL(draggingPos(int)), + this, SIGNAL(draggingPos(int)) ); +#if ENABLE_DELAYED_DRAGGING + t->setDragDelay(drag_delay); + + connect( t, SIGNAL(delayedDraggingPos(int)), + this, SIGNAL(delayedDraggingPos(int)) ); +#endif + + return t; +} + + +VolumeSliderAction::VolumeSliderAction( QWidget * parent ) + : MyWidgetAction(parent) +{ + tick_position = QSlider::TicksBelow; +} + +VolumeSliderAction::~VolumeSliderAction() { +} + +void VolumeSliderAction::setValue(int v) { + QList l = createdWidgets(); + for (int n=0; n < l.count(); n++) { + MySlider *s = (MySlider*) l[n]; + bool was_blocked = s->blockSignals(true); + s->setValue(v); + s->blockSignals(was_blocked); + } +} + +int VolumeSliderAction::value() { + QList l = createdWidgets(); + if (l.count() >= 1) { + MySlider *s = (MySlider*) l[0]; + return s->value(); + } else { + return -1; + } +} + +void VolumeSliderAction::setTickPosition(QSlider::TickPosition position) { + // For new widgets + tick_position = position; + + // Propagate changes to all existing widgets + QList l = createdWidgets(); + for (int n=0; n < l.count(); n++) { + MySlider *s = (MySlider*) l[n]; + s->setTickPosition(tick_position); + } +} + +QWidget * VolumeSliderAction::createWidget ( QWidget * parent ) { + MySlider *t = new MySlider(parent); + + if (custom_style) t->setStyle(custom_style); + if (!custom_stylesheet.isEmpty()) t->setStyleSheet(custom_stylesheet); + if (fixed_size.isValid()) t->setFixedSize(fixed_size); + + t->setMinimum(0); + t->setMaximum(100); + t->setValue(50); + t->setOrientation( Qt::Horizontal ); + t->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); + t->setFocusPolicy( Qt::NoFocus ); + t->setTickPosition( tick_position ); + t->setTickInterval( 10 ); + t->setSingleStep( 1 ); + t->setPageStep( 10 ); + t->setToolTip( tr("Volume") ); + t->setEnabled( isEnabled() ); + t->setAttribute(Qt::WA_NoMousePropagation); + + connect( t, SIGNAL(valueChanged(int)), + this, SIGNAL(valueChanged(int)) ); + return t; +} + + +TimeLabelAction::TimeLabelAction( QWidget * parent ) + : MyWidgetAction(parent) +{ +} + +TimeLabelAction::~TimeLabelAction() { +} + +void TimeLabelAction::setText(QString s) { + _text = s; + emit newText(s); +} + +QWidget * TimeLabelAction::createWidget ( QWidget * parent ) { + QLabel * time_label = new QLabel(parent); + time_label->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + time_label->setAutoFillBackground(true); + + ColorUtils::setBackgroundColor( time_label, QColor(0,0,0) ); + ColorUtils::setForegroundColor( time_label, QColor(255,255,255) ); + time_label->setText( "00:00:00 / 00:00:00" ); + time_label->setFrameShape( QFrame::Panel ); + time_label->setFrameShadow( QFrame::Sunken ); + + connect( this, SIGNAL(newText(QString)), + time_label, SLOT(setText(QString)) ); + + return time_label; +} + +#if MINI_ARROW_BUTTONS +SeekingButton::SeekingButton( QList actions, QWidget * parent ) + : QWidgetAction(parent) +{ + _actions = actions; +} + +SeekingButton::~SeekingButton() { +} + +QWidget * SeekingButton::createWidget( QWidget * parent ) { + QToolButton * button = new QToolButton(parent); + button->setPopupMode(QToolButton::MenuButtonPopup); + + if (_actions.count() > 0 ) { + button->setDefaultAction( _actions[0] ); + } + for (int n = 1; n < _actions.count(); n++) { + button->addAction( _actions[n] ); + } + + return button; +} +#endif + +#include "moc_widgetactions.cpp" diff --git a/plugins/smplayer_plugin/widgetactions.h b/plugins/smplayer_plugin/widgetactions.h new file mode 100644 index 000000000..c7dca39b8 --- /dev/null +++ b/plugins/smplayer_plugin/widgetactions.h @@ -0,0 +1,158 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _WIDGETACTIONS_H_ +#define _WIDGETACTIONS_H_ + +#include +#include "timeslider.h" +#include "config.h" +#include "guiconfig.h" + +class QStyle; + +class MyWidgetAction : public QWidgetAction +{ + Q_OBJECT + +public: + MyWidgetAction( QWidget * parent ); + ~MyWidgetAction(); + + void setCustomStyle(QStyle * style) { custom_style = style; }; + QStyle * customStyle() { return custom_style; }; + + void setStyleSheet(QString style) { custom_stylesheet = style; }; + QString styleSheet() { return custom_stylesheet; }; + +public slots: + virtual void enable(); // setEnabled in QAction is not virtual :( + virtual void disable(); + +protected: + virtual void propagate_enabled(bool); + +protected: + QStyle * custom_style; + QString custom_stylesheet; +}; + + +class TimeSliderAction : public MyWidgetAction +{ + Q_OBJECT + +public: + TimeSliderAction( QWidget * parent ); + ~TimeSliderAction(); + +public slots: + virtual void setPos(int); + virtual int pos(); +#if ENABLE_DELAYED_DRAGGING + void setDragDelay(int); + int dragDelay(); + +private: + int drag_delay; +#endif + +signals: + void posChanged(int value); + void draggingPos(int value); +#if ENABLE_DELAYED_DRAGGING + void delayedDraggingPos(int); +#endif + +protected: + virtual QWidget * createWidget ( QWidget * parent ); +}; + + +class VolumeSliderAction : public MyWidgetAction +{ + Q_OBJECT + +public: + VolumeSliderAction( QWidget * parent ); + ~VolumeSliderAction(); + + void setFixedSize(QSize size) { fixed_size = size; }; + QSize fixedSize() { return fixed_size; }; + + void setTickPosition(QSlider::TickPosition position); + QSlider::TickPosition tickPosition() { return tick_position; }; + +public slots: + virtual void setValue(int); + virtual int value(); + +signals: + void valueChanged(int value); + +protected: + virtual QWidget * createWidget ( QWidget * parent ); + +private: + QSize fixed_size; + QSlider::TickPosition tick_position; +}; + + +class TimeLabelAction : public MyWidgetAction +{ + Q_OBJECT + +public: + TimeLabelAction( QWidget * parent ); + ~TimeLabelAction(); + + virtual QString text() { return _text; }; + +public slots: + virtual void setText(QString s); + +signals: + void newText(QString s); + +protected: + virtual QWidget * createWidget ( QWidget * parent ); + +private: + QString _text; +}; + + +#if MINI_ARROW_BUTTONS +class SeekingButton : public QWidgetAction +{ + Q_OBJECT + +public: + SeekingButton( QList actions, QWidget * parent ); + ~SeekingButton(); + +protected: + virtual QWidget * createWidget ( QWidget * parent ); + + QList _actions; +}; +#endif + +#endif + diff --git a/plugins/smplayer_plugin/winfileassoc.cpp b/plugins/smplayer_plugin/winfileassoc.cpp new file mode 100644 index 000000000..398ecb7c0 --- /dev/null +++ b/plugins/smplayer_plugin/winfileassoc.cpp @@ -0,0 +1,482 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Winfileassoc.cpp + + Handles file associations in Windows Vista/XP/2000/NT/ME/98/95. + We assume that the code is run without administrator privileges, so the associations are done for current user only. + System-wide associations require writing to HKEY_CLASSES_ROOT and we don't want to get our hands dirty with that. + Each user on the computer can configure his own set of file associations for SMPlayer, which is extremely cool. + + Optionally, during uninstall, it would be a good idea to call RestoreFileAssociations for all media types so + that we can clean up the registry and restore the old associations for current user. + + Vista: + The code can only register the app as default program for selected extensions and check if it is the default. + It cannot restore 'old' default application, since this doesn't seem to be possible with the current Vista API. + + Tested on: Win98, Win2000, WinXP, Vista. + NOT tested on: Win95, ME and NT 4.0 (it should work on 95, ME; Not sure about NT 4.0). + + Author: Florin Braghis (florin@libertv.ro) +*/ + +#include "winfileassoc.h" +#include +#include +#include + +/* + Note by RVM: Added some #ifdef Q_OS_WIN to allow the file to compile under linux. + It should compile the code for Windows XP. + The registry entries are saved on a file named HKEY_CURRENT_USER. +*/ + +WinFileAssoc::WinFileAssoc( const QString ClassId, const QString AppName ) +{ + m_ClassId = ClassId; + m_AppName = AppName; + m_ClassId2 = QFileInfo(QApplication::applicationFilePath()).fileName(); +} + +//Associates all extensions in the fileExtensions list with current app. +//Returns number of extensions processed successfully. +int WinFileAssoc::CreateFileAssociations(const QStringList& fileExtensions) +{ +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA) + { + return VistaSetAppsAsDefault(fileExtensions); + } +#endif + + QSettings RegCR ("HKEY_CLASSES_ROOT", QSettings::NativeFormat); //Read only on NT+ + QSettings RegCU ("HKEY_CURRENT_USER", QSettings::NativeFormat); + + if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError) + return 0; + + if (RegCR.status() != QSettings::NoError) + return 0; + +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion < QSysInfo::WV_NT && !RegCR.isWritable()) //Win98 + return 0; +#endif + + //Check if classId exists in the registry + if (!RegCR.contains(m_ClassId) && !RegCU.contains("Software/Classes/" + m_ClassId)) + { + //If doesn't exist (user didn't run the setup program), try to create the ClassId for current user. + if (!CreateClassId(QApplication::applicationFilePath(), "SMPlayer Media Player")) + return 0; + } + + int count = 0; + foreach(const QString& fileExtension, fileExtensions) + { + QString ExtKeyName = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension); + QString ClassesKeyName = m_ClassId; + + QString BackupKeyName = ClassesKeyName + "/" + fileExtension; + QString CUKeyName = "Software/Classes/." + fileExtension; + + //Save current ClassId for current user + QString KeyVal = RegCU.value(CUKeyName + "/.").toString(); + + if (KeyVal.length() == 0 || KeyVal == m_ClassId) + { + //No registered app for this extension for current user. + //Check the system-wide (HKEY_CLASSES_ROOT) ClassId for this extension + KeyVal = RegCR.value("." + fileExtension + "/.").toString(); + } + + if (KeyVal != m_ClassId) + RegCU.setValue(CUKeyName + "/MPlayer_Backup", KeyVal); + + //Save last ProgId and Application values from the Exts key + KeyVal = RegCU.value(ExtKeyName + "/Progid").toString(); + + if (KeyVal != m_ClassId && KeyVal != m_ClassId2) + RegCU.setValue(ExtKeyName + "/MPlayer_Backup_ProgId", KeyVal); + + KeyVal = RegCU.value(ExtKeyName + "/Application").toString(); + if (KeyVal != m_ClassId || KeyVal != m_ClassId2) + RegCU.setValue(ExtKeyName + "/MPlayer_Backup_Application", KeyVal); + + //Create the associations +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT) +#endif + { + RegCU.setValue(CUKeyName + "/.", m_ClassId); //Extension class + RegCU.setValue(ExtKeyName + "/Progid", m_ClassId); //Explorer FileExt association + + } +#ifdef Q_OS_WIN + else + { + //Windows ME/98/95 support + RegCR.setValue("." + fileExtension + "/.", m_ClassId); + } +#endif + + if (RegCU.status() == QSettings::NoError && RegCR.status() == QSettings::NoError) + count++; + } + + return count; +} + +//Checks if extensions in extensionsToCheck are registered with this application. Returns a list of registered extensions. +//Returns false if there was an error accessing the registry. +//Returns true and 0 elements in registeredExtensions if no extension is associated with current app. +bool WinFileAssoc::GetRegisteredExtensions( const QStringList& extensionsToCheck, QStringList& registeredExtensions) +{ + registeredExtensions.clear(); + +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA) + { + return VistaGetDefaultApps(extensionsToCheck, registeredExtensions); + } +#endif + + QSettings RegCR ("HKEY_CLASSES_ROOT", QSettings::NativeFormat); + QSettings RegCU ("HKEY_CURRENT_USER", QSettings::NativeFormat); + + if (RegCR.status() != QSettings::NoError) + return false; + + if (RegCU.status() != QSettings::NoError) + return false; + + foreach(const QString& fileExtension, extensionsToCheck) + { + bool bRegistered = false; + //Check the explorer extension (Always use this program to open this kind of file...) + +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT) +#endif + { + QString FileExtsKey = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension); + QString CurClassId = RegCU.value(FileExtsKey + "/Progid").toString(); + QString CurAppId = RegCU.value(FileExtsKey + "/Application").toString(); + + if (CurClassId.size()) //Registered with Open With... / ProgId ? + { + bRegistered = (CurClassId == m_ClassId) || (0 == CurClassId.compare(m_ClassId2, Qt::CaseInsensitive)); + } + else + if (CurAppId.size()) + { + //If user uses Open With..., explorer creates it's own ClassId under Application, usually "smplayer.exe" + bRegistered = (CurAppId == m_ClassId) || (0 == CurAppId.compare(m_ClassId2, Qt::CaseInsensitive)); + } + else + { + //No classId means that no associations exists in Default Programs or Explorer + //Check the default per-user association + bRegistered = RegCU.value("Software/Classes/." + fileExtension + "/.").toString() == m_ClassId; + } + } + + //Finally, check the system-wide association + if (!bRegistered) + bRegistered = RegCR.value("." + fileExtension + "/.").toString() == m_ClassId; + + + if (bRegistered) + registeredExtensions.append(fileExtension); + } + + return true; +} + +//Restores file associations to old defaults (if any) for all extensions in the fileExtensions list. +//Cleans up our backup keys from the registry. +//Returns number of extensions successfully processed (error if fileExtensions.count() != return value && count > 0). +int WinFileAssoc::RestoreFileAssociations(const QStringList& fileExtensions) +{ +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA) + return 0; //Not supported by the API +#endif + + QSettings RegCR ("HKEY_CLASSES_ROOT", QSettings::NativeFormat); + QSettings RegCU ("HKEY_CURRENT_USER", QSettings::NativeFormat); + + if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError) + return 0; + + if (RegCR.status() != QSettings::NoError) + return 0; + +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion < QSysInfo::WV_NT && !RegCR.isWritable()) //Win98 + return 0; +#endif + + int count = 0; + foreach(const QString& fileExtension, fileExtensions) + { + QString ExtKeyName = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension); + QString OldProgId = RegCU.value(ExtKeyName + "/MPlayer_Backup_ProgId").toString(); + QString OldApp = RegCU.value(ExtKeyName + "/MPlayer_Backup_Application").toString(); + QString OldClassId = RegCU.value("Software/Classes/." + fileExtension + "/MPlayer_Backup").toString(); + + //Restore old explorer ProgId + if (!OldProgId.isEmpty() && OldProgId != m_ClassId) + RegCU.setValue(ExtKeyName + "/Progid", OldProgId); + else + { + QString CurProgId = RegCU.value(ExtKeyName + "/Progid").toString(); + if ((CurProgId == m_ClassId) || (0 == CurProgId.compare(m_ClassId2, Qt::CaseInsensitive))) //Only remove if we own it + RegCU.remove(ExtKeyName + "/Progid"); + } + + //Restore old explorer Application + if (!OldApp.isEmpty() && OldApp != m_ClassId) + RegCU.setValue(ExtKeyName + "/Application", OldApp); + else + { + QString CurApp = RegCU.value(ExtKeyName + "/Application").toString(); + if ((CurApp == m_ClassId) || (0 == CurApp.compare(m_ClassId2, Qt::CaseInsensitive))) //Only remove if we own it + RegCU.remove(ExtKeyName + "/Application"); + } + +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT) +#endif + { + //Restore old association for current user + if (!OldClassId.isEmpty() && OldClassId != m_ClassId) + RegCU.setValue("Software/Classes/." + fileExtension + "/.", OldClassId); + else + { + if (RegCU.value("Software/Classes/." + fileExtension + "/.").toString() == m_ClassId) //Only remove if we own it + RegCU.remove("Software/Classes/." + fileExtension); + } + } +#ifdef Q_OS_WIN + else + { + //Windows 98 ==> Write to HKCR + if (!OldClassId.isEmpty() && OldClassId != m_ClassId) + RegCR.setValue("." + fileExtension + "/.", OldClassId); + else + { + if (RegCR.value("." + fileExtension + "/.").toString() == m_ClassId) + RegCR.remove("." + fileExtension); + } + } +#endif + //Remove our keys: + //CurrentUserClasses/.ext/MPlayerBackup + //Explorer: Backup_Application and Backup_ProgId + RegCU.remove("Software/Classes/." + fileExtension + "/MPlayer_Backup"); + RegCU.remove(ExtKeyName + "/MPlayer_Backup_Application"); + RegCU.remove(ExtKeyName + "/MPlayer_Backup_ProgId"); + } + return count; +} + +//Creates a ClassId for current application. +//Note: It's better to create the classId from the installation program. +bool WinFileAssoc::CreateClassId(const QString& executablePath, const QString& friendlyName) +{ + QString RootKeyName; + QString classId; + +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT) +#endif + { + classId = "Software/Classes/" + m_ClassId; + RootKeyName = "HKEY_CURRENT_USER"; + } +#ifdef Q_OS_WIN + else + { + classId = m_ClassId; + RootKeyName = "HKEY_CLASSES_ROOT"; //Windows 95/98/ME + } +#endif + + QSettings Reg (RootKeyName, QSettings::NativeFormat); + if (!Reg.isWritable() || Reg.status() != QSettings::NoError) + return false; + + QString appPath = executablePath; + appPath.replace('/', '\\'); //Explorer gives 'Access Denied' if we write the path with forward slashes to the registry + + //Add our ProgId to the HKCR classes + Reg.setValue(classId + "/shell/open/FriendlyAppName", friendlyName); + Reg.setValue(classId + "/shell/open/command/.", QString("\"%1\" \"%2\"").arg(appPath, "%1")); + Reg.setValue(classId + "/DefaultIcon/.", QString("\"%1\",1").arg(appPath)); + //Add "Enqueue" command + Reg.setValue(classId + "/shell/enqueue/.", QObject::tr("Enqueue in SMPlayer")); + Reg.setValue(classId + "/shell/enqueue/command/.", QString("\"%1\" -add-to-playlist \"%2\"").arg(appPath, "%1")); + return true; +} +//Remove ClassId from the registry. +//Called when no associations exist. Note: It's better to do this in the Setup program. +bool WinFileAssoc::RemoveClassId() +{ + QString RootKeyName; + QString classId; + +#ifdef Q_OS_WIN + if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT) +#endif + { + classId = "Software/Classes/" + m_ClassId; + RootKeyName = "HKEY_CURRENT_USER"; + } +#ifdef Q_OS_WIN + else + { + classId = m_ClassId; + RootKeyName = "HKEY_CLASSES_ROOT"; //Windows 95/98/ME + } +#endif + + QSettings RegCU (RootKeyName, QSettings::NativeFormat); + + if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError) + return false; + + RegCU.remove(classId); + return true; +} + +//Windows Vista specific implementation +//Add libole32.a library if compiling with mingw. +//In smplayer.pro, under win32{ : +// LIBS += libole32 +#ifdef WIN32 +#include + +#if !defined(IApplicationAssociationRegistration) + +typedef enum tagASSOCIATIONLEVEL +{ + AL_MACHINE, + AL_EFFECTIVE, + AL_USER +} ASSOCIATIONLEVEL; + +typedef enum tagASSOCIATIONTYPE +{ + AT_FILEEXTENSION, + AT_URLPROTOCOL, + AT_STARTMENUCLIENT, + AT_MIMETYPE +} ASSOCIATIONTYPE; + +MIDL_INTERFACE("4e530b0a-e611-4c77-a3ac-9031d022281b") +IApplicationAssociationRegistration : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE QueryCurrentDefault(LPCWSTR pszQuery, + ASSOCIATIONTYPE atQueryType, + ASSOCIATIONLEVEL alQueryLevel, + LPWSTR *ppszAssociation) = 0; + virtual HRESULT STDMETHODCALLTYPE QueryAppIsDefault(LPCWSTR pszQuery, + ASSOCIATIONTYPE atQueryType, + ASSOCIATIONLEVEL alQueryLevel, + LPCWSTR pszAppRegistryName, + BOOL *pfDefault) = 0; + virtual HRESULT STDMETHODCALLTYPE QueryAppIsDefaultAll(ASSOCIATIONLEVEL alQueryLevel, + LPCWSTR pszAppRegistryName, + BOOL *pfDefault) = 0; + virtual HRESULT STDMETHODCALLTYPE SetAppAsDefault(LPCWSTR pszAppRegistryName, + LPCWSTR pszSet, + ASSOCIATIONTYPE atSetType) = 0; + virtual HRESULT STDMETHODCALLTYPE SetAppAsDefaultAll(LPCWSTR pszAppRegistryName) = 0; + virtual HRESULT STDMETHODCALLTYPE ClearUserAssociations( void) = 0; +}; +#endif + +static const CLSID CLSID_ApplicationAssociationReg = {0x591209C7,0x767B,0x42B2,{0x9F,0xBA,0x44,0xEE,0x46,0x15,0xF2,0xC7}}; +static const IID IID_IApplicationAssociationReg = {0x4e530b0a,0xe611,0x4c77,{0xa3,0xac,0x90,0x31,0xd0,0x22,0x28,0x1b}}; + +int WinFileAssoc::VistaSetAppsAsDefault(const QStringList& fileExtensions) +{ + IApplicationAssociationRegistration* pAAR; + HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationReg, + NULL, CLSCTX_INPROC, IID_IApplicationAssociationReg, (void**)&pAAR); + + int count = 0; + if (SUCCEEDED(hr) && (pAAR != NULL)) + { + foreach(const QString& fileExtension, fileExtensions) + { + hr = pAAR->SetAppAsDefault((const WCHAR*)m_AppName.utf16(), + (const WCHAR*)QString("." + fileExtension).utf16(), + AT_FILEEXTENSION); + + if (SUCCEEDED(hr)) + count++; + } + pAAR->Release(); + } + return count; +} + +bool WinFileAssoc::VistaGetDefaultApps(const QStringList &extensions, QStringList& registeredExt) +{ + IApplicationAssociationRegistration* pAAR; + + HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationReg, + NULL, CLSCTX_INPROC, IID_IApplicationAssociationReg, (void**)&pAAR); + + if (SUCCEEDED(hr) && (pAAR != NULL)) + { + foreach(const QString& fileExtension, extensions) + { + BOOL bIsDefault = FALSE; + hr = pAAR->QueryAppIsDefault((const WCHAR*)QString("." + fileExtension).utf16(), + AT_FILEEXTENSION, + AL_EFFECTIVE, + (const WCHAR*)m_AppName.utf16(), + &bIsDefault); + if (SUCCEEDED(hr) && bIsDefault) + { + registeredExt.append(fileExtension); + } + } + + pAAR->Release(); + return true; + } + return false; +} +#else +bool WinFileAssoc::VistaGetDefaultApps(const QStringList &extensions, QStringList& registeredExt) +{ + return false; +} + +int WinFileAssoc::VistaSetAppsAsDefault(const QStringList& extensions) +{ + return 0; +} +#endif + diff --git a/plugins/smplayer_plugin/winfileassoc.h b/plugins/smplayer_plugin/winfileassoc.h new file mode 100644 index 000000000..7970ac643 --- /dev/null +++ b/plugins/smplayer_plugin/winfileassoc.h @@ -0,0 +1,51 @@ +/* smplayer, GUI front-end for mplayer. + Copyright (C) 2006-2008 Ricardo Villalba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Winfileassoc.h + Handles file associations in Windows + Author: Florin Braghis (florin@libertv.ro) +*/ + +#ifndef WINFILEASSOC_H +#define WINFILEASSOC_H + +#include +#include + +class WinFileAssoc +{ +protected: + QString m_ClassId; //Application ClassId + QString m_ClassId2; //The ClassId created by explorer if user selects 'Open With...', usually smplayer.exe + QString m_AppName; + +protected: + bool CreateClassId(const QString& executablePath, const QString& friendlyName); + bool RemoveClassId(); + bool VistaGetDefaultApps(const QStringList &extensions, QStringList& registeredExt); + int VistaSetAppsAsDefault(const QStringList& extensions); +public: + WinFileAssoc(const QString ClassId = "MPlayerFileVideo", const QString AppName="SMPlayer"); + //Checks the registry to see which extensions are registered with SMPlayer + bool GetRegisteredExtensions(const QStringList& extensionsToCheck, QStringList& registeredExtensions); + + int CreateFileAssociations(const QStringList& fileExtensions); + int RestoreFileAssociations(const QStringList& fileExtensions); +}; + +#endif diff --git a/plugins/stegosaurus_plugin/StegoSaurus.rc b/plugins/stegosaurus_plugin/StegoSaurus.rc new file mode 100644 index 000000000..01b710c0a --- /dev/null +++ b/plugins/stegosaurus_plugin/StegoSaurus.rc @@ -0,0 +1,110 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource1.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) (unknown sub-lang: 0x10) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENN) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, 0x10 +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource1.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "stegosaurus.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "400904b0" + BEGIN + VALUE "FileDescription", "StegoSaurus Exe" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "StegoSaurus" + VALUE "LegalCopyright", "Copyright (C) 2009" + VALUE "OriginalFilename", "StegoSaurus.exe" + VALUE "ProductName", "StegoSaurus" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x4009, 1200 + END +END + +#endif // English (U.S.) (unknown sub-lang: 0x10) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/stegosaurus_plugin/StegoSaurus.vcproj b/plugins/stegosaurus_plugin/StegoSaurus.vcproj new file mode 100644 index 000000000..8460fb99f --- /dev/null +++ b/plugins/stegosaurus_plugin/StegoSaurus.vcproj @@ -0,0 +1,469 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/stegosaurus_plugin/StegoSaurusPlugin.cpp b/plugins/stegosaurus_plugin/StegoSaurusPlugin.cpp new file mode 100644 index 000000000..91f9bb5ab --- /dev/null +++ b/plugins/stegosaurus_plugin/StegoSaurusPlugin.cpp @@ -0,0 +1,32 @@ +//#include +//#include +//#include + +#include "StegoSaurusPlugin.h" +#include "stegosaurus.h" + +QString +StegoSaurusPlugin::pluginDescription() const +{ + QString res; + res = "a StegoSaurus plugin" ; + + return res; +} + +QString +StegoSaurusPlugin::pluginName() const +{ + return "StegoSaurus" ; +} + +QWidget* +StegoSaurusPlugin::pluginWidget(QWidget * parent ) +{ + StegoSaurus* window = new StegoSaurus(parent); + + return window; +} + + +Q_EXPORT_PLUGIN2(stegosaurus_plugin, StegoSaurusPlugin) diff --git a/plugins/stegosaurus_plugin/StegoSaurusPlugin.h b/plugins/stegosaurus_plugin/StegoSaurusPlugin.h new file mode 100644 index 000000000..952d7485d --- /dev/null +++ b/plugins/stegosaurus_plugin/StegoSaurusPlugin.h @@ -0,0 +1,27 @@ +#ifndef _STEGOSAURUS_PLUGIN_H_ +#define _STEGOSAURUS_PLUGIN_H_ + +#include + +#include +#include + +#include + +#include + +class StegoSaurusPlugin: public QObject, public PluginInterface +{ + Q_OBJECT + Q_INTERFACES(PluginInterface) + + public slots: + + virtual QString pluginDescription() const ; + virtual QString pluginName() const ; + + virtual QWidget* pluginWidget(QWidget * parent = 0) ; + +}; + +#endif diff --git a/plugins/stegosaurus_plugin/images/stegosaurus-128x128.png b/plugins/stegosaurus_plugin/images/stegosaurus-128x128.png new file mode 100644 index 000000000..b89abe308 Binary files /dev/null and b/plugins/stegosaurus_plugin/images/stegosaurus-128x128.png differ diff --git a/plugins/stegosaurus_plugin/images/stegosaurus-16x16.png b/plugins/stegosaurus_plugin/images/stegosaurus-16x16.png new file mode 100644 index 000000000..ebc99d621 Binary files /dev/null and b/plugins/stegosaurus_plugin/images/stegosaurus-16x16.png differ diff --git a/plugins/stegosaurus_plugin/images/stegosaurus-256x256.png b/plugins/stegosaurus_plugin/images/stegosaurus-256x256.png new file mode 100644 index 000000000..96e6e080a Binary files /dev/null and b/plugins/stegosaurus_plugin/images/stegosaurus-256x256.png differ diff --git a/plugins/stegosaurus_plugin/images/stegosaurus-32x32.png b/plugins/stegosaurus_plugin/images/stegosaurus-32x32.png new file mode 100644 index 000000000..2954b2013 Binary files /dev/null and b/plugins/stegosaurus_plugin/images/stegosaurus-32x32.png differ diff --git a/plugins/stegosaurus_plugin/images/stegosaurus-48x48.png b/plugins/stegosaurus_plugin/images/stegosaurus-48x48.png new file mode 100644 index 000000000..262b469cc Binary files /dev/null and b/plugins/stegosaurus_plugin/images/stegosaurus-48x48.png differ diff --git a/plugins/stegosaurus_plugin/main.cpp b/plugins/stegosaurus_plugin/main.cpp new file mode 100644 index 000000000..232cf924e --- /dev/null +++ b/plugins/stegosaurus_plugin/main.cpp @@ -0,0 +1,15 @@ +/**************************************************************************** +***************************Author: Agnit Sarkar****************************** +**************************CopyRight: April 2009****************************** +********************* Email: agnitsarkar@yahoo.co.uk************************* +****************************************************************************/ +#include +#include "stegosaurus.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + StegoSaurus w; + w.show(); + return a.exec(); +} diff --git a/plugins/stegosaurus_plugin/resource.h b/plugins/stegosaurus_plugin/resource.h new file mode 100644 index 000000000..d5b430124 --- /dev/null +++ b/plugins/stegosaurus_plugin/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by StegoSaurus.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/stegosaurus_plugin/resource1.h b/plugins/stegosaurus_plugin/resource1.h new file mode 100644 index 000000000..fb80c0dda --- /dev/null +++ b/plugins/stegosaurus_plugin/resource1.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by StegoSaurus.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/stegosaurus_plugin/stegosaurus.cpp b/plugins/stegosaurus_plugin/stegosaurus.cpp new file mode 100644 index 000000000..1cfa50981 --- /dev/null +++ b/plugins/stegosaurus_plugin/stegosaurus.cpp @@ -0,0 +1,452 @@ +/**************************************************************************** +***************************Author: Agnit Sarkar****************************** +**************************CopyRight: April 2009****************************** +********************* Email: agnitsarkar@yahoo.co.uk************************* +****************************************************************************/ +#include "stegosaurus.h" + +StegoSaurus::StegoSaurus(QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + ui.setupUi(this); + bitsAvailable=0; + sizeofData=0; + inputFileSize=0; +} + +StegoSaurus::~StegoSaurus() +{ + +} + + +void StegoSaurus::on_btnDryImg_clicked() +{ + static QString srcImgFileName="/home/"; + srcImgFileName= QFileDialog::getOpenFileName(this, "Open Bitmap", srcImgFileName, "Bitmap Files(*.bmp)"); + + if(srcImgFileName.isEmpty()){ + ui.lblDryImgDisplay->setText("

    Drag Image Here

    OR

    Select it by browsing

    (BMP Images only)

    "); + ui.lblDryImgDisplay->setPixmap(QPixmap(":/StegoSaurus/images/stegosaurus-256x256.png")); + bitsAvailable=0; + ui.txtDryImg->setText(""); + ui.lblDryImgInfo->setText("No image Loaded"); + return; + } + setDryImage(srcImgFileName); + +} + +void StegoSaurus::on_btnFiletoHide_clicked() +{ + static QString srcFileName="/home/"; + srcFileName= QFileDialog::getOpenFileName(this, "Open file to hide", srcFileName); + + if(srcFileName.isEmpty()){ + inputFileSize=0; + ui.txtFiletoHide->setText(""); + ui.lblFiletoHideinfo->setText("No file loaded"); + return; + } + + //Get File information + QFileInfo fi= QFileInfo(srcFileName); + inputFileSize= fi.size(); + ui.txtFiletoHide->setText(srcFileName); + ui.lblFiletoHideinfo->setText(QString("Size=%L1 bytes").arg(inputFileSize)); + +} + +void StegoSaurus::resizeEvent(QResizeEvent * event) +{ + //Set the label image + if(ui.txtDryImg->text().isEmpty()) + return; + QPixmap pixmap(ui.txtDryImg->text()); + pixmap= pixmap.scaledToHeight(ui.lblDryImgDisplay->height()); + ui.lblDryImgDisplay->setPixmap(pixmap); + + QPixmap pixmap2(ui.txtWetImg->text()); + pixmap2= pixmap2.scaledToHeight(ui.lblWetImgDisplay->height()); + ui.lblWetImgDisplay->setPixmap(pixmap2); +} + +void StegoSaurus::on_btnWetImg_clicked() +{ + static QString srcImgFileName="/home/"; + srcImgFileName= QFileDialog::getOpenFileName(this, "Open Bitmap", srcImgFileName, "Bitmap Files(*.bmp)"); + + if(srcImgFileName.isEmpty()){ + ui.lblWetImgDisplay->setText("

    Drag Image Here

    OR

    Select it by browsing

    (BMP Images only)

    "); + ui.lblWetImgDisplay->setPixmap(QPixmap(":/StegoSaurus/images/stegosaurus-256x256.png")); + ui.lblWetImgInfo->setText("No image loaded"); + ui.txtWetImg->setText(""); + sizeofData=0; + return; + } + + setWetImage(srcImgFileName); + +} +void StegoSaurus::setDryImage(const QString &srcImgFileName) +{ + //Get file info + dryImage= new QImage(srcImgFileName); + unsigned int height= dryImage->height(); + unsigned int width= dryImage->width(); + int depth= dryImage->depth(); + //Check the depth, and return if it is not 24-bit + if(depth<24){ + QMessageBox::information(this, "StegoSaurus", "Must be 24-bit bitmap."); + ui.txtDryImg->setText(""); + ui.lblDryImgInfo->setText("No image Loaded"); + return; + } + + //Set the label image + QPixmap pixmap(srcImgFileName); + pixmap= pixmap.scaledToHeight(ui.lblDryImgDisplay->height()); + ui.lblDryImgDisplay->setPixmap(pixmap); + bitsAvailable= height*width*3; + + ui.txtDryImg->setText(srcImgFileName); + + if(bitsAvailable){ + ui.lblDryImgInfo->setText(QString("Height= %L1 Width=%L2 Free Space=%L3 bytes").arg(height) + .arg(width).arg(bitsAvailable/8)); + }else{ + ui.lblDryImgInfo->setText("No room for data"); + qApp->beep(); + } +} +void StegoSaurus::setWetImage(const QString &srcImgFileName) +{ + //Get file info + wetImage= new QImage(srcImgFileName); + unsigned int height= wetImage->height(); + unsigned int width= wetImage->width(); + int depth= wetImage->depth(); + + //Check the depth, and return if it is not 24-bit + if(depth<24){ + QMessageBox::information(this, "StegoSaurus", "Must be 24-bit bitmap."); + ui.txtWetImg->setText(""); + ui.lblWetImgInfo->setText("No image Loaded"); + return; + } + + //Set the label image + QPixmap pixmap(srcImgFileName); + pixmap= pixmap.scaledToHeight(ui.lblWetImgDisplay->height()); + ui.lblWetImgDisplay->setPixmap(pixmap); + + //Read the size of the embeded data + QFile imgFile(srcImgFileName); + if (!imgFile.open(QIODevice::ReadOnly)){ + QMessageBox::warning(this, "StegoSaurus", "Unable to open bitmap file."); + return; + } + if(imgFile.seek(6)){ + imgFile.read((char *)&sizeofData, 4); + }else{ + QMessageBox::warning(this, "StegoSaurus", "Unable to read bitmap file."); + return; + } + + ui.txtWetImg->setText(srcImgFileName); + + if(sizeofData){ + ui.lblWetImgInfo->setText(QString("Height= %L1 Width=%L2 Probable Size of Data=%L3 bytes").arg(height) + .arg(width).arg(sizeofData)); + }else{ + ui.lblWetImgInfo->setText("No data in image."); + qApp->beep(); + } +} + +//The drag and drop methods +void StegoSaurus::dragEnterEvent(QDragEnterEvent *event) +{ + if(ui.tabWidget->currentIndex()==2)return; + + if (event->mimeData()->hasFormat("text/uri-list")){ + QList urls = event->mimeData()->urls(); + if (urls.isEmpty()) + return; + QString fileName = urls.first().toLocalFile(); + //Check the extension + if (fileName.isEmpty()||!fileName.endsWith(".bmp", Qt::CaseInsensitive)) + return; + event->acceptProposedAction(); + } +} + +void StegoSaurus::dropEvent(QDropEvent *event) +{ + QList urls = event->mimeData()->urls(); + if (urls.isEmpty()) + return; + QString fileName = urls.first().toLocalFile(); + if (fileName.isEmpty()) + return; + + switch(ui.tabWidget->currentIndex()){ + case 0: + setDryImage(fileName); + break; + case 1: + setWetImage(fileName); + break; + default: + break; + } + +} + +//The hide methods +void StegoSaurus::on_btnHide_clicked() +{ + //Get the filenames + QString imgFileName= ui.txtDryImg->text(); + QString inputFileName= ui.txtFiletoHide->text(); + //Check if both image file and data file has been selected + if(imgFileName.isEmpty()||inputFileName.isEmpty()){ + QMessageBox::information(this, "StegoSaurus", "Please select a bitmap image and a data file."); + return; + } + //Now check if size of the data file is less than that of the space available + if(inputFileSize*8>bitsAvailable){ + QMessageBox::information(this, "StegoSaurus", "Not enough space available in image to hide the data."); + return; + } + static QString targetImgName="/home/"; + targetImgName= QFileDialog::getSaveFileName(this, "Save bitmap with data to", targetImgName, "Bitmap Files(*.bmp)"); + + if(targetImgName.isEmpty())return; + + //If an image file with the same name exists delete it and then copy, unless source and target are same + if(imgFileName!=inputFileName){ + QFile::remove(targetImgName); + QFile::copy(imgFileName, targetImgName); + } + + //Calculate the no. of padding bytes + unsigned int width= dryImage->width(); + unsigned int padding=0; + if((width*3)%4==0) + padding=0; + unsigned int quotient= (width*3)/4; + padding= 4*(quotient+1)- width*3; + + /////////////////////////////////Hide the data//////////////////////////////////////////// + QFile inputFile(inputFileName); + if (!inputFile.open(QIODevice::ReadOnly)){ + QMessageBox::warning(this, "StegoSaurus", "Unable to open data file for reading."); + return; + } + + //Stamp the size of the data file to the reserved bytes of the image file + QFile imgOutputFile(targetImgName); + if (!imgOutputFile.open(QIODevice::ReadWrite)){ + QMessageBox::warning(this, "StegoSaurus", "Unable to open bitmap file."); + return; + } + if(imgOutputFile.seek(6)){ + imgOutputFile.write((char *)&inputFileSize, 4); + }else{ + QMessageBox::warning(this, "StegoSaurus", "Unable to write to bitmap file."); + return; + } + //Read the dataoffset of the bitmap + unsigned int dataoffset=0; + if(imgOutputFile.seek(10)){ + imgOutputFile.read((char *)&dataoffset, 4); + }else{ + QMessageBox::warning(this, "StegoSaurus", "Unable to read bitmap file."); + return; + } + + //Move by dataoffset bytes + if(!imgOutputFile.seek(dataoffset)){ + QMessageBox::warning(this, "StegoSaurus", "Unable to read bitmap file."); + return; + } + QProgressDialog progress("Embedding Data", "Cancel", 0, inputFileSize, this); + progress.show(); + unsigned int progresscount=0; + unsigned int countBytes=0; + while (!inputFile.atEnd()){ + //Read a byte + unsigned char dataByte=0; + inputFile.getChar((char *)&dataByte); + + //Store each bit of the data byte in 1 byte of the image pixel + //starting with the MSB + for(int i=7; i>=0; i--){ + //Get the bit at position i in the data byte + unsigned char checkByte= 0x01; + checkByte= checkByte<>i; + + unsigned char imageByte=0; + //To ignore the padding bytes + if(countBytes>=width*3){ + countBytes= 0; + //Advance the read pointer + for(int j=0; jtext(); + + //Check image file has been selected + if(imgFileName.isEmpty()){ + QMessageBox::information(this, "StegoSaurus", "Please select a bitmap image."); + return; + } + + static QString targetFileName="/home/"; + targetFileName= QFileDialog::getSaveFileName(this, "Save recovered data to", targetFileName, "All Files(*.*)"); + + if(targetFileName.isEmpty())return; + + //If a file with the same name exists delete it + QFile::remove(targetFileName); + + //Calculate the no. of padding bytes + unsigned int width= wetImage->width(); + unsigned int padding=0; + if((width*3)%4==0) + padding=0; + unsigned int quotient= (width*3)/4; + padding= 4*(quotient+1)- width*3; + + /////////////////////////////////Recover the data//////////////////////////////////////////// + QFile targetFile(targetFileName); + if (!targetFile.open(QIODevice::WriteOnly)){ + QMessageBox::warning(this, "StegoSaurus", "Unable to open data file."); + return; + } + + QFile imgInputFile(imgFileName); + if (!imgInputFile.open(QIODevice::ReadOnly)){ + QMessageBox::warning(this, "StegoSaurus", "Unable to open bitmap file."); + return; + } + + //Read the dataoffset of the bitmap + unsigned int dataoffset=0; + if(imgInputFile.seek(10)){ + imgInputFile.read((char *)&dataoffset, 4); + }else{ + QMessageBox::warning(this, "StegoSaurus", "Unable to read bitmap file."); + return; + } + + //Move by dataoffset bytes + if(!imgInputFile.seek(dataoffset)){ + QMessageBox::warning(this, "StegoSaurus", "Unable to read bitmap file."); + return; + } + + QProgressDialog progress("Recovering Data", "Cancel", 0, sizeofData, this); + progress.show(); + unsigned int progresscount=0; + unsigned int countBytes=0; + //Iterate to recover targetFileSize bytes + for(unsigned int byteNo= 0; byteNo< sizeofData; byteNo++){ + //construct each byte + unsigned char dataByte= 0x00; + for(int bitNo=7; bitNo>=0; bitNo--){ + unsigned char imageByte=0xFF; + //To ignore the padding bytes + if(countBytes>=width*3){ + countBytes= 0; + //Advance the read pointer + for(int j=0; j +#include "ui_stegosaurus.h" + +class StegoSaurus : public QDialog +{ + Q_OBJECT + +public: + StegoSaurus(QWidget *parent = 0, Qt::WFlags flags = 0); + ~StegoSaurus(); + +protected: + void dragEnterEvent(QDragEnterEvent *event); + void dropEvent(QDropEvent *event); + +private: + void resizeEvent ( QResizeEvent *); + Ui::StegoSaurusClass ui; + QImage *dryImage, *wetImage; + unsigned int bitsAvailable, inputFileSize, sizeofData; + + void setDryImage(const QString &); + void setWetImage(const QString &); + +private slots: + + void on_btnWetImg_clicked(); + void on_btnFiletoHide_clicked(); + void on_btnDryImg_clicked(); + + //The hide method + void on_btnHide_clicked(); + //The recover method + void on_btnRecover_clicked(); +}; + +#endif // STEGOSAURUS_H diff --git a/plugins/stegosaurus_plugin/stegosaurus.ico b/plugins/stegosaurus_plugin/stegosaurus.ico new file mode 100644 index 000000000..5b5d38a89 Binary files /dev/null and b/plugins/stegosaurus_plugin/stegosaurus.ico differ diff --git a/plugins/stegosaurus_plugin/stegosaurus.qrc b/plugins/stegosaurus_plugin/stegosaurus.qrc new file mode 100644 index 000000000..32b23abbb --- /dev/null +++ b/plugins/stegosaurus_plugin/stegosaurus.qrc @@ -0,0 +1,9 @@ + + + images/stegosaurus-128x128.png + images/stegosaurus-16x16.png + images/stegosaurus-256x256.png + images/stegosaurus-32x32.png + images/stegosaurus-48x48.png + + diff --git a/plugins/stegosaurus_plugin/stegosaurus.ui b/plugins/stegosaurus_plugin/stegosaurus.ui new file mode 100644 index 000000000..7bb9f9308 --- /dev/null +++ b/plugins/stegosaurus_plugin/stegosaurus.ui @@ -0,0 +1,1615 @@ + + + StegoSaurusClass + + + + 0 + 0 + 599 + 451 + + + + false + + + StegoSaurus 1.0 + + + + :/StegoSaurus/images/stegosaurus-16x16.png:/StegoSaurus/images/stegosaurus-16x16.png + + + + + + false + + + 0 + + + + Hide + + + + + + + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large;">Drag Image Here<br /><br />OR<br /><br />Select it by browsing<br /><br />(BMP Images only)</span></p></body></html> + + + true + + + QFrame::StyledPanel + + + QFrame::Plain + + + + + + :/StegoSaurus/images/stegosaurus-256x256.png + + + Qt::AlignCenter + + + + + + + Bitmap Image + + + + + + + false + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">The path of the dry image</span></p></body></html> + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Select the dry image</span></p></body></html> + + + Browse + + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Shows dry image info</span></p></body></html> + + + QFrame::StyledPanel + + + No image loaded + + + + + + + File to Embed + + + + + + + false + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Path of the file to be hidden</span></p></body></html> + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Select the file to be hidden</span></p></body></html> + + + Browse + + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Shows file info</span></p></body></html> + + + QFrame::StyledPanel + + + No file loaded + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Hit this to hide the file into the bitmap image</span></p></body></html> + + + Hide Data + + + + + + + + Recover + + + + + + + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:x-large;">Drag Image Here<br /><br />OR<br /><br />Select it by browsing<br /><br />(BMP Images only)</span></p></body></html> + + + true + + + QFrame::StyledPanel + + + QFrame::Plain + + + + + + :/StegoSaurus/images/stegosaurus-256x256.png + + + Qt::AlignCenter + + + + + + + Bitmap Image + + + + + + + false + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:12pt; font-weight:600;">The path of the wet image</span></p></body></html> + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:11pt; font-weight:600;">Select the wet image</span></p></body></html> + + + Browse + + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Shows wet image info</span></p></body></html> + + + QFrame::StyledPanel + + + No image loaded + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Hit this to recover data from the bitmap image</span></p></body></html> + + + Recover Data + + + + + + + + About + + + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/StegoSaurus/images/stegosaurus-128x128.png" /></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#5500ff;">Stegosaurus v 1.0</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; color:#5500ff;">Designed by:</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; color:#5500ff;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; color:#5500ff;">Agnit Sarkar</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; color:#5500ff;">(April 2009)</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; color:#5500ff;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; color:#5500ff;">Email:</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; color:#5500ff;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="mailto:agnitsarkar@yahoo.co.uk"><span style=" font-size:12pt; text-decoration: underline; color:#5500ff;">agnitsarkar@yahoo.co.uk</span></a></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; font-style:italic; color:#5500ff;"></p></body></html> + + + Qt::AlignCenter + + + true + + + + + + + + + + + + + + + diff --git a/plugins/stegosaurus_plugin/stegosaurus_plugin.pro b/plugins/stegosaurus_plugin/stegosaurus_plugin.pro new file mode 100644 index 000000000..1b67fe78f --- /dev/null +++ b/plugins/stegosaurus_plugin/stegosaurus_plugin.pro @@ -0,0 +1,29 @@ +#=== this part is common (similar) for all plugin projects ===================== +TEMPLATE = lib +CONFIG += plugin release + +# this is directory, where PluginInterface.h is located +INCLUDEPATH += ../ + +# and, the result (*.so or *.dll) should appear in this directory +DESTDIR = ../bin +OBJECTS_DIR = temp/obj +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + + +# the name of the result file; +TARGET = $$qtLibraryTarget(stegosaurus_plugin) + +HEADERS += ../PluginInterface.h \ + StegoSaurusPlugin.h +SOURCES += StegoSaurusPlugin.cpp + +#=============================================================================== + +# Input +HEADERS += resource.h resource1.h stegosaurus.h +FORMS += stegosaurus.ui +SOURCES += main.cpp stegosaurus.cpp +RESOURCES += stegosaurus.qrc diff --git a/retroshare-gui/src/README.txt b/retroshare-gui/src/README.txt new file mode 100644 index 000000000..e4c645361 --- /dev/null +++ b/retroshare-gui/src/README.txt @@ -0,0 +1,65 @@ +======================================================================================= +README for RetroShare +======================================================================================= + +RetroShare web site . . . . http://retroshare.sourceforge.net/ +Documentation . . . . . . . http://retroshare.sourceforge.net/doc.html +Support . . . . . . . . . . http://retroshare.sourceforge.net/support.html +Forums . . . . . . . . . . http://retroshare.sourceforge.net/forum/ +Wiki . . . . . . . . . . . http://retroshare.sourceforge.net/wiki/ +The Developers site . . . . http://retroshare.sourceforge.net/developers.html +Project site . . . . . . . https://sourceforge.net/projects/retroshare + +Contact: . . . . . . . . . retroshare@lunamutt.com ,defnax@users.sourceforge.net + + +Compiling + Running RetroShare (V0.5.xxx) +========================================================================================= +REQUIREMENTS +========================================================================================= + +Libraries/Tools: + * C/C++ Compiler. (standard on Linux/cygwin) + * Qt >= 4.5.x http://qt.nokia.com/downloads/downloads#lgpl + * OpenSSL http://www.openssl.org/source/openssl-0.9.8k.tar.gz + * MiniUPnP http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.3.tar.gz + * gpgme ftp://ftp.gnupg.org/gcrypt/gpgme/gpgme-1.1.8.tar.bz2 + * libgpg-error ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.7.tar.bz2 + +Windows only: + * Cygwin http://www.cygwin.com/cygwin/setup.exe (for openssl compile) + * MinGW/Msys package http://sourceforge.net/projects/mingw/files/ (for compile gpgme,libgpg-error) + * Pthreads http://sourceware.org/pthreads-win32/ + * Zlib http://www.zlib.net/ + + Latest RetroShare sources from (SVN) sourceforge.net: + svn co https://retroshare.svn.sourceforge.net/svnroot/retroshare retroshare + +========================================================================================= + +Build Scripts are avaible on SVN for Debian and Ubuntu: +http://retroshare.svn.sourceforge.net/viewvc/retroshare/trunk/build_scripts/ + +Latest stable OpenSSL is available at: +http://www.openssl.org + +Latest miniupnpc-1.3 is avaible at: +http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.3.tar.gz + +Latest gpgme Library is avaible at: +ftp://ftp.gnupg.org/gcrypt/gpgme/gpgme-1.1.8.tar.bz2 + +Latest libgpg-error Library is avaible at: +ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.7.tar.bz2 + +Windows only: + pthreads: ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz + zlib: http://www.zlib.net/zlib-1.2.3.tar.gz +========================================================================================= +You can find here instrustions howto compile libretroshare and gui: +http://retroshare.sourceforge.net/wiki/index.php/Developers_Corner + +========================================================================================= +You can go on over to our forum when you have trouble with compiling: +http://retroshare.sourceforge.net/forum/ +--------------------------------------------- diff --git a/retroshare-gui/src/RetroShare.pro b/retroshare-gui/src/RetroShare.pro new file mode 100644 index 000000000..833d34678 --- /dev/null +++ b/retroshare-gui/src/RetroShare.pro @@ -0,0 +1,795 @@ +CONFIG += qt gui uic qrc resources uitools idle bitdht # framecatcher# blogs +QT += network xml script + +TEMPLATE = app +TARGET = RetroShare + +#CONFIG += minimal + +DEFINES += RS_RELEASE_VERSION +RCC_DIR = temp/qrc +UI_DIR = temp/ui +MOC_DIR = temp/moc + +#CONFIG += debug +debug { + QMAKE_CFLAGS += -g +} + +minimal { + CONFIG -= blogs + + DEFINES += MINIMAL_RSGUI +} + +################################# Linux ########################################## +# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib +linux-* { + #CONFIG += version_detail_bash_script + QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 + + system(which gpgme-config >/dev/null 2>&1) { + INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") + } else { + message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) + } + + PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a + + LIBS += ../../libretroshare/src/lib/libretroshare.a + LIBS += -lssl -lgpgme -lupnp -lXss -lgnome-keyring + LIBS *= -rdynamic + DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions + DEFINES *= UBUNTU +} + +linux-g++ { + OBJECTS_DIR = temp/linux-g++/obj +} + +linux-g++-64 { + OBJECTS_DIR = temp/linux-g++-64/obj +} + +version_detail_bash_script { + DEFINES += ADD_LIBRETROSHARE_VERSION_INFO + QMAKE_EXTRA_TARGETS += write_version_detail + PRE_TARGETDEPS = write_version_detail + write_version_detail.commands = ./version_detail.sh +} + +install_rs { + INSTALLS += binary_rs + binary_rs.path = $$(PREFIX)/usr/bin + binary_rs.files = ./RetroShare +} + +#################### Cross compilation for windows under Linux ################### + +win32-x-g++ { + OBJECTS_DIR = temp/win32-x-g++/obj + + LIBS += ../../libretroshare/src/lib.win32xgcc/libretroshare.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libssl.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libcrypto.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libgpgme.dll.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libminiupnpc.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libz.a + LIBS += -L${HOME}/.wine/drive_c/pthreads/lib -lpthreadGCE2 + LIBS += -lQtUiTools + LIBS += -lws2_32 -luuid -lole32 -liphlpapi -lcrypt32 -gdi32 + LIBS += -lole32 -lwinmm + + DEFINES *= WINDOWS_SYS WIN32 WIN32_CROSS_UBUNTU + + INCLUDEPATH += ../../../../gpgme-1.1.8/src/ + INCLUDEPATH += ../../../../libgpg-error-1.7/src/ + + RC_FILE = gui/images/retroshare_win.rc +} + +#################################### Windows ##################################### + +win32 { + # Switch off optimization for release version + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE += -O0 + QMAKE_CFLAGS_RELEASE -= -O2 + QMAKE_CFLAGS_RELEASE += -O0 + + # Switch on optimization for debug version + #QMAKE_CXXFLAGS_DEBUG += -O2 + #QMAKE_CFLAGS_DEBUG += -O2 + + OBJECTS_DIR = temp/obj + #LIBS += -L"D/Qt/2009.03/qt/plugins/imageformats" + #QTPLUGIN += qjpeg + + PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a + + LIBS += ../../libretroshare/src/lib/libretroshare.a + LIBS += -L"../../../../lib" + LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz +# added after bitdht +# LIBS += -lws2_32 + LIBS += -luuid -lole32 -liphlpapi -lcrypt32-cygwin -lgdi32 + LIBS += -lole32 -lwinmm + RC_FILE = gui/images/retroshare_win.rc + + DEFINES += WINDOWS_SYS + + GPG_ERROR_DIR = ../../../../libgpg-error-1.7 + GPGME_DIR = ../../../../gpgme-1.1.8 + INCLUDEPATH += . $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src +} + +##################################### MacOS ###################################### + +macx { + # ENABLE THIS OPTION FOR Univeral Binary BUILD. + CONFIG += ppc x86 + QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 + + CONFIG += version_detail_bash_script + LIBS += ../../libretroshare/src/lib/libretroshare.a + LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan + LIBS += ../../../miniupnpc-1.0/libminiupnpc.a + LIBS += -framework CoreFoundation + LIBS += -framework Security + + # LIBS += -framework CoreServices + + INCLUDEPATH += . + #DEFINES* = MAC_IDLE # for idle feature + CONFIG -= uitools + + +} + +############################## Common stuff ###################################### + +# On Linux systems that alredy have libssl and libcrypto it is advisable +# to rename the patched version of SSL to something like libsslxpgp.a and libcryptoxpg.a + +# ########################################### + +bitdht { + LIBS += ../../libbitdht/src/lib/libbitdht.a + PRE_TARGETDEPS *= ../../libbitdht/src/lib/libbitdht.a +} + +win32 { +# must be added after bitdht + LIBS += -lws2_32 +} + +DEPENDPATH += . \ + rsiface \ + control \ + gui \ + lang \ + util \ + gui\bwgraph \ + gui\chat \ + gui\connect \ + gui\images \ + gui\common \ + gui\toaster \ + gui\help\browser \ + gui\elastic + +INCLUDEPATH += ../../libretroshare/src/ + +# Input +HEADERS += rshare.h \ + gui/notifyqt.h \ + control/bandwidthevent.h \ + control/eventtype.h \ + gui/QuickStartWizard.h \ + gui/DetailsDialog.h \ + gui/DLListDelegate.h \ + gui/ULListDelegate.h \ + gui/StartDialog.h \ + gui/NetworkDialog.h \ + gui/GenCertDialog.h \ + gui/TransfersDialog.h \ + gui/graphframe.h \ + gui/linetypes.h \ + gui/mainpage.h \ + gui/mainpagestack.h \ + gui/MainWindow.h \ + gui/RSHumanReadableDelegate.h \ + gui/TurtleRouterDialog.h \ + gui/TurtleRouterStatistics.h \ + gui/AboutDialog.h \ + gui/ForumsDialog.h \ + gui/forums/ForumDetails.h \ + gui/forums/EditForumDetails.h \ + gui/forums/CreateForum.h \ + gui/forums/CreateForumMsg.h \ + gui/NetworkView.h \ + gui/TrustView.h \ + gui/MessengerWindow.h \ + gui/FriendsDialog.h \ + gui/RemoteDirModel.h \ + gui/RetroShareLink.h \ + gui/SearchTreeWidget.h \ + gui/SearchDialog.h \ + gui/SharedFilesDialog.h \ + gui/ShareManager.h \ + gui/ShareDialog.h \ + gui/SFListDelegate.h \ + gui/SoundManager.h \ + gui/FileTransferInfoWidget.h \ + gui/RsAutoUpdatePage.h \ + gui/HelpDialog.h \ + gui/InfoDialog.h \ + gui/LogoBar.h \ + gui/xprogressbar.h \ + gui/plugins/PluginInterface.h \ + gui/im_history/ImHistoryBrowser.h \ + gui/im_history/IMHistoryKeeper.h \ + gui/im_history/IMHistoryReader.h \ + gui/im_history/IMHistoryItem.h \ + gui/im_history/IMHistoryItemDelegate.h \ + gui/im_history/IMHistoryItemPainter.h \ + gui/im_history/IMHistoryWriter.h \ + lang/languagesupport.h \ + util/stringutil.h \ + util/win32.h \ + util/RetroStyleLabel.h \ + util/dllexport.h \ + util/NonCopyable.h \ + util/rsutildll.h \ + util/dllexport.h \ + util/global.h \ + util/rsqtutildll.h \ + util/Interface.h \ + util/PixmapMerging.h \ + util/MouseEventFilter.h \ + util/EventFilter.h \ + util/EventReceiver.h \ + util/Widget.h \ + util/rsversion.h \ + util/RsAction.h \ + util/printpreview.h \ + util/log.h \ + util/misc.h \ + gui/bwgraph/bwgraph.h \ + gui/profile/ProfileView.h \ + gui/profile/ProfileEdit.h \ + gui/profile/ProfileWidget.h \ + gui/profile/StatusMessage.h \ + gui/chat/PopupChatWindow.h \ + gui/chat/PopupChatDialog.h \ + gui/chat/HandleRichText.h \ + gui/chat/ChatStyle.h \ + gui/channels/CreateChannel.h \ + gui/channels/ChannelDetails.h \ + gui/channels/CreateChannelMsg.h \ + gui/channels/EditChanDetails.h \ + gui/channels/ShareKey.h \ + gui/connect/ConfCertDialog.h \ + gui/msgs/MessageComposer.h \ + gui/msgs/MessageWindow.h \ + gui/msgs/MessageWidget.h \ + gui/msgs/TagsMenu.h \ + gui/msgs/textformat.h \ + gui/images/retroshare_win.rc.h \ + gui/settings/rsharesettings.h \ + gui/settings/RsharePeerSettings.h \ + gui/settings/rsettings.h \ + gui/settings/rsettingswin.h \ + gui/settings/configpage.h \ + gui/settings/GeneralPage.h \ + gui/settings/DirectoriesPage.h \ + gui/settings/ServerPage.h \ + gui/settings/NetworkPage.h \ + gui/settings/NotifyPage.h \ + gui/settings/CryptoPage.h \ + gui/settings/MessagePage.h \ + gui/settings/NewTag.h \ + gui/settings/ForumPage.h \ + gui/settings/PluginsPage.h \ + gui/settings/AppearancePage.h \ + gui/settings/FileAssociationsPage.h \ + gui/settings/SoundPage.h \ + gui/settings/TransferPage.h \ + gui/settings/ChatPage.h \ + gui/settings/AddFileAssociationDialog.h \ + gui/toaster/MessageToaster.h \ + gui/toaster/OnlineToaster.h \ + gui/toaster/DownloadToaster.h \ + gui/common/vmessagebox.h \ + gui/common/rwindow.h \ + gui/common/html.h \ + gui/common/StatusDefs.h \ + gui/common/TagDefs.h \ + gui/common/GroupDefs.h \ + gui/common/Emoticons.h \ + gui/common/RSTreeWidgetItem.h \ + gui/common/RSTabWidget.h \ + gui/common/RSItemDelegate.h \ + gui/common/PeerDefs.h \ + gui/common/PopularityDefs.h \ + gui/common/GroupTreeWidget.h \ + gui/common/RSTreeView.h \ + gui/style/RSStyle.h \ + gui/style/StyleDialog.h \ + gui/MessagesDialog.h \ + gui/help/browser/helpbrowser.h \ + gui/help/browser/helptextbrowser.h \ + gui/statusbar/peerstatus.h \ + gui/statusbar/natstatus.h \ + gui/statusbar/dhtstatus.h \ + gui/statusbar/ratesstatus.h \ + gui/statusbar/hashingstatus.h \ + gui/statusbar/discstatus.h \ + gui/advsearch/advancedsearchdialog.h \ + gui/advsearch/expressionwidget.h \ + gui/advsearch/guiexprelement.h \ + gui/elastic/graphwidget.h \ + gui/elastic/edge.h \ + gui/elastic/arrow.h \ + gui/elastic/node.h \ + gui/NewsFeed.h \ + gui/ChannelFeed.h \ + gui/feeds/FeedHolder.h \ + gui/feeds/ForumNewItem.h \ + gui/feeds/ForumMsgItem.h \ + gui/feeds/PeerItem.h \ + gui/feeds/MsgItem.h \ + gui/feeds/ChatMsgItem.h \ + gui/feeds/ChanNewItem.h \ + gui/feeds/ChanMsgItem.h \ + gui/feeds/SubFileItem.h \ + gui/feeds/SubDestItem.h \ + gui/feeds/AttachFileItem.h \ + gui/connect/ConnectFriendWizard.h \ + gui/groups/CreateGroup.h + + +FORMS += gui/StartDialog.ui \ + gui/GenCertDialog.ui \ + gui/AboutDialog.ui \ + gui/QuickStartWizard.ui \ + gui/NetworkDialog.ui \ + gui/TransfersDialog.ui \ + gui/ForumsDialog.ui \ + gui/MainWindow.ui \ + gui/TurtleRouterDialog.ui \ + gui/TurtleRouterStatistics.ui \ + gui/forums/CreateForum.ui \ + gui/forums/CreateForumMsg.ui \ + gui/forums/ForumDetails.ui \ + gui/forums/EditForumDetails.ui \ + gui/NetworkView.ui \ + gui/TrustView.ui \ + gui/MessengerWindow.ui \ + gui/FriendsDialog.ui \ + gui/SearchDialog.ui \ + gui/SharedFilesDialog.ui \ + gui/ShareManager.ui \ + gui/ShareDialog.ui \ + gui/MessagesDialog.ui \ + gui/help/browser/helpbrowser.ui \ + gui/HelpDialog.ui \ + gui/InfoDialog.ui \ + gui/DetailsDialog.ui \ + gui/bwgraph/bwgraph.ui \ + gui/profile/ProfileView.ui \ + gui/profile/ProfileEdit.ui \ + gui/profile/ProfileWidget.ui \ + gui/profile/StatusMessage.ui \ + gui/channels/CreateChannel.ui \ + gui/channels/CreateChannelMsg.ui \ + gui/channels/ChannelDetails.ui \ + gui/channels/EditChanDetails.ui \ + gui/channels/ShareKey.ui \ + gui/chat/PopupChatWindow.ui \ + gui/chat/PopupChatDialog.ui \ + gui/connect/ConfCertDialog.ui \ + gui/msgs/MessageComposer.ui \ + gui/msgs/MessageWindow.ui\ + gui/msgs/MessageWidget.ui\ + gui/settings/settings.ui \ + gui/settings/GeneralPage.ui \ + gui/settings/DirectoriesPage.ui \ + gui/settings/ServerPage.ui \ + gui/settings/NetworkPage.ui \ + gui/settings/NotifyPage.ui \ + gui/settings/CryptoPage.ui \ + gui/settings/MessagePage.ui \ + gui/settings/NewTag.ui \ + gui/settings/ForumPage.ui \ + gui/settings/PluginsPage.ui \ + gui/settings/AppearancePage.ui \ + gui/settings/TransferPage.ui \ + gui/settings/SoundPage.ui \ + gui/settings/ChatPage.ui \ + gui/toaster/MessageToaster.ui \ + gui/toaster/OnlineToaster.ui \ + gui/toaster/DownloadToaster.ui \ + gui/advsearch/AdvancedSearchDialog.ui \ + gui/advsearch/expressionwidget.ui \ + gui/NewsFeed.ui \ + gui/ChannelFeed.ui \ + gui/feeds/ForumNewItem.ui \ + gui/feeds/ForumMsgItem.ui \ + gui/feeds/PeerItem.ui \ + gui/feeds/MsgItem.ui \ + gui/feeds/ChatMsgItem.ui \ + gui/feeds/ChanNewItem.ui \ + gui/feeds/ChanMsgItem.ui \ + gui/feeds/SubFileItem.ui \ + gui/feeds/SubDestItem.ui \ + gui/feeds/AttachFileItem.ui \ + gui/im_history/ImHistoryBrowser.ui \ + gui/groups/CreateGroup.ui \ + gui/common/GroupTreeWidget.ui \ + gui/style/StyleDialog.ui + +SOURCES += main.cpp \ + rshare.cpp \ + gui/notifyqt.cpp \ + gui/AboutDialog.cpp \ + gui/QuickStartWizard.cpp \ + gui/DetailsDialog.cpp \ + gui/DLListDelegate.cpp \ + gui/ULListDelegate.cpp \ + gui/StartDialog.cpp \ + gui/GenCertDialog.cpp \ + gui/NetworkDialog.cpp \ + gui/TransfersDialog.cpp \ + gui/graphframe.cpp \ + gui/mainpagestack.cpp \ + gui/TurtleRouterDialog.cpp \ + gui/TurtleRouterStatistics.cpp \ + gui/MainWindow.cpp \ + gui/ForumsDialog.cpp \ + gui/forums/ForumDetails.cpp \ + gui/forums/EditForumDetails.cpp \ + gui/forums/CreateForum.cpp \ + gui/forums/CreateForumMsg.cpp \ + gui/NetworkView.cpp \ + gui/TrustView.cpp \ + gui/MessengerWindow.cpp \ + gui/FriendsDialog.cpp \ + gui/RemoteDirModel.cpp \ + gui/RsAutoUpdatePage.cpp \ + gui/RetroShareLink.cpp \ + gui/SearchTreeWidget.cpp \ + gui/SearchDialog.cpp \ + gui/SharedFilesDialog.cpp \ + gui/ShareManager.cpp \ + gui/ShareDialog.cpp \ + gui/SFListDelegate.cpp \ + gui/SoundManager.cpp \ + gui/MessagesDialog.cpp \ + gui/FileTransferInfoWidget.cpp \ + gui/im_history/ImHistoryBrowser.cpp \ + gui/im_history/IMHistoryKeeper.cpp \ + gui/im_history/IMHistoryReader.cpp \ + gui/im_history/IMHistoryItem.cpp \ + gui/im_history/IMHistoryItemDelegate.cpp \ + gui/im_history/IMHistoryItemPainter.cpp \ + gui/im_history/IMHistoryWriter.cpp \ + gui/help/browser/helpbrowser.cpp \ + gui/help/browser/helptextbrowser.cpp \ + gui/HelpDialog.cpp \ + gui/InfoDialog.cpp \ + gui/LogoBar.cpp \ + gui/xprogressbar.cpp \ + lang/languagesupport.cpp \ + util/stringutil.cpp \ + util/win32.cpp \ + util/RetroStyleLabel.cpp \ + util/WidgetBackgroundImage.cpp \ + util/NonCopyable.cpp \ + util/PixmapMerging.cpp \ + util/MouseEventFilter.cpp \ + util/EventFilter.cpp \ + util/EventReceiver.cpp \ + util/Widget.cpp \ + util/RsAction.cpp \ + util/rsversion.cpp \ + util/printpreview.cpp \ + util/log.cpp \ + util/misc.cpp \ + gui/bwgraph/bwgraph.cpp \ + gui/profile/ProfileView.cpp \ + gui/profile/ProfileEdit.cpp \ + gui/profile/ProfileWidget.cpp \ + gui/profile/StatusMessage.cpp \ + gui/channels/CreateChannel.cpp \ + gui/channels/CreateChannelMsg.cpp \ + gui/channels/ChannelDetails.cpp \ + gui/channels/EditChanDetails.cpp \ + gui/channels/ShareKey.cpp \ + gui/chat/PopupChatWindow.cpp \ + gui/chat/PopupChatDialog.cpp \ + gui/chat/HandleRichText.cpp \ + gui/chat/ChatStyle.cpp \ + gui/connect/ConfCertDialog.cpp \ + gui/msgs/MessageComposer.cpp \ + gui/msgs/MessageWidget.cpp \ + gui/msgs/MessageWindow.cpp \ + gui/msgs/TagsMenu.cpp \ + gui/common/vmessagebox.cpp \ + gui/common/rwindow.cpp \ + gui/common/html.cpp \ + gui/common/StatusDefs.cpp \ + gui/common/TagDefs.cpp \ + gui/common/GroupDefs.cpp \ + gui/common/Emoticons.cpp \ + gui/common/RSTreeWidgetItem.cpp \ + gui/common/RSTabWidget.cpp \ + gui/common/RSItemDelegate.cpp \ + gui/common/PeerDefs.cpp \ + gui/common/PopularityDefs.cpp \ + gui/common/GroupTreeWidget.cpp \ + gui/common/RSTreeView.cpp \ + gui/style/RSStyle.cpp \ + gui/style/StyleDialog.cpp \ + gui/settings/configpage.cpp \ + gui/settings/rsharesettings.cpp \ + gui/settings/RsharePeerSettings.cpp \ + gui/settings/rsettings.cpp \ + gui/settings/rsettingswin.cpp \ + gui/settings/GeneralPage.cpp \ + gui/settings/DirectoriesPage.cpp \ + gui/settings/ServerPage.cpp \ + gui/settings/NetworkPage.cpp \ + gui/settings/NotifyPage.cpp \ + gui/settings/CryptoPage.cpp \ + gui/settings/MessagePage.cpp \ + gui/settings/NewTag.cpp \ + gui/settings/ForumPage.cpp \ + gui/settings/PluginsPage.cpp \ + gui/settings/AppearancePage.cpp \ + gui/settings/FileAssociationsPage.cpp \ + gui/settings/SoundPage.cpp \ + gui/settings/TransferPage.cpp \ + gui/settings/ChatPage.cpp \ + gui/settings/AddFileAssociationDialog.cpp \ + gui/statusbar/peerstatus.cpp \ + gui/statusbar/natstatus.cpp \ + gui/statusbar/dhtstatus.cpp \ + gui/statusbar/ratesstatus.cpp \ + gui/statusbar/hashingstatus.cpp \ + gui/statusbar/discstatus.cpp \ + gui/toaster/MessageToaster.cpp \ + gui/toaster/DownloadToaster.cpp \ + gui/toaster/OnlineToaster.cpp \ + gui/advsearch/advancedsearchdialog.cpp \ + gui/advsearch/expressionwidget.cpp \ + gui/advsearch/guiexprelement.cpp \ + gui/elastic/graphwidget.cpp \ + gui/elastic/edge.cpp \ + gui/elastic/arrow.cpp \ + gui/elastic/node.cpp \ + gui/NewsFeed.cpp \ + gui/ChannelFeed.cpp \ + gui/feeds/ForumNewItem.cpp \ + gui/feeds/ForumMsgItem.cpp \ + gui/feeds/PeerItem.cpp \ + gui/feeds/MsgItem.cpp \ + gui/feeds/ChatMsgItem.cpp \ + gui/feeds/ChanNewItem.cpp \ + gui/feeds/ChanMsgItem.cpp \ + gui/feeds/SubFileItem.cpp \ + gui/feeds/SubDestItem.cpp \ + gui/feeds/AttachFileItem.cpp \ + gui/connect/ConnectFriendWizard.cpp \ + gui/groups/CreateGroup.cpp + +RESOURCES += gui/images.qrc lang/lang.qrc gui/help/content/content.qrc + +TRANSLATIONS += \ + lang/retroshare_en.ts \ + lang/retroshare_es.ts \ + lang/retroshare_da.ts \ + lang/retroshare_de.ts \ + lang/retroshare_fi.ts \ + lang/retroshare_fr.ts \ + lang/retroshare_ja_JP.ts \ + lang/retroshare_ko.ts \ + lang/retroshare_ru.ts \ + lang/retroshare_tr.ts \ + lang/retroshare_sv.ts \ + lang/retroshare_zh_CN.ts + +unfinishedtranslations { + + TRANSLATIONS += \ + lang/retroshare_bg.ts \ + lang/retroshare_af.ts \ + lang/retroshare_gr.ts \ + lang/retroshare_it.ts \ + lang/retroshare_nl.ts \ + lang/retroshare_pl.ts \ + lang/retroshare_pt.ts \ + lang/retroshare_sl.ts \ + lang/retroshare_sr.ts \ + lang/retroshare_zh_TW.ts + +} + +# Shifted Qt4.4 dependancies to here. +# qmake CONFIG=pluginmgr + +pluginmgr { + + SOURCES += gui/PluginsPage.cpp \ + gui/PluginManagerWidget.cpp \ + gui/PluginManager.cpp + + HEADERS += gui/PluginsPage.h \ + gui/PluginManagerWidget.h \ + gui/PluginManager.h + + DEFINES *= PLUGINMGR + +} + +blogs { + +DEPENDPATH += gui/unfinished \ + +HEADERS += gui/unfinished/blogs/BlogsDialog.h \ + gui/unfinished/blogs/CreateBlog.h \ + gui/unfinished/blogs/CreateBlogMsg.h \ + gui/unfinished/blogs/BlogsMsgItem.h \ + gui/unfinished/blogs/BlogDetails.h \ + gui/feeds/BlogNewItem.h \ + gui/feeds/BlogMsgItem.h \ + +FORMS += gui/unfinished/blogs/BlogsDialog.ui \ + gui/unfinished/blogs/CreateBlog.ui \ + gui/unfinished/blogs/CreateBlogMsg.ui \ + gui/unfinished/blogs/BlogsMsgItem.ui \ + gui/unfinished/blogs/BlogDetails.ui \ + gui/feeds/BlogNewItem.ui \ + gui/feeds/BlogMsgItem.ui \ + +SOURCES += gui/unfinished/blogs/BlogsDialog.cpp \ + gui/unfinished/blogs/CreateBlog.cpp \ + gui/unfinished/blogs/CreateBlogMsg.cpp \ + gui/unfinished/blogs/BlogsMsgItem.cpp \ + gui/unfinished/blogs/BlogDetails.cpp \ + gui/feeds/BlogNewItem.cpp \ + gui/feeds/BlogMsgItem.cpp \ + +DEFINES += BLOGS +} + +# use_links { +# HEADERS += gui/AddLinksDialog.h \ +# gui/LinksDialog.h +# +# FORMS += gui/AddLinksDialog.ui \ +# gui/LinksDialog.ui +# +# SOURCES += gui/AddLinksDialog.cpp \ +# gui/LinksDialog.cpp +# +# DEFINES += RS_USE_LINKS +# } + +unfinished { + +DEPENDPATH += gui/unfinished \ + +HEADERS += gui/unfinished/ApplicationWindow.h \ + gui/unfinished/CalDialog.h \ + gui/unfinished/ExampleDialog.h \ + gui/unfinished/GamesDialog.h \ + gui/unfinished/PhotoDialog.h \ + gui/unfinished/PhotoShow.h \ + gui/unfinished/StatisticDialog.h + + +FORMS += gui/unfinished/ApplicationWindow.ui \ + gui/unfinished/CalDialog.ui \ + gui/unfinished/ExampleDialog.ui \ + gui/unfinished/GamesDialog.ui \ + gui/unfinished/PhotoDialog.ui \ + gui/unfinished/PhotoShow.ui \ + gui/unfinished/StatisticDialog.ui + +SOURCES += gui/unfinished/ApplicationWindow.cpp \ + gui/unfinished/CalDialog.cpp \ + gui/unfinished/ExampleDialog.cpp \ + gui/unfinished/GamesDialog.cpp \ + gui/unfinished/PhotoDialog.cpp \ + gui/unfinished/PhotoShow.cpp \ + gui/unfinished/StatisticDialog.cpp + + DEFINES *= UNFINISHED +} + +idle { + +HEADERS += idle/idle.h + +SOURCES += idle/idle.cpp \ + idle/idle_platform.cpp +} + +framecatcher { + +HEADERS += util/framecatcher.h + +SOURCES += util/framecatcher.cpp + +LIBS += -lxine + +DEFINES *= CHANNELS_FRAME_CATCHER + +} + + + +minimal { + SOURCES = main.cpp \ + rshare.cpp \ + gui/notifyqt.cpp \ + gui/MessengerWindow.cpp \ + gui/StartDialog.cpp \ + gui/GenCertDialog.cpp \ + gui/connect/ConfCertDialog.cpp \ + gui/InfoDialog.cpp \ + gui/help/browser/helpbrowser.cpp \ + gui/help/browser/helptextbrowser.cpp \ + gui/settings/rsettings.cpp \ + gui/settings/RsharePeerSettings.cpp \ + gui/settings/rsharesettings.cpp \ + gui/common/rwindow.cpp \ + gui/common/StatusDefs.cpp \ + gui/common/PeerDefs.cpp \ + gui/common/RSTreeWidgetItem.cpp \ + gui/LogoBar.cpp \ + gui/RsAutoUpdatePage.cpp \ + gui/common/vmessagebox.cpp \ + gui/common/html.cpp \ + util/RetroStyleLabel.cpp \ + util/log.cpp \ + util/win32.cpp \ + util/Widget.cpp \ + util/stringutil.cpp \ + lang/languagesupport.cpp + + FORMS = gui/MessengerWindow.ui \ + gui/StartDialog.ui \ + gui/GenCertDialog.ui \ + gui/connect/ConfCertDialog.ui \ + gui/InfoDialog.ui \ + gui/help/browser/helpbrowser.ui + + HEADERS = rshare.h \ + gui/notifyqt.h \ + gui/MessengerWindow.h \ + gui/StartDialog.h \ + gui/GenCertDialog.h \ + gui/connect/ConfCertDialog.h \ + gui/InfoDialog.h \ + gui/help/browser/helpbrowser.h \ + gui/help/browser/helptextbrowser.h \ + gui/settings/rsettings.h \ + gui/settings/rsharesettings.h \ + gui/settings/RsharePeerSettings.h \ + gui/common/rwindow.h \ + gui/common/StatusDefs.h \ + gui/common/PeerDefs.h \ + gui/common/RSTreeWidgetItem.h \ + gui/LogoBar.h \ + gui/RsAutoUpdatePage.h \ + gui/common/vmessagebox.h \ + gui/common/html.h \ + util/RetroStyleLabel.h \ + util/log.h \ + util/win32.h \ + util/Widget.h \ + util/stringutil.h \ + lang/languagesupport.h +} diff --git a/retroshare-gui/src/Todo.txt b/retroshare-gui/src/Todo.txt new file mode 100644 index 000000000..1d1bcab64 --- /dev/null +++ b/retroshare-gui/src/Todo.txt @@ -0,0 +1,7 @@ +RetroShare Todo list +==================================================================== + +Projects list and Todo list on Wiki: +http://retroshare.sourceforge.net/wiki/index.php/Development + +http://retroshare.sourceforge.net/wiki/index.php/To_do_list diff --git a/retroshare-gui/src/changelog.txt b/retroshare-gui/src/changelog.txt new file mode 100644 index 000000000..e51cbf929 --- /dev/null +++ b/retroshare-gui/src/changelog.txt @@ -0,0 +1,1375 @@ +Changes for v0.5.1d + +* Found the CacheTransfer Killing Bug... misplaced brackets! +* fixed a bug in pqissl and pqistreamer. The 2nd one was responsible for disconnections and errors in GetTlvString type +* Fixed the Missing Cache File bug. +* Added Old Cache Storage... so these can be retrieved. +* Connected up the CancelCacheFile() -> FileCancel. +* Removed ipaddr = 1 bug +* added #ifdefs to remove debugging output in p3BitDht. +* corrected uninitialized value +* made "." be a plugin directory for debugging only +* corrected display of uploaded size +* made search case insentitive, by default +* made the default behavior for multiple keywords search to eb an AND between keywords (emule style) +* Fixed html title bug in the forum message when answering to a message in ForumMsgItem. +* Fixed enabled sate of the new message buton in ForumsDialog. +* moved Plugins page little bit to the top of the settings +* PluginManager: + * Fixed compile under Windows. + * Removed CloseHandle of GetModuleHandle. + * Added missing return when the function entry of the plugin is NULL. + * Fixed checking for the extension ".dll". +* Fixed reaction of the checkbox "web of trust". Now the list of unvalid gpg keys is shown or hide directly after the click. +* Fixed calculation of the unread messages in MessagesDialog. The starred messages was not counted as unread. +* Set some tree widgets to allColumnsShowFocus. +* added settings page for plugins. +* fixed LinksCloud Plugin +* fixed plugin .pri file for windows and ubuntu +* added dlopen method for windows. To be tested. +* Added basic infrastructure to plugin system in libretroshare and retroshare-gui. +* ported LinksCloud to a new plugin, and removed it from main sources +* Made the hash-cache more compliant with mounted/network drives: + * corrected bug that would wipe out the cache file every other start + * missing root directories are not discarded anymore, but kept empty, unless the user really removes them +* Reworked settings dialog: + * The settings page loads the data with the first show. The dialog now starts faster. + * Cleaned DirectoriesPage, removed the directory list and save the data with the OK button. +* Automatic add the recommended friend(s) as CC in the MessageComposer. +* Fixed crash in ForumsDialog (second try). +* Added a "return" if QTreeWidgetItem = NULL, to stop crash. +* Fixed crash in ForumsDialog (hopefully) +* send plain text message instead of html, when the text contains no html specifics. +* enabled new Spanish translation +* Fixed refill of the threads tree after receiving a new message. +* Now the new message is expanded. +* Moved the fill function of the ForumsDialog to a QThread. +* Fixed memory leak of the fill thread of the history browser. +* cleaned display of TR statistics +* Optimized the functions for the forum messages. + - used "const std::string&" for the parameters + - used "std::map" for the read status + - removed useless variables +* Added new define DEBUG_FORUMS in ForumsDialog.cpp. +* Added function to generate mass data for the forum messages. +* Fixed german language for the FriendsDialog. +* Added a placeholder text to the message list in the MessagesDialog (currently used when Starred is selected). +* Connected the menu actions reply, reply all and forward in MessagesDialog. Now they work again. +* Added missing Q_OBJECT to TreeStyle_RDM and fixed translation. +* MessagesDialog: + - Renamed "Favorite Tags" to "Quick View". + - Added the quick view "Starred" to the list to show all messages signed with a star. +* Redesigned the MessagesDialog to open the message in a new tab or new window for reading. +* The MessageComposer is now only for writing a new message or editing a message from the draft box. +* Added a new setting to the MessagePage. +* Added a second tab for Router Statistics +* renamed Tunneling to Router Requests +* added missing info for search depths +* improved tunnel statistics gui +* moved TR filtering to beginning of TR handlign function. Makes it more consistent w.t.r. the displayed turtle statistics +* added automatic limitation of turtle search and turtle tunnel requests as a function of current traffic +* added additional statistics from turtle router. +* Moved the star to the first column in MessagesDialog. +* Fixed debug output in FriendsDialog. +* Show the selected tag in the tab title in MessagesDialog. +* Included patch to compile on OpenSUSE 11.4 (from AsamK) +* Added a star column for messages. +* added a display of turtle search/tunnel requests over time, to help spotting potential spammers +* Added to sort by Age when one day, one week or one month is selected +* Fixed compile Problems on Ubuntu LTS +* Added tags to the MessageComposer. +* Added context menu to contact list in MessageComposer. +* Show the RetroShare id of the peer and the signers of the key in ConfCertDialog as clickable links. +* Disabled the CACHE_OPT code, until the duplicate cache entries is fixed. +* re-worked printcache to analyse a large batch of cache files. +* Added "Copy RetroShare Link" of the selected peer in PeersDialog and NetworkDialog. +* Removed the + button in channels and forums and moved the post button to the right side. +* Added tooltip's for Messages columns +* Added word wrap to the title of the thread and the subject of the message to avoid the stretch of the splitter. +* Changed style sheet of the tags in MessageDialog to gradient color. +* Added a new button in the forums dialog to download all links in the selected forum message. +* Fixed style sheet of auto download button in channels. +* Removed the difference of the separator for Linux and Windows. +* Removed extra "/" of the filename (e.g. "E://") of the hashed file when sharing a whole drive. +* fixed bug related to opening cache hist file in text mode for windows +* added cleaning of cipher context to authssl encrypt decrypt functions +* added header to trustview which caused compilation error +* Fixed drag and drop of files to a forum message with utf8 chars. +* Fixed recommend friend. +* fixed the layout of ForumMsgItem +* added to RetroShare Help page new commands entry for "-r retroshare://..." +* Fixed some more utf8 handling in the GUI. +* Optimized creation of the RetroShare links for forum and channel messages. +* added history cache optimisation to subscribed/client groups. +* added couple more ifdefines to remove cache opt code. +* fixed ForumsMsgItem to not stretch the widget +* Added new RetroShare link format to write a message +* retroshare://message?id=...[&subject=...] +* Added clickable links in ForumMsgItem for the signer of the message to start the MessageComposer. +* Fixed creation of the RetroShare links as anchor. +* Corrected bugs in chat: + - sending large messages now works, thanks to RsChatMsgItem splitting (not 100% backward compatible, but avoids crashing) + - removed crash due to dynamic_cast onto a deleted pointer. +* Enabled on Private Chat to display for the status string smileys, when there is smiley codes used. +* Added new RetroShare link format to start a search retroshare://search?keywords=... +* Enabled key "delete" to remove search results. +* Removed the GoTo buttons from the feeds and added clickable links. +* Enabled space to switch the read state in MessagesDialog and ForumsDialog. +* Added the name and location to the title of the MainWindow. +* Get the name and location for the window tile and tray tooltip only once at start. +* Added title to the RetroShare file links shown as toolhelp "hash (size)". +* added script to gather statistics from ppa repository +* suppressed channel source ID from the file source peer list +* updated base resolution of RS icon to 48x48 +* Enabled drag and drop in ShareManager to add folders to the share. +* improved strategy of cleaning unfinished cache transfers +* fixed display inconsistency in tunnel local src/dst when getPeerDetails() call fails +* always set location for connected peer. Previous settign was causing blank location display + +Changes for v0.5.1c + +* added print-cache code to the tests suite +* Added new RetroShare link formats: + - retroshare://forum? + - retroshare://channel?... +* Added "Go to" from the news feed of forums and channels. +* Added "Copy RetroShare Link" to the forum/channel tree and messagees. +* Fixed style sheet of the auto download button in ChannelFeed. +* Fixed wrong size of the transfered link from the command line in EventReceiver. +* changed policy for canceling cache files: only inactive transfers get canceled now. +* used tr1::unordered_set instead of std::set to store pointer checking list, as it is more efficients for lookups +* Adding a link from the browser now starts RetroShare when it is not running. +* Added handling of RetroShare protocol under Windows. +* Added new command line parameter "-r retroshare://..." for adding links to the registered running RetroShare. +* attempt at making remoteDirModel less CPU intentive. Remove potential deadlock source in SearchDialog. +* removed potential seg fault with decrypting cache file +* implemented a verification for tunnel results. + - When the network gets heavily loaded, some tunnel results happen to get back twice. + - This stops the tunnel result sibblings +* fixed cache opt bug related to new msg notice being flagged up for historical msgs +* New dialog for defining own colors for the private chat window. +* enabled file preview again for non windows users, using a direct call to the file in partials +* added logic to deal with case where auto dl has been disabled then re-enabled after a manual download +* for each channel msg post download request is now only called once. +* fast simplification of code in pqistreamer, and added a missing =null in p3service that could cause a bug +* Removed automatic cleaning of the certificate in p3Peers::loadDetailsFromStringCert. +* Added new button in ConnectFriendWizard for cleaning the certificate. +* Fixed cleaning: + - added blank line after the armor header + - moved the checksum to a new line +* auto download option: + - ability to enable and disable channels auto dl added + - added gui update to channel feed +* reduced path to only parent directory, to make cost tractable +* added random bias to search and tunnel request maximum depth +* added random (and biased) re-routing of tunnel request to improve tunnel length. +* added a column for directory in flat view of shared files +* made sign GPG key button disabled by default, and added a tooltip. As this action cannot be undone,it must be performed knowingly. +* Fixed Q_ASSERT in SharedFilesDialog on Windows. +* Load and save the view type (flat or tree) in SharedFilesDialog. +* fix the msg download problem +* part of code the disable auto download for channels +* Fixed problem with utf characters in the %APPDATA% path on Windows. +* made FileEntry derive from SmallObject class, to improve memory cache efficiency (50% time gained) +* added some optimization to RequestDirDetails internal functions +* improved sorting/selection in shared files flat mode +* Fixed crash on shutdown of RetroShare, when the cache loading is running. + - Now the p3distrib threads are stopped before the instance of AuthGPG is deleted. +* fixed some stylesheets to use gradients instead of a background images, to solve some problems +* implemented an optional flat view for shared files that allows sorting by date/peer/name +* restored the search for flat view only (very slow for tree view) +* cleaned the code a bit: made two subclasses of RetroshareDirModel: TreeStyle_RDM and FlatStyle_RDM +* turned some uint32_t into int, for file watch period (did not produce a bug, but was still incorrect) +* added a missing pthread_join in file checking, that eventually caused a leak of thread resources +* changed the order of check in tick() to allow cancelling a file that is being checked +* removed the hash step from mutex protection +* added error message when thread creation fails +* made sign GPG key checkbox unchecked by default +* made current index be 0 for showing uploads by default +* added a checkbox in settings for tuning auto-check of shared directories +* Saved the visible state of the avatar picture in private chat for the friend. +* Added parameter to RSettingsWin::showYourself to show the options with a specific page for news feed. +* added tooltip for systray to display nickname and location +* Show last error (GetLastError) in log when lock file cannot be accessed on Windows. +* fixed file leak in history cache opt +* added main parts of history cache optimisation. disabled at the moment (has file leakage) +* check-pointing work essentially, but in principle working, +* added lockfile path info to the multiple-instances warning window in rs- +* attempt to make GPG errors more verbose at cert exchange time +* implemented a backward compatible fix for bug when searching (advanced) with max size larger than 2Gb +* implemented a better management of tunnel requests +* Added a basic description of the chat style. +* disabled the default context menus for the QToolBar's +* Share the download directory by default. +* Removed member ftController::mShareDownloadDir and calculate the value from the shared directories. +* Combined the two methods for share and unshare of the download dir. +* Added share incoming directory to the QuickStartWizard. +* Translate QuickStartWizard, GenCertDialog and StartDialog into german. +* Fixed tab order of the upload and download settings in QuickStartWizard. +* Fixed utf8 issues when the partial or the download dir is set to a utf8 dir. +* Use the native dialog for selecting the shared folder. +* Messages with plain text (like the welcome message) are shown correctly. +* added missign destructors, causing some parasitic memory leaks + +Changes for v0.5.1b + +* Added missing return... which was crashing OSX during directory creation. +* fixed a toolbar icon to display with a correct size on macosx +* The working (hashing) thread FileIndexMonitor is now stopped when RetroShare is closed. +* Removed tab focus from the toolbar and image buttons. +* Fixd german translation. +* supressed memory leak due to not deleting a RsItem +* suppressed potential SIGSEGV as exit time +* suppressed memory leak in GUI +* Added a confirm to the delete history action. +* Added the RetroShare icon to the password input window. +* fixed soem other potential SIGSEGVs +* fixed potential SIGSEGV because of not checking returned pointer + +Changes for v0.5.1a + +New features (DHT, Channels, Network View) +Improved stability w.r.t. previous version 0.5.0g" +Added lots of improvements, check for details svn log entrys + +Changes for v0.5.0g + +* corrected a bug that caused file copy error: a closeFile() was missing when the file is complete. + + +Changes for v0.5.0f + +* restored the retroshare-nogui executable +* bug corrections in cachestrapper +* bug corrections in RsTunnelItem and p3tunnel +* better error handling in rstunnelitem on windows +* removed deadlock in data multiplex +* improved p3disc info update + + +Changes for v0.5.0e + +* Made a pass on the code in p3disc. + +* Corrected some bugs: + - suppressed an unwanted return in packet treatment + - prevented sending info to a peer about itself + - changed askInfoToAllPeers() such as not to discard info from peers with + NODISC flag (because we especially need info for these) + - enabled receiving p3disc info even if p3discovery is disabled. Indeed, + disabeling p3disc is a measure of protection, so it should limit the + export of p3disc info, not the import. + - removed test discarding info about dummy friends, because it is useless + - don't discard info about peers that have the NODISC flag (meaning that we + especially need info for them) + - added safety check about received GPG keys. Before we relied on this test + being performed by p3ConnMgr::addFriend() + - added some debug info + +* put correct (i.e. non conservative) size for RsDiscReply packets + +* corrected bug in rsdiscitem that prevented RsDiscReply packets to transfer cp serialiser/rsdiscitems.cc + +* switched ip addr finder to on by default (users seem to request it, and its not harmful) + +* automatic removal of file lists from deleted peers, at restart (After double check that this does not alter exchange of file lists in any way) + +* set heartbeat values to intermediate value + +* added verification for file size computation (bug correction) + +* augmented the heartbeat parameters, to reduce the stress on connections. Seems to help a lot when the traffic is high. + +Changes for v0.5.0d + +Package improvements: + +* suppressed package dependency on gpg-agent + +Improvements: + +* implemented a free disk space checking method, with a warning when running low +* fixed proper sorting/updating of IP lists. +* only keep the most recent port for identical ips. +* don't start when the local address+port are already in use to avoid corrupting file lists, config files etc +* added failure tests for fwrite +* added tests against wrong ip 1.0.0.0 on MacOS + +Major bug corrections: + +* added missing locks in search requests into fimonitor.cc +* Suppressed the possibility for browsable only files to be searched by hash from turtle router. +* cleaned up some deadly code in rsdiscitems.cc, causing crashes +* improved the security of size determination for file lists, that caused a chain reaction ending in crash at clients. +* added missign lock in ftcontroller + +Minor bug corrections: + +* added a check to avoid (possibly rare) data races in data multiplex +* suppressed double click action for download in Shared File lists + + +Changes for v0.5.0c + +* Fixes two problems in the current group chat: + - the parser fails to embed two links in the same sentence + - the parser can potentially put smileys in the middle of tags + Solution: + Since the message is in HTML, it is parsed into a DOM tree, then that DOM tree + is traversed and only the text nodes are parsed (see HandleRichText.cpp for details). + Bonus fixes: + - missing std:: for endl (which was falling back to its Qt counterpart) + - commenting useless code in PeersDialog::smileyWidgetgroupchat() + - replacing int by size_t + - RetroShare.pro now queries gpgme-config for its include path +* fixed Memory leaks: + - getLocalInterfaces -> iptable = (MIB_IPADDRTABLE *) malloc(dwSize); + - main -> RshareSettings *_settings = new RshareSettings(); + - ExtAddrFinder::~ExtAddrFinder - use free for pointer allocated with malloc +* fixed RetroShare stopped responding during signing a key and asking for password. + - The QSingleShotTimer of ConfCertDialog wants to update the gui and stopped in PeerItem::updateItem. +* fixed chat bug that was truncating some messages, due to using a uint16_t to store a local size. Totally backward compatible. +* fixed crash with second open of HelpDialog solved +* implemented a short circuit to local cache transfers. + - This saves a large number of file descriptors, and improves reactivity of the software + +Changes for v0.5.0b + +* suppressed unused files +* added a checkpoint to file hashing, to save intermediate results every 10 GB +* corrected memory leak in p3disc heart-beat system. +* correct bug with selection with human readable delegate. +* fixed the sorting of SearchDialog by age and by size, by using proper delegates for displaying the numbers. +* Removed the SR_REALSIZE_COL column, that is no longer necessary. +* improved readability of cert generation dialog. Added tooltips, information, and wait cursor +* corrected bug in search: files with size > 2Gb would not be added to transfers +* corrected bug about persistence of default chunk strategy +* fix a gui bug +* The settings in the settings window are only loaded once. +* Saving the settings without changing the network settings doesn't shutdown the connections +* Forwarding a message keep the attached recommended files + - starting with ssl_id which has saved pword, and switching ids at start dialog + - secondary id may or may not have saved pword. +* added check for the result of fscanf +* fixed compatibility issue with dyndns patch +* Ported trunk commit 2780: Set the trust lvl to 3 when accepting a friend and the trust lvl is unknown. +* Removed some potentially harmful (deadlock) code. +* Put some printf into debugging #ifdef +* Bug fix: Checkbox for automatic share of the incoming directory doesn't correctly set with setDown, use setChecked +* ShareManager and RSettingsWin doesn't need to be created all the time +* RSettingsWin: Save the last active page for the current runtime +* ShareManager and DirectoryPage: Show changed shared directories direct after the change + +Changes for v0.5.0a + +* Bug fix: Checkbox for automatic share of the incoming directory doesn't correctly set with setDown, use setChecked +* ShareManager and RSettingsWin doesn't need to be created all the time +* RSettingsWin: Save the last active page for the current runtime +* ShareManager and DirectoryPage: Show changed shared directories direct after the change +* corrected handling of null strings in RsTlvBase::GetTlvString() +* suppressed uninitialized memory read +* added security check against malformed packets +* added a security check to avoid core dump when a bad p3discReply packet is received +* corrected other mismatched free/delete in avatar items +* corrected mismatched free/delete in avatar items. Might have caused random crashes. +* removed double definition of fingerprint +* Fixed deadlock when asking for GPG passwd with gpg callback during session. +* Added a method lockAllEvents()/unlockAllEvents() to remove timer updates in RsAutoUpdatePage +* Updated passwd message to be more user-friendly +* removed some warnings in authgpg.cc +* added commandline option '-U' to allow user to access different profile + - in the situation where autologin is enabled + - BUG found (or rather autologin induced it), if one asks to make friends to a + peer (in ConfCertDialog) 'within' a session that uses autologin it freezes +* add the internal counter mutex lock. Move the code of the rw mutec to the rsthreads.cc file +* fix a code bug +* add a read / write lock and refactor authgpg with it +* Fix a bug when adding a cert +* Fixed new message string +* added gpg initialization for autologin + - your friends are not authenticated if not +* Added support for Auto-login + - Using rc4 to store ssl pword on file for linux, for windows already using cryptprotect + - yes its not safe, but its the user's choice to keep pword or not + - consider using method closely hooked to linux kernel (another layer of obfuscation) + - windows i believe is stronger (because its proprietary/ heavily obfuscated) + - added checkbox in start dialog including warning (autologin not safe) + - added check box in gen setting to disable autologin on shutdown +* block the notify callback of authgpg when the main windows is launched + +Changes for v0.5.0 + +* corrected small bug in max search determination +* Fixed translations on StatusBar display. +* added a state message for examining files. +* suppressed bug in settings +* cleaned the code and debugged the icons +* suppressed notify callback in main thread, resulting in deadlock, and explicitely askes for queued message passing for notifyError +* bug fixed for deleting selected messages +* change the timings and add some randomness for tcp connections +* corrected one nasty bug due to missing return +* added security to fd management, corrected bug causing bad fseeks +* suppressed some uninitialized memory reads +* made the key font Courier New to allow fixed-size display (makes the key much more readable) +* suppressed uninitialized memory read in file transfer, also made the TransferDialog more secure +* reset only ComboBox when close all search results +* Fixed to display Dir Count in search +* fixed to display Certificate in CryptoPage userfriendly +* restored the courier new font, to allow the user to quickly vizualize errors in the keys (and to make the display less messy) +* fixed open file, removed file action menu (already handled by the system) +* fixed the update of message icon when there is a new message +* fixed: enabled translation for Hide/Expand Button in Messages +* cleaned some debug text, suppressed a few memory leaks +* suppressed some memory leaks due to bad use of QMenu +* fixed Folder Age with min_age +* Change the status bar network display +* add the ability to copy file details text + +Changes for v0.5.0 alpha 2 + +* fixed a bug in download queue when ticking inactive files. Added a checkbox for showing cache transfers. Cleaned the dialog cleaning method. +* suppresed bad lookup in _queue causing SIGV +* utf8 fix +* fixed RS link clipboard so that links can be imported/exported from both RS and the application clipboard. +* cleaned the config->Transfers tab, made the default chunk strategy combobox effective. +* fixed copy/paste of RS links in public and private chat +* cleaned the code for anchorClick() in private chat +* added return false for FileRequest of already have files +* suppressed sources when the file is complete, in TransfersDialog. +* added info and consistency for gpg sign and trust signification +* added proper close for file transfers. This drops down the number of FDs from 250 to ... 50 svn status +* added missing locks, that caused random crashes +* improve the recieving of bad gpg keys +* fixed RS link copy/paste from shared/search to transfers/forums/messages +* increase udp ttl +* fixed queue menu to work on multiple languages +* change ssl binary encryption to aes debug code +* change ssl binary encryption to aes +* lower connection attempt timings +* moved removal of sources off turtle mutex to avoid cross-lock. Added a closeFile() call when moving files out of the queue +* fixed to get work again Chinese language , and load now Qt translations for widgets +* bug correction: avoid reading deleted pointers by moving saveDone() after the next line +* added paste multiple links +* added Timestamps for forum message feeds to know the date for each Forum Message. +* cleaned the RS link code, factorized the parsing into a single class. +* fix a bug in the double file configuration loading +* Fixed config forward compatibility problem + - note to self: C++ binary file not same as C binary file +* fixed sharemanager closing +* fixed to enable translation suppor for Trustview strings +* added for Queue actions own icons +* clean up languages and corrected few languages +* added proper dynamic suppression of sources from chunkmap, and updated the gui +* suppressed bug in dynamic removal of sources. suppressed bug in string search. Suppressed some warnings. +* added to show bytes and formates size FileTranferInfoWidget +* suppressed debug msg +* Added proper dl queue behavior + - suppressed old DwlQueue class + - turned mDownloads into a list of pointers to allow easy cross-info update between queue and std::map of downloads + - added queue functionality for moving files top/bottom/up/down + - added the necessary functions in rsFiles +* reengineered the network dialog insert connect method +* small design change of confcertdialog +* restrain ip list exchange in an attempt for bug solving +* small update of connct mgr and ssl connection +* added Popularity view as icons to display for each channel +* fixed to display pasted plaintext retroshare link in public chat in html format to get click able. +* added Copy link as html format +* fixed to get click able the retroshare links in privat chat +* fixed only show a new message icon on tray when its a inbox message +* small change in ext address detection +* Added new 2-pass save method to configuration management + - essentially if any part of the file saving procedure fails, there should be config files whose signatures/hash match up +* set a item foreground color for Inbox when get a new message, set gridsize for listwidget to 18 +* disable the extract failed certificate +* make the gpg key list reading a little more error proof +* change the pointer offset cast +* added Download Time column to Downloads +* added to DetailsDialog Download Time label +* added formating the filesize's for FileTransferInfoWidget +* suppressed bug in file transfer while removing inactive chunks. +* added initialisation of gpgmeKeySelected. +* suppressed deadlock (mutex explicitely locked before thread exit) +* Fixed to get again gui resize able , search not allowed more to set gui to a minimum size. +* color adjustement for the network dialog +* cleaned some memory leak in search, added 2 checkboxes for F2F and friend lists, made the "include own files" work properly +* put the max result test at a more appropriate place in the code +* fixed display of uploads tunnels +* fixed trayicon tooltip +* added change trayicon when get a new message, added change trust icons when trust is changed +* added a spacer when counting Messages +* added to installer to install gpg4win +* change the color of peer display +* change the button at the end the the connect friend wizard dialog +* small fix on gencert dialog +* small fix xhen loading detail from a string cert +* change the gpg key list display +* add own ip addresses list to profile widget +* cleaned the code in fimonitor, modified the order of file hashing, and put a more explicit progress message while hashing. +* connect PrintButton when not use the menu +* disable the ssl cert config persistance +* changed add friend icon +* small bug correction in display of unknown hashes +* added a spinbox to limit the number of search results (too many results may hang the gui) +* add the tunnel config to server tab, and activate the tunnel on fresh configs +* reimplemented the tunnel handshake +* update implemention for new ssl encryption +* remove some exit(1) +* implementation of an SSL binary encryption +* enabled Run Email Program for all platforms +* moved the Buttons Make Friends,Deny Friend, Sig GPG Key to the Bottom of Trust Tab +* improved the icons and Buttons in Trust Tab +* use for color sources friends sources + anonymous sources +* added missing NetworkWide flag to download from recommendation +* added missing NetworkWide flag to download from recommendation +* corrected bug in MessageDialog: friendly size was could not be properly converted into a real file size. We should not use it. +* Properly close ssl connection when receiving error SYS_CALL. Bug solved +* Fixed Load and Save own status Message in MessengerWindow works now. +* suppressed unninitialisez memory reads +* added context menu action for Paste retroshare Link for Create Forum Message +* added smotth interpolation flag to image scaling +* added Paste retroshare link's from a Button in Create Forum Message, and fixed to not allow send blank Forum Messages +* improved display of turtle router info +* changed the default Blog Header stylesheet, and use now white Text Color +* include own files check option on search +* fixed Resume/Pause context menu actions to work properly in all Translations +* redesign Create Blog Msg Publisher with html Formating features and fixed textSize formating for Message Composer +* added to can use *.gif pictures now too for Avatars. +* added new French translation +* search result filtering +* fixed display issue in transfers (bad colors in crosses) +* improved display of tunnel info +* made gpg ids more consistent with the way gpg lists them +* added more detailed info about gpg ids in login and gen certificates dialogs +* fixed to get work properly Play and OpenFile when File Transfer is complete, Play action is only visible when its a media file. +* added additional info into FileTransferInfoWidget +* added actions for disable/enable Emoticons in Privat Chat and for Clear Chat History +* made complete files stay in the download list +* fixed bug in clink on link in group chat +* added action to GroupChats Button Menu for disable/enable Emoticon's +* filter after search, not before search +* fixed group chat download +* fixed the recommend system +* corrected compled completion and file progress issues +* security fix to xprogressbar display +* reengineered the transfer list display +* reduced cost of progress bar display +* fixed a bug on MessengerWindow context menu +* messenger-window thumbnail photo update on change +* set TextAlignment for sources to AlignRight +* added to show files sources count in form of friend source/ total source +* fixed stylesheets for Search LineEdit's frame +* put a safety check against sockfd==-1 +* limited the search to > 3 chars +* fixed remove a bug in peersdialog +* added clear Filter Button for Messages Filter +* change the profile widget to replave spinbox by lineedit +* add some validators for gpg key gen +* fixed setFocus for search LineEdit when clearing it. +* improved turtle router display +* added put the tunnel info as a new tab in the transfer page. +* added hide reset button when search field is empty +* fixed to get work again to hide/show the Messages Filelist +* added a ending 0 to form a proper string in gpg cert export +* fixed the left side friends list for Message Composer to get resizeable +* fixed display issues: always -> all and void string -> unknown for turtle hashes +* fixed Messages items to not editable +* corrected bug in file completion +* added Messages Filter for Attachments,Subject,From,Date, +* rewrite MessagesDialog to use QTreeView with QStandardItemModel +* added change search results text color when it has more sources +* fixed stylesheets and enable OpenExternalLinks on InfoDialog +* change peericon when indicator changed +* added Save Cert Button to ConnectFriend Wizard +* added more info for Network Wide/Browsable to the Description Label in Share Manager +* added icon for gpg key checkbox +* improved design of profile generation + +Changes for v0.5.0 alpha 1 + +* suppressed uninitialized memory read +* corrected display bug in transfers +* suppressed bug in creation of cache directories +* suppressed uninitialized memory due to empty cache file +* corrected invalid memory read due to bad deletion method in std::map +* suppressed some uninitialised memory reads +* add error info when gpg password is wrong +* add gpg password static store when gpg password callback is called +* added for indicator change Folder icons +* solve a bug when the tmpcfg directory already exists under windows +* added security check +* suppressed possible SIGSEGV due to null information in certificate +* improved display of turtle routing info, corrected some minor compilation issues +* made the age indicator functional, by recursively changing color of directory/files +* use CreatForumMsg when replying from News Feed +* re implement chat parsing for urls. External web browser call might not work on some systems +* fixed to show for Folders Type Folder, and set root is decorated to not download a dir when want expand it. +* fix a bug in quick start wizard +* added some security checks to turtle router +* add new info to infodialog +* redesign cert generation +* set private key trust to full when the validity was unknown +* solve a bug with gpg private key validity unknown +* fix a bug wich stops multiple connection against the same peer +* set a default Avatar when Friend has no Avatar for Privat Chat. +* corrected issue in display of download/upload progress +* Msg forums are now signed by ssl certs +* corrected bug about display/selection of anonymous files +* add gpg authentication everytime we got an ssl auth error +* Added to send own Shared File as link to Public Chat +* Added attaching files to Public Chat via Button/Drag and Drop +* in message composer, connected peers are colored in blue +* factorized and cleaned the common code between fistore.cc and fimonitor.cc, + - improved the stability of FileIndex, + - improved the display in RemoteDirModel +* store file certs as .rsc extension* +* changed the Date Format to dd.MM.yyyy for Messages +* update start wizard, change gui settings directory into ssl profile directory (RestroShare.conf) +* added NETWORK_WIDE flag to remote dir model download +* added file priority strategy based on which files are requested first. This provides: + - equal file speed for files with equal (source,priority) + - effective priority speed for file of same source but different priority +* removed state variable load/save from turtle, as it's not needed anymore (FileRequest re-opens tunnels as needed) +* manage availability per peer instead of per file type: direct peer ids always assume file availability, while turtle tunnels don't +* added Chunk size and Number of Chunks to DetailsDialog +* solve a bug with gpg signature summary +* add input validator for gpg key gen +* improved peer name info in cachestrapper, gence improving dir names in file lists +* added Copy and Send retroshare links for Search +* reduce the reading access to gpgme +* added regular cleaning of inactive chunks and slices, so that they can be treated by a different peer +* fixed don't send an empty gpg key in p3disc +* Added Attach File feature for Messages +* added RS_FILE_HINTS_NETWORK_WIDE for SubFileItem +* added a icon for SSL item when connected +* add the possibility to create a gpg key for new profile +* add a check button to hide unconnected friends +* update display of the profilewidget tab in peersdialog +* don't send gpg key when all the ssl childs are on no disc or when we got no ssl child of it +* ask disc info when adding a new friend +* removing of own gpg key as friend when not necessary +* Added a new CreateChannelMsg Dialog as replacement for GeneralMessage for Channels. +* add key generation at startup if no gpg key found +* Added Timestamp for each Channel Message +* fixed up file attachement to forum msgs +* fixed startup password handling, so that it wont ask for passwd again, hence preventing deadlocks when the gui is running +* added to Send RetroShare link as html format for Messages +* added to can download from Messages when clicked on link. +* added when start connection attempt then change icon on location. +* added functionnality to complain when a download is initiated over a file already in download, or in the HD +* fixed downloading of links attached to forums +* adding a deleted ssl friends persistence in p3disc to avoid getting back a friend we just deleted +* fix a bug when removing friends +* Added attaching files feature for Forums. +* add a ssl check that the peer isn't already connected +* change mutex lock in authgpg to avoid deadlock +* send just connected peer info to all others +* implementation of p3disc with new gpg key management +* implement the remove friend for gpg key, and improve the tranfer of ip address from a dummy peer to a normal peer +* change the design of the connect friends wizard +* change the cert to gpg + some ssl details +* show correct location when adding an sl cert +* solve a bug in the load list af connect mgr +* add persistence of accepted gpg key to connect with +* remove the ssl cert storage. Big rewrite of ssl cert and friend management +* allow ssl connection with a new cert, ad a friend when happening +* implement the trust settings in the gui +* make peer detail gui work for the gpg and the ssl id +* make peer details work for GPG key in the network view gui +* remove the store of the pgp password +* implemented the sign, trust and validitty functionnality in authGPG. Fix a singleton bug for authGPG and authSSL +* fix a bug in rsinit with pgp name +* added flags to file request: RS_FILE_HINTS_ASSUME_AVAILABILITY to not wait/ask for chunk maps. + - Used for cache transfer and also whenever the turtle traffic is not involved, such as chat file exchange, + - and RS_FILE_HINTS_NETWORK_WIDE to force using turtle routing for traffic. +* Implemented chunk-based file transfer from partial sources. This in particular means: + - exchange of chunk availability maps from different peers + - correct handling of what is available to which source before asking the data + - correct display of chunks in the progress bars + - generalised the use of compressed chunk maps + - removed the size parameters from the hash search functions +* added Reply to Author feature for each Forum Message +* added Quick Start Wizard +* added DetailsDialog for Transfers +* added allowed Messages Information for each Forum if its a Anonymous or Authenticated Forum +* added Smiley Support when creating new Forum Message +* fix a bug in peer display +* added when no Thread selected clear Forum Name ,Post Text and Thread Title +* added when switched Thread then clear last Post Text and Thread Title +* added a generic RsItem to the turtle router and the methods to route it. This makes the code much more elegant. +* suppressed a cross mutex lock bug that happened rarely while digging tunnels +* changed FileDetails in ftServer so that it's now possiblt to search for hashes of files being downloaded +* improved the search code in ftdatamultiplex +* added some comments to the turtle code +* added Popularity/Date to Forum Details +* Added Forum Details Dialog +* show Popularity as ToolTip, removed not usefull items which stretches the Forums list +* added use for Authd forum a different forum icon +* Added setFocus feature, when creating new Thread or Reply Message change the Focus +* suspending the auth code in p3distrib to allow forum messages to display. +* implemented a visualisation for currently handled chunks, availability maps, and transfer info +* implemented transfer protocol for chunk availability maps between peers (not enabled yet though) +* don't do a tunnell connect attempt when already connected through a tunnel +* use siglen -1 for both gpg2 and gpg1 verify signature +* Add heartbeat (an empty packet, wich is 100 bytes long) in p3disc every 4 seconds +* start listener not immediately after net reset to avoid connection flickering. +* stop ssl listening when already connected +* stop sending data when ssl read returns 0 +* The external ip address is now set when a peer is connected if there is no upnp or extadrfinder +* change packet version for rsdisc +* fix a bug with ip serialization when ip or port is 0 +* add serializiont of own ipaddress list in rsdiscitem +* send own ip address list with p3disc +* change the way we handle our own address when recieving a disc item +* fix a bug for own disc item and address list +* fix a bug when connected through a tunnel +* add a break in case ipAddressList don't deserialize correctly +* add current local and external address to ip list +* fix a bug in the udp timeout +* DHT disabled, remove DHT from the gui +* perform a net reset when network config is changed +* change the address selection of udp connection +* Add the tunneling connection. +* Implemented load/save of chunk maps for current downloads. +* added a ChunkMap class responsible for allocating new chunks to be downloaded, according to + - a given chunk strategy + - the availablility map of each source + - Integrated this into ftFileCreator + - added gui menu in file transfer+right click to change the chunk strategy: streaming vs. random +* Added consistent display of chunk map +* Modified and renamed the taskGraphPainterWidget to display info about currently selected file transfers. +* Added a parent page widget (class RsAutoUpdatePage) to handle auto-update. +* check to see a peer is connected before doing a net reset. +* remove upnp mapping before adding new ones +* fix a bug when removing 1 from a zero siglen +* simplified and improve ip list for connect attempt. Show the ip in the gui +* add port filtering if 0 for address list +* add address list to gui +* add the ip list to the connect attemps +* implemented the ipAddressList methods +* change to only one ip list instead of one local and one remote +* added the serializing of ip adress list, and the process to ad ip to the list when a connection is made to a peer +* fix a bug when closing RS for upnp +* update of network dialog when peer address was manualy changed. +* display the best available ip for peers in the gui, instead of 0.0.0.0. This does only affect the gui, not the way ips are trusted and propagated. +* setup reconnexion time to 5 seconds after reset +* added reset of current connexions and force-reconnect when network configuration changes. +* added dynamic local and external ip reconfiguration. I still need to reset connexions when changing ips. +* made the passwd dialog call Qt-independent (thanks to notifyBase) +* added gpgme and gpg error includes for win32 +* added a QTDialog for the gpg key passphrase input +* fix uninitialized pointer fir libupnp +* improving safe upnp shutdown +* rewrite connection manager +* improved stun check +* improve time for initialisation of upnp +* store exaddr from upnp to stun +* improved stun failure resistance +* added network reset ehancement for stun and udp +* added reset net status when shutingdown +* added loopback network interface compatibility +* added new method for external upnp address +* change back the engine setting. Now it should work with gpg1 and gpg2 +* fix the length of the encrypting ssl passphrase +* remove the pgp/password fields for start dialog +* set gpg2 engine for gpgme +* change ssl password encryption to non symmetric +* added new/old age indicator for shared files +* added functionality to edit your own Personal message on Label click +* suppressed sigsegv when deleting an unallocated object +* fixed exchange of custom strings. +* fixed the update of avatars in the various chat dialogs +* added a "peer is typing" function to the group chat. +* fixed up avatar exchange between peers +* Added and ToolTip's For Avatar Button +* added StatusMessage Dialog +* added functionality to store own status to chat.cfg and to gui settings +* added timers for update own status/avatar faster +* edited ProfileWidget to open from there the StatusMessage Dialog +* added code for storing and sending a custom status string (for e.g. saying "I'm not here now") in p3ChatService +* added code for sending group chat status messages "peer is typing". +* Redesign MessageToaster +* bugfix with rehashing already shared files +* Added ProfileWidget as Tab to show own Profile Details +* make possible to download an entire found directory from search dialog +* Added Age column for Search Results +* added For Friends Context Menu a Title Widget +* fixed the file size issue with turtle search +* fixed keeps transfers sorted when redisplay them +* replace double with one clik when browsing channels +* few changes added to channel gui - list of groups and channels was replaced with a tree view +* correct speed for non active downloads +* GUI mods for new Forum sorting method. (Last Post) +* added extra forum sorting method: Last Post. +* Integrated turtle download to all kind of user-requested downloads +* fixed core dump issue where AuthSSL::VerifySignBin() is called with NULL parameters. Still, this should not happen. +* added Enable disable minimize to Tray feature when closing RetroShare +* correct wrong the setting of the friend ip address when adding a contact +* add debug info when ip address is set to an unknown peer +* restored accounting for LAN transfer rates. +* win32 fix for large file support +* added to Friends own Avatar and own nick labels +* Teaked the TrustView and NetworkView so that they only update when visible. Doing so, the CPU overload is only present when strictly needed. +* downloading directories from search dialog +* added support for searching and display directories +* add random ssl password generation +* hide ssl password when logging in +* added encrypt and decrypt ssl password +* add links to cloud from shared files dialog +* improved turtle router console +* Integrated the turtle search and download to the gui. Now the search handles both friend and turtle searching. +* added a console in config->server->F2F routing to be able to visualize turtle routing statistics +* download recommended files from inside links cloud dialog +* corrected potentially harmful uninitialized memory reads +* scroll to previously selected item(s) at next redisplay +* fixed some mutex bugs and some pointer access bugs in the FileIndexStore +* ensured early creation of cache directories to avoid "Cannot copy file" bug +* added a pointer controller to findex to avoid RemoteDirModel to incidentally request for deleted pointers. +* suppressed auto-collapse of directories when updated. +* Share Flags: + - now, only files with the NETWORK_WIDE flag are searchable by turtle hopping. +* added persistence to download queue +* Share Flags: + - 1st attempt at displaying share properties in the SharedFlagsDialog. + - added share flags in DirDetails structure in place of Rank, that is not used anymore. +* Share Flags: + - own directory browsing is now done through FileIndexMonitor. This allows: + - to browse shared directories independently of their flags + - to update files as they get hashed +* Share Flags: + - now only the directories with flag "browsable" on are dispatched to friends + - when switching flags, directories are re-sent to friends +* added checkbox for Preferences to can disable the Quit MessageBox +* Changes to startup / login function to handle multiple accounts. +* Switched on OpenPGP version by default +* Major change to the way certificates are stored now defaults to ~/.retroshare/SSLID/ +* Added to supports Multiple Accounts on same computer. +* Changend mods to use miniupnpc v1.3 +* Fixed Bug to use WriteFile instead of write under windows with gpgme. +* Redesign of dwl queue - dwls will be enqueued and picked from there. +* Changed to display the dwl queue in the transfers dialog +* Added implementation for priority download queue +* Added switching colors for different uploads +* Changend Quit RetroShare MessageBox with "Yes" and not more with "OK" +* Added use real name instead hash name for partials for preview +* Fixed Bug to make pgp friend sharing work. +* Fixes to the PGP Network View. +* Fixed corrected the connexion + one-way bug +* Suppressed bug in RsTlvBinData that could return true even when the serialisation fails +* Redesign SharedFiles, with splitted view for Remote and Local Dirs +* Added show Friends RS version on peer details panel +* Added download of whole directory from gui +* Added Add Friend and Export Cert to Menu Button +* Added Export Cert to Network Dialog Context menu +* Added a Security Page for Options to View, Copy and Export own Public Key. +* Added checkbox for group chat in Notify Options. +* Added Copy Cert to Clipboard functionality for ConnectFriendWizard. +* Added alert chat window when a new message was arrived +* Added systray notification for group chat +* Fixed proper update of shared list when list is modiffied from a different place +* Changend default name for finished downloads directory was changed from Downloads to Incoming +* Added share of incoming directory by default +* Added storing Network Tab Position +* Added for Check files button to change text when checking files +* Change on the Timers of Network Menu that weren't wroking properlly +* Fixed the context menu position of the Netwok Log +* Fixed Bug - right click on local shared list won't abort the app +* Fixed Bug for gpg connections. +* Added open file/folder actions in local sharedfiles dialog +* Added open or preview downloading files with a suitable application +* Changend reorder transfer context menu +* Added pause, resume and open folder actions added in context menu for Downloads +* Added exchange of what version of retroshare our friends are using. +* Restored backward compatibility in p3disc. + +Changes for v0.4.13c + +* Changed the order of upnp/stun and extaddrFinder to limit wrong analysis of firewalled situation +* Bug fix about not acconting identical tunnels appropriately +* Added missing continue which caused sigsegv +* Added removal of turtle handling when canceling/ending a file transfer. +* Added function for properly removing handled file hashes (turtle) +* Made turtle tunnel ids asymetric +* Cleaned up the documentation in p3turtle.h +* Update tunnel time stamp only *on the way back* to avoid unsuccessful requests to update a timestamp. +* Implemented persistence of which hashes are to be handled. +* Fixed bug when storing incoming and partials directory +* Added suppressed file download memory leak +* Added new computing for download and upload rate. No more indiv rate settings +* Added turtle tunnel management +* Added delete autostart functionality when uninstall RetroShare on windows +* Added functionality when collapse tree change treeicon +* Added status icon in the name field of download peers +* Added view functionality to can set root decorated or not decorated for Downloads list. +* Added integration of filetype icons on downloading files +* First commit for the turtle download. It works without perturbating RS traffic, but still needs some (internal) smoothing +* switched pgp password to encrypted entry +* corrected NetworkDialog / NetworkView to use validLvl instead of trustLvl. +* Major bugfixes to get PGP authentication finished. +* p3disc now exchanges "Issuer" (pgp) certificates as well. +* additional types for rsdiscitems.h +* Bug Fix for NULL packet in p3service.cc +* Allow unauthed SSL certificates to be added in AuthSSL - otherwise cant add new friends! +* Only save authed SSL certificates. +* Fixed ref/unref of PGP keys in AuthGPG +* Added Mutex protection to AuthGPG +* Added PGP reloading when key is imported, or signed. +* Fixed PGP key signing. +* Added Additional field validLvl to RsPeerDetails. +* Corrected bug in connectFriendWizard gui + +Changes for v0.4.13b + +* Minor changes required to get the gui working with PGP, +* Improved NetworkView to show signatures, and friends. +* Addition of openpgp support! +* Added switch trayicon if online count is 0 or bigger +* Added for FileTransfer: line is click-able, when collapsed it displays all download peers +* Added for FileTransfer: sources column shows number of peers as online (offline) +* Added for FileTransfer: name column for root/peer shows filename/peername +* Added proper notification for network list update. +* Added a make friend with friends of my friends option in the connection wizard. +* Added Copy/Paste/Send retroshare//: file urls/links +* Restored file recommendation feature. Improved it a little. +* Corrected upload/download status in upload transfers +* Disabled auto-login for non windows systems. +* Suppressed Settings/ directory, as it_s not used at all +* Suppressed unused smplayer action from left bar +* set tooltip for OK Button +* Added smooth avatar scaling +* Setup connection so that deny friend in peers dialog updates the network view. +* Changed popup fchat focus for typingnotification +* Fixed don't send the extrafil link when SubFileItem is cancel (ERROR mode). Improve chat url parsing. +* Fixed set the SubFileItem in error mode when cancelling from the GUI +* Added a missing return after deletion of membio in case of fail read (error handling) +* Suppressed double item deletion that happens rarely (error handling case) +* Added More alternative colours to NetworkView. +* Added tooltip for add file button +* Fixed the history problem with SearchDialog +* Refuse directory drop for extrafile +* Added the drag'n drop file to popup chat, still a bug when adding a directory +* Enabled double click download feature for SearchDialog +* Enabled reseting keywords in SearchDialog +* Enabled translation for STATUS strings +* Fixed NetworkView lets get refresh the graph at rs start too +* Fixed startMinized now it works +* Enabled for the MessageBox'es translations support + +Changes for v0.4.13a + +* Merged peer detail dialogs from network and friends tab +* Enabled multiple selections via mouse,keyboard,CTRL + A ... +* Added feature to can delete files via Qt::Key_Delete +* Added messagebox when cancel files from Transfers +* Modified libretroshare to compile on Cygwin / MinGW. +* Removed exceptions from serialiser (had troubles previously on win32). +* Modified code in startup (enable CRYPTO structure) and rsdir. +* Remove the downloads item for file index cache transfer +* Set fileIndex cache transfer timeout to 300sec +* Corrected setLogInfo core dump state. +* Added add the ip adress to the cert text for friend add wizard +* Changed Bad Packet message to log in network dialog +* Added "peer is typing" functionality to private chat. +* Moved Network Status Tab from Preferences to NetworkDialog +* Fixed the total Transfer rate is lower than the individual rate. +* Added grey user icon for statusbar when no Online Friends avaible else blue +* Added NAT status to statusbar +* Added DHT status to statusbar +* Added Network Status for Log Tab too +* Enabled toolbar moveable to all toolbar areas. +* Added view button for Network Tabs + +Changes for v0.4.12d + +* Added partially completed authssl.cc, as we move towards openpgp authentication. +* Tweaks, and removed debug statements. +* Added missing files (extaddrfinder & p3turtle) to Makefiles. +* Turtle tunnel management. In progress. +* win32 compilation fix +* Corrected potential mutex lock problem +* Implemented turtle tunneling. +* Fixed the bug with copypasting certifcates. +* Added new icon for Notify +* Set correct icon for Deny Friend Context Menu +* Added qmovie for InDirectoryCheck +* Fixed libretroshare.pro for win32 compile +* Polished drop down menus in the network tab +* Added Feature: user can set commands fo opening shared files with some external applications. First revision. +* Added automatic slicing of search response packets so as to cope with streaming packet size requirements. +* Added NULL gard in dhtPublish() +* Added a checkbox to control the use of external servers for ip determination. +* put back Network on the left +* NetworkDialog: - set the info in columns about trust to be more explicit +* NetworkDialog: - changed dark green into light green to comply with colors in the trust matrix (it's also more readable in light green) +* NetworkDialog: - corrected trust strings that appeared in the Last Contact column +* Changed "generate certificate" in connect friends wizard into "export my certificate..." which is more appropriate +* Added missing file entry +* Corrected compilation pb + pushed news feed out of release version + put back network in left most place. +* Added server-based ip determination as a fallback to existing methods. Forced Dht publishing as soon as an external ip is known +* Replaced doquit with normal QMessageBox +* Fixed compilation fix for cygwin +* Corrected the 127.0.0.1 persistency bug +* Fixed file rename by using a common rsDirUtil function +* Added Wizard for adding friends + +Changes for v0.4.12c + +For the sake of increased stability, internal file formats have slightly +changed. As a result, prople using the new version will have to re-trust +their friends. This can be done efficiently using the drop down menu in +the network view. + +* Fixed win32 compatibility +* Suppressed #ifdef TURTLE_HOPPING from libretroshare, as it s not anymore needed. +* Added a direct make friend button in the drop down list of network dialog +* Suppressed misleading ssl error. +* Secured the output of .cfg files and cache files. Now closing RS or serializing errors while saving these files cannot corrupt them anymore. +* Added a callback to notify when clicking on make friend button +* Made own avatar persistent. Next task will be to make friends avatars persistent too +* Fixed file moving between different file systems, which forced people to have their Incoming directory on the same file system than the Partials directory +* Invitation text contains only certificate information; +* Buttons for saving/opening pqi-files become more noticeable. +* Removed "Email" button from invite dialog. +* Update, during the GUI for invitation changes +* Turtle search now connected to the gui. Next move: digg turtle tunnels for fast download. +* Turtle dev. Worked on serialisation, mainly, and connexion to gui. +* Finished turtle router.Next task: turtle serializer +* Fixed bug: the MainWindow object wasn't deleted. +* Added history support in group chat; almost stable; +* Suppressed uninitialized memory read +* Fixed the ssl connexion problem +* Added another anti-lag strategy in pqissl.cc. This is to avoid connexion problems +* Started turtle hopping implementation. +* Added a rsicontrol global variable for compatibility with new notification method +* Added a workarround for the packet sending problem. +* Improved the gui to increase responsiveness (e.g. forum display, network discovery info, friends, msg deletion and selection) +* Improved the notification model so that it uses Qt signals to avoid core dumps, +* Update Wiki Link in Help Dialog +* Fixed win32 compilation compatibility +* Suppressed some debuggign output. +* Fixed a bug with wrong packet size. +* Set Refresh Rate for down/up speed on statusbar to 1000 +* Added Uptime and Since to Statistics + +Changes for v0.4.12b + +* Suppressed an initialized memory read +* Changed PreMods() and postMods() functions into signals in notifyqt +* Added functionality for Bandwidth Graph +* Suppressed bug when creating new certificate +* Added Reply to all Button for Messages +* Changed pointer cast from int to void +* Changed retroshare invite so that it does not contain signatures anymore. +* Small fix to upload transfer rates +* Plugin system: plugin management features added (loading and unloading) +* Fixed bugs in upload speed computation +* Added info for upload peers and rate in Transfer tab +* Enabled translations for QString's in RemoteDirModel +* Fixed Bug: incorrect creation of the plugin +* Fixed Launch Email Bug +* Fixed Save cert to File + +Changes for v0.4.12a + +* Implemented plugin system: first demo version +* Removed streching for Remote Directories +* Added icon Label for Messages Toaster +* Set userfriendly Column names for Remote/local Directories to Friends Directories and My Directories +* Removed not needed path show in Rank +* Set Qt::IgnoreAspectRatio for pictures +* Added for MessengerWindow the new getAvatar and updateAvatar function +* Added protocol for Avatar exchange in private chat. +* Redesign SharedFiles dialog with Tabs +* Set Font Size for MainWindow ToolBar to 9 +* Corrected two nasty bugs in file transfer which caused random core dumps (at least on ubuntu 32 and 64 bits) +* Fixed font formating MAC OS X releated +* Set colors for Online, Friends, Network and set First Tab of Peer Details to first +* Set for Online Toaster Peer Online Bold and set TextColor +* Fixed directory problem wirh emoticons +* Added darkBlue TextColor for Connected Friend, Set TextColor Bold +* Put emoticon images and .acs file into qrc image file +* Suppressed line with pouty.png which caused a bug by altering actual html code. +* Added a layout to hashing info widget to get it left-aligned +* Regression of ft/ftcontroler.{h,cc} to svn=932 because the 933 commit (download queue) causes a large scope bug. +* Added to remove when deinstalling RetroShare to delete from APPDATA cache,Partials folder, *.cfg,*.log and *.conf files +* Added a "Trusts me" text field to the peer details dialog +* Replaced toText in MessagesDialog QTextEdit with QTextBrowser to get use a scrollbar +* Set context menu icon for Connect To Friend +* Fixed OnlineToaster's Picture Label Layout +* Set for Make Friend a Header Image and Text +* Added a display for file hashing activity using notifyQt class +* Corrected a bug in openDHT for 64 bits systems +* Added a Menu Entry for KDE/Gnome/XFCe +* Updated Changelog for .deb Packages +* Fixed time out unused uploads +* Removed march=i686 commandline options, causes problems while 64Bit compiling. +* Fixed error: UINT_MAX was not declared in this scope +* Added a Doxygen configuration file in order to help me sort out libretroshare... +* Redesign Login Dialog +* Redesign Online Toaster +* Switched to use autostart,it will be bether then Run with Registry +* Added for Messenger Window Share Manager Button +* Added for systray contextmenu Open Messages +* Set for MessengerWindow to use RWindow now +* Set for the Avatar Button a Background image +* Set for Avatar Pictures to use IgnoreAspectRatio +* Added QMessagesBox feature for the ShareManager's Add/Remove +* Fixed DirectoriesDialogs's Add Folder method. +* Set ToolTips for The DirectoriesDialogs's Buttons +* Added a callback in MainWindow.cpp to display info about hashed files. +* Added a callback to fimonitor to be able to keep track of file hashing +* Added svn version number in build script +* Added basic set avatar picture for MessengerWindow and Privat Chat +* Added second tab in Peer Details for Trust Settings +* Added Last Contact info to Peer Details +* Added doubleclick download feature +* Update Preferences and Settings forms +* Added context menu for Share Manager to can remove a Shared Directory +* Update RemoteDirModel's extension's +* Added tool tip and info to peer that trust you, in NetworkDialog +* small improvement in display of 3rd party trust info +* Added the infrastructure for propagating trust info through third parties +* Added to clean up completed cache files automatically +* Added to display peer names in transfers dialog +* Added two hidden columns in searchresultTableWidget to store the real size and srcId hash +* Added for Partials Directory to Directories +* Added New Share Manager + +Changes for v0.4.11d + +* Bugfix for launching desktop support. +* Small fix to universal script and some extra debugging. +* switched off some debugging. +* fixed tickrate slow down (when no activity) +* added extra flags to interface. +* Added NewsFeed / Popup / Chat Configuration options. +* Gui modifications to support authenticated forums. +* Added Authenticated Forums. +* add Sign / Verify functions to authxpgp +* sign/verify messages, and control flags for p3distrib/p3forums. +* add authmgr to p3distrib etc. +* added AUTH flags to rsforums interface. +* implement function for clearCompleted on filetransfer panel +* added display for author of forum posts +* suppressed uninitialized memory read. +* remove temporary file when cancel file transfer +* Bugfixes for correct Channels display. +* Corrected search in ftserver. +* Updated avail in controller FileDetails. +* Fixed Channel: SubFileItem display and play. +* added openFile function to MainWindow. (uses QtDesktopServices) +* disabled PlayAll in ChanMsgItem (as we can't do this). +* enabled play() once files downloaded. + +Changes for v0.4.11c + +* suppressed uninitialized memory read. +* remove temporary file when cancel file transfer +* Bugfixes for correct Channels display. +* Corrected search in ftserver. +* Updated avail in controller FileDetails. +* Fixed Channel: SubFileItem display and play. +* added openFile function to MainWindow. (uses QtDesktopServices) +* disabled PlayAll in ChanMsgItem (as we can't do this). +* enabled play() once files downloaded. +* tested play audio/video files on MacOSX +* Fixed Add Friend and Invite Frieds Dialogs +* Set minimum size for Channels frame +* Set minimum size for Friends TreeWidget +* add code for cancen file transfer +* Tweaked tabs and order. +* Added NewsFeed. +* Added Template functions for ssl+xpgp code. +* changed trust table name into trust matrix +* Tuned the matrix to show sub-networks +* Added a function to not allow to create a Forum/Channel without a Name. +* Fixed sorting in Friends +* disabled auto scroll for Friends Widgett +* added retroshare own logo for Network icon +* Fixed layouts/margins/spacings of the Create Forum Message Dialog +* Fixed Create Forum Message Dialog +* Fixed some Displaying isues for statusbar +* Enabled save() function in SubFileItems. +* Improved Channel Menu Item: added Icon and popularity. +* Reduced most of the margins in Channel Feed. +* updated libretroshare interface files. +* Added Function to move an 'extraFile' to another location.This will be used to retrieve channel files. +* set correct WindowsTitle for Create Channel +* Added Forward Message Button with Forward feature +* set for Reply Message/Forward Message correct WindowTitle from Message Title +* Added for Forward Message insertForwardPastedText() function to add Forwarded Message in a
    +* suppressed double mutex lock +* added files gpgauthmgr.cc and gpgauthmgr.h this provides the new GPG implementation +* added API to store all GPG keys in a map +* added APIs to get GPG certificate IDs +* added APIs to get Details from the Certificates +* set Text Alignments for some columns to Center +* missing file for defining sleep() etc under windows. +* fixed SharedFiles columns + +Changes for v0.4.11b + +* Bugfixes for 'sleep' issues under windows. +* Extra debugging for transfer module. +* Fixed channel directory creation. (extra 'break' statement) +* Fixed very slow transfers on Windows platform (uninitialised variable) +* Added Mutex protection to the core comms (pqihandler + pqipersongrp). +* Added a Mutex to the ServiceServer. +* Fixed, transfer start when subscribing to channel. +* Cleaned up p3distrib callbacks. +* Added holdQueue for transfer startup in controller. +* Fixed partial resume. +* Updated Mac script to only build library. +* Fixed compatibility bug in file transfer... +* Can now communicate between V0.4.9b and V0.4.11+ +* Improvements to the file transfer algorithm. +* Increased max individual file speed to 1MB/s +* Bugfixes in CreateForumMsg +* Added auto update feature to the trust matrix +* Implemented a big trust table where people can see who trusts who, and who is trusted by who. +* Added Configurations to new file transfer. +* Enabled config in p3file-startup.cc +* Enabled resumeTransfers +* Added new RsFileConfigItem to serialiser. +* Extended ftFiMonitor to use Configuration. +* Bug fix to add/remove Shared Dirs. +* Increased Channel/forum periods to 3/12 months. +* Create channels directory correctly. +* Added File Transfers to Config List. +* Connected statusChange() monitor callback. +* Fixed file sources in transfermodule. +* Fixed up transfer restarts / sleeps. +* Enabled opening files read only. +* More bugfixes for file transfer. +* Added File Transfer / ExtraList to channels. +* Fixed mutex deadlock. +* Added slow transfer for background tf. +* Added checks to FileRequest to accumulate peers. +* Added ExtraList callback +* Show Date in Network Tab using QT functions. +* Added multiple selection to the msgWidget QTreeView and setup context menu in accordance +* Added Delete key function to easily delete messages +* Enabled (and implemented) response to message +* Enabled for Uploads progess xprogressbar +* Added for Files Treeview File Typ icons +* Added for Files Treeview Folder icons +* Added Help System Dialog + + +Changes for V0.4.10b +* Cleaned up Mac Fonts +* Improvements to ft - but still in development. +* Various GUI tweaks. + +Changes for V0.4.10a +* BUGFIX for multiple reconnect attempts. +* Addition of new NewsFeed System +* Addition of Basic Calendar Interface (Unfinished) +* Addition of Forums / Channels (Demo) +* Improvements to Blog System (Unfinished) +* Partial Fixes for GCC4.4 compilation. + +Changes for V0.4.09b +* Tweaked Status Bar. +* Added Icons and Sorting to Links Cloud +* Updated default chat html/css +* Fixed Chat from Messenger Window. Changes for V0.4.09a (STANDARD RELEASE) +* BUGFIX for Determining External Address. +* Fixed AutoLogin. +* Fixed Toaster. +* Added Status Bar functionality (data rates, peers online) +* Fixed Transfer Display (data rates, file name, peer name) Changes for V0.4.08a +* Addition of Chat Styles. +* Improved Link Cloud Rankings + Bugfixes. +* Moved Link Cloud to MainWindow. Changes for V0.4.07b +* Full Mutex protection for ConnectionMgr +* Context Menus for Link Cloud +* Share Anonymously in Link Cloud. +* Beginnings of qBlog and Status added. Changes for V0.4.07a +* New implementation for Link Cloud. +* dummy Forum system. +* Added NonRelease features back in Changes for V0.4.06d +* BUGFIX: mutex not being released if UPNP unavailable. + +Changes for V0.4.06c +* Fixed Upnp Issues. +* Various GUI/stylesheet tweaks Changes for V0.4.06b +* Added Fonts + Bold/Italic to Group Chat. +* Fixed Color/Font issues for Chats +* Fixed Server and Peer Config windows. +* Enabled saving of data rate limits. +* Fixed Lost certificates issue(!) +* Tweaked Tick rate parameters. +* Improved Chat Delays (under a second now) + +Changes for V0.4.06a +* Reduced CPU requirements by removing some debug. +* Fixed Memory Leaks (serialiser + file transfer) +* Fixed Application Quit when window is closed. +* Fixed Unread Msgs bug. +* Reinstated variable Tick rate (reduces CPU load). +* Added "Stop Retroshare" message to installer. Changes for V0.4.05a +* HTML Chat and Messages. +* emoticons, bold, italic, fonts, colors for chat +* save, print, pdf functions for messages. +* New Side Toolbar. +* Switched Link Cloud to share Friends Links. +* BUGFIX: Added Emergency Dir if existing Incoming fails. +* BUGFIX: Added notify for connection to RS V0.3.X. +* Fixed Online/Offline Message Forwarding. +* Added Check Files, and Icon to indicate Hashing State. +* Added functions to Transfers + LocalSharedDirs. +* Included MPlayer in release. * reenabled skins. +* new Multi-Language Installer. + +Changes for V0.4.04a +* Fixed UPnP on Windows platform. +* added TIMEOUTS for TCP connections (5 secs) +* GUI display of connection type (UDP/TCP) +* Increased default data rates (100/500 kb/s) +* Removed Default bootstrap Ids. Changes for V0.4.03c +* NEW: HTML Messaging! +* NEW: Msg Composing Window. +* NEW: Contacts docking window. + +Changes for V0.4.03b +* BUGFIX: EXT PORT notification. +* BUGFIX: Save Config after Signature of Peer. +* BUGFIX: Config MetaFile + Sig saved in correct directory. +* BUGFIX: ForceExtPort initialised correctly. +* Improvements to Chat Layout +* New Log Display in Network Tab. +* Show/Hide Network View Settings. + +Changes for V0.4.03a: +* Modifications to the Chat. +* new Icons for new GUi bits. +* Network View has been done with elastic forces between nodes. +* Network View have been added to Network Tab. +* New Automatic Bootstrap system. +* BUGFIX for reconnection attempts. +* BUGFIX for UDP + TCP simulateous connections. +* Added Bootstrap Monitoring tools + +Changes for V0.3.52a: +* New improved search system. +* New Translations. +* Fixed Bugs in UPnP +* Can now remove Shared Directories. +* Attached the 'Recommend to' Context Menus. +* New Timestamps in Chats / Messages. +* Notification of Offline Peer in Chats. +* Example Games (not networked yet) +* Updated About Text. + +Changes for V0.3.51a + * Fixed 2-3 hour crash bug. + * Fixed On-Off Reconnect behaviour + +Changes for V0.3.x Development +We have available for those interested in retroshare: +(1) New Source release for Linux! V0.3.12B, The compilation script can also compile from SVN. +(2) deb installation files for debian/etch and kubuntu/feisty +(3) Language pack for those interested in translating. + + \ No newline at end of file diff --git a/retroshare-gui/src/control/bandwidthevent.h b/retroshare-gui/src/control/bandwidthevent.h new file mode 100644 index 000000000..4ebbf9c90 --- /dev/null +++ b/retroshare-gui/src/control/bandwidthevent.h @@ -0,0 +1,50 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _BANDWIDTHEVENT_H +#define _BANDWIDTHEVENT_H +#include "eventtype.h" + +#include + + +class BandwidthEvent : public QEvent +{ +public: + /** Constructor */ + BandwidthEvent(quint64 bytesRead, quint64 bytesWritten) + : QEvent((QEvent::Type)CustomEventType::BandwidthEvent) + { _bytesRead = bytesRead; _bytesWritten = bytesWritten; } + + /** Returns the number of bytes read in the last second */ + quint64 bytesRead() { return _bytesRead; } + /** Returns the number of bytes written in the last second */ + quint64 bytesWritten() { return _bytesWritten; } + +private: + quint64 _bytesWritten; + quint64 _bytesRead; +}; + +#endif + diff --git a/retroshare-gui/src/control/eventtype.h b/retroshare-gui/src/control/eventtype.h new file mode 100644 index 000000000..aa785cce6 --- /dev/null +++ b/retroshare-gui/src/control/eventtype.h @@ -0,0 +1,38 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _EVENTTYPE_H +#define _EVENTTYPE_H + +#include + + +/** Custom event type identifiers. */ +namespace CustomEventType { + /** Bandwidth update event. */ + const int BandwidthEvent = QEvent::User; + +} + +#endif + diff --git a/retroshare-gui/src/gui/AboutDialog.cpp b/retroshare-gui/src/gui/AboutDialog.cpp new file mode 100644 index 000000000..e83b6a893 --- /dev/null +++ b/retroshare-gui/src/gui/AboutDialog.cpp @@ -0,0 +1,739 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2009, RetroShare Team + * Copyright (C) 2008 Unipro, Russia (http://ugene.unipro.ru) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "AboutDialog.h" +#include "HelpDialog.h" + +#include +#include +#include "settings/rsharesettings.h" + +#include +#include +#include +#include +#include +#include + + +AboutDialog::AboutDialog(QWidget* parent) +:QDialog(parent) +{ + + setupUi(this); + + QHBoxLayout* l = new QHBoxLayout(); + l->setMargin(0); + l->addStretch(1); + l->addStretch(1); + frame->setContentsMargins(0, 0, 0, 0); + frame->setLayout(l); + tWidget = NULL; + installAWidget(); + + /* get libretroshare version */ + std::map::iterator vit; + std::map versions; + const RsConfig &conf = rsiface->getConfig(); + bool retv = rsDisc->getDiscVersions(versions); + if (retv && versions.end() != (vit = versions.find(conf.ownId))) + { + QString version = QString::fromStdString(vit->second); + setWindowTitle(tr("About RetroShare %1").arg(version)); + } + +#ifdef Q_OS_WIN + setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint); +#endif +} + +void AboutDialog::installAWidget() { + assert(tWidget == NULL); + AWidget* aWidget = new AWidget(); + QVBoxLayout* l = (QVBoxLayout*)frame->layout(); + l->insertWidget(0, aWidget); + l->setStretchFactor(aWidget, 100); +} + +void AboutDialog::installTWidget() { + assert(tWidget == NULL); + tWidget = new TBoard(); + QLabel* npLabel = new NextPieceLabel(tWidget); + tWidget->setNextPieceLabel(npLabel); + + QWidget* pan = new QWidget(); + QVBoxLayout* vl = new QVBoxLayout(pan); + QLabel* topRecLabel = new QLabel(tr("Max score: %1").arg(tWidget->getMaxScore())); + QLabel* scoreLabel = new QLabel(pan); + QLabel* levelLabel = new QLabel(pan); + vl->addStretch(); + vl->addWidget(topRecLabel); + vl->addStretch(); + vl->addWidget(npLabel); + vl->addStretch(); + vl->addWidget(scoreLabel); + vl->addWidget(levelLabel); + vl->addStretch(); + + QHBoxLayout* l = (QHBoxLayout*)frame->layout(); + l->insertWidget(0, pan); + l->insertWidget(0, tWidget); + QRect cRect = frame->contentsRect(); + int height = tWidget->heightForWidth(cRect.width()); + tWidget->setFixedSize(cRect.width() * cRect.height() / height, cRect.height()); + npLabel->setFixedSize(tWidget->squareWidth()*4, tWidget->squareHeight()*5); + l->setStretchFactor(tWidget, 100); + connect(tWidget, SIGNAL(scoreChanged(int)), SLOT(sl_scoreChanged(int))); + connect(tWidget, SIGNAL(levelChanged(int)), SLOT(sl_levelChanged(int))); + connect(this, SIGNAL(si_scoreChanged(QString)), scoreLabel, SLOT(setText(QString))); + connect(this, SIGNAL(si_levelChanged(QString)), levelLabel, SLOT(setText(QString))); + tWidget->setFocus(); + tWidget->start(); +} + +void AboutDialog::switchPages() { + QLayoutItem* li = NULL; + QLayout* l = frame->layout(); + while ((li = l->takeAt(0)) && li->widget()) { + li->widget()->deleteLater(); + } + if (tWidget==NULL) { + installTWidget(); + } else { + tWidget = NULL; + installAWidget(); + } + updateTitle(); +} + +void AboutDialog::sl_scoreChanged(int sc) { + emit si_scoreChanged(tr("Score: %1").arg(sc)); +} + +void AboutDialog::sl_levelChanged(int level) { + emit si_levelChanged(tr("Level: %1").arg(level)); +} + + +void AboutDialog::updateTitle() { + if (tWidget == NULL) { + + /* get libretroshare version */ + std::map::iterator vit; + std::map versions; + const RsConfig &conf = rsiface->getConfig(); + bool retv = rsDisc->getDiscVersions(versions); + if (retv && versions.end() != (vit = versions.find(conf.ownId))) + { + + QString version = QString::fromStdString(vit->second); + setWindowTitle(tr("About RetroShare %1").arg(version)); + + } + } else { + setWindowTitle(tr("Have fun ;-)")); + } +} + +void AboutDialog::keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_T) { + switchPages(); + } else if (tWidget!=NULL && (e->key() == Qt::Key_P || e->key() == Qt::Key_Pause)) { + tWidget->pause(); + } + QDialog::keyPressEvent(e); +} + +void AboutDialog::mousePressEvent(QMouseEvent *e) { + QPoint globalPos = mapToGlobal(e->pos()); + QPoint framePos = frame->mapFromGlobal(globalPos); + if (frame->contentsRect().contains(framePos)) { + switchPages(); + } + QDialog::mousePressEvent(e); +} + +void AboutDialog::on_help_button_clicked() +{ + HelpDialog helpdlg (this); + helpdlg.exec(); +} + +AWidget::AWidget() { + setMouseTracking(true); + + QImage image(":/images/about.png"); + QPainter p(&image); + p.setPen(Qt::lightGray); + + /* get libretroshare version */ + std::map::iterator vit; + std::map versions; + const RsConfig &conf = rsiface->getConfig(); + bool retv = rsDisc->getDiscVersions(versions); + if (retv && versions.end() != (vit = versions.find(conf.ownId))) + { + QString version = QString::fromStdString("RetroShare version : \n") + QString::fromStdString(vit->second); + p.drawText(QRect(10, 20, width()-10, 60), version); + + } + p.end(); + + image1 = image2 = image; + setFixedSize(image1.size()); + + int w = image1.width(); + int h = image1.height(); + heightField1.resize(w*h); + heightField2.resize(w*h); + + density = 5; + page = 0; + + startTimer(15); +} + + +void AWidget::timerEvent(QTimerEvent* e) { + drawWater((QRgb*)image1.bits(), (QRgb*)image2.bits()); + calcWater(page, density); + page ^= 1; + + if (qrand() % 128 == 0) { + int r = 3 + qRound(qrand() * 4 / RAND_MAX); + int h = 300 + qrand() * 200 / RAND_MAX; + int x = 1 + r + qrand()%(image1.width() -2*r-1); + int y = 1 + r + qrand()%(image1.height()-2*r-1); + addBlob(x, y, r, h); + } + + update(); + QObject::timerEvent(e); +} + + +void AWidget::paintEvent(QPaintEvent* e) { + QWidget::paintEvent(e); + + QPainter p(this); + p.drawImage(0, 0, image2); +} + +void AWidget::mouseMoveEvent(QMouseEvent* e) { + QPoint point = e->pos(); + addBlob(point.x() - 15,point.y(), 5, 400); +} + + +void AWidget::calcWater(int npage, int density) { + int w = image1.width(); + int h = image1.height(); + int count = w + 1; + + + // Set up the pointers + int *newptr; + int *oldptr; + if(npage == 0) { + newptr = &heightField1.front(); + oldptr = &heightField2.front(); + } else { + newptr = &heightField2.front(); + oldptr = &heightField1.front(); + } + + for (int y = (h-1)*w; count < y; count += 2) { + for (int x = count+w-2; count < x; count++) { + // This does the eight-pixel method. It looks much better. + int newh = ((oldptr[count + w] + + oldptr[count - w] + + oldptr[count + 1] + + oldptr[count - 1] + + oldptr[count - w - 1] + + oldptr[count - w + 1] + + oldptr[count + w - 1] + + oldptr[count + w + 1] + ) >> 2 ) - newptr[count]; + + newptr[count] = newh - (newh >> density); + } + } +} + +void AWidget::addBlob(int x, int y, int radius, int height) { + int w = image1.width(); + int h = image1.height(); + + // Set up the pointers + int *newptr; + int *oldptr; + if (page == 0) { + newptr = &heightField1.front(); + oldptr = &heightField2.front(); + } else { + newptr = &heightField2.front(); + oldptr = &heightField1.front(); + } + + int rquad = radius * radius; + + int left=-radius, right = radius; + int top=-radius, bottom = radius; + + // Perform edge clipping... + if (x - radius < 1) left -= (x-radius-1); + if (y - radius < 1) top -= (y-radius-1); + if (x + radius > w-1) right -= (x+radius-w+1); + if (y + radius > h-1) bottom-= (y+radius-h+1); + + for(int cy = top; cy < bottom; cy++) { + int cyq = cy*cy; + for(int cx = left; cx < right; cx++) { + if (cx*cx + cyq < rquad) { + newptr[w*(cy+y) + (cx+x)] += height; + } + } + } +} + + +void AWidget::drawWater(QRgb* srcImage,QRgb* dstImage) { + int w = image1.width(); + int h = image1.height(); + + int offset = w + 1; + int lIndex; + int lBreak = w * h; + + int *ptr = &heightField1.front(); + + for (int y = (h-1)*w; offset < y; offset += 2) { + for (int x = offset+w-2; offset < x; offset++) { + int dx = ptr[offset] - ptr[offset+1]; + int dy = ptr[offset] - ptr[offset+w]; + + lIndex = offset + w*(dy>>3) + (dx>>3); + if(lIndex < lBreak && lIndex > 0) { + QRgb c = srcImage[lIndex]; + c = shiftColor(c, dx); + dstImage[offset] = c; + } + offset++; + dx = ptr[offset] - ptr[offset+1]; + dy = ptr[offset] - ptr[offset+w]; + + lIndex = offset + w*(dy>>3) + (dx>>3); + if(lIndex < lBreak && lIndex > 0) { + QRgb c = srcImage[lIndex]; + c = shiftColor(c, dx); + dstImage[offset] = c; + } + } + } +} + +////////////////////////////////////////////////////////////////////////// +// T +TBoard::TBoard(QWidget *parent) { + Q_UNUSED(parent); + + setFocusPolicy(Qt::StrongFocus); + isStarted = false; + isPaused = false; + clearBoard(); + nextPiece.setRandomShape(); + score = 0; + level = 0; + + maxScore = Settings->value("/about/maxsc").toInt(); +} +TBoard::~TBoard() { + int oldMax = Settings->value("/about/maxsc").toInt(); + int newMax = qMax(maxScore, score); + if (oldMax < newMax) { + Settings->setValue("/about/maxsc", newMax); + } +} + +int TBoard::heightForWidth ( int w ) const { + return qRound(BoardHeight * float(w)/BoardWidth); +} + + +void TBoard::start() { + if (isPaused) { + return; + } + + isStarted = true; + isWaitingAfterLine = false; + numLinesRemoved = 0; + numPiecesDropped = 0; + maxScore = qMax(score, maxScore); + score = 0; + level = 1; + clearBoard(); + + emit linesRemovedChanged(numLinesRemoved); + emit scoreChanged(score); + emit levelChanged(level); + + newPiece(); + timer.start(timeoutTime(), this); +} + +void TBoard::pause() { + if (!isStarted) { + return; + } + + isPaused = !isPaused; + if (isPaused) { + timer.stop(); + } else { + timer.start(timeoutTime(), this); + } + update(); +} + +void TBoard::paintEvent(QPaintEvent *event) { + QWidget::paintEvent(event); + + QPainter painter(this); + + painter.setPen(Qt::black); + painter.drawRect(frameRect()); + QRect rect = boardRect(); + painter.fillRect(rect, Qt::white); + + if (isPaused) { + painter.drawText(rect, Qt::AlignCenter, tr("Pause")); + return; + } + + int boardTop = rect.bottom() - BoardHeight*squareHeight(); + + for (int i = 0; i < BoardHeight; ++i) { + for (int j = 0; j < BoardWidth; ++j) { + TPiece::Shape shape = shapeAt(j, BoardHeight - i - 1); + if (shape != TPiece::NoShape) { + drawSquare(painter, rect.left() + j * squareWidth(), boardTop + i * squareHeight(), shape); + } + } + } + if (curPiece.shape() != TPiece::NoShape) { + for (int i = 0; i < 4; ++i) { + int x = curX + curPiece.x(i); + int y = curY - curPiece.y(i); + drawSquare(painter, rect.left() + x * squareWidth(), boardTop + (BoardHeight - y - 1) * squareHeight(), curPiece.shape()); + } + } +} + +void TBoard::keyPressEvent(QKeyEvent *event) { + if (!isStarted || isPaused || curPiece.shape() == TPiece::NoShape) { + QWidget::keyPressEvent(event); + return; + } + + switch (event->key()) { + case Qt::Key_Left: + tryMove(curPiece, curX - 1, curY); + break; + case Qt::Key_Right: + tryMove(curPiece, curX + 1, curY); + break; + case Qt::Key_Down: + tryMove(curPiece.rotatedRight(), curX, curY); + break; + case Qt::Key_Up: + tryMove(curPiece.rotatedLeft(), curX, curY); + break; + case Qt::Key_Space: + dropDown(); + break; + case Qt::Key_Control: + oneLineDown(); + break; + default: + QWidget::keyPressEvent(event); + } +} + +void TBoard::timerEvent(QTimerEvent *event) { + if (event->timerId() == timer.timerId()) { + if (isWaitingAfterLine) { + isWaitingAfterLine = false; + newPiece(); + timer.start(timeoutTime(), this); + } else { + oneLineDown(); + } + } else { + QWidget::timerEvent(event); + } +} +void TBoard::clearBoard() { + for (int i = 0; i < BoardHeight * BoardWidth; ++i) { + board[i] = TPiece::NoShape; + } +} + +void TBoard::dropDown() { + int dropHeight = 0; + int newY = curY; + while (newY > 0) { + if (!tryMove(curPiece, curX, newY - 1)) { + break; + } + newY--; + dropHeight++; + } + pieceDropped(dropHeight); +} +void TBoard::oneLineDown() { + if (!tryMove(curPiece, curX, curY - 1)) + pieceDropped(0); +} +void TBoard::pieceDropped(int dropHeight) { + for (int i = 0; i < 4; ++i) { + int x = curX + curPiece.x(i); + int y = curY - curPiece.y(i); + shapeAt(x, y) = curPiece.shape(); + } + + ++numPiecesDropped; + if (numPiecesDropped % 50 == 0) { + ++level; + timer.start(timeoutTime(), this); + emit levelChanged(level); + } + + score += dropHeight + 7; + emit scoreChanged(score); + removeFullLines(); + + if (!isWaitingAfterLine) { + newPiece(); + } +} + +void TBoard::removeFullLines() { + int numFullLines = 0; + + for (int i = BoardHeight - 1; i >= 0; --i) { + bool lineIsFull = true; + + for (int j = 0; j < BoardWidth; ++j) { + if (shapeAt(j, i) == TPiece::NoShape) { + lineIsFull = false; + break; + } + } + + if (lineIsFull) { + ++numFullLines; + for (int k = i; k < BoardHeight - 1; ++k) { + for (int j = 0; j < BoardWidth; ++j) { + shapeAt(j, k) = shapeAt(j, k + 1); + } + } + for (int j = 0; j < BoardWidth; ++j) { + shapeAt(j, BoardHeight - 1) = TPiece::NoShape; + } + } + } + + if (numFullLines > 0) { + numLinesRemoved += numFullLines; + score += 10 * numFullLines; + emit linesRemovedChanged(numLinesRemoved); + emit scoreChanged(score); + + timer.start(500, this); + isWaitingAfterLine = true; + curPiece.setShape(TPiece::NoShape); + update(); + } +} +void TBoard::newPiece() { + curPiece = nextPiece; + nextPiece.setRandomShape(); + showNextPiece(); + curX = BoardWidth / 2 + 1; + curY = BoardHeight - 1 + curPiece.minY(); + + if (!tryMove(curPiece, curX, curY)) { + curPiece.setShape(TPiece::NoShape); + timer.stop(); + isStarted = false; + } +} + +void TBoard::showNextPiece() { + if (!nextPieceLabel) { + return; + } + + int dx = nextPiece.maxX() - nextPiece.minX() + 1; + int dy = nextPiece.maxY() - nextPiece.minY() + 1; + + QPixmap pixmap(dx * squareWidth(), dy * squareHeight()); + QPainter painter(&pixmap); + painter.fillRect(pixmap.rect(), nextPieceLabel->palette().background()); + + for (int i = 0; i < 4; ++i) { + int x = nextPiece.x(i) - nextPiece.minX(); + int y = nextPiece.y(i) - nextPiece.minY(); + drawSquare(painter, x * squareWidth(), y * squareHeight(), nextPiece.shape()); + } + nextPieceLabel->setPixmap(pixmap); +} + +bool TBoard::tryMove(const TPiece &newPiece, int newX, int newY) { + for (int i = 0; i < 4; ++i) { + int x = newX + newPiece.x(i); + int y = newY - newPiece.y(i); + if (x < 0 || x >= BoardWidth || y < 0 || y >= BoardHeight) { + return false; + } + if (shapeAt(x, y) != TPiece::NoShape) { + return false; + } + } + + curPiece = newPiece; + curX = newX; + curY = newY; + update(); + return true; +} + +void TBoard::drawSquare(QPainter &painter, int x, int y, TPiece::Shape shape) { + static const QRgb colorTable[8] = { 0x000000, 0xCC6666, 0x66CC66, 0x6666CC, 0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00}; + + QColor color = colorTable[int(shape)]; + painter.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2, color); + + painter.setPen(color.light()); + painter.drawLine(x, y + squareHeight() - 1, x, y); + painter.drawLine(x, y, x + squareWidth() - 1, y); + + painter.setPen(color.dark()); + painter.drawLine(x + 1, y + squareHeight() - 1, x + squareWidth() - 1, y + squareHeight() - 1); + painter.drawLine(x + squareWidth() - 1, y + squareHeight() - 1, x + squareWidth() - 1, y + 1); +} + + +void TPiece::setRandomShape() { + setShape(TPiece::Shape(qrand() % 7 + 1)); +} + + +void TPiece::setShape(TPiece::Shape shape) { + static const int coordsTable[8][4][2] = { + { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 0, -1 }, { 0, 0 }, { -1, 0 }, { -1, 1 } }, + { { 0, -1 }, { 0, 0 }, { 1, 0 }, { 1, 1 } }, + { { 0, -1 }, { 0, 0 }, { 0, 1 }, { 0, 2 } }, + { { -1, 0 }, { 0, 0 }, { 1, 0 }, { 0, 1 } }, + { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }, + { { -1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } }, + { { 1, -1 }, { 0, -1 }, { 0, 0 }, { 0, 1 } } + }; + + for (int i = 0; i < 4 ; i++) { + for (int j = 0; j < 2; ++j) { + coords[i][j] = coordsTable[shape][i][j]; + } + } + pieceShape = shape; +} +int TPiece::minX() const { + int min = coords[0][0]; + for (int i = 1; i < 4; ++i) { + min = qMin(min, coords[i][0]); + } + return min; +} + +int TPiece::maxX() const { + int max = coords[0][0]; + for (int i = 1; i < 4; ++i) { + max = qMax(max, coords[i][0]); + } + return max; +} + +int TPiece::minY() const { + int min = coords[0][1]; + for (int i = 1; i < 4; ++i) { + min = qMin(min, coords[i][1]); + } + return min; +} + +int TPiece::maxY() const { + int max = coords[0][1]; + for (int i = 1; i < 4; ++i) { + max = qMax(max, coords[i][1]); + } + return max; +} + +TPiece TPiece::rotatedLeft() const { + if (pieceShape == SquareShape) { + return *this; + } + + TPiece result; + result.pieceShape = pieceShape; + for (int i = 0; i < 4; ++i) { + result.setX(i, y(i)); + result.setY(i, -x(i)); + } + return result; +} + +TPiece TPiece::rotatedRight() const { + if (pieceShape == SquareShape) { + return *this; + } + TPiece result; + result.pieceShape = pieceShape; + for (int i = 0; i < 4; ++i) { + result.setX(i, -y(i)); + result.setY(i, x(i)); + } + return result; +} + +NextPieceLabel::NextPieceLabel( QWidget* parent /*= 0*/ ) : QLabel(parent) +{ + QPalette p = palette(); + p.setColor(QPalette::Background, Qt::white); + setPalette(p); + setFrameShape(QFrame::Box); + setAlignment(Qt::AlignCenter); + setAutoFillBackground(true); +} + diff --git a/retroshare-gui/src/gui/AboutDialog.h b/retroshare-gui/src/gui/AboutDialog.h new file mode 100644 index 000000000..85e28905a --- /dev/null +++ b/retroshare-gui/src/gui/AboutDialog.h @@ -0,0 +1,203 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2009, RetroShare Team + * Copyright (C) 2008 Unipro, Russia (http://ugene.unipro.ru) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _GB2_ABOUT_DIALOG_ +#define _GB2_ABOUT_DIALOG_ + +#include "ui_AboutDialog.h" + +#include +#include + +#include +#include +#include +#include +#include + + +class AWidget; +class TBoard; +class NextPieceLabel; + +class AboutDialog : public QDialog, public Ui::AboutDialog +{ + Q_OBJECT +public: + AboutDialog(QWidget *parent = 0); + +private slots: + void sl_scoreChanged(int); + void sl_levelChanged(int); + void on_help_button_clicked(); + +signals: + void si_scoreChanged(QString); + void si_maxScoreChanged(QString); + void si_levelChanged(QString); + +protected: + void keyPressEvent(QKeyEvent *event); + void mousePressEvent(QMouseEvent *event); +private: + void switchPages(); + void installAWidget(); + void installTWidget(); + void updateTitle(); + + TBoard* tWidget; +}; + +////////////////////////////////////////////////////////////////////////// +// A +class AWidget : public QWidget { + Q_OBJECT + +public: + AWidget(); + +protected: + void timerEvent(QTimerEvent* e); + void paintEvent(QPaintEvent* e); + void mouseMoveEvent(QMouseEvent* e); + +private: + void calcWater(int npage, int density); + + void addBlob(int x, int y, int radius, int height); + + void drawWater(QRgb* srcImage, QRgb* dstImage); + + static QRgb shiftColor(QRgb color,int shift) { + return qRgb(qBound(0, qRed(color) - shift, 255), + qBound(0, qGreen(color) - shift,255), + qBound(0, qBlue(color) - shift, 255)); + } + + int page; + int density; + QVector heightField1; + QVector heightField2; + QImage image1; + QImage image2; +}; + +////////////////////////////////////////////////////////////////////////// +// T + +class TPiece { +public: + enum Shape { NoShape, ZShape, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape }; + + TPiece() { setShape(NoShape); } + + void setRandomShape(); + void setShape(Shape shape); + + Shape shape() const { return pieceShape; } + int x(int index) const { return coords[index][0]; } + int y(int index) const { return coords[index][1]; } + int minX() const; + int maxX() const; + int minY() const; + int maxY() const; + TPiece rotatedLeft() const; + TPiece rotatedRight() const; + +private: + void setX(int index, int x) { coords[index][0] = x; } + void setY(int index, int y) { coords[index][1] = y; } + + Shape pieceShape; + int coords[4][2]; +}; + +class TBoard : public QWidget { + Q_OBJECT + +public: + TBoard(QWidget *parent = 0); + ~TBoard(); + int heightForWidth ( int w ) const; + int getScore() const {return score;} + int getMaxScore() const {return qMax(maxScore, score);} + int getLevel() const {return level;} + void setNextPieceLabel(QLabel *label) {nextPieceLabel = label;} + int squareWidth() const { return boardRect().width() / BoardWidth; } + int squareHeight() const { return boardRect().height() / BoardHeight; } + +public slots: + void start(); + void pause(); + +signals: + void scoreChanged(int score); + void levelChanged(int level); + void linesRemovedChanged(int numLines); + +protected: + void paintEvent(QPaintEvent *event); + void keyPressEvent(QKeyEvent *event); + void timerEvent(QTimerEvent *event); + +private: + + enum { BoardWidth = 10, BoardHeight = 22 }; + + TPiece::Shape &shapeAt(int x, int y) { return board[(y * BoardWidth) + x]; } + int timeoutTime() const { return 1000 / (1 + level); } + QRect boardRect() const {return QRect(1, 1, width()-2, height()-2);} + QRect frameRect() const {return QRect(0, 0, width()-1, height()-1);} + void clearBoard(); + void dropDown(); + void oneLineDown(); + void pieceDropped(int dropHeight); + void removeFullLines(); + void newPiece(); + void showNextPiece(); + bool tryMove(const TPiece &newPiece, int newX, int newY); + void drawSquare(QPainter &painter, int x, int y, TPiece::Shape shape); + + QBasicTimer timer; + QPointer nextPieceLabel; + bool isStarted; + bool isPaused; + bool isWaitingAfterLine; + TPiece curPiece; + TPiece nextPiece; + int curX; + int curY; + int numLinesRemoved; + int numPiecesDropped; + int score; + int maxScore; + int level; + TPiece::Shape board[BoardWidth * BoardHeight]; +}; + +class NextPieceLabel : public QLabel { +public: + NextPieceLabel(QWidget* parent = 0); +}; + + +#endif diff --git a/retroshare-gui/src/gui/AboutDialog.ui b/retroshare-gui/src/gui/AboutDialog.ui new file mode 100644 index 000000000..2f8617f46 --- /dev/null +++ b/retroshare-gui/src/gui/AboutDialog.ui @@ -0,0 +1,109 @@ + + + AboutDialog + + + Qt::NonModal + + + + 0 + 0 + 271 + 376 + + + + + 0 + 0 + + + + About RetroShare + + + + + + false + + + true + + + + 9 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Qt::Horizontal + + + + + + + + + About + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + close + + + + + + + + + + + + + close_button + clicked() + AboutDialog + reject() + + + 243 + 281 + + + 145 + 187 + + + + + diff --git a/retroshare-gui/src/gui/AddLinksDialog.cpp b/retroshare-gui/src/gui/AddLinksDialog.cpp new file mode 100644 index 000000000..af1958b99 --- /dev/null +++ b/retroshare-gui/src/gui/AddLinksDialog.cpp @@ -0,0 +1,124 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "common/vmessagebox.h" + +#include "AddLinksDialog.h" +#include "RetroShareLink.h" +#include + +/* Images for context menu icons */ +#define IMAGE_EXPORTFRIEND ":/images/exportpeers_16x16.png" +#define IMAGE_GREAT ":/images/filerating5.png" +#define IMAGE_GOOD ":/images/filerating4.png" +#define IMAGE_OK ":/images/filerating3.png" +#define IMAGE_SUX ":/images/filerating2.png" +#define IMAGE_BADLINK ":/images/filerating1.png" + +/** Constructor */ +AddLinksDialog::AddLinksDialog(QString url, QWidget *parent) +: QDialog(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + /* add button */ + connect(ui.addLinkButton, SIGNAL(clicked()), this, SLOT(addLinkComment())); + connect(ui.closepushButton, SIGNAL(clicked()), this, SLOT(close())); + + connect( ui.anonBox, SIGNAL( stateChanged ( int ) ), this, SLOT( load ( void ) ) ); + + ui.linkLineEdit->setText(url); + + RetroShareLink link(url); + + if(link.valid() && link.type() == RetroShareLink::TYPE_FILE) + ui.titleLineEdit->setText(link.name()); + else + ui.titleLineEdit->setText("New File"); + + load(); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +int AddLinksDialog::IndexToScore(int index) +{ + if ((index == -1) || (index > 4)) + return 0; + int score = 2 - index; + return score; +} + +void AddLinksDialog::addLinkComment() +{ + /* get the title / link / comment */ + QString title = ui.titleLineEdit->text(); + QString link = ui.linkLineEdit->text(); + QString comment = ui.linkTextEdit->toPlainText(); + int32_t score = AddLinksDialog::IndexToScore(ui.scoreBox->currentIndex()); + + if ((link == "") || (title == "")) + { + QMessageBox::warning(NULL, tr("Add Link Failure"), tr("Missing Link and/or Title"), QMessageBox::Ok); + /* can't do anything */ + return; + } + + /* add it either way */ + if (ui.anonBox->isChecked()) + { + rsRanks->anonRankMsg("", link.toStdWString(), title.toStdWString()); + } + else + { + rsRanks->newRankMsg(link.toStdWString(), + title.toStdWString(), + comment.toStdWString(), score); + } + + close(); +} + +void AddLinksDialog::load() +{ + if (ui.anonBox->isChecked()) + { + + /* disable comment + score */ + ui.scoreBox->setEnabled(false); + ui.linkTextEdit->setEnabled(false); + + /* done! */ + return; + } + else + { + /* enable comment + score */ + ui.scoreBox->setEnabled(true); + ui.linkTextEdit->setEnabled(true); + } +} diff --git a/retroshare-gui/src/gui/AddLinksDialog.h b/retroshare-gui/src/gui/AddLinksDialog.h new file mode 100644 index 000000000..9e4451117 --- /dev/null +++ b/retroshare-gui/src/gui/AddLinksDialog.h @@ -0,0 +1,48 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _ADDLINKS_DIALOG_H +#define _ADDLINKS_DIALOG_H + +#include "ui_AddLinksDialog.h" + +class AddLinksDialog : public QDialog +{ + Q_OBJECT + +public: + /** Default Constructor */ + AddLinksDialog(QString url, QWidget *parent = 0); + /** Default Destructor */ + + static int IndexToScore(int index); + +public slots: + void addLinkComment(); + + void load(); + +private: + /** Qt Designer generated object */ + Ui::AddLinksDialog ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/AddLinksDialog.ui b/retroshare-gui/src/gui/AddLinksDialog.ui new file mode 100644 index 000000000..04b9363a4 --- /dev/null +++ b/retroshare-gui/src/gui/AddLinksDialog.ui @@ -0,0 +1,288 @@ + + + AddLinksDialog + + + + 0 + 0 + 614 + 415 + + + + Add Link + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + 0 + + + + + + 16777215 + 52 + + + + QFrame#frame{background-image: url(:/images/connect/connectFriendBanner.png);} + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + 32 + 32 + + + + + + + :/images/irkick.png + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Cancel + + + + + + + Add Link + + + false + + + true + + + + + + + Qt::Horizontal + + + + 375 + 20 + + + + + + + + Add a new Link + + + + 1 + + + + + + + + + Title: + + + + + + + Url: + + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + 16777215 + 40 + + + + QFrame#frame_3{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Add Anonymous Link + + + + + + + + +2 Great! + + + + :/images/filerating5.png:/images/filerating5.png + + + + + +1 Good + + + + :/images/filerating4.png:/images/filerating4.png + + + + + 0 Okay + + + + :/images/filerating3.png:/images/filerating3.png + + + + + -1 Sux + + + + :/images/filerating2.png:/images/filerating2.png + + + + + -2 Bad Link + + + + :/images/filerating1.png:/images/filerating1.png + + + + + + + + Qt::Horizontal + + + + 299 + 20 + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/ChannelFeed.cpp b/retroshare-gui/src/gui/ChannelFeed.cpp new file mode 100644 index 000000000..73837dbe2 --- /dev/null +++ b/retroshare-gui/src/gui/ChannelFeed.cpp @@ -0,0 +1,645 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include "ChannelFeed.h" + +#include "feeds/ChanMsgItem.h" +#include "common/PopularityDefs.h" +#include "settings/rsharesettings.h" + +#include "channels/CreateChannel.h" +#include "channels/ChannelDetails.h" +#include "channels/CreateChannelMsg.h" +#include "channels/EditChanDetails.h" +#include "channels/ShareKey.h" +#include "notifyqt.h" +#include "RetroShareLink.h" + +#define CHAN_DEFAULT_IMAGE ":/images/channels.png" + +#define WARNING_LIMIT 3600*24*2 + +/**** + * #define CHAN_DEBUG + ***/ + +/** Constructor */ +ChannelFeed::ChannelFeed(QWidget *parent) +: RsAutoUpdatePage(1000,parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + connect(newChannelButton, SIGNAL(clicked()), this, SLOT(createChannel())); + connect(postButton, SIGNAL(clicked()), this, SLOT(createMsg())); + connect(subscribeButton, SIGNAL( clicked( void ) ), this, SLOT( subscribeChannel ( void ) ) ); + connect(unsubscribeButton, SIGNAL( clicked( void ) ), this, SLOT( unsubscribeChannel ( void ) ) ); + connect(setAllAsReadButton, SIGNAL(clicked()), this, SLOT(setAllAsReadClicked())); + connect(autoDownload, SIGNAL(clicked()), this, SLOT(toggleAutoDownload())); + + connect(NotifyQt::getInstance(), SIGNAL(channelMsgReadSatusChanged(QString,QString,int)), this, SLOT(channelMsgReadSatusChanged(QString,QString,int))); + + /*************** Setup Left Hand Side (List of Channels) ****************/ + + connect(treeWidget, SIGNAL(treeCustomContextMenuRequested(QPoint)), this, SLOT( channelListCustomPopupMenu( QPoint ) ) ); + connect(treeWidget, SIGNAL(treeCurrentItemChanged(QString)), this, SLOT(selectChannel(QString))); + + mChannelId.clear(); + + /* Set initial size the splitter */ + QList sizes; + sizes << 300 << width(); // Qt calculates the right sizes + splitter->setSizes(sizes); + + /* Initialize group tree */ + treeWidget->initDisplayMenu(displayButton); + + ownChannels = treeWidget->addCategoryItem(tr("Own Channels"), QIcon(), true); + subcribedChannels = treeWidget->addCategoryItem(tr("Subscribed Channels"), QIcon(), true); + popularChannels = treeWidget->addCategoryItem(tr("Popular Channels"), QIcon(), false); + otherChannels = treeWidget->addCategoryItem(tr("Other Channels"), QIcon(), false); + + + //added from ahead + updateChannelList(); + + nameLabel->setFont(QFont("MS SANS SERIF", 22)); + nameLabel->setMinimumWidth(20); + + /* load settings */ + processSettings(true); + + updateChannelMsgs(); +} + +ChannelFeed::~ChannelFeed() +{ + // save settings + processSettings(false); +} + +void ChannelFeed::processSettings(bool load) +{ + Settings->beginGroup(QString("ChannelFeed")); + + if (load) { + // load settings + + // state of splitter + splitter->restoreState(Settings->value("Splitter").toByteArray()); + } else { + // save settings + + // state of splitter + Settings->setValue("Splitter", splitter->saveState()); + } + + treeWidget->processSettings(Settings, load); + + Settings->endGroup(); +} + +void ChannelFeed::channelListCustomPopupMenu( QPoint point ) +{ + ChannelInfo ci; + if (!rsChannels->getChannelInfo(mChannelId, ci)) { + return; + } + + QMenu contextMnu(this); + + QAction *postchannelAct = new QAction(QIcon(":/images/mail_reply.png"), tr( "Post to Channel" ), &contextMnu); + connect( postchannelAct , SIGNAL( triggered() ), this, SLOT( createMsg() ) ); + + QAction *subscribechannelAct = new QAction(QIcon(":/images/edit_add24.png"), tr( "Subscribe to Channel" ), &contextMnu); + connect( subscribechannelAct , SIGNAL( triggered() ), this, SLOT( subscribeChannel() ) ); + + QAction *unsubscribechannelAct = new QAction(QIcon(":/images/cancel.png"), tr( "Unsubscribe to Channel" ), &contextMnu); + connect( unsubscribechannelAct , SIGNAL( triggered() ), this, SLOT( unsubscribeChannel() ) ); + + QAction *channeldetailsAct = new QAction(QIcon(":/images/info16.png"), tr( "Show Channel Details" ), &contextMnu); + connect( channeldetailsAct , SIGNAL( triggered() ), this, SLOT( showChannelDetails() ) ); + + QAction *restoreKeysAct = new QAction(QIcon(":/images/settings16.png"), tr("Restore Publish Rights for Channel" ), &contextMnu); + connect( restoreKeysAct , SIGNAL( triggered() ), this, SLOT( restoreChannelKeys() ) ); + + QAction *editChannelDetailAct = new QAction(QIcon(":/images/edit_16.png"), tr("Edit Channel Details"), &contextMnu); + connect( editChannelDetailAct, SIGNAL( triggered() ), this, SLOT( editChannelDetail() ) ); + + QAction *shareKeyAct = new QAction(QIcon(":/images/gpgp_key_generate.png"), tr("Share Channel"), &contextMnu); + connect( shareKeyAct, SIGNAL( triggered() ), this, SLOT( shareKey() ) ); + + if ((ci.channelFlags & RS_DISTRIB_PUBLISH) && (ci.channelFlags & RS_DISTRIB_ADMIN)) { + contextMnu.addAction( postchannelAct ); + contextMnu.addSeparator(); + contextMnu.addAction( editChannelDetailAct); + contextMnu.addAction( shareKeyAct ); + contextMnu.addAction( channeldetailsAct ); + } + else if ((ci.channelFlags & RS_DISTRIB_PUBLISH) && (ci.channelFlags & RS_DISTRIB_SUBSCRIBED)) { + contextMnu.addAction( postchannelAct ); + contextMnu.addSeparator(); + contextMnu.addAction( channeldetailsAct ); + contextMnu.addAction( shareKeyAct ); + contextMnu.addAction( restoreKeysAct ); + } else if (ci.channelFlags & RS_DISTRIB_SUBSCRIBED) { + contextMnu.addAction( unsubscribechannelAct ); + contextMnu.addSeparator(); + contextMnu.addAction( channeldetailsAct ); + contextMnu.addAction( restoreKeysAct ); + } else { + contextMnu.addAction( subscribechannelAct ); + contextMnu.addSeparator(); + contextMnu.addAction( channeldetailsAct ); + contextMnu.addAction( restoreKeysAct ); + } + + QAction *action = contextMnu.addAction(QIcon(":/images/copyrslink.png"), tr("Copy RetroShare Link"), this, SLOT(copyChannelLink())); + action->setEnabled(!mChannelId.empty()); + + contextMnu.exec(QCursor::pos()); +} + +void ChannelFeed::createChannel() +{ + CreateChannel cf (this); + cf.exec(); +} + +/*************************************************************************************/ +/*************************************************************************************/ +/*************************************************************************************/ + +void ChannelFeed::deleteFeedItem(QWidget *item, uint32_t type) +{ +} + +void ChannelFeed::openChat(std::string peerId) +{ +} + +void ChannelFeed::editChannelDetail(){ + + EditChanDetails editUi(this, 0, mChannelId); + editUi.exec(); +} + +void ChannelFeed::shareKey() +{ + ShareKey shareUi(this, 0, mChannelId); + shareUi.exec(); +} + +void ChannelFeed::copyChannelLink() +{ + if (mChannelId.empty()) { + return; + } + + ChannelInfo ci; + if (rsChannels->getChannelInfo(mChannelId, ci)) { + RetroShareLink link; + if (link.createChannel(ci.channelId, "")) { + std::vector urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } + } +} + +void ChannelFeed::createMsg() +{ + if (mChannelId.empty()) { + return; + } + + CreateChannelMsg *msgDialog = new CreateChannelMsg(mChannelId); + msgDialog->show(); + + /* window will destroy itself! */ +} + +void ChannelFeed::restoreChannelKeys() +{ + rsChannels->channelRestoreKeys(mChannelId); +} + +void ChannelFeed::selectChannel(const QString &id) +{ + mChannelId = id.toStdString(); + + bool autoDl = false; + rsChannels->channelGetAutoDl(mChannelId, autoDl); + + setAutoDownloadButton(autoDl); + + updateChannelMsgs(); +} + +void ChannelFeed::updateDisplay() +{ + if (!rsChannels) { + return; + } + + std::list chanIds; + std::list::iterator it; + + if (rsChannels->channelsChanged(chanIds)) { + /* update channel list */ + updateChannelList(); + + it = std::find(chanIds.begin(), chanIds.end(), mChannelId); + if (it != chanIds.end()) { + updateChannelMsgs(); + } + } +} + +static void channelInfoToGroupItemInfo(const ChannelInfo &channelInfo, GroupItemInfo &groupItemInfo) +{ + groupItemInfo.id = QString::fromStdString(channelInfo.channelId); + groupItemInfo.name = QString::fromStdWString(channelInfo.channelName); + groupItemInfo.description = QString::fromStdWString(channelInfo.channelDesc); + groupItemInfo.popularity = channelInfo.pop; + groupItemInfo.lastpost = QDateTime::fromTime_t(channelInfo.lastPost); + + QPixmap chanImage; + if (channelInfo.pngImageLen) { + chanImage.loadFromData(channelInfo.pngChanImage, channelInfo.pngImageLen, "PNG"); + } else { + chanImage = QPixmap(CHAN_DEFAULT_IMAGE); + } + + groupItemInfo.icon = QIcon(chanImage); +} + +void ChannelFeed::updateChannelList() +{ + if (!rsChannels) { + return; + } + + std::list channelList; + std::list::iterator it; + rsChannels->getChannelList(channelList); + + std::list keysAvailable; + std::list::iterator keyIt; + rsChannels->getPubKeysAvailableGrpIds(keysAvailable); + + /* get the ids for our lists */ + QList adminList; + QList subList; + QList popList; + QList otherList; + std::multimap popMap; + + for(it = channelList.begin(); it != channelList.end(); it++) { + /* sort it into Publish (Own), Subscribed, Popular and Other */ + uint32_t flags = it->channelFlags; + + GroupItemInfo groupItemInfo; + channelInfoToGroupItemInfo(*it, groupItemInfo); + + if ((flags & RS_DISTRIB_ADMIN) && (flags & RS_DISTRIB_PUBLISH) && (flags & RS_DISTRIB_SUBSCRIBED)) { + adminList.push_back(groupItemInfo); + } else { + for (keyIt = keysAvailable.begin(); keyIt != keysAvailable.end(); keyIt++) { + if (it->channelId == *keyIt) { + /* Found Key, set title text to bold and colored blue */ + groupItemInfo.privatekey = true; + break; + } + } + + if ((flags & RS_DISTRIB_SUBSCRIBED) || ((flags & RS_DISTRIB_SUBSCRIBED) && (flags & RS_DISTRIB_PUBLISH)) ) { + subList.push_back(groupItemInfo); + } else { + /* rate the others by popularity */ + popMap.insert(std::make_pair(it->pop, groupItemInfo)); + } + } + } + + /* iterate backwards through popMap - take the top 5 or 10% of list */ + uint32_t popCount = 5; + if (popCount < popMap.size() / 10) { + popCount = popMap.size() / 10; + } + + uint32_t i = 0; + std::multimap::reverse_iterator rit; + for (rit = popMap.rbegin(); rit != popMap.rend(); rit++) { + if (i < popCount) { + popList.push_back(rit->second); + i++; + } else { + otherList.push_back(rit->second); + } + } + + /* now we have our lists ---> update entries */ + + treeWidget->fillGroupItems(ownChannels, adminList); + treeWidget->fillGroupItems(subcribedChannels, subList); + treeWidget->fillGroupItems(popularChannels, popList); + treeWidget->fillGroupItems(otherChannels, otherList); + + updateMessageSummaryList(""); +} + + +void ChannelFeed::channelMsgReadSatusChanged(const QString& channelId, const QString& msgId, int status) +{ + updateMessageSummaryList(channelId.toStdString()); +} + +void ChannelFeed::updateMessageSummaryList(const std::string &channelId) +{ + QTreeWidgetItem *items[2] = { ownChannels, subcribedChannels }; + + for (int item = 0; item < 2; item++) { + int child; + int childCount = items[item]->childCount(); + for (child = 0; child < childCount; child++) { + QTreeWidgetItem *childItem = items[item]->child(child); + std::string childId = treeWidget->itemId(childItem).toStdString(); + if (childId.empty()) { + continue; + } + + if (channelId.empty() || childId == channelId) { + /* Calculate unread messages */ + unsigned int newMessageCount = 0; + unsigned int unreadMessageCount = 0; + rsChannels->getMessageCount(childId, newMessageCount, unreadMessageCount); + + treeWidget->setUnreadCount(childItem, unreadMessageCount); + + if (channelId.empty() == false) { + /* Calculate only this channel */ + break; + } + } + } + } +} + +static bool sortChannelMsgSummary(const ChannelMsgSummary &msg1, const ChannelMsgSummary &msg2) +{ + return (msg1.ts > msg2.ts); +} + +void ChannelFeed::updateChannelMsgs() +{ + if (!rsChannels) { + return; + } + + /* replace all the messages with new ones */ + std::list::iterator mit; + for (mit = mChanMsgItems.begin(); mit != mChanMsgItems.end(); mit++) { + delete (*mit); + } + mChanMsgItems.clear(); + + ChannelInfo ci; + if (!rsChannels->getChannelInfo(mChannelId, ci)) { + postButton->setEnabled(false); + subscribeButton->setEnabled(false); + unsubscribeButton->setEnabled(false); + setAllAsReadButton->setEnabled(false); + autoDownload->setEnabled(false); + nameLabel->setText(tr("No Channel Selected")); + iconLabel->setPixmap(QPixmap(":/images/channels.png")); + iconLabel->setEnabled(false); + return; + } + + if (ci.pngImageLen != 0) { + QPixmap chanImage; + chanImage.loadFromData(ci.pngChanImage, ci.pngImageLen, "PNG"); + iconLabel->setPixmap(chanImage); + iconLabel->setStyleSheet("QLabel{border: 3px solid white;}"); + } else { + QPixmap defaulImage(CHAN_DEFAULT_IMAGE); + iconLabel->setPixmap(defaulImage); + iconLabel->setStyleSheet("QLabel{border: 2px solid white;border-radius: 10px;}"); + } + iconLabel->setEnabled(true); + + /* set textcolor for Channel name */ + QString channelStr("%1"); + + /* set Channel name */ + QString cname = QString::fromStdWString(ci.channelName); + nameLabel->setText(channelStr.arg(cname)); + + /* do buttons */ + if (ci.channelFlags & RS_DISTRIB_SUBSCRIBED) { + subscribeButton->setEnabled(false); + unsubscribeButton->setEnabled(true); + setAllAsReadButton->setEnabled(true); + } else { + subscribeButton->setEnabled(true); + unsubscribeButton->setEnabled(false); + setAllAsReadButton->setEnabled(false); + autoDownload->setEnabled(false); + } + + if (ci.channelFlags & RS_DISTRIB_PUBLISH) { + postButton->setEnabled(true); + autoDownload->setEnabled(false); + } else { + postButton->setEnabled(false); + } + + if(!(ci.channelFlags & RS_DISTRIB_PUBLISH) && + (ci.channelFlags & RS_DISTRIB_SUBSCRIBED)) + autoDownload->setEnabled(true); + + + std::list msgs; + std::list::iterator it; + rsChannels->getChannelMsgList(mChannelId, msgs); + + msgs.sort(sortChannelMsgSummary); + + + for(it = msgs.begin(); it != msgs.end(); it++) { + ChanMsgItem *cmi = new ChanMsgItem(this, 0, mChannelId, it->msgId, true); + + + mChanMsgItems.push_back(cmi); + verticalLayout_2->addWidget(cmi); + } +} + +void ChannelFeed::unsubscribeChannel() +{ +#ifdef CHAN_DEBUG + std::cerr << "ChannelFeed::unsubscribeChannel()"; + std::cerr << std::endl; +#endif + + if (rsChannels) { + rsChannels->channelSubscribe(mChannelId, false, false); + } + + updateChannelMsgs(); +} + + +void ChannelFeed::subscribeChannel() +{ +#ifdef CHAN_DEBUG + std::cerr << "ChannelFeed::subscribeChannel()"; + std::cerr << std::endl; +#endif + + if (rsChannels) { + rsChannels->channelSubscribe(mChannelId, true, true); + } + + updateChannelMsgs(); +} + +void ChannelFeed::showChannelDetails() +{ + if (mChannelId.empty()) { + return; + } + + if (!rsChannels) { + return; + } + + ChannelDetails channelui (this); + + channelui.showDetails(mChannelId); + channelui.exec(); +} + +void ChannelFeed::setAllAsReadClicked() +{ + if (mChannelId.empty()) { + return; + } + + if (!rsChannels) { + return; + } + + ChannelInfo ci; + if (rsChannels->getChannelInfo(mChannelId, ci) == false) { + return; + } + + if (ci.channelFlags & RS_DISTRIB_SUBSCRIBED) { + std::list msgs; + std::list::iterator it; + + rsChannels->getChannelMsgList(mChannelId, msgs); + + for(it = msgs.begin(); it != msgs.end(); it++) { + rsChannels->setMessageStatus(mChannelId, it->msgId, CHANNEL_MSG_STATUS_READ, CHANNEL_MSG_STATUS_READ | CHANNEL_MSG_STATUS_UNREAD_BY_USER); + } + } +} + +void ChannelFeed::toggleAutoDownload(){ + + if(mChannelId.empty()) + return; + + bool autoDl = true; + + if(rsChannels->channelGetAutoDl(mChannelId, autoDl)){ + + // if auto dl is set true, then set false + if(autoDl){ + rsChannels->channelSetAutoDl(mChannelId, false); + }else{ + rsChannels->channelSetAutoDl(mChannelId, true); + } + setAutoDownloadButton(!autoDl); + } + else{ + std::cerr << "Auto Download failed to set" + << std::endl; + } +} + +bool ChannelFeed::navigate(const std::string& channelId, const std::string& msgId) +{ + if (channelId.empty()) { + return false; + } + + if (treeWidget->activateId(QString::fromStdString(channelId), msgId.empty()) == NULL) { + return false; + } + + /* Messages are filled in selectChannel */ + if (mChannelId != channelId) { + return false; + } + + if (msgId.empty()) { + return true; + } + + /* Search exisiting item */ + std::list::iterator mit; + for (mit = mChanMsgItems.begin(); mit != mChanMsgItems.end(); mit++) { + ChanMsgItem *item = *mit; + if (item->msgId() == msgId) { + // the next two lines are necessary to calculate the layout of the widgets in the scroll area (maybe there is a better solution) + item->show(); + QCoreApplication::processEvents(); + + scrollArea->ensureWidgetVisible(item, 0, 0); + return true; + } + } + + return false; +} + +void ChannelFeed::setAutoDownloadButton(bool autoDl) +{ + if (autoDl) { + autoDownload->setText(tr("Disable Auto-Download")); + }else{ + autoDownload->setText(tr("Enable Auto-Download")); + } +} diff --git a/retroshare-gui/src/gui/ChannelFeed.h b/retroshare-gui/src/gui/ChannelFeed.h new file mode 100644 index 000000000..607db5cc5 --- /dev/null +++ b/retroshare-gui/src/gui/ChannelFeed.h @@ -0,0 +1,102 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CHANNEL_FEED_DIALOG_H +#define _CHANNEL_FEED_DIALOG_H + +#include +#include +#include + +#include "mainpage.h" +#include "RsAutoUpdatePage.h" + +#include "ui_ChannelFeed.h" + +#include "gui/feeds/FeedHolder.h" + +class ChanMsgItem; +class QTreeWidgetItem; + +class ChannelFeed : public RsAutoUpdatePage, public FeedHolder, private Ui::ChannelFeed +{ + Q_OBJECT + +public: + /** Default Constructor */ + ChannelFeed(QWidget *parent = 0); + /** Default Destructor */ + ~ChannelFeed(); + + virtual void deleteFeedItem(QWidget *item, uint32_t type); + virtual void openChat(std::string peerId); + + bool navigate(const std::string& channelId, const std::string& msgId); + + /* overloaded from RsAuthUpdatePage */ + virtual void updateDisplay(); + +private slots: + void channelListCustomPopupMenu( QPoint point ); + void selectChannel(const QString &id); + + void createChannel(); + + void subscribeChannel(); + void unsubscribeChannel(); + void setAllAsReadClicked(); + void toggleAutoDownload(); + + void createMsg(); + + void showChannelDetails(); + void restoreChannelKeys(); + void editChannelDetail(); + void shareKey(); + void copyChannelLink(); + + void channelMsgReadSatusChanged(const QString& channelId, const QString& msgId, int status); + +private: + void updateChannelList(); + void updateChannelMsgs(); + void updateMessageSummaryList(const std::string &channelId); + + void processSettings(bool load); + + void setAutoDownloadButton(bool autoDl); + + std::string mChannelId; /* current Channel */ + + /* Layout Pointers */ + QBoxLayout *mMsgLayout; + + std::list mChanMsgItems; + std::map mChanSearchScore; //chanId, score + + QTreeWidgetItem *ownChannels; + QTreeWidgetItem *subcribedChannels; + QTreeWidgetItem *popularChannels; + QTreeWidgetItem *otherChannels; +}; + +#endif + diff --git a/retroshare-gui/src/gui/ChannelFeed.ui b/retroshare-gui/src/gui/ChannelFeed.ui new file mode 100644 index 000000000..ae31412e6 --- /dev/null +++ b/retroshare-gui/src/gui/ChannelFeed.ui @@ -0,0 +1,612 @@ + + + ChannelFeed + + + + 0 + 0 + 681 + 476 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + QFrame#chanFrame{border: none;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 0 + + + + + 0 + + + + + + 0 + 0 + + + + + + + + + + QFrame#chheaderframe{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + 0 + + + + + + 24 + 24 + + + + + + + :/images/channels32.png + + + true + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::NoFocus + + + Display + + + QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + } + + QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open { + position: relative; + top: 2px; left: 2px; /* shift the arrow by 2 px */ + } + + QPushButton:hover { + border: 1px solid #CCCCCC; + } + + + + :/images/looknfeel.png:/images/looknfeel.png + + + true + + + + + + + true + + + Qt::NoFocus + + + Create Channel + + + + :/images/add_channel24.png:/images/add_channel24.png + + + true + + + + + + + + + + + + + + QFrame#frame{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #F2F2F2, stop:1 #E6E6E6); +border: 1px solid #CCCCCC;} + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + 16 + + + 9 + + + + + + 64 + 64 + + + + + 64 + 64 + + + + QLabel{ +border: 2px solid white; +border-radius: 10px; +} + + + + + + :/images/channels.png + + + true + + + + + + + + 75 + true + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt;">Channel Name</span></p></body></html> + + + true + + + + + + + + + Qt::Horizontal + + + + + + + 2 + + + 2 + + + + + + 0 + 0 + + + + + 0 + 26 + + + + Unsubcribe To Channel + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + Unsubscribe + + + + + + + + 0 + 0 + + + + + 0 + 26 + + + + + 16777215 + 26 + + + + Subscribe To Channel + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + Subscribe + + + + :/images/konqsidebar_news16.png:/images/konqsidebar_news16.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 26 + + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + Set all to read + + + + + + + + 0 + 26 + + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + Enable Auto-download + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 16777215 + 26 + + + + Qt::NoFocus + + + Post to Channel + + + + + + + + + + :/images/mail_send.png:/images/mail_send.png + + + true + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + true + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + 0 + 0 + 484 + 331 + + + + QWidget#scrollAreaWidgetContents{border: none;} + + + + 0 + + + 0 + + + + + + + + Qt::Vertical + + + + 391 + 266 + + + + + + + + + + + + + + + + + + + + GroupTreeWidget + QWidget +
    gui/common/GroupTreeWidget.h
    + 1 +
    +
    + + + + +
    diff --git a/retroshare-gui/src/gui/DLListDelegate.cpp b/retroshare-gui/src/gui/DLListDelegate.cpp new file mode 100644 index 000000000..8da2c0190 --- /dev/null +++ b/retroshare-gui/src/gui/DLListDelegate.cpp @@ -0,0 +1,237 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "DLListDelegate.h" + +Q_DECLARE_METATYPE(FileProgressInfo) + +DLListDelegate::DLListDelegate(QObject *parent) : QAbstractItemDelegate(parent) +{ + ; +} + +DLListDelegate::~DLListDelegate(void) +{ + ; +} + +void DLListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const +{ + QString byteUnits[4] = {tr("B"), tr("KB"), tr("MB"), tr("GB")}; + QStyleOptionViewItem opt = option; + QStyleOptionProgressBarV2 newopt; + QRect pixmapRect; + QPixmap pixmap; + qlonglong fileSize; + double dlspeed, multi; + int seconds,minutes, hours, days; + qlonglong remaining; + QString temp , status; + qlonglong completed; + qlonglong downloadtime; + + // prepare + painter->save(); + painter->setClipRect(opt.rect); + + //set text color + QVariant value = index.data(Qt::TextColorRole); + if(value.isValid() && qvariant_cast(value).isValid()) { + opt.palette.setColor(QPalette::Text, qvariant_cast(value)); + } + QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; + if(option.state & QStyle::State_Selected){ + painter->setPen(opt.palette.color(cg, QPalette::HighlightedText)); + } else { + painter->setPen(opt.palette.color(cg, QPalette::Text)); + } + + // draw the background color if not the progress column or if progress is not displayed + if(index.column() != PROGRESS) { + if(option.showDecorationSelected && (option.state & QStyle::State_Selected)) { + if(cg == QPalette::Normal && !(option.state & QStyle::State_Active)) { + cg = QPalette::Inactive; + } + painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight)); + } else { + value = index.data(Qt::BackgroundRole); + if(value.isValid() && qvariant_cast(value).isValid()) { + painter->fillRect(option.rect, qvariant_cast(value)); + } + } + } + switch(index.column()) { + case SIZE: + fileSize = index.data().toLongLong(); + if(fileSize <= 0){ + temp = ""; + } else { + multi = 1.0; + for(int i = 0; i < 5; ++i) { + if (fileSize < 1024) { + fileSize = index.data().toLongLong(); + temp.sprintf("%.2f ", fileSize / multi); + temp += byteUnits[i]; + break; + } + fileSize /= 1024; + multi *= 1024.0; + } + } + painter->drawText(option.rect, Qt::AlignRight, temp); + break; + case REMAINING: + remaining = index.data().toLongLong(); + if(remaining <= 0){ + temp = ""; + } else { + multi = 1.0; + for(int i = 0; i < 5; ++i) { + if (remaining < 1024) { + remaining = index.data().toLongLong(); + temp.sprintf("%.2f ", remaining / multi); + temp += byteUnits[i]; + break; + } + remaining /= 1024; + multi *= 1024.0; + } + } + painter->drawText(option.rect, Qt::AlignRight, temp); + break; + case COMPLETED: + completed = index.data().toLongLong(); + if(completed <= 0){ + temp = ""; + } else { + multi = 1.0; + for(int i = 0; i < 5; ++i) { + if (completed < 1024) { + completed = index.data().toLongLong(); + temp.sprintf("%.2f ", completed / multi); + temp += byteUnits[i]; + break; + } + completed /= 1024; + multi *= 1024.0; + } + } + painter->drawText(option.rect, Qt::AlignRight, temp); + break; + case DLSPEED: + dlspeed = index.data().toDouble(); + if (dlspeed <= 0) { + temp = ""; + } else { + temp.clear(); + temp.sprintf("%.2f", dlspeed/1024.); + temp += " KB/s"; + } + painter->drawText(option.rect, Qt::AlignRight, temp); + break; + case PROGRESS: + { + // create a xProgressBar + FileProgressInfo pinfo = index.data().value() ; + +// std::cerr << "drawing progress info: nb_chunks = " << pinfo.nb_chunks ; +// for(uint i=0;isave() ; + xProgressBar progressBar(pinfo,option.rect, painter); // the 3rd param is the color schema (0 is the default value) + if(pinfo.type == FileProgressInfo::DOWNLOAD_LINE) + { + progressBar.setDisplayText(true); // should display % text? + progressBar.setColorSchema(0) ; + } + else + { + progressBar.setDisplayText(false); // should display % text? + progressBar.setColorSchema(1) ; + } + progressBar.setVerticalSpan(1); + progressBar.paint(); // paint the progress bar + + painter->restore() ; + } + painter->drawText(option.rect, Qt::AlignCenter, newopt.text); + break; + case DOWNLOADTIME: + downloadtime = index.data().toLongLong(); + minutes = downloadtime / 60; + seconds = downloadtime % 60; + hours = minutes / 60; + minutes = minutes % 60 ; + days = hours / 24; + hours = hours % 24 ; + if(days > 0) { + temp = QString::number(days)+"d "+QString::number(hours)+"h" ; + } else if(hours > 0 || days > 0) { + temp = QString::number(hours)+"h "+QString::number(minutes)+"m" ; + } else if(minutes > 0 || hours > 0) { + temp = QString::number(minutes)+"m"+QString::number(seconds)+"s" ; + } else if(seconds > 0) { + temp = QString::number(seconds)+"s" ; + } else + temp = "" ; + painter->drawText(option.rect, Qt::AlignCenter, temp); + break; + case NAME: + // decoration + value = index.data(Qt::DecorationRole); + temp = index.data().toString(); + pixmap = qvariant_cast(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); + pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); + if (pixmapRect.isValid()){ + QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft(); + painter->drawPixmap(p, pixmap); + temp = " " + temp; + } + painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft, temp); + break; + default: + painter->drawText(option.rect, Qt::AlignCenter, index.data().toString()); + } + + // done + painter->restore(); +} + +QSize DLListDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const +{ + return QSize(50,17); + QVariant value = index.data(Qt::FontRole); + QFont fnt = value.isValid() ? qvariant_cast(value) : option.font; + QFontMetrics fontMetrics(fnt); + const QString text = index.data(Qt::DisplayRole).toString(); + QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1)); + return textRect.size(); +} + diff --git a/retroshare-gui/src/gui/DLListDelegate.h b/retroshare-gui/src/gui/DLListDelegate.h new file mode 100644 index 000000000..0e69f70cf --- /dev/null +++ b/retroshare-gui/src/gui/DLListDelegate.h @@ -0,0 +1,69 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007,2008 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef DLLISTDELEGATE_H +#define DLLISTDELEGATE_H + +#include +#include "xprogressbar.h" + + +// Defines for download list list columns +#define NAME 0 +#define SIZE 1 +#define COMPLETED 2 +#define DLSPEED 3 +#define PROGRESS 4 +#define SOURCES 5 +#define STATUS 6 +#define PRIORITY 7 +#define REMAINING 8 +#define DOWNLOADTIME 9 +#define ID 10 + + +#define MAX_CHAR_TMP 128 + +class QModelIndex; +class QPainter; +class QStyleOptionProgressBarV2; +class QProgressBar; +class QApplication; + + +class DLListDelegate: public QAbstractItemDelegate { + + Q_OBJECT + + public: + DLListDelegate(QObject *parent=0); + ~DLListDelegate(); + void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; + QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const; + + private: + + public slots: + + signals: +}; +#endif + diff --git a/retroshare-gui/src/gui/DetailsDialog.cpp b/retroshare-gui/src/gui/DetailsDialog.cpp new file mode 100644 index 000000000..7df7ee756 --- /dev/null +++ b/retroshare-gui/src/gui/DetailsDialog.cpp @@ -0,0 +1,185 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006-2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "DetailsDialog.h" +#include "TransfersDialog.h" + +#include "util/misc.h" + +/** Default constructor */ +DetailsDialog::DetailsDialog(QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + CommentsModel = new QStandardItemModel(0, 3); + CommentsModel->setHeaderData(0, Qt::Horizontal, tr("Rating")); + CommentsModel->setHeaderData(1, Qt::Horizontal, tr("Comments")); + CommentsModel->setHeaderData(2, Qt::Horizontal, tr("File Name")); + + ui.commentsTreeView->setModel(CommentsModel); + ui.commentsTreeView->setSortingEnabled(true); + ui.commentsTreeView->setRootIsDecorated(false); + + /* Set header resize modes and initial section sizes */ + QHeaderView * _coheader = ui.commentsTreeView->header(); + _coheader->setResizeMode ( 0, QHeaderView::Custom); + _coheader->resizeSection ( 0, 100 ); + _coheader->resizeSection ( 1, 240 ); + _coheader->resizeSection ( 2, 100 ); + +} + +/** Destructor. */ +DetailsDialog::~DetailsDialog() +{ + TransfersDialog::detailsdlg = NULL; +} + +void DetailsDialog::on_ok_dButton_clicked() +{ + QDialog::close(); +} + +void DetailsDialog::on_cancel_dButton_clicked() +{ + //reject(); + QDialog::close(); +} + + +void +DetailsDialog::show() +{ + ui.tabWidget->setCurrentIndex(0); + if (!this->isVisible()) { + QDialog::show(); + } else { + QDialog::activateWindow(); + setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); + QDialog::raise(); + } +} + +void DetailsDialog::closeEvent (QCloseEvent * event) +{ + QWidget::closeEvent(event); +} + +void DetailsDialog::setFileName(const QString & filename) +{ + int c; + QModelIndex index; + + c = CommentsModel->rowCount(); + CommentsModel->removeRows(0,c); + + c = CommentsModel->rowCount(); + CommentsModel->insertRow(c); + + index = CommentsModel->index(c, 0); + CommentsModel->setData(index, tr("Not Rated")); + + index = CommentsModel->index(c, 1); + CommentsModel->setData(index, tr("No Comments")); + + index = CommentsModel->index(c, 2); + CommentsModel->setData(index, filename); + + ui.name_label_2->setText(filename); + +} + +void DetailsDialog::setHash(const QString & hash) +{ + ui.hash_label_2->setText(hash); +} + +void DetailsDialog::setSize(const qulonglong & size) +{ + ui.size_label_2->setText(misc::friendlyUnit(size) + " " + "(" + QString::number(size) + " " + "Bytes" + ")"); +} + +void DetailsDialog::setStatus(const QString & status) +{ + ui.status_label_2->setText(status); +} + +void DetailsDialog::setPriority(const QString & priority) +{ + ui.priority_label_2->setText(priority); +} + +void DetailsDialog::setType(const QString & type) +{ + ui.type_label_2->setText(type); +} + +void DetailsDialog::setSources(const QString & sources) +{ + ui.sources_line->setText(sources); +} + +void DetailsDialog::setDatarate(const double & datarate) +{ + QString temp; + temp.clear(); + temp.sprintf("%.2f", datarate/1024.); + temp += " KB/s"; + + ui.datarate_line->setText(temp); +} + +void DetailsDialog::setCompleted(const QString & completed) +{ + ui.completed_line->setText(completed); +} + +void DetailsDialog::setRemaining(const QString & remaining) +{ + ui.remaining_line->setText(remaining); +} + +void DetailsDialog::setDownloadtime(const QString & downloadtime) +{ + ui.downloadtime_line->setText(downloadtime); +} + +void DetailsDialog::setLink(const QString & link) +{ + ui.Linktext->setText(link); +} + +void DetailsDialog::setChunkSize(uint32_t chunksize) +{ + ui.chunksizelabel->setText(misc::friendlyUnit(chunksize)); +} + +void DetailsDialog::setNumberOfChunks(size_t numberofchunks) +{ + ui.numberofchunkslabel->setText(QString::number(numberofchunks)); +} diff --git a/retroshare-gui/src/gui/DetailsDialog.h b/retroshare-gui/src/gui/DetailsDialog.h new file mode 100644 index 000000000..b22a90e45 --- /dev/null +++ b/retroshare-gui/src/gui/DetailsDialog.h @@ -0,0 +1,81 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006-2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _DETAILSDIALOG_H +#define _DETAILSDIALOG_H + +#include +#include "ui_DetailsDialog.h" + +class FileChunksInfo ; + +class DetailsDialog : public QDialog +{ + Q_OBJECT + +public: + /** Default constructor */ + DetailsDialog(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~DetailsDialog(); + + void setFileHash(const std::string& hash) { _file_hash = hash ; } + +public slots: + /** Overloaded QWidget.show */ + void show(); + + void setFileName(const QString & filename); + void setHash(const QString & hash); + void setLink(const QString & link); + void setSize(const qulonglong & size); + void setStatus(const QString & status); + void setPriority(const QString & priority); + void setSources(const QString & sources); + void setDatarate(const double & datarate); + void setCompleted(const QString & completed); + void setRemaining(const QString & remaining) ; + void setDownloadtime(const QString & downloadtime); + void setType(const QString & type); + void setChunkSize(const uint32_t chunksize); + void setNumberOfChunks(const size_t numberofchunks); + + +protected: + void closeEvent (QCloseEvent * event); + +private slots: + void on_ok_dButton_clicked(); + void on_cancel_dButton_clicked(); + +private: + + class QStandardItemModel *CommentsModel; + + std::string _file_hash ; + + + /** Qt Designer generated object */ + Ui::DetailsDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/DetailsDialog.ui b/retroshare-gui/src/gui/DetailsDialog.ui new file mode 100644 index 000000000..1f22a156d --- /dev/null +++ b/retroshare-gui/src/gui/DetailsDialog.ui @@ -0,0 +1,446 @@ + + + DetailsDialog + + + + 0 + 0 + 525 + 477 + + + + Details + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + 0 + + + + + :/images/fileinfo.png:/images/fileinfo.png + + + General + + + + + + General + + + + + + + 16777215 + 16777215 + + + + Qt::LeftToRight + + + File Name: + + + + + + + Name Label + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + + 336 + 98 + + + + + + + + + 1677215 + 16777215 + + + + Qt::LeftToRight + + + Hash: + + + + + + + + 16777215 + 16777215 + + + + Qt::LeftToRight + + + Size: + + + + + + + Size Label + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + 16777215 + 16777215 + + + + Qt::LeftToRight + + + Status: + + + + + + + Status Label + + + Qt::LinksAccessibleByMouse + + + + + + + Priority: + + + + + + + Priority Label + + + Qt::LinksAccessibleByMouse + + + + + + + Type Label + + + + + + + Type: + + + + + + + Hash Label + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + Transfer + + + + + + Sources: + + + + + + + Datarate: + + + + + + + Completed: + + + + + + + Source Label + + + + + + + Datarate Label + + + + + + + Completed Label + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Chunks Label + + + + + + + Chunk size: + + + + + + + Number of Chunks + + + Chunks Number Label + + + + + + + Number of Chunks + + + Chunks: + + + + + + + Remaining Label + + + + + + + Remaining: + + + + + + + + + + Date + + + + + + Download time: + + + + + + + Download Time Label + + + + + + + Qt::Horizontal + + + + 274 + 20 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + :/images/filecomments.png:/images/filecomments.png + + + Comments + + + + + + + + + + retroshare link(s) + + + + + + retroshare link(s) + + + + + + + + + + + + Qt::Horizontal + + + + 351 + 20 + + + + + + + + Copy + + + + + + + + + + + Qt::Horizontal + + + + 321 + 20 + + + + + + + + OK + + + true + + + + + + + Cancel + + + + + + + + + + diff --git a/retroshare-gui/src/gui/FileTransferInfoWidget.cpp b/retroshare-gui/src/gui/FileTransferInfoWidget.cpp new file mode 100644 index 000000000..d79d7e1a2 --- /dev/null +++ b/retroshare-gui/src/gui/FileTransferInfoWidget.cpp @@ -0,0 +1,268 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, csoler + * Copyright (c) 2009, defnax + * Copyright (c) 2009, lsn752 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include "util/misc.h" +#include "FileTransferInfoWidget.h" + +// Variables to decide of display behaviour. Should be adapted to window size. +// +static const int chunk_square_size = 13 ; +static const int text_height = 10 ; // should be set according to the font size +static const int block_sep = 3 ; // separator between blocks +static const int ch_num_size = 50 ; // size of field for chunk number +static const int availability_map_size_X = 400 ;// length of availability bar +static const int availability_map_size_Y = 20 ; // height of availability bar +static const int tab_size = 200 ;// size between tabulated entries + +FileTransferInfoWidget::FileTransferInfoWidget(QWidget * parent, Qt::WFlags f ) +{ + QRect TaskGraphRect = geometry(); + maxWidth = TaskGraphRect.width(); + maxHeight = 0; + pixmap = QPixmap(size()); + pixmap.fill(this, 0, 0); + + downloadedPixmap.load(":images/graph-downloaded.png"); + downloadingPixmap.load(":images/graph-downloading.png"); + notDownloadPixmap.load(":images/graph-notdownload.png"); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +} + +void FileTransferInfoWidget::resizeEvent(QResizeEvent *event) +{ + QRect TaskGraphRect = geometry(); + maxWidth = TaskGraphRect.width(); + + updateDisplay(); +} +void FileTransferInfoWidget::updateDisplay() +{ + //std::cout << "In TaskGraphPainterWidget::updateDisplay()" << std::endl ; + + bool ok=true ; + FileInfo nfo ; + if(!rsFiles->FileDetails(_file_hash, RS_FILE_HINTS_DOWNLOAD, nfo)) + ok = false ; + FileChunksInfo info ; + if(!rsFiles->FileDownloadChunksDetails(_file_hash, info)) + ok = false ; + + //std::cout << "got details for file " << nfo.fname << std::endl ; + +// pixmap = QPixmap(size()); +// pixmap.fill(this, 0, 0); + pixmap = QPixmap(maxWidth, maxHeight); + pixmap.fill(this, 0, 0); + setFixedHeight(maxHeight); + + QPainter painter(&pixmap); + painter.initFrom(this); + + if(ok) + { + int blocks = info.chunks.size() ; + int columns = maxWidth/chunk_square_size; + y = blocks/columns*chunk_square_size; + x = blocks%columns*chunk_square_size; + maxHeight = y+150+info.active_chunks.size()*(block_sep+text_height); // warning: this should be computed from the different size parameter and the number of objects drawn, otherwise the last objects to be displayed will be truncated. + + draw(nfo,info,&painter) ; + } + pixmap2 = pixmap; +} + +void FileTransferInfoWidget::paintEvent(QPaintEvent *event) +{ + //std::cout << "In paint event" << std::endl ; + QStylePainter painter(this); + + painter.drawPixmap(0, 0, pixmap2); + pixmap = pixmap2; +} + +void FileTransferInfoWidget::draw(const FileInfo& nfo,const FileChunksInfo& info,QPainter *painter) +{ + x=0; + y=0; + int blocks = info.chunks.size() ; + uint64_t fileSize = info.file_size ; + uint32_t blockSize = info.chunk_size ; + + if (fileSize%blockSize == 0) blocks--; + QRectF source(0.0, 0.0, 12.0, 12.0); + + painter->setPen(QColor::fromRgb(0,0,0)) ; + y += text_height ; + painter->drawText(0,y,tr("Chunk map") + ":") ; + y += block_sep ; + + // draw the chunk map + // + for (int i=0;i maxWidth - chunk_square_size) + { + x = 0; + y += chunk_square_size; + } + QRectF target(x, y, 12.0, 12.0); + + switch(info.chunks[i]) + { + case FileChunksInfo::CHUNK_DONE: painter->drawPixmap(target, downloadedPixmap, source); + break ; + + case FileChunksInfo::CHUNK_ACTIVE: painter->drawPixmap(target, downloadingPixmap, source); + break ; + + case FileChunksInfo::CHUNK_OUTSTANDING: painter->drawPixmap(target, notDownloadPixmap, source); + break ; + default: ; + } + x += chunk_square_size; + } + y += chunk_square_size ; + + // draw the currently downloaded chunks + // + painter->setPen(QColor::fromRgb(70,70,70)) ; + painter->drawLine(0,y,maxWidth,y) ; + + uint32_t sizeX = 100 ; + uint32_t sizeY = 10 ; + y += block_sep ; + y += text_height ; + painter->setPen(QColor::fromRgb(0,0,0)) ; + painter->drawText(0,y,tr("Active chunks") + ":") ; + y += block_sep ; + + for(uint i=0;isetPen(QColor::fromRgb(0,0,0)) ; + painter->drawText(5,y+text_height,QString::number(info.active_chunks[i].first)) ; + + int size_of_this_chunk = ( info.active_chunks[i].first == info.chunks.size()-1 && ((info.file_size % blockSize)>0) )?(info.file_size % blockSize):blockSize ; + uint32_t s = (uint32_t)rint(sizeX*(size_of_this_chunk - info.active_chunks[i].second)/(float)size_of_this_chunk) ; + + //std::cerr << "chunk " << info.active_chunks[i].first << ": Last received byte: " << size_of_this_chunk - info.active_chunks[i].second << std::endl; + + // Already Downloaded. + // + painter->fillRect(ch_num_size,y,s,sizeY,QColor::fromHsv(200,200,255)) ; + + // Remains to download + // + painter->fillRect(ch_num_size+s,y,sizeX-s,sizeY,QColor::fromHsv(200,50,255)) ; + + // now draw the slices under pending requests + // + std::map >::const_iterator it(info.pending_slices.find(info.active_chunks[i].first)) ; + + if(it != info.pending_slices.end()) + for(uint k=0;ksecond.size();++k) + { + uint32_t s1 = (uint32_t)floor(sizeX*(it->second[k].start)/(float)size_of_this_chunk) ; + uint32_t ss = (uint32_t)ceil(sizeX*(it->second[k].size )/(float)size_of_this_chunk) ; + + painter->fillRect(ch_num_size+s1,y,ss,sizeY,QColor::fromHsv(50,250,250)) ; + + } + + painter->setPen(QColor::fromRgb(0,0,0)) ; + float percent = (size_of_this_chunk - info.active_chunks[i].second)*100.0/size_of_this_chunk ; + + painter->drawText(sizeX+55,y+text_height,QString::number(percent,'f',2) + " %") ; + + y += sizeY+block_sep ; + } + + // draw the availability map + // + painter->setPen(QColor::fromRgb(70,70,70)) ; + painter->drawLine(0,y,maxWidth,y) ; + + y += block_sep ; + y += text_height ; + painter->setPen(QColor::fromRgb(0,0,0)) ; + painter->drawText(0,y,(info.compressed_peer_availability_maps.size() == 1 ? tr("Availability map (%1 active source)") : tr("Availability map (%1 active sources)")).arg(info.compressed_peer_availability_maps.size())) ; + y += block_sep ; + + // Note (for non geeks): the !! operator transforms anything positive into 1 and 0 into 0. + // + int nb_chunks = info.file_size/info.chunk_size + !!(info.file_size % info.chunk_size); + + for(int i=0;i::const_iterator it(info.compressed_peer_availability_maps.begin());it!=info.compressed_peer_availability_maps.end();++it) + nb_src += it->second[chunk_num] ; + + painter->setPen(QColor::fromHsv(200,50*nb_src,200)) ; // the more sources, the more saturated + painter->drawLine(i,y,i,y+availability_map_size_Y) ; + } + + y += block_sep + availability_map_size_Y ; + painter->setPen(QColor::fromRgb(70,70,70)) ; + painter->drawLine(0,y,maxWidth,y) ; + y += block_sep ; + + // various info: + // + + painter->setPen(QColor::fromRgb(0,0,0)) ; + y += text_height ; painter->drawText(0,y,tr("File info") + ":") ; + y += block_sep ; + y += text_height ; painter->drawText(20,y,tr("File hash") + ":") ; painter->drawText(tab_size,y,QString::fromStdString(nfo.hash)) ; + y += block_sep ; + y += text_height ; painter->drawText(20,y,tr("File size") + ":") ; painter->drawText(tab_size,y,QString::number(info.file_size) + " " + tr("bytes") + " " + "(" + misc::friendlyUnit(info.file_size) + ")") ; + y += block_sep ; + y += text_height ; painter->drawText(20,y,tr("Chunk size") + ":") ; painter->drawText(tab_size,y,QString::number(info.chunk_size) + " " + tr("bytes") + " " + "(" + misc::friendlyUnit(info.chunk_size) + ")") ; + y += block_sep ; + y += text_height ; painter->drawText(20,y,tr("Number of chunks") + ":") ; painter->drawText(tab_size,y,QString::number(info.chunks.size())) ; + y += block_sep ; + y += text_height ; painter->drawText(20,y,tr("Transfered") + ":") ; painter->drawText(tab_size,y,QString::number(nfo.transfered) + " " + tr("bytes") + " " + "(" + misc::friendlyUnit(nfo.transfered) + ")") ; + y += block_sep ; + y += text_height ; painter->drawText(20,y,tr("Remaining") + ":") ; painter->drawText(tab_size,y,QString::number(info.file_size - nfo.transfered) + " " + tr("bytes") + " " + "(" + misc::friendlyUnit(info.file_size - nfo.transfered) + ")") ; + y += block_sep ; + y += text_height ; painter->drawText(20,y,tr("Number of sources") + ":") ; painter->drawText(tab_size,y,QString::number(info.compressed_peer_availability_maps.size())) ; + y += block_sep ; + y += text_height ; painter->drawText(20,y,tr("Chunk strategy") + ":") ; painter->drawText(tab_size,y,(info.strategy==FileChunksInfo::CHUNK_STRATEGY_RANDOM)?"Random":"Streaming") ; + y += block_sep ; + y += text_height ; painter->drawText(20,y,tr("Transfer type") + ":") ; + if(info.flags & RS_FILE_HINTS_NETWORK_WIDE) painter->drawText(tab_size,y,tr("Anonymous F2F")) ; + if(info.flags & RS_FILE_HINTS_ASSUME_AVAILABILITY) painter->drawText(tab_size,y,tr("Direct friend transfer / Availability assumed")) ; + y += text_height ; + y += block_sep ; + + maxHeight = y+15; +} + + diff --git a/retroshare-gui/src/gui/FileTransferInfoWidget.h b/retroshare-gui/src/gui/FileTransferInfoWidget.h new file mode 100644 index 000000000..c2f1b88da --- /dev/null +++ b/retroshare-gui/src/gui/FileTransferInfoWidget.h @@ -0,0 +1,61 @@ +#pragma once +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2009, defnax + * Copyright (c) 2009, lsn752 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include "RsAutoUpdatePage.h" + +class FileChunksInfo ; +class FileInfo ; + +class FileTransferInfoWidget : public RsAutoUpdatePage +{ + Q_OBJECT + +public: + FileTransferInfoWidget(QWidget * parent = 0, Qt::WFlags f = 0 ); + + void setFileHash(const std::string& hash) { _file_hash = hash ; } + + virtual void updateDisplay() ; // update from RsAutoUpdateWidget +protected: + void draw(const FileInfo& nfo,const FileChunksInfo& details,QPainter *painter) ; + + virtual void paintEvent(QPaintEvent *); + virtual void resizeEvent(QResizeEvent *event); + +private: + int x; + int y; + int maxWidth; + int maxHeight; + QPixmap pixmap; + QPixmap pixmap2; + QPixmap downloadedPixmap; + QPixmap downloadingPixmap; + QPixmap notDownloadPixmap; + + std::string _file_hash ; +}; + diff --git a/retroshare-gui/src/gui/ForumsDialog.cpp b/retroshare-gui/src/gui/ForumsDialog.cpp new file mode 100644 index 000000000..0912ae407 --- /dev/null +++ b/retroshare-gui/src/gui/ForumsDialog.cpp @@ -0,0 +1,1930 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "ForumsDialog.h" +#include "forums/CreateForum.h" +#include "forums/CreateForumMsg.h" +#include "forums/ForumDetails.h" +#include "forums/EditForumDetails.h" +#include "msgs/MessageComposer.h" +#include "settings/rsharesettings.h" +#include "common/Emoticons.h" +#include "common/RSItemDelegate.h" +#include "common/PopularityDefs.h" +#include "RetroShareLink.h" + +#include +#include + +#include + +//#define DEBUG_FORUMS + +/* Images for context menu icons */ +#define IMAGE_MESSAGE ":/images/folder-draft.png" +#define IMAGE_MESSAGEREPLY ":/images/mail_reply.png" +#define IMAGE_MESSAGEREMOVE ":/images/mail_delete.png" +#define IMAGE_DOWNLOAD ":/images/start.png" +#define IMAGE_DOWNLOADALL ":/images/startall.png" + +/* Images for TreeWidget */ +#define IMAGE_FOLDER ":/images/folder16.png" +#define IMAGE_FOLDERGREEN ":/images/folder_green.png" +#define IMAGE_FOLDERRED ":/images/folder_red.png" +#define IMAGE_FOLDERYELLOW ":/images/folder_yellow.png" +#define IMAGE_FORUM ":/images/konversation16.png" +#define IMAGE_SUBSCRIBE ":/images/edit_add24.png" +#define IMAGE_UNSUBSCRIBE ":/images/cancel.png" +#define IMAGE_INFO ":/images/info16.png" +#define IMAGE_NEWFORUM ":/images/new_forum16.png" +#define IMAGE_FORUMAUTHD ":/images/konv_message2.png" +#define IMAGE_COPYLINK ":/images/copyrslink.png" + +#define VIEW_LAST_POST 0 +#define VIEW_THREADED 1 +#define VIEW_FLAT 2 + +/* Thread constants */ +#define COLUMN_THREAD_COUNT 6 +#define COLUMN_THREAD_TITLE 0 +#define COLUMN_THREAD_READ 1 +#define COLUMN_THREAD_DATE 2 +#define COLUMN_THREAD_AUTHOR 3 +#define COLUMN_THREAD_SIGNED 4 +#define COLUMN_THREAD_CONTENT 5 + +#define COLUMN_THREAD_DATA 0 // column for storing the userdata like msgid and parentid + +#define ROLE_THREAD_MSGID Qt::UserRole +#define ROLE_THREAD_STATUS Qt::UserRole + 1 +#define ROLE_THREAD_MISSING Qt::UserRole + 2 +// no need to copy, don't count in ROLE_THREAD_COUNT +#define ROLE_THREAD_READCHILDREN Qt::UserRole + 3 +#define ROLE_THREAD_UNREADCHILDREN Qt::UserRole + 4 + +#define ROLE_THREAD_COUNT 3 + +#define IS_UNREAD(status) ((status & FORUM_MSG_STATUS_READ) == 0 || (status & FORUM_MSG_STATUS_UNREAD_BY_USER)) +#define IS_FORUM_ADMIN(subscribeFlags) (subscribeFlags & RS_DISTRIB_ADMIN) +#define IS_FORUM_SUBSCRIBED(subscribeFlags) (subscribeFlags & (RS_DISTRIB_ADMIN | RS_DISTRIB_SUBSCRIBED)) + +static int FilterColumnFromComboBox(int nIndex) +{ + switch (nIndex) { + case 0: + return COLUMN_THREAD_DATE; + case 1: + return COLUMN_THREAD_TITLE; + case 2: + return COLUMN_THREAD_AUTHOR; + case 3: + return COLUMN_THREAD_CONTENT; + } + + return COLUMN_THREAD_TITLE; +} + +static int FilterColumnToComboBox(int nIndex) +{ + switch (nIndex) { + case COLUMN_THREAD_DATE: + return 0; + case COLUMN_THREAD_TITLE: + return 1; + case COLUMN_THREAD_AUTHOR: + return 2; + case COLUMN_THREAD_CONTENT: + return 3; + } + + return FilterColumnToComboBox(COLUMN_THREAD_TITLE); +} + +/** Constructor */ +ForumsDialog::ForumsDialog(QWidget *parent) +: RsAutoUpdatePage(1000,parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + m_bProcessSettings = false; + subscribeFlags = 0; + + connect( ui.forumTreeWidget, SIGNAL( treeCustomContextMenuRequested( QPoint ) ), this, SLOT( forumListCustomPopupMenu( QPoint ) ) ); + connect( ui.threadTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( threadListCustomPopupMenu( QPoint ) ) ); + + connect(ui.newForumButton, SIGNAL(clicked()), this, SLOT(newforum())); + connect(ui.newmessageButton, SIGNAL(clicked()), this, SLOT(createmessage())); + connect(ui.newthreadButton, SIGNAL(clicked()), this, SLOT(createthread())); + + connect( ui.forumTreeWidget, SIGNAL( treeCurrentItemChanged(QString) ), this, SLOT( changedForum(QString) ) ); + + 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 () ) ); + + connect(ui.expandButton, SIGNAL(clicked()), this, SLOT(togglethreadview())); + connect(ui.previousButton, SIGNAL(clicked()), this, SLOT(previousMessage())); + connect(ui.nextButton, SIGNAL(clicked()), this, SLOT(nextMessage())); + connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(downloadAllFiles())); + + connect(ui.clearButton, SIGNAL(clicked()), this, SLOT(clearFilter())); + connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged())); + connect(ui.filterColumnComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterColumnChanged())); + + /* Set initial size the splitter */ + QList sizes; + sizes << 300 << width(); // Qt calculates the right sizes + ui.splitter->setSizes(sizes); + + /* Set own item delegate */ + RSItemDelegate *itemDelegate = new RSItemDelegate(this); + itemDelegate->setSpacing(QSize(0, 2)); + ui.threadTreeWidget->setItemDelegate(itemDelegate); + + /* Set header resize modes and initial section sizes */ + QHeaderView * ttheader = ui.threadTreeWidget->header () ; + ttheader->setResizeMode (COLUMN_THREAD_TITLE, QHeaderView::Interactive); + ttheader->resizeSection (COLUMN_THREAD_DATE, 140); + ttheader->resizeSection (COLUMN_THREAD_TITLE, 290); + + ui.threadTreeWidget->sortItems( COLUMN_THREAD_DATE, Qt::DescendingOrder ); + + /* Set text of column "Read" to empty - without this the column has a number as header text */ + QTreeWidgetItem *headerItem = ui.threadTreeWidget->headerItem(); + headerItem->setText(COLUMN_THREAD_READ, ""); + + m_ForumNameFont = QFont("Times", 12, QFont::Bold); + ui.forumName->setFont(m_ForumNameFont); + ui.threadTitle->setFont(m_ForumNameFont); + + /* Initialize group tree */ + ui.forumTreeWidget->initDisplayMenu(ui.displayButton); + + /* create forum tree */ + yourForums = ui.forumTreeWidget->addCategoryItem(tr("Your Forums"), QIcon(IMAGE_FOLDER), true); + subscribedForums = ui.forumTreeWidget->addCategoryItem(tr("Subscribed Forums"), QIcon(IMAGE_FOLDERRED), true); + popularForums = ui.forumTreeWidget->addCategoryItem(tr("Popular Forums"), QIcon(IMAGE_FOLDERGREEN), false); + otherForums = ui.forumTreeWidget->addCategoryItem(tr("Other Forums"), QIcon(IMAGE_FOLDERYELLOW), false); + + lastViewType = -1; + + ui.clearButton->hide(); + + // load settings + processSettings(true); + + /* Set header sizes for the fixed columns and resize modes, must be set after processSettings */ + ttheader->resizeSection (COLUMN_THREAD_READ, 24); + ttheader->setResizeMode (COLUMN_THREAD_READ, QHeaderView::Fixed); + ttheader->hideSection (COLUMN_THREAD_CONTENT); + + ui.progressBar->hide(); + fillThread = NULL; + + insertThreads(); + + ui.threadTreeWidget->installEventFilter(this); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +ForumsDialog::~ForumsDialog() +{ + if (fillThread) { + fillThread->stop(); + delete(fillThread); + fillThread = NULL; + } + + // save settings + processSettings(false); +} + +void ForumsDialog::processSettings(bool bLoad) +{ + m_bProcessSettings = true; + + QHeaderView *pHeader = ui.threadTreeWidget->header () ; + + Settings->beginGroup(QString("ForumsDialog")); + + if (bLoad) { + // load settings + + // expandFiles + bool bValue = Settings->value("expandButton", true).toBool(); + ui.expandButton->setChecked(bValue); + togglethreadview_internal(); + + // filterColumn + int nValue = FilterColumnToComboBox(Settings->value("filterColumn", true).toInt()); + ui.filterColumnComboBox->setCurrentIndex(nValue); + + // index of viewBox + ui.viewBox->setCurrentIndex(Settings->value("viewBox", VIEW_THREADED).toInt()); + + // state of thread tree + pHeader->restoreState(Settings->value("ThreadTree").toByteArray()); + + // state of splitter + ui.splitter->restoreState(Settings->value("Splitter").toByteArray()); + ui.threadSplitter->restoreState(Settings->value("threadSplitter").toByteArray()); + } else { + // save settings + + // state of thread tree + Settings->setValue("ThreadTree", pHeader->saveState()); + + // state of splitter + Settings->setValue("Splitter", ui.splitter->saveState()); + Settings->setValue("threadSplitter", ui.threadSplitter->saveState()); + } + + ui.forumTreeWidget->processSettings(Settings, bLoad); + + Settings->endGroup(); + m_bProcessSettings = false; +} + +void ForumsDialog::forumListCustomPopupMenu( QPoint point ) +{ + QMenu contextMnu( this ); + + QAction *action = contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe to Forum"), this, SLOT(subscribeToForum())); + action->setDisabled (mCurrForumId.empty() || IS_FORUM_SUBSCRIBED(subscribeFlags)); + + action = contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe to Forum"), this, SLOT(unsubscribeToForum())); + action->setEnabled (!mCurrForumId.empty() && IS_FORUM_SUBSCRIBED(subscribeFlags)); + + contextMnu.addSeparator(); + + contextMnu.addAction(QIcon(IMAGE_NEWFORUM), tr("New Forum"), this, SLOT(newforum())); + + action = contextMnu.addAction(QIcon(IMAGE_INFO), tr("Show Forum Details"), this, SLOT(showForumDetails())); + action->setEnabled (!mCurrForumId.empty ()); + + action = contextMnu.addAction(QIcon(":/images/settings16.png"), tr("Edit Forum Details"), this, SLOT(editForumDetails())); + action->setEnabled (!mCurrForumId.empty () && IS_FORUM_ADMIN(subscribeFlags)); + + QAction *restoreKeysAct = new QAction(QIcon(":/images/settings16.png"), tr("Restore Publish Rights for Forum" ), &contextMnu); + connect( restoreKeysAct , SIGNAL( triggered() ), this, SLOT( restoreForumKeys() ) ); + + restoreKeysAct->setEnabled(!mCurrForumId.empty() && !IS_FORUM_ADMIN(subscribeFlags)); + contextMnu.addAction( restoreKeysAct); + + action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyForumLink())); + action->setEnabled(!mCurrForumId.empty()); + + contextMnu.addSeparator(); + + action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark all as read"), this, SLOT(markMsgAsReadAll())); + action->setEnabled (!mCurrForumId.empty () && IS_FORUM_SUBSCRIBED(subscribeFlags)); + + action = contextMnu.addAction(QIcon(":/images/message-mail.png"), tr("Mark all as unread"), this, SLOT(markMsgAsUnreadAll())); + action->setEnabled (!mCurrForumId.empty () && IS_FORUM_SUBSCRIBED(subscribeFlags)); + +#ifdef DEBUG_FORUMS + contextMnu.addSeparator(); + action = contextMnu.addAction("Generate mass data", this, SLOT(generateMassData())); + action->setEnabled (!mCurrForumId.empty() && IS_FORUM_SUBSCRIBED(subscribeFlags)); +#endif + + contextMnu.exec(QCursor::pos()); +} + +void ForumsDialog::threadListCustomPopupMenu( QPoint point ) +{ + if (fillThread) { + return; + } + + QMenu contextMnu( this ); + + QAction *replyAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply" ), &contextMnu ); + connect( replyAct , SIGNAL( triggered() ), this, SLOT( createmessage() ) ); + + QAction *newthreadAct = new QAction(QIcon(IMAGE_DOWNLOADALL), tr( "Start New Thread" ), &contextMnu ); + newthreadAct->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags)); + connect( newthreadAct , SIGNAL( triggered() ), this, SLOT( createthread() ) ); + + QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply to Author" ), &contextMnu ); + connect( replyauthorAct , SIGNAL( triggered() ), this, SLOT( replytomessage() ) ); + + QAction* expandAll = new QAction(tr( "Expand all" ), &contextMnu ); + connect( expandAll , SIGNAL( triggered() ), ui.threadTreeWidget, SLOT (expandAll()) ); + + QAction* collapseAll = new QAction(tr( "Collapse all" ), &contextMnu ); + connect( collapseAll , SIGNAL( triggered() ), ui.threadTreeWidget, SLOT(collapseAll()) ); + + QAction *markMsgAsRead = new QAction(QIcon(":/images/message-mail-read.png"), tr("Mark as read"), &contextMnu); + connect(markMsgAsRead , SIGNAL(triggered()), this, SLOT(markMsgAsRead())); + + QAction *markMsgAsReadChildren = new QAction(QIcon(":/images/message-mail-read.png"), tr("Mark as read") + " (" + tr ("with children") + ")", &contextMnu); + connect(markMsgAsReadChildren, SIGNAL(triggered()), this, SLOT(markMsgAsReadChildren())); + + QAction *markMsgAsUnread = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread"), &contextMnu); + connect(markMsgAsUnread , SIGNAL(triggered()), this, SLOT(markMsgAsUnread())); + + QAction *markMsgAsUnreadChildren = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread") + " (" + tr ("with children") + ")", &contextMnu); + connect(markMsgAsUnreadChildren , SIGNAL(triggered()), this, SLOT(markMsgAsUnreadChildren())); + + if (IS_FORUM_SUBSCRIBED(subscribeFlags)) { + QList Rows; + QList RowsRead; + QList RowsUnread; + int nCount = getSelectedMsgCount (&Rows, &RowsRead, &RowsUnread); + + if (RowsUnread.size() == 0) { + + markMsgAsRead->setDisabled(true); + } + if (RowsRead.size() == 0) { + markMsgAsUnread->setDisabled(true); + } + + bool bHasUnreadChildren = false; + bool bHasReadChildren = false; + int nRowCount = Rows.count(); + for (int i = 0; i < nRowCount; i++) { + if (bHasUnreadChildren || Rows[i]->data(COLUMN_THREAD_DATA, ROLE_THREAD_UNREADCHILDREN).toBool()) { + bHasUnreadChildren = true; + } + if (bHasReadChildren || Rows[i]->data(COLUMN_THREAD_DATA, ROLE_THREAD_READCHILDREN).toBool()) { + bHasReadChildren = true; + } + } + markMsgAsReadChildren->setEnabled(bHasUnreadChildren); + markMsgAsUnreadChildren->setEnabled(bHasReadChildren); + + if (nCount == 1) { + replyAct->setEnabled (true); + replyauthorAct->setEnabled (true); + } else { + replyAct->setDisabled (true); + replyauthorAct->setDisabled (true); + } + } else { + markMsgAsRead->setDisabled(true); + markMsgAsReadChildren->setDisabled(true); + markMsgAsUnread->setDisabled(true); + markMsgAsUnreadChildren->setDisabled(true); + replyAct->setDisabled (true); + replyauthorAct->setDisabled (true); + } + + contextMnu.addAction( replyAct); + contextMnu.addAction( newthreadAct); + contextMnu.addAction( replyauthorAct); + QAction* action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr( "Copy RetroShare Link"), this, SLOT(copyMessageLink())); + action->setEnabled(!mCurrForumId.empty() && !mCurrThreadId.empty()); + contextMnu.addSeparator(); + contextMnu.addAction(markMsgAsRead); + contextMnu.addAction(markMsgAsReadChildren); + contextMnu.addAction(markMsgAsUnread); + contextMnu.addAction(markMsgAsUnreadChildren); + contextMnu.addSeparator(); + contextMnu.addAction( expandAll); + contextMnu.addAction( collapseAll); + + contextMnu.exec(QCursor::pos()); +} + +bool ForumsDialog::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == ui.threadTreeWidget) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent && keyEvent->key() == Qt::Key_Space) { + // Space pressed + QTreeWidgetItem *item = ui.threadTreeWidget->currentItem (); + clickedThread (item, COLUMN_THREAD_READ); + return true; // eat event + } + } + } + // pass the event on to the parent class + return RsAutoUpdatePage::eventFilter(obj, event); +} + +void ForumsDialog::restoreForumKeys(void) +{ + rsForums->forumRestoreKeys(mCurrForumId); +} + +void ForumsDialog::togglethreadview() +{ + // save state of button + Settings->setValueToGroup("ForumsDialog", "expandButton", ui.expandButton->isChecked()); + + togglethreadview_internal(); +} + +void ForumsDialog::togglethreadview_internal() +{ + if (ui.expandButton->isChecked()) { + ui.postText->setVisible(true); + ui.expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + ui.expandButton->setToolTip(tr("Hide")); + } else { + ui.postText->setVisible(false); + ui.expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + ui.expandButton->setToolTip(tr("Expand")); + } +} + +void ForumsDialog::updateDisplay() +{ + std::list forumIds; + std::list::iterator it; + if (!rsForums) + return; + + if (rsForums->forumsChanged(forumIds)) + { + /* update Forums List */ + insertForums(); + + it = std::find(forumIds.begin(), forumIds.end(), mCurrForumId); + if (it != forumIds.end()) + { + /* update threads as well */ + insertThreads(); + } + } +} + +static void CleanupItems (QList &Items) +{ + QList::iterator Item; + for (Item = Items.begin (); Item != Items.end (); Item++) { + if (*Item) { + delete (*Item); + } + } + Items.clear(); +} + +void ForumsDialog::forumInfoToGroupItemInfo(const ForumInfo &forumInfo, GroupItemInfo &groupItemInfo) +{ + groupItemInfo.id = QString::fromStdString(forumInfo.forumId); + groupItemInfo.name = QString::fromStdWString(forumInfo.forumName); + groupItemInfo.description = QString::fromStdWString(forumInfo.forumDesc); + groupItemInfo.popularity = forumInfo.pop; + groupItemInfo.lastpost = QDateTime::fromTime_t(forumInfo.lastPost); + + if (forumInfo.forumFlags & RS_DISTRIB_AUTHEN_REQ) { + groupItemInfo.name += " (" + tr("AUTHD") + ")"; + groupItemInfo.icon = QIcon(IMAGE_FORUMAUTHD); + } else { + groupItemInfo.icon = QIcon(IMAGE_FORUM); + } +} + +void ForumsDialog::insertForums() +{ + std::list forumList; + std::list::iterator it; + if (!rsForums) + { + return; + } + + rsForums->getForumList(forumList); + + QList adminList; + QList subList; + QList popList; + QList otherList; + std::multimap popMap; + + for (it = forumList.begin(); it != forumList.end(); it++) { + /* sort it into Publish (Own), Subscribed, Popular and Other */ + uint32_t flags = it->subscribeFlags; + + GroupItemInfo groupItemInfo; + forumInfoToGroupItemInfo(*it, groupItemInfo); + + if (flags & RS_DISTRIB_ADMIN) { + adminList.push_back(groupItemInfo); + } else if (flags & RS_DISTRIB_SUBSCRIBED) { + /* subscribed forum */ + subList.push_back(groupItemInfo); + } else { + /* rate the others by popularity */ + popMap.insert(std::make_pair(it->pop, groupItemInfo)); + } + } + + /* iterate backwards through popMap - take the top 5 or 10% of list */ + uint32_t popCount = 5; + if (popCount < popMap.size() / 10) + { + popCount = popMap.size() / 10; + } + + uint32_t i = 0; + uint32_t popLimit = 0; + std::multimap::reverse_iterator rit; + for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); rit++, i++); + if (rit != popMap.rend()) { + popLimit = rit->first; + } + + for (rit = popMap.rbegin(); rit != popMap.rend(); rit++) { + if (rit->second.popularity < (int) popLimit) { + otherList.append(rit->second); + } else { + popList.append(rit->second); + } + } + + /* now we can add them in as a tree! */ + ui.forumTreeWidget->fillGroupItems(yourForums, adminList); + ui.forumTreeWidget->fillGroupItems(subscribedForums, subList); + ui.forumTreeWidget->fillGroupItems(popularForums, popList); + ui.forumTreeWidget->fillGroupItems(otherForums, otherList); + + updateMessageSummaryList(""); +} + +void ForumsDialog::changedForum(const QString &id) +{ + mCurrForumId = id.toStdString(); + + insertThreads(); +} + +void ForumsDialog::changedThread () +{ + if (fillThread) { + return; + } + + /* just grab the ids of the current item */ + QTreeWidgetItem *curr = ui.threadTreeWidget->currentItem(); + + if ((!curr) || (!curr->isSelected())) { + mCurrThreadId = ""; + } else { + mCurrThreadId = curr->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString(); + } + insertPost(); +} + +void ForumsDialog::clickedThread (QTreeWidgetItem *item, int column) +{ + if (mCurrForumId.empty() || !IS_FORUM_SUBSCRIBED(subscribeFlags)) { + return; + } + + if (item == NULL) { + return; + } + + if (column == COLUMN_THREAD_READ) { + QList Rows; + Rows.append(item); + uint32_t status = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + setMsgAsReadUnread(Rows, IS_UNREAD(status)); + return; + } +} + +void ForumsDialog::CalculateIconsAndFonts(QTreeWidgetItem *pItem, bool &bHasReadChilddren, bool &bHasUnreadChilddren) +{ + uint32_t status = pItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + + bool bUnread = IS_UNREAD(status); + bool missing = pItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING).toBool(); + + // set icon + if (missing) { + pItem->setIcon(COLUMN_THREAD_READ, QIcon()); + pItem->setIcon(COLUMN_THREAD_TITLE, QIcon()); + } else { + if (bUnread) { + pItem->setIcon(COLUMN_THREAD_READ, QIcon(":/images/message-state-unread.png")); + } else { + pItem->setIcon(COLUMN_THREAD_READ, QIcon(":/images/message-state-read.png")); + } + if (status & FORUM_MSG_STATUS_READ) { + pItem->setIcon(COLUMN_THREAD_TITLE, QIcon()); + } else { + pItem->setIcon(COLUMN_THREAD_TITLE, QIcon(":/images/message-state-new.png")); + } + } + + int nItem; + int nItemCount = pItem->childCount(); + + bool bMyReadChilddren = false; + bool bMyUnreadChilddren = false; + + for (nItem = 0; nItem < nItemCount; nItem++) { + CalculateIconsAndFonts(pItem->child(nItem), bMyReadChilddren, bMyUnreadChilddren); + } + + // set font + for (int i = 0; i < COLUMN_THREAD_COUNT; i++) { + QFont qf = pItem->font(i); + + if (!IS_FORUM_SUBSCRIBED(subscribeFlags)) { + qf.setBold(false); + pItem->setTextColor(i, Qt::black); + } else if (bUnread) { + qf.setBold(true); + pItem->setTextColor(i, Qt::black); + } else if (bMyUnreadChilddren) { + qf.setBold(true); + pItem->setTextColor(i, Qt::gray); + } else { + qf.setBold(false); + pItem->setTextColor(i, Qt::gray); + } + if (missing) { + /* Missing message */ + pItem->setTextColor(i, Qt::darkRed); + } + pItem->setFont(i, qf); + } + + pItem->setData(COLUMN_THREAD_DATA, ROLE_THREAD_READCHILDREN, bHasReadChilddren || bMyReadChilddren); + pItem->setData(COLUMN_THREAD_DATA, ROLE_THREAD_UNREADCHILDREN, bHasUnreadChilddren || bMyUnreadChilddren); + + bHasReadChilddren = bHasReadChilddren || bMyReadChilddren || !bUnread; + bHasUnreadChilddren = bHasUnreadChilddren || bMyUnreadChilddren || bUnread; +} + +void ForumsDialog::CalculateIconsAndFonts(QTreeWidgetItem *pItem /*= NULL*/) +{ + bool bDummy1 = false; + bool bDummy2 = false; + + if (pItem) { + CalculateIconsAndFonts(pItem, bDummy1, bDummy2); + return; + } + + int nItem; + int nItemCount = ui.threadTreeWidget->topLevelItemCount(); + + for (nItem = 0; nItem < nItemCount; nItem++) { + bDummy1 = false; + bDummy2 = false; + CalculateIconsAndFonts(ui.threadTreeWidget->topLevelItem(nItem), bDummy1, bDummy2); + } +} + +void ForumsDialog::fillThreadFinished() +{ +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::fillThreadFinished" << std::endl; +#endif + + // thread has finished + ForumsFillThread *thread = dynamic_cast(sender()); + if (thread) { + if (thread == fillThread) { + // current thread has finished, hide progressbar and release thread + ui.progressBar->hide(); + fillThread = NULL; + } + + if (thread->wasStopped()) { + // thread was stopped +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::fillThreadFinished Thread was stopped" << std::endl; +#endif + } else { +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::fillThreadFinished Add messages" << std::endl; +#endif + /* add all messages in! */ + if (lastViewType != thread->viewType || lastForumID != mCurrForumId) { + ui.threadTreeWidget->clear(); + lastViewType = thread->viewType; + lastForumID = mCurrForumId; + ui.threadTreeWidget->insertTopLevelItems(0, thread->items); + + // clear list + thread->items.clear(); + } else { + FillThreads (thread->items, thread->expandNewMessages, thread->itemToExpand); + + // cleanup list + CleanupItems (thread->items); + } + + QList::iterator Item; + for (Item = thread->itemToExpand.begin(); Item != thread->itemToExpand.end(); Item++) { + if ((*Item)->isHidden() == false) { + (*Item)->setExpanded(true); + } + } + thread->itemToExpand.clear(); + + if (ui.filterPatternLineEdit->text().isEmpty() == false) { + FilterItems(); + } + + insertPost (); + CalculateIconsAndFonts(); + + ui.newthreadButton->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags)); + } + +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::fillThreadFinished Delete thread" << std::endl; +#endif + + thread->deleteLater(); + thread = NULL; + } + +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::fillThreadFinished done" << std::endl; +#endif +} + +void ForumsDialog::fillThreadProgress(int current, int count) +{ + // show fill progress + if (count) { + ui.progressBar->setValue(current * ui.progressBar->maximum() / count); + } +} + +void ForumsDialog::insertThreads() +{ +#ifdef DEBUG_FORUMS + /* get the current Forum */ + std::cerr << "ForumsDialog::insertThreads()" << std::endl; +#endif + + if (fillThread) { +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::insertThreads() stop current fill thread" << std::endl; +#endif + // stop and disconnect current fill thread + ForumsFillThread *thread = fillThread; + fillThread = NULL; + + // disconnect only the signal "progress", the signal "finished" is needed to delete the thread + thread->disconnect(this, SIGNAL(progress(int,int))); + thread->stop(); + + ui.progressBar->hide(); + } + + subscribeFlags = 0; + + ui.newmessageButton->setEnabled (false); + ui.newthreadButton->setEnabled (false); + + ui.postText->clear(); + ui.threadTitle->clear(); + + if (mCurrForumId.empty()) + { + /* not an actual forum - clear */ + ui.threadTreeWidget->clear(); + /* when no Thread selected - clear */ + ui.forumName->clear(); + /* clear last stored forumID */ + mCurrForumId.erase(); + lastForumID.erase(); + +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::insertThreads() Current Thread Invalid" << std::endl; +#endif + + return; + } + + ForumInfo fi; + if (!rsForums->getForumInfo(mCurrForumId, fi)) { + return; + } + + subscribeFlags = fi.subscribeFlags; + ui.forumName->setText(QString::fromStdWString(fi.forumName)); + + ui.progressBar->show(); + + // create fill thread + fillThread = new ForumsFillThread(this); + + // set data + fillThread->forumId = mCurrForumId; + fillThread->filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); + fillThread->subscribeFlags = subscribeFlags; + fillThread->viewType = ui.viewBox->currentIndex(); + if (lastViewType != fillThread->viewType || lastForumID != mCurrForumId) { + fillThread->fillComplete = true; + } + + if (fillThread->viewType == VIEW_FLAT) { + ui.threadTreeWidget->setRootIsDecorated(false); + } else { + ui.threadTreeWidget->setRootIsDecorated(true); + } + + // connect thread + connect(fillThread, SIGNAL(finished()), this, SLOT(fillThreadFinished()), Qt::BlockingQueuedConnection); + connect(fillThread, SIGNAL(progress(int,int)), this, SLOT(fillThreadProgress(int,int))); + +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::insertThreads() Start fill thread" << std::endl; +#endif + + // start thread + fillThread->start(); +} + +void ForumsDialog::FillThreads(QList &ThreadList, bool expandNewMessages, QList &itemToExpand) +{ +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::FillThreads()" << std::endl; +#endif + + int Index = 0; + QTreeWidgetItem *Thread; + QList::iterator NewThread; + + // delete not existing + while (Index < ui.threadTreeWidget->topLevelItemCount ()) { + Thread = ui.threadTreeWidget->topLevelItem (Index); + + // search existing new thread + int Found = -1; + for (NewThread = ThreadList.begin (); NewThread != ThreadList.end (); NewThread++) { + if (Thread->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*NewThread)->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { + // found it + Found = Index; + break; + } + } + if (Found >= 0) { + Index++; + } else { + delete (ui.threadTreeWidget->takeTopLevelItem (Index)); + } + } + + // iterate all new threads + for (NewThread = ThreadList.begin (); NewThread != ThreadList.end (); NewThread++) { + // search existing thread + int Found = -1; + int Count = ui.threadTreeWidget->topLevelItemCount (); + for (Index = 0; Index < Count; Index++) { + Thread = ui.threadTreeWidget->topLevelItem (Index); + if (Thread->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*NewThread)->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { + // found it + Found = Index; + break; + } + } + + if (Found >= 0) { + // set child data + int i; + for (i = 0; i < COLUMN_THREAD_COUNT; i++) { + Thread->setText (i, (*NewThread)->text (i)); + } + for (i = 0; i < ROLE_THREAD_COUNT; i++) { + Thread->setData (COLUMN_THREAD_DATA, Qt::UserRole + i, (*NewThread)->data (COLUMN_THREAD_DATA, Qt::UserRole + i)); + } + + // fill recursive + FillChildren (Thread, *NewThread, expandNewMessages, itemToExpand); + } else { + // add new thread + ui.threadTreeWidget->addTopLevelItem (*NewThread); + Thread = *NewThread; + *NewThread = NULL; + } + + uint32_t status = Thread->data (COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + if (expandNewMessages && IS_UNREAD(status)) { + QTreeWidgetItem *pParent = Thread; + while ((pParent = pParent->parent()) != NULL) { + if (std::find(itemToExpand.begin(), itemToExpand.end(), pParent) == itemToExpand.end()) { + itemToExpand.push_back(pParent); + } + } + } + } + +#ifdef DEBUG_FORUMS + std::cerr << "ForumsDialog::FillThreads() done" << std::endl; +#endif +} + +void ForumsDialog::FillChildren(QTreeWidgetItem *Parent, QTreeWidgetItem *NewParent, bool expandNewMessages, QList &itemToExpand) +{ + int Index = 0; + int NewIndex; + int NewCount = NewParent->childCount(); + + QTreeWidgetItem *Child; + QTreeWidgetItem *NewChild; + + // delete not existing + while (Index < Parent->childCount ()) { + Child = Parent->child (Index); + + // search existing new child + int Found = -1; + int Count = NewParent->childCount(); + for (NewIndex = 0; NewIndex < Count; NewIndex++) { + NewChild = NewParent->child (NewIndex); + if (NewChild->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == Child->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { + // found it + Found = Index; + break; + } + } + if (Found >= 0) { + Index++; + } else { + delete (Parent->takeChild (Index)); + } + } + + // iterate all new children + for (NewIndex = 0; NewIndex < NewCount; NewIndex++) { + NewChild = NewParent->child (NewIndex); + + // search existing child + int Found = -1; + int Count = Parent->childCount(); + for (Index = 0; Index < Count; Index++) { + Child = Parent->child (Index); + if (Child->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == NewChild->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) { + // found it + Found = Index; + break; + } + } + + if (Found >= 0) { + // set child data + int i; + for (i = 0; i < COLUMN_THREAD_COUNT; i++) { + Child->setText (i, NewChild->text (i)); + } + for (i = 0; i < ROLE_THREAD_COUNT; i++) { + Child->setData (COLUMN_THREAD_DATA, Qt::UserRole + i, NewChild->data (COLUMN_THREAD_DATA, Qt::UserRole + i)); + } + + // fill recursive + FillChildren (Child, NewChild, expandNewMessages, itemToExpand); + } else { + // add new child + Child = NewParent->takeChild(NewIndex); + Parent->addChild (Child); + NewIndex--; + NewCount--; + } + + uint32_t status = Child->data (COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + if (expandNewMessages && IS_UNREAD(status)) { + QTreeWidgetItem *pParent = Child; + while ((pParent = pParent->parent()) != NULL) { + if (std::find(itemToExpand.begin(), itemToExpand.end(), pParent) == itemToExpand.end()) { + itemToExpand.push_back(pParent); + } + } + } + } +} + +void ForumsDialog::insertPost() +{ + if ((mCurrForumId == "") || (mCurrThreadId == "")) + { + ui.postText->setText(""); + ui.threadTitle->setText(""); + ui.previousButton->setEnabled(false); + ui.nextButton->setEnabled(false); + ui.newmessageButton->setEnabled (false); + return; + } + + QTreeWidgetItem *curr = ui.threadTreeWidget->currentItem(); + if (curr) { + QTreeWidgetItem *Parent = curr->parent (); + int Index = Parent ? Parent->indexOfChild (curr) : ui.threadTreeWidget->indexOfTopLevelItem (curr); + int Count = Parent ? Parent->childCount () : ui.threadTreeWidget->topLevelItemCount (); + ui.previousButton->setEnabled (Index > 0); + ui.nextButton->setEnabled (Index < Count - 1); + } else { + // there is something wrong + ui.previousButton->setEnabled(false); + ui.nextButton->setEnabled(false); + return; + } + + ui.newmessageButton->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags) && mCurrThreadId.empty() == false); + + /* get the Post */ + ForumMsgInfo msg; + if (!rsForums->getForumMessage(mCurrForumId, mCurrThreadId, msg)) + { + ui.postText->setText(""); + return; + } + + bool bSetToReadOnActive = Settings->getForumMsgSetToReadOnActivate(); + uint32_t status = curr->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + + QList Row; + Row.append(curr); + if (status & FORUM_MSG_STATUS_READ) { + if (bSetToReadOnActive && (status & FORUM_MSG_STATUS_UNREAD_BY_USER)) { + /* set to read */ + setMsgAsReadUnread(Row, true); + } + } else { + /* set to read */ + if (bSetToReadOnActive) { + setMsgAsReadUnread(Row, true); + } else { + /* set to unread by user */ + setMsgAsReadUnread(Row, false); + } + } + + QString extraTxt = RsHtml::formatText(QString::fromStdWString(msg.msg), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); + + ui.postText->setHtml(extraTxt); + ui.threadTitle->setText(QString::fromStdWString(msg.title)); +} + +void ForumsDialog::previousMessage () +{ + QTreeWidgetItem *Item = ui.threadTreeWidget->currentItem (); + if (Item == NULL) { + return; + } + + QTreeWidgetItem *Parent = Item->parent (); + int Index = Parent ? Parent->indexOfChild (Item) : ui.threadTreeWidget->indexOfTopLevelItem (Item); + if (Index > 0) { + QTreeWidgetItem *Previous = Parent ? Parent->child (Index - 1) : ui.threadTreeWidget->topLevelItem (Index - 1); + if (Previous) { + ui.threadTreeWidget->setCurrentItem (Previous); + } + } +} + +void ForumsDialog::nextMessage () +{ + QTreeWidgetItem *Item = ui.threadTreeWidget->currentItem (); + if (Item == NULL) { + return; + } + + QTreeWidgetItem *Parent = Item->parent (); + int Index = Parent ? Parent->indexOfChild (Item) : ui.threadTreeWidget->indexOfTopLevelItem (Item); + int Count = Parent ? Parent->childCount () : ui.threadTreeWidget->topLevelItemCount (); + if (Index < Count - 1) { + QTreeWidgetItem *Next = Parent ? Parent->child (Index + 1) : ui.threadTreeWidget->topLevelItem (Index + 1); + if (Next) { + ui.threadTreeWidget->setCurrentItem (Next); + } + } +} + +void ForumsDialog::downloadAllFiles() +{ + QStringList urls; + if (RsHtml::findAnchors(ui.postText->toHtml(), urls) == false) { + return; + } + + if (urls.count() == 0) { + return; + } + + RetroShareLink::process(urls, RetroShareLink::TYPE_FILE, true); +} + +// TODO +#if 0 +void ForumsDialog::removemessage() +{ + //std::cerr << "ForumsDialog::removemessage()" << std::endl; + std::string cid, mid; + if (!getCurrentMsg(cid, mid)) + { + //std::cerr << "ForumsDialog::removemessage()"; + //std::cerr << " No Message selected" << std::endl; + return; + } + + rsMsgs -> MessageDelete(mid); +} +#endif + +/* get selected messages + the messages tree is single selected, but who knows ... */ +int ForumsDialog::getSelectedMsgCount(QList *pRows, QList *pRowsRead, QList *pRowsUnread) +{ + if (pRowsRead) pRowsRead->clear(); + if (pRowsUnread) pRowsUnread->clear(); + + QList selectedItems = ui.threadTreeWidget->selectedItems(); + for(QList::iterator it = selectedItems.begin(); it != selectedItems.end(); it++) { + if (pRows) pRows->append(*it); + if (pRowsRead || pRowsUnread) { + uint32_t status = (*it)->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + if (IS_UNREAD(status)) { + if (pRowsUnread) pRowsUnread->append(*it); + } else { + if (pRowsRead) pRowsRead->append(*it); + } + } + } + + return selectedItems.size(); +} + +void ForumsDialog::setMsgAsReadUnread(QList &Rows, bool bRead) +{ + QList::iterator Row; + std::list changedItems; + + for (Row = Rows.begin(); Row != Rows.end(); Row++) { + if ((*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING).toBool()) { + /* Missing message */ + continue; + } + + uint32_t status = (*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + + /* set always as read ... */ + uint32_t statusNew = status | FORUM_MSG_STATUS_READ; + if (bRead) { + /* ... and as read by user */ + statusNew &= ~FORUM_MSG_STATUS_UNREAD_BY_USER; + } else { + /* ... and as unread by user */ + statusNew |= FORUM_MSG_STATUS_UNREAD_BY_USER; + } + if (status != statusNew) { + std::string msgId = (*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString(); + rsForums->setMessageStatus(mCurrForumId, msgId, statusNew, FORUM_MSG_STATUS_READ | FORUM_MSG_STATUS_UNREAD_BY_USER); + + (*Row)->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, statusNew); + + QTreeWidgetItem *parentItem = *Row; + while (parentItem->parent()) { + parentItem = parentItem->parent(); + } + if (std::find(changedItems.begin(), changedItems.end(), parentItem) == changedItems.end()) { + changedItems.push_back(parentItem); + } + } + } + + if (changedItems.size()) { + for (std::list::iterator it = changedItems.begin(); it != changedItems.end(); it++) { + CalculateIconsAndFonts(*it); + } + updateMessageSummaryList(mCurrForumId); + } +} + +void ForumsDialog::markMsgAsReadUnread (bool bRead, bool bChildren, bool bForum) +{ + if (mCurrForumId.empty() || !IS_FORUM_SUBSCRIBED(subscribeFlags)) { + return; + } + + /* get selected messages */ + QList Rows; + if (bForum) { + int itemCount = ui.threadTreeWidget->topLevelItemCount(); + for (int item = 0; item < itemCount; item++) { + Rows.push_back(ui.threadTreeWidget->topLevelItem(item)); + } + } else { + getSelectedMsgCount (&Rows, NULL, NULL); + } + + if (bChildren) { + /* add children */ + QList AllRows; + + while (Rows.isEmpty() == false) { + QTreeWidgetItem *pRow = Rows.takeFirst(); + + /* add only items with the right state or with not FORUM_MSG_STATUS_READ */ + uint32_t status = pRow->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt(); + if (IS_UNREAD(status) == bRead || (status & FORUM_MSG_STATUS_READ) == 0) { + AllRows.append(pRow); + } + + for (int i = 0; i < pRow->childCount(); i++) { + /* add child to main list and let the main loop do the work */ + Rows.append(pRow->child(i)); + } + } + + if (AllRows.isEmpty()) { + /* nothing to do */ + return; + } + + setMsgAsReadUnread (AllRows, bRead); + + return; + } + + setMsgAsReadUnread (Rows, bRead); +} + +void ForumsDialog::markMsgAsRead() +{ + markMsgAsReadUnread(true, false, false); +} + +void ForumsDialog::markMsgAsReadChildren() +{ + markMsgAsReadUnread(true, true, false); +} + +void ForumsDialog::markMsgAsReadAll() +{ + markMsgAsReadUnread(true, true, true); +} + +void ForumsDialog::markMsgAsUnread() +{ + markMsgAsReadUnread(false, false, false); +} + +void ForumsDialog::markMsgAsUnreadChildren() +{ + markMsgAsReadUnread(false, true, false); +} + +void ForumsDialog::markMsgAsUnreadAll() +{ + markMsgAsReadUnread(false, true, true); +} + +void ForumsDialog::copyForumLink() +{ + if (mCurrForumId.empty()) { + return; + } + + ForumInfo fi; + if (rsForums->getForumInfo(mCurrForumId, fi)) { + RetroShareLink link; + if (link.createForum(fi.forumId, "")) { + std::vector urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } + } +} + +void ForumsDialog::copyMessageLink() +{ + if (mCurrForumId.empty() || mCurrThreadId.empty()) { + return; + } + + ForumInfo fi; + if (rsForums->getForumInfo(mCurrForumId, fi)) { + RetroShareLink link; + if (link.createForum(mCurrForumId, mCurrThreadId)) { + std::vector urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } + } +} + +void ForumsDialog::newforum() +{ + CreateForum cf (this); + cf.exec (); +} + +void ForumsDialog::createmessage() +{ + if (mCurrForumId.empty () || !IS_FORUM_SUBSCRIBED(subscribeFlags)) { + return; + } + + CreateForumMsg *cfm = new CreateForumMsg(mCurrForumId, mCurrThreadId); + cfm->show(); + + /* window will destroy itself! */ +} + +void ForumsDialog::createthread() +{ + if (mCurrForumId.empty ()) { + QMessageBox::information(this, tr("RetroShare"), tr("No Forum Selected!")); + return; + } + + CreateForumMsg *cfm = new CreateForumMsg(mCurrForumId, ""); + cfm->setWindowTitle(tr("Start New Thread")); + cfm->show(); + + /* window will destroy itself! */ +} + +void ForumsDialog::subscribeToForum() +{ + forumSubscribe(true); +} + +void ForumsDialog::unsubscribeToForum() +{ + forumSubscribe(false); +} + +void ForumsDialog::forumSubscribe(bool subscribe) +{ + if (mCurrForumId.empty()) { + return; + } + + rsForums->forumSubscribe(mCurrForumId, subscribe); +} + +void ForumsDialog::showForumDetails() +{ + if (mCurrForumId.empty()) { + return; + } + + ForumDetails fui; + + fui.showDetails (mCurrForumId); + fui.exec (); +} + +void ForumsDialog::editForumDetails() +{ + if (mCurrForumId.empty()) { + return; + } + + EditForumDetails editUi(mCurrForumId, this); + editUi.exec(); +} + +void ForumsDialog::replytomessage() +{ + if (mCurrForumId.empty()) { + return; + } + + std::string fId = mCurrForumId; + std::string pId = mCurrThreadId; + + ForumMsgInfo msgInfo ; + rsForums->getForumMessage(fId,pId,msgInfo) ; + + if (rsPeers->getPeerName(msgInfo.srcId) !="") + { + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + nMsgDialog->insertTitleText(QString::fromStdWString(msgInfo.title), MessageComposer::REPLY); + + QTextDocument doc ; + doc.setHtml(QString::fromStdWString(msgInfo.msg)) ; + + nMsgDialog->insertPastedText(doc.toPlainText()); + nMsgDialog->addRecipient(MessageComposer::TO, msgInfo.srcId, false); + nMsgDialog->show(); + nMsgDialog->activateWindow(); + + /* window will destroy itself! */ + } + else + { + QMessageBox::information(this, tr("RetroShare"),tr("You cant reply a Anonymous Author")); + } +} + +void ForumsDialog::filterRegExpChanged() +{ +// QRegExp regExp(ui.filterPatternLineEdit->text(), Qt::CaseInsensitive , QRegExp::FixedString); +// proxyModel->setFilterRegExp(regExp); + + QString text = ui.filterPatternLineEdit->text(); + + if (text.isEmpty()) { + ui.clearButton->hide(); + } else { + ui.clearButton->show(); + } + + FilterItems(); +} + +/* clear Filter */ +void ForumsDialog::clearFilter() +{ + ui.filterPatternLineEdit->clear(); + ui.filterPatternLineEdit->setFocus(); +} + +void ForumsDialog::changedViewBox() +{ + if (m_bProcessSettings) { + return; + } + + // save index + Settings->setValueToGroup("ForumsDialog", "viewBox", ui.viewBox->currentIndex()); + + insertThreads(); +} + +void ForumsDialog::filterColumnChanged() +{ + if (m_bProcessSettings) { + return; + } + + int filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); + if (filterColumn == COLUMN_THREAD_CONTENT) { + // need content ... refill + insertThreads(); + } else { + FilterItems(); + } + + // save index + Settings->setValueToGroup("ForumsDialog", "filterColumn", filterColumn); +} + +void ForumsDialog::FilterItems() +{ + QString sPattern = ui.filterPatternLineEdit->text(); + int filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); + + int nCount = ui.threadTreeWidget->topLevelItemCount (); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + FilterItem(ui.threadTreeWidget->topLevelItem(nIndex), sPattern, filterColumn); + } +} + +bool ForumsDialog::FilterItem(QTreeWidgetItem *pItem, QString &sPattern, int filterColumn) +{ + bool bVisible = true; + + if (sPattern.isEmpty() == false) { + if (pItem->text(filterColumn).contains(sPattern, Qt::CaseInsensitive) == false) { + bVisible = false; + } + } + + int nVisibleChildCount = 0; + int nCount = pItem->childCount(); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + if (FilterItem(pItem->child(nIndex), sPattern, filterColumn)) { + nVisibleChildCount++; + } + } + + if (bVisible || nVisibleChildCount) { + pItem->setHidden(false); + } else { + pItem->setHidden(true); + } + + return (bVisible || nVisibleChildCount); +} + +void ForumsDialog::updateMessageSummaryList(std::string forumId) +{ + QTreeWidgetItem *items[2] = { yourForums, subscribedForums }; + + for (int item = 0; item < 2; item++) { + int child; + int childCount = items[item]->childCount(); + for (child = 0; child < childCount; child++) { + QTreeWidgetItem *childItem = items[item]->child(child); + std::string childId = ui.forumTreeWidget->itemId(childItem).toStdString(); + if (childId.empty()) { + continue; + } + + if (forumId.empty() || childId == forumId) { + /* calculate unread messages */ + unsigned int newMessageCount = 0; + unsigned int unreadMessageCount = 0; + rsForums->getMessageCount(childId, newMessageCount, unreadMessageCount); + + ui.forumTreeWidget->setUnreadCount(childItem, unreadMessageCount); + + if (forumId.empty() == false) { + /* Calculate only this forum */ + break; + } + } + } + } +} + +bool ForumsDialog::navigate(const std::string& forumId, const std::string& msgId) +{ + if (forumId.empty()) { + return false; + } + + if (ui.forumTreeWidget->activateId(QString::fromStdString(forumId), msgId.empty()) == NULL) { + return false; + } + + /* Threads are filled in changedForum */ + if (mCurrForumId != forumId) { + return false; + } + + if (msgId.empty()) { + return true; + } + + /* Search exisiting item */ + QTreeWidgetItemIterator itemIterator(ui.threadTreeWidget); + QTreeWidgetItem *item = NULL; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString() == msgId) { + ui.threadTreeWidget->setCurrentItem(item); + ui.threadTreeWidget->setFocus(); + return true; + } + } + + return false; +} + +void ForumsDialog::generateMassData() +{ +#ifdef DEBUG_FORUMS + if (mCurrForumId.empty ()) { + return; + } + + if (QMessageBox::question(this, "Generate mass data", "Do you really want to generate mass data ?", QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::No) { + return; + } + + for (int thread = 1; thread < 1000; thread++) { + ForumMsgInfo threadInfo; + threadInfo.forumId = mCurrForumId; + threadInfo.title = QString("Test %1").arg(thread, 3, 10, QChar('0')).toStdWString(); + threadInfo.msg = QString("That is only a test").toStdWString(); + + if (rsForums->ForumMessageSend(threadInfo) == false) { + return; + } + + for (int msg = 1; msg < 3; msg++) { + ForumMsgInfo msgInfo; + msgInfo.forumId = mCurrForumId; + msgInfo.threadId = threadInfo.msgId; + msgInfo.parentId = threadInfo.msgId; + msgInfo.title = threadInfo.title; + msgInfo.msg = threadInfo.msg; + + if (rsForums->ForumMessageSend(msgInfo) == false) { + return; + } + } + } +#endif +} + +// ForumsFillThread +ForumsFillThread::ForumsFillThread(ForumsDialog *parent) + : QThread(parent) +{ + stopped = false; + + expandNewMessages = Settings->getExpandNewMessages(); + fillComplete = false; + + filterColumn = 0; + subscribeFlags = 0; + viewType = 0; +} + +ForumsFillThread::~ForumsFillThread() +{ +#ifdef DEBUG_FORUMS + std::cerr << "ForumsFillThread::~ForumsFillThread" << std::endl; +#endif + // remove all items (when items are available, the thread was terminated) + CleanupItems (items); + itemToExpand.clear(); +} + +void ForumsFillThread::stop() +{ + stopped = true; +} + +void ForumsFillThread::run() +{ +#ifdef DEBUG_FORUMS + std::cerr << "ForumsFillThread::run()" << std::endl; +#endif + + uint32_t status; + + std::list threads; + std::list::iterator tit; + rsForums->getForumThreadList(forumId, threads); + + bool flatView = false; + bool useChildTS = false; + switch(viewType) + { + case VIEW_LAST_POST: + useChildTS = true; + break; + case VIEW_FLAT: + flatView = true; + break; + case VIEW_THREADED: + break; + } + + int count = threads.size(); + int pos = 0; + + for (tit = threads.begin(); tit != threads.end(); tit++) + { + if (stopped) { + break; + } + +#ifdef DEBUG_FORUMS + std::cerr << "ForumsFillThread::run() Adding TopLevel Thread: mId: " << tit->msgId << std::endl; +#endif + + ForumMsgInfo msginfo; + if (rsForums->getForumMessage(forumId, tit->msgId, msginfo) == false) { +#ifdef DEBUG_FORUMS + std::cerr << "ForumsFillThread::run() Failed to Get Msg" << std::endl; +#endif + continue; + } + + /* add Msg */ + /* setup + * + */ + + QTreeWidgetItem *item = new QTreeWidgetItem(); + + QString text; + + { + QDateTime qtime; + if (useChildTS) + qtime.setTime_t(tit->childTS); + else + qtime.setTime_t(tit->ts); + + text = qtime.toString("yyyy-MM-dd hh:mm:ss"); + if (useChildTS) + { + QDateTime qtime2; + qtime2.setTime_t(tit->ts); + QString timestamp2 = qtime2.toString("yyyy-MM-dd hh:mm:ss"); + text += " / "; + text += timestamp2; + } + item->setText(COLUMN_THREAD_DATE, text); + } + + item->setText(COLUMN_THREAD_TITLE, QString::fromStdWString(tit->title)); + + text = QString::fromStdString(rsPeers->getPeerName(msginfo.srcId)); + if (text.isEmpty()) + { + item->setText(COLUMN_THREAD_AUTHOR, tr("Anonymous")); + } + else + { + item->setText(COLUMN_THREAD_AUTHOR, text); + } + + if (msginfo.msgflags & RS_DISTRIB_AUTHEN_REQ) + { + item->setText(COLUMN_THREAD_SIGNED, tr("signed")); + item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signed.png")); + } + else + { + item->setText(COLUMN_THREAD_SIGNED, tr("none")); + item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signature-unknown.png")); + } + + if (filterColumn == COLUMN_THREAD_CONTENT) { + // need content for filter + QTextDocument doc; + doc.setHtml(QString::fromStdWString(msginfo.msg)); + item->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" "))); + } + + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(tit->msgId)); + + if (IS_FORUM_SUBSCRIBED(subscribeFlags) && !(msginfo.msgflags & RS_DISTRIB_MISSING_MSG)) { + rsForums->getMessageStatus(msginfo.forumId, msginfo.msgId, status); + } else { + // show message as read + status = FORUM_MSG_STATUS_READ; + } + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, status); + + item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, (msginfo.msgflags & RS_DISTRIB_MISSING_MSG) ? true : false); + + std::list threadlist; + threadlist.push_back(item); + + while (threadlist.size() > 0) + { + if (stopped) { + break; + } + + /* get children */ + QTreeWidgetItem *parent = threadlist.front(); + threadlist.pop_front(); + std::string pId = parent->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString(); + + std::list msgs; + std::list::iterator mit; + +#ifdef DEBUG_FORUMS + std::cerr << "ForumsFillThread::run() Getting Children of : " << pId << std::endl; +#endif + + if (rsForums->getForumThreadMsgList(forumId, pId, msgs)) + { +#ifdef DEBUG_FORUMS + std::cerr << "ForumsFillThread::run() #Children " << msgs.size() << std::endl; +#endif + + /* iterate through child */ + for(mit = msgs.begin(); mit != msgs.end(); mit++) + { +#ifdef DEBUG_FORUMS + std::cerr << "ForumsFillThread::run() adding " << mit->msgId << std::endl; +#endif + + ForumMsgInfo msginfo; + if (rsForums->getForumMessage(forumId, mit->msgId, msginfo) == false) { +#ifdef DEBUG_FORUMS + std::cerr << "ForumsFillThread::run() Failed to Get Msg" << std::endl; +#endif + continue; + } + + QTreeWidgetItem *child = NULL; + if (flatView) + { + child = new QTreeWidgetItem(); + } + else + { + child = new QTreeWidgetItem(parent); + } + + { + QDateTime qtime; + if (useChildTS) + qtime.setTime_t(mit->childTS); + else + qtime.setTime_t(mit->ts); + + text = qtime.toString("yyyy-MM-dd hh:mm:ss"); + + if (useChildTS) + { + QDateTime qtime2; + qtime2.setTime_t(mit->ts); + QString timestamp2 = qtime2.toString("yyyy-MM-dd hh:mm:ss"); + text += " / "; + text += timestamp2; + } + child->setText(COLUMN_THREAD_DATE, text); + } + + child->setText(COLUMN_THREAD_TITLE, QString::fromStdWString(mit->title)); + + text = QString::fromStdString(rsPeers->getPeerName(msginfo.srcId)); + if (text.isEmpty()) + { + child->setText(COLUMN_THREAD_AUTHOR, tr("Anonymous")); + } + else + { + child->setText(COLUMN_THREAD_AUTHOR, text); + } + + if (msginfo.msgflags & RS_DISTRIB_AUTHEN_REQ) + { + child->setText(COLUMN_THREAD_SIGNED, tr("signed")); + child->setIcon(COLUMN_THREAD_SIGNED,(QIcon(":/images/mail-signed.png"))); + } + else + { + child->setText(COLUMN_THREAD_SIGNED, tr("none")); + child->setIcon(COLUMN_THREAD_SIGNED,(QIcon(":/images/mail-signature-unknown.png"))); + } + + if (filterColumn == COLUMN_THREAD_CONTENT) { + // need content for filter + QTextDocument doc; + doc.setHtml(QString::fromStdWString(msginfo.msg)); + child->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" "))); + } + + child->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(mit->msgId)); + + if (IS_FORUM_SUBSCRIBED(subscribeFlags) && !(msginfo.msgflags & RS_DISTRIB_MISSING_MSG)) { + rsForums->getMessageStatus(msginfo.forumId, msginfo.msgId, status); + } else { + // show message as read + status = FORUM_MSG_STATUS_READ; + } + child->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, status); + + child->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, (msginfo.msgflags & RS_DISTRIB_MISSING_MSG) ? true : false); + + if (fillComplete && expandNewMessages && IS_UNREAD(status)) { + QTreeWidgetItem *pParent = child; + while ((pParent = pParent->parent()) != NULL) { + if (std::find(itemToExpand.begin(), itemToExpand.end(), pParent) == itemToExpand.end()) { + itemToExpand.push_back(pParent); + } + } + } + + /* setup child */ + threadlist.push_back(child); + + if (flatView) + { + items.append(child); + } + } + } + } + + /* add to list */ + items.append(item); + + emit progress(++pos, count); + } + +#ifdef DEBUG_FORUMS + std::cerr << "ForumsFillThread::run() stopped: " << (wasStopped() ? "yes" : "no") << std::endl; +#endif +} diff --git a/retroshare-gui/src/gui/ForumsDialog.h b/retroshare-gui/src/gui/ForumsDialog.h new file mode 100644 index 000000000..8b9074f0e --- /dev/null +++ b/retroshare-gui/src/gui/ForumsDialog.h @@ -0,0 +1,177 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _FORUMSDIALOG_H +#define _FORUMSDIALOG_H + +#include + +#include "mainpage.h" +#include "RsAutoUpdatePage.h" +#include "ui_ForumsDialog.h" + +class ForumInfo; +class ForumsFillThread; + +class ForumsDialog : public RsAutoUpdatePage +{ + Q_OBJECT + +public: + ForumsDialog(QWidget *parent = 0); + ~ForumsDialog(); + + bool navigate(const std::string& forumId, const std::string& msgId); + + /* overloaded from RsAuthUpdatePage */ + virtual void updateDisplay(); + +protected: + bool eventFilter(QObject *obj, QEvent *ev); + +private slots: + /** Create the context popup menu and it's submenus */ + void forumListCustomPopupMenu( QPoint point ); + void threadListCustomPopupMenu( QPoint point ); + void restoreForumKeys(); + void newforum(); + + void changedForum(const QString &id); + void changedThread(); + void clickedThread (QTreeWidgetItem *item, int column); + + void replytomessage(); + //void print(); + //void printpreview(); + + //void removemessage(); + void markMsgAsRead(); + void markMsgAsReadChildren(); + void markMsgAsReadAll(); + void markMsgAsUnread(); + void markMsgAsUnreadAll(); + void markMsgAsUnreadChildren(); + void copyForumLink(); + void copyMessageLink(); + + /* handle splitter */ + void togglethreadview(); + + void createthread(); + void createmessage(); + + void subscribeToForum(); + void unsubscribeToForum(); + + void showForumDetails(); + void editForumDetails(); + + void previousMessage (); + void nextMessage (); + void downloadAllFiles(); + + void changedViewBox(); + + void filterColumnChanged(); + void filterRegExpChanged(); + void clearFilter(); + + void generateMassData(); + + void fillThreadFinished(); + void fillThreadProgress(int current, int count); + +private: + void insertForums(); + void insertThreads(); + void insertPost(); + void updateMessageSummaryList(std::string forumId); + void forumInfoToGroupItemInfo(const ForumInfo &forumInfo, GroupItemInfo &groupItemInfo); + + void forumSubscribe(bool subscribe); + void FillThreads(QList &ThreadList, bool bExpandNewMessages, QList &itemToExpand); + void FillChildren(QTreeWidgetItem *Parent, QTreeWidgetItem *NewParent, bool bExpandNewMessages, QList &itemToExpand); + + int getSelectedMsgCount(QList *pRows, QList *pRowsRead, QList *pRowsUnread); + void setMsgAsReadUnread(QList &Rows, bool bRead); + void markMsgAsReadUnread(bool bRead, bool bChildren, bool bForum); + void CalculateIconsAndFonts(QTreeWidgetItem *pItem = NULL); + void CalculateIconsAndFonts(QTreeWidgetItem *pItem, bool &bHasReadChilddren, bool &bHasUnreadChilddren); + + void processSettings(bool bLoad); + void togglethreadview_internal(); + + void FilterItems(); + bool FilterItem(QTreeWidgetItem *pItem, QString &sPattern, int filterColumn); + + bool m_bProcessSettings; + + QTreeWidgetItem *yourForums; + QTreeWidgetItem *subscribedForums; + QTreeWidgetItem *popularForums; + QTreeWidgetItem *otherForums; + + std::string mCurrForumId; + std::string mCurrThreadId; + int subscribeFlags; + + QFont m_ForumNameFont; + int lastViewType; + std::string lastForumID; + + ForumsFillThread *fillThread; + + /** Qt Designer generated object */ + Ui::ForumsDialog ui; +}; + +class ForumsFillThread : public QThread +{ + Q_OBJECT + +public: + ForumsFillThread(ForumsDialog *parent); + ~ForumsFillThread(); + + void run(); + void stop(); + bool wasStopped() { return stopped; } + +signals: + void progress(int current, int count); + +public: + std::string forumId; + int filterColumn; + int subscribeFlags; + bool fillComplete; + int viewType; + bool expandNewMessages; + + QList items; + QList itemToExpand; + +private: + volatile bool stopped; +}; + +#endif + diff --git a/retroshare-gui/src/gui/ForumsDialog.ui b/retroshare-gui/src/gui/ForumsDialog.ui new file mode 100644 index 000000000..4193d7862 --- /dev/null +++ b/retroshare-gui/src/gui/ForumsDialog.ui @@ -0,0 +1,1269 @@ + + + ForumsDialog + + + + 0 + 0 + 732 + 420 + + + + + 0 + 2 + + + + + 60 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::DefaultContextMenu + + + + 9 + + + 9 + + + + + Qt::Horizontal + + + + + 300 + 300 + + + + QFrame#frame{border: none;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + QFrame#chheaderframe{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + 0 + + + + + + 24 + 24 + + + + + + + :/images/konversation.png + + + true + + + + + + + + Arial + 10 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + + + + + Qt::Horizontal + + + + 123 + 13 + + + + + + + + Qt::NoFocus + + + Display + + + QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + } + + QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open { + position: relative; + top: 2px; left: 2px; /* shift the arrow by 2 px */ + } + + QPushButton:hover { + border: 1px solid #CCCCCC; + } + + + + :/images/looknfeel.png:/images/looknfeel.png + + + true + + + + + + + Qt::NoFocus + + + Create Forum + + + + :/images/new_forum16.png:/images/new_forum16.png + + + true + + + + + + + + + + + 0 + 0 + + + + + 9 + + + + + -1 + -1 + + + + + + + + + Qt::Vertical + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 10 + 75 + true + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + + + + 2 + 0 + + + + + 0 + 0 + + + + + 16777215 + 1677215 + + + + +border: 2px solid #CCCCCC; +border-radius:6px; +background: white; + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + + + + + + 9 + + + + Qt::CustomContextMenu + + + true + + + true + + + + Title + + + + + + + + + :/images/message-state-header.png:/images/message-state-header.png + + + + + Date + + + + + Author + + + + + Signed + + + + + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + + + QLabel#threadTitle{ +border: 2px solid #CCCCCC; +border-radius: 6px; +background: white;} + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + false + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + Previous Thread + + + + + + + :/images/back.png:/images/back.png + + + + + + + false + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + Next Thread + + + + + + + :/images/forward.png:/images/forward.png + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + + + + + :/images/edit_remove24.png:/images/edit_remove24.png + + + true + + + true + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + Download all files + + + + :/images/down.png:/images/down.png + + + + + + + + + + 0 + 32 + + + + QFrame#frame_2{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + 2 + + + + + + + + :/images/find-16.png + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + MS Shell Dlg 2 + + + + Qt::NoFocus + + + Reset + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + + + 0 + 0 + + + + + MS Shell Dlg 2 + + + + 1 + + + + Date + + + + + Title + + + + + Author + + + + + Content + + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + Reply Message + + + + :/images/mail_reply.png:/images/mail_reply.png + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + Start new Thread for Selected Forum + + + + :/images/mail_new.png:/images/mail_new.png + + + true + + + + + + + + + + + 16777215 + 10 + + + + 1000 + + + 0 + + + false + + + + + + + + + 0 + 10 + + + + + 9 + + + + true + + + true + + + + + + + + + Print + + + + + PrintPreview + + + + + + GroupTreeWidget + QWidget +
    gui/common/GroupTreeWidget.h
    + 1 +
    +
    + + + + +
    diff --git a/retroshare-gui/src/gui/FriendsDialog.cpp b/retroshare-gui/src/gui/FriendsDialog.cpp new file mode 100644 index 000000000..f274bfe2c --- /dev/null +++ b/retroshare-gui/src/gui/FriendsDialog.cpp @@ -0,0 +1,2301 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2011 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common/vmessagebox.h" +#include "common/StatusDefs.h" +#include "common/GroupDefs.h" +#include "common/Emoticons.h" +#include + +#include "retroshare/rsinit.h" +#include "FriendsDialog.h" +#include +#include +#include +#include +#include +#include "settings/rsharesettings.h" +#include "notifyqt.h" + +#include "chat/PopupChatDialog.h" +#include "msgs/MessageComposer.h" +#include "connect/ConfCertDialog.h" +#include "profile/ProfileView.h" +#include "profile/ProfileWidget.h" +#include "profile/StatusMessage.h" + +#include "connect/ConnectFriendWizard.h" +#include "forums/CreateForum.h" +#include "channels/CreateChannel.h" +#include "groups/CreateGroup.h" +#include "feeds/AttachFileItem.h" +#include "im_history/ImHistoryBrowser.h" +#include "common/RSTreeWidgetItem.h" + +#include "RetroShareLink.h" + +#include "MainWindow.h" +#include "NewsFeed.h" +#include "util/misc.h" + +#include +#include +#include +#include + +#include + +/* Images for context menu icons */ +#define IMAGE_DENYFRIEND ":/images/denied16.png" +#define IMAGE_REMOVEFRIEND ":/images/removefriend16.png" +#define IMAGE_EXPORTFRIEND ":/images/exportpeers_16x16.png" +#define IMAGE_ADDFRIEND ":/images/user/add_user16.png" +#define IMAGE_FRIENDINFO ":/images/peerdetails_16x16.png" +#define IMAGE_CHAT ":/images/chat.png" +#define IMAGE_MSG ":/images/mail_new.png" +#define IMAGE_CONNECT ":/images/connect_friend.png" +#define IMAGE_COPYLINK ":/images/copyrslink.png" +/* Images for Status icons */ +#define IMAGE_AVAILABLE ":/images/user/identityavaiblecyan24.png" +#define IMAGE_CONNECT2 ":/images/reload24.png" +#define IMAGE_PASTELINK ":/images/pasterslink.png" +#define IMAGE_GROUP16 ":/images/user/group16.png" +#define IMAGE_GROUP24 ":/images/user/group24.png" +#define IMAGE_EDIT ":/images/edit_16.png" +#define IMAGE_REMOVE ":/images/delete.png" +#define IMAGE_EXPAND ":/images/edit_add24.png" +#define IMAGE_COLLAPSE ":/images/edit_remove24.png" +#define IMAGE_NEWSFEED "" +#define IMAGE_NEWSFEED_NEW ":/images/message-state-new.png" + +#define COLUMN_COUNT 2 +#define COLUMN_NAME 0 +#define COLUMN_STATE 1 + +#define COLUMN_DATA 0 // column for storing the userdata id + +#define ROLE_SORT Qt::UserRole +#define ROLE_ID Qt::UserRole + 1 +#define ROLE_STANDARD Qt::UserRole + 2 + +#define TYPE_GPG 0 +#define TYPE_SSL 1 +#define TYPE_GROUP 2 + +/****** + * #define FRIENDS_DEBUG 1 + *****/ + + +/** Constructor */ +FriendsDialog::FriendsDialog(QWidget *parent) + : RsAutoUpdatePage(1500,parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + last_status_send_time = 0 ; + groupsHasChanged = false; + correctColumnStatusSize = false; + + m_compareRole = new RSTreeWidgetItemCompareRole; + m_compareRole->setRole(COLUMN_NAME, ROLE_SORT); + m_compareRole->setRole(COLUMN_STATE, ROLE_SORT); + + connect( ui.peertreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( peertreeWidgetCostumPopupMenu( QPoint ) ) ); + connect( ui.peertreeWidget, SIGNAL( itemDoubleClicked ( QTreeWidgetItem *, int)), this, SLOT(chatfriend(QTreeWidgetItem *))); + connect( ui.peertreeWidget->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(peerSortIndicatorChanged(int,Qt::SortOrder))); + + connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(QString,int)), this, SLOT(updateOwnStatus(QString,int))); + + connect( ui.avatartoolButton, SIGNAL(clicked()), SLOT(getAvatar())); + connect( ui.mypersonalstatuslabel, SIGNAL(clicked()), SLOT(statusmessage())); + connect( ui.actionSet_your_Avatar, SIGNAL(triggered()), this, SLOT(getAvatar())); + connect( ui.actionSet_your_Personal_Message, SIGNAL(triggered()), this, SLOT(statusmessage())); + connect( ui.addfileButton, SIGNAL(clicked() ), this , SLOT(addExtraFile())); + + connect(ui.actionAdd_Friend, SIGNAL(triggered()), this, SLOT(addFriend())); + connect(ui.action_Hide_Offline_Friends, SIGNAL(triggered()), this, SLOT(insertPeers())); + connect(ui.action_Hide_Status_Column, SIGNAL(triggered()), this, SLOT(setStateColumn())); + connect(ui.action_Sort_by_State, SIGNAL(triggered()), this, SLOT(setStateColumn())); + connect(ui.actionSort_Peers_Ascending_Order, SIGNAL(triggered()), this, SLOT(sortPeersAscendingOrder())); + connect(ui.actionSort_Peers_Descending_Order, SIGNAL(triggered()), this, SLOT(sortPeersDescendingOrder())); + + ui.peertabWidget->setTabPosition(QTabWidget::North); + ui.peertabWidget->addTab(new ProfileWidget(), tr("Profile")); + NewsFeed *newsFeed = new NewsFeed(); + newsFeedTabIndex = ui.peertabWidget->addTab(newsFeed, tr("News Feed")); + ui.peertabWidget->tabBar()->setIconSize(QSize(10, 10)); + + /* get the current text and text color of the tab bar */ + newsFeedTabColor = ui.peertabWidget->tabBar()->tabTextColor(newsFeedTabIndex); + newsFeedText = ui.peertabWidget->tabBar()->tabText(newsFeedTabIndex); + + connect(newsFeed, SIGNAL(newsFeedChanged(int)), this, SLOT(newsFeedChanged(int))); + + ui.peertreeWidget->setColumnCount(COLUMN_COUNT); + ui.peertreeWidget->sortItems(COLUMN_NAME, Qt::AscendingOrder); + + // set header text aligment + QTreeWidgetItem * headerItem = ui.peertreeWidget->headerItem(); + headerItem->setTextAlignment(COLUMN_NAME, Qt::AlignHCenter | Qt::AlignVCenter); + headerItem->setTextAlignment(COLUMN_STATE, Qt::AlignLeft | Qt::AlignVCenter); + + wasStatusColumnHidden = ui.peertreeWidget->isColumnHidden(COLUMN_STATE); + + connect(ui.Sendbtn, SIGNAL(clicked()), this, SLOT(sendMsg())); + connect(ui.emoticonBtn, SIGNAL(clicked()), this, SLOT(smileyWidgetgroupchat())); + + connect(ui.lineEdit,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenu(QPoint))); + + connect(ui.textboldChatButton, SIGNAL(clicked()), this, SLOT(setFont())); + connect(ui.textunderlineChatButton, SIGNAL(clicked()), this, SLOT(setFont())); + connect(ui.textitalicChatButton, SIGNAL(clicked()), this, SLOT(setFont())); + connect(ui.fontsButton, SIGNAL(clicked()), this, SLOT(getFont())); + connect(ui.colorChatButton, SIGNAL(clicked()), this, SLOT(setColor())); + connect(ui.actionSave_History, SIGNAL(triggered()), this, SLOT(fileSaveAs())); + + ui.fontsButton->setIcon(QIcon(QString(":/images/fonts.png"))); + + mCurrentColor = Qt::black; + mCurrentFont.fromString(Settings->getChatScreenFont()); + + colorChanged(mCurrentColor); + fontChanged(mCurrentFont); + + style.setStyleFromSettings(ChatStyle::TYPE_PUBLIC); + + setChatInfo(tr("Welcome to RetroShare's group chat."), QString::fromUtf8("blue")); + + if (Settings->valueFromGroup("Chat", QString::fromUtf8("GroupChat_History"), true).toBool()) { + historyKeeper.init(QString::fromStdString(RsInit::RsProfileConfigDirectory()) + "/chatPublic.xml"); + + int messageCount = Settings->getPublicChatHistoryCount(); + if (messageCount > 0) { + QList historyItems; + historyKeeper.getMessages(historyItems, messageCount); + foreach(IMHistoryItem item, historyItems) { + addChatMsg(item.incoming, true, item.name, item.recvTime, item.messageText); + } + } + } + + QMenu * grpchatmenu = new QMenu(); + grpchatmenu->addAction(ui.actionClear_Chat_History); + grpchatmenu->addAction(ui.actionDelete_Chat_History); + grpchatmenu->addAction(ui.actionSave_History); + grpchatmenu->addAction(ui.actionMessageHistory); + ui.menuButton->setMenu(grpchatmenu); + + QMenu *menu = new QMenu(); + menu->addAction(ui.actionAdd_Friend); + menu->addAction(ui.actionAdd_Group); + + menu->addSeparator(); + menu->addAction(ui.actionCreate_New_Forum); +#ifndef RS_RELEASE_VERSION + menu->addAction(ui.actionCreate_New_Channel); +#endif + menu->addAction(ui.actionSet_your_Avatar); + menu->addAction(ui.actionSet_your_Personal_Message); + + ui.menupushButton->setMenu(menu); + + setAcceptDrops(true); + ui.lineEdit->setAcceptDrops(false); + + updateAvatar(); + loadmypersonalstatus(); + displayMenu(); + + // load settings + processSettings(true); + + /* Set header sizes for the fixed columns and resize modes, must be set after processSettings */ + QHeaderView *header = ui.peertreeWidget->header(); + header->setStretchLastSection(true); + ui.peertreeWidget->setColumnWidth(COLUMN_STATE, 20); // small enough + header->setResizeMode(COLUMN_STATE, QHeaderView::Stretch); + + // workaround for Qt bug, should be solved in next Qt release 4.7.0 + // http://bugreports.qt.nokia.com/browse/QTBUG-8270 + QShortcut *Shortcut = new QShortcut(QKeySequence (Qt::Key_Delete), ui.peertreeWidget, 0, 0, Qt::WidgetShortcut); + connect(Shortcut, SIGNAL(activated()), this, SLOT( removefriend ())); + + ui.lineEdit->installEventFilter(this); + + // add self nick and Avatar to Friends. + RsPeerDetails pd ; + if (rsPeers->getPeerDetails(rsPeers->getOwnId(),pd)) { + QString titleStr("%1"); + ui.nicklabel->setText(titleStr.arg(QString::fromStdString(pd.name) + " (" + tr("me") + ") " + QString::fromUtf8(pd.location.c_str()))); + } + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +FriendsDialog::~FriendsDialog () +{ + // save settings + processSettings(false); + + delete(m_compareRole); +} + +void FriendsDialog::processSettings(bool bLoad) +{ + QHeaderView *header = ui.peertreeWidget->header (); + + Settings->beginGroup(QString("FriendsDialog")); + + if (bLoad) { + // load settings + + // state of peer tree + header->restoreState(Settings->value("PeerTree").toByteArray()); + wasStatusColumnHidden = ui.peertreeWidget->isColumnHidden(COLUMN_STATE); + + // state of hideUnconnected + ui.action_Hide_Offline_Friends->setChecked(Settings->value("hideUnconnected", false).toBool()); + + // state of the status + ui.action_Hide_State->setChecked(Settings->value("hideState", false).toBool()); + + // state of hideStatusColumn + ui.action_Hide_Status_Column->setChecked(Settings->value("hideStatusColumn", false).toBool()); + + // state of splitter + ui.splitter->restoreState(Settings->value("Splitter").toByteArray()); + ui.splitter_2->restoreState(Settings->value("GroupChatSplitter").toByteArray()); + + // open groups + openGroups.clear(); + int arrayIndex = Settings->beginReadArray("Groups"); + for (int index = 0; index < arrayIndex; index++) { + Settings->setArrayIndex(index); + openGroups.push_back(Settings->value("open").toString().toStdString()); + } + Settings->endArray(); + + if (ui.peertreeWidget->isColumnHidden(COLUMN_STATE) && header->sectionSize(COLUMN_STATE) < 100) { + // Workaround + correctColumnStatusSize = true; + } + + setStateColumn(); + } else { + // save settings + + // state of peer tree + Settings->setValue("PeerTree", header->saveState()); + + // state of hideUnconnected + Settings->setValue("hideUnconnected", ui.action_Hide_Offline_Friends->isChecked()); + + // state of the status + Settings->setValue("hideState", ui.action_Hide_State->isChecked()); + + // state of hideStatusColumn + Settings->setValue("hideStatusColumn", ui.action_Hide_Status_Column->isChecked()); + + // state of splitter + Settings->setValue("Splitter", ui.splitter->saveState()); + Settings->setValue("GroupChatSplitter", ui.splitter_2->saveState()); + + // open groups + Settings->beginWriteArray("Groups"); + int arrayIndex = 0; + int itemCount = ui.peertreeWidget->topLevelItemCount(); + for (int index = 0; index < itemCount; index++) { + QTreeWidgetItem *item = ui.peertreeWidget->topLevelItem(index); + if (item->type() == TYPE_GROUP && item->isExpanded()) { + Settings->setArrayIndex(arrayIndex++); + Settings->setValue("open", item->data(COLUMN_DATA, ROLE_ID).toString()); + } + } + Settings->endArray(); + } + + Settings->endGroup(); +} + +void FriendsDialog::showEvent(QShowEvent *event) +{ + static bool first = true; + if (first) { + // Workaround: now the scroll position is correct calculated + first = false; + QScrollBar *scrollbar = ui.msgText->verticalScrollBar(); + scrollbar->setValue(scrollbar->maximum()); + } + + RsAutoUpdatePage::showEvent(event); +} + +void FriendsDialog::pasteLink() +{ + ui.lineEdit->insertHtml(RSLinkClipboard::toHtml()) ; +} + +void FriendsDialog::contextMenu(QPoint point) +{ + QMenu *contextMnu = ui.lineEdit->createStandardContextMenu(); + + contextMnu->addSeparator(); + QAction *action = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink())); + action->setDisabled(RSLinkClipboard::empty()); + + contextMnu->exec(QCursor::pos()); + delete(contextMnu); +} + +void FriendsDialog::peertreeWidgetCostumPopupMenu( QPoint point ) +{ + QTreeWidgetItem *c = getCurrentPeer(); + + QMenu contextMnu( this ); + QAction *action; + + QWidget *widget = new QWidget(&contextMnu); + widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); + + // create menu header + QHBoxLayout *hbox = new QHBoxLayout(); + hbox->setMargin(0); + hbox->setSpacing(6); + + iconLabel = new QLabel( this ); + iconLabel->setPixmap(QPixmap(":/images/user/friends24.png")); + iconLabel->setMaximumSize( iconLabel->frameSize().height() + 24, 24 ); + hbox->addWidget(iconLabel); + + textLabel = new QLabel("RetroShare", widget ); + + hbox->addWidget(textLabel); + + spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + hbox->addItem(spacerItem); + + widget->setLayout( hbox ); + + QWidgetAction *widgetAction = new QWidgetAction(this); + widgetAction->setDefaultWidget(widget); + + contextMnu.addAction( widgetAction); + + // create menu entries + if (c) { + int type = c->type(); + + // define header + switch (type) { + case TYPE_GROUP: + //this is a GPG key + textLabel->setText("" + tr("Group") + ""); + break; + case TYPE_GPG: + //this is a GPG key + textLabel->setText("" + tr("Friend") + ""); + break; + case TYPE_SSL: + //this is a SSL key + textLabel->setText("" + tr("Location") + ""); + break; + } + + switch (type) { + case TYPE_GROUP: + { + bool standard = c->data(COLUMN_DATA, ROLE_STANDARD).toBool(); + + contextMnu.addAction(QIcon(IMAGE_MSG), tr("Message Group"), this, SLOT(msgfriend())); + contextMnu.addAction(QIcon(IMAGE_ADDFRIEND), tr("Add Friend"), this, SLOT(addFriend())); + + contextMnu.addSeparator(); + + action = contextMnu.addAction(QIcon(IMAGE_EDIT), tr("Edit Group"), this, SLOT(editGroup())); + action->setDisabled(standard); + + action = contextMnu.addAction(QIcon(IMAGE_REMOVE), tr("Remove Group"), this, SLOT(removeGroup())); + action->setDisabled(standard); + } + break; + case TYPE_GPG: + case TYPE_SSL: + { + contextMnu.addAction(QIcon(IMAGE_CHAT), tr("Chat"), this, SLOT(chatfriendproxy())); + contextMnu.addAction(QIcon(IMAGE_MSG), tr("Message Friend"), this, SLOT(msgfriend())); + + contextMnu.addSeparator(); + + contextMnu.addAction(QIcon(IMAGE_FRIENDINFO), tr("Friend Details"), this, SLOT(configurefriend())); +// contextMnu.addAction(QIcon(IMAGE_PEERINFO), tr("Profile View"), this, SLOT(viewprofile())); +// action = contextMnu.addAction(QIcon(IMAGE_EXPORTFRIEND), tr("Export Friend"), this, SLOT(exportfriend())); + + if (type == TYPE_GPG) { + contextMnu.addAction(QIcon(IMAGE_EXPORTFRIEND), tr("Recommend this Friend to..."), this, SLOT(recommendfriend())); + } + + contextMnu.addAction(QIcon(IMAGE_CONNECT), tr("Connect To Friend"), this, SLOT(connectfriend())); + + if (type == TYPE_GPG) { + contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyLink())); + } + + action = contextMnu.addAction(QIcon(IMAGE_PASTELINK), tr("Paste Friend Link"), this, SLOT(pastePerson())); + if (RSLinkClipboard::empty(RetroShareLink::TYPE_PERSON)) { + action->setDisabled(true); + } + + if (type == TYPE_GPG) { + contextMnu.addAction(QIcon(IMAGE_DENYFRIEND), tr("Deny Friend"), this, SLOT(removefriend())); + } else { + //this is a SSL key + contextMnu.addAction(QIcon(IMAGE_REMOVEFRIEND), tr("Remove Friend Location"), this, SLOT(removefriend())); + } + + if (type == TYPE_GPG) { + QMenu* groupsMenu = NULL; + QMenu* addToGroupMenu = NULL; + QMenu* moveToGroupMenu = NULL; + + std::list groupInfoList; + rsPeers->getGroupInfoList(groupInfoList); + + GroupDefs::sortByName(groupInfoList); + + std::string gpgId = c->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + + QTreeWidgetItem *parent = c->parent(); + + bool foundGroup = false; + // add action for all groups, except the own group + for (std::list::iterator groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); groupIt++) { + if (std::find(groupIt->peerIds.begin(), groupIt->peerIds.end(), gpgId) == groupIt->peerIds.end()) { + if (parent) { + if (addToGroupMenu == NULL) { + addToGroupMenu = new QMenu(tr("Add to group"), &contextMnu); + } + QAction* addToGroupAction = new QAction(GroupDefs::name(*groupIt), addToGroupMenu); + addToGroupAction->setData(QString::fromStdString(groupIt->id)); + connect(addToGroupAction, SIGNAL(triggered()), this, SLOT(addToGroup())); + addToGroupMenu->addAction(addToGroupAction); + } + + if (moveToGroupMenu == NULL) { + moveToGroupMenu = new QMenu(tr("Move to group"), &contextMnu); + } + QAction* moveToGroupAction = new QAction(GroupDefs::name(*groupIt), moveToGroupMenu); + moveToGroupAction->setData(QString::fromStdString(groupIt->id)); + connect(moveToGroupAction, SIGNAL(triggered()), this, SLOT(moveToGroup())); + moveToGroupMenu->addAction(moveToGroupAction); + } else { + foundGroup = true; + } + } + + if (addToGroupMenu || moveToGroupMenu || foundGroup) { + groupsMenu = contextMnu.addMenu(QIcon(IMAGE_GROUP16), tr("Groups")); + + if (addToGroupMenu) { + groupsMenu->addMenu(addToGroupMenu); + } + + if (moveToGroupMenu) { + groupsMenu->addMenu(moveToGroupMenu); + } + + if (foundGroup) { + // add remove from group + if (parent && parent->type() == TYPE_GROUP) { + QAction *removeFromGroup = groupsMenu->addAction(tr("Remove from group")); + removeFromGroup->setData(parent->data(COLUMN_DATA, ROLE_ID)); + connect(removeFromGroup, SIGNAL(triggered()), this, SLOT(removeFromGroup())); + } + + QAction *removeFromAllGroups = groupsMenu->addAction(tr("Remove from all groups")); + removeFromAllGroups->setData(""); + connect(removeFromAllGroups, SIGNAL(triggered()), this, SLOT(removeFromGroup())); + } + } + } + } + } + } else { + action = contextMnu.addAction(QIcon(IMAGE_PASTELINK), tr("Paste Friend Link"), this, SLOT(pastePerson())); + if (RSLinkClipboard::empty(RetroShareLink::TYPE_PERSON)) { + action->setDisabled(true); + } + } + + contextMnu.addSeparator(); + + contextMnu.addAction(QIcon(IMAGE_EXPAND), tr("Expand all"), ui.peertreeWidget, SLOT(expandAll())); + contextMnu.addAction(QIcon(IMAGE_COLLAPSE), tr("Collapse all"), ui.peertreeWidget, SLOT(collapseAll())); + + contextMnu.exec(QCursor::pos()); +} + +// replaced by shortcut +//void FriendsDialog::keyPressEvent(QKeyEvent *e) +//{ +// if(e->key() == Qt::Key_Delete) +// { +// removefriend() ; +// e->accept() ; +// } +// else +// MainPage::keyPressEvent(e) ; +//} + +void FriendsDialog::updateDisplay() +{ + insertPeers() ; +} + +/* get the list of peers from the RsIface. */ +void FriendsDialog::insertPeers() +{ +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::insertPeers() called." << std::endl; +#endif + + std::list gpgFriends; + std::list::iterator gpgIt; + + std::list statusInfo; + rsStatus->getStatusList(statusInfo); + + if (!rsPeers) { + /* not ready yet! */ + std::cerr << "FriendsDialog::insertPeers() not ready yet : rsPeers unintialized." << std::endl; + return; + } + + bool hideUnconnected = ui.action_Hide_Offline_Friends->isChecked(); + bool useStatusColumn = !ui.action_Hide_Status_Column->isChecked(); + bool showState = !ui.action_Hide_State->isChecked(); + + // get ids of existing private chat messages + std::list privateChatIds; + rsMsgs->getPrivateChatQueueIds(true, privateChatIds); + + // get existing groups + std::list groupInfoList; + std::list::iterator groupIt; + rsPeers->getGroupInfoList(groupInfoList); + + rsPeers->getGPGAcceptedList(gpgFriends); + + //add own gpg id, if we have more than on location (ssl client) + std::list ownSslContacts; + std::string ownId = rsPeers->getGPGOwnId(); + rsPeers->getSSLChildListOfGPGId(ownId, ownSslContacts); + if (ownSslContacts.size() > 0) { + gpgFriends.push_back(ownId); + } + + /* get a link to the table */ + QTreeWidget *peertreeWidget = ui.peertreeWidget; + + // remove items don't exist anymore + QTreeWidgetItemIterator itemIterator(peertreeWidget); + QTreeWidgetItem *item; + while ((item = *itemIterator) != NULL) { + itemIterator++; + switch (item->type()) { + case TYPE_GPG: + { + QTreeWidgetItem *parent = item->parent(); + std::string gpg_widget_id = item->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + + // remove items that are not friends anymore + if (std::find(gpgFriends.begin(), gpgFriends.end(), gpg_widget_id) == gpgFriends.end()) { + if (parent) { + delete(parent->takeChild(parent->indexOfChild(item))); + } else { + delete(peertreeWidget->takeTopLevelItem(peertreeWidget->indexOfTopLevelItem(item))); + } + break; + } + + if (groupsHasChanged) { + if (parent) { + if (parent->type() == TYPE_GROUP) { + std::string groupId = parent->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + + // the parent is a group, check if the gpg id is assigned to the group + for (groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); groupIt++) { + if (groupIt->id == groupId) { + if (std::find(groupIt->peerIds.begin(), groupIt->peerIds.end(), gpg_widget_id) == groupIt->peerIds.end()) { + delete(parent->takeChild(parent->indexOfChild(item))); + } + break; + } + } + } + } else { + // gpg item without group, check if the gpg id is assigned to the group + for (groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); groupIt++) { + if (std::find(groupIt->peerIds.begin(), groupIt->peerIds.end(), gpg_widget_id) != groupIt->peerIds.end()) { + delete(peertreeWidget->takeTopLevelItem(peertreeWidget->indexOfTopLevelItem(item))); + break; + } + } + } + } + } + break; + case TYPE_GROUP: + { + if (groupsHasChanged) { + // remove deleted groups + std::string groupId = item->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + for (groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); groupIt++) { + if (groupIt->id == groupId) { + break; + } + } + if (groupIt == groupInfoList.end() || groupIt->peerIds.size() == 0) { + if (item->parent()) { + delete(item->parent()->takeChild(item->parent()->indexOfChild(item))); + } else { + delete(peertreeWidget->takeTopLevelItem(peertreeWidget->indexOfTopLevelItem(item))); + } + } + } + } + break; + } + } + + std::list fillGpgIds; + + // start with groups + groupIt = groupInfoList.begin(); + while (true) { + QTreeWidgetItem *groupItem = NULL; + RsGroupInfo *groupInfo = NULL; + int onlineCount = 0; + int availableCount = 0; + if (groupIt != groupInfoList.end()) { + groupInfo = &(*groupIt); + + if ((groupInfo->flag & RS_GROUP_FLAG_STANDARD) && groupInfo->peerIds.size() == 0) { + // don't show empty standard groups + groupIt++; + continue; + } + + // search existing group item + int itemCount = peertreeWidget->topLevelItemCount(); + for (int index = 0; index < itemCount; index++) { + QTreeWidgetItem *groupItemLoop = peertreeWidget->topLevelItem(index); + if (groupItemLoop->type() == TYPE_GROUP && groupItemLoop->data(COLUMN_DATA, ROLE_ID).toString().toStdString() == groupInfo->id) { + groupItem = groupItemLoop; + break; + } + } + + if (groupItem == NULL) { + // add group item + groupItem = new RSTreeWidgetItem(m_compareRole, TYPE_GROUP); + + /* Add item to the list. Add here, because for setHidden the item must be added */ + peertreeWidget->addTopLevelItem(groupItem); + + groupItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); + groupItem->setSizeHint(COLUMN_NAME, QSize(26, 26)); + groupItem->setTextAlignment(COLUMN_NAME, Qt::AlignLeft | Qt::AlignVCenter); + groupItem->setIcon(COLUMN_NAME, QIcon(IMAGE_GROUP24)); + groupItem->setForeground(COLUMN_NAME, QBrush(QColor(123, 123, 123))); + + /* used to find back the item */ + groupItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(groupInfo->id)); + groupItem->setData(COLUMN_DATA, ROLE_STANDARD, (groupInfo->flag & RS_GROUP_FLAG_STANDARD) ? true : false); + + if (openGroups.size()) { + if (std::find(openGroups.begin(), openGroups.end(), groupInfo->id) != openGroups.end()) { + groupItem->setExpanded(true); + } + } + } else { + // remove all gpg items that are not more assigned + int childCount = groupItem->childCount(); + int childIndex = 0; + while (childIndex < childCount) { + QTreeWidgetItem *gpgItemLoop = groupItem->child(childIndex); + if (gpgItemLoop->type() == TYPE_GPG) { + if (std::find(groupInfo->peerIds.begin(), groupInfo->peerIds.end(), gpgItemLoop->data(COLUMN_DATA, ROLE_ID).toString().toStdString()) == groupInfo->peerIds.end()) { + delete(groupItem->takeChild(groupItem->indexOfChild(gpgItemLoop))); + childCount = groupItem->childCount(); + continue; + } + } + childIndex++; + } + } + + // name is set after calculation of online/offline items + } + + // iterate through gpg friends + for (gpgIt = gpgFriends.begin(); gpgIt != gpgFriends.end(); gpgIt++) { + std::string gpgId = *gpgIt; + + if (groupInfo) { + // we fill a group, check if gpg id is assigned + if (std::find(groupInfo->peerIds.begin(), groupInfo->peerIds.end(), gpgId) == groupInfo->peerIds.end()) { + continue; + } + } else { + // we fill the not assigned gpg ids + if (std::find(fillGpgIds.begin(), fillGpgIds.end(), gpgId) != fillGpgIds.end()) { + continue; + } + } + + // add equal too, its no problem + fillGpgIds.push_back(gpgId); + + //add the gpg friends +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::insertPeers() inserting gpg_id : " << gpgId << std::endl; +#endif + + /* make a widget per friend */ + QTreeWidgetItem *gpgItem = NULL; + QTreeWidgetItem *gpgItemLoop = NULL; + + // search existing gpg item + int itemCount = groupItem ? groupItem->childCount() : peertreeWidget->topLevelItemCount(); + for (int index = 0; index < itemCount; index++) { + gpgItemLoop = groupItem ? groupItem->child(index) : peertreeWidget->topLevelItem(index); + if (gpgItemLoop->type() == TYPE_GPG && gpgItemLoop->data(COLUMN_DATA, ROLE_ID).toString().toStdString() == gpgId) { + gpgItem = gpgItemLoop; + break; + } + } + + RsPeerDetails detail; + if ((!rsPeers->getPeerDetails(gpgId, detail) || !detail.accept_connection) && detail.gpg_id != ownId) { + // don't accept anymore connection, remove from the view + if (gpgItem) { + if (groupItem) { + delete(groupItem->takeChild(groupItem->indexOfChild(gpgItem))); + } else { + delete (peertreeWidget->takeTopLevelItem(peertreeWidget->indexOfTopLevelItem(gpgItem))); + } + } + continue; + } + + if (gpgItem == NULL) { + // create gpg item and add it to tree + gpgItem = new RSTreeWidgetItem(m_compareRole, TYPE_GPG); //set type to 0 for custom popup menu + + /* Add gpg item to the list. Add here, because for setHidden the item must be added */ + if (groupItem) { + groupItem->addChild(gpgItem); + } else { + peertreeWidget->addTopLevelItem(gpgItem); + } + + gpgItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); + gpgItem->setSizeHint(COLUMN_NAME, QSize(26, 26)); + gpgItem->setTextAlignment(COLUMN_NAME, Qt::AlignLeft | Qt::AlignVCenter); + + /* not displayed, used to find back the item */ + gpgItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(detail.id)); + } + + availableCount++; + + QString gpgItemText = QString::fromStdString(detail.name); + + // remove items that are not friends anymore + int childCount = gpgItem->childCount(); + int childIndex = 0; + while (childIndex < childCount) { + std::string ssl_id = gpgItem->child(childIndex)->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + if (!rsPeers->isFriend(ssl_id)) { + delete (gpgItem->takeChild(childIndex)); + // count again + childCount = gpgItem->childCount(); + } else { + childIndex++; + } + } + + // update the childs (ssl certs) + bool gpg_connected = false; + bool gpg_online = false; + bool gpg_hasPrivateChat = false; + std::list sslContacts; + + rsPeers->getSSLChildListOfGPGId(detail.gpg_id, sslContacts); + for (std::list::iterator sslIt = sslContacts.begin(); sslIt != sslContacts.end(); sslIt++) { + QTreeWidgetItem *sslItem = NULL; + std::string sslId = *sslIt; + + //find the corresponding sslItem child item of the gpg item + bool newChild = true; + childCount = gpgItem->childCount(); + for (int childIndex = 0; childIndex < childCount; childIndex++) { + // we assume, that only ssl items are child of the gpg item, so we don't need to test the type + if (gpgItem->child(childIndex)->data(COLUMN_DATA, ROLE_ID).toString().toStdString() == sslId) { + sslItem = gpgItem->child(childIndex); + newChild = false; + break; + } + } + + RsPeerDetails sslDetail; + if (!rsPeers->getPeerDetails(sslId, sslDetail) || !rsPeers->isFriend(sslId)) { +#ifdef FRIENDS_DEBUG + std::cerr << "Removing widget from the view : id : " << sslId << std::endl; +#endif + //child has disappeared, remove it from the gpg_item + if (sslItem) { + gpgItem->removeChild(sslItem); + } + continue; + } + + if (newChild) { + sslItem = new RSTreeWidgetItem(m_compareRole, TYPE_SSL); //set type to 1 for custom popup menu + +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::insertPeers() inserting sslItem." << std::endl; +#endif + + /* Add ssl child to the list. Add here, because for setHidden the item must be added */ + gpgItem->addChild(sslItem); + } + + /* not displayed, used to find back the item */ + sslItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(sslDetail.id)); + + QString sText; + QString customStateString; + if (sslDetail.state & RS_PEER_STATE_CONNECTED) { + customStateString = QString::fromUtf8(rsMsgs->getCustomStateString(sslDetail.id).c_str()); + } + sText = tr("location") + " : " + QString::fromUtf8(sslDetail.location.c_str()); + if (customStateString.isEmpty() == false) { + sText += " - " + customStateString; + } + + QString connectStateString = StatusDefs::connectStateString(sslDetail); + if (useStatusColumn) { + sslItem->setText(COLUMN_STATE, connectStateString); + } else if (showState && connectStateString.isEmpty() == false) { + sText += " [" + StatusDefs::connectStateString(sslDetail) + "]"; + } + sslItem->setText( COLUMN_NAME, sText); + + if (useStatusColumn == false && showState == false) { + /* Show the state as tooltip */ + sslItem->setToolTip(COLUMN_NAME, connectStateString); + } else { + sslItem->setToolTip(COLUMN_NAME, ""); + } + + // sort location + sslItem->setData(COLUMN_STATE, ROLE_SORT, sText); + + /* change color and icon */ + QIcon sslIcon; + QFont sslFont; + QColor sslColor; + if (sslDetail.state & RS_PEER_STATE_CONNECTED) { + sslItem->setHidden(false); + gpg_connected = true; + + sslIcon = QIcon(":/images/connect_established.png"); + + sslFont.setBold(true); + sslColor = Qt::darkBlue; + } else if (sslDetail.state & RS_PEER_STATE_ONLINE) { + sslItem->setHidden(hideUnconnected); + gpg_online = true; + + if (sslDetail.connectState) { + sslIcon = QIcon(":/images/connect_creating.png"); + } else { + sslIcon = QIcon(":/images/connect_no.png"); + } + + sslFont.setBold(true); + sslColor = Qt::black; + } else { + sslItem->setHidden(hideUnconnected); + if (sslDetail.connectState) { + sslIcon = QIcon(":/images/connect_creating.png"); + } else { + sslIcon = QIcon(":/images/connect_no.png"); + } + + sslFont.setBold(false); + sslColor = Qt::black; + } + + if (std::find(privateChatIds.begin(), privateChatIds.end(), sslDetail.id) != privateChatIds.end()) { + // private chat is available + sslIcon = QIcon(":/images/chat.png"); + gpg_hasPrivateChat = true; + } + sslItem -> setIcon(COLUMN_NAME, sslIcon); + + for (int i = 0; i < COLUMN_COUNT; i++) { + sslItem -> setTextColor(i, sslColor); + sslItem -> setFont(i, sslFont); + } + } + + int bestPeerState = 0; // for gpg item + int i = 0; + QIcon gpgIcon; + if (gpg_connected) { + gpgItem->setHidden(false); + + onlineCount++; + + std::string bestSslId; // for gpg item + unsigned int bestRSState = 0; // for gpg item + + std::list::iterator it; + for(it = statusInfo.begin(); it != statusInfo.end() ; it++) { + + // don't forget the kids + std::list::iterator cont_it; + for (cont_it = sslContacts.begin(); cont_it != sslContacts.end(); cont_it++) { + + if((it->id == *cont_it) && (rsPeers->isOnline(*cont_it))){ + + int peerState = 0; + + switch (it->status) { + case RS_STATUS_INACTIVE: + peerState = PEER_STATE_INACTIVE; + break; + + case RS_STATUS_ONLINE: + peerState = PEER_STATE_ONLINE; + break; + + case RS_STATUS_AWAY: + peerState = PEER_STATE_AWAY; + break; + + case RS_STATUS_BUSY: + peerState = PEER_STATE_BUSY; + break; + } + + /* find the best ssl contact for the gpg item */ + if (bestPeerState == 0) { + /* first ssl contact */ + bestPeerState = peerState; + bestSslId = *cont_it; + bestRSState = it->status; + } else if (peerState < bestPeerState) { + /* higher state */ + bestPeerState = peerState; + bestSslId = *cont_it; + bestRSState = it->status; + } else if (peerState == bestPeerState) { + /* equal state ... use first */ + } + } + } + } + + if (bestPeerState == 0) { + // show as online + bestPeerState = PEER_STATE_ONLINE; + bestRSState = RS_STATUS_ONLINE; + } + + QColor textColor = StatusDefs::textColor(bestRSState); + QFont font = StatusDefs::font(bestRSState); + for(i = 0; i < COLUMN_COUNT; i++) { + gpgItem->setTextColor(i, textColor); + gpgItem->setFont(i, font); + } + + gpgIcon = QIcon(StatusDefs::imageUser(bestRSState)); + + if (useStatusColumn) { + gpgItem->setText(COLUMN_STATE, StatusDefs::name(bestRSState)); + } else if (showState) { + gpgItemText += " [" + StatusDefs::name(bestRSState) + "]"; + } + +// gpgItem->setToolTip(COLUMN_NAME, StatusDefs::tooltip(bestRSState)); + } else if (gpg_online) { + if (useStatusColumn) { + gpgItem->setText(COLUMN_STATE, tr("Available")); + } else if (showState) { + gpgItemText += " [" + tr("Available") + "]"; + } + + bestPeerState = PEER_STATE_AVAILABLE; + onlineCount++; + gpgItem->setHidden(hideUnconnected); + gpgIcon = QIcon(IMAGE_AVAILABLE); + + QFont font; + font.setBold(true); + for(i = 0; i < COLUMN_COUNT; i++) { + gpgItem->setTextColor(i,(Qt::black)); + gpgItem->setFont(i,font); + } + } else { + if (useStatusColumn) { + gpgItem->setText(COLUMN_STATE, StatusDefs::name(RS_STATUS_OFFLINE)); + } else if (showState) { + gpgItemText += " [" + StatusDefs::name(RS_STATUS_OFFLINE) + "]"; + } + + bestPeerState = PEER_STATE_OFFLINE; + gpgItem->setHidden(hideUnconnected); + gpgIcon = QIcon(StatusDefs::imageUser(RS_STATUS_OFFLINE)); + + QColor textColor = StatusDefs::textColor(RS_STATUS_OFFLINE); + QFont font = StatusDefs::font(RS_STATUS_OFFLINE); + for(i = 0; i < COLUMN_COUNT; i++) { + gpgItem->setTextColor(i, textColor); + gpgItem->setFont(i, font); + } + } + + if (gpg_hasPrivateChat) { + gpgIcon = QIcon(":/images/chat.png"); + } + + gpgItem->setText(COLUMN_NAME, gpgItemText); + gpgItem->setData(COLUMN_NAME, ROLE_SORT, "2 " + gpgItemText); + gpgItem->setData(COLUMN_STATE, ROLE_SORT, "2 " + BuildStateSortString(true, gpgItemText, bestPeerState)); + gpgItem->setIcon(COLUMN_NAME, gpgIcon); + } + + if (groupInfo && groupItem) { + if ((groupInfo->flag & RS_GROUP_FLAG_STANDARD) && groupItem->childCount() == 0) { + // there are some dead id's assigned + groupItem->setHidden(true); + } else { + QString groupName = GroupDefs::name(*groupInfo); + groupItem->setText(COLUMN_NAME, QString("%1 (%2/%3)").arg(groupName).arg(onlineCount).arg(availableCount)); + // show first the standard groups, than the user groups + groupItem->setData(COLUMN_NAME, ROLE_SORT, ((groupInfo->flag & RS_GROUP_FLAG_STANDARD) ? "0 " : "1 ") + groupName); + } + } + + if (groupIt != groupInfoList.end()) { + groupIt++; + } else { + // all done + break; + } + } + + QTreeWidgetItem *c = getCurrentPeer(); + if (c && c->isHidden()) { + // active item is hidden, deselect it + ui.peertreeWidget->setCurrentItem(NULL); + } + + groupsHasChanged = false; + openGroups.clear(); +} + +/* Utility Fns */ +std::string getPeerRsCertId(QTreeWidgetItem *i) +{ + std::string id = i -> data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + return id; +} + +/** Open a QFileDialog to browse for export a file. */ +void FriendsDialog::exportfriend() +{ + QTreeWidgetItem *c = getCurrentPeer(); + +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::exportfriend()" << std::endl; +#endif + if (!c) + { +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::exportfriend() None Selected -- sorry" << std::endl; +#endif + return; + } + + std::string id = getPeerRsCertId(c); + + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_CERT, tr("Save Certificate"), tr("Certificates (*.pqi)"), fileName)) + { +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::exportfriend() Saving to: " << fileName.toStdString() << std::endl; +#endif + if (rsPeers) + { + rsPeers->saveCertificateToFile(id, fileName.toUtf8().constData()); + } + } + +} + +void FriendsDialog::chatfriendproxy() +{ + chatfriend(getCurrentPeer()); +} + +void FriendsDialog::chatfriend(QTreeWidgetItem *pPeer) +{ + if (pPeer == NULL) { + return; + } + + std::string id = pPeer->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + PopupChatDialog::chatFriend(id); +} + +void FriendsDialog::msgfriend() +{ + QTreeWidgetItem *peer = getCurrentPeer(); + + if (!peer) + return; + + std::string id = peer->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + MessageComposer::msgFriend(id, (peer->type() == TYPE_GROUP)); +} + +void FriendsDialog::recommendfriend() +{ + QTreeWidgetItem *peer = getCurrentPeer(); + + if (!peer) + return; + + std::list ids; + ids.push_back(peer->data(COLUMN_DATA, ROLE_ID).toString().toStdString()); + MessageComposer::recommendFriend(ids); +} + +void FriendsDialog::pastePerson() +{ + RSLinkClipboard::process(RetroShareLink::TYPE_PERSON, RSLINK_PROCESS_NOTIFY_ERROR); +} + +void FriendsDialog::copyLink() +{ + QTreeWidgetItem *c = getCurrentPeer(); + + if (c == NULL) { + return; + } + + std::vector urls; + RetroShareLink link; + if (link.createPerson(c->data(COLUMN_DATA, ROLE_ID).toString().toStdString())) { + urls.push_back(link); + } + + RSLinkClipboard::copyLinks(urls); +} + +QTreeWidgetItem *FriendsDialog::getCurrentPeer() +{ + /* get the current, and extract the Id */ + + /* get a link to the table */ + QTreeWidget *peerWidget = ui.peertreeWidget; + QTreeWidgetItem *item = peerWidget -> currentItem(); + if (!item) + { +#ifdef FRIENDS_DEBUG + std::cerr << "Invalid Current Item" << std::endl; +#endif + return NULL; + } + +#ifdef FRIENDS_DEBUG + /* Display the columns of this item. */ + std::ostringstream out; + out << "CurrentPeerItem: " << std::endl; + + for(int i = 1; i < COLUMN_COUNT; i++) + { + QString txt = item -> text(i); + out << "\t" << i << ":" << txt.toStdString() << std::endl; + } + std::cerr << out.str(); +#endif + return item; +} + +/* So from the Peers Dialog we can call the following control Functions: + * (1) Remove Current. FriendRemove(id) + * (2) Allow/DisAllow. FriendStatus(id, accept) + * (2) Connect. FriendConnectAttempt(id, accept) + * (3) Set Address. FriendSetAddress(id, str, port) + * (4) Set Trust. FriendTrustSignature(id, bool) + * (5) Configure (GUI Only) -> 3/4 + * + * All of these rely on the finding of the current Id. + */ + + +void FriendsDialog::removefriend() +{ + QTreeWidgetItem *c = getCurrentPeer(); +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::removefriend()" << std::endl; +#endif + if (!c) + { +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::removefriend() None Selected -- sorry" << std::endl; +#endif + return; + } + + if (rsPeers) + { + if ((QMessageBox::question(this, "RetroShare",tr("Do you want to remove this Friend?"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) + { + rsPeers->removeFriend(getPeerRsCertId(c)); + emit friendsUpdated() ; + } + return; + } +} + +void FriendsDialog::connectfriend() +{ + QTreeWidgetItem *c = getCurrentPeer(); +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::connectfriend()" << std::endl; +#endif + if (!c) + { +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::connectfriend() Noone Selected -- sorry" << std::endl; +#endif + return; + } + + if (rsPeers) + { + if (c->type() == TYPE_GPG) { + int childCount = c->childCount(); + for (int childIndex = 0; childIndex < childCount; childIndex++) { + QTreeWidgetItem *item = c->child(childIndex); + if (item->type() == TYPE_SSL) { + rsPeers->connectAttempt(getPeerRsCertId(item)); + item->setIcon(COLUMN_NAME,(QIcon(IMAGE_CONNECT2))); + } + } + } else { + //this is a SSL key + rsPeers->connectAttempt(getPeerRsCertId(c)); + c->setIcon(COLUMN_NAME,(QIcon(IMAGE_CONNECT2))); + } + } +} + +/* GUI stuff -> don't do anything directly with Control */ +void FriendsDialog::configurefriend() +{ + ConfCertDialog::showIt(getPeerRsCertId(getCurrentPeer()), ConfCertDialog::PageDetails); +} + +void FriendsDialog::addFriend() +{ + std::string groupId; + + QTreeWidgetItem *c = getCurrentPeer(); + if (c && c->type() == TYPE_GROUP) { + groupId = c->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + } + + ConnectFriendWizard connwiz (this); + + if (groupId.empty() == false) { + connwiz.setGroup(groupId); + } + + connwiz.exec (); +} + +void FriendsDialog::resetStatusBar() +{ +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog: reseting status bar." << std::endl ; +#endif + + ui.statusStringLabel->setText(QString("")) ; +} + +void FriendsDialog::updateStatusTyping() +{ + if(time(NULL) - last_status_send_time > 5) // limit 'peer is typing' packets to at most every 10 sec + { +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog: sending group chat typing info." << std::endl ; +#endif + +#ifdef ONLY_FOR_LINGUIST + tr("is typing..."); +#endif + + rsMsgs->sendGroupChatStatusString("is typing..."); + last_status_send_time = time(NULL) ; + } +} + +// Called by libretroshare through notifyQt to display the peer's status +// +void FriendsDialog::updateStatusString(const QString& peer_id, const QString& status_string) +{ +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog: received group chat typing info. updating gui." << std::endl ; +#endif + + QString status = QString::fromStdString(rsPeers->getPeerName(peer_id.toStdString())) + " " + tr(status_string.toAscii()); + ui.statusStringLabel->setText(status) ; // displays info for 5 secs. + + QTimer::singleShot(5000,this,SLOT(resetStatusBar())) ; +} + +void FriendsDialog::updatePeersAvatar(const QString& peer_id) +{ +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog: Got notified of new avatar for peer " << peer_id.toStdString() << std::endl ; +#endif + + PopupChatDialog *pcd = PopupChatDialog::getPrivateChat(peer_id.toStdString(), 0); + if (pcd) { + pcd->updatePeerAvatar(peer_id.toStdString()); + } +} + +void FriendsDialog::updatePeerStatusString(const QString& peer_id,const QString& status_string,bool is_private_chat) +{ + if(is_private_chat) + { + PopupChatDialog *pcd = PopupChatDialog::getExistingInstance(peer_id.toStdString()); + if (pcd) { + pcd->updateStatusString(peer_id, status_string); + } + } + else + { +#ifdef FRIENDS_DEBUG + std::cerr << "Updating public chat msg from peer " << rsPeers->getPeerName(peer_id.toStdString()) << ": " << status_string.toStdString() << std::endl ; +#endif + + updateStatusString(peer_id, status_string); + } +} + +void FriendsDialog::publicChatChanged(int type) +{ + if (type == NOTIFY_TYPE_ADD) { + insertChat(); + } +} + +void FriendsDialog::addChatMsg(bool incoming, bool history, QString &name, QDateTime &recvTime, QString &message) +{ + unsigned int formatFlag = CHAT_FORMATMSG_EMBED_LINKS; + + // embed smileys ? + if (Settings->valueFromGroup(QString("Chat"), QString::fromUtf8("Emoteicons_GroupChat"), true).toBool()) { + formatFlag |= CHAT_FORMATMSG_EMBED_SMILEYS; + } + + ChatStyle::enumFormatMessage type; + if (incoming) { + if (history) { + type = ChatStyle::FORMATMSG_HINCOMING; + } else { + type = ChatStyle::FORMATMSG_INCOMING; + } + } else { + if (history) { + type = ChatStyle::FORMATMSG_HOUTGOING; + } else { + type = ChatStyle::FORMATMSG_OUTGOING; + } + } + QString formatMsg = style.formatMessage(type, name, recvTime, message, formatFlag); + + ui.msgText->append(formatMsg); +} + +void FriendsDialog::insertChat() +{ + std::list newchat; + if (!rsMsgs->getPublicChatQueue(newchat)) + { +#ifdef FRIENDS_DEBUG + std::cerr << "no chat available." << std::endl ; +#endif + return; + } +#ifdef FRIENDS_DEBUG + std::cerr << "got new chat." << std::endl; +#endif + std::list::iterator it; + + /* add in lines at the bottom */ + for(it = newchat.begin(); it != newchat.end(); it++) + { + /* are they private? */ + if (it->chatflags & RS_CHAT_PRIVATE) + { + /* this should not happen */ + continue; + } + + QDateTime sendTime = QDateTime::fromTime_t(it->sendTime); + QDateTime recvTime = QDateTime::fromTime_t(it->recvTime); + QString name = QString::fromStdString(rsPeers->getPeerName(it->rsid)); + QString msg = QString::fromStdWString(it->msg); + +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::insertChat(): " << msg.toStdString() << std::endl; +#endif + + bool incoming = false; + + // notify with a systray icon msg + if(it->rsid != rsPeers->getOwnId()) + { + incoming = true; + + // This is a trick to translate HTML into text. + QTextEdit editor; + editor.setHtml(msg); + QString notifyMsg = name + ": " + editor.toPlainText(); + + if(notifyMsg.length() > 30) + emit notifyGroupChat(tr("New group chat"), notifyMsg.left(30) + QString("...")); + else + emit notifyGroupChat(tr("New group chat"), notifyMsg); + } + + historyKeeper.addMessage(incoming, it->rsid, name, sendTime, recvTime, msg); + addChatMsg(incoming, false, name, recvTime, msg); + } +} + +bool FriendsDialog::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == ui.lineEdit) { + if (event->type() == QEvent::KeyPress) { + updateStatusTyping() ; + + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent && (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)) { + // Enter pressed + if (Settings->getChatSendMessageWithCtrlReturn()) { + if (keyEvent->modifiers() & Qt::ControlModifier) { + // send message with Ctrl+Enter + sendMsg(); + return true; // eat event + } + } else { + if (keyEvent->modifiers() & Qt::ControlModifier) { + // insert return + ui.lineEdit->textCursor().insertText("\n"); + } else { + // send message with Enter + sendMsg(); + } + return true; // eat event + } + } + } + } + // pass the event on to the parent class + return RsAutoUpdatePage::eventFilter(obj, event); +} + +void FriendsDialog::sendMsg() +{ + QTextEdit *lineWidget = ui.lineEdit; + + if (lineWidget->toPlainText().isEmpty()) { + // nothing to send + return; + } + + std::wstring message = lineWidget->toHtml().toStdWString(); + +#ifdef FRIENDS_DEBUG + std::string msg(message.begin(), message.end()); + std::cerr << "FriendsDialog::sendMsg(): " << msg << std::endl; +#endif + + rsMsgs->sendPublicChat(message); + ui.lineEdit->clear(); + // workaround for Qt bug - http://bugreports.qt.nokia.com/browse/QTBUG-2533 + // QTextEdit::clear() does not reset the CharFormat if document contains hyperlinks that have been accessed. + ui.lineEdit->setCurrentCharFormat(QTextCharFormat ()); + + setFont(); + + /* redraw send list */ + insertSendList(); +} + +void FriendsDialog::insertSendList() +{ +#ifdef false + std::list peers; + std::list::iterator it; + + if (!rsPeers) + { + /* not ready yet! */ + return; + } + + rsPeers->getOnlineList(peers); + + /* get a link to the table */ + //QTreeWidget *sendWidget = ui.msgSendList; + QList items; + + for(it = peers.begin(); it != peers.end(); it++) + { + + RsPeerDetails details; + if (!rsPeers->getPeerDetails(*it, details)) + { + continue; /* BAD */ + } + + /* make a widget per friend */ + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + + /* add all the labels */ + /* (0) Person */ + item -> setText(0, QString::fromStdString(details.name)); + + item -> setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + //item -> setFlags(Qt::ItemIsUserCheckable); + + item -> setCheckState(0, Qt::Checked); + + if (rsicontrol->IsInChat(*it)) + { + item -> setCheckState(0, Qt::Checked); + } + else + { + item -> setCheckState(0, Qt::Unchecked); + } + + /* disable for the moment */ + item -> setFlags(Qt::ItemIsUserCheckable); + item -> setCheckState(0, Qt::Checked); + + /* add to the list */ + items.append(item); + } + + /* remove old items */ + //sendWidget->clear(); + //sendWidget->setColumnCount(1); + + /* add the items in! */ + //sendWidget->insertTopLevelItems(0, items); + + //sendWidget->update(); /* update display */ +#endif +} + + +/* to toggle the state */ + + +//void FriendsDialog::toggleSendItem( QTreeWidgetItem *item, int col ) +//{ +//#ifdef FRIENDS_DEBUG +// std::cerr << "ToggleSendItem()" << std::endl; +//#endif +// +// /* extract id */ +// std::string id = (item -> text(4)).toStdString(); +// +// /* get state */ +// bool inChat = (Qt::Checked == item -> checkState(0)); /* alway column 0 */ +// +// /* call control fns */ +// +// rsicontrol -> SetInChat(id, inChat); +// return; +//} + +//============================================================================ + +void FriendsDialog::setColor() +{ + bool ok; + QRgb color = QColorDialog::getRgba(ui.lineEdit->textColor().rgba(), &ok, this); + if (ok) { + mCurrentColor = QColor(color); + colorChanged(mCurrentColor); + } + setFont(); +} + +void FriendsDialog::colorChanged(const QColor &c) +{ + QPixmap pxm(16,16); + pxm.fill(mCurrentColor); + ui.colorChatButton->setIcon(pxm); +} + +void FriendsDialog::getFont() +{ + bool ok; + mCurrentFont = QFontDialog::getFont(&ok, mCurrentFont, this); + if (ok) { + fontChanged(mCurrentFont); + } +} + +void FriendsDialog::fontChanged(const QFont &font) +{ + mCurrentFont = font; + + ui.textboldChatButton->setChecked(mCurrentFont.bold()); + ui.textunderlineChatButton->setChecked(mCurrentFont.underline()); + ui.textitalicChatButton->setChecked(mCurrentFont.italic()); + + setFont(); +} + +void FriendsDialog::setFont() +{ + mCurrentFont.setBold(ui.textboldChatButton->isChecked()); + mCurrentFont.setUnderline(ui.textunderlineChatButton->isChecked()); + mCurrentFont.setItalic(ui.textitalicChatButton->isChecked()); + ui.lineEdit->setFont(mCurrentFont); + ui.lineEdit->setTextColor(mCurrentColor); + Settings->setChatScreenFont(mCurrentFont.toString()); + + ui.lineEdit->setFocus(); +} + +// Update Chat Info information +void FriendsDialog::setChatInfo(QString info, QColor color) +{ + static unsigned int nbLines = 0; + ++nbLines; + // Check log size, clear it if too big + if(nbLines > 200) { + ui.msgText->clear(); + nbLines = 1; + } + ui.msgText->append(QString::fromUtf8("")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8(" - ") + info + QString::fromUtf8("")); +} + +void FriendsDialog::on_actionClear_Chat_History_triggered() +{ + ui.msgText->clear(); +} + +void FriendsDialog::on_actionDelete_Chat_History_triggered() +{ + if ((QMessageBox::question(this, "RetroShare", tr("Do you really want to physically delete the history?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) == QMessageBox::Yes) { + on_actionClear_Chat_History_triggered(); + historyKeeper.clear(); + } +} + +void FriendsDialog::smileyWidgetgroupchat() +{ + Emoticons::showSmileyWidget(this, ui.emoticonBtn, SLOT(addSmileys()), true); +} + +void FriendsDialog::addSmileys() +{ + ui.lineEdit->textCursor().insertText(qobject_cast(sender())->toolTip().split("|").first()); +} + +/* GUI stuff -> don't do anything directly with Control */ +void FriendsDialog::viewprofile() +{ + /* display Dialog */ + + QTreeWidgetItem *c = getCurrentPeer(); + + + static ProfileView *profileview = new ProfileView(); + + + if (!c) + return; + + /* set the Id */ + std::string id = getPeerRsCertId(c); + + profileview -> setPeerId(id); + profileview -> show(); +} + +void FriendsDialog::updateAvatar() +{ + unsigned char *data = NULL; + int size = 0 ; + + rsMsgs->getOwnAvatarData(data,size); + +#ifdef FRIENDS_DEBUG + std::cerr << "Image size = " << size << std::endl ; +#endif + + if(size == 0) + std::cerr << "Got no image" << std::endl ; + + // set the image + QPixmap pix ; + pix.loadFromData(data,size,"PNG") ; + ui.avatartoolButton->setIcon(pix); // writes image into ba in PNG format + + PopupChatDialog::updateAllAvatars(); + + delete[] data ; +} + +void FriendsDialog::getAvatar() +{ + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg *.tiff *.gif)"), fileName)) + { + QPixmap picture; + picture = QPixmap(fileName).scaled(96,96, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + +#ifdef FRIENDS_DEBUG + std::cerr << "Sending avatar image down the pipe" << std::endl ; +#endif + + // send avatar down the pipe for other peers to get it. + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + picture.save(&buffer, "PNG"); // writes image into ba in PNG format + +#ifdef FRIENDS_DEBUG + std::cerr << "Image size = " << ba.size() << std::endl ; +#endif + + rsMsgs->setOwnAvatarData((unsigned char *)(ba.data()),ba.size()) ; // last char 0 included. + + // I suppressed this because it gets called already by rsMsgs->setOwnAvatarData() through a Qt notification signal + //updateAvatar() ; + } +} + +void FriendsDialog::changeAvatarClicked() +{ + + updateAvatar(); +} + +void FriendsDialog::on_actionCreate_New_Forum_activated() +{ + MainWindow::activatePage (MainWindow::Forums); + + CreateForum cf (this); + cf.exec(); + +} + +void FriendsDialog::on_actionCreate_New_Channel_activated() +{ +#ifndef RS_RELEASE_VERSION + MainWindow::activatePage (MainWindow::Channels); + + CreateChannel cf (this); + cf.exec(); +#endif +} + + +/** Loads own personal status */ +void FriendsDialog::loadmypersonalstatus() +{ + ui.mypersonalstatuslabel->setText(QString::fromUtf8(rsMsgs->getCustomStateString().c_str())); +} + +void FriendsDialog::statusmessage() +{ + StatusMessage statusmsgdialog (this); + statusmsgdialog.exec(); +} + +void FriendsDialog::addExtraFile() +{ + QString file; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", file)) { + addAttachment(file.toUtf8().constData()); + } +} + +void FriendsDialog::addAttachment(std::string filePath) { + /* add a AttachFileItem to the attachment section */ + std::cerr << "PopupChatDialog::addExtraFile() hashing file." << std::endl; + + /* add widget in for new destination */ + AttachFileItem *file = new AttachFileItem(filePath); + //file-> + + ui.verticalLayout->addWidget(file, 1, 0); + + //when the file is local or is finished hashing, call the fileHashingFinished method to send a chat message + if (file->getState() == AFI_STATE_LOCAL) { + fileHashingFinished(file); + } else { + QObject::connect(file,SIGNAL(fileFinished(AttachFileItem *)), SLOT(fileHashingFinished(AttachFileItem *))) ; + } +} + +void FriendsDialog::fileHashingFinished(AttachFileItem* file) +{ + std::cerr << "FriendsDialog::fileHashingFinished() started." << std::endl; + + //check that the file is ok tos end + if (file->getState() == AFI_STATE_ERROR) { +#ifdef FRIENDS_DEBUG + std::cerr << "PopupChatDialog::fileHashingFinished error file is not hashed." << std::endl; +#endif + return; + } + + //convert fileSize from uint_64 to string for html link + // char fileSizeChar [100]; + // sprintf(fileSizeChar, "%lld", file->FileSize()); + // std::string fileSize = *(&fileSizeChar); + + RetroShareLink link; + if (!link.createFile(QString::fromUtf8(file->FileName().c_str()), file->FileSize(), QString::fromStdString(file->FileHash()))) { + return; + } + QString mesgString = link.toHtmlSize(); + + // std::string mesgString = "
    " + // + "retroshare://file|" + (file->FileName()) + "|" + fileSize + "|" + (file->FileHash()) + ""; +#ifdef FRIENDS_DEBUG + std::cerr << "FriendsDialog::fileHashingFinished mesgString : " << mesgString.toStdString() << std::endl; +#endif + + /* convert to real html document */ + QTextBrowser textBrowser; + textBrowser.setHtml(mesgString); + std::wstring msg = textBrowser.toHtml().toStdWString(); + + rsMsgs->sendPublicChat(msg); + setFont(); +} + +void FriendsDialog::dropEvent(QDropEvent *event) +{ + if (!(Qt::CopyAction & event->possibleActions())) + { + std::cerr << "FriendsDialog::dropEvent() Rejecting uncopyable DropAction" << std::endl; + + /* can't do it */ + return; + } + + std::cerr << "FriendsDialog::dropEvent() Formats" << std::endl; + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) + { + std::cerr << "Format: " << (*it).toStdString() << std::endl; + } + + if (event->mimeData()->hasUrls()) + { + std::cerr << "FriendsDialog::dropEvent() Urls:" << std::endl; + + QList urls = event->mimeData()->urls(); + QList::iterator uit; + for(uit = urls.begin(); uit != urls.end(); uit++) + { + QString localpath = uit->toLocalFile(); + std::cerr << "Whole URL: " << uit->toString().toStdString() << std::endl; + std::cerr << "or As Local File: " << localpath.toStdString() << std::endl; + + if (localpath.isEmpty() == false) + { + //Check that the file does exist and is not a directory + QDir dir(localpath); + if (dir.exists()) { + std::cerr << "FriendsDialog::dropEvent() directory not accepted."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("Directory can't be dropped, only files are accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } else if (QFile::exists(localpath)) { + FriendsDialog::addAttachment(localpath.toUtf8().constData()); + } else { + std::cerr << "FriendsDialog::dropEvent() file does not exists."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("File not found or file name not accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } + } + } + } + + event->setDropAction(Qt::CopyAction); + event->accept(); +} + +void FriendsDialog::dragEnterEvent(QDragEnterEvent *event) +{ + /* print out mimeType */ + std::cerr << "FriendsDialog::dragEnterEvent() Formats" << std::endl; + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) + { + std::cerr << "Format: " << (*it).toStdString() << std::endl; + } + + if (event->mimeData()->hasUrls()) + { + std::cerr << "FriendsDialog::dragEnterEvent() Accepting Urls" << std::endl; + event->acceptProposedAction(); + } + else + { + std::cerr << "FriendsDialog::dragEnterEvent() No Urls" << std::endl; + } +} + +bool FriendsDialog::fileSave() +{ + if (fileName.isEmpty()) + return fileSaveAs(); + + QFile file(fileName); + if (!file.open(QFile::WriteOnly)) + return false; + QTextStream ts(&file); + ts.setCodec(QTextCodec::codecForName("UTF-8")); + ts << ui.msgText->document()->toPlainText(); + ui.msgText->document()->setModified(false); + return true; +} + +bool FriendsDialog::fileSaveAs() +{ + QString fn; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_HISTORY, tr("Save as..."), tr("Text File (*.txt );;All Files (*)"), fn)) { + setCurrentFileName(fn); + return fileSave(); + } + + return false; +} + +void FriendsDialog::setCurrentFileName(const QString &fileName) +{ + this->fileName = fileName; + ui.msgText->document()->setModified(false); + + setWindowModified(false); +} + +////play sound when recv a message +void FriendsDialog::playsound(){ + Settings->beginGroup("Sound"); + Settings->beginGroup("SoundFilePath"); + QString OnlineSound = Settings->value("NewChatMessage","").toString(); + Settings->endGroup(); + Settings->beginGroup("Enable"); + bool flag = Settings->value("NewChatMessage",false).toBool(); + Settings->endGroup(); + Settings->endGroup(); + if(!OnlineSound.isEmpty()&&flag) + if(QSound::isAvailable()) + QSound::play(OnlineSound); +} + +void FriendsDialog::displayMenu() +{ + QMenu *displaymenu = new QMenu(); + + displaymenu->addAction(ui.actionSort_Peers_Descending_Order); + displaymenu->addAction(ui.actionSort_Peers_Ascending_Order); + displaymenu->addAction(ui.action_Hide_Offline_Friends); + displaymenu->addAction(ui.action_Sort_by_State); + displaymenu->addAction(ui.action_Hide_Status_Column); + displaymenu->addAction(ui.action_Hide_State); + + ui.displayButton->setMenu(displaymenu); +} + +void FriendsDialog::setStateColumn() +{ + if (ui.action_Hide_Status_Column->isChecked()) { + ui.peertreeWidget->setColumnHidden(COLUMN_STATE, true); + ui.peertreeWidget->setHeaderHidden(true); + ui.action_Hide_State->setEnabled(true); + wasStatusColumnHidden = true; + } else { + ui.peertreeWidget->setColumnHidden(COLUMN_STATE, false); + ui.peertreeWidget->setHeaderHidden(false); + ui.action_Hide_State->setEnabled(false); + if (correctColumnStatusSize) { + correctColumnStatusSize = false; + ui.peertreeWidget->header()->resizeSection(COLUMN_STATE, 100); + } + if (wasStatusColumnHidden) { + ui.peertreeWidget->header()->resizeSection(COLUMN_NAME, ui.peertreeWidget->header()->sectionSize(COLUMN_NAME) - ui.peertreeWidget->header()->sectionSize(COLUMN_STATE)); + } + wasStatusColumnHidden = false; + } + + if(ui.action_Sort_by_State->isChecked()) { + ui.peertreeWidget->sortByColumn(COLUMN_STATE); + } else { + ui.peertreeWidget->sortByColumn(COLUMN_NAME); + } +} + +void FriendsDialog::sortPeersAscendingOrder() +{ + ui.peertreeWidget->sortByColumn(ui.peertreeWidget->sortColumn(), Qt::AscendingOrder); +} + +void FriendsDialog::sortPeersDescendingOrder() +{ + ui.peertreeWidget->sortByColumn(ui.peertreeWidget->sortColumn(), Qt::DescendingOrder); +} + +void FriendsDialog::peerSortIndicatorChanged(int column, Qt::SortOrder) +{ + ui.action_Sort_by_State->setChecked(column == COLUMN_STATE); +} + +void FriendsDialog::on_actionMessageHistory_triggered() +{ + ImHistoryBrowser imBrowser("", historyKeeper, ui.lineEdit, this); + imBrowser.exec(); +} + +void FriendsDialog::on_actionAdd_Group_activated() +{ + CreateGroup createGrpDialog ("", this); + createGrpDialog.exec(); +} + +void FriendsDialog::addToGroup() +{ + QTreeWidgetItem *c = getCurrentPeer(); + if (c == NULL) { + return; + } + + if (c->type() != TYPE_GPG) { + // wrong type + return; + } + + std::string groupId = qobject_cast(sender())->data().toString().toStdString(); + std::string gpgId = c->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + + if (gpgId.empty() || groupId.empty()) { + return; + } + + // add to group + rsPeers->assignPeerToGroup(groupId, gpgId, true); +} + +void FriendsDialog::moveToGroup() +{ + QTreeWidgetItem *c = getCurrentPeer(); + if (c == NULL) { + return; + } + + if (c->type() != TYPE_GPG) { + // wrong type + return; + } + + std::string groupId = qobject_cast(sender())->data().toString().toStdString(); + std::string gpgId = c->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + + if (gpgId.empty() || groupId.empty()) { + return; + } + + // remove from all groups + rsPeers->assignPeerToGroup("", gpgId, false); + + // add to group + rsPeers->assignPeerToGroup(groupId, gpgId, true); +} + +void FriendsDialog::removeFromGroup() +{ + QTreeWidgetItem *c = getCurrentPeer(); + if (c == NULL) { + return; + } + + if (c->type() != TYPE_GPG) { + // wrong type + return; + } + + std::string groupId = qobject_cast(sender())->data().toString().toStdString(); + std::string gpgId = c->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + + if (gpgId.empty()) { + return; + } + + // remove from (all) group(s) + rsPeers->assignPeerToGroup(groupId, gpgId, false); +} + +void FriendsDialog::editGroup() +{ + QTreeWidgetItem *c = getCurrentPeer(); + if (c == NULL) { + return; + } + + if (c->type() != TYPE_GROUP) { + // wrong type + return; + } + + std::string groupId = c->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + + if (groupId.empty()) { + return; + } + + CreateGroup editGrpDialog (groupId, this); + editGrpDialog.exec(); +} + +void FriendsDialog::removeGroup() +{ + QTreeWidgetItem *c = getCurrentPeer(); + if (c == NULL) { + return; + } + + if (c->type() != TYPE_GROUP) { + // wrong type + return; + } + + std::string groupId = c->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + + if (groupId.empty()) { + return; + } + + rsPeers->removeGroup(groupId); +} + +void FriendsDialog::groupsChanged(int type) +{ + Q_UNUSED(type); + + groupsHasChanged = true; +} + +void FriendsDialog::newsFeedChanged(int count) +{ + if (count) { + ui.peertabWidget->tabBar()->setTabText(newsFeedTabIndex, QString("%1 (%2)").arg(newsFeedText).arg(count)); + ui.peertabWidget->tabBar()->setTabTextColor(newsFeedTabIndex, Qt::blue); + ui.peertabWidget->tabBar()->setTabIcon(newsFeedTabIndex, QIcon(IMAGE_NEWSFEED_NEW)); + } else { + ui.peertabWidget->tabBar()->setTabText(newsFeedTabIndex, newsFeedText); + ui.peertabWidget->tabBar()->setTabTextColor(newsFeedTabIndex, newsFeedTabColor); + ui.peertabWidget->tabBar()->setTabIcon(newsFeedTabIndex, QIcon(IMAGE_NEWSFEED)); + } +} + +void FriendsDialog::updateOwnStatus(const QString &peer_id, int status) +{ + // add self nick + own status + if (peer_id.toStdString() == rsPeers->getOwnId()) + { + // my status has changed + + switch (status) { + case RS_STATUS_OFFLINE: + ui.avatartoolButton->setStyleSheet("QToolButton#avatartoolButton{border-image:url(:/images/mystatus_bg_offline.png); }"); + break; + + case RS_STATUS_INACTIVE: + ui.avatartoolButton->setStyleSheet("QToolButton#avatartoolButton{border-image:url(:/images/mystatus_bg_idle.png); }"); + break; + + case RS_STATUS_ONLINE: + ui.avatartoolButton->setStyleSheet("QToolButton#avatartoolButton{border-image:url(:/images/mystatus_bg_online.png); }"); + break; + + case RS_STATUS_AWAY: + ui.avatartoolButton->setStyleSheet("QToolButton#avatartoolButton{border-image:url(:/images/mystatus_bg_idle.png); }"); + break; + + case RS_STATUS_BUSY: + ui.avatartoolButton->setStyleSheet("QToolButton#avatartoolButton{border-image:url(:/images/mystatus_bg_busy.png); }"); + break; + } + + return; + } +} diff --git a/retroshare-gui/src/gui/FriendsDialog.h b/retroshare-gui/src/gui/FriendsDialog.h new file mode 100644 index 000000000..21fd42b44 --- /dev/null +++ b/retroshare-gui/src/gui/FriendsDialog.h @@ -0,0 +1,225 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006 - 2011 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _FRIENDSDIALOG_H +#define _FRIENDSDIALOG_H + +#include "chat/ChatStyle.h" +#include "RsAutoUpdatePage.h" + +#include "mainpage.h" + +#include "im_history/IMHistoryKeeper.h" + +// states for sorting (equal values are possible) +// used in BuildSortString - state + name +#define PEER_STATE_ONLINE 1 +#define PEER_STATE_BUSY 2 +#define PEER_STATE_AWAY 3 +#define PEER_STATE_AVAILABLE 4 +#define PEER_STATE_INACTIVE 5 +#define PEER_STATE_OFFLINE 6 + +#define BuildStateSortString(bEnabled,sName,nState) bEnabled ? (QString ("%1").arg(nState) + " " + sName) : sName + +#ifndef MINIMAL_RSGUI +#include "ui_FriendsDialog.h" + +class QFont; +class QAction; +class QTextEdit; +class QTextCharFormat; +class ChatDialog; +class AttachFileItem; +class RSTreeWidgetItemCompareRole; + +class FriendsDialog : public RsAutoUpdatePage +{ + Q_OBJECT + +public: + /** Default Constructor */ + FriendsDialog(QWidget *parent = 0); + /** Default Destructor */ + ~FriendsDialog (); + + // void setChatDialog(ChatDialog *cd); + + virtual void updateDisplay() ; // overloaded from RsAutoUpdatePage + // replaced by shortcut + // virtual void keyPressEvent(QKeyEvent *) ; + +public slots: + + void insertPeers(); + void publicChatChanged(int type); +// void toggleSendItem( QTreeWidgetItem *item, int col ); + + void insertChat(); + void setChatInfo(QString info, QColor color=QApplication::palette().color(QPalette::WindowText)); + void resetStatusBar() ; + + void fileHashingFinished(AttachFileItem* file); + + void smileyWidgetgroupchat(); + void addSmileys(); + + // called by notifyQt when another peer is typing (in group chant and private chat) + void updatePeerStatusString(const QString& peer_id,const QString& status_string,bool is_private_chat) ; + + void updatePeersAvatar(const QString& peer_id); + void updateAvatar(); // called by notifyQt to update the avatar when it gets changed by another component + + void groupsChanged(int type); + +protected: + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); + bool eventFilter(QObject *obj, QEvent *ev); + void showEvent (QShowEvent *event); + +private slots: + void pasteLink() ; + void contextMenu(QPoint) ; + + void on_actionClear_Chat_History_triggered(); + void on_actionDelete_Chat_History_triggered(); + void on_actionMessageHistory_triggered(); + + /** Create the context popup menu and it's submenus */ + void peertreeWidgetCostumPopupMenu( QPoint point ); + + void updateStatusString(const QString& peer_id, const QString& statusString) ; // called when a peer is typing in group chat + void updateStatusTyping() ; // called each time a key is hit + + //void updatePeerStatusString(const QString& peer_id,const QString& chat_status) ; + + /** Export friend in Friends Dialog */ + void exportfriend(); + /** Remove friend */ + void removefriend(); + /** start a chat with a friend **/ + void addFriend(); + void chatfriend(QTreeWidgetItem* ); + void chatfriendproxy(); + void msgfriend(); + void recommendfriend(); + void pastePerson(); + void copyLink(); + void addToGroup(); + void moveToGroup(); + void removeFromGroup(); + void editGroup(); + void removeGroup(); + + void configurefriend(); + void viewprofile(); + + /** RsServer Friend Calls */ + void connectfriend(); + + void setColor(); + void insertSendList(); + void sendMsg(); + + void statusmessage(); + + void setFont(); + void getFont(); + + void changeAvatarClicked(); + void getAvatar(); + void updateOwnStatus(const QString &peer_id, int status); + + void on_actionAdd_Group_activated(); + void on_actionCreate_New_Forum_activated(); + void on_actionCreate_New_Channel_activated(); + + void loadmypersonalstatus(); + + void addExtraFile(); + void addAttachment(std::string); + + bool fileSave(); + bool fileSaveAs(); + + void setCurrentFileName(const QString &fileName); + + void setStateColumn(); + void sortPeersAscendingOrder(); + void sortPeersDescendingOrder(); + void peerSortIndicatorChanged(int,Qt::SortOrder); + + void newsFeedChanged(int count); + +signals: + void friendsUpdated() ; + void notifyGroupChat(const QString&,const QString&) ; + +private: + void processSettings(bool bLoad); + void addChatMsg(bool incoming, bool history, QString &name, QDateTime &recvTime, QString &message); + + void colorChanged(const QColor &c); + void fontChanged(const QFont &font); + + class QLabel *iconLabel, *textLabel; + class QWidget *widget; + class QWidgetAction *widgetAction; + class QSpacerItem *spacerItem; + + RSTreeWidgetItemCompareRole *m_compareRole; + + void displayMenu(); + ///play the sound when recv a message + void playsound(); + + QString fileName; + bool groupsHasChanged; + std::list openGroups; + + /* Worker Functions */ + /* (1) Update Display */ + + /* (2) Utility Fns */ + QTreeWidgetItem *getCurrentPeer(); + + IMHistoryKeeper historyKeeper; + ChatStyle style; + + QColor mCurrentColor; + time_t last_status_send_time ; + + QFont mCurrentFont; /* how the text will come out */ + + int newsFeedTabIndex; + QColor newsFeedTabColor; + QString newsFeedText; + bool wasStatusColumnHidden; + bool correctColumnStatusSize; + + /** Qt Designer generated object */ + Ui::FriendsDialog ui; +}; + +#endif // MINIMAL_RSGUI + +#endif diff --git a/retroshare-gui/src/gui/FriendsDialog.ui b/retroshare-gui/src/gui/FriendsDialog.ui new file mode 100644 index 000000000..b1e748afe --- /dev/null +++ b/retroshare-gui/src/gui/FriendsDialog.ui @@ -0,0 +1,1608 @@ + + + FriendsDialog + + + + 0 + 0 + 764 + 428 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + Qt::NoContextMenu + + + + + + Qt::Horizontal + + + + + 6 + + + 0 + + + + + QFrame#frame_2{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + 0 + + + + + + + + :/images/user/friends24.png + + + + + + + + Arial + 10 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + + + + + Qt::NoFocus + + + Add + + + QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + } + + QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open { + position: relative; + top: 2px; left: 2px; /* shift the arrow by 2 px */ + } + + QPushButton:hover { + border: 1px solid #CCCCCC; + } + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + 16 + 16 + + + + false + + + true + + + + + + + Qt::Horizontal + + + + 123 + 13 + + + + + + + + Qt::NoFocus + + + Display + + + QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + } + + QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open { + position: relative; + top: 2px; left: 2px; /* shift the arrow by 2 px */ + } + + QPushButton:hover { + border: 1px solid #CCCCCC; + } + + + + :/images/looknfeel.png:/images/looknfeel.png + + + + 24 + 16 + + + + true + + + true + + + + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + + 16777215 + 16777215 + + + + + Arial + 9 + PreferAntialias + true + + + + Qt::CustomContextMenu + + + false + + + QTreeWidget#peertreeWidget{border: 1px solid #CCCCCC; +background: white;} + + + false + + + + 24 + 24 + + + + 1 + + + 20 + + + true + + + true + + + true + + + false + + + false + + + 200 + + + 200 + + + + Friends + + + + + Status + + + + + + + + + + 1 + + + + + + 0 + 0 + + + + + 0 + 70 + + + + + 16777215 + 70 + + + + QFrame#frame{background-image: url(:/images/connect/connectFriendBanner.png)} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 1 + + + 1 + + + + + + 61 + 61 + + + + + 61 + 61 + + + + Add or Change your Avatar + + + QToolButton#avatartoolButton{border-image: url(:/images/mystatus_bg.png);} + + + + + + + 43 + 43 + + + + true + + + + + + + + 0 + 32 + + + + + 16777215 + 42 + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; color:#00aa00;">nickname (me)</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 221 + 76 + + + + + + + + + 0 + 0 + + + + Edit Personal message + + + QPushButton:hover { + border: 1px solid #CCCCCC; + } + + + + + + true + + + + + + + Qt::Horizontal + + + + 277 + 20 + + + + + + + + + + + 0 + + + + Group Chat + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::Vertical + + + 5 + + + + + 0 + 0 + + + + + 0 + 60 + + + + QTextEdit#msgText{border: 1px solid #CCCCCC; +background: white;} + + + true + + + true + + + true + + + + + + 0 + + + + + + + + + + + + + 30 + 0 + + + + + 0 + 30 + + + + + 16777215 + 16777215 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::CustomContextMenu + + + Messages entered here are sent to all collected friends + + + QTextEdit#lineEdit{border: 1px solid #CCCCCC; +} + + + + + + + + + + + + 16777215 + 38 + + + + QFrame#buttonframe{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + 6 + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + + + + + :/images/emoticons/kopete/kopete020.png:/images/emoticons/kopete/kopete020.png + + + + 24 + 24 + + + + true + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + Bold + + + + + + + :/images/edit-bold.png:/images/edit-bold.png + + + true + + + true + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + Underline + + + + + + + :/images/edit-underline.png:/images/edit-underline.png + + + true + + + true + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + Italic + + + + + + + :/images/edit-italic.png:/images/edit-italic.png + + + true + + + true + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + Font + + + + + + + :/images/fonts.png:/images/fonts.png + + + true + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + Text Color + + + + + + true + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + + 24 + 24 + + + + Qt::NoFocus + + + QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + } + + QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open { + position: relative; + top: 1px; left: 1px; /* shift the arrow by 2 px */ + } + + QPushButton:hover { + border: 1px solid #CCCCCC; + } + + + + + + + :/images/configure.png:/images/configure.png + + + + 22 + 22 + + + + true + + + + + + + + 0 + 0 + + + + + 26 + 26 + + + + + 26 + 26 + + + + Qt::NoFocus + + + Attach File + + + + + + + :/images/add-share24.png:/images/add-share24.png + + + + 24 + 24 + + + + true + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 321 + 20 + + + + + + + + Send + + + + + + + + + + + + + + + + + + + + + + + + :/images/edit-clear-history.png:/images/edit-clear-history.png + + + Clear Chat History + + + + + + :/images/user/add_user16.png:/images/user/add_user16.png + + + Add Friend + + + + + + :/images/contact_new.png:/images/contact_new.png + + + Create new Profile + + + + + + :/images/new_forum16.png:/images/new_forum16.png + + + Create new Forum + + + Create new Forum + + + F + + + + + + :/images/add_channel24.png:/images/add_channel24.png + + + Create new Channel + + + Create new Channel + + + C + + + + + + :/images/add_image24.png:/images/add_image24.png + + + Add your Avatar Picture + + + A + + + + + + :/images/message-news.png:/images/message-news.png + + + Set your Personal Message + + + Edit your status Message + + + + + Browse Message History + + + Browse History + + + + + Save Chat History + + + Save Chat History + + + + + true + + + Hide Offline Friends + + + + + true + + + Hide Status Column + + + + + true + + + Sort by State + + + Sort by State + + + + + true + + + Hide State + + + + + + :/images/user/add_group22.png:/images/user/add_group22.png + + + Add a new Group + + + Add a new Group + + + + + + :/images/sort_decrease.png:/images/sort_decrease.png + + + Sort Descending Order + + + Sort Descending Order + + + + + + :/images/sort_incr.png:/images/sort_incr.png + + + Sort Ascending Order + + + Sort Ascending Order + + + + + + :/images/edit-clear-history.png:/images/edit-clear-history.png + + + Delete Chat History + + + Deletes all stored and displayed chat history + + + + + + RSTabWidget + QTabWidget +
    gui/common/RSTabWidget.h
    + 1 +
    +
    + + +
    diff --git a/retroshare-gui/src/gui/GenCertDialog.cpp b/retroshare-gui/src/gui/GenCertDialog.cpp new file mode 100644 index 000000000..f1e31a767 --- /dev/null +++ b/retroshare-gui/src/gui/GenCertDialog.cpp @@ -0,0 +1,354 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include "GenCertDialog.h" +#include "InfoDialog.h" +#include +#include +#include +#include +#include + + +/* Define the format used for displaying the date and time */ +#define DATETIME_FMT "MMM dd hh:mm:ss" + + +/** Default constructor */ +GenCertDialog::GenCertDialog(QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + connect(ui.new_gpg_key_checkbox, SIGNAL(clicked()), this, SLOT(newGPGKeyGenUiSetup())); + + connect(ui.genButton, SIGNAL(clicked()), this, SLOT(genPerson())); + connect(ui.infopushButton,SIGNAL(clicked()), this, SLOT(infodlg())); + //connect(ui.selectButton, SIGNAL(clicked()), this, SLOT(selectFriend())); + //connect(ui.friendBox, SIGNAL(stateChanged(int)), this, SLOT(checkChanged(int))); + + //ui.genName->setFocus(Qt::OtherFocusReason); + + QString titleString("%1"); + + /* get all available pgp private certificates.... + * mark last one as default. + */ + std::cerr << "Finding PGPUsers" << std::endl; + + std::list pgpIds; + std::list::iterator it; + bool foundGPGKeys = false; + if (RsInit::GetPGPLogins(pgpIds)) { + for(it = pgpIds.begin(); it != pgpIds.end(); it++) + { + const QVariant & userData = QVariant(QString::fromStdString(*it)); + std::string name, email; + RsInit::GetPGPLoginDetails(*it, name, email); + std::cerr << "Adding PGPUser: " << name << " id: " << *it << std::endl; + QString gid = QString::fromStdString(*it).right(8) ; + ui.genPGPuser->addItem(QString::fromStdString(name + " <" + email + "> (")+gid+")", userData); + foundGPGKeys = true; + } + } + + if (foundGPGKeys) { + ui.no_gpg_key_label->hide(); + ui.progressBar->hide(); + ui.new_gpg_key_checkbox->setChecked(false); + setWindowTitle(tr("Create new Location")); + ui.genButton->setText(tr("Generate new Location")); + ui.label_3->setText( titleString.arg( tr("Create a new Location") ) ) ; + genNewGPGKey = false; + } else { + ui.no_gpg_key_label->show(); + ui.new_gpg_key_checkbox->setChecked(true); + ui.new_gpg_key_checkbox->hide(); + ui.progressBar->hide(); + setWindowTitle(tr("Create new Profile")); + ui.genButton->setText(tr("Generate new Profile")); + ui.label_3->setText( titleString.arg( tr("Create a new Profile") ) ) ; + genNewGPGKey = true; + } + newGPGKeyGenUiSetup(); +} + +/** Destructor. */ +//GenCertDialog::~GenCertDialog() +//{ +//} + + +/** + Overloads the default show() slot so we can set opacity*/ + +void GenCertDialog::show() +{ + //loadSettings(); + if(!this->isVisible()) { + QWidget::show(); + + } +} + +void GenCertDialog::closeEvent (QCloseEvent * event) +{ + + + QDialog::closeEvent(event); +} + +void GenCertDialog::closeinfodlg() +{ + close(); +} + +void GenCertDialog::newGPGKeyGenUiSetup() { + + QString titleStr("%1"); + + if (ui.new_gpg_key_checkbox->isChecked()) { + genNewGPGKey = true; + ui.name_label->show(); + ui.name_input->show(); + ui.email_label->show(); + ui.email_input->show(); + ui.password_label->show(); + ui.password_input->show(); + ui.genPGPuserlabel->hide(); + ui.genPGPuser->hide(); + setWindowTitle(tr("Create new Profile")); + ui.genButton->setText(tr("Generate new Profile")); + ui.label_3->setText( titleStr.arg( tr("Create a new Profile") ) ) ; + } else { + genNewGPGKey = false; + ui.name_label->hide(); + ui.name_input->hide(); + ui.email_label->hide(); + ui.email_input->hide(); + ui.password_label->hide(); + ui.password_input->hide(); + ui.genPGPuserlabel->show(); + ui.genPGPuser->show(); + setWindowTitle(tr("Create new Location")); + ui.genButton->setText(tr("Generate new Location")); + ui.label_3->setText( titleStr.arg( tr("Create a new Location") ) ) ; + } +} +void GenCertDialog::genPerson() +{ + + /* Check the data from the GUI. */ + std::string genLoc = ui.location_input->text().toStdString(); + std::string PGPId; + + if (!genNewGPGKey) { + if (ui.location_input->text().length() < 3) { + /* Message Dialog */ + QMessageBox::warning ( NULL, + tr("Generate GPG key Failure"), + tr("Location field is required with a minimum of 3 characters"), + QMessageBox::Ok); + return; + } + int pgpidx = ui.genPGPuser->currentIndex(); + if (pgpidx < 0) + { + /* Message Dialog */ + QMessageBox::warning ( NULL, + "Generate ID Failure", + "Missing PGP Certificate", + QMessageBox::Ok); + return; + } + QVariant data = ui.genPGPuser->itemData(pgpidx); + PGPId = (data.toString()).toStdString(); + } else { + if (ui.password_input->text().length() < 3 || ui.name_input->text().length() < 3 + || ui.email_input->text().length() < 3 || ui.location_label->text().length() < 3) { + /* Message Dialog */ + QMessageBox::warning ( NULL, + tr("Generate GPG key Failure"), + tr("All fields are required with a minimum of 3 characters"), + QMessageBox::Ok); + return; + } + //generate a new gpg key + std::string err_string; + ui.no_gpg_key_label->setText(tr("Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. \n\nFill in your GPG password when asked, to sign your new key.")); + ui.no_gpg_key_label->show(); + ui.progressBar->show(); + ui.new_gpg_key_checkbox->hide(); + ui.name_label->hide(); + ui.name_input->hide(); + ui.email_label->hide(); + ui.email_input->hide(); + ui.password_label->hide(); + ui.password_input->hide(); + ui.genPGPuserlabel->hide(); + ui.genPGPuser->hide(); + ui.location_label->hide(); + ui.location_input->hide(); + ui.infopushButton->hide(); + ui.genButton->hide(); + ui.label_location2->hide(); +// QMessageBox::StandardButton info = QMessageBox::information( NULL, +// "Generating GPG key", +// "This process can take some time (approximately one minute), please be patient after pressing the OK button", +// QMessageBox::Ok); + //info-> + setCursor(Qt::WaitCursor) ; + + QCoreApplication::processEvents(); + while(QAbstractEventDispatcher::instance()->processEvents(QEventLoop::AllEvents)) ; + + RsInit::GeneratePGPCertificate(ui.name_input->text().toStdString(), ui.email_input->text().toStdString(), ui.password_input->text().toStdString(), PGPId, err_string); + + setCursor(Qt::ArrowCursor) ; + } + + + //generate a random ssl password + std::string sslPasswd = RSRandom::random_alphaNumericString(RsInit::getSslPwdLen()) ; + +// std::cerr << "Generated sslPasswd: " << sslPasswd << std::endl; + +// const int PWD_LEN = RsInit::getSslPwdLen(); +// +// for( int i = 0 ; i < PWD_LEN ; ++i ) +// { +// int iNumber; +// iNumber = qrand()%(127-33) + 33; +// sslPasswd += (char)iNumber; +// } + + /* Initialise the PGP user first */ + RsInit::SelectGPGAccount(PGPId); + //RsInit::LoadGPGPassword(PGPpasswd); + + std::string sslId; + std::cerr << "GenCertDialog::genPerson() Generating SSL cert with gpg id : " << PGPId << std::endl; + std::string err; + bool okGen = RsInit::GenerateSSLCertificate(PGPId, "", genLoc, "", sslPasswd, sslId, err); + + if (okGen) + { + /* complete the process */ + RsInit::LoadPassword(sslId, sslPasswd); + loadCertificates(); + } + else + { + /* Message Dialog */ + QMessageBox::warning ( NULL, + "Generate ID Failure", + "Failed to Generate your new Certificate, maybe PGP password is wrong !", + QMessageBox::Ok); + } +} + + + + + +void GenCertDialog::selectFriend() +{ + +#if 0 + /* still need to find home (first) */ + + QString fileName = QFileDialog::getOpenFileName(this, tr("Select Trusted Friend"), "", + tr("Certificates (*.pqi *.pem)")); + + std::string fname, userName; + fname = fileName.toStdString(); + if (RsInit::ValidateTrustedUser(fname, userName)) + { + ui.genFriend -> setText(QString::fromStdString(userName)); + } + else + { + ui.genFriend -> setText(""); + } +#endif + +} + + +void GenCertDialog::checkChanged(int i) +{ + +#if 0 + if (i) + { + selectFriend(); + } + else + { + /* invalidate selection */ + std::string fname = ""; + std::string userName = ""; + RsInit::ValidateTrustedUser(fname, userName); + ui.genFriend -> setText(""); + } +#endif + +} + + +void GenCertDialog::loadCertificates() +{ + std::string lockFile; + int retVal = RsInit::LockAndLoadCertificates(false, lockFile); + switch(retVal) + { + case 0: close(); + break; + case 1: QMessageBox::warning( this, + tr("Multiple instances"), + tr("Another RetroShare using the same profile is " + "already running on your system. Please close " + "that instance first") ); + break; + case 2: QMessageBox::warning( this, + tr("Multiple instances"), + tr("An unexpected error occurred when Retroshare" + "tried to acquire the single instance lock") ); + break; + case 3: QMessageBox::warning( this, + tr("Generate ID Failure"), + tr("Failed to Load your new Certificate!") ); + break; + default: std::cerr << "StartDialog::loadCertificates() unexpected switch value " << retVal << std::endl; + } +} + +void GenCertDialog::infodlg() +{ + InfoDialog infodialog (this); + infodialog.exec (); +} diff --git a/retroshare-gui/src/gui/GenCertDialog.h b/retroshare-gui/src/gui/GenCertDialog.h new file mode 100644 index 000000000..a686d743c --- /dev/null +++ b/retroshare-gui/src/gui/GenCertDialog.h @@ -0,0 +1,76 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _GENCERTDIALOG_H +#define _GENCERTDIALOG_H + +//#include "rsiface/rsiface.h" + +#include "ui_GenCertDialog.h" + + + +class GenCertDialog : public QDialog +{ + Q_OBJECT + +public: + /** Default constructor */ + GenCertDialog(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + + //~GenCertDialog(); + +public slots: + /** Overloaded QWidget.show */ + void show(); + +protected: + void closeEvent (QCloseEvent * event); + +private slots: + + void closeinfodlg(); + void genPerson(); + //void loadPerson(); + void selectFriend(); + void checkChanged(int i); + void infodlg(); + void newGPGKeyGenUiSetup(); + +private: + + /** Loads the saved connectidialog settings */ + // void loadSettings(); + void loadCertificates(); + + + QMovie *movie; + + /** Qt Designer generated object */ + Ui::GenCertDialog ui; + + bool genNewGPGKey; +}; + +#endif + diff --git a/retroshare-gui/src/gui/GenCertDialog.ui b/retroshare-gui/src/gui/GenCertDialog.ui new file mode 100644 index 000000000..946cda23b --- /dev/null +++ b/retroshare-gui/src/gui/GenCertDialog.ui @@ -0,0 +1,914 @@ + + + GenCertDialog + + + + 0 + 0 + 600 + 480 + + + + + 0 + 0 + + + + + 167777 + 167777 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 160 + 160 + 160 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 160 + 160 + 160 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 160 + 160 + 160 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + Create new Profile + + + + :/images/rstray3.png:/images/rstray3.png + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +*{ +color: black; +} + +QComboBox QAbstractItemView { +background-color:white; +} + +QComboBox::down-arrow { +image: url(:/images/combobox_arrow.png); +} + +QComboBox:drop-down +{ +subcontrol-origin: padding; +subcontrol-position: top right; +border-left-style: none; +border-top-right-radius: 1px; +border-bottom-right-radius: 1px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + + 0 + + + 0 + + + + + + 0 + 30 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 20 + + + + + + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + true + + + + + + + + 16777215 + 32 + + + + Your profile is associated to a GPG key + + + Generate a new Profile + + + + :/images/contact_new128.png:/images/contact_new128.png + + + + 32 + 32 + + + + false + + + + + + + + 16777215 + 32 + + + + + + + + + + + + + Use Profile + + + + + + + Your profile is associated to a GPG key + + + + + + + Name + + + + + + + Enter here your nickname + + + + + + + Email + + + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + + + This Password is for GPG + + + Password + + + + + + + Put a strong password here. This password protects your GPG key. + + + + + + QLineEdit::Password + + + + + + + Location + + + + + + + + + + + 0 + 30 + + + + 1 + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + false + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0 + + + -1 + + + false + + + + + + + + + + + + + 16777215 + 26 + + + + Generate New Profile + + + + :/images/contact_new.png:/images/contact_new.png + + + + + + + Qt::Horizontal + + + + 210 + 22 + + + + + + + + + 16777215 + 26 + + + + Info + + + + :/images/info16.png:/images/info16.png + + + + + + + + + + + + + 16777215 + 140 + + + + QFrame#frame_2{background-image: url(:/images/genbackground.png);} + + + + QFrame::NoFrame + + + QFrame::Plain + + + + + + + 128 + 128 + + + + + + + :/images/contact_new128.png + + + true + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + + + + + + genPGPuser + name_input + email_input + password_input + location_input + + + + + + diff --git a/retroshare-gui/src/gui/HelpDialog.cpp b/retroshare-gui/src/gui/HelpDialog.cpp new file mode 100644 index 000000000..c5d07d4f3 --- /dev/null +++ b/retroshare-gui/src/gui/HelpDialog.cpp @@ -0,0 +1,89 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#include "HelpDialog.h" +#include +#include + +#include +#include + +#include +#include + +/* Images for context menu icons */ +#define IMAGE_DOWNLOAD ":/images/start.png" + +/** Constructor */ +HelpDialog::HelpDialog(QWidget *parent) +:QDialog(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + //QFile licenseFile(QLatin1String(":/images/COPYING")); + QFile licenseFile(QLatin1String(":/help/licence.html")); + if (licenseFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&licenseFile); + ui.license->setText(in.readAll()); + } + QFile authorsFile(QLatin1String(":/help/authors.html")); + if (authorsFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&authorsFile); + ui.authors->setText(in.readAll()); + } + QFile thanksFile(QLatin1String(":/help/thanks.html")); + if (thanksFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&thanksFile); + ui.thanks->setText(in.readAll()); + } + + QFile versionFile(QLatin1String(":/help/version.html")); + if (versionFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&versionFile); + QString version = in.readAll(); + +#ifdef ADD_LIBRETROSHARE_VERSION_INFO + /* get libretroshare version */ + std::map::iterator vit; + std::map versions; + const RsConfig &conf = rsiface->getConfig(); + bool retv = rsDisc->getDiscVersions(versions); + if (retv && versions.end() != (vit = versions.find(conf.ownId))) + { + version += QString::fromStdString("Retroshare library version : \n") + QString::fromStdString(vit->second); + } +#endif + + ui.version->setText(version); + } + + ui.label_2->setMinimumWidth(20); + + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + + diff --git a/retroshare-gui/src/gui/HelpDialog.h b/retroshare-gui/src/gui/HelpDialog.h new file mode 100644 index 000000000..2e25adb58 --- /dev/null +++ b/retroshare-gui/src/gui/HelpDialog.h @@ -0,0 +1,51 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _HELPDIALOG_H +#define _HELPDIALOG_H + +#include + + +//#include "mainpage.h" +#include "ui_HelpDialog.h" + +#include + +class HelpDialog : public QDialog +{ + Q_OBJECT + +public: + /** Default Constructor */ + HelpDialog(QWidget *parent = 0); + /** Default Destructor */ + +private slots: + +private: + /** Qt Designer generated object */ + Ui::HelpDialog ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/HelpDialog.ui b/retroshare-gui/src/gui/HelpDialog.ui new file mode 100644 index 000000000..5c7929e4e --- /dev/null +++ b/retroshare-gui/src/gui/HelpDialog.ui @@ -0,0 +1,805 @@ + + + HelpDialog + + + + 0 + 0 + 590 + 521 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + 0 + + + 0 + + + + + + 9 + + + + 0 + + + + About + + + + 9 + + + 6 + + + + + + 0 + 0 + + + + + 16777215 + 70 + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + true + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + Authors + + + + 6 + + + 9 + + + + + false + + + QTextEdit::NoWrap + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + false + + + Qt::TextBrowserInteraction + + + + + + + + Thanks to + + + + 6 + + + 9 + + + + + false + + + QTextEdit::NoWrap + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + false + + + Qt::TextBrowserInteraction + + + + + + + + Translation + + + + 6 + + + 9 + + + + + false + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + false + + + Qt::TextSelectableByMouse + + + + + + + + License Agreement + + + + 6 + + + 9 + + + + + false + + + QTextEdit::WidgetWidth + + + false + + + Qt::TextBrowserInteraction + + + + + + + + + + + 6 + + + 6 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0 + + + 6 + + + + + + + + :/images/info16.png + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + + + + + + + translation + authors + license + tabWidget + + + + + + diff --git a/retroshare-gui/src/gui/InfoDialog.cpp b/retroshare-gui/src/gui/InfoDialog.cpp new file mode 100644 index 000000000..7c6074b74 --- /dev/null +++ b/retroshare-gui/src/gui/InfoDialog.cpp @@ -0,0 +1,51 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#include "InfoDialog.h" +#include + +#include +#include + +#include +#include + +/* Images for context menu icons */ +#define IMAGE_DOWNLOAD ":/images/start.png" + +/** Constructor */ +InfoDialog::InfoDialog(QWidget *parent) +:QDialog(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + + diff --git a/retroshare-gui/src/gui/InfoDialog.h b/retroshare-gui/src/gui/InfoDialog.h new file mode 100644 index 000000000..dc395a46c --- /dev/null +++ b/retroshare-gui/src/gui/InfoDialog.h @@ -0,0 +1,49 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _INFODIALOG_H +#define _INFODIALOG_H + +#include + +#include "ui_InfoDialog.h" + +#include + +class InfoDialog : public QDialog +{ + Q_OBJECT + +public: + /** Default Constructor */ + InfoDialog(QWidget *parent = 0); + /** Default Destructor */ + +private slots: + +private: + /** Qt Designer generated object */ + Ui::InfoDialog ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/InfoDialog.ui b/retroshare-gui/src/gui/InfoDialog.ui new file mode 100644 index 000000000..1ee920d46 --- /dev/null +++ b/retroshare-gui/src/gui/InfoDialog.ui @@ -0,0 +1,87 @@ + + + InfoDialog + + + + 0 + 0 + 624 + 313 + + + + Info + + + + :/images/info16.png:/images/info16.png + + + + + + QLabel#label{background: white; +border: 2px solid black; +border-radius: 10px;} + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + 9 + + + true + + + + + + + Qt::Horizontal + + + + 502 + 20 + + + + + + + + QDialogButtonBox::Close + + + + + + + + + + diff --git a/retroshare-gui/src/gui/LinksDialog.cpp b/retroshare-gui/src/gui/LinksDialog.cpp new file mode 100644 index 000000000..e073003ce --- /dev/null +++ b/retroshare-gui/src/gui/LinksDialog.cpp @@ -0,0 +1,1055 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include + +#include "LinksDialog.h" +#include "RetroShareLink.h" +#include "AddLinksDialog.h" +#include +#include +#include + +#include + + +/* Images for context menu icons */ +#define IMAGE_EXPORTFRIEND ":/images/exportpeers_16x16.png" +#define IMAGE_GREAT ":/images/filerating5.png" +#define IMAGE_GOOD ":/images/filerating4.png" +#define IMAGE_OK ":/images/filerating3.png" +#define IMAGE_SUX ":/images/filerating2.png" +#define IMAGE_BADLINK ":/images/filerating1.png" +#define IMAGE_NOCOMMENTRATING ":/images/filerating0.png" +#define IMAGE_DOWNLOAD ":/images/download16.png" + +/****** + * #define LINKS_DEBUG 1 + *****/ + +/** Constructor */ +LinksDialog::LinksDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.linkTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( linkTreeWidgetCostumPopupMenu( QPoint ) ) ); + + + /* link combos */ + connect( ui.rankComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( changedSortRank( int ) ) ); + connect( ui.periodComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( changedSortPeriod( int ) ) ); + connect( ui.fromComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( changedSortFrom( int ) ) ); + connect( ui.topComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( changedSortTop( int ) ) ); + + /* add button */ + connect( ui.addButton, SIGNAL( clicked( void ) ), this, SLOT( addLinkComment( void ) ) ); + connect( ui.expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggleWindows( void ) ) ); + + connect( ui.pushButton, SIGNAL( clicked( ) ), this, SLOT( addNewLink( ) ) ); + + connect( ui.linkTreeWidget, SIGNAL( currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem * ) ), + this, SLOT( changedItem ( QTreeWidgetItem *, QTreeWidgetItem * ) ) ); + + connect( ui.linkTreeWidget, SIGNAL( itemDoubleClicked ( QTreeWidgetItem *, int ) ), + this, SLOT( openLink ( QTreeWidgetItem *, int ) ) ); + + connect( ui.anonBox, SIGNAL( stateChanged ( int ) ), this, SLOT( checkAnon ( void ) ) ); + + connect( ui.linklabel, SIGNAL(anchorClicked(const QUrl &)), SLOT(anchorClicked(const QUrl &))); + + + mStart = 0; + + + /* Set header resize modes and initial section sizes */ + QHeaderView * _header = ui.linkTreeWidget->header () ; + _header->setResizeMode (0, QHeaderView::Interactive); + _header->setResizeMode (1, QHeaderView::Interactive); + _header->setResizeMode (2, QHeaderView::Interactive); + + _header->resizeSection ( 0, 400 ); + _header->resizeSection ( 1, 60 ); + _header->resizeSection ( 2, 150 ); + + ui.linkTreeWidget->setSortingEnabled(true); + + ui.linklabel->setMinimumWidth(20); + + + /* Set a GUI update timer - much cleaner than + * doing everything through the notify agent + */ + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + timer->start(1000); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif + +} + +void LinksDialog::checkUpdate() +{ + /* update */ + if (!rsRanks) + return; + + if (rsRanks->updated()) + { + updateLinks(); + } + + return; +} + +void LinksDialog::linkTreeWidgetCostumPopupMenu( QPoint point ) +{ + + QMenu contextMnu( this ); + + QAction *voteupAct = new QAction(QIcon(IMAGE_EXPORTFRIEND), tr( "Share Link Anonymously" ), &contextMnu ); + connect( voteupAct , SIGNAL( triggered() ), this, SLOT( voteup_anon() ) ); + + + QMenu *voteMenu = new QMenu( tr("Vote on Link"), &contextMnu ); + voteMenu->setIcon(QIcon(IMAGE_EXPORTFRIEND)); + + QAction *vote_p2 = new QAction( QIcon(IMAGE_GREAT), "[+2] Great", &contextMnu ); + connect( vote_p2 , SIGNAL( triggered() ), this, SLOT( voteup_p2() ) ); + voteMenu->addAction(vote_p2); + QAction *vote_p1 = new QAction( QIcon(IMAGE_GOOD), "[+1] Good", &contextMnu ); + connect( vote_p1 , SIGNAL( triggered() ), this, SLOT( voteup_p1() ) ); + voteMenu->addAction(vote_p1); + QAction *vote_p0 = new QAction( QIcon(IMAGE_OK), "[+0] Okay", &contextMnu ); + connect( vote_p0 , SIGNAL( triggered() ), this, SLOT( voteup_p0() ) ); + voteMenu->addAction(vote_p0); + QAction *vote_m1 = new QAction( QIcon(IMAGE_SUX), "[-1] Sux", &contextMnu ); + connect( vote_m1 , SIGNAL( triggered() ), this, SLOT( voteup_m1() ) ); + voteMenu->addAction(vote_m1); + QAction *vote_m2 = new QAction( QIcon(IMAGE_BADLINK), "[-2] BAD LINK", &contextMnu ); + connect( vote_m2 , SIGNAL( triggered() ), this, SLOT( voteup_m2() ) ); + voteMenu->addAction(vote_m2); + + QAction *downloadAct = new QAction(QIcon(IMAGE_DOWNLOAD), tr("Download"), &contextMnu); + connect(downloadAct, SIGNAL(triggered()), this, SLOT(downloadSelected())); + + contextMnu.addAction(voteupAct); + contextMnu.addSeparator(); + contextMnu.addMenu(voteMenu); + contextMnu.addSeparator(); + contextMnu.addAction(downloadAct); + + contextMnu.exec(QCursor::pos()); +} + +void LinksDialog::changedSortRank( int index ) +{ + /* update */ + if (!rsRanks) + return; + + /* translate */ + uint32_t type = 0; + switch (index) + { + case 1: + type = RS_RANK_TIME; + break; + case 2: + type = RS_RANK_SCORE; + break; + default: + case 0: + type = RS_RANK_ALG; + break; + } + + if (type) + { + rsRanks->setSortMethod(type); + } + updateLinks(); +} + +void LinksDialog::changedSortPeriod( int index ) +{ + /* update */ + if (!rsRanks) + return; + + /* translate */ + uint32_t period = 0; + switch (index) + { + case 1: + period = 60 * 60 * 24 * 7; /* WEEK */ + break; + case 2: + period = 60 * 60 * 24; /* DAY */ + break; + default: + case 0: + period = 60 * 60 * 24 * 30; /* MONTH */ + break; + } + + if (period) + { + rsRanks->setSortPeriod(period); + } + updateLinks(); +} + +void LinksDialog::changedSortFrom( int index ) +{ + /* update */ + if (!rsRanks) + return; + + std::list peers; + + /* translate */ + switch (index) + { + default: + case 0: + break; + case 1: + peers.push_back(rsPeers->getOwnId()); + break; + } + + if (peers.size() < 1) + { + rsRanks->clearPeerFilter(); + } + else + { + rsRanks->setPeerFilter(peers); + } + updateLinks(); +} + +#define ENTRIES_PER_BLOCK 100 + +void LinksDialog::changedSortTop( int index ) +{ + /* update */ + if (!rsRanks) + return; + + std::list peers; + + /* translate */ + switch (index) + { + default: + case 0: + mStart = 0; + break; + case 1: + mStart = 1 * ENTRIES_PER_BLOCK; + break; + case 2: + mStart = 2 * ENTRIES_PER_BLOCK; + break; + case 3: + mStart = 3 * ENTRIES_PER_BLOCK; + break; + case 4: + mStart = 4 * ENTRIES_PER_BLOCK; + break; + case 5: + mStart = -1; + break; + } + updateLinks(); +} + + +/* get the list of Links from the RsRanks. */ +void LinksDialog::updateLinks() +{ + + std::list rids; + std::list::iterator rit; + std::list::iterator cit; + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::updateLinks()" << std::endl; +#endif + + /* Work out the number/entries to show */ + uint32_t count = rsRanks->getRankingsCount(); + uint32_t start; + + uint32_t entries = ENTRIES_PER_BLOCK; + if (count < entries) + { + entries = count; + } + + if (mStart == -1) + { + /* backwards */ + start = count-entries; + } + else + { + start = mStart; + if (start + entries > count) + { + start = count - entries; + } + } + + /* get a link to the table */ + QTreeWidget *linkWidget = ui.linkTreeWidget; + QList items; + + rsRanks->getRankings(start, entries, rids); + float maxRank = rsRanks->getMaxRank(); + + for(rit = rids.begin(); rit != rids.end(); rit++) + { + RsRankDetails detail; + if (!rsRanks->getRankDetails(*rit, detail)) + { + continue; + } + + /* create items */ + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + + /* (0) Title */ + { + item -> setText(0, QString::fromStdWString(detail.title)); + item -> setSizeHint(0, QSize( 20,20 ) ); + + /* Bold and bigger */ + /*QFont font = item->font(0); + font.setBold(true); + font.setPointSize(font.pointSize() + 2); + item->setFont(0, font);*/ + } + + /* (1) Rank */ + { + std::ostringstream out; + out << 100 * (detail.rank / (maxRank + 0.01)); + item -> setText(1, QString::fromStdString(out.str())); + item -> setSizeHint(1, QSize( 20,20 ) ); + + /* Bold and bigger */ + /*QFont font = item->font(1); + font.setBold(true); + font.setPointSize(font.pointSize() + 2); + item->setFont(1, font);*/ + } + + /* (2) Link */ + { + item -> setText(2, QString::fromStdWString(detail.link)); + item -> setSizeHint(2, QSize( 20,20 ) ); + + /* Bold and bigger */ + /*QFont font = item->font(2); + font.setBold(true); + font.setPointSize(font.pointSize() + 2); + item->setFont(2, font);*/ + } + + /* (3) Date */ + /*{ + QDateTime qtime; + qtime.setTime_t(it->lastPost); + QString timestamp = qtime.toString("yyyy-MM-dd hh:mm:ss"); + item -> setText(3, timestamp); + }*/ + + + /* (4) rid */ + item -> setText(4, QString::fromStdString(detail.rid)); + + + /* add children */ + int i = 0; + for(cit = detail.comments.begin(); + cit != detail.comments.end(); cit++, i++) + { + /* create items */ + QTreeWidgetItem *child = new QTreeWidgetItem((QTreeWidget*)0); + + QString commentText; + QString peerScore; + if (cit->score > 1) + { + peerScore = "[+2] "; + child -> setIcon(0,(QIcon(IMAGE_GREAT))); + item -> setIcon(0,(QIcon(IMAGE_GREAT))); + //peerScore = "[+2 Great Link] "; + } + else if (cit->score == 1) + { + peerScore = "[+1] "; + child -> setIcon(0,(QIcon(IMAGE_GOOD))); + item -> setIcon(0,(QIcon(IMAGE_GOOD))); + //peerScore = "[+1 Good] "; + } + else if (cit->score == 0) + { + peerScore = "[+0] "; + child -> setIcon(0,(QIcon(IMAGE_OK))); + item -> setIcon(0,(QIcon(IMAGE_OK))); + //peerScore = "[+0 Okay] "; + } + else if (cit->score == -1) + { + peerScore = "[-1] "; + child -> setIcon(0,(QIcon(IMAGE_SUX))); + item -> setIcon(0,(QIcon(IMAGE_SUX))); + //peerScore = "[-1 Not Worth It] "; + } + else //if (cit->score < -1) + { + peerScore = "[-2 BAD] "; + child -> setIcon(0,(QIcon(IMAGE_BADLINK))); + item -> setIcon(0,(QIcon(IMAGE_BADLINK))); + //peerScore = "[-2 BAD Link] "; + } + + /* (0) Comment */ + if (cit->comment != L"") + { + commentText = peerScore + QString::fromStdWString(cit->comment); + } + else + { + commentText = peerScore + "No Comment"; + } + child -> setText(0, commentText); + + /* (2) Peer / Date */ + { + QDateTime qtime; + qtime.setTime_t(cit->timestamp); + QString timestamp = qtime.toString("yyyy-MM-dd hh:mm:ss"); + + QString peerLabel = QString::fromStdString(rsPeers->getPeerName(cit->id)); + if (peerLabel == "") + { + peerLabel = "<"; + peerLabel += QString::fromStdString(cit->id); + peerLabel += ">"; + } + peerLabel += " "; + + peerLabel += timestamp; + child -> setText(2, peerLabel); + + } + + /* (4) Id */ + child -> setText(4, QString::fromStdString(cit->id)); + + if (i % 2 == 1) + { + /* set to light gray background */ + child->setBackground(0,QBrush(Qt::lightGray)); + child->setBackground(1,QBrush(Qt::lightGray)); + child->setBackground(2,QBrush(Qt::lightGray)); + } + + /* push to items */ + item->addChild(child); + } + + /* add to the list */ + items.append(item); + } + + /* remove old items */ + linkWidget->clear(); + linkWidget->setColumnCount(3); + + /* add the items in! */ + linkWidget->insertTopLevelItems(0, items); + + linkWidget->update(); /* update display */ + + +} + +void LinksDialog::openLink ( QTreeWidgetItem * item, int ) +{ +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::openLink()" << std::endl; +#endif + + /* work out the ids */ + if (!item) + { + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::openLink() Failed Item" << std::endl; +#endif + return; + } + + std::string rid; + std::string pid; + + QTreeWidgetItem *parent = item->parent(); + if (parent) + { + /* a child comment -> ignore double click */ +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::openLink() Failed Child" << std::endl; +#endif + return; + } + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::openLink() " << (item->text(2)).toStdString() << std::endl; +#endif + /* open a browser */ + QUrl url(item->text(2)); + QDesktopServices::openUrl ( url ); + + /* close expansion */ + bool state = item->isExpanded(); + item->setExpanded(!state); +} + +void LinksDialog::changedItem(QTreeWidgetItem *curr, QTreeWidgetItem *) +{ + /* work out the ids */ + if (!curr) + { + updateComments("", ""); + return; + } + + std::string rid; + std::string pid; + + QTreeWidgetItem *parent = curr->parent(); + if (parent) + { + rid = (parent->text(4)).toStdString(); + pid = (curr->text(4)).toStdString(); + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::changedItem() Rid: " << rid << " Pid: " << pid; + std::cerr << std::endl; +#endif + + updateComments(rid, pid); + } + else + { + rid = (curr->text(4)).toStdString(); + +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::changedItem() Rid: " << rid << " Pid: NULL"; + std::cerr << std::endl; +#endif + + updateComments(rid, ""); + } +} + +void LinksDialog::checkAnon() +{ + changedItem(ui.linkTreeWidget->currentItem(), NULL); +} + + +int IndexToScore(int index) +{ + if ((index == -1) || (index > 4)) + return 0; + int score = 2 - index; + return score; +} + +int ScoreToIndex(int score) +{ + if ((score < -2) || (score > 2)) + return 2; + int index = 2 - score; + return index; +} + + +/* get the list of Links from the RsRanks. */ +void LinksDialog::updateComments(std::string rid, std::string ) +{ + std::list::iterator cit; + + + if (ui.anonBox->isChecked()) + { + /* empty everything */ + ui.titleLineEdit->setText(""); + ui.linkLineEdit->setText(""); + ui.linkTextEdit->setText(""); + ui.scoreBox->setCurrentIndex(ScoreToIndex(0)); + mLinkId = rid; /* must be set for Context Menu */ + + /* disable comment + score */ + ui.scoreBox->setEnabled(false); + ui.linkTextEdit->setEnabled(false); + + /* done! */ + return; + } + else + { + /* enable comment + score */ + ui.scoreBox->setEnabled(true); + ui.linkTextEdit->setEnabled(true); + } + + + RsRankDetails detail; + if ((rid == "") || (!rsRanks->getRankDetails(rid, detail))) + { + /* clear it up */ + ui.titleLineEdit->setText(""); + ui.linkLineEdit->setText(""); + ui.linkTextEdit->setText(""); + ui.scoreBox->setCurrentIndex(ScoreToIndex(0)); + mLinkId = rid; + return; + } + + + /* set Link details */ + ui.titleLineEdit->setText(QString::fromStdWString(detail.title)); + ui.linkLineEdit->setText(QString::fromStdWString(detail.link)); + ui.linklabel->setHtml(" " + QString::fromStdWString(detail.link) +""); + + + if (mLinkId == rid) + { + /* leave comments */ + //ui.linkTextEdit->setText(""); + return; + } + + mLinkId = rid; + + /* Add your text to the comment */ + std::string ownId = rsPeers->getOwnId(); + + for(cit = detail.comments.begin(); cit != detail.comments.end(); cit++) + { + if (cit->id == ownId) + break; + } + + if (cit != detail.comments.end()) + { + QString comment = QString::fromStdWString(cit->comment); + ui.linkTextEdit->setText(comment); + ui.scoreBox->setCurrentIndex(ScoreToIndex(cit->score)); + } + else + { + ui.linkTextEdit->setText(""); + ui.scoreBox->setCurrentIndex(ScoreToIndex(0)); + + } + + return; +} + +void LinksDialog::addLinkComment( void ) +{ + /* get the title / link / comment */ + QString title = ui.titleLineEdit->text(); + QString link = ui.linkLineEdit->text(); + QString comment = ui.linkTextEdit->toPlainText(); + int32_t score = IndexToScore(ui.scoreBox->currentIndex()); + + if ((mLinkId == "") || (ui.anonBox->isChecked())) + { + if ((link == "") || (title == "")) + { + QMessageBox::warning ( NULL, "Add Link Failure", "Missing Link and/or Title", QMessageBox::Ok); + /* can't do anything */ + return; + } + + /* add it either way */ + if (ui.anonBox->isChecked()) + { + rsRanks->anonRankMsg("", link.toStdWString(), title.toStdWString()); + } + else + { + rsRanks->newRankMsg( + link.toStdWString(), + title.toStdWString(), + comment.toStdWString(), score); + } + + updateLinks(); + return; + } + + /* get existing details */ + + RsRankDetails detail; + if (!rsRanks->getRankDetails(mLinkId, detail)) + { + /* strange error! */ + QMessageBox::warning ( NULL, "Add Link Failure", "Missing Link Data", QMessageBox::Ok); + return; + } + + if (link.toStdWString() == detail.link) /* same link! - we can add a comment */ + { + if (comment == "") /* no comment! */ + { + QMessageBox::warning ( NULL, "Add Link Failure", "Missing Comment", QMessageBox::Ok); + return; + } + + rsRanks->updateComment(mLinkId, + comment.toStdWString(), + score); + } + else + { + QMessageBox::StandardButton sb = QMessageBox::Yes; + + if ((title.toStdWString() == detail.title) /* same title! - wrong */ + || (title == "")) + { + sb = QMessageBox::question ( NULL, "Link Title Not Changed", + "Do you want to continue?", + (QMessageBox::Yes | QMessageBox::No)); + } + + /* add Link! */ + if (sb == QMessageBox::Yes) + { + rsRanks->newRankMsg( + link.toStdWString(), + title.toStdWString(), + comment.toStdWString(), + score); + } + } + updateLinks(); + return; +} + +void LinksDialog::toggleWindows( void ) +{ + /* if msg header visible -> hide by changing splitter + */ + + QList sizeList = ui.msgSplitter->sizes(); + QList::iterator it; + + int listSize = 0; + int msgSize = 0; + int i = 0; + + for(it = sizeList.begin(); it != sizeList.end(); it++, i++) + { + if (i == 0) + { + listSize = (*it); + } + else if (i == 1) + { + msgSize = (*it); + } + } + + int totalSize = listSize + msgSize; + + bool toShrink = true; + if (msgSize < (int) totalSize / 10) + { + toShrink = false; + } + + QList newSizeList; + if (toShrink) + { + newSizeList.push_back(totalSize); + newSizeList.push_back(0); + ui.expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + ui.expandButton->setToolTip(tr("Expand")); + } + else + { + newSizeList.push_back(totalSize * 3/4); + newSizeList.push_back(totalSize * 1/4); + ui.expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + ui.expandButton->setToolTip(tr("Hide")); + } + + ui.msgSplitter->setSizes(newSizeList); + return; +} + + +QTreeWidgetItem *LinksDialog::getCurrentLine() +{ + /* get the current, and extract the Id */ + + /* get a link to the table */ + QTreeWidget *peerWidget = ui.linkTreeWidget; + QTreeWidgetItem *item = peerWidget -> currentItem(); + if (!item) + { +#ifdef LINKS_DEBUG + std::cerr << "Invalid Current Item" << std::endl; +#endif + return NULL; + } + +#ifdef LINKS_DEBUG + /* Display the columns of this item. */ + std::ostringstream out; + out << "CurrentPeerItem: " << std::endl; + + for(int i = 1; i < 6; i++) + { + QString txt = item -> text(i); + out << "\t" << i << ":" << txt.toStdString() << std::endl; + } + std::cerr << out.str(); +#endif + + return item; +} + +void LinksDialog::voteup_anon() +{ + //QTreeWidgetItem *c = getCurrentLine(); + + if (mLinkId == "") + { + return; + } + + RsRankDetails detail; + if (!rsRanks->getRankDetails(mLinkId, detail)) + { + /* not there! */ + return; + } + + QString link = QString::fromStdWString(detail.link); +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::voteup_anon() : " << link.toStdString() << std::endl; +#endif + // need a proper anon sharing option. + rsRanks->anonRankMsg(mLinkId, detail.link, detail.title); +} + + + + +void LinksDialog::voteup_score(int score) +{ + if (mLinkId == "") + { + return; + } + + RsRankDetails detail; + if (!rsRanks->getRankDetails(mLinkId, detail)) + { + /* not there! */ + return; + } + + QString link = QString::fromStdWString(detail.link); + std::wstring comment; +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::voteup_score() : " << link.toStdString() << std::endl; +#endif + + + std::list::iterator cit; + /* Add your text to the comment */ + std::string ownId = rsPeers->getOwnId(); + + for(cit = detail.comments.begin(); cit != detail.comments.end(); cit++) + { + if (cit->id == ownId) + break; + } + + if (cit != detail.comments.end()) + { + comment = cit->comment; + } + + rsRanks->updateComment(mLinkId, comment, score); +} + + +void LinksDialog::voteup_p2() +{ + voteup_score(2); +} + +void LinksDialog::voteup_p1() +{ + voteup_score(1); +} + +void LinksDialog::voteup_p0() +{ + voteup_score(0); +} + +void LinksDialog::voteup_m1() +{ + voteup_score(-1); +} + +void LinksDialog::voteup_m2() +{ + voteup_score(-2); +} + +void LinksDialog::downloadSelected() +{ + if (mLinkId == "") + { + return; + } + + RsRankDetails detail; + if (!rsRanks->getRankDetails(mLinkId, detail)) + { + /* not there! */ + return; + } + + QString link = QString::fromStdWString(detail.link); + std::wstring comment; +#ifdef LINKS_DEBUG + std::cerr << "LinksDialog::downloadSelected() : " << link.toStdString() << std::endl; +#endif + + RetroShareLink rslink(QString::fromStdWString(detail.link)); + + if(!rslink.valid() || rslink.type() != RetroShareLink::TYPE_FILE) + { + QMessageBox::critical(NULL,"Badly formed link","This link is badly formed. Can't parse/use it. This is a bug. Please contact the developers.") ; + return ; + } + + /* retrieve all peers id for this file */ + FileInfo info; + rsFiles->FileDetails(rslink.hash().toStdString(), 0, info); + + std::list srcIds; + std::list::iterator pit; + for (pit = info.peers.begin(); pit != info.peers.end(); pit ++) + srcIds.push_back(pit->peerId); + + rsFiles->FileRequest(rslink.name().toStdString(), rslink.hash().toStdString(), rslink.size(), "", 0, srcIds); +} + +void LinksDialog::anchorClicked (const QUrl& link ) +{ + #ifdef LINK_DEBUG + std::cerr << "LinksDialog::anchorClicked link.scheme() : " << link.scheme().toStdString() << std::endl; + #endif + + if (link.scheme() == "retroshare") + { + QStringList L = link.toString().split("|") ; + + std::string fileName = L.at(1).toStdString() ; + uint64_t fileSize = L.at(2).toULongLong(); + std::string fileHash = L.at(3).toStdString() ; + +#ifdef LINK_DEBUG + std::cerr << "LinksDialog::anchorClicked FileRequest : fileName : " << fileName << ". fileHash : " << fileHash << ". fileSize : " << fileSize << std::endl; +#endif + + if (fileName != "" && fileHash != "") + { + std::list srcIds; + + if(rsFiles->FileRequest(fileName, fileHash, fileSize, "", RS_FILE_HINTS_NETWORK_WIDE, srcIds)) + { + QMessageBox mb(tr("File Request Confirmation"), tr("The file has been added to your download list."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + else + { + QMessageBox mb(tr("File Request canceled"), tr("The file has not been added to your download list, because you already have it."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } + } + else + { + QMessageBox mb(tr("File Request Error"), tr("The file link is malformed."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + } + else if (link.scheme() == "http") + { + QDesktopServices::openUrl(link); + } + else if (link.scheme() == "") + { + //it's probably a web adress, let's add http:// at the beginning of the link + QString newAddress = link.toString(); + newAddress.prepend("http://"); + QDesktopServices::openUrl(QUrl(newAddress)); + } +} + +void LinksDialog::addNewLink() +{ + + AddLinksDialog *nAddLinksDialog = new AddLinksDialog(""); + + nAddLinksDialog->show(); + + /* window will destroy itself! */ +} diff --git a/retroshare-gui/src/gui/LinksDialog.h b/retroshare-gui/src/gui/LinksDialog.h new file mode 100644 index 000000000..cf55ea134 --- /dev/null +++ b/retroshare-gui/src/gui/LinksDialog.h @@ -0,0 +1,92 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _LINKS_DIALOG_H +#define _LINKS_DIALOG_H + +#include "mainpage.h" +#include "ui_LinksDialog.h" + + +class LinksDialog : public MainPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + LinksDialog(QWidget *parent = 0); + /** Default Destructor */ + + void insertExample(); + +private slots: + /** Create the context popup menu and it's submenus */ + void linkTreeWidgetCostumPopupMenu( QPoint point ); + + void voteup_anon(); + void voteup_score(int score); + void voteup_p2(); + void voteup_p1(); + void voteup_p0(); + void voteup_m1(); + void voteup_m2(); + void downloadSelected(); + + void changedSortRank( int index ); + void changedSortPeriod( int index ); + void changedSortFrom( int index ); + void changedSortTop( int index ); + + void updateLinks(); + void addLinkComment( void ); + void toggleWindows( void ); + + void openLink ( QTreeWidgetItem * item, int column ); + void changedItem(QTreeWidgetItem *curr, QTreeWidgetItem *prev); + void checkAnon(); + + void checkUpdate(); + + void anchorClicked (const QUrl &); + + void addNewLink(); + +private: + +void updateComments(std::string rid, std::string pid); + + int mStart; /* start of rank list */ + std::string mLinkId; + + /* Worker Functions */ + /* (1) Update Display */ + + /* (2) Utility Fns */ + QTreeWidgetItem *getCurrentLine(); + + QTreeWidget *exampletreeWidget; + + /** Qt Designer generated object */ + Ui::LinksDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/LinksDialog.ui b/retroshare-gui/src/gui/LinksDialog.ui new file mode 100644 index 000000000..59055342b --- /dev/null +++ b/retroshare-gui/src/gui/LinksDialog.ui @@ -0,0 +1,587 @@ + + + LinksDialog + + + + 0 + 0 + 738 + 583 + + + + + + + + 6 + + + 0 + + + + + + 0 + 0 + + + + Qt::Vertical + + + + + + + + 9 + + + + Qt::CustomContextMenu + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + + + + + + + + :/images/edit_remove24.png:/images/edit_remove24.png + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + + 75 + true + + + + Sort by + + + + + + + + Combo + + + + + Time + + + + :/images/kalarm.png:/images/kalarm.png + + + + + Ranking + + + + :/images/records.png:/images/records.png + + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + + 75 + true + + + + In last + + + + + + + + Month + + + + :/images/view_calendar_month.png:/images/view_calendar_month.png + + + + + Week + + + + :/images/view_calendar_week.png:/images/view_calendar_week.png + + + + + Day + + + + :/images/view_calendar_day.png:/images/view_calendar_day.png + + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + + 75 + true + + + + From + + + + + + + + All Peers + + + + :/images/user/friends24.png:/images/user/friends24.png + + + + + Own Links + + + + :/images/user/identity16.png:/images/user/identity16.png + + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + + 75 + true + + + + Show + + + + + + + + Top 100 + + + + :/images/records.png:/images/records.png + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + + + + + 16777215 + 22 + + + + QTextBrowser{border: 2px solid #CCCCCC; +border-radius: 10px; +background: white;} + + + Qt::ScrollBarAlwaysOff + + + false + + + + + + + + 75 + true + + + + Link: + + + + + + + + + + + + + Qt::Horizontal + + + + 311 + 32 + + + + + + + + + 50 + false + + + + Add Anonymous Link + + + + + + + Add Link/Comment + + + + + + + + + + + Title: + + + + + + + QLineEdit{border: 2px solid #CCCCCC; +border-radius: 10px; +background: white;} + + + + + + + Score: + + + + + + + + +2 Great! + + + + :/images/filerating5.png:/images/filerating5.png + + + + + +1 Good + + + + :/images/filerating4.png:/images/filerating4.png + + + + + 0 Okay + + + + :/images/filerating3.png:/images/filerating3.png + + + + + -1 Sux + + + + :/images/filerating2.png:/images/filerating2.png + + + + + -2 Bad Link + + + + :/images/filerating1.png:/images/filerating1.png + + + + + + + + + + + + Url: + + + + + + + QLineEdit{border: 2px solid #CCCCCC; +border-radius: 10px; +background: white;} + + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QTextEdit{border: 2px solid #CCCCCC; +border-radius: 10px; +background: white;} + + + + + + + + + + + + 16777215 + 32 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + + 24 + 24 + + + + + + + :/images/irkick.png + + + true + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 596 + 15 + + + + + + + + QPushButton:hover { +border: 1px solid #CCCCCC; +} + + + Add new link + + + + :/images/edit_add24.png:/images/edit_add24.png + + + true + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/LogoBar.cpp b/retroshare-gui/src/gui/LogoBar.cpp new file mode 100644 index 000000000..0ee7e96b0 --- /dev/null +++ b/retroshare-gui/src/gui/LogoBar.cpp @@ -0,0 +1,105 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "LogoBar.h" + +#include +#include + + +#include + +LogoBar::LogoBar(QWidget * parent) + : QFrame(parent) { + + init(); +} + +LogoBar::~LogoBar() { +} + +void LogoBar::init() { + setFrameShape(QFrame::NoFrame); + + + + //LogoButton + _logoButton = new RetroStyleLabel(this); + _logoButton->setPixmaps( + QPixmap(":/images/logobar/rslogo2.png"), //Start + QPixmap(), //End + QPixmap(), //Fill + + QPixmap(":/images/logobar/rslogo2.png"), //Start + QPixmap(), //End + QPixmap() //Fill + ); + _logoButton->setMaximumSize(QSize(110, 65)); + _logoButton->setMinimumSize(QSize(110, 65)); + connect(_logoButton, SIGNAL(clicked()), SLOT(logoButtonClickedSlot())); + + //FillLabel1 + RetroStyleLabel * FillLabel1 = new RetroStyleLabel(this); + FillLabel1->setPixmaps( + QPixmap(), //Start + QPixmap(), //End + QPixmap(":/images/logobar/logo_bar_fill.png"), //Fill + + QPixmap(), //Start + QPixmap(), //End + QPixmap(":/images/logobar/logo_bar_fill.png") //Fill + ); + + //FillLabel2 + RetroStyleLabel * FillLabel2 = new RetroStyleLabel(this); + FillLabel2->setPixmaps( + QPixmap(), //Start + QPixmap(), //End + QPixmap(":/images/logobar/logo_bar_fill.png"), //Fill + + QPixmap(), //Start + QPixmap(), //End + QPixmap(":/images/logobar/logo_bar_fill.png") //Fill + ); + + QGridLayout * layout = new QGridLayout(this); + layout->setMargin(0); + layout->setSpacing(0); + + layout->addWidget(FillLabel1, 0, 0); + layout->addWidget(_logoButton, 0, 1); + layout->addWidget(FillLabel2, 0, 2); + + +} + +void LogoBar::setEnabledLogoButton(bool enable) { + _logoButton->setEnabled(enable); +} + + +void LogoBar::logoButtonClickedSlot() { + logoButtonClicked(); +} + + + + diff --git a/retroshare-gui/src/gui/LogoBar.h b/retroshare-gui/src/gui/LogoBar.h new file mode 100644 index 000000000..0b5bfb6f9 --- /dev/null +++ b/retroshare-gui/src/gui/LogoBar.h @@ -0,0 +1,79 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef LOGOBAR_H +#define LOGOBAR_H + +#include + +#include + +class RetroStyleLabel; + +class QString; +class QIcon; + +/** + * logo bar inside the login window. + * + * + * + * + * + * + * + */ +class LogoBar : public QFrame { + Q_OBJECT +public: + + LogoBar(QWidget * parent); + + ~LogoBar(); + + void setEnabledLogoButton(bool enable); + + + +Q_SIGNALS: + + void logoButtonClicked(); + + + +private Q_SLOTS: + + void logoButtonClickedSlot(); + + + +private: + + void init(); + + + + RetroStyleLabel * _logoButton; + + +}; + +#endif //LOGOBAR_H diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp new file mode 100644 index 000000000..e873d0226 --- /dev/null +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -0,0 +1,1468 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BLOGS +#include "gui/unfinished/blogs/BlogsDialog.h" +#endif + +#include +#include "rshare.h" +#include "MainWindow.h" +#include "MessengerWindow.h" +#include "NetworkDialog.h" +#include "SearchDialog.h" +#include "TransfersDialog.h" +#include "MessagesDialog.h" +#include "SharedFilesDialog.h" +#include "PluginsPage.h" +#include "ShareManager.h" +#include "NetworkView.h" +#include "ForumsDialog.h" +#include "FriendsDialog.h" +#include "HelpDialog.h" +#include "AboutDialog.h" +#include "QuickStartWizard.h" +#include "ChannelFeed.h" +#include "bwgraph/bwgraph.h" +#include "help/browser/helpbrowser.h" +#include "chat/PopupChatDialog.h" +#include "RetroShareLink.h" + +#ifdef UNFINISHED +#include "unfinished/ApplicationWindow.h" +#endif + +#include "gui/TurtleRouterDialog.h" +#include "idle/idle.h" + +#include "statusbar/peerstatus.h" +#include "statusbar/natstatus.h" +#include "statusbar/ratesstatus.h" +#include "statusbar/dhtstatus.h" +#include "statusbar/hashingstatus.h" +#include "statusbar/discstatus.h" +#include + +#include +#include +#include +#include +#include +#include + +#include "gui/connect/ConnectFriendWizard.h" +#include "util/rsversion.h" +#include "settings/rsettingswin.h" +#include "settings/rsharesettings.h" +#include "common/StatusDefs.h" + +#include +#include +#include + +#define FONT QFont("Arial", 9) + +/* Images for toolbar icons */ +#define IMAGE_NETWORK2 ":/images/rs1.png" +#define IMAGE_PEERS ":/images/groupchat.png" +#define IMAGE_SEARCH ":/images/filefind.png" +#define IMAGE_TRANSFERS ":/images/ktorrent32.png" +#define IMAGE_FILES ":/images/fileshare32.png" +#define IMAGE_CHANNELS ":/images/channels.png" +#define IMAGE_FORUMS ":/images/konversation.png" +#define IMAGE_PREFERENCES ":/images/kcmsystem24.png" +#define IMAGE_CHAT ":/images/groupchat.png" +#define IMAGE_RETROSHARE ":/images/rstray3.png" +#define IMAGE_ABOUT ":/images/informations_24x24.png" +#define IMAGE_STATISTIC ":/images/utilities-system-monitor.png" +#define IMAGE_MESSAGES ":/images/evolution.png" +#define IMAGE_BWGRAPH ":/images/ksysguard.png" +#define IMAGE_RSM32 ":/images/kdmconfig.png" +#define IMAGE_RSM16 ":/images/rsmessenger16.png" +#define IMAGE_CLOSE ":/images/close_normal.png" +#define IMAGE_BLOCK ":/images/blockdevice.png" +#define IMAGE_COLOR ":/images/highlight.png" +#define IMAGE_GAMES ":/images/kgames.png" +#define IMAGE_PHOTO ":/images/lphoto.png" +#define IMAGE_ADDFRIEND ":/images/add-friend24.png" +#define IMAGE_ADDSHARE ":/images/directoryadd_24x24_shadow.png" +#define IMAGE_OPTIONS ":/images/settings.png" +#define IMAGE_QUIT ":/images/exit_24x24.png" +#define IMAGE_UNFINISHED ":/images/underconstruction.png" +#define IMAGE_MINIMIZE ":/images/window_nofullscreen.png" +#define IMAGE_MAXIMIZE ":/images/window_fullscreen.png" +#define IMG_HELP ":/images/help.png" +#define IMAGE_NEWSFEED ":/images/konqsidebar_news24.png" +#define IMAGE_PLUGINS ":/images/extension_32.png" +#define IMAGE_NOONLINE ":/images/rstray0.png" +#define IMAGE_ONEONLINE ":/images/rstray1.png" +#define IMAGE_TWOONLINE ":/images/rstray2.png" +#define IMAGE_BLOGS ":/images/kblogger.png" + +/*static*/ MainWindow *MainWindow::_instance = NULL; + +/** create main window */ +/*static*/ MainWindow *MainWindow::Create () +{ + if (_instance == NULL) { + /* _instance is set in constructor */ + new MainWindow (); + } + + return _instance; +} + +/*static*/ MainWindow *MainWindow::getInstance() +{ + return _instance; +} + +/** Constructor */ +MainWindow::MainWindow(QWidget* parent, Qt::WFlags flags) + : RWindow("MainWindow", parent, flags) +{ + /* Invoke the Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + _instance = this; + + m_bStatusLoadDone = false; + isIdle = false; + + trayIconCombined = NULL; + trayIconMessages = NULL; + trayIconForums = NULL; + trayIconChannels = NULL; + trayIconChat = NULL; + trayIconTransfers = NULL; + trayActionMessages = NULL; + trayActionForums = NULL; + trayActionChannels = NULL; + trayActionChat = NULL; + trayActionTransfers = NULL; + + /* Calculate only once */ + 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())); + } + + setWindowTitle(tr("RetroShare %1 a secure decentralised communication platform").arg(retroshareVersion()) + " - " + nameAndLocation); + + /* add url handler for RetroShare links */ + QDesktopServices::setUrlHandler(RSLINK_SCHEME, this, "linkActivated"); + + // Setting icons + this->setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + + /* Create all the dialogs of which we only want one instance */ + _bandwidthGraph = new BandwidthGraph(); + + #ifdef UNFINISHED + applicationWindow = new ApplicationWindow(); + applicationWindow->hide(); + #endif + + /** Left Side ToolBar**/ + connect(ui.actionAdd_Friend, SIGNAL(triggered() ), this , SLOT( addFriend() ) ); + connect(ui.actionAdd_Share, SIGNAL(triggered() ), this , SLOT( openShareManager() ) ); + connect(ui.actionOptions, SIGNAL(triggered()), this, SLOT( showSettings()) ); + connect(ui.actionMessenger, SIGNAL(triggered()), this, SLOT( showMessengerWindow()) ); + + ui.actionMessenger->setVisible(true); + + connect(ui.actionAbout, SIGNAL(triggered()), this, SLOT( showabout()) ); + //connect(ui.actionColor, SIGNAL(triggered()), this, SLOT( setStyle()) ); + + + /** adjusted quit behaviour: trigger a warning that can be switched off in the saved + config file RetroShare.conf */ + connect(ui.actionQuit, SIGNAL(triggered()), this, SLOT(doQuit())); + + /* load the StyleSheet*/ + loadStyleSheet(Rshare::stylesheet()); + + + /* Create the Main pages and actions */ + QActionGroup *grp = new QActionGroup(this); + + + ui.stackPages->add(networkDialog = new NetworkDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_NETWORK2), tr("Network"), grp)); + + + ui.stackPages->add(friendsDialog = new FriendsDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_PEERS), tr("Friends"), grp)); + + + ui.stackPages->add(searchDialog = new SearchDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_SEARCH), tr("Search"), grp)); + + + ui.stackPages->add(transfersDialog = new TransfersDialog(ui.stackPages), + transferAction = createPageAction(QIcon(IMAGE_TRANSFERS), tr("Transfers"), grp)); + + + ui.stackPages->add(sharedfilesDialog = new SharedFilesDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_FILES), tr("Files"), grp)); + + + ui.stackPages->add(messagesDialog = new MessagesDialog(ui.stackPages), + messageAction = createPageAction(QIcon(IMAGE_MESSAGES), tr("Messages"), grp)); + + ui.stackPages->add(channelFeed = new ChannelFeed(ui.stackPages), + channelAction = createPageAction(QIcon(IMAGE_CHANNELS), tr("Channels"), grp)); + +#ifdef BLOGS + ui.stackPages->add(blogsFeed = new BlogsDialog(ui.stackPages), createPageAction(QIcon(IMAGE_BLOGS), tr("Blogs"), grp)); +#endif + + ui.stackPages->add(forumsDialog = new ForumsDialog(ui.stackPages), + forumAction = createPageAction(QIcon(IMAGE_FORUMS), tr("Forums"), grp)); + + std::cerr << "Looking for interfaces in existing plugins:" << std::endl; + for(uint32_t i = 0;inbPlugins();++i) + { + if(rsPlugins->plugin(i)->qt_page() != NULL && rsPlugins->plugin(i)->qt_icon() != NULL) + { + std::cerr << " Addign widget page for plugin " << rsPlugins->plugin(i)->getPluginName() << std::endl; + ui.stackPages->add(rsPlugins->plugin(i)->qt_page(), createPageAction(*rsPlugins->plugin(i)->qt_icon(), QString::fromStdString(rsPlugins->plugin(i)->getPluginName()), grp)); + } + //ui.stackPages->add(linksDialog = new LinksDialog(ui.stackPages), createPageAction(QIcon(IMAGE_LINKS), tr("Links Cloud"), grp)); + } + +#ifndef RS_RELEASE_VERSION +#ifdef PLUGINMGR + ui.stackPages->add(pluginsPage = new PluginsPage(ui.stackPages), + createPageAction(QIcon(IMAGE_PLUGINS), tr("Plugins"), grp)); +#endif +#endif + + /* Create the toolbar */ + ui.toolBar->addActions(grp->actions()); + + connect(grp, SIGNAL(triggered(QAction *)), ui.stackPages, SLOT(showPage(QAction *))); + +#ifdef UNFINISHED + ui.toolBar->addSeparator(); + addAction(new QAction(QIcon(IMAGE_UNFINISHED), tr("Unfinished"), ui.toolBar), SLOT(showApplWindow())); +#endif + + if (activatePage((Page) Settings->getLastPageInMainWindow()) == false) { + /* Select the first action */ + grp->actions()[0]->setChecked(true); + } + + /** StatusBar section ********/ + /* initialize combobox in status bar */ + statusComboBox = new QComboBox(statusBar()); + initializeStatusObject(statusComboBox, true); + + QWidget *widget = new QWidget(); + QHBoxLayout *hbox = new QHBoxLayout(); + hbox->setMargin(0); + hbox->setSpacing(6); + hbox->addWidget(statusComboBox); + widget->setLayout(hbox); + statusBar()->addWidget(widget); + + peerstatus = new PeerStatus(); + statusBar()->addWidget(peerstatus); + + natstatus = new NATStatus(); + statusBar()->addWidget(natstatus); + + dhtstatus = new DHTStatus(); + statusBar()->addWidget(dhtstatus); + + hashingstatus = new HashingStatus(); + statusBar()->addPermanentWidget(hashingstatus); + + discstatus = new DiscStatus(); + statusBar()->addPermanentWidget(discstatus); + + ratesstatus = new RatesStatus(); + statusBar()->addPermanentWidget(ratesstatus); + /** Status Bar end ******/ + + /* Creates a tray icon with a context menu and adds it to the system's * notification area. */ + createTrayIcon(); + + loadOwnStatus(); + + /* Set focus to the current page */ + ui.stackPages->currentWidget()->setFocus(); + + idle = new Idle(); + idle->start(); + connect(idle, SIGNAL(secondsIdle(int)), this, SLOT(checkAndSetIdle(int))); + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(updateStatus())); + timer->start(1000); +} + +/** Destructor. */ +MainWindow::~MainWindow() +{ + Settings->setLastPageInMainWindow(getActivatePage()); + + delete peerstatus; + delete natstatus; + delete dhtstatus; + delete ratesstatus; + delete discstatus; + MessengerWindow::releaseInstance(); +#ifdef UNFINISHED + delete applicationWindow; +#endif +} + +void MainWindow::displayDiskSpaceWarning(int loc,int size_limit_mb) +{ + QString locString ; + switch(loc) + { + case RS_PARTIALS_DIRECTORY: locString = "Partials" ; + break ; + + case RS_CONFIG_DIRECTORY: locString = "Config" ; + break ; + + case RS_DOWNLOAD_DIRECTORY: locString = "Download" ; + break ; + + default: + std::cerr << "Error: " << __PRETTY_FUNCTION__ << " was called with an unknown parameter loc=" << loc << std::endl ; + return ; + } + QMessageBox::critical(NULL,tr("Low disk space warning"), + tr("The disk space in your ")+locString +tr(" directory is running low (current limit is ")+QString::number(size_limit_mb)+tr("MB). \n\n RetroShare will now safely suspend any disk access to this directory. \n\n Please make some free space and click Ok.")) ; +} + +/** Creates a tray icon with a context menu and adds it to the system + * notification area. */ +void MainWindow::createTrayIcon() +{ + /** Tray icon Menu **/ + QMenu *trayMenu = new QMenu(this); + QObject::connect(trayMenu, SIGNAL(aboutToShow()), this, SLOT(updateMenu())); + toggleVisibilityAction = trayMenu->addAction(QIcon(IMAGE_RETROSHARE), tr("Show/Hide"), this, SLOT(toggleVisibilitycontextmenu())); + + QMenu *pStatusMenu = trayMenu->addMenu(tr("Status")); + initializeStatusObject(pStatusMenu, true); + + trayMenu->addSeparator(); + trayMenu->addAction(QIcon(IMAGE_RSM16), tr("Open Messenger"), this, SLOT(showMessengerWindow())); + trayMenu->addAction(QIcon(IMAGE_MESSAGES), tr("Open Messages"), this, SLOT(showMess())); + trayMenu->addAction(QIcon(IMAGE_BWGRAPH), tr("Bandwidth Graph"), _bandwidthGraph, SLOT(showWindow())); + +#ifdef UNFINISHED + trayMenu->addAction(QIcon(IMAGE_UNFINISHED), tr("Applications"), this, SLOT(showApplWindow())); +#endif + trayMenu->addAction(QIcon(IMAGE_PREFERENCES), tr("Options"), this, SLOT(showSettings())); + trayMenu->addAction(QIcon(IMG_HELP), tr("Help"), this, SLOT(showHelpDialog())); + trayMenu->addSeparator(); + trayMenu->addAction(QIcon(IMAGE_MINIMIZE), tr("Minimize"), this, SLOT(showMinimized())); + trayMenu->addAction(QIcon(IMAGE_MAXIMIZE), tr("Maximize"), this, SLOT(showMaximized())); + trayMenu->addSeparator(); + trayMenu->addAction(QIcon(IMAGE_CLOSE), tr("&Quit"), this, SLOT(doQuit())); + /** End of Icon Menu **/ + + // Create the tray icon + trayIcon = new QSystemTrayIcon(this); + trayIcon->setToolTip(tr("RetroShare")); + trayIcon->setContextMenu(trayMenu); + trayIcon->setIcon(QIcon(IMAGE_NOONLINE)); + + connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(toggleVisibility(QSystemTrayIcon::ActivationReason))); + trayIcon->show(); + + createNotifyIcons(); +} + +void MainWindow::createNotifyIcons() +{ +#define DELETE_ICON(x) if (x) { delete(x); x = NULL; } + + int notifyFlag = Settings->getTrayNotifyFlags(); + + QMenu *trayMenu = NULL; + + /* Delete combined systray icon and rebuild it */ + trayActionMessages = NULL; + trayActionForums = NULL; + trayActionChannels = NULL; + trayActionChat = NULL; + trayActionTransfers = NULL; + DELETE_ICON(trayIconCombined); + + if (notifyFlag & TRAYNOTIFY_COMBINEDICON) { + /* Delete single systray icons */ + DELETE_ICON(trayIconMessages); + DELETE_ICON(trayIconForums); + DELETE_ICON(trayIconChannels); + DELETE_ICON(trayIconChat); + DELETE_ICON(trayIconTransfers); + + /* Create combined systray icon */ + trayIconCombined = new QSystemTrayIcon(this); + trayIconCombined->setIcon(QIcon(":/images/rstray_new.png")); + + trayMenu = new QMenu(this); + trayIconCombined->setContextMenu(trayMenu); + } + + /* Create systray icons or actions */ + if (notifyFlag & TRAYNOTIFY_MESSAGES) { + if (trayMenu) { + DELETE_ICON(trayIconMessages); + + trayActionMessages = trayMenu->addAction(QIcon(":/images/newmsg.png"), "", this, SLOT(trayIconMessagesClicked())); + trayActionMessages->setVisible(false); + trayActionMessages->setData(tr("Messages")); + } else if (trayIconMessages == NULL) { + // Create the tray icon for messages + trayIconMessages = new QSystemTrayIcon(this); + trayIconMessages->setIcon(QIcon(":/images/newmsg.png")); + connect(trayIconMessages, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconMessagesClicked(QSystemTrayIcon::ActivationReason))); + } + } else { + DELETE_ICON(trayIconMessages); + } + + if (notifyFlag & TRAYNOTIFY_FORUMS) { + if (trayMenu) { + DELETE_ICON(trayIconForums); + + trayActionForums = trayMenu->addAction(QIcon(":/images/konversation16.png"), "", this, SLOT(trayIconForumsClicked())); + trayActionForums->setVisible(false); + trayActionForums->setData(tr("Forums")); + } else if (trayIconForums == NULL) { + // Create the tray icon for forums + trayIconForums = new QSystemTrayIcon(this); + trayIconForums->setIcon(QIcon(":/images/konversation16.png")); + connect(trayIconForums, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconForumsClicked(QSystemTrayIcon::ActivationReason))); + } + } else { + DELETE_ICON(trayIconForums); + } + + if (notifyFlag & TRAYNOTIFY_CHANNELS) { + if (trayMenu) { + DELETE_ICON(trayIconChannels); + + trayActionChannels = trayMenu->addAction(QIcon(":/images/channels16.png"), "", this, SLOT(trayIconChannelsClicked())); + trayActionChannels->setVisible(false); + trayActionChannels->setData(tr("Channels")); + } else if (trayIconChannels == NULL) { + // Create the tray icon for channels + trayIconChannels = new QSystemTrayIcon(this); + trayIconChannels->setIcon(QIcon(":/images/channels16.png")); + connect(trayIconChannels, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconChannelsClicked(QSystemTrayIcon::ActivationReason))); + } + } else { + DELETE_ICON(trayIconChannels); + } + + if (notifyFlag & TRAYNOTIFY_PRIVATECHAT) { + if (trayMenu) { + DELETE_ICON(trayIconChat); + + trayActionChat = trayMenu->addAction(QIcon(":/images/chat.png"), "", this, SLOT(trayIconChatClicked())); + trayActionChat->setVisible(false); + trayActionChat->setData(tr("Chat")); + } else if (trayIconChat == NULL) { + // Create the tray icon for chat + trayIconChat = new QSystemTrayIcon(this); + trayIconChat->setIcon(QIcon(":/images/chat.png")); + connect(trayIconChat, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconChatClicked(QSystemTrayIcon::ActivationReason))); + } + } else { + DELETE_ICON(trayIconChat); + } + + if (notifyFlag & TRAYNOTIFY_TRANSFERS) { + if (trayMenu) { + DELETE_ICON(trayIconTransfers); + + trayActionTransfers = trayMenu->addAction(QIcon(":/images/ktorrent32.png"), "", this, SLOT(trayIconTransfersClicked())); + trayActionTransfers->setVisible(false); + trayActionTransfers->setData(tr("Transfers")); + } else if (trayIconTransfers == NULL) { + // Create the tray icon for transfers + trayIconTransfers = new QSystemTrayIcon(this); + trayIconTransfers->setIcon(QIcon(":/images/ktorrent32.png")); + connect(trayIconTransfers, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconTransfersClicked(QSystemTrayIcon::ActivationReason))); + } + } else { + DELETE_ICON(trayIconTransfers); + } + + /* call once */ + updateMessages(); + updateForums(); + updateChannels(NOTIFY_TYPE_ADD); + privateChatChanged(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD); + // transfer + +#undef DELETE_ICON +} + +/*static*/ void MainWindow::installGroupChatNotifier() +{ + if (_instance == NULL) { + // nothing to do + return; + } + + if(Settings->getDisplayTrayGroupChat()) { + QObject::connect(_instance->friendsDialog, SIGNAL(notifyGroupChat(const QString&,const QString&)), _instance, SLOT(displaySystrayMsg(const QString&,const QString&)), Qt::QueuedConnection); + } else { + QObject::disconnect(_instance->friendsDialog, SIGNAL(notifyGroupChat(const QString&,const QString&)), _instance, SLOT(displaySystrayMsg(const QString&,const QString&))); + } +} + +/*static*/ void MainWindow::installNotifyIcons() +{ + if (_instance == NULL) { + // nothing to do + return; + } + + _instance->createNotifyIcons(); +} + +void MainWindow::displaySystrayMsg(const QString& title,const QString& msg) +{ + trayIcon->showMessage(title, msg, QSystemTrayIcon::Information, 3000); +} + +void MainWindow::updateMessages() +{ + unsigned int newInboxCount = 0; + rsMsgs->getMessageCount (NULL, &newInboxCount, NULL, NULL, NULL, NULL); + + if(newInboxCount) { + messageAction->setIcon(QIcon(QPixmap(":/images/messages_new.png"))) ; + } else { + messageAction->setIcon(QIcon(QPixmap(":/images/evolution.png"))) ; + } + + if (trayIconMessages) { + if (newInboxCount) { + if (newInboxCount > 1) { + trayIconMessages->setToolTip("RetroShare\n" + tr("You have %1 new messages").arg(newInboxCount)); + } else { + trayIconMessages->setToolTip("RetroShare\n" + tr("You have %1 new message").arg(newInboxCount)); + } + trayIconMessages->show(); + } else { + trayIconMessages->hide(); + } + } + + if (trayActionMessages) { + if (newInboxCount) { + if (newInboxCount > 1) { + trayActionMessages->setText(tr("%1 new messages").arg(newInboxCount)); + } else { + trayActionMessages->setText(tr("%1 new message").arg(newInboxCount)); + } + trayActionMessages->setVisible(true); + } else { + trayActionMessages->setVisible(false); + } + } + + updateTrayCombine(); +} + +void MainWindow::updateForums() +{ + unsigned int newMessageCount = 0; + unsigned int unreadMessageCount = 0; + rsForums->getMessageCount("", newMessageCount, unreadMessageCount); + + if (newMessageCount) { + forumAction->setIcon(QIcon(":/images/konversation_new.png")) ; + } else { + forumAction->setIcon(QIcon(IMAGE_FORUMS)) ; + } + + if (trayIconForums) { + if (newMessageCount) { + if (newMessageCount > 1) { + trayIconForums->setToolTip("RetroShare\n" + tr("You have %1 new messages").arg(newMessageCount)); + } else { + trayIconForums->setToolTip("RetroShare\n" + tr("You have %1 new message").arg(newMessageCount)); + } + trayIconForums->show(); + } else { + trayIconForums->hide(); + } + } + + if (trayActionForums) { + if (newMessageCount) { + if (newMessageCount > 1) { + trayActionForums->setText(tr("%1 new messages").arg(newMessageCount)); + } else { + trayActionForums->setText(tr("%1 new message").arg(newMessageCount)); + } + trayActionForums->setVisible(true); + } else { + trayActionForums->setVisible(false); + } + } + + updateTrayCombine(); +} + +void MainWindow::updateChannels(int type) +{ + unsigned int newMessageCount = 0; + unsigned int unreadMessageCount = 0; + rsChannels->getMessageCount("", newMessageCount, unreadMessageCount); + + if (newMessageCount) { + channelAction->setIcon(QIcon(":/images/channels_new32.png")) ; + } else { + channelAction->setIcon(QIcon(IMAGE_CHANNELS)) ; + } + + if (trayIconChannels) { + if (newMessageCount) { + if (newMessageCount > 1) { + trayIconChannels->setToolTip("RetroShare\n" + tr("You have %1 new messages").arg(newMessageCount)); + } else { + trayIconChannels->setToolTip("RetroShare\n" + tr("You have %1 new message").arg(newMessageCount)); + } + trayIconChannels->show(); + } else { + trayIconChannels->hide(); + } + } + + if (trayActionChannels) { + if (newMessageCount) { + if (newMessageCount > 1) { + trayActionChannels->setText(tr("%1 new messages").arg(newMessageCount)); + } else { + trayActionChannels->setText(tr("%1 new message").arg(newMessageCount)); + } + trayActionChannels->setVisible(true); + } else { + trayActionChannels->setVisible(false); + } + } + + updateTrayCombine(); +} + +void MainWindow::updateTransfers(int count) +{ + if (count) { + transferAction->setIcon(QIcon(":/images/transfers_new32.png")) ; + } else { + transferAction->setIcon(QIcon(IMAGE_TRANSFERS)) ; + } + + if (trayIconTransfers) { + if (count) { + if (count > 1) { + trayIconTransfers->setToolTip("RetroShare\n" + tr("You have %1 completed downloads").arg(count)); + } else { + trayIconTransfers->setToolTip("RetroShare\n" + tr("You have %1 completed download").arg(count)); + } + trayIconTransfers->show(); + } else { + trayIconTransfers->hide(); + } + } + + if (trayActionTransfers) { + if (count) { + if (count > 1) { + trayActionTransfers->setText(tr("%1 completed downloads").arg(count)); + } else { + trayActionTransfers->setText(tr("%1 completed download").arg(count)); + } + trayActionTransfers->setVisible(true); + } else { + trayActionTransfers->setVisible(false); + } + } + + updateTrayCombine(); +} + +void MainWindow::updateTrayCombine() +{ + if (trayIconCombined) { + QMenu *trayMenu = trayIconCombined->contextMenu(); + QList actions = trayMenu->actions(); + + bool visible = false; + QString toolTip; + + QList::iterator actionIt; + for (actionIt = actions.begin(); actionIt != actions.end(); actionIt++) { + if ((*actionIt)->isVisible()) { + visible = true; + if (toolTip.isEmpty() == false) { + toolTip += "\r"; + } + toolTip += (*actionIt)->data().toString() + ":" + (*actionIt)->text(); + } + } + + trayIconCombined->setToolTip(toolTip); + trayIconCombined->setVisible(visible); + } +} + +void MainWindow::updateStatus() +{ + // This call is essential to remove locks due to QEventLoop re-entrance while asking gpg passwds. Dont' remove it! + if(RsAutoUpdatePage::eventsLocked()) + return; + + unsigned int nFriendCount = 0; + unsigned int nOnlineCount = 0; + rsPeers->getPeerCount (&nFriendCount, &nOnlineCount, false); + + float downKb = 0; + float upKb = 0; + rsicontrol -> ConfigGetDataRates(downKb, upKb); + + if (ratesstatus) + ratesstatus->getRatesStatus(downKb, upKb); + + if (peerstatus) + peerstatus->getPeerStatus(nFriendCount, nOnlineCount); + + if (natstatus) + natstatus->getNATStatus(); + + if (dhtstatus) + dhtstatus->getDHTStatus(); + + if (discstatus) { + discstatus->update(); + } + + if (nOnlineCount == 0) + { + trayIcon->setIcon(QIcon(IMAGE_NOONLINE)); + } + else if (nOnlineCount < 2) + { + trayIcon->setIcon(QIcon(IMAGE_ONEONLINE)); + } + else if (nOnlineCount < 3) + { + trayIcon->setIcon(QIcon(IMAGE_TWOONLINE)); + } + else + { + trayIcon->setIcon(QIcon(IMAGE_RETROSHARE)); + } + + QString tray = "RetroShare\n" + tr("Down: %1 (kB/s)").arg(downKb, 0, 'f', 2) + " | " + tr("Up: %1 (kB/s)").arg(upKb, 0, 'f', 2) + "\n"; + + if (nOnlineCount == 1) { + tray += tr("%1 friend connected").arg(nOnlineCount); + } else { + tray += tr("%1 friends connected").arg(nOnlineCount); + } + + tray += "\n" + nameAndLocation; + + trayIcon->setToolTip(tray); +} + +void MainWindow::privateChatChanged(int list, int type) +{ + /* first process the chat messages */ + PopupChatDialog::privateChatChanged(list, type); + + if (list == NOTIFY_LIST_PRIVATE_INCOMING_CHAT) { + /* than count the chat messages */ + int chatCount = rsMsgs->getPrivateChatQueueCount(true); + + if (trayIconChat) { + if (chatCount) { + if (chatCount > 1) { + trayIconChat->setToolTip("RetroShare\n" + tr("You have %1 new messages").arg(chatCount)); + } else { + trayIconChat->setToolTip("RetroShare\n" + tr("You have %1 new message").arg(chatCount)); + } + trayIconChat->show(); + } else { + trayIconChat->hide(); + } + } + + if (trayActionChat) { + if (chatCount) { + if (chatCount > 1) { + trayActionChat->setText(tr("%1 new messages").arg(chatCount)); + } else { + trayActionChat->setText(tr("%1 new message").arg(chatCount)); + } + trayActionChat->setVisible(true); + } else { + trayActionChat->setVisible(false);; + } + } + + updateTrayCombine(); + } +} + +void MainWindow::postModDirectories(bool update_local) +{ + RSettingsWin::postModDirectories(update_local); + ShareManager::postModDirectories(update_local); + + QCoreApplication::flush(); +} + +/** Creates a new action associated with a config page. */ +QAction* MainWindow::createPageAction(QIcon img, QString text, QActionGroup *group) +{ + QAction *action = new QAction(img, text, group); + action->setCheckable(true); + action->setFont(FONT); + return action; +} + +/** Adds the given action to the toolbar and hooks its triggered() signal to + * the specified slot (if given). */ +void MainWindow::addAction(QAction *action, const char *slot) +{ + action->setFont(FONT); + ui.toolBar->addAction(action); + connect(action, SIGNAL(triggered()), this, slot); +} + +/** Shows the MainWindow with focus set to the given page. */ +/*static*/ void MainWindow::showWindow(Page page) +{ + if (_instance == NULL) { + return; + } + + /* Show the dialog. */ + _instance->show(); + /* Set the focus to the specified page. */ + activatePage (page); +} + +/** Set focus to the given page. */ +/*static*/ bool MainWindow::activatePage(Page page) +{ + if (_instance == NULL) { + return false; + } + + MainPage *Page = NULL; + + switch (page) { + case Network: + Page = _instance->networkDialog; + break; + case Friends: + Page = _instance->friendsDialog; + break; + case Search: + Page = _instance->searchDialog; + break; + case Transfers: + Page = _instance->transfersDialog; + break; + case SharedDirectories: + Page = _instance->sharedfilesDialog; + break; + case Messages: + Page = _instance->messagesDialog; + break; + case Channels: + Page = _instance->channelFeed; + break; + case Forums: + Page = _instance->forumsDialog; + break; +#ifdef BLOGS + case Blogs: + Page = _instance->blogsFeed; + break; +#endif + } + + if (Page) { + /* Set the focus to the specified page. */ + _instance->ui.stackPages->setCurrentPage(Page); + return true; + } + + return false; +} + +/** Get the active page. */ +/*static*/ MainWindow::Page MainWindow::getActivatePage() +{ + if (_instance == NULL) { + return Network; + } + + QWidget *page = _instance->ui.stackPages->currentWidget(); + + if (page == _instance->networkDialog) { + return Network; + } + if (page == _instance->friendsDialog) { + return Friends; + } + if (page == _instance->searchDialog) { + return Search; + } + if (page == _instance->transfersDialog) { + return Transfers; + } + if (page == _instance->sharedfilesDialog) { + return SharedDirectories; + } + if (page == _instance->messagesDialog) { + return Messages; + } +#ifdef RS_USE_LINKS + if (page == _instance->linksDialog) { + return Links; + } +#endif + if (page == _instance->channelFeed) { + return Channels; + } + if (page == _instance->forumsDialog) { + return Forums; + } +#ifdef BLOGS + if (page == _instance->blogsFeed) { + return Blogs; + } +#endif + + return Network; +} + +/** get page */ +/*static*/ MainPage *MainWindow::getPage (Page page) +{ + if (_instance == NULL) { + return NULL; + } + + switch (page) { + case Network: + return _instance->networkDialog; + case Friends: + return _instance->friendsDialog; + case Search: + return _instance->searchDialog; + case Transfers: + return _instance->transfersDialog; + case SharedDirectories: + return _instance->sharedfilesDialog; + case Messages: + return _instance->messagesDialog; +#ifdef RS_USE_LINKS + case Links: + return _instance->linksDialog; +#endif + case Channels: + return _instance->channelFeed; + case Forums: + return _instance->forumsDialog; +#ifdef BLOGS + case Blogs: + return _instance->blogsFeed; +#endif + } + + return NULL; +} + +/***** TOOL BAR FUNCTIONS *****/ + +/** Add a Friend ShortCut */ +void MainWindow::addFriend() +{ + ConnectFriendWizard connwiz (this); + + connwiz.exec (); +} + +/** Shows Share Manager */ +void MainWindow::openShareManager() +{ + ShareManager::showYourself(); +} + + +/** Shows Messages Dialog */ +void +MainWindow::showMess() +{ + showWindow(MainWindow::Messages); +} + + +/** Shows Options */ +void MainWindow::showSettings() +{ + RSettingsWin::showYourself(this); +} + +/** Shows Messenger window */ +void MainWindow::showMessengerWindow() +{ + MessengerWindow::showYourself(); +} + + +/** Shows Application window */ +#ifdef UNFINISHED +void MainWindow::showApplWindow() +{ + applicationWindow->show(); +} +#endif + +/** If the user attempts to quit the app, a check-warning is issued. This warning can be + turned off for future quit events. +*/ +void MainWindow::doQuit() +{ + if(!Settings->value("doQuit", false).toBool()) + { + QString queryWrn; + queryWrn.clear(); + queryWrn.append(tr("Do you really want to exit RetroShare ?")); + + if ((QMessageBox::question(this, tr("Really quit ? "),queryWrn,QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) + { + qApp->quit(); + } + else + return; + } + + rApp->quit(); +} + +void MainWindow::displayErrorMessage(int a,int b,const QString& error_msg) +{ + QMessageBox::critical(NULL, tr("Internal Error"),error_msg) ; +} + +void MainWindow::closeEvent(QCloseEvent *e) +{ + static bool firstTime = true; + + if(!Settings->getCloseToTray()) + { + if (trayIcon->isVisible()) { + if (firstTime) + { +/***** + QMessageBox::information(this, tr("RetroShare System tray"), + tr("Application will continue running. Quit using context menu in the system tray")); +*****/ + firstTime = false; + } + hide(); + e->ignore(); + } + } + else + { + rsicontrol->rsGlobalShutDown(); + rApp->quit(); + } + + +} + +void MainWindow::updateMenu() +{ + toggleVisibilityAction->setText(isVisible() ? tr("Hide") : tr("Show")); +} + +void MainWindow::toggleVisibility(QSystemTrayIcon::ActivationReason e) +{ + if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick){ + if(isHidden()){ + show(); + if(isMinimized()){ + if(isMaximized()){ + showMaximized(); + }else{ + showNormal(); + } + } + raise(); + activateWindow(); + }else{ + hide(); + } + } +} + +void MainWindow::trayIconMessagesClicked(QSystemTrayIcon::ActivationReason e) +{ + if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { + showMess(); + } +} + +void MainWindow::trayIconForumsClicked(QSystemTrayIcon::ActivationReason e) +{ + if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { + showWindow(MainWindow::Forums); + } +} + +void MainWindow::trayIconChannelsClicked(QSystemTrayIcon::ActivationReason e) +{ + if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { + showWindow(MainWindow::Channels); + } +} + +void MainWindow::trayIconChatClicked(QSystemTrayIcon::ActivationReason e) +{ + if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { + PopupChatDialog *pcd = NULL; + std::list ids; + if (rsMsgs->getPrivateChatQueueIds(true, ids) && ids.size()) { + pcd = PopupChatDialog::getPrivateChat(ids.front(), RS_CHAT_OPEN | RS_CHAT_FOCUS); + } + + if (pcd == NULL) { + showWindow(MainWindow::Friends); + } + } +} + +void MainWindow::trayIconTransfersClicked(QSystemTrayIcon::ActivationReason e) +{ + if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { + showWindow(MainWindow::Transfers); + } +} + +void MainWindow::toggleVisibilitycontextmenu() +{ + if (isVisible()) + hide(); + else + show(); +} + +void MainWindow::loadStyleSheet(const QString &sheetName) +{ + /** internal Stylesheets **/ + //QFile file(":/qss/" + sheetName.toLower() + ".qss"); + + /** extern Stylesheets **/ + QFile file(QApplication::applicationDirPath() + "/qss/" + sheetName.toLower() + ".qss"); + + file.open(QFile::ReadOnly); + QString styleSheet = QLatin1String(file.readAll()); + + qApp->setStyleSheet(styleSheet); + +} + +void MainWindow::showabout() +{ + AboutDialog adlg(this); + adlg.exec(); +} + +/** Displays the help browser and displays the most recently viewed help + * topic. */ +void MainWindow::showHelpDialog() +{ + showHelpDialog(QString()); +} + + +/**< Shows the help browser and displays the given help topic. */ +void MainWindow::showHelpDialog(const QString &topic) +{ + static HelpBrowser *helpBrowser = 0; + if (!helpBrowser) + helpBrowser = new HelpBrowser(this); + helpBrowser->showWindow(topic); +} + +void MainWindow::on_actionQuick_Start_Wizard_activated() +{ + QuickStartWizard qstartwizard(this); + qstartwizard.exec(); +} + +/** Called when the user changes the UI translation. */ +void +MainWindow::retranslateUi() +{ + ui.retranslateUi(this); + foreach (MainPage *page, ui.stackPages->pages()) { + page->retranslateUi(); + } + foreach (QAction *action, ui.toolBar->actions()) { + action->setText(tr(qPrintable(action->data().toString()), "MainWindow")); + } +} + +void MainWindow::setStyle() +{ + QString standardSheet = "{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 , stop:1 );}"; + QColor stop1 = QColorDialog::getColor(Qt::white); + QColor stop2 = QColorDialog::getColor(Qt::black); + //QString widgetSheet = ".QWidget" + standardSheet.replace("", stop1.name()).replace("", stop2.name()); + QString toolSheet = "QToolBar" + standardSheet.replace("", stop1.name()).replace("", stop2.name()); + QString menuSheet = "QMenuBar" + standardSheet.replace("", stop1.name()).replace("", stop2.name()); + qApp->setStyleSheet(/*widgetSheet + */toolSheet + menuSheet); + +} + +/* set status object to status value */ +static void setStatusObject(QObject *pObject, int nStatus) +{ + QMenu *pMenu = dynamic_cast(pObject); + if (pMenu) { + /* set action in menu */ + foreach(QObject *pObject, pMenu->children()) { + QAction *pAction = qobject_cast (pObject); + if (pAction == NULL) { + continue; + } + + if (pAction->data().toInt() == nStatus) { + pAction->setChecked(true); + break; + } + } + return; + } + QComboBox *pComboBox = dynamic_cast(pObject); + if (pComboBox) { + /* set index of combobox */ + int nIndex = pComboBox->findData(nStatus, Qt::UserRole); + if (nIndex != -1) { + pComboBox->setCurrentIndex(nIndex); + } + return; + } + + /* add more objects here */ +} + +/** Load own status Online,Away,Busy **/ +void MainWindow::loadOwnStatus() +{ + m_bStatusLoadDone = true; + + StatusInfo statusInfo; + if (rsStatus->getOwnStatus(statusInfo)) { + /* send status to all added objects */ + for (std::set ::iterator it = m_apStatusObjects.begin(); it != m_apStatusObjects.end(); it++) { + setStatusObject(*it, statusInfo.status); + } + } +} + +void MainWindow::checkAndSetIdle(int idleTime) +{ + int maxTimeBeforeIdle = Settings->getMaxTimeBeforeIdle(); + if ((idleTime >= maxTimeBeforeIdle) && !isIdle) { + setIdle(true); + } else if ((idleTime < maxTimeBeforeIdle) && isIdle) { + setIdle(false); + } + + return; +} + +void MainWindow::setIdle(bool idle) +{ + isIdle = idle; + + StatusInfo statusInfo; + if (rsStatus->getOwnStatus(statusInfo)) { + setStatus(NULL, statusInfo.status); + } +} + +/* add and initialize status object */ +void MainWindow::initializeStatusObject(QObject *pObject, bool bConnect) +{ + if (m_apStatusObjects.find(pObject) != m_apStatusObjects.end()) { + /* already added */ + return; + } + + m_apStatusObjects.insert(m_apStatusObjects.end(), pObject); + + std::string statusString; + + QMenu *pMenu = dynamic_cast(pObject); + if (pMenu) { + /* initialize menu */ + QActionGroup *pGroup = new QActionGroup(pMenu); + + QAction *pAction = new QAction(QIcon(StatusDefs::imageIM(RS_STATUS_ONLINE)), StatusDefs::name(RS_STATUS_ONLINE), pMenu); + pAction->setData(RS_STATUS_ONLINE); + pAction->setCheckable(true); + pMenu->addAction(pAction); + pGroup->addAction(pAction); + + pAction = new QAction(QIcon(StatusDefs::imageIM(RS_STATUS_BUSY)), StatusDefs::name(RS_STATUS_BUSY), pMenu); + pAction->setData(RS_STATUS_BUSY); + pAction->setCheckable(true); + pMenu->addAction(pAction); + pGroup->addAction(pAction); + + pAction = new QAction(QIcon(StatusDefs::imageIM(RS_STATUS_AWAY)), StatusDefs::name(RS_STATUS_AWAY), pMenu); + pAction->setData(RS_STATUS_AWAY); + pAction->setCheckable(true); + pMenu->addAction(pAction); + pGroup->addAction(pAction); + + if (bConnect) { + connect(pMenu, SIGNAL(triggered (QAction*)), this, SLOT(statusChangedMenu(QAction*))); + } + } else { + /* initialize combobox */ + QComboBox *pComboBox = dynamic_cast(pObject); + if (pComboBox) { + pComboBox->addItem(QIcon(StatusDefs::imageIM(RS_STATUS_ONLINE)), StatusDefs::name(RS_STATUS_ONLINE), RS_STATUS_ONLINE); + pComboBox->addItem(QIcon(StatusDefs::imageIM(RS_STATUS_BUSY)), StatusDefs::name(RS_STATUS_BUSY), RS_STATUS_BUSY); + pComboBox->addItem(QIcon(StatusDefs::imageIM(RS_STATUS_AWAY)), StatusDefs::name(RS_STATUS_AWAY), RS_STATUS_AWAY); + + if (bConnect) { + connect(pComboBox, SIGNAL(activated(int)), this, SLOT(statusChangedComboBox(int))); + } + } + /* add more objects here */ + } + + if (m_bStatusLoadDone) { + /* loadOwnStatus done, set own status directly */ + StatusInfo statusInfo; + if (rsStatus->getOwnStatus(statusInfo)) { + setStatusObject(pObject, statusInfo.status); + } + } +} + +/* remove status object */ +void MainWindow::removeStatusObject(QObject *pObject) +{ + m_apStatusObjects.erase(pObject); + + /* disconnect all signals between the object and MainWindow */ + disconnect(pObject, NULL, this, NULL); +} + +/** Save own status Online,Away,Busy **/ +void MainWindow::setStatus(QObject *pObject, int nStatus) +{ + if (isIdle && nStatus == (int) RS_STATUS_ONLINE) { + /* set idle only when I am online */ + nStatus = RS_STATUS_INACTIVE; + } + + rsStatus->sendStatus("", nStatus); + + /* set status in all status objects, but the calling one */ + for (std::set ::iterator it = m_apStatusObjects.begin(); it != m_apStatusObjects.end(); it++) { + if (*it != pObject) { + setStatusObject(*it, nStatus); + } + } +} + +/* new status from context menu */ +void MainWindow::statusChangedMenu(QAction *pAction) +{ + if (pAction == NULL) { + return; + } + + setStatus(pAction->parent(), pAction->data().toInt()); +} + +/* new status from combobox in statusbar */ +void MainWindow::statusChangedComboBox(int index) +{ + if (index < 0) { + return; + } + + /* no object known */ + setStatus(NULL, statusComboBox->itemData(index, Qt::UserRole).toInt()); +} + +void MainWindow::linkActivated(const QUrl &url) +{ + RetroShareLink link(url); + + if (link.valid() == false) { + // QUrl can't handle the old RetroShare link format properly + if (url.host().isEmpty()) { + QMessageBox mb("RetroShare", tr("It seems to be an old RetroShare link. Please use copy instead."), QMessageBox::Critical, QMessageBox::Ok, 0, 0); + mb.setWindowIcon(QIcon(":/images/rstray3.png")); + mb.exec(); + return; + } + + QMessageBox mb("RetroShare", tr("The file link is malformed."), QMessageBox::Critical, QMessageBox::Ok, 0, 0); + mb.setWindowIcon(QIcon(":/images/rstray3.png")); + mb.exec(); + return; + } + + link.process(RSLINK_PROCESS_NOTIFY_ERROR | RSLINK_PROCESS_NOTIFY_SUCCESS); +} diff --git a/retroshare-gui/src/gui/MainWindow.h b/retroshare-gui/src/gui/MainWindow.h new file mode 100644 index 000000000..c022c539e --- /dev/null +++ b/retroshare-gui/src/gui/MainWindow.h @@ -0,0 +1,267 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 The RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _MainWindow_H +#define _MainWindow_H + +#include +#include + +#include "ui_MainWindow.h" +#include "gui/common/rwindow.h" + +class QComboBox; +class QLabel; +class Idle; +class PeerStatus; +class NATStatus; +class RatesStatus; +class DiscStatus; +class DHTStatus; +class HashingStatus; +class ForumsDialog; +class FriendsDialog; +class ChatDialog; +class NetworkDialog; +class SearchDialog; +class TransfersDialog; +class MessagesDialog; +class SharedFilesDialog; +class MessengerWindow; +class PluginsPage; +class ChannelFeed; +class BandwidthGraph; + +#ifdef RS_USE_LINKS +class LinksDialog; +#endif + +#ifdef BLOGS +class BlogsDialog; +#endif + +#ifdef UNFINISHED +class ApplicationWindow; +#endif + +class MainWindow : public RWindow +{ + Q_OBJECT + +public: + /** Main dialog pages. */ + enum Page { + /* Fixed numbers for load and save the last page */ + Network = 0, /** Network page. */ + Friends = 1, /** Friends page. */ + Search = 2, /** Search page. */ + Transfers = 3, /** Transfers page. */ + SharedDirectories = 4, /** Shared Directories page. */ + Messages = 5, /** Messages page. */ + Channels = 6, /** Channels page. */ + Forums = 7, /** Forums page. */ +#ifdef BLOGS + Blogs = 8, /** Blogs page. */ +#endif +#ifdef RS_USE_LINKS + Links = 9, /** Links page. */ +#endif + }; + + /** Create main window */ + static MainWindow *Create (); + static MainWindow *getInstance(); + + /** Destructor. */ + ~MainWindow(); + + /** Shows the MainWindow dialog with focus set to the given page. */ + static void showWindow(Page page); + /** Set focus to the given page. */ + static bool activatePage (Page page); + static Page getActivatePage (); + + /** get page */ + static MainPage *getPage (Page page); + + /* A Bit of a Hack... but public variables for + * the dialogs, so we can add them to the + * Notify Class... + */ + + NetworkDialog *networkDialog; + FriendsDialog *friendsDialog; + SearchDialog *searchDialog; + TransfersDialog *transfersDialog; + ChatDialog *chatDialog; + MessagesDialog *messagesDialog; + SharedFilesDialog *sharedfilesDialog; + ForumsDialog *forumsDialog; + ChannelFeed *channelFeed; + Idle *idle; + +#ifdef RS_USE_LINKS + LinksDialog *linksDialog; +#endif + +#ifdef BLOGS + BlogsDialog *blogsFeed; +#endif + +#ifdef UNFINISHED + ApplicationWindow *applicationWindow; +#endif + PluginsPage* pluginsPage ; + + static void installGroupChatNotifier(); + static void installNotifyIcons(); + + /* initialize widget with status informations, status constant stored in data or in Qt::UserRole */ + void initializeStatusObject(QObject *pObject, bool bConnect); + void removeStatusObject(QObject *pObject); + void setStatus(QObject *pObject, int nStatus); + +public slots: + void displayErrorMessage(int,int,const QString&) ; + void postModDirectories(bool update_local); + void displayDiskSpaceWarning(int loc,int size_limit_mb) ; + void checkAndSetIdle(int idleTime); + void updateMessages(); + void updateForums(); + void updateChannels(int type); + void updateTransfers(int count); + void privateChatChanged(int list, int type); + + void linkActivated(const QUrl &url); + +protected: + /** Default Constructor */ + MainWindow(QWidget *parent = 0, Qt::WFlags flags = 0); + + void closeEvent(QCloseEvent *); + + /** Called when the user changes the UI translation. */ + virtual void retranslateUi(); + +private slots: + + void updateMenu(); + void updateStatus(); + + void toggleVisibility(QSystemTrayIcon::ActivationReason e); + void toggleVisibilitycontextmenu(); + + /* default parameter for connect with the actions of the combined systray icon */ + void trayIconMessagesClicked(QSystemTrayIcon::ActivationReason e = QSystemTrayIcon::Trigger); + void trayIconForumsClicked(QSystemTrayIcon::ActivationReason e = QSystemTrayIcon::Trigger); + void trayIconChannelsClicked(QSystemTrayIcon::ActivationReason e = QSystemTrayIcon::Trigger); + void trayIconChatClicked(QSystemTrayIcon::ActivationReason e = QSystemTrayIcon::Trigger); + void trayIconTransfersClicked(QSystemTrayIcon::ActivationReason e = QSystemTrayIcon::Trigger); + + /** Toolbar fns. */ + void addFriend(); + void showMessengerWindow(); +#ifdef UNFINISHED + void showApplWindow(); +#endif + + void showabout(); + void openShareManager(); + void displaySystrayMsg(const QString&,const QString&) ; + + /** Displays the help browser and displays the most recently viewed help + * topic. */ + void showHelpDialog(); + /** Called when a child window requests the given help topic. */ + void showHelpDialog(const QString &topic); + + void showMess(); + void showSettings(); + void setStyle(); + void statusChangedMenu(QAction *pAction); + void statusChangedComboBox(int index); + + /** Called when user attempts to quit via quit button*/ + void doQuit(); + + void on_actionQuick_Start_Wizard_activated(); + +private: + void createTrayIcon(); + void createNotifyIcons(); + void updateTrayCombine(); + + static MainWindow *_instance; + + /** A BandwidthGraph object which handles monitoring RetroShare bandwidth usage */ + BandwidthGraph* _bandwidthGraph; + + /** Creates a new action for a Main page. */ + QAction* createPageAction(QIcon img, QString text, QActionGroup *group); + /** Adds a new action to the toolbar. */ + void addAction(QAction *action, const char *slot = 0); + + void loadStyleSheet(const QString &sheetName); + + QString nameAndLocation; + + QSystemTrayIcon *trayIcon; + QSystemTrayIcon *trayIconCombined; + QSystemTrayIcon *trayIconMessages; + QSystemTrayIcon *trayIconForums; + QSystemTrayIcon *trayIconChannels; + QSystemTrayIcon *trayIconChat; + QSystemTrayIcon *trayIconTransfers; + QAction *trayActionMessages; + QAction *trayActionForums; + QAction *trayActionChannels; + QAction *trayActionChat; + QAction *trayActionTransfers; + QAction *toggleVisibilityAction, *toolAct; + + PeerStatus *peerstatus; + NATStatus *natstatus; + DHTStatus *dhtstatus; + RatesStatus *ratesstatus; + DiscStatus *discstatus; + HashingStatus *hashingstatus; + QComboBox *statusComboBox; + + QAction *messageAction; + QAction *forumAction; + QAction *channelAction; + QAction *transferAction; + + /* Status */ + std::set m_apStatusObjects; // added objects for status + bool m_bStatusLoadDone; + + void loadOwnStatus(); + + // idle function + void setIdle(bool Idle); + bool isIdle; + + /** Qt Designer generated object */ + Ui::MainWindow ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/MainWindow.ui b/retroshare-gui/src/gui/MainWindow.ui new file mode 100644 index 000000000..f8806bd70 --- /dev/null +++ b/retroshare-gui/src/gui/MainWindow.ui @@ -0,0 +1,150 @@ + + + MainWindow + + + + 0 + 0 + 571 + 450 + + + + MainWindow + + + + + 0 + + + + + + + + + + Qt::CustomContextMenu + + + Qt::ToolButtonTextUnderIcon + + + TopToolBarArea + + + false + + + + + Qt::CustomContextMenu + + + LeftToolBarArea + + + false + + + + + + + + + + + + + + + :/images/user/add_user24.png:/images/user/add_user24.png + + + Add Friend + + + Add a Friend Wizard + + + + + + :/images/add-share24.png:/images/add-share24.png + + + Add Share + + + + + + :/images/kcmsystem24.png:/images/kcmsystem24.png + + + Options + + + + + + :/images/messenger.png:/images/messenger.png + + + Messenger + + + true + + + + + + :/images/informations_24x24.png:/images/informations_24x24.png + + + About + + + + + SMPlayer + + + + + + :/images/exit_24x24.png:/images/exit_24x24.png + + + Quit + + + + + + :/images/tools_wizard.png:/images/tools_wizard.png + + + Quick Start Wizard + + + Quick Start Wizard + + + + + + MainPageStack + QWidget +
    gui/mainpagestack.h
    +
    +
    + + + + +
    diff --git a/retroshare-gui/src/gui/MessagesDialog.cpp b/retroshare-gui/src/gui/MessagesDialog.cpp new file mode 100644 index 000000000..49c7dac5b --- /dev/null +++ b/retroshare-gui/src/gui/MessagesDialog.cpp @@ -0,0 +1,1994 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include + +#include "MessagesDialog.h" +#include "msgs/MessageComposer.h" +#include "msgs/MessageWidget.h" +#include "msgs/TagsMenu.h" +#include "settings/rsharesettings.h" +#include "common/TagDefs.h" +#include "common/PeerDefs.h" +#include "common/RSItemDelegate.h" + +#include +#include + +#include + +/* Images for context menu icons */ +#define IMAGE_MESSAGE ":/images/folder-draft.png" +#define IMAGE_MESSAGEREMOVE ":/images/message-mail-imapdelete.png" +#define IMAGE_STAR_ON ":/images/star-on-16.png" +#define IMAGE_STAR_OFF ":/images/star-off-16.png" + +#define COLUMN_COUNT 8 +#define COLUMN_STAR 0 +#define COLUMN_ATTACHEMENTS 1 +#define COLUMN_SUBJECT 2 +#define COLUMN_UNREAD 3 +#define COLUMN_FROM 4 +#define COLUMN_DATE 5 +#define COLUMN_CONTENT 6 +#define COLUMN_TAGS 7 + +#define COLUMN_DATA 0 // column for storing the userdata like msgid and srcid + +#define ROLE_SORT Qt::UserRole +#define ROLE_MSGID Qt::UserRole + 1 +#define ROLE_SRCID Qt::UserRole + 2 +#define ROLE_UNREAD Qt::UserRole + 3 +#define ROLE_MSGFLAGS Qt::UserRole + 4 + +#define ROLE_QUICKVIEW_TYPE Qt::UserRole +#define ROLE_QUICKVIEW_ID Qt::UserRole + 1 +#define ROLE_QUICKVIEW_TEXT Qt::UserRole + 2 + +#define QUICKVIEW_TYPE_NOTHING 0 +#define QUICKVIEW_TYPE_STATIC 1 +#define QUICKVIEW_TYPE_TAG 2 + +#define QUICKVIEW_STATIC_ID_STARRED 1 + +#define ROW_INBOX 0 +#define ROW_OUTBOX 1 +#define ROW_DRAFTBOX 2 +#define ROW_SENTBOX 3 +#define ROW_TRASHBOX 4 + + +MessagesDialog::LockUpdate::LockUpdate (MessagesDialog *pDialog, bool bUpdate) +{ + m_pDialog = pDialog; + m_bUpdate = bUpdate; + + m_pDialog->m_nLockUpdate++; +} + +MessagesDialog::LockUpdate::~LockUpdate () +{ + if(--m_pDialog->m_nLockUpdate < 0) + m_pDialog->m_nLockUpdate = 0; + + if (m_bUpdate && m_pDialog->m_nLockUpdate == 0) { + m_pDialog->insertMessages(); + } +} + +void MessagesDialog::LockUpdate::setUpdate(bool bUpdate) +{ + m_bUpdate = bUpdate; +} + +static int FilterColumnFromComboBox(int nIndex) +{ + switch (nIndex) { + case 0: + return COLUMN_ATTACHEMENTS; + case 1: + return COLUMN_SUBJECT; + case 2: + return COLUMN_FROM; + case 3: + return COLUMN_DATE; + case 4: + return COLUMN_CONTENT; + case 5: + return COLUMN_TAGS; + } + + return COLUMN_SUBJECT; +} + +static int FilterColumnToComboBox(int nIndex) +{ + switch (nIndex) { + case COLUMN_ATTACHEMENTS: + return 0; + case COLUMN_SUBJECT: + return 1; + case COLUMN_FROM: + return 2; + case COLUMN_DATE: + return 3; + case COLUMN_CONTENT: + return 4; + case COLUMN_TAGS: + return 5; + } + + return FilterColumnToComboBox(COLUMN_SUBJECT); +} + +/** Constructor */ +MessagesDialog::MessagesDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + m_bProcessSettings = false; + inChange = false; + m_nLockUpdate = 0; + + connect(ui.messagestreeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(messageslistWidgetCostumPopupMenu(QPoint))); + connect(ui.listWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(folderlistWidgetCostumPopupMenu(QPoint))); + connect(ui.messagestreeView, SIGNAL(clicked(const QModelIndex&)) , this, SLOT(clicked(const QModelIndex&))); + connect(ui.messagestreeView, SIGNAL(doubleClicked(const QModelIndex&)) , this, SLOT(doubleClicked(const QModelIndex&))); + connect(ui.listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(changeBox(int))); + connect(ui.quickViewWidget, SIGNAL(currentRowChanged(int)), this, SLOT(changeQuickView(int))); + connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); + connect(ui.tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int))); + connect(ui.newmessageButton, SIGNAL(clicked()), this, SLOT(newmessage())); + + connect(ui.actionTextBesideIcon, SIGNAL(triggered()), this, SLOT(buttonStyle())); + connect(ui.actionIconOnly, SIGNAL(triggered()), this, SLOT(buttonStyle())); + connect(ui.actionTextUnderIcon, SIGNAL(triggered()), this, SLOT(buttonStyle())); + + ui.actionTextBesideIcon->setData(Qt::ToolButtonTextBesideIcon); + ui.actionIconOnly->setData(Qt::ToolButtonIconOnly); + ui.actionTextUnderIcon->setData(Qt::ToolButtonTextUnderIcon); + + connect(ui.clearButton, SIGNAL(clicked()), this, SLOT(clearFilter())); + connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged())); + + connect(ui.filterColumnComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterColumnChanged())); + + msgWidget = new MessageWidget(true, this); + ui.msgLayout->addWidget(msgWidget); + + connectActions(); + + m_eListMode = LIST_NOTHING; + + mCurrMsgId = ""; + + // Set the QStandardItemModel + MessagesModel = new QStandardItemModel(0, COLUMN_COUNT); + MessagesModel->setHeaderData(COLUMN_ATTACHEMENTS, Qt::Horizontal, QIcon(":/images/attachment.png"), Qt::DecorationRole); + MessagesModel->setHeaderData(COLUMN_SUBJECT, Qt::Horizontal, tr("Subject")); + MessagesModel->setHeaderData(COLUMN_UNREAD, Qt::Horizontal, QIcon(":/images/message-state-header.png"), Qt::DecorationRole); + MessagesModel->setHeaderData(COLUMN_FROM, Qt::Horizontal, tr("From")); + MessagesModel->setHeaderData(COLUMN_DATE, Qt::Horizontal, tr("Date")); + MessagesModel->setHeaderData(COLUMN_TAGS, Qt::Horizontal, tr("Tags")); + MessagesModel->setHeaderData(COLUMN_CONTENT, Qt::Horizontal, tr("Content")); + MessagesModel->setHeaderData(COLUMN_STAR, Qt::Horizontal, QIcon(IMAGE_STAR_ON), Qt::DecorationRole); + + MessagesModel->setHeaderData(COLUMN_ATTACHEMENTS, Qt::Horizontal, tr("Click to sort by attachments"), Qt::ToolTipRole); + MessagesModel->setHeaderData(COLUMN_SUBJECT, Qt::Horizontal, tr("Click to sort by subject"), Qt::ToolTipRole); + MessagesModel->setHeaderData(COLUMN_UNREAD, Qt::Horizontal, tr("Click to sort by read"), Qt::ToolTipRole); + MessagesModel->setHeaderData(COLUMN_FROM, Qt::Horizontal, tr("Click to sort by from"), Qt::ToolTipRole); + MessagesModel->setHeaderData(COLUMN_DATE, Qt::Horizontal, tr("Click to sort by date"), Qt::ToolTipRole); + MessagesModel->setHeaderData(COLUMN_TAGS, Qt::Horizontal, tr("Click to sort by tags"), Qt::ToolTipRole); + MessagesModel->setHeaderData(COLUMN_STAR, Qt::Horizontal, tr("Click to sort by star"), Qt::ToolTipRole); + + proxyModel = new QSortFilterProxyModel(this); + proxyModel->setDynamicSortFilter(true); + proxyModel->setSourceModel(MessagesModel); + proxyModel->setSortRole(ROLE_SORT); + proxyModel->sort (COLUMN_DATE, Qt::DescendingOrder); + ui.messagestreeView->setModel(proxyModel); + ui.messagestreeView->setSelectionBehavior(QTreeView::SelectRows); + connect(ui.messagestreeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(updateInterface())); + + RSItemDelegate *itemDelegate = new RSItemDelegate(this); + itemDelegate->setSpacing(QSize(0, 2)); + ui.messagestreeView->setItemDelegate(itemDelegate); + + ui.messagestreeView->setRootIsDecorated(false); + ui.messagestreeView->setSortingEnabled(true); + ui.messagestreeView->sortByColumn(COLUMN_DATE, Qt::DescendingOrder); + + // connect after setting model + connect( ui.messagestreeView->selectionModel(), SIGNAL(currentChanged ( QModelIndex, QModelIndex ) ) , this, SLOT( currentChanged( const QModelIndex & ) ) ); + + // workaround for Qt bug, should be solved in next Qt release 4.7.0 + // http://bugreports.qt.nokia.com/browse/QTBUG-8270 + QShortcut *Shortcut = new QShortcut(QKeySequence (Qt::Key_Delete), ui.messagestreeView, 0, 0, Qt::WidgetShortcut); + connect(Shortcut, SIGNAL(activated()), this, SLOT( removemessage ())); + Shortcut = new QShortcut(QKeySequence (Qt::SHIFT | Qt::Key_Delete), ui.messagestreeView, 0, 0, Qt::WidgetShortcut); + connect(Shortcut, SIGNAL(activated()), this, SLOT( removemessage ())); + + /* Set header initial section sizes */ + QHeaderView * msgwheader = ui.messagestreeView->header () ; + msgwheader->resizeSection (COLUMN_ATTACHEMENTS, 24); + msgwheader->resizeSection (COLUMN_SUBJECT, 250); + msgwheader->resizeSection (COLUMN_UNREAD, 16); + msgwheader->resizeSection (COLUMN_FROM, 140); + msgwheader->resizeSection (COLUMN_DATE, 140); + msgwheader->resizeSection (COLUMN_STAR, 16); + + msgwheader->setResizeMode (COLUMN_STAR, QHeaderView::Fixed); + msgwheader->resizeSection (COLUMN_STAR, 24); + + ui.forwardmessageButton->setToolTip(tr("Forward selected Message")); + ui.replyallmessageButton->setToolTip(tr("Reply to All")); + + QMenu *printmenu = new QMenu(); + printmenu->addAction(ui.actionPrint); + printmenu->addAction(ui.actionPrintPreview); + ui.printbutton->setMenu(printmenu); + + QMenu *viewmenu = new QMenu(); + viewmenu->addAction(ui.actionTextBesideIcon); + viewmenu->addAction(ui.actionIconOnly); + //viewmenu->addAction(ui.actionTextUnderIcon); + ui.viewtoolButton->setMenu(viewmenu); + + ui.filterPatternLineEdit->setMinimumWidth(20); + + //setting default filter by column as subject + proxyModel->setFilterKeyColumn(FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex())); + + ui.clearButton->hide(); + + // load settings + processSettings(true); + + /* Set header sizes for the fixed columns and resize modes, must be set after processSettings */ + msgwheader->setResizeMode (COLUMN_ATTACHEMENTS, QHeaderView::Fixed); + msgwheader->setResizeMode (COLUMN_DATE, QHeaderView::Interactive); + msgwheader->setResizeMode (COLUMN_UNREAD, QHeaderView::Fixed); + msgwheader->resizeSection (COLUMN_UNREAD, 24); + msgwheader->resizeSection (COLUMN_STAR, 24); + msgwheader->setResizeMode (COLUMN_STAR, QHeaderView::Fixed); + + // fill folder list + updateMessageSummaryList(); + ui.listWidget->setCurrentRow(ROW_INBOX); + + // create tag menu + TagsMenu *menu = new TagsMenu (tr("Tags"), this); + connect(menu, SIGNAL(aboutToShow()), this, SLOT(tagAboutToShow())); + connect(menu, SIGNAL(tagSet(int, bool)), this, SLOT(tagSet(int, bool))); + connect(menu, SIGNAL(tagRemoveAll()), this, SLOT(tagRemoveAll())); + + ui.tagButton->setMenu(menu); + + // fill quick view + fillQuickView(); + + // create timer for navigation + timer = new QTimer(this); + timer->setInterval(300); + timer->setSingleShot(true); + connect(timer, SIGNAL(timeout()), this, SLOT(updateCurrentMessage())); + + ui.messagestreeView->installEventFilter(this); + + // remove close button of the the first tab + QTabBar::ButtonPosition buttonPosition = (QTabBar::ButtonPosition) ui.tabWidget->tabBar()->style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, 0); + QWidget *tabButton = ui.tabWidget->tabBar()->tabButton(0, buttonPosition); + if (tabButton) { + tabButton->hide(); + } + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +MessagesDialog::~MessagesDialog() +{ + // stop and delete timer + timer->stop(); + delete(timer); + + // save settings + processSettings(false); +} + +void MessagesDialog::processSettings(bool load) +{ + int messageTreeVersion = 2; // version number for the settings to solve problems when modifying the column count + + m_bProcessSettings = true; + + QHeaderView *msgwheader = ui.messagestreeView->header () ; + + Settings->beginGroup("MessageDialog"); + + if (load) { + // load settings + + // filterColumn + int nValue = FilterColumnToComboBox(Settings->value("filterColumn", true).toInt()); + ui.filterColumnComboBox->setCurrentIndex(nValue); + + // state of message tree + if (Settings->value("MessageTreeVersion").toInt() == messageTreeVersion) { + msgwheader->restoreState(Settings->value("MessageTree").toByteArray()); + } + + // state of quick view list + bool value = Settings->value("QuickViewList", true).toBool(); + ui.quickViewsButton->setChecked(value); + + // state of splitter + ui.msgSplitter->restoreState(Settings->value("Splitter").toByteArray()); + ui.msgSplitter_2->restoreState(Settings->value("Splitter2").toByteArray()); + ui.listSplitter->restoreState(Settings->value("Splitter3").toByteArray()); + + /* toolbar button style */ + Qt::ToolButtonStyle style = (Qt::ToolButtonStyle) Settings->value("ToolButon_Stlye", Qt::ToolButtonIconOnly).toInt(); + setToolbarButtonStyle(style); + } else { + // save settings + + // state of message tree + Settings->setValue("MessageTree", msgwheader->saveState()); + Settings->setValue("MessageTreeVersion", messageTreeVersion); + + // state of quick view list + Settings->setValue("QuickViewList", ui.quickViewsButton->isChecked()); + + // state of splitter + Settings->setValue("Splitter", ui.msgSplitter->saveState()); + Settings->setValue("Splitter2", ui.msgSplitter_2->saveState()); + Settings->setValue("Splitter3", ui.listSplitter->saveState()); + + /* toolbar button style */ + Settings->setValue("ToolButon_Stlye", ui.newmessageButton->toolButtonStyle()); + } + + Settings->endGroup(); + + if (msgWidget) { + msgWidget->processSettings("MessageDialog", load); + } + + m_bProcessSettings = false; +} + +bool MessagesDialog::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == ui.messagestreeView) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent && keyEvent->key() == Qt::Key_Space) { + // Space pressed + QModelIndex currentIndex = ui.messagestreeView->currentIndex(); + QModelIndex index = ui.messagestreeView->model()->index(currentIndex.row(), COLUMN_UNREAD, currentIndex.parent()); + clicked(index); + return true; // eat event + } + } + } + // pass the event on to the parent class + return MainPage::eventFilter(obj, event); +} + +void MessagesDialog::fillQuickView() +{ + MsgTagType tags; + rsMsgs->getMessageTagTypes(tags); + std::map >::iterator tag; + + // fill tags + inChange = true; + + // save current selection + QListWidgetItem *item = ui.quickViewWidget->currentItem(); + int nSelectedType = 0; + uint32_t nSelectedId = 0; + if (item) { + nSelectedType = item->data(ROLE_QUICKVIEW_TYPE).toInt(); + nSelectedId = item->data(ROLE_QUICKVIEW_ID).toInt(); + } + + QListWidgetItem *itemToSelect = NULL; + QString text; + + ui.quickViewWidget->clear(); + + // add static items + item = new QListWidgetItem(tr("Starred"), ui.quickViewWidget); + item->setIcon(QIcon(IMAGE_STAR_ON)); + item->setData(ROLE_QUICKVIEW_TYPE, QUICKVIEW_TYPE_STATIC); + item->setData(ROLE_QUICKVIEW_ID, QUICKVIEW_STATIC_ID_STARRED); + item->setData(ROLE_QUICKVIEW_TEXT, item->text()); // for updateMessageSummaryList + + if (nSelectedType == QUICKVIEW_TYPE_STATIC && nSelectedId == QUICKVIEW_STATIC_ID_STARRED) { + itemToSelect = item; + } + + for (tag = tags.types.begin(); tag != tags.types.end(); tag++) { + text = TagDefs::name(tag->first, tag->second.first); + + item = new QListWidgetItem (text, ui.quickViewWidget); + item->setForeground(QBrush(QColor(tag->second.second))); + item->setIcon(QIcon(":/images/foldermail.png")); + item->setData(ROLE_QUICKVIEW_TYPE, QUICKVIEW_TYPE_TAG); + item->setData(ROLE_QUICKVIEW_ID, tag->first); + item->setData(ROLE_QUICKVIEW_TEXT, text); // for updateMessageSummaryList + + if (nSelectedType == QUICKVIEW_TYPE_TAG && tag->first == nSelectedId) { + itemToSelect = item; + } + } + + if (itemToSelect) { + ui.quickViewWidget->setCurrentItem(itemToSelect); + } + + inChange = false; + + updateMessageSummaryList(); +} + +// replaced by shortcut +//void MessagesDialog::keyPressEvent(QKeyEvent *e) +//{ +// if(e->key() == Qt::Key_Delete) +// { +// removemessage() ; +// e->accept() ; +// } +// else +// MainPage::keyPressEvent(e) ; +//} + +int MessagesDialog::getSelectedMsgCount (QList *pRows, QList *pRowsRead, QList *pRowsUnread, QList *pRowsStar) +{ + if (pRowsRead) pRowsRead->clear(); + if (pRowsUnread) pRowsUnread->clear(); + if (pRowsStar) pRowsStar->clear(); + + //To check if the selection has more than one row. + QList selectedIndexList = ui.messagestreeView->selectionModel() -> selectedIndexes (); + QList rowList; + for(QList::iterator it = selectedIndexList.begin(); it != selectedIndexList.end(); it++) + { + int row = it->row(); + if (rowList.contains(row) == false) + { + rowList.append(row); + + if (pRows || pRowsRead || pRowsUnread || pRowsStar) { + int mappedRow = proxyModel->mapToSource(*it).row(); + + if (pRows) pRows->append(mappedRow); + + if (MessagesModel->item(mappedRow, COLUMN_DATA)->data(ROLE_UNREAD).toBool()) { + if (pRowsUnread) pRowsUnread->append(mappedRow); + } else { + if (pRowsRead) pRowsRead->append(mappedRow); + } + + if (pRowsStar) { + if (MessagesModel->item(mappedRow, COLUMN_DATA)->data(ROLE_MSGFLAGS).toInt() & RS_MSG_STAR) { + pRowsStar->append(mappedRow); + } + } + } + } + } + + return rowList.size(); +} + +bool MessagesDialog::isMessageRead(int nRow) +{ + QStandardItem *item = MessagesModel->item(nRow,COLUMN_DATA); + return !item->data(ROLE_UNREAD).toBool(); +} + +bool MessagesDialog::hasMessageStar(int nRow) +{ + QStandardItem *item = MessagesModel->item(nRow,COLUMN_DATA); + return item->data(ROLE_MSGFLAGS).toInt() & RS_MSG_STAR; +} + +void MessagesDialog::messageslistWidgetCostumPopupMenu( QPoint point ) +{ + std::string cid; + std::string mid; + + MessageInfo msgInfo; + if (getCurrentMsg(cid, mid)) { + rsMsgs->getMessage(mid, msgInfo); + } + + QList RowsRead; + QList RowsUnread; + QList RowsStar; + int nCount = getSelectedMsgCount (NULL, &RowsRead, &RowsUnread, &RowsStar); + + /** Defines the actions for the context menu */ + + QMenu contextMnu( this ); + + QAction *action = contextMnu.addAction(tr("Open in a new window"), this, SLOT(openAsWindow())); + if (nCount != 1) { + action->setDisabled(true); + } + + action = contextMnu.addAction(tr("Open in a new tab"), this, SLOT(openAsTab())); + if (nCount != 1) { + action->setDisabled(true); + } + + contextMnu.addSeparator(); + + contextMnu.addAction(ui.actionReply); + ui.actionReply->setEnabled(nCount == 1); + + contextMnu.addAction(ui.actionReplyAll); + ui.actionReplyAll->setEnabled(nCount == 1); + + contextMnu.addAction(ui.actionForward); + ui.actionForward->setEnabled(nCount == 1); + + contextMnu.addSeparator(); + + action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark as read"), this, SLOT(markAsRead())); + if (RowsUnread.size() == 0) { + action->setDisabled(true); + } + + action = contextMnu.addAction(QIcon(":/images/message-mail.png"), tr("Mark as unread"), this, SLOT(markAsUnread())); + if (RowsRead.size() == 0) { + action->setDisabled(true); + } + + action = contextMnu.addAction(tr("Add Star")); + action->setCheckable(true); + action->setChecked(RowsStar.size()); + connect(action, SIGNAL(triggered(bool)), this, SLOT(markWithStar(bool))); + + contextMnu.addSeparator(); + + // add tags + contextMnu.addMenu(ui.tagButton->menu()); + + contextMnu.addSeparator(); + + QString text; + if ((msgInfo.msgflags & RS_MSG_BOXMASK) == RS_MSG_DRAFTBOX) { + text = tr("Edit"); + } else { + text = tr("Edit as new"); + } + action = contextMnu.addAction(text, this, SLOT(editmessage())); + if (nCount != 1) { + action->setDisabled(true); + } + + action = contextMnu.addAction(QIcon(IMAGE_MESSAGEREMOVE), (nCount > 1) ? tr("Remove Messages") : tr("Remove Message"), this, SLOT(removemessage())); + if (nCount == 0) { + action->setDisabled(true); + } + + int listrow = ui.listWidget->currentRow(); + if (listrow == ROW_TRASHBOX) { + action = contextMnu.addAction(tr("Undelete"), this, SLOT(undeletemessage())); + if (nCount == 0) { + action->setDisabled(true); + } + } + + contextMnu.addAction(ui.actionSaveAs); + contextMnu.addAction(ui.actionPrintPreview); + contextMnu.addAction(ui.actionPrint); + contextMnu.addSeparator(); + + contextMnu.addAction(QIcon(IMAGE_MESSAGE), tr("New Message"), this, SLOT(newmessage())); + + contextMnu.exec(QCursor::pos()); +} + +void MessagesDialog::folderlistWidgetCostumPopupMenu(QPoint point) +{ + if (ui.listWidget->currentRow() != ROW_TRASHBOX) { + /* Context menu only neede for trash box */ + return; + } + + QMenu contextMnu(this); + + contextMnu.addAction(tr("Empty trash"), this, SLOT(emptyTrash())); + + contextMnu.exec(QCursor::pos()); +} + +void MessagesDialog::newmessage() +{ + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + nMsgDialog->show(); + nMsgDialog->activateWindow(); + + /* window will destroy itself! */ +} + +void MessagesDialog::openAsWindow() +{ + std::string cid; + std::string mid; + + if(!getCurrentMsg(cid, mid)) + return ; + + MessageWidget *msgWidget = MessageWidget::openMsg(mid, true); + if (msgWidget == NULL) { + return; + } + + msgWidget->activateWindow(); + + /* window will destroy itself! */ +} + +void MessagesDialog::openAsTab() +{ + std::string cid; + std::string mid; + + if(!getCurrentMsg(cid, mid)) + return ; + + MessageWidget *msgWidget = MessageWidget::openMsg(mid, false); + if (msgWidget == NULL) { + return; + } + + ui.tabWidget->addTab(msgWidget, msgWidget->subject(true)); + ui.tabWidget->setCurrentWidget(msgWidget); + + /* window will destroy itself! */ +} + +void MessagesDialog::editmessage() +{ + std::string cid; + std::string mid; + + if(!getCurrentMsg(cid, mid)) + return ; + + MessageComposer *msgComposer = MessageComposer::newMsg(mid); + if (msgComposer == NULL) { + return; + } + + msgComposer->show(); + msgComposer->activateWindow(); + + /* window will destroy itself! */ +} + +void MessagesDialog::changeBox(int) +{ + if (inChange) { + // already in change method + return; + } + + inChange = true; + + MessagesModel->removeRows (0, MessagesModel->rowCount()); + + ui.quickViewWidget->setCurrentItem(NULL); + m_eListMode = LIST_BOX; + + insertMessages(); + insertMsgTxtAndFiles(); + + inChange = false; +} + +void MessagesDialog::changeQuickView(int newrow) +{ + Q_UNUSED(newrow); + + if (inChange) { + // already in change method + return; + } + + inChange = true; + + MessagesModel->removeRows (0, MessagesModel->rowCount()); + + ui.listWidget->setCurrentItem(NULL); + m_eListMode = LIST_QUICKVIEW; + + insertMessages(); + insertMsgTxtAndFiles(); + + inChange = false; +} + +void MessagesDialog::messagesTagsChanged() +{ + if (m_nLockUpdate) { + return; + } + + fillQuickView(); + insertMessages(); +} + +static void InitIconAndFont(QStandardItem *item[COLUMN_COUNT]) +{ + int msgFlags = item[COLUMN_DATA]->data(ROLE_MSGFLAGS).toInt(); + + // show the real "New" state + if (msgFlags & RS_MSG_NEW) { + item[COLUMN_SUBJECT]->setIcon(QIcon(":/images/message-state-new.png")); + } else { + if (msgFlags & RS_MSG_UNREAD_BY_USER) { + if ((msgFlags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_REPLIED) { + item[COLUMN_SUBJECT]->setIcon(QIcon(":/images/message-mail-replied.png")); + } else if ((msgFlags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_FORWARDED) { + item[COLUMN_SUBJECT]->setIcon(QIcon(":/images/message-mail-forwarded.png")); + } else if ((msgFlags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == (RS_MSG_REPLIED | RS_MSG_FORWARDED)) { + item[COLUMN_SUBJECT]->setIcon(QIcon(":/images/message-mail-replied-forw.png")); + } else { + item[COLUMN_SUBJECT]->setIcon(QIcon(":/images/message-mail.png")); + } + } else { + if ((msgFlags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_REPLIED) { + item[COLUMN_SUBJECT]->setIcon(QIcon(":/images/message-mail-replied-read.png")); + } else if ((msgFlags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == RS_MSG_FORWARDED) { + item[COLUMN_SUBJECT]->setIcon(QIcon(":/images/message-mail-forwarded-read.png")); + } else if ((msgFlags & (RS_MSG_REPLIED | RS_MSG_FORWARDED)) == (RS_MSG_REPLIED | RS_MSG_FORWARDED)) { + item[COLUMN_SUBJECT]->setIcon(QIcon(":/images/message-mail-replied-forw-read.png")); + } else { + item[COLUMN_SUBJECT]->setIcon(QIcon(":/images/message-mail-read.png")); + } + } + } + + if (msgFlags & RS_MSG_STAR) { + item[COLUMN_STAR]->setIcon(QIcon(IMAGE_STAR_ON)); + item[COLUMN_STAR]->setText("1"); + } else { + item[COLUMN_STAR]->setIcon(QIcon(IMAGE_STAR_OFF)); + item[COLUMN_STAR]->setText("0"); + } + + bool isNew = msgFlags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER); + + // set icon + if (isNew) { + item[COLUMN_UNREAD]->setIcon(QIcon(":/images/message-state-unread.png")); + item[COLUMN_UNREAD]->setText("1"); + } else { + item[COLUMN_UNREAD]->setIcon(QIcon(":/images/message-state-read.png")); + item[COLUMN_UNREAD]->setText("0"); + } + + // set font + for (int i = 0; i < COLUMN_COUNT; i++) { + QFont qf = item[i]->font(); + qf.setBold(isNew); + item[i]->setFont(qf); + } + + item[COLUMN_DATA]->setData(isNew, ROLE_UNREAD); +} + +void MessagesDialog::insertMessages() +{ + if (m_nLockUpdate) { + return; + } + + std::cerr <<"MessagesDialog::insertMessages called"; + + std::list msgList; + std::list::const_iterator it; + MessageInfo msgInfo; + bool bGotInfo; + QString text; + + rsMsgs -> getMessageSummaries(msgList); + + std::cerr << "MessagesDialog::insertMessages()" << std::endl; + + int nFilterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); + + /* check the mode we are in */ + unsigned int msgbox = 0; + bool isTrash = false; + bool doFill = true; + int quickViewType = 0; + uint32_t quickViewId = 0; + QString boxText; + QIcon boxIcon; + QString placeholderText; + + switch (m_eListMode) { + case LIST_NOTHING: + doFill = false; + break; + + case LIST_BOX: + { + QListWidgetItem *item = ui.listWidget->currentItem(); + if (item) { + boxIcon = item->icon(); + } + + int listrow = ui.listWidget->currentRow(); + + switch (listrow) { + case ROW_INBOX: + msgbox = RS_MSG_INBOX; + boxText = tr("Inbox"); + break; + case ROW_OUTBOX: + msgbox = RS_MSG_OUTBOX; + boxText = tr("Outbox"); + break; + case ROW_DRAFTBOX: + msgbox = RS_MSG_DRAFTBOX; + boxText = tr("Drafts"); + break; + case ROW_SENTBOX: + msgbox = RS_MSG_SENTBOX; + boxText = tr("Sent"); + break; + case ROW_TRASHBOX: + isTrash = true; + boxText = tr("Trash"); + break; + default: + doFill = false; + } + } + break; + + case LIST_QUICKVIEW: + { + QListWidgetItem *item = ui.quickViewWidget->currentItem(); + if (item) { + quickViewType = item->data(ROLE_QUICKVIEW_TYPE).toInt(); + quickViewId = item->data(ROLE_QUICKVIEW_ID).toInt(); + + boxText = item->text(); + boxIcon = item->icon(); + + switch (quickViewType) { + case QUICKVIEW_TYPE_NOTHING: + doFill = false; + break; + case QUICKVIEW_TYPE_STATIC: + switch (quickViewId) { + case QUICKVIEW_STATIC_ID_STARRED: + placeholderText = tr("No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message."); + break; + } + break; + case QUICKVIEW_TYPE_TAG: + break; + } + } else { + doFill = false; + } + } + break; + + default: + doFill = false; + } + + ui.tabWidget->setTabText (0, boxText); + ui.tabWidget->setTabIcon (0, boxIcon); + ui.messagestreeView->setPlaceholderText(placeholderText); + + if (msgbox == RS_MSG_INBOX) { + MessagesModel->setHeaderData(COLUMN_FROM, Qt::Horizontal, tr("From")); + MessagesModel->setHeaderData(COLUMN_FROM, Qt::Horizontal, tr("Click to sort by from"), Qt::ToolTipRole); + } else { + MessagesModel->setHeaderData(COLUMN_FROM, Qt::Horizontal, tr("To")); + MessagesModel->setHeaderData(COLUMN_FROM, Qt::Horizontal, tr("Click to sort by to"), Qt::ToolTipRole); + } + + if (doFill) { + MsgTagType Tags; + rsMsgs->getMessageTagTypes(Tags); + + /* search messages */ + std::list msgToShow; + for(it = msgList.begin(); it != msgList.end(); it++) { + if (m_eListMode == LIST_BOX) { + if (isTrash) { + if ((it->msgflags & RS_MSG_TRASH) == 0) { + continue; + } + } else { + if (it->msgflags & RS_MSG_TRASH) { + continue; + } + if ((it->msgflags & RS_MSG_BOXMASK) != msgbox) { + continue; + } + } + } else if (m_eListMode == LIST_QUICKVIEW && quickViewType == QUICKVIEW_TYPE_TAG) { + MsgTagInfo tagInfo; + rsMsgs->getMessageTag(it->msgId, tagInfo); + if (std::find(tagInfo.tagIds.begin(), tagInfo.tagIds.end(), quickViewId) == tagInfo.tagIds.end()) { + continue; + } + } else if (m_eListMode == LIST_QUICKVIEW && quickViewType == QUICKVIEW_TYPE_STATIC) { + if ((it->msgflags & RS_MSG_STAR) == 0) { + continue; + } + } else { + continue; + } + + msgToShow.push_back(*it); + } + + /* remove old items */ + int nRowCount = MessagesModel->rowCount(); + int nRow = 0; + for (nRow = 0; nRow < nRowCount; ) { + std::string msgIdFromRow = MessagesModel->item(nRow, COLUMN_DATA)->data(ROLE_MSGID).toString().toStdString(); + for(it = msgToShow.begin(); it != msgToShow.end(); it++) { + if (it->msgId == msgIdFromRow) { + break; + } + } + + if (it == msgToShow.end ()) { + MessagesModel->removeRow (nRow); + nRowCount = MessagesModel->rowCount(); + } else { + nRow++; + } + } + + for(it = msgToShow.begin(); it != msgToShow.end(); it++) + { + /* check the message flags, to decide which + * group it should go in... + * + * InBox + * OutBox + * Drafts + * Sent + * + * FLAGS = OUTGOING. + * -> Outbox/Drafts/Sent + * + SENT -> Sent + * + IN_PROGRESS -> Draft. + * + nuffing -> Outbox. + * FLAGS = INCOMING = (!OUTGOING) + * -> + NEW -> Bold. + * + */ + + bGotInfo = false; + msgInfo = MessageInfo(); // clear + + // search exisisting items + nRowCount = MessagesModel->rowCount(); + for (nRow = 0; nRow < nRowCount; nRow++) { + if (it->msgId == MessagesModel->item(nRow, COLUMN_DATA)->data(ROLE_MSGID).toString().toStdString()) { + break; + } + } + + /* make a widget per friend */ + + QStandardItem *item [COLUMN_COUNT]; + + bool bInsert = false; + + if (nRow < nRowCount) { + for (int i = 0; i < COLUMN_COUNT; i++) { + item[i] = MessagesModel->item(nRow, i); + } + } else { + for (int i = 0; i < COLUMN_COUNT; i++) { + item[i] = new QStandardItem(); + } + bInsert = true; + } + + //set this false if you want to expand on double click + for (int i = 0; i < COLUMN_COUNT; i++) { + item[i]->setEditable(false); + } + + /* So Text should be: + * (1) Msg / Broadcast + * (1b) Person / Channel Name + * (2) Rank + * (3) Date + * (4) Title + * (5) Msg + * (6) File Count + * (7) File Total + */ + + QString dateString; + // Date First.... (for sorting) + { + QDateTime qdatetime; + qdatetime.setTime_t(it->ts); + + // add string to all data + dateString = qdatetime.toString("_yyyyMMdd_hhmmss"); + + //if the mail is on same date show only time. + if (qdatetime.daysTo(QDateTime::currentDateTime()) == 0) + { + QTime qtime = qdatetime.time(); + QVariant varTime(qtime); + item[COLUMN_DATE]->setData(varTime, Qt::DisplayRole); + } + else + { + QVariant varDateTime(qdatetime); + item[COLUMN_DATE]->setData(varDateTime, Qt::DisplayRole); + } + // for sorting + item[COLUMN_DATE]->setData(qdatetime, ROLE_SORT); + } + + // From .... + { + if (msgbox == RS_MSG_INBOX || msgbox == RS_MSG_OUTBOX) { + text = QString::fromStdString(rsPeers->getPeerName(it->srcId)); + } else { + if (bGotInfo || rsMsgs->getMessage(it->msgId, msgInfo)) { + bGotInfo = true; + + text.clear(); + + std::list::const_iterator pit; + for (pit = msgInfo.msgto.begin(); pit != msgInfo.msgto.end(); pit++) + { + if (text.isEmpty() == false) { + text += ", "; + } + + std::string peerName = rsPeers->getPeerName(*pit); + if (peerName.empty()) { + text += PeerDefs::rsid("", *pit); + } else { + text += QString::fromStdString(peerName); + } + } + } else { + std::cerr << "MessagesDialog::insertMsgTxtAndFiles() Couldn't find Msg" << std::endl; + } + } + item[COLUMN_FROM]->setText(text); + item[COLUMN_FROM]->setData(text + dateString, ROLE_SORT); + } + + // Subject + text = QString::fromStdWString(it->title); + item[COLUMN_SUBJECT]->setText(text); + item[COLUMN_SUBJECT]->setData(text + dateString, ROLE_SORT); + + // internal data + QString msgId = QString::fromStdString(it->msgId); + item[COLUMN_DATA]->setData(QString::fromStdString(it->srcId), ROLE_SRCID); + item[COLUMN_DATA]->setData(msgId, ROLE_MSGID); + item[COLUMN_DATA]->setData(it->msgflags, ROLE_MSGFLAGS); + + // Init icon and font + InitIconAndFont(item); + + // Tags + MsgTagInfo tagInfo; + rsMsgs->getMessageTag(it->msgId, tagInfo); + + text.clear(); + + // build tag names + std::map >::iterator Tag; + for (std::list::iterator tagId = tagInfo.tagIds.begin(); tagId != tagInfo.tagIds.end(); tagId++) { + if (text.isEmpty() == false) { + text += ","; + } + Tag = Tags.types.find(*tagId); + if (Tag != Tags.types.end()) { + text += TagDefs::name(Tag->first, Tag->second.first); + } else { + // clean tagId + rsMsgs->setMessageTag(it->msgId, *tagId, false); + } + } + item[COLUMN_TAGS]->setText(text); + + // set color + QBrush Brush; // standard + if (tagInfo.tagIds.size()) { + Tag = Tags.types.find(tagInfo.tagIds.front()); + if (Tag != Tags.types.end()) { + Brush = QBrush(Tag->second.second); + } else { + // clean tagId + rsMsgs->setMessageTag(it->msgId, tagInfo.tagIds.front(), false); + } + } + for (int i = 0; i < COLUMN_COUNT; i++) { + item[i]->setForeground(Brush); + } + + // No of Files. + { + item[COLUMN_ATTACHEMENTS] -> setText(QString::number(it -> count)); + item[COLUMN_ATTACHEMENTS] -> setData(item[COLUMN_ATTACHEMENTS]->text() + dateString, ROLE_SORT); + item[COLUMN_ATTACHEMENTS] -> setTextAlignment(Qt::AlignHCenter); + } + + if (nFilterColumn == COLUMN_CONTENT) { + // need content for filter + if (bGotInfo || rsMsgs->getMessage(it->msgId, msgInfo)) { + bGotInfo = true; + QTextDocument doc; + doc.setHtml(QString::fromStdWString(msgInfo.msg)); + item[COLUMN_CONTENT]->setText(doc.toPlainText().replace(QString("\n"), QString(" "))); + } else { + std::cerr << "MessagesDialog::insertMsgTxtAndFiles() Couldn't find Msg" << std::endl; + item[COLUMN_CONTENT]->setText(""); + } + } + + if (bInsert) { + /* add to the list */ + QList itemList; + for (int i = 0; i < COLUMN_COUNT; i++) { + itemList.append(item[i]); + } + MessagesModel->appendRow(itemList); + } + } + } else { + MessagesModel->removeRows (0, MessagesModel->rowCount()); + } + + ui.messagestreeView->showColumn(COLUMN_ATTACHEMENTS); + ui.messagestreeView->showColumn(COLUMN_SUBJECT); + ui.messagestreeView->showColumn(COLUMN_UNREAD); + ui.messagestreeView->showColumn(COLUMN_FROM); + ui.messagestreeView->showColumn(COLUMN_DATE); + ui.messagestreeView->showColumn(COLUMN_TAGS); + ui.messagestreeView->hideColumn(COLUMN_CONTENT); + + updateMessageSummaryList(); +} + +// current row in messagestreeView has changed +void MessagesDialog::currentChanged(const QModelIndex &index ) +{ + timer->stop(); + timerIndex = index; + timer->start(); +} + +// click in messagestreeView +void MessagesDialog::clicked(const QModelIndex &index ) +{ + if (index.isValid() == false) { + return; + } + + switch (index.column()) { + case COLUMN_UNREAD: + { + int mappedRow = proxyModel->mapToSource(index).row(); + + QList Rows; + Rows.append(mappedRow); + setMsgAsReadUnread(Rows, !isMessageRead(mappedRow)); + insertMsgTxtAndFiles(index, false); + updateMessageSummaryList(); + return; + } + case COLUMN_STAR: + { + int mappedRow = proxyModel->mapToSource(index).row(); + + QList Rows; + Rows.append(mappedRow); + setMsgStar(Rows, !hasMessageStar(mappedRow)); + return; + } + } + + timer->stop(); + timerIndex = index; + // show current message directly + updateCurrentMessage(); +} + +// double click in messagestreeView +void MessagesDialog::doubleClicked(const QModelIndex &index) +{ + /* activate row */ + clicked (index); + + std::string cid; + std::string mid; + + if(!getCurrentMsg(cid, mid)) + return ; + + MessageInfo msgInfo; + if (!rsMsgs->getMessage(mid, msgInfo)) { + return; + } + + if ((msgInfo.msgflags & RS_MSG_BOXMASK) == RS_MSG_DRAFTBOX) { + editmessage(); + return; + } + + /* edit message */ + switch (Settings->getMsgOpen()) { + case RshareSettings::MSG_OPEN_TAB: + openAsTab(); + break; + case RshareSettings::MSG_OPEN_WINDOW: + openAsWindow(); + break; + } +} + +// show current message directly +void MessagesDialog::updateCurrentMessage() +{ + timer->stop(); + insertMsgTxtAndFiles(timerIndex); +} + +void MessagesDialog::setMsgAsReadUnread(const QList &Rows, bool read) +{ + LockUpdate Lock (this, false); + + for (int nRow = 0; nRow < Rows.size(); nRow++) { + QStandardItem* item[COLUMN_COUNT]; + for(int nCol = 0; nCol < COLUMN_COUNT; nCol++) + { + item[nCol] = MessagesModel->item(Rows [nRow], nCol); + } + + std::string mid = item[COLUMN_DATA]->data(ROLE_MSGID).toString().toStdString(); + + if (rsMsgs->MessageRead(mid, !read)) { + int msgFlag = item[COLUMN_DATA]->data(ROLE_MSGFLAGS).toInt(); + msgFlag &= ~RS_MSG_NEW; + + if (read) { + msgFlag &= ~RS_MSG_UNREAD_BY_USER; + } else { + msgFlag |= RS_MSG_UNREAD_BY_USER; + } + + item[COLUMN_DATA]->setData(msgFlag, ROLE_MSGFLAGS); + + InitIconAndFont(item); + } + } + + // LockUpdate +} + +void MessagesDialog::markAsRead() +{ + QList RowsUnread; + getSelectedMsgCount (NULL, NULL, &RowsUnread, NULL); + + setMsgAsReadUnread (RowsUnread, true); + updateMessageSummaryList(); +} + +void MessagesDialog::markAsUnread() +{ + QList RowsRead; + getSelectedMsgCount (NULL, &RowsRead, NULL, NULL); + + setMsgAsReadUnread (RowsRead, false); + updateMessageSummaryList(); +} + +void MessagesDialog::markWithStar(bool checked) +{ + QList Rows; + getSelectedMsgCount (&Rows, NULL, NULL, NULL); + + setMsgStar(Rows, checked); +} + +void MessagesDialog::setMsgStar(const QList &Rows, bool star) +{ + LockUpdate Lock (this, false); + + for (int nRow = 0; nRow < Rows.size(); nRow++) { + QStandardItem* item[COLUMN_COUNT]; + for(int nCol = 0; nCol < COLUMN_COUNT; nCol++) + { + item[nCol] = MessagesModel->item(Rows [nRow], nCol); + } + + std::string mid = item[COLUMN_DATA]->data(ROLE_MSGID).toString().toStdString(); + + if (rsMsgs->MessageStar(mid, star)) { + int msgFlag = item[COLUMN_DATA]->data(ROLE_MSGFLAGS).toInt(); + msgFlag &= ~RS_MSG_STAR; + + if (star) { + msgFlag |= RS_MSG_STAR; + } else { + msgFlag &= ~RS_MSG_STAR; + } + + item[COLUMN_DATA]->setData(msgFlag, ROLE_MSGFLAGS); + + InitIconAndFont(item); + + Lock.setUpdate(true); + } + } + + // LockUpdate +} + +void MessagesDialog::insertMsgTxtAndFiles(QModelIndex Index, bool bSetToRead) +{ + std::cerr << "MessagesDialog::insertMsgTxtAndFiles()" << std::endl; + + /* get its Ids */ + std::string cid; + std::string mid; + + QModelIndex currentIndex = proxyModel->mapToSource(Index); + if (currentIndex.isValid() == false) { + mCurrMsgId.clear(); + msgWidget->fill(mCurrMsgId); + updateInterface(); + return; + } + + QStandardItem *item = MessagesModel->item(currentIndex.row(),COLUMN_DATA); + if (item == NULL) { + mCurrMsgId.clear(); + msgWidget->fill(mCurrMsgId); + updateInterface(); + return; + } + mid = item->data(ROLE_MSGID).toString().toStdString(); + + int nCount = getSelectedMsgCount (NULL, NULL, NULL, NULL); + if (nCount == 1) { + ui.actionSaveAs->setEnabled(true); + ui.actionPrintPreview->setEnabled(true); + ui.actionPrint->setEnabled(true); + } else { + ui.actionSaveAs->setDisabled(true); + ui.actionPrintPreview->setDisabled(true); + ui.actionPrint->setDisabled(true); + } + + if (mCurrMsgId == mid) { + // message doesn't changed + return; + } + + /* Save the Data.... for later */ + + mCurrMsgId = mid; + + MessageInfo msgInfo; + if (!rsMsgs -> getMessage(mid, msgInfo)) { + std::cerr << "MessagesDialog::insertMsgTxtAndFiles() Couldn't find Msg" << std::endl; + return; + } + + QList Rows; + Rows.append(currentIndex.row()); + + bool bSetToReadOnActive = Settings->getMsgSetToReadOnActivate(); + + if (msgInfo.msgflags & RS_MSG_NEW) { + // set always to read or unread + if (bSetToReadOnActive == false || bSetToRead == false) { + // set locally to unread + setMsgAsReadUnread(Rows, false); + } else { + setMsgAsReadUnread(Rows, true); + } + updateMessageSummaryList(); + } else { + if ((msgInfo.msgflags & RS_MSG_UNREAD_BY_USER) && bSetToRead && bSetToReadOnActive) { + // set to read + setMsgAsReadUnread(Rows, true); + updateMessageSummaryList(); + } + } + + msgWidget->fill(mCurrMsgId); + updateInterface(); +} + +bool MessagesDialog::getCurrentMsg(std::string &cid, std::string &mid) +{ + QModelIndex currentIndex = ui.messagestreeView->currentIndex(); + currentIndex = proxyModel->mapToSource(currentIndex); + int rowSelected = -1; + + /* get its Ids */ + if (currentIndex.isValid() == false) + { + //If no message is selected. assume first message is selected. + if(MessagesModel->rowCount() == 0) + { + return false; + } + else + { + rowSelected = 0; + } + } + else + { + rowSelected = currentIndex.row(); + } + + QStandardItem *item = MessagesModel->item(rowSelected,COLUMN_DATA); + if (item == NULL) { + return false; + } + cid = item->data(ROLE_SRCID).toString().toStdString(); + mid = item->data(ROLE_MSGID).toString().toStdString(); + return true; +} + +void MessagesDialog::removemessage() +{ + LockUpdate Lock (this, true); + + QList selectedIndexList= ui.messagestreeView->selectionModel() -> selectedIndexes (); + QList rowList; + QModelIndex selectedIndex; + + for(QList::iterator it = selectedIndexList.begin(); it != selectedIndexList.end(); it++) { + selectedIndex = proxyModel->mapToSource(*it); + int row = selectedIndex.row(); + if (rowList.contains(row) == false) { + rowList.append(row); + } + } + + bool bDelete = false; + int listrow = ui.listWidget->currentRow(); + if (listrow == ROW_TRASHBOX) { + bDelete = true; + } else { + if (QApplication::keyboardModifiers() & Qt::ShiftModifier) { + bDelete = true; + } + } + + for(QList::const_iterator it1 = rowList.begin(); it1 != rowList.end(); it1++) { + QStandardItem *pItem = MessagesModel->item((*it1), COLUMN_DATA); + if (pItem) { + QString mid = pItem->data(ROLE_MSGID).toString(); + + // close tab showing this message +// closeTab(mid.toStdString()); + + if (bDelete) { + rsMsgs->MessageDelete(mid.toStdString()); + } else { + rsMsgs->MessageToTrash(mid.toStdString(), true); + } + } + } + + // LockUpdate -> insertMessages(); +} + +void MessagesDialog::undeletemessage() +{ + LockUpdate Lock (this, true); + + QList Rows; + getSelectedMsgCount (&Rows, NULL, NULL, NULL); + for (int nRow = 0; nRow < Rows.size(); nRow++) { + QString mid = MessagesModel->item (Rows [nRow], COLUMN_DATA)->data(ROLE_MSGID).toString(); + rsMsgs->MessageToTrash(mid.toStdString(), false); + } + + // LockUpdate -> insertMessages(); +} + +void MessagesDialog::setToolbarButtonStyle(Qt::ToolButtonStyle style) +{ + ui.newmessageButton->setToolButtonStyle(style); + ui.removemessageButton->setToolButtonStyle(style); + ui.replymessageButton->setToolButtonStyle(style); + ui.replyallmessageButton->setToolButtonStyle(style); + ui.forwardmessageButton->setToolButtonStyle(style); + ui.tagButton->setToolButtonStyle(style); + ui.printbutton->setToolButtonStyle(style); + ui.viewtoolButton->setToolButtonStyle(style); +} + +void MessagesDialog::buttonStyle() +{ + setToolbarButtonStyle((Qt::ToolButtonStyle) dynamic_cast(sender())->data().toInt()); +} + +void MessagesDialog::filterRegExpChanged() +{ + QRegExp regExp(ui.filterPatternLineEdit->text(), Qt::CaseInsensitive , QRegExp::FixedString); + proxyModel->setFilterRegExp(regExp); + + QString text = ui.filterPatternLineEdit->text(); + + if (text.isEmpty()) + { + ui.clearButton->hide(); + } + else + { + ui.clearButton->show(); + } +} + +void MessagesDialog::filterColumnChanged() +{ + if (m_bProcessSettings) { + return; + } + + int nFilterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); + if (nFilterColumn == COLUMN_CONTENT) { + // need content ... refill + insertMessages(); + } + proxyModel->setFilterKeyColumn(nFilterColumn); + + // save index + Settings->setValueToGroup("MessageDialog", "filterColumn", nFilterColumn); +} + +void MessagesDialog::updateMessageSummaryList() +{ + unsigned int newInboxCount = 0; + unsigned int newOutboxCount = 0; + unsigned int newDraftCount = 0; + unsigned int newSentboxCount = 0; + unsigned int inboxCount = 0; + unsigned int trashboxCount = 0; + unsigned int starredCount = 0; + + /* calculating the new messages */ +// rsMsgs->getMessageCount (&inboxCount, &newInboxCount, &newOutboxCount, &newDraftCount, &newSentboxCount); + + std::list msgList; + std::list::const_iterator it; + + rsMsgs->getMessageSummaries(msgList); + + QMap tagCount; + + /* calculating the new messages */ + for (it = msgList.begin(); it != msgList.end(); it++) { + /* calcluate tag count */ + MsgTagInfo tagInfo; + rsMsgs->getMessageTag(it->msgId, tagInfo); + for (std::list::iterator tagId = tagInfo.tagIds.begin(); tagId != tagInfo.tagIds.end(); tagId++) { + int nCount = tagCount [*tagId]; + nCount++; + tagCount [*tagId] = nCount; + } + + if (it->msgflags & RS_MSG_STAR) { + starredCount++; + } + + /* calculate box */ + if (it->msgflags & RS_MSG_TRASH) { + trashboxCount++; + continue; + } + + switch (it->msgflags & RS_MSG_BOXMASK) { + case RS_MSG_INBOX: + inboxCount++; + if (it->msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER)) { + newInboxCount++; + } + break; + case RS_MSG_OUTBOX: + newOutboxCount++; + break; + case RS_MSG_DRAFTBOX: + newDraftCount++; + break; + case RS_MSG_SENTBOX: + newSentboxCount++; + break; + } + } + + + int listrow = ui.listWidget->currentRow(); + QString textTotal; + + switch (listrow) + { + case ROW_INBOX: + textTotal = tr("Total:") + " " + QString::number(inboxCount); + ui.total_label->setText(textTotal); + break; + case ROW_OUTBOX: + textTotal = tr("Total:") + " " + QString::number(newOutboxCount); + ui.total_label->setText(textTotal); + break; + case ROW_DRAFTBOX: + textTotal = tr("Total:") + " " + QString::number(newDraftCount); + ui.total_label->setText(textTotal); + break; + case ROW_SENTBOX: + textTotal = tr("Total:") + " " + QString::number(newSentboxCount); + ui.total_label->setText(textTotal); + break; + case ROW_TRASHBOX: + textTotal = tr("Total:") + " " + QString::number(trashboxCount); + ui.total_label->setText(textTotal); + break; + } + + + QString textItem; + /*updating the labels in leftcolumn*/ + + //QList QListWidget::findItems ( const QString & text, Qt::MatchFlags flags ) const + QListWidgetItem* item = ui.listWidget->item(ROW_INBOX); + if (newInboxCount != 0) + { + textItem = tr("Inbox") + " (" + QString::number(newInboxCount)+")"; + item->setText(textItem); + QFont qf = item->font(); + qf.setBold(true); + item->setFont(qf); + item->setIcon(QIcon(":/images/folder-inbox-new.png")); + item->setForeground(QBrush(QColor(49, 106, 197))); + } + else + { + textItem = tr("Inbox"); + item->setText(textItem); + QFont qf = item->font(); + qf.setBold(false); + item->setFont(qf); + item->setIcon(QIcon(":/images/folder-inbox.png")); + item->setForeground(QBrush(QColor(0, 0, 0))); + } + + //QList QListWidget::findItems ( const QString & text, Qt::MatchFlags flags ) const + item = ui.listWidget->item(ROW_OUTBOX); + if (newOutboxCount != 0) + { + textItem = tr("Outbox") + " (" + QString::number(newOutboxCount)+")"; + item->setText(textItem); + QFont qf = item->font(); + qf.setBold(true); + item->setFont(qf); + } + else + { + textItem = tr("Outbox"); + item->setText(textItem); + QFont qf = item->font(); + qf.setBold(false); + item->setFont(qf); + + } + + //QList QListWidget::findItems ( const QString & text, Qt::MatchFlags flags ) const + item = ui.listWidget->item(ROW_DRAFTBOX); + if (newDraftCount != 0) + { + textItem = tr("Drafts") + " (" + QString::number(newDraftCount)+")"; + item->setText(textItem); + QFont qf = item->font(); + qf.setBold(true); + item->setFont(qf); + } + else + { + textItem = tr("Drafts"); + item->setText(textItem); + QFont qf = item->font(); + qf.setBold(false); + item->setFont(qf); + + } + + item = ui.listWidget->item(ROW_TRASHBOX); + if (trashboxCount != 0) + { + textItem = tr("Trash") + " (" + QString::number(trashboxCount)+")"; + item->setText(textItem); + } + else + { + textItem = tr("Trash"); + item->setText(textItem); + } + + /* set tag counts */ + int rowCount = ui.quickViewWidget->count(); + for (int row = 0; row < rowCount; row++) { + QListWidgetItem *item = ui.quickViewWidget->item(row); + switch (item->data(ROLE_QUICKVIEW_TYPE).toInt()) { + case QUICKVIEW_TYPE_TAG: + { + int count = tagCount[item->data(ROLE_QUICKVIEW_ID).toInt()]; + + QString text = item->data(ROLE_QUICKVIEW_TEXT).toString(); + if (count) { + text += " (" + QString::number(count) + ")"; + } + + item->setText(text); + } + break; + case QUICKVIEW_TYPE_STATIC: + { + QString text = item->data(ROLE_QUICKVIEW_TEXT).toString(); + switch (item->data(ROLE_QUICKVIEW_ID).toInt()) { + case QUICKVIEW_STATIC_ID_STARRED: + text += " (" + QString::number(starredCount) + ")"; + break; + } + + item->setText(text); + } + break; + } + } +} + +/** clear Filter **/ +void MessagesDialog::clearFilter() +{ + ui.filterPatternLineEdit->clear(); + ui.filterPatternLineEdit->setFocus(); +} + +void MessagesDialog::tagAboutToShow() +{ + TagsMenu *menu = dynamic_cast(ui.tagButton->menu()); + if (menu == NULL) { + return; + } + + // activate actions from the first selected row + MsgTagInfo tagInfo; + + QList rows; + getSelectedMsgCount (&rows, NULL, NULL, NULL); + + if (rows.size()) { + QStandardItem* item = MessagesModel->item(rows [0], COLUMN_DATA); + std::string msgId = item->data(ROLE_MSGID).toString().toStdString(); + + rsMsgs->getMessageTag(msgId, tagInfo); + } + + menu->activateActions(tagInfo.tagIds); +} + +void MessagesDialog::tagRemoveAll() +{ + LockUpdate Lock (this, false); + + QList rows; + getSelectedMsgCount (&rows, NULL, NULL, NULL); + for (int row = 0; row < rows.size(); row++) { + QStandardItem* item = MessagesModel->item(rows [row], COLUMN_DATA); + std::string msgId = item->data(ROLE_MSGID).toString().toStdString(); + + rsMsgs->setMessageTag(msgId, 0, false); + Lock.setUpdate(true); + } + + // LockUpdate -> insertMessages(); +} + +void MessagesDialog::tagSet(int tagId, bool set) +{ + if (tagId == 0) { + return; + } + + LockUpdate Lock (this, false); + + QList rows; + getSelectedMsgCount (&rows, NULL, NULL, NULL); + for (int row = 0; row < rows.size(); row++) { + QStandardItem* item = MessagesModel->item(rows [row], COLUMN_DATA); + std::string msgId = item->data(ROLE_MSGID).toString().toStdString(); + + if (rsMsgs->setMessageTag(msgId, tagId, set)) { + Lock.setUpdate(true); + } + } + + // LockUpdate -> insertMessages(); +} + +void MessagesDialog::emptyTrash() +{ + LockUpdate Lock (this, true); + + std::list msgList; + rsMsgs->getMessageSummaries(msgList); + + std::list::const_iterator it; + for (it = msgList.begin(); it != msgList.end(); it++) { + if (it->msgflags & RS_MSG_TRASH) { + rsMsgs->MessageDelete(it->msgId); + } + } + + // LockUpdate -> insertMessages(); +} + +void MessagesDialog::tabChanged(int tab) +{ + connectActions(); + updateInterface(); +} + +void MessagesDialog::tabCloseRequested(int tab) +{ + if (tab == 0) { + return; + } + + QWidget *widget = ui.tabWidget->widget(tab); + + if (widget) { + widget->deleteLater(); + } +} + +void MessagesDialog::closeTab(const std::string &msgId) +{ + QList msgWidgets; + + for (int tab = 1; tab < ui.tabWidget->count(); tab++) { + MessageWidget *msgWidget = dynamic_cast(ui.tabWidget->widget(tab)); + if (msgWidget && msgWidget->msgId() == msgId) { + msgWidgets.append(msgWidget); + } + } + qDeleteAll(msgWidgets); +} + +void MessagesDialog::connectActions() +{ + int tab = ui.tabWidget->currentIndex(); + + MessageWidget *msg; + if (tab == 0) { + msg = msgWidget; + } else { + msg = dynamic_cast(ui.tabWidget->widget(tab)); + } + + ui.replymessageButton->disconnect(); + ui.replyallmessageButton->disconnect(); + ui.forwardmessageButton->disconnect(); + ui.printbutton->disconnect(); + ui.actionPrint->disconnect(); + ui.actionPrintPreview->disconnect(); + ui.actionSaveAs->disconnect(); + ui.removemessageButton->disconnect(); + + ui.actionReply->disconnect(); + ui.actionReplyAll->disconnect(); + ui.actionForward->disconnect(); + + if (msgWidget) { + // connect actions + msg->connectAction(MessageWidget::ACTION_REPLY, ui.actionReply); + msg->connectAction(MessageWidget::ACTION_REPLY_ALL, ui.actionReplyAll); + msg->connectAction(MessageWidget::ACTION_FORWARD, ui.actionForward); + } + + if (msg) { + if (tab == 0) { + // connect with own slot to remove multiple messages + connect(ui.removemessageButton, SIGNAL(clicked()), this, SLOT(removemessage())); + } else { + msg->connectAction(MessageWidget::ACTION_REMOVE, ui.removemessageButton); + } + msg->connectAction(MessageWidget::ACTION_REPLY, ui.replymessageButton); + msg->connectAction(MessageWidget::ACTION_REPLY_ALL, ui.replyallmessageButton); + msg->connectAction(MessageWidget::ACTION_FORWARD, ui.forwardmessageButton); + msg->connectAction(MessageWidget::ACTION_PRINT, ui.printbutton); + msg->connectAction(MessageWidget::ACTION_PRINT, ui.actionPrint); + msg->connectAction(MessageWidget::ACTION_PRINT_PREVIEW, ui.actionPrintPreview); + msg->connectAction(MessageWidget::ACTION_SAVE_AS, ui.actionSaveAs); + } +} + +void MessagesDialog::updateInterface() +{ + int count = 0; + + int tab = ui.tabWidget->currentIndex(); + + if (tab == 0) { + count = getSelectedMsgCount(NULL, NULL, NULL, NULL); + } else { + MessageWidget *msg = dynamic_cast(ui.tabWidget->widget(tab)); + if (msg && msg->msgId().empty() == false) { + count = 1; + } + } + + ui.replymessageButton->setEnabled(count == 1); + ui.replyallmessageButton->setEnabled(count == 1); + ui.forwardmessageButton->setEnabled(count == 1); + ui.printbutton->setEnabled(count == 1); + ui.actionPrint->setEnabled(count == 1); + ui.actionPrintPreview->setEnabled(count == 1); + ui.actionSaveAs->setEnabled(count == 1); + ui.removemessageButton->setEnabled(count >= 1); + ui.tagButton->setEnabled(count >= 1); +} diff --git a/retroshare-gui/src/gui/MessagesDialog.h b/retroshare-gui/src/gui/MessagesDialog.h new file mode 100644 index 000000000..e9f552d41 --- /dev/null +++ b/retroshare-gui/src/gui/MessagesDialog.h @@ -0,0 +1,149 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _MESSAGESDIALOG_H +#define _MESSAGESDIALOG_H + +#include + +#include "mainpage.h" +#include "ui_MessagesDialog.h" + +class MessageWidget; + +class MessagesDialog : public MainPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + MessagesDialog(QWidget *parent = 0); + /** Default Destructor */ + ~MessagesDialog(); + +// replaced by shortcut +// virtual void keyPressEvent(QKeyEvent *) ; + +protected: + bool eventFilter(QObject *obj, QEvent *ev); + +public slots: + void insertMessages(); + void messagesTagsChanged(); + +private slots: + /** Create the context popup menu and it's submenus */ + void messageslistWidgetCostumPopupMenu( QPoint point ); + void folderlistWidgetCostumPopupMenu(QPoint); + + void changeBox(int newrow); + void changeQuickView(int newrow); + void updateCurrentMessage(); + void currentChanged(const QModelIndex&); + void clicked(const QModelIndex&); + void doubleClicked(const QModelIndex &); + + void newmessage(); + void openAsWindow(); + void openAsTab(); + void editmessage(); + + void removemessage(); + void undeletemessage(); + + void markAsRead(); + void markAsUnread(); + void markWithStar(bool checked); + + void emptyTrash(); + + void buttonStyle(); + + void filterRegExpChanged(); + void filterColumnChanged(); + + void clearFilter(); + void tagAboutToShow(); + void tagSet(int tagId, bool set); + void tagRemoveAll(); + + void tabChanged(int tab); + void tabCloseRequested(int tab); + + void updateInterface(); + +private: + class LockUpdate + { + public: + LockUpdate (MessagesDialog *pDialog, bool bUpdate); + ~LockUpdate (); + + void setUpdate(bool bUpdate); + + private: + MessagesDialog *m_pDialog; + bool m_bUpdate; + }; + + class QStandardItemModel *MessagesModel; + QSortFilterProxyModel *proxyModel; + + void connectActions(); + + void updateMessageSummaryList(); + void insertMsgTxtAndFiles(QModelIndex index = QModelIndex(), bool bSetToRead = true); + + bool getCurrentMsg(std::string &cid, std::string &mid); + void setMsgAsReadUnread(const QList &Rows, bool read); + void setMsgStar(const QList &Rows, bool mark); + + int getSelectedMsgCount (QList *pRows, QList *pRowsRead, QList *pRowsUnread, QList *pRowsStar); + bool isMessageRead(int nRow); + bool hasMessageStar(int nRow); + + void processSettings(bool load); + + void setToolbarButtonStyle(Qt::ToolButtonStyle style); + void fillQuickView(); + + void closeTab(const std::string &msgId); + + bool m_bProcessSettings; + bool inChange; + int m_nLockUpdate; // use with LockUpdate + + enum { LIST_NOTHING, LIST_BOX, LIST_QUICKVIEW } m_eListMode; + + std::string mCurrMsgId; + + // timer and index for showing message + QTimer *timer; + QModelIndex timerIndex; + + MessageWidget *msgWidget; + + /** Qt Designer generated object */ + Ui::MessagesDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/MessagesDialog.ui b/retroshare-gui/src/gui/MessagesDialog.ui new file mode 100644 index 000000000..55ae84421 --- /dev/null +++ b/retroshare-gui/src/gui/MessagesDialog.ui @@ -0,0 +1,1439 @@ + + + MessagesDialog + + + + 0 + 0 + 775 + 511 + + + + + 0 + 0 + + + + + 60 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::DefaultContextMenu + + + + 1 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 36 + + + + + 0 + 68 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 6 + + + + + + 0 + 0 + + + + + 167777 + 167777 + + + + Qt::NoFocus + + + New Message + + + + + + Compose + + + + :/images/folder-draft24.png:/images/folder-draft24.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777 + 16777 + + + + Qt::NoFocus + + + Reply to selected message + + + + + + Reply + + + + :/images/replymail-pressed.png:/images/replymail-pressed.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + + 0 + 0 + + + + + 16777 + 16777 + + + + Qt::NoFocus + + + Reply all to selected message + + + Reply all + + + + :/images/replymailall24-hover.png:/images/replymailall24-hover.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + + 0 + 0 + + + + + 16777 + 16777 + + + + Qt::NoFocus + + + Forward selected message + + + Foward + + + + :/images/mailforward24-hover.png:/images/mailforward24-hover.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + + 16777 + 16777 + + + + Qt::NoFocus + + + Remove selected message + + + + + + Delete + + + + :/images/deletemail24.png:/images/deletemail24.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777 + 16777 + + + + Qt::NoFocus + + + Print selected message + + + Print + + + + :/images/print24.png:/images/print24.png + + + + 24 + 24 + + + + QToolButton::MenuButtonPopup + + + Qt::ToolButtonIconOnly + + + true + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Display + + + + :/images/looknfeel.png:/images/looknfeel.png + + + + 24 + 24 + + + + QToolButton::MenuButtonPopup + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + + + + + + :/images/find-16.png + + + + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + Qt::NoFocus + + + Reset + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + + 0 + + + + Attachments + + + + + Subject + + + + + From + + + + + Date + + + + + Content + + + + + Tags + + + + + + + + Qt::NoFocus + + + Tags + + + Tags + + + + :/images/tag24.png:/images/tag24.png + + + + 24 + 24 + + + + QToolButton::MenuButtonPopup + + + true + + + + + + + + + + Qt::LeftToRight + + + true + + + + Main Tab + + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + + 160 + 16777215 + + + + QFrame#frame_2{border: none;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 160 + 16777215 + + + + + 0 + 0 + + + + + 9 + + + + Qt::CustomContextMenu + + + + + + 1 + + + 0 + + + false + + + QListView::Fixed + + + 0 + + + + 100 + 18 + + + + 0 + + + false + + + false + + + + Inbox + + + + :/images/folder-inbox.png:/images/folder-inbox.png + + + + + Outbox + + + + :/images/folder-outbox.png:/images/folder-outbox.png + + + + + Draft + + + + :/images/folder-draft.png:/images/folder-draft.png + + + + + Sent + + + + :/images/folder-sent.png:/images/folder-sent.png + + + + + Trash + + + + :/images/folder-trash.png:/images/folder-trash.png + + + + + + + + + 160 + 16777215 + + + + + 0 + 0 + + + + + + + + + 0 + 22 + + + + + 160 + 16777215 + + + + QToolButton#quickViewsButton{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + Quick View + + + + :/images/tag24.png:/images/tag24.png + + + true + + + true + + + Qt::ToolButtonTextBesideIcon + + + Qt::NoArrow + + + + + + + + 0 + 18 + + + + + 9 + + + + Total Inbox: + + + + + + + + 0 + 22 + + + + + 160 + 22 + + + + Qt::LeftToRight + + + QPushButton#Folders_Button{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); +border: 1px solid #CCCCCC; +text-align: left; +padding: 4px; +} + + + + + Folders + + + false + + + false + + + + + + + + Qt::Vertical + + + + Qt::Vertical + + + + + 9 + + + + Qt::CustomContextMenu + + + QAbstractItemView::ExtendedSelection + + + true + + + true + + + + + + + + + + + + + + + + + Print... + + + Print... + + + + + Print Preview + + + + + Buttons Icon Only + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + Buttons with Text + + + + + Buttons Text Under Icon + + + Set Text Under Icon + + + + + Save As... + + + + + + :/images/mail_reply.png:/images/mail_reply.png + + + Reply to Message + + + + + + :/images/mail_replyall.png:/images/mail_replyall.png + + + Reply to All + + + + + + :/images/mail_forward.png:/images/mail_forward.png + + + Forward Message + + + + + + RSTabWidget + QTabWidget +
    gui/common/RSTabWidget.h
    + 1 +
    + + RSTreeView + QTreeView +
    gui/common/RSTreeView.h
    +
    +
    + + newmessageButton + replymessageButton + listWidget + + + + + + + quickViewsButton + toggled(bool) + quickViewWidget + setVisible(bool) + + + 78 + 287 + + + 78 + 399 + + + + +
    diff --git a/retroshare-gui/src/gui/MessengerWindow.cpp b/retroshare-gui/src/gui/MessengerWindow.cpp new file mode 100644 index 000000000..101b1399b --- /dev/null +++ b/retroshare-gui/src/gui/MessengerWindow.cpp @@ -0,0 +1,1274 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include + +#include "common/vmessagebox.h" +#include "common/StatusDefs.h" + +#include +#include +#include +#include +#include + +#include "rshare.h" +#include "MessengerWindow.h" +#include "RsAutoUpdatePage.h" + +#ifndef MINIMAL_RSGUI +#include "MainWindow.h" +#include "chat/PopupChatDialog.h" +#include "msgs/MessageComposer.h" +#include "ShareManager.h" +#include "notifyqt.h" +#include "connect/ConnectFriendWizard.h" +#endif // MINIMAL_RSGUI +#include "FriendsDialog.h" +#include "connect/ConfCertDialog.h" +#include "util/PixmapMerging.h" +#include "LogoBar.h" +#include "util/Widget.h" +#include "settings/rsharesettings.h" +#include "common/RSTreeWidgetItem.h" + +#include "RetroShareLink.h" + +#include +#include +#include +#include + +/* Images for context menu icons */ +#define IMAGE_REMOVEFRIEND ":/images/removefriend16.png" +#define IMAGE_EXPIORTFRIEND ":/images/exportpeers_16x16.png" +#define IMAGE_CHAT ":/images/chat.png" +#define IMAGE_MSG ":/images/message-mail.png" +#define IMAGE_CONNECT ":/images/connect_friend.png" +#define IMAGE_PEERINFO ":/images/peerdetails_16x16.png" +#define IMAGE_AVAIBLE ":/images/user/identityavaiblecyan24.png" +#define IMAGE_CONNECT2 ":/images/reload24.png" +#define IMAGE_PASTELINK ":/images/pasterslink.png" + +#define COLUMN_COUNT 3 +#define COLUMN_NAME 0 +#define COLUMN_STATE 1 +#define COLUMN_INFO 2 + +#define COLUMN_DATA 0 // column for storing the userdata id + +#define ROLE_SORT Qt::UserRole +#define ROLE_ID Qt::UserRole + 1 + +/****** + * #define MSG_DEBUG 1 + *****/ + +MessengerWindow* MessengerWindow::_instance = NULL; +static std::set *expandedPeers = NULL; + +/*static*/ void MessengerWindow::showYourself () +{ + if (_instance == NULL) { + _instance = new MessengerWindow(); + } + + _instance->show(); + _instance->activateWindow(); +} + +MessengerWindow* MessengerWindow::getInstance() +{ + return _instance; +} + +void MessengerWindow::releaseInstance() +{ + if (_instance) { + delete _instance; + } + if (expandedPeers) { + /* delete saved expanded peers */ + delete(expandedPeers); + expandedPeers = NULL; + } +} + +/** Constructor */ +MessengerWindow::MessengerWindow(QWidget* parent, Qt::WFlags flags) + : RWindow("MessengerWindow", parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); +#ifdef MINIMAL_RSGUI + setAttribute (Qt::WA_QuitOnClose, true); +#endif // MINIMAL_RSGUI + + m_compareRole = new RSTreeWidgetItemCompareRole; + m_compareRole->setRole(COLUMN_NAME, ROLE_SORT); + + connect( ui.messengertreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( messengertreeWidgetCostumPopupMenu( QPoint ) ) ); +#ifndef MINIMAL_RSGUI + connect( ui.messengertreeWidget, SIGNAL(itemDoubleClicked ( QTreeWidgetItem *, int)), this, SLOT(chatfriend(QTreeWidgetItem *))); + + connect( ui.avatarButton, SIGNAL(clicked()), SLOT(getAvatar())); + connect( ui.shareButton, SIGNAL(clicked()), SLOT(openShareManager())); + connect( ui.addIMAccountButton, SIGNAL(clicked( bool ) ), this , SLOT( addFriend() ) ); +#endif // MINIMAL_RSGUI + connect( ui.actionHide_Offline_Friends, SIGNAL(triggered()), this, SLOT(insertPeers())); + connect( ui.actionSort_by_State, SIGNAL(triggered()), this, SLOT(insertPeers())); + connect(ui.clearButton, SIGNAL(clicked()), this, SLOT(clearFilter())); + + connect(ui.messagelineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(savestatusmessage())); + connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged())); + +#ifndef MINIMAL_RSGUI + connect(NotifyQt::getInstance(), SIGNAL(friendsChanged()), this, SLOT(updateMessengerDisplay())); + connect(NotifyQt::getInstance(), SIGNAL(ownAvatarChanged()), this, SLOT(updateAvatar())); + connect(NotifyQt::getInstance(), SIGNAL(ownStatusMessageChanged()), this, SLOT(loadmystatusmessage())); + connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(QString,int)), this, SLOT(updateOwnStatus(QString,int))); +#endif // MINIMAL_RSGUI + + timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(updateMessengerDisplay())); + timer->setInterval(1000); /* one second */ + timer->setSingleShot(true); + + /* to hide the header */ + ui.messengertreeWidget->header()->hide(); + + /* Set header resize modes and initial section sizes */ + ui.messengertreeWidget->setColumnCount(COLUMN_COUNT); + ui.messengertreeWidget->setColumnHidden ( COLUMN_INFO, true); + ui.messengertreeWidget->sortItems( COLUMN_NAME, Qt::AscendingOrder ); + + QHeaderView * _header = ui.messengertreeWidget->header () ; + _header->setResizeMode (COLUMN_NAME, QHeaderView::Stretch); + _header->setResizeMode (COLUMN_STATE, QHeaderView::Custom); + _header->setStretchLastSection(false); + + _header->resizeSection ( COLUMN_NAME, 200 ); + _header->resizeSection ( COLUMN_STATE, 42 ); + + //LogoBar + _rsLogoBarmessenger = NULL; + _rsLogoBarmessenger = new LogoBar(ui.logoframe); + Widget::createLayout(ui.logoframe)->addWidget(_rsLogoBarmessenger); + + ui.messagelineEdit->setMinimumWidth(20); + + itemFont = QFont("ARIAL", 10); + itemFont.setBold(true); + + displayMenu(); + + // load settings + processSettings(true); + + // add self nick + RsPeerDetails pd; + std::string ownId = rsPeers->getOwnId(); + if (rsPeers->getPeerDetails(ownId, pd)) { + /* calculate only once */ + m_nickName = QString::fromUtf8(pd.name.c_str()); +#ifdef MINIMAL_RSGUI + ui.statusButton->setText(m_nickName); +#endif + } + +#ifndef MINIMAL_RSGUI + /* Show nick and current state */ + StatusInfo statusInfo; + rsStatus->getOwnStatus(statusInfo); + updateOwnStatus(QString::fromStdString(ownId), statusInfo.status); + + MainWindow *pMainWindow = MainWindow::getInstance(); + if (pMainWindow) { + QMenu *pStatusMenu = new QMenu(); + pMainWindow->initializeStatusObject(pStatusMenu, true); + ui.statusButton->setMenu(pStatusMenu); + } + + updateAvatar(); + loadmystatusmessage(); +#endif // MINIMAL_RSGUI + + insertPeers(); + + ui.clearButton->hide(); + + updateMessengerDisplay(); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN +#endif +} + +MessengerWindow::~MessengerWindow () +{ + // save settings + processSettings(false); + +#ifndef MINIMAL_RSGUI + MainWindow *pMainWindow = MainWindow::getInstance(); + if (pMainWindow) { + pMainWindow->removeStatusObject(ui.statusButton); + } +#endif // MINIMAL_RSGUI + + delete(m_compareRole); + + _instance = NULL; +} + +void MessengerWindow::processSettings(bool bLoad) +{ + QHeaderView *header = ui.messengertreeWidget->header (); + + Settings->beginGroup(_name); + + if (bLoad) { + // load settings + + // state of messenger tree + header->restoreState(Settings->value("MessengerTree").toByteArray()); + + // state of actionHide_Offline_Friends + ui.actionHide_Offline_Friends->setChecked(Settings->value("hideOfflineFriends", false).toBool()); + + // state of actionSort_by_State + ui.actionSort_by_State->setChecked(Settings->value("sortByState", false).toBool()); + + // state of actionRoot_is_decorated + ui.actionRoot_is_decorated->setChecked(Settings->value("rootIsDecorated", true).toBool()); + on_actionRoot_is_decorated_activated(); + } else { + // save settings + + // state of messenger tree + Settings->setValue("MessengerTree", header->saveState()); + + // state of actionSort_by_State + Settings->setValue("sortByState", ui.actionSort_by_State->isChecked()); + + // state of actionHide_Offline_Friends + Settings->setValue("hideOfflineFriends", ui.actionHide_Offline_Friends->isChecked()); + + // state of actionRoot_is_decorated + Settings->setValue("rootIsDecorated", ui.actionRoot_is_decorated->isChecked()); + } + + Settings->endGroup(); +} + +void MessengerWindow::messengertreeWidgetCostumPopupMenu( QPoint point ) +{ + QTreeWidgetItem *c = getCurrentPeer(); + + QMenu contextMnu( this ); + + QAction* expandAll = new QAction(tr( "Expand all" ), &contextMnu ); + connect( expandAll , SIGNAL( triggered() ), ui.messengertreeWidget, SLOT (expandAll()) ); + + QAction* collapseAll = new QAction(tr( "Collapse all" ), &contextMnu ); + connect( collapseAll , SIGNAL( triggered() ), ui.messengertreeWidget, SLOT(collapseAll()) ); + +#ifndef MINIMAL_RSGUI + QAction* chatAct = new QAction(QIcon(IMAGE_CHAT), tr( "Chat" ), &contextMnu ); + if (c) { + connect( chatAct , SIGNAL( triggered() ), this, SLOT( chatfriendproxy() ) ); + } else { + chatAct->setDisabled(true); + } + + QAction* sendMessageAct = new QAction(QIcon(IMAGE_MSG), tr( "Message Friend" ), &contextMnu ); + if (c) { + connect( sendMessageAct , SIGNAL( triggered() ), this, SLOT( sendMessage() ) ); + } else { + sendMessageAct->setDisabled(true); + } +#endif // MINIMAL_RSGUI + + QAction* connectfriendAct = new QAction(QIcon(IMAGE_CONNECT), tr( "Connect To Friend" ), &contextMnu ); + if (c) { + connect( connectfriendAct , SIGNAL( triggered() ), this, SLOT( connectfriend() ) ); + } else { + connectfriendAct->setDisabled(true); + } + +#ifndef MINIMAL_RSGUI + QAction* configurefriendAct = new QAction(QIcon(IMAGE_PEERINFO), tr( "Peer Details" ), &contextMnu ); + if (c) { + connect( configurefriendAct , SIGNAL( triggered() ), this, SLOT( configurefriend() ) ); + } else { + configurefriendAct->setDisabled(true); + } + + QAction* recommendfriendAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Recomend this Friend to..." ), &contextMnu ); + if (c && c->type() == 0) { + connect( recommendfriendAct , SIGNAL( triggered() ), this, SLOT( recommendfriend() ) ); + } else { + recommendfriendAct->setDisabled(true); + } + + QAction* pastePersonAct = new QAction(QIcon(IMAGE_PASTELINK), tr( "Paste RetroShare Link" ), &contextMnu ); + if(!RSLinkClipboard::empty(RetroShareLink::TYPE_PERSON)) { + connect( pastePersonAct , SIGNAL( triggered() ), this, SLOT( pastePerson() ) ); + } else { + pastePersonAct->setDisabled(true); + } + + //QAction* profileviewAct = new QAction(QIcon(IMAGE_PEERINFO), tr( "Profile View" ), &contextMnu ); + //connect( profileviewAct , SIGNAL( triggered() ), this, SLOT( viewprofile() ) ); + + QAction* exportfriendAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Export Friend" ), &contextMnu ); + if (c) { + connect( exportfriendAct , SIGNAL( triggered() ), this, SLOT( exportfriend() ) ); + } else { + exportfriendAct->setDisabled(true); + } + + QAction* removefriendAct = new QAction(QIcon(IMAGE_REMOVEFRIEND), tr( "Deny Friend" ), &contextMnu ); + if (c) { + if (c->type() == 1) { + //this is a SSL key + removefriendAct->setText(tr( "Remove Friend Location")); + } + connect( removefriendAct , SIGNAL( triggered() ), this, SLOT( removefriend() ) ); + } else { + removefriendAct->setDisabled(true); + } +#endif // MINIMAL_RSGUI + + QWidget *widget = new QWidget(); + widget->setStyleSheet( ".QWidget{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #FEFEFE, stop:1 #E8E8E8); border: 1px solid #CCCCCC;}"); + + QHBoxLayout *hbox = new QHBoxLayout(&contextMnu); + hbox->setMargin(0); + hbox->setSpacing(6); + + QLabel *iconLabel = new QLabel(&contextMnu); + iconLabel->setPixmap(QPixmap(":/images/user/friends24.png")); + iconLabel->setMaximumSize( iconLabel->frameSize().height() + 24, 24 ); + hbox->addWidget(iconLabel); + + QLabel *textLabel; + textLabel = new QLabel( tr("RetroShare instance"), widget ); + if (c && c->type() == 0) { + //this is a GPG key + textLabel->setText(tr("GPG Key")); + } + + hbox->addWidget(textLabel); + + QSpacerItem *spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + hbox->addItem(spacerItem); + + widget->setLayout( hbox ); + + QWidgetAction *widgetAction = new QWidgetAction(this); + widgetAction->setDefaultWidget(widget); + + contextMnu.addAction( widgetAction); +#ifndef MINIMAL_RSGUI + contextMnu.addAction( chatAct); + contextMnu.addAction( sendMessageAct); + contextMnu.addAction( configurefriendAct); + //contextMnu.addAction( profileviewAct); + contextMnu.addAction( recommendfriendAct); +#endif // MINIMAL_RSGUI + contextMnu.addAction( connectfriendAct); +#ifndef MINIMAL_RSGUI + contextMnu.addAction(pastePersonAct); + contextMnu.addAction( removefriendAct); +#endif // MINIMAL_RSGUI + //contextMnu.addAction( exportfriendAct); + contextMnu.addSeparator(); + contextMnu.addAction( expandAll); + contextMnu.addAction( collapseAll); + contextMnu.exec(QCursor::pos()); +} + +void MessengerWindow::updateMessengerDisplay() +{ + if (RsAutoUpdatePage::eventsLocked() == false) { + insertPeers(); + } + + timer->start(); +} + +/* get the list of peers from the RsIface. */ +void MessengerWindow::insertPeers() +{ + std::list gpgFriends; + std::list::iterator it; + std::list statusInfo; +#ifndef MINIMAL_RSGUI + rsStatus->getStatusList(statusInfo); +#endif // MINIMAL_RSGUI + + if (!rsPeers) { + /* not ready yet! */ + std::cerr << "FriendsDialog::insertPeers() not ready yet : rsPeers unintialized." << std::endl; + return; + } + + std::list privateChatIds; +#ifndef MINIMAL_RSGUI + rsMsgs->getPrivateChatQueueIds(true, privateChatIds); +#endif // MINIMAL_RSGUI + + rsPeers->getGPGAcceptedList(gpgFriends); + + std::string sOwnId = rsPeers->getGPGOwnId(); + + //add own gpg id, if we have more than on location (ssl client) + std::list ownSslContacts; + rsPeers->getSSLChildListOfGPGId(sOwnId, ownSslContacts); + if (ownSslContacts.size() > 0) { + gpgFriends.push_back(sOwnId); + } + + /* get a link to the table */ + QTreeWidget *peertreeWidget = ui.messengertreeWidget; + + bool sortState = ui.actionSort_by_State->isChecked(); + bool hideOfflineFriends = ui.actionHide_Offline_Friends->isChecked(); + + //remove items that are not fiends anymore + int itemCount = peertreeWidget->topLevelItemCount(); + int index = 0; + while (index < itemCount) { + std::string gpg_widget_id = peertreeWidget->topLevelItem(index)->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + if (std::find(gpgFriends.begin(), gpgFriends.end(), gpg_widget_id) == gpgFriends.end()) { + delete (peertreeWidget->takeTopLevelItem(index)); + // count again + itemCount = peertreeWidget->topLevelItemCount(); + } else { + index++; + } + } + + //add the gpg friends + for(it = gpgFriends.begin(); it != gpgFriends.end(); it++) { + /* make a widget per friend */ + QTreeWidgetItem *gpg_item = NULL; + QTreeWidgetItem *gpg_item_loop = NULL; + QString gpgid = QString::fromStdString(*it); + itemCount = peertreeWidget->topLevelItemCount(); + for (int nIndex = 0; nIndex < itemCount; nIndex++) { + gpg_item_loop = peertreeWidget->topLevelItem(nIndex); + if (gpg_item_loop->data(COLUMN_DATA, ROLE_ID).toString() == gpgid) { + gpg_item = gpg_item_loop; + break; + } + } + + RsPeerDetails detail; + if ((!rsPeers->getPeerDetails(*it, detail) || !detail.accept_connection) + && detail.gpg_id != sOwnId) { + //don't accept anymore connection, remove from the view + delete (peertreeWidget->takeTopLevelItem(peertreeWidget->indexOfTopLevelItem(gpg_item))); + continue; + } + + if (gpg_item == NULL) { + gpg_item = new RSTreeWidgetItem(m_compareRole, 0); //set type to 0 for custom popup menu + gpg_item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); + } + + gpg_item -> setTextAlignment(COLUMN_NAME, Qt::AlignLeft | Qt::AlignVCenter ); + gpg_item -> setSizeHint(COLUMN_NAME, QSize( 40,40 ) ); + + /* not displayed, used to find back the item */ + gpg_item -> setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(detail.id)); + + //remove items that are not friends anymore + int childCount = gpg_item->childCount(); + int childIndex = 0; + while (childIndex < childCount) { + std::string ssl_id = gpg_item->child(childIndex)->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + if (!rsPeers->isFriend(ssl_id)) { + delete (gpg_item->takeChild(childIndex)); + // count again + childCount = gpg_item->childCount(); + } else { + childIndex++; + } + } + + //update the childs (ssl certs) + bool gpg_connected = false; + bool gpg_online = false; + bool gpg_hasPrivateChat = false; + std::list sslContacts; + std::map sslLocations; + std::map sslCustomStateStrings; + + rsPeers->getSSLChildListOfGPGId(detail.gpg_id, sslContacts); + for(std::list::iterator sslIt = sslContacts.begin(); sslIt != sslContacts.end(); sslIt++) { + QTreeWidgetItem *sslItem = NULL; + + //find the corresponding sslItem child item of the gpg item + bool newChild = true; + childCount = gpg_item->childCount(); + for (int childIndex = 0; childIndex < childCount; childIndex++) { + if (gpg_item->child(childIndex)->data(COLUMN_DATA, ROLE_ID).toString().toStdString() == *sslIt) { + sslItem = gpg_item->child(childIndex); + newChild = false; + break; + } + } + + RsPeerDetails sslDetail; + if (!rsPeers->getPeerDetails(*sslIt, sslDetail) || !rsPeers->isFriend(*sslIt)) { + std::cerr << "Removing widget from the view : id : " << *sslIt << std::endl; + if (sslItem) { + //child has disappeared, remove it from the gpg_item + gpg_item->removeChild(sslItem); + } + continue; + } + + if (sslItem == NULL) { + sslItem = new RSTreeWidgetItem(m_compareRole, 1); //set type to 1 for custom popup menu + } + + /* not displayed, used to find back the item */ + sslItem -> setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(sslDetail.id)); + + /* store location */ + sslLocations[sslDetail.id] = sslDetail.location; + + QString sCustomString; +#ifndef MINIMAL_RSGUI + if (sslDetail.state & RS_PEER_STATE_CONNECTED) { + sCustomString = QString::fromUtf8(rsMsgs->getCustomStateString(sslDetail.id).c_str()); + } +#endif // MINIMAL_RSGUI + if (sCustomString.isEmpty()) { + sslItem -> setText( COLUMN_NAME, tr("location") + " : " + QString::fromUtf8(sslDetail.location.c_str()) + " " + StatusDefs::connectStateString(sslDetail)); + sslItem -> setToolTip( COLUMN_NAME, tr("location") + " : " + QString::fromUtf8(sslDetail.location.c_str())); + } else { + sslItem -> setText( COLUMN_NAME, tr("location") + " : " + QString::fromUtf8(sslDetail.location.c_str()) + " " + StatusDefs::connectStateString(sslDetail)); + sslItem -> setToolTip( COLUMN_NAME, tr("location") + " : " + QString::fromUtf8(sslDetail.location.c_str()) + " - " + sCustomString); + + /* store custom state string */ + sslCustomStateStrings[sslDetail.id] = sCustomString; + } + + QIcon sslIcon; + QFont sslFont; + QColor sslColor; + if (sslDetail.state & RS_PEER_STATE_CONNECTED) { + sslItem->setHidden(false); + gpg_connected = true; + +#ifdef MINIMAL_RSGUI +// to show the gpg as online, remove it with MINIMAL_RSGUI + QFont font1; + font1.setBold(true); + + gpg_item->setToolTip(COLUMN_NAME, StatusDefs::tooltip(RS_STATUS_ONLINE)); + gpg_item->setData(COLUMN_NAME, ROLE_SORT, BuildStateSortString(sortState, gpg_item->text(COLUMN_NAME), PEER_STATE_ONLINE)); + + QColor textColor = StatusDefs::textColor(RS_STATUS_ONLINE); + QFont font = StatusDefs::font(RS_STATUS_ONLINE); + for(int i = 0; i < COLUMN_COUNT; i++) { + gpg_item -> setTextColor(i, textColor); + gpg_item -> setFont(i, font); + } +#endif // MINIMAL_RSGUI + + /* change color and icon */ + sslIcon = QIcon(":/images/connect_established.png"); + sslFont.setBold(true); + sslColor = Qt::darkBlue; + } else if (sslDetail.state & RS_PEER_STATE_ONLINE) { + sslItem->setHidden(hideOfflineFriends); + gpg_online = true; + + if (sslDetail.connectState) { + sslIcon = QIcon(":/images/connect_creating.png"); + } else { + sslIcon = QIcon(":/images/connect_no.png"); + } + + sslFont.setBold(true); + sslColor = Qt::black; + } else { + sslItem->setHidden(hideOfflineFriends); + if (sslDetail.connectState) { + sslIcon = QIcon(":/images/connect_creating.png"); + } else { + sslIcon = QIcon(":/images/connect_no.png"); + } + + sslFont.setBold(false); + sslColor = Qt::black; + } + + if (std::find(privateChatIds.begin(), privateChatIds.end(), sslDetail.id) != privateChatIds.end()) { + // private chat is available + sslIcon = QIcon(":/images/chat.png"); + gpg_hasPrivateChat = true; + } + sslItem -> setIcon(COLUMN_NAME, sslIcon); + + for (int i = 0; i < COLUMN_COUNT; i++) { + sslItem -> setTextColor(i, sslColor); + sslItem -> setFont(i, sslFont); + } + +#ifdef PEERS_DEBUG + std::cerr << "FriendsDialog::insertPeers() inserting sslItem." << std::endl; +#endif + /* add sl child to the list. If item is already in the list, it won't be duplicated thanks to Qt */ + gpg_item->addChild(sslItem); + if (newChild) { + gpg_item->setExpanded(true); + } + } + + int i = 0; + QIcon gpgIcon; + + if (gpg_connected) { + gpg_item->setHidden(false); + +#ifdef MINIMAL_RSGUI + gpgIcon = QIcon(StatusDefs::imageIM(RS_STATUS_ONLINE)); +#else + int bestPeerState = 0; // for gpg item + std::string bestSslId; // for gpg item + unsigned int bestRSState = 0; // for gpg item + + std::list::iterator it = statusInfo.begin(); + for(; it != statusInfo.end() ; it++){ + + // don't forget the kids + std::list::iterator cont_it = sslContacts.begin(); + for(; cont_it != sslContacts.end(); cont_it++){ + + if((it->id == *cont_it) && (rsPeers->isOnline(*cont_it))) { + + int peerState = 0; + + gpg_item -> setText(COLUMN_STATE, StatusDefs::name(it->status)); + + unsigned char *data = NULL; + int size = 0 ; + rsMsgs->getAvatarData(it->id ,data,size); + + if(size != 0){ + QPixmap avatar ; + avatar.loadFromData(data,size,"PNG") ; + QIcon avatar_icon(avatar); + gpg_item-> setIcon(COLUMN_STATE, avatar_icon); + delete[] data; + + } else { + gpg_item -> setIcon(COLUMN_STATE,(QIcon(":/images/no_avatar_70.png"))); + } + + switch (it->status) { + case RS_STATUS_INACTIVE: + peerState = PEER_STATE_INACTIVE; + break; + + case RS_STATUS_ONLINE: + peerState = PEER_STATE_ONLINE; + break; + + case RS_STATUS_AWAY: + peerState = PEER_STATE_AWAY; + break; + + case RS_STATUS_BUSY: + peerState = PEER_STATE_BUSY; + break; + } + + /* find the best ssl contact for the gpg item */ + if (bestPeerState == 0) { + /* first ssl contact */ + bestPeerState = peerState; + bestSslId = *cont_it; + bestRSState = it->status; + } else if (peerState < bestPeerState) { + /* higher state */ + bestPeerState = peerState; + bestSslId = *cont_it; + bestRSState = it->status; + } else if (peerState == bestPeerState) { + /* equal state */ + + /* use the ssl id with existing custom state string */ + std::map::iterator it1 = sslCustomStateStrings.find(bestSslId); + std::map::iterator it2 = sslCustomStateStrings.find(*cont_it); + + if (it1 == sslCustomStateStrings.end()) { + if (it2 == sslCustomStateStrings.end()) { + /* both with no custom state string ... use first */ + } else { + /* second with a custom state string ... use second */ + bestPeerState = peerState; + bestSslId = *cont_it; + } + } else { + /* use first */ + } + } + } + } + } + + if (bestPeerState == 0) { + // show as online + bestPeerState = PEER_STATE_ONLINE; + bestRSState = RS_STATUS_ONLINE; + } + + QColor textColor = StatusDefs::textColor(bestRSState); + QFont font = StatusDefs::font(bestRSState); + for(i = 0; i < COLUMN_COUNT; i++) { + gpg_item -> setTextColor(i, textColor); + gpg_item -> setFont(i, font); + } + + gpgIcon = QIcon(StatusDefs::imageIM(bestRSState)); + + gpg_item->setText(COLUMN_NAME, QString::fromStdString(detail.name)); + gpg_item -> setToolTip(COLUMN_NAME, StatusDefs::tooltip(bestRSState)); + + std::map::iterator customStateString = sslCustomStateStrings.find(bestSslId); + if (customStateString == sslCustomStateStrings.end()) { +// std::map::iterator location = sslLocations.find(bestSslId); +// if (location == sslLocations.end()) { +// /* show only the name */ +// gpg_item->setText(COLUMN_NAME, QString::fromStdString(detail.name)); +// } else { +// /* show the name with location */ +// gpg_item->setText(COLUMN_NAME, QString::fromStdString(detail.name) + "\n" + QString::fromStdString(location->second)); +// } + + /* use state string for location */ + QString stateString; + stateString = StatusDefs::name(bestRSState); + + if (stateString.isEmpty()) { + /* show only the name */ + gpg_item->setText(COLUMN_NAME, QString::fromStdString(detail.name)); + } else { + /* show the name with location */ + gpg_item->setText(COLUMN_NAME, QString::fromStdString(detail.name) + "\n" + stateString); + } + } else { + /* show the name with custom state string */ + gpg_item->setText(COLUMN_NAME, QString::fromStdString(detail.name) + "\n" + customStateString->second); + } + + gpg_item->setData(COLUMN_NAME, ROLE_SORT, BuildStateSortString(sortState, gpg_item->text(COLUMN_NAME), bestPeerState)); + +#endif // MINIMAL_RSGUI + } else if (gpg_online) { + gpg_item->setHidden(hideOfflineFriends); + gpg_item->setText(COLUMN_NAME, QString::fromStdString(detail.name)); + gpgIcon = QIcon(IMAGE_AVAIBLE); + gpg_item->setData(COLUMN_NAME, ROLE_SORT, BuildStateSortString(sortState, gpg_item->text(COLUMN_NAME), PEER_STATE_AVAILABLE)); + QFont font; + font.setBold(true); + for(i = 0; i < COLUMN_COUNT; i++) { + gpg_item -> setTextColor(i,(Qt::black)); + gpg_item -> setFont(i,font); + } + } else { + gpg_item->setHidden(hideOfflineFriends); + gpg_item->setText(COLUMN_NAME, QString::fromStdString(detail.name)); + gpgIcon = QIcon(StatusDefs::imageIM(RS_STATUS_OFFLINE)); + gpg_item->setData(COLUMN_NAME, ROLE_SORT, BuildStateSortString(sortState, gpg_item->text(COLUMN_NAME), PEER_STATE_OFFLINE)); + + QColor textColor = StatusDefs::textColor(RS_STATUS_OFFLINE); + QFont font = StatusDefs::font(RS_STATUS_OFFLINE); + for(i = 0; i < COLUMN_COUNT; i++) { + gpg_item -> setTextColor(i, textColor); + gpg_item -> setFont(i, font); + } + } + + if (gpg_hasPrivateChat) { + gpgIcon = QIcon(":/images/chat.png"); + } + + gpg_item -> setIcon(COLUMN_NAME, gpgIcon); + + /* add gpg item to the list. If item is already in the list, it won't be duplicated thanks to Qt */ + peertreeWidget->addTopLevelItem(gpg_item); + + if (expandedPeers && expandedPeers->find(detail.gpg_id) != expandedPeers->end()) { + /* we have information about expanded peers and the peer was expanded */ + gpg_item->setExpanded(true); + } + } + + if (ui.filterPatternLineEdit->text().isEmpty() == false) { + FilterItems(); + } + + if (expandedPeers) { + /* we don't need the informations anymore */ + delete(expandedPeers); + expandedPeers = NULL; + } + + QTreeWidgetItem *c = getCurrentPeer(); + if (c && c->isHidden()) { + // active item is hidden, deselect it + ui.messengertreeWidget->setCurrentItem(NULL); + } +} + +/* Utility Fns */ +std::string getPeersRsCertId(QTreeWidgetItem *i) +{ + std::string id = i -> data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + return id; +} + +#ifndef MINIMAL_RSGUI +/** Add a Friend ShortCut */ +void MessengerWindow::addFriend() +{ + ConnectFriendWizard connwiz (this); + + connwiz.exec (); +} + +/** Open a QFileDialog to browse for export a file. */ +void MessengerWindow::exportfriend() +{ + QTreeWidgetItem *c = getCurrentPeer(); + +#ifdef PEERS_DEBUG + std::cerr << "FriendsDialog::exportfriend()" << std::endl; +#endif + if (!c) + { +#ifdef PEERS_DEBUG + std::cerr << "FriendsDialog::exportfriend() None Selected -- sorry" << std::endl; +#endif + return; + } + + std::string id = getPeersRsCertId(c); + QString fileName = QFileDialog::getSaveFileName(this, tr("Save Certificate"), "", + tr("Certificates (*.pqi)")); + + std::string file = fileName.toStdString(); + if (file != "") + { +#ifdef PEERS_DEBUG + std::cerr << "FriendsDialog::exportfriend() Saving to: " << file << std::endl; + std::cerr << std::endl; +#endif + if (rsPeers) + { + rsPeers->saveCertificateToFile(id, file); + } + } + +} + +void MessengerWindow::chatfriendproxy() +{ + chatfriend(getCurrentPeer()); +} + +void MessengerWindow::chatfriend(QTreeWidgetItem *pPeer) +{ + if (pPeer == NULL) { + return; + } + + std::string id = pPeer->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + PopupChatDialog::chatFriend(id); +} +#endif // MINIMAL_RSGUI + +QTreeWidgetItem *MessengerWindow::getCurrentPeer() +{ + /* get the current, and extract the Id */ + + /* get a link to the table */ + QTreeWidget *peerWidget = ui.messengertreeWidget; + QTreeWidgetItem *item = peerWidget -> currentItem(); + if (!item) + { +#ifdef PEERS_DEBUG + std::cerr << "Invalid Current Item" << std::endl; +#endif + return NULL; + } + +#ifdef PEERS_DEBUG + /* Display the columns of this item. */ + std::ostringstream out; + out << "CurrentPeerItem: " << std::endl; + + for(int i = 1; i < 6; i++) + { + QString txt = item -> text(i); + out << "\t" << i << ":" << txt.toStdString() << std::endl; + } + std::cerr << out.str(); +#endif + return item; +} + +/* So from the Peers Dialog we can call the following control Functions: + * (1) Remove Current. FriendRemove(id) + * (2) Allow/DisAllow. FriendStatus(id, accept) + * (2) Connect. FriendConnectAttempt(id, accept) + * (3) Set Address. FriendSetAddress(id, str, port) + * (4) Set Trust. FriendTrustSignature(id, bool) + * (5) Configure (GUI Only) -> 3/4 + * + * All of these rely on the finding of the current Id. + */ + +#ifndef MINIMAL_RSGUI +void MessengerWindow::removefriend() +{ + QTreeWidgetItem *c = getCurrentPeer(); +#ifdef PEERS_DEBUG + std::cerr << "FriendsDialog::removefriend()" << std::endl; +#endif + if (!c) + { +#ifdef PEERS_DEBUG + std::cerr << "FriendsDialog::removefriend() Noone Selected -- sorry" << std::endl; +#endif + return; + } + + if (rsPeers) + { + rsPeers->removeFriend(getPeersRsCertId(c)); + emit friendsUpdated() ; + } +} +#endif // MINIMAL_RSGUI + +void MessengerWindow::connectfriend() +{ + QTreeWidgetItem *c = getCurrentPeer(); +#ifdef PEERS_DEBUG + std::cerr << "FriendsDialog::connectfriend()" << std::endl; +#endif + if (!c) + { +#ifdef PEERS_DEBUG + std::cerr << "FriendsDialog::connectfriend() Noone Selected -- sorry" << std::endl; +#endif + return; + } + + if (rsPeers) + { + if (c->type() == 0) { + int childCount = c->childCount(); + for (int childIndex = 0; childIndex < childCount; childIndex++) { + QTreeWidgetItem *item = c->child(childIndex); + if (item->type() == 1) { + rsPeers->connectAttempt(getPeersRsCertId(item)); + item->setIcon(COLUMN_NAME,(QIcon(IMAGE_CONNECT2))); + } + } + } else { + //this is a SSL key + rsPeers->connectAttempt(getPeersRsCertId(c)); + c->setIcon(COLUMN_NAME,(QIcon(IMAGE_CONNECT2))); + } + } +} + +#ifndef MINIMAL_RSGUI +/* GUI stuff -> don't do anything directly with Control */ +void MessengerWindow::configurefriend() +{ + ConfCertDialog::showIt(getPeersRsCertId(getCurrentPeer()), ConfCertDialog::PageDetails); +} + +void MessengerWindow::recommendfriend() +{ + QTreeWidgetItem *peer = getCurrentPeer(); + + if (!peer) + return; + + std::list ids; + ids.push_back(peer->data(COLUMN_DATA, ROLE_ID).toString().toStdString()); + MessageComposer::recommendFriend(ids); +} + +void MessengerWindow::pastePerson() +{ + RSLinkClipboard::process(RetroShareLink::TYPE_PERSON, RSLINK_PROCESS_NOTIFY_ERROR); +} +#endif // MINIMAL_RSGUI + +//============================================================================ + + +void MessengerWindow::closeEvent (QCloseEvent * event) +{ + /* save the expanded peers */ + if (expandedPeers == NULL) { + expandedPeers = new std::set; + } else { + expandedPeers->clear(); + } + + for (int nIndex = 0; nIndex < ui.messengertreeWidget->topLevelItemCount(); nIndex++) { + QTreeWidgetItem *item = ui.messengertreeWidget->topLevelItem(nIndex); + if (item->isExpanded()) { + expandedPeers->insert(expandedPeers->end(), item->data(COLUMN_DATA, ROLE_ID).toString().toStdString()); + } + } + +} + +LogoBar & MessengerWindow::getLogoBar() const { + return *_rsLogoBarmessenger; +} + +#ifndef MINIMAL_RSGUI +/** Shows Share Manager */ +void MessengerWindow::openShareManager() +{ + ShareManager::showYourself(); +} + +void MessengerWindow::sendMessage() +{ + QTreeWidgetItem *peer = getCurrentPeer(); + + if (!peer) + return; + + std::string id = peer->data(COLUMN_DATA, ROLE_ID).toString().toStdString(); + MessageComposer::msgFriend(id, false); +} + +void MessengerWindow::changeAvatarClicked() +{ + updateAvatar(); +} + +void MessengerWindow::updateAvatar() +{ + unsigned char *data = NULL; + int size = 0 ; + + rsMsgs->getOwnAvatarData(data,size); + + std::cerr << "Image size = " << size << std::endl ; + + if(size == 0) + std::cerr << "Got no image" << std::endl ; + + // set the image + QPixmap pix ; + pix.loadFromData(data,size,"PNG") ; + ui.avatarButton->setIcon(pix); // writes image into ba in PNG format + + delete[] data ; +} + +void MessengerWindow::getAvatar() +{ + QString fileName = QFileDialog::getOpenFileName(this, "Load File", QDir::homePath(), "Pictures (*.png *.xpm *.jpg)"); + if(!fileName.isEmpty()) + { + picture = QPixmap(fileName).scaled(96,96, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + + std::cerr << "Sending avatar image down the pipe" << std::endl ; + + // send avatar down the pipe for other peers to get it. + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + picture.save(&buffer, "PNG"); // writes image into ba in PNG format + + std::cerr << "Image size = " << ba.size() << std::endl ; + + rsMsgs->setOwnAvatarData((unsigned char *)(ba.data()),ba.size()) ; // last char 0 included. + + updateAvatar() ; + } +} + +/** Loads own personal status message */ +void MessengerWindow::loadmystatusmessage() +{ + ui.messagelineEdit->setEditText( QString::fromUtf8(rsMsgs->getCustomStateString().c_str())); +} + +/** Save own status message */ +void MessengerWindow::savestatusmessage() +{ + rsMsgs->setCustomStateString(ui.messagelineEdit->currentText().toUtf8().constData()); +} + +void MessengerWindow::updateOwnStatus(const QString &peer_id, int status) +{ + // add self nick + own status + if (peer_id.toStdString() == rsPeers->getOwnId()) + { + // my status has changed + + ui.statusButton->setText(m_nickName + " (" + StatusDefs::name(status) + ")"); + + switch (status) { + case RS_STATUS_OFFLINE: + ui.avatarButton->setStyleSheet("QToolButton#avatarButton{border-image:url(:/images/mystatus_bg_offline.png); }"); + break; + + case RS_STATUS_INACTIVE: + ui.avatarButton->setStyleSheet("QToolButton#avatarButton{border-image:url(:/images/mystatus_bg_idle.png); }"); + break; + + case RS_STATUS_ONLINE: + ui.avatarButton->setStyleSheet("QToolButton#avatarButton{border-image:url(:/images/mystatus_bg_online.png); }"); + break; + + case RS_STATUS_AWAY: + ui.avatarButton->setStyleSheet("QToolButton#avatarButton{border-image:url(:/images/mystatus_bg_idle.png); }"); + break; + + case RS_STATUS_BUSY: + ui.avatarButton->setStyleSheet("QToolButton#avatarButton{border-image:url(:/images/mystatus_bg_busy.png); }"); + break; + } + + return; + } +} + +#endif // MINIMAL_RSGUI + +void MessengerWindow::on_actionSort_Peers_Descending_Order_activated() +{ + ui.messengertreeWidget->sortItems ( COLUMN_NAME, Qt::DescendingOrder ); +} + +void MessengerWindow::on_actionSort_Peers_Ascending_Order_activated() +{ + ui.messengertreeWidget->sortItems ( COLUMN_NAME, Qt::AscendingOrder ); +} + +void MessengerWindow::on_actionRoot_is_decorated_activated() +{ + ui.messengertreeWidget->setRootIsDecorated(ui.actionRoot_is_decorated->isChecked()); +} + +void MessengerWindow::displayMenu() +{ + QMenu *lookmenu = new QMenu(); + lookmenu->addAction(ui.actionSort_Peers_Descending_Order); + lookmenu->addAction(ui.actionSort_Peers_Ascending_Order); + lookmenu->addAction(ui.actionSort_by_State); + lookmenu->addAction(ui.actionHide_Offline_Friends); + lookmenu->addAction(ui.actionRoot_is_decorated); + + ui.displaypushButton->setMenu(lookmenu); +} + +/* clear Filter */ +void MessengerWindow::clearFilter() +{ + ui.filterPatternLineEdit->clear(); + ui.filterPatternLineEdit->setFocus(); +} + +void MessengerWindow::filterRegExpChanged() +{ + + QString text = ui.filterPatternLineEdit->text(); + + if (text.isEmpty()) { + ui.clearButton->hide(); + } else { + ui.clearButton->show(); + } + + FilterItems(); +} + +void MessengerWindow::FilterItems() +{ + QString sPattern = ui.filterPatternLineEdit->text(); + + int nCount = ui.messengertreeWidget->topLevelItemCount (); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + FilterItem(ui.messengertreeWidget->topLevelItem(nIndex), sPattern); + } + + QTreeWidgetItem *c = getCurrentPeer(); + if (c && c->isHidden()) { + // active item is hidden, deselect it + ui.messengertreeWidget->setCurrentItem(NULL); + } +} + +bool MessengerWindow::FilterItem(QTreeWidgetItem *pItem, QString &sPattern) +{ + bool bVisible = true; + + if (sPattern.isEmpty() == false) { + if (pItem->text(0).contains(sPattern, Qt::CaseInsensitive) == false) { + bVisible = false; + } + } + + int nVisibleChildCount = 0; + int nCount = pItem->childCount(); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + if (FilterItem(pItem->child(nIndex), sPattern)) { + nVisibleChildCount++; + } + } + + if (bVisible || nVisibleChildCount) { + pItem->setHidden(false); + } else { + pItem->setHidden(true); + } + + return (bVisible || nVisibleChildCount); +} diff --git a/retroshare-gui/src/gui/MessengerWindow.h b/retroshare-gui/src/gui/MessengerWindow.h new file mode 100644 index 000000000..b75f1042f --- /dev/null +++ b/retroshare-gui/src/gui/MessengerWindow.h @@ -0,0 +1,141 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2007, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _MESSENGERWINDOW_H +#define _MESSENGERWINDOW_H + +#include "ui_MessengerWindow.h" + +#include + +class LogoBar; +class FriendsDialog; +class PopupChatDialog; +class RSTreeWidgetItemCompareRole; + +class MessengerWindow : public RWindow +{ + Q_OBJECT + + public: + QPixmap picture; + + static void showYourself (); + static MessengerWindow* getInstance(); + static void releaseInstance(); + +public slots: + void updateMessengerDisplay() ; +#ifndef MINIMAL_RSGUI + void updateAvatar(); + void loadmystatusmessage(); +#endif // MINIMAL_RSGUI + + LogoBar & getLogoBar() const; + +protected: + /** Default Constructor */ + MessengerWindow(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default Destructor */ + ~MessengerWindow(); + + void closeEvent (QCloseEvent * event); + +private slots: + /** Create the context popup menu and it's submenus */ + void messengertreeWidgetCostumPopupMenu( QPoint point ); + +#ifndef MINIMAL_RSGUI + /** Add a new friend */ + void addFriend(); + /** Export friend */ + void exportfriend(); + /** Remove friend */ + void removefriend(); +#endif // MINIMAL_RSGUI + /** start to connect to a friend **/ + void connectfriend(); +#ifndef MINIMAL_RSGUI + /** start a chat with a friend **/ + void chatfriend(QTreeWidgetItem *pPeer); + void chatfriendproxy(); + /** start Messages Composer **/ + void sendMessage(); + /** show peers details for each friend **/ + void configurefriend(); + + void recommendfriend(); + void pastePerson(); + + /** Open Shared Manager **/ + void openShareManager(); + + /** get own last stored Avatar**/ + void getAvatar(); + + void changeAvatarClicked(); + void updateOwnStatus(const QString &peer_id, int status); + + void savestatusmessage(); +#endif // MINIMAL_RSGUI + + void on_actionSort_Peers_Descending_Order_activated(); + void on_actionSort_Peers_Ascending_Order_activated(); + void on_actionRoot_is_decorated_activated(); + + void filterRegExpChanged(); + void clearFilter(); + +signals: + void friendsUpdated() ; + +private: + static MessengerWindow *_instance; + + void processSettings(bool bLoad); + + void displayMenu(); + + /* Worker Functions */ + /* (1) Update Display */ + QTimer *timer; + + /* (2) Utility Fns */ + QTreeWidgetItem *getCurrentPeer(); + void insertPeers(); + + void FilterItems(); + bool FilterItem(QTreeWidgetItem *pItem, QString &sPattern); + + QTreeView *messengertreeWidget; + + LogoBar * _rsLogoBarmessenger; + + QFont itemFont; + QString m_nickName; + + RSTreeWidgetItemCompareRole *m_compareRole; + + /** Qt Designer generated object */ + Ui::MessengerWindow ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/MessengerWindow.ui b/retroshare-gui/src/gui/MessengerWindow.ui new file mode 100644 index 000000000..d2146d8fa --- /dev/null +++ b/retroshare-gui/src/gui/MessengerWindow.ui @@ -0,0 +1,480 @@ + + + MessengerWindow + + + + 0 + 0 + 258 + 482 + + + + RetroShare Messenger + + + + :/images/rstray3.png:/images/rstray3.png + + + + + 0 + + + 0 + + + + + + 16777215 + 82 + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + + + + 70 + 70 + + + + + 70 + 70 + + + + Click to Change your Avatar + + + QToolButton#avatarButton{border-image: url(:/images/mystatus_bg.png);} + + + + :/images/user/personal64.png:/images/user/personal64.png + + + + 50 + 50 + + + + true + + + + + + + + + true + + + + + + + + 0 + 16 + + + + QPushButton { + text-align: left; +} +QPushButton:hover { + border: 2px solid #8f8f91; + border-radius: 6px; + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #f6f7fa, stop: 1 #dadbde); + min-width: 80px; + +} +QPushButton:pressed { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #dadbde, stop: 1 #f6f7fa); +} + +QPushButton:flat { + border: none; /* no border for a flat push button */ +} + +QPushButton:default { + border-color: navy; /* make the default button prominent */ +} + + + + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + 16777215 + 32 + + + + #frame { +border-image:none; +background-color: qlineargradient(x1: 0, y1: 0, x2: 0.0, y2: 1.0, +stop: 0 #ffffff, +stop: 0.4 #eeeeee, +stop: 0.401 #e2e2e2, +stop: 1 #dddddd); +color: #CCCCCC; +border-top: 1px solid #606060; +border-bottom: 1px solid #CCCCCC; +} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + + 0 + 0 + + + + + 32 + 32 + + + + Add a Friend + + + + + + + :/images/user/add_user24.png:/images/user/add_user24.png + + + + 24 + 24 + + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + 0 + 0 + + + + Share Files for your Friends + + + + + + + + + + :/images/friendsfolder24.png:/images/friendsfolder24.png + + + + 24 + 24 + + + + true + + + + + + + QPushButton::menu-indicator { +subcontrol-origin: padding; +subcontrol-position: bottom right; +} + + + + + + + + + :/images/looknfeel.png:/images/looknfeel.png + + + + 24 + 24 + + + + true + + + + + + + 2 + + + + + + + + :/images/find-16.png + + + + + + + Search Friends + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + MS Shell Dlg 2 + + + + Reset + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + + + + + QFrame#logoframe{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + QFrame#frame_2{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); +} + + + + + + Qt::CustomContextMenu + + + QTreeWidget#messengertreeWidget{ +border: 1px solid #CCCCCC; +} + + + + 38 + 38 + + + + 22 + + + true + + + 0 + + + false + + + false + + + + + + + + + + + + 0 + 0 + 258 + 20 + + + + + + + :/images/sort_decrease.png:/images/sort_decrease.png + + + Sort Descending Order + + + Sort Descending Order + + + + + + :/images/sort_incr.png:/images/sort_incr.png + + + Sort Ascending Order + + + Sort Ascending Order + + + + + true + + + Set root is Decorated + + + Set Root Decorated + + + + + true + + + Hide Offline Friends + + + + + true + + + Sort by State + + + + + + + + diff --git a/retroshare-gui/src/gui/NetworkDialog.cpp b/retroshare-gui/src/gui/NetworkDialog.cpp new file mode 100644 index 000000000..ce3664a35 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog.cpp @@ -0,0 +1,908 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "common/vmessagebox.h" +#include "common/RSTreeWidgetItem.h" +#include "NetworkDialog.h" +#include "TrustView.h" +#include "NetworkView.h" +#include "GenCertDialog.h" +#include "connect/ConfCertDialog.h" +#include "settings/rsharesettings.h" +#include "RetroShareLink.h" + +#include + +/* Images for context menu icons */ +#define IMAGE_LOADCERT ":/images/loadcert16.png" +#define IMAGE_PEERDETAILS ":/images/peerdetails_16x16.png" +#define IMAGE_AUTH ":/images/encrypted16.png" +#define IMAGE_MAKEFRIEND ":/images/user/add_user16.png" +#define IMAGE_EXPORT ":/images/exportpeers_16x16.png" +#define IMAGE_COPYLINK ":/images/copyrslink.png" + +/* Images for Status icons */ +#define IMAGE_AUTHED ":/images/accepted16.png" +#define IMAGE_DENIED ":/images/denied16.png" +#define IMAGE_TRUSTED ":/images/rs-2.png" + +#define COLUMN_PEERNAME 1 +#define COLUMN_PEERID 4 + +static int FilterColumnFromComboBox(int nIndex) +{ + switch (nIndex) { + case 0: + return COLUMN_PEERNAME; + case 1: + return COLUMN_PEERID; + } + + return COLUMN_PEERNAME; +} + +RsCertId getNeighRsCertId(QTreeWidgetItem *i); + +/****** + * #define NET_DEBUG 1 + *****/ + +/** Constructor */ +NetworkDialog::NetworkDialog(QWidget *parent) +: RsAutoUpdatePage(10000,parent) // updates every 10 sec. +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.connecttreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connecttreeWidgetCostumPopupMenu( QPoint ) ) ); + connect( ui.connecttreeWidget, SIGNAL( itemSelectionChanged()), ui.unvalidGPGkeyWidget, SLOT( clearSelection() ) ); + connect( ui.unvalidGPGkeyWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( connecttreeWidgetCostumPopupMenu( QPoint ) ) ); + connect( ui.unvalidGPGkeyWidget, SIGNAL( itemSelectionChanged()), ui.connecttreeWidget, SLOT( clearSelection() ) ); + + connect( ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged())); + connect( ui.filterColumnComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterColumnChanged())); + connect( ui.clearButton, SIGNAL(clicked()), this, SLOT(clearFilter())); + + connect( ui.showUnvalidKeys, SIGNAL(clicked()), this, SLOT(insertConnect())); + + + /* hide the Tree +/- */ + ui.connecttreeWidget -> setRootIsDecorated( false ); + ui.connecttreeWidget -> setColumnCount(5); + ui.unvalidGPGkeyWidget-> setColumnCount(5); + + /* Set header resize modes and initial section sizes */ + QHeaderView * _header = ui.connecttreeWidget->header () ; + _header->setResizeMode (0, QHeaderView::Custom); + _header->setResizeMode (1, QHeaderView::Interactive); + _header->setResizeMode (2, QHeaderView::Interactive); + _header->setResizeMode (3, QHeaderView::Interactive); + _header->setResizeMode (4, QHeaderView::Interactive); + + _header->resizeSection ( 0, 25 ); + _header->resizeSection ( 1, 200 ); + _header->resizeSection ( 2, 200 ); + _header->resizeSection ( 3, 200 ); + + // set header text aligment + QTreeWidgetItem * headerItem = ui.connecttreeWidget->headerItem(); + headerItem->setTextAlignment(0, Qt::AlignHCenter | Qt::AlignVCenter); + headerItem->setTextAlignment(1, Qt::AlignHCenter | Qt::AlignVCenter); + headerItem->setTextAlignment(2, Qt::AlignHCenter | Qt::AlignVCenter); + headerItem->setTextAlignment(3, Qt::AlignHCenter | Qt::AlignVCenter); + headerItem->setTextAlignment(4, Qt::AlignVCenter); + + /* hide the Tree +/- */ + ui.unvalidGPGkeyWidget -> setRootIsDecorated( false ); + + /* Set header resize modes and initial section sizes */ + ui.unvalidGPGkeyWidget->header()->setResizeMode (0, QHeaderView::Custom); + ui.unvalidGPGkeyWidget->header()->setResizeMode (1, QHeaderView::Interactive); + ui.unvalidGPGkeyWidget->header()->setResizeMode (2, QHeaderView::Interactive); + ui.unvalidGPGkeyWidget->header()->setResizeMode (3, QHeaderView::Interactive); + ui.unvalidGPGkeyWidget->header()->setResizeMode (4, QHeaderView::Interactive); + + ui.unvalidGPGkeyWidget->header()->resizeSection ( 0, 25 ); + ui.unvalidGPGkeyWidget->header()->resizeSection ( 1, 200 ); + ui.unvalidGPGkeyWidget->header()->resizeSection ( 2, 200 ); + ui.unvalidGPGkeyWidget->header()->resizeSection ( 3, 200 ); + + // set header text aligment + ui.unvalidGPGkeyWidget->headerItem()->setTextAlignment(0, Qt::AlignHCenter | Qt::AlignVCenter); + ui.unvalidGPGkeyWidget->headerItem()->setTextAlignment(1, Qt::AlignHCenter | Qt::AlignVCenter); + ui.unvalidGPGkeyWidget->headerItem()->setTextAlignment(2, Qt::AlignHCenter | Qt::AlignVCenter); + ui.unvalidGPGkeyWidget->headerItem()->setTextAlignment(3, Qt::AlignHCenter | Qt::AlignVCenter); + ui.unvalidGPGkeyWidget->headerItem()->setTextAlignment(4, Qt::AlignVCenter); + + ui.connecttreeWidget->sortItems( 1, Qt::AscendingOrder ); + ui.unvalidGPGkeyWidget->sortItems( 1, Qt::AscendingOrder ); + + ui.networkTab->addTab(new TrustView(),QString(tr("Authentication matrix"))); + ui.networkTab->addTab(networkview = new NetworkView(),QString(tr("Network View"))); + + ui.showUnvalidKeys->setMinimumWidth(20); + + QString version = "-"; + std::map::iterator vit; + std::map versions; + bool retv = rsDisc->getDiscVersions(versions); + if (retv && versions.end() != (vit = versions.find(rsPeers->getOwnId()))) { + version = QString::fromStdString(vit->second); + } + + QMenu *menu = new QMenu(); + //menu->addAction(ui.actionAddFriend); + //menu->addAction(ui.actionCopyKey); + //menu->addAction(ui.actionExportKey); + //menu->addAction(ui.actionCreate_New_Profile); + //menu->addSeparator(); + menu->addAction(ui.actionTabsright); + menu->addAction(ui.actionTabswest); + menu->addAction(ui.actionTabssouth); + menu->addAction(ui.actionTabsnorth); + menu->addSeparator(); + menu->addAction(ui.actionTabsTriangular); + menu->addAction(ui.actionTabsRounded); + ui.viewButton->setMenu(menu); + + QTimer *timer2 = new QTimer(this); + connect(timer2, SIGNAL(timeout()), this, SLOT(updateNetworkStatus())); + timer2->start(1000); + + updateNetworkStatus(); + loadtabsettings(); + + ui.clearButton->hide(); + + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +void NetworkDialog::updateNewDiscoveryInfo() +{ + //std::cerr << "Received new p3disc info. Updating networkview." << std::endl; + networkview->update(); + networkview->updateDisplay(); +} + +void NetworkDialog::connecttreeWidgetCostumPopupMenu( QPoint point ) +{ + //std::cerr << "NetworkDialog::connecttreeWidgetCostumPopupMenu( QPoint point ) called" << std::endl; + QTreeWidgetItem *wi = getCurrentNeighbour(); + if (!wi) + return; + + QMenu contextMnu( this ); + + std::string peer_id = wi->text(4).toStdString() ; + + // That's what context menus are made for + RsPeerDetails detail; + if(!rsPeers->getGPGDetails(peer_id, detail)) // that is not suppose to fail. + return ; + + if(peer_id != rsPeers->getGPGOwnId()) + { + if(detail.accept_connection) + { + QAction* denyFriendAct = new QAction(QIcon(IMAGE_DENIED), tr( "Deny friend" ), &contextMnu ); + + connect( denyFriendAct , SIGNAL( triggered() ), this, SLOT( denyFriend() ) ); + contextMnu.addAction( denyFriendAct); + } + else // not a friend + { + QAction* makefriendAct = new QAction(QIcon(IMAGE_MAKEFRIEND), tr( "Make friend" ), &contextMnu ); + + connect( makefriendAct , SIGNAL( triggered() ), this, SLOT( makeFriend() ) ); + contextMnu.addAction( makefriendAct); +#ifdef TODO + if(detail.validLvl > RS_TRUST_LVL_MARGINAL) // it's a denied old friend. + { + QAction* deleteCertAct = new QAction(QIcon(IMAGE_PEERDETAILS), tr( "Delete certificate" ), &contextMnu ); + connect( deleteCertAct, SIGNAL( triggered() ), this, SLOT( deleteCert() ) ); + contextMnu.addAction( deleteCertAct ); + } + +#endif + } + } + if(peer_id == rsPeers->getGPGOwnId()) + { + QAction* exportcertAct = new QAction(QIcon(IMAGE_EXPORT), tr( "Export my Cert" ), &contextMnu ); + connect( exportcertAct , SIGNAL( triggered() ), this, SLOT( on_actionExportKey_activated() ) ); + contextMnu.addAction( exportcertAct); + } + + QAction* peerdetailsAct = new QAction(QIcon(IMAGE_PEERDETAILS), tr( "Peer details..." ), &contextMnu ); + connect( peerdetailsAct , SIGNAL( triggered() ), this, SLOT( peerdetails() ) ); + contextMnu.addAction( peerdetailsAct); + + contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyLink())); + + contextMnu.exec(QCursor::pos()); +} + +void NetworkDialog::denyFriend() +{ + QTreeWidgetItem *wi = getCurrentNeighbour(); + std::string peer_id = wi->text(4).toStdString() ; + rsPeers->removeFriend(peer_id) ; + + insertConnect() ; +} +void NetworkDialog::deleteCert() +{ +#ifdef TODO + // do whatever is needed to remove the certificate completely, hopping this + // will eventually remove the signature we've stamped on it. + std::cout << "Deleting friend !" << std::endl ; + + QTreeWidgetItem *wi = getCurrentNeighbour(); + std::string peer_id = wi->text(9).toStdString() ; + rsPeers->deleteCertificate(peer_id) ; + + insertConnect() ; +#endif +} + +void NetworkDialog::makeFriend() +{ + ConfCertDialog::showIt(getCurrentNeighbour()->text(4).toStdString(), ConfCertDialog::PageTrust); +} + +/** Shows Peer Information/Auth Dialog */ +void NetworkDialog::peerdetails() +{ + ConfCertDialog::showIt(getCurrentNeighbour()->text(4).toStdString(), ConfCertDialog::PageDetails); +} + +void NetworkDialog::copyLink() +{ + QTreeWidgetItem *wi = getCurrentNeighbour(); + if (wi == NULL) { + return; + } + + std::string peer_id = wi->text(4).toStdString() ; + + std::vector urls; + RetroShareLink link; + if (link.createPerson(peer_id)) { + urls.push_back(link); + } + + RSLinkClipboard::copyLinks(urls); +} + +/** Open a QFileDialog to browse for a pem/pqi file. */ +//void NetworkDialog::loadcert() +//{ +// use misc::getOpenFileName +// /* Create a new input dialog, which allows users to create files, too */ +// QFileDialog dialog (this, tr("Select a pem/pqi File")); +// //dialog.setDirectory(QFileInfo(ui.lineTorConfig->text()).absoluteDir()); +// //dialog.selectFile(QFileInfo(ui.lineTorConfig->text()).fileName()); +// dialog.setFileMode(QFileDialog::AnyFile); +// dialog.setReadOnly(false); +// +// /* Prompt the user to select a file or create a new one */ +// if (!dialog.exec() || dialog.selectedFiles().isEmpty()) { +// return; +// } +// QString filename = QDir::convertSeparators(dialog.selectedFiles().at(0)); +// +// /* Check if the file exists */ +// QFile torrcFile(filename); +// if (!QFileInfo(filename).exists()) { +// /* The given file does not exist. Should we create it? */ +// int response = VMessageBox::question(this, +// tr("File Not Found"), +// tr("%1 does not exist. Would you like to create it?") +// .arg(filename), +// VMessageBox::Yes, VMessageBox::No); +// +// if (response == VMessageBox::No) { +// /* Don't create it. Just bail. */ +// return; +// } +// /* Attempt to create the specified file */ +// if (!torrcFile.open(QIODevice::WriteOnly)) { +// VMessageBox::warning(this, +// tr("Failed to Create File"), +// tr("Unable to create %1 [%2]").arg(filename) +// .arg(torrcFile.errorString()), +// VMessageBox::Ok); +// return; +// } +// } +// //ui.lineTorConfig->setText(filename); +//} + +void NetworkDialog::updateDisplay() +{ + insertConnect() ; +} + +/* get the list of Neighbours from the RsIface. */ +void NetworkDialog::insertConnect() +{ + static time_t last_time = 0 ; + + if (!rsPeers) + return; + + if (ui.showUnvalidKeys->isChecked()) { + ui.unvalidGPGkeyWidget->show(); + } else { + ui.unvalidGPGkeyWidget->hide(); + } + + // Because this is called from a qt signal, there's no limitation between calls. + time_t now = time(NULL); + if(last_time + 5 > now) // never update more often then every 5 seconds. + return ; + + last_time = now ; + + std::list neighs; //these are GPG ids + std::list::iterator it; + rsPeers->getGPGAllList(neighs); + + /* get a link to the table */ + QTreeWidget *connectWidget = ui.connecttreeWidget; + + //remove items + int index = 0; + while (index < connectWidget->topLevelItemCount()) { + std::string gpg_widget_id = (connectWidget->topLevelItem(index))->text(4).toStdString(); + RsPeerDetails detail; + if (!rsPeers->getGPGDetails(gpg_widget_id, detail) || (detail.validLvl < GPGME_VALIDITY_MARGINAL && !detail.accept_connection)) { + delete (connectWidget->takeTopLevelItem(index)); + } else { + index++; + } + } + index = 0; + while (index < ui.unvalidGPGkeyWidget->topLevelItemCount()) { + std::string gpg_widget_id = (ui.unvalidGPGkeyWidget->topLevelItem(index))->text(4).toStdString(); + RsPeerDetails detail; + if (!rsPeers->getGPGDetails(gpg_widget_id, detail) || detail.validLvl >= GPGME_VALIDITY_MARGINAL || detail.accept_connection) { + delete (ui.unvalidGPGkeyWidget->takeTopLevelItem(index)); + } else { + index++; + } + } + + QList validItems; + QList unvalidItems; + for(it = neighs.begin(); it != neighs.end(); it++) + { +#ifdef NET_DEBUG + std::cerr << "NetworkDialog::insertConnect() inserting gpg key : " << *it << std::endl; +#endif + if (*it == rsPeers->getGPGOwnId()) { + continue; + } + + RsPeerDetails detail; + if (!rsPeers->getGPGDetails(*it, detail)) + { + continue; /* BAD */ + } + + /* make a widget per friend */ + QTreeWidgetItem *item; + QList list = connectWidget->findItems(QString::fromStdString(*it), Qt::MatchExactly, 4); + if (list.size() == 1) { + item = list.front(); + } else { + list = ui.unvalidGPGkeyWidget->findItems(QString::fromStdString(*it), Qt::MatchExactly, 4); + if (list.size() == 1) { + item = list.front(); + } else { + //create new item +#ifdef NET_DEBUG + std::cerr << "NetworkDialog::insertConnect() creating new tree widget item : " << *it << std::endl; +#endif + item = new RSTreeWidgetItem(NULL, 0); + item -> setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); + item -> setSizeHint(0, QSize( 18,18 ) ); + + /* (1) Person */ + item -> setText(COLUMN_PEERNAME, QString::fromStdString(detail.name)); + + /* (4) key id */ + item -> setText(COLUMN_PEERID, QString::fromStdString(detail.id)); + } + } + + QString TrustLevelString ; + + /* (2) Key validity */ + if (detail.ownsign) + { + item -> setText(2, tr("Personal signature")); + item -> setToolTip(2, tr("GPG key signed by you")); + } + else + switch(detail.trustLvl) + { + case GPGME_VALIDITY_MARGINAL: item->setText(2,tr("Marginally trusted peer")) ; break; + case GPGME_VALIDITY_FULL: + case GPGME_VALIDITY_ULTIMATE: item->setText(2,tr("Fully trusted peer")) ; break ; + case GPGME_VALIDITY_UNKNOWN: + case GPGME_VALIDITY_UNDEFINED: + case GPGME_VALIDITY_NEVER: + default: item->setText(2,tr("Untrusted peer")) ; break ; + } + + QString PeerAuthenticationString = tr("Unknown") ; + /* (3) has me auth */ + if (detail.hasSignedMe) + PeerAuthenticationString = tr("Has authenticated me"); + + item->setText(3,PeerAuthenticationString) ; + + /** + * Determinated the Background Color + */ + QColor backgrndcolor; + + if (detail.accept_connection) + { + if (detail.ownsign) + { + item -> setText(0, "0"); + item -> setIcon(0,(QIcon(IMAGE_AUTHED))); + backgrndcolor=QColor("#45ff45");//bright green + } + else + { + item -> setText(0, "0"); + item -> setIcon(0,(QIcon(IMAGE_AUTHED))); + backgrndcolor=QColor("#43C043");//light green + } + } + else + { + item -> setText(0, "1"); + + if (detail.hasSignedMe) + { + backgrndcolor=QColor("#B242B2"); //kind of purple + item -> setIcon(0,(QIcon(IMAGE_DENIED))); + for(int k=0;k<8;++k) + item -> setToolTip(k, QString::fromStdString(detail.name) + tr(" has authenticated you. \nRight-click and select 'make friend' to be able to connect.")); + } + else + { + backgrndcolor=Qt::lightGray; + item -> setIcon(0,(QIcon(IMAGE_DENIED))); + } + } + + // Color each Background column in the Network Tab except the first one => 1-9 + // whith the determinated color + for(int i = 0; i <10; i++) + item -> setBackground(i,QBrush(backgrndcolor)); + + /* add to the list */ + if (detail.accept_connection || detail.validLvl >= GPGME_VALIDITY_MARGINAL) + { + /* add gpg item to the list. If item is already in the list, it won't be duplicated thanks to Qt */ + connectWidget->addTopLevelItem(item); + } + else + { + ui.unvalidGPGkeyWidget->addTopLevelItem(item); + } + + } + + // add self to network. + RsPeerDetails ownGPGDetails; + rsPeers->getGPGDetails(rsPeers->getGPGOwnId(), ownGPGDetails); + /* make a widget per friend */ + QTreeWidgetItem *self_item; + QList list = connectWidget->findItems(QString::fromStdString(ownGPGDetails.gpg_id), Qt::MatchExactly, 4); + if (list.size() == 1) { + self_item = list.front(); + } else { + self_item = new RSTreeWidgetItem(NULL, 0); + self_item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); + } + self_item -> setText(0, "0"); + self_item->setIcon(0,(QIcon(IMAGE_AUTHED))); + self_item->setText(COLUMN_PEERNAME, QString::fromStdString(ownGPGDetails.name) + " (" + tr("yourself") + ")"); + self_item->setText(2,"N/A"); + self_item->setText(COLUMN_PEERID, QString::fromStdString(ownGPGDetails.id)); + + // Color each Background column in the Network Tab except the first one => 1-9 + for(int i=0;i<10;++i) + { + self_item->setBackground(i,Qt::yellow) ;//QBrush(QColor("#45ff45"))); + } + connectWidget->addTopLevelItem(self_item); + + connectWidget->update(); /* update display */ + ui.unvalidGPGkeyWidget->update(); /* update display */ + + if (ui.filterPatternLineEdit->text().isEmpty() == false) { + FilterItems(); + } + +} + +QTreeWidgetItem *NetworkDialog::getCurrentNeighbour() +{ + if (ui.connecttreeWidget->selectedItems().size() != 0) { + return ui.connecttreeWidget -> currentItem(); + } else if (ui.unvalidGPGkeyWidget->selectedItems().size() != 0) { + return ui.unvalidGPGkeyWidget->currentItem(); + } + + return NULL; +} + +/* Utility Fns */ +RsCertId getNeighRsCertId(QTreeWidgetItem *i) +{ + RsCertId id = (i -> text(4)).toStdString(); + return id; +} + +/* So from the Neighbours Dialog we can call the following control Functions: + * (1) Load Certificate NeighLoadCertificate(std::string file) + * (2) Neigh Auth NeighAuthFriend(id, code) + * (4) Neigh Add NeighAddFriend(id) + * + * All of these rely on the finding of the current Id. + */ + +//std::string NetworkDialog::loadneighbour() +//{ +//#ifdef NET_DEBUG +// std::cerr << "NetworkDialog::loadneighbour()" << std::endl; +//#endif +// use misc::getOpenFileName +// QString fileName = QFileDialog::getOpenFileName(this, tr("Select Certificate"), "", +// tr("Certificates (*.pqi *.pem)")); +// +// std::string file = fileName.toStdString(); +// std::string id; +// std::string gpg_id; +// if (file != "") +// { +// rsPeers->loadCertificateFromFile(file, id, gpg_id); +// } +// return id; +//} + +//void NetworkDialog::addneighbour() +//{ +//// QTreeWidgetItem *c = getCurrentNeighbour(); +//#ifdef NET_DEBUG +// std::cerr << "NetworkDialog::addneighbour()" << std::endl; +//#endif +// /* +// rsServer->NeighAddFriend(getNeighRsCertId(c)); +// */ +//} + +//void NetworkDialog::authneighbour() +//{ +//// QTreeWidgetItem *c = getCurrentNeighbour(); +//#ifdef NET_DEBUG +// std::cerr << "NetworkDialog::authneighbour()" << std::endl; +//#endif +// /* +// RsAuthId code; +// rsServer->NeighAuthFriend(getNeighRsCertId(c), code); +// */ +//} + +/** Open a QFileDialog to browse for a pem/pqi file. */ +void NetworkDialog::on_actionAddFriend_activated() +{ +// /* Create a new input dialog, which allows users to create files, too */ +// use misc::getOpenFileName +// QFileDialog dialog (this, tr("Select a pem/pqi File")); +// //dialog.setDirectory(QFileInfo(ui.lineTorConfig->text()).absoluteDir()); +// //dialog.selectFile(QFileInfo(ui.lineTorConfig->text()).fileName()); +// dialog.setFileMode(QFileDialog::AnyFile); +// dialog.setReadOnly(false); +// +// /* Prompt the user to select a file or create a new one */ +// if (!dialog.exec() || dialog.selectedFiles().isEmpty()) { +// return; +// } +// QString filename = QDir::convertSeparators(dialog.selectedFiles().at(0)); +// +// /* Check if the file exists */ +// QFile torrcFile(filename); +// if (!QFileInfo(filename).exists()) { +// /* The given file does not exist. Should we create it? */ +// int response = VMessageBox::question(this, +// tr("File Not Found"), +// tr("%1 does not exist. Would you like to create it?") +// .arg(filename), +// VMessageBox::Yes, VMessageBox::No); +// +// if (response == VMessageBox::No) { +// /* Don't create it. Just bail. */ +// return; +// } +// /* Attempt to create the specified file */ +// if (!torrcFile.open(QIODevice::WriteOnly)) { +// VMessageBox::warning(this, +// tr("Failed to Create File"), +// tr("Unable to create %1 [%2]").arg(filename) +// .arg(torrcFile.errorString()), +// VMessageBox::Ok); +// return; +// } +// } +// //ui.lineTorConfig->setText(filename); +} + + +void NetworkDialog::on_actionExportKey_activated() +{ +// qDebug() << " exportcert"; +// +// std::string cert = rsPeers->GetRetroshareInvite(); +// if (cert.empty()) { +// QMessageBox::information(this, tr("RetroShare"), +// tr("Sorry, create certificate failed"), +// QMessageBox::Ok, QMessageBox::Ok); +// return; +// } +// +// use misc::getSaveFileName +// QString qdir = QFileDialog::getSaveFileName(this, +// tr("Please choose a filename"), +// QDir::homePath(), +// tr("RetroShare Certificate (*.rsc );;All Files (*)")); +// //Todo: move save to file to p3Peers::SaveCertificateToFile +// +// if (qdir.isEmpty() == false) { +// QFile CertFile (qdir); +// if (CertFile.open(QIODevice::WriteOnly/* | QIODevice::Text*/)) { +// if (CertFile.write(QByteArray(cert.c_str())) > 0) { +// QMessageBox::information(this, tr("RetroShare"), +// tr("Certificate file successfully created"), +// QMessageBox::Ok, QMessageBox::Ok); +// } else { +// QMessageBox::information(this, tr("RetroShare"), +// tr("Sorry, certificate file creation failed"), +// QMessageBox::Ok, QMessageBox::Ok); +// } +// CertFile.close(); +// } else { +// QMessageBox::information(this, tr("RetroShare"), +// tr("Sorry, certificate file creation failed"), +// QMessageBox::Ok, QMessageBox::Ok); +// } +// } +} + +void NetworkDialog::on_actionCreate_New_Profile_activated() +{ +// GenCertDialog gencertdialog (this); +// gencertdialog.exec (); +} + +void NetworkDialog::updateNetworkStatus() +{ + if(RsAutoUpdatePage::eventsLocked()) + return ; + + rsiface->lockData(); /* Lock Interface */ + + /* now the extra bit .... switch on check boxes */ + const RsConfig &config = rsiface->getConfig(); + + + /******* Network Status Tab *******/ + + if(config.netUpnpOk) + { + ui.iconlabel_upnp->setPixmap(QPixmap(":/images/ledon1.png")); + } + else + { + ui.iconlabel_upnp->setPixmap(QPixmap(":/images/ledoff1.png")); + } + + if (config.netLocalOk) + { + ui.iconlabel_netLimited->setPixmap(QPixmap(":/images/ledon1.png")); + } + else + { + ui.iconlabel_netLimited->setPixmap(QPixmap(":/images/ledoff1.png")); + } + + if (config.netExtraAddressOk) + { + ui.iconlabel_ext->setPixmap(QPixmap(":/images/ledon1.png")); + } + else + { + ui.iconlabel_ext->setPixmap(QPixmap(":/images/ledoff1.png")); + } + + rsiface->unlockData(); /* UnLock Interface */ +} + +void NetworkDialog::on_actionTabsnorth_activated() +{ + ui.networkTab->setTabPosition(QTabWidget::North); + + Settings->setValueToGroup("NetworkDialog", "TabWidget_Position",ui.networkTab->tabPosition()); +} + +void NetworkDialog::on_actionTabssouth_activated() +{ + ui.networkTab->setTabPosition(QTabWidget::South); + + Settings->setValueToGroup("NetworkDialog", "TabWidget_Position",ui.networkTab->tabPosition()); + +} + +void NetworkDialog::on_actionTabswest_activated() +{ + ui.networkTab->setTabPosition(QTabWidget::West); + + Settings->setValueToGroup("NetworkDialog", "TabWidget_Position",ui.networkTab->tabPosition()); +} + +void NetworkDialog::on_actionTabsright_activated() +{ + ui.networkTab->setTabPosition(QTabWidget::East); + + Settings->setValueToGroup("NetworkDialog", "TabWidget_Position",ui.networkTab->tabPosition()); +} + +void NetworkDialog::on_actionTabsTriangular_activated() +{ + ui.networkTab->setTabShape(QTabWidget::Triangular); + ui.tabBottom->setTabShape(QTabWidget::Triangular); +} + +void NetworkDialog::on_actionTabsRounded_activated() +{ + ui.networkTab->setTabShape(QTabWidget::Rounded); + ui.tabBottom->setTabShape(QTabWidget::Rounded); +} + +void NetworkDialog::loadtabsettings() +{ + Settings->beginGroup("NetworkDialog"); + + if(Settings->value("TabWidget_Position","0").toInt() == 0) + { + qDebug() << "Tab North"; + ui.networkTab->setTabPosition(QTabWidget::North); + } + else if (Settings->value("TabWidget_Position","1").toInt() == 1) + { + qDebug() << "Tab South"; + ui.networkTab->setTabPosition(QTabWidget::South); + } + else if (Settings->value("TabWidget_Position","2").toInt() ==2) + { + qDebug() << "Tab West"; + ui.networkTab->setTabPosition(QTabWidget::West); + } + else if(Settings->value("TabWidget_Position","3").toInt() ==3) + { + qDebug() << "Tab East"; + ui.networkTab->setTabPosition(QTabWidget::East); + } + + Settings->endGroup(); +} + +/* clear Filter */ +void NetworkDialog::clearFilter() +{ + ui.filterPatternLineEdit->clear(); + ui.filterPatternLineEdit->setFocus(); +} + +void NetworkDialog::filterRegExpChanged() +{ + + QString text = ui.filterPatternLineEdit->text(); + + if (text.isEmpty()) { + ui.clearButton->hide(); + } else { + ui.clearButton->show(); + } + + FilterItems(); +} + +void NetworkDialog::filterColumnChanged() +{ + + FilterItems(); + +} + +void NetworkDialog::FilterItems() +{ + QString sPattern = ui.filterPatternLineEdit->text(); + int nFilterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); + + int nCount = ui.connecttreeWidget->topLevelItemCount (); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + FilterItem(ui.connecttreeWidget->topLevelItem(nIndex), sPattern, nFilterColumn); + } + nCount = ui.unvalidGPGkeyWidget->topLevelItemCount (); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + FilterItem(ui.unvalidGPGkeyWidget->topLevelItem(nIndex), sPattern, nFilterColumn); + } +} + +bool NetworkDialog::FilterItem(QTreeWidgetItem *pItem, QString &sPattern, int nFilterColumn) +{ + bool bVisible = true; + + if (sPattern.isEmpty() == false) { + if (pItem->text(nFilterColumn).contains(sPattern, Qt::CaseInsensitive) == false) { + bVisible = false; + } + } + + int nVisibleChildCount = 0; + int nCount = pItem->childCount(); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + if (FilterItem(pItem->child(nIndex), sPattern, nFilterColumn)) { + nVisibleChildCount++; + } + } + + if (bVisible || nVisibleChildCount) { + pItem->setHidden(false); + } else { + pItem->setHidden(true); + } + + return (bVisible || nVisibleChildCount); +} diff --git a/retroshare-gui/src/gui/NetworkDialog.h b/retroshare-gui/src/gui/NetworkDialog.h new file mode 100644 index 000000000..369426947 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog.h @@ -0,0 +1,101 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _CONNECTIONSDIALOG_H +#define _CONNECTIONSDIALOG_H + +#include "ui_NetworkDialog.h" +#include "RsAutoUpdatePage.h" + +class NetworkDialog : public RsAutoUpdatePage +{ + Q_OBJECT + +public: + /** Default Constructor */ + NetworkDialog(QWidget *parent = 0); + + //void load(); + virtual void updateDisplay() ; // overloaded from RsAutoUpdatePage + +public slots: + void insertConnect(); +// std::string loadneighbour(); + /* void loadneighbour(); */ + void updateNewDiscoveryInfo() ; + + +private slots: + + void makeFriend() ; + void denyFriend() ; + void deleteCert() ; + void peerdetails(); + void copyLink(); + /** Create the context popup menu and it's submenus */ + void connecttreeWidgetCostumPopupMenu( QPoint point ); + //void unvalidGPGkeyWidgetCostumPopupMenu( QPoint point ); + + /** Called when user clicks "Load Cert" to choose location of a Cert file */ +// void loadcert(); + +// void authneighbour(); +// void addneighbour(); + + void on_actionAddFriend_activated(); + //void on_actionCopyKey_activated(); + void on_actionExportKey_activated(); + + void on_actionCreate_New_Profile_activated(); + + void updateNetworkStatus(); + + void loadtabsettings(); + + void on_actionTabsright_activated(); + void on_actionTabsnorth_activated(); + void on_actionTabssouth_activated(); + void on_actionTabswest_activated(); + + void on_actionTabsRounded_activated(); + void on_actionTabsTriangular_activated(); + + void filterColumnChanged(); + void filterRegExpChanged(); + void clearFilter(); + +private: + QTreeWidgetItem *getCurrentNeighbour(); + + QTreeWidget *connecttreeWidget; + + class NetworkView *networkview; + + void FilterItems(); + bool FilterItem(QTreeWidgetItem *pItem, QString &sPattern, int nFilterColumn); + + /** Qt Designer generated object */ + Ui::NetworkDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/NetworkDialog.ui b/retroshare-gui/src/gui/NetworkDialog.ui new file mode 100644 index 000000000..03aeece92 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkDialog.ui @@ -0,0 +1,605 @@ + + + NetworkDialog + + + + 0 + 0 + 629 + 346 + + + + + 6 + + + 9 + + + 6 + + + 0 + + + + + QTabWidget::North + + + 0 + + + + Network + + + + 6 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Qt::CustomContextMenu + + + false + + + false + + + 20 + + + + 16 + 16 + + + + true + + + true + + + true + + + true + + + true + + + true + + + 200 + + + true + + + true + + + 200 + + + true + + + + + + + + + Name + + + + + Did I authenticated peer + + + Did I sign his gpg key + + + + + Did peer authenticated me + + + + + Cert Id + + + + + + + + + 0 + 32 + + + + + 16777215 + 16777215 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + 1 + + + + + + 22 + 22 + + + + + + + :/images/rs1.png + + + true + + + + + + + + Arial + 10 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + + + 2 + + + + + + + + :/images/find-16.png + + + + + + + Search Network + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + MS Shell Dlg 2 + + + + Qt::NoFocus + + + Clear Filter + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + + + 0 + 0 + + + + + MS Shell Dlg 2 + + + + 0 + + + + Name + + + + + Peer ID + + + + + + + + Show keys that are not validated by the GPG web of trust + + + + + + + Qt::NoFocus + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + QPushButton::menu-indicator { +subcontrol-origin: padding; +subcontrol-position: bottom right; +} + + + + + + + + + :/images/looknfeel.png:/images/looknfeel.png + + + false + + + true + + + + + + + + + + + 16777215 + 60 + + + + QTabWidget::North + + + 0 + + + + Network Status + + + + + + 6 + + + 6 + + + + + + 16 + 16 + + + + + + + :/images/ledoff1.png + + + + + + + Local network + + + + + + + + + 6 + + + 6 + + + + + + 16 + 16 + + + + + + + :/images/ledoff1.png + + + + + + + UPnP + + + + + + + + + 6 + + + 6 + + + + + + 16 + 16 + + + + + + + :/images/ledoff1.png + + + + + + + External ip address finder + + + + + + + + + Qt::Horizontal + + + + 250 + 13 + + + + + + + + + + + + Qt::CustomContextMenu + + + true + + + true + + + true + + + 200 + + + true + + + true + + + 200 + + + true + + + + + + + + + Name + + + + + Did I authenticated peer + + + + + Did peer authenticated me + + + + + Cert Id + + + + + + + + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + + :/images/user/add_user16.png:/images/user/add_user16.png + + + Add Friend + + + + + Copy My Key to Clipboard + + + + + + :/images/exportpeers_16x16.png:/images/exportpeers_16x16.png + + + Export My Key + + + + + Create New Profile + + + Create a new Profile + + + + + + diff --git a/retroshare-gui/src/gui/NetworkView.cpp b/retroshare-gui/src/gui/NetworkView.cpp new file mode 100644 index 000000000..006160060 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkView.cpp @@ -0,0 +1,227 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "NetworkView.h" +#include +#include + +#include + +#include +#include +#include +#include + +#include "gui/elastic/node.h" + +/******** +* #define DEBUG_NETWORKVIEW +********/ + +/** Constructor */ +NetworkView::NetworkView(QWidget *parent) +: RsAutoUpdatePage(60000,parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + mScene = new QGraphicsScene(); + mScene->setItemIndexMethod(QGraphicsScene::NoIndex); + mScene->setSceneRect(-200, -200, 1200, 1200); + + ui.graphicsView->setScene(mScene); + ui.graphicsView->setEdgeLength(ui.edgeLengthSB->value()) ; + + setMaxFriendLevel(ui.maxFriendLevelSB->value()) ; + + /* add button */ + connect( ui.refreshButton, SIGNAL( clicked( void ) ), this, SLOT( redraw( void ) ) ); + connect( mScene, SIGNAL( changed ( const QList & ) ), this, SLOT ( changedScene( void ) ) ); + + /* Hide Settings frame */ + connect( ui.maxFriendLevelSB, SIGNAL(valueChanged(int)), this, SLOT(setMaxFriendLevel(int))); + connect( ui.edgeLengthSB, SIGNAL(valueChanged(int)), this, SLOT(setEdgeLength(int))); + + _should_update = true ; +} + +NetworkView::~NetworkView() +{ + if(mScene != NULL) + delete mScene ; +} + +void NetworkView::setEdgeLength(int l) +{ + ui.graphicsView->setEdgeLength(l); +} +void NetworkView::setMaxFriendLevel(int m) +{ + ui.graphicsView->snapshotNodesPositions() ; + clear() ; + _max_friend_level = m ; + updateDisplay() ; +} +void NetworkView::changedFoFCheckBox( ) +{ + updateDisplay(); +} +void NetworkView::redraw() +{ + ui.graphicsView->clearNodesPositions() ; + clear() ; + updateDisplay() ; +} + +void NetworkView::clear() +{ + ui.graphicsView->clearGraph() ; + _node_ids.clear() ; + update() ; +} + +class NodeInfo +{ + public: + NodeInfo(const std::string& _gpg_id,uint32_t lev) : gpg_id(_gpg_id),friend_level(lev) {} + + std::string gpg_id ; + uint32_t friend_level ; +} ; + +void NetworkView::update() +{ + _should_update = true ; +} +void NetworkView::updateDisplay() +{ + if(!isVisible()) + return ; + if(!_should_update) + return ; + + /* add all friends */ + std::string ownGPGId = rsPeers->getGPGOwnId(); +#ifdef DEBUG_NETWORKVIEW + std::cerr << "NetworkView::updateDisplay()" << std::endl; +#endif + + int i = 0; + + std::deque nodes_to_treat ; // list of nodes to be treated. Used as a queue. The int is the level of friendness + std::set nodes_considered ; // list of nodes already considered. Eases lookup. + + nodes_to_treat.push_front(NodeInfo(ownGPGId,0)) ; // initialize queue with own id. + nodes_considered.insert(rsPeers->getOwnId()) ; + + // Put own id in queue, and empty the queue, treating all nodes. + // + while(!nodes_to_treat.empty()) + { + NodeInfo info(nodes_to_treat.back()) ; + nodes_to_treat.pop_back() ; +#ifdef DEBUG_NETWORKVIEW + std::cerr << " Poped out of queue: " << info.gpg_id << ", with level " << info.friend_level << std::endl ; +#endif + GraphWidget::NodeType type ; + GraphWidget::AuthType auth ; + + switch(info.friend_level) + { + case 0: type = GraphWidget::ELASTIC_NODE_TYPE_OWN ; + break ; + case 1: type = GraphWidget::ELASTIC_NODE_TYPE_FRIEND ; + break ; + case 2: type = GraphWidget::ELASTIC_NODE_TYPE_F_OF_F ; + break ; + default: + type = GraphWidget::ELASTIC_NODE_TYPE_UNKNOWN ; + } + + RsPeerDetails detail ; + if(!rsPeers->getPeerDetails(info.gpg_id, detail)) + continue ; + + switch(detail.validLvl) + { + case GPGME_VALIDITY_MARGINAL: auth = GraphWidget::ELASTIC_NODE_AUTH_MARGINAL ; break; + case GPGME_VALIDITY_FULL: + case GPGME_VALIDITY_ULTIMATE: auth = GraphWidget::ELASTIC_NODE_AUTH_FULL ; break; + case GPGME_VALIDITY_UNKNOWN: + case GPGME_VALIDITY_UNDEFINED: + case GPGME_VALIDITY_NEVER: + default: auth = GraphWidget::ELASTIC_NODE_AUTH_UNKNOWN ; break ; + } + + if(info.friend_level <= _max_friend_level && _node_ids.find(info.gpg_id) == _node_ids.end()) + { + _node_ids[info.gpg_id] = ui.graphicsView->addNode(" "+detail.name, detail.name+"@"+detail.gpg_id,type,auth,"",info.gpg_id); +#ifdef DEBUG_NETWORKVIEW + std::cerr << " inserted node " << info.gpg_id << ", type=" << type << ", auth=" << auth << std::endl ; +#endif + } + + std::list friendList; + rsDisc->getDiscGPGFriends(info.gpg_id, friendList); + +#ifdef DEBUG_NETWORKVIEW + std::cerr << " Got a list of " << friendList.size() << " friends for this peer." << std::endl ; +#endif + + if(info.friend_level+1 <= _max_friend_level) + for(std::list::const_iterator sit(friendList.begin()); sit != friendList.end(); ++sit) + if(nodes_considered.find(*sit) == nodes_considered.end()) + { +#ifdef DEBUG_NETWORKVIEW + std::cerr << " adding to queue: " << *sit << ", with level " << info.friend_level+1 << std::endl ; +#endif + nodes_to_treat.push_front( NodeInfo(*sit,info.friend_level + 1) ) ; + nodes_considered.insert(*sit) ; + } + } + + /* iterate through all friends */ + +#ifdef DEBUG_NETWORKVIEW + std::cerr << "NetworkView::insertSignatures()" << std::endl; +#endif + + for(std::map::const_iterator it(_node_ids.begin()); it != _node_ids.end(); it++) + { + std::list friendList ; + + if(rsDisc->getDiscGPGFriends(it->first,friendList)) + for(std::list::const_iterator sit(friendList.begin()); sit != friendList.end(); sit++) + { +#ifdef DEBUG_NETWORKVIEW + std::cerr << "NetworkView: Adding Edge: "; + std::cerr << *sit << " <-> " << it->first; + std::cerr << std::endl; +#endif + + if(_node_ids.find(*sit) != _node_ids.end()) + ui.graphicsView->addEdge(_node_ids[*sit], it->second); + } + } + + _should_update = false ; +} + diff --git a/retroshare-gui/src/gui/NetworkView.h b/retroshare-gui/src/gui/NetworkView.h new file mode 100644 index 000000000..eec403ab4 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkView.h @@ -0,0 +1,67 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _NETWORK_VIEW_H +#define _NETWORK_VIEW_H + +#include + +#include "RsAutoUpdatePage.h" +#include "ui_NetworkView.h" + + +class NetworkView : public RsAutoUpdatePage +{ + Q_OBJECT + + public: + NetworkView(QWidget *parent = 0); + virtual ~NetworkView(); + + virtual void updateDisplay() ; // derived from RsAutoUpdatePage + + public slots: + void update() ; + + private slots: + + void setMaxFriendLevel(int) ; + void setEdgeLength(int) ; + + void changedFoFCheckBox( ); + void redraw(); + + private: + + void clear(); + + QGraphicsScene *mScene; + + /** Qt Designer generated object */ + Ui::NetworkView ui; + int _max_friend_level ; + std::map _node_ids ; + + bool _should_update ; +}; + +#endif + diff --git a/retroshare-gui/src/gui/NetworkView.ui b/retroshare-gui/src/gui/NetworkView.ui new file mode 100644 index 000000000..e389b63d3 --- /dev/null +++ b/retroshare-gui/src/gui/NetworkView.ui @@ -0,0 +1,111 @@ + + + NetworkView + + + + 0 + 0 + 616 + 499 + + + + + 6 + + + 2 + + + 0 + + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + + + 9 + + + 6 + + + + + Redraw + + + + + + + Qt::Horizontal + + + + 391 + 23 + + + + + + + + 0 + + + 2 + + + 1 + + + + + + + Friendship level: + + + + + + + 10 + + + 200 + + + 50 + + + + + + + Edge length: + + + + + + + + + + GraphWidget + QGraphicsView +
    gui/elastic/graphwidget.h
    +
    +
    + + +
    diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp new file mode 100644 index 000000000..ef8e4e794 --- /dev/null +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -0,0 +1,497 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "NewsFeed.h" + +#include +#include + +#include "feeds/ChanNewItem.h" +#include "feeds/ChanMsgItem.h" +#include "feeds/ForumNewItem.h" +#include "feeds/ForumMsgItem.h" +#include "settings/rsettingswin.h" + +#ifdef BLOGS +#include "feeds/BlogNewItem.h" +#include "feeds/BlogMsgItem.h" +#endif + +#include "feeds/MsgItem.h" +#include "feeds/PeerItem.h" +#include "feeds/ChatMsgItem.h" + +#include "settings/rsharesettings.h" +#include "chat/PopupChatDialog.h" + +const uint32_t NEWSFEED_PEERLIST = 0x0001; +const uint32_t NEWSFEED_FORUMNEWLIST = 0x0002; +const uint32_t NEWSFEED_FORUMMSGLIST = 0x0003; +const uint32_t NEWSFEED_CHANNEWLIST = 0x0004; +const uint32_t NEWSFEED_CHANMSGLIST = 0x0005; +const uint32_t NEWSFEED_BLOGNEWLIST = 0x0006; +const uint32_t NEWSFEED_BLOGMSGLIST = 0x0007; +const uint32_t NEWSFEED_MESSAGELIST = 0x0008; +const uint32_t NEWSFEED_CHATMSGLIST = 0x0009; + +/***** + * #define NEWS_DEBUG 1 + ****/ + +/** Constructor */ +NewsFeed::NewsFeed(QWidget *parent) +: MainPage (parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + connect(removeAllButton, SIGNAL(clicked()), this, SLOT(removeAll())); + connect(feedOptionsButton, SIGNAL(clicked()), this, SLOT(feedoptions())); + + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(updateFeed())); + timer->start(1000); +} + + + +void NewsFeed::updateFeed() +{ + if (!rsNotify) + return; + + uint flags = Settings->getNewsFeedFlags(); + + /* check for new messages */ + RsFeedItem fi; + if (rsNotify->GetFeedItem(fi)) + { + switch(fi.mType) + { + case RS_FEED_ITEM_PEER_CONNECT: + if (flags & RS_FEED_TYPE_PEER) + addFeedItemPeerConnect(fi); + break; + case RS_FEED_ITEM_PEER_DISCONNECT: + if (flags & RS_FEED_TYPE_PEER) + addFeedItemPeerDisconnect(fi); + break; + case RS_FEED_ITEM_PEER_NEW: + if (flags & RS_FEED_TYPE_PEER) + addFeedItemPeerNew(fi); + break; + case RS_FEED_ITEM_PEER_HELLO: + if (flags & RS_FEED_TYPE_PEER) + addFeedItemPeerHello(fi); + break; + + case RS_FEED_ITEM_CHAN_NEW: + if (flags & RS_FEED_TYPE_CHAN) + addFeedItemChanNew(fi); + break; + case RS_FEED_ITEM_CHAN_UPDATE: + if (flags & RS_FEED_TYPE_CHAN) + addFeedItemChanUpdate(fi); + break; + case RS_FEED_ITEM_CHAN_MSG: + if (flags & RS_FEED_TYPE_CHAN) + addFeedItemChanMsg(fi); + break; + + case RS_FEED_ITEM_FORUM_NEW: + if (flags & RS_FEED_TYPE_FORUM) + addFeedItemForumNew(fi); + break; + case RS_FEED_ITEM_FORUM_UPDATE: + if (flags & RS_FEED_TYPE_FORUM) + addFeedItemForumUpdate(fi); + break; + case RS_FEED_ITEM_FORUM_MSG: + if (flags & RS_FEED_TYPE_FORUM) + addFeedItemForumMsg(fi); + break; + + case RS_FEED_ITEM_BLOG_NEW: + if (flags & RS_FEED_TYPE_BLOG) + addFeedItemBlogNew(fi); + break; + case RS_FEED_ITEM_BLOG_MSG: + if (flags & RS_FEED_TYPE_BLOG) + addFeedItemBlogMsg(fi); + break; + case RS_FEED_ITEM_CHAT_NEW: + if (flags & RS_FEED_TYPE_CHAT) + addFeedItemChatNew(fi); + break; + case RS_FEED_ITEM_MESSAGE: + if (flags & RS_FEED_TYPE_MSG) + addFeedItemMessage(fi); + break; + case RS_FEED_ITEM_FILES_NEW: + if (flags & RS_FEED_TYPE_FILES) + addFeedItemFilesNew(fi); + break; + default: + break; + } + } +} + +void NewsFeed::addFeedItem(QWidget *item) +{ + item->setAttribute(Qt::WA_DeleteOnClose, true); + + connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(itemDestroyed(QObject*))); + widgetList.push_back(item); + + sendNewsFeedChanged(); + + if (Settings->getAddFeedsAtEnd()) { + verticalLayout->addWidget(item); + } else { + verticalLayout->insertWidget(0, item); + } +} + +void NewsFeed::addFeedItemPeerConnect(RsFeedItem &fi) +{ + /* make new widget */ + PeerItem *pi = new PeerItem(this, NEWSFEED_PEERLIST, fi.mId1, PEER_TYPE_CONNECT, false); + + /* store */ + + /* add to layout */ + addFeedItem(pi); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemPeerConnect()"; + std::cerr << std::endl; +#endif + +} + + +void NewsFeed::addFeedItemPeerDisconnect(RsFeedItem &fi) +{ + /* make new widget */ + PeerItem *pi = new PeerItem(this, NEWSFEED_PEERLIST, fi.mId1, PEER_TYPE_STD, false); + + /* store */ + + /* add to layout */ + addFeedItem(pi); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemPeerDisconnect()"; + std::cerr << std::endl; +#endif +} + + +void NewsFeed::addFeedItemPeerHello(RsFeedItem &fi) +{ + /* make new widget */ + PeerItem *pi = new PeerItem(this, NEWSFEED_PEERLIST, fi.mId1, PEER_TYPE_HELLO, false); + + /* store */ + + /* add to layout */ + addFeedItem(pi); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemPeerHello()"; + std::cerr << std::endl; +#endif +} + + +void NewsFeed::addFeedItemPeerNew(RsFeedItem &fi) +{ + /* make new widget */ + PeerItem *pi = new PeerItem(this, NEWSFEED_PEERLIST, fi.mId1, PEER_TYPE_NEW_FOF, false); + + /* store */ + + /* add to layout */ + addFeedItem(pi); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemPeerNew()"; + std::cerr << std::endl; +#endif +} + + +void NewsFeed::addFeedItemChanNew(RsFeedItem &fi) +{ + /* make new widget */ + ChanNewItem *cni = new ChanNewItem(this, NEWSFEED_CHANNEWLIST, fi.mId1, false, true); + + /* store in list */ + + /* add to layout */ + addFeedItem(cni); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemChanNew()"; + std::cerr << std::endl; +#endif +} + + +void NewsFeed::addFeedItemChanUpdate(RsFeedItem &fi) +{ + /* make new widget */ + ChanNewItem *cni = new ChanNewItem(this, NEWSFEED_CHANNEWLIST, fi.mId1, false, false); + + /* store in list */ + + /* add to layout */ + addFeedItem(cni); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemChanUpdate()"; + std::cerr << std::endl; +#endif +} + + +void NewsFeed::addFeedItemChanMsg(RsFeedItem &fi) +{ + /* make new widget */ + ChanMsgItem *cm = new ChanMsgItem(this, NEWSFEED_CHANMSGLIST, fi.mId1, fi.mId2, false); + + /* store in forum list */ + + /* add to layout */ + addFeedItem(cm); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemChanMsg()"; + std::cerr << std::endl; +#endif +} + + +void NewsFeed::addFeedItemForumNew(RsFeedItem &fi) +{ + /* make new widget */ + ForumNewItem *fni = new ForumNewItem(this, NEWSFEED_FORUMNEWLIST, fi.mId1, false, true); + + /* store in forum list */ + mForumNewItems.push_back(fni); + + /* add to layout */ + addFeedItem(fni); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemForumNew()"; + std::cerr << std::endl; +#endif +} + + +void NewsFeed::addFeedItemForumUpdate(RsFeedItem &fi) +{ + /* make new widget */ + ForumNewItem *fni = new ForumNewItem(this, NEWSFEED_FORUMNEWLIST, fi.mId1, false, false); + + /* store in forum list */ + mForumNewItems.push_back(fni); + + /* add to layout */ + addFeedItem(fni); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemForumUpdate()"; + std::cerr << std::endl; +#endif +} + + +void NewsFeed::addFeedItemForumMsg(RsFeedItem &fi) +{ + /* make new widget */ + ForumMsgItem *fm = new ForumMsgItem(this, NEWSFEED_FORUMMSGLIST, fi.mId1, fi.mId2, false); + + /* store in forum list */ + + /* add to layout */ + addFeedItem(fm); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemForumMsg()"; + std::cerr << std::endl; +#endif +} + +void NewsFeed::addFeedItemBlogNew(RsFeedItem &fi) +{ +#ifdef BLOGS + /* make new widget */ + BlogNewItem *bni = new BlogNewItem(this, NEWSFEED_BLOGNEWLIST, fi.mId1, false, true); + + /* store in list */ + + /* add to layout */ + addFeedItem(bni); +#endif + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemBlogNew()"; + std::cerr << std::endl; +#endif +} + +void NewsFeed::addFeedItemBlogMsg(RsFeedItem &fi) +{ +#ifdef BLOGS + /* make new widget */ + BlogMsgItem *bm = new BlogMsgItem(this, NEWSFEED_BLOGMSGLIST, fi.mId1, fi.mId2, false); + + /* store in forum list */ + + /* add to layout */ + addFeedItem(bm); +#endif + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemBlogMsg()"; + std::cerr << std::endl; +#endif +} + + +void NewsFeed::addFeedItemChatNew(RsFeedItem &fi) +{ +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemChatNew()"; + std::cerr << std::endl; +#endif + + if (fi.mId1 == rsPeers->getOwnId()) { + /* chat message from myself */ + return; + } + + /* make new widget */ + ChatMsgItem *cm = new ChatMsgItem(this, NEWSFEED_CHATMSGLIST, fi.mId1, fi.mId2, true); + + /* store in forum list */ + + /* add to layout */ + addFeedItem(cm); +} + +void NewsFeed::addFeedItemMessage(RsFeedItem &fi) +{ + /* make new widget */ + MsgItem *mi = new MsgItem(this, NEWSFEED_MESSAGELIST, fi.mId1, false); + + /* store in list */ + + /* add to layout */ + addFeedItem(mi); + +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemMessage()"; + std::cerr << std::endl; +#endif +} + +void NewsFeed::addFeedItemFilesNew(RsFeedItem &fi) +{ +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::addFeedItemFilesNew()"; + std::cerr << std::endl; +#endif +} + +/* FeedHolder Functions (for FeedItem functionality) */ +void NewsFeed::deleteFeedItem(QWidget *item, uint32_t type) +{ +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::deleteFeedItem()"; + std::cerr << std::endl; +#endif + + if (item) { + item->close (); + } +} + +void NewsFeed::openChat(std::string peerId) +{ +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::openChat()"; + std::cerr << std::endl; +#endif + + PopupChatDialog::chatFriend(peerId); +} + +void NewsFeed::itemDestroyed(QObject *item) +{ + int index = widgetList.indexOf(item); + if (index >= 0) { + widgetList.removeAt(index); + } + + sendNewsFeedChanged(); +} + +void NewsFeed::removeAll() +{ +#ifdef NEWS_DEBUG + std::cerr << "NewsFeed::removeAll()" << std::endl; +#endif + while (widgetList.count()) { + QObject *item = widgetList.first(); + widgetList.pop_front(); + + if (item) { + item->deleteLater(); + } + } +} + +void NewsFeed::sendNewsFeedChanged() +{ + int count = 0; + + QObjectList::iterator it; + for (it = widgetList.begin(); it != widgetList.end(); it++) { + if (dynamic_cast(*it) == NULL) { + /* don't count PeerItem's */ + count++; + } + } + + emit newsFeedChanged(count); +} + +void NewsFeed::feedoptions() +{ + RSettingsWin::showYourself(this, RSettingsWin::Notify); +} diff --git a/retroshare-gui/src/gui/NewsFeed.h b/retroshare-gui/src/gui/NewsFeed.h new file mode 100644 index 000000000..83cbac0c0 --- /dev/null +++ b/retroshare-gui/src/gui/NewsFeed.h @@ -0,0 +1,94 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _NEWS_FEED_DIALOG_H +#define _NEWS_FEED_DIALOG_H + +#include "mainpage.h" +#include "ui_NewsFeed.h" + +#include "gui/feeds/FeedHolder.h" +class RsFeedItem; + +class ForumNewItem; +class ChanMsgItem; +class ChatMsgItem; + +class NewsFeed : public MainPage, public FeedHolder, private Ui::NewsFeed +{ + Q_OBJECT + +public: + /** Default Constructor */ + NewsFeed(QWidget *parent = 0); + /** Default Destructor */ + + /* FeedHolder Functions (for FeedItem functionality) */ + virtual void deleteFeedItem(QWidget *item, uint32_t type); + virtual void openChat(std::string peerId); + +signals: + void newsFeedChanged(int count); + +private slots: + // void toggleChanMsgItems(bool on); + void feedoptions(); + + void updateFeed(); + void removeAll(); + void itemDestroyed(QObject*); + +private: + void addFeedItem(QWidget *item); + + void addFeedItemPeerConnect(RsFeedItem &fi); + void addFeedItemPeerDisconnect(RsFeedItem &fi); + void addFeedItemPeerNew(RsFeedItem &fi); + void addFeedItemPeerHello(RsFeedItem &fi); + void addFeedItemChanNew(RsFeedItem &fi); + void addFeedItemChanUpdate(RsFeedItem &fi); + void addFeedItemChanMsg(RsFeedItem &fi); + void addFeedItemForumNew(RsFeedItem &fi); + void addFeedItemForumUpdate(RsFeedItem &fi); + void addFeedItemForumMsg(RsFeedItem &fi); + void addFeedItemBlogNew(RsFeedItem &fi); + void addFeedItemBlogMsg(RsFeedItem &fi); + void addFeedItemChatNew(RsFeedItem &fi); + void addFeedItemMessage(RsFeedItem &fi); + void addFeedItemFilesNew(RsFeedItem &fi); + + void sendNewsFeedChanged(); + + QLayout *mLayout; + QObjectList widgetList; + + /* lists of feedItems */ + std::list mForumNewItems; + + std::list mChanMsgItems; + +}; + + + +#endif + + diff --git a/retroshare-gui/src/gui/NewsFeed.ui b/retroshare-gui/src/gui/NewsFeed.ui new file mode 100644 index 000000000..70d393f7f --- /dev/null +++ b/retroshare-gui/src/gui/NewsFeed.ui @@ -0,0 +1,163 @@ + + + NewsFeed + + + + 0 + 0 + 428 + 256 + + + + + 0 + + + 0 + + + + + 6 + + + 6 + + + 0 + + + 6 + + + 0 + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/konqsidebar_news16.png" /></p></body></html> + + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 424 + 229 + + + + + 0 + + + 0 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Remove All + + + + + + + Qt::Horizontal + + + + 321 + 13 + + + + + + + + Options + + + + + + + + diff --git a/retroshare-gui/src/gui/PluginManager.cpp b/retroshare-gui/src/gui/PluginManager.cpp new file mode 100644 index 000000000..e3801dafe --- /dev/null +++ b/retroshare-gui/src/gui/PluginManager.cpp @@ -0,0 +1,350 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include + +#include //a strange thing: it compiles without this header, but + //then segfaults in some place + +#include + +#include "PluginManager.h" +#include "PluginManagerWidget.h" +#include "plugins/PluginInterface.h" +#include "rshare.h" + +//============================================================================= +//============================================================================= +//============================================================================= + +PluginManager::PluginManager() +{ + baseFolder = //qApp->applicationDirPath()+"///plugins" ; +Rshare::dataDirectory() + "/plugins" ; + lastError = "No error."; + + viewWidget = 0; + +// defaultLoad(); +} + +//============================================================================= + +void +PluginManager::defaultLoad( ) +{ + qDebug() << " " << "Default load started" ; + + QDir workDir(baseFolder); + + if ( !workDir.exists() ) + { + QString em= QString("base folder %1 doesn't exist, default load failed") + .arg( baseFolder ); + emit errorAppeared( em ); + return ; + } + + //=== get current available plugins ===== + QStringList currAvailable = workDir.entryList(QDir::Files); +#if defined(Q_OS_WIN) + QRegExp trx("*.dll") ; +#else + QRegExp trx("*.so"); +#endif + trx.setPatternSyntax(QRegExp::Wildcard ); + + currAvailable.filter( trx ); + + qDebug() << " " << "can load this plugins: " << currAvailable ; + + //=== + foreach(QString pluginFileName, currAvailable) + { + QString fullfn( workDir.absoluteFilePath( pluginFileName ) ); + QString newName; + int ti = readPluginInformation( fullfn, newName); + if (! ti ) + { + acceptPlugin(fullfn, newName); + } + }// foreach(QString pluginFileName, currAvailable) + + qDebug() << " " << "names are " << names; +} + +//============================================================================= + +int +PluginManager::readPluginInformation(QString fullFileName, QString& pluginName) +{ + qDebug() << " " << "processing file " << fullFileName; + + PluginInterface* plugin = loadPluginInterface(fullFileName) ; + pluginName = "Undefined name" ; + if (plugin) + { + pluginName = plugin->pluginName(); + qDebug() << " " << "got pluginName:" << pluginName; + delete plugin; + return 0 ; + } + else + { + //do not emit anything, cuz error message already was sent + //from loadPluginInterface(..) + return 1; //this means, some rrror appeared + } +} + +//============================================================================= + +PluginInterface* +PluginManager::loadPluginInterface(QString fileName) +{ + QString errorMessage = "Default Error Message" ; + PluginInterface* plugin = 0 ; + QPluginLoader* plLoader = new QPluginLoader(fileName); + + QObject *pluginObject = plLoader->instance(); + if (pluginObject) + { + //qDebug() << " " << "loaded..." ; + plugin = qobject_cast (pluginObject) ; + + if (plugin) + { + errorMessage = "No error" ; + } + else + { + errorMessage = "Cast to 'PluginInterface*' failed"; + emit errorAppeared( errorMessage ); + } + } + else + { + errorMessage = "Istance wasn't created: " + plLoader->errorString() ; + emit errorAppeared( errorMessage ); + } + + delete plLoader; // plugin instance will not be deleted with this action + return plugin; +} + +//============================================================================= + +PluginManager:: ~PluginManager() +{ +} + +//============================================================================= + +void +PluginManager::acceptPlugin(QString fileName, QString pluginName) +{ + qDebug() << " " << "accepting plugin " << pluginName; + + names.append(pluginName); + fileNames.append(fileName); + + if (viewWidget) + viewWidget->registerNewPlugin( pluginName ); + + emit newPluginRegistered( pluginName ); +} + +//============================================================================= + +QWidget* +PluginManager::pluginWidget(QString pluginName) +{ + QWidget* result = 0; + int plIndex = names.indexOf( pluginName ) ; + if (plIndex >=0 ) + { + //=== load plugin's interface + QString fn = fileNames.at(plIndex); + PluginInterface* pliface = loadPluginInterface(fn); + if (pliface) + { + //=== now, get a widget + result = pliface->pluginWidget() ; + if (result) + { + // all was good, + qDebug() << " " << "got plg widget..." ; + return result; + } + else + { + QString em=QString("Error: instance '%1'can't create a widget") + .arg( pluginName ); + emit errorAppeared( em ); + return 0; + } + } + else + { + // do nothing here... + } + } + else + { + QString em = QString("Error: no plugin with name '%1' found") + .arg(pluginName); + emit errorAppeared( em ); + } +} + +//============================================================================= + +QWidget* +PluginManager::getViewWidget(QWidget* parent ) +{ + if (viewWidget) + return viewWidget; + + //=== else, create the viewWidget and return it + // + viewWidget = new PluginManagerWidget(); + + foreach(QString pn, names) + { + qDebug() << " " << "reg new plg " << pn; + viewWidget->registerNewPlugin( pn ); + } + + connect(this , SIGNAL( errorAppeared(QString) ) , + viewWidget, SLOT( acceptErrorMessage( QString))); + + connect(viewWidget, SIGNAL( destroyed() ) , + this , SLOT( viewWidgetDestroyed( ))); + + connect(viewWidget, SIGNAL( installPluginRequested(QString)), + this , SLOT( installPlugin( QString))); + + connect(viewWidget, SIGNAL( removeRequested( QString ) ), + this , SLOT( removePlugin(QString ))); + + + + + qDebug() << " PluginManager::getViewWidget done"; + + return viewWidget; +} + +//============================================================================= + +void +PluginManager::viewWidgetDestroyed(QObject* obj ) +{ + qDebug() << " PluginManager::viewWidgetDestroyed is here"; + + viewWidget = 0; +} + +//============================================================================= + +void +PluginManager::removePlugin(QString pluginName) +{ + QWidget* result = 0; + int plIndex = names.indexOf( pluginName ) ; + if (plIndex >=0 ) + { + QString fn = fileNames.at(plIndex); + if (QDir::isRelativePath(fn)) + fn = QDir(baseFolder).path() + QDir::separator() + fn ; + + QFile fl(fn); + if (!fl.remove()) + { + QString em = QString("Error: failed to revove file %1" + "(uninstalling plugin '%2')") + .arg(fn).arg(pluginName); + emit errorAppeared( em); + } + else + { + if (viewWidget) + viewWidget->removePluginFrame( pluginName); + } + } + else + { + QString em = QString("Error(uninstall): no plugin with name '%1' found") + .arg(pluginName); + emit errorAppeared( em ); + } +} + +//============================================================================= + +void +PluginManager::installPlugin(QString fileName) +{ + qDebug() << " " << "PluginManager::installPlugin is here" ; + + if (!QFile::exists( fileName) ) + { + QString em = QString("Error(installation): flugin file %1 doesn't exist") + .arg( fileName ); + + emit errorAppeared( em ); + return ; + } + + QString pn; + if (! readPluginInformation(fileName, pn)) + { + QFile sf( fileName) ; + QString newFileName = baseFolder + QDir::separator() + + QFileInfo( fileName).fileName(); + if ( QFile::copy( fileName, newFileName ) ) + { + QString pn; + int ti = readPluginInformation( newFileName , pn ); + if (! ti ) + { + acceptPlugin(newFileName, pn); + } + } // + else + { + QString em = QString("Error: can't copy %1 as %2") + .arg(fileName, newFileName) ; + emit errorAppeared( em ); + } + } + else + { +// do nothing here: read plugin information emits its own error + } +} + +//============================================================================= + diff --git a/retroshare-gui/src/gui/PluginManager.h b/retroshare-gui/src/gui/PluginManager.h new file mode 100644 index 000000000..229072e4e --- /dev/null +++ b/retroshare-gui/src/gui/PluginManager.h @@ -0,0 +1,148 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _PLUGIN_MANAGER_H_ +#define _PLUGIN_MANAGER_H_ + +#include + +#include +#include +#include + +#include + +#include + +class PluginInterface; +class PluginManagerWidget; + +//! An engine for plugins management + +//! This class performs oaa plugin management operations: installing, +//! loading, remowing. it also provides a PluginManagerWidget for controlling +//! itself. I supose, a appication has to create a global instance of the class, +//! so all pages (instances of the MainPage class) could receive plugin widgets. +class PluginManager: public QObject +{ + Q_OBJECT + +public: + PluginManager(); + ~PluginManager(); + + //! Checks up 'plugins' folder for loadable plugins + + //! This is a separate method, becouse an application should create + //! a PluginManager instance, then connect all its signals, optionally + //! create a view widget, and only after all perform lookup + void defaultLoad( ) ; + + //! GUI for the loader. + + //! Returns a PluginManagerWidget instance. When called for the first time, + //! creates a new object; after that returns pointer to the same instance. + //! After the instance was deleteted (it could be safely done in usual way) + //! may create a new one. + QWidget* getViewWidget(QWidget* parent = 0); + + //! Loads a widget of the plugin with given name + + //! Loads a new copy (called twice will return different objects) of the + //! plugin widget. If there is no plugin with given name, returns 0 (also + //! emits errorAppeared(..) with an error description). + //! PluginManager provides ablolutely no control over returned widget; + //! the application should delete it, like all other widgets + QWidget* pluginWidget(QString pluginName); + + //! returns last error appeared; + + //! Sorry, doesn't work in current implementation + QString getLastError(); + +public slots: + //! processes the desctucrion of the view widget; + void viewWidgetDestroyed(QObject * obj = 0); + + //! processes the plugin installation request + + //! After successful installatio a newPluginRegistered(..) signal will be + //! emitted. On some error -- errorAppeared(..) will be emitted; + //! 'Installation' means that plgin file (dll or so) will be checked and + //! copied to the 'plugins' directory. Later, in pluginWidget(..) call this + //! copy will be used + void installPlugin(QString fileName); + + //! Processes plugin remove request + + //! 'Remove' means that plugin file (so or dll) will be physically deleted + //! from 'plugins' folder. + void removePlugin(QString pluginName); + +signals: + //! PluginManager emits this signal on every error; + + //! This signal is connected to the PluginManagerWidget::acceptErrorMessage. + //! So, all error messages will appear on the view widget (only if that one + //! was created, of course) + void errorAppeared(QString errorDescription); + + //! Is emitted after plugin removing; + + //! Already loaded plugin widgets, will not be deleted. Nobody will touch + //! them + void pluginRemoveCompleted(QString pluginName); + + //! Is emitted for every loadable plugin + + void newPluginRegistered(QString pluginName); + +protected: + PluginManagerWidget* viewWidget; + + QStringList fileNames; + QStringList names; + + QString baseFolder; + QString lastError; + + //! Reads information from plugin file + + //! The function tries to read the info from the plugin file (in current + //! implementation only pluginName). + //! \returns 0 on success, error code (>0) on fail + int readPluginInformation( QString fileName, QString& pluginName); + + //! --- + + //! Adds plugin name and plugin filename to the lists, emits nesessary + //! signals, updates the view widget + void acceptPlugin( QString fileName, QString pluginName); + + + PluginInterface* loadPluginInterface(QString fileName ) ; + +}; + + +#endif + + diff --git a/retroshare-gui/src/gui/PluginManagerWidget.cpp b/retroshare-gui/src/gui/PluginManagerWidget.cpp new file mode 100644 index 000000000..b017bf700 --- /dev/null +++ b/retroshare-gui/src/gui/PluginManagerWidget.cpp @@ -0,0 +1,207 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "PluginManagerWidget.h" + +#include +#include +#include +#include +#include +#include + + +#include +#include + +#include "PluginManagerWidget.h" + +//============================================================================= +//============================================================================= +//============================================================================= +PluginFrame::PluginFrame( QString pluginName, QWidget * parent) + :QFrame(parent) +{ + plgName = pluginName; + + // labels + labelsLay = new QVBoxLayout() ; + nameLabel = new QLabel(); + nameLabel->setText(pluginName); + nameLabel->setAlignment(Qt::AlignHCenter); + labelsLay->addWidget(nameLabel); + descrLabel = new QLabel(); + descrLabel->setText("# # # # # # # # # #"); +// "plugin description will appear here someday"); + descrLabel->setWordWrap(true); + labelsLay->addWidget(descrLabel); + + // buttons + buttonsLay = new QVBoxLayout() ; + + removeBtn = new QPushButton() ; + removeBtn->setText( tr("Remove") ) ; + connect( removeBtn, SIGNAL( clicked() ) , + this , SLOT ( removeButtonClicked() ) ) ; + buttonsLay->addWidget( removeBtn ) ; + + //all together + mainLay = new QHBoxLayout(this); + mainLay->addLayout(labelsLay); + mainLay->addLayout(buttonsLay); + + this->setFrameStyle(QFrame::Box | QFrame::Raised); +} + +//============================================================================= + +PluginFrame::~PluginFrame() +{ + //nothing to do here at this moment +} + +//============================================================================= + +void +PluginFrame::removeButtonClicked() +{ + emit needToRemove( plgName ); +} + +//============================================================================= + +QString +PluginFrame::getPluginName() +{ + return plgName ; +} + +//============================================================================= +//============================================================================= +//============================================================================= + +PluginManagerWidget::PluginManagerWidget(QWidget * parent) + :QFrame(parent) +{ + qDebug() << " " << "PluginManagerWidget::PluginManagerWidget here"; + + mainLayout = new QVBoxLayout(this); + + //=== + installPluginLayout = new QHBoxLayout(); + installPluginButton = new QPushButton(); + + installPluginButton->setText(tr("Install New Plugin...")); + connect( installPluginButton, SIGNAL( clicked() ), + this , SLOT( installPluginButtonClicked() ) ); + installPluginLayout->addWidget(installPluginButton); + installPluginSpacer = new QSpacerItem(283, 20, + QSizePolicy::Expanding, QSizePolicy::Minimum); + installPluginLayout->addItem(installPluginSpacer); + + mainLayout->addLayout( installPluginLayout ); + + //=== + pluginFramesContainer = new QFrame(); + pluginFramesLayout = new QVBoxLayout(pluginFramesContainer); + + mainLayout->addWidget(pluginFramesContainer); + + //=== + errorsConsole = new QTextEdit(); + + mainLayout->addWidget( errorsConsole ); + + qDebug() << " " << "PluginManagerWidget::PluginManagerWidget done"; +} + +//============================================================================= + +PluginManagerWidget::~PluginManagerWidget() +{ + //nothing to do here +} + +//============================================================================= + +void +PluginManagerWidget::registerNewPlugin(QString pluginName) +{ + qDebug() << " " << "PluginManagerWidget::registerNewPlugin "<< pluginName; + + PluginFrame* pf = new PluginFrame(pluginName, pluginFramesContainer) ; + + connect( pf , SIGNAL( needToRemove(QString)), + this, SIGNAL( removeRequested(QString) ) ); + + pluginFramesLayout->addWidget(pf); +} + +//============================================================================= + +void +PluginManagerWidget::installPluginButtonClicked() +{ + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open Plugin to install"), + "./", + tr("Plugins (*.so *.dll)")); + if (!fileName.isNull()) + { + emit installPluginRequested(fileName); + } +} + +//============================================================================= + +void +PluginManagerWidget::removePluginFrame(QString pluginName) +{ + foreach(QObject* ob, pluginFramesContainer->children()) + { + PluginFrame* pf = qobject_cast (ob); + if (pf) + { + if (pf->getPluginName() == pluginName ) + { + pf->setParent(0); + delete pf; + return ; + } + } + } + + // normally unreachable place + QString em = QString("Widget for plugin %1 not found on plugins frame") + .arg( pluginName ) ; + acceptErrorMessage( em ); +} + +//============================================================================= + +void +PluginManagerWidget::acceptErrorMessage(QString errorMessage) +{ + errorsConsole->append( errorMessage ); +} + +//============================================================================= + diff --git a/retroshare-gui/src/gui/PluginManagerWidget.h b/retroshare-gui/src/gui/PluginManagerWidget.h new file mode 100644 index 000000000..d67f1eb90 --- /dev/null +++ b/retroshare-gui/src/gui/PluginManagerWidget.h @@ -0,0 +1,116 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _PLUGIN_MANAGER_WIDGET_ +#define _PLUGIN_MANAGER_WIDGET_ + +#include + +#include + +class QWidget; +class QLabel; +class QHBoxLayout; +class QVBoxLayout; +class QPushButton; +class QSpacerItem; +class QTextEdit; + +//============================================================================= + +class PluginFrame : public QFrame +{ + Q_OBJECT + +public: + PluginFrame( QString pluginName, QWidget* parent =0 ); + virtual ~PluginFrame(); + + QString getPluginName(); + +signals: + void needToRemove(QString pluginName); + +protected slots: + void removeButtonClicked(); + +protected: + QString plgName; + + QPushButton* removeBtn; + QVBoxLayout* buttonsLay; + + QHBoxLayout* mainLay; // main layout for the frame + + QVBoxLayout* labelsLay; + QLabel* nameLabel; + QLabel* descrLabel; + +}; + +//============================================================================= + +//! GUI representation of the PluginManager class + +//! This is something like GUI for PluginManager class. Or you can think +//! about PluginManagerWidget as a view, and a PluginManager as a model. +//! Instances should be created only by PluginManager class; maybe later i'll +//! hide constructor in some way. Parent (or somebody else) can delete it. +//! Widget itself can be used anywere, in some 'settings' dialogs. +class PluginManagerWidget: public QFrame +{ + Q_OBJECT + +public: + PluginManagerWidget(QWidget* parent =0); + virtual ~PluginManagerWidget(); + + void registerNewPlugin(QString pluginName); + void removePluginFrame(QString pluginName); + +signals: + void removeRequested(QString pluginName); + void installPluginRequested(QString fileName) ; + +public slots: + void acceptErrorMessage(QString errorMessage); + +protected slots: + +protected: + QVBoxLayout* mainLayout; + QFrame* pluginFramesContainer; + QVBoxLayout* pluginFramesLayout; + + QPushButton* installPluginButton; + QHBoxLayout* installPluginLayout; + QSpacerItem* installPluginSpacer; + + QTextEdit* errorsConsole; + +protected slots: + void installPluginButtonClicked(); +}; + +//============================================================================= + +#endif + diff --git a/retroshare-gui/src/gui/PluginsPage.cpp b/retroshare-gui/src/gui/PluginsPage.cpp new file mode 100644 index 000000000..ef452727d --- /dev/null +++ b/retroshare-gui/src/gui/PluginsPage.cpp @@ -0,0 +1,100 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +//#include +//#include +//#include +#include +#include +#include + +//#include // for qApp->.... +//#include + +#include +#include + +#include "PluginsPage.h" +#include "PluginManager.h" + +//============================================================================== + +PluginsPage::PluginsPage(QWidget *parent ) +// :QGroupBox(parent) // this is for toy applications, do not remove + :MainPage(parent) // this for real retroshare app +{ + //=== + pluginManager = new PluginManager(); + connect( pluginManager, SIGNAL( newPluginRegistered(QString) ), + this , SLOT( pluginRegistered(QString) ) ); + + //=== create some gui elements ===== + pluginPageLayout = new QVBoxLayout(this); + +// this->setTitle("RetroShare plugins"); + + pluginTabs = new QTabWidget(this) ; + pluginPageLayout->addWidget(pluginTabs); + + pmFrame = new QFrame(this); + pmLay = new QVBoxLayout(pmFrame); + + QWidget* tw = pluginManager->getViewWidget(); + + pmLay->addWidget( tw ); + + pmSpacer = new QSpacerItem(283, 20, + QSizePolicy::Expanding, QSizePolicy::Minimum); + pmLay->addItem(pmSpacer); + + pluginTabs->addTab( pmFrame, "Manager" ) ; + + + pluginManager->defaultLoad( ) ; +} + +//============================================================================== + +PluginsPage::~PluginsPage() +{ + delete pluginManager; +} + +//============================================================================= + +void +PluginsPage::pluginRegistered(QString pluginName) +{ + // + QWidget* pw = pluginManager->pluginWidget( pluginName); + + pluginTabs->addTab( pw , pluginName ); +} + +//============================================================================== diff --git a/retroshare-gui/src/gui/PluginsPage.h b/retroshare-gui/src/gui/PluginsPage.h new file mode 100644 index 000000000..de90a3d8f --- /dev/null +++ b/retroshare-gui/src/gui/PluginsPage.h @@ -0,0 +1,86 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _PLUGINS_PAGE_H_ +#define _PLUGINS_PAGE_H_ + +#include "mainpage.h" + +#include +#include +#include + +class QVBoxLayout; +class QTabWidget; +class QFrame; +class QLabel; +class QTextEdit; +class QSpacerItem; + +class QScriptEngine; + +class PluginManager; + + +//! A demo widget for showing plugin engine in action :) + +//! In current version this is just a container for PluginManagerWidget and +//! loaded plugin widgets. All specific actions moved to +//! PluginManagerWidget class. It contains a PluginManager instance, but it's +//! supposed that in future a pluginManager will become a global variable +class PluginsPage : public MainPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + PluginsPage(QWidget *parent = 0); + /** Default Destructor */ + virtual ~PluginsPage() ; + +public slots: + //! A slot for processing new plugin registration events. + + //! Every page, which supports plugins, has to process + //! the PluginManager::newPluginRegistered signal. Suppose, the page knows, + //! that there is a possible plugin "PuzzleGame"; Then, the page should + //! compare received pluginName with "PuzzleGame", and request the plugin + //! widget with PluginManager::pluginWidget(..) method + void pluginRegistered(QString pluginName); + +protected: + QVBoxLayout* pluginPageLayout; + QGroupBox* pluginPanel; + QVBoxLayout* pluginPanelLayout; + + //! Plugin widgets will be loaded into this tabs + QTabWidget* pluginTabs ; + + QVBoxLayout* pmLay; + QFrame* pmFrame; + QSpacerItem* pmSpacer; + + //! This should be global, every page should have access to it + PluginManager* pluginManager; +}; + +#endif + diff --git a/retroshare-gui/src/gui/QuickStartWizard.cpp b/retroshare-gui/src/gui/QuickStartWizard.cpp new file mode 100644 index 000000000..5dc9c316f --- /dev/null +++ b/retroshare-gui/src/gui/QuickStartWizard.cpp @@ -0,0 +1,538 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006-2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "QuickStartWizard.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "settings/rsharesettings.h" + + +QuickStartWizard::QuickStartWizard(QWidget *parent) : + QDialog(parent) +{ + ui.setupUi(this); + + ui.pagesWizard->setCurrentIndex(0); + + loadNetwork(); + loadShare(); + loadGeneral(); + + +// ui.checkBoxF2FRouting->setChecked(true) ; +// ui.checkBoxF2FRouting->setEnabled(false) ; + + connect( ui.netModeComboBox, SIGNAL( activated ( int ) ), this, SLOT( toggleUPnP( ) ) ); +// connect( ui.checkBoxTunnelConnection, SIGNAL( toggled( bool ) ), this, SLOT( toggleTunnelConnection(bool) ) ); + +// bool b = rsPeers->getAllowTunnelConnection() ; +// ui.checkBoxTunnelConnection->setChecked(b) ; + + ui.shareddirList->horizontalHeader()->setResizeMode( 0,QHeaderView::Stretch); + ui.shareddirList->horizontalHeader()->setResizeMode( 2,QHeaderView::Interactive); + + ui.shareddirList->horizontalHeader()->resizeSection( 0, 360 ); + ui.shareddirList->horizontalHeader()->setStretchLastSection(false); + + /* Hide platform specific features */ +#ifndef Q_WS_WIN + ui.checkBoxRunRetroshareAtSystemStartup->setVisible(false); + ui.chkRunRetroshareAtSystemStartupMinimized->setVisible(false); +#endif +} + +QuickStartWizard::~QuickStartWizard() +{ +} + +void QuickStartWizard::changeEvent(QEvent *e) +{ + switch (e->type()) { + case QEvent::LanguageChange: + ui.retranslateUi(this); + break; + default: + break; + } +} + +void QuickStartWizard::on_pushButtonWelcomeNext_clicked() +{ + ui.pagesWizard->setCurrentIndex(1); +} + +void QuickStartWizard::on_pushButtonWelcomeExit_clicked() +{ + close(); +} + +void QuickStartWizard::on_pushButtonConnectionBack_clicked() +{ + ui.pagesWizard->setCurrentIndex(0); +} + +void QuickStartWizard::on_pushButtonConnectionNext_clicked() +{ + /* Check if netMode has changed */ + int netMode = 0; + switch(ui.netModeComboBox->currentIndex()) + { + case 2: + netMode = RS_NETMODE_EXT; + break; + case 1: + netMode = RS_NETMODE_UDP; + break; + default: + case 0: + netMode = RS_NETMODE_UPNP; + break; + } + std::cerr << "ui.netModeComboBox->currentIndex()" << ui.netModeComboBox->currentIndex() << std::endl; + rsPeers->setNetworkMode(rsPeers->getOwnId(), netMode); + + /* Check if vis has changed */ + uint32_t visState = 0; + switch(ui.discoveryComboBox->currentIndex()) + { + case 0: + visState |= (RS_VS_DISC_ON | RS_VS_DHT_ON); + break; + case 1: + visState |= RS_VS_DISC_ON; + break; + case 2: + visState |= RS_VS_DHT_ON; + break; + case 3: + default: + break; + } + + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail)) + { + return; + } + if (visState != detail.visState) + { + rsPeers->setVisState(rsPeers->getOwnId(), visState); + } + rsicontrol->ConfigSetDataRates( ui.doubleSpinBoxDownloadSpeed->value(), ui.doubleSpinBoxUploadSpeed->value() ); + + if (ui.DynDNS->text().toStdString() != detail.dyndns) + rsPeers->setDynDNS (rsPeers->getOwnId(), ui.DynDNS->text().toStdString()); + + ui.pagesWizard->setCurrentIndex(2); +} + +void QuickStartWizard::on_pushButtonConnectionExit_clicked() +{ + on_pushButtonConnectionNext_clicked(); + close(); +} + +void QuickStartWizard::on_pushButtonSharesBack_clicked() +{ + ui.pagesWizard->setCurrentIndex(1); +} + +void QuickStartWizard::on_pushButtonSharesNext_clicked() +{ + ui.pagesWizard->setCurrentIndex(3); +} + +void QuickStartWizard::on_pushButtonSharesExit_clicked() +{ + close(); +} + +void QuickStartWizard::on_pushButtonSystemBack_clicked() +{ + ui.pagesWizard->setCurrentIndex(2); +} + +void QuickStartWizard::on_pushButtonSystemFinish_clicked() +{ + Settings->setStartMinimized(ui.checkBoxStartMinimized->isChecked()); + Settings->setValue("doQuit", ui.checkBoxQuit->isChecked()); +#ifdef Q_WS_WIN + Settings->setRunRetroshareOnBoot(ui.checkBoxRunRetroshareAtSystemStartup->isChecked(), ui.chkRunRetroshareAtSystemStartupMinimized->isChecked()); +#endif + + saveChanges(); + + close(); +} + +void QuickStartWizard::on_pushButtonSystemExit_clicked() +{ + close(); +} + +void QuickStartWizard::on_pushButtonSharesAdd_clicked() +{ +/* select a dir + */ + + QString qdir = QFileDialog::getExistingDirectory(this, tr("Select A Folder To Share"), "", + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + /* add it to the server */ + std::string dir = qdir.toStdString(); + if (dir != "") + { + SharedDirInfo sdi ; + sdi.filename = dir ; + sdi.shareflags = RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE ; + + rsFiles->addSharedDirectory(sdi); + + messageBoxOk(tr("Shared Directory Added!")); + loadShare(); + } +} + +void QuickStartWizard::on_pushButtonSharesRemove_clicked() +{ + /* id current dir */ + /* ask for removal */ + QTableWidget *listWidget = ui.shareddirList; + int row = listWidget -> currentRow(); + QTableWidgetItem *qdir = listWidget->item(row,0) ; + + QString queryWrn; + queryWrn.clear(); + queryWrn.append(tr("Do you really want to stop sharing this directory ? ")); + + if (qdir) + { + if ((QMessageBox::question(this, tr("Warning!"),queryWrn,QMessageBox::Ok|QMessageBox::No, QMessageBox::Ok))== QMessageBox::Ok) + { + rsFiles->removeSharedDirectory( qdir->text().toStdString()); + loadShare(); + } + else + return; + } +} + +void QuickStartWizard::on_shareIncomingDirectory_clicked() +{ + rsFiles->shareDownloadDirectory(ui.shareIncomingDirectory->isChecked()); + loadShare(); +} + +void QuickStartWizard::loadShare() +{ + std::cerr << "ShareManager:: In load !!!!!" << std::endl ; + + std::list::const_iterator it; + std::list dirs; + rsFiles->getSharedDirectories(dirs); + + ui.shareIncomingDirectory->setChecked(rsFiles->getShareDownloadDirectory()); + + /* get a link to the table */ + QTableWidget *listWidget = ui.shareddirList; + + /* remove old items ??? */ + listWidget->clearContents() ; + listWidget->setRowCount(0) ; + + connect(this,SIGNAL(itemClicked(QTableWidgetItem*)),this,SLOT(updateFlags(QTableWidgetItem*))) ; + + int row=0 ; + for(it = dirs.begin(); it != dirs.end(); it++,++row) + { + listWidget->insertRow(row) ; + listWidget->setItem(row,0,new QTableWidgetItem(QString::fromStdString((*it).filename))); +#ifdef USE_COMBOBOX + QComboBox *cb = new QComboBox ; + cb->addItem(QString("Network Wide")) ; + cb->addItem(QString("Browsable")) ; + cb->addItem(QString("Universal")) ; + + cb->setToolTip(QString("Decide here whether this directory is\n* Network Wide: \tanonymously shared over the network (including your friends)\n* Browsable: \tbrowsable by your friends\n* Universal: \t\tboth")) ; + + // TODO + // - set combobox current value depending on what rsFiles reports. + // - use a signal mapper to get the correct row that contains the combo box sending the signal: + // mapper = new SignalMapper(this) ; + // + // for(all cb) + // { + // signalMapper->setMapping(cb,...) + // } + // + int index = 0 ; + index += ((*it).shareflags & RS_FILE_HINTS_NETWORK_WIDE) > 0 ; + index += (((*it).shareflags & RS_FILE_HINTS_BROWSABLE) > 0) * 2 ; + listWidget->setCellWidget(row,1,cb); + + if(index < 1 || index > 3) + std::cerr << "******* ERROR IN FILE SHARING FLAGS. Flags = " << (*it).shareflags << " ***********" << std::endl ; + else + index-- ; + + cb->setCurrentIndex(index) ; +#else + QCheckBox *cb1 = new QCheckBox ; + QCheckBox *cb2 = new QCheckBox ; + + cb1->setChecked( (*it).shareflags & RS_FILE_HINTS_NETWORK_WIDE ) ; + cb2->setChecked( (*it).shareflags & RS_FILE_HINTS_BROWSABLE ) ; + + cb1->setToolTip(QString("If checked, the share is anonymously shared to anybody.")) ; + cb2->setToolTip(QString("If checked, the share is browsable by your friends.")) ; + + listWidget->setCellWidget(row,1,cb1); + listWidget->setCellWidget(row,2,cb2); + + QObject::connect(cb1,SIGNAL(toggled(bool)),this,SLOT(updateFlags(bool))) ; + QObject::connect(cb2,SIGNAL(toggled(bool)),this,SLOT(updateFlags(bool))) ; +#endif + } + + //ui.incomingDir->setText(QString::fromStdString(rsFiles->getDownloadDirectory())); + + listWidget->update(); /* update display */ + update(); +} + +void QuickStartWizard::updateFlags(bool b) +{ + std::cerr << "Updating flags (b=" << b << ") !!!" << std::endl ; + + std::list::iterator it; + std::list dirs; + rsFiles->getSharedDirectories(dirs); + + int row=0 ; + for(it = dirs.begin(); it != dirs.end(); it++,++row) + { + std::cerr << "Looking for row=" << row << ", file=" << (*it).filename << ", flags=" << (*it).shareflags << std::endl ; + uint32_t current_flags = 0 ; + current_flags |= (dynamic_cast(ui.shareddirList->cellWidget(row,1)))->isChecked()? RS_FILE_HINTS_NETWORK_WIDE:0 ; + current_flags |= (dynamic_cast(ui.shareddirList->cellWidget(row,2)))->isChecked()? RS_FILE_HINTS_BROWSABLE:0 ; + + if( (*it).shareflags ^ current_flags ) + { + (*it).shareflags = current_flags ; + rsFiles->updateShareFlags(*it) ; // modifies the flags + + std::cout << "Updating share flags for directory " << (*it).filename << std::endl ; + } + } +} + +bool QuickStartWizard::messageBoxOk(QString msg) + { + QMessageBox mb("Share Manager InfoBox!",msg,QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + return true; + } + +/*void QuickStartWizard::showEvent(QShowEvent *event) +{ + if (!event->spontaneous()) + { + loadsharelist(); + } +}*/ + +/** Loads the settings for this page */ +void +QuickStartWizard::loadGeneral() +{ +#ifdef Q_WS_WIN + bool minimized; + ui.checkBoxRunRetroshareAtSystemStartup->setChecked(Settings->runRetroshareOnBoot(minimized)); + ui.chkRunRetroshareAtSystemStartupMinimized->setChecked(minimized); +#endif + + ui.checkBoxStartMinimized->setChecked(Settings->getStartMinimized()); + ui.checkBoxQuit->setChecked(Settings->value("doQuit", false).toBool()); + + //ui.checkBoxQuickWizard->setChecked(settings.value(QString::fromUtf8("FirstRun"), false).toBool()); +} + +//bool QuickStartWizard::firstRunWizard() const { +// if(ui.checkBoxQuickWizard->isChecked()) return true; +// return ui.checkBoxQuickWizard->isChecked(); +//} + +/** Loads the settings for this page */ +void QuickStartWizard::loadNetwork() +{ + + /* load up configuration from rsPeers */ + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail)) + { + return; + } + + /* set net mode */ + int netIndex = 0; + switch(detail.tryNetMode) + { + case RS_NETMODE_EXT: + netIndex = 2; + break; + case RS_NETMODE_UDP: + netIndex = 1; + break; + default: + case RS_NETMODE_UPNP: + netIndex = 0; + break; + } + ui.netModeComboBox->setCurrentIndex(netIndex); + + /* DHT + Discovery: (public) + * Discovery only: (private) + * DHT only: (inverted) + * None: (dark net) + */ + + netIndex = 3; // NONE. + if (detail.visState & RS_VS_DHT_ON) + { + if (detail.visState & RS_VS_DISC_ON) + { + netIndex = 0; // PUBLIC + } + else + { + netIndex = 2; // INVERTED + } + } + else + { + if (detail.visState & RS_VS_DISC_ON) + { + netIndex = 1; // PRIVATE + } + else + { + netIndex = 3; // NONE + } + } + + ui.discoveryComboBox->setCurrentIndex(netIndex); + + rsiface->lockData(); /* Lock Interface */ + + ui.doubleSpinBoxDownloadSpeed->setValue(rsiface->getConfig().maxDownloadDataRate); + ui.doubleSpinBoxUploadSpeed->setValue(rsiface->getConfig().maxUploadDataRate); + + rsiface->unlockData(); /* UnLock Interface */ +} + +void QuickStartWizard::saveChanges() +{ + QString str; + + //bool saveAddr = false; + + + RsPeerDetails detail; + std::string ownId = rsPeers->getOwnId(); + + if (!rsPeers->getPeerDetails(ownId, detail)) + { + return; + } + + + /* Check if netMode has changed */ + int netMode = 0; + int netIndex = ui.netModeComboBox->currentIndex(); + std::cerr << "ui.netModeComboBox->currentIndex()" << ui.netModeComboBox->currentIndex() << std::endl; + switch(netIndex) + { + case 2: + netMode = RS_NETMODE_EXT; + break; + case 1: + netMode = RS_NETMODE_UDP; + break; + default: + case 0: + netMode = RS_NETMODE_UPNP; + break; + } + + rsPeers->setNetworkMode(ownId, netMode); + + uint32_t visState = 0; + /* Check if vis has changed */ + switch(ui.discoveryComboBox->currentIndex()) + { + case 0: + visState |= (RS_VS_DISC_ON | RS_VS_DHT_ON); + break; + case 1: + visState |= RS_VS_DISC_ON; + break; + case 2: + visState |= RS_VS_DHT_ON; + break; + case 3: + default: + break; + } + + if (visState != detail.visState) + { + rsPeers->setVisState(ownId, visState); + } + + /*if (0 != netIndex) + { + saveAddr = true; + }*/ + + /*if (saveAddr) + { + rsPeers->setLocalAddress(rsPeers->getOwnId(), ui.localAddress->text().toStdString(), ui.localPort->value()); + rsPeers->setExtAddress(rsPeers->getOwnId(), ui.extAddress->text().toStdString(), ui.extPort->value()); + }*/ + + rsicontrol->ConfigSetDataRates( ui.doubleSpinBoxDownloadSpeed->value(), ui.doubleSpinBoxUploadSpeed->value() ); + loadNetwork(); +} + +//void QuickStartWizard::toggleTunnelConnection(bool b) +//{ +// std::cerr << "QuickStartWizard::toggleTunnelConnection() set tunnel to : " << b << std::endl; +// rsPeers->allowTunnelConnection(b) ; +//} diff --git a/retroshare-gui/src/gui/QuickStartWizard.h b/retroshare-gui/src/gui/QuickStartWizard.h new file mode 100644 index 000000000..48a579e7d --- /dev/null +++ b/retroshare-gui/src/gui/QuickStartWizard.h @@ -0,0 +1,78 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006-2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _QUICKSTARTWIZARD_H +#define _QUICKSTARTWIZARD_H + +#include +#include + +#include "ui_QuickStartWizard.h" + + +class QuickStartWizard : public QDialog +{ + Q_OBJECT + Q_DISABLE_COPY(QuickStartWizard) + +public: + explicit QuickStartWizard(QWidget *parent = 0); + virtual ~QuickStartWizard(); + + void loadNetwork(); + void loadShare(); + void loadGeneral(); + +protected: + virtual void changeEvent(QEvent *e); + // virtual void showEvent(QShowEvent * event); + +private: + Ui::QuickStartWizard ui; + + bool messageBoxOk(QString); + +private Q_SLOTS: + void on_shareIncomingDirectory_clicked(); + void on_pushButtonSharesRemove_clicked(); + void on_pushButtonSharesAdd_clicked(); + void on_pushButtonSystemExit_clicked(); + void on_pushButtonSystemFinish_clicked(); + void on_pushButtonSystemBack_clicked(); + void on_pushButtonSharesExit_clicked(); + void on_pushButtonSharesNext_clicked(); + void on_pushButtonSharesBack_clicked(); + void on_pushButtonWelcomeExit_clicked(); + void on_pushButtonWelcomeNext_clicked(); + void on_pushButtonConnectionExit_clicked(); + void on_pushButtonConnectionNext_clicked(); + void on_pushButtonConnectionBack_clicked(); + + void updateFlags(bool); + void saveChanges(); + //void toggleUPnP(); + //void toggleTunnelConnection(bool) ; + + + +}; + +#endif // _QUICKSTARTWIZARD_H diff --git a/retroshare-gui/src/gui/QuickStartWizard.ui b/retroshare-gui/src/gui/QuickStartWizard.ui new file mode 100644 index 000000000..895557859 --- /dev/null +++ b/retroshare-gui/src/gui/QuickStartWizard.ui @@ -0,0 +1,1019 @@ + + + QuickStartWizard + + + Qt::ApplicationModal + + + + 0 + 0 + 445 + 370 + + + + + 445 + 357 + + + + + 457 + 370 + + + + Quick Start Wizard + + + + :/images/rstray3.png:/images/rstray3.png + + + QComboBox QAbstractItemView { +background-color:white; +} + +QComboBox::down-arrow { +image: url(:/images/combobox_arrow.png); +} + +QComboBox:drop-down +{ +subcontrol-origin: padding; +subcontrol-position: top right; +border-left-style: none; +border-top-right-radius: 1px; +border-bottom-right-radius: 1px; +} + +QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + true + + + + 0 + + + 0 + + + + + + 0 + 50 + + + + + 16777215 + 50 + + + + background-image: url(:/images/connect/connectFriendBanner.png); + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 1 + + + 0 + + + + + + 48 + 48 + + + + background-color: transparent; + + + :/images/rs_wizard.png + + + true + + + + + + + + 0 + 0 + + + + color: rgb(255, 255, 255); + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + + + + + + + + + 0 + + + + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Sunken + + + + 4 + + + 4 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 4 + + + 4 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Next > + + + true + + + + + + + Exit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Sunken + + + + + + + 0 + 0 + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + Choose your download speed limit: + + + KB/s + + + 0 + + + 29.000000000000000 + + + 155000.000000000000000 + + + 2048.000000000000000 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Choose your upload speed limit: + + + KB/s + + + 0 + + + 29.000000000000000 + + + 155000.000000000000000 + + + 256.000000000000000 + + + + + + + + + Connection : + + + + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + + + + Discovery : + + + + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + + + Dynamic DNS: + + + + + + + + + + + + + 16777215 + 40 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + + + + + + Qt::Horizontal + + + + + + + 4 + + + 4 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + < Back + + + + + + + Next > + + + true + + + + + + + Exit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Sunken + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + QLayout::SetMaximumSize + + + 0 + + + + + + 16777215 + 120 + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + 22 + + + false + + + 22 + + + true + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + + + + + + Add + + + + + + + Remove + + + + + + + Qt::Horizontal + + + + 258 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Automatically share incoming directory (Recommended) + + + + + + + + + + Qt::Horizontal + + + + + + + 4 + + + 4 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + < Back + + + + + + + Next > + + + true + + + + + + + Exit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Sunken + + + + 4 + + + 4 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + true + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + Do not show a message when Closing RetroShare + + + + + + + Start Minimized + + + + + + + Start RetroShare when my System Starts. + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 15 + 20 + + + + + + + + Start minimized on system start + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Qt::Horizontal + + + + + + + 4 + + + 4 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + < Back + + + + + + + Finish + + + true + + + + + + + Exit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/QuickStartWizard2.ui b/retroshare-gui/src/gui/QuickStartWizard2.ui new file mode 100644 index 000000000..2597e2fc0 --- /dev/null +++ b/retroshare-gui/src/gui/QuickStartWizard2.ui @@ -0,0 +1,795 @@ + + + QuickStartWizard + + + Qt::ApplicationModal + + + + 0 + 0 + 766 + 510 + + + + + 400 + 300 + + + + + 800 + 600 + + + + Quick Start Wizard + + + + :/images/rstray3.png:/images/rstray3.png + + + QComboBox QAbstractItemView { +background-color:white; +} + +QComboBox::down-arrow { +image: url(:/images/combobox_arrow.png); +} + +QComboBox:drop-down +{ +subcontrol-origin: padding; +subcontrol-position: top right; +border-left-style: none; +border-top-right-radius: 1px; +border-bottom-right-radius: 1px; +} + +QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + true + + + + 0 + + + 0 + + + + + + 0 + 50 + + + + + 16777215 + 50 + + + + background-image: url(:/images/connect/connectFriendBanner.png); + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 1 + + + 0 + + + + + + 48 + 48 + + + + background-color: transparent; + + + :/images/rs_wizard.png + + + true + + + + + + + + 0 + 0 + + + + color: rgb(255, 255, 255); + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + + + + + + + + + 1 + + + + + + + + 0 + + + 0 + + + + + 4 + + + 4 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Next > + + + true + + + + + + + Exit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Sunken + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">Welcome to RetroShare.</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">No Questions, No Limits, Pure Privacy. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">The QuickStart wizard helps you get started with RetroShare.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">This Wizard helps you </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">Add Friends</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;"> and </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">Add Shared Folders</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">You can restart the Wizard at anytime from the Toolbar.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">Help I don't know what I'm doing! Someone just sent me a link...</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Firstly, </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">Don't Panic... </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Retroshare is easy to use. Most things are handled automatically for you.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Retroshare is a </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">Secure Social Network</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;"> which allows you to privately share stuff with your friends. </span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Follow the Instructions on each page of this wizard to setup Retroshare. (Click the &quot;Next&quot; Button!)</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">Retroshare References</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">You will find more information about Retroshare on the Following Webpages:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.retroshare.org"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Offical Website</span></a></p></body></html> + + + + + + + + + + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + + + + 4 + + + 4 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + < Back + + + + + + + Next > + + + true + + + + + + + Exit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Sunken + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">Invite Your Friends To Retroshare</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">No Questions, No Limits, Pure Privacy. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Increasing your number of friends makes Retroshare a more powerful tool. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Each person provides a some content, </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">together with Retroshare</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;"> you form a </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">secure social network.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">How do I invite with Friends?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Retroshare uses a Web of Trust to identify people. To connect with a friend, you must exchange &quot;Certificates&quot;</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">This is easy to do: Click on the &quot;Launch Invite Email&quot; button below and an email will be created.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Select your closest friends, add their email address, and send it!</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">How do I add Friends Certificates?</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">If someone has sent you a Retroshare Invite Email, Click the &quot;Add Friend&quot; button below.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Cut and Paste their invitation into the new Window and click Okay. Then click Make friend to add them.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Be sure to send them your certificate as well, otherwise you will not connect.</span></p></body></html> + + + + + + + + + Add Friend + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Launch Invite Email + + + + + + + + + + + + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + + + + 4 + + + 4 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + < Back + + + + + + + Next > + + + true + + + + + + + Exit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Sunken + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">Setup your Shared Folders.</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">No Questions, No Limits, Pure Privacy. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Click the &quot;Add&quot; Button, and select which Folder you want to share with your Friends.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">You can Share Folders in two different Modes:</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:14pt; font-weight:600;"> Browsable by friends</span><span style=" font-family:'Sans'; font-size:14pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:14pt; font-weight:600;"> Anonymously shared</span><span style=" font-family:'Sans'; font-size:14pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">When you add a new folder, It will be initially be shared both Anonymously and be Browsable by your Friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">Be sure to change the shared flags to your prefered settings.</span></p></body></html> + + + + + + + + 16777215 + 120 + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + 22 + + + false + + + 22 + + + true + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + + + + Automatically share incoming directory (Recommended) + + + + + + + + + Add + + + + + + + Remove + + + + + + + Qt::Horizontal + + + + 258 + 20 + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Sunken + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Lucida Grande'; font-size:13pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">Congratulations, you have just configured Retroshare.</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">No Questions, No Limits, Pure Privacy. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">When your Friends reply with Invitations, Launch the Wizard again, Add Your Friends and Start Retrosharing!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">Getting the Most Out of Retroshare</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">Invite your friends:</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;"> We suggest you get at least 5 friends to make Retroshare really useful.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">Keep Retroshare running</span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">: You help make the network better by running Retroshare in the background.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt; font-weight:600;">Open a External Port </span><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">on your Router via uPnP, this improves the Network Performance.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">Retroshare Tutorials</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt; font-style:italic;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:14pt;">If you want to learn a little bit more about using Retroshare. Have a look at the following Websites:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://pclosmag.com/html/Issues/201105/page14.html"><span style=" font-size:14pt; text-decoration: underline; color:#0000ff;">PcLinuxOS Tutorial. Part 1 getting started with Retroshare</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:14pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://pclosmag.com/html/Issues/201104/page20.html"><span style=" font-size:14pt; text-decoration: underline; color:#0000ff;">PcLinuxOS Tutorial. Part 2 explaining the Windows</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:14pt; text-decoration: underline; color:#0000ff;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:italic;">Thank you for trying out Retroshare. We hope that you find it useful.</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:14pt;"></p></body></html> + + + + + + + + + + Qt::Horizontal + + + + + + + 4 + + + 4 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + < Back + + + + + + + Finish + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/RSHumanReadableDelegate.h b/retroshare-gui/src/gui/RSHumanReadableDelegate.h new file mode 100644 index 000000000..52b516328 --- /dev/null +++ b/retroshare-gui/src/gui/RSHumanReadableDelegate.h @@ -0,0 +1,111 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 Cyril Soler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +/** Use this class for displaying dates and sizes in a readable format, while allowing to read the + * real size in the column. + * + * To use: + * + * - in the QABstractItemView constructor, do a + * + * myView->setItemDelegateForColumn(SR_SIZE_COL,new RSHumanReadableSizeDelegate()) ; + * + * - each field must be filled with a string that allows a proper sorting based on lexicographic + * order. For Sizes, use this: + * + * myView->setText(SR_SIZE_COL, QString("%1").arg(dir.count,(int)15,(int)10)); + * + * Note: there's no .cpp file, because the code here is really simple. + */ + +#include +#include +#include + +class RSHumanReadableDelegate: public QAbstractItemDelegate +{ + public: + virtual QSize sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const + { + return QSize(50,17) ; + } + virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const = 0; + + protected: + virtual void setPainterOptions(QPainter *painter,QStyleOptionViewItem& option,const QModelIndex& index) const + { + // This part of the code is copied from DLListDelegate.cpp + // + QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; + QVariant value = index.data(Qt::TextColorRole); + + if(value.isValid() && qvariant_cast(value).isValid()) + option.palette.setColor(QPalette::Text, qvariant_cast(value)); + + // select pen color + if(option.state & QStyle::State_Selected) + painter->setPen(option.palette.color(cg, QPalette::HighlightedText)); + else + painter->setPen(option.palette.color(cg, QPalette::Text)); + + // draw the background color + if(option.showDecorationSelected && (option.state & QStyle::State_Selected)) + { + if(cg == QPalette::Normal && !(option.state & QStyle::State_Active)) + cg = QPalette::Inactive; + + painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight)); + } + else + { + value = index.data(Qt::BackgroundColorRole); + + if(value.isValid() && qvariant_cast(value).isValid()) + painter->fillRect(option.rect, qvariant_cast(value)); + } + } +}; + +class RSHumanReadableAgeDelegate: public RSHumanReadableDelegate +{ + public: + virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const + { + QStyleOptionViewItem opt(option) ; + setPainterOptions(painter,opt,index) ; + + painter->drawText(opt.rect, Qt::AlignCenter, misc::userFriendlyDuration(index.data().toLongLong())) ; + } +}; + +class RSHumanReadableSizeDelegate: public RSHumanReadableDelegate +{ + public: + virtual void paint(QPainter *painter,const QStyleOptionViewItem & option, const QModelIndex & index) const + { + QStyleOptionViewItem opt(option) ; + setPainterOptions(painter,opt,index) ; + + painter->drawText(opt.rect, Qt::AlignRight, misc::friendlyUnit(index.data().toULongLong())); + } +}; + diff --git a/retroshare-gui/src/gui/RemoteDirModel.cpp b/retroshare-gui/src/gui/RemoteDirModel.cpp new file mode 100644 index 000000000..8807897dd --- /dev/null +++ b/retroshare-gui/src/gui/RemoteDirModel.cpp @@ -0,0 +1,1378 @@ +/*************************************:*************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include "RemoteDirModel.h" +#include +#include +#include +#include "util/misc.h" + +#include +#include +#include + +/***** + * #define RDM_DEBUG + ****/ + +RetroshareDirModel::RetroshareDirModel(bool mode, QObject *parent) + : QAbstractItemModel(parent), + ageIndicator(IND_ALWAYS), + RemoteMode(mode), nIndex(1), indexSet(1) /* ass zero index cant be used */ +{ + _visible = false ; + _needs_update = true ; + setSupportedDragActions(Qt::CopyAction); + treeStyle(); +} + +void RetroshareDirModel::update() +{ + if(_needs_update) + { + preMods() ; + postMods() ; + } +} +void RetroshareDirModel::treeStyle() +{ + categoryIcon.addPixmap(QPixmap(":/images/folder16.png"), + QIcon::Normal, QIcon::Off); + categoryIcon.addPixmap(QPixmap(":/images/folder_video.png"), + QIcon::Normal, QIcon::On); + peerIcon = QIcon(":/images/user/identity16.png"); +} + +bool TreeStyle_RDM::hasChildren(const QModelIndex &parent) const +{ + +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::hasChildren() :" << parent.internalPointer(); + std::cerr << ": "; +#endif + + if (!parent.isValid()) + { +#ifdef RDM_DEBUG + std::cerr << "root -> true "; + std::cerr << std::endl; +#endif + return true; + } + + void *ref = parent.internalPointer(); + + DirDetails details; + uint32_t flags = DIR_FLAGS_CHILDREN; + if (RemoteMode) + flags |= DIR_FLAGS_REMOTE; + else + flags |= DIR_FLAGS_LOCAL; + + if (!requestDirDetails(ref, details, flags)) + { + /* error */ +#ifdef RDM_DEBUG + std::cerr << "lookup failed -> false"; + std::cerr << std::endl; +#endif + return false; + } + + if (details.type == DIR_TYPE_FILE) + { +#ifdef RDM_DEBUG + std::cerr << "lookup FILE -> false"; + std::cerr << std::endl; +#endif + return false; + } + /* PERSON/DIR*/ +#ifdef RDM_DEBUG + std::cerr << "lookup PER/DIR #" << details.count; + std::cerr << std::endl; +#endif + return (details.count > 0); /* do we have children? */ +} +bool FlatStyle_RDM::hasChildren(const QModelIndex &parent) const +{ + +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::hasChildren() :" << parent.internalPointer(); + std::cerr << ": "; +#endif + + if (!parent.isValid()) + { +#ifdef RDM_DEBUG + std::cerr << "root -> true "; + std::cerr << std::endl; +#endif + return true; + } + else + return false ; +} + +int TreeStyle_RDM::rowCount(const QModelIndex &parent) const +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::rowCount(): " << parent.internalPointer(); + std::cerr << ": "; +#endif + + void *ref = (parent.isValid())? parent.internalPointer() : NULL ; + + DirDetails details; + uint32_t flags = DIR_FLAGS_CHILDREN; + if (RemoteMode) + flags |= DIR_FLAGS_REMOTE; + else + flags |= DIR_FLAGS_LOCAL; + + if (!requestDirDetails(ref, details, flags)) + { +#ifdef RDM_DEBUG + std::cerr << "lookup failed -> 0"; + std::cerr << std::endl; +#endif + return 0; + } + if (details.type == DIR_TYPE_FILE) + { +#ifdef RDM_DEBUG + std::cerr << "lookup FILE: 0"; + std::cerr << std::endl; +#endif + return 0; + } + + /* else PERSON/DIR*/ +#ifdef RDM_DEBUG + std::cerr << "lookup PER/DIR #" << details.count; + std::cerr << std::endl; +#endif + return details.count; +} + +int FlatStyle_RDM::rowCount(const QModelIndex &parent) const +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::rowCount(): " << parent.internalPointer(); + std::cerr << ": "; +#endif + + return _ref_entries.size() ; +} +int TreeStyle_RDM::columnCount(const QModelIndex &parent) const +{ + return 5; +} +int FlatStyle_RDM::columnCount(const QModelIndex &parent) const +{ + return 5; +} +QString RetroshareDirModel::getFlagsString(uint32_t flags) +{ + switch(flags & (DIR_FLAGS_NETWORK_WIDE|DIR_FLAGS_BROWSABLE)) + { + case DIR_FLAGS_NETWORK_WIDE: return tr("Anonymous") ; + case DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE: return tr("Anonymous and browsable by friends") ; + case DIR_FLAGS_BROWSABLE: return tr("Only browsable by friends") ; + default: + return QString() ; + } +} + +QString RetroshareDirModel::getAgeIndicatorString(const DirDetails &details) const +{ + QString ret(""); + QString nind = tr("NEW"); +// QString oind = tr("OLD"); + uint32_t age = details.age; + + switch (ageIndicator) { + case IND_LAST_DAY: + if (age < 24 * 60 * 60) return nind; + break; + case IND_LAST_WEEK: + if (age < 7 * 24 * 60 * 60) return nind; + break; + case IND_LAST_MONTH: + if (age < 30 * 24 * 60 * 60) return nind; + break; +// case IND_OLDER: +// if (age >= 30 * 24 * 60 * 60) return oind; +// break; + case IND_ALWAYS: + return ret; + default: + return ret; + } + + return ret; +} + +QVariant RetroshareDirModel::decorationRole(const DirDetails& details,int coln) const +{ + if(coln > 0) + return QVariant() ; + + if (details.type == DIR_TYPE_PERSON) + { + if(details.min_age > ageIndicator) + return QIcon(":/images/folder_grey.png"); + else if (ageIndicator == IND_LAST_DAY ) + return QIcon(":/images/folder_green.png"); + else if (ageIndicator == IND_LAST_WEEK ) + return QIcon(":/images/folder_yellow.png"); + else if (ageIndicator == IND_LAST_MONTH ) + return QIcon(":/images/folder_red.png"); + else + return (QIcon(peerIcon)); + } + else if (details.type == DIR_TYPE_DIR) + { + if(details.min_age > ageIndicator) + return QIcon(":/images/folder_grey.png"); + else if (ageIndicator == IND_LAST_DAY ) + return QIcon(":/images/folder_green.png"); + else if (ageIndicator == IND_LAST_WEEK ) + return QIcon(":/images/folder_yellow.png"); + else if (ageIndicator == IND_LAST_MONTH ) + return QIcon(":/images/folder_red.png"); + else + return QIcon(categoryIcon); + } + else if (details.type == DIR_TYPE_FILE) /* File */ + { + // extensions predefined + QString ext = QFileInfo(QString::fromUtf8(details.name.c_str())).suffix(); + if (ext == "jpg" || ext == "jpeg" || ext == "png" || ext == "gif" + || ext == "bmp" || ext == "ico" || ext == "svg") + return QIcon(":/images/FileTypePicture.png"); + else if (ext == "avi" || ext == "AVI" || ext == "mpg" || ext == "mpeg" || ext == "wmv" || ext == "ogm" + || ext == "mkv" || ext == "mp4" || ext == "flv" || ext == "mov" + || ext == "vob" || ext == "qt" || ext == "rm" || ext == "3gp") + return QIcon(":/images/FileTypeVideo.png"); + else if (ext == "ogg" || ext == "mp3" || ext == "wav" || ext == "wma" || ext == "xpm") + return QIcon(":/images/FileTypeAudio.png"); + else if (ext == "tar" || ext == "bz2" || ext == "zip" || ext == "gz" || ext == "7z" + || ext == "rar" || ext == "rpm" || ext == "deb") + return QIcon(":/images/FileTypeArchive.png"); + else if (ext == "app" || ext == "bat" || ext == "cgi" || ext == "com" + || ext == "bin" || ext == "exe" || ext == "js" || ext == "pif" + || ext == "py" || ext == "pl" || ext == "sh" || ext == "vb" || ext == "ws") + return QIcon(":/images/FileTypeProgram.png"); + else if (ext == "iso" || ext == "nrg" || ext == "mdf" ) + return QIcon(":/images/FileTypeCDImage.png"); + else if (ext == "txt" || ext == "cpp" || ext == "c" || ext == "h") + return QIcon(":/images/FileTypeDocument.png"); + else if (ext == "doc" || ext == "rtf" || ext == "sxw" || ext == "xls" + || ext == "sxc" || ext == "odt" || ext == "ods") + return QIcon(":/images/FileTypeDocument.png"); + else if (ext == "html" || ext == "htm" || ext == "php") + return QIcon(":/images/FileTypeDocument.png"); + else + return QIcon(":/images/FileTypeAny.png"); + } + else + return QVariant(); + +} /* end of DecorationRole */ + +QVariant TreeStyle_RDM::displayRole(const DirDetails& details,int coln) const +{ + + /* + * Person: name, id, 0, 0; + * File : name, size, rank, (0) ts + * Dir : name, (0) count, (0) path, (0) ts + */ + + + if (details.type == DIR_TYPE_PERSON) /* Person */ + { + switch(coln) + { + case 0: + return QString::fromUtf8(details.name.c_str()); + case 1: + return QString() ; + case 2: + return misc::userFriendlyDuration(details.min_age); + default: + return QString() ; + } + } + else if (details.type == DIR_TYPE_FILE) /* File */ + { + switch(coln) + { + case 0: + return QString::fromUtf8(details.name.c_str()); + case 1: + return misc::friendlyUnit(details.count); + case 2: + return misc::userFriendlyDuration(details.age); + case 3: + return getFlagsString(details.flags); + case 4: + { + QString ind(""); + if (ageIndicator != IND_ALWAYS) + ind = getAgeIndicatorString(details); + return ind; + } + default: + return tr("FILE"); + } + } + else if (details.type == DIR_TYPE_DIR) /* Dir */ + { + switch(coln) + { + case 0: + return QString::fromUtf8(details.name.c_str()); + break; + case 1: + if (details.count > 1) + { + return QString::number(details.count) + " " + tr("Files"); + } + return QString::number(details.count) + " " + tr("File"); + case 2: + return misc::userFriendlyDuration(details.min_age); + case 3: + return getFlagsString(details.flags); + default: + return tr("DIR"); + } + } + return QVariant(); +} /* end of DisplayRole */ + +QString FlatStyle_RDM::computeDirectoryPath(const DirDetails& details) const +{ + QString dir ; + DirDetails det(details) ; + uint32_t flags = (RemoteMode)?DIR_FLAGS_REMOTE:DIR_FLAGS_LOCAL; + + if(!requestDirDetails(det.parent,det,flags)) + return QString(); + +#ifdef SHOW_TOTAL_PATH + do + { +#endif + dir = QString::fromStdString(det.name)+"/"+dir ; + +#ifdef SHOW_TOTAL_PATH + if(!requestDirDetails(det.parent,det,flags)) + break ; + } + while(det.parent != NULL); +#endif + + return dir ; +} + +QVariant FlatStyle_RDM::displayRole(const DirDetails& details,int coln) const +{ + if (details.type == DIR_TYPE_FILE) /* File */ + switch(coln) + { + case 0: return QString::fromUtf8(details.name.c_str()); + case 1: return misc::friendlyUnit(details.count); + case 2: return misc::userFriendlyDuration(details.age); + case 3: return QString::fromStdString(rsPeers->getPeerName(details.id)); + case 4: return computeDirectoryPath(details); + default: + return QVariant() ; + } + + return QVariant(); +} /* end of DisplayRole */ +QVariant TreeStyle_RDM::sortRole(const QModelIndex& index,const DirDetails& details,int coln) const +{ + /* + * Person: name, id, 0, 0; + * File : name, size, rank, (0) ts + * Dir : name, (0) count, (0) path, (0) ts + */ + + if (details.type == DIR_TYPE_PERSON) /* Person */ + { + switch(coln) + { + case 0: + return QString::fromUtf8(details.name.c_str()); + case 1: + return QString(); + case 2: + return details.min_age; + default: + return QString(); + } + } + else if (details.type == DIR_TYPE_FILE) /* File */ + { + switch(coln) + { + case 0: + return QString::fromUtf8(details.name.c_str()); + case 1: + return (qulonglong) details.count; + case 2: + return details.age; + case 3: + return getFlagsString(details.flags); + case 4: + { + QString ind(""); + if (ageIndicator != IND_ALWAYS) + ind = getAgeIndicatorString(details); + return ind; + } + default: + return tr("FILE"); + } + } + else if (details.type == DIR_TYPE_DIR) /* Dir */ + { + switch(coln) + { + case 0: + return QString::fromUtf8(details.name.c_str()); + case 1: + return (qulonglong) details.count; + case 2: + return details.min_age; + case 3: + return getFlagsString(details.flags); + default: + return tr("DIR"); + } + } + return QVariant(); +} +QVariant FlatStyle_RDM::sortRole(const QModelIndex& index,const DirDetails& details,int coln) const +{ + /* + * Person: name, id, 0, 0; + * File : name, size, rank, (0) ts + * Dir : name, (0) count, (0) path, (0) ts + */ + + if (details.type == DIR_TYPE_FILE) /* File */ + { + switch(coln) + { + case 0: return QString::fromUtf8(details.name.c_str()); + case 1: return (qulonglong) details.count; + case 2: return details.age; + case 3: return QString::fromStdString(rsPeers->getPeerName(details.id)); + case 4: return _ref_entries[index.row()].second ; + } + } + return QVariant(); +} /* end of SortRole */ + + + + +QVariant RetroshareDirModel::data(const QModelIndex &index, int role) const +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::data(): " << index.internalPointer(); + std::cerr << ": "; + std::cerr << std::endl; +#endif + + if (!index.isValid()) + return QVariant(); + + /* get the data from the index */ + void *ref = index.internalPointer(); + int coln = index.column(); + + DirDetails details; + uint32_t flags = DIR_FLAGS_DETAILS; + if (RemoteMode) + flags |= DIR_FLAGS_REMOTE; + else + flags |= DIR_FLAGS_LOCAL; + + if (!requestDirDetails(ref, details, flags)) + return QVariant(); + + if (role == RetroshareDirModel::FileNameRole) /* end of FileNameRole */ + return QString::fromUtf8(details.name.c_str()); + + if (role == Qt::TextColorRole) + { + if(details.min_age > ageIndicator) + return Qt::gray ; + else + return Qt::black ; + } /* end of TextColorRole */ + + + if(role == Qt::DecorationRole) + return decorationRole(details,coln) ; + + /***************** + Qt::EditRole + Qt::ToolTipRole + Qt::StatusTipRole + Qt::WhatsThisRole + Qt::SizeHintRole + ****************/ + + if (role == Qt::SizeHintRole) + { + return QSize(18, 18); + } /* end of SizeHintRole */ + + if (role == Qt::TextAlignmentRole) + { + if(coln == 1) + { + return int( Qt::AlignRight | Qt::AlignVCenter); + } + return QVariant(); + } /* end of TextAlignmentRole */ + + if (role == Qt::DisplayRole) + return displayRole(details,coln) ; + + if (role == SortRole) + return sortRole(index,details,coln) ; + + return QVariant(); +} + +void RetroshareDirModel::getAgeIndicatorRec(DirDetails &details, QString &ret) const { + if (details.type == DIR_TYPE_FILE) { + ret = getAgeIndicatorString(details); + return; + } else if (details.type == DIR_TYPE_DIR && ret.isEmpty()) { + std::list::iterator it; + for (it = details.children.begin(); it != details.children.end(); it++) { + void *ref = it->ref; + DirDetails childDetails; + uint32_t flags; + + if (RemoteMode) + flags |= DIR_FLAGS_REMOTE; + else + flags |= DIR_FLAGS_LOCAL; + + if (requestDirDetails(ref, childDetails, flags) && ret == tr("")) + getAgeIndicatorRec(childDetails, ret); + } + } +} + +QVariant TreeStyle_RDM::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::SizeHintRole) + { + int defw = 50; + int defh = 21; + if (section < 2) + { + defw = 200; + } + return QSize(defw, defh); + } + + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + { + switch(section) + { + case 0: + if (RemoteMode) + return tr("Friends Directories"); + else + return tr("My Directories"); + case 1: + return tr("Size"); + case 2: + return tr("Age"); + case 3: + if (RemoteMode) + return tr("Friend"); + else + return tr("Share Type"); + case 4: + return tr("What's new"); + } + return QString("Column %1").arg(section); + } + else + return QString("Row %1").arg(section); +} +QVariant FlatStyle_RDM::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role == Qt::SizeHintRole) + { + int defw = 50; + int defh = 21; + if (section < 2) + { + defw = 200; + } + return QSize(defw, defh); + } + + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + { + switch(section) + { + case 0: + if (RemoteMode) + { + return tr("Friends Directories"); + } + return tr("My Directories"); + case 1: + return tr("Size"); + case 2: + return tr("Age"); + case 3: + if(RemoteMode) + return tr("Friend"); + else + return tr("Share Type"); + case 4: + return tr("Directory"); + } + return QString("Column %1").arg(section); + } + else + return QString("Row %1").arg(section); +} + +QModelIndex TreeStyle_RDM::index(int row, int column, const QModelIndex & parent) const +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::index(): " << parent.internalPointer(); + std::cerr << ": row:" << row << " col:" << column << " "; +#endif + + if(row < 0) + return QModelIndex() ; + + void *ref = (parent.isValid()) ? parent.internalPointer() : NULL; + + /******** + if (!RemoteMode) + { + remote = &(rsiface->getLocalDirectoryList()); + } + ********/ + + DirDetails details; + uint32_t flags = DIR_FLAGS_CHILDREN; + if (RemoteMode) + flags |= DIR_FLAGS_REMOTE; + else + flags |= DIR_FLAGS_LOCAL; + + if (!requestDirDetails(ref, details, flags)) + { +#ifdef RDM_DEBUG + std::cerr << "lookup failed -> invalid"; + std::cerr << std::endl; +#endif + return QModelIndex(); + } + + + /* now iterate through the details to + * get the reference number + */ + + std::list::iterator it; + int i = 0; + for(it = details.children.begin(); ((i < row) && (it != details.children.end())); ++it,++i) ; + + if (it == details.children.end()) + { +#ifdef RDM_DEBUG + std::cerr << "wrong number of children -> invalid"; + std::cerr << std::endl; +#endif + return QModelIndex(); + } + +#ifdef RDM_DEBUG + std::cerr << "success index(" << row << "," << column << "," << it->ref << ")"; + std::cerr << std::endl; +#endif + + /* we can just grab the reference now */ + + return createIndex(row, column, it->ref); +} +QModelIndex FlatStyle_RDM::index(int row, int column, const QModelIndex & parent) const +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::index(): " << parent.internalPointer(); + std::cerr << ": row:" << row << " col:" << column << " "; +#endif + + if(row < 0) + return QModelIndex() ; + + if(row < _ref_entries.size()) + { + void *ref = _ref_entries[row].first ; + + return createIndex(row, column, ref); + } + else + return QModelIndex(); +} + +QModelIndex TreeStyle_RDM::parent( const QModelIndex & index ) const +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::parent(): " << index.internalPointer(); + std::cerr << ": "; +#endif + + /* create the index */ + if (!index.isValid()) + { +#ifdef RDM_DEBUG + std::cerr << "Invalid Index -> invalid"; + std::cerr << std::endl; +#endif + /* Parent is invalid too */ + return QModelIndex(); + } + void *ref = index.internalPointer(); + + DirDetails details; + uint32_t flags = (RemoteMode)?DIR_FLAGS_REMOTE:DIR_FLAGS_LOCAL; + + if (!requestDirDetails(ref, details, flags)) + { +#ifdef RDM_DEBUG + std::cerr << "Failed Lookup -> invalid"; + std::cerr << std::endl; +#endif + return QModelIndex(); + } + + if (!(details.parent)) + { +#ifdef RDM_DEBUG + std::cerr << "success. parent is Root/NULL --> invalid"; + std::cerr << std::endl; +#endif + return QModelIndex(); + } + +#ifdef RDM_DEBUG + std::cerr << "success index(" << details.prow << ",0," << details.parent << ")"; + std::cerr << std::endl; + +#endif + return createIndex(details.prow, 0, details.parent); +} +QModelIndex FlatStyle_RDM::parent( const QModelIndex & index ) const +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::parent(): " << index.internalPointer(); + std::cerr << ": "; +#endif + + return QModelIndex(); +} +Qt::ItemFlags RetroshareDirModel::flags( const QModelIndex & index ) const +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::flags()"; + std::cerr << std::endl; +#endif + + if (!index.isValid()) + return (Qt::ItemIsSelectable); // Error. + + void *ref = index.internalPointer(); + + DirDetails details; + uint32_t flags = DIR_FLAGS_DETAILS; + if (RemoteMode) + flags |= DIR_FLAGS_REMOTE; + else + flags |= DIR_FLAGS_LOCAL; + + if (!requestDirDetails(ref, details, flags)) + return Qt::ItemIsSelectable; // Error. + + switch(details.type) + { + case DIR_TYPE_PERSON: return Qt::ItemIsEnabled; + case DIR_TYPE_DIR: return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + case DIR_TYPE_FILE: return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; + } + + return Qt::ItemIsSelectable; +} + +// The other flags... +//Qt::ItemIsUserCheckable +//Qt::ItemIsEditable +//Qt::ItemIsDropEnabled +//Qt::ItemIsTristate + + + +/* Callback from */ + void RetroshareDirModel::preMods() + { +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::preMods()" << std::endl; +#endif + //modelAboutToBeReset(); +// reset(); +#if QT_VERSION >= 0x040600 + beginResetModel(); +#endif + layoutAboutToBeChanged(); + } + +/* Callback from */ + void RetroshareDirModel::postMods() + { +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::postMods()" << std::endl; +#endif + //modelReset(); + layoutChanged(); +#if QT_VERSION >= 0x040600 + endResetModel(); +#endif + } + +bool RetroshareDirModel::requestDirDetails(void *ref,DirDetails& details,uint32_t flags) const +{ + // We should use a cache instead of calling RsFiles::RequestDirDetails(), which is very costly + // due to some pointer checking crap. + + return rsFiles->RequestDirDetails(ref, details, flags) ; +} + +void RetroshareDirModel::downloadSelected(const QModelIndexList &list) +{ + if (!RemoteMode) + { +#ifdef RDM_DEBUG + std::cerr << "Cannot download from local" << std::endl; +#endif + } + + /* so for all the selected .... get the name out, + * make it into something the RsControl can understand + */ + + std::vector dirVec; + + getDirDetailsFromSelect(list, dirVec); + + /* Fire off requests */ + for (int i = 0, n = dirVec.size(); i < n; ++i) + { + if (!RemoteMode) + { + continue; /* don't try to download local stuff */ + } + + const DirDetails& details = dirVec[i]; + + /* if it is a file */ + if (details.type == DIR_TYPE_FILE) + { + std::cerr << "RetroshareDirModel::downloadSelected() Calling File Request"; + std::cerr << std::endl; + std::list srcIds; + srcIds.push_back(details.id); + rsFiles -> FileRequest(details.name, details.hash, + details.count, "", RS_FILE_HINTS_NETWORK_WIDE, srcIds); + } + /* if it is a dir, copy all files included*/ + else if (details.type == DIR_TYPE_DIR) + { + int prefixLen = details.path.rfind(details.name); + if (prefixLen < 0) continue; + downloadDirectory(details, prefixLen); + } + } +} + +/* recursively download a directory */ +void RetroshareDirModel::downloadDirectory(const DirDetails & dirDetails, int prefixLen) +{ + if (dirDetails.type & DIR_TYPE_FILE) + { + std::list srcIds; + QString cleanPath = QDir::cleanPath(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str()) + "/" + QString::fromUtf8(dirDetails.path.substr(prefixLen).c_str())); + + srcIds.push_back(dirDetails.id); + rsFiles->FileRequest(dirDetails.name, dirDetails.hash, dirDetails.count, cleanPath.toUtf8().constData(), RS_FILE_HINTS_NETWORK_WIDE, srcIds); + } + else if (dirDetails.type & DIR_TYPE_DIR) + { + std::list::const_iterator it; + QDir dwlDir(rsFiles->getDownloadDirectory().c_str()); + QString cleanPath = QDir::cleanPath(QString::fromUtf8(dirDetails.path.substr(prefixLen).c_str())); + + if (!dwlDir.mkpath(cleanPath)) return; + + for (it = dirDetails.children.begin(); it != dirDetails.children.end(); it++) + { + if (!it->ref) continue; + + DirDetails subDirDetails; + uint32_t flags = DIR_FLAGS_CHILDREN | DIR_FLAGS_REMOTE; + + if (!requestDirDetails(it->ref, subDirDetails, flags)) continue; + + downloadDirectory(subDirDetails, prefixLen); + } + } +} + +void RetroshareDirModel::getDirDetailsFromSelect (const QModelIndexList &list, std::vector & dirVec) +{ + dirVec.clear(); + + /* Fire off requests */ + QModelIndexList::const_iterator it; + for(it = list.begin(); it != list.end(); it++) + { + if(it->column()==1) + { + void *ref = it -> internalPointer(); + + DirDetails details; + uint32_t flags = DIR_FLAGS_DETAILS; + if (RemoteMode) + { + flags |= DIR_FLAGS_REMOTE; + } + else + { + flags |= DIR_FLAGS_LOCAL; + } + + if (!requestDirDetails(ref, details, flags)) + { + continue; + } + + dirVec.push_back(details); + } + } +} + +/**************************************************************************** + * OLD RECOMMEND SYSTEM - DISABLED + * + */ + +void RetroshareDirModel::getFileInfoFromIndexList(const QModelIndexList& list, std::list& file_details) +{ + file_details.clear() ; + +#ifdef RDM_DEBUG + std::cerr << "recommendSelected()" << std::endl; +#endif + if (RemoteMode) + { +#ifdef RDM_DEBUG + std::cerr << "Cannot recommend remote! (should download)" << std::endl; +#endif + } + /* Fire off requests */ + + std::set already_in ; + + for(QModelIndexList::const_iterator it(list.begin()); it != list.end(); ++it) + if(it->column()==0) + { + void *ref = it -> internalPointer(); + + DirDetails details; + uint32_t flags = DIR_FLAGS_DETAILS; + + if (RemoteMode) + flags |= DIR_FLAGS_REMOTE; + else + flags |= DIR_FLAGS_LOCAL; + + if (!requestDirDetails(ref, details, flags)) + continue; + + if(details.type == DIR_TYPE_PERSON) + continue ; + +#ifdef RDM_DEBUG + std::cerr << "::::::::::::FileRecommend:::: " << std::endl; + std::cerr << "Name: " << details.name << std::endl; + std::cerr << "Hash: " << details.hash << std::endl; + std::cerr << "Size: " << details.count << std::endl; + std::cerr << "Path: " << details.path << std::endl; +#endif + // Note: for directories, the returned hash, is the peer id, so if we collect + // dirs, we need to be a bit more conservative for the + + if(already_in.find(details.hash+details.name) == already_in.end()) + { + file_details.push_back(details) ; + already_in.insert(details.hash+details.name) ; + } + } +#ifdef RDM_DEBUG + std::cerr << "::::::::::::Done FileRecommend" << std::endl; +#endif +} + +/**************************************************************************** + * OLD RECOMMEND SYSTEM - DISABLED + ******/ + +void RetroshareDirModel::openSelected(const QModelIndexList &qmil) +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::openSelected()" << std::endl; +#endif + + if (RemoteMode) { +#ifdef RDM_DEBUG + std::cerr << "Cannot open remote. Download first." << std::endl; +#endif + return; + } + + std::list dirs_to_open; + + std::list files_info; + std::list::iterator it; + getFileInfoFromIndexList(qmil, files_info); + + for (it = files_info.begin(); it != files_info.end(); it++) + { + if ((*it).type & DIR_TYPE_PERSON) continue; + + std::string path, name; + rsFiles->ConvertSharedFilePath((*it).path, path); + + QDir dir(QString::fromUtf8(path.c_str())); + QString dest; + if ((*it).type & DIR_TYPE_FILE) { + dest = dir.absoluteFilePath(QString::fromUtf8(it->name.c_str())); + } else if ((*it).type & DIR_TYPE_DIR) { + dest = dir.absolutePath(); + } + + std::cerr << "Opening this file: " << dest.toStdString() << std::endl ; + + QDesktopServices::openUrl(QUrl::fromLocalFile(dest)); + } + +#ifdef RDM_DEBUG + std::cerr << "::::::::::::Done RetroshareDirModel::openSelected()" << std::endl; +#endif +} + +void RetroshareDirModel::getFilePaths(const QModelIndexList &list, std::list &fullpaths) +{ +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::getFilePaths()" << std::endl; +#endif + if (RemoteMode) + { +#ifdef RDM_DEBUG + std::cerr << "No File Paths for remote files" << std::endl; +#endif + return; + } + /* translate */ + QModelIndexList::const_iterator it; + for(it = list.begin(); it != list.end(); it++) + { + void *ref = it -> internalPointer(); + + DirDetails details; + uint32_t flags = DIR_FLAGS_DETAILS; + flags |= DIR_FLAGS_LOCAL; + + if (!requestDirDetails(ref, details, flags)) + { +#ifdef RDM_DEBUG + std::cerr << "getFilePaths() Bad Request" << std::endl; +#endif + continue; + } + + if (details.type != DIR_TYPE_FILE) + { +#ifdef RDM_DEBUG + std::cerr << "getFilePaths() Not File" << std::endl; +#endif + continue; /* not file! */ + } + +#ifdef RDM_DEBUG + std::cerr << "::::::::::::File Details:::: " << std::endl; + std::cerr << "Name: " << details.name << std::endl; + std::cerr << "Hash: " << details.hash << std::endl; + std::cerr << "Size: " << details.count << std::endl; + std::cerr << "Path: " << details.path << std::endl; +#endif + + std::string filepath = details.path + "/"; + filepath += details.name; + +#ifdef RDM_DEBUG + std::cerr << "Constructed FilePath: " << filepath << std::endl; +#endif + if (fullpaths.end() == std::find(fullpaths.begin(), fullpaths.end(), filepath)) + { + fullpaths.push_back(filepath); + } + } +#ifdef RDM_DEBUG + std::cerr << "::::::::::::Done getFilePaths" << std::endl; +#endif +} + + /* Drag and Drop Functionality */ +QMimeData * RetroshareDirModel::mimeData ( const QModelIndexList & indexes ) const +{ + /* extract from each the member text */ + std::string text; + QModelIndexList::const_iterator it; + std::map drags; + std::map::iterator dit; + + for(it = indexes.begin(); it != indexes.end(); it++) + { + void *ref = it -> internalPointer(); + + DirDetails details; + uint32_t flags = DIR_FLAGS_DETAILS; + if (RemoteMode) + { + flags |= DIR_FLAGS_REMOTE; + } + else + { + flags |= DIR_FLAGS_LOCAL; + } + + if (!requestDirDetails(ref, details, flags)) + { + continue; + } + +#ifdef RDM_DEBUG + std::cerr << "::::::::::::FileDrag:::: " << std::endl; + std::cerr << "Name: " << details.name << std::endl; + std::cerr << "Hash: " << details.hash << std::endl; + std::cerr << "Size: " << details.count << std::endl; + std::cerr << "Path: " << details.path << std::endl; +#endif + + if (details.type != DIR_TYPE_FILE) + { +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::mimeData() Not File" << std::endl; +#endif + continue; /* not file! */ + } + + if (drags.end() != (dit = drags.find(details.hash))) + { +#ifdef RDM_DEBUG + std::cerr << "RetroshareDirModel::mimeData() Duplicate" << std::endl; +#endif + continue; /* duplicate */ + } + + drags[details.hash] = details.count; + + std::string line = details.name; + line += "/"; + line += details.hash; + line += "/"; + + { + std::ostringstream out; + out << details.count; + line += out.str(); + line += "/"; + } + + if (RemoteMode) + { + line += "Remote"; + } + else + { + line += "Local"; + } + line += "/\n"; + + text += line; + } + +#ifdef RDM_DEBUG + std::cerr << "Created MimeData:"; + std::cerr << std::endl; + + std::cerr << text; + std::cerr << std::endl; +#endif + + QMimeData *data = new QMimeData(); + data->setData("application/x-rsfilelist", QByteArray(text.c_str())); + + return data; + + +} + +QStringList RetroshareDirModel::mimeTypes () const +{ + QStringList list; + list.push_back("application/x-rsfilelist"); + + return list; +} + +//============================================================================ + +int RetroshareDirModel::getType ( const QModelIndex & index ) const +{ + //if (RemoteMode) // only local files can be opened + // return ; + + uint32_t flags = RemoteMode?DIR_FLAGS_REMOTE:DIR_FLAGS_LOCAL; + + return rsFiles->getType(index.internalPointer(),flags); +} + +FlatStyle_RDM::~FlatStyle_RDM() +{ +} + +TreeStyle_RDM::~TreeStyle_RDM() +{ +} +void FlatStyle_RDM::postMods() +{ + if(visible()) + { + _ref_entries.clear() ; + _ref_stack.clear() ; + + _ref_stack.push_back(NULL) ; // init the stack with the topmost parent directory + + std::cerr << "FlatStyle_RDM::postMods(): cleared ref entries" << std::endl; + _needs_update = false ; + updateRefs() ; + } + else + _needs_update = true ; +} + +void FlatStyle_RDM::updateRefs() +{ + if(RsAutoUpdatePage::eventsLocked()) + { + _needs_update = true ; + return ; + } + + RetroshareDirModel::preMods() ; + + static const uint32_t MAX_REFS_PER_SECOND = 2000 ; + uint32_t nb_treated_refs = 0 ; + + while(!_ref_stack.empty()) + { + void *ref = _ref_stack.back() ; +#ifdef RDM_DEBUG + std::cerr << "FlatStyle_RDM::postMods(): poped ref " << ref << std::endl; +#endif + _ref_stack.pop_back() ; + uint32_t flags = DIR_FLAGS_DETAILS; + DirDetails details ; + + if (requestDirDetails(ref, details, flags)) + { + if(details.type == DIR_TYPE_FILE) // only push files, not directories nor persons. + _ref_entries.push_back(std::pair(ref,computeDirectoryPath(details))); +#ifdef RDM_DEBUG + std::cerr << "FlatStyle_RDM::postMods(): addign ref " << ref << std::endl; +#endif + for(std::list::iterator it = details.children.begin(); it != details.children.end(); it++) + _ref_stack.push_back(it->ref) ; + } + if(++nb_treated_refs > MAX_REFS_PER_SECOND) // we've done enough, let's give back hand to + { // the user and setup a timer to finish the job later. + _needs_update = true ; + + if(visible()) + QTimer::singleShot(2000,this,SLOT(updateRefs())) ; + else + std::cerr << "Not visible: suspending update"<< std::endl; + break ; + } + } + std::cerr << "reference tab contains " << _ref_entries.size() << " files" << std::endl; + + if(_ref_stack.empty()) + _needs_update = false ; + + RetroshareDirModel::postMods() ; +} + diff --git a/retroshare-gui/src/gui/RemoteDirModel.h b/retroshare-gui/src/gui/RemoteDirModel.h new file mode 100644 index 000000000..291040cf1 --- /dev/null +++ b/retroshare-gui/src/gui/RemoteDirModel.h @@ -0,0 +1,208 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef REMOTE_DIR_MODEL +#define REMOTE_DIR_MODEL + +#include +#include +#include +#include + +class DirDetails; + +static const uint32_t IND_LAST_DAY = 3600*24 ; +static const uint32_t IND_LAST_WEEK = 3600*24*7 ; +static const uint32_t IND_LAST_MONTH = 3600*24*31 ; // I know, this is approximate +static const uint32_t IND_ALWAYS = ~(uint32_t)0 ; + +class RetroshareDirModel : public QAbstractItemModel +{ + Q_OBJECT + + public: + enum Roles{ FileNameRole = Qt::UserRole+1, SortRole = Qt::UserRole+2 }; + + RetroshareDirModel(bool mode, QObject *parent = 0); + virtual ~RetroshareDirModel() {} + + Qt::ItemFlags flags ( const QModelIndex & index ) const; + + /* Callback from Core */ + virtual void preMods(); + virtual void postMods(); + + void setVisible(bool b) { _visible = b ; } + bool visible() { return _visible ;} + + /* Callback from GUI */ + void downloadSelected(const QModelIndexList &list); + + void getDirDetailsFromSelect (const QModelIndexList &list, std::vector & dirVec); + + int getType ( const QModelIndex & index ) const ; + void getFileInfoFromIndexList(const QModelIndexList& list, std::list& files_info) ; + void openSelected(const QModelIndexList &list); + void getFilePaths(const QModelIndexList &list, std::list &fullpaths); + void changeAgeIndicator(uint32_t indicator) { ageIndicator = indicator; } + + bool requestDirDetails(void *ref,DirDetails& details,uint32_t flags) const; + void update() ; + public: + + virtual QMimeData * mimeData ( const QModelIndexList & indexes ) const; + virtual QStringList mimeTypes () const; + virtual QVariant data(const QModelIndex &index, int role) const; + + protected: + bool _visible ; + bool _needs_update ; + + void treeStyle(); + void downloadDirectory(const DirDetails & details, int prefixLen); + static QString getFlagsString(uint32_t) ; + QString getAgeIndicatorString(const DirDetails &) const; + void getAgeIndicatorRec(DirDetails &details, QString &ret) const; + + virtual QVariant displayRole(const DirDetails&,int) const = 0 ; + virtual QVariant sortRole(const QModelIndex&,const DirDetails&,int) const =0; + + QVariant decorationRole(const DirDetails&,int) const ; + + uint32_t ageIndicator; + + QIcon categoryIcon; + QIcon peerIcon; + + class RemoteIndex + { + public: + RemoteIndex() {} + RemoteIndex(std::string in_person, + std::string in_path, + int in_idx, + int in_row, + int in_column, + std::string in_name, + int in_size, + int in_type, + int in_ts, int in_rank) + :id(in_person), path(in_path), parent(in_idx), + row(in_row), column(in_column), + name(in_name), size(in_size), + type(in_type), timestamp(in_ts), rank(in_rank) + { + return; + } + + std::string id; + std::string path; + int parent; + int row; + int column; + + /* display info */ + std::string name; + int size; + int type; + int timestamp; + int rank; + + }; + + bool RemoteMode; + + mutable int nIndex; + mutable std::vector indexSet; + +}; + +// This class shows the classical hierarchical directory view of shared files +// Columns are: +// file name | Size | Age +// +class TreeStyle_RDM: public RetroshareDirModel +{ + Q_OBJECT + + public: + TreeStyle_RDM(bool mode) + : RetroshareDirModel(mode) + { + } + + virtual ~TreeStyle_RDM() ; + + protected: + /* These are all overloaded Virtual Functions */ + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual QVariant displayRole(const DirDetails&,int) const ; + virtual QVariant sortRole(const QModelIndex&,const DirDetails&,int) const ; + + virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex() ) const; + virtual QModelIndex parent ( const QModelIndex & index ) const; + virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const; +}; + +// This class shows a flat list of all shared files +// Columns are: +// file name | Owner | Size | Age +// +class FlatStyle_RDM: public RetroshareDirModel +{ + Q_OBJECT + + public: + FlatStyle_RDM(bool mode) + : RetroshareDirModel(mode) + { + } + + virtual ~FlatStyle_RDM() ; + + protected slots: + void updateRefs() ; + + protected: + virtual void postMods(); + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual QVariant displayRole(const DirDetails&,int) const ; + virtual QVariant sortRole(const QModelIndex&,const DirDetails&,int) const ; + + virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex() ) const; + virtual QModelIndex parent ( const QModelIndex & index ) const; + virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const; + + QString computeDirectoryPath(const DirDetails& details) const ; + + std::vector > _ref_entries ;// used to store the refs to display + std::vector _ref_stack ; // used to store the refs to update +}; + + +#endif diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp new file mode 100644 index 000000000..82e1bd4cf --- /dev/null +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -0,0 +1,1011 @@ +/*************************************************************************** + * Copyright (C) 2009 * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "RetroShareLink.h" +#include "MainWindow.h" +#include "ForumsDialog.h" +#include "ChannelFeed.h" +#include "SearchDialog.h" +#include "msgs/MessageComposer.h" +#include "util/misc.h" +#include "common/PeerDefs.h" +#include "gui/connect/ConfCertDialog.h" + +#include +#include +#include +#include + +//#define DEBUG_RSLINK 1 + +#define HOST_FILE "file" +#define HOST_PERSON "person" +#define HOST_FORUM "forum" +#define HOST_CHANNEL "channel" +#define HOST_MESSAGE "message" +#define HOST_REGEXP "file|person|forum|channel|search|message" + +#define FILE_NAME "name" +#define FILE_SIZE "size" +#define FILE_HASH "hash" + +#define PERSON_NAME "name" +#define PERSON_HASH "hash" + +#define FORUM_NAME "name" +#define FORUM_ID "id" +#define FORUM_MSGID "msgid" + +#define CHANNEL_NAME "name" +#define CHANNEL_ID "id" +#define CHANNEL_MSGID "msgid" + +#define MESSAGE_ID "id" +#define MESSAGE_SUBJECT "subject" + +#define HOST_SEARCH "search" +#define SEARCH_KEYWORDS "keywords" + +RetroShareLink::RetroShareLink(const QUrl& url) +{ + fromUrl(url); +} + +RetroShareLink::RetroShareLink(const QString& url) +{ + fromString(url); +} + +void RetroShareLink::fromString(const QString& url) +{ + clear(); + + // parse +#ifdef DEBUG_RSLINK + std::cerr << "got new RS link \"" << url.toStdString() << "\"" << std::endl ; +#endif + + if ((url.startsWith(QString(RSLINK_SCHEME) + "://" + QString(HOST_FILE)) && url.count("|") == 3) || + (url.startsWith(QString(RSLINK_SCHEME) + "://" + QString(HOST_PERSON)) && url.count("|") == 2)) { + /* Old link, we try it */ + QStringList list = url.split ("|"); + + if (list.size() >= 1) { + if (list.size() == 4 && list[0] == QString(RSLINK_SCHEME) + "://" + QString(HOST_FILE)) { + bool ok ; + + _type = TYPE_FILE; + _name = list[1] ; + _size = list[2].toULongLong(&ok) ; + _hash = list[3].left(40) ; // normally not necessary, but it's a security. + + if (ok) { +#ifdef DEBUG_RSLINK + std::cerr << "New RetroShareLink forged:" << std::endl ; + std::cerr << " name = \"" << _name.toStdString() << "\"" << std::endl ; + std::cerr << " hash = \"" << _hash.toStdString() << "\"" << std::endl ; + std::cerr << " size = " << _size << std::endl ; +#endif + check(); + return; + } + } else if (list.size() == 3 && list[0] == QString(RSLINK_SCHEME) + "://" + QString(HOST_PERSON)) { + _type = TYPE_PERSON; + _name = list[1] ; + _hash = list[2].left(40) ; // normally not necessary, but it's a security. + _size = 0; + check(); + return; + } + + // bad link + } + } + + /* Now try QUrl */ + fromUrl(QUrl::fromEncoded(url.toAscii())); +} + +void RetroShareLink::fromUrl(const QUrl& url) +{ + clear(); + + // parse +#ifdef DEBUG_RSLINK + std::cerr << "got new RS link \"" << url.toString().toStdString() << "\"" << std::endl ; +#endif + + if (url.scheme() != RSLINK_SCHEME) { + /* No RetroShare-Link */ + return; + } + + if (url.host() == HOST_FILE) { + bool ok ; + + _type = TYPE_FILE; + _name = url.queryItemValue(FILE_NAME); + _size = url.queryItemValue(FILE_SIZE).toULongLong(&ok); + _hash = url.queryItemValue(FILE_HASH).left(40); // normally not necessary, but it's a security. + + if (ok) { +#ifdef DEBUG_RSLINK + std::cerr << "New RetroShareLink forged:" << std::endl ; + std::cerr << " name = \"" << _name.toStdString() << "\"" << std::endl ; + std::cerr << " hash = \"" << _hash.toStdString() << "\"" << std::endl ; + std::cerr << " size = " << _size << std::endl ; +#endif + check(); + return; + } + } + + if (url.host() == HOST_PERSON) { + _type = TYPE_PERSON; + _name = url.queryItemValue(PERSON_NAME); + _hash = url.queryItemValue(PERSON_HASH).left(40); // normally not necessary, but it's a security. + check(); + return; + } + + if (url.host() == HOST_FORUM) { + _type = TYPE_FORUM; + _name = url.queryItemValue(FORUM_NAME); + _hash = url.queryItemValue(FORUM_ID); + _msgId = url.queryItemValue(FORUM_MSGID); + check(); + return; + } + + if (url.host() == HOST_CHANNEL) { + _type = TYPE_CHANNEL; + _name = url.queryItemValue(CHANNEL_NAME); + _hash = url.queryItemValue(CHANNEL_ID); + _msgId = url.queryItemValue(CHANNEL_MSGID); + check(); + return; + } + + if (url.host() == HOST_SEARCH) { + _type = TYPE_SEARCH; + _name = url.queryItemValue(SEARCH_KEYWORDS); + check(); + return; + } + + if (url.host() == HOST_MESSAGE) { + _type = TYPE_MESSAGE; + std::string id = url.queryItemValue(MESSAGE_ID).toStdString(); + createMessage(id, url.queryItemValue(MESSAGE_SUBJECT)); + return; + } + + // bad link + +#ifdef DEBUG_RSLINK + std::cerr << "Wrongly formed RS link. Can't process." << std::endl ; +#endif + clear(); +} + +RetroShareLink::RetroShareLink() +{ + clear(); +} + +bool RetroShareLink::createFile(const QString& name, uint64_t size, const QString& hash) +{ + clear(); + + _name = name; + _size = size; + _hash = hash; + + _type = TYPE_FILE; + + check(); + + return valid(); +} + +bool RetroShareLink::createPerson(const std::string& id) +{ + clear(); + + RsPeerDetails detail; + if (rsPeers->getPeerDetails(id, detail) == false) { + std::cerr << "RetroShareLink::createPerson() Couldn't find peer id " << id << std::endl; + return false; + } + + _hash = QString::fromStdString(id); + _name = QString::fromUtf8(detail.name.c_str()); + + _type = TYPE_PERSON; + + check(); + + return valid(); +} + +bool RetroShareLink::createForum(const std::string& id, const std::string& msgId) +{ + clear(); + + if (!id.empty()) { + _hash = QString::fromStdString(id); + _msgId = QString::fromStdString(msgId); + + _type = TYPE_FORUM; + + if (msgId.empty()) { + ForumInfo fi; + if (rsForums->getForumInfo(id, fi)) { + _name = QString::fromStdWString(fi.forumName); + } + } else { + ForumMsgInfo mi; + if (rsForums->getForumMessage(id, msgId, mi)) { + _name = QString::fromStdWString(mi.title); + } + } + } + + check(); + + return valid(); +} + +bool RetroShareLink::createChannel(const std::string& id, const std::string& msgId) +{ + clear(); + + if (!id.empty()) { + _hash = QString::fromStdString(id); + _msgId = QString::fromStdString(msgId); + + _type = TYPE_CHANNEL; + + if (msgId.empty()) { + ChannelInfo ci; + if (rsChannels->getChannelInfo(id, ci)) { + _name = QString::fromStdWString(ci.channelName); + } + } else { + ChannelMsgInfo mi; + if (rsChannels->getChannelMessage(id, msgId, mi)) { + _name = QString::fromStdWString(mi.subject); + } + } + } + + check(); + + return valid(); +} + +bool RetroShareLink::createSearch(const QString& keywords) +{ + clear(); + + _name = keywords; + + _type = TYPE_SEARCH; + + check(); + + return valid(); +} + +bool RetroShareLink::createMessage(const std::string& peerId, const QString& subject) +{ + clear(); + + _hash = QString::fromStdString(peerId); + PeerDefs::rsidFromId(peerId, &_name); + _subject = subject; + + _type = TYPE_MESSAGE; + + check(); + + return valid(); +} + +void RetroShareLink::clear() +{ + _valid = false; + _type = TYPE_UNKNOWN; + _hash = "" ; + _size = 0 ; + _name = "" ; +} + +void RetroShareLink::check() +{ + _valid = true; + + switch (_type) { + case TYPE_UNKNOWN: + _valid = false; + break; + case TYPE_FILE: + if(_size > (((uint64_t)1)<<40)) // 1TB. Who has such large files? + _valid = false; + + if(!checkName(_name)) + _valid = false; + + if(!checkHash(_hash)) + _valid = false; + break; + case TYPE_PERSON: + if(_size != 0) + _valid = false; + + if(_name.isEmpty()) + _valid = false; + + if(_hash.isEmpty()) + _valid = false; + break; + case TYPE_FORUM: + if(_size != 0) + _valid = false; + + if(_name.isEmpty()) + _valid = false; + + if(_hash.isEmpty()) + _valid = false; + break; + case TYPE_CHANNEL: + if(_size != 0) + _valid = false; + + if(_name.isEmpty()) + _valid = false; + + if(_hash.isEmpty()) + _valid = false; + break; + case TYPE_SEARCH: + if(_size != 0) + _valid = false; + + if(_name.isEmpty()) + _valid = false; + + if(!_hash.isEmpty()) + _valid = false; + break; + case TYPE_MESSAGE: + if(_size != 0) + _valid = false; + + if(_hash.isEmpty()) + _valid = false; + break; + } + + if (!_valid) { + clear(); + } +} + +QString RetroShareLink::title() const +{ + if (!valid()) { + return ""; + } + + switch (_type) { + case TYPE_UNKNOWN: + break; + case TYPE_FILE: + return QString("%1 (%2)").arg(hash()).arg(misc::friendlyUnit(size())); + case TYPE_PERSON: + return PeerDefs::rsidFromId(hash().toStdString()); + case TYPE_FORUM: + case TYPE_CHANNEL: + case TYPE_SEARCH: + break; + case TYPE_MESSAGE: + return PeerDefs::rsidFromId(hash().toStdString()); + } + + return ""; +} + +QString RetroShareLink::toString(bool encoded /*= true*/) const +{ + switch (_type) { + case TYPE_UNKNOWN: + break; + case TYPE_FILE: + { + QUrl url; + url.setScheme(RSLINK_SCHEME); + url.setHost(HOST_FILE); + url.addQueryItem(FILE_NAME, _name); + url.addQueryItem(FILE_SIZE, QString::number(_size)); + url.addQueryItem(FILE_HASH, _hash); + + if (encoded) { + return url.toEncoded(); + } + + return url.toString(); + } + case TYPE_PERSON: + { + QUrl url; + url.setScheme(RSLINK_SCHEME); + url.setHost(HOST_PERSON); + url.addQueryItem(PERSON_NAME, _name); + url.addQueryItem(PERSON_HASH, _hash); + + if (encoded) { + return url.toEncoded(); + } + + return url.toString(); + } + case TYPE_FORUM: + { + QUrl url; + url.setScheme(RSLINK_SCHEME); + url.setHost(HOST_FORUM); + url.addQueryItem(FORUM_NAME, _name); + url.addQueryItem(FORUM_ID, _hash); + if (!_msgId.isEmpty()) { + url.addQueryItem(FORUM_MSGID, _msgId); + } + + if (encoded) { + return url.toEncoded(); + } + + return url.toString(); + } + case TYPE_CHANNEL: + { + QUrl url; + url.setScheme(RSLINK_SCHEME); + url.setHost(HOST_CHANNEL); + url.addQueryItem(CHANNEL_NAME, _name); + url.addQueryItem(CHANNEL_ID, _hash); + if (!_msgId.isEmpty()) { + url.addQueryItem(CHANNEL_MSGID, _msgId); + } + + if (encoded) { + return url.toEncoded(); + } + + return url.toString(); + } + case TYPE_SEARCH: + { + QUrl url; + url.setScheme(RSLINK_SCHEME); + url.setHost(HOST_SEARCH); + url.addQueryItem(SEARCH_KEYWORDS, _name); + + if (encoded) { + return url.toEncoded(); + } + + return url.toString(); + } + case TYPE_MESSAGE: + { + QUrl url; + url.setScheme(RSLINK_SCHEME); + url.setHost(HOST_MESSAGE); + url.addQueryItem(MESSAGE_ID, _hash); + if (_subject.isEmpty() == false) { + url.addQueryItem(MESSAGE_SUBJECT, _subject); + } + + if (encoded) { + return url.toEncoded(); + } + + return url.toString(); + } + } + + return ""; +} + +QString RetroShareLink::niceName() const +{ + if (type() == TYPE_PERSON) { + return PeerDefs::rsid(name().toStdString(), hash().toStdString()); + } + + return name(); +} + +QString RetroShareLink::toHtml() const +{ + QString html = "" ; + + return html; +} + +QString RetroShareLink::toHtmlFull() const +{ + return QString("" + toString(false) + "" ; +} + +QString RetroShareLink::toHtmlSize() const +{ + return QString("" + name() +"" + " " + "" + "(" + misc::friendlyUnit(_size) + ")" +""; +} + +bool RetroShareLink::checkName(const QString& name) +{ + if(name == "") + return false ; + + for(int i=0;i47 && b<58) || (b>96 && b<103))) + return false ; + } + + return true ; +} + +bool RetroShareLink::process(int flag) +{ + if (valid() == false) { + std::cerr << " RetroShareLink::process invalid request" << std::endl; + return false; + } + + switch (type()) { + case TYPE_UNKNOWN: + break; + + case TYPE_FILE: + { +#ifdef DEBUG_RSLINK + std::cerr << " RetroShareLink::process FileRequest : fileName : " << name().toUtf8().constData() << ". fileHash : " << hash().toStdString() << ". fileSize : " << size() << std::endl; +#endif + + // Get a list of available direct sources, in case the file is browsable only. + std::list srcIds; + FileInfo finfo ; + rsFiles->FileDetails(hash().toStdString(), RS_FILE_HINTS_REMOTE,finfo) ; + + for(std::list::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it) + { +#ifdef DEBUG_RSLINK + std::cerr << " adding peerid " << (*it).peerId << std::endl ; +#endif + srcIds.push_back((*it).peerId) ; + } + + if (rsFiles->FileRequest(name().toUtf8().constData(), hash().toStdString(), size(), "", RS_FILE_HINTS_NETWORK_WIDE, srcIds)) { + if (flag & RSLINK_PROCESS_NOTIFY_SUCCESS) { + QMessageBox mb(QObject::tr("File Request Confirmation"), QObject::tr("The file has been added to your download list."),QMessageBox::Information,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return true; + } + + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("File Request canceled"), QObject::tr("The file has not been added to your download list, because you already have it."),QMessageBox::Critical,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return false; + } + + case TYPE_PERSON: + { +#ifdef DEBUG_RSLINK + std::cerr << " RetroShareLink::process FriendRequest : name : " << name().toStdString() << ". id : " << hash().toStdString() << std::endl; +#endif + + RsPeerDetails detail; + if (rsPeers->getPeerDetails(hash().toStdString(), detail)) { + if (detail.gpg_id == rsPeers->getGPGOwnId()) { + // it's me, do nothing + return true; + } + + if (detail.accept_connection) { + // peer connection is already accepted + if (flag & RSLINK_PROCESS_NOTIFY_SUCCESS) { + QMessageBox mb(QObject::tr("Friend Request Confirmation"), QObject::tr("The friend is already in your list."),QMessageBox::Information,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return true; + } + + if (rsPeers->setAcceptToConnectGPGCertificate(hash().toStdString(), true)) { + ConfCertDialog::loadAll(); + if (flag & RSLINK_PROCESS_NOTIFY_SUCCESS) { + QMessageBox mb(QObject::tr("Friend Request Confirmation"), QObject::tr("The friend has been added to your list."),QMessageBox::Information,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return true; + } + + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("Friend Request canceled"), QObject::tr("The friend could not be added to your list."),QMessageBox::Critical,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return false; + } + + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("Friend Request canceled"), QObject::tr("The friend could not be found."),QMessageBox::Critical,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return false; + } + + case TYPE_FORUM: + { +#ifdef DEBUG_RSLINK + std::cerr << " RetroShareLink::process ForumRequest : name : " << name().toStdString() << ". id : " << hash().toStdString() << ". msgId : " << msgId().toStdString() << std::endl; +#endif + + ForumInfo fi; + if (!rsForums->getForumInfo(id().toStdString(), fi)) { + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("Forum Request canceled"), QObject::tr("The forum \"%1\" could not be found.").arg(name()),QMessageBox::Critical,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return false; + } + + ForumMsgInfo msg; + if (!msgId().isEmpty()) { + if (!rsForums->getForumMessage(fi.forumId, msgId().toStdString(), msg)) { + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("Forum Request canceled"), QObject::tr("The forum message in forum \"%1\" could not be found.").arg(name()),QMessageBox::Critical,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return false; + } + } + + MainWindow::showWindow(MainWindow::Forums); + ForumsDialog *forumsDialog = dynamic_cast(MainWindow::getPage(MainWindow::Forums)); + if (!forumsDialog) { + return false; + } + + return forumsDialog->navigate(fi.forumId, msg.msgId); + } + + case TYPE_CHANNEL: + { +#ifdef DEBUG_RSLINK + std::cerr << " RetroShareLink::process ChannelRequest : name : " << name().toStdString() << ". id : " << hash().toStdString() << ". msgId : " << msgId().toStdString() << std::endl; +#endif + + ChannelInfo ci; + if (!rsChannels->getChannelInfo(id().toStdString(), ci)) { + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("Channel Request canceled"), QObject::tr("The channel \"%1\" could not be found.").arg(name()),QMessageBox::Critical,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return false; + } + + ChannelMsgInfo msg; + if (!msgId().isEmpty()) { + if (!rsChannels->getChannelMessage(ci.channelId, msgId().toStdString(), msg)) { + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("Channel Request canceled"), QObject::tr("The channel message in channel \"%1\" could not be found.").arg(name()),QMessageBox::Critical,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return false; + } + } + + MainWindow::showWindow(MainWindow::Channels); + ChannelFeed *channelFeed = dynamic_cast(MainWindow::getPage(MainWindow::Channels)); + if (!channelFeed) { + return false; + } + + return channelFeed->navigate(ci.channelId, msg.msgId); + } + + case TYPE_SEARCH: + { +#ifdef DEBUG_RSLINK + std::cerr << " RetroShareLink::process SearchRequest : string : " << name().toStdString() << std::endl; +#endif + + MainWindow::showWindow(MainWindow::Search); + SearchDialog *searchDialog = dynamic_cast(MainWindow::getPage(MainWindow::Search)); + if (!searchDialog) { + return false; + } + + searchDialog->searchKeywords(name()); + return true; + } + + case TYPE_MESSAGE: + { +#ifdef DEBUG_RSLINK + std::cerr << " RetroShareLink::process MessageRequest : id : " << _hash.toStdString() << ", subject : " << name().toStdString() << std::endl; +#endif + RsPeerDetails detail; + if (rsPeers->getPeerDetails(hash().toStdString(), detail)) { + if (detail.accept_connection || detail.id == rsPeers->getOwnId() || detail.id == rsPeers->getGPGOwnId()) { + MessageComposer *msg = MessageComposer::newMsg(); + msg->addRecipient(MessageComposer::TO, detail.id, false); + if (subject().isEmpty() == false) { + msg->insertTitleText(subject()); + } + msg->show(); + + return true; + } else { + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("Message Request canceled"), QObject::tr("Cannot send a message to a not accepted receipient \"%1\".").arg(hash()), QMessageBox::Critical, QMessageBox::Ok, 0, 0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + } + } else { + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("Message Request canceled"), QObject::tr("The receipient of the message is unknown."), QMessageBox::Critical, QMessageBox::Ok, 0, 0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + } + + return false; + } + } + + std::cerr << " RetroShareLink::process unknown type: " << type() << std::endl; + + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + QMessageBox mb(QObject::tr("File Request Error"), QObject::tr("The file link is malformed."),QMessageBox::Critical,QMessageBox::Ok,0,0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + return false; +} + +/*static*/ int RetroShareLink::process(QStringList &urls, RetroShareLink::enumType type /*= RetroShareLink::TYPE_UNKNOWN*/, bool notify /*= true*/) +{ + int processed = 0; + + for (QStringList::iterator it = urls.begin(); it != urls.end(); it++) { + RetroShareLink link(*it); + if (link.valid() && (type == RetroShareLink::TYPE_UNKNOWN || link.type() == type)) { + if (link.process(0)) { + processed++; + } + } + } + + if (notify) { + QString text = QObject::tr("%1 of %2 RetroShare links processed.").arg(processed).arg(urls.count()); + QMessageBox mb(QObject::tr("Request Confirmation"), text, QMessageBox::Information, QMessageBox::Ok, 0, 0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + + return processed; +} + +void RSLinkClipboard::copyLinks(const std::vector& links) +{ + QString res ; + for(uint32_t i=0;isetText(res) ; +} + +void RSLinkClipboard::pasteLinks(std::vector &links) +{ + return parseClipboard(links); +} + +void RSLinkClipboard::parseClipboard(std::vector &links) +{ + // parse clipboard for links. + // + links.clear(); + QString text = QApplication::clipboard()->text() ; + + std::cerr << "Parsing clipboard:" << text.toStdString() << std::endl ; + + QRegExp rx(QString("retroshare://(%1)[^\r\n]+").arg(HOST_REGEXP)); + + int pos = 0; + + while((pos = rx.indexIn(text, pos)) != -1) + { + QString url(text.mid(pos, rx.matchedLength())); + RetroShareLink link(url); + + if(link.valid()) + { + // check that the link is not already in the list: + bool already = false ; + for(uint32_t i=0;i links; + parseClipboard(links); + + QString res ; + for(uint32_t i=0;i links; + parseClipboard(links); + + QString res ; + for(uint32_t i=0;i" ; + + return res ; +} + +QString RSLinkClipboard::toHtmlFull() +{ + std::vector links; + parseClipboard(links); + + QString res ; + for(uint32_t i=0;i" ; + + return res ; +} + +bool RSLinkClipboard::empty(RetroShareLink::enumType type /*= RetroShareLink::TYPE_UNKNOWN*/) +{ + std::vector links; + parseClipboard(links); + + if (type == RetroShareLink::TYPE_UNKNOWN) { + return links.empty(); + } + + for (std::vector::iterator link = links.begin(); link != links.end(); link++) { + if (link->type() == type) { + return false; + } + } + + return true; +} + +/*static*/ int RSLinkClipboard::process(RetroShareLink::enumType type /*= RetroShareLink::TYPE_UNKNOWN*/, int flag /*= RSLINK_PROCESS_NOTIFY_ALL*/) +{ + std::vector links; + pasteLinks(links); + + int count = 0; + + for (uint32_t i = 0; i < links.size(); i++) { + if (links[i].valid() && (type == RetroShareLink::TYPE_UNKNOWN || links[i].type() == type)) { + if (links[i].process(flag)) { + count++; + } + } + } + + return count; +} diff --git a/retroshare-gui/src/gui/RetroShareLink.h b/retroshare-gui/src/gui/RetroShareLink.h new file mode 100644 index 000000000..260ffb9ad --- /dev/null +++ b/retroshare-gui/src/gui/RetroShareLink.h @@ -0,0 +1,164 @@ +/*************************************************************************** + * Copyright (C) 2009 Cyril Soler * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef RETROSHARE_LINK_ANALYZER +#define RETROSHARE_LINK_ANALYZER + +// This class implements a RS link. +// +// The link is done in a way that if valid()==true, then the link can be used. +// +// The following combinations have been tested: +// copy paste-> Transfers (DL) | Message compose (forums) | Private msg | Public chat | private Chat +// -------------+----------------+--------------------------+------------------+-------------+------------- +// search | Y | Y | Y (send RS link) | Paste menu? | Paste menu? +// -------------+----------------+--------------------------+------------------+-------------+------------- +// shared | Y | Y | Y (send RS link) | Paste menu? | Paste menu? +// -------------+----------------+--------------------------+------------------+-------------+------------- +// +#include +#include +#include +#include + +#define RSLINK_PROCESS_NOTIFY_SUCCESS 1 // notify on success +#define RSLINK_PROCESS_NOTIFY_ERROR 2 // notify on error + +#define RSLINK_PROCESS_NOTIFY_ALL -1 + +#define RSLINK_SCHEME "retroshare" + +class RetroShareLink +{ + public: + enum enumType { TYPE_UNKNOWN, TYPE_FILE, TYPE_PERSON, TYPE_FORUM, TYPE_CHANNEL, TYPE_SEARCH, TYPE_MESSAGE }; + + public: + RetroShareLink(); + RetroShareLink(const QUrl& url); + RetroShareLink(const QString& url); + + bool createFile(const QString& name, uint64_t size, const QString& hash); + bool createPerson(const std::string& id); + bool createForum(const std::string& id, const std::string& msgId); + bool createChannel(const std::string& id, const std::string& msgId); + bool createSearch(const QString& keywords); + bool createMessage(const std::string& peerId, const QString& subject); + + enumType type() const {return _type; } + uint64_t size() const { return _size ; } + const QString& name() const { return _name ; } + const QString& hash() const { return _hash ; } + const QString& id() const { return _hash ; } + const QString& msgId() const { return _msgId ; } + const QString& subject() const { return _subject ; } + QString title() const; + + // get nice name for anchor + QString niceName() const; + + /// returns the string retroshare://file?name=&size=&hash= + /// retroshare://person?name=&hash= + QString toString(bool encoded = true) const ; + /// returns the string name + /// name@hash + QString toHtml() const ; + /// returns the string retroshare://file?name=&size=&hash= + /// retroshare://person?name=&hash= + QString toHtmlFull() const ; + + QString toHtmlSize() const ; + + QUrl toUrl() const ; + + bool valid() const { return _valid; } + + bool operator==(const RetroShareLink& l) const { return _type == l._type && _hash == l._hash ; } + + bool process(int flag); + + static int process(QStringList &urls, RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN, bool notify = true); + + private: + void fromString(const QString &url); + void fromUrl(const QUrl &url); + void clear(); + void check(); + static bool checkHash(const QString& hash); + static bool checkName(const QString& name); + + bool _valid; + enumType _type; + QString _name; + uint64_t _size; + QString _hash; // or id (forum, channel, message) + QString _msgId; // id of the message (forum, channel) + QString _subject; +}; + +/// This class handles the copy/paste of links. Every member is static to ensure unicity. +/// I put no mutex, because all calls supposely com from the GUI thread. +/// +/// All links are stored in html format into the clipboard. Why? Because this allows to import +/// links from both the clipboard and the RS application, e.g. paste links from an internet forum. +/// This requires many clipboard parsing operations, but this is not a problem because this code is +/// not performances-critical. +// +class RSLinkClipboard +{ + public: + // Copy these links to the RS clipboard. Also copy them to the system clipboard + // + static void copyLinks(const std::vector& links) ; + + // Get the liste of pasted links, either from the internal RS links, or by default + // from the clipboard. + // + static void pasteLinks(std::vector &links) ; + + // Produces a list of links with no html structure. + static QString toString() ; + + // produces a list of html links that displays with the file names only + // + static QString toHtml(); + + // produces a list of html links that displays the full links + // + static QString toHtmlFull(); + + // produces a list of html links that displays with the file name + filesize + // + static QString toHtmlSize(); + + // Returns true is no links are found to paste. + // Useful for menus. + // + static bool empty(RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN); + + // Returns the count of processed links + // Useful for menus. + // + static int process(RetroShareLink::enumType type = RetroShareLink::TYPE_UNKNOWN, int flag = RSLINK_PROCESS_NOTIFY_ALL); + + private: + static void parseClipboard(std::vector &links) ; +}; + +#endif diff --git a/retroshare-gui/src/gui/RsAutoUpdatePage.cpp b/retroshare-gui/src/gui/RsAutoUpdatePage.cpp new file mode 100644 index 000000000..ecd794fe1 --- /dev/null +++ b/retroshare-gui/src/gui/RsAutoUpdatePage.cpp @@ -0,0 +1,49 @@ +#include +#include +#include "RsAutoUpdatePage.h" +#include "MessengerWindow.h" + +bool RsAutoUpdatePage::_locked = false ; + +RsAutoUpdatePage::RsAutoUpdatePage(int ms_update_period,QWidget *parent) + : MainPage(parent) +{ + _timer = new QTimer ; + _timer->setInterval(ms_update_period); + _timer->setSingleShot(true); + + QObject::connect(_timer,SIGNAL(timeout()),this,SLOT(timerUpdate())) ; + + _timer->start() ; +} + +RsAutoUpdatePage::~RsAutoUpdatePage() +{ + if(_timer != NULL) + delete _timer ; + + _timer = NULL ; +} + +void RsAutoUpdatePage::showEvent(QShowEvent *event) +{ + //std::cout << "RsAutoUpdatePage::showEvent() In show event !!" << std::endl ; + if(!_locked) + updateDisplay(); +} + +void RsAutoUpdatePage::timerUpdate() +{ + // only update when the widget is visible. + // + if(_locked == false && isVisible()) { + updateDisplay(); + update() ; // Qt flush + } + + _timer->start() ; +} + +void RsAutoUpdatePage::lockAllEvents() { _locked = true ; } +void RsAutoUpdatePage::unlockAllEvents() { _locked = false ; } +bool RsAutoUpdatePage::eventsLocked() { return _locked ; } diff --git a/retroshare-gui/src/gui/RsAutoUpdatePage.h b/retroshare-gui/src/gui/RsAutoUpdatePage.h new file mode 100644 index 000000000..2116a7200 --- /dev/null +++ b/retroshare-gui/src/gui/RsAutoUpdatePage.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include "mainpage.h" + +// This class implement a basic RS functionality which is that widgets displayign info +// should update regularly. They also should update only when visible, to save CPU time. +// +// Using this class simply needs to derive your widget from RsAutoUpdateWidget +// and oveload the update() function with the actual code that updates the +// widget. +// +class QTimer ; + +class RsAutoUpdatePage: public MainPage +{ + Q_OBJECT + + public: + RsAutoUpdatePage(int ms_update_period = 1000,QWidget *parent=NULL) ; + virtual ~RsAutoUpdatePage() ; + + virtual void updateDisplay() {} + + static void lockAllEvents() ; + static void unlockAllEvents() ; + static bool eventsLocked() ; + + protected: + virtual void showEvent(QShowEvent *e) ; + + private slots: + void timerUpdate() ; + + private: + QTimer *_timer ; + + static bool _locked ; +}; + diff --git a/retroshare-gui/src/gui/SFListDelegate.cpp b/retroshare-gui/src/gui/SFListDelegate.cpp new file mode 100644 index 000000000..1b2c29ba6 --- /dev/null +++ b/retroshare-gui/src/gui/SFListDelegate.cpp @@ -0,0 +1,109 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include + +#include "SFListDelegate.h" + +SFListDelegate::SFListDelegate(QObject *parent) : QAbstractItemDelegate(parent) +{ + ; +} + +SFListDelegate::~SFListDelegate(void) +{ + ; +} + +void SFListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const +{ + QString byteUnits[4] = {tr("B"), tr("KB"), tr("MB"), tr("GB")}; + QStyleOptionViewItem opt = option; + QStyleOptionProgressBarV2 newopt; + QRect pixmapRect; + QPixmap pixmap; + qlonglong fileSize; + double multi; + QString temp , status; + + + //set text color + QVariant value = index.data(Qt::TextColorRole); + if(value.isValid() && qvariant_cast(value).isValid()) { + opt.palette.setColor(QPalette::Text, qvariant_cast(value)); + } + QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; + if(option.state & QStyle::State_Selected){ + painter->setPen(opt.palette.color(cg, QPalette::HighlightedText)); + } else { + painter->setPen(opt.palette.color(cg, QPalette::Text)); + } + switch(index.column()) { + case FSIZE: + fileSize = index.data().toLongLong(); + if(fileSize < 0){ + temp = "Unknown"; + } else { + multi = 1.0; + for(int i = 0; i < 5; ++i) { + if (fileSize < 1024) { + fileSize = index.data().toLongLong(); + temp.sprintf("%.2f ", fileSize / multi); + temp += byteUnits[i]; + break; + } + fileSize /= 1024; + multi *= 1024.0; + } + } + painter->drawText(option.rect, Qt::AlignRight, temp); + break; + case FNAME: + // decoration + value = index.data(Qt::DecorationRole); + pixmap = qvariant_cast(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); + pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); + if (pixmapRect.isValid()){ + QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft(); + painter->drawPixmap(p, pixmap); + } + painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft, index.data().toString()); + break; + default: + painter->drawText(option.rect, Qt::AlignCenter, index.data().toString()); + } +} + +QSize SFListDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const +{ + return QSize(50,17); + QVariant value = index.data(Qt::FontRole); + QFont fnt = value.isValid() ? qvariant_cast(value) : option.font; + QFontMetrics fontMetrics(fnt); + const QString text = index.data(Qt::DisplayRole).toString(); + QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1)); + return textRect.size(); +} + diff --git a/retroshare-gui/src/gui/SFListDelegate.h b/retroshare-gui/src/gui/SFListDelegate.h new file mode 100644 index 000000000..26820a646 --- /dev/null +++ b/retroshare-gui/src/gui/SFListDelegate.h @@ -0,0 +1,60 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef SFLISTDELEGATE_H +#define SFLISTDELEGATE_H + +#include + +// Defines for download list list columns +#define FNAME 0 +#define FSIZE 1 + + + + +#define MAX_CHAR_TMP 128 + +class QModelIndex; +class QPainter; +class QStyleOptionProgressBarV2; +class QProgressBar; +class QApplication; + + +class SFListDelegate: public QAbstractItemDelegate { + + Q_OBJECT + + public: + SFListDelegate(QObject *parent=0); + ~SFListDelegate(); + void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; + QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const; + + private: + + public slots: + + signals: +}; +#endif + diff --git a/retroshare-gui/src/gui/SearchDialog.cpp b/retroshare-gui/src/gui/SearchDialog.cpp new file mode 100644 index 000000000..f9e8729af --- /dev/null +++ b/retroshare-gui/src/gui/SearchDialog.cpp @@ -0,0 +1,1491 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include + +#include "SearchDialog.h" +#include "RetroShareLink.h" +#include "msgs/MessageComposer.h" +#include "gui/RSHumanReadableDelegate.h" +#include "gui/RsAutoUpdatePage.h" +#include "settings/rsharesettings.h" +#include "advsearch/advancedsearchdialog.h" + +#include +#include +#include + +/* Images for context menu icons */ +#define IMAGE_START ":/images/download.png" +#define IMAGE_REMOVE ":/images/delete.png" +#define IMAGE_REMOVEALL ":/images/deleteall.png" +#define IMAGE_DIRECTORY ":/images/folder16.png" + +/* Key for UI Preferences */ +#define UI_PREF_ADVANCED_SEARCH "UIOptions/AdvancedSearch" + +/* indicies for search results item columns SR_ = Search Result */ +/* indicies for search results item columns SR_ = Search Result */ +#define SR_NAME_COL 0 +#define SR_SIZE_COL 1 +#define SR_ID_COL 2 +#define SR_TYPE_COL 3 +#define SR_AGE_COL 4 +#define SR_HASH_COL 5 +#define SR_SEARCH_ID_COL 6 +#define SR_UID_COL 7 + +/* indicies for search summary item columns SS_ = Search Summary */ +#define SS_TEXT_COL 0 +#define SS_COUNT_COL 1 +#define SS_SEARCH_ID_COL 2 + +#define IMAGE_COPYLINK ":/images/copyrslink.png" + +/* static members */ +/* These indices MUST be identical to their equivalent indices in the combobox */ +const int SearchDialog::FILETYPE_IDX_ANY = 0; +const int SearchDialog::FILETYPE_IDX_ARCHIVE = 1; +const int SearchDialog::FILETYPE_IDX_AUDIO = 2; +const int SearchDialog::FILETYPE_IDX_CDIMAGE = 3; +const int SearchDialog::FILETYPE_IDX_DOCUMENT = 4; +const int SearchDialog::FILETYPE_IDX_PICTURE = 5; +const int SearchDialog::FILETYPE_IDX_PROGRAM = 6; +const int SearchDialog::FILETYPE_IDX_VIDEO = 7; +const int SearchDialog::FILETYPE_IDX_DIRECTORY = 8; +QMap * SearchDialog::FileTypeExtensionMap = new QMap(); +bool SearchDialog::initialised = false; + +static int FilterColumnFromComboBox(int nIndex) +{ + switch (nIndex) { + case 0: + return SR_NAME_COL; + case 1: + return SR_SIZE_COL; + } + + return SR_NAME_COL; +} + +/** Constructor */ +SearchDialog::SearchDialog(QWidget *parent) +: MainPage(parent), + advSearchDialog(NULL), + nextSearchId(1) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + m_bProcessSettings = false; + + _queueIsAlreadyTakenCareOf = false ; + ui.lineEdit->setFocus(); + ui.lineEdit->setToolTip(tr("Enter a keyword here (at least 3 char long)")); + + /* initialise the filetypes mapping */ + if (!SearchDialog::initialised) + { + initialiseFileTypeMappings(); + } + + connect(ui.toggleAdvancedSearchBtn, SIGNAL(clicked()), this, SLOT(showAdvSearchDialog())); + + connect( ui.searchResultWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( searchtableWidgetCostumPopupMenu( QPoint ) ) ); + + connect( ui.searchSummaryWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( searchtableWidget2CostumPopupMenu( QPoint ) ) ); + + connect( ui.lineEdit, SIGNAL( returnPressed ( void ) ), this, SLOT( searchKeywords( void ) ) ); + connect( ui.lineEdit, SIGNAL( textChanged ( const QString& ) ), this, SLOT( checkText( const QString& ) ) ); + connect( ui.pushButtonsearch, SIGNAL( released ( void ) ), this, SLOT( searchKeywords( void ) ) ); + connect( ui.pushButtonDownload, SIGNAL( released ( void ) ), this, SLOT( download( void ) ) ); + connect( ui.cloaseallsearchresultsButton, SIGNAL(clicked()), this, SLOT(searchRemoveAll())); + connect( ui.resetButton, SIGNAL(clicked()), this, SLOT(clearKeyword())); + connect( ui.lineEdit, SIGNAL( textChanged(const QString &)), this, SLOT(togglereset())); + + connect( ui.searchResultWidget, SIGNAL( itemDoubleClicked ( QTreeWidgetItem *, int)), this, SLOT(download())); + + connect ( ui.searchSummaryWidget, SIGNAL( currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem * ) ), + this, SLOT( selectSearchResults( void ) ) ); + + connect(ui.FileTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectSearchResults(int))); + + connect( ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged())); + connect( ui.filterColumnComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterColumnChanged())); + connect( ui.clearButton, SIGNAL(clicked()), this, SLOT(clearFilter())); + + /* hide the Tree +/- */ + ui.searchResultWidget -> setRootIsDecorated( true ); + ui.searchResultWidget -> setColumnHidden( SR_UID_COL,true ); + ui.searchSummaryWidget -> setRootIsDecorated( false ); + + // We set some delegates to handle the display of size and date. + // To allow a proper sorting, be careful to pad at right with spaces. This + // is achieved by using QString("%1").arg(number,15,10). + // + ui.searchResultWidget->setItemDelegateForColumn(SR_SIZE_COL,new RSHumanReadableSizeDelegate()) ; + ui.searchResultWidget->setItemDelegateForColumn(SR_AGE_COL,new RSHumanReadableAgeDelegate()) ; + + /* make it extended selection */ + ui.searchResultWidget -> setSelectionMode(QAbstractItemView::ExtendedSelection); + + + /* Set header resize modes and initial section sizes */ + ui.searchSummaryWidget->setColumnCount(3); + ui.searchSummaryWidget->setColumnHidden ( 2, true); + + QHeaderView * _smheader = ui.searchSummaryWidget->header () ; + _smheader->setResizeMode (0, QHeaderView::Interactive); + _smheader->setResizeMode (1, QHeaderView::Interactive); + + _smheader->resizeSection ( 0, 160 ); + _smheader->resizeSection ( 1, 50 ); + + ui.searchResultWidget->setColumnCount(6); + _smheader = ui.searchResultWidget->header () ; + _smheader->setResizeMode (0, QHeaderView::Interactive); + _smheader->setResizeMode (1, QHeaderView::Interactive); + _smheader->setResizeMode (2, QHeaderView::Interactive); + + _smheader->resizeSection ( 0, 240 ); + _smheader->resizeSection ( 1, 75 ); + _smheader->resizeSection ( 2, 75 ); + _smheader->resizeSection ( 3, 75 ); + _smheader->resizeSection ( 4, 90 ); + _smheader->resizeSection ( 5, 240 ); + + + // set header text aligment + QTreeWidgetItem * headerItem = ui.searchResultWidget->headerItem(); + headerItem->setTextAlignment(1, Qt::AlignRight | Qt::AlignRight); + headerItem->setTextAlignment(2, Qt::AlignRight | Qt::AlignRight); + + ui.searchResultWidget->sortItems(SR_NAME_COL, Qt::AscendingOrder); + + ui.resetButton->hide(); + ui.clearButton->hide(); + + // load settings + processSettings(true); + + ui._ownFiles_CB->setMinimumWidth(20); + ui._friendListsearch_SB->setMinimumWidth(20); + ui._anonF2Fsearch_CB->setMinimumWidth(20); + ui.label->setMinimumWidth(20); + + // workaround for Qt bug, should be solved in next Qt release 4.7.0 + // http://bugreports.qt.nokia.com/browse/QTBUG-8270 + QShortcut *Shortcut = new QShortcut(QKeySequence (Qt::Key_Delete), ui.searchSummaryWidget, 0, 0, Qt::WidgetShortcut); + connect(Shortcut, SIGNAL(activated()), this, SLOT(searchRemove())); + +/* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +SearchDialog::~SearchDialog() +{ + // save settings + processSettings(false); +} + +void SearchDialog::processSettings(bool bLoad) +{ + m_bProcessSettings = true; + + QHeaderView *pHeader = ui.searchSummaryWidget->header () ; + + Settings->beginGroup(QString("SearchDialog")); + + if (bLoad) { + // load settings + + // state of SearchSummary tree + pHeader->restoreState(Settings->value("SearchSummaryTree").toByteArray()); + + // state of splitter + ui.splitter->restoreState(Settings->value("Splitter").toByteArray()); + } else { + // save settings + + // state of SearchSummary tree + Settings->setValue("SearchSummaryTree", pHeader->saveState()); + + // state of splitter + Settings->setValue("Splitter", ui.splitter->saveState()); + } + + Settings->endGroup(); + m_bProcessSettings = false; +} + + +void SearchDialog::checkText(const QString& txt) +{ + if(txt.length() < 3) + { + std::cout << "setting palette 1" << std::endl ; + ui.searchlineframe->setStyleSheet("QFrame#searchlineframe{ border: 2px solid #079E00; background-color: #DBDBDB; }"); + } + else + { + ui.searchlineframe->setStyleSheet("QFrame#searchlineframe{ border: 2px solid #079E00; background-color: white; }"); + std::cout << "setting palette 2" << std::endl ; + } +} + +void SearchDialog::initialiseFileTypeMappings() +{ + /* edit these strings to change the range of extensions recognised by the search */ + SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ANY, ""); + SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_AUDIO, + "aac aif flac iff m3u m4a mid midi mp3 mpa ogg ra ram wav wma"); + SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ARCHIVE, + "7z bz2 gz pkg rar sea sit sitx tar zip"); + SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_CDIMAGE, + "iso nrg mdf"); + SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_DOCUMENT, + "doc odt ott rtf pdf ps txt log msg wpd wps" ); + SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PICTURE, + "3dm 3dmf ai bmp drw dxf eps gif ico indd jpe jpeg jpg mng pcx pcc pct pgm " + "pix png psd psp qxd qxprgb sgi svg tga tif tiff xbm xcf"); + SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PROGRAM, + "app bat cgi com bin exe js pif py pl sh vb ws "); + SearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_VIDEO, + "3gp asf asx avi mov mp4 mkv flv mpeg mpg qt rm swf vob wmv"); + SearchDialog::initialised = true; +} + +void SearchDialog::searchtableWidgetCostumPopupMenu( QPoint point ) +{ + // block the popup if no results available + if ((ui.searchResultWidget->selectedItems()).size() == 0) return; + + QMenu contextMnu(this); + + contextMnu.addAction(QIcon(IMAGE_START), tr("Download"), this, SLOT(download())); + contextMnu.addSeparator(); + contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyResultLink())); + contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Send RetroShare Link"), this, SLOT(sendLinkTo())); + +// contextMnu.addAction(tr("Broadcast on Channel"), this, SLOT(broadcastonchannel())); +// contextMnu.addAction(tr("Recommend to Friends"), this, SLOT(recommendtofriends())); + + contextMnu.exec(QCursor::pos()); +} + +void SearchDialog::getSourceFriendsForHash(const std::string& hash,std::list& srcIds) +{ + std::cerr << "Searching sources for file " << hash << std::endl ; + srcIds.clear(); + + FileInfo finfo ; + rsFiles->FileDetails(hash, RS_FILE_HINTS_REMOTE,finfo) ; + + for(std::list::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it) + { + std::cerr << " adding peerid " << (*it).peerId << std::endl ; + srcIds.push_back((*it).peerId) ; + } +} + +void SearchDialog::download() +{ + /* should also be able to handle multi-selection */ + QList itemsForDownload = ui.searchResultWidget->selectedItems(); + int numdls = itemsForDownload.size(); + QTreeWidgetItem * item; + bool attemptDownloadLocal = false; + + for (int i = 0; i < numdls; ++i) + { + item = itemsForDownload.at(i); + // call the download + // + if (item->text(SR_HASH_COL).isEmpty()) // we have a folder + downloadDirectory(item, tr("")); + else + { + std::cerr << "SearchDialog::download() Calling File Request"; + std::cerr << std::endl; + std::list srcIds; + + std::string hash = item->text(SR_HASH_COL).toStdString(); + getSourceFriendsForHash(hash,srcIds) ; + + if(!rsFiles -> FileRequest((item->text(SR_NAME_COL)).toStdString(), hash, (item->text(SR_SIZE_COL)).toULongLong(), "", RS_FILE_HINTS_NETWORK_WIDE, srcIds)) + attemptDownloadLocal = true ; + else + { + std::cout << "isuing file request from search dialog: -" << (item->text(SR_NAME_COL)).toStdString() << "-" << hash << "-" << (item->text(SR_SIZE_COL)).toULongLong() << "-ids=" ; + for(std::list::const_iterator it(srcIds.begin());it!=srcIds.end();++it) + std::cout << *it << "-" << std::endl ; + } + } + } + if (attemptDownloadLocal) + QMessageBox::information(0, tr("Download Notice"), tr("Skipping Local Files")); +} + +void SearchDialog::downloadDirectory(const QTreeWidgetItem *item, const QString &base) +{ + if (!item->childCount()) + { + std::list srcIds; + + QString path = QString::fromStdString(rsFiles->getDownloadDirectory()) + + "/" + base + "/"; + QString cleanPath = QDir::cleanPath(path); + + std::string hash = item->text(SR_HASH_COL).toStdString(); + + getSourceFriendsForHash(hash,srcIds) ; + + rsFiles->FileRequest(item->text(SR_NAME_COL).toStdString(), + hash, + item->text(SR_SIZE_COL).toULongLong(), + cleanPath.toStdString(),RS_FILE_HINTS_NETWORK_WIDE, srcIds); + + std::cout << "SearchDialog::downloadDirectory(): "\ + "issuing file request from search dialog: -" + << (item->text(SR_NAME_COL)).toStdString() + << "-" << hash + << "-" << (item->text(SR_SIZE_COL)).toULongLong() + << "-ids=" ; + for(std::list::const_iterator it(srcIds.begin()); + it!=srcIds.end();++it) + std::cout << *it << "-" << std::endl ; + } else { + QDir dwlDir(QString::fromStdString(rsFiles->getDownloadDirectory())); + QString path; + if (base == tr("")) + path = item->text(SR_NAME_COL); + else + path = base + "/" + item->text(SR_NAME_COL); + QString cleanPath = QDir::cleanPath(path); + + // create this folder in download path + if (!dwlDir.mkpath(cleanPath)) { + std::cerr << "SearchDialog::downloadDirectory() - can't create " + << cleanPath.toStdString() << " directory" << std::endl; + return; + } + + // recursive call for every child - file or folder + for (int i = 0, cnt = item->childCount(); i < cnt; i++) { + QTreeWidgetItem *child = item->child(i); + downloadDirectory(child, path); + } + } +} + +void SearchDialog::broadcastonchannel() +{ + + QMessageBox::warning(0, tr("Sorry"), tr("This function is not yet implemented.")); +} + + +void SearchDialog::recommendtofriends() +{ + QMessageBox::warning(0, tr("Sorry"), tr("This function is not yet implemented.")); + +} + + +/** context menu searchTablewidget2 **/ +void SearchDialog::searchtableWidget2CostumPopupMenu( QPoint point ) +{ + // block the popup if no results available + if ((ui.searchSummaryWidget->selectedItems()).size() == 0) return; + + QMenu contextMnu(this); + + contextMnu.addAction(QIcon(IMAGE_REMOVE), tr("Remove"), this, SLOT(searchRemove())); + contextMnu.addAction(QIcon(IMAGE_REMOVE), tr("Remove All"), this, SLOT(searchRemoveAll())); + contextMnu.addSeparator(); + contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copySearchLink())); + + contextMnu.exec(QCursor::pos()); +} + +/** remove selected search result **/ +void SearchDialog::searchRemove() +{ + /* get the current search id from the summary window */ + QTreeWidgetItem *ci = ui.searchSummaryWidget->currentItem(); + if (!ci) + return; + + /* get the searchId text */ + QString searchId = ci->text(SS_SEARCH_ID_COL); + + std::cerr << "SearchDialog::searchRemove(): searchId: " << searchId.toStdString(); + std::cerr << std::endl; + + /* show only matching searchIds in main window */ + int items = ui.searchResultWidget->topLevelItemCount(); + for(int i = 0; i < items;) + { + /* get item */ + QTreeWidgetItem *ti = ui.searchResultWidget->topLevelItem(i); + if (ti->text(SR_SEARCH_ID_COL) == searchId) + { + /* remove */ + delete (ui.searchResultWidget->takeTopLevelItem(i)); + items--; + } + else + { + /* step to the next */ + i++; + } + } + int sii = ui.searchSummaryWidget->indexOfTopLevelItem(ci); + if (sii != -1) + { + delete (ui.searchSummaryWidget->takeTopLevelItem(sii)); + } + + ui.searchResultWidget->update(); + ui.searchSummaryWidget->update(); +} + +/** remove all search results **/ +void SearchDialog::searchRemoveAll() +{ + ui.searchResultWidget->clear(); + ui.searchSummaryWidget->clear(); + ui.FileTypeComboBox->setCurrentIndex(0); + nextSearchId = 1; +} + +/** clear keywords and ComboBox **/ +void SearchDialog::clearKeyword() +{ + ui.lineEdit->clear(); + ui.lineEdit->setFocus(); +} + +void SearchDialog::copySearchLink() +{ + /* get the current search id from the summary window */ + QTreeWidgetItem *ci = ui.searchSummaryWidget->currentItem(); + if (!ci) + return; + + /* get the keywords */ + QString keywords = ci->text(SS_TEXT_COL); + + std::cerr << "SearchDialog::copySearchLink(): keywords: " << keywords.toStdString(); + std::cerr << std::endl; + + RetroShareLink link; + if (link.createSearch(keywords)) { + std::vector urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } +} + +/* ***************************************************************** + Advanced search implementation +*******************************************************************/ +// Event handlers for hide and show events +void SearchDialog::hideEvent(QHideEvent * event) +{ + showAdvSearchDialog(false); + MainPage::hideEvent(event); +} + +void SearchDialog::toggleAdvancedSearchDialog(bool toggled) +{ + // record the users preference for future reference + QString key (UI_PREF_ADVANCED_SEARCH); + Settings->setValue(key, QVariant(toggled)); + + showAdvSearchDialog(toggled); +} + +void SearchDialog::showAdvSearchDialog(bool show) +{ + // instantiate if about to show for the first time + if (advSearchDialog == 0 && show) + { + advSearchDialog = new AdvancedSearchDialog(); + connect(advSearchDialog, SIGNAL(search(Expression*)), + this, SLOT(advancedSearch(Expression*))); + } + if (show) { + advSearchDialog->show(); + advSearchDialog->raise(); + advSearchDialog->setFocus(); + } else if (advSearchDialog != 0){ + advSearchDialog->hide(); + } +} + +// Creates a new entry in the search summary, not to leave it blank whatever happens. +// +void SearchDialog::initSearchResult(const std::string& txt,qulonglong searchId) +{ + QString sid_hexa = QString::number(searchId,16) ; + + QTreeWidgetItem *item2 = new QTreeWidgetItem(); + item2->setText(SS_TEXT_COL, QString::fromStdString(txt)); + item2->setText(SS_COUNT_COL, QString::number(0)); + item2->setText(SS_SEARCH_ID_COL, sid_hexa); + + ui.searchSummaryWidget->addTopLevelItem(item2); + ui.searchSummaryWidget->setCurrentItem(item2); +} + +void SearchDialog::advancedSearch(Expression* expression) +{ + advSearchDialog->hide(); + + /* call to core */ + std::list results; + + // send a turtle search request + LinearizedExpression e ; + expression->linearize(e) ; + + TurtleRequestId req_id = rsTurtle->turtleSearch(e) ; + + // This will act before turtle results come to the interface, thanks to the signals scheduling policy. + // The text "bool exp" should be replaced by an appropriate text describing the actual search. + initSearchResult(std::string("bool exp"),req_id) ; + + rsFiles -> SearchBoolExp(expression, results, DIR_FLAGS_REMOTE | DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE); + + /* abstraction to allow reusee of tree rendering code */ + resultsToTree((advSearchDialog->getSearchAsString()).toStdString(),req_id, results); + +// // debug stuff +// Expression *expression2 = LinearizedExpression::toExpr(e) ; +// results.clear() ; +// rsFiles -> SearchBoolExp(expression2, results, DIR_FLAGS_REMOTE | DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE); +// resultsToTree((advSearchDialog->getSearchAsString()).toStdString(),req_id+1, results); +} + +void SearchDialog::searchKeywords() +{ + searchKeywords(ui.lineEdit->text()); +} + +void SearchDialog::searchKeywords(const QString& keywords) +{ + std::string txt = keywords.toStdString(); + + if(txt.length() < 3) + return ; + + std::cerr << "SearchDialog::searchKeywords() : " << txt << std::endl; + + QStringList qWords = keywords.split(" ", QString::SkipEmptyParts); + std::list words; + QStringListIterator qWordsIter(qWords); + while (qWordsIter.hasNext()) + words.push_back(qWordsIter.next().toStdString()); + + int n = words.size() ; + + if (n < 1) + return; + + NameExpression exprs(ContainsAllStrings,words,true) ; + LinearizedExpression lin_exp ; + exprs.linearize(lin_exp) ; + + TurtleRequestId req_id ; + + if(ui._anonF2Fsearch_CB->isChecked()) + { + if(n==1) + req_id = rsTurtle->turtleSearch(txt) ; + else + req_id = rsTurtle->turtleSearch(lin_exp) ; + } + else + req_id = (((uint32_t)rand()) << 16)^0x1e2fd5e4 + ((uint32_t)rand())^0x1b19acfe ; // generate a random 32 bits request id + + initSearchResult(txt,req_id) ; // this will act before turtle results come to the interface, thanks to the signals scheduling policy. + + if(ui._friendListsearch_SB->isChecked() || ui._ownFiles_CB->isChecked()) + { + /* extract keywords from lineEdit */ + // make a compound expression with an AND + // + + std::list finalResults ; + + if(ui._friendListsearch_SB->isChecked()) + { + std::list initialResults; + + rsFiles->SearchBoolExp(&exprs, initialResults, DIR_FLAGS_REMOTE) ; + + /* which extensions do we use? */ + DirDetails dd; + + for(std::list::iterator resultsIter = initialResults.begin(); resultsIter != initialResults.end(); resultsIter ++) + { + dd = *resultsIter; + finalResults.push_back(dd); + } + } + + if(ui._ownFiles_CB->isChecked()) + { + std::list initialResults; + + rsFiles->SearchBoolExp(&exprs, initialResults, DIR_FLAGS_LOCAL | DIR_FLAGS_NETWORK_WIDE | DIR_FLAGS_BROWSABLE) ; + + /* which extensions do we use? */ + DirDetails dd; + + for(std::list::iterator resultsIter = initialResults.begin(); resultsIter != initialResults.end(); resultsIter ++) + { + dd = *resultsIter; + finalResults.push_back(dd); + } + } + + /* abstraction to allow reusee of tree rendering code */ + resultsToTree(txt,req_id, finalResults); + ui.lineEdit->clear() ; + } +} + +void SearchDialog::updateFiles(qulonglong search_id,FileDetail file) +{ + searchResultsQueue.push_back(std::pair(search_id,file)) ; + + if(!_queueIsAlreadyTakenCareOf) + { + QTimer::singleShot(100,this,SLOT(processResultQueue())) ; + _queueIsAlreadyTakenCareOf = true ; + } +} + +void SearchDialog::processResultQueue() +{ + // This avoids a deadlock when gpg callback asks a passwd. + // Send again in 10 secs. + // + if(RsAutoUpdatePage::eventsLocked()) + { + QTimer::singleShot(10000,this,SLOT(processResultQueue())) ; + return ; + } + + int nb_treated_elements = 0 ; + + while(!searchResultsQueue.empty() && nb_treated_elements++ < 500) + { + qulonglong search_id = searchResultsQueue.back().first ; + FileDetail file = searchResultsQueue.back().second ; + + searchResultsQueue.pop_back() ; + + /* which extensions do we use? */ + std::string txt = ui.lineEdit->text().toStdString(); +#ifdef DEBUG + std::cout << "Updating file detail:" << std::endl ; + std::cout << " size = " << file.size << std::endl ; + std::cout << " name = " << file.name << std::endl ; + std::cout << " s_id = " << search_id << std::endl ; +#endif + + if (ui.FileTypeComboBox->currentIndex() == FILETYPE_IDX_ANY) + insertFile(txt,search_id,file); + else + { + // amend the text description of the search + txt += " (" + ui.FileTypeComboBox->currentText().toStdString() + ")"; + // collect the extensions to use + QString extStr = SearchDialog::FileTypeExtensionMap->value(ui.FileTypeComboBox->currentIndex()); + QStringList extList = extStr.split(" "); + + // get this file's extension + QString qName = QString::fromUtf8(file.name.c_str()); + int extIndex = qName.lastIndexOf("."); + + if (extIndex >= 0) + { + QString qExt = qName.mid(extIndex+1).toUpper(); + + if (qExt != "" ) + for (int i = 0; i < extList.size(); ++i) + if (qExt == extList.at(i).toUpper()) + insertFile(txt,search_id,file); + } + } + } + if(!searchResultsQueue.empty()) + QTimer::singleShot(1000,this,SLOT(processResultQueue())) ; + else + _queueIsAlreadyTakenCareOf = false ; +} + +void SearchDialog::insertDirectory(const std::string &txt, qulonglong searchId, const DirDetails &dir, QTreeWidgetItem *item) +{ + QString sid_hexa = QString::number(searchId,16) ; + + if (dir.type == DIR_TYPE_FILE) + { + QTreeWidgetItem *child; + if (item == NULL) { + child = new QTreeWidgetItem(ui.searchResultWidget); + } else { + child = new QTreeWidgetItem(item); + } + + /* translate search result for a file */ + + child->setText(SR_NAME_COL, QString::fromUtf8(dir.name.c_str())); + child->setText(SR_HASH_COL, QString::fromStdString(dir.hash)); + QString ext = QFileInfo(QString::fromStdString(dir.name)).suffix(); + child->setText(SR_SIZE_COL, QString("%1").arg(dir.count,(int)15,(int)10)); // very important for sorting + child->setText(SR_AGE_COL, QString("%1").arg(dir.age,15,10)); + child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); + + child->setText(SR_ID_COL, QString::number(1)); + child->setTextAlignment( SR_ID_COL, Qt::AlignRight ); + + child->setText(SR_SEARCH_ID_COL, sid_hexa); + setIconAndType(child, ext); + + if (item == NULL) { + ui.searchResultWidget->addTopLevelItem(child); + } else { + item->addChild(child); + } + } + else + { /* it is a directory */ + QTreeWidgetItem *child; + if (item == NULL) { + child = new QTreeWidgetItem(ui.searchResultWidget); + } else { + child = new QTreeWidgetItem(item); + } + + child->setIcon(SR_NAME_COL, QIcon(IMAGE_DIRECTORY)); + child->setText(SR_NAME_COL, QString::fromUtf8(dir.name.c_str())); + child->setText(SR_HASH_COL, QString::fromStdString(dir.hash)); + //child->setText(SR_SIZE_COL, misc::toQString(dir.count)); + child->setText(SR_SIZE_COL, QString("%1").arg(dir.count,15,10)); // very important for sorting + child->setText(SR_AGE_COL, QString("%1").arg(dir.age,15,10)); + child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); + child->setText(SR_ID_COL, QString::number(1)); + child->setTextAlignment( SR_ID_COL, Qt::AlignRight ); + child->setText(SR_SEARCH_ID_COL, sid_hexa); + child->setText(SR_TYPE_COL, tr("Folder")); + + + if (item == NULL) { + ui.searchResultWidget->addTopLevelItem(child); + + /* add to the summary as well */ + + int items = ui.searchSummaryWidget->topLevelItemCount(); + bool found = false ; + + for(int i = 0; i < items; i++) + { + if(ui.searchSummaryWidget->topLevelItem(i)->text(SS_SEARCH_ID_COL) == sid_hexa) + { + // increment result since every item is new + int s = ui.searchSummaryWidget->topLevelItem(i)->text(SS_COUNT_COL).toInt() ; + ui.searchSummaryWidget->topLevelItem(i)->setText(SS_COUNT_COL,QString::number(s+1)); + found = true ; + } + } + if(!found) + { + QTreeWidgetItem *item2 = new QTreeWidgetItem(); + item2->setText(SS_TEXT_COL, QString::fromStdString(txt)); + item2->setText(SS_COUNT_COL, QString::number(1)); + item2->setTextAlignment( SS_COUNT_COL, Qt::AlignRight ); + item2->setText(SS_SEARCH_ID_COL, sid_hexa); + + ui.searchSummaryWidget->addTopLevelItem(item2); + ui.searchSummaryWidget->setCurrentItem(item2); + } + + /* select this search result */ + selectSearchResults(); + } else { + item->addChild(child); + } + + /* go through all children directories/files for a recursive call */ + for (std::list::const_iterator it(dir.children.begin()); it != dir.children.end(); it ++) { + DirDetails details; + rsFiles->RequestDirDetails(it->ref, details, 0); + insertDirectory(txt, searchId, details, child); + } + } + + if (ui.filterPatternLineEdit->text().isEmpty() == false) { + FilterItems(); + } +} + +void SearchDialog::insertDirectory(const std::string &txt, qulonglong searchId, const DirDetails &dir) +{ + return ; // Remove this statement to allow adding directories to the search results. + + QString sid_hexa = QString::number(searchId,16) ; + QTreeWidgetItem *child = new QTreeWidgetItem(ui.searchResultWidget); + + child->setIcon(SR_NAME_COL, QIcon(IMAGE_DIRECTORY)); + child->setText(SR_NAME_COL, QString::fromUtf8(dir.name.c_str())); + child->setText(SR_HASH_COL, QString::fromStdString(dir.hash)); + child->setText(SR_SIZE_COL, QString("%1").arg(dir.count,(int)15,(int)10)); // very important for sorting + child->setText(SR_AGE_COL, QString("%1").arg(dir.min_age,15,10)); + child->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); + child->setText(SR_ID_COL, QString::number(1)); + child->setTextAlignment( SR_ID_COL, Qt::AlignRight ); + child->setText(SR_SEARCH_ID_COL, sid_hexa); + child->setText(SR_TYPE_COL, tr("Folder")); + + ui.searchResultWidget->addTopLevelItem(child); + + /* add to the summary as well */ + + int items = ui.searchSummaryWidget->topLevelItemCount(); + bool found = false ; + + for(int i = 0; i < items; i++) + { + if(ui.searchSummaryWidget->topLevelItem(i)->text(SS_SEARCH_ID_COL) == sid_hexa) + { + // increment result since every item is new + int s = ui.searchSummaryWidget->topLevelItem(i)->text(SS_COUNT_COL).toInt() ; + ui.searchSummaryWidget->topLevelItem(i)->setText(SS_COUNT_COL,QString::number(s+1)); + found = true ; + } + } + if(!found) + { + QTreeWidgetItem *item2 = new QTreeWidgetItem(); + item2->setText(SS_TEXT_COL, QString::fromStdString(txt)); + item2->setText(SS_COUNT_COL, QString::number(1)); + item2->setTextAlignment( SS_COUNT_COL, Qt::AlignRight ); + item2->setText(SS_SEARCH_ID_COL, sid_hexa); + + ui.searchSummaryWidget->addTopLevelItem(item2); + ui.searchSummaryWidget->setCurrentItem(item2); + } + + selectSearchResults(); + + if (ui.filterPatternLineEdit->text().isEmpty() == false) { + FilterItems(); + } +// TODO: check for duplicate directories +} + +void SearchDialog::insertFile(const std::string& txt,qulonglong searchId, const FileDetail& file, int searchType) +{ + // algo: + // + // 1 - look in result window whether the file already exist. + // 1.1 - If yes, just increment the source number. + // 2.2 - Otherwize, add an entry. + // 2 - look in the summary whether there exist the same request id. + // 1.1 - If yes, just increment the result number. + // 2.2 - Otherwize, add an entry. + // + // + static std::map nb_results ; + + if(nb_results.find(searchId) == nb_results.end()) + nb_results[searchId] = 0 ; + + if(nb_results[searchId] >= ui._max_results_SB->value()) + return ; + + // 1 - look in result window whether the file already exists. + // + bool found = false ; + int sources; + int friendSource = 0; + int anonymousSource = 0; + QString modifiedResult; + + QString sid_hexa = QString::number(searchId,16) ; + + QList itms = ui.searchResultWidget->findItems(QString::fromStdString(file.hash),Qt::MatchExactly,SR_HASH_COL) ; + + for(QList::const_iterator it(itms.begin());it!=itms.end();++it) + if((*it)->text(SR_SEARCH_ID_COL) == sid_hexa) + { + QString resultCount = (*it)->text(SR_ID_COL); + QStringList modifiedResultCount = resultCount.split("/", QString::SkipEmptyParts); + if(searchType == FRIEND_SEARCH) + { + friendSource = modifiedResultCount.at(0).toInt() + 1; + anonymousSource = modifiedResultCount.at(1).toInt(); + } + else + { + friendSource = modifiedResultCount.at(0).toInt(); + anonymousSource = modifiedResultCount.at(1).toInt() + 1; + } + anonymousSource = anonymousSource + friendSource; + modifiedResult = QString::number(friendSource) + "/" + QString::number(anonymousSource); + (*it)->setText(SR_ID_COL,modifiedResult); + QTreeWidgetItem *item = (*it); + found = true ; + int sources = friendSource + anonymousSource ; + if ( sources < 1) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 19))); + } + } + else if ( sources < 2) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 38))); + } + } + else if ( sources < 3) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 57))); + } + } + else if ( sources < 4) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 76))); + } + } + else if ( sources < 5) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 96))); + } + } + else if ( sources < 6) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 114))); + } + } + else if ( sources < 7) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 133))); + } + } + else if ( sources < 8) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 152))); + } + } + else if ( sources < 9) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 171))); + } + } + else if ( sources < 10) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 190))); + } + } + else if ( sources < 11) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 209))); + } + } + else if ( sources < 12) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 228))); + } + } + else + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 228))); + } + } + break ; + } + + if(!found) + { + ++nb_results[searchId] ; + + /* translate search results */ + + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(SR_NAME_COL, QString::fromUtf8(file.name.c_str())); + item->setText(SR_HASH_COL, QString::fromStdString(file.hash)); + + QString ext = QFileInfo(QString::fromStdString(file.name)).suffix(); + setIconAndType(item, ext); + + /* + * to facilitate downlaods we need to save the file size too + */ + + item->setText(SR_SIZE_COL, QString("%1").arg(file.size,15,10)); // very important for sorting + item->setText(SR_AGE_COL, QString("%1").arg(file.age,15,10)); + item->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); + if(searchType == FRIEND_SEARCH) + { + friendSource = 1; + anonymousSource = 0; + } + else + { + friendSource = 0; + anonymousSource = 1; + } + + anonymousSource = anonymousSource + friendSource; + modifiedResult =QString::number(friendSource) + "/" + QString::number(anonymousSource); + item->setText(SR_ID_COL,modifiedResult); + item->setTextAlignment( SR_ID_COL, Qt::AlignRight ); + item->setText(SR_SEARCH_ID_COL, sid_hexa); + + + sources = item->text(SR_ID_COL).toInt(); + if ( sources == 1) + { + for(int i = 0; i < 7; i++) + { + item->setForeground(i,QBrush( QColor(0, 0, 0))); + } + } + + ui.searchResultWidget->addTopLevelItem(item); + } + + /* add to the summary as well */ + + int items2 = ui.searchSummaryWidget->topLevelItemCount(); + bool found2 = false ; + + for(int i = 0; i < items2; i++) + if(ui.searchSummaryWidget->topLevelItem(i)->text(SS_SEARCH_ID_COL) == sid_hexa) + { + if(!found) // only increment result when it's a new item. + { + int s = ui.searchSummaryWidget->topLevelItem(i)->text(SS_COUNT_COL).toInt() ; + ui.searchSummaryWidget->topLevelItem(i)->setText(SS_COUNT_COL,QString::number(s+1)); + } + found2 = true ; + break ; + } + + if(!found2) + { + QTreeWidgetItem *item2 = new QTreeWidgetItem(); + item2->setText(SS_TEXT_COL, QString::fromStdString(txt)); + item2->setText(SS_COUNT_COL, QString::number(1)); + item2->setTextAlignment( SS_COUNT_COL, Qt::AlignRight ); + item2->setText(SS_SEARCH_ID_COL, sid_hexa); + + ui.searchSummaryWidget->addTopLevelItem(item2); + ui.searchSummaryWidget->setCurrentItem(item2); + } + + /* select this search result */ + selectSearchResults(); + + if (ui.filterPatternLineEdit->text().isEmpty() == false) { + FilterItems(); + } +} + +void SearchDialog::resultsToTree(std::string txt,qulonglong searchId, const std::list& results) +{ + ui.searchResultWidget->setSortingEnabled(false); + + /* translate search results */ + std::ostringstream out; + out << searchId; + + std::list::const_iterator it; + for(it = results.begin(); it != results.end(); it++) + if (it->type == DIR_TYPE_FILE) { + FileDetail fd; + fd.id = it->id; + fd.name = it->name; + fd.hash = it->hash; + fd.path = it->path; + fd.size = it->count; + fd.age = it->age; + fd.rank = 0; + + insertFile(txt,searchId,fd, FRIEND_SEARCH); + } else if (it->type == DIR_TYPE_DIR) { +// insertDirectory(txt, searchId, *it, NULL); + insertDirectory(txt, searchId, *it); + } + + ui.searchResultWidget->setSortingEnabled(true); +} + +void SearchDialog::selectSearchResults(int index) +{ + int cindex = ui.FileTypeComboBox->currentIndex(); + index = (index == -1) ? (cindex == -1 ? 0 : cindex):index; + QString alltypes = FileTypeExtensionMap->value(index); + QStringList types = alltypes.split(" "); + + + /* highlight this search in summary window */ + QTreeWidgetItem *ci = ui.searchSummaryWidget->currentItem(); + if (!ci) + return; + + /* get the searchId text */ + QString searchId = ci->text(SS_SEARCH_ID_COL); +#ifdef DEBUG + std::cerr << "SearchDialog::selectSearchResults(): searchId: " << searchId.toStdString(); + std::cerr << std::endl; +#endif + + /* show only matching searchIds in main window */ + int items = ui.searchResultWidget->topLevelItemCount(); + for(int i = 0; i < items; i++) + { + /* get item */ + QTreeWidgetItem *ti = ui.searchResultWidget->topLevelItem(i); + if (ti->text(SR_SEARCH_ID_COL) == searchId) + { + if (index == FILETYPE_IDX_ANY) + ti->setHidden(false); + else if (index == FILETYPE_IDX_DIRECTORY && ti->text(SR_HASH_COL).isEmpty()) + ti->setHidden(false); + else if (types.contains(QFileInfo(ti->text(SR_NAME_COL)).suffix(), Qt::CaseInsensitive)) + ti->setHidden(false); + else + ti->setHidden(true); + } + else + { + ti->setHidden(true); + } + } + ui.searchResultWidget->update(); + ui.filterPatternLineEdit->clear(); +} + +void SearchDialog::setIconAndType(QTreeWidgetItem *item, QString ext) +{ + ext = ext.toLower(); + if (ext == "jpg" || ext == "jpeg" || ext == "png" || ext == "gif" || ext == "bmp" || ext == "ico" + || ext == "svg" || ext == "tif" || ext == "tiff") + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypePicture.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Picture")); + } + else if (ext == "avi" || ext == "mpg" || ext == "mpeg" || ext == "wmv" || ext == "mkv" || ext == "mp4" + || ext == "flv" || ext == "mov" || ext == "vob" || ext == "qt" || ext == "rm" || ext == "3gp" + || ext == "dvx" || ext == "divx") + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeVideo.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Video")); + } + else if (ext == "flac" || ext == "ogg" || ext == "mp3" || ext == "m4a" || ext == "mp1" || ext == "mp2" || ext == "wav" || ext == "wma") + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeAudio.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Audio")); + } + else if (ext == "tar" || ext == "bz2" || ext == "zip" || ext == "tgz" || ext == "gz" || ext == "rar" + || ext == "rpm" || ext == "7z" || ext == "ace" || ext == "jar" || ext == "cab" || ext == "deb") + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeArchive.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Archive")); + } + else if (ext == "app" || ext == "bat" || ext == "cgi" || ext == "com" || ext == "bin" || ext == "exe" || ext == "js" + || ext == "msi" ||ext == "pif" || ext == "py" || ext == "pl" || ext == "sh" || ext == "vb" || ext == "ws") + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeProgram.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Program")); + } + else if (ext == "iso" || ext == "nrg" || ext == "mdf" || ext == "img" || ext == "dmg" || ext == "bin" || ext == "uif" ) + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeCDImage.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("CD-Image")); + } + else if (ext == "txt" || ext == "cpp" || ext == "c" || ext == "h") + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeDocument.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Document")); + } + else if (ext == "pdf" ) + { + item->setIcon(SR_NAME_COL, QIcon(":/images/mimetypes/pdf.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Document")); + } + else if (ext == "doc" || ext == "rtf" || ext == "sxw" || ext == "xls" || ext == "pps" || ext == "xml" || ext == "nfo" + || ext == "reg" || ext == "sxc" || ext == "odt" || ext == "ods" || ext == "dot" || ext == "ppt" || ext == "css" || ext == "crt" ) + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeDocument.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Document")); + } + else if (ext == "html" || ext == "htm" || ext == "php") + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeDocument.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Document")); + } + else if (ext == "sub" || ext == "srt") + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeAny.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Subtitles")); + } + else if (ext == "nds") + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeAny.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Nintendo DS Rom")); + } + else + { + item->setIcon(SR_NAME_COL, QIcon(":/images/FileTypeAny.png")); + } +} + +void SearchDialog::copyResultLink() +{ + /* should also be able to handle multi-selection */ + QList itemsForCopy = ui.searchResultWidget->selectedItems(); + int numdls = itemsForCopy.size(); + QTreeWidgetItem * item; + + std::vector urls ; + + for (int i = 0; i < numdls; ++i) + { + item = itemsForCopy.at(i); + // call copy + + if (!item->childCount()) + { + std::cerr << "SearchDialog::copyResultLink() Calling set retroshare link"; + std::cerr << std::endl; + + QString fhash = item->text(SR_HASH_COL); + qulonglong fsize = item->text(SR_SIZE_COL).toULongLong(); + QString fname = item->text(SR_NAME_COL); + + RetroShareLink link; + if (link.createFile(fname, fsize, fhash)) { + std::cerr << "new link added to clipboard: " << link.toString().toStdString() << std::endl ; + urls.push_back(link) ; + } + } + } + RSLinkClipboard::copyLinks(urls) ; +} + +void SearchDialog::sendLinkTo( ) +{ + copyResultLink(); + + /* create a message */ + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + nMsgDialog->insertTitleText(tr("New RetroShare Link(s)")); + + nMsgDialog->insertMsgText(RSLinkClipboard::toHtml()) ; + nMsgDialog->show(); + + /* window will destroy itself! */ +} + +void SearchDialog::togglereset() +{ + QString text = ui.lineEdit->text(); + + if (text.isEmpty()) + { + ui.resetButton->hide(); + } + else + { + ui.resetButton->show(); + } + +} + +// not in use for the moment +void SearchDialog::onComboIndexChanged(int index) +{ + if (!FileTypeExtensionMap->contains(index) && index != FILETYPE_IDX_DIRECTORY) + return; + QString alltypes = FileTypeExtensionMap->value(index); + QStringList types = alltypes.split(" "); + int items = ui.searchResultWidget->topLevelItemCount(); + for (int i = 0; i < items; i++) { + QTreeWidgetItem *ti = ui.searchResultWidget->topLevelItem(i); + QString name = ti->text(SR_NAME_COL); + + if (index == FILETYPE_IDX_ANY) { + if (ti->isHidden()) { + QTreeWidgetItem *ci = ui.searchSummaryWidget->currentItem(); + if (!ci) { + ti->setHidden(false); + continue; + } + if (ti->text(SR_SEARCH_ID_COL) == ci->text(SS_SEARCH_ID_COL)) { + ti->setHidden(false); + } + } + } else if (index == FILETYPE_IDX_DIRECTORY) { + if (ti->text(SR_HASH_COL).isEmpty()) { + if (ti->isHidden()) { + QTreeWidgetItem *ci = ui.searchSummaryWidget->currentItem(); + if (!ci) { + ti->setHidden(false); + continue; + } + if (ti->text(SR_SEARCH_ID_COL) == ci->text(SS_SEARCH_ID_COL)) { + ti->setHidden(false); + } + } + } else { + ti->setHidden(true); + } + } else { + if (name.lastIndexOf(".") >= 0) { + QString ext = name.mid(name.lastIndexOf(".") + 1); + if (!ext.isEmpty() && types.contains(ext, Qt::CaseInsensitive)) { + if (ti->isHidden()) { + QTreeWidgetItem *ci = ui.searchSummaryWidget->currentItem(); + if (!ci) { + ti->setHidden(false); + continue; + } + if (ti->text(SR_SEARCH_ID_COL) == ci->text(SS_SEARCH_ID_COL)) { + ti->setHidden(false); + } + } + } else { + ti->setHidden(true); + } + } else { + ti->setHidden(true); + } + } + } +} + +/* clear Filter */ +void SearchDialog::clearFilter() +{ + ui.filterPatternLineEdit->clear(); + ui.filterPatternLineEdit->setFocus(); +} + +void SearchDialog::filterRegExpChanged() +{ + + QString text = ui.filterPatternLineEdit->text(); + + if (text.isEmpty()) { + ui.clearButton->hide(); + } else { + ui.clearButton->show(); + } + + FilterItems(); +} + +void SearchDialog::filterColumnChanged() +{ + + FilterItems(); + +} + +void SearchDialog::FilterItems() +{ + QString sPattern = ui.filterPatternLineEdit->text(); + int nFilterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex()); + + int nCount = ui.searchResultWidget->topLevelItemCount (); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + FilterItem(ui.searchResultWidget->topLevelItem(nIndex), sPattern, nFilterColumn); + } + +} + +bool SearchDialog::FilterItem(QTreeWidgetItem *pItem, QString &sPattern, int nFilterColumn) +{ + bool bVisible = true; + + if (sPattern.isEmpty() == false) { + if (pItem->text(nFilterColumn).contains(sPattern, Qt::CaseInsensitive) == false) { + bVisible = false; + } + } + + int nVisibleChildCount = 0; + int nCount = pItem->childCount(); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + if (FilterItem(pItem->child(nIndex), sPattern, nFilterColumn)) { + nVisibleChildCount++; + } + } + + if (bVisible || nVisibleChildCount) { + pItem->setHidden(false); + } else { + pItem->setHidden(true); + } + + return (bVisible || nVisibleChildCount); +} diff --git a/retroshare-gui/src/gui/SearchDialog.h b/retroshare-gui/src/gui/SearchDialog.h new file mode 100644 index 000000000..72ce7f2ca --- /dev/null +++ b/retroshare-gui/src/gui/SearchDialog.h @@ -0,0 +1,146 @@ +/**************************************************************** +* RShare is distributed under the following license: +* +* Copyright (C) 2006, crypton +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ + +#ifndef _SEARCHDIALOG_H +#define _SEARCHDIALOG_H + +#include +#include "ui_SearchDialog.h" +#include "mainpage.h" + +class AdvancedSearchDialog; +class Expression; + +#define FRIEND_SEARCH 1 +#define ANONYMOUS_SEARCH 2 +class SearchDialog : public MainPage +{ + Q_OBJECT + + public: +/** Default Constructor */ + SearchDialog(QWidget *parent = 0); +/** Default Destructor */ + ~SearchDialog(); + + void searchKeywords(const QString& keywords); + +public slots: + void updateFiles(qulonglong request_id,FileDetail file) ; + +private slots: + +/** Create the context popup menu and it's submenus */ + void searchtableWidgetCostumPopupMenu( QPoint point ); + + void processResultQueue(); + void searchtableWidget2CostumPopupMenu( QPoint point ); + + void download(); + + void broadcastonchannel(); + + void recommendtofriends(); + void checkText(const QString&) ; + + void copyResultLink(); + void copySearchLink(); + + void searchRemove(); + void searchRemoveAll(); + void searchKeywords(); + +/** management of the adv search dialog object when switching search modes */ + void toggleAdvancedSearchDialog(bool); + void hideEvent(QHideEvent * event); + +/** raises (and if necessary instantiates) the advanced search dialog */ + void showAdvSearchDialog(bool=true); + +/** perform the advanced search */ + void advancedSearch(Expression*); + + void selectSearchResults(int index = -1); + + void clearKeyword(); + + void sendLinkTo(); + + void togglereset(); + + void onComboIndexChanged(int index); + + void filterColumnChanged(); + void filterRegExpChanged(); + void clearFilter(); + + + +private: +/** render the results to the tree widget display */ + void initSearchResult(const std::string& txt,qulonglong searchId) ; + void resultsToTree(std::string,qulonglong searchId, const std::list&); + void insertFile(const std::string& txt,qulonglong searchId, const FileDetail& file, int searchType = ANONYMOUS_SEARCH) ; + void insertDirectory(const std::string &txt, qulonglong searchId, const DirDetails &dir, QTreeWidgetItem *item); + void insertDirectory(const std::string &txt, qulonglong searchId, const DirDetails &dir); + void setIconAndType(QTreeWidgetItem *item, QString ext); + void downloadDirectory(const QTreeWidgetItem *item, const QString &base); + void getSourceFriendsForHash(const std::string& hash,std::list& srcIds); + + + +/** the advanced search dialog instance */ + AdvancedSearchDialog * advSearchDialog; + +/** Contains the mapping of filetype combobox to filetype extensions */ + static const int FILETYPE_IDX_ANY; + static const int FILETYPE_IDX_ARCHIVE; + static const int FILETYPE_IDX_AUDIO; + static const int FILETYPE_IDX_CDIMAGE; + static const int FILETYPE_IDX_DOCUMENT; + static const int FILETYPE_IDX_PICTURE; + static const int FILETYPE_IDX_PROGRAM; + static const int FILETYPE_IDX_VIDEO; + static const int FILETYPE_IDX_DIRECTORY; + + + static QMap * FileTypeExtensionMap; + static bool initialised; + void initialiseFileTypeMappings(); + + void processSettings(bool bLoad); + + void FilterItems(); + bool FilterItem(QTreeWidgetItem *pItem, QString &sPattern, int nFilterColumn); + + bool m_bProcessSettings; + + int nextSearchId; + +/** Qt Designer generated object */ + Ui::SearchDialog ui; + + bool _queueIsAlreadyTakenCareOf ; + std::vector > searchResultsQueue ; +}; + +#endif + diff --git a/retroshare-gui/src/gui/SearchDialog.ui b/retroshare-gui/src/gui/SearchDialog.ui new file mode 100644 index 000000000..05c9bd46e --- /dev/null +++ b/retroshare-gui/src/gui/SearchDialog.ui @@ -0,0 +1,1441 @@ + + + SearchDialog + + + + 0 + 0 + 574 + 329 + + + + + 1 + 1 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + + 6 + + + 0 + + + + + + 16777215 + 32 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + 3 + + + 0 + + + 3 + + + 0 + + + 6 + + + 0 + + + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +*{ +color: black; +} + +QComboBox QAbstractItemView { +background-color:white; +} + +QComboBox::down-arrow { +image: url(:/images/combobox_arrow.png); +} + +QComboBox:drop-down +{ +subcontrol-origin: padding; +subcontrol-position: top right; +border-left-style: none; +border-top-right-radius: 1px; +border-bottom-right-radius: 1px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + + + Any + + + + :/images/FileTypeAny.png:/images/FileTypeAny.png + + + + + Archive + + + + :/images/FileTypeArchive.png:/images/FileTypeArchive.png + + + + + Audio + + + + :/images/FileTypeAudio.png:/images/FileTypeAudio.png + + + + + CD-Image + + + + :/images/FileTypeCDImage.png:/images/FileTypeCDImage.png + + + + + Document + + + + :/images/FileTypeDocument.png:/images/FileTypeDocument.png + + + + + Picture + + + + :/images/FileTypePicture.png:/images/FileTypePicture.png + + + + + Program + + + + :/images/FileTypeProgram.png:/images/FileTypeProgram.png + + + + + Video + + + + :/images/FileTypeVideo.png:/images/FileTypeVideo.png + + + + + Directory + + + + :/images/folder16.png:/images/folder16.png + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 13 + 20 + + + + + + + + 0 + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + QFrame#searchlineframe{border: 2px solid #079E00; +background: white;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 1 + + + 0 + + + + + + 3 + 0 + + + + + 0 + 16 + + + + + 1677777 + 16777215 + + + + Enter a Keyword here + + + QLineEdit#lineEdit{background: transparent; +border: none;} + + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + Qt::NoFocus + + + Reset + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + 0 + 0 + + + + + 16 + 16 + + + + + 16 + 16 + + + + QPushButton#pushButton{background: transparent; +border: none;} + + + + + + + :/images/find-16.png:/images/find-16.png + + + + 16 + 16 + + + + + + + + + + + Qt::NoFocus + + + Start Search + + + QPushButton { +border-image: url(:/images/btn1.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +*{ +color: black; +} + +QPushButton:hover { +border-image: url(:/images/btn2.png) 4; +} + +QPushButton:pressed{ +border-image: url(:/images/btn3.png) 4; +} + + + Search + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 50 + 20 + + + + + + + + Advanced Search + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +*{ +color: black; +} + +QComboBox QAbstractItemView { +background-color:white; +} + +QComboBox::down-arrow { +image: url(:/images/combobox_arrow.png); +} + +QComboBox:drop-down +{ +subcontrol-origin: padding; +subcontrol-position: top right; +border-left-style: none; +border-top-right-radius: 1px; +border-bottom-right-radius: 1px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + + Advanced + + + + + + + + + + Qt::Horizontal + + + + + 0 + 1 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 9 + + + + true + + + Qt::CustomContextMenu + + + true + + + + KeyWords + + + + + Results + + + + + Search Id + + + + + + + + + 6 + + + 6 + + + + + 2 + + + + + + + + :/images/find-16.png + + + + + + + + 0 + 0 + + + + Filter Search Result + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + MS Shell Dlg 2 + + + + Qt::NoFocus + + + Clear Filter + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + + false + + + + 0 + 0 + + + + + 0 + 0 + + + + + MS Shell Dlg 2 + + + + 0 + + + + File Name + + + + + File Size + + + + + + + + + + + 1 + 0 + + + + + 9 + + + + Qt::CustomContextMenu + + + true + + + QAbstractItemView::DragOnly + + + true + + + + Filename + + + + + Size + + + + + Sources + + + + + Type + + + + + Age + + + + + Hash + + + + + + + + + + + + Close all Search Resullts + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +*{ +color: black; +} + +QComboBox QAbstractItemView { +background-color:white; +} + +QComboBox::down-arrow { +image: url(:/images/combobox_arrow.png); +} + +QComboBox:drop-down +{ +subcontrol-origin: padding; +subcontrol-position: top right; +border-left-style: none; +border-top-right-radius: 1px; +border-bottom-right-radius: 1px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + + Close All Search Results + + + + + + + Qt::Horizontal + + + + 29 + 17 + + + + + + + + + 120 + 0 + + + + + 16777215 + 26 + + + + Download Selected + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +*{ +color: black; +} + +QComboBox QAbstractItemView { +background-color:white; +} + +QComboBox::down-arrow { +image: url(:/images/combobox_arrow.png); +} + +QComboBox:drop-down +{ +subcontrol-origin: padding; +subcontrol-position: top right; +border-left-style: none; +border-top-right-radius: 1px; +border-bottom-right-radius: 1px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + + Download + + + + :/images/download16.png:/images/download16.png + + + + + + + + 16777215 + 38 + + + + QFrame#frame_3{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); +border-radius: 10px; +border: 2px solid #CCCCCC;} + + + + 6 + + + 1 + + + 3 + + + + + + 0 + 0 + + + + Include files from your own file list in the search result + + + Include own files + + + + + + + Search inside "browsable" files of your friends + + + Search in friends lists + + + true + + + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + F2F search + + + true + + + + + + + Limit number of results to : + + + + + + + + + + 100 + + + 5000 + + + 100 + + + 1000 + + + + + + + Qt::Horizontal + + + + 40 + 5 + + + + + + + + + + + + SearchTreeWidget + QTreeWidget +
    gui/SearchTreeWidget.h
    +
    +
    + + + + +
    diff --git a/retroshare-gui/src/gui/SearchTreeWidget.cpp b/retroshare-gui/src/gui/SearchTreeWidget.cpp new file mode 100644 index 000000000..22ccd1af3 --- /dev/null +++ b/retroshare-gui/src/gui/SearchTreeWidget.cpp @@ -0,0 +1,79 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2008 Robert Fernie +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ + +#include + +#include "SearchTreeWidget.h" + +#include + +SearchTreeWidget::SearchTreeWidget(QWidget *parent) + :QTreeWidget(parent) +{ + return; +} + +QMimeData * SearchTreeWidget::mimeData ( const QList items ) const +{ + /* extract from each QTreeWidgetItem... all the member text */ + QList::const_iterator it; + QString text; + for(it = items.begin(); it != items.end(); it++) + { + QString line; + for(int i = 0; i < (*it)->columnCount(); i++) + { + line += (*it)->text(i); + line += "/"; + } + line += "\n"; + text += line; + } + + std::cerr << "Created MimeData:"; + std::cerr << std::endl; + + std::string str = text.toStdString(); + std::cerr << str; + std::cerr << std::endl; + + QMimeData *data = new QMimeData(); + data->setData("application/x-rsfilelist", QByteArray(str.c_str())); + + return data; +} + + + +QStringList SearchTreeWidget::mimeTypes () const +{ + QStringList list; + list.push_back("application/x-rsfilelist"); + + return list; +} + + +Qt::DropActions SearchTreeWidget::supportedDropActions () const +{ + return Qt::CopyAction; +} + diff --git a/retroshare-gui/src/gui/SearchTreeWidget.h b/retroshare-gui/src/gui/SearchTreeWidget.h new file mode 100644 index 000000000..64637f473 --- /dev/null +++ b/retroshare-gui/src/gui/SearchTreeWidget.h @@ -0,0 +1,43 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2008 Robert Fernie +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ + +#ifndef _SEARCH_TREE_WIDGET_H +#define _SEARCH_TREE_WIDGET_H + +#include + +class SearchTreeWidget : public QTreeWidget +{ + Q_OBJECT + + public: + SearchTreeWidget(QWidget *parent = 0); + + protected: +virtual QMimeData * mimeData ( const QList items ) const; +virtual QStringList mimeTypes () const; +virtual Qt::DropActions supportedDropActions () const; + +}; + + +#endif + diff --git a/retroshare-gui/src/gui/ShareDialog.cpp b/retroshare-gui/src/gui/ShareDialog.cpp new file mode 100644 index 000000000..2e0c3323d --- /dev/null +++ b/retroshare-gui/src/gui/ShareDialog.cpp @@ -0,0 +1,136 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006- 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include "ShareDialog.h" + +#include + +#include +#include +#include +#include + +/** Default constructor */ +ShareDialog::ShareDialog(std::string filename, QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + connect(ui.browseButton, SIGNAL(clicked( bool ) ), this , SLOT( browseDirectory() ) ); + connect(ui.okButton, SIGNAL(clicked( bool ) ), this , SLOT( addDirectory() ) ); + connect(ui.closeButton, SIGNAL(clicked()), this, SLOT(close())); + + ui.okButton->setEnabled(false); + + if (filename.empty() == false) { + /* edit exisiting share */ + std::list dirs; + rsFiles->getSharedDirectories(dirs); + + std::list::const_iterator it; + for (it = dirs.begin(); it != dirs.end(); it++) { + if (it->filename == filename) { + /* fill dialog */ + ui.okButton->setEnabled(true); + + ui.localpath_lineEdit->setText(QString::fromUtf8(it->filename.c_str())); + ui.localpath_lineEdit->setDisabled(true); + ui.browseButton->setDisabled(true); + ui.virtualpath_lineEdit->setText(QString::fromUtf8(it->virtualname.c_str())); + + ui.browsableCheckBox->setChecked(it->shareflags & RS_FILE_HINTS_BROWSABLE); + ui.networkwideCheckBox->setChecked(it->shareflags & RS_FILE_HINTS_NETWORK_WIDE); + break; + } + } + } +} + +void ShareDialog::browseDirectory() +{ + /* select a dir*/ + QString qdir = QFileDialog::getExistingDirectory(this, tr("Select A Folder To Share"), "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + /* add it to the server */ + if (qdir.isEmpty()) { + ui.okButton->setEnabled(false); + return; + } + ui.okButton->setEnabled(true); + ui.localpath_lineEdit->setText(qdir); +} + +void ShareDialog::addDirectory() +{ + SharedDirInfo sdi ; + sdi.filename = ui.localpath_lineEdit->text().toUtf8().constData(); + sdi.virtualname = ui.virtualpath_lineEdit->text().toUtf8().constData(); + + sdi.shareflags = 0; + + if (ui.browsableCheckBox->isChecked()) { + sdi.shareflags |= RS_FILE_HINTS_BROWSABLE ; + } + if (ui.networkwideCheckBox->isChecked()) { + sdi.shareflags |= RS_FILE_HINTS_NETWORK_WIDE; + } + + if (ui.localpath_lineEdit->isEnabled()) { + /* add new share */ + rsFiles->addSharedDirectory(sdi); + } else { + /* edit exisiting share */ + bool found = false; + + std::list dirs; + rsFiles->getSharedDirectories(dirs); + + std::list::iterator it; + for (it = dirs.begin(); it != dirs.end(); it++) { + if (it->filename == sdi.filename) { + found = true; + + if (it->virtualname != sdi.virtualname) { + /* virtual name changed, remove shared directory and add it again */ + rsFiles->removeSharedDirectory(it->filename); + rsFiles->addSharedDirectory(sdi); + break; + } + if (it->shareflags ^ sdi.shareflags) { + /* modifies the flags */ + it->shareflags = sdi.shareflags; + rsFiles->updateShareFlags(*it); + break; + } + + /* nothing changed */ + break; + } + } + + if (found == false) { + /* not modified, add share directory instead */ + rsFiles->addSharedDirectory(sdi); + } + } + + close(); +} diff --git a/retroshare-gui/src/gui/ShareDialog.h b/retroshare-gui/src/gui/ShareDialog.h new file mode 100644 index 000000000..349684728 --- /dev/null +++ b/retroshare-gui/src/gui/ShareDialog.h @@ -0,0 +1,48 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _SHAREDIALOG_H +#define _SHAREDIALOG_H + +#include + +#include "ui_ShareDialog.h" + +class ShareDialog : public QDialog +{ + Q_OBJECT + +public: + /** Default constructor */ + ShareDialog( std::string filename, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + +private slots: + void browseDirectory(); + void addDirectory(); + +private: + /** Qt Designer generated object */ + Ui::ShareDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/ShareDialog.ui b/retroshare-gui/src/gui/ShareDialog.ui new file mode 100644 index 000000000..54b1cc619 --- /dev/null +++ b/retroshare-gui/src/gui/ShareDialog.ui @@ -0,0 +1,282 @@ + + + ShareDialog + + + Qt::NonModal + + + + 0 + 0 + 536 + 313 + + + + RetroShare Share Folder + + + + :/images/rstray3.png:/images/rstray3.png + + + false + + + + 0 + + + 0 + + + + + + 16777215 + 60 + + + + QFrame#frame{background-image: url(:/images/connect/connectFriendBanner.png);} + + + + QFrame::NoFrame + + + QFrame::Raised + + + 1 + + + + 6 + + + 6 + + + + + + 48 + 48 + + + + + 48 + 48 + + + + + + + + + + :/images/fileshare48.png + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + + + Share Folder + + + + + + + + Local Path + + + + + + + true + + + + + + + + 27 + 0 + + + + + 200 + 200 + + + + Browse + + + + 24 + 24 + + + + + + + + Virtual Folder + + + + + + + + + + + + Share Flags + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Browseable by Friends + + + Browsable + + + + + + + Anonymous shared Network Wide + + + Network Wide + + + + + + + + + + + + + + 0 + 0 + + + + + 200 + 200 + + + + OK + + + + 16 + 16 + + + + false + + + true + + + + + + + Qt::Horizontal + + + + 191 + 20 + + + + + + + + Cancel + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/ShareManager.cpp b/retroshare-gui/src/gui/ShareManager.cpp new file mode 100644 index 000000000..4a5302c2a --- /dev/null +++ b/retroshare-gui/src/gui/ShareManager.cpp @@ -0,0 +1,364 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ShareManager.h" +#include "ShareDialog.h" +#include "settings/rsharesettings.h" + +/* Images for context menu icons */ +#define IMAGE_CANCEL ":/images/delete.png" +#define IMAGE_EDIT ":/images/edit_16.png" + +#define COLUMN_PATH 0 +#define COLUMN_VIRTUALNAME 1 +#define COLUMN_NETWORKWIDE 2 +#define COLUMN_BROWSABLE 3 +#define COLUMN_COUNT 3 + +ShareManager *ShareManager::_instance = NULL ; + +/** Default constructor */ +ShareManager::ShareManager(QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + isLoading = false; + load(); + + Settings->loadWidgetInformation(this); + + connect(ui.addButton, SIGNAL(clicked( bool ) ), this , SLOT( showShareDialog() ) ); + connect(ui.editButton, SIGNAL(clicked( bool ) ), this , SLOT( editShareDirectory() ) ); + connect(ui.removeButton, SIGNAL(clicked( bool ) ), this , SLOT( removeShareDirectory() ) ); + connect(ui.closeButton, SIGNAL(clicked()), this, SLOT(close())); + + connect(ui.shareddirList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(shareddirListCostumPopupMenu(QPoint))); + connect(ui.shareddirList, SIGNAL(currentCellChanged(int,int,int,int)), this, SLOT(shareddirListCurrentCellChanged(int,int,int,int))); + + ui.editButton->setEnabled(false); + ui.removeButton->setEnabled(false); + + ui.shareddirList->horizontalHeader()->setResizeMode( COLUMN_PATH, QHeaderView::Stretch); + ui.shareddirList->horizontalHeader()->setResizeMode( COLUMN_BROWSABLE, QHeaderView::Interactive); + + ui.shareddirList->horizontalHeader()->resizeSection( COLUMN_PATH, 360 ); + ui.shareddirList->horizontalHeader()->setStretchLastSection(false); + + ui.shareddirList->setRangeSelected(QTableWidgetSelectionRange(0, 0, 0, COLUMN_COUNT), true); + + setAcceptDrops(true); + + setAttribute(Qt::WA_DeleteOnClose, true); +} + +ShareManager::~ShareManager() +{ + _instance = NULL; + + Settings->saveWidgetInformation(this); +} + +void ShareManager::shareddirListCostumPopupMenu( QPoint point ) +{ + QMenu contextMnu( this ); + + QAction *editAct = new QAction(QIcon(IMAGE_EDIT), tr( "Edit" ), &contextMnu ); + connect( editAct , SIGNAL( triggered() ), this, SLOT( editShareDirectory() ) ); + + QAction *removeAct = new QAction(QIcon(IMAGE_CANCEL), tr( "Remove" ), &contextMnu ); + connect( removeAct , SIGNAL( triggered() ), this, SLOT( removeShareDirectory() ) ); + + contextMnu.addAction( editAct ); + contextMnu.addAction( removeAct ); + + contextMnu.exec(QCursor::pos()); +} + +/** Loads the settings for this page */ +void ShareManager::load() +{ + isLoading = true; + std::cerr << "ShareManager:: In load !!!!!" << std::endl ; + + std::list::const_iterator it; + std::list dirs; + rsFiles->getSharedDirectories(dirs); + + /* get a link to the table */ + QTableWidget *listWidget = ui.shareddirList; + + /* set new row count */ + listWidget->setRowCount(dirs.size()); + + connect(this,SIGNAL(itemClicked(QTableWidgetItem*)),this,SLOT(updateFlags(QTableWidgetItem*))) ; + +#ifndef USE_COMBOBOX + QString ToolTips [2] = { tr("If checked, the share is anonymously shared to anybody."), + tr("If checked, the share is browsable by your friends.") }; + int Flags [2] = { RS_FILE_HINTS_NETWORK_WIDE, RS_FILE_HINTS_BROWSABLE }; +#endif + + int row=0 ; + for(it = dirs.begin(); it != dirs.end(); it++,++row) + { + listWidget->setItem(row, COLUMN_PATH, new QTableWidgetItem(QString::fromUtf8((*it).filename.c_str()))); + listWidget->setItem(row, COLUMN_VIRTUALNAME, new QTableWidgetItem(QString::fromUtf8((*it).virtualname.c_str()))); + +#ifdef USE_COMBOBOX + QComboBox *cb = new QComboBox ; + cb->addItem(QString("Network Wide")) ; + cb->addItem(QString("Browsable")) ; + cb->addItem(QString("Universal")) ; + + cb->setToolTip(QString("Decide here whether this directory is\n* Network Wide: \tanonymously shared over the network (including your friends)\n* Browsable: \tbrowsable by your friends\n* Universal: \t\tboth")) ; + + // TODO + // - set combobox current value depending on what rsFiles reports. + // - use a signal mapper to get the correct row that contains the combo box sending the signal: + // mapper = new SignalMapper(this) ; + // + // for(all cb) + // { + // signalMapper->setMapping(cb,...) + // } + // + int index = 0 ; + index += ((*it).shareflags & RS_FILE_HINTS_NETWORK_WIDE) > 0 ; + index += (((*it).shareflags & RS_FILE_HINTS_BROWSABLE) > 0) * 2 ; + listWidget->setCellWidget(row,1,cb); + + if(index < 1 || index > 3) + std::cerr << "******* ERROR IN FILE SHARING FLAGS. Flags = " << (*it).shareflags << " ***********" << std::endl ; + else + index-- ; + + cb->setCurrentIndex(index) ; +#else + int col; + for (col = 0; col <= 1; col++) { + QModelIndex index = listWidget->model()->index(row, col + COLUMN_NETWORKWIDE, QModelIndex()); + QCheckBox *cb = (QCheckBox*) listWidget->indexWidget(index); + if (cb == NULL) { + cb = new QCheckBox; + cb->setToolTip(ToolTips [col]); + listWidget->setCellWidget(row, col + COLUMN_NETWORKWIDE, cb); + + QObject::connect(cb, SIGNAL(toggled(bool)), this, SLOT(updateFlags(bool))) ; + } + cb->setChecked((*it).shareflags & Flags [col]); + } +#endif + } + + //ui.incomingDir->setText(QString::fromStdString(rsFiles->getDownloadDirectory())); + + listWidget->update(); /* update display */ + update(); + + isLoading = false ; +} + +void ShareManager::showYourself() +{ + if(_instance == NULL) + _instance = new ShareManager(NULL,0) ; + + _instance->show() ; + _instance->activateWindow(); +} + +/*static*/ void ShareManager::postModDirectories(bool update_local) +{ + if (_instance == NULL || _instance->isHidden()) { + return; + } + + if (update_local) { + _instance->load(); + } +} + +void ShareManager::updateFlags(bool b) +{ + if(isLoading) + return ; + + std::cerr << "Updating flags (b=" << b << ") !!!" << std::endl ; + + std::list::iterator it; + std::list dirs; + rsFiles->getSharedDirectories(dirs); + + int row=0 ; + for(it = dirs.begin(); it != dirs.end(); it++,++row) + { + std::cerr << "Looking for row=" << row << ", file=" << (*it).filename << ", flags=" << (*it).shareflags << std::endl ; + uint32_t current_flags = 0 ; + current_flags |= (dynamic_cast(ui.shareddirList->cellWidget(row,COLUMN_NETWORKWIDE)))->isChecked()? RS_FILE_HINTS_NETWORK_WIDE:0 ; + current_flags |= (dynamic_cast(ui.shareddirList->cellWidget(row,COLUMN_BROWSABLE)))->isChecked()? RS_FILE_HINTS_BROWSABLE:0 ; + + if( (*it).shareflags ^ current_flags ) + { + (*it).shareflags = current_flags ; + rsFiles->updateShareFlags(*it) ; // modifies the flags + + std::cout << "Updating share flags for directory " << (*it).filename << std::endl ; + } + } +} + +void ShareManager::editShareDirectory() +{ + /* id current dir */ + int row = ui.shareddirList->currentRow(); + QTableWidgetItem *item = ui.shareddirList->item(row, COLUMN_PATH); + + if (item) { + std::string filename = item->text().toUtf8().constData(); + + std::list dirs; + rsFiles->getSharedDirectories(dirs); + + std::list::const_iterator it; + for (it = dirs.begin(); it != dirs.end(); it++) { + if (it->filename == filename) { + /* file name found, show dialog */ + ShareDialog sharedlg (it->filename, this); + sharedlg.exec(); + break; + } + } + } +} + +void ShareManager::removeShareDirectory() +{ + /* id current dir */ + /* ask for removal */ + QTableWidget *listWidget = ui.shareddirList; + int row = listWidget -> currentRow(); + QTableWidgetItem *qdir = listWidget->item(row, COLUMN_PATH); + + if (qdir) + { + if ((QMessageBox::question(this, tr("Warning!"),tr("Do you really want to stop sharing this directory ?"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) + { + rsFiles->removeSharedDirectory( qdir->text().toUtf8().constData()); + load(); + } + } +} + +void ShareManager::showEvent(QShowEvent *event) +{ + if (!event->spontaneous()) + { + load(); + } +} + +void ShareManager::showShareDialog() +{ + ShareDialog sharedlg ("", this); + sharedlg.exec(); +} + +void ShareManager::shareddirListCurrentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn) +{ + Q_UNUSED(currentColumn); + Q_UNUSED(previousRow); + Q_UNUSED(previousColumn); + + if (currentRow >= 0) { + ui.editButton->setEnabled(true); + ui.removeButton->setEnabled(true); + } else { + ui.editButton->setEnabled(false); + ui.removeButton->setEnabled(false); + } +} + +void ShareManager::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } +} + +void ShareManager::dropEvent(QDropEvent *event) +{ + if (!(Qt::CopyAction & event->possibleActions())) { + /* can't do it */ + return; + } + + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + + bool errorShown = false; + + if (event->mimeData()->hasUrls()) { + QList urls = event->mimeData()->urls(); + QList::iterator it; + for (it = urls.begin(); it != urls.end(); it++) { + QString localpath = it->toLocalFile(); + + if (localpath.isEmpty() == false) { + QDir dir(localpath); + if (dir.exists()) { + SharedDirInfo sdi; + sdi.filename = localpath.toUtf8().constData(); + sdi.virtualname.clear(); + + sdi.shareflags = 0; + + /* add new share */ + rsFiles->addSharedDirectory(sdi); + } else if (QFile::exists(localpath)) { + if (errorShown == false) { + QMessageBox mb(tr("Drop file error."), tr("File can't be dropped, only directories are accepted."), QMessageBox::Information, QMessageBox::Ok, 0, 0, this); + mb.exec(); + errorShown = true; + } + } else { + QMessageBox mb(tr("Drop file error."), tr("Directory not found or directory name not accepted."), QMessageBox::Information, QMessageBox::Ok, 0, 0, this); + mb.exec(); + } + } + } + } + + event->setDropAction(Qt::CopyAction); + event->accept(); +} diff --git a/retroshare-gui/src/gui/ShareManager.h b/retroshare-gui/src/gui/ShareManager.h new file mode 100644 index 000000000..885962b2f --- /dev/null +++ b/retroshare-gui/src/gui/ShareManager.h @@ -0,0 +1,76 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _SHAREMANAGER_H +#define _SHAREMANAGER_H + +#include +#include + +#include "ui_ShareManager.h" + +class ShareManager : public QDialog +{ + Q_OBJECT + +public: + static void showYourself() ; + static void postModDirectories(bool update_local); + +private: + /** Default constructor */ + ShareManager( QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~ShareManager(); + + /** Loads the settings for this page */ + void load(); + +protected: + virtual void showEvent(QShowEvent * event); + + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); + +private slots: + /** Create the context popup menu and it's submenus */ + void shareddirListCurrentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn); + void shareddirListCostumPopupMenu( QPoint point ); + + void showShareDialog(); + void editShareDirectory(); + void removeShareDirectory(); + void updateFlags(bool); + +private: + static ShareManager *_instance; + bool isLoading; + + /** Define the popup menus for the Context menu */ + QMenu* contextMnu; + + /** Qt Designer generated object */ + Ui::ShareManager ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/ShareManager.ui b/retroshare-gui/src/gui/ShareManager.ui new file mode 100644 index 000000000..39aee17a7 --- /dev/null +++ b/retroshare-gui/src/gui/ShareManager.ui @@ -0,0 +1,315 @@ + + + ShareManager + + + Qt::NonModal + + + + 0 + 0 + 506 + 343 + + + + RetroShare Share Manager + + + + :/images/rstray3.png:/images/rstray3.png + + + false + + + + 0 + + + 0 + + + + + QFrame#frame{background-image: url(:/images/connect/connectFriendBanner.png);} + + + + QFrame::NoFrame + + + QFrame::Raised + + + 1 + + + + 6 + + + 6 + + + + + + 48 + 48 + + + + + 48 + 48 + + + + + + + + + + :/images/fileshare48.png + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + + + Shared Folder Manager + + + + 2 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + true + + + + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + true + + + 100 + + + true + + + false + + + 22 + + + false + + + 22 + + + true + + + true + + + 100 + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + + + + Browsable + + + + + + + + + + + + + + + 0 + 0 + + + + + 200 + 200 + + + + Add a Share Directory + + + Add + + + + 24 + 24 + + + + + + + + + 0 + 0 + + + + + 200 + 200 + + + + Stop sharing selected Directory + + + Remove + + + + 16 + 16 + + + + + + + + Qt::Horizontal + + + + 191 + 20 + + + + + + + + Close + + + + + + + Edit selected Shared Directory + + + Edit + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/SharedFilesDialog.cpp b/retroshare-gui/src/gui/SharedFilesDialog.cpp new file mode 100644 index 000000000..cb9b2aca4 --- /dev/null +++ b/retroshare-gui/src/gui/SharedFilesDialog.cpp @@ -0,0 +1,1022 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "SharedFilesDialog.h" +#include "settings/AddFileAssociationDialog.h" +#include "util/RsAction.h" +#include "msgs/MessageComposer.h" +#include "settings/rsharesettings.h" +#ifdef RS_USE_LINKS +#include "AddLinksDialog.h" +#endif +#include "RetroShareLink.h" +#include "RemoteDirModel.h" +#include "common/PeerDefs.h" + +#include +#include + + +/* Images for context menu icons */ +#define IMAGE_DOWNLOAD ":/images/download16.png" +#define IMAGE_PLAY ":/images/start.png" +#define IMAGE_HASH_BUSY ":/images/settings.png" +#define IMAGE_HASH_DONE ":/images/accepted16.png" +#define IMAGE_MSG ":/images/message-mail.png" +#define IMAGE_ATTACHMENT ":/images/attachment.png" +#define IMAGE_FRIEND ":/images/peers_16x16.png" +#define IMAGE_PROGRESS ":/images/browse-looking.gif" +#define IMAGE_COPYLINK ":/images/copyrslink.png" +#define IMAGE_OPENFOLDER ":/images/folderopen.png" +#define IMAGE_OPENFILE ":/images/fileopen.png" + +// Define to avoid using the search in treeview, because it is really slow for now. +// +#define DONT_USE_SEARCH_IN_TREE_VIEW 1 + +const QString Image_AddNewAssotiationForFile = ":/images/kcmsystem24.png"; + +class SFDSortFilterProxyModel : public QSortFilterProxyModel +{ +public: + SFDSortFilterProxyModel(RetroshareDirModel *dirModel, QObject *parent) : QSortFilterProxyModel(parent) + { + m_dirModel = dirModel; + }; + +protected: + virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const + { + bool dirLeft = (m_dirModel->getType(left) == DIR_TYPE_DIR); + bool dirRight = (m_dirModel->getType(right) == DIR_TYPE_DIR); + + if (dirLeft ^ dirRight) { + return dirLeft; + } + + return QSortFilterProxyModel::lessThan(left, right); + } + +private: + RetroshareDirModel *m_dirModel; +}; + +/** Constructor */ +SharedFilesDialog::SharedFilesDialog(QWidget *parent) +: RsAutoUpdatePage(1000,parent),model(NULL) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect(ui.checkButton, SIGNAL(clicked()), this, SLOT(forceCheck())); + 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.localDirTreeView, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( sharedDirTreeWidgetContextMenu( QPoint ) ) ); + connect( ui.remoteDirTreeView, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( shareddirtreeviewCostumPopupMenu( QPoint ) ) ); + +// connect( ui.remoteDirTreeView, SIGNAL( doubleClicked(const QModelIndex&)), this, SLOT( downloadRemoteSelected())); + connect( ui.downloadButton, SIGNAL( clicked()), this, SLOT( downloadRemoteSelected())); + + connect(ui.indicatorCBox, SIGNAL(currentIndexChanged(int)), this, SLOT(indicatorChanged(int))); + +/* + connect( ui.remoteDirTreeView, SIGNAL( itemExpanded( QTreeWidgetItem * ) ), + this, SLOT( checkForLocalDirRequest( QTreeWidgetItem * ) ) ); + + connect( ui.localDirTreeWidget, SIGNAL( itemExpanded( QTreeWidgetItem * ) ), + this, SLOT( checkForRemoteDirRequest( QTreeWidgetItem * ) ) ); +*/ + + tree_model = new TreeStyle_RDM(true); + flat_model = new FlatStyle_RDM(true); + + tree_proxyModel = new SFDSortFilterProxyModel(tree_model, this); + tree_proxyModel->setDynamicSortFilter(true); + tree_proxyModel->setSourceModel(tree_model); + tree_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + tree_proxyModel->setSortRole(RetroshareDirModel::SortRole); + tree_proxyModel->sort(0); + + flat_proxyModel = new SFDSortFilterProxyModel(flat_model, this); + flat_proxyModel->setDynamicSortFilter(true); + flat_proxyModel->setSourceModel(flat_model); + flat_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + flat_proxyModel->setSortRole(RetroshareDirModel::SortRole); + flat_proxyModel->sort(0); + + localModel = new TreeStyle_RDM(false); + + localProxyModel = new SFDSortFilterProxyModel(localModel, this); + localProxyModel->setDynamicSortFilter(true); + localProxyModel->setSourceModel(localModel); + localProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + localProxyModel->setSortRole(RetroshareDirModel::SortRole); + localProxyModel->sort(0); + + ui.localDirTreeView->setModel(localProxyModel); + + connect( ui.localDirTreeView, SIGNAL( collapsed(const QModelIndex & ) ), localModel, SLOT( collapsed(const QModelIndex & ) ) ); + connect( ui.localDirTreeView, SIGNAL( expanded(const QModelIndex & ) ), localModel, SLOT( expanded(const QModelIndex & ) ) ); + + connect( localModel, SIGNAL( layoutAboutToBeChanged() ), ui.localDirTreeView, SLOT( reset() ) ); + connect( localModel, SIGNAL( layoutChanged() ), ui.localDirTreeView, SLOT( update() ) ); + + connect(ui.filterClearButton, SIGNAL(clicked()), this, SLOT(clearFilter())); + connect(ui.filterStartButton, SIGNAL(clicked()), this, SLOT(startFilter())); + connect(ui.filterPatternLineEdit, SIGNAL(returnPressed()), this, SLOT(startFilter())); + connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged())); + + /* Set header resize modes and initial section sizes */ + QHeaderView * l_header = ui.localDirTreeView->header () ; +// l_header->setResizeMode (0, QHeaderView::Interactive); +// l_header->setResizeMode (1, QHeaderView::Fixed); +// l_header->setResizeMode (2, QHeaderView::Interactive); +// l_header->setResizeMode (3, QHeaderView::Interactive); +// l_header->setResizeMode (4, QHeaderView::Interactive); + + l_header->resizeSection ( 0, 490 ); + l_header->resizeSection ( 1, 70 ); + l_header->resizeSection ( 2, 100 ); + l_header->resizeSection ( 3, 100 ); +// l_header->resizeSection ( 4, 100 ); + + l_header->setStretchLastSection(false); +// l_header->setHighlightSections(false); + + // Setup the current view model. + // + changeCurrentViewModel(ui.viewType_CB->currentIndex()) ; + + /* Set header resize modes and initial section sizes */ + QHeaderView * r_header = ui.remoteDirTreeView->header () ; + + r_header->setResizeMode (0, QHeaderView::Interactive); + r_header->setStretchLastSection(false); + +// r_header->setResizeMode (1, QHeaderView::Fixed); +// // r_header->setResizeMode (2, QHeaderView::Interactive); +// r_header->setResizeMode (3, QHeaderView::Fixed); +// // r_header->setResizeMode (4, QHeaderView::Interactive); + + r_header->resizeSection ( 0, 490 ); + r_header->resizeSection ( 1, 70 ); + r_header->resizeSection ( 2, 80 ); + r_header->resizeSection ( 3, 100 ); + r_header->resizeSection ( 4, 80 ); + +// r_header->setHighlightSections(false); + + /* Set Multi Selection */ + ui.remoteDirTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection); + ui.localDirTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection); + +//#ifdef RS_RELEASE_VERSION +// ui.filterLabel->hide(); +// ui.filterPatternLineEdit->hide(); +//#endif + + // load settings + processSettings(true); + + // Hide columns after loading the settings + ui.remoteDirTreeView->setColumnHidden(3,false) ; + ui.remoteDirTreeView->setColumnHidden(4,true) ; + ui.localDirTreeView->setColumnHidden(4,true) ; + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif + copylinklocalAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Copy retroshare Links to Clipboard" ), this ); + connect( copylinklocalAct , SIGNAL( triggered() ), this, SLOT( copyLinkLocal() ) ); + copylinklocalhtmlAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Copy retroshare Links to Clipboard (HTML)" ), this ); + connect( copylinklocalhtmlAct , SIGNAL( triggered() ), this, SLOT( copyLinkhtml() ) ); + sendlinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Send retroshare Links" ), this ); + connect( sendlinkAct , SIGNAL( triggered() ), this, SLOT( sendLinkTo( ) ) ); + sendhtmllinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Send retroshare Links (HTML)" ), this ); + connect( sendhtmllinkAct , SIGNAL( triggered() ), this, SLOT( sendHtmlLinkTo( ) ) ); +#ifdef RS_USE_LINKS + sendlinkCloudAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Send retroshare Links to Cloud" ), this ); + connect( sendlinkCloudAct , SIGNAL( triggered() ), this, SLOT( sendLinkToCloud( ) ) ); + addlinkCloudAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Add Links to Cloud" ), this ); + connect( addlinkCloudAct , SIGNAL( triggered() ), this, SLOT( addLinkToCloud( ) ) ); +#endif + openfileAct = new QAction(QIcon(IMAGE_OPENFILE), tr("Open File"), this); + connect(openfileAct, SIGNAL(triggered()), this, SLOT(openfile())); + openfolderAct = new QAction(QIcon(IMAGE_OPENFOLDER), tr("Open Folder"), this); + connect(openfolderAct, SIGNAL(triggered()), this, SLOT(openfolder())); +} + +void SharedFilesDialog::hideEvent(QHideEvent *) +{ + if(model!=NULL) + model->setVisible(false) ; + //std::cerr << "Hidden!"<< std::endl; +} +void SharedFilesDialog::showEvent(QShowEvent *) +{ + if(model!=NULL) + { + model->setVisible(true) ; + model->update() ; + } + //std::cerr << "Shown!"<< std::endl; +} +SharedFilesDialog::~SharedFilesDialog() +{ + // save settings + processSettings(false); +} + +void SharedFilesDialog::processSettings(bool bLoad) +{ + Settings->beginGroup("SharedFilesDialog"); + + if (bLoad) { + // load settings + + // state of the trees + ui.localDirTreeView->header()->restoreState(Settings->value("LocalDirTreeView").toByteArray()); + ui.remoteDirTreeView->header()->restoreState(Settings->value("RemoteDirTreeView").toByteArray()); + + // state of splitter + ui.splitter->restoreState(Settings->value("Splitter").toByteArray()); + + // view type + ui.viewType_CB->setCurrentIndex(Settings->value("ViewType").toInt()); + } else { + // save settings + + // state of trees + Settings->setValue("LocalDirTreeView", ui.localDirTreeView->header()->saveState()); + Settings->setValue("RemoteDirTreeView", ui.remoteDirTreeView->header()->saveState()); + + // state of splitter + Settings->setValue("Splitter", ui.splitter->saveState()); + + // view type + Settings->setValue("ViewType", ui.viewType_CB->currentIndex()); + } + + Settings->endGroup(); +} + +void SharedFilesDialog::changeCurrentViewModel(int c) +{ + disconnect( ui.remoteDirTreeView, SIGNAL( collapsed(const QModelIndex & ) ), 0, 0 ); + disconnect( ui.remoteDirTreeView, SIGNAL( expanded(const QModelIndex & ) ), 0, 0 ); + + if(model!=NULL) + model->setVisible(false) ; + + if(c == 0) + { + model = tree_model ; + proxyModel = tree_proxyModel ; + ui.remoteDirTreeView->setColumnHidden(3,true) ; + ui.remoteDirTreeView->setColumnHidden(4,true) ; +#ifdef DONT_USE_SEARCH_IN_TREE_VIEW + ui.filterLabel->hide(); + ui.filterPatternLineEdit->hide(); + ui.filterStartButton->hide(); + ui.filterClearButton->hide(); +#endif + } + else + { + model = flat_model ; + proxyModel = flat_proxyModel ; + ui.remoteDirTreeView->setColumnHidden(3,false) ; + ui.remoteDirTreeView->setColumnHidden(4,false) ; +#ifdef DONT_USE_SEARCH_IN_TREE_VIEW + ui.filterLabel->show(); + ui.filterPatternLineEdit->show(); +#endif + } + + if(isVisible()) + { + model->setVisible(true) ; + model->update() ; + } + + connect( ui.remoteDirTreeView, SIGNAL( collapsed(const QModelIndex & ) ), model, SLOT( collapsed(const QModelIndex & ) ) ); + connect( ui.remoteDirTreeView, SIGNAL( expanded(const QModelIndex & ) ), model, SLOT( expanded(const QModelIndex & ) ) ); + + ui.remoteDirTreeView->setModel(proxyModel); + ui.remoteDirTreeView->update(); + + ui.remoteDirTreeView->header()->headerDataChanged(Qt::Horizontal,0,4) ; + +#ifdef DONT_USE_SEARCH_IN_TREE_VIEW + if(c == 1) +#endif + FilterItems(); +} + +void SharedFilesDialog::checkUpdate() +{ + /* update */ + if (rsFiles->InDirectoryCheck()) + { + ui.checkButton->setText(tr("Checking...")); + } + else + { + ui.checkButton->setText(tr("Check files")); + ui.hashLabel->setPixmap(QPixmap(IMAGE_HASH_DONE)); + ui.hashLabel->setToolTip("") ; + } + + return; +} + + +void SharedFilesDialog::forceCheck() +{ + rsFiles->ForceDirectoryCheck(); + return; +} + + +void SharedFilesDialog::shareddirtreeviewCostumPopupMenu( QPoint point ) +{ + QModelIndex idx = ui.remoteDirTreeView->indexAt(point); + if (!idx.isValid()) + return; + QModelIndex midx = proxyModel->mapToSource(idx); + if (!midx.isValid()) + return; + + int type = model->getType(midx); + if (type != DIR_TYPE_DIR && type != DIR_TYPE_FILE) { + return; + } + + QMenu contextMnu( this ); + + 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( copyLinkRemote() ) ); + + QAction *sendremotelinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Send retroshare Link" ), &contextMnu ); + connect( sendremotelinkAct , SIGNAL( triggered() ), this, SLOT( sendremoteLinkTo( ) ) ); + + contextMnu.addSeparator(); + contextMnu.addAction( copyremotelinkAct); + contextMnu.addAction( sendremotelinkAct); + contextMnu.addSeparator(); + contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to"), this, SLOT(addMsgRemoteSelected())); + } + + contextMnu.exec(QCursor::pos()); +} + +QModelIndexList SharedFilesDialog::getLocalSelected() +{ + QModelIndexList list = ui.localDirTreeView->selectionModel()->selectedIndexes(); + QModelIndexList proxyList; + for (QModelIndexList::iterator index = list.begin(); index != list.end(); index++) { + proxyList.append(localProxyModel->mapToSource(*index)); + } + + return proxyList; +} + +QModelIndexList SharedFilesDialog::getRemoteSelected() +{ + QModelIndexList list = ui.remoteDirTreeView->selectionModel()->selectedIndexes(); + QModelIndexList proxyList; + for (QModelIndexList::iterator index = list.begin(); index != list.end(); index++) { + proxyList.append(proxyModel->mapToSource(*index)); + } + + return proxyList; +} + +void SharedFilesDialog::downloadRemoteSelected() +{ + /* call back to the model (which does all the interfacing? */ + + std::cerr << "Downloading Files"; + std::cerr << std::endl; + + QModelIndexList lst = getRemoteSelected(); + model -> downloadSelected(lst); +} + +void SharedFilesDialog::copyLink (const QModelIndexList& lst, bool remote) +{ + std::vector dirVec; + + if (remote) + model->getDirDetailsFromSelect(lst, dirVec); + else + localModel->getDirDetailsFromSelect(lst, dirVec); + + std::vector urls ; + + for (int i = 0, n = dirVec.size(); i < n; ++i) + { + const DirDetails& details = dirVec[i]; + + if (details.type == DIR_TYPE_DIR) + { + for (std::list::const_iterator cit = details.children.begin();cit != details.children.end(); ++cit) + { + const DirStub& dirStub = *cit; + + DirDetails details; + uint32_t flags = DIR_FLAGS_DETAILS; + if (remote) + flags |= DIR_FLAGS_REMOTE; + else + flags |= DIR_FLAGS_LOCAL; + + // do not recursive copy sub dirs. + if (!rsFiles->RequestDirDetails(dirStub.ref, details, flags) || details.type != DIR_TYPE_FILE) + continue; + + RetroShareLink link; + if (link.createFile(QString::fromUtf8(details.name.c_str()), details.count, details.hash.c_str())) { + urls.push_back(link) ; + } + } + } + else + { + RetroShareLink link; + if (link.createFile(QString::fromUtf8(details.name.c_str()), details.count, details.hash.c_str())) { + urls.push_back(link) ; + } + } + } + RSLinkClipboard::copyLinks(urls) ; +} + +void SharedFilesDialog::copyLinkRemote() +{ + QModelIndexList lst = getRemoteSelected(); + copyLink (lst, true); +} + +void SharedFilesDialog::copyLinkLocal() +{ + QModelIndexList lst = getLocalSelected(); + copyLink (lst, false); +} + +void SharedFilesDialog::copyLinkhtml( ) +{ + copyLinkLocal (); + + QString link = QApplication::clipboard()->text(); + + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(" " + link + ""); + +} + +void SharedFilesDialog::sendremoteLinkTo() +{ + copyLinkRemote (); + + /* create a message */ + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + /* fill it in + * files are receommended already + * just need to set peers + */ + std::cerr << "SharedFilesDialog::sendremoteLinkTo()" << std::endl; + nMsgDialog->insertTitleText(tr("RetroShare Link")); + nMsgDialog->insertMsgText(RSLinkClipboard::toHtml()); + + nMsgDialog->show(); + + /* window will destroy itself! */ +} + +void SharedFilesDialog::sendLinkTo() +{ + copyLinkLocal (); + + /* create a message */ + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + /* fill it in + * files are receommended already + * just need to set peers + */ + std::cerr << "SharedFilesDialog::sendLinkTo()" << std::endl; + nMsgDialog->insertTitleText(tr("RetroShare Link")); + + nMsgDialog->insertMsgText(RSLinkClipboard::toHtml()); + + nMsgDialog->show(); + + /* window will destroy itself! */ +} + +void SharedFilesDialog::sendHtmlLinkTo() +{ + copyLinkLocal (); + + /* create a message */ + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + /* fill it in + * files are receommended already + * just need to set peers + */ + std::cerr << "SharedFilesDialog::sendLinkTo()" << std::endl; + nMsgDialog->insertTitleText(tr("RetroShare Link")); + // nMsgDialog->insertHtmlText(QApplication::clipboard()->text().toStdString());// not compatible with multiple links + nMsgDialog->insertMsgText(RSLinkClipboard::toHtml()); + + nMsgDialog->show(); + + /* window will destroy itself! */ +} + +#ifdef RS_USE_LINKS +void SharedFilesDialog::sendLinkToCloud() +{ + copyLinkLocal (); + + AddLinksDialog *nAddLinksDialog = new AddLinksDialog(QApplication::clipboard()->text()); + + nAddLinksDialog->addLinkComment(); + nAddLinksDialog->close(); + + /* window will destroy itself! */ +} + +void SharedFilesDialog::addLinkToCloud() +{ + copyLinkLocal (); + + AddLinksDialog *nAddLinksDialog = new AddLinksDialog(QApplication::clipboard()->text()); + + nAddLinksDialog->show(); + + /* window will destroy itself! */ +} +#endif + +void SharedFilesDialog::playselectedfiles() +{ + /* call back to the model (which does all the interfacing? */ + + std::cerr << "SharedFilesDialog::playselectedfiles()"; + std::cerr << std::endl; + + std::list paths; + localModel -> getFilePaths(getLocalSelected(), paths); + + std::list::iterator it; + QStringList fullpaths; + for(it = paths.begin(); it != paths.end(); it++) + { + std::string fullpath; + rsFiles->ConvertSharedFilePath(*it, fullpath); + fullpaths.push_back(QString::fromStdString(fullpath)); + + std::cerr << "Playing: " << fullpath; + std::cerr << std::endl; + + } + + playFiles(fullpaths); + + std::cerr << "SharedFilesDialog::playselectedfiles() Completed"; + std::cerr << std::endl; +} + +void SharedFilesDialog::addMsgRemoteSelected() +{ + std::list files_info ; + + model->getFileInfoFromIndexList(getRemoteSelected(),files_info); + + if(files_info.empty()) + return ; + + /* create a message */ + + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + nMsgDialog->insertFileList(files_info) ; + nMsgDialog->insertTitleText(tr("Recommendation(s)")); + nMsgDialog->insertMsgText(tr("Recommendation(s)")); + nMsgDialog->show(); + + /* window will destroy itself! */ +} + +void SharedFilesDialog::recommendFilesToMsg() +{ + std::list files_info ; + + localModel->getFileInfoFromIndexList(getLocalSelected(),files_info); + + if(files_info.empty()) + return ; + + /* create a message */ + + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + nMsgDialog->insertFileList(files_info) ; + nMsgDialog->insertTitleText(tr("Recommendation(s)")); + nMsgDialog->insertMsgText(tr("Recommendation(s)")); + nMsgDialog->show(); + + /* window will destroy itself! */ +} + +void SharedFilesDialog::openfile() +{ + /* call back to the model (which does all the interfacing? */ + + std::cerr << "SharedFilesDialog::openfile" << std::endl; + + QModelIndexList qmil = getLocalSelected(); + localModel->openSelected(qmil); +} + + +void SharedFilesDialog::openfolder() +{ + std::cerr << "SharedFilesDialog::openfolder" << std::endl; + + QModelIndexList qmil = getLocalSelected(); + localModel->openSelected(qmil); +} + +void SharedFilesDialog::preModDirectories(bool update_local) +{ + //std::cerr << "SharedFilesDialog::preModDirectories called with update_local = " << update_local << std::endl ; + if (update_local) + localModel->preMods(); + else + model->preMods(); +} + + +void SharedFilesDialog::postModDirectories(bool update_local) +{ + //std::cerr << "SharedFilesDialog::postModDirectories called with update_local = " << update_local << std::endl ; + if (update_local) + { + localModel->postMods(); + ui.localDirTreeView->update() ; + } + else + { + model->postMods(); + ui.remoteDirTreeView->update() ; + + if (ui.filterPatternLineEdit->text().isEmpty() == false) { + FilterItems(); + } + } + + QCoreApplication::flush(); +} + + +void SharedFilesDialog::sharedDirTreeWidgetContextMenu( QPoint point ) +{ + if (!rsPeers) { + /* not ready yet! */ + return; + } + + QModelIndex idx = ui.localDirTreeView->indexAt(point); + if (!idx.isValid()) + return; + QModelIndex midx = localProxyModel->mapToSource(idx); + if (!midx.isValid()) + return; + + currentFile = localModel->data(midx, RetroshareDirModel::FileNameRole).toString(); + + int type = localModel->getType(midx); + + QMenu contextMnu(this); + +// QAction* menuAction = fileAssotiationAction(currentFile) ; +//new QAction(QIcon(IMAGE_PLAY), currentFile, this); +//tr( "111Play File(s)" ), this ); +// connect( openfolderAct , SIGNAL( triggered() ), this, +// SLOT( playselectedfiles() ) ); + + switch (type) { + case DIR_TYPE_DIR: + contextMnu.addAction(openfolderAct); + break; + case DIR_TYPE_FILE: + contextMnu.addAction(openfileAct); + contextMnu.addSeparator(); + contextMnu.addAction(copylinklocalAct); +// contextMnu.addAction(copylinklocalhtmlAct); + contextMnu.addAction(sendlinkAct); +// contextMnu.addAction(sendhtmllinkAct); + contextMnu.addSeparator(); +#ifdef RS_USE_LINKS + contextMnu.addAction(sendlinkCloudAct); + contextMnu.addAction(addlinkCloudAct); + contextMnu.addSeparator(); +#endif + contextMnu.addSeparator(); + contextMnu.addAction(QIcon(IMAGE_MSG), tr("Recommend in a message to"), this, SLOT(recommendFilesToMsg())); + break; + default: + return; + } + + contextMnu.exec(QCursor::pos()); +} + +//============================================================================ + +QAction* +SharedFilesDialog::fileAssotiationAction(const QString fileName) +{ + QAction* result = 0; + + Settings->beginGroup("FileAssotiations"); + + QString key = AddFileAssociationDialog::cleanFileType(currentFile) ; + if ( Settings->contains(key) ) + { + result = new QAction(QIcon(IMAGE_PLAY), tr( "Open File" ), this ); + connect( result , SIGNAL( triggered() ), + this, SLOT( runCommandForFile() ) ); + + currentCommand = (Settings->value( key )).toString(); + } + else + { + result = new QAction(QIcon(Image_AddNewAssotiationForFile), + tr( "Set command for opening this file"), this ); + connect( result , SIGNAL( triggered() ), + this, SLOT( tryToAddNewAssotiation() ) ); + } + + Settings->endGroup(); + + return result; +} + +//============================================================================ + +void +SharedFilesDialog::runCommandForFile() +{ + QStringList tsl; + tsl.append( currentFile ); + QProcess::execute( currentCommand, tsl); + //QString("%1 %2").arg(currentCommand).arg(currentFile) ); + +// QString tmess = "Some command(%1) should be executed here for file %2"; +// tmess = tmess.arg(currentCommand).arg(currentFile); +// QMessageBox::warning(this, tr("RetroShare"), tmess, QMessageBox::Ok); +} + +//============================================================================ + +void +SharedFilesDialog::tryToAddNewAssotiation() +{ + AddFileAssociationDialog afad(true, this);//'add file assotiations' dialog + + afad.setFileType(AddFileAssociationDialog::cleanFileType(currentFile)); + + int ti = afad.exec(); + + if (ti==QDialog::Accepted) + { + QString currType = afad.resultFileType() ; + QString currCmd = afad.resultCommand() ; + + Settings->setValueToGroup("FileAssotiations", currType, currCmd); + } +} + +//============================================================================ +/** + Toggles the Splitted, Remote and Local View on and off*/ + +void SharedFilesDialog::showFrame(bool show) +{ + if (show) { + ui.localframe->setVisible(true); + ui.remoteframe->setVisible(false); + + ui.localButton->setChecked(true); + + ui.remoteButton->setChecked(false); + ui.splittedButton->setChecked(false); + + ui.labeltext->setText( tr("My Shared Files")); + } +} + +void SharedFilesDialog::showFrameRemote(bool show) +{ + if (show) { + ui.remoteframe->setVisible(true); + ui.localframe->setVisible(false); + + ui.remoteButton->setChecked(true); + ui.localButton->setChecked(false); + ui.splittedButton->setChecked(false); + + ui.labeltext->setText( tr("Friends Files")); + } +} + +void SharedFilesDialog::showFrameSplitted(bool show) +{ + if (show) { + ui.remoteframe->setVisible(true); + ui.localframe->setVisible(true); + + ui.splittedButton->setChecked(true); + + ui.localButton->setChecked(false); + ui.remoteButton->setChecked(false); + + ui.labeltext->setText( tr("Files")); + } +} + +void SharedFilesDialog::indicatorChanged(int index) +{ + static uint32_t correct_indicator[4] = { IND_ALWAYS,IND_LAST_DAY,IND_LAST_WEEK,IND_LAST_MONTH } ; + + model->changeAgeIndicator(correct_indicator[index]); + localModel->changeAgeIndicator(correct_indicator[index]); + + ui.remoteDirTreeView->update(ui.remoteDirTreeView->rootIndex()); + ui.localDirTreeView->update(ui.localDirTreeView->rootIndex()) ; + + if (correct_indicator[index] != IND_ALWAYS) + { + ui.remoteDirTreeView->sortByColumn(2, Qt::AscendingOrder); + } + else + { + ui.remoteDirTreeView->sortByColumn(0, Qt::AscendingOrder); + } + + updateDisplay() ; +} + +void SharedFilesDialog::filterRegExpChanged() +{ + QString text = ui.filterPatternLineEdit->text(); + + if (text.isEmpty()) { + ui.filterClearButton->hide(); + } else { + ui.filterClearButton->show(); + } + + if (text == lastFilterString) { + ui.filterStartButton->hide(); + } else { + ui.filterStartButton->show(); + } +} + +/* clear Filter */ +void SharedFilesDialog::clearFilter() +{ + ui.filterPatternLineEdit->clear(); + ui.filterPatternLineEdit->setFocus(); + + startFilter(); +} + +/* clear Filter */ +void SharedFilesDialog::startFilter() +{ + ui.filterStartButton->hide(); + lastFilterString = ui.filterPatternLineEdit->text(); + + FilterItems(); +} + +void SharedFilesDialog::FilterItems() +{ + QString text = ui.filterPatternLineEdit->text(); + + setCursor(Qt::WaitCursor); + QCoreApplication::processEvents() ; + + int rowCount = ui.remoteDirTreeView->model()->rowCount(); + for (int row = 0; row < rowCount; row++) + if(proxyModel == tree_proxyModel) + tree_FilterItem(ui.remoteDirTreeView->model()->index(row, 0), text, 0); + else + flat_FilterItem(ui.remoteDirTreeView->model()->index(row, 0), text, 0); + + setCursor(Qt::ArrowCursor); +} + +bool SharedFilesDialog::flat_FilterItem(const QModelIndex &index, const QString &text, int level) +{ + if(index.data(RetroshareDirModel::FileNameRole).toString().contains(text, Qt::CaseInsensitive)) + { + ui.remoteDirTreeView->setRowHidden(index.row(), index.parent(), false); + return false ; + } + else + { + ui.remoteDirTreeView->setRowHidden(index.row(), index.parent(), true); + return true ; + } +} + +bool SharedFilesDialog::tree_FilterItem(const QModelIndex &index, const QString &text, int level) +{ + bool visible = true; + + if (text.isEmpty() == false) { + // better use RetroshareDirModel::getType, but its slow enough + if (/*index.parent().isValid()*/ level >= 1) { + if (index.data(RetroshareDirModel::FileNameRole).toString().contains(text, Qt::CaseInsensitive) == false) { + visible = false; + } + } else { + visible = false; + } + } + + int visibleChildCount = 0; + int rowCount = ui.remoteDirTreeView->model()->rowCount(index); + for (int row = 0; row < rowCount; row++) { + if (tree_FilterItem(ui.remoteDirTreeView->model()->index(row, index.column(), index), text, level + 1)) { + visibleChildCount++; + } + } + + if (visible || visibleChildCount) { + ui.remoteDirTreeView->setRowHidden(index.row(), index.parent(), false); + } else { + ui.remoteDirTreeView->setRowHidden(index.row(), index.parent(), true); + } + + return (visible || visibleChildCount); +} + diff --git a/retroshare-gui/src/gui/SharedFilesDialog.h b/retroshare-gui/src/gui/SharedFilesDialog.h new file mode 100644 index 000000000..05a3f48e2 --- /dev/null +++ b/retroshare-gui/src/gui/SharedFilesDialog.h @@ -0,0 +1,153 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006-2009, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _SHAREDFILESDIALOG_H +#define _SHAREDFILESDIALOG_H + +#include "RsAutoUpdatePage.h" +#include "ui_SharedFilesDialog.h" + +class RetroshareDirModel; +class QSortFilterProxyModel; + +class SharedFilesDialog : public RsAutoUpdatePage +{ + Q_OBJECT + +public: + /** Default Constructor */ + SharedFilesDialog(QWidget *parent = 0); + /** Default Destructor */ + ~SharedFilesDialog(); + + virtual void updatePage() { checkUpdate() ; } + virtual void hideEvent(QHideEvent *) ; + virtual void showEvent(QShowEvent *) ; + + +private slots: + + /* For handling the model updates */ + void preModDirectories(bool update_local); + void postModDirectories(bool update_local); + + void checkUpdate(); + void forceCheck(); + + /** Create the context popup menu and it's submenus */ + void shareddirtreeviewCostumPopupMenu( QPoint point ); + + void sharedDirTreeWidgetContextMenu( QPoint point ); + + void downloadRemoteSelected(); + void addMsgRemoteSelected(); + + void copyLinkRemote(); + void copyLinkLocal(); + void copyLinkhtml(); + void sendLinkTo(); + void sendremoteLinkTo(); + void sendHtmlLinkTo(); +#ifdef RS_USE_LINKS + void sendLinkToCloud(); + void addLinkToCloud(); +#endif + + void showFrame(bool show); + void showFrameRemote(bool show); + void showFrameSplitted(bool show); + + void playselectedfiles(); + void openfile(); + void openfolder(); + + void recommendFilesToMsg(); + void runCommandForFile(); + void tryToAddNewAssotiation(); + + void indicatorChanged(int index); + + void filterRegExpChanged(); + void clearFilter(); + void startFilter(); + + public slots: + void changeCurrentViewModel(int) ; +signals: + void playFiles(QStringList files); + +private: + //now context menu are created again every time theu are called ( in some + //slots.. Maybe it's not good... + //** Define the popup menus for the Context menu */ + //QMenu* contextMnu; + + //QMenu* contextMnu2; + + void processSettings(bool bLoad); + + void copyLink (const QModelIndexList& lst, bool remote); + + void FilterItems(); + bool tree_FilterItem(const QModelIndex &index, const QString &text, int level); + bool flat_FilterItem(const QModelIndex &index, const QString &text, int level); + + QModelIndexList getRemoteSelected(); + QModelIndexList getLocalSelected(); + + /** Defines the actions for the context menu for QTreeWidget */ + QAction* openfileAct; + QAction* openfolderAct; + QAction* copyremotelinkAct; + QAction* copylinklocalAct; + QAction* sendlinkAct; + QAction* sendhtmllinkAct; +#ifdef RS_USE_LINKS + QAction* sendlinkCloudAct; + QAction* addlinkCloudAct; +#endif + QAction* sendchatlinkAct; + QAction* copylinklocalhtmlAct; + + /** Qt Designer generated object */ + Ui::SharedFilesDialog ui; + + /* RetroshareDirModel */ + RetroshareDirModel *tree_model; + RetroshareDirModel *flat_model; + RetroshareDirModel *model; + QSortFilterProxyModel *tree_proxyModel; + QSortFilterProxyModel *flat_proxyModel; + QSortFilterProxyModel *proxyModel; + + RetroshareDirModel *localModel; + QSortFilterProxyModel *localProxyModel; + + QString currentCommand; + QString currentFile; + + QString lastFilterString; + + QAction* fileAssotiationAction(const QString fileName); +}; + +#endif + diff --git a/retroshare-gui/src/gui/SharedFilesDialog.ui b/retroshare-gui/src/gui/SharedFilesDialog.ui new file mode 100644 index 000000000..889df0c0b --- /dev/null +++ b/retroshare-gui/src/gui/SharedFilesDialog.ui @@ -0,0 +1,1027 @@ + + + SharedFilesDialog + + + + 0 + 0 + 934 + 402 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + Qt::NoContextMenu + + + + 0 + + + + + + 0 + 0 + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + 2 + + + 6 + + + + + + 24 + 24 + + + + + + + :/images/fileshare24.png + + + true + + + + + + + + 16777215 + 16 + + + + + Arial + 10 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 100 + 20 + + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + Splitted View + + + + + + + :/images/view_split_top_bottom.png:/images/view_split_top_bottom.png + + + true + + + true + + + true + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + Friends Folders + + + + + + + :/images/friendsfolder24.png:/images/friendsfolder24.png + + + true + + + false + + + true + + + + + + + + 24 + 24 + + + + Qt::NoFocus + + + My Folders + + + + + + + :/images/folder16.png:/images/folder16.png + + + true + + + false + + + true + + + + + + + + All + + + + :/images/view_calendar_list.png:/images/view_calendar_list.png + + + + + One day old + + + + :/images/view_calendar_day.png:/images/view_calendar_day.png + + + + + One Week old + + + + :/images/view_calendar_week.png:/images/view_calendar_week.png + + + + + One month old + + + + :/images/view_calendar_month.png:/images/view_calendar_month.png + + + + + + + + 2 + + + + + + + + :/images/find-16.png + + + + + + + Search files + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + MS Shell Dlg 2 + + + + Qt::NoFocus + + + Start Search + + + QPushButton +{ + border-image: url(:/images/start.png) +} + + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + MS Shell Dlg 2 + + + + Qt::NoFocus + + + Reset + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + + + Tree view + + + + + Flat view + + + + + + + + + + + + + + Qt::Vertical + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + + 4 + 0 + + + + Qt::CustomContextMenu + + + #remoteDirTreeView{border: 1px solid #CCCCCC; +background: white;} + + + true + + + QAbstractItemView::DragOnly + + + false + + + 0 + + + true + + + true + + + false + + + false + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + + 0 + 0 + + + + Qt::CustomContextMenu + + + false + + + #localDirTreeView{border: 1px solid #CCCCCC; +background: white;} + + + true + + + QAbstractItemView::DragOnly + + + false + + + QAbstractItemView::ContiguousSelection + + + true + + + false + + + false + + + + + + + + + + + 2 + + + + + + 140 + 0 + + + + + 16777215 + 28 + + + + Download selected + + + Download + + + + :/images/download16.png:/images/download16.png + + + + + + + Qt::Horizontal + + + + 391 + 20 + + + + + + + + check files + + + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/SoundManager.cpp b/retroshare-gui/src/gui/SoundManager.cpp new file mode 100644 index 000000000..ee78cbe01 --- /dev/null +++ b/retroshare-gui/src/gui/SoundManager.cpp @@ -0,0 +1,103 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "SoundManager.h" +#include "settings/rsharesettings.h" + +SoundManager::SoundManager() +{ + isMute=false; + reInit(); +} + +void SoundManager::doMute(bool t) +{ + isMute=t; +} + +void SoundManager::event_User_go_Online() +{ + if(isMute==true) return; + + if(enable_eventUser_go_Online) + QSound::play(SoundFileUser_go_Online); +} +void SoundManager::event_User_go_Offline() +{ + if(isMute==true) return; + if(enable_eventUser_go_Offline) + QSound::play(SoundFileUser_go_Offline); +} +void SoundManager::event_FileSend_Finished() +{ + if(isMute==true) return; + if(enable_eventFileSend_Finished) + QSound::play(SoundFileFileSend_Finished); +} +void SoundManager::event_FileRecive_Incoming() +{ + if(isMute==true) return; + if(enable_eventFileRecive_Incoming) + QSound::play(SoundFileFileRecive_Incoming); +} + +void SoundManager::event_FileRecive_Finished() +{ + if(isMute==true) return; + if(enable_eventFileRecive_Finished) + QSound::play(SoundFileFileRecive_Finished); +} + + +void SoundManager::event_NewChatMessage() +{ + if(isMute==true) return; + if(enable_eventNewChatMessage) + { + QSound::play(SoundFileNewChatMessage); + + } +} + +void SoundManager::reInit() +{ + Settings->beginGroup("Sound"); + Settings->beginGroup("Enable"); + enable_eventUser_go_Online = Settings->value("User_go_Online",false).toBool(); + enable_eventUser_go_Offline = Settings->value("User_go_Offline",false).toBool(); + enable_eventFileSend_Finished = Settings->value("FileSend_Finished",false).toBool(); + enable_eventFileRecive_Incoming = Settings->value("FileRecive_Incoming",false).toBool(); + enable_eventFileRecive_Finished = Settings->value("FileRecive_Finished",false).toBool(); + enable_eventNewChatMessage = Settings->value("NewChatMessage",false).toBool(); + Settings->endGroup(); + + Settings->beginGroup("SoundFilePath"); + SoundFileUser_go_Online = Settings->value("User_go_Online","").toString(); + SoundFileUser_go_Offline = Settings->value("User_go_Offline","").toString(); + SoundFileFileSend_Finished = Settings->value("FileSend_Finished","").toString(); + SoundFileFileRecive_Incoming = Settings->value("FileRecive_Incoming","").toString(); + SoundFileFileRecive_Finished = Settings->value("FileRecive_Finished","").toString(); + SoundFileNewChatMessage = Settings->value("NewChatMessage","").toString(); + Settings->endGroup(); + Settings->endGroup(); +} diff --git a/retroshare-gui/src/gui/SoundManager.h b/retroshare-gui/src/gui/SoundManager.h new file mode 100644 index 000000000..a95c31553 --- /dev/null +++ b/retroshare-gui/src/gui/SoundManager.h @@ -0,0 +1,60 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#ifndef SOUND_MANAGER_H +#define SOUND_MANAGER_H + +#include + +class SoundManager :public QObject +{ + Q_OBJECT + public: + SoundManager(); + + public slots: + void doMute(bool t); + void event_User_go_Online(); + void event_User_go_Offline(); + void event_FileSend_Finished(); + void event_FileRecive_Incoming(); + void event_FileRecive_Finished(); + void event_NewChatMessage(); + void reInit(); + + + private: + bool isMute; + QString SoundFileUser_go_Online; + QString SoundFileUser_go_Offline; + QString SoundFileFileSend_Finished; + QString SoundFileFileRecive_Incoming; + QString SoundFileFileRecive_Finished; + QString SoundFileNewChatMessage; + + bool enable_eventUser_go_Online; + bool enable_eventUser_go_Offline; + bool enable_eventFileSend_Finished; + bool enable_eventFileRecive_Incoming; + bool enable_eventFileRecive_Finished; + bool enable_eventNewChatMessage; + +}; +#endif diff --git a/retroshare-gui/src/gui/StartDialog.cpp b/retroshare-gui/src/gui/StartDialog.cpp new file mode 100644 index 000000000..8c53dd3de --- /dev/null +++ b/retroshare-gui/src/gui/StartDialog.cpp @@ -0,0 +1,223 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include "StartDialog.h" +#include "InfoDialog.h" +#include "LogoBar.h" +#include +#include +#include "util/Widget.h" +#include "settings/rsharesettings.h" + +/* Define the format used for displaying the date and time */ +#define DATETIME_FMT "MMM dd hh:mm:ss" + + + +/** Default constructor */ +StartDialog::StartDialog(QWidget *parent, Qt::WFlags flags) + : QMainWindow(parent, flags), reqNewCert(false) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + /* Create Bandwidth Graph related QObjects */ + Settings->loadWidgetInformation(this); + + _rsLogoBar = NULL; + + //LogoBar + _rsLogoBar = new LogoBar(ui.callBarFrame); + Widget::createLayout(ui.callBarFrame)->addWidget(_rsLogoBar); + + ui.loadButton->setFocus(); + + + connect(ui.loadButton, SIGNAL(clicked()), this, SLOT(loadPerson())); + connect(ui.autologin_checkbox, SIGNAL(clicked()), this, SLOT(notSecureWarning())); + + /* load the Certificate File name */ + std::string userName; + + /* get all available pgp private certificates.... + * mark last one as default. + */ + std::list accountIds; + std::list::iterator it; + std::string preferedId; + RsInit::getPreferedAccountId(preferedId); + int pidx = -1; + int i; + + if (RsInit::getAccountIds(accountIds)) + { + for(it = accountIds.begin(), i = 0; it != accountIds.end(); it++, i++) + { + const QVariant & userData = QVariant(QString::fromStdString(*it)); + std::string gpgid, name, email, location; + RsInit::getAccountDetails(*it, gpgid, name, email, location); + QString accountName = QString::fromStdString(name + " (") + QString::fromStdString(gpgid).right(8) + ") - " + QString::fromStdString(location); + ui.loadName->addItem(accountName, userData); + + if (preferedId == *it) + { + pidx = i; + } + } + } + + if (pidx > 0) + { + ui.loadName->setCurrentIndex(pidx); + } +} + + + +/** + Overloads the default show() slot so we can set opacity*/ + +void StartDialog::show() +{ + //loadSettings(); + if(!this->isVisible()) { + QMainWindow::show(); + + } +} + +void StartDialog::closeEvent (QCloseEvent * event) +{ + Settings->saveWidgetInformation(this); + + QWidget::closeEvent(event); +} + +void StartDialog::closeinfodlg() +{ + close(); +} + + + +void StartDialog::loadPerson() +{ + std::string accountId = ""; + + int pgpidx = ui.loadName->currentIndex(); + if (pgpidx < 0) + { + /* Message Dialog */ + QMessageBox::warning ( this, + "Load Person Failure", + "Missing PGP Certificate", + QMessageBox::Ok); + return; + } + + QVariant data = ui.loadName->itemData(pgpidx); + accountId = (data.toString()).toStdString(); + + std::string gpgId, gpgName, gpgEmail, sslName; + if (RsInit::getAccountDetails(accountId, + gpgId, gpgName, gpgEmail, sslName)) + { + RsInit::SelectGPGAccount(gpgId); + } + + RsInit::LoadPassword(accountId, ""); + loadCertificates(); +} + +void StartDialog::loadCertificates() +{ + /* Final stage of loading */ + std::string lockFile; + int retVal = RsInit::LockAndLoadCertificates(ui.autologin_checkbox->isChecked(), lockFile); + switch(retVal) + { + case 0: close(); + break; + case 1: QMessageBox::warning( this, + tr("Multiple instances"), + tr("Another RetroShare using the same profile is " + "already running on your system. Please close " + "that instance first, or choose another profile\n" + "lock file:\n ")+ QString::fromStdString(lockFile)); + break; + case 2: QMessageBox::warning( this, + tr("Multiple instances"), + tr("An unexpected error occurred when Retroshare" + "tried to acquire the single instance lock\n" + "lock file:\n ")+ QString::fromStdString(lockFile)); + break; + case 3: QMessageBox::warning( this, + tr("Login Failure"), + tr("Maybe password is wrong") ); + break; + default: std::cerr << "StartDialog::loadCertificates() unexpected switch value " << retVal << std::endl; + } +} + + + +void StartDialog::on_labelProfile_linkActivated(QString link) +{ + +// if ((QMessageBox::question(this, tr("Create a New Profile"),tr("This will generate a new Profile\n Are you sure you want to continue?"),QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes))== QMessageBox::Yes) +// { + reqNewCert = true; + close(); +// } +// else +// return; + +} + +void StartDialog::on_labelInfo_linkActivated(QString link) +{ + InfoDialog infodialog (this); + infodialog.exec (); +} + +bool StartDialog::requestedNewCert() +{ + return reqNewCert; +} + +LogoBar & StartDialog::getLogoBar() const { + return *_rsLogoBar; +} + +void StartDialog::notSecureWarning() { + + /* some error msg */ + if(ui.autologin_checkbox->isChecked()) +#ifdef UBUNTU + QMessageBox::warning ( this, tr("Warning"), tr("The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. \n\n Your PGP passwd will not be stored.\n\nThis choice can be reverted in settings."), QMessageBox::Ok); +#else + QMessageBox::warning ( this, tr("Warning"), tr("The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. \n\n Your PGP passwd will not be stored.\n\nThis choice can be reverted in settings."), QMessageBox::Ok); +#endif + + return; +} diff --git a/retroshare-gui/src/gui/StartDialog.h b/retroshare-gui/src/gui/StartDialog.h new file mode 100644 index 000000000..cfb1b87e6 --- /dev/null +++ b/retroshare-gui/src/gui/StartDialog.h @@ -0,0 +1,90 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _STARTDIALOG_H +#define _STARTDIALOG_H + +#include +/******** +#if (QT_VERSION >= 040300) +#include "qskinobject/qskinobject.h" +#endif +*******/ + +#include "ui_StartDialog.h" + +class LogoBar; + +class StartDialog : public QMainWindow +{ + Q_OBJECT + +public: + /** Default constructor */ + StartDialog(QWidget *parent = 0, Qt::WFlags flags = 0); + + bool requestedNewCert(); + +public slots: + /** Overloaded QWidget.show */ + void show(); + + LogoBar & getLogoBar() const; + +protected: + void closeEvent (QCloseEvent * event); + +private slots: + + void closeinfodlg(); + void loadPerson(); + + /** + * Warns the user that autologin is not secure + */ + void notSecureWarning(); + + void on_labelProfile_linkActivated(QString link); + void on_labelInfo_linkActivated(QString link); + +private: + + /** Loads the saved connectidialog settings */ +// void loadSettings(); + void loadCertificates(); + + LogoBar * _rsLogoBar; + + /** Qt Designer generated object */ + Ui::StartDialog ui; + +/************** +#if (QT_VERSION >= 040300) + QSkinObject *skinobject; +#endif +**************/ + + bool reqNewCert; +}; + +#endif + diff --git a/retroshare-gui/src/gui/StartDialog.ui b/retroshare-gui/src/gui/StartDialog.ui new file mode 100644 index 000000000..8ca527c53 --- /dev/null +++ b/retroshare-gui/src/gui/StartDialog.ui @@ -0,0 +1,719 @@ + + + StartDialog + + + + 0 + 0 + 291 + 433 + + + + + + + + + 0 + 0 + 0 + + + + + + + 244 + 244 + 244 + + + + + + + 244 + 244 + 244 + + + + + + + 241 + 239 + 226 + + + + + + + 140 + 140 + 140 + + + + + + + 163 + 163 + 163 + + + + + + + 0 + 0 + 0 + + + + + + + 244 + 244 + 244 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 236 + 243 + 246 + + + + + + + 106 + 106 + 106 + + + + + + + 197 + 231 + 246 + + + + + + + 0 + 0 + 0 + + + + + + + 232 + 232 + 232 + + + + + + + + + 0 + 0 + 0 + + + + + + + 244 + 244 + 244 + + + + + + + 244 + 244 + 244 + + + + + + + 241 + 239 + 226 + + + + + + + 140 + 140 + 140 + + + + + + + 163 + 163 + 163 + + + + + + + 0 + 0 + 0 + + + + + + + 244 + 244 + 244 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 236 + 243 + 246 + + + + + + + 106 + 106 + 106 + + + + + + + 244 + 244 + 244 + + + + + + + 0 + 0 + 0 + + + + + + + 232 + 232 + 232 + + + + + + + + + 122 + 122 + 122 + + + + + + + 244 + 244 + 244 + + + + + + + 244 + 244 + 244 + + + + + + + 244 + 244 + 244 + + + + + + + 140 + 140 + 140 + + + + + + + 163 + 163 + 163 + + + + + + + 122 + 122 + 122 + + + + + + + 244 + 244 + 244 + + + + + + + 122 + 122 + 122 + + + + + + + 244 + 244 + 244 + + + + + + + 236 + 243 + 246 + + + + + + + 0 + 0 + 0 + + + + + + + 197 + 231 + 246 + + + + + + + 0 + 0 + 0 + + + + + + + 232 + 232 + 232 + + + + + + + + + + + Qt::NoContextMenu + + + RetroShare + + + + :/images/rstray3.png:/images/rstray3.png + + + .QWidget { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #ECECEC, stop:1 #E0E0E0); + } + + + + + 0 + + + 0 + + + 0 + + + + + 0 + + + 6 + + + 0 + + + 6 + + + 6 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QToolButton{ +border-image: url(:/images/avatar_background.png); + +} + + + + + + + + :/images/user/personal64.png:/images/user/personal64.png + + + + 96 + 96 + + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 16777215 + 32 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + + + Qt::Horizontal + + + + 48 + 20 + + + + + + + + + + + 16 + 65 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + + + 9 + + + 9 + + + + + Log In + + + true + + + false + + + + + + + Qt::Horizontal + + + + 61 + 20 + + + + + + + + Qt::Horizontal + + + + 71 + 20 + + + + + + + + + + true + + + + + + + + + Name (GPG Id) - location: + + + + + + + + + + Remember Password + + + false + + + + + + + + + + + loadButton + toolButton + + + + + + diff --git a/retroshare-gui/src/gui/TransfersDialog.cpp b/retroshare-gui/src/gui/TransfersDialog.cpp new file mode 100644 index 000000000..6b8563fb3 --- /dev/null +++ b/retroshare-gui/src/gui/TransfersDialog.cpp @@ -0,0 +1,1644 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifdef WIN32 + #include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "TransfersDialog.h" +#include "RetroShareLink.h" +#include "DetailsDialog.h" +#include "DLListDelegate.h" +#include "ULListDelegate.h" +#include "FileTransferInfoWidget.h" +#include "TurtleRouterDialog.h" +#include "TurtleRouterStatistics.h" +#include "xprogressbar.h" +#include "settings/rsharesettings.h" + +#include +#include +#include +#include "util/misc.h" + +/* Images for context menu icons */ +#define IMAGE_INFO ":/images/fileinfo.png" +#define IMAGE_CANCEL ":/images/delete.png" +#define IMAGE_CLEARCOMPLETED ":/images/deleteall.png" +#define IMAGE_PLAY ":/images/player_play.png" +#define IMAGE_COPYLINK ":/images/copyrslink.png" +#define IMAGE_PASTELINK ":/images/pasterslink.png" +#define IMAGE_PAUSE ":/images/pause.png" +#define IMAGE_RESUME ":/images/resume.png" +#define IMAGE_OPENFOLDER ":/images/folderopen.png" +#define IMAGE_OPENFILE ":/images/fileopen.png" +#define IMAGE_STOP ":/images/stop.png" +#define IMAGE_PREVIEW ":/images/preview.png" +#define IMAGE_PRIORITY ":/images/filepriority.png" +#define IMAGE_PRIORITYLOW ":/images/prioritylow.png" +#define IMAGE_PRIORITYNORMAL ":/images/prioritynormal.png" +#define IMAGE_PRIORITYHIGH ":/images/priorityhigh.png" +#define IMAGE_PRIORITYAUTO ":/images/priorityauto.png" + +Q_DECLARE_METATYPE(FileProgressInfo) + +DetailsDialog *TransfersDialog::detailsdlg = NULL; + +class SortByNameItem : public QStandardItem +{ +public: + SortByNameItem(QHeaderView *header) : QStandardItem() + { + this->header = header; + } + + virtual bool operator<(const QStandardItem &other) const + { + QStandardItemModel *m = model(); + if (m == NULL) { + return QStandardItem::operator<(other); + } + + QStandardItem *myParent = parent(); + QStandardItem *otherParent = other.parent(); + + if (myParent == NULL || otherParent == NULL) { + return QStandardItem::operator<(other); + } + + QStandardItem *myName = myParent->child(index().row(), NAME); + QStandardItem *otherName = otherParent->child(other.index().row(), NAME); + + if (header == NULL || header->sortIndicatorOrder() == Qt::AscendingOrder) { + /* Ascending */ + return *myName < *otherName; + } + + /* Descending, sort peers in ascending order */ + return !(*myName < *otherName); + } + +private: + QHeaderView *header; +}; + +class ProgressItem : public SortByNameItem +{ +public: + ProgressItem(QHeaderView *header) : SortByNameItem(header) {} + + virtual bool operator<(const QStandardItem &other) const + { + const int role = model() ? model()->sortRole() : Qt::DisplayRole; + + FileProgressInfo l = data(role).value(); + FileProgressInfo r = other.data(role).value(); + + if (l < r) { + return true; + } + if (l > r) { + return false; + } + + return SortByNameItem::operator<(other); + } +}; + +/** Constructor */ +TransfersDialog::TransfersDialog(QWidget *parent) +: RsAutoUpdatePage(1000,parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + m_bProcessSettings = false; + + connect( ui.downloadList, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( downloadListCostumPopupMenu( QPoint ) ) ); + + // Set Download list model + DLListModel = new QStandardItemModel(0,ID + 1); + DLListModel->setHeaderData(NAME, Qt::Horizontal, tr("Name", "i.e: file name")); + DLListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size", "i.e: file size")); + DLListModel->setHeaderData(COMPLETED, Qt::Horizontal, tr("Completed", "")); + DLListModel->setHeaderData(DLSPEED, Qt::Horizontal, tr("Speed", "i.e: Download speed")); + DLListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress / Availability", "i.e: % downloaded")); + DLListModel->setHeaderData(SOURCES, Qt::Horizontal, tr("Sources", "i.e: Sources")); + DLListModel->setHeaderData(STATUS, Qt::Horizontal, tr("Status")); + DLListModel->setHeaderData(PRIORITY, Qt::Horizontal, tr("Speed / Queue position")); + DLListModel->setHeaderData(REMAINING, Qt::Horizontal, tr("Remaining")); + DLListModel->setHeaderData(DOWNLOADTIME, Qt::Horizontal, tr("Download time", "i.e: Estimated Time of Arrival / Time left")); + DLListModel->setHeaderData(ID, Qt::Horizontal, tr("Core-ID")); + ui.downloadList->setModel(DLListModel); + ui.downloadList->hideColumn(ID); + DLDelegate = new DLListDelegate(); + ui.downloadList->setItemDelegate(DLDelegate); + +// Why disable autoscroll ? +// With disabled autoscroll, the treeview doesn't scroll with cursor move +// ui.downloadList->setAutoScroll(false) ; + + // workaround for Qt bug, should be solved in next Qt release 4.7.0 + // http://bugreports.qt.nokia.com/browse/QTBUG-8270 + QShortcut *Shortcut = new QShortcut(QKeySequence (Qt::Key_Delete), ui.downloadList, 0, 0, Qt::WidgetShortcut); + connect(Shortcut, SIGNAL(activated()), this, SLOT( cancel ())); + + //Selection Setup + selection = ui.downloadList->selectionModel(); + + ui.downloadList->setSelectionMode(QAbstractItemView::ExtendedSelection); + + ui.downloadList->setRootIsDecorated(true); + + + /* Set header resize modes and initial section sizes Downloads TreeView*/ + QHeaderView * _header = ui.downloadList->header () ; + _header->setResizeMode (NAME, QHeaderView::Interactive); + _header->setResizeMode (SIZE, QHeaderView::Interactive); + _header->setResizeMode (COMPLETED, QHeaderView::Interactive); + _header->setResizeMode (DLSPEED, QHeaderView::Interactive); + _header->setResizeMode (PROGRESS, QHeaderView::Interactive); + _header->setResizeMode (SOURCES, QHeaderView::Interactive); + _header->setResizeMode (STATUS, QHeaderView::Interactive); + _header->setResizeMode (PRIORITY, QHeaderView::Interactive); + _header->setResizeMode (REMAINING, QHeaderView::Interactive); + + _header->resizeSection ( NAME, 170 ); + _header->resizeSection ( SIZE, 70 ); + _header->resizeSection ( COMPLETED, 75 ); + _header->resizeSection ( DLSPEED, 75 ); + _header->resizeSection ( PROGRESS, 170 ); + _header->resizeSection ( SOURCES, 90 ); + _header->resizeSection ( STATUS, 100 ); + _header->resizeSection ( PRIORITY, 100 ); + _header->resizeSection ( REMAINING, 100 ); + + // set default column and sort order for download + ui.downloadList->sortByColumn(NAME, Qt::AscendingOrder); + + // Set Upload list model + ULListModel = new QStandardItemModel(0,8); + ULListModel->setHeaderData(UNAME, Qt::Horizontal, tr("Name", "i.e: file name")); + ULListModel->setHeaderData(USIZE, Qt::Horizontal, tr("Size", "i.e: file size")); + ULListModel->setHeaderData(USERNAME, Qt::Horizontal, tr("Peer", "i.e: user name")); + ULListModel->setHeaderData(UPROGRESS, Qt::Horizontal, tr("Progress", "i.e: % uploaded")); + ULListModel->setHeaderData(ULSPEED, Qt::Horizontal, tr("Speed", "i.e: upload speed")); + ULListModel->setHeaderData(USTATUS, Qt::Horizontal, tr("Status")); + ULListModel->setHeaderData(UTRANSFERRED, Qt::Horizontal, tr("Transferred", "")); + ULListModel->setHeaderData(UHASH, Qt::Horizontal, tr("Hash", "")); + ui.uploadsList->setModel(ULListModel); + ULListModel->insertColumn(UUSERID); + ui.uploadsList->hideColumn(UUSERID); + ULDelegate = new ULListDelegate(); + ui.uploadsList->setItemDelegate(ULDelegate); + +// Why disable autoscroll ? +// With disabled autoscroll, the treeview doesn't scroll with cursor move +// ui.uploadsList->setAutoScroll(false) ; + + ui.uploadsList->setRootIsDecorated(false); + + + //Selection Setup + selectionup = ui.uploadsList->selectionModel(); + ui.uploadsList->setSelectionMode(QAbstractItemView::ExtendedSelection); + + /* Set header resize modes and initial section sizes Uploads TreeView*/ + QHeaderView * upheader = ui.uploadsList->header () ; + upheader->setResizeMode (UNAME, QHeaderView::Interactive); + upheader->setResizeMode (USIZE, QHeaderView::Interactive); + upheader->setResizeMode (UTRANSFERRED, QHeaderView::Interactive); + upheader->setResizeMode (ULSPEED, QHeaderView::Interactive); + upheader->setResizeMode (UPROGRESS, QHeaderView::Interactive); + upheader->setResizeMode (USTATUS, QHeaderView::Interactive); + upheader->setResizeMode (USERNAME, QHeaderView::Interactive); + + upheader->resizeSection ( UNAME, 190 ); + upheader->resizeSection ( USIZE, 70 ); + upheader->resizeSection ( UTRANSFERRED, 75 ); + upheader->resizeSection ( ULSPEED, 75 ); + upheader->resizeSection ( UPROGRESS, 170 ); + upheader->resizeSection ( USTATUS, 100 ); + upheader->resizeSection ( USERNAME, 120 ); + + // set default column and sort order for upload + ui.uploadsList->sortByColumn(UNAME, Qt::AscendingOrder); + + FileTransferInfoWidget *ftiw = new FileTransferInfoWidget(); + ui.fileTransferInfoWidget->setWidget(ftiw); + ui.fileTransferInfoWidget->setWidgetResizable(true); + ui.fileTransferInfoWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + ui.fileTransferInfoWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + ui.fileTransferInfoWidget->viewport()->setBackgroundRole(QPalette::NoRole); + ui.fileTransferInfoWidget->setFrameStyle(QFrame::NoFrame); + ui.fileTransferInfoWidget->setFocusPolicy(Qt::NoFocus); + + QObject::connect(ui.downloadList->selectionModel(),SIGNAL(selectionChanged (const QItemSelection&, const QItemSelection&)),this,SLOT(showFileDetails())) ; + + ui.tabWidget->addTab( new TurtleRouterStatistics(), tr("Router Statistics")) ; + + ui.tabWidget->addTab( new TurtleRouterDialog(), tr("Router Requests")) ; + + +// TurtleRouterDialog *trdl = new TurtleRouterDialog(); +// ui.tunnelInfoWidget->setWidget(trdl); +// ui.tunnelInfoWidget->setWidgetResizable(true); +// ui.tunnelInfoWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); +// ui.tunnelInfoWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); +// ui.tunnelInfoWidget->viewport()->setBackgroundRole(QPalette::NoRole); +// ui.tunnelInfoWidget->setFrameStyle(QFrame::NoFrame); +// ui.tunnelInfoWidget->setFocusPolicy(Qt::NoFocus); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif + + QObject::connect(ui._showCacheTransfers_CB,SIGNAL(toggled(bool)),this,SLOT(insertTransfers())) ; + + // Actions. Only need to be defined once. + pauseAct = new QAction(QIcon(IMAGE_PAUSE), tr("Pause"), this); + connect(pauseAct, SIGNAL(triggered()), this, SLOT(pauseFileTransfer())); + + resumeAct = new QAction(QIcon(IMAGE_RESUME), tr("Resume"), this); + connect(resumeAct, SIGNAL(triggered()), this, SLOT(resumeFileTransfer())); + + forceCheckAct = new QAction(QIcon(IMAGE_CANCEL), tr( "Force Check" ), this ); + connect( forceCheckAct , SIGNAL( triggered() ), this, SLOT( forceCheck() ) ); + + cancelAct = new QAction(QIcon(IMAGE_CANCEL), tr( "Cancel" ), this ); + connect( cancelAct , SIGNAL( triggered() ), this, SLOT( cancel() ) ); + + openfolderAct = new QAction(QIcon(IMAGE_OPENFOLDER), tr("Open Folder"), this); + connect(openfolderAct, SIGNAL(triggered()), this, SLOT(openFolderTransfer())); + + openfileAct = new QAction(QIcon(IMAGE_OPENFILE), tr("Open File"), this); + connect(openfileAct, SIGNAL(triggered()), this, SLOT(openTransfer())); + + previewfileAct = new QAction(QIcon(IMAGE_PREVIEW), tr("Preview File"), this); + connect(previewfileAct, SIGNAL(triggered()), this, SLOT(previewTransfer())); + + detailsfileAct = new QAction(QIcon(IMAGE_INFO), tr("Details..."), this); + connect(detailsfileAct, SIGNAL(triggered()), this, SLOT(showDetailsDialog())); + + clearcompletedAct = new QAction(QIcon(IMAGE_CLEARCOMPLETED), tr( "Clear Completed" ), this ); + connect( clearcompletedAct , SIGNAL( triggered() ), this, SLOT( clearcompleted() ) ); + + + copylinkAct = new QAction(QIcon(IMAGE_COPYLINK), tr( "Copy RetroShare Link" ), this ); + connect( copylinkAct , SIGNAL( triggered() ), this, SLOT( copyLink() ) ); + pastelinkAct = new QAction(QIcon(IMAGE_PASTELINK), tr( "Paste RetroShare Link" ), this ); + connect( pastelinkAct , SIGNAL( triggered() ), this, SLOT( pasteLink() ) ); + queueDownAct = new QAction(QIcon(":/images/go-down.png"), tr("Down"), this); + connect(queueDownAct, SIGNAL(triggered()), this, SLOT(priorityQueueDown())); + queueUpAct = new QAction(QIcon(":/images/go-up.png"), tr("Up"), this); + connect(queueUpAct, SIGNAL(triggered()), this, SLOT(priorityQueueUp())); + queueTopAct = new QAction(QIcon(":/images/go-top.png"), tr("Top"), this); + connect(queueTopAct, SIGNAL(triggered()), this, SLOT(priorityQueueTop())); + queueBottomAct = new QAction(QIcon(":/images/go-bottom.png"), tr("Bottom"), this); + connect(queueBottomAct, SIGNAL(triggered()), this, SLOT(priorityQueueBottom())); + chunkStreamingAct = new QAction(QIcon(IMAGE_PRIORITYAUTO), tr("Streaming"), this); + connect(chunkStreamingAct, SIGNAL(triggered()), this, SLOT(chunkStreaming())); + prioritySlowAct = new QAction(QIcon(IMAGE_PRIORITYLOW), tr("Slower"), this); + connect(prioritySlowAct, SIGNAL(triggered()), this, SLOT(speedSlow())); + priorityMediumAct = new QAction(QIcon(IMAGE_PRIORITYNORMAL), tr("Average"), this); + connect(priorityMediumAct, SIGNAL(triggered()), this, SLOT(speedAverage())); + priorityFastAct = new QAction(QIcon(IMAGE_PRIORITYHIGH), tr("Faster"), this); + connect(priorityFastAct, SIGNAL(triggered()), this, SLOT(speedFast())); + chunkRandomAct = new QAction(QIcon(IMAGE_PRIORITYAUTO), tr("Random"), this); + connect(chunkRandomAct, SIGNAL(triggered()), this, SLOT(chunkRandom())); + playAct = new QAction(QIcon(IMAGE_PLAY), tr( "Play" ), this ); + connect( playAct , SIGNAL( triggered() ), this, SLOT( openTransfer() ) ); + + // load settings + processSettings(true); +} + +TransfersDialog::~TransfersDialog() +{ + // save settings + processSettings(false); +} + +void TransfersDialog::processSettings(bool bLoad) +{ + m_bProcessSettings = true; + + QHeaderView *DLHeader = ui.downloadList->header () ; + QHeaderView *ULHeader = ui.uploadsList->header () ; + + Settings->beginGroup(QString("TransfersDialog")); + + if (bLoad) { + // load settings + + // state of checks + ui._showCacheTransfers_CB->setChecked(Settings->value("showCacheTransfers", false).toBool()); + + // state of the lists + DLHeader->restoreState(Settings->value("downloadList").toByteArray()); + ULHeader->restoreState(Settings->value("uploadList").toByteArray()); + + // state of splitter + ui.splitter->restoreState(Settings->value("Splitter").toByteArray()); + } else { + // save settings + + // state of checks + Settings->setValue("showCacheTransfers", ui._showCacheTransfers_CB->isChecked()); + + // state of the lists + Settings->setValue("downloadList", DLHeader->saveState()); + Settings->setValue("uploadList", ULHeader->saveState()); + + // state of splitter + Settings->setValue("Splitter", ui.splitter->saveState()); + } + + Settings->endGroup(); + m_bProcessSettings = false; +} + +// replaced by shortcut +//void TransfersDialog::keyPressEvent(QKeyEvent *e) +//{ +// if(e->key() == Qt::Key_Delete) +// { +// cancel() ; +// e->accept() ; +// } +// else +// RsAutoUpdatePage::keyPressEvent(e) ; +//} + +void TransfersDialog::downloadListCostumPopupMenu( QPoint point ) +{ + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + + bool single = (items.size() == 1) ; + + /* check which item is selected + * - if it is completed - play should appear in menu + */ + std::cerr << "TransfersDialog::downloadListCostumPopupMenu()" << std::endl; + + FileInfo info; + + for (it = items.begin(); it != items.end(); it ++) { + if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) continue; + break; + } + + bool addPlayOption = false; + bool addOpenFileOption = false; + + if (info.downloadStatus == FT_STATE_COMPLETE) + { + std::cerr << "Add Play Option" << std::endl; + + addOpenFileOption = true; + + size_t pos = info.fname.find_last_of('.'); + + /* check if the file is a media file */ + if(pos != std::string::npos && misc::isPreviewable(info.fname.substr(pos + 1).c_str())) + addPlayOption = true; + } + + QMenu priorityQueueMenu(tr("Move in Queue..."), this); + priorityQueueMenu.setIcon(QIcon(IMAGE_PRIORITY)); + priorityQueueMenu.addAction(queueTopAct); + priorityQueueMenu.addAction(queueUpAct); + priorityQueueMenu.addAction(queueDownAct); + priorityQueueMenu.addAction(queueBottomAct); + + QMenu prioritySpeedMenu(tr("Priority (Speed)..."), this); + prioritySpeedMenu.setIcon(QIcon(IMAGE_PRIORITY)); + prioritySpeedMenu.addAction(prioritySlowAct); + prioritySpeedMenu.addAction(priorityMediumAct); + prioritySpeedMenu.addAction(priorityFastAct); + + QMenu chunkMenu(tr("Chunk strategy"), this); + chunkMenu.setIcon(QIcon(IMAGE_PRIORITY)); + chunkMenu.addAction(chunkStreamingAct); + chunkMenu.addAction(chunkRandomAct); + + QMenu contextMnu( this ); + + if (addPlayOption) + contextMnu.addAction(playAct); + + contextMnu.addSeparator(); + + if(!items.empty()) + { + bool all_paused = true ; + bool all_downld = true ; + bool all_downloading = true ; + bool all_queued = true ; + + QModelIndexList lst = ui.downloadList->selectionModel ()->selectedIndexes (); + + for (int i = 0; i < lst.count (); i++) + { + if ( lst[i].column() == 0 && info.downloadStatus == FT_STATE_PAUSED ) + all_downld = false ; + if ( lst[i].column() == 0 && info.downloadStatus == FT_STATE_DOWNLOADING ) + all_paused = false ; + + if ( lst[i].column() == 0) + { + if(info.downloadStatus == FT_STATE_QUEUED) + all_downloading = false ; + else + all_queued = false ; + } + } + + if(all_downloading) + contextMnu.addMenu(&prioritySpeedMenu); + else if(all_queued) + contextMnu.addMenu(&priorityQueueMenu) ; + + if(all_downloading) + contextMnu.addMenu( &chunkMenu); + + if(!all_paused) + contextMnu.addAction( pauseAct); + if(!all_downld) + contextMnu.addAction( resumeAct); + + if(single) + { + if(info.downloadStatus == FT_STATE_PAUSED) + contextMnu.addAction( resumeAct); + else if(info.downloadStatus != FT_STATE_COMPLETE) + contextMnu.addAction( pauseAct); + } + + if(info.downloadStatus != FT_STATE_COMPLETE) + { + contextMnu.addAction( forceCheckAct); + contextMnu.addAction( cancelAct); + } + + contextMnu.addSeparator(); + } + + if(single) + { + if (addOpenFileOption) + contextMnu.addAction( openfileAct); + +#ifndef WIN32 + contextMnu.addAction( previewfileAct); +#endif + contextMnu.addAction( openfolderAct); + contextMnu.addAction( detailsfileAct); + contextMnu.addSeparator(); + } + + contextMnu.addAction( clearcompletedAct); + contextMnu.addSeparator(); + + if(!items.empty()) + contextMnu.addAction( copylinkAct); + + if(!RSLinkClipboard::empty(RetroShareLink::TYPE_FILE)) { + pastelinkAct->setEnabled(true); + } else { + pastelinkAct->setDisabled(true); + } + contextMnu.addAction( pastelinkAct); + + contextMnu.addSeparator(); + + contextMnu.exec(QCursor::pos()); +} + +int TransfersDialog::addItem(const QString&, const QString& name, const QString& coreID, qlonglong fileSize, const FileProgressInfo& pinfo, double dlspeed, + const QString& sources, const QString& status, const QString& priority, qlonglong completed, qlonglong remaining, qlonglong downloadtime) +{ + int rowCount = DLListModel->rowCount(); + int row ; + for(row=0;rowitem(row,ID)->data(Qt::DisplayRole).toString() == coreID) + break ; + + if(row >= rowCount ) + { + row = rowCount; + DLListModel->insertRow(row); + + // change progress column to own class for sorting + DLListModel->setItem(row, PROGRESS, new ProgressItem (NULL)); + } + + DLListModel->setData(DLListModel->index(row, NAME), QVariant(name)); + DLListModel->setData(DLListModel->index(row, SIZE), QVariant((qlonglong)fileSize)); + DLListModel->setData(DLListModel->index(row, COMPLETED), QVariant((qlonglong)completed)); + DLListModel->setData(DLListModel->index(row, DLSPEED), QVariant((double)dlspeed)); + DLListModel->setData(DLListModel->index(row, PROGRESS), QVariant::fromValue(pinfo)); + DLListModel->setData(DLListModel->index(row, SOURCES), QVariant((QString)sources)); + DLListModel->setData(DLListModel->index(row, STATUS), QVariant((QString)status)); + DLListModel->setData(DLListModel->index(row, PRIORITY), QVariant((QString)priority)); + DLListModel->setData(DLListModel->index(row, REMAINING), QVariant((qlonglong)remaining)); + DLListModel->setData(DLListModel->index(row, DOWNLOADTIME), QVariant((qlonglong)downloadtime)); + DLListModel->setData(DLListModel->index(row, ID), QVariant((QString)coreID)); + + QString ext = QFileInfo(name).suffix(); + DLListModel->setData(DLListModel->index(row,NAME), getIconFromExtension(ext), Qt::DecorationRole); + + return row ; +} + +QIcon TransfersDialog::getIconFromExtension(QString ext) +{ + ext = ext.toLower(); + if (ext == "jpg" || ext == "jpeg" || ext == "tif" || ext == "tiff" || ext == "png" || ext == "gif" || ext == "bmp" || ext == "ico" || ext == "svg") + return QIcon(QString::fromUtf8(":/images/FileTypePicture.png")) ; + else if (ext == "avi" || ext == "mpg" || ext == "mpeg" || ext == "wmv" || ext == "divx" || ext == "ts" + || ext == "mkv" || ext == "mp4" || ext == "flv" || ext == "mov" || ext == "asf" || ext == "xvid" + || ext == "vob" || ext == "qt" || ext == "rm" || ext == "3gp" || ext == "ogm") + return QIcon(QString::fromUtf8(":/images/FileTypeVideo.png")) ; + else if (ext == "ogg" || ext == "mp3" || ext == "mp1" || ext == "mp2" || ext == "wav" || ext == "wma" || ext == "m4a" || ext == "flac") + return QIcon(QString::fromUtf8(":/images/FileTypeAudio.png")) ; + else if (ext == "tar" || ext == "bz2" || ext == "zip" || ext == "gz" || ext == "7z" || ext == "msi" + || ext == "rar" || ext == "rpm" || ext == "ace" || ext == "jar" || ext == "tgz" || ext == "lha" + || ext == "cab" || ext == "cbz"|| ext == "cbr" || ext == "alz" || ext == "sit" || ext == "arj" || ext == "deb") + return QIcon(QString::fromUtf8(":/images/FileTypeArchive.png")) ; + else if (ext == "app" || ext == "bat" || ext == "cgi" || ext == "com" + || ext == "exe" || ext == "js" || ext == "pif" + || ext == "py" || ext == "pl" || ext == "sh" || ext == "vb" || ext == "ws") + return QIcon(QString::fromUtf8(":/images/FileTypeProgram.png")) ; + else if (ext == "iso" || ext == "nrg" || ext == "mdf" || ext == "img" || ext == "dmg" || ext == "bin" ) + return QIcon(QString::fromUtf8(":/images/FileTypeCDImage.png")) ; + else if (ext == "txt" || ext == "cpp" || ext == "c" || ext == "h") + return QIcon(QString::fromUtf8(":/images/FileTypeDocument.png")) ; + else if (ext == "doc" || ext == "rtf" || ext == "sxw" || ext == "xls" || ext == "pps" || ext == "xml" + || ext == "sxc" || ext == "odt" || ext == "ods" || ext == "dot" || ext == "ppt" || ext == "css" ) + return QIcon(QString::fromUtf8(":/images/FileTypeDocument.png")) ; + else if (ext == "html" || ext == "htm" || ext == "php") + return QIcon(QString::fromUtf8(":/images/FileTypeDocument.png")) ; + else + return QIcon(QString::fromUtf8(":/images/FileTypeAny.png")) ; +} + +int TransfersDialog::addPeerToItem(int row, const QString& name, const QString& coreID, double dlspeed, uint32_t status, const FileProgressInfo& peerInfo) +{ + QStandardItem *dlItem = DLListModel->item(row); + if (!dlItem) return -1; + + //try to find the item + int childRow = -1; + int count = 0; + QStandardItem* childId=NULL ; + + for(count=0; (childId = dlItem->child(count, ID)) != NULL;++count) + if (childId->data(Qt::DisplayRole).toString() == coreID) + { + childRow = count; + break; + } + + + QStandardItem *si1 = NULL,*si7=NULL; + + if (childRow == -1) + { + //set this false if you want to expand on double click + dlItem->setEditable(false); + + QHeaderView *header = ui.downloadList->header (); + + QStandardItem *i1 = new QStandardItem(); + QStandardItem *i2 = new SortByNameItem(header); + QStandardItem *i3 = new SortByNameItem(header); + QStandardItem *i4 = new SortByNameItem(header); + QStandardItem *i5 = new ProgressItem(header); + QStandardItem *i6 = new SortByNameItem(header); + QStandardItem *i7 = new SortByNameItem(header); + QStandardItem *i8 = new SortByNameItem(header); + QStandardItem *i9 = new SortByNameItem(header); + QStandardItem *i10 = new SortByNameItem(header); + QStandardItem *i11 = new SortByNameItem(header); + + si1 = i1 ; + si7 = i7 ; + + QList items; + i1->setData(QVariant((QString)" "+name), Qt::DisplayRole); + i2->setData(QVariant(QString()), Qt::DisplayRole); + i3->setData(QVariant(QString()), Qt::DisplayRole); + i4->setData(QVariant((double)dlspeed), Qt::DisplayRole); + i5->setData(QVariant::fromValue(peerInfo), Qt::DisplayRole); + i6->setData(QVariant(QString()), Qt::DisplayRole); + + i8->setData(QVariant(QString()), Qt::DisplayRole); // blank field for priority + i9->setData(QVariant(QString()), Qt::DisplayRole); + i10->setData(QVariant(QString()), Qt::DisplayRole); + i11->setData(QVariant((QString)coreID), Qt::DisplayRole); + + items.append(i1); + items.append(i2); + items.append(i3); + items.append(i4); + items.append(i5); + items.append(i6); + items.append(i7); + items.append(i8); + items.append(i9); + items.append(i10); + items.append(i11); + dlItem->appendRow(items); + + childRow = dlItem->rowCount()-1 ; + } + else + { + //just update the child (peer) + dlItem->child(childRow, DLSPEED)->setData(QVariant((double)dlspeed), Qt::DisplayRole); + dlItem->child(childRow, PROGRESS)->setData(QVariant::fromValue(peerInfo), Qt::DisplayRole); + + si1 = dlItem->child(childRow,NAME) ; + si7 = dlItem->child(childRow, STATUS) ; + } + + QString sstatus; + switch (status) + { + case FT_STATE_FAILED: si7->setData(QVariant(tr("Failed"))) ; + si1->setData(QIcon(QString::fromUtf8(":/images/Client1.png")), Qt::DecorationRole); + break ; + + case FT_STATE_OKAY: si7->setData(QVariant(tr("Okay"))); + si1->setData(QIcon(QString::fromUtf8(":/images/Client2.png")), Qt::DecorationRole); + break ; + + case FT_STATE_WAITING: si7->setData(QVariant(tr(""))); + si1->setData(QIcon(QString::fromUtf8(":/images/Client3.png")), Qt::DecorationRole); + break ; + + case FT_STATE_DOWNLOADING: si7->setData(QVariant(tr("Transferring"))); + si1->setData(QIcon(QString::fromUtf8(":/images/Client0.png")), Qt::DecorationRole); + break ; + + case FT_STATE_COMPLETE: si7->setData(QVariant(tr("Complete"))); + si1->setData(QIcon(QString::fromUtf8(":/images/Client0.png")), Qt::DecorationRole); + break ; + + default: si7->setData(QVariant(tr(""))); + break ; + si1->setData(QIcon(QString::fromUtf8(":/images/Client4.png")), Qt::DecorationRole); + } + + + return childRow; +} + + +int TransfersDialog::addUploadItem( const QString&, const QString& name, const QString& coreID, + qlonglong fileSize, const FileProgressInfo& pinfo, double dlspeed, + const QString& source, const QString& peer_id, const QString& status, qlonglong completed, qlonglong) +{ + // Find items does not work reliably, because it (apparently) needs Qt to flush pending events to work, so we can't call it + // on a table that was just filled in. + // + int row ; + for(row=0;rowrowCount();++row) + if(ULListModel->item(row,UUSERID)->data(Qt::EditRole).toString() == peer_id && ULListModel->item(row,UHASH)->data(Qt::EditRole).toString() == coreID) + break ; + + if(row >= ULListModel->rowCount() ) + { + row = ULListModel->rowCount(); + ULListModel->insertRow(row); + + // change progress column to own class for sorting + ULListModel->setItem(row, UPROGRESS, new ProgressItem(NULL)); + } + + ULListModel->setData(ULListModel->index(row, UNAME), QVariant((QString)" "+name), Qt::DisplayRole); + ULListModel->setData(ULListModel->index(row, USIZE), QVariant((qlonglong)fileSize)); + ULListModel->setData(ULListModel->index(row, UTRANSFERRED), QVariant((qlonglong)completed)); + ULListModel->setData(ULListModel->index(row, ULSPEED), QVariant((double)dlspeed)); + ULListModel->setData(ULListModel->index(row, UPROGRESS), QVariant::fromValue(pinfo)); + ULListModel->setData(ULListModel->index(row, USTATUS), QVariant((QString)status)); + ULListModel->setData(ULListModel->index(row, USERNAME), QVariant((QString)source)); + ULListModel->setData(ULListModel->index(row, UHASH), QVariant((QString)coreID)); + ULListModel->setData(ULListModel->index(row, UUSERID), QVariant((QString)peer_id)); + + QString ext = QFileInfo(name).suffix(); + ULListModel->setData(ULListModel->index(row,UNAME), getIconFromExtension(ext), Qt::DecorationRole); + + return row; +} + + +//void TransfersDialog::delItem(int row) +//{ +// DLListModel->removeRow(row, QModelIndex()); +//} + +//void TransfersDialog::delUploadItem(int row) +//{ +// ULListModel->removeRow(row, QModelIndex()); +//} + + /* get the list of Transfers from the RsIface. **/ +void TransfersDialog::updateDisplay() +{ + insertTransfers(); + updateDetailsDialog (); +} + +static void QListDelete (const QList &List) +{ + qDeleteAll (List); +} + +void TransfersDialog::insertTransfers() +{ + /* disable for performance issues, enable after insert all transfers */ + ui.downloadList->setSortingEnabled(false); + + /* get the download lists */ + std::list downHashes; + rsFiles->FileDownloads(downHashes); + +// std::list dwlDetails; +// rsFiles->getDwlDetails(dwlDetails); + + bool showCacheTransfers = ui._showCacheTransfers_CB->isChecked(); + + /* get online peers only once */ + std::list onlineIds; + rsPeers->getOnlineList(onlineIds); + + /* get also only once */ + std::map versions; + bool retv = rsDisc->getDiscVersions(versions); + + std::set used_hashes ; + + // clear all source peers. + + std::list::iterator it; + for (it = downHashes.begin(); it != downHashes.end(); it++) + { + FileInfo info; + if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) { + //if file transfer is a cache file index file, don't show it + continue; + } + + if((info.flags & RS_FILE_HINTS_CACHE) && !showCacheTransfers) + continue; + + QString fileName = QString::fromUtf8(info.fname.c_str()); + QString fileHash = QString::fromStdString(info.hash); + qlonglong fileSize = info.size; + double fileDlspeed = (info.downloadStatus==FT_STATE_DOWNLOADING)?(info.tfRate * 1024.0):0.0; + + /* get the sources (number of online peers) */ + int active = 0; + std::list::iterator pit; + for (pit = info.peers.begin(); pit != info.peers.end(); pit++) + if(pit->tfRate > 0 && info.downloadStatus==FT_STATE_DOWNLOADING) + active++; + + QString sources = QString("%1 (%2)").arg(active).arg(info.peers.size()); + + QString status; + switch (info.downloadStatus) { + case FT_STATE_FAILED: status = tr("Failed"); break; + case FT_STATE_OKAY: status = tr("Okay"); break; + case FT_STATE_WAITING: status = tr("Waiting"); break; + case FT_STATE_DOWNLOADING: status = tr("Downloading"); break; + case FT_STATE_COMPLETE: status = tr("Complete"); break; + case FT_STATE_QUEUED: status = tr("Queued"); break; + case FT_STATE_PAUSED: status = tr("Paused"); break; + case FT_STATE_CHECKING_HASH:status = tr("Checking..."); break; + default: status = tr("Unknown"); break; + } + + QString priority; + + if(info.downloadStatus == FT_STATE_QUEUED) + priority = QString::number(info.queue_position) ; + else + switch (info.priority) + { + case SPEED_LOW: priority = tr("Slower");break; + case SPEED_NORMAL: priority = tr("Average");break; + case SPEED_HIGH: priority = tr("Faster");break; + default: priority = tr("Average");break; + } + + qlonglong completed = info.transfered; + qlonglong remaining = info.size - info.transfered; + qlonglong downloadtime = (info.size - info.transfered) / (info.tfRate * 1024.0); + + FileChunksInfo fcinfo ; + if(!rsFiles->FileDownloadChunksDetails(*it,fcinfo)) + continue ; + + FileProgressInfo pinfo ; + pinfo.cmap = fcinfo.chunks ; + pinfo.type = FileProgressInfo::DOWNLOAD_LINE ; + pinfo.progress = (info.size==0)?0:(completed*100.0/info.size) ; + pinfo.nb_chunks = pinfo.cmap._map.empty()?0:fcinfo.chunks.size() ; + + for(uint32_t i=0;i::iterator vit; + + std::set used_rows ; + + if(info.downloadStatus != FT_STATE_COMPLETE) + for (pit = info.peers.begin(); pit != info.peers.end(); pit++) + { + QString peerName = getPeerName(pit->peerId); + //unique combination: fileHash + peerId, variant: hash + peerName (too long) + QString hashFileAndPeerId = fileHash + QString::fromStdString(pit->peerId); + QString version; + if (retv && versions.end() != (vit = versions.find(pit->peerId))) { + version = tr("version: ") + QString::fromStdString(vit->second); + } + + double peerDlspeed = 0; + if ((uint32_t)pit->status == FT_STATE_DOWNLOADING && info.downloadStatus != FT_STATE_PAUSED && info.downloadStatus != FT_STATE_COMPLETE) + peerDlspeed = pit->tfRate * 1024.0; + + FileProgressInfo peerpinfo ; + peerpinfo.cmap = fcinfo.compressed_peer_availability_maps[pit->peerId]; + peerpinfo.type = FileProgressInfo::DOWNLOAD_SOURCE ; + peerpinfo.progress = 0.0 ; // we don't display completion for sources. + peerpinfo.nb_chunks = peerpinfo.cmap._map.empty()?0:fcinfo.chunks.size(); + + int row_id = addPeerToItem(addedRow, peerName, hashFileAndPeerId, peerDlspeed, pit->status, peerpinfo); + + used_rows.insert(row_id) ; + } + + QStandardItem *dlItem = DLListModel->item(addedRow); + + // This is not optimal, but we deal with a small number of elements. The reverse order is really important, + // because rows after the deleted rows change positions ! + // + for(int r=dlItem->rowCount()-1;r>=0;--r) + if(used_rows.find(r) == used_rows.end()) + QListDelete (dlItem->takeRow(r)) ; + } + + // remove hashes that where not shown + //first clean the model in case some files are not download anymore + //remove items that are not fiends anymore + int removeIndex = 0; + int rowCount = DLListModel->rowCount(); + while (removeIndex < rowCount) + { + std::string hash = DLListModel->item(removeIndex, ID)->data(Qt::DisplayRole).toString().toStdString(); + + if(used_hashes.find(hash) == used_hashes.end()) { + QListDelete (DLListModel->takeRow(removeIndex)); + rowCount = DLListModel->rowCount(); + } else + removeIndex++; + } + + ui.downloadList->setSortingEnabled(true); + + ui.uploadsList->setSortingEnabled(false); + + // Now show upload hashes + // + std::list upHashes; + rsFiles->FileUploads(upHashes); + + std::string ownId = rsPeers->getOwnId(); + + used_hashes.clear() ; + + for(it = upHashes.begin(); it != upHashes.end(); it++) + { + FileInfo info; + if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_UPLOAD, info)) + continue; + + if((info.flags & RS_FILE_HINTS_CACHE) && showCacheTransfers) + continue ; + + std::list::iterator pit; + for(pit = info.peers.begin(); pit != info.peers.end(); pit++) + { + if (pit->peerId == ownId) //don't display transfer to ourselves + continue ; + + QString fileHash = QString::fromStdString(info.hash); + QString fileName = QString::fromUtf8(info.fname.c_str()); + QString source = getPeerName(pit->peerId); + + QString status; + switch(pit->status) + { + case FT_STATE_FAILED: status = tr("Failed"); break; + case FT_STATE_OKAY: status = tr("Okay"); break; + case FT_STATE_WAITING: status = tr("Waiting"); break; + case FT_STATE_DOWNLOADING: status = tr("Uploading"); break; + case FT_STATE_COMPLETE: status = tr("Complete"); break; + default: status = tr("Complete"); break; + + } + + FileProgressInfo pinfo ; + + if(!rsFiles->FileUploadChunksDetails(*it,pit->peerId,pinfo.cmap) ) + continue ; + + double dlspeed = pit->tfRate * 1024.0; + qlonglong fileSize = info.size; + qlonglong completed = pit->transfered; + double progress = (info.size > 0)?(pit->transfered * 100.0 / info.size):0.0; + qlonglong remaining = (info.size - pit->transfered) / (pit->tfRate * 1024.0); + + // Estimate the completion. We need something more accurate, meaning that we need to + // transmit the completion info. + // + uint32_t chunk_size = 1024*1024 ; + uint32_t nb_chunks = (uint32_t)(info.size / (uint64_t)(chunk_size) ) ; + if((info.size % (uint64_t)chunk_size) != 0) + ++nb_chunks ; + + uint32_t filled_chunks = pinfo.cmap.filledChunks(nb_chunks) ; + pinfo.type = FileProgressInfo::UPLOAD_LINE ; + pinfo.nb_chunks = pinfo.cmap._map.empty()?0:nb_chunks ; + + if(filled_chunks > 0 && nb_chunks > 0) + { + pinfo.progress = filled_chunks*100.0/nb_chunks ; + completed = std::min(info.size,((uint64_t)filled_chunks)*chunk_size) ; // we use min, because the last chunk might be smaller than chunk_size. + } + else + { + completed = pit->transfered % chunk_size ; // use the position with respect to last request. + pinfo.progress = (info.size>0)?((pit->transfered % chunk_size)*100.0/info.size):0 ; + } + + addUploadItem("", fileName, fileHash, fileSize, pinfo, dlspeed, source,QString::fromStdString(pit->peerId), status, completed, remaining); + + used_hashes.insert(fileHash.toStdString() + pit->peerId) ; + } + } + + // remove hashes that where not shown + //first clean the model in case some files are not download anymore + //remove items that are not fiends anymore + removeIndex = 0; + rowCount = ULListModel->rowCount(); + while (removeIndex < rowCount) + { + std::string hash = ULListModel->item(removeIndex, UHASH)->data(Qt::EditRole).toString().toStdString(); + std::string peer = ULListModel->item(removeIndex, UUSERID)->data(Qt::EditRole).toString().toStdString(); + + if(used_hashes.find(hash + peer) == used_hashes.end()) { + QListDelete (ULListModel->takeRow(removeIndex)); + rowCount = ULListModel->rowCount(); + } else + removeIndex++; + } + + ui.uploadsList->setSortingEnabled(true); +} + +QString TransfersDialog::getPeerName(const std::string& id) const +{ + QString res = QString::fromStdString(rsPeers->getPeerName(id)) ; + + // This is because turtle tunnels have no name (I didn't want to bother with + // connect mgr). In such a case their id can suitably hold for a name. + // + if(res == "") + return QString::fromStdString(id) ; + else + return res ; +} + +void TransfersDialog::forceCheck() +{ + if (!controlTransferFile(RS_FILE_CTRL_FORCE_CHECK)) + std::cerr << "resumeFileTransfer(): can't force check file transfer" << std::endl; +} + +void TransfersDialog::cancel() +{ + bool first = true; + + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + for (it = items.begin(); it != items.end(); it ++) { + if (first) { + first = false; + QString queryWrn2; + queryWrn2.clear(); + queryWrn2.append(tr("Are you sure that you want to cancel and delete these files?")); + + if ((QMessageBox::question(this, tr("RetroShare"),queryWrn2,QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes)) == QMessageBox::No) { + break; + } + } + + rsFiles->FileCancel(*it); + } +} + +//void TransfersDialog::handleDownloadRequest(const QString& url) +//{ +// RetroShareLink link(url); +// +// if (!link.valid ()) +// { +// QMessageBox::critical(NULL,"Link error","This link could not be parsed. This is a bug. Please contact the developers.") ; +// return; +// } +// +// QVector linkList; +// analyzer.getFileInformation (linkList); +// +// std::list srcIds; +// +// for (int i = 0, n = linkList.size (); i < n; ++i) +// { +// const RetroShareLinkData& linkData = linkList[i]; +// +// rsFiles->FileRequest (linkData.getName ().toStdString (), linkData.getHash ().toStdString (), +// linkData.getSize ().toInt (), "", 0, srcIds); +// } +//} + +void TransfersDialog::copyLink () +{ + std::vector links ; + + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + + for (it = items.begin(); it != items.end(); it ++) { + FileInfo info; + if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) { + continue; + } + + RetroShareLink link; + if (link.createFile(QString::fromUtf8(info.fname.c_str()), info.size, QString::fromStdString(info.hash))) { + links.push_back(link) ; + } + } + + RSLinkClipboard::copyLinks(links) ; +} + +void TransfersDialog::showDetailsDialog() +{ + if (detailsdlg == NULL) { + // create window + detailsdlg = new DetailsDialog (); + } + + updateDetailsDialog (); + + detailsdlg->show(); +} + +void TransfersDialog::updateDetailsDialog() +{ + if (detailsdlg == NULL) { + return; + } + + std::string file_hash ; + QString fhash; + QString fsize; + QString fname; + QString fstatus; + QString fpriority; + QString fsources; + + qulonglong filesize = 0; + double fdatarate = 0; + qulonglong fcompleted = 0; + qulonglong fremaining = 0; + + qulonglong fdownloadtime = 0; + + std::set rows; + std::set::iterator it; + getSelectedItems(NULL, &rows); + + if (rows.size()) { + int row = *rows.begin(); + + fhash = getID(row, DLListModel); + fsize = getFileSize(row, DLListModel); + fname = getFileName(row, DLListModel); + fstatus = getStatus(row, DLListModel); + fpriority = getPriority(row, DLListModel); + fsources = getSources(row, DLListModel); + + filesize = getFileSize(row, DLListModel); + fdatarate = getSpeed(row, DLListModel); + fcompleted = getTransfered(row, DLListModel); + fremaining = getRemainingTime(row, DLListModel); + + fdownloadtime = getDownloadTime(row, DLListModel); + +// maybe show all links in retroshare link(s) Tab +// int nb_select = 0 ; +// +// for(int i = 0; i <= DLListModel->rowCount(); i++) +// if(selection->isRowSelected(i, QModelIndex())) +// { +// file_hash = getID(i, DLListModel).toStdString(); +// ++nb_select ; +// } + + file_hash = getID(row, DLListModel).toStdString(); + } + + detailsdlg->setFileHash(file_hash); + + // Set Details.. Window Title + detailsdlg->setWindowTitle(tr("Details:") + fname); + + // General GroupBox + detailsdlg->setHash(fhash); + detailsdlg->setFileName(fname); + detailsdlg->setSize(filesize); + detailsdlg->setStatus(fstatus); + detailsdlg->setPriority(fpriority); + detailsdlg->setType(QFileInfo(fname).suffix()); + + // Transfer GroupBox + detailsdlg->setSources(fsources); + detailsdlg->setDatarate(fdatarate); + if (fname.isEmpty()) { + detailsdlg->setCompleted(misc::friendlyUnit(-1)); + detailsdlg->setRemaining(misc::friendlyUnit(-1)); + } else { + detailsdlg->setCompleted(misc::friendlyUnit(fcompleted)); + detailsdlg->setRemaining(misc::friendlyUnit(fremaining)); + } + + //Date GroupBox + if (fname.isEmpty()) { + detailsdlg->setDownloadtime(misc::userFriendlyDuration(-1)); + } else { + detailsdlg->setDownloadtime(misc::userFriendlyDuration(fdownloadtime)); + } + + // retroshare link(s) Tab + if (fname.isEmpty()) { + detailsdlg->setLink(""); + } else { + RetroShareLink link; + if (link.createFile(fname, filesize, fhash)) { + detailsdlg->setLink(link.toString()); + } else { + detailsdlg->setLink(""); + } + } + + FileChunksInfo info ; + if (fhash.isEmpty() == false && rsFiles->FileDownloadChunksDetails(fhash.toStdString(), info)) { + detailsdlg->setChunkSize(info.chunk_size); + detailsdlg->setNumberOfChunks(info.chunks.size()); + } else { + detailsdlg->setChunkSize(0); + detailsdlg->setNumberOfChunks(0); + } +} + +void TransfersDialog::pasteLink() +{ + RSLinkClipboard::process(RetroShareLink::TYPE_FILE, RSLINK_PROCESS_NOTIFY_ERROR); +} + +void TransfersDialog::getSelectedItems(std::set *ids, std::set *rows) +{ + if (ids == NULL && rows == NULL) { + return; + } + + if (ids) ids->clear(); + if (rows) rows->clear(); + + int i, imax = DLListModel->rowCount(); + for (i = 0; i < imax; i++) { + bool isParentSelected = false; + bool isChildSelected = false; + + QStandardItem *parent = DLListModel->item(i); + if (!parent) continue; + QModelIndex pindex = parent->index(); + if (selection->isSelected(pindex)) { + isParentSelected = true; + } else { + int j, jmax = parent->rowCount(); + for (j = 0; j < jmax && !isChildSelected; j++) { + QStandardItem *child = parent->child(j); + if (!child) continue; + QModelIndex cindex = child->index(); + if (selection->isSelected(cindex)) { + isChildSelected = true; + } + } + } + + /* if transfered file or it's peers are selected control it*/ + if (isParentSelected || isChildSelected) { + if (ids) { + QStandardItem *id = DLListModel->item(i, ID); + ids->insert(id->data(Qt::DisplayRole).toString().toStdString()); + } + if (rows) { + rows->insert(i); + } + } + } +} + +bool TransfersDialog::controlTransferFile(uint32_t flags) +{ + bool result = true; + + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + for (it = items.begin(); it != items.end(); it ++) { + result &= rsFiles->FileControl(*it, flags); + } + + return result; +} + +void TransfersDialog::pauseFileTransfer() +{ + if (!controlTransferFile(RS_FILE_CTRL_PAUSE)) + { + std::cerr << "pauseFileTransfer(): can't pause file transfer" << std::endl; + } +} + +void TransfersDialog::resumeFileTransfer() +{ + if (!controlTransferFile(RS_FILE_CTRL_START)) + { + std::cerr << "resumeFileTransfer(): can't resume file transfer" << std::endl; + } +} + +void TransfersDialog::openFolderTransfer() +{ + FileInfo info; + + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + for (it = items.begin(); it != items.end(); it ++) { + if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) continue; + break; + } + + /* make path for downloaded or downloading files */ + QFileInfo qinfo; + std::string path; + if (info.downloadStatus == FT_STATE_COMPLETE) { + path = info.path; + } else { + path = rsFiles->getPartialsDirectory(); + } + + /* open folder with a suitable application */ + qinfo.setFile(QString::fromUtf8(path.c_str())); + if (qinfo.exists() && qinfo.isDir()) { + if (!QDesktopServices::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { + std::cerr << "openFolderTransfer(): can't open folder " << path << std::endl; + } + } +} + +void TransfersDialog::previewTransfer() +{ + FileInfo info; + + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + for (it = items.begin(); it != items.end(); it ++) { + if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) continue; + break; + } + + size_t pos = info.fname.find_last_of('.'); + if (pos == std::string::npos) + return; /* can't identify type of file */ + + /* check if the file is a media file */ + if (!misc::isPreviewable(info.fname.substr(pos + 1).c_str())) return; + + /* make path for downloaded or downloading files */ + bool complete = false; + std::string path; + if (info.downloadStatus == FT_STATE_COMPLETE) { + path = info.path + "/" + info.fname; + complete = true; + } else { + path = rsFiles->getPartialsDirectory() + "/" + info.hash; + } + +#ifndef WIN32 + if (!QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromUtf8(path.c_str())))) + QMessageBox::warning(this, tr("File preview"), tr("File %1 preview failed.").arg(QString::fromUtf8(path.c_str()))); +#else + /* open or preview them with a suitable application */ + QFileInfo qinfo; + if (complete) { + qinfo.setFile(QString::fromUtf8(path.c_str())); + if (qinfo.exists()) { + if (!QDesktopServices::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { + std::cerr << "previewTransfer(): can't preview file " << path << std::endl; + } + } + } else { + QString linkName = QString::fromUtf8(path.c_str()) + + QString::fromUtf8(info.fname.substr(info.fname.find_last_of('.')).c_str()); + if (QFile::link(QString::fromUtf8(path.c_str()), linkName)) { + qinfo.setFile(linkName); + if (qinfo.exists()) { + if (!QDesktopServices::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { + std::cerr << "previewTransfer(): can't preview file " << path << std::endl; + } + } + /* wait for the file to open then remove the link */ +#ifdef WIN32 + Sleep(2000); +#else + sleep(2); +#endif + QFile::remove(linkName); + } else { + std::cerr << "previewTransfer(): can't create link for file " << path << std::endl; + } + } +#endif +} + +void TransfersDialog::openTransfer() +{ + FileInfo info; + + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + for (it = items.begin(); it != items.end(); it ++) { + if (!rsFiles->FileDetails(*it, RS_FILE_HINTS_DOWNLOAD, info)) continue; + break; + } + + /* make path for downloaded or downloading files */ + std::string path; + if (info.downloadStatus == FT_STATE_COMPLETE) { + path = info.path + "/" + info.fname; + + /* open file with a suitable application */ + QFileInfo qinfo; + qinfo.setFile(QString::fromUtf8(path.c_str())); + if (qinfo.exists()) { + if (!QDesktopServices::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { + std::cerr << "openTransfer(): can't open file " << path << std::endl; + } + } + } else { + /* rise a message box for incompleted download file */ + QMessageBox::information(this, tr("Open Transfer"), + tr("File %1 is not completed. If it is a media file, try to preview it.").arg(QString::fromUtf8(info.fname.c_str()))); + } +} + +/* clear download or all queue - for pending dwls */ +//void TransfersDialog::clearQueuedDwl() +//{ +// std::set items; +// std::set::iterator it; +// getSelectedItems(&items, NULL); +// +// for (it = items.begin(); it != items.end(); it ++) { +// std::string hash = (*it)->data(Qt::DisplayRole).toString().toStdString(); +// rsFiles->clearDownload(hash); +// } +//} +//void TransfersDialog::clearQueue() +//{ +// rsFiles->clearQueue(); +//} + +void TransfersDialog::chunkStreaming() +{ + setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_STREAMING) ; +} +void TransfersDialog::chunkRandom() +{ + setChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; +} +void TransfersDialog::setChunkStrategy(FileChunksInfo::ChunkStrategy s) +{ + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + + for (it = items.begin(); it != items.end(); it ++) { + rsFiles->setChunkStrategy(*it, s); + } +} +/* modify download priority actions */ +void TransfersDialog::speedSlow() +{ + changeSpeed(0); +} +void TransfersDialog::speedAverage() +{ + changeSpeed(1); +} +void TransfersDialog::speedFast() +{ + changeSpeed(2); +} + +void TransfersDialog::priorityQueueUp() +{ + changeQueuePosition(QUEUE_UP); +} +void TransfersDialog::priorityQueueDown() +{ + changeQueuePosition(QUEUE_DOWN); +} +void TransfersDialog::priorityQueueTop() +{ + changeQueuePosition(QUEUE_TOP); +} +void TransfersDialog::priorityQueueBottom() +{ + changeQueuePosition(QUEUE_BOTTOM); +} + +void TransfersDialog::changeSpeed(int speed) +{ + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + + for (it = items.begin(); it != items.end(); it ++) + { + rsFiles->changeDownloadSpeed(*it, speed); + } +} + + +void TransfersDialog::changeQueuePosition(QueueMove mv) +{ + std::cerr << "In changeQueuePosition (gui)"<< std::endl ; + std::set items; + std::set::iterator it; + getSelectedItems(&items, NULL); + + for (it = items.begin(); it != items.end(); it ++) + { + rsFiles->changeQueuePosition(*it, mv); + } +} + +void TransfersDialog::clearcompleted() +{ + std::cerr << "TransfersDialog::clearcompleted()" << std::endl; + rsFiles->FileClearCompleted(); +} + +void TransfersDialog::showFileDetails() +{ + std::string file_hash ; + int nb_select = 0 ; + + std::cout << "new selection " << std::endl ; + + for(int i = 0; i <= DLListModel->rowCount(); i++) + if(selection->isRowSelected(i, QModelIndex())) + { + file_hash = getID(i, DLListModel).toStdString(); + ++nb_select ; + } + if(nb_select != 1) + dynamic_cast(ui.fileTransferInfoWidget->widget())->setFileHash("") ; + else + dynamic_cast(ui.fileTransferInfoWidget->widget())->setFileHash(file_hash) ; + + std::cout << "calling update " << std::endl ; + dynamic_cast(ui.fileTransferInfoWidget->widget())->updateDisplay() ; + std::cout << "done" << std::endl ; + + updateDetailsDialog (); +} + +double TransfersDialog::getProgress(int , QStandardItemModel *) +{ +// return model->data(model->index(row, PROGRESS), Qt::DisplayRole).toDouble(); +return 0.0 ; +} + +double TransfersDialog::getSpeed(int row, QStandardItemModel *model) +{ + return model->data(model->index(row, DLSPEED), Qt::DisplayRole).toDouble(); +} + +QString TransfersDialog::getFileName(int row, QStandardItemModel *model) +{ + return model->data(model->index(row, NAME), Qt::DisplayRole).toString(); +} + +QString TransfersDialog::getStatus(int row, QStandardItemModel *model) +{ + return model->data(model->index(row, STATUS), Qt::DisplayRole).toString(); +} + +QString TransfersDialog::getID(int row, QStandardItemModel *model) +{ + return model->data(model->index(row, ID), Qt::DisplayRole).toString().left(40); // gets only the "hash" part of the name +} + +QString TransfersDialog::getPriority(int row, QStandardItemModel *model) +{ + return model->data(model->index(row, PRIORITY), Qt::DisplayRole).toString(); +} + +qlonglong TransfersDialog::getFileSize(int row, QStandardItemModel *model) +{ + bool ok = false; + return model->data(model->index(row, SIZE), Qt::DisplayRole).toULongLong(&ok); +} + +qlonglong TransfersDialog::getTransfered(int row, QStandardItemModel *model) +{ + bool ok = false; + return model->data(model->index(row, COMPLETED), Qt::DisplayRole).toULongLong(&ok); +} + +qlonglong TransfersDialog::getRemainingTime(int row, QStandardItemModel *model) +{ + bool ok = false; + return model->data(model->index(row, REMAINING), Qt::DisplayRole).toULongLong(&ok); +} + +qlonglong TransfersDialog::getDownloadTime(int row, QStandardItemModel *model) +{ + return model->data(model->index(row, DOWNLOADTIME), Qt::DisplayRole).toULongLong(); +} + +QString TransfersDialog::getSources(int row, QStandardItemModel *model) +{ + return model->data(model->index(row, SOURCES), Qt::DisplayRole).toString(); +} diff --git a/retroshare-gui/src/gui/TransfersDialog.h b/retroshare-gui/src/gui/TransfersDialog.h new file mode 100644 index 000000000..b42611234 --- /dev/null +++ b/retroshare-gui/src/gui/TransfersDialog.h @@ -0,0 +1,193 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _TRANSFERSDIALOG_H +#define _TRANSFERSDIALOG_H + +#include + +#include +#include "RsAutoUpdatePage.h" + +#include "ui_TransfersDialog.h" + + +class DLListDelegate; +class ULListDelegate; +class QStandardItemModel; +class QStandardItem; +class DetailsDialog; +class FileProgressInfo; + +class TransfersDialog : public RsAutoUpdatePage +{ +Q_OBJECT + +public: + /** Default Constructor */ + TransfersDialog(QWidget *parent = 0); + ~TransfersDialog(); + +// replaced by shortcut +// virtual void keyPressEvent(QKeyEvent *) ; + virtual void updateDisplay() ; // derived from RsAutoUpdateWidget + + static DetailsDialog *detailsdlg; + +public slots: + void insertTransfers(); + +// void handleDownloadRequest(const QString& url); + +private slots: + + /** Create the context popup menu and it's submenus */ + void downloadListCostumPopupMenu( QPoint point ); + + void cancel(); + void forceCheck(); + /** removes finished Downloads**/ + void clearcompleted(); + + void copyLink(); + void pasteLink(); + +// void rootdecorated(); +// void rootisnotdecorated(); + + void pauseFileTransfer(); + void resumeFileTransfer(); + void openFolderTransfer(); + void openTransfer(); + void previewTransfer(); + + /** clear download or all queue - for pending dwls */ +// void clearQueue(); + + /** modify download priority actions */ + void priorityQueueUp(); + void priorityQueueDown(); + void priorityQueueTop(); + void priorityQueueBottom(); + + void speedSlow(); + void speedAverage(); + void speedFast(); + + void changeSpeed(int) ; + void changeQueuePosition(QueueMove) ; + + void chunkRandom(); + void chunkStreaming(); + + void showDetailsDialog(); + void updateDetailsDialog(); + +signals: + void playFiles(QStringList files); + +private: + QString getPeerName(const std::string& peer_id) const ; + static QIcon getIconFromExtension(QString) ; + + QStandardItemModel *DLListModel; + QStandardItemModel *ULListModel; + QItemSelectionModel *selection; + QItemSelectionModel *selectionup; + + DLListDelegate *DLDelegate; + ULListDelegate *ULDelegate; + + /** Create the actions on the tray menu or menubar */ + void createActions(); + + /** Defines the actions for the context menu */ + QAction* showdowninfoAct; + QAction* playAct; + QAction* cancelAct; + QAction* forceCheckAct; + QAction* clearcompletedAct; + QAction* copylinkAct; + QAction* pastelinkAct; + QAction* rootisnotdecoratedAct; + QAction* rootisdecoratedAct; + QAction *pauseAct; + QAction *resumeAct; + QAction *openfolderAct; + QAction *openfileAct; + QAction *previewfileAct; +// QAction *clearQueuedDwlAct; +// QAction *clearQueueAct; + QAction *changePriorityAct; + QAction *prioritySlowAct; + QAction *priorityMediumAct; + QAction *priorityFastAct; + QAction *queueDownAct; + QAction *queueUpAct; + QAction *queueTopAct; + QAction *queueBottomAct; + QAction *chunkRandomAct; + QAction *chunkStreamingAct; + QAction *detailsfileAct; + + bool m_bProcessSettings; + void processSettings(bool bLoad); + + void getSelectedItems(std::set *ids, std::set *rows); + bool controlTransferFile(uint32_t flags); + void changePriority(int priority); + void setChunkStrategy(FileChunksInfo::ChunkStrategy s) ; + + QTreeView *downloadList; + + /** Adds a new action to the toolbar. */ + void addAction(QAction *action, const char *slot = 0); + + /** Qt Designer generated object */ + Ui::TransfersDialog ui; + +public slots: + // these two functions add entries to the transfers dialog, and return the row id of the entry modified/added + // + int addItem(const QString& symbol, const QString& name, const QString& coreID, qlonglong size, const FileProgressInfo& pinfo, double dlspeed, const QString& sources, const QString& status, const QString& priority, qlonglong completed, qlonglong remaining, qlonglong downloadtime); + int addPeerToItem(int row, const QString& name, const QString& coreID, double dlspeed, uint32_t status, const FileProgressInfo& peerInfo); +// void delItem(int row); + + int addUploadItem(const QString& symbol, const QString& name, const QString& coreID, qlonglong size, const FileProgressInfo& pinfo, double dlspeed, const QString& sources,const QString& source_id, const QString& status, qlonglong completed, qlonglong remaining); +// void delUploadItem(int row); + + void showFileDetails() ; + + double getProgress(int row, QStandardItemModel *model); + double getSpeed(int row, QStandardItemModel *model); + QString getFileName(int row, QStandardItemModel *model); + QString getStatus(int row, QStandardItemModel *model); + QString getID(int row, QStandardItemModel *model); + QString getPriority(int row, QStandardItemModel *model); + qlonglong getFileSize(int row, QStandardItemModel *model); + qlonglong getTransfered(int row, QStandardItemModel *model); + qlonglong getRemainingTime(int row, QStandardItemModel *model); + qlonglong getDownloadTime(int row, QStandardItemModel *model); + QString getSources(int row, QStandardItemModel *model); +}; + +#endif + diff --git a/retroshare-gui/src/gui/TransfersDialog.ui b/retroshare-gui/src/gui/TransfersDialog.ui new file mode 100644 index 000000000..89433b933 --- /dev/null +++ b/retroshare-gui/src/gui/TransfersDialog.ui @@ -0,0 +1,835 @@ + + + TransfersDialog + + + + 0 + 0 + 620 + 353 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + true + + + Qt::PreventContextMenu + + + + + + Qt::Vertical + + + + + 0 + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + 0 + + + 6 + + + + + + + + :/images/down.png + + + + + + + + 10 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + + + + + Qt::Horizontal + + + + 483 + 20 + + + + + + + + Show cache transfers + + + + + + + + + + + Arial + 9 + + + + true + + + Qt::CustomContextMenu + + + false + + + 0 + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked + + + false + + + false + + + false + + + QAbstractItemView::NoDragDrop + + + false + + + true + + + true + + + false + + + true + + + false + + + + + + + + + 75 + true + + + + 1 + + + + + :/images/up.png:/images/up.png + + + Uploads + + + + 0 + + + 0 + + + + + + Arial + 9 + + + + true + + + + + + + + + :/images/blockdevice.png:/images/blockdevice.png + + + Selected transfer + + + + 0 + + + 6 + + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 598 + 99 + + + + + + + + + 6 + + + + + + + + + + :/images/graph-downloaded.png + + + + + + + Done + + + + + + + + + + + + + + :/images/graph-downloading.png + + + + + + + Active + + + + + + + + + + + + + + :/images/graph-notdownload.png + + + + + + + Outstanding + + + + + + + + + Qt::Horizontal + + + + 368 + 13 + + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/TrustView.cpp b/retroshare-gui/src/gui/TrustView.cpp new file mode 100644 index 000000000..c64c0cfd7 --- /dev/null +++ b/retroshare-gui/src/gui/TrustView.cpp @@ -0,0 +1,263 @@ +#include +#include +#include +#include +#include +#include + +#include +#include "TrustView.h" + +#include + +using namespace std ; + +TrustView::TrustView() + : RsAutoUpdatePage(10000) +{ + setupUi(this) ; + + trustTableTW->setMouseTracking(true) ; +// trustInconsistencyCB->setEnabled(false) ; + + zoomHS->setValue(100) ; + + QObject::connect(zoomHS,SIGNAL(valueChanged(int)),this,SLOT(updateZoom(int))) ; + QObject::connect(updatePB,SIGNAL(clicked()),this,SLOT(update())) ; + QObject::connect(trustTableTW,SIGNAL(cellClicked(int,int)),this,SLOT(selectCell(int,int))) ; + QObject::connect(trustTableTW->verticalHeader(),SIGNAL(sectionClicked(int)),this,SLOT(hideShowPeers(int))) ; + QObject::connect(trustTableTW->horizontalHeader(),SIGNAL(sectionClicked(int)),this,SLOT(hideShowPeers(int))) ; + + updatePB->setToolTip(tr("This table normaly auto-updates every 10 seconds.")) ; +} + +void TrustView::showEvent(QShowEvent *e) +{ + QWidget::showEvent(e) ; + update() ; +} +void TrustView::wheelEvent(QWheelEvent *e) +{ + if(e->modifiers() & Qt::ShiftModifier) + { + if(e->delta() > 0) + zoomHS->setValue(zoomHS->value()-5) ; + else + zoomHS->setValue(zoomHS->value()+5) ; + } +} + +void TrustView::selectCell(int row,int col) +{ + static int last_row = -1 ; + static int last_col = -1 ; +#ifdef DEBUG_TRUSTVIEW + cout << "row = " << row << ", column = " << col << endl; + if(row == 0 || col == 0) + cout << "***********************************************" << endl ; +#endif + if(last_row > -1) + { + int col_s,row_s ; + getCellSize(zoomHS->value(),col_s,row_s) ; + + trustTableTW->setColumnWidth(last_col,col_s) ; + trustTableTW->setRowHeight(last_row,row_s) ; + } + + if(row != last_row || col != last_col) + { + trustTableTW->setColumnWidth(col,_base_cell_width) ; + trustTableTW->setRowHeight(row,_base_cell_height) ; + + last_col = col ; + last_row = row ; + } + else + { + last_col = -1 ; + last_row = -1 ; + } +} + +void TrustView::getCellSize(int z,int& col_s,int& row_s) const +{ + col_s = max(10,(int)rint( z/100.0 * _base_cell_width )) ; + row_s = max(10,(int)rint( z/100.0 * _base_cell_height)) ; +} + +void TrustView::updateZoom(int z) +{ + int col_s,row_s ; + getCellSize(z,col_s,row_s) ; + + for(int i=0;icolumnCount();++i) + trustTableTW->setColumnWidth(i,col_s) ; + + for(int i=0;irowCount();++i) + trustTableTW->setRowHeight(i,row_s) ; + +// cout << "updated zoom" << endl; +} + +int TrustView::getRowColId(const string& peerid) +{ + static map peeridToRow ; + + map::const_iterator itpr(peeridToRow.find( peerid )) ; + int i ; + + if(itpr == peeridToRow.end()) + { + i = trustTableTW->columnCount() ; + + trustTableTW->insertColumn(i) ; + trustTableTW->insertRow(i) ; + + peeridToRow[peerid] = i ; + + std::string name = rsPeers->getPeerName(peerid) ; + + trustTableTW->setHorizontalHeaderItem(i,new QTableWidgetItem(QString(name.c_str()))) ; + trustTableTW->setVerticalHeaderItem(i,new QTableWidgetItem(QString(name.c_str()))) ; + + trustTableTW->setColumnWidth(i,_base_cell_width) ; + trustTableTW->setRowHeight(i,_base_cell_height) ; + } + else + i = (*itpr).second ; + + return i ; +} + +void TrustView::updateDisplay() +{ + update() ; +} +void TrustView::update() +{ + std::list neighs; + + if(!rsPeers->getGPGAllList(neighs)) + return ; + + neighs.push_back(rsPeers->getGPGOwnId()) ; + + trustTableTW->setSortingEnabled(false) ; + + RsPeerDetails details ; + + // Fill everything + for(list::const_iterator it1(neighs.begin()); it1 != neighs.end(); ++it1) + { + std::list friends_ids ; + + if(!rsPeers->getPeerDetails(*it1,details)) + continue ; + + int i = getRowColId(details.id) ; + std::string issuer(details.issuer) ; // the one we check for trust. + + for(list::const_iterator it2(details.gpgSigners.begin());it2!=details.gpgSigners.end();++it2) + { +#ifdef DEBUG_TRUSTVIEW + cout << *it2 << " " ; +#endif + + int j = getRowColId(*it2) ; + + QString trr( (i==j)?tr("Self"):tr("Trust")) ; + + if(trustTableTW->item(i,j) == NULL) + trustTableTW->setItem(i,j,new QTableWidgetItem(trr)) ; + else + trustTableTW->item(i,j)->setText(trr) ; + } + // cout << endl ; + } + // assign colors + vector ni(trustTableTW->rowCount(),0) ; + vector nj(trustTableTW->columnCount(),0) ; + + for(int i=0;irowCount();++i) + for(int j=0;jcolumnCount();++j) + { + QTableWidgetItem *i_ij(trustTableTW->item(i,j)) ; + QTableWidgetItem *i_ji(trustTableTW->item(j,i)) ; + + QColor color ; + + // check bidirectional trust + // + if(i_ij != NULL) + { + ++ni[i] ; + ++nj[j] ; + + if(i_ji == NULL) + { + i_ij->setBackgroundColor(Qt::yellow) ; + i_ij->setToolTip(trustTableTW->horizontalHeaderItem(i)->text() + tr(" is authenticated (one way) by " )+trustTableTW->verticalHeaderItem(j)->text()) ; + i_ij->setText(tr("Half")) ; + } + else + { + if(i==j) + { + i_ij->setBackgroundColor(Qt::red) ; + i_ij->setToolTip(trustTableTW->horizontalHeaderItem(i)->text() + tr(" authenticated himself") ) ; + } + else + { + i_ij->setBackgroundColor(Qt::green) ; + i_ij->setToolTip(trustTableTW->horizontalHeaderItem(i)->text() + " and " +trustTableTW->verticalHeaderItem(j)->text() + tr(" authenticated each other") ) ; + i_ij->setText(tr("Full")) ; + } + } + } + } + for(int i=0;irowCount();++i) + trustTableTW->verticalHeaderItem(i)->setToolTip(trustTableTW->verticalHeaderItem(i)->text()+ tr(" is authenticated by ") + QString::number(ni[i]) + tr(" peers, including him(her)self.")) ; + + for(int j=0;jcolumnCount();++j) + trustTableTW->horizontalHeaderItem(j)->setToolTip(trustTableTW->horizontalHeaderItem(j)->text()+ tr(" authenticated ") + QString::number(nj[j]) + tr(" peers, including him(her)self.")) ; + +} + +void TrustView::hideShowPeers(int col) +{ + // Choose what to show/hide + // + + static int last_col = -1 ; + + if(col == last_col) + { + for(int i=0;irowCount();++i) + { + trustTableTW->setColumnHidden(i,false) ; + trustTableTW->setRowHidden(i,false) ; + } + last_col = -1 ; + + showingLabel->setText(tr("Showing: whole network")) ; + } + else + { + for(int i=0;irowCount();++i) + if(trustTableTW->item(i,col) == NULL && trustTableTW->item(col,i) == NULL) + { + trustTableTW->setColumnHidden(i,true) ; + trustTableTW->setRowHidden(i,true) ; + } + else + { + trustTableTW->setColumnHidden(i,false) ; + trustTableTW->setRowHidden(i,false) ; + } + last_col = col ; + showingLabel->setText(tr("Showing: peers connected to ")+trustTableTW->verticalHeaderItem(col)->text()) ; + } +} + + diff --git a/retroshare-gui/src/gui/TrustView.h b/retroshare-gui/src/gui/TrustView.h new file mode 100644 index 000000000..1ebc3b630 --- /dev/null +++ b/retroshare-gui/src/gui/TrustView.h @@ -0,0 +1,32 @@ +#include "ui_TrustView.h" +#include + +class QWheelEvent ; +class QShowEvent ; + +class TrustView: public RsAutoUpdatePage, public Ui::TrustView +{ + Q_OBJECT + + public: + TrustView() ; + + protected: + virtual void wheelEvent(QWheelEvent *) ; + virtual void showEvent(QShowEvent *) ; + + virtual void updateDisplay() ; + public slots: + void update() ; + void updateZoom(int) ; + void selectCell(int,int) ; + void hideShowPeers(int) ; + + private: + void getCellSize(int z,int& cell_width,int& cell_height) const ; + int getRowColId(const std::string& name) ; + + static const int _base_cell_width = 60 ; + static const int _base_cell_height = 30 ; +}; + diff --git a/retroshare-gui/src/gui/TrustView.ui b/retroshare-gui/src/gui/TrustView.ui new file mode 100644 index 000000000..2c9ff663f --- /dev/null +++ b/retroshare-gui/src/gui/TrustView.ui @@ -0,0 +1,68 @@ + + + TrustView + + + + 0 + 0 + 468 + 394 + + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + + + Qt::Vertical + + + + + + + Zoom : + + + + + + + 100 + + + Qt::Horizontal + + + + + + + Update + + + + + + + Showing: whole network + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/TurtleRouterDialog.cpp b/retroshare-gui/src/gui/TurtleRouterDialog.cpp new file mode 100644 index 000000000..d7b03556e --- /dev/null +++ b/retroshare-gui/src/gui/TurtleRouterDialog.cpp @@ -0,0 +1,221 @@ +#include +#include +#include +#include +#include +#include "TurtleRouterDialog.h" +#include +#include + +#include "gui/settings/rsharesettings.h" + +static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ; + + +TurtleRouterDialog::TurtleRouterDialog(QWidget *parent) + : RsAutoUpdatePage(2000,parent) +{ + setupUi(this) ; + + m_bProcessSettings = false; + + // Init the basic setup. + // + QStringList stl ; + int n=0 ; + + stl.clear() ; + stl.push_back(tr("Search requests")) ; + top_level_s_requests = new QTreeWidgetItem(_f2f_TW,stl) ; + _f2f_TW->insertTopLevelItem(n++,top_level_s_requests) ; + + stl.clear() ; + stl.push_back(tr("Tunnel requests")) ; + top_level_t_requests = new QTreeWidgetItem(_f2f_TW,stl) ; + _f2f_TW->insertTopLevelItem(n++,top_level_t_requests) ; + + top_level_hashes.clear() ; + + // load settings + processSettings(true); +} + +TurtleRouterDialog::~TurtleRouterDialog() +{ + + // save settings + processSettings(false); +} + +void TurtleRouterDialog::processSettings(bool bLoad) +{ + m_bProcessSettings = true; + + Settings->beginGroup(QString("TurtleRouterDialog")); + + if (bLoad) { + // load settings + + // state of splitter + //splitter->restoreState(Settings->value("Splitter").toByteArray()); + } else { + // save settings + + // state of splitter + //Settings->setValue("Splitter", splitter->saveState()); + + } + + Settings->endGroup(); + + m_bProcessSettings = false; + +} + + +void TurtleRouterDialog::updateDisplay() +{ + std::vector > hashes_info ; + std::vector > tunnels_info ; + std::vector search_reqs_info ; + std::vector tunnel_reqs_info ; + + rsTurtle->getInfo(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; + + updateTunnelRequests(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; + +} + +QString TurtleRouterDialog::getPeerName(const std::string& peer_id) +{ + static std::map names ; + + std::map::const_iterator it = names.find(peer_id) ; + + if( it != names.end()) + return it->second ; + else + { + RsPeerDetails detail ; + if(!rsPeers->getPeerDetails(peer_id,detail)) + return "unknown peer"; + + return (names[peer_id] = QString::fromStdString(detail.name)) ; + } +} + +void TurtleRouterDialog::updateTunnelRequests( const std::vector >& hashes_info, + const std::vector >& tunnels_info, + const std::vector& search_reqs_info, + const std::vector& tunnel_reqs_info) +{ + // now display this in the QTableWidgets + + QStringList stl ; + + // remove all children of top level objects + for(int i=0;i<_f2f_TW->topLevelItemCount();++i) + { + QTreeWidgetItem *taken ; + while( (taken = _f2f_TW->topLevelItem(i)->takeChild(0)) != NULL) + delete taken ; + } + + for(uint i=0;itext(0).left(14) == QString("Unknown hashes")) + unknown_hash_found = true ; + + QString str = QString::fromStdString( "Tunnel id: " + tunnels_info[i][0] + "\t [" + tunnels_info[i][2] + "] --> [" + tunnels_info[i][1] + "]\t\t last transfer: " + tunnels_info[i][4] + "\t Speed: " + tunnels_info[i][5] ) ; + stl.clear() ; + stl.push_back(str) ; + + parent->addChild(new QTreeWidgetItem(stl)) ; + } + + for(uint i=0;iaddChild(new QTreeWidgetItem(stl)) ; + } + top_level_s_requests->setText(0, tr("Search requests") + "(" + QString::number(search_reqs_info.size()) + ")" ) ; + + for(uint i=0;i= tunnel_reqs_info.size() || i < MAX_TUNNEL_REQUESTS_DISPLAY) + { + QString str = "Request id: " + QString::number(tunnel_reqs_info[i].request_id,16) + "\t from [" + getPeerName(tunnel_reqs_info[i].source_peer_id) + "]\t " + QString::number(tunnel_reqs_info[i].age)+" secs ago" ; + + stl.clear() ; + stl.push_back(str) ; + + top_level_t_requests->addChild(new QTreeWidgetItem(stl)) ; + } + else if(i == MAX_TUNNEL_REQUESTS_DISPLAY) + { + stl.clear() ; + stl.push_back(QString("...")) ; + top_level_t_requests->addChild(new QTreeWidgetItem(stl)) ; + + } + + top_level_t_requests->setText(0, tr("Tunnel requests") + "("+QString::number(tunnel_reqs_info.size()) + ")") ; + + QTreeWidgetItem *unknown_hashs_item = findParentHashItem("") ; + unknown_hashs_item->setText(0,QString("Unknown hashes (") + QString::number(unknown_hashs_item->childCount())+QString(")")) ; + + // Ok, this is a N2 search, but there are very few elements in the list. + for(int i=2;i<_f2f_TW->topLevelItemCount();) + { + bool found = false ; + + if(_f2f_TW->topLevelItem(i)->text(0).left(14) == "Unknown hashes" && unknown_hash_found) + found = true ; + + if(_f2f_TW->topLevelItem(i)->childCount() > 0) // this saves uploading hashes + found = true ; + + for(uint j=0;jtopLevelItem(i)->text(0).toStdString() == hashes_info[j][0]) + found=true ; + + if(!found) + delete _f2f_TW->takeTopLevelItem(i) ; + else + ++i ; + } +} + +QTreeWidgetItem *TurtleRouterDialog::findParentHashItem(const std::string& hash) +{ + // look for the hash, and insert a new element if necessary. + // + QList items = _f2f_TW->findItems((hash=="")?QString("Unknown hashes"):QString::fromStdString(hash),Qt::MatchStartsWith) ; + + if(items.empty()) + { + QStringList stl ; + stl.push_back((hash=="")?QString("Unknown hashes"):QString::fromStdString(hash)) ; + QTreeWidgetItem *item = new QTreeWidgetItem(_f2f_TW,stl) ; + _f2f_TW->insertTopLevelItem(0,item) ; + + return item ; + } + else + return items.front() ; +} + + diff --git a/retroshare-gui/src/gui/TurtleRouterDialog.h b/retroshare-gui/src/gui/TurtleRouterDialog.h new file mode 100644 index 000000000..97f9fbacc --- /dev/null +++ b/retroshare-gui/src/gui/TurtleRouterDialog.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include "ui_TurtleRouterDialog.h" +#include "RsAutoUpdatePage.h" + + +class TurtleRouterDialog: public RsAutoUpdatePage, public Ui::TurtleRouterDialogForm +{ + public: + TurtleRouterDialog(QWidget *parent = NULL) ; + ~TurtleRouterDialog(); + + // Cache for peer names. + static QString getPeerName(const std::string& peer_id) ; + + private: + void updateTunnelRequests( const std::vector > >&, + const std::vector > >&, + const std::vector&, + const std::vector&) ; + + void processSettings(bool bLoad); + bool m_bProcessSettings; + + virtual void updateDisplay() ; + QTreeWidgetItem *findParentHashItem(const std::string& hash) ; + + std::map top_level_hashes ; + QTreeWidgetItem *top_level_unknown_hashes ; + QTreeWidgetItem *top_level_s_requests ; + QTreeWidgetItem *top_level_t_requests ; + +} ; + + + diff --git a/retroshare-gui/src/gui/TurtleRouterDialog.ui b/retroshare-gui/src/gui/TurtleRouterDialog.ui new file mode 100644 index 000000000..da4780cf2 --- /dev/null +++ b/retroshare-gui/src/gui/TurtleRouterDialog.ui @@ -0,0 +1,39 @@ + + + TurtleRouterDialogForm + + + + 0 + 0 + 572 + 350 + + + + Router Statistics + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + true + + + + F2F router information + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/TurtleRouterStatistics.cpp b/retroshare-gui/src/gui/TurtleRouterStatistics.cpp new file mode 100644 index 000000000..6472a9fb1 --- /dev/null +++ b/retroshare-gui/src/gui/TurtleRouterStatistics.cpp @@ -0,0 +1,347 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 20011, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include +#include + +#include +#include +#include "TurtleRouterStatistics.h" + +#include "gui/settings/rsharesettings.h" + +static const int MAX_TUNNEL_REQUESTS_DISPLAY = 10 ; + +class TRHistogram +{ + public: + TRHistogram(const std::vector& info) :_infos(info) {} + + QColor colorScale(float f) + { + if(f == 0) + return QColor::fromHsv(0,0,192) ; + else + return QColor::fromHsv((int)((1.0-f)*280),200,255) ; + } + + virtual void draw(QPainter *painter,int& ox,int& oy,const QString& title) + { + static const int MaxTime = 61 ; + static const int MaxDepth = 8 ; + static const int cellx = 7 ; + static const int celly = 12 ; + + int save_ox = ox ; + painter->setPen(QColor::fromRgb(0,0,0)) ; + painter->drawText(2+ox,celly+oy,title) ; + oy+=2+2*celly ; + + if(_infos.empty()) + return ; + + ox += 10 ; + std::map > hits ; + std::map > depths ; + std::map >::iterator it ; + + int max_hits = 1; + int max_depth = 1; + + for(uint32_t i=0;i<_infos.size();++i) + { + std::vector& h(hits[_infos[i].source_peer_id]) ; + std::vector& g(depths[_infos[i].source_peer_id]) ; + + if(h.size() <= _infos[i].age) + h.resize(MaxTime,0) ; + + if(g.empty()) + g.resize(MaxDepth,0) ; + + if(_infos[i].age < h.size()) + { + h[_infos[i].age]++ ; + if(h[_infos[i].age] > max_hits) + max_hits = h[_infos[i].age] ; + } + if(_infos[i].depth < g.size()) + { + g[_infos[i].depth]++ ; + + if(g[_infos[i].depth] > max_depth) + max_depth = g[_infos[i].depth] ; + } + } + + int max_bi = std::max(max_hits,max_depth) ; + int p=0 ; + + for(it=depths.begin();it!=depths.end();++it,++p) + for(int i=0;ifillRect(ox+MaxTime*cellx+20+i*cellx,oy+p*celly,cellx,celly,colorScale(it->second[i]/(float)max_bi)) ; + + painter->setPen(QColor::fromRgb(0,0,0)) ; + painter->drawRect(ox+MaxTime*cellx+20,oy,MaxDepth*cellx,p*celly) ; + + for(int i=0;idrawText(ox+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ; + + p=0 ; + int great_total = 0 ; + + for(it=hits.begin();it!=hits.end();++it,++p) + { + int total = 0 ; + + for(int i=0;ifillRect(ox+i*cellx,oy+p*celly,cellx,celly,colorScale(it->second[i]/(float)max_bi)) ; + total += it->second[i] ; + } + + painter->setPen(QColor::fromRgb(0,0,0)) ; + painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx,oy+(p+1)*celly,TurtleRouterStatistics::getPeerName(it->first)) ; + painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+(p+1)*celly,"("+QString::number(total)+")") ; + great_total += total ; + } + + painter->drawRect(ox,oy,MaxTime*cellx,p*celly) ; + + for(int i=0;idrawText(ox+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ; + for(int i=0;idrawText(ox+MaxTime*cellx+20+i*cellx,oy+(p+1)*celly+4,QString::number(i)) ; + painter->setPen(QColor::fromRgb(255,130,80)) ; + painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+(p+1)*celly+4,"("+QString::number(great_total)+")"); + + oy += (p+1)*celly+6 ; + + painter->setPen(QColor::fromRgb(0,0,0)) ; + painter->drawText(ox,oy+celly,QObject::tr("(Age in seconds)")); + painter->drawText(ox+MaxTime*cellx+20,oy+celly,QObject::tr("(Depth)")); + + painter->drawText(ox+MaxDepth*cellx+30+(MaxTime+1)*cellx+120,oy+celly,"("+QObject::tr("total")+")"); + + oy += 3*celly ; + + // now, draw a scale + + int last_hts = -1 ; + int cellid = 0 ; + + for(int i=0;i<=10;++i) + { + int hts = (int)(max_bi*i/10.0) ; + + if(hts > last_hts) + { + painter->fillRect(ox+cellid*(cellx+22),oy,cellx,celly,colorScale(i/10.0f)) ; + painter->setPen(QColor::fromRgb(0,0,0)) ; + painter->drawRect(ox+cellid*(cellx+22),oy,cellx,celly) ; + painter->drawText(ox+cellid*(cellx+22)+cellx+4,oy+celly,QString::number(hts)) ; + last_hts = hts ; + ++cellid ; + } + } + + oy += celly*2 ; + + ox = save_ox ; + } + + private: + const std::vector& _infos ; +}; + +TurtleRouterStatistics::TurtleRouterStatistics(QWidget *parent) + : RsAutoUpdatePage(2000,parent) +{ + setupUi(this) ; + + m_bProcessSettings = false; + + _tunnel_statistics_F->setWidget( _tst_CW = new TurtleRouterStatisticsWidget() ) ; + _tunnel_statistics_F->setWidgetResizable(true); + _tunnel_statistics_F->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + _tunnel_statistics_F->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + _tunnel_statistics_F->viewport()->setBackgroundRole(QPalette::NoRole); + _tunnel_statistics_F->setFrameStyle(QFrame::NoFrame); + _tunnel_statistics_F->setFocusPolicy(Qt::NoFocus); + + // load settings + processSettings(true); +} + +TurtleRouterStatistics::~TurtleRouterStatistics() +{ + + // save settings + processSettings(false); +} + +void TurtleRouterStatistics::processSettings(bool bLoad) +{ + m_bProcessSettings = true; + + Settings->beginGroup(QString("TurtleRouterStatistics")); + + if (bLoad) { + // load settings + + // state of splitter + //splitter->restoreState(Settings->value("Splitter").toByteArray()); + } else { + // save settings + + // state of splitter + //Settings->setValue("Splitter", splitter->saveState()); + + } + + Settings->endGroup(); + + m_bProcessSettings = false; + +} + + +void TurtleRouterStatistics::updateDisplay() +{ + std::vector > hashes_info ; + std::vector > tunnels_info ; + std::vector search_reqs_info ; + std::vector tunnel_reqs_info ; + + rsTurtle->getInfo(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; + + //updateTunnelRequests(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; + _tst_CW->updateTunnelStatistics(hashes_info,tunnels_info,search_reqs_info,tunnel_reqs_info) ; + _tst_CW->update(); +} + +QString TurtleRouterStatistics::getPeerName(const std::string& peer_id) +{ + static std::map names ; + + std::map::const_iterator it = names.find(peer_id) ; + + if( it != names.end()) + return it->second ; + else + { + RsPeerDetails detail ; + if(!rsPeers->getPeerDetails(peer_id,detail)) + return "unknown peer"; + + return (names[peer_id] = QString::fromStdString(detail.name)) ; + } +} + +TurtleRouterStatisticsWidget::TurtleRouterStatisticsWidget(QWidget *parent) + : QWidget(parent) +{ + maxWidth = 200 ; + maxHeight = 0 ; +} + +void TurtleRouterStatisticsWidget::updateTunnelStatistics(const std::vector >& hashes_info, + const std::vector >& tunnels_info, + const std::vector& search_reqs_info, + const std::vector& tunnel_reqs_info) + +{ + static const int cellx = 6 ; + static const int celly = 10+4 ; + + QPixmap tmppixmap(maxWidth, maxHeight); + tmppixmap.fill(this, 0, 0); + setFixedHeight(maxHeight); + + QPainter painter(&tmppixmap); + painter.initFrom(this); + + maxHeight = 500 ; + + // std::cerr << "Drawing into pixmap of size " << maxWidth << "x" << maxHeight << std::endl; + // draw... + int ox=5,oy=5 ; + + TRHistogram(search_reqs_info).draw(&painter,ox,oy,QObject::tr("Search requests repartition:")) ; + + painter.setPen(QColor::fromRgb(70,70,70)) ; + painter.drawLine(0,oy,maxWidth,oy) ; + oy += celly ; + + TRHistogram(tunnel_reqs_info).draw(&painter,ox,oy,QObject::tr("Tunnel requests repartition:")) ; + + // now give information about turtle traffic. + // + TurtleTrafficStatisticsInfo info ; + rsTurtle->getTrafficStatistics(info) ; + + painter.setPen(QColor::fromRgb(70,70,70)) ; + painter.drawLine(0,oy,maxWidth,oy) ; + oy += celly ; + + painter.drawText(ox,oy+celly,tr("Turtle router traffic:")) ; oy += celly*2 ; + painter.drawText(ox+2*cellx,oy+celly,tr("Tunnel requests Up")+"\t: " + speedString(info.tr_up_Bps) ) ; oy += celly ; + painter.drawText(ox+2*cellx,oy+celly,tr("Tunnel requests Dn")+"\t: " + speedString(info.tr_dn_Bps) ) ; oy += celly ; + painter.drawText(ox+2*cellx,oy+celly,tr("Incoming file data")+"\t: " + speedString(info.data_dn_Bps) ) ; oy += celly ; + painter.drawText(ox+2*cellx,oy+celly,tr("Outgoing file data")+"\t: " + speedString(info.data_up_Bps) ) ; oy += celly ; + painter.drawText(ox+2*cellx,oy+celly,tr("Forwarded data ")+"\t: " + speedString(info.unknown_updn_Bps) ) ; oy += celly ; + + // update the pixmap + // + pixmap = tmppixmap; + maxHeight = oy ; +} + +QString TurtleRouterStatisticsWidget::speedString(float f) +{ + if(f < 1.0f) + return QString("0 B/s") ; + if(f < 1024.0f) + return QString::number((int)f)+" B/s" ; + + return QString::number(f/1024.0,'f',2) + " KB/s"; +} + +void TurtleRouterStatisticsWidget::paintEvent(QPaintEvent *event) +{ + QStylePainter(this).drawPixmap(0, 0, pixmap); +} + +void TurtleRouterStatisticsWidget::resizeEvent(QResizeEvent *event) +{ + QRect TaskGraphRect = geometry(); + maxWidth = TaskGraphRect.width(); + maxHeight = TaskGraphRect.height() ; + + QWidget::resizeEvent(event); + update(); +} + + diff --git a/retroshare-gui/src/gui/TurtleRouterStatistics.h b/retroshare-gui/src/gui/TurtleRouterStatistics.h new file mode 100644 index 000000000..0e3ab2d5a --- /dev/null +++ b/retroshare-gui/src/gui/TurtleRouterStatistics.h @@ -0,0 +1,69 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 20011, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#pragma once + +#include +#include +#include "ui_TurtleRouterStatistics.h" +#include "RsAutoUpdatePage.h" + +class TurtleRouterStatisticsWidget ; + +class TurtleRouterStatistics: public RsAutoUpdatePage, public Ui::TurtleRouterStatistics +{ + public: + TurtleRouterStatistics(QWidget *parent = NULL) ; + ~TurtleRouterStatistics(); + + // Cache for peer names. + static QString getPeerName(const std::string& peer_id) ; + + private: + + void processSettings(bool bLoad); + bool m_bProcessSettings; + + virtual void updateDisplay() ; + + TurtleRouterStatisticsWidget *_tst_CW ; +} ; + +class TurtleRouterStatisticsWidget: public QWidget +{ + public: + TurtleRouterStatisticsWidget(QWidget *parent = NULL) ; + + virtual void paintEvent(QPaintEvent *event) ; + virtual void resizeEvent(QResizeEvent *event); + + void updateTunnelStatistics( const std::vector > >&, + const std::vector > >&, + const std::vector&, + const std::vector&) ; + + private: + static QString speedString(float f) ; + + QPixmap pixmap ; + int maxWidth,maxHeight ; +}; + diff --git a/retroshare-gui/src/gui/TurtleRouterStatistics.ui b/retroshare-gui/src/gui/TurtleRouterStatistics.ui new file mode 100644 index 000000000..365d3f362 --- /dev/null +++ b/retroshare-gui/src/gui/TurtleRouterStatistics.ui @@ -0,0 +1,55 @@ + + + TurtleRouterStatistics + + + + 0 + 0 + 611 + 408 + + + + Router Statistics + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + Qt::Vertical + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 593 + 390 + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/ULListDelegate.cpp b/retroshare-gui/src/gui/ULListDelegate.cpp new file mode 100644 index 000000000..7d416819f --- /dev/null +++ b/retroshare-gui/src/gui/ULListDelegate.cpp @@ -0,0 +1,185 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "ULListDelegate.h" +#include "xprogressbar.h" + +Q_DECLARE_METATYPE(FileProgressInfo) + +ULListDelegate::ULListDelegate(QObject *parent) : QAbstractItemDelegate(parent) +{ + ; +} + +ULListDelegate::~ULListDelegate(void) +{ + ; +} + +void ULListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const +{ + QString byteUnits[4] = {tr("B"), tr("KB"), tr("MB"), tr("GB")}; + QStyleOptionViewItem opt = option; + QStyleOptionProgressBarV2 newopt; + QRect pixmapRect; + QPixmap pixmap; + qlonglong fileSize; + double ulspeed, multi; + QString temp , status; + qlonglong transferred; + + // prepare + painter->save(); + painter->setClipRect(opt.rect); + + //set text color + QVariant value = index.data(Qt::TextColorRole); + if(value.isValid() && qvariant_cast(value).isValid()) { + opt.palette.setColor(QPalette::Text, qvariant_cast(value)); + } + QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; + if(option.state & QStyle::State_Selected){ + painter->setPen(opt.palette.color(cg, QPalette::HighlightedText)); + } else { + painter->setPen(opt.palette.color(cg, QPalette::Text)); + } + + // draw the background color + if(index.column() != UPROGRESS) { + if(option.showDecorationSelected && (option.state & QStyle::State_Selected)) { + if(cg == QPalette::Normal && !(option.state & QStyle::State_Active)) { + cg = QPalette::Inactive; + } + painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight)); + } else { + value = index.data(Qt::BackgroundRole); + if(value.isValid() && qvariant_cast(value).isValid()) { + painter->fillRect(option.rect, qvariant_cast(value)); + } + } + } + switch(index.column()) { + case USIZE: + fileSize = index.data().toLongLong(); + if(fileSize <= 0){ + temp = ""; + } else { + multi = 1.0; + for(int i = 0; i < 5; ++i) { + if (fileSize < 1024) { + fileSize = index.data().toLongLong(); + temp.sprintf("%.2f ", fileSize / multi); + temp += byteUnits[i]; + break; + } + fileSize /= 1024; + multi *= 1024.0; + } + } + painter->drawText(option.rect, Qt::AlignRight, temp); + break; + case UTRANSFERRED: + transferred = index.data().toLongLong(); + if(transferred <= 0){ + temp = ""; + } else { + multi = 1.0; + for(int i = 0; i < 5; ++i) { + if (transferred < 1024) { + transferred = index.data().toLongLong(); + temp.sprintf("%.2f ", transferred / multi); + temp += byteUnits[i]; + break; + } + transferred /= 1024; + multi *= 1024.0; + } + } + painter->drawText(option.rect, Qt::AlignRight, temp); + break; + case ULSPEED: + ulspeed = index.data().toDouble(); + if (ulspeed <= 0) { + temp = ""; + } else { + temp.clear(); + temp.sprintf("%.2f", ulspeed/1024.); + temp += " KB/s"; + } + painter->drawText(option.rect, Qt::AlignRight, temp); + break; + case UPROGRESS: + { + FileProgressInfo pinfo = index.data().value() ; + + // create a xProgressBar + painter->save() ; + xProgressBar progressBar(pinfo,option.rect,painter,0);// the 3rd param is the color schema (0 is the default value) + + QString ext = QFileInfo(QString::fromStdString(index.sibling(index.row(), UNAME).data().toString().toStdString())).suffix();; + if (ext == "rsfc" || ext == "rsrl" || ext == "dist" || ext == "rsfb") + progressBar.setColorSchema( 9); + else + progressBar.setColorSchema( 8); + + progressBar.setDisplayText(true); // should display % text? + progressBar.setVerticalSpan(1); + progressBar.paint(); // paint the progress bar + + painter->restore() ; + } + painter->drawText(option.rect, Qt::AlignCenter, newopt.text); + break; + case UNAME: + // decoration + value = index.data(Qt::DecorationRole); + pixmap = qvariant_cast(value).pixmap(option.decorationSize, option.state & QStyle::State_Enabled ? QIcon::Normal : QIcon::Disabled, option.state & QStyle::State_Open ? QIcon::On : QIcon::Off); + pixmapRect = (pixmap.isNull() ? QRect(0, 0, 0, 0): QRect(QPoint(0, 0), option.decorationSize)); + if (pixmapRect.isValid()){ + QPoint p = QStyle::alignedRect(option.direction, Qt::AlignLeft, pixmap.size(), option.rect).topLeft(); + painter->drawPixmap(p, pixmap); + } + painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignLeft, index.data().toString()); + break; + case USTATUS: + painter->drawText(option.rect.translated(pixmap.size().width(), 0), Qt::AlignCenter, index.data().toString()); + break; + default: + painter->drawText(option.rect, Qt::AlignCenter, index.data().toString()); + } + + // done + painter->restore(); +} + +QSize ULListDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const +{ + return QSize(50,17); + QVariant value = index.data(Qt::FontRole); + QFont fnt = value.isValid() ? qvariant_cast(value) : option.font; + QFontMetrics fontMetrics(fnt); + const QString text = index.data(Qt::DisplayRole).toString(); + QRect textRect = QRect(0, 0, 0, fontMetrics.lineSpacing() * (text.count(QLatin1Char('\n')) + 1)); + return textRect.size(); +} + diff --git a/retroshare-gui/src/gui/ULListDelegate.h b/retroshare-gui/src/gui/ULListDelegate.h new file mode 100644 index 000000000..a5960b9e2 --- /dev/null +++ b/retroshare-gui/src/gui/ULListDelegate.h @@ -0,0 +1,66 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef ULLISTDELEGATE_H +#define ULLISTDELEGATE_H + +#include + +// Defines for upload list list columns +#define UNAME 0 +#define USIZE 1 +#define UTRANSFERRED 2 +#define ULSPEED 3 +#define UPROGRESS 4 +#define USTATUS 5 +#define USERNAME 6 +#define UHASH 7 +#define UUSERID 8 + + + +#define MAX_CHAR_TMP 128 + +class QModelIndex; +class QPainter; +class QStyleOptionProgressBarV2; +class QProgressBar; +class QApplication; + + +class ULListDelegate: public QAbstractItemDelegate { + + Q_OBJECT + + public: + ULListDelegate(QObject *parent=0); + ~ULListDelegate(); + void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; + QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const; + + private: + + public slots: + + signals: +}; +#endif + diff --git a/retroshare-gui/src/gui/advsearch/AdvancedSearchDialog.ui b/retroshare-gui/src/gui/advsearch/AdvancedSearchDialog.ui new file mode 100644 index 000000000..cd9ff4649 --- /dev/null +++ b/retroshare-gui/src/gui/advsearch/AdvancedSearchDialog.ui @@ -0,0 +1,285 @@ + + + AdvancedSearchDialog + + + + 0 + 0 + 838 + 130 + + + + RetroShare: Advanced Search + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + + + + 0 + 130 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + +QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +*{ +color: black; +} + +QComboBox QAbstractItemView { +background-color:white; +} + +QComboBox::down-arrow { +image: url(:/images/combobox_arrow.png); +} + +QComboBox:drop-down +{ +subcontrol-origin: padding; +subcontrol-position: top right; +border-left-style: none; +border-top-right-radius: 1px; +border-bottom-right-radius: 1px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 1 + 1 + + + + + 800 + 60 + + + + false + + + QWidget#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + Search Criteria + + + Qt::AlignJustify|Qt::AlignTop + + + + 0 + + + 2 + + + + + + 1 + 0 + + + + + 600 + 26 + + + + false + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 6 + + + 0 + + + + + Add a further search criterion. + + + + + + + :/images/add_24x24.png:/images/add_24x24.png + + + + 24 + 24 + + + + + + + + Reset the search criteria. + + + + + + + :/images/reset.png:/images/reset.png + + + + 24 + 24 + + + + + + + + Qt::Horizontal + + + + 381 + 27 + + + + + + + + + 0 + 26 + + + + Cancels the search. + + + Cancel + + + + + + + + 0 + 26 + + + + Perform the advanced search. + + + Search + + + + + + + + + + + + + + + + cancelButton + clicked() + AdvancedSearchDialog + close() + + + 736 + 102 + + + 418 + 64 + + + + + diff --git a/retroshare-gui/src/gui/advsearch/advancedsearchdialog.cpp b/retroshare-gui/src/gui/advsearch/advancedsearchdialog.cpp new file mode 100644 index 000000000..3d60260be --- /dev/null +++ b/retroshare-gui/src/gui/advsearch/advancedsearchdialog.cpp @@ -0,0 +1,154 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2006, 2007 The RetroShare Team +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ + +#include "advancedsearchdialog.h" + +AdvancedSearchDialog::AdvancedSearchDialog(QWidget * parent) : QDialog (parent) +{ + setupUi(this); + dialogLayout = this->layout(); + metrics = new QFontMetrics(this->font()); + + // the list of expressions + expressions = new QList(); + + // a area for holding the objects + expressionsLayout = new QVBoxLayout(); + expressionsLayout->setSpacing(0); + expressionsLayout->setMargin(0); + expressionsLayout->setObjectName(QString::fromUtf8("expressionsLayout")); + expressionsFrame->setSizePolicy(QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding); + expressionsFrame->setLayout(expressionsLayout); + + // we now add the first expression widgets to the dialog via a vertical + // layout + reset();//addNewExpression(); + + connect (this->addExprButton, SIGNAL(clicked()), + this, SLOT(addNewExpression())); + connect (this->resetButton, SIGNAL(clicked()), + this, SLOT(reset())); + connect(this->executeButton, SIGNAL(clicked()), + this, SLOT(prepareSearch())); +} + + +void AdvancedSearchDialog::addNewExpression() +{ + int sizeChange = metrics->height() + 26; + + ExpressionWidget *expr; + if (expressions->size() == 0) + { + //create an initial expression + expr = new ExpressionWidget(expressionsFrame, true); + } else { + expr = new ExpressionWidget(expressionsFrame); + } + + expressions->append(expr); + expressionsLayout->addWidget(expr, 1, Qt::AlignLeft); + + + connect(expr, SIGNAL(signalDelete(ExpressionWidget*)), + this, SLOT(deleteExpression(ExpressionWidget*))); + + //expressionsLayout->invalidate(); + //searchCriteriaBox->setMinimumSize(searchCriteriaBox->minimumWidth(), + // searchCriteriaBox->minimumHeight() + sizeChange); + //searchCriteriaBox->adjustSize(); + expressionsFrame->adjustSize(); + this->setMinimumSize(this->minimumWidth(), this->minimumHeight()+sizeChange); + this->adjustSize(); + +} + +void AdvancedSearchDialog::deleteExpression(ExpressionWidget* expr) +{ + int sizeChange = metrics->height() + 26; + + expressions->removeAll(expr); + expr->hide(); + expressionsLayout->removeWidget(expr); + delete expr; + + expressionsLayout->invalidate(); + //searchCriteriaBox->setMinimumSize(searchCriteriaBox->minimumWidth(), + // searchCriteriaBox->minimumHeight() - sizeChange); + //searchCriteriaBox->adjustSize(); + expressionsFrame->adjustSize(); + this->setMinimumSize(this->minimumWidth(), this->minimumHeight()-sizeChange); + this->adjustSize(); +} + +void AdvancedSearchDialog::reset() +{ + ExpressionWidget *expr; + while (!expressions->isEmpty()) + { + expr = expressions->takeLast(); + deleteExpression(expr); + } + + // now add a new default expressions + addNewExpression(); +} + +void AdvancedSearchDialog::prepareSearch() +{ + emit search(getRsExpr()); +} + + +Expression * AdvancedSearchDialog::getRsExpr() +{ + Expression * wholeExpression; + + // process the special case: first expression + wholeExpression = expressions->at(0)->getRsExpression(); + + + // iterate through the items in elements and + for (int i = 1; i < expressions->size(); ++i) { + // extract the expression information and compound it with the + // first expression + wholeExpression = new CompoundExpression(expressions->at(i)->getOperator(), + wholeExpression, + expressions->at(i)->getRsExpression()); + } + return wholeExpression; +} + +QString AdvancedSearchDialog::getSearchAsString() +{ + QString str = expressions->at(0)->toString(); + + + // iterate through the items in elements and + for (int i = 1; i < expressions->size(); ++i) { + // extract the expression information and compound it with the + // first expression + str += QString(" ") + expressions->at(i)->toString(); + } + return str; +} + diff --git a/retroshare-gui/src/gui/advsearch/advancedsearchdialog.h b/retroshare-gui/src/gui/advsearch/advancedsearchdialog.h new file mode 100644 index 000000000..296829057 --- /dev/null +++ b/retroshare-gui/src/gui/advsearch/advancedsearchdialog.h @@ -0,0 +1,57 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2006, 2007 The RetroShare Team +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ +#ifndef _AdvancedSearch_h_ +#define _AdvancedSearch_h_ + +#include +#include +#include +#include +#include +#include "ui_AdvancedSearchDialog.h" +#include "expressionwidget.h" +#include + +class AdvancedSearchDialog : public QDialog, public Ui::AdvancedSearchDialog +{ + Q_OBJECT + +public: + AdvancedSearchDialog(QWidget * parent = 0 ); + Expression * getRsExpr(); + QString getSearchAsString(); +signals: + void search(Expression*); + +private slots: + void deleteExpression(ExpressionWidget*); + void addNewExpression(); + void reset(); + void prepareSearch(); + +private: + QLayout * dialogLayout; + QVBoxLayout * expressionsLayout; + QList * expressions; + QFontMetrics * metrics; +}; + +#endif // _AdvancedSearch_h_ diff --git a/retroshare-gui/src/gui/advsearch/expressionwidget.cpp b/retroshare-gui/src/gui/advsearch/expressionwidget.cpp new file mode 100644 index 000000000..dfca2c2f5 --- /dev/null +++ b/retroshare-gui/src/gui/advsearch/expressionwidget.cpp @@ -0,0 +1,243 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2006, 2007 The RetroShare Team +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ + +#include "expressionwidget.h" + +ExpressionWidget::ExpressionWidget(QWidget * parent, bool initial) : QWidget(parent) +{ + setupUi(this); + + inRangedConfig = false; + + // the default search type + searchType = NameSearch; + + exprLayout = this->layout(); + + exprOpFrame->setLayout (createLayout()); + exprTermFrame->setLayout (createLayout()); + exprConditionFrame->setLayout (createLayout()); + exprParamFrame->setLayout (createLayout()); + exprParamFrame->setSizePolicy(QSizePolicy::MinimumExpanding, + QSizePolicy::Fixed); + + elements = new QList(); + + exprOpElem = new ExprOpElement(); + exprOpFrame->layout()->addWidget(exprOpElem); + elements->append(exprOpElem); + + exprTermElem = new ExprTermsElement(); + exprTermFrame->layout()->addWidget(exprTermElem); + elements->append(exprTermElem); + connect (exprTermElem, SIGNAL(currentIndexChanged(int)), + this, SLOT (adjustExprForTermType(int))); + + exprCondElem = new ExprConditionElement(searchType); + exprConditionFrame->layout()->addWidget(exprCondElem); + elements->append(exprCondElem); + connect (exprCondElem, SIGNAL (currentIndexChanged(int)), + this, SLOT (adjustExprForConditionType(int))); + + exprParamElem= new ExprParamElement(searchType); + exprParamFrame->layout()->addWidget(exprParamElem); + elements->append(exprParamElem); + + // set up the default search: a search on name + adjustExprForTermType(searchType); + isFirst = initial; + deleteExprButton ->setVisible(!isFirst); + exprOpElem ->setVisible(!isFirst); + exprTermFrame ->show(); + exprConditionFrame ->show(); + exprParamFrame ->show(); + + // connect the delete button signal + connect (deleteExprButton, SIGNAL (clicked()), + this, SLOT(deleteExpression())); + + this->show(); +} + +QLayout * ExpressionWidget::createLayout(QWidget * parent) +{ + QHBoxLayout * hboxLayout; + if (parent == 0) + { + hboxLayout = new QHBoxLayout(); + } else { + hboxLayout = new QHBoxLayout(parent); + } + hboxLayout->setSpacing(0); + hboxLayout->setMargin(0); + return hboxLayout; +} + +bool ExpressionWidget::isStringSearchExpression() +{ + return (searchType == NameSearch || searchType == PathSearch + || searchType == ExtSearch || searchType == HashSearch); +} + +void ExpressionWidget::adjustExprForTermType(int index) +{ + ExprSearchType type = (*GuiExprElement::TermsIndexMap)[index]; + searchType = type; + + // now adjust the relevant elements + // the condition combobox + exprCondElem->adjustForSearchType(type); + + // the parameter expression: can be a date, 1-2 edit fields + // or a size with units etc + exprParamElem->adjustForSearchType(type); + exprParamFrame->adjustSize(); + + exprLayout->invalidate(); + this->adjustSize(); +} + +void ExpressionWidget::adjustExprForConditionType(int newCondition) +{ + // we adjust the appearance for a ranged selection + inRangedConfig = (newCondition == GuiExprElement::RANGE_INDEX); + exprParamElem->setRangedSearch(inRangedConfig); + exprParamFrame->layout()->invalidate(); + exprParamFrame->adjustSize(); +} + +void ExpressionWidget::deleteExpression() +{ + this->hide(); + emit signalDelete(this); +} + +LogicalOperator ExpressionWidget::getOperator() +{ + return exprOpElem->getLogicalOperator(); +} + +static int checkedConversion(uint64_t s) +{ + if(s > 0x7fffffff) + { + std::cerr << "Error: bad convertion from uint64_t s=" << s << " into int" << std::endl; + return 0 ; + } + return (int)s ; +} + +Expression* ExpressionWidget::getRsExpression() +{ + Expression * expr = NULL; + + std::list wordList; + uint64_t lowVal = 0; + uint64_t highVal = 0; + + if (isStringSearchExpression()) + { + QString txt = exprParamElem->getStrSearchValue(); + QStringList words = txt.split(" ", QString::SkipEmptyParts); + for (int i = 0; i < words.size(); ++i) + wordList.push_back(words.at(i).toStdString()); + } else if (inRangedConfig){ + // correct for reversed ranges to be nice to the user + lowVal = exprParamElem->getIntLowValue(); + highVal = exprParamElem->getIntHighValue(); + if (lowVal >highVal) + { + lowVal = lowVal^highVal; // csoler: wow, that is some style! + highVal = lowVal^highVal; + lowVal = lowVal^highVal; + } + } + + switch (searchType) + { + case NameSearch: + expr = new NameExpression(exprCondElem->getStringOperator(), + wordList, + exprParamElem->ignoreCase()); + break; + case PathSearch: + expr = new PathExpression(exprCondElem->getStringOperator(), + wordList, + exprParamElem->ignoreCase()); + break; + case ExtSearch: + expr = new ExtExpression(exprCondElem->getStringOperator(), + wordList, + exprParamElem->ignoreCase()); + break; + case HashSearch: + expr = new HashExpression(exprCondElem->getStringOperator(), + wordList); + break; + case DateSearch: + if (inRangedConfig) { + expr = new DateExpression(exprCondElem->getRelOperator(), checkedConversion(lowVal), checkedConversion(highVal)); + } else { + expr = new DateExpression(exprCondElem->getRelOperator(), checkedConversion(exprParamElem->getIntValue())); + } + break; + case PopSearch: + if (inRangedConfig) { + expr = new DateExpression(exprCondElem->getRelOperator(), checkedConversion(lowVal), checkedConversion(highVal)); + } else { + expr = new DateExpression(exprCondElem->getRelOperator(), checkedConversion(exprParamElem->getIntValue())); + } + break; + case SizeSearch: + if (inRangedConfig) + { + if(lowVal >= (uint64_t)(1024*1024*1024) || highVal >= (uint64_t)(1024*1024*1024)) + expr = new SizeExpressionMB(exprCondElem->getRelOperator(), (int)(lowVal / (1024*1024)), (int)(highVal / (1024*1024))); + else + expr = new SizeExpression(exprCondElem->getRelOperator(), lowVal, highVal); + } + else + { + uint64_t s = exprParamElem->getIntValue() ; + + if(s >= (uint64_t)(1024*1024*1024)) + expr = new SizeExpressionMB(exprCondElem->getRelOperator(), (int)(s/(1024*1024))) ; + else + expr = new SizeExpression(exprCondElem->getRelOperator(), (int)s) ; + } + break; + }; + return expr; +} + +QString ExpressionWidget::toString() +{ + QString str = ""; + if (!isFirst) + { + str += exprOpElem->toString() + " "; + } + str += exprTermElem->toString() + " "; + str += exprCondElem->toString() + " "; + str += exprParamElem->toString(); + return str; +} + diff --git a/retroshare-gui/src/gui/advsearch/expressionwidget.h b/retroshare-gui/src/gui/advsearch/expressionwidget.h new file mode 100644 index 000000000..21f964449 --- /dev/null +++ b/retroshare-gui/src/gui/advsearch/expressionwidget.h @@ -0,0 +1,93 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2006, 2007 The RetroShare Team +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ +#ifndef _ExpressionWidget_h_ +#define _ExpressionWidget_h_ +#include +#include +#include + +#include +#include "guiexprelement.h" +#include "ui_expressionwidget.h" + + +/** + Represents an Advanced Search GUI Expression object which acts as a container + for a series of GuiExprElement objects. The structure of the expression can + change dynamically, dependant on user choices made while assembling an expression. + The default appearance is simply a search on name. +*/ +class ExpressionWidget : public QWidget, public Ui::ExpressionWidget +{ + Q_OBJECT + +public: + ExpressionWidget( QWidget * parent = 0, bool initial=false ); + + /** delivers the expression represented by this widget + the operator to join this expression with any previous + expressions is provided by the getOperator method */ + Expression* getRsExpression(); + + /** supplies the operator to be used when joining this expression + to the whole query */ + LogicalOperator getOperator(); + + QString toString(); + +signals: + /** associates an expression object with the delete event */ + void signalDelete(ExpressionWidget*); + +private slots: + /** emits the signalDelete signal with a pointer to this object + for use by listeners */ + void deleteExpression(); + + /** dynbamically changes the structure of the expression based on + the terms combobox changes */ + void adjustExprForTermType(int); + + /** dynamically adjusts the expression dependant on the choices + made in the condition combobox e.g. inRange and equals + have different parameter fields */ + void adjustExprForConditionType(int); + + +private: + QLayout * createLayout(QWidget* parent = 0); + + bool isStringSearchExpression(); + + QList * elements; + QLayout * exprLayout; + + ExprOpElement * exprOpElem; + ExprTermsElement * exprTermElem; + ExprConditionElement * exprCondElem; + ExprParamElement* exprParamElem; + + bool inRangedConfig; + bool isFirst; + ExprSearchType searchType; +}; + +#endif // _ExpressionWidget_h_ diff --git a/retroshare-gui/src/gui/advsearch/expressionwidget.ui b/retroshare-gui/src/gui/advsearch/expressionwidget.ui new file mode 100644 index 000000000..d4bd4f8bd --- /dev/null +++ b/retroshare-gui/src/gui/advsearch/expressionwidget.ui @@ -0,0 +1,185 @@ + + + ExpressionWidget + + + + 0 + 0 + 800 + 34 + + + + + 0 + 0 + + + + + 800 + 30 + + + + + 16777215 + 55 + + + + Expression Widget + + + + + + false + + + QWidget#ExpressionWidget{ +background: transparent;} + + + + 6 + + + 6 + + + + + + 0 + 0 + + + + + 90 + 26 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + 0 + 0 + + + + + 100 + 26 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + 0 + 0 + + + + + 180 + 26 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + 1 + 0 + + + + + 350 + 26 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + Delete this expression + + + + + + + :/images/delete.png:/images/delete.png + + + + + + + Qt::Horizontal + + + + 0 + 30 + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/advsearch/guiexprelement.cpp b/retroshare-gui/src/gui/advsearch/guiexprelement.cpp new file mode 100644 index 000000000..98bcc9742 --- /dev/null +++ b/retroshare-gui/src/gui/advsearch/guiexprelement.cpp @@ -0,0 +1,642 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2006, 2007 The RetroShare Team +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ + +#include "guiexprelement.h" +#define STR_FIELDS_MIN_WIDTH 200 +#define SIZE_FIELDS_MIN_WIDTH 80 +#define DATE_FIELDS_MIN_WIDTH 100 +#define FIELDS_MIN_HEIGHT 26 + +#define LOGICAL_OP_CB_WIDTH 70 +#define STD_CB_WIDTH 90 +#define CONDITION_CB_WIDTH 170 + +const int GuiExprElement::AND_INDEX = 0; +const int GuiExprElement::OR_INDEX = 1; +const int GuiExprElement::XOR_INDEX = 2; + +const int GuiExprElement::NAME_INDEX = 0; +const int GuiExprElement::PATH_INDEX = 1; +const int GuiExprElement::EXT_INDEX = 2; +const int GuiExprElement::HASH_INDEX = 3; +/*const int GuiExprElement::KEYWORDS_INDEX = ???; +const int GuiExprElement::COMMENTS_INDEX = ???; +const int GuiExprElement::META_INDEX = ???;*/ +const int GuiExprElement::DATE_INDEX = 4; +const int GuiExprElement::SIZE_INDEX = 5; +const int GuiExprElement::POP_INDEX = 6; + +const int GuiExprElement::CONTAINS_INDEX = 0; +const int GuiExprElement::CONTALL_INDEX = 1; +const int GuiExprElement::IS_INDEX = 2; + +const int GuiExprElement::LT_INDEX = 0; +const int GuiExprElement::LTE_INDEX = 1; +const int GuiExprElement::EQUAL_INDEX = 2; +const int GuiExprElement::GTE_INDEX = 3; +const int GuiExprElement::GT_INDEX = 4; +const int GuiExprElement::RANGE_INDEX = 5; + +QStringList * GuiExprElement::exprOpsList = new QStringList(); +QStringList * GuiExprElement::searchTermsOptionsList = new QStringList(); +QStringList * GuiExprElement::stringOptionsList = new QStringList(); +QStringList * GuiExprElement::relOptionsList = new QStringList(); + +QMap * GuiExprElement::TermsIndexMap = new QMap(); + +QMap * GuiExprElement::logicalOpIndexMap = new QMap(); +QMap * GuiExprElement::strConditionIndexMap = new QMap(); +QMap * GuiExprElement::relConditionIndexMap = new QMap(); + +QMap * GuiExprElement::logicalOpStrMap = new QMap(); +QMap * GuiExprElement::termsStrMap = new QMap(); +QMap * GuiExprElement::strConditionStrMap = new QMap(); +QMap * GuiExprElement::relConditionStrMap = new QMap(); + +bool GuiExprElement::initialised = false; + + +GuiExprElement::GuiExprElement(QWidget * parent) + : QWidget(parent) +{ + if (!GuiExprElement::initialised) + { + initialiseOptionsLists(); + } + searchType = NameSearch; + +} + + +void GuiExprElement::initialiseOptionsLists() +{ + const QString AND = tr("and"); + const QString OR = tr("and / or"); + const QString XOR = tr("or"); // exclusive or + + const QString NAME = tr("Name"); + const QString PATH = tr("Path"); + const QString EXT = tr("Extension"); + const QString HASH = tr("Hash"); + //const QString KEYWORDS= tr("Keywords"); + //const QString COMMENTS= tr("Comments"); + //const QString META = tr("Meta"); + const QString DATE = tr("Date"); + const QString SIZE = tr("Size"); + const QString POP = tr("Popularity"); + + const QString CONTAINS= tr("contains"); + const QString CONTALL = tr("contains all"); + const QString IS = tr("is"); + + const QString LT = tr("less than"); + const QString LTE = tr("less than or equal"); + const QString EQUAL = tr("equals"); + const QString GTE = tr("greater than or equal"); + const QString GT = tr("greater than"); + const QString RANGE = tr("is in range"); + + exprOpsList->append(AND); + exprOpsList->append(OR); + exprOpsList->append(XOR); + + GuiExprElement::searchTermsOptionsList->append(NAME); + GuiExprElement::searchTermsOptionsList->append(PATH); + GuiExprElement::searchTermsOptionsList->append(EXT); + GuiExprElement::searchTermsOptionsList->append(HASH); + //GuiExprElement::searchTermsOptionsList->append(KEYWORDS); + //GuiExprElement::searchTermsOptionsList->append(COMMENTS); + //GuiExprElement::searchTermsOptionsList->append(META); + GuiExprElement::searchTermsOptionsList->append(DATE); + GuiExprElement::searchTermsOptionsList->append(SIZE); +// GuiExprElement::searchTermsOptionsList->append(POP); + + GuiExprElement::stringOptionsList->append(CONTAINS); + GuiExprElement::stringOptionsList->append(CONTALL); + GuiExprElement::stringOptionsList->append(IS); + + GuiExprElement::relOptionsList->append(LT); + GuiExprElement::relOptionsList->append(LTE); + GuiExprElement::relOptionsList->append(EQUAL); + GuiExprElement::relOptionsList->append(GTE); + GuiExprElement::relOptionsList->append(GT); + GuiExprElement::relOptionsList->append(RANGE); + + // now the maps + (*GuiExprElement::logicalOpIndexMap)[GuiExprElement::AND_INDEX] = AndOp; + (*GuiExprElement::logicalOpIndexMap)[GuiExprElement::OR_INDEX] = OrOp; + (*GuiExprElement::logicalOpIndexMap)[GuiExprElement::XOR_INDEX] = XorOp; + + (*GuiExprElement::TermsIndexMap)[GuiExprElement::NAME_INDEX] = NameSearch; + (*GuiExprElement::TermsIndexMap)[GuiExprElement::PATH_INDEX] = PathSearch; + (*GuiExprElement::TermsIndexMap)[GuiExprElement::EXT_INDEX] = ExtSearch; + (*GuiExprElement::TermsIndexMap)[GuiExprElement::HASH_INDEX] = HashSearch; + (*GuiExprElement::TermsIndexMap)[GuiExprElement::DATE_INDEX] = DateSearch; + (*GuiExprElement::TermsIndexMap)[GuiExprElement::SIZE_INDEX] = SizeSearch; + (*GuiExprElement::TermsIndexMap)[GuiExprElement::POP_INDEX] = PopSearch; + + (*GuiExprElement::strConditionIndexMap)[GuiExprElement::CONTAINS_INDEX] = ContainsAnyStrings; + (*GuiExprElement::strConditionIndexMap)[GuiExprElement::CONTALL_INDEX] = ContainsAllStrings; + (*GuiExprElement::strConditionIndexMap)[GuiExprElement::IS_INDEX] = EqualsString; + +/* W A R N I N G !!!! + the cb elements correspond to their inverse rel op counterparts in rsexpr.h due to the nature of + the implementation.there + For example consider "size greater than 100kb" selected in the GUI. + The rsexpr.cc impl returns true if the CONDITION specified is greater than the file size passed as argument + as rsexpr iterates through the files. So, the user wants files that are greater than 100kb but the impl returns + files where the condition is greater than the file size i.e. files whose size is less than or equal to the condition + Therefore we invert the mapping of rel conditions here to match the behaviour of the impl. +*/ + (*GuiExprElement::relConditionIndexMap)[GuiExprElement::LT_INDEX] = GreaterEquals; + (*GuiExprElement::relConditionIndexMap)[GuiExprElement::LTE_INDEX] = Greater; + (*GuiExprElement::relConditionIndexMap)[GuiExprElement::EQUAL_INDEX] = Equals; + (*GuiExprElement::relConditionIndexMap)[GuiExprElement::GTE_INDEX] = Smaller; + (*GuiExprElement::relConditionIndexMap)[GuiExprElement::GT_INDEX] = SmallerEquals; + (*GuiExprElement::relConditionIndexMap)[GuiExprElement::RANGE_INDEX] = InRange; + + // the string to index map + (*GuiExprElement::termsStrMap)[GuiExprElement::NAME_INDEX] = NAME; + (*GuiExprElement::termsStrMap)[GuiExprElement::PATH_INDEX] = PATH; + (*GuiExprElement::termsStrMap)[GuiExprElement::EXT_INDEX] = EXT; + (*GuiExprElement::termsStrMap)[GuiExprElement::HASH_INDEX] = HASH; + (*GuiExprElement::termsStrMap)[GuiExprElement::DATE_INDEX] = DATE; + (*GuiExprElement::termsStrMap)[GuiExprElement::SIZE_INDEX] = SIZE; + (*GuiExprElement::termsStrMap)[GuiExprElement::POP_INDEX] = POP; + + (*GuiExprElement::logicalOpStrMap)[GuiExprElement::AND_INDEX] = AND; + (*GuiExprElement::logicalOpStrMap)[GuiExprElement::XOR_INDEX] = XOR; + (*GuiExprElement::logicalOpStrMap)[GuiExprElement::OR_INDEX] = OR; + + (*GuiExprElement::strConditionStrMap)[GuiExprElement::CONTAINS_INDEX] = CONTAINS; + (*GuiExprElement::strConditionStrMap)[GuiExprElement::CONTALL_INDEX] = CONTALL; + (*GuiExprElement::strConditionStrMap)[GuiExprElement::IS_INDEX] = IS; + + (*GuiExprElement::relConditionStrMap)[GuiExprElement::LT_INDEX] = LT; + (*GuiExprElement::relConditionStrMap)[GuiExprElement::LTE_INDEX] = LTE; + (*GuiExprElement::relConditionStrMap)[GuiExprElement::EQUAL_INDEX] = EQUAL; + (*GuiExprElement::relConditionStrMap)[GuiExprElement::GTE_INDEX] = GTE; + (*GuiExprElement::relConditionStrMap)[GuiExprElement::GT_INDEX] = GT; + (*GuiExprElement::relConditionStrMap)[GuiExprElement::RANGE_INDEX] = RANGE; + + + GuiExprElement::initialised = true; +} + +QStringList* GuiExprElement::getConditionOptions(ExprSearchType t) +{ + QStringList * list = new QStringList(); + switch (t) { + case NameSearch: + case PathSearch: + case ExtSearch: + case HashSearch: + list = GuiExprElement::stringOptionsList; + break; + case DateSearch: + case PopSearch: + case SizeSearch: + default: + list = GuiExprElement::relOptionsList; + } + return list; +} + +QHBoxLayout * GuiExprElement::createLayout(QWidget * parent) +{ + QHBoxLayout * hboxLayout; + if (parent == 0) + { + hboxLayout = new QHBoxLayout(); + } else { + hboxLayout = new QHBoxLayout(parent); + } + hboxLayout->setMargin(0); + hboxLayout->setSpacing(0); + return hboxLayout; +} + +bool GuiExprElement::isStringSearchExpression() +{ + return (searchType == NameSearch || searchType == PathSearch + || searchType == ExtSearch || searchType == HashSearch); +} + + +/* ********************************************************************/ +/* *********** L O G I C A L O P E L E M E N T ******************/ +/* ********************************************************************/ +ExprOpElement::ExprOpElement(QWidget * parent) + : GuiExprElement(parent) +{ + internalframe = new QFrame(this); + internalframe->setLayout(createLayout()); + cb = new QComboBox(this); + cb->setMinimumSize(LOGICAL_OP_CB_WIDTH, FIELDS_MIN_HEIGHT); + cb->addItems(*(GuiExprElement::exprOpsList)); + internalframe->layout()->addWidget(cb); +} + +QString ExprOpElement::toString() +{ + return (*GuiExprElement::logicalOpStrMap)[cb->currentIndex()]; +} + + +LogicalOperator ExprOpElement::getLogicalOperator() +{ + return (*GuiExprElement::logicalOpIndexMap)[cb->currentIndex()]; +} + + +/* **********************************************************/ +/* *********** T E R M S E L E M E N T ******************/ +/* **********************************************************/ +ExprTermsElement::ExprTermsElement(QWidget * parent) + : GuiExprElement(parent) +{ + internalframe = new QFrame(this); + internalframe->setLayout(createLayout()); + cb = new QComboBox(this); + cb->setMinimumSize(STD_CB_WIDTH, FIELDS_MIN_HEIGHT); + connect (cb, SIGNAL(currentIndexChanged(int)), + this, SIGNAL(currentIndexChanged(int))); + cb->addItems(*(GuiExprElement::searchTermsOptionsList)); + internalframe->layout()->addWidget(cb); +} +QString ExprTermsElement::toString() +{ + return (*GuiExprElement::termsStrMap)[cb->currentIndex()]; +} + +/* ******************************************************************/ +/* *********** C O N D I T I O N E L E M E N T ******************/ +/* ******************************************************************/ +ExprConditionElement::ExprConditionElement(ExprSearchType type, QWidget * parent) + : GuiExprElement(parent) +{ + internalframe = new QFrame(this); + internalframe->setLayout(createLayout()); + cb = new QComboBox(this); + cb->setMinimumSize(CONDITION_CB_WIDTH, FIELDS_MIN_HEIGHT); + connect (cb, SIGNAL(currentIndexChanged(int)), + this, SIGNAL(currentIndexChanged(int))); + cb->addItems(*(getConditionOptions(type))); + internalframe->layout()->addWidget(cb); +} + + +QString ExprConditionElement::toString() +{ + QString str = ""; + if (isStringSearchExpression()) + { + str = (*GuiExprElement::strConditionStrMap)[cb->currentIndex()]; + } else { + str = (*GuiExprElement::relConditionStrMap)[cb->currentIndex()]; + } + return str; +} + +RelOperator ExprConditionElement::getRelOperator() +{ + return (*GuiExprElement::relConditionIndexMap)[cb->currentIndex()]; +} + +StringOperator ExprConditionElement::getStringOperator() +{ + return (*GuiExprElement::strConditionIndexMap)[cb->currentIndex()]; +} + +void ExprConditionElement::adjustForSearchType(ExprSearchType type) +{ + cb->clear(); + cb->addItems(*(getConditionOptions(type))); + searchType = type; +} + +/* **********************************************************/ +/* *********** P A R A M E L E M E N T ******************/ +/* **********************************************************/ +ExprParamElement::ExprParamElement(ExprSearchType type, QWidget * parent) + : GuiExprElement(parent) +{ + internalframe = new QFrame(this); + internalframe->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + internalframe->setLayout(createLayout()); + inRangedConfig = false; + searchType = type; + adjustForSearchType(type); +} + +QString ExprParamElement::toString() +{ + QString str = ""; + if (isStringSearchExpression()) + { + str = QString("\"") + getStrSearchValue() + QString("\""); + // we don't bother with case if hash search + if (searchType != HashSearch) { + str += (ignoreCase() ? QString(" (ignore case)") + : QString(" (case sensitive)")); + } + } else + { + if (searchType == DateSearch) { + QDateEdit * dateEdit = qFindChild (internalframe, "param1"); + str = dateEdit->text(); + if (inRangedConfig) + { + str += QString(" ") + tr("to") + QString(" "); + dateEdit = qFindChild (internalframe, "param2"); + str += dateEdit->text(); + } + } else if (searchType == SizeSearch) + { + QLineEdit * lineEditSize = qFindChild(internalframe, "param1"); + str = ("" == lineEditSize->text()) ? "0" + : lineEditSize->text(); + QComboBox * cb = qFindChild (internalframe, "unitsCb1"); + str += QString(" ") + cb->itemText(cb->currentIndex()); + if (inRangedConfig) + { + str += QString(" ") + tr("to") + QString(" "); + lineEditSize = qFindChild(internalframe, "param2"); + str += ("" == lineEditSize->text()) ? "0" + : lineEditSize->text(); + cb = qFindChild (internalframe, "unitsCb2"); + str += QString(" ") + cb->itemText(cb->currentIndex()); + } + } + } + return str; +} + + +void ExprParamElement::adjustForSearchType(ExprSearchType type) +{ + // record which search type is active + searchType = type; + QRegExp regExp("0|[1-9][0-9]*"); + numValidator = new QRegExpValidator(regExp, this); + QRegExp hexRegExp("[A-Fa-f0-9]*"); + hexValidator = new QRegExpValidator(hexRegExp, this); + + // remove all elements + QList children = qFindChildren(internalframe); + QWidget* child; + QLayout * lay_out = internalframe->layout(); + while (!children.isEmpty()) + { + child = children.takeLast(); + child->hide(); + lay_out->removeWidget(child); + delete child; + } + delete lay_out; + + QHBoxLayout* hbox = createLayout(); + internalframe->setLayout(hbox); + internalframe->setMinimumSize(320,26); + + if (isStringSearchExpression()) + { + // set up for default of a simple input field + QLineEdit* lineEdit = new QLineEdit(internalframe); + lineEdit->setMinimumSize(STR_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); + lineEdit->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + lineEdit->setObjectName("param1"); + hbox->addWidget(lineEdit); + hbox->addSpacing(9); + QCheckBox* icCb = new QCheckBox(tr("ignore case"), internalframe); + icCb->setObjectName("ignoreCaseCB"); + icCb->setCheckState(Qt::Checked); + // hex search specifics: hidden case sensitivity and hex validator + if (searchType == HashSearch) { + icCb->hide(); + lineEdit->setValidator(hexValidator); + } + hbox->addWidget(icCb); + hbox->addStretch(); + + } else if (searchType == DateSearch) + { + QDateEdit * dateEdit = new QDateEdit(QDate::currentDate(), internalframe); + dateEdit->setMinimumSize(DATE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); + dateEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + dateEdit->setDisplayFormat(tr("dd.MM.yyyy")); + dateEdit->setObjectName("param1"); + dateEdit->setMinimumDate(QDate(1970, 1, 1)); + dateEdit->setMaximumDate(QDate(2099, 12,31)); + hbox->addWidget(dateEdit, Qt::AlignLeft); + hbox->addStretch(); + } else if (searchType == SizeSearch) + { + QLineEdit * lineEdit = new QLineEdit(internalframe); + lineEdit->setMinimumSize(SIZE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); + lineEdit->setMaximumSize(SIZE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); + lineEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + lineEdit->setObjectName("param1"); + lineEdit->setValidator(numValidator); + hbox->addWidget(lineEdit, Qt::AlignLeft); + + QComboBox * cb = new QComboBox(internalframe); + cb->setObjectName("unitsCb1"); + cb-> addItem(tr("KB"), QVariant(1024)); + cb->addItem(tr("MB"), QVariant(1048576)); + cb->addItem(tr("GB"), QVariant(1073741824)); + hbox->addSpacing(9); + internalframe->layout()->addWidget(cb); + hbox->addStretch(); + } + + /* POP Search not implemented + else if (searchType == PopSearch) + { + QLineEdit * lineEdit = new QLineEdit(elem); + lineEdit->setObjectName("param1"); + lineEdit->setValidator(numValidator); + elem->layout()->addWidget(lineEdit); + }*/ + hbox->invalidate(); + internalframe->adjustSize(); + internalframe->show(); + this->adjustSize(); +} + +void ExprParamElement::setRangedSearch(bool ranged) +{ + + if (inRangedConfig == ranged) return; // nothing to do here + inRangedConfig = ranged; + QHBoxLayout* hbox = (dynamic_cast(internalframe->layout())); + + // add additional or remove extra input fields depending on whether + // ranged search or not + if (inRangedConfig) + { + QLabel * toLbl = new QLabel(tr("to")); + toLbl->setMinimumSize(10, FIELDS_MIN_HEIGHT); + toLbl->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + if (searchType == DateSearch) { + internalframe->setMinimumSize(250,26); + QDateEdit * dateEdit = new QDateEdit(QDate::currentDate(), internalframe); + dateEdit->setMinimumSize(DATE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); + dateEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + dateEdit->setObjectName("param2"); + dateEdit->setDisplayFormat(tr("dd.MM.yyyy")); + dateEdit->setMinimumDate(QDate(1970, 1, 1)); + dateEdit->setMaximumDate(QDate(2099, 12,31)); + + hbox->addSpacing(9); + hbox->addWidget(toLbl, Qt::AlignLeft); + hbox->addSpacing(9); + hbox->addWidget(dateEdit, Qt::AlignLeft); + hbox->addStretch(); + } else if (searchType == SizeSearch) { + internalframe->setMinimumSize(340,26); + QLineEdit * lineEdit = new QLineEdit(internalframe); + lineEdit->setMinimumSize(SIZE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); + lineEdit->setMaximumSize(SIZE_FIELDS_MIN_WIDTH, FIELDS_MIN_HEIGHT); + lineEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + lineEdit->setObjectName("param2"); + lineEdit->setValidator(numValidator); + + QComboBox * cb = new QComboBox(internalframe); + cb->setObjectName("unitsCb2"); + cb-> addItem(tr("KB"), QVariant(1024)); + cb->addItem(tr("MB"), QVariant(1048576)); + cb->addItem(tr("GB"), QVariant(1073741824)); + + hbox->addSpacing(9); + hbox->addWidget(toLbl, Qt::AlignLeft); + hbox->addSpacing(9); + hbox->addWidget(lineEdit, Qt::AlignLeft); + hbox->addSpacing(9); + hbox->addWidget(cb); + hbox->addStretch(); + } +// else if (searchType == PopSearch) +// { +// elem->layout()->addWidget(new QLabel(tr("to")), Qt::AlignCenter); +// QLineEdit * lineEdit = new QLineEdit(elem); +// lineEdit->setObjectName("param2"); +// lineEdit->setValidator(numValidator); +// elem->layout()->addWidget(slineEdit); +// } + hbox->invalidate(); + internalframe->adjustSize(); + internalframe->show(); + this->adjustSize(); + } else { + adjustForSearchType(searchType); + } +} + +bool ExprParamElement::ignoreCase() +{ + return (isStringSearchExpression() + && (qFindChild(internalframe, "ignoreCaseCB")) + ->checkState()==Qt::Checked); +} + +QString ExprParamElement::getStrSearchValue() +{ + if (!isStringSearchExpression()) return ""; + + QLineEdit * lineEdit = qFindChild(internalframe, "param1"); + return lineEdit->displayText(); +} + +uint64_t ExprParamElement::getIntValueFromField(QString fieldName, bool isToField,bool *ok) +{ + uint64_t val = 0; + if(ok!=NULL) + *ok=true ; + QString suffix = (isToField) ? "2": "1" ; + + // NOTE qFindChild necessary for MSVC 6 compatibility!! + switch (searchType) + { + case DateSearch: + { + QDateEdit * dateEdit = qFindChild (internalframe, (fieldName + suffix)); + QDateTime * time = new QDateTime(dateEdit->date()); + val = (uint64_t)time->toTime_t(); + break; + } + case SizeSearch: + { + QLineEdit * lineEditSize = qFindChild(internalframe, (fieldName + suffix)); + bool ok2 = false; + val = (lineEditSize->displayText()).toULongLong(&ok2); + if (ok2) + { + QComboBox * cb = qFindChild (internalframe, (QString("unitsCb") + suffix)); + QVariant data = cb->itemData(cb->currentIndex()); + val *= data.toULongLong(); + } + else + if(ok!=NULL) + *ok=false ; + + break; + } + case PopSearch: // not implemented +/* { + QLineEdit * lineEditPop = qFindChild(elem, (fieldName + suffix)); + bool ok = false; + val = (lineEditPop->displayText()).toInt(&ok); + if (!ok) { + val = -1; + } + break; + }*/ + case NameSearch: + case PathSearch: + case ExtSearch: + case HashSearch: + default: + // shouldn't be here...val stays at -1 + if(ok!=NULL) + *ok=false ; + } + + return val; +} + +uint64_t ExprParamElement::getIntValue() +{ + return getIntValueFromField("param"); +} + +uint64_t ExprParamElement::getIntLowValue() +{ + return getIntValue(); +} + +uint64_t ExprParamElement::getIntHighValue() +{ + if (!inRangedConfig) return getIntValue(); + return getIntValueFromField("param", true); +} + diff --git a/retroshare-gui/src/gui/advsearch/guiexprelement.h b/retroshare-gui/src/gui/advsearch/guiexprelement.h new file mode 100644 index 000000000..1cdcf1f2a --- /dev/null +++ b/retroshare-gui/src/gui/advsearch/guiexprelement.h @@ -0,0 +1,208 @@ +/**************************************************************** +* RetroShare is distributed under the following license: +* +* Copyright (C) 2006, 2007 The RetroShare Team +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ +#ifndef _GuiExprElement_h_ +#define _GuiExprElement_h_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +enum ExprSearchType +{ + NameSearch, + PathSearch, + ExtSearch, + HashSearch, + DateSearch, + SizeSearch, + PopSearch + +}; + +class GuiExprElement: public QWidget +{ + Q_OBJECT + +public: + GuiExprElement(QWidget * parent = 0); + virtual void adjustForSearchType(ExprSearchType) {} + virtual ~GuiExprElement(){} + virtual void set(int){} + virtual void set(QObject*){} + bool isStringSearchExpression(); + +/* indices for possible cb options */ + static const int AND_INDEX; + static const int XOR_INDEX; + static const int OR_INDEX; + static const int NAME_INDEX; + static const int PATH_INDEX; + static const int EXT_INDEX; + static const int HASH_INDEX; + static const int KEYWORDS_INDEX; + static const int COMMENTS_INDEX; + static const int META_INDEX; + static const int DATE_INDEX; + static const int SIZE_INDEX; + static const int POP_INDEX; + + static const int CONTAINS_INDEX; + static const int CONTALL_INDEX; + static const int IS_INDEX; + + static const int LT_INDEX; + static const int LTE_INDEX; + static const int EQUAL_INDEX; + static const int GTE_INDEX; + static const int GT_INDEX; + static const int RANGE_INDEX; + + static QMap * TermsIndexMap; + + virtual QString toString(){return QString("");} + +protected: + /** prepare the option lists for use */ + void initialiseOptionsLists(); + + /** provides the appropriate options list for the + condition combobox */ + QStringList* getConditionOptions(ExprSearchType t); + + QHBoxLayout* createLayout(QWidget* parent = 0); + QFrame * internalframe; + + ExprSearchType searchType; + + static bool initialised; + static QStringList * exprOpsList; + static QStringList * searchTermsOptionsList; + static QStringList * stringOptionsList; + static QStringList * relOptionsList; + + // provides a mapping of condition operators to RSExpr reloperators + static QMap * logicalOpIndexMap; + static QMap * strConditionIndexMap; + static QMap * relConditionIndexMap; + + // provides a mapping of indexes to translatable strings + static QMap * logicalOpStrMap; + static QMap * termsStrMap; + static QMap * strConditionStrMap; + static QMap * relConditionStrMap; + + +}; + +/** the Expression operator combobox element */ +class ExprOpElement : public GuiExprElement +{ + Q_OBJECT + +public: + ExprOpElement(QWidget * parent = 0); + LogicalOperator getLogicalOperator(); + QString toString(); +private: + QComboBox * cb; +}; + +/** the Terms combobox element */ +class ExprTermsElement : public GuiExprElement +{ + Q_OBJECT + +public: + ExprTermsElement(QWidget * parent = 0); + int getTermsIndex(); + RelOperator getRelOperator(); + StringOperator getStringOperator(); + void set(int i) {cb->setCurrentIndex(i);} + QString toString(); + +signals: + void currentIndexChanged(int); + +private: + QComboBox * cb; +}; + +/** the Conditions combobox element */ +class ExprConditionElement : public GuiExprElement +{ + Q_OBJECT + +public: + ExprConditionElement(ExprSearchType, QWidget * parent = 0); + RelOperator getRelOperator(); + StringOperator getStringOperator(); + void adjustForSearchType(ExprSearchType); + void set(int i) {cb->setCurrentIndex(i);} + QString toString(); + +signals: + void currentIndexChanged(int); + +private: + QComboBox * cb; +}; + +/** the Parameter element */ +class ExprParamElement : public GuiExprElement +{ + Q_OBJECT + +public: + ExprParamElement(ExprSearchType, QWidget * parent = 0); + QVariant* getRSExprValue(); + void adjustForSearchType(ExprSearchType); + void setRangedSearch(bool ranged = true); + bool ignoreCase(); + QString getStrSearchValue(); + uint64_t getIntValue(); + uint64_t getIntLowValue(); + uint64_t getIntHighValue(); + virtual QString toString(); + +private: + QRegExpValidator * numValidator; + QRegExpValidator * hexValidator; + QFrame * rangeParamsFrame; + bool inRangedConfig; + uint64_t getIntValueFromField(QString fieldName, bool isToField=false,bool *ok = NULL); +}; + +#endif diff --git a/retroshare-gui/src/gui/bwgraph/bwgraph.cpp b/retroshare-gui/src/gui/bwgraph/bwgraph.cpp new file mode 100644 index 000000000..9319f698f --- /dev/null +++ b/retroshare-gui/src/gui/bwgraph/bwgraph.cpp @@ -0,0 +1,315 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#include +#include +#include "bwgraph.h" +#include +#include + +#include +#include +#include + +#define BWGRAPH_LINE_SEND (1u<<0) +#define BWGRAPH_LINE_RECV (1u<<1) +#define SETTING_FILTER "LineFilter" +#define SETTING_OPACITY "Opacity" +#define SETTING_ALWAYS_ON_TOP "AlwaysOnTop" +#define SETTING_STYLE "GraphStyle" +#define DEFAULT_FILTER (BWGRAPH_LINE_SEND|BWGRAPH_LINE_RECV) +#define DEFAULT_ALWAYS_ON_TOP false +#define DEFAULT_OPACITY 100 +#define DEFAULT_STYLE GraphFrame::AreaGraph + +#define ADD_TO_FILTER(f,v,b) (f = ((b) ? ((f) | (v)) : ((f) & ~(v)))) + +/* Define the format used for displaying the date and time */ +#define DATETIME_FMT "MMM dd hh:mm:ss" + +/* Images used in the graph style drop-down */ +#define IMG_AREA_GRAPH ":/images/16x16/graph-area.png" +#define IMG_LINE_GRAPH ":/images/16x16/graph-line.png" + + +/** Default constructor */ +BandwidthGraph::BandwidthGraph(QWidget *parent, Qt::WFlags flags) + : RWindow("BandwidthGraph", parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); +#if defined(Q_WS_WIN) + setShortcut("Esc", SLOT(close())); +#else + setShortcut("Ctrl+W", SLOT(close())); +#endif + + /* Bind events to actions */ + createActions(); + + /* Ask RetroShare core to notify us about bandwidth updates */ + //_rsControl = RetroShare::rsControl(); + //_rsControl->setEvent(REvents::Bandwidth, this, true); + + /* Initialize Sent/Receive data counters */ + reset(); + /* Hide Bandwidth Graph Settings frame */ + showSettingsFrame(false); + /* Load the previously saved settings */ + loadSettings(); + + /* Turn off opacity group on unsupported platforms */ +#if defined(Q_WS_WIN) + if(!(QSysInfo::WV_2000 <= QSysInfo::WindowsVersion && QSysInfo::WindowsVersion <= QSysInfo::WV_2003)) { + ui.frmOpacity->setVisible(false); + } +#endif + +#if defined(Q_WS_X11) + ui.frmOpacity->setVisible(false); +#endif + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(updategraphstatus())); + timer->start(5113); +} + +/** Custom event handler. Checks if the event is a bandwidth update event. If it + * is, it will add the data point to the history and updates the graph. */ +void +BandwidthGraph::customEvent(QEvent *event) +{ + if (event->type() == CustomEventType::BandwidthEvent) { + BandwidthEvent *bw = (BandwidthEvent *)event; + updateGraph(bw->bytesRead(), bw->bytesWritten()); + } +} + +void +BandwidthGraph::timerEvent( QTimerEvent * ) +{ + /* set users/friends/network */ + /*float downKb = 0; + float upKb = 0; + rsicontrol -> ConfigGetDataRates(downKb, upKb); + + updateGraph(downKb,upKb);*/ + +} + +void +BandwidthGraph::updategraphstatus( ) +{ + if(RsAutoUpdatePage::eventsLocked()) + return ; + + /* set users/friends/network */ + float downKb = 0; + float upKb = 0; + rsicontrol -> ConfigGetDataRates(downKb, upKb); + + updateGraph(downKb,upKb); + +} + +/** Binds events to actions. */ +void +BandwidthGraph::createActions() +{ + connect(ui.btnToggleSettings, SIGNAL(toggled(bool)), + this, SLOT(showSettingsFrame(bool))); + + connect(ui.btnReset, SIGNAL(clicked()), + this, SLOT(reset())); + + connect(ui.btnSaveSettings, SIGNAL(clicked()), + this, SLOT(saveChanges())); + + connect(ui.btnCancelSettings, SIGNAL(clicked()), + this, SLOT(cancelChanges())); + + connect(ui.sldrOpacity, SIGNAL(valueChanged(int)), + this, SLOT(setOpacity(int))); +} + +/** Adds new data to the graph. */ +void +BandwidthGraph::updateGraph(qreal bytesRead, qreal bytesWritten) +{ + /* Graph only cares about kilobytes */ + ui.frmGraph->addPoints(bytesRead/*/1024.0*/, bytesWritten/*/1024.0*/); +} + +/** Loads the saved Bandwidth Graph settings. */ +void +BandwidthGraph::loadSettings() +{ + /* Set window opacity slider widget */ + ui.sldrOpacity->setValue(getSetting(SETTING_OPACITY, DEFAULT_OPACITY).toInt()); + setOpacity(ui.sldrOpacity->value()); + + /* Set whether the window appears on top. */ + ui.chkAlwaysOnTop->setChecked(getSetting(SETTING_ALWAYS_ON_TOP, + DEFAULT_ALWAYS_ON_TOP).toBool()); + if (ui.chkAlwaysOnTop->isChecked()) { + setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); + } else { + setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint); + } + + /* Set the line filter checkboxes accordingly */ + uint filter = getSetting(SETTING_FILTER, DEFAULT_FILTER).toUInt(); + ui.chkReceiveRate->setChecked(filter & BWGRAPH_LINE_RECV); + ui.chkSendRate->setChecked(filter & BWGRAPH_LINE_SEND); + + /* Set whether we are plotting bandwidth as area graphs or not */ + int graphStyle = getSetting(SETTING_STYLE, DEFAULT_STYLE).toInt(); + if (graphStyle < 0 || graphStyle >= ui.cmbGraphStyle->count()) { + graphStyle = DEFAULT_STYLE; + } + ui.cmbGraphStyle->setCurrentIndex(graphStyle); + ui.frmGraph->setGraphStyle((GraphFrame::GraphStyle)graphStyle); + + /* Set graph frame settings */ + ui.frmGraph->setShowCounters(ui.chkReceiveRate->isChecked(), + ui.chkSendRate->isChecked()); +} + +/** Resets the log start time. */ +void +BandwidthGraph::reset() +{ + /* Set to current time */ + ui.statusbar->showMessage(tr("Since:") + " " + + QDateTime::currentDateTime() + .toString(DATETIME_FMT)); + /* Reset the graph */ + ui.frmGraph->resetGraph(); +} + +/** Saves the Bandwidth Graph settings and adjusts the graph if necessary. */ +void +BandwidthGraph::saveChanges() +{ + /* Hide the settings frame and reset toggle button */ + showSettingsFrame(false); + + /* Save the opacity and graph style */ + saveSetting(SETTING_OPACITY, ui.sldrOpacity->value()); + saveSetting(SETTING_STYLE, ui.cmbGraphStyle->currentIndex()); + + /* Save the Always On Top setting */ + saveSetting(SETTING_ALWAYS_ON_TOP, ui.chkAlwaysOnTop->isChecked()); + if (ui.chkAlwaysOnTop->isChecked()) { + setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); + } else { + setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint); + } + setOpacity(ui.sldrOpacity->value()); + + /* Save the line filter values */ + uint filter = 0; + ADD_TO_FILTER(filter, BWGRAPH_LINE_RECV, ui.chkReceiveRate->isChecked()); + ADD_TO_FILTER(filter, BWGRAPH_LINE_SEND, ui.chkSendRate->isChecked()); + saveSetting(SETTING_FILTER, filter); + + + /* Update the graph frame settings */ + ui.frmGraph->setShowCounters(ui.chkReceiveRate->isChecked(), + ui.chkSendRate->isChecked()); + ui.frmGraph->setGraphStyle((GraphFrame::GraphStyle)ui.cmbGraphStyle->currentIndex()); + + /* A change in window flags causes the window to disappear, so make sure + * it's still visible. */ + showNormal(); +} + +/** Simply restores the previously saved settings. */ +void +BandwidthGraph::cancelChanges() +{ + /* Hide the settings frame and reset toggle button */ + showSettingsFrame(false); + + /* Reload the settings */ + loadSettings(); +} + +/** Toggles the Settings pane on and off, changes toggle button text. */ +void +BandwidthGraph::showSettingsFrame(bool show) +{ + static QSize minSize = minimumSize(); + + QSize newSize = size(); + if (show) { + /* Extend the bottom of the bandwidth graph and show the settings */ + ui.frmSettings->setVisible(true); + ui.btnToggleSettings->setChecked(true); + ui.btnToggleSettings->setText(tr("Hide Settings")); + + /* 6 = vertical spacing between the settings frame and graph frame */ + newSize.setHeight(newSize.height() + ui.frmSettings->height() + 6); + } else { + /* Shrink the height of the bandwidth graph and hide the settings */ + ui.frmSettings->setVisible(false); + ui.btnToggleSettings->setChecked(false); + ui.btnToggleSettings->setText(tr("Show Settings")); + + /* 6 = vertical spacing between the settings frame and graph frame */ + newSize.setHeight(newSize.height() - ui.frmSettings->height() - 6); + setMinimumSize(minSize); + } + resize(newSize); +} + +/** Sets the opacity of the Bandwidth Graph window. */ +void +BandwidthGraph::setOpacity(int value) +{ + qreal newValue = value / 100.0; + + /* Opacity only supported by Mac and Win32 */ +#if defined(Q_WS_MAC) + this->setWindowOpacity(newValue); + ui.lblPercentOpacity->setText(QString::number(value)); +#elif defined(Q_WS_WIN) + if(QSysInfo::WV_2000 <= QSysInfo::WindowsVersion && QSysInfo::WindowsVersion <= QSysInfo::WV_2003) { + this->setWindowOpacity(newValue); + ui.lblPercentOpacity->setText(QString::number(value)); + } +#else + Q_UNUSED(newValue); +#endif +} + +/** Overloads the default show() slot so we can set opacity. */ +void +BandwidthGraph::showWindow() +{ + /* Load saved settings */ + loadSettings(); + /* Show the window */ + RWindow::showWindow(); +} + diff --git a/retroshare-gui/src/gui/bwgraph/bwgraph.h b/retroshare-gui/src/gui/bwgraph/bwgraph.h new file mode 100644 index 000000000..46bf39332 --- /dev/null +++ b/retroshare-gui/src/gui/bwgraph/bwgraph.h @@ -0,0 +1,84 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _BWGRAPH_H +#define _BWGRAPH_H + +#include +#include +#include + +#include + +#include "ui_bwgraph.h" + +/** Redraw graph every 1000ms **/ +#define REFRESH_RATE 1000 + + +class BandwidthGraph : public RWindow +{ + Q_OBJECT + +public: + /** Default constructor */ + BandwidthGraph(QWidget *parent = 0, Qt::WFlags flags = 0); + +public slots: + /** Overloaded QWidget.show */ + void showWindow(); + +protected: + /** Called to deliver a bandwidth update event from Tor. */ + void customEvent(QEvent *event); + void timerEvent(QTimerEvent*); + +private slots: + /** Adds new data to the graph */ + void updateGraph(qreal bytesRead, qreal bytesWritten); + /** Called when settings button is toggled */ + void showSettingsFrame(bool show); + /** Called when the settings button is toggled */ + void setOpacity(int value); + /** Called when the user saves settings */ + void saveChanges(); + /** Called when the user cancels changes settings */ + void cancelChanges(); + /** Called when the reset button is pressed */ + void reset(); + + void updategraphstatus(); + + +private: + /** Create and bind actions to events **/ + void createActions(); + /** Loads the saved Bandwidth Graph settings */ + void loadSettings(); + + /** Qt Designer generated object */ + Ui::BandwidthGraph ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/bwgraph/bwgraph.ui b/retroshare-gui/src/gui/bwgraph/bwgraph.ui new file mode 100644 index 000000000..34e97a989 --- /dev/null +++ b/retroshare-gui/src/gui/bwgraph/bwgraph.ui @@ -0,0 +1,485 @@ + + + BandwidthGraph + + + + 0 + 0 + 414 + 305 + + + + RetroShare Bandwidth Usage + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + + + 120 + 80 + + + + + 10 + + + + Qt::NoContextMenu + + + QFrame::Box + + + QFrame::Plain + + + + + + + 6 + + + 0 + + + + + Show Settings + + + true + + + + + + + Qt::Horizontal + + + + 21 + 20 + + + + + + + + Reset + + + + + + + + + + 0 + 0 + + + + + 355 + 82 + + + + + 355 + 82 + + + + Qt::NoContextMenu + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + 9 + + + + + 6 + + + 3 + + + + + + 10 + + + + Qt::NoContextMenu + + + + + + Qt::RightToLeft + + + Receive Rate + + + false + + + + + + + + 10 + + + + Qt::NoContextMenu + + + + + + Qt::RightToLeft + + + Send Rate + + + false + + + + + + + Qt::RightToLeft + + + Always on Top + + + + + + + Qt::Vertical + + + + 20 + 21 + + + + + + + + + + 1 + + + 0 + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + + 10 + + + + Style + + + + + + + + + + + + :/images/graph-line.png:/images/graph-line.png + + + + + + + + + :/images/graph-area.png:/images/graph-area.png + + + + + + + + + + Qt::NoContextMenu + + + QFrame::NoFrame + + + QFrame::Plain + + + + 3 + + + 0 + + + + + Qt::NoContextMenu + + + Changes the transparency of the Bandwidth Graph + + + 30 + + + 100 + + + 100 + + + 100 + + + false + + + Qt::Horizontal + + + false + + + QSlider::NoTicks + + + 10 + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 21 + 0 + + + + + + + + + 25 + 0 + + + + + 10 + + + + Qt::NoContextMenu + + + Qt::RightToLeft + + + 100 + + + + + + + + 10 + + + + Qt::NoContextMenu + + + % Opaque + + + + + + + Qt::Horizontal + + + + 21 + 0 + + + + + + + + + + + + + Qt::Vertical + + + + 21 + 20 + + + + + + + + + + Qt::Horizontal + + + + 21 + 20 + + + + + + + + 1 + + + 0 + + + + + Save + + + + + + + Cancel + + + + + + + + + + + + + + + GraphFrame + QFrame +
    gui/graphframe.h
    + 1 +
    +
    + + + + +
    diff --git a/retroshare-gui/src/gui/channels/ChannelDetails.cpp b/retroshare-gui/src/gui/channels/ChannelDetails.cpp new file mode 100644 index 000000000..f1e88c0e5 --- /dev/null +++ b/retroshare-gui/src/gui/channels/ChannelDetails.cpp @@ -0,0 +1,156 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include "ChannelDetails.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +/* Define the format used for displaying the date and time */ +#define DATETIME_FMT "MMM dd hh:mm:ss" + +/** Default constructor */ +ChannelDetails::ChannelDetails(QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyDialog())); + connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(closeinfodlg())); + + ui.applyButton->setToolTip(tr("Close")); + + ui.nameline ->setReadOnly(true); + ui.popline ->setReadOnly(true); + ui.postline ->setReadOnly(true); + ui.IDline ->setReadOnly(true); + ui.DescriptiontextEdit ->setReadOnly(true); + + ui.typeEncrypted->setEnabled(false); + ui.typePrivate->setEnabled(false); + + +} + + +/** + Overloads the default show() slot so we can set opacity*/ + +void +ChannelDetails::show() +{ + //loadSettings(); + if(!this->isVisible()) { + QDialog::show(); + + } +} + +void ChannelDetails::closeEvent (QCloseEvent * event) +{ + QWidget::closeEvent(event); +} + +void ChannelDetails::closeinfodlg() +{ + close(); +} + +void ChannelDetails::showDetails(std::string mChannelId) +{ + cId = mChannelId; + loadChannel(); +} + +void ChannelDetails::loadChannel() +{ + + if (!rsChannels) + { + return; + } + uint32_t flags = 0; + + ChannelInfo ci; + rsChannels->getChannelInfo(cId, ci); + flags = ci.channelFlags; + + // Set Channel Name + ui.nameline->setText(QString::fromStdWString(ci.channelName)); + + // Set Channel Popularity + { + std::ostringstream out; + out << ci.pop; + ui.popline -> setText(QString::fromStdString(out.str())); + } + + // Set Last Channel Post Date + if (ci.lastPost) { + QDateTime qtime; + qtime.setTime_t(ci.lastPost); + QString timestamp = qtime.toString("yyyy-MM-dd hh:mm:ss"); + ui.postline -> setText(timestamp); + } + + // Set Channel ID + ui.IDline->setText(QString::fromStdString(ci.channelId)); + + // Set Channel Description + ui.DescriptiontextEdit->setText(QString::fromStdWString(ci.channelDesc)); + + if (flags |= RS_DISTRIB_PRIVATE) + { + ui.typeEncrypted->setChecked(false); + ui.typePrivate->setChecked(true); + } + else if (flags |= RS_DISTRIB_ENCRYPTED) + { + ui.typeEncrypted->setChecked(true); + ui.typePrivate->setChecked(false); + } + +} + +void ChannelDetails::applyDialog() +{ + + /* reload now */ + loadChannel(); + + /* close the Dialog after the Changes applied */ + closeinfodlg(); + +} + + + diff --git a/retroshare-gui/src/gui/channels/ChannelDetails.h b/retroshare-gui/src/gui/channels/ChannelDetails.h new file mode 100644 index 000000000..87ce1528c --- /dev/null +++ b/retroshare-gui/src/gui/channels/ChannelDetails.h @@ -0,0 +1,68 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CHANNELDETAILS_H +#define _CHANNELDETAILS_H + +#include + +#include "ui_ChannelDetails.h" + +class ChannelDetails : public QDialog +{ + Q_OBJECT + + public: + + /** Default constructor */ + ChannelDetails(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + + void showDetails(std::string mChannelId); + +signals: + void configChanged() ; + +public slots: + /** Overloaded QWidget.show */ + void show(); + +protected: + void closeEvent (QCloseEvent * event); + +private slots: + + void closeinfodlg(); + void applyDialog(); + + +private: + + void loadChannel(); + + std::string cId; + /** Qt Designer generated object */ + Ui::ChannelDetails ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/channels/ChannelDetails.ui b/retroshare-gui/src/gui/channels/ChannelDetails.ui new file mode 100644 index 000000000..f5c8a2549 --- /dev/null +++ b/retroshare-gui/src/gui/channels/ChannelDetails.ui @@ -0,0 +1,174 @@ + + + ChannelDetails + + + + 0 + 0 + 455 + 408 + + + + Channel Details + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + 0 + + + + + :/images/info16.png:/images/info16.png + + + Channel Details + + + + + + Channel Info + + + + + + Channel Name + + + + + + + + + + Popularity + + + + + + + true + + + + + + + Last Post + + + + + + + true + + + + + + + Channel ID + + + + + + + + + + Channel Description + + + + + + + + + Type + + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + + + Private - (Private Publish Key required to view Messages) + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 311 + 20 + + + + + + + + Cancel + + + + + + + OK + + + false + + + true + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/channels/CreateChannel.cpp b/retroshare-gui/src/gui/channels/CreateChannel.cpp new file mode 100644 index 000000000..f7acdfec1 --- /dev/null +++ b/retroshare-gui/src/gui/channels/CreateChannel.cpp @@ -0,0 +1,254 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include + +#include "CreateChannel.h" +#include "gui/common/PeerDefs.h" +#include "util/misc.h" + +#include +#include + +/** Constructor */ +CreateChannel::CreateChannel(QWidget *parent) +: QDialog(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + picture = NULL; + + // connect up the buttons. + connect( ui.cancelButton, SIGNAL( clicked ( bool ) ), this, SLOT( cancelChannel( ) ) ); + connect( ui.createButton, SIGNAL( clicked ( bool ) ), this, SLOT( createChannel( ) ) ); + + connect( ui.LogoButton, SIGNAL(clicked() ), this , SLOT(addChannelLogo())); + connect( ui.ChannelLogoButton, SIGNAL(clicked() ), this , SLOT(addChannelLogo())); + connect( ui.pubKeyShare_cb, SIGNAL( clicked() ), this, SLOT( setShareList( ) )); + connect( ui.keyShareList, SIGNAL(itemChanged( QTreeWidgetItem *, int ) ), + this, SLOT(togglePersonItem( QTreeWidgetItem *, int ) )); + + if(!ui.pubKeyShare_cb->isChecked()){ + + ui.contactsdockWidget->hide(); + this->resize(this->size().width() - ui.contactsdockWidget->size().width(), + this->size().height()); + } + + newChannel(); + +} + +void CreateChannel::show() +{ + //loadSettings(); + if(!this->isVisible()) { + QWidget::show(); + + } +} + +void CreateChannel::setShareList(){ + + if(ui.pubKeyShare_cb->isChecked()){ + this->resize(this->size().width() + ui.contactsdockWidget->size().width(), + this->size().height()); + ui.contactsdockWidget->show(); + + + if (!rsPeers) + { + /* not ready yet! */ + return; + } + + std::list peers; + std::list::iterator it; + + rsPeers->getFriendList(peers); + + /* get a link to the table */ + QTreeWidget *shareWidget = ui.keyShareList; + + QList items; + + for(it = peers.begin(); it != peers.end(); it++) + { + + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(*it, detail)) + { + continue; /* BAD */ + } + + /* make a widget per friend */ + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + + item -> setText(0, PeerDefs::nameWithLocation(detail)); + if (detail.state & RS_PEER_STATE_CONNECTED) { + item -> setTextColor(0,(Qt::darkBlue)); + } + item -> setSizeHint(0, QSize( 17,17 ) ); + + item -> setText(1, QString::fromStdString(detail.id)); + + item -> setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + item -> setCheckState(0, Qt::Unchecked); + + + /* add to the list */ + items.append(item); + } + + /* remove old items */ + shareWidget->clear(); + shareWidget->setColumnCount(1); + + /* add the items in! */ + shareWidget->insertTopLevelItems(0, items); + + shareWidget->update(); /* update display */ + + }else{ + ui.contactsdockWidget->hide(); + this->resize(this->size().width() - ui.contactsdockWidget->size().width(), + this->size().height()); + mShareList.clear(); + } + +} + +void CreateChannel::newChannel() +{ + /* enforce Private for the moment */ + ui.typePrivate->setChecked(true); + + ui.typeEncrypted->setEnabled(true); + + ui.msgAnon->setChecked(true); + ui.msgAuth->setEnabled(false); + ui.msgGroupBox->hide(); +} + +void CreateChannel::createChannel() +{ + QString name = misc::removeNewLine(ui.channelName->text()); + QString desc = ui.channelDesc->toPlainText(); + uint32_t flags = 0; + + if(name.isEmpty()) + { /* error message */ + QMessageBox::warning(this, tr("RetroShare"),tr("Please add a Name"), + QMessageBox::Ok, QMessageBox::Ok); + + return; //Don't add a empty name!! + } + else + + if (ui.typePrivate->isChecked()) + { + flags |= RS_DISTRIB_PRIVATE; + } + else if (ui.typeEncrypted->isChecked()) + { + flags |= RS_DISTRIB_ENCRYPTED; + } + + if (ui.msgAuth->isChecked()) + { + flags |= RS_DISTRIB_AUTHEN_REQ; + } + else if (ui.msgAnon->isChecked()) + { + flags |= RS_DISTRIB_AUTHEN_ANON; + } + QByteArray ba; + QBuffer buffer(&ba); + + if(!picture.isNull()){ + // send chan image + + buffer.open(QIODevice::WriteOnly); + picture.save(&buffer, "PNG"); // writes image into ba in PNG format + } + + if (rsChannels) + { + std::string chId = rsChannels->createChannel(name.toStdWString(), desc.toStdWString(), flags, (unsigned char*)ba.data(), ba.size()); + + if(ui.pubKeyShare_cb->isChecked()) + rsChannels->channelShareKeys(chId, mShareList); + } + + + close(); + return; +} + + +void CreateChannel::togglePersonItem( QTreeWidgetItem *item, int col ) +{ + + /* extract id */ + std::string id = (item -> text(1)).toStdString(); + + /* get state */ + bool checked = (Qt::Checked == item -> checkState(0)); /* alway column 0 */ + + /* call control fns */ + std::list::iterator lit = std::find(mShareList.begin(), mShareList.end(), id); + + if(checked && (lit == mShareList.end())){ + + // make sure ids not added already + mShareList.push_back(id); + + }else + if(lit != mShareList.end()){ + + mShareList.erase(lit); + + } + + return; +} + +void CreateChannel::cancelChannel() +{ + close(); + return; +} + +void CreateChannel::addChannelLogo() +{ + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg)"), fileName)) + { + picture = QPixmap(fileName).scaled(64,64, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + + // to show the selected + ui.ChannelLogoButton->setIcon(picture); + } +} diff --git a/retroshare-gui/src/gui/channels/CreateChannel.h b/retroshare-gui/src/gui/channels/CreateChannel.h new file mode 100644 index 000000000..ab123c6c0 --- /dev/null +++ b/retroshare-gui/src/gui/channels/CreateChannel.h @@ -0,0 +1,63 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _CREATE_CHANNEL_DIALOG_H +#define _CREATE_CHANNEL_DIALOG_H + +#include "ui_CreateChannel.h" + +class CreateChannel : public QDialog +{ + Q_OBJECT + +public: + CreateChannel(QWidget *parent = 0); + +void newChannel(); /* cleanup */ + + /** Qt Designer generated object */ + Ui::CreateChannel ui; + + QPixmap picture; + +public slots: + /** Overloaded QWidget.show */ + void show(); + +private slots: + + /* actions to take.... */ +void createChannel(); +void cancelChannel(); + +void addChannelLogo(); +void setShareList(); +void togglePersonItem(QTreeWidgetItem* item, int col); + +private: + +std::list mShareList; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/channels/CreateChannel.ui b/retroshare-gui/src/gui/channels/CreateChannel.ui new file mode 100644 index 000000000..31dc43fbb --- /dev/null +++ b/retroshare-gui/src/gui/channels/CreateChannel.ui @@ -0,0 +1,482 @@ + + + CreateChannel + + + + 0 + 0 + 703 + 611 + + + + + 0 + 0 + + + + Create a new Channel + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + 0 + + + + + + 16777215 + 64 + + + + QFrame#frame_2{background-image: url(:/images/connect/connectFriendBanner.png);} + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 6 + + + + + + 48 + 48 + + + + + + + + + + :/images/add_channel64.png + + + true + + + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + Name + + + + + + + + + + + + true + + + + 0 + 0 + + + + + 300 + 524287 + + + + + 220 + 0 + + + + + 0 + 0 + + + + check peers you would like to share private publish key with + + + false + + + QDockWidget::NoDockWidgetFeatures + + + Share Key With + + + + + 0 + + + 0 + + + + + + 0 + 4 + + + + + 20 + 0 + + + + + 300 + 16777215 + + + + + 220 + 0 + + + + + 200 + 0 + + + + true + + + + Contacts: + + + + + + + + + + + + + + Description + + + + + + + + + + + + Type: + + + + 0 + + + 6 + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + + + Private - (Private Publish Key required to view Messages) + + + + + + + + + + Allowed Messages + + + + 0 + + + 6 + + + + + Anonymous Messages + + + + + + + Authenticated Messages + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Key Sharing + + + + 0 + + + 6 + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + Share Private Publish Key + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Channel Logo + + + + 6 + + + 6 + + + 6 + + + 2 + + + 6 + + + + + + + + 64 + 64 + + + + + 64 + 64 + + + + +border: 2px solid white; +border-radius: 10px; + + + + + + + + :/images/channels.png:/images/channels.png + + + + 64 + 64 + + + + + + + + Add Channel Logo + + + + :/images/add_image24.png:/images/add_image24.png + + + + + + + Qt::Horizontal + + + + 118 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 238 + 20 + + + + + + + + Cancel + + + + + + + Create + + + true + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/channels/CreateChannelMsg.cpp b/retroshare-gui/src/gui/channels/CreateChannelMsg.cpp new file mode 100644 index 000000000..a289a729f --- /dev/null +++ b/retroshare-gui/src/gui/channels/CreateChannelMsg.cpp @@ -0,0 +1,599 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "CreateChannelMsg.h" +#include "gui/feeds/SubFileItem.h" +#include "util/misc.h" + +#include +#include + +#include + +/** Constructor */ +CreateChannelMsg::CreateChannelMsg(std::string cId) +: QDialog (NULL), mChannelId(cId) ,mCheckAttachment(true), mAutoMediaThumbNail(false) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + connect(buttonBox, SIGNAL(accepted()), this, SLOT(sendMsg())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(cancelMsg())); + + connect(addFileButton, SIGNAL(clicked() ), this , SLOT(addExtraFile())); + connect(addfilepushButton, SIGNAL(clicked() ), this , SLOT(addExtraFile())); + connect(addThumbnailButton, SIGNAL(clicked() ), this , SLOT(addThumbnail())); + connect(thumbNailCb, SIGNAL(toggled(bool)), this, SLOT(allowAutoMediaThumbNail(bool))); + thumbNailCb->setVisible(false); + thumbNailCb->setEnabled(false); +#ifdef CHANNELS_FRAME_CATCHER + fCatcher = new framecatcher(); + thumbNailCb->setVisible(true); + thumbNailCb->setEnabled(true); +#endif + //buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + + setAcceptDrops(true); + + newChannelMsg(); +} + +CreateChannelMsg::~CreateChannelMsg(){ + +#ifdef CHANNELS_FRAME_CATCHER + delete fCatcher; +#endif + +} + +/* Dropping */ + +void CreateChannelMsg::dragEnterEvent(QDragEnterEvent *event) +{ + /* print out mimeType */ + std::cerr << "CreateChannelMsg::dragEnterEvent() Formats"; + std::cerr << std::endl; + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) + { + std::cerr << "Format: " << (*it).toStdString(); + std::cerr << std::endl; + } + + if (event->mimeData()->hasFormat("text/plain")) + { + std::cerr << "CreateChannelMsg::dragEnterEvent() Accepting PlainText"; + std::cerr << std::endl; + event->acceptProposedAction(); + } + else if (event->mimeData()->hasUrls()) + { + std::cerr << "CreateChannelMsg::dragEnterEvent() Accepting Urls"; + std::cerr << std::endl; + event->acceptProposedAction(); + } + else if (event->mimeData()->hasFormat("application/x-rsfilelist")) + { + std::cerr << "CreateChannelMsg::dragEnterEvent() accepting Application/x-qabs..."; + std::cerr << std::endl; + event->acceptProposedAction(); + } + else + { + std::cerr << "CreateChannelMsg::dragEnterEvent() No PlainText/Urls"; + std::cerr << std::endl; + } +} + +void CreateChannelMsg::dropEvent(QDropEvent *event) +{ + if (!(Qt::CopyAction & event->possibleActions())) + { + std::cerr << "CreateChannelMsg::dropEvent() Rejecting uncopyable DropAction"; + std::cerr << std::endl; + + /* can't do it */ + return; + } + + std::cerr << "CreateChannelMsg::dropEvent() Formats" << std::endl; + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) + { + std::cerr << "Format: " << (*it).toStdString(); + std::cerr << std::endl; + } + + if (event->mimeData()->hasText()) + { + std::cerr << "CreateChannelMsg::dropEvent() Plain Text:"; + std::cerr << std::endl; + std::cerr << event->mimeData()->text().toStdString(); + std::cerr << std::endl; + } + + if (event->mimeData()->hasUrls()) + { + std::cerr << "CreateChannelMsg::dropEvent() Urls:" << std::endl; + + QList urls = event->mimeData()->urls(); + QList::iterator uit; + for(uit = urls.begin(); uit != urls.end(); uit++) + { + QString localpath = uit->toLocalFile(); + std::cerr << "Whole URL: " << uit->toString().toStdString() << std::endl; + std::cerr << "or As Local File: " << localpath.toStdString() << std::endl; + + if (localpath.isEmpty() == false) + { + // Check that the file does exist and is not a directory + QDir dir(localpath); + if (dir.exists()) { + std::cerr << "CreateChannelMsg::dropEvent() directory not accepted."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("Directory can't be dropped, only files are accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } else if (QFile::exists(localpath)) { + addAttachment(localpath.toUtf8().constData()); + } else { + std::cerr << "CreateChannelMsg::dropEvent() file does not exists."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("File not found or file name not accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } + } + } + } + else if (event->mimeData()->hasFormat("application/x-rsfilelist")) + { + std::cerr << "CreateChannelMsg::dropEvent() Application/x-rsfilelist"; + std::cerr << std::endl; + + QByteArray data = event->mimeData()->data("application/x-rsfilelist"); + std::cerr << "Data Len:" << data.length(); + std::cerr << std::endl; + std::cerr << "Data is:" << data.data(); + std::cerr << std::endl; + + std::string newattachments(data.data()); + parseRsFileListAttachments(newattachments); + } + + event->setDropAction(Qt::CopyAction); + event->accept(); +} + +void CreateChannelMsg::parseRsFileListAttachments(const std::string &attachList) +{ + /* split into lines */ + QString input = QString::fromStdString(attachList); + + QStringList attachItems = input.split("\n"); + QStringList::iterator it; + QStringList::iterator it2; + + for(it = attachItems.begin(); it != attachItems.end(); it++) + { + std::cerr << "CreateChannelMsg::parseRsFileListAttachments() Entry: "; + + QStringList parts = (*it).split("/"); + + bool ok = false; + quint64 qsize = 0; + + std::string fname; + std::string hash; + uint64_t size = 0; + std::string source; + + int i = 0; + for(it2 = parts.begin(); it2 != parts.end(); it2++, i++) + { + std::cerr << "\"" << it2->toStdString() << "\" "; + switch(i) + { + case 0: + fname = it2->toStdString(); + break; + case 1: + hash = it2->toStdString(); + break; + case 2: + qsize = it2->toULongLong(&ok, 10); + size = qsize; + break; + case 3: + source = it2->toStdString(); + break; + } + } + + std::cerr << std::endl; + + std::cerr << "\tfname: " << fname << std::endl; + std::cerr << "\thash: " << hash << std::endl; + std::cerr << "\tsize: " << size << std::endl; + std::cerr << "\tsource: " << source << std::endl; + + /* basic error checking */ + if ((ok) && (hash.size() == 40)) + { + std::cerr << "Item Ok" << std::endl; + if (source == "Local") + { + addAttachment(hash, fname, size, true, ""); + } + else + { + // TEMP NOT ALLOWED UNTIL FT WORKING. + addAttachment(hash, fname, size, false, source); + } + + } + else + { + std::cerr << "Error Decode: Hash size: " << hash.size() << std::endl; + } + + } +} + + +void CreateChannelMsg::addAttachment(const std::string &hash, const std::string &fname, uint64_t size, bool local, const std::string &srcId) +{ + /* add a SubFileItem to the attachment section */ + std::cerr << "CreateChannelMsg::addAttachment()"; + std::cerr << std::endl; + + /* add widget in for new destination */ + + uint32_t flags = SFI_TYPE_CHANNEL; + if (local) + { + flags |= SFI_STATE_LOCAL; + } + else + { + flags |= SFI_STATE_REMOTE; + } + + SubFileItem *file = new SubFileItem(hash, fname, "", size, flags, srcId); // destroyed when fileFrame (this subfileitem) is destroyed + + mAttachments.push_back(file); + QLayout *layout = fileFrame->layout(); + layout->addWidget(file); + + if (mCheckAttachment) + { + checkAttachmentReady(); + } + + return; +} + + +void CreateChannelMsg::addExtraFile() +{ + /* add a SubFileItem to the attachment section */ + std::cerr << "CreateChannelMsg::addExtraFile() opening file dialog"; + std::cerr << std::endl; + + QStringList files; + if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { + for (QStringList::iterator fileIt = files.begin(); fileIt != files.end(); fileIt++) { + addAttachment((*fileIt).toUtf8().constData()); + } + } +} + + +void CreateChannelMsg::addAttachment(const std::string &path) +{ + /* add a SubFileItem to the attachment section */ + std::cerr << "CreateChannelMsg::addAttachment()"; + std::cerr << std::endl; + + if(mAutoMediaThumbNail) + setThumbNail(path, 2000); + + /* add widget in for new destination */ + uint32_t flags = SFI_TYPE_CHANNEL | SFI_STATE_EXTRA; + + + // check attachment if hash exists already + std::list::iterator it; + + for(it= mAttachments.begin(); it != mAttachments.end(); it++){ + + if((*it)->FilePath() == path){ + QMessageBox::warning(this, tr("RetroShare"), + tr("File already Added and Hashed"), + QMessageBox::Ok, QMessageBox::Ok); + + return; + } + + } + + // channels creates copy of file into channels directory and shares this + + FileInfo fInfo; + rsChannels->channelExtraFileHash(path, mChannelId, fInfo); + + + + + // file is not innitial + SubFileItem *file = new SubFileItem(fInfo.hash, fInfo.fname, fInfo.path, fInfo.size, + flags, mChannelId); // destroyed when fileFrame (this subfileitem) is destroyed + + mAttachments.push_back(file); + QLayout *layout = fileFrame->layout(); + layout->addWidget(file); + + if (mCheckAttachment) + { + checkAttachmentReady(); + } + + return; + +} + + + +bool CreateChannelMsg::setThumbNail(const std::string& path, int frame){ + +#ifdef CHANNELS_FRAME_CATCHER + unsigned char* imageBuffer = NULL; + int width = 0, height = 0, errCode = 0; + int length; + std::string errString; + + if(1 != (errCode = fCatcher->open(path))){ + fCatcher->getError(errCode, errString); + std::cerr << errString << std::endl; + return false; + } + + length = fCatcher->getLength(); + + // make sure frame chosen is at lease a quarter length of video length if not choose quarter length + if(frame < (int) (0.25 * length)) + frame = 0.25 * length; + + if(1 != (errCode = fCatcher->getRGBImage(frame, imageBuffer, width, height))){ + fCatcher->getError(errCode, errString); + std::cerr << errString << std::endl; + return false; + } + + if(imageBuffer == NULL) + return false; + + QImage tNail(imageBuffer, width, height, QImage::Format_RGB32); + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + tNail.save(&buffer, "PNG"); + QPixmap img; + img.loadFromData(ba, "PNG"); + img = img.scaled(thumbnail_label->width(), thumbnail_label->height(), Qt::KeepAspectRatio); + thumbnail_label->setPixmap(img); + + delete[] imageBuffer; + +#endif + + return true; +} + +void CreateChannelMsg::allowAutoMediaThumbNail(bool allowThumbNail){ + + mAutoMediaThumbNail = allowThumbNail; +} + +void CreateChannelMsg::checkAttachmentReady() +{ + std::list::iterator fit; + + mCheckAttachment = false; + + for(fit = mAttachments.begin(); fit != mAttachments.end(); fit++) + { + if (!(*fit)->isHidden()) + { + if (!(*fit)->ready()) + { + /* ensure file is hashed or file will be hashed, thus + * recognized by librs but not correctly by gui (can't + * formally remove it) + */ + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false); + break; + } + } + } + + if (fit == mAttachments.end()) + { + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(true); + } + + /* repeat... */ + int msec_rate = 1000; + QTimer::singleShot( msec_rate, this, SLOT(checkAttachmentReady(void))); +} + + +void CreateChannelMsg::cancelMsg() +{ + std::cerr << "CreateChannelMsg::cancelMsg() :" + << "Deleting EXTRA attachments" << std::endl; + + std::cerr << std::endl; + + std::list::const_iterator it; + + for(it = mAttachments.begin(); it != mAttachments.end(); it++) + rsChannels->channelExtraFileRemove((*it)->FileHash(), mChannelId); + + close(); + return; +} + +void CreateChannelMsg::newChannelMsg() +{ + + if (!rsChannels) + return; + + ChannelInfo ci; + if (!rsChannels->getChannelInfo(mChannelId, ci)) + { + + return; + } + + channelName->setText(QString::fromStdWString(ci.channelName)); +} + + +void CreateChannelMsg::sendMsg() +{ + std::cerr << "CreateChannelMsg::sendMsg()"; + std::cerr << std::endl; + + /* construct message bits */ + std::wstring subject = misc::removeNewLine(subjectEdit->text()).toStdWString(); + std::wstring msg = msgEdit->toPlainText().toStdWString(); + + std::list files; + + std::list::iterator fit; + + for(fit = mAttachments.begin(); fit != mAttachments.end(); fit++) + { + if (!(*fit)->isHidden()) + { + FileInfo fi; + fi.hash = (*fit)->FileHash(); + fi.fname = (*fit)->FileName(); + fi.size = (*fit)->FileSize(); + + files.push_back(fi); + + /* commence downloads - if we don't have the file */ + + if (!(*fit)->done()) + { + if ((*fit)->ready()) + { + (*fit)->download(); + } + // Skips unhashed files. + } + } + } + + sendMessage(subject, msg, files); + +} + +void CreateChannelMsg::sendMessage(std::wstring subject, std::wstring msg, std::list &files) +{ + QString name = misc::removeNewLine(subjectEdit->text()); + + if(name.isEmpty()) + { /* error message */ + QMessageBox::warning(this, tr("RetroShare"), + tr("Please add a Subject"), + QMessageBox::Ok, QMessageBox::Ok); + + return; //Don't add an empty Subject!! + } + else + /* rsChannels */ + if (rsChannels) + { + ChannelMsgInfo msgInfo; + + msgInfo.channelId = mChannelId; + msgInfo.msgId = ""; + + msgInfo.subject = subject; + msgInfo.msg = msg; + msgInfo.files = files; + + QByteArray ba; + QBuffer buffer(&ba); + + if(!picture.isNull()){ + // send chan image + + buffer.open(QIODevice::WriteOnly); + picture.save(&buffer, "PNG"); // writes image into ba in PNG format + msgInfo.thumbnail.image_thumbnail = (unsigned char*) ba.data(); + msgInfo.thumbnail.im_thumbnail_size = ba.size(); + } + + rsChannels->ChannelMessageSend(msgInfo); + } + + close(); + return; + +} + +void CreateChannelMsg::addThumbnail() +{ + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg)"), fileName)) + { + picture = QPixmap(fileName).scaled(156,107, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + + // to show the selected + thumbnail_label->setPixmap(picture); + + std::cerr << "Sending Thumbnail image down the pipe" << std::endl ; + + // send Thumbnail down the pipe for other peers to get it. + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + picture.save(&buffer, "PNG"); // writes image into ba in PNG format + + std::cerr << "Image size = " << ba.size() << std::endl ; + + //updateThumbnail() ; + } +} diff --git a/retroshare-gui/src/gui/channels/CreateChannelMsg.h b/retroshare-gui/src/gui/channels/CreateChannelMsg.h new file mode 100644 index 000000000..e200c23ec --- /dev/null +++ b/retroshare-gui/src/gui/channels/CreateChannelMsg.h @@ -0,0 +1,89 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CREATECHANNELMSG_H +#define _CREATECHANNELMSG_H + +#include "ui_CreateChannelMsg.h" +#include + +#ifdef CHANNELS_FRAME_CATCHER +#include "util/framecatcher.h" +#endif + +class SubFileItem; +class FileInfo; + +class CreateChannelMsg : public QDialog, private Ui::CreateChannelMsg +{ + Q_OBJECT + +public: + /** Default Constructor */ + CreateChannelMsg(std::string cId); + + + /** Default Destructor */ + ~CreateChannelMsg(); + + void addAttachment(const std::string &path); + void addAttachment(const std::string &hash, const std::string &fname, uint64_t size, bool local, const std::string &srcId); + + void newChannelMsg(); + + QPixmap picture; + +protected: +virtual void dragEnterEvent(QDragEnterEvent *event); +virtual void dropEvent(QDropEvent *event); + +private slots: + void addExtraFile(); + void checkAttachmentReady(); + + void cancelMsg(); + void sendMsg(); + + void addThumbnail(); + void allowAutoMediaThumbNail(bool); + +private: + + void parseRsFileListAttachments(const std::string &attachList); + void sendMessage(std::wstring subject, std::wstring msg, std::list &files); + bool setThumbNail(const std::string& path, int frame); + + + std::string mChannelId; + + std::list mAttachments; + + bool mCheckAttachment; + bool mAutoMediaThumbNail; + +#ifdef CHANNELS_FRAME_CATCHER + framecatcher* fCatcher; +#endif + +}; + +#endif + diff --git a/retroshare-gui/src/gui/channels/CreateChannelMsg.ui b/retroshare-gui/src/gui/channels/CreateChannelMsg.ui new file mode 100644 index 000000000..907b167a7 --- /dev/null +++ b/retroshare-gui/src/gui/channels/CreateChannelMsg.ui @@ -0,0 +1,425 @@ + + + CreateChannelMsg + + + + 0 + 0 + 509 + 479 + + + + true + + + New Channel Post + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + 0 + + + + + + 16777215 + 64 + + + + QFrame#frame{background-image: url(:/images/connect/connectFriendBanner.png);} + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + 48 + 48 + + + + + 48 + 48 + + + + + + + :/images/channels.png + + + true + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + 0 + + + + Channel Post + + + + + + + + + 75 + true + + + + Channel Post to: + + + + + + + true + + + true + + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + + + Add File to Attach + + + + :/images/add-share24.png:/images/add-share24.png + + + + + + + Add Channel Thumbnail + + + + :/images/add_image24.png:/images/add_image24.png + + + + + + + + + + 156 + 107 + + + + + 0 + 0 + + + + + + + :/images/thumb-default-video.png + + + + + + + Qt::Horizontal + + + + 12 + 98 + + + + + + + + Message + + + + + + + + + 75 + true + + + + Subject : + + + + + + + + + + + + + + + + + + + + :/images/attachment.png:/images/attachment.png + + + Attachments + + + + + + + + + :/images/attachment.png + + + + + + + + 16777215 + 26 + + + + + 75 + true + + + + Attachments + + + + + + + Qt::Horizontal + + + + 334 + 26 + + + + + + + + + 0 + 0 + + + + + 34 + 34 + + + + + + + + :/images/add-share24.png:/images/add-share24.png + + + + 24 + 24 + + + + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + Auto Thumbnail + + + + + + + Qt::ScrollBarAlwaysOn + + + true + + + + + 0 + 0 + 456 + 260 + + + + + + + + 0 + 0 + + + + true + + + Drag and Drop Files from Search Results + + + QFrame#fileFrame{border: 2px solid black; +background: white;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + + Qt::Vertical + + + + 438 + 137 + + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/channels/EditChanDetails.cpp b/retroshare-gui/src/gui/channels/EditChanDetails.cpp new file mode 100644 index 000000000..ae4cfc375 --- /dev/null +++ b/retroshare-gui/src/gui/channels/EditChanDetails.cpp @@ -0,0 +1,149 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 Christopher Evi-Parker + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include "EditChanDetails.h" + +#include + +#include + +#include "util/misc.h" + +#include +#include +#include + +#define CHAN_DEFAULT_IMAGE ":/images/channels.png" + + +/** Default constructor */ +EditChanDetails::EditChanDetails(QWidget *parent, Qt::WFlags flags, std::string cId) + : QDialog(parent, flags), mChannelId(cId) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyDialog())); + connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(closeinfodlg())); + + connect( ui.LogoButton, SIGNAL(clicked() ), this , SLOT(addChannelLogo())); + connect( ui.ChannelLogoButton, SIGNAL(clicked() ), this , SLOT(addChannelLogo())); + + ui.ChannelLogoButton->setDisabled(true); + ui.LogoButton->setDisabled(true); + + loadChannel(); + +} + + +/** + Overloads the default show() slot so we can set opacity*/ + +void EditChanDetails::show() +{ + + if(!this->isVisible()) { + QDialog::show(); + + } +} + +void EditChanDetails::closeEvent (QCloseEvent * event) +{ + QWidget::closeEvent(event); +} + +void EditChanDetails::closeinfodlg() +{ + close(); +} + + +void EditChanDetails::loadChannel() +{ + + if (!rsChannels) + { + return; + } + + ChannelInfo ci; + rsChannels->getChannelInfo(mChannelId, ci); + + // Set Channel Name + ui.nameline->setText(QString::fromStdWString(ci.channelName)); + + // Set Channel Description + ui.DescriptiontextEdit->setText(QString::fromStdWString(ci.channelDesc)); + + // Set Channel Logo + if(ci.pngImageLen != 0) + { + QPixmap chanImage; + chanImage.loadFromData(ci.pngChanImage, ci.pngImageLen, "PNG"); + ui.ChannelLogoButton->setIcon(QIcon(chanImage)); + } + else + { + QPixmap defaulImage(CHAN_DEFAULT_IMAGE); + ui.ChannelLogoButton->setIcon(QIcon(defaulImage)); + } + +} + +void EditChanDetails::applyDialog() +{ + + if(!rsChannels) + return; + + // if text boxes have not been edited leave alone + if(!ui.nameline->isModified() && !ui.DescriptiontextEdit->document()->isModified()) + return; + + ChannelInfo ci; + + ci.channelName = misc::removeNewLine(ui.nameline->text()).toStdWString(); + ci.channelDesc = ui.DescriptiontextEdit->document()->toPlainText().toStdWString(); + + + /* reload now */ + rsChannels->channelEditInfo(mChannelId, ci); + + /* close the Dialog after the Changes applied */ + closeinfodlg(); + + return; +} + + +void EditChanDetails::addChannelLogo() +{ + QString fileName = QFileDialog::getOpenFileName(this, tr("Load File"), QDir::homePath(), tr("Pictures (*.png *.xpm *.jpg)")); + if(!fileName.isEmpty()) + { + picture = QPixmap(fileName).scaled(64,64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + // to show the selected + ui.ChannelLogoButton->setIcon(picture); + } +} + diff --git a/retroshare-gui/src/gui/channels/EditChanDetails.h b/retroshare-gui/src/gui/channels/EditChanDetails.h new file mode 100644 index 000000000..b5c7b81fe --- /dev/null +++ b/retroshare-gui/src/gui/channels/EditChanDetails.h @@ -0,0 +1,71 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 Christopher Evi-Parker + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _EDITCHANDETAILS_H +#define _EDITCHANDETAILS_H + +#include + +#include "ui_EditChanDetails.h" + +class EditChanDetails : public QDialog +{ + Q_OBJECT + +public: + + /** Default constructor */ + EditChanDetails(QWidget *parent = 0, Qt::WFlags flags = 0, std::string cId = ""); + /** Default destructor */ + +signals: + void configChanged() ; + +public slots: + /** Overloaded QWidget.show */ + void show(); + + +protected: + void closeEvent (QCloseEvent * event); + +private slots: + + void closeinfodlg(); + void applyDialog(); + void addChannelLogo(); + + +private: + + void loadChannel(); + + std::string mChannelId; + + QPixmap picture; + + /** Qt Designer generated object */ + Ui::EditChanDetails ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/channels/EditChanDetails.ui b/retroshare-gui/src/gui/channels/EditChanDetails.ui new file mode 100644 index 000000000..8d2e0a9ca --- /dev/null +++ b/retroshare-gui/src/gui/channels/EditChanDetails.ui @@ -0,0 +1,176 @@ + + + EditChanDetails + + + + 0 + 0 + 436 + 355 + + + + Channel Details + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + + + Qt::Horizontal + + + + 311 + 20 + + + + + + + + Cancel + + + + + + + OK + + + false + + + true + + + + + + + + + 0 + + + + + :/images/info16.png:/images/info16.png + + + Edit Channel Details + + + + + + Channel Info + + + + + + Channel Name + + + + + + + + + + Channel Description + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 118 + 20 + + + + + + + + Add Channel Logo + + + + :/images/add_image24.png:/images/add_image24.png + + + + + + + + 64 + 64 + + + + + 64 + 64 + + + + +border: 2px solid white; +border-radius: 10px; + + + + + + + + :/images/channels.png:/images/channels.png + + + + 64 + 64 + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/channels/ShareKey.cpp b/retroshare-gui/src/gui/channels/ShareKey.cpp new file mode 100644 index 000000000..c348a0467 --- /dev/null +++ b/retroshare-gui/src/gui/channels/ShareKey.cpp @@ -0,0 +1,186 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 Christopher Evi-Parker + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "ShareKey.h" + +#include +#include + +#include +#include + +#include "gui/common/PeerDefs.h" + +ShareKey::ShareKey(QWidget *parent, Qt::WFlags flags, std::string chanId) : + QDialog(parent, flags), mChannelId(chanId) +{ + ui = new Ui::ShareKey(); + ui->setupUi(this); + + + connect( ui->shareButton, SIGNAL( clicked ( bool ) ), this, SLOT( shareKey( ) ) ); + connect( ui->cancelButton, SIGNAL( clicked ( bool ) ), this, SLOT( cancel( ) ) ); + + connect(ui->keyShareList, SIGNAL(itemChanged( QTreeWidgetItem *, int ) ), + this, SLOT(togglePersonItem( QTreeWidgetItem *, int ) )); + + setShareList(); + +} + + +ShareKey::~ShareKey() +{ + delete ui; +} + +void ShareKey::closeEvent (QCloseEvent * event) +{ + QWidget::closeEvent(event); +} + +void ShareKey::changeEvent(QEvent *e) +{ + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + +void ShareKey::shareKey() +{ + + if(!rsChannels) + return; + + if(mShareList.empty()) + { + QMessageBox::warning(this, tr("RetroShare"),tr("Please select at least one peer"), + QMessageBox::Ok, QMessageBox::Ok); + + return; + } + + if(!rsChannels->channelShareKeys(mChannelId, mShareList)){ + + std::cerr << "Failed to share keys!" << std::endl; + + return; + } + + close(); + return; +} + +void ShareKey::cancel() +{ + close(); + return; +} + +void ShareKey::setShareList(){ + + if (!rsPeers) + { + /* not ready yet! */ + return; + } + + std::list peers; + std::list::iterator it; + + rsPeers->getFriendList(peers); + + /* get a link to the table */ + QTreeWidget *shareWidget = ui->keyShareList; + + QList items; + + for(it = peers.begin(); it != peers.end(); it++) + { + + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(*it, detail)) + { + continue; /* BAD */ + } + + /* make a widget per friend */ + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + + item -> setText(0, PeerDefs::nameWithLocation(detail)); + if (detail.state & RS_PEER_STATE_CONNECTED) { + item -> setTextColor(0,(Qt::darkBlue)); + } + item -> setSizeHint(0, QSize( 17,17 ) ); + + item -> setText(1, QString::fromStdString(detail.id)); + + item -> setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + item -> setCheckState(0, Qt::Unchecked); + + + /* add to the list */ + items.append(item); + } + + /* remove old items */ + shareWidget->clear(); + shareWidget->setColumnCount(1); + + /* add the items in! */ + shareWidget->insertTopLevelItems(0, items); + + shareWidget->update(); /* update display */ + +} + +void ShareKey::togglePersonItem( QTreeWidgetItem *item, int col ) +{ + + /* extract id */ + std::string id = (item -> text(1)).toStdString(); + + /* get state */ + bool checked = (Qt::Checked == item -> checkState(0)); /* alway column 0 */ + + /* call control fns */ + std::list::iterator lit = std::find(mShareList.begin(), mShareList.end(), id); + + if(checked && (lit == mShareList.end())){ + + // make sure ids not added already + mShareList.push_back(id); + + }else + if(lit != mShareList.end()){ + + mShareList.erase(lit); + + } + + return; +} + diff --git a/retroshare-gui/src/gui/channels/ShareKey.h b/retroshare-gui/src/gui/channels/ShareKey.h new file mode 100644 index 000000000..b8b6456e1 --- /dev/null +++ b/retroshare-gui/src/gui/channels/ShareKey.h @@ -0,0 +1,43 @@ +#ifndef SHAREKEY_H +#define SHAREKEY_H + +#include + +#include "ui_ShareKey.h" + + +class ShareKey : public QDialog { + Q_OBJECT +public: + /* + *@param chanId The channel id to send request for + */ + ShareKey(QWidget *parent = 0, Qt::WFlags flags = 0, std::string chanId = ""); + ~ShareKey(); + + + +protected: + void changeEvent(QEvent *e); + void closeEvent (QCloseEvent * event); + +private: + + void setShareList(); + + Ui::ShareKey *ui; + + std::string mChannelId; + std::list mShareList; + + +private slots: + + void shareKey(); + void cancel(); + void togglePersonItem(QTreeWidgetItem* item, int col); + + +}; + +#endif // SHAREKEY_H diff --git a/retroshare-gui/src/gui/channels/ShareKey.ui b/retroshare-gui/src/gui/channels/ShareKey.ui new file mode 100644 index 000000000..f61f64444 --- /dev/null +++ b/retroshare-gui/src/gui/channels/ShareKey.ui @@ -0,0 +1,251 @@ + + + ShareKey + + + + 0 + 0 + 472 + 347 + + + + Share Channel + + + + 0 + + + 0 + + + + + + + + 239 + 49 + + + + QFrame#frame{background-image: url(:/images/connect/connectFriendBanner.png); +} + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + + + + 64 + 64 + + + + + + + :/images/user/agt_forum64.png + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + true + + + + 0 + 0 + + + + + 52487 + 524287 + + + + + 220 + 0 + + + + + 0 + 0 + + + + check peers you would like to share private publish key with + + + false + + + QDockWidget::NoDockWidgetFeatures + + + Share for Friend + + + + + 0 + + + 0 + + + + + + 0 + 4 + + + + + 20 + 0 + + + + + 1677215 + 16777215 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16 + 16 + + + + true + + + + Contacts: + + + + + + + + + + + + QLayout::SetDefaultConstraint + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Share + + + + + + + Cancel + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/chat/ChatStyle.cpp b/retroshare-gui/src/gui/chat/ChatStyle.cpp new file mode 100644 index 000000000..8b6955d8b --- /dev/null +++ b/retroshare-gui/src/gui/chat/ChatStyle.cpp @@ -0,0 +1,515 @@ +/**************************************************************** + * + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, Thunder + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* Directory tree for stylesheets: + + Install version: /stylesheets + Portable version: /stylesheets + + stylesheets + +history + |-Style1 + |-Style2 + +private + |-Style1 + |-Style2 + +public + |-Style1 + |-Style2 + + Files and dirs of the style: + info.xml - description + incoming.htm - incoming messages + outgoing.htm - outgoing messages + hincoming.htm - incoming history messages + houtgoing.htm - outgoing history messages + ooutgoing.htm - outgoing offline messages (private chat) + main.css - stylesheet + + variants - directory with variants (optional) + +- *.css - Stylesheets for the variants + + Example: + info.xml + + + + + + Author + E-Mail + + + + incoming.htm + + %time% + %name% + %message% + + outgoing.htm + + %time% + %name% + %message% + + main.css + .incomingTime { + color:#C00000; + } + .incomingName{ + color:#2D84C9; + } + .outgoingTime { + color:#C00000; + } + .outgoingName{ + color:#2D84C9; + } + : + more definitions for history and offline messages + + See standard styles in retroshare-gui/src/gui/qss/chat/ +*/ + +#include + +#include "ChatStyle.h" +#include "gui/settings/rsharesettings.h" +#include "gui/notifyqt.h" +#include "gui/common/Emoticons.h" + +#include + +enum enumGetStyle +{ + GETSTYLE_INCOMING, + GETSTYLE_OUTGOING, + GETSTYLE_HINCOMING, + GETSTYLE_HOUTGOING, + GETSTYLE_OOUTGOING +}; + +/* Default constructor */ +ChatStyle::ChatStyle() : QObject() +{ + m_styleType = TYPE_UNKNOWN; + + connect(NotifyQt::getInstance(), SIGNAL(chatStyleChanged(int)), SLOT(styleChanged(int))); +} + +/* Destructor. */ +ChatStyle::~ChatStyle() +{ +} + +void ChatStyle::styleChanged(int styleType) +{ + if (m_styleType == styleType) { + setStyleFromSettings(m_styleType); + } +} + +bool ChatStyle::setStylePath(const QString &stylePath, const QString &styleVariant) +{ + m_styleType = TYPE_UNKNOWN; + + m_styleDir.setPath(QApplication::applicationDirPath()); + if (m_styleDir.cd(stylePath) == false) { + m_styleDir = QDir(""); + m_styleVariant.clear(); + return false; + } + + m_styleVariant = styleVariant; + + return true; +} + +bool ChatStyle::setStyleFromSettings(enumStyleType styleType) +{ + QString stylePath; + QString styleVariant; + + switch (styleType) { + case TYPE_PUBLIC: + Settings->getPublicChatStyle(stylePath, styleVariant); + break; + case TYPE_PRIVATE: + Settings->getPrivateChatStyle(stylePath, styleVariant); + break; + case TYPE_HISTORY: + Settings->getHistoryChatStyle(stylePath, styleVariant); + break; + case TYPE_UNKNOWN: + return false; + } + + bool result = setStylePath(stylePath, styleVariant); + + m_styleType = styleType; + + // reset cache + for (int i = 0; i < FORMATMSG_COUNT; i++) { + m_style[i].clear(); + } + + return result; +} + +static QString getStyle(const QDir &styleDir, const QString &styleVariant, enumGetStyle type) +{ + QString style; + + if (styleDir == QDir("")) { + return ""; + } + + QFile fileHtml; + switch (type) { + case GETSTYLE_INCOMING: + fileHtml.setFileName(QFileInfo(styleDir, "incoming.htm").absoluteFilePath()); + break; + case GETSTYLE_OUTGOING: + fileHtml.setFileName(QFileInfo(styleDir, "outgoing.htm").absoluteFilePath()); + break; + case GETSTYLE_HINCOMING: + fileHtml.setFileName(QFileInfo(styleDir, "hincoming.htm").absoluteFilePath()); + break; + case GETSTYLE_HOUTGOING: + fileHtml.setFileName(QFileInfo(styleDir, "houtgoing.htm").absoluteFilePath()); + break; + case GETSTYLE_OOUTGOING: + fileHtml.setFileName(QFileInfo(styleDir, "ooutgoing.htm").absoluteFilePath()); + break; + default: + return ""; + } + + if (fileHtml.open(QIODevice::ReadOnly)) { + style = fileHtml.readAll(); + fileHtml.close(); + + QFile fileCss(QFileInfo(styleDir, "main.css").absoluteFilePath()); + QString css; + if (fileCss.open(QIODevice::ReadOnly)) { + css = fileCss.readAll(); + fileCss.close(); + } + + if (styleVariant.isEmpty() == false) { + QFile fileCssVariant(QFileInfo(styleDir, "variants/" + styleVariant + ".css").absoluteFilePath()); + QString cssVariant; + if (fileCssVariant.open(QIODevice::ReadOnly)) { + cssVariant = fileCssVariant.readAll(); + fileCssVariant.close(); + + css += "\n" + cssVariant; + } + } + + style.replace("%css-style%", css); + } + + return style; +} + +QString ChatStyle::formatMessage(enumFormatMessage type, const QString &name, const QDateTime ×tamp, const QString &message, unsigned int flag) +{ + QString style = m_style[type]; + + if (style.isEmpty()) { + switch (type) { + case FORMATMSG_INCOMING: + style = getStyle(m_styleDir, m_styleVariant, GETSTYLE_INCOMING); + break; + case FORMATMSG_OUTGOING: + style = getStyle(m_styleDir, m_styleVariant, GETSTYLE_OUTGOING); + break; + case FORMATMSG_HINCOMING: + style = getStyle(m_styleDir, m_styleVariant, GETSTYLE_HINCOMING); + break; + case FORMATMSG_HOUTGOING: + style = getStyle(m_styleDir, m_styleVariant, GETSTYLE_HOUTGOING); + break; + case FORMATMSG_OOUTGOING: + style = getStyle(m_styleDir, m_styleVariant, GETSTYLE_OOUTGOING); + break; + } + + if (style.isEmpty()) { + // default style + style = "
    %name%%time%
    %message%
    "; + } + + m_style[type] = style; + } + + unsigned int formatFlag = 0; + if (flag & CHAT_FORMATMSG_EMBED_SMILEYS) { + formatFlag |= RSHTML_FORMATTEXT_EMBED_SMILEYS; + } + if (flag & CHAT_FORMATMSG_EMBED_LINKS) { + formatFlag |= RSHTML_FORMATTEXT_EMBED_LINKS; + } + + QString msg = RsHtml::formatText(message, formatFlag); + +// //replace http://, https:// and www. with links +// QRegExp rx("(retroshare://[^ <>]*)|(https?://[^ <>]*)|(www\\.[^ <>]*)"); +// int count = 0; +// int pos = 100; //ignore the first 100 char because of the standard DTD ref +// while ( (pos = rx.indexIn(message, pos)) != -1 ) { +// //we need to look ahead to see if it's already a well formed link +// if (message.mid(pos - 6, 6) != "href=\"" && message.mid(pos - 6, 6) != "href='" && message.mid(pos - 6, 6) != "ttp://" ) { +// QString tempMessg = message.left(pos) + "" + rx.cap(count) + "" + message.mid(pos + rx.matchedLength(), -1); +// message = tempMessg; +// } +// pos += rx.matchedLength() + 15; +// count ++; +// } + +// { +// QHashIterator i(smileys); +// while(i.hasNext()) +// { +// i.next(); +// foreach(QString code, i.key().split("|")) +// message.replace(code, ""); +// } +// } + + QString formatMsg = style.replace("%name%", name) + .replace("%date%", timestamp.date().toString("dd.MM.yyyy")) + .replace("%time%", timestamp.time().toString("hh:mm:ss")) + .replace("%message%", msg); + + return formatMsg; +} + +static bool getStyleInfo(QString stylePath, QString stylePathRelative, ChatStyleInfo &info) +{ + // Initialize info + info = ChatStyleInfo(); + + QFileInfo file(stylePath, "info.xml"); + + QFile xmlFile(file.filePath()); + if (xmlFile.open(QIODevice::ReadOnly) == false) { + // No info file found + return false; + } + + QXmlStreamReader reader; + reader.setDevice(&xmlFile); + + while (reader.atEnd() == false) { + reader.readNext(); + if (reader.isStartElement()) { + if (reader.name() == "RetroShare_Style") { + if (reader.attributes().value("version") == "1.0") { + info.stylePath = stylePathRelative; + continue; + } + // Not the right format of the xml file; + return false ; + } + + if (info.stylePath.isEmpty()) { + continue; + } + + if (reader.name() == "style") { + // read style information + while (reader.atEnd() == false) { + reader.readNext(); + if (reader.isEndElement()) { + if (reader.name() == "style") { + break; + } + continue; + } + if (reader.isStartElement()) { + if (reader.name() == "name") { + info.styleName = reader.readElementText(); + continue; + } + if (reader.name() == "description") { + info.styleDescription = reader.readElementText(); + continue; + } + // ingore all other entries + } + } + continue; + } + + if (reader.name() == "author") { + // read author information + while (reader.atEnd() == false) { + reader.readNext(); + if (reader.isEndElement()) { + if (reader.name() == "author") { + break; + } + continue; + } + if (reader.isStartElement()) { + if (reader.name() == "name") { + info.authorName = reader.readElementText(); + continue; + } + if (reader.name() == "email") { + info.authorEmail = reader.readElementText(); + continue; + } + // ingore all other entries + } + } + continue; + } + // ingore all other entries + } + } + + if (reader.hasError()) { + return false; + } + + if (info.stylePath.isEmpty()) { + return false; + } + return true; +} + +static QString getBaseDir() +{ + // application path + std::string configDir = RsInit::RsConfigDirectory(); + QString baseDir = QString::fromStdString(configDir); + +#ifdef WIN32 + if (RsInit::isPortable ()) { + // application dir for portable version + baseDir = QApplication::applicationDirPath(); + } +#endif + + return baseDir; +} + +/*static*/ bool ChatStyle::getAvailableStyles(enumStyleType styleType, QList &styles) +{ + styles.clear(); + + // base dir + QDir baseDir(getBaseDir()); + + ChatStyleInfo standardInfo; + QString stylePath; + + switch (styleType) { + case TYPE_PUBLIC: + if (getStyleInfo(":/qss/chat/public", ":/qss/chat/public", standardInfo)) { + standardInfo.styleDescription = tr("Standard style for group chat"); + styles.append(standardInfo); + } + stylePath = "stylesheets/public"; + break; + case TYPE_PRIVATE: + if (getStyleInfo(":/qss/chat/private", ":/qss/chat/private", standardInfo)) { + standardInfo.styleDescription = tr("Standard style for private chat"); + styles.append(standardInfo); + } + stylePath = "stylesheets/private"; + break; + case TYPE_HISTORY: + if (getStyleInfo(":/qss/chat/history", ":/qss/chat/history", standardInfo)) { + standardInfo.styleDescription = tr("Standard style for history"); + styles.append(standardInfo); + } + stylePath = "stylesheets/history"; + break; + case TYPE_UNKNOWN: + default: + return false; + } + + QDir dir(baseDir); + if (dir.cd(stylePath) == false) { + // no user styles available + return true; + } + + // get all style directories + QFileInfoList dirList = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name); + + // iterate style directories and get info + for (QFileInfoList::iterator dir = dirList.begin(); dir != dirList.end(); dir++) { + ChatStyleInfo info; + if (getStyleInfo(dir->absoluteFilePath(), baseDir.relativeFilePath(dir->absoluteFilePath()), info)) { + styles.append(info); + } + } + + return true; +} + +/*static*/ bool ChatStyle::getAvailableVariants(const QString &stylePath, QStringList &variants) +{ + variants.clear(); + + if (stylePath.isEmpty()) { + return false; + } + + // application path + QDir dir(QApplication::applicationDirPath()); + if (dir.cd(stylePath) == false) { + // style not found + return false; + } + + if (dir.cd("variants") == false) { + // no variants available + return true; + } + + // get all variants + QStringList filters; + filters.append("*.css"); + QFileInfoList fileList = dir.entryInfoList(filters, QDir::Files, QDir::Name); + + // iterate variants + for (QFileInfoList::iterator file = fileList.begin(); file != fileList.end(); file++) { + variants.append(file->baseName()); + } + + return true; +} diff --git a/retroshare-gui/src/gui/chat/ChatStyle.h b/retroshare-gui/src/gui/chat/ChatStyle.h new file mode 100644 index 000000000..c1c1f2009 --- /dev/null +++ b/retroshare-gui/src/gui/chat/ChatStyle.h @@ -0,0 +1,105 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, Thunder + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _CHATSTYLE_H +#define _CHATSTYLE_H + +#include +#include +#include +#include +#include + +/* Flags for ChatStyle::formatMessage */ +#define CHAT_FORMATMSG_EMBED_SMILEYS 1 +#define CHAT_FORMATMSG_EMBED_LINKS 2 + +/* Flags for ChatStyle::formatText */ +#define CHAT_FORMATTEXT_EMBED_SMILEYS 1 +#define CHAT_FORMATTEXT_EMBED_LINKS 2 + +#define FORMATMSG_COUNT 5 + +class ChatStyleInfo +{ +public: + ChatStyleInfo() {} + +public: + QString stylePath; + QString styleName; + QString styleDescription; + QString authorName; + QString authorEmail; +}; + +Q_DECLARE_METATYPE(ChatStyleInfo) + +class ChatStyle : public QObject +{ + Q_OBJECT + +public: + enum enumFormatMessage + { + FORMATMSG_INCOMING = 0, + FORMATMSG_OUTGOING = 1, + FORMATMSG_HINCOMING = 2, + FORMATMSG_HOUTGOING = 3, + FORMATMSG_OOUTGOING = 4, + // FORMATMSG_COUNT + }; + + enum enumStyleType + { + TYPE_UNKNOWN, + TYPE_PUBLIC, + TYPE_PRIVATE, + TYPE_HISTORY + }; + +public: + /* Default constructor */ + ChatStyle(); + /* Default destructor */ + ~ChatStyle(); + + bool setStylePath(const QString &stylePath, const QString &styleVariant); + bool setStyleFromSettings(enumStyleType styleType); + + QString formatMessage(enumFormatMessage type, const QString &name, const QDateTime ×tamp, const QString &message, unsigned int flag); + + static bool getAvailableStyles(enumStyleType styleType, QList &styles); + static bool getAvailableVariants(const QString &stylePath, QStringList &variants); + +private slots: + void styleChanged(int styleType); + +private: + enumStyleType m_styleType; + QDir m_styleDir; + QString m_styleVariant; + + QString m_style[FORMATMSG_COUNT]; +}; + +#endif // _CHATSTYLE_H diff --git a/retroshare-gui/src/gui/chat/HandleRichText.cpp b/retroshare-gui/src/gui/chat/HandleRichText.cpp new file mode 100644 index 000000000..63a7f00c5 --- /dev/null +++ b/retroshare-gui/src/gui/chat/HandleRichText.cpp @@ -0,0 +1,218 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, Thomas Kister + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include "HandleRichText.h" +#include "gui/RetroShareLink.h" + +namespace RsHtml { + +EmbedInHtmlImg defEmbedImg; + +void EmbedInHtmlImg::InitFromAwkwardHash(const QHash< QString, QString >& hash) +{ + QString newRE; + for(QHash::const_iterator it = hash.begin(); it != hash.end(); ++it) + foreach(QString smile, it.key().split("|")) { + if (smile.isEmpty()) { + continue; + } + smileys.insert(smile, it.value()); + newRE += "(" + QRegExp::escape(smile) + ")|"; + } + newRE.chop(1); // remove last | + myRE.setPattern(newRE); +} + +/** + * Parses a DOM tree and replaces text by HTML tags. + * The tree is traversed depth-first, but only through children of Element type + * nodes. Any other kind of node is terminal. + * + * If the node is of type Text, its data is checked against the user-provided + * regular expression. If there is a match, the text is cut in three parts: the + * preceding part that will be inserted before, the part to be replaced, and the + * following part which will be itself checked against the regular expression. + * + * The part to be replaced is sent to a user-provided functor that will create + * the necessary embedding and return a new Element node to be inserted. + * + * @param[in] doc The whole DOM tree, necessary to create new nodes + * @param[in,out] currentElement The current node (which is of type Element) + * @param[in] embedInfos The regular expression and the type of embedding to use + */ +static void embedHtml(QDomDocument& doc, QDomElement& currentElement, EmbedInHtml& embedInfos) +{ + if(embedInfos.myRE.pattern().length() == 0) // we'll get stuck with an empty regexp + return; + + QDomNodeList children = currentElement.childNodes(); + for(uint index = 0; index < children.length(); index++) { + QDomNode node = children.item(index); + if(node.isElement()) { + // child is an element, we skip it if it's an tag + QDomElement element = node.toElement(); + if(element.tagName().toLower() == "head") { + // skip it + } else if (element.tagName().toLower() == "a") { + // skip it, but add title if not available + if (element.attribute("title").isEmpty()) { + RetroShareLink link(element.attribute("href")); + QString title = link.title(); + if (!title.isEmpty()) { + element.setAttribute("title", title); + } + } + } else { + embedHtml(doc, element, embedInfos); + } + } + else if(node.isText()) { + // child is a text, we parse it + QString tempText = node.toText().data(); + if(embedInfos.myRE.indexIn(tempText) == -1) + continue; + + // there is at least one link inside, we start replacing + int currentPos = 0; + int nextPos = 0; + while((nextPos = embedInfos.myRE.indexIn(tempText, currentPos)) != -1) { + // if nextPos == 0 it means the text begins by a link + if(nextPos > 0) { + QDomText textPart = doc.createTextNode(tempText.mid(currentPos, nextPos - currentPos)); + currentElement.insertBefore(textPart, node); + index++; + } + + // inserted tag + QDomElement insertedTag; + switch(embedInfos.myType) { + case Ahref: + { + insertedTag = doc.createElement("a"); + insertedTag.setAttribute("href", embedInfos.myRE.cap(0)); + + RetroShareLink link(embedInfos.myRE.cap(0)); + QString title = link.title(); + if (!title.isEmpty()) { + insertedTag.setAttribute("title", title); + } + + insertedTag.appendChild(doc.createTextNode(embedInfos.myRE.cap(0))); + } + break; + case Img: + { + insertedTag = doc.createElement("img"); + const EmbedInHtmlImg& embedImg = static_cast(embedInfos); + insertedTag.setAttribute("src", embedImg.smileys[embedInfos.myRE.cap(0)]); + } + break; + } + currentElement.insertBefore(insertedTag, node); + + currentPos = nextPos + embedInfos.myRE.matchedLength(); + index++; + } + + // text after the last link, only if there's one, don't touch the index + // otherwise decrement the index because we're going to remove node + if(currentPos < tempText.length()) { + QDomText textPart = doc.createTextNode(tempText.mid(currentPos)); + currentElement.insertBefore(textPart, node); + } + else + index--; + + currentElement.removeChild(node); + } + } +} + +QString formatText(const QString &text, unsigned int flag) +{ + if (flag == 0 || text.isEmpty()) { + // nothing to do + return text; + } + + QDomDocument doc; + if (doc.setContent(text) == false) { + // convert text with QTextBrowser + QTextBrowser textBrowser; + textBrowser.setText(text); + doc.setContent(textBrowser.toHtml()); + } + + QDomElement body = doc.documentElement(); + if (flag & RSHTML_FORMATTEXT_EMBED_SMILEYS) { + embedHtml(doc, body, defEmbedImg); + } + if (flag & RSHTML_FORMATTEXT_EMBED_LINKS) { + EmbedInHtmlAhref defEmbedAhref; + embedHtml(doc, body, defEmbedAhref); + } + + return doc.toString(-1); // -1 removes any annoying carriage return misinterpreted by QTextEdit +} + +static void findElements(QDomDocument& doc, QDomElement& currentElement, const QString& nodeName, const QString& nodeAttribute, QStringList &elements) +{ + if(nodeName.isEmpty()) { + return; + } + + QDomNodeList children = currentElement.childNodes(); + for (uint index = 0; index < children.length(); index++) { + QDomNode node = children.item(index); + if (node.isElement()) { + QDomElement element = node.toElement(); + if (QString::compare(element.tagName(), nodeName, Qt::CaseInsensitive) == 0) { + if (nodeAttribute.isEmpty()) { + // use text + elements.append(element.text()); + } else { + QString attribute = element.attribute(nodeAttribute); + if (attribute.isEmpty() == false) { + elements.append(attribute); + } + } + continue; + } + findElements(doc, element, nodeName, nodeAttribute, elements); + } + } +} + +bool findAnchors(const QString &text, QStringList& urls) +{ + QDomDocument doc; + if (doc.setContent(text) == false) { + return false; + } + + QDomElement body = doc.documentElement(); + findElements(doc, body, "a", "href", urls); + + return true; +} + +} // namespace RsHtml diff --git a/retroshare-gui/src/gui/chat/HandleRichText.h b/retroshare-gui/src/gui/chat/HandleRichText.h new file mode 100644 index 000000000..e5a2c046f --- /dev/null +++ b/retroshare-gui/src/gui/chat/HandleRichText.h @@ -0,0 +1,117 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, Thomas Kister + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/** + * This file provides helper functions and functors for translating data from/to + * rich text format and HTML. Its main goal is to facilitate decoding of chat + * messages, particularly embedding special information into HTML tags. + */ + + +#ifndef HANDLE_RICH_TEXT_H_ +#define HANDLE_RICH_TEXT_H_ + + +#include +#include + +/* Flags for RsHtml::formatText */ +#define RSHTML_FORMATTEXT_EMBED_SMILEYS 1 +#define RSHTML_FORMATTEXT_EMBED_LINKS 2 + +namespace RsHtml { + + +/** + * The type of embedding we'd like to do + */ +enum EmbeddedType +{ + Ahref, ///< into + Img, ///< into +}; + + +/** + * Base class for storing information about a given kind of embedding. + * + * Its only constructor is protected so it is impossible to instantiate it, and + * at the same time derived classes have to provide a type. + */ +class EmbedInHtml +{ +protected: + EmbedInHtml(EmbeddedType newType) : + myType(newType) + {} + +public: + const EmbeddedType myType; + QRegExp myRE; +}; + + +/** + * This class is used to store information for embedding links into tags. + */ +class EmbedInHtmlAhref : public EmbedInHtml +{ +public: + EmbedInHtmlAhref() : + EmbedInHtml(Ahref) + { + myRE.setPattern("(\\bretroshare://[^\\s]*)|(\\bhttps?://[^\\s]*)|(\\bwww\\.[^\\s]*)"); + } +}; + + + +/** + * This class is used to store information for embedding smileys into tags. + * + * By default the QRegExp the variables are empty, which means it must be + * filled at runtime, typically when the smileys set is loaded. It can be + * either done by hand or by using one of the helper methods available. + * + * Note: The QHash uses only *one* smiley per key (unlike soon-to-be-upgraded + * code out there). + */ +class EmbedInHtmlImg : public EmbedInHtml +{ +public: + EmbedInHtmlImg() : + EmbedInHtml(Img) + {} + + void InitFromAwkwardHash(const QHash& hash); + + QHash smileys; +}; + +extern EmbedInHtmlImg defEmbedImg; + +QString formatText(const QString &text, unsigned int flag); +bool findAnchors(const QString &text, QStringList& urls); + +} // namespace RsHtml + + +#endif // HANDLE_RICH_TEXT_H_ diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp new file mode 100644 index 000000000..57dccf91e --- /dev/null +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp @@ -0,0 +1,1273 @@ +/**************************************************************** + * + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PopupChatDialog.h" +#include "PopupChatWindow.h" +#include "gui/RetroShareLink.h" +#include "util/misc.h" +#include "rshare.h" + +#include +#include +#include +#include "retroshare/rsinit.h" +#include +#include +#include +#include "gui/settings/rsharesettings.h" +#include "gui/settings/RsharePeerSettings.h" +#include "gui/notifyqt.h" +#include "../RsAutoUpdatePage.h" +#include "gui/common/StatusDefs.h" +#include "gui/common/Emoticons.h" +#include "gui/im_history/ImHistoryBrowser.h" + +#include "gui/feeds/AttachFileItem.h" +#include "gui/msgs/MessageComposer.h" +#include "gui/common/PeerDefs.h" + +#include + +#define appDir QApplication::applicationDirPath() + +#define WINDOW(This) dynamic_cast(This->window()) + +/***** + * #define CHAT_DEBUG 1 + *****/ + +static std::map chatDialogs; + +// play sound when recv a message +void playsound() +{ + Settings->beginGroup("Sound"); + Settings->beginGroup("SoundFilePath"); + QString OnlineSound = Settings->value("NewChatMessage","").toString(); + Settings->endGroup(); + Settings->beginGroup("Enable"); + bool flag = Settings->value("NewChatMessage",false).toBool(); + Settings->endGroup(); + Settings->endGroup(); + + if (!OnlineSound.isEmpty() && flag) { + if (QSound::isAvailable()) { + QSound::play(OnlineSound); + } + } +} + +/** Default constructor */ +PopupChatDialog::PopupChatDialog(const std::string &id, const QString &name, QWidget *parent, Qt::WFlags flags) + : QWidget(parent, flags), dialogId(id), dialogName(name), + lastChatTime(0), lastChatName("") + +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + newMessages = false; + typing = false; + m_manualDelete = false; + peerStatus = 0; + + last_status_send_time = 0 ; + chatStyle.setStyleFromSettings(ChatStyle::TYPE_PRIVATE); + + /* Hide or show the frames */ + showAvatarFrame(PeerSettings->getShowAvatarFrame(dialogId)); + ui.infoframe->setVisible(false); + ui.statusmessagelabel->hide(); + + connect(ui.avatarFrameButton, SIGNAL(toggled(bool)), this, SLOT(showAvatarFrame(bool))); + + connect(ui.sendButton, SIGNAL(clicked( ) ), this, SLOT(sendChat( ) )); + connect(ui.addFileButton, SIGNAL(clicked() ), this , SLOT(addExtraFile())); + + connect(ui.textboldButton, SIGNAL(clicked()), this, SLOT(setFont())); + connect(ui.textunderlineButton, SIGNAL(clicked()), this, SLOT(setFont())); + connect(ui.textitalicButton, SIGNAL(clicked()), this, SLOT(setFont())); + connect(ui.attachPictureButton, SIGNAL(clicked()), this, SLOT(addExtraPicture())); + connect(ui.fontButton, SIGNAL(clicked()), this, SLOT(getFont())); + connect(ui.colorButton, SIGNAL(clicked()), this, SLOT(setColor())); + connect(ui.emoteiconButton, SIGNAL(clicked()), this, SLOT(smileyWidget())); + connect(ui.actionSave_Chat_History, SIGNAL(triggered()), this, SLOT(fileSaveAs())); + connect(ui.actionClearOfflineMessages, SIGNAL(triggered()), this, SLOT(clearOfflineMessages())); + + + connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(const QString&, int)), this, SLOT(updateStatus(const QString&, int))); + connect(NotifyQt::getInstance(), SIGNAL(peerHasNewCustomStateString(const QString&, const QString&)), this, SLOT(updatePeersCustomStateString(const QString&, const QString&))); + + connect(ui.chattextEdit,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenu(QPoint))); + + // Create the status bar + resetStatusBar(); + + ui.textboldButton->setIcon(QIcon(QString(":/images/edit-bold.png"))); + ui.textunderlineButton->setIcon(QIcon(QString(":/images/edit-underline.png"))); + ui.textitalicButton->setIcon(QIcon(QString(":/images/edit-italic.png"))); + ui.fontButton->setIcon(QIcon(QString(":/images/fonts.png"))); + ui.emoteiconButton->setIcon(QIcon(QString(":/images/emoticons/kopete/kopete020.png"))); + + ui.textboldButton->setCheckable(true); + ui.textunderlineButton->setCheckable(true); + ui.textitalicButton->setCheckable(true); + + setAcceptDrops(true); + ui.chattextEdit->setAcceptDrops(false); + + QMenu * toolmenu = new QMenu(); + toolmenu->addAction(ui.actionClear_Chat_History); + toolmenu->addAction(ui.actionDelete_Chat_History); + toolmenu->addAction(ui.actionSave_Chat_History); + toolmenu->addAction(ui.actionClearOfflineMessages); + toolmenu->addAction(ui.actionMessageHistory); + //toolmenu->addAction(ui.action_Disable_Emoticons); + ui.pushtoolsButton->setMenu(toolmenu); + + mCurrentColor.setNamedColor(PeerSettings->getPrivateChatColor(dialogId)); + mCurrentFont.fromString(PeerSettings->getPrivateChatFont(dialogId)); + + colorChanged(mCurrentColor); + fontChanged(mCurrentFont); + + updateAvatar() ; + updatePeerAvatar(id) ; + + // load settings + processSettings(true); + + // load style + PeerSettings->getStyle(dialogId, "PopupChatDialog", style); + + // initialize first status + StatusInfo peerStatusInfo; + // No check of return value. Non existing status info is handled as offline. + rsStatus->getStatus(dialogId, peerStatusInfo); + updateStatus(QString::fromStdString(dialogId), peerStatusInfo.status); + + StatusInfo ownStatusInfo; + if (rsStatus->getOwnStatus(ownStatusInfo)) { + updateStatus(QString::fromStdString(ownStatusInfo.id), ownStatusInfo.status); + } + + // initialize first custom state string + QString customStateString = QString::fromUtf8(rsMsgs->getCustomStateString(dialogId).c_str()); + updatePeersCustomStateString(QString::fromStdString(dialogId), customStateString); + + if (Settings->valueFromGroup("Chat", QString::fromUtf8("PrivateChat_History"), true).toBool()) { + historyKeeper.init(QString::fromStdString(RsInit::RsProfileConfigDirectory()) + "/chat_" + QString::fromStdString(dialogId) + ".xml"); + + // get offline chat messages + std::list offlineChat; + std::list::iterator offineChatIt; + rsMsgs->getPrivateChatQueueCount(false) && rsMsgs->getPrivateChatQueue(false, dialogId, offlineChat); + + QList historyItems; + int messageCount = Settings->getPrivateChatHistoryCount(); + if (messageCount > 0) { + historyKeeper.getMessages(historyItems, messageCount); + } + foreach(IMHistoryItem item, historyItems) { + for(offineChatIt = offlineChat.begin(); offineChatIt != offlineChat.end(); offineChatIt++) { + /* are they public? */ + if ((offineChatIt->chatflags & RS_CHAT_PRIVATE) == 0) { + /* this should not happen */ + continue; + } + + QDateTime sendTime = QDateTime::fromTime_t(offineChatIt->sendTime); + QString message = QString::fromStdWString(offineChatIt->msg); + + if (IMHistoryKeeper::compareItem(item, false, offineChatIt->rsid, sendTime, message)) { + // don't show offline message out of the history + break; + } + } + + if (offineChatIt == offlineChat.end()) { + addChatMsg(item.incoming, item.id, item.name, item.sendTime, item.recvTime, item.messageText, TYPE_HISTORY, false); + } + } + } + + ui.chattextEdit->installEventFilter(this); + + // call once + onPrivateChatChanged(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_ADD, true); + +#ifdef RS_RELEASE_VERSION + ui.attachPictureButton->setVisible(false); +#endif +} + +/** Destructor. */ +PopupChatDialog::~PopupChatDialog() +{ + // save settings + processSettings(false); + + PopupChatWindow *window = WINDOW(this); + if (window) { + window->removeDialog(this); + window->calculateTitle(NULL); + } + + std::map::iterator it; + if (chatDialogs.end() != (it = chatDialogs.find(dialogId))) { + chatDialogs.erase(it); + } +} + +void PopupChatDialog::processSettings(bool bLoad) +{ + Settings->beginGroup(QString("ChatDialog")); + + if (bLoad) { + // load settings + + // state of splitter + ui.chatsplitter->restoreState(Settings->value("ChatSplitter").toByteArray()); + } else { + // save settings + + // state of splitter + Settings->setValue("ChatSplitter", ui.chatsplitter->saveState()); + } + + Settings->endGroup(); +} + +/*static*/ PopupChatDialog *PopupChatDialog::getExistingInstance(const std::string &id) +{ + std::map::iterator it; + if (chatDialogs.end() != (it = chatDialogs.find(id))) { + /* exists already */ + return it->second; + } + + return NULL; +} + +/*static*/ PopupChatDialog *PopupChatDialog::getPrivateChat(const std::string &id, uint chatflags) +{ + /* see if it exists already */ + PopupChatDialog *popupchatdialog = getExistingInstance(id); + if (popupchatdialog == NULL) { + if (chatflags & RS_CHAT_OPEN) { + RsPeerDetails sslDetails; + if (rsPeers->getPeerDetails(id, sslDetails)) { + popupchatdialog = new PopupChatDialog(id, PeerDefs::nameWithLocation(sslDetails)); + chatDialogs[id] = popupchatdialog; + + PopupChatWindow *window = PopupChatWindow::getWindow(false); + window->addDialog(popupchatdialog); + } + } + } + + if (popupchatdialog == NULL) { + return NULL; + } + + popupchatdialog->insertChatMsgs(); + + PopupChatWindow *window = WINDOW(popupchatdialog); + if (window) { + window->showDialog(popupchatdialog, chatflags); + } + + return popupchatdialog; +} + +/*static*/ void PopupChatDialog::cleanupChat() +{ + PopupChatWindow::cleanup(); + + /* PopupChatDialog destuctor removes the entry from the map */ + std::list list; + + std::map::iterator it; + for (it = chatDialogs.begin(); it != chatDialogs.end(); it++) { + if (it->second) { + list.push_back(it->second); + } + } + + chatDialogs.clear(); + + std::list::iterator it1; + for (it1 = list.begin(); it1 != list.end(); it1++) { + delete (*it1); + } +} + +/*static*/ void PopupChatDialog::privateChatChanged(int list, int type) +{ + if (list == NOTIFY_LIST_PRIVATE_INCOMING_CHAT && type == NOTIFY_TYPE_ADD) { + std::list ids; + if (rsMsgs->getPrivateChatQueueIds(true, ids)) { + uint chatflags = Settings->getChatFlags(); + + std::list::iterator id; + for (id = ids.begin(); id != ids.end(); id++) { + PopupChatDialog *pcd = getPrivateChat(*id, chatflags); + + if (pcd) { + pcd->insertChatMsgs(); + } + } + } + } + + /* now notify all open priavate chat windows */ + std::map::iterator it; + for (it = chatDialogs.begin (); it != chatDialogs.end(); it++) { + if (it->second) { + it->second->onPrivateChatChanged(list, type); + } + } +} + +void PopupChatDialog::chatFriend(const std::string &id) +{ + if (id.empty()){ + return; + } + std::cerr<<" popup dialog chat friend 1"<getPeerDetails(id, detail)) { + return; + } + + std::string firstId; + + if (detail.isOnlyGPGdetail) { + //let's get the ssl child details, and open all the chat boxes + std::list sslIds; + rsPeers->getSSLChildListOfGPGId(detail.gpg_id, sslIds); + for (std::list::iterator it = sslIds.begin(); it != sslIds.end(); it++) { + if (firstId.empty()) { + firstId = *it; + } + + RsPeerDetails sslDetails; + if (rsPeers->getPeerDetails(*it, sslDetails)) { + if (sslDetails.state & RS_PEER_STATE_CONNECTED) { + getPrivateChat(*it, RS_CHAT_OPEN | RS_CHAT_FOCUS); + return; + } + } + } + } else { + if (detail.state & RS_PEER_STATE_CONNECTED) { + getPrivateChat(id, RS_CHAT_OPEN | RS_CHAT_FOCUS); + return; + } + firstId = id; + } + + /* info dialog */ + QMessageBox mb(QMessageBox::Question, tr("Friend not Online"), tr("Your Friend is offline \nDo you want to send them a Message instead"), QMessageBox::Yes | QMessageBox::No); + mb.setWindowIcon(QIcon(":/images/rstray3.png")); + if (mb.exec() == QMessageBox::Yes) { + MessageComposer::msgFriend(id, false); + } else { + if (firstId.empty() == false) { + getPrivateChat(firstId, RS_CHAT_OPEN | RS_CHAT_FOCUS); + } + } +} + +/*static*/ void PopupChatDialog::updateAllAvatars() +{ + for(std::map::const_iterator it(chatDialogs.begin());it!=chatDialogs.end();++it) + it->second->updateAvatar() ; +} + +void PopupChatDialog::focusDialog() +{ + ui.chattextEdit->setFocus(); +} + +void PopupChatDialog::pasteLink() +{ + std::cerr << "In paste link" << std::endl ; + ui.chattextEdit->insertHtml(RSLinkClipboard::toHtml()) ; +} + +void PopupChatDialog::contextMenu( QPoint point ) +{ + std::cerr << "In context menu" << std::endl ; + + QMenu *contextMnu = ui.chattextEdit->createStandardContextMenu(); + + contextMnu->addSeparator(); + QAction *action = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink())); + action->setDisabled(RSLinkClipboard::empty()); + + contextMnu->exec(QCursor::pos()); + delete(contextMnu); +} + +void PopupChatDialog::resetStatusBar() +{ + ui.statusLabel->clear(); + ui.typingpixmapLabel->clear(); + + typing = false; + + PopupChatWindow *window = WINDOW(this); + if (window) { + window->calculateTitle(this); + } +} + +void PopupChatDialog::updateStatusTyping() +{ + if (time(NULL) - last_status_send_time > 5) // limit 'peer is typing' packets to at most every 10 sec + { +#ifdef ONLY_FOR_LINGUIST + tr("is typing..."); +#endif + + rsMsgs->sendStatusString(dialogId, "is typing..."); + last_status_send_time = time(NULL) ; + } +} + +// Called by libretroshare through notifyQt to display the peer's status +// +void PopupChatDialog::updateStatusString(const QString& peer_id, const QString& status_string) +{ + QString status = QString::fromStdString(rsPeers->getPeerName(peer_id.toStdString())) + " " + tr(status_string.toAscii()); + ui.statusLabel->setText(status); // displays info for 5 secs. + ui.typingpixmapLabel->setPixmap(QPixmap(":images/typing.png") ); + + if (status_string == "is typing...") { + typing = true; + + PopupChatWindow *window = WINDOW(this); + if (window) { + window->calculateTitle(this); + } + } + + QTimer::singleShot(5000,this,SLOT(resetStatusBar())) ; +} + +void PopupChatDialog::resizeEvent(QResizeEvent *event) +{ + // Workaround: now the scroll position is correct calculated + QScrollBar *scrollbar = ui.textBrowser->verticalScrollBar(); + scrollbar->setValue(scrollbar->maximum()); +} + +void PopupChatDialog::activate() +{ + PopupChatWindow *window = WINDOW(this); + if (window) { + if (window->isActiveWindow()) { + newMessages = false; + window->calculateTitle(this); + focusDialog(); + } + } else { + newMessages = false; + } +} + +void PopupChatDialog::onPrivateChatChanged(int list, int type, bool initial /*= false*/) +{ + if (list == NOTIFY_LIST_PRIVATE_OUTGOING_CHAT) { + switch (type) { + case NOTIFY_TYPE_ADD: + { + m_savedOfflineChat.clear(); + + QString name = QString::fromUtf8(rsPeers->getPeerName(rsPeers->getOwnId()).c_str()); + + std::list offlineChat; + if (rsMsgs->getPrivateChatQueueCount(false) && rsMsgs->getPrivateChatQueue(false, dialogId, offlineChat)) { + ui.actionClearOfflineMessages->setEnabled(true); + + std::list::iterator it; + for(it = offlineChat.begin(); it != offlineChat.end(); it++) { + /* are they public? */ + if ((it->chatflags & RS_CHAT_PRIVATE) == 0) { + /* this should not happen */ + continue; + } + + m_savedOfflineChat.push_back(*it); + + QDateTime sendTime = QDateTime::fromTime_t(it->sendTime); + QDateTime recvTime = QDateTime::fromTime_t(it->recvTime); + QString message = QString::fromStdWString(it->msg); + + bool existingMessage; + bool showMessage; + if (initial) { + // show all messages on startup + existingMessage = true; + showMessage = true; + } else { + int hiid; + existingMessage = historyKeeper.findMessage(false, it->rsid, sendTime, message, hiid); + showMessage = !existingMessage; + } + + if (showMessage) { + addChatMsg(false, it->rsid, name, sendTime, recvTime, message, TYPE_OFFLINE, !existingMessage); + } + } + } + } + break; + case NOTIFY_TYPE_DEL: + { + if (m_manualDelete == false) { + QString name = QString::fromUtf8(rsPeers->getPeerName(rsPeers->getOwnId()).c_str()); + + // now show saved offline chat messages as sent + std::list::iterator it; + for(it = m_savedOfflineChat.begin(); it != m_savedOfflineChat.end(); it++) { + QDateTime sendTime = QDateTime::fromTime_t(it->sendTime); + QDateTime recvTime = QDateTime::fromTime_t(it->recvTime); + QString message = QString::fromStdWString(it->msg); + + addChatMsg(false, it->rsid, name, sendTime, recvTime, message, TYPE_NORMAL, false); + } + } + + m_savedOfflineChat.clear(); + } + break; + } + + ui.actionClearOfflineMessages->setEnabled(!m_savedOfflineChat.empty()); + } +} + +void PopupChatDialog::insertChatMsgs() +{ + std::list newchat; + if (!rsMsgs->getPrivateChatQueue(true, dialogId, newchat)) + { +#ifdef PEERS_DEBUG + std::cerr << "no chat for " << dialogId << " available." << std::endl ; +#endif + return; + } + + std::list::iterator it; + for(it = newchat.begin(); it != newchat.end(); it++) { + /* are they public? */ + if ((it->chatflags & RS_CHAT_PRIVATE) == 0) { + /* this should not happen */ + continue; + } + + addChatMsg(true, it->rsid, QString::fromStdString(rsPeers->getPeerName(it->rsid)), QDateTime::fromTime_t(it->sendTime), QDateTime::fromTime_t(it->recvTime), QString::fromStdWString(it->msg), TYPE_NORMAL, true); + } + + rsMsgs->clearPrivateChatQueue(true, dialogId); + + playsound(); + + PopupChatWindow *window = WINDOW(this); + if (window) { + window->alertDialog(this); + } + + if (isVisible() == false || (window && window->isActiveWindow() == false)) { + newMessages = true; + + if (window) { + window->calculateTitle(this); + } + } +} + +void PopupChatDialog::addChatMsg(bool incoming, const std::string &id, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &message, enumChatType chatType, bool addToHistory) +{ + std::string ownId = rsPeers->getOwnId(); + +#ifdef CHAT_DEBUG + std::cout << "PopupChatDialog:addChatMsg message : " << message.toStdString() << std::endl; +#endif + + unsigned int formatFlag = CHAT_FORMATMSG_EMBED_LINKS; + + // embed smileys ? + if (Settings->valueFromGroup(QString("Chat"), QString::fromUtf8("Emoteicons_PrivatChat"), true).toBool()) { + formatFlag |= CHAT_FORMATMSG_EMBED_SMILEYS; + } + + ChatStyle::enumFormatMessage type; + if (chatType == TYPE_OFFLINE) { + type = ChatStyle::FORMATMSG_OOUTGOING; + } else if (chatType == TYPE_HISTORY) { + type = incoming ? ChatStyle::FORMATMSG_HINCOMING : ChatStyle::FORMATMSG_HOUTGOING; + } else { + type = incoming ? ChatStyle::FORMATMSG_INCOMING : ChatStyle::FORMATMSG_OUTGOING; + } + + QString formatMsg = chatStyle.formatMessage(type, name, recvTime, message, formatFlag); + + if (addToHistory) { + historyKeeper.addMessage(incoming, id, name, sendTime, recvTime, message); + } + + ui.textBrowser->append(formatMsg); + + /* Scroll to the end */ + QScrollBar *scrollbar = ui.textBrowser->verticalScrollBar(); + scrollbar->setValue(scrollbar->maximum()); + + resetStatusBar(); +} + +bool PopupChatDialog::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == ui.chattextEdit) { + if (event->type() == QEvent::KeyPress) { + updateStatusTyping() ; + + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent && (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)) { + // Enter pressed + if (Settings->getChatSendMessageWithCtrlReturn()) { + if (keyEvent->modifiers() & Qt::ControlModifier) { + // send message with Ctrl+Enter + sendChat(); + return true; // eat event + } + } else { + if (keyEvent->modifiers() & Qt::ControlModifier) { + // insert return + ui.chattextEdit->textCursor().insertText("\n"); + } else { + // send message with Enter + sendChat(); + } + return true; // eat event + } + } + } + } + // pass the event on to the parent class + return QWidget::eventFilter(obj, event); +} + +void PopupChatDialog::sendChat() +{ + QTextEdit *chatWidget = ui.chattextEdit; + + if (chatWidget->toPlainText().isEmpty()) { + // nothing to send + return; + } + + std::wstring msg = chatWidget->toHtml().toStdWString(); + + if (msg.empty()) { + // nothing to send + return; + } + + std::string ownId; + + { + rsiface->lockData(); /* Lock Interface */ + const RsConfig &conf = rsiface->getConfig(); + + ownId = conf.ownId; + + rsiface->unlockData(); /* Unlock Interface */ + } + +#ifdef CHAT_DEBUG + std::cout << "PopupChatDialog:sendChat " << std::endl; +#endif + + if (rsMsgs->sendPrivateChat(dialogId, msg)) { + QDateTime currentTime = QDateTime::currentDateTime(); + addChatMsg(false, ownId, QString::fromStdString(rsPeers->getPeerName(ownId)), currentTime, currentTime, QString::fromStdWString(msg), TYPE_NORMAL, true); + } + + chatWidget->clear(); + // workaround for Qt bug - http://bugreports.qt.nokia.com/browse/QTBUG-2533 + // QTextEdit::clear() does not reset the CharFormat if document contains hyperlinks that have been accessed. + chatWidget->setCurrentCharFormat(QTextCharFormat ()); + + setFont(); +} + +/** + Toggles the ToolBox on and off, changes toggle button text + */ +void PopupChatDialog::showAvatarFrame(bool show) +{ + if (show) { + ui.avatarframe->setVisible(true); + ui.avatarFrameButton->setChecked(true); + ui.avatarFrameButton->setToolTip(tr("Hide Avatar")); + ui.avatarFrameButton->setIcon(QIcon(":images/hide_toolbox_frame.png")); + } else { + ui.avatarframe->setVisible(false); + ui.avatarFrameButton->setChecked(false); + ui.avatarFrameButton->setToolTip(tr("Show Avatar")); + ui.avatarFrameButton->setIcon(QIcon(":images/show_toolbox_frame.png")); + } + + PeerSettings->setShowAvatarFrame(dialogId, show); +} + +void PopupChatDialog::on_closeInfoFrameButton_clicked() +{ + ui.infoframe->setVisible(false); +} + +void PopupChatDialog::setColor() +{ + bool ok; + QRgb color = QColorDialog::getRgba(ui.chattextEdit->textColor().rgba(), &ok, window()); + if (ok) { + mCurrentColor = QColor(color); + PeerSettings->setPrivateChatColor(dialogId, mCurrentColor.name()); + colorChanged(mCurrentColor); + } + setFont(); +} + +void PopupChatDialog::colorChanged(const QColor &c) +{ + QPixmap pix(16, 16); + pix.fill(c); + ui.colorButton->setIcon(pix); +} + +void PopupChatDialog::getFont() +{ + bool ok; + QFont font = QFontDialog::getFont(&ok, mCurrentFont, this); + if (ok) { + fontChanged(font); + } +} + +void PopupChatDialog::fontChanged(const QFont &font) +{ + mCurrentFont = font; + + ui.textboldButton->setChecked(mCurrentFont.bold()); + ui.textunderlineButton->setChecked(mCurrentFont.underline()); + ui.textitalicButton->setChecked(mCurrentFont.italic()); + + setFont(); +} + +void PopupChatDialog::setFont() +{ + mCurrentFont.setBold(ui.textboldButton->isChecked()); + mCurrentFont.setUnderline(ui.textunderlineButton->isChecked()); + mCurrentFont.setItalic(ui.textitalicButton->isChecked()); + + ui.chattextEdit->setFont(mCurrentFont); + ui.chattextEdit->setTextColor(mCurrentColor); + + ui.chattextEdit->setFocus(); + + PeerSettings->setPrivateChatFont(dialogId, mCurrentFont.toString()); +} + +//============================================================================ + +void PopupChatDialog::smileyWidget() +{ + Emoticons::showSmileyWidget(this, ui.emoteiconButton, SLOT(addSmiley()), true); +} + +//============================================================================ + +void PopupChatDialog::addSmiley() +{ + ui.chattextEdit->textCursor().insertText(qobject_cast(sender())->toolTip().split("|").first()); +} + +//============================================================================ + +void PopupChatDialog::on_actionClear_Chat_History_triggered() +{ + ui.textBrowser->clear(); +} + +void PopupChatDialog::on_actionDelete_Chat_History_triggered() +{ + if ((QMessageBox::question(this, "RetroShare", tr("Do you really want to physically delete the history?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) == QMessageBox::Yes) { + on_actionClear_Chat_History_triggered(); + historyKeeper.clear(); + } +} + +void PopupChatDialog::updatePeerAvatar(const std::string& peer_id) +{ + #ifdef CHAT_DEBUG + std::cerr << "popupchatDialog::updatePeerAvatar() updating avatar for peer " << peer_id << std::endl ; + std::cerr << "Requesting avatar image for peer " << peer_id << std::endl ; + #endif + + unsigned char *data = NULL; + int size = 0 ; + + rsMsgs->getAvatarData(peer_id,data,size); + + #ifdef CHAT_DEBUG + std::cerr << "Image size = " << size << std::endl; + #endif + + if(size == 0) { + #ifdef CHAT_DEBUG + std::cerr << "Got no image" << std::endl ; + #endif + ui.avatarlabel->setPixmap(QPixmap(":/images/no_avatar_background.png")); + return ; + } + + // set the image + QPixmap pix ; + pix.loadFromData(data,size,"PNG") ; + ui.avatarlabel->setPixmap(pix); // writes image into ba in JPG format + + delete[] data ; +} + +void PopupChatDialog::updateAvatar() +{ + unsigned char *data = NULL; + int size = 0 ; + + rsMsgs->getOwnAvatarData(data,size); + + #ifdef CHAT_DEBUG + std::cerr << "Image size = " << size << std::endl ; + #endif + + if(size == 0) { + #ifdef CHAT_DEBUG + std::cerr << "Got no image" << std::endl ; + #endif + } + + // set the image + QPixmap pix ; + pix.loadFromData(data,size,"PNG") ; + ui.myavatarlabel->setPixmap(pix); // writes image into ba in PNGformat + + delete[] data ; +} + +void PopupChatDialog::addExtraFile() +{ + QString file; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", file)) { + addAttachment(file.toUtf8().constData(), 0); + } +} + +void PopupChatDialog::addExtraPicture() +{ + // select a picture file + QString file; + if (misc::getOpenFileName(window(), RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg)", file)) { + addAttachment(file.toUtf8().constData(), 1); + } +} + +void PopupChatDialog::addAttachment(std::string filePath,int flag) +{ + /* add a AttachFileItem to the attachment section */ + std::cerr << "PopupChatDialog::addExtraFile() hashing file."; + std::cerr << std::endl; + + /* add widget in for new destination */ + AttachFileItem *file = new AttachFileItem(filePath); + //file-> + + if(flag==1) + file->setPicFlag(1); + + ui.vboxLayout->addWidget(file, 1, 0); + + //when the file is local or is finished hashing, call the fileHashingFinished method to send a chat message + if (file->getState() == AFI_STATE_LOCAL) { + fileHashingFinished(file); + } else { + QObject::connect(file,SIGNAL(fileFinished(AttachFileItem *)), SLOT(fileHashingFinished(AttachFileItem *))) ; + } +} + +void PopupChatDialog::fileHashingFinished(AttachFileItem* file) +{ + std::cerr << "PopupChatDialog::fileHashingFinished() started."; + std::cerr << std::endl; + + //check that the file is ok tos end + if (file->getState() == AFI_STATE_ERROR) { +#ifdef CHAT_DEBUG + std::cerr << "PopupChatDialog::fileHashingFinished error file is not hashed."; +#endif + return; + } + + std::string ownId; + + { + rsiface->lockData(); /* Lock Interface */ + const RsConfig &conf = rsiface->getConfig(); + + ownId = conf.ownId; + + rsiface->unlockData(); /* Unlock Interface */ + } + + QString message; + QString ext = QFileInfo(QString::fromStdString(file->FileName())).suffix(); + + if(file->getPicFlag()==1){ + message+="FilePath().c_str(); + message+="\" width=\"100\" height=\"100\">"; + message+="
    "; + } + else if (ext == "ogg" || ext == "mp3" || ext == "MP3" || ext == "mp1" || ext == "mp2" || ext == "wav" || ext == "wma") + { + message+=""; + message+="
    "; + } + else if (ext == "avi" || ext == "AVI" || ext == "mpg" || ext == "mpeg" || ext == "wmv" || ext == "ogm" + || ext == "mkv" || ext == "mp4" || ext == "flv" || ext == "mov" + || ext == "vob" || ext == "qt" || ext == "rm" || ext == "3gp") + { + message+=""; + message+="
    "; + } + else if (ext == "tar" || ext == "bz2" || ext == "zip" || ext == "gz" || ext == "7z" + || ext == "rar" || ext == "rpm" || ext == "deb") + { + message+=""; + message+="
    "; + } + else if (ext == "jpg" || ext == "jpeg" || ext == "png" || ext == "gif" || ext == "bmp" || ext == "ico" + || ext == "svg" || ext == "tif" || ext == "tiff" || ext == "JPG") + { + message+=""; + message+="
    "; + } + + RetroShareLink link; + link.createFile(QString::fromUtf8(file->FileName().c_str()),file->FileSize(),QString::fromStdString(file->FileHash())); + message += link.toHtmlSize(); + +#ifdef CHAT_DEBUG + std::cerr << "PopupChatDialog::fileHashingFinished message : " << message.toStdString() << std::endl; +#endif + + /* convert to real html document */ + QTextBrowser textBrowser; + textBrowser.setHtml(message); + std::wstring msg = textBrowser.toHtml().toStdWString(); + + if (rsMsgs->sendPrivateChat(dialogId, msg)) { + QDateTime currentTime = QDateTime::currentDateTime(); + addChatMsg(false, ownId, QString::fromStdString(rsPeers->getPeerName(ownId)), currentTime, currentTime, QString::fromStdWString(msg), TYPE_NORMAL, true); + } +} + +void PopupChatDialog::dropEvent(QDropEvent *event) +{ + if (!(Qt::CopyAction & event->possibleActions())) + { + std::cerr << "PopupChatDialog::dropEvent() Rejecting uncopyable DropAction"; + std::cerr << std::endl; + + /* can't do it */ + return; + } + + std::cerr << "PopupChatDialog::dropEvent() Formats"; + std::cerr << std::endl; + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) + { + std::cerr << "Format: " << (*it).toStdString(); + std::cerr << std::endl; + } + + if (event->mimeData()->hasUrls()) + { + std::cerr << "PopupChatDialog::dropEvent() Urls:"; + std::cerr << std::endl; + + QList urls = event->mimeData()->urls(); + QList::iterator uit; + for(uit = urls.begin(); uit != urls.end(); uit++) + { + QString localpath = uit->toLocalFile(); + std::cerr << "Whole URL: " << uit->toString().toStdString() << std::endl; + std::cerr << "or As Local File: " << localpath.toStdString() << std::endl; + + if (localpath.isEmpty() == false) + { + //Check that the file does exist and is not a directory + QDir dir(localpath); + if (dir.exists()) { + std::cerr << "PopupChatDialog::dropEvent() directory not accepted."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("Directory can't be dropped, only files are accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } else if (QFile::exists(localpath)) { + PopupChatDialog::addAttachment(localpath.toUtf8().constData(), false); + } else { + std::cerr << "PopupChatDialog::dropEvent() file does not exists."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("File not found or file name not accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } + } + } + } + + event->setDropAction(Qt::CopyAction); + event->accept(); +} + +void PopupChatDialog::dragEnterEvent(QDragEnterEvent *event) +{ + /* print out mimeType */ + std::cerr << "PopupChatDialog::dragEnterEvent() Formats"; + std::cerr << std::endl; + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) + { + std::cerr << "Format: " << (*it).toStdString(); + std::cerr << std::endl; + } + + if (event->mimeData()->hasUrls()) + { + std::cerr << "PopupChatDialog::dragEnterEvent() Accepting Urls"; + std::cerr << std::endl; + event->acceptProposedAction(); + } + else + { + std::cerr << "PopupChatDialog::dragEnterEvent() No Urls"; + std::cerr << std::endl; + } +} + +bool PopupChatDialog::fileSave() +{ + if (fileName.isEmpty()) + return fileSaveAs(); + + QFile file(fileName); + if (!file.open(QFile::WriteOnly)) + return false; + QTextStream ts(&file); + ts.setCodec(QTextCodec::codecForName("UTF-8")); + ts << ui.textBrowser->document()->toPlainText(); + ui.textBrowser->document()->setModified(false); + return true; +} + +bool PopupChatDialog::fileSaveAs() +{ + QString fn; + if (misc::getSaveFileName(window(), RshareSettings::LASTDIR_HISTORY, tr("Save as..."), tr("Text File (*.txt );;All Files (*)"), fn)) { + setCurrentFileName(fn); + return fileSave(); + } + + return false; +} + +void PopupChatDialog::setCurrentFileName(const QString &fileName) +{ + this->fileName = fileName; + ui.textBrowser->document()->setModified(false); + + setWindowModified(false); +} + +void PopupChatDialog::clearOfflineMessages() +{ + m_manualDelete = true; + rsMsgs->clearPrivateChatQueue(false, dialogId); + m_manualDelete = false; +} + +void PopupChatDialog::updateStatus(const QString &peer_id, int status) +{ + std::string stdPeerId = peer_id.toStdString(); + + /* set font size for status */ + if (stdPeerId == dialogId) { + // the peers status has changed + + switch (status) { + case RS_STATUS_OFFLINE: + ui.avatarlabel->setStyleSheet("QLabel#avatarlabel{ border-image:url(:/images/avatarstatus_bg_offline.png); }"); + ui.avatarlabel->setEnabled(false); + ui.infoframe->setVisible(true); + ui.infolabel->setText(dialogName + " " + tr("apears to be Offline.") +"\n" + tr("Messages you send will be delivered after Friend is again Online")); + break; + + case RS_STATUS_INACTIVE: + ui.avatarlabel->setStyleSheet("QLabel#avatarlabel{ border-image:url(:/images/avatarstatus_bg_away.png); }"); + ui.avatarlabel->setEnabled(true); + ui.infoframe->setVisible(true); + ui.infolabel->setText(dialogName + " " + tr("is Idle and may not reply")); + break; + + case RS_STATUS_ONLINE: + ui.avatarlabel->setStyleSheet("QLabel#avatarlabel{ border-image:url(:/images/avatarstatus_bg_online.png); }"); + ui.avatarlabel->setEnabled(true); + ui.infoframe->setVisible(false); + break; + + case RS_STATUS_AWAY: + ui.avatarlabel->setStyleSheet("QLabel#avatarlabel{ border-image:url(:/images/avatarstatus_bg_away.png); }"); + ui.avatarlabel->setEnabled(true); + ui.infolabel->setText(dialogName + " " + tr("is Away and may not reply")); + ui.infoframe->setVisible(true); + break; + + case RS_STATUS_BUSY: + ui.avatarlabel->setStyleSheet("QLabel#avatarlabel{ border-image:url(:/images/avatarstatus_bg_busy.png); }"); + ui.avatarlabel->setEnabled(true); + ui.infolabel->setText(dialogName + " " + tr("is Busy and may not reply")); + ui.infoframe->setVisible(true); + break; + } + + QString statusString("%1"); + ui.friendnamelabel->setText(dialogName + " (" + statusString.arg(StatusDefs::name(status)) + ")") ; + + peerStatus = status; + + PopupChatWindow *window = WINDOW(this); + if (window) { + window->calculateTitle(this); + } + + return; + } + + if (stdPeerId == rsPeers->getOwnId()) { + // my status has changed + + switch (status) { + case RS_STATUS_OFFLINE: + ui.myavatarlabel->setStyleSheet("QLabel#myavatarlabel{border-image:url(:/images/avatarstatus_bg_offline.png); }"); + break; + + case RS_STATUS_INACTIVE: + ui.myavatarlabel->setStyleSheet("QLabel#myavatarlabel{border-image:url(:/images/avatarstatus_bg_away.png); }"); + break; + + case RS_STATUS_ONLINE: + ui.myavatarlabel->setStyleSheet("QLabel#myavatarlabel{border-image:url(:/images/avatarstatus_bg_online.png); }"); + break; + + case RS_STATUS_AWAY: + ui.myavatarlabel->setStyleSheet("QLabel#myavatarlabel{border-image:url(:/images/avatarstatus_bg_away.png); }"); + break; + + case RS_STATUS_BUSY: + ui.myavatarlabel->setStyleSheet("QLabel#myavatarlabel{border-image:url(:/images/avatarstatus_bg_busy.png); }"); + break; + } + + return; + } + + // ignore status change +} + +void PopupChatDialog::updatePeersCustomStateString(const QString& peer_id, const QString& status_string) +{ + std::string stdPeerId = peer_id.toStdString(); + QString status_text; + + if (stdPeerId == dialogId) { + // the peers status string has changed + if (status_string.isEmpty()) { + ui.statusmessagelabel->hide(); + } else { + ui.statusmessagelabel->show(); + status_text = RsHtml::formatText(status_string, RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); + ui.statusmessagelabel->setText(status_text); + } + } +} + +void PopupChatDialog::on_actionMessageHistory_triggered() +{ + ImHistoryBrowser imBrowser(dialogId, historyKeeper, ui.chattextEdit, window()); + imBrowser.exec(); +} + +bool PopupChatDialog::setStyle() +{ + if (style.showDialog(window())) { + PeerSettings->setStyle(dialogId, "PopupChatDialog", style); + return true; + } + + return false; +} + +const RSStyle &PopupChatDialog::getStyle() +{ + return style; +} diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.h b/retroshare-gui/src/gui/chat/PopupChatDialog.h new file mode 100644 index 000000000..0a323ddc0 --- /dev/null +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.h @@ -0,0 +1,159 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _POPUPCHATDIALOG_H +#define _POPUPCHATDIALOG_H + +#include "ui_PopupChatDialog.h" + +class QAction; +class QTextEdit; +class QTextCharFormat; +class AttachFileItem; +class ChatInfo; + +#include +#include "gui/im_history/IMHistoryKeeper.h" +#include "ChatStyle.h" +#include "gui/style/RSStyle.h" + +class PopupChatDialog : public QWidget +{ + Q_OBJECT + +public: + enum enumChatType { TYPE_NORMAL, TYPE_HISTORY, TYPE_OFFLINE }; + +public: + static PopupChatDialog *getExistingInstance(const std::string &id); + static PopupChatDialog *getPrivateChat(const std::string &id, uint chatflags); + static void cleanupChat(); + static void chatFriend(const std::string &id); + static void updateAllAvatars(); + static void privateChatChanged(int list, int type); + + void updateStatusString(const QString& peer_id, const QString& statusString); + void updatePeerAvatar(const std::string&); + std::string getPeerId() { return dialogId; } + QString getTitle() { return dialogName; } + bool hasNewMessages() { return newMessages; } + bool isTyping() { return typing; } + int getPeerStatus() { return peerStatus; } + void focusDialog(); + void activate(); + bool setStyle(); + const RSStyle &getStyle(); + +public slots: + void updateStatus(const QString &peer_id, int status); + +protected: + /** Default constructor */ + PopupChatDialog(const std::string &id, const QString &name, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~PopupChatDialog(); + + virtual void resizeEvent(QResizeEvent *event); + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); + + bool eventFilter(QObject *obj, QEvent *ev); + + void insertChatMsgs(); + void addChatMsg(bool incoming, const std::string &id, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &message, enumChatType chatType, bool addToHistory); + + void updateAvatar(); + +private slots: + void pasteLink() ; + void contextMenu(QPoint) ; + + void fileHashingFinished(AttachFileItem* file); + + void smileyWidget(); + void addSmiley(); + + void resetStatusBar() ; + void updateStatusTyping() ; + + void on_actionMessageHistory_triggered(); + void addExtraFile(); + void addExtraPicture(); + void showAvatarFrame(bool show); + void on_closeInfoFrameButton_clicked(); + + void setColor(); + void getFont(); + void setFont(); + + void sendChat(); + + void updatePeersCustomStateString(const QString& peer_id, const QString& status_string) ; + + void on_actionClear_Chat_History_triggered(); + void on_actionDelete_Chat_History_triggered(); + + bool fileSave(); + bool fileSaveAs(); + void clearOfflineMessages(); + +private: + void setCurrentFileName(const QString &fileName); + + void colorChanged(const QColor &c); + void fontChanged(const QFont &font); + void addAttachment(std::string,int flag); + void processSettings(bool bLoad); + + void onPrivateChatChanged(int list, int type, bool initial = false); + + QAction *actionTextBold; + QAction *actionTextUnderline; + QAction *actionTextItalic; + + std::string dialogId; + QString dialogName; + unsigned int lastChatTime; + std::string lastChatName; + + time_t last_status_send_time ; + QColor mCurrentColor; + QFont mCurrentFont; + + std::list m_savedOfflineChat; + QString wholeChat; + QString fileName; + + bool newMessages; + bool typing; + int peerStatus; + IMHistoryKeeper historyKeeper; + ChatStyle chatStyle; + bool m_manualDelete; + + RSStyle style; + + /** Qt Designer generated object */ + Ui::PopupChatDialog ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.ui b/retroshare-gui/src/gui/chat/PopupChatDialog.ui new file mode 100644 index 000000000..18ef93418 --- /dev/null +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.ui @@ -0,0 +1,948 @@ + + + PopupChatDialog + + + Qt::NonModal + + + + 0 + 0 + 531 + 451 + + + + MainWindow + + + + + + + 0 + + + + + + 0 + + + 0 + + + + + 0 + + + 1 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 14 + 16777215 + + + + QFrame#frame{border: transparent} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + + 14 + 31 + + + + + 14 + 31 + + + + + + + + 16 + 31 + + + + true + + + + + + + Qt::Vertical + + + + 12 + 335 + + + + + + + + + + + + 132 + 16777215 + + + + border: transparent; + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + 6 + + + 6 + + + 9 + + + + + + 116 + 116 + + + + + 116 + 116 + + + + QLabel{ +border-image: url(:/images/avatarstatus_bg.png); + +} + + + + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 61 + 141 + + + + + + + + + 116 + 116 + + + + + 116 + 116 + + + + QLabel{ +border-image: url(:/images/avatarstatus_bg.png); + +} + + + + + + Qt::AlignCenter + + + + + + + + + + QFrame#frame_2{border: transparent} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 6 + + + 6 + + + 6 + + + + + + 0 + 0 + + + + + Arial + 13 + 75 + true + true + + + + TextLabel + + + + + + + + Arial + 9 + + + + TextLabel + + + + + + + + + + QFrame#infoframe{border: 1px solid #DCDC41; +border-radius: 6px; +background: #FFFFD7; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FFFFD7, stop:1 #FFFFB2);} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + + + + 16 + 16 + + + + + + + :/images/info16.png + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + TextLabel + + + + + + + + 16 + 16 + + + + Qt::NoFocus + + + Close + + + QToolButton +{ + border-image: url(:/images/closenormal.png) +} + +QToolButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QToolButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + true + + + + + + + + + + + 347 + 30 + + + + + 16777215 + 30 + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 1 + + + 6 + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + QPushButton::menu-indicator { +subcontrol-origin: padding; +subcontrol-position: bottom right; +} + +QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open { +position: relative; +top: 1px; left: 1px; /* shift the arrow by 2 px */ +} + +QPushButton:hover { +border: 1px solid #CCCCCC; +} + + + + + + + :/images/configure.png:/images/configure.png + + + + 22 + 22 + + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Attach a Picture + + + + + + + :/images/add_image24.png:/images/add_image24.png + + + + 24 + 24 + + + + true + + + + + + + + 28 + 28 + + + + Qt::NoFocus + + + Add a File for your Friend + + + + + + + :/images/add-share24.png:/images/add-share24.png + + + + 24 + 24 + + + + true + + + + + + + Qt::Horizontal + + + + 190 + 25 + + + + + + + + Send + + + + + + + + 0 + 0 + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + + + + + 24 + 24 + + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Bold + + + + + + + ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup + + + false + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Underline + + + + + + + ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup + + + false + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Italic + + + + + + + ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup + + + false + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Font + + + + + + + ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup + + + false + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Text Color + + + + + + true + + + + + + + + + + + + + 1 + + + Qt::Vertical + + + 2 + + + + + + + + 0 + 0 + + + + + 0 + 100 + + + + QTextBrowser{border: 1px solid #B8B6B1; +border-radius: 6px; +background: white;} + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + true + + + true + + + + + + + + + 0 + + + + + + + + 0 + + + 3 + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + Qt::CustomContextMenu + + + QTextEdit{border: 1px solid #B8B6B1; +border-radius: 6px; +background: white;} + + + + + + + + 18 + 18 + + + + + 18 + 18 + + + + T + + + Qt::AlignCenter + + + + + + + + + + + + + + + + Bold + + + + + Italic + + + + + Underline + + + + + Strike + + + + + + :/images/edit-clear-history.png:/images/edit-clear-history.png + + + Clear Chat History + + + + + true + + + Disable Emoticons + + + + + Save Chat History + + + Save Chat History + + + + + Clear offline messages + + + + + Browse Message History + + + Browse History + + + + + + :/images/edit-clear-history.png:/images/edit-clear-history.png + + + Delete Chat History + + + Deletes all stored and displayed chat history + + + + + + + + diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.cpp b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp new file mode 100644 index 000000000..7e0f563fc --- /dev/null +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp @@ -0,0 +1,370 @@ +/**************************************************************** + * + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "PopupChatWindow.h" +#include "PopupChatDialog.h" +#include "gui/settings/rsharesettings.h" +#include "gui/settings/RsharePeerSettings.h" +#include "gui/common/StatusDefs.h" +#include "gui/style/RSStyle.h" +#include"util/misc.h" + +#include +#include + +#define IMAGE_WINDOW ":/images/rstray3.png" +#define IMAGE_TYPING ":/images/typing.png" +#define IMAGE_CHAT ":/images/chat.png" + +static PopupChatWindow *instance = NULL; + +/*static*/ PopupChatWindow *PopupChatWindow::getWindow(bool needSingleWindow) +{ + if (needSingleWindow == false && (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW)) { + if (instance == NULL) { + instance = new PopupChatWindow(true); + } + + return instance; + } + + return new PopupChatWindow(false); +} + +/*static*/ void PopupChatWindow::cleanup() +{ + if (instance) { + delete(instance); + instance = NULL; + } +} + +/** Default constructor */ +PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + tabbedWindow = tabbed; + firstShow = true; + chatDialog = NULL; + + ui.tabWidget->setVisible(tabbedWindow); + + if (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW) { + ui.actionDockTab->setVisible(tabbedWindow == false); + ui.actionUndockTab->setVisible(tabbedWindow); + } else { + ui.actionDockTab->setVisible(false); + ui.actionUndockTab->setVisible(false); + } + + setAttribute(Qt::WA_DeleteOnClose, true); + + connect(ui.actionAvatar, SIGNAL(triggered()),this, SLOT(getAvatar())); + connect(ui.actionColor, SIGNAL(triggered()), this, SLOT(setStyle())); + connect(ui.actionDockTab, SIGNAL(triggered()), this, SLOT(dockTab())); + connect(ui.actionUndockTab, SIGNAL(triggered()), this, SLOT(undockTab())); + + connect(ui.tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(tabCloseRequested(int))); + connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabCurrentChanged(int))); + + setWindowIcon(QIcon(IMAGE_WINDOW)); +} + +/** Destructor. */ +PopupChatWindow::~PopupChatWindow() +{ + if (tabbedWindow) { + Settings->saveWidgetInformation(this); + } else { + PeerSettings->saveWidgetInformation(peerId, this); + } + + if (this == instance) { + instance = NULL; + } +} + +void PopupChatWindow::showEvent(QShowEvent *event) +{ + if (firstShow) { + firstShow = false; + + if (tabbedWindow) { + Settings->loadWidgetInformation(this); + } else { + this->move(qrand()%100, qrand()%100); //avoid to stack multiple popup chat windows on the same position + PeerSettings->loadWidgetInformation(peerId, this); + } + } +} + +PopupChatDialog *PopupChatWindow::getCurrentDialog() +{ + if (tabbedWindow) { + return dynamic_cast(ui.tabWidget->currentWidget()); + } + + return chatDialog; +} + +void PopupChatWindow::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::ActivationChange) { + PopupChatDialog *pcd = getCurrentDialog(); + if (pcd) { + pcd->activate(); + } + } +} + +void PopupChatWindow::addDialog(PopupChatDialog *dialog) +{ + if (tabbedWindow) { + ui.tabWidget->addTab(dialog, dialog->getTitle()); + } else { + ui.horizontalLayout->addWidget(dialog); + peerId = dialog->getPeerId(); + chatDialog = dialog; + calculateStyle(dialog); + } +} + +void PopupChatWindow::removeDialog(PopupChatDialog *dialog) +{ + if (tabbedWindow) { + int tab = ui.tabWidget->indexOf(dialog); + if (tab >= 0) { + ui.tabWidget->removeTab(tab); + } + + if (ui.tabWidget->count() == 0) { + deleteLater(); + } + } else { + if (chatDialog == dialog) { + ui.horizontalLayout->removeWidget(dialog); + chatDialog = NULL; + deleteLater(); + } + } +} + +void PopupChatWindow::showDialog(PopupChatDialog *dialog, uint chatflags) +{ + if (chatflags & RS_CHAT_FOCUS) { + if (tabbedWindow) { + ui.tabWidget->setCurrentWidget(dialog); + } + show(); + activateWindow(); + setWindowState((windowState() & (~Qt::WindowMinimized)) | Qt::WindowActive); + raise(); + dialog->focusDialog(); + } else { + if (isVisible() == false) { + showMinimized(); + } + alertDialog(dialog); + } +} + +void PopupChatWindow::alertDialog(PopupChatDialog *dialog) +{ + QApplication::alert(this); +} + +void PopupChatWindow::calculateTitle(PopupChatDialog *dialog) +{ + if (dialog) { + if (ui.tabWidget->isVisible()) { + int tab = ui.tabWidget->indexOf(dialog); + if (tab >= 0) { + if (dialog->isTyping()) { + ui.tabWidget->setTabIcon(tab, QIcon(IMAGE_TYPING)); + } else if (dialog->hasNewMessages()) { + ui.tabWidget->setTabIcon(tab, QIcon(IMAGE_CHAT)); + } else { + ui.tabWidget->setTabIcon(tab, QIcon(StatusDefs::imageIM(dialog->getPeerStatus()))); + } + } + } + } + + bool hasNewMessages = false; + PopupChatDialog *pcd; + + /* is typing */ + bool isTyping = false; + if (ui.tabWidget->isVisible()) { + int tabCount = ui.tabWidget->count(); + for (int i = 0; i < tabCount; i++) { + pcd = dynamic_cast(ui.tabWidget->widget(i)); + if (pcd) { + if (pcd->isTyping()) { + isTyping = true; + } + if (pcd->hasNewMessages()) { + hasNewMessages = true; + } + } + } + } else { + if (dialog) { + isTyping = dialog->isTyping(); + hasNewMessages = dialog->hasNewMessages(); + } + } + + if (ui.tabWidget->isVisible()) { + pcd = dynamic_cast(ui.tabWidget->currentWidget()); + } else { + pcd = dialog; + } + + QIcon icon; + if (isTyping) { + icon = QIcon(IMAGE_TYPING); + } else if (hasNewMessages) { + icon = QIcon(IMAGE_CHAT); + } else { + if (pcd) { + icon = QIcon(StatusDefs::imageIM(pcd->getPeerStatus())); + } else { + icon = QIcon(IMAGE_WINDOW); + } + } + + setWindowIcon(icon); + + if (pcd) { + setWindowTitle(pcd->getTitle() + " (" + StatusDefs::name(pcd->getPeerStatus()) + ")"); + } else { + setWindowTitle(tr("RetroShare")); + } +} + +void PopupChatWindow::getAvatar() +{ + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg *.tiff *.gif)"), fileName)) + { + QPixmap picture = QPixmap(fileName).scaled(96,96, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + + std::cerr << "Sending avatar image down the pipe" << std::endl; + + // send avatar down the pipe for other peers to get it. + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + picture.save(&buffer, "PNG"); // writes image into ba in PNG format + + std::cerr << "Image size = " << ba.size() << std::endl; + + rsMsgs->setOwnAvatarData((unsigned char *)(ba.data()), ba.size()); // last char 0 included. + } +} + +void PopupChatWindow::tabCloseRequested(int tab) +{ + QWidget *widget = ui.tabWidget->widget(tab); + + if (widget) { + widget->deleteLater(); + } +} + +void PopupChatWindow::tabCurrentChanged(int tab) +{ + PopupChatDialog *pcd = dynamic_cast(ui.tabWidget->widget(tab)); + + if (pcd) { + pcd->activate(); + calculateStyle(pcd); + } +} + +void PopupChatWindow::dockTab() +{ + if ((Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW) && chatDialog) { + PopupChatWindow *pcw = getWindow(false); + if (pcw) { + PopupChatDialog *pcd = chatDialog; + removeDialog(pcd); + pcw->addDialog(pcd); + pcw->show(); + pcw->calculateTitle(pcd); + } + } +} + +void PopupChatWindow::undockTab() +{ + PopupChatDialog *pcd = dynamic_cast(ui.tabWidget->currentWidget()); + + if (pcd) { + PopupChatWindow *pcw = getWindow(true); + if (pcw) { + removeDialog(pcd); + pcw->addDialog(pcd); + pcd->show(); + pcw->show(); + pcw->calculateTitle(pcd); + } + } +} + +void PopupChatWindow::setStyle() +{ + PopupChatDialog *pcd = getCurrentDialog(); + + if (pcd && pcd->setStyle()) { + calculateStyle(pcd); + } +} + +void PopupChatWindow::calculateStyle(PopupChatDialog *dialog) +{ + QString toolSheet; + QString statusSheet; + QString widgetSheet; + + if (dialog) { + const RSStyle &style = dialog->getStyle(); + + QString styleSheet = style.getStyleSheet(); + + if (styleSheet.isEmpty() == false) { + toolSheet = QString("QToolBar{%1}").arg(styleSheet); + statusSheet = QString(".QStatusBar{%1}").arg(styleSheet); + widgetSheet = QString(".QWidget{%1}").arg(styleSheet); + } + } + + ui.chattoolBar->setStyleSheet(toolSheet); + ui.chatstatusbar->setStyleSheet(statusSheet); + ui.chatcentralwidget->setStyleSheet(widgetSheet); +} diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.h b/retroshare-gui/src/gui/chat/PopupChatWindow.h new file mode 100644 index 000000000..698ce693b --- /dev/null +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.h @@ -0,0 +1,76 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _POPUPCHATWINDOW_H +#define _POPUPCHATWINDOW_H + +#include +#include "ui_PopupChatWindow.h" + +class PopupChatDialog; + +class PopupChatWindow : public QMainWindow +{ + Q_OBJECT + +public: + static PopupChatWindow *getWindow(bool needSingleWindow); + static void cleanup(); + +public: + void addDialog(PopupChatDialog *dialog); + void removeDialog(PopupChatDialog *dialog); + void showDialog(PopupChatDialog *dialog, uint chatflags); + void alertDialog(PopupChatDialog *dialog); + void calculateTitle(PopupChatDialog *dialog); + +protected: + /** Default constructor */ + PopupChatWindow(bool tabbed, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~PopupChatWindow(); + + virtual void showEvent(QShowEvent *event); + virtual void changeEvent(QEvent *event); + +private slots: + void getAvatar(); + void tabCloseRequested(int tab); + void tabCurrentChanged(int tab); + void dockTab(); + void undockTab(); + void setStyle(); + +private: + bool tabbedWindow; + bool firstShow; + std::string peerId; + PopupChatDialog *chatDialog; + + PopupChatDialog *getCurrentDialog(); + void calculateStyle(PopupChatDialog *dialog); + + /** Qt Designer generated object */ + Ui::PopupChatWindow ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.ui b/retroshare-gui/src/gui/chat/PopupChatWindow.ui new file mode 100644 index 000000000..89ab82c63 --- /dev/null +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.ui @@ -0,0 +1,126 @@ + + + PopupChatWindow + + + Qt::NonModal + + + + 0 + 0 + 531 + 451 + + + + MainWindow + + + + + + + + + + + + + true + + + true + + + + + + + + + + 16777215 + 32 + + + + false + + + Qt::LeftToolBarArea|Qt::TopToolBarArea + + + + 24 + 24 + + + + false + + + TopToolBarArea + + + false + + + + + + + + + + :/images/no_avatar_70.png:/images/no_avatar_70.png + + + Avatar + + + Set your Avatar Picture + + + + + + :/images/tab-dock.png:/images/tab-dock.png + + + Dock tab + + + Dock tab + + + + + + :/images/tab-undock.png:/images/tab-undock.png + + + Undock tab + + + Undock tab + + + + + + :/images/highlight.png:/images/highlight.png + + + Set Chat Window Color + + + Set Chat Window Color + + + + + + + + diff --git a/retroshare-gui/src/gui/common/Emoticons.cpp b/retroshare-gui/src/gui/common/Emoticons.cpp new file mode 100644 index 000000000..7156a69d8 --- /dev/null +++ b/retroshare-gui/src/gui/common/Emoticons.cpp @@ -0,0 +1,210 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Emoticons.h" + +static QHash Smileys; + +void Emoticons::load() +{ + QString sm_codes; + bool internalEmoticons = true; + +#if defined(Q_OS_WIN32) + // first try external emoticons + QFile sm_file(QApplication::applicationDirPath() + "/emoticons/emotes.acs"); + if(sm_file.open(QIODevice::ReadOnly)) + { + internalEmoticons = false; + } else { + // then embedded emotions + sm_file.setFileName(":/smileys/emotes.acs"); + if(!sm_file.open(QIODevice::ReadOnly)) + { + std::cout << "error opening ressource file" << std::endl ; + return ; + } + } +#else + QFile sm_file(QString(":/smileys/emotes.acs")); + if(!sm_file.open(QIODevice::ReadOnly)) + { + std::cout << "error opening ressource file" << std::endl ; + return ; + } +#endif + + sm_codes = sm_file.readAll(); + sm_file.close(); + + sm_codes.remove("\n"); + sm_codes.remove("\r"); + + int i = 0; + QString smcode; + QString smfile; + while(sm_codes[i] != '{') + { + i++; + } + while (i < sm_codes.length()-2) + { + smcode = ""; + smfile = ""; + + while(sm_codes[i] != '\"') + { + i++; + } + i++; + while (sm_codes[i] != '\"') + { + smcode += sm_codes[i]; + i++; + } + i++; + + while(sm_codes[i] != '\"') + { + i++; + } + i++; + while(sm_codes[i] != '\"' && sm_codes[i+1] != ';') + { + smfile += sm_codes[i]; + i++; + } + i++; + if(!smcode.isEmpty() && !smfile.isEmpty()) { + while (smcode.right(1) == "|") { + smcode.remove(smcode.length() - 1, 1); + } + + if (internalEmoticons) { + Smileys.insert(smcode, ":/"+smfile); + } else { + Smileys.insert(smcode, smfile); + } + } + } + + // init embedder + RsHtml::defEmbedImg.InitFromAwkwardHash(Smileys); +} + +void Emoticons::showSmileyWidget(QWidget *parent, QWidget *button, const char *slotAddMethod, bool above) +{ + QWidget *smWidget = new QWidget(parent, Qt::Popup); + + const int buttonWidth = 26; + const int buttonHeight = 26; + const int countPerLine = 9; + + int rowCount = (Smileys.size()/countPerLine) + ((Smileys.size() % countPerLine) ? 1 : 0); + + smWidget->setAttribute( Qt::WA_DeleteOnClose); + smWidget->setWindowTitle("Emoticons"); + smWidget->setWindowIcon(QIcon(QString(":/images/rstray3.png"))); + smWidget->setBaseSize(countPerLine*buttonWidth, rowCount*buttonHeight); + + //Warning: this part of code was taken from kadu instant messenger; + // It was EmoticonSelector::alignTo(QWidget* w) function there + // comments are Polish, I dont' know how does it work... + // oblicz pozycj� widgetu do kt�rego r�wnamy + // oblicz rozmiar selektora + QPoint pos = button->mapToGlobal(QPoint(0,0)); + QSize e_size = smWidget->sizeHint(); + // oblicz rozmiar pulpitu + QSize s_size = QApplication::desktop()->size(); + // oblicz dystanse od widgetu do lewego brzegu i do prawego + int l_dist = pos.x(); + int r_dist = s_size.width() - (pos.x() + button->width()); + // oblicz pozycj� w zale�no�ci od tego czy po lewej stronie + // jest wi�cej miejsca czy po prawej + int x; + if (l_dist >= r_dist) + x = pos.x() - e_size.width(); + else + x = pos.x() + button->width(); + // oblicz pozycj� y - centrujemy w pionie + int y = pos.y() + button->height()/2 - e_size.height()/2; + // je�li wychodzi poza doln� kraw�d� to r�wnamy do niej + if (y + e_size.height() > s_size.height()) + y = s_size.height() - e_size.height(); + + if (above) { + y -= rowCount*buttonHeight; + } + + // je�li wychodzi poza g�rn� kraw�d� to r�wnamy do niej + if (y < 0) + y = 0; + // ustawiamy selektor na wyliczonej pozycji + smWidget->move(x, y); + + x = 0; + y = 0; + + QHashIterator i(Smileys); + while(i.hasNext()) + { + i.next(); + QPushButton *smButton = new QPushButton("", smWidget); + smButton->setGeometry(x*buttonWidth, y*buttonHeight, buttonWidth, buttonHeight); + smButton->setIconSize(QSize(buttonWidth, buttonHeight)); + smButton->setIcon(QPixmap(i.value())); + smButton->setToolTip(i.key()); + smButton->setStyleSheet("QPushButton:hover {border: 3px solid white; border-radius: 2px;}"); + smButton->setFlat(true); + ++x; + if(x >= countPerLine) + { + x = 0; + y++; + } + QObject::connect(smButton, SIGNAL(clicked()), parent, slotAddMethod); + QObject::connect(smButton, SIGNAL(clicked()), smWidget, SLOT(close())); + } + + smWidget->show(); +} + +void Emoticons::formatText(QString &text) +{ + QHashIterator i(Smileys); + while(i.hasNext()) { + i.next(); + foreach (QString code, i.key().split("|")) { + text.replace(code, ""); + } + } +} diff --git a/retroshare-gui/src/gui/common/Emoticons.h b/retroshare-gui/src/gui/common/Emoticons.h new file mode 100644 index 000000000..d9c722d6b --- /dev/null +++ b/retroshare-gui/src/gui/common/Emoticons.h @@ -0,0 +1,42 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _EMOTICONS_H +#define _EMOTICONS_H + +#include "gui/chat/HandleRichText.h" + +class QWidget; +class QString; + +class Emoticons +{ +public: + static void load(); + + static void showSmileyWidget(QWidget *parent, QWidget *button, const char *slotAddMethod, bool above); + + static void formatText(QString &text); +}; + +#endif + diff --git a/retroshare-gui/src/gui/common/GroupDefs.cpp b/retroshare-gui/src/gui/common/GroupDefs.cpp new file mode 100644 index 000000000..2b493124e --- /dev/null +++ b/retroshare-gui/src/gui/common/GroupDefs.cpp @@ -0,0 +1,66 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include +#include + +#include "GroupDefs.h" +#include "util/misc.h" + +const QString GroupDefs::name(const RsGroupInfo &groupInfo) +{ + if ((groupInfo.flag & RS_GROUP_FLAG_STANDARD) == 0) { + /* no need to be translated */ + return misc::removeNewLine(groupInfo.name); + } + + if (groupInfo.id == RS_GROUP_ID_FRIENDS) { + return qApp->translate("GroupDefs", "Friends"); + } + if (groupInfo.id == RS_GROUP_ID_FAMILY) { + return qApp->translate("GroupDefs", "Family"); + } + if (groupInfo.id == RS_GROUP_ID_COWORKERS) { + return qApp->translate("GroupDefs", "Co-Workers"); + } + if (groupInfo.id == RS_GROUP_ID_OTHERS) { + return qApp->translate("GroupDefs", "Other Contacts"); + } + if (groupInfo.id == RS_GROUP_ID_FAVORITES) { + return qApp->translate("GroupDefs", "Favorites"); + } + + std::cerr << "GroupDefs::name: Unknown group id requested " << groupInfo.id; + return ""; +} + +static bool sortGroupInfo(const RsGroupInfo &groupInfo1, const RsGroupInfo &groupInfo2) +{ + return (GroupDefs::name(groupInfo1).compare(GroupDefs::name(groupInfo2), Qt::CaseInsensitive) < 0); +} + +void GroupDefs::sortByName(std::list &groupInfoList) +{ + groupInfoList.sort(sortGroupInfo); +} diff --git a/retroshare-gui/src/gui/common/GroupDefs.h b/retroshare-gui/src/gui/common/GroupDefs.h new file mode 100644 index 000000000..b502aa6bd --- /dev/null +++ b/retroshare-gui/src/gui/common/GroupDefs.h @@ -0,0 +1,37 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _GROUPDEFS_H +#define _GROUPDEFS_H + +class RsGroupInfo; + +class GroupDefs +{ +public: + static const QString name(const RsGroupInfo &groupInfo); + + static void sortByName(std::list &groupInfoList); +}; + +#endif + diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp new file mode 100644 index 000000000..72895dacf --- /dev/null +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp @@ -0,0 +1,485 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "GroupTreeWidget.h" +#include "ui_GroupTreeWidget.h" + +#include "RSItemDelegate.h" +#include "PopularityDefs.h" +#include "gui/settings/rsharesettings.h" +#include "RSTreeWidgetItem.h" + +#include + +#define COLUMN_NAME 0 +#define COLUMN_POPULARITY 1 +#define COLUMN_COUNT 2 +#define COLUMN_DATA COLUMN_NAME + +#define ROLE_ID Qt::UserRole +#define ROLE_NAME Qt::UserRole + 1 +#define ROLE_DESCRIPTION Qt::UserRole + 2 +#define ROLE_POPULARITY Qt::UserRole + 3 +#define ROLE_LASTPOST Qt::UserRole + 4 +#define ROLE_SEARCH_SCORE Qt::UserRole + 5 + +#define COMBO_NAME_INDEX 0 +#define COMBO_DESC_INDEX 1 + +GroupTreeWidget::GroupTreeWidget(QWidget *parent) : + QWidget(parent), ui(new Ui::GroupTreeWidget) +{ + ui->setupUi(this); + + displayMenu = NULL; + actionSortAscending = NULL; +// actionSortDescending = NULL; + actionSortByName = NULL; + actionSortByPopularity = NULL; + actionSortByLastPost = NULL; + + compareRole = new RSTreeWidgetItemCompareRole; + compareRole->setRole(COLUMN_DATA, ROLE_NAME); + + /* Connect signals */ + connect(ui->clearFilter, SIGNAL(clicked()), this, SLOT(clearFilter())); + connect(ui->filterText, SIGNAL(textChanged(const QString &)), this, SLOT(filterChanged())); + connect(ui->filterCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(filterChanged())); + + connect(ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint))); + connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + + /* Add own item delegate */ + RSItemDelegate *itemDelegate = new RSItemDelegate(this); + itemDelegate->setSpacing(QSize(0, 2)); + ui->treeWidget->setItemDelegate(itemDelegate); + + /* Initialize tree widget */ + ui->treeWidget->setColumnCount(COLUMN_COUNT); + + /* Set header resize modes and initial section sizes */ + QHeaderView *header = ui->treeWidget->header (); + header->setResizeMode(COLUMN_NAME, QHeaderView::Stretch); + header->resizeSection(COLUMN_NAME, 170); + header->setResizeMode(COLUMN_POPULARITY, QHeaderView::Fixed); + header->resizeSection(COLUMN_POPULARITY, 25); + + /* Initialize filter */ + ui->clearFilter->hide(); +} + +GroupTreeWidget::~GroupTreeWidget() +{ + delete ui; +} + +void GroupTreeWidget::changeEvent(QEvent *e) +{ + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + +void GroupTreeWidget::processSettings(RshareSettings *settings, bool load) +{ + if (settings == NULL) { + return; + } + + const int SORTBY_NAME = 1; + const int SORTBY_POPULRITY = 2; + const int SORTBY_LASTPOST = 3; + + if (load) { + // load settings + + // state of sort + int sortby = settings->value("GroupSortBy").toInt(); + switch (sortby) { + case SORTBY_NAME: + if (actionSortByName) { + actionSortByName->setChecked(true); + } + break; + case SORTBY_POPULRITY: + if (actionSortByPopularity) { + actionSortByPopularity->setChecked(true); + } + break; + case SORTBY_LASTPOST: + if (actionSortByLastPost) { + actionSortByLastPost->setChecked(true); + } + break; + } + } else { + // save settings + + // state of sort + int sortby = SORTBY_NAME; + if (actionSortByName && actionSortByName->isChecked()) { + sortby = SORTBY_NAME; + } else if (actionSortByPopularity && actionSortByPopularity->isChecked()) { + sortby = SORTBY_POPULRITY; + } else if (actionSortByLastPost && actionSortByLastPost->isChecked()) { + sortby = SORTBY_LASTPOST; + } + settings->setValue("GroupSortBy", sortby); + } +} + +void GroupTreeWidget::initDisplayMenu(QPushButton *pushButton) +{ + displayMenu = new QMenu(); +// QActionGroup *actionGroup = new QActionGroup(displayMenu); +// +// actionSortDescending = displayMenu->addAction(QIcon(":/images/sort_decrease.png"), tr("Sort Descending Order"), this, SLOT(sort())); +// actionSortDescending->setCheckable(true); +// actionSortDescending->setActionGroup(actionGroup); +// +// actionSortAscending = displayMenu->addAction(QIcon(":/images/sort_incr.png"), tr("Sort Ascending Order"), this, SLOT(sort())); +// actionSortAscending->setCheckable(true); +// actionSortAscending->setChecked(true); // set standard to sort ascending +// actionSortAscending->setActionGroup(actionGroup); +// +// displayMenu->addSeparator(); + + QActionGroup *actionGroup = new QActionGroup(displayMenu); + actionSortByName = displayMenu->addAction(QIcon(), tr("Sort by Name"), this, SLOT(sort())); + actionSortByName->setCheckable(true); + actionSortByName->setChecked(true); // set standard to sort by name + actionSortByName->setActionGroup(actionGroup); + + actionSortByPopularity = displayMenu->addAction(QIcon(), tr("Sort by Popularity"), this, SLOT(sort())); + actionSortByPopularity->setCheckable(true); + actionSortByPopularity->setActionGroup(actionGroup); + + actionSortByLastPost = displayMenu->addAction(QIcon(), tr("Sort by Last Post"), this, SLOT(sort())); + actionSortByLastPost->setCheckable(true); + actionSortByLastPost->setActionGroup(actionGroup); + + pushButton->setMenu(displayMenu); +} + +void GroupTreeWidget::customContextMenuRequested(const QPoint &pos) +{ + emit treeCustomContextMenuRequested(pos); +} + +void GroupTreeWidget::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + Q_UNUSED(previous); + + QString id; + + if (current) { + id = current->data(COLUMN_DATA, ROLE_ID).toString(); + } + + emit treeCurrentItemChanged(id); +} + +QTreeWidgetItem *GroupTreeWidget::addCategoryItem(const QString &name, const QIcon &icon, bool expand) +{ + QFont font = QFont("ARIAL", 10); + font.setBold(true); + + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(COLUMN_NAME, name); + item->setData(COLUMN_DATA, ROLE_NAME, name); + item->setFont(COLUMN_NAME, font); + item->setIcon(COLUMN_NAME, icon); + item->setSizeHint(COLUMN_NAME, QSize(18, 18)); + item->setForeground(COLUMN_NAME, QBrush(QColor(79, 79, 79))); + + ui->treeWidget->addTopLevelItem(item); + + item->setExpanded(expand); + + return item; +} + +QString GroupTreeWidget::itemId(QTreeWidgetItem *item) +{ + if (item == NULL) { + return ""; + } + + return item->data(COLUMN_DATA, ROLE_ID).toString(); +} + +void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList &itemList) +{ + if (categoryItem == NULL) { + return; + } + + /* Iterate all items */ + QList::const_iterator it; + for (it = itemList.begin(); it != itemList.end(); it++) { + const GroupItemInfo &itemInfo = *it; + + QTreeWidgetItem *item = NULL; + + /* Search exisiting item */ + int childCount = categoryItem->childCount(); + for (int child = 0; child < childCount; child++) { + QTreeWidgetItem *childItem = categoryItem->child(child); + if (childItem->data(COLUMN_DATA, ROLE_ID).toString() == itemInfo.id) { + /* Found child */ + item = childItem; + break; + } + } + + if (item == NULL) { + item = new RSTreeWidgetItem(compareRole); + item->setData(COLUMN_DATA, ROLE_ID, itemInfo.id); + categoryItem->addChild(item); + } + + item->setText(COLUMN_NAME, itemInfo.name); + item->setData(COLUMN_DATA, ROLE_NAME, itemInfo.name); + item->setData(COLUMN_DATA, ROLE_DESCRIPTION, itemInfo.description); + + /* Set last post */ + qlonglong lastPost = itemInfo.lastpost.toTime_t(); + item->setData(COLUMN_DATA, ROLE_LASTPOST, -lastPost); // negative for correct sorting + + /* Set icon */ + item->setIcon(COLUMN_NAME, itemInfo.icon); + + /* Set popularity */ + QString tooltip = PopularityDefs::tooltip(itemInfo.popularity); + item->setIcon(COLUMN_POPULARITY, PopularityDefs::icon(itemInfo.popularity)); + item->setData(COLUMN_DATA, ROLE_POPULARITY, -itemInfo.popularity); // negative for correct sorting + + /* Set tooltip */ + if (itemInfo.privatekey) { + tooltip += "\n" + tr("Private Key Available"); + } + item->setToolTip(COLUMN_NAME, tooltip); + item->setToolTip(COLUMN_POPULARITY, tooltip); + + /* Set color */ + QBrush brush; + if (itemInfo.privatekey) { + brush = QBrush(Qt::blue); + } + item->setForeground(COLUMN_NAME, brush); + + /* Calculate score */ + calculateScore(item); + } + + /* Remove all items not in list */ + int child = 0; + int childCount = categoryItem->childCount(); + while (child < childCount) { + QString id = categoryItem->child(child)->data(COLUMN_DATA, ROLE_ID).toString(); + + for (it = itemList.begin(); it != itemList.end(); it++) { + if (it->id == id) { + break; + } + } + + if (it == itemList.end()) { + delete(categoryItem->takeChild(child)); + childCount = categoryItem->childCount(); + } else { + child++; + } + } + + resort(categoryItem); +} + +void GroupTreeWidget::setUnreadCount(QTreeWidgetItem *item, int unreadCount) +{ + if (item == NULL) { + return; + } + + QString name = item->data(COLUMN_DATA, ROLE_NAME).toString(); + QFont font = item->font(COLUMN_NAME); + + if (unreadCount) { + name += QString(" (%1)").arg(unreadCount); + font.setBold(true); + } else { + font.setBold(false); + } + + item->setText(COLUMN_NAME, name); + item->setFont(COLUMN_NAME, font); + +} + +QTreeWidgetItem *GroupTreeWidget::getItemFromId(const QString &id) +{ + if (id.isEmpty()) { + return NULL; + } + + /* Search exisiting item */ + QTreeWidgetItemIterator itemIterator(ui->treeWidget); + QTreeWidgetItem *item; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + if (item->parent() == NULL) { + continue; + } + if (item->data(COLUMN_DATA, ROLE_ID).toString() == id) { + return item; + } + } + return NULL ; +} + +QTreeWidgetItem *GroupTreeWidget::activateId(const QString &id, bool focus) +{ + QTreeWidgetItem *item = getItemFromId(id); + if (item == NULL) { + return NULL; + } + + ui->treeWidget->setCurrentItem(item); + if (focus) { + ui->treeWidget->setFocus(); + } + return item; +} + +void GroupTreeWidget::calculateScore(QTreeWidgetItem *item) +{ + if (item) { + /* Calculate one item */ + QString filterText = ui->filterText->text(); + int score; + if (filterText.isEmpty()) { + score = 0; + item->setHidden(false); + } else { + QString scoreString; + + switch (ui->filterCombo->currentIndex()) { + case COMBO_NAME_INDEX: + scoreString = item->data(COLUMN_DATA, ROLE_NAME).toString(); + break; + case COMBO_DESC_INDEX: + scoreString = item->data(COLUMN_DATA, ROLE_DESCRIPTION).toString(); + break; + } + + score = scoreString.count(filterText, Qt::CaseInsensitive); + + if (score) { + item->setHidden(false); + } else { + item->setHidden(true); + } + } + + item->setData(COLUMN_DATA, ROLE_SEARCH_SCORE, -score); // negative for correct sorting + + return; + } + + /* Find out which has given word in it */ + QTreeWidgetItemIterator itemIterator(ui->treeWidget); + QTreeWidgetItem *item; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + if (item->data(COLUMN_DATA, ROLE_ID).toString().isEmpty()) { + continue; + } + + calculateScore(item); + } +} + +void GroupTreeWidget::filterChanged() +{ + if (ui->filterText->text().isEmpty()) { + clearFilter(); + return; + } + + ui->clearFilter->setEnabled(true); + ui->clearFilter->show(); + + /* Recalculate score */ + calculateScore(NULL); + + resort(NULL); +} + +void GroupTreeWidget::clearFilter() +{ + ui->filterText->clear(); + ui->clearFilter->hide(); + ui->filterText->setFocus(); + + /* Recalculate score */ + calculateScore(NULL); + + resort(NULL); +} + +void GroupTreeWidget::resort(QTreeWidgetItem *categoryItem) +{ + Qt::SortOrder order = (actionSortAscending == NULL || actionSortAscending->isChecked()) ? Qt::AscendingOrder : Qt::DescendingOrder; + + if (ui->filterText->text().isEmpty() == false) { + compareRole->setRole(COLUMN_DATA, ROLE_SEARCH_SCORE); + compareRole->addRole(COLUMN_DATA, ROLE_LASTPOST); + } else if (actionSortByName && actionSortByName->isChecked()) { + compareRole->setRole(COLUMN_DATA, ROLE_NAME); + } else if (actionSortByPopularity && actionSortByPopularity->isChecked()) { + compareRole->setRole(COLUMN_DATA, ROLE_POPULARITY); + } else if (actionSortByLastPost && actionSortByLastPost->isChecked()) { + compareRole->setRole(COLUMN_DATA, ROLE_LASTPOST); + } + + if (categoryItem) { + categoryItem->sortChildren(COLUMN_DATA, order); + } else { + int count = ui->treeWidget->topLevelItemCount(); + for (int child = 0; child < count; child++) { + ui->treeWidget->topLevelItem(child)->sortChildren(COLUMN_DATA, order); + } + } +} + +void GroupTreeWidget::sort() +{ + resort(NULL); +} diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.h b/retroshare-gui/src/gui/common/GroupTreeWidget.h new file mode 100644 index 000000000..abeae0862 --- /dev/null +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.h @@ -0,0 +1,114 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef GROUPTREEWIDGET_H +#define GROUPTREEWIDGET_H + +#include +#include +#include +#include + +class QPushButton; +class RshareSettings; +class RSTreeWidgetItemCompareRole; + +namespace Ui { + class GroupTreeWidget; +} + +class GroupItemInfo +{ +public: + GroupItemInfo() + { + popularity = 0; + privatekey = false; + } + +public: + QString id; + QString name; + QString description; + int popularity; + QDateTime lastpost; + QIcon icon; + bool privatekey; +}; + +class GroupTreeWidget : public QWidget +{ + Q_OBJECT + +public: + GroupTreeWidget(QWidget *parent = 0); + ~GroupTreeWidget(); + + // Load and save settings (group must be startet from the caller) + void processSettings(RshareSettings *settings, bool load); + // Initialize the display menu for sorting + void initDisplayMenu(QPushButton *pushButton); + + // Add a new category item + QTreeWidgetItem *addCategoryItem(const QString &name, const QIcon &icon, bool expand); + // Get id of item + QString itemId(QTreeWidgetItem *item); + // Fill items of a group + void fillGroupItems(QTreeWidgetItem *categoryItem, const QList &itemList); + // Set the unread count of an item + void setUnreadCount(QTreeWidgetItem *item, int unreadCount); + + QTreeWidgetItem *getItemFromId(const QString &id); + QTreeWidgetItem *activateId(const QString &id, bool focus); + +signals: + void treeCustomContextMenuRequested(const QPoint &pos); + void treeCurrentItemChanged(const QString &id); + +protected: + void changeEvent(QEvent *e); + +private slots: + void customContextMenuRequested(const QPoint &pos); + void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void filterChanged(); + void clearFilter(); + + void sort(); + +private: + void calculateScore(QTreeWidgetItem *item); + void resort(QTreeWidgetItem *categoryItem); + +private: + QMenu *displayMenu; + QAction *actionSortAscending; +// QAction *actionSortDescending; + QAction *actionSortByName; + QAction *actionSortByPopularity; + QAction *actionSortByLastPost; + + RSTreeWidgetItemCompareRole *compareRole; + + Ui::GroupTreeWidget *ui; +}; + +#endif // GROUPTREEWIDGET_H diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.ui b/retroshare-gui/src/gui/common/GroupTreeWidget.ui new file mode 100644 index 000000000..35e0fa1ff --- /dev/null +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.ui @@ -0,0 +1,245 @@ + + + GroupTreeWidget + + + + 0 + 0 + 316 + 257 + + + + QComboBox QAbstractItemView { +background-color:white; +} + +QComboBox::down-arrow { +image: url(:/images/combobox_arrow.png); +} + +QComboBox:drop-down +{ +subcontrol-origin: padding; +subcontrol-position: top right; +border-left-style: none; +border-top-right-radius: 1px; +border-bottom-right-radius: 1px; +} + +QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QComboBox::disabled { +color:gray; +} + + + + 2 + + + 0 + + + + + 0 + + + + + + 0 + 22 + + + + + 16777215 + 16777215 + + + + QFrame#searchlineframe{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 1 + + + 0 + + + + + + 3 + 0 + + + + + 0 + 16 + + + + + 1677777 + 16777215 + + + + Enter a Keyword here + + + QLineEdit#searchLine{ +border: none;} + + + + + + + + + 0 + 20 + + + + + Title + + + + + Description + + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + Qt::NoFocus + + + Reset + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + + + + + true + + + + 0 + 0 + + + + + 9 + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + + 19 + 19 + + + + true + + + false + + + false + + + false + + + false + + + + 1 + + + + + + + + + diff --git a/retroshare-gui/src/gui/common/PeerDefs.cpp b/retroshare-gui/src/gui/common/PeerDefs.cpp new file mode 100644 index 000000000..b8ca4d3b9 --- /dev/null +++ b/retroshare-gui/src/gui/common/PeerDefs.cpp @@ -0,0 +1,95 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "PeerDefs.h" + +const QString PeerDefs::nameWithLocation(const RsPeerDetails &details) +{ + QString name = QString::fromUtf8(details.name.c_str()); + if (details.location.empty() == false) { + name += " (" + QString::fromUtf8(details.location.c_str()) + ")"; + } + + return name; +} + +const QString PeerDefs::rsid(const std::string &name, const std::string &id) +{ + if (name.empty()) { + return qApp->translate("PeerDefs", "Unknown") + "@" + QString::fromStdString(id); + } + + return QString::fromUtf8(name.c_str()) + "@" + QString::fromStdString(id); +} + +const QString PeerDefs::rsid(const RsPeerDetails &details) +{ + return rsid(details.name, details.id); +} + +const QString PeerDefs::rsidFromId(const std::string &id, QString *name /*= NULL*/) +{ + QString rsid; + + std::string peerName = rsPeers->getPeerName(id); + if (peerName.empty()) { + rsid = PeerDefs::rsid("", id); + + if (name) { + *name = qApp->translate("PeerDefs", "Unknown"); + } + } else { + rsid = PeerDefs::rsid(peerName, id); + + if (name) { + *name = QString::fromUtf8(peerName.c_str()); + } + } + + return rsid; +} + +const std::string PeerDefs::idFromRsid(const QString &rsid, bool check) +{ + // search for cert id in string + std::string id; + + int index = rsid.indexOf("@"); + if (index >= 0) { + // found "@", extract cert id from string + id = rsid.mid(index + 1).toStdString(); + } else { + // maybe its only the cert id + id = rsid.toStdString(); + } + + if (check) { + RsPeerDetails detail; + if (rsPeers->getPeerDetails(id, detail) == false) { + id.clear(); + } + } + + return id; +} diff --git a/retroshare-gui/src/gui/common/PeerDefs.h b/retroshare-gui/src/gui/common/PeerDefs.h new file mode 100644 index 000000000..a5eaeb47c --- /dev/null +++ b/retroshare-gui/src/gui/common/PeerDefs.h @@ -0,0 +1,42 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _PEERDEFS_H +#define _PEERDEFS_H + +#include + +class RsPeerDetails; + +class PeerDefs +{ +public: + static const QString nameWithLocation(const RsPeerDetails &details); + + static const QString rsid(const RsPeerDetails &details); + static const QString rsid(const std::string &name, const std::string &id); + static const QString rsidFromId(const std::string &id, QString *name = NULL); + static const std::string idFromRsid(const QString &rsid, bool check); +}; + +#endif + diff --git a/retroshare-gui/src/gui/common/PopularityDefs.cpp b/retroshare-gui/src/gui/common/PopularityDefs.cpp new file mode 100644 index 000000000..56805c76f --- /dev/null +++ b/retroshare-gui/src/gui/common/PopularityDefs.cpp @@ -0,0 +1,51 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "PopularityDefs.h" + +QIcon PopularityDefs::icon(int popularity) +{ + if (popularity == 0) { + return QIcon(":/images/hot_0.png"); + } else if (popularity <= 7) { + /* 1-7 */ + return QIcon(":/images/hot_1.png"); + } else if (popularity <= 15) { + /* 8-15 */ + return QIcon(":/images/hot_2.png"); + } else if (popularity <= 24) { + /* 16-24 */ + return QIcon(":/images/hot_3.png"); + } else if (popularity <= 34) { + /* 25-34 */ + return QIcon(":/images/hot_4.png"); + } + + /* >34 */ + return QIcon(":/images/hot_5.png"); +} + +QString PopularityDefs::tooltip(int popularity) +{ + return QString("%1: %2").arg(qApp->translate("PopularityDefs", "Popularity")).arg(popularity); +} diff --git a/retroshare-gui/src/gui/common/PopularityDefs.h b/retroshare-gui/src/gui/common/PopularityDefs.h new file mode 100644 index 000000000..5d989786d --- /dev/null +++ b/retroshare-gui/src/gui/common/PopularityDefs.h @@ -0,0 +1,36 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _POPULARITYDEFS_H +#define _POPULARITYDEFS_H + +#include + +class PopularityDefs +{ +public: + static QIcon icon(int popularity); + static QString tooltip(int popularity); +}; + +#endif + diff --git a/retroshare-gui/src/gui/common/RSItemDelegate.cpp b/retroshare-gui/src/gui/common/RSItemDelegate.cpp new file mode 100644 index 000000000..bf53e9653 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSItemDelegate.cpp @@ -0,0 +1,64 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "RSItemDelegate.h" + +RSItemDelegate::RSItemDelegate(QObject *parent) : QItemDelegate(parent) +{ +} + +void RSItemDelegate::paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem ownOption (option); + + if (m_noFocusRect.indexOf(index.column()) >= 0) { + ownOption.state &= ~QStyle::State_HasFocus; // don't show text and focus rectangle + } + + QItemDelegate::paint (painter, ownOption, index); +} + +QSize RSItemDelegate::sizeHint (const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem ownOption (option); + + if (m_noFocusRect.indexOf(index.column()) >= 0) { + ownOption.state &= ~QStyle::State_HasFocus; // don't show text and focus rectangle + } + + QSize size = QItemDelegate::sizeHint(ownOption, index); + + size += m_spacing; + + return size; +} + +void RSItemDelegate::removeFocusRect(int column) +{ + if (m_noFocusRect.indexOf(column) == -1) { + m_noFocusRect.push_back(column); + } +} + +void RSItemDelegate::setSpacing(const QSize &spacing) +{ + m_spacing = spacing; +} diff --git a/retroshare-gui/src/gui/common/RSItemDelegate.h b/retroshare-gui/src/gui/common/RSItemDelegate.h new file mode 100644 index 000000000..1b4aedf8f --- /dev/null +++ b/retroshare-gui/src/gui/common/RSItemDelegate.h @@ -0,0 +1,45 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _RSITEMDELEGATE_H +#define _RSITEMDELEGATE_H + +#include + +class RSItemDelegate : public QItemDelegate +{ +public: + RSItemDelegate(QObject *parent = 0); + + void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint (const QStyleOptionViewItem &option, const QModelIndex &index) const; + + void removeFocusRect(int column); + void setSpacing(const QSize &spacing); + +private: + QList m_noFocusRect; + QSize m_spacing; +}; + +#endif + diff --git a/retroshare-gui/src/gui/common/RSTabWidget.cpp b/retroshare-gui/src/gui/common/RSTabWidget.cpp new file mode 100644 index 000000000..b9e3f79de --- /dev/null +++ b/retroshare-gui/src/gui/common/RSTabWidget.cpp @@ -0,0 +1,31 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "RSTabWidget.h" + +RSTabWidget::RSTabWidget(QWidget *parent) : QTabWidget(parent) +{ +} + +QTabBar *RSTabWidget::tabBar() const +{ + return QTabWidget::tabBar(); +}; diff --git a/retroshare-gui/src/gui/common/RSTabWidget.h b/retroshare-gui/src/gui/common/RSTabWidget.h new file mode 100644 index 000000000..68a728554 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSTabWidget.h @@ -0,0 +1,37 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _RSTABWIDGET_H +#define _RSTABWIDGET_H + +#include + +/* Subclassing QTabWidget to get the instance of QTabBar. The base method of QTabWidget is protected. */ +class RSTabWidget : public QTabWidget +{ +public: + RSTabWidget(QWidget *parent = 0); + +public: + QTabBar *tabBar() const; +}; + +#endif diff --git a/retroshare-gui/src/gui/common/RSTreeView.cpp b/retroshare-gui/src/gui/common/RSTreeView.cpp new file mode 100644 index 000000000..6d9e4f61c --- /dev/null +++ b/retroshare-gui/src/gui/common/RSTreeView.cpp @@ -0,0 +1,51 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include "RSTreeView.h" + +RSTreeView::RSTreeView(QWidget *parent) : QTreeView(parent) +{ +} + +void RSTreeView::setPlaceholderText(const QString &text) +{ + placeholderText = text; + repaint(); +} + +void RSTreeView::paintEvent(QPaintEvent *event) +{ + QTreeView::paintEvent(event); + + if (placeholderText.isEmpty() == false && model() && model()->rowCount() == 0) { + QWidget *vieportWidget = viewport(); + QPainter painter(vieportWidget); + + QPen pen = painter.pen(); + QColor color = pen.color(); + color.setAlpha(128); + pen.setColor(color); + painter.setPen(pen); + + painter.drawText(QRect(QPoint(), vieportWidget->size()), Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextWordWrap, placeholderText); + } +}; diff --git a/retroshare-gui/src/gui/common/RSTreeView.h b/retroshare-gui/src/gui/common/RSTreeView.h new file mode 100644 index 000000000..789728870 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSTreeView.h @@ -0,0 +1,43 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _RSTREEVIEW_H +#define _RSTREEVIEW_H + +#include + +/* Subclassing QTreeView */ +class RSTreeView : public QTreeView +{ + Q_OBJECT + +public: + RSTreeView(QWidget *parent = 0); + + void setPlaceholderText(const QString &text); + +protected: + void paintEvent(QPaintEvent *event); + + QString placeholderText; +}; + +#endif diff --git a/retroshare-gui/src/gui/common/RSTreeWidgetItem.cpp b/retroshare-gui/src/gui/common/RSTreeWidgetItem.cpp new file mode 100644 index 000000000..573a57d8b --- /dev/null +++ b/retroshare-gui/src/gui/common/RSTreeWidgetItem.cpp @@ -0,0 +1,171 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "RSTreeWidgetItem.h" + +RSTreeWidgetItemCompareRole::RSTreeWidgetItemCompareRole() +{ +} + +void RSTreeWidgetItemCompareRole::setRole(int column, int role) +{ + QList roles; + roles.push_back(role); + insert(column, roles); +} + +void RSTreeWidgetItemCompareRole::addRole(int column, int role) +{ + RSTreeWidgetItemCompareRole::iterator it = find(column); + if (it == end()) { + setRole(column, role); + return; + } + + it.value().push_back(role); +} + +void RSTreeWidgetItemCompareRole::findRoles(const int column, QList &roles) const +{ + RSTreeWidgetItemCompareRole::const_iterator it = find(column); + if (it == end()) { + roles.clear(); + roles.push_back(Qt::DisplayRole); + return; + } + + roles = it.value(); +} + +RSTreeWidgetItem::RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, int type) : QTreeWidgetItem(type) +{ + m_compareRole = compareRole; +} + +RSTreeWidgetItem::RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, const QStringList &strings, int type) : QTreeWidgetItem(strings, type) +{ + m_compareRole = compareRole; +} + +RSTreeWidgetItem::RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidget *view, const QStringList &strings, int type) : QTreeWidgetItem(view, strings, type) +{ + m_compareRole = compareRole; +} + +RSTreeWidgetItem::RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidget *view, QTreeWidgetItem *after, int type) : QTreeWidgetItem(view, after, type) +{ + m_compareRole = compareRole; +} + +RSTreeWidgetItem::RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidgetItem *parent, const QStringList &strings, int type) : QTreeWidgetItem(parent, strings, type) +{ + m_compareRole = compareRole; +} + +RSTreeWidgetItem::RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidgetItem *parent, QTreeWidgetItem *after, int type) : QTreeWidgetItem(parent, after, type) +{ + m_compareRole = compareRole; +} + +RSTreeWidgetItem::RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, const QTreeWidgetItem &other) : QTreeWidgetItem(other) +{ + m_compareRole = compareRole; +} + +static uint typeOfVariant(const QVariant &value) +{ + //return 0 for integer, 1 for floating point and 2 for other + switch (value.userType()) { + case QVariant::Bool: + case QVariant::Int: + case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: + case QVariant::Char: + case QMetaType::Short: + case QMetaType::UShort: + case QMetaType::UChar: + case QMetaType::ULong: + case QMetaType::Long: + return 0; + case QVariant::Double: + case QMetaType::Float: + return 1; + default: + return 2; + } +} + +bool RSTreeWidgetItem::operator<(const QTreeWidgetItem &other) const +{ + int column = treeWidget()->sortColumn(); + QList roles; + + /* Own role for sort defined ? */ + if (m_compareRole) { + m_compareRole->findRoles(column, roles); + } + + QList::iterator role; + for (role = roles.begin(); role != roles.end(); role++) { + // taken from "bool QTreeWidgetItem::operator<(const QTreeWidgetItem &other) const" + const QVariant v1 = data(column, *role); + const QVariant v2 = other.data(column, *role); + + // taken from "bool QAbstractItemModelPrivate::variantLessThan(const QVariant &v1, const QVariant &v2)" + switch(qMax(typeOfVariant(v1), typeOfVariant(v2))) + { + case 0: //integer type + { + qlonglong value1 = v1.toLongLong(); + qlonglong value2 = v2.toLongLong(); + + if (value1 != value2) { + return value1 < value2; + } + } + break; + case 1: //floating point + { + double value1 = v1.toDouble(); + double value2 = v2.toDouble(); + + if (value1 != value2) { + return value1 < value2; + } + } + break; + default: + { + int compare = v1.toString().compare (v2.toString(), Qt::CaseInsensitive); + if (compare) { + return (compare < 0); + } + } + } + } + + /* Compare DisplayRole */ + const QVariant v1 = data(column, Qt::DisplayRole); + const QVariant v2 = other.data(column, Qt::DisplayRole); + + return (v1.toString().compare (v2.toString(), Qt::CaseInsensitive) < 0); +} diff --git a/retroshare-gui/src/gui/common/RSTreeWidgetItem.h b/retroshare-gui/src/gui/common/RSTreeWidgetItem.h new file mode 100644 index 000000000..8dc0754e4 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSTreeWidgetItem.h @@ -0,0 +1,59 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _RSTREEWIDGETITEM_H +#define _RSTREEWIDGETITEM_H + +#include +#include +#include + +/* For definition of the UserRole for comparing */ +class RSTreeWidgetItemCompareRole : QMap > +{ +public: + RSTreeWidgetItemCompareRole(); + + void setRole(int column, int role); + void addRole(int column, int role); + void findRoles(const int column, QList &roles) const; +}; + +class RSTreeWidgetItem : public QTreeWidgetItem +{ +public: + RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole = NULL, int type = Type); + RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, const QStringList &strings, int type = Type); + RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidget *view, const QStringList &strings, int type = Type); + RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidget *view, QTreeWidgetItem *after, int type = Type); + RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidgetItem *parent, const QStringList &strings, int type = Type); + RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidgetItem *parent, QTreeWidgetItem *after, int type = Type); + RSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, const QTreeWidgetItem &other); + + bool operator<(const QTreeWidgetItem &other) const; + +private: + const RSTreeWidgetItemCompareRole *m_compareRole; +}; + +#endif + diff --git a/retroshare-gui/src/gui/common/StatusDefs.cpp b/retroshare-gui/src/gui/common/StatusDefs.cpp new file mode 100644 index 000000000..8c0a5fdd6 --- /dev/null +++ b/retroshare-gui/src/gui/common/StatusDefs.cpp @@ -0,0 +1,205 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include "StatusDefs.h" + +QString StatusDefs::name(unsigned int status) +{ + switch (status) { + case RS_STATUS_OFFLINE: + return qApp->translate("StatusDefs", "Offline"); + case RS_STATUS_AWAY: + return qApp->translate("StatusDefs", "Away"); + case RS_STATUS_BUSY: + return qApp->translate("StatusDefs", "Busy"); + case RS_STATUS_ONLINE: + return qApp->translate("StatusDefs", "Online"); + case RS_STATUS_INACTIVE: + return qApp->translate("StatusDefs", "Idle"); + } + + std::cerr << "StatusDefs::name: Unknown status requested " << status; + return ""; +} + +const char *StatusDefs::imageIM(unsigned int status) +{ + switch (status) { + case RS_STATUS_OFFLINE: + return ":/images/im-user-offline.png"; + case RS_STATUS_AWAY: + return ":/images/im-user-away.png"; + case RS_STATUS_BUSY: + return ":/images/im-user-busy.png"; + case RS_STATUS_ONLINE: + return ":/images/im-user.png"; + case RS_STATUS_INACTIVE: + return ":/images/im-user-inactive.png"; + } + + std::cerr << "StatusDefs::imageIM: Unknown status requested " << status; + return ""; +} + +const char *StatusDefs::imageUser(unsigned int status) +{ + switch (status) { + case RS_STATUS_OFFLINE: + return ":/images/user/identityoffline24.png"; + case RS_STATUS_AWAY: + return ":/images/user/identity24away.png"; + case RS_STATUS_BUSY: + return ":/images/user/identity24busy.png"; + case RS_STATUS_ONLINE: + return ":/images/user/identity24.png"; + case RS_STATUS_INACTIVE: + return ":/images/user/identity24idle.png"; + } + + std::cerr << "StatusDefs::imageUser: Unknown status requested " << status; + return ""; +} + +QString StatusDefs::tooltip(unsigned int status) +{ + switch (status) { + case RS_STATUS_OFFLINE: + return qApp->translate("StatusDefs", "Friend is offline"); + case RS_STATUS_AWAY: + return qApp->translate("StatusDefs", "Friend is away"); + case RS_STATUS_BUSY: + return qApp->translate("StatusDefs", "Friend is busy"); + case RS_STATUS_ONLINE: + return qApp->translate("StatusDefs", "Friend is online"); + case RS_STATUS_INACTIVE: + return qApp->translate("StatusDefs", "Friend is idle"); + } + + std::cerr << "StatusDefs::tooltip: Unknown status requested " << status; + return ""; +} + +QColor StatusDefs::textColor(unsigned int status) +{ + switch (status) { + case RS_STATUS_OFFLINE: + return Qt::black; + case RS_STATUS_AWAY: + return Qt::gray; + case RS_STATUS_BUSY: + return Qt::gray; + case RS_STATUS_ONLINE: + return Qt::darkBlue; + case RS_STATUS_INACTIVE: + return Qt::gray; + } + + std::cerr << "StatusDefs::textColor: Unknown status requested " << status; + return Qt::black; +} + +QFont StatusDefs::font(unsigned int status) +{ + QFont font; + + switch (status) { + case RS_STATUS_AWAY: + case RS_STATUS_BUSY: + case RS_STATUS_ONLINE: + case RS_STATUS_INACTIVE: + font.setBold(true); + return font; + case RS_STATUS_OFFLINE: + font.setBold(false); + return font; + } + + std::cerr << "StatusDefs::font: Unknown status requested " << status; + return font; +} + +QString StatusDefs::peerStateString(int peerState) +{ + if (peerState & RS_PEER_STATE_CONNECTED) { + return qApp->translate("StatusDefs", "Connected"); + } else if (peerState & RS_PEER_STATE_UNREACHABLE) { + return qApp->translate("StatusDefs", "Unreachable"); + } else if (peerState & RS_PEER_STATE_ONLINE) { + return qApp->translate("StatusDefs", "Available"); + } else if (peerState & RS_PEER_STATE_FRIEND) { + return qApp->translate("StatusDefs", "Offline"); + } + + return qApp->translate("StatusDefs", "Neighbour"); +} + +QString StatusDefs::connectStateString(RsPeerDetails &details) +{ + QString stateString; + + switch (details.connectState) { + case 0: + stateString = peerStateString(details.state); + break; + case RS_PEER_CONNECTSTATE_TRYING_TUNNEL: + stateString = qApp->translate("StatusDefs", "Trying tunnel connection"); + break; + case RS_PEER_CONNECTSTATE_TRYING_TCP: + stateString = qApp->translate("StatusDefs", "Trying TCP"); + break; + case RS_PEER_CONNECTSTATE_TRYING_UDP: + stateString = qApp->translate("StatusDefs", "Trying UDP"); + break; + case RS_PEER_CONNECTSTATE_CONNECTED_TCP: + stateString = qApp->translate("StatusDefs", "Connected: TCP"); + break; + case RS_PEER_CONNECTSTATE_CONNECTED_UDP: + stateString = qApp->translate("StatusDefs", "Connected: UDP"); + break; + case RS_PEER_CONNECTSTATE_CONNECTED_TUNNEL: + stateString = qApp->translate("StatusDefs", "Connected: Tunnel"); + break; + case RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN: + stateString = qApp->translate("StatusDefs", "Connected: Unknown"); + break; + } + + if (details.connectStateString.empty() == false) { + if (stateString.isEmpty() == false) { + stateString += ": "; + } + stateString += QString::fromStdString(details.connectStateString); + } + + /* HACK to display DHT Status info too */ + if (details.foundDHT) { + if (stateString.isEmpty() == false) { + stateString += ", "; + } + stateString += qApp->translate("StatusDefs", "DHT: Contact"); + } + + return stateString; +} diff --git a/retroshare-gui/src/gui/common/StatusDefs.h b/retroshare-gui/src/gui/common/StatusDefs.h new file mode 100644 index 000000000..25066c15d --- /dev/null +++ b/retroshare-gui/src/gui/common/StatusDefs.h @@ -0,0 +1,47 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _STATUSDEFS_H +#define _STATUSDEFS_H + +#include +#include + +class RsPeerDetails; + +class StatusDefs +{ +public: + static QString name(unsigned int status); + static const char* imageIM(unsigned int status); + static const char* imageUser(unsigned int status); + static QString tooltip(unsigned int status); + + static QColor textColor(unsigned int status); + static QFont font(unsigned int status); + + static QString peerStateString(int peerState); + static QString connectStateString(RsPeerDetails &details); +}; + +#endif + diff --git a/retroshare-gui/src/gui/common/TagDefs.cpp b/retroshare-gui/src/gui/common/TagDefs.cpp new file mode 100644 index 000000000..a4c12f0ed --- /dev/null +++ b/retroshare-gui/src/gui/common/TagDefs.cpp @@ -0,0 +1,73 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include + +#include "TagDefs.h" + +const QString TagDefs::name(const unsigned int tagId, const std::string &text) +{ + if (tagId >= RS_MSGTAGTYPE_USER) { + /* no need to be translated */ + return QString::fromStdString(text); + } + + switch (tagId) { + case RS_MSGTAGTYPE_IMPORTANT: + return qApp->translate("TagDefs", "Important"); + case RS_MSGTAGTYPE_WORK: + return qApp->translate("TagDefs", "Work"); + case RS_MSGTAGTYPE_PERSONAL: + return qApp->translate("TagDefs", "Personal"); + case RS_MSGTAGTYPE_TODO: + return qApp->translate("TagDefs", "Todo"); + case RS_MSGTAGTYPE_LATER: + return qApp->translate("TagDefs", "Later"); + } + + std::cerr << "TagDefs::name: Unknown tag id requested " << tagId; + return ""; +} + +const QString TagDefs::labelStyleSheet(const QColor &color) +{ + /* calculate best text color */ + QRgb textColor; + if (qGray(color.rgb()) < 128) { + /* dark color, use white */ + textColor = qRgb(255, 255, 255); + } else { + /* light color, use black */ + textColor = qRgb(0, 0, 0); + } + + QColor colorBorder = color.darker(120); + QColor colorGradient = color.lighter(150); + + return QString("QLabel{padding-left: 2px; padding-right: 2px; color: #%1; background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #%2, stop:1 #%3); border-radius: 3px; border-color: #%4; border-width: 1; border-style: solid}") + .arg(textColor & RGB_MASK, 6, 16, QChar('0')) + .arg(colorGradient.rgb() & RGB_MASK, 6, 16, QChar('0')) + .arg(color.rgb() & RGB_MASK, 6, 16, QChar('0')) + .arg(colorBorder.rgb() & RGB_MASK, 6, 16, QChar('0')); +} diff --git a/retroshare-gui/src/gui/common/TagDefs.h b/retroshare-gui/src/gui/common/TagDefs.h new file mode 100644 index 000000000..30211a50b --- /dev/null +++ b/retroshare-gui/src/gui/common/TagDefs.h @@ -0,0 +1,36 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _TAGDEFS_H +#define _TAGDEFS_H + +class QColor; + +class TagDefs +{ +public: + static const QString name(const unsigned int tagId, const std::string &text); + static const QString labelStyleSheet(const QColor &color); +}; + +#endif + diff --git a/retroshare-gui/src/gui/common/html.cpp b/retroshare-gui/src/gui/common/html.cpp new file mode 100644 index 000000000..4f1772e15 --- /dev/null +++ b/retroshare-gui/src/gui/common/html.cpp @@ -0,0 +1,86 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* +** \file html.cpp +** \version $Id: html.cpp 2362 2008-02-29 04:30:11Z edmanm $ +** \brief HTML formatting functions +*/ + +#include "html.h" + + +/** Wraps a string in "

    " tags, converts "\n" to "
    " and converts "\n\n" + * to a new paragraph. */ +QString +p(QString str) +{ + str = "

    " + str + "

    "; + str.replace("\n\n", "

    "); + str.replace("\n", "
    "); + return str; +} + +/** Wraps a string in "" tags. */ +QString +i(QString str) +{ + return QString("%1").arg(str); +} + +/** Wraps a string in "" tags. */ +QString +b(QString str) +{ + return QString("%1").arg(str); +} + +/** Wraps a string in "" tags. */ +QString +trow(QString str) +{ + return QString("%1").arg(str); +} + +/** Wraps a string in "" tags. */ +QString +tcol(QString str) +{ + return QString("%1").arg(str); +} + +/** Wraps a string in "" tags. */ +QString +thead(QString str) +{ + return QString("%1").arg(str); +} + +/** Escapes "<" and ">" characters in the given string. */ +QString +escape(QString str) +{ + str.replace("<", "<"); + str.replace(">", ">"); + return str; +} + diff --git a/retroshare-gui/src/gui/common/html.h b/retroshare-gui/src/gui/common/html.h new file mode 100644 index 000000000..9eb4ca9bc --- /dev/null +++ b/retroshare-gui/src/gui/common/html.h @@ -0,0 +1,58 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* +** \file html.h +** \version $Id: html.h 2362 2008-02-29 04:30:11Z edmanm $ +** \brief HTML formatting functions +*/ + +#ifndef _HTML_H +#define _HTML_H + +#include + + +/** Wraps a string in "

    " tags, converts "\n" to "
    " and converts "\n\n" + * to a new paragraph. */ +QString p(QString str); + +/** Wraps a string in "" tags. */ +QString i(QString str); + +/** Wraps a string in "" tags. */ +QString b(QString str); + +/** Wraps a string in "" tags. */ +QString trow(QString str); + +/** Wraps a string in "" tags. */ +QString tcol(QString str); + +/** Wraps a string in "" tags. */ +QString thead(QString str); + +/** Escapes "<" and ">" characters in a string, for html. */ +QString escape(QString str); + +#endif + diff --git a/retroshare-gui/src/gui/common/rwindow.cpp b/retroshare-gui/src/gui/common/rwindow.cpp new file mode 100644 index 000000000..94ec711e7 --- /dev/null +++ b/retroshare-gui/src/gui/common/rwindow.cpp @@ -0,0 +1,142 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include "rwindow.h" + + +/** Default constructor. */ +RWindow::RWindow(QString name, QWidget *parent, Qt::WFlags flags) + : QMainWindow(parent, flags) +{ + _name = name; + m_bSaveStateOnClose = false; +} + +/** Destructor. */ +RWindow::~RWindow() +{ + saveWindowState(); +} + +/** Associates a shortcut key sequence with a slot. */ +void +RWindow::setShortcut(QString shortcut, const char *slot) +{ + rApp->createShortcut(QKeySequence(shortcut), this, this, slot); +} + +/** Saves the size and location of the window. */ +void +RWindow::saveWindowState() +{ + if (m_bSaveStateOnClose == false) { + // nothing to save + return; + } + +#if QT_VERSION >= 0x040200 + saveSetting("Geometry", saveGeometry()); +#else + saveSetting("Size", size()); + saveSetting("Position", pos()); +#endif +} + +/** Restores the last size and location of the window. */ +void +RWindow::restoreWindowState() +{ + m_bSaveStateOnClose = true; // now we save the window state on close + +#if QT_VERSION >= 0x040200 + QByteArray geometry = getSetting("Geometry", QByteArray()).toByteArray(); + if (geometry.isEmpty()) + adjustSize(); + else + restoreGeometry(geometry); +#else + QRect screen = QDesktopWidget().availableGeometry(); + + /* Restore the window size. */ + QSize size = getSetting("Size", QSize()).toSize(); + if (!size.isEmpty()) { + size = size.boundedTo(screen.size()); + resize(size); + } + + /* Restore the window position. */ + QPoint pos = getSetting("Position", QPoint()).toPoint(); + if (!pos.isNull() && screen.contains(pos)) { + move(pos); + } +#endif +} + +/** Gets the saved value of a property associated with this window object. + * If no value was saved, the default value is returned. */ +QVariant +RWindow::getSetting(QString setting, QVariant defaultValue) +{ + RSettings settings(_name); + return settings.value(setting, defaultValue); +} + +/** Saves a value associated with a property name for this window object. */ +void +RWindow::saveSetting(QString prop, QVariant value) +{ + RSettings settings(_name); + settings.setValue(prop, value); +} + +/** Overloaded QWidget::setVisible(). If this window is already visible and + * visible is true, this window will be brought to the top and given + * focus. If visible is false, then the window state will be saved and + * this window will be hidden. */ +void +RWindow::setVisible(bool visible) +{ + if (visible) { + /* Bring the window to the top, if it's already open. Otherwise, make the + * window visible. */ + if (isVisible()) { + activateWindow(); + setWindowState(windowState() & ~Qt::WindowMinimized | Qt::WindowActive); + raise(); + } else { + restoreWindowState(); + } + } else { + /* Save the last size and position of this window. */ + saveWindowState(); + } + QMainWindow::setVisible(visible); +} + diff --git a/retroshare-gui/src/gui/common/rwindow.h b/retroshare-gui/src/gui/common/rwindow.h new file mode 100644 index 000000000..14d85c2ad --- /dev/null +++ b/retroshare-gui/src/gui/common/rwindow.h @@ -0,0 +1,77 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _RETROSHAREWINDOW_H +#define _RETROSHAREWINDOW_H + +#include +#include +#include +#include +#include + + +class RWindow : public QMainWindow +{ + Q_OBJECT + +public: + /** Default constructor. */ + RWindow(QString name, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Destructor. */ + ~RWindow(); + + /** Associates a shortcut key sequence with a slot. */ + void setShortcut(QString shortcut, const char *slot); + /** Saves the size and location of the window. */ + void saveWindowState(); + /** Restores the last size and location of the window. */ + void restoreWindowState(); + + /** Gets the saved value of a property associated with this window object. + * If no value was saved, the default value is returned. */ + QVariant getSetting(QString name, QVariant defaultValue); + /** Saves a value associated with a setting name for this window object. */ + void saveSetting(QString name, QVariant value); + +public slots: + /** Shows or hides this window. */ + virtual void setVisible(bool visible); + /** Show this window. This method really just exists for subclasses to + * override, since QMainWindow::show() is non-virtual. */ + virtual void showWindow() { QMainWindow::show(); } + +signals: + /** Emitted when a RWindow requests help information on the specified + * topic. */ + void helpRequested(const QString &topic); + +protected: + QString _name; /**< Name associated with this window. */ + +private: + bool m_bSaveStateOnClose; // is set to true in restoreWindowState +}; + +#endif + diff --git a/retroshare-gui/src/gui/common/vmessagebox.cpp b/retroshare-gui/src/gui/common/vmessagebox.cpp new file mode 100644 index 000000000..933310acd --- /dev/null +++ b/retroshare-gui/src/gui/common/vmessagebox.cpp @@ -0,0 +1,172 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* +** \file vmessagebox.cpp +** \version $Id: vmessagebox.cpp 2362 2008-02-29 04:30:11Z edmanm $ +** \brief Provides a custom Vidalia mesage box +*/ + +#include "html.h" +#include "vmessagebox.h" + + +/** Default constructor. */ +VMessageBox::VMessageBox(QWidget *parent) +: QMessageBox(parent) +{ +} + +/** Returns the button (0, 1, or 2) that is OR-ed with QMessageBox::Default, + * or 0 if none are. */ +int +VMessageBox::defaultButton(int button0, int button1, int button2) +{ + Q_UNUSED(button0); + int defaultButton = 0; + if (button1 & QMessageBox::Default) { + defaultButton = 1; + } else if (button2 & QMessageBox::Default) { + defaultButton = 2; + } + return defaultButton; +} + +/** Returns the button (0, 1, or 2) that is OR-ed with QMessageBox::Escape, + * or -1 if none are. */ +int +VMessageBox::escapeButton(int button0, int button1, int button2) +{ + int escapeButton = -1; + if (button0 & QMessageBox::Escape) { + escapeButton = 0; + } else if (button1 & QMessageBox::Escape) { + escapeButton = 1; + } else if (button2 & QMessageBox::Escape) { + escapeButton = 2; + } + return escapeButton; +} + +/** Returns the Button enum value from the given return value. */ +int +VMessageBox::selected(int ret, int button0, int button1, int button2) +{ + if (ret == 0) { + return (button0 & QMessageBox::ButtonMask); + } else if (ret == 1) { + return (button1 & QMessageBox::ButtonMask); + } + return (button2 & QMessageBox::ButtonMask); +} + +/** Converts a Button enum value to a translated string. */ +QString +VMessageBox::buttonText(int btn) +{ + QString text; + int button = (btn & ~QMessageBox::FlagMask); + switch (button) { + case Ok: text = tr("OK"); break; + case Cancel: text = tr("Cancel"); break; + case Yes: text = tr("Yes"); break; + case No: text = tr("No"); break; + case Help: text = tr("Help"); break; + case Retry: text = tr("Retry"); break; + case ShowLog: text = tr("Show Log"); break; + case ShowSettings: text = tr("Show Settings"); break; + case Continue: text = tr("Continue"); break; + case Quit: text = tr("Quit"); break; + case Browse: text = tr("Browse"); break; + default: break; + } + return text; +} + +/** Displays a critical message box with the given caption, message text, and + * visible buttons. To specify a button as a default button or an escape + * button, OR the Button enum value with QMessageBox::Default or + * QMessageBox::Escape, respectively. */ +int +VMessageBox::critical(QWidget *parent, QString caption, QString text, + int button0, int button1, int button2) +{ + int ret = QMessageBox::critical(parent, caption, p(text), + VMessageBox::buttonText(button0), + VMessageBox::buttonText(button1), + VMessageBox::buttonText(button2), + VMessageBox::defaultButton(button0, button1, button2), + VMessageBox::escapeButton(button0, button1, button2)); + return VMessageBox::selected(ret, button0, button1, button2); +} + +/** Displays an question message box with the given caption, message text, and + * visible buttons. To specify a button as a default button or an escape + * button, OR the Button enum value with QMessageBox::Default or + * QMessageBox::Escape, respectively. */ +int +VMessageBox::question(QWidget *parent, QString caption, QString text, + int button0, int button1, int button2) +{ + int ret = QMessageBox::question(parent, caption, p(text), + VMessageBox::buttonText(button0), + VMessageBox::buttonText(button1), + VMessageBox::buttonText(button2), + VMessageBox::defaultButton(button0, button1, button2), + VMessageBox::escapeButton(button0, button1, button2)); + return VMessageBox::selected(ret, button0, button1, button2); +} + +/** Displays an information message box with the given caption, message text, and + * visible buttons. To specify a button as a default button or an escape + * button, OR the Button enum value with QMessageBox::Default or + * QMessageBox::Escape, respectively. */ +int +VMessageBox::information(QWidget *parent, QString caption, QString text, + int button0, int button1, int button2) +{ + int ret = QMessageBox::information(parent, caption, p(text), + VMessageBox::buttonText(button0), + VMessageBox::buttonText(button1), + VMessageBox::buttonText(button2), + VMessageBox::defaultButton(button0, button1, button2), + VMessageBox::escapeButton(button0, button1, button2)); + return VMessageBox::selected(ret, button0, button1, button2); +} + +/** Displays a warning message box with the given caption, message text, and + * visible buttons. To specify a button as a default button or an escape + * button, OR the Button enum value with QMessageBox::Default or + * QMessageBox::Escape, respectively. */ +int +VMessageBox::warning(QWidget *parent, QString caption, QString text, + int button0, int button1, int button2) +{ + int ret = QMessageBox::warning(parent, caption, p(text), + VMessageBox::buttonText(button0), + VMessageBox::buttonText(button1), + VMessageBox::buttonText(button2), + VMessageBox::defaultButton(button0, button1, button2), + VMessageBox::escapeButton(button0, button1, button2)); + return VMessageBox::selected(ret, button0, button1, button2); +} + diff --git a/retroshare-gui/src/gui/common/vmessagebox.h b/retroshare-gui/src/gui/common/vmessagebox.h new file mode 100644 index 000000000..4a5b307ec --- /dev/null +++ b/retroshare-gui/src/gui/common/vmessagebox.h @@ -0,0 +1,106 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* +** \file vmessagebox.h +** \version $Id: vmessagebox.h 2362 2008-02-29 04:30:11Z edmanm $ +** \brief Provides a custom Vidalia mesage box +*/ + +#ifndef _VMESSAGEBOX_H +#define _VMESSAGEBOX_H + +#include +#include + + +class VMessageBox : public QMessageBox +{ + Q_OBJECT + +public: + enum Button { + NoButton = 0, + Ok, + Cancel, + Yes, + No, + Help, + Retry, + ShowLog, + ShowSettings, + Continue, + Quit, + Browse + }; + + /** Default constructor. */ + VMessageBox(QWidget *parent = 0); + + /** Displays an critical message box with the given caption, message text, + * and visible buttons. To specify a button as a default button or an escape + * button, OR the Button enum value with QMessageBox::Default or + * QMessageBox::Escape, respectively. */ + static int critical(QWidget *parent, QString caption, QString text, + int button0, int button1 = NoButton, + int button2 = NoButton); + + /** Displays an information message box with the given caption, message text, + * and visible buttons. To specify a button as a default button or an escape + * button, OR the Button enum value with QMessageBox::Default or + * QMessageBox::Escape, respectively. */ + static int information(QWidget *parent, QString caption, QString text, + int button0, int button1 = NoButton, + int button2 = NoButton); + + /** Displays a warning message box with the given caption, message text, and + * visible buttons. To specify as a default button or an escape + * button, OR the Button enum value with QMessageBox::Default or + * QMessageBox::Escape, respectively. */ + static int warning(QWidget *parent, QString caption, QString text, + int button0, int button1 = NoButton, + int button2 = NoButton); + + /** Displays a warning message box with the given caption, message text, and + * visible buttons. To specify as a default button or an escape + * button, OR the Button enum value with QMessageBox::Default or + * QMessageBox::Escape, respectively. */ + static int question(QWidget *parent, QString caption, QString text, + int button0, int button1 = NoButton, + int button2 = NoButton); + + /** Converts a Button enum value to a translated string. */ + static QString buttonText(int button); + +private: + /** Returns the button (0, 1, or 2) that is OR-ed with QMessageBox::Default, + * or 0 if none are. */ + static int defaultButton(int button0, int button1, int button2); + /** Returns the button (0, 1, or 2) that is OR-ed with QMessageBox::Escape, + * or -1 if none are. */ + static int escapeButton(int button0, int button1, int button2); + /** Returns the Button enum value from the given return value. */ + static int selected(int ret, int button0, int button1, int button2); +}; + +#endif + diff --git a/retroshare-gui/src/gui/connect/ConfCertDialog.cpp b/retroshare-gui/src/gui/connect/ConfCertDialog.cpp new file mode 100644 index 000000000..c811f993d --- /dev/null +++ b/retroshare-gui/src/gui/connect/ConfCertDialog.cpp @@ -0,0 +1,442 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include + +#include "ConfCertDialog.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "gui/help/browser/helpbrowser.h" +#include "gui/common/PeerDefs.h" +#include "gui/common/StatusDefs.h" +#include "gui/RetroShareLink.h" + +#ifndef MINIMAL_RSGUI +#include "gui/MainWindow.h" +#endif // !MINIMAL_RSGUI + +static QMap instances; + +ConfCertDialog *ConfCertDialog::instance(const std::string& peer_id) +{ + ConfCertDialog *d = instances[peer_id]; + if (d) { + return d; + } + + d = new ConfCertDialog(peer_id); + instances[peer_id] = d; + + return d; +} + +/* Define the format used for displaying the date and time */ +#define DATETIME_FMT "MMM dd hh:mm:ss" + +/** Default constructor */ +ConfCertDialog::ConfCertDialog(const std::string& id, QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags), mId(id) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + setAttribute(Qt::WA_DeleteOnClose, true); + + connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyDialog())); + connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(close())); + connect(ui.make_friend_button, SIGNAL(clicked()), this, SLOT(makeFriend())); + connect(ui.denyFriendButton, SIGNAL(clicked()), this, SLOT(denyFriend())); + connect(ui.signKeyButton, SIGNAL(clicked()), this, SLOT(signGPGKey())); + connect(ui.trusthelpButton, SIGNAL(clicked()), this, SLOT(showHelpDialog())); + +#ifndef MINIMAL_RSGUI + MainWindow *w = MainWindow::getInstance(); + if (w) { + connect(this, SIGNAL(configChanged()), w->getPage(MainWindow::Network), SLOT(insertConnect())); + } +#endif // !MINIMAL_RSGUI +} + +ConfCertDialog::~ConfCertDialog() +{ + QMap::iterator it = instances.find(mId); + if (it != instances.end()) { + instances.erase(it); + } +} + +void ConfCertDialog::showIt(const std::string& peer_id, enumPage page) +{ + ConfCertDialog *confdialog = instance(peer_id); + + switch (page) { + case PageDetails: + confdialog->ui.stabWidget->setCurrentIndex(0); + break; + case PageTrust: + confdialog->ui.stabWidget->setCurrentIndex(1); + break; + case PageCertificate: + confdialog->ui.stabWidget->setCurrentIndex(2); + break; + } + + confdialog->load(); + confdialog->show(); + confdialog->raise(); + confdialog->activateWindow(); + + /* window will destroy itself! */ +} + +void ConfCertDialog::loadAll() +{ + QMap::iterator it; + for (it = instances.begin(); it != instances.end(); it++) { + it.value()->load(); + } +} + +void ConfCertDialog::load() +{ + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(mId, detail)) + { + QMessageBox::information(this, + tr("RetroShare"), + tr("Error : cannot get peer details.")); + close(); + return; + } + + ui.name->setText(QString::fromStdString(detail.name)); + ui.peerid->setText(QString::fromStdString(detail.id)); + + RetroShareLink link; + link.createPerson(detail.id); + + ui.rsid->setText(link.toHtml()); + ui.rsid->setToolTip(link.title()); + + if (!detail.isOnlyGPGdetail) { + + ui.loc->setText(QString::fromUtf8(detail.location.c_str())); + // Dont Show a timestamp in RS calculate the day + QDateTime date = QDateTime::fromTime_t(detail.lastConnect); + QString stime = date.toString(Qt::LocalDate); + ui.lastcontact-> setText(stime); + + /* set retroshare version */ + std::map::iterator vit; + std::map versions; + bool retv = rsDisc->getDiscVersions(versions); + if (retv && versions.end() != (vit = versions.find(detail.id))) + { + ui.version->setText(QString::fromStdString(vit->second)); + } + + /* set local address */ + ui.localAddress->setText(QString::fromStdString(detail.localAddr)); + ui.localPort -> setValue(detail.localPort); + /* set the server address */ + ui.extAddress->setText(QString::fromStdString(detail.extAddr)); + ui.extPort -> setValue(detail.extPort); + + ui.dynDNS->setText(QString::fromStdString(detail.dyndns)); + + ui.statusline->setText(StatusDefs::connectStateString(detail)); + + ui.ipAddressList->clear(); + for(std::list::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) + ui.ipAddressList->addItem(QString::fromStdString(*it)); + + ui.loc->show(); + ui.label_loc->show(); + ui.statusline->show(); + ui.label_status->show(); + ui.lastcontact->show(); + ui.label_last_contact->show(); + ui.version->show(); + ui.label_version->show(); + + ui.groupBox->show(); + ui.rsid->hide(); + ui.label_rsid->hide(); + } else { + ui.rsid->show(); + ui.label_rsid->show(); + ui.loc->hide(); + ui.label_loc->hide(); + ui.statusline->hide(); + ui.label_status->hide(); + ui.lastcontact->hide(); + ui.label_last_contact->hide(); + ui.version->hide(); + ui.label_version->hide(); + + ui.groupBox->hide(); + } + + if (detail.gpg_id == rsPeers->getGPGOwnId()) { + ui.make_friend_button->hide(); + ui.signGPGKeyCheckBox->hide(); + ui.signKeyButton->hide(); + ui.denyFriendButton->hide(); + + ui.web_of_trust_label->hide(); + ui.radioButton_trust_fully->hide(); + ui.radioButton_trust_marginnaly->hide(); + ui.radioButton_trust_never->hide(); + + ui.is_signing_me->hide(); + ui.signersBox->setTitle(tr("Your key is signed by : ")); + + } else { + ui.web_of_trust_label->show(); + ui.radioButton_trust_fully->show(); + ui.radioButton_trust_marginnaly->show(); + ui.radioButton_trust_never->show(); + + ui.is_signing_me->show(); + ui.signersBox->setTitle(tr("Peer key is signed by : ")); + + if (detail.accept_connection) { + ui.make_friend_button->hide(); + ui.denyFriendButton->show(); + ui.signGPGKeyCheckBox->hide(); + //connection already accepted, propose to sign gpg key + if (!detail.ownsign) { + ui.signKeyButton->show(); + } else { + ui.signKeyButton->hide(); + } + } else { + ui.make_friend_button->show(); + ui.denyFriendButton->hide(); + ui.signKeyButton->hide(); + if (!detail.ownsign) { + ui.signGPGKeyCheckBox->show(); + ui.signGPGKeyCheckBox->setChecked(false); + } else { + ui.signGPGKeyCheckBox->hide(); + } + } + + //web of trust + if (detail.trustLvl == GPGME_VALIDITY_ULTIMATE) { + //trust is ultimate, it means it's one of our own keys + ui.web_of_trust_label->setText(tr("Your trust in this peer is ultimate, it's probably a key you own.")); + ui.radioButton_trust_fully->hide(); + ui.radioButton_trust_marginnaly->hide(); + ui.radioButton_trust_never->hide(); + } else { + ui.radioButton_trust_fully->show(); + ui.radioButton_trust_marginnaly->show(); + ui.radioButton_trust_never->show(); + if (detail.trustLvl == GPGME_VALIDITY_FULL) { + ui.web_of_trust_label->setText(tr("Your trust in this peer is full.")); + ui.radioButton_trust_fully->setChecked(true); + ui.radioButton_trust_fully->setIcon(QIcon(":/images/security-high-48.png")); + ui.radioButton_trust_marginnaly->setIcon(QIcon(":/images/security-medium-off-48.png")); + ui.radioButton_trust_never->setIcon(QIcon(":/images/security-low-off-48.png")); + } else if (detail.trustLvl == GPGME_VALIDITY_MARGINAL) { + ui.web_of_trust_label->setText(tr("Your trust in this peer is marginal.")); + ui.radioButton_trust_marginnaly->setChecked(true); + ui.radioButton_trust_marginnaly->setIcon(QIcon(":/images/security-medium-48.png")); + ui.radioButton_trust_never->setIcon(QIcon(":/images/security-low-off-48.png")); + ui.radioButton_trust_fully->setIcon(QIcon(":/images/security-high-off-48.png")); + } else if (detail.trustLvl == GPGME_VALIDITY_NEVER) { + ui.web_of_trust_label->setText(tr("Your trust in this peer is none.")); + ui.radioButton_trust_never->setChecked(true); + ui.radioButton_trust_never->setIcon(QIcon(":/images/security-low-48.png")); + ui.radioButton_trust_fully->setIcon(QIcon(":/images/security-high-off-48.png")); + ui.radioButton_trust_marginnaly->setIcon(QIcon(":/images/security-medium-off-48.png")); + } else { + ui.web_of_trust_label->setText(tr("Your trust in this peer is not set.")); + + //we have to set up the set exclusive to false in order to uncheck it all + ui.radioButton_trust_fully->setAutoExclusive(false); + ui.radioButton_trust_marginnaly->setAutoExclusive(false); + ui.radioButton_trust_never->setAutoExclusive(false); + + ui.radioButton_trust_fully->setChecked(false); + ui.radioButton_trust_marginnaly->setChecked(false); + ui.radioButton_trust_never->setChecked(false); + + ui.radioButton_trust_fully->setAutoExclusive(true); + ui.radioButton_trust_marginnaly->setAutoExclusive(true); + ui.radioButton_trust_never->setAutoExclusive(true); + + ui.radioButton_trust_never->setIcon(QIcon(":/images/security-low-off-48.png")); + ui.radioButton_trust_fully->setIcon(QIcon(":/images/security-high-off-48.png")); + ui.radioButton_trust_marginnaly->setIcon(QIcon(":/images/security-medium-off-48.png")); + } + } + + if (detail.hasSignedMe) { + ui.is_signing_me->setText(tr("Peer has authenticated me as a friend and did sign my GPG key")); + } else { + ui.is_signing_me->setText(tr("Peer has not authenticated me as a friend and did not sign my GPG key")); + } + } + + QString text; + for(std::list::const_iterator it(detail.gpgSigners.begin());it!=detail.gpgSigners.end();++it) { + link.createPerson(*it); + if (link.valid()) { + text += link.toHtml() + "
    "; + } + } + ui.signers->setHtml(text); + + std::string invite = rsPeers->GetRetroshareInvite(detail.id) ; // this needs to be a SSL id + + ui.userCertificateText->setReadOnly(true); + ui.userCertificateText->setMinimumHeight(200); + ui.userCertificateText->setMinimumWidth(530); + QFont font("Courier New",10,50,false); + font.setStyleHint(QFont::TypeWriter,QFont::PreferMatch); + font.setStyle(QFont::StyleNormal); + ui.userCertificateText->setFont(font); + ui.userCertificateText->setText(QString::fromStdString(invite)); +} + + +void ConfCertDialog::applyDialog() +{ + std::cerr << "ConfCertDialog::applyDialog() called" << std::endl ; + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(mId, detail)) + { + if (!rsPeers->getGPGDetails(mId, detail)) { + QMessageBox::information(this, + tr("RetroShare"), + tr("Error : cannot get peer details.")); + close(); + return; + } + } + + //check the GPG trustlvl + if (ui.radioButton_trust_fully->isChecked() && detail.trustLvl != GPGME_VALIDITY_FULL) { + //trust has changed to fully + rsPeers->trustGPGCertificate(detail.id, GPGME_VALIDITY_FULL); + } else if (ui.radioButton_trust_marginnaly->isChecked() && detail.trustLvl != GPGME_VALIDITY_MARGINAL) { + rsPeers->trustGPGCertificate(detail.id, GPGME_VALIDITY_MARGINAL); + } else if (ui.radioButton_trust_never->isChecked() && detail.trustLvl != GPGME_VALIDITY_NEVER) { + rsPeers->trustGPGCertificate(detail.id, GPGME_VALIDITY_NEVER); + } + + if (!detail.isOnlyGPGdetail) { + /* check if the data is the same */ + bool localChanged = false; + bool extChanged = false; + bool dnsChanged = false; + + /* set local address */ + if ((detail.localAddr != ui.localAddress->text().toStdString()) || (detail.localPort != ui.localPort -> value())) + localChanged = true; + + if ((detail.extAddr != ui.extAddress->text().toStdString()) || (detail.extPort != ui.extPort -> value())) + extChanged = true; + + if ((detail.dyndns != ui.dynDNS->text().toStdString())) + dnsChanged = true; + + /* now we can action the changes */ + if (localChanged) + rsPeers->setLocalAddress(mId, ui.localAddress->text().toStdString(), ui.localPort->value()); + + if (extChanged) + rsPeers->setExtAddress(mId,ui.extAddress->text().toStdString(), ui.extPort->value()); + + if (dnsChanged) + rsPeers->setDynDNS(mId, ui.dynDNS->text().toStdString()); + + if(localChanged || extChanged || dnsChanged) + emit configChanged(); + } + + loadAll(); + close(); +} + +void ConfCertDialog::makeFriend() +{ + std::string gpg_id = rsPeers->getGPGId(mId); + if (ui.signGPGKeyCheckBox->isChecked()) { + rsPeers->signGPGCertificate(gpg_id); + } else { + rsPeers->setAcceptToConnectGPGCertificate(gpg_id, true); + } + rsPeers->addFriend(mId, gpg_id); + loadAll(); + + emit configChanged(); +} + +void ConfCertDialog::denyFriend() +{ + std::string gpg_id = rsPeers->getGPGId(mId); + rsPeers->setAcceptToConnectGPGCertificate(gpg_id, false); + loadAll(); + + emit configChanged(); +} + +void ConfCertDialog::signGPGKey() +{ + std::string gpg_id = rsPeers->getGPGId(mId); + if (!rsPeers->signGPGCertificate(gpg_id)) { + QMessageBox::warning ( NULL, + tr("Signature Failure"), + tr("Maybe password is wrong"), + QMessageBox::Ok); + } + loadAll(); + + emit configChanged(); +} + +/** Displays the help browser and displays the most recently viewed help + * topic. */ +void ConfCertDialog::showHelpDialog() +{ + showHelpDialog("trust"); +} + +/**< Shows the help browser and displays the given help topic. */ +void ConfCertDialog::showHelpDialog(const QString &topic) +{ + static HelpBrowser *helpBrowser = 0; + if (!helpBrowser) + helpBrowser = new HelpBrowser(this); + helpBrowser->showWindow(topic); +} diff --git a/retroshare-gui/src/gui/connect/ConfCertDialog.h b/retroshare-gui/src/gui/connect/ConfCertDialog.h new file mode 100644 index 000000000..5900a7b8d --- /dev/null +++ b/retroshare-gui/src/gui/connect/ConfCertDialog.h @@ -0,0 +1,70 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _CONFCERTDIALOG_H +#define _CONFCERTDIALOG_H + +#include + +#include "ui_ConfCertDialog.h" + +class ConfCertDialog : public QDialog +{ + Q_OBJECT + +public: + enum enumPage { PageDetails, PageTrust, PageCertificate }; + + static void showIt(const std::string& id, enumPage page); + static void loadAll(); + +signals: + void configChanged(); + +private: + /** Default constructor */ + ConfCertDialog(const std::string& id, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~ConfCertDialog(); + + static ConfCertDialog *instance(const std::string& peer_id); + + void load(); + +private slots: + void applyDialog(); + void makeFriend(); + void denyFriend(); + void signGPGKey(); + + void showHelpDialog(); + /** Called when a child window requests the given help topic. */ + void showHelpDialog(const QString &topic); + +private: + std::string mId; + + /** Qt Designer generated object */ + Ui::ConfCertDialog ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/connect/ConfCertDialog.ui b/retroshare-gui/src/gui/connect/ConfCertDialog.ui new file mode 100644 index 000000000..31b9f8e4e --- /dev/null +++ b/retroshare-gui/src/gui/connect/ConfCertDialog.ui @@ -0,0 +1,701 @@ + + + ConfCertDialog + + + + 0 + 0 + 520 + 639 + + + + Friend Details + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + 1 + + + + + :/images/peerdetails_16x16.png:/images/peerdetails_16x16.png + + + Details + + + + + + Peer Info + + + + + + Name + + + + + + + true + + + + + + + Peer ID + + + + + + + true + + + + + + + Last Contact + + + + + + + true + + + + + + + true + + + + + + + Version + + + + + + + Loc + + + + + + + true + + + + + + + RetroShare ID + + + + + + + true + + + + 0 + 0 + + + + + 16777215 + 20 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + true + + + true + + + + + + + Status + + + + + + + true + + + + + + + + + + Peer Address + + + + + + + + + + Qt::LeftToRight + + + Local Address + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + External Address + + + + + + + Dynamic DNS + + + + + + + + + + + + + + + + + + + + + + + + Port + + + + + + + Port + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 27 + + + + + + + + + + + + 0 + + + 65535 + + + 7812 + + + + + + + 0 + + + 65535 + + + 7812 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Addresses list + + + + + + + Qt::DefaultContextMenu + + + QAbstractItemView::MultiSelection + + + + + + + Qt::Vertical + + + + 20 + 47 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + :/images/security-high-16.png:/images/security-high-16.png + + + Trust + + + + + + Your trust in this peer is: + + + true + + + + + + + + + + 125 + 16777215 + + + + None + + + + :/images/security-low-48.png:/images/security-low-48.png + + + + 48 + 48 + + + + + + + + + 140 + 16777215 + + + + Marginal + + + + :/images/security-medium-48.png:/images/security-medium-48.png + + + + 48 + 48 + + + + + + + + + 130 + 16777215 + + + + Full + + + + :/images/security-high-48.png:/images/security-high-48.png + + + + 48 + 48 + + + + + + + + + + + 50 + false + + + + GPG Key + + + false + + + false + + + + + + + 75 + true + + + + Peer has signed my GPG key + + + + + + + Show Help for Trust Settings and Signing + + + + + + + :/images/informations_24x24.png:/images/informations_24x24.png + + + + 24 + 24 + + + + + + + + Peer key is signed by : + + + + + + true + + + + + + + + + + + + + 6 + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + Sign GPG key + + + + :/images/view-certificate-sign-32.png:/images/view-certificate-sign-32.png + + + + 32 + 32 + + + + false + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + Sign GPG key + + + + :/images/view-certificate-sign-48.png:/images/view-certificate-sign-48.png + + + + 48 + 48 + + + + Qt::ToolButtonTextUnderIcon + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Deny Friend + + + + :/images/user/deny_user48.png:/images/user/deny_user48.png + + + + 48 + 48 + + + + Qt::ToolButtonTextUnderIcon + + + + + + + Make Friend + + + + :/images/user/add_user48.png:/images/user/add_user48.png + + + + 48 + 48 + + + + false + + + false + + + Qt::ToolButtonTextUnderIcon + + + false + + + Qt::NoArrow + + + + + + + + + + + :/images/view-certificate-sign-32.png:/images/view-certificate-sign-32.png + + + Certificate + + + + + + + + + + + + + + + Qt::Horizontal + + + + 311 + 20 + + + + + + + + Apply and Close + + + OK + + + false + + + true + + + + + + + Cancel + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/connect/ConnectFriendWizard.cpp b/retroshare-gui/src/gui/connect/ConnectFriendWizard.cpp new file mode 100755 index 000000000..0b9659b51 --- /dev/null +++ b/retroshare-gui/src/gui/connect/ConnectFriendWizard.cpp @@ -0,0 +1,1249 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "ConnectFriendWizard.h" +#include "gui/common/PeerDefs.h" +#include "gui/common/GroupDefs.h" + +#include //for rsPeers variable +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SSL_ID_FIELD_CONNECT_FRIEND_WIZARD "idField" +#define GPG_ID_FIELD_CONNECT_FRIEND_WIZARD "GPGidField" +#define LOCATION_FIELD_CONNECT_FRIEND_WIZARD "peerLocation" +#define CERT_STRING_FIELD_CONNECT_FRIEND_WIZARD "peerCertString" +#define SIGN_RADIO_BUTTON_FIELD_CONNECT_FRIEND_WIZARD "signCheckBox" +#define ACCEPT_RADIO_BUTTON_FIELD_CONNECT_FRIEND_WIZARD "acceptCheckBox" +#define GROUP_ID_FIELD_CONNECT_FRIEND_WIZARD "groupIdField" + + + + +//============================================================================ +//! +ConnectFriendWizard::ConnectFriendWizard(QWidget *parent) + : QWizard(parent) +{ + setPage(Page_Intro, new IntroPage); + setPage(Page_Text, new TextPage); + setPage(Page_Cert, new CertificatePage); + setPage(Page_Foff, new FofPage); + setPage(Page_Rsid, new RsidPage); + setPage(Page_Email, new EmailPage); + + setPage(Page_ErrorMessage, new ErrorMessagePage); + setPage(Page_Conclusion, new ConclusionPage); + + setStartId(Page_Intro); + + +// this define comes from Qt example. I don't have mac, so it wasn't tested +#ifndef Q_WS_MAC + setWizardStyle(ModernStyle); +#endif + + +// at this moment I don't know, what information should be in help +// setOption(HaveHelpButton, true); +// connect(this, SIGNAL(helpRequested()), this, SLOT(showHelp())); + + setPixmap(QWizard::LogoPixmap, + QPixmap(":/images/connect/connectFriendLogo.png")); +// we have no good pictures for watermarks +// setPixmap(QWizard::WatermarkPixmap, +// QPixmap(":/images/connectFriendWatermark.png")); + setPixmap(QWizard::BannerPixmap, + QPixmap(":/images/connect/connectFriendBanner.png")) ; + + setWindowTitle(tr("Connect Friend Wizard")); +} + + +//============================================================================ + +void ConnectFriendWizard::setGroup(const std::string &groupId) +{ + setField(GROUP_ID_FIELD_CONNECT_FRIEND_WIZARD, QString::fromStdString(groupId)); +} + +//============================================================================ + +void +ConnectFriendWizard::accept() +{ + if ( hasVisitedPage(Page_Conclusion) ) { + std::cerr << "ConnectFriendWizard::accept() called with page conclusion visited" << std::endl; + + std::string ssl_Id = field(SSL_ID_FIELD_CONNECT_FRIEND_WIZARD).toString().toStdString(); + std::string gpg_Id = field(GPG_ID_FIELD_CONNECT_FRIEND_WIZARD).toString().toStdString(); + bool sign = field(SIGN_RADIO_BUTTON_FIELD_CONNECT_FRIEND_WIZARD).toBool(); + bool accept_connection = field(ACCEPT_RADIO_BUTTON_FIELD_CONNECT_FRIEND_WIZARD).toBool(); + + if (gpg_Id != "") { + if (sign) { + std::cerr << "ConclusionPage::validatePage() signing GPG key." << std::endl; + rsPeers->signGPGCertificate(gpg_Id); //bye default sign set accept_connection to true; + } else if (accept_connection) { + std::cerr << "ConclusionPage::validatePage() accepting GPG key for connection." << std::endl; + rsPeers->setAcceptToConnectGPGCertificate(gpg_Id, true); + } + + QString groupId = field(GROUP_ID_FIELD_CONNECT_FRIEND_WIZARD).toString(); + if (groupId.isEmpty() == false) { + rsPeers->assignPeerToGroup(groupId.toStdString(), gpg_Id, true); + } + } + + if (ssl_Id != "") { + rsPeers->addFriend(ssl_Id, gpg_Id); + //let's check if there is ip adresses in the wizard. + if (!this->field("ext_friend_ip").isNull() && !this->field("ext_friend_port").isNull()) { + std::cerr << "ConnectFriendWizard::accept() : setting ip ext address." << std::endl; + rsPeers->setExtAddress(ssl_Id, this->field("ext_friend_ip").toString().toStdString(), this->field("ext_friend_port").toInt()); + } + if (!this->field("local_friend_ip").isNull() && !this->field("local_friend_port").isNull()) { + std::cerr << "ConnectFriendWizard::accept() : setting ip local address." << std::endl; + rsPeers->setLocalAddress(ssl_Id, this->field("local_friend_ip").toString().toStdString(), this->field("local_friend_port").toInt()); + } + if (!this->field("dyndns").isNull()) { + std::cerr << "ConnectFriendWizard::accept() : setting DynDNS." << std::endl; + rsPeers->setDynDNS(ssl_Id, this->field("dyndns").toString().toStdString()); + } + if (!this->field(LOCATION_FIELD_CONNECT_FRIEND_WIZARD).isNull()) { + std::cerr << "ConnectFriendWizard::accept() : setting peerLocation." << std::endl; + rsPeers->setLocation(ssl_Id, this->field(LOCATION_FIELD_CONNECT_FRIEND_WIZARD).toString().toStdString()); + } + } + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_NEIGHBOURS,1) ; + } + + QDialog::accept(); +} + +//============================================================================ +//============================================================================ +//============================================================================ +// +IntroPage::IntroPage(QWidget *parent) + : QWizardPage(parent) +{ + QString titleStr("%1"); + setTitle( titleStr.arg( tr("Add a new Friend") ) ) ; + + setSubTitle(tr("This wizard will help you to connect to your friend(s) to RetroShare network.\nThese ways are possible to do this:")); + + textRadioButton = new QRadioButton(tr("&Enter the certificate manually")); + certRadioButton = new QRadioButton(tr("&You get a certificate file from your friend" )); + foffRadioButton = new QRadioButton(tr("&Make friend with selected friends of my friends" )); + rsidRadioButton = new QRadioButton(tr("&Enter RetroShare ID manually" )); + emailRadioButton = new QRadioButton(tr("&Send a Invitation by Email \n (She/He receives a email with instructions howto to download RetroShare) " )); + + textRadioButton->setChecked(true); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(textRadioButton); + layout->addWidget(certRadioButton); + //layout->addWidget(foffRadioButton); + //layout->addWidget(rsidRadioButton); + layout->addWidget(emailRadioButton); + setLayout(layout); +} +// +//============================================================================ +// +int IntroPage::nextId() const +{ + if (textRadioButton->isChecked()) return ConnectFriendWizard::Page_Text; + if (certRadioButton->isChecked()) return ConnectFriendWizard::Page_Cert; + if (foffRadioButton->isChecked()) return ConnectFriendWizard::Page_Foff; + if (rsidRadioButton->isChecked()) return ConnectFriendWizard::Page_Rsid; + if (emailRadioButton->isChecked()) return ConnectFriendWizard::Page_Email; + + return ConnectFriendWizard::Page_Foff; +} +// +//============================================================================ +//============================================================================ +//============================================================================ +// +TextPage::TextPage(QWidget *parent) + : QWizardPage(parent) +{ + QString titleStr("%1"); + setTitle( titleStr.arg( tr("Text certificate") ) ) ; + + setSubTitle(tr("Use text representation of the PGP certificates.")); + + userCertLabel = new QLabel(tr("The text below is your PGP certificate. " + "You have to provide it to your friend ")); + + std::cerr << "TextPage() getting Invite" << std::endl; + userCertEdit = new QTextEdit; + std::string invite = rsPeers->GetRetroshareInvite(); + + userCertEdit->setReadOnly(true); + QFont font("Courier New",10,50,false); + font.setStyleHint(QFont::TypeWriter,QFont::PreferMatch); + font.setStyle(QFont::StyleNormal); + userCertEdit->setFont(font); + userCertEdit->setText(QString::fromStdString(invite)); + + std::cerr << "TextPage() getting Invite: " << invite << std::endl; + + userCertHelpButton = new QPushButton; + userCertHelpButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + userCertHelpButton->setFixedSize(20,20); + userCertHelpButton->setFlat(true); + userCertHelpButton->setIcon( QIcon(":images/connect/info16.png") ); + connect (userCertHelpButton, SIGNAL( clicked()), + this, SLOT( showHelpUserCert()) ); + + userCertCopyButton = new QPushButton; + userCertCopyButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + userCertCopyButton->setFixedSize(20,20); + + userCertCopyButton->setFlat(true); + userCertCopyButton->setIcon( QIcon(":images/copyrslink.png") ); + userCertCopyButton->setToolTip(tr("Copy your Cert to Clipboard")); + connect (userCertCopyButton, SIGNAL( clicked()), + this, SLOT( copyCert()) ); + + userCertSaveButton = new QPushButton; + userCertSaveButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + userCertSaveButton->setFixedSize(20,20); + userCertSaveButton->setFlat(true); + userCertSaveButton->setIcon( QIcon(":images/document_save.png") ); + userCertSaveButton->setToolTip(tr("Save your Cert into a File")); + connect (userCertSaveButton, SIGNAL( clicked()), + this, SLOT( fileSaveAs()) ); + + userCertMailButton = new QPushButton; + userCertMailButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + userCertMailButton->setFixedSize(20,20); + userCertMailButton->setFlat(true); + userCertMailButton->setIcon( QIcon(":images/connect/mail_send.png") ); + userCertMailButton->setToolTip(tr("Run Email program")); + connect (userCertMailButton, SIGNAL( clicked()), + this, SLOT( runEmailClient()) ); + + userCertButtonsLayout = new QVBoxLayout(); + userCertButtonsLayout->addWidget(userCertHelpButton); + userCertButtonsLayout->addWidget(userCertCopyButton); + userCertButtonsLayout->addWidget(userCertSaveButton); + userCertButtonsLayout->addWidget(userCertMailButton); + + userCertLayout = new QHBoxLayout(); + userCertLayout->addWidget(userCertEdit); + userCertLayout->addLayout(userCertButtonsLayout); + + friendCertLabel = new QLabel(tr("Please, paste your friends PGP " + "certificate into the box below" )) ; + + friendCertEdit = new QTextEdit; + + //font.setWeight(75); + friendCertEdit->setFont(font); + + friendCertCleanButton = new QPushButton; + friendCertCleanButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + friendCertCleanButton->setFixedSize(20,20); + friendCertCleanButton->setFlat(true); + friendCertCleanButton->setIcon( QIcon(":images/accepted16.png") ); + friendCertCleanButton->setToolTip(tr("Clean certificate")); + connect (friendCertCleanButton, SIGNAL(clicked()), this, SLOT(cleanFriendCert())); + + friendCertButtonsLayout = new QVBoxLayout(); + friendCertButtonsLayout->addWidget(friendCertCleanButton); + + friendCertLayout = new QHBoxLayout(); + friendCertLayout->addWidget(friendCertEdit); + friendCertLayout->addLayout(friendCertButtonsLayout); + + //=== add all widgets to one layout + textPageLayout = new QVBoxLayout(); + textPageLayout->addWidget(userCertLabel); + textPageLayout->addLayout(userCertLayout); + textPageLayout->addWidget(friendCertLabel); + textPageLayout->addLayout(friendCertLayout); +// + setLayout(textPageLayout); +} +// +//============================================================================ +// + +static void sendMail (std::string sAddress, std::string sSubject, std::string sBody) +{ + /* search and replace the end of lines with: "%0D%0A" */ + size_t loc; + while ((loc = sBody.find("\n")) != sBody.npos) { + sBody.replace(loc, 1, "%0D%0A"); + } + + std::string mailstr = "mailto:" + sAddress; + mailstr += "?subject=" + sSubject; + mailstr += "&body=" + sBody; + + std::cerr << "MAIL STRING:" << mailstr.c_str() << std::endl; + + /* pass the url directly to QDesktopServices::openUrl */ + QDesktopServices::openUrl (QUrl (QString::fromStdString(mailstr))); +} + +void +TextPage::runEmailClient() +{ + sendMail ("", tr("RetroShare Invite").toStdString(), userCertEdit->toPlainText().toStdString()); +} + +void TextPage::cleanFriendCert() +{ + std::string cert = friendCertEdit->toPlainText().toStdString(); + std::string cleanCert; + + if (rsPeers->cleanCertificate(cert, cleanCert)) { + friendCertEdit->setText(QString::fromStdString(cleanCert)); + } +} + +// +//============================================================================ +// +void +TextPage::showHelpUserCert() +{ + QMessageBox::information(this, + tr("Connect Friend Help"), + tr("You can copy this text and send it to your " + "friend via email or some other way")); + +} +// +//============================================================================ +// +void +TextPage::copyCert() +{ + QMessageBox::information(this, + tr("RetroShare"), + tr("Your Cert is copied to Clipboard, paste and send it to your " + "friend via email or some other way")); + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(userCertEdit->toPlainText()); + +} +// +//============================================================================ +// + +bool TextPage::fileSave() +{ + if (fileName.isEmpty()) + return fileSaveAs(); + + QFile file(fileName); + if (!file.open(QFile::WriteOnly)) + return false; + + //Todo: move save to file to p3Peers::SaveCertificateToFile + + QTextStream ts(&file); + ts.setCodec(QTextCodec::codecForName("UTF-8")); + ts << userCertEdit->document()->toPlainText(); + userCertEdit->document()->setModified(false); + return true; +} + +bool TextPage::fileSaveAs() +{ + QString fn = QFileDialog::getSaveFileName(this, tr("Save as..."), + QString(), tr("RetroShare Certificate (*.rsc );;All Files (*)")); + if (fn.isEmpty()) + return false; + setCurrentFileName(fn); + return fileSave(); +} + +void TextPage::setCurrentFileName(const QString &fileName) +{ + this->fileName = fileName; + userCertEdit->document()->setModified(false); + + setWindowModified(false); +} + + +// +//============================================================================ +// + +int TextPage::nextId() const { + + std::string certstr; + certstr = friendCertEdit->toPlainText().toStdString(); + std::string error_string ; + RsPeerDetails pd; + if ( rsPeers->loadDetailsFromStringCert(certstr, pd,error_string) ) { +#ifdef FRIEND_WIZARD_DEBUG + std::cerr << "ConnectFriendWizard got id : " << pd.id << "; gpg_id : " << pd.gpg_id << std::endl; +#endif + wizard()->setField(SSL_ID_FIELD_CONNECT_FRIEND_WIZARD, QString::fromStdString(pd.id)); + wizard()->setField(GPG_ID_FIELD_CONNECT_FRIEND_WIZARD, QString::fromStdString(pd.gpg_id)); + wizard()->setField(LOCATION_FIELD_CONNECT_FRIEND_WIZARD, QString::fromUtf8(pd.location.c_str())); + wizard()->setField(CERT_STRING_FIELD_CONNECT_FRIEND_WIZARD, QString::fromStdString(certstr)); + + wizard()->setField("ext_friend_ip", QString::fromStdString(pd.extAddr)); + wizard()->setField("ext_friend_port", QString::number(pd.extPort)); + wizard()->setField("local_friend_ip", QString::fromStdString(pd.localAddr)); + wizard()->setField("local_friend_port", QString::number(pd.localPort)); + wizard()->setField("dyndns", QString::fromStdString(pd.dyndns)); + + return ConnectFriendWizard::Page_Conclusion ; + } + else + { + // error message + wizard()->setField("errorMessage", tr("Certificate Load Failed")+": "+QString::fromStdString(error_string) ); + return ConnectFriendWizard::Page_ErrorMessage; + } + + return ConnectFriendWizard::Page_ErrorMessage; +} +// +//============================================================================ +//============================================================================ +//============================================================================ +// +FofPage::FofPage(QWidget *parent) : QWizardPage(parent) { + _friends_signed = false ; + QString titleStr("%1"); + setTitle( titleStr.arg( tr("Friends of friends") ) ) ; + + setSubTitle(tr("Select now who you want to make friends with.")); + + userFileLabel = new QLabel(tr("Show me: ")) ; + userSelectionCB = new QComboBox ; + userSelectionCB->addItem(tr("Any peer I've not signed")) ; + userSelectionCB->addItem(tr("Friends of my friends who already trust me")) ; + userSelectionCB->addItem(tr("Signed peers showing as denied")) ; + + selectedPeersTW = new QTableWidget(0,4,NULL) ; + selectedPeersTW->setHorizontalHeaderItem(0,new QTableWidgetItem(tr(""))) ; + selectedPeersTW->setHorizontalHeaderItem(1,new QTableWidgetItem(tr("Peer name"))) ; + selectedPeersTW->setHorizontalHeaderItem(2,new QTableWidgetItem(tr("Also signed by"))) ; + selectedPeersTW->setHorizontalHeaderItem(3,new QTableWidgetItem(tr("Peer id"))) ; + + makeFriendButton = new QPushButton(tr("Make friend with these peers")) ; + + userFileLayout = new QVBoxLayout; + userFileLayout->addWidget(userFileLabel); + userFileLayout->addWidget(userSelectionCB); + userFileLayout->addWidget(selectedPeersTW); + userFileLayout->addWidget(makeFriendButton); + +// userFileFrame = new QGroupBox; +// userFileFrame->setFlat(true); +// userFileFrame->setTitle("toto"); +// userFileFrame->setLayout(userFileLayout); + + setLayout(userFileLayout) ; + + connect(makeFriendButton,SIGNAL(clicked()),this,SLOT(signAllSelectedUsers())) ; + connect(userSelectionCB,SIGNAL(activated(int)),this,SLOT(updatePeersList(int))) ; + + updatePeersList(0) ; +} + +void FofPage::updatePeersList(int e) { + rsiface->unlockData(); /* UnLock Interface */ + + selectedPeersTW->clearContents() ; + selectedPeersTW->setRowCount(0) ; + + std::string sOwnId = rsPeers->getGPGOwnId(); + + int row = 0 ; + + _id_boxes.clear() ; + std::cerr << "FofPage::updatePeersList() updating peers list with e=" << e << std::endl ; + + // We have to use this trick because signers are given by their names instead of their ids. That's a cause + // for some confusion when two peers have the same name. + // + std::list gpg_ids; + rsPeers->getGPGAllList(gpg_ids); + for(std::list::const_iterator it(gpg_ids.begin());it!=gpg_ids.end();++it) + { + if (*it == sOwnId) { + // its me + continue; + } + + std::cerr << "examining peer " << *it << " (name=" << rsPeers->getPeerName(*it) ; + RsPeerDetails details ; + + if(!rsPeers->getPeerDetails(*it,details)) + { + std::cerr << " no details." << std::endl ; + continue ; + } + + // determine common friends + + std::set common_friends ; + + for(std::list::const_iterator it2(details.gpgSigners.begin());it2!=details.gpgSigners.end();++it2) { + if(rsPeers->isGPGAccepted(*it2)) { + common_friends.insert(*it2); + } + } + bool show = false; + + switch(e) + { + case 2: // "Peers shown as denied" + show = details.ownsign && !(details.state & RS_PEER_STATE_FRIEND) ; + std::cerr << "case 2, ownsign=" << details.ownsign << ", state_friend=" << (details.state & RS_PEER_STATE_FRIEND) << ", show=" << show << std::endl ; + break ; + + case 1: // "Unsigned peers who already signed my certificate" + show = details.hasSignedMe && !(details.state & RS_PEER_STATE_FRIEND) ; + std::cerr << "case 1, ownsign=" << details.ownsign << ", is_authed_me=" << details.hasSignedMe << ", show=" << show << std::endl ; + break ; + + case 0: // "All unsigned friends of my friends" + show= !details.ownsign ; + std::cerr << "case 0: ownsign=" << details.ownsign << ", show=" << show << std::endl ; + break ; + + default: break ; + } + + if(show) + { + selectedPeersTW->insertRow(row) ; + + QCheckBox *cb = new QCheckBox ; + cb->setChecked(true) ; + _id_boxes[cb] = details.id ; + _gpg_id_boxes[cb] = details.gpg_id ; + + selectedPeersTW->setCellWidget(row,0,cb) ; + selectedPeersTW->setItem(row,1,new QTableWidgetItem(QString::fromStdString(details.name))) ; + + QComboBox *qcb = new QComboBox ; + + if(common_friends.empty()) + qcb->addItem(tr("*** None ***")) ; + else + for(std::set::const_iterator it2(common_friends.begin());it2!=common_friends.end();++it2) + qcb->addItem(QString::fromStdString(*it2)); + + selectedPeersTW->setCellWidget(row,2,qcb) ; + selectedPeersTW->setItem(row,3,new QTableWidgetItem(QString::fromStdString(details.id))) ; + ++row ; + } + } + std::cerr << "FofPage::updatePeersList() finished iterating over peers" << std::endl ; + + if(row>0) + { + selectedPeersTW->resizeColumnsToContents() ; + makeFriendButton->setEnabled(true) ; + } + else + makeFriendButton->setEnabled(false) ; + + selectedPeersTW->verticalHeader()->hide() ; + selectedPeersTW->setSortingEnabled(true) ; +} + +int FofPage::nextId() const { + return -1 ; +} + +bool FofPage::isComplete() const { + return _friends_signed ; +} + +void FofPage::signAllSelectedUsers() { + std::cerr << "makign lots of friends !!" << std::endl ; + + for(std::map::const_iterator it(_id_boxes.begin());it!=_id_boxes.end();++it) + if(it->first->isChecked()) + { + std::cerr << "Making friend with " << it->second << std::endl ; + //rsPeers->AuthCertificate(it->second, ""); + rsPeers->addFriend(it->second, _gpg_id_boxes[it->first]); + } + + _friends_signed = true ; + + userSelectionCB->setEnabled(false) ; + selectedPeersTW->setEnabled(false) ; + makeFriendButton->setEnabled(false) ; + + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_NEIGHBOURS,0) ; + rsicontrol->getNotify().notifyListChange(NOTIFY_LIST_FRIENDS,0) ; + emit completeChanged(); +} +// +//============================================================================ +//============================================================================ +//============================================================================ + +CertificatePage::CertificatePage(QWidget *parent) : QWizardPage(parent) { + QString titleStr("%1"); + setTitle( titleStr.arg( tr("Certificate files") ) ) ; + + setSubTitle(tr("Use PGP certificates saved in files.")); + + userFileLabel = new QLabel(tr("You have to generate a file with your " + "certificate and give it to your friend. " + "Also, you can use a file generated " + "before.")); + userFileLabel->setWordWrap(true); + + setAcceptDrops(true); + + userFileCreateButton = new QPushButton; + userFileCreateButton->setText(tr("Export my certificate...")); + connect(userFileCreateButton, SIGNAL( clicked() ), this, SLOT( generateCertificateCalled())); + + userFileLayout = new QHBoxLayout; + userFileLayout->addWidget(userFileLabel); + userFileLayout->addWidget(userFileCreateButton); + + userFileFrame = new QGroupBox; + userFileFrame->setFlat(true); + userFileFrame->setTitle(tr("Import friend's certificate...")); + userFileFrame->setLayout(userFileLayout); + + friendFileLabel = new QLabel(tr("Drag and Drop your friends's certificate in this Window or specify path " + "in the box below " ) ); + friendFileNameEdit = new QLineEdit; + registerField("friendCertificateFile*", friendFileNameEdit); + + friendFileNameOpenButton= new QPushButton; + friendFileNameOpenButton->setText(tr("Browse")); + connect(friendFileNameOpenButton, SIGNAL( clicked()), this, SLOT( loadFriendCert())); + + friendFileLayout = new QHBoxLayout; + friendFileLayout->addWidget(friendFileNameEdit) ; + friendFileLayout->addWidget(friendFileNameOpenButton); + + certPageLayout = new QVBoxLayout; + certPageLayout->addWidget(userFileFrame); + certPageLayout->addWidget(friendFileLabel); + certPageLayout->addLayout(friendFileLayout); + + setLayout(certPageLayout); +} + +//============================================================================ + +void CertificatePage::loadFriendCert() { + QString fileName = + QFileDialog::getOpenFileName(this, tr("Select Certificate"), + "", tr("RetroShare Certificate (*.rsc );;All Files (*)")); + + if (!fileName.isNull()) + { + friendFileNameEdit->setText(fileName); + emit completeChanged(); + } +} + +//============================================================================ + +void CertificatePage::generateCertificateCalled() { + qDebug() << " generateCertificateCalled"; + + std::string cert = rsPeers->GetRetroshareInvite(); + if (cert.empty()) { + QMessageBox::information(this, tr("RetroShare"), + tr("Sorry, create certificate failed"), + QMessageBox::Ok, QMessageBox::Ok); + return; + } + + QString qdir = QFileDialog::getSaveFileName(this, + tr("Please choose a filename"), + QDir::homePath(), + tr("RetroShare Certificate (*.rsc );;All Files (*)")); + //Todo: move save to file to p3Peers::SaveCertificateToFile + + if (qdir.isEmpty() == false) { + QFile CertFile (qdir); + if (CertFile.open(QIODevice::WriteOnly/* | QIODevice::Text*/)) { + if (CertFile.write(QByteArray(cert.c_str())) > 0) { + QMessageBox::information(this, tr("RetroShare"), + tr("Certificate file successfully created"), + QMessageBox::Ok, QMessageBox::Ok); + } else { + QMessageBox::information(this, tr("RetroShare"), + tr("Sorry, certificate file creation failed"), + QMessageBox::Ok, QMessageBox::Ok); + } + CertFile.close(); + } else { + QMessageBox::information(this, tr("RetroShare"), + tr("Sorry, certificate file creation failed"), + QMessageBox::Ok, QMessageBox::Ok); + } + } +} + +//============================================================================ + +void CertificatePage::dragEnterEvent(QDragEnterEvent *event) +{ + // accept just text/uri-list mime format + if (event->mimeData()->hasFormat("text/uri-list")) + { + event->acceptProposedAction(); + } +} + + +void CertificatePage::dropEvent(QDropEvent *event) +{ + QList urlList; + QString fName; + QFileInfo info; + + if (event->mimeData()->hasUrls()) + { + urlList = event->mimeData()->urls(); // returns list of QUrls + // if just text was dropped, urlList is empty (size == 0) + + if ( urlList.size() > 0) // if at least one QUrl is present in list + { + fName = urlList[0].toLocalFile(); // convert first QUrl to local path + info.setFile( fName ); // information about file + if ( info.isFile() ) + friendFileNameEdit->setText( fName ); // if is file, setText + } + } + + event->acceptProposedAction(); +} + +//============================================================================ + +bool CertificatePage::isComplete() const { + return !( (friendFileNameEdit->text()).isEmpty() ); +} + +//============================================================================ + +int CertificatePage::nextId() const +{ + QString fn = friendFileNameEdit->text(); + if (QFile::exists(fn)) { + //Todo: move read from file to p3Peers::loadCertificateFromFile + + // read from file + std::string certstr; + QFile CertFile (fn); + if (CertFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + certstr = QString (CertFile.readAll()).toStdString(); + CertFile.close(); + } + + if (certstr.empty() == false) { + RsPeerDetails pd; + std::string error_string ; + if ( rsPeers->loadDetailsFromStringCert(certstr, pd,error_string) ) { +#ifdef FRIEND_WIZARD_DEBUG + std::cerr << "ConnectFriendWizard got id : " << pd.id << "; gpg_id : " << pd.gpg_id << std::endl; +#endif + wizard()->setField(SSL_ID_FIELD_CONNECT_FRIEND_WIZARD, QString::fromStdString(pd.id)); + wizard()->setField(GPG_ID_FIELD_CONNECT_FRIEND_WIZARD, QString::fromStdString(pd.gpg_id)); + wizard()->setField(LOCATION_FIELD_CONNECT_FRIEND_WIZARD, QString::fromUtf8(pd.location.c_str())); + wizard()->setField(CERT_STRING_FIELD_CONNECT_FRIEND_WIZARD, QString::fromStdString(certstr)); + + wizard()->setField("ext_friend_ip", QString::fromStdString(pd.extAddr)); + wizard()->setField("ext_friend_port", QString::number(pd.extPort)); + wizard()->setField("local_friend_ip", QString::fromStdString(pd.localAddr)); + wizard()->setField("local_friend_port", QString::number(pd.localPort)); + wizard()->setField("dyndns", QString::fromStdString(pd.dyndns)); + + return ConnectFriendWizard::Page_Conclusion ; + } else { + wizard()->setField("errorMessage", QString(tr("Certificate Load Failed:something is wrong with %1 ")).arg(fn)+": "+QString::fromStdString(error_string) ); + return ConnectFriendWizard::Page_ErrorMessage; + } + } else { + wizard()->setField("errorMessage", QString(tr("Certificate Load Failed:can't read from file %1 ")).arg(fn) ); + return ConnectFriendWizard::Page_ErrorMessage; + } + } else { + QString mess = + QString(tr("Certificate Load Failed:file %1 not found")) + .arg(fn); + + wizard()->setField("errorMessage", mess); + + return ConnectFriendWizard::Page_ErrorMessage; + } +} + +// +//============================================================================ +//============================================================================ +//============================================================================ + +ErrorMessagePage::ErrorMessagePage(QWidget *parent) + : QWizardPage(parent) +{ + QString titleStr("%1"); + setTitle( titleStr.arg( tr("Sorry, some error appeared") ) ) ; + setSubTitle( tr("Here is the error message: ") ); + + messageLabel = new QLabel("zooloo"); + registerField("errorMessage", messageLabel, "text"); + + errMessLayout = new QVBoxLayout; + errMessLayout->addWidget(messageLabel); + setLayout(errMessLayout); +} + +//============================================================================ +// +int ErrorMessagePage::nextId() const +{ + return -1; +} +// +//============================================================================ +//============================================================================ +//============================================================================ + +ConclusionPage::ConclusionPage(QWidget *parent) : QWizardPage(parent) { + QString titleStr("%1"); + setTitle( titleStr.arg( tr("Make Friend") ) ) ; + + setSubTitle(tr("Details about your friend : ")); + + peerDetailsFrame = new QGroupBox; + peerDetailsFrame->setTitle( tr("Peer details") ); + + peerDetailsLayout = new QGridLayout(); + + trustLabel = new QLabel( tr("Key validity:") ); + peerDetailsLayout->addWidget(trustLabel, 0,0,1,1); + trustEdit = new QLabel(); + peerDetailsLayout->addWidget(trustEdit, 0,1,1,1); + nameLabel = new QLabel( tr("Name:") ); + peerDetailsLayout->addWidget(nameLabel, 1,0,1,1); + nameEdit = new QLabel(); + peerDetailsLayout->addWidget(nameEdit, 1,1,1,1); + emailLabel = new QLabel( tr("Email:") ); + peerDetailsLayout->addWidget(emailLabel, 2,0,1,1); + emailEdit = new QLabel(); + peerDetailsLayout->addWidget(emailEdit, 2,1,1,1); + locLabel = new QLabel( tr("Loc:") ); + peerDetailsLayout->addWidget(locLabel, 3,0,1,1); + locEdit = new QLabel(); + peerDetailsLayout->addWidget(locEdit, 3,1,1,1); + signersLabel = new QLabel( tr("Signers") ); + peerDetailsLayout->addWidget(signersLabel, 4,0,1,1); + signersEdit = new QTextEdit(); + peerDetailsLayout->addWidget(signersEdit, 4,1,1,1); + + peerDetailsFrame->setLayout(peerDetailsLayout); + + optionsFrame = new QGroupBox; + optionsFrame ->setTitle( tr("Options") ); + optionsLayout = new QGridLayout(); + + groupLabel = new QLabel( tr("Add friend to group:") ); + optionsLayout->addWidget(groupLabel, 0,0,1,1); + + groupComboBox = new QComboBox(this); + optionsLayout->addWidget(groupComboBox, 0,1,1,1); + + optionsFrame->setLayout(optionsLayout); + + + signGPGCheckBox = new QCheckBox(); + signGPGCheckBox->setText(tr("Authenticate friend (Sign GPG Key)")); + registerField(SIGN_RADIO_BUTTON_FIELD_CONNECT_FRIEND_WIZARD,signGPGCheckBox); + acceptNoSignGPGCheckBox = new QCheckBox(); + acceptNoSignGPGCheckBox->setText(tr("Add as friend to connect with")); + registerField(ACCEPT_RADIO_BUTTON_FIELD_CONNECT_FRIEND_WIZARD,acceptNoSignGPGCheckBox); + optionsLayout->addWidget(acceptNoSignGPGCheckBox, 5,0,1,-1); // QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = 0 ) + optionsLayout->addWidget(signGPGCheckBox, 6,0,1,-1); // QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = 0 ) + + + conclusionPageLayout = new QVBoxLayout(); + conclusionPageLayout->addWidget(peerDetailsFrame); + conclusionPageLayout->addWidget(optionsFrame); + + setLayout(conclusionPageLayout); + + //registering fields for cross pages access. There maybe a cleaner solution + peerIdEdit = new QLineEdit(this); + peerIdEdit->setVisible(false); + registerField(SSL_ID_FIELD_CONNECT_FRIEND_WIZARD,peerIdEdit); + + peerGPGIdEdit = new QLineEdit(this); + peerGPGIdEdit->setVisible(false); + registerField(GPG_ID_FIELD_CONNECT_FRIEND_WIZARD,peerGPGIdEdit); + + peerLocation = new QLineEdit(this); + peerLocation->setVisible(false); + registerField(LOCATION_FIELD_CONNECT_FRIEND_WIZARD,peerLocation); + + peerCertStringEdit = new QLineEdit(this); + peerCertStringEdit->setVisible(false); + registerField(CERT_STRING_FIELD_CONNECT_FRIEND_WIZARD,peerCertStringEdit); + + ext_friend_ip = new QLineEdit(this); + ext_friend_ip->setVisible(false); + registerField("ext_friend_ip",ext_friend_ip); + + ext_friend_port = new QLineEdit(this); + ext_friend_port->setVisible(false); + registerField("ext_friend_port",ext_friend_port); + + local_friend_ip = new QLineEdit(this); + local_friend_ip->setVisible(false); + registerField("local_friend_ip",local_friend_ip); + + local_friend_port = new QLineEdit(this); + local_friend_port->setVisible(false); + registerField("local_friend_port",local_friend_port); + + dyndns = new QLineEdit(this); + dyndns->setVisible(false); + registerField("dyndns",dyndns); + + //groupLabel = new QLabel(this); + //groupLabel->setVisible(false); + registerField(GROUP_ID_FIELD_CONNECT_FRIEND_WIZARD, groupLabel); +} + +//============================================================================ +// +int ConclusionPage::nextId() const { + return -1; +} + +// +//============================================================================ +// +void ConclusionPage::groupCurrentIndexChanged(int index) +{ + setField(GROUP_ID_FIELD_CONNECT_FRIEND_WIZARD, groupComboBox->itemData(index, Qt::UserRole)); +} + +// +//============================================================================ +// + +void ConclusionPage::initializePage() { + std::string id = field(SSL_ID_FIELD_CONNECT_FRIEND_WIZARD).toString().toStdString(); + std::string gpg_id = field(GPG_ID_FIELD_CONNECT_FRIEND_WIZARD).toString().toStdString(); + std::string location = field(LOCATION_FIELD_CONNECT_FRIEND_WIZARD).toString().toStdString(); + std::string certString = field(CERT_STRING_FIELD_CONNECT_FRIEND_WIZARD).toString().toStdString(); + std::cerr << "Conclusion page id : " << id << "; gpg_id : " << gpg_id << std::endl; + + RsPeerDetails detail; + std::string error_string ; + if (!rsPeers->loadDetailsFromStringCert(certString, detail,error_string)) { + if (!rsPeers->getPeerDetails(id, detail)) { + if (!rsPeers->getPeerDetails(gpg_id, detail)) { + rsiface->unlockData(); /* UnLock Interface */ + return ;//false; + } + } + } + + //set the radio button to sign the GPG key + if (detail.accept_connection && !detail.ownsign) { + //gpg key connection is already accepted, don't propose to accept it again + signGPGCheckBox->setChecked(true); + acceptNoSignGPGCheckBox->hide(); + acceptNoSignGPGCheckBox->setChecked(false); + } + if (!detail.accept_connection && detail.ownsign) { + //gpg key is already signed, don't propose to sign it again + acceptNoSignGPGCheckBox->setChecked(true); + signGPGCheckBox->hide(); + signGPGCheckBox->setChecked(false); + } + if (!detail.accept_connection && !detail.ownsign) { + acceptNoSignGPGCheckBox->setChecked(true); + signGPGCheckBox->show(); + signGPGCheckBox->setChecked(true); + acceptNoSignGPGCheckBox->show(); + } + if (detail.accept_connection && detail.ownsign) { + acceptNoSignGPGCheckBox->setChecked(false); + acceptNoSignGPGCheckBox->hide(); + signGPGCheckBox->setChecked(false); + signGPGCheckBox->hide(); + radioButtonsLabel = new QLabel(tr("It seems your friend is already registered. Adding it might just set it's ip address.")); + radioButtonsLabel->setWordWrap(true); + peerDetailsLayout->addWidget(radioButtonsLabel, 7,0,1,-1); // QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = 0 ) + } + + std::string trustString; + switch(detail.validLvl) + { + case RS_TRUST_LVL_ULTIMATE: + trustString = "Ultimate"; + break; + case RS_TRUST_LVL_FULL: + trustString = "Full"; + break; + case RS_TRUST_LVL_MARGINAL: + trustString = "Marginal"; + break; + case RS_TRUST_LVL_NONE: + trustString = "None"; + break; + default: + trustString = "No Trust"; + break; + } + + QString ts; + std::list::iterator it; + for(it = detail.gpgSigners.begin(); it != detail.gpgSigners.end(); it++) { + ts.append(QString::fromStdString( rsPeers->getPeerName(*it) )); + ts.append( "<" ) ; + ts.append( QString::fromStdString(*it) ); + ts.append( ">" ); + ts.append( "\n" ); + } + + nameEdit->setText( QString::fromStdString( detail.name ) ) ; + trustEdit->setText(QString::fromStdString( trustString ) ) ; + emailEdit->setText(QString::fromStdString( detail.email ) ); + locEdit->setText( QString::fromUtf8( detail.location.c_str() ) ); + signersEdit->setPlainText( ts ); + + std::list groupInfoList; + rsPeers->getGroupInfoList(groupInfoList); + GroupDefs::sortByName(groupInfoList); + groupComboBox->addItem("", ""); // empty value + for (std::list::iterator groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); groupIt++) { + groupComboBox->addItem(GroupDefs::name(*groupIt), QString::fromStdString(groupIt->id)); + } + + QString groupId = field(GROUP_ID_FIELD_CONNECT_FRIEND_WIZARD).toString(); + if (groupId.isEmpty() == false) { + groupComboBox->setCurrentIndex(groupComboBox->findData(groupId)); + } + connect(groupComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(groupCurrentIndexChanged(int))); +} + +//============================================================================ +// + +// +//============================================================================ +//============================================================================ +//============================================================================ + +RsidPage::RsidPage(QWidget *parent) : QWizardPage(parent) { + QString titleStr("%1"); + setTitle( titleStr.arg( tr("RetroShare ID") ) ) ; + + setSubTitle(tr("Use RetroShare ID for adding a Friend which is available in your network.")); + + + setAcceptDrops(true); + + userRsidLayout = new QHBoxLayout; + + userRsidFrame = new QGroupBox; + userRsidFrame->setFlat(true); + userRsidFrame->setTitle(tr("Add Friends RetroShare ID...")); + userRsidFrame->setLayout(userRsidLayout); + + friendRsidLabel = new QLabel(tr("Paste Friends RetroShare ID " + "in the box below " ) ); + friendRsidEdit = new QLineEdit; + friendRsidEdit->setWhatsThis(tr("Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF ")); + registerField("friendRSID*", friendRsidEdit); + + + friendRSIDLayout = new QHBoxLayout; + friendRSIDLayout->addWidget(friendRsidEdit) ; + + RsidLayout = new QVBoxLayout; + RsidLayout->addWidget(userRsidFrame); + RsidLayout->addWidget(friendRsidLabel); + RsidLayout->addLayout(friendRSIDLayout); + + setLayout(RsidLayout); +} + + +//============================================================================ + +bool RsidPage::isComplete() const { + return !( (friendRsidEdit->text()).isEmpty() ); +} + +int RsidPage::nextId() const { + + QString rsidstring = friendRsidEdit->text(); + + if (rsidstring.isEmpty() == false) { + // search for peer id in string + std::string rsidstr = PeerDefs::idFromRsid(rsidstring, false); + + RsPeerDetails pd; + if (rsidstr.empty() == false && rsPeers->getPeerDetails(rsidstr, pd) ) { + wizard()->setField(SSL_ID_FIELD_CONNECT_FRIEND_WIZARD, QString::fromStdString(pd.id)); + wizard()->setField(GPG_ID_FIELD_CONNECT_FRIEND_WIZARD, QString::fromStdString(pd.gpg_id)); + wizard()->setField(LOCATION_FIELD_CONNECT_FRIEND_WIZARD, QString::fromUtf8(pd.location.c_str())); + + wizard()->setField("ext_friend_ip", QString::fromStdString(pd.extAddr)); + wizard()->setField("ext_friend_port", QString::number(pd.extPort)); + wizard()->setField("local_friend_ip", QString::fromStdString(pd.localAddr)); + wizard()->setField("local_friend_port", QString::number(pd.localPort)); + wizard()->setField("dyndns", QString::fromStdString(pd.dyndns)); + + return ConnectFriendWizard::Page_Conclusion ; + } else { + wizard()->setField("errorMessage", QString(tr("This Peer %1 is not available in your Network")).arg(rsidstring) ); + return ConnectFriendWizard::Page_ErrorMessage; + } + } + + return ConnectFriendWizard::Page_Rsid; +} + +// +//============================================================================ +//============================================================================ +//============================================================================ + +EmailPage::EmailPage(QWidget *parent) : QWizardPage(parent) { + QString titleStr("%1"); + setTitle( titleStr.arg( tr("Invite Friends by Email") ) ) ; + + setSubTitle(tr("Enter your friends' email addresses (seperate each on with a semicolon)")); + + addressLabel = new QLabel(tr("Your friends' email addresses:" ) ); + addressEdit = new QLineEdit; + addressEdit->setWhatsThis(tr("Enter Friends Email addresses")); + registerField("addressEdit*", addressEdit); + + subjectLabel = new QLabel(tr("Subject:" ) ); + subjectEdit = new QLineEdit; + subjectEdit->setText(tr("Friend invites you to check out RetroShare")); + registerField("subjectEdit*", subjectEdit); + + emailhbox2Layout = new QHBoxLayout; + emailhbox2Layout->addWidget(addressLabel); + emailhbox2Layout->addWidget(addressEdit) ; + + emailhbox3Layout = new QHBoxLayout; + + emailhbox3Layout->addWidget(subjectLabel); + emailhbox3Layout->addWidget(subjectEdit ) ; + + inviteTextEdit = new QTextEdit; + inviteTextEdit->setReadOnly(true); + inviteTextEdit->setHtml(tr("Friend uses RetroShare to communicate securely, and invites you to join him to share files together.
    " + "RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled.
    " + "For more information, see our website http://retroshare.sourceforge.net/ " + "or download the software here http://retroshare.sourceforge.net/downloads.html.
    " + "See you soon on RetroShare!")); + + emailvboxLayout = new QVBoxLayout; + emailvboxLayout->addLayout(emailhbox2Layout); + emailvboxLayout->addLayout(emailhbox3Layout); + emailvboxLayout->addWidget(inviteTextEdit ) ; + + QFont font("Courier New",11,50,false); + font.setStyleHint(QFont::TypeWriter,QFont::PreferMatch); + font.setStyle(QFont::StyleNormal); + inviteTextEdit->setFont(font); + + setLayout(emailvboxLayout); +} + +//============================================================================ + +bool EmailPage::isComplete() const { + return !( (addressEdit->text()).isEmpty() ); +} + +int EmailPage::nextId() const { + return -1; +} + +bool EmailPage::validatePage() +{ + QString mailaddresses = addressEdit->text(); + + if (mailaddresses.isEmpty() == false) + { + std::string body = inviteTextEdit->toPlainText().toStdString(); + body += "\n\n" + rsPeers->GetRetroshareInvite(); + + sendMail (mailaddresses.toStdString(), subjectEdit->text().toStdString(), body); + return true; + } + + return false; +} diff --git a/retroshare-gui/src/gui/connect/ConnectFriendWizard.h b/retroshare-gui/src/gui/connect/ConnectFriendWizard.h new file mode 100755 index 000000000..a45461433 --- /dev/null +++ b/retroshare-gui/src/gui/connect/ConnectFriendWizard.h @@ -0,0 +1,326 @@ +#ifndef __ConnectFriendWizard__ +#define __ConnectFriendWizard__ + +#include +#include + +//QT_BEGIN_NAMESPACE +class QCheckBox; +class QLabel; +class QTextEdit; +class QLineEdit; +class QRadioButton; +class QVBoxLayout; +class QHBoxLayout; +class QGroupBox; +class QGridLayout; +class QComboBox; +class QTableWidget; +//QT_END_NAMESPACE + +//============================================================================ +//! A wizard for adding friends. Based on standard QWizard component + +//! The process of adding friends follows this scheme: +//! /-> Use text certificates \ /-> errorpage(if went wrong) +//! intro -| |-> -> +//! \-> Use *.pqi files / \-> fill peer details +//! +//! So, there are five possible pages in this wizard. + +class ConnectFriendWizard : public QWizard +{// + Q_OBJECT + +public: + + enum { Page_Intro, Page_Text, Page_Cert, Page_ErrorMessage, Page_Conclusion,Page_Foff, Page_Rsid, Page_Email }; + + ConnectFriendWizard(QWidget *parent = 0); + + void setGroup(const std::string &groupId); + + void accept(); + +private slots: +// void showHelp(); // we'll have to implement it in future +}; + +//============================================================================ +//! Introduction page for "Add friend" wizard. +class IntroPage : public QWizardPage +{ + Q_OBJECT + +public: + IntroPage(QWidget *parent = 0); + + int nextId() const; + +private: + QLabel *topLabel; + QRadioButton *textRadioButton; + QRadioButton *certRadioButton; + QRadioButton *foffRadioButton; + QRadioButton *rsidRadioButton; + QRadioButton *emailRadioButton; +}; + +//============================================================================ +//! Text page (for exchnging text certificates) for "Add friend" wizard. +class TextPage : public QWizardPage +{ + Q_OBJECT + +public: + TextPage(QWidget *parent = 0); + + int nextId() const; + +private: + QLabel* userCertLabel; + QTextEdit* userCertEdit; + QHBoxLayout* userCertLayout; + QVBoxLayout* userCertButtonsLayout; + QPushButton* userCertHelpButton; + QPushButton* userCertCopyButton; + QPushButton* userCertSaveButton; + QPushButton* userCertMailButton;//! on Windows, click on this button + //! launches default email client + QLabel* friendCertLabel; + QTextEdit* friendCertEdit; + QPushButton* friendCertCleanButton; + QVBoxLayout* friendCertButtonsLayout; + QHBoxLayout* friendCertLayout; + + QVBoxLayout* textPageLayout; + + void setCurrentFileName(const QString &fileName); + + QString fileName; + +private slots: + void showHelpUserCert(); + void copyCert(); + void cleanFriendCert(); + + bool fileSave(); + bool fileSaveAs(); + + + //! launches default email client (on windows) + //! Tested on Vista, it work normally... But a bit slowly. + void runEmailClient(); +}; + +//============================================================================ +//! A page for exchanging *.pqi files, for "Add friend" wizard. +class CertificatePage : public QWizardPage +{ + Q_OBJECT + +public: + CertificatePage(QWidget *parent = 0); + + int nextId() const; + bool isComplete() const ; + + void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + +private: + QGroupBox* userFileFrame; + QLabel *userFileLabel; + QPushButton* userFileCreateButton; + QHBoxLayout* userFileLayout; + + QLabel* friendFileLabel; + QLineEdit *friendFileNameEdit; + QPushButton* friendFileNameOpenButton; + QHBoxLayout* friendFileLayout; + + QVBoxLayout* certPageLayout; + +private slots: + void generateCertificateCalled(); + void loadFriendCert(); + + +}; + +//============================================================================ +//! A page for signing certificates from some people on the network (e.g. friends +// of friends, people trusting me...) +// +class FofPage : public QWizardPage +{ + Q_OBJECT + +public: + FofPage(QWidget *parent = 0); + + int nextId() const; + bool isComplete() const ; + +private: +// QGroupBox* userFileFrame; + QLabel *userFileLabel; + QVBoxLayout *userFileLayout; + QComboBox *userSelectionCB; + QPushButton* makeFriendButton; + QTableWidget *selectedPeersTW; + + QVBoxLayout* certPageLayout; + + bool _friends_signed ; + std::map _id_boxes ; + std::map _gpg_id_boxes ; + +private slots: + void signAllSelectedUsers() ; + void updatePeersList(int) ; +}; + + +//============================================================================ +//! Page for displaying error messages (for "Add friend" wizard). +class ErrorMessagePage : public QWizardPage +{ + Q_OBJECT + +public: + ErrorMessagePage(QWidget *parent = 0); + + int nextId() const; + +private: + QLabel *messageLabel; + QVBoxLayout* errMessLayout; +}; + +//============================================================================ +//! Page for filling peer details in "Add friend" wizard. + +//! Warning: This page duplicates functionality of the ConnectDialo class (and +//! also some pieces of code). TODO: remove this duplication +class ConclusionPage : public QWizardPage +{ + Q_OBJECT + +public: + ConclusionPage(QWidget *parent = 0); + + void initializePage(); + int nextId() const; + +private slots: +// void printButtonClicked(); + void groupCurrentIndexChanged(int index); + +private: + QGroupBox* peerDetailsFrame; + QGridLayout* peerDetailsLayout; + QGroupBox* optionsFrame; + QGridLayout* optionsLayout; + QLabel* trustLabel; + QLabel* trustEdit; + QLabel* nameLabel; + QLabel* nameEdit; + QLabel* emailLabel; + QLabel* emailEdit; + QLabel* locLabel; + QLabel* locEdit; + QLabel* signersLabel; + QTextEdit* signersEdit; + QComboBox* groupComboBox; + QLabel* groupLabel; + + QLabel* radioButtonsLabel; + QCheckBox *signGPGCheckBox; + QCheckBox *acceptNoSignGPGCheckBox; + + QVBoxLayout* conclusionPageLayout; + + //! peer id + +// //! It's a hack; This widget is used only to register "id" field in the +// //! wizard. Really the widget isn't displayed. + QLineEdit* peerIdEdit; + QLineEdit* peerGPGIdEdit; + QLineEdit* peerLocation; + QLineEdit* peerCertStringEdit; + QLineEdit* ext_friend_ip; + QLineEdit* ext_friend_port; + QLineEdit* local_friend_ip; + QLineEdit* local_friend_port; + QLineEdit* dyndns; +}; + +//============================================================================ +//! A page for exchanging RSID , for "Add friend" wizard. +class RsidPage : public QWizardPage +{ + Q_OBJECT + +public: + RsidPage(QWidget *parent = 0); + + int nextId() const; + bool isComplete() const ; + + +private: + QGroupBox* userRsidFrame; + QLabel *userFileLabel; + QHBoxLayout* userRsidLayout; + + QLabel* friendRsidLabel; + QLineEdit *friendRsidEdit; + QHBoxLayout* friendRSIDLayout; + + QVBoxLayout* RsidLayout; + +private slots: + + + +}; + +//============================================================================ + +//============================================================================ +//! A page for Email Invite +class EmailPage : public QWizardPage +{ + Q_OBJECT + +public: + EmailPage(QWidget *parent = 0); + + int nextId() const; + bool isComplete() const ; + bool validatePage(); + +private: + QLabel* addressLabel; + QLineEdit *addressEdit; + + QLabel* subjectLabel; + QLineEdit *subjectEdit; + + QTextEdit* inviteTextEdit; + + QHBoxLayout* emailhbox2Layout; + QHBoxLayout* emailhbox3Layout; + + QVBoxLayout* emailvboxLayout; + +private slots: + + + +}; + +//============================================================================ + +#endif diff --git a/retroshare-gui/src/gui/elastic/arrow.cpp b/retroshare-gui/src/gui/elastic/arrow.cpp new file mode 100644 index 000000000..8ef0991d4 --- /dev/null +++ b/retroshare-gui/src/gui/elastic/arrow.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2006-2007 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/ +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.0, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** In addition, as a special exception, Trolltech, as the sole copyright +** holder for Qt Designer, grants users of the Qt/Eclipse Integration +** plug-in the right for the Qt/Eclipse Integration to link to +** functionality provided by Qt Designer and its related libraries. +** +** Trolltech reserves all rights not expressly granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include + +#include "arrow.h" +#include "node.h" + +#include + +static const double Pi = 3.14159265358979323846264338327950288419717; +static double TwoPi = 2.0 * Pi; + +Arrow::Arrow(Node *sourceNode, Node *destNode) + : arrowSize(10) +{ + setAcceptedMouseButtons(0); + source = sourceNode; + dest = destNode; +#ifdef SUSP + source->addArrow(this); + dest->addArrow(this); +#endif + adjust(); +} + +Arrow::~Arrow() +{ +} + +Node *Arrow::sourceNode() const +{ + return source; +} + +void Arrow::setSourceNode(Node *node) +{ + source = node; + adjust(); +} + +Node *Arrow::destNode() const +{ + return dest; +} + +void Arrow::setDestNode(Node *node) +{ + dest = node; + adjust(); +} + +void Arrow::adjust() +{ + if (!source || !dest) + return; + + QLineF line(mapFromItem(source, 0, 0), mapFromItem(dest, 0, 0)); + qreal length = line.length(); + QPointF edgeOffset((line.dx() * 10) / length, (line.dy() * 10) / length); + + prepareGeometryChange(); + sourcePoint = line.p1() + edgeOffset; + destPoint = line.p2() - edgeOffset; +} + +QRectF Arrow::boundingRect() const +{ + if (!source || !dest) + return QRectF(); + + qreal penWidth = 1; + qreal extra = (penWidth + arrowSize) / 2.0; + + return QRectF(sourcePoint, QSizeF(destPoint.x() - sourcePoint.x(), + destPoint.y() - sourcePoint.y())) + .normalized() + .adjusted(-extra, -extra, extra, extra); +} + +void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + if (!source || !dest) + return; + + // Draw the line itself + QLineF line(sourcePoint, destPoint); + //painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter->setPen(QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter->drawLine(line); + + // Draw the arrows if there's enough room + double angle = ::acos(line.dx() / line.length()); + if (line.dy() >= 0) + angle = TwoPi - angle; + + QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + Pi / 3) * arrowSize, + cos(angle + Pi / 3) * arrowSize); + QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + Pi - Pi / 3) * arrowSize, + cos(angle + Pi - Pi / 3) * arrowSize); + QPointF destArrowP1 = destPoint + QPointF(sin(angle - Pi / 3) * arrowSize, + cos(angle - Pi / 3) * arrowSize); + QPointF destArrowP2 = destPoint + QPointF(sin(angle - Pi + Pi / 3) * arrowSize, + cos(angle - Pi + Pi / 3) * arrowSize); + + painter->setBrush(Qt::black); + painter->drawPolygon(QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2); + painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2); +} diff --git a/retroshare-gui/src/gui/elastic/arrow.h b/retroshare-gui/src/gui/elastic/arrow.h new file mode 100644 index 000000000..9bcbc170e --- /dev/null +++ b/retroshare-gui/src/gui/elastic/arrow.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2006-2007 Trolltech ASA. All rights reserved. +** +** This file is part of the example classes of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/ +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.0, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** In addition, as a special exception, Trolltech, as the sole copyright +** holder for Qt Designer, grants users of the Qt/Eclipse Integration +** plug-in the right for the Qt/Eclipse Integration to link to +** functionality provided by Qt Designer and its related libraries. +** +** Trolltech reserves all rights not expressly granted herein. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef ARROW_H +#define ARROW_H + +#include + +class Node; + +class Arrow : public QGraphicsItem +{ +public: + Arrow(Node *sourceNode, Node *destNode); + ~Arrow(); + + Node *sourceNode() const; + void setSourceNode(Node *node); + + Node *destNode() const; + void setDestNode(Node *node); + + void adjust(); + + enum { Type = UserType + 3 }; + int type() const { return Type; } + +protected: + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +private: + Node *source, *dest; + + QPointF sourcePoint; + QPointF destPoint; + qreal arrowSize; +}; + +#endif diff --git a/retroshare-gui/src/gui/elastic/edge.cpp b/retroshare-gui/src/gui/elastic/edge.cpp new file mode 100644 index 000000000..220bb3b55 --- /dev/null +++ b/retroshare-gui/src/gui/elastic/edge.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "edge.h" +#include "node.h" + +#include + +static const double Pi = 3.14159265358979323846264338327950288419717; +static double TwoPi = 2.0 * Pi; + +Edge::Edge(Node *sourceNode, Node *destNode) + : arrowSize(10) +{ + setAcceptedMouseButtons(0); + source = sourceNode; + dest = destNode; + source->addEdge(this); + dest->addEdge(this); + adjust(); +} + +Edge::~Edge() +{ +} + +Node *Edge::sourceNode() const +{ + return source; +} + +void Edge::setSourceNode(Node *node) +{ + source = node; + adjust(); +} + +Node *Edge::destNode() const +{ + return dest; +} + +void Edge::setDestNode(Node *node) +{ + dest = node; + adjust(); +} + +void Edge::adjust() +{ + if (!source || !dest) + return; + + QLineF line(mapFromItem(source, 0, 0), mapFromItem(dest, 0, 0)); + qreal length = line.length(); + if(length==0.0f) + length=1.0 ; + QPointF edgeOffset((line.dx() * 10) / length, (line.dy() * 10) / length); + + prepareGeometryChange(); + sourcePoint = line.p1() + edgeOffset; + destPoint = line.p2() - edgeOffset; +} + +QRectF Edge::boundingRect() const +{ + if (!source || !dest) + return QRectF(); + + qreal penWidth = 1; + qreal extra = (penWidth + arrowSize) / 2.0; + + return QRectF(sourcePoint, QSizeF(destPoint.x() - sourcePoint.x(), + destPoint.y() - sourcePoint.y())) + .normalized() + .adjusted(-extra, -extra, extra, extra); +} + +void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + if (!source || !dest) + return; + + // Draw the line itself + QLineF line(sourcePoint, destPoint); + painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter->drawLine(line); + + return ; + // Draw the arrows if there's enough room + + float length = line.length() ; + float cos_theta,sin_theta ; + + if(length == 0.0f) + { + cos_theta = 1.0f ; + sin_theta = 0.0f ; + } + else + { + cos_theta = line.dx() / length ; + sin_theta =-line.dy() / length ; + } + + static const float cos_pi_over_3 = 0.5 ; + static const float sin_pi_over_3 = 0.5 * sqrt(3) ; + static const float cos_2_pi_over_3 =-0.5 ; + static const float sin_2_pi_over_3 = 0.5 * sqrt(3) ; + + float cos_theta_plus_pi_over_3 = cos_theta * cos_pi_over_3 - sin_theta * sin_pi_over_3 ; + float sin_theta_plus_pi_over_3 = sin_theta * cos_pi_over_3 + cos_theta * sin_pi_over_3 ; + + float cos_theta_mins_pi_over_3 = cos_theta_plus_pi_over_3 + 2 * sin_theta * sin_pi_over_3 ; + float sin_theta_mins_pi_over_3 = sin_theta_plus_pi_over_3 - 2 * cos_theta * sin_pi_over_3 ; + + float cos_theta_plus_2_pi_over_3 = cos_theta * cos_2_pi_over_3 - sin_theta * sin_2_pi_over_3 ; + float sin_theta_plus_2_pi_over_3 = sin_theta * cos_2_pi_over_3 + cos_theta * sin_2_pi_over_3 ; + + float cos_theta_mins_2_pi_over_3 = cos_theta_plus_2_pi_over_3 + 2 * sin_theta * sin_2_pi_over_3 ; + float sin_theta_mins_2_pi_over_3 = sin_theta_plus_2_pi_over_3 - 2 * cos_theta * sin_2_pi_over_3 ; + + QPointF sourceArrowP1 = sourcePoint + QPointF( sin_theta_plus_pi_over_3 * arrowSize, cos_theta_plus_pi_over_3 * arrowSize); + QPointF sourceArrowP2 = sourcePoint + QPointF(sin_theta_plus_2_pi_over_3 * arrowSize, cos_theta_plus_2_pi_over_3 * arrowSize); + + QPointF destArrowP1 = destPoint + QPointF( sin_theta_mins_pi_over_3 * arrowSize, cos_theta_mins_pi_over_3 * arrowSize); + QPointF destArrowP2 = destPoint + QPointF(sin_theta_mins_2_pi_over_3 * arrowSize, cos_theta_mins_2_pi_over_3 * arrowSize); + + painter->setBrush(Qt::black); + painter->drawConvexPolygon(QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2); + painter->drawConvexPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2); +} + diff --git a/retroshare-gui/src/gui/elastic/edge.h b/retroshare-gui/src/gui/elastic/edge.h new file mode 100644 index 000000000..4a2cc0cd9 --- /dev/null +++ b/retroshare-gui/src/gui/elastic/edge.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EDGE_H +#define EDGE_H + +#include + +class Node; + +class Edge : public QGraphicsItem +{ +public: + Edge(Node *sourceNode, Node *destNode); + ~Edge(); + + Node *sourceNode() const; + void setSourceNode(Node *node); + + Node *destNode() const; + void setDestNode(Node *node); + + void adjust(); + + enum { Type = UserType + 2 }; + int type() const { return Type; } + +protected: + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +private: + Node *source, *dest; + + QPointF sourcePoint; + QPointF destPoint; + qreal arrowSize; +}; + +#endif diff --git a/retroshare-gui/src/gui/elastic/graphwidget.cpp b/retroshare-gui/src/gui/elastic/graphwidget.cpp new file mode 100644 index 000000000..96634d3ad --- /dev/null +++ b/retroshare-gui/src/gui/elastic/graphwidget.cpp @@ -0,0 +1,425 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "graphwidget.h" +#include "edge.h" +#include "node.h" + +#include +#include +#include +#include + +#include + +#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr + +void fourn(double data[],unsigned long nn[],unsigned long ndim,int isign) +{ + int i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2; + int ibit,idim,k1,k2,n,nprev,nrem,ntot; + double tempi,tempr; + double theta,wi,wpi,wpr,wr,wtemp; + + ntot=1; + for (idim=1;idim<=ndim;idim++) + ntot *= nn[idim]; + nprev=1; + for (idim=ndim;idim>=1;idim--) { + n=nn[idim]; + nrem=ntot/(n*nprev); + ip1=nprev << 1; + ip2=ip1*n; + ip3=ip2*nrem; + i2rev=1; + for (i2=1;i2<=ip2;i2+=ip1) { + if (i2 < i2rev) { + for (i1=i2;i1<=i2+ip1-2;i1+=2) { + for (i3=i1;i3<=ip3;i3+=ip2) { + i3rev=i2rev+i3-i2; + SWAP(data[i3],data[i3rev]); + SWAP(data[i3+1],data[i3rev+1]); + } + } + } + ibit=ip2 >> 1; + while (ibit >= ip1 && i2rev > ibit) { + i2rev -= ibit; + ibit >>= 1; + } + i2rev += ibit; + } + ifp1=ip1; + while (ifp1 < ip2) { + ifp2=ifp1 << 1; + theta=isign*6.28318530717959/(ifp2/ip1); + wtemp=sin(0.5*theta); + wpr = -2.0*wtemp*wtemp; + wpi=sin(theta); + wr=1.0; + wi=0.0; + for (i3=1;i3<=ifp1;i3+=ip1) { + for (i1=i3;i1<=i3+ip1-2;i1+=2) { + for (i2=i1;i2<=ip3;i2+=ifp2) { + k1=i2; + k2=k1+ifp1; + tempr=wr*data[k2]-wi*data[k2+1]; + tempi=wr*data[k2+1]+wi*data[k2]; + data[k2]=data[k1]-tempr; + data[k2+1]=data[k1+1]-tempi; + data[k1] += tempr; + data[k1+1] += tempi; + } + } + wr=(wtemp=wr)*wpr-wi*wpi+wr; + wi=wi*wpr+wtemp*wpi+wi; + } + ifp1=ifp2; + } + nprev *= n; + } +} + +#undef SWAP + +GraphWidget::GraphWidget(QWidget *) + : timerId(0) +{ +// QGraphicsScene *scene = new QGraphicsScene(QRectF(0,0,500,500),this); +// scene->setItemIndexMethod(QGraphicsScene::NoIndex); +// scene->clear() ; +// setScene(scene); +// scene->setSceneRect(0, 0, 500, 500); + + setCacheMode(CacheBackground); + setViewportUpdateMode(BoundingRectViewportUpdate); + setRenderHint(QPainter::Antialiasing); + setTransformationAnchor(AnchorUnderMouse); + setResizeAnchor(AnchorViewCenter); + + + + scale(qreal(0.8), qreal(0.8)); +} + +void GraphWidget::clearGraph() +{ +// QGraphicsScene *scene = new QGraphicsScene(this); +// scene->setItemIndexMethod(QGraphicsScene::NoIndex); +// setScene(scene); + +// scene->addItem(centerNode); +// centerNode->setPos(0, 0); + +// if (oldscene != NULL) +// { +// delete oldscene; +// } + + scene()->clear(); + scene()->setSceneRect(-200, -200, 1000, 1000); + _edges.clear(); + _nodes.clear(); +} + +GraphWidget::NodeId GraphWidget::addNode(const std::string& node_short_string,const std::string& node_complete_string,NodeType type,AuthType auth,const std::string& ssl_id,const std::string& gpg_id) +{ + Node *node = new Node(node_short_string,type,auth,this,ssl_id,gpg_id); + node->setToolTip(QString::fromStdString(node_complete_string)) ; + _nodes.push_back(node) ; + scene()->addItem(node); + + std::map::const_iterator it(_node_cached_positions.find(gpg_id)) ; + if(_node_cached_positions.end() != it) + node->setPos(it->second) ; + else + { + qreal x1,y1,x2,y2 ; + sceneRect().getCoords(&x1,&y1,&x2,&y2) ; + + float f1 = (type == GraphWidget::ELASTIC_NODE_TYPE_OWN)?0.5:(rand()/(float)RAND_MAX) ; + float f2 = (type == GraphWidget::ELASTIC_NODE_TYPE_OWN)?0.5:(rand()/(float)RAND_MAX) ; + + node->setPos(x1+f1*(x2-x1),y1+f2*(y2-y1)); + } +#ifdef DEBUG_ELASTIC + std::cerr << "Added node " << _nodes.size()-1 << std::endl ; +#endif + return _nodes.size()-1 ; +} +void GraphWidget::snapshotNodesPositions() +{ + for(uint32_t i=0;i<_nodes.size();++i) + _node_cached_positions[_nodes[i]->idString()] = _nodes[i]->mapToScene(QPointF(0,0)) ; +} +void GraphWidget::clearNodesPositions() +{ + _node_cached_positions.clear() ; +} + +GraphWidget::EdgeId GraphWidget::addEdge(NodeId n1,NodeId n2) +{ + std::pair ed(std::min(n1,n2),std::max(n1,n2)) ; + + if( _edges.find(ed) == _edges.end() ) + { + Edge *edge = new Edge(_nodes[n1],_nodes[n2]); + scene()->addItem(edge); + _edges[ed] = edge ; +#ifdef DEBUG_ELASTIC + std::cerr << "Added edge " << n1 << " - " << n2 << std::endl ; +#endif + } + + return 0 ; +} + +void GraphWidget::itemMoved() +{ + if (!timerId) + { +#ifdef DEBUG_ELASTIC + std::cout << "starting timer" << std::endl; +#endif + timerId = startTimer(1000 / 25); + } +} + +void GraphWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { +// case Qt::Key_Up: +// centerNode->moveBy(0, -20); +// break; +// case Qt::Key_Down: +// centerNode->moveBy(0, 20); +// break; +// case Qt::Key_Left: +// centerNode->moveBy(-20, 0); +// break; +// case Qt::Key_Right: +// centerNode->moveBy(20, 0); +// break; + case Qt::Key_Plus: + scaleView(qreal(1.2)); + break; + case Qt::Key_Minus: + scaleView(1 / qreal(1.2)); + break; + case Qt::Key_Space: + case Qt::Key_Enter: + foreach (QGraphicsItem *item, scene()->items()) { + if (qgraphicsitem_cast(item)) + item->setPos(-150 + qrand() % 300, -150 + qrand() % 300); + } + break; + default: + QGraphicsView::keyPressEvent(event); + } +} + +static void convolveWithGaussian(double *forceMap,int S,int s) +{ + static double *bf = NULL ; + + if(bf == NULL) + { + bf = new double[S*S*2] ; + + for(int i=0;i derivative is constant + bf[2*(i+S*j)+1] = 0 ; + } + + unsigned long nn[2] = {S,S}; + fourn(&bf[-1],&nn[-1],2,1) ; + } + + unsigned long nn[2] = {S,S}; + fourn(&forceMap[-1],&nn[-1],2,1) ; + + for(int i=0;isceneRect()) ; + + foreach (Node *node, _nodes) + { + QPointF pos = node->mapToScene(QPointF(0,0)) ; + + float x = S*(pos.x()-R.left())/R.width() ; + float y = S*(pos.y()- R.top())/R.height() ; + + int i=(int)floor(x) ; + int j=(int)floor(y) ; + float di = x-i ; + float dj = y-j ; + + if( i>=0 && i=0 && jmapToScene(QPointF(0,0)) ; + float x = S*(pos.x()-R.left())/R.width() ; + float y = S*(pos.y()-R.top())/R.height() ; + + node->calculateForces(forceMap,R.width(),R.height(),S,S,x,y,speedf); + } + + bool itemsMoved = false; + foreach (Node *node, _nodes) + if(node->advance()) + itemsMoved = true; + + if (!itemsMoved) { + killTimer(timerId); +#ifdef DEBUG_ELASTIC + std::cerr << "Killing timr" << std::endl ; +#endif + timerId = 0; + } +} + +void GraphWidget::setEdgeLength(uint32_t l) +{ + _edge_length = l ; + + if(!timerId) + { +#ifdef DEBUG_ELASTIC + std::cout << "starting timer" << std::endl; +#endif + timerId = startTimer(1000 / 25); + } +} + +void GraphWidget::wheelEvent(QWheelEvent *event) +{ + scaleView(pow((double)2, -event->delta() / 240.0)); +} + +void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect) +{ + Q_UNUSED(rect); + + // Shadow + QRectF sceneRect = this->sceneRect(); + QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height()); + QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5); + if (rightShadow.intersects(rect) || rightShadow.contains(rect)) + painter->fillRect(rightShadow, Qt::darkGray); + if (bottomShadow.intersects(rect) || bottomShadow.contains(rect)) + painter->fillRect(bottomShadow, Qt::darkGray); + + // Fill + QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight()); + gradient.setColorAt(0, Qt::white); + gradient.setColorAt(1, Qt::lightGray); + painter->fillRect(rect.intersect(sceneRect), gradient); + painter->setBrush(Qt::NoBrush); + painter->drawRect(sceneRect); + + // Text + QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4, + sceneRect.width() - 4, sceneRect.height() - 4); + QString message(tr("Click and drag the nodes around, and zoom with the mouse " + "wheel or the '+' and '-' keys")); + + QFont font = painter->font(); + font.setBold(true); + font.setPointSize(14); + painter->setFont(font); + painter->setPen(Qt::lightGray); + painter->drawText(textRect.translated(2, 2), message); + painter->setPen(Qt::black); + painter->drawText(textRect, message); +} + +void GraphWidget::scaleView(qreal scaleFactor) +{ + qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); + if (factor < 0.07 || factor > 100) + return; + + scale(scaleFactor, scaleFactor); +} diff --git a/retroshare-gui/src/gui/elastic/graphwidget.h b/retroshare-gui/src/gui/elastic/graphwidget.h new file mode 100644 index 000000000..de71b59a2 --- /dev/null +++ b/retroshare-gui/src/gui/elastic/graphwidget.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GRAPHWIDGET_H +#define GRAPHWIDGET_H + +#include +#include +#include + +class Node; +class Edge; + +class GraphWidget : public QGraphicsView +{ + Q_OBJECT + +public: + GraphWidget(QWidget * = NULL); + + typedef int NodeId ; + typedef int EdgeId ; + + typedef enum { + ELASTIC_NODE_TYPE_OWN = 0x0000, + ELASTIC_NODE_TYPE_FRIEND = 0x0001, + ELASTIC_NODE_TYPE_F_OF_F = 0x0002, + ELASTIC_NODE_TYPE_UNKNOWN = 0x0003 + } NodeType ; + + typedef enum { + ELASTIC_NODE_AUTH_FULL = 0x0000, + ELASTIC_NODE_AUTH_MARGINAL = 0x0001, + ELASTIC_NODE_AUTH_UNKNOWN = 0x0002 + } AuthType ; + + NodeId addNode(const std::string& NodeShortText,const std::string& nodeCompleteText,NodeType type,AuthType auth,const std::string& ssl_id,const std::string& gpg_id) ; + EdgeId addEdge(NodeId n1,NodeId n2) ; + + void snapshotNodesPositions() ; + void clearNodesPositions() ; + void clearGraph() ; + virtual void itemMoved(); + + void setEdgeLength(uint32_t l) ; + uint32_t edgeLength() const { return _edge_length ; } + +protected: + void keyPressEvent(QKeyEvent *event); + void timerEvent(QTimerEvent *event); + void wheelEvent(QWheelEvent *event); + void drawBackground(QPainter *painter, const QRectF &rect); + + void scaleView(qreal scaleFactor); + +private: + int timerId; + //Node *centerNode; + bool mDeterminedBB ; + + std::vector _nodes ; + std::map,Edge *> _edges ; + std::map _node_cached_positions ; + + uint32_t _edge_length ; +}; + +#endif diff --git a/retroshare-gui/src/gui/elastic/node.cpp b/retroshare-gui/src/gui/elastic/node.cpp new file mode 100644 index 000000000..d32a1019e --- /dev/null +++ b/retroshare-gui/src/gui/elastic/node.cpp @@ -0,0 +1,333 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "edge.h" +#include "node.h" +#include "graphwidget.h" + +#define IMAGE_AUTHED ":/images/accepted16.png" +#define IMAGE_DENIED ":/images/denied16.png" +#define IMAGE_TRUSTED ":/images/rs-2.png" +#define IMAGE_MAKEFRIEND ":/images/user/add_user16.png" + +Node::Node(const std::string& node_string,GraphWidget::NodeType type,GraphWidget::AuthType auth,GraphWidget *graphWidget,const std::string& ssl_id,const std::string& gpg_id) + : graph(graphWidget),_desc_string(node_string),_type(type),_auth(auth),_ssl_id(ssl_id),_gpg_id(gpg_id) +{ +#ifdef DEBUG_ELASTIC + std::cerr << "Created node type " << type << ", string=" << node_string << std::endl ; +#endif + setFlag(ItemIsMovable); +#if QT_VERSION >= 0x040600 + setFlag(ItemSendsGeometryChanges); +#endif + setCacheMode(DeviceCoordinateCache); + setZValue(1); + mDeterminedBB = false ; + mBBWidth = 0 ; + + _speedx=_speedy=0; + _steps=0; +} + +void Node::addEdge(Edge *edge) +{ + edgeList << edge; + edge->adjust(); +} + +const QList& Node::edges() const +{ + return edgeList; +} + +static double interpolate(const double *map,int W,int H,float x,float y) +{ + if(x>W-2) x=W-2 ; + if(y>H-2) y=H-2 ; + if(x<0 ) x=0 ; + if(y<0 ) y=0 ; + + int i=(int)floor(x) ; + int j=(int)floor(y) ; + double di = x-i ; + double dj = y-j ; + + return (1-di)*( (1-dj)*map[2*(i+W*j)] + dj*map[2*(i+W*(j+1))]) + +di *( (1-dj)*map[2*(i+1+W*j)] + dj*map[2*(i+1+W*(j+1))]) ; +} + +void Node::calculateForces(const double *map,int width,int height,int W,int H,float x,float y,float speedf) +{ + if (!scene() || scene()->mouseGrabberItem() == this) + { + newPos = pos(); + return; + } + + + // Sum up all forces pushing this item away + qreal xforce = 0; + qreal yforce = 0; + + float dei=0.0f ; + float dej=0.0f ; + + static float *e = NULL ; + static const int KS = 5 ; + + if(e == NULL) + { + e = new float[(2*KS+1)*(2*KS+1)] ; + + for(int i=-KS;i<=KS;++i) + for(int j=-KS;j<=KS;++j) + e[i+KS+(2*KS+1)*(j+KS)] = exp( -(i*i+j*j)/30.0 ) ; // can be precomputed + } + + for(int i=-KS;i<=KS;++i) + for(int j=-KS;j<=KS;++j) + { + int X = std::min(W-1,std::max(0,(int)rint(x))) ; + int Y = std::min(H-1,std::max(0,(int)rint(y))) ; + + float val = map[2*((i+X+W)%W + W*((j+Y+H)%H))] ; + + dei += i * e[i+KS+(2*KS+1)*(j+KS)] * val ; + dej += j * e[i+KS+(2*KS+1)*(j+KS)] * val ; + } + + xforce = REPULSION_FACTOR * dei/25.0; + yforce = REPULSION_FACTOR * dej/25.0; + + // Now subtract all forces pulling items together + double weight = (n_edges() + 1) ; + + foreach (Edge *edge, edgeList) { + QPointF pos; + double w2 ; // This factor makes the edge length depend on connectivity, so clusters of friends tend to stay in the + // same location. + // + if (edge->sourceNode() == this) + { + pos = mapFromItem(edge->destNode(), 0, 0); + w2 = sqrtf(std::min(n_edges(),edge->destNode()->n_edges())) ; + } + else + { + pos = mapFromItem(edge->sourceNode(), 0, 0); + w2 = sqrtf(std::min(n_edges(),edge->sourceNode()->n_edges())) ; + } + + float dist = sqrtf(pos.x()*pos.x() + pos.y()*pos.y()) ; + float val = dist - graph->edgeLength() * w2 ; + + xforce += 0.01*pos.x() * val / weight; + yforce += 0.01*pos.y() * val / weight; + } + + xforce -= FRICTION_FACTOR * _speedx ; + yforce -= FRICTION_FACTOR * _speedy ; + + // This term drags nodes away from the sides. + // + if(x < 15) xforce += 100.0/(x+0.1) ; + if(y < 15) yforce += 100.0/(y+0.1) ; + if(x > width-15) xforce -= 100.0/(width-x+0.1) ; + if(y > height-15) yforce -= 100.0/(height-y+0.1) ; + + // now time filter: + + _speedx += xforce / MASS_FACTOR; + _speedy += yforce / MASS_FACTOR; + + if(_speedx > 10) _speedx = 10.0f ; + if(_speedy > 10) _speedy = 10.0f ; + if(_speedx <-10) _speedx =-10.0f ; + if(_speedy <-10) _speedy =-10.0f ; + + QRectF sceneRect = scene()->sceneRect(); + newPos = pos() + QPointF(_speedx, _speedy); + newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)); + newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)); +} + +bool Node::advance() +{ + if(_type == GraphWidget::ELASTIC_NODE_TYPE_OWN) + return false; + + float f = std::max(fabs(newPos.x() - pos().x()), fabs(newPos.y() - pos().y())) ; + + setPos(newPos); + return f > 0.5; +} + +QRectF Node::boundingRect() const +{ + qreal adjust = 2; + /* add in the size of the text */ + qreal realwidth = 40; + if (mDeterminedBB) + { + realwidth = mBBWidth + adjust; + } + if (realwidth < 23 + adjust) + { + realwidth = 23 + adjust; + } + + return QRectF(-10 - adjust, -10 - adjust, + realwidth, 23 + adjust); +} + +QPainterPath Node::shape() const +{ + QPainterPath path; + path.addEllipse(-10, -10, 20, 20); + return path; +} + +void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + static QColor type_color[4] = { QColor(Qt::yellow), QColor(Qt::green), QColor(Qt::cyan), QColor(Qt::black) } ; + + QColor col0(type_color[_type]) ; + + painter->setPen(Qt::NoPen); + painter->setBrush(Qt::darkGray); + painter->drawEllipse(-7, -7, 20, 20); + + QRadialGradient gradient(-3, -3, 10); + if (option->state & QStyle::State_Sunken) + { + gradient.setCenter(3, 3); + gradient.setFocalPoint(3, 3); + gradient.setColorAt(1, col0.light(120).dark(100+_auth*100)); + gradient.setColorAt(0, col0.light(70).dark(100+_auth*100)); + } + else + { + gradient.setColorAt(1, col0.light(50).dark(100+_auth*100)); + gradient.setColorAt(0, col0.dark(100+_auth*100)); + } + painter->setBrush(gradient); + painter->setPen(QPen(Qt::black, 0)); + painter->drawEllipse(-10, -10, 20, 20); + painter->drawText(-10, 0, QString::fromStdString(_desc_string)); + + if (!mDeterminedBB) + { + QRect textBox = painter->boundingRect(-10, 0, 400, 20, 0, QString::fromStdString(_desc_string)); + mBBWidth = textBox.width(); + mDeterminedBB = true; + } +} + +QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) +{ + switch (change) { + case ItemPositionHasChanged: + foreach (Edge *edge, edgeList) + edge->adjust(); + graph->itemMoved(); + break; + default: + break; + }; + + return QGraphicsItem::itemChange(change, value); +} + +void Node::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + update(); + QGraphicsItem::mousePressEvent(event); +} + +void Node::peerDetails() +{ +#ifdef DEBUG_ELASTIC + std::cerr << "Calling peer details" << std::endl; +#endif + ConfCertDialog::showIt(_gpg_id, ConfCertDialog::PageDetails); +} +void Node::makeFriend() +{ + ConfCertDialog::showIt(_gpg_id, ConfCertDialog::PageTrust); +} +void Node::denyFriend() +{ + ConfCertDialog::showIt(_gpg_id, ConfCertDialog::PageTrust); +} + +void Node::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + QMenu contextMnu ; + + if(_type == GraphWidget::ELASTIC_NODE_TYPE_FRIEND) + contextMnu.addAction(QIcon(IMAGE_DENIED), QObject::tr( "Deny friend" ), this, SLOT(denyFriend()) ); + else if(_type != GraphWidget::ELASTIC_NODE_TYPE_OWN) + contextMnu.addAction(QIcon(IMAGE_MAKEFRIEND), QObject::tr( "Make friend" ), this, SLOT(makeFriend()) ); + + contextMnu.addAction(QIcon(IMAGE_MAKEFRIEND), QObject::tr( "Peer details" ), this, SLOT(peerDetails()) ); + + contextMnu.exec(event->screenPos()); +} + +void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + update(); + QGraphicsItem::mouseReleaseEvent(event); +} diff --git a/retroshare-gui/src/gui/elastic/node.h b/retroshare-gui/src/gui/elastic/node.h new file mode 100644 index 000000000..a194150bf --- /dev/null +++ b/retroshare-gui/src/gui/elastic/node.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the example classes of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NODE_H +#define NODE_H + +#include +#include + +#include "graphwidget.h" + +class Edge; +QT_BEGIN_NAMESPACE +class QGraphicsSceneMouseEvent; +QT_END_NAMESPACE + +class Node : public QObject, public QGraphicsItem +{ + Q_OBJECT + +public: + Node(const std::string& node_string,GraphWidget::NodeType type,GraphWidget::AuthType auth,GraphWidget *graphWidget,const std::string& ssl_id,const std::string& gpg_id); + + void addEdge(Edge *edge); + const QList& edges() const; + + int type() const { return Type; } + const std::string& idString() const { return _gpg_id ; } + + void calculateForces(const double *data,int width,int height,int W,int H,float x,float y,float speedf); + bool advance(); + + QRectF boundingRect() const; + QPainterPath shape() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + int n_edges() const { return edgeList.size() ; } +protected: + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + + virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *) ; + + protected slots: + void denyFriend() ; + void makeFriend() ; + void peerDetails() ; +private: + QList edgeList; + QPointF newPos; + GraphWidget *graph; + qreal _speedx,_speedy; + int _steps ; + std::string _desc_string ; + GraphWidget::NodeType _type ; + GraphWidget::AuthType _auth ; + bool mDeterminedBB ; + int mBBWidth ; + + std::string _ssl_id ; + std::string _gpg_id ; + + static const float MASS_FACTOR = 10 ; + static const float FRICTION_FACTOR = 6.8 ; + static const float REPULSION_FACTOR = 4 ; + static const float NODE_DISTANCE = 130.0 ; +}; + +#endif diff --git a/retroshare-gui/src/gui/feeds/AttachFileItem.cpp b/retroshare-gui/src/gui/feeds/AttachFileItem.cpp new file mode 100644 index 000000000..a9ea91c88 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/AttachFileItem.cpp @@ -0,0 +1,525 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "AttachFileItem.h" + +#include + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/******************************************************************* + * AttachFileItem fully controls the file transfer from the gui side + * + * Display: (In order) + * + * 1) HASHING + * 2) REMOTE / DOWNLOAD + * 3) LOCAL + * 4) LOCAL / UPLOAD + * + * Behaviours: + * a) Addition to General Dialog (1), (2), (3) + * (i) (1), request Hash -> (3). + * (ii) (2), download complete -> (3) + * (iii) (3) + * + * b) Message/Blog/Channel (2), (3) + * (i) (2), download complete -> (3) + * (ii) (3) + * + * c) Transfers (2), (4) + * (i) (2) + * (ii) (3) + * + * + */ + + + +const uint32_t AFI_DEFAULT_PERIOD = (30 * 3600 * 24); /* 30 Days */ + +/** Constructor */ +AttachFileItem::AttachFileItem(std::string hash, std::string name, uint64_t size, + uint32_t flags, std::string srcId) +:QWidget(NULL), mFileHash(hash), mFileName(name), mFileSize(size), mSrcId(srcId) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + mMode = flags & AFI_MASK_STATE; + mType = flags & AFI_MASK_TYPE; + mPicFlag=0; + + if (mMode == AFI_STATE_EXTRA) + { + mMode = AFI_STATE_ERROR; + } + /**** Enable **** + *****/ + + /* all other states are possible */ + + if (!rsFiles) + { + mMode = AFI_STATE_ERROR; + } + + Setup(); +} + +/** Constructor */ +AttachFileItem::AttachFileItem(std::string path) +:QWidget(NULL), mPath(path), mFileSize(0) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + mMode = AFI_STATE_EXTRA; + mType = AFI_TYPE_ATTACH; + mPicFlag=0; + + /* ask for Files to hash/prepare it for us */ + if ((!rsFiles) || (!rsFiles->ExtraFileHash(path, AFI_DEFAULT_PERIOD, 0))) + { + mMode = AFI_STATE_ERROR; + } + + Setup(); +} + +void AttachFileItem::Setup() +{ + + connect( cancelButton, SIGNAL( clicked( void ) ), this, SLOT( cancel ( void ) ) ); + + /* once off check - if remote, check if we have it + * NB: This check might be expensive - and it'll happen often! + */ +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::Setup(): " << mFileName; + std::cerr << std::endl; +#endif + + if (mMode == AFI_STATE_REMOTE) + { + FileInfo fi; + uint32_t hintflags = RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL + | RS_FILE_HINTS_SPEC_ONLY; + + /* look up path */ + if (rsFiles->FileDetails(mFileHash, hintflags, fi)) + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::Setup() STATE=>Local Found File"; + std::cerr << std::endl; + std::cerr << "AttachFileItem::Setup() path: " << fi.path; + std::cerr << std::endl; +#endif + mMode = AFI_STATE_LOCAL; + mPath = fi.path; + } + } + + updateItemStatic(); + updateItem(); + + +} + + +bool AttachFileItem::done() +{ + return (mMode >= AFI_STATE_LOCAL); +} + +bool AttachFileItem::ready() +{ + return (mMode >= AFI_STATE_REMOTE); +} + +void AttachFileItem::updateItemStatic() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItemStatic(): " << mFileName; + std::cerr << std::endl; +#endif + + QString filename = QString::fromUtf8(mFileName.c_str()); + mDivisor = 1; + + if (mFileSize > 10000000) /* 10 Mb */ + { + progressBar->setRange(0, mFileSize / 1000000); + progressBar->setFormat("%v MB"); + mDivisor = 1000000; + } + else if (mFileSize > 10000) /* 10 Kb */ + { + progressBar->setRange(0, mFileSize / 1000); + progressBar->setFormat("%v kB"); + mDivisor = 1000; + } + else + { + progressBar->setRange(0, mFileSize); + progressBar->setFormat("%v B"); + mDivisor = 1; + } + + /* get full path for local file */ + if ((mMode == AFI_STATE_LOCAL) || (mMode == AFI_STATE_UPLOAD)) + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItemStatic() STATE=Local/Upload checking path"; + std::cerr << std::endl; +#endif + if (mPath == "") + { + FileInfo fi; + uint32_t hintflags = RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_LOCAL + | RS_FILE_HINTS_SPEC_ONLY; + + /* look up path */ + if (!rsFiles->FileDetails(mFileHash, hintflags, fi)) + { + mMode = AFI_STATE_ERROR; +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItemStatic() STATE=>Error No Details"; + std::cerr << std::endl; +#endif + } + else + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItemStatic() Updated Path"; + std::cerr << std::endl; +#endif + mPath = fi.path; + } + } + } + + /* do buttons + display */ + switch (mMode) + { + case AFI_STATE_ERROR: + progressBar->setRange(0, 100); + progressBar->setFormat("ERROR"); + + cancelButton->setEnabled(false); + + progressBar->setValue(0); + filename = "[ERROR] " + filename; + + break; + + case AFI_STATE_EXTRA: + filename = QString::fromUtf8(mPath.c_str()); + + progressBar->setRange(0, 100); + progressBar->setFormat("HASHING"); + + cancelButton->setEnabled(false); + + progressBar->setValue(0); + filename = "[EXTRA] " + filename; + + break; + + case AFI_STATE_REMOTE: + cancelButton->setEnabled(false); + + progressBar->setValue(0); + filename = "[REMOTE] " + filename; + + break; + + case AFI_STATE_DOWNLOAD: + cancelButton->setEnabled(true); + filename = "[DOWNLOAD] " + filename; + + break; + + case AFI_STATE_LOCAL: + cancelButton->setEnabled(false); + + progressBar->setValue(mFileSize / mDivisor); + filename = "[LOCAL] " + filename; + + break; + + case AFI_STATE_UPLOAD: + cancelButton->setEnabled(false); + filename = "[UPLOAD] " + filename; + + break; + } + + + switch(mType) + { + case AFI_TYPE_CHANNEL: + { + if (mMode == AFI_STATE_LOCAL) + { + } + else + { + } + } + break; + case AFI_TYPE_ATTACH: + { + cancelButton->setEnabled(true); + cancelButton->setToolTip("Remove Attachment"); + } + break; + default: + break; + } + + + fileLabel->setText(filename); + fileLabel->setToolTip(filename); + +} + +void AttachFileItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem():" << mFileName; + std::cerr << std::endl; +#endif + + /* Extract File Details */ + /* Update State if necessary */ + + FileInfo fi; + bool stateChanged = false; + int msec_rate = 1000; + + if ((mMode == AFI_STATE_ERROR) || (mMode == AFI_STATE_LOCAL)) + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() STATE=Local/Error ignore"; + std::cerr << std::endl; +#endif + /* ignore - dead file, or done */ + } + else if (mMode == AFI_STATE_EXTRA) + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() STATE=Extra File"; + std::cerr << std::endl; +#endif + /* check for file status */ + if (rsFiles->ExtraFileStatus(mPath, fi)) + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() STATE=>Local"; + std::cerr << std::endl; +#endif + mMode = AFI_STATE_LOCAL; + + /* fill in file details */ + mFileName = fi.fname; + mFileSize = fi.size; + mFileHash = fi.hash; + + /* have path already! */ + + stateChanged = true; + } + } + else + { + uint32_t hintflags = 0; + switch(mMode) + { + case AFI_STATE_REMOTE: + hintflags = RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY; + break; + case AFI_STATE_DOWNLOAD: + hintflags = RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY; + break; + case AFI_STATE_UPLOAD: + hintflags = RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_SPEC_ONLY; + break; + } + + bool detailsOk = rsFiles->FileDetails(mFileHash, hintflags, fi); + + /* have details - see if state has changed */ + switch(mMode) + { + case AFI_STATE_REMOTE: +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() STATE=Remote"; + std::cerr << std::endl; +#endif + /* is it downloading? */ + if (detailsOk) + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() STATE=>Download"; + std::cerr << std::endl; +#endif + /* downloading */ + mMode = AFI_STATE_DOWNLOAD; + stateChanged = true; + } + break; + case AFI_STATE_DOWNLOAD: +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() STATE=Download"; + std::cerr << std::endl; +#endif + + if (!detailsOk) + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() STATE=>Remote"; + std::cerr << std::endl; +#endif + mMode = AFI_STATE_REMOTE; + stateChanged = true; + } + else + { + /* has it completed? */ + if (fi.avail == mFileSize) + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() STATE=>Local"; + std::cerr << std::endl; +#endif + /* save path */ + /* update progress */ + mMode = AFI_STATE_LOCAL; + mPath = fi.path; + stateChanged = true; + } + progressBar->setValue(fi.avail / mDivisor); + } + break; + case AFI_STATE_UPLOAD: +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() STATE=Upload"; + std::cerr << std::endl; +#endif + + if (detailsOk) + { + progressBar->setValue(fi.avail / mDivisor); + } + + /* update progress */ + break; + } + + } + + /****** update based on new state ******/ + if (stateChanged) + { + updateItemStatic(); + } + + uint32_t repeat = 0; + + switch (mMode) + { + case AFI_STATE_ERROR: + repeat = 0; + break; + + case AFI_STATE_EXTRA: + repeat = 1; + msec_rate = 5000; /* slow */ + break; + + case AFI_STATE_REMOTE: + repeat = 1; + msec_rate = 30000; /* very slow */ + break; + + case AFI_STATE_DOWNLOAD: + repeat = 1; + msec_rate = 2000; /* should be download rate dependent */ + break; + + case AFI_STATE_LOCAL: + repeat = 0; + emit fileFinished(this); + hide(); // auto hide + break; + + case AFI_STATE_UPLOAD: + repeat = 1; + msec_rate = 2000; /* should be download rate dependent */ + break; + } + + + if (repeat) + { +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::updateItem() callback for update!"; + std::cerr << std::endl; +#endif + QTimer::singleShot( msec_rate, this, SLOT(updateItem( void ) )); + } + +} + + +void AttachFileItem::cancel() +{ +#ifdef DEBUG_ITEM + std::cerr << "AttachFileItem::cancel()"; + std::cerr << std::endl; +#endif + //set the state to error mode + mMode = AFI_STATE_ERROR; + + /* Only occurs - if it is downloading */ + if (mType == AFI_TYPE_ATTACH) + { + hide(); + } + else + { + rsFiles->FileCancel(mFileHash); + } +} + + +uint32_t AttachFileItem::getState() { + return mMode; +} diff --git a/retroshare-gui/src/gui/feeds/AttachFileItem.h b/retroshare-gui/src/gui/feeds/AttachFileItem.h new file mode 100644 index 000000000..929b846a5 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/AttachFileItem.h @@ -0,0 +1,102 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _ATTACH_FILE_ITEM_DIALOG_H +#define _ATTACH_FILE_ITEM_DIALOG_H + +#include "ui_AttachFileItem.h" +#include + +const uint32_t AFI_MASK_STATE = 0x000f; +const uint32_t AFI_MASK_TYPE = 0x00f0; +const uint32_t AFI_MASK_FT = 0x0f00; + +const uint32_t AFI_STATE_ERROR = 0x0001; +const uint32_t AFI_STATE_EXTRA = 0x0002; +const uint32_t AFI_STATE_REMOTE = 0x0003; +const uint32_t AFI_STATE_DOWNLOAD = 0x0004; +const uint32_t AFI_STATE_LOCAL = 0x0005; +const uint32_t AFI_STATE_UPLOAD = 0x0006; + +const uint32_t AFI_TYPE_CHANNEL = 0x0010; +const uint32_t AFI_TYPE_ATTACH = 0x0020; + +class AttachFileItem : public QWidget, private Ui::AttachFileItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + AttachFileItem(std::string localpath); + AttachFileItem(std::string hash, std::string name, uint64_t size, + uint32_t flags, std::string srcId); + + /** Default Destructor */ + + std::string FileHash() { return mFileHash; } + std::string FileName() { return mFileName; } + uint64_t FileSize() { return mFileSize; } + std::string FilePath() { return mPath; } + int getPicFlag() { return mPicFlag;} + void setPicFlag(int flag) { mPicFlag=flag;} + + void updateItemStatic(); + + bool done(); + bool ready(); + uint32_t getState(); + +public slots: + +private slots: + + void cancel(); + + void updateItem(); + +private: + + void Setup(); + + + std::string mPath; + std::string mFileHash; + std::string mFileName; + uint64_t mFileSize; + std::string mSrcId; + + uint32_t mPicFlag; + uint32_t mMode; + uint32_t mType; + uint64_t mDivisor; + + /* for display purposes */ + float amountDone; + +signals: + void fileFinished(AttachFileItem * AttachFileItem); + +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/AttachFileItem.ui b/retroshare-gui/src/gui/feeds/AttachFileItem.ui new file mode 100644 index 000000000..93d33ad61 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/AttachFileItem.ui @@ -0,0 +1,160 @@ + + + AttachFileItem + + + + 0 + 0 + 469 + 35 + + + + + 0 + 0 + + + + Form + + + QWidget#SubFileItem{border: none;} + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + QFrame#frame{border: 2px solid black; +background: white;} + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 2 + + + + + + 0 + 0 + + + + + 300 + 16777215 + + + + + 75 + true + true + + + + File Name + + + false + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + + + 24 + + + %p Kb + + + + + + + + 0 + 0 + + + + Cancel Download + + + + + + + :/images/delete.png:/images/delete.png + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/BlogMsgItem.cpp b/retroshare-gui/src/gui/feeds/BlogMsgItem.cpp new file mode 100644 index 000000000..736d90fc7 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/BlogMsgItem.cpp @@ -0,0 +1,181 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "BlogMsgItem.h" + +#include "FeedHolder.h" +#include "SubFileItem.h" + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +BlogMsgItem::BlogMsgItem(FeedHolder *parent, uint32_t feedId, std::string peerId, std::string msgId, bool isHome) +:QWidget(NULL), mParent(parent), mFeedId(feedId), + mPeerId(peerId), mMsgId(msgId), mIsHome(isHome) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + /* general ones */ + connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + //connect( gotoButton, SIGNAL( clicked( void ) ), this, SLOT( gotoHome ( void ) ) ); + + /* specific ones */ + connect( playButton, SIGNAL( clicked( void ) ), this, SLOT( playMedia ( void ) ) ); + + small(); + updateItemStatic(); + updateItem(); +} + + +void BlogMsgItem::updateItemStatic() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "BlogMsgItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + msgLabel->setText("What did you expect? \nThe Blogs will be up and running shortly!"); + titleLabel->setText("Blog Feed: Jacki @ Friday"); + subjectLabel->setText("Brand new exciting Blog stuff"); + + /* add Files */ + int total = (int) (10.0 * (rand() / (RAND_MAX + 1.0))); + int i; + + total = 0; + + for(i = 0; i < total; i++) + { + /* add file */ + SubFileItem *fi = new SubFileItem("dummyHash", "dummy_File", "", 1283918, SFI_STATE_REMOTE, mPeerId); + mFileItems.push_back(fi); + + QLayout *layout = expandFrame->layout(); + layout->addWidget(fi); + } + + playButton->setEnabled(false); + + if (mIsHome) + { + /* disable buttons */ + clearButton->setEnabled(false); + //gotoButton->setEnabled(false); + + clearButton->hide(); + } +} + + +void BlogMsgItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "BlogMsgItem::updateItem()"; + std::cerr << std::endl; +#endif + int msec_rate = 10000; + + /* Very slow Tick to check when all files are downloaded */ + std::list::iterator it; + for(it = mFileItems.begin(); it != mFileItems.end(); it++) + { + if (!(*it)->done()) + { + /* loop again */ + QTimer::singleShot( msec_rate, this, SLOT(updateItem( void ) )); + return; + } + } + if (mFileItems.size() > 0) + { + playButton->setEnabled(true); + } +} + + +void BlogMsgItem::small() +{ + expandFrame->hide(); +} + +void BlogMsgItem::toggle() +{ + if (expandFrame->isHidden()) + { + expandFrame->show(); + expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + expandButton->setToolTip("Hide"); + } + else + { + expandFrame->hide(); + expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + expandButton->setToolTip("Expand"); + } +} + + +void BlogMsgItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "BlogMsgItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + + +void BlogMsgItem::gotoHome() +{ +#ifdef DEBUG_ITEM + std::cerr << "BlogMsgItem::gotoHome()"; + std::cerr << std::endl; +#endif +} + +/*********** SPECIFIC FUNCTIOSN ***********************/ + + +void BlogMsgItem::playMedia() +{ +#ifdef DEBUG_ITEM + std::cerr << "BlogMsgItem::playMedia()"; + std::cerr << std::endl; +#endif +} + + + diff --git a/retroshare-gui/src/gui/feeds/BlogMsgItem.h b/retroshare-gui/src/gui/feeds/BlogMsgItem.h new file mode 100644 index 000000000..0165b4f03 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/BlogMsgItem.h @@ -0,0 +1,69 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _BLOG_MSG_ITEM_DIALOG_H +#define _BLOG_MSG_ITEM_DIALOG_H + +#include "ui_BlogMsgItem.h" +#include + +class FeedHolder; +class SubFileItem; + +class BlogMsgItem : public QWidget, private Ui::BlogMsgItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + BlogMsgItem(FeedHolder *parent, uint32_t feedId, std::string peerId, std::string msgId, bool isHome); + + /** Default Destructor */ + + void updateItemStatic(); + void small(); + +private slots: + /* default stuff */ + void gotoHome(); + void removeItem(); + void toggle(); + + void playMedia(); + + void updateItem(); + +private: + FeedHolder *mParent; + uint32_t mFeedId; + + std::string mPeerId; + std::string mMsgId; + + bool mIsHome; + + std::list mFileItems; +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/BlogMsgItem.ui b/retroshare-gui/src/gui/feeds/BlogMsgItem.ui new file mode 100644 index 000000000..bb6aeb83e --- /dev/null +++ b/retroshare-gui/src/gui/feeds/BlogMsgItem.ui @@ -0,0 +1,245 @@ + + + BlogMsgItem + + + + 0 + 0 + 552 + 238 + + + + Form + + + + + + + 6 + + + + + + 0 + 0 + + + + QFrame#frame{ +border: 2px solid #6ACEFF; +border-radius: 10px; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #0076B1, stop:1 #12A3EB);} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + 6 + + + + + + 0 + 0 + + + + Remove Item + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 16 + 26 + + + + + + + + + 0 + 0 + + + + + 75 + true + true + + + + Blog + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 1000 + 20 + + + + + + + + + 0 + 0 + + + + Expand + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + + + + Subject + + + + + + + + 0 + 0 + + + + subjectLabel + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 500 + 20 + + + + + + + + + 0 + 0 + + + + Play Media + + + + + + + :/images/startall.png:/images/startall.png + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + Long + message here + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/BlogNewItem.cpp b/retroshare-gui/src/gui/feeds/BlogNewItem.cpp new file mode 100644 index 000000000..a71e9d71a --- /dev/null +++ b/retroshare-gui/src/gui/feeds/BlogNewItem.cpp @@ -0,0 +1,211 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "BlogNewItem.h" +#include "FeedHolder.h" + +#include + +#define BLOG_DEFAULT_IMAGE ":/images/hi64-app-kblogger.png" + + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +BlogNewItem::BlogNewItem(FeedHolder *parent, uint32_t feedId, std::string blogId, bool isHome, bool isNew) +:QWidget(NULL), mParent(parent), mFeedId(feedId), + mBlogId(blogId), mIsHome(isHome), mIsNew(isNew) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + /* general ones */ + connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + + /* specific ones */ + connect( subscribeButton, SIGNAL( clicked( void ) ), this, SLOT( subscribeBlog ( void ) ) ); + + small(); + updateItemStatic(); + updateItem(); +} + + +void BlogNewItem::updateItemStatic() +{ + if (!rsBlogs) + return; + + + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "BlogNewItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + BlogInfo bi; + if (rsBlogs->getBlogInfo(mBlogId, bi)) + { + nameLabel->setText(QString::fromStdWString(bi.blogName)); + + descLabel->setText(QString::fromStdWString(bi.blogDesc)); + + if(bi.pngImageLen != 0){ + + QPixmap blogImage; + blogImage.loadFromData(bi.pngChanImage, bi.pngImageLen, "PNG"); + logo_label->setPixmap(QPixmap(blogImage)); + }else{ + QPixmap defaulImage(BLOG_DEFAULT_IMAGE); + logo_label->setPixmap(QPixmap(defaulImage)); + } + + if (bi.blogFlags & RS_DISTRIB_SUBSCRIBED) + { + subscribeButton->setEnabled(false); + //postButton->setEnabled(true); + } + else + { + subscribeButton->setEnabled(true); + //postButton->setEnabled(false); + } + + + /* should also check the other flags */ + } + else + { + nameLabel->setText("Unknown Blog"); + titleLabel->setText("Blog ???"); + descLabel->setText(""); + } + + if (mIsNew) + { + titleLabel->setText("New Blog"); + } + else + { + titleLabel->setText("Updated Blog"); + } + + if (mIsHome) + { + /* disable buttons */ + clearButton->setEnabled(false); + //gotoButton->setEnabled(false); + } +} + + +void BlogNewItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "BlogNewItem::updateItem()"; + std::cerr << std::endl; +#endif + +} + + +void BlogNewItem::small() +{ + expandFrame->hide(); +} + +void BlogNewItem::toggle() +{ + if (expandFrame->isHidden()) + { + expandFrame->show(); + expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + expandButton->setToolTip("Hide"); + } + else + { + expandFrame->hide(); + expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + expandButton->setToolTip("Expand"); + } +} + + +void BlogNewItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "BlogNewItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + + +void BlogNewItem::gotoHome() +{ +#ifdef DEBUG_ITEM + std::cerr << "BlogNewItem::gotoHome()"; + std::cerr << std::endl; +#endif +} + +/*********** SPECIFIC FUNCTIOSN ***********************/ + + +void BlogNewItem::unsubscribeBlog() +{ +#ifdef DEBUG_ITEM + std::cerr << "BlogNewItem::unsubscribeBlog()"; + std::cerr << std::endl; +#endif + if (rsBlogs) + { + rsBlogs->blogSubscribe(mBlogId, false); + } + updateItemStatic(); +} + + +void BlogNewItem::subscribeBlog() +{ +#ifdef DEBUG_ITEM + std::cerr << "BlogNewItem::subscribeBlog()"; + std::cerr << std::endl; +#endif + if (rsBlogs) + { + rsBlogs->blogSubscribe(mBlogId, true); + } + updateItemStatic(); +} + + + diff --git a/retroshare-gui/src/gui/feeds/BlogNewItem.h b/retroshare-gui/src/gui/feeds/BlogNewItem.h new file mode 100644 index 000000000..562533805 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/BlogNewItem.h @@ -0,0 +1,66 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _BLOG_NEW_ITEM_DIALOG_H +#define _BLOG_NEW_ITEM_DIALOG_H + +#include "ui_BlogNewItem.h" +#include + +class FeedHolder; + +class BlogNewItem : public QWidget, private Ui::BlogNewItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + BlogNewItem(FeedHolder *parent, uint32_t feedId, std::string blogId, bool isHome, bool isNew); + + /** Default Destructor */ + + void updateItemStatic(); + void small(); + +private slots: + /* default stuff */ + void gotoHome(); + void removeItem(); + void toggle(); + + void unsubscribeBlog(); + void subscribeBlog(); + + void updateItem(); + +private: + FeedHolder *mParent; + uint32_t mFeedId; + + std::string mBlogId; + bool mIsHome; + bool mIsNew; +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/BlogNewItem.ui b/retroshare-gui/src/gui/feeds/BlogNewItem.ui new file mode 100644 index 000000000..bcf3dd249 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/BlogNewItem.ui @@ -0,0 +1,276 @@ + + + BlogNewItem + + + + 0 + 0 + 643 + 158 + + + + + + + + 6 + + + + + + 0 + 0 + + + + QFrame#frame{ +border: 2px solid #6ACEFF; +border-radius: 10px; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #0076B1, stop:1 #12A3EB);} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + 6 + + + + + + + + 0 + 0 + + + + Remove Item + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + 0 + 0 + + + + + 75 + true + true + + + + New Blog + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + 32 + 32 + + + + Logo + + + true + + + + + + + name + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 500 + 20 + + + + + + + + + 0 + 0 + + + + Subscribe to Blog + + + + + + + :/images/directoryadd_24x24_shadow.png:/images/directoryadd_24x24_shadow.png + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + Expand + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + Blog Decscription + + + + + + + + + :/images/contacts24.png + + + + + + + + 0 + 0 + + + + Description + of Blog + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/ChanMsgItem.cpp b/retroshare-gui/src/gui/feeds/ChanMsgItem.cpp new file mode 100644 index 000000000..1c2c4393b --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ChanMsgItem.cpp @@ -0,0 +1,415 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "ChanMsgItem.h" + +#include "FeedHolder.h" +#include "SubFileItem.h" +#include "gui/notifyqt.h" +#include "util/misc.h" +#include "gui/RetroShareLink.h" + +#include + +#include + + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +ChanMsgItem::ChanMsgItem(FeedHolder *parent, uint32_t feedId, std::string chanId, std::string msgId, bool isHome) +:QWidget(NULL), mParent(parent), mFeedId(feedId), + mChanId(chanId), mMsgId(msgId), mIsHome(isHome) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + m_inUpdateItemStatic = false; + + /* general ones */ + connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + + /* specific */ + connect( unsubscribeButton, SIGNAL( clicked( void ) ), this, SLOT( unsubscribeChannel ( void ) ) ); + connect( downloadButton, SIGNAL( clicked( void ) ), this, SLOT( download ( void ) ) ); + connect( playButton, SIGNAL( clicked( void ) ), this, SLOT( play ( void ) ) ); + connect( copyLinkButton, SIGNAL( clicked( void ) ), this, SLOT( copyLink ( void ) ) ); + + connect( readButton, SIGNAL( toggled(bool) ), this, SLOT( readToggled(bool) ) ); + connect( NotifyQt::getInstance(), SIGNAL(channelMsgReadSatusChanged(QString,QString,int)), this, SLOT(channelMsgReadSatusChanged(QString,QString,int)), Qt::QueuedConnection); + + downloadButton->hide(); + playButton->hide(); + warn_image_label->hide(); + warning_label->hide(); + + titleLabel->setMinimumWidth(100); + subjectLabel->setMinimumWidth(100); + warning_label->setMinimumWidth(100); + + small(); + updateItemStatic(); + updateItem(); +} + +void ChanMsgItem::updateItemStatic() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ChanMsgItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + ChannelMsgInfo cmi; + + if (!rsChannels) + return; + + if (!rsChannels->getChannelMessage(mChanId, mMsgId, cmi)) + return; + + m_inUpdateItemStatic = true; + + QString title; + + ChannelInfo ci; + rsChannels->getChannelInfo(mChanId, ci); + + if (!mIsHome) + { + title = tr("Channel Feed") + ": "; + RetroShareLink link; + link.createChannel(ci.channelId, ""); + title += link.toHtml(); + titleLabel->setText(title); + RetroShareLink msgLink; + msgLink.createChannel(cmi.channelId, cmi.msgId); + subjectLabel->setText(msgLink.toHtml()); + + if ((ci.channelFlags & RS_DISTRIB_SUBSCRIBED) || (ci.channelFlags & RS_DISTRIB_ADMIN)) { + unsubscribeButton->setEnabled(true); + } else { + unsubscribeButton->setEnabled(false); + } + readButton->hide(); + newLabel->hide(); + copyLinkButton->hide(); + } + else + { + /* subject */ + titleLabel->setText(QString::fromStdWString(cmi.subject)); + subjectLabel->setText(QString::fromStdWString(cmi.msg)); + + /* disable buttons: deletion facility not enabled with cache services yet */ + clearButton->setEnabled(false); + unsubscribeButton->setEnabled(false); + clearButton->hide(); + unsubscribeButton->hide(); + copyLinkButton->show(); + + if ((ci.channelFlags & RS_DISTRIB_SUBSCRIBED) || (ci.channelFlags & RS_DISTRIB_ADMIN)) { + readButton->setVisible(true); + + uint32_t status = 0; + rsChannels->getMessageStatus(mChanId, mMsgId, status); + + if ((status & CHANNEL_MSG_STATUS_READ) == 0 || (status & CHANNEL_MSG_STATUS_UNREAD_BY_USER)) { + readButton->setChecked(true); + readButton->setIcon(QIcon(":/images/message-state-unread.png")); + } else { + readButton->setChecked(false); + readButton->setIcon(QIcon(":/images/message-state-read.png")); + } + + if (status & CHANNEL_MSG_STATUS_READ) { + newLabel->setVisible(false); + frame->setStyleSheet("QFrame#frame {border: 3px solid #D3D3D3;background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFFF, stop:1 #F2F2F2);border-radius: 10px;}"); + + } else { + newLabel->setVisible(true); + frame->setStyleSheet("QFrame#frame {border: 3px solid #82B9F4;background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F0F8FD, stop:0.8 #E6F2FD, stop: 0.81 #E6F2FD, stop: 1 #D2E7FD);border-radius: 10px;}"); + } + } else { + readButton->setVisible(false); + newLabel->setVisible(false); + } + } + + msgLabel->setText(QString::fromStdWString(cmi.msg)); + + QDateTime qtime; + qtime.setTime_t(cmi.ts); + QString timestamp = qtime.toString("dd.MMMM yyyy hh:mm"); + datetimelabel->setText(timestamp); + + { + std::ostringstream out; + out << "(" << cmi.count << " Files)"; + filelabel->setText(QString::fromStdString(out.str()) + " " + misc::friendlyUnit(cmi.size)); + } + + + if (mFileItems.empty() == false) { + std::list::iterator it; + for(it = mFileItems.begin(); it != mFileItems.end(); it++) + { + delete(*it); + } + mFileItems.clear(); + } + + std::list::iterator it; + for(it = cmi.files.begin(); it != cmi.files.end(); it++) + { + /* add file */ + SubFileItem *fi = new SubFileItem(it->hash, it->fname, it->path, it->size, + SFI_STATE_REMOTE | SFI_TYPE_CHANNEL, ""); + mFileItems.push_back(fi); + + QLayout *layout = expandFrame->layout(); + layout->addWidget(fi); + } + + if(cmi.thumbnail.image_thumbnail != NULL) + { + QPixmap thumbnail; + thumbnail.loadFromData(cmi.thumbnail.image_thumbnail, cmi.thumbnail.im_thumbnail_size, + "PNG"); + + label->setPixmap(thumbnail); + label->setStyleSheet("QLabel#label{border: 2px solid #D3D3D3;border-radius: 3px;}"); + } + + m_inUpdateItemStatic = false; +} + +void ChanMsgItem::setFileCleanUpWarning(uint32_t time_left) +{ + int hours = (int)time_left/3600; + int minutes = (time_left - hours*3600)%60; + + warning_label->setText(tr("Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it.").arg( + QString::number(hours)).arg(QString::number(minutes))); + + QFont warnFont = warning_label->font(); + warnFont.setBold(true); + warning_label->setFont(warnFont); + + warn_image_label->setVisible(true); + warning_label->setVisible(true); + return; + +} + +void ChanMsgItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ChanMsgItem::updateItem()"; + std::cerr << std::endl; +#endif + int msec_rate = 10000; + + int downloadCount = 0; + int downloadStartable = 0; + int playCount = 0; + int playStartable = 0; + bool startable; + bool loopAgain = false; + + /* Very slow Tick to check when all files are downloaded */ + std::list::iterator it; + for(it = mFileItems.begin(); it != mFileItems.end(); it++) + { + SubFileItem *item = *it; + + if (item->isDownloadable(startable)) { + downloadCount++; + if (startable) { + downloadStartable++; + } + } + if (item->isPlayable(startable)) { + playCount++; + if (startable) { + playStartable++; + } + } + + if (!item->done()) + { + /* loop again */ + loopAgain = true; + } + } + + if (downloadCount) { + downloadButton->show(); + + if (downloadStartable) { + downloadButton->setEnabled(true); + } else { + downloadButton->setEnabled(false); + } + } else { + downloadButton->hide(); + } + if (playCount) { + /* one file is playable */ + playButton->show(); + + if (playStartable == 1) { + playButton->setEnabled(true); + } else { + playButton->setEnabled(false); + } + } else { + playButton->hide(); + } + + if (loopAgain) { + QTimer::singleShot( msec_rate, this, SLOT(updateItem( void ) )); + } +} + +void ChanMsgItem::small() +{ + expandFrame->hide(); +} + +void ChanMsgItem::toggle() +{ + if (expandFrame->isHidden()) + { + expandFrame->show(); + expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + expandButton->setToolTip(tr("Hide")); + } + else + { + expandFrame->hide(); + expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + expandButton->setToolTip(tr("Expand")); + } +} + +void ChanMsgItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChanMsgItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + +/*********** SPECIFIC FUNCTIONS ***********************/ + +void ChanMsgItem::unsubscribeChannel() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChanMsgItem::unsubscribeChannel()"; + std::cerr << std::endl; +#endif + + if (rsChannels) + { + rsChannels->channelSubscribe(mChanId, false, false); + } + updateItemStatic(); +} + +void ChanMsgItem::download() +{ + std::list::iterator it; + for(it = mFileItems.begin(); it != mFileItems.end(); it++) + { + (*it)->download(); + } + + updateItem(); +} + +void ChanMsgItem::play() +{ + std::list::iterator it; + for(it = mFileItems.begin(); it != mFileItems.end(); it++) + { + bool startable; + if ((*it)->isPlayable(startable) && startable) { + (*it)->play(); + } + } +} + +void ChanMsgItem::readToggled(bool checked) +{ + if (m_inUpdateItemStatic) { + return; + } + + /* set always as read ... */ + uint32_t statusNew = CHANNEL_MSG_STATUS_READ; + if (checked) { + /* ... and as unread by user */ + statusNew |= CHANNEL_MSG_STATUS_UNREAD_BY_USER; + } else { + /* ... and as read by user */ + statusNew &= ~CHANNEL_MSG_STATUS_UNREAD_BY_USER; + } + rsChannels->setMessageStatus(mChanId, mMsgId, statusNew, CHANNEL_MSG_STATUS_READ | CHANNEL_MSG_STATUS_UNREAD_BY_USER); +} + +void ChanMsgItem::channelMsgReadSatusChanged(const QString& channelId, const QString& msgId, int status) +{ + if (channelId.toStdString() == mChanId && msgId.toStdString() == mMsgId) { + updateItemStatic(); + } +} + +void ChanMsgItem::copyLink() +{ + if (mChanId.empty() || mMsgId.empty()) { + return; + } + + ChannelMsgInfo cmi; + if (rsChannels->getChannelMessage(mChanId, mMsgId, cmi)) { + RetroShareLink link; + if (link.createChannel(cmi.channelId, cmi.msgId)) { + std::vector urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } + } +} diff --git a/retroshare-gui/src/gui/feeds/ChanMsgItem.h b/retroshare-gui/src/gui/feeds/ChanMsgItem.h new file mode 100644 index 000000000..67ade9512 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ChanMsgItem.h @@ -0,0 +1,74 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CHAN_MSG_ITEM_DIALOG_H +#define _CHAN_MSG_ITEM_DIALOG_H + +#include "ui_ChanMsgItem.h" +#include + +class FeedHolder; +class SubFileItem; + +class ChanMsgItem : public QWidget, private Ui::ChanMsgItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + ChanMsgItem(FeedHolder *parent, uint32_t feedId, std::string chanId, std::string msgId, bool isHome); + + void updateItemStatic(); + void small(); + void setFileCleanUpWarning(uint32_t time_left); + + const std::string &msgId() { return mMsgId; } + +private slots: + /* default stuff */ + void removeItem(); + void toggle(); + + void unsubscribeChannel(); + void download(); + void play(); + void copyLink(); + + void readToggled(bool checked); + void channelMsgReadSatusChanged(const QString& channelId, const QString& msgId, int status); + + void updateItem(); + +private: + FeedHolder *mParent; + uint32_t mFeedId; + + std::string mChanId; + std::string mMsgId; + + bool mIsHome; + bool m_inUpdateItemStatic; + + std::list mFileItems; +}; + +#endif + diff --git a/retroshare-gui/src/gui/feeds/ChanMsgItem.ui b/retroshare-gui/src/gui/feeds/ChanMsgItem.ui new file mode 100644 index 000000000..956b6d172 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ChanMsgItem.ui @@ -0,0 +1,509 @@ + + + ChanMsgItem + + + + 0 + 0 + 546 + 208 + + + + + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + + 6 + + + 1 + + + 6 + + + 1 + + + 6 + + + 1 + + + + + + 0 + 0 + + + + + 16777215 + 140 + + + + QFrame#frame{border: 3px solid #D3D3D3; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FFFFFF, stop:1 #F2F2F2);; +border-radius: 10px;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 156 + 107 + + + + + + + :/images/thumb-default-video.png + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 138 + 1 + + + + + + + + + + 4 + + + + + + 0 + 0 + + + + + 11 + 75 + true + true + PreferAntialias + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:normal; color:#656565;">Channel Subject</span></p></body></html> + + + false + + + true + + + + + + + + 75 + true + PreferAntialias + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + + + + PreferAntialias + + + + fileLabel + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + + + + 0 + 0 + + + + + 16777215 + 60 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Short Description</span></p></body></html> + + + true + + + true + + + + + + + + 24 + 16777215 + + + + Toggle Message Read Status + + + + :/images/message-state-unread.png:/images/message-state-unread.png + + + true + + + false + + + false + + + + + + + + 16777215 + 21 + + + + + PreferAntialias + + + + QLabel{border: 1px solid #167BE7; +background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, +stop: 0 #2291E0, stop: 1 #3EB3FF); +border-radius: 3px} + + + New + + + + + + + + -1 + + + + Download + + + + :/images/download16.png:/images/download16.png + + + + + + + + -1 + + + + Play + + + + :/images/player_play.png:/images/player_play.png + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 13 + 21 + + + + + + + + + + + :/images/status_unknown.png + + + + + + + TextLabel + + + + + + + + 0 + 0 + + + + + 24 + 16777215 + + + + Unsubscribe From Channel + + + + + + + :/images/mail_delete.png:/images/mail_delete.png + + + + + + + + 0 + 0 + + + + + 24 + 16777215 + + + + Remove Item + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + 0 + 0 + + + + + 24 + 16777215 + + + + Expand + + + + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + 0 + 0 + + + + + 24 + 16777215 + + + + Copy RetroShare Link + + + + + + + :/images/copyrslink.png:/images/copyrslink.png + + + + + + + + + + + + QFrame#expandFrame{border: 2px solid #D3D3D3; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FFFFFF, stop:1 #F2F2F2);; +border-radius: 10px;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + PreferAntialias + + + + QLabel#msgLabel{border: 2px solid #238; +border-radius: 10px;} + + + + + + true + + + + + + + + + + Qt::Vertical + + + + 20 + 5 + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/ChanNewItem.cpp b/retroshare-gui/src/gui/feeds/ChanNewItem.cpp new file mode 100644 index 000000000..ecedefe66 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ChanNewItem.cpp @@ -0,0 +1,204 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "ChanNewItem.h" +#include "FeedHolder.h" +#include "gui/RetroShareLink.h" + +#include + +#define CHAN_DEFAULT_IMAGE ":/images/channels.png" + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +ChanNewItem::ChanNewItem(FeedHolder *parent, uint32_t feedId, std::string chanId, bool isHome, bool isNew) +:QWidget(NULL), mParent(parent), mFeedId(feedId), + mChanId(chanId), mIsHome(isHome), mIsNew(isNew) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + /* general ones */ + connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + + /* specific ones */ + connect( subscribeButton, SIGNAL( clicked( void ) ), this, SLOT( subscribeChannel ( void ) ) ); + + small(); + updateItemStatic(); + updateItem(); +} + + +void ChanNewItem::updateItemStatic() +{ + if (!rsChannels) + return; + + + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ChanNewItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + ChannelInfo ci; + if (rsChannels->getChannelInfo(mChanId, ci)) + { + RetroShareLink link; + link.createChannel(ci.channelId, ""); + nameLabel->setText(link.toHtml()); + + descLabel->setText(QString::fromStdWString(ci.channelDesc)); + + if(ci.pngImageLen != 0){ + + QPixmap chanImage; + chanImage.loadFromData(ci.pngChanImage, ci.pngImageLen, "PNG"); + logo_label->setPixmap(QPixmap(chanImage)); + }else{ + QPixmap defaulImage(CHAN_DEFAULT_IMAGE); + logo_label->setPixmap(QPixmap(defaulImage)); + } + + if (ci.channelFlags & RS_DISTRIB_SUBSCRIBED) + { + subscribeButton->setEnabled(false); + //postButton->setEnabled(true); + } + else + { + subscribeButton->setEnabled(true); + //postButton->setEnabled(false); + } + + + /* should also check the other flags */ + } + else + { + nameLabel->setText(tr("Unknown Channel")); + titleLabel->setText("Channel ???"); + descLabel->setText(""); + } + + if (mIsNew) + { + titleLabel->setText(tr("New Channel")); + } + else + { + titleLabel->setText(tr("Updated Channel")); + } + + if (mIsHome) + { + /* disable buttons */ + clearButton->setEnabled(false); + } +} + + +void ChanNewItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ChanNewItem::updateItem()"; + std::cerr << std::endl; +#endif + +} + + +void ChanNewItem::small() +{ + expandFrame->hide(); +} + +void ChanNewItem::toggle() +{ + if (expandFrame->isHidden()) + { + expandFrame->show(); + expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + expandButton->setToolTip("Hide"); + } + else + { + expandFrame->hide(); + expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + expandButton->setToolTip("Expand"); + } +} + + +void ChanNewItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChanNewItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + + +/*********** SPECIFIC FUNCTIOSN ***********************/ + + +void ChanNewItem::unsubscribeChannel() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChanNewItem::unsubscribeChannel()"; + std::cerr << std::endl; +#endif + if (rsChannels) + { + rsChannels->channelSubscribe(mChanId, false, false); + } + updateItemStatic(); +} + + +void ChanNewItem::subscribeChannel() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChanNewItem::subscribeChannel()"; + std::cerr << std::endl; +#endif + if (rsChannels) + { + rsChannels->channelSubscribe(mChanId, true, true); + } + updateItemStatic(); +} + + + diff --git a/retroshare-gui/src/gui/feeds/ChanNewItem.h b/retroshare-gui/src/gui/feeds/ChanNewItem.h new file mode 100644 index 000000000..d373674fb --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ChanNewItem.h @@ -0,0 +1,65 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CHANNEL_NEW_ITEM_DIALOG_H +#define _CHANNEL_NEW_ITEM_DIALOG_H + +#include "ui_ChanNewItem.h" +#include + +class FeedHolder; + +class ChanNewItem : public QWidget, private Ui::ChanNewItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + ChanNewItem(FeedHolder *parent, uint32_t feedId, std::string chanId, bool isHome, bool isNew); + + /** Default Destructor */ + + void updateItemStatic(); + void small(); + +private slots: + /* default stuff */ + void removeItem(); + void toggle(); + + void unsubscribeChannel(); + void subscribeChannel(); + + void updateItem(); + +private: + FeedHolder *mParent; + uint32_t mFeedId; + + std::string mChanId; + bool mIsHome; + bool mIsNew; +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/ChanNewItem.ui b/retroshare-gui/src/gui/feeds/ChanNewItem.ui new file mode 100644 index 000000000..a8a11978b --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ChanNewItem.ui @@ -0,0 +1,274 @@ + + + ChanNewItem + + + + 0 + 0 + 643 + 173 + + + + + + + + 6 + + + + + + 0 + 0 + + + + QFrame#frame{border: 2px solid #D3D3D3; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FFFFFF, stop:1 #F2F2F2);; +border-radius: 10px;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 64 + 64 + + + + + 64 + 64 + + + + QLabel{border: 2px solid #D3D3D3; + +border-radius: 2px;} + + + Logo + + + true + + + + + + + name + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + 0 + 0 + + + + + 75 + true + true + + + + New Channel + + + false + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 338 + 28 + + + + + + + + + 0 + 0 + + + + Subscribe to Channel + + + + + + + :/images/directoryadd_24x24_shadow.png:/images/directoryadd_24x24_shadow.png + + + + + + + + 0 + 0 + + + + Expand + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + 0 + 0 + + + + Remove Item + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + + Qt::Horizontal + + + + 455 + 20 + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + Channel Decscription + + + + + + + + + :/images/contacts24.png + + + + + + + + 0 + 0 + + + + Description + of Channel + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp b/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp new file mode 100644 index 000000000..c5f428f77 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ChatMsgItem.cpp @@ -0,0 +1,295 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "ChatMsgItem.h" +#include "FeedHolder.h" +#include "../RsAutoUpdatePage.h" +#include "gui/msgs/MessageComposer.h" +#include "gui/chat/HandleRichText.h" +#include "gui/settings/rsharesettings.h" + +#include "gui/notifyqt.h" + +#include +#include + +#include + +/***** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +ChatMsgItem::ChatMsgItem(FeedHolder *parent, uint32_t feedId, std::string peerId, std::string message, bool isHome) +:QWidget(NULL), mParent(parent), mFeedId(feedId), + mPeerId(peerId), mIsHome(isHome) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + messageframe->setVisible(false); + sendButton->hide(); + cancelButton->hide(); + sendButton->setEnabled(false); + + /* general ones */ + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + + /* specific ones */ + connect( chatButton, SIGNAL( clicked( void ) ), this, SLOT( openChat ( void ) ) ); + connect( msgButton, SIGNAL( clicked( void ) ), this, SLOT( sendMsg ( void ) ) ); + connect( quickmsgButton, SIGNAL( clicked( ) ), this, SLOT( togglequickmessage() ) ); + connect( cancelButton, SIGNAL( clicked( ) ), this, SLOT( togglequickmessage() ) ); + connect( sendButton, SIGNAL( clicked( ) ), this, SLOT( sendMessage() ) ); + + connect(NotifyQt::getInstance(), SIGNAL(peerHasNewAvatar(const QString&)), this, SLOT(updateAvatar(const QString&))); + + updateItemStatic(); + updateItem(); + updateAvatar(QString::fromStdString(mPeerId)); + insertChat(message); +} + +void ChatMsgItem::updateItemStatic() +{ + if (!rsPeers) + return; + + RsPeerDetails details; + if (rsPeers->getPeerDetails(mPeerId, details)) + { + + /* set textcolor for peername */ + QString nameStr("%1"); + + /* set Peer name */ + QString peername = QString::fromStdString(details.name); + peernameLabel->setText(nameStr.arg(peername)); + } + else + { + chatButton->setEnabled(false); + msgButton->setEnabled(false); + } + + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ChatMsgItem::updateItemStatic()"; + std::cerr << std::endl; +#endif +} + +void ChatMsgItem::updateItem() +{ + if (!rsPeers) + return; + + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ChatMsgItem::updateItem()"; + std::cerr << std::endl; +#endif + + if(!RsAutoUpdatePage::eventsLocked()) { + RsPeerDetails details; + if (!rsPeers->getPeerDetails(mPeerId, details)) + { + return; + } + + /* do buttons */ + chatButton->setEnabled(details.state & RS_PEER_STATE_CONNECTED); + if (details.state & RS_PEER_STATE_FRIEND) + { + msgButton->setEnabled(true); + } + else + { + msgButton->setEnabled(false); + } + } + + /* slow Tick */ + int msec_rate = 10129; + + QTimer::singleShot( msec_rate, this, SLOT(updateItem( void ) )); + return; +} + +void ChatMsgItem::insertChat(std::string &message) +{ +#ifdef DEBUG_ITEM + std::cerr << "ChatMsgItem::insertChat(): " << msg << std::endl; +#endif + + QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss"); + timestampLabel->setText(timestamp); + + QString formatMsg = QString::fromStdString(message); + + unsigned int formatFlag = RSHTML_FORMATTEXT_EMBED_LINKS; + + // embed smileys ? + if (Settings->valueFromGroup(QString("Chat"), QString::fromUtf8("Emoteicons_GroupChat"), true).toBool()) { + formatFlag |= RSHTML_FORMATTEXT_EMBED_SMILEYS; + } + + formatMsg = RsHtml::formatText(formatMsg, formatFlag); + + chatTextlabel->setText(formatMsg); +} + +void ChatMsgItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChatMsgItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + +void ChatMsgItem::gotoHome() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChatMsgItem::gotoHome()"; + std::cerr << std::endl; +#endif +} + +/*********** SPECIFIC FUNCTIOSN ***********************/ + + +void ChatMsgItem::sendMsg() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChatMsgItem::sendMsg()"; + std::cerr << std::endl; +#endif + + if (mParent) + { + + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + nMsgDialog->addRecipient(MessageComposer::TO, mPeerId, false); + nMsgDialog->show(); + nMsgDialog->activateWindow(); + + /* window will destroy itself! */ + } +} + + +void ChatMsgItem::openChat() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChatMsgItem::openChat()"; + std::cerr << std::endl; +#endif + if (mParent) + { + mParent->openChat(mPeerId); + } +} + +void ChatMsgItem::updateAvatar(const QString &peer_id) +{ + if (peer_id.toStdString() != mPeerId) { + /* it 's not me */ + return; + } + + unsigned char *data = NULL; + int size = 0 ; + + rsMsgs->getAvatarData(mPeerId,data,size); + + if(size != 0) + { + // set the image + QPixmap pix ; + pix.loadFromData(data,size,"PNG") ; + avatar_label->setPixmap(pix); + delete[] data ; + + } + else + { + avatar_label->setPixmap(QPixmap(":/images/user/personal64.png")); + } +} + +void ChatMsgItem::togglequickmessage() +{ + if (messageframe->isHidden()) + { + messageframe->setVisible(true); + sendButton->show(); + cancelButton->show(); + } + else + { + messageframe->setVisible(false); + sendButton->hide(); + cancelButton->hide(); + } + +} + +void ChatMsgItem::sendMessage() +{ + /* construct a message */ + MessageInfo mi; + + mi.title = tr("Quick Message").toStdWString(); + mi.msg = quickmsgText->toHtml().toStdWString(); + mi.msgto.push_back(mPeerId); + + rsMsgs->MessageSend(mi); + + quickmsgText->clear(); + messageframe->setVisible(false); + sendButton->hide(); + cancelButton->hide(); +} + +void ChatMsgItem::on_quickmsgText_textChanged() +{ + if (quickmsgText->toPlainText().isEmpty()) + { + sendButton->setEnabled(false); + } + else + { + sendButton->setEnabled(true); + } +} diff --git a/retroshare-gui/src/gui/feeds/ChatMsgItem.h b/retroshare-gui/src/gui/feeds/ChatMsgItem.h new file mode 100644 index 000000000..afbfbeff2 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ChatMsgItem.h @@ -0,0 +1,72 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CHATMSG_ITEM_DIALOG_H +#define _CHATMSG_ITEM_DIALOG_H + +#include "ui_ChatMsgItem.h" +#include + + +class FeedHolder; + + +class ChatMsgItem : public QWidget, private Ui::ChatMsgItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + ChatMsgItem(FeedHolder *parent, uint32_t feedId, std::string peerId, std::string message, bool isHome); + + /** Default Destructor */ + + void updateItemStatic(); + +private slots: + /* default stuff */ + void gotoHome(); + void removeItem(); + + void sendMsg(); + void openChat(); + + void updateItem(); + void updateAvatar(const QString &peer_id); + + void togglequickmessage(); + void sendMessage(); + + void on_quickmsgText_textChanged(); + +private: + void insertChat(std::string &message); + + FeedHolder *mParent; + uint32_t mFeedId; + + std::string mPeerId; + + bool mIsHome; +}; + +#endif + diff --git a/retroshare-gui/src/gui/feeds/ChatMsgItem.ui b/retroshare-gui/src/gui/feeds/ChatMsgItem.ui new file mode 100644 index 000000000..97ac35efb --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ChatMsgItem.ui @@ -0,0 +1,338 @@ + + + ChatMsgItem + + + + 0 + 0 + 543 + 213 + + + + + + + + 6 + + + + + + 0 + 0 + + + + QFrame#frame{border: 2px solid black; + background-color: #FEF6DE; +border-radius: 10px} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + QLabel#avatar_label{border: 2px solid black; + +} + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 0 + + + + + + + Qt::Vertical + + + + 20 + 1 + + + + + + + + + + + + + Peer Name + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Qt::Horizontal + + + + 267 + 21 + + + + + + + + + 0 + 0 + + + + + 10 + 75 + true + + + + TextLabel + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Remove Item + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Text Label + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + + 16777215 + 115 + + + + + + + + + + + Write a quick Message + + + + :/images/message-mail.png:/images/message-mail.png + + + false + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + 0 + 0 + + + + Send Mail + + + Write Message + + + + :/images/mail_send.png:/images/mail_send.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + 0 + 0 + + + + Start Chat + + + Qt::LeftToRight + + + Start Chat + + + + :/images/chat.png:/images/chat.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Qt::Horizontal + + + + 347 + 17 + + + + + + + + Send + + + true + + + + + + + Cancel + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/FeedHolder.h b/retroshare-gui/src/gui/feeds/FeedHolder.h new file mode 100644 index 000000000..67b658749 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/FeedHolder.h @@ -0,0 +1,42 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _FEED_HOLDER_H +#define _FEED_HOLDER_H + +#include +#include + +const uint32_t FEEDHOLDER_MSG_MESSAGE = 0x0001; +const uint32_t FEEDHOLDER_MSG_FORUM = 0x0002; +const uint32_t FEEDHOLDER_MSG_CHANNEL = 0x0003; +const uint32_t FEEDHOLDER_MSG_BLOG = 0x0004; + +class FeedHolder +{ + public: + +virtual void deleteFeedItem(QWidget *item, uint32_t type) = 0; +virtual void openChat(std::string peerId) = 0; +}; + +#endif + diff --git a/retroshare-gui/src/gui/feeds/ForumMsgItem.cpp b/retroshare-gui/src/gui/feeds/ForumMsgItem.cpp new file mode 100644 index 000000000..bf0d2b6a5 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ForumMsgItem.cpp @@ -0,0 +1,474 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "ForumMsgItem.h" +#include "FeedHolder.h" +#include "gui/RetroShareLink.h" + +#include +#include +#include + +#include "gui/notifyqt.h" + +#include "gui/forums/CreateForumMsg.h" +#include "gui/chat/HandleRichText.h" + +#include + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +ForumMsgItem::ForumMsgItem(FeedHolder *parent, uint32_t feedId, const std::string &forumId, const std::string &postId, bool isHome) +:QWidget(NULL), mParent(parent), mFeedId(feedId), mForumId(forumId), mPostId(postId), mIsHome(isHome), mIsTop(false) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + /* general ones */ + connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + + /* specific ones */ + connect( unsubscribeButton, SIGNAL( clicked( void ) ), this, SLOT( unsubscribeForum ( void ) ) ); + connect( replyButton, SIGNAL( clicked( void ) ), this, SLOT( replyToPost ( void ) ) ); + connect( sendButton, SIGNAL( clicked( ) ), this, SLOT( sendMsg() ) ); + + connect(NotifyQt::getInstance(), SIGNAL(peerHasNewAvatar(const QString&)), this, SLOT(updateAvatar(const QString&))); + + subjectLabel->setMinimumWidth(20); + + small(); + updateItemStatic(); + updateItem(); + textEdit->hide(); + sendButton->hide(); + signedcheckBox->hide(); +} + + +void ForumMsgItem::updateItemStatic() +{ + if (!rsForums) + return; + + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ForumMsgItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + canReply = false; + + ForumInfo fi; + if (rsForums->getForumInfo(mForumId, fi)) + { + RetroShareLink link; + link.createForum(fi.forumId, ""); + QString title = tr("Forum Post") + ": "; + title += link.toHtml(); + + titleLabel->setText(title); + if (fi.subscribeFlags & (RS_DISTRIB_ADMIN | RS_DISTRIB_SUBSCRIBED)) + { + unsubscribeButton->setEnabled(true); + replyButton->setEnabled(true); + + if (fi.forumFlags & RS_DISTRIB_AUTHEN_REQ) + { + signedcheckBox->setChecked(true); + signedcheckBox->setEnabled(false); + } + + canReply = true; + } + else + { + unsubscribeButton->setEnabled(false); + replyButton->setEnabled(false); + } + } + else + { + titleLabel->setText(tr("Unknown Forum Post")); + } + + /* get actual Message */ + ForumMsgInfo msg; + if (rsForums->getForumMessage(mForumId, mPostId, msg)) + { +#ifdef DEBUG_ITEM + std::cerr << "Ids: MsgId: " << msg.msgId; + std::cerr << std::endl; + std::cerr << "Ids: ParentId: " << msg.parentId; + std::cerr << std::endl; + std::cerr << "Ids: ThreadId: " << msg.threadId; + std::cerr << std::endl; +#endif + + /* decide if top or not */ + if ((msg.msgId == msg.threadId) || (msg.threadId == "")) + { + mIsTop = true; + } + + RetroShareLink link; + link.createForum(msg.forumId, msg.msgId); + + if (mIsTop) + { + mGpgIdPrev = msg.srcId; + + if (rsPeers->getPeerName(msg.srcId) !="") + { + RetroShareLink linkMessage; + linkMessage.createMessage(msg.srcId, ""); + namelabel->setText(linkMessage.toHtml()); + } + else + { + namelabel->setText(tr("Anonymous")); + } + + prevSubLabel->setText(link.toHtml()); + prevMsgLabel->setText(RsHtml::formatText(QString::fromStdWString(msg.msg), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); + + QDateTime qtime; + qtime.setTime_t(msg.ts); + QString timestamp = qtime.toString("dd.MMMM yyyy hh:mm"); + timestamplabel->setText(timestamp); + + nextFrame->hide(); + } + else + { + mGpgIdNext = msg.srcId; + + if (rsPeers->getPeerName(msg.srcId) !="") + { + RetroShareLink linkMessage; + linkMessage.createMessage(msg.srcId, ""); + nextnamelabel->setText(linkMessage.toHtml()); + } + else + { + nextnamelabel->setText(tr("Anonymous")); + } + + nextSubLabel->setText(link.toHtml()); + nextMsgLabel->setText(RsHtml::formatText(QString::fromStdWString(msg.msg), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); + + QDateTime qtime; + qtime.setTime_t(msg.ts); + QString timestamp = qtime.toString("dd.MMMM yyyy hh:mm"); + timestamplabel->setText(timestamp); + + prevSHLabel->setText(tr("In Reply to") + ": "); + + ForumMsgInfo msgParent; + if (rsForums->getForumMessage(mForumId, msg.parentId, msgParent)) + { + mGpgIdPrev = msgParent.srcId; + + RetroShareLink linkParent; + linkParent.createForum(msgParent.forumId, msgParent.msgId); + prevSubLabel->setText(linkParent.toHtml()); + prevMsgLabel->setText(RsHtml::formatText(QString::fromStdWString(msgParent.msg), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); + + if (rsPeers->getPeerName(msgParent.srcId) !="") + { + RetroShareLink linkMessage; + linkMessage.createMessage(msgParent.srcId, ""); + namelabel->setText(linkMessage.toHtml()); + } + else + { + namelabel->setText(tr("Anonymous")); + } + } + else + { + prevSubLabel->setText("???"); + prevMsgLabel->setText("???"); + } + } + + /* header stuff */ + subjectLabel->setText(QString::fromStdWString(msg.title)); + //srcLabel->setText(QString::fromStdString(msg.srcId)); + } + + if (mIsHome) + { + /* disable buttons */ + clearButton->setEnabled(false); + //gotoButton->setEnabled(false); + + clearButton->hide(); + } + + unsubscribeButton->hide(); + + showAvatar("", true); + showAvatar("", false); +} + + +void ForumMsgItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ForumMsgItem::updateItem()"; + std::cerr << std::endl; +#endif + +} + + +void ForumMsgItem::small() +{ + nextFrame->hide(); + prevFrame->hide(); +} + +void ForumMsgItem::toggle() +{ + if (prevFrame->isHidden()) + { + prevFrame->show(); + textEdit->setVisible(canReply); + sendButton->setVisible(canReply); + signedcheckBox->setVisible(canReply); + expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + expandButton->setToolTip("Hide"); + if (!mIsTop) + { + nextFrame->show(); + } + } + else + { + prevFrame->hide(); + nextFrame->hide(); + textEdit->hide(); + sendButton->hide(); + signedcheckBox->hide(); + expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + expandButton->setToolTip("Expand"); + } +} + + +void ForumMsgItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "ForumMsgItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + +/*********** SPECIFIC FUNCTIOSN ***********************/ + + +void ForumMsgItem::unsubscribeForum() +{ +#ifdef DEBUG_ITEM + std::cerr << "ForumMsgItem::unsubscribeForum()"; + std::cerr << std::endl; +#endif + if (rsForums) + { + rsForums->forumSubscribe(mForumId, false); + } + updateItemStatic(); +} + + +void ForumMsgItem::subscribeForum() +{ +#ifdef DEBUG_ITEM + std::cerr << "ForumMsgItem::subscribeForum()"; + std::cerr << std::endl; +#endif + if (rsForums) + { + rsForums->forumSubscribe(mForumId, true); + } + updateItemStatic(); +} + +void ForumMsgItem::replyToPost() +{ + if (canReply == false) { + return; + } + +#ifdef DEBUG_ITEM + std::cerr << "ForumMsgItem::replyToPost()"; + std::cerr << std::endl; +#endif + if (mParent) + { + CreateForumMsg *cfm = new CreateForumMsg(mForumId, mPostId); + cfm->show(); + } + +} + +void ForumMsgItem::sendMsg() +{ + if (canReply == false) { + return; + } + + QString desc = textEdit->toHtml(); + + if(textEdit->toPlainText().isEmpty()) + { /* error message */ + QMessageBox::warning(this, "RetroShare",tr("Please give a Text Message"), + QMessageBox::Ok, QMessageBox::Ok); + + return; //Don't add a empty Message!! + } + + ForumMsgInfo msg; + + /* get message */ + if (rsForums->getForumMessage(mForumId, mPostId, msg)) { + ForumMsgInfo msgInfo; + + msgInfo.forumId = mForumId; + msgInfo.threadId = ""; + msgInfo.parentId = mPostId; + msgInfo.msgId = ""; + + /* modify title */ + QString text = QString::fromStdWString(msg.title); + if (text.startsWith("Re:", Qt::CaseInsensitive)) { + msgInfo.title = msg.title; + } else { + msgInfo.title = L"Re: " + msg.title; + } + + msgInfo.msg = desc.toStdWString(); + msgInfo.msgflags = 0; + + if (signedcheckBox->isChecked()) + { + msgInfo.msgflags = RS_DISTRIB_AUTHEN_REQ; + } + + if ((msgInfo.msg == L"") && (msgInfo.title == L"")) + return; /* do nothing */ + + if (rsForums->ForumMessageSend(msgInfo) == true) { + textEdit->clear(); + } + } +} + +void ForumMsgItem::updateAvatar(const QString &peer_id) +{ + if (mGpgIdPrev.empty() == false) { + /* Is this one of the ssl ids of the gpg id ? */ + std::list sslIds; + if (rsPeers->getSSLChildListOfGPGId(mGpgIdPrev, sslIds) == false) { + return; + } + + if (std::find(sslIds.begin(), sslIds.end(), peer_id.toStdString()) != sslIds.end()) { + /* One of the ssl ids of the gpg id */ + showAvatar(peer_id.toStdString(), false); + } + } + + if (mGpgIdNext.empty() == false) { + /* Is this one of the ssl ids of the gpg id ? */ + std::list sslIds; + if (rsPeers->getSSLChildListOfGPGId(mGpgIdNext, sslIds) == false) { + return; + } + + if (std::find(sslIds.begin(), sslIds.end(), peer_id.toStdString()) != sslIds.end()) { + /* One of the ssl ids of the gpg id */ + showAvatar(peer_id.toStdString(), true); + } + } +} + +void ForumMsgItem::showAvatar(const std::string &peer_id, bool next) +{ + std::string gpgId = next ? mGpgIdNext : mGpgIdPrev; + QLabel *avatar = next ? nextavatarlabel : avatarlabel; + + if (gpgId.empty()) { + avatar->setPixmap(QPixmap(":/images/user/personal64.png")); + return; + } + + unsigned char *data = NULL; + int size = 0 ; + + if (gpgId == rsPeers->getGPGOwnId()) { + /* Its me */ + rsMsgs->getOwnAvatarData(data,size); + } else { + if (peer_id.empty()) { + /* Show the first available avatar of one of the ssl ids */ + std::list sslIds; + if (rsPeers->getSSLChildListOfGPGId(gpgId, sslIds) == false) { + return; + } + + std::list::iterator sslId; + for (sslId = sslIds.begin(); sslId != sslIds.end(); sslId++) { + rsMsgs->getAvatarData(*sslId,data,size); + if (size) { + break; + } + } + } else { + rsMsgs->getAvatarData(peer_id,data,size); + } + } + + if(size != 0) { + // set the image + QPixmap pix ; + pix.loadFromData(data,size,"PNG") ; + avatar->setPixmap(pix); + delete[] data ; + } else { + avatar->setPixmap(QPixmap(":/images/user/personal64.png")); + } +} diff --git a/retroshare-gui/src/gui/feeds/ForumMsgItem.h b/retroshare-gui/src/gui/feeds/ForumMsgItem.h new file mode 100644 index 000000000..4a93a2a5c --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ForumMsgItem.h @@ -0,0 +1,75 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _FORUM_MSG_ITEM_DIALOG_H +#define _FORUM_MSG_ITEM_DIALOG_H + +#include "ui_ForumMsgItem.h" + +class FeedHolder; + +#include +class ForumMsgItem : public QWidget, private Ui::ForumMsgItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + ForumMsgItem(FeedHolder *parent, uint32_t feedId, const std::string &forumId, const std::string &postId, bool isHome); + + /** Default Destructor */ + + void updateItemStatic(); + void small(); + +private slots: + /* default stuff */ + void removeItem(); + void toggle(); + + void unsubscribeForum(); + void subscribeForum(); + void replyToPost(); + void sendMsg(); + + + void updateItem(); + void updateAvatar(const QString &peer_id); + +private: + void showAvatar(const std::string &peer_id, bool next); + + FeedHolder *mParent; + uint32_t mFeedId; + bool canReply; + + std::string mForumId; + std::string mPostId; + std::string mGpgIdPrev; + std::string mGpgIdNext; + bool mIsHome; + bool mIsTop; +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/ForumMsgItem.ui b/retroshare-gui/src/gui/feeds/ForumMsgItem.ui new file mode 100644 index 000000000..b1bffbcb4 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ForumMsgItem.ui @@ -0,0 +1,629 @@ + + + ForumMsgItem + + + + 0 + 0 + 577 + 423 + + + + + + + + 6 + + + + + + 0 + 0 + + + + QFrame#frame_3{border: 2px solid #CCCCCC; +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #EEEEEE, stop: 1 #CCCCCC); +border-radius: 10px} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 48 + 48 + + + + + 48 + 48 + + + + QLabel#label{border: 2px solid black; +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #EEEEEE, stop: 1 #CCCCCC); +border-radius: 10px} + + + + + + :/images/konversation.png + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 9 + 75 + false + true + + + + Forum Name + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + + + Qt::Horizontal + + + + 358 + 20 + + + + + + + + + 9 + 75 + true + + + + Timestamp + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Qt::Horizontal + + + + 518 + 20 + + + + + + + + + + + + + 75 + true + + + + Subject: + + + + + + + Subject... + + + false + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 10 + 20 + + + + + + + + + 0 + 0 + + + + Unsubscribe To Forum + + + + + + + :/images/mail_delete.png:/images/mail_delete.png + + + + + + + + 0 + 0 + + + + Reply + + + + + + + :/images/replymail24.png:/images/replymail24.png + + + + + + + + 0 + 0 + + + + Expand + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + 0 + 0 + + + + Remove Item + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + + QFrame#prevFrame{border: 2px solid black; +border-radius: 10px} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + true + + + + + + + + 75 + true + + + + color: rgb(59, 89, 152); + + + Friend Name + + + true + + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Subject: + + + + + + + + 0 + 0 + + + + Message is about ??? + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 9 + + + + + + + + + + + 0 + 0 + + + + Previous Message... + + + true + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 20 + + + + + + + + + + + + + QFrame#nextFrame{border: 2px solid black; +border-radius: 10px} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + true + + + + + + + + 75 + true + + + + color: rgb(59, 89, 152); + + + Next Name + + + true + + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Subject: + + + + + + + + 0 + 0 + + + + Message is about ??? + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 27 + + + + + + + + + + + 0 + 0 + + + + Current Message.. + + + true + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + + + + 16777215 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 2 + + + + + + + + Send + + + + + + + Signed + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/ForumNewItem.cpp b/retroshare-gui/src/gui/feeds/ForumNewItem.cpp new file mode 100644 index 000000000..fd76c6fa9 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ForumNewItem.cpp @@ -0,0 +1,206 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "ForumNewItem.h" +#include "FeedHolder.h" + +#include +#include "gui/forums/CreateForumMsg.h" +#include "gui/RetroShareLink.h" + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +ForumNewItem::ForumNewItem(FeedHolder *parent, uint32_t feedId, std::string forumId, bool isHome, bool isNew) +:QWidget(NULL), mParent(parent), mFeedId(feedId), + mForumId(forumId), mIsHome(isHome), mIsNew(isNew) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + /* general ones */ + connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + + /* specific ones */ + connect( subscribeButton, SIGNAL( clicked( void ) ), this, SLOT( subscribeForum ( void ) ) ); + // To Cheeky to post on a brand new forum.... + connect( postButton, SIGNAL( clicked( void ) ), this, SLOT( postToForum ( void ) ) ); + + small(); + updateItemStatic(); + updateItem(); +} + + +void ForumNewItem::updateItemStatic() +{ + if (!rsForums) + return; + + + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ForumNewItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + ForumInfo fi; + if (rsForums->getForumInfo(mForumId, fi)) + { + RetroShareLink link; + link.createForum(fi.forumId, ""); + nameLabel->setText(link.toHtml()); + + descLabel->setText(QString::fromStdWString(fi.forumDesc)); + + if (fi.subscribeFlags & RS_DISTRIB_SUBSCRIBED) + { + subscribeButton->setEnabled(false); + postButton->setEnabled(true); + } + else + { + subscribeButton->setEnabled(true); + postButton->setEnabled(false); + } + + /* should also check the other flags */ + } + else + { + nameLabel->setText("Unknown Forum"); + titleLabel->setText("New Forum"); + descLabel->setText(""); + } + + if (mIsNew) + { + titleLabel->setText("New Forum"); + } + else + { + titleLabel->setText("Updated Forum"); + } + + if (mIsHome) + { + /* disable buttons */ + clearButton->setEnabled(false); + } +} + + +void ForumNewItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ForumNewItem::updateItem()"; + std::cerr << std::endl; +#endif + +} + + +void ForumNewItem::small() +{ + expandFrame->hide(); +} + +void ForumNewItem::toggle() +{ + if (expandFrame->isHidden()) + { + expandFrame->show(); + expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + expandButton->setToolTip("Hide"); + } + else + { + expandFrame->hide(); + expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + expandButton->setToolTip("Expand"); + } +} + + +void ForumNewItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "ForumNewItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + + +/*********** SPECIFIC FUNCTIOSN ***********************/ + + +void ForumNewItem::unsubscribeForum() +{ +#ifdef DEBUG_ITEM + std::cerr << "ForumNewItem::unsubscribeForum()"; + std::cerr << std::endl; +#endif + if (rsForums) + { + rsForums->forumSubscribe(mForumId, false); + } + updateItemStatic(); +} + + +void ForumNewItem::subscribeForum() +{ +#ifdef DEBUG_ITEM + std::cerr << "ForumNewItem::subscribeForum()"; + std::cerr << std::endl; +#endif + if (rsForums) + { + rsForums->forumSubscribe(mForumId, true); + } + updateItemStatic(); +} + +void ForumNewItem::postToForum() +{ +#ifdef DEBUG_ITEM + std::cerr << "ForumNewItem::subscribeForum()"; + std::cerr << std::endl; +#endif + if (mParent) + { + //mParent->openMsg(FEEDHOLDER_MSG_FORUM, mForumId, ""); + CreateForumMsg *cfm = new CreateForumMsg(mForumId, ""); + cfm->show(); + } +} + diff --git a/retroshare-gui/src/gui/feeds/ForumNewItem.h b/retroshare-gui/src/gui/feeds/ForumNewItem.h new file mode 100644 index 000000000..58743af91 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ForumNewItem.h @@ -0,0 +1,66 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _FORUM_NEW_ITEM_DIALOG_H +#define _FORUM_NEW_ITEM_DIALOG_H + +#include "ui_ForumNewItem.h" +#include + +class FeedHolder; + +class ForumNewItem : public QWidget, private Ui::ForumNewItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + ForumNewItem(FeedHolder *parent, uint32_t feedId, std::string forumId, bool isHome, bool isNew); + + /** Default Destructor */ + + void updateItemStatic(); + void small(); + +private slots: + /* default stuff */ + void removeItem(); + void toggle(); + + void unsubscribeForum(); + void subscribeForum(); + void postToForum(); + + void updateItem(); + +private: + FeedHolder *mParent; + uint32_t mFeedId; + + std::string mForumId; + bool mIsHome; + bool mIsNew; +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/ForumNewItem.ui b/retroshare-gui/src/gui/feeds/ForumNewItem.ui new file mode 100644 index 000000000..01416a52d --- /dev/null +++ b/retroshare-gui/src/gui/feeds/ForumNewItem.ui @@ -0,0 +1,299 @@ + + + ForumNewItem + + + + 0 + 0 + 618 + 354 + + + + Form + + + + 6 + + + + + + 0 + 0 + + + + QFrame#frame{border: 2px solid orange; +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FB8428); +border-radius: 10px} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 9 + + + 6 + + + 6 + + + + + + + + + + :/images/konversation.png + + + + + + + + 0 + 0 + + + + + 75 + true + true + + + + + + + Forum + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + name + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 500 + 20 + + + + + + + + + 0 + 0 + + + + Subscribe to Forum + + + + + + + :/images/directoryadd_24x24_shadow.png:/images/directoryadd_24x24_shadow.png + + + + + + + + + + + :/images/mail_new.png:/images/mail_new.png + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + Expand + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + 0 + 0 + + + + Remove Item + + + + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + Forum Description + + + + + + + + + + + + :/images/contacts24.png + + + + + + + + 0 + 0 + + + + + + + Description + of Forum + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/MsgItem.cpp b/retroshare-gui/src/gui/feeds/MsgItem.cpp new file mode 100644 index 000000000..2796c3e86 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/MsgItem.cpp @@ -0,0 +1,305 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "MsgItem.h" +#include "FeedHolder.h" +#include "SubFileItem.h" +#include "gui/msgs/MessageComposer.h" +#include "gui/chat/HandleRichText.h" +#include "gui/notifyqt.h" + +#include +#include + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +MsgItem::MsgItem(FeedHolder *parent, uint32_t feedId, std::string msgId, bool isHome) +:QWidget(NULL), mParent(parent), mFeedId(feedId), mMsgId(msgId), mIsHome(isHome) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + /* general ones */ + connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + //connect( gotoButton, SIGNAL( clicked( void ) ), this, SLOT( gotoHome ( void ) ) ); + + /* specific ones */ + connect( playButton, SIGNAL( clicked( void ) ), this, SLOT( playMedia ( void ) ) ); + connect( deleteButton, SIGNAL( clicked( void ) ), this, SLOT( deleteMsg ( void ) ) ); + connect( replyButton, SIGNAL( clicked( void ) ), this, SLOT( replyMsg ( void ) ) ); + + connect(NotifyQt::getInstance(), SIGNAL(peerHasNewAvatar(const QString&)), this, SLOT(updateAvatar(const QString&))); + + small(); + updateItemStatic(); + updateItem(); + updateAvatar(QString::fromStdString(mPeerId)); +} + + +void MsgItem::updateItemStatic() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "MsgItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + MessageInfo mi; + + if (!rsMsgs) + return; + + if (!rsMsgs->getMessage(mMsgId, mi)) + return; + + /* get peer Id */ + mPeerId = mi.srcId; + + QString title; + QString timestamp; + QString srcName = QString::fromStdString(rsPeers->getPeerName(mi.srcId)); + + { + QDateTime qtime; + qtime.setTime_t(mi.ts); + timestamp = qtime.toString("yyyy-MM-dd hh:mm:ss"); + } + + if (!mIsHome) + { + title = tr("Message From") + ": "; + } + else + { + /* subject */ + uint32_t box = mi.msgflags & RS_MSG_BOXMASK; + switch(box) + { + case RS_MSG_SENTBOX: + title = tr("Sent Msg") + ": "; + replyButton->setEnabled(false); + break; + case RS_MSG_DRAFTBOX: + title = tr("Draft Msg") + ": "; + replyButton->setEnabled(false); + break; + case RS_MSG_OUTBOX: + title = tr("Pending Msg") + ": "; + //deleteButton->setEnabled(false); + replyButton->setEnabled(false); + break; + default: + case RS_MSG_INBOX: + title = ""; + break; + } + } + title += srcName + " @ " + timestamp; + + titleLabel->setText(title); + subjectLabel->setText(QString::fromStdWString(mi.title)); + + msgLabel->setText(RsHtml::formatText(QString::fromStdWString(mi.msg), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); + + std::list::iterator it; + for(it = mi.files.begin(); it != mi.files.end(); it++) + { + /* add file */ + SubFileItem *fi = new SubFileItem(it->hash, it->fname, it->path, it->size, SFI_STATE_REMOTE, mi.srcId); + mFileItems.push_back(fi); + + QLayout *layout = expandFrame->layout(); + layout->addWidget(fi); + } + + playButton->setEnabled(false); + + if (mIsHome) + { + /* disable buttons */ + clearButton->setEnabled(false); + //gotoButton->setEnabled(false); + + /* hide buttons */ + clearButton->hide(); + } + else + { + //deleteButton->setEnabled(false); + } +} + + +void MsgItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "MsgItem::updateItem()"; + std::cerr << std::endl; +#endif + int msec_rate = 10000; + + /* Very slow Tick to check when all files are downloaded */ + std::list::iterator it; + for(it = mFileItems.begin(); it != mFileItems.end(); it++) + { + if (!(*it)->done()) + { + /* loop again */ + QTimer::singleShot( msec_rate, this, SLOT(updateItem( void ) )); + return; + } + } + if (mFileItems.size() > 0) + { + playButton->setEnabled(true); + } +} + + +void MsgItem::small() +{ + expandFrame->hide(); +} + +void MsgItem::toggle() +{ + if (expandFrame->isHidden()) + { + expandFrame->show(); + expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + expandButton->setToolTip(tr("Hide")); + } + else + { + expandFrame->hide(); + expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + expandButton->setToolTip(tr("Expand")); + } +} + + +void MsgItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "MsgItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + + +void MsgItem::gotoHome() +{ +#ifdef DEBUG_ITEM + std::cerr << "MsgItem::gotoHome()"; + std::cerr << std::endl; +#endif +} + +/*********** SPECIFIC FUNCTIONS ***********************/ + + +void MsgItem::deleteMsg() +{ +#ifdef DEBUG_ITEM + std::cerr << "MsgItem::deleteMsg()"; + std::cerr << std::endl; +#endif + if (rsMsgs) + { + rsMsgs->MessageDelete(mMsgId); + + hide(); /* will be cleaned up next refresh */ + } +} + +void MsgItem::replyMsg() +{ +#ifdef DEBUG_ITEM + std::cerr << "MsgItem::replyMsg()"; + std::cerr << std::endl; +#endif + if (mParent) + { + //mParent->openMsg(FEEDHOLDER_MSG_MESSAGE, mPeerId, mMsgId); + + MessageComposer *nMsgDialog = MessageComposer::replyMsg(mMsgId, false); + if (nMsgDialog == NULL) { + return; + } + + nMsgDialog->show(); + nMsgDialog->activateWindow(); + + /* window will destroy itself! */ + } +} + +void MsgItem::playMedia() +{ +#ifdef DEBUG_ITEM + std::cerr << "MsgItem::playMedia()"; + std::cerr << std::endl; +#endif +} + +void MsgItem::updateAvatar(const QString &peer_id) +{ + if (peer_id.toStdString() != mPeerId) { + /* it 's not me */ + return; + } + + unsigned char *data = NULL; + int size = 0 ; + + rsMsgs->getAvatarData(mPeerId,data,size); + + if(size != 0) + { + // set the image + QPixmap pix ; + pix.loadFromData(data,size,"PNG") ; + avatarlabel->setPixmap(pix); + delete[] data ; + + } + else + { + avatarlabel->setPixmap(QPixmap(":/images/user/personal64.png")); + } +} + diff --git a/retroshare-gui/src/gui/feeds/MsgItem.h b/retroshare-gui/src/gui/feeds/MsgItem.h new file mode 100644 index 000000000..d1d220815 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/MsgItem.h @@ -0,0 +1,72 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _MSG_ITEM_DIALOG_H +#define _MSG_ITEM_DIALOG_H + +#include "ui_MsgItem.h" +#include + +class FeedHolder; +class SubFileItem; + +class MsgItem : public QWidget, private Ui::MsgItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + MsgItem(FeedHolder *parent, uint32_t feedId, std::string msgId, bool isHome); + + /** Default Destructor */ + + void updateItemStatic(); + void small(); + +private slots: + /* default stuff */ + void gotoHome(); + void removeItem(); + void toggle(); + + void playMedia(); + void deleteMsg(); + void replyMsg(); + + void updateItem(); + void updateAvatar(const QString &peer_id); + +private: + FeedHolder *mParent; + uint32_t mFeedId; + + std::string mPeerId; + std::string mMsgId; + + bool mIsHome; + + std::list mFileItems; +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/MsgItem.ui b/retroshare-gui/src/gui/feeds/MsgItem.ui new file mode 100644 index 000000000..6f2a4c7c0 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/MsgItem.ui @@ -0,0 +1,282 @@ + + + MsgItem + + + + 0 + 0 + 710 + 174 + + + + + + + + 6 + + + + + + 0 + 0 + + + + QFrame#frame{border: 2px solid blue; +background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, +stop: 0 #2291E0, stop: 1 #3EB3FF); +border-radius: 10px} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + + 70 + 70 + + + + + 70 + 70 + + + + QLabel#avatarlabel{border: 2px solid blue; +background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, +stop: 0 #2291E0, stop: 1 #3EB3FF); +} + + + true + + + + + + + + + + 0 + 0 + + + + + 75 + true + true + + + + Message + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 557 + 18 + + + + + + + + + 0 + 0 + + + + Expand + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + 0 + 0 + + + + Remove Item + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + 0 + 0 + + + + subjectLabel + + + true + + + + + + + + + Reply to Message + + + Reply Message + + + + :/images/mail_reply.png:/images/mail_reply.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Qt::Horizontal + + + + 424 + 20 + + + + + + + + + 0 + 0 + + + + Delete Message + + + + + + + :/images/mail_delete.png:/images/mail_delete.png + + + + + + + + 0 + 0 + + + + Play Media + + + + + + + :/images/startall.png:/images/startall.png + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + Long + message here + + + true + + + true + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/PeerItem.cpp b/retroshare-gui/src/gui/feeds/PeerItem.cpp new file mode 100644 index 000000000..eef83010c --- /dev/null +++ b/retroshare-gui/src/gui/feeds/PeerItem.cpp @@ -0,0 +1,401 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "PeerItem.h" +#include "FeedHolder.h" +#include "../RsAutoUpdatePage.h" +#include "gui/msgs/MessageComposer.h" +#include "gui/common/StatusDefs.h" + +#include "gui/notifyqt.h" + +#include +#include + +#include + +/***** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +PeerItem::PeerItem(FeedHolder *parent, uint32_t feedId, std::string peerId, uint32_t type, bool isHome) +:QWidget(NULL), mParent(parent), mFeedId(feedId), + mPeerId(peerId), mType(type), mIsHome(isHome) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + messageframe->setVisible(false); + sendmsgButton->setEnabled(false); + + /* general ones */ + connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + + /* specific ones */ + connect( chatButton, SIGNAL( clicked( void ) ), this, SLOT( openChat ( void ) ) ); + connect( actionNew_Message, SIGNAL( triggered( ) ), this, SLOT( sendMsg ( void ) ) ); + + connect( quickmsgButton, SIGNAL( clicked( ) ), this, SLOT( togglequickmessage() ) ); + connect( cancelButton, SIGNAL( clicked( ) ), this, SLOT( togglequickmessage() ) ); + + connect( sendmsgButton, SIGNAL( clicked( ) ), this, SLOT( sendMessage() ) ); + + connect(NotifyQt::getInstance(), SIGNAL(peerHasNewAvatar(const QString&)), this, SLOT(updateAvatar(const QString&))); + + QMenu *msgmenu = new QMenu(); + msgmenu->addAction(actionNew_Message); + + quickmsgButton->setMenu(msgmenu); + + small(); + updateItemStatic(); + updateItem(); + updateAvatar(QString::fromStdString(mPeerId)); +} + + +void PeerItem::updateItemStatic() +{ + if (!rsPeers) + return; + + + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "PeerItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + RsPeerDetails details; + if (rsPeers->getPeerDetails(mPeerId, details)) + { + QString title; + + switch(mType) + { + case PEER_TYPE_STD: + title = tr("Friend"); + break; + case PEER_TYPE_CONNECT: + title = tr("Friend Connected"); + break; + case PEER_TYPE_HELLO: + title = tr("Connect Attempt"); + break; + case PEER_TYPE_NEW_FOF: + title = tr("Friend of Friend"); + break; + default: + title = tr("Peer"); + break; + } + + titleLabel->setText(title); + + /* set textcolor for peername */ + QString nameStr("%1"); + + /* set Blog name */ + QString peername = QString::fromStdString(details.name); + peernameLabel->setText(nameStr.arg(peername)); + + QDateTime date = QDateTime::fromTime_t(details.lastConnect); + QString stime = date.toString(Qt::LocalDate); + lastLabel-> setText(stime); + + /* expanded Info */ + nameLabel->setText(QString::fromUtf8(details.name.c_str())); + idLabel->setText(QString::fromStdString(details.id)); + locLabel->setText(QString::fromUtf8(details.location.c_str())); + } + else + { + statusLabel->setText(tr("Unknown Peer")); + titleLabel->setText(tr("Unknown Peer")); + trustLabel->setText(tr("Unknown Peer")); + nameLabel->setText(tr("Unknown Peer")); + idLabel->setText(tr("Unknown Peer")); + locLabel->setText(tr("Unknown Peer")); + ipLabel->setText(tr("Unknown Peer")); + connLabel->setText(tr("Unknown Peer")); + lastLabel->setText(tr("Unknown Peer")); + + chatButton->setEnabled(false); + + } + + if (mIsHome) + { + /* disable buttons */ + clearButton->setEnabled(false); + //gotoButton->setEnabled(false); + + /* disable buttons */ + clearButton->hide(); + } + +} + + +void PeerItem::updateItem() +{ + if (!rsPeers) + return; + + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "PeerItem::updateItem()"; + std::cerr << std::endl; +#endif + if(!RsAutoUpdatePage::eventsLocked()) { + RsPeerDetails details; + if (!rsPeers->getPeerDetails(mPeerId, details)) + { + return; + } + + /* top Level info */ + QString status = StatusDefs::peerStateString(details.state); + +#if 0 + /* Append additional status info from status service */ + StatusInfo statusInfo; + if ((rsStatus) && (rsStatus->getStatus(*it, statusInfo))) + { + status.append(QString::fromStdString("/" + RsStatusString(statusInfo.status))); + } +#endif + statusLabel->setText(status); + trustLabel->setText(QString::fromStdString( + RsPeerTrustString(details.trustLvl))); + + { + std::ostringstream out; + out << details.localAddr << ":"; + out << details.localPort << "/"; + out << details.extAddr << ":"; + out << details.extPort; + ipLabel->setText(QString::fromStdString(out.str())); + } + + connLabel->setText(StatusDefs::connectStateString(details)); + + /* do buttons */ + chatButton->setEnabled(details.state & RS_PEER_STATE_CONNECTED); + if (details.state & RS_PEER_STATE_FRIEND) + { + //addButton->setEnabled(false); + //removeButton->setEnabled(true); + quickmsgButton->setEnabled(true); + } + else + { + //addButton->setEnabled(true); + //removeButton->setEnabled(false); + quickmsgButton->setEnabled(false); + } + } + + /* slow Tick */ + int msec_rate = 10129; + + QTimer::singleShot( msec_rate, this, SLOT(updateItem( void ) )); + return; +} + +void PeerItem::small() +{ + expandFrame->hide(); +} + +void PeerItem::toggle() +{ + if (expandFrame->isHidden()) + { + expandFrame->show(); + expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + expandButton->setToolTip(tr("Hide")); + } + else + { + expandFrame->hide(); + expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + expandButton->setToolTip(tr("Expand")); + } +} + + +void PeerItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "PeerItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + + +void PeerItem::gotoHome() +{ +#ifdef DEBUG_ITEM + std::cerr << "PeerItem::gotoHome()"; + std::cerr << std::endl; +#endif +} + +/*********** SPECIFIC FUNCTIOSN ***********************/ + +void PeerItem::addFriend() +{ +#ifdef DEBUG_ITEM + std::cerr << "PeerItem::addFriend()"; + std::cerr << std::endl; +#endif +} + + + +void PeerItem::removeFriend() +{ +#ifdef DEBUG_ITEM + std::cerr << "PeerItem::removeFriend()"; + std::cerr << std::endl; +#endif +} + + + +void PeerItem::sendMsg() +{ +#ifdef DEBUG_ITEM + std::cerr << "PeerItem::sendMsg()"; + std::cerr << std::endl; +#endif + + if (mParent) + { + //mParent->openMsg(FEEDHOLDER_MSG_MESSAGE, mPeerId, ""); + + MessageComposer *nMsgDialog = MessageComposer::newMsg(); + if (nMsgDialog == NULL) { + return; + } + + nMsgDialog->addRecipient(MessageComposer::TO, mPeerId, false); + nMsgDialog->show(); + nMsgDialog->activateWindow(); + + /* window will destroy itself! */ + } +} + + +void PeerItem::openChat() +{ +#ifdef DEBUG_ITEM + std::cerr << "PeerItem::openChat()"; + std::cerr << std::endl; +#endif + if (mParent) + { + mParent->openChat(mPeerId); + } +} + +void PeerItem::updateAvatar(const QString &peer_id) +{ + if (peer_id.toStdString() != mPeerId) { + /* it 's not me */ + return; + } + + unsigned char *data = NULL; + int size = 0 ; + + rsMsgs->getAvatarData(mPeerId,data,size); + + + if(size != 0) + { + // set the image + QPixmap pix ; + pix.loadFromData(data,size,"PNG") ; + avatar_label->setPixmap(pix); + delete[] data ; + + } + else + { + avatar_label->setPixmap(QPixmap(":/images/user/personal64.png")); + } + + +} + +void PeerItem::togglequickmessage() +{ + if (messageframe->isHidden()) + { + messageframe->setVisible(true); + } + else + { + messageframe->setVisible(false); + } + +} + +void PeerItem::sendMessage() +{ + /* construct a message */ + MessageInfo mi; + + mi.title = tr("Quick Message").toStdWString(); + mi.msg = quickmsgText->toHtml().toStdWString(); + mi.msgto.push_back(mPeerId); + + rsMsgs->MessageSend(mi); + + quickmsgText->clear(); + messageframe->setVisible(false); +} + +void PeerItem::on_quickmsgText_textChanged() +{ + if (quickmsgText->toPlainText().isEmpty()) + { + sendmsgButton->setEnabled(false); + } + else + { + sendmsgButton->setEnabled(true); + } +} diff --git a/retroshare-gui/src/gui/feeds/PeerItem.h b/retroshare-gui/src/gui/feeds/PeerItem.h new file mode 100644 index 000000000..551659fec --- /dev/null +++ b/retroshare-gui/src/gui/feeds/PeerItem.h @@ -0,0 +1,81 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _PEER_ITEM_DIALOG_H +#define _PEER_ITEM_DIALOG_H + +#include "ui_PeerItem.h" +#include + +const uint32_t PEER_TYPE_STD = 0x0001; +const uint32_t PEER_TYPE_CONNECT = 0x0002; +const uint32_t PEER_TYPE_HELLO = 0x0003; /* failed Connect Attempt */ +const uint32_t PEER_TYPE_NEW_FOF = 0x0004; /* new Friend of Friend */ + +class FeedHolder; + + +class PeerItem : public QWidget, private Ui::PeerItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + PeerItem(FeedHolder *parent, uint32_t feedId, std::string peerId, uint32_t type, bool isHome); + + /** Default Destructor */ + + void updateItemStatic(); + void small(); + +private slots: + /* default stuff */ + void gotoHome(); + void removeItem(); + void toggle(); + + void addFriend(); + void removeFriend(); + void sendMsg(); + void openChat(); + + void updateItem(); + void updateAvatar(const QString &peer_id); + + void togglequickmessage(); + void sendMessage(); + + void on_quickmsgText_textChanged(); + + +private: + FeedHolder *mParent; + uint32_t mFeedId; + + std::string mPeerId; + uint32_t mType; + bool mIsHome; +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/PeerItem.ui b/retroshare-gui/src/gui/feeds/PeerItem.ui new file mode 100644 index 000000000..8c90cd15d --- /dev/null +++ b/retroshare-gui/src/gui/feeds/PeerItem.ui @@ -0,0 +1,587 @@ + + + PeerItem + + + + 0 + 0 + 476 + 382 + + + + + + + + 6 + + + + + + 0 + 0 + + + + QFrame#frame{border: 2px solid green; + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #649C35); +border-radius: 10px} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + QFrame#frame_2{border: transparent} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + + + + 70 + 70 + + + + + 70 + 70 + + + + QLabel#avatar_label{border: 2px solid green; + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); +} + + + + + + true + + + 0 + + + + + + + + + + + + Peer Name + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + 0 + 0 + + + + + 75 + true + true + + + + Connected + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + + + + Qt::Horizontal + + + + 190 + 13 + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + TextLabel + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Expand + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + 0 + 0 + + + + Remove Item + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 388 + 21 + + + + + + + + Write a quick Message + + + + :/images/message-mail.png:/images/message-mail.png + + + QToolButton::MenuButtonPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + 0 + 0 + + + + Chat + + + Start Chat + + + + :/images/chat.png:/images/chat.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + avatar_label + + + + + + + + + + 16777215 + 130 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 0 + + + + + Cancel + + + + + + + Send + + + false + + + true + + + + + + + Qt::Horizontal + + + + 469 + 20 + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Qt::Vertical + + + + 200 + 78 + + + + + + + + + + + + + 75 + true + + + + Name: + + + + + + + + 75 + true + + + + Peer ID: + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Trust: + + + + + + + + 75 + true + + + + Location + + + + + + + + 75 + true + + + + IP Address + + + + + + + + 75 + true + + + + Connection Method + + + + + + + + 0 + 0 + + + + + 75 + true + true + + + + Status: + + + + + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + Good + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + Connected + + + + + + + + + + + + + + + + + + :/images/mail_send.png:/images/mail_send.png + + + Write Message + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/SubDestItem.cpp b/retroshare-gui/src/gui/feeds/SubDestItem.cpp new file mode 100644 index 000000000..dec9c23eb --- /dev/null +++ b/retroshare-gui/src/gui/feeds/SubDestItem.cpp @@ -0,0 +1,109 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "SubDestItem.h" +#include "FeedHolder.h" + +#include +#include +#include + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +SubDestItem::SubDestItem(uint32_t type, std::string groupId, std::string inReplyTo) +:QWidget(NULL), mType(type), mGroupId(groupId), mInReplyTo(inReplyTo) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + connect( cancelButton, SIGNAL( clicked( void ) ), this, SLOT( cancel ( void ) ) ); + + updateItemStatic(); +} + +void SubDestItem::updateItemStatic() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "SubDestItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + QString name = "Unknown"; + switch(mType) + { + case FEEDHOLDER_MSG_MESSAGE: + { + typeLabel->setText("Message To: "); + if (rsPeers) + { + name = QString::fromStdString(rsPeers->getPeerName(mGroupId)); + } + } + break; + + case FEEDHOLDER_MSG_FORUM: + { + typeLabel->setText("Forum Post To: "); + ForumInfo fi; + if ((rsForums) && (rsForums->getForumInfo(mGroupId, fi))) + { + name = QString::fromStdWString(fi.forumName); + } + } + break; + + case FEEDHOLDER_MSG_CHANNEL: + { + typeLabel->setText("Channel Post To: "); + ChannelInfo ci; + if ((rsChannels) && (rsChannels->getChannelInfo(mGroupId, ci))) + { + name = QString::fromStdWString(ci.channelName); + } + } + break; + + case FEEDHOLDER_MSG_BLOG: + { + typeLabel->setText("Blog Post"); + name = ""; + } + break; + + } + nameLabel->setText(name); +} + +void SubDestItem::cancel() +{ +#ifdef DEBUG_ITEM + std::cerr << "SubDestItem::cancel()"; + std::cerr << std::endl; +#endif + hide(); +} + diff --git a/retroshare-gui/src/gui/feeds/SubDestItem.h b/retroshare-gui/src/gui/feeds/SubDestItem.h new file mode 100644 index 000000000..df347ae9b --- /dev/null +++ b/retroshare-gui/src/gui/feeds/SubDestItem.h @@ -0,0 +1,57 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _SUB_DEST_ITEM_DIALOG_H +#define _SUB_DEST_ITEM_DIALOG_H + +#include "ui_SubDestItem.h" +#include + +class SubDestItem : public QWidget, private Ui::SubDestItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + SubDestItem(uint32_t type, std::string groupId, std::string inReplyTo); + + /** Default Destructor */ + + uint32_t DestType() { return mType; } + std::string DestGroupId() { return mGroupId; } + std::string DestInReplyTo() { return mInReplyTo; } + +void updateItemStatic(); + +private slots: + /* default stuff */ + void cancel(); + +private: + uint32_t mType; + std::string mGroupId; + std::string mInReplyTo; +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/SubDestItem.ui b/retroshare-gui/src/gui/feeds/SubDestItem.ui new file mode 100644 index 000000000..c748eb082 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/SubDestItem.ui @@ -0,0 +1,172 @@ + + + SubDestItem + + + + 0 + 0 + 592 + 77 + + + + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame#frame{border: 2px solid black; +background: white;} + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + 300 + 16777215 + + + + + 75 + true + true + + + + Type + + + false + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + + 300 + 16777215 + + + + + 75 + true + true + + + + Person/Channel Name + + + false + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 71 + 21 + + + + + + + + + 0 + 0 + + + + Delete FeedItem + + + + + + + :/images/close-down.png:/images/close-down.png + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/SubFileItem.cpp b/retroshare-gui/src/gui/feeds/SubFileItem.cpp new file mode 100644 index 000000000..19fa96dd2 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/SubFileItem.cpp @@ -0,0 +1,688 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include + +#include "SubFileItem.h" + +#include +#include "util/misc.h" + + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/******************************************************************* + * SubFileItem fully controls the file transfer from the gui side + * + * Display: (In order) + * + * 1) HASHING + * 2) REMOTE / DOWNLOAD + * 3) LOCAL + * 4) LOCAL / UPLOAD + * + * Behaviours: + * a) Addition to General Dialog (1), (2), (3) + * (i) (1), request Hash -> (3). + * (ii) (2), download complete -> (3) + * (iii) (3) + * + * b) Message/Blog/Channel (2), (3) + * (i) (2), download complete -> (3) + * (ii) (3) + * + * c) Transfers (2), (4) + * (i) (2) + * (ii) (3) + * + * + */ + + + +const uint32_t SFI_DEFAULT_PERIOD = (30 * 3600 * 24); /* 30 Days */ + +/** Constructor */ +SubFileItem::SubFileItem(const std::string &hash, const std::string &name, const std::string &path, uint64_t size, uint32_t flags, const std::string &srcId) +:QWidget(NULL), mPath(path), mFileHash(hash), mFileName(name), mFileSize(size), mSrcId(srcId) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + mMode = flags & SFI_MASK_STATE; + mType = flags & SFI_MASK_TYPE; + + /**** Enable **** + *****/ + + /* all other states are possible */ + + if (!rsFiles) + { + mMode = SFI_STATE_ERROR; + } + + Setup(); +} + + +void SubFileItem::Setup() +{ + connect( playButton, SIGNAL( clicked( void ) ), this, SLOT( play ( void ) ) ); + connect( downloadButton, SIGNAL( clicked( void ) ), this, SLOT( download ( void ) ) ); + connect( cancelButton, SIGNAL( clicked( void ) ), this, SLOT( cancel ( void ) ) ); + connect( saveButton, SIGNAL( clicked( void ) ), this, SLOT( save ( void ) ) ); + + /* once off check - if remote, check if we have it + * NB: This check might be expensive - and it'll happen often! + */ +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::Setup(): " << mFileName; + std::cerr << std::endl; +#endif + + if (mMode == SFI_STATE_REMOTE) + { + FileInfo fi; + + /* look up path */ + if (rsFiles->alreadyHaveFile(mFileHash, fi)) + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::Setup() STATE=>Local Found File"; + std::cerr << std::endl; + std::cerr << "SubFileItem::Setup() path: " << fi.path; + std::cerr << std::endl; +#endif + mMode = SFI_STATE_LOCAL; + mPath = fi.path; + } + } + + smaller(); + updateItemStatic(); + updateItem(); +} + + +bool SubFileItem::done() +{ + return (mMode >= SFI_STATE_LOCAL); +} + +bool SubFileItem::ready() +{ + return (mMode >= SFI_STATE_REMOTE); +} + +void SubFileItem::updateItemStatic() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItemStatic(): " << mFileName; + std::cerr << std::endl; +#endif + + QString filename = QString::fromUtf8(mFileName.c_str()); + mDivisor = 1; + + if (mFileSize > 10000000) /* 10 Mb */ + { + progressBar->setRange(0, mFileSize / 1000000); + progressBar->setFormat("%v MB"); + mDivisor = 1000000; + } + else if (mFileSize > 10000) /* 10 Kb */ + { + progressBar->setRange(0, mFileSize / 1000); + progressBar->setFormat("%v kB"); + mDivisor = 1000; + } + else + { + progressBar->setRange(0, mFileSize); + progressBar->setFormat("%v B"); + mDivisor = 1; + } + + /* get full path for local file */ + if ((mMode == SFI_STATE_LOCAL) || (mMode == SFI_STATE_UPLOAD)) + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItemStatic() STATE=Local/Upload checking path"; + std::cerr << std::endl; +#endif + if (mPath == "") + { + FileInfo fi; + uint32_t hintflags = RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SPEC_ONLY | RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_BROWSABLE; + + /* look up path */ + if (!rsFiles->FileDetails(mFileHash, hintflags, fi)) + { + mMode = SFI_STATE_ERROR; +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItemStatic() STATE=>Error No Details"; + std::cerr << std::endl; +#endif + } + else + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItemStatic() Updated Path"; + std::cerr << std::endl; +#endif + mPath = fi.path; + } + } + } + + /* do buttons + display */ + switch (mMode) + { + case SFI_STATE_ERROR: + progressBar->setRange(0, 100); + progressBar->setFormat(tr("ERROR")); + + playButton->setEnabled(false); + downloadButton->setEnabled(false); + cancelButton->setEnabled(false); + + progressBar->setValue(0); + filename = "[" + tr("ERROR") + "] " + filename; + + break; + + case SFI_STATE_EXTRA: + filename = QString::fromUtf8(mPath.c_str()); + + progressBar->setRange(0, 100); + progressBar->setFormat("HASHING"); + + playButton->setEnabled(false); + downloadButton->setEnabled(false); + cancelButton->setEnabled(false); + + progressBar->setValue(0); + filename = "[" + tr("EXTRA") + "] " + filename; + + break; + + case SFI_STATE_REMOTE: + playButton->setEnabled(false); + downloadButton->setEnabled(true); + cancelButton->setEnabled(false); + + progressBar->setValue(0); + filename = "[" + tr("REMOTE") + "] " + filename + " (" + misc::friendlyUnit(mFileSize) + ")"; + + break; + + case SFI_STATE_DOWNLOAD: + playButton->setEnabled(false); + downloadButton->setEnabled(false); + cancelButton->setEnabled(true); + filename = "[" + tr("DOWNLOAD") + "] " + filename; + + break; + + case SFI_STATE_LOCAL: + playButton->setEnabled(true); + downloadButton->setEnabled(false); + cancelButton->setEnabled(true); + + progressBar->setValue(mFileSize / mDivisor); + filename = "[" + tr("LOCAL") + "] " + filename + " (" + misc::friendlyUnit(mFileSize) + ")"; + + break; + + case SFI_STATE_UPLOAD: + playButton->setEnabled(true); + downloadButton->setEnabled(false); + cancelButton->setEnabled(false); + filename = "[" + tr("UPLOAD") + "] " + filename; + + break; + } + + saveButton->hide(); + + switch(mType) + { + case SFI_TYPE_CHANNEL: + { + saveButton->show(); + if (mMode == SFI_STATE_LOCAL) + { + saveButton->setEnabled(true); + cancelButton->setEnabled(true); // channel files which are extra files are removed + } + else + { + saveButton->setEnabled(false); + } + } + break; + case SFI_TYPE_ATTACH: + { + playButton->hide(); + downloadButton->hide(); + cancelButton->setEnabled(true); + cancelButton->setToolTip("Remove Attachment"); + } + break; + default: + break; + } + + + fileLabel->setText(filename); + fileLabel->setToolTip(filename); + +} + +void SubFileItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem():" << mFileName; + std::cerr << std::endl; +#endif + + /* Extract File Details */ + /* Update State if necessary */ + + FileInfo fi; + bool stateChanged = false; + int msec_rate = 1000; + + if ((mMode == SFI_STATE_ERROR) || (mMode == SFI_STATE_LOCAL)) + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() STATE=Local/Error ignore"; + std::cerr << std::endl; +#endif + /* ignore - dead file, or done */ + + if (mMode == SFI_STATE_ERROR) { + /* updateStatic once */ + stateChanged = true; + } + } + else if (mMode == SFI_STATE_EXTRA) + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() STATE=Extra File"; + std::cerr << std::endl; +#endif + /* check for file status */ + if (rsFiles->ExtraFileStatus(mPath, fi)) + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() STATE=>Local"; + std::cerr << std::endl; +#endif + mMode = SFI_STATE_LOCAL; + + /* fill in file details */ + mFileName = fi.fname; + mFileSize = fi.size; + mFileHash = fi.hash; + + /* have path already! */ + + stateChanged = true; + } + } + else + { + uint32_t hintflags = 0; + switch(mMode) + { + case SFI_STATE_REMOTE: + hintflags = RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY; + break; + case SFI_STATE_DOWNLOAD: + hintflags = RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY; + break; + case SFI_STATE_UPLOAD: + hintflags = RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_SPEC_ONLY; + break; + } + + bool detailsOk = rsFiles->FileDetails(mFileHash, hintflags, fi); + + /* have details - see if state has changed */ + switch(mMode) + { + case SFI_STATE_REMOTE: +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() STATE=Remote"; + std::cerr << std::endl; +#endif + /* is it downloading? */ + if (detailsOk) + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() STATE=>Download"; + std::cerr << std::endl; +#endif + /* downloading */ + mMode = SFI_STATE_DOWNLOAD; + stateChanged = true; + } + break; + case SFI_STATE_DOWNLOAD: +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() STATE=Download"; + std::cerr << std::endl; +#endif + + if (!detailsOk) + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() STATE=>Remote"; + std::cerr << std::endl; +#endif + mMode = SFI_STATE_REMOTE; + stateChanged = true; + } + else + { + /* has it completed? */ + if (fi.avail == mFileSize) + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() STATE=>Local"; + std::cerr << std::endl; +#endif + /* save path */ + /* update progress */ + mMode = SFI_STATE_LOCAL; + mPath = fi.path; + stateChanged = true; + } + progressBar->setValue(fi.avail / mDivisor); + } + break; + case SFI_STATE_UPLOAD: +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() STATE=Upload"; + std::cerr << std::endl; +#endif + + if (detailsOk) + { + progressBar->setValue(fi.avail / mDivisor); + } + + /* update progress */ + break; + } + + } + + /****** update based on new state ******/ + if (stateChanged) + { + updateItemStatic(); + } + + uint32_t repeat = 0; + + switch (mMode) + { + case SFI_STATE_ERROR: + repeat = 0; + break; + + case SFI_STATE_EXTRA: + repeat = 1; + msec_rate = 5000; /* slow */ + break; + + case SFI_STATE_REMOTE: + repeat = 1; + msec_rate = 30000; /* very slow */ + break; + + case SFI_STATE_DOWNLOAD: + repeat = 1; + msec_rate = 2000; /* should be download rate dependent */ + break; + + case SFI_STATE_LOCAL: + repeat = 0; + emit fileFinished(this); + break; + + case SFI_STATE_UPLOAD: + repeat = 1; + msec_rate = 2000; /* should be download rate dependent */ + break; + } + + + if (repeat) + { +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::updateItem() callback for update!"; + std::cerr << std::endl; +#endif + QTimer::singleShot( msec_rate, this, SLOT(updateItem( void ) )); + } + +} + + + + +void SubFileItem::smaller() +{ +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::cancel()"; + std::cerr << std::endl; +#endif + +#if 0 + expandFrame->hide(); +#endif +} + +void SubFileItem::toggle() +{ +#if 0 + if (expandFrame->isHidden()) + { + expandFrame->show(); + } + else + { + expandFrame->hide(); + } +#endif +} + +void SubFileItem::cancel() +{ +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::cancel()"; + std::cerr << std::endl; +#endif + //set the state to error mode + mMode = SFI_STATE_ERROR; + + /* Only occurs - if it is downloading */ + if ((mType == SFI_TYPE_ATTACH) || (mType == SFI_TYPE_CHANNEL)) + { + hide(); + rsFiles->ExtraFileRemove(FileHash(), RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_EXTRA); + mPath = ""; + } + else + { + rsFiles->FileCancel(mFileHash); + } + + updateItem(); +} + + +void SubFileItem::play() +{ + FileInfo info; + uint32_t flags = RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_NETWORK_WIDE; + + + if (!rsFiles->FileDetails( mFileHash, flags, info)) + return; + + if (done()) { + + /* open file with a suitable application */ + QFileInfo qinfo; + qinfo.setFile(info.path.c_str()); + if (qinfo.exists()) { + if (!QDesktopServices::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath()))) { + std::cerr << "openTransfer(): can't open file " << info.path << std::endl; + } + }else{ + QMessageBox::information(this, tr("Play File"), + tr("File %1 does not exist at location.").arg(info.path.c_str())); + return; + } + } else { + /* rise a message box for incompleted download file */ + QMessageBox::information(this, tr("Play File"), + tr("File %1 is not completed.").arg(info.fname.c_str())); + return; + } + +} + +void SubFileItem::download() +{ +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::download()"; + std::cerr << std::endl; +#endif + + if (mType == SFI_TYPE_CHANNEL) + { + /* send request via rsChannels -> as it knows how to do it properly */ + //std::string grpId = mSrcId; + //rsChannels->FileRequest(mFileName, mFileHash, mFileSize, grpId); + } + else + { + //rsFile->FileRequest(mFileName, mFileHash, mFileSize, "", 0, mSrcId); + } + + // TEMP + std::cerr << "SubFileItem::download() Calling File Request"; + std::cerr << std::endl; + std::list srcIds; + if (mSrcId != "") + { + srcIds.push_back(mSrcId); + } + rsFiles->FileRequest(mFileName, mFileHash, mFileSize, "", RS_FILE_HINTS_NETWORK_WIDE, srcIds); + + downloadButton->setEnabled(false); + + updateItem(); +} + + +void SubFileItem::save() +{ +#ifdef DEBUG_ITEM + std::cerr << "SubFileItem::save()"; + std::cerr << std::endl; +#endif + + FileInfo fInfo; + + if (mType == SFI_TYPE_CHANNEL) + { + /* only enable these function for Channels. */ + + /* find out where they want to save it */ + QString startpath = ""; + QString dir = QFileDialog::getExistingDirectory(this, tr("Save Channel File"), + startpath, + QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks); + + std::string destpath = dir.toStdString(); + + if (destpath != "") + { + bool copied = rsFiles->ExtraFileMove(mFileName, mFileHash, mFileSize, destpath); + + // may be manually downloaded channel file + if(!copied){ + rsFiles->FileDetails(mFileHash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_EXTRA, fInfo); + + if(fInfo.path != "") + { + + destpath += "/" + fInfo.fname; + rsFiles->CopyFile(fInfo.path, destpath); + } + } + } + } + else + { + } +} + +uint32_t SubFileItem::getState() { + return mMode; +} + +bool SubFileItem::isDownloadable(bool &startable) +{ + /* Check buttons. Not good, but it works. */ + bool visible = downloadButton->isVisibleTo(this); + startable = visible && downloadButton->isEnabled(); + + return visible; +} + +bool SubFileItem::isPlayable(bool &startable) +{ + /* Check buttons. Not good, but it works. */ + bool visible = playButton->isVisibleTo(this); + startable = visible && playButton->isEnabled(); + + return visible; +} + diff --git a/retroshare-gui/src/gui/feeds/SubFileItem.h b/retroshare-gui/src/gui/feeds/SubFileItem.h new file mode 100644 index 000000000..e6df56157 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/SubFileItem.h @@ -0,0 +1,113 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _SUB_FILE_ITEM_DIALOG_H +#define _SUB_FILE_ITEM_DIALOG_H + +#include "ui_SubFileItem.h" +#include +const uint32_t SFI_MASK_STATE = 0x000f; +const uint32_t SFI_MASK_TYPE = 0x00f0; +const uint32_t SFI_MASK_FT = 0x0f00; + +const uint32_t SFI_STATE_ERROR = 0x0001; +const uint32_t SFI_STATE_EXTRA = 0x0002; +const uint32_t SFI_STATE_REMOTE = 0x0003; +const uint32_t SFI_STATE_DOWNLOAD = 0x0004; +const uint32_t SFI_STATE_LOCAL = 0x0005; +const uint32_t SFI_STATE_UPLOAD = 0x0006; + +const uint32_t SFI_TYPE_CHANNEL = 0x0010; +const uint32_t SFI_TYPE_ATTACH = 0x0020; + + +//! This create a gui widget that allows users to access files shared by user +/*! + * Widget that allows user to share files with a visual attachment interface + * Note: extra files (files not already shared/hashed in rs) need to + * be hashed by the clients of this class or else objects of this class will + * have reduced functionality + */ +class SubFileItem : public QWidget, private Ui::SubFileItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + SubFileItem(const std::string &hash, const std::string &name, const std::string &path, uint64_t size, uint32_t flags, const std::string &srcId); + + /** Default Destructor */ + + void smaller(); + + std::string FileHash() { return mFileHash; } + std::string FileName() { return mFileName; } + uint64_t FileSize() { return mFileSize; } + std::string FilePath() { return mPath; } + + void updateItemStatic(); + + bool done(); + bool ready(); + uint32_t getState(); + + bool isDownloadable(bool &startable); + bool isPlayable(bool &startable); + +public slots: + void download(); + void play(); + +private slots: + void toggle(); + + void cancel(); + void save(); + + void updateItem(); + +private: + + void Setup(); + + + std::string mPath; + std::string mFileHash; + std::string mFileName; + uint64_t mFileSize; + std::string mSrcId; + + uint32_t mMode; + uint32_t mType; + uint64_t mDivisor; + + /* for display purposes */ + float amountDone; + +signals: + void fileFinished(SubFileItem * subFileItem); + +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/feeds/SubFileItem.ui b/retroshare-gui/src/gui/feeds/SubFileItem.ui new file mode 100644 index 000000000..78d5093c3 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/SubFileItem.ui @@ -0,0 +1,294 @@ + + + SubFileItem + + + + 0 + 0 + 464 + 122 + + + + + 0 + 0 + + + + + + + QWidget#SubFileItem{border: none;} + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 122 + + + + QFrame#frame{border: 2px solid #238; +background: white; +border-radius: 10px;} + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 75 + true + true + PreferAntialias + + + + File Name + + + false + + + + + + + + + + + + 0 + 0 + + + + + 50 + 26 + + + + QProgressBar { +border: 1px solid black; +text-align: center; +color: white; +padding: 1px; +border-top-left-radius: 7px; +border-bottom-left-radius: 7px; +background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, +stop: 0 #fff, +stop: 0.4999 #eee, +stop: 0.5 #ddd, +stop: 1 #eee ); +width: 15px; +} +QProgressBar::chunk { +background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0, +stop: 0 #78d, +stop: 0.4999 #46a, +stop: 0.5 #45a, +stop: 1 #238 ); +border-top-left-radius: 7px; +border-bottom-left-radius: 7px; +border: 1px solid black; +} + + + 24 + + + Qt::Horizontal + + + %p Kb + + + + + + + + 0 + 0 + + + + + 0 + 26 + + + + Cancel Download + + + + + + + :/images/delete.png:/images/delete.png + + + + + + + + 0 + 0 + + + + + 0 + 26 + + + + Download File + + + Download + + + + :/images/download.png:/images/download.png + + + + + + + + 0 + 0 + + + + + 0 + 26 + + + + Play File + + + Play + + + + :/images/player_play.png:/images/player_play.png + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 418 + 17 + + + + + + + + + 0 + 0 + + + + + 0 + 26 + + + + Save File + + + + + + + :/images/save24.png:/images/save24.png + + + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/forums/CreateForum.cpp b/retroshare-gui/src/gui/forums/CreateForum.cpp new file mode 100644 index 000000000..4b0c28541 --- /dev/null +++ b/retroshare-gui/src/gui/forums/CreateForum.cpp @@ -0,0 +1,113 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "util/misc.h" + +#include "CreateForum.h" + +#include + +/** Constructor */ +CreateForum::CreateForum(QWidget *parent) +: QDialog(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + // connect up the buttons. + connect( ui.cancelButton, SIGNAL( clicked ( bool ) ), this, SLOT( cancelForum( ) ) ); + connect( ui.createButton, SIGNAL( clicked ( bool ) ), this, SLOT( createForum( ) ) ); + + newForum(); +} + +void CreateForum::newForum() +{ + /* enforce Public for the moment */ + ui.typePublic->setChecked(true); + + ui.typePrivate->setEnabled(false); + ui.typeEncrypted->setEnabled(false); + +#ifdef RS_RELEASE_VERSION + ui.typePrivate->setVisible(false); + ui.typeEncrypted->setVisible(false); +#endif + + ui.msgAnon->setChecked(true); + //ui.msgAuth->setEnabled(false); + + ui.forumName->clear(); + ui.forumDesc->clear(); +} + +void CreateForum::createForum() +{ + QString name = misc::removeNewLine(ui.forumName->text()); + QString desc = ui.forumDesc->toPlainText(); //toHtml(); + uint32_t flags = 0; + + if(name.isEmpty()) + { /* error message */ + QMessageBox::warning(this, "RetroShare", + tr("Please add a Name"), + QMessageBox::Ok, QMessageBox::Ok); + return; //Don't add a empty name!! + } + else + + if (ui.typePublic->isChecked()) + { + flags |= RS_DISTRIB_PUBLIC; + } + else if (ui.typePrivate->isChecked()) + { + flags |= RS_DISTRIB_PRIVATE; + } + else if (ui.typeEncrypted->isChecked()) + { + flags |= RS_DISTRIB_ENCRYPTED; + } + + if (ui.msgAuth->isChecked()) + { + flags |= RS_DISTRIB_AUTHEN_REQ; + } + else if (ui.msgAnon->isChecked()) + { + flags |= RS_DISTRIB_AUTHEN_ANON; + } + + if (rsForums) + { + rsForums->createForum(name.toStdWString(), desc.toStdWString(), flags); + } + + close(); +} + + +void CreateForum::cancelForum() +{ + close(); +} diff --git a/retroshare-gui/src/gui/forums/CreateForum.h b/retroshare-gui/src/gui/forums/CreateForum.h new file mode 100644 index 000000000..a439ca121 --- /dev/null +++ b/retroshare-gui/src/gui/forums/CreateForum.h @@ -0,0 +1,51 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _CREATE_FORUM_DIALOG_H +#define _CREATE_FORUM_DIALOG_H + +#include "ui_CreateForum.h" + +class CreateForum : public QDialog +{ + Q_OBJECT + +public: + CreateForum(QWidget *parent = 0); + +void newForum(); /* cleanup */ + + /** Qt Designer generated object */ + Ui::CreateForum ui; + + QPixmap picture; + +private slots: + + /* actions to take.... */ +void createForum(); +void cancelForum(); + +}; + +#endif + diff --git a/retroshare-gui/src/gui/forums/CreateForum.ui b/retroshare-gui/src/gui/forums/CreateForum.ui new file mode 100644 index 000000000..636e7b037 --- /dev/null +++ b/retroshare-gui/src/gui/forums/CreateForum.ui @@ -0,0 +1,244 @@ + + + CreateForum + + + + 0 + 0 + 500 + 424 + + + + Create new Forum + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + 0 + + + + + + 16777215 + 64 + + + + QFrame#frame_2{background-image: url(:/images/connect/connectFriendBanner.png);} + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 6 + + + + + + 48 + 48 + + + + + + + + + + :/images/konversation64.png + + + true + + + + + + + color: rgb(255, 255, 255); + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + Name + + + + + + + + + + + + + + Description + + + + + + + + + + + + Type: + + + + 0 + + + 6 + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + + + Private - (Private Publish Key required to view Messages) + + + + + + + + + + Allowed Messages + + + + 0 + + + 6 + + + + + Authenticated Messages + + + + + + + Anonymous Messages + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Qt::Horizontal + + + + 238 + 20 + + + + + + + + Cancel + + + + + + + Create + + + true + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/forums/CreateForumMsg.cpp b/retroshare-gui/src/gui/forums/CreateForumMsg.cpp new file mode 100644 index 000000000..7fd60c099 --- /dev/null +++ b/retroshare-gui/src/gui/forums/CreateForumMsg.cpp @@ -0,0 +1,341 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "CreateForumMsg.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include "gui/settings/rsharesettings.h" +#include "gui/RetroShareLink.h" +#include "gui/feeds/AttachFileItem.h" +#include "gui/common/Emoticons.h" + +#include "util/misc.h" + +#include + + +/** Constructor */ +CreateForumMsg::CreateForumMsg(std::string fId, std::string pId) +: QMainWindow(NULL), mForumId(fId), mParentId(pId) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + + Settings->loadWidgetInformation(this); + + connect( ui.forumMessage, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( forumMessageCostumPopupMenu( QPoint ) ) ); + + // connect up the buttons. + connect( ui.postmessage_action, SIGNAL( triggered (bool) ), this, SLOT( createMsg( ) ) ); + connect( ui.close_action, SIGNAL( triggered (bool) ), this, SLOT( cancelMsg( ) ) ); + connect( ui.emoticonButton, SIGNAL(clicked()), this, SLOT(smileyWidgetForums())); + connect( ui.attachFileButton, SIGNAL(clicked() ), this , SLOT(addFile())); + connect( ui.pastersButton, SIGNAL(clicked() ), this , SLOT(pasteLink())); + + setAcceptDrops(true); + + newMsg(); +} + +/** context menu searchTablewidget2 **/ +void CreateForumMsg::forumMessageCostumPopupMenu( QPoint point ) +{ + QMenu *contextMnu = ui.forumMessage->createStandardContextMenu(); + + contextMnu->addSeparator(); + QAction *pasteLinkAct = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink())); + QAction *pasteLinkFullAct = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste full RetroShare Link"), this, SLOT(pasteLinkFull())); + + if (RSLinkClipboard::empty()) { + pasteLinkAct->setDisabled (true); + pasteLinkFullAct->setDisabled (true); + } + + contextMnu->exec(QCursor::pos()); + delete(contextMnu); +} + +void CreateForumMsg::newMsg() +{ + /* clear all */ + ForumInfo fi; + if (rsForums->getForumInfo(mForumId, fi)) + { + ForumMsgInfo msg; + + QString name = QString::fromStdWString(fi.forumName); + QString subj; + if ((mParentId != "") && (rsForums->getForumMessage(mForumId, mParentId, msg))) + { + QString title = QString::fromStdWString(msg.title); + name += " " + tr("In Reply to") + ": "; + name += title; + + QString text = title; + + if (text.startsWith("Re:", Qt::CaseInsensitive)) + { + subj = title; + } + else + { + subj = "Re: " + title; + } + + } + + ui.forumName->setText(misc::removeNewLine(name)); + ui.forumSubject->setText(misc::removeNewLine(subj)); + + if (!ui.forumSubject->text().isEmpty()) + { + ui.forumMessage->setFocus(); + } + else + { + ui.forumSubject->setFocus(); + } + + if (fi.forumFlags & RS_DISTRIB_AUTHEN_REQ) + { + ui.signBox->setChecked(true); + ui.signBox->setEnabled(false); + } + else + { + /* Uncheck sign box by default for anonymous forums */ + ui.signBox->setChecked(false); + ui.signBox->setEnabled(true); + } + } + + ui.forumMessage->setText(""); +} + +void CreateForumMsg::createMsg() +{ + QString name = misc::removeNewLine(ui.forumSubject->text()); + QString desc = ui.forumMessage->toHtml(); + + if(desc == QTextDocument(ui.forumMessage->toPlainText()).toHtml()) + desc = ui.forumMessage->toPlainText() ; + + if(name.isEmpty()) + { /* error message */ + QMessageBox::warning(this, tr("RetroShare"),tr("Please set a Forum Subject and Forum Message"), + QMessageBox::Ok, QMessageBox::Ok); + + return; //Don't add a empty Subject!! + } + + ForumMsgInfo msgInfo; + + msgInfo.forumId = mForumId; + msgInfo.threadId = ""; + msgInfo.parentId = mParentId; + msgInfo.msgId = ""; + + msgInfo.title = name.toStdWString(); + msgInfo.msg = desc.toStdWString(); + msgInfo.msgflags = 0; + + if (ui.signBox->isChecked()) + { + msgInfo.msgflags = RS_DISTRIB_AUTHEN_REQ; + } + + if ((msgInfo.msg == L"") && (msgInfo.title == L"")) + return; /* do nothing */ + + if (rsForums->ForumMessageSend(msgInfo) == true) { + close(); + } +} + +void CreateForumMsg::closeEvent (QCloseEvent * event) +{ + Settings->saveWidgetInformation(this); +} + +void CreateForumMsg::cancelMsg() +{ + close(); +} + +void CreateForumMsg::smileyWidgetForums() +{ + Emoticons::showSmileyWidget(this, ui.emoticonButton, SLOT(addSmileys()), false); +} + +void CreateForumMsg::addSmileys() +{ + ui.forumMessage->textCursor().insertText(qobject_cast(sender())->toolTip().split("|").first()); +} + +void CreateForumMsg::addFile() +{ + QStringList files; + if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { + for (QStringList::iterator fileIt = files.begin(); fileIt != files.end(); fileIt++) { + addAttachment((*fileIt).toUtf8().constData()); + } + } +} + +void CreateForumMsg::addAttachment(std::string filePath) { + /* add a AttachFileItem to the attachment section */ + std::cerr << "CreateForumMsg::addFile() hashing file."; + std::cerr << std::endl; + + /* add widget in for new destination */ + AttachFileItem *file = new AttachFileItem(filePath); + //file-> + + ui.verticalLayout->addWidget(file, 1, 0); + + //when the file is local or is finished hashing, call the fileHashingFinished method to send a forum message + if (file->getState() == AFI_STATE_LOCAL) { + fileHashingFinished(file); + } else { + QObject::connect(file,SIGNAL(fileFinished(AttachFileItem *)),this, SLOT(fileHashingFinished(AttachFileItem *))) ; + } +} + +void CreateForumMsg::fileHashingFinished(AttachFileItem* file) { + std::cerr << "CreateForumMsg::fileHashingFinished() started."; + std::cerr << std::endl; + + //check that the file is ok tos end + if (file->getState() == AFI_STATE_ERROR) { + #ifdef CHAT_DEBUG + std::cerr << "CreateForumMsg::fileHashingFinished error file is not hashed."; + #endif + return; + } + + RetroShareLink link; + if (link.createFile(QString::fromUtf8(file->FileName().c_str()), file->FileSize(), QString::fromStdString(file->FileHash()))) { + QString mesgString = link.toHtmlSize() + "
    "; + +#ifdef CHAT_DEBUG + std::cerr << "CreateForumMsg::anchorClicked mesgString : " << mesgString.toStdString() << std::endl; +#endif + + ui.forumMessage->textCursor().insertHtml(mesgString); + + ui.forumMessage->setFocus( Qt::OtherFocusReason ); + } +} + +void CreateForumMsg::dropEvent(QDropEvent *event) +{ + if (!(Qt::CopyAction & event->possibleActions())) + { + std::cerr << "CreateForumMsg::dropEvent() Rejecting uncopyable DropAction" << std::endl; + + /* can't do it */ + return; + } + + std::cerr << "CreateForumMsg::dropEvent() Formats" << std::endl; + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) + { + std::cerr << "Format: " << (*it).toStdString() << std::endl; + } + + if (event->mimeData()->hasUrls()) + { + std::cerr << "CreateForumMsg::dropEvent() Urls:" << std::endl; + + QList urls = event->mimeData()->urls(); + QList::iterator uit; + for(uit = urls.begin(); uit != urls.end(); uit++) + { + QString localpath = uit->toLocalFile(); + std::cerr << "Whole URL: " << uit->toString().toStdString() << std::endl; + std::cerr << "or As Local File: " << localpath.toStdString() << std::endl; + + if (localpath.isEmpty() == false) + { + // Check that the file does exist and is not a directory + QDir dir(localpath); + if (dir.exists()) { + std::cerr << "CreateForumMsg::dropEvent() directory not accepted."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("Directory can't be dropped, only files are accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } else if (QFile::exists(localpath)) { + addAttachment(localpath.toUtf8().constData()); + } else { + std::cerr << "CreateForumMsg::dropEvent() file does not exists."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("File not found or file name not accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } + } + } + } + + event->setDropAction(Qt::CopyAction); + event->accept(); +} + +void CreateForumMsg::dragEnterEvent(QDragEnterEvent *event) +{ + /* print out mimeType */ + std::cerr << "CreateForumMsg::dragEnterEvent() Formats" << std::endl; + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) + { + std::cerr << "Format: " << (*it).toStdString() << std::endl; + } + + if (event->mimeData()->hasUrls()) + { + std::cerr << "CreateForumMsg::dragEnterEvent() Accepting Urls" << std::endl; + event->acceptProposedAction(); + } + else + { + std::cerr << "CreateForumMsg::dragEnterEvent() No Urls" << std::endl; + } +} + +void CreateForumMsg::pasteLink() +{ + ui.forumMessage->insertHtml(RSLinkClipboard::toHtml()) ; +} + +void CreateForumMsg::pasteLinkFull() +{ + ui.forumMessage->insertHtml(RSLinkClipboard::toHtmlFull()) ; +} + diff --git a/retroshare-gui/src/gui/forums/CreateForumMsg.h b/retroshare-gui/src/gui/forums/CreateForumMsg.h new file mode 100644 index 000000000..6e3f34de1 --- /dev/null +++ b/retroshare-gui/src/gui/forums/CreateForumMsg.h @@ -0,0 +1,70 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _CREATE_FORUM_MSG_DIALOG_H +#define _CREATE_FORUM_MSG_DIALOG_H + +#include "ui_CreateForumMsg.h" + +class AttachFileItem; + +class CreateForumMsg : public QMainWindow +{ + Q_OBJECT + +public: + CreateForumMsg(std::string fId, std::string pId); + + void newMsg(); /* cleanup */ + +private slots: + /** Create the context popup menu and it's submenus */ + void forumMessageCostumPopupMenu( QPoint point ); + + void fileHashingFinished(AttachFileItem* file); + /* actions to take.... */ + void createMsg(); + void cancelMsg(); + void pasteLink(); + void pasteLinkFull(); + + void smileyWidgetForums(); + void addSmileys(); + void addFile(); + void addAttachment(std::string); + +protected: + void closeEvent (QCloseEvent * event); + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); + + +private: + std::string mForumId; + std::string mParentId; + + /** Qt Designer generated object */ + Ui::CreateForumMsg ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/forums/CreateForumMsg.ui b/retroshare-gui/src/gui/forums/CreateForumMsg.ui new file mode 100644 index 000000000..8e327f39c --- /dev/null +++ b/retroshare-gui/src/gui/forums/CreateForumMsg.ui @@ -0,0 +1,350 @@ + + + CreateForumMsg + + + Qt::NonModal + + + + 0 + 0 + 482 + 448 + + + + Post Forum Message + + + + :/images/rstray3.png:/images/rstray3.png + + + QToolBar#toolBar{background-image: url(:/images/connect/connectFriendBanner.png)} + + + Qt::ToolButtonTextUnderIcon + + + + + 0 + + + 0 + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 6 + + + + + + + Forum + + + + + + + false + + + + + + + + + + + Subject + + + + + + + + + + + + + + + + 16777215 + 38 + + + + QFrame#frame_2{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::Raised + + + + 6 + + + + + Qt::NoFocus + + + Attach File + + + + + + + :/images/add-share24.png:/images/add-share24.png + + + + 24 + 24 + + + + true + + + + + + + Qt::NoFocus + + + + + + + :/images/emoticons/kopete/kopete020.png:/images/emoticons/kopete/kopete020.png + + + + 24 + 24 + + + + true + + + + + + + Qt::NoFocus + + + Sign Message + + + + :/images/pgp.png:/images/pgp.png + + + + 24 + 24 + + + + true + + + + + + + Qt::Horizontal + + + + 40 + 15 + + + + + + + + Qt::NoFocus + + + Paste RetroShare Link + + + + + + + :/images/pasterslink.png:/images/pasterslink.png + + + true + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 6 + + + + + Forum Post + + + + + + Qt::CustomContextMenu + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + + + + + + Attach files via drag and drop + + + + + + You can attach files via drag and drop here in this window + + + true + + + + + 0 + 0 + 440 + 57 + + + + + 0 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + :/images/mail_send24.png:/images/mail_send24.png + + + Post Forum Msg + + + + + + :/images/button_cancel.png:/images/button_cancel.png + + + Close + + + + + + + + diff --git a/retroshare-gui/src/gui/forums/EditForumDetails.cpp b/retroshare-gui/src/gui/forums/EditForumDetails.cpp new file mode 100644 index 000000000..87221b6f0 --- /dev/null +++ b/retroshare-gui/src/gui/forums/EditForumDetails.cpp @@ -0,0 +1,81 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "EditForumDetails.h" + +#include + +#include "util/misc.h" + +#include +#include +#include + + +/** Default constructor */ +EditForumDetails::EditForumDetails(std::string forumId, QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags), m_forumId(forumId) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyDialog())); + + loadForum(); +} + +void EditForumDetails::loadForum() +{ + if (!rsForums) { + return; + } + + ForumInfo info; + rsForums->getForumInfo(m_forumId, info); + + // set name + ui.nameline->setText(QString::fromStdWString(info.forumName)); + + // set description + ui.DescriptiontextEdit->setText(QString::fromStdWString(info.forumDesc)); +} + +void EditForumDetails::applyDialog() +{ + if (!rsForums) { + return; + } + + // if text boxes have not been edited leave alone + if (!ui.nameline->isModified() && !ui.DescriptiontextEdit->document()->isModified()) { + return; + } + + ForumInfo info; + + info.forumName = misc::removeNewLine(ui.nameline->text()).toStdWString(); + info.forumDesc = ui.DescriptiontextEdit->document()->toPlainText().toStdWString(); + + rsForums->setForumInfo(m_forumId, info); + + /* close the Dialog after the Changes applied */ + close(); +} diff --git a/retroshare-gui/src/gui/forums/EditForumDetails.h b/retroshare-gui/src/gui/forums/EditForumDetails.h new file mode 100644 index 000000000..17e700a77 --- /dev/null +++ b/retroshare-gui/src/gui/forums/EditForumDetails.h @@ -0,0 +1,53 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _EDITFORUMDETAILS_H +#define _EDITFORUMDETAILS_H + +#include + +#include "ui_EditForumDetails.h" + +class EditForumDetails : public QDialog +{ + Q_OBJECT + +public: + /** Default constructor */ + EditForumDetails(std::string forumId = "", QWidget *parent = 0, Qt::WFlags flags = 0); + +signals: + void configChanged(); + +private slots: + void applyDialog(); + +private: + void loadForum(); + + std::string m_forumId; + + /** Qt Designer generated object */ + Ui::EditForumDetails ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/forums/EditForumDetails.ui b/retroshare-gui/src/gui/forums/EditForumDetails.ui new file mode 100644 index 000000000..e5cdb8992 --- /dev/null +++ b/retroshare-gui/src/gui/forums/EditForumDetails.ui @@ -0,0 +1,130 @@ + + + EditForumDetails + + + + 0 + 0 + 436 + 355 + + + + Forum Details + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + + + Qt::Horizontal + + + + 311 + 20 + + + + + + + + Cancel + + + + + + + OK + + + false + + + true + + + + + + + + + 0 + + + + + :/images/info16.png:/images/info16.png + + + Edit Forum Details + + + + + + Forum Info + + + + + + Forum Name + + + + + + + + + + Forum Description + + + + + + + + + + + + + + + + + + + + + + + cancelButton + clicked() + EditForumDetails + close() + + + 307 + 333 + + + 217 + 177 + + + + + diff --git a/retroshare-gui/src/gui/forums/ForumDetails.cpp b/retroshare-gui/src/gui/forums/ForumDetails.cpp new file mode 100644 index 000000000..6f5fc3a96 --- /dev/null +++ b/retroshare-gui/src/gui/forums/ForumDetails.cpp @@ -0,0 +1,143 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include "ForumDetails.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +/* Define the format used for displaying the date and time */ +#define DATETIME_FMT "MMM dd hh:mm:ss" + +/** Default constructor */ +ForumDetails::ForumDetails(QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyDialog())); + connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(closeinfodlg())); + + ui.applyButton->setToolTip(tr("Apply and Close")); + + ui.nameline ->setReadOnly(true); + ui.popline ->setReadOnly(true); + ui.postline ->setReadOnly(true); + ui.IDline ->setReadOnly(true); + ui.DescriptiontextEdit ->setReadOnly(true); + + ui.radioButton_authd->setEnabled(false); + ui.radioButton_anonymous->setEnabled(false); +} + + +/** + Overloads the default show() slot so we can set opacity*/ + +void +ForumDetails::show() +{ + //loadSettings(); + if(!this->isVisible()) { + QDialog::show(); + + } +} + +void ForumDetails::closeEvent (QCloseEvent * event) +{ + QWidget::closeEvent(event); +} + +void ForumDetails::closeinfodlg() +{ + close(); +} + +void ForumDetails::showDetails(std::string mCurrForumId) +{ + fId = mCurrForumId; + loadDialog(); +} + +void ForumDetails::loadDialog() +{ + if (!rsForums) + { + return; + } + + ForumInfo fi; + rsForums->getForumInfo(fId, fi); + + // Set Forum Name + ui.nameline->setText(QString::fromStdWString(fi.forumName)); + + // Set Popularity + ui.popline->setText(QString::number(fi.pop)); + + // Set Last Post Date + if (fi.lastPost) { + QDateTime qtime; + qtime.setTime_t(fi.lastPost); + QString timestamp = qtime.toString("yyyy-MM-dd hh:mm:ss"); + ui.postline->setText(timestamp); + } + + // Set Forum ID + ui.IDline->setText(QString::fromStdString(fi.forumId)); + + // Set Forum Description + ui.DescriptiontextEdit->setText(QString::fromStdWString(fi.forumDesc)); + + if (fi.forumFlags & RS_DISTRIB_AUTHEN_REQ) + { + ui.radioButton_authd->setChecked(true); + ui.radioButton_anonymous->setChecked(false); + } + if (fi.forumFlags & RS_DISTRIB_AUTHEN_ANON) + { + ui.radioButton_authd->setChecked(false); + ui.radioButton_anonymous->setChecked(true); + } +} + +void ForumDetails::applyDialog() +{ + + /* reload now */ + loadDialog(); + + /* close the Dialog after the Changes applied */ + closeinfodlg(); + +} diff --git a/retroshare-gui/src/gui/forums/ForumDetails.h b/retroshare-gui/src/gui/forums/ForumDetails.h new file mode 100644 index 000000000..26d294d8f --- /dev/null +++ b/retroshare-gui/src/gui/forums/ForumDetails.h @@ -0,0 +1,67 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _FORUMDETAILS_H +#define _FORUMDETAILS_H + +#include + +#include "ui_ForumDetails.h" + +class ForumDetails : public QDialog +{ + Q_OBJECT + + public: + + /** Default constructor */ + ForumDetails(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + + void showDetails(std::string mCurrForumId); + +signals: + void configChanged() ; + +public slots: + /** Overloaded QWidget.show */ + void show(); + +protected: + void closeEvent (QCloseEvent * event); + +private slots: + + void closeinfodlg(); + void applyDialog(); + +private: + + void loadDialog(); + + std::string fId; + /** Qt Designer generated object */ + Ui::ForumDetails ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/forums/ForumDetails.ui b/retroshare-gui/src/gui/forums/ForumDetails.ui new file mode 100644 index 000000000..190451ae3 --- /dev/null +++ b/retroshare-gui/src/gui/forums/ForumDetails.ui @@ -0,0 +1,201 @@ + + + ForumDetails + + + + 0 + 0 + 436 + 355 + + + + Forum Details + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + 0 + + + + + :/images/info16.png:/images/info16.png + + + Forum Details + + + + + + Forum Info + + + + + + Forum Name + + + + + + + + + + Popularity + + + + + + + true + + + + + + + Last Post + + + + + + + true + + + + + + + Forum ID + + + + + + + + + + Forum Description + + + + + + + + + + + + + + + + + :/images/encrypted22.png:/images/encrypted22.png + + + Security + + + + + + Allowed Messages + + + + + + Authemticated Messages + + + + + + + Anonymous Messages + + + true + + + + + + + + + + Qt::Vertical + + + + 358 + 172 + + + + + + + + + + + + + + Qt::Horizontal + + + + 311 + 20 + + + + + + + + Cancel + + + + + + + OK + + + false + + + true + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/graphframe.cpp b/retroshare-gui/src/gui/graphframe.cpp new file mode 100644 index 000000000..772555b0b --- /dev/null +++ b/retroshare-gui/src/gui/graphframe.cpp @@ -0,0 +1,302 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + + +#include + +#include "graphframe.h" + + +/** Default contructor */ +GraphFrame::GraphFrame(QWidget *parent) +: QFrame(parent) +{ + /* Create Graph Frame related objects */ + _recvData = new QList(); + _sendData = new QList(); + _painter = new QPainter(); + _graphStyle = SolidLine; + + /* Initialize graph values */ + _recvData->prepend(0); + _sendData->prepend(0); + _maxPoints = getNumPoints(); + _showRecv = true; + _showSend = true; + _maxValue = MIN_SCALE; +} + +/** Default destructor */ +GraphFrame::~GraphFrame() +{ + delete _painter; + delete _recvData; + delete _sendData; +} + +/** Gets the width of the desktop, which is the maximum number of points + * we can plot in the graph. */ +int +GraphFrame::getNumPoints() +{ + QDesktopWidget *desktop = QApplication::desktop(); + int width = desktop->width(); + return width; +} + +/** Adds new data points to the graph. */ +void +GraphFrame::addPoints(qreal recv, qreal send) +{ + /* If maximum number of points plotted, remove oldest */ + if (_sendData->size() == _maxPoints) { + _sendData->removeLast(); + _recvData->removeLast(); + } + + /* Add the points to their respective lists */ + _sendData->prepend(send); + _recvData->prepend(recv); + + /* Add to the total counters */ + _totalSend += send; + _totalRecv += recv; + + /* Check for a new maximum value */ + if (send > _maxValue) _maxValue = send; + if (recv > _maxValue) _maxValue = recv; + + this->update(); +} + +/** Clears the graph. */ +void +GraphFrame::resetGraph() +{ + _recvData->clear(); + _sendData->clear(); + _recvData->prepend(0); + _sendData->prepend(0); + _maxValue = MIN_SCALE; + _totalSend = 0; + _totalRecv = 0; + this->update(); +} + +/** Toggles display of respective graph lines and counters. */ +void +GraphFrame::setShowCounters(bool showRecv, bool showSend) +{ + _showRecv = showRecv; + _showSend = showSend; + this->update(); +} + +/** Overloads default QWidget::paintEvent. Draws the actual + * bandwidth graph. */ +void +GraphFrame::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + + /* Set current graph dimensions */ + _rec = this->frameRect(); + + /* Start the painter */ + _painter->begin(this); + + /* We want antialiased lines and text */ + _painter->setRenderHint(QPainter::Antialiasing); + _painter->setRenderHint(QPainter::TextAntialiasing); + + /* Fill in the background */ + _painter->fillRect(_rec, QBrush(BACK_COLOR)); + _painter->drawRect(_rec); + + /* Paint the scale */ + paintScale(); + /* Plot the send/receive data */ + paintData(); + /* Paint the send/recv totals */ + paintTotals(); + + /* Stop the painter */ + _painter->end(); +} + +/** Paints an integral and an outline of that integral for each data set (send + * and/or receive) that is to be displayed. The integrals will be drawn first, + * followed by the outlines, since we want the area of overlapping integrals + * to blend, but not the outlines of those integrals. */ +void +GraphFrame::paintData() +{ + QVector recvPoints, sendPoints; + + /* Convert the bandwidth data points to graph points */ + recvPoints = pointsFromData(_recvData); + sendPoints = pointsFromData(_sendData); + + if (_graphStyle == AreaGraph) { + /* Plot the bandwidth data as area graphs */ + if (_showRecv) + paintIntegral(recvPoints, RECV_COLOR, 0.6); + if (_showSend) + paintIntegral(sendPoints, SEND_COLOR, 0.4); + } + + /* Plot the bandwidth as solid lines. If the graph style is currently an + * area graph, we end up outlining the integrals. */ + if (_showRecv) + paintLine(recvPoints, RECV_COLOR); + if (_showSend) + paintLine(sendPoints, SEND_COLOR); +} + +/** Returns a list of points on the bandwidth graph based on the supplied set + * of send or receive values. */ +QVector +GraphFrame::pointsFromData(QList* list) +{ + QVector points; + int x = _rec.width(); + int y = _rec.height(); + qreal scale = (y - (y/10)) / _maxValue; + qreal currValue; + + /* Translate all data points to points on the graph frame */ + points << QPointF(x, y); + for (int i = 0; i < list->size(); i++) { + currValue = y - (list->at(i) * scale); + if (x - SCROLL_STEP < SCALE_WIDTH) { + points << QPointF(SCALE_WIDTH, currValue); + break; + } + points << QPointF(x, currValue); + x -= SCROLL_STEP; + } + points << QPointF(SCALE_WIDTH, y); + return points; +} + +/** Plots an integral using the data points in points. The area will be + * filled in using color and an alpha-blending level of alpha + * (default is opaque). */ +void +GraphFrame::paintIntegral(QVector points, QColor color, qreal alpha) +{ + /* Save the current brush, plot the integral, and restore the old brush */ + QBrush oldBrush = _painter->brush(); + color.setAlphaF(alpha); + _painter->setBrush(QBrush(color)); + _painter->drawPolygon(points.data(), points.size()); + _painter->setBrush(oldBrush); +} + +/** Iterates the input list and draws a line on the graph in the appropriate + * color. */ +void +GraphFrame::paintLine(QVector points, QColor color, Qt::PenStyle lineStyle) +{ + /* Save the current brush, plot the line, and restore the old brush */ + QPen oldPen = _painter->pen(); + _painter->setPen(QPen(color, lineStyle)); + _painter->drawPolyline(points.data(), points.size()); + _painter->setPen(oldPen); +} + +/** Paints selected total indicators on the graph. */ +void +GraphFrame::paintTotals() +{ + int x = SCALE_WIDTH + FONT_SIZE, y = 0; + int rowHeight = FONT_SIZE; + +#if !defined(Q_WS_MAC) + /* On Mac, we don't need vertical spacing between the text rows. */ + rowHeight += 5; +#endif + + /* If total received is selected */ + if (_showRecv) { + y = rowHeight; + _painter->setPen(RECV_COLOR); + _painter->drawText(x, y, + tr("Recv: ") + totalToStr(_totalRecv) + + " ("+tr("%1 KB/s").arg(_recvData->first(), 0, 'f', 2)+")"); + } + + /* If total sent is selected */ + if (_showSend) { + y += rowHeight; + _painter->setPen(SEND_COLOR); + _painter->drawText(x, y, + tr("Sent: ") + totalToStr(_totalSend) + + " ("+tr("%1 KB/s").arg(_sendData->first(), 0, 'f', 2)+")"); + } +} + +/** Returns a formatted string with the correct size suffix. */ +QString +GraphFrame::totalToStr(qreal total) +{ + /* Determine the correct size suffix */ + if (total < 1024) { + /* Use KB suffix */ + return tr("%1 KB").arg(total, 0, 'f', 2); + } else if (total < 1048576) { + /* Use MB suffix */ + return tr("%1 MB").arg(total/1024.0, 0, 'f', 2); + } else { + /* Use GB suffix */ + return tr("%1 GB").arg(total/1048576.0, 0, 'f', 2); + } +} + +/** Paints the scale on the graph. */ +void +GraphFrame::paintScale() +{ + qreal markStep = _maxValue * .25; + int top = _rec.y(); + int bottom = _rec.height(); + qreal paintStep = (bottom - (bottom/10)) / 4; + + /* Draw the other marks in their correctly scaled locations */ + qreal scale; + qreal pos; + for (int i = 1; i < 5; i++) { + pos = bottom - (i * paintStep); + scale = i * markStep; + _painter->setPen(SCALE_COLOR); + _painter->drawText(QPointF(5, pos+FONT_SIZE), + tr("%1 KB/s").arg(scale, 0, 'f', 2)); + _painter->setPen(GRID_COLOR); + _painter->drawLine(QPointF(SCALE_WIDTH, pos), + QPointF(_rec.width(), pos)); + } + + /* Draw vertical separator */ + _painter->drawLine(SCALE_WIDTH, top, SCALE_WIDTH, bottom); +} + diff --git a/retroshare-gui/src/gui/graphframe.h b/retroshare-gui/src/gui/graphframe.h new file mode 100644 index 000000000..cc6597124 --- /dev/null +++ b/retroshare-gui/src/gui/graphframe.h @@ -0,0 +1,121 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _GRAPHFRAME_H +#define _GRAPHFRAME_H + +#include +#include +#include +#include +#include +#include + +#define HOR_SPC 2 /** Space between data points */ +#define SCALE_WIDTH 75 /** Width of the scale */ +#define MIN_SCALE 10 /** 10 kB/s is the minimum scale */ +#define SCROLL_STEP 4 /** Horizontal change on graph update */ + +#define BACK_COLOR Qt::black +#define SCALE_COLOR Qt::green +#define GRID_COLOR Qt::darkGreen +#define RECV_COLOR Qt::cyan +#define SEND_COLOR Qt::yellow + +#define FONT_SIZE 11 + + +class GraphFrame : public QFrame +{ + Q_OBJECT + +public: + /** Bandwidth graph style. */ + enum GraphStyle { + SolidLine = 0, /**< Plot bandwidth as solid lines. */ + AreaGraph /**< Plot bandwidth as alpha blended area graphs. */ + }; + + /** Default Constructor */ + GraphFrame(QWidget *parent = 0); + /** Default Destructor */ + ~GraphFrame(); + + /** Add data points. */ + void addPoints(qreal recv, qreal send); + /** Clears the graph. */ + void resetGraph(); + /** Toggles display of data counters. */ + void setShowCounters(bool showRecv, bool showSend); + /** Sets the graph style used to display bandwidth data. */ + void setGraphStyle(GraphStyle style) { _graphStyle = style; } + +protected: + /** Overloaded QWidget::paintEvent() */ + void paintEvent(QPaintEvent *event); + +private: + /** Gets the width of the desktop, the max # of points. */ + int getNumPoints(); + + /** Paints an integral and an outline of that integral for each data set + * (send and/or receive) that is to be displayed. */ + void paintData(); + /** Paints the send/receive totals. */ + void paintTotals(); + /** Paints the scale in the graph. */ + void paintScale(); + /** Returns a formatted string representation of total. */ + QString totalToStr(qreal total); + /** Returns a list of points on the bandwidth graph based on the supplied set + * of send or receive values. */ + QVector pointsFromData(QList* list); + /** Paints a line with the data in points. */ + void paintLine(QVector points, QColor color, + Qt::PenStyle lineStyle = Qt::SolidLine); + /** Paints an integral using the supplied data. */ + void paintIntegral(QVector points, QColor color, qreal alpha = 1.0); + + /** Style with which the bandwidth data will be graphed. */ + GraphStyle _graphStyle; + /** A QPainter object that handles drawing the various graph elements. */ + QPainter* _painter; + /** Holds the received data points. */ + QList *_recvData; + /** Holds the sent data points. */ + QList *_sendData; + /** The current dimensions of the graph. */ + QRect _rec; + /** The maximum data value plotted. */ + qreal _maxValue; + /** The maximum number of points to store. */ + int _maxPoints; + /** The total data sent/recv. */ + qreal _totalSend; + qreal _totalRecv; + /** Show the respective lines and counters. */ + bool _showRecv; + bool _showSend; +}; + +#endif diff --git a/retroshare-gui/src/gui/groups/CreateGroup.cpp b/retroshare-gui/src/gui/groups/CreateGroup.cpp new file mode 100644 index 000000000..64c2ea2c6 --- /dev/null +++ b/retroshare-gui/src/gui/groups/CreateGroup.cpp @@ -0,0 +1,103 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include + +#include "util/misc.h" + +#include "CreateGroup.h" +#include "gui/common/GroupDefs.h" + +/** Default constructor */ +CreateGroup::CreateGroup(const std::string groupId, QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + m_groupId = groupId; + + if (m_groupId.empty() == false) { + /* edit exisiting group */ + RsGroupInfo groupInfo; + if (rsPeers->getGroupInfo(m_groupId, groupInfo)) { + ui.groupname->setText(misc::removeNewLine(groupInfo.name)); + + setWindowTitle(tr("Edit Group")); + ui.headerLabel->setText(tr("" + "" + "

    Edit Group

    ")); + } else { + /* Group not found, create new */ + m_groupId.clear(); + } + } + + std::list groupInfoList; + rsPeers->getGroupInfoList(groupInfoList); + + std::list::iterator groupIt; + for (groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); groupIt++) { + if (m_groupId.empty() || groupIt->id != m_groupId) { + usedGroupNames.append(GroupDefs::name(*groupIt)); + } + } + + on_groupname_textChanged(ui.groupname->text()); +} + +/** Destructor. */ +CreateGroup::~CreateGroup() +{ +} + +void CreateGroup::on_groupname_textChanged(QString text) +{ + if (text.isEmpty() || usedGroupNames.contains(misc::removeNewLine(text))) { + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } else { + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } +} + +void CreateGroup::on_buttonBox_accepted() +{ + RsGroupInfo groupInfo; + + if (m_groupId.empty()) { + // add new group + groupInfo.name = misc::removeNewLine(ui.groupname->text()).toUtf8().constData(); + if (rsPeers->addGroup(groupInfo)) { + close(); + } + } else { + if (rsPeers->getGroupInfo(m_groupId, groupInfo) == true) { + groupInfo.name = misc::removeNewLine(ui.groupname->text()).toUtf8().constData(); + if (rsPeers->editGroup(m_groupId, groupInfo)) { + close(); + } + } + } +} diff --git a/retroshare-gui/src/gui/groups/CreateGroup.h b/retroshare-gui/src/gui/groups/CreateGroup.h new file mode 100644 index 000000000..7e2b03d45 --- /dev/null +++ b/retroshare-gui/src/gui/groups/CreateGroup.h @@ -0,0 +1,57 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _CREATEGROUP_H +#define _CREATEGROUP_H + +#include "ui_CreateGroup.h" + + +class CreateGroup : public QDialog +{ + Q_OBJECT + +public: + /** Default constructor */ + CreateGroup(const std::string groupId, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~CreateGroup(); + +public slots: + +private slots: + +private: + std::string m_groupId; + + QStringList usedGroupNames; + + /** Qt Designer generated object */ + Ui::CreateGroup ui; + +private slots: + void on_buttonBox_accepted(); + void on_groupname_textChanged(QString ); +}; + +#endif + diff --git a/retroshare-gui/src/gui/groups/CreateGroup.ui b/retroshare-gui/src/gui/groups/CreateGroup.ui new file mode 100644 index 000000000..d1ba1a54a --- /dev/null +++ b/retroshare-gui/src/gui/groups/CreateGroup.ui @@ -0,0 +1,195 @@ + + + CreateGroup + + + + 0 + 0 + 386 + 158 + + + + Create a Group + + + + 6 + + + 0 + + + 0 + + + + + QFrame#frame{background-image: url(:/images/connect/connectFriendBanner.png);} + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 9 + + + 6 + + + 9 + + + 6 + + + + + + 64 + 64 + + + + + 64 + 64 + + + + + + + :/images/user/add_group256.png + + + true + + + + + + + + 18 + 75 + true + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + 0 + + + 6 + + + + + Group Name + + + + + + + Enter a name for your group + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 24 + 20 + + + + + + + + + + Qt::Vertical + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 208 + 21 + + + + + + + + + + + + + + + buttonBox + rejected() + CreateGroup + reject() + + + 338 + 116 + + + 192 + 78 + + + + + diff --git a/retroshare-gui/src/gui/help/authors.html b/retroshare-gui/src/gui/help/authors.html new file mode 100644 index 000000000..9e9f61740 --- /dev/null +++ b/retroshare-gui/src/gui/help/authors.html @@ -0,0 +1,73 @@ + + + + + authors + + + + +

    + +

    The RetroShare Team:

    + +

    + +

    Lead Developers

    + + +

    Active Developers

    + + +

    The Release Team

    + + +

    Past Developers

    + + +

    Developed TLV Serialiser

    + + +

    Developed Search/Channel features

    + + + +

    Developed Smiley,Skinobject,Chat Skin

    + + +

    Developed XProgressBar

    + + + + diff --git a/retroshare-gui/src/gui/help/browser/helpbrowser.cpp b/retroshare-gui/src/gui/help/browser/helpbrowser.cpp new file mode 100644 index 000000000..1c3e24b2d --- /dev/null +++ b/retroshare-gui/src/gui/help/browser/helpbrowser.cpp @@ -0,0 +1,452 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* +** \file helpbrowser.cpp +** \version $Id: helpbrowser.cpp 2362 2008-02-29 04:30:11Z edmanm $ +** \brief Displays a list of help topics and content +*/ + +#include +#include +#include +#include "gui/settings/rsharesettings.h" + +#include "helpbrowser.h" + + +#define LEFT_PANE_INDEX 0 +#define NO_STRETCH 0 +#define MINIMUM_PANE_SIZE 1 + +/* Names of elements and attributes in the XML file */ +#define ELEMENT_CONTENTS "Contents" +#define ELEMENT_TOPIC "Topic" +#define ATTRIBUTE_TOPIC_ID "id" +#define ATTRIBUTE_TOPIC_HTML "html" +#define ATTRIBUTE_TOPIC_NAME "name" +#define ATTRIBUTE_TOPIC_SECTION "section" + +/* Define two roles used to store data associated with a topic item */ +#define ROLE_TOPIC_ID Qt::UserRole +#define ROLE_TOPIC_QRC_PATH (Qt::UserRole+1) + + +/** Constuctor. This will probably do more later */ +HelpBrowser::HelpBrowser(QWidget *parent) + : RWindow("HelpBrowser", parent) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); +#if defined(Q_WS_MAC) + ui.actionHome->setShortcut(QString("Shift+Ctrl+H")); +#endif +#if !defined(Q_WS_WIN) + ui.actionClose->setShortcut(QString("Ctrl+W")); +#endif + + /* Hide Search frame */ + ui.frmFind->setHidden(true); + + /* Set the splitter pane sizes so that only the txtBrowser pane expands + * and set to arbitrary sizes (the minimum sizes will take effect */ + QList sizes; + sizes.append(MINIMUM_PANE_SIZE); + sizes.append(MINIMUM_PANE_SIZE); + ui.splitter->setSizes(sizes); + ui.splitter->setStretchFactor(LEFT_PANE_INDEX, NO_STRETCH); + + connect(ui.treeContents, + SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), + this, SLOT(contentsItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); + + connect(ui.treeSearch, + SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), + this, SLOT(searchItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); + + /* Connect the navigation actions to their slots */ + connect(ui.actionHome, SIGNAL(triggered()), ui.txtBrowser, SLOT(home())); + connect(ui.actionBack, SIGNAL(triggered()), ui.txtBrowser, SLOT(backward())); + connect(ui.actionForward, SIGNAL(triggered()), ui.txtBrowser, SLOT(forward())); + connect(ui.txtBrowser, SIGNAL(backwardAvailable(bool)), + ui.actionBack, SLOT(setEnabled(bool))); + connect(ui.txtBrowser, SIGNAL(forwardAvailable(bool)), + ui.actionForward, SLOT(setEnabled(bool))); + connect(ui.btnFindNext, SIGNAL(clicked()), this, SLOT(findNext())); + connect(ui.btnFindPrev, SIGNAL(clicked()), this, SLOT(findPrev())); + connect(ui.btnSearch, SIGNAL(clicked()), this, SLOT(search())); + + /* Load the help topics from XML */ + loadContentsFromXml(":/help/" + language() + "/contents.xml"); + + /* Show the first help topic in the tree */ + ui.treeContents->setCurrentItem(ui.treeContents->topLevelItem(0)); + ui.treeContents->setItemExpanded(ui.treeContents->topLevelItem(0), true); +} + +/** Returns the language in which help topics should appear, or English + * ("en") if no translated help files exist for the current GUI language. */ +QString +HelpBrowser::language() +{ + QString lang = Rshare::language(); + if (!QDir(":/help/" + lang).exists()) + lang = "en"; + return lang; +} + +/** Load the contents of the help topics tree from the specified XML file. */ +void +HelpBrowser::loadContentsFromXml(QString xmlFile) +{ + QString errorString; + QFile file(xmlFile); + QDomDocument document; + + /* Load the XML contents into the DOM document */ + if (!document.setContent(&file, true, &errorString)) { + ui.txtBrowser->setPlainText(tr("Error Loading Help Contents: ")+errorString); + return; + } + /* Load the DOM document contents into the tree view */ + if (!loadContents(&document, errorString)) { + ui.txtBrowser->setPlainText(tr("Error Loading Help Contents: ")+errorString); + return; + } +} + +/** Load the contents of the help topics tree from the given DOM document. */ +bool +HelpBrowser::loadContents(const QDomDocument *document, QString &errorString) +{ + /* Grab the root document element and make sure it's the right one */ + QDomElement root = document->documentElement(); + if (root.tagName() != ELEMENT_CONTENTS) { + errorString = tr("Supplied XML file is not a valid Contents document."); + return false; + } + _elementList << root; + + /* Create the home item */ + QTreeWidgetItem *home = createTopicTreeItem(root, 0); + ui.treeContents->addTopLevelItem(home); + + /* Process all top-level help topics */ + QDomElement child = root.firstChildElement(ELEMENT_TOPIC); + while (!child.isNull()) { + parseHelpTopic(child, home); + child = child.nextSiblingElement(ELEMENT_TOPIC); + } + return true; +} + +/** Parse a Topic element and handle all its children recursively. */ +void +HelpBrowser::parseHelpTopic(const QDomElement &topicElement, + QTreeWidgetItem *parent) +{ + /* Check that we have a valid help topic */ + if (isValidTopicElement(topicElement)) { + /* Save this element for later (used for searching) */ + _elementList << topicElement; + + /* Create and populate the new topic item in the tree */ + QTreeWidgetItem *topic = createTopicTreeItem(topicElement, parent); + + /* Process all its child elements */ + QDomElement child = topicElement.firstChildElement(ELEMENT_TOPIC); + while (!child.isNull()) { + parseHelpTopic(child, topic); + child = child.nextSiblingElement(ELEMENT_TOPIC); + } + } +} + +/** Returns true if the given Topic element has the necessary attributes. */ +bool +HelpBrowser::isValidTopicElement(const QDomElement &topicElement) +{ + return (topicElement.hasAttribute(ATTRIBUTE_TOPIC_ID) && + topicElement.hasAttribute(ATTRIBUTE_TOPIC_NAME) && + topicElement.hasAttribute(ATTRIBUTE_TOPIC_HTML)); +} + +/** Builds a resource path to an html file associated with the given help + * topic. If the help topic needs an achor, the anchor will be formatted and + * appended. */ +QString +HelpBrowser::getResourcePath(const QDomElement &topicElement) +{ + QString link = language() + "/" + topicElement.attribute(ATTRIBUTE_TOPIC_HTML); + if (topicElement.hasAttribute(ATTRIBUTE_TOPIC_SECTION)) { + link += "#" + topicElement.attribute(ATTRIBUTE_TOPIC_SECTION); + } + return link; +} + +/** Creates a new element to be inserted into the topic tree. */ +QTreeWidgetItem* +HelpBrowser::createTopicTreeItem(const QDomElement &topicElement, + QTreeWidgetItem *parent) +{ + QTreeWidgetItem *topic = new QTreeWidgetItem(parent); + topic->setText(0, topicElement.attribute(ATTRIBUTE_TOPIC_NAME)); + topic->setData(0, ROLE_TOPIC_ID, topicElement.attribute(ATTRIBUTE_TOPIC_ID)); + topic->setData(0, ROLE_TOPIC_QRC_PATH, getResourcePath(topicElement)); + return topic; +} + +/** Called when the user selects a different item in the content topic tree */ +void +HelpBrowser::contentsItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *prev) +{ + QList selected = ui.treeSearch->selectedItems(); + /* Deselect the selection in the search tree */ + if (!selected.isEmpty()) { + ui.treeSearch->setItemSelected(selected[0], false); + } + currentItemChanged(current, prev); +} + +/** Called when the user selects a different item in the content topic tree */ +void +HelpBrowser::searchItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *prev) +{ + QList selected = ui.treeContents->selectedItems(); + /* Deselect the selection in the contents tree */ + if (!selected.isEmpty()) { + ui.treeContents->setItemSelected(selected[0], false); + } + + /* Change to selected page */ + currentItemChanged(current, prev); + + /* Highlight search phrase */ + QTextCursor found; + QTextDocument::FindFlags flags = QTextDocument::FindWholeWords; + found = ui.txtBrowser->document()->find(_lastSearch, 0, flags); + if (!found.isNull()) { + ui.txtBrowser->setTextCursor(found); + } +} + +/** Called when the user selects a different item in the tree. */ +void +HelpBrowser::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *prev) +{ + Q_UNUSED(prev); + if (current) { + ui.txtBrowser->setSource(QUrl(current->data(0, + ROLE_TOPIC_QRC_PATH).toString())); + } + _foundBefore = false; +} + +/** Searches for a topic in the topic tree. Returns a pointer to that topics + * item in the topic tree if it is found, 0 otherwise. */ +QTreeWidgetItem* +HelpBrowser::findTopicItem(QTreeWidgetItem *startItem, QString topic) +{ + /* If startItem is null, then we don't know where to start searching. */ + if (!startItem) + return 0; + + /* Parse the first subtopic in the topic id. */ + QString subtopic = topic.mid(0, topic.indexOf(".")).toLower(); + + /* Search through all children of startItem and look for a subtopic match */ + for (int i = 0; i < startItem->childCount(); i++) { + QTreeWidgetItem *item = startItem->child(i); + + if (subtopic == item->data(0, ROLE_TOPIC_ID).toString().toLower()) { + /* Found a subtopic match, so expand this item */ + ui.treeContents->setItemExpanded(item, true); + if (!topic.contains(".")) { + /* Found the exact topic */ + return item; + } + /* Search recursively for the next subtopic */ + return findTopicItem(item, topic.mid(topic.indexOf(".")+1)); + } + } + return 0; +} + +/** Shows the help browser. If a sepcified topic was given, the search for + * that topic's ID (e.g., "log.basic") and display the appropriate page. */ +void +HelpBrowser::showTopic(QString topic) +{ + /* Search for the topic in the contents tree */ + QTreeWidgetItem *item = + findTopicItem(ui.treeContents->topLevelItem(0), topic); + + if (item) { + /* Item was found, so show its location in the hierarchy and select its + * tree item. */ + QTreeWidgetItem* selected = ui.treeContents->selectedItems()[0]; + if (selected) { + ui.treeContents->setItemSelected(selected, false); + } + ui.treeContents->setItemExpanded(ui.treeContents->topLevelItem(0), true); + ui.treeContents->setItemSelected(item, true); + currentItemChanged(item, selected); + } +} + +/** Called when the user clicks "Find Next". */ +void +HelpBrowser::findNext() +{ + find(true); +} + +/** Called when the user clicks "Find Previous". */ +void +HelpBrowser::findPrev() +{ + find(false); +} + +/** Searches the current page for the phrase in the Find box. + * Highlights the first instance found in the document + * \param forward true search forward if true, backward if false + **/ +void +HelpBrowser::find(bool forward) +{ + /* Don't bother searching if there is no search phrase */ + if (ui.lineFind->text().isEmpty()) { + return; + } + + QTextDocument::FindFlags flags = 0; + QTextCursor cursor = ui.txtBrowser->textCursor(); + QString searchPhrase = ui.lineFind->text(); + + /* Clear status bar */ + this->statusBar()->clearMessage(); + + /* Set search direction and other flags */ + if (!forward) { + flags |= QTextDocument::FindBackward; + } + if (ui.chkbxMatchCase->isChecked()) { + flags |= QTextDocument::FindCaseSensitively; + } + if (ui.chkbxWholePhrase->isChecked()) { + flags |= QTextDocument::FindWholeWords; + } + + /* Check if search phrase is the same as the previous */ + if (searchPhrase != _lastFind) { + _foundBefore = false; + } + _lastFind = searchPhrase; + + /* Set the cursor to the appropriate start location if necessary */ + if (!cursor.hasSelection()) { + if (forward) { + cursor.movePosition(QTextCursor::Start); + } else { + cursor.movePosition(QTextCursor::End); + } + ui.txtBrowser->setTextCursor(cursor); + } + + /* Search the page */ + QTextCursor found; + found = ui.txtBrowser->document()->find(searchPhrase, cursor, flags); + + /* If found, move the cursor to the location */ + if (!found.isNull()) { + ui.txtBrowser->setTextCursor(found); + /* If not found, display appropriate error message */ + } else { + if (_foundBefore) { + if (forward) + this->statusBar()->showMessage(tr("Search reached end of document")); + else + this->statusBar()->showMessage(tr("Search reached start of document")); + } else { + this->statusBar()->showMessage(tr("Text not found in document")); + } + } + + /* Even if not found this time, may have been found previously */ + _foundBefore |= !found.isNull(); +} + +/** Searches all help pages for the phrase the Search box. + * Fills treeSearch with documents containing matches and sets the + * status bar text appropriately. + */ +void +HelpBrowser::search() +{ + /* Clear the list */ + ui.treeSearch->clear(); + + /* Don't search if invalid document or blank search phrase */ + if (ui.lineSearch->text().isEmpty()) { + return; + } + + HelpTextBrowser browser; + QTextCursor found; + QTextDocument::FindFlags flags = QTextDocument::FindWholeWords; + + _lastSearch = ui.lineSearch->text(); + + /* Search through all the pages looking for the phrase */ + for (int i=0; i < _elementList.size(); ++i) { + /* Load page data into browser */ + browser.setSource(QUrl(getResourcePath(_elementList[i]))); + + /* Search current document */ + found = browser.document()->find(ui.lineSearch->text(), 0, flags); + + /* If found, add page to tree */ + if (!found.isNull()) { + ui.treeSearch->addTopLevelItem(createTopicTreeItem(_elementList[i], 0)); + } + } + + /* Set the status bar text */ + this->statusBar()->showMessage(tr("Found %1 results") + .arg(ui.treeSearch->topLevelItemCount())); +} + +/** Overrides the default show method */ +void +HelpBrowser::showWindow(QString topic) +{ + + /* Bring the window to the top */ + RWindow::showWindow(); + + /* If a topic was specified, then go ahead and display it. */ + if (!topic.isEmpty()) { + showTopic(topic); + } +} + diff --git a/retroshare-gui/src/gui/help/browser/helpbrowser.h b/retroshare-gui/src/gui/help/browser/helpbrowser.h new file mode 100644 index 000000000..97ccc0c08 --- /dev/null +++ b/retroshare-gui/src/gui/help/browser/helpbrowser.h @@ -0,0 +1,108 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* +** \file helpbrowser.h +** \version $Id: helpbrowser.h 2362 2008-02-29 04:30:11Z edmanm $ +** \brief Displays a list of help topics and content +*/ + +#ifndef _HELPBROWSER_H +#define _HELPBROWSER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ui_helpbrowser.h" + +class HelpBrowser : public RWindow +{ + Q_OBJECT + +public: + /** Default constructor **/ + HelpBrowser(QWidget *parent = 0); + +public slots: + /** Overrides the default QWidget::show() */ + void showWindow(QString topic = QString()); + +private slots: + /** Called when the user clicks "Find Next" */ + void findNext(); + /** Called when the user clicks "Find Previous" */ + void findPrev(); + /** Called when the user starts a search */ + void search(); + /** Called when the user selects a different item in the contents tree */ + void contentsItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *prev); + /** Called when the user selects a different item in the search tree */ + void searchItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *prev); + +private: + /** Returns the language in which help topics should appear, or English + * ("en") if no translated help files exist for the current GUI language. */ + QString language(); + /** Load the contents of the help topics tree from the specified XML file. */ + void loadContentsFromXml(QString xmlFile); + /** Load the contents of the help topics tree from the given DOM document. */ + bool loadContents(const QDomDocument *document, QString &errorString); + /** Parse a Topic element and handle all its children. */ + void parseHelpTopic(const QDomElement &element, QTreeWidgetItem *parent); + /** Returns true if the given Topic element has the necessary attributes. */ + bool isValidTopicElement(const QDomElement &topicElement); + /** Builds a resource path to an html file associated with a help topic. */ + QString getResourcePath(const QDomElement &topicElement); + /** Searches the current page for the phrase in the Find box */ + void find(bool forward); + /** Creates a new item to be placed in the topic tree. */ + QTreeWidgetItem* createTopicTreeItem(const QDomElement &topicElement, + QTreeWidgetItem *parent); + /** Called when the user selects a different item in the tree. */ + void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *prev); + /** Finds a topic in the topic tree. */ + QTreeWidgetItem* findTopicItem(QTreeWidgetItem *startItem, QString topic); + /** Shows the help browser and finds a specific a topic in the browser. */ + void showTopic(QString topic); + + /** List of DOM elements representing topics. */ + QList _elementList; + /** Last phrase used for 'Find' */ + QString _lastFind; + /** Last phrase searched on */ + QString _lastSearch; + /** Indicates if phrase was previously found on current page */ + bool _foundBefore; + + /** Qt Designer generated QObject */ + Ui::HelpBrowser ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/help/browser/helpbrowser.ui b/retroshare-gui/src/gui/help/browser/helpbrowser.ui new file mode 100644 index 000000000..6706907d8 --- /dev/null +++ b/retroshare-gui/src/gui/help/browser/helpbrowser.ui @@ -0,0 +1,720 @@ + + HelpBrowser + + + + 0 + 0 + 703 + 583 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::NoContextMenu + + + RetroShare Help + + + + :/images/help.png:/images/help.png + + + + + + true + + + Qt::ToolButtonTextUnderIcon + + + + + 0 + 52 + 703 + 510 + + + + + 6 + + + 9 + + + + + + 0 + 0 + + + + + 450 + 79 + + + + + 16777215 + 79 + + + + Qt::NoContextMenu + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 9 + + + 6 + + + + + 6 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 24 + 24 + + + + Qt::NoContextMenu + + + + + + + :/images/button_cancel.png:/images/button_cancel.png + + + + 22 + 22 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + Qt::NoContextMenu + + + Find: + + + lineFind + + + + + + + Qt::NoContextMenu + + + + + + + + + Qt::NoContextMenu + + + Find Previous + + + + :/images/22x22/go-up-search.png:/images/22x22/go-up-search.png + + + + + + + Qt::NoContextMenu + + + Find Next + + + + :/images/22x22/go-down-search.png:/images/22x22/go-down-search.png + + + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::NoContextMenu + + + Case sensitive + + + + + + + Qt::NoContextMenu + + + Whole words only + + + + + + + + + + + + Qt::NoContextMenu + + + Qt::Horizontal + + + + Qt::NoContextMenu + + + QTabWidget::North + + + QTabWidget::Rounded + + + 0 + + + + + 0 + 0 + 268 + 380 + + + + RetroShare Help + + + + :/images/help.png:/images/help.png + + + Contents + + + + 6 + + + 6 + + + + + + 1 + 0 + + + + + 200 + 0 + + + + + 16777215 + 16777215 + + + + Qt::WheelFocus + + + Qt::NoContextMenu + + + QAbstractItemView::SelectItems + + + true + + + + Help Topics + + + + + + + + + + 4 + 23 + 268 + 380 + + + + Search + + + + 6 + + + 6 + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::NoContextMenu + + + Search + + + + + + + + + Qt::NoContextMenu + + + Searching for: + + + lineSearch + + + + + + + + 1 + 0 + + + + + 200 + 0 + + + + + 16777215 + 16777215 + + + + Qt::WheelFocus + + + Qt::NoContextMenu + + + QAbstractItemView::SelectItems + + + true + + + + Found Documents + + + + + + + + Qt::NoContextMenu + + + + + + + + + + 100 + 0 + + + + Qt::NoContextMenu + + + true + + + + + + + + + + 0 + 562 + 703 + 21 + + + + + + + 0 + 0 + 703 + 52 + + + + + 0 + 0 + + + + Qt::NoContextMenu + + + false + + + Qt::Horizontal + + + Qt::ToolButtonTextUnderIcon + + + TopToolBarArea + + + false + + + + + + + + + + + + :/images/back.png:/images/back.png + + + Back + + + Move to previous page (Backspace) + + + Backspace + + + + + + :/images/forward.png:/images/forward.png + + + Forward + + + Move to next page (Shift+Backspace) + + + Shift+Backspace + + + + + + :/images/gohome.png:/images/gohome.png + + + Home + + + Move to the Home page (Ctrl+H) + + + Ctrl+H + + + + + true + + + + :/images/find.png:/images/find.png + + + Find + + + Find + + + Find + + + Search for a word or phrase on current page (Ctrl+F) + + + Ctrl+F + + + + + + :/images/exit_24x24.png:/images/exit_24x24.png + + + Close + + + Close Vidalia Help + + + Esc + + + + + + HelpTextBrowser + QTextBrowser +
    gui/help/browser/helptextbrowser.h
    +
    +
    + + tabsMenu + btnCloseFind + lineFind + btnFindNext + btnFindPrev + chkbxMatchCase + chkbxWholePhrase + treeContents + txtBrowser + lineSearch + btnSearch + treeSearch + + + + + + + actionFind + triggered() + lineFind + setFocus() + + + -1 + -1 + + + 200 + 108 + + + + + btnCloseFind + clicked() + actionFind + toggle() + + + 34 + 107 + + + -1 + -1 + + + + + actionFind + toggled(bool) + frmFind + setVisible(bool) + + + -1 + -1 + + + 243 + 108 + + + + + actionClose + triggered() + HelpBrowser + close() + + + -1 + -1 + + + 317 + 248 + + + + + lineFind + returnPressed() + btnFindNext + click() + + + 293 + 108 + + + 539 + 108 + + + + + lineSearch + returnPressed() + btnSearch + click() + + + 153 + 245 + + + 244 + 277 + + + + +
    diff --git a/retroshare-gui/src/gui/help/browser/helptextbrowser.cpp b/retroshare-gui/src/gui/help/browser/helptextbrowser.cpp new file mode 100644 index 000000000..20a3df753 --- /dev/null +++ b/retroshare-gui/src/gui/help/browser/helptextbrowser.cpp @@ -0,0 +1,110 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* +** \file helptextbrowser.cpp +** \version $Id: helptextbrowser.cpp 2679 2008-06-10 03:07:10Z edmanm $ +** \brief Displays an HTML-based help document +*/ + +#include +#include +#include +#include "gui/common/vmessagebox.h" +#include "gui/common/html.h" +#include + +#include "helptextbrowser.h" + + +/** Default constructor. */ +HelpTextBrowser::HelpTextBrowser(QWidget *parent) + : QTextBrowser(parent) +{ + setOpenExternalLinks(false); +} + +/** Loads a resource into the browser. If it is an HTML resource, we'll load + * it as UTF-8, so the special characters in our translations appear properly. */ +QVariant +HelpTextBrowser::loadResource(int type, const QUrl &name) +{ + /* If it's an HTML file, we'll handle it ourselves */ + if (type == QTextDocument::HtmlResource) { + QString helpPath = ":/help/"; + + /* Fall back to English if there is no translation of the specified help + * page in the current language. */ + if (!name.path().contains("/")) { + QString language = Rshare::language(); + if (!QDir(":/help/" + language).exists()) + language = "en"; + helpPath += language + "/"; + } + + QFile file(helpPath + name.path()); + if (!file.open(QIODevice::ReadOnly)) { + return tr("Error opening help file: ") + name.path(); + } + return QString::fromUtf8(file.readAll()); + } + /* Everything else, just let QTextBrowser take care of it. */ + return QTextBrowser::loadResource(type, name); +} + + +/** Called when the displayed document is changed. If url specifies + * an external link, then the user will be prompted for whether they want to + * open the link in their default browser or not. */ +void +HelpTextBrowser::setSource(const QUrl &url) +{ + if (url.scheme() != "qrc" && !url.isRelative()) { + /* External link. Prompt the user for a response. */ + int ret = VMessageBox::question(this, + tr("Opening External Link"), + p(tr("RetroShare can open the link you selected in your default " + "Web browser. If your browser is not currently " + "configured to use Tor then the request will not be " + "anonymous.")) + + p(tr("Do you want Retroshare to open the link in your Web " + "browser?")), + VMessageBox::Yes|VMessageBox::Default, + VMessageBox::Cancel|VMessageBox::Cancel); + + if (ret == VMessageBox::Cancel) + return; + + bool ok = QDesktopServices::openUrl(url); + if (!ok) { + VMessageBox::information(this, + tr("Unable to Open Link"), + tr("RetroShare was unable to open the selected link in your Web browser. " + "You can still copy the URL and paste it into your browser."), + VMessageBox::Ok); + } + } else { + /* Internal link. Just load it like normal. */ + QTextBrowser::setSource(url); + } +} + diff --git a/retroshare-gui/src/gui/help/browser/helptextbrowser.h b/retroshare-gui/src/gui/help/browser/helptextbrowser.h new file mode 100644 index 000000000..320297ba9 --- /dev/null +++ b/retroshare-gui/src/gui/help/browser/helptextbrowser.h @@ -0,0 +1,54 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* +** \file helptextbrowser.h +** \version $Id: helptextbrowser.h 2679 2008-06-10 03:07:10Z edmanm $ +** \brief Displays an HTML-based help document +*/ + +#ifndef _HELPTEXTBROWSER_H +#define _HELPTEXTBROWSER_H + +#include +#include + + +class HelpTextBrowser : public QTextBrowser +{ + Q_OBJECT + +public: + /** Default constructor. */ + HelpTextBrowser(QWidget *parent = 0); + /** Loads a resource into the browser. */ + QVariant loadResource(int type, const QUrl &name); + +public slots: + /** Called when the displayed document is changed. If url specifies + * an external link, then the user will be prompted for whether they want to + * open the link in their default browser or not. */ + virtual void setSource(const QUrl &url); +}; + +#endif + diff --git a/retroshare-gui/src/gui/help/content/content.qrc b/retroshare-gui/src/gui/help/content/content.qrc new file mode 100644 index 000000000..7bc123d30 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/content.qrc @@ -0,0 +1,18 @@ + + + + en/contents.xml + en/index.html + en/config.html + en/links.html + en/commandline.html + en/peerdetails.html + + de/contents.xml + de/index.html + de/links.html + de/commandline.html + de/peerdetails.html + + + diff --git a/retroshare-gui/src/gui/help/content/contents.dtd b/retroshare-gui/src/gui/help/content/contents.dtd new file mode 100644 index 000000000..5da21e94e --- /dev/null +++ b/retroshare-gui/src/gui/help/content/contents.dtd @@ -0,0 +1,52 @@ + + + + + + + + + + diff --git a/retroshare-gui/src/gui/help/content/de/commandline.html b/retroshare-gui/src/gui/help/content/de/commandline.html new file mode 100644 index 000000000..9e751b3ec --- /dev/null +++ b/retroshare-gui/src/gui/help/content/de/commandline.html @@ -0,0 +1,68 @@ + + + + + +

    Kommandozeilen-Optionen

    +
    + +

    +Kommandozeilen-Optionen fr retroshare-nogui. +

    + + +

    Kommandozeilen-Befehle :

    + +
      +
    • -h Show the help
    • +
    • -l [logfile] Set the logfilename
    • +
    • -w [password] Set the password
    • +
    • -i [ip_adress] Set IP Adress to use
    • +
    • -p [port] Set the Port to listen on
    • +
    • -c [basedir] Set the config basdir
    • +
    • -s Output to Stderr
    • +
    • -d [debuglevel] Set the debuglevel
    • +
    • -u Only listen to UDP
    • +
    • -e Use a forwarded external Port
    • +
    • -U username (ssl id) to login with
    • +
    • -r "retroshare://..." for adding links to the registered running RetroShare
    • +
    + +
    +

    Beispiel:

    + +
      +
    • ./retroshare-nogui -w meingeheimespasswort -e
    • +
    + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/help/content/de/contents.xml b/retroshare-gui/src/gui/help/content/de/contents.xml new file mode 100644 index 000000000..57a4908a9 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/de/contents.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/retroshare-gui/src/gui/help/content/de/index.html b/retroshare-gui/src/gui/help/content/de/index.html new file mode 100644 index 000000000..d250b07b1 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/de/index.html @@ -0,0 +1,53 @@ + + + + + +

    RetroShare Hilfe

    +
    + +

    +Wählen Sie ein Hilfe-Thema aus der Liste von der linken Seite +oder klicken Sie auf Suche über der Liste um eine Suche durch +alle verfügbaren Hilfe-Themen durchzuführen. +

    + +

    +Sie können oben die Schaltfläche Suchen benutzen, +um innerhalb eines bestimmten Hilfe-Themas zu suchen. +

    + +

    +Die Schaltfläche Startseite wird Sie zu dieser Seite +zurück führen. +

    + +

    +Auf der Seite Nützliche Links finden Sie +weiterführende Hilfe und Informationen zu Vidalia und Tor. +

    + + + + diff --git a/retroshare-gui/src/gui/help/content/de/links.html b/retroshare-gui/src/gui/help/content/de/links.html new file mode 100644 index 000000000..09f26b392 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/de/links.html @@ -0,0 +1,87 @@ + + + + + +

    Nützliche Links

    +
    + +

    RetroShare

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       Homepage + + http://retroshare.sourceforge.net +
       RetroShare Forum + + http://retroshare.sourceforge.net/forum +
       RetroShare MediaWiki + + http://retroshare.sourceforge.net/wiki +
       Project Page + + http://sourceforge.net/projects/retroshare +
       Fehlerdatenbank + + http://sourceforge.net/tracker/?group_id=178712&atid=886239 +
       bersetzung + + http://retroshare.sourceforge.net/wiki/index.php/Translation +
    + + + + + + diff --git a/retroshare-gui/src/gui/help/content/de/peerdetails.html b/retroshare-gui/src/gui/help/content/de/peerdetails.html new file mode 100644 index 000000000..1bf624618 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/de/peerdetails.html @@ -0,0 +1,63 @@ + + + + + +

    Peer Details

    +
    + +

    +Peer Details Trust settings and Signing +

    + + +

    Trust Settings

    + +

    +The trust settings refers to the gnupg web of trust mecanism.
    +This trust means how you trust your friends when he is signing other gpg keys.
    +If you set your trust to "full", it means that when your friend sign a key, this key will be shown as validated by the web of trust in the network view.

    + + +
    +

    Signing

    +
    +

    Commands:

    + +
      +
    • -h Show the help
    • +
    • -l [logfile] Set the logfilename
    • +
    • -w [password] Set the password
    • +
    • -i [ip_adress] Set IP Adress to use
    • +
    • -p [port] Set the Port to listen on
    • +
    • -c [basedir] Set the config basdir
    • +
    • -s Output to Stderr
    • +
    • -d [debuglevel] Set the debuglevel
    • +
    • -u Only listen to UDP
    • +
    • -e Use a forwarded external Port
    • +
    • -U username (ssl id) to login with
    • +
    • -r "retroshare://..." for adding links to the registered running RetroShare
    • +
    + +
    +

    Example:

    + +
      +
    • ./retroshare-nogui -w mysecretpassword -e
    • +
    + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/help/content/en/config.html b/retroshare-gui/src/gui/help/content/en/config.html new file mode 100644 index 000000000..218014f96 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/en/config.html @@ -0,0 +1,96 @@ + + + + + +

    Configuring RetroShare

    +
    + +

    +RetroShare allows you to configure some of the most commonly modified aspects of +RetroShare. +

    + +
    +

    General Settings

    +

    +The settings on the General page are the most commonly modified settings. +

    +
      +
    • Startup Options: + You can also configure RetroShare to run when your system + starts (Windows only). +
    • +
    + +
    +

    Server Settings

    +

    +The Server settings page lets you change how RetroShare connects to the RetroShare +network. +

    +
      + +
    + +
    +

    Directories Settings

    +

    + +The Directories settings page lets you add and remove Shared Directories and can set a Incoming Directorie. + +

    + +
    +

    Appearance Settings

    +

    +The settings on the Appearance page allow you to customize the +look and feel of RetroShare. +

    +
      +
    • Language: + RetroShare's interface has been translated into many languages by helpful + volunteers. When RetroShare is first run, it will try to guess which language + your computer is currently using. If RetroShare guesses incorrectly, or if + you prefer a different language, you can choose another language from the + dropdown box. You will need to restart RetroShare after changing the + displayed language for the changes to take effect. +
    • +
    • Style: + In most cases, RetroShare will default to using your platform's default + interface style. If you dislike the default, you can choose whichever + interface style you prefer from the dropdown box. +
    • +
    • Style Sheet: + RetroShare will default to using default style sheet. + If you dislike the default, you can choose whichever + style sheet you prefer from the dropdown box. +
    • +
    + + + + + + diff --git a/retroshare-gui/src/gui/help/content/en/contents.xml b/retroshare-gui/src/gui/help/content/en/contents.xml new file mode 100644 index 000000000..f47f46eb7 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/en/contents.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/help/content/en/index.html b/retroshare-gui/src/gui/help/content/en/index.html new file mode 100644 index 000000000..54edca521 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/en/index.html @@ -0,0 +1,51 @@ + + + + + +

    RetroShare Help

    +
    + +

    +Select a help topic from the tree on the left or click on the Search button +above the list of topics to search through all available help topics. +

    + +

    +You can use the Find button on the toolbar above to search within a +particular help topic. +

    + +

    +The Home button above will bring you back to this home page. +

    + +

    +See the Helpful Links topic for some places you +can visit to find additional help and information about Vidalia and Tor. +

    + + + + diff --git a/retroshare-gui/src/gui/help/content/en/links.html b/retroshare-gui/src/gui/help/content/en/links.html new file mode 100644 index 000000000..cff11e993 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/en/links.html @@ -0,0 +1,86 @@ + + + + + +

    Helpful Links

    +
    + +

    RetroShare

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       Homepage + + http://retroshare.sourceforge.net +
       RetroShare Forum + + http://retroshare.sourceforge.net/forum +
       RetroShare Wiki + + http://retroshare.sourceforge.net/wiki +
       Project Page + + http://sourceforge.net/projects/retroshare +
       Bugtracker + + http://sourceforge.net/tracker/?group_id=178712&atid=886239 +
       Translation + + http://retroshare.sourceforge.net/wiki/index.php/Translation +
    + + + + + + diff --git a/retroshare-gui/src/gui/help/content/en/peerdetails.html b/retroshare-gui/src/gui/help/content/en/peerdetails.html new file mode 100644 index 000000000..470e32884 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/en/peerdetails.html @@ -0,0 +1,63 @@ + + + + + +

    Peer Details

    +
    + +

    +Trust settings and Signing +

    + + +

    Trust Settings

    + +

    +The trust settings refers to the gnupg web of trust mecanism.
    +This trust means how you trust your friends when he is signing other gpg keys.
    +If you set your trust to "full", it means that when your friend sign a key, this key will be shown as validated by the web of trust in the network view.

    + + +
    +

    Signing

    +

    + +You should sign a key when you are sure that the person who claims ownership on this key is the real owner of the key.
    +When you are sure that the name of the key owner is the real name of the emmitter of this key, you may sign it to confirm it.
    +Signing the key will be public unless public discovery is not setted. This means you friends can check if you did sign someone's key.
    +

    + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/help/content/en/commandline.html b/retroshare-gui/src/gui/help/content/en/commandline.html new file mode 100644 index 000000000..e5ecb0b76 --- /dev/null +++ b/retroshare-gui/src/gui/help/content/en/commandline.html @@ -0,0 +1,68 @@ + + + + + +

    Commandline Options

    +
    + +

    +The commandline options are for retroshare-nogui, a headless server in a shell, or systems without QT. +

    + +

    + +You should sign a key when you are sure that the person who claims ownership on this key is the real owner of the key.
    +When you are sure that the name of the key owner is the real name of the emmitter of this key, you may sign it to confirm it.
    +Signing the key will be public unless public discovery is not setted. This means you friends can check if you did sign someone's key.
    +

    + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/help/licence.html b/retroshare-gui/src/gui/help/licence.html new file mode 100644 index 000000000..4ce067118 --- /dev/null +++ b/retroshare-gui/src/gui/help/licence.html @@ -0,0 +1,354 @@ + + + + + + licence + + + + +

    Retroshare's Licences

    + +

    All of Retroshare's Code is available freely under open source licences, +

    + +

    However the software does not fall exclusively under one licence.

    + +

    libretroshare : (the core library)

    + +

    Is licenced under the LGPL (Gnu Library General Public Licence)

    + +

    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html

    + +

    This library also depends on:

    +
      +
    1. miniupnpc: BSD Licence
    2. +
    3. OpenSSL: OpenSSL Licence.
    4. +
    5. GPGme: LGPL Licence.
    6. +
    7. KadC : GPL Licence.
    8. +
    + +

    Retroshare GUI and Applications

    + +

    These are generally licenced under the GPL (Gnu General Public Licence)

    + +

    http://www.gnu.org/licenses/gpl.html

    + +

    And are built on top of Trolltech's Qt Libraries.

    + +

    + +

    + +

    GNU GENERAL PUBLIC LICENSE

    + +

    Version 2, June 1991

    + +

    + +

    Copyright (C) 1989, 1991 Free Software Foundation, Inc.

    + +

    51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA

    + +

    Everyone is permitted to copy and distribute verbatim copies

    + +

    of this license document, but changing it is not allowed.

    + +

    + +

    Preamble

    + +

    + +

    The licenses for most software are designed to take away your freedom to +share and change it. By contrast, the GNU General Public License is intended +to guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program +whose authors commit to using it. (Some other Free Software Foundation +software is covered by the GNU Library General Public License instead.) You +can apply it to your programs, too.

    + +

    When we speak of free software, we are referring to freedom, not price. +Our General Public Licenses are designed to make sure that you have the +freedom to distribute copies of free software (and charge for this service if +you wish), that you receive source code or can get it if you want it, that +you can change the software or use pieces of it in new free programs; and +that you know you can do these things.

    + +

    To protect your rights, we need to make restrictions that forbid anyone to +deny you these rights or to ask you to surrender the rights. These +restrictions translate to certain responsibilities for you if you distribute +copies of the software, or if you modify it.

    + +

    For example, if you distribute copies of such a program, whether gratis or +for a fee, you must give the recipients all the rights that you have. You +must make sure that they, too, receive or can get the source code. And you +must show them these terms so they know their rights.

    + +

    We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software.

    + +

    Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations.

    + +

    Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program +proprietary. To prevent this, we have made it clear that any patent must be +licensed for everyone's free use or not licensed at all.

    + +

    The precise terms and conditions for copying, distribution and +modification follow.

    + +

    + +

    GNU GENERAL PUBLIC LICENSE

    + +

    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

    + +

    + +

    0. This License applies to any program or other work which contains a +notice placed by the copyright holder saying it may be distributed under the +terms of this General Public License. The "Program", below, refers to any +such program or work, and a "work based on the Program" means either the +Program or any derivative work under copyright law: that is to say, a work +containing the Program or a portion of it, either verbatim or with +modifications and/or translated into another language. (Hereinafter, +translation is included without limitation in the term "modification".) Each +licensee is addressed as "you".

    + +

    Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of running the +Program is not restricted, and the output from the Program is covered only if +its contents constitute a work based on the Program (independent of having +been made by running the Program). Whether that is true depends on what the +Program does.

    + +

    + +

    1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +License and to the absence of any warranty; and give any other recipients of +the Program a copy of this License along with the Program.

    + +

    You may charge a fee for the physical act of transferring a copy, and you +may at your option offer warranty protection in exchange for a fee.

    + +

    + +

    2. You may modify your copy or copies of the Program or any portion of it, +thus forming a work based on the Program, and copy and distribute such +modifications or work under the terms of Section 1 above, provided that you +also meet all of these conditions:

    + +

    a) You must cause the modified files to carry prominent notices stating +that you changed the files and the date of any change.

    + +

    b) You must cause any work that you distribute or publish, that in whole +or in part contains or is derived from the Program or any part thereof, to be +licensed as a whole at no charge to all third parties under the terms of this +License.

    + +

    c) If the modified program normally reads commands interactively when run, +you must cause it, when started running for such interactive use in the most +ordinary way, to print or display an announcement including an appropriate +copyright notice and a notice that there is no warranty (or else, saying that +you provide a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this License. +(Exception: if the Program itself is interactive but does not normally print +such an announcement, your work based on the Program is not required to print +an announcement.)

    + +

    These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, +and its terms, do not apply to those sections when you distribute them as +separate works. But when you distribute the same sections as part of a whole +which is a work based on the Program, the distribution of the whole must be +on the terms of this License, whose permissions for other licensees extend to +the entire whole, and thus to each and every part regardless of who wrote +it.

    + +

    Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on +the Program.

    + +

    In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of a +storage or distribution medium does not bring the other work under the scope +of this License.

    + +

    + +

    3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 +and 2 above provided that you also do one of the following:

    + +

    a) Accompany it with the complete corresponding machine-readable source +code, which must be distributed under the terms of Sections 1 and 2 above on +a medium customarily used for software interchange; or,

    + +

    b) Accompany it with a written offer, valid for at least three years, to +give any third party, for a charge no more than your cost of physically +performing source distribution, a complete machine-readable copy of the +corresponding source code, to be distributed under the terms of Sections 1 +and 2 above on a medium customarily used for software interchange; or,

    + +

    c) Accompany it with the information you received as to the offer to +distribute corresponding source code. (This alternative is allowed only for +noncommercial distribution and only if you received the program in object +code or executable form with such an offer, in accord with Subsection b +above.)

    + +

    The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all +the source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and +installation of the executable. However, as a special exception, the source +code distributed need not include anything that is normally distributed (in +either source or binary form) with the major components (compiler, kernel, +and so on) of the operating system on which the executable runs, unless that +component itself accompanies the executable.

    + +

    If distribution of executable or object code is made by offering access to +copy from a designated place, then offering equivalent access to copy the +source code from the same place counts as distribution of the source code, +even though third parties are not compelled to copy the source along with the +object code.

    + +

    + +

    4. You may not copy, modify, sublicense, or distribute the Program except +as expressly provided under this License. Any attempt otherwise to copy, +modify, sublicense or distribute the Program is void, and will automatically +terminate your rights under this License. However, parties who have received +copies, or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance.

    + +

    + +

    5. You are not required to accept this License, since you have not signed +it. However, nothing else grants you permission to modify or distribute the +Program or its derivative works. These actions are prohibited by law if you +do not accept this License. Therefore, by modifying or distributing the +Program (or any work based on the Program), you indicate your acceptance of +this License to do so, and all its terms and conditions for copying, +distributing or modifying the Program or works based on it.

    + +

    + +

    6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these terms and +conditions. You may not impose any further restrictions on the recipients' +exercise of the rights granted herein. You are not responsible for enforcing +compliance by third parties to this License.

    + +

    + +

    7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not excuse +you from the conditions of this License. If you cannot distribute so as to +satisfy simultaneously your obligations under this License and any other +pertinent obligations, then as a consequence you may not distribute the +Program at all. For example, if a patent license would not permit +royalty-free redistribution of the Program by all those who receive copies +directly or indirectly through you, then the only way you could satisfy both +it and this License would be to refrain entirely from distribution of the +Program.

    + +

    If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and +the section as a whole is intended to apply in other circumstances.

    + +

    It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any such +claims; this section has the sole purpose of protecting the integrity of the +free software distribution system, which is implemented by public license +practices. Many people have made generous contributions to the wide range of +software distributed through that system in reliance on consistent +application of that system; it is up to the author/donor to decide if he or +she is willing to distribute software through any other system and a licensee +cannot impose that choice.

    + +

    This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License.

    + +

    + +

    8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program under this License may add an +explicit geographical distribution limitation excluding those countries, so +that distribution is permitted only in or among countries not thus excluded. +In such case, this License incorporates the limitation as if written in the +body of this License.

    + +

    + +

    9. The Free Software Foundation may publish revised and/or new versions of +the General Public License from time to time. Such new versions will be +similar in spirit to the present version, but may differ in detail to address +new problems or concerns.

    + +

    Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any later +version", you have the option of following the terms and conditions either of +that version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of this License, +you may choose any version ever published by the Free Software Foundation.

    + +

    + +

    10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author to +ask for permission. For software which is copyrighted by the Free Software +Foundation, write to the Free Software Foundation; we sometimes make +exceptions for this. Our decision will be guided by the two goals of +preserving the free status of all derivatives of our free software and of +promoting the sharing and reuse of software generally.

    + +

    + +

    NO WARRANTY

    + +

    11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR +IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO +THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM +PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION.

    + +

    + +

    12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO +LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR +THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES.

    + +

    END OF TERMS AND CONDITIONS

    + + diff --git a/retroshare-gui/src/gui/help/thanks.html b/retroshare-gui/src/gui/help/thanks.html new file mode 100644 index 000000000..dab996591 --- /dev/null +++ b/retroshare-gui/src/gui/help/thanks.html @@ -0,0 +1,45 @@ + + + + + + thanks + + + + +

    + +

    Thanks to all the developers and supporters of open-source software.

    + +

    + +

    We are especially indebted to the the authors of several key packages - +which we rely on:

    + +

    + +

    The Linux Kernel and Gnu Compiler Tools.

    + +

    OpenSSL and OpenPGP for security.

    + +

    Qt for a nice GUI.

    + +

    KadC for a DHT interface.

    + +

    miniupnpc for uPnP interface.

    + +

    + +

    + +

    + +

    + +

    + +

    + + diff --git a/retroshare-gui/src/gui/help/version.html b/retroshare-gui/src/gui/help/version.html new file mode 100644 index 000000000..b28b04f64 --- /dev/null +++ b/retroshare-gui/src/gui/help/version.html @@ -0,0 +1,3 @@ + + + diff --git a/retroshare-gui/src/gui/im_history/IMHistoryItem.cpp b/retroshare-gui/src/gui/im_history/IMHistoryItem.cpp new file mode 100644 index 000000000..afd6ded2f --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryItem.cpp @@ -0,0 +1,51 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "IMHistoryItem.h" + +//============================================================================ + +IMHistoryItem::IMHistoryItem() +{ + hiid = 0; +} + +//============================================================================ + +IMHistoryItem::IMHistoryItem(int hiidIn, bool incomingIn, const std::string &idIn, const QString &nameIn, const QDateTime &sendTimeIn, const QDateTime &recvTimeIn, const QString &messageTextIn) +{ + hiid = hiidIn; + incoming = incomingIn; + id = idIn; + name = nameIn; + sendTime = sendTimeIn; + recvTime = recvTimeIn; + messageText = messageTextIn; +} + +//============================================================================ + +//! after qSort() older messages will become first +bool +IMHistoryItem::operator<(const IMHistoryItem& item) const +{ + return (recvTime < item.recvTime) ; +} diff --git a/retroshare-gui/src/gui/im_history/IMHistoryItem.h b/retroshare-gui/src/gui/im_history/IMHistoryItem.h new file mode 100644 index 000000000..85306c95a --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryItem.h @@ -0,0 +1,47 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef __IM_history_item__ +#define __IM_history_item__ + +#include +#include + +class IMHistoryItem +{ +public: + IMHistoryItem(); + + IMHistoryItem(int hiid, bool incoming, const std::string &id, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &messageText); + + int hiid; + bool incoming; + std::string id; + QString name; + QDateTime sendTime; + QDateTime recvTime; + QString messageText; + + bool operator<(const IMHistoryItem& item) const; +} ; + +#endif + diff --git a/retroshare-gui/src/gui/im_history/IMHistoryItemDelegate.cpp b/retroshare-gui/src/gui/im_history/IMHistoryItemDelegate.cpp new file mode 100644 index 000000000..b32da15cc --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryItemDelegate.cpp @@ -0,0 +1,51 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "IMHistoryItemDelegate.h" +#include "IMHistoryItemPainter.h" + +IMHistoryItemDelegate::IMHistoryItemDelegate(QWidget *parent) + : QItemDelegate(parent) +{ +} + +void IMHistoryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (qVariantCanConvert(index.data())) { + IMHistoryItemPainter itemPainter = qVariantValue(index.data()); + itemPainter.paint(painter, option, IMHistoryItemPainter::ReadOnly); + } else { + QItemDelegate::paint(painter, option, index); + } +} + +QSize IMHistoryItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + if (qVariantCanConvert(index.data())) { + IMHistoryItemPainter painter = qVariantValue(index.data()); + return painter.sizeHint(); + } else { + return QItemDelegate::sizeHint(option, index); + } +} diff --git a/retroshare-gui/src/gui/im_history/IMHistoryItemDelegate.h b/retroshare-gui/src/gui/im_history/IMHistoryItemDelegate.h new file mode 100644 index 000000000..13ec08c3d --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryItemDelegate.h @@ -0,0 +1,38 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _IMHISTORYITEMDELEGATE_H_ +#define _IMHISTORYITEMDELEGATE_H_ + +#include + +class IMHistoryItemDelegate : public QItemDelegate +{ + Q_OBJECT + +public: + IMHistoryItemDelegate(QWidget *parent = 0); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + +#endif // _IMHISTORYITEMDELEGATE_H_ diff --git a/retroshare-gui/src/gui/im_history/IMHistoryItemPainter.cpp b/retroshare-gui/src/gui/im_history/IMHistoryItemPainter.cpp new file mode 100644 index 000000000..c943205bd --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryItemPainter.cpp @@ -0,0 +1,64 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include "IMHistoryItemPainter.h" + +IMHistoryItemPainter::IMHistoryItemPainter(const QString &text) +{ + itemText = text; + + /* calcultate size */ + QTextDocument doc; + doc.setHtml(itemText); + size = doc.size().toSize(); +} + +QSize IMHistoryItemPainter::sizeHint() const +{ + return size; +} + +void IMHistoryItemPainter::paint(QPainter *painter, const QStyleOptionViewItem &option, EditMode mode) const +{ +// if (mode == Editable) { +// painter->setBrush(option.palette.highlight()); +// } else { + painter->setBrush(option.palette.foreground()); +// } + if (option.state & QStyle::State_Selected) { + painter->fillRect(option.rect, option.palette.highlight()); + } + + painter->save(); + + QTextDocument doc; + doc.setHtml(itemText); + QAbstractTextDocumentLayout::PaintContext context; + doc.setPageSize(option.rect.size()); + painter->translate(option.rect.x(), option.rect.y()); + doc.documentLayout()->draw(painter, context); + + painter->restore(); +} diff --git a/retroshare-gui/src/gui/im_history/IMHistoryItemPainter.h b/retroshare-gui/src/gui/im_history/IMHistoryItemPainter.h new file mode 100644 index 000000000..34a7b051b --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryItemPainter.h @@ -0,0 +1,50 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _IMHISTORYITEMPAINTER_H_ +#define _IMHISTORYITEMPAINTER_H_ + +#include +#include +#include + +#include "IMHistoryItem.h" + +class QPainter; + +class IMHistoryItemPainter +{ +public: + enum EditMode { /*Editable,*/ ReadOnly }; + + IMHistoryItemPainter(const QString &text = ""); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, EditMode mode) const; + QSize sizeHint() const; + +private: + QString itemText; + QSize size; +}; + +Q_DECLARE_METATYPE(IMHistoryItemPainter) + +#endif // _IMHISTORYITEMPAINTER_H_ diff --git a/retroshare-gui/src/gui/im_history/IMHistoryKeeper.cpp b/retroshare-gui/src/gui/im_history/IMHistoryKeeper.cpp new file mode 100644 index 000000000..ea4345578 --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryKeeper.cpp @@ -0,0 +1,267 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "IMHistoryKeeper.h" +#include + +#include +#include +#include + +#include //for qSort + +#include + +#include "IMHistoryReader.h" +#include "IMHistoryWriter.h" + + +//============================================================================= + +IMHistoryKeeper::IMHistoryKeeper() +{ + historyChanged = false; + + // save histroy every 10 seconds (when changed) + saveTimer = new QTimer(this); + saveTimer->connect(saveTimer, SIGNAL(timeout()), this, SLOT(saveHistory())); + saveTimer->setInterval(10000); + saveTimer->start(); + + lasthiid = 0; +}; + +//============================================================================= + +IMHistoryKeeper::~IMHistoryKeeper() +{ + saveHistory(); +} + +//============================================================================= + +void IMHistoryKeeper::init(QString historyFileName) +{ + lasthiid = 0; + + hfName = historyFileName; + loadHistoryFile(); +} + +//============================================================================= + +void IMHistoryKeeper::addMessage(bool incoming, const std::string &id, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &messageText) +{ + IMHistoryItem item(++lasthiid, incoming, id, name, sendTime, recvTime, messageText); + + hitems.append(item); + + historyChanged = true; + + emit historyAdd(item); + + //std::cerr << "IMHistoryKeeper::addMessage " + // << messageText.toStdString() << "\n"; + + //std::cerr << "IMHistoryKeeper::addMessage count is" << hitems.count(); +} + +//============================================================================= + +bool IMHistoryKeeper::loadHistoryFile() +{ + qDebug() << " IMHistoryKeeper::loadHistoryFile is here"; + + if (hfName.isEmpty()) { + lastErrorMessage = "history file not set"; + return false; + } + + QFile fl(hfName); + if (!fl.exists()) { + lastErrorMessage = QString("history file not found (%1)").arg(hfName) ; + return false; + } + + IMHistoryReader hreader; + if (!hreader.read(hitems, hfName, lasthiid)) { + lastErrorMessage = hreader.errorMessage(); + return false; + } + + qSort(hitems.begin(), hitems.end()); + + qDebug() << " IMHistoryKeeper::loadHistoryFile finished"; + + historyChanged = false; + + return true; +} + +//============================================================================= + +QString IMHistoryKeeper::errorMessage() +{ + QString errorMessage = lastErrorMessage; + lastErrorMessage.clear(); + return errorMessage; +} + +//============================================================================= + +bool IMHistoryKeeper::getMessages(QList &historyItems, const int messagesCount) +{ + int messFound = 0; + + historyItems.clear(); + + QListIterator hii(hitems); + hii.toBack(); + while (hii.hasPrevious()) { + IMHistoryItem hitem = hii.previous(); + + historyItems.insert(historyItems.begin(), hitem); + messFound++; + if (messagesCount && messFound >= messagesCount) { + break; + } + } + + return true; // successful end +} + +//============================================================================= + +bool IMHistoryKeeper::getMessage(int hiid, IMHistoryItem &item) +{ + QList::iterator it; + for (it = hitems.begin(); it != hitems.end(); it++) { + if (it->hiid == hiid) { + item = *it; + return true; + } + } + + return false; +} + +//============================================================================= + +void IMHistoryKeeper::clear() +{ + hitems.clear(); + historyChanged = true; + + lasthiid = 0; + + emit historyClear(); +} + +//============================================================================= + +/*static*/ bool IMHistoryKeeper::compareItem(const IMHistoryItem &item, bool incoming, const std::string &id, const QDateTime &sendTime, const QString &messageText) +{ + // "\n" is not saved in xml + QString copyMessage1(messageText); + copyMessage1.replace("\n", ""); + + QString copyMessage2(item.messageText); + copyMessage2.replace("\n", ""); + + if (item.incoming == incoming && item.id == id && item.sendTime == sendTime && copyMessage1 == copyMessage2) { + return true; + } + + return false; +} + +//============================================================================= + +bool IMHistoryKeeper::findMessage(bool incoming, const std::string &id, const QDateTime &sendTime, const QString &messageText, int &hiid) +{ + hiid = 0; + + QList::const_iterator it; + for (it = hitems.begin(); it != hitems.end(); it++) { + if (compareItem(*it, incoming, id, sendTime, messageText)) { + hiid = it->hiid; + return true; + } + } + + return false; +} + +//============================================================================= + +void IMHistoryKeeper::removeMessage(int hiid) +{ + QList::iterator it; + for (it = hitems.begin(); it != hitems.end(); it++) { + if (it->hiid == hiid) { + emit historyRemove(*it); + hitems.erase(it); + historyChanged = true; + break; + } + } +} + +//============================================================================= + +void IMHistoryKeeper::removeMessages(QList &hiids) +{ + bool changed = false; + + QList::iterator it = hitems.begin(); + while (it != hitems.end()) { + if (qFind(hiids, it->hiid) != hiids.end()) { + emit historyRemove(*it); + + it = hitems.erase(it); + + changed = true; + + continue; + } + it++; + } + + if (changed) { + historyChanged = true; + } +} + +//============================================================================= + +void IMHistoryKeeper::saveHistory() +{ + if (historyChanged && hfName.isEmpty() == false) { + //=== we have to save all messages + qSort( hitems.begin(), hitems.end() ) ; // not nesessary, but just in case... + // it will not take a long time over ordered array + + IMHistoryWriter wri; + wri.write(hitems, hfName); + + historyChanged = false; + } +} diff --git a/retroshare-gui/src/gui/im_history/IMHistoryKeeper.h b/retroshare-gui/src/gui/im_history/IMHistoryKeeper.h new file mode 100644 index 000000000..4349c9c09 --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryKeeper.h @@ -0,0 +1,115 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _HISTORY_KEEPER_H_ +#define _HISTORY_KEEPER_H_ + +#include +#include +#include + +#include "IMHistoryItem.h" + +class QTimer; + +//! An engine for instant messaging history management + +//! This class holds history for instant messages. It stores all messages +//! in xml file. Something like +//! +//! +//! +//! manual message +//! ... +//! other messages in ... tags +//! ... +//! +//! +//! The class loads all messages from the file after creation, and saves them +//! at destruction. This means, the more history user has, the more memory +//! will be used. Maybe it's not good, but it isn't so large, I think + +class IMHistoryKeeper : public QObject +{ + Q_OBJECT + +public: + IMHistoryKeeper(); + + //! A destructor + + //! Warning: history messages will be saved to the file here. This means, + //! a IMHistoryKeeper object must be deleted properly. + virtual ~IMHistoryKeeper(); + + //! last error description + QString errorMessage(); + + //! initialize history keeper + void init(QString historyFileName); + + //! Select messages from history + + //! Fills given list with items + bool getMessages(QList &historyItems, const int messagesCount); + + //! Get message + bool getMessage(int hiid, IMHistoryItem &item); + + //! Adds new message to the history + + //! Adds new message to the history, but the message will be saved to + //! file only after destroing the object + void addMessage(bool incoming, const std::string &id, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &messageText); + + //! Clear the history + void clear(); + + //! Find message + static bool compareItem(const IMHistoryItem &item, bool incoming, const std::string &id, const QDateTime &sendTime, const QString &messageText); + bool findMessage(bool incoming, const std::string &id, const QDateTime &sendTime, const QString &messageText, int &hiid); + + //! Remove item + void removeMessage(int hiid); + + //! Remove items + void removeMessages(QList &hiids); + +private: + bool loadHistoryFile(); + + QList hitems; + QString hfName ; //! history file name + bool historyChanged; + QString lastErrorMessage; + QTimer *saveTimer; + int lasthiid; + +private slots: + void saveHistory(); + +signals: + void historyAdd(IMHistoryItem item) const; + void historyRemove(IMHistoryItem item) const; + void historyClear() const; +}; + +#endif // _HISTORY_KEEPER_H_ diff --git a/retroshare-gui/src/gui/im_history/IMHistoryReader.cpp b/retroshare-gui/src/gui/im_history/IMHistoryReader.cpp new file mode 100644 index 000000000..601b56027 --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryReader.cpp @@ -0,0 +1,206 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "IMHistoryReader.h" + +#include + +#include + +//============================================================================= + +IMHistoryReader::IMHistoryReader() + :errMess("No error") +{ + // nothing to do here +} + +//============================================================================= + +bool IMHistoryReader::read(QList& resultList, const QString fileName, int &lasthiid) +{ + errMess = "No error"; + + resultList.clear(); + + //==== check for file and open it + QFile fl(fileName); + if (fl.exists()) { + fl.open(QIODevice::ReadOnly); + } else { + errMess = QString("file not found (%1)").arg(fileName); + return false ; + } + + //==== set the file, and check it once more + setDevice(&fl); + + if (atEnd()) { + errMess = "end of document reached before anything happened"; + return false; + } + + //==== now, read the first element (it should be document element) + while (!atEnd()) { + readNext(); + if (isStartElement()) { + if (name() == "history_file" && attributes().value("format_version") == "1.0") { + readHistory(resultList, lasthiid); + break; + } else { + errMess = "The file is not a history file with format version 1.0"; + return false ; + } + } + } + + if (error()) { + errMess = errorString(); +// } else { +// QList::const_iterator hii;//history items iterator +// for (hii = result.constBegin(); hii != result.constEnd(); ++hii) { +// resultList << *hii; +// } + } + + return !error(); +} + +//============================================================================= + +QString IMHistoryReader::errorMessage() +{ + QString result = errMess; + errMess = "No error" ; + return result; +} + +//============================================================================= + +void IMHistoryReader::readUnknownElement() +{ + Q_ASSERT(isStartElement()); + + qDebug()<< " " << "unknown node " << name().toString(); + + while (!atEnd()) { + readNext(); + if (isEndElement()) { + break; + } + + if (isStartElement()) { + readUnknownElement(); + } + } +} + +//============================================================================= + +void IMHistoryReader::readHistory(QList &historyItems, int &lasthiid) +{ + Q_ASSERT(isStartElement()); + + // qDebug()<< " " << "node with message " << name() ; + + historyItems.clear(); + lasthiid = 0; + + bool recalculate = false; + + while (!atEnd()) { + readNext(); + if (isEndElement()) { + break; + } + + if (isStartElement()) { + if ( name() == "message") { + IMHistoryItem item; + readMessage(item); + if (item.hiid == 0) { + recalculate = true; + } else { + if (item.hiid > lasthiid) { + lasthiid = item.hiid; + } + } + historyItems.append(item); + } else { + readUnknownElement(); + } + } + } + + if (recalculate) { + // calculate hiid + QList::iterator item = historyItems.begin(); + for (item = historyItems.begin(); item != historyItems.end(); item++) { + if (item->hiid == 0) { + item->hiid = ++lasthiid; + } + } + } +} + +//============================================================================= + +void IMHistoryReader::readMessage(IMHistoryItem &historyItem) +{ +// Q_ASSERT(isStartElement() ); + + if (isStartElement() && (name() == "message")) { + //=== process attributes + + historyItem.hiid = attributes().value("hiid").toString().toInt(); + historyItem.incoming = (attributes().value("incoming").toString().toInt() == 1); + historyItem.id = attributes().value("id").toString().toStdString(); + historyItem.name = attributes().value("name").toString(); + + int ti = attributes().value("sendTime").toString().toInt(); + historyItem.sendTime = QDateTime::fromTime_t(ti); + + ti = attributes().value("recvTime").toString().toInt(); + if (ti) { + historyItem.recvTime = QDateTime::fromTime_t(ti); + } else { + historyItem.recvTime = historyItem.sendTime; + } + + //=== after processing attributes, read the message text + QString tstr = readElementText(); + + //=== remove '\0' chars from the string. Is it a QXmlStuff bug, + // if they appear? + for (int i = 0; i< tstr.length(); i++) { + if (tstr.at(i) == '\n') { + tstr.remove(i, 1); + } + } + + historyItem.messageText = tstr; + + //qDebug() << QString(" readMessage: %1, %2, %3, %4" ) + // .arg(rez.text()).arg(rez.sender()) + // .arg(rez.receiver()).arg(ti) ; + } +} + diff --git a/retroshare-gui/src/gui/im_history/IMHistoryReader.h b/retroshare-gui/src/gui/im_history/IMHistoryReader.h new file mode 100644 index 000000000..509c301a4 --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryReader.h @@ -0,0 +1,50 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef __IM_History_reader__ +#define __IM_History_reader__ + +#include + +#include +#include + +#include "IMHistoryItem.h" + +class IMHistoryReader : public QXmlStreamReader +{ +public: + IMHistoryReader(); + + bool read(QList& resultList, const QString fileName, int &lasthiid); + + QString errorMessage(); + +private: + void readUnknownElement(); + void readHistory(QList &historyItems, int &lasthiid); + void readMessage(IMHistoryItem &historyItem); + + QString errMess; +} ; + +#endif + diff --git a/retroshare-gui/src/gui/im_history/IMHistoryWriter.cpp b/retroshare-gui/src/gui/im_history/IMHistoryWriter.cpp new file mode 100644 index 000000000..2251e59a8 --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryWriter.cpp @@ -0,0 +1,93 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "IMHistoryWriter.h" + +#include +#include +#include + +//============================================================================= + +IMHistoryWriter::IMHistoryWriter() + :errMess("No error") +{ + // nothing to do here +} + +//============================================================================= + +bool IMHistoryWriter::write(QList& itemList, const QString fileName) +{ + qDebug() << " IMHistoryWriter::write is here" ; + + errMess = "No error"; + + if (itemList.size() == 0) { + return remove(fileName); + } + + //==== check for file and open it + QFile fl(fileName); + if (fl.open(QIODevice::WriteOnly | QIODevice::Truncate) == false) { + errMess = QString("error opening file %1 (code %2)") + .arg(fileName).arg( fl.error() ); + return false; + } + + //==== set the file, and check it once more + setDevice(&fl); + + writeStartDocument(); + writeDTD(""); + writeStartElement("history_file"); + writeAttribute("format_version", "1.0"); + + foreach(IMHistoryItem item, itemList) { + writeStartElement("message"); + writeAttribute("hiid", QString::number(item.hiid)); + writeAttribute("incoming", QString::number(item.incoming ? 1 : 0)); + writeAttribute("id", QString::fromStdString(item.id)); + writeAttribute("name", item.name); + writeAttribute("sendTime", QString::number(item.sendTime.toTime_t())); + writeAttribute("recvTime", QString::number(item.recvTime.toTime_t())); + writeCDATA(item.messageText); + writeEndElement(); + } + + writeEndDocument() ; + + fl.close(); + + qDebug() << " IMHistoryWriter::write done" ; + + return true; +} + +bool IMHistoryWriter::remove(const QString &fileName) +{ + if (!QFile::remove(fileName)) { + qDebug() << " IMHistoryWriter::remove Failed to remove history file"; + return false; + } + + return true; +} diff --git a/retroshare-gui/src/gui/im_history/IMHistoryWriter.h b/retroshare-gui/src/gui/im_history/IMHistoryWriter.h new file mode 100644 index 000000000..5a2a0c9a2 --- /dev/null +++ b/retroshare-gui/src/gui/im_history/IMHistoryWriter.h @@ -0,0 +1,53 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef __IM_History_writer__ +#define __IM_History_writer__ + +#include + +#include +//#include + +#include "IMHistoryItem.h" + +class IMHistoryWriter : public QXmlStreamWriter +{ +public: + IMHistoryWriter(); + + bool write(QList& itemList, + const QString fileName ); + + //! remove history file + bool remove(const QString& fileName); + + QString errorMessage(); + +private: + + + QString errMess; +} ; + + + +#endif diff --git a/retroshare-gui/src/gui/im_history/ImHistoryBrowser.cpp b/retroshare-gui/src/gui/im_history/ImHistoryBrowser.cpp new file mode 100644 index 000000000..33794be46 --- /dev/null +++ b/retroshare-gui/src/gui/im_history/ImHistoryBrowser.cpp @@ -0,0 +1,515 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 The RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ImHistoryBrowser.h" +#include "IMHistoryItemDelegate.h" +#include "IMHistoryItemPainter.h" + +#include "rshare.h" +#include "gui/settings/rsharesettings.h" +#include "gui/notifyqt.h" + +#define ROLE_HIID Qt::UserRole +#define ROLE_PLAINTEXT Qt::UserRole + 1 +#define ROLE_OFFLINE Qt::UserRole + 2 + +ImHistoryBrowserCreateItemsThread::ImHistoryBrowserCreateItemsThread(ImHistoryBrowser *parent, IMHistoryKeeper &histKeeper) + : QThread(parent), m_historyKeeper(histKeeper) +{ + m_historyBrowser = parent; + stopped = false; +} + +ImHistoryBrowserCreateItemsThread::~ImHistoryBrowserCreateItemsThread() +{ + // remove all items (when items are available, the thread was terminated) + QList::iterator it; + for (it = m_items.begin(); it != m_items.end(); it++) { + delete(*it); + } + + m_items.clear(); +} + +void ImHistoryBrowserCreateItemsThread::stop() +{ + disconnect(); + stopped = true; + wait(); +} + +void ImHistoryBrowserCreateItemsThread::run() +{ + QList historyItems; + m_historyKeeper.getMessages(historyItems, 0); + + int count = historyItems.count(); + int current = 0; + + foreach(IMHistoryItem item, historyItems) { + if (stopped) { + break; + } + QListWidgetItem *itemWidget = m_historyBrowser->createItem(item); + if (itemWidget) { + m_items.push_back(itemWidget); + emit progress(++current, count); + } + } +} + +/** Default constructor */ +ImHistoryBrowser::ImHistoryBrowser(const std::string &peerId, IMHistoryKeeper &histKeeper, QTextEdit *edit, QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags), historyKeeper(histKeeper) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + m_peerId = peerId; + m_isPrivateChat = !m_peerId.empty(); + textEdit = edit; + + connect(&historyKeeper, SIGNAL(historyAdd(IMHistoryItem)), this, SLOT(historyAdd(IMHistoryItem))); + connect(&historyKeeper, SIGNAL(historyRemove(IMHistoryItem)), this, SLOT(historyRemove(IMHistoryItem))); + connect(&historyKeeper, SIGNAL(historyClear()), this, SLOT(historyClear())); + + connect(ui.clearFilterButton, SIGNAL(clicked()), this, SLOT(clearFilter())); + connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged())); + + connect(ui.copyButton, SIGNAL(clicked()), SLOT(copyMessage())); + connect(ui.removeButton, SIGNAL(clicked()), SLOT(removeMessages())); + + connect(ui.listWidget, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged())); + connect(ui.listWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint))); + + connect(NotifyQt::getInstance(), SIGNAL(privateChatChanged(int,int)), this, SLOT(privateChatChanged(int,int))); + + ui.clearFilterButton->hide(); + + // embed smileys ? + if (m_isPrivateChat) { + embedSmileys = Settings->valueFromGroup("Chat", "Emoteicons_PrivatChat", true).toBool(); + } else { + embedSmileys = Settings->valueFromGroup("Chat", "Emoteicons_GroupChat", true).toBool(); + } + + style.setStyleFromSettings(ChatStyle::TYPE_HISTORY); + + ui.listWidget->setItemDelegate(new IMHistoryItemDelegate); + + // call once + privateChatChanged(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_ADD); + + QByteArray geometry = Settings->valueFromGroup("HistorieBrowser", "Geometry", QByteArray()).toByteArray(); + if (geometry.isEmpty() == false) { + restoreGeometry(geometry); + } + + // dummy call for set buttons + itemSelectionChanged(); + + ui.listWidget->installEventFilter(this); + + m_createThread = new ImHistoryBrowserCreateItemsThread(this, historyKeeper); + connect(m_createThread, SIGNAL(finished()), this, SLOT(createThreadFinished())); + connect(m_createThread, SIGNAL(progress(int,int)), this, SLOT(createThreadProgress(int,int))); + m_createThread->start(); +} + +ImHistoryBrowser::~ImHistoryBrowser() +{ + Settings->setValueToGroup("HistorieBrowser", "Geometry", saveGeometry()); + + if (m_createThread) { + m_createThread->stop(); + delete(m_createThread); + m_createThread = NULL; + } +} + +void ImHistoryBrowser::createThreadFinished() +{ + if (m_createThread == sender()) { + ui.progressBar->setVisible(false); + + if (!m_createThread->wasStopped()) { + // append created items + QList::iterator it; + for (it = m_createThread->m_items.begin(); it != m_createThread->m_items.end(); it++) { + ui.listWidget->addItem(*it); + } + + // clear list + m_createThread->m_items.clear(); + + filterRegExpChanged(); + + // dummy call for set buttons + itemSelectionChanged(); + + m_createThread->deleteLater(); + m_createThread = NULL; + + QList::iterator histIt; + for (histIt = m_itemsAddedOnLoad.begin(); histIt != m_itemsAddedOnLoad.end(); histIt++) { + historyAdd(*histIt); + } + m_itemsAddedOnLoad.clear(); + } + } +} + +void ImHistoryBrowser::createThreadProgress(int current, int count) +{ + if (count) { + ui.progressBar->setValue(current * ui.progressBar->maximum() / count); + } +} + +bool ImHistoryBrowser::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == ui.listWidget) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent && keyEvent->key() == Qt::Key_Delete) { + // Delete pressed + removeMessages(); + return true; // eat event + } + } + } + // pass the event on to the parent class + return QDialog::eventFilter(obj, event); +} + +void ImHistoryBrowser::historyAdd(IMHistoryItem item) +{ + if (m_createThread) { + // create later + m_itemsAddedOnLoad.push_back(item); + return; + } + + QListWidgetItem *itemWidget = createItem(item); + if (itemWidget) { + ui.listWidget->addItem(itemWidget); + filterItems(itemWidget); + } +} + +void ImHistoryBrowser::historyRemove(IMHistoryItem item) +{ + int count = ui.listWidget->count(); + for (int i = 0; i < count; i++) { + QListWidgetItem *itemWidget = ui.listWidget->item(i); + if (itemWidget->data(ROLE_HIID).toString().toInt() == item.hiid) { + delete(ui.listWidget->takeItem(i)); + break; + } + } +} + +void ImHistoryBrowser::historyClear() +{ + ui.listWidget->clear(); +} + +void ImHistoryBrowser::fillItem(QListWidgetItem *itemWidget, IMHistoryItem &item) +{ + unsigned int formatFlag = CHAT_FORMATMSG_EMBED_LINKS; + + if (embedSmileys) { + formatFlag |= CHAT_FORMATMSG_EMBED_SMILEYS; + } + + std::list::iterator offineChatIt; + for(offineChatIt = m_savedOfflineChat.begin(); offineChatIt != m_savedOfflineChat.end(); offineChatIt++) { + /* are they public? */ + if ((offineChatIt->chatflags & RS_CHAT_PRIVATE) == 0) { + /* this should not happen */ + continue; + } + + QDateTime sendTime = QDateTime::fromTime_t(offineChatIt->sendTime); + QString message = QString::fromStdWString(offineChatIt->msg); + + if (IMHistoryKeeper::compareItem(item, false, offineChatIt->rsid, sendTime, message)) { + break; + } + } + + ChatStyle::enumFormatMessage type; + if (offineChatIt == m_savedOfflineChat.end()) { + if (item.incoming) { + type = ChatStyle::FORMATMSG_INCOMING; + } else { + type = ChatStyle::FORMATMSG_OUTGOING; + } + } else { + type = ChatStyle::FORMATMSG_OOUTGOING; + } + + QString formatMsg = style.formatMessage(type, item.name, item.sendTime, item.messageText, formatFlag); + + itemWidget->setData(Qt::DisplayRole, qVariantFromValue(IMHistoryItemPainter(formatMsg))); + itemWidget->setData(ROLE_HIID, item.hiid); + itemWidget->setData(ROLE_OFFLINE, (type == ChatStyle::FORMATMSG_OOUTGOING) ? true : false); + + /* calculate plain text */ + QTextDocument doc; + doc.setHtml(item.messageText); + itemWidget->setData(ROLE_PLAINTEXT, doc.toPlainText()); +} + +QListWidgetItem *ImHistoryBrowser::createItem(IMHistoryItem &item) +{ + QListWidgetItem *itemWidget = new QListWidgetItem; + fillItem(itemWidget, item); + return itemWidget; +} + +void ImHistoryBrowser::filterRegExpChanged() +{ + QString text = ui.filterPatternLineEdit->text(); + + if (text.isEmpty()) { + ui.clearFilterButton->hide(); + } else { + ui.clearFilterButton->show(); + } + + filterItems(); +} + +void ImHistoryBrowser::clearFilter() +{ + ui.filterPatternLineEdit->clear(); + ui.filterPatternLineEdit->setFocus(); +} + +void ImHistoryBrowser::filterItems(QListWidgetItem *item) +{ + QString text = ui.filterPatternLineEdit->text(); + + if (item == NULL) { + int count = ui.listWidget->count(); + for (int i = 0; i < count; i++) { + item = ui.listWidget->item(i); + if (text.isEmpty()) { + item->setHidden(false); + } else { + if (item->data(ROLE_PLAINTEXT).toString().contains(text, Qt::CaseInsensitive)) { + item->setHidden(false); + } else { + item->setHidden(true); + } + } + } + } else { + if (text.isEmpty()) { + item->setHidden(false); + } else { + if (item->data(ROLE_PLAINTEXT).toString().contains(text, Qt::CaseInsensitive)) { + item->setHidden(false); + } else { + item->setHidden(true); + } + } + } +} + +void ImHistoryBrowser::getSelectedItems(QList &items) +{ + QList itemWidgets = ui.listWidget->selectedItems(); + + QList::iterator it; + for (it = itemWidgets.begin(); it != itemWidgets.end(); it++) { + QListWidgetItem *item = *it; + if (item->isHidden()) { + continue; + } + items.append(item->data(ROLE_HIID).toString().toInt()); + } +} + +void ImHistoryBrowser::itemSelectionChanged() +{ + QList hiids; + getSelectedItems(hiids); + + if (hiids.size()) { + // activate buttons + ui.copyButton->setEnabled(true); + ui.removeButton->setEnabled(true); + } else { + // deactivate buttons + ui.copyButton->setDisabled(true); + ui.removeButton->setDisabled(true); + } +} + +void ImHistoryBrowser::customContextMenuRequested(QPoint pos) +{ + QList hiids; + getSelectedItems(hiids); + + QListWidgetItem *currentItem = ui.listWidget->currentItem(); + + QMenu contextMnu(this); + + QAction *selectAll = new QAction(tr("Mark all"), &contextMnu); + QAction *copyMessage = new QAction(tr("Copy"), &contextMnu); + QAction *removeMessages = new QAction(tr("Delete"), &contextMnu); + QAction *clearHistory = new QAction(tr("Clear history"), &contextMnu); + + QAction *sendItem = NULL; + if (textEdit) { + sendItem = new QAction(tr("Send"), &contextMnu); + if (currentItem) { + connect(sendItem, SIGNAL(triggered()), this, SLOT(sendMessage())); + } else { + sendItem->setDisabled(true); + } + } + + if (hiids.size()) { + connect(selectAll, SIGNAL(triggered()), ui.listWidget, SLOT(selectAll())); + connect(copyMessage, SIGNAL(triggered()), this, SLOT(copyMessage())); + connect(removeMessages, SIGNAL(triggered()), this, SLOT(removeMessages())); + connect(clearHistory, SIGNAL(triggered()), this, SLOT(clearHistory())); + } else { + selectAll->setDisabled(true); + copyMessage->setDisabled(true); + removeMessages->setDisabled(true); + clearHistory->setDisabled(true); + } + + contextMnu.addAction(selectAll); + contextMnu.addSeparator(); + contextMnu.addAction(copyMessage); + contextMnu.addAction(removeMessages); + contextMnu.addAction(clearHistory); + if (sendItem) { + contextMnu.addSeparator(); + contextMnu.addAction(sendItem); + } + + contextMnu.exec(QCursor::pos()); +} + +void ImHistoryBrowser::copyMessage() +{ + QListWidgetItem *currentItem = ui.listWidget->currentItem(); + if (currentItem) { + int hiid = currentItem->data(ROLE_HIID).toString().toInt(); + IMHistoryItem item; + if (historyKeeper.getMessage(hiid, item)) { + QTextDocument doc; + doc.setHtml(item.messageText); + QApplication::clipboard()->setText(doc.toPlainText()); + } + } +} + +void ImHistoryBrowser::removeMessages() +{ + QList hiids; + getSelectedItems(hiids); + + historyKeeper.removeMessages(hiids); +} + +void ImHistoryBrowser::clearHistory() +{ + historyKeeper.clear(); +} + +void ImHistoryBrowser::sendMessage() +{ + if (textEdit) { + QListWidgetItem *currentItem = ui.listWidget->currentItem(); + if (currentItem) { + int hiid = currentItem->data(ROLE_HIID).toString().toInt(); + IMHistoryItem item; + if (historyKeeper.getMessage(hiid, item)) { + textEdit->clear(); + textEdit->setText(item.messageText); + textEdit->setFocus(); + QTextCursor cursor = textEdit->textCursor(); + cursor.movePosition(QTextCursor::End); + textEdit->setTextCursor(cursor); + close(); + } + } + } +} + +void ImHistoryBrowser::privateChatChanged(int list, int type) +{ + if (m_isPrivateChat == false) { + return; + } + + if (list == NOTIFY_LIST_PRIVATE_OUTGOING_CHAT) { + switch (type) { + case NOTIFY_TYPE_ADD: + { + m_savedOfflineChat.clear(); + rsMsgs->getPrivateChatQueueCount(false) && rsMsgs->getPrivateChatQueue(false, m_peerId, m_savedOfflineChat); + } + break; + case NOTIFY_TYPE_DEL: + { + m_savedOfflineChat.clear(); + } + break; + } + + // recalculate items in history + int count = ui.listWidget->count(); + for (int i = 0; i < count; i++) { + QListWidgetItem *itemWidget = ui.listWidget->item(i); + + if (itemWidget->data(ROLE_OFFLINE).toBool()) { + int hiid = itemWidget->data(ROLE_HIID).toInt(); + + IMHistoryItem item; + if (historyKeeper.getMessage(hiid, item) == false) { + continue; + } + + fillItem(itemWidget, item); + } + } + + filterRegExpChanged(); + } +} diff --git a/retroshare-gui/src/gui/im_history/ImHistoryBrowser.h b/retroshare-gui/src/gui/im_history/ImHistoryBrowser.h new file mode 100644 index 000000000..89295dfef --- /dev/null +++ b/retroshare-gui/src/gui/im_history/ImHistoryBrowser.h @@ -0,0 +1,121 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 The RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _IMHISTORYBROWSER_H +#define _IMHISTORYBROWSER_H + +#include +#include + +#include +#include "IMHistoryKeeper.h" +#include "gui/chat/ChatStyle.h" + +#include "ui_ImHistoryBrowser.h" + +class QTextEdit; +class ImHistoryBrowserCreateItemsThread; + +class ImHistoryBrowser : public QDialog +{ + Q_OBJECT + + friend class ImHistoryBrowserCreateItemsThread; + +public: + /** Default constructor */ + ImHistoryBrowser(const std::string &peerId, IMHistoryKeeper &histKeeper, QTextEdit *edit, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + virtual ~ImHistoryBrowser(); + +protected: + bool eventFilter(QObject *obj, QEvent *ev); + +private slots: + void createThreadFinished(); + void createThreadProgress(int current, int count); + + void historyAdd(IMHistoryItem item); + void historyRemove(IMHistoryItem item); + void historyClear(); + + void filterRegExpChanged(); + void clearFilter(); + + void itemSelectionChanged(); + void customContextMenuRequested(QPoint pos); + + void copyMessage(); + void removeMessages(); + void clearHistory(); + void sendMessage(); + + void privateChatChanged(int list, int type); + +private: + QListWidgetItem *createItem(IMHistoryItem &item); + void fillItem(QListWidgetItem *itemWidget, IMHistoryItem &item); + void filterItems(QListWidgetItem *item = NULL); + + void getSelectedItems(QList &items); + + ImHistoryBrowserCreateItemsThread *m_createThread; + + std::string m_peerId; + bool m_isPrivateChat; + QTextEdit *textEdit; + bool embedSmileys; + IMHistoryKeeper &historyKeeper; + ChatStyle style; + + std::list m_savedOfflineChat; + QList m_itemsAddedOnLoad; + + /** Qt Designer generated object */ + Ui::ImHistoryBrowser ui; +}; + +class ImHistoryBrowserCreateItemsThread : public QThread +{ + Q_OBJECT + +public: + ImHistoryBrowserCreateItemsThread(ImHistoryBrowser *parent, IMHistoryKeeper &histKeeper); + ~ImHistoryBrowserCreateItemsThread(); + + void run(); + void stop(); + bool wasStopped() { return stopped; } + +signals: + void progress(int current, int count); + +public: + QList m_items; + +private: + IMHistoryKeeper &m_historyKeeper; + ImHistoryBrowser *m_historyBrowser; + volatile bool stopped; +}; + +#endif diff --git a/retroshare-gui/src/gui/im_history/ImHistoryBrowser.ui b/retroshare-gui/src/gui/im_history/ImHistoryBrowser.ui new file mode 100644 index 000000000..e7f986c27 --- /dev/null +++ b/retroshare-gui/src/gui/im_history/ImHistoryBrowser.ui @@ -0,0 +1,324 @@ + + + ImHistoryBrowser + + + + 0 + 0 + 502 + 387 + + + + Message History + + + + :/images/rstray3.png:/images/rstray3.png + + + true + + + + 0 + + + 0 + + + + + QFrame#frame_2{background-image: url(:/images/connect/connectFriendBanner.png)} + + + QFrame::NoFrame + + + QFrame::Plain + + + 1 + + + + 6 + + + 2 + + + 2 + + + 2 + + + 9 + + + 6 + + + + + + 64 + 64 + + + + + 64 + 64 + + + + + + + :/images/user/agt_forum64.png + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + + + + + + + 16777215 + 38 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + 1 + + + + + + + + :/images/find-16.png + + + + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + Reset + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + + + + Qt::NoFocus + + + Copy + + + + :/images/copy.png:/images/copy.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Qt::NoFocus + + + Remove + + + + :/images/delete.png:/images/delete.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 9 + + + + + Qt::CustomContextMenu + + + QAbstractItemView::ExtendedSelection + + + + + + + 6 + + + + + Qt::Horizontal + + + + 404 + 20 + + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Close + + + + + + + + + 1000 + + + 0 + + + false + + + + + + + + + + + + + buttonBox + rejected() + ImHistoryBrowser + reject() + + + 427 + 310 + + + 237 + 166 + + + + + diff --git a/retroshare-gui/src/gui/images.qrc b/retroshare-gui/src/gui/images.qrc new file mode 100644 index 000000000..b093229a4 --- /dev/null +++ b/retroshare-gui/src/gui/images.qrc @@ -0,0 +1,559 @@ + + + images/splash.png + images/attach.png + images/audio-x-monkey.png + images/video-x-generic.png + images/application-x-rar.png + images/application-draw.png + images/pgp.png + images/rs_wizard.png + images/about.png + images/backblue.png + images/backchat.png + images/buttonframe.png + images/btn1.png + images/btn2.png + images/btn3.png + images/btn4.png + images/btn_26.png + images/btn_26_hover.png + images/btn_26_pressed.png + images/btn_27.png + images/btn_27_hover.png + images/connect_established.png + images/connect_creating.png + images/connect_no.png + images/dht16.png + images/edit-clear-history.png + images/edit_16.png + images/feedback_arrow.png + images/feedback_arrow_hover.png + images/list_bullet_arrow.png + images/rc_combined.png + images/combobox_arrow.png + images/arrow-left.png + images/arrow-right.png + help/authors.html + help/licence.html + help/thanks.html + images/accepted16.png + images/add_image24.png + images/add_channel64.png + images/add_channel24.png + images/add_channel32.png + images/user/add_group22.png + images/user/add_group256.png + images/avatarstatus_bg.png + images/avatarstatus_bg_online.png + images/avatarstatus_bg_away.png + images/avatarstatus_bg_busy.png + images/avatarstatus_bg_offline.png + images/browse-looking.gif + images/back.png + images/backgroundl.png + images/blockdevice.png + images/blockdevice2.png + images/configure.png + images/channels.png + images/turtle.png + images/channels16.png + images/channels24.png + images/channels32.png + images/channels_new32.png + images/copyrslink.png + images/contacts24.png + images/connection.png + images/contact_new.png + images/contact.png + images/Client0.png + images/Client1.png + images/Client2.png + images/Client3.png + images/Client4.png + images/closenormal.png + images/closehover.png + images/closepressed.png + images/denied16.png + images/filetype-association.png + images/FileTypeAny.png + images/FileTypeArchive.png + images/FileTypeAudio.png + images/FileTypeCDImage.png + images/FileTypeDocument.png + images/FileTypePicture.png + images/FileTypeProgram.png + images/FileTypeVideo.png + images/finished_background.png + images/fonts.png + images/folder16.png + images/foldermail.png + images/folderopen.png + images/fileopen.png + images/graph-downloaded.png + images/graph-downloading.png + images/graph-notdownload.png + images/add-friend24.png + images/add-share24.png + images/add_24x24.png + images/advsearch_24x24.png + images/amsn.png + images/amsn16.png + images/attachment.png + images/avatar_background.png + images/backgroundimage.png + images/button_cancel.png + images/calendar.png + images/chat.png + images/chat_24.png + images/cancel.png + images/close-down.png + images/close_normal.png + images/console-small-down.png + images/console-small-hover.png + images/console-small-up.png + images/contact_new128.png + images/copy.png + images/delete.png + images/deleteall.png + images/deletemail-pressed.png + images/deletemail24.png + images/directoryadd_24x24_shadow.png + images/directoryremove_24x24_shadow.png + images/directoryselect_24x24_shadow.png + images/diskSave.png + images/document_save.png + images/down.png + images/down_24x24.png + images/download.png + images/download16.png + images/edit_add24.png + images/edit-bold.png + images/edit-italic.png + images/edit-underline.png + images/edit_remove24.png + images/encrypted16.png + images/encrypted22.png + images/encrypted32.png + images/encrypted48.png + images/evolution.png + images/exit_24x24.png + images/expand_frame.png + images/exportpeers_16x16.png + images/extension_32.png + images/filefind.png + images/fileinfo.png + images/filename.png + images/filepriority.png + images/filecomments.png + images/filerating0.png + images/filerating1.png + images/filerating2.png + images/filerating3.png + images/filerating4.png + images/filerating5.png + images/fileshare16.png + images/fileshare24.png + images/fileshare32.png + images/fileshare48.png + images/find.png + images/find-16.png + images/emoticons/kopete/kopete020.png + images/flags/af.png + images/flags/bg.png + images/flags/zh_CN.png + images/flags/zh_TW.png + images/flags/de.png + images/flags/da.png + images/flags/en.png + images/flags/es.png + images/flags/fi.png + images/flags/fr.png + images/flags/gr.png + images/flags/it.png + images/flags/ja_JP.png + images/flags/ko.png + images/flags/pl.png + images/flags/pt.png + images/flags/ru.png + images/flags/sv.png + images/flags/sl.png + images/flags/tr.png + images/folder-draft.png + images/folder-draft24-pressed.png + images/folder-draft24.png + images/folder_inbox64.png + images/folder-inbox.png + images/folder-inbox-new.png + images/folder-outbox.png + images/folder-sent.png + images/folder-trash.png + images/folder_doments.png + images/folder_green.png + images/folder_red.png + images/folder_grey.png + images/folder_yellow.png + images/folder_open.png + images/folder_video.png + images/folder_blueshared.png + images/forward.png + images/friendsfolder24.png + images/kgames.png + images/go-down.png + images/go-top.png + images/go-up.png + images/go-bottom.png + images/graph-area.png + images/graph-line.png + images/groupchat.png + images/genbackground.png + images/gohome.png + images/gpgp_key_generate.png + images/help.png + images/help24.png + images/hide_toolbox_frame.png + images/hide_frame.png + images/highlight.png + images/hi16-app-ktorrent.png + images/hot_0.png + images/hot_1.png + images/hot_2.png + images/hot_3.png + images/hot_4.png + images/hot_5.png + images/image16.png + images/info16.png + images/im-user.png + images/im-user-offline.png + images/im-user-away.png + images/im-user-busy.png + images/im-user-inactive.png + images/informations_24x24.png + images/invite-friend24.png + images/connect_friend.png + images/kalarm.png + images/kbackgammon.png + images/kblogger.png + images/hi48-app-kblogger.png + images/hi64-app-kblogger.png + images/kcmsystem24.png + images/kdmconfig.png + images/konsole.png + images/konqsidebar_news16.png + images/konqsidebar_news24.png + images/konversation.png + images/konversation_new.png + images/konversation16.png + images/konversation128.png + images/konv_message2.png + images/konversation64.png + images/ksysguard.png + images/ksysguard32.png + images/ktorrent.png + images/ktorrent32.png + images/knewsticker24.png + images/library.png + images/loadcert16.png + images/ledoff1.png + images/ledon1.png + images/locale.png + images/looknfeel.png + images/lphoto.png + images/lphoto16.png + images/lphoto24.png + images/logobar/logo_bar_fill.png + images/logobar/logo_bar_start.png + images/logobar/rslogo.png + images/logobar/rslogo2.png + images/mail-signed.png + images/mail-signature-unknown.png + images/mail_delete.png + images/mail_get.png + images/mail_reply.png + images/mail_replyall.png + images/mail_forward.png + images/mail_send.png + images/mail_new.png + images/mail_send24.png + images/mailforward24-hover.png + images/message-mail.png + images/message-mail-read.png + images/message-mail-imapdelete.png + images/message-mail-replied-read.png + images/message-mail-forwarded-read.png + images/message-mail-replied.png + images/message-mail-forwarded.png + images/message-mail-replied-forw.png + images/message-mail-replied-forw-read.png + images/message-state-read.png + images/message-state-unread.png + images/message-state-header.png + images/message-state-new.png + images/message-news.png + images/message.png + images/messages_new.png + images/messenger.png + images/mystatus_bg_idle.png + images/mystatus_bg_busy.png + images/mystatus_bg_online.png + images/mystatus_bg_offline.png + images/mystatus_bg.png + images/network.png + images/network16.png + images/network32.png + images/new-mail-alert.png + images/new_forum16.png + images/newmsg.png + images/no_avatar.png + images/no_avatar_70.png + images/no_avatar_background.png + images/openimage.png + images/pasterslink.png + images/package_games1.png + images/peerdetails_16x16.png + images/peers_16x16.png + images/peers_24x24.png + images/print24.png + images/priorityauto.png + images/priorityhigh.png + images/prioritylow.png + images/prioritynormal.png + images/pause.png + images/preview.png + images/player_play.png + images/quick_restart24.png + images/quote_24.png + images/redled.png + images/greenled.png + images/grayled.png + images/yellowled.png + images/rate-1.png + images/rate-2.png + images/rate-3.png + images/rate-4.png + images/rate-5.png + images/rating.png + images/records.png + images/records.png + images/removefriend16.png + images/replymail-pressed.png + images/replymail24.png + images/replymailall24-hover.png + images/reload24.png + images/reset.png + images/resume.png + images/RetroShare16.png + images/retrosharelogo1.png + images/retrosharelogo2.png + images/retrosharelogo32.png + images/rs1.png + images/rs-2.png + images/rsmessenger16.png + images/rsmessenger32.png + images/rstray3.png + images/rstray0.png + images/rstray1.png + images/rstray2.png + images/rstray_new.png + images/security-high-16.png + images/security-high-48.png + images/security-low-48.png + images/security-medium-48.png + images/security-high-off-48.png + images/security-low-off-48.png + images/security-medium-off-48.png + images/save24.png + images/send24.png + images/settings.png + images/settings16.png + images/show_toolbox_frame.png + images/start.png + images/stop.png + images/star-on-16.png + images/star-off-16.png + images/StatsCumulative.png + images/StatisticsDetail.png + images/status_unknown.png + images/startall.png + images/server_24x24.png + images/sort_incr.png + images/sort_decrease.png + images/sound.png + images/tab-dock.png + images/tab-undock.png + images/tag24.png + images/transferupdown.png + images/transfers_new32.png + images/tools_wizard.png + images/typing.png + images/trustsettings.png + images/uploads.png + images/loader/16-loader.gif + images/loader/32-loader.gif + images/loader/progress.gif + images/mimetypes/pdf.png + images/view-certificate-copy-32.png + images/view-certificate-export-32.png + images/textedit/textbold.png + images/textedit/textitalic.png + images/textedit/textunder.png + images/textedit/textjustify.png + images/textedit/textcenter.png + images/textedit/textleft.png + images/textedit/textright.png + images/textedit/editcopy.png + images/textedit/editcut.png + images/textedit/editpaste.png + images/textedit/editredo.png + images/textedit/editundo.png + images/textedit/exportpdf.png + images/textedit/filenew.png + images/textedit/fileopen.png + images/textedit/fileprint.png + images/textedit/filesave.png + images/textedit/format-text-color.png + images/textedit/format-list-ordered.png + images/textedit/format-list-unordered.png + images/textedit/zoomin.png + images/textedit/zoomout.png + images/textedit/format_font_size_more.png + images/textedit/format_font_size_less.png + images/textedit/hi22-action-format-text-blockquote.png + images/textedit/hi22-action-format-text-code.png + images/textedit/hi22-action-insert-more-mark.png + images/toaster/chat.png + images/toaster/hangup.png + images/toaster/pickup.png + images/toaster/backgroundtoaster.png + images/thumb-default-video.png + images/user/add_user24.png + images/user/add_user48.png + images/user/deny_user48.png + images/user/friends24.png + images/user/identity16.png + images/user/identity24.png + images/user/identity32.png + images/user/identity48.png + images/user/identityoffline24.png + images/user/identity24away.png + images/user/identity24busy.png + images/user/identity24idle.png + images/user/identityavaiblecyan24.png + images/user/agt_forum24.png + images/user/identitygray16.png + images/user/add_user16.png + images/user/personal64.png + images/user/personal128.png + images/user/kuser24.png + images/user/agt_forum64.png + images/user/agt_forum128.png + images/user/group16.png + images/user/group24.png + images/up.png + images/up0down0.png + images/up0down1.png + images/up1down1.png + images/up1down0.png + images/underconstruction.png + images/user.png + images/view-certificate-sign-32.png + images/view_calendar_day.png + images/view_calendar_week.png + images/view_calendar_month.png + images/view_calendar_list.png + images/view_split_top_bottom.png + images/window_fullscreen.png + images/window_nofullscreen.png + layouts/default.ui + qss/chat/private/info.xml + qss/chat/private/incoming.htm + qss/chat/private/outgoing.htm + qss/chat/private/hincoming.htm + qss/chat/private/houtgoing.htm + qss/chat/private/ooutgoing.htm + qss/chat/private/main.css + qss/chat/private/variants/Standard.css + qss/chat/public/info.xml + qss/chat/public/incoming.htm + qss/chat/public/outgoing.htm + qss/chat/public/hincoming.htm + qss/chat/public/houtgoing.htm + qss/chat/public/ooutgoing.htm + qss/chat/public/main.css + qss/chat/public/variants/Standard.css + qss/chat/history/info.xml + qss/chat/history/incoming.htm + qss/chat/history/outgoing.htm + qss/chat/history/hincoming.htm + qss/chat/history/houtgoing.htm + qss/chat/history/ooutgoing.htm + qss/chat/history/main.css + qss/chat/history/variants/Standard.css + smileys/amorous.png + smileys/angry.png + smileys/bad.png + smileys/beer.png + smileys/cake.png + smileys/camera.png + smileys/cat.png + smileys/clock.png + smileys/coffee.png + smileys/coins.png + smileys/confused.png + smileys/crying.png + smileys/embarrassed.png + smileys/eyeroll.png + smileys/excited.png + smileys/face-devil-grin48.png + smileys/happy.png + smileys/in-love.png + smileys/island.png + smileys/kissing.png + smileys/laugh.png + smileys/liquor.png + smileys/love-over.png + smileys/love.png + smileys/mobile.png + smileys/moon.png + smileys/party.png + smileys/peace.png + smileys/phone.png + smileys/pirate.png + smileys/pizza.png + smileys/pouty.png + smileys/pumpkin.png + smileys/rotfl.png + smileys/sad.png + smileys/shocked.png + smileys/sleeping.png + smileys/tongue.png + smileys/umbrella.png + smileys/wink.png + smileys/emotes.acs + smileys/moon.png + smileys/lamp.png + smileys/good.png + smileys/drink.png + smileys/airplane.png + smileys/turtle.png + smileys/time-out.png + smileys/weather-overcast.png + smileys/weather-few-clouds.png + smileys/weather-clear.png + smileys/weather-clear-night.png + smileys/weather-few-clouds-night.png + smileys/weather-severe-alert.png + smileys/weather-showers.png + smileys/weather-showers-scattered.png + smileys/weather-snow.png + smileys/weather-storm.png + smileys/weather-showers.png + images/connect/connectFriendWatermark.png + images/connect/connectFriendLogo.png + images/connect/connectFriendBanner.png + images/connect/info16.png + images/connect/mail_send.png + help/version.html + images/view-certificate-sign-48.png + + diff --git a/retroshare-gui/src/gui/images/COPYING b/retroshare-gui/src/gui/images/COPYING new file mode 100644 index 000000000..c6b1bb9c9 --- /dev/null +++ b/retroshare-gui/src/gui/images/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/retroshare-gui/src/gui/images/Client0.png b/retroshare-gui/src/gui/images/Client0.png new file mode 100644 index 000000000..5585cf80f Binary files /dev/null and b/retroshare-gui/src/gui/images/Client0.png differ diff --git a/retroshare-gui/src/gui/images/Client1.png b/retroshare-gui/src/gui/images/Client1.png new file mode 100644 index 000000000..b495f7db4 Binary files /dev/null and b/retroshare-gui/src/gui/images/Client1.png differ diff --git a/retroshare-gui/src/gui/images/Client2.png b/retroshare-gui/src/gui/images/Client2.png new file mode 100644 index 000000000..68acf1166 Binary files /dev/null and b/retroshare-gui/src/gui/images/Client2.png differ diff --git a/retroshare-gui/src/gui/images/Client3.png b/retroshare-gui/src/gui/images/Client3.png new file mode 100644 index 000000000..16139a95a Binary files /dev/null and b/retroshare-gui/src/gui/images/Client3.png differ diff --git a/retroshare-gui/src/gui/images/Client4.png b/retroshare-gui/src/gui/images/Client4.png new file mode 100644 index 000000000..31708ec64 Binary files /dev/null and b/retroshare-gui/src/gui/images/Client4.png differ diff --git a/retroshare-gui/src/gui/images/Eterm.png b/retroshare-gui/src/gui/images/Eterm.png new file mode 100644 index 000000000..b2027f5a9 Binary files /dev/null and b/retroshare-gui/src/gui/images/Eterm.png differ diff --git a/retroshare-gui/src/gui/images/FileTypeAny.png b/retroshare-gui/src/gui/images/FileTypeAny.png new file mode 100644 index 000000000..34e64b73c Binary files /dev/null and b/retroshare-gui/src/gui/images/FileTypeAny.png differ diff --git a/retroshare-gui/src/gui/images/FileTypeArchive.png b/retroshare-gui/src/gui/images/FileTypeArchive.png new file mode 100644 index 000000000..b982beb6c Binary files /dev/null and b/retroshare-gui/src/gui/images/FileTypeArchive.png differ diff --git a/retroshare-gui/src/gui/images/FileTypeAudio.png b/retroshare-gui/src/gui/images/FileTypeAudio.png new file mode 100644 index 000000000..988b27bf7 Binary files /dev/null and b/retroshare-gui/src/gui/images/FileTypeAudio.png differ diff --git a/retroshare-gui/src/gui/images/FileTypeCDImage.png b/retroshare-gui/src/gui/images/FileTypeCDImage.png new file mode 100644 index 000000000..cb3ae8289 Binary files /dev/null and b/retroshare-gui/src/gui/images/FileTypeCDImage.png differ diff --git a/retroshare-gui/src/gui/images/FileTypeDocument.png b/retroshare-gui/src/gui/images/FileTypeDocument.png new file mode 100644 index 000000000..41d20a5c3 Binary files /dev/null and b/retroshare-gui/src/gui/images/FileTypeDocument.png differ diff --git a/retroshare-gui/src/gui/images/FileTypePicture.png b/retroshare-gui/src/gui/images/FileTypePicture.png new file mode 100644 index 000000000..7e9bb14f6 Binary files /dev/null and b/retroshare-gui/src/gui/images/FileTypePicture.png differ diff --git a/retroshare-gui/src/gui/images/FileTypeProgram.png b/retroshare-gui/src/gui/images/FileTypeProgram.png new file mode 100644 index 000000000..63b9f6c32 Binary files /dev/null and b/retroshare-gui/src/gui/images/FileTypeProgram.png differ diff --git a/retroshare-gui/src/gui/images/FileTypeVideo.png b/retroshare-gui/src/gui/images/FileTypeVideo.png new file mode 100644 index 000000000..9bcc41b78 Binary files /dev/null and b/retroshare-gui/src/gui/images/FileTypeVideo.png differ diff --git a/retroshare-gui/src/gui/images/Login Manager.png b/retroshare-gui/src/gui/images/Login Manager.png new file mode 100644 index 000000000..37371456c Binary files /dev/null and b/retroshare-gui/src/gui/images/Login Manager.png differ diff --git a/retroshare-gui/src/gui/images/RetroShare16.png b/retroshare-gui/src/gui/images/RetroShare16.png new file mode 100644 index 000000000..60c7c5da5 Binary files /dev/null and b/retroshare-gui/src/gui/images/RetroShare16.png differ diff --git a/retroshare-gui/src/gui/images/StatisticsDetail.png b/retroshare-gui/src/gui/images/StatisticsDetail.png new file mode 100644 index 000000000..e1a1bafd2 Binary files /dev/null and b/retroshare-gui/src/gui/images/StatisticsDetail.png differ diff --git a/retroshare-gui/src/gui/images/StatsCumulative.png b/retroshare-gui/src/gui/images/StatsCumulative.png new file mode 100644 index 000000000..174813e77 Binary files /dev/null and b/retroshare-gui/src/gui/images/StatsCumulative.png differ diff --git a/retroshare-gui/src/gui/images/about.png b/retroshare-gui/src/gui/images/about.png new file mode 100644 index 000000000..9e2a10c9f Binary files /dev/null and b/retroshare-gui/src/gui/images/about.png differ diff --git a/retroshare-gui/src/gui/images/accepted16.png b/retroshare-gui/src/gui/images/accepted16.png new file mode 100644 index 000000000..2f86f0ae6 Binary files /dev/null and b/retroshare-gui/src/gui/images/accepted16.png differ diff --git a/retroshare-gui/src/gui/images/add-friend24.png b/retroshare-gui/src/gui/images/add-friend24.png new file mode 100644 index 000000000..30c2dbc06 Binary files /dev/null and b/retroshare-gui/src/gui/images/add-friend24.png differ diff --git a/retroshare-gui/src/gui/images/add-share24.png b/retroshare-gui/src/gui/images/add-share24.png new file mode 100644 index 000000000..031542f51 Binary files /dev/null and b/retroshare-gui/src/gui/images/add-share24.png differ diff --git a/retroshare-gui/src/gui/images/add_24x24.png b/retroshare-gui/src/gui/images/add_24x24.png new file mode 100644 index 000000000..bbf64ca18 Binary files /dev/null and b/retroshare-gui/src/gui/images/add_24x24.png differ diff --git a/retroshare-gui/src/gui/images/add_channel24.png b/retroshare-gui/src/gui/images/add_channel24.png new file mode 100644 index 000000000..8ba048f74 Binary files /dev/null and b/retroshare-gui/src/gui/images/add_channel24.png differ diff --git a/retroshare-gui/src/gui/images/add_channel32.png b/retroshare-gui/src/gui/images/add_channel32.png new file mode 100644 index 000000000..62d178e11 Binary files /dev/null and b/retroshare-gui/src/gui/images/add_channel32.png differ diff --git a/retroshare-gui/src/gui/images/add_channel64.png b/retroshare-gui/src/gui/images/add_channel64.png new file mode 100644 index 000000000..ebc17374c Binary files /dev/null and b/retroshare-gui/src/gui/images/add_channel64.png differ diff --git a/retroshare-gui/src/gui/images/add_image24.png b/retroshare-gui/src/gui/images/add_image24.png new file mode 100644 index 000000000..396035fe9 Binary files /dev/null and b/retroshare-gui/src/gui/images/add_image24.png differ diff --git a/retroshare-gui/src/gui/images/advsearch_24x24.png b/retroshare-gui/src/gui/images/advsearch_24x24.png new file mode 100644 index 000000000..94182e8fe Binary files /dev/null and b/retroshare-gui/src/gui/images/advsearch_24x24.png differ diff --git a/retroshare-gui/src/gui/images/amsn.png b/retroshare-gui/src/gui/images/amsn.png new file mode 100644 index 000000000..dd1572626 Binary files /dev/null and b/retroshare-gui/src/gui/images/amsn.png differ diff --git a/retroshare-gui/src/gui/images/amsn16.png b/retroshare-gui/src/gui/images/amsn16.png new file mode 100644 index 000000000..54edfb50e Binary files /dev/null and b/retroshare-gui/src/gui/images/amsn16.png differ diff --git a/retroshare-gui/src/gui/images/application-draw.png b/retroshare-gui/src/gui/images/application-draw.png new file mode 100644 index 000000000..bbe1180e1 Binary files /dev/null and b/retroshare-gui/src/gui/images/application-draw.png differ diff --git a/retroshare-gui/src/gui/images/application-x-cd-image.png b/retroshare-gui/src/gui/images/application-x-cd-image.png new file mode 100644 index 000000000..6d2673ecc Binary files /dev/null and b/retroshare-gui/src/gui/images/application-x-cd-image.png differ diff --git a/retroshare-gui/src/gui/images/application-x-rar.png b/retroshare-gui/src/gui/images/application-x-rar.png new file mode 100644 index 000000000..84eaa19aa Binary files /dev/null and b/retroshare-gui/src/gui/images/application-x-rar.png differ diff --git a/retroshare-gui/src/gui/images/arrow-left.png b/retroshare-gui/src/gui/images/arrow-left.png new file mode 100644 index 000000000..6a29679ae Binary files /dev/null and b/retroshare-gui/src/gui/images/arrow-left.png differ diff --git a/retroshare-gui/src/gui/images/arrow-right.png b/retroshare-gui/src/gui/images/arrow-right.png new file mode 100644 index 000000000..207f7fcf2 Binary files /dev/null and b/retroshare-gui/src/gui/images/arrow-right.png differ diff --git a/retroshare-gui/src/gui/images/attach.png b/retroshare-gui/src/gui/images/attach.png new file mode 100644 index 000000000..53f31750b Binary files /dev/null and b/retroshare-gui/src/gui/images/attach.png differ diff --git a/retroshare-gui/src/gui/images/attachment.png b/retroshare-gui/src/gui/images/attachment.png new file mode 100644 index 000000000..89842af21 Binary files /dev/null and b/retroshare-gui/src/gui/images/attachment.png differ diff --git a/retroshare-gui/src/gui/images/audio-x-monkey.png b/retroshare-gui/src/gui/images/audio-x-monkey.png new file mode 100644 index 000000000..c573de966 Binary files /dev/null and b/retroshare-gui/src/gui/images/audio-x-monkey.png differ diff --git a/retroshare-gui/src/gui/images/avatar_background.png b/retroshare-gui/src/gui/images/avatar_background.png new file mode 100644 index 000000000..a26219a05 Binary files /dev/null and b/retroshare-gui/src/gui/images/avatar_background.png differ diff --git a/retroshare-gui/src/gui/images/avatarstatus_bg.png b/retroshare-gui/src/gui/images/avatarstatus_bg.png new file mode 100644 index 000000000..cf0744e29 Binary files /dev/null and b/retroshare-gui/src/gui/images/avatarstatus_bg.png differ diff --git a/retroshare-gui/src/gui/images/avatarstatus_bg_away.png b/retroshare-gui/src/gui/images/avatarstatus_bg_away.png new file mode 100644 index 000000000..e25114641 Binary files /dev/null and b/retroshare-gui/src/gui/images/avatarstatus_bg_away.png differ diff --git a/retroshare-gui/src/gui/images/avatarstatus_bg_busy.png b/retroshare-gui/src/gui/images/avatarstatus_bg_busy.png new file mode 100644 index 000000000..e0eaee6a4 Binary files /dev/null and b/retroshare-gui/src/gui/images/avatarstatus_bg_busy.png differ diff --git a/retroshare-gui/src/gui/images/avatarstatus_bg_offline.png b/retroshare-gui/src/gui/images/avatarstatus_bg_offline.png new file mode 100644 index 000000000..baa1088ed Binary files /dev/null and b/retroshare-gui/src/gui/images/avatarstatus_bg_offline.png differ diff --git a/retroshare-gui/src/gui/images/avatarstatus_bg_online.png b/retroshare-gui/src/gui/images/avatarstatus_bg_online.png new file mode 100644 index 000000000..632a7ff09 Binary files /dev/null and b/retroshare-gui/src/gui/images/avatarstatus_bg_online.png differ diff --git a/retroshare-gui/src/gui/images/back.png b/retroshare-gui/src/gui/images/back.png new file mode 100644 index 000000000..78dcc7011 Binary files /dev/null and b/retroshare-gui/src/gui/images/back.png differ diff --git a/retroshare-gui/src/gui/images/backblue.png b/retroshare-gui/src/gui/images/backblue.png new file mode 100644 index 000000000..8ca7d7745 Binary files /dev/null and b/retroshare-gui/src/gui/images/backblue.png differ diff --git a/retroshare-gui/src/gui/images/backchat.png b/retroshare-gui/src/gui/images/backchat.png new file mode 100644 index 000000000..6ea9c9f49 Binary files /dev/null and b/retroshare-gui/src/gui/images/backchat.png differ diff --git a/retroshare-gui/src/gui/images/backgroundimage.png b/retroshare-gui/src/gui/images/backgroundimage.png new file mode 100644 index 000000000..f67e5176f Binary files /dev/null and b/retroshare-gui/src/gui/images/backgroundimage.png differ diff --git a/retroshare-gui/src/gui/images/backgroundl.png b/retroshare-gui/src/gui/images/backgroundl.png new file mode 100644 index 000000000..13d166dbe Binary files /dev/null and b/retroshare-gui/src/gui/images/backgroundl.png differ diff --git a/retroshare-gui/src/gui/images/blockdevice.png b/retroshare-gui/src/gui/images/blockdevice.png new file mode 100644 index 000000000..77584164f Binary files /dev/null and b/retroshare-gui/src/gui/images/blockdevice.png differ diff --git a/retroshare-gui/src/gui/images/blockdevice2.png b/retroshare-gui/src/gui/images/blockdevice2.png new file mode 100644 index 000000000..312d63e40 Binary files /dev/null and b/retroshare-gui/src/gui/images/blockdevice2.png differ diff --git a/retroshare-gui/src/gui/images/browse-looking.gif b/retroshare-gui/src/gui/images/browse-looking.gif new file mode 100644 index 000000000..6da15f60d Binary files /dev/null and b/retroshare-gui/src/gui/images/browse-looking.gif differ diff --git a/retroshare-gui/src/gui/images/btn1.png b/retroshare-gui/src/gui/images/btn1.png new file mode 100644 index 000000000..bbe3b7278 Binary files /dev/null and b/retroshare-gui/src/gui/images/btn1.png differ diff --git a/retroshare-gui/src/gui/images/btn2.png b/retroshare-gui/src/gui/images/btn2.png new file mode 100644 index 000000000..92100d787 Binary files /dev/null and b/retroshare-gui/src/gui/images/btn2.png differ diff --git a/retroshare-gui/src/gui/images/btn3.png b/retroshare-gui/src/gui/images/btn3.png new file mode 100644 index 000000000..bbe3b7278 Binary files /dev/null and b/retroshare-gui/src/gui/images/btn3.png differ diff --git a/retroshare-gui/src/gui/images/btn4.png b/retroshare-gui/src/gui/images/btn4.png new file mode 100644 index 000000000..bbe3b7278 Binary files /dev/null and b/retroshare-gui/src/gui/images/btn4.png differ diff --git a/retroshare-gui/src/gui/images/btn_26.png b/retroshare-gui/src/gui/images/btn_26.png new file mode 100644 index 000000000..51de8bc89 Binary files /dev/null and b/retroshare-gui/src/gui/images/btn_26.png differ diff --git a/retroshare-gui/src/gui/images/btn_26_hover.png b/retroshare-gui/src/gui/images/btn_26_hover.png new file mode 100644 index 000000000..391690431 Binary files /dev/null and b/retroshare-gui/src/gui/images/btn_26_hover.png differ diff --git a/retroshare-gui/src/gui/images/btn_26_pressed.png b/retroshare-gui/src/gui/images/btn_26_pressed.png new file mode 100644 index 000000000..0aa53120d Binary files /dev/null and b/retroshare-gui/src/gui/images/btn_26_pressed.png differ diff --git a/retroshare-gui/src/gui/images/btn_27.png b/retroshare-gui/src/gui/images/btn_27.png new file mode 100644 index 000000000..bcdf90ded Binary files /dev/null and b/retroshare-gui/src/gui/images/btn_27.png differ diff --git a/retroshare-gui/src/gui/images/btn_27_hover.png b/retroshare-gui/src/gui/images/btn_27_hover.png new file mode 100644 index 000000000..2bc8680d7 Binary files /dev/null and b/retroshare-gui/src/gui/images/btn_27_hover.png differ diff --git a/retroshare-gui/src/gui/images/button_cancel.png b/retroshare-gui/src/gui/images/button_cancel.png new file mode 100644 index 000000000..3f0c98b7d Binary files /dev/null and b/retroshare-gui/src/gui/images/button_cancel.png differ diff --git a/retroshare-gui/src/gui/images/buttonframe.png b/retroshare-gui/src/gui/images/buttonframe.png new file mode 100644 index 000000000..22031115a Binary files /dev/null and b/retroshare-gui/src/gui/images/buttonframe.png differ diff --git a/retroshare-gui/src/gui/images/calendar.png b/retroshare-gui/src/gui/images/calendar.png new file mode 100644 index 000000000..e91b13d73 Binary files /dev/null and b/retroshare-gui/src/gui/images/calendar.png differ diff --git a/retroshare-gui/src/gui/images/cancel.png b/retroshare-gui/src/gui/images/cancel.png new file mode 100644 index 000000000..e2db55f22 Binary files /dev/null and b/retroshare-gui/src/gui/images/cancel.png differ diff --git a/retroshare-gui/src/gui/images/channels.png b/retroshare-gui/src/gui/images/channels.png new file mode 100644 index 000000000..3c53997a0 Binary files /dev/null and b/retroshare-gui/src/gui/images/channels.png differ diff --git a/retroshare-gui/src/gui/images/channels16.png b/retroshare-gui/src/gui/images/channels16.png new file mode 100644 index 000000000..e84292c1f Binary files /dev/null and b/retroshare-gui/src/gui/images/channels16.png differ diff --git a/retroshare-gui/src/gui/images/channels24.png b/retroshare-gui/src/gui/images/channels24.png new file mode 100644 index 000000000..9eb351ae7 Binary files /dev/null and b/retroshare-gui/src/gui/images/channels24.png differ diff --git a/retroshare-gui/src/gui/images/channels32.png b/retroshare-gui/src/gui/images/channels32.png new file mode 100644 index 000000000..ddb19884e Binary files /dev/null and b/retroshare-gui/src/gui/images/channels32.png differ diff --git a/retroshare-gui/src/gui/images/channels_new32.png b/retroshare-gui/src/gui/images/channels_new32.png new file mode 100644 index 000000000..e3f9f3034 Binary files /dev/null and b/retroshare-gui/src/gui/images/channels_new32.png differ diff --git a/retroshare-gui/src/gui/images/chat.png b/retroshare-gui/src/gui/images/chat.png new file mode 100644 index 000000000..70c84cc17 Binary files /dev/null and b/retroshare-gui/src/gui/images/chat.png differ diff --git a/retroshare-gui/src/gui/images/chat_24.png b/retroshare-gui/src/gui/images/chat_24.png new file mode 100644 index 000000000..3a791ba17 Binary files /dev/null and b/retroshare-gui/src/gui/images/chat_24.png differ diff --git a/retroshare-gui/src/gui/images/chats_24x24.png b/retroshare-gui/src/gui/images/chats_24x24.png new file mode 100644 index 000000000..cdf12ca35 Binary files /dev/null and b/retroshare-gui/src/gui/images/chats_24x24.png differ diff --git a/retroshare-gui/src/gui/images/close-down.png b/retroshare-gui/src/gui/images/close-down.png new file mode 100644 index 000000000..d73012fa2 Binary files /dev/null and b/retroshare-gui/src/gui/images/close-down.png differ diff --git a/retroshare-gui/src/gui/images/close_normal.png b/retroshare-gui/src/gui/images/close_normal.png new file mode 100644 index 000000000..fb510fbea Binary files /dev/null and b/retroshare-gui/src/gui/images/close_normal.png differ diff --git a/retroshare-gui/src/gui/images/closehover.png b/retroshare-gui/src/gui/images/closehover.png new file mode 100644 index 000000000..bb0411ad6 Binary files /dev/null and b/retroshare-gui/src/gui/images/closehover.png differ diff --git a/retroshare-gui/src/gui/images/closenormal.png b/retroshare-gui/src/gui/images/closenormal.png new file mode 100644 index 000000000..766a8f29f Binary files /dev/null and b/retroshare-gui/src/gui/images/closenormal.png differ diff --git a/retroshare-gui/src/gui/images/closepressed.png b/retroshare-gui/src/gui/images/closepressed.png new file mode 100644 index 000000000..c61b067e3 Binary files /dev/null and b/retroshare-gui/src/gui/images/closepressed.png differ diff --git a/retroshare-gui/src/gui/images/combobox_arrow.png b/retroshare-gui/src/gui/images/combobox_arrow.png new file mode 100644 index 000000000..fa180a27e Binary files /dev/null and b/retroshare-gui/src/gui/images/combobox_arrow.png differ diff --git a/retroshare-gui/src/gui/images/configure.png b/retroshare-gui/src/gui/images/configure.png new file mode 100644 index 000000000..45b8fae8b Binary files /dev/null and b/retroshare-gui/src/gui/images/configure.png differ diff --git a/retroshare-gui/src/gui/images/connect/connectFriendBanner.png b/retroshare-gui/src/gui/images/connect/connectFriendBanner.png new file mode 100644 index 000000000..94f6acfcf Binary files /dev/null and b/retroshare-gui/src/gui/images/connect/connectFriendBanner.png differ diff --git a/retroshare-gui/src/gui/images/connect/connectFriendLogo.png b/retroshare-gui/src/gui/images/connect/connectFriendLogo.png new file mode 100644 index 000000000..d5ac0af38 Binary files /dev/null and b/retroshare-gui/src/gui/images/connect/connectFriendLogo.png differ diff --git a/retroshare-gui/src/gui/images/connect/connectFriendLogo2.png b/retroshare-gui/src/gui/images/connect/connectFriendLogo2.png new file mode 100644 index 000000000..b4bacbdff Binary files /dev/null and b/retroshare-gui/src/gui/images/connect/connectFriendLogo2.png differ diff --git a/retroshare-gui/src/gui/images/connect/connectFriendWatermark.png b/retroshare-gui/src/gui/images/connect/connectFriendWatermark.png new file mode 100644 index 000000000..d68db6277 Binary files /dev/null and b/retroshare-gui/src/gui/images/connect/connectFriendWatermark.png differ diff --git a/retroshare-gui/src/gui/images/connect/info16.png b/retroshare-gui/src/gui/images/connect/info16.png new file mode 100644 index 000000000..fb3b689e9 Binary files /dev/null and b/retroshare-gui/src/gui/images/connect/info16.png differ diff --git a/retroshare-gui/src/gui/images/connect/mail_send.png b/retroshare-gui/src/gui/images/connect/mail_send.png new file mode 100644 index 000000000..0366228e9 Binary files /dev/null and b/retroshare-gui/src/gui/images/connect/mail_send.png differ diff --git a/retroshare-gui/src/gui/images/connect_creating.png b/retroshare-gui/src/gui/images/connect_creating.png new file mode 100644 index 000000000..55643bc19 Binary files /dev/null and b/retroshare-gui/src/gui/images/connect_creating.png differ diff --git a/retroshare-gui/src/gui/images/connect_established.png b/retroshare-gui/src/gui/images/connect_established.png new file mode 100644 index 000000000..2c45f9d86 Binary files /dev/null and b/retroshare-gui/src/gui/images/connect_established.png differ diff --git a/retroshare-gui/src/gui/images/connect_friend.png b/retroshare-gui/src/gui/images/connect_friend.png new file mode 100755 index 000000000..3549e6d83 Binary files /dev/null and b/retroshare-gui/src/gui/images/connect_friend.png differ diff --git a/retroshare-gui/src/gui/images/connect_no.png b/retroshare-gui/src/gui/images/connect_no.png new file mode 100644 index 000000000..9605f62f5 Binary files /dev/null and b/retroshare-gui/src/gui/images/connect_no.png differ diff --git a/retroshare-gui/src/gui/images/connection.png b/retroshare-gui/src/gui/images/connection.png new file mode 100644 index 000000000..e22cb6c7c Binary files /dev/null and b/retroshare-gui/src/gui/images/connection.png differ diff --git a/retroshare-gui/src/gui/images/console-big-down.png b/retroshare-gui/src/gui/images/console-big-down.png new file mode 100644 index 000000000..4ffbbcf84 Binary files /dev/null and b/retroshare-gui/src/gui/images/console-big-down.png differ diff --git a/retroshare-gui/src/gui/images/console-big-hover.png b/retroshare-gui/src/gui/images/console-big-hover.png new file mode 100644 index 000000000..a5163017f Binary files /dev/null and b/retroshare-gui/src/gui/images/console-big-hover.png differ diff --git a/retroshare-gui/src/gui/images/console-big-up.png b/retroshare-gui/src/gui/images/console-big-up.png new file mode 100644 index 000000000..c88112c81 Binary files /dev/null and b/retroshare-gui/src/gui/images/console-big-up.png differ diff --git a/retroshare-gui/src/gui/images/console-small-down.png b/retroshare-gui/src/gui/images/console-small-down.png new file mode 100644 index 000000000..4c5fa594f Binary files /dev/null and b/retroshare-gui/src/gui/images/console-small-down.png differ diff --git a/retroshare-gui/src/gui/images/console-small-hover.png b/retroshare-gui/src/gui/images/console-small-hover.png new file mode 100644 index 000000000..9dfb61454 Binary files /dev/null and b/retroshare-gui/src/gui/images/console-small-hover.png differ diff --git a/retroshare-gui/src/gui/images/console-small-up.png b/retroshare-gui/src/gui/images/console-small-up.png new file mode 100644 index 000000000..551d3f923 Binary files /dev/null and b/retroshare-gui/src/gui/images/console-small-up.png differ diff --git a/retroshare-gui/src/gui/images/contact.png b/retroshare-gui/src/gui/images/contact.png new file mode 100644 index 000000000..b86f35012 Binary files /dev/null and b/retroshare-gui/src/gui/images/contact.png differ diff --git a/retroshare-gui/src/gui/images/contact_new.png b/retroshare-gui/src/gui/images/contact_new.png new file mode 100644 index 000000000..0a915b51b Binary files /dev/null and b/retroshare-gui/src/gui/images/contact_new.png differ diff --git a/retroshare-gui/src/gui/images/contact_new128.png b/retroshare-gui/src/gui/images/contact_new128.png new file mode 100644 index 000000000..ff60d9b48 Binary files /dev/null and b/retroshare-gui/src/gui/images/contact_new128.png differ diff --git a/retroshare-gui/src/gui/images/contacts24.png b/retroshare-gui/src/gui/images/contacts24.png new file mode 100644 index 000000000..979c51ecb Binary files /dev/null and b/retroshare-gui/src/gui/images/contacts24.png differ diff --git a/retroshare-gui/src/gui/images/copy.png b/retroshare-gui/src/gui/images/copy.png new file mode 100644 index 000000000..9f5661aec Binary files /dev/null and b/retroshare-gui/src/gui/images/copy.png differ diff --git a/retroshare-gui/src/gui/images/copyrslink.png b/retroshare-gui/src/gui/images/copyrslink.png new file mode 100644 index 000000000..7e8bb7960 Binary files /dev/null and b/retroshare-gui/src/gui/images/copyrslink.png differ diff --git a/retroshare-gui/src/gui/images/delete.png b/retroshare-gui/src/gui/images/delete.png new file mode 100644 index 000000000..931ee1101 Binary files /dev/null and b/retroshare-gui/src/gui/images/delete.png differ diff --git a/retroshare-gui/src/gui/images/deleteall.png b/retroshare-gui/src/gui/images/deleteall.png new file mode 100644 index 000000000..a8f1dd4ec Binary files /dev/null and b/retroshare-gui/src/gui/images/deleteall.png differ diff --git a/retroshare-gui/src/gui/images/deletemail-pressed.png b/retroshare-gui/src/gui/images/deletemail-pressed.png new file mode 100644 index 000000000..8d79b7e61 Binary files /dev/null and b/retroshare-gui/src/gui/images/deletemail-pressed.png differ diff --git a/retroshare-gui/src/gui/images/deletemail24.png b/retroshare-gui/src/gui/images/deletemail24.png new file mode 100644 index 000000000..b584ead3f Binary files /dev/null and b/retroshare-gui/src/gui/images/deletemail24.png differ diff --git a/retroshare-gui/src/gui/images/denied16.png b/retroshare-gui/src/gui/images/denied16.png new file mode 100644 index 000000000..48f1fae8f Binary files /dev/null and b/retroshare-gui/src/gui/images/denied16.png differ diff --git a/retroshare-gui/src/gui/images/dht16.png b/retroshare-gui/src/gui/images/dht16.png new file mode 100644 index 000000000..5e60b5227 Binary files /dev/null and b/retroshare-gui/src/gui/images/dht16.png differ diff --git a/retroshare-gui/src/gui/images/directoryadd_24x24_shadow.png b/retroshare-gui/src/gui/images/directoryadd_24x24_shadow.png new file mode 100644 index 000000000..ca14db0a0 Binary files /dev/null and b/retroshare-gui/src/gui/images/directoryadd_24x24_shadow.png differ diff --git a/retroshare-gui/src/gui/images/directoryremove_24x24_shadow.png b/retroshare-gui/src/gui/images/directoryremove_24x24_shadow.png new file mode 100644 index 000000000..269bc9828 Binary files /dev/null and b/retroshare-gui/src/gui/images/directoryremove_24x24_shadow.png differ diff --git a/retroshare-gui/src/gui/images/directoryselect_24x24_shadow.png b/retroshare-gui/src/gui/images/directoryselect_24x24_shadow.png new file mode 100644 index 000000000..ad22ed11a Binary files /dev/null and b/retroshare-gui/src/gui/images/directoryselect_24x24_shadow.png differ diff --git a/retroshare-gui/src/gui/images/diskSave.png b/retroshare-gui/src/gui/images/diskSave.png new file mode 100644 index 000000000..b5b8e2c7e Binary files /dev/null and b/retroshare-gui/src/gui/images/diskSave.png differ diff --git a/retroshare-gui/src/gui/images/document_save.png b/retroshare-gui/src/gui/images/document_save.png new file mode 100644 index 000000000..076da14a4 Binary files /dev/null and b/retroshare-gui/src/gui/images/document_save.png differ diff --git a/retroshare-gui/src/gui/images/down.png b/retroshare-gui/src/gui/images/down.png new file mode 100644 index 000000000..c005fe4ba Binary files /dev/null and b/retroshare-gui/src/gui/images/down.png differ diff --git a/retroshare-gui/src/gui/images/down_24x24.png b/retroshare-gui/src/gui/images/down_24x24.png new file mode 100644 index 000000000..92517a244 Binary files /dev/null and b/retroshare-gui/src/gui/images/down_24x24.png differ diff --git a/retroshare-gui/src/gui/images/download.png b/retroshare-gui/src/gui/images/download.png new file mode 100644 index 000000000..ff38dd4ca Binary files /dev/null and b/retroshare-gui/src/gui/images/download.png differ diff --git a/retroshare-gui/src/gui/images/download16.png b/retroshare-gui/src/gui/images/download16.png new file mode 100644 index 000000000..a0c30f12b Binary files /dev/null and b/retroshare-gui/src/gui/images/download16.png differ diff --git a/retroshare-gui/src/gui/images/edit-bold.png b/retroshare-gui/src/gui/images/edit-bold.png new file mode 100644 index 000000000..a2c44d52d Binary files /dev/null and b/retroshare-gui/src/gui/images/edit-bold.png differ diff --git a/retroshare-gui/src/gui/images/edit-clear-history.png b/retroshare-gui/src/gui/images/edit-clear-history.png new file mode 100644 index 000000000..136dadbe1 Binary files /dev/null and b/retroshare-gui/src/gui/images/edit-clear-history.png differ diff --git a/retroshare-gui/src/gui/images/edit-italic.png b/retroshare-gui/src/gui/images/edit-italic.png new file mode 100644 index 000000000..a0ab94570 Binary files /dev/null and b/retroshare-gui/src/gui/images/edit-italic.png differ diff --git a/retroshare-gui/src/gui/images/edit-underline.png b/retroshare-gui/src/gui/images/edit-underline.png new file mode 100644 index 000000000..98a1441e1 Binary files /dev/null and b/retroshare-gui/src/gui/images/edit-underline.png differ diff --git a/retroshare-gui/src/gui/images/edit_16.png b/retroshare-gui/src/gui/images/edit_16.png new file mode 100644 index 000000000..42f442c2f Binary files /dev/null and b/retroshare-gui/src/gui/images/edit_16.png differ diff --git a/retroshare-gui/src/gui/images/edit_add24.png b/retroshare-gui/src/gui/images/edit_add24.png new file mode 100644 index 000000000..5a4483325 Binary files /dev/null and b/retroshare-gui/src/gui/images/edit_add24.png differ diff --git a/retroshare-gui/src/gui/images/edit_remove24.png b/retroshare-gui/src/gui/images/edit_remove24.png new file mode 100644 index 000000000..314eea713 Binary files /dev/null and b/retroshare-gui/src/gui/images/edit_remove24.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete006.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete006.png new file mode 100644 index 000000000..53c1819fe Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete006.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete007.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete007.png new file mode 100644 index 000000000..563532756 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete007.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete008.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete008.png new file mode 100644 index 000000000..a4788a820 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete008.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete009.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete009.png new file mode 100644 index 000000000..fc8dd7218 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete009.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete010.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete010.png new file mode 100644 index 000000000..3be11a3de Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete010.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete011.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete011.png new file mode 100644 index 000000000..19a7b33a9 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete011.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete012.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete012.png new file mode 100644 index 000000000..181c3c776 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete012.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete013.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete013.png new file mode 100644 index 000000000..41205b572 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete013.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete014.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete014.png new file mode 100644 index 000000000..c7a3c013d Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete014.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete015.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete015.png new file mode 100644 index 000000000..dc113eac5 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete015.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete016.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete016.png new file mode 100644 index 000000000..d6d6de45c Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete016.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete017.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete017.png new file mode 100644 index 000000000..74938a7e5 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete017.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete018.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete018.png new file mode 100644 index 000000000..9138b2860 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete018.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete019.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete019.png new file mode 100644 index 000000000..11bb359f2 Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete019.png differ diff --git a/retroshare-gui/src/gui/images/emoticons/kopete/kopete020.png b/retroshare-gui/src/gui/images/emoticons/kopete/kopete020.png new file mode 100644 index 000000000..a113e35cf Binary files /dev/null and b/retroshare-gui/src/gui/images/emoticons/kopete/kopete020.png differ diff --git a/retroshare-gui/src/gui/images/encrypted16.png b/retroshare-gui/src/gui/images/encrypted16.png new file mode 100644 index 000000000..b2619730c Binary files /dev/null and b/retroshare-gui/src/gui/images/encrypted16.png differ diff --git a/retroshare-gui/src/gui/images/encrypted22.png b/retroshare-gui/src/gui/images/encrypted22.png new file mode 100644 index 000000000..1cf62bf68 Binary files /dev/null and b/retroshare-gui/src/gui/images/encrypted22.png differ diff --git a/retroshare-gui/src/gui/images/encrypted32.png b/retroshare-gui/src/gui/images/encrypted32.png new file mode 100644 index 000000000..974cd6816 Binary files /dev/null and b/retroshare-gui/src/gui/images/encrypted32.png differ diff --git a/retroshare-gui/src/gui/images/encrypted48.png b/retroshare-gui/src/gui/images/encrypted48.png new file mode 100644 index 000000000..b09df126a Binary files /dev/null and b/retroshare-gui/src/gui/images/encrypted48.png differ diff --git a/retroshare-gui/src/gui/images/evolution.png b/retroshare-gui/src/gui/images/evolution.png new file mode 100644 index 000000000..a54a36647 Binary files /dev/null and b/retroshare-gui/src/gui/images/evolution.png differ diff --git a/retroshare-gui/src/gui/images/exit_24x24.png b/retroshare-gui/src/gui/images/exit_24x24.png new file mode 100644 index 000000000..3f77be3e0 Binary files /dev/null and b/retroshare-gui/src/gui/images/exit_24x24.png differ diff --git a/retroshare-gui/src/gui/images/expand_frame.png b/retroshare-gui/src/gui/images/expand_frame.png new file mode 100644 index 000000000..8032af04e Binary files /dev/null and b/retroshare-gui/src/gui/images/expand_frame.png differ diff --git a/retroshare-gui/src/gui/images/exportpeers_16x16.png b/retroshare-gui/src/gui/images/exportpeers_16x16.png new file mode 100644 index 000000000..c3bd700ba Binary files /dev/null and b/retroshare-gui/src/gui/images/exportpeers_16x16.png differ diff --git a/retroshare-gui/src/gui/images/extension.svg b/retroshare-gui/src/gui/images/extension.svg new file mode 100644 index 000000000..bd7dc0935 --- /dev/null +++ b/retroshare-gui/src/gui/images/extension.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Extension + + + Andreas Nilsson + + + http://tango-project.org + + + extention + addon + plugin + puzzle + + + + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/images/extension_32.png b/retroshare-gui/src/gui/images/extension_32.png new file mode 100644 index 000000000..5d8edb76d Binary files /dev/null and b/retroshare-gui/src/gui/images/extension_32.png differ diff --git a/retroshare-gui/src/gui/images/extension_48.png b/retroshare-gui/src/gui/images/extension_48.png new file mode 100644 index 000000000..f32e65cef Binary files /dev/null and b/retroshare-gui/src/gui/images/extension_48.png differ diff --git a/retroshare-gui/src/gui/images/feedback_arrow.png b/retroshare-gui/src/gui/images/feedback_arrow.png new file mode 100644 index 000000000..8766098a5 Binary files /dev/null and b/retroshare-gui/src/gui/images/feedback_arrow.png differ diff --git a/retroshare-gui/src/gui/images/feedback_arrow_hover.png b/retroshare-gui/src/gui/images/feedback_arrow_hover.png new file mode 100644 index 000000000..43d990714 Binary files /dev/null and b/retroshare-gui/src/gui/images/feedback_arrow_hover.png differ diff --git a/retroshare-gui/src/gui/images/filecomments.png b/retroshare-gui/src/gui/images/filecomments.png new file mode 100644 index 000000000..7e1423f4e Binary files /dev/null and b/retroshare-gui/src/gui/images/filecomments.png differ diff --git a/retroshare-gui/src/gui/images/filefind.png b/retroshare-gui/src/gui/images/filefind.png new file mode 100644 index 000000000..941825598 Binary files /dev/null and b/retroshare-gui/src/gui/images/filefind.png differ diff --git a/retroshare-gui/src/gui/images/fileinfo.png b/retroshare-gui/src/gui/images/fileinfo.png new file mode 100644 index 000000000..578466bd6 Binary files /dev/null and b/retroshare-gui/src/gui/images/fileinfo.png differ diff --git a/retroshare-gui/src/gui/images/filename.png b/retroshare-gui/src/gui/images/filename.png new file mode 100644 index 000000000..dabf31e61 Binary files /dev/null and b/retroshare-gui/src/gui/images/filename.png differ diff --git a/retroshare-gui/src/gui/images/fileopen.png b/retroshare-gui/src/gui/images/fileopen.png new file mode 100644 index 000000000..965bf4e81 Binary files /dev/null and b/retroshare-gui/src/gui/images/fileopen.png differ diff --git a/retroshare-gui/src/gui/images/filepriority.png b/retroshare-gui/src/gui/images/filepriority.png new file mode 100644 index 000000000..96f0c20dd Binary files /dev/null and b/retroshare-gui/src/gui/images/filepriority.png differ diff --git a/retroshare-gui/src/gui/images/filerating0.png b/retroshare-gui/src/gui/images/filerating0.png new file mode 100644 index 000000000..1fac1a4c5 Binary files /dev/null and b/retroshare-gui/src/gui/images/filerating0.png differ diff --git a/retroshare-gui/src/gui/images/filerating1.png b/retroshare-gui/src/gui/images/filerating1.png new file mode 100644 index 000000000..f8e3138b0 Binary files /dev/null and b/retroshare-gui/src/gui/images/filerating1.png differ diff --git a/retroshare-gui/src/gui/images/filerating2.png b/retroshare-gui/src/gui/images/filerating2.png new file mode 100644 index 000000000..8b3cff94a Binary files /dev/null and b/retroshare-gui/src/gui/images/filerating2.png differ diff --git a/retroshare-gui/src/gui/images/filerating3.png b/retroshare-gui/src/gui/images/filerating3.png new file mode 100644 index 000000000..edd28c2d6 Binary files /dev/null and b/retroshare-gui/src/gui/images/filerating3.png differ diff --git a/retroshare-gui/src/gui/images/filerating4.png b/retroshare-gui/src/gui/images/filerating4.png new file mode 100644 index 000000000..48f0f9ba0 Binary files /dev/null and b/retroshare-gui/src/gui/images/filerating4.png differ diff --git a/retroshare-gui/src/gui/images/filerating5.png b/retroshare-gui/src/gui/images/filerating5.png new file mode 100644 index 000000000..a88e73945 Binary files /dev/null and b/retroshare-gui/src/gui/images/filerating5.png differ diff --git a/retroshare-gui/src/gui/images/fileshare16.png b/retroshare-gui/src/gui/images/fileshare16.png new file mode 100644 index 000000000..cc9cd1e13 Binary files /dev/null and b/retroshare-gui/src/gui/images/fileshare16.png differ diff --git a/retroshare-gui/src/gui/images/fileshare24.png b/retroshare-gui/src/gui/images/fileshare24.png new file mode 100644 index 000000000..15880ce7c Binary files /dev/null and b/retroshare-gui/src/gui/images/fileshare24.png differ diff --git a/retroshare-gui/src/gui/images/fileshare32.png b/retroshare-gui/src/gui/images/fileshare32.png new file mode 100644 index 000000000..58e833c37 Binary files /dev/null and b/retroshare-gui/src/gui/images/fileshare32.png differ diff --git a/retroshare-gui/src/gui/images/fileshare48.png b/retroshare-gui/src/gui/images/fileshare48.png new file mode 100644 index 000000000..3b9fcdd3c Binary files /dev/null and b/retroshare-gui/src/gui/images/fileshare48.png differ diff --git a/retroshare-gui/src/gui/images/filetype-association.png b/retroshare-gui/src/gui/images/filetype-association.png new file mode 100755 index 000000000..24c5fa32f Binary files /dev/null and b/retroshare-gui/src/gui/images/filetype-association.png differ diff --git a/retroshare-gui/src/gui/images/find-16.png b/retroshare-gui/src/gui/images/find-16.png new file mode 100644 index 000000000..81cfa5ef8 Binary files /dev/null and b/retroshare-gui/src/gui/images/find-16.png differ diff --git a/retroshare-gui/src/gui/images/find.png b/retroshare-gui/src/gui/images/find.png new file mode 100644 index 000000000..417149f51 Binary files /dev/null and b/retroshare-gui/src/gui/images/find.png differ diff --git a/retroshare-gui/src/gui/images/finished_background.png b/retroshare-gui/src/gui/images/finished_background.png new file mode 100644 index 000000000..49375aa79 Binary files /dev/null and b/retroshare-gui/src/gui/images/finished_background.png differ diff --git a/retroshare-gui/src/gui/images/flags/af.png b/retroshare-gui/src/gui/images/flags/af.png new file mode 100644 index 000000000..ba01b2b37 Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/af.png differ diff --git a/retroshare-gui/src/gui/images/flags/bg.png b/retroshare-gui/src/gui/images/flags/bg.png new file mode 100644 index 000000000..6572ba75b Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/bg.png differ diff --git a/retroshare-gui/src/gui/images/flags/cn.png b/retroshare-gui/src/gui/images/flags/cn.png new file mode 100644 index 000000000..2d1c8803d Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/cn.png differ diff --git a/retroshare-gui/src/gui/images/flags/cz.png b/retroshare-gui/src/gui/images/flags/cz.png new file mode 100644 index 000000000..69157da03 Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/cz.png differ diff --git a/retroshare-gui/src/gui/images/flags/da.png b/retroshare-gui/src/gui/images/flags/da.png new file mode 100644 index 000000000..ba866686e Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/da.png differ diff --git a/retroshare-gui/src/gui/images/flags/de.png b/retroshare-gui/src/gui/images/flags/de.png new file mode 100644 index 000000000..3e4fa430f Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/de.png differ diff --git a/retroshare-gui/src/gui/images/flags/dk.png b/retroshare-gui/src/gui/images/flags/dk.png new file mode 100644 index 000000000..ba866686e Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/dk.png differ diff --git a/retroshare-gui/src/gui/images/flags/en.png b/retroshare-gui/src/gui/images/flags/en.png new file mode 100644 index 000000000..48931bc86 Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/en.png differ diff --git a/retroshare-gui/src/gui/images/flags/es.png b/retroshare-gui/src/gui/images/flags/es.png new file mode 100644 index 000000000..6219730be Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/es.png differ diff --git a/retroshare-gui/src/gui/images/flags/fi.png b/retroshare-gui/src/gui/images/flags/fi.png new file mode 100644 index 000000000..d51567449 Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/fi.png differ diff --git a/retroshare-gui/src/gui/images/flags/fr.png b/retroshare-gui/src/gui/images/flags/fr.png new file mode 100644 index 000000000..71021748e Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/fr.png differ diff --git a/retroshare-gui/src/gui/images/flags/gr.png b/retroshare-gui/src/gui/images/flags/gr.png new file mode 100644 index 000000000..7803cb4f9 Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/gr.png differ diff --git a/retroshare-gui/src/gui/images/flags/it.png b/retroshare-gui/src/gui/images/flags/it.png new file mode 100644 index 000000000..0d6879162 Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/it.png differ diff --git a/retroshare-gui/src/gui/images/flags/ja_JP.png b/retroshare-gui/src/gui/images/flags/ja_JP.png new file mode 100644 index 000000000..b6563899e Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/ja_JP.png differ diff --git a/retroshare-gui/src/gui/images/flags/ko.png b/retroshare-gui/src/gui/images/flags/ko.png new file mode 100644 index 000000000..e2edef509 Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/ko.png differ diff --git a/retroshare-gui/src/gui/images/flags/pl.png b/retroshare-gui/src/gui/images/flags/pl.png new file mode 100644 index 000000000..8f8957664 Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/pl.png differ diff --git a/retroshare-gui/src/gui/images/flags/pt.png b/retroshare-gui/src/gui/images/flags/pt.png new file mode 100644 index 000000000..9d3aa9b8f Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/pt.png differ diff --git a/retroshare-gui/src/gui/images/flags/ru.png b/retroshare-gui/src/gui/images/flags/ru.png new file mode 100644 index 000000000..d0ce8817f Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/ru.png differ diff --git a/retroshare-gui/src/gui/images/flags/se.png b/retroshare-gui/src/gui/images/flags/se.png new file mode 100644 index 000000000..463382f7a Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/se.png differ diff --git a/retroshare-gui/src/gui/images/flags/sl.png b/retroshare-gui/src/gui/images/flags/sl.png new file mode 100644 index 000000000..4daf7d48f Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/sl.png differ diff --git a/retroshare-gui/src/gui/images/flags/sv.png b/retroshare-gui/src/gui/images/flags/sv.png new file mode 100644 index 000000000..463382f7a Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/sv.png differ diff --git a/retroshare-gui/src/gui/images/flags/tr.png b/retroshare-gui/src/gui/images/flags/tr.png new file mode 100644 index 000000000..f799e03ca Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/tr.png differ diff --git a/retroshare-gui/src/gui/images/flags/zh_CN.png b/retroshare-gui/src/gui/images/flags/zh_CN.png new file mode 100644 index 000000000..2d1c8803d Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/zh_CN.png differ diff --git a/retroshare-gui/src/gui/images/flags/zh_TW.png b/retroshare-gui/src/gui/images/flags/zh_TW.png new file mode 100644 index 000000000..2d1c8803d Binary files /dev/null and b/retroshare-gui/src/gui/images/flags/zh_TW.png differ diff --git a/retroshare-gui/src/gui/images/folder-draft.png b/retroshare-gui/src/gui/images/folder-draft.png new file mode 100644 index 000000000..7639d7b31 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder-draft.png differ diff --git a/retroshare-gui/src/gui/images/folder-draft24-pressed.png b/retroshare-gui/src/gui/images/folder-draft24-pressed.png new file mode 100644 index 000000000..8f2127908 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder-draft24-pressed.png differ diff --git a/retroshare-gui/src/gui/images/folder-draft24.png b/retroshare-gui/src/gui/images/folder-draft24.png new file mode 100644 index 000000000..5a2aaeb6c Binary files /dev/null and b/retroshare-gui/src/gui/images/folder-draft24.png differ diff --git a/retroshare-gui/src/gui/images/folder-inbox-new.png b/retroshare-gui/src/gui/images/folder-inbox-new.png new file mode 100644 index 000000000..da0667362 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder-inbox-new.png differ diff --git a/retroshare-gui/src/gui/images/folder-inbox.png b/retroshare-gui/src/gui/images/folder-inbox.png new file mode 100644 index 000000000..25e6204bd Binary files /dev/null and b/retroshare-gui/src/gui/images/folder-inbox.png differ diff --git a/retroshare-gui/src/gui/images/folder-outbox.png b/retroshare-gui/src/gui/images/folder-outbox.png new file mode 100644 index 000000000..a7362ec29 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder-outbox.png differ diff --git a/retroshare-gui/src/gui/images/folder-sent.png b/retroshare-gui/src/gui/images/folder-sent.png new file mode 100644 index 000000000..7ab95edae Binary files /dev/null and b/retroshare-gui/src/gui/images/folder-sent.png differ diff --git a/retroshare-gui/src/gui/images/folder-trash.png b/retroshare-gui/src/gui/images/folder-trash.png new file mode 100644 index 000000000..0712aaa71 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder-trash.png differ diff --git a/retroshare-gui/src/gui/images/folder.png b/retroshare-gui/src/gui/images/folder.png new file mode 100644 index 000000000..66704bdf3 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder.png differ diff --git a/retroshare-gui/src/gui/images/folder16.png b/retroshare-gui/src/gui/images/folder16.png new file mode 100644 index 000000000..66704bdf3 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder16.png differ diff --git a/retroshare-gui/src/gui/images/folder_blueshared.png b/retroshare-gui/src/gui/images/folder_blueshared.png new file mode 100755 index 000000000..55c67b931 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_blueshared.png differ diff --git a/retroshare-gui/src/gui/images/folder_doments.png b/retroshare-gui/src/gui/images/folder_doments.png new file mode 100644 index 000000000..8a6f1eff7 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_doments.png differ diff --git a/retroshare-gui/src/gui/images/folder_green.png b/retroshare-gui/src/gui/images/folder_green.png new file mode 100644 index 000000000..1269904ab Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_green.png differ diff --git a/retroshare-gui/src/gui/images/folder_grey.png b/retroshare-gui/src/gui/images/folder_grey.png new file mode 100644 index 000000000..86361c1e4 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_grey.png differ diff --git a/retroshare-gui/src/gui/images/folder_inbox64.png b/retroshare-gui/src/gui/images/folder_inbox64.png new file mode 100755 index 000000000..a105a8963 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_inbox64.png differ diff --git a/retroshare-gui/src/gui/images/folder_music.png b/retroshare-gui/src/gui/images/folder_music.png new file mode 100755 index 000000000..32a6c5134 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_music.png differ diff --git a/retroshare-gui/src/gui/images/folder_open.png b/retroshare-gui/src/gui/images/folder_open.png new file mode 100644 index 000000000..723b13b1c Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_open.png differ diff --git a/retroshare-gui/src/gui/images/folder_red.png b/retroshare-gui/src/gui/images/folder_red.png new file mode 100644 index 000000000..33d736aee Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_red.png differ diff --git a/retroshare-gui/src/gui/images/folder_video.png b/retroshare-gui/src/gui/images/folder_video.png new file mode 100755 index 000000000..0e45d0cb9 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_video.png differ diff --git a/retroshare-gui/src/gui/images/folder_yellow.png b/retroshare-gui/src/gui/images/folder_yellow.png new file mode 100644 index 000000000..1462d0756 Binary files /dev/null and b/retroshare-gui/src/gui/images/folder_yellow.png differ diff --git a/retroshare-gui/src/gui/images/foldermail.png b/retroshare-gui/src/gui/images/foldermail.png new file mode 100644 index 000000000..c6902aff7 Binary files /dev/null and b/retroshare-gui/src/gui/images/foldermail.png differ diff --git a/retroshare-gui/src/gui/images/folderopen.png b/retroshare-gui/src/gui/images/folderopen.png new file mode 100644 index 000000000..bbe4fc78f Binary files /dev/null and b/retroshare-gui/src/gui/images/folderopen.png differ diff --git a/retroshare-gui/src/gui/images/fonts.png b/retroshare-gui/src/gui/images/fonts.png new file mode 100644 index 000000000..267a732e6 Binary files /dev/null and b/retroshare-gui/src/gui/images/fonts.png differ diff --git a/retroshare-gui/src/gui/images/forward.png b/retroshare-gui/src/gui/images/forward.png new file mode 100644 index 000000000..a7d90d558 Binary files /dev/null and b/retroshare-gui/src/gui/images/forward.png differ diff --git a/retroshare-gui/src/gui/images/friendsfolder24.png b/retroshare-gui/src/gui/images/friendsfolder24.png new file mode 100644 index 000000000..107e8e70b Binary files /dev/null and b/retroshare-gui/src/gui/images/friendsfolder24.png differ diff --git a/retroshare-gui/src/gui/images/genbackground.png b/retroshare-gui/src/gui/images/genbackground.png new file mode 100644 index 000000000..24ab3725d Binary files /dev/null and b/retroshare-gui/src/gui/images/genbackground.png differ diff --git a/retroshare-gui/src/gui/images/go-bottom.png b/retroshare-gui/src/gui/images/go-bottom.png new file mode 100644 index 000000000..468362c37 Binary files /dev/null and b/retroshare-gui/src/gui/images/go-bottom.png differ diff --git a/retroshare-gui/src/gui/images/go-down.png b/retroshare-gui/src/gui/images/go-down.png new file mode 100644 index 000000000..5891219e4 Binary files /dev/null and b/retroshare-gui/src/gui/images/go-down.png differ diff --git a/retroshare-gui/src/gui/images/go-top.png b/retroshare-gui/src/gui/images/go-top.png new file mode 100644 index 000000000..999539296 Binary files /dev/null and b/retroshare-gui/src/gui/images/go-top.png differ diff --git a/retroshare-gui/src/gui/images/go-up.png b/retroshare-gui/src/gui/images/go-up.png new file mode 100644 index 000000000..b3d9cef97 Binary files /dev/null and b/retroshare-gui/src/gui/images/go-up.png differ diff --git a/retroshare-gui/src/gui/images/gohome.png b/retroshare-gui/src/gui/images/gohome.png new file mode 100644 index 000000000..6c45397e4 Binary files /dev/null and b/retroshare-gui/src/gui/images/gohome.png differ diff --git a/retroshare-gui/src/gui/images/gpgp_key_generate.png b/retroshare-gui/src/gui/images/gpgp_key_generate.png new file mode 100644 index 000000000..472b82c84 Binary files /dev/null and b/retroshare-gui/src/gui/images/gpgp_key_generate.png differ diff --git a/retroshare-gui/src/gui/images/graph-area.png b/retroshare-gui/src/gui/images/graph-area.png new file mode 100644 index 000000000..2ab2deb7c Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-area.png differ diff --git a/retroshare-gui/src/gui/images/graph-blue.png b/retroshare-gui/src/gui/images/graph-blue.png new file mode 100644 index 000000000..0854760de Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-blue.png differ diff --git a/retroshare-gui/src/gui/images/graph-bluegrey.png b/retroshare-gui/src/gui/images/graph-bluegrey.png new file mode 100644 index 000000000..022523786 Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-bluegrey.png differ diff --git a/retroshare-gui/src/gui/images/graph-downloaded.png b/retroshare-gui/src/gui/images/graph-downloaded.png new file mode 100644 index 000000000..9bb2bc347 Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-downloaded.png differ diff --git a/retroshare-gui/src/gui/images/graph-downloading.png b/retroshare-gui/src/gui/images/graph-downloading.png new file mode 100644 index 000000000..0aacd599c Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-downloading.png differ diff --git a/retroshare-gui/src/gui/images/graph-gold.png b/retroshare-gui/src/gui/images/graph-gold.png new file mode 100644 index 000000000..8bab9afad Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-gold.png differ diff --git a/retroshare-gui/src/gui/images/graph-indigo.png b/retroshare-gui/src/gui/images/graph-indigo.png new file mode 100644 index 000000000..873b294ee Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-indigo.png differ diff --git a/retroshare-gui/src/gui/images/graph-lightorange.png b/retroshare-gui/src/gui/images/graph-lightorange.png new file mode 100644 index 000000000..9fca16fec Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-lightorange.png differ diff --git a/retroshare-gui/src/gui/images/graph-line.png b/retroshare-gui/src/gui/images/graph-line.png new file mode 100644 index 000000000..43eedd48c Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-line.png differ diff --git a/retroshare-gui/src/gui/images/graph-notdownload.png b/retroshare-gui/src/gui/images/graph-notdownload.png new file mode 100644 index 000000000..9414f771a Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-notdownload.png differ diff --git a/retroshare-gui/src/gui/images/graph-orange.png b/retroshare-gui/src/gui/images/graph-orange.png new file mode 100644 index 000000000..1c010e95b Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-orange.png differ diff --git a/retroshare-gui/src/gui/images/graph-violet.png b/retroshare-gui/src/gui/images/graph-violet.png new file mode 100644 index 000000000..87b191621 Binary files /dev/null and b/retroshare-gui/src/gui/images/graph-violet.png differ diff --git a/retroshare-gui/src/gui/images/grayled.png b/retroshare-gui/src/gui/images/grayled.png new file mode 100644 index 000000000..a3b54fde2 Binary files /dev/null and b/retroshare-gui/src/gui/images/grayled.png differ diff --git a/retroshare-gui/src/gui/images/greenled.png b/retroshare-gui/src/gui/images/greenled.png new file mode 100644 index 000000000..70a875b32 Binary files /dev/null and b/retroshare-gui/src/gui/images/greenled.png differ diff --git a/retroshare-gui/src/gui/images/groupchat.png b/retroshare-gui/src/gui/images/groupchat.png new file mode 100644 index 000000000..558f316bd Binary files /dev/null and b/retroshare-gui/src/gui/images/groupchat.png differ diff --git a/retroshare-gui/src/gui/images/help.png b/retroshare-gui/src/gui/images/help.png new file mode 100644 index 000000000..9f0c92f23 Binary files /dev/null and b/retroshare-gui/src/gui/images/help.png differ diff --git a/retroshare-gui/src/gui/images/help24.png b/retroshare-gui/src/gui/images/help24.png new file mode 100644 index 000000000..2c8279b6a Binary files /dev/null and b/retroshare-gui/src/gui/images/help24.png differ diff --git a/retroshare-gui/src/gui/images/hi128-app-ktorrent.png b/retroshare-gui/src/gui/images/hi128-app-ktorrent.png new file mode 100644 index 000000000..764568d35 Binary files /dev/null and b/retroshare-gui/src/gui/images/hi128-app-ktorrent.png differ diff --git a/retroshare-gui/src/gui/images/hi16-app-ktorrent.png b/retroshare-gui/src/gui/images/hi16-app-ktorrent.png new file mode 100644 index 000000000..6bdf51399 Binary files /dev/null and b/retroshare-gui/src/gui/images/hi16-app-ktorrent.png differ diff --git a/retroshare-gui/src/gui/images/hi32-app-ktorrent.png b/retroshare-gui/src/gui/images/hi32-app-ktorrent.png new file mode 100644 index 000000000..fe92c486e Binary files /dev/null and b/retroshare-gui/src/gui/images/hi32-app-ktorrent.png differ diff --git a/retroshare-gui/src/gui/images/hi48-app-kblogger.png b/retroshare-gui/src/gui/images/hi48-app-kblogger.png new file mode 100644 index 000000000..da691264b Binary files /dev/null and b/retroshare-gui/src/gui/images/hi48-app-kblogger.png differ diff --git a/retroshare-gui/src/gui/images/hi48-app-ktorrent.png b/retroshare-gui/src/gui/images/hi48-app-ktorrent.png new file mode 100644 index 000000000..9afbadc6f Binary files /dev/null and b/retroshare-gui/src/gui/images/hi48-app-ktorrent.png differ diff --git a/retroshare-gui/src/gui/images/hi64-app-kblogger.png b/retroshare-gui/src/gui/images/hi64-app-kblogger.png new file mode 100644 index 000000000..2ae6d7ecb Binary files /dev/null and b/retroshare-gui/src/gui/images/hi64-app-kblogger.png differ diff --git a/retroshare-gui/src/gui/images/hi64-app-ktorrent.png b/retroshare-gui/src/gui/images/hi64-app-ktorrent.png new file mode 100644 index 000000000..47bbb7ee0 Binary files /dev/null and b/retroshare-gui/src/gui/images/hi64-app-ktorrent.png differ diff --git a/retroshare-gui/src/gui/images/hide_frame.png b/retroshare-gui/src/gui/images/hide_frame.png new file mode 100644 index 000000000..246a0bf43 Binary files /dev/null and b/retroshare-gui/src/gui/images/hide_frame.png differ diff --git a/retroshare-gui/src/gui/images/hide_toolbox_frame.png b/retroshare-gui/src/gui/images/hide_toolbox_frame.png new file mode 100644 index 000000000..a54a4e74a Binary files /dev/null and b/retroshare-gui/src/gui/images/hide_toolbox_frame.png differ diff --git a/retroshare-gui/src/gui/images/highlight.png b/retroshare-gui/src/gui/images/highlight.png new file mode 100644 index 000000000..54f6736de Binary files /dev/null and b/retroshare-gui/src/gui/images/highlight.png differ diff --git a/retroshare-gui/src/gui/images/hot_0.png b/retroshare-gui/src/gui/images/hot_0.png new file mode 100644 index 000000000..a1f7a8114 Binary files /dev/null and b/retroshare-gui/src/gui/images/hot_0.png differ diff --git a/retroshare-gui/src/gui/images/hot_1.png b/retroshare-gui/src/gui/images/hot_1.png new file mode 100644 index 000000000..cde121b53 Binary files /dev/null and b/retroshare-gui/src/gui/images/hot_1.png differ diff --git a/retroshare-gui/src/gui/images/hot_2.png b/retroshare-gui/src/gui/images/hot_2.png new file mode 100644 index 000000000..9f29930f4 Binary files /dev/null and b/retroshare-gui/src/gui/images/hot_2.png differ diff --git a/retroshare-gui/src/gui/images/hot_3.png b/retroshare-gui/src/gui/images/hot_3.png new file mode 100644 index 000000000..d3c92ba5a Binary files /dev/null and b/retroshare-gui/src/gui/images/hot_3.png differ diff --git a/retroshare-gui/src/gui/images/hot_4.png b/retroshare-gui/src/gui/images/hot_4.png new file mode 100644 index 000000000..d3c92ba5a Binary files /dev/null and b/retroshare-gui/src/gui/images/hot_4.png differ diff --git a/retroshare-gui/src/gui/images/hot_5.png b/retroshare-gui/src/gui/images/hot_5.png new file mode 100644 index 000000000..770a9f7d6 Binary files /dev/null and b/retroshare-gui/src/gui/images/hot_5.png differ diff --git a/retroshare-gui/src/gui/images/im-ban-kick-user.png b/retroshare-gui/src/gui/images/im-ban-kick-user.png new file mode 100644 index 000000000..180582c0a Binary files /dev/null and b/retroshare-gui/src/gui/images/im-ban-kick-user.png differ diff --git a/retroshare-gui/src/gui/images/im-ban-user.png b/retroshare-gui/src/gui/images/im-ban-user.png new file mode 100644 index 000000000..37712914a Binary files /dev/null and b/retroshare-gui/src/gui/images/im-ban-user.png differ diff --git a/retroshare-gui/src/gui/images/im-invisible-user.png b/retroshare-gui/src/gui/images/im-invisible-user.png new file mode 100644 index 000000000..15bdb5194 Binary files /dev/null and b/retroshare-gui/src/gui/images/im-invisible-user.png differ diff --git a/retroshare-gui/src/gui/images/im-kick-user.png b/retroshare-gui/src/gui/images/im-kick-user.png new file mode 100644 index 000000000..f9f0eec97 Binary files /dev/null and b/retroshare-gui/src/gui/images/im-kick-user.png differ diff --git a/retroshare-gui/src/gui/images/im-user-away.png b/retroshare-gui/src/gui/images/im-user-away.png new file mode 100644 index 000000000..297e40cc1 Binary files /dev/null and b/retroshare-gui/src/gui/images/im-user-away.png differ diff --git a/retroshare-gui/src/gui/images/im-user-busy.png b/retroshare-gui/src/gui/images/im-user-busy.png new file mode 100644 index 000000000..359824cda Binary files /dev/null and b/retroshare-gui/src/gui/images/im-user-busy.png differ diff --git a/retroshare-gui/src/gui/images/im-user-inactive.png b/retroshare-gui/src/gui/images/im-user-inactive.png new file mode 100644 index 000000000..2e136b23b Binary files /dev/null and b/retroshare-gui/src/gui/images/im-user-inactive.png differ diff --git a/retroshare-gui/src/gui/images/im-user-offline.png b/retroshare-gui/src/gui/images/im-user-offline.png new file mode 100644 index 000000000..49ec47cd7 Binary files /dev/null and b/retroshare-gui/src/gui/images/im-user-offline.png differ diff --git a/retroshare-gui/src/gui/images/im-user.png b/retroshare-gui/src/gui/images/im-user.png new file mode 100644 index 000000000..69de2e48f Binary files /dev/null and b/retroshare-gui/src/gui/images/im-user.png differ diff --git a/retroshare-gui/src/gui/images/image16.png b/retroshare-gui/src/gui/images/image16.png new file mode 100644 index 000000000..b57e381d0 Binary files /dev/null and b/retroshare-gui/src/gui/images/image16.png differ diff --git a/retroshare-gui/src/gui/images/inbox_22.png b/retroshare-gui/src/gui/images/inbox_22.png new file mode 100644 index 000000000..3f161a78a Binary files /dev/null and b/retroshare-gui/src/gui/images/inbox_22.png differ diff --git a/retroshare-gui/src/gui/images/info16.png b/retroshare-gui/src/gui/images/info16.png new file mode 100644 index 000000000..fb3b689e9 Binary files /dev/null and b/retroshare-gui/src/gui/images/info16.png differ diff --git a/retroshare-gui/src/gui/images/informations_24x24.png b/retroshare-gui/src/gui/images/informations_24x24.png new file mode 100644 index 000000000..68733266b Binary files /dev/null and b/retroshare-gui/src/gui/images/informations_24x24.png differ diff --git a/retroshare-gui/src/gui/images/invite-friend24.png b/retroshare-gui/src/gui/images/invite-friend24.png new file mode 100644 index 000000000..32403b384 Binary files /dev/null and b/retroshare-gui/src/gui/images/invite-friend24.png differ diff --git a/retroshare-gui/src/gui/images/irkick.png b/retroshare-gui/src/gui/images/irkick.png new file mode 100644 index 000000000..b399814ff Binary files /dev/null and b/retroshare-gui/src/gui/images/irkick.png differ diff --git a/retroshare-gui/src/gui/images/irkickflash.png b/retroshare-gui/src/gui/images/irkickflash.png new file mode 100644 index 000000000..0d67d3841 Binary files /dev/null and b/retroshare-gui/src/gui/images/irkickflash.png differ diff --git a/retroshare-gui/src/gui/images/kalarm.png b/retroshare-gui/src/gui/images/kalarm.png new file mode 100644 index 000000000..0fdb87d72 Binary files /dev/null and b/retroshare-gui/src/gui/images/kalarm.png differ diff --git a/retroshare-gui/src/gui/images/kbackgammon.png b/retroshare-gui/src/gui/images/kbackgammon.png new file mode 100644 index 000000000..9bdda1083 Binary files /dev/null and b/retroshare-gui/src/gui/images/kbackgammon.png differ diff --git a/retroshare-gui/src/gui/images/kblogger.png b/retroshare-gui/src/gui/images/kblogger.png new file mode 100644 index 000000000..dca1970f8 Binary files /dev/null and b/retroshare-gui/src/gui/images/kblogger.png differ diff --git a/retroshare-gui/src/gui/images/kcmsystem24.png b/retroshare-gui/src/gui/images/kcmsystem24.png new file mode 100644 index 000000000..cedcf7f0f Binary files /dev/null and b/retroshare-gui/src/gui/images/kcmsystem24.png differ diff --git a/retroshare-gui/src/gui/images/kdmconfig.png b/retroshare-gui/src/gui/images/kdmconfig.png new file mode 100644 index 000000000..688eb8491 Binary files /dev/null and b/retroshare-gui/src/gui/images/kdmconfig.png differ diff --git a/retroshare-gui/src/gui/images/kgames.png b/retroshare-gui/src/gui/images/kgames.png new file mode 100644 index 000000000..2ec077b76 Binary files /dev/null and b/retroshare-gui/src/gui/images/kgames.png differ diff --git a/retroshare-gui/src/gui/images/knewsticker24.png b/retroshare-gui/src/gui/images/knewsticker24.png new file mode 100644 index 000000000..e15b73542 Binary files /dev/null and b/retroshare-gui/src/gui/images/knewsticker24.png differ diff --git a/retroshare-gui/src/gui/images/konqsidebar_news16.png b/retroshare-gui/src/gui/images/konqsidebar_news16.png new file mode 100644 index 000000000..9507646e9 Binary files /dev/null and b/retroshare-gui/src/gui/images/konqsidebar_news16.png differ diff --git a/retroshare-gui/src/gui/images/konqsidebar_news24.png b/retroshare-gui/src/gui/images/konqsidebar_news24.png new file mode 100644 index 000000000..0a6d63034 Binary files /dev/null and b/retroshare-gui/src/gui/images/konqsidebar_news24.png differ diff --git a/retroshare-gui/src/gui/images/konsole.png b/retroshare-gui/src/gui/images/konsole.png new file mode 100644 index 000000000..b74026477 Binary files /dev/null and b/retroshare-gui/src/gui/images/konsole.png differ diff --git a/retroshare-gui/src/gui/images/konv_message.png b/retroshare-gui/src/gui/images/konv_message.png new file mode 100644 index 000000000..b11381d2c Binary files /dev/null and b/retroshare-gui/src/gui/images/konv_message.png differ diff --git a/retroshare-gui/src/gui/images/konv_message2.png b/retroshare-gui/src/gui/images/konv_message2.png new file mode 100644 index 000000000..da0dba1e3 Binary files /dev/null and b/retroshare-gui/src/gui/images/konv_message2.png differ diff --git a/retroshare-gui/src/gui/images/konversation.png b/retroshare-gui/src/gui/images/konversation.png new file mode 100644 index 000000000..7b9299718 Binary files /dev/null and b/retroshare-gui/src/gui/images/konversation.png differ diff --git a/retroshare-gui/src/gui/images/konversation128.png b/retroshare-gui/src/gui/images/konversation128.png new file mode 100644 index 000000000..4398fd869 Binary files /dev/null and b/retroshare-gui/src/gui/images/konversation128.png differ diff --git a/retroshare-gui/src/gui/images/konversation16.png b/retroshare-gui/src/gui/images/konversation16.png new file mode 100644 index 000000000..18565596d Binary files /dev/null and b/retroshare-gui/src/gui/images/konversation16.png differ diff --git a/retroshare-gui/src/gui/images/konversation64.png b/retroshare-gui/src/gui/images/konversation64.png new file mode 100644 index 000000000..6d3a8e8e3 Binary files /dev/null and b/retroshare-gui/src/gui/images/konversation64.png differ diff --git a/retroshare-gui/src/gui/images/konversation_new.png b/retroshare-gui/src/gui/images/konversation_new.png new file mode 100644 index 000000000..db5dc8310 Binary files /dev/null and b/retroshare-gui/src/gui/images/konversation_new.png differ diff --git a/retroshare-gui/src/gui/images/ksysguard.png b/retroshare-gui/src/gui/images/ksysguard.png new file mode 100644 index 000000000..10c196ebf Binary files /dev/null and b/retroshare-gui/src/gui/images/ksysguard.png differ diff --git a/retroshare-gui/src/gui/images/ksysguard32.png b/retroshare-gui/src/gui/images/ksysguard32.png new file mode 100755 index 000000000..b30f71d2b Binary files /dev/null and b/retroshare-gui/src/gui/images/ksysguard32.png differ diff --git a/retroshare-gui/src/gui/images/ktorrent.png b/retroshare-gui/src/gui/images/ktorrent.png new file mode 100644 index 000000000..740badb8c Binary files /dev/null and b/retroshare-gui/src/gui/images/ktorrent.png differ diff --git a/retroshare-gui/src/gui/images/ktorrent32.png b/retroshare-gui/src/gui/images/ktorrent32.png new file mode 100644 index 000000000..fe92c486e Binary files /dev/null and b/retroshare-gui/src/gui/images/ktorrent32.png differ diff --git a/retroshare-gui/src/gui/images/ledoff1.png b/retroshare-gui/src/gui/images/ledoff1.png new file mode 100644 index 000000000..3cbc2849d Binary files /dev/null and b/retroshare-gui/src/gui/images/ledoff1.png differ diff --git a/retroshare-gui/src/gui/images/ledon1.png b/retroshare-gui/src/gui/images/ledon1.png new file mode 100644 index 000000000..450d73745 Binary files /dev/null and b/retroshare-gui/src/gui/images/ledon1.png differ diff --git a/retroshare-gui/src/gui/images/library.png b/retroshare-gui/src/gui/images/library.png new file mode 100644 index 000000000..d9e473dce Binary files /dev/null and b/retroshare-gui/src/gui/images/library.png differ diff --git a/retroshare-gui/src/gui/images/list_bullet_arrow.png b/retroshare-gui/src/gui/images/list_bullet_arrow.png new file mode 100644 index 000000000..acf9f5da5 Binary files /dev/null and b/retroshare-gui/src/gui/images/list_bullet_arrow.png differ diff --git a/retroshare-gui/src/gui/images/loadcert16.png b/retroshare-gui/src/gui/images/loadcert16.png new file mode 100644 index 000000000..aa4f287b0 Binary files /dev/null and b/retroshare-gui/src/gui/images/loadcert16.png differ diff --git a/retroshare-gui/src/gui/images/loader/16-loader.gif b/retroshare-gui/src/gui/images/loader/16-loader.gif new file mode 100644 index 000000000..5b33f7e54 Binary files /dev/null and b/retroshare-gui/src/gui/images/loader/16-loader.gif differ diff --git a/retroshare-gui/src/gui/images/loader/32-loader.gif b/retroshare-gui/src/gui/images/loader/32-loader.gif new file mode 100644 index 000000000..3288d1035 Binary files /dev/null and b/retroshare-gui/src/gui/images/loader/32-loader.gif differ diff --git a/retroshare-gui/src/gui/images/loader/progress.gif b/retroshare-gui/src/gui/images/loader/progress.gif new file mode 100644 index 000000000..d84f65378 Binary files /dev/null and b/retroshare-gui/src/gui/images/loader/progress.gif differ diff --git a/retroshare-gui/src/gui/images/locale.png b/retroshare-gui/src/gui/images/locale.png new file mode 100644 index 000000000..e1bc30916 Binary files /dev/null and b/retroshare-gui/src/gui/images/locale.png differ diff --git a/retroshare-gui/src/gui/images/logobar/logo_bar_fill.png b/retroshare-gui/src/gui/images/logobar/logo_bar_fill.png new file mode 100644 index 000000000..fa8257794 Binary files /dev/null and b/retroshare-gui/src/gui/images/logobar/logo_bar_fill.png differ diff --git a/retroshare-gui/src/gui/images/logobar/logo_bar_start.png b/retroshare-gui/src/gui/images/logobar/logo_bar_start.png new file mode 100644 index 000000000..9ebb7d1fe Binary files /dev/null and b/retroshare-gui/src/gui/images/logobar/logo_bar_start.png differ diff --git a/retroshare-gui/src/gui/images/logobar/rslogo.png b/retroshare-gui/src/gui/images/logobar/rslogo.png new file mode 100644 index 000000000..18aaa95b2 Binary files /dev/null and b/retroshare-gui/src/gui/images/logobar/rslogo.png differ diff --git a/retroshare-gui/src/gui/images/logobar/rslogo2.png b/retroshare-gui/src/gui/images/logobar/rslogo2.png new file mode 100644 index 000000000..ff7e0dfee Binary files /dev/null and b/retroshare-gui/src/gui/images/logobar/rslogo2.png differ diff --git a/retroshare-gui/src/gui/images/logobar/rslogoclean.png b/retroshare-gui/src/gui/images/logobar/rslogoclean.png new file mode 100644 index 000000000..0ebb66fa9 Binary files /dev/null and b/retroshare-gui/src/gui/images/logobar/rslogoclean.png differ diff --git a/retroshare-gui/src/gui/images/looknfeel.png b/retroshare-gui/src/gui/images/looknfeel.png new file mode 100644 index 000000000..155e2d865 Binary files /dev/null and b/retroshare-gui/src/gui/images/looknfeel.png differ diff --git a/retroshare-gui/src/gui/images/lphoto.png b/retroshare-gui/src/gui/images/lphoto.png new file mode 100644 index 000000000..c7bb01c11 Binary files /dev/null and b/retroshare-gui/src/gui/images/lphoto.png differ diff --git a/retroshare-gui/src/gui/images/lphoto16.png b/retroshare-gui/src/gui/images/lphoto16.png new file mode 100644 index 000000000..f57102985 Binary files /dev/null and b/retroshare-gui/src/gui/images/lphoto16.png differ diff --git a/retroshare-gui/src/gui/images/lphoto24.png b/retroshare-gui/src/gui/images/lphoto24.png new file mode 100644 index 000000000..4eb197db1 Binary files /dev/null and b/retroshare-gui/src/gui/images/lphoto24.png differ diff --git a/retroshare-gui/src/gui/images/mail-signature-unknown.png b/retroshare-gui/src/gui/images/mail-signature-unknown.png new file mode 100644 index 000000000..300d5452c Binary files /dev/null and b/retroshare-gui/src/gui/images/mail-signature-unknown.png differ diff --git a/retroshare-gui/src/gui/images/mail-signed.png b/retroshare-gui/src/gui/images/mail-signed.png new file mode 100644 index 000000000..288f6ca77 Binary files /dev/null and b/retroshare-gui/src/gui/images/mail-signed.png differ diff --git a/retroshare-gui/src/gui/images/mail_delete.png b/retroshare-gui/src/gui/images/mail_delete.png new file mode 100644 index 000000000..dc9c020f7 Binary files /dev/null and b/retroshare-gui/src/gui/images/mail_delete.png differ diff --git a/retroshare-gui/src/gui/images/mail_forward.png b/retroshare-gui/src/gui/images/mail_forward.png new file mode 100755 index 000000000..833360b24 Binary files /dev/null and b/retroshare-gui/src/gui/images/mail_forward.png differ diff --git a/retroshare-gui/src/gui/images/mail_get.png b/retroshare-gui/src/gui/images/mail_get.png new file mode 100644 index 000000000..a8fc27a5c Binary files /dev/null and b/retroshare-gui/src/gui/images/mail_get.png differ diff --git a/retroshare-gui/src/gui/images/mail_new.png b/retroshare-gui/src/gui/images/mail_new.png new file mode 100644 index 000000000..55bba1bdd Binary files /dev/null and b/retroshare-gui/src/gui/images/mail_new.png differ diff --git a/retroshare-gui/src/gui/images/mail_reply.png b/retroshare-gui/src/gui/images/mail_reply.png new file mode 100644 index 000000000..471a08ebf Binary files /dev/null and b/retroshare-gui/src/gui/images/mail_reply.png differ diff --git a/retroshare-gui/src/gui/images/mail_replyall.png b/retroshare-gui/src/gui/images/mail_replyall.png new file mode 100755 index 000000000..6e738a11e Binary files /dev/null and b/retroshare-gui/src/gui/images/mail_replyall.png differ diff --git a/retroshare-gui/src/gui/images/mail_send.png b/retroshare-gui/src/gui/images/mail_send.png new file mode 100644 index 000000000..0366228e9 Binary files /dev/null and b/retroshare-gui/src/gui/images/mail_send.png differ diff --git a/retroshare-gui/src/gui/images/mail_send24.png b/retroshare-gui/src/gui/images/mail_send24.png new file mode 100644 index 000000000..be6d64f00 Binary files /dev/null and b/retroshare-gui/src/gui/images/mail_send24.png differ diff --git a/retroshare-gui/src/gui/images/mailforward24-hover.png b/retroshare-gui/src/gui/images/mailforward24-hover.png new file mode 100644 index 000000000..bb00a4fb4 Binary files /dev/null and b/retroshare-gui/src/gui/images/mailforward24-hover.png differ diff --git a/retroshare-gui/src/gui/images/mailforward24.png b/retroshare-gui/src/gui/images/mailforward24.png new file mode 100644 index 000000000..eaa8a6296 Binary files /dev/null and b/retroshare-gui/src/gui/images/mailforward24.png differ diff --git a/retroshare-gui/src/gui/images/message-mail-forwarded-read.png b/retroshare-gui/src/gui/images/message-mail-forwarded-read.png new file mode 100644 index 000000000..390c5b8ad Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail-forwarded-read.png differ diff --git a/retroshare-gui/src/gui/images/message-mail-forwarded.png b/retroshare-gui/src/gui/images/message-mail-forwarded.png new file mode 100644 index 000000000..e7d9881a5 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail-forwarded.png differ diff --git a/retroshare-gui/src/gui/images/message-mail-imapdelete.png b/retroshare-gui/src/gui/images/message-mail-imapdelete.png new file mode 100644 index 000000000..688577262 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail-imapdelete.png differ diff --git a/retroshare-gui/src/gui/images/message-mail-new.png b/retroshare-gui/src/gui/images/message-mail-new.png new file mode 100644 index 000000000..fdd4f3dab Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail-new.png differ diff --git a/retroshare-gui/src/gui/images/message-mail-read.png b/retroshare-gui/src/gui/images/message-mail-read.png new file mode 100644 index 000000000..2599d6e90 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail-read.png differ diff --git a/retroshare-gui/src/gui/images/message-mail-replied-forw-read.png b/retroshare-gui/src/gui/images/message-mail-replied-forw-read.png new file mode 100644 index 000000000..54340d00d Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail-replied-forw-read.png differ diff --git a/retroshare-gui/src/gui/images/message-mail-replied-forw.png b/retroshare-gui/src/gui/images/message-mail-replied-forw.png new file mode 100644 index 000000000..b465758f5 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail-replied-forw.png differ diff --git a/retroshare-gui/src/gui/images/message-mail-replied-read.png b/retroshare-gui/src/gui/images/message-mail-replied-read.png new file mode 100644 index 000000000..b41e15441 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail-replied-read.png differ diff --git a/retroshare-gui/src/gui/images/message-mail-replied.png b/retroshare-gui/src/gui/images/message-mail-replied.png new file mode 100644 index 000000000..1205b7021 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail-replied.png differ diff --git a/retroshare-gui/src/gui/images/message-mail.png b/retroshare-gui/src/gui/images/message-mail.png new file mode 100644 index 000000000..a1a1431f5 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-mail.png differ diff --git a/retroshare-gui/src/gui/images/message-news.png b/retroshare-gui/src/gui/images/message-news.png new file mode 100644 index 000000000..c46bf3c95 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-news.png differ diff --git a/retroshare-gui/src/gui/images/message-state-header.png b/retroshare-gui/src/gui/images/message-state-header.png new file mode 100644 index 000000000..df2ab6572 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-state-header.png differ diff --git a/retroshare-gui/src/gui/images/message-state-new.png b/retroshare-gui/src/gui/images/message-state-new.png new file mode 100644 index 000000000..75190ca18 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-state-new.png differ diff --git a/retroshare-gui/src/gui/images/message-state-read.png b/retroshare-gui/src/gui/images/message-state-read.png new file mode 100644 index 000000000..a62a523d6 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-state-read.png differ diff --git a/retroshare-gui/src/gui/images/message-state-unread.png b/retroshare-gui/src/gui/images/message-state-unread.png new file mode 100644 index 000000000..e4fa9c227 Binary files /dev/null and b/retroshare-gui/src/gui/images/message-state-unread.png differ diff --git a/retroshare-gui/src/gui/images/message.png b/retroshare-gui/src/gui/images/message.png new file mode 100644 index 000000000..6000bcd3f Binary files /dev/null and b/retroshare-gui/src/gui/images/message.png differ diff --git a/retroshare-gui/src/gui/images/messages_new.png b/retroshare-gui/src/gui/images/messages_new.png new file mode 100644 index 000000000..c2239d6f2 Binary files /dev/null and b/retroshare-gui/src/gui/images/messages_new.png differ diff --git a/retroshare-gui/src/gui/images/messenger.png b/retroshare-gui/src/gui/images/messenger.png new file mode 100644 index 000000000..cf15aadc5 Binary files /dev/null and b/retroshare-gui/src/gui/images/messenger.png differ diff --git a/retroshare-gui/src/gui/images/mimetypes/pdf.png b/retroshare-gui/src/gui/images/mimetypes/pdf.png new file mode 100644 index 000000000..73946b90d Binary files /dev/null and b/retroshare-gui/src/gui/images/mimetypes/pdf.png differ diff --git a/retroshare-gui/src/gui/images/mimetypes/source_c.png b/retroshare-gui/src/gui/images/mimetypes/source_c.png new file mode 100644 index 000000000..51e7d3976 Binary files /dev/null and b/retroshare-gui/src/gui/images/mimetypes/source_c.png differ diff --git a/retroshare-gui/src/gui/images/mimetypes/source_cpp.png b/retroshare-gui/src/gui/images/mimetypes/source_cpp.png new file mode 100644 index 000000000..522dc111f Binary files /dev/null and b/retroshare-gui/src/gui/images/mimetypes/source_cpp.png differ diff --git a/retroshare-gui/src/gui/images/mimetypes/source_h.png b/retroshare-gui/src/gui/images/mimetypes/source_h.png new file mode 100644 index 000000000..116790f4e Binary files /dev/null and b/retroshare-gui/src/gui/images/mimetypes/source_h.png differ diff --git a/retroshare-gui/src/gui/images/mystatus_bg.png b/retroshare-gui/src/gui/images/mystatus_bg.png new file mode 100644 index 000000000..4a428424c Binary files /dev/null and b/retroshare-gui/src/gui/images/mystatus_bg.png differ diff --git a/retroshare-gui/src/gui/images/mystatus_bg_busy.png b/retroshare-gui/src/gui/images/mystatus_bg_busy.png new file mode 100644 index 000000000..5dbfae3e1 Binary files /dev/null and b/retroshare-gui/src/gui/images/mystatus_bg_busy.png differ diff --git a/retroshare-gui/src/gui/images/mystatus_bg_idle.png b/retroshare-gui/src/gui/images/mystatus_bg_idle.png new file mode 100644 index 000000000..360203528 Binary files /dev/null and b/retroshare-gui/src/gui/images/mystatus_bg_idle.png differ diff --git a/retroshare-gui/src/gui/images/mystatus_bg_offline.png b/retroshare-gui/src/gui/images/mystatus_bg_offline.png new file mode 100644 index 000000000..55805b607 Binary files /dev/null and b/retroshare-gui/src/gui/images/mystatus_bg_offline.png differ diff --git a/retroshare-gui/src/gui/images/mystatus_bg_online.png b/retroshare-gui/src/gui/images/mystatus_bg_online.png new file mode 100644 index 000000000..1c6e1ca77 Binary files /dev/null and b/retroshare-gui/src/gui/images/mystatus_bg_online.png differ diff --git a/retroshare-gui/src/gui/images/network.png b/retroshare-gui/src/gui/images/network.png new file mode 100644 index 000000000..99a04417a Binary files /dev/null and b/retroshare-gui/src/gui/images/network.png differ diff --git a/retroshare-gui/src/gui/images/network16.png b/retroshare-gui/src/gui/images/network16.png new file mode 100644 index 000000000..e1f1bd7cb Binary files /dev/null and b/retroshare-gui/src/gui/images/network16.png differ diff --git a/retroshare-gui/src/gui/images/network32.png b/retroshare-gui/src/gui/images/network32.png new file mode 100644 index 000000000..e74a67f44 Binary files /dev/null and b/retroshare-gui/src/gui/images/network32.png differ diff --git a/retroshare-gui/src/gui/images/new-mail-alert.png b/retroshare-gui/src/gui/images/new-mail-alert.png new file mode 100644 index 000000000..78a1557b3 Binary files /dev/null and b/retroshare-gui/src/gui/images/new-mail-alert.png differ diff --git a/retroshare-gui/src/gui/images/new_forum16.png b/retroshare-gui/src/gui/images/new_forum16.png new file mode 100644 index 000000000..712802dde Binary files /dev/null and b/retroshare-gui/src/gui/images/new_forum16.png differ diff --git a/retroshare-gui/src/gui/images/newmsg.png b/retroshare-gui/src/gui/images/newmsg.png new file mode 100644 index 000000000..6f011f878 Binary files /dev/null and b/retroshare-gui/src/gui/images/newmsg.png differ diff --git a/retroshare-gui/src/gui/images/no_avatar.png b/retroshare-gui/src/gui/images/no_avatar.png new file mode 100644 index 000000000..eac675fdd Binary files /dev/null and b/retroshare-gui/src/gui/images/no_avatar.png differ diff --git a/retroshare-gui/src/gui/images/no_avatar_70.png b/retroshare-gui/src/gui/images/no_avatar_70.png new file mode 100644 index 000000000..abd29c18a Binary files /dev/null and b/retroshare-gui/src/gui/images/no_avatar_70.png differ diff --git a/retroshare-gui/src/gui/images/no_avatar_background.png b/retroshare-gui/src/gui/images/no_avatar_background.png new file mode 100644 index 000000000..b09f36f37 Binary files /dev/null and b/retroshare-gui/src/gui/images/no_avatar_background.png differ diff --git a/retroshare-gui/src/gui/images/null.png b/retroshare-gui/src/gui/images/null.png new file mode 100644 index 000000000..a85bb6491 Binary files /dev/null and b/retroshare-gui/src/gui/images/null.png differ diff --git a/retroshare-gui/src/gui/images/openimage.png b/retroshare-gui/src/gui/images/openimage.png new file mode 100644 index 000000000..d5c263c8b Binary files /dev/null and b/retroshare-gui/src/gui/images/openimage.png differ diff --git a/retroshare-gui/src/gui/images/package_games1.png b/retroshare-gui/src/gui/images/package_games1.png new file mode 100644 index 000000000..5ea65cf6e Binary files /dev/null and b/retroshare-gui/src/gui/images/package_games1.png differ diff --git a/retroshare-gui/src/gui/images/pasterslink.png b/retroshare-gui/src/gui/images/pasterslink.png new file mode 100644 index 000000000..5c003038a Binary files /dev/null and b/retroshare-gui/src/gui/images/pasterslink.png differ diff --git a/retroshare-gui/src/gui/images/pause.png b/retroshare-gui/src/gui/images/pause.png new file mode 100644 index 000000000..6374a4026 Binary files /dev/null and b/retroshare-gui/src/gui/images/pause.png differ diff --git a/retroshare-gui/src/gui/images/peerdetails_16x16.png b/retroshare-gui/src/gui/images/peerdetails_16x16.png new file mode 100644 index 000000000..c3038709e Binary files /dev/null and b/retroshare-gui/src/gui/images/peerdetails_16x16.png differ diff --git a/retroshare-gui/src/gui/images/peers_16x16.png b/retroshare-gui/src/gui/images/peers_16x16.png new file mode 100644 index 000000000..a1d1bac82 Binary files /dev/null and b/retroshare-gui/src/gui/images/peers_16x16.png differ diff --git a/retroshare-gui/src/gui/images/peers_24x24.png b/retroshare-gui/src/gui/images/peers_24x24.png new file mode 100644 index 000000000..f72aa562f Binary files /dev/null and b/retroshare-gui/src/gui/images/peers_24x24.png differ diff --git a/retroshare-gui/src/gui/images/pgp.png b/retroshare-gui/src/gui/images/pgp.png new file mode 100644 index 000000000..1d9a89252 Binary files /dev/null and b/retroshare-gui/src/gui/images/pgp.png differ diff --git a/retroshare-gui/src/gui/images/player_play.png b/retroshare-gui/src/gui/images/player_play.png new file mode 100644 index 000000000..e7819a09a Binary files /dev/null and b/retroshare-gui/src/gui/images/player_play.png differ diff --git a/retroshare-gui/src/gui/images/preview.png b/retroshare-gui/src/gui/images/preview.png new file mode 100644 index 000000000..7252c88d9 Binary files /dev/null and b/retroshare-gui/src/gui/images/preview.png differ diff --git a/retroshare-gui/src/gui/images/print24.png b/retroshare-gui/src/gui/images/print24.png new file mode 100644 index 000000000..31657ea49 Binary files /dev/null and b/retroshare-gui/src/gui/images/print24.png differ diff --git a/retroshare-gui/src/gui/images/priorityauto.png b/retroshare-gui/src/gui/images/priorityauto.png new file mode 100644 index 000000000..9126fb3d9 Binary files /dev/null and b/retroshare-gui/src/gui/images/priorityauto.png differ diff --git a/retroshare-gui/src/gui/images/priorityhigh.png b/retroshare-gui/src/gui/images/priorityhigh.png new file mode 100644 index 000000000..7418516f5 Binary files /dev/null and b/retroshare-gui/src/gui/images/priorityhigh.png differ diff --git a/retroshare-gui/src/gui/images/prioritylow.png b/retroshare-gui/src/gui/images/prioritylow.png new file mode 100644 index 000000000..d32a3e70b Binary files /dev/null and b/retroshare-gui/src/gui/images/prioritylow.png differ diff --git a/retroshare-gui/src/gui/images/prioritynormal.png b/retroshare-gui/src/gui/images/prioritynormal.png new file mode 100644 index 000000000..36816479d Binary files /dev/null and b/retroshare-gui/src/gui/images/prioritynormal.png differ diff --git a/retroshare-gui/src/gui/images/priorityquestion.png b/retroshare-gui/src/gui/images/priorityquestion.png new file mode 100644 index 000000000..9126fb3d9 Binary files /dev/null and b/retroshare-gui/src/gui/images/priorityquestion.png differ diff --git a/retroshare-gui/src/gui/images/quick_restart24.png b/retroshare-gui/src/gui/images/quick_restart24.png new file mode 100644 index 000000000..928e87422 Binary files /dev/null and b/retroshare-gui/src/gui/images/quick_restart24.png differ diff --git a/retroshare-gui/src/gui/images/quote_24.png b/retroshare-gui/src/gui/images/quote_24.png new file mode 100644 index 000000000..57107f679 Binary files /dev/null and b/retroshare-gui/src/gui/images/quote_24.png differ diff --git a/retroshare-gui/src/gui/images/quote_24_hover.png b/retroshare-gui/src/gui/images/quote_24_hover.png new file mode 100644 index 000000000..cc16fdbd8 Binary files /dev/null and b/retroshare-gui/src/gui/images/quote_24_hover.png differ diff --git a/retroshare-gui/src/gui/images/rate-1.png b/retroshare-gui/src/gui/images/rate-1.png new file mode 100644 index 000000000..b24fcc309 Binary files /dev/null and b/retroshare-gui/src/gui/images/rate-1.png differ diff --git a/retroshare-gui/src/gui/images/rate-2.png b/retroshare-gui/src/gui/images/rate-2.png new file mode 100644 index 000000000..22e0c855d Binary files /dev/null and b/retroshare-gui/src/gui/images/rate-2.png differ diff --git a/retroshare-gui/src/gui/images/rate-3.png b/retroshare-gui/src/gui/images/rate-3.png new file mode 100644 index 000000000..759f1e415 Binary files /dev/null and b/retroshare-gui/src/gui/images/rate-3.png differ diff --git a/retroshare-gui/src/gui/images/rate-4.png b/retroshare-gui/src/gui/images/rate-4.png new file mode 100644 index 000000000..f6fb27ec6 Binary files /dev/null and b/retroshare-gui/src/gui/images/rate-4.png differ diff --git a/retroshare-gui/src/gui/images/rate-5.png b/retroshare-gui/src/gui/images/rate-5.png new file mode 100644 index 000000000..36b95cdbd Binary files /dev/null and b/retroshare-gui/src/gui/images/rate-5.png differ diff --git a/retroshare-gui/src/gui/images/rating.png b/retroshare-gui/src/gui/images/rating.png new file mode 100644 index 000000000..6e47827b5 Binary files /dev/null and b/retroshare-gui/src/gui/images/rating.png differ diff --git a/retroshare-gui/src/gui/images/rc_combined.png b/retroshare-gui/src/gui/images/rc_combined.png new file mode 100644 index 000000000..c395794ca Binary files /dev/null and b/retroshare-gui/src/gui/images/rc_combined.png differ diff --git a/retroshare-gui/src/gui/images/records.png b/retroshare-gui/src/gui/images/records.png new file mode 100644 index 000000000..0aa5ec2a4 Binary files /dev/null and b/retroshare-gui/src/gui/images/records.png differ diff --git a/retroshare-gui/src/gui/images/redled.png b/retroshare-gui/src/gui/images/redled.png new file mode 100644 index 000000000..6ed35dee2 Binary files /dev/null and b/retroshare-gui/src/gui/images/redled.png differ diff --git a/retroshare-gui/src/gui/images/reload24.png b/retroshare-gui/src/gui/images/reload24.png new file mode 100644 index 000000000..be0e77052 Binary files /dev/null and b/retroshare-gui/src/gui/images/reload24.png differ diff --git a/retroshare-gui/src/gui/images/removefriend16.png b/retroshare-gui/src/gui/images/removefriend16.png new file mode 100644 index 000000000..91839538b Binary files /dev/null and b/retroshare-gui/src/gui/images/removefriend16.png differ diff --git a/retroshare-gui/src/gui/images/replymail-hover.png b/retroshare-gui/src/gui/images/replymail-hover.png new file mode 100644 index 000000000..aea2193e0 Binary files /dev/null and b/retroshare-gui/src/gui/images/replymail-hover.png differ diff --git a/retroshare-gui/src/gui/images/replymail-pressed.png b/retroshare-gui/src/gui/images/replymail-pressed.png new file mode 100644 index 000000000..aea2193e0 Binary files /dev/null and b/retroshare-gui/src/gui/images/replymail-pressed.png differ diff --git a/retroshare-gui/src/gui/images/replymail24.png b/retroshare-gui/src/gui/images/replymail24.png new file mode 100644 index 000000000..41c52c79e Binary files /dev/null and b/retroshare-gui/src/gui/images/replymail24.png differ diff --git a/retroshare-gui/src/gui/images/replymailall24-hover.png b/retroshare-gui/src/gui/images/replymailall24-hover.png new file mode 100644 index 000000000..ca8acf2a8 Binary files /dev/null and b/retroshare-gui/src/gui/images/replymailall24-hover.png differ diff --git a/retroshare-gui/src/gui/images/replymailall24.png b/retroshare-gui/src/gui/images/replymailall24.png new file mode 100644 index 000000000..5da21d539 Binary files /dev/null and b/retroshare-gui/src/gui/images/replymailall24.png differ diff --git a/retroshare-gui/src/gui/images/reset.png b/retroshare-gui/src/gui/images/reset.png new file mode 100644 index 000000000..84439ebb9 Binary files /dev/null and b/retroshare-gui/src/gui/images/reset.png differ diff --git a/retroshare-gui/src/gui/images/resume.png b/retroshare-gui/src/gui/images/resume.png new file mode 100644 index 000000000..594fbe1f2 Binary files /dev/null and b/retroshare-gui/src/gui/images/resume.png differ diff --git a/retroshare-gui/src/gui/images/retroshare_win.rc b/retroshare-gui/src/gui/images/retroshare_win.rc new file mode 100644 index 000000000..88d53bdc9 --- /dev/null +++ b/retroshare-gui/src/gui/images/retroshare_win.rc @@ -0,0 +1,3 @@ +#include "retroshare_win.rc.h" + +IDI_ICON1 ICON "gui/images/rs1.ico" diff --git a/retroshare-gui/src/gui/images/retroshare_win.rc.h b/retroshare-gui/src/gui/images/retroshare_win.rc.h new file mode 100644 index 000000000..2c189044e --- /dev/null +++ b/retroshare-gui/src/gui/images/retroshare_win.rc.h @@ -0,0 +1,25 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + + +#define IDI_ICON1 101 + diff --git a/retroshare-gui/src/gui/images/retrosharelogo1.png b/retroshare-gui/src/gui/images/retrosharelogo1.png new file mode 100644 index 000000000..9d0ff4810 Binary files /dev/null and b/retroshare-gui/src/gui/images/retrosharelogo1.png differ diff --git a/retroshare-gui/src/gui/images/retrosharelogo2.png b/retroshare-gui/src/gui/images/retrosharelogo2.png new file mode 100644 index 000000000..39629e2b0 Binary files /dev/null and b/retroshare-gui/src/gui/images/retrosharelogo2.png differ diff --git a/retroshare-gui/src/gui/images/retrosharelogo32.png b/retroshare-gui/src/gui/images/retrosharelogo32.png new file mode 100755 index 000000000..abe849812 Binary files /dev/null and b/retroshare-gui/src/gui/images/retrosharelogo32.png differ diff --git a/retroshare-gui/src/gui/images/retrotoolbar.png b/retroshare-gui/src/gui/images/retrotoolbar.png new file mode 100644 index 000000000..4a8e6cd39 Binary files /dev/null and b/retroshare-gui/src/gui/images/retrotoolbar.png differ diff --git a/retroshare-gui/src/gui/images/rs-2.png b/retroshare-gui/src/gui/images/rs-2.png new file mode 100644 index 000000000..e5691d430 Binary files /dev/null and b/retroshare-gui/src/gui/images/rs-2.png differ diff --git a/retroshare-gui/src/gui/images/rs1.ico b/retroshare-gui/src/gui/images/rs1.ico new file mode 100644 index 000000000..04898b69b Binary files /dev/null and b/retroshare-gui/src/gui/images/rs1.ico differ diff --git a/retroshare-gui/src/gui/images/rs1.png b/retroshare-gui/src/gui/images/rs1.png new file mode 100644 index 000000000..5c58c14ef Binary files /dev/null and b/retroshare-gui/src/gui/images/rs1.png differ diff --git a/retroshare-gui/src/gui/images/rs_wizard.png b/retroshare-gui/src/gui/images/rs_wizard.png new file mode 100644 index 000000000..387d21177 Binary files /dev/null and b/retroshare-gui/src/gui/images/rs_wizard.png differ diff --git a/retroshare-gui/src/gui/images/rsmessenger16.png b/retroshare-gui/src/gui/images/rsmessenger16.png new file mode 100644 index 000000000..cdc8dd66c Binary files /dev/null and b/retroshare-gui/src/gui/images/rsmessenger16.png differ diff --git a/retroshare-gui/src/gui/images/rsmessenger32.png b/retroshare-gui/src/gui/images/rsmessenger32.png new file mode 100644 index 000000000..d768a5624 Binary files /dev/null and b/retroshare-gui/src/gui/images/rsmessenger32.png differ diff --git a/retroshare-gui/src/gui/images/rsmessenger48.png b/retroshare-gui/src/gui/images/rsmessenger48.png new file mode 100644 index 000000000..f01ab76b4 Binary files /dev/null and b/retroshare-gui/src/gui/images/rsmessenger48.png differ diff --git a/retroshare-gui/src/gui/images/rstray0.png b/retroshare-gui/src/gui/images/rstray0.png new file mode 100644 index 000000000..255bd3e7e Binary files /dev/null and b/retroshare-gui/src/gui/images/rstray0.png differ diff --git a/retroshare-gui/src/gui/images/rstray1.png b/retroshare-gui/src/gui/images/rstray1.png new file mode 100644 index 000000000..cb8a756a1 Binary files /dev/null and b/retroshare-gui/src/gui/images/rstray1.png differ diff --git a/retroshare-gui/src/gui/images/rstray2.png b/retroshare-gui/src/gui/images/rstray2.png new file mode 100644 index 000000000..e5ee501db Binary files /dev/null and b/retroshare-gui/src/gui/images/rstray2.png differ diff --git a/retroshare-gui/src/gui/images/rstray3.png b/retroshare-gui/src/gui/images/rstray3.png new file mode 100644 index 000000000..d03d45063 Binary files /dev/null and b/retroshare-gui/src/gui/images/rstray3.png differ diff --git a/retroshare-gui/src/gui/images/rstray_new.png b/retroshare-gui/src/gui/images/rstray_new.png new file mode 100644 index 000000000..a45d972d3 Binary files /dev/null and b/retroshare-gui/src/gui/images/rstray_new.png differ diff --git a/retroshare-gui/src/gui/images/rswinicon.ico b/retroshare-gui/src/gui/images/rswinicon.ico new file mode 100644 index 000000000..9b319e658 Binary files /dev/null and b/retroshare-gui/src/gui/images/rswinicon.ico differ diff --git a/retroshare-gui/src/gui/images/save24.png b/retroshare-gui/src/gui/images/save24.png new file mode 100644 index 000000000..6a93835a4 Binary files /dev/null and b/retroshare-gui/src/gui/images/save24.png differ diff --git a/retroshare-gui/src/gui/images/security-high-16.png b/retroshare-gui/src/gui/images/security-high-16.png new file mode 100644 index 000000000..d93b4bdd9 Binary files /dev/null and b/retroshare-gui/src/gui/images/security-high-16.png differ diff --git a/retroshare-gui/src/gui/images/security-high-32.png b/retroshare-gui/src/gui/images/security-high-32.png new file mode 100755 index 000000000..95e73d93e Binary files /dev/null and b/retroshare-gui/src/gui/images/security-high-32.png differ diff --git a/retroshare-gui/src/gui/images/security-high-48.png b/retroshare-gui/src/gui/images/security-high-48.png new file mode 100644 index 000000000..fb54fd735 Binary files /dev/null and b/retroshare-gui/src/gui/images/security-high-48.png differ diff --git a/retroshare-gui/src/gui/images/security-high-off-48.png b/retroshare-gui/src/gui/images/security-high-off-48.png new file mode 100644 index 000000000..d4149def2 Binary files /dev/null and b/retroshare-gui/src/gui/images/security-high-off-48.png differ diff --git a/retroshare-gui/src/gui/images/security-low-48.png b/retroshare-gui/src/gui/images/security-low-48.png new file mode 100644 index 000000000..9d5659f46 Binary files /dev/null and b/retroshare-gui/src/gui/images/security-low-48.png differ diff --git a/retroshare-gui/src/gui/images/security-low-off-48.png b/retroshare-gui/src/gui/images/security-low-off-48.png new file mode 100644 index 000000000..80901511d Binary files /dev/null and b/retroshare-gui/src/gui/images/security-low-off-48.png differ diff --git a/retroshare-gui/src/gui/images/security-medium-48.png b/retroshare-gui/src/gui/images/security-medium-48.png new file mode 100644 index 000000000..9265eb46c Binary files /dev/null and b/retroshare-gui/src/gui/images/security-medium-48.png differ diff --git a/retroshare-gui/src/gui/images/security-medium-off-48.png b/retroshare-gui/src/gui/images/security-medium-off-48.png new file mode 100644 index 000000000..89c83df46 Binary files /dev/null and b/retroshare-gui/src/gui/images/security-medium-off-48.png differ diff --git a/retroshare-gui/src/gui/images/send24-hover.png b/retroshare-gui/src/gui/images/send24-hover.png new file mode 100644 index 000000000..f987787f9 Binary files /dev/null and b/retroshare-gui/src/gui/images/send24-hover.png differ diff --git a/retroshare-gui/src/gui/images/send24.png b/retroshare-gui/src/gui/images/send24.png new file mode 100644 index 000000000..1f66781f3 Binary files /dev/null and b/retroshare-gui/src/gui/images/send24.png differ diff --git a/retroshare-gui/src/gui/images/server_24x24.png b/retroshare-gui/src/gui/images/server_24x24.png new file mode 100644 index 000000000..fa4091150 Binary files /dev/null and b/retroshare-gui/src/gui/images/server_24x24.png differ diff --git a/retroshare-gui/src/gui/images/settings.png b/retroshare-gui/src/gui/images/settings.png new file mode 100644 index 000000000..9e6d52b8b Binary files /dev/null and b/retroshare-gui/src/gui/images/settings.png differ diff --git a/retroshare-gui/src/gui/images/settings16.png b/retroshare-gui/src/gui/images/settings16.png new file mode 100644 index 000000000..5f31eb45a Binary files /dev/null and b/retroshare-gui/src/gui/images/settings16.png differ diff --git a/retroshare-gui/src/gui/images/show_toolbox_frame.png b/retroshare-gui/src/gui/images/show_toolbox_frame.png new file mode 100644 index 000000000..e1d9351ce Binary files /dev/null and b/retroshare-gui/src/gui/images/show_toolbox_frame.png differ diff --git a/retroshare-gui/src/gui/images/sort_decrease.png b/retroshare-gui/src/gui/images/sort_decrease.png new file mode 100644 index 000000000..3d58baf4e Binary files /dev/null and b/retroshare-gui/src/gui/images/sort_decrease.png differ diff --git a/retroshare-gui/src/gui/images/sort_incr.png b/retroshare-gui/src/gui/images/sort_incr.png new file mode 100644 index 000000000..1fbf09dce Binary files /dev/null and b/retroshare-gui/src/gui/images/sort_incr.png differ diff --git a/retroshare-gui/src/gui/images/sound.png b/retroshare-gui/src/gui/images/sound.png new file mode 100644 index 000000000..fe37e137e Binary files /dev/null and b/retroshare-gui/src/gui/images/sound.png differ diff --git a/retroshare-gui/src/gui/images/sound_off.png b/retroshare-gui/src/gui/images/sound_off.png new file mode 100644 index 000000000..a7b048e8b Binary files /dev/null and b/retroshare-gui/src/gui/images/sound_off.png differ diff --git a/retroshare-gui/src/gui/images/splash.bmp b/retroshare-gui/src/gui/images/splash.bmp new file mode 100644 index 000000000..36ab545d4 Binary files /dev/null and b/retroshare-gui/src/gui/images/splash.bmp differ diff --git a/retroshare-gui/src/gui/images/splash.png b/retroshare-gui/src/gui/images/splash.png new file mode 100644 index 000000000..02a467ff1 Binary files /dev/null and b/retroshare-gui/src/gui/images/splash.png differ diff --git a/retroshare-gui/src/gui/images/star-off-16.png b/retroshare-gui/src/gui/images/star-off-16.png new file mode 100644 index 000000000..4c9da18ec Binary files /dev/null and b/retroshare-gui/src/gui/images/star-off-16.png differ diff --git a/retroshare-gui/src/gui/images/star-on-16.png b/retroshare-gui/src/gui/images/star-on-16.png new file mode 100644 index 000000000..d53827817 Binary files /dev/null and b/retroshare-gui/src/gui/images/star-on-16.png differ diff --git a/retroshare-gui/src/gui/images/start.png b/retroshare-gui/src/gui/images/start.png new file mode 100644 index 000000000..167cae741 Binary files /dev/null and b/retroshare-gui/src/gui/images/start.png differ diff --git a/retroshare-gui/src/gui/images/startall.png b/retroshare-gui/src/gui/images/startall.png new file mode 100644 index 000000000..2077ee514 Binary files /dev/null and b/retroshare-gui/src/gui/images/startall.png differ diff --git a/retroshare-gui/src/gui/images/status_unknown.png b/retroshare-gui/src/gui/images/status_unknown.png new file mode 100644 index 000000000..2f0c0fa9f Binary files /dev/null and b/retroshare-gui/src/gui/images/status_unknown.png differ diff --git a/retroshare-gui/src/gui/images/stop.png b/retroshare-gui/src/gui/images/stop.png new file mode 100644 index 000000000..b3313507d Binary files /dev/null and b/retroshare-gui/src/gui/images/stop.png differ diff --git a/retroshare-gui/src/gui/images/tab-dock.png b/retroshare-gui/src/gui/images/tab-dock.png new file mode 100644 index 000000000..ba059de40 Binary files /dev/null and b/retroshare-gui/src/gui/images/tab-dock.png differ diff --git a/retroshare-gui/src/gui/images/tab-undock.png b/retroshare-gui/src/gui/images/tab-undock.png new file mode 100644 index 000000000..f2827606c Binary files /dev/null and b/retroshare-gui/src/gui/images/tab-undock.png differ diff --git a/retroshare-gui/src/gui/images/tag24.png b/retroshare-gui/src/gui/images/tag24.png new file mode 100644 index 000000000..5da99c1d0 Binary files /dev/null and b/retroshare-gui/src/gui/images/tag24.png differ diff --git a/retroshare-gui/src/gui/images/textedit/editcopy.png b/retroshare-gui/src/gui/images/textedit/editcopy.png new file mode 100644 index 000000000..1121b47d8 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/editcopy.png differ diff --git a/retroshare-gui/src/gui/images/textedit/editcut.png b/retroshare-gui/src/gui/images/textedit/editcut.png new file mode 100644 index 000000000..38e55f742 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/editcut.png differ diff --git a/retroshare-gui/src/gui/images/textedit/editpaste.png b/retroshare-gui/src/gui/images/textedit/editpaste.png new file mode 100644 index 000000000..ffab15aaf Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/editpaste.png differ diff --git a/retroshare-gui/src/gui/images/textedit/editredo.png b/retroshare-gui/src/gui/images/textedit/editredo.png new file mode 100644 index 000000000..9d679fe6f Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/editredo.png differ diff --git a/retroshare-gui/src/gui/images/textedit/editundo.png b/retroshare-gui/src/gui/images/textedit/editundo.png new file mode 100644 index 000000000..eee23d24a Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/editundo.png differ diff --git a/retroshare-gui/src/gui/images/textedit/exportpdf.png b/retroshare-gui/src/gui/images/textedit/exportpdf.png new file mode 100644 index 000000000..eef513292 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/exportpdf.png differ diff --git a/retroshare-gui/src/gui/images/textedit/filenew.png b/retroshare-gui/src/gui/images/textedit/filenew.png new file mode 100644 index 000000000..af5d12214 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/filenew.png differ diff --git a/retroshare-gui/src/gui/images/textedit/fileopen.png b/retroshare-gui/src/gui/images/textedit/fileopen.png new file mode 100644 index 000000000..fc6f17e97 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/fileopen.png differ diff --git a/retroshare-gui/src/gui/images/textedit/fileprint.png b/retroshare-gui/src/gui/images/textedit/fileprint.png new file mode 100644 index 000000000..ba7c02dc1 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/fileprint.png differ diff --git a/retroshare-gui/src/gui/images/textedit/filesave.png b/retroshare-gui/src/gui/images/textedit/filesave.png new file mode 100644 index 000000000..8feec99be Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/filesave.png differ diff --git a/retroshare-gui/src/gui/images/textedit/format-list-ordered.png b/retroshare-gui/src/gui/images/textedit/format-list-ordered.png new file mode 100644 index 000000000..043caa363 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/format-list-ordered.png differ diff --git a/retroshare-gui/src/gui/images/textedit/format-list-unordered.png b/retroshare-gui/src/gui/images/textedit/format-list-unordered.png new file mode 100644 index 000000000..d60c0f60b Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/format-list-unordered.png differ diff --git a/retroshare-gui/src/gui/images/textedit/format-text-color.png b/retroshare-gui/src/gui/images/textedit/format-text-color.png new file mode 100644 index 000000000..98f617311 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/format-text-color.png differ diff --git a/retroshare-gui/src/gui/images/textedit/format-text-strikethrough.png b/retroshare-gui/src/gui/images/textedit/format-text-strikethrough.png new file mode 100644 index 000000000..3e25ced5c Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/format-text-strikethrough.png differ diff --git a/retroshare-gui/src/gui/images/textedit/format_font_size_less.png b/retroshare-gui/src/gui/images/textedit/format_font_size_less.png new file mode 100644 index 000000000..43ab7d23a Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/format_font_size_less.png differ diff --git a/retroshare-gui/src/gui/images/textedit/format_font_size_more.png b/retroshare-gui/src/gui/images/textedit/format_font_size_more.png new file mode 100644 index 000000000..904245147 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/format_font_size_more.png differ diff --git a/retroshare-gui/src/gui/images/textedit/hi22-action-format-text-blockquote.png b/retroshare-gui/src/gui/images/textedit/hi22-action-format-text-blockquote.png new file mode 100644 index 000000000..0306a103a Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/hi22-action-format-text-blockquote.png differ diff --git a/retroshare-gui/src/gui/images/textedit/hi22-action-format-text-code.png b/retroshare-gui/src/gui/images/textedit/hi22-action-format-text-code.png new file mode 100644 index 000000000..3cb27895c Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/hi22-action-format-text-code.png differ diff --git a/retroshare-gui/src/gui/images/textedit/hi22-action-insert-more-mark.png b/retroshare-gui/src/gui/images/textedit/hi22-action-insert-more-mark.png new file mode 100644 index 000000000..64b3b0975 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/hi22-action-insert-more-mark.png differ diff --git a/retroshare-gui/src/gui/images/textedit/textbold.png b/retroshare-gui/src/gui/images/textedit/textbold.png new file mode 100644 index 000000000..a5535e33f Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/textbold.png differ diff --git a/retroshare-gui/src/gui/images/textedit/textcenter.png b/retroshare-gui/src/gui/images/textedit/textcenter.png new file mode 100644 index 000000000..1907b44d8 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/textcenter.png differ diff --git a/retroshare-gui/src/gui/images/textedit/textitalic.png b/retroshare-gui/src/gui/images/textedit/textitalic.png new file mode 100644 index 000000000..a50211f4f Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/textitalic.png differ diff --git a/retroshare-gui/src/gui/images/textedit/textjustify.png b/retroshare-gui/src/gui/images/textedit/textjustify.png new file mode 100644 index 000000000..eddb7bfa7 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/textjustify.png differ diff --git a/retroshare-gui/src/gui/images/textedit/textleft.png b/retroshare-gui/src/gui/images/textedit/textleft.png new file mode 100644 index 000000000..37a9c5e0e Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/textleft.png differ diff --git a/retroshare-gui/src/gui/images/textedit/textright.png b/retroshare-gui/src/gui/images/textedit/textright.png new file mode 100644 index 000000000..404315b71 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/textright.png differ diff --git a/retroshare-gui/src/gui/images/textedit/textunder.png b/retroshare-gui/src/gui/images/textedit/textunder.png new file mode 100644 index 000000000..e51139505 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/textunder.png differ diff --git a/retroshare-gui/src/gui/images/textedit/zoomin.png b/retroshare-gui/src/gui/images/textedit/zoomin.png new file mode 100644 index 000000000..2e586fc7b Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/zoomin.png differ diff --git a/retroshare-gui/src/gui/images/textedit/zoomout.png b/retroshare-gui/src/gui/images/textedit/zoomout.png new file mode 100644 index 000000000..a736d3934 Binary files /dev/null and b/retroshare-gui/src/gui/images/textedit/zoomout.png differ diff --git a/retroshare-gui/src/gui/images/thumb-default-archive.png b/retroshare-gui/src/gui/images/thumb-default-archive.png new file mode 100644 index 000000000..d82190eae Binary files /dev/null and b/retroshare-gui/src/gui/images/thumb-default-archive.png differ diff --git a/retroshare-gui/src/gui/images/thumb-default-audio.png b/retroshare-gui/src/gui/images/thumb-default-audio.png new file mode 100644 index 000000000..4fb22e167 Binary files /dev/null and b/retroshare-gui/src/gui/images/thumb-default-audio.png differ diff --git a/retroshare-gui/src/gui/images/thumb-default-docs.png b/retroshare-gui/src/gui/images/thumb-default-docs.png new file mode 100644 index 000000000..4877605d2 Binary files /dev/null and b/retroshare-gui/src/gui/images/thumb-default-docs.png differ diff --git a/retroshare-gui/src/gui/images/thumb-default-images.png b/retroshare-gui/src/gui/images/thumb-default-images.png new file mode 100644 index 000000000..45cc46ce4 Binary files /dev/null and b/retroshare-gui/src/gui/images/thumb-default-images.png differ diff --git a/retroshare-gui/src/gui/images/thumb-default-iso.png b/retroshare-gui/src/gui/images/thumb-default-iso.png new file mode 100644 index 000000000..ae111df82 Binary files /dev/null and b/retroshare-gui/src/gui/images/thumb-default-iso.png differ diff --git a/retroshare-gui/src/gui/images/thumb-default-video.png b/retroshare-gui/src/gui/images/thumb-default-video.png new file mode 100644 index 000000000..f9e0c27cb Binary files /dev/null and b/retroshare-gui/src/gui/images/thumb-default-video.png differ diff --git a/retroshare-gui/src/gui/images/toaster/backgroundtoaster.png b/retroshare-gui/src/gui/images/toaster/backgroundtoaster.png new file mode 100644 index 000000000..96b7a2f5c Binary files /dev/null and b/retroshare-gui/src/gui/images/toaster/backgroundtoaster.png differ diff --git a/retroshare-gui/src/gui/images/toaster/backgroundtoasterblue.png b/retroshare-gui/src/gui/images/toaster/backgroundtoasterblue.png new file mode 100644 index 000000000..71f57408d Binary files /dev/null and b/retroshare-gui/src/gui/images/toaster/backgroundtoasterblue.png differ diff --git a/retroshare-gui/src/gui/images/toaster/chat.png b/retroshare-gui/src/gui/images/toaster/chat.png new file mode 100644 index 000000000..1dd453348 Binary files /dev/null and b/retroshare-gui/src/gui/images/toaster/chat.png differ diff --git a/retroshare-gui/src/gui/images/toaster/hangup.png b/retroshare-gui/src/gui/images/toaster/hangup.png new file mode 100644 index 000000000..2febc25be Binary files /dev/null and b/retroshare-gui/src/gui/images/toaster/hangup.png differ diff --git a/retroshare-gui/src/gui/images/toaster/pickup.png b/retroshare-gui/src/gui/images/toaster/pickup.png new file mode 100644 index 000000000..9da541978 Binary files /dev/null and b/retroshare-gui/src/gui/images/toaster/pickup.png differ diff --git a/retroshare-gui/src/gui/images/tools_wizard.png b/retroshare-gui/src/gui/images/tools_wizard.png new file mode 100644 index 000000000..9d0c70f3b Binary files /dev/null and b/retroshare-gui/src/gui/images/tools_wizard.png differ diff --git a/retroshare-gui/src/gui/images/transfers_new32.png b/retroshare-gui/src/gui/images/transfers_new32.png new file mode 100644 index 000000000..58ab91723 Binary files /dev/null and b/retroshare-gui/src/gui/images/transfers_new32.png differ diff --git a/retroshare-gui/src/gui/images/transferupdown.png b/retroshare-gui/src/gui/images/transferupdown.png new file mode 100644 index 000000000..96838be85 Binary files /dev/null and b/retroshare-gui/src/gui/images/transferupdown.png differ diff --git a/retroshare-gui/src/gui/images/trustsettings.png b/retroshare-gui/src/gui/images/trustsettings.png new file mode 100644 index 000000000..e7386a10c Binary files /dev/null and b/retroshare-gui/src/gui/images/trustsettings.png differ diff --git a/retroshare-gui/src/gui/images/tst.ico b/retroshare-gui/src/gui/images/tst.ico new file mode 100644 index 000000000..d0d18b00f Binary files /dev/null and b/retroshare-gui/src/gui/images/tst.ico differ diff --git a/retroshare-gui/src/gui/images/turtle.png b/retroshare-gui/src/gui/images/turtle.png new file mode 100644 index 000000000..84ece2205 Binary files /dev/null and b/retroshare-gui/src/gui/images/turtle.png differ diff --git a/retroshare-gui/src/gui/images/typing.png b/retroshare-gui/src/gui/images/typing.png new file mode 100644 index 000000000..28580e9a6 Binary files /dev/null and b/retroshare-gui/src/gui/images/typing.png differ diff --git a/retroshare-gui/src/gui/images/underconstruction.png b/retroshare-gui/src/gui/images/underconstruction.png new file mode 100644 index 000000000..af754a98c Binary files /dev/null and b/retroshare-gui/src/gui/images/underconstruction.png differ diff --git a/retroshare-gui/src/gui/images/up.png b/retroshare-gui/src/gui/images/up.png new file mode 100644 index 000000000..c1e63c893 Binary files /dev/null and b/retroshare-gui/src/gui/images/up.png differ diff --git a/retroshare-gui/src/gui/images/up0down0.png b/retroshare-gui/src/gui/images/up0down0.png new file mode 100644 index 000000000..a321264ac Binary files /dev/null and b/retroshare-gui/src/gui/images/up0down0.png differ diff --git a/retroshare-gui/src/gui/images/up0down1.png b/retroshare-gui/src/gui/images/up0down1.png new file mode 100644 index 000000000..08e22b97b Binary files /dev/null and b/retroshare-gui/src/gui/images/up0down1.png differ diff --git a/retroshare-gui/src/gui/images/up1down0.png b/retroshare-gui/src/gui/images/up1down0.png new file mode 100644 index 000000000..f142551c6 Binary files /dev/null and b/retroshare-gui/src/gui/images/up1down0.png differ diff --git a/retroshare-gui/src/gui/images/up1down1.png b/retroshare-gui/src/gui/images/up1down1.png new file mode 100644 index 000000000..ede925682 Binary files /dev/null and b/retroshare-gui/src/gui/images/up1down1.png differ diff --git a/retroshare-gui/src/gui/images/uploads.png b/retroshare-gui/src/gui/images/uploads.png new file mode 100644 index 000000000..c1e63c893 Binary files /dev/null and b/retroshare-gui/src/gui/images/uploads.png differ diff --git a/retroshare-gui/src/gui/images/user.png b/retroshare-gui/src/gui/images/user.png new file mode 100644 index 000000000..8b5d14cc5 Binary files /dev/null and b/retroshare-gui/src/gui/images/user.png differ diff --git a/retroshare-gui/src/gui/images/user/add_group16.png b/retroshare-gui/src/gui/images/user/add_group16.png new file mode 100644 index 000000000..1339c808c Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_group16.png differ diff --git a/retroshare-gui/src/gui/images/user/add_group22.png b/retroshare-gui/src/gui/images/user/add_group22.png new file mode 100644 index 000000000..1ebed7886 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_group22.png differ diff --git a/retroshare-gui/src/gui/images/user/add_group256.png b/retroshare-gui/src/gui/images/user/add_group256.png new file mode 100644 index 000000000..085e3502b Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_group256.png differ diff --git a/retroshare-gui/src/gui/images/user/add_group32.png b/retroshare-gui/src/gui/images/user/add_group32.png new file mode 100644 index 000000000..c319007c3 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_group32.png differ diff --git a/retroshare-gui/src/gui/images/user/add_group48.png b/retroshare-gui/src/gui/images/user/add_group48.png new file mode 100644 index 000000000..c76b2b609 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_group48.png differ diff --git a/retroshare-gui/src/gui/images/user/add_user16.png b/retroshare-gui/src/gui/images/user/add_user16.png new file mode 100644 index 000000000..6d0e97fc9 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_user16.png differ diff --git a/retroshare-gui/src/gui/images/user/add_user22.png b/retroshare-gui/src/gui/images/user/add_user22.png new file mode 100644 index 000000000..7d0f19d85 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_user22.png differ diff --git a/retroshare-gui/src/gui/images/user/add_user24.png b/retroshare-gui/src/gui/images/user/add_user24.png new file mode 100644 index 000000000..12f1a2be7 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_user24.png differ diff --git a/retroshare-gui/src/gui/images/user/add_user256.png b/retroshare-gui/src/gui/images/user/add_user256.png new file mode 100644 index 000000000..93ad22d41 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_user256.png differ diff --git a/retroshare-gui/src/gui/images/user/add_user32.png b/retroshare-gui/src/gui/images/user/add_user32.png new file mode 100644 index 000000000..29d57b4a7 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_user32.png differ diff --git a/retroshare-gui/src/gui/images/user/add_user48.png b/retroshare-gui/src/gui/images/user/add_user48.png new file mode 100644 index 000000000..d5ac0af38 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/add_user48.png differ diff --git a/retroshare-gui/src/gui/images/user/agt_forum128.png b/retroshare-gui/src/gui/images/user/agt_forum128.png new file mode 100644 index 000000000..268f52884 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/agt_forum128.png differ diff --git a/retroshare-gui/src/gui/images/user/agt_forum16.png b/retroshare-gui/src/gui/images/user/agt_forum16.png new file mode 100644 index 000000000..9083ed501 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/agt_forum16.png differ diff --git a/retroshare-gui/src/gui/images/user/agt_forum24.png b/retroshare-gui/src/gui/images/user/agt_forum24.png new file mode 100644 index 000000000..09bc3cfcb Binary files /dev/null and b/retroshare-gui/src/gui/images/user/agt_forum24.png differ diff --git a/retroshare-gui/src/gui/images/user/agt_forum32.png b/retroshare-gui/src/gui/images/user/agt_forum32.png new file mode 100644 index 000000000..37371456c Binary files /dev/null and b/retroshare-gui/src/gui/images/user/agt_forum32.png differ diff --git a/retroshare-gui/src/gui/images/user/agt_forum48 .png b/retroshare-gui/src/gui/images/user/agt_forum48 .png new file mode 100644 index 000000000..4bdf6d9c3 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/agt_forum48 .png differ diff --git a/retroshare-gui/src/gui/images/user/agt_forum64.png b/retroshare-gui/src/gui/images/user/agt_forum64.png new file mode 100644 index 000000000..40d133b37 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/agt_forum64.png differ diff --git a/retroshare-gui/src/gui/images/user/delete_group16.png b/retroshare-gui/src/gui/images/user/delete_group16.png new file mode 100644 index 000000000..913d2ad6f Binary files /dev/null and b/retroshare-gui/src/gui/images/user/delete_group16.png differ diff --git a/retroshare-gui/src/gui/images/user/delete_user16.png b/retroshare-gui/src/gui/images/user/delete_user16.png new file mode 100644 index 000000000..7780da33b Binary files /dev/null and b/retroshare-gui/src/gui/images/user/delete_user16.png differ diff --git a/retroshare-gui/src/gui/images/user/deny_user48.png b/retroshare-gui/src/gui/images/user/deny_user48.png new file mode 100644 index 000000000..858c10a34 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/deny_user48.png differ diff --git a/retroshare-gui/src/gui/images/user/friends128.png b/retroshare-gui/src/gui/images/user/friends128.png new file mode 100644 index 000000000..2911ac478 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/friends128.png differ diff --git a/retroshare-gui/src/gui/images/user/friends24.png b/retroshare-gui/src/gui/images/user/friends24.png new file mode 100644 index 000000000..1e734ea8e Binary files /dev/null and b/retroshare-gui/src/gui/images/user/friends24.png differ diff --git a/retroshare-gui/src/gui/images/user/friends32.png b/retroshare-gui/src/gui/images/user/friends32.png new file mode 100644 index 000000000..558f316bd Binary files /dev/null and b/retroshare-gui/src/gui/images/user/friends32.png differ diff --git a/retroshare-gui/src/gui/images/user/friends48.png b/retroshare-gui/src/gui/images/user/friends48.png new file mode 100644 index 000000000..ff21d328a Binary files /dev/null and b/retroshare-gui/src/gui/images/user/friends48.png differ diff --git a/retroshare-gui/src/gui/images/user/friends64.png b/retroshare-gui/src/gui/images/user/friends64.png new file mode 100644 index 000000000..6c0cfa418 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/friends64.png differ diff --git a/retroshare-gui/src/gui/images/user/group16.png b/retroshare-gui/src/gui/images/user/group16.png new file mode 100644 index 000000000..4e8a1d7b5 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/group16.png differ diff --git a/retroshare-gui/src/gui/images/user/group24.png b/retroshare-gui/src/gui/images/user/group24.png new file mode 100644 index 000000000..b7274e8dc Binary files /dev/null and b/retroshare-gui/src/gui/images/user/group24.png differ diff --git a/retroshare-gui/src/gui/images/user/identity16.png b/retroshare-gui/src/gui/images/user/identity16.png new file mode 100644 index 000000000..997b0a937 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identity16.png differ diff --git a/retroshare-gui/src/gui/images/user/identity24.png b/retroshare-gui/src/gui/images/user/identity24.png new file mode 100644 index 000000000..0f5315239 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identity24.png differ diff --git a/retroshare-gui/src/gui/images/user/identity24away.png b/retroshare-gui/src/gui/images/user/identity24away.png new file mode 100644 index 000000000..a36d4d023 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identity24away.png differ diff --git a/retroshare-gui/src/gui/images/user/identity24busy.png b/retroshare-gui/src/gui/images/user/identity24busy.png new file mode 100644 index 000000000..6e51d30cc Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identity24busy.png differ diff --git a/retroshare-gui/src/gui/images/user/identity24idle.png b/retroshare-gui/src/gui/images/user/identity24idle.png new file mode 100644 index 000000000..c743cda36 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identity24idle.png differ diff --git a/retroshare-gui/src/gui/images/user/identity32.png b/retroshare-gui/src/gui/images/user/identity32.png new file mode 100644 index 000000000..c28066af6 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identity32.png differ diff --git a/retroshare-gui/src/gui/images/user/identity48.png b/retroshare-gui/src/gui/images/user/identity48.png new file mode 100644 index 000000000..086146d19 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identity48.png differ diff --git a/retroshare-gui/src/gui/images/user/identityavaible24.png b/retroshare-gui/src/gui/images/user/identityavaible24.png new file mode 100644 index 000000000..a84f22d31 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identityavaible24.png differ diff --git a/retroshare-gui/src/gui/images/user/identityavaiblecyan24.png b/retroshare-gui/src/gui/images/user/identityavaiblecyan24.png new file mode 100644 index 000000000..f34baab28 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identityavaiblecyan24.png differ diff --git a/retroshare-gui/src/gui/images/user/identitygray16.png b/retroshare-gui/src/gui/images/user/identitygray16.png new file mode 100644 index 000000000..8f701dd1e Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identitygray16.png differ diff --git a/retroshare-gui/src/gui/images/user/identityoffline24.png b/retroshare-gui/src/gui/images/user/identityoffline24.png new file mode 100644 index 000000000..3dc3ef155 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/identityoffline24.png differ diff --git a/retroshare-gui/src/gui/images/user/kuser24.png b/retroshare-gui/src/gui/images/user/kuser24.png new file mode 100644 index 000000000..06ae9ba7c Binary files /dev/null and b/retroshare-gui/src/gui/images/user/kuser24.png differ diff --git a/retroshare-gui/src/gui/images/user/kuser32.png b/retroshare-gui/src/gui/images/user/kuser32.png new file mode 100644 index 000000000..75fd223f4 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/kuser32.png differ diff --git a/retroshare-gui/src/gui/images/user/kuser48.png b/retroshare-gui/src/gui/images/user/kuser48.png new file mode 100644 index 000000000..79f96b8dd Binary files /dev/null and b/retroshare-gui/src/gui/images/user/kuser48.png differ diff --git a/retroshare-gui/src/gui/images/user/personal128.png b/retroshare-gui/src/gui/images/user/personal128.png new file mode 100644 index 000000000..feb636e39 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/personal128.png differ diff --git a/retroshare-gui/src/gui/images/user/personal24.png b/retroshare-gui/src/gui/images/user/personal24.png new file mode 100644 index 000000000..6304b1a1f Binary files /dev/null and b/retroshare-gui/src/gui/images/user/personal24.png differ diff --git a/retroshare-gui/src/gui/images/user/personal32.png b/retroshare-gui/src/gui/images/user/personal32.png new file mode 100644 index 000000000..48f6eb2f3 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/personal32.png differ diff --git a/retroshare-gui/src/gui/images/user/personal64.png b/retroshare-gui/src/gui/images/user/personal64.png new file mode 100755 index 000000000..00b640003 Binary files /dev/null and b/retroshare-gui/src/gui/images/user/personal64.png differ diff --git a/retroshare-gui/src/gui/images/video-x-generic.png b/retroshare-gui/src/gui/images/video-x-generic.png new file mode 100644 index 000000000..28f9700f4 Binary files /dev/null and b/retroshare-gui/src/gui/images/video-x-generic.png differ diff --git a/retroshare-gui/src/gui/images/view-certificate-copy-32.png b/retroshare-gui/src/gui/images/view-certificate-copy-32.png new file mode 100644 index 000000000..c5bea2449 Binary files /dev/null and b/retroshare-gui/src/gui/images/view-certificate-copy-32.png differ diff --git a/retroshare-gui/src/gui/images/view-certificate-export-32.png b/retroshare-gui/src/gui/images/view-certificate-export-32.png new file mode 100644 index 000000000..f4075b9d6 Binary files /dev/null and b/retroshare-gui/src/gui/images/view-certificate-export-32.png differ diff --git a/retroshare-gui/src/gui/images/view-certificate-sign-32.png b/retroshare-gui/src/gui/images/view-certificate-sign-32.png new file mode 100644 index 000000000..1ea763f14 Binary files /dev/null and b/retroshare-gui/src/gui/images/view-certificate-sign-32.png differ diff --git a/retroshare-gui/src/gui/images/view-certificate-sign-48.png b/retroshare-gui/src/gui/images/view-certificate-sign-48.png new file mode 100644 index 000000000..012e8aea8 Binary files /dev/null and b/retroshare-gui/src/gui/images/view-certificate-sign-48.png differ diff --git a/retroshare-gui/src/gui/images/view_calendar_day.png b/retroshare-gui/src/gui/images/view_calendar_day.png new file mode 100644 index 000000000..a32fbb723 Binary files /dev/null and b/retroshare-gui/src/gui/images/view_calendar_day.png differ diff --git a/retroshare-gui/src/gui/images/view_calendar_list.png b/retroshare-gui/src/gui/images/view_calendar_list.png new file mode 100644 index 000000000..f41b620b3 Binary files /dev/null and b/retroshare-gui/src/gui/images/view_calendar_list.png differ diff --git a/retroshare-gui/src/gui/images/view_calendar_month.png b/retroshare-gui/src/gui/images/view_calendar_month.png new file mode 100644 index 000000000..e90194dcc Binary files /dev/null and b/retroshare-gui/src/gui/images/view_calendar_month.png differ diff --git a/retroshare-gui/src/gui/images/view_calendar_week.png b/retroshare-gui/src/gui/images/view_calendar_week.png new file mode 100644 index 000000000..eb12f42d8 Binary files /dev/null and b/retroshare-gui/src/gui/images/view_calendar_week.png differ diff --git a/retroshare-gui/src/gui/images/view_split_top_bottom.png b/retroshare-gui/src/gui/images/view_split_top_bottom.png new file mode 100644 index 000000000..8c0e4db56 Binary files /dev/null and b/retroshare-gui/src/gui/images/view_split_top_bottom.png differ diff --git a/retroshare-gui/src/gui/images/warning_16x16.png b/retroshare-gui/src/gui/images/warning_16x16.png new file mode 100644 index 000000000..56ad042e5 Binary files /dev/null and b/retroshare-gui/src/gui/images/warning_16x16.png differ diff --git a/retroshare-gui/src/gui/images/window_fullscreen.png b/retroshare-gui/src/gui/images/window_fullscreen.png new file mode 100644 index 000000000..18a00007a Binary files /dev/null and b/retroshare-gui/src/gui/images/window_fullscreen.png differ diff --git a/retroshare-gui/src/gui/images/window_nofullscreen.png b/retroshare-gui/src/gui/images/window_nofullscreen.png new file mode 100644 index 000000000..bfd4fa597 Binary files /dev/null and b/retroshare-gui/src/gui/images/window_nofullscreen.png differ diff --git a/retroshare-gui/src/gui/images/yellowled.png b/retroshare-gui/src/gui/images/yellowled.png new file mode 100644 index 000000000..c6103e5df Binary files /dev/null and b/retroshare-gui/src/gui/images/yellowled.png differ diff --git a/retroshare-gui/src/gui/layouts/default.ui b/retroshare-gui/src/gui/layouts/default.ui new file mode 100644 index 000000000..9667e9929 --- /dev/null +++ b/retroshare-gui/src/gui/layouts/default.ui @@ -0,0 +1,1039 @@ + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 10 + 36 + 106 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 212 + 208 + 200 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 120 + 120 + 120 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 139 + 139 + 139 + + + + + + + 120 + 120 + 120 + + + + + + + 255 + 255 + 255 + + + + + + + 120 + 120 + 120 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 10 + 36 + 106 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + Arial + 10 + 50 + false + false + false + false + + + + Qt::CustomContextMenu + + + RetroShare + + + :/images/RShare32.png + + + + 32 + 32 + + + + Qt::ToolButtonTextUnderIcon + + + + + 2 + + + 2 + + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 160 + 160 + 160 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 10 + 36 + 106 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 160 + 160 + 160 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 212 + 208 + 200 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 120 + 120 + 120 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 160 + 160 + 160 + + + + + + + 120 + 120 + 120 + + + + + + + 255 + 255 + 255 + + + + + + + 120 + 120 + 120 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 10 + 36 + 106 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + Qt::NoContextMenu + + + + + 0 + 0 + 100 + 30 + + + + + + + + + + + Qt::NoContextMenu + + + true + + + Qt::Horizontal + + + + 24 + 24 + + + + 4 + + + + + + MainPageStack + QStackedPageWidget +
    gui/mainpagestack.h
    +
    +
    + + + + +
    diff --git a/retroshare-gui/src/gui/linetypes.h b/retroshare-gui/src/gui/linetypes.h new file mode 100644 index 000000000..5d128db36 --- /dev/null +++ b/retroshare-gui/src/gui/linetypes.h @@ -0,0 +1,26 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + + +#define BWGRAPH_SEND (1u<<0) +#define BWGRAPH_REC (1u<<1) diff --git a/retroshare-gui/src/gui/mainpage.h b/retroshare-gui/src/gui/mainpage.h new file mode 100644 index 000000000..7a966a5b5 --- /dev/null +++ b/retroshare-gui/src/gui/mainpage.h @@ -0,0 +1,39 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _MAINPAGE_H +#define _MAINPAGE_H + +#include + + +class MainPage : public QWidget +{ +public: + /** Default Constructor */ + MainPage(QWidget *parent = 0) : QWidget(parent) {} + + virtual void retranslateUi() {} +}; + +#endif + diff --git a/retroshare-gui/src/gui/mainpagestack.cpp b/retroshare-gui/src/gui/mainpagestack.cpp new file mode 100644 index 000000000..778a446ac --- /dev/null +++ b/retroshare-gui/src/gui/mainpagestack.cpp @@ -0,0 +1,63 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include "mainpagestack.h" + +/** Default constructor. */ +MainPageStack::MainPageStack(QWidget *parent) +: QStackedWidget(parent) +{ +} + +/** Adds a page to the stack. */ +void +MainPageStack::add(MainPage *page, QAction *action) +{ + _pages.insert(action, page); + insertWidget(count(), page); +} + +/** Sets the current Main page and checks its action. */ +void +MainPageStack::setCurrentPage(MainPage *page) +{ + foreach (QAction *action, _pages.keys(page)) { + action->setChecked(true); + } + setCurrentWidget(page); +} + +/** Sets the current Main page index and checks its action. */ +void +MainPageStack::setCurrentIndex(int index) +{ + setCurrentPage((MainPage *)widget(index)); +} + +/** Shows the Main page associated with the activated action. */ +void +MainPageStack::showPage(QAction *pageAction) +{ + setCurrentWidget(_pages.value(pageAction)); +} + diff --git a/retroshare-gui/src/gui/mainpagestack.h b/retroshare-gui/src/gui/mainpagestack.h new file mode 100644 index 000000000..f8e9949da --- /dev/null +++ b/retroshare-gui/src/gui/mainpagestack.h @@ -0,0 +1,60 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _MAINPAGESTACK_H +#define _MAINPAGESTACK_H + +#include +#include + +#include "mainpage.h" + + +class MainPageStack : public QStackedWidget +{ + Q_OBJECT + +public: + /** Constructor. */ + MainPageStack(QWidget *parent = 0); + + /** Adds a Mainuration page to the stack. */ + void add(MainPage *page, QAction *action); + /** Sets the current Main page and checks its action. */ + void setCurrentPage(MainPage *page); + /** Sets the current Main page index and checks its action. */ + void setCurrentIndex(int index); + + /** Returns a list of all pages in the stack. */ + QList pages() { return _pages.values(); } + +public slots: + /** Displays the page associated with the activated action. */ + void showPage(QAction *pageAction); + +private: + /** Maps an action to a Main page. */ + QHash _pages; +}; + +#endif + diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.cpp b/retroshare-gui/src/gui/msgs/MessageComposer.cpp new file mode 100644 index 000000000..e028d0276 --- /dev/null +++ b/retroshare-gui/src/gui/msgs/MessageComposer.cpp @@ -0,0 +1,2617 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rshare.h" +#include "MessageComposer.h" + +#include +#include +#include +#include + +#include "gui/notifyqt.h" +#include "gui/common/RSTreeWidgetItem.h" +#include "gui/common/GroupDefs.h" +#include "gui/common/StatusDefs.h" +#include "gui/common/PeerDefs.h" +#include "gui/RetroShareLink.h" +#include "gui/settings/rsharesettings.h" +#include "gui/feeds/AttachFileItem.h" +#include "gui/common/Emoticons.h" +#include "textformat.h" +#include "util/misc.h" +#include "TagsMenu.h" +#include "gui/common/TagDefs.h" +#include "gui/connect/ConfCertDialog.h" + +#define IMAGE_GROUP16 ":/images/user/group16.png" +#define IMAGE_FRIENDINFO ":/images/peerdetails_16x16.png" + +#define COLUMN_CONTACT_NAME 0 +#define COLUMN_CONTACT_DATA 0 + +#define ROLE_CONTACT_ID Qt::UserRole +#define ROLE_CONTACT_SORT Qt::UserRole + 1 + +#define COLOR_CONNECT Qt::blue + +#define TYPE_GROUP 0 +#define TYPE_SSL 1 + +#define COLUMN_RECIPIENT_TYPE 0 +#define COLUMN_RECIPIENT_ICON 1 +#define COLUMN_RECIPIENT_NAME 2 +#define COLUMN_RECIPIENT_COUNT 3 +#define COLUMN_RECIPIENT_DATA COLUMN_RECIPIENT_ICON // the column with a QTableWidgetItem + +#define ROLE_RECIPIENT_ID Qt::UserRole +#define ROLE_RECIPIENT_GROUP Qt::UserRole + 1 + +#define COLUMN_FILE_CHECKED 0 +#define COLUMN_FILE_NAME 0 +#define COLUMN_FILE_SIZE 1 +#define COLUMN_FILE_HASH 2 +#define COLUMN_FILE_COUNT 3 + +#define STYLE_NORMAL "QLineEdit#%1 { border : none; }" +#define STYLE_FAIL "QLineEdit#%1 { border : none; color : red; }" + +class MessageItemDelegate : public QItemDelegate +{ +public: + MessageItemDelegate(QObject *parent = 0) : QItemDelegate(parent) + { + } + + void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const + { + QStyleOptionViewItem ownOption (option); + + ownOption.state |= QStyle::State_Enabled; // the item is disabled to get no focus, but draw the icon as enabled (no grayscale) + + QItemDelegate::paint (painter, ownOption, index); + } +}; + +/** Constructor */ +MessageComposer::MessageComposer(QWidget *parent, Qt::WFlags flags) +: QMainWindow(parent, flags), mCheckAttachment(true) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + m_msgType = NORMAL; + + setupFileActions(); + setupEditActions(); + setupViewActions(); + setupInsertActions(); + + m_compareRole = new RSTreeWidgetItemCompareRole; + m_compareRole->setRole(COLUMN_CONTACT_NAME, ROLE_CONTACT_SORT); + + m_completer = NULL; + + Settings->loadWidgetInformation(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + ui.hashBox->hide(); + + // connect up the buttons. + connect( ui.actionSend, SIGNAL( triggered (bool)), this, SLOT( sendMessage( ) ) ); + //connect( ui.actionReply, SIGNAL( triggered (bool)), this, SLOT( replyMessage( ) ) ); + connect(ui.boldbtn, SIGNAL(clicked()), this, SLOT(textBold())); + connect(ui.underlinebtn, SIGNAL(clicked()), this, SLOT(textUnderline())); + connect(ui.italicbtn, SIGNAL(clicked()), this, SLOT(textItalic())); + connect(ui.colorbtn, SIGNAL(clicked()), this, SLOT(textColor())); + connect(ui.imagebtn, SIGNAL(clicked()), this, SLOT(addImage())); + connect(ui.emoticonButton, SIGNAL(clicked()), this, SLOT(smileyWidget())); + //connect(ui.linkbtn, SIGNAL(clicked()), this, SLOT(insertLink())); + connect(ui.actionContactsView, SIGNAL(triggered()), this, SLOT(toggleContacts())); + connect(ui.actionSaveas, SIGNAL(triggered()), this, SLOT(saveasDraft())); + connect(ui.actionAttach, SIGNAL(triggered()), this, SLOT(attachFile())); + connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged())); + connect(ui.clearButton, SIGNAL(clicked()), this, SLOT(clearFilter())); + connect(ui.titleEdit, SIGNAL(textChanged(const QString &)), this, SLOT(titleChanged())); + + connect(ui.sizeincreaseButton, SIGNAL (clicked()), this, SLOT (fontSizeIncrease())); + connect(ui.sizedecreaseButton, SIGNAL (clicked()), this, SLOT (fontSizeDecrease())); + connect(ui.actionQuote, SIGNAL(triggered()), this, SLOT(blockQuote())); + connect(ui.codeButton, SIGNAL (clicked()), this, SLOT (toggleCode())); + + connect(ui.msgText, SIGNAL( checkSpellingChanged( bool ) ), this, SLOT( spellChecking( bool ) ) ); + + connect(ui.msgText, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)), this, SLOT(currentCharFormatChanged(const QTextCharFormat &))); + connect(ui.msgText, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged())); + connect(ui.msgText,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenu(QPoint))); + + connect(ui.msgText->document(), SIGNAL(modificationChanged(bool)), actionSave, SLOT(setEnabled(bool))); + connect(ui.msgText->document(), SIGNAL(modificationChanged(bool)), this, SLOT(setWindowModified(bool))); + connect(ui.msgText->document(), SIGNAL(undoAvailable(bool)), actionUndo, SLOT(setEnabled(bool))); + connect(ui.msgText->document(), SIGNAL(redoAvailable(bool)), actionRedo, SLOT(setEnabled(bool))); + + connect(ui.msgFileList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuFileList(QPoint))); + connect(ui.msgSendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuMsgSendList(QPoint))); + + setWindowModified(ui.msgText->document()->isModified()); + actionSave->setEnabled(ui.msgText->document()->isModified()); + actionUndo->setEnabled(ui.msgText->document()->isUndoAvailable()); + actionRedo->setEnabled(ui.msgText->document()->isRedoAvailable()); + + connect(actionUndo, SIGNAL(triggered()), ui.msgText, SLOT(undo())); + connect(actionRedo, SIGNAL(triggered()), ui.msgText, SLOT(redo())); + + actionCut->setEnabled(false); + actionCopy->setEnabled(false); + + connect(actionCut, SIGNAL(triggered()), ui.msgText, SLOT(cut())); + connect(actionCopy, SIGNAL(triggered()), ui.msgText, SLOT(copy())); + connect(actionPaste, SIGNAL(triggered()), ui.msgText, SLOT(paste())); + + connect(ui.msgText, SIGNAL(copyAvailable(bool)), actionCut, SLOT(setEnabled(bool))); + connect(ui.msgText, SIGNAL(copyAvailable(bool)), actionCopy, SLOT(setEnabled(bool))); + + connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged())); + + connect(ui.addToButton, SIGNAL(clicked(void)), this, SLOT(addTo())); + connect(ui.addCcButton, SIGNAL(clicked(void)), this, SLOT(addCc())); + connect(ui.addBccButton, SIGNAL(clicked(void)), this, SLOT(addBcc())); + connect(ui.addRecommendButton, SIGNAL(clicked(void)), this, SLOT(addRecommend())); + connect(ui.msgSendList, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(addTo())); + + connect(NotifyQt::getInstance(), SIGNAL(groupsChanged(int)), this, SLOT(groupsChanged(int))); + connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(const QString&,int)), this, SLOT(peerStatusChanged(const QString&,int))); + + /* hide the Tree +/- */ + ui.msgFileList -> setRootIsDecorated( false ); + + /* to hide the header */ + //ui.msgSendList->header()->hide(); + + /* sort send list by name ascending */ + ui.msgSendList->sortItems(0, Qt::AscendingOrder); + + QActionGroup *grp = new QActionGroup(this); + connect(grp, SIGNAL(triggered(QAction *)), this, SLOT(textAlign(QAction *))); + + actionAlignLeft = new QAction(QIcon(":/images/textedit/textleft.png"), tr("&Left"), grp); + actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L); + actionAlignLeft->setCheckable(true); + actionAlignCenter = new QAction(QIcon(":/images/textedit/textcenter.png"), tr("C&enter"), grp); + actionAlignCenter->setShortcut(Qt::CTRL + Qt::Key_E); + actionAlignCenter->setCheckable(true); + actionAlignRight = new QAction(QIcon(":/images/textedit/textright.png"), tr("&Right"), grp); + actionAlignRight->setShortcut(Qt::CTRL + Qt::Key_R); + actionAlignRight->setCheckable(true); + actionAlignJustify = new QAction(QIcon(":/images/textedit/textjustify.png"), tr("&Justify"), grp); + actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J); + actionAlignJustify->setCheckable(true); + + setupFormatActions(); + + /*ui.comboStyle->addItem("Standard"); + ui.comboStyle->addItem("Bullet List (Disc)"); + ui.comboStyle->addItem("Bullet List (Circle)"); + ui.comboStyle->addItem("Bullet List (Square)"); + ui.comboStyle->addItem("Ordered List (Decimal)"); + ui.comboStyle->addItem("Ordered List (Alpha lower)"); + ui.comboStyle->addItem("Ordered List (Alpha upper)");*/ + //connect(ui.comboStyle, SIGNAL(activated(int)),this, SLOT(textStyle(int))); + connect(ui.comboStyle, SIGNAL(activated(int)),this, SLOT(changeFormatType(int))); + + connect(ui.comboFont, SIGNAL(activated(const QString &)), this, SLOT(textFamily(const QString &))); + + ui.comboSize->setEditable(true); + + QFontDatabase db; + foreach(int size, db.standardSizes()) + ui.comboSize->addItem(QString::number(size)); + + connect(ui.comboSize, SIGNAL(activated(const QString &)),this, SLOT(textSize(const QString &))); + ui.comboSize->setCurrentIndex(ui.comboSize->findText(QString::number(QApplication::font().pointSize()))); + + ui.textalignmentbtn->setIcon(QIcon(QString(":/images/textedit/textcenter.png"))); + + QMenu * alignmentmenu = new QMenu(); + alignmentmenu->addAction(actionAlignLeft); + alignmentmenu->addAction(actionAlignCenter); + alignmentmenu->addAction(actionAlignRight); + alignmentmenu->addAction(actionAlignJustify); + ui.textalignmentbtn->setMenu(alignmentmenu); + + QPixmap pxm(24,24); + pxm.fill(Qt::black); + ui.colorbtn->setIcon(pxm); + + /* Set header resize modes and initial section sizes */ + QHeaderView * _smheader = ui.msgFileList->header () ; + + _smheader->resizeSection(COLUMN_FILE_NAME, 200); + _smheader->resizeSection(COLUMN_FILE_SIZE, 60); + _smheader->resizeSection(COLUMN_FILE_HASH, 220); + + QPalette palette = QApplication::palette(); + codeBackground = palette.color( QPalette::Active, QPalette::Midlight ); + + ui.clearButton->hide(); + + ui.recipientWidget->setColumnCount(COLUMN_RECIPIENT_COUNT); + + QHeaderView *header = ui.recipientWidget->horizontalHeader(); + header->resizeSection(COLUMN_RECIPIENT_TYPE, 50); + header->resizeSection(COLUMN_RECIPIENT_ICON, 22); + header->setResizeMode(COLUMN_RECIPIENT_TYPE, QHeaderView::Fixed); + header->setResizeMode(COLUMN_RECIPIENT_ICON, QHeaderView::Fixed); + header->setResizeMode(COLUMN_RECIPIENT_NAME, QHeaderView::Interactive); + header->setStretchLastSection(true); + + /* Set own item delegate */ + QItemDelegate *delegate = new MessageItemDelegate(this); + ui.recipientWidget->setItemDelegateForColumn(COLUMN_RECIPIENT_ICON, delegate); + + addEmptyRecipient(); + + // load settings + processSettings(true); + + /* worker fns */ + insertSendList(); + + /* set focus to subject */ + ui.titleEdit->setFocus(); + + // create tag menu + TagsMenu *menu = new TagsMenu (tr("Tags"), this); + connect(menu, SIGNAL(aboutToShow()), this, SLOT(tagAboutToShow())); + connect(menu, SIGNAL(tagSet(int, bool)), this, SLOT(tagSet(int, bool))); + connect(menu, SIGNAL(tagRemoveAll()), this, SLOT(tagRemoveAll())); + + ui.tagButton->setMenu(menu); + + setAcceptDrops(true); + +#ifdef RS_RELEASE_VERSION + ui.imagebtn->setVisible(false); + ui.imagebtn->setVisible(false); +#endif + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +MessageComposer::~MessageComposer() +{ + delete(m_compareRole); +} + +void MessageComposer::processSettings(bool bLoad) +{ + Settings->beginGroup(QString("MessageComposer")); + + if (bLoad) { + // load settings + + // state of contact sidebar + ui.contactsdockWidget->setVisible(Settings->value("ContactSidebar", true).toBool()); + + // state of splitter + ui.splitter->restoreState(Settings->value("Splitter").toByteArray()); + ui.splitter_2->restoreState(Settings->value("Splitter2").toByteArray()); + } else { + // save settings + + // state of contact sidebar + Settings->setValue("ContactSidebar", ui.contactsdockWidget->isVisible()); + + // state of splitter + Settings->setValue("Splitter", ui.splitter->saveState()); + Settings->setValue("Splitter2", ui.splitter_2->saveState()); + } + + Settings->endGroup(); +} + +/*static*/ void MessageComposer::msgFriend(std::string id, bool group) +{ +// std::cerr << "MessageComposer::msgfriend()" << std::endl; + + /* create a message */ + + MessageComposer *pMsgDialog = MessageComposer::newMsg(); + if (pMsgDialog == NULL) { + return; + } + + if (group) { + pMsgDialog->addRecipient(TO, id, true); + } else { + RsPeerDetails detail; + if (rsPeers->getPeerDetails(id, detail) && detail.accept_connection) { + if (detail.isOnlyGPGdetail) { + //put all sslChilds in message list + std::list sslIds; + rsPeers->getSSLChildListOfGPGId(id, sslIds); + + std::list::const_iterator it; + for (it = sslIds.begin(); it != sslIds.end(); it++) { + pMsgDialog->addRecipient(TO, *it, false); + } + } else { + pMsgDialog->addRecipient(TO, detail.id, false); + } + } + } + + pMsgDialog->show(); + + /* window will destroy itself! */ +} + +static QString BuildRecommendHtml(std::list &peerids) +{ + QString text; + + /* process peer ids */ + std::list ::iterator peerid; + for (peerid = peerids.begin(); peerid != peerids.end(); peerid++) { + RetroShareLink link; + if (link.createPerson(*peerid)) { + text += link.toHtml() + "
    "; + } + } + + return text; +} + +void MessageComposer::recommendFriend(std::list &peerids) +{ +// std::cerr << "MessageComposer::recommendFriend()" << std::endl; + + if (peerids.size() == 0) { + return; + } + + /* create a message */ + MessageComposer *pMsgDialog = MessageComposer::newMsg(); + + pMsgDialog->insertTitleText(tr("Friend Recommendation(s)")); + + QString sMsgText = tr("I recommend a good friend of me, you can trust him too when you trust me.
    Copy friend link and paste to Friends list"); + sMsgText += "

    "; + sMsgText += BuildRecommendHtml(peerids); + pMsgDialog->insertMsgText(sMsgText); + + std::list ::iterator peerIt; + for (peerIt = peerids.begin(); peerIt != peerids.end(); peerIt++) { + pMsgDialog->addRecipient(CC, *peerIt, false); + } + + pMsgDialog->show(); + + /* window will destroy itself! */ +} + +void MessageComposer::closeEvent (QCloseEvent * event) +{ + bool bClose = true; + + /* Save to Drafts? */ + + if (ui.msgText->document()->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("Save Message"), + tr("Message has not been Sent.\n" + "Do you want to save message to draft box?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + switch (ret) { + case QMessageBox::Yes: + sendMessage_internal(true); + break; + case QMessageBox::Cancel: + bClose = false; + break; + default: + break; + } + } + + if (bClose) { + Settings->saveWidgetInformation(this); + + // save settings + processSettings(false); + + QMainWindow::closeEvent(event); + } else { + event->ignore(); + } +} + +void MessageComposer::contextMenu(QPoint) +{ + QMenu *contextMnu = ui.msgText->createStandardContextMenu(); + + contextMnu->addSeparator(); + QAction *action = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink())); + action->setDisabled(RSLinkClipboard::empty()); + + contextMnu->exec(QCursor::pos()); + delete(contextMnu); +} + +void MessageComposer::pasteLink() +{ + ui.msgText->insertHtml(RSLinkClipboard::toHtml()) ; +} + +void MessageComposer::contextMenuFileList(QPoint) +{ + QMenu contextMnu(this); + + QAction *action = contextMnu.addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteRecommended())); + action->setDisabled(RSLinkClipboard::empty(RetroShareLink::TYPE_FILE)); + + contextMnu.exec(QCursor::pos()); +} + +void MessageComposer::contextMenuMsgSendList(QPoint) +{ + QMenu contextMnu(this); + + int selectedCount = ui.msgSendList->selectedItems().count(); + + QAction *action = contextMnu.addAction(QIcon(), tr("Add to \"To\""), this, SLOT(addTo())); + action->setEnabled(selectedCount); + action = contextMnu.addAction(QIcon(), tr("Add to \"CC\""), this, SLOT(addCc())); + action->setEnabled(selectedCount); + action = contextMnu.addAction(QIcon(), tr("Add to \"BCC\""), this, SLOT(addBcc())); + action->setEnabled(selectedCount); + action = contextMnu.addAction(QIcon(), tr("Add as Recommend"), this, SLOT(addRecommend())); + action->setEnabled(selectedCount); + + contextMnu.addSeparator(); + + action = contextMnu.addAction(QIcon(IMAGE_FRIENDINFO), tr("Friend Details"), this, SLOT(friendDetails())); + action->setEnabled(selectedCount == 1); + + contextMnu.exec(QCursor::pos()); +} + +void MessageComposer::pasteRecommended() +{ + std::vector links; + RSLinkClipboard::pasteLinks(links); + + for (uint32_t i = 0; i < links.size(); i++) { + if (links[i].valid() && links[i].type() == RetroShareLink::TYPE_FILE) { + FileInfo fileInfo; + fileInfo.fname = links[i].name().toStdString(); + fileInfo.hash = links[i].hash().toStdString(); + fileInfo.size = links[i].size(); + + addFile(fileInfo); + } + } +} + +static void setNewCompleter(QTableWidget *tableWidget, QCompleter *completer) +{ + int rowCount = tableWidget->rowCount(); + int row; + + for (row = 0; row < rowCount; row++) { + QLineEdit *lineEdit = dynamic_cast(tableWidget->cellWidget(row, COLUMN_RECIPIENT_NAME)); + if (lineEdit) { + lineEdit->setCompleter(completer); + } + } +} + +void MessageComposer::insertSendList() +{ + /* get a link to the table */ + QTreeWidget *sendWidget = ui.msgSendList; + + /* remove old items */ + sendWidget->clear(); + sendWidget->setColumnCount(1); + + setNewCompleter(ui.recipientWidget, NULL); + if (m_completer) { + delete(m_completer); + m_completer = NULL; + } + + if (!rsPeers) + { + /* not ready yet! */ + return; + } + + // get existing groups + std::list groupInfoList; + std::list::iterator groupIt; + rsPeers->getGroupInfoList(groupInfoList); + + std::list peers; + std::list::iterator peerIt; + rsPeers->getFriendList(peers); + + std::list statusInfo; + rsStatus->getStatusList(statusInfo); + + std::list fillPeerIds; + + // start with groups + groupIt = groupInfoList.begin(); + while (true) { + QTreeWidgetItem *groupItem = NULL; + RsGroupInfo *groupInfo = NULL; + + if (groupIt != groupInfoList.end()) { + groupInfo = &(*groupIt); + + if (groupInfo->peerIds.size() == 0) { + // don't show empty groups + groupIt++; + continue; + } + + // add group item + groupItem = new RSTreeWidgetItem(m_compareRole, TYPE_GROUP); + + // Add item to the list + sendWidget->addTopLevelItem(groupItem); + + groupItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless); +// groupItem->setSizeHint(COLUMN_NAME, QSize(26, 26)); + groupItem->setTextAlignment(COLUMN_CONTACT_NAME, Qt::AlignLeft | Qt::AlignVCenter); + groupItem->setIcon(COLUMN_CONTACT_NAME, QIcon(IMAGE_GROUP16)); + + /* used to find back the item */ + groupItem->setData(COLUMN_CONTACT_DATA, ROLE_CONTACT_ID, QString::fromStdString(groupInfo->id)); + + groupItem->setExpanded(true); + + QString groupName = GroupDefs::name(*groupInfo); + groupItem->setText(COLUMN_CONTACT_NAME, groupName); + groupItem->setData(COLUMN_CONTACT_DATA, ROLE_CONTACT_SORT, ((groupInfo->flag & RS_GROUP_FLAG_STANDARD) ? "0 " : "1 ") + groupName); + } + + // iterate through peers + for (peerIt = peers.begin(); peerIt != peers.end(); peerIt++) { + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(*peerIt, detail)) { + continue; /* BAD */ + } + + if (groupInfo) { + // we fill a group, check if gpg id is assigned + if (std::find(groupInfo->peerIds.begin(), groupInfo->peerIds.end(), detail.gpg_id) == groupInfo->peerIds.end()) { + continue; + } + } else { + // we fill the not assigned gpg ids + if (std::find(fillPeerIds.begin(), fillPeerIds.end(), *peerIt) != fillPeerIds.end()) { + continue; + } + } + + // add equal too, its no problem + fillPeerIds.push_back(detail.id); + + /* make a widget per friend */ + QTreeWidgetItem *item = new RSTreeWidgetItem(m_compareRole, TYPE_SSL); + + /* add all the labels */ + /* (0) Person */ + QString name = PeerDefs::nameWithLocation(detail); + item->setText(COLUMN_CONTACT_NAME, name); + + int state = RS_STATUS_OFFLINE; + if (detail.state & RS_PEER_STATE_CONNECTED) { + std::list::iterator it; + for (it = statusInfo.begin(); it != statusInfo.end() ; it++) { + if (it->id == detail.id) { + state = it->status; + break; + } + } + } + + if (state != (int) RS_STATUS_OFFLINE) { + item->setTextColor(COLUMN_CONTACT_NAME, COLOR_CONNECT); + } + + item->setIcon(COLUMN_CONTACT_NAME, QIcon(StatusDefs::imageUser(state))); + item->setData(COLUMN_CONTACT_DATA, ROLE_CONTACT_ID, QString::fromStdString(detail.id)); + item->setData(COLUMN_CONTACT_DATA, ROLE_CONTACT_SORT, "2 " + name); + + // add to the list + if (groupItem) { + groupItem->addChild(item); + } else { + sendWidget->addTopLevelItem(item); + } + } + + if (groupIt != groupInfoList.end()) { + groupIt++; + } else { + // all done + break; + } + } + + if (ui.filterPatternLineEdit->text().isEmpty() == false) { + FilterItems(); + } + + sendWidget->update(); /* update display */ + + // create completer list for friends + QStringList completerList; + QStringList completerGroupList; + + for (peerIt = peers.begin(); peerIt != peers.end(); peerIt++) { + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(*peerIt, detail)) { + continue; /* BAD */ + } + + QString name = PeerDefs::nameWithLocation(detail); + if (completerList.indexOf(name) == -1) { + completerList.append(name); + } + } + + completerList.sort(); + + // create completer list for groups + for (groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); groupIt++) { + completerGroupList.append(GroupDefs::name(*groupIt)); + } + + completerGroupList.sort(); + completerList.append(completerGroupList); + + m_completer = new QCompleter(completerList, this); + m_completer->setCaseSensitivity(Qt::CaseInsensitive); + setNewCompleter(ui.recipientWidget, m_completer); +} + +void MessageComposer::groupsChanged(int type) +{ + Q_UNUSED(type); + + insertSendList(); +} + +void MessageComposer::peerStatusChanged(const QString& peer_id, int status) +{ + QTreeWidgetItemIterator itemIterator(ui.msgSendList); + QTreeWidgetItem *item; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + if (item->data(COLUMN_CONTACT_DATA, ROLE_CONTACT_ID).toString() == peer_id) { + QColor color; + if (status != (int) RS_STATUS_OFFLINE) { + color = COLOR_CONNECT; + } else { + color = Qt::black; + } + + item->setTextColor(COLUMN_CONTACT_NAME, color); + item->setIcon(COLUMN_CONTACT_NAME, QIcon(StatusDefs::imageUser(status))); + //break; no break, peers can assigned to groups more than one + } + } + + int rowCount = ui.recipientWidget->rowCount(); + int row; + + for (row = 0; row < rowCount; row++) { + enumType type; + std::string id; + bool group; + + if (getRecipientFromRow(row, type, id, group) && id.empty() == false) { + if (group == false && QString::fromStdString(id) == peer_id) { + QTableWidgetItem *item = ui.recipientWidget->item(row, COLUMN_RECIPIENT_ICON); + if (item) { + item->setIcon(QIcon(StatusDefs::imageUser(status))); + } + } + } + } +} + +void MessageComposer::insertFileList(const std::list& dir_info) +{ + std::list files_info; + std::list::const_iterator it; + + /* convert dir_info to files_info */ + for(it = dir_info.begin(); it != dir_info.end(); it++) + { + FileInfo info ; + info.fname = it->name ; + info.hash = it->hash ; + info.size = it->count ; + files_info.push_back(info) ; + } + + insertFileList(files_info); +} + +void MessageComposer::insertFileList(const std::list& files_info) +{ + _recList.clear() ; + + ui.msgFileList->clear(); + + std::list::const_iterator it; + for(it = files_info.begin(); it != files_info.end(); it++) { + addFile(*it); + } + + ui.msgFileList->update(); /* update display */ +} + +void MessageComposer::addFile(const FileInfo &fileInfo) +{ + for(std::list::iterator it = _recList.begin(); it != _recList.end(); it++) { + if (it->hash == fileInfo.hash) { + /* File already added */ + return; + } + } + + _recList.push_back(fileInfo) ; + + /* make a widget per person */ + QTreeWidgetItem *item = new QTreeWidgetItem; + + item->setText(COLUMN_FILE_NAME, QString::fromUtf8(fileInfo.fname.c_str())); + item->setText(COLUMN_FILE_SIZE, misc::friendlyUnit(fileInfo.size)); + item->setText(COLUMN_FILE_HASH, QString::fromStdString(fileInfo.hash)); + item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + item->setCheckState(COLUMN_FILE_CHECKED, Qt::Checked); + + /* add to the list */ + ui.msgFileList->addTopLevelItem(item); +} + +/* title changed */ +void MessageComposer::titleChanged() +{ + calculateTitle(); + ui.msgText->document()->setModified(true); +} + +void MessageComposer::calculateTitle() +{ + setWindowTitle(tr("Compose") + ": " + misc::removeNewLine(ui.titleEdit->text())); +} + +static void calculateGroupsOfSslIds(std::list &existingGroupInfos, std::list &checkSslIds, std::list &checkGroupIds) +{ + checkGroupIds.clear(); + + if (checkSslIds.empty()) { + // nothing to do + return; + } + + std::map sslToGpg; + std::map > gpgToSslIds; + + std::list groupInfos; + + // iterate all groups + std::list::iterator groupInfoIt; + for (groupInfoIt = existingGroupInfos.begin(); groupInfoIt != existingGroupInfos.end(); groupInfoIt++) { + if (groupInfoIt->peerIds.empty()) { + continue; + } + + // iterate all assigned peers (gpg id's) + std::list::iterator peerIt; + for (peerIt = groupInfoIt->peerIds.begin(); peerIt != groupInfoIt->peerIds.end(); peerIt++) { + std::list sslIds; + + std::map >::iterator it = gpgToSslIds.find(*peerIt); + if (it == gpgToSslIds.end()) { + rsPeers->getSSLChildListOfGPGId(*peerIt, sslIds); + + gpgToSslIds[*peerIt] = sslIds; + } else { + sslIds = it->second; + } + + // iterate all ssl id's + std::list::const_iterator sslIt; + for (sslIt = sslIds.begin(); sslIt != sslIds.end(); sslIt++) { + // search in ssl list + if (std::find(checkSslIds.begin(), checkSslIds.end(), *sslIt) == checkSslIds.end()) { + // not found + break; + } + } + if (sslIt != sslIds.end()) { + // one or more ssl id's not found + break; + } + } + + if (peerIt == groupInfoIt->peerIds.end()) { + // all ssl id's of all assigned gpg id's found + groupInfos.push_back(*groupInfoIt); + } + } + + // remove all ssl id's of all found groups from the list + for (groupInfoIt = groupInfos.begin(); groupInfoIt != groupInfos.end(); groupInfoIt++) { + // iterate all assigned peers (gpg id's) + std::list::iterator peerIt; + for (peerIt = groupInfoIt->peerIds.begin(); peerIt != groupInfoIt->peerIds.end(); peerIt++) { + std::list sslIds; + + std::map >::iterator it = gpgToSslIds.find(*peerIt); + if (it == gpgToSslIds.end()) { + rsPeers->getSSLChildListOfGPGId(*peerIt, sslIds); + + gpgToSslIds[*peerIt] = sslIds; + } else { + sslIds = it->second; + } + + // iterate all ssl id's + std::list::const_iterator sslIt; + for (sslIt = sslIds.begin(); sslIt != sslIds.end(); sslIt++) { + // search in ssl list + std::list::iterator it = std::find(checkSslIds.begin(), checkSslIds.end(), *sslIt); + if (it != checkSslIds.end()) { + checkSslIds.erase(it); + } + } + } + + checkGroupIds.push_back(groupInfoIt->id); + } +} + +MessageComposer *MessageComposer::newMsg(const std::string &msgId /*= ""*/) +{ + MessageComposer *msgComposer = new MessageComposer(); + + msgComposer->addEmptyRecipient(); + + if (msgId.empty() == false) { + // fill existing message + MessageInfo msgInfo; + if (!rsMsgs->getMessage(msgId, msgInfo)) { + std::cerr << "MessageComposer::newMsg() Couldn't find Msg" << std::endl; + delete msgComposer; + return NULL; + } + + if (msgInfo.msgflags & RS_MSG_DRAFT) { + msgComposer->m_sDraftMsgId = msgId; + + rsMsgs->getMsgParentId(msgId, msgComposer->m_msgParentId); + + if (msgInfo.msgflags & RS_MSG_REPLIED) { + msgComposer->m_msgType = REPLY; + } else if (msgInfo.msgflags & RS_MSG_FORWARDED) { + msgComposer->m_msgType = FORWARD; + } + } + + msgComposer->insertTitleText(QString::fromStdWString(msgInfo.title)); + + msgComposer->insertMsgText(QString::fromStdWString(msgInfo.msg)); + + msgComposer->insertFileList(msgInfo.files); + + // get existing groups + std::list groupInfoList; + rsPeers->getGroupInfoList(groupInfoList); + + std::list groupIds; + std::list::iterator groupIt; + std::list::iterator it; + + calculateGroupsOfSslIds(groupInfoList, msgInfo.msgto, groupIds); + for (groupIt = groupIds.begin(); groupIt != groupIds.end(); groupIt++ ) { + msgComposer->addRecipient(MessageComposer::TO, *groupIt, true) ; + } + for (it = msgInfo.msgto.begin(); it != msgInfo.msgto.end(); it++ ) { + msgComposer->addRecipient(MessageComposer::TO, *it, false) ; + } + + calculateGroupsOfSslIds(groupInfoList, msgInfo.msgcc, groupIds); + for (groupIt = groupIds.begin(); groupIt != groupIds.end(); groupIt++ ) { + msgComposer->addRecipient(MessageComposer::CC, *groupIt, true) ; + } + for (it = msgInfo.msgcc.begin(); it != msgInfo.msgcc.end(); it++ ) { + msgComposer->addRecipient(MessageComposer::CC, *it, false) ; + } + + calculateGroupsOfSslIds(groupInfoList, msgInfo.msgbcc, groupIds); + for (groupIt = groupIds.begin(); groupIt != groupIds.end(); groupIt++ ) { + msgComposer->addRecipient(MessageComposer::BCC, *groupIt, true) ; + } + for (it = msgInfo.msgbcc.begin(); it != msgInfo.msgbcc.end(); it++ ) { + msgComposer->addRecipient(MessageComposer::BCC, *it, false) ; + } + + MsgTagInfo tagInfo; + rsMsgs->getMessageTag(msgId, tagInfo); + msgComposer->m_tagIds = tagInfo.tagIds; + + msgComposer->showTagLabels(); + + msgComposer->ui.msgText->document()->setModified(false); + } + + msgComposer->calculateTitle(); + + return msgComposer; +} + +MessageComposer *MessageComposer::replyMsg(const std::string &msgId, bool all) +{ + MessageInfo msgInfo; + if (!rsMsgs->getMessage(msgId, msgInfo)) { + return NULL; + } + + MessageComposer *msgComposer = MessageComposer::newMsg(); + msgComposer->m_msgParentId = msgId; + msgComposer->m_msgType = REPLY; + + /* fill it in */ + + msgComposer->insertTitleText(QString::fromStdWString(msgInfo.title), REPLY); + + QTextDocument doc ; + doc.setHtml(QString::fromStdWString(msgInfo.msg)); + + msgComposer->insertPastedText(doc.toPlainText()); + msgComposer->addRecipient(MessageComposer::TO, msgInfo.srcId, false); + + if (all) { + std::string ownId = rsPeers->getOwnId(); + + for (std::list::iterator tli = msgInfo.msgto.begin(); tli != msgInfo.msgto.end(); tli++) { + if (ownId != *tli) { + msgComposer->addRecipient(MessageComposer::TO, *tli, false) ; + } + } + + for (std::list::iterator tli = msgInfo.msgcc.begin(); tli != msgInfo.msgcc.end(); tli++) { + if (ownId != *tli) { + msgComposer->addRecipient(MessageComposer::TO, *tli, false) ; + } + } + } + + msgComposer->calculateTitle(); + + /* window will destroy itself! */ + + return msgComposer; +} + +MessageComposer *MessageComposer::forwardMsg(const std::string &msgId) +{ + MessageInfo msgInfo; + if (!rsMsgs->getMessage(msgId, msgInfo)) { + return NULL; + } + + MessageComposer *msgComposer = MessageComposer::newMsg(); + msgComposer->m_msgParentId = msgId; + msgComposer->m_msgType = FORWARD; + + /* fill it in */ + + msgComposer->insertTitleText(QString::fromStdWString(msgInfo.title), FORWARD); + + QTextDocument doc ; + doc.setHtml(QString::fromStdWString(msgInfo.msg)) ; + + msgComposer->insertForwardPastedText(doc.toPlainText()); + + std::list& files_info = msgInfo.files; + + msgComposer->insertFileList(files_info); + + msgComposer->calculateTitle(); + + /* window will destroy itself! */ + + return msgComposer; +} + +void MessageComposer::insertTitleText(const QString &title, enumMessageType type) +{ + QString titleText; + + switch (type) { + case NORMAL: + titleText = title; + break; + case REPLY: + if (title.startsWith("Re:", Qt::CaseInsensitive)) { + titleText = title; + } else { + titleText = tr("Re:") + " " + title; + } + break; + case FORWARD: + if (title.startsWith("Fwd:", Qt::CaseInsensitive)) { + titleText = title; + } else { + titleText = tr("Fwd:") + " " + title; + } + break; + } + + ui.titleEdit->setText(misc::removeNewLine(titleText)); +} + +void MessageComposer::insertPastedText(QString msg) +{ + msg.replace("\n", "\n
    > "); + + ui.msgText->setHtml(" > " + msg + "

    "); + + ui.msgText->setFocus( Qt::OtherFocusReason ); + + QTextCursor c = ui.msgText->textCursor(); + c.movePosition(QTextCursor::End); + ui.msgText->setTextCursor(c); + + ui.msgText->document()->setModified(true); +} + +void MessageComposer::insertForwardPastedText(QString msg) +{ + msg.replace("\n", "\n
    > "); + + ui.msgText->setHtml("
    > " + msg + "

    "); + + ui.msgText->setFocus( Qt::OtherFocusReason ); + + QTextCursor c = ui.msgText->textCursor(); + c.movePosition(QTextCursor::End); + ui.msgText->setTextCursor(c); + + ui.msgText->document()->setModified(true); +} + +void MessageComposer::insertMsgText(const QString &msg) +{ + ui.msgText->setText(msg); + + ui.msgText->setFocus( Qt::OtherFocusReason ); + + QTextCursor c = ui.msgText->textCursor(); + c.movePosition(QTextCursor::End); + ui.msgText->setTextCursor(c); + + ui.msgText->document()->setModified(true); +} + +void MessageComposer::insertHtmlText(const QString &msg) +{ + ui.msgText->setHtml(" " + msg + ""); + + ui.msgText->document()->setModified(true); +} + +void MessageComposer::sendMessage() +{ + if (sendMessage_internal(false)) { + close(); + } +} + +bool MessageComposer::sendMessage_internal(bool bDraftbox) +{ + /* construct a message */ + MessageInfo mi; + + mi.title = misc::removeNewLine(ui.titleEdit->text()).toStdWString(); + mi.msg = ui.msgText->toHtml().toStdWString(); + + /* check for existing title */ + if (bDraftbox == false && mi.title.empty()) { + if (QMessageBox::warning(this, tr("RetroShare"), tr("Do you want to send the message without a subject ?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) { + ui.titleEdit->setFocus(); + return false; // Don't send with an empty subject + } + } + + int filesCount = ui.msgFileList->topLevelItemCount(); + for (int i = 0; i < filesCount; i++) { + QTreeWidgetItem *item = ui.msgFileList->topLevelItem(i); + if (item->checkState(COLUMN_FILE_CHECKED)) { + std::string hash = item->text(COLUMN_FILE_HASH).toStdString(); + for(std::list::iterator it = _recList.begin(); it != _recList.end(); it++) { + if (it->hash == hash) { + mi.files.push_back(*it); + break; + } + } + } + } + + /* get the ids from the send list */ + std::list peers; + rsPeers->getFriendList(peers); + + int rowCount = ui.recipientWidget->rowCount(); + int row; + + for (row = 0; row < rowCount; row++) { + enumType type; + std::string id; + bool group; + + if (getRecipientFromRow(row, type, id, group) && id.empty() == false) { + if (group) { + RsGroupInfo groupInfo; + if (rsPeers->getGroupInfo(id, groupInfo) == false) { + // group not found + continue; + } + + std::list::const_iterator groupIt; + for (groupIt = groupInfo.peerIds.begin(); groupIt != groupInfo.peerIds.end(); groupIt++) { + std::list sslIds; + rsPeers->getSSLChildListOfGPGId(*groupIt, sslIds); + + std::list::const_iterator sslIt; + for (sslIt = sslIds.begin(); sslIt != sslIds.end(); sslIt++) { + if (std::find(peers.begin(), peers.end(), *sslIt) == peers.end()) { + // no friend + continue; + } + + switch (type) { + case TO: + if (std::find(mi.msgto.begin(), mi.msgto.end(), *sslIt) == mi.msgto.end()) { + mi.msgto.push_back(*sslIt); + } + break; + case CC: + if (std::find(mi.msgcc.begin(), mi.msgcc.end(), *sslIt) == mi.msgcc.end()) { + mi.msgcc.push_back(*sslIt); + } + break; + case BCC: + if (std::find(mi.msgbcc.begin(), mi.msgbcc.end(), *sslIt) == mi.msgbcc.end()) { + mi.msgbcc.push_back(*sslIt); + } + break; + } + } + } + } else { + if (std::find(peers.begin(), peers.end(), id) == peers.end()) { + // no friend + continue; + } + + switch (type) { + case TO: + if (std::find(mi.msgto.begin(), mi.msgto.end(), id) == mi.msgto.end()) { + mi.msgto.push_back(id); + } + break; + case CC: + if (std::find(mi.msgcc.begin(), mi.msgcc.end(), id) == mi.msgcc.end()) { + mi.msgcc.push_back(id); + } + break; + case BCC: + if (std::find(mi.msgbcc.begin(), mi.msgbcc.end(), id) == mi.msgbcc.end()) { + mi.msgbcc.push_back(id); + } + break; + } + } + } + } + + if (bDraftbox) { + mi.msgId = m_sDraftMsgId; + + rsMsgs->MessageToDraft(mi, m_msgParentId); + + // use new message id + m_sDraftMsgId = mi.msgId; + + switch (m_msgType) { + case NORMAL: + break; + case REPLY: + rsMsgs->MessageReplied(m_sDraftMsgId, true); + break; + case FORWARD: + rsMsgs->MessageForwarded(m_sDraftMsgId, true); + break; + } + } else { + /* check for the recipient */ + if (mi.msgto.empty()) { + QMessageBox::warning(this, tr("RetroShare"), tr("Please insert at least one recipient."), QMessageBox::Ok); + return false; // Don't send with no recipient + } + + if (rsMsgs->MessageSend(mi) == false) { + return false; + } + + if (m_msgParentId.empty() == false) { + switch (m_msgType) { + case NORMAL: + break; + case REPLY: + rsMsgs->MessageReplied(m_msgParentId, true); + break; + case FORWARD: + rsMsgs->MessageForwarded(m_msgParentId, true); + break; + } + } + } + + if (mi.msgId.empty() == false) { + MsgTagInfo tagInfo; + rsMsgs->getMessageTag(mi.msgId, tagInfo); + + /* insert new tags */ + std::list::iterator tag; + for (tag = m_tagIds.begin(); tag != m_tagIds.end(); tag++) { + if (std::find(tagInfo.tagIds.begin(), tagInfo.tagIds.end(), *tag) == tagInfo.tagIds.end()) { + rsMsgs->setMessageTag(mi.msgId, *tag, true); + } else { + tagInfo.tagIds.remove(*tag); + } + } + + /* remove deleted tags */ + for (tag = tagInfo.tagIds.begin(); tag != tagInfo.tagIds.end(); tag++) { + rsMsgs->setMessageTag(mi.msgId, *tag, false); + } + } + ui.msgText->document()->setModified(false); + return true; +} + +void MessageComposer::cancelMessage() +{ + close(); + return; +} + +/* Toggling .... Check Boxes..... + * This is dependent on whether we are a + * + * Chan or Msg Dialog. + */ + +void MessageComposer::addEmptyRecipient() +{ + int lastRow = ui.recipientWidget->rowCount(); + if (lastRow > 0) { + QTableWidgetItem *item = ui.recipientWidget->item(lastRow - 1, COLUMN_RECIPIENT_DATA); + if (item && item->data(ROLE_RECIPIENT_ID).toString().isEmpty()) { + return; + } + } + + setRecipientToRow(lastRow, TO, "", false); +} + +bool MessageComposer::getRecipientFromRow(int row, enumType &type, std::string &id, bool &group) +{ + if (row >= ui.recipientWidget->rowCount()) { + return false; + } + + QComboBox *cb = dynamic_cast(ui.recipientWidget->cellWidget(row, COLUMN_RECIPIENT_TYPE)); + if (cb == NULL) { + return false; + } + + type = (enumType) cb->itemData(cb->currentIndex(), Qt::UserRole).toInt(); + id = ui.recipientWidget->item(row, COLUMN_RECIPIENT_DATA)->data(ROLE_RECIPIENT_ID).toString().toStdString(); + group = ui.recipientWidget->item(row, COLUMN_RECIPIENT_DATA)->data(ROLE_RECIPIENT_GROUP).toBool(); + + return true; +} + +void MessageComposer::setRecipientToRow(int row, enumType type, std::string id, bool group) +{ + if (row + 1 > ui.recipientWidget->rowCount()) { + ui.recipientWidget->setRowCount(row + 1); + } + + QComboBox *comboBox = dynamic_cast(ui.recipientWidget->cellWidget(row, COLUMN_RECIPIENT_TYPE)); + if (comboBox == NULL) { + comboBox = new QComboBox; + comboBox->addItem(tr("To"), TO); + comboBox->addItem(tr("Cc"), CC); + comboBox->addItem(tr("Bcc"), BCC); + + ui.recipientWidget->setCellWidget(row, COLUMN_RECIPIENT_TYPE, comboBox); + + comboBox->installEventFilter(this); + } + + QLineEdit *lineEdit = dynamic_cast(ui.recipientWidget->cellWidget(row, COLUMN_RECIPIENT_NAME)); + if (lineEdit == NULL) { + lineEdit = new QLineEdit; + + QString objectName = "lineEdit" + QString::number(row); + lineEdit->setObjectName(objectName); + + lineEdit->setCompleter(m_completer); + + ui.recipientWidget->setCellWidget(row, COLUMN_RECIPIENT_NAME, lineEdit); + + connect(lineEdit, SIGNAL(editingFinished()), this, SLOT(editingRecipientFinished())); + lineEdit->installEventFilter(this); + } + + QIcon icon; + QString name; + if (id.empty() == FALSE) { + if (group) { + icon = QIcon(IMAGE_GROUP16); + + RsGroupInfo groupInfo; + if (rsPeers->getGroupInfo(id, groupInfo)) { + name = GroupDefs::name(groupInfo); + } else { + name = tr("Unknown"); + id.clear(); + } + } else { + RsPeerDetails details; + if (rsPeers->getPeerDetails(id, details)) { + name = PeerDefs::nameWithLocation(details); + + StatusInfo peerStatusInfo; + // No check of return value. Non existing status info is handled as offline. + rsStatus->getStatus(id, peerStatusInfo); + + icon = QIcon(StatusDefs::imageUser(peerStatusInfo.status)); + } else { + icon = QIcon(StatusDefs::imageUser(RS_STATUS_OFFLINE)); + name = tr("Unknown friend"); + id.clear(); + } + } + } + + comboBox->setCurrentIndex(comboBox->findData(type, Qt::UserRole)); + + lineEdit->setText(name); + if (id.empty()) { + lineEdit->setStyleSheet(QString(STYLE_FAIL).arg(lineEdit->objectName())); + } else { + lineEdit->setStyleSheet(QString(STYLE_NORMAL).arg(lineEdit->objectName())); + } + + QTableWidgetItem *item = new QTableWidgetItem(icon, "", 0); + item->setFlags(Qt::NoItemFlags); + ui.recipientWidget->setItem(row, COLUMN_RECIPIENT_ICON, item); + ui.recipientWidget->item(row, COLUMN_RECIPIENT_DATA)->setData(ROLE_RECIPIENT_ID, QString::fromStdString(id)); + ui.recipientWidget->item(row, COLUMN_RECIPIENT_DATA)->setData(ROLE_RECIPIENT_GROUP, group); + + addEmptyRecipient(); +} + +bool MessageComposer::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::FocusIn) { + QLineEdit *lineEdit = dynamic_cast(obj); + if (lineEdit) { + int rowCount = ui.recipientWidget->rowCount(); + int row; + for (row = 0; row < rowCount; row++) { + if (ui.recipientWidget->cellWidget(row, COLUMN_RECIPIENT_NAME) == lineEdit) { + break; + } + } + if (row < rowCount) { + ui.recipientWidget->setCurrentCell(row, COLUMN_RECIPIENT_NAME); +// lineEdit->setFocus(); + } + } else { + QComboBox *comboBox = dynamic_cast(obj); + if (comboBox) { + int rowCount = ui.recipientWidget->rowCount(); + int row; + for (row = 0; row < rowCount; row++) { + if (ui.recipientWidget->cellWidget(row, COLUMN_RECIPIENT_TYPE) == comboBox) { + break; + } + } + if (row < rowCount) { + ui.recipientWidget->setCurrentCell(row, COLUMN_RECIPIENT_TYPE); +// comboBox->setFocus(); + } + } + } + } + + // pass the event on to the parent class + return QMainWindow::eventFilter(obj, event); +} + +void MessageComposer::editingRecipientFinished() +{ + QLineEdit *lineEdit = dynamic_cast(QObject::sender()); + if (lineEdit == NULL) { + return; + } + + lineEdit->setStyleSheet(QString(STYLE_NORMAL).arg(lineEdit->objectName())); + + // find row of the widget + int rowCount = ui.recipientWidget->rowCount(); + int row; + for (row = 0; row < rowCount; row++) { + if (ui.recipientWidget->cellWidget(row, COLUMN_RECIPIENT_NAME) == lineEdit) { + break; + } + } + if (row >= rowCount) { + // not found + return; + } + + enumType type; + std::string id; // dummy + bool group; // dummy + getRecipientFromRow(row, type, id, group); + + QString text = lineEdit->text(); + + if (text.isEmpty()) { + setRecipientToRow(row, type, "", false); + return; + } + + // start with peers + std::list peers; + rsPeers->getFriendList(peers); + + std::list::iterator peerIt; + for (peerIt = peers.begin(); peerIt != peers.end(); peerIt++) { + RsPeerDetails details; + if (!rsPeers->getPeerDetails(*peerIt, details)) { + continue; /* BAD */ + } + + QString name = PeerDefs::nameWithLocation(details); + if (text.compare(name, Qt::CaseSensitive) == 0) { + // found it + setRecipientToRow(row, type, details.id, false); + return; + } + } + + // then groups + std::list groupInfoList; + rsPeers->getGroupInfoList(groupInfoList); + + std::list::iterator groupIt; + for (groupIt = groupInfoList.begin(); groupIt != groupInfoList.end(); groupIt++) { + QString groupName = GroupDefs::name(*groupIt); + if (text.compare(groupName, Qt::CaseSensitive) == 0) { + // found it + setRecipientToRow(row, type, groupIt->id, true); + return; + } + } + + setRecipientToRow(row, type, "", false); + lineEdit->setStyleSheet(QString(STYLE_FAIL).arg(lineEdit->objectName())); + lineEdit->setText(text); +} + +void MessageComposer::addRecipient(enumType type, const std::string &id, bool group) +{ + std::list sslIds; + if (group) { + sslIds.push_back(id); + } else { + // check for gpg id or ssl id + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(id, detail)) { + return; + } + + if (detail.isOnlyGPGdetail) { + if (!rsPeers->getSSLChildListOfGPGId(id, sslIds)) { + return; + } + } else { + sslIds.push_back(id); + } + } + std::list::const_iterator sslIt; + for (sslIt = sslIds.begin(); sslIt != sslIds.end(); sslIt++) { + // search existing or empty row + int rowCount = ui.recipientWidget->rowCount(); + int row; + for (row = 0; row < rowCount; row++) { + enumType rowType; + std::string rowId; + bool rowGroup; + + if (getRecipientFromRow(row, rowType, rowId, rowGroup) == true) { + if (rowId.empty()) { + // use row + break; + } + + if (rowId == *sslIt && rowType == type && group == rowGroup) { + // existing row + break; + } + } else { + // use row + break; + } + } + + setRecipientToRow(row, type, *sslIt, group); + } +} + +void MessageComposer::setupFileActions() +{ + QMenu *menu = new QMenu(tr("&File"), this); + menuBar()->addMenu(menu); + + QAction *a; + + a = new QAction(QIcon(":/images/textedit/filenew.png"), tr("&New"), this); + a->setShortcut(QKeySequence::New); + connect(a, SIGNAL(triggered()), this, SLOT(fileNew())); + menu->addAction(a); + + a = new QAction(QIcon(":/images/textedit/fileopen.png"), tr("&Open..."), this); + a->setShortcut(QKeySequence::Open); + connect(a, SIGNAL(triggered()), this, SLOT(fileOpen())); + menu->addAction(a); + + menu->addSeparator(); + + actionSave = a = new QAction(QIcon(":/images/textedit/filesave.png"), tr("&Save"), this); + a->setShortcut(QKeySequence::Save); + connect(a, SIGNAL(triggered()), this, SLOT(saveasDraft())); + a->setEnabled(false); + menu->addAction(a); + + a = new QAction(tr("Save &As File"), this); + connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAs())); + menu->addAction(a); + + a = new QAction(tr("Save &As Draft"), this); + connect(a, SIGNAL(triggered()), this, SLOT(saveasDraft())); + menu->addAction(a); + menu->addSeparator(); + + a = new QAction(QIcon(":/images/textedit/fileprint.png"), tr("&Print..."), this); + a->setShortcut(QKeySequence::Print); + connect(a, SIGNAL(triggered()), this, SLOT(filePrint())); + menu->addAction(a); + + /*a = new QAction(QIcon(":/images/textedit/fileprint.png"), tr("Print Preview..."), this); + connect(a, SIGNAL(triggered()), this, SLOT(filePrintPreview())); + menu->addAction(a);*/ + + a = new QAction(QIcon(":/images/textedit/exportpdf.png"), tr("&Export PDF..."), this); + a->setShortcut(Qt::CTRL + Qt::Key_D); + connect(a, SIGNAL(triggered()), this, SLOT(filePrintPdf())); + menu->addAction(a); + + menu->addSeparator(); + + a = new QAction(tr("&Quit"), this); + a->setShortcut(Qt::CTRL + Qt::Key_Q); + connect(a, SIGNAL(triggered()), this, SLOT(close())); + menu->addAction(a); +} + +void MessageComposer::setupEditActions() +{ + QMenu *menu = new QMenu(tr("&Edit"), this); + menuBar()->addMenu(menu); + + QAction *a; + a = actionUndo = new QAction(QIcon(":/images/textedit/editundo.png"), tr("&Undo"), this); + a->setShortcut(QKeySequence::Undo); + menu->addAction(a); + a = actionRedo = new QAction(QIcon(":/images/textedit/editredo.png"), tr("&Redo"), this); + a->setShortcut(QKeySequence::Redo); + menu->addAction(a); + menu->addSeparator(); + a = actionCut = new QAction(QIcon(":/images/textedit/editcut.png"), tr("Cu&t"), this); + a->setShortcut(QKeySequence::Cut); + menu->addAction(a); + a = actionCopy = new QAction(QIcon(":/images/textedit/editcopy.png"), tr("&Copy"), this); + a->setShortcut(QKeySequence::Copy); + menu->addAction(a); + a = actionPaste = new QAction(QIcon(":/images/textedit/editpaste.png"), tr("&Paste"), this); + a->setShortcut(QKeySequence::Paste); + menu->addAction(a); + actionPaste->setEnabled(!QApplication::clipboard()->text().isEmpty()); +} + +void MessageComposer::setupViewActions() +{ + QMenu *menu = new QMenu(tr("&View"), this); + menuBar()->addMenu(menu); + + contactSidebarAction = menu->addAction(QIcon(), tr("&Contacts Sidebar"), this, SLOT(toggleContacts())); + contactSidebarAction->setCheckable(true); +} + +void MessageComposer::setupInsertActions() +{ + QMenu *menu = new QMenu(tr("&Insert"), this); + menuBar()->addMenu(menu); + + QAction *a; + +#ifndef RS_RELEASE_VERSION + a = new QAction(QIcon(""), tr("&Image"), this); + connect(a, SIGNAL(triggered()), this, SLOT(addImage())); + menu->addAction(a); +#endif + + a = new QAction(QIcon(""), tr("&Horizontal Line"), this); + connect(a, SIGNAL(triggered()), this, SLOT(addPostSplitter())); + menu->addAction(a); + +} + +void MessageComposer::setupFormatActions() +{ + QMenu *menu = new QMenu(tr("&Format"), this); + menuBar()->addMenu(menu); + + menu->addAction(actionAlignLeft); + menu->addAction(actionAlignCenter); + menu->addAction(actionAlignRight); + menu->addAction(actionAlignJustify); + +} + +void MessageComposer::textBold() +{ + QTextCharFormat fmt; + fmt.setFontWeight(ui.boldbtn->isChecked() ? QFont::Bold : QFont::Normal); + mergeFormatOnWordOrSelection(fmt); +} + +void MessageComposer::textUnderline() +{ + QTextCharFormat fmt; + fmt.setFontUnderline(ui.underlinebtn->isChecked()); + mergeFormatOnWordOrSelection(fmt); +} + +void MessageComposer::textItalic() +{ + QTextCharFormat fmt; + fmt.setFontItalic(ui.italicbtn->isChecked()); + mergeFormatOnWordOrSelection(fmt); +} + +void MessageComposer::textFamily(const QString &f) +{ + QTextCharFormat fmt; + fmt.setFontFamily(f); + mergeFormatOnWordOrSelection(fmt); +} + +void MessageComposer::textSize(const QString &p) +{ + qreal pointSize = p.toFloat(); + if (p.toFloat() > 0) { + QTextCharFormat fmt; + fmt.setFontPointSize(pointSize); + mergeFormatOnWordOrSelection(fmt); + } +} + +void MessageComposer::changeFormatType(int styleIndex ) +{ + ui.msgText->setFocus( Qt::OtherFocusReason ); + + QTextCursor cursor = ui.msgText->textCursor(); + //QTextBlockFormat bformat = cursor.blockFormat(); + QTextBlockFormat bformat; + QTextCharFormat cformat; + + switch (styleIndex) { + default: + case 0: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 0 ) ); + cformat.setFontWeight( QFont::Normal ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 0 ) ); + break; + case 1: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 1 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 3 ) ); + break; + case 2: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 2 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 2 ) ); + break; + case 3: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 3 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 1 ) ); + break; + case 4: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 4 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 0 ) ); + break; + case 5: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 5 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( -1 ) ); + break; + case 6: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 6 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( -2 ) ); + break; + } + //cformat.clearProperty( TextFormat::HasCodeStyle ); + + cursor.beginEditBlock(); + cursor.mergeBlockFormat( bformat ); + cursor.select( QTextCursor::BlockUnderCursor ); + cursor.mergeCharFormat( cformat ); + cursor.endEditBlock(); +} + +void MessageComposer::textStyle(int styleIndex) +{ + QTextCursor cursor = ui.msgText->textCursor(); + + if (styleIndex != 0) { + QTextListFormat::Style style = QTextListFormat::ListDisc; + + switch (styleIndex) { + default: + case 1: + style = QTextListFormat::ListDisc; + break; + case 2: + style = QTextListFormat::ListCircle; + break; + case 3: + style = QTextListFormat::ListSquare; + break; + case 4: + style = QTextListFormat::ListDecimal; + break; + case 5: + style = QTextListFormat::ListLowerAlpha; + break; + case 6: + style = QTextListFormat::ListUpperAlpha; + break; + } + + cursor.beginEditBlock(); + + QTextBlockFormat blockFmt = cursor.blockFormat(); + + QTextListFormat listFmt; + + if (cursor.currentList()) { + listFmt = cursor.currentList()->format(); + } else { + listFmt.setIndent(blockFmt.indent() + 1); + blockFmt.setIndent(0); + cursor.setBlockFormat(blockFmt); + } + + listFmt.setStyle(style); + + cursor.createList(listFmt); + + cursor.endEditBlock(); + } else { + // #### + QTextBlockFormat bfmt; + bfmt.setObjectIndex(-1); + cursor.mergeBlockFormat(bfmt); + } +} + +void MessageComposer::textColor() +{ + QColor col = QColorDialog::getColor(ui.msgText->textColor(), this); + if (!col.isValid()) + return; + QTextCharFormat fmt; + fmt.setForeground(col); + mergeFormatOnWordOrSelection(fmt); + colorChanged(col); +} + +void MessageComposer::textAlign(QAction *a) +{ + if (a == actionAlignLeft) + ui.msgText->setAlignment(Qt::AlignLeft); + else if (a == actionAlignCenter) + ui.msgText->setAlignment(Qt::AlignHCenter); + else if (a == actionAlignRight) + ui.msgText->setAlignment(Qt::AlignRight); + else if (a == actionAlignJustify) + ui.msgText->setAlignment(Qt::AlignJustify); +} + +void MessageComposer::smileyWidget() +{ + Emoticons::showSmileyWidget(this, ui.emoticonButton, SLOT(addSmileys()), false); +} + +void MessageComposer::addSmileys() +{ + ui.msgText->textCursor().insertText(qobject_cast(sender())->toolTip().split("|").first()); +} + +void MessageComposer::currentCharFormatChanged(const QTextCharFormat &format) +{ + fontChanged(format.font()); + colorChanged(format.foreground().color()); +} + +void MessageComposer::cursorPositionChanged() +{ + alignmentChanged(ui.msgText->alignment()); +} + +void MessageComposer::mergeFormatOnWordOrSelection(const QTextCharFormat &format) +{ + QTextCursor cursor = ui.msgText->textCursor(); + if (!cursor.hasSelection()) + cursor.select(QTextCursor::WordUnderCursor); + cursor.mergeCharFormat(format); + ui.msgText->mergeCurrentCharFormat(format); +} + +void MessageComposer::fontChanged(const QFont &f) +{ + ui.comboFont->setCurrentIndex(ui.comboFont->findText(QFontInfo(f).family())); + ui.comboSize->setCurrentIndex(ui.comboSize->findText(QString::number(f.pointSize()))); + ui.boldbtn->setChecked(f.bold()); + ui.italicbtn->setChecked(f.italic()); + ui.underlinebtn->setChecked(f.underline()); +} + +void MessageComposer::colorChanged(const QColor &c) +{ + QPixmap pix(16, 16); + pix.fill(c); + ui.colorbtn->setIcon(pix); +} + +void MessageComposer::alignmentChanged(Qt::Alignment a) +{ + if (a & Qt::AlignLeft) { + actionAlignLeft->setChecked(true); + } else if (a & Qt::AlignHCenter) { + actionAlignCenter->setChecked(true); + } else if (a & Qt::AlignRight) { + actionAlignRight->setChecked(true); + } else if (a & Qt::AlignJustify) { + actionAlignJustify->setChecked(true); + } +} + +void MessageComposer::clipboardDataChanged() +{ + actionPaste->setEnabled(!QApplication::clipboard()->text().isEmpty()); +} + +void MessageComposer::fileNew() +{ + if (maybeSave()) { + ui.msgText->clear(); + //setCurrentFileName(QString()); + } +} + +void MessageComposer::fileOpen() +{ + QString fn; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Open File..."), tr("HTML-Files (*.htm *.html);;All Files (*)"), fn)) { + load(fn); + } +} + +bool MessageComposer::fileSave() +{ + if (fileName.isEmpty()) + return fileSaveAs(); + + QFile file(fileName); + if (!file.open(QFile::WriteOnly)) + return false; + QTextStream ts(&file); + ts.setCodec(QTextCodec::codecForName("UTF-8")); + ts << ui.msgText->document()->toHtml("UTF-8"); + ui.msgText->document()->setModified(false); + return true; +} + +bool MessageComposer::fileSaveAs() +{ + QString fn; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Save as..."), tr("HTML-Files (*.htm *.html);;All Files (*)"), fn)) { + setCurrentFileName(fn); + return fileSave(); + } + + return false; +} + +void MessageComposer::saveasDraft() +{ + sendMessage_internal(true); +} + +void MessageComposer::filePrint() +{ +#ifndef QT_NO_PRINTER + QPrinter printer(QPrinter::HighResolution); + printer.setFullPage(true); + QPrintDialog *dlg = new QPrintDialog(&printer, this); + if (ui.msgText->textCursor().hasSelection()) + dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection); + dlg->setWindowTitle(tr("Print Document")); + if (dlg->exec() == QDialog::Accepted) { + ui.msgText->print(&printer); + } + delete dlg; +#endif +} + +void MessageComposer::filePrintPdf() +{ +#ifndef QT_NO_PRINTER + QString fileName; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Export PDF"), "*.pdf", fileName)) { + if (QFileInfo(fileName).suffix().isEmpty()) + fileName.append(".pdf"); + QPrinter printer(QPrinter::HighResolution); + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setOutputFileName(fileName); + ui.msgText->document()->print(&printer); + } +#endif +} + +void MessageComposer::setCurrentFileName(const QString &fileName) +{ + this->fileName = fileName; + ui.msgText->document()->setModified(false); + + setWindowModified(false); +} + +bool MessageComposer::load(const QString &f) +{ + if (!QFile::exists(f)) + return false; + QFile file(f); + if (!file.open(QFile::ReadOnly)) + return false; + + QByteArray data = file.readAll(); + QTextCodec *codec = Qt::codecForHtml(data); + QString str = codec->toUnicode(data); + if (Qt::mightBeRichText(str)) { + ui.msgText->setHtml(str); + } else { + str = QString::fromLocal8Bit(data); + ui.msgText->setPlainText(str); + } + + setCurrentFileName(f); + return true; +} + +bool MessageComposer::maybeSave() +{ + if (!ui.msgText->document()->isModified()) + return true; + if (fileName.startsWith(QLatin1String(":/"))) + return true; + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("Save Message"), + tr("Message has not been Sent.\n" + "Do you want to save message ?"), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return fileSave(); + else if (ret == QMessageBox::Cancel) + return false; + return true; +} + + +void MessageComposer::toggleContacts() +{ + ui.contactsdockWidget->setVisible(!ui.contactsdockWidget->isVisible()); +} + +void MessageComposer::on_contactsdockWidget_visibilityChanged(bool visible) +{ + contactSidebarAction->setChecked(visible); +} + +void MessageComposer::addImage() +{ + QString fileimg; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Choose Image"), tr("Image Files supported (*.png *.jpeg *.jpg *.gif)"), fileimg)) { + QImage base(fileimg); + + QString pathimage = fileimg.left(fileimg.lastIndexOf("/"))+"/"; + Settings->setValueToGroup("MessageComposer", "LastDir", pathimage); + + Create_New_Image_Tag(fileimg); + } +} + +void MessageComposer::Create_New_Image_Tag( const QString urlremoteorlocal ) +{ + /*if (image_extension(urlremoteorlocal)) {*/ + QString subtext = QString("

    ").arg(urlremoteorlocal); + ///////////subtext.append("

    Description on image.

    "); + QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(subtext); + ui.msgText->textCursor().insertFragment(fragment); + //emit statusMessage(QString("Image new :").arg(urlremoteorlocal)); + //} +} + +void MessageComposer::fontSizeIncrease() +{ + if ( !( ui.msgText->textCursor().blockFormat().hasProperty( TextFormat::HtmlHeading ) && + ui.msgText->textCursor().blockFormat().intProperty( TextFormat::HtmlHeading ) ) ) { + QTextCharFormat format; + int idx = ui.msgText->currentCharFormat().intProperty( QTextFormat::FontSizeAdjustment ); + if ( idx < 3 ) { + format.setProperty( QTextFormat::FontSizeAdjustment, QVariant( ++idx ) ); + ui.msgText->textCursor().mergeCharFormat( format ); + } + } + ui.msgText->setFocus( Qt::OtherFocusReason ); +} + +void MessageComposer::fontSizeDecrease() +{ + if ( !( ui.msgText->textCursor().blockFormat().hasProperty( TextFormat::HtmlHeading ) && + ui.msgText->textCursor().blockFormat().intProperty( TextFormat::HtmlHeading ) ) ) { + QTextCharFormat format; + int idx = ui.msgText->currentCharFormat().intProperty( QTextFormat::FontSizeAdjustment ); + if ( idx > -1 ) { + format.setProperty( QTextFormat::FontSizeAdjustment, QVariant( --idx ) ); + ui.msgText->textCursor().mergeCharFormat( format ); + } + } + ui.msgText->setFocus( Qt::OtherFocusReason ); +} + +void MessageComposer::blockQuote() +{ + QTextBlockFormat blockFormat = ui.msgText->textCursor().blockFormat(); + QTextBlockFormat f; + + if ( blockFormat.hasProperty( TextFormat::IsBlockQuote ) && + blockFormat.boolProperty( TextFormat::IsBlockQuote ) ) { + f.setProperty( TextFormat::IsBlockQuote, QVariant( false ) ); + f.setLeftMargin( 0 ); + f.setRightMargin( 0 ); + } else { + f.setProperty( TextFormat::IsBlockQuote, QVariant( true ) ); + f.setLeftMargin( 40 ); + f.setRightMargin( 40 ); + } + ui.msgText->textCursor().mergeBlockFormat( f ); +} + +void MessageComposer::toggleCode() +{ + static QString preFontFamily; + + QTextCharFormat charFormat = ui.msgText->currentCharFormat(); + QTextCharFormat f; + + if ( charFormat.hasProperty( TextFormat::HasCodeStyle ) && + charFormat.boolProperty( TextFormat::HasCodeStyle ) ) { + f.setProperty( TextFormat::HasCodeStyle, QVariant( false ) ); + f.setBackground( defaultCharFormat.background() ); + f.setFontFamily( preFontFamily ); + ui.msgText->textCursor().mergeCharFormat( f ); + + } else { + preFontFamily = ui.msgText->fontFamily(); + f.setProperty( TextFormat::HasCodeStyle, QVariant( true ) ); + f.setBackground( codeBackground ); + f.setFontFamily( "Dejavu Sans Mono" ); + ui.msgText->textCursor().mergeCharFormat( f ); + } + ui.msgText->setFocus( Qt::OtherFocusReason ); +} + +void MessageComposer::addPostSplitter() +{ + QTextBlockFormat f = ui.msgText->textCursor().blockFormat(); + QTextBlockFormat f1 = f; + + f.setProperty( TextFormat::IsHtmlTagSign, true ); + f.setProperty( QTextFormat::BlockTrailingHorizontalRulerWidth, + QTextLength( QTextLength::PercentageLength, 80 ) ); + if ( ui.msgText->textCursor().block().text().isEmpty() ) { + ui.msgText->textCursor().mergeBlockFormat( f ); + } else { + ui.msgText->textCursor().insertBlock( f ); + } + ui.msgText->textCursor().insertBlock( f1 ); +} + +void MessageComposer::attachFile() +{ + // select a file + QStringList files; + if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { + for (QStringList::iterator fileIt = files.begin(); fileIt != files.end(); fileIt++) { + addAttachment((*fileIt).toUtf8().constData()); + } + } +} + +void MessageComposer::addAttachment(std::string filePath) +{ + /* add a AttachFileItem to the attachment section */ + std::cerr << "MessageComposer::addFile() hashing file."; + std::cerr << std::endl; + + /* add widget in for new destination */ + AttachFileItem *file = new AttachFileItem(filePath); + + ui.hashBox->show(); + ui.msgFileList->hide(); + ui.verticalLayout->addWidget(file, 1, 0); + + //when the file is local or is finished hashing, call the fileHashingFinished method to send a chat message + if (file->getState() == AFI_STATE_LOCAL) { + fileHashingFinished(file); + } else { + QObject::connect(file,SIGNAL(fileFinished(AttachFileItem *)),this, SLOT(fileHashingFinished(AttachFileItem *))) ; + } + mAttachments.push_back(file); + + if (mCheckAttachment) + { + checkAttachmentReady(); + } +} + +void MessageComposer::fileHashingFinished(AttachFileItem* file) +{ + std::cerr << "MessageComposer::fileHashingFinished() started."; + std::cerr << std::endl; + + //check that the file is ok tos end + if (file->getState() == AFI_STATE_ERROR) { +#ifdef CHAT_DEBUG + std::cerr << "MessageComposer::fileHashingFinished error file is not hashed."; +#endif + return; + } + + FileInfo fileInfo; + fileInfo.fname = file->FileName(); + fileInfo.hash = file->FileHash(); + fileInfo.size = file->FileSize(); + + addFile(fileInfo); +} + +void MessageComposer::checkAttachmentReady() +{ + std::list::iterator fit; + + mCheckAttachment = false; + + for(fit = mAttachments.begin(); fit != mAttachments.end(); fit++) + { + if (!(*fit)->isHidden()) + { + if (!(*fit)->ready()) + { + ui.actionSend->setEnabled(false); + break; + } + } + } + + if (fit == mAttachments.end()) + { + ui.actionSend->setEnabled(true); + ui.hashBox->hide(); + ui.msgFileList->show(); + } + + /* repeat... */ + int msec_rate = 1000; + QTimer::singleShot( msec_rate, this, SLOT(checkAttachmentReady(void))); +} + +/* clear Filter */ +void MessageComposer::clearFilter() +{ + ui.filterPatternLineEdit->clear(); + ui.filterPatternLineEdit->setFocus(); +} + +void MessageComposer::filterRegExpChanged() +{ + QString text = ui.filterPatternLineEdit->text(); + + if (text.isEmpty()) { + ui.clearButton->hide(); + } else { + ui.clearButton->show(); + } + + FilterItems(); +} + +void MessageComposer::FilterItems() +{ + QString sPattern = ui.filterPatternLineEdit->text(); + + int nCount = ui.msgSendList->topLevelItemCount (); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + FilterItem(ui.msgSendList->topLevelItem(nIndex), sPattern); + } +} + +bool MessageComposer::FilterItem(QTreeWidgetItem *pItem, QString &sPattern) +{ + bool bVisible = true; + + if (sPattern.isEmpty() == false) { + if (pItem->text(0).contains(sPattern, Qt::CaseInsensitive) == false) { + bVisible = false; + } + } + + int nVisibleChildCount = 0; + int nCount = pItem->childCount(); + for (int nIndex = 0; nIndex < nCount; nIndex++) { + if (FilterItem(pItem->child(nIndex), sPattern)) { + nVisibleChildCount++; + } + } + + if (bVisible || nVisibleChildCount) { + pItem->setHidden(false); + } else { + pItem->setHidden(true); + } + + return (bVisible || nVisibleChildCount); +} + +void MessageComposer::addContact(enumType type) +{ + QTreeWidgetItemIterator itemIterator(ui.msgSendList); + QTreeWidgetItem *item; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + if (item->isSelected()) { + std::string id = item->data(COLUMN_CONTACT_DATA, ROLE_CONTACT_ID).toString().toStdString(); + bool group = (item->type() == TYPE_GROUP); + addRecipient(type, id, group); + } + } +} + +void MessageComposer::addTo() +{ + addContact(TO); +} + +void MessageComposer::addCc() +{ + addContact(CC); +} + +void MessageComposer::addBcc() +{ + addContact(BCC); +} + +void MessageComposer::addRecommend() +{ + std::list gpgIds; + + QTreeWidgetItemIterator itemIterator(ui.msgSendList); + QTreeWidgetItem *item; + while ((item = *itemIterator) != NULL) { + itemIterator++; + + if (item->isSelected()) { + std::string id = item->data(COLUMN_CONTACT_DATA, ROLE_CONTACT_ID).toString().toStdString(); + bool group = (item->type() == TYPE_GROUP); + + if (group) { + RsGroupInfo groupInfo; + if (rsPeers->getGroupInfo(id, groupInfo) == false) { + continue; + } + + std::list::iterator it; + for (it = groupInfo.peerIds.begin(); it != groupInfo.peerIds.end(); it++) { + if (std::find(gpgIds.begin(), gpgIds.end(), *it) == gpgIds.end()) { + gpgIds.push_back(*it); + } + } + } else { + RsPeerDetails detail; + if (rsPeers->getPeerDetails(id, detail) == false) { + continue; + } + + if (std::find(gpgIds.begin(), gpgIds.end(), detail.gpg_id) == gpgIds.end()) { + gpgIds.push_back(detail.gpg_id); + } + } + } + } + + if (gpgIds.empty()) { + return; + } + + std::list ::iterator it; + for (it = gpgIds.begin(); it != gpgIds.end(); it++) { + addRecipient(CC, *it, false); + } + + QString text = BuildRecommendHtml(gpgIds); + ui.msgText->textCursor().insertHtml(text); + ui.msgText->setFocus(Qt::OtherFocusReason); +} + +void MessageComposer::friendDetails() +{ + QList selectedItems = ui.msgSendList->selectedItems(); + if (selectedItems.count() != 1) { + return; + } + + QTreeWidgetItem *item = selectedItems[0]; + if (item->type() == TYPE_GROUP) { + return; + } + + std::string id = item->data(COLUMN_CONTACT_DATA, ROLE_CONTACT_ID).toString().toStdString(); + ConfCertDialog::showIt(id, ConfCertDialog::PageDetails); +} + +void MessageComposer::dragEnterEvent(QDragEnterEvent *event) +{ + /* print out mimeType */ + std::cerr << "PopupChatDialog::dragEnterEvent() Formats"; + std::cerr << std::endl; + + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) { + std::cerr << "Format: " << (*it).toStdString(); + std::cerr << std::endl; + } + + if (event->mimeData()->hasUrls()) { + std::cerr << "PopupChatDialog::dragEnterEvent() Accepting Urls"; + std::cerr << std::endl; + event->acceptProposedAction(); + } else { + std::cerr << "PopupChatDialog::dragEnterEvent() No Urls"; + std::cerr << std::endl; + } +} + +void MessageComposer::dropEvent(QDropEvent *event) +{ + if (!(Qt::CopyAction & event->possibleActions())) { + std::cerr << "PopupChatDialog::dropEvent() Rejecting uncopyable DropAction"; + std::cerr << std::endl; + + /* can't do it */ + return; + } + + std::cerr << "PopupChatDialog::dropEvent() Formats"; + std::cerr << std::endl; + + QStringList formats = event->mimeData()->formats(); + QStringList::iterator it; + for(it = formats.begin(); it != formats.end(); it++) { + std::cerr << "Format: " << (*it).toStdString(); + std::cerr << std::endl; + } + + if (event->mimeData()->hasUrls()) { + std::cerr << "PopupChatDialog::dropEvent() Urls:"; + std::cerr << std::endl; + + QList urls = event->mimeData()->urls(); + QList::iterator uit; + for(uit = urls.begin(); uit != urls.end(); uit++) { + QString localpath = uit->toLocalFile(); + std::cerr << "Whole URL: " << uit->toString().toStdString() << std::endl; + std::cerr << "or As Local File: " << localpath.toStdString() << std::endl; + + if (localpath.isEmpty() == false) { + //Check that the file does exist and is not a directory + QDir dir(localpath); + if (dir.exists()) { + std::cerr << "PopupChatDialog::dropEvent() directory not accepted."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("Directory can't be dropped, only files are accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } else if (QFile::exists(localpath)) { + addAttachment(localpath.toUtf8().constData()); + } else { + std::cerr << "PopupChatDialog::dropEvent() file does not exists."<< std::endl; + QMessageBox mb(tr("Drop file error."), tr("File not found or file name not accepted."),QMessageBox::Information,QMessageBox::Ok,0,0,this); + mb.exec(); + } + } + } + } + + event->setDropAction(Qt::CopyAction); + event->accept(); +} + +void MessageComposer::tagAboutToShow() +{ + TagsMenu *menu = dynamic_cast(ui.tagButton->menu()); + if (menu == NULL) { + return; + } + + menu->activateActions(m_tagIds); +} + +void MessageComposer::tagRemoveAll() +{ + m_tagIds.clear(); + + showTagLabels(); +} + +void MessageComposer::tagSet(int tagId, bool set) +{ + if (tagId == 0) { + return; + } + + std::list::iterator tag = std::find(m_tagIds.begin(), m_tagIds.end(), tagId); + if (tag == m_tagIds.end()) { + if (set) { + m_tagIds.push_back(tagId); + /* Keep the list sorted */ + m_tagIds.sort(); + } + } else { + if (set == false) { + m_tagIds.remove(tagId); + } + } + + showTagLabels(); +} + +void MessageComposer::clearTagLabels() +{ + /* clear all tags */ + while (tagLabels.size()) { + delete tagLabels.front(); + tagLabels.pop_front(); + } + while (ui.tagLayout->count()) { + delete ui.tagLayout->takeAt(0); + } +} + +void MessageComposer::showTagLabels() +{ + clearTagLabels(); + + if (m_tagIds.empty() == false) { + MsgTagType tags; + rsMsgs->getMessageTagTypes(tags); + + std::map >::iterator tag; + for (std::list::iterator tagId = m_tagIds.begin(); tagId != m_tagIds.end(); tagId++) { + tag = tags.types.find(*tagId); + if (tag != tags.types.end()) { + QLabel *tagLabel = new QLabel(TagDefs::name(tag->first, tag->second.first), this); + tagLabel->setMaximumHeight(16); + tagLabel->setStyleSheet(TagDefs::labelStyleSheet(tag->second.second)); + tagLabels.push_back(tagLabel); + ui.tagLayout->addWidget(tagLabel); + ui.tagLayout->addSpacing(3); + } + } + ui.tagLayout->addStretch(); + } +} diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.h b/retroshare-gui/src/gui/msgs/MessageComposer.h new file mode 100644 index 000000000..fc34dfc28 --- /dev/null +++ b/retroshare-gui/src/gui/msgs/MessageComposer.h @@ -0,0 +1,233 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2007, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _MESSAGECOMPOSER_H +#define _MESSAGECOMPOSER_H + +#include +#include +#include "ui_MessageComposer.h" + +class QAction; +class QComboBox; +class QFontComboBox; +class QTextEdit; +class QTextCharFormat; +class AttachFileItem; +class RSTreeWidgetItemCompareRole; + +class MessageComposer : public QMainWindow +{ + Q_OBJECT + +public: + enum enumType { TO, CC, BCC }; + enum enumMessageType { NORMAL, REPLY, FORWARD }; + +public: + /** Default Constructor */ + + MessageComposer(QWidget *parent = 0, Qt::WFlags flags = 0); + ~MessageComposer(); + + static void msgFriend(std::string id, bool group); + static void recommendFriend(std::list &peerids); + + static MessageComposer *newMsg(const std::string &msgId = ""); + static MessageComposer *replyMsg(const std::string &msgId, bool all); + static MessageComposer *forwardMsg(const std::string &msgId); + + /* worker fns */ + void insertSendList(); + void insertFileList(const std::list&); + void insertFileList(const std::list&); + void addFile(const FileInfo &fileInfo); + void insertTitleText(const QString &title, enumMessageType type = NORMAL); + void insertPastedText(QString msg) ; + void insertForwardPastedText(QString msg); + void insertHtmlText(const QString &msg); + void insertMsgText(const QString &msg); + void addRecipient(enumType type, const std::string &id, bool group); + void Create_New_Image_Tag(const QString urlremoteorlocal); + +public slots: + /* actions to take.... */ + void sendMessage(); + void cancelMessage(); + void addImage(); + + void changeFormatType(int styleIndex ); + +protected: + void closeEvent (QCloseEvent * event); + bool eventFilter(QObject *obj, QEvent *ev); + + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); + +private slots: + /* toggle Contacts DockWidget */ + void contextMenu(QPoint); + void pasteLink(); + void contextMenuFileList(QPoint); + void contextMenuMsgSendList(QPoint); + void pasteRecommended(); + void on_contactsdockWidget_visibilityChanged(bool visible); + void toggleContacts(); + + void fileNew(); + void fileOpen(); + bool fileSave(); + bool fileSaveAs(); + void filePrint(); + void saveasDraft(); + + //void filePrintPreview(); + void filePrintPdf(); + + void textBold(); + void textUnderline(); + void textItalic(); + void textFamily(const QString &f); + void textSize(const QString &p); + void textStyle(int styleIndex); + void textColor(); + void textAlign(QAction *a); + void smileyWidget(); + void addSmileys(); + + void currentCharFormatChanged(const QTextCharFormat &format); + void cursorPositionChanged(); + + void clipboardDataChanged(); + + void fileHashingFinished(AttachFileItem* file); + + void attachFile(); + void addAttachment(std::string); + void checkAttachmentReady(); + + void fontSizeIncrease(); + void fontSizeDecrease(); + void blockQuote(); + void toggleCode(); + void addPostSplitter(); + + void filterRegExpChanged(); + void clearFilter(); + void titleChanged(); + + // Add to To/Cc/Bcc address fields + void addTo(); + void addCc(); + void addBcc(); + void addRecommend(); + void editingRecipientFinished(); + void friendDetails(); + + void groupsChanged(int type); + void peerStatusChanged(const QString& peer_id, int status); + + void tagAboutToShow(); + void tagSet(int tagId, bool set); + void tagRemoveAll(); + +private: + void processSettings(bool bLoad); + + void addContact(enumType type); + void setTextColor(const QColor& col) ; + void setupFileActions(); + void setupEditActions(); + void setupViewActions(); + void setupInsertActions(); + void setupFormatActions(); + + bool load(const QString &f); + bool maybeSave(); + //bool image_extension( QString nametomake ); + void setCurrentFileName(const QString &fileName); + + void mergeFormatOnWordOrSelection(const QTextCharFormat &format); + void fontChanged(const QFont &f); + void colorChanged(const QColor &c); + void alignmentChanged(Qt::Alignment a); + + bool sendMessage_internal(bool bDraftbox); + + void FilterItems(); + bool FilterItem(QTreeWidgetItem *pItem, QString &sPattern); + + void calculateTitle(); + void addEmptyRecipient(); + + bool getRecipientFromRow(int row, enumType &type, std::string &id, bool &group); + void setRecipientToRow(int row, enumType type, std::string id, bool group); + + void clearTagLabels(); + void showTagLabels(); + + QAction *actionSave, + *actionAlignLeft, + *actionAlignCenter, + *actionAlignRight, + *actionAlignJustify, + *actionUndo, + *actionRedo, + *actionCut, + *actionCopy, + *actionPaste; + + QAction *contactSidebarAction; + + QTreeView *channelstreeView; + + QString fileName; + QString nametomake; + + QColor codeBackground; + QTextCharFormat defaultCharFormat; + + QHash autoLinkDictionary; + QHash autoLinkTitleDictionary; + QHash autoLinkTargetDictionary; + + std::string m_msgParentId; // parent message id + std::string m_sDraftMsgId; // existing message id + enumMessageType m_msgType; + std::list m_tagIds; + QList tagLabels; + + /* maps of files */ + std::list mAttachments; + + bool mCheckAttachment; + + RSTreeWidgetItemCompareRole *m_compareRole; + QCompleter *m_completer; + + /** Qt Designer generated object */ + Ui::MessageComposer ui; + + std::list _recList ; +}; + +#endif diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.ui b/retroshare-gui/src/gui/msgs/MessageComposer.ui new file mode 100644 index 000000000..516aa5ac9 --- /dev/null +++ b/retroshare-gui/src/gui/msgs/MessageComposer.ui @@ -0,0 +1,1098 @@ + + + MessageComposer + + + + 0 + 0 + 796 + 588 + + + + Qt::NoContextMenu + + + Compose + + + + :/images/folder-draft.png:/images/folder-draft.png + + + QToolBar#toolBar{background-image: url(:/images/connect/connectFriendBanner.png)} + + + + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + 300 + 524287 + + + + + 220 + 0 + + + + + 0 + 0 + + + + false + + + QDockWidget::DockWidgetClosable + + + Contacts + + + + + 1 + + + + + 2 + + + + + Search for Name: + + + + + + + Search Friends + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + MS Shell Dlg 2 + + + + Qt::NoFocus + + + Reset + + + QPushButton +{ + border-image: url(:/images/closenormal.png) +} + +QPushButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QPushButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + + + + + + + + 0 + 4 + + + + + 20 + 0 + + + + + 300 + 16777215 + + + + + 220 + 0 + + + + + 200 + 0 + + + + Qt::CustomContextMenu + + + QAbstractItemView::ExtendedSelection + + + true + + + false + + + + Send To: + + + + + + + + + + + + + 0 + 0 + + + + >> To + + + + + + + + + + + + 0 + 0 + + + + >> Cc + + + + + + + + 0 + 0 + + + + >> Bcc + + + + + + + + + + + + 0 + 0 + + + + >> Recommend + + + + + + + + + + + + + Qt::Vertical + + + + + 2 + + + + + + 16777215 + 38 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + + + 1 + + + + + + 16777215 + 16777215 + + + + Qt::ClickFocus + + + + Paragraph + + + + + Heading 1 + + + + + Heading 2 + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + + + + + 100 + 16777215 + + + + Qt::ClickFocus + + + + + + + + 45 + 16777215 + + + + Qt::ClickFocus + + + Font size + + + + + + + + 1677 + 1677 + + + + Qt::NoFocus + + + Increase font size + + + + + + + :/images/textedit/format_font_size_more.png:/images/textedit/format_font_size_more.png + + + + 24 + 24 + + + + true + + + + + + + + 167 + 167 + + + + Qt::NoFocus + + + Decrease font size + + + + + + + :/images/textedit/format_font_size_less.png:/images/textedit/format_font_size_less.png + + + + 24 + 24 + + + + true + + + + + + + + 0 + 0 + + + + + 1677 + 1677 + + + + Qt::NoFocus + + + Bold + + + + + + + :/images/textedit/textbold.png:/images/textedit/textbold.png + + + + 24 + 24 + + + + true + + + true + + + + + + + + 0 + 0 + + + + + 167 + 167 + + + + Qt::NoFocus + + + Italic + + + + + + + :/images/textedit/textitalic.png:/images/textedit/textitalic.png + + + + 24 + 24 + + + + true + + + true + + + + + + + + 0 + 0 + + + + + 167 + 167 + + + + Qt::NoFocus + + + Select Color + + + + + + true + + + + + + + + 0 + 0 + + + + + 167 + 167 + + + + Qt::NoFocus + + + Alignment + + + + + + + 24 + 24 + + + + QToolButton::MenuButtonPopup + + + true + + + + + + + + 0 + 0 + + + + + 167 + 167 + + + + Qt::NoFocus + + + Add a Image + + + + + + + :/images/add_image24.png:/images/add_image24.png + + + + 24 + 24 + + + + true + + + + + + + Qt::NoFocus + + + Sets text font to code style + + + + + + + :/images/textedit/hi22-action-format-text-code.png:/images/textedit/hi22-action-format-text-code.png + + + + 22 + 22 + + + + true + + + + + + + Qt::Horizontal + + + + 20 + 24 + + + + + + + + Qt::NoFocus + + + + :/images/emoticons/kopete/kopete020.png:/images/emoticons/kopete/kopete020.png + + + + 24 + 24 + + + + true + + + + + + + + 0 + 0 + + + + + 167 + 167 + + + + Qt::NoFocus + + + Underline + + + + + + + :/images/textedit/textunder.png:/images/textedit/textunder.png + + + + 24 + 24 + + + + true + + + true + + + + + + + + + + + + + 4 + 4 + + + + Qt::CustomContextMenu + + + Qt::TextEditorInteraction + + + + + + + + 0 + 0 + + + + + 0 + 68 + + + + + 16777215 + 68 + + + + false + + + QAbstractItemView::SingleSelection + + + false + + + false + + + 22 + + + false + + + 22 + + + false + + + + + + + QLayout::SetNoConstraint + + + + + Subject: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Tags: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Tags + + + + :/images/tag24.png:/images/tag24.png + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + + + 6 + + + + + + 0 + 0 + + + + + 10 + 75 + true + + + + Recommended Files + + + + + + + + 0 + 0 + + + + Qt::CustomContextMenu + + + true + + + + File Name + + + + + Size + + + + + Hash + + + + + + + + true + + + + + 0 + 0 + 560 + 57 + + + + + 0 + + + + + + + + Qt::Vertical + + + + 20 + 46 + + + + + + + + + + + + + + + + + + + 0 + 0 + 796 + 20 + + + + + + + Qt::NoContextMenu + + + false + + + Qt::Horizontal + + + Qt::ToolButtonTextUnderIcon + + + TopToolBarArea + + + false + + + + + + + + + + + + :/images/send24.png:/images/send24.png + + + Send + + + Send this message now + + + + + + :/images/replymail24.png:/images/replymail24.png + + + Reply + + + + + + :/images/contacts24.png:/images/contacts24.png + + + Contacts + + + Toggle Contacts View + + + + + + :/images/save24.png:/images/save24.png + + + Save + + + Save this message + + + + + + :/images/attach.png:/images/attach.png + + + Attach + + + Attach File + + + + + true + + + + :/images/quote_24.png:/images/quote_24.png + + + Quote + + + Add Blockquote + + + + + recipientWidget + titleEdit + msgText + msgFileList + filterPatternLineEdit + msgSendList + addToButton + addCcButton + addBccButton + addRecommendButton + comboSize + comboStyle + comboFont + hashBox + + + + diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.cpp b/retroshare-gui/src/gui/msgs/MessageWidget.cpp new file mode 100644 index 000000000..d1a1ae6e6 --- /dev/null +++ b/retroshare-gui/src/gui/msgs/MessageWidget.cpp @@ -0,0 +1,651 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2011 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "gui/notifyqt.h" +#include "gui/RetroShareLink.h" +#include "gui/common/TagDefs.h" +#include "gui/common/PeerDefs.h" +#include "gui/common/Emoticons.h" +#include "gui/settings/rsharesettings.h" +#include "MessageComposer.h" +#include "MessageWidget.h" +#include "MessageWindow.h" +#include "util/misc.h" +#include "util/printpreview.h" + +#include +#include +#include + +/* Images for context menu icons */ +#define IMAGE_DOWNLOAD ":/images/start.png" +#define IMAGE_DOWNLOADALL ":/images/startall.png" + +#define COLUMN_FILE_NAME 0 +#define COLUMN_FILE_SIZE 1 +#define COLUMN_FILE_HASH 2 +#define COLUMN_FILE_COUNT 3 + +MessageWidget *MessageWidget::openMsg(const std::string &msgId, bool window) +{ + if (msgId.empty()) { + return NULL; + } + + MessageInfo msgInfo; + if (!rsMsgs->getMessage(msgId, msgInfo)) { + std::cerr << "MessageWidget::openMsg() Couldn't find Msg" << std::endl; + return NULL; + } + + MessageWindow *parent = NULL; + if (window) { + parent = new MessageWindow; + } + MessageWidget *msgWidget = new MessageWidget(false, parent); + msgWidget->isWindow = window; + msgWidget->fill(msgId); + if (parent) { + parent->addWidget(msgWidget); + } + + if (parent) { + parent->show(); + parent->activateWindow(); + } + + return msgWidget; +} + +/** Constructor */ +MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WFlags flags) +: QWidget(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + isControlled = controlled; + isWindow = false; + + connect(ui.msgList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(msgfilelistWidgetCostumPopupMenu(QPoint))); + connect(ui.expandFilesButton, SIGNAL(clicked()), this, SLOT(togglefileview())); + connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(getallrecommended())); + + connect(NotifyQt::getInstance(), SIGNAL(messagesTagsChanged()), this, SLOT(messagesTagsChanged())); + connect(NotifyQt::getInstance(), SIGNAL(messagesChanged()), this, SLOT(messagesChanged())); + + /* hide the Tree +/- */ + ui.msgList->setRootIsDecorated( false ); + ui.msgList->setSelectionMode( QAbstractItemView::ExtendedSelection ); + + /* Set header resize modes and initial section sizes */ + QHeaderView * msglheader = ui.msgList->header () ; + msglheader->setResizeMode (COLUMN_FILE_NAME, QHeaderView::Interactive); + msglheader->setResizeMode (COLUMN_FILE_SIZE, QHeaderView::Interactive); + msglheader->setResizeMode (COLUMN_FILE_HASH, QHeaderView::Interactive); + + msglheader->resizeSection (COLUMN_FILE_NAME, 200); + msglheader->resizeSection (COLUMN_FILE_SIZE, 100); + msglheader->resizeSection (COLUMN_FILE_HASH, 200); + + QFont font = QFont("Arial", 10, QFont::Bold); + ui.subjectText->setFont(font); + + ui.bcclabel->setVisible(false); + ui.bccText->setVisible(false); + ui.cclabel->setVisible(false); + ui.ccText->setVisible(false); + + ui.tagsLabel->setVisible(false); + + if (isControlled == false) { + processSettings("MessageWidget", true); + } + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +MessageWidget::~MessageWidget() +{ + if (isControlled == false) { + processSettings("MessageWidget", false); + } +} + +void MessageWidget::connectAction(enumActionType actionType, QToolButton* button) +{ + switch (actionType) { + case ACTION_REMOVE: + connect(button, SIGNAL(clicked()), this, SLOT(remove())); + break; + case ACTION_REPLY: + connect(button, SIGNAL(clicked()), this, SLOT(reply())); + break; + case ACTION_REPLY_ALL: + connect(button, SIGNAL(clicked()), this, SLOT(replyAll())); + break; + case ACTION_FORWARD: + connect(button, SIGNAL(clicked()), this, SLOT(forward())); + break; + case ACTION_PRINT: + connect(button, SIGNAL(clicked()), this, SLOT(print())); + break; + case ACTION_PRINT_PREVIEW: + connect(button, SIGNAL(clicked()), this, SLOT(printPreview())); + break; + case ACTION_SAVE_AS: + connect(button, SIGNAL(clicked()), this, SLOT(saveAs())); + break; + } +} + +void MessageWidget::connectAction(enumActionType actionType, QAction *action) +{ + switch (actionType) { + case ACTION_REMOVE: + connect(action, SIGNAL(triggered()), this, SLOT(remove())); + break; + case ACTION_REPLY: + connect(action, SIGNAL(triggered()), this, SLOT(reply())); + break; + case ACTION_REPLY_ALL: + connect(action, SIGNAL(triggered()), this, SLOT(replyAll())); + break; + case ACTION_FORWARD: + connect(action, SIGNAL(triggered()), this, SLOT(forward())); + break; + case ACTION_PRINT: + connect(action, SIGNAL(triggered()), this, SLOT(print())); + break; + case ACTION_PRINT_PREVIEW: + connect(action, SIGNAL(triggered()), this, SLOT(printPreview())); + break; + case ACTION_SAVE_AS: + connect(action, SIGNAL(triggered()), this, SLOT(saveAs())); + break; + } +} + +void MessageWidget::processSettings(const QString &settingsGroup, bool load) +{ + Settings->beginGroup(settingsGroup); + + if (load) { + // load settings + + // expandFiles + bool value = Settings->value("expandFiles", true).toBool(); + ui.expandFilesButton->setChecked(value); + ui.msgList->setVisible(value); + togglefileview(); + } else { + // save settings + + // expandFiles + Settings->setValue("expandFiles", ui.expandFilesButton->isChecked()); + } + + Settings->endGroup(); +} + +QString MessageWidget::subject(bool noEmpty) +{ + QString subject = ui.subjectText->text(); + if (subject.isEmpty() && noEmpty) { + return "[" + tr("No subject") + "]"; + } + + return subject; +} + +void MessageWidget::msgfilelistWidgetCostumPopupMenu( QPoint point ) +{ + QMenu contextMnu(this); + + contextMnu.addAction(QIcon(IMAGE_DOWNLOAD), tr("Download"), this, SLOT(getcurrentrecommended())); + contextMnu.addAction(QIcon(IMAGE_DOWNLOADALL), tr("Download all"), this, SLOT(getallrecommended())); + + contextMnu.exec(QCursor::pos()); +} + +void MessageWidget::togglefileview() +{ + /* if msg header visible -> change icon and tooltip + * three widgets... + */ + + if (ui.expandFilesButton->isChecked()) { + ui.expandFilesButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + ui.expandFilesButton->setToolTip(tr("Hide")); + } else { + ui.expandFilesButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + ui.expandFilesButton->setToolTip(tr("Expand")); + } +} + +/* download the recommendations... */ +void MessageWidget::getcurrentrecommended() +{ + MessageInfo msgInfo; + if (rsMsgs->getMessage(currMsgId, msgInfo) == false) { + return; + } + + std::list srcIds; + srcIds.push_back(msgInfo.srcId); + + QModelIndexList list = ui.msgList->selectionModel()->selectedIndexes(); + + std::map files ; + + for (QModelIndexList::const_iterator it(list.begin());it!=list.end();++it) { + FileInfo& fi(files[it->row()]) ; + + switch (it->column()) { + case COLUMN_FILE_NAME: + fi.fname = it->data().toString().toStdString() ; + break ; + case COLUMN_FILE_SIZE: + fi.size = it->data().toULongLong() ; + break ; + case COLUMN_FILE_HASH: + fi.hash = it->data().toString().toStdString() ; + break ; + } + } + + for(std::map::const_iterator it(files.begin());it!=files.end();++it) { + const FileInfo& fi(it->second) ; + std::cout << "Requesting file " << fi.fname << ", size=" << fi.size << ", hash=" << fi.hash << std::endl ; + + if (rsFiles->FileRequest(fi.fname, fi.hash, fi.size, "", RS_FILE_HINTS_NETWORK_WIDE, srcIds) == false) { + QMessageBox mb(QObject::tr("File Request canceled"), QObject::tr("The following has not been added to your download list, because you already have it:\n ") + QString::fromStdString(fi.fname), QMessageBox::Critical, QMessageBox::Ok, 0, 0); + mb.setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + mb.exec(); + } + } +} + +void MessageWidget::getallrecommended() +{ + /* get Message */ + MessageInfo msgInfo; + if (rsMsgs->getMessage(currMsgId, msgInfo) == false) { + return; + } + + const std::list &recList = msgInfo.files; + std::list::const_iterator it; + + /* do the requests */ + for(it = recList.begin(); it != recList.end(); it++) { + std::cerr << "MessageWidget::getallrecommended() Calling File Request" << std::endl; + std::list srcIds; + srcIds.push_back(msgInfo.srcId); + rsFiles->FileRequest(it->fname, it->hash, it->size, "", RS_FILE_HINTS_NETWORK_WIDE, srcIds); + } +} + +void MessageWidget::messagesTagsChanged() +{ + showTagLabels(); +} + +void MessageWidget::messagesChanged() +{ + if (isControlled) { + /* processed by MessagesDialog */ + return; + } + + /* test Message */ + MessageInfo msgInfo; + if (rsMsgs->getMessage(currMsgId, msgInfo) == false) { + /* messages was removed */ + if (isWindow) { + window()->close(); + } else { + deleteLater(); + } + } +} + +void MessageWidget::clearTagLabels() +{ + /* clear all tags */ + while (tagLabels.size()) { + delete tagLabels.front(); + tagLabels.pop_front(); + } + while (ui.tagLayout->count()) { + delete ui.tagLayout->takeAt(0); + } + + ui.tagsLabel->setVisible(false); +} + +void MessageWidget::showTagLabels() +{ + clearTagLabels(); + + if (currMsgId.empty()) { + return; + } + + MsgTagInfo tagInfo; + rsMsgs->getMessageTag(currMsgId, tagInfo); + + if (tagInfo.tagIds.empty() == false) { + ui.tagsLabel->setVisible(true); + + MsgTagType Tags; + rsMsgs->getMessageTagTypes(Tags); + + std::map >::iterator Tag; + for (std::list::iterator tagId = tagInfo.tagIds.begin(); tagId != tagInfo.tagIds.end(); tagId++) { + Tag = Tags.types.find(*tagId); + if (Tag != Tags.types.end()) { + QLabel *tagLabel = new QLabel(TagDefs::name(Tag->first, Tag->second.first), this); + tagLabel->setMaximumHeight(16); + tagLabel->setStyleSheet(TagDefs::labelStyleSheet(Tag->second.second)); + tagLabels.push_back(tagLabel); + ui.tagLayout->addWidget(tagLabel); + ui.tagLayout->addSpacing(3); + } + } + ui.tagLayout->addStretch(); + } else { + ui.tagsLabel->setVisible(false); + } +} + +void MessageWidget::fill(const std::string &msgId) +{ + if (currMsgId == msgId) { + // message doesn't changed + return; + } + + currMsgId = msgId; + + if (currMsgId.empty()) { + /* blank it */ + ui.dateText-> setText(""); + ui.toText->setText(""); + ui.fromText->setText(""); + ui.filesText->setText(""); + + ui.cclabel->setVisible(false); + ui.ccText->setVisible(false); + ui.ccText->clear(); + + ui.bcclabel->setVisible(false); + ui.bccText->setVisible(false); + ui.bccText->clear(); + + ui.subjectText->setText(""); + ui.msgList->clear(); + ui.msgText->clear(); + + clearTagLabels(); + + return; + } + + clearTagLabels(); + + MessageInfo msgInfo; + if (rsMsgs->getMessage(currMsgId, msgInfo) == false) { + std::cerr << "MessageWidget::fill() Couldn't find Msg" << std::endl; + return; + } + + const std::list &recList = msgInfo.files; + std::list::const_iterator it; + + ui.msgList->clear(); + + QList items; + for (it = recList.begin(); it != recList.end(); it++) { + QTreeWidgetItem *item = new QTreeWidgetItem; + item->setText(COLUMN_FILE_NAME, QString::fromStdString(it->fname)); + item->setText(COLUMN_FILE_SIZE, QString::number(it->size)); + item->setText(COLUMN_FILE_HASH, QString::fromStdString(it->hash)); + + /* add to the list */ + items.append(item); + } + + /* add the items in! */ + ui.msgList->insertTopLevelItems(0, items); + + /* iterate through the sources */ + std::list::const_iterator pit; + + RetroShareLink link; + QString text; + + for(pit = msgInfo.msgto.begin(); pit != msgInfo.msgto.end(); pit++) { + if (link.createMessage(*pit, "")) { + text += link.toHtml() + " "; + } + } + ui.toText->setText(text); + + if (msgInfo.msgcc.size() > 0) { + ui.cclabel->setVisible(true); + ui.ccText->setVisible(true); + + text.clear(); + for(pit = msgInfo.msgcc.begin(); pit != msgInfo.msgcc.end(); pit++) { + if (link.createMessage(*pit, "")) { + text += link.toHtml() + " "; + } + } + ui.ccText->setText(text); + } else { + ui.cclabel->setVisible(false); + ui.ccText->setVisible(false); + ui.ccText->clear(); + } + + if (msgInfo.msgbcc.size() > 0) { + ui.bcclabel->setVisible(true); + ui.bccText->setVisible(true); + + text.clear(); + for(pit = msgInfo.msgbcc.begin(); pit != msgInfo.msgbcc.end(); pit++) { + if (link.createMessage(*pit, "")) { + text += link.toHtml() + " "; + } + } + ui.bccText->setText(text); + } else { + ui.bcclabel->setVisible(false); + ui.bccText->setVisible(false); + ui.bccText->clear(); + } + + { + QDateTime qtime; + qtime.setTime_t(msgInfo.ts); + QString timestamp = qtime.toString("dd.MM.yyyy hh:mm:ss"); + ui.dateText->setText(timestamp); + } + + std::string srcId; + if ((msgInfo.msgflags & RS_MSG_BOXMASK) == RS_MSG_OUTBOX) { + // outgoing message are from me + srcId = rsPeers->getOwnId(); + } else { + srcId = msgInfo.srcId; + } + link.createMessage(srcId, ""); + + ui.fromText->setText(link.toHtml()); + ui.fromText->setToolTip(PeerDefs::rsidFromId(srcId)); + + ui.subjectText->setText(QString::fromStdWString(msgInfo.title)); + + text = RsHtml::formatText(QString::fromStdWString(msgInfo.msg), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); + ui.msgText->setHtml(text); + + ui.filesText->setText(QString("(%1 %2)").arg(msgInfo.count).arg(msgInfo.count == 1 ? tr("File") : tr("Files"))); + + showTagLabels(); +} + +void MessageWidget::remove() +{ + MessageInfo msgInfo; + if (rsMsgs->getMessage(currMsgId, msgInfo) == false) { + std::cerr << "MessageWidget::fill() Couldn't find Msg" << std::endl; + return; + } + + bool deleteReal = false; + if (msgInfo.msgflags & RS_MSG_TRASH) { + deleteReal = true; + } else { + if (QApplication::keyboardModifiers() & Qt::ShiftModifier) { + deleteReal = true; + } + } + + if (deleteReal) { + rsMsgs->MessageDelete(currMsgId); + } else { + rsMsgs->MessageToTrash(currMsgId, true); + } + + if (isWindow) { + window()->close(); + } else { + deleteLater(); + } +} + +void MessageWidget::print() +{ +#ifndef QT_NO_PRINTER + QPrinter printer(QPrinter::HighResolution); + printer.setFullPage(true); + QPrintDialog *dlg = new QPrintDialog(&printer, this); + if (ui.msgText->textCursor().hasSelection()) + dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection); + dlg->setWindowTitle(tr("Print Document")); + if (dlg->exec() == QDialog::Accepted) { + ui.msgText->print(&printer); + } + delete dlg; +#endif +} + +void MessageWidget::printPreview() +{ + PrintPreview *preview = new PrintPreview(ui.msgText->document(), this); + preview->setWindowModality(Qt::WindowModal); + preview->setAttribute(Qt::WA_DeleteOnClose); + preview->show(); + + /* window will destroy itself! */ +} + +void MessageWidget::saveAs() +{ + QString filename; + if (misc::getSaveFileName(window(), RshareSettings::LASTDIR_MESSAGES, tr("Save as..."), tr("HTML-Files (*.htm *.html);;All Files (*)"), filename)) { + QFile file(filename); + if (!file.open(QFile::WriteOnly)) + return; + QTextStream ts(&file); + ts.setCodec(QTextCodec::codecForName("UTF-8")); + ts << ui.msgText->document()->toHtml("UTF-8"); + ui.msgText->document()->setModified(false); + } +} + +void MessageWidget::reply() +{ + /* put msg on msgBoard, and switch to it. */ + + if (currMsgId.empty()) { + return; + } + + MessageComposer *msgComposer = MessageComposer::replyMsg(currMsgId, false); + if (msgComposer == NULL) { + return; + } + + msgComposer->show(); + msgComposer->activateWindow(); + + /* window will destroy itself! */ +} + +void MessageWidget::replyAll() +{ + /* put msg on msgBoard, and switch to it. */ + + if (currMsgId.empty()) { + return; + } + + MessageComposer *msgComposer = MessageComposer::replyMsg(currMsgId, true); + if (msgComposer == NULL) { + return; + } + + msgComposer->show(); + msgComposer->activateWindow(); + + /* window will destroy itself! */ +} + +void MessageWidget::forward() +{ + /* put msg on msgBoard, and switch to it. */ + + if (currMsgId.empty()) { + return; + } + + MessageComposer *msgComposer = MessageComposer::forwardMsg(currMsgId); + if (msgComposer == NULL) { + return; + } + + msgComposer->show(); + msgComposer->activateWindow(); + + /* window will destroy itself! */ +} diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.h b/retroshare-gui/src/gui/msgs/MessageWidget.h new file mode 100644 index 000000000..07fb4cc4e --- /dev/null +++ b/retroshare-gui/src/gui/msgs/MessageWidget.h @@ -0,0 +1,93 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2011, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _MESSAGEWIDGET_H +#define _MESSAGEWIDGET_H + +#include +#include "ui_MessageWidget.h" + +class QToolButton; +class QAction; +class QTextEdit; + +class MessageWidget : public QWidget +{ + Q_OBJECT + +public: + enum enumActionType { + ACTION_REMOVE, + ACTION_REPLY, + ACTION_REPLY_ALL, + ACTION_FORWARD, + ACTION_PRINT, + ACTION_PRINT_PREVIEW, + ACTION_SAVE_AS + }; + +public: + MessageWidget(bool controlled, QWidget *parent = 0, Qt::WFlags flags = 0); + ~MessageWidget(); + + static MessageWidget *openMsg(const std::string &msgId, bool window); + + std::string msgId() { return currMsgId; } + void connectAction(enumActionType actionType, QToolButton* button); + void connectAction(enumActionType actionType, QAction* action); + + void fill(const std::string &msgId); + void processSettings(const QString &settingsGroup, bool load); + + QString subject(bool noEmpty); + +private slots: + void reply(); + void replyAll(); + void forward(); + void remove(); + void print(); + void printPreview(); + void saveAs(); + + void msgfilelistWidgetCostumPopupMenu(QPoint); + void messagesTagsChanged(); + void messagesChanged(); + + void togglefileview(); + void getcurrentrecommended(); + void getallrecommended(); + +private: + void clearTagLabels(); + void showTagLabels(); + + bool isControlled; + bool isWindow; + std::string currMsgId; + + QList tagLabels; + + /** Qt Designer generated object */ + Ui::MessageWidget ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.ui b/retroshare-gui/src/gui/msgs/MessageWidget.ui new file mode 100644 index 000000000..75432a2c6 --- /dev/null +++ b/retroshare-gui/src/gui/msgs/MessageWidget.ui @@ -0,0 +1,505 @@ + + + MessageWidget + + + + 0 + 0 + 698 + 539 + + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + 2 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + true + + + true + + + + + + + + + 0 + + + 6 + + + + + + + + :/images/attachment.png + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + + + + + + + + 10 + true + + + + + + + + + + + + + Qt::Horizontal + + + + 351 + 20 + + + + + + + + Qt::NoFocus + + + Download all Recommended Files + + + + :/images/down.png:/images/down.png + + + + + + + Qt::NoFocus + + + + + + + :/images/edit_remove24.png:/images/edit_remove24.png + + + true + + + true + + + + + + + + + 6 + + + 0 + + + 6 + + + 0 + + + + + 6 + + + 3 + + + + + + 0 + 0 + + + + + 9 + 50 + false + + + + Subject: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 9 + 50 + false + + + + From: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 2 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 9 + + + + true + + + true + + + + + + + + 0 + 0 + + + + + 9 + 50 + false + + + + To: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + true + + + true + + + + + + + + 0 + 0 + + + + + 9 + 50 + false + + + + Cc: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 0 + 0 + + + + + 9 + 50 + false + + + + Bcc: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + true + + + true + + + + + + + true + + + true + + + + + + + + 0 + 0 + + + + + 9 + 50 + false + + + + Tags: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + 0 + 0 + + + + + 9 + + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + + 9 + + + + Qt::LeftToRight + + + Date + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + + + + + + + 9 + + + + Qt::CustomContextMenu + + + true + + + true + + + + File Name + + + + + Size + + + + + Hash + + + + + + + + + Print + + + + + Print Preview + + + + + + + + + expandFilesButton + clicked(bool) + msgList + setVisible(bool) + + + 672 + 334 + + + 348 + 432 + + + + + diff --git a/retroshare-gui/src/gui/msgs/MessageWindow.cpp b/retroshare-gui/src/gui/msgs/MessageWindow.cpp new file mode 100644 index 000000000..d4e721790 --- /dev/null +++ b/retroshare-gui/src/gui/msgs/MessageWindow.cpp @@ -0,0 +1,229 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2011 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "MessageWindow.h" +#include "MessageWidget.h" +#include "MessageComposer.h" +#include "TagsMenu.h" +#include "gui/settings/rsharesettings.h" + +#include + +/** Constructor */ +MessageWindow::MessageWindow(QWidget *parent, Qt::WFlags flags) +: RWindow("MessageWindow", parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + actionSaveAs = NULL; + actionPrint = NULL; + actionPrintPreview = NULL; + + setupFileActions(); + + connect(ui.newmessageButton, SIGNAL(clicked()), this, SLOT(newmessage())); + + connect(ui.actionTextBesideIcon, SIGNAL(triggered()), this, SLOT(buttonStyle())); + connect(ui.actionIconOnly, SIGNAL(triggered()), this, SLOT(buttonStyle())); + connect(ui.actionTextUnderIcon, SIGNAL(triggered()), this, SLOT(buttonStyle())); + + ui.actionTextBesideIcon->setData(Qt::ToolButtonTextBesideIcon); + ui.actionIconOnly->setData(Qt::ToolButtonIconOnly); + ui.actionTextUnderIcon->setData(Qt::ToolButtonTextUnderIcon); + + msgWidget = NULL; + + // create tag menu + TagsMenu *menu = new TagsMenu (tr("Tags"), this); + connect(menu, SIGNAL(aboutToShow()), this, SLOT(tagAboutToShow())); + connect(menu, SIGNAL(tagSet(int, bool)), this, SLOT(tagSet(int, bool))); + connect(menu, SIGNAL(tagRemoveAll()), this, SLOT(tagRemoveAll())); + + ui.tagButton->setMenu(menu); + + // create print menu + QMenu *printmenu = new QMenu(); + printmenu->addAction(ui.actionPrint); + printmenu->addAction(ui.actionPrint_Preview); + ui.printbutton->setMenu(printmenu); + + // create view menu + QMenu *viewmenu = new QMenu(); + viewmenu->addAction(ui.actionTextBesideIcon); + viewmenu->addAction(ui.actionIconOnly); + //viewmenu->addAction(ui.actionTextUnderIcon); + ui.viewtoolButton->setMenu(viewmenu); + + processSettings(true); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +MessageWindow::~MessageWindow() +{ + processSettings(false); +} + +void MessageWindow::processSettings(bool load) +{ + Settings->beginGroup(QString("MessageDialog")); + + if (load) { + // load settings + + /* toolbar button style */ + Qt::ToolButtonStyle style = (Qt::ToolButtonStyle) Settings->value("ToolButon_Stlye", Qt::ToolButtonIconOnly).toInt(); + setToolbarButtonStyle(style); + } else { + // save settings + + /* toolbar button style */ + Settings->setValue("ToolButon_Stlye", ui.newmessageButton->toolButtonStyle()); + } + + Settings->endGroup(); +} + +void MessageWindow::addWidget(MessageWidget *widget) +{ + if (msgWidget) { + delete(msgWidget); + } + + msgWidget = widget; + if (msgWidget) { + ui.msgLayout->addWidget(msgWidget); + setWindowTitle(msgWidget->subject(true)); + + msgWidget->connectAction(MessageWidget::ACTION_REMOVE, ui.removemessageButton); + msgWidget->connectAction(MessageWidget::ACTION_REPLY, ui.replymessageButton); + msgWidget->connectAction(MessageWidget::ACTION_REPLY_ALL, ui.replyallmessageButton); + msgWidget->connectAction(MessageWidget::ACTION_FORWARD, ui.forwardmessageButton); + msgWidget->connectAction(MessageWidget::ACTION_PRINT, ui.printbutton); + msgWidget->connectAction(MessageWidget::ACTION_PRINT, ui.actionPrint); + msgWidget->connectAction(MessageWidget::ACTION_PRINT, actionPrint); + msgWidget->connectAction(MessageWidget::ACTION_PRINT_PREVIEW, ui.actionPrint_Preview); + msgWidget->connectAction(MessageWidget::ACTION_PRINT_PREVIEW, actionPrintPreview); +// msgWidget->connectAction(ACTION_SAVE, + msgWidget->connectAction(MessageWidget::ACTION_SAVE_AS, actionSaveAs); + } else { + setWindowTitle(""); + } +} + +void MessageWindow::newmessage() +{ + MessageComposer *msgComposer = MessageComposer::newMsg(); + if (msgComposer == NULL) { + return; + } + + /* fill it in */ + msgComposer->show(); + msgComposer->activateWindow(); + + /* window will destroy itself! */ +} + +void MessageWindow::tagAboutToShow() +{ + if (msgWidget == NULL) { + return; + } + + TagsMenu *menu = dynamic_cast(ui.tagButton->menu()); + if (menu == NULL) { + return; + } + + // activate actions + MsgTagInfo tagInfo; + rsMsgs->getMessageTag(msgWidget->msgId(), tagInfo); + + menu->activateActions(tagInfo.tagIds); +} + +void MessageWindow::tagRemoveAll() +{ + if (msgWidget == NULL) { + return; + } + + rsMsgs->setMessageTag(msgWidget->msgId(), 0, false); +} + +void MessageWindow::tagSet(int tagId, bool set) +{ + if (msgWidget == NULL) { + return; + } + + if (tagId == 0) { + return; + } + + rsMsgs->setMessageTag(msgWidget->msgId(), tagId, set); +} + +void MessageWindow::setupFileActions() +{ + QMenu *menu = new QMenu(tr("&File"), this); + menuBar()->addMenu(menu); + + actionSaveAs = menu->addAction(tr("Save &As File")); + actionPrint = menu->addAction(QIcon(":/images/textedit/fileprint.png"), tr("&Print...")); + actionPrint->setShortcut(QKeySequence::Print); + + actionPrintPreview = menu->addAction(QIcon(":/images/textedit/fileprint.png"), tr("Print Preview...")); + +// a = new QAction(QIcon(":/images/textedit/exportpdf.png"), tr("&Export PDF..."), this); +// a->setShortcut(Qt::CTRL + Qt::Key_D); +// connect(a, SIGNAL(triggered()), this, SLOT(filePrintPdf())); +// menu->addAction(a); + + menu->addSeparator(); + + QAction *action = menu->addAction(tr("&Quit"), this, SLOT(close())); + action->setShortcut(Qt::CTRL + Qt::Key_Q); +} + +void MessageWindow::setToolbarButtonStyle(Qt::ToolButtonStyle style) +{ + ui.newmessageButton->setToolButtonStyle(style); + ui.removemessageButton->setToolButtonStyle(style); + ui.replymessageButton->setToolButtonStyle(style); + ui.replyallmessageButton->setToolButtonStyle(style); + ui.forwardmessageButton->setToolButtonStyle(style); + ui.tagButton->setToolButtonStyle(style); + ui.printbutton->setToolButtonStyle(style); + ui.viewtoolButton->setToolButtonStyle(style); +} + +void MessageWindow::buttonStyle() +{ + setToolbarButtonStyle((Qt::ToolButtonStyle) dynamic_cast(sender())->data().toInt()); +} diff --git a/retroshare-gui/src/gui/msgs/MessageWindow.h b/retroshare-gui/src/gui/msgs/MessageWindow.h new file mode 100644 index 000000000..40217f9f5 --- /dev/null +++ b/retroshare-gui/src/gui/msgs/MessageWindow.h @@ -0,0 +1,64 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2011, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _MESSAGEWINDOW_H +#define _MESSAGEWINDOW_H + +#include "gui/common/rwindow.h" +#include "ui_MessageWindow.h" + +class MessageWidget; + +class MessageWindow : public RWindow +{ + Q_OBJECT + +public: + /** Default Constructor */ + + MessageWindow(QWidget *parent = 0, Qt::WFlags flags = 0); + ~MessageWindow(); + + void addWidget(MessageWidget *widget); + +private slots: + void newmessage(); + void tagAboutToShow(); + void tagSet(int tagId, bool set); + void tagRemoveAll(); + + void buttonStyle(); + +private: + void setupFileActions(); + void processSettings(bool load); + void setToolbarButtonStyle(Qt::ToolButtonStyle style); + + MessageWidget *msgWidget; + QAction *actionSaveAs; + QAction *actionPrint; + QAction *actionPrintPreview; + + /** Qt Designer generated object */ + Ui::MessageWindow ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/msgs/MessageWindow.ui b/retroshare-gui/src/gui/msgs/MessageWindow.ui new file mode 100644 index 000000000..53fbde101 --- /dev/null +++ b/retroshare-gui/src/gui/msgs/MessageWindow.ui @@ -0,0 +1,400 @@ + + + MessageWindow + + + + 0 + 0 + 698 + 539 + + + + + :/images/rstray3.png:/images/rstray3.png + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 36 + + + + + 0 + 68 + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 6 + + + + + Qt::NoFocus + + + New Message + + + Compose + + + + :/images/folder-draft24.png:/images/folder-draft24.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + Qt::Vertical + + + + + + + Qt::NoFocus + + + Reply to selected message + + + Reply + + + + :/images/replymail-pressed.png:/images/replymail-pressed.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + Qt::NoFocus + + + Reply all to selected message + + + Reply all + + + + :/images/replymailall24-hover.png:/images/replymailall24-hover.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + + 0 + 0 + + + + + 16777 + 16777 + + + + Qt::NoFocus + + + Forward selected message + + + Foward + + + + :/images/mailforward24-hover.png:/images/mailforward24-hover.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + Qt::Vertical + + + + + + + Qt::NoFocus + + + Remove selected message + + + Delete + + + + :/images/deletemail24.png:/images/deletemail24.png + + + + 24 + 24 + + + + Qt::ToolButtonIconOnly + + + true + + + + + + + Qt::NoFocus + + + Print selected message + + + Print + + + + :/images/print24.png:/images/print24.png + + + + 24 + 24 + + + + QToolButton::MenuButtonPopup + + + Qt::ToolButtonIconOnly + + + true + + + + + + + Qt::NoFocus + + + Display + + + + :/images/looknfeel.png:/images/looknfeel.png + + + + 24 + 24 + + + + QToolButton::MenuButtonPopup + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::NoFocus + + + Tags + + + Tags + + + + :/images/tag24.png:/images/tag24.png + + + + 24 + 24 + + + + QToolButton::MenuButtonPopup + + + true + + + + + + + + + + + + + + + + 0 + 0 + 698 + 20 + + + + + + Print + + + + + Print Preview + + + + + Buttons Icon Only + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + Buttons with Text + + + + + Buttons Text Under Icon + + + Set Text Under Icon + + + + + + + + diff --git a/retroshare-gui/src/gui/msgs/TagsMenu.cpp b/retroshare-gui/src/gui/msgs/TagsMenu.cpp new file mode 100644 index 000000000..cc4fcc181 --- /dev/null +++ b/retroshare-gui/src/gui/msgs/TagsMenu.cpp @@ -0,0 +1,199 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include + +#include + +#include "TagsMenu.h" +#include "gui/common/TagDefs.h" +#include "gui/settings/NewTag.h" +#include "gui/notifyqt.h" + +#define ACTION_TAGSINDEX_SIZE 3 +#define ACTION_TAGSINDEX_TYPE "Type" +#define ACTION_TAGSINDEX_ID "ID" +#define ACTION_TAGSINDEX_COLOR "Color" + +#define ACTION_TAGS_REMOVEALL 0 +#define ACTION_TAGS_TAG 1 +#define ACTION_TAGS_NEWTAG 2 + +TagsMenu::TagsMenu(const QString &title, QWidget *parent) + : QMenu (title, parent) +{ + connect(this, SIGNAL(triggered (QAction*)), this, SLOT(tagTriggered(QAction*))); + connect(NotifyQt::getInstance(), SIGNAL(messagesTagsChanged()), this, SLOT(fillTags())); + + fillTags(); +} + +void TagsMenu::paintEvent(QPaintEvent *e) +{ + QMenu::paintEvent(e); + + QPainter p(this); + QRegion emptyArea = QRegion(rect()); + + //draw the items with color + foreach (QAction *action, actions()) { + QRect adjustedActionRect = actionGeometry(action); + if (!e->rect().intersects(adjustedActionRect)) + continue; + + const QMap &values = action->data().toMap(); + if (values.size () != ACTION_TAGSINDEX_SIZE) { + continue; + } + if (values [ACTION_TAGSINDEX_TYPE] != ACTION_TAGS_TAG) { + continue; + } + + //set the clip region to be extra safe (and adjust for the scrollers) + QRegion adjustedActionReg(adjustedActionRect); + emptyArea -= adjustedActionReg; + p.setClipRegion(adjustedActionReg); + + QStyleOptionMenuItem opt; + initStyleOption(&opt, action); + + opt.palette.setColor(QPalette::ButtonText, QColor(values [ACTION_TAGSINDEX_COLOR].toInt())); + // needed for Cleanlooks + opt.palette.setColor(QPalette::Text, QColor(values [ACTION_TAGSINDEX_COLOR].toInt())); + + opt.rect = adjustedActionRect; + style()->drawControl(QStyle::CE_MenuItem, &opt, &p, this); + } +} + +void TagsMenu::fillTags() +{ + clear(); + + MsgTagType tags; + rsMsgs->getMessageTagTypes(tags); + std::map >::iterator tag; + + bool user = false; + + QString text; + QAction *action; + QMap values; + + if (tags.types.size()) { + action = new QAction(tr("Remove All Tags"), this); + values [ACTION_TAGSINDEX_TYPE] = ACTION_TAGS_REMOVEALL; + values [ACTION_TAGSINDEX_ID] = 0; + values [ACTION_TAGSINDEX_COLOR] = 0; + action->setData (values); + addAction(action); + + addSeparator(); + + for (tag = tags.types.begin(); tag != tags.types.end(); tag++) { + text = TagDefs::name(tag->first, tag->second.first); + + action = new QAction(text, this); + values [ACTION_TAGSINDEX_TYPE] = ACTION_TAGS_TAG; + values [ACTION_TAGSINDEX_ID] = tag->first; + values [ACTION_TAGSINDEX_COLOR] = QRgb(tag->second.second); + action->setData (values); + action->setCheckable(true); + + if (tag->first >= RS_MSGTAGTYPE_USER && user == false) { + user = true; + addSeparator(); + } + + addAction(action); + } + + addSeparator(); + } + + action = new QAction(tr("New tag ..."), this); + values [ACTION_TAGSINDEX_TYPE] = ACTION_TAGS_NEWTAG; + values [ACTION_TAGSINDEX_ID] = 0; + values [ACTION_TAGSINDEX_COLOR] = 0; + action->setData (values); + addAction(action); +} + +void TagsMenu::activateActions(std::list& tagIds) +{ + foreach(QObject *object, children()) { + QAction *action = qobject_cast (object); + if (action == NULL) { + continue; + } + + const QMap &values = action->data().toMap(); + if (values.size () != ACTION_TAGSINDEX_SIZE) { + continue; + } + if (values [ACTION_TAGSINDEX_TYPE] != ACTION_TAGS_TAG) { + continue; + } + + std::list::iterator tagId = std::find(tagIds.begin(), tagIds.end(), values [ACTION_TAGSINDEX_ID]); + action->setChecked(tagId != tagIds.end()); + } +} + +void TagsMenu::tagTriggered(QAction *action) +{ + if (action == NULL) { + return; + } + + const QMap &values = action->data().toMap(); + if (values.size () != ACTION_TAGSINDEX_SIZE) { + return; + } + + if (values [ACTION_TAGSINDEX_TYPE] == ACTION_TAGS_REMOVEALL) { + // remove all tags + emit tagRemoveAll(); + } else if (values [ACTION_TAGSINDEX_TYPE] == ACTION_TAGS_NEWTAG) { + // new tag + MsgTagType tags; + rsMsgs->getMessageTagTypes(tags); + + NewTag tagDlg(tags); + if (tagDlg.exec() == QDialog::Accepted && tagDlg.m_nId) { + std::map >::iterator tag = tags.types.find(tagDlg.m_nId); + if (tag != tags.types.end()) { + if (rsMsgs->setMessageTagType(tag->first, tag->second.first, tag->second.second)) { + emit tagSet(tagDlg.m_nId, true); + } + } + } + } else if (values [ACTION_TAGSINDEX_TYPE].toInt() == ACTION_TAGS_TAG) { + int tagId = values [ACTION_TAGSINDEX_ID].toInt(); + if (tagId) { + emit tagSet(tagId, action->isChecked()); + } + } +} diff --git a/retroshare-gui/src/gui/msgs/TagsMenu.h b/retroshare-gui/src/gui/msgs/TagsMenu.h new file mode 100644 index 000000000..80a56cbdd --- /dev/null +++ b/retroshare-gui/src/gui/msgs/TagsMenu.h @@ -0,0 +1,50 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2007, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _TAGSMENU_H +#define _TAGSMENU_H + +#include + +#include + +class TagsMenu : public QMenu +{ + Q_OBJECT + +public: + TagsMenu(const QString &title, QWidget *parent); + + void activateActions(std::list& tagIds); + +signals: + void tagSet(int tagId, bool set); + void tagRemoveAll(); + +protected: + virtual void paintEvent(QPaintEvent *e); + +private slots: + void fillTags(); + void tagTriggered(QAction *action); +}; + +#endif diff --git a/retroshare-gui/src/gui/msgs/textformat.h b/retroshare-gui/src/gui/msgs/textformat.h new file mode 100644 index 000000000..dcc55035b --- /dev/null +++ b/retroshare-gui/src/gui/msgs/textformat.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * This file is distributed under the following license: * + * Copyright (c) 2006-2010 RetroShare Team * + * Copyright (C) 2008-2009 Mehrdad Momeny * + * Copyright (C) 2008-2009 Golnaz Nilieh * + * * + * It is a modified version of "bilbotextformat.h", which was part * + * of the Bilbo Blogger. It has been customized for * + * use in RetroShare, at January 2010. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef TEXTFORMAT_H +#define TEXTFORMAT_H + +#include + +/** + * Adds some textformat attributes which don't exist in QTextFormat class. + * this class may be removed in future, if all editor related staff be ordered as a lib. + * + @author Mehrdad Momeny + @author Golnaz Nilieh +*/ +// class TextCharFormat : public QTextCharFormat + +class TextFormat +{ +public: + + enum Property { + /// Anchor properties + AnchorTitle = 0x100010, + AnchorTarget = 0x100011, + + /// Image properties + ImageTitle = 0x100020, + ImageAlternateText = 0x100021, + + HasCodeStyle = 0x100030, + + /// Block Properties + HtmlHeading = 0x100040, //zero if block is not in heading format, 1 for Heading 1, and so on. + IsBlockQuote = 0x100041, + + IsHtmlTagSign = 0x100042, + }; + +}; + +#endif diff --git a/retroshare-gui/src/gui/notifyqt.cpp b/retroshare-gui/src/gui/notifyqt.cpp new file mode 100644 index 000000000..2e91e8b58 --- /dev/null +++ b/retroshare-gui/src/gui/notifyqt.cpp @@ -0,0 +1,817 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *************************************************************************/ + +#include +#include +#include +//#include +#include + +#include "notifyqt.h" +#include +#include +#include +#include +#ifdef TURTLE_HOPPING +#include +#endif + +#include "RsAutoUpdatePage.h" + +#ifndef MINIMAL_RSGUI +#include "MainWindow.h" +#include "toaster/OnlineToaster.h" +#include "toaster/MessageToaster.h" +#include "toaster/DownloadToaster.h" +#endif // MINIMAL_RSGUI + +#include "gui/settings/rsharesettings.h" + +#include +#include +#include + +/***** + * #define NOTIFY_DEBUG + ****/ + +class Toaster +{ +public: + Toaster(QWidget *widget) + { + this->widget = widget; + + /* Standard values */ + timeToShow = 500; + timeToLive = 3000; + timeToHide = 500; + + /* Calculated values */ + elapsedTimeToShow = 0; + elapsedTimeToLive = 0; + elapsedTimeToHide = 0; + } + +public: + QWidget *widget; + + /* Standard values */ + int timeToShow; + int timeToLive; + int timeToHide; + + /* Calculated values */ + QPoint startPos; + QPoint endPos; + int elapsedTimeToShow; + int elapsedTimeToLive; + int elapsedTimeToHide; +}; + +/*static*/ NotifyQt *NotifyQt::_instance = NULL; + +/*static*/ NotifyQt *NotifyQt::Create () +{ + if (_instance == NULL) { + _instance = new NotifyQt (); + } + + return _instance; +} + +/*static*/ NotifyQt *NotifyQt::getInstance () +{ + return _instance; +} + +NotifyQt::NotifyQt() : cDialog(NULL) +{ + runningToasterTimer = new QTimer(this); + connect(runningToasterTimer, SIGNAL(timeout()), this, SLOT(runningTick())); + runningToasterTimer->setInterval(10); // tick 100 times a second + runningToasterTimer->setSingleShot(true); +} + +void NotifyQt::notifyErrorMsg(int list, int type, std::string msg) +{ + emit errorOccurred(list,type,QString::fromStdString(msg)) ; +} + +void NotifyQt::notifyOwnAvatarChanged() +{ + #ifdef NOTIFY_DEBUG + std::cerr << "Notifyqt:: notified that own avatar changed" << std::endl ; + #endif + emit ownAvatarChanged() ; +} + +std::string NotifyQt::askForPassword(const std::string& key_details,bool prev_is_bad) +{ + RsAutoUpdatePage::lockAllEvents() ; + + QInputDialog dialog; + dialog.setWindowTitle(tr("GPG key passphrase")); + dialog.setLabelText((prev_is_bad?tr("Wrong password !") + "\n\n" : QString()) + + tr("Please enter the password to unlock the following GPG key:") + "\n" + QString::fromStdString(key_details)); + dialog.setTextEchoMode(QLineEdit::Password); + dialog.setWindowIcon(QIcon(":/images/rstray3.png")); + + int ret = dialog.exec(); + + RsAutoUpdatePage::unlockAllEvents() ; + + if (ret) { + return dialog.textValue().toStdString(); + } + + return ""; +} + +void NotifyQt::notifyDiscInfoChanged() +{ +#ifdef NOTIFY_DEBUG + std::cerr << "Notifyqt:: notified that discoveryInfo changed" << std::endl ; +#endif + + emit discInfoChanged() ; +} + +void NotifyQt::notifyDownloadComplete(const std::string& fileHash) +{ +#ifdef NOTIFY_DEBUG + std::cerr << "Notifyqt::notifyDownloadComplete notified that a download is completed" << std::endl; +#endif + + emit downloadComplete(QString::fromStdString(fileHash)); +} + +void NotifyQt::notifyDownloadCompleteCount(uint32_t count) +{ + std::cerr << "Notifyqt::notifyDownloadCompleteCount " << count << std::endl; + + emit downloadCompleteCountChanged(count); +} + +void NotifyQt::notifyDiskFull(uint32_t loc,uint32_t size_in_mb) +{ + std::cerr << "Notifyqt:: notified that disk is full" << std::endl ; + + emit diskFull(loc,size_in_mb) ; +} + +/* peer has changed the state */ +void NotifyQt::notifyPeerStatusChanged(const std::string& peer_id, uint32_t state) +{ + #ifdef NOTIFY_DEBUG + std::cerr << "Notifyqt:: notified that peer " << peer_id << " has changed the state to " << state << std::endl; + #endif + + emit peerStatusChanged(QString::fromStdString(peer_id), state); +} + +/* one or more peers has changed the states */ +void NotifyQt::notifyPeerStatusChangedSummary() +{ + #ifdef NOTIFY_DEBUG + std::cerr << "Notifyqt:: notified that one peer has changed the state" << std::endl; + #endif + + emit peerStatusChangedSummary(); +} + +void NotifyQt::notifyChannelMsgReadSatusChanged(const std::string& channelId, const std::string& msgId, uint32_t status) +{ + emit channelMsgReadSatusChanged(QString::fromStdString(channelId), QString::fromStdString(msgId), status); +} + +void NotifyQt::notifyOwnStatusMessageChanged() +{ + #ifdef NOTIFY_DEBUG + std::cerr << "Notifyqt:: notified that own avatar changed" << std::endl ; + #endif + emit ownStatusMessageChanged() ; +} + +void NotifyQt::notifyPeerHasNewAvatar(std::string peer_id) +{ + #ifdef NOTIFY_DEBUG + std::cerr << "notifyQt: notification of new avatar." << std::endl ; + #endif + emit peerHasNewAvatar(QString::fromStdString(peer_id)) ; +} + +void NotifyQt::notifyCustomState(const std::string& peer_id, const std::string& status_string) +{ + #ifdef NOTIFY_DEBUG + std::cerr << "notifyQt: Received custom status string notification" << std::endl ; + #endif + emit peerHasNewCustomStateString(QString::fromStdString(peer_id), QString::fromStdString(status_string)) ; +} + +void NotifyQt::notifyChatStatus(const std::string& peer_id,const std::string& status_string,bool is_private) +{ + #ifdef NOTIFY_DEBUG + std::cerr << "notifyQt: Received chat status string: " << status_string << std::endl ; + #endif + emit chatStatusChanged(QString::fromStdString(peer_id),QString::fromStdString(status_string),is_private) ; +} + +void NotifyQt::notifyTurtleSearchResult(uint32_t search_id,const std::list& files) +{ + #ifdef NOTIFY_DEBUG + std::cerr << "in notify search result..." << std::endl ; + #endif + + for(std::list::const_iterator it(files.begin());it!=files.end();++it) + { + FileDetail det ; + det.rank = 0 ; + det.age = 0 ; + det.name = (*it).name ; + det.hash = (*it).hash ; + det.size = (*it).size ; + det.id = "Anonymous" ; + + emit gotTurtleSearchResult(search_id,det) ; + } +} + +void NotifyQt::notifyHashingInfo(uint32_t type, const std::string& fileinfo) +{ + QString info; + + switch (type) { + case NOTIFY_HASHTYPE_EXAMINING_FILES: + info = tr("Examining shared files..."); + break; + case NOTIFY_HASHTYPE_FINISH: + break; + case NOTIFY_HASHTYPE_HASH_FILE: + info = tr("Hashing file") + " " + QString::fromUtf8(fileinfo.c_str()); + break; + case NOTIFY_HASHTYPE_SAVE_FILE_INDEX: + info = tr("Saving file index..."); + break; + } + + emit hashingInfoChanged(info); +} + +//void NotifyQt::notifyChat() +//{ +// std::cerr << "Received chat notification" << std::endl ; +// return; +//} + +void NotifyQt::notifyListChange(int list, int type) +{ +#ifdef NOTIFY_DEBUG + std::cerr << "NotifyQt::notifyListChange()" << std::endl; +#endif + switch(list) + { + case NOTIFY_LIST_NEIGHBOURS: +#ifdef NOTIFY_DEBUG + std::cerr << "received neighbrs changed" << std::endl ; +#endif + emit neighborsChanged(); + break; + case NOTIFY_LIST_FRIENDS: +#ifdef NOTIFY_DEBUG + std::cerr << "received friends changed" << std::endl ; +#endif + emit friendsChanged() ; + break; + case NOTIFY_LIST_DIRLIST_LOCAL: +#ifdef NOTIFY_DEBUG + std::cerr << "received files changed" << std::endl ; +#endif + emit filesPostModChanged(true) ; /* Local */ + break; + case NOTIFY_LIST_DIRLIST_FRIENDS: +#ifdef NOTIFY_DEBUG + std::cerr << "received files changed" << std::endl ; +#endif + emit filesPostModChanged(false) ; /* Local */ + break; + case NOTIFY_LIST_SEARCHLIST: + break; + case NOTIFY_LIST_MESSAGELIST: +#ifdef NOTIFY_DEBUG + std::cerr << "received msg changed" << std::endl ; +#endif + emit messagesChanged() ; + break; + case NOTIFY_LIST_MESSAGE_TAGS: +#ifdef NOTIFY_DEBUG + std::cerr << "received msg tags changed" << std::endl ; +#endif + emit messagesTagsChanged(); + break; + case NOTIFY_LIST_CHANNELLIST: + break; + case NOTIFY_LIST_TRANSFERLIST: +#ifdef NOTIFY_DEBUG + std::cerr << "received transfer changed" << std::endl ; +#endif + emit transfersChanged() ; + break; + case NOTIFY_LIST_CONFIG: +#ifdef NOTIFY_DEBUG + std::cerr << "received config changed" << std::endl ; +#endif + emit configChanged() ; + break ; + case NOTIFY_LIST_FORUMLIST_LOCKED: +#ifdef NOTIFY_DEBUG + std::cerr << "received forum msg changed" << std::endl ; +#endif + emit forumsChanged(); // use connect with Qt::QueuedConnection + break; + case NOTIFY_LIST_CHANNELLIST_LOCKED: +#ifdef NOTIFY_DEBUG + std::cerr << "received channel msg changed" << std::endl ; +#endif + emit channelsChanged(type); // use connect with Qt::QueuedConnection + break; + case NOTIFY_LIST_PUBLIC_CHAT: +#ifdef NOTIFY_DEBUG + std::cerr << "received public chat changed" << std::endl ; +#endif + emit publicChatChanged(type); + break; + case NOTIFY_LIST_PRIVATE_INCOMING_CHAT: + case NOTIFY_LIST_PRIVATE_OUTGOING_CHAT: +#ifdef NOTIFY_DEBUG + std::cerr << "received private chat changed" << std::endl ; +#endif + emit privateChatChanged(list, type); + break; + case NOTIFY_LIST_GROUPLIST: +#ifdef NOTIFY_DEBUG + std::cerr << "received groups changed" << std::endl ; +#endif + emit groupsChanged(type); + break; + default: + break; + } + return; +} + + +void NotifyQt::notifyListPreChange(int list, int type) +{ +#ifdef NOTIFY_DEBUG + std::cerr << "NotifyQt::notifyListPreChange()" << std::endl; +#endif + switch(list) + { + case NOTIFY_LIST_NEIGHBOURS: + break; + case NOTIFY_LIST_FRIENDS: + emit friendsChanged() ; + break; + case NOTIFY_LIST_DIRLIST_FRIENDS: + emit filesPreModChanged(false) ; /* remote */ + break ; + case NOTIFY_LIST_DIRLIST_LOCAL: + emit filesPreModChanged(true) ; /* local */ + break; + case NOTIFY_LIST_SEARCHLIST: + break; + case NOTIFY_LIST_MESSAGELIST: + break; + case NOTIFY_LIST_CHANNELLIST: + break; + case NOTIFY_LIST_TRANSFERLIST: + break; + default: + break; + } + return; +} + + /* New Timer Based Update scheme ... + * means correct thread seperation + * + * uses Flags, to detect changes + */ + +void NotifyQt::UpdateGUI() +{ +#ifndef MINIMAL_RSGUI + /* hack to force updates until we've fixed that part */ + static time_t lastTs = 0; + +// std::cerr << "Got update signal t=" << lastTs << std::endl ; + + lastTs = time(NULL) ; + + static bool already_updated = false ; // these only update once at start because they may already have been set before + // the gui is running, then they get updated by callbacks. + if(!already_updated) + { + emit messagesChanged() ; + emit neighborsChanged(); + emit configChanged(); + + already_updated = true ; + } + + /* Finally Check for PopupMessages / System Error Messages */ + + if (rsNotify) + { + uint32_t sysid; + uint32_t type; + std::string title, id, msg; + + if (rsNotify->NotifyPopupMessage(type, id, title, msg)) + { + uint popupflags = Settings->getNotifyFlags(); + + /* You can set timeToShow, timeToLive and timeToHide or can leave the standard */ + Toaster *toaster = NULL; + + /* id the name */ + std::string name; + std::string realmsg; + unsigned char *data = NULL; + int size = 0 ; + + if (type == RS_POPUP_DOWNLOAD) { + /* id = file hash */ + } else { + name = rsPeers->getPeerName(id); + realmsg = "" + name + ""; + + rsMsgs->getAvatarData(id,data,size); + } + + switch(type) + { + case RS_POPUP_MSG: + if (popupflags & RS_POPUP_MSG) + { + toaster = new Toaster(new MessageToaster(QString::fromStdString(realmsg), QString::fromStdString(title), QString::fromStdString(msg))); + } + break; + case RS_POPUP_CONNECT: + if (popupflags & RS_POPUP_CONNECT) + { + QPixmap avatar; + if(size != 0) + { + // set the image + avatar.loadFromData(data,size,"PNG"); + } + else + { + avatar = QPixmap(":/images/user/personal64.png"); + } + + toaster = new Toaster(new OnlineToaster(id, QString::fromStdString(realmsg), avatar)); + } + break; + case RS_POPUP_DOWNLOAD: + if (popupflags & RS_POPUP_DOWNLOAD) + { + toaster = new Toaster(new DownloadToaster(id, QString::fromUtf8(title.c_str()))); + } + break; + } + + if (data) { + delete[] data; + } + + if (toaster) { + /* init attributes */ + toaster->widget->setWindowFlags(Qt::ToolTip | Qt::WindowStaysOnTopHint); + + /* add toaster to waiting list */ +// QMutexLocker lock(&waitingToasterMutex); + waitingToasterList.push_back(toaster); + } + } + + if (rsNotify->NotifySysMessage(sysid, type, title, msg)) + { + /* make a warning message */ + switch(type) + { + case RS_SYS_ERROR: + QMessageBox::critical(MainWindow::getInstance(), + QString::fromStdString(title), + QString::fromStdString(msg)); + break; + case RS_SYS_WARNING: + QMessageBox::warning(MainWindow::getInstance(), + QString::fromStdString(title), + QString::fromStdString(msg)); + break; + default: + case RS_SYS_INFO: + QMessageBox::information(MainWindow::getInstance(), + QString::fromStdString(title), + QString::fromStdString(msg)); + break; + } + } + + if (rsNotify->NotifyLogMessage(sysid, type, title, msg)) + { + /* make a log message */ + std::string logMesString = title + " " + msg; + switch(type) + { + case RS_SYS_ERROR: + case RS_SYS_WARNING: + case RS_SYS_INFO: emit logInfoChanged(QString(logMesString.c_str())); + default:; + } + } + } + + /* Now start the waiting toasters */ + startWaitingToasters(); + +#endif // MINIMAL_RSGUI +} + +void NotifyQt::notifyChatStyleChanged(int /*ChatStyle::enumStyleType*/ styleType) +{ + emit chatStyleChanged(styleType); +} + +void NotifyQt::startWaitingToasters() +{ + { +// QMutexLocker lock(&waitingToasterMutex); + + if (waitingToasterList.empty()) { + /* No toasters are waiting */ + return; + } + } + + { +// QMutexLocker lock(&runningToasterMutex); + + if (runningToasterList.size() >= 3) { + /* Don't show more than 3 toasters at once */ + return; + } + } + + Toaster *toaster = NULL; + + { +// QMutexLocker lock(&waitingToasterMutex); + + if (waitingToasterList.size()) { + /* Take one toaster of the waiting list */ + toaster = waitingToasterList.front(); + waitingToasterList.pop_front(); + } + } + + if (toaster) { +// QMutexLocker lock(&runningToasterMutex); + + /* Calculate positions */ + QSize size = toaster->widget->size(); + + QDesktopWidget *desktop = QApplication::desktop(); + QRect desktopGeometry = desktop->availableGeometry(desktop->primaryScreen()); + + RshareSettings::enumToasterPosition position = Settings->getToasterPosition(); + QPoint margin = Settings->getToasterMargin(); + + switch (position) { + case RshareSettings::TOASTERPOS_TOPLEFT: + toaster->startPos = QPoint(desktopGeometry.left() + margin.x(), desktopGeometry.top() - size.height()); + toaster->endPos = QPoint(toaster->startPos.x(), desktopGeometry.top() + margin.y()); + break; + case RshareSettings::TOASTERPOS_TOPRIGHT: + toaster->startPos = QPoint(desktopGeometry.right() - size.width() - margin.x(), desktopGeometry.top() - size.height()); + toaster->endPos = QPoint(toaster->startPos.x(), desktopGeometry.top() + margin.y()); + break; + case RshareSettings::TOASTERPOS_BOTTOMLEFT: + toaster->startPos = QPoint(desktopGeometry.left() + margin.x(), desktopGeometry.bottom()); + toaster->endPos = QPoint(toaster->startPos.x(), desktopGeometry.bottom() - size.height() - margin.y()); + break; + case RshareSettings::TOASTERPOS_BOTTOMRIGHT: // default + default: + toaster->startPos = QPoint(desktopGeometry.right() - size.width() - margin.x(), desktopGeometry.bottom()); + toaster->endPos = QPoint(toaster->startPos.x(), desktopGeometry.bottom() - size.height() - margin.y()); + break; + } + + /* Initialize widget */ + toaster->widget->move(toaster->startPos); + + /* Initialize toaster */ + toaster->elapsedTimeToShow = 0; + toaster->elapsedTimeToLive = 0; + toaster->elapsedTimeToHide = 0; + + /* Add toaster to the running list */ + runningToasterList.push_front(toaster); + if (runningToasterTimer->isActive() == false) { + /* Start the toaster timer */ + runningToasterTimer->start(); + } + } +} + +void NotifyQt::runningTick() +{ +// QMutexLocker lock(&runningToasterMutex); + + QDesktopWidget *desktop = QApplication::desktop(); + QRect desktopGeometry = desktop->availableGeometry(desktop->primaryScreen()); + + int interval = runningToasterTimer->interval(); + QPoint diff; + + QList::iterator it = runningToasterList.begin(); + while (it != runningToasterList.end()) { + Toaster *toaster = *it; + + bool visible = true; + if (toaster->elapsedTimeToShow) { + /* Toaster is started, check for visible */ + visible = toaster->widget->isVisible(); + } + + QPoint newPos; + enum { NOTHING, SHOW, HIDE } operation = NOTHING; + + if (visible && toaster->elapsedTimeToShow <= toaster->timeToShow) { + /* Toaster is showing */ + if (toaster->elapsedTimeToShow == 0) { + /* Toaster is not visible, show it now */ + operation = SHOW; + } + + toaster->elapsedTimeToShow += interval; + + newPos = QPoint(toaster->startPos.x() - (toaster->startPos.x() - toaster->endPos.x()) * toaster->elapsedTimeToShow / toaster->timeToShow, + toaster->startPos.y() - (toaster->startPos.y() - toaster->endPos.y()) * toaster->elapsedTimeToShow / toaster->timeToShow); + } else if (visible && toaster->elapsedTimeToLive <= toaster->timeToLive) { + /* Toaster is living */ + toaster->elapsedTimeToLive += interval; + + newPos = toaster->endPos; + } else if (visible && toaster->elapsedTimeToHide <= toaster->timeToHide) { + /* Toaster is hiding */ + toaster->elapsedTimeToHide += interval; + + if (toaster->elapsedTimeToHide == toaster->timeToHide) { + /* Toaster is back at the start position, hide it */ + operation = HIDE; + } + + newPos = QPoint(toaster->startPos.x() - (toaster->startPos.x() - toaster->endPos.x()) * (toaster->timeToHide - toaster->elapsedTimeToHide) / toaster->timeToHide, + toaster->startPos.y() - (toaster->startPos.y() - toaster->endPos.y()) * (toaster->timeToHide - toaster->elapsedTimeToHide) / toaster->timeToHide); + } else { + /* Toaster is hidden, delete it */ + it = runningToasterList.erase(it); + delete(toaster->widget); + delete(toaster); + continue; + } + + toaster->widget->move(newPos + diff); + diff += newPos - toaster->startPos; + + QRect mask = QRect(0, 0, toaster->widget->width(), qAbs(toaster->startPos.y() - newPos.y())); + if (newPos.y() > toaster->startPos.y()) { + /* Toaster is moving from top */ + mask.moveTop(toaster->widget->height() - (newPos.y() - toaster->startPos.y())); + } + toaster->widget->setMask(QRegion(mask)); + + switch (operation) { + case NOTHING: + break; + case SHOW: + toaster->widget->show(); + break; + case HIDE: + toaster->widget->hide(); + break; + } + + ++it; + } + + if (runningToasterList.size()) { + /* There are more running toasters, start the timer again */ + runningToasterTimer->start(); + } +} + +//void NotifyQt::displaySearch() +//{ +// iface->lockData(); /* Lock Interface */ +// +//#ifdef NOTIFY_DEBUG +// std::ostringstream out; +// std::cerr << out.str(); +//#endif +// +// iface->unlockData(); /* UnLock Interface */ +//} + +// void NotifyQt::displayChat() +// { +// iface->lockData(); /* Lock Interface */ +// +// #ifdef NOTIFY_DEBUG +// std::ostringstream out; +// std::cerr << out.str(); +// #endif +// +// iface->unlockData(); /* UnLock Interface */ +// +// if (hDialog) +// hDialog -> insertChat(); +// } +// +// +//void NotifyQt::displayChannels() +//{ +// iface->lockData(); /* Lock Interface */ +// +//#ifdef NOTIFY_DEBUG +// std::ostringstream out; +// std::cerr << out.str(); +//#endif +// +// iface->unlockData(); /* UnLock Interface */ +// +// if (sDialog) +// sDialog -> insertChannels(); +//} +// +// +//void NotifyQt::displayTransfers() +//{ +// /* Do the GUI */ +// if (tDialog) +// tDialog->insertTransfers(); +//} +// +// +//void NotifyQt::preDisplayNeighbours() +//{ +// +//} +// +//void NotifyQt::preDisplayFriends() +//{ +// +//} + +//void NotifyQt::preDisplaySearch() +//{ +// +//} +// +//void NotifyQt::preDisplayMessages() +//{ +// +//} +// +//void NotifyQt::preDisplayChannels() +//{ +// +//} +// +//void NotifyQt::preDisplayTransfers() +//{ +// +// +//} diff --git a/retroshare-gui/src/gui/notifyqt.h b/retroshare-gui/src/gui/notifyqt.h new file mode 100644 index 000000000..dbfd2f326 --- /dev/null +++ b/retroshare-gui/src/gui/notifyqt.h @@ -0,0 +1,148 @@ +#ifndef RSIFACE_NOTIFY_TXT_H +#define RSIFACE_NOTIFY_TXT_H + +#include +#include +#include +//#include + +#include + +class QTimer; +class NetworkDialog; +class FriendsDialog; +class SharedFilesDialog; +class TransfersDialog; +class ChatDialog; +class MessagesDialog; +class ChannelsDialog; +class MessengerWindow; +class Toaster; +struct TurtleFileInfo; + +//class NotifyQt: public NotifyBase, public QObject +class NotifyQt: public QObject, public NotifyBase +{ + Q_OBJECT + public: + static NotifyQt *Create (); + static NotifyQt *getInstance (); + + virtual ~NotifyQt() { return; } + + void setNetworkDialog(NetworkDialog *c) { cDialog = c; } + + virtual void notifyListPreChange(int list, int type); + virtual void notifyListChange(int list, int type); + virtual void notifyErrorMsg(int list, int sev, std::string msg); + virtual void notifyChatStatus(const std::string& peer_id,const std::string& status_string,bool is_private); + virtual void notifyCustomState(const std::string& peer_id, const std::string& status_string); + virtual void notifyHashingInfo(uint32_t type, const std::string& fileinfo); + virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list& found_files); + virtual void notifyPeerHasNewAvatar(std::string peer_id) ; + virtual void notifyOwnAvatarChanged() ; + virtual void notifyOwnStatusMessageChanged() ; + virtual void notifyDiskFull(uint32_t loc,uint32_t size_in_mb) ; + /* peer has changed the state */ + virtual void notifyPeerStatusChanged(const std::string& peer_id, uint32_t state); + /* one or more peers has changed the states */ + virtual void notifyPeerStatusChangedSummary(); + virtual void notifyChannelMsgReadSatusChanged(const std::string& channelId, const std::string& msgId, uint32_t status); + + virtual void notifyDiscInfoChanged() ; + virtual void notifyDownloadComplete(const std::string& fileHash); + virtual void notifyDownloadCompleteCount(uint32_t count); + virtual std::string askForPassword(const std::string& key_details,bool prev_is_bad) ; + + /* Notify from GUI */ + void notifyChatStyleChanged(int /*ChatStyle::enumStyleType*/ styleType); + + signals: + // It's beneficial to send info to the GUI using signals, because signals are thread-safe + // as they get queued by Qt. + // + void hashingInfoChanged(const QString&) const ; + void filesPreModChanged(bool) const ; + void filesPostModChanged(bool) const ; + void transfersChanged() const ; + void friendsChanged() const ; + void neighborsChanged() const ; + void messagesChanged() const ; + void messagesTagsChanged() const; + void forumsChanged() const ; // use connect with Qt::QueuedConnection + void channelsChanged(int type) const ; // use connect with Qt::QueuedConnection + void configChanged() const ; + void logInfoChanged(const QString&) const ; + void chatStatusChanged(const QString&,const QString&,bool) const ; + void peerHasNewCustomStateString(const QString& /* peer_id */, const QString& /* status_string */) const ; + void gotTurtleSearchResult(qulonglong search_id,FileDetail file) const ; + void peerHasNewAvatar(const QString& peer_id) const ; + void ownAvatarChanged() const ; + void ownStatusMessageChanged() const ; + void errorOccurred(int,int,const QString&) const ; + void diskFull(int,int) const ; + void peerStatusChanged(const QString& /* peer_id */, int /* status */); + void peerStatusChangedSummary() const; + void publicChatChanged(int type) const ; + void privateChatChanged(int list, int type) const ; + void groupsChanged(int type) const ; + void discInfoChanged() const ; + void downloadComplete(const QString& /* fileHash */); + void downloadCompleteCountChanged(int /* count */); + void channelMsgReadSatusChanged(const QString& channelId, const QString& msgId, int status); + + /* Notify from GUI */ + void chatStyleChanged(int /*ChatStyle::enumStyleType*/ styleType); + + public slots: + + void UpdateGUI(); /* called by timer */ + + private slots: + void runningTick(); + + private: + NotifyQt(); + + static NotifyQt *_instance; + + void startWaitingToasters(); + +// QMutex waitingToasterMutex; // for lock of the waiting toaster list + QList waitingToasterList; + + QTimer *runningToasterTimer; +// QMutex runningToasterMutex; // for lock of the running toaster list + QList runningToasterList; + +// void displayNeighbours(); +// void displayFriends(); +// void displayDirectories(); +// void displaySearch(); +// void displayChat(); +// void displayMessages(); +// void displayChannels(); +// void displayTransfers(); + +// void preDisplayNeighbours(); +// void preDisplayFriends(); +// void preDisplayDirectories(); +// void preDisplaySearch(); +// void preDisplayMessages(); +// void preDisplayChannels(); +// void preDisplayTransfers(); + + /* so we can update windows */ + NetworkDialog *cDialog; +// FriendsDialog *fDialog; +// SharedFilesDialog *dDialog; +// TransfersDialog *tDialog; +// ChatDialog *hDialog; +// MessagesDialog *mDialog; +// ChannelsDialog *sDialog; +// MessengerWindow *mWindow; + +// RsIface *iface; +}; + +#endif diff --git a/retroshare-gui/src/gui/plugins/PluginInterface.h b/retroshare-gui/src/gui/plugins/PluginInterface.h new file mode 100644 index 000000000..5d64df426 --- /dev/null +++ b/retroshare-gui/src/gui/plugins/PluginInterface.h @@ -0,0 +1,51 @@ +#ifndef _PLUGIN_INTERFACE_H_ +#define _PLUGIN_INTERFACE_H_ + +#include + +#include +/*** +QT_BEGIN_NAMESPACE +class QString; +class QWidget; +QT_END_NAMESPACE +***/ + +//! a base class for plugins + +//! All plugin classes must inherite this class and QObject. +class PluginInterface +{ +public: + virtual ~PluginInterface() {} + +public slots: + //! A description of the plugin + + //! A description of the plugin. Is not used in current version. + virtual QString pluginDescription() const = 0; + + //! The plugin's name + + //! A name serves like an unique ID. The name is used in all operations + //! such as installing, removing, receiving a widget + virtual QString pluginName() const = 0; + + //! plugin's widget. + + //! Returns the widget, which is actually a plugin. Main application must + //! delete the widget; usually, a parent widget does it. If you want to use + //! the widget as top-level (i.e. parent==0), please, set + //! Qt::WA_DeleteOnClose flag . + virtual QWidget* pluginWidget(QWidget * parent = 0) = 0; +}; + +QT_BEGIN_NAMESPACE + +Q_DECLARE_INTERFACE(PluginInterface, + "com.beardog.retroshare.PluginInterface/1.0") + +QT_END_NAMESPACE + +#endif + diff --git a/retroshare-gui/src/gui/profile/ProfileEdit.cpp b/retroshare-gui/src/gui/profile/ProfileEdit.cpp new file mode 100644 index 000000000..e3f99d6ab --- /dev/null +++ b/retroshare-gui/src/gui/profile/ProfileEdit.cpp @@ -0,0 +1,128 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "gui/profile/ProfileEdit.h" + +#include + +#include + +#include + + +/** Constructor */ +ProfileEdit::ProfileEdit(QWidget *parent) +: QDialog(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.profileTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( profileCustomPopupMenu( QPoint ) ) ); + + // connect up the buttons. + connect(ui.addButton, SIGNAL(clicked()), this, SLOT(profileEntryAdd())); + connect(ui.moveDownButton, SIGNAL(clicked()), this, SLOT(profileEntryMoveDown())); + connect(ui.moveUpButton, SIGNAL(clicked()), this, SLOT(profileEntryMoveUp())); + connect(ui.closeButton, SIGNAL(clicked()), this, SLOT(close())); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +void ProfileEdit::profileCustomPopupMenu( QPoint point ) +{ + QMenu contextMnu( this ); + + QAction *removeAct = new QAction( tr( "Remove Profile Entry" ), this ); + QAction *moveupAct = new QAction( tr( "Move Profile Entry Up" ), this ); + QAction *movedownAct = new QAction( tr( "Move Profile Entry Down" ), this ); + + connect( removeAct , SIGNAL( triggered() ), this, SLOT( profileEntryRemove() ) ); + connect( moveupAct , SIGNAL( triggered() ), this, SLOT( profileEntryMoveUp() ) ); + connect( movedownAct , SIGNAL( triggered() ), this, SLOT( profileEntryMoveDown() ) ); + + contextMnu.addAction( removeAct ); + contextMnu.addAction( moveupAct ); + contextMnu.addAction( movedownAct ); + + contextMnu.exec(QCursor::pos()); +} + +void ProfileEdit::clear() +{ + return; +} + +void ProfileEdit::update() +{ + /* load it up! */ + std::string pId = "OwnId"; + + std::list< std::pair > profile; + std::list< std::pair >::iterator pit; + + QList itemList; + for(pit = profile.begin(); pit != profile.end(); pit++) + { + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(0, QString::fromStdWString(pit->first)); + item->setText(1, QString::fromStdWString(pit->second)); + + itemList.push_back(item); + } + + ui.profileTreeWidget->clear(); + ui.profileTreeWidget->insertTopLevelItems(0, itemList); + + return; +} + +/* For context Menus */ +/* for Profile */ +void ProfileEdit::profileEntryAdd() +{ + return; +} + +void ProfileEdit::profileEntryRemove() +{ + return; +} + +void ProfileEdit::profileEntryMoveUp() +{ + return; +} + +void ProfileEdit::profileEntryMoveDown() +{ + return; +} + + +void ProfileEdit::profileEntryCustomChanged() /* check box */ +{ + return; +} + + diff --git a/retroshare-gui/src/gui/profile/ProfileEdit.h b/retroshare-gui/src/gui/profile/ProfileEdit.h new file mode 100644 index 000000000..49b2abede --- /dev/null +++ b/retroshare-gui/src/gui/profile/ProfileEdit.h @@ -0,0 +1,67 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008, Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _PROFILE_EDIT_H +#define _PROFILE_EDIT_H + +#include "ui_ProfileEdit.h" + +#include +#include + +class ProfileEdit : public QDialog +{ + Q_OBJECT + +public: + /** Default Constructor */ + + ProfileEdit(QWidget *parent = 0); + /** Default Destructor */ + +void clear(); +void update(); + +public slots: + +private slots: + + /** context popup menus */ + void profileCustomPopupMenu( QPoint point ); + + /* for Profile */ + void profileEntryAdd(); + void profileEntryRemove(); + void profileEntryMoveUp(); + void profileEntryMoveDown(); + + void profileEntryCustomChanged(); /* check box */ + +private: + + /** Qt Designer generated object */ + Ui::ProfileEdit ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/profile/ProfileEdit.ui b/retroshare-gui/src/gui/profile/ProfileEdit.ui new file mode 100644 index 000000000..f21b2578b --- /dev/null +++ b/retroshare-gui/src/gui/profile/ProfileEdit.ui @@ -0,0 +1,221 @@ + + ProfileEdit + + + + 0 + 0 + 540 + 469 + + + + Profile Edit + + + Qt::LeftToRight + + + + + + Qt::Vertical + + + + + + + + 75 + true + + + + Profile + + + + + + + Qt::CustomContextMenu + + + false + + + + Category + + + + + Thoughts + + + + + + + + + + + + + 75 + true + + + + Edit Profile Category + + + + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + + + + Qt::RightToLeft + + + or Custom Entry + + + + + + + + + + + + + + + + + + + Add Entry + + + + :/images/add_24x24.png:/images/add_24x24.png + + + + + + + Qt::Horizontal + + + + 71 + 28 + + + + + + + + Qt::RightToLeft + + + Move + + + + :/images/down.png:/images/down.png + + + + + + + Move + + + + :/images/up.png:/images/up.png + + + + + + + Qt::Horizontal + + + + 71 + 28 + + + + + + + + Qt::RightToLeft + + + Close Editor + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/profile/ProfileView.cpp b/retroshare-gui/src/gui/profile/ProfileView.cpp new file mode 100644 index 000000000..7d9c0df6a --- /dev/null +++ b/retroshare-gui/src/gui/profile/ProfileView.cpp @@ -0,0 +1,311 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "gui/profile/ProfileView.h" +#include "gui/profile/ProfileEdit.h" + +#include +#include + +#include + +//#include +#include +#include +#include + + +/** Constructor */ +ProfileView::ProfileView(QWidget *parent) +: QDialog(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.photoLabel, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( imageCustomPopupMenu( QPoint ) ) ); + connect( ui.profileTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( profileCustomPopupMenu( QPoint ) ) ); + connect( ui.fileTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( fileCustomPopupMenu( QPoint ) ) ); + // + + // connect up the buttons. + connect(ui.closeButton, SIGNAL(clicked()), this, SLOT(closeView())); + connect(ui.profileditButton, SIGNAL(clicked()), this, SLOT(profileEdit())); + + loadAvatar(); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +/** context popup menus */ +void ProfileView::imageCustomPopupMenu( QPoint point ) +{ + if (!mIsOwnId) + { + return; + } + + QMenu contextMnu( this ); + + QAction *clearImageAct = new QAction( tr( "Clear Photo" ), this ); + QAction *changeImageAct = new QAction( tr( "Change Photo" ), this ); + + connect( clearImageAct , SIGNAL( triggered() ), this, SLOT( clearimage() ) ); + connect( changeImageAct , SIGNAL( triggered() ), this, SLOT( selectimagefile() ) ); + + contextMnu.addAction( clearImageAct ); + contextMnu.addAction( changeImageAct ); + + contextMnu.exec(QCursor::pos()); +} + + +void ProfileView::profileCustomPopupMenu( QPoint point ) +{ + if (!mIsOwnId) + { + return; + } + + QMenu contextMnu( this ); + + QAction *editAct = new QAction( tr( "Edit Profile" ), this ); + connect( editAct , SIGNAL( triggered() ), this, SLOT( profileEdit() ) ); + + contextMnu.addAction( editAct ); + + contextMnu.exec(QCursor::pos()); +} + +void ProfileView::fileCustomPopupMenu( QPoint point ) +{ + QMenu contextMnu( this ); + + QAction *downloadAct = NULL; + QAction *downloadAllAct = NULL; + QAction *removeAct = NULL; + QAction *clearAct = NULL; + + if (mIsOwnId) + { + removeAct = new QAction( tr( "Remove Favourite" ), this ); + clearAct = new QAction( tr( "Clear Favourites" ), this ); + connect( removeAct , SIGNAL( triggered() ), this, SLOT( fileRemove() ) ); + connect( clearAct , SIGNAL( triggered() ), this, SLOT( filesClear() ) ); + + contextMnu.addAction( clearAct ); + contextMnu.addAction( removeAct ); + } + else + { + downloadAct = new QAction( tr( "Download File" ), this ); + downloadAllAct = new QAction( tr( "Download All" ), this ); + connect( downloadAct , SIGNAL( triggered() ), this, SLOT( fileDownload() ) ); + connect( downloadAllAct , SIGNAL( triggered() ), this, SLOT( filesDownloadAll() ) ); + + contextMnu.addAction( downloadAct ); + contextMnu.addAction( downloadAllAct ); + } + + contextMnu.exec(QCursor::pos()); +} + + +void ProfileView::setPeerId(std::string id) +{ + pId = id; + update(); +} + + +void ProfileView::expand() +{ + return; +} + + +void ProfileView::closeView() +{ + close(); + return; +} + + +void ProfileView::clear() +{ + return; +} + +void ProfileView::update() +{ + /* load it up! */ + + /* if id bad -> clear */ + + //if (ownId) + //{ + // isOwnId = true; + //} + + mIsOwnId = true; /* switche on context menues */ + + + uint32_t PostTs; + std::wstring BlogPost; + std::list< std::pair > profile; + std::list< std::pair >::iterator pit; + std::list files; + std::list::iterator fit; + + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(pId, detail)) + { + QMessageBox::information(this, + tr("RetroShare"), + tr("Error : cannot get peer details.")); + } + + + ui.idLineEdit->setText(QString::fromStdString(pId)); + ui.nameLineEdit->setText(QString::fromStdString(detail.name)); + { + std::ostringstream out; + out << PostTs; + ui.timeLineEdit->setText(QString::fromStdString(out.str())); + } + ui.postTextEdit->setHtml(QString::fromStdWString(BlogPost)); + + QList itemList; + for(pit = profile.begin(); pit != profile.end(); pit++) + { + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(0, QString::fromStdWString(pit->first)); + item->setText(1, QString::fromStdWString(pit->second)); + + itemList.push_back(item); + } + + ui.profileTreeWidget->clear(); + ui.profileTreeWidget->insertTopLevelItems(0, itemList); + + QList fileList; + for(fit = files.begin(); fit != files.end(); fit++) + { + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(0, QString::fromStdString(fit->fname)); + { + std::ostringstream out; + out << fit-> size; + item->setText(1, QString::fromStdString(out.str())); + } + item->setText(2, QString::fromStdString(fit->hash)); + + fileList.push_back(item); + } + + ui.fileTreeWidget->clear(); + ui.fileTreeWidget->insertTopLevelItems(0, fileList); + + return; +} + +/* For context Menus */ +/* Image Context Menu */ +void ProfileView::selectimagefile() +{ + QString fileName = QFileDialog::getOpenFileName(this, "Load File", + QDir::homePath(), + "Pictures (*.png *.xpm *.jpg)"); + if(!fileName.isEmpty()) + { + picture = QPixmap(fileName).scaled(108,108, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + ui.photoLabel->setPixmap(picture); + } +} + +void ProfileView::clearimage() +{ + return; +} + + +/* for Profile */ +void ProfileView::profileEdit() +{ +static ProfileEdit *edit = new ProfileEdit(NULL); + edit->update(); + edit->show(); + + return; +} + +/* for Favourite Files */ +void ProfileView::fileDownload() +{ + return; +} + +void ProfileView::filesDownloadAll() +{ + return; +} + + +void ProfileView::fileRemove() +{ + return; +} + +void ProfileView::filesClear() +{ + return; +} + +/* add must be done from Shared Files */ + +void ProfileView::loadAvatar() +{ + + unsigned char *data = NULL; + int size = 0 ; + + rsMsgs->getAvatarData(pId,data,size); + + + if(size != 0) + { + // set the image + QPixmap pix ; + pix.loadFromData(data,size,"PNG") ; + ui.photoLabel->setPixmap(pix); + delete[] data ; + + } + else + { + ui.photoLabel->setPixmap(QPixmap(":/images/user/personal64.png")); + } + + +} + diff --git a/retroshare-gui/src/gui/profile/ProfileView.h b/retroshare-gui/src/gui/profile/ProfileView.h new file mode 100644 index 000000000..823271c59 --- /dev/null +++ b/retroshare-gui/src/gui/profile/ProfileView.h @@ -0,0 +1,90 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2007, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _PROFILE_VIEW_H +#define _PROFILE_VIEW_H + +#include "ui_ProfileView.h" + +#include +#include + +class ProfileView : public QDialog +{ + Q_OBJECT + +public: + /** Default Constructor */ + + ProfileView(QWidget *parent = 0); + /** Default Destructor */ + +void setPeerId(std::string id); + +void clear(); +void update(); +void loadAvatar(); + + +public slots: + +private slots: + + /** context popup menus */ + void imageCustomPopupMenu( QPoint point ); + void profileCustomPopupMenu( QPoint point ); + void fileCustomPopupMenu( QPoint point ); + + /* For context Menus */ + /* Image Context Menu */ + void selectimagefile(); + void clearimage(); + + /* for Profile */ + void profileEdit(); + + /* for Favourite Files */ + void fileRemove(); + void filesClear(); + void fileDownload(); + void filesDownloadAll(); + /* add must be done from Shared Files */ + + + /* expand / close */ + void expand(); + void closeView(); + +private: + std::string pId; + bool mIsOwnId; + + QPixmap picture; + + + /** Qt Designer generated object */ + Ui::ProfileView ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/profile/ProfileView.ui b/retroshare-gui/src/gui/profile/ProfileView.ui new file mode 100644 index 000000000..275670cba --- /dev/null +++ b/retroshare-gui/src/gui/profile/ProfileView.ui @@ -0,0 +1,301 @@ + + + ProfileView + + + + 0 + 0 + 590 + 464 + + + + Profile View + + + + :/images/rstray3.png:/images/rstray3.png + + + Qt::LeftToRight + + + + + + + + + 100 + 100 + + + + + 100 + 100 + + + + Qt::CustomContextMenu + + + QLabel#photoLabel{ +border-image: url(:/images/avatar_background.png); +} + + + + + + :/images/user/personal64.png + + + Qt::AlignCenter + + + + + + + + + Name + + + + + + + true + + + + + + + + + + + Peer ID + + + + + + + true + + + + + + + + + Qt::Vertical + + + + 408 + 28 + + + + + + + + + + + + + + Last Post: + + + + + + + true + + + + + + + + + + 16777215 + 128 + + + + + + + + + + 6 + + + 0 + + + + + + 75 + true + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 368 + 20 + + + + + + + + Edit Profile + + + + + + + :/images/user/kuser24.png:/images/user/kuser24.png + + + + 24 + 24 + + + + + + + + Qt::CustomContextMenu + + + false + + + + Category + + + + + Thoughts + + + + + + + + + + 0 + + + + + + 75 + true + + + + Favourite Files + + + + + + + Qt::CustomContextMenu + + + + Name + + + + + Size + + + + + Hash + + + + + + + + + + Qt::Horizontal + + + + 241 + 28 + + + + + + + + Qt::RightToLeft + + + Close Profile + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/profile/ProfileWidget.cpp b/retroshare-gui/src/gui/profile/ProfileWidget.cpp new file mode 100644 index 000000000..e9555f6b2 --- /dev/null +++ b/retroshare-gui/src/gui/profile/ProfileWidget.cpp @@ -0,0 +1,122 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009, RetroShre Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include "ProfileWidget.h" + +#include +#include +#include + +#include "StatusMessage.h" + +#include + +#include +#include + +/* Define the format used for displaying the date and time */ +#define DATETIME_FMT "MMM dd hh:mm:ss" + + +/** Default constructor */ +ProfileWidget::ProfileWidget(QWidget *parent, Qt::WFlags flags) + : QWidget(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + connect(ui.editstatuspushButton,SIGNAL(clicked()), this, SLOT(statusmessagedlg())); + + ui.onlinesince->setText(QDateTime::currentDateTime().toString(DATETIME_FMT)); + +} + +/** Destructor. */ +ProfileWidget::~ProfileWidget() +{ + +} + +void ProfileWidget::closeEvent (QCloseEvent * event) +{ + QWidget::closeEvent(event); +} + +void ProfileWidget::showEvent ( QShowEvent * event ) +{ + + RsPeerDetails detail; + if (rsPeers->getPeerDetails(rsPeers->getOwnId(),detail)) + { + + ui.name->setText(QString::fromUtf8(detail.name.c_str())); + ui.country->setText(QString::fromUtf8(detail.location.c_str())); + + ui.peerid->setText(QString::fromStdString(detail.id)); + + // Dont Show a timestamp in RS calculate the day + QDateTime date = QDateTime::fromTime_t(detail.lastConnect); + QString stime = date.toString(Qt::LocalDate); + + /* set retroshare version */ + std::map::iterator vit; + std::map versions; + bool retv = rsDisc->getDiscVersions(versions); + if (retv && versions.end() != (vit = versions.find(detail.id))) + { + ui.version->setText(QString::fromStdString(vit->second)); + } + + ui.ipAddressList->clear(); + for(std::list::const_iterator it(detail.ipAddressList.begin());it!=detail.ipAddressList.end();++it) + ui.ipAddressList->addItem(QString::fromStdString(*it)); + + + /* set local address */ + ui.localAddress->setText(QString::fromStdString(detail.localAddr)); + ui.localPort -> setText(QString::number(detail.localPort)); + /* set the server address */ + ui.extAddress->setText(QString::fromStdString(detail.extAddr)); + ui.extPort -> setText(QString::number(detail.extPort)); + /* set DynDNS */ + ui.dyndns->setText(QString::fromStdString(detail.dyndns)); + ui.dyndns->setCursorPosition (0); + + std::list ids; + ids.clear(); + rsPeers->getGPGAcceptedList(ids); + int friends = ids.size(); + + std::ostringstream out; + out << friends << ""; + ui.friendsEdit->setText(QString::fromStdString(out.str())); + + } + +} + +void ProfileWidget::statusmessagedlg() +{ + static StatusMessage *statusmsgdialog = new StatusMessage(); + statusmsgdialog->show(); +} + + + diff --git a/retroshare-gui/src/gui/profile/ProfileWidget.h b/retroshare-gui/src/gui/profile/ProfileWidget.h new file mode 100644 index 000000000..0b80864e5 --- /dev/null +++ b/retroshare-gui/src/gui/profile/ProfileWidget.h @@ -0,0 +1,58 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _PROFILEWIDGET_H +#define _PROFILEWIDGET_H + +#include + +#include "ui_ProfileWidget.h" + +class ProfileWidget : public QWidget +{ + Q_OBJECT + + public: + /** Default constructor */ + ProfileWidget(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~ProfileWidget(); + + +protected: + void closeEvent (QCloseEvent * event); + +private slots: + + void showEvent ( QShowEvent * event ); + void statusmessagedlg(); + +private: + + + /** Qt Designer generated object */ + Ui::ProfileWidget ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/profile/ProfileWidget.ui b/retroshare-gui/src/gui/profile/ProfileWidget.ui new file mode 100644 index 000000000..ea8604153 --- /dev/null +++ b/retroshare-gui/src/gui/profile/ProfileWidget.ui @@ -0,0 +1,704 @@ + + + ProfileWidget + + + + 0 + 0 + 500 + 603 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + + + QFrame#frame{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 1 + + + 1 + + + 1 + + + + + Edit Personal message + + + QPushButton:hover { +border: 1px solid #CCCCCC; +} + + + Edit Personal message + + + true + + + + + + + Qt::Horizontal + + + + 298 + 20 + + + + + + + + + + + true + + + + + 0 + 0 + 498 + 574 + + + + + + + QFrame#frame_2{ +background-color: white; + +border: 2px solid #CCCCCC;} + + + + + + + + + 16 + 16 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + + + + 75 + true + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 252 + 20 + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + + + + 75 + true + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 252 + 20 + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + + + + 75 + true + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 252 + 20 + + + + + + + + + + + QFrame#frame_3{ +background-color: white; + +border: 2px solid #CCCCCC;} + + + + + + + + + 16 + 16 + + + + + + + :/images/info16.png + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + + + + 75 + true + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + + + + 75 + true + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 211 + 17 + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + + + + 75 + true + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + QFrame#frame_4{ +background-color: white; + +border: 2px solid #CCCCCC;} + + + + + + + + + 16 + 16 + + + + + + + :/images/info16.png + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + + + + + + + + 110 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + + + + 0 + 0 + + + + 14 + + + true + + + + + + + + 20 + 0 + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 5 + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 110 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + + + + 0 + 0 + + + + 14 + + + true + + + + + + + + 20 + 0 + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 5 + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 110 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + + + + 0 + 0 + + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + + + + 16777215 + 150 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/profile/StatusMessage.cpp b/retroshare-gui/src/gui/profile/StatusMessage.cpp new file mode 100644 index 000000000..38db3ac35 --- /dev/null +++ b/retroshare-gui/src/gui/profile/StatusMessage.cpp @@ -0,0 +1,70 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009, RetroShre Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include "StatusMessage.h" + +#include +#include +#include +#include +#include "gui/settings/rsharesettings.h" + + +#include + +#include +#include + + +/** Default constructor */ +StatusMessage::StatusMessage(QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(close())); + connect(ui.okButton, SIGNAL(clicked()), this, SLOT(save())); + + load(); + +} + +/** Destructor. */ +StatusMessage::~StatusMessage() +{ +} + +/** Saves the changes on this page */ +void StatusMessage::save() +{ + rsMsgs->setCustomStateString(ui.txt_StatusMessage->text().toUtf8().constData()); + + close(); +} + +/** Loads the settings for this page */ +void StatusMessage::load() +{ + ui.txt_StatusMessage->setText(QString::fromUtf8(rsMsgs->getCustomStateString().c_str())); +} + + + diff --git a/retroshare-gui/src/gui/profile/StatusMessage.h b/retroshare-gui/src/gui/profile/StatusMessage.h new file mode 100644 index 000000000..7707d79e4 --- /dev/null +++ b/retroshare-gui/src/gui/profile/StatusMessage.h @@ -0,0 +1,54 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _STATUSMESSAGE_H +#define _STATUSMESSAGE_H + +#include + +#include "ui_StatusMessage.h" + +class StatusMessage : public QDialog +{ + Q_OBJECT + +public: + /** Default constructor */ + StatusMessage(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~StatusMessage(); + +private slots: + + /** Saves the changes on this page */ + void save(); + /** Loads the settings for this page */ + void load(); + +private: + /** Qt Designer generated object */ + Ui::StatusMessage ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/profile/StatusMessage.ui b/retroshare-gui/src/gui/profile/StatusMessage.ui new file mode 100644 index 000000000..7c8afd02c --- /dev/null +++ b/retroshare-gui/src/gui/profile/StatusMessage.ui @@ -0,0 +1,202 @@ + + + StatusMessage + + + + 0 + 0 + 387 + 217 + + + + + 0 + 0 + + + + + 387 + 217 + + + + + 387 + 217 + + + + Personal message + + + + :/images/rstray3.png:/images/rstray3.png + + + + + 9 + 60 + 368 + 113 + + + + QFrame#frame{background: white; +border: 1px solid #CCCCCC;} + + + + + + 91 + 40 + 261 + 16 + + + + Status message + + + + + + 91 + 60 + 221 + 20 + + + + + + + + 100 + 10 + 281 + 31 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + + 100 + 40 + 271 + 16 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + + 20 + 20 + 64 + 64 + + + + + 64 + 64 + + + + + + + :/images/user/personal64.png + + + + + + 0 + -1 + 391 + 241 + + + + QFrame#frame_2{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 220 + 180 + 75 + 23 + + + + OK + + + true + + + + + + 300 + 180 + 75 + 23 + + + + Cancel + + + + frame_2 + frame + label_3 + label_2 + label + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/qskinobject/qskinobject.h b/retroshare-gui/src/gui/qskinobject/qskinobject.h new file mode 100644 index 000000000..1f65bdba1 --- /dev/null +++ b/retroshare-gui/src/gui/qskinobject/qskinobject.h @@ -0,0 +1,90 @@ +/******************************************************************************************************** + * PROGRAM : childform + * DATE - TIME : Samstag 30 Dezember 2006 - 12h04 + * AUTHOR : ( ) + * FILENAME : QSkinMainWindow.h + * LICENSE : + * COMMENTARY : + ********************************************************************************************************/ +#ifndef QSkinObject_H +#define QSkinObject_H +#include "qskinwidgetresizehandler.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef WIN32 +#define _WIN32_WINNT 0x0500 +#define WINVER 0x0500 +#include +#endif +class QSkinWidgetResizeHandler; +class QSkinObject : public QObject +{ + Q_OBJECT + friend class QSkinWidgetResizeHandler; +public: + QSkinObject(QWidget* wgtParent); + ~QSkinObject(){} + void setSkinPath(const QString & skinpath); + QString getSkinPath(); + int customFrameWidth(); +public slots: + void updateStyle(); + void updateButtons(); + void startSkinning(); + void stopSkinning(); +protected: + bool eventFilter(QObject *o, QEvent *e); + //Events to filter + //void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + //void mouseReleaseEvent(QMouseEvent *mouseEvent); + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *e); + //void closeEvent(QCloseEvent *e); + + void loadSkinIni(); + void manageRegions(); + QPixmap drawCtrl(QWidget * widget); + QRegion childRegion; + void timerEvent ( QTimerEvent * event ); +private: + QRect saveRect; + QRect skinGeometry; + QPixmap widgetMask;//the pixmap, in which the ready frame is stored on pressed? + QString skinPath; + QFont titleFont; + QColor titleColor; + bool milchglas; + bool gotMousePress; + QRegion quitButton; + QRegion maxButton; + QRegion minButton; + QRect contentsRect; + QSkinWidgetResizeHandler * resizeHandler; + bool mousePress; + QBasicTimer *skinTimer; + QWidget *skinWidget; + void fastbluralpha(QImage &img, int radius); + Qt::WindowFlags flags; + int wlong; +#ifdef WIN32 +public slots: + void setLayered(); + void updateAlpha(); +private: + double alpha; +#endif +}; +#endif + diff --git a/retroshare-gui/src/gui/qskinobject/qskinwidgetresizehandler.h b/retroshare-gui/src/gui/qskinobject/qskinwidgetresizehandler.h new file mode 100644 index 000000000..45ba0788e --- /dev/null +++ b/retroshare-gui/src/gui/qskinobject/qskinwidgetresizehandler.h @@ -0,0 +1,115 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, The RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef QSKINWIDGETRESIZEHANDLER_P_H +#define QSKINWIDGETRESIZEHANDLER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// + +#include +#include +#include "qskinobject.h" +class QSkinObject; +class QMouseEvent; +class QKeyEvent; + +class QSkinWidgetResizeHandler : public QObject +{ + Q_OBJECT + friend class QSkinObject; +public: + enum Action { + Move = 0x01, + Resize = 0x02, + Any = Move|Resize + }; + + explicit QSkinWidgetResizeHandler(QSkinObject * skobj, QWidget *parent, QWidget *cw = 0); + void setActive(bool b) { setActive(Any, b); } + void setActive(Action ac, bool b); + bool isActive() const { return isActive(Any); } + bool isActive(Action ac) const; + void setMovingEnabled(bool b) { movingEnabled = b; } + bool isMovingEnabled() const { return movingEnabled; } + + bool isButtonDown() const { return buttonDown; } + + void setExtraHeight(int h) { extrahei = h; } + void setSizeProtection(bool b) { sizeprotect = b; } + + void setFrameWidth(int w) { fw = w; } + + void doResize(); + void doMove(); + +Q_SIGNALS: + void activate(); + +protected: + bool eventFilter(QObject *o, QEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void keyPressEvent(QKeyEvent *e); + +private: + Q_DISABLE_COPY(QSkinWidgetResizeHandler) + QSkinObject *obj; + enum MousePosition { + Nowhere, + TopLeft, BottomRight, BottomLeft, TopRight, + Top, Bottom, Left, Right, + Center + }; + + QWidget *widget; + QWidget *childWidget; + QPoint moveOffset; + QPoint invertedMoveOffset; + MousePosition mode; + int fw; + int extrahei; + int range; + uint buttonDown :1; + uint moveResizeMode :1; + uint activeForResize :1; + uint sizeprotect :1; + uint movingEnabled :1; + uint activeForMove :1; + uint widgetType; + void setMouseCursor(MousePosition m); + bool isMove() const { + return moveResizeMode && mode == Center; + } + bool isResize() const { + return moveResizeMode && !isMove(); + } +}; + + +#endif // QSkinWidgetResizeHandler_P_H diff --git a/retroshare-gui/src/gui/qss/chat/history/hincoming.htm b/retroshare-gui/src/gui/qss/chat/history/hincoming.htm new file mode 100644 index 000000000..c668e565a --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/history/hincoming.htm @@ -0,0 +1,15 @@ + + + + + + +
    %name%[%date% %time%]
    + + + + +
    %message%
    + \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/history/houtgoing.htm b/retroshare-gui/src/gui/qss/chat/history/houtgoing.htm new file mode 100644 index 000000000..4c2e0c1c0 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/history/houtgoing.htm @@ -0,0 +1,15 @@ + + + + + + +
    %name%[%date% %time%]
    + + + + +
    %message%
    + \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/history/incoming.htm b/retroshare-gui/src/gui/qss/chat/history/incoming.htm new file mode 100644 index 000000000..ca1efd722 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/history/incoming.htm @@ -0,0 +1,15 @@ + + + + + + +
    %name%[%date% %time%]
    + + + + +
    %message%
    + \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/history/info.xml b/retroshare-gui/src/gui/qss/chat/history/info.xml new file mode 100644 index 000000000..7f0445b03 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/history/info.xml @@ -0,0 +1,12 @@ + + + + + + RetroShare Team + + + \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/history/main.css b/retroshare-gui/src/gui/qss/chat/history/main.css new file mode 100644 index 000000000..ebd5d18bd --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/history/main.css @@ -0,0 +1,71 @@ +.header { + font-weight: bold; +} + +.time { +} + +.incomingTable{ + background-color:#dfedff; +} + +.incomingHeader { + border-color:#fafafa #d1dfef #d1dfef #fafafa; + color: #295b07; +} + +.incomingTime { + color: #295b07; +} + +.outgoingTable{ + background-color:#f5f5f5; +} + +.outgoingHeader { + border-color:#fafafa #e3e3e3 #e3e3e3 #fafafa; + color: #244578; +} + +.outgoingTime { + color: #244578; +} + +.hincomingTable{ + background-color:#dfedff; +} + +.hincomingHeader { + border-color:#fafafa #d1dfef #d1dfef #fafafa; + color: #295b07; +} + +.hincomingTime { + color: #295b07; +} + +.houtgoingTable{ + background-color:#f5f5f5; +} + +.houtgoingHeader { + border-color:#fafafa #e3e3e3 #e3e3e3 #fafafa; + color: #244578; +} + +.houtgoingTime { + color: #244578; +} + +.ooutgoingTable{ + background-color:#ffbebe; +} + +.ooutgoingHeader { + border-color:#fafafa #e3e3e3 #e3e3e3 #fafafa; + color: #244578; +} + +.ooutgoingTime { + color: #244578; +} diff --git a/retroshare-gui/src/gui/qss/chat/history/ooutgoing.htm b/retroshare-gui/src/gui/qss/chat/history/ooutgoing.htm new file mode 100644 index 000000000..152bd4aab --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/history/ooutgoing.htm @@ -0,0 +1,15 @@ + + + + + + +
    %name%[%date% %time%]
    + + + + +
    %message%
    + \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/history/outgoing.htm b/retroshare-gui/src/gui/qss/chat/history/outgoing.htm new file mode 100644 index 000000000..2f86ebba7 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/history/outgoing.htm @@ -0,0 +1,15 @@ + + + + + + +
    %name%[%date% %time%]
    + + + + +
    %message%
    + \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/history/variants/Standard.css b/retroshare-gui/src/gui/qss/chat/history/variants/Standard.css new file mode 100644 index 000000000..e69de29bb diff --git a/retroshare-gui/src/gui/qss/chat/images/Thumbs.db b/retroshare-gui/src/gui/qss/chat/images/Thumbs.db new file mode 100644 index 000000000..d4795cf89 Binary files /dev/null and b/retroshare-gui/src/gui/qss/chat/images/Thumbs.db differ diff --git a/retroshare-gui/src/gui/qss/chat/images/rstray3.png b/retroshare-gui/src/gui/qss/chat/images/rstray3.png new file mode 100644 index 000000000..d03d45063 Binary files /dev/null and b/retroshare-gui/src/gui/qss/chat/images/rstray3.png differ diff --git a/retroshare-gui/src/gui/qss/chat/private/hincoming.htm b/retroshare-gui/src/gui/qss/chat/private/hincoming.htm new file mode 100644 index 000000000..fdf4b60c6 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/private/hincoming.htm @@ -0,0 +1,14 @@ + + + + + + +
    %name%%date% %time%
    + + + + +
    %message%
    \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/private/houtgoing.htm b/retroshare-gui/src/gui/qss/chat/private/houtgoing.htm new file mode 100644 index 000000000..3a8c63b20 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/private/houtgoing.htm @@ -0,0 +1,14 @@ + + + + + + +
    %name%%date% %time%
    + + + + +
    %message%
    \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/private/incoming.htm b/retroshare-gui/src/gui/qss/chat/private/incoming.htm new file mode 100644 index 000000000..a0281c500 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/private/incoming.htm @@ -0,0 +1,14 @@ + + + + + + +
    %name%%time%
    + + + + +
    %message%
    \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/private/info.xml b/retroshare-gui/src/gui/qss/chat/private/info.xml new file mode 100644 index 000000000..7f0445b03 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/private/info.xml @@ -0,0 +1,12 @@ + + + + + + RetroShare Team + + + \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/private/main.css b/retroshare-gui/src/gui/qss/chat/private/main.css new file mode 100644 index 000000000..297d758ba --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/private/main.css @@ -0,0 +1,36 @@ +.name{ + font-weight: bold; +} + +.time { +} + +.incomingHeader { + background-color:#dfedff; + border-color:#fafafa #d1dfef #d1dfef #fafafa; + color: #295b07; +} + +.outgoingHeader { + background-color:#f5f5f5; + border-color:#fafafa #e3e3e3 #e3e3e3 #fafafa; + color: #244578; +} + +.hincomingHeader { + background-color:#dfedff; + border-color:#fafafa #d1dfef #d1dfef #fafafa; + color: #88f042; +} + +.houtgoingHeader { + background-color:#f5f5f5; + border-color:#fafafa #e3e3e3 #e3e3e3 #fafafa; + color: #6491d2; +} + +.ooutgoingHeader { + background-color:#ffbebe; + border-color:#fafafa #e3e3e3 #e3e3e3 #fafafa; + color: #244578; +} diff --git a/retroshare-gui/src/gui/qss/chat/private/ooutgoing.htm b/retroshare-gui/src/gui/qss/chat/private/ooutgoing.htm new file mode 100644 index 000000000..68f914367 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/private/ooutgoing.htm @@ -0,0 +1,14 @@ + + + + + + +
    %name%%time%
    + + + + +
    %message%
    \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/private/outgoing.htm b/retroshare-gui/src/gui/qss/chat/private/outgoing.htm new file mode 100644 index 000000000..7bf036a26 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/private/outgoing.htm @@ -0,0 +1,14 @@ + + + + + + +
    %name%%time%
    + + + + +
    %message%
    \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/private/variants/Standard.css b/retroshare-gui/src/gui/qss/chat/private/variants/Standard.css new file mode 100644 index 000000000..e69de29bb diff --git a/retroshare-gui/src/gui/qss/chat/public/hincoming.htm b/retroshare-gui/src/gui/qss/chat/public/hincoming.htm new file mode 100644 index 000000000..6b20807d5 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/public/hincoming.htm @@ -0,0 +1,7 @@ + + +%date% %time% +%name% +%message% diff --git a/retroshare-gui/src/gui/qss/chat/public/houtgoing.htm b/retroshare-gui/src/gui/qss/chat/public/houtgoing.htm new file mode 100644 index 000000000..b9c22da01 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/public/houtgoing.htm @@ -0,0 +1,7 @@ + + +%date% %time% +%name% +%message% diff --git a/retroshare-gui/src/gui/qss/chat/public/incoming.htm b/retroshare-gui/src/gui/qss/chat/public/incoming.htm new file mode 100644 index 000000000..f65d02b56 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/public/incoming.htm @@ -0,0 +1,7 @@ + + +%time% +%name% +%message% diff --git a/retroshare-gui/src/gui/qss/chat/public/info.xml b/retroshare-gui/src/gui/qss/chat/public/info.xml new file mode 100644 index 000000000..7f0445b03 --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/public/info.xml @@ -0,0 +1,12 @@ + + + + + + RetroShare Team + + + \ No newline at end of file diff --git a/retroshare-gui/src/gui/qss/chat/public/main.css b/retroshare-gui/src/gui/qss/chat/public/main.css new file mode 100644 index 000000000..d276a74ca --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/public/main.css @@ -0,0 +1,40 @@ +.incomingTime { + color:#C00000; +} + +.incomingName{ + color:#2D84C9; +} + +.outgoingTime { + color:#C00000; +} + +.outgoingName{ + color:#2D84C9; +} + +.hincomingTime { + color:#800000; +} + +.hincomingName{ + color:#1E5684; +} + +.houtgoingTime { + color:#800000; +} + +.houtgoingName{ + color:#1E5684; +} + +.ooutgoingTime { + color:#C00000; +} + +.ooutgoingName{ + color:#2D84C9; +} + diff --git a/retroshare-gui/src/gui/qss/chat/public/ooutgoing.htm b/retroshare-gui/src/gui/qss/chat/public/ooutgoing.htm new file mode 100644 index 000000000..715c9375a --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/public/ooutgoing.htm @@ -0,0 +1,7 @@ + + +%time% +%name% +%message% diff --git a/retroshare-gui/src/gui/qss/chat/public/outgoing.htm b/retroshare-gui/src/gui/qss/chat/public/outgoing.htm new file mode 100644 index 000000000..59e07d67f --- /dev/null +++ b/retroshare-gui/src/gui/qss/chat/public/outgoing.htm @@ -0,0 +1,7 @@ + + +%time% +%name% +%message% diff --git a/retroshare-gui/src/gui/qss/chat/public/variants/Standard.css b/retroshare-gui/src/gui/qss/chat/public/variants/Standard.css new file mode 100644 index 000000000..e69de29bb diff --git a/retroshare-gui/src/gui/settings/AddFileAssociationDialog.cpp b/retroshare-gui/src/gui/settings/AddFileAssociationDialog.cpp new file mode 100755 index 000000000..b34e1097e --- /dev/null +++ b/retroshare-gui/src/gui/settings/AddFileAssociationDialog.cpp @@ -0,0 +1,228 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "AddFileAssociationDialog.h" + +//#include "rshare.h" // for Rshare::dataDirectory() method +//#include "rsharesettings.h" +#include //for win registry access +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +//============================================================================ + +AddFileAssociationDialog::AddFileAssociationDialog(bool onlyEdit, + QWidget* parent) + :QDialog(parent) +{ + fileTypeLabel = new QLabel(); + fileTypeLabel->setText(tr("File type(extension):")); + + + fileTypeEdit = new QLineEdit(); + fileTypeEdit->setEnabled( !onlyEdit ); + fileTypeEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + fileTypeEdit->setFixedWidth(50); + connect(fileTypeEdit, SIGNAL( textEdited( const QString& )), + this , SLOT( fileTypeEdited(const QString & )) ) ; + + loadSystemDefault = new QPushButton(); + loadSystemDefault->setText(tr("Use default command")); + loadSystemDefault->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + loadSystemDefault->setEnabled( fileTypeEdit && + (!(fileTypeEdit->text().isEmpty())) ) ; + connect(loadSystemDefault, SIGNAL(clicked()), + this, SLOT(loadSystemDefaultCommand())); + loadSystemDefault->setVisible(false); //the button sholud remain unvisivle, + //until it will work properly + + commandLabel = new QLabel(); + commandLabel->setText(tr("Command")); + + commandEdit = new QLineEdit; + + selectExecutable = new QPushButton(); + selectExecutable->setText("..."); + selectExecutable->setFixedWidth(30); + + QHBoxLayout* ftlay = new QHBoxLayout(); + ftlay->addWidget( fileTypeLabel ); + ftlay->addWidget( fileTypeEdit ); + + buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok + | QDialogButtonBox::Cancel ); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + QGridLayout* mainLay = new QGridLayout(); + mainLay->addWidget(fileTypeLabel,0,0,1,1, Qt::AlignLeft); + mainLay->addWidget(fileTypeEdit,0,1,1,1, Qt::AlignLeft); + mainLay->addWidget(loadSystemDefault, 0,2,1,2,Qt::AlignRight); + mainLay->addWidget( commandLabel, 1,0,1,1, Qt::AlignLeft); + mainLay->addWidget( commandEdit, 1,1,1,2); + mainLay->addWidget( selectExecutable, 1,3,1,1); + mainLay->addWidget( buttonBox, 2,1,1,4, Qt::AlignLeft); + + mainLay->setColumnStretch(2,1); + mainLay->setRowStretch(2,1); + + this->setLayout( mainLay ); + + //TODO: in the next line we have to count a real height of the dialog; + // It's not good to use a hardcoded const value; + this->resize(600,200);//this->height()); + +} + +//============================================================================ + +void +AddFileAssociationDialog::fileTypeEdited(const QString & text ) +{ + loadSystemDefault->setEnabled( !( text.isEmpty() ) ); +} + +//============================================================================ + +void +AddFileAssociationDialog::setFileType(QString ft) +{ + fileTypeEdit->setText(ft); +} + +//============================================================================ + +void +AddFileAssociationDialog::loadSystemDefaultCommand() +{ + qDebug() << " lsdc is here"; + + QString fileExt = cleanFileType(fileTypeEdit->text()) ; + //fileExt.prepend('/'); + fileExt.append("/."); + qDebug() << " fileExt is " << fileExt; + QSettings reg("HKEY_CLASSES_ROOT", QSettings::NativeFormat); + + if (reg.contains(fileExt)) + { + QString appKey = reg.value(fileExt).toString(); + qDebug() << " got app key " << appKey; + appKey.append("/shell/open/command/."); + QString command = reg.value(appKey, "-").toString(); + if (command!="-") + { + qDebug() << " got command :" << command ; + commandEdit->setText( command ); + return; + } + } + + QMessageBox::warning(this, tr("RetroShare"), + tr("Sorry, can't determine system " + "default command for this file\n"), + QMessageBox::Ok); + + +} + +//============================================================================ + +QString +AddFileAssociationDialog::cleanFileType(QString ft) +{ + QString result = ft; + + //-- first remove possible filder names from received filename. (like + // "like "/moviedir/file.avi", we will leave only "file.avi" + int ti; + // dirs may be separated with "/" + ti = result.lastIndexOf('/'); + if (ti > -1) + { + result.remove(0,ti+1); + } + + // or "\" + ti = result.lastIndexOf('\\'); + if (ti > -1) + { + result.remove(0,ti+1); + } + + //-- then, if it is filename (like "file.avi"), we'll have to remove + //-- the name (ans leave just ".avi") + ti = result.lastIndexOf('.'); + if (ti > -1) + { + result.remove(0,ti); + return result; + } + + //-- also, if filename still is not prepended with dot, do it + if ((!result.isEmpty()) && (result.at(0)!='.')) + result.prepend('.'); + + //-- that's all + return result; +} + +//============================================================================ + +QString +AddFileAssociationDialog::resultCommand() +{ + return commandEdit->text(); +} + +//============================================================================ + +QString +AddFileAssociationDialog::resultFileType() +{ + return cleanFileType( fileTypeEdit->text() ) ; +} + +//============================================================================ + +void +AddFileAssociationDialog::setCommand(QString cmd) +{ + commandEdit->setText( cmd ); +} + +//============================================================================ + +//============================================================================ + + diff --git a/retroshare-gui/src/gui/settings/AddFileAssociationDialog.h b/retroshare-gui/src/gui/settings/AddFileAssociationDialog.h new file mode 100755 index 000000000..b247e8762 --- /dev/null +++ b/retroshare-gui/src/gui/settings/AddFileAssociationDialog.h @@ -0,0 +1,79 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef __AddFileAssociationDialog__ +#define __AddFileAssociationDialog__ + + +#include + +class QPushButton; +class QDialogButtonBox; + +class QLabel; +class QLineEdit; + +//============================================================================= +//! A dialog for specifying file type and associated command +class AddFileAssociationDialog: public QDialog +{ + Q_OBJECT +public: + //! constructor + + //! if (onlyEdit == true), user woll not be able to change file type, + //! only command (used for editing existing commands) + AddFileAssociationDialog( bool onlyEdit = false, QWidget *parent = 0 ) ; + virtual ~AddFileAssociationDialog(){}; + void setFileType(QString ft); + void setCommand(QString cmd); + + //! Gets file type (file extension) from given filename (or other string) + + //! "file type" has to be like '.png'(some symbols, prepended by a dot) + static QString cleanFileType(QString ft); + + QString resultCommand(); + QString resultFileType(); + +protected: + //QTabWidget *tabWidget; + QLabel* fileTypeLabel; + QLineEdit* fileTypeEdit; + QPushButton* loadSystemDefault; + QPushButton* selectExecutable; + QLabel* commandLabel; + QLineEdit* commandEdit; + QDialogButtonBox *buttonBox; + +protected slots: + void fileTypeEdited(const QString & text ); + + //! On win32, loads default command from system registry. + + //! Unfinished. Is not used in current version. + void loadSystemDefaultCommand(); + + +}; + +#endif + diff --git a/retroshare-gui/src/gui/settings/AppearancePage.cpp b/retroshare-gui/src/gui/settings/AppearancePage.cpp new file mode 100755 index 000000000..b5881c9a4 --- /dev/null +++ b/retroshare-gui/src/gui/settings/AppearancePage.cpp @@ -0,0 +1,138 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include "lang/languagesupport.h" +#include +#include "AppearancePage.h" +#include "rsharesettings.h" + + +/** Constructor */ +AppearancePage::AppearancePage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect(ui.styleSheetCombo, SIGNAL(clicked()), this, SLOT(loadStyleSheet())); + + /* Populate combo boxes */ + foreach (QString code, LanguageSupport::languageCodes()) { + ui.cmboLanguage->addItem(QIcon(":/images/flags/" + code + ".png"), + LanguageSupport::languageName(code), + code); + } + foreach (QString style, QStyleFactory::keys()) { + ui.cmboStyle->addItem(style, style.toLower()); + } + + //loadStyleSheet("Default"); + loadqss(); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +AppearancePage::~AppearancePage() +{ +} + +/** Saves the changes on this page */ +bool +AppearancePage::save(QString &errmsg) +{ + Q_UNUSED(errmsg); + QString languageCode = LanguageSupport::languageCode(ui.cmboLanguage->currentText()); + + Settings->setLanguageCode(languageCode); + Settings->setInterfaceStyle(ui.cmboStyle->currentText()); + Settings->setSheetName(ui.styleSheetCombo->currentText()); + + /* Set to new style */ + Rshare::setStyle(ui.cmboStyle->currentText()); + return true; +} + +/** Loads the settings for this page */ +void +AppearancePage::load() +{ + int index = ui.cmboLanguage->findData(Settings->getLanguageCode()); + ui.cmboLanguage->setCurrentIndex(index); + + index = ui.cmboStyle->findData(Rshare::style().toLower()); + ui.cmboStyle->setCurrentIndex(index); + + index = ui.styleSheetCombo->findText(Settings->getSheetName()); + if (index == -1) { + index = ui.styleSheetCombo->findText("noskin"); + } + ui.styleSheetCombo->setCurrentIndex(index); + + /** load saved internal styleSheet **/ + //QFile file(":/qss/" + (settings.getSheetName().toLower()) + ".qss"); + + /** load saved extern Stylesheets **/ + QFile file(QApplication::applicationDirPath() + "/qss/" + (Settings->getSheetName().toLower()) + ".qss"); + + file.open(QFile::ReadOnly); + QString styleSheet = QLatin1String(file.readAll()); + qApp->setStyleSheet(styleSheet); +} + +void AppearancePage::on_styleSheetCombo_activated(const QString &sheetName) +{ + loadStyleSheet(sheetName); +} + +void AppearancePage::loadStyleSheet(const QString &sheetName) +{ + /** internal Stylesheets **/ + //QFile file(":/qss/" + sheetName.toLower() + ".qss"); + + /** extern Stylesheets **/ + QFile file(QApplication::applicationDirPath() + "/qss/" + sheetName.toLower() + ".qss"); + + file.open(QFile::ReadOnly); + QString styleSheet = QLatin1String(file.readAll()); + + + qApp->setStyleSheet(styleSheet); + +} + +void AppearancePage::loadqss() +{ + + QFileInfoList slist = QDir(QApplication::applicationDirPath() + "/qss/").entryInfoList(); + foreach(QFileInfo st, slist) + { + if(st.fileName() != "." && st.fileName() != ".." && st.isFile()) + ui.styleSheetCombo->addItem(st.fileName().remove(".qss")); + } + +} diff --git a/retroshare-gui/src/gui/settings/AppearancePage.h b/retroshare-gui/src/gui/settings/AppearancePage.h new file mode 100755 index 000000000..195750922 --- /dev/null +++ b/retroshare-gui/src/gui/settings/AppearancePage.h @@ -0,0 +1,57 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _APPERARANCEPAGE_H +#define _APPERARANCEPAGE_H + +#include "configpage.h" +#include "ui_AppearancePage.h" + +class AppearancePage : public ConfigPage +{ + Q_OBJECT + + public: + /** Default Constructor */ + AppearancePage(QWidget * parent = 0, Qt::WFlags flags = 0); + /** Default Destructor */ + ~AppearancePage(); + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + + private slots: + + void on_styleSheetCombo_activated(const QString &styleSheetName); + + + private: + void loadStyleSheet(const QString &sheetName); + void loadqss(); + + /** Qt Designer generated object */ + Ui::AppearancePage ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/settings/AppearancePage.ui b/retroshare-gui/src/gui/settings/AppearancePage.ui new file mode 100755 index 000000000..5dd74eda3 --- /dev/null +++ b/retroshare-gui/src/gui/settings/AppearancePage.ui @@ -0,0 +1,685 @@ + + + AppearancePage + + + + 0 + 0 + 406 + 291 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + 6 + + + 0 + + + + + + 0 + 75 + + + + Qt::NoContextMenu + + + Language + + + + + + Qt::NoContextMenu + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + + + + + + 150 + 0 + + + + Qt::NoContextMenu + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + false + + + + 24 + 16 + + + + + + + + Qt::Horizontal + + + + 300 + 16 + + + + + + + + + + + + 0 + 64 + + + + Qt::NoContextMenu + + + + + + Style + + + + + + + 150 + 0 + + + + Qt::NoContextMenu + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + false + + + + + + + Qt::Horizontal + + + + 215 + 20 + + + + + + + + + + + + 0 + 64 + + + + Style Sheet + + + + + + + 150 + 0 + + + + + + + + Qt::Horizontal + + + + 215 + 20 + + + + + + + + + + + Qt::Vertical + + + + 361 + 61 + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/ChatPage.cpp b/retroshare-gui/src/gui/settings/ChatPage.cpp new file mode 100644 index 000000000..4ea9ff6a0 --- /dev/null +++ b/retroshare-gui/src/gui/settings/ChatPage.cpp @@ -0,0 +1,347 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "ChatPage.h" +#include "gui/chat/ChatStyle.h" +#include "gui/notifyqt.h" +#include "rsharesettings.h" + +#define VARIANT_STANDARD "Standard" + +static QString loadStyleInfo(ChatStyle::enumStyleType type, QListWidget *listWidget, QComboBox *comboBox, QString &styleVariant) +{ + QList styles; + QList::iterator style; + QListWidgetItem *item; + QListWidgetItem *activeItem = NULL; + + QString stylePath; + + switch (type) { + case ChatStyle::TYPE_PUBLIC: + Settings->getPublicChatStyle(stylePath, styleVariant); + break; + case ChatStyle::TYPE_PRIVATE: + Settings->getPrivateChatStyle(stylePath, styleVariant); + break; + case ChatStyle::TYPE_HISTORY: + Settings->getHistoryChatStyle(stylePath, styleVariant); + break; + case ChatStyle::TYPE_UNKNOWN: + return ""; + } + + ChatStyle::getAvailableStyles(type, styles); + for (style = styles.begin(); style != styles.end(); style++) { + item = new QListWidgetItem(style->styleName); + item->setData(Qt::UserRole, qVariantFromValue(*style)); + listWidget->addItem(item); + + if (style->stylePath == stylePath) { + activeItem = item; + } + } + + listWidget->setCurrentItem(activeItem); + + /* now the combobox should be filled */ + + int index = comboBox->findText(styleVariant); + if (index != -1) { + comboBox->setCurrentIndex(index); + } else { + if (comboBox->count()) { + comboBox->setCurrentIndex(0); + } + } + return stylePath; +} + +/** Constructor */ +ChatPage::ChatPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +/** Saves the changes on this page */ +bool +ChatPage::save(QString &errmsg) +{ + Settings->beginGroup(QString("Chat")); + + Settings->setValue(QString::fromUtf8("Emoteicons_PrivatChat"), ui.checkBox_emoteprivchat->isChecked()); + Settings->setValue(QString::fromUtf8("Emoteicons_GroupChat"), ui.checkBox_emotegroupchat->isChecked()); + Settings->setValue(QString::fromUtf8("GroupChat_History"), ui.checkBox_groupchathistory->isChecked()); + Settings->setValue(QString::fromUtf8("PrivateChat_History"), ui.checkBox_privatechathistory->isChecked()); + Settings->endGroup(); + + Settings->setChatScreenFont(fontTempChat.toString()); + + Settings->setChatSendMessageWithCtrlReturn(ui.sendMessageWithCtrlReturn->isChecked()); + + Settings->setPublicChatHistoryCount(ui.groupchatspinBox->value()); + Settings->setPrivateChatHistoryCount(ui.privatchatspinBox->value()); + + ChatStyleInfo info; + QListWidgetItem *item = ui.publicList->currentItem(); + if (item) { + info = qVariantValue(item->data(Qt::UserRole)); + if (publicStylePath != info.stylePath || publicStyleVariant != ui.publicComboBoxVariant->currentText()) { + Settings->setPublicChatStyle(info.stylePath, ui.publicComboBoxVariant->currentText()); + NotifyQt::getInstance()->notifyChatStyleChanged(ChatStyle::TYPE_PUBLIC); + } + } + + item = ui.privateList->currentItem(); + if (item) { + info = qVariantValue(item->data(Qt::UserRole)); + if (privateStylePath != info.stylePath || privateStyleVariant != ui.privateComboBoxVariant->currentText()) { + Settings->setPrivateChatStyle(info.stylePath, ui.privateComboBoxVariant->currentText()); + NotifyQt::getInstance()->notifyChatStyleChanged(ChatStyle::TYPE_PRIVATE); + } + } + + item = ui.historyList->currentItem(); + if (item) { + info = qVariantValue(item->data(Qt::UserRole)); + if (historyStylePath != info.stylePath || historyStyleVariant != ui.historyComboBoxVariant->currentText()) { + Settings->setHistoryChatStyle(info.stylePath, ui.historyComboBoxVariant->currentText()); + NotifyQt::getInstance()->notifyChatStyleChanged(ChatStyle::TYPE_HISTORY); + } + } + + return true; +} + +/** Loads the settings for this page */ +void +ChatPage::load() +{ + Settings->beginGroup(QString("Chat")); + + ui.checkBox_emoteprivchat->setChecked(Settings->value(QString::fromUtf8("Emoteicons_PrivatChat"), true).toBool()); + ui.checkBox_emotegroupchat->setChecked(Settings->value(QString::fromUtf8("Emoteicons_GroupChat"), true).toBool()); + ui.checkBox_groupchathistory->setChecked(Settings->value(QString::fromUtf8("GroupChat_History"), true).toBool()); + ui.checkBox_privatechathistory->setChecked(Settings->value(QString::fromUtf8("PrivateChat_History"), true).toBool()); + + Settings->endGroup(); + + fontTempChat.fromString(Settings->getChatScreenFont()); + + ui.sendMessageWithCtrlReturn->setChecked(Settings->getChatSendMessageWithCtrlReturn()); + + ui.groupchatspinBox->setValue(Settings->getPublicChatHistoryCount()); + ui.privatchatspinBox->setValue(Settings->getPrivateChatHistoryCount()); + + ui.labelChatFontPreview->setText(fontTempChat.rawName()); + ui.labelChatFontPreview->setFont(fontTempChat); + + /* Load styles */ + publicStylePath = loadStyleInfo(ChatStyle::TYPE_PUBLIC, ui.publicList, ui.publicComboBoxVariant, publicStyleVariant); + privateStylePath = loadStyleInfo(ChatStyle::TYPE_PRIVATE, ui.privateList, ui.privateComboBoxVariant, privateStyleVariant); + historyStylePath = loadStyleInfo(ChatStyle::TYPE_HISTORY, ui.historyList, ui.historyComboBoxVariant, historyStyleVariant); +} + +void ChatPage::on_pushButtonChangeChatFont_clicked() +{ + bool ok; + QFont font = QFontDialog::getFont(&ok, fontTempChat, this); + if (ok) { + fontTempChat = font; + ui.labelChatFontPreview->setText(fontTempChat.rawName()); + ui.labelChatFontPreview->setFont(fontTempChat); + } +} + +void ChatPage::setPreviewMessages(QString &stylePath, QString styleVariant, QTextBrowser *textBrowser) +{ + ChatStyle style; + style.setStylePath(stylePath, styleVariant); + + textBrowser->clear(); + + QString nameIncoming = "Incoming"; + QString nameOutgoing = "Outgoing"; + QDateTime timestmp = QDateTime::fromTime_t(time(NULL)); + QTextEdit textEdit; + QString message; + + textEdit.setText(tr("Incoming message in history")); + message = textEdit.toHtml(); + textBrowser->append(style.formatMessage(ChatStyle::FORMATMSG_HINCOMING, nameIncoming, timestmp, message, CHAT_FORMATTEXT_EMBED_SMILEYS)); + textEdit.setText(tr("Outgoing message in history")); + message = textEdit.toHtml(); + textBrowser->append(style.formatMessage(ChatStyle::FORMATMSG_HOUTGOING, nameOutgoing, timestmp, message, CHAT_FORMATTEXT_EMBED_SMILEYS)); + textEdit.setText(tr("Incoming message")); + message = textEdit.toHtml(); + textBrowser->append(style.formatMessage(ChatStyle::FORMATMSG_INCOMING, nameIncoming, timestmp, message, CHAT_FORMATTEXT_EMBED_SMILEYS)); + textEdit.setText(tr("Outgoing message")); + message = textEdit.toHtml(); + textBrowser->append(style.formatMessage(ChatStyle::FORMATMSG_OUTGOING, nameOutgoing, timestmp, message, CHAT_FORMATTEXT_EMBED_SMILEYS)); + textEdit.setText(tr("Outgoing offline message")); + message = textEdit.toHtml(); + textBrowser->append(style.formatMessage(ChatStyle::FORMATMSG_OOUTGOING, nameOutgoing, timestmp, message, CHAT_FORMATTEXT_EMBED_SMILEYS)); +} + +void ChatPage::fillPreview(QListWidget *listWidget, QComboBox *comboBox, QTextBrowser *textBrowser) +{ + QListWidgetItem *item = listWidget->currentItem(); + if (item) { + ChatStyleInfo info = qVariantValue(item->data(Qt::UserRole)); + + setPreviewMessages(info.stylePath, comboBox->currentText(), textBrowser); + } else { + textBrowser->clear(); + } +} + +void ChatPage::on_publicList_currentRowChanged(int currentRow) +{ + if (currentRow != -1) { + QListWidgetItem *item = ui.publicList->item(currentRow); + ChatStyleInfo info = qVariantValue(item->data(Qt::UserRole)); + + QString author = info.authorName; + if (info.authorEmail.isEmpty() == false) { + author += " (" + info.authorEmail + ")"; + } + ui.publicAuthor->setText(author); + ui.publicDescription->setText(info.styleDescription); + + QStringList variants; + ChatStyle::getAvailableVariants(info.stylePath, variants); + ui.publicComboBoxVariant->clear(); + ui.publicComboBoxVariant->setEnabled(variants.size() != 0); + ui.publicComboBoxVariant->addItems(variants); + + /* try to find "Standard" */ + int index = ui.publicComboBoxVariant->findText(VARIANT_STANDARD); + if (index != -1) { + ui.publicComboBoxVariant->setCurrentIndex(index); + } else { + ui.publicComboBoxVariant->setCurrentIndex(0); + } + } else { + ui.publicAuthor->clear(); + ui.publicDescription->clear(); + ui.publicComboBoxVariant->clear(); + ui.publicComboBoxVariant->setDisabled(true); + } + + fillPreview(ui.publicList, ui.publicComboBoxVariant, ui.publicPreview); +} + +void ChatPage::on_privateList_currentRowChanged(int currentRow) +{ + if (currentRow != -1) { + QListWidgetItem *item = ui.privateList->item(currentRow); + ChatStyleInfo info = qVariantValue(item->data(Qt::UserRole)); + + QString author = info.authorName; + if (info.authorEmail.isEmpty() == false) { + author += " (" + info.authorEmail + ")"; + } + ui.privateAuthor->setText(author); + ui.privateDescription->setText(info.styleDescription); + + QStringList variants; + ChatStyle::getAvailableVariants(info.stylePath, variants); + ui.privateComboBoxVariant->clear(); + ui.privateComboBoxVariant->setEnabled(variants.size() != 0); + ui.privateComboBoxVariant->addItems(variants); + + /* try to find "Standard" */ + int index = ui.privateComboBoxVariant->findText(VARIANT_STANDARD); + if (index != -1) { + ui.privateComboBoxVariant->setCurrentIndex(index); + } else { + ui.privateComboBoxVariant->setCurrentIndex(0); + } + } else { + ui.privateAuthor->clear(); + ui.privateDescription->clear(); + ui.privateComboBoxVariant->clear(); + ui.privateComboBoxVariant->setDisabled(true); + } + + fillPreview(ui.privateList, ui.privateComboBoxVariant, ui.privatePreview); +} + +void ChatPage::on_historyList_currentRowChanged(int currentRow) +{ + if (currentRow != -1) { + QListWidgetItem *item = ui.historyList->item(currentRow); + ChatStyleInfo info = qVariantValue(item->data(Qt::UserRole)); + + QString author = info.authorName; + if (info.authorEmail.isEmpty() == false) { + author += " (" + info.authorEmail + ")"; + } + ui.historyAuthor->setText(author); + ui.historyDescription->setText(info.styleDescription); + + QStringList variants; + ChatStyle::getAvailableVariants(info.stylePath, variants); + ui.historyComboBoxVariant->clear(); + ui.historyComboBoxVariant->setEnabled(variants.size() != 0); + ui.historyComboBoxVariant->addItems(variants); + + /* try to find "Standard" */ + int index = ui.historyComboBoxVariant->findText(VARIANT_STANDARD); + if (index != -1) { + ui.historyComboBoxVariant->setCurrentIndex(index); + } else { + ui.historyComboBoxVariant->setCurrentIndex(0); + } + } else { + ui.historyAuthor->clear(); + ui.historyDescription->clear(); + ui.historyComboBoxVariant->clear(); + ui.historyComboBoxVariant->setDisabled(true); + } + + fillPreview(ui.historyList, ui.historyComboBoxVariant, ui.historyPreview); +} + +void ChatPage::on_publicComboBoxVariant_currentIndexChanged(int index) +{ + fillPreview(ui.publicList, ui.publicComboBoxVariant, ui.publicPreview); +} + +void ChatPage::on_privateComboBoxVariant_currentIndexChanged(int index) +{ + fillPreview(ui.privateList, ui.privateComboBoxVariant, ui.privatePreview); +} + +void ChatPage::on_historyComboBoxVariant_currentIndexChanged(int index) +{ + fillPreview(ui.historyList, ui.historyComboBoxVariant, ui.historyPreview); +} diff --git a/retroshare-gui/src/gui/settings/ChatPage.h b/retroshare-gui/src/gui/settings/ChatPage.h new file mode 100644 index 000000000..3704ed389 --- /dev/null +++ b/retroshare-gui/src/gui/settings/ChatPage.h @@ -0,0 +1,70 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CHATPAGE_H +#define _CHATPAGE_H + +#include "configpage.h" +#include "ui_ChatPage.h" + +class ChatPage : public ConfigPage +{ + Q_OBJECT + + public: + /** Default Constructor */ + ChatPage(QWidget * parent = 0, Qt::WFlags flags = 0); + /** Default Destructor */ + ~ChatPage() {} + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + + private slots: + void on_historyComboBoxVariant_currentIndexChanged(int index); + void on_privateComboBoxVariant_currentIndexChanged(int index); + void on_publicComboBoxVariant_currentIndexChanged(int index); + void on_pushButtonChangeChatFont_clicked(); + void on_publicList_currentRowChanged(int currentRow); + void on_privateList_currentRowChanged(int currentRow); + void on_historyList_currentRowChanged(int currentRow); + + private: + void setPreviewMessages(QString &stylePath, QString styleVariant, QTextBrowser *textBrowser); + void fillPreview(QListWidget *listWidget, QComboBox *comboBox, QTextBrowser *textBrowser); + + QFont fontTempChat; + + QString publicStylePath; + QString publicStyleVariant; + QString privateStylePath; + QString privateStyleVariant; + QString historyStylePath; + QString historyStyleVariant; + + /** Qt Designer generated object */ + Ui::ChatPage ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/settings/ChatPage.ui b/retroshare-gui/src/gui/settings/ChatPage.ui new file mode 100644 index 000000000..87a448d94 --- /dev/null +++ b/retroshare-gui/src/gui/settings/ChatPage.ui @@ -0,0 +1,1142 @@ + + + ChatPage + + + + 0 + 0 + 405 + 326 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + 0 + + + + General + + + + + + + 0 + 0 + + + + Chat Settings + + + + + + Enable Emoticons Privat Chat + + + true + + + + + + + + 16777215 + 16777215 + + + + + + + Chat Font + + + + 2 + + + 0 + + + 0 + + + 0 + + + 2 + + + + + Change Chat Font + + + + + + + + 0 + 0 + + + + Chat Font: + + + + + + + Font Preview + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Enable Emoticons Group Chat + + + true + + + + + + + Enable Private Chat History + + + + + + + Enable Group Chat History + + + true + + + + + + + Send message with Ctrl+Return + + + + + + + Chat History + + + + + + Load number of messages (0 = off) + + + + + + + + + Group Chat + + + + + + + + + + + + + 20 + + + + + + + Private Chat + + + + + + + 20 + + + + + + + + + Qt::Vertical + + + + 176 + 480 + + + + + + + + + + + + + + + Style + + + + + + QTabWidget::North + + + 0 + + + + Group chat + + + + + + + + + + + 0 + 0 + + + + + 170 + 16777215 + + + + + + + + + + + 0 + 0 + + + + Variant + + + + + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + QLayout::SetFixedSize + + + + + + 0 + 0 + + + + Author: + + + + + + + + 0 + 0 + + + + Description: + + + + + + + + + + + + 0 + 0 + + + + Author + + + + + + + + 0 + 0 + + + + Description + + + + + + + + + + + + Private chat + + + + + + + + + + + 0 + 0 + + + + + 170 + 16777215 + + + + + + + + + + + 0 + 0 + + + + Variant + + + + + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + QLayout::SetFixedSize + + + + + + 0 + 0 + + + + Author: + + + + + + + + 0 + 0 + + + + Description: + + + + + + + + + + + + 0 + 0 + + + + Author + + + + + + + + 0 + 0 + + + + Description + + + + + + + + + + + + History + + + + + + + + + + + 0 + 0 + + + + + 170 + 16777215 + + + + + + + + + + + 0 + 0 + + + + Variant + + + + + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + QLayout::SetFixedSize + + + + + + 0 + 0 + + + + Author: + + + + + + + + 0 + 0 + + + + Description: + + + + + + + + + + + + 0 + 0 + + + + Author + + + + + + + + 0 + 0 + + + + Description + + + + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/CryptoPage.cpp b/retroshare-gui/src/gui/settings/CryptoPage.cpp new file mode 100755 index 000000000..9fbb52f66 --- /dev/null +++ b/retroshare-gui/src/gui/settings/CryptoPage.cpp @@ -0,0 +1,115 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include + +#include "CryptoPage.h" +#include "util/misc.h" + +#include //for rsPeers variable + +/** Constructor */ +CryptoPage::CryptoPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect(ui.copykeyButton, SIGNAL(clicked()), this, SLOT(copyPublicKey())); + connect(ui.saveButton, SIGNAL(clicked()), this, SLOT(fileSaveAs())); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +CryptoPage::~CryptoPage() +{ +} + +/** Saves the changes on this page */ +bool +CryptoPage::save(QString &errmsg) +{ + return true; +} + +/** Loads the settings for this page */ +void +CryptoPage::load() +{ + /* Loads ouer default Puplickey */ + QFont font("Courier New",9,50,false) ; + ui.certtextEdit->setFont(font) ; + + ui.certtextEdit->setPlainText(QString::fromStdString(rsPeers->GetRetroshareInvite())); + ui.certtextEdit->setReadOnly(true); + ui.certtextEdit->setMinimumHeight(200); +} + +void +CryptoPage::copyPublicKey() +{ + QMessageBox::information(this, + tr("RetroShare"), + tr("Your Public Key is copied to Clipboard, paste and send it to your" + " friend via email or some other way")); + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(ui.certtextEdit->toPlainText()); +} + +bool CryptoPage::fileSave() +{ + if (fileName.isEmpty()) + return fileSaveAs(); + + QFile file(fileName); + if (!file.open(QFile::WriteOnly)) + return false; + QTextStream ts(&file); + ts.setCodec(QTextCodec::codecForName("UTF-8")); + ts << ui.certtextEdit->document()->toPlainText(); + ui.certtextEdit->document()->setModified(false); + return true; +} + +bool CryptoPage::fileSaveAs() +{ + QString fn; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_CERT, tr("Save as..."), tr("RetroShare Certificate (*.rsc );;All Files (*)"), fn)) { + setCurrentFileName(fn); + return fileSave(); + } + return false; +} + +void CryptoPage::setCurrentFileName(const QString &fileName) +{ + this->fileName = fileName; + ui.certtextEdit->document()->setModified(false); + + setWindowModified(false); +} diff --git a/retroshare-gui/src/gui/settings/CryptoPage.h b/retroshare-gui/src/gui/settings/CryptoPage.h new file mode 100755 index 000000000..9ca39b9f5 --- /dev/null +++ b/retroshare-gui/src/gui/settings/CryptoPage.h @@ -0,0 +1,59 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CRYPTOPAGE_H +#define _CRYPTOPAGE_H + +#include "configpage.h" +#include "ui_CryptoPage.h" + +class CryptoPage : public ConfigPage +{ + Q_OBJECT + + public: + /** Default Constructor */ + CryptoPage(QWidget * parent = 0, Qt::WFlags flags = 0); + /** Default Destructor */ + ~CryptoPage(); + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + + private slots: + void copyPublicKey(); + + bool fileSave(); + bool fileSaveAs(); + + private: + void setCurrentFileName(const QString &fileName); + + QString fileName; + + /** Qt Designer generated object */ + Ui::CryptoPage ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/settings/CryptoPage.ui b/retroshare-gui/src/gui/settings/CryptoPage.ui new file mode 100755 index 000000000..e444f169b --- /dev/null +++ b/retroshare-gui/src/gui/settings/CryptoPage.ui @@ -0,0 +1,571 @@ + + + CryptoPage + + + + 0 + 0 + 542 + 355 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + Public Key + + + + + + + false + + + + false + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + Copy Key + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + Save Key + + + + + + + Qt::Horizontal + + + + 278 + 20 + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/DirectoriesPage.cpp b/retroshare-gui/src/gui/settings/DirectoriesPage.cpp new file mode 100755 index 000000000..96f426273 --- /dev/null +++ b/retroshare-gui/src/gui/settings/DirectoriesPage.cpp @@ -0,0 +1,154 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "DirectoriesPage.h" +#include "gui/ShareManager.h" +#include + +#include "rshare.h" +#include + +#include + +DirectoriesPage::DirectoriesPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + ui.setupUi(this); + + connect(ui.incomingButton, SIGNAL(clicked( bool ) ), this , SLOT( setIncomingDirectory() ) ); + connect(ui.partialButton, SIGNAL(clicked( bool ) ), this , SLOT( setPartialsDirectory() ) ); + connect(ui.editShareButton, SIGNAL(clicked()), this, SLOT(editDirectories())); + connect(ui.cleanHashCachePB, SIGNAL(clicked()), this, SLOT(clearHashCache())); + connect(ui.rememberHashesCB, SIGNAL(clicked(bool)), this, SLOT(clickedRememberHashes(bool))); + connect(ui.rememberHashesCB, SIGNAL(clicked(bool)), this, SLOT(toggleRememberHashes())); + connect(ui.autoCheckDirectories_CB, SIGNAL(clicked(bool)), this, SLOT(toggleAutoCheckDirectories(bool))); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +void DirectoriesPage::clearHashCache() +{ + if(QMessageBox::question(this,"Cache cleaning confirmation","The will forget any former hash of non shared files. Do you confirm ?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) + rsFiles->clearHashCache() ; +} + +void DirectoriesPage::toggleAutoCheckDirectories(bool b) +{ + ui.autoCheckDirectoriesDelay_SB->setEnabled(b); +} + +void DirectoriesPage::editDirectories() +{ + ShareManager::showYourself() ; +} + +void DirectoriesPage::clickedRememberHashes(bool b) +{ + if (!b) { + if (QMessageBox::question(this,"Cache cleaning confirmation","The will forget any former hash of non shared files. Do you confirm ?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) { + ui.rememberHashesCB->setChecked(true); + } + } +} + +void DirectoriesPage::toggleRememberHashes() +{ + bool b = ui.rememberHashesCB->isChecked(); + ui.rememberHashesSB->setEnabled(b); + ui.cleanHashCachePB->setEnabled(b); +} + +/** Saves the changes on this page */ +bool DirectoriesPage::save(QString &errmsg) +{ + rsFiles->setRememberHashFilesDuration(ui.rememberHashesSB->value()); + rsFiles->setWatchPeriod(ui.autoCheckDirectoriesDelay_SB->value()); + + std::string dir = ui.incomingDir->text().toUtf8().constData(); + if (!dir.empty()) + { + rsFiles->setDownloadDirectory(dir); + } + + dir = ui.partialsDir->text().toUtf8().constData(); + if (!dir.empty()) + { + rsFiles->setPartialsDirectory(dir); + } + + if (ui.rememberHashesCB->isChecked()) { + rsFiles->setRememberHashFiles(true); + } else { + rsFiles->setRememberHashFiles(false); + rsFiles->clearHashCache() ; + } + + if (ui.autoCheckDirectories_CB->isChecked()) { + rsFiles->setWatchPeriod(ui.autoCheckDirectoriesDelay_SB->value()); + } else { + rsFiles->setWatchPeriod(-ui.autoCheckDirectoriesDelay_SB->value()); + } + + rsFiles->shareDownloadDirectory(ui.shareDownloadDirectoryCB->isChecked()); + + return true; +} + +/** Loads the settings for this page */ +void DirectoriesPage::load() +{ + ui.shareDownloadDirectoryCB->setChecked(rsFiles->getShareDownloadDirectory()); + + ui.rememberHashesSB->setValue(rsFiles->rememberHashFilesDuration()); + ui.rememberHashesCB->setChecked(rsFiles->rememberHashFiles()); + toggleRememberHashes(); + + int u = rsFiles->watchPeriod() ; + ui.autoCheckDirectoriesDelay_SB->setValue(abs(u)) ; + ui.autoCheckDirectories_CB->setChecked(u>0) ; + ui.autoCheckDirectoriesDelay_SB->setEnabled(u>0) ; + + ui.incomingDir->setText(QString::fromUtf8(rsFiles->getDownloadDirectory().c_str())); + ui.partialsDir->setText(QString::fromUtf8(rsFiles->getPartialsDirectory().c_str())); +} + +void DirectoriesPage::setIncomingDirectory() +{ + QString qdir = QFileDialog::getExistingDirectory(this, tr("Set Incoming Directory"), "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (qdir.isEmpty()) { + return; + } + + ui.incomingDir->setText(qdir); +} + +void DirectoriesPage::setPartialsDirectory() +{ + QString qdir = QFileDialog::getExistingDirectory(this, tr("Set Partials Directory"), "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (qdir.isEmpty()) { + return; + } + + ui.partialsDir->setText(qdir); +} diff --git a/retroshare-gui/src/gui/settings/DirectoriesPage.h b/retroshare-gui/src/gui/settings/DirectoriesPage.h new file mode 100755 index 000000000..3f035c836 --- /dev/null +++ b/retroshare-gui/src/gui/settings/DirectoriesPage.h @@ -0,0 +1,54 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef DIRECTORIESPAGE_H +#define DIRECTORIESPAGE_H + +#include "configpage.h" +#include "ui_DirectoriesPage.h" + +class DirectoriesPage: public ConfigPage +{ + Q_OBJECT + +public: + DirectoriesPage(QWidget * parent = 0, Qt::WFlags flags = 0); + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + +private slots: + void editDirectories() ; + void setIncomingDirectory(); + void setPartialsDirectory(); + void clearHashCache(); + void clickedRememberHashes(bool); + void toggleRememberHashes(); + void toggleAutoCheckDirectories(bool); + +private: + Ui::DirectoriesPage ui; +}; + +#endif // !GENERALPAGE_H + diff --git a/retroshare-gui/src/gui/settings/DirectoriesPage.ui b/retroshare-gui/src/gui/settings/DirectoriesPage.ui new file mode 100755 index 000000000..79238f049 --- /dev/null +++ b/retroshare-gui/src/gui/settings/DirectoriesPage.ui @@ -0,0 +1,740 @@ + + + DirectoriesPage + + + + 0 + 0 + 485 + 549 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 10 + 50 + false + false + false + false + + + + true + + + Qt::NoContextMenu + + + + 6 + + + 0 + + + + + Incoming Directory + + + + + + true + + + + + + + + 31 + 31 + + + + + 31 + 31 + + + + Browse + + + + + + + :/images/directoryselect_24x24_shadow.png:/images/directoryselect_24x24_shadow.png + + + + 24 + 24 + + + + + + + + + + + Partials Directory + + + + + + true + + + + + + + + 31 + 31 + + + + + 31 + 31 + + + + Browse + + + + + + + :/images/directoryselect_24x24_shadow.png:/images/directoryselect_24x24_shadow.png + + + + 24 + 24 + + + + + + + + + + + Shared Directories + + + + + + + + true + + + Automatically share incoming directory (Recommended) + + + true + + + + + + + Edit Share + + + + + + + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + Remember hashed files for + + + true + + + + + + + days + + + 1 + + + 365 + + + 10 + + + + + + + Forget any hashed file that is not anymore shared. + + + Clean Hash Cache + + + + + + + + + + + Auto-check shared directories every + + + true + + + + + + + minute(s) + + + 1 + + + 5000 + + + 10 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + incomingDir + incomingButton + + + + + + diff --git a/retroshare-gui/src/gui/settings/FileAssociationsPage.cpp b/retroshare-gui/src/gui/settings/FileAssociationsPage.cpp new file mode 100755 index 000000000..cba53d501 --- /dev/null +++ b/retroshare-gui/src/gui/settings/FileAssociationsPage.cpp @@ -0,0 +1,373 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "FileAssociationsPage.h" +#include "AddFileAssociationDialog.h" +//#include "rshare.h" // for Rshare::dataDirectory() method +#include "rsharesettings.h" + +#include +#include + +#include +#include +#include +#include + +//#include +//#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +//#include + +//============================================================================ + +FileAssociationsPage::FileAssociationsPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +//:QFrame() +{ + QVBoxLayout* pageLay = new QVBoxLayout(this); + + toolBar = new QToolBar("actions", this); + newAction = new QAction(QIcon(":/images/add_24x24.png"), tr("&New"), this); + //newAction->setShortcut(tr("Ctrl+N")); + newAction->setStatusTip(tr("Add new Association")); + connect(newAction, SIGNAL(triggered()), this, SLOT(addnew())); + toolBar->addAction(newAction); + + editAction = new QAction(QIcon(":/images/kcmsystem24.png"), + tr("&Edit"), this); + editAction->setStatusTip(tr("Edit this Association")); + connect(editAction, SIGNAL(triggered()), this, SLOT(edit())); + toolBar->addAction(editAction); + + removeAction = new QAction(QIcon(":/images/edit_remove24.png"), + tr("&Remove"), this); + removeAction->setStatusTip(tr("Remove this Association")); + connect(removeAction, SIGNAL(triggered()), this, SLOT(remove())); + toolBar->addAction( removeAction ); + + pageLay->addWidget( toolBar ); + + table = new QTableWidget(5,2,this);//default 5 rows, 2 columns + table->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("File type") ) ); + + table->setHorizontalHeaderItem(1, new QTableWidgetItem("Command") ); + connect( table, SIGNAL( cellActivated(int, int)), + this, SLOT( tableCellActivated(int, int)) ); + connect( table, SIGNAL( cellClicked(int, int)), + this, SLOT( tableCellActivated(int, int)) ); + +// connect( table, SIGNAL( cellChanged(int, int)), +// this, SLOT( tableCellActivated(int, int)) ); +// +// connect( table, SIGNAL( cellDoubleClicked(int, int)), +// this, SLOT( tableCellActivated(int, int)) ); +// +// connect( table, SIGNAL( cellEntered(int, int)), +// this, SLOT( tableCellActivated(int, int)) ); +// +// connect( table, SIGNAL( cellPressed(int, int)), +// this, SLOT( tableCellActivated(int, int)) ); + + +// connect( table, SIGNAL( itemClicked(QTableWidgetItem*)), +// this, SLOT( tableItemActivated(QTableWidgetItem*)) ); + + pageLay->addWidget(table); + +// addNewAssotiationButton = new QPushButton; +// addNewAssotiationButton->setText(tr("Add..")); +// QHBoxLayout* anbLay = new QHBoxLayout; +// anbLay->addStretch(); +// anbLay->addWidget(addNewAssotiationButton); +// pageLay->addLayout(anbLay); +// connect( addNewAssotiationButton, SIGNAL( clicked() ), +// this, SLOT( testButtonClicked() ) ); + +// RshareSettings settings; + //new QSettings( qApp->applicationDirPath()+"/sett.ini", + // QSettings::IniFormat); +// settings.beginGroup("FileAssociations"); + + + +} + +//============================================================================ + +FileAssociationsPage::~FileAssociationsPage() +{ +} + +//============================================================================ + +bool +FileAssociationsPage::save (QString &errmsg) +{ +// RshareSettings settings; + + +// settings.beginGroup("FileAssotiations"); +// settings.setValue(".s01", "s01 test"); +// settings.setValue(".s02", "s02 test"); +// settings.setValue(".s03", "s03 test"); +// settings.setValue(".s04", "s04 test"); +// QMap::const_iterator ati = ations.constBegin(); +// while (ati != ations.constEnd()) +// { +// settings.setValue( ati.key(), ati.value() ); +// qDebug() << " - " << ati.key() << ati.value() << "\n" ; +// ati++; +// } +// +// settings.endGroup(); + +// settings.sync(); + +// delete settings; +/* */ + return true; +} + +//============================================================================ + +void +FileAssociationsPage::load() +{ +// Settings->beginGroup("FileAssotiations"); + QStringList keys = Settings->allKeys(); + + table->setRowCount( keys.count() ); + + int rowi = 0; + QStringList::const_iterator ki; + for(ki=keys.constBegin(); ki!=keys.constEnd(); ki++) + { + QString val = (Settings->value(*ki, "")).toString(); + + addNewItemToTable( rowi, 0, *ki ); + addNewItemToTable( rowi, 1, val ); + + rowi++; + } + + if (keys.count()==0) + { + removeAction->setEnabled(false); + editAction->setEnabled(false); + } + + table->selectRow(0); +} + +//============================================================================ + +void +FileAssociationsPage::remove() +{ + int currentRow = table->currentRow() ; + QTableWidgetItem const * titem = table->item( currentRow,0); + QString key = (titem->data(QTableWidgetItem::Type)).toString(); + + Settings->remove(key); + table->removeRow( currentRow ); + + if ( table->rowCount()==0 ) + { + removeAction->setEnabled(false); + editAction->setEnabled(false); + } +} + +//============================================================================ + +void +FileAssociationsPage::addnew() +{ + AddFileAssociationDialog afad(false, this);//'add file assotiations' dialog + + int currentRow = table->currentRow() ; + QTableWidgetItem* titem; + + int ti = afad.exec(); + + if (ti==QDialog::Accepted) + { + QString currType = afad.resultFileType() ; + QString currCmd = afad.resultCommand() ; + + + if ( !Settings->contains(currType) )//new item should be added only if + { // it wasn't entered before. + int nridx = table->rowCount();//new row index + table->setRowCount(nridx+1); + addNewItemToTable(nridx,0, currType) ; + addNewItemToTable(nridx,1, currCmd); + } + else + { + for(int rowi=0; rowirowCount(); rowi++) + { + titem = table->item( rowi, 0); + if (titem->data(QTableWidgetItem::Type).toString()==currType) + { + titem = table->item( rowi, 1); + titem->setData(QTableWidgetItem::Type, currCmd); + break; + } + } + } + + Settings->setValue(currType, currCmd); + + removeAction->setEnabled(true); + editAction->setEnabled(true); + } +} + +//============================================================================ + +void +FileAssociationsPage::edit() +{ + AddFileAssociationDialog afad(true, this);//'add file assotiations' dialog + + int currentRow = table->currentRow() ; + QTableWidgetItem* titem; + + titem = table->item( currentRow,0); + QString currType = (titem->data(QTableWidgetItem::Type)).toString(); + titem = table->item( currentRow,1); + QString currCmd = (titem->data(QTableWidgetItem::Type)).toString(); + afad.setCommand(currCmd); + afad.setFileType(currType); + + int ti = afad.exec(); + + if (ti==QDialog::Accepted) + { + currCmd = afad.resultCommand() ; + titem = table->item( currentRow,1); + + titem->setData(QTableWidgetItem::Type, currCmd); + + Settings->setValue(currType, currCmd); + } +} + +//============================================================================ + +void +FileAssociationsPage::tableCellActivated ( int row, int column ) +{ + table->selectRow(row); +} + +//============================================================================ + +void +FileAssociationsPage::tableItemActivated ( QTableWidgetItem * item ) +{ + qDebug() << "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\n"; + QMessageBox::information(this, + tr(" Friend Help"), + tr("You this")); + table->selectRow(table->row(item)); + +} + +//============================================================================ + +void +FileAssociationsPage::addNewItemToTable(int row, int column, + QString itemText) +{ + QTableWidgetItem* tmpitem ; + + tmpitem = new QTableWidgetItem(itemText) ; + tmpitem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + // | Qt::ItemIsUserCheckable); + table->setItem(row, column, tmpitem ); +} + +//============================================================================ + +void +FileAssociationsPage::testButtonClicked() +{ + AddFileAssociationDialog afad(this);// = new AddFileAssotiationDialog(); + +// commented code below is a test for +// AddFileAssotiationDialog::loadSystemDefaultCommand(QString ft) method +// QString tmps; +// tmps = "/home/folder/file"; +// qDebug() << " for " << tmps <<" is " << afad.cleanFileType(tmps); +// tmps = "/home/folder/file.avi"; +// qDebug() << " for " << tmps <<" is " << afad.cleanFileType(tmps); +// tmps = "file.avi"; +// qDebug() << " for " << tmps <<" is " << afad.cleanFileType(tmps); +// tmps = ".file"; +// qDebug() << " for " << tmps <<" is " << afad.cleanFileType(tmps); +// tmps = "c:\\home\\folder\\file"; +// qDebug() << " for " << tmps <<" is " << afad.cleanFileType(tmps); +// tmps = "/home/folder/.file"; +// qDebug() << " for " << tmps <<" is " << afad.cleanFileType(tmps); +// tmps = "D:\\folder\\file.asd.avi"; +// qDebug() << " for " << tmps <<" is " << afad.cleanFileType(tmps); + + + + int ti = afad.exec(); + + if (ti==QDialog::Accepted) + { + qDebug() << " dialog was accepted"; + QProcess::execute(afad.resultCommand());//, + //QStringList("D:\\prog\\eclipse_workspace\\tapp-fa\\tt.txt") ); + qDebug() << " process finished?"; + } + else + if (ti == QDialog::Rejected) + qDebug() << " dialog rejected" ; + else + qDebug() << "dialog returned something else" ; + + +} + +//============================================================================ + + + diff --git a/retroshare-gui/src/gui/settings/FileAssociationsPage.h b/retroshare-gui/src/gui/settings/FileAssociationsPage.h new file mode 100755 index 000000000..bc51cd13c --- /dev/null +++ b/retroshare-gui/src/gui/settings/FileAssociationsPage.h @@ -0,0 +1,81 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 The RetroShare Team, Oleksiy Bilyanskyy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef __FileAssociationsPage__ +#define __FileAssociationsPage__ + +#include "configpage.h" + +class QToolBar; +class QAction; +class QTableWidget; +class QTableWidgetItem; +class QPushButton; +class QDialogButtonBox; + + +class QLabel; +class QLineEdit; + +//class QSettings; + +//============================================================================= +//! Dialog for setting file assotiations for RS + +//! With this config page user can specify, what programs should be executed +//! to open some types of files. Here 'type' means 'file extension'(and +//! 'file extension' means 'some symbols after last dot in filename'). +class FileAssociationsPage : public ConfigPage +{ + Q_OBJECT + +public: + FileAssociationsPage(QWidget * parent = 0, Qt::WFlags flags = 0); + virtual ~FileAssociationsPage(); + + void load(); + bool save (QString &errmsg); + +protected: + QToolBar* toolBar; + + QAction* newAction; + QAction* editAction; + QAction* removeAction; + + QTableWidget* table; + QPushButton* addNewAssotiationButton; + QString settingsFileName; + + void addNewItemToTable(int row, int column, QString itemText); + +protected slots: + void remove(); + void addnew(); + void edit(); + void tableCellActivated ( int row, int column ); + void tableItemActivated ( QTableWidgetItem * item ) ; + void testButtonClicked();//! slot for debuggin purposes, nnot really used +}; + + + +#endif diff --git a/retroshare-gui/src/gui/settings/ForumPage.cpp b/retroshare-gui/src/gui/settings/ForumPage.cpp new file mode 100644 index 000000000..98a49a124 --- /dev/null +++ b/retroshare-gui/src/gui/settings/ForumPage.cpp @@ -0,0 +1,56 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "ForumPage.h" +#include "rshare.h" +#include "rsharesettings.h" + +#include "../MainWindow.h" +#include "../ForumsDialog.h" + +ForumPage::ForumPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + ui.setupUi(this); + setAttribute(Qt::WA_QuitOnClose, false); +} + +ForumPage::~ForumPage() +{ +} + +/** Saves the changes on this page */ +bool +ForumPage::save(QString &errmsg) +{ + Settings->setForumMsgSetToReadOnActivate(ui.setMsgToReadOnActivate->isChecked()); + Settings->setExpandNewMessages(ui.expandNewMessages->isChecked()); + + return true; +} + +/** Loads the settings for this page */ +void +ForumPage::load() +{ + ui.setMsgToReadOnActivate->setChecked(Settings->getForumMsgSetToReadOnActivate()); + ui.expandNewMessages->setChecked(Settings->getExpandNewMessages()); +} diff --git a/retroshare-gui/src/gui/settings/ForumPage.h b/retroshare-gui/src/gui/settings/ForumPage.h new file mode 100644 index 000000000..c381e5601 --- /dev/null +++ b/retroshare-gui/src/gui/settings/ForumPage.h @@ -0,0 +1,46 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef FORUMPAGE_H +#define FORUMPAGE_H + +#include "configpage.h" +#include "ui_ForumPage.h" + +class ForumPage : public ConfigPage +{ + Q_OBJECT + +public: + ForumPage(QWidget * parent = 0, Qt::WFlags flags = 0); + ~ForumPage(); + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + +private: + Ui::ForumPage ui; +}; + +#endif // !FORUMPAGE_H + diff --git a/retroshare-gui/src/gui/settings/ForumPage.ui b/retroshare-gui/src/gui/settings/ForumPage.ui new file mode 100644 index 000000000..b6b4b2940 --- /dev/null +++ b/retroshare-gui/src/gui/settings/ForumPage.ui @@ -0,0 +1,543 @@ + + + ForumPage + + + + 0 + 0 + 423 + 340 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + Misc + + + + + + Set message to read on activate + + + + + + + Expand new messages + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/GeneralPage.cpp b/retroshare-gui/src/gui/settings/GeneralPage.cpp new file mode 100755 index 000000000..ffea345d1 --- /dev/null +++ b/retroshare-gui/src/gui/settings/GeneralPage.cpp @@ -0,0 +1,91 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include "GeneralPage.h" +#include +#include +#include "rsharesettings.h" + +/** Constructor */ +GeneralPage::GeneralPage(QWidget * parent, Qt::WFlags flags) +: ConfigPage(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + /* Hide platform specific features */ +#ifndef Q_WS_WIN + ui.chkRunRetroshareAtSystemStartup->setVisible(false); + ui.chkRunRetroshareAtSystemStartupMinimized->setVisible(false); + ui.enableRetroShareProtocol->setVisible(false); +#endif +} + +/** Destructor */ +GeneralPage::~GeneralPage() +{ +} + +/** Saves the changes on this page */ +bool GeneralPage::save(QString &errmsg) +{ + Settings->setStartMinimized(ui.checkStartMinimized->isChecked()); + Settings->setValue("doQuit", ui.checkQuit->isChecked()); + Settings->setCloseToTray(ui.checkClosetoTray->isChecked()); + +#ifdef Q_WS_WIN + Settings->setRunRetroshareOnBoot(ui.chkRunRetroshareAtSystemStartup->isChecked(), ui.chkRunRetroshareAtSystemStartupMinimized->isChecked()); + + if (ui.enableRetroShareProtocol->isChecked() != Settings->getRetroShareProtocol()) { + Settings->setRetroShareProtocol(ui.enableRetroShareProtocol->isChecked()); + } +#endif + + Settings->setMaxTimeBeforeIdle(ui.spinBox->value()); + + RsInit::setAutoLogin(ui.autoLogin->isChecked()); + + return true; +} + +/** Loads the settings for this page */ +void GeneralPage::load() +{ +#ifdef Q_WS_WIN + bool minimized; + ui.chkRunRetroshareAtSystemStartup->setChecked(Settings->runRetroshareOnBoot(minimized)); + ui.chkRunRetroshareAtSystemStartupMinimized->setChecked(minimized); + + ui.enableRetroShareProtocol->setChecked(Settings->getRetroShareProtocol()); +#endif + + ui.checkStartMinimized->setChecked(Settings->getStartMinimized()); + ui.checkQuit->setChecked(Settings->value("doQuit", false).toBool()); + + ui.checkClosetoTray->setChecked(Settings->getCloseToTray()); + + ui.spinBox->setValue(Settings->getMaxTimeBeforeIdle()); + + ui.autoLogin->setChecked(RsInit::getAutoLogin()); +} diff --git a/retroshare-gui/src/gui/settings/GeneralPage.h b/retroshare-gui/src/gui/settings/GeneralPage.h new file mode 100755 index 000000000..dc4bc2f21 --- /dev/null +++ b/retroshare-gui/src/gui/settings/GeneralPage.h @@ -0,0 +1,50 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _GENERALPAGE_H +#define _GENERALPAGE_H + +#include "configpage.h" +#include "ui_GeneralPage.h" + +class GeneralPage : public ConfigPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + GeneralPage(QWidget * parent = 0, Qt::WFlags flags = 0); + /** Default Destructor */ + ~GeneralPage(); + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + +private: + /** Qt Designer generated object */ + Ui::GeneralPage ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/settings/GeneralPage.ui b/retroshare-gui/src/gui/settings/GeneralPage.ui new file mode 100755 index 000000000..2d677f9bc --- /dev/null +++ b/retroshare-gui/src/gui/settings/GeneralPage.ui @@ -0,0 +1,642 @@ + + + GeneralPage + + + + 0 + 0 + 413 + 314 + + + + + 0 + 64 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 10 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + Startup + + + + + + Start RetroShare when my system starts + + + + + + + Start minimized + + + true + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 15 + 0 + + + + + + + + Start minimized on system start + + + + + + + + + + + + Misc + + + + + + Do not show the Quit RetroShare MessageBox + + + + + + + Do not Minimize to Tray Icon + + + true + + + + + + + Auto Login + + + + + + + Register retroshare:// as url protocol (Restart required) + + + + + + + + + + Qt::Vertical + + + + 178 + 95 + + + + + + + + Idle + + + + + + Idle Time + + + + + + + seconds + + + + + + 1000 + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/MessagePage.cpp b/retroshare-gui/src/gui/settings/MessagePage.cpp new file mode 100644 index 000000000..b713daab0 --- /dev/null +++ b/retroshare-gui/src/gui/settings/MessagePage.cpp @@ -0,0 +1,230 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "rshare.h" +#include "rsharesettings.h" +#include "retroshare/rsmsgs.h" + +#include "MessagePage.h" +#include "gui/common/TagDefs.h" + +#include + +#include "NewTag.h" + +MessagePage::MessagePage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + ui.setupUi(this); + + m_pTags = new MsgTagType; + + connect (ui.addpushButton, SIGNAL(clicked(bool)), this, SLOT (addTag())); + connect (ui.editpushButton, SIGNAL(clicked(bool)), this, SLOT (editTag())); + connect (ui.deletepushButton, SIGNAL(clicked(bool)), this, SLOT (deleteTag())); + connect (ui.defaultTagButton, SIGNAL(clicked(bool)), this, SLOT (defaultTag())); + + connect (ui.tags_listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(currentRowChangedTag(int))); + + ui.editpushButton->setEnabled(false); + ui.deletepushButton->setEnabled(false); + + ui.openComboBox->addItem(tr("A new tab"), RshareSettings::MSG_OPEN_TAB); + ui.openComboBox->addItem(tr("A new window"), RshareSettings::MSG_OPEN_WINDOW); +} + +MessagePage::~MessagePage() +{ + delete(m_pTags); +} + +/** Saves the changes on this page */ +bool +MessagePage::save(QString &errmsg) +{ + Settings->setMsgSetToReadOnActivate(ui.setMsgToReadOnActivate->isChecked()); + Settings->setMsgOpen((RshareSettings::enumMsgOpen) ui.openComboBox->itemData(ui.openComboBox->currentIndex()).toInt()); + + std::map >::iterator Tag; + for (Tag = m_pTags->types.begin(); Tag != m_pTags->types.end(); Tag++) { + // check for changed tags + std::list::iterator changedTagId; + for (changedTagId = m_changedTagIds.begin(); changedTagId != m_changedTagIds.end(); changedTagId++) { + if (*changedTagId == Tag->first) { + if (Tag->second.first.empty()) { + // delete tag + rsMsgs->removeMessageTagType(Tag->first); + continue; + } + + rsMsgs->setMessageTagType(Tag->first, Tag->second.first, Tag->second.second); + break; + } + } + } + + return true; +} + +/** Loads the settings for this page */ +void +MessagePage::load() +{ + ui.setMsgToReadOnActivate->setChecked(Settings->getMsgSetToReadOnActivate()); + ui.openComboBox->setCurrentIndex(ui.openComboBox->findData(Settings->getMsgOpen())); + + // fill items + rsMsgs->getMessageTagTypes(*m_pTags); + fillTags(); +} + +// fill tags +void MessagePage::fillTags() +{ + ui.tags_listWidget->clear(); + + std::map >::iterator Tag; + for (Tag = m_pTags->types.begin(); Tag != m_pTags->types.end(); Tag++) { + QString text = TagDefs::name(Tag->first, Tag->second.first); + + QListWidgetItem *pItemWidget = new QListWidgetItem(text, ui.tags_listWidget); + pItemWidget->setTextColor(QColor(Tag->second.second)); + pItemWidget->setData(Qt::UserRole, Tag->first); + } +} + +void MessagePage::addTag() +{ + NewTag TagDlg(*m_pTags); + if (TagDlg.exec() == QDialog::Accepted && TagDlg.m_nId) { + std::map >::iterator Tag; + Tag = m_pTags->types.find(TagDlg.m_nId); + if (Tag != m_pTags->types.end()) { + QString text = TagDefs::name(Tag->first, Tag->second.first); + + QListWidgetItem *pItemWidget = new QListWidgetItem(text, ui.tags_listWidget); + pItemWidget->setTextColor(QColor(Tag->second.second)); + pItemWidget->setData(Qt::UserRole, TagDlg.m_nId); + + m_changedTagIds.push_back(TagDlg.m_nId); + } + } +} + +void MessagePage::editTag() +{ + QListWidgetItem *pItemWidget = ui.tags_listWidget->currentItem(); + if (pItemWidget == NULL) { + return; + } + + uint32_t nId = pItemWidget->data(Qt::UserRole).toInt(); + if (nId == 0) { + return; + } + + NewTag TagDlg(*m_pTags, nId); + TagDlg.setWindowTitle(tr("Edit Tag")); + if (TagDlg.exec() == QDialog::Accepted && TagDlg.m_nId) { + std::map >::iterator Tag; + Tag = m_pTags->types.find(TagDlg.m_nId); + if (Tag != m_pTags->types.end()) { + if (Tag->first >= RS_MSGTAGTYPE_USER) { + pItemWidget->setText(QString::fromStdString(Tag->second.first)); + } + pItemWidget->setTextColor(QColor(Tag->second.second)); + + if (std::find(m_changedTagIds.begin(), m_changedTagIds.end(), TagDlg.m_nId) == m_changedTagIds.end()) { + m_changedTagIds.push_back(TagDlg.m_nId); + } + } + } +} + +void MessagePage::deleteTag() +{ + QListWidgetItem *pItemWidget = ui.tags_listWidget->currentItem(); + if (pItemWidget == NULL) { + return; + } + + uint32_t nId = pItemWidget->data(Qt::UserRole).toInt(); + if (nId == 0) { + return; + } + + if (nId < RS_MSGTAGTYPE_USER) { + // can't delete standard tag item + return; + } + + std::map >::iterator Tag; + Tag = m_pTags->types.find(nId); + if (Tag != m_pTags->types.end()) { + // erase the text for later delete + Tag->second.first.erase(); + } + + ui.tags_listWidget->removeItemWidget(pItemWidget); + delete (pItemWidget); + + if (std::find(m_changedTagIds.begin(), m_changedTagIds.end(), nId) == m_changedTagIds.end()) { + m_changedTagIds.push_back(nId); + } +} + +void MessagePage::defaultTag() +{ + rsMsgs->resetMessageStandardTagTypes(*m_pTags); + + // add all standard items to changed list + std::map >::iterator Tag; + for (Tag = m_pTags->types.begin(); Tag != m_pTags->types.end(); Tag++) { + if (Tag->first < RS_MSGTAGTYPE_USER) { + if (std::find(m_changedTagIds.begin(), m_changedTagIds.end(), Tag->first) == m_changedTagIds.end()) { + m_changedTagIds.push_back(Tag->first); + } + } + } + + fillTags(); +} + +void MessagePage::currentRowChangedTag(int row) +{ + QListWidgetItem *pItemWidget = ui.tags_listWidget->item(row); + + bool bEditEnable = false; + bool bDeleteEnable = false; + + if (pItemWidget) { + bEditEnable = true; + + uint32_t nId = pItemWidget->data(Qt::UserRole).toInt(); + + if (nId >= RS_MSGTAGTYPE_USER) { + bDeleteEnable = true; + } + } + + ui.editpushButton->setEnabled(bEditEnable); + ui.deletepushButton->setEnabled(bDeleteEnable); +} diff --git a/retroshare-gui/src/gui/settings/MessagePage.h b/retroshare-gui/src/gui/settings/MessagePage.h new file mode 100644 index 000000000..662cb4660 --- /dev/null +++ b/retroshare-gui/src/gui/settings/MessagePage.h @@ -0,0 +1,64 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef MESSAGEPAGE_H +#define MESSAGEPAGE_H + +#include + +#include "configpage.h" +#include "ui_MessagePage.h" + +class MsgTagType; + +class MessagePage : public ConfigPage +{ + Q_OBJECT + +public: + MessagePage(QWidget * parent = 0, Qt::WFlags flags = 0); + ~MessagePage(); + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + +private slots: + void addTag(); + void editTag(); + void deleteTag(); + void defaultTag(); + + void currentRowChangedTag(int row); + +private: + void fillTags(); + + /* Pointer for not include of rsmsgs.h */ + MsgTagType *m_pTags; + std::list m_changedTagIds; + + Ui::MessagePage ui; +}; + +#endif // !MESSAGEPAGE_H + diff --git a/retroshare-gui/src/gui/settings/MessagePage.ui b/retroshare-gui/src/gui/settings/MessagePage.ui new file mode 100644 index 000000000..233d7fd58 --- /dev/null +++ b/retroshare-gui/src/gui/settings/MessagePage.ui @@ -0,0 +1,613 @@ + + + MessagePage + + + + 0 + 0 + 423 + 340 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + Reading + + + + + + Set message to read on activate + + + + + + + + + Open messages in + + + + + + + + + + + + + + + Tags + + + + + + Tags can be used to categorize and prioritize your messages + + + + + + + + + + Add + + + + + + + Edit + + + + + + + Qt::Vertical + + + + 38 + 116 + + + + + + + + Delete + + + + + + + Default + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/NetworkPage.cpp b/retroshare-gui/src/gui/settings/NetworkPage.cpp new file mode 100755 index 000000000..56025cefe --- /dev/null +++ b/retroshare-gui/src/gui/settings/NetworkPage.cpp @@ -0,0 +1,45 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "NetworkPage.h" +#include "rshare.h" + +NetworkPage::NetworkPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + ui.setupUi(this); + setAttribute(Qt::WA_QuitOnClose, false); + +} + +/** Saves the changes on this page */ +bool +NetworkPage::save(QString &errmsg) +{ + return true; +} + +/** Loads the settings for this page */ +void +NetworkPage::load() +{ +} + diff --git a/retroshare-gui/src/gui/settings/NetworkPage.h b/retroshare-gui/src/gui/settings/NetworkPage.h new file mode 100755 index 000000000..2702ddbc3 --- /dev/null +++ b/retroshare-gui/src/gui/settings/NetworkPage.h @@ -0,0 +1,44 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef NETWORKPAGE_H +#define NETWORKPAGE_H + +#include "configpage.h" +#include "ui_NetworkPage.h" + +class NetworkPage : public ConfigPage +{ +public: + NetworkPage(QWidget * parent = 0, Qt::WFlags flags = 0); + ~NetworkPage() {} + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + +private: + Ui::NetworkPage ui; +}; + +#endif // !NETWROKPAGE_H + diff --git a/retroshare-gui/src/gui/settings/NetworkPage.ui b/retroshare-gui/src/gui/settings/NetworkPage.ui new file mode 100755 index 000000000..cbdc5cc51 --- /dev/null +++ b/retroshare-gui/src/gui/settings/NetworkPage.ui @@ -0,0 +1,506 @@ + + NetworkPage + + + + 0 + 0 + 398 + 389 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + + diff --git a/retroshare-gui/src/gui/settings/NewTag.cpp b/retroshare-gui/src/gui/settings/NewTag.cpp new file mode 100644 index 000000000..21910c5af --- /dev/null +++ b/retroshare-gui/src/gui/settings/NewTag.cpp @@ -0,0 +1,139 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009, RetroShre Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include "NewTag.h" + +#include "retroshare/rsmsgs.h" + +#include + +/** Default constructor */ +NewTag::NewTag(MsgTagType &Tags, uint32_t nId /*= 0*/, QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags), m_Tags(Tags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + m_nId = nId; + + connect(ui.okButton, SIGNAL(clicked()), this, SLOT(OnOK())); + connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(OnCancel())); + connect(ui.colorButton, SIGNAL(clicked()), this, SLOT(setTagColor())); + + connect(ui.lineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(textChanged(const QString &))); + + ui.okButton->setEnabled(false); + + if (m_nId) { + std::map >::iterator Tag; + Tag = m_Tags.types.find(m_nId); + if (Tag != m_Tags.types.end()) { + ui.lineEdit->setText(QString::fromStdString(Tag->second.first)); + m_Color = QRgb(Tag->second.second); + + if (m_nId < RS_MSGTAGTYPE_USER) { + // standard tag + ui.lineEdit->setEnabled(false); + } + } else { + // tag id not found + m_Color = 0; + m_nId = 0; + } + } else { + m_Color = 0; + } + + showColor (m_Color); +} + +void NewTag::OnOK() +{ + if (m_nId == 0) { + // calculate new id + m_nId = RS_MSGTAGTYPE_USER; + std::map >::iterator Tag; + for (Tag = m_Tags.types.begin(); Tag != m_Tags.types.end(); Tag++) { + if (Tag->first + 1 > m_nId) { + m_nId = Tag->first + 1; + } + } + } + + std::pair newTag(ui.lineEdit->text().toStdString(), m_Color); + m_Tags.types [m_nId] = newTag; + + setResult(QDialog::Accepted); + hide(); +} + +void NewTag::OnCancel() +{ + setResult(QDialog::Rejected); + hide(); +} + +void NewTag::textChanged(const QString &text) +{ + bool bEnabled = true; + std::string stdText = text.toStdString(); + + if (text.isEmpty()) { + bEnabled = false; + } else { + // check for existing text + std::map >::iterator Tag; + for (Tag = m_Tags.types.begin(); Tag != m_Tags.types.end(); Tag++) { + if (m_nId && Tag->first == m_nId) { + // its me + continue; + } + + if (Tag->second.first.empty()) { + // deleted + continue; + } + + if (Tag->second.first == stdText) { + bEnabled = false; + break; + } + } + } + + ui.okButton->setEnabled(bEnabled); +} + +void NewTag::setTagColor() +{ + bool ok; + QRgb color = QColorDialog::getRgba(m_Color, &ok, this); + if (ok) { + m_Color = color; + showColor (m_Color); + } +} + +void NewTag::showColor(QRgb color) +{ + QPixmap pxm(16,16); + pxm.fill(QColor(m_Color)); + ui.colorButton->setIcon(pxm); +} diff --git a/retroshare-gui/src/gui/settings/NewTag.h b/retroshare-gui/src/gui/settings/NewTag.h new file mode 100644 index 000000000..9092d3aad --- /dev/null +++ b/retroshare-gui/src/gui/settings/NewTag.h @@ -0,0 +1,62 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _NEWTAG_H +#define _NEWTAG_H + +#include + +#include + +#include "ui_NewTag.h" + +class MsgTagType; + +class NewTag : public QDialog +{ + Q_OBJECT + +public: + /** Default constructor */ + NewTag(MsgTagType &Tags, uint32_t nId = 0, QWidget *parent = 0, Qt::WFlags flags = 0); + + uint32_t m_nId; + +private slots: + void OnOK(); + void OnCancel(); + + void textChanged(const QString &); + + void setTagColor(); + +private: + void showColor(QRgb color); + + MsgTagType &m_Tags; + QRgb m_Color; + + /** Qt Designer generated object */ + Ui::NewTag ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/settings/NewTag.ui b/retroshare-gui/src/gui/settings/NewTag.ui new file mode 100644 index 000000000..c3c3f4a7d --- /dev/null +++ b/retroshare-gui/src/gui/settings/NewTag.ui @@ -0,0 +1,118 @@ + + + NewTag + + + + 0 + 0 + 320 + 105 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 367777 + 367777 + + + + New Tag + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + + + + 16777215 + 22 + + + + Name: + + + + + + + + + + Choose color + + + + + + + + + + Qt::Horizontal + + + + 135 + 20 + + + + + + + + OK + + + true + + + + + + + Cancel + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/NotifyPage.cpp b/retroshare-gui/src/gui/settings/NotifyPage.cpp new file mode 100755 index 000000000..bc3bbe42f --- /dev/null +++ b/retroshare-gui/src/gui/settings/NotifyPage.cpp @@ -0,0 +1,183 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#include +#include "NotifyPage.h" + +#include +#include "rsharesettings.h" + +#include "gui/MainWindow.h" + + +/** Constructor */ +NotifyPage::NotifyPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +NotifyPage::~NotifyPage() +{ +} + +/** Saves the changes on this page */ +bool +NotifyPage::save(QString &errmsg) +{ + /* extract from rsNotify the flags */ + + uint notifyflags = 0; + uint traynotifyflags = 0; + uint newsflags = 0; + uint chatflags = 0; + + if (ui.popup_Connect->isChecked()) + notifyflags |= RS_POPUP_CONNECT; + if (ui.popup_NewMsg->isChecked()) + notifyflags |= RS_POPUP_MSG; + if (ui.popup_DownloadFinished->isChecked()) + notifyflags |= RS_POPUP_DOWNLOAD; + + if (ui.notify_Peers->isChecked()) + newsflags |= RS_FEED_TYPE_PEER; + if (ui.notify_Channels->isChecked()) + newsflags |= RS_FEED_TYPE_CHAN; + if (ui.notify_Forums->isChecked()) + newsflags |= RS_FEED_TYPE_FORUM; + if (ui.notify_Blogs->isChecked()) + newsflags |= RS_FEED_TYPE_BLOG; + if (ui.notify_Chat->isChecked()) + newsflags |= RS_FEED_TYPE_CHAT; + if (ui.notify_Messages->isChecked()) + newsflags |= RS_FEED_TYPE_MSG; + if (ui.notify_Chat->isChecked()) + newsflags |= RS_FEED_TYPE_CHAT; + + if (ui.chat_NewWindow->isChecked()) + chatflags |= RS_CHAT_OPEN; + if (ui.chat_Focus->isChecked()) + chatflags |= RS_CHAT_FOCUS; + if (ui.chat_tabbedWindow->isChecked()) + chatflags |= RS_CHAT_TABBED_WINDOW; + + if (ui.trayNotify_PrivateChat->isChecked()) + traynotifyflags |= TRAYNOTIFY_PRIVATECHAT; + if (ui.trayNotify_Messages->isChecked()) + traynotifyflags |= TRAYNOTIFY_MESSAGES; + if (ui.trayNotify_Channels->isChecked()) + traynotifyflags |= TRAYNOTIFY_CHANNELS; + if (ui.trayNotify_Forums->isChecked()) + traynotifyflags |= TRAYNOTIFY_FORUMS; + if (ui.trayNotify_Transfer->isChecked()) + traynotifyflags |= TRAYNOTIFY_TRANSFERS; + if (ui.trayNotify_CombinedIcon->isChecked()) + traynotifyflags |= TRAYNOTIFY_COMBINEDICON; + + Settings->setNotifyFlags(notifyflags); + Settings->setTrayNotifyFlags(traynotifyflags); + Settings->setNewsFeedFlags(newsflags); + Settings->setChatFlags(chatflags); + + Settings->setDisplayTrayGroupChat(ui.systray_GroupChat->isChecked()); + MainWindow::installGroupChatNotifier(); + MainWindow::installNotifyIcons(); + + Settings->setAddFeedsAtEnd(ui.addFeedsAtEnd->isChecked()); + + int index = ui.comboBoxToasterPosition->currentIndex(); + if (index != -1) { + Settings->setToasterPosition((RshareSettings::enumToasterPosition) ui.comboBoxToasterPosition->itemData(index).toInt()); + } + + Settings->setToasterMargin(QPoint(ui.spinBoxToasterXMargin->value(), ui.spinBoxToasterYMargin->value())); + + load(); + return true; +} + + +/** Loads the settings for this page */ +void NotifyPage::load() +{ + /* extract from rsNotify the flags */ + uint notifyflags = Settings->getNotifyFlags(); + uint traynotifyflags = Settings->getTrayNotifyFlags(); + uint newsflags = Settings->getNewsFeedFlags(); + uint chatflags = Settings->getChatFlags(); + + ui.popup_Connect->setChecked(notifyflags & RS_POPUP_CONNECT); + ui.popup_NewMsg->setChecked(notifyflags & RS_POPUP_MSG); + ui.popup_DownloadFinished->setChecked(notifyflags & RS_POPUP_DOWNLOAD); + + ui.notify_Peers->setChecked(newsflags & RS_FEED_TYPE_PEER); + ui.notify_Channels->setChecked(newsflags & RS_FEED_TYPE_CHAN); + ui.notify_Forums->setChecked(newsflags & RS_FEED_TYPE_FORUM); + ui.notify_Blogs->setChecked(newsflags & RS_FEED_TYPE_BLOG); + ui.notify_Chat->setChecked(newsflags & RS_FEED_TYPE_CHAT); + ui.notify_Messages->setChecked(newsflags & RS_FEED_TYPE_MSG); + ui.notify_Chat->setChecked(newsflags & RS_FEED_TYPE_CHAT); + + ui.chat_NewWindow->setChecked(chatflags & RS_CHAT_OPEN); + ui.chat_Focus->setChecked(chatflags & RS_CHAT_FOCUS); + ui.chat_tabbedWindow->setChecked(chatflags & RS_CHAT_TABBED_WINDOW); + + ui.systray_GroupChat->setChecked(Settings->getDisplayTrayGroupChat()); + + ui.trayNotify_PrivateChat->setChecked(traynotifyflags & TRAYNOTIFY_PRIVATECHAT); + ui.trayNotify_Messages->setChecked(traynotifyflags & TRAYNOTIFY_MESSAGES); + ui.trayNotify_Channels->setChecked(traynotifyflags & TRAYNOTIFY_CHANNELS); + ui.trayNotify_Forums->setChecked(traynotifyflags & TRAYNOTIFY_FORUMS); + ui.trayNotify_Transfer->setChecked(traynotifyflags & TRAYNOTIFY_TRANSFERS); + ui.trayNotify_CombinedIcon->setChecked(traynotifyflags & TRAYNOTIFY_COMBINEDICON); + + ui.addFeedsAtEnd->setChecked(Settings->getAddFeedsAtEnd()); + + RshareSettings::enumToasterPosition toasterPosition = Settings->getToasterPosition(); + ui.comboBoxToasterPosition->clear(); + + QMap toasterPositions; + toasterPositions[RshareSettings::TOASTERPOS_TOPLEFT] = tr("Top Left"); + toasterPositions[RshareSettings::TOASTERPOS_TOPRIGHT] = tr("Top Right"); + toasterPositions[RshareSettings::TOASTERPOS_BOTTOMLEFT] = tr("Bottom Left"); + toasterPositions[RshareSettings::TOASTERPOS_BOTTOMRIGHT] = tr("Bottom Right"); + + QMap::iterator it; + int index = 0; + for (it = toasterPositions.begin(); it != toasterPositions.end(); it++, index++) { + ui.comboBoxToasterPosition->addItem(it.value(), it.key()); + + if (it.key() == toasterPosition) { + ui.comboBoxToasterPosition->setCurrentIndex(index); + } + } + + QPoint margin = Settings->getToasterMargin(); + ui.spinBoxToasterXMargin->setValue(margin.x()); + ui.spinBoxToasterYMargin->setValue(margin.y()); +} diff --git a/retroshare-gui/src/gui/settings/NotifyPage.h b/retroshare-gui/src/gui/settings/NotifyPage.h new file mode 100755 index 000000000..d984ccc38 --- /dev/null +++ b/retroshare-gui/src/gui/settings/NotifyPage.h @@ -0,0 +1,49 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef NOTIFYPAGE_H +#define NOTIFYPAGE_H + +#include "configpage.h" +#include "ui_NotifyPage.h" + +class NotifyPage : public ConfigPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + NotifyPage(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default Destructor */ + ~NotifyPage(); + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + +private: + /** Qt Designer generated object */ + Ui::NotifyPage ui; +}; + +#endif // !NOTIFYPAGE_H + diff --git a/retroshare-gui/src/gui/settings/NotifyPage.ui b/retroshare-gui/src/gui/settings/NotifyPage.ui new file mode 100755 index 000000000..7a0a65ac7 --- /dev/null +++ b/retroshare-gui/src/gui/settings/NotifyPage.ui @@ -0,0 +1,835 @@ + + + NotifyPage + + + + 0 + 0 + 408 + 425 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 10 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + + + + + News Feed + + + + 0 + + + 6 + + + + + Peers + + + + + + + Channels + + + + + + + Forums + + + + + + + Blogs + + + + + + + Messages + + + + + + + Chat + + + + + + + Qt::Horizontal + + + + + + + Add feeds at end + + + + + + + + + + Systray Icon + + + + + + Private Message + + + + + + + Message + + + + + + + Channel Post + + + + + + + Forum Post + + + + + + + Download completed + + + + + + + Qt::Horizontal + + + + + + + Combined icon + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Toasters + + + + 9 + + + 9 + + + + + Friend Connect + + + + + + + New Message + + + + + + + Download completed + + + + + + + + + + 0 + 0 + + + + Position + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + X Margin + + + + + + + + 0 + 0 + + + + 20 + + + + + + + + 0 + 0 + + + + Y Margin + + + + + + + + 0 + 0 + + + + 20 + + + + + + + + + + + + Private Chat + + + + + + Open Window for new chat + + + + + + + Grab Focus when chat arrives + + + + + + + Use a single tabbed window + + + + + + + + + + Group chat + + + + + + Display systray message + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 130 + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/PluginsPage.cpp b/retroshare-gui/src/gui/settings/PluginsPage.cpp new file mode 100644 index 000000000..57ba2b40c --- /dev/null +++ b/retroshare-gui/src/gui/settings/PluginsPage.cpp @@ -0,0 +1,73 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "PluginsPage.h" +#include "rshare.h" +#include "rsharesettings.h" + +#include + +#include "../MainWindow.h" + +PluginsPage::PluginsPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + ui.setupUi(this); + setAttribute(Qt::WA_QuitOnClose, false); + + QString text ; + + if(rsPlugins->nbPlugins() > 0) + for(int i=0;inbPlugins();++i) + { + text += ""+tr("Plugin")+": \t" + QString::fromStdString(rsPlugins->plugin(i)->getPluginName()) + "
    " ; + text += ""+tr("Description")+": \t" + QString::fromStdString(rsPlugins->plugin(i)->getShortPluginDescription()) + "
    " ; + text += "
    " ; + } + else + text = tr("

    No plugins loaded.

    ") ; + + ui._loadedPlugins_TB->setHtml(text) ; + + const std::vector& dirs(rsPlugins->getPluginDirectories()) ; + text = "" ; + + for(int i=0;i
    " ; + + ui._lookupDirectories_TB->setHtml(text) ; +} + +PluginsPage::~PluginsPage() +{ +} + +/** Saves the changes on this page */ +bool PluginsPage::save(QString &errmsg) +{ + // nothing to save for now. + return true; +} + +/** Loads the settings for this page */ +void PluginsPage::load() +{ +} diff --git a/retroshare-gui/src/gui/settings/PluginsPage.h b/retroshare-gui/src/gui/settings/PluginsPage.h new file mode 100644 index 000000000..f0f32e649 --- /dev/null +++ b/retroshare-gui/src/gui/settings/PluginsPage.h @@ -0,0 +1,43 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#pragma once + +#include "configpage.h" +#include "ui_PluginsPage.h" + +class PluginsPage : public ConfigPage +{ + Q_OBJECT + +public: + PluginsPage(QWidget * parent = 0, Qt::WFlags flags = 0); + ~PluginsPage(); + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + +private: + Ui::PluginsPage ui; +}; + diff --git a/retroshare-gui/src/gui/settings/PluginsPage.ui b/retroshare-gui/src/gui/settings/PluginsPage.ui new file mode 100644 index 000000000..909d8f19d --- /dev/null +++ b/retroshare-gui/src/gui/settings/PluginsPage.ui @@ -0,0 +1,544 @@ + + + PluginsPage + + + + 0 + 0 + 423 + 340 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + Loaded plugins + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Plugin look-up directories + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/RsharePeerSettings.cpp b/retroshare-gui/src/gui/settings/RsharePeerSettings.cpp new file mode 100644 index 000000000..86fac1b50 --- /dev/null +++ b/retroshare-gui/src/gui/settings/RsharePeerSettings.cpp @@ -0,0 +1,247 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (C) 2006 - 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "RsharePeerSettings.h" +#include "gui/style/RSStyle.h" + +/** The file in which all settings of he peers will read and written. */ +#define SETTINGS_FILE (RsInit::RsProfileConfigDirectory() + "/RSPeers.conf") + +/* clean dead gpg id's after these days */ +#define DAYS_TO_CLEAN 7 + +/* Group for general data */ +#define GROUP_GENERAL "Default" + +/* the one and only global settings object */ +RsharePeerSettings *PeerSettings = NULL; + +/*static*/ void RsharePeerSettings::Create () +{ + if (PeerSettings == NULL) { + PeerSettings = new RsharePeerSettings(); + } +} + +/** Default Constructor */ +RsharePeerSettings::RsharePeerSettings() + : QSettings(QString::fromStdString(SETTINGS_FILE), QSettings::IniFormat) +{ + cleanDeadGpgIds(); +} + +void RsharePeerSettings::cleanDeadGpgIds() +{ + beginGroup(GROUP_GENERAL); + QDateTime lastClean = value("lastClean").toDateTime(); + endGroup(); + + QDateTime currentDate = QDateTime::currentDateTime(); + + if (lastClean.addDays(DAYS_TO_CLEAN) < currentDate) { + /* clean */ + QStringList groups = childGroups(); + for (QStringList::iterator group = groups.begin(); group != groups.end(); group++) { + if (*group == GROUP_GENERAL) { + continue; + } + + if (rsPeers->isGPGAccepted((*group).toStdString()) == false) { + remove(*group); + } + } + + beginGroup(GROUP_GENERAL); + setValue("lastClean", currentDate); + endGroup(); + } +} + +bool RsharePeerSettings::getGpgIdOfSslId(const std::string &sslId, std::string &gpgId) + +{ + std::map::iterator it = m_SslToGpg.find(sslId); + if (it != m_SslToGpg.end()) { + gpgId = it->second; + return true; + } + + RsPeerDetails details; + if (rsPeers->getPeerDetails(sslId, details) == false) { + return false; + } + + gpgId = details.gpg_id; + m_SslToGpg[sslId] = gpgId; + + return true; +} + +/* get value of peer */ +QVariant RsharePeerSettings::get(const std::string &peerId, const QString &key, const QVariant &defaultValue) +{ + QVariant result; + + std::string gpgId; + if (getGpgIdOfSslId(peerId, gpgId) == false) { + /* gpg id not found */ + return result; + } + + beginGroup(QString::fromStdString(gpgId)); + result = value(key, defaultValue); + endGroup(); + + return result; +} + +/* set value of peer */ +void RsharePeerSettings::set(const std::string &peerId, const QString &key, const QVariant &value) +{ + std::string gpgId; + if (getGpgIdOfSslId(peerId, gpgId) == false) { + /* gpg id not found */ + return; + } + + beginGroup(QString::fromStdString(gpgId)); + setValue(key, value); + endGroup(); +} + +QString RsharePeerSettings::getPrivateChatColor(const std::string &peerId) +{ + return get(peerId, "PrivateChatColor", QColor(Qt::black).name()).toString(); +} + +void RsharePeerSettings::setPrivateChatColor(const std::string &peerId, const QString &value) +{ + set(peerId, "PrivateChatColor", value); +} + +QString RsharePeerSettings::getPrivateChatFont(const std::string &peerId) +{ + return get(peerId, "PrivateChatFont", QFont("Comic Sans MS", 10).toString()).toString(); +} + +void RsharePeerSettings::setPrivateChatFont(const std::string &peerId, const QString &value) +{ + set(peerId, "PrivateChatFont", value); +} + +void RsharePeerSettings::saveWidgetInformation(const std::string &peerId, QWidget *widget) +{ + std::string gpgId; + if (getGpgIdOfSslId(peerId, gpgId) == false) { + /* gpg id not found */ + return; + } + + beginGroup(QString::fromStdString(gpgId)); + beginGroup("widgetInformation"); + beginGroup(widget->objectName()); + + setValue("size", widget->size()); + setValue("pos", widget->pos()); + + endGroup(); + endGroup(); + endGroup(); +} + +void RsharePeerSettings::loadWidgetInformation(const std::string &peerId, QWidget *widget) +{ + std::string gpgId; + if (getGpgIdOfSslId(peerId, gpgId) == false) { + /* gpg id not found */ + return; + } + + beginGroup(QString::fromStdString(gpgId)); + beginGroup("widgetInformation"); + beginGroup(widget->objectName()); + + widget->resize(value("size", widget->size()).toSize()); + widget->move(value("pos", QPoint(200, 200)).toPoint()); + + endGroup(); + endGroup(); + endGroup(); +} + +bool RsharePeerSettings::getShowAvatarFrame(const std::string &peerId) +{ + return get(peerId, "ShowAvatarFrame", true).toBool(); +} + +void RsharePeerSettings::setShowAvatarFrame(const std::string &peerId, bool value) +{ + return set(peerId, "ShowAvatarFrame", value); +} + +void RsharePeerSettings::getStyle(const std::string &peerId, const QString &name, RSStyle &style) +{ + std::string gpgId; + if (getGpgIdOfSslId(peerId, gpgId) == false) { + /* gpg id not found */ + return; + } + + beginGroup(QString::fromStdString(gpgId)); + beginGroup("style"); + beginGroup(name); + + style.readSetting(*this); + + endGroup(); + endGroup(); + endGroup(); +} + +void RsharePeerSettings::setStyle(const std::string &peerId, const QString &name, RSStyle &style) +{ + std::string gpgId; + if (getGpgIdOfSslId(peerId, gpgId) == false) { + /* gpg id not found */ + return; + } + + beginGroup(QString::fromStdString(gpgId)); + beginGroup("style"); + beginGroup(name); + + style.writeSetting(*this); + + endGroup(); + endGroup(); + endGroup(); +} diff --git a/retroshare-gui/src/gui/settings/RsharePeerSettings.h b/retroshare-gui/src/gui/settings/RsharePeerSettings.h new file mode 100644 index 000000000..ab8cf8a9e --- /dev/null +++ b/retroshare-gui/src/gui/settings/RsharePeerSettings.h @@ -0,0 +1,70 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (C) 2006 - 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _RSHAREPEERSETTINGS_H +#define _RSHAREPEERSETTINGS_H + +#include + +class RSStyle; + +/** Handles saving and restoring RShares's settings for peers */ +class RsharePeerSettings : public QSettings +{ +public: + /* create settings object */ + static void Create (); + + QString getPrivateChatColor(const std::string &peerId); + void setPrivateChatColor(const std::string &peerId, const QString &value); + + QString getPrivateChatFont(const std::string &peerId); + void setPrivateChatFont(const std::string &peerId, const QString &value); + + void saveWidgetInformation(const std::string &peerId, QWidget *widget); + void loadWidgetInformation(const std::string &peerId, QWidget *widget); + + bool getShowAvatarFrame(const std::string &peerId); + void setShowAvatarFrame(const std::string &peerId, bool value); + + void getStyle(const std::string &peerId, const QString &name, RSStyle &style); + void setStyle(const std::string &peerId, const QString &name, RSStyle &style); + +protected: + /** Default constructor. */ + RsharePeerSettings(); + + bool getGpgIdOfSslId(const std::string &sslId, std::string &gpgId); + void cleanDeadGpgIds(); + + /* get value of peer */ + QVariant get(const std::string &peerId, const QString &key, const QVariant &defaultValue = QVariant()); + /* set value of peer */ + void set(const std::string &peerId, const QString &key, const QVariant &value); + + /* map for fast access of the gpg id to the ssl id */ + std::map m_SslToGpg; +}; + +// the one and only global settings object +extern RsharePeerSettings *PeerSettings; + +#endif diff --git a/retroshare-gui/src/gui/settings/ServerPage.cpp b/retroshare-gui/src/gui/settings/ServerPage.cpp new file mode 100755 index 000000000..ed1c30847 --- /dev/null +++ b/retroshare-gui/src/gui/settings/ServerPage.cpp @@ -0,0 +1,309 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "ServerPage.h" +#include + +#include "rshare.h" +#include "rsharesettings.h" + +#include +#include + +#include +#include + +#include + +ServerPage::ServerPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.netModeComboBox, SIGNAL( activated ( int ) ), this, SLOT( toggleUPnP( ) ) ); + connect( ui.allowIpDeterminationCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleIpDetermination(bool) ) ); + connect( ui.allowTunnelConnectionCB, SIGNAL( toggled( bool ) ), this, SLOT( toggleTunnelConnection(bool) ) ); + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(updateStatus())); + timer->start(1000); + + //load(); + updateStatus(); + + bool b = rsPeers->getAllowServerIPDetermination() ; + ui.allowIpDeterminationCB->setChecked(b) ; + ui.IPServersLV->setEnabled(b) ; + +#ifdef RS_RELEASE_VERSION + ui.allowTunnelConnectionCB->hide(); + this->toggleTunnelConnection(false); +#else + b = rsPeers->getAllowTunnelConnection() ; + ui.allowTunnelConnectionCB->setChecked(b) ; +#endif + + std::list ip_servers ; + rsPeers->getIPServersList(ip_servers) ; + + for(std::list::const_iterator it(ip_servers.begin());it!=ip_servers.end();++it) + ui.IPServersLV->addItem(QString::fromStdString(*it)) ; + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +void ServerPage::toggleIpDetermination(bool b) +{ + rsPeers->allowServerIPDetermination(b) ; + ui.IPServersLV->setEnabled(b) ; +} + +void ServerPage::toggleTunnelConnection(bool b) +{ + std::cerr << "ServerPage::toggleTunnelConnection() set tunnel to : " << b << std::endl; + rsPeers->allowTunnelConnection(b) ; +} + +/** Saves the changes on this page */ +bool +ServerPage::save(QString &errmsg) +{ + Settings->setStatusBarFlag(STATUSBAR_DISC, ui.showDiscStatusBar->isChecked()); + +/* save the server address */ +/* save local address */ +/* save the url for DNS access */ + +/* restart server */ + +/* save all? */ + saveAddresses(); + return true; +} + +/** Loads the settings for this page */ +void ServerPage::load() +{ + + /* load up configuration from rsPeers */ + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail)) + { + return; + } + + /* set net mode */ + int netIndex = 0; + switch(detail.tryNetMode) + { + case RS_NETMODE_EXT: + netIndex = 2; + break; + case RS_NETMODE_UDP: + netIndex = 1; + break; + default: + case RS_NETMODE_UPNP: + netIndex = 0; + break; + } + ui.netModeComboBox->setCurrentIndex(netIndex); + + /* DHT + Discovery: (public) + * Discovery only: (private) + * DHT only: (inverted) + * None: (dark net) + */ + + netIndex = 3; // NONE. + if (detail.visState & RS_VS_DHT_ON) + { + if (detail.visState & RS_VS_DISC_ON) + { + netIndex = 0; // PUBLIC + } + else + { + netIndex = 2; // INVERTED + } + } + else + { + if (detail.visState & RS_VS_DISC_ON) + { + netIndex = 1; // PRIVATE + } + else + { + netIndex = 3; // NONE + } + } + + ui.discComboBox->setCurrentIndex(netIndex); + + rsiface->lockData(); /* Lock Interface */ + + ui.totalDownloadRate->setValue(rsiface->getConfig().maxDownloadDataRate); + ui.totalUploadRate->setValue(rsiface->getConfig().maxUploadDataRate); + + rsiface->unlockData(); /* UnLock Interface */ + + + toggleUPnP(); + + + /* Addresses must be set here - otherwise can't edit it */ + /* set local address */ + ui.localAddress->setText(QString::fromStdString(detail.localAddr)); + ui.localPort -> setValue(detail.localPort); + /* set the server address */ + ui.extAddress->setText(QString::fromStdString(detail.extAddr)); + ui.extPort -> setValue(detail.extPort); + /* set DynDNS */ + ui.dynDNS -> setText(QString::fromStdString(detail.dyndns)); + + ui.showDiscStatusBar->setChecked(Settings->getStatusBarFlags() & STATUSBAR_DISC); +} + +/** Loads the settings for this page */ +void ServerPage::updateStatus() +{ + if(!isVisible()) + return ; + + /* load up configuration from rsPeers */ + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(rsPeers->getOwnId(), detail)) + return; + + /* only update if can't edit */ + if (!ui.localPort->isEnabled()) + { + /* set local address */ + ui.localPort -> setValue(detail.localPort); + ui.extPort -> setValue(detail.extPort); + } + + /* set local address */ + ui.localAddress->setText(QString::fromStdString(detail.localAddr)); + /* set the server address */ + ui.extAddress->setText(QString::fromStdString(detail.extAddr)); +} + +void ServerPage::toggleUPnP() +{ + /* switch on the radioButton */ + bool settingChangeable = false; + if (0 != ui.netModeComboBox->currentIndex()) + { + settingChangeable = true; + } + + if (settingChangeable) + { + ui.localAddress->setEnabled(false); + ui.localPort -> setEnabled(true); + ui.extAddress -> setEnabled(false); + ui.extPort -> setEnabled(true); + } + else + { + ui.localAddress->setEnabled(false); + ui.localPort -> setEnabled(false); + ui.extAddress -> setEnabled(false); + ui.extPort -> setEnabled(false); + } +} + +void ServerPage::saveAddresses() +{ + QString str; + + bool saveAddr = false; + + RsPeerDetails detail; + std::string ownId = rsPeers->getOwnId(); + + if (!rsPeers->getPeerDetails(ownId, detail)) + return; + + int netIndex = ui.netModeComboBox->currentIndex(); + + /* Check if netMode has changed */ + uint32_t netMode = 0; + switch(netIndex) + { + case 2: + netMode = RS_NETMODE_EXT; + break; + case 1: + netMode = RS_NETMODE_UDP; + break; + default: + case 0: + netMode = RS_NETMODE_UPNP; + break; + } + + if (detail.tryNetMode != netMode) + rsPeers->setNetworkMode(ownId, netMode); + + uint32_t visState = 0; + /* Check if vis has changed */ + switch(ui.discComboBox->currentIndex()) + { + case 0: + visState |= (RS_VS_DISC_ON | RS_VS_DHT_ON); + break; + case 1: + visState |= RS_VS_DISC_ON; + break; + case 2: + visState |= RS_VS_DHT_ON; + break; + case 3: + default: + break; + } + + if (visState != detail.visState) + rsPeers->setVisState(ownId, visState); + + if (0 != netIndex) + saveAddr = true; + + if (saveAddr) + { + rsPeers->setLocalAddress(ownId, ui.localAddress->text().toStdString(), ui.localPort->value()); + rsPeers->setExtAddress(ownId, ui.extAddress->text().toStdString(), ui.extPort->value()); + } + + rsPeers->setDynDNS(ownId, ui.dynDNS->text().toStdString()); + + rsicontrol->ConfigSetDataRates( ui.totalDownloadRate->value(), ui.totalUploadRate->value() ); + + load(); +} + diff --git a/retroshare-gui/src/gui/settings/ServerPage.h b/retroshare-gui/src/gui/settings/ServerPage.h new file mode 100755 index 000000000..05ec80f5c --- /dev/null +++ b/retroshare-gui/src/gui/settings/ServerPage.h @@ -0,0 +1,55 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef SERVERPAGE_H +#define SERVERPAGE_H + +#include "configpage.h" +#include "ui_ServerPage.h" + +class ServerPage: public ConfigPage +{ + Q_OBJECT + +public: + ServerPage(QWidget * parent = 0, Qt::WFlags flags = 0); + ~ServerPage() {} + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + +public slots: + void updateStatus(); + +private slots: + void saveAddresses(); + void toggleUPnP(); + void toggleIpDetermination(bool) ; + void toggleTunnelConnection(bool) ; + +private: + Ui::ServerPage ui; +}; + +#endif // !SERVERPAGE_H + diff --git a/retroshare-gui/src/gui/settings/ServerPage.ui b/retroshare-gui/src/gui/settings/ServerPage.ui new file mode 100755 index 000000000..6fa5fd0ce --- /dev/null +++ b/retroshare-gui/src/gui/settings/ServerPage.ui @@ -0,0 +1,840 @@ + + + ServerPage + + + + 0 + 0 + 573 + 400 + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + Qt::NoContextMenu + + + + 6 + + + + + + 0 + 0 + + + + Network Configuration + + + + + + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + + + + + + 200 + 0 + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + + + + + + + + + 0 + 0 + + + + Transfer Rates + + + + + + + + Download (KB/s) + + + + + + + kB/s + + + 1 + + + 100000 + + + 1 + + + + + + + + + 6 + + + + + Upload (KB/s) + + + + + + + kB/s + + + + + + 1 + + + 100000 + + + 1 + + + + + + + + + + + + 0 + + + + Network Configuration + + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + Allow Tunnel Connection + + + true + + + + + + + 6 + + + + + + + Local Address + + + + + + + External Address + + + + + + + Dynamic DNS + + + + + + + + + 6 + + + + + + + + Port: + + + + + + + 0 + + + 65535 + + + 7812 + + + + + + + + + + Port: + + + + + + + 0 + + + 65535 + + + 7812 + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Show Discovery information in statusbar + + + + + + + + IP Service + + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + Allow RetroShare to ask my ip to these websites: + + + true + + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + + + + + localAddress + localPort + extPort + totalDownloadRate + + + + diff --git a/retroshare-gui/src/gui/settings/SoundPage.cpp b/retroshare-gui/src/gui/settings/SoundPage.cpp new file mode 100644 index 000000000..facbd18b7 --- /dev/null +++ b/retroshare-gui/src/gui/settings/SoundPage.cpp @@ -0,0 +1,179 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#include +#include "SoundPage.h" +#include "rsharesettings.h" + + +/** Constructor */ +SoundPage::SoundPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect(ui.cmd_openFile, SIGNAL(clicked(bool) ),this,SLOT(on_cmd_openFile())); + //connect(ui.cmd_openFile_2,SIGNAL(clicked(bool) ),this,SLOT(on_cmd_openFile2())); + connect(ui.cmd_openFile_3,SIGNAL(clicked(bool) ),this,SLOT(on_cmd_openFile3())); + connect(ui.cmd_openFile_4,SIGNAL(clicked(bool) ),this,SLOT(on_cmd_openFile4())); + connect(ui.cmd_openFile_5,SIGNAL(clicked(bool) ),this,SLOT(on_cmd_openFile5())); + connect(ui.cmd_openFile_6,SIGNAL(clicked(bool) ),this,SLOT(on_cmd_openFile6())); + + ui.groupBox_13->hide(); + ui.groupBox_14->hide(); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +SoundPage::~SoundPage() +{ +} + +/** Saves the changes on this page */ +bool +SoundPage::save(QString &errmsg) +{ + Settings->beginGroup("Sound"); + Settings->beginGroup("Enable"); + Settings->setValue("User_go_Online",ui.checkBoxSound->isChecked()); + //settings.setValue("User_go_Offline",ui.checkBoxSound_2->isChecked()); + Settings->setValue("FileSend_Finished",ui.checkBoxSound_3->isChecked()); + Settings->setValue("FileRecive_Incoming",ui.checkBoxSound_4->isChecked()); + Settings->setValue("FileRecive_Finished",ui.checkBoxSound_5->isChecked()); + Settings->setValue("NewChatMessage",ui.checkBoxSound_6->isChecked()); + Settings->endGroup(); + Settings->beginGroup("SoundFilePath"); + Settings->setValue("User_go_Online",ui.txt_SoundFile->text()); + //settings.setValue("User_go_Offline",ui.txt_SoundFile2->text()); + Settings->setValue("FileSend_Finished",ui.txt_SoundFile3->text()); + Settings->setValue("FileRecive_Incoming",ui.txt_SoundFile4->text()); + Settings->setValue("FileRecive_Finished",ui.txt_SoundFile5->text()); + Settings->setValue("NewChatMessage",ui.txt_SoundFile6->text()); + Settings->endGroup(); + Settings->endGroup(); + + return true; +} + + + +/** Loads the settings for this page */ +void +SoundPage::load() +{ + Settings->beginGroup("Sound"); + Settings->beginGroup("SoundFilePath"); + ui.txt_SoundFile->setText(Settings->value("User_go_Online","").toString()); + //ui.txt_SoundFile2->setText(settings.value("User_go_Offline","").toString()); + ui.txt_SoundFile3->setText(Settings->value("FileSend_Finished","").toString()); + ui.txt_SoundFile4->setText(Settings->value("FileRecive_Incoming","").toString()); + ui.txt_SoundFile5->setText(Settings->value("FileRecive_Finished","").toString()); + ui.txt_SoundFile6->setText(Settings->value("NewChatMessage","").toString()); + + if(!ui.txt_SoundFile->text().isEmpty())ui.checkBoxSound->setEnabled(true); + //if(!ui.txt_SoundFile2->text().isEmpty())ui.checkBoxSound_2->setEnabled(true); + if(!ui.txt_SoundFile3->text().isEmpty())ui.checkBoxSound_3->setEnabled(true); + if(!ui.txt_SoundFile4->text().isEmpty())ui.checkBoxSound_4->setEnabled(true); + if(!ui.txt_SoundFile5->text().isEmpty())ui.checkBoxSound_5->setEnabled(true); + if(!ui.txt_SoundFile6->text().isEmpty())ui.checkBoxSound_6->setEnabled(true); + + Settings->endGroup(); + + Settings->beginGroup("Enable"); + ui.checkBoxSound->setChecked(Settings->value("User_go_Online",false).toBool()); + //ui.checkBoxSound_2->setChecked(settings.value("User_go_Offline",false).toBool()); + ui.checkBoxSound_3->setChecked(Settings->value("FileSend_Finished",false).toBool()); + ui.checkBoxSound_4->setChecked(Settings->value("FileRecive_Incoming",false).toBool()); + ui.checkBoxSound_5->setChecked(Settings->value("FileRecive_Finished",false).toBool()); + ui.checkBoxSound_6->setChecked(Settings->value("NewChatMessage",false).toBool()); + Settings->endGroup(); + Settings->endGroup(); +} + +void SoundPage::on_cmd_openFile() +{ + + ui.txt_SoundFile->setText(QFileDialog::getOpenFileName(this,"Open File", ".", "wav (*.wav)")); + if(ui.txt_SoundFile->text().isEmpty()){ + ui.checkBoxSound->setChecked(false); + ui.checkBoxSound->setEnabled(false); + } + else + ui.checkBoxSound->setEnabled(true); +} + +/*void SoundPage::on_cmd_openFile2() +{ + ui.txt_SoundFile2->setText(QFileDialog::getOpenFileName(this,"Open File", ".", "wav (*.wav)")); + if(ui.txt_SoundFile2->text().isEmpty()){ + ui.checkBoxSound_2->setChecked(false); + ui.checkBoxSound_2->setEnabled(false); + } + else + ui.checkBoxSound_2->setEnabled(true); + +}*/ +void SoundPage::on_cmd_openFile3() +{ + ui.txt_SoundFile3->setText(QFileDialog::getOpenFileName(this,"Open File", ".", "wav (*.wav)")); + if(ui.txt_SoundFile3->text().isEmpty()){ + ui.checkBoxSound_3->setChecked(false); + ui.checkBoxSound_3->setEnabled(false); + } + else + ui.checkBoxSound_3->setEnabled(true); +} +void SoundPage::on_cmd_openFile4() +{ + ui.txt_SoundFile4->setText(QFileDialog::getOpenFileName(this,"Open File", ".", "wav (*.wav)")); + if(ui.txt_SoundFile4->text().isEmpty()){ + ui.checkBoxSound_4->setChecked(false); + ui.checkBoxSound_4->setEnabled(false); + } + else + ui.checkBoxSound_4->setEnabled(true); +} +void SoundPage::on_cmd_openFile5() +{ + ui.txt_SoundFile5->setText(QFileDialog::getOpenFileName(this,"Open File", ".", "wav (*.wav)")); + if(ui.txt_SoundFile5->text().isEmpty()){ + ui.checkBoxSound_5->setChecked(false); + ui.checkBoxSound_5->setEnabled(false); + } + else + ui.checkBoxSound_5->setEnabled(true); +} +void SoundPage::on_cmd_openFile6() +{ + ui.txt_SoundFile6->setText(QFileDialog::getOpenFileName(this,"Open File", ".", "wav (*.wav)")); + if(ui.txt_SoundFile6->text().isEmpty()){ + ui.checkBoxSound_6->setChecked(false); + ui.checkBoxSound_6->setEnabled(false); + } + else + ui.checkBoxSound_6->setEnabled(true); + +} diff --git a/retroshare-gui/src/gui/settings/SoundPage.h b/retroshare-gui/src/gui/settings/SoundPage.h new file mode 100644 index 000000000..68cf813f8 --- /dev/null +++ b/retroshare-gui/src/gui/settings/SoundPage.h @@ -0,0 +1,60 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _SOUNDPAGE_H +#define _SOUNDPAGE_H + +#include + +#include "configpage.h" +#include "ui_SoundPage.h" + +class SoundPage : public ConfigPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + SoundPage(QWidget * parent = 0, Qt::WFlags flags = 0); + /** Default Destructor */ + ~SoundPage(); + + /** Saves the changes on this page */ + bool save(QString &errmsg); + /** Loads the settings for this page */ + void load(); + +private slots: + + void on_cmd_openFile(); + //void on_cmd_openFile2(); + void on_cmd_openFile3(); + void on_cmd_openFile4(); + void on_cmd_openFile5(); + void on_cmd_openFile6(); + +private: + /** Qt Designer generated object */ + Ui::SoundPage ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/settings/SoundPage.ui b/retroshare-gui/src/gui/settings/SoundPage.ui new file mode 100644 index 000000000..12b84c94f --- /dev/null +++ b/retroshare-gui/src/gui/settings/SoundPage.ui @@ -0,0 +1,679 @@ + + + SoundPage + + + + 0 + 0 + 463 + 370 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + Sound Events + + + + + + Friend + + + + + + false + + + go Online + + + + + + + false + + + + + + + Browse + + + + + + + + + + Chatmessage + + + + + + false + + + New Msg + + + + + + + false + + + + + + + Browse + + + + + + + + + + FileSend + + + + + + false + + + + + + + Browse + + + + + + + false + + + Finished + + + + + + + + + + FileRecive + + + + + + false + + + Incoming + + + + + + + false + + + + + + + Browse + + + + + + + false + + + Finished + + + + + + + false + + + + + + + Browse + + + + + + + + + + Qt::Vertical + + + + 20 + 29 + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/TransferPage.cpp b/retroshare-gui/src/gui/settings/TransferPage.cpp new file mode 100644 index 000000000..c799f1849 --- /dev/null +++ b/retroshare-gui/src/gui/settings/TransferPage.cpp @@ -0,0 +1,82 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "TransferPage.h" + +#include "rshare.h" + +#include +#include + +#include +#include +#include + +#include + +TransferPage::TransferPage(QWidget * parent, Qt::WFlags flags) + : ConfigPage(parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + ui._queueSize_SB->setValue(rsFiles->getQueueSize()) ; + + if(rsFiles->defaultChunkStrategy() == FileChunksInfo::CHUNK_STRATEGY_STREAMING) + ui._defaultStrategy_CB->setCurrentIndex(0) ; + else + ui._defaultStrategy_CB->setCurrentIndex(1) ; + + ui._diskSpaceLimit_SB->setValue(rsFiles->freeDiskSpaceLimit()) ; + + QObject::connect(ui._queueSize_SB,SIGNAL(valueChanged(int)),this,SLOT(updateQueueSize(int))) ; + QObject::connect(ui._defaultStrategy_CB,SIGNAL(activated(int)),this,SLOT(updateDefaultStrategy(int))) ; + QObject::connect(ui._diskSpaceLimit_SB,SIGNAL(valueChanged(int)),this,SLOT(updateDiskSizeLimit(int))) ; + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +void TransferPage::updateDefaultStrategy(int i) +{ + switch(i) + { + case 0: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_STREAMING) ; + break ; + + case 1: rsFiles->setDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_RANDOM) ; + break ; + + default: ; + } +} + +void TransferPage::updateDiskSizeLimit(int s) +{ + rsFiles->setFreeDiskSpaceLimit(s) ; +} + +void TransferPage::updateQueueSize(int s) +{ + rsFiles->setQueueSize(s) ; +} diff --git a/retroshare-gui/src/gui/settings/TransferPage.h b/retroshare-gui/src/gui/settings/TransferPage.h new file mode 100644 index 000000000..ddb2aaf7a --- /dev/null +++ b/retroshare-gui/src/gui/settings/TransferPage.h @@ -0,0 +1,54 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef TRANSFERPAGE_H +# define TRANSFERPAGE_H + +# include + +#include "configpage.h" +#include "ui_TransferPage.h" + +class TransferPage: public ConfigPage +{ + Q_OBJECT + + public: + TransferPage(QWidget * parent = 0, Qt::WFlags flags = 0); + ~TransferPage() {} + + /** Saves the changes on this page */ + virtual bool save(QString &errmsg) { return true ; } + /** Loads the settings for this page */ + virtual void load() {} + + public slots: + void updateQueueSize(int) ; + void updateDefaultStrategy(int) ; + void updateDiskSizeLimit(int) ; + + private: + + Ui::TransferPage ui; +}; + +#endif // !TRANSFERPAGE_H + diff --git a/retroshare-gui/src/gui/settings/TransferPage.ui b/retroshare-gui/src/gui/settings/TransferPage.ui new file mode 100644 index 000000000..45edbc954 --- /dev/null +++ b/retroshare-gui/src/gui/settings/TransferPage.ui @@ -0,0 +1,130 @@ + + + TransferPage + + + + 0 + 0 + 604 + 340 + + + + + + + Transfer options + + + + + + + + + + Queue Size: + + + + + + + Default chunk strategy: + + + + + + + Safety disk space limit : + + + + + + + + + + + true + + + 1 + + + 1 + + + 5 + + + + + + + true + + + + Streaming + + + + + Random + + + + + + + + MB + + + 50 + + + 1000 + + + 10 + + + 100 + + + + + + + + + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/settings/configpage.cpp b/retroshare-gui/src/gui/settings/configpage.cpp new file mode 100644 index 000000000..cc7de9495 --- /dev/null +++ b/retroshare-gui/src/gui/settings/configpage.cpp @@ -0,0 +1,44 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "configpage.h" + +ConfigPage::ConfigPage(QWidget *parent, Qt::WFlags flags) : QWidget(parent, flags) +{ + loaded = false; +} + +void ConfigPage::showEvent(QShowEvent *event) +{ + if (loaded) { + return; + } + + loaded = true; + + /* Load the settings */ + load(); +} + +bool ConfigPage::wasLoaded() +{ + return loaded; +} diff --git a/retroshare-gui/src/gui/settings/configpage.h b/retroshare-gui/src/gui/settings/configpage.h new file mode 100644 index 000000000..d1091a036 --- /dev/null +++ b/retroshare-gui/src/gui/settings/configpage.h @@ -0,0 +1,50 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CONFIGPAGE_H +#define _CONFIGPAGE_H + +#include + + +class ConfigPage : public QWidget +{ +public: + /** Default Constructor */ + ConfigPage(QWidget *parent = 0, Qt::WFlags flags = 0); + + /** Pure virtual method. Subclassed pages load their config settings here. */ + virtual void load() = 0; + /** Pure virtual method. Subclassed pages save their config settings here + * and return true if everything was saved successfully. */ + virtual bool save(QString &errmsg) = 0; + + bool wasLoaded(); + +protected: + void showEvent(QShowEvent * event); + + bool loaded; +}; + +#endif + diff --git a/retroshare-gui/src/gui/settings/rsettings.cpp b/retroshare-gui/src/gui/settings/rsettings.cpp new file mode 100644 index 000000000..643dcaa8a --- /dev/null +++ b/retroshare-gui/src/gui/settings/rsettings.cpp @@ -0,0 +1,131 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, crypton + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "rsettings.h" +#include + +/** The file in which all settings will read and written. */ +#define SETTINGS_FILE (RsInit::RsProfileConfigDirectory() + "/RetroShare.conf") + +/** Constructor */ +RSettings::RSettings(const QString settingsGroup) +: QSettings(QString::fromStdString(SETTINGS_FILE), QSettings::IniFormat) +{ + std::string sPreferedId; + m_bValid = RsInit::getPreferedAccountId(sPreferedId); + + if (!settingsGroup.isEmpty()) + beginGroup(settingsGroup); +} + +RSettings::RSettings(std::string fileName, const QString settingsGroup) +: QSettings(QString::fromStdString(fileName), QSettings::IniFormat) +{ + m_bValid = true; + if (!settingsGroup.isEmpty()) + beginGroup(settingsGroup); +} + +/** Returns the saved value associated with key. If no value has been + * set, the default value is returned. + * \sa setDefault + */ +QVariant +RSettings::value(const QString &key, const QVariant &defaultVal) const +{ + if (m_bValid == false) { + // return only default value + return defaultVal.isNull() ? defaultValue(key) : defaultVal; + } + return QSettings::value(key, defaultVal.isNull() ? defaultValue(key) : defaultVal); +} + +/** Sets the value associated with key to val. */ +void +RSettings::setValue(const QString &key, const QVariant &val) +{ + if (m_bValid == false) { + std::cerr << "RSettings::setValue() Calling on invalid object, key = " << key.toStdString() << std::endl; + return; + } + if (val == defaultValue(key)) + QSettings::remove(key); + else if (val != value(key)) + QSettings::setValue(key, val); +} + +QVariant RSettings::valueFromGroup(const QString &group, const QString &key, const QVariant &defaultVal) +{ + beginGroup(group); + QVariant val = value(key, defaultVal); + endGroup(); + + return val; +} + +void RSettings::setValueToGroup(const QString &group, const QString &key, const QVariant &val) +{ + beginGroup(group); + setValue(key, val); + endGroup(); +} + +/** Sets the default setting for key to val. */ +void +RSettings::setDefault(const QString &key, const QVariant &val) +{ + _defaults.insert(key, val); +} + +/** Returns the default setting value associated with key. If + * key has no default value, then an empty QVariant is returned. */ +QVariant +RSettings::defaultValue(const QString &key) const +{ + if (_defaults.contains(key)) + return _defaults.value(key); + return QVariant(); +} + +/** Resets all settings. */ +void +RSettings::reset() +{ + /* Static method, so we have to create a QSettings object. */ + QSettings settings(QString::fromStdString(SETTINGS_FILE), QSettings::IniFormat); + settings.clear(); +} + +/** Returns a map of all currently saved settings at the last appyl() point. */ +/*QMap +RSettings::allSettings() const +{ + QMap settings; + foreach (QString key, allKeys()) { + settings.insert(key, value(key)); + } + return settings; +}*/ + diff --git a/retroshare-gui/src/gui/settings/rsettings.h b/retroshare-gui/src/gui/settings/rsettings.h new file mode 100644 index 000000000..095b84413 --- /dev/null +++ b/retroshare-gui/src/gui/settings/rsettings.h @@ -0,0 +1,79 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, crypton + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _RSETTINGS_H +#define _RSETTINGS_H + +#include +#include + + +class RSettings : public QSettings +{ + Q_OBJECT + +public: + /** Default constructor. The optional parameter group can be used to + * set a prefix that will be prepended to keys specified to RSettings in + * value() and setValue(). */ + RSettings(const QString group = QString()); + + /** Default constructor. The optional parameter group can be used to + * set a prefix that will be prepended to keys specified to RSettings in + * value() and setValue(). */ + RSettings(std::string fileName, const QString group = QString()); + + /** Resets all settings. */ + static void reset(); + + /** Returns the saved value associated with key. If no value has been + * set, the default value is returned. + * \sa setDefault + */ + virtual QVariant value(const QString &key, + const QVariant &defaultVal = QVariant()) const; + /** Sets the value associated with key to val. */ + virtual void setValue(const QString &key, const QVariant &val); + + virtual QVariant valueFromGroup(const QString &group, const QString &key, + const QVariant &defaultVal = QVariant()); + virtual void setValueToGroup(const QString &group, const QString &key, const QVariant &val); + +protected: + bool m_bValid; // is valid - dependent on RsInit::getPreferedAccountId + + /** Sets the default setting for key to val. */ + void setDefault(const QString &key, const QVariant &val); + /** Returns the default setting value associated with key. If + * key has no default value, then an empty QVariant is returned. */ + QVariant defaultValue(const QString &key) const; + /** Returns a map of all currently saved settings at the last apply() + * point. */ + //QMap allSettings() const; + +private: + /** Association of setting key names to default setting values. */ + QHash _defaults; +}; + +#endif + diff --git a/retroshare-gui/src/gui/settings/rsettingswin.cpp b/retroshare-gui/src/gui/settings/rsettingswin.cpp new file mode 100644 index 000000000..e2dcd37a2 --- /dev/null +++ b/retroshare-gui/src/gui/settings/rsettingswin.cpp @@ -0,0 +1,225 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 -2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "GeneralPage.h" +#include "DirectoriesPage.h" +#include "ServerPage.h" +#include "NetworkPage.h" +#include "NotifyPage.h" +#include "CryptoPage.h" +#include "AppearancePage.h" +#include "FileAssociationsPage.h" +#include "SoundPage.h" +#include "TransferPage.h" +#include "ChatPage.h" +#include "MessagePage.h" +#include "ForumPage.h" +#include "PluginsPage.h" + +#define IMAGE_GENERAL ":/images/kcmsystem24.png" + + +#include "rsettingswin.h" + +RSettingsWin *RSettingsWin::_instance = NULL; +int RSettingsWin::lastPage = 0; + +RSettingsWin::RSettingsWin(QWidget * parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + setModal(false); + + initStackedWidget(); + + connect(listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(setNewPage(int))); + connect(applyButton, SIGNAL(clicked( bool )), this, SLOT( saveChanges()) ); +} + +RSettingsWin::~RSettingsWin() +{ + lastPage = stackedWidget->currentIndex (); + _instance = NULL; +} + +/*static*/ void RSettingsWin::showYourself(QWidget *parent, PageType page /*= LastPage*/) +{ + if(_instance == NULL) { + _instance = new RSettingsWin(parent); + } + + if (page != LastPage) { + /* show given page */ + _instance->setNewPage(page); + } else { + if (_instance->isHidden()) { + _instance->setNewPage(lastPage); + } + } + + _instance->show(); + _instance->activateWindow(); +} + +/*static*/ void RSettingsWin::postModDirectories(bool update_local) +{ + if (_instance == NULL || _instance->isHidden() || _instance->stackedWidget == NULL) { + return; + } + + if (update_local) { + if (_instance->stackedWidget->currentIndex() == Directories) { + ConfigPage *Page = dynamic_cast (_instance->stackedWidget->currentWidget()); + if (Page) { + Page->load(); + } + } + } +} + +void +RSettingsWin::initStackedWidget() +{ + stackedWidget->setCurrentIndex(-1); + stackedWidget->removeWidget(stackedWidget->widget(0)); + + stackedWidget->addWidget(new GeneralPage(0)); + stackedWidget->addWidget(new ServerPage()); + stackedWidget->addWidget(new TransferPage()); + stackedWidget->addWidget(new DirectoriesPage()); + stackedWidget->addWidget(new PluginsPage() ); + stackedWidget->addWidget(new NotifyPage()); + stackedWidget->addWidget(new CryptoPage()); + stackedWidget->addWidget(new MessagePage()); + stackedWidget->addWidget(new ForumPage()); + stackedWidget->addWidget(new ChatPage()); + stackedWidget->addWidget(new AppearancePage()); + stackedWidget->addWidget(new SoundPage() ); + + setNewPage(General); +} + +void +RSettingsWin::setNewPage(int page) +{ + QString text; + + switch (page) + { + case General: + text = tr("General"); + pageicon->setPixmap(QPixmap(":/images/kcmsystem24.png")); + break; + case Directories: + text = tr("Directories"); + pageicon->setPixmap(QPixmap(":/images/folder_doments.png")); + break; + case Server: + text = tr("Server"); + pageicon->setPixmap(QPixmap(":/images/server_24x24.png")); + break; + case Transfer: + text = tr("Transfer"); + pageicon->setPixmap(QPixmap(":/images/ktorrent32.png")); + break; + case Notify: + text = tr("Notify"); + pageicon->setPixmap(QPixmap(":/images/status_unknown.png")); + break; + case Security: + text = tr("Security"); + pageicon->setPixmap(QPixmap(":/images/encrypted32.png")); + break; + case Message: + text = tr("Message"); + pageicon->setPixmap(QPixmap(":/images/evolution.png")); + break; + case Forum: + text = tr("Forum"); + pageicon->setPixmap(QPixmap(":/images/konversation.png")); + break; + case Plugins: + text = tr("Plugins"); + pageicon->setPixmap(QPixmap(":/images/extension_32.png")); + break; + case Chat: + text = tr("Chat"); + pageicon->setPixmap(QPixmap(":/images/chat_24.png")); + break; + case Appearance: + text = tr("Appearance"); + pageicon->setPixmap(QPixmap(":/images/looknfeel.png")); + break; + /*// #ifndef RS_RELEASE_VERSION + case Fileassociations: + text = tr("File Associations"); + pageicon->setPixmap(QPixmap(":/images/filetype-association.png")); + break;*/ + case Sound: + text = tr("Sound"); + pageicon->setPixmap(QPixmap(":/images/sound.png")); + break; + // #endif + default: + text = tr("UnknownPage");// impossible case + } + + pageName->setText(text); + stackedWidget->setCurrentIndex(page); + listWidget->setCurrentRow(page); +} + +/** Saves changes made to settings. */ +void +RSettingsWin::saveChanges() +{ + QString errmsg; + + /* Call each config page's save() method to save its data */ + int i, count = stackedWidget->count(); + for (i = 0; i < count; i++) + { + ConfigPage *page = dynamic_cast(stackedWidget->widget(i)); + if (page && page->wasLoaded()) { + if (!page->save(errmsg)) + { + /* Display the offending page */ + stackedWidget->setCurrentWidget(page); + + /* Show the user what went wrong */ + QMessageBox::warning(this, + tr("Error Saving Configuration on page ")+QString::number(i), errmsg, + QMessageBox::Ok, QMessageBox::NoButton); + + /* Don't process the rest of the pages */ + return; + } + } + } + + /* call to RsIface save function.... */ + //rsicontrol -> ConfigSave(); + + close(); +} diff --git a/retroshare-gui/src/gui/settings/rsettingswin.h b/retroshare-gui/src/gui/settings/rsettingswin.h new file mode 100755 index 000000000..ae51ce2e4 --- /dev/null +++ b/retroshare-gui/src/gui/settings/rsettingswin.h @@ -0,0 +1,60 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RSETTINGSWIN_HPP_ +# define RSETTINGSWIN_HPP_ + +# include +# include "ui_settings.h" + + +class RSettingsWin: public QDialog, private Ui::Settings +{ + Q_OBJECT + + public: + enum PageType { LastPage = -1, General = 0, Server, Transfer, + Directories, Plugins, Notify, Security, Message, Forum, Chat, Appearance, Sound, Fileassociations }; + + static void showYourself(QWidget *parent, PageType page = LastPage); + static void postModDirectories(bool update_local); + + protected: + RSettingsWin(QWidget * parent = 0, Qt::WFlags flags = 0); + ~RSettingsWin(); + + public slots: + //! Go to a specific part of the control panel. + void setNewPage(int page); + + private slots: + /** Called when user clicks "Save Settings" */ + void saveChanges(); + + private: + void initStackedWidget(); + + private: + static RSettingsWin *_instance; + static int lastPage; +}; + +#endif // !RSETTINGSWIN_HPP_ diff --git a/retroshare-gui/src/gui/settings/rsharesettings.cpp b/retroshare-gui/src/gui/settings/rsharesettings.cpp new file mode 100644 index 000000000..e9eaf8e61 --- /dev/null +++ b/retroshare-gui/src/gui/settings/rsharesettings.cpp @@ -0,0 +1,691 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + + +#include +#include +#include +#include +#include +#include + +#include "rsharesettings.h" +#ifdef MINIMAL_RSGUI +#include +#else +#include "gui/MainWindow.h" +#endif // MINIMAL_RSGUI + +#include +#include + +#if defined(Q_WS_WIN) +#include +#endif + + +/* Retroshare's Settings */ +#define SETTING_LANGUAGE "LanguageCode" +#define SETTING_STYLE "InterfaceStyle" +#define SETTING_SHEETNAME "SheetName" + +#define SETTING_DATA_DIRECTORY "DataDirectory" +#define SETTING_BWGRAPH_FILTER "StatisticDialog/BWLineFilter" +#define SETTING_BWGRAPH_OPACITY "StatisticDialog/Opacity" +#define SETTING_BWGRAPH_ALWAYS_ON_TOP "StatisticDialog/AlwaysOnTop" + +#define SETTING_NEWSFEED_FLAGS "NewsFeedFlags" +#define SETTING_CHAT_FLAGS "ChatFlags" +#define SETTING_NOTIFY_FLAGS "NotifyFlags" +#define SETTING_TRAYNOTIFY_FLAGS "TrayNotifyFlags" +#define SETTING_CHAT_AVATAR "ChatAvatar" + +/* Default Retroshare Settings */ +#define DEFAULT_OPACITY 100 + + +#if defined(Q_OS_WIN32) +#define STARTUP_REG_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Run" +#define RETROSHARE_REG_KEY "RetroShare" +#endif + +/* Default bandwidth graph settings */ +#define DEFAULT_BWGRAPH_FILTER (BWGRAPH_SEND|BWGRAPH_REC) +#define DEFAULT_BWGRAPH_ALWAYS_ON_TOP false + +// the one and only global settings object +RshareSettings *Settings = NULL; + +/*static*/ void RshareSettings::Create () +{ + if (Settings && Settings->m_bValid == false) { + // recreate with correct path + delete (Settings); + Settings = NULL; + } + if (Settings == NULL) { + Settings = new RshareSettings (); + } +} + +/** Default Constructor */ +RshareSettings::RshareSettings() +{ + m_maxTimeBeforeIdle = -1; + + initSettings(); +} + +void RshareSettings::initSettings() +{ +#if defined(Q_WS_MAC) + setDefault(SETTING_STYLE, "macintosh (aqua)"); +#else + static QStringList styles = QStyleFactory::keys(); +#if defined(Q_WS_WIN) + if (styles.contains("windowsvista", Qt::CaseInsensitive)) + setDefault(SETTING_STYLE, "windowsvista"); + else if (styles.contains("windowsxp", Qt::CaseInsensitive)) + setDefault(SETTING_STYLE, "windowsxp"); + else +#endif + { + if (styles.contains("cleanlooks", Qt::CaseInsensitive)) + setDefault(SETTING_STYLE, "cleanlooks"); + else + setDefault(SETTING_STYLE, "plastique"); + } +#endif + + setDefault(SETTING_LANGUAGE, LanguageSupport::defaultLanguageCode()); + setDefault(SETTING_SHEETNAME, true); + + /* defaults here are not ideal.... but dusent matter */ + + uint defChat = RS_CHAT_OPEN; + // This is not default... RS_CHAT_FOCUS. + + uint defNotify = (RS_POPUP_CONNECT | RS_POPUP_MSG); + + uint defNewsFeed = (RS_FEED_TYPE_PEER | RS_FEED_TYPE_CHAN | + RS_FEED_TYPE_FORUM | RS_FEED_TYPE_BLOG | + RS_FEED_TYPE_CHAT | RS_FEED_TYPE_MSG | + RS_FEED_TYPE_FILES); + + setDefault(SETTING_NEWSFEED_FLAGS, defNewsFeed); + setDefault(SETTING_CHAT_FLAGS, defChat); + setDefault(SETTING_NOTIFY_FLAGS, defNotify); + + setDefault("DisplayTrayGroupChat", true); + setDefault("AddFeedsAtEnd", false); +} + +/** Gets the currently preferred language code for Rshare. */ +QString RshareSettings::getLanguageCode() +{ + return value(SETTING_LANGUAGE).toString(); +} + +/** Sets the preferred language code. */ +void RshareSettings::setLanguageCode(QString languageCode) +{ + setValue(SETTING_LANGUAGE, languageCode); +} + +/** Gets the interface style key (e.g., "windows", "motif", etc.) */ +QString RshareSettings::getInterfaceStyle() +{ + return value(SETTING_STYLE).toString(); +} + +/** Sets the interface style key. */ +void RshareSettings::setInterfaceStyle(QString styleKey) +{ + setValue(SETTING_STYLE, styleKey); +} + +/** Gets the sheetname.*/ +QString RshareSettings::getSheetName() +{ + return value(SETTING_SHEETNAME).toString(); +} +/** Sets the sheetname.*/ +void RshareSettings::setSheetName(QString sheet) +{ + setValue(SETTING_SHEETNAME, sheet); +} + +static QString getKeyForLastDir(RshareSettings::enumLastDir type) +{ + switch (type) { + case RshareSettings::LASTDIR_EXTRAFILE: + return "ExtraFile"; + case RshareSettings::LASTDIR_CERT: + return "Certificate"; + case RshareSettings::LASTDIR_HISTORY: + return "History"; + case RshareSettings::LASTDIR_IMAGES: + return "Images"; + case RshareSettings::LASTDIR_MESSAGES: + return "Messages"; + case RshareSettings::LASTDIR_BLOGS: + return "Messages"; + } + return ""; +} + +QString RshareSettings::getLastDir(enumLastDir type) +{ + QString key = getKeyForLastDir(type); + if (key.isEmpty()) { + return ""; + } + + return valueFromGroup("LastDir", key).toString(); +} + +void RshareSettings::setLastDir(enumLastDir type, const QString &lastDir) +{ + QString key = getKeyForLastDir(type); + if (key.isEmpty()) { + return; + } + + setValueToGroup("LastDir", key, lastDir); +} + +/** Returns the bandwidth line filter. */ +uint RshareSettings::getBWGraphFilter() +{ + return value(SETTING_BWGRAPH_FILTER, DEFAULT_BWGRAPH_FILTER).toUInt(); +} + +/** Saves the setting for whether or not the given line will be graphed */ +void RshareSettings::setBWGraphFilter(uint line, bool status) +{ + uint filter = getBWGraphFilter(); + filter = (status ? (filter | line) : (filter & ~(line))); + setValue(SETTING_BWGRAPH_FILTER, filter); +} + +/** Get the level of opacity for the BandwidthGraph window. */ +int RshareSettings::getBWGraphOpacity() +{ + return value(SETTING_BWGRAPH_OPACITY, DEFAULT_OPACITY).toInt(); +} + +/** Set the level of opacity for the BandwidthGraph window. */ +void RshareSettings::setBWGraphOpacity(int value) +{ + setValue(SETTING_BWGRAPH_OPACITY, value); +} + +/** Gets whether the bandwidth graph is always on top when displayed. */ +bool RshareSettings::getBWGraphAlwaysOnTop() +{ + return value(SETTING_BWGRAPH_ALWAYS_ON_TOP, + DEFAULT_BWGRAPH_ALWAYS_ON_TOP).toBool(); +} + +/** Sets whether the bandwidth graph is always on top when displayed. */ +void RshareSettings::setBWGraphAlwaysOnTop(bool alwaysOnTop) +{ + setValue(SETTING_BWGRAPH_ALWAYS_ON_TOP, alwaysOnTop); +} + +/** Returns true if RetroShare's main window should be visible when the + * application starts. */ +bool RshareSettings::getStartMinimized() +{ + return value("StartMinimized", false).toBool(); +} + +/** Sets whether to show RetroShare's main window when the application starts. */ +void RshareSettings::setStartMinimized(bool startMinimized) +{ + setValue("StartMinimized", startMinimized); +} + +bool RshareSettings::getCloseToTray() +{ + return value("ClosetoTray", false).toBool(); +} + +void RshareSettings::setCloseToTray(bool closeToTray) +{ + setValue("ClosetoTray", closeToTray); +} + +/** Setting for Notify / Chat and NewsFeeds **/ +uint RshareSettings::getNewsFeedFlags() +{ + return value(SETTING_NEWSFEED_FLAGS).toUInt(); +} + +void RshareSettings::setNewsFeedFlags(uint flags) +{ + setValue(SETTING_NEWSFEED_FLAGS, flags); +} + +uint RshareSettings::getChatFlags() +{ + return value(SETTING_CHAT_FLAGS).toUInt(); +} + +void RshareSettings::setChatFlags(uint flags) +{ + setValue(SETTING_CHAT_FLAGS, flags); +} + +uint RshareSettings::getNotifyFlags() +{ + return value(SETTING_NOTIFY_FLAGS).toUInt(); +} + +void RshareSettings::setNotifyFlags(uint flags) +{ + setValue(SETTING_NOTIFY_FLAGS, flags); +} + +uint RshareSettings::getTrayNotifyFlags() +{ + return value(SETTING_TRAYNOTIFY_FLAGS, TRAYNOTIFY_ALL).toUInt(); +} + +void RshareSettings::setTrayNotifyFlags(uint flags) +{ + setValue(SETTING_TRAYNOTIFY_FLAGS, flags); +} + +bool RshareSettings::getDisplayTrayGroupChat() +{ + return value("DisplayTrayGroupChat").toBool(); +} + +void RshareSettings::setDisplayTrayGroupChat(bool bValue) +{ + setValue("DisplayTrayGroupChat", bValue); +} + +bool RshareSettings::getAddFeedsAtEnd() +{ + return value("AddFeedsAtEnd").toBool(); +} + +void RshareSettings::setAddFeedsAtEnd(bool bValue) +{ + setValue("AddFeedsAtEnd", bValue); +} + +bool RshareSettings::getChatSendMessageWithCtrlReturn() +{ + return valueFromGroup("Chat", "SendMessageWithCtrlReturn", false).toBool(); +} + +RshareSettings::enumToasterPosition RshareSettings::getToasterPosition() +{ + return (enumToasterPosition) value("ToasterPosition", TOASTERPOS_BOTTOMRIGHT).toInt(); +} + +void RshareSettings::setToasterPosition(enumToasterPosition position) +{ + setValue("ToasterPosition", position); +} + +QPoint RshareSettings::getToasterMargin() +{ + return value("ToasterMargin", QPoint(10, 10)).toPoint(); +} + +void RshareSettings::setToasterMargin(QPoint margin) +{ + setValue("ToasterMargin", margin); +} + +void RshareSettings::setChatSendMessageWithCtrlReturn(bool bValue) +{ + setValueToGroup("Chat", "SendMessageWithCtrlReturn", bValue); +} + +QString RshareSettings::getChatScreenFont() +{ + return valueFromGroup("Chat", "ChatScreenFont").toString(); +} + +void RshareSettings::setChatScreenFont(const QString &font) +{ + setValueToGroup("Chat", "ChatScreenFont", font); +} + +void RshareSettings::getPublicChatStyle(QString &stylePath, QString &styleVariant) +{ + stylePath = valueFromGroup("Chat", "StylePublic", ":/qss/chat/public").toString(); + styleVariant = valueFromGroup("Chat", "StylePublicVariant", "").toString(); +} + +void RshareSettings::setPublicChatStyle(const QString &stylePath, const QString &styleVariant) +{ + setValueToGroup("Chat", "StylePublic", stylePath); + setValueToGroup("Chat", "StylePublicVariant", styleVariant); +} + +void RshareSettings::getPrivateChatStyle(QString &stylePath, QString &styleVariant) +{ + stylePath = valueFromGroup("Chat", "StylePrivate", ":/qss/chat/private").toString(); + styleVariant = valueFromGroup("Chat", "StylePrivateVariant", "").toString(); +} + +void RshareSettings::setPrivateChatStyle(const QString &stylePath, const QString &styleVariant) +{ + setValueToGroup("Chat", "StylePrivate", stylePath); + setValueToGroup("Chat", "StylePrivateVariant", styleVariant); +} + +void RshareSettings::getHistoryChatStyle(QString &stylePath, QString &styleVariant) +{ + stylePath = valueFromGroup("Chat", "StyleHistory", ":/qss/chat/history").toString(); + styleVariant = valueFromGroup("Chat", "StylePrivateVariant", "").toString(); +} + +void RshareSettings::setHistoryChatStyle(const QString &stylePath, const QString &styleVariant) +{ + setValueToGroup("Chat", "StyleHistory", stylePath); + setValueToGroup("Chat", "StylePrivateVariant", styleVariant); +} + +int RshareSettings::getPublicChatHistoryCount() +{ + return valueFromGroup("Chat", "PublicChatHistoryCount", 0).toInt(); +} + +void RshareSettings::setPublicChatHistoryCount(int value) +{ + setValueToGroup("Chat", "PublicChatHistoryCount", value); +} + +int RshareSettings::getPrivateChatHistoryCount() +{ + return valueFromGroup("Chat", "PrivateChatHistoryCount", 20).toInt(); +} + +void RshareSettings::setPrivateChatHistoryCount(int value) +{ + setValueToGroup("Chat", "PrivateChatHistoryCount", value); +} + +/** Returns true if RetroShare is set to run on system boot. */ +bool +RshareSettings::runRetroshareOnBoot(bool &minimized) +{ + minimized = false; + +#if defined(Q_WS_WIN) + QString value = win32_registry_get_key_value(STARTUP_REG_KEY, RETROSHARE_REG_KEY); + + if (!value.isEmpty()) { + /* Simple check for "-m" */ + minimized = value.contains(" -m"); + return true; + } + return false; +#else + /* Platforms other than windows aren't supported yet */ + return false; +#endif +} + +/** If run is set to true, then RetroShare will run on system boot. */ +void +RshareSettings::setRunRetroshareOnBoot(bool run, bool minimized) +{ +#if defined(Q_WS_WIN) + if (run) { + QString value = "\"" + QDir::convertSeparators(QCoreApplication::applicationFilePath()) + "\""; + + if (minimized) { + value += " -m"; + } + + win32_registry_set_key_value(STARTUP_REG_KEY, RETROSHARE_REG_KEY, value); + } else { + win32_registry_remove_key(STARTUP_REG_KEY, RETROSHARE_REG_KEY); + } +#else + /* Platforms othe rthan windows aren't supported yet */ + Q_UNUSED(run); + Q_UNUSED(minimized); +#endif +} + +static QString getAppPathForProtocol() +{ + return "\"" + QDir::convertSeparators(QCoreApplication::applicationFilePath()) + "\" -r \"%1\""; +} + +/** Returns true if retroshare:// is registered as protocol */ +bool RshareSettings::getRetroShareProtocol() +{ +#if defined(Q_WS_WIN) + /* Check key */ + QSettings retroshare("HKEY_CLASSES_ROOT\\retroshare", QSettings::NativeFormat); + if (retroshare.contains("Default")) { + /* Check profile */ + if (retroshare.value("Profile").toString().toStdString() == rsPeers->getOwnId()) { + /* Check app path */ + QSettings command("HKEY_CLASSES_ROOT\\retroshare\\shell\\open\\command", QSettings::NativeFormat); + if (command.value("Default").toString() == getAppPathForProtocol()) { + return true; + } + } + } +#else + /* Platforms other than windows aren't supported yet */ +#endif + return false; +} + +/** Register retroshare:// as protocl */ +void RshareSettings::setRetroShareProtocol(bool value) +{ +#if defined(Q_WS_WIN) + if (value) { + QSettings retroshare("HKEY_CLASSES_ROOT\\retroshare", QSettings::NativeFormat); + retroshare.setValue("Default", "URL: RetroShare protocol"); + retroshare.setValue("URL Protocol", ""); + retroshare.setValue("Profile", QString::fromStdString(rsPeers->getOwnId())); + + QSettings command("HKEY_CLASSES_ROOT\\retroshare\\shell\\open\\command", QSettings::NativeFormat); + command.setValue("Default", getAppPathForProtocol()); + } else { + QSettings retroshare("HKEY_CLASSES_ROOT", QSettings::NativeFormat); + retroshare.remove("retroshare"); + } +#else + /* Platforms othe rthan windows aren't supported yet */ + Q_UNUSED(value); +#endif +} + +/** Saving Generic Widget Size / Location */ + +void RshareSettings::saveWidgetInformation(QWidget *widget) +{ + beginGroup("widgetInformation"); + beginGroup(widget->objectName()); + + setValue("size", widget->size()); + setValue("pos", widget->pos()); + + endGroup(); + endGroup(); +} + +void RshareSettings::saveWidgetInformation(QMainWindow *widget, QToolBar *toolBar) +{ + beginGroup("widgetInformation"); + beginGroup(widget->objectName()); + + setValue("toolBarArea", widget->toolBarArea(toolBar)); + + endGroup(); + endGroup(); + + saveWidgetInformation(widget); +} + +void RshareSettings::loadWidgetInformation(QWidget *widget) +{ + beginGroup("widgetInformation"); + beginGroup(widget->objectName()); + + widget->resize(value("size", widget->size()).toSize()); + widget->move(value("pos", QPoint(200, 200)).toPoint()); + + endGroup(); + endGroup(); +} + +void RshareSettings::loadWidgetInformation(QMainWindow *widget, QToolBar *toolBar) +{ + beginGroup("widgetInformation"); + beginGroup(widget->objectName()); + + widget->addToolBar((Qt::ToolBarArea) value("toolBarArea", Qt::TopToolBarArea).toInt(), + toolBar); + + endGroup(); + endGroup(); + + loadWidgetInformation(widget); +} + +#ifndef MINIMAL_RSGUI +/* MainWindow */ +int RshareSettings::getLastPageInMainWindow () +{ + return valueFromGroup("MainWindow", "LastPage", MainWindow::Network).toInt(); +} + +void RshareSettings::setLastPageInMainWindow (int value) +{ + setValueToGroup("MainWindow", "LastPage", value); +} + +uint RshareSettings::getStatusBarFlags() +{ + /* Default = All but disc status */ + return valueFromGroup("MainWindow", "StatusBarFlags", 0xFFFFFFFF ^ STATUSBAR_DISC).toUInt(); +} + +void RshareSettings::setStatusBarFlags(uint flags) +{ + setValueToGroup("MainWindow", "StatusBarFlags", flags); +} + +void RshareSettings::setStatusBarFlag(uint flag, bool enable) +{ + uint flags = getStatusBarFlags(); + + if (enable) { + flags |= flag; + } else { + flags &= ~flag; + } + + setStatusBarFlags(flags); +} +#endif // MINIMAL_RSGUI + +/* Messages */ +bool RshareSettings::getMsgSetToReadOnActivate () +{ + return valueFromGroup("MessageDialog", "SetMsgToReadOnActivate", true).toBool(); +} + +void RshareSettings::setMsgSetToReadOnActivate (bool bValue) +{ + setValueToGroup("MessageDialog", "SetMsgToReadOnActivate", bValue); +} + +RshareSettings::enumMsgOpen RshareSettings::getMsgOpen() +{ + enumMsgOpen value = (enumMsgOpen) valueFromGroup("MessageDialog", "msgOpen", MSG_OPEN_TAB).toInt(); + + switch (value) { + case MSG_OPEN_TAB: + case MSG_OPEN_WINDOW: + return value; + } + + return MSG_OPEN_TAB; +} + +void RshareSettings::setMsgOpen(enumMsgOpen value) +{ + switch (value) { + case MSG_OPEN_TAB: + case MSG_OPEN_WINDOW: + break; + default: + value = MSG_OPEN_TAB; + } + + setValueToGroup("MessageDialog", "msgOpen", value); +} + +/* Forums */ +bool RshareSettings::getForumMsgSetToReadOnActivate () +{ + return valueFromGroup("ForumDialog", "SetMsgToReadOnActivate", true).toBool(); +} + +void RshareSettings::setForumMsgSetToReadOnActivate (bool bValue) +{ + setValueToGroup("ForumDialog", "SetMsgToReadOnActivate", bValue); +} + +bool RshareSettings::getExpandNewMessages() +{ + return valueFromGroup("ForumDialog", "ExpandNewMessages", true).toBool(); +} + +void RshareSettings::setExpandNewMessages (bool bValue) +{ + setValueToGroup("ForumDialog", "ExpandNewMessages", bValue); +} + +/* time before idle */ +uint RshareSettings::getMaxTimeBeforeIdle() +{ + if (m_maxTimeBeforeIdle == -1) { + m_maxTimeBeforeIdle = valueFromGroup("General", "maxTimeBeforeIdle", 30).toUInt(); + } + + return m_maxTimeBeforeIdle; +} + +void RshareSettings::setMaxTimeBeforeIdle(uint nValue) +{ + m_maxTimeBeforeIdle = nValue; + setValueToGroup("General", "maxTimeBeforeIdle", nValue); +} diff --git a/retroshare-gui/src/gui/settings/rsharesettings.h b/retroshare-gui/src/gui/settings/rsharesettings.h new file mode 100644 index 000000000..18bda3e8c --- /dev/null +++ b/retroshare-gui/src/gui/settings/rsharesettings.h @@ -0,0 +1,246 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _RSHARESETTINGS_H +#define _RSHARESETTINGS_H + +#include +#include + +#include +#include "rsettings.h" + +/* Defines for get/setTrayNotifyFlags */ +#define TRAYNOTIFY_PRIVATECHAT 0x00000001 +#define TRAYNOTIFY_MESSAGES 0x00000002 +#define TRAYNOTIFY_CHANNELS 0x00000004 +#define TRAYNOTIFY_FORUMS 0x00000008 +#define TRAYNOTIFY_TRANSFERS 0x00000010 +#define TRAYNOTIFY_ALL 0x0000001F + +#define TRAYNOTIFY_COMBINEDICON 0x80000000 + +#define STATUSBAR_DISC 0x00000001 + +//Forward declaration. +class QWidget; +class QTableWidget; +class QToolBar; +class QMainWindow; + +/** Handles saving and restoring RShares's settings + * + * NOTE: Qt 4.1 documentation states that constructing a QSettings object is + * "very fast", so we shouldn't need to create a global instance of this + * class. + */ +class RshareSettings : public RSettings +{ +public: + enum enumLastDir + { + LASTDIR_EXTRAFILE, + LASTDIR_CERT, + LASTDIR_HISTORY, + LASTDIR_IMAGES, + LASTDIR_MESSAGES, + LASTDIR_BLOGS + }; + + enum enumToasterPosition + { + TOASTERPOS_TOPLEFT, + TOASTERPOS_TOPRIGHT, + TOASTERPOS_BOTTOMLEFT, + TOASTERPOS_BOTTOMRIGHT + }; + + enum enumMsgOpen + { + MSG_OPEN_TAB, + MSG_OPEN_WINDOW + }; + +public: + /* create settings object */ + static void Create (); + + /** Gets the currently preferred language code for RShare. */ + QString getLanguageCode(); + /** Saves the preferred language code. */ + void setLanguageCode(QString languageCode); + + /** Gets the interface style key (e.g., "windows", "motif", etc.) */ + QString getInterfaceStyle(); + /** Sets the interface style key. */ + void setInterfaceStyle(QString styleKey); + + /** Sets the stylesheet */ + void setSheetName(QString sheet); + /** Gets the stylesheet */ + QString getSheetName(); + + /** Returns true if RetroShare's main window should be visible when the + * application starts. */ + bool getStartMinimized(); + /** Sets whether to show main window when the application starts. */ + void setStartMinimized(bool startMinimized); + + bool getCloseToTray(); + void setCloseToTray(bool closeToTray); + + /** Returns true if RetroShare should start on system boot. */ + bool runRetroshareOnBoot(bool &minimized); + + /** Set whether to run RetroShare on system boot. */ + void setRunRetroshareOnBoot(bool run, bool minimized); + + /** Returns true if retroshare:// is registered as protocol */ + bool getRetroShareProtocol(); + /** Register retroshare:// as protocl */ + void setRetroShareProtocol(bool value); + + /* Get the destination log file. */ + QString getLogFile(); + /** Set the destination log file. */ + void setLogFile(QString file); + + QString getLastDir(enumLastDir type); + void setLastDir(enumLastDir type, const QString &lastDir); + + /* Get the bandwidth graph line filter. */ + uint getBWGraphFilter(); + /** Set the bandwidth graph line filter. */ + void setBWGraphFilter(uint line, bool status); + + /** Set the bandwidth graph opacity setting. */ + int getBWGraphOpacity(); + /** Set the bandwidth graph opacity settings. */ + void setBWGraphOpacity(int value); + + /** Gets whether the bandwidth graph is always on top. */ + bool getBWGraphAlwaysOnTop(); + /** Sets whether the bandwidth graph is always on top. */ + void setBWGraphAlwaysOnTop(bool alwaysOnTop); + + uint getNewsFeedFlags(); + void setNewsFeedFlags(uint flags); + + uint getChatFlags(); + void setChatFlags(uint flags); + + uint getNotifyFlags(); + void setNotifyFlags(uint flags); + + uint getTrayNotifyFlags(); + void setTrayNotifyFlags(uint flags); + + bool getDisplayTrayGroupChat(); + void setDisplayTrayGroupChat(bool bValue); + + bool getAddFeedsAtEnd(); + void setAddFeedsAtEnd(bool bValue); + + bool getChatSendMessageWithCtrlReturn(); + void setChatSendMessageWithCtrlReturn(bool bValue); + + enumToasterPosition getToasterPosition(); + void setToasterPosition(enumToasterPosition position); + + QPoint getToasterMargin(); + void setToasterMargin(QPoint margin); + + /* chat font */ + QString getChatScreenFont(); + void setChatScreenFont(const QString &font); + + /* chat styles */ + void getPublicChatStyle(QString &stylePath, QString &styleVariant); + void setPublicChatStyle(const QString &stylePath, const QString &styleVariant); + + void getPrivateChatStyle(QString &stylePath, QString &styleVariant); + void setPrivateChatStyle(const QString &stylePath, const QString &styleVariant); + + void getHistoryChatStyle(QString &stylePath, QString &styleVariant); + void setHistoryChatStyle(const QString &stylePath, const QString &styleVariant); + + /* Chat */ + int getPublicChatHistoryCount(); + void setPublicChatHistoryCount(int value); + + int getPrivateChatHistoryCount(); + void setPrivateChatHistoryCount(int value); + + //! Save placement, state and size information of a window. + void saveWidgetInformation(QWidget *widget); + + //! Load placement, state and size information of a window. + void loadWidgetInformation(QWidget *widget); + + //! Method overload. Save window and toolbar information. + void saveWidgetInformation(QMainWindow *widget, QToolBar *toolBar); + + //! Method overload. Restore window and toolbar information. + void loadWidgetInformation(QMainWindow *widget, QToolBar *toolBar); + +#ifndef MINIMAL_RSGUI + /* MainWindow */ + int getLastPageInMainWindow (); + void setLastPageInMainWindow (int value); + uint getStatusBarFlags(); + void setStatusBarFlags(uint flags); + void setStatusBarFlag(uint flag, bool enable); +#endif // MINIMAL_RSGUI + + /* Messages */ + bool getMsgSetToReadOnActivate (); + void setMsgSetToReadOnActivate (bool bValue); + + enumMsgOpen getMsgOpen(); + void setMsgOpen(enumMsgOpen value); + + /* Forums */ + bool getForumMsgSetToReadOnActivate (); + void setForumMsgSetToReadOnActivate (bool bValue); + bool getExpandNewMessages (); + void setExpandNewMessages (bool bValue); + + /* time before idle */ + uint getMaxTimeBeforeIdle(); + void setMaxTimeBeforeIdle(uint nValue); + +protected: + /** Default constructor. */ + RshareSettings(); + + void initSettings(); + + /* member for fast access */ + int m_maxTimeBeforeIdle; +}; + +// the one and only global settings object +extern RshareSettings *Settings; + +#endif + diff --git a/retroshare-gui/src/gui/settings/settings.ui b/retroshare-gui/src/gui/settings/settings.ui new file mode 100755 index 000000000..6dbea58ac --- /dev/null +++ b/retroshare-gui/src/gui/settings/settings.ui @@ -0,0 +1,350 @@ + + + Settings + + + + 0 + 0 + 458 + 366 + + + + Options + + + + :/images/kcmsystem24.png:/images/kcmsystem24.png + + + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + false + + + + 24 + 24 + + + + Qt::ElideMiddle + + + QListView::Static + + + QListView::TopToBottom + + + false + + + QListView::Fixed + + + QListView::SinglePass + + + 0 + + + + 100 + 24 + + + + QListView::ListMode + + + 0 + + + true + + + -1 + + + + General + + + + :/images/kcmsystem24.png:/images/kcmsystem24.png + + + + + Server + + + + :/images/server_24x24.png:/images/server_24x24.png + + + + + Transfer + + + + :/images/ktorrent32.png:/images/ktorrent32.png + + + + + Directories + + + + :/images/folder_doments.png:/images/folder_doments.png + + + + + Plugins + + + + :/images/extension_32.png:/images/extension_32.png + + + + + Notify + + + + :/images/status_unknown.png:/images/status_unknown.png + + + + + Security + + + + :/images/encrypted32.png:/images/encrypted32.png + + + + + Message + + + + :/images/evolution.png:/images/evolution.png + + + + + Forum + + + + :/images/konversation.png:/images/konversation.png + + + + + Chat + + + + :/images/chat_24.png:/images/chat_24.png + + + + + Appearance + + + + :/images/looknfeel.png:/images/looknfeel.png + + + + + Sound + + + + :/images/sound.png:/images/sound.png + + + + + + + + + + + 24 + 24 + + + + + + + true + + + + + + + + 0 + 0 + + + + + Sans Serif + 11 + 75 + false + true + false + false + + + + + + + + + + + Qt::Horizontal + + + + + + + + + 0 + + + + + + + + Qt::Horizontal + + + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 312 + 31 + + + + + + + + + 0 + 22 + + + + Cancel + + + + + + + + 0 + 22 + + + + OK + + + true + + + + + + + + + + + + + applyButton + clicked() + Settings + accept() + + + 278 + 253 + + + 96 + 254 + + + + + canceButton + clicked() + Settings + reject() + + + 369 + 253 + + + 179 + 282 + + + + + diff --git a/retroshare-gui/src/gui/smileys/act-up.png b/retroshare-gui/src/gui/smileys/act-up.png new file mode 100644 index 000000000..a6ed2c482 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/act-up.png differ diff --git a/retroshare-gui/src/gui/smileys/afraid.png b/retroshare-gui/src/gui/smileys/afraid.png new file mode 100644 index 000000000..623a5d26e Binary files /dev/null and b/retroshare-gui/src/gui/smileys/afraid.png differ diff --git a/retroshare-gui/src/gui/smileys/airplane.png b/retroshare-gui/src/gui/smileys/airplane.png new file mode 100644 index 000000000..dd87f7a0d Binary files /dev/null and b/retroshare-gui/src/gui/smileys/airplane.png differ diff --git a/retroshare-gui/src/gui/smileys/alien.png b/retroshare-gui/src/gui/smileys/alien.png new file mode 100644 index 000000000..b9ca044e3 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/alien.png differ diff --git a/retroshare-gui/src/gui/smileys/amorous.png b/retroshare-gui/src/gui/smileys/amorous.png new file mode 100644 index 000000000..e752acc97 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/amorous.png differ diff --git a/retroshare-gui/src/gui/smileys/angel.png b/retroshare-gui/src/gui/smileys/angel.png new file mode 100644 index 000000000..cdf33893e Binary files /dev/null and b/retroshare-gui/src/gui/smileys/angel.png differ diff --git a/retroshare-gui/src/gui/smileys/angry.png b/retroshare-gui/src/gui/smileys/angry.png new file mode 100644 index 000000000..3b57d969b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/angry.png differ diff --git a/retroshare-gui/src/gui/smileys/arrogant.png b/retroshare-gui/src/gui/smileys/arrogant.png new file mode 100644 index 000000000..61093e475 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/arrogant.png differ diff --git a/retroshare-gui/src/gui/smileys/at-wits-end.png b/retroshare-gui/src/gui/smileys/at-wits-end.png new file mode 100644 index 000000000..218e5319a Binary files /dev/null and b/retroshare-gui/src/gui/smileys/at-wits-end.png differ diff --git a/retroshare-gui/src/gui/smileys/bad.png b/retroshare-gui/src/gui/smileys/bad.png new file mode 100644 index 000000000..a297f8680 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/bad.png differ diff --git a/retroshare-gui/src/gui/smileys/bashful.png b/retroshare-gui/src/gui/smileys/bashful.png new file mode 100644 index 000000000..92a99836f Binary files /dev/null and b/retroshare-gui/src/gui/smileys/bashful.png differ diff --git a/retroshare-gui/src/gui/smileys/beat-up.png b/retroshare-gui/src/gui/smileys/beat-up.png new file mode 100644 index 000000000..d1367cefa Binary files /dev/null and b/retroshare-gui/src/gui/smileys/beat-up.png differ diff --git a/retroshare-gui/src/gui/smileys/beauty.png b/retroshare-gui/src/gui/smileys/beauty.png new file mode 100644 index 000000000..95943affc Binary files /dev/null and b/retroshare-gui/src/gui/smileys/beauty.png differ diff --git a/retroshare-gui/src/gui/smileys/beer.png b/retroshare-gui/src/gui/smileys/beer.png new file mode 100644 index 000000000..6f82e46b9 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/beer.png differ diff --git a/retroshare-gui/src/gui/smileys/blowkiss.png b/retroshare-gui/src/gui/smileys/blowkiss.png new file mode 100644 index 000000000..132df9941 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/blowkiss.png differ diff --git a/retroshare-gui/src/gui/smileys/bomb.png b/retroshare-gui/src/gui/smileys/bomb.png new file mode 100644 index 000000000..f50d40758 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/bomb.png differ diff --git a/retroshare-gui/src/gui/smileys/bored.png b/retroshare-gui/src/gui/smileys/bored.png new file mode 100644 index 000000000..e063f962c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/bored.png differ diff --git a/retroshare-gui/src/gui/smileys/bowl.png b/retroshare-gui/src/gui/smileys/bowl.png new file mode 100644 index 000000000..e800c7287 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/bowl.png differ diff --git a/retroshare-gui/src/gui/smileys/boy.png b/retroshare-gui/src/gui/smileys/boy.png new file mode 100644 index 000000000..3e70c5471 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/boy.png differ diff --git a/retroshare-gui/src/gui/smileys/brb.png b/retroshare-gui/src/gui/smileys/brb.png new file mode 100644 index 000000000..61b3a146a Binary files /dev/null and b/retroshare-gui/src/gui/smileys/brb.png differ diff --git a/retroshare-gui/src/gui/smileys/bulgy-eyes.png b/retroshare-gui/src/gui/smileys/bulgy-eyes.png new file mode 100644 index 000000000..8cc7c3cd6 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/bulgy-eyes.png differ diff --git a/retroshare-gui/src/gui/smileys/bunny.png b/retroshare-gui/src/gui/smileys/bunny.png new file mode 100644 index 000000000..77d97c4ff Binary files /dev/null and b/retroshare-gui/src/gui/smileys/bunny.png differ diff --git a/retroshare-gui/src/gui/smileys/bye.png b/retroshare-gui/src/gui/smileys/bye.png new file mode 100644 index 000000000..9bfaeaa1a Binary files /dev/null and b/retroshare-gui/src/gui/smileys/bye.png differ diff --git a/retroshare-gui/src/gui/smileys/cake.png b/retroshare-gui/src/gui/smileys/cake.png new file mode 100644 index 000000000..519fd4cea Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cake.png differ diff --git a/retroshare-gui/src/gui/smileys/call-me.png b/retroshare-gui/src/gui/smileys/call-me.png new file mode 100644 index 000000000..1044de0c5 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/call-me.png differ diff --git a/retroshare-gui/src/gui/smileys/camera.png b/retroshare-gui/src/gui/smileys/camera.png new file mode 100644 index 000000000..d8ccc97b6 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/camera.png differ diff --git a/retroshare-gui/src/gui/smileys/can.png b/retroshare-gui/src/gui/smileys/can.png new file mode 100644 index 000000000..e4792ccd0 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/can.png differ diff --git a/retroshare-gui/src/gui/smileys/car.png b/retroshare-gui/src/gui/smileys/car.png new file mode 100644 index 000000000..97622bc2c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/car.png differ diff --git a/retroshare-gui/src/gui/smileys/cat.png b/retroshare-gui/src/gui/smileys/cat.png new file mode 100644 index 000000000..4b602dae8 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cat.png differ diff --git a/retroshare-gui/src/gui/smileys/chicken.png b/retroshare-gui/src/gui/smileys/chicken.png new file mode 100644 index 000000000..8356dbf09 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/chicken.png differ diff --git a/retroshare-gui/src/gui/smileys/chilli.png b/retroshare-gui/src/gui/smileys/chilli.png new file mode 100644 index 000000000..a9873bcb0 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/chilli.png differ diff --git a/retroshare-gui/src/gui/smileys/cigarette.png b/retroshare-gui/src/gui/smileys/cigarette.png new file mode 100644 index 000000000..68cffedf0 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cigarette.png differ diff --git a/retroshare-gui/src/gui/smileys/clap.png b/retroshare-gui/src/gui/smileys/clap.png new file mode 100644 index 000000000..d0b4ae6e6 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/clap.png differ diff --git a/retroshare-gui/src/gui/smileys/clock.png b/retroshare-gui/src/gui/smileys/clock.png new file mode 100644 index 000000000..e0bbb8547 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/clock.png differ diff --git a/retroshare-gui/src/gui/smileys/cloudy.png b/retroshare-gui/src/gui/smileys/cloudy.png new file mode 100644 index 000000000..4202a0ef2 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cloudy.png differ diff --git a/retroshare-gui/src/gui/smileys/clover.png b/retroshare-gui/src/gui/smileys/clover.png new file mode 100644 index 000000000..c90494ad5 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/clover.png differ diff --git a/retroshare-gui/src/gui/smileys/clown.png b/retroshare-gui/src/gui/smileys/clown.png new file mode 100644 index 000000000..bfc9552d1 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/clown.png differ diff --git a/retroshare-gui/src/gui/smileys/coffee.png b/retroshare-gui/src/gui/smileys/coffee.png new file mode 100644 index 000000000..51c4f90ad Binary files /dev/null and b/retroshare-gui/src/gui/smileys/coffee.png differ diff --git a/retroshare-gui/src/gui/smileys/coins.png b/retroshare-gui/src/gui/smileys/coins.png new file mode 100644 index 000000000..7e06f3eab Binary files /dev/null and b/retroshare-gui/src/gui/smileys/coins.png differ diff --git a/retroshare-gui/src/gui/smileys/cold.png b/retroshare-gui/src/gui/smileys/cold.png new file mode 100644 index 000000000..83ba4d4a9 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cold.png differ diff --git a/retroshare-gui/src/gui/smileys/computer.png b/retroshare-gui/src/gui/smileys/computer.png new file mode 100644 index 000000000..1b11a0932 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/computer.png differ diff --git a/retroshare-gui/src/gui/smileys/confused.png b/retroshare-gui/src/gui/smileys/confused.png new file mode 100644 index 000000000..3b77b55dc Binary files /dev/null and b/retroshare-gui/src/gui/smileys/confused.png differ diff --git a/retroshare-gui/src/gui/smileys/console.png b/retroshare-gui/src/gui/smileys/console.png new file mode 100644 index 000000000..4933bc5ee Binary files /dev/null and b/retroshare-gui/src/gui/smileys/console.png differ diff --git a/retroshare-gui/src/gui/smileys/cool.png b/retroshare-gui/src/gui/smileys/cool.png new file mode 100644 index 000000000..a4788a820 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cool.png differ diff --git a/retroshare-gui/src/gui/smileys/cow.png b/retroshare-gui/src/gui/smileys/cow.png new file mode 100644 index 000000000..62657da08 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cow.png differ diff --git a/retroshare-gui/src/gui/smileys/cowboy.png b/retroshare-gui/src/gui/smileys/cowboy.png new file mode 100644 index 000000000..8d895a960 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cowboy.png differ diff --git a/retroshare-gui/src/gui/smileys/crying.png b/retroshare-gui/src/gui/smileys/crying.png new file mode 100644 index 000000000..ec9c6f47c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/crying.png differ diff --git a/retroshare-gui/src/gui/smileys/curl-lip.png b/retroshare-gui/src/gui/smileys/curl-lip.png new file mode 100644 index 000000000..fc33918e4 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/curl-lip.png differ diff --git a/retroshare-gui/src/gui/smileys/curse.png b/retroshare-gui/src/gui/smileys/curse.png new file mode 100644 index 000000000..c1d20588a Binary files /dev/null and b/retroshare-gui/src/gui/smileys/curse.png differ diff --git a/retroshare-gui/src/gui/smileys/cute.png b/retroshare-gui/src/gui/smileys/cute.png new file mode 100644 index 000000000..f76bce10c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cute.png differ diff --git a/retroshare-gui/src/gui/smileys/cyclops.png b/retroshare-gui/src/gui/smileys/cyclops.png new file mode 100644 index 000000000..49b2f72b3 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/cyclops.png differ diff --git a/retroshare-gui/src/gui/smileys/dance.png b/retroshare-gui/src/gui/smileys/dance.png new file mode 100644 index 000000000..60e44d5db Binary files /dev/null and b/retroshare-gui/src/gui/smileys/dance.png differ diff --git a/retroshare-gui/src/gui/smileys/dazed.png b/retroshare-gui/src/gui/smileys/dazed.png new file mode 100644 index 000000000..293736055 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/dazed.png differ diff --git a/retroshare-gui/src/gui/smileys/desire.png b/retroshare-gui/src/gui/smileys/desire.png new file mode 100644 index 000000000..a04d2926b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/desire.png differ diff --git a/retroshare-gui/src/gui/smileys/devil.png b/retroshare-gui/src/gui/smileys/devil.png new file mode 100644 index 000000000..d7d0f46b4 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/devil.png differ diff --git a/retroshare-gui/src/gui/smileys/disappointed.png b/retroshare-gui/src/gui/smileys/disappointed.png new file mode 100644 index 000000000..ab307be52 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/disappointed.png differ diff --git a/retroshare-gui/src/gui/smileys/disdain.png b/retroshare-gui/src/gui/smileys/disdain.png new file mode 100644 index 000000000..a122e7825 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/disdain.png differ diff --git a/retroshare-gui/src/gui/smileys/doctor.png b/retroshare-gui/src/gui/smileys/doctor.png new file mode 100644 index 000000000..6183061a6 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/doctor.png differ diff --git a/retroshare-gui/src/gui/smileys/dog.png b/retroshare-gui/src/gui/smileys/dog.png new file mode 100644 index 000000000..d8c1ddf6f Binary files /dev/null and b/retroshare-gui/src/gui/smileys/dog.png differ diff --git a/retroshare-gui/src/gui/smileys/doh.png b/retroshare-gui/src/gui/smileys/doh.png new file mode 100644 index 000000000..66e9679d8 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/doh.png differ diff --git a/retroshare-gui/src/gui/smileys/dont-know.png b/retroshare-gui/src/gui/smileys/dont-know.png new file mode 100644 index 000000000..d6bc7eda9 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/dont-know.png differ diff --git a/retroshare-gui/src/gui/smileys/drink.png b/retroshare-gui/src/gui/smileys/drink.png new file mode 100644 index 000000000..563ab9402 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/drink.png differ diff --git a/retroshare-gui/src/gui/smileys/drool.png b/retroshare-gui/src/gui/smileys/drool.png new file mode 100644 index 000000000..5771d5bfa Binary files /dev/null and b/retroshare-gui/src/gui/smileys/drool.png differ diff --git a/retroshare-gui/src/gui/smileys/embarrassed.png b/retroshare-gui/src/gui/smileys/embarrassed.png new file mode 100644 index 000000000..f8ca79f13 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/embarrassed.png differ diff --git a/retroshare-gui/src/gui/smileys/emotes.acs b/retroshare-gui/src/gui/smileys/emotes.acs new file mode 100644 index 000000000..5ff450009 --- /dev/null +++ b/retroshare-gui/src/gui/smileys/emotes.acs @@ -0,0 +1,57 @@ +{ +":-)|:)":"smileys/happy.png"; +":-D|:D":"smileys/excited.png"; +";-)|;)":"smileys/wink.png"; +":')":"smileys/crying.png"; +":-O|:O":"smileys/shocked.png"; +":-S|:S":"smileys/confused.png"; +":$|:-$":"smileys/embarrassed.png"; +":-(|:(":"smileys/sad.png"; +":-*|:-{}":"smileys/kissing.png"; +":-P|:P":"smileys/tongue.png"; +"$-)|$)":"smileys/coins.png"; +":-@":"smileys/angry.png"; +"8-)":"smileys/eyeroll.png"; +"=))|:-j|:-J":"smileys/rotfl.png"; +"(B)|(b)":"smileys/beer.png"; +"(@)":"smileys/cat.png"; +"(P)|(p)":"smileys/camera.png"; +"(C)|(c)":"smileys/coffee.png"; +"*JOKINGLY*|:))|:-))":"smileys/laugh.png"; +"*TIRED*":"smileys/sleeping.png"; +"(bj)|baijiu":"smileys/liquor.png"; +"(L)|(l)":"smileys/love.png"; +"(U)|(u)":"smileys/love-over.png"; +"(S)":"smileys/moon.png"; +"(mp)":"smileys/mobile.png"; +"(pi)":"smileys/pizza.png"; +":)-":"smileys/peace.png"; +"(T)|(t)":"smileys/phone.png"; +"P)":"smileys/pirate.png"; +"(~~)":"smileys/pumpkin.png"; +":X|:x|:-x|:-X":"smileys/amorous.png"; +"(ip)":"smileys/island.png"; +"(^)":"smileys/cake.png"; +"<:-P|<:-p":"smileys/party.png"; +"(O)|(o)":"smileys/clock.png"; +"(um)":"smileys/umbrella.png"; +"(6)":"smileys/face-devil-grin48.png"; +"(S)":"smileys/moon.png" +"*-:)":"smileys/lamp.png" +"(Y)|(y)":"smileys/good.png" +"(N)|(n)":"smileys/bad.png" +"(D)|(d)":"smileys/drink.png" +"(ap)":"smileys/airplane.png" +"(tu)":"smileys/turtle.png" +":-t|:-T":"smileys/time-out.png" +"(~)|(wo)":"smileys/weather-overcast.png" +"(wfc)":"smileys/weather-few-clouds.png" +"(wc)":"smileys/weather-clear.png" +"(wcn)":"smileys/weather-clear-night.png" +"(wfcn)":"smileys/weather-few-clouds-night.png" +"(wsa)":"smileys/weather-severe-alert.png" +"(wss)":"smileys/weather-showers-scattered.png" +"(wsnow)":"smileys/weather-snow.png" +"(li)":"smileys/weather-storm.png" +"(st)|(ws)":"smileys/weather-showers.png" +} diff --git a/retroshare-gui/src/gui/smileys/excited.png b/retroshare-gui/src/gui/smileys/excited.png new file mode 100644 index 000000000..ce3f8664b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/excited.png differ diff --git a/retroshare-gui/src/gui/smileys/excruciating.png b/retroshare-gui/src/gui/smileys/excruciating.png new file mode 100644 index 000000000..1e7fec34e Binary files /dev/null and b/retroshare-gui/src/gui/smileys/excruciating.png differ diff --git a/retroshare-gui/src/gui/smileys/eyeroll.png b/retroshare-gui/src/gui/smileys/eyeroll.png new file mode 100644 index 000000000..0d8f021c2 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/eyeroll.png differ diff --git a/retroshare-gui/src/gui/smileys/face-devil-grin48.png b/retroshare-gui/src/gui/smileys/face-devil-grin48.png new file mode 100644 index 000000000..a3d5d4eef Binary files /dev/null and b/retroshare-gui/src/gui/smileys/face-devil-grin48.png differ diff --git a/retroshare-gui/src/gui/smileys/female-fighter.png b/retroshare-gui/src/gui/smileys/female-fighter.png new file mode 100644 index 000000000..188bd1bc5 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/female-fighter.png differ diff --git a/retroshare-gui/src/gui/smileys/film.png b/retroshare-gui/src/gui/smileys/film.png new file mode 100644 index 000000000..66acb127c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/film.png differ diff --git a/retroshare-gui/src/gui/smileys/fingers-crossed.png b/retroshare-gui/src/gui/smileys/fingers-crossed.png new file mode 100644 index 000000000..33576ff10 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/fingers-crossed.png differ diff --git a/retroshare-gui/src/gui/smileys/flag.png b/retroshare-gui/src/gui/smileys/flag.png new file mode 100644 index 000000000..aff86374b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/flag.png differ diff --git a/retroshare-gui/src/gui/smileys/foot-in-mouth.png b/retroshare-gui/src/gui/smileys/foot-in-mouth.png new file mode 100644 index 000000000..79aaa149b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/foot-in-mouth.png differ diff --git a/retroshare-gui/src/gui/smileys/freaked-out.png b/retroshare-gui/src/gui/smileys/freaked-out.png new file mode 100644 index 000000000..85ca5717c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/freaked-out.png differ diff --git a/retroshare-gui/src/gui/smileys/ghost.png b/retroshare-gui/src/gui/smileys/ghost.png new file mode 100644 index 000000000..a58efa52f Binary files /dev/null and b/retroshare-gui/src/gui/smileys/ghost.png differ diff --git a/retroshare-gui/src/gui/smileys/giggle.png b/retroshare-gui/src/gui/smileys/giggle.png new file mode 100644 index 000000000..906fb4ae4 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/giggle.png differ diff --git a/retroshare-gui/src/gui/smileys/girl.png b/retroshare-gui/src/gui/smileys/girl.png new file mode 100644 index 000000000..82c942820 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/girl.png differ diff --git a/retroshare-gui/src/gui/smileys/glasses-cool.png b/retroshare-gui/src/gui/smileys/glasses-cool.png new file mode 100644 index 000000000..855bc4916 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/glasses-cool.png differ diff --git a/retroshare-gui/src/gui/smileys/glasses-nerdy.png b/retroshare-gui/src/gui/smileys/glasses-nerdy.png new file mode 100644 index 000000000..3d794b2ad Binary files /dev/null and b/retroshare-gui/src/gui/smileys/glasses-nerdy.png differ diff --git a/retroshare-gui/src/gui/smileys/go-away.png b/retroshare-gui/src/gui/smileys/go-away.png new file mode 100644 index 000000000..24611ed0a Binary files /dev/null and b/retroshare-gui/src/gui/smileys/go-away.png differ diff --git a/retroshare-gui/src/gui/smileys/goat.png b/retroshare-gui/src/gui/smileys/goat.png new file mode 100644 index 000000000..f44db4a4b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/goat.png differ diff --git a/retroshare-gui/src/gui/smileys/good.png b/retroshare-gui/src/gui/smileys/good.png new file mode 100644 index 000000000..c32988d22 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/good.png differ diff --git a/retroshare-gui/src/gui/smileys/hammer.png b/retroshare-gui/src/gui/smileys/hammer.png new file mode 100644 index 000000000..53098ac0b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/hammer.png differ diff --git a/retroshare-gui/src/gui/smileys/handcuffs.png b/retroshare-gui/src/gui/smileys/handcuffs.png new file mode 100644 index 000000000..849ee912d Binary files /dev/null and b/retroshare-gui/src/gui/smileys/handcuffs.png differ diff --git a/retroshare-gui/src/gui/smileys/handshake.png b/retroshare-gui/src/gui/smileys/handshake.png new file mode 100644 index 000000000..a51da2d54 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/handshake.png differ diff --git a/retroshare-gui/src/gui/smileys/happy.png b/retroshare-gui/src/gui/smileys/happy.png new file mode 100644 index 000000000..8a2ba4925 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/happy.png differ diff --git a/retroshare-gui/src/gui/smileys/highfive.png b/retroshare-gui/src/gui/smileys/highfive.png new file mode 100644 index 000000000..01a715985 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/highfive.png differ diff --git a/retroshare-gui/src/gui/smileys/hot.png b/retroshare-gui/src/gui/smileys/hot.png new file mode 100644 index 000000000..1b7fbec14 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/hot.png differ diff --git a/retroshare-gui/src/gui/smileys/hug-left.png b/retroshare-gui/src/gui/smileys/hug-left.png new file mode 100644 index 000000000..fba82606d Binary files /dev/null and b/retroshare-gui/src/gui/smileys/hug-left.png differ diff --git a/retroshare-gui/src/gui/smileys/hug-right.png b/retroshare-gui/src/gui/smileys/hug-right.png new file mode 100644 index 000000000..6cd79205d Binary files /dev/null and b/retroshare-gui/src/gui/smileys/hug-right.png differ diff --git a/retroshare-gui/src/gui/smileys/hungry.png b/retroshare-gui/src/gui/smileys/hungry.png new file mode 100644 index 000000000..393482f13 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/hungry.png differ diff --git a/retroshare-gui/src/gui/smileys/hypnotized.png b/retroshare-gui/src/gui/smileys/hypnotized.png new file mode 100644 index 000000000..7b7488f49 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/hypnotized.png differ diff --git a/retroshare-gui/src/gui/smileys/in-love.png b/retroshare-gui/src/gui/smileys/in-love.png new file mode 100644 index 000000000..31aeea275 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/in-love.png differ diff --git a/retroshare-gui/src/gui/smileys/island.png b/retroshare-gui/src/gui/smileys/island.png new file mode 100644 index 000000000..5e63e1dc3 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/island.png differ diff --git a/retroshare-gui/src/gui/smileys/jump.png b/retroshare-gui/src/gui/smileys/jump.png new file mode 100644 index 000000000..d476c556f Binary files /dev/null and b/retroshare-gui/src/gui/smileys/jump.png differ diff --git a/retroshare-gui/src/gui/smileys/kiss.png b/retroshare-gui/src/gui/smileys/kiss.png new file mode 100644 index 000000000..697392fd9 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/kiss.png differ diff --git a/retroshare-gui/src/gui/smileys/kissed.png b/retroshare-gui/src/gui/smileys/kissed.png new file mode 100644 index 000000000..7049c4819 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/kissed.png differ diff --git a/retroshare-gui/src/gui/smileys/kissing.png b/retroshare-gui/src/gui/smileys/kissing.png new file mode 100644 index 000000000..31f8da999 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/kissing.png differ diff --git a/retroshare-gui/src/gui/smileys/knife.png b/retroshare-gui/src/gui/smileys/knife.png new file mode 100644 index 000000000..6db80de15 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/knife.png differ diff --git a/retroshare-gui/src/gui/smileys/lamp.png b/retroshare-gui/src/gui/smileys/lamp.png new file mode 100644 index 000000000..85b7968aa Binary files /dev/null and b/retroshare-gui/src/gui/smileys/lamp.png differ diff --git a/retroshare-gui/src/gui/smileys/lashes.png b/retroshare-gui/src/gui/smileys/lashes.png new file mode 100644 index 000000000..062d964d5 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/lashes.png differ diff --git a/retroshare-gui/src/gui/smileys/laugh.png b/retroshare-gui/src/gui/smileys/laugh.png new file mode 100644 index 000000000..306b2c592 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/laugh.png differ diff --git a/retroshare-gui/src/gui/smileys/liquor.png b/retroshare-gui/src/gui/smileys/liquor.png new file mode 100644 index 000000000..cd509c9f0 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/liquor.png differ diff --git a/retroshare-gui/src/gui/smileys/lol.png b/retroshare-gui/src/gui/smileys/lol.png new file mode 100644 index 000000000..74938a7e5 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/lol.png differ diff --git a/retroshare-gui/src/gui/smileys/loser.png b/retroshare-gui/src/gui/smileys/loser.png new file mode 100644 index 000000000..0cecd2fce Binary files /dev/null and b/retroshare-gui/src/gui/smileys/loser.png differ diff --git a/retroshare-gui/src/gui/smileys/love-over.png b/retroshare-gui/src/gui/smileys/love-over.png new file mode 100644 index 000000000..59c8a6ef6 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/love-over.png differ diff --git a/retroshare-gui/src/gui/smileys/love.png b/retroshare-gui/src/gui/smileys/love.png new file mode 100644 index 000000000..5171deed6 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/love.png differ diff --git a/retroshare-gui/src/gui/smileys/lying.png b/retroshare-gui/src/gui/smileys/lying.png new file mode 100644 index 000000000..c7e8be338 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/lying.png differ diff --git a/retroshare-gui/src/gui/smileys/mad-tongue.png b/retroshare-gui/src/gui/smileys/mad-tongue.png new file mode 100644 index 000000000..14cfd37c1 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/mad-tongue.png differ diff --git a/retroshare-gui/src/gui/smileys/mail.png b/retroshare-gui/src/gui/smileys/mail.png new file mode 100644 index 000000000..a1a365f0d Binary files /dev/null and b/retroshare-gui/src/gui/smileys/mail.png differ diff --git a/retroshare-gui/src/gui/smileys/male-fighter1.png b/retroshare-gui/src/gui/smileys/male-fighter1.png new file mode 100644 index 000000000..e3a4b1790 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/male-fighter1.png differ diff --git a/retroshare-gui/src/gui/smileys/male-fighter2.png b/retroshare-gui/src/gui/smileys/male-fighter2.png new file mode 100644 index 000000000..5feb9dd7c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/male-fighter2.png differ diff --git a/retroshare-gui/src/gui/smileys/mean.png b/retroshare-gui/src/gui/smileys/mean.png new file mode 100644 index 000000000..ac05d2128 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/mean.png differ diff --git a/retroshare-gui/src/gui/smileys/meeting.png b/retroshare-gui/src/gui/smileys/meeting.png new file mode 100644 index 000000000..02b4b1a67 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/meeting.png differ diff --git a/retroshare-gui/src/gui/smileys/messed.png b/retroshare-gui/src/gui/smileys/messed.png new file mode 100644 index 000000000..f76307f63 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/messed.png differ diff --git a/retroshare-gui/src/gui/smileys/mobile.png b/retroshare-gui/src/gui/smileys/mobile.png new file mode 100644 index 000000000..ac3469007 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/mobile.png differ diff --git a/retroshare-gui/src/gui/smileys/mohawk.png b/retroshare-gui/src/gui/smileys/mohawk.png new file mode 100644 index 000000000..60a9f0ffb Binary files /dev/null and b/retroshare-gui/src/gui/smileys/mohawk.png differ diff --git a/retroshare-gui/src/gui/smileys/moneymouth.png b/retroshare-gui/src/gui/smileys/moneymouth.png new file mode 100644 index 000000000..8fe1fa470 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/moneymouth.png differ diff --git a/retroshare-gui/src/gui/smileys/monkey.png b/retroshare-gui/src/gui/smileys/monkey.png new file mode 100644 index 000000000..dfc05f5b3 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/monkey.png differ diff --git a/retroshare-gui/src/gui/smileys/moon.png b/retroshare-gui/src/gui/smileys/moon.png new file mode 100644 index 000000000..0679d3dec Binary files /dev/null and b/retroshare-gui/src/gui/smileys/moon.png differ diff --git a/retroshare-gui/src/gui/smileys/mrgreen.png b/retroshare-gui/src/gui/smileys/mrgreen.png new file mode 100644 index 000000000..eda7038bb Binary files /dev/null and b/retroshare-gui/src/gui/smileys/mrgreen.png differ diff --git a/retroshare-gui/src/gui/smileys/music.png b/retroshare-gui/src/gui/smileys/music.png new file mode 100644 index 000000000..e9d87e1fe Binary files /dev/null and b/retroshare-gui/src/gui/smileys/music.png differ diff --git a/retroshare-gui/src/gui/smileys/musical-note.png b/retroshare-gui/src/gui/smileys/musical-note.png new file mode 100644 index 000000000..d003bc617 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/musical-note.png differ diff --git a/retroshare-gui/src/gui/smileys/nervous.png b/retroshare-gui/src/gui/smileys/nervous.png new file mode 100644 index 000000000..6888af8e0 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/nervous.png differ diff --git a/retroshare-gui/src/gui/smileys/neutral.png b/retroshare-gui/src/gui/smileys/neutral.png new file mode 100644 index 000000000..00691ac1e Binary files /dev/null and b/retroshare-gui/src/gui/smileys/neutral.png differ diff --git a/retroshare-gui/src/gui/smileys/on-the-phone.png b/retroshare-gui/src/gui/smileys/on-the-phone.png new file mode 100644 index 000000000..dd8155994 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/on-the-phone.png differ diff --git a/retroshare-gui/src/gui/smileys/party.png b/retroshare-gui/src/gui/smileys/party.png new file mode 100644 index 000000000..66828bd96 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/party.png differ diff --git a/retroshare-gui/src/gui/smileys/peace.png b/retroshare-gui/src/gui/smileys/peace.png new file mode 100644 index 000000000..ffeab9d95 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/peace.png differ diff --git a/retroshare-gui/src/gui/smileys/phone.png b/retroshare-gui/src/gui/smileys/phone.png new file mode 100644 index 000000000..a3c86155c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/phone.png differ diff --git a/retroshare-gui/src/gui/smileys/pig.png b/retroshare-gui/src/gui/smileys/pig.png new file mode 100644 index 000000000..1dc5c1ff7 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/pig.png differ diff --git a/retroshare-gui/src/gui/smileys/pill.png b/retroshare-gui/src/gui/smileys/pill.png new file mode 100644 index 000000000..04d326a2b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/pill.png differ diff --git a/retroshare-gui/src/gui/smileys/pirate.png b/retroshare-gui/src/gui/smileys/pirate.png new file mode 100644 index 000000000..ff807af9a Binary files /dev/null and b/retroshare-gui/src/gui/smileys/pirate.png differ diff --git a/retroshare-gui/src/gui/smileys/pissed-off.png b/retroshare-gui/src/gui/smileys/pissed-off.png new file mode 100644 index 000000000..224021002 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/pissed-off.png differ diff --git a/retroshare-gui/src/gui/smileys/pizza.png b/retroshare-gui/src/gui/smileys/pizza.png new file mode 100644 index 000000000..9b8da769b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/pizza.png differ diff --git a/retroshare-gui/src/gui/smileys/plate.png b/retroshare-gui/src/gui/smileys/plate.png new file mode 100644 index 000000000..0ed2c6fdb Binary files /dev/null and b/retroshare-gui/src/gui/smileys/plate.png differ diff --git a/retroshare-gui/src/gui/smileys/poop.png b/retroshare-gui/src/gui/smileys/poop.png new file mode 100644 index 000000000..3413bbaff Binary files /dev/null and b/retroshare-gui/src/gui/smileys/poop.png differ diff --git a/retroshare-gui/src/gui/smileys/pouty.png b/retroshare-gui/src/gui/smileys/pouty.png new file mode 100644 index 000000000..dc113eac5 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/pouty.png differ diff --git a/retroshare-gui/src/gui/smileys/pray.png b/retroshare-gui/src/gui/smileys/pray.png new file mode 100644 index 000000000..a7815aed9 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/pray.png differ diff --git a/retroshare-gui/src/gui/smileys/present.png b/retroshare-gui/src/gui/smileys/present.png new file mode 100644 index 000000000..ac43e38db Binary files /dev/null and b/retroshare-gui/src/gui/smileys/present.png differ diff --git a/retroshare-gui/src/gui/smileys/pumpkin.png b/retroshare-gui/src/gui/smileys/pumpkin.png new file mode 100644 index 000000000..389c2b0c8 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/pumpkin.png differ diff --git a/retroshare-gui/src/gui/smileys/qq.png b/retroshare-gui/src/gui/smileys/qq.png new file mode 100644 index 000000000..cf5a02a92 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/qq.png differ diff --git a/retroshare-gui/src/gui/smileys/question.png b/retroshare-gui/src/gui/smileys/question.png new file mode 100644 index 000000000..c4bc2e104 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/question.png differ diff --git a/retroshare-gui/src/gui/smileys/quiet.png b/retroshare-gui/src/gui/smileys/quiet.png new file mode 100644 index 000000000..371574fa4 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/quiet.png differ diff --git a/retroshare-gui/src/gui/smileys/rain.png b/retroshare-gui/src/gui/smileys/rain.png new file mode 100644 index 000000000..6954d826a Binary files /dev/null and b/retroshare-gui/src/gui/smileys/rain.png differ diff --git a/retroshare-gui/src/gui/smileys/rainbow.png b/retroshare-gui/src/gui/smileys/rainbow.png new file mode 100644 index 000000000..344fdb5dc Binary files /dev/null and b/retroshare-gui/src/gui/smileys/rainbow.png differ diff --git a/retroshare-gui/src/gui/smileys/rose-dead.png b/retroshare-gui/src/gui/smileys/rose-dead.png new file mode 100644 index 000000000..927cf90eb Binary files /dev/null and b/retroshare-gui/src/gui/smileys/rose-dead.png differ diff --git a/retroshare-gui/src/gui/smileys/rose.png b/retroshare-gui/src/gui/smileys/rose.png new file mode 100644 index 000000000..33cfb1378 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/rose.png differ diff --git a/retroshare-gui/src/gui/smileys/rotfl.png b/retroshare-gui/src/gui/smileys/rotfl.png new file mode 100644 index 000000000..f0c4879ef Binary files /dev/null and b/retroshare-gui/src/gui/smileys/rotfl.png differ diff --git a/retroshare-gui/src/gui/smileys/sad.png b/retroshare-gui/src/gui/smileys/sad.png new file mode 100644 index 000000000..bf20e9df8 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/sad.png differ diff --git a/retroshare-gui/src/gui/smileys/sarcastic.png b/retroshare-gui/src/gui/smileys/sarcastic.png new file mode 100644 index 000000000..eef0e8e96 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/sarcastic.png differ diff --git a/retroshare-gui/src/gui/smileys/search.png b/retroshare-gui/src/gui/smileys/search.png new file mode 100644 index 000000000..d61cebb36 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/search.png differ diff --git a/retroshare-gui/src/gui/smileys/secret.png b/retroshare-gui/src/gui/smileys/secret.png new file mode 100644 index 000000000..64fc95ef3 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/secret.png differ diff --git a/retroshare-gui/src/gui/smileys/shame.png b/retroshare-gui/src/gui/smileys/shame.png new file mode 100644 index 000000000..a4b054798 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/shame.png differ diff --git a/retroshare-gui/src/gui/smileys/sheep.png b/retroshare-gui/src/gui/smileys/sheep.png new file mode 100644 index 000000000..dc3feaa45 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/sheep.png differ diff --git a/retroshare-gui/src/gui/smileys/shocked.png b/retroshare-gui/src/gui/smileys/shocked.png new file mode 100644 index 000000000..0e7438e9e Binary files /dev/null and b/retroshare-gui/src/gui/smileys/shocked.png differ diff --git a/retroshare-gui/src/gui/smileys/shout.png b/retroshare-gui/src/gui/smileys/shout.png new file mode 100644 index 000000000..1fe2fa9db Binary files /dev/null and b/retroshare-gui/src/gui/smileys/shout.png differ diff --git a/retroshare-gui/src/gui/smileys/shut-mouth.png b/retroshare-gui/src/gui/smileys/shut-mouth.png new file mode 100644 index 000000000..5037ad681 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/shut-mouth.png differ diff --git a/retroshare-gui/src/gui/smileys/sick.png b/retroshare-gui/src/gui/smileys/sick.png new file mode 100644 index 000000000..94e4e598c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/sick.png differ diff --git a/retroshare-gui/src/gui/smileys/sidefrown.png b/retroshare-gui/src/gui/smileys/sidefrown.png new file mode 100644 index 000000000..2d4e42206 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/sidefrown.png differ diff --git a/retroshare-gui/src/gui/smileys/silly.png b/retroshare-gui/src/gui/smileys/silly.png new file mode 100644 index 000000000..950400c1b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/silly.png differ diff --git a/retroshare-gui/src/gui/smileys/sinister.png b/retroshare-gui/src/gui/smileys/sinister.png new file mode 100644 index 000000000..f26a3a617 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/sinister.png differ diff --git a/retroshare-gui/src/gui/smileys/skeleton.png b/retroshare-gui/src/gui/smileys/skeleton.png new file mode 100644 index 000000000..f59540d58 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/skeleton.png differ diff --git a/retroshare-gui/src/gui/smileys/skywalker.png b/retroshare-gui/src/gui/smileys/skywalker.png new file mode 100644 index 000000000..d6365f1e5 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/skywalker.png differ diff --git a/retroshare-gui/src/gui/smileys/sleeping.png b/retroshare-gui/src/gui/smileys/sleeping.png new file mode 100644 index 000000000..e3bfe411b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/sleeping.png differ diff --git a/retroshare-gui/src/gui/smileys/sleepy.png b/retroshare-gui/src/gui/smileys/sleepy.png new file mode 100644 index 000000000..2c3e78fd8 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/sleepy.png differ diff --git a/retroshare-gui/src/gui/smileys/smile.png b/retroshare-gui/src/gui/smileys/smile.png new file mode 100644 index 000000000..a113e35cf Binary files /dev/null and b/retroshare-gui/src/gui/smileys/smile.png differ diff --git a/retroshare-gui/src/gui/smileys/smirk.png b/retroshare-gui/src/gui/smileys/smirk.png new file mode 100644 index 000000000..c458e1a60 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/smirk.png differ diff --git a/retroshare-gui/src/gui/smileys/snail.png b/retroshare-gui/src/gui/smileys/snail.png new file mode 100644 index 000000000..2e8ac91ba Binary files /dev/null and b/retroshare-gui/src/gui/smileys/snail.png differ diff --git a/retroshare-gui/src/gui/smileys/snicker.png b/retroshare-gui/src/gui/smileys/snicker.png new file mode 100644 index 000000000..a40c46261 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/snicker.png differ diff --git a/retroshare-gui/src/gui/smileys/snowman.png b/retroshare-gui/src/gui/smileys/snowman.png new file mode 100644 index 000000000..9fec7d7d5 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/snowman.png differ diff --git a/retroshare-gui/src/gui/smileys/soccerball.png b/retroshare-gui/src/gui/smileys/soccerball.png new file mode 100644 index 000000000..358a157b3 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/soccerball.png differ diff --git a/retroshare-gui/src/gui/smileys/soldier.png b/retroshare-gui/src/gui/smileys/soldier.png new file mode 100644 index 000000000..04435a9e3 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/soldier.png differ diff --git a/retroshare-gui/src/gui/smileys/star.png b/retroshare-gui/src/gui/smileys/star.png new file mode 100644 index 000000000..cc92a69a7 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/star.png differ diff --git a/retroshare-gui/src/gui/smileys/starving.png b/retroshare-gui/src/gui/smileys/starving.png new file mode 100644 index 000000000..4eb3b62d5 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/starving.png differ diff --git a/retroshare-gui/src/gui/smileys/stop.png b/retroshare-gui/src/gui/smileys/stop.png new file mode 100644 index 000000000..469eaa0e8 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/stop.png differ diff --git a/retroshare-gui/src/gui/smileys/stressed.png b/retroshare-gui/src/gui/smileys/stressed.png new file mode 100644 index 000000000..8168455af Binary files /dev/null and b/retroshare-gui/src/gui/smileys/stressed.png differ diff --git a/retroshare-gui/src/gui/smileys/struggle.png b/retroshare-gui/src/gui/smileys/struggle.png new file mode 100644 index 000000000..f3fc010d7 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/struggle.png differ diff --git a/retroshare-gui/src/gui/smileys/sun.png b/retroshare-gui/src/gui/smileys/sun.png new file mode 100644 index 000000000..43a61280c Binary files /dev/null and b/retroshare-gui/src/gui/smileys/sun.png differ diff --git a/retroshare-gui/src/gui/smileys/surprised.png b/retroshare-gui/src/gui/smileys/surprised.png new file mode 100644 index 000000000..19a7b33a9 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/surprised.png differ diff --git a/retroshare-gui/src/gui/smileys/talktohand.png b/retroshare-gui/src/gui/smileys/talktohand.png new file mode 100644 index 000000000..721895515 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/talktohand.png differ diff --git a/retroshare-gui/src/gui/smileys/teeth.png b/retroshare-gui/src/gui/smileys/teeth.png new file mode 100644 index 000000000..42ae1d558 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/teeth.png differ diff --git a/retroshare-gui/src/gui/smileys/terror.png b/retroshare-gui/src/gui/smileys/terror.png new file mode 100644 index 000000000..91c07d660 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/terror.png differ diff --git a/retroshare-gui/src/gui/smileys/theme b/retroshare-gui/src/gui/smileys/theme new file mode 100644 index 000000000..887d11da5 --- /dev/null +++ b/retroshare-gui/src/gui/smileys/theme @@ -0,0 +1,497 @@ +Name=Default +Description=Pidgin smileys +Icon=wink.png +Author=Hylke Bons + + +# Default smileys +[default] +happy.png :) :-) +excited.png :-D :-d :D :d +sad.png :-( :( +wink.png ;-) ;) +tongue.png :P :p :-P :-p +shocked.png =-O =-o +kiss.png :-* +glasses-cool.png 8-) +embarrassed.png :-[ +crying.png :'( :'-( +thinking.png :-/ :-\\ +angel.png O:-) o:-) +shut-mouth.png :-X +moneymouth.png :-$ +foot-in-mouth.png :-! +shout.png >:o >:O +! skywalker.png C:-) c:-) C:) c:) +! monkey.png :-(|) :(|) 8-|) +! cyclops.png O-) o-) + + +[XMPP] +# Following XEP-0038 + GTalk + our default set, in default set order +# The GTalk strings come from ticket #3307. +happy.png :) :-) =) +excited.png :-D :-d :D :d =D =d +sad.png :-( :( +wink.png ;-) ;) ;^) +tongue.png :P :p :-P :-p +shocked.png =-O =-o :-O :-o +kiss.png :kiss: :-* +glasses-cool.png 8-) B-) +embarrassed.png :-[ +crying.png :'-( :'( +thinking.png :-/ :-\\ +angel.png O:-) o:-) +shut-mouth.png :-X +moneymouth.png :-$ +foot-in-mouth.png :-! +shout.png >:o >:O + +# Following XEP-0038 + GTalk +angry.png >:-( >:( X-( x-( +good.png :yes: +bad.png :no: +stop.png :wait: +rose.png @->-- :rose: +phone.png :telephone: +mail.png :email: +lamp.png :jabber: +cake.png :cake: +in_love.png :heart: :love: <3 +love-over.png :brokenheart: +musical-note.png :music: +beer.png :beer: +coffee.png :coffee: +coins.png :money: +moon.png :moon: +sun.png :sun: +star.png :star: + +# Others +neutral.png :| :-| +victory.png \\m/ + +# Hidden icons from the default set. +! skywalker.png C:-) c:-) C:) c:) +! monkey.png :-(|) :(|) 8-|) +! cyclops.png O-) o-) + + +# Following AIM 6.1 +[AIM] +happy.png :-) :) +wink.png ;-) ;) +sad.png :-( :( +tongue.png :P :p :-P :-p +shocked.png =-O +kiss.png :-* +shout.png >:o +excited.png :-D :D +moneymouth.png :-$ +foot-in-mouth.png :-! +embarrassed.png :-[ +angel.png O:-) +thinking.png :-\\ :-/ +crying.png :'( +shut-mouth.png :-X +glasses-cool.png 8-) +! skywalker.png C:-) c:-) C:) c:) +! monkey.png :-(|) :(|) 8-|) +! cyclops.png O-) o-) + + +# Following Windows Live Messenger 8.1 +[MSN] +happy.png :) :-) +excited.png :D :d :-D :-d +wink.png ;) ;-) +shocked.png :-O :-o :O :o +tongue.png :-P :P :-p :p +glasses-cool.png (H) (h) +angry.png :@ :-@ +embarrassed.png :$ :-$ +confused.png :S :s :-S :-s +sad.png :( :-( +crying.png :'( +neutral.png :| :-| +devil.png (6) +angel.png (A) (a) +in_love.png (L) (l) +love-over.png (U) (u) +msn.png (M) (m) +cat.png (@) +dog.png (&) +moon.png (S) +star.png (*) +film.png (~) +musical-note.png (8) +mail.png (E) (e) +rose.png (F) (f) +rose-dead.png (W) (w) +clock.png (O) (o) +kiss.png (K) (k) +present.png (G) (g) +cake.png (^) +camera.png (P) (p) +lamp.png (I) (i) +coffee.png (C) (c) +phone.png (T) (t) +hug-left.png ({) +hug-right.png (}) +beer.png (B) (b) +drink.png (D) (d) +boy.png (Z) (z) +girl.png (X) (x) +good.png (Y) (y) +bad.png (N) (n) +vampire.png :[ :-[ +goat.png (nah) +sun.png (#) +rainbow.png (R) (r) +quiet.png :-# +teeth.png 8o| +glasses-nerdy.png 8-| +sarcastic.png ^o) +secret.png :-* +sick.png +o( +snail.png (sn) +turtle.png (tu) +plate.png (pl) +bowl.png (||) +pizza.png (pi) +soccerball.png (so) +car.png (au) +airplane.png (ap) +umbrella.png (um) +island.png (ip) +computer.png (co) +mobile.png (mp) +brb.png (brb) +rain.png (st) +highfive.png (h5) +coins.png (mo) +sheep.png (bah) +dont-know.png :^) +thinking.png *-) +thunder.png (li) +party.png <:o) +eyeroll.png 8-) +sleepy.png |-) +bunny.png ('.') +! skywalker.png C:-) c:-) C:) c:) +! monkey.png :-(|) :(|) 8-|) +! cyclops.png O-) o-) + +# Hidden MSN emotes +cigarette.png (ci) (CI) +handcuffs.png (%) +console.png (xx) (XX) +fingers-crossed.png (yn) (YN) + + +# Following QQ 2006 +[QQ] +shocked.png /:O /jy /surprised +curl-lip.png /:~ /pz /curl_lip +desire.png /:* /se /desire +dazed.png /:| /dazed +party.png /8-) /dy /revel +crying.png /:< /ll /cry +bashful.png /:$ /hx /bashful +shut-mouth.png /:X /bz /shut_mouth +sleeping.png /:Z /shui /sleep +weep.png /:'( /dk /weep +embarrassed.png /:-| /gg /embarassed +pissed-off.png /:@ /fn /pissed_off +act-up.png /:P /tp /act_up +excited.png /:D /cy /toothy_smile +happy.png /:) /wx /small_smile +sad.png /:( /ng /sad +glasses-cool.png /:+ /kuk /cool +doctor.png /:# /feid /SARS +silly.png /:Q /zk /crazy +sick.png /:T /tu /vomit +snicker.png /;p /tx /titter +cute.png /;-D /ka /cute +disdain.png /;d /by /disdain +arrogant.png /;o /am /arrogant +starving.png /:g /jie /starving +sleepy.png /|-) /kun /sleepy +terror.png /:! /jk /terror +hot.png /:L /sweat +smirk.png /:> /hanx /smirk +soldier.png /:; /db /soldier +struggle.png /;f /fendou /struggle +curse.png /:-S /zhm /curse +question.png /? /yiw /question +quiet.png /;x /xu /shh +hypnotized.png /;@ /yun /dizzy +excruciating.png /:8 /zhem /excrutiating +freaked-out.png /;! /shuai /freaked_out +skeleton.png /!!! /kl /skeleton +hammer.png /xx /qiao /hammer +bye.png /bye /zj /bye +go-away.png /go /shan /go +afraid.png /shake /fad /shake +amorous.png /love /aiq /love +jump.png /jump /tiao /jump +search.png /find /zhao /search +lashes.png /& /mm /beautiful_eyebrows +pig.png /pig /zt /pig +cat.png /cat /mm /cat +dog.png /dog /xg /dog +hug-left.png /hug /yb /hug +coins.png /$ /qianc /money +lamp.png /! /dp /lightbulb +bowl.png /cup /bei /cup +cake.png /cake /dg /cake +thunder.png /li /shd /lightning +bomb.png /bome /zhd /bomb +knife.png /kn /dao /knife +soccerball.png /footb /zq /soccer +musical-note.png /music /yy /music +poop.png /shit /bb /shit +coffee.png /coffee /kf /coffee +hungry.png /eat /fan /eat +pill.png /pill /yw /pill +rose.png /rose /mg /rose +wilt.png /fade /dx /wilt +kiss.png /kiss /wen /kiss +in_love.png /heart /xin /heart +love-over.png /break /xs /broken_heart +meeting.png /meeting /hy /meeting +present.png /gift /lw /gift +phone.png /phone /dh /phone +clock.png /time /sj /time +mail.png /email /yj /email +tv.png /TV /ds /TV +sun.png /sun /ty /sun +moon.png /moon /yl /moon +good.png /strong /qiang /thumbs_up +bad.png /weak /ruo /thumbs_down +handshake.png /share /ws /handshake +victory.png /v /shl /victory +beauty.png / /mn /beauty +qq.png / /qz /qq +blowkiss.png / /fw /blow_kiss +angry.png / /oh /angry +liquor.png / /bj /baijiu +can.png / /qsh /soda +watermelon.png / /xigua /watermelon +rain.png / /xy /rain +cloudy.png /<~> /duoy /cloudy +snowman.png / /xr /snowman +star.png /<*> /xixing /star +girl.png /<00> /nv /woman +boy.png /<11> /nan /man +! skywalker.png C:-) c:-) C:) c:) +! monkey.png :-(|) :(|) 8-|) +! cyclops.png O-) o-) + + +# Following ICQ 6.0 +[ICQ] +happy.png :-) :) +neutral.png :-$ +sad.png :-( :( +shocked.png =-O +wink.png ;-) ;) +tongue.png :-P :P :-p :p +music.png [:-} +laugh.png *JOKINGLY* +sleeping.png *TIRED* +crying.png :'( :'-( +sick.png :-! +kissed.png *KISSED* +stop.png *STOP* +kiss.png :-{} :-* +kissing.png *KISSING* +victory.png *YAHOO* +silly.png %) +embarrassed.png :-[ +devil.png ]:-> +angel.png O:-) +rose.png @}->-- +shut-mouth.png :-X :X :-x :x +bomb.png @= +thinking.png :-\\ :-/ +good.png *THUMBS\ UP* +shout.png >:o >:O :-@ +beer.png *DRINK* +excited.png :-D :D +glasses-cool.png 8-) +amorous.png *IN\ LOVE* +! skywalker.png C:-) c:-) C:) c:) +! monkey.png :-(|) :(|) 8-|) +! cyclops.png O-) o-) + + +# Following Yahoo! Messenger 8.1 +[Yahoo] +happy.png :) :-) +question.png :-/ :-\\ +shocked.png :-O :O :-o :o +devil.png >:) +angel.png O:-) o:-) 0:-) +sick.png :-& +sleepy.png (:| +hypnotized.png @-) +on-the-phone.png :)] +sad.png :( :-( +amorous.png :x :-x :X :-X +angry.png X-( x-( X( x( +crying.png :(( +glasses-nerdy.png :-B :-b +quiet.png :-$ +drool.png =P~ =p~ +lying.png :^O :^o +call-me.png :-c +wink.png ;) ;-) +embarrassed.png :"> +mean.png :-> :> +laugh.png :)) :-)) +bye.png =; +arrogant.png [-( +thinking.png :-? +waiting.png :-w :-W +at-wits-end.png ~x( ~X( +excited.png :D :-D :d :-d +tongue.png :-P :P :-p :p +glasses-cool.png B-) b-) +neutral.png :| :-| +sleeping.png I-) i-) |-) +clown.png :o) :O) +doh.png #-o #-O +weep.png :-< +go-away.png :-h +lashes.png ;;) +kiss.png :-* :* +confused.png :-S :-s +sarcastic.png /:) +eyeroll.png 8-| +silly.png 8-} +clap.png =D> =d> +mad-tongue.png >:P >:p +time-out.png :-t :-T +hug-left.png >:D< >:d< +love-over.png =(( +hot.png #:-S #:-s +rotfl.png =)) :-j :-J +loser.png L-) l-) +party.png <:-P <:-p +nervous.png :-SS :-Ss :-sS :-ss +cowboy.png <):) +desire.png 8-> +! skywalker.png C:-) c:-) C:) c:) +! monkey.png :-(|) :(|) 8-|) +! cyclops.png O-) o-) + +# Hidden Yahoo emotes +alien.png =:) >-) +beat-up.png b-( B-( +chicken.png ~:> +coffee.png ~o) ~O) +cow.png 3:-O 3:-o +dance.png \\:D/ \\:d/ +rose.png @};- +dont-know.png :-L :-l +skeleton.png 8-X 8-x +lamp.png *-:) +monkey.png :(|) +coins.png $-) +peace.png :)>- +pig.png :@) +pray.png [-o< [-O< +pumpkin.png (~~) +shame.png [-X [-x +flag.png **== +clover.png %%- +musical-note.png :-" +giggle.png ;)) +worship.png ^:)^ +star.png (*) +waving.png >:/ +talktohand.png :-@ + +# Only available after activating the Yahoo! Fighter IMVironment +male-fighter1.png o-> O-> +male-fighter2.png o=> O=> +female-fighter.png o-+ O-+ +yin-yang.png (%) + + +# Following MySpaceIM Beta 1.0.697.0 +[MySpaceIM] +excited.png :D :-D +devil.png }:) +confused.png :Z +glasses-nerdy.png B) +bulgy-eyes.png %) +freaked-out.png :E +smile.png :) :-) +amorous.png :X +laugh.png :)) +mohawk.png -: +mad-tongue.png X( +messed.png X) +glasses-nerdy.png Q) +doh.png :G +pirate.png P) +shocked.png :O +sidefrown.png :{ +sinister.png :B +smirk.png :, +neutral.png :| +tongue.png :P :p +pissed-off.png B| +wink.png ;-) ;) +sad.png :[ +kiss.png :x +! skywalker.png C:-) c:-) C:) c:) +! monkey.png :-(|) :(|) 8-|) +! cyclops.png O-) o-) + + +# MXit standard emoticons +[MXit] +happy.png :-) :) +sad.png :-( :( +wink.png ;-) ;) +excited.png :-D :D :-> :> +neutral.png :-| :| +shocked.png :-O :O +tongue.png :-P :P +embarrassed.png :-$ :$ +glasses-cool.png 8-) +in_love.png (H) +rose.png (F) +### Added in v3.0 +boy.png (m) +girl.png (f) +star.png (*) +chilli.png (c) +kiss.png (x) +lamp.png (i) +pissed-off.png :e :-e +shut-mouth.png :-x :x +thunder.png (z) +coffee.png (U) +mrgreen.png (G) +### Added in v5.0 +sick.png :o( +excruciating.png :-{ :{ +amorous.png :-} :} +eyeroll.png 8-o 8o +crying.png :'( +thinking.png :-? :? +drool.png :-~ :~ +sleeping.png :-z :z +lying.png :L) +glasses-nerdy.png 8-| 8| +pirate.png P-) +### Added in v5.9.7 +bored.png :-[ :[ +cold.png :-< :< +confused.png :-, :, +hungry.png :-C :C +stressed.png :-s :s diff --git a/retroshare-gui/src/gui/smileys/thinking.png b/retroshare-gui/src/gui/smileys/thinking.png new file mode 100644 index 000000000..5567953a6 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/thinking.png differ diff --git a/retroshare-gui/src/gui/smileys/thunder.png b/retroshare-gui/src/gui/smileys/thunder.png new file mode 100644 index 000000000..fef2007b8 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/thunder.png differ diff --git a/retroshare-gui/src/gui/smileys/time-out.png b/retroshare-gui/src/gui/smileys/time-out.png new file mode 100644 index 000000000..7b8ff4d62 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/time-out.png differ diff --git a/retroshare-gui/src/gui/smileys/tongue.png b/retroshare-gui/src/gui/smileys/tongue.png new file mode 100644 index 000000000..029f0a566 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/tongue.png differ diff --git a/retroshare-gui/src/gui/smileys/turtle.png b/retroshare-gui/src/gui/smileys/turtle.png new file mode 100644 index 000000000..a95b64f03 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/turtle.png differ diff --git a/retroshare-gui/src/gui/smileys/tv.png b/retroshare-gui/src/gui/smileys/tv.png new file mode 100644 index 000000000..30b896986 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/tv.png differ diff --git a/retroshare-gui/src/gui/smileys/umbrella.png b/retroshare-gui/src/gui/smileys/umbrella.png new file mode 100644 index 000000000..8c5a8518f Binary files /dev/null and b/retroshare-gui/src/gui/smileys/umbrella.png differ diff --git a/retroshare-gui/src/gui/smileys/vampire.png b/retroshare-gui/src/gui/smileys/vampire.png new file mode 100644 index 000000000..6758b35aa Binary files /dev/null and b/retroshare-gui/src/gui/smileys/vampire.png differ diff --git a/retroshare-gui/src/gui/smileys/victory.png b/retroshare-gui/src/gui/smileys/victory.png new file mode 100644 index 000000000..b35692fa1 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/victory.png differ diff --git a/retroshare-gui/src/gui/smileys/waiting.png b/retroshare-gui/src/gui/smileys/waiting.png new file mode 100644 index 000000000..0f6baeea7 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/waiting.png differ diff --git a/retroshare-gui/src/gui/smileys/watermelon.png b/retroshare-gui/src/gui/smileys/watermelon.png new file mode 100644 index 000000000..4a201d523 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/watermelon.png differ diff --git a/retroshare-gui/src/gui/smileys/waving.png b/retroshare-gui/src/gui/smileys/waving.png new file mode 100644 index 000000000..e309c3e34 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/waving.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-clear-night.png b/retroshare-gui/src/gui/smileys/weather-clear-night.png new file mode 100644 index 000000000..aa2714cbe Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-clear-night.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-clear.png b/retroshare-gui/src/gui/smileys/weather-clear.png new file mode 100644 index 000000000..c84e8d377 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-clear.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-few-clouds-night.png b/retroshare-gui/src/gui/smileys/weather-few-clouds-night.png new file mode 100644 index 000000000..62e21d7ff Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-few-clouds-night.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-few-clouds.png b/retroshare-gui/src/gui/smileys/weather-few-clouds.png new file mode 100644 index 000000000..8c14e0d71 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-few-clouds.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-overcast.png b/retroshare-gui/src/gui/smileys/weather-overcast.png new file mode 100644 index 000000000..cc22e4ce4 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-overcast.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-severe-alert.png b/retroshare-gui/src/gui/smileys/weather-severe-alert.png new file mode 100644 index 000000000..fb75808bb Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-severe-alert.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-showers-scattered.png b/retroshare-gui/src/gui/smileys/weather-showers-scattered.png new file mode 100644 index 000000000..6e85a7bc9 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-showers-scattered.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-showers.png b/retroshare-gui/src/gui/smileys/weather-showers.png new file mode 100644 index 000000000..00743484e Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-showers.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-snow.png b/retroshare-gui/src/gui/smileys/weather-snow.png new file mode 100644 index 000000000..fef6e4dde Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-snow.png differ diff --git a/retroshare-gui/src/gui/smileys/weather-storm.png b/retroshare-gui/src/gui/smileys/weather-storm.png new file mode 100644 index 000000000..8a7db962b Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weather-storm.png differ diff --git a/retroshare-gui/src/gui/smileys/weep.png b/retroshare-gui/src/gui/smileys/weep.png new file mode 100644 index 000000000..85c87319f Binary files /dev/null and b/retroshare-gui/src/gui/smileys/weep.png differ diff --git a/retroshare-gui/src/gui/smileys/wilt.png b/retroshare-gui/src/gui/smileys/wilt.png new file mode 100644 index 000000000..fd8912904 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/wilt.png differ diff --git a/retroshare-gui/src/gui/smileys/wink.png b/retroshare-gui/src/gui/smileys/wink.png new file mode 100644 index 000000000..6316618a9 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/wink.png differ diff --git a/retroshare-gui/src/gui/smileys/worship.png b/retroshare-gui/src/gui/smileys/worship.png new file mode 100644 index 000000000..2a3010df8 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/worship.png differ diff --git a/retroshare-gui/src/gui/smileys/yin-yang.png b/retroshare-gui/src/gui/smileys/yin-yang.png new file mode 100644 index 000000000..4d3f970a7 Binary files /dev/null and b/retroshare-gui/src/gui/smileys/yin-yang.png differ diff --git a/retroshare-gui/src/gui/statusbar/dhtstatus.cpp b/retroshare-gui/src/gui/statusbar/dhtstatus.cpp new file mode 100644 index 000000000..2c508b194 --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/dhtstatus.cpp @@ -0,0 +1,101 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include "dhtstatus.h" + +#include +#include +#include +#include + +#include "retroshare/rsiface.h" +#include "retroshare/rspeers.h" + +#include "util/misc.h" + +#include +#include + +DHTStatus::DHTStatus(QWidget *parent) + : QWidget(parent) +{ + QHBoxLayout *hbox = new QHBoxLayout(); + hbox->setMargin(0); + hbox->setSpacing(6); + + statusDHT = new QLabel("" + tr("DHT") + ":", this ); + hbox->addWidget(statusDHT); + + dhtstatusLabel = new QLabel( this ); + dhtstatusLabel->setPixmap(QPixmap(":/images/grayled.png")); + hbox->addWidget(dhtstatusLabel); + + spaceLabel = new QLabel( "|", this ); + spaceLabel->setVisible(false); + hbox->addWidget(spaceLabel); + + dhtnetworkLabel = new QLabel( this ); + dhtnetworkLabel->setVisible(false); + dhtnetworkLabel->setPixmap(QPixmap(":/images/dht16.png")); + hbox->addWidget(dhtnetworkLabel); + + dhtnetworksizeLabel = new QLabel( "0 (0) ",this ); + dhtnetworksizeLabel->setVisible(false); + hbox->addWidget(dhtnetworksizeLabel); + + hbox->addSpacing(2); + + setLayout( hbox ); +} + +void DHTStatus::getDHTStatus() +{ + rsiface->lockData(); /* Lock Interface */ + + /* now the extra bit .... switch on check boxes */ + const RsConfig &config = rsiface->getConfig(); + + if (config.netDhtOk) + { + dhtstatusLabel->setPixmap(QPixmap(":/images/greenled.png")); + dhtstatusLabel->setToolTip(tr("DHT On")); + + spaceLabel->setVisible(true); + dhtnetworkLabel->setVisible(true); + dhtnetworksizeLabel->setVisible(true); + + dhtnetworksizeLabel->setText(QString("%1 (%2)").arg(misc::userFriendlyUnit(config.netDhtRsNetSize, 1)).arg(misc::userFriendlyUnit(config.netDhtNetSize, 1))); + dhtnetworksizeLabel->setToolTip(tr("RetroShare users in DHT (Total DHT users)") ); + } + else + { + dhtstatusLabel->setPixmap(QPixmap(":/images/redled.png")); + dhtstatusLabel->setToolTip(tr("DHT Off")); + + spaceLabel->setVisible(false); + dhtnetworkLabel->setVisible(false); + dhtnetworksizeLabel->setVisible(false); + + dhtnetworksizeLabel->setText(""); + dhtnetworksizeLabel->setToolTip(""); + } + + rsiface->unlockData(); /* UnLock Interface */ +} diff --git a/retroshare-gui/src/gui/statusbar/dhtstatus.h b/retroshare-gui/src/gui/statusbar/dhtstatus.h new file mode 100644 index 000000000..8ea26d45c --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/dhtstatus.h @@ -0,0 +1,41 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#ifndef DHTSTATUS_H +#define DHTSTATUS_H + +#include + +class QLabel; + +class DHTStatus : public QWidget +{ + Q_OBJECT +public: + DHTStatus(QWidget *parent = 0); + + void getDHTStatus( ); + +private: + QLabel *dhtstatusLabel, *statusDHT, *dhtnetworkLabel, *dhtnetworksizeLabel, *spaceLabel; + +}; + +#endif diff --git a/retroshare-gui/src/gui/statusbar/discstatus.cpp b/retroshare-gui/src/gui/statusbar/discstatus.cpp new file mode 100644 index 000000000..a64528c0b --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/discstatus.cpp @@ -0,0 +1,78 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "discstatus.h" +#include "gui/settings/rsharesettings.h" + +#include + +DiscStatus::DiscStatus(QWidget *parent) + : QWidget(parent) +{ + hide (); // show only, when pending operations are available + + QHBoxLayout *hbox = new QHBoxLayout(this); + hbox->setMargin(0); + hbox->setSpacing(6); + + QLabel *iconLabel = new QLabel(this); + iconLabel->setPixmap(QPixmap(":/images/uploads.png")); + iconLabel->setToolTip(tr("Waiting outgoing discovery operations")); + hbox->addWidget(iconLabel); + + sendLabel = new QLabel("0", this); + sendLabel->setToolTip(iconLabel->toolTip()); + hbox->addWidget(sendLabel); + + iconLabel = new QLabel(this); + iconLabel->setPixmap(QPixmap(":/images/download.png")); + iconLabel->setToolTip(tr("Waiting incoming discovery operations")); + hbox->addWidget(iconLabel); + + recvLabel = new QLabel("0", this); + recvLabel->setToolTip(iconLabel->toolTip()); + hbox->addWidget(recvLabel); + + hbox->addSpacing(2); + + setLayout(hbox); +} + +void DiscStatus::update() +{ + if (rsDisc == NULL || (Settings->getStatusBarFlags() & STATUSBAR_DISC) == 0) { + hide(); + return; + } + + unsigned int sendCount = 0; + unsigned int recvCount = 0; + + rsDisc->getWaitingDiscCount(&sendCount, &recvCount); + + sendLabel->setText(QString::number(sendCount)); + recvLabel->setText(QString::number(recvCount)); + + setVisible(sendCount || recvCount); +} diff --git a/retroshare-gui/src/gui/statusbar/discstatus.h b/retroshare-gui/src/gui/statusbar/discstatus.h new file mode 100644 index 000000000..cfe8eeccb --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/discstatus.h @@ -0,0 +1,43 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef DISCSTATUS_H +#define DISCSTATUS_H + +#include + +class QLabel; + +class DiscStatus : public QWidget +{ + Q_OBJECT + +public: + DiscStatus(QWidget *parent = 0); + + void update(); + +private: + QLabel *sendLabel; + QLabel *recvLabel; +}; + +#endif diff --git a/retroshare-gui/src/gui/statusbar/hashingstatus.cpp b/retroshare-gui/src/gui/statusbar/hashingstatus.cpp new file mode 100644 index 000000000..d388e3c79 --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/hashingstatus.cpp @@ -0,0 +1,99 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include "hashingstatus.h" + +#include "gui/notifyqt.h" + +class StatusLabel : public QLabel +{ +public: + StatusLabel(QLayout *layout, int diffWidth, QWidget *parent = NULL, Qt::WindowFlags f = 0) : QLabel(parent, f) + { + m_layout = layout; + m_diffWidth = diffWidth; + } + + virtual QSize minimumSizeHint() const + { + const QSize sizeHint = QLabel::minimumSizeHint(); + + // do not resize the layout + return QSize(qMin(sizeHint.width(), m_layout->geometry().width() - m_diffWidth), sizeHint.height()); + } + +private: + QLayout *m_layout; + int m_diffWidth; +}; + +HashingStatus::HashingStatus(QWidget *parent) + : QWidget(parent) +{ + QHBoxLayout *hbox = new QHBoxLayout(this); + hbox->setMargin(0); + hbox->setSpacing(6); + + movie = new QMovie(":/images/loader/16-loader.gif"); + movie->setSpeed(80); // 2x speed + hashloader = new QLabel(this); + hashloader->setMovie(movie); + hbox->addWidget(hashloader); + + movie->jumpToNextFrame(); // to calculate the real width + statusHashing = new StatusLabel(hbox, movie->frameRect().width() + hbox->spacing(), this); + hbox->addWidget(statusHashing); + + QSpacerItem *horizontalSpacer = new QSpacerItem(1000, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + hbox->addItem(horizontalSpacer); + + setLayout(hbox); + + hashloader->hide(); + statusHashing->hide(); + + connect(NotifyQt::getInstance(), SIGNAL(hashingInfoChanged(const QString&)), SLOT(updateHashingInfo(const QString&))); +} + +HashingStatus::~HashingStatus() +{ + delete(movie); +} + +void HashingStatus::updateHashingInfo(const QString& s) +{ + if(s.isEmpty()) { + statusHashing->hide(); + hashloader->hide(); + + movie->stop(); + } else { + statusHashing->setText(s); + statusHashing->show(); + hashloader->show(); + + movie->start(); + } +} diff --git a/retroshare-gui/src/gui/statusbar/hashingstatus.h b/retroshare-gui/src/gui/statusbar/hashingstatus.h new file mode 100644 index 000000000..c33e2dc59 --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/hashingstatus.h @@ -0,0 +1,44 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#ifndef HASHINGSTATUS_H +#define HASHINGSTATUS_H + +#include + +class QLabel; + +class HashingStatus : public QWidget +{ + Q_OBJECT + +public: + HashingStatus(QWidget *parent = 0); + ~HashingStatus(); + +public slots: + void updateHashingInfo(const QString&) ; + +private: + QLabel *statusHashing, *hashloader; + QMovie *movie; +}; + +#endif diff --git a/retroshare-gui/src/gui/statusbar/natstatus.cpp b/retroshare-gui/src/gui/statusbar/natstatus.cpp new file mode 100644 index 000000000..9e1b10e8b --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/natstatus.cpp @@ -0,0 +1,113 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "natstatus.h" + +#include + +NATStatus::NATStatus(QWidget *parent) + : QWidget(parent) +{ + QHBoxLayout *hbox = new QHBoxLayout(this); + hbox->setMargin(0); + hbox->setSpacing(6); + + statusNAT = new QLabel( tr("NAT:"), this ); +// statusDHT->setMinimumSize( statusPeers->frameSize().width() + 0, 0 ); + hbox->addWidget(statusNAT); + + iconLabel = new QLabel(this); + iconLabel->setPixmap(QPixmap(":/images/grayled.png")); + // iconLabel doesn't change over time, so we didn't need a minimum size + hbox->addWidget(iconLabel); + + hbox->addSpacing(2); + + setLayout(hbox); +} + +void NATStatus::getNATStatus() +{ + rsiface->lockData(); /* Lock Interface */ + + /* now the extra bit .... switch on check boxes */ + const RsConfig &config = rsiface->getConfig(); + +// if(config.netUpnpOk) +// { +// iconLabel->setPixmap(QPixmap::QPixmap(":/images/greenled.png")); +// iconLabel->setToolTip(tr("UPNP is active.")); +// } +// else +// { +// iconLabel->setPixmap(QPixmap::QPixmap(":/images/yellowled.png")); +// iconLabel->setToolTip(tr("UPNP NOT FOUND.")); +// } +// +// if(config.netExtOk) +// { +// iconLabel->setPixmap(QPixmap::QPixmap(":/images/greenled.png")); +// iconLabel->setToolTip(tr("Stable External IP Address")); +// } +// else +// { +// iconLabel->setPixmap(QPixmap::QPixmap(":/images/yellowled.png")); +// iconLabel->setToolTip(tr("Not Found External Address")); +// } +// +// if(config.netUdpOk) +// { +// iconLabel->setPixmap(QPixmap::QPixmap(":/images/yellowled.png")); +// iconLabel->setToolTip(tr("UDP Port is reachable")); +// } +// else +// { +// iconLabel->setPixmap(QPixmap::QPixmap(":/images/grayled.png")); +// iconLabel->setToolTip(tr("UDP Port is not reachable")); +// } + + if (config.netUpnpOk) + { + iconLabel->setPixmap(QPixmap(":/images/greenled.png")); + iconLabel->setToolTip(tr("OK | RetroShare Server")); + } + else if (config.netStunOk || config.netExtraAddressOk) + { + iconLabel->setPixmap(QPixmap(":/images/greenled.png")); + iconLabel->setToolTip(tr("Internet connection")); + } + else if (config.netLocalOk) + { + iconLabel->setPixmap(QPixmap(":/images/grayled.png")); + iconLabel->setToolTip(tr("No internet connection")); + } + else + { + iconLabel->setPixmap(QPixmap(":/images/redled.png")); + iconLabel->setToolTip(tr("No local network")); + } + + rsiface->unlockData(); /* UnLock Interface */ + +} diff --git a/retroshare-gui/src/gui/statusbar/natstatus.h b/retroshare-gui/src/gui/statusbar/natstatus.h new file mode 100644 index 000000000..7762ee02c --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/natstatus.h @@ -0,0 +1,41 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#ifndef NATSTATUS_H +#define NATSTATUS_H + +#include + +class QLabel; + +class NATStatus : public QWidget +{ + Q_OBJECT + +public: + NATStatus(QWidget *parent = 0); + + void getNATStatus( ); + +private: + QLabel *iconLabel, *statusNAT; +}; + +#endif diff --git a/retroshare-gui/src/gui/statusbar/peerstatus.cpp b/retroshare-gui/src/gui/statusbar/peerstatus.cpp new file mode 100644 index 000000000..aac4ad3c8 --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/peerstatus.cpp @@ -0,0 +1,76 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "peerstatus.h" + +#include + +PeerStatus::PeerStatus(QWidget *parent) + : QWidget(parent) +{ + QHBoxLayout *hbox = new QHBoxLayout(this); + hbox->setMargin(0); + hbox->setSpacing(6); + + iconLabel = new QLabel( this ); + iconLabel->setPixmap(QPixmap(":/images/user/identitygray16.png")); + // iconLabel doesn't change over time, so we didn't need a minimum size + hbox->addWidget(iconLabel); + + statusPeers = new QLabel( tr("Friends: 0/0"), this ); +// statusPeers->setMinimumSize( statusPeers->frameSize().width() + 0, 0 ); + hbox->addWidget(statusPeers); + + setLayout(hbox); + +} + +void PeerStatus::getPeerStatus(unsigned int nFriendCount, unsigned int nOnlineCount) +{ + /* set users/friends/network */ + + std::ostringstream out; + out << nFriendCount << " "; + + std::ostringstream out2; + out2 << nOnlineCount << ""; + + statusPeers->setToolTip(tr("Online Friends/Total Friends") ); + + if (statusPeers) + statusPeers -> setText( "" + tr("Friends") + ": " + QString::fromStdString(out2.str()) + "/" + QString::fromStdString(out.str()) ); + + if (nOnlineCount > 0) + { + iconLabel->setPixmap(QPixmap(":/images/user/identity16.png")); + } + else + { + iconLabel->setPixmap(QPixmap(":/images/user/identitygray16.png")); + } + + +} + + diff --git a/retroshare-gui/src/gui/statusbar/peerstatus.h b/retroshare-gui/src/gui/statusbar/peerstatus.h new file mode 100644 index 000000000..a8c83636c --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/peerstatus.h @@ -0,0 +1,41 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#ifndef PEERSTATUS_H +#define PEERSTATUS_H + +#include + +class QLabel; + +class PeerStatus : public QWidget +{ + Q_OBJECT + +public: + PeerStatus(QWidget *parent = 0); + + void getPeerStatus(unsigned int nFriendCount, unsigned int nOnlineCount); + +private: + QLabel *iconLabel, *statusPeers; +}; + +#endif diff --git a/retroshare-gui/src/gui/statusbar/ratesstatus.cpp b/retroshare-gui/src/gui/statusbar/ratesstatus.cpp new file mode 100644 index 000000000..a1a20d67a --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/ratesstatus.cpp @@ -0,0 +1,83 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "ratesstatus.h" +#include + +#include +#include + +RatesStatus::RatesStatus(QWidget *parent) + : QWidget(parent) +{ + QHBoxLayout *hbox = new QHBoxLayout(this); + hbox->setMargin(0); + hbox->setSpacing(6); + + iconLabel = new QLabel( this ); + iconLabel->setPixmap(QPixmap(":/images/up0down0.png")); + // iconLabel doesn't change over time, so we didn't need a minimum size + hbox->addWidget(iconLabel); + + statusRates = new QLabel( tr("Down: 0.00 (kB/s) | Up: 0.00 (kB/s) "), this ); +// statusPeers->setMinimumSize( statusPeers->frameSize().width() + 0, 0 ); + hbox->addWidget(statusRates); + + setLayout(hbox); +} + +void RatesStatus::getRatesStatus(float downKb, float upKb) +{ + /* set users/friends/network */ + + std::ostringstream out; + out << std::setprecision(2) << std::fixed << downKb ; + + std::ostringstream out2; + out2 << std::setprecision(2) << std::fixed << upKb ; + + + if (statusRates) + statusRates -> setText( tr("Down:") + " " + QString::fromStdString(out.str()) + " (kB/s) | " + tr("Up:") + " " + QString::fromStdString(out2.str()) + " (kB/s) " ); + + if( upKb > 0 || downKb < 0 ) + { + iconLabel->setPixmap(QPixmap(":/images/up1down0.png")); + } + + if( upKb < 0 || downKb > 0 ) + { + iconLabel->setPixmap(QPixmap(":/images/up0down1.png")); + } + + if( upKb > 0 || downKb > 0 ) + { + iconLabel->setPixmap(QPixmap(":/images/up1down1.png")); + } + + else + { + iconLabel->setPixmap(QPixmap(":/images/up0down0.png")); + } +} diff --git a/retroshare-gui/src/gui/statusbar/ratesstatus.h b/retroshare-gui/src/gui/statusbar/ratesstatus.h new file mode 100644 index 000000000..77e657932 --- /dev/null +++ b/retroshare-gui/src/gui/statusbar/ratesstatus.h @@ -0,0 +1,41 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#ifndef RATESSTATUS_H +#define RATESSTATUS_H + +#include + +class QLabel; + +class RatesStatus : public QWidget +{ + Q_OBJECT + +public: + RatesStatus(QWidget *parent = 0); + + void getRatesStatus(float downKb, float upKb); + +private: + QLabel *iconLabel, *statusRates; +}; + +#endif diff --git a/retroshare-gui/src/gui/style/RSStyle.cpp b/retroshare-gui/src/gui/style/RSStyle.cpp new file mode 100644 index 000000000..1b677e060 --- /dev/null +++ b/retroshare-gui/src/gui/style/RSStyle.cpp @@ -0,0 +1,114 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "RSStyle.h" +#include "StyleDialog.h" + +RSStyle::RSStyle() +{ + styleType = STYLETYPE_NONE; +} + +/*static*/ int RSStyle::neededColors(StyleType styleType) +{ + switch (styleType) { + case STYLETYPE_NONE: + return 0; + case STYLETYPE_SOLID: + return 1; + case STYLETYPE_GRADIENT: + return 2; + } + + return 0; +} + +QString RSStyle::getStyleSheet() const +{ + QString sheet; + + switch (styleType) { + case STYLETYPE_NONE: + break; + case STYLETYPE_SOLID: + sheet = "background-color: "; + break; + case STYLETYPE_GRADIENT: + sheet = "background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 , stop:1 );"; + break; + } + + if (sheet.isEmpty() == false) { + /* Replace colors */ + for (int i = 0; i < colors.size(); i++) { + sheet.replace(QString("").arg(i + 1), colors[i].name()); + } + } + + return sheet; +} + +bool RSStyle::showDialog(QWidget *parent) +{ + StyleDialog dlg(*this, parent); + int result = dlg.exec(); + if (result == QDialog::Accepted) { + dlg.getStyle(*this); + return true; + } + + return false; +} + +void RSStyle::readSetting (QSettings &settings) +{ + int type = (StyleType) settings.value("styleType").toInt(); + if (type >= 0 && type <= STYLETYPE_MAX) { + styleType = (StyleType) type; + } else { + styleType = STYLETYPE_NONE; + } + + colors.empty(); + + int size = settings.beginReadArray("colors"); + for (int i = 0; i < size; i++) { + settings.setArrayIndex(i); + colors.append(QColor(settings.value("value").toString())); + } + settings.endArray(); +} + +void RSStyle::writeSetting (QSettings &settings) +{ + settings.setValue("styleType", styleType); + + settings.beginWriteArray("colors"); + int size = colors.size(); + for (int i = 0; i < size; i++) { + settings.setArrayIndex(i); + settings.setValue("value", colors[i].name()); + } + settings.endArray(); +} diff --git a/retroshare-gui/src/gui/style/RSStyle.h b/retroshare-gui/src/gui/style/RSStyle.h new file mode 100644 index 000000000..bdc5cf93c --- /dev/null +++ b/retroshare-gui/src/gui/style/RSStyle.h @@ -0,0 +1,58 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _RSSTYLE_H +#define _RSSTYLE_H + +#include +class QSettings; + +class RSStyle +{ +public: + enum StyleType + { + STYLETYPE_NONE = 0, + STYLETYPE_SOLID = 1, + STYLETYPE_GRADIENT = 2, + STYLETYPE_MAX = 2 + }; + +public: + RSStyle(); + + QString getStyleSheet() const; + + bool showDialog(QWidget *parent); + + static int neededColors(StyleType styleType); + + void readSetting (QSettings &settings); + void writeSetting (QSettings &settings); + +public: + StyleType styleType; + QList colors; +}; + +#endif + diff --git a/retroshare-gui/src/gui/style/StyleDialog.cpp b/retroshare-gui/src/gui/style/StyleDialog.cpp new file mode 100644 index 000000000..ffbc22245 --- /dev/null +++ b/retroshare-gui/src/gui/style/StyleDialog.cpp @@ -0,0 +1,161 @@ +/**************************************************************** + * + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "gui/settings/rsharesettings.h" + +#include "StyleDialog.h" +#include "gui/style/RSStyle.h" + +/** Default constructor */ +StyleDialog::StyleDialog(RSStyle &style, QWidget *parent, Qt::WFlags flags) : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + /* Load window postion */ + QByteArray geometry = Settings->valueFromGroup("StyleDialog", "Geometry", QByteArray()).toByteArray(); + if (geometry.isEmpty() == false) { + restoreGeometry(geometry); + } + +// setWindowIcon(QIcon(":/images/rstray3.png")); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(onOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + + connect(ui.color1Button, SIGNAL(clicked()), this, SLOT(chooseColor())); + connect(ui.color2Button, SIGNAL(clicked()), this, SLOT(chooseColor())); + + /* Initialize style combobox */ + ui.styleComboBox->addItem(tr("None"), RSStyle::STYLETYPE_NONE); + ui.styleComboBox->addItem(tr("Solid"), RSStyle::STYLETYPE_SOLID); + ui.styleComboBox->addItem(tr("Gradient"), RSStyle::STYLETYPE_GRADIENT); + + ui.styleComboBox->setCurrentIndex(style.styleType); + connect(ui.styleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(showButtons())); + + /* Add pushbuttons and labels */ + pushButtons.append(ui.color1Button); + pushButtons.append(ui.color2Button); + + labels.append(ui.color1Label); + labels.append(ui.color2Label); + + /* Set pushbuttons visible */ + showButtons(); + + /* Init colors */ + for (int i = 0; i < pushButtons.size(); i++) { + if (i < style.colors.size()) { + colors[pushButtons[i]] = style.colors[i]; + } else { + colors[pushButtons[i]] = Qt::white; + } + } + + drawButtons(); + drawPreview(); +} + +/** Destructor. */ +StyleDialog::~StyleDialog() +{ + /* Save window postion */ + Settings->setValueToGroup("StyleDialog", "Geometry", saveGeometry()); +} + +void StyleDialog::onOK() +{ + accept(); +} + +int StyleDialog::neededColors() +{ + return RSStyle::neededColors((RSStyle::StyleType) ui.styleComboBox->itemData(ui.styleComboBox->currentIndex()).toInt()); +} + +void StyleDialog::getStyle(RSStyle &style) +{ + style.styleType = (RSStyle::StyleType) ui.styleComboBox->itemData(ui.styleComboBox->currentIndex()).toInt(); + + style.colors.clear(); + + int count = qMin(neededColors(), pushButtons.size()); + for (int i = 0; i < count; i++) { + style.colors.append(colors[pushButtons[i]]); + } +} + +void StyleDialog::showButtons() +{ + int count = neededColors(); + for (int i = 0; i < pushButtons.size(); i++) { + pushButtons[i]->setVisible(i < count); + labels[i]->setVisible(i < count); + } + + drawPreview(); +} + +void StyleDialog::drawButtons() +{ + QPixmap pxm(16,14); + + QMap::iterator it; + for (it = colors.begin(); it != colors.end(); it++) { + pxm.fill(it.value()); + it.key()->setIcon(pxm); + } +} + +void StyleDialog::drawPreview() +{ + RSStyle style; + getStyle(style); + + QString widgetSheet; + + QString styleSheet = style.getStyleSheet(); + if (styleSheet.isEmpty() == false) { + widgetSheet = QString(".QWidget{%1}").arg(styleSheet); + } + + ui.previewWidget->setStyleSheet(widgetSheet); +} + +void StyleDialog::chooseColor() +{ + QPushButton *button = dynamic_cast(sender()); + if (button == NULL) { + return; + } + + QColor color = QColorDialog::getColor(colors[button]); + if (color.isValid()) { + colors[button] = color; + + drawButtons(); + drawPreview(); + } +} diff --git a/retroshare-gui/src/gui/style/StyleDialog.h b/retroshare-gui/src/gui/style/StyleDialog.h new file mode 100644 index 000000000..db4a6f0e0 --- /dev/null +++ b/retroshare-gui/src/gui/style/StyleDialog.h @@ -0,0 +1,63 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _STYLEDIALOG_H +#define _STYLEDIALOG_H + +#include +#include + +#include "ui_StyleDialog.h" + +class QPushButton; +class RSStyle; + +class StyleDialog : public QDialog +{ + Q_OBJECT + +public: + /** Default constructor */ + StyleDialog(RSStyle &style, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~StyleDialog(); + + void getStyle(RSStyle &style); + +private slots: + void onOK(); + void chooseColor(); + void showButtons(); + +private: + QMap colors; + QList pushButtons; + QList labels; + + void drawButtons(); + int neededColors(); + void drawPreview(); + + /** Qt Designer generated object */ + Ui::StyleDialog ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/style/StyleDialog.ui b/retroshare-gui/src/gui/style/StyleDialog.ui new file mode 100644 index 000000000..e9b41d95e --- /dev/null +++ b/retroshare-gui/src/gui/style/StyleDialog.ui @@ -0,0 +1,273 @@ + + + StyleDialog + + + Qt::NonModal + + + + 0 + 0 + 387 + 227 + + + + + 0 + 0 + + + + + 387 + 227 + + + + Define Style + + + + :/images/rstray3.png:/images/rstray3.png + + + true + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame#frame{background-image: url(:/images/connect/connectFriendBanner.png);} + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 9 + + + 6 + + + 9 + + + 6 + + + + + + 64 + 64 + + + + + 64 + 64 + + + + + + + :/images/library.png + + + true + + + + + + + + 18 + 75 + true + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + + + + 0 + 0 + + + + Choose color + + + + + + + + + + + 0 + 0 + + + + Choose color + + + + + + + + + + + 0 + 0 + + + + Color 2 + + + + + + + + 0 + 0 + + + + Color 1 + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + + + + + + 0 + 0 + + + + Style + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 0 + 5000 + + + + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + true + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/toaster/DownloadToaster.cpp b/retroshare-gui/src/gui/toaster/DownloadToaster.cpp new file mode 100644 index 000000000..805e76cdf --- /dev/null +++ b/retroshare-gui/src/gui/toaster/DownloadToaster.cpp @@ -0,0 +1,66 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (C) 2007 - 2010 Xesc & Technology + * Copyright (c) 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *************************************************************************/ + +#include +#include +#include +#include + +#include "DownloadToaster.h" + +#include + +DownloadToaster::DownloadToaster(const std::string &hash, const QString &name) : QWidget(NULL) +{ + ui.setupUi(this); + + fileHash = hash; + + /* connect buttons */ + connect(ui.spbClose, SIGNAL(clicked()), this, SLOT(hide())); + connect(ui.startButton, SIGNAL(clicked()), this, SLOT(play())); + + /* set informations */ + ui.labelTitle->setText(name); +} + +void DownloadToaster::play() +{ + /* look up path */ + FileInfo fi; + if (!rsFiles->FileDetails(fileHash, RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_DOWNLOAD | RS_FILE_HINTS_SPEC_ONLY, fi)) { + return; + } + + std::string filename = fi.path + "/" + fi.fname; + + /* open file with a suitable application */ + QFileInfo qinfo; + qinfo.setFile(filename.c_str()); + if (qinfo.exists()) { + QDesktopServices::openUrl(QUrl::fromLocalFile(qinfo.absoluteFilePath())); + }else{ +// QMessageBox::information(this, "RetroShare", tr("File %1 does not exist at location.").arg(fi.path.c_str())); + } + + hide(); +} diff --git a/retroshare-gui/src/gui/toaster/DownloadToaster.h b/retroshare-gui/src/gui/toaster/DownloadToaster.h new file mode 100644 index 000000000..6c1005474 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/DownloadToaster.h @@ -0,0 +1,45 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (C) 2007 - 2010 Xesc & Technology + * Copyright (c) 2010 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *************************************************************************/ + +#ifndef DOWNLOADTOASTER_H +#define DOWNLOADTOASTER_H + +#include "ui_DownloadToaster.h" + +class DownloadToaster : public QWidget +{ + Q_OBJECT + +public: + DownloadToaster(const std::string &hash, const QString &name); + +private slots: + void play(); + +private: + std::string fileHash; + + /** Qt Designer generated object */ + Ui::DownloadToaster ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/toaster/DownloadToaster.ui b/retroshare-gui/src/gui/toaster/DownloadToaster.ui new file mode 100644 index 000000000..69f8a1060 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/DownloadToaster.ui @@ -0,0 +1,211 @@ + + + DownloadToaster + + + + 0 + 0 + 300 + 100 + + + + + + 10 + 30 + 241 + 61 + + + + + + + + + 0 + 0 + 127 + + + + + + + 255 + 247 + 221 + + + + + + + + + 0 + 0 + 127 + + + + + + + 255 + 247 + 221 + + + + + + + + + 117 + 116 + 118 + + + + + + + 255 + 247 + 221 + + + + + + + + + + + true + + + + + + 260 + 43 + 31 + 31 + + + + Qt::NoFocus + + + Start file + + + + + + + :/images/player_play.png:/images/player_play.png + + + + 22 + 22 + + + + true + + + + + + 30 + 10 + 241 + 20 + + + + <b>Download completed</b> + + + + + + 4 + 10 + 21 + 21 + + + + + + + :/images/rstray3.png + + + true + + + + + + 270 + 10 + 20 + 20 + + + + Qt::NoFocus + + + Close + + + + + + + :/images/closenormal.png:/images/closenormal.png + + + true + + + + + + 0 + 0 + 300 + 100 + + + + :/images/toaster/backgroundtoaster.png + + + background + labelTitle + startButton + lblTitle + label + spbClose + + + startButton + spbClose + + + + + + diff --git a/retroshare-gui/src/gui/toaster/MessageToaster.cpp b/retroshare-gui/src/gui/toaster/MessageToaster.cpp new file mode 100644 index 000000000..6d272fca4 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/MessageToaster.cpp @@ -0,0 +1,45 @@ +/* + * RetroShare + * Copyright (C) 2006 - 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MessageToaster.h" +#include "../MainWindow.h" + +MessageToaster::MessageToaster(const QString &name, const QString &title, const QString &message) : QWidget(NULL) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + /* connect buttons */ + connect(ui.closebtn, SIGNAL(clicked()), this, SLOT(hide())); + //connect(ui.openmessagebtn, SIGNAL(clicked()), this, SLOT(openmessageClicked())); + connect(ui.openmessagetoolButton, SIGNAL(clicked()), this, SLOT(openmessageClicked())); + + /* set informations */ + ui.subjectline->setText(tr("Sub:") + " " + title); + ui.subjectline->setToolTip(title); + ui.contentBrowser->setText(message); + ui.contentBrowser->setToolTip(message); + ui.namelabel->setText(name); +} + +void MessageToaster::openmessageClicked() +{ + MainWindow::showWindow(MainWindow::Messages); + hide(); +} diff --git a/retroshare-gui/src/gui/toaster/MessageToaster.h b/retroshare-gui/src/gui/toaster/MessageToaster.h new file mode 100644 index 000000000..05eb108d9 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/MessageToaster.h @@ -0,0 +1,46 @@ +/* +* +* This file is part of xVideoServiceThief, +* an open-source cross-platform Video service download +* +* Copyright (C) 2007 - 2008 Xesc & Technology +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with xVideoServiceThief. If not, see . +* +* Contact e-mail: Xesc +* Program URL : http://xviservicethief.sourceforge.net/ +* +*/ + +#ifndef MESSAGETOASTER_H +#define MESSAGETOASTER_H + +#include "ui_MessageToaster.h" + +class MessageToaster : public QWidget +{ + Q_OBJECT + +public: + MessageToaster(const QString &name, const QString &title, const QString &message); + +private slots: + void openmessageClicked(); + +private: + /** Qt Designer generated object */ + Ui::MessageToaster ui; +}; + +#endif diff --git a/retroshare-gui/src/gui/toaster/MessageToaster.ui b/retroshare-gui/src/gui/toaster/MessageToaster.ui new file mode 100644 index 000000000..df5d38f50 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/MessageToaster.ui @@ -0,0 +1,200 @@ + + + MessageToaster + + + + 0 + 0 + 300 + 100 + + + + + + 150 + 0 + 16 + 16 + + + + + + + + + + 0 + 0 + 300 + 100 + + + + :/images/toaster/backgroundtoaster.png + + + + + + 10 + 30 + 61 + 61 + + + + + 64 + 64 + + + + + + + + :/images/folder_inbox64.png:/images/folder_inbox64.png + + + + 64 + 64 + + + + true + + + + + + 40 + 10 + 221 + 16 + + + + <b>1 new Message from</b> + + + + + + 10 + 10 + 16 + 16 + + + + + + + :/images/rstray3.png + + + true + + + + + + 270 + 10 + 20 + 20 + + + + Qt::NoFocus + + + Close + + + Close button + + + Close the information dialog + + + + + + + :/images/closenormal.png:/images/closenormal.png + + + true + + + + + false + + + + 80 + 50 + 201 + 41 + + + + false + + + background-color: transparent; +border: none; + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Message</span></p></body></html> + + + + + false + + + + 80 + 30 + 201 + 20 + + + + false + + + background-color: transparent; +border: none; +color: black; + + + Subject + + + + + closebtn + + + + + + diff --git a/retroshare-gui/src/gui/toaster/OnlineToaster.cpp b/retroshare-gui/src/gui/toaster/OnlineToaster.cpp new file mode 100644 index 000000000..7ece1dc65 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/OnlineToaster.cpp @@ -0,0 +1,67 @@ +/* + * RetroShare + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "OnlineToaster.h" +#include "gui/settings/rsharesettings.h" +#include "gui/chat/PopupChatDialog.h" +#include "util/WidgetBackgroundImage.h" + +OnlineToaster::OnlineToaster(const std::string &peerId, const QString &name, const QPixmap &avatar) : QWidget(NULL) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + this->peerId = peerId; + + /* connect buttons */ + connect(ui.messageButton, SIGNAL(clicked()), SLOT(chatButtonSlot())); + connect(ui.closeButton, SIGNAL(clicked()), SLOT(hide())); + + /* set informations */ + ui.messageLabel->setText(name); + ui.pixmaplabel->setPixmap(avatar); + + WidgetBackgroundImage::setBackgroundImage(ui.windowFrame, ":images/toaster/backgroundtoaster.png", WidgetBackgroundImage::AdjustNone); + + play(); +} + +void OnlineToaster::chatButtonSlot() +{ + PopupChatDialog::chatFriend(peerId); + hide(); +} + +void OnlineToaster::play() +{ + Settings->beginGroup("Sound"); + Settings->beginGroup("SoundFilePath"); + QString OnlineSound = Settings->value("User_go_Online","").toString(); + Settings->endGroup(); + Settings->beginGroup("Enable"); + bool flag = Settings->value("User_go_Online",false).toBool(); + Settings->endGroup(); + Settings->endGroup(); + + if(!OnlineSound.isEmpty()&&flag) + if(QSound::isAvailable()) + QSound::play(OnlineSound); +} diff --git a/retroshare-gui/src/gui/toaster/OnlineToaster.h b/retroshare-gui/src/gui/toaster/OnlineToaster.h new file mode 100644 index 000000000..1a4515a7a --- /dev/null +++ b/retroshare-gui/src/gui/toaster/OnlineToaster.h @@ -0,0 +1,49 @@ +/* + * RetroShare + * Copyright (C) 2006 crypton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ONLINETOASTER_H +#define ONLINETOASTER_H + +#include "ui_OnlineToaster.h" + +/** + * Shows a toaster when friend is Online . + * + * + */ +class OnlineToaster : public QWidget +{ + Q_OBJECT + +public: + OnlineToaster(const std::string &peerId, const QString &name, const QPixmap &avatar); + +private slots: + void chatButtonSlot(); + +private: + void play(); + + std::string peerId; + + /** Qt Designer generated object */ + Ui::OnlineToaster ui; +}; + +#endif //MESSAGETOASTER_H diff --git a/retroshare-gui/src/gui/toaster/OnlineToaster.ui b/retroshare-gui/src/gui/toaster/OnlineToaster.ui new file mode 100644 index 000000000..3ce8576c5 --- /dev/null +++ b/retroshare-gui/src/gui/toaster/OnlineToaster.ui @@ -0,0 +1,252 @@ + + + OnlineToaster + + + + 0 + 0 + 300 + 100 + + + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + + + 6 + + + 2 + + + 6 + + + 0 + + + 6 + + + 0 + + + + + + 18 + 18 + + + + + 18 + 18 + + + + + :/images/closenormal.png:/images/closenormal.png + + + + 16 + 16 + + + + true + + + + + + + Qt::Horizontal + + + + 20 + 22 + + + + + + + + + 16 + 16 + + + + + 16 + 16 + + + + + + + :/images/rstray3.png + + + true + + + + + + + + 9 + 75 + true + + + + RetroShare + + + + + + + + + 6 + + + 2 + + + 6 + + + 0 + + + 9 + + + 0 + + + + + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + QLabel#pixmaplabel{ +border: 2px solid #238; +border-radius: 4px;} + + + + + + + :/images/user/personal64.png + + + Qt::AlignCenter + + + + + + + + 75 + true + + + + color: #238; + + + Friend Online + + + + + + + Qt::Horizontal + + + + 20 + 10 + + + + + + + + + + Qt::Vertical + + + + 100 + 40 + + + + + + + + + + + closeButton + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/ApplicationWindow.cpp b/retroshare-gui/src/gui/unfinished/ApplicationWindow.cpp new file mode 100644 index 000000000..81354db4a --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/ApplicationWindow.cpp @@ -0,0 +1,211 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "ApplicationWindow.h" + +#include + +#include "GamesDialog.h" +#include "PhotoDialog.h" +#include "CalDialog.h" +#include "StatisticDialog.h" + +#define FONT QFont("Arial", 9) + +/* Images for toolbar icons */ +#define IMAGE_RETROSHARE ":/images/RetroShare16.png" +#define IMAGE_ABOUT ":/images/informations_24x24.png" +#define IMAGE_STATISTIC ":/images/ksysguard32.png" +#define IMAGE_GAMES ":/images/kgames.png" +#define IMAGE_PHOTO ":/images/lphoto.png" +#define IMAGE_BWGRAPH ":/images/ksysguard.png" +#define IMAGE_CLOSE ":/images/close_normal.png" +#define IMAGE_CALENDAR ":/images/calendar.png" +#define IMAGE_LIBRARY ":/images/library.png" +#define IMAGE_PLUGINS ":/images/extension_32.png" + + +/** Constructor */ +ApplicationWindow::ApplicationWindow(QWidget* parent, Qt::WFlags flags) + : QMainWindow(parent, flags) +{ + /* Invoke the Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + setWindowTitle(tr("RetroShare")); + + Settings->loadWidgetInformation(this); + + // Setting icons + this->setWindowIcon(QIcon(QString::fromUtf8(":/images/rstray3.png"))); + loadStyleSheet("Default"); + + /* Create the config pages and actions */ + QActionGroup *grp = new QActionGroup(this); + + StatisticDialog *statisticDialog = NULL; + ui.stackPages->add(statisticDialog = new StatisticDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_STATISTIC), tr("Statistics"), grp)); + + PhotoDialog *photoDialog = NULL; + ui.stackPages->add(photoDialog = new PhotoDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_PHOTO), tr("Photo View"), grp)); + + GamesDialog *gamesDialog = NULL; + ui.stackPages->add(gamesDialog = new GamesDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_GAMES), tr("Games Launcher"), grp)); + + CalDialog *calDialog = NULL; + ui.stackPages->add(calDialog = new CalDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_CALENDAR), tr("Shared Calendars"), grp)); + + + + /* Create the toolbar */ + ui.toolBar->addActions(grp->actions()); + ui.toolBar->addSeparator(); + connect(grp, SIGNAL(triggered(QAction *)), ui.stackPages, SLOT(showPage(QAction *))); + + +} + +/** Creates a new action associated with a config page. */ +QAction* ApplicationWindow::createPageAction(QIcon img, QString text, QActionGroup *group) +{ + QAction *action = new QAction(img, text, group); + action->setCheckable(true); + action->setFont(FONT); + return action; +} + +/** Adds the given action to the toolbar and hooks its triggered() signal to + * the specified slot (if given). */ +void ApplicationWindow::addAction(QAction *action, const char *slot) +{ + action->setFont(FONT); + ui.toolBar->addAction(action); + connect(action, SIGNAL(triggered()), this, slot); +} + +/** Overloads the default show so we can load settings */ +void ApplicationWindow::show() +{ + + if (!this->isVisible()) { + QMainWindow::show(); + } else { + QMainWindow::activateWindow(); + setWindowState(windowState() & ~Qt::WindowMinimized | Qt::WindowActive); + QMainWindow::raise(); + } +} + + +/** Shows the config dialog with focus set to the given page. */ +void ApplicationWindow::show(Page page) +{ + /* Show the dialog. */ + show(); + + /* Set the focus to the specified page. */ + ui.stackPages->setCurrentIndex((int)page); +} + + +/** Destructor. */ +ApplicationWindow::~ApplicationWindow() +{ +// is this allocated anywhere ?? +// delete exampleDialog; +} + +/** Create and bind actions to events. Setup for initial + * tray menu configuration. */ +void ApplicationWindow::createActions() +{ +} + +void ApplicationWindow::closeEvent(QCloseEvent *e) +{ + Settings->saveWidgetInformation(this); + + hide(); + e->ignore(); +} + + +void ApplicationWindow::updateMenu() +{ + toggleVisibilityAction->setText(isVisible() ? tr("Hide") : tr("Show")); +} + +void ApplicationWindow::toggleVisibility(QSystemTrayIcon::ActivationReason e) +{ + if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick){ + if(isHidden()){ + show(); + if(isMinimized()){ + if(isMaximized()){ + showMaximized(); + }else{ + showNormal(); + } + } + raise(); + activateWindow(); + }else{ + hide(); + } + } +} + +void ApplicationWindow::toggleVisibilitycontextmenu() +{ + if (isVisible()) + hide(); + else + show(); +} + + + +void ApplicationWindow::loadStyleSheet(const QString &sheetName) +{ + QFile file(":/qss/" + sheetName.toLower() + ".qss"); + file.open(QFile::ReadOnly); + QString styleSheet = QLatin1String(file.readAll()); + + + qApp->setStyleSheet(styleSheet); + +} + + + diff --git a/retroshare-gui/src/gui/unfinished/ApplicationWindow.h b/retroshare-gui/src/gui/unfinished/ApplicationWindow.h new file mode 100644 index 000000000..04c70b88c --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/ApplicationWindow.h @@ -0,0 +1,113 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _ApplicationWindow_H +#define _ApplicationWindow_H + +#include +#include +#include + +#include "ExampleDialog.h" + + +#include "ui_ApplicationWindow.h" + + +class ApplicationWindow : public QMainWindow +{ + Q_OBJECT + +public: + /** Main dialog pages. */ + enum Page { + Graph = 0, /** Network Graph */ + Channels = 1, /** Channels page. */ + SharedDirectories = 2, /** Shared Directories page. */ + Search = 3, /** Search page. */ + Transfers = 4, /** Transfers page. */ + Chat = 5, /** Chat page. */ + Messages = 6, /** Messages page. */ + Statistics = 8 /** Statistic page. */ + + }; + + /** Default Constructor */ + ApplicationWindow(QWidget *parent = 0, Qt::WFlags flags = 0); + + /** Destructor. */ + ~ApplicationWindow(); + + /* A Bit of a Hack... but public variables for + * the dialogs, so we can add them to the + * Notify Class... + */ + + ExampleDialog *exampleDialog; + //ChannelsDialog *channelsDialog; + //GroupsDialog *groupsDialog; + //StatisticDialog *statisticDialog; + +public slots: + /** Called when this dialog is to be displayed */ + void show(); + /** Shows the config dialog with focus set to the given page. */ + void show(Page page); + + +private slots: + + void updateMenu(); + + void toggleVisibility(QSystemTrayIcon::ActivationReason e); + void toggleVisibilitycontextmenu(); + + +protected: + void closeEvent(QCloseEvent *); + + +private slots: + + + +private: + + /** Create the actions on the tray menu or menubar */ + void createActions(); + + /** Creates a new action for a config page. */ + QAction* createPageAction(QIcon img, QString text, QActionGroup *group); + /** Adds a new action to the toolbar. */ + void addAction(QAction *action, const char *slot = 0); + + void loadStyleSheet(const QString &sheetName); + + QSystemTrayIcon *trayIcon; + QAction *toggleVisibilityAction; + QMenu *menu; + + /** Qt Designer generated object */ + Ui::ApplicationWindow ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui b/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui new file mode 100644 index 000000000..fb8be2949 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/ApplicationWindow.ui @@ -0,0 +1,1076 @@ + + ApplicationWindow + + + + 0 + 0 + 679 + 542 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 10 + 36 + 106 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 212 + 208 + 200 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 120 + 120 + 120 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 139 + 139 + 139 + + + + + + + 120 + 120 + 120 + + + + + + + 255 + 255 + 255 + + + + + + + 120 + 120 + 120 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 10 + 36 + 106 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + Qt::CustomContextMenu + + + RetroShare + + + + 24 + 24 + + + + Qt::ToolButtonTextUnderIcon + + + + + 0 + 12 + 679 + 509 + + + + + 6 + + + 0 + + + 6 + + + 0 + + + 0 + + + + + + 120 + 0 + + + + + 120 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 160 + 160 + 160 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 10 + 36 + 106 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 160 + 160 + 160 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 212 + 208 + 200 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 120 + 120 + 120 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 120 + 120 + 120 + + + + + + + 160 + 160 + 160 + + + + + + + 120 + 120 + 120 + + + + + + + 255 + 255 + 255 + + + + + + + 120 + 120 + 120 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 10 + 36 + 106 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + + + 50 + false + + + + Qt::NoContextMenu + + + + + + + + + 0 + 521 + 679 + 21 + + + + + + + 0 + 0 + 679 + 12 + + + + Qt::NoContextMenu + + + true + + + Qt::TopToolBarArea + + + Qt::Horizontal + + + + 24 + 24 + + + + Qt::ToolButtonTextUnderIcon + + + TopToolBarArea + + + false + + + + + + MainPageStack + QWidget +
    gui/mainpagestack.h
    +
    +
    + + + + +
    diff --git a/retroshare-gui/src/gui/unfinished/CalDialog.cpp b/retroshare-gui/src/gui/unfinished/CalDialog.cpp new file mode 100644 index 000000000..30e4ab09e --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/CalDialog.cpp @@ -0,0 +1,134 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include +#include + +//#include "rshare.h" +#include "CalDialog.h" +//#include +//#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +/** Constructor */ +CalDialog::CalDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + //declare local variables for GUI items + name = ui.lne_name; + location = ui.lne_location; + status = ui.cbx_status; + calendarList = ui.lst_calList; + + //Set GUI Item Properties + location->setEnabled(false); + + //Create GUI Connections + connect(ui.btn_add,SIGNAL(clicked()),this,SLOT(addItem())); + connect(ui.btn_addFile,SIGNAL(clicked()),this,SLOT(addFile())); + connect(ui.lst_calList,SIGNAL(itemPressed(QListWidgetItem*)),this,SLOT(setDetails(QListWidgetItem*))); + connect(ui.btn_remove,SIGNAL(clicked()),this,SLOT(removeItem())); +} + +void CalDialog::addItem() +{ + itemDetails = new CalItem(); + if(name->text() != QString("")) + itemDetails->name = name->text(); + if(location->text() != QString("")) + itemDetails->location = QString(location->text()); + itemDetails->status = status->currentIndex(); + + //Add Item to Calendar Item Map + calItems.insert(itemDetails->name, *itemDetails); + clearDetails(); //Clear Textbox Details (and itemDetails pointer) + updateList(); //Update listWidget with new map data. +} + +void CalDialog::removeItem() +{ + QListWidgetItem* item = calendarList->currentItem(); + calItems.remove(item->text()); + clearDetails(); + updateList(); +} + +void CalDialog::updateList() +{ + calendarList->clear(); //Clear existing items + //Rebuild list from Map + QMap::iterator it; + for(it = calItems.begin();it != calItems.end();++it) + calendarList->addItem(it.key()); +} + +void CalDialog::clearDetails() +{ + name->setText(""); + location->setText(""); + status->setCurrentIndex(0); + itemDetails = NULL; +} + +void CalDialog::addFile() +{ + //Prompt for ICS calendar file + QStringList file = QFileDialog::getOpenFileNames(this, + "Select calendar to share",location->text(), "Calendars (*.ics)"); + + //Populate location LineEdit if file selected + if(!file.empty()) + location->setText(*file.begin()); +} + +void CalDialog::setDetails(QListWidgetItem* item) +{ + clearDetails(); + QMap::iterator it = calItems.find(item->text()); + CalItem temp = it.value(); + name->setText(temp.name); + location->setText(temp.location); + status->setCurrentIndex(temp.status); +} diff --git a/retroshare-gui/src/gui/unfinished/CalDialog.h b/retroshare-gui/src/gui/unfinished/CalDialog.h new file mode 100644 index 000000000..09012733b --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/CalDialog.h @@ -0,0 +1,72 @@ +/**************************************************************** + * RetroShare GUI is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CALENDAR_DIALOG_H +#define _CALENDAR_DIALOG_H + +#include +#include +#include +#include + +#include "gui/mainpage.h" +#include "ui_CalDialog.h" + +class CalItem +{ + public: + CalItem() {return;} + QString name; + QString location; + int status; +}; + +class CalDialog : public MainPage +{ + Q_OBJECT + +public: +/** Default Constructor */ + CalDialog(QWidget *parent = 0); + +private slots: + void addItem(); + void removeItem(); + void updateList(); + void clearDetails(); + void addFile(); + void setDetails(QListWidgetItem*); + +private: + //Should this be a vector for alphabetical sorting? + QMap calItems; + CalItem *itemDetails; + +/** Qt Designer generated object */ + Ui::CalDialog ui; + + QLineEdit* name; + QLineEdit* location; + QComboBox* status; + QListWidget* calendarList; +}; + +#endif diff --git a/retroshare-gui/src/gui/unfinished/CalDialog.ui b/retroshare-gui/src/gui/unfinished/CalDialog.ui new file mode 100644 index 000000000..8615caa12 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/CalDialog.ui @@ -0,0 +1,285 @@ + + CalDialog + + + + 0 + 0 + 740 + 540 + + + + Form + + + + 0 + + + 6 + + + 0 + + + 6 + + + 0 + + + + + QTabWidget::Rounded + + + 0 + + + Qt::ElideNone + + + + + 0 + 0 + 734 + 501 + + + + Local Calendars + + + + + + QLayout::SetMaximumSize + + + + + + 75 + true + + + + Shared Calendar List + + + + + + + + 0 + 0 + + + + + 289 + 0 + + + + + + + + + + + 75 + true + + + + Share Details + + + + + + + QLayout::SetMaximumSize + + + + + Name: + + + + + + + + + + Location: + + + + + + + QLayout::SetMaximumSize + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 30 + 0 + + + + + 0 + 16777215 + + + + + 0 + 0 + + + + ... + + + + + + + + + Status: + + + + + + + + 100 + 0 + + + + + 0 + 16777215 + + + + + Private + + + + + Public + + + + + + + + Allow List: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + <Disabled> + + + + + + + + + + QLayout::SetMaximumSize + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add + + + + + + + Remove + + + + + + + + + + + 26 + 45 + 760 + 509 + + + + Peer Calendars + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/ExampleDialog.cpp b/retroshare-gui/src/gui/unfinished/ExampleDialog.cpp new file mode 100644 index 000000000..e54317075 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/ExampleDialog.cpp @@ -0,0 +1,279 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "rshare.h" +#include "ExampleDialog.h" +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Images for context menu icons */ +#define IMAGE_REMOVEFRIEND ":/images/removefriend16.png" +#define IMAGE_EXPIORTFRIEND ":/images/exportpeers_16x16.png" +#define IMAGE_CHAT ":/images/chat.png" +/* Images for Status icons */ +#define IMAGE_ONLINE ":/images/im-user.png" +#define IMAGE_OFFLINE ":/images/im-user-offline.png" + +/** Constructor */ +ExampleDialog::ExampleDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.peertreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( peertreeWidgetCostumPopupMenu( QPoint ) ) ); + + /* hide the Tree +/- */ + ui.peertreeWidget -> setRootIsDecorated( false ); + + /* Set header resize modes and initial section sizes */ + QHeaderView * _header = ui.peertreeWidget->header () ; + _header->setResizeMode (0, QHeaderView::Custom); + _header->setResizeMode (1, QHeaderView::Interactive); + _header->setResizeMode (2, QHeaderView::Interactive); + _header->setResizeMode (3, QHeaderView::Interactive); + _header->setResizeMode (4, QHeaderView::Interactive); + _header->setResizeMode (5, QHeaderView::Interactive); + _header->setResizeMode (6, QHeaderView::Interactive); + _header->setResizeMode (7, QHeaderView::Interactive); + _header->setResizeMode (8, QHeaderView::Interactive); + _header->setResizeMode (9, QHeaderView::Interactive); + _header->setResizeMode (10, QHeaderView::Interactive); + _header->setResizeMode (11, QHeaderView::Interactive); + + _header->resizeSection ( 0, 25 ); + _header->resizeSection ( 1, 100 ); + _header->resizeSection ( 2, 100 ); + _header->resizeSection ( 3, 100 ); + _header->resizeSection ( 4, 100 ); + _header->resizeSection ( 5, 200 ); + _header->resizeSection ( 6, 100 ); + _header->resizeSection ( 7, 100 ); + _header->resizeSection ( 8, 100 ); + _header->resizeSection ( 9, 100 ); + _header->resizeSection ( 10, 100 ); + + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +void ExampleDialog::peertreeWidgetCostumPopupMenu( QPoint point ) +{ + + QMenu contextMnu( this ); + QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); + + voteupAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Vote Up" ), this ); + connect( voteupAct , SIGNAL( triggered() ), this, SLOT( voteup() ) ); + + votedownAct = new QAction(QIcon(IMAGE_REMOVEFRIEND), tr( "Vote Down" ), this ); + connect( votedownAct , SIGNAL( triggered() ), this, SLOT( votedown() ) ); + + contextMnu.clear(); + contextMnu.addAction(voteupAct); + contextMnu.addSeparator(); + contextMnu.addAction(votedownAct); + contextMnu.exec( mevent->globalPos() ); +} + + + +/* get the list of peers from the RsIface. */ +void ExampleDialog::insertExample() +{ + +#if 0 + rsiface->lockData(); /* Lock Interface */ + + std::map::const_iterator it; + const std::map &friends = + rsiface->getFriendMap(); + + /* get a link to the table */ + QTreeWidget *peerWidget = ui.peertreeWidget; + + /* remove old items ??? */ + peerWidget->clear(); + peerWidget->setColumnCount(12); + + + + QList items; + for(it = friends.begin(); it != friends.end(); it++) + { + /* make a widget per friend */ + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + + /* add all the labels */ + /* First 5 (1-5) Key Items */ + /* () Status Icon */ + item -> setText(0, ""); + + /* (0) Status */ + item -> setText(1, QString::fromStdString( + it->second.statusString)); + + /* (1) Person */ + item -> setText(2, QString::fromStdString(it->second.name)); + + /* (2) Auto Connect */ + item -> setText(3, QString::fromStdString( + it->second.connectString)); + + /* (3) Trust Level */ + item -> setText(4, QString::fromStdString(it->second.trustString)); + /* (4) Peer Address */ + item -> setText(5, QString::fromStdString(it->second.peerAddress)); + + /* less important ones */ + /* () Last Contact */ + item -> setText(6, QString::fromStdString(it->second.lastConnect)); + + /* () Org */ + item -> setText(7, QString::fromStdString(it->second.org)); + /* () Location */ + item -> setText(8, QString::fromStdString(it->second.loc)); + /* () Country */ + item -> setText(9, QString::fromStdString(it->second.country)); + + + /* Hidden ones: */ + /* () RsCertId */ + { + std::ostringstream out; + out << it -> second.id; + item -> setText(10, QString::fromStdString(out.str())); + } + + /* () AuthCode */ + item -> setText(11, QString::fromStdString(it->second.authCode)); + + /* change background */ + int i; + if (it->second.statusString == "Online") + { + /* bright green */ + for(i = 1; i < 12; i++) + { + item -> setBackground(i,QBrush(Qt::green)); + item -> setIcon(0,(QIcon(IMAGE_ONLINE))); + } + } + else + { + if (it->second.lastConnect != "Never") + { + for(i = 1; i < 12; i++) + { + item -> setBackground(i,QBrush(Qt::lightGray)); + item -> setIcon(0,(QIcon(IMAGE_OFFLINE))); + } + } + else + { + for(i = 1; i < 12; i++) + { + item -> setBackground(i,QBrush(Qt::gray)); + item -> setIcon(0,(QIcon(IMAGE_OFFLINE))); + } + } + } + + + + /* add to the list */ + items.append(item); + } + + /* add the items in! */ + peerWidget->insertTopLevelItems(0, items); + + rsiface->unlockData(); /* UnLock Interface */ + + peerWidget->update(); /* update display */ +#endif +} + +QTreeWidgetItem *ExampleDialog::getCurrentLine() +{ + /* get the current, and extract the Id */ + + /* get a link to the table */ + QTreeWidget *peerWidget = ui.peertreeWidget; + QTreeWidgetItem *item = peerWidget -> currentItem(); + if (!item) + { + std::cerr << "Invalid Current Item" << std::endl; + return NULL; + } + + /* Display the columns of this item. */ + std::ostringstream out; + out << "CurrentPeerItem: " << std::endl; + + for(int i = 1; i < 6; i++) + { + QString txt = item -> text(i); + out << "\t" << i << ":" << txt.toStdString() << std::endl; + } + std::cerr << out.str(); + return item; +} + +void ExampleDialog::voteup() +{ + QTreeWidgetItem *c = getCurrentLine(); + std::cerr << "ExampleDialog::voteup()" << std::endl; +} + +void ExampleDialog::votedown() +{ + QTreeWidgetItem *c = getCurrentLine(); + std::cerr << "ExampleDialog::votedown()" << std::endl; + + /* need to get the input address / port */ + /* + std::string addr; + unsigned short port; + rsServer->FriendSetAddress(getPeerRsCertId(c), addr, port); + */ +} + + + diff --git a/retroshare-gui/src/gui/unfinished/ExampleDialog.h b/retroshare-gui/src/gui/unfinished/ExampleDialog.h new file mode 100644 index 000000000..4e9b5cd7b --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/ExampleDialog.h @@ -0,0 +1,70 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _EXAMPLEDIALOG_H +#define _EXAMPLEDIALOG_H + +#include + +#include "gui/mainpage.h" +#include "ui_ExampleDialog.h" + + +class ExampleDialog : public MainPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + ExampleDialog(QWidget *parent = 0); + /** Default Destructor */ + + void insertExample(); + +private slots: + /** Create the context popup menu and it's submenus */ + void peertreeWidgetCostumPopupMenu( QPoint point ); + + void voteup(); + void votedown(); + +private: + + /* Worker Functions */ + /* (1) Update Display */ + + /* (2) Utility Fns */ + QTreeWidgetItem *getCurrentLine(); + + /** Define the popup menus for the Context menu */ + QMenu* contextMnu; + /** Defines the actions for the context menu */ + QAction* voteupAct; + QAction* votedownAct; + + QTreeWidget *exampletreeWidget; + + /** Qt Designer generated object */ + Ui::ExampleDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/ExampleDialog.ui b/retroshare-gui/src/gui/unfinished/ExampleDialog.ui new file mode 100644 index 000000000..c77a700c6 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/ExampleDialog.ui @@ -0,0 +1,643 @@ + + ExampleDialog + + + + 0 + 0 + 436 + 261 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + 1 + + + 1 + + + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0 + + + 6 + + + + + + + + :/images/peers_16x16.png + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + + + + + + + Qt::CustomContextMenu + + + false + + + + 16 + 16 + + + + true + + + true + + + + # + + + + + Status + + + + + Person + + + + + Auto Connect + + + + + Trust Level + + + + + Peer Address + + + + + Last Contact + + + + + Organisation + + + + + Location + + + + + Country + + + + + Person Id + + + + + Auth Code + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/GamesDialog.cpp b/retroshare-gui/src/gui/unfinished/GamesDialog.cpp new file mode 100644 index 000000000..014784777 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/GamesDialog.cpp @@ -0,0 +1,587 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "GamesDialog.h" +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +const uint32_t GAME_LIST_TYPE = 0; +const uint32_t GAME_LIST_SERVER = 1; +const uint32_t GAME_LIST_STATUS = 2; +const uint32_t GAME_LIST_NAME = 3; +const uint32_t GAME_LIST_ID = 4; + +const uint32_t GAME_PEER_PLAYER = 0; +const uint32_t GAME_PEER_INVITE = 1; +const uint32_t GAME_PEER_INTEREST = 2; +const uint32_t GAME_PEER_PLAY = 3; +const uint32_t GAME_PEER_ID = 4; + + +/* Images for context menu icons */ +#define IMAGE_REMOVEFRIEND ":/images/removefriend16.png" +#define IMAGE_EXPIORTFRIEND ":/images/exportpeers_16x16.png" +#define IMAGE_CHAT ":/images/chat.png" +/* Images for Status icons */ +#define IMAGE_ONLINE ":/images/im-user.png" +#define IMAGE_OFFLINE ":/images/im-user-offline.png" + +/** Constructor */ +GamesDialog::GamesDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.gameTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( gameListPopupMenu( QPoint ) ) ); + connect( ui.peertreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( gamePeersPopupMenu( QPoint ) ) ); + + connect( ui.createButton, SIGNAL( pressed( void ) ), this, SLOT( createGame( void ) ) ); + connect( ui.deleteButton, SIGNAL( pressed( void ) ), this, SLOT( deleteGame( void ) ) ); + connect( ui.inviteButton, SIGNAL( pressed( void ) ), this, SLOT( inviteGame( void ) ) ); + connect( ui.playButton, SIGNAL( pressed( void ) ), this, SLOT( playGame ( void ) ) ); + + connect( ui.gameTreeWidget, SIGNAL( itemSelectionChanged( void ) ), this, SLOT( updateGameDetails( void ) ) ); + + /* hide the Tree +/- */ + ui.peertreeWidget -> setRootIsDecorated( false ); + + /* Set header resize modes and initial section sizes */ +// QHeaderView * _header = ui.peertreeWidget->header () ; +// _header->setResizeMode (0, QHeaderView::Custom); +// _header->setResizeMode (1, QHeaderView::Interactive); +// _header->setResizeMode (2, QHeaderView::Interactive); +// _header->setResizeMode (3, QHeaderView::Interactive); +// _header->setResizeMode (4, QHeaderView::Interactive); +// _header->setResizeMode (5, QHeaderView::Interactive); +// _header->setResizeMode (6, QHeaderView::Interactive); +// _header->setResizeMode (7, QHeaderView::Interactive); +// _header->setResizeMode (8, QHeaderView::Interactive); +// _header->setResizeMode (9, QHeaderView::Interactive); +// _header->setResizeMode (10, QHeaderView::Interactive); +// _header->setResizeMode (11, QHeaderView::Interactive); +// +// _header->resizeSection ( 0, 25 ); +// _header->resizeSection ( 1, 100 ); +// _header->resizeSection ( 2, 100 ); +// _header->resizeSection ( 3, 100 ); +// _header->resizeSection ( 4, 100 ); +// _header->resizeSection ( 5, 200 ); +// _header->resizeSection ( 6, 100 ); +// _header->resizeSection ( 7, 100 ); +// _header->resizeSection ( 8, 100 ); +// _header->resizeSection ( 9, 100 ); +// _header->resizeSection ( 10, 100 ); + + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + + +void GamesDialog::updateGameList() +{ + /* get the list of games from the server */ + std::list gameList; + std::list::iterator it; + + rsGameLauncher->getGameList(gameList); + + /* get a link to the table */ + QTreeWidget *gameWidget = ui.gameTreeWidget; + QTreeWidgetItem *oldSelect = getCurrentGame(); + QTreeWidgetItem *newSelect = NULL; + std::string oldId; + if (oldSelect) + { + oldId = (oldSelect->text(GAME_LIST_ID)).toStdString(); + } + + + QList items; + for(it = gameList.begin(); it != gameList.end(); it++) + { + /* make a widget per game */ + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + std::string serverName = rsPeers->getPeerName(it->serverId); + item -> setText(GAME_LIST_TYPE, QString::fromStdString(it->gameType)); + item -> setText(GAME_LIST_SERVER, QString::fromStdString(serverName)); + item -> setText(GAME_LIST_NAME, QString::fromStdWString(it->gameName)); + item -> setText(GAME_LIST_STATUS, QString::fromStdString(it->status)); + item -> setText(GAME_LIST_ID, QString::fromStdString(it->gameId)); + + if ((oldSelect) && (oldId == it->gameId)) + { + newSelect = item; + } + + /* add to the list */ + items.append(item); + } + + gameWidget->clear(); + gameWidget->setColumnCount(5); + + /* add the items in! */ + gameWidget->insertTopLevelItems(0, items); + if (newSelect) + { + gameWidget->setCurrentItem(newSelect); + } + gameWidget->update(); /* update display */ + + updateGameDetails(); +} + +QTreeWidgetItem *GamesDialog::getCurrentGame() +{ + return ui.gameTreeWidget->currentItem(); +} + +QTreeWidgetItem *GamesDialog::getCurrentPeer() +{ + return ui.peertreeWidget->currentItem(); +} + +void GamesDialog::updateGameDetails() +{ + /* get the list of games from the server */ + RsGameDetail detail; + + /* get a link to the table */ + QTreeWidget *detailWidget = ui.peertreeWidget; + QTreeWidgetItem *gameSelect = getCurrentGame(); + if (!gameSelect) + { + /* clear and finished */ + detailWidget->clear(); + //detailWidget->update(); + mCurrentGame = ""; + mCurrentGameStatus = ""; + return; + } + + std::string gameId = (gameSelect->text(GAME_LIST_ID)).toStdString(); + + rsGameLauncher->getGameDetail(gameId, detail); + + QTreeWidgetItem *oldSelect = getCurrentPeer(); + QTreeWidgetItem *newSelect = NULL; + std::string oldId; + if (mCurrentGame != gameId) + oldSelect = NULL; /* if we've changed game -> clear select */ + + if (oldSelect) + { + oldId = (oldSelect->text(GAME_PEER_ID)).toStdString(); + } + + QList items; + /* layout depends on the game status */ + std::map::iterator it; + for(it = detail.gamers.begin(); it != detail.gamers.end(); it++) + { + bool showPeer = false; + if ((detail.status == "Setup") || + (detail.status == "Invite")) + { + showPeer = true; + } + else if ((detail.status == "Confirm") || + (detail.status == "Ready")) + { + if ((it->second).invite == true) + showPeer = true; + } + else if (detail.status == "Playing") + { + if ((it->second).play == true) + showPeer = true; + } + + /* display */ + if (showPeer) + { + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + std::string name = rsPeers->getPeerName(it->second.id); + if (it->second.id == rsPeers->getOwnId()) + { + name = "Yourself"; + } + + item -> setText(GAME_PEER_PLAYER, QString::fromStdString(name)); + + if (it->second.invite) + item -> setText(GAME_PEER_INVITE, "Yes"); + else + item -> setText(GAME_PEER_INVITE, "No"); + + if (it->second.interested) + item -> setText(GAME_PEER_INTEREST, "Yes"); + else + item -> setText(GAME_PEER_INTEREST, "No"); + + if (it->second.play) + item -> setText(GAME_PEER_PLAY, "Yes"); + else + item -> setText(GAME_PEER_PLAY, "No"); + + /* add a checkItem here */ + //item -> setText(GAME_PEER_PLAY, "Maybe"); + item -> setText(GAME_PEER_ID, QString::fromStdString(it->second.id)); + + if ((oldSelect) && (oldId == it->first)) + { + newSelect = item; + } + + /* add to the list */ + items.append(item); + } + } + if (detail.status == "Setup") + { + std::list friends; + std::list::iterator fit; + + rsPeers->getOnlineList(friends); + + for(fit = friends.begin(); fit != friends.end(); fit++) + { + if (detail.gamers.end() != detail.gamers.find(*fit)) + { + /* already present */ + continue; + } + + std::string name = rsPeers->getPeerName(*fit); + + /* make a widget per friend */ + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + item -> setText(GAME_PEER_PLAYER, QString::fromStdString(name)); + item -> setText(GAME_PEER_INVITE, "No"); + item -> setText(GAME_PEER_INTEREST, "?"); + item -> setText(GAME_PEER_PLAY, "?"); + item -> setText(GAME_PEER_ID, QString::fromStdString(*fit)); + + if ((oldSelect) && (oldId == *fit)) + { + newSelect = item; + } + + /* add to the list */ + items.append(item); + } + } + + detailWidget->clear(); + detailWidget->setColumnCount(5); + + /* add the items in! */ + detailWidget->insertTopLevelItems(0, items); + if (newSelect) + { + detailWidget->setCurrentItem(newSelect); + } + detailWidget->update(); /* update display */ + + /* store the game Id */ + mCurrentGame = gameId; + mCurrentGameStatus = detail.status; +} + + + +void GamesDialog::gameListPopupMenu( QPoint point ) +{ + + QMenu contextMnu( this ); + QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); + + QAction *deleteAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Cancel Game" ), this ); + connect( deleteAct , SIGNAL( triggered() ), this, SLOT( deleteGame() ) ); + + contextMnu.clear(); + contextMnu.addSeparator(); + contextMnu.addAction(deleteAct); + contextMnu.addSeparator(); + contextMnu.exec( mevent->globalPos() ); +} + + +void GamesDialog::gamePeersPopupMenu( QPoint point ) +{ + + QMenu contextMnu( this ); + QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); + + if (mCurrentGame == "") + { + return; + } + + if (mCurrentGameStatus == "Setup") + { + /* invite */ + /* uninvite */ + + QAction *inviteAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Add to Invite List" ), this ); + connect( inviteAct , SIGNAL( triggered() ), this, SLOT( invitePeer() ) ); + QAction *uninviteAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Remove from Invite List" ), this ); + connect( uninviteAct , SIGNAL( triggered() ), this, SLOT( uninvitePeer() ) ); + + contextMnu.clear(); + contextMnu.addAction(inviteAct); + contextMnu.addAction(uninviteAct); + contextMnu.exec( mevent->globalPos() ); + } + else if (mCurrentGameStatus == "Invite") + { + /* invite */ + /* uninvite */ + + QAction *inviteAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Interested in Playing" ), this ); + connect( inviteAct , SIGNAL( triggered() ), this, SLOT( interested() ) ); + QAction *uninviteAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Not Interested in Game" ), this ); + connect( uninviteAct , SIGNAL( triggered() ), this, SLOT( uninterested() ) ); + + contextMnu.clear(); + contextMnu.addAction(inviteAct); + contextMnu.addAction(uninviteAct); + contextMnu.exec( mevent->globalPos() ); + } + else if (mCurrentGameStatus == "Invite") + { + /* invite */ + /* uninvite */ + + QAction *interestedAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Interested in Playing" ), this ); + connect( interestedAct , SIGNAL( triggered() ), this, SLOT( interested() ) ); + QAction *uninterestedAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Not Interested" ), this ); + connect( uninterestedAct , SIGNAL( triggered() ), this, SLOT( uninterested() ) ); + + contextMnu.clear(); + contextMnu.addAction(interestedAct); + contextMnu.addAction(uninterestedAct); + contextMnu.exec( mevent->globalPos() ); + } + else if (mCurrentGameStatus == "Confirm") + { + /* invite */ + /* uninvite */ + + QAction *inviteAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Confirm Peer in Game" ), this ); + connect( inviteAct , SIGNAL( triggered() ), this, SLOT( confirmPeer() ) ); + QAction *uninviteAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Remove Peer from Game" ), this ); + connect( uninviteAct , SIGNAL( triggered() ), this, SLOT( unconfirmPeer() ) ); + + contextMnu.clear(); + contextMnu.addAction(inviteAct); + contextMnu.addAction(uninviteAct); + contextMnu.exec( mevent->globalPos() ); + } + else if (mCurrentGameStatus == "Ready") + { + /* invite */ + /* uninvite */ + + QAction *interestedAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Interested in Game" ), this ); + connect( interestedAct , SIGNAL( triggered() ), this, SLOT( interested() ) ); + QAction *uninterestedAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Not Interested" ), this ); + connect( uninterestedAct , SIGNAL( triggered() ), this, SLOT( uninterested() ) ); + + contextMnu.clear(); + contextMnu.addAction(interestedAct); + contextMnu.addAction(uninterestedAct); + contextMnu.exec( mevent->globalPos() ); + } + else /* PLAYING */ + { + /* no menu for playing */ + QAction *quitAct = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Quit Game" ), this ); + contextMnu.clear(); + contextMnu.addAction(quitAct); + contextMnu.exec( mevent->globalPos() ); + } + + return; +} + + + +void GamesDialog::createGame() +{ + /* extract the Game Type and number of players from GUI */ + std::wstring gameName = ui.gameNameEdit->text().toStdWString(); + uint32_t gameType = ui.gameComboBox->currentIndex(); + bool addAll = ui.checkInviteAll->isChecked(); + std::list playerList; + + std::string gameId = rsGameLauncher->createGame(gameType, gameName); + + if (addAll) + { + std::list friends; + std::list::iterator fit; + + rsPeers->getOnlineList(friends); + for(fit = friends.begin(); fit != friends.end(); fit++) + { + rsGameLauncher -> invitePeer(gameId, *fit); + } + } + + /* call to the GameControl */ + std::string tmpName(gameName.begin(), gameName.end()); + std::cerr << "GamesDialog::createGame() Game: " << gameType << " name: " << tmpName; + std::cerr << std::endl; + + updateGameList(); +} + +void GamesDialog::deleteGame() +{ + QTreeWidgetItem *gameSelect = getCurrentGame(); + if (!gameSelect) + return; + + std::string gameId = (gameSelect->text(GAME_LIST_ID)).toStdString(); + rsGameLauncher->deleteGame(gameId); + + updateGameList(); +} + + +void GamesDialog::inviteGame() +{ + QTreeWidgetItem *gameSelect = getCurrentGame(); + if (!gameSelect) + return; + + std::string gameId = (gameSelect->text(GAME_LIST_ID)).toStdString(); + rsGameLauncher->inviteGame(gameId); + + updateGameList(); +} + + +void GamesDialog::playGame() +{ + QTreeWidgetItem *gameSelect = getCurrentGame(); + if (!gameSelect) + return; + + std::string gameId = (gameSelect->text(GAME_LIST_ID)).toStdString(); + rsGameLauncher->playGame(gameId); + + updateGameList(); +} + +void GamesDialog::invitePeer() +{ + QTreeWidgetItem *peerSelect = getCurrentPeer(); + if (!peerSelect) + return; + + std::string peerId = (peerSelect->text(GAME_PEER_ID)).toStdString(); + rsGameLauncher->invitePeer(mCurrentGame, peerId); + updateGameDetails(); +} + + +void GamesDialog::uninvitePeer() +{ + QTreeWidgetItem *peerSelect = getCurrentPeer(); + if (!peerSelect) + return; + + std::string peerId = (peerSelect->text(GAME_PEER_ID)).toStdString(); + rsGameLauncher->uninvitePeer(mCurrentGame, peerId); + updateGameDetails(); +} + + +void GamesDialog::confirmPeer() +{ + QTreeWidgetItem *peerSelect = getCurrentPeer(); + if (!peerSelect) + return; + + std::string peerId = (peerSelect->text(GAME_PEER_ID)).toStdString(); + rsGameLauncher->confirmPeer(mCurrentGame, peerId); + updateGameDetails(); +} + + +void GamesDialog::unconfirmPeer() +{ + QTreeWidgetItem *peerSelect = getCurrentPeer(); + if (!peerSelect) + return; + + std::string peerId = (peerSelect->text(GAME_PEER_ID)).toStdString(); + rsGameLauncher->unconfirmPeer(mCurrentGame, peerId); + updateGameDetails(); +} + + +void GamesDialog::interested() +{ + QTreeWidgetItem *gameSelect = getCurrentGame(); + if (!gameSelect) + return; + + std::string gameId = (gameSelect->text(GAME_LIST_ID)).toStdString(); + rsGameLauncher->interestedPeer(gameId); + updateGameDetails(); +} + + +void GamesDialog::uninterested() +{ + QTreeWidgetItem *gameSelect = getCurrentGame(); + if (!gameSelect) + return; + + std::string gameId = (gameSelect->text(GAME_LIST_ID)).toStdString(); + rsGameLauncher->uninterestedPeer(gameId); + updateGameDetails(); +} + + diff --git a/retroshare-gui/src/gui/unfinished/GamesDialog.h b/retroshare-gui/src/gui/unfinished/GamesDialog.h new file mode 100644 index 000000000..e83075f17 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/GamesDialog.h @@ -0,0 +1,80 @@ +/**************************************************************** + * RetroShareGui is distributed under the following license: + * + * Copyright (C) 2007-2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _GAMESDIALOG_H +#define _GAMESDIALOG_H + +#include "gui/mainpage.h" +#include "ui_GamesDialog.h" + +class GamesDialog : public MainPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + GamesDialog(QWidget *parent = 0); + /** Default Destructor */ + + void insertExample(); + +private slots: + /** Create the context popup menu and it's submenus */ + void gameListPopupMenu( QPoint point ); + void gamePeersPopupMenu( QPoint point ); + + void createGame(); + void deleteGame(); + void inviteGame(); + void playGame(); + + void invitePeer(); + void uninvitePeer(); + void confirmPeer(); + void unconfirmPeer(); + + void interested(); + void uninterested(); + + void updateGameList(); + void updateGameDetails(); + /*** + * + */ + +private: + + + /***** UTILS *******/ +QTreeWidgetItem *getCurrentGame(); +QTreeWidgetItem *getCurrentPeer(); + + /* Data */ +std::string mCurrentGame; +std::string mCurrentGameStatus; +private: + + /** Qt Designer generated object */ + Ui::GamesDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/GamesDialog.ui b/retroshare-gui/src/gui/unfinished/GamesDialog.ui new file mode 100644 index 000000000..074504d9d --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/GamesDialog.ui @@ -0,0 +1,333 @@ + + GamesDialog + + + + 0 + 0 + 598 + 526 + + + + Form + + + + 0 + + + 6 + + + 0 + + + 0 + + + + + + + + :/images/package_games1.png + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 431 + 20 + + + + + + + + + + + + + + + 10 + + + + Game: + + + + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + + + + + + + + + 10 + + + + Title / Comment + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 10 + + + + Create New Game + + + + :/images/kbackgammon.png:/images/kbackgammon.png + + + + + + + + 10 + + + + Invite All Friends + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Vertical + + + + Qt::CustomContextMenu + + + + Game Type + + + + + Server + + + + + Status + + + + + Comment + + + + + GameID + + + + + + Qt::CustomContextMenu + + + + Player + + + + + Invite + + + + + Interested + + + + + Accept + + + + + + + + + + + + 10 + + + + Delete + + + + :/images/reset.png:/images/reset.png + + + + + + + + 10 + + + + Invite + + + + :/images/dadd.png:/images/add_user24.png + + + + + + + + 10 + + + + Move Player + + + + :/images/up.png:/images/up.png + + + + + + + + 10 + + + + Move Player + + + + :/images/down_24x24.png:/images/down_24x24.png + + + + + + + + 10 + + + + Play Game + + + + :/images/startall.png:/images/startall.png + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/LibraryDialog.cpp b/retroshare-gui/src/gui/unfinished/LibraryDialog.cpp new file mode 100644 index 000000000..057b25404 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/LibraryDialog.cpp @@ -0,0 +1,150 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008, defnax + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#include "rshare.h" +#include "LibraryDialog.h" + +#include "ShareManager.h" + +#include "util/RsAction.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Images for context menu icons */ +#define IMAGE_DOWNLOAD ":/images/download16.png" +#define IMAGE_PLAY ":/images/start.png" +#define IMAGE_HASH_BUSY ":/images/settings.png" +#define IMAGE_HASH_DONE ":/images/friendsfolder24.png" +#define IMAGE_MSG ":/images/message-mail.png" +#define IMAGE_ATTACHMENT ":/images/attachment.png" +#define IMAGE_FRIEND ":/images/peers_16x16.png" +#define IMAGE_PROGRESS ":/images/browse-looking.gif" +#define IMAGE_LIBRARY ":/images/library.png" + + +/** Constructor */ +LibraryDialog::LibraryDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect(ui.shareFiles_btn,SIGNAL(clicked()),this, SLOT(CallShareFilesBtn_library())); + //connect(ui.tileView_btn_library,SIGNAL(clicked()),this, SLOT(CallTileViewBtn_library())); + //connect(ui.showDetails_btn_library,SIGNAL(clicked()),this, SLOT(CallShowDetailsBtn_library())); + //connect(ui.createAlbum_btn_library,SIGNAL(clicked()),this, SLOT(CallCreateAlbumBtn_library())); + //connect(ui.deleteAlbum_btn_library,SIGNAL(clicked()),this, SLOT(CallDeleteAlbumBtn_library())); + //connect(ui.find_btn_library,SIGNAL(clicked()),this, SLOT(CallFindBtn_library())); + + //Load the library + fileSystemModelLibraryFolders.setFilter(QDir::AllDirs|QDir::NoDotAndDotDot); + fileSystemModelLibraryFolders.setRootPath(Settings.Library.Shares.join(" ")); + + ui.treeViewLibraryNavigatorFolders->setModel(&fileSystemModelLibraryFolders); + + + /*QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + timer->start(1000);*/ + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + + + +void LibraryDialog::copyFile() +{ + +} + +void LibraryDialog::DeleteFile() +{ + +} + +void LibraryDialog::RenameFile() +{ + +} + +void LibraryDialog::StopRename() +{ + +} + + +void LibraryDialog::CallShareFilesBtn_library() +{ + ShareManager::showYourself(); +} + +void LibraryDialog::CallTileViewBtn_library() +{ + //QMessageBox::information(this, tr("RetroShare"),tr("Will be Introducing this .. soon- tilesView in Library")); +} + +void LibraryDialog::CallShowDetailsBtn_library() +{ + //QMessageBox::information(this, tr("RetroShare"),tr("Will be Introducing this .. soon- showdetails in Library")); +} + +void LibraryDialog::CallCreateAlbumBtn_library() +{ + //QMessageBox::information(this, tr("RetroShare"),tr("Will be Introducing this .. soon- Create Album in Library")); +} + +void LibraryDialog::CallDeleteAlbumBtn_library() +{ + //QMessageBox::information(this, tr("RetroShare"),tr("Will be Introducing this .. soon- Delete Album in Library")); +} + +void LibraryDialog::CallFindBtn_library() +{ + +} + +void LibraryDialog:: player() +{ + + +} + +void LibraryDialog::browseFile() + { + + } diff --git a/retroshare-gui/src/gui/unfinished/LibraryDialog.h b/retroshare-gui/src/gui/unfinished/LibraryDialog.h new file mode 100644 index 000000000..8d3ea2e60 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/LibraryDialog.h @@ -0,0 +1,76 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008, defnax + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _SHAREDFILESDIALOG_H +#define _SHAREDFILESDIALOG_H + +#include + +#include "gui/mainpage.h" +#include "ui_LibraryDialog.h" + +#include +#include "gui/RemoteDirModel.h" + +class LibraryDialog : public MainPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + LibraryDialog(QWidget *parent = 0); + /** Default Destructor */ + + +private slots: + + void PopulateList(); + + void CallShareFilesBtn_library(); + void CallTileViewBtn_library(); + void CallShowDetailsBtn_library(); + void CallCreateAlbumBtn_library(); + void CallDeleteAlbumBtn_library(); + void CallFindBtn_library(); + + void browseFile(); + void player(); + void PlayFrmList(); + void copyFile(); + void DeleteFile(); + void RenameFile(); + void StopRename(); + + +signals: + + +private: + + + /** Qt Designer generated object */ + Ui::LibraryDialog ui; + + +}; + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/LibraryDialog.ui b/retroshare-gui/src/gui/unfinished/LibraryDialog.ui new file mode 100644 index 000000000..da20212c0 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/LibraryDialog.ui @@ -0,0 +1,810 @@ + + + Form + + + + 0 + 0 + 703 + 527 + + + + Form + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + + 200 + 16777215 + + + + QFrame { + background-color: rgb(199, 202, 255); +} + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 0 + + + + + 4 + + + 4 + + + 4 + + + + + + 0 + 0 + + + + + 16777215 + 25 + + + + Manage the physical folders in your library. + + + + + + Share Files + + + + :/Actions/Graphics/Actions/SharedFolders.png:/Actions/Graphics/Actions/SharedFolders.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + + QTabWidget::pane { /* The tab widget frame */ + border-top: 2px solid #C2C7CB; + } + + QTabWidget::tab-bar { + left: 5px; /* move to the right by 5px */ + } + + /* Style the tab using the tab sub-control. Note that + it reads QTabBar _not_ QTabWidget */ + QTabBar::tab { + background:transparent; + border: 2px solid transparent; + min-width: 8ex; + padding: 2px; + } + + QTabBar::tab:selected, QTabBar::tab:hover { + border: 1px solid rgb(78, 96, 255); + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #dadbde, stop: 1 #f6f7fa); + } + + QTabBar::tab:selected { + border: 1px solid rgb(78, 96, 255); + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #dadbde, stop: 1 #f6f7fa); + } + + + 1 + + + + + :/Actions/Graphics/Actions/OpenDownloadFolder.png:/Actions/Graphics/Actions/OpenDownloadFolder.png + + + Shares + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QTreeView { + background-color: rgb(255, 255, 255); +} + + + false + + + + + + + + 0 + 0 + + + + QAbstractItemView { + background-color: rgb(255, 255, 255); +} + + + + + + + + + :/Actions/Graphics/Actions/Libary.png:/Actions/Graphics/Actions/Libary.png + + + Organiser + + + + 0 + + + + + + 0 + 0 + + + + QTreeWidget { + background-color: rgb(255, 255, 255); +} + + + false + + + + Organiser + + + + + All Files + + + + :/Actions/Graphics/Actions/Libary.png:/Actions/Graphics/Actions/Libary.png + + + + + Favorites + + + + :/Controls/Graphics/Controls/Favorites.png:/Controls/Graphics/Controls/Favorites.png + + + + + Ghost Files + + + + :/Controls/Graphics/Controls/GhostFiles.png:/Controls/Graphics/Controls/GhostFiles.png + + + + + My Applications + + + + :/Controls/Graphics/Controls/MyApplications.png:/Controls/Graphics/Controls/MyApplications.png + + + + All Applications + + + + + + My eBooks + + + + :/Controls/Graphics/Controls/MyeBooks.png:/Controls/Graphics/Controls/MyeBooks.png + + + + All eBooks + + + + + + My Documents + + + + :/Controls/Graphics/Controls/MyDocuments.png:/Controls/Graphics/Controls/MyDocuments.png + + + + All Documents + + + + + + My Images + + + + :/Controls/Graphics/Controls/MyImages.png:/Controls/Graphics/Controls/MyImages.png + + + + All Images + + + + + + My Music + + + + :/Controls/Graphics/Controls/MyMusic.png:/Controls/Graphics/Controls/MyMusic.png + + + + All Music + + + + + By Album + + + + + By Artist + + + + + By Genre + + + + + + My Video + + + + :/Actions/Graphics/Actions/Media.png:/Actions/Graphics/Actions/Media.png + + + + All Video + + + + + Films + + + + + Music Videos + + + + + TV Shows + + + + + + + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + 0 + + + + + 0 + + + 0 + + + + + + 0 + + + 0 + + + + + + + Qt::Horizontal + + + QSizePolicy::MinimumExpanding + + + + 40 + 20 + + + + + + + + + 250 + 16777215 + + + + + + + + Search + + + + :/Actions/Graphics/Actions/Search.png:/Actions/Graphics/Actions/Search.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + + + + + + QLayout::SetDefaultConstraint + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 143 + 32 + + + + + + + + Tile View + + + + :/Controls/Graphics/Controls/TileView.png:/Controls/Graphics/Controls/TileView.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + Qt::NoArrow + + + + + + + Show Details + + + + :/Controls/Graphics/Controls/ShowDetails.png:/Controls/Graphics/Controls/ShowDetails.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + 240 + 35 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/Actions/Graphics/Actions/OpenDownloadFolder.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:10pt; font-weight:600;">Exploring My Shared Folders</span></p></body></html> + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + QLayout::SetDefaultConstraint + + + 0 + + + 0 + + + + + + 240 + 35 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/Icons/Resource/Folder Libary_32.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:10pt; font-weight:600;">Exploring With The Organiser</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 143 + 32 + + + + + + + + Tile View + + + + :/Controls/Graphics/Controls/TileView.png:/Controls/Graphics/Controls/TileView.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Show Details + + + + :/Controls/Graphics/Controls/ShowDetails.png:/Controls/Graphics/Controls/ShowDetails.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + 0 + 23 + + + + background-color: rgb(11, 27, 99); + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + + + + + + + + + + 0 + + + 0 + + + + + + + Create Album + + + + :/Controls/Graphics/Controls/Add.png:/Controls/Graphics/Controls/Add.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Delete Album + + + + :/Controls/Graphics/Controls/Remove.png:/Controls/Graphics/Controls/Remove.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::MinimumExpanding + + + + 40 + 20 + + + + + + + + + 250 + 16777215 + + + + + + + + Search + + + + :/Actions/Graphics/Actions/Search.png:/Actions/Graphics/Actions/Search.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/PhotoDialog.cpp b/retroshare-gui/src/gui/unfinished/PhotoDialog.cpp new file mode 100644 index 000000000..0b7b7d985 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/PhotoDialog.cpp @@ -0,0 +1,608 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "PhotoDialog.h" +#include "PhotoShow.h" +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Images for context menu icons */ +#define IMAGE_REMOVEFRIEND ":/images/removefriend16.png" +#define IMAGE_EXPIORTFRIEND ":/images/exportpeers_16x16.png" +#define IMAGE_REMOVE ":/images/cancel.png" +#define IMAGE_CHAT ":/images/chat.png" +/* Images for Status icons */ +#define IMAGE_PEER ":/images/user/identity16.png" +#define IMAGE_PHOTOS ":/images/image16.png" + + +#define PHOTO_ICON_SIZE 90 + + +#define PHOTO_PEER_COL_NAME 0 +#define PHOTO_PEER_COL_SHOW 1 +#define PHOTO_PEER_COL_PHOTO 2 +#define PHOTO_PEER_COL_PID 3 +#define PHOTO_PEER_COL_SID 4 +#define PHOTO_PEER_COL_PHOTOID 5 + +#define PHOTO_LIST_COL_PHOTO 0 +#define PHOTO_LIST_COL_NAME 1 +#define PHOTO_LIST_COL_COMMENT 2 +#define PHOTO_LIST_COL_DATE 3 +#define PHOTO_LIST_COL_LOCATION 4 +#define PHOTO_LIST_COL_SIZE 5 +#define PHOTO_LIST_COL_PEERID 6 +#define PHOTO_LIST_COL_PHOTOID 7 + +/****** + * #define PHOTO_DEBUG 1 + *****/ + + + +/** Constructor */ +PhotoDialog::PhotoDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + connect( ui.peerTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( peerTreeWidgetCustomPopupMenu( QPoint ) ) ); + connect( ui.photoTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( photoTreeWidgetCustomPopupMenu( QPoint ) ) ); + + connect( ui.peerTreeWidget, SIGNAL( currentItemChanged ( QTreeWidgetItem * , QTreeWidgetItem * ) ), this, SLOT( updatePhotoList( ) ) ); + + connect( ui.photoTreeWidget, SIGNAL( itemDoubleClicked ( QTreeWidgetItem * , int ) ), this, SLOT( showPhoto( QTreeWidgetItem *, int ) ) ); + connect( ui.addButton, SIGNAL( clicked( ) ), this, SLOT( addPhotos( ) ) ); + connect( ui.expandButton, SIGNAL(clicked()), this, SLOT(togglefileview())); + + /* hide the Tree +/- */ + ui.photoTreeWidget -> setRootIsDecorated( false ); + + QSize iconSize(PHOTO_ICON_SIZE,PHOTO_ICON_SIZE); + ui.photoTreeWidget->setIconSize(iconSize); + + /* Set header resize modes and initial section sizes */ + QHeaderView * ptw_header = ui.peerTreeWidget->header () ; + ptw_header->setResizeMode (0, QHeaderView::Interactive); + + ptw_header->resizeSection ( 0, 175 ); + + + + /* Set a GUI update timer - much cleaner than + * doing everything through the notify agent + */ + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + timer->start(1000); + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif + +} + +void PhotoDialog::checkUpdate() +{ + /* update */ + if (!rsPhoto) + return; + + if (rsPhoto->updated()) + { + insertShowLists(); + } + + return; +} + + +void PhotoDialog::peerTreeWidgetCustomPopupMenu( QPoint point ) +{ + + QMenu contextMnu( this ); + QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); + + QAction *ins = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Insert Show Lists" ), this ); + connect( ins , SIGNAL( triggered() ), this, SLOT( insertShowLists() ) ); + + contextMnu.clear(); + contextMnu.addAction(ins); + contextMnu.exec( mevent->globalPos() ); +} + +void PhotoDialog::photoTreeWidgetCustomPopupMenu( QPoint point ) +{ + + QMenu contextMnu( this ); + QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); + + QAction *openphotoAct = new QAction(QIcon(":/images/openimage.png"), tr( "Open" ), this ); + openphotoAct->setShortcut(Qt::CTRL + Qt::Key_O); + connect( openphotoAct , SIGNAL( triggered(QTreeWidgetItem * , int) ), this, SLOT( showPhoto( QTreeWidgetItem *, int ) ) ); + + QAction *removephotoAct = new QAction(QIcon(IMAGE_REMOVE), tr( "Remove" ), this ); + removephotoAct->setShortcut(Qt::Key_Delete); + connect( removephotoAct , SIGNAL( triggered() ), this, SLOT( removePhoto() ) ); + + rateExcellenAct = new QAction(QIcon(":/images/rate-5.png"), tr("Excellent"), this); + rateExcellenAct->setShortcut(Qt::CTRL + Qt::Key_5); + connect(rateExcellenAct, SIGNAL(triggered()), this, SLOT(rateExcellent())); + + rateGoodAct = new QAction(QIcon(":/images/rate-4.png"), tr("Good"), this); + rateGoodAct->setShortcut(Qt::CTRL + Qt::Key_4); + connect(rateGoodAct, SIGNAL(triggered()), this, SLOT(rateGood())); + + rateAverageAct = new QAction(QIcon(":/images/rate-3.png"), tr("Average"), this); + rateAverageAct->setShortcut(Qt::CTRL + Qt::Key_3); + connect(rateAverageAct, SIGNAL(triggered()), this, SLOT(rateAvarge())); + + rateBelowAvarageAct = new QAction(QIcon(":/images/rate-2.png"), tr("Below avarage"), this); + rateBelowAvarageAct->setShortcut(Qt::CTRL + Qt::Key_2); + connect(rateBelowAvarageAct, SIGNAL(triggered()), this, SLOT(rateBelowAverage())); + + rateBadAct = new QAction(QIcon(":/images/rate-1.png"), tr("Bad"), this); + rateBadAct->setShortcut(Qt::CTRL + Qt::Key_1); + connect(rateBadAct, SIGNAL(triggered()), this, SLOT(rateBad())); + + rateUnratedAct = new QAction(tr("Unrated"), this); + rateUnratedAct->setShortcut(Qt::CTRL + Qt::Key_0); + connect(rateUnratedAct, SIGNAL(triggered()), this, SLOT(rateUnrated())); + + QMenu *ratingMenu = new QMenu(tr("Rating"), this); + ratingMenu->setIcon(QIcon(":/images/rating.png")); + ratingMenu->addAction(rateExcellenAct); + ratingMenu->addAction(rateGoodAct); + ratingMenu->addAction(rateAverageAct); + ratingMenu->addAction(rateBelowAvarageAct); + ratingMenu->addAction(rateBadAct); + ratingMenu->addAction(rateUnratedAct); + + contextMnu.clear(); + contextMnu.addAction(openphotoAct); + contextMnu.addSeparator(); + contextMnu.addMenu( ratingMenu); + contextMnu.addSeparator(); + contextMnu.addAction(removephotoAct); + contextMnu.exec( mevent->globalPos() ); +} + +void PhotoDialog::togglefileview() +{ + /* if msg header visible -> hide by changing splitter + * three widgets... + */ + + QList sizeList = ui.photoSplitter->sizes(); + QList::iterator it; + + int listSize = 0; + int msgSize = 0; + int i = 0; + + for(it = sizeList.begin(); it != sizeList.end(); it++, i++) + { + if (i == 0) + { + listSize = (*it); + } + else if (i == 1) + { + msgSize = (*it); + } + } + + int totalSize = listSize + msgSize; + + bool toShrink = true; + if (msgSize < (int) totalSize / 10) + { + toShrink = false; + } + + QList newSizeList; + if (toShrink) + { + newSizeList.push_back(totalSize); + newSizeList.push_back(0); + ui.expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + ui.expandButton->setToolTip("Expand"); + } + else + { + /* no change */ + int nlistSize = (totalSize / 2); + int nMsgSize = (totalSize / 2); + newSizeList.push_back(nlistSize); + newSizeList.push_back(nMsgSize); + ui.expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + ui.expandButton->setToolTip("Hide"); + } + + ui.photoSplitter->setSizes(newSizeList); +} + +void PhotoDialog::insertShowLists() +{ + /* clear it all */ + ui.peerTreeWidget->clear(); + + /* iterate through peers */ + addShows(rsPeers->getOwnId()); + + std::list ids; + std::list::iterator it; + rsPeers->getFriendList(ids); + + for(it = ids.begin(); it != ids.end(); it++) + { + addShows(*it); + } +} + +void PhotoDialog::addShows(std::string id) +{ + std::list allPhotos; + std::list showIds; + std::list::iterator it; + + QTreeWidgetItem *peerItem = new QTreeWidgetItem((QTreeWidget*)0); + peerItem->setText(PHOTO_PEER_COL_NAME, QString::fromStdString(rsPeers->getPeerName(id))); + peerItem->setText(PHOTO_PEER_COL_PID, QString::fromStdString(id)); + peerItem->setText(PHOTO_PEER_COL_SID, ""); + peerItem->setText(PHOTO_PEER_COL_PHOTOID, ""); + peerItem->setIcon(0,(QIcon(IMAGE_PEER))); + + ui.peerTreeWidget->insertTopLevelItem(0, peerItem); + + QTreeWidgetItem *allItem = new QTreeWidgetItem((QTreeWidget*)0); + allItem->setText(PHOTO_PEER_COL_SHOW, "All Photos"); + allItem->setText(PHOTO_PEER_COL_PID, QString::fromStdString(id)); + allItem->setText(PHOTO_PEER_COL_SID, ""); + allItem->setText(PHOTO_PEER_COL_PHOTOID, ""); + allItem->setIcon(0,(QIcon(IMAGE_PHOTOS))); + + peerItem->addChild(allItem); + + rsPhoto->getPhotoList(id, allPhotos); + rsPhoto->getShowList(id, showIds); + + for(it = allPhotos.begin(); it != allPhotos.end(); it++) + { + QTreeWidgetItem *photoItem = new QTreeWidgetItem((QTreeWidget*)0); + photoItem->setText(PHOTO_PEER_COL_PHOTO, QString::fromStdString(*it)); + + photoItem->setText(PHOTO_PEER_COL_PID, QString::fromStdString(id)); + photoItem->setText(PHOTO_PEER_COL_SID, ""); + photoItem->setText(PHOTO_PEER_COL_PHOTOID, QString::fromStdString(*it)); + photoItem->setIcon(0,(QIcon(IMAGE_PHOTOS))); + + allItem->addChild(photoItem); + } + + + for(it = showIds.begin(); it != showIds.end(); it++) + { + /* get details */ + RsPhotoShowDetails detail; + rsPhoto->getShowDetails(id, *it, detail); + + QTreeWidgetItem *showItem = new QTreeWidgetItem((QTreeWidget*)0); + showItem->setText(PHOTO_PEER_COL_SHOW, QString::fromStdString(*it)); + + showItem->setText(PHOTO_PEER_COL_PID, QString::fromStdString(id)); + showItem->setText(PHOTO_PEER_COL_SID, QString::fromStdString(*it)); + showItem->setText(PHOTO_PEER_COL_PHOTOID, ""); + + peerItem->addChild(showItem); + + std::list::iterator sit; + for(sit = detail.photos.begin(); sit != detail.photos.end(); sit++) + { + QTreeWidgetItem *photoItem = new QTreeWidgetItem((QTreeWidget*)0); + photoItem->setText(PHOTO_PEER_COL_PHOTO, QString::fromStdString(sit->photoId)); + + photoItem->setText(PHOTO_PEER_COL_PID, QString::fromStdString(id)); + photoItem->setText(PHOTO_PEER_COL_SID, QString::fromStdString(*it)); + photoItem->setText(PHOTO_PEER_COL_PHOTOID, QString::fromStdString(sit->photoId)); + + showItem->addChild(photoItem); + } + } +} + + +void PhotoDialog::updatePhotoList() +{ +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::updatePhotoList()" << std::endl; +#endif + + /* get current item */ + QTreeWidgetItem *item = ui.peerTreeWidget->currentItem(); + + if (!item) + { + /* leave current list */ +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::updatePhotoList() No Current item -> leave" << std::endl; +#endif + return; + } + + /* check if it has changed */ + std::string pid = item->text(PHOTO_PEER_COL_PID).toStdString(); + std::string sid = item->text(PHOTO_PEER_COL_SID).toStdString(); + + if ((mCurrentPID == pid) && (mCurrentSID == sid)) + { + /* still good */ +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::updatePhotoList() List still good!" << std::endl; +#endif + return; + } + +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::updatePhotoList() pid: " << pid << " sid: " << sid << std::endl; +#endif + /* get the list of photos */ + + ui.photoTreeWidget->clear(); + QList items; + + if (sid != "") + { +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::updatePhotoList() SID -> showing show" << std::endl; +#endif + /* load up show list */ + RsPhotoShowDetails detail; + rsPhoto->getShowDetails(pid, sid, detail); + + + std::list::iterator sit; + for(sit = detail.photos.begin(); sit != detail.photos.end(); sit++) + { + RsPhotoDetails photoDetail; + + if (!rsPhoto->getPhotoDetails(pid, sit->photoId, photoDetail)) + { +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::updatePhotoList() getPhotoDetails: " << sit->photoId << " FAILED" << std::endl; +#endif + continue; + } + + QTreeWidgetItem *photoItem = new QTreeWidgetItem((QTreeWidget*)0); + if (photoDetail.isAvailable) + { + QPixmap qpp(QString::fromStdString(photoDetail.path)); + photoItem->setIcon(PHOTO_LIST_COL_PHOTO, + QIcon(qpp.scaledToHeight(PHOTO_ICON_SIZE))); + + QSize iconSize(PHOTO_ICON_SIZE + 10,PHOTO_ICON_SIZE + 10); + photoItem->setSizeHint(PHOTO_LIST_COL_PHOTO, iconSize); + } + else + { + photoItem->setText(PHOTO_LIST_COL_PHOTO, "Photo Not Available"); + } + + photoItem->setText(PHOTO_LIST_COL_NAME, + QString::fromStdString(photoDetail.name)); + photoItem->setText(PHOTO_LIST_COL_COMMENT, + QString::fromStdWString(photoDetail.comment)); + photoItem->setText(PHOTO_LIST_COL_DATE, + QString::fromStdString(photoDetail.date)); + photoItem->setText(PHOTO_LIST_COL_LOCATION, + QString::fromStdString(photoDetail.location)); + photoItem->setText(PHOTO_LIST_COL_SIZE, + QString::number(photoDetail.size)); + photoItem->setText(PHOTO_LIST_COL_PEERID, + QString::fromStdString(photoDetail.id)); + photoItem->setText(PHOTO_LIST_COL_PHOTOID, + QString::fromStdString(photoDetail.hash)); + + items.append(photoItem); + } + } + else + { +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::updatePhotoList() No SID -> show all" << std::endl; +#endif + + std::list photoIds; + std::list::iterator pit; + rsPhoto->getPhotoList(pid, photoIds); + for(pit = photoIds.begin(); pit != photoIds.end(); pit++) + { + RsPhotoDetails photoDetail; + + if (!rsPhoto->getPhotoDetails(pid, *pit, photoDetail)) + { +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::updatePhotoList() getPhotoDetails: " << *pit << " FAILED" << std::endl; +#endif + continue; + } + + QTreeWidgetItem *photoItem = new QTreeWidgetItem((QTreeWidget*)0); + if (photoDetail.isAvailable) + { + QPixmap qpp(QString::fromStdString(photoDetail.path)); + photoItem->setIcon(PHOTO_LIST_COL_PHOTO, + QIcon(qpp.scaledToHeight(PHOTO_ICON_SIZE))); + + QSize iconSize(PHOTO_ICON_SIZE + 10,PHOTO_ICON_SIZE + 10); + photoItem->setSizeHint(PHOTO_LIST_COL_PHOTO, iconSize); + } + else + { + photoItem->setText(PHOTO_LIST_COL_PHOTO, "Photo Not Available"); + } + + photoItem->setText(PHOTO_LIST_COL_NAME, + QString::fromStdString(photoDetail.name)); + photoItem->setText(PHOTO_LIST_COL_COMMENT, + QString::fromStdWString(photoDetail.comment)); + photoItem->setText(PHOTO_LIST_COL_DATE, + QString::fromStdString(photoDetail.date)); + photoItem->setText(PHOTO_LIST_COL_LOCATION, + QString::fromStdString(photoDetail.location)); + photoItem->setText(PHOTO_LIST_COL_SIZE, + QString::number(photoDetail.size)); + photoItem->setText(PHOTO_LIST_COL_PEERID, + QString::fromStdString(photoDetail.id)); + photoItem->setText(PHOTO_LIST_COL_PHOTOID, + QString::fromStdString(photoDetail.hash)); + + +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::updatePhotoList() added Item: " << *pit << std::endl; +#endif + items.append(photoItem); + } + + } + + /* update ids? */ + mCurrentPID = pid; + mCurrentSID = sid; + + /* add the items in! */ + ui.photoTreeWidget->insertTopLevelItems(0, items); + ui.photoTreeWidget->update(); +} + + + +/* get the list of peers from the RsIface. */ +void PhotoDialog::insertExample() +{ + +} + +QTreeWidgetItem *PhotoDialog::getCurrentLine() +{ + /* get the current, and extract the Id */ + + /* get a link to the table */ + QTreeWidget *peerWidget = ui.photoTreeWidget; + QTreeWidgetItem *item = peerWidget -> currentItem(); + if (!item) + { +#ifdef PHOTO_DEBUG + std::cerr << "Invalid Current Item" << std::endl; +#endif + return NULL; + } + + /* Display the columns of this item. */ +#ifdef PHOTO_DEBUG + std::ostringstream out; + out << "CurrentPeerItem: " << std::endl; + + for(int i = 1; i < 6; i++) + { + QString txt = item -> text(i); + out << "\t" << i << ":" << txt.toStdString() << std::endl; + } + std::cerr << out.str(); +#endif + return item; +} + +void PhotoDialog::removePhoto() +{ + QTreeWidgetItem *c = getCurrentLine(); +#ifdef PHOTO_DEBUG + std::cerr << "PhotoDialog::removePhoto()" << std::endl; +#endif +} + + +void PhotoDialog::addPhotos() +{ + /* get file dialog */ + QStringList files = QFileDialog::getOpenFileNames(this, + "Select one or more Photos to add", + "/home", "Images (*.png *.xpm *.jpg *.gif)"); + /* add photo to list */ + QStringList::iterator it; + for(it = files.begin(); it != files.end(); it++) + { + addPhoto(*it); + } +} + +void PhotoDialog::addPhoto(QString filename) +{ + /* store in rsPhoto */ + std::string photoId = rsPhoto->addPhoto(filename.toStdString()); + +} + +void PhotoDialog::showPhoto( QTreeWidgetItem *item, int column) +{ + + if (!item) + return; + + /* get the photoId */ + std::string pid = item->text(PHOTO_LIST_COL_PEERID).toStdString(); + std::string photoid = item->text(PHOTO_LIST_COL_PHOTOID).toStdString(); + + PhotoShow *newView = new PhotoShow(); + newView->show(); + + newView->setPeerId(pid); + newView->setPhotoId(photoid); + + return; +} + + + + + diff --git a/retroshare-gui/src/gui/unfinished/PhotoDialog.h b/retroshare-gui/src/gui/unfinished/PhotoDialog.h new file mode 100644 index 000000000..e8af5dd30 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/PhotoDialog.h @@ -0,0 +1,96 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _PHOTODIALOG_H +#define _PHOTODIALOG_H + +#include + +#include "gui/mainpage.h" +#include "ui_PhotoDialog.h" + +#include + + +class PhotoDialog : public MainPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + PhotoDialog(QWidget *parent = 0); + /** Default Destructor */ + + void insertExample(); + void insertShowLists(); + +private slots: + /** Create the context popup menu and it's submenus */ + void photoTreeWidgetCustomPopupMenu( QPoint point ); + void peerTreeWidgetCustomPopupMenu( QPoint point ); + + void updatePhotoList(); + + void removePhoto(); + void addPhotos(); + + void checkUpdate(); + + /* handle splitter */ + void togglefileview(); + + void showPhoto( QTreeWidgetItem *item, int column); + +private: + + void addShows(std::string peerid); + + void addPhoto(QString filename); + + /* Worker Functions */ + /* (1) Update Display */ + + /* (2) Utility Fns */ + QTreeWidgetItem *getCurrentLine(); + + std::map photoMap; + + std::string mCurrentPID; + std::string mCurrentSID; + + /** Define the popup menus for the Context menu */ + QMenu* contextMnu; + + QAction *rateExcellenAct; + QAction *rateGoodAct; + QAction *rateAverageAct; + QAction *rateBelowAvarageAct; + QAction *rateBadAct; + QAction *rateUnratedAct; + + QTreeWidget *exampletreeWidget; + + /** Qt Designer generated object */ + Ui::PhotoDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/PhotoDialog.ui b/retroshare-gui/src/gui/unfinished/PhotoDialog.ui new file mode 100644 index 000000000..3e4e01fa3 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/PhotoDialog.ui @@ -0,0 +1,265 @@ + + + PhotoDialog + + + + 0 + 0 + 561 + 489 + + + + + 0 + + + 6 + + + 0 + + + 0 + + + + + + + + :/images/image16.png + + + true + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + + + Qt::Horizontal + + + + 391 + 20 + + + + + + + + Qt::Vertical + + + + + + + Qt::Horizontal + + + + Qt::CustomContextMenu + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + + Qt::CustomContextMenu + + + + Thumb Image + + + + + Image Name + + + + + Comment + + + + + Date + + + + + Location + + + + + Size + + + + + PeerId + + + + + PhotoId + + + + + + + + + + + + + + + :/images/edit_remove24.png:/images/edit_remove24.png + + + + + + + Add Photo(s) + + + Add Photo(s) + + + + :/images/add_image24.png:/images/add_image24.png + + + + + + + Add Photo SlideShow + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Update Details + + + + :/images/quick_restart24.png:/images/quick_restart24.png + + + + + + + + + + + + + Photo + + + + + + + + + + Date + + + + + + + + + + Location + + + + + + + + + + Description + + + + + + + + + + Comment + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/PhotoShow.cpp b/retroshare-gui/src/gui/unfinished/PhotoShow.cpp new file mode 100644 index 000000000..58af772c9 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/PhotoShow.cpp @@ -0,0 +1,161 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "PhotoShow.h" +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** Constructor */ +PhotoShow::PhotoShow(QWidget *parent) +: QWidget(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + // connect( ui.peerTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( peerTreeWidgetCustomPopupMenu( QPoint ) ) ); + // connect( ui.photoTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( photoTreeWidgetCustomPopupMenu( QPoint ) ) ); + + // connect( ui.peerTreeWidget, SIGNAL( currentItemChanged ( QTreeWidgetItem * , QTreeWidgetItem * ) ), this, SLOT( updatePhotoList( ) ) ); + + //connect( ui.photoTreeWidget, SIGNAL( currentItemChanged ( QTreeWidgetItem * , QTreeWidgetItem * ) ), this, SLOT( displayPhoto( ) ) ); + //connect( ui.addButton, SIGNAL( clicked( ) ), this, SLOT( addPhotos( ) ) ); + + + /* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif + +} + +void PhotoShow::photoCustomPopupMenu( QPoint point ) +{ + +// QMenu contextMnu( this ); +// QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); +// +// QAction *rm = new QAction(QIcon(IMAGE_EXPIORTFRIEND), tr( "Remove" ), this ); +// connect( rm , SIGNAL( triggered() ), this, SLOT( removePhoto() ) ); +// +// contextMnu.clear(); +// contextMnu.addAction(rm); +// contextMnu.addSeparator(); +// contextMnu.exec( mevent->globalPos() ); +} + +void PhotoShow::updatePhotoShow() +{ + std::cerr << "PhotoShow::updatePhotoShow()" << std::endl; + + if (mDoShow) + { + std::cerr << "PhotoShow::updatePhotoShow() (Show) pid: " << mPeerId << " sid: " << mShowId << std::endl; + } + else + { + std::cerr << "PhotoShow::updatePhotoShow() (Image) pid: " << mPeerId << " photoId: " << mPhotoId << std::endl; + updatePhoto(mPeerId, mPhotoId); + } + +} + +void PhotoShow::updatePhoto(std::string pid, std::string photoId) +{ + RsPhotoDetails photoDetail; + std::cerr << "PhotoShow::updatePhoto() pid: "; + std::cerr << pid << " photoId: " << photoId; + std::cerr << std::endl; + + if (!rsPhoto->getPhotoDetails(pid, photoId, photoDetail)) + { + std::cerr << "PhotoShow::updatePhotoShow() BAD Photo Id"; + std::cerr << std::endl; + return; + } + + ui.photoLabel->clear(); + + if (photoDetail.isAvailable) + { + QPixmap qpp(QString::fromStdString(photoDetail.path)); + QSize diaSize = ui.photoLabel->size(); + int width = diaSize.width(); + ui.photoLabel->setPixmap(qpp.scaledToWidth(width)); + } + else + { + ui.photoLabel->setText("Photo Not Available"); + } + + ui.commentLineEdit->setText(QString::fromStdWString(photoDetail.comment)); + ui.dateLineEdit->setText(QString::fromStdString(photoDetail.date)); + ui.locLineEdit->setText(QString::fromStdString(photoDetail.location)); + + //ui.nameLineEdit->setText(QString::fromStdString(photoDetail.name)); + //ui.sizeLineEdit->setText(QString::number(photoDetail.size)); + //ui.peeridLineEdit->setText(QString::fromStdString(photoDetail.id)); + //ui.photoidLineEdit->setText(QString::fromStdString(photoDetail.hash)); + +} + +void PhotoShow::setPeerId(std::string id) +{ + mPeerId = id; + return; +} + +void PhotoShow::setPhotoId(std::string id) +{ + mPhotoId = id; + mDoShow = false; + + updatePhotoShow(); + return; +} + +void PhotoShow::setPhotoShow(std::string id) +{ + mShowId = id; + mDoShow = true; + + updatePhotoShow(); + return; +} + + + diff --git a/retroshare-gui/src/gui/unfinished/PhotoShow.h b/retroshare-gui/src/gui/unfinished/PhotoShow.h new file mode 100644 index 000000000..fbac1e12b --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/PhotoShow.h @@ -0,0 +1,68 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _PHOTOSHOW_H +#define _PHOTOSHOW_H + +#include + +#include "gui/mainpage.h" +#include "ui_PhotoShow.h" + +#include + + +class PhotoShow : public QWidget +{ + Q_OBJECT + +public: + /** Default Constructor */ + PhotoShow(QWidget *parent = 0); + /** Default Destructor */ + + void setPeerId(std::string id); + void setPhotoId(std::string id); + void setPhotoShow(std::string id); + + +private slots: + /** Create the context popup menu and it's submenus */ + void photoCustomPopupMenu( QPoint point ); + + void updatePhotoShow(); + + +private: + + void updatePhoto(std::string pid, std::string photoId); + + bool mDoShow; + std::string mPeerId; + std::string mShowId; + std::string mPhotoId; + + /** Qt Designer generated object */ + Ui::PhotoShow ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/PhotoShow.ui b/retroshare-gui/src/gui/unfinished/PhotoShow.ui new file mode 100644 index 000000000..112a63e4d --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/PhotoShow.ui @@ -0,0 +1,250 @@ + + + PhotoShow + + + + 0 + 0 + 528 + 421 + + + + Photo Show + + + + + + + + + + + + Date: + + + + + + + Location: + + + + + + + Comment: + + + + + + + + + + + + + + + + + + + + + + + + + + Display Size: + + + + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + + + + Play Rate: + + + + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Edit Photo Details + + + + + + + Save Photo + + + + + + + + + No Photo Selected + + + true + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Back + + + + :/images/back.png:/images/back.png + + + + + + + Start + + + + + + + Play + + + + + + + Pause + + + + + + + Forward + + + + :/images/forward.png:/images/forward.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/StatisticDialog.cpp b/retroshare-gui/src/gui/unfinished/StatisticDialog.cpp new file mode 100644 index 000000000..84bf094d2 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/StatisticDialog.cpp @@ -0,0 +1,277 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "rshare.h" +#include "StatisticDialog.h" +#include + +#include + +#include +#include + +/* Define the format used for displaying the date and time */ +#define DATETIME_FMT "yyyy MM dd hh:mm:ss" + +QTime UpTime; +int UpDays; +bool dayChange; +static int Timer=0; + +/** Constructor */ +StatisticDialog::StatisticDialog(QWidget *parent) +: MainPage(parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + /* Bind events to actions */ + createActions(); + + UpDays=0; + dayChange=false; + UpTime.start(); + + /* Initialize Sent/Receive data counters */ + reset(); + + /* Hide Bandwidth Graph Settings frame */ + showSettingsFrame(false); + + /* Set header resize modes and initial section sizes */ + QHeaderView * _stheader = ui.treeWidget-> header(); + _stheader->resizeSection ( 0, 210 ); + + QAbstractItemModel * model =ui.treeWidget->model(); + QModelIndex ind2; + // set Times --> Session --> Since + ind2=model->index(4,0).child(0,0).child(1,1); + model->setData(ind2,QDateTime::currentDateTime() + .toString(DATETIME_FMT)); + + /* Turn off opacity group on unsupported platforms */ +#if defined(Q_WS_WIN) + if(!(QSysInfo::WV_2000 <= QSysInfo::WindowsVersion <= QSysInfo::WV_2003)) { + ui.frmOpacity->setVisible(false); + } +#endif + +#if defined(Q_WS_X11) + ui.frmOpacity->setVisible(false); +#endif + + Timer=startTimer(REFRESH_RATE); + +} + +/** + Custom event handler. Checks if the event is a bandwidth update event. If it + is, it will add the data point to the history and updates the graph.*/ + +void +StatisticDialog::customEvent(QEvent *event) +{ + if (event->type() == CustomEventType::BandwidthEvent) { + BandwidthEvent *bw = (BandwidthEvent *)event; + updateGraph(bw->bytesRead(), bw->bytesWritten()); + } +} + +void StatisticDialog::timerEvent( QTimerEvent * ) +{ + QAbstractItemModel * model =ui.treeWidget->model(); + QModelIndex ind1; + // set download --> session bytes + //ind1=model->index(1,0).child(0,0).child(0,1); + //model->setData(ind1,totalToString(TotBytesDownloaded/1024.0)); + // set upload --> session bytes + //ind1=model->index(2,0).child(0,0).child(0,1); + //model->setData(ind1,totalToString(TotBytesUploaded/1024.0)); + + // set Times --> Session --> Uptime + ind1=model->index(4,0).child(0,0).child(0,1); + if(! dayChange && (UpTime.elapsed()/1000 > 60*60*23)) dayChange=true; + if( dayChange && (UpTime.elapsed() <10000)) {dayChange=false;UpDays++;} + + QTime elapsed; + elapsed= QTime(0,0,0).addMSecs(UpTime.elapsed()); + if( UpDays>0) + model->setData(ind1,QString(tr("%1 days ")).arg(UpDays)+elapsed.toString("hh:mm:ss")); + else + model->setData(ind1,elapsed.toString("hh:mm:ss")); + + /* set users/friends/network */ + float downKb = 0; + float upKb = 0; + rsicontrol -> ConfigGetDataRates(downKb, upKb); + + updateGraph(downKb,upKb); + // + +} + +/** + Binds events to actions +*/ +void +StatisticDialog::createActions() +{ + connect(ui.btnToggleSettings, SIGNAL(toggled(bool)), + this, SLOT(showSettingsFrame(bool))); + + connect(ui.btnReset, SIGNAL(clicked()), + this, SLOT(reset())); + + connect(ui.btnSaveSettings, SIGNAL(clicked()), + this, SLOT(saveChanges())); + + connect(ui.btnCancelSettings, SIGNAL(clicked()), + this, SLOT(cancelChanges())); + + connect(ui.sldrOpacity, SIGNAL(valueChanged(int)), + this, SLOT(setOpacity(int))); +} + +/** + Adds new data to the graph +*/ +void +StatisticDialog::updateGraph(quint64 bytesRead, quint64 bytesWritten) +{ + /* Graph only cares about kilobytes */ + ui.frmGraph->addPoints(bytesRead, bytesWritten); +} + + +/** + Loads the saved Bandwidth Graph settings +*/ +void +StatisticDialog::loadSettings() +{ + /* Set window opacity slider widget */ + ui.sldrOpacity->setValue(_settings->getBWGraphOpacity()); + + + + /* Set the line filter checkboxes accordingly */ + uint filter = Settings->getBWGraphFilter(); + ui.chkReceiveRate->setChecked(filter & BWGRAPH_REC); + ui.chkSendRate->setChecked(filter & BWGRAPH_SEND); + + /* Set graph frame settings */ + ui.frmGraph->setShowCounters(ui.chkReceiveRate->isChecked(), + ui.chkSendRate->isChecked()); +} + +/** + Resets the log start time +*/ +void +StatisticDialog::reset() +{ + /* Set to current time */ +// ui.statusbar->showMessage(tr("Since:") + " " + +// QDateTime::currentDateTime() +// .toString(DATETIME_FMT)); + /* Reset the graph */ + ui.frmGraph->resetGraph(); +} + +/** + Saves the Bandwidth Graph settings and adjusts the graph if necessary +*/ +void +StatisticDialog::saveChanges() +{ + /* Hide the settings frame and reset toggle button */ + showSettingsFrame(false); + + /* Save the opacity */ + Settings->setBWGraphOpacity(ui.sldrOpacity->value()); + + + + /* Save the line filter values */ + Settings->setBWGraphFilter(BWGRAPH_REC, ui.chkReceiveRate->isChecked()); + Settings->setBWGraphFilter(BWGRAPH_SEND, ui.chkSendRate->isChecked()); + + /* Update the graph frame settings */ + ui.frmGraph->setShowCounters(ui.chkReceiveRate->isChecked(), + ui.chkSendRate->isChecked()); + + /* A change in window flags causes the window to disappear, so make sure + * it's still visible. */ + showNormal(); +} + +/** + Simply restores the previously saved settings +*/ +void +StatisticDialog::cancelChanges() +{ + /* Hide the settings frame and reset toggle button */ + showSettingsFrame(false); + + /* Reload the settings */ + loadSettings(); +} + +/** + Toggles the Settings pane on and off, changes toggle button text +*/ +void +StatisticDialog::showSettingsFrame(bool show) +{ + if (show) { + ui.frmSettings->setVisible(true); + ui.btnToggleSettings->setChecked(true); + ui.btnToggleSettings->setText(tr("Hide Settings")); + } else { + ui.frmSettings->setVisible(false); + ui.btnToggleSettings->setChecked(false); + ui.btnToggleSettings->setText(tr("Show Settings")); + } +} + +/** + Sets the opacity of the Bandwidth Graph window +*/ +void +StatisticDialog::setOpacity(int value) +{ + qreal newValue = value / 100.0; + + /* Opacity only supported by Mac and Win32 */ +#if defined(Q_WS_MAC) + this->setWindowOpacity(newValue); +#elif defined(Q_WS_WIN) + if(QSysInfo::WV_2000 <= QSysInfo::WindowsVersion <= QSysInfo::WV_2003) { + this->setWindowOpacity(newValue); + } +#else + Q_UNUSED(newValue); +#endif +} + + + diff --git a/retroshare-gui/src/gui/unfinished/StatisticDialog.h b/retroshare-gui/src/gui/unfinished/StatisticDialog.h new file mode 100644 index 000000000..985df73a3 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/StatisticDialog.h @@ -0,0 +1,78 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _STATISTICDIALOG_H +#define _STATISTICDIALOG_H + +#include +#include +#include +#include + +#include "gui/mainpage.h" +#include "gui/linetypes.h" + +#include "ui_StatisticDialog.h" + +/** Redraw graph every 1000ms **/ +#define REFRESH_RATE 1000 + +class StatisticDialog : public MainPage +{ + Q_OBJECT + +public: + /** Default Constructor */ + StatisticDialog(QWidget *parent = 0); + +protected: + /** Called to deliver a bandwidth update event from RetroShare. */ + void customEvent(QEvent *event); + void timerEvent(QTimerEvent*); + + +private slots: + /** Adds new data to the graph */ + void updateGraph(quint64 bytesRead, quint64 bytesWritten); + /** Called when settings button is toggled */ + void showSettingsFrame(bool show); + /** Called when the settings button is toggled */ + void setOpacity(int value); + /** Called when the user saves settings */ + void saveChanges(); + /** Called when the user cancels changes settings */ + void cancelChanges(); + /** Called when the reset button is pressed */ + void reset(); + + +private: + /** Create and bind actions to events **/ + void createActions(); + /** Loads the saved Bandwidth Graph settings */ + void loadSettings(); + + /** Qt Designer generated object */ + Ui::StatisticDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/StatisticDialog.ui b/retroshare-gui/src/gui/unfinished/StatisticDialog.ui new file mode 100644 index 000000000..26f11ca42 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/StatisticDialog.ui @@ -0,0 +1,1292 @@ + + StatisticDialog + + + + 0 + 0 + 701 + 449 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + 6 + + + 9 + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + 0 + 0 + + + + + Statistics + + + + + Now + + + + + Transfer + + + + :/images/transferupdown.png:/images/transferupdown.png + + + + + + + Session UL:DL Ratio: + + + + + + + + Cumulative UL:DL Ratio + + + + + + + + + Download + + + + :/images/download.png:/images/download.png + + + + + + + Session: + + + + :/images/StatisticsDetail.png:/images/StatisticsDetail.png + + + + + + + Downloaded: + + + + + + + + Count of Downloads: + + + + + + + + + Overall + + + + :/images/StatsCumulative.png:/images/StatsCumulative.png + + + + + + + Downloaded: + + + + + + + + Count of Downloads: + + + + + + + + + + Upload + + + + :/images/up.png:/images/up.png + + + + + + + Session + + + + :/images/StatisticsDetail.png:/images/StatisticsDetail.png + + + + + + + Uploaded: + + + + + + + + Count of Uploads: + + + + + + + + + Overall + + + + :/images/StatsCumulative.png:/images/StatsCumulative.png + + + + + + + Uploaded + + + + + + + + Count of Uploads: + + + + + + + + + + Connections: + + + + :/images/connect_friend.png:/images/connect_friend.png + + + + + + + Session + + + + :/images/StatisticsDetail.png:/images/StatisticsDetail.png + + + + + + + Connections: + + + + + + + + Peers: + + + + + + + + + Overall + + + + :/images/StatsCumulative.png:/images/StatsCumulative.png + + + + + + + Connections: + + + + + + + + Peers: + + + + + + + + + + Time Statistics + + + + :/images/kalarm.png:/images/kalarm.png + + + + + + + Session + + + + :/images/StatisticsDetail.png:/images/StatisticsDetail.png + + + + + + + Uptime + + + + + + + + Since: + + + + + + + + + Cumulative + + + + :/images/StatsCumulative.png:/images/StatsCumulative.png + + + + + + + Uptime + + + + + + + + + + Records + + + + :/images/records.png:/images/records.png + + + + + + + Uploadspeed: + + + + + + + + Downloadspeed: + + + + + + + + Connections: + + + + + + + + Peers: + + + + + + + + Uptime: + + + + + + + + + + + 1 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + 9 + + + + + + 120 + 80 + + + + + Arial + 10 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + + 6 + + + 0 + + + + + Show Settings + + + true + + + + + + + Qt::Horizontal + + + + 21 + 20 + + + + + + + + Reset + + + + + + + + + + 0 + 0 + + + + + 355 + 82 + + + + + 355 + 82 + + + + Qt::NoContextMenu + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + 9 + + + + + 6 + + + 3 + + + + + + Arial + 10 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + Qt::RightToLeft + + + Receive Rate + + + false + + + + + + + + Arial + 10 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + + + Qt::RightToLeft + + + Send Rate + + + false + + + + + + + + Arial + 10 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + Qt::RightToLeft + + + Always On Top + + + + + + + Qt::Vertical + + + + 20 + 21 + + + + + + + + + + Qt::NoContextMenu + + + QFrame::NoFrame + + + QFrame::Plain + + + + 3 + + + 0 + + + + + 0 + + + 0 + + + + + + 25 + 0 + + + + + Arial + 10 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + Qt::RightToLeft + + + 100 + + + + + + + + Arial + 10 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + % Opaque + + + + + + + + + Qt::NoContextMenu + + + Changes the transparency of the Bandwidth Graph + + + 30 + + + 100 + + + 100 + + + 100 + + + false + + + Qt::Horizontal + + + false + + + QSlider::TicksBelow + + + 10 + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 21 + 20 + + + + + + + + 1 + + + 0 + + + + + Save + + + + + + + Cancel + + + + + + + + + + + + + + + + + GraphFrame + QWidget +
    gui/graphframe.h
    + 1 +
    +
    + + + + +
    diff --git a/retroshare-gui/src/gui/unfinished/blogs/BlogDetails.cpp b/retroshare-gui/src/gui/unfinished/blogs/BlogDetails.cpp new file mode 100644 index 000000000..bc80e6ccc --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/BlogDetails.cpp @@ -0,0 +1,148 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +#include "BlogDetails.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +/** Default constructor */ +BlogDetails::BlogDetails(QWidget *parent, Qt::WFlags flags) + : QDialog(parent, flags) +{ + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(applyDialog())); + connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(closeinfodlg())); + + ui.applyButton->setToolTip(tr("Close")); + + ui.nameline ->setReadOnly(true); + ui.popline ->setReadOnly(true); + ui.postline ->setReadOnly(true); + ui.IDline ->setReadOnly(true); + ui.DescriptiontextEdit ->setReadOnly(true); + + +} + +/** Overloads the default show() */ +void +BlogDetails::show() +{ + if(!this->isVisible()) { + QDialog::show(); + + } +} + +void BlogDetails::closeEvent (QCloseEvent * event) +{ + QWidget::closeEvent(event); +} + +void BlogDetails::closeinfodlg() +{ + close(); +} + +void BlogDetails::showDetails(std::string mBlogId) +{ + bId = mBlogId; + loadBlog(); +} + +void BlogDetails::loadBlog() +{ + + if (!rsBlogs) + { + return; + } + + std::list channelList; + std::list::iterator it; + + BlogInfo bi; + rsBlogs->getBlogInfo(bId, bi); + + rsBlogs->getBlogList(channelList); + + + for(it = channelList.begin(); it != channelList.end(); it++) + { + + // Set Blog Name + ui.nameline->setText(QString::fromStdWString(bi.blogName)); + + // Set Blog Popularity + { + std::ostringstream out; + out << it->pop; + ui.popline -> setText(QString::fromStdString(out.str())); + } + + // Set Last Blog Post Date + { + QDateTime qtime; + qtime.setTime_t(it->lastPost); + QString timestamp = qtime.toString("yyyy-MM-dd hh:mm:ss"); + ui.postline -> setText(timestamp); + } + + // Set Blog ID + ui.IDline->setText(QString::fromStdString(bi.blogId)); + + // Set Blog Description + ui.DescriptiontextEdit->setText(QString::fromStdWString(bi.blogDesc)); + + + + } + +} + +void BlogDetails::applyDialog() +{ + + /* reload now */ + loadBlog(); + + /* close the Dialog after the Changes applied */ + closeinfodlg(); + +} + + + diff --git a/retroshare-gui/src/gui/unfinished/blogs/BlogDetails.h b/retroshare-gui/src/gui/unfinished/blogs/BlogDetails.h new file mode 100644 index 000000000..f0e654d8c --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/BlogDetails.h @@ -0,0 +1,68 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2009 RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _BLOGDETAILS_H +#define _BLOGDETAILS_H + +#include + +#include "ui_BlogDetails.h" + +class BlogDetails : public QDialog +{ + Q_OBJECT + + public: + + /** Default constructor */ + BlogDetails(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + + void showDetails(std::string mChannelId); + +signals: + void configChanged() ; + +public slots: + /** Overloaded QWidget.show */ + void show(); + +protected: + void closeEvent (QCloseEvent * event); + +private slots: + + void closeinfodlg(); + void applyDialog(); + + +private: + + void loadBlog(); + + std::string bId; + /** Qt Designer generated object */ + Ui::BlogDetails ui; + +}; + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/blogs/BlogDetails.ui b/retroshare-gui/src/gui/unfinished/blogs/BlogDetails.ui new file mode 100644 index 000000000..2315161fe --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/BlogDetails.ui @@ -0,0 +1,151 @@ + + + BlogDetails + + + + 0 + 0 + 436 + 355 + + + + Blog Details + + + + :/images/rstray3.png:/images/rstray3.png + + + + + + 0 + + + + + :/images/info16.png:/images/info16.png + + + Blog Details + + + + + + Blog Info + + + + + + Blog Name + + + + + + + + + + Popularity + + + + + + + true + + + + + + + Last Post + + + + + + + true + + + + + + + Blog ID + + + + + + + + + + Blog Description + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 311 + 20 + + + + + + + + Cancel + + + + + + + OK + + + false + + + true + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/blogs/BlogsDialog.cpp b/retroshare-gui/src/gui/unfinished/blogs/BlogsDialog.cpp new file mode 100644 index 000000000..c506a4501 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/BlogsDialog.cpp @@ -0,0 +1,588 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include + +#include + +#include +#include //to retrieve peer/usrId info + +#include "BlogsDialog.h" + +#include "BlogsMsgItem.h" +#include "CreateBlog.h" +#include "CreateBlogMsg.h" +#include "BlogDetails.h" + +#include "gui/ChanGroupDelegate.h" + +#define BLOG_DEFAULT_IMAGE ":/images/hi64-app-kblogger.png" + +/** Constructor */ +BlogsDialog::BlogsDialog(QWidget *parent) +: MainPage (parent) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + connect(actionCreate_Blog, SIGNAL(triggered()), this, SLOT(createBlog())); + connect(postButton, SIGNAL(clicked()), this, SLOT(createMsg())); + connect(subscribeButton, SIGNAL( clicked( void ) ), this, SLOT( subscribeBlog ( void ) ) ); + connect(unsubscribeButton, SIGNAL( clicked( void ) ), this, SLOT( unsubscribeBlog ( void ) ) ); + + connect(treeView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(selectBlog(const QModelIndex &))); + connect(treeView, SIGNAL(activated(const QModelIndex &)), this, SLOT(toggleSelection(const QModelIndex &))); + connect(treeView, SIGNAL(customContextMenuRequested( QPoint ) ), this, SLOT( blogListCustomPopupMenu( QPoint ) ) ); + + mBlogId = ""; + mPeerId = rsPeers->getOwnId(); // add your id + + model = new QStandardItemModel(0, 2, this); + model->setHeaderData(0, Qt::Horizontal, tr("Name"), Qt::DisplayRole); + model->setHeaderData(1, Qt::Horizontal, tr("ID"), Qt::DisplayRole); + + treeView->setModel(model); + treeView->setEditTriggers(QAbstractItemView::NoEditTriggers); + + treeView->setItemDelegate(new ChanGroupDelegate()); + + // hide header and id column + treeView->setHeaderHidden(true); + treeView->hideColumn(1); + + itemFont = QFont("ARIAL", 10); + itemFont.setBold(true); + + QStandardItem *OwnBlogs = new QStandardItem(tr("Own Blogs")); + OwnBlogs->setForeground(QBrush(QColor(79, 79, 79))); + OwnBlogs->setFont(itemFont); + + QStandardItem *SubscribedBlogs = new QStandardItem(tr("Subscribed Blogs")); + SubscribedBlogs->setForeground(QBrush(QColor(79, 79, 79))); + SubscribedBlogs->setFont(itemFont); + + QStandardItem *PopularBlogs = new QStandardItem(tr("Popular Blogs")); + PopularBlogs->setForeground(QBrush(QColor(79, 79, 79))); + PopularBlogs->setFont(itemFont); + + QStandardItem *OtherBlogs = new QStandardItem(tr("Other Blogs")); + OtherBlogs->setForeground(QBrush(QColor(79, 79, 79))); + OtherBlogs->setFont(itemFont); + + model->appendRow(OwnBlogs); + model->appendRow(SubscribedBlogs); + model->appendRow(PopularBlogs); + model->appendRow(OtherBlogs); + + //added from ahead + updateBlogList(); + + mBlogFont = QFont("MS SANS SERIF", 22); + nameLabel->setFont(mBlogFont); + nameLabel->setMinimumWidth(20); + + QMenu *blogmenu = new QMenu(); + blogmenu->addAction(actionCreate_Blog); + blogmenu->addSeparator(); + blogpushButton->setMenu(blogmenu); + + QTimer *timer = new QTimer(this); + timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + timer->start(1000); +} + +void BlogsDialog::blogListCustomPopupMenu( QPoint point ) +{ + BlogInfo bi; + if (!rsBlogs->getBlogInfo(mBlogId, bi)) + { + return; + } + + QMenu contextMnu( this ); + + QAction *createblogpostAct = new QAction(QIcon(":/images/mail_reply.png"), tr( "Post to Blog" ), this ); + connect( createblogpostAct , SIGNAL( triggered() ), this, SLOT( createMsg() ) ); + + QAction *subscribeblogAct = new QAction(QIcon(":/images/edit_add24.png"), tr( "Subscribe to Blog" ), this ); + connect( subscribeblogAct , SIGNAL( triggered() ), this, SLOT( subscribeBlog() ) ); + + QAction *unsubscribeblogAct = new QAction(QIcon(":/images/cancel.png"), tr( "Unsubscribe to Blog" ), this ); + connect( unsubscribeblogAct , SIGNAL( triggered() ), this, SLOT( unsubscribeBlog() ) ); + + QAction *blogdetailsAct = new QAction(QIcon(":/images/info16.png"), tr( "Show Blog Details" ), this ); + connect( blogdetailsAct , SIGNAL( triggered() ), this, SLOT( showBlogDetails() ) ); + + contextMnu.clear(); + + if (bi.blogFlags & RS_DISTRIB_PUBLISH) + { + contextMnu.addAction( createblogpostAct ); + contextMnu.addSeparator(); + contextMnu.addAction( blogdetailsAct ); + } + else if (bi.blogFlags & RS_DISTRIB_SUBSCRIBED) + { + contextMnu.addAction( unsubscribeblogAct ); + contextMnu.addSeparator(); + contextMnu.addAction( blogdetailsAct );; + } + else + { + contextMnu.addAction( subscribeblogAct ); + contextMnu.addSeparator(); + contextMnu.addAction( blogdetailsAct ); + } + + contextMnu.exec(QCursor::pos()); +} + +void BlogsDialog::createBlog() +{ + CreateBlog cf (this, false); + + cf.setWindowTitle(tr("Create a new Blog")); + cf.exec(); +} + +void BlogsDialog::blogSelection() +{ + /* which item was selected? */ + + + /* update mBlogId */ + + updateBlogMsgs(); +} + + +/*************************************************************************************/ +/*************************************************************************************/ +/*************************************************************************************/ + +void BlogsDialog::deleteFeedItem(QWidget *item, uint32_t type) +{ + return; +} + +void BlogsDialog::openChat(std::string peerId) +{ + return; +} + +void BlogsDialog::createMsg() +{ + if (mBlogId == "") + { + return; + } + + CreateBlogMsg *msgDialog = new CreateBlogMsg(mBlogId); + + msgDialog->show(); + + /* window will destroy itself! */ +} + +void BlogsDialog::selectBlog( std::string bId) +{ + mBlogId = bId; + + updateBlogMsgs(); +} + +void BlogsDialog::selectBlog(const QModelIndex &index) +{ + int row = index.row(); + int col = index.column(); + if (col != 1) { + QModelIndex sibling = index.sibling(row, 1); + if (sibling.isValid()) + mBlogId = sibling.data().toString().toStdString(); + } else + mBlogId = index.data().toString().toStdString(); + updateBlogMsgs(); +} + +void BlogsDialog::checkUpdate() +{ + std::list blogIds; + std::list::iterator it; + if (!rsBlogs) + return; + + if (rsBlogs->blogsChanged(blogIds)) + { + /* update Blogs List */ + updateBlogList(); + + it = std::find(blogIds.begin(), blogIds.end(), mBlogId); + if (it != blogIds.end()) + { + updateBlogMsgs(); + } + } +} + +void BlogsDialog::updateBlogList() +{ + + std::list channelList; + std::list::iterator it; + if (!rsBlogs) + { + return; + } + + rsBlogs->getBlogList(channelList); + + /* get the ids for our lists */ + std::list adminIds; + std::list subIds; + std::list popIds; + std::list otherIds; + std::multimap popMap; + + for(it = channelList.begin(); it != channelList.end(); it++) + { + /* sort it into Publish (Own), Subscribed, Popular and Other */ + uint32_t flags = it->blogFlags; + + if (flags & RS_DISTRIB_ADMIN) + { + adminIds.push_back(it->blogId); + } + else if (flags & RS_DISTRIB_SUBSCRIBED) + { + subIds.push_back(it->blogId); + } + else + { + /* rate the others by popularity */ + popMap.insert(std::make_pair(it->pop, it->blogId)); + } + } + + /* iterate backwards through popMap - take the top 5 or 10% of list */ + uint32_t popCount = 5; + if (popCount < popMap.size() / 10) + { + popCount = popMap.size() / 10; + } + + uint32_t i = 0; + std::multimap::reverse_iterator rit; + for(rit = popMap.rbegin(); rit != popMap.rend(); rit++) + { + if(i < popCount){ + popIds.push_back(rit->second); + i++; + }else{ + otherIds.push_back(rit->second); + } + } + + /* now we have our lists ---> update entries */ + + updateBlogListOwn(adminIds); + updateBlogListSub(subIds); + updateBlogListPop(popIds); + updateBlogListOther(otherIds); +} + +void BlogsDialog::updateBlogListOwn(std::list &ids) +{ + std::list::iterator iit; + + /* remove rows with groups before adding new ones */ + model->item(OWN)->removeRows(0, model->item(OWN)->rowCount()); + + for (iit = ids.begin(); iit != ids.end(); iit ++) { +#ifdef BLOG_DEBUG + std::cerr << "BlogsDialog::updateBlogListOwn(): " << *iit << std::endl; +#endif + QStandardItem *ownGroup = model->item(OWN); + QList blog; + QStandardItem *blogNameitem = new QStandardItem(); + QStandardItem *blogIditem = new QStandardItem(); + + BlogInfo bi; + if (rsBlogs && rsBlogs->getBlogInfo(*iit, bi)) { + blogNameitem->setData(QVariant(QString::fromStdWString(bi.blogName)), Qt::DisplayRole); + blogIditem->setData(QVariant(QString::fromStdString(bi.blogId)), Qt::DisplayRole); + blogNameitem->setToolTip(tr("Popularity: %1\nFetches: %2\nAvailable: %3" + ).arg(QString::number(bi.pop)).arg(9999).arg(9999)); + } else { + blogNameitem->setData(QVariant(QString("Unknown Blog")), Qt::DisplayRole); + blogIditem->setData(QVariant(QString::fromStdString(*iit)), Qt::DisplayRole); + blogNameitem->setToolTip("Unknown Blog\nNo Description"); + } + + blog.append(blogNameitem); + blog.append(blogIditem); + ownGroup->appendRow(blog); + } +} + +void BlogsDialog::updateBlogListSub(std::list &ids) +{ + std::list::iterator iit; + + /* remove rows with groups before adding new ones */ + model->item(SUBSCRIBED)->removeRows(0, model->item(SUBSCRIBED)->rowCount()); + + for (iit = ids.begin(); iit != ids.end(); iit ++) { +#ifdef BLOG_DEBUG + std::cerr << "BlogsDialog::updateBlogListSub(): " << *iit << std::endl; +#endif + QStandardItem *ownGroup = model->item(SUBSCRIBED); + QList blog; + QStandardItem *blogNameitem = new QStandardItem(); + QStandardItem *blogIditem = new QStandardItem(); + + BlogInfo bi; + if (rsBlogs && rsBlogs->getBlogInfo(*iit, bi)) { + blogNameitem->setData(QVariant(QString::fromStdWString(bi.blogName)), Qt::DisplayRole); + blogIditem->setData(QVariant(QString::fromStdString(bi.blogId)), Qt::DisplayRole); + blogNameitem->setToolTip(tr("Popularity: %1\nFetches: %2\nAvailable: %3" + ).arg(QString::number(bi.pop)).arg(9999).arg(9999)); + } else { + blogNameitem->setData(QVariant(QString("Unknown Blog")), Qt::DisplayRole); + blogIditem->setData(QVariant(QString::fromStdString(*iit)), Qt::DisplayRole); + blogNameitem->setToolTip("Unknown Blog\nNo Description"); + } + + blog.append(blogNameitem); + blog.append(blogIditem); + ownGroup->appendRow(blog); + } + +} + +void BlogsDialog::updateBlogListPop(std::list &ids) +{ + std::list::iterator iit; + + /* remove rows with groups before adding new ones */ + model->item(POPULAR)->removeRows(0, model->item(POPULAR)->rowCount()); + + for (iit = ids.begin(); iit != ids.end(); iit ++) { +#ifdef BLOG_DEBUG + std::cerr << "BlogsDialog::updateBlogListPop(): " << *iit << std::endl; +#endif + QStandardItem *ownGroup = model->item(POPULAR); + QList blog; + QStandardItem *blogNameitem = new QStandardItem(); + QStandardItem *blogIditem = new QStandardItem(); + + BlogInfo bi; + if (rsBlogs && rsBlogs->getBlogInfo(*iit, bi)) { + blogNameitem->setData(QVariant(QString::fromStdWString(bi.blogName)), Qt::DisplayRole); + blogIditem->setData(QVariant(QString::fromStdString(bi.blogId)), Qt::DisplayRole); + blogNameitem->setToolTip(tr("Popularity: %1\nFetches: %2\nAvailable: %3" + ).arg(QString::number(bi.pop)).arg(9999).arg(9999)); + } else { + blogNameitem->setData(QVariant(QString("Unknown Blog")), Qt::DisplayRole); + blogIditem->setData(QVariant(QString::fromStdString(*iit)), Qt::DisplayRole); + blogNameitem->setToolTip("Unknown Blog\nNo Description"); + } + + blog.append(blogNameitem); + blog.append(blogIditem); + ownGroup->appendRow(blog); + } +} + +void BlogsDialog::updateBlogListOther(std::list &ids) +{ + std::list::iterator iit; + + /* remove rows with groups before adding new ones */ + model->item(OTHER)->removeRows(0, model->item(OTHER)->rowCount()); + + for (iit = ids.begin(); iit != ids.end(); iit ++) { +#ifdef BLOG_DEBUG + std::cerr << "BlogsDialog::updateBlogListOther(): " << *iit << std::endl; +#endif + QStandardItem *ownGroup = model->item(OTHER); + QList blog; + QStandardItem *blogNameitem = new QStandardItem(); + QStandardItem *blogIditem = new QStandardItem(); + + BlogInfo bi; + if (rsBlogs && rsBlogs->getBlogInfo(*iit, bi)) { + blogNameitem->setData(QVariant(QString::fromStdWString(bi.blogName)), Qt::DisplayRole); + blogIditem->setData(QVariant(QString::fromStdString(bi.blogId)), Qt::DisplayRole); + blogNameitem->setToolTip(tr("Popularity: %1\nFetches: %2\nAvailable: %3" + ).arg(QString::number(bi.pop)).arg(9999).arg(9999)); + } else { + blogNameitem->setData(QVariant(QString("Unknown Blog")), Qt::DisplayRole); + blogIditem->setData(QVariant(QString::fromStdString(*iit)), Qt::DisplayRole); + blogNameitem->setToolTip("Unknown Blog\nNo Description"); + } + + blog.append(blogNameitem); + blog.append(blogIditem); + ownGroup->appendRow(blog); + } +} + +void BlogsDialog::updateBlogMsgs() +{ + if (!rsBlogs) + return; + + BlogInfo bi; + if (!rsBlogs->getBlogInfo(mBlogId, bi)) + { + postButton->setEnabled(false); + subscribeButton->setEnabled(false); + unsubscribeButton->setEnabled(false); + nameLabel->setText("No Blog Selected"); + iconLabel->setPixmap(QPixmap(":/images/hi64-app-kblogger.png")); + iconLabel->setEnabled(false); + frame->setStyleSheet("QFrame#frame{ border: 2px solid #808080;border-radius: 10px;background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #C0C0C0, stop:1 #A0A0A0); }"); + return; + } + + if(bi.pngImageLen != 0){ + + QPixmap blogImage; + blogImage.loadFromData(bi.pngChanImage, bi.pngImageLen, "PNG"); + iconLabel->setPixmap(blogImage); + iconLabel->setStyleSheet("QLabel{border: 2px solid white;}"); + }else{ + QPixmap defaultImage(BLOG_DEFAULT_IMAGE); + iconLabel->setPixmap(defaultImage); + iconLabel->setStyleSheet("QLabel{border: 2px solid white;border-radius: 10px;}"); + } + + iconLabel->setEnabled(true); + + + /* set textcolor for Blog name */ + QString blogStr("%1"); + + /* set Blog name */ + QString bname = QString::fromStdWString(bi.blogName); + nameLabel->setText(blogStr.arg(bname)); + + /* do buttons */ + if (bi.blogFlags & RS_DISTRIB_SUBSCRIBED) + { + subscribeButton->setEnabled(false); + unsubscribeButton->setEnabled(true); + frame->setStyleSheet("QFrame#frame{ border: 2px solid #FF0000;border-radius: 10px;background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #B61407, stop:1 #A91106); }"); + + } + else + { + subscribeButton->setEnabled(true); + unsubscribeButton->setEnabled(false); + frame->setStyleSheet("QFrame#frame{ border: 2px solid #267F00;border-radius: 10px;background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #89D51D, stop:1 #579E10); }"); + } + + if (bi.blogFlags & RS_DISTRIB_PUBLISH) + { + postButton->setEnabled(true); + frame->setStyleSheet("QFrame#frame{ border: 2px solid #6ACEFF;border-radius: 10px;background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 #0076B1, stop:1 #12A3EB); }"); + } + else + { + postButton->setEnabled(false); + } + + /* replace all the messages with new ones */ + std::list::iterator mit; + for(mit = mBlogMsgItems.begin(); mit != mBlogMsgItems.end(); mit++) + { + delete (*mit); + } + mBlogMsgItems.clear(); + + std::list msgs; + std::list::iterator it; + + rsBlogs->getBlogMsgList(mBlogId, msgs); + + for(it = msgs.begin(); it != msgs.end(); it++) + { + BlogsMsgItem *cmi = new BlogsMsgItem(this, 0, mPeerId, mBlogId, it->msgId, true); + + mBlogMsgItems.push_back(cmi); + verticalLayout_2->addWidget(cmi); + } +} + +void BlogsDialog::unsubscribeBlog() +{ +#ifdef BLOG_DEBUG + std::cerr << "BlogsDialog::unsubscribeBlog()"; + std::cerr << std::endl; +#endif + if (rsBlogs) + { + rsBlogs->blogSubscribe(mBlogId, false); + } + updateBlogMsgs(); +} + +void BlogsDialog::subscribeBlog() +{ +#ifdef BLOG_DEBUG + std::cerr << "BlogsDialog::subscribeBlog()"; + std::cerr << std::endl; +#endif + if (rsBlogs) + { + rsBlogs->blogSubscribe(mBlogId, true); + } + updateBlogMsgs(); +} + +void BlogsDialog::toggleSelection(const QModelIndex &index) +{ + QItemSelectionModel *selectionModel = treeView->selectionModel(); + if (index.child(0, 0).isValid()) + selectionModel->select(index, QItemSelectionModel::Toggle); +} + +void BlogsDialog::showBlogDetails() +{ + if (mBlogId == "") + { + return; + } + + if (!rsBlogs) + return; + + BlogDetails *blogui = new BlogDetails(); + + blogui->showDetails(mBlogId); + blogui->show(); + + /* window will destroy itself! */ +} diff --git a/retroshare-gui/src/gui/unfinished/blogs/BlogsDialog.h b/retroshare-gui/src/gui/unfinished/blogs/BlogsDialog.h new file mode 100644 index 000000000..2366d317b --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/BlogsDialog.h @@ -0,0 +1,107 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _BLOGSDIALOG_H +#define _BLOGSDIALOG_H + +#include "gui/mainpage.h" +#include "ui_BlogsDialog.h" + +#include "gui/feeds/FeedHolder.h" + +class QStandardItemModel; + +#define OWN 0 +#define SUBSCRIBED 1 +#define POPULAR 2 +#define OTHER 3 + +class BlogsMsgItem; + + +class BlogsDialog : public MainPage, public FeedHolder, private Ui::BlogsDialog +{ + Q_OBJECT + +public: + /** Default Constructor */ + BlogsDialog(QWidget *parent = 0); + /** Default Destructor */ + + +virtual void deleteFeedItem(QWidget *item, uint32_t type); +virtual void openChat(std::string peerId); + +public slots: + + void selectBlog( std::string ); + void selectBlog(const QModelIndex &); + void toggleSelection(const QModelIndex &); + +private slots: + + void blogListCustomPopupMenu( QPoint point ); + + void checkUpdate(); + + void createBlog(); + //void sendMsg(); + + void blogSelection(); + + void subscribeBlog(); + void unsubscribeBlog(); + + void createMsg(); + + void showBlogDetails(); + +private: + + void updateBlogList(); + void updateBlogListOwn(std::list &ids); + void updateBlogListSub(std::list &ids); + void updateBlogListPop(std::list &ids); + void updateBlogListOther(std::list &ids); + + void updateBlogMsgs(); + + QStandardItemModel *model; + + std::string mBlogId; /* current Blog */ + std::string mPeerId; + + /* Layout Pointers */ + QBoxLayout *mMsgLayout; + + + + std::list mBlogMsgItems; + + QFont mBlogFont; + QFont itemFont; + +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/blogs/BlogsDialog.ui b/retroshare-gui/src/gui/unfinished/blogs/BlogsDialog.ui new file mode 100644 index 000000000..92c1bbed9 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/BlogsDialog.ui @@ -0,0 +1,575 @@ + + + BlogsDialog + + + + 0 + 0 + 681 + 476 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Form + + + + + + + 0 + 0 + + + + + 222 + 0 + + + + + 222 + 16777215 + + + + + 0 + 0 + + + + + 221 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + + 220 + 0 + + + + + 220 + 38 + + + + + 220 + 0 + + + + QFrame#chheaderframe{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + + + 0 + + + + + + 24 + 24 + + + + + + + :/images/kblogger.png + + + true + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + + + + + Qt::Horizontal + + + + 123 + 13 + + + + + + + + Add + + + QPushButton::menu-indicator { + subcontrol-origin: padding; + subcontrol-position: bottom right; + } + + QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open { + position: relative; + top: 2px; left: 2px; /* shift the arrow by 2 px */ + } + + QPushButton:hover { + border: 1px solid #CCCCCC; + } + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + 16 + 16 + + + + false + + + true + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + + + + + + :/images/mail_send.png:/images/mail_send.png + + + true + + + + + + + + + + Qt::CustomContextMenu + + + + + + + + + + + + QFrame#frame{ +border: 2px solid #6ACEFF; +border-radius: 10px; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #0076B1, stop:1 #12A3EB);} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + 16 + + + 9 + + + + + + 64 + 64 + + + + + 64 + 64 + + + + QLabel{ +border: 2px solid white; +border-radius: 10px; +} + + + + + + :/images/hi64-app-kblogger.png + + + false + + + Qt::AlignCenter + + + + + + + + 75 + true + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + true + + + + + + + + + 9 + + + 9 + + + + + + 0 + 0 + + + + + 26 + 26 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + Unsubscribe + + + + + + + + 0 + 0 + + + + + 26 + 26 + + + + + 16777215 + 26 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + Subscribe + + + + :/images/konqsidebar_news16.png:/images/konqsidebar_news16.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + 1 + 0 + + + + + 0 + 0 + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + true + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + 0 + 0 + 429 + 332 + + + + QWidget#scrollAreaWidgetContents{border: none;} + + + + 0 + + + 0 + + + + + + + + Qt::Vertical + + + + 391 + 266 + + + + + + + + + + + + + + + + + + :/images/kblogger.png:/images/kblogger.png + + + Create New Blog + + + Create New Blog + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/blogs/BlogsMsgItem.cpp b/retroshare-gui/src/gui/unfinished/blogs/BlogsMsgItem.cpp new file mode 100644 index 000000000..7536b242b --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/BlogsMsgItem.cpp @@ -0,0 +1,195 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "BlogsMsgItem.h" +#include "gui/feeds/FeedHolder.h" + +#include + + +/**** + * #define DEBUG_ITEM 1 + ****/ + +/** Constructor */ +BlogsMsgItem::BlogsMsgItem(FeedHolder *parent, uint32_t feedId, std::string peerId, std::string blogId, std::string msgId, bool isHome) +:QWidget(NULL), mParent(parent), mFeedId(feedId), + mPeerId(peerId), mBlogId(blogId), mMsgId(msgId), mIsHome(isHome) +{ + /* Invoke the Qt Designer generated object setup routine */ + setupUi(this); + + /* general ones */ + connect( expandButton, SIGNAL( clicked( void ) ), this, SLOT( toggle ( void ) ) ); + connect( clearButton, SIGNAL( clicked( void ) ), this, SLOT( removeItem ( void ) ) ); + //connect( gotoButton, SIGNAL( clicked( void ) ), this, SLOT( gotoHome ( void ) ) ); + + /* specific ones */ + //connect( playButton, SIGNAL( clicked( void ) ), this, SLOT( playMedia ( void ) ) ); + connect( unsubscribeButton, SIGNAL( clicked( void ) ), this, SLOT( unsubscribeChannel ( void ) ) ); + + small(); + updateItemStatic(); + updateItem(); + +} + + +void BlogsMsgItem::updateItemStatic() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "ChanMsgItem::updateItemStatic()"; + std::cerr << std::endl; +#endif + + BlogMsgInfo cmi; + + if (!rsBlogs) + return; + + if (!rsBlogs->getBlogMessage(mBlogId, mMsgId, cmi)) + return; + + QString title; + + if (!mIsHome) + { + BlogInfo ci; + rsBlogs->getBlogInfo(mBlogId, ci); + title = "Channel Feed: "; + title += QString::fromStdWString(ci.blogName); + titleLabel->setText(title); + //subjectLabel->setText(QString::fromStdWString(cmi.subject)); + } + else + { + /* subject */ + titleLabel->setText(QString::fromStdWString(cmi.subject)); + /* Blog Message */ + textBrowser->setHtml( QString::fromStdWString(cmi.msg)); + } + + //msgLabel->setText(QString::fromStdWString(cmi.msg)); + //msgcommentstextEdit->setHtml(QString::fromStdWString(cmi.msg)); + + QDateTime qtime; + qtime.setTime_t(cmi.ts); + QString timestamp = qtime.toString("dd.MMMM yyyy hh:mm:ss"); + datetimelabel->setText(timestamp); + + //playButton->setEnabled(false); + + if (mIsHome) + { + /* disable buttons */ + clearButton->setEnabled(false); + //gotoButton->setEnabled(false); + unsubscribeButton->setEnabled(false); + + clearButton->hide(); + } + + /* don't really want this at all! */ + unsubscribeButton->hide(); + //playButton->hide(); +} + + +void BlogsMsgItem::updateItem() +{ + /* fill in */ +#ifdef DEBUG_ITEM + std::cerr << "BlogMsgItem::updateItem()"; + std::cerr << std::endl; +#endif + + +} + + +void BlogsMsgItem::small() +{ + expandFrame->hide(); +} + +void BlogsMsgItem::toggle() +{ + if (expandFrame->isHidden()) + { + expandFrame->show(); + expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); + expandButton->setToolTip(tr("Hide")); + } + else + { + expandFrame->hide(); + expandButton->setIcon(QIcon(QString(":/images/edit_add24.png"))); + expandButton->setToolTip(tr("Expand")); + } +} + + +void BlogsMsgItem::removeItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChanMsgItem::removeItem()"; + std::cerr << std::endl; +#endif + hide(); + if (mParent) + { + mParent->deleteFeedItem(this, mFeedId); + } +} + + +void BlogsMsgItem::gotoHome() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChanMsgItem::gotoHome()"; + std::cerr << std::endl; +#endif +} + +/*********** SPECIFIC FUNCTIOSN ***********************/ + + +void BlogsMsgItem::unsubscribeChannel() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChanMsgItem::unsubscribeChannel()"; + std::cerr << std::endl; +#endif +} + + +void BlogsMsgItem::playMedia() +{ +#ifdef DEBUG_ITEM + std::cerr << "ChanMsgItem::playMedia()"; + std::cerr << std::endl; +#endif +} + + diff --git a/retroshare-gui/src/gui/unfinished/blogs/BlogsMsgItem.h b/retroshare-gui/src/gui/unfinished/blogs/BlogsMsgItem.h new file mode 100644 index 000000000..ee307daae --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/BlogsMsgItem.h @@ -0,0 +1,71 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _BLOGS_MSG_ITEM_DIALOG_H +#define _BLOGS_MSG_ITEM_DIALOG_H + +#include "ui_BlogsMsgItem.h" +#include + + +class FeedHolder; +class SubFileItem; + +class BlogsMsgItem : public QWidget, private Ui::BlogsMsgItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + BlogsMsgItem(FeedHolder *parent, uint32_t feedId, std::string peerId, std::string blogId, std::string msgId, bool isHome); + + /** Default Destructor */ + + void updateItemStatic(); + void small(); + +private slots: + /* default stuff */ + void gotoHome(); + void removeItem(); + void toggle(); + + void playMedia(); + void unsubscribeChannel(); + + void updateItem(); + +private: + FeedHolder *mParent; + uint32_t mFeedId; + + std::string mBlogId; + std::string mMsgId; + std::string mPeerId; + + bool mIsHome; + +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/blogs/BlogsMsgItem.ui b/retroshare-gui/src/gui/unfinished/blogs/BlogsMsgItem.ui new file mode 100644 index 000000000..4972df312 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/BlogsMsgItem.ui @@ -0,0 +1,274 @@ + + + BlogsMsgItem + + + + 0 + 0 + 516 + 294 + + + + Form + + + QToolButton, QPushButton, QComboBox { +border-image: url(:/images/btn_26.png) 4; +border-width: 4; +padding: 0px 6px; +font-size: 12px; +} + +QToolButton:hover, QPushButton:hover, QComboBox:hover { +border-image: url(:/images/btn_26_hover.png) 4; +} + +QToolButton:disabled, QPushButton:disabled, QComboBox::disabled { +color:gray; +} + +QToolButton:pressed, QPushButton:pressed{ +border-image: url(:/images/btn_26_pressed.png) 4; +} + + + + 0 + + + 6 + + + + + + 0 + 0 + + + + QFrame#frame{border: 3px solid #407AC1; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FFFFFF, stop:1 #F2F2F2);; +border-radius: 10px;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 0 + 0 + + + + + 11 + 75 + true + true + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + + + + 75 + true + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 288 + 21 + + + + + + + + + 0 + 0 + + + + Expand + + + + + + + + + + :/images/edit_add24.png:/images/edit_add24.png + + + + + + + + 0 + 0 + + + + Remove Item + + + + + + + :/images/close_normal.png:/images/close_normal.png + + + + + + + + 0 + 0 + + + + Unsubscribe From Channel + + + + + + + :/images/mail_delete.png:/images/mail_delete.png + + + + + + + + 0 + 0 + + + + QTextBrowser#textBrowser{border: 2px solid #D3D3D3; +background-color: transparent; +border-radius: 10px;} + + + + + + + + + QFrame#expandFrame{border: 2px solid #D3D3D3; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FFFFFF, stop:1 #F2F2F2);; +border-radius: 10px;} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + Comments here + + + + + + + + + + + 16777215 + 60 + + + + + + + + Qt::Horizontal + + + + 398 + 20 + + + + + + + + Comment + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.cpp b/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.cpp new file mode 100644 index 000000000..3798041af --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.cpp @@ -0,0 +1,173 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "CreateBlog.h" +#include "util/misc.h" + +#include + +/** Constructor */ +CreateBlog::CreateBlog(QWidget *parent, bool isForum) +: QDialog(parent), mIsForum(isForum) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + // connect up the buttons. + connect( ui.cancelButton, SIGNAL( clicked ( bool ) ), this, SLOT( cancelBlog( ) ) ); + connect( ui.createButton, SIGNAL( clicked ( bool ) ), this, SLOT( createBlog( ) ) ); + connect( ui.LogoButton, SIGNAL(clicked() ), this , SLOT(addBlogLogo())); + connect( ui.blogLogoButton, SIGNAL(clicked() ), this , SLOT(addBlogLogo())); + + newBlog(); + +} + +void CreateBlog::show() +{ + //loadSettings(); + if(!this->isVisible()) { + QWidget::show(); + + } +} + + +void CreateBlog::newBlog() +{ + + if (mIsForum) + { + /* enforce Public for the moment */ + ui.typePublic->setChecked(true); + + ui.typePrivate->setEnabled(false); + ui.typeEncrypted->setEnabled(false); + + ui.msgAnon->setChecked(true); + //ui.msgAuth->setEnabled(false); + } + else + { + /* enforce Private for the moment */ + ui.typePrivate->setChecked(true); + + ui.typePublic->setEnabled(false); + ui.typeEncrypted->setEnabled(false); + + ui.msgAnon->setChecked(true); + ui.msgAuth->setEnabled(false); + ui.msgGroupBox->hide(); + } +} + +void CreateBlog::createBlog() +{ + QString name = ui.forumName->text(); + QString desc = ui.forumDesc->toPlainText(); //toHtml(); + uint32_t flags = 0; + + if(name.isEmpty()) + { /* error message */ + QMessageBox::warning(this, tr("RetroShare"), + tr("Please add a Name"), + QMessageBox::Ok, QMessageBox::Ok); + + return; //Don't add a empty name!! + } + else + + if (ui.typePublic->isChecked()) + { + flags |= RS_DISTRIB_PUBLIC; + } + else if (ui.typePrivate->isChecked()) + { + flags |= RS_DISTRIB_PRIVATE; + } + else if (ui.typeEncrypted->isChecked()) + { + flags |= RS_DISTRIB_ENCRYPTED; + } + + if (ui.msgAuth->isChecked()) + { + flags |= RS_DISTRIB_AUTHEN_REQ; + } + else if (ui.msgAnon->isChecked()) + { + flags |= RS_DISTRIB_AUTHEN_ANON; + } + + QByteArray ba; + QBuffer buffer(&ba); + + if(!picture.isNull()){ + // send chan image + + buffer.open(QIODevice::WriteOnly); + picture.save(&buffer, "PNG"); // writes image into ba in PNG format + } + + if (rsBlogs) + { + rsBlogs->createBlog(name.toStdWString(), desc.toStdWString(), flags, + (unsigned char*) ba.data(), ba.size()); + } + + + close(); + return; +} + +void CreateBlog::addBlogLogo(){ + + QString fileName; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_IMAGES, tr("Load File"), tr("Pictures (*.png *.xpm *.jpg)"), fileName)) + { + picture = QPixmap(fileName).scaled(64,64, Qt::IgnoreAspectRatio,Qt::SmoothTransformation); + + // to show the selected + ui.blogLogoButton->setIcon(picture); + + std::cerr << "Sending avatar image down the pipe" << std::endl ; + + // send avatar down the pipe for other peers to get it. + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + picture.save(&buffer, "PNG"); // writes image into ba in PNG format + + std::cerr << "Image size = " << ba.size() << std::endl ; + } + +} + +void CreateBlog::cancelBlog() +{ + close(); + return; +} + + diff --git a/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.h b/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.h new file mode 100644 index 000000000..842987053 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.h @@ -0,0 +1,60 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CREATE_BLOG_DIALOG_H +#define _CREATE_BLOG_DIALOG_H + +#include "ui_CreateBlog.h" + +class CreateBlog : public QDialog +{ + Q_OBJECT + +public: + CreateBlog(QWidget *parent = 0, bool isForum = true); + +void newBlog(); /* cleanup */ + + /** Qt Designer generated object */ + Ui::CreateBlog ui; + + QPixmap picture; + +public slots: + /** Overloaded QWidget.show */ + void show(); + +private slots: + + /* actions to take.... */ +void createBlog(); +void cancelBlog(); +void addBlogLogo(); + + +private: + + + bool mIsForum; +}; + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.ui b/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.ui new file mode 100644 index 000000000..091fa047f --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/CreateBlog.ui @@ -0,0 +1,329 @@ + + + CreateBlog + + + + 0 + 0 + 534 + 545 + + + + Create new Blog + + + + :/images/rstray3.png:/images/rstray3.png + + + + 0 + + + 0 + + + + + + 16777215 + 64 + + + + QFrame#frame_2{background-image: url(:/images/connect/connectFriendBanner.png);} + + + QFrame::NoFrame + + + QFrame::Raised + + + + 6 + + + 6 + + + + + + 48 + 48 + + + + + + + + + + :/images/hi48-app-kblogger.png + + + true + + + + + + + color: rgb(255, 255, 255); + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + + Name + + + + + + + + + + + + Description + + + + + + + + + + Type: + + + + 0 + + + 6 + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + + + Private - (Private Publish Key required to view Messages) + + + + + + + + + + Allowed Messages + + + + 0 + + + 6 + + + + + Authemticated Messages + + + + + + + Anonymous Messages + + + + + + + + + + Blog Logo + + + + 6 + + + 6 + + + 6 + + + 2 + + + 6 + + + + + + + + 64 + 64 + + + + + 64 + 64 + + + + +border: 2px solid white; +border-radius: 10px; + + + + + + + + :/images/hi64-app-kblogger.png:/images/hi64-app-kblogger.png + + + + 64 + 64 + + + + + + + + Add Blog Logo + + + + :/images/add_image24.png:/images/add_image24.png + + + + + + + Qt::Horizontal + + + + 118 + 20 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 238 + 20 + + + + + + + + Cancel + + + + + + + Create + + + true + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.cpp b/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.cpp new file mode 100644 index 000000000..3a1ff2959 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.cpp @@ -0,0 +1,923 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CreateBlogMsg.h" +#include "gui/msgs/textformat.h" +#include "util/misc.h" + +#include + +/** Constructor */ +CreateBlogMsg::CreateBlogMsg(std::string cId ,QWidget* parent, Qt::WFlags flags) +: mBlogId(cId), QMainWindow (parent, flags) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + setAttribute ( Qt::WA_DeleteOnClose, true ); + + setupFileActions(); + setupEditActions(); + setupViewActions(); + setupInsertActions(); + setupParagraphActions(); + + setAcceptDrops(true); + setStartupText(); + + newBlogMsg(); + + ui.toolBar_2->addAction(ui.actionIncreasefontsize); + ui.toolBar_2->addAction(ui.actionDecreasefontsize); + ui.toolBar_2->addAction(ui.actionBlockquoute); + ui.toolBar_2->addAction(ui.actionOrderedlist); + ui.toolBar_2->addAction(ui.actionUnorderedlist); + ui.toolBar_2->addAction(ui.actionBlockquoute); + ui.toolBar_2->addAction(ui.actionCode); + ui.toolBar_2->addAction(ui.actionsplitPost); + + setupTextActions(); + + connect(ui.actionPublish, SIGNAL(triggered()), this, SLOT(sendMsg())); + connect(ui.actionNew, SIGNAL(triggered()), this, SLOT (fileNew())); + + connect(ui.actionIncreasefontsize, SIGNAL (triggered()), this, SLOT (fontSizeIncrease())); + connect(ui.actionDecreasefontsize, SIGNAL (triggered()), this, SLOT (fontSizeDecrease())); + connect(ui.actionBlockquoute, SIGNAL (triggered()), this, SLOT (blockQuote())); + connect(ui.actionCode, SIGNAL (triggered()), this, SLOT (toggleCode())); + connect(ui.actionsplitPost, SIGNAL (triggered()), this, SLOT (addPostSplitter())); + connect(ui.actionOrderedlist, SIGNAL (triggered()), this, SLOT (addOrderedList())); + connect(ui.actionUnorderedlist, SIGNAL (triggered()), this, SLOT (addUnorderedList())); + + //connect(webView, SIGNAL(loadFinished(bool)),this, SLOT(updateTextEdit())); + connect( ui.msgEdit, SIGNAL( textChanged(const QString &)), this, SLOT(updateTextEdit())); + + connect( ui.msgEdit, SIGNAL(currentCharFormatChanged(QTextCharFormat)), + this, SLOT(currentCharFormatChanged(QTextCharFormat))); + connect( ui.msgEdit, SIGNAL(cursorPositionChanged()), + this, SLOT(cursorPositionChanged())); + + QPalette palette = QApplication::palette(); + codeBackground = palette.color( QPalette::Active, QPalette::Midlight ); + + fontChanged(ui.msgEdit->font()); + colorChanged(ui.msgEdit->textColor()); + alignmentChanged(ui.msgEdit->alignment()); + + connect( ui.msgEdit->document(), SIGNAL(modificationChanged(bool)), + actionSave, SLOT(setEnabled(bool))); + connect( ui.msgEdit->document(), SIGNAL(modificationChanged(bool)), + this, SLOT(setWindowModified(bool))); + connect( ui.msgEdit->document(), SIGNAL(undoAvailable(bool)), + actionUndo, SLOT(setEnabled(bool))); + connect( ui.msgEdit->document(), SIGNAL(undoAvailable(bool)), + ui.actionUndo, SLOT(setEnabled(bool))); + connect( ui.msgEdit->document(), SIGNAL(redoAvailable(bool)), + actionRedo, SLOT(setEnabled(bool))); + + setWindowModified( ui.msgEdit->document()->isModified()); + actionSave->setEnabled( ui.msgEdit->document()->isModified()); + actionUndo->setEnabled( ui.msgEdit->document()->isUndoAvailable()); + ui.actionUndo->setEnabled( ui.msgEdit->document()->isUndoAvailable()); + actionRedo->setEnabled( ui.msgEdit->document()->isRedoAvailable()); + + connect(actionUndo, SIGNAL(triggered()), ui.msgEdit, SLOT(undo())); + connect(ui.actionUndo, SIGNAL(triggered()), ui.msgEdit, SLOT(undo())); + connect(actionRedo, SIGNAL(triggered()), ui.msgEdit, SLOT(redo())); + + actionCut->setEnabled(false); + actionCopy->setEnabled(false); + + connect(actionCut, SIGNAL(triggered()), ui.msgEdit, SLOT(cut())); + connect(actionCopy, SIGNAL(triggered()), ui.msgEdit, SLOT(copy())); + connect(actionPaste, SIGNAL(triggered()), ui.msgEdit, SLOT(paste())); + + connect(ui.msgEdit, SIGNAL(copyAvailable(bool)), actionCut, SLOT(setEnabled(bool))); + connect(ui.msgEdit, SIGNAL(copyAvailable(bool)), actionCopy, SLOT(setEnabled(bool))); + +#ifndef QT_NO_CLIPBOARD + connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged())); +#endif + + //defaultCharFormat + defaultCharFormat = ui.msgEdit->currentCharFormat(); + + const QFont defaultFont = ui.msgEdit->document()->defaultFont(); + defaultCharFormat.setFont( defaultFont ); + defaultCharFormat.setForeground( ui.msgEdit->currentCharFormat().foreground() ); + defaultCharFormat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 0 ) ); + defaultCharFormat.setBackground( palette.color( QPalette::Active, + QPalette::Base ) ); + defaultCharFormat.setProperty( TextFormat::HasCodeStyle, QVariant( false ) ); + + //defaultBlockFormat + defaultBlockFormat = ui.msgEdit->textCursor().blockFormat(); + +} + + +void CreateBlogMsg::cancelMsg() +{ + std::cerr << "CreateBlogMsg::cancelMsg()"; + std::cerr << std::endl; + close(); + return; +} + +void CreateBlogMsg::newBlogMsg() +{ + + if (!rsBlogs) + return; + + BlogInfo ci; + if (!rsBlogs->getBlogInfo(mBlogId, ci)) + { + + return; + } + + ui.channelName->setText(QString::fromStdWString(ci.blogName)); + +} + + +void CreateBlogMsg::sendMsg() +{ + std::cerr << "CreateBlogMsg::sendMsg()"; + std::cerr << std::endl; + + /* construct message bits */ + std::wstring subject = ui.subjectEdit->text().toStdWString(); + std::wstring msg = ui.msgEdit->toHtml().toStdWString(); + + sendMessage(subject, msg); + +} + +void CreateBlogMsg::sendMessage(std::wstring subject, std::wstring msg) +{ + std::cerr << "CreateBlogMsg::sendMessage()" << std::endl; + + QString name = ui.subjectEdit->text(); + + if(name.isEmpty()) + { /* error message */ + QMessageBox::warning(this, tr("RetroShare"), + tr("Please add a Subject"), + QMessageBox::Ok, QMessageBox::Ok); + + return; //Don't add a empty Subject!! + } + else + + /* rsChannels */ + if (rsBlogs) + { + BlogMsgInfo msgInfo; + + msgInfo.blogId = mBlogId; + msgInfo.msgId = ""; + + msgInfo.subject = subject; + msgInfo.msg = msg; + msgInfo.msgIdReply = "nothing"; + rsBlogs->BlogMessageSend(msgInfo); + } + + close(); + return; + +} + +void CreateBlogMsg::fontSizeIncrease() +{ + if ( !( ui.msgEdit->textCursor().blockFormat().hasProperty( TextFormat::HtmlHeading ) && + ui.msgEdit->textCursor().blockFormat().intProperty( TextFormat::HtmlHeading ) ) ) { + QTextCharFormat format; + int idx = ui.msgEdit->currentCharFormat().intProperty( QTextFormat::FontSizeAdjustment ); + if ( idx < 3 ) { + format.setProperty( QTextFormat::FontSizeAdjustment, QVariant( ++idx ) ); + ui.msgEdit->textCursor().mergeCharFormat( format ); + } + } + ui.msgEdit->setFocus( Qt::OtherFocusReason ); +} + +void CreateBlogMsg::fontSizeDecrease() +{ + if ( !( ui.msgEdit->textCursor().blockFormat().hasProperty( TextFormat::HtmlHeading ) && + ui.msgEdit->textCursor().blockFormat().intProperty( TextFormat::HtmlHeading ) ) ) { + QTextCharFormat format; + int idx = ui.msgEdit->currentCharFormat().intProperty( QTextFormat::FontSizeAdjustment ); + if ( idx > -1 ) { + format.setProperty( QTextFormat::FontSizeAdjustment, QVariant( --idx ) ); + ui.msgEdit->textCursor().mergeCharFormat( format ); + } + } + ui.msgEdit->setFocus( Qt::OtherFocusReason ); +} + +void CreateBlogMsg::blockQuote() +{ + QTextBlockFormat blockFormat = ui.msgEdit->textCursor().blockFormat(); + QTextBlockFormat f; + + if ( blockFormat.hasProperty( TextFormat::IsBlockQuote ) && + blockFormat.boolProperty( TextFormat::IsBlockQuote ) ) { + f.setProperty( TextFormat::IsBlockQuote, QVariant( false ) ); + f.setLeftMargin( 0 ); + f.setRightMargin( 0 ); + } else { + f.setProperty( TextFormat::IsBlockQuote, QVariant( true ) ); + f.setLeftMargin( 40 ); + f.setRightMargin( 40 ); + } + ui.msgEdit->textCursor().mergeBlockFormat( f ); +} + +void CreateBlogMsg::toggleCode() +{ + static QString preFontFamily; + + QTextCharFormat charFormat = ui.msgEdit->currentCharFormat(); + QTextCharFormat f; + + if ( charFormat.hasProperty( TextFormat::HasCodeStyle ) && + charFormat.boolProperty( TextFormat::HasCodeStyle ) ) { + f.setProperty( TextFormat::HasCodeStyle, QVariant( false ) ); + f.setBackground( defaultCharFormat.background() ); + f.setFontFamily( preFontFamily ); + ui.msgEdit->textCursor().mergeCharFormat( f ); + + } else { + preFontFamily = ui.msgEdit->fontFamily(); + f.setProperty( TextFormat::HasCodeStyle, QVariant( true ) ); + f.setBackground( codeBackground ); + f.setFontFamily( "Dejavu Sans Mono" ); + ui.msgEdit->textCursor().mergeCharFormat( f ); + } + ui.msgEdit->setFocus( Qt::OtherFocusReason ); +} + +void CreateBlogMsg::addPostSplitter() +{ + QTextBlockFormat f = ui.msgEdit->textCursor().blockFormat(); + QTextBlockFormat f1 = f; + + f.setProperty( TextFormat::IsHtmlTagSign, true ); + f.setProperty( QTextFormat::BlockTrailingHorizontalRulerWidth, + QTextLength( QTextLength::PercentageLength, 80 ) ); + if ( ui.msgEdit->textCursor().block().text().isEmpty() ) { + ui.msgEdit->textCursor().mergeBlockFormat( f ); + } else { + ui.msgEdit->textCursor().insertBlock( f ); + } + ui.msgEdit->textCursor().insertBlock( f1 ); +} + +void CreateBlogMsg::setStartupText() +{ + QString string = "

    HTML Previewer

    " + "

    This example shows you how to use QWebView to" + " preview HTML data written in a QPlainTextEdit.

    " + " "; + //webView->setHtml(string); +} + +void CreateBlogMsg::updateTextEdit() +{ + //QWebFrame *mainFrame = webView->page()->mainFrame(); + QString frameText = ui.msgEdit->toHtml(); + ui.plainTextEdit->setPlainText(frameText); + //QString text = plainTextEdit->toPlainText(); +} + +void CreateBlogMsg::textBold() +{ + QTextCharFormat fmt; + fmt.setFontWeight(actionTextBold->isChecked() ? QFont::Bold : QFont::Normal); + mergeFormatOnWordOrSelection(fmt); +} + +void CreateBlogMsg::textUnderline() +{ + QTextCharFormat fmt; + fmt.setFontUnderline(actionTextUnderline->isChecked()); + mergeFormatOnWordOrSelection(fmt); +} + +void CreateBlogMsg::textItalic() +{ + QTextCharFormat fmt; + fmt.setFontItalic(actionTextItalic->isChecked()); + mergeFormatOnWordOrSelection(fmt); +} + + +void CreateBlogMsg::textAlign(QAction *a) +{ + if (a == actionAlignLeft) + ui.msgEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute); + else if (a == actionAlignCenter) + ui.msgEdit->setAlignment(Qt::AlignHCenter | Qt::AlignAbsolute); + else if (a == actionAlignRight) + ui.msgEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute); + else if (a == actionAlignJustify) + ui.msgEdit->setAlignment(Qt::AlignJustify | Qt::AlignAbsolute); + +} + +void CreateBlogMsg::alignmentChanged(Qt::Alignment a) +{ + if (a & Qt::AlignLeft) { + actionAlignLeft->setChecked(true); + } else if (a & Qt::AlignHCenter) { + actionAlignCenter->setChecked(true); + } else if (a & Qt::AlignRight) { + actionAlignRight->setChecked(true); + } else if (a & Qt::AlignJustify) { + actionAlignJustify->setChecked(true); + } +} + +void CreateBlogMsg::textFamily(const QString &f) +{ + QTextCharFormat fmt; + fmt.setFontFamily(f); + mergeFormatOnWordOrSelection(fmt); +} + +void CreateBlogMsg::textSize(const QString &p) +{ + qreal pointSize = p.toFloat(); + if (p.toFloat() > 0) { + QTextCharFormat fmt; + fmt.setFontPointSize(pointSize); + mergeFormatOnWordOrSelection(fmt); + } +} + +void CreateBlogMsg::changeFormatType(int styleIndex ) +{ + ui.msgEdit->setFocus( Qt::OtherFocusReason ); + + QTextCursor cursor = ui.msgEdit->textCursor(); + //QTextBlockFormat bformat = cursor.blockFormat(); + QTextBlockFormat bformat; + QTextCharFormat cformat; + + switch (styleIndex) { + default: + case 0: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 0 ) ); + cformat.setFontWeight( QFont::Normal ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 0 ) ); + break; + case 1: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 1 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 3 ) ); + break; + case 2: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 2 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 2 ) ); + break; + case 3: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 3 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 1 ) ); + break; + case 4: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 4 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( 0 ) ); + break; + case 5: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 5 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( -1 ) ); + break; + case 6: + bformat.setProperty( TextFormat::HtmlHeading, QVariant( 6 ) ); + cformat.setFontWeight( QFont::Bold ); + cformat.setProperty( QTextFormat::FontSizeAdjustment, QVariant( -2 ) ); + break; + } + //cformat.clearProperty( TextFormat::HasCodeStyle ); + + cursor.beginEditBlock(); + cursor.mergeBlockFormat( bformat ); + cursor.select( QTextCursor::BlockUnderCursor ); + cursor.mergeCharFormat( cformat ); + cursor.endEditBlock(); +} + + +void CreateBlogMsg::textColor() +{ + QColor col = QColorDialog::getColor(ui.msgEdit->textColor(), this); + if (!col.isValid()) + return; + QTextCharFormat fmt; + fmt.setForeground(col); + mergeFormatOnWordOrSelection(fmt); + colorChanged(col); +} + +void CreateBlogMsg::fontChanged(const QFont &f) +{ + comboFont->setCurrentIndex(comboFont->findText(QFontInfo(f).family())); + comboSize->setCurrentIndex(comboSize->findText(QString::number(f.pointSize()))); + actionTextBold->setChecked(f.bold()); + actionTextItalic->setChecked(f.italic()); + actionTextUnderline->setChecked(f.underline()); +} + +void CreateBlogMsg::colorChanged(const QColor &c) +{ + QPixmap pix(16, 16); + pix.fill(c); + //ui.colorbtn->setIcon(pix); + actionTextColor->setIcon(pix); +} + +void CreateBlogMsg::mergeFormatOnWordOrSelection(const QTextCharFormat &format) +{ + QTextCursor cursor = ui.msgEdit->textCursor(); + if (!cursor.hasSelection()) + cursor.select(QTextCursor::WordUnderCursor); + cursor.mergeCharFormat(format); + ui.msgEdit->mergeCurrentCharFormat(format); +} + +void CreateBlogMsg::currentCharFormatChanged(const QTextCharFormat &format) +{ + fontChanged(format.font()); + colorChanged(format.foreground().color()); +} + +void CreateBlogMsg::cursorPositionChanged() +{ + alignmentChanged(ui.msgEdit->alignment()); +} + +void CreateBlogMsg::clipboardDataChanged() +{ +#ifndef QT_NO_CLIPBOARD + actionPaste->setEnabled(!QApplication::clipboard()->text().isEmpty()); +#endif +} + + +void CreateBlogMsg::addOrderedList() +{ + ui.msgEdit->textCursor().createList( QTextListFormat::ListDecimal ); + +} + +void CreateBlogMsg::addUnorderedList() +{ + ui.msgEdit->textCursor().createList( QTextListFormat::ListDisc ); +} + +void CreateBlogMsg::setupFileActions() +{ + QMenu *menu = new QMenu(tr("&File"), this); + menuBar()->addMenu(menu); + + QAction *a; + + a = new QAction(QIcon(":/images/textedit/filenew.png"), tr("&New"), this); + a->setShortcut(QKeySequence::New); + connect(a, SIGNAL(triggered()), this, SLOT(fileNew())); + menu->addAction(a); + + a = new QAction(QIcon(":/images/textedit/fileopen.png"), tr("&Open..."), this); + a->setShortcut(QKeySequence::Open); + connect(a, SIGNAL(triggered()), this, SLOT(fileOpen())); + menu->addAction(a); + + menu->addSeparator(); + + actionSave = a = new QAction(QIcon(":/images/textedit/filesave.png"), tr("&Save"), this); + a->setShortcut(QKeySequence::Save); + connect(a, SIGNAL(triggered()), this, SLOT(fileSave())); + a->setEnabled(false); + menu->addAction(a); + + a = new QAction(tr("Save &As..."), this); + connect(a, SIGNAL(triggered()), this, SLOT(fileSaveAs())); + menu->addAction(a); + menu->addSeparator(); + + a = new QAction(QIcon(":/images/textedit/fileprint.png"), tr("&Print..."), this); + a->setShortcut(QKeySequence::Print); + connect(a, SIGNAL(triggered()), this, SLOT(filePrint())); + menu->addAction(a); + + a = new QAction(QIcon(":/images/textedit/fileprint.png"), tr("Print Preview..."), this); + connect(a, SIGNAL(triggered()), this, SLOT(filePrintPreview())); + menu->addAction(a); + + a = new QAction(QIcon(":/images/textedit/exportpdf.png"), tr("&Export PDF..."), this); + a->setShortcut(Qt::CTRL + Qt::Key_D); + connect(a, SIGNAL(triggered()), this, SLOT(filePrintPdf())); + menu->addAction(a); + + menu->addSeparator(); + + a = new QAction(tr("&Quit"), this); + a->setShortcut(Qt::CTRL + Qt::Key_Q); + connect(a, SIGNAL(triggered()), this, SLOT(cancelMsg())); + menu->addAction(a); +} + +void CreateBlogMsg::setupEditActions() +{ + QMenu *menu = new QMenu(tr("&Edit"), this); + menuBar()->addMenu(menu); + + QAction *a; + a = actionUndo = new QAction(QIcon(":/images/textedit/editundo.png"), tr("&Undo"), this); + a->setShortcut(QKeySequence::Undo); + menu->addAction(a); + a = actionRedo = new QAction(QIcon(":/images/textedit/editredo.png"), tr("&Redo"), this); + a->setShortcut(QKeySequence::Redo); + menu->addAction(a); + menu->addSeparator(); + a = actionCut = new QAction(QIcon(":/images/textedit/editcut.png"), tr("Cu&t"), this); + a->setShortcut(QKeySequence::Cut); + menu->addAction(a); + a = actionCopy = new QAction(QIcon(":/images/textedit/editcopy.png"), tr("&Copy"), this); + a->setShortcut(QKeySequence::Copy); + menu->addAction(a); + a = actionPaste = new QAction(QIcon(":/images/textedit/editpaste.png"), tr("&Paste"), this); + a->setShortcut(QKeySequence::Paste); + menu->addAction(a); + actionPaste->setEnabled(!QApplication::clipboard()->text().isEmpty()); +} + +void CreateBlogMsg::setupViewActions() +{ + QMenu *menu = new QMenu(tr("&View"), this); + menuBar()->addMenu(menu); + + QAction *a; + + +} + +void CreateBlogMsg::setupInsertActions() +{ + QMenu *menu = new QMenu(tr("&Insert"), this); + menuBar()->addMenu(menu); + + QAction *a; + + a = new QAction(QIcon(""), tr("&Image"), this); + connect(a, SIGNAL(triggered()), this, SLOT(addImage())); + menu->addAction(a); + +} + +void CreateBlogMsg::setupParagraphActions() +{ + comboStyle = new QComboBox(ui.toolBar_2); + ui.toolBar_2->addWidget(comboStyle); + comboStyle->addItem("Paragraph"); + comboStyle->addItem("Heading 1"); + comboStyle->addItem("Heading 2"); + comboStyle->addItem("Heading 3"); + comboStyle->addItem("Heading 4"); + comboStyle->addItem("Heading 5"); + comboStyle->addItem("Heading 6"); + + connect(comboStyle, SIGNAL(activated(int)), + this, SLOT(changeFormatType(int))); +} + +void CreateBlogMsg::setupTextActions() +{ + + QMenu *menu = new QMenu(tr("F&ormat"), this); + menuBar()->addMenu(menu); + + actionTextBold = new QAction(QIcon(":/images/textedit/textbold.png"),tr("&Bold"), this); + actionTextBold->setShortcut(Qt::CTRL + Qt::Key_B); + //actionTextBold->setPriority(QAction::LowPriority); + QFont bold; + bold.setBold(true); + actionTextBold->setFont(bold); + connect(actionTextBold, SIGNAL(triggered()), this, SLOT(textBold())); + + ui.toolBar_2->addAction(actionTextBold); + menu->addAction(actionTextBold); + actionTextBold->setCheckable(true); + + actionTextItalic = new QAction(QIcon(":/images/textedit/textitalic.png"),tr("&Italic"), this); + //actionTextItalic->setPriority(QAction::LowPriority); + actionTextItalic->setShortcut(Qt::CTRL + Qt::Key_I); + QFont italic; + italic.setItalic(true); + actionTextItalic->setFont(italic); + connect(actionTextItalic, SIGNAL(triggered()), this, SLOT(textItalic())); + + ui.toolBar_2->addAction(actionTextItalic); + menu->addAction(actionTextItalic); + actionTextItalic->setCheckable(true); + + actionTextUnderline = new QAction(QIcon(":/images/textedit/textunder.png"),tr("&Underline"), this); + actionTextUnderline->setShortcut(Qt::CTRL + Qt::Key_U); + //actionTextUnderline->setPriority(QAction::LowPriority); + QFont underline; + underline.setUnderline(true); + actionTextUnderline->setFont(underline); + connect(actionTextUnderline, SIGNAL(triggered()), this, SLOT(textUnderline())); + + ui.toolBar_2->addAction(actionTextUnderline); + menu->addAction(actionTextUnderline); + actionTextUnderline->setCheckable(true); + + menu->addSeparator(); + + QActionGroup *grp = new QActionGroup(this); + connect(grp, SIGNAL(triggered(QAction*)), this, SLOT(textAlign(QAction*))); + + // Make sure the alignLeft is always left of the alignRight + if (QApplication::isLeftToRight()) { + actionAlignLeft = new QAction(QIcon(":/images/textedit/textleft.png"),tr("&Left"), grp); + actionAlignCenter = new QAction(QIcon(":/images/textedit/textcenter.png"), tr("C&enter"), grp); + actionAlignRight = new QAction(QIcon(":/images/textedit/textright.png"), tr("&Right"), grp); + } else { + actionAlignRight = new QAction(QIcon(":/images/textedit/textright.png"), tr("&Right"), grp); + actionAlignCenter = new QAction(QIcon(":/images/textedit/textcenter.png"), tr("C&enter"), grp); + actionAlignLeft = new QAction(QIcon(":/images/textedit/textleft.png"), tr("&Left"), grp); + } + actionAlignJustify = new QAction(QIcon(":/images/textedit/textjustify.png"), tr("&Justify"), grp); + + actionAlignLeft->setShortcut(Qt::CTRL + Qt::Key_L); + actionAlignLeft->setCheckable(true); + //actionAlignLeft->setPriority(QAction::LowPriority); + actionAlignCenter->setShortcut(Qt::CTRL + Qt::Key_E); + actionAlignCenter->setCheckable(true); + //actionAlignCenter->setPriority(QAction::LowPriority); + actionAlignRight->setShortcut(Qt::CTRL + Qt::Key_R); + actionAlignRight->setCheckable(true); + //actionAlignRight->setPriority(QAction::LowPriority); + actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J); + actionAlignJustify->setCheckable(true); + //actionAlignJustify->setPriority(QAction::LowPriority); + + ui.toolBar_2->addActions(grp->actions()); + menu->addActions(grp->actions()); + + menu->addSeparator(); + + QPixmap pix(16, 16); + pix.fill(Qt::black); + actionTextColor = new QAction(pix, tr("&Text Color..."), this); + connect(actionTextColor, SIGNAL(triggered()), this, SLOT(textColor())); + + ui.toolBar_2->addAction(actionTextColor); + menu->addAction(actionTextColor); + + menu->addAction(ui.actionOrderedlist); + menu->addAction(ui.actionUnorderedlist); + menu->addAction(ui.actionBlockquoute); + + + /*comboStyle = new QComboBox(ui.toolBar_2); + ui.toolBar_2->addWidget(comboStyle); + comboStyle->addItem("Paragraph"); + comboStyle->addItem("Heading 1"); + comboStyle->addItem("Heading 2"); + comboStyle->addItem("Heading 3"); + comboStyle->addItem("Heading 4"); + comboStyle->addItem("Heading 5"); + comboStyle->addItem("Heading 6"); + + connect(comboStyle, SIGNAL(activated(int)), + this, SLOT(changeFormatType(int)));*/ + + comboFont = new QFontComboBox(ui.toolBar_2); + ui.toolBar_2->addWidget(comboFont); + connect(comboFont, SIGNAL(activated(QString)), + this, SLOT(textFamily(QString))); + + comboSize = new QComboBox(ui.toolBar_2); + comboSize->setObjectName("comboSize"); + ui.toolBar_2->addWidget(comboSize); + comboSize->setEditable(true); + + QFontDatabase db; + foreach(int size, db.standardSizes()) + comboSize->addItem(QString::number(size)); + + connect(comboSize, SIGNAL(activated(QString)), + this, SLOT(textSize(QString))); + comboSize->setCurrentIndex(comboSize->findText(QString::number(QApplication::font() + .pointSize()))); +} + +bool CreateBlogMsg::load(const QString &f) +{ + if (!QFile::exists(f)) + return false; + QFile file(f); + if (!file.open(QFile::ReadOnly)) + return false; + + QByteArray data = file.readAll(); + QTextCodec *codec = Qt::codecForHtml(data); + QString str = codec->toUnicode(data); + if (Qt::mightBeRichText(str)) { + ui.msgEdit->setHtml(str); + } else { + str = QString::fromLocal8Bit(data); + ui.msgEdit->setPlainText(str); + } + + setCurrentFileName(f); + return true; +} + +bool CreateBlogMsg::maybeSave() +{ + if (!ui.msgEdit->document()->isModified()) + return true; + if (fileName.startsWith(QLatin1String(":/"))) + return true; + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("Application"), + tr("The document has been modified.\n" + "Do you want to save your changes?"), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) + return fileSave(); + else if (ret == QMessageBox::Cancel) + return false; + return true; +} + +void CreateBlogMsg::fileNew() +{ + if (maybeSave()) { + ui.msgEdit->clear(); + setCurrentFileName(QString()); + } +} + +void CreateBlogMsg::fileOpen() +{ + QString fn; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_BLOGS, tr("Open File..."), tr("HTML-Files (*.htm *.html);;All Files (*)"), fn)) + load(fn); +} + +bool CreateBlogMsg::fileSave() +{ + if (fileName.isEmpty()) + return fileSaveAs(); + + QTextDocumentWriter writer(fileName); + bool success = writer.write(ui.msgEdit->document()); + if (success) + ui.msgEdit->document()->setModified(false); + return success; +} + +bool CreateBlogMsg::fileSaveAs() +{ + QString fn; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_BLOGS, tr("Save as..."), tr("ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*)"), fn)) { + if (! (fn.endsWith(".odt", Qt::CaseInsensitive) || fn.endsWith(".htm", Qt::CaseInsensitive) || fn.endsWith(".html", Qt::CaseInsensitive)) ) + fn += ".odt"; // default + setCurrentFileName(fn); + return fileSave(); + } + + return false; +} + +void CreateBlogMsg::filePrint() +{ +#ifndef QT_NO_PRINTER + QPrinter printer(QPrinter::HighResolution); + QPrintDialog *dlg = new QPrintDialog(&printer, this); + if (ui.msgEdit->textCursor().hasSelection()) + dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection); + dlg->setWindowTitle(tr("Print Document")); + if (dlg->exec() == QDialog::Accepted) { + ui.msgEdit->print(&printer); + } + delete dlg; +#endif +} + +void CreateBlogMsg::filePrintPreview() +{ +#ifndef QT_NO_PRINTER + QPrinter printer(QPrinter::HighResolution); + QPrintPreviewDialog preview(&printer, this); + connect(&preview, SIGNAL(paintRequested(QPrinter*)), SLOT(printPreview(QPrinter*))); + preview.exec(); +#endif +} + +void CreateBlogMsg::printPreview(QPrinter *printer) +{ +#ifdef QT_NO_PRINTER + Q_UNUSED(printer); +#else + ui.msgEdit->print(printer); +#endif +} + + +void CreateBlogMsg::filePrintPdf() +{ +#ifndef QT_NO_PRINTER +//! [0] + QString fileName; + if (misc::getSaveFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Export PDF"), "*.pdf", fileName)) { + if (QFileInfo(fileName).suffix().isEmpty()) + fileName.append(".pdf"); + QPrinter printer(QPrinter::HighResolution); + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setOutputFileName(fileName); + ui.msgEdit->document()->print(&printer); + } +//! [0] +#endif +} + +void CreateBlogMsg::setCurrentFileName(const QString &fileName) +{ + this->fileName = fileName; + ui.msgEdit->document()->setModified(false); + + QString shownName; + if (fileName.isEmpty()) + shownName = "untitled.txt"; + else + shownName = QFileInfo(fileName).fileName(); + + //setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("Rich Text"))); + setWindowModified(false); +} + +void CreateBlogMsg::addImage() +{ + QString fileimg; + if (misc::getOpenFileName(this, RshareSettings::LASTDIR_MESSAGES, tr("Choose Image"), tr("Image Files supported (*.png *.jpeg *.jpg *.gif)"), fileimg)) { + QImage base(fileimg); + + Create_New_Image_Tag(fileimg); + } +} + +void CreateBlogMsg::Create_New_Image_Tag( const QString urlremoteorlocal ) +{ + /*if (image_extension(urlremoteorlocal)) {*/ + QString subtext = QString("

    ").arg(urlremoteorlocal); + ///////////subtext.append("

    Description on image.

    "); + QTextDocumentFragment fragment = QTextDocumentFragment::fromHtml(subtext); + ui.msgEdit->textCursor().insertFragment(fragment); + //emit statusMessage(QString("Image new :").arg(urlremoteorlocal)); + //} +} diff --git a/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.h b/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.h new file mode 100644 index 000000000..91a3c9610 --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.h @@ -0,0 +1,161 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2008 Robert Fernie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _CREATEBLOGMSG_H +#define _CREATEBLOGMSG_H + +#include + +#include "ui_CreateBlogMsg.h" +#include + +class SubFileItem; +class FileInfo; + +QT_FORWARD_DECLARE_CLASS(QAction) +QT_FORWARD_DECLARE_CLASS(QComboBox) +QT_FORWARD_DECLARE_CLASS(QFontComboBox) +QT_FORWARD_DECLARE_CLASS(QTextEdit) +QT_FORWARD_DECLARE_CLASS(QTextCharFormat) +QT_FORWARD_DECLARE_CLASS(QMenu) + +class CreateBlogMsg : public QMainWindow +{ + Q_OBJECT + +public: + /** Default Constructor */ + CreateBlogMsg(std::string cId, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default Destructor */ + + void addAttachment(std::string path); + void addAttachment(std::string hash, std::string fname, uint64_t size, + bool local, std::string srcId); + + void newBlogMsg(); + + QPixmap picture; + QSettings setter; + + void Create_New_Image_Tag( const QString urlremoteorlocal ); + +private slots: + + void cancelMsg(); + void sendMsg(); + void addImage(); + + void fontSizeIncrease(); + void fontSizeDecrease(); + void blockQuote(); + void toggleCode(); + void addPostSplitter(); + + void setStartupText(); + void updateTextEdit(); + + void fileNew(); + void fileOpen(); + bool fileSave(); + bool fileSaveAs(); + void filePrint(); + void filePrintPreview(); + void filePrintPdf(); + void printPreview(QPrinter *); + + void textBold(); + void textUnderline(); + void textItalic(); + void textFamily(const QString &f); + void textSize(const QString &p); + void changeFormatType(int styleIndex ); + + + void textColor(); + void textAlign(QAction *a); + + void addOrderedList(); + void addUnorderedList(); + + void currentCharFormatChanged(const QTextCharFormat &format); + void cursorPositionChanged(); + + void clipboardDataChanged(); + + +private: + void setupFileActions(); + void setupEditActions(); + void setupViewActions(); + void setupInsertActions(); + void setupParagraphActions(); + void setupTextActions(); + + void setCurrentFileName(const QString &fileName); + bool load(const QString &f); + bool maybeSave(); + + void mergeFormatOnWordOrSelection(const QTextCharFormat &format); + + void fontChanged(const QFont &f); + void colorChanged(const QColor &c); + void alignmentChanged(Qt::Alignment a); + + + void sendMessage(std::wstring subject, std::wstring msg); + + std::string mBlogId; + + QAction *actionSave, + *actionTextBold, + *actionTextUnderline, + *actionTextItalic, + *actionTextColor, + *actionAlignLeft, + *actionAlignCenter, + *actionAlignRight, + *actionAlignJustify, + *actionUndo, + *actionRedo, + *actionCut, + *actionCopy, + *actionPaste; + + QComboBox *comboStyle; + QFontComboBox *comboFont; + QComboBox *comboSize; + + QString fileName; + + QColor codeBackground; + QTextCharFormat defaultCharFormat; + QTextBlockFormat defaultBlockFormat; + QTextCharFormat lastCharFormat; + QTextBlockFormat lastBlockFormat; + + /** Qt Designer generated object */ + Ui::CreateBlogMsg ui; +}; + + + +#endif + diff --git a/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.ui b/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.ui new file mode 100644 index 000000000..66874ee6e --- /dev/null +++ b/retroshare-gui/src/gui/unfinished/blogs/CreateBlogMsg.ui @@ -0,0 +1,343 @@ + + + CreateBlogMsg + + + + 0 + 0 + 666 + 515 + + + + New Blog Post + + + + :/images/rstray3.png:/images/rstray3.png + + + QToolBar#toolBar{background-image: url(:/images/connect/connectFriendBanner.png); +} + +QToolButton { + color: white; +} + +QToolBar#toolBar_2{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FEFEFE, stop:1 #E8E8E8); + +border: 1px solid #CCCCCC;} + + + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + + + QTabWidget::South + + + 0 + + + + Blog Post + + + + + + + + + 75 + true + + + + Blog Post to: + + + + + + + true + + + true + + + + + + + + + 1 + + + + Visual Editor + + + + + + Blog Message + + + + + + + + + 75 + true + + + + Subject : + + + + + + + + + + + + + + + + + + + Html Editor + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 666 + 25 + + + + + + + + 0 + 32 + + + + + 9 + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + toolBar_2 + + + TopToolBarArea + + + true + + + + + + true + + + + :/images/textedit/hi22-action-format-text-blockquote.png:/images/textedit/hi22-action-format-text-blockquote.png + + + blockquoute + + + + + + :/images/textedit/format_font_size_more.png:/images/textedit/format_font_size_more.png + + + Increase font Size + + + + + + :/images/textedit/format_font_size_less.png:/images/textedit/format_font_size_less.png + + + Decrease font size + + + + + + :/images/textedit/textbold.png:/images/textedit/textbold.png + + + Bold + + + + + + :/images/textedit/textunder.png:/images/textedit/textunder.png + + + Underline + + + + + + :/images/textedit/textitalic.png:/images/textedit/textitalic.png + + + Italic + + + + + Publish + + + + + New + + + + + + :/images/textedit/hi22-action-format-text-code.png:/images/textedit/hi22-action-format-text-code.png + + + Code + + + + + + :/images/textedit/hi22-action-insert-more-mark.png:/images/textedit/hi22-action-insert-more-mark.png + + + splitPost + + + + + + :/images/textedit/format-list-ordered.png:/images/textedit/format-list-ordered.png + + + Ordered List + + + + + + :/images/textedit/format-list-unordered.png:/images/textedit/format-list-unordered.png + + + Unordered List + + + + + true + + + + :/images/textedit/editcut.png:/images/textedit/editcut.png + + + Clipboard + + + + + + :/images/textedit/editundo.png:/images/textedit/editundo.png + + + Undo + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/xprogressbar.cpp b/retroshare-gui/src/gui/xprogressbar.cpp new file mode 100644 index 000000000..d62219a79 --- /dev/null +++ b/retroshare-gui/src/gui/xprogressbar.cpp @@ -0,0 +1,287 @@ +/* + * xProgressBar: A custom progress bar for Qt 4. + * Author: xEsk (Xesc & Technology 2008) + * + * Changelog: + * + * v1.0: + * ----- + * - First release + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include "xprogressbar.h" + +bool FileProgressInfo::operator<(const FileProgressInfo &other) const +{ + return progress < other.progress; +} + +bool FileProgressInfo::operator>(const FileProgressInfo &other) const +{ + return progress > other.progress; +} + +xProgressBar::xProgressBar(const FileProgressInfo& pinfo,QRect rect, QPainter *painter, int schemaIndex) + : _pinfo(pinfo) +{ + // assign internal data + this->schemaIndex = schemaIndex; + this->rect = rect; + this->painter = painter; + // set the progress bar colors + setColor(); + // configure span + vSpan = 0; + hSpan = 0; + // text color + textColor = QColor("black"); +} + +void xProgressBar::setColor() +{ + /* TEMPORAL SCHEMA DEFINITION */ + + switch (schemaIndex) + { + /* blue schema */ + case 0: + // background + backgroundBorderColor.setRgb(143, 180, 219); + backgroundColor.setRgb(198, 209, 221); + // progress + gradBorderColor.setRgb(35, 96, 167); + gradColor1.setRgb(100, 136, 252); + gradColor2.setRgb(165, 183, 240); + // ok + break; + + /* green schema */ + case 1: + // background + backgroundBorderColor.setRgb(53, 194, 26); + backgroundColor.setRgb(176, 214, 93); + // progress + gradBorderColor.setRgb(8, 77, 16); + gradColor1.setRgb(0, 137, 16); + gradColor2.setRgb(78, 194, 81); + // ok + break; + + /* red schema */ + case 2: + // background + backgroundBorderColor.setRgb(255, 62, 62); + backgroundColor.setRgb(248, 175, 175); + // progress + gradBorderColor.setRgb(151, 0, 0); + gradColor1.setRgb(251, 54, 54); + gradColor2.setRgb(246, 118, 118); + // ok + break; + + /* gray schema */ + case 3: + // background + backgroundBorderColor.setRgb(116, 177, 160); + backgroundColor.setRgb(178, 215, 205); + // progress + gradBorderColor.setRgb(106, 106, 106); + gradColor1.setRgb(168, 168, 168); + gradColor2.setRgb(197, 197, 197); + // ok + break; + + /* yellow schema */ + case 4: + // background + backgroundBorderColor.setRgb(227, 204, 79); + backgroundColor.setRgb(255, 236, 130); + // progress + gradBorderColor.setRgb(215, 182, 0); + gradColor1.setRgb(233, 197, 0); + gradColor2.setRgb(255, 236, 130); + // ok + break; + + /* black schema */ + case 5: + // background + backgroundBorderColor.setRgb(99, 99, 99); + backgroundColor.setRgb(134, 134, 134); + // progress + gradBorderColor.setRgb(0, 0, 0); + gradColor1.setRgb(38, 38, 38); + gradColor2.setRgb(113, 113, 113); + // ok + break; + + /* purple schema */ + case 6: + // background + backgroundBorderColor.setRgb(234, 127, 223); + backgroundColor.setRgb(255, 164, 246); + // progress + gradBorderColor.setRgb(150, 0, 134); + gradColor1.setRgb(218, 0, 195); + gradColor2.setRgb(255, 121, 241); + // ok + break; + + /* maroon schema */ + case 7: + // background + backgroundBorderColor.setRgb(255, 174, 49); + backgroundColor.setRgb(255, 204, 132); + // progress + gradBorderColor.setRgb(159, 94, 0); + gradColor1.setRgb(223, 134, 6); + gradColor2.setRgb(248, 170, 59); + // ok + break; + + /* clean schema */ + case 8: + // background + backgroundBorderColor.setRgb(143, 180, 219); + backgroundColor.setRgb(198, 209, 221); + // progress + gradBorderColor.setRgb(209, 128, 24); + gradColor1.setRgb(246, 199, 138); + gradColor2.setRgb(255, 227, 190); + // ok + break; + + /* light gray */ + case 9: + // background + backgroundBorderColor.setRgb(194, 194, 194); + backgroundColor.setRgb(232, 233, 233); + // progress + gradBorderColor.setRgb(176, 176, 176); + gradColor1.setRgb(201, 201, 201); + gradColor2.setRgb(223, 223, 223); + // set text color (white is not a good option) + textColor = QColor(58, 58, 58); + // ok + break; + } +} + +void xProgressBar::paint() +{ + // paint the progressBar background + painter->setBrush(backgroundColor); + painter->setPen(backgroundBorderColor); + painter->drawRect(rect.x() + hSpan, rect.y() + vSpan, rect.width() - 1 - hSpan, rect.height() - 1 - vSpan * 2); + + // define gradient + QLinearGradient linearGrad(rect.x(), rect.y(), rect.x(), rect.y() + rect.height() - 1); + + linearGrad.setColorAt(0.00, gradColor1); + linearGrad.setColorAt(0.16, gradColor2); + linearGrad.setColorAt(1.00, gradColor1); + painter->setPen(gradBorderColor); + + int width = static_cast(rect.width()-1-2*hSpan) ; + + painter->setBrush(linearGrad); + + uint32_t ss = _pinfo.nb_chunks ; + + if(ss > 1) // for small files we use a more progressive display + { + if(!_pinfo.cmap._map.empty()) + for(uint32_t i=0;i0 && o >= 1.0f) // limits the number of regions drawn + { + painter->setOpacity(o) ; + painter->drawRect(rect.x() + hSpan+(int)rint(i*width/(float)ss), rect.y() + vSpan, (int)ceil(j*width/(float)ss), rect.height() - 1 - vSpan * 2); + } + + i += j ; + } + + QColor gradColor_a1, gradColor_a2 ; + gradColor_a1.setRgb(223, 134, 6); + gradColor_a2.setRgb(248, 170, 59); + linearGrad.setColorAt(0.00, gradColor_a1); + linearGrad.setColorAt(0.16, gradColor_a2); + linearGrad.setColorAt(1.00, gradColor_a1); + painter->setBrush(linearGrad); + + for(uint32_t i=0;i<_pinfo.chunks_in_progress.size();++i) + painter->drawRect(rect.x() + hSpan+(int)rint(_pinfo.chunks_in_progress[i]*width/(float)ss), rect.y() + vSpan, (int)ceil(1.0f*width/(float)ss), rect.height() - 1 - vSpan * 2); + } + else + { + // calculate progress value + int preWidth = static_cast((rect.width() - 1 - hSpan)*(_pinfo.progress/100.0f)); + int progressWidth = rect.width() - preWidth; + if (progressWidth == rect.width() - hSpan) return; + + // paint the progress + painter->setBrush(linearGrad); + painter->drawRect(rect.x() + hSpan, rect.y() + vSpan, rect.width() - progressWidth - hSpan, rect.height() - 1 - vSpan * 2); + } + painter->setOpacity(1.0f) ; + + + // paint text? + if (displayText) + { + QLocale locale; + painter->setPen(textColor); + painter->drawText(rect, Qt::AlignCenter, locale.toString(_pinfo.progress, 'f', 2) + "%"); + } + + backgroundColor.setRgb(255, 255, 255); + painter->setBrush(backgroundColor); + backgroundBorderColor.setRgb(0, 0, 0); + painter->setPen(backgroundBorderColor); +} + +void xProgressBar::setColorSchema(const int value) +{ + schemaIndex = value; + // set the progress bar colors + setColor(); +} + +void xProgressBar::setDisplayText(const bool display) +{ + displayText = display; +} + +void xProgressBar::setVerticalSpan(const int value) +{ + vSpan = value; +} + +void xProgressBar::setHorizontalSpan(const int value) +{ + hSpan = value; +} diff --git a/retroshare-gui/src/gui/xprogressbar.h b/retroshare-gui/src/gui/xprogressbar.h new file mode 100644 index 000000000..bfb409b7b --- /dev/null +++ b/retroshare-gui/src/gui/xprogressbar.h @@ -0,0 +1,90 @@ +/* + * xProgressBar: A custom progress bar for Qt 4. + * Author: xEsk (Xesc & Technology 2008) + * + * Changelog: + * + * v1.0: + * ----- + * - First release + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef XPROGRESSBAR_H +#define XPROGRESSBAR_H +// +#include +#include +#include +#include +#include +#include + +#include + +class FileProgressInfo +{ + public: + typedef enum { DOWNLOAD_LINE,UPLOAD_LINE,DOWNLOAD_SOURCE } LineType ; + + LineType type ; + CompressedChunkMap cmap ; + float progress ; + uint32_t nb_chunks ; + + std::vector chunks_in_progress ; + + bool operator<(const FileProgressInfo &other) const; + bool operator>(const FileProgressInfo &other) const; +}; +// +class xProgressBar : public QObject +{ +Q_OBJECT + private: + // progress vlues + uint32_t _nb_chunks ; + int schemaIndex; + bool displayText; + int vSpan; + int hSpan; + // painter config + QRect rect; + QPainter *painter; + // text color + QColor textColor; + // progress colors + QColor backgroundBorderColor; + QColor backgroundColor; + QColor gradBorderColor; + QColor gradColor1; + QColor gradColor2; + // configure the color + void setColor(); + + const FileProgressInfo& _pinfo ; + public: + xProgressBar(const FileProgressInfo& pinfo,QRect rect, QPainter *painter, int schemaIndex = 0); + + void paint(); + + void setColorSchema(const int value); + void setDisplayText(const bool display); + void setVerticalSpan(const int value); + void setHorizontalSpan(const int value); +}; +#endif diff --git a/retroshare-gui/src/idle/idle.cpp b/retroshare-gui/src/idle/idle.cpp new file mode 100644 index 000000000..5110a10b3 --- /dev/null +++ b/retroshare-gui/src/idle/idle.cpp @@ -0,0 +1,130 @@ +/* + * idle.cpp - detect desktop idle time + * Copyright (C) 2003 Justin Karneges + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "idle.h" + +#include +#include +#include + +static IdlePlatform *platform = 0; +static int platform_ref = 0; + +Idle::Idle() +{ + d = new Private; + d->active = false; + d->idleTime = 0; + + // try to use platform idle + if(!platform) { + IdlePlatform *p = new IdlePlatform; + if(p->init()) + platform = p; + else + delete p; + } + if(platform) + ++platform_ref; + + connect(&d->checkTimer, SIGNAL(timeout()), SLOT(doCheck())); +} + +Idle::~Idle() +{ + if(platform) { + --platform_ref; + if(platform_ref == 0) { + delete platform; + platform = 0; + } + } + delete d; +} + +bool Idle::isActive() const +{ + return d->active; +} + +bool Idle::usingPlatform() const +{ + return (platform ? true: false); +} + +void Idle::start() +{ + d->startTime = QDateTime::currentDateTime(); + + if(!platform) { + // generic idle + d->lastMousePos = QCursor::pos(); + d->idleSince = QDateTime::currentDateTime(); + } + + // poll every second (use a lower value if you need more accuracy) + d->checkTimer.start(1000); +} + +void Idle::stop() +{ + d->checkTimer.stop(); +} + +int Idle::secondsIdle() +{ + int i; + if (platform) + i = platform->secondsIdle(); + else { + QPoint curMousePos = QCursor::pos(); + QDateTime curDateTime = QDateTime::currentDateTime(); + if(d->lastMousePos != curMousePos) { + d->lastMousePos = curMousePos; + d->idleSince = curDateTime; + } + i = d->idleSince.secsTo(curDateTime); + } + + // set 'beginIdle' to the beginning of the idle time (by backtracking 'i' seconds from now) + QDateTime beginIdle = QDateTime::currentDateTime().addSecs(-i); + + // set 't' to hold the number of seconds between 'beginIdle' and 'startTime' + int t = beginIdle.secsTo(d->startTime); + + // beginIdle later than (or equal to) startTime? + if(t <= 0) { + // scoot ourselves up to the new idle start + d->startTime = beginIdle; + } + // beginIdle earlier than startTime? + else if(t > 0) { + // do nothing + } + + // how long have we been idle? + int idleTime = d->startTime.secsTo(QDateTime::currentDateTime()); + return idleTime; +} + +void Idle::doCheck() +{ + emit secondsIdle(secondsIdle()); +} diff --git a/retroshare-gui/src/idle/idle.h b/retroshare-gui/src/idle/idle.h new file mode 100644 index 000000000..5e6a9d694 --- /dev/null +++ b/retroshare-gui/src/idle/idle.h @@ -0,0 +1,83 @@ +/* + * idle.h - detect desktop idle time + * Copyright (C) 2003 Justin Karneges + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef IDLE_H +#define IDLE_H + +#include +#include +#include +#include + +class IdlePlatform; + +class Idle : public QObject +{ + Q_OBJECT +public: + Idle(); + ~Idle(); + + bool isActive() const; + bool usingPlatform() const; + void start(); + void stop(); + int secondsIdle(); + +signals: + void secondsIdle(int); + +private slots: + void doCheck(); + +private: + class Private; + Private *d; +}; + +class IdlePlatform +{ +public: + IdlePlatform(); + ~IdlePlatform(); + + bool init(); + int secondsIdle(); + +private: + class Private; + Private *d; +}; + +class Idle::Private +{ +public: + Private() {} + + QPoint lastMousePos; + QDateTime idleSince; + + bool active; + int idleTime; + QDateTime startTime; + QTimer checkTimer; +}; + +#endif diff --git a/retroshare-gui/src/idle/idle_platform.cpp b/retroshare-gui/src/idle/idle_platform.cpp new file mode 100644 index 000000000..91aba8dd7 --- /dev/null +++ b/retroshare-gui/src/idle/idle_platform.cpp @@ -0,0 +1,329 @@ +/* + * idle_x11.cpp - detect desktop idle time + * Copyright (C) 2003 Justin Karneges + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "idle.h" + +//linux +#ifdef HAVE_XSS + +#include +#include +#include + +#include +#include +#include + +static XErrorHandler old_handler = 0; +extern "C" int xerrhandler(Display* dpy, XErrorEvent* err) +{ + if(err->error_code == BadDrawable) + return 0; + + return (*old_handler)(dpy, err); +} + +class IdlePlatform::Private +{ +public: + Private() {} + + XScreenSaverInfo *ss_info; +}; + +IdlePlatform::IdlePlatform() +{ + d = new Private; + d->ss_info = 0; +} + +IdlePlatform::~IdlePlatform() +{ + if(d->ss_info) + XFree(d->ss_info); + if(old_handler) { + XSetErrorHandler(old_handler); + old_handler = 0; + } + delete d; +} + +bool IdlePlatform::init() +{ + if(d->ss_info) + return true; + + old_handler = XSetErrorHandler(xerrhandler); + + int event_base, error_base; + if(XScreenSaverQueryExtension(QApplication::desktop()->screen()->x11Info().display(), &event_base, &error_base)) { + d->ss_info = XScreenSaverAllocInfo(); + return true; + } + return false; +} + +int IdlePlatform::secondsIdle() +{ + if(!d->ss_info) + return 0; + if(!XScreenSaverQueryInfo(QApplication::desktop()->screen()->x11Info().display(), QX11Info::appRootWindow(), d->ss_info)) + return 0; + return d->ss_info->idle / 1000; +} + +#else // windows +#ifdef WINDOWS_SYS + +#include +#include + +#ifndef tagLASTINPUTINFO +typedef struct __tagLASTINPUTINFO { + UINT cbSize; + DWORD dwTime; + } __LASTINPUTINFO, *__PLASTINPUTINFO; +#endif + +class IdlePlatform::Private +{ +public: + Private() + { + GetLastInputInfo = NULL; + lib = 0; + } + + BOOL (__stdcall * GetLastInputInfo)(__PLASTINPUTINFO); + DWORD (__stdcall * IdleUIGetLastInputTime)(void); + QLibrary *lib; +}; + +IdlePlatform::IdlePlatform() +{ + d = new Private; +} + +IdlePlatform::~IdlePlatform() +{ + delete d->lib; + delete d; +} + +bool IdlePlatform::init() +{ + if(d->lib) + return true; + void *p; + + // try to find the built-in Windows 2000 function + d->lib = new QLibrary("user32"); + if(d->lib->load() && (p = d->lib->resolve("GetLastInputInfo"))) { + d->GetLastInputInfo = (BOOL (__stdcall *)(__PLASTINPUTINFO))p; + return true; + } else { + delete d->lib; + d->lib = 0; + } + + // fall back on idleui + d->lib = new QLibrary("idleui"); + if(d->lib->load() && (p = d->lib->resolve("IdleUIGetLastInputTime"))) { + d->IdleUIGetLastInputTime = (DWORD (__stdcall *)(void))p; + return true; + } else { + delete d->lib; + d->lib = 0; + } + + return false; +} + +int IdlePlatform::secondsIdle() +{ + int i; + if(d->GetLastInputInfo) { + __LASTINPUTINFO li; + li.cbSize = sizeof(__LASTINPUTINFO); + bool ok = d->GetLastInputInfo(&li); + if(!ok) + return 0; + i = li.dwTime; + } else if (d->IdleUIGetLastInputTime) { + i = d->IdleUIGetLastInputTime(); + } else + return 0; + + return (GetTickCount() - i) / 1000; +} + +#else //mac +#ifdef MAC_IDLE + +#include + + +// Why does Apple have to make this so complicated? +static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr) { + OSStatus err; + FSRef frameworksFolderRef; + CFURLRef baseURL; + CFURLRef bundleURL; + + if ( bundlePtr == nil ) return( -1 ); + + *bundlePtr = nil; + + baseURL = nil; + bundleURL = nil; + + err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef); + if (err == noErr) { + baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef); + if (baseURL == nil) { + err = coreFoundationUnknownErr; + } + } + if (err == noErr) { + bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, framework, false); + if (bundleURL == nil) { + err = coreFoundationUnknownErr; + } + } + if (err == noErr) { + *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL); + if (*bundlePtr == nil) { + err = coreFoundationUnknownErr; + } + } + if (err == noErr) { + if ( ! CFBundleLoadExecutable( *bundlePtr ) ) { + err = coreFoundationUnknownErr; + } + } + + // Clean up. + if (err != noErr && *bundlePtr != nil) { + CFRelease(*bundlePtr); + *bundlePtr = nil; + } + if (bundleURL != nil) { + CFRelease(bundleURL); + } + if (baseURL != nil) { + CFRelease(baseURL); + } + + return err; +} + + +class IdlePlatform::Private { +public: + EventLoopTimerRef mTimerRef; + int mSecondsIdle; + + Private() : mTimerRef(0), mSecondsIdle(0) {} + + static pascal void IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData); + +}; + + +pascal void IdlePlatform::Private::IdleTimerAction(EventLoopTimerRef, EventLoopIdleTimerMessage inState, void* inUserData) { + switch (inState) { + case kEventLoopIdleTimerStarted: + case kEventLoopIdleTimerStopped: + // Get invoked with this constant at the start of the idle period, + // or whenever user activity cancels the idle. + ((IdlePlatform::Private*)inUserData)->mSecondsIdle = 0; + break; + case kEventLoopIdleTimerIdling: + // Called every time the timer fires (i.e. every second). + ((IdlePlatform::Private*)inUserData)->mSecondsIdle++; + break; + } +} + + +IdlePlatform::IdlePlatform() { + d = new Private(); +} + +IdlePlatform::~IdlePlatform() { + RemoveEventLoopTimer(d->mTimerRef); + delete d; +} + + +// Typedef for the function we're getting back from CFBundleGetFunctionPointerForName. +typedef OSStatus (*InstallEventLoopIdleTimerPtr)(EventLoopRef inEventLoop, + EventTimerInterval inFireDelay, + EventTimerInterval inInterval, + EventLoopIdleTimerUPP inTimerProc, + void * inTimerData, + EventLoopTimerRef * outTimer); + + +bool IdlePlatform::init() { + // May already be init'ed. + if (d->mTimerRef) { + return true; + } + + // According to the docs, InstallEventLoopIdleTimer is new in 10.2. + // According to the headers, it has been around since 10.0. + // One of them is lying. We'll play it safe and weak-link the function. + + // Load the "Carbon.framework" bundle. + CFBundleRef carbonBundle; + if (LoadFrameworkBundle( CFSTR("Carbon.framework"), &carbonBundle ) != noErr) { + return false; + } + + // Load the Mach-O function pointers for the routine we will be using. + InstallEventLoopIdleTimerPtr myInstallEventLoopIdleTimer = (InstallEventLoopIdleTimerPtr)CFBundleGetFunctionPointerForName(carbonBundle, CFSTR("InstallEventLoopIdleTimer")); + if (myInstallEventLoopIdleTimer == 0) { + return false; + } + + EventLoopIdleTimerUPP timerUPP = NewEventLoopIdleTimerUPP(Private::IdleTimerAction); + if ((*myInstallEventLoopIdleTimer)(GetMainEventLoop(), kEventDurationSecond, kEventDurationSecond, timerUPP, 0, &d->mTimerRef)) { + return true; + } + + return false; +} + + +int IdlePlatform::secondsIdle() { + return d->mSecondsIdle; +} + +#else + +IdlePlatform::IdlePlatform() {} +IdlePlatform::~IdlePlatform() {} +bool IdlePlatform::init() { return false; } +int IdlePlatform::secondsIdle() { return 0; } + +#endif +#endif +#endif diff --git a/retroshare-gui/src/lang/lang.qrc b/retroshare-gui/src/lang/lang.qrc new file mode 100644 index 000000000..e08bb380b --- /dev/null +++ b/retroshare-gui/src/lang/lang.qrc @@ -0,0 +1,17 @@ + + + retroshare_en.qm + retroshare_es.qm + retroshare_da.qm + retroshare_de.qm + retroshare_fi.qm + retroshare_fr.qm + retroshare_ja_JP.qm + retroshare_ko.qm + retroshare_ru.qm + retroshare_tr.qm + retroshare_sv.qm + retroshare_zh_CN.qm + + + diff --git a/retroshare-gui/src/lang/languagesupport.cpp b/retroshare-gui/src/lang/languagesupport.cpp new file mode 100644 index 000000000..d6e30515f --- /dev/null +++ b/retroshare-gui/src/lang/languagesupport.cpp @@ -0,0 +1,156 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include + +#include "languagesupport.h" + + +/** Initializes the list of available languages. */ +QMap +LanguageSupport::languages() +{ + static QMap languages; + if (languages.isEmpty()) { + //languages.insert("af", "Afrikaans"); + //languages.insert("bg", "Bulgarien"); + //languages.insert("cy", "Welsh"); + languages.insert("de", "Deutsch"); + languages.insert("da", "Danish"); + languages.insert("en", "English"); + languages.insert("es", QString::fromUtf8("spanish")); + languages.insert("fr", QString::fromUtf8("Fran\303\247ais")); + languages.insert("fi", "suomi"); + //languages.insert("gr", "Greek"); + //languages.insert("it", "Italiano"); + languages.insert("ja_JP", QString::fromUtf8("\346\227\245\346\234\254\350\252\236")); + languages.insert("ko", "Korean"); + //languages.insert("pl", "Polish"); + //languages.insert("pt", "Portuguese"); + languages.insert("ru", QString::fromUtf8("\320\240\321\203\321\201\321\201\320\272\320\270\320\271")); + //languages.insert("sl", "slovenian"); + //languages.insert("sr", "Serbian"); + languages.insert("sv", "svenska"); + languages.insert("tr", QString::fromUtf8("T\303\274rk\303\247e")); + languages.insert("zh_CN", QString::fromUtf8("\347\256\200\344\275\223\345\255\227")); + //languages.insert("zh_TW", QString::fromUtf8("\347\260\241\351\253\224\345\255\227")); + } + return languages; +} + +/** Returns the default language code for the system locale. */ +QString +LanguageSupport::defaultLanguageCode() +{ + QString language = QLocale::system().name(); + + if (language != "zh_CN" && language != "zh_TW") + language = language.mid(0, language.indexOf("_")); + if (!isValidLanguageCode(language)) + language = "en"; + + return language; +} + +/** Returns the language code for a given language name. */ +QString +LanguageSupport::languageCode(const QString &languageName) +{ + return languages().key(languageName); +} + +/** Returns a list of all supported language codes. (e.g., "en"). */ +QStringList +LanguageSupport::languageCodes() +{ + return languages().keys(); +} + +/** Returns the language name for a given language code. */ +QString +LanguageSupport::languageName(const QString &languageCode) +{ + return languages().value(languageCode); +} + +/** Returns a list of all supported language names (e.g., "English"). */ +QStringList +LanguageSupport::languageNames() +{ + return languages().values(); +} + +/** Returns true if we understand the given language code. */ +bool +LanguageSupport::isValidLanguageCode(const QString &languageCode) +{ + return languageCodes().contains(languageCode); +} + +/** Returns true if languageCode requires a right-to-left layout. */ +bool +LanguageSupport::isRightToLeft(const QString &languageCode) +{ + return (!languageCode.compare("ar", Qt::CaseInsensitive) + || !languageCode.compare("fa", Qt::CaseInsensitive) + || !languageCode.compare("he", Qt::CaseInsensitive)); +} +/** Sets the application's translator to the specified language. */ +bool +LanguageSupport::translate(const QString &languageCode) +{ + if (!isValidLanguageCode(languageCode)) + return false; + if (languageCode == "en") + return true; + + /* Attempt to load the translations for Qt's internal widgets from their + * installed Qt directory. */ + QString qtTranslation = QLibraryInfo::location(QLibraryInfo::TranslationsPath) + "/qt_" + languageCode + ".qm"; + QTranslator *systemQtTranslator = new QTranslator(rApp); + Q_CHECK_PTR(systemQtTranslator); + + if (QFile::exists(qtTranslation) && systemQtTranslator->load(qtTranslation)) + QApplication::installTranslator(systemQtTranslator); + else { + /* Attempt to load the translations for Qt's internal widgets from the translations directory in the exe dir. */ + qtTranslation = QCoreApplication::applicationDirPath() + "/translations/qt_" + languageCode + ".qm"; + if (QFile::exists(qtTranslation) && systemQtTranslator->load(qtTranslation)) + QApplication::installTranslator(systemQtTranslator); + else + delete systemQtTranslator; + } + + /* Install a translator for RetroShare's UI widgets */ + QTranslator *retroshareTranslator = new QTranslator(rApp); + Q_CHECK_PTR(retroshareTranslator); + + if (retroshareTranslator->load(":/lang/retroshare_" + languageCode + ".qm")) { + QApplication::installTranslator(retroshareTranslator); + return true; + } + delete retroshareTranslator; + return false; +} diff --git a/retroshare-gui/src/lang/languagesupport.h b/retroshare-gui/src/lang/languagesupport.h new file mode 100644 index 000000000..53cc947e9 --- /dev/null +++ b/retroshare-gui/src/lang/languagesupport.h @@ -0,0 +1,58 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + + +#ifndef _LANGUAGESUPPORT_H +#define _LANGUAGESUPPORT_H + +#include +#include +#include + + + +class LanguageSupport +{ +public: + /** Returns the default language code for the system locale. */ + static QString defaultLanguageCode(); + /** Returns the language code for a given language name. */ + static QString languageCode(const QString &languageName); + /** Returns a list of all supported language codes (e.g., "en"). */ + static QStringList languageCodes(); + /** Returns the language name for a given language code. */ + static QString languageName(const QString &languageCode); + /** Returns a list of all supported language names (e.g., "English"). */ + static QStringList languageNames(); + /** Returns a list of all supported language codes and names. */ + static QMap languages(); + /** Returns true if we understand the given language code. */ + static bool isValidLanguageCode(const QString &languageCode); + /** Returns true if languageCode requires a right-to-left layout. */ + static bool isRightToLeft(const QString &languageCode); + /** Sets the application's translator to the specified language. */ + static bool translate(const QString &languageCode); +}; + +#endif + diff --git a/retroshare-gui/src/lang/retroshare_af.qm b/retroshare-gui/src/lang/retroshare_af.qm new file mode 100644 index 000000000..738a85435 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_af.qm differ diff --git a/retroshare-gui/src/lang/retroshare_af.ts b/retroshare-gui/src/lang/retroshare_af.ts new file mode 100644 index 000000000..c8c5ee1de --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_af.ts @@ -0,0 +1,13857 @@ + + + + + + + Arial + Afrikaans Arial + + + + @default + + Arial + Afrikaans Arial + + + + AboutDialog + + + About RetroShare + + + + + About + About + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + Retroshare + + + + Sorry, can't determine system default command for this file + + + + + + AddFileAssotiationDialog + + RetroShare + Retroshare + + + + AddFriendDialog + + Cancel + Kanselleer + + + Done + Done + + + Load From File + belaai vanaf tou + + + RetroShare + Retroshare + + + Certificate Load Failed + sertifikaat belaai nee werk + + + + AddFriendWizard + + Cancel + kanselleer + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Cancel + kanselleer + + + + Search + Search + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search Criteria + + + + + AppearanceDialog + + Language + Language + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + Style + Style + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + Style Sheet + Style Sheet + + + + AppearancePage + + + Language + Language + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + + Style + Style + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + + Style Sheet + Style Sheet + + + + ApplicationWindow + + + Hide + Hide + + + + Show + Show + + + + + RetroShare + Retroshare + + + Transfers + Oorsteek + + + Messages + Email + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + Statistics + + + + AttachFileItem + + + Form + + + + File Name + File Name + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + bewys + + + Authenticate Friend By Entering Their Code + bewys vriend by insit die kode + + + OK + Top OK + + + Cancel + kanselleer + + + + BandwidthGraph + + + + Show Settings + Show Settings + + + + Reset + Reset + + + + Receive Rate + Receive Rate + + + + Send Rate + Send Rate + + + + Style + Style + + + + Changes the transparency of the Bandwidth Graph + Changes the transparency of the Bandwidth Graph + + + + 100 + 100 + + + + % Opaque + 100 + + + + Save + Save + + + + Cancel + kanselleer + + + + Since: + + + + + Hide Settings + Hide Settings + + + + RetroShare Bandwidth Usage + + + + + Always on Top + + + + + BgWindow + + Options + Options + + + About + About + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + + + + + Close + Toemaak + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + Name + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + Hide + + + + CalDialog + + + Remove + Remove + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + Select Certificate + + + Certificates (*.pqi *.pem) + Certificates (*.pqi *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + Retroshare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + Create a new Broadcast Channel + kreëer nuut oorsend kanaal + + + Create A New Broadcast Channel + kreëer nuut oorsend kanaal + + + Channel Name: + kanaal naam: + + + Type: + Tipe: + + + Public Channel (Signed) + Publiek kanaal (teken) + + + Private Channel (Encrypted) + privaat kanaal (veilig) + + + Cancel Channel + kanselleer kanaal + + + Create Channel + kreëer kanaal + + + + ChanMsgDialog + + Compose + kreëer + + + Recommended Files + vasstel tou + + + Send To: + Oorsend aan: + + + Send + Oorsend + + + Delete Channel + kanselleer kanaal + + + Create Channel MSG + kreëer kanaal boodskap + + + File Name + File Name + + + Size + Size + + + Sources + Sources + + + Save + Save + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + Download + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Hide + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + Kanaal + + + Video + Video + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + Tipe: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + + + + + OK + + + + + Close + Toemaak + + + + ChannelFeed + + + Create Channel + kreëer kanaal + + + + Subscribe To Channel + Subscribe To Kanaal + + + Title + Koplyn: + + + Reset + Reset + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + Name + Name + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChatDialog + + Chat + Praat + + + Send + Oorsend + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + Oorsend + + + + Cancel + + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + General + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + Style + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + Maak Vriend + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + Options + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Cancel + kanselleer + + + Port: + Port: + + + Trust Settings + Vertroue Verstel + + + Trust Level + Vertroue Level + + + Trust Their Signature + Vertroue vanaf handtekening + + + Sign The Certificate + bewys sertifikaat + + + + Details + Details + + + + Name + Name + + + + Loc + + + + + Peer Address + Peer Address + + + + Last Contact + Last Contact + + + Peer Details + Peer Details + + + + Peer Info + + + + + Peer ID + + + + + Version + + + + + Addresses list + + + + + Apply and Close + + + + + + RetroShare + Retroshare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + None + + + + + Marginal + + + + + Full + + + + + Deny Friend + + + + + + Sign GPG key + + + + + Friend Details + + + + + RetroShare ID + + + + + Status + Status + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port + + + + + Your trust in this peer is: + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Make Friend + Maak Vriend + + + + Certificate + + + + + OK + + + + + ConnectDialog + + Peer Details + Peer Details + + + Make Friend + Maak Vriend + + + Cancel + kanselleer + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + Name + + + + Description + + + + + Type: + Tipe: + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + Retroshare + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + Name + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + Tipe: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + Retroshare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Name + + + + Type: + Tipe: + + + + Authenticated Messages + + + + + Cancel + kanselleer + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Description + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Create + + + + + CreateForumMsg + + + Close + Toemaak + + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + Retroshare + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + Retroshare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + CryptographyDialog + + RSA Key Size + RSA Key Size + + + Rijndael Block size + Rijndael Block size + + + 128 Bits + 128 Bits + + + 192 Bits + 192 Bits + + + 256 Bits + 256 Bits + + + Rijndael Key Size + Rijndael Key Size + + + Rijndael Mode + Rijndael Mode + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + Rijndael Padding + Rijndael Padding + + + PKCS7 + PKCS7 + + + Zeros + Zeros + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Rijndael Feedback Size + + + Key Size: + Key Size: + + + Block Size: + Block Size: + + + Feedback Size: + Feedback Size: + + + Mode: + Mode: + + + Padding: + Padding: + + + RetroShare + Retroshare + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Details + + + + + General + General + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + Tipe: + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + Date + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + + + + + Cancel + + + + + Rating + + + + + File Name + File Name + + + + Not Rated + + + + + No Comments + + + + + DirectoriesDialog + + Shared Directories + Shared Directories + + + Other Directories + Other Directories + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + + + Add Shared Directory + Add Shared Directory + + + + DirectoriesPage + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + Shared Directories + + + + Edit Share + + + + Incoming files + Incoming files + + + + + Browse + + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + Toemaak + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Vriend</span></p></body></html> + + + + Status + Status + + + + Person + Person + + + + Auto Connect + Auto Connect + + + + Trust Level + Trust Level + + + + Peer Address + Peer Address + + + + Last Contact + Last Contact + + + + Organisation + Organisation + + + + Location + Location + + + + Country + Country + + + + Person Id + Person ID + + + + Auth Code + Auth Code + + + + # + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileHashDialog + + Download + Download + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + %1 KB + %1 KB + + + File Name + File Name + + + Size + Size + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + Size + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + OK + + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + Oorsend + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + Misc + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + Hide + + + + Expand + + + + + + RetroShare + Retroshare + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + + Date + Date + + + + + Title + Koplyn: + + + + + Start New Thread + + + + New Message + Nuut Boodskap + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + Reset + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + Praat saam met Vriend + + + + Status + Status + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + Oorsend + + + + Clear Chat History + + + + + + Add Friend + Byvoeg Vriend + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + Location + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + Verbind to Vriend + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + Save Certificate + + + + Certificates (*.pqi) + Certificates (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + General + + + Network + Network + + + Directories + Directories + + + Server + Peer Settings + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Status + Status + + + + Accept + Accept + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Retroshare setup + + + Load Trusted Certificate (Optional) + Load Trusted Certificate (Optional) + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + Name + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + Location + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + + + Select File + Select File + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + + + Generate New Certificate + Generate New Certificate + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + Select Trusted Friend + + + + Certificates (*.pqi *.pem) + Certificates (*.pqi *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + GeneralDialog + + Style + Style + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + Language + Language + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + Style Sheet + Style Sheet + + + Login + Login + + + Misc + Misc + + + + GeneralPage + + Keys manager + Keys manager + + + Style + Style + + + Choose RetroShare's interface style + Choose RetroShare's interface style + + + Language + Language + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + Choose the language used in RetroShare + Choose the language used in RetroShare + + + Login + Login + + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + Misc + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Recv: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Sent: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Praat saam met Vriend + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + Koplyn: + + + + Description + + + + + Reset + Reset + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + Name + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + Date + + + + Size + Size + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + Search + Search + + + + Home + Home + + + + Close + Toemaak + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + About + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + Reset + + + + + Copy + + + + + Remove + Remove + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + Oorsend + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + InviteDialog + + Done + Done + + + Cancel + Kanselleer + + + Launch Email + Start Email + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + Download + + + + Expand + + + + + Hide + Hide + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + vanaf + + + + Show + Show + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + LogDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> + +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +</body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table></body></html> + + + + MainWindow + + + Network + Network + + + + Friends + Praat saam met Vriend + + + + + Transfers + Oorsteek + + + + + Messages + Email + + + + + Channels + Kanaal + + + + Blogs + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + Status + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + + + Options + Options + + + + Hide + Hide + + + + Show + Show + + + + RetroShare + Retroshare + + + Invite Friend + Nooi Vriend + + + + MainWindow + + + + + Add Friend + Byvoeg Vriend + + + + Add a Friend Wizard + + + + + Add Share + Byvoeg Gedeelte + + + + + Quick Start Wizard + + + + + Search + Search + + + + Files + Files Biblioteek + + + Add Shared Directory + Byvoeg Gedeelte Katalogus + + + + Show/Hide + + + + + &Quit + + + + + + + + You have %1 new message + + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Minimize + + + + + Maximize + + + + + Links Cloud + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Unfinished + + + + + Help + Help + + + + About + About + + + + + Forums + + + + + Open Messages + + + + + Applications + + + + Settings + Settings + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + Quit + + + + + SMPlayer + + + + + Messenger + + + + + MessageComposer + + + + Compose + kreëer + + + + + Contacts + + + + + Search for Name: + + + + + Reset + Reset + + + + Send To: + Oorsend aan: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + vasstel tou + + + + File Name + File Name + + + + Size + Size + + + Sources + Sources + + + + Hash + + + + + Send + Oorsend + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + Save + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + Retroshare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + Misc + Misc + + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + boodskap + + + New Message + Nuut Boodskap + + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + Toemaak + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Vasstel Tou</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + File Name + + + + Size + Size + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + Download + + + + Download all + + + + + Hide + Hide + + + + Expand + + + + + File + + + + + Files + Files Biblioteek + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + Nuut Boodskap + + + + Compose + kreëer + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + Nuut Boodskap + + + + Quick View + + + + + Reply to Message + Antwoord aan Boodskap + + + + Remove Message + Remove Boodskap + + + + + Date + Date + + + + + + From + From + + + Size + Size + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Vasstel Tou</span></p></body></html> + + + + Reply + + + + + Reply all + + + + + Foward + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + + + + Delete + + + + + Compose + kreëer + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + Reset + Reset + + + + Attachments + + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + Email-Inbox + + + + + + + Outbox + Email-Outbox + + + + Draft + Konsep + + + + + Sent + Email-Sent + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nuut Boodskap</p></body></html> + + + Download All + Download All + + + File Name + File Name + + + Sources + Sources + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + Download + + + + Empty trash + + + + Hide + Hide + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + Files + Files Biblioteek + + + + + + + + Total: + + + + + + Reply to All + + + + + + Subject + + + + + Print + + + + + MessagesPopupDialog + + New Message + Nuut Boodskap + + + Reply to Message + Antwoord aan Boodskap + + + Remove Message + Remove Boodskap + + + Messages + Email + + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Draft + Konsep + + + Sent + Email-Sent + + + Date + Date + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Vasstel Tou</span></p></body></html> + + + File Name + File Name + + + Size + Size + + + Sources + Sources + + + Compose + kreëer + + + Remove + Remove + + + + MessengerDirModel + + Size + Size + + + Rank + Rank + + + + MessengerSharedFiles + + Download + Download + + + + MessengerWindow + + + Expand all + + + + + Collapse all + + + + + Chat + GroepPraat + + + + Message Friend + + + + + Connect To Friend + Verbind to Vriend + + + + Peer Details + Peer Details + + + + Recomend this Friend to... + + + + + Export Friend + Configure Friend + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + Save Certificate + + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Remove Friend + Remove Friend + + + + Click to Change your Avatar + + + + + Search Friends + + + + + Reset + Reset + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Sent + Email-Sent + + + Date + Date + + + + MsgItem + + + Reply to Message + Antwoord aan Boodskap + + + + Remove Item + + + + + + Expand + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Hide + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">boodskaps</span></p></body></html> + + + Date + Date + + + Rank + Rank + + + From + vanaf + + + Title + Koplyn: + + + Msg + Boodskap + + + Count + Count + + + Size + Size + + + Type + Tipe: + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Boodskap Teks</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Vasstel Tou</span></p></body></html> + + + Delete Channel + kanselleer kanaal + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">boodskaps</span></p></body></html> + + + Date + Date + + + Rank + Rank + + + From + vanaf + + + Title + Koplyn: + + + Msg + Boodskap + + + Count + Count + + + Size + Size + + + Type + Tipe: + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Boodskap Teks</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Vasstel Tou</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + belaai sertifikaat + + + Select a pem/pqi File + Select a pem/pqi File + + + File Not Found + File Not Found + + + %1 does not exist. Would you like to create it? + %1 does not exist. Would you like to create it? + + + Failed to Create File + Failed to Create File + + + Unable to create %1 [%2] + Unable to create %1 [%2] + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + Select Certificate + Select Certificate + + + Certificates (*.pqi *.pem) + Certificates (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + + + Accept + Accept + + + Trust + Vertroue + + + Last Contact + Last Contact + + + + + + Name + Name + + + Peer Address + Peer Address + + + Organisation + Organisation + + + Location + Location + + + Country + Country + + + + + Cert Id + Cert Id + + + + Network + Network + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Unknown + + + + + yourself + + + + RetroShare + Retroshare + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + Byvoeg Vriend + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + Rate Options + + + Max Total Data Rate (KB/S): + Max Total Data Rate (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Hide Settings + + + Show Settings + Show Settings + + + Settings + Settings + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Praat saam met Vriend + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Remove All + + + + Options + Options + + + + NotifyDialog + + Channels + Kanaal + + + Messages + Email + + + New Message + Nuut Boodskap + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + Kanaal + + + + Forums + + + + + Chat + + + + + Blogs + + + + + Messages + Email + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + Nuut Boodskap + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + OptionsDlg + + Cancel + kanselleer + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + Make Friend + Maak Vriend + + + Remove Friend + Remove Friend + + + + Chat + GroepPraat + + + + Start Chat + + + + Organisation + Organisation + + + + Location + Location + + + Country + Country + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Send + Oorsend + + + + Cancel + + + + + Peer ID: + + + + + Write Message + + + + + Status: + + + + + Trust: + + + + + Name: + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + Hide + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Praat saam met Vriend + + + + PeersDialog + + Chat + Praat + + + Export Friend + Configure Friend + + + Remove Friend + Remove Friend + + + Save Certificate + Save Certificate + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Status + Status + + + Person + Person + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Vriend</span></p></body></html> + + + Connect To Friend + Verbind to Vriend + + + Location + Location + + + Peer Details + Peer Details + + + RetroShare + Retroshare + + + Send + Oorsend + + + Add Friend + Byvoeg Vriend + + + Friends + Praat saam met Vriend + + + + PeersFeed + + Save Certificate + Save Certificate + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Friends + Praat saam met Vriend + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Remove + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + + Date + Date + + + + + Location + Location + + + + Size + Size + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + Remove + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + RetroShare + Retroshare + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + Oorsend + + + + Close + Toemaak + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + Retroshare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Directories + Directories + + + Error Saving Configuration + Error Saving Configuration + + + General + General + + + Server + Peer Settings + + + Options + Options + + + Cancel + Kanselleer + + + OK + Top OK + + + Help + Help + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + Download al die + + + + RetroShare + Retroshare + + + + Error : cannot get peer details. + + + + + + Name + Name + + + + Peer ID + + + + + Size + Size + + + + Profile View + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + Name + Name + + + Date + Date + + + Size + Size + + + + + RetroShare + Retroshare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + Remove + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + General + + + + Directories + + + + + Server + + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Error Saving Configuration + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RemoteDirModel + + Size + Size + + + Rank + Rank + + + Files + Files Biblioteek + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Invalid language code specified: + + + + Invalid GUI style specified: + Invalid GUI style specified: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + Sources + + + + Results + Results + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + Download + + + + Enter a keyword here (at least 3 char long) + + + + Broadcast on Channel + Broadcast on Channe + + + Recommend to Friends + Recommend to Friends + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + Remove + + + + Remove All + Remove All + + + + + Folder + + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + + Any + Any + + + + Audio + Audio + + + + Video + Video + + + Images + Images + + + Programs + Programs + + + Archives + Archives + + + Documents + Documents + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Size + Size + + + + Type + Tipe: + + + + Archive + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + File Name + + + + File Size + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + Search + + + + Reset + Reset + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Search Id + + + + + SendLinkDialog + + Send + Oorsend + + + + ServerDialog + + Transfer Rates + Transfer Rates + + + Port: + Port: + + + + ServerPage + + Change + Restart Server + Change + Restart + + + Server Settings + Peer Settings + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Download (KB/s) + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + Port: + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + Misc + Misc + + + behinde Firewall + Behind a Firewall + + + Forwarded External Port + Forwarded External Port (Router) + + + + Transfer Rates + Transfer Rates + + + + Settings + + Settings + Settings + + + + Options + Options + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + Cancel + Kanselleer + + + Apply + Apply + + + + OK + OK + + + + General + General + + + Network + Network + + + + Server + Peer + + + + Directories + Katalogus + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + Friends + Praat saam met Vriend + + + + OK + + + + + Cancel + + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + Retroshare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + Remove + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + Toemaak + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Download + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + Reset + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + Retroshare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + Statistics + + + + Download + Download + + + + Session: + Session: + + + + + Downloaded: + Downloaded: + + + Average Downloadspeed: + Average Downloadspeed: + + + + + Count of Downloads: + Count of Downloads: + + + + + + Overall + Overall + + + + Upload + Upload + + + + + + Session + Session + + + + Uploaded: + Uploaded: + + + Average Uploadspeed: + Average Uploadspeed: + + + + + Count of Uploads: + Count of Uploads: + + + + Uploaded + Uploaded + + + + + + + Connections: + Connections: + + + + + + Peers: + Peers: + + + Misc + Misc + + + + Uptime: + Uptime: + + + Overall: + Overall: + + + + + Uptime + Uptime + + + + Records + Records + + + + Uploadspeed: + Uploadspeed: + + + + Downloadspeed: + Downloadspeed: + + + + + Show Settings + Show Settings + + + + Reset + Reset + + + + Receive Rate + Receive Rate + + + + Send Rate + Send Rate + + + + Always On Top + Always On Top + + + + 100 + 100 + + + + % Opaque + 100 + + + + Changes the transparency of the Bandwidth Graph + Changes the transparency of the Bandwidth Graph + + + + Save + Save + + + + Cancel + Cancel + + + + Hide Settings + Hide Settings + + + + %1 days + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Since: + + + + + Cumulative + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + + + + + Cancel + + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + Style + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Tipe: + + + + Delete FeedItem + + + + + SubFileItem + + File Name + File Name + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + Download + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + Retroshare + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + sertifikaat belaai nee werk + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Kanselleer + + + + Clear Completed + Clear Completed + + + + + Status + Status + + + + Completed + Completed + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + Done + + + + Active + + + + + Outstanding + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + + + + + Name + i.e: file name + Name + + + + + Size + i.e: file size + Size + + + Progress + i.e: % downloaded + Progress + + + + Speed + i.e: Download speed + Speed + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + Sources + + + + Core-ID + + + + + Progress + i.e: % uploaded + Progress + + + + Speed + i.e: upload speed + Speed + + + + Transferred + + + + + Hash + + + + + Play + + + + + Pause + + + + + Resume + + + + + Force Check + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Priority (Speed)... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + Queued + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + Retroshare + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Peer + i.e: user name + + + + + Router Statistics + + + + + Router Requests + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Move in Queue... + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + version: + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + Files Biblioteek + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + Size + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + Vertroue + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + File Name + File Name + + + Type + Tipe: + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Download + Download + + + Broadcast on Channel + Broadcast on Channe + + + Recommend to Friends + Recommend to Friends + + + Remove + Remove + + + Remove All + Remove All + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + Any + Any + + + Audio + Audio + + + Video + Video + + + Size + Size + + + Sources + Sources + + + Type + Tipe: + + + Results + Results + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + OK + + + + Cancel + Kanselleer + + + + Yes + Ja + + + + No + No + + + + Help + Help + + + + Retry + Retry + + + + Show Log + Show Log + + + + Show Settings + Show Settings + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Details + Details + + + OK + OK + + + Name + Name + + + Value + Value + + + diff --git a/retroshare-gui/src/lang/retroshare_bg.qm b/retroshare-gui/src/lang/retroshare_bg.qm new file mode 100644 index 000000000..d9c7f6276 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_bg.qm differ diff --git a/retroshare-gui/src/lang/retroshare_bg.ts b/retroshare-gui/src/lang/retroshare_bg.ts new file mode 100644 index 000000000..1a9e52c79 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_bg.ts @@ -0,0 +1,13683 @@ + + + + + + + Arial + Arial + + + + @default + + Arial + Arial + + + + AboutDialog + + + About RetroShare + + + + + About + За програмата + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + RetroShare + + + + Sorry, can't determine system default command for this file + + + + + + AddFileAssotiationDialog + + RetroShare + RetroShare + + + + AddFriendDialog + + Cancel + Отказ + + + Done + Готово! + + + Load From File + Зареждане от файл + + + RetroShare + RetroShare + + + Certificate Load Failed + Неуспешно зареждане на сертификат + + + + AddFriendWizard + + Cancel + Отказ + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + Отказ + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Cancel + Отказ + + + + Search + Търсене + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search Criteria + + + + + AppearanceDialog + + Language + Език + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Изберете език, с който да работи RetroShare</p></body></html> + + + + AppearancePage + + + Language + Език + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Изберете език, с който да работи RetroShare</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + + + Style + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + + + Style Sheet + + + + + ApplicationWindow + + + Hide + Скриване + + + + Show + Показване + + + + + RetroShare + RetroShare + + + Transfers + Трансфер + + + Messages + Съобщения + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + Статистика + + + + AttachFileItem + + + Form + + + + File Name + Име на файл + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + Идентификация + + + Authenticate Friend By Entering Their Code + Идентификация на приятел чрез код + + + OK + OK + + + Cancel + Отказ + + + + BandwidthGraph + + + + Show Settings + Показване на настройките + + + + Reset + Рестартиране + + + + Receive Rate + Скорост на получаване + + + + Send Rate + СКорост на изпращане + + + + Changes the transparency of the Bandwidth Graph + Променя прозрачността на графиката за канала + + + + 100 + 100 + + + + % Opaque + % непрозрачност + + + + Save + Съхраняване + + + + Cancel + Отказ + + + + Since: + + + + + Hide Settings + Скриване на настройките + + + + RetroShare Bandwidth Usage + + + + + Always on Top + + + + + Style + + + + + BgWindow + + Options + Настройки + + + About + За програмата + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + Отказ + + + + OK + + + + + Close + Затваряне + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + Име + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + Скриване + + + + CalDialog + + + Remove + Изтриване + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + Изберете сертификат + + + Certificates (*.pqi *.pem) + Сертификати (*.pqi *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + RetroShare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + Create a new Broadcast Channel + Създаване на нов канал + + + Create A New Broadcast Channel + Създаване на нов канал + + + Channel Name: + Име на канала: + + + Type: + Вид: + + + Public Channel (Signed) + Публичен канал (с подпис) + + + Private Channel (Encrypted) + Таен канал (криптиран) + + + Cancel Channel + Отказ + + + Create Channel + Създаване на канал + + + + ChanMsgDialog + + Compose + Създаване + + + Recommended Files + Препоръчани файлове + + + Send To: + До: + + + Send + Изпращане + + + Delete Channel + Изтриване на канал + + + Create Channel MSG + Създаване на канал MSG + + + File Name + Име на файл + + + Size + Размер + + + Sources + Източници + + + Save + Съхраняване + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + Сваляне + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Скриване + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + Канали + + + Video + Видео + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + Вид + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + Отказ + + + + OK + + + + + Close + Затваряне + + + + ChannelFeed + + + Create Channel + Създаване на канал + + + + Subscribe To Channel + Абонамент за канал + + + Title + Заглавие + + + Reset + Рестартиране + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + Name + Име + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChatDialog + + Chat + Разговор + + + Send + Изпращане + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + Изпращане + + + + Cancel + Отказ + + + Chat + Разговор + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + Общи + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + Нов приятел + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + Настройки + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Cancel + Отказ + + + Port: + Порт: + + + Trust Settings + Настройки за доверие + + + Trust Level + Ниво на доверие + + + Trust Their Signature + Сертифициране на подпис + + + Sign The Certificate + Подпис на сертификата + + + + Details + Подробности + + + + Name + Име + + + + Loc + + + + + Peer Address + Адрес + + + + Last Contact + Последно свързване + + + Peer Details + Потребителска информация + + + + Peer Info + + + + + Peer ID + + + + + Version + + + + + Addresses list + + + + + Apply and Close + + + + + + RetroShare + RetroShare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + None + + + + + Marginal + + + + + Full + + + + + Deny Friend + + + + + + Sign GPG key + + + + + Friend Details + + + + + RetroShare ID + + + + + Status + Състояние + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port + + + + + Your trust in this peer is: + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Make Friend + Нов приятел + + + + Certificate + + + + + OK + + + + + ConnectDialog + + Peer Details + Потребителска информация + + + Make Friend + Нов приятел + + + Cancel + Отказ + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + Име + + + + Description + + + + + Type: + Вид: + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + Отказ + + + + Create + + + + + RetroShare + RetroShare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + RetroShare + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + Име + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + Вид: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + Отказ + + + + Create + + + + + RetroShare + RetroShare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + RetroShare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Име + + + + Type: + Вид: + + + + Authenticated Messages + + + + + Cancel + Отказ + + + RetroShare + RetroShare + + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Description + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Create + + + + + CreateForumMsg + + + Close + Затваряне + + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + RetroShare + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + RetroShare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + CryptographyDialog + + RSA Key Size + Размер на RSA ключ + + + Rijndael Block size + Размер на Rijndael блок + + + 128 Bits + 128 Bits + + + 192 Bits + 192 Bits + + + 256 Bits + 256 Bits + + + Rijndael Key Size + Размер на Rijndael ключ + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + PKCS7 + PKCS7 + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Размер на Rijndael + + + Key Size: + Размер на ключа: + + + Block Size: + Размер на блока: + + + Feedback Size: + Размер на обратната връзка: + + + RetroShare + RetroShare + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Подробности + + + + + General + Общи + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + Вид: + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + Дата + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + + + + + Cancel + Отказ + + + + Rating + + + + + File Name + Име на файл + + + + Not Rated + + + + + No Comments + + + + + DirectoriesDialog + + Shared Directories + Споделени директории + + + Other Directories + Други директории + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Входящи файлове</span></p></body></html> + + + Add Shared Directory + Добавяне на директория за споделяне + + + + DirectoriesPage + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + Споделени директории + + + + Edit Share + + + + Incoming files + Входящи файлове + + + + + Browse + + + + Add Shared Directory + Добавяне на директория за споделяне + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + Затваряне + + + + EditChanDetails + + + Channel Details + + + + + Cancel + Отказ + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + Отказ + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Приятели</span></p></body></html> + + + + Status + Състояние + + + + Person + Потребител + + + + Auto Connect + Автоматично свързване + + + + Trust Level + Ниво на доверие + + + + Peer Address + Адрес + + + + Last Contact + Последно свързване + + + + Organisation + Организация + + + + Location + Местоположение + + + + Country + Държава + + + + Person Id + Потребителска идентификация + + + + Auth Code + Идентификационен код + + + + # + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileHashDialog + + Download + Сваляне + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + %1 KB + %1 KB + + + File Name + Име на файл + + + Size + Размер + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + Размер + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + Отказ + + + + OK + + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + Изпращане + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + Разни + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + Скриване + + + + Expand + + + + + + RetroShare + RetroShare + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + + Date + Дата + + + + + Title + Заглавие + + + + + Start New Thread + + + + New Message + Ново съобщение + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + Рестартиране + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + Приятели + + + + Status + Състояние + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + Изпращане + + + + Clear Chat History + + + + + + Add Friend + Добавяне на приятел + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + Местоположение + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + Разговор + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + Свързване с приятел + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + Запазване на сертификат + + + + Certificates (*.pqi) + Сертификати (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + Общи + + + Network + Мрежа + + + Directories + Директории + + + Server + Сървър + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Server + Сървър + + + + Status + Състояние + + + + Accept + Приемане + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Инсталация на Retro Share + + + Load Trusted Certificate (Optional) + Зареждане на сертификат (по избор) + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + Име + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + Местоположение + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Приятел</span></p></body></html> + + + Select File + Избор на файл + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Име:</p></body></html> + + + Generate New Certificate + Генериране на нов сертификат + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + Избор на доверен приятел + + + + Certificates (*.pqi *.pem) + Сертификати (*.pqi *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + GeneralDialog + + Language + Език + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Изберете език, с който да работи RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Промяната на езика ще настъпи когато рестартирате RetroShare!</p></body></html> + + + Login + Вход + + + Misc + Разни + + + + GeneralPage + + Keys manager + Управление на ключовете + + + Choose RetroShare's interface style + Избор на интерфейсен език за Retro Share + + + Language + Език + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Промяната на езика ще настъпи при рестартиране на RetroShare!</p></body></html> + + + Choose the language used in RetroShare + Избор на език за работа с Retro Share + + + Login + Вход + + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + Разни + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Получени: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Изпратени: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Приятели + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + Заглавие + + + + Description + + + + + Reset + Рестартиране + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + Име + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + Дата + + + + Size + Размер + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + Search + Търсене + + + + Home + Начало + + + + Close + Затваряне + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + За програмата + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + Рестартиране + + + + + Copy + + + + + Remove + Изтриване + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + Изпращане + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + InviteDialog + + Done + Готово! + + + Cancel + Отказ + + + Launch Email + Зареждане на електронна поща + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + Сваляне + + + + Expand + + + + + Hide + Скриване + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + От + + + + Show + Показване + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + MainWindow + + + Network + Мрежа + + + + Friends + Приятели + + + + + Transfers + Трансфер + + + + + Messages + Съобщения + + + + + Channels + Канали + + + + Blogs + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + Състояние + + + + Chat + Разговор + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + + + Options + Настройки + + + + Hide + Скриване + + + + Show + Показване + + + + RetroShare + RetroShare + + + Invite Friend + Покана за приятел + + + + MainWindow + + + + + Add Friend + Добавяне на приятел + + + + Add a Friend Wizard + + + + + Add Share + Добавяне на директория + + + + + Quick Start Wizard + + + + + Search + Търсене + + + + Files + Файлове + + + Add Shared Directory + Добавяне на директория за споделяне + + + + Show/Hide + + + + + &Quit + + + + + + + + You have %1 new message + + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Minimize + + + + + Maximize + + + + + Links Cloud + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Unfinished + + + + + Help + Помощ + + + + About + За програмата + + + + + Forums + + + + + Open Messages + + + + + Applications + + + + Settings + Настройки + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + Quit + + + + + SMPlayer + + + + + Messenger + + + + + MessageComposer + + + + Compose + Създаване + + + + + Contacts + + + + + Search for Name: + + + + + Reset + Рестартиране + + + + Send To: + До: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + Препоръчани файлове + + + + File Name + Име на файл + + + + Size + Размер + + + Sources + Източници + + + + Hash + + + + + Send + Изпращане + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + Съхраняване + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + RetroShare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + Misc + Разни + + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + съобщение + + + New Message + Ново съобщение + + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + Затваряне + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоръчани файлове</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + Име на файл + + + + Size + Размер + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + Сваляне + + + + Download all + + + + + Hide + Скриване + + + + Expand + + + + + File + + + + + Files + Файлове + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + Ново съобщение + + + + Compose + Създаване + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + Ново съобщение + + + + Quick View + + + + + Reply to Message + Отговор + + + + Remove Message + Изтриване + + + + + Date + Дата + + + + + + From + От + + + Size + Размер + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоръчани файлове</span></p></body></html> + + + + Reply + + + + + Reply all + + + + + Foward + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">изтриване на избраните съобщения</p></body></html> + + + + Delete + + + + + Compose + Създаване + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + Reset + Рестартиране + + + + Attachments + + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + Входяща кутия + + + + + + + Outbox + Изходяща кутия + + + + Draft + Чернови + + + + + Sent + Изпратени + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">отговор на избраните съобщения </p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ново съобщение</p></body></html> + + + Download All + Изтегляне на всички + + + File Name + Име на файл + + + Sources + Източници + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + Сваляне + + + + Empty trash + + + + Hide + Скриване + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + Files + Файлове + + + + + + + + Total: + + + + + + Reply to All + + + + + + Subject + + + + + Print + + + + + MessagesPopupDialog + + New Message + Ново съобщение + + + Reply to Message + Отговор + + + Remove Message + Изтриване + + + Messages + Съобщения + + + Inbox + Входяща кутия + + + Outbox + Изходяща кутия + + + Draft + Чернови + + + Sent + Изпратени + + + From + От + + + Date + Дата + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоръчани файлове</span></p></body></html> + + + File Name + Име на файл + + + Size + Размер + + + Sources + Източници + + + Compose + Създаване + + + Remove + Изтриване + + + + MessengerDirModel + + Size + Размер + + + Rank + Ранг + + + + MessengerSharedFiles + + Download + Сваляне + + + + MessengerWindow + + + Expand all + + + + + Collapse all + + + + + Chat + Разговор + + + + Message Friend + + + + + Connect To Friend + Свързване с приятел + + + + Peer Details + Потребителска информация + + + + Recomend this Friend to... + + + + + Export Friend + Експорт на приятел + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + Запазване на сертификат + + + + Certificates (*.pqi) + Сертификати (*.pqi) + + + Remove Friend + Изтриване на приятел + + + + Click to Change your Avatar + + + + + Search Friends + + + + + Reset + Рестартиране + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + Входяща кутия + + + Outbox + Изходяща кутия + + + Sent + Изпратени + + + Date + Дата + + + + MsgItem + + + Reply to Message + Отговор + + + + Remove Item + + + + + + Expand + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Скриване + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Съобщения</span></p></body></html> + + + Date + Дата + + + Rank + Ранг + + + From + От + + + Title + Заглавие + + + Msg + Съобщение + + + Count + Брой + + + Size + Размер + + + Type + Вид + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Текст на съобщението</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоръчани файлове</span></p></body></html> + + + Delete Channel + Изтриване на канал + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Съобщения</span></p></body></html> + + + Date + Дата + + + Rank + Ранг + + + From + От + + + Title + Заглавие + + + Msg + Съобщение + + + Count + Брой + + + Size + Размер + + + Type + Вид + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Текст на съобщението</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоръчани файлове</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + Зареждане на сертификат + + + Select a pem/pqi File + Избор на pem/pqi файл + + + File Not Found + Файлът не е намерен + + + %1 does not exist. Would you like to create it? + %1 не съществува. Искате ли да го създадете? + + + Failed to Create File + Грешка при създаването на файла + + + Unable to create %1 [%2] + %1 [%2] не може да бъде създаден + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + Select Certificate + Изберете сертификат + + + Certificates (*.pqi *.pem) + Сертификати (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Мрежа:</span></p></body></html> + + + Accept + Приемане + + + Trust + Доверие + + + Last Contact + Последно свързване + + + + + + Name + Име + + + Peer Address + Адрес + + + Organisation + Организация + + + Location + Местоположение + + + Country + Държава + + + + + Cert Id + Сертификат + + + + Network + Мрежа + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Unknown + + + + + yourself + + + + RetroShare + RetroShare + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + Добавяне на приятел + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + Настройки за скоростта + + + Max Total Data Rate (KB/S): + Общ максимум за скорост (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Скорост за един потребител (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Скриване на настройките + + + Show Settings + Показване на настройките + + + Settings + Настройки + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Приятели + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + + + + + Cancel + Отказ + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Изтриване на всичко + + + + Options + Настройки + + + + NotifyDialog + + Channels + Канали + + + Chat + Разговор + + + Messages + Съобщения + + + New Message + Ново съобщение + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + Канали + + + + Forums + + + + + Chat + Разговор + + + + Blogs + + + + + Messages + Съобщения + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + Ново съобщение + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + OptionsDlg + + Cancel + Отказ + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + Make Friend + Нов приятел + + + Remove Friend + Изтриване на приятел + + + + Chat + Разговор + + + + Start Chat + + + + Organisation + Организация + + + + Location + Местоположение + + + Country + Държава + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Send + Изпращане + + + + Cancel + Отказ + + + + Peer ID: + + + + + Write Message + + + + + Status: + + + + + Trust: + + + + + Name: + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + Скриване + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Приятели + + + + PeersDialog + + Chat + Разговор + + + Export Friend + Експорт на приятел + + + Remove Friend + Изтриване на приятел + + + Save Certificate + Запазване на сертификат + + + Certificates (*.pqi) + Сертификати (*.pqi) + + + Status + Състояние + + + Person + Потребител + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Приятели</span></p></body></html> + + + Connect To Friend + Свързване с приятел + + + Location + Местоположение + + + Peer Details + Потребителска информация + + + RetroShare + RetroShare + + + Send + Изпращане + + + Add Friend + Добавяне на приятел + + + Friends + Приятели + + + + PeersFeed + + Save Certificate + Запазване на сертификат + + + Certificates (*.pqi) + Сертификати (*.pqi) + + + Friends + Приятели + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Изтриване + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + + Date + Дата + + + + + Location + Местоположение + + + + Size + Размер + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + Изтриване + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + RetroShare + RetroShare + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + Изпращане + + + + Close + Затваряне + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + RetroShare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Directories + Директории + + + Error Saving Configuration + Грешка при запазване на настройките + + + General + Общи + + + Server + Сървър + + + Options + Настройки + + + Cancel + Отказ + + + OK + ОК + + + Help + Помощ + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + Сваляне на всичко + + + + RetroShare + RetroShare + + + + Error : cannot get peer details. + + + + + + Name + Име + + + + Peer ID + + + + + Size + Размер + + + + Profile View + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + Name + Име + + + Date + Дата + + + Size + Размер + + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + Изтриване + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + Общи + + + + Directories + Директории + + + + Server + Сървър + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + Разговор + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Грешка при запазване на настройките + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RemoteDirModel + + Size + Размер + + + Rank + Ранг + + + Files + Файлове + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Посочен е невалиден езиков код: + + + + Invalid GUI style specified: + Посочен е невалиден GUI стил: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + Източници + + + + Results + Резултати + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + Сваляне + + + + Enter a keyword here (at least 3 char long) + + + + Broadcast on Channel + Излъчване по канал + + + Recommend to Friends + Препоръка за приятели + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + Изтриване + + + + Remove All + Изтриване на всичко + + + + + Folder + + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Формат</p></body></html> + + + + Any + Всички + + + + Audio + Аудио + + + + Video + Видео + + + Images + Изображения + + + Programs + Програми + + + Archives + Архиви + + + Documents + Документи + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Size + Размер + + + + Type + Вид + + + + Archive + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + Име на файл + + + + File Size + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + Търсене + + + + Reset + Рестартиране + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Search Id + + + + + SendLinkDialog + + Send + Изпращане + + + + ServerDialog + + Transfer Rates + Скорост на трансфер + + + Port: + Порт: + + + + ServerPage + + Change + Restart Server + Промяна и рестартиране на сървъра + + + Server Settings + Настройки на сървъра + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Външен адрес:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Вътрешен адрес:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Порт:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Download (KB/s) + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + Порт: + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + Misc + Разни + + + behinde Firewall + зад Огнена стена + + + Forwarded External Port + Външен порт за пренасочване + + + + Transfer Rates + Скорост на трансфер + + + + Settings + + Settings + Настройки + + + + Options + Настройки + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + Разговор + + + + Appearance + + + + + Sound + + + + + Cancel + Отказ + + + Apply + Прилагане + + + + OK + ОК + + + + General + Общи + + + Network + Мрежа + + + + Server + Сървър + + + + Directories + Директории + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + Friends + Приятели + + + + OK + + + + + Cancel + Отказ + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + Отказ + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + RetroShare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + Изтриване + + + Add Shared Directory + Добавяне на директория за споделяне + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + Затваряне + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Сваляне + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Файлове</span></p></body></html> + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + Рестартиране + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + RetroShare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + Статистика + + + + Download + Сваляне + + + + Session: + Сесия: + + + + + Downloaded: + Свалено: + + + Average Downloadspeed: + Средна скорост на сваляне: + + + + + Count of Downloads: + Брой на свалянията: + + + + + + Overall + Общо + + + + Upload + Качено + + + + + + Session + Сесия + + + + Uploaded: + Качено: + + + Average Uploadspeed: + Средна скорост на качване: + + + + + Count of Uploads: + Брой на качванията: + + + + Uploaded + Качено + + + + + + + Connections: + Връзки: + + + + + + Peers: + Потребители: + + + Misc + Разни + + + + Uptime: + Време на активност: + + + Overall: + Общо: + + + + + Uptime + Време на активност + + + + Records + Записи + + + + Uploadspeed: + Скорост на качване: + + + + Downloadspeed: + Скорост на сваляне: + + + + + Show Settings + Показване на настройките + + + + Reset + Рестартиране + + + + Receive Rate + Скорост на получаване + + + + Send Rate + СКорост на изпращане + + + + Always On Top + Над всички прозорци + + + + 100 + 100 + + + + % Opaque + % непрозрачност + + + + Changes the transparency of the Bandwidth Graph + Променя прозрачността на графиката за канала + + + + Save + Съхраняване + + + + Cancel + Отказ + + + + Hide Settings + Скриване на настройките + + + + %1 days + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Since: + + + + + Cumulative + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + + + + + Cancel + Отказ + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Вид + + + + Delete FeedItem + + + + + SubFileItem + + File Name + Име на файл + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + Сваляне + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + RetroShare + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + Неуспешно зареждане на сертификат + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Отказ + + + + Clear Completed + Изчистване на готовите + + + + + Status + Състояние + + + + Completed + Готови + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Сваляне:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + Готово! + + + + Active + + + + + Outstanding + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Качване:</span></p></body></html> + + + + + Name + i.e: file name + Име + + + + + Size + i.e: file size + Размер + + + Progress + i.e: % downloaded + Развитие + + + + Speed + i.e: Download speed + Скорост + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + Източници + + + + Core-ID + + + + + Progress + i.e: % uploaded + Развитие + + + + Speed + i.e: upload speed + Скорост + + + + Transferred + + + + + Hash + + + + + Play + + + + + Pause + + + + + Resume + + + + + Force Check + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Priority (Speed)... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + Queued + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + RetroShare + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Peer + i.e: user name + + + + + Router Statistics + + + + + Router Requests + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Move in Queue... + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + version: + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + Файлове + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + Размер + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + Доверие + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + File Name + Име на файл + + + Type + Вид + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Download + Сваляне + + + Broadcast on Channel + Излъчване по канал + + + Recommend to Friends + Препоръка за приятели + + + Remove + Изтриване + + + Remove All + Изтриване на всичко + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Формат</p></body></html> + + + Any + Всички + + + Audio + Аудио + + + Video + Видео + + + Size + Размер + + + Sources + Източници + + + Type + Вид + + + Results + Резултати + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + ОК + + + + Cancel + Отказ + + + + Yes + Да + + + + No + Не + + + + Help + Помощ + + + + Retry + Нов опит + + + + Show Log + История + + + + Show Settings + Показване на настройките + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Details + Подробности + + + OK + ОК + + + Name + Име + + + Value + Стойност + + + diff --git a/retroshare-gui/src/lang/retroshare_cy.qm b/retroshare-gui/src/lang/retroshare_cy.qm new file mode 100644 index 000000000..90ca60e26 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_cy.qm differ diff --git a/retroshare-gui/src/lang/retroshare_cy.ts b/retroshare-gui/src/lang/retroshare_cy.ts new file mode 100644 index 000000000..3e7528745 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_cy.ts @@ -0,0 +1,7545 @@ + + + + + + + + + Arial + + + + + AddFileAssociationDialog + + + File type(extension): + Ffeil math (estyniad): + + + + Use default command + + + + + Command + + + + + RetroShare + + + + + Sorry, can't determine system default command for this file + + + + + + AddLinksDialog + + + + Add Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600; color:#00aa00;">Add Link to Cloud</span></p></body></html> + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + Cancel + + + + + AdvancedSearchDialog + + + RetrosShare: Advanced Search + + + + + Add a further search criterion. + + + + + Add a selection criterion + + + + + Reset the search criteria. + + + + + Reset + + + + + Cancels the search. + + + + + Cancel + + + + + Perform the advanced search. + + + + + Search + + + + + Search Criteria + + + + + AppearancePage + + + Language + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + + + Style + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + + + Style Sheet + + + + + ApplicationWindow + + + Hide + + + + + Show + + + + + Peers + + + + + Transfers + + + + + Messages + + + + + Blog Feed + + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + + + + + + RetroShare + + + + + BandwidthGraph + + + + Show Settings + + + + + Since: + + + + + Hide Settings + + + + + RetroShare Bandwidth Usage + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always on Top + + + + + Style + + + + + Changes the transparency of the Bandwidth Graph + + + + + 100 + + + + + % Opaque + + + + + Save + + + + + Cancel + + + + + BlogDialog + + + Form + + + + + Blogs + + + + + Last Month + + + + + Last Week + + + + + Last Day + + + + + All Users + + + + + Jimmy + + + + + John + + + + + Jacki + + + + + No Feeds + + + + + Post Blog + + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Connected + + + + + Expand + + + + + Subject + + + + + subjectLabel + + + + + Play Media + + + + + Long + message here + + + + + CalDialog + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + Preifat + + + + Public + Cyhoeddus + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Remove + + + + + Peer Calendars + + + + + CallToaster + + + Message + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + Rhaid i chi greu ffeil gyda'ch tystysgrif a rhoi i eich ffrind. Hefyd, gallwch ddefnyddio ffeil a gynhyrchwyd cyn. + + + + + Export my certificate... + + + + + Specify path to your friend's certificate in the box below + + + + + Browse + + + + + Select Certificate + + + + + Certificates (*.pqi *.pem) + + + + + Please choose a filename + + + + + + RetroShare + + + + + Certificate file successfully created + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + + Create a new Broadcast Channel + + + + + Create A New Broadcast Channel + + + + + Channel Name: + + + + + Type: + + + + + Cancel Channel + + + + + Create Channel + + + + + Public Channel (Signed) + + + + + Private Channel (Encrypted) + + + + + ChanGroupItem + + + Form + + + + + Expand + + + + + Channel Group + + + + + ChanMenuItem + + + Form + + + + + Expand + + + + + Connected + + + + + Popularity: + + + + + Fetches: + + + + + Available: + + + + + Description + of Forum + + + + + ChanMsgDialog + + + Delete Channel + + + + + Create Channel MSG + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + Send this message now + + + + + Toggle Contacts View + + + + + Save this message + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Compose + + + + + + Contacts + + + + + Send To: + + + + + Subject: + + + + + Font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Color + + + + + Alignment + + + + + Add a Image + + + + + Recommended Files + + + + + File Name + + + + + Size + + + + + Sources + + + + + Hash + + + + + Send + + + + + Reply + + + + + Save + + + + + ChanMsgItem + + + Form + + + + + Remove Item + + + + + Connected + + + + + Expand + + + + + subjectLabel + + + + + Unsubscribe From Channel + + + + + Play Media + + + + + Long + message here + + + + + ChanNewItem + + + Form + + + + + Remove Item + + + + + Connected + + + + + name + + + + + Subscribe to Channel + + + + + Expand + + + + + Description + of Forum + + + + + ChannelFeed + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt;">Channel Name</span></p></body></html> + + + + + Post To Channel + + + + + Unsubscribe + + + + + Subscribe To Channel + + + + + Subscribe + + + + + Create New Channel + + + + + Unsubcribe To Channel + + + + + Name + + + + + ID + + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Create a new Channel + + + + + New Channel + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + ChatToaster + + + Message + + + + + ConclusionPage + + + Make Friend + + + + + Fill details about your friend here + + + + + Peer details + + + + + Trust: + + + + + Name: + + + + + Org: + + + + + Loc: + + + + + Country: + + + + + Signers + + + + + AUTH CODE + + + + + ConfCertDialog + + + + Details + + + + + Peer Info + + + + + Name: + + + + + Org / Loc: + + + + + Country/State: + + + + + Peer ID + + + + + Last Contact + + + + + Version + + + + + Peer Address + + + + + Local Address: + + + + + External Address: + + + + + + Port: + + + + + Addresses list + + + + + Trust Settings + + + + + Sign this certificate + + + + + Accept connexions from this peer + + + + + Peer has signed my certficate + + + + + Certificate signers + + + + + Make friend (Sign certificate and accept) + + + + + Cancel + + + + + Apply and Close + + + + + Trust + + + + + OK + + + + + ConnectDialog + + + + Make Friend + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#000000;"> Make Friend</span></p></body></html> + + + + + Peer Details + + + + + Trust: + + + + + Name: + + + + + Org: + + + + + Loc: + + + + + Country: + + + + + signers: + + + + + AUTH CODE: + + + + + Cancel + + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateForum + + + RetroShare + + + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Name + + + + + Description + + + + + Type: + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + Create + + + + + CreateForumMsg + + + Post Forum Message + + + + + Forum + + + + + Forum Post Subject + + + + + Forum Post + + + + + Sign Message + + + + + toolBar + + + + + Post Forum Msg + + + + + Close + + + + + CryptoPage + + + + + RetroShare + + + + + Your Public Key is copied to Clipbard, paste and send it to yourfriend via email or some other way + + + + + Certificate file successfully created + + + + + Sorry, certificate file creation failed + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Export my Key as file</p></body></html> + + + + + Export Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DirectoriesPage + + + Add a Share Directory + + + + + Remove Shared Directory + + + + + + Browse + + + + + Add Shared Directory + + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + Incoming Directory + + + + + Partials Direcrtory + + + + + Shared Directories + + + + + Automatically share incoming directory (Recommanded) + + + + + Edit Share + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + + + # + + + + + Status + + + + + Person + + + + + Auto Connect + + + + + Trust Level + + + + + Peer Address + + + + + Last Contact + + + + + Organisation + + + + + Location + + + + + Country + + + + + Person Id + + + + + Auth Code + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileTransferInfoWidget + + + Chunk map: + + + + + Active chunks: + + + + + Availability map ( + + + + + sources + + + + + File info: + + + + + File size: + + + + + Chunk size: + + + + + Number of chunks: + + + + + Number of sources: + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumMsgItem + + + Form + + + + + Remove Item + + + + + Forum Name + + + + + Expand + + + + + + + Subject: + + + + + Subject... + + + + + Persons Name + + + + + Unsubscribe To Forum + + + + + Reply + + + + + + Message is about ??? + + + + + Previous Message... + + + + + Currnent Message.. + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Connected + + + + + name + + + + + Subscribe to Forum + + + + + Expand + + + + + Description + of Forum + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + + New Forum + + + + + Show Forum Details + + + + + Reply + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + Start New Thread + + + + + Forum Name + + + + + Popularity + + + + + Posts + + + + + New Message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + Date + + + + + Title + + + + + Author + + + + + Signed + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Forum Post</span></p></body></html> + + + + + Prev + + + + + Next + + + + + Print + + + + + PrintPreview + + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + + + + + Status + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Accept + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + + Select Trusted Friend + + + + + Certificates (*.pqi *.pem) + + + + + RetroShare : Create new user Profile + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Create a new RetroShare profile</span><br /><br /><span style=" font-size:9pt;">Please fill in the information which will<br />allow your RetroShare to connect to</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Friends.</span></p></body></html> + + + + + Organisation: + + + + + OpenPGP User + + + + + PGP Password + + + + + Info + + + + + Generate New Profil + + + + + Location: + + + + + Country: + + + + + Name: + + + + + GeneralMsgDialog + + + + Channel + + + + + + Forum + + + + + + Blog + + + + + Message + + + + + Add Extra File + + + + + Dialog + + + + + Friend + + + + + Add Message Destination + + + + + Message Destination + + + + + Drag and Drop Files from Search Results + + + + + Attachments + + + + + Subject : + + + + + GeneralPage + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Misc + + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + GraphFrame + + + Recv: + + + + + + + %1 KB/s + + + + + Sent: + + + + + %1 KB + + + + + %1 MB + + + + + %1 GB + + + + + GraphWidget + + + Elastic Nodes + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + + Search + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Home + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/retrosharelogo2.png" /></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must create for RetroShare a GPG key, this is required for creating a RetroShare Profile.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows must install gpg4win package:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p></body></html> + + + + + IntroPage + + + This wizard will help you to connect to your friend(s) to RetroShare network. There are three possible ways to do this: + + + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + &Enter the certificate manually + + + + + &Use *.pqi files with certificates + + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + From + + + + + All Peers + + + + + Own Links + + + + + Show + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + MainWindow + + + Network + + + + + Friends + + + + + Transfers + + + + + Messages + + + + + + Channels + + + + + + Options + + + + + Hide + + + + + Show + + + + + RetroShare + + + + + Search + + + + + Files + + + + + Show/Hide + + + + + &Quit + + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Minimize + + + + + Maximize + + + + + + Links Cloud + + + + + Unfinished + + + + + Help + + + + + News Feed + + + + + + Forums + + + + + Open Messages + + + + + Applications + + + + + RetroShare %1 a secure decentralised commmunication platform + + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + toolBar_2 + + + + + Add Friend + + + + + Add a Friend Wizard + + + + + Add Share + + + + + Quit + + + + + SMPlayer + + + + + Messenger + + + + + MainWindow + + + + + toolBar + + + + + About + + + + + MessageToaster + + + Play video + + + + + Play button + + + + + Play the downloaded video + + + + + <b>1 new Message from</b> + + + + + Close + + + + + Close button + + + + + Close the information dialog + + + + + MessagesDialog + + + New Message + + + + + Reply to Message + + + + + Remove Message + + + + + Print Document + + + + + Forward selected Message + + + + + Remove Messages + + + + + Forward Message + + + + + Download + + + + + + Re: + + + + + Fwd: + + + + + Replay to All + + + + + Reply to All + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + + + + + Inbox + + + + + Outbox + + + + + Draft + + + + + Sent + + + + + From + + + + + Subject + + + + + Date + + + + + Subject: + + + + + From: + + + + + Date: + + + + + To: + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + + + + + File Name + + + + + Size + + + + + Sources + + + + + Hash + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + + + + + Print + + + + + PrintPreview + + + + + MessagesPopupDialog + + + Messages + + + + + Compose + + + + + Reply + + + + + Forward + + + + + Remove + + + + + + Print + + + + + PrintPreview + + + + + MessengerWindow + + + Chat + + + + + Connect To Friend + + + + + Offline + + + + + Send Message + + + + + Remove Friend + + + + + RetroShare Messenger + + + + + Click to Change your Avatar + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Change your Status and your display</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">picture here.</p></body></html> + + + + + + Online + + + + + Busy + + + + + Be right Back + + + + + Away + + + + + In a Call + + + + + Out of lunch + + + + + Apear Offline + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Share a personal message with your contacts</p></body></html> + + + + + Share Files for your Friends + + + + + ... + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Add a Friend</p></body></html> + + + + + MsgFeed + + + Form + + + + + Msgs In: + + + + + Inbox + + + + + Outbox + + + + + Drafts + + + + + Sent + + + + + From: + + + + + All + + + + + Sort By: + + + + + Date + + + + + Subject + + + + + Received + + + + + New Msg + + + + + MsgItem + + + Form + + + + + Remove Item + + + + + Connected + + + + + Expand + + + + + subjectLabel + + + + + Reply to Message + + + + + Delete Message + + + + + Play Media + + + + + Long + message here + + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + + + Select a pem/pqi File + + + + + + File Not Found + + + + + + %1 does not exist. Would you like to create it? + + + + + + Failed to Create File + + + + + + Unable to create %1 [%2] + + + + + Select Certificate + + + + + Certificates (*.pqi *.pem) + + + + + Welcome to RetroShare. + + + + + Menu + + + + + is trusting you. +Right-click and select 'make friend' to be able to connect. + + + + + Trust matrix + + + + + RetroShare %1 started. + + + + + Deny friend + + + + + Accept friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Trusted + + + + + Denied + + + + + Is trusting me + + + + + Unknown + + + + + Never seen + + + + + + RetroShare + + + + + Certificate file successfully created + + + + + Sorry, certificate file creation failed + + + + + UPNP is active. + + + + + UPNP NOT FOUND. + + + + + DHT OK. + + + + + Stun external address detection is working. + + + + + Stun is not working. + + + + + Local network detected + + + + + No local network detected + + + + + ip found via external address finder + + + + + external address finder didn't found anything + + + + + DHT is not working (down). + + + + + Network View + + + + + Form + + + + + Network + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + + + + + Your trust + + + + + Peer's trust + + + + + Last Contact + + + + + Name + + + + + Peer Address + + + + + Organisation + + + + + Location + + + + + Country + + + + + Cert Id + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Log + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + UDP stun external ip address + + + + + External ip address finder + + + + + Create New Profile + + + + + Create a new Profile + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + NetworkView + + + Hide Settings + + + + + Show Settings + + + + + Form + + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); + + + + + + + + + Refresh + + + + + Settings + + + + + Show Friends of Friends + + + + + Connect Signature + + + + + Draw Friend Connections + + + + + NewsFeed + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/konqsidebar_news16.png" /></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + + + + + Forums + + + + + Chat + + + + + Blogs + + + + + Messages + + + + + Downloads + + + + + Toasters + + + + + Peer Connect + + + + + New Message + + + + + Private Chat + + + + + Open Window for new Peer Chat + + + + + Reopen if closed by user: + + + + + Grab Focus when chat arrives + + + + + Group chat + + + + + Display systray message + + + + + OnlineToaster + + + Peer Online + + + + + PeerItem + + + Form + + + + + Remove Item + + + + + + Connected + + + + + Expand + + + + + Status: + + + + + Trust: + + + + + Good + + + + + Make Friend + + + + + Remove Friend + + + + + Send Mail + + + + + Chat + + + + + Name: + + + + + RsId: + + + + + Organisation + + + + + Location + + + + + Country + + + + + + + + + + + + TextLabel + + + + + IP Address + + + + + Connection Method + + + + + Last Contact: + + + + + PeerStatus + + + Online: 0 | Friends: 0 | Network: 0 + + + + + Online: + + + + + Friends: + + + + + Network: + + + + + PeersDialog + + + Chat + + + + + Export Friend + + + + + <strong>Friends</strong> + + + + + (me) + + + + + + - + + + + + Save Certificate + + + + + Certificates (*.pqi) + + + + + Connect To Friend + + + + + Profile + + + + + Welcome to RetroShare's group chat. + + + + + Message Friend + + + + + Peer Details + + + + + Profile View + + + + + Deny Friend + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + # + + + + + Status + + + + + Person + + + + + Italic + + + + + Underline + + + + + Add or Change your Avatar + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; color:#00aa00;">nickname (me)</span></p></body></html> + + + + + Edit Personal message + + + + + Live Chat + + + + + Bold + + + + + Text Color + + + + + Add Friend + + + + + Create new Profile + + + + + Font + + + + + Send + + + + + Clear Chat History + + + + + PeersFeed + + + Save Certificate + + + + + Certificates (*.pqi) + + + + + Form + + + + + Show: + + + + + Friends + + + + + Online Friends + + + + + Friends of Friends. + + + + + All Peers + + + + + PhotoDialog + + + Insert Show Lists + + + + + Remove + + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + + Date + + + + + + Location + + + + + Size + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Form + + + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopupChatDialog + + + Hide Avatar + + + + + :images/hide_toolbox_frame.png + + + + + Show Avatar + + + + + :images/show_toolbox_frame.png + + + + + Open Style + + + + + Styles (*.htm) + + + + + RetroShare - Encrypted Chat + + + + + MainWindow + + + + + + QLabel{ +border-image: url(:/images/mystatus_bg.png); + +} + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Set Chat Window Style</p></body></html> + + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Set Font + + + + + Text Color + + + + + Send + + + + + toolBar + + + + + Strike + + + + + Avatar + + + + + Set your Avatar Picture + + + + + Chatting with + + + + + Add Extra File + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request Error + + + + + The file link is malformed. + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + + + + + Profile View + + + + + Rs ID + + + + + + Name + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Size + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + Form + + + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + + + + + + + TextLabel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Org / Loc:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Country/State:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Last Contact</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Local Address</span></p></body></html> + + + + + QObject + + + Name + + + + + Path + + + + + Extension + + + + + Date + + + + + Size + + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + and + + + + + and / or + + + + + or + + + + + equals + + + + + Hash + + + + + RSettingsWin + + + General + + + + + Directories + + + + + Server + + + + + Notify + + + + + Security + + + + + Appearance + + + + + File Associations + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration + + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + Down: + + + + + Up: + + + + + RemoteDirModel + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Share type + + + + + What's new + + + + + Age + + + + + FILE + + + + + DIR + + + + + Rshare + + + Invalid language code specified: + + + + + Invalid GUI style specified: + + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of Vidalia's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + SearchDialog + + + + Download + + + + + Broadcast on Channel + + + + + Recommend to Friends + + + + + + / + + + + + Remove + + + + + Remove All + + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Any + + + + + Archive + + + + + Audio + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Video + + + + + Directory + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enter a Keyword here</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Close all Search Resullts</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Download Selected</span></p></body></html> + + + + + Filename + + + + + Start Search + + + + + Search + + + + + + Reset + + + + + Advanced Search + + + + + Advanced + + + + + Size + + + + + Sources + + + + + Type + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Results + + + + + Search Id + + + + + Close All Search Results + + + + + ServerPage + + + Network Configuration (restart not needed) + + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Should be disabled if you don't want to share connection information between peers. + + + + + Discovery Enabled + + + + + Discovery Disabled + + + + + Transfer Rates + + + + + Download (KB/s) + + + + + Upload (KB/s) + + + + + Network Configuration + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + + Port: + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + + F2F routing + + + + + enable anonymous F2F routing + + + + + Show router statistics + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">If want to you use </span><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> to anonymously share and download files, leaving this checked drastically increases your download scope, and participate into the overall network bandwidth. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are browsable from your direct friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files can be downloaded by anybody through anonymous tunnels.</li></ul></body></html> + + + + + Settings + + + Options + + + + + General + + + + + Server + + + + + Directories + + + + + Notify + + + + + Security + + + + + Appearance + + + + + File Associations + + + + + Sound + + + + + Cancel + + + + + Apply + + + + + OK + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + Select A Folder To Share + + + + + Do you really want to stop sharing this directory ? + + + + + + Remove + + + + + Warning! + + + + + Shared Directory Added! + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all file in that folder are shared.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + SharedFilesDialog + + + + Download + + + + + Checking... + + + + + Check files + + + + + + Copy retroshare Link + + + + + + Send retroshare Link + + + + + Recommend (Automated message) To + + + + + Recommend in a message to + + + + + Send retroshare Link to Cloud + + + + + Add Link to Cloud + + + + + + Open File + + + + + Open Folder + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Files</span></p></body></html> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + No indicator + + + + + Last day + + + + + Last week + + + + + Last month + + + + + Older + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + User + + + + + go Online + + + + + go Offline + + + + + + + + + + ... + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + New + + + + + StartDialog + + + RetroShare + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Name: + + + + + Password: + + + + + Auto-login + + + + + PGP Password + + + + + Log In + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Create new Profile...</span></a></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + StatisticDialog + + + + Show Settings + + + + + Hide Settings + + + + + %1 days + + + + + Statistics + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Download + + + + + Session: + + + + + + Downloaded: + + + + + + Count of Downloads: + + + + + + + Overall + + + + + Upload + + + + + + + Session + + + + + Uploaded: + + + + + + Count of Uploads: + + + + + Uploaded + + + + + + + + Connections: + + + + + + + Peers: + + + + + Time Statistics + + + + + + Uptime + + + + + Since: + + + + + Cumulative + + + + + Records + + + + + Uploadspeed: + + + + + Downloadspeed: + + + + + Uptime: + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always On Top + + + + + 100 + + + + + % Opaque + + + + + Changes the transparency of the Bandwidth Graph + + + + + Save + + + + + Cancel + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + SubDestItem + + + Form + + + + + Type + + + + + Person/Channel Name + + + + + Delete FeedItem + + + + + SubFileItem + + + Save Channel File + + + + + Form + + + + + File Name + + + + + %p Kb + + + + + Expand + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + Play File + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + Your Cert is copied to Clipboard, paste and send it to yourfriend via email or some other way + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Run Email program + + + + + Connect Friend Help + + + + + Certificate Load Failed + + + + + TransferFeed + + + Form + + + + + Sort: + + + + + None + + + + + TransfersDialog + + + Cancel + + + + + Clear Completed + + + + + + Status + + + + + Completed + + + + + + Name + i.e: file name + + + + + + Size + i.e: file size + + + + + Progress + i.e: % downloaded + + + + + Speed + i.e: Download speed + + + + + Sources + i.e: Sources + + + + + Priority + + + + + Remaining + i.e: Estimated Time of Arrival / Time left + + + + + Core-ID + + + + + Peer + i.e: user name + + + + + Progress + i.e: % uploaded + + + + + Speed + i.e: upload speed + + + + + Transferred + + + + + Play + + + + + Pause + + + + + Resume + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Copy retroshare Link + + + + + Paste retroshare Link + + + + + Set Root is not Decorated + + + + + Set Root is Decorated + + + + + View + + + + + Clear from Queue + + + + + Clear Queue + + + + + + Low + + + + + + Normal + + + + + + High + + + + + + + Auto + + + + + Priority (Download) + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + Queued + + + + + RetroShare + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + + + + + Uploads + + + + + Selected transfer + + + + + Done + + + + + Active + + + + + Outstanding + + + + + + + + Failed + + + + + + + + Okay + + + + + + + + Waiting + + + + + + Downloading + + + + + + + + + Complete + + + + + + + Unknown + + + + + + Uploading + + + + + TrustView + + + Form + + + + + Zoom : + + + + + Update + + + + + Showing: whole network + + + + + TurtleRouterDialog + + + Stop handling this hash + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + Hashes and Tunnels + + + + + Handled file hashes + + + + + File hash + + + + + File Name + + + + + Active tunnels + + + + + Last tunnel request + + + + + Current tunnels + + + + + Tunnel id + + + + + Source + + + + + Destination + + + + + Hash + + + + + Last transfer + + + + + Tunnels / Search Requests + + + + + Tunnel Requests + + + + + + Request id + + + + + + Origin + + + + + + Age + + + + + Search Requests + + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + + + + + Cancel + + + + + Yes + + + + + No + + + + + Help + + + + + Retry + + + + + Show Log + + + + + Show Settings + + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1y %1d %2h %3m + e.g: 2 years 2days 10hours 2minutes + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + %1d %2h %3m + e.g: 2days 10hours 2minutes + + + + diff --git a/retroshare-gui/src/lang/retroshare_da.qm b/retroshare-gui/src/lang/retroshare_da.qm new file mode 100644 index 000000000..3379d9411 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_da.qm differ diff --git a/retroshare-gui/src/lang/retroshare_da.ts b/retroshare-gui/src/lang/retroshare_da.ts new file mode 100644 index 000000000..849fb603c --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_da.ts @@ -0,0 +1,13806 @@ + + + + + AboutDialog + + + About RetroShare + + + + + About + Om + + + + close + Luk + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + RetroShare + + + + Sorry, can't determine system default command for this file + + + + + + AddFileAssotiationDialog + + RetroShare + RetroShare + + + + AddFriendDialog + + Cancel + Afbryd + + + Done + Færdig + + + Load From File + Hent fra fil + + + RetroShare + RetroShare + + + Certificate Load Failed + Certifikat indlæsning fejlede + + + + AddFriendWizard + + Cancel + Afbryd + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + Afbryd + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + Cancel + Afbryd + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + RetroShare: Advanced Search + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search + Søg + + + + Search Criteria + + + + + AppearancePage + + + Language + Sprog + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vælg det sprog, der anvendes i RetroShare</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ændringer i sprog vil først træde i kraft efter genstart RetroShare!</p></body></html> + + + + Style + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vælg RetroShare's grænseflade stil</p></body></html> + + + + Style Sheet + + + + + ApplicationWindow + + + Hide + Skjul + + + + Show + Vis + + + + + RetroShare + RetroShare + + + Transfers + Overførsler + + + Messages + Beskeder + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + + + + + AttachFileItem + + + Form + + + + File Name + Filnavn + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + Autorisér + + + Authenticate Friend By Entering Their Code + Autorisér ven ved at indtaste deres kode + + + OK + O.k. + + + Cancel + Afbryd + + + + BandwidthGraph + + + + Show Settings + + + + + Cancel + Afbryd + + + + Since: + + + + + Hide Settings + + + + + RetroShare Bandwidth Usage + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always on Top + + + + + Style + + + + + Changes the transparency of the Bandwidth Graph + + + + + 100 + + + + + % Opaque + + + + + Save + Gemme + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + Popularitet + + + + Last Post + Sidste indlæg + + + + Blog ID + + + + + Blog Description + + + + + Cancel + Afbryd + + + + OK + O.k. + + + + Close + Luk + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + udvide + + + + Subject + Om + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + udvide + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + Tilføj + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + Navn + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + udvide + + + + Comments here + + + + + Hide + Skjul + + + + CalDialog + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + Navn: + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + Tilføj + + + + Remove + Fjerne + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + Gennemse + + + + Select Certificate + Vælg certifikat + + + Certificates (*.pqi *.pem) + Certifikater (*.pqi *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + RetroShare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare Certificate (*.rsc); Alle filer (*) + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + Create a new Broadcast Channel + Opret en ny udsendelseskanal + + + Create A New Broadcast Channel + Opret en ny udsendelseskanal + + + Channel Name: + Kanalnavn: + + + Type: + Type: + + + Public Channel (Signed) + Offentlig kanal (signeret) + + + Private Channel (Encrypted) + Privat kanal (krypteret) + + + Cancel Channel + Afbryd kanal + + + Create Channel + Opret kanal + + + + ChanMsgDialog + + Compose + Komponér + + + Select Color + Vælg farve + + + Recommended Files + Anbefalede filer + + + Send To: + Send til: + + + Send + Sende + + + Delete Channel + Slet kanal + + + Create Channel MSG + Opret kanal MSG + + + Send this message now + Send denne besked nu + + + Toggle Contacts View + Toggle Kontakter View + + + Save this message + Gem denne besked + + + Compose: + Komponér: + + + &File + &Filer + + + &Open... + &Åbn... + + + &Save + &Gem + + + Save &As... + Gem &som.. + + + &Print... + &Udskriv... + + + &Quit + &Afslut + + + &Edit + &Rediger + + + &Undo + &Fortryd + + + &Copy + &Kopier + + + &Paste + &Indsæt + + + &View + &Vis + + + &Insert + &Indsæt + + + Open File... + Åbn fil... + + + Save as... + Gem som... + + + Print Document + Udskriv dokument + + + Save Message + Gem besked + + + Message has not been Sent. +Do you want to save message ? + Beskeden er ikke blevet sendt. +Ønsker du at gemme beskeden? + + + Choose Image + Vælg Billede + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Billedfiler understøttes (*.png *.jpeg *.jpg *.gif) + + + Add Extra File + Tilføj ekstra fil + + + Size + Størrelse + + + Contacts + Kontakter + + + Subject: + Emne: + + + Font size + Skriftstørrelse + + + Increase font size + Forøg skriftstørrelse + + + Decrease font size + Formindsk skriftstørrelse + + + Attach + Vedhæft + + + Attach File + Vedhæft fil + + + Quote + Citat + + + File Name + Filnavn + + + Sources + Kilder + + + Reply + Svar + + + Save + Gemme + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + + + + + Play + Lege + + + + Remove Item + + + + + + Expand + udvide + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Skjul + + + + ChanNewItem + + + Remove Item + + + + + Unknown Channel + + + + + New Channel + Ny kanal + + + + Updated Channel + + + + + Subscribe to Channel + + + + + Expand + udvide + + + + Channel Decscription + + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + Forum Name + Forum navn + + + + Popularity + Popularitet + + + + Last Post + Sidste indlæg + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + Type + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + Afbryd + + + + OK + O.k. + + + + Close + Luk + + + + ChannelFeed + + + Create Channel + Opret kanal + + + + Subscribe To Channel + Abonnér på kanal + + + Title + Titel + + + Description + Beskrivelse + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + Add + Tilføj + + + + Display + + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + Name + Navn + + + Popularity + Popularitet + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + Create a new Channel + Opret en ny kanal + + + New Channel + Ny kanal + + + + ChatDialog + + Chat + Samtale + + + Send + Send + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + + + + + Cancel + + + + Chat + Samtale + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + Generelt + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + Bliv venner + + + + Details about your friend : + Oplysninger om din ven: + + + + Key validity: + + + + + Email: + + + + + Options + Indstillinger + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + Peer Detaljer + + + + Name: + Navn: + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Cancel + Annuller + + + Port: + Port: + + + Trust Settings + Trust indstillinger + + + Trust Level + Trust niveau + + + Trust Their Signature + Stol på deres signatur + + + Sign The Certificate + Underskriv certifikatet + + + + OK + OK + + + + Peer Address + Peer Adresse + + + + Name + Navn + + + + Last Contact + Sidste kontakt + + + + Details + Detaljer + + + Peer Details + Peer Detaljer + + + + Peer Info + + + + + Peer ID + + + + + Version + + + + + RetroShare ID + + + + + Status + + + + + Dynamic DNS + + + + + Addresses list + Adresser liste + + + + None + Ingen + + + + Marginal + + + + + Full + Fuld + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Deny Friend + Afvis ven + + + + Make Friend + Bliv venner + + + + Certificate + + + + + + Sign GPG key + + + + + Friend Details + + + + + Loc + + + + + Local Address + Lokale Adresse + + + + External Address + Eksterne Adresse + + + + + Port + + + + + Your trust in this peer is: + Deres tillid i denne peer er: + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + Apply and Close + Anvend og Luk + + + + + RetroShare + RetroShare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + Din nøgle er underskrevet af: + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + Deres tillid i denne peer er ultimative, er det sikkert en nøgle, du ejer. + + + + Your trust in this peer is full. + Deres tillid i denne peer er fuld. + + + + Your trust in this peer is marginal. + Deres tillid i denne peer er marginal. + + + + Your trust in this peer is none. + Deres tillid i denne peer er ingen. + + + + Your trust in this peer is not set. + Deres tillid i denne peer er ikke indstillet. + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + Måske password er forkert + + + + Trust + Have tillid til + + + + ConnectDialog + + Peer Details + Peer detaljer + + + Make Friend + Bliv venner + + + Cancel + Afbryd + + + Name: + Navn: + + + + ConnectFriendWizard + + + Connect Friend Wizard + Tilslut ven Guiden + + + + CreateBlog + + + Create new Blog + Opret ny blog + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Ny Blog</span></p></body></html> + + + + Name + Navn + + + + Description + Beskrivelse + + + + Type: + Type: + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + Tilladt beskeder + + + + Authemticated Messages + Godkendt Beskeder + + + + Anonymous Messages + Anonym Beskeder + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + Annuller + + + + Create + Opret + + + + RetroShare + RetroShare + + + + Please add a Name + Du tilføje et navn + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + Emne: + + + + Html Editor + + + + Attachments + Vedhæftede filer + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + Formindsk skriftstørrelse + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + Add Extra File + Tilføj ekstra fil + + + + RetroShare + RetroShare + + + + Please add a Subject + + + + + &File + &Filer + + + + &New + + + + + &Open... + &Åbn... + + + + &Save + &Gem + + + + Save &As... + Gem &som.. + + + + &Print... + &Udskriv... + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + &Afslut + + + + &Edit + &Rediger + + + + &Undo + &Fortryd + + + + &Redo + + + + + Cu&t + + + + + &Copy + &Kopier + + + + &Paste + &Indsæt + + + + &View + &Vis + + + + &Insert + &Indsæt + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + Åbn fil... + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + Gem som... + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + Udskriv dokument + + + + Export PDF + + + + + Choose Image + Vælg Billede + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Billedfiler understøttes (*.png *.jpeg *.jpg *.gif) + + + + CreateChannel + + + Create a new Channel + Opret en ny kanal + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + Navn + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + Beskrivelse + + + + Type: + Type: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + Tilladt beskeder + + + + Anonymous Messages + Anonym Beskeder + + + + Authenticated Messages + + + + Authemticated Messages + Godkendt Beskeder + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + + + + + Create + Opret + + + + RetroShare + RetroShare + + + + Please add a Name + Du tilføje et navn + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + Emne: + + + + + Attachments + Vedhæftede filer + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + Tilføj ekstra fil + + + + + RetroShare + RetroShare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Navn + + + + Type: + Type: + + + + Authenticated Messages + + + + + Cancel + Annuller + + + RetroShare + RetroShare + + + + Please add a Name + Du tilføje et navn + + + + Create new Forum + Opret nyt forum + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Nye forum</span></p></body></html> + + + + Description + Beskrivelse + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + Tilladt beskeder + + + Authemticated Messages + Godkendt Beskeder + + + + Anonymous Messages + Anonym Beskeder + + + + Create + Opret + + + + CreateForumMsg + + + Close + Luk + + + + Post Forum Message + + + + + Forum + + + + Forum Post Subject + Forum Post Emne + + + + Attach File + Vedhæft fil + + + + Forum Post + + + + + Sign Message + + + + + Subject + Om + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + RetroShare + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + Tilføj ekstra fil + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + RetroShare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + Din offentlige nøgle kopieres til Udklipsholder, indsætte og sende det til din ven via email eller på anden måde + + + + Save as... + Gem som... + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare Certificate (*.rsc); Alle filer (*) + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + Kopi Key + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + Gem Key + + + + CryptographyDialog + + RetroShare + RetroShare + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Detaljer + + + + + General + Generelt + + + + File Name: + Filnavn: + + + + Hash: + + + + + Size: + Størrelse + + + + Status: + + + + Priority + Prioritet + + + + Priority: + + + + + Type: + Type: + + + + Transfer + Overførsel + + + + Sources: + Kilder: + + + + Datarate: + Hastighed: + + + + Completed: + Faerdiggjort: + + + + Chunk size: + Chunk Størrelse: + + + + + Number of Chunks + Antal stykker + + + + Chunks: + + + + + Remaining: + Tilbage: + + + + Date + Dato + + + + Download time: + Download tid: + + + + + Comments + Kommentarer + + + + + retroshare link(s) + + + + + Copy + Kopier + + + + OK + O.k. + + + + Cancel + Annuller + + + + Rating + Bewertung + + + + File Name + Filnavn + + + + Not Rated + + + + + No Comments + + + + + DirectoriesPage + + Add a Share Directory + Tilføj en Del Directory + + + Remove Shared Directory + Fjern Delt Directory + + + + + Browse + Gennemse + + + Add Shared Directory + Tilføj Delt Directory + + + + Set Incoming Directory + Sæt Indgående Directory + + + + Set Partials Directory + Sæt Partials Directory + + + + Incoming Directory + Indgående filer + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + Partials Direcrtory + Partials filer + + + + Shared Directories + Delte Mapper + + + Automatically share incoming directory (Recommanded) + Automatisk aksjer indgående bibliotek (anbefalet) + + + + Edit Share + Rediger aksjer + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + Luk + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + Forum Detaljer + + + + Cancel + + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + Forum navn + + + + Forum Description + Forum Beskrivelse + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + Trust Level + Trust niveau + + + + Peer Address + Peer adresse + + + + Last Contact + Sidste kontakt + + + + Organisation + Organisation + + + + Location + Lokation + + + + Country + Land + + + + Auth Code + Auth Kode + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + + + # + + + + + Status + + + + + Person + + + + + Auto Connect + + + + + Person Id + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + &Rediger + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileTransferInfoWidget + + Chunk map: + Chunk kort: + + + Active chunks: + Aktiv stykker: + + + Availability map ( + Tilgængelighed kort ( + + + active sources + aktive kilder + + + File info: + Fil info: + + + File hash: + Fil hash: + + + File size: + Fil størrelse: + + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + Tilbage + + + + Number of sources + + + + + Chunk strategy + Chunk strategi + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + Chunk size: + Chunk størrelse: + + + Number of chunks: + Antal stykker: + + + Transfered: + Overført: + + + Number of sources: + Antal kilder: + + + Chunk strategy: + Chunk strategi: + + + + FindWindow + + Size + Størrelse + + + + FlatStyle_RDM + + + Friends Directories + Venner mapper + + + + My Directories + Min mapper + + + + Size + Størrelse + + + + Age + Alder + + + + Friend + + + + + Share Type + Del Type + + + + Directory + Mapper + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + Forum Detaljer + + + + Forum Info + + + + + Forum Name + Forum navn + + + + Popularity + Popularitet + + + + Last Post + Sidste indlæg + + + + Forum ID + + + + + Forum Description + Forum Beskrivelse + + + + Security + Sikkerhed + + + + Allowed Messages + Tilladt beskeder + + + + Authemticated Messages + Godkendt Beskeder + + + + Anonymous Messages + Anonym Beskeder + + + + Cancel + Annuller + + + + OK + OK + + + + Apply and Close + Anvend og Luk + + + + ForumMsgItem + + + Remove Item + + + + Forum Name + Forum navn + + + + Expand + udvide + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + Svar + + + + Send + + + + + Signed + Underskrevet + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + Anonym + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + Abonner på forum + + + + Expand + udvide + + + + Forum Description + Forum Beskrivelse + + + + ForumPage + + + Misc + + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + Abonner på forum + + + + Unsubscribe to Forum + Afmeld til Forum + + + + New Forum + Nye Forum + + + + Show Forum Details + Vis Forum detaljer + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + Svar + + + + Reply to Author + Svar til forfatter + + + + Expand all + Udvid alle + + + + Collapse all + Skjul alle + + + + AUTHD + + + + Popularity: + Popularitet: + + + + Your Forums + Din Forums + + + + Subscribed Forums + Abonnerede Forums + + + + Popular Forums + Populære Forums + + + + Other Forums + Andre Forums + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + Skjul + + + + Expand + udvide + + + Anonymous + Anonym + + + signed + underskrevet + + + none + ingen + + + + + RetroShare + RetroShare + + + + No Forum Selected! + Ikke Forum Udvalgte! + + + + You cant reply a Anonymous Author + Du kan ikke besvare en Anonym Author + + + + + Date + Dato + + + + + Title + Titel + + + + + Start New Thread + Start ny tråd + + + New Message + Ny besked + + + Add + Tilføj + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start new Thread for Selected Forum</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start ny tråd for udvalgte Forum</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reply Message</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Svar Message</p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + Last Post + Sidste indlæg + + + + Threaded View + + + + + Flat View + + + + + + Author + Forfatter + + + + Signed + Underskrevet + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tråd:</span></p></body></html> + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + + + + + Content + + + + + Create Forum + Opret Forum + + + + Print + Udskriv + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + Start new Thread for Selected Forum + + + + + Display + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + Udskriftsvisning + + + + ForumsFillThread + + + + Anonymous + Anonym + + + + + signed + underskrevet + + + + + none + ingen + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Venner</span></p></body></html> + + + + Add + Tilføj + + + + Display + + + + + Friends + Venner + + + + Status + + + + + Add or Change your Avatar + Tilføje eller ændre din avatar + + + + Edit Personal message + Rediger Personlig hilsen + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + Vedhæft fil + + + + Send + + + + + Clear Chat History + Ryd Chatoversigt + + + + + Add Friend + Tilføj ven + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + Opret ny kanal + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + Profil + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + Mig + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + Lokation + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + Samtale + + + + Message Friend + Besked ven + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + Tilslut til ven + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + Afvis ven + + + + Remove Friend Location + Fjern kollega Beliggenhed + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + Udvid alle + + + + Collapse all + Skjul alle + + + + location + + + + + + Available + + + + + Save Certificate + Gem certifikat + + + + Certificates (*.pqi) + + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + Tilføj ekstra fil + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + Gem som... + + + + Text File (*.txt );;All Files (*) + + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Accept + Acceptér + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + + + + + Status + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + Slet + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + + + + + Certificates (*.pqi *.pem) + Certifikater (*.pqi *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + Navn + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + Lokation + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + + GeneralMsgDialog + + Add Extra File + Tilføj ekstra fil + + + Attachments + Vedhæftede filer + + + Subject : + Emne: + + + + GeneralPage + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + + + + + + + %1 KB/s + + + + + Sent: + + + + + %1 KB + + + + + %1 MB + + + + + %1 GB + + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Venner + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + Titel + + + + Description + Beskrivelse + + + + Reset + + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + Navn + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + Dato + + + + Size + Størrelse + + + + Popularity + Popularitet + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + Close + Luk + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + + Search + Søg + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Home + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + Om + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + + + + + + Copy + Kopier + + + + Remove + Fjerne + + + + Mark all + + + + + Delete + Slet + + + + Clear history + + + + + Send + + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + InviteDialog + + Done + Færdig + + + Cancel + Afbryd + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + + + + + Expand + udvide + + + + Hide + Skjul + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + Fra + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Show + Vis + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + MainWindow + + + Network + Netværk + + + + Friends + Venner + + + + + Transfers + Overførsler + + + + + Messages + Beskeder + + + + + Channels + Kanaler + + + + + Options + Indstillinger + + + + Hide + Skjul + + + + Show + Vis + + + + RetroShare + RetroShare + + + + RetroShare %1 a secure decentralised communication platform + + + + + Search + Søg + + + + Files + Filer + + + + Blogs + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Show/Hide + Vis/Skjul + + + + Status + + + + + &Quit + &Afslut + + + + Chat + Samtale + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + You has a new message + Du har en ny besked + + + + Bandwidth Graph + Båndbredde graf + + + + Open Messenger + Åbn Messenger + + + + Internal Error + + + + + Minimize + Minimer + + + + Maximize + Maksimer + + + + Links Cloud + + + + + Unfinished + + + + + Help + Hjælp + + + + + Forums + + + + + + + + You have %1 new messages + + + + + + + + You have %1 new message + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Open Messages + Åbn Beskeder + + + + Applications + Ansøgninger + + + + Plugins + + + + + Really quit ? + Virkelig holde op? + + + + Do you really want to exit RetroShare ? + Vil du virkelig afslutte RetroShare? + + + + Add Friend + Tilføj ven + + + + Add a Friend Wizard + Tilføj en ven guiden + + + + Add Share + Tilføj Del + + + + Quit + Afslut + + + + + Quick Start Wizard + Quick Start Guiden + + + + SMPlayer + + + + + Messenger + + + + + MainWindow + + + + + About + Om + + + + MessageComposer + + + + Compose + Komponér + + + + + Contacts + Kontakter + + + + Search for Name: + + + + + Reset + + + + + Send To: + Send til: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + Skriftstørrelse + + + + Increase font size + Forøg skriftstørrelse + + + + Decrease font size + Formindsk skriftstørrelse + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + Vælg farve + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + Anbefalede filer + + + + File Name + Filnavn + + + + Size + Størrelse + + + Sources + Kilder + + + + Hash + + + + + Send + + + + + Send this message now + Send denne besked nu + + + + Reply + Svar + + + + Toggle Contacts View + Toggle Kontakter View + + + + Save + Gemme + + + + Save this message + Gem denne besked + + + + Attach + Vedhæft + + + + Attach File + Vedhæft fil + + + + Quote + Citat + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + Gem besked + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + Compose: + Komponér: + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + RetroShare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + Ukendt + + + + Unknown friend + + + + + &File + &Filer + + + + &New + + + + + &Open... + &Åbn... + + + + &Save + &Gem + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + &Udskriv... + + + + &Export PDF... + + + + + &Quit + &Afslut + + + + &Edit + &Rediger + + + + &Undo + &Fortryd + + + + &Redo + + + + + Cu&t + + + + + &Copy + &Kopier + + + + &Paste + &Indsæt + + + + &View + &Vis + + + + &Contacts Sidebar + + + + + &Insert + &Indsæt + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + Åbn fil... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + Gem som... + + + + Print Document + Udskriv dokument + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + Beskeden er ikke blevet sendt. +Ønsker du at gemme beskeden? + + + + Choose Image + Vælg Billede + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Billedfiler understøttes (*.png *.jpeg *.jpg *.gif) + + + + Add Extra File + Tilføj ekstra fil + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + Tilføj + + + + Edit + + + + + Delete + Slet + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + besked + + + New Message + Ny besked + + + + Subject + Om + + + + <b>1 new Message from</b> + + + + + Close + Luk + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Anbefalet filer</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + Fra: + + + + To: + Til: + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + Filnavn + + + + Size + Størrelse + + + + Hash + + + + + Print + Udskriv + + + + Print Preview + Udskriftsvisning + + + + No subject + + + + + Download + + + + + Download all + + + + + Hide + Skjul + + + + Expand + udvide + + + + File + + + + + Files + Filer + + + + Print Document + Udskriv dokument + + + + Save as... + Gem som... + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + Ny besked + + + + Compose + Komponér + + + + Reply to selected message + + + + + Reply + Svar + + + + Reply all to selected message + + + + + Reply all + Svar alle + + + + Forward selected message + + + + + Foward + Videresend + + + + Remove selected message + + + + + Delete + Slet + + + + Print selected message + + + + + + Print + Udskriv + + + + Display + + + + + + + Tags + + + + + Print Preview + Udskriftsvisning + + + + + Buttons Icon Only + Knapper Icon Kun + + + + Buttons Text Beside Icon + Knapper Tekst Udover Icon + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + &Filer + + + + Save &As File + + + + + &Print... + &Udskriv... + + + + Print Preview... + + + + + &Quit + &Afslut + + + + MessagesDialog + + + + New Message + Ny besked + + + + Quick View + + + + + Reply to Message + Besvar Besked + + + + Remove Message + Fjern Besked + + + + + Date + Dato + + + + + + From + Fra + + + Size + Størrelse + + + Download All + Hent alle + + + Print Document + Udskriv dokument + + + + Forward selected Message + Frem udvalgte Besked + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + Fjern Besked + + + + Forward Message + Videresend meddelelse + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + + Empty trash + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + Click to sort by to + + + + Files + Filer + + + Compose: + Komponér: + + + Hide + Skjul + + + Expand + udvide + + + + + + Drafts + + + + + To + + + + Anonymous + Anonym + + + Save as... + Gem som... + + + + + + + + Total: + + + + + + Reply to All + Svar til alle + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nyt brev</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">svar til udvalgte besked</p></body></html> + + + + Reply + Svar + + + + Reply all + Svar alle + + + + Foward + Videresend + + + + Delete + Slet + + + + Compose + Komponér + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + + + + Inbox + Indbakke + + + + + + + Outbox + Udbakke + + + + Draft + Udkast til + + + + + Sent + Sendte + + + + + Subject + Om + + + + Reset + + + + + Attachments + Vedhæftede filer + + + Subject: + Om: + + + From: + Fra: + + + Date: + Dato: + + + To: + Til: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Anbefalet filer</span></p></body></html> + + + + + Content + + + + + + + + + Tags + + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download alle Anbefalet Filer</p></body></html> + + + File Name + Filnavn + + + Sources + Kilder + + + + + Print... + Udskriv... + + + + Print Preview + Udskriftsvisning + + + + + Buttons Icon Only + Knapper Icon Kun + + + + Buttons Text Beside Icon + Knapper Tekst Udover Icon + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + Gem som... + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">fjerne valgte meddelelse</p></body></html> + + + + Print + Udskriv + + + + MessagesPopupDialog + + New Message + Ny besked + + + Download All + Hent alle + + + From + Fra + + + Date + Dato + + + Size + Størrelse + + + Compose + Komponér + + + Messages + Beskeder + + + Reply + Svar + + + Remove + Fjerne + + + Print + Udskriv + + + PrintPreview + Udskriftsvisning + + + + MessengerDirModel + + Size + Størrelse + + + Rank + Placering + + + + MessengerWindow + + + Expand all + Udvid alle + + + + Collapse all + Skjul alle + + + + Chat + Samtale + + + + Message Friend + Besked ven + + + + Connect To Friend + Tilslut til ven + + + + Peer Details + Peer Detaljer + + + + Recomend this Friend to... + + + + + Paste RetroShare Link + + + + + Export Friend + + + + + Deny Friend + Afvis ven + + + + Remove Friend Location + Fjern kollega Beliggenhed + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + location : + Beliggenhed: + + + + Save Certificate + Gem certifikat + + + + Certificates (*.pqi) + + + + Friend Not Online + Ven ikke online + + + + Click to Change your Avatar + Tilføje eller ændre din avatar + + + + Search Friends + + + + + Reset + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + Indbakke + + + Outbox + Udbakke + + + Sent + Sendte + + + All + Alle + + + Date + Dato + + + Subject + Om + + + + MsgItem + + + Remove Item + + + + + + Expand + udvide + + + + Reply to Message + Besvar Besked + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Skjul + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + + + Date + Dato + + + Rank + Placering + + + From + Fra + + + Title + Titel + + + Msg + Msg + + + Count + Antal + + + Size + Størrelse + + + Type + Type + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + Delete Channel + Slet kanal + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + + + Date + Dato + + + Rank + Placering + + + From + Fra + + + Title + Titel + + + Msg + Msg + + + Count + Antal + + + Size + Størrelse + + + Type + Type + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + Hent certifikat + + + Select a pem/pqi File + Vælg en pem/pqi fil + + + File Not Found + Fil ikke fundet + + + %1 does not exist. Would you like to create it? + %1 findes ikke. Vil du oprette den? + + + Failed to Create File + Kunne ikke oprette fil + + + Unable to create %1 [%2] + Kunne ikke oprette %1 [%2] + + + + Copy RetroShare Link + + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + Har bekræftet mig + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + Select Certificate + Vælg certifikat + + + Certificates (*.pqi *.pem) + Certifikater (*.pqi *.pem) + + + Accept + Acceptér + + + Trust + Trust + + + Last Contact + Sidste kontakt + + + + + + Name + Navn + + + Peer Address + Peer adresse + + + Organisation + Organisation + + + Location + Lokation + + + Country + Land + + + + + Cert Id + Cert Id + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + Afvis ven + + + + Make friend + Gør ven + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + Peer Detaljer + + + Authenticated + Godkendt + + + Not Authenticated + Ikke godkendt + + + + Unknown + Ukendt + + + + yourself + + + + RetroShare + RetroShare + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare Certificate (*.rsc); Alle filer (*) + + + + Network + Netværk + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + + Did peer authenticated me + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Netværk:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + Show keys that are not validated by the GPG web of trust + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Search Network + + + + + Clear Filter + + + + + Peer ID + + + + + Network Status + Netværk Status + + + + Local network + Lokale netværk + + + + UPnP + + + + + External ip address finder + Eksterne ip-adresse søg + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + Tilføj ven + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkView + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Venner + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + Navn: + + + + Choose color + + + + + OK + + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Fjern alle + + + + Options + Indstillinger + + + + NotifyDialog + + Chat + Samtale + + + New Message + Ny besked + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + Kanaler + + + + Forums + + + + + Chat + Samtale + + + + Blogs + + + + + Messages + Beskeder + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + Ny besked + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + OptionsDlg + + Cancel + Afbryd + + + + PeerDefs + + Anonymous + Anonym + + + + + Unknown + Ukendt + + + + PeerItem + + Make Friend + Bliv venner + + + + Chat + Samtale + + + + Start Chat + + + + Organisation + Organisation + + + + Location + Lokation + + + Country + Land + + + + Remove Item + + + + + + Expand + udvide + + + + Write a quick Message + + + + + Send + + + + + Cancel + + + + + Peer ID: + + + + + Write Message + + + + + Status: + + + + + Trust: + + + + + Name: + Navn: + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + Skjul + + + + Quick Message + + + + + PeerStatus + + Online: 0 | Friends: 0 | Network: 0 + Online: 0 | Venner: 0 | Netværk: 0 + + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Venner + + + Friends: + Venner: + + + + PeersDialog + + Chat + Samtale + + + me + Mig + + + location : + Beliggenhed: + + + Save Certificate + Gem certifikat + + + Connect To Friend + Tilslut til ven + + + Profile + Profil + + + Expand all + Udvid alle + + + Collapse all + Skjul alle + + + Message Friend + Besked ven + + + Peer Details + Peer Detaljer + + + Deny Friend + Afvis ven + + + Remove Friend Location + Fjern kollega Beliggenhed + + + Friend Not Online + Ven ikke online + + + RetroShare + RetroShare + + + Create a new Channel + Opret en ny kanal + + + New Channel + Ny kanal + + + Add Extra File + Tilføj ekstra fil + + + Location + Lokation + + + Save as... + Gem som... + + + Send + Sende + + + Profile View + Profil Vis + + + Add + Tilføj + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Venner</span></p></body></html> + + + hide unconnected + skjul uvedkommende + + + Add or Change your Avatar + Tilføje eller ændre din avatar + + + Edit Personal message + Rediger Personlig hilsen + + + Create New Forum + Opret ny Forum + + + Create new Forum + Opret ny Forum + + + Create New Channel + Opret ny kanal + + + Create new Channel + Opret ny kanal + + + Add Friend + Tilføj ven + + + Friends + Venner + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">set Text Color</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">sæt Tekstfarve</span></p></body></html> + + + Attach File + Vedhæft fil + + + Clear Chat History + Ryd Chatoversigt + + + + PeersFeed + + Friends + Venner + + + Save Certificate + Gem certifikat + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Fjerne + + + + Excellent + + + + + Good + + + + + Average + Gennemsnit + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + Bewertung + + + + + Date + Dato + + + + + Location + Lokation + + + + Size + Størrelse + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + Beskrivelse + + + + PhotoShow + + + Date: + Dato: + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + Fjerne + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + Popularitet + + + + PopupChatDialog + + Friend Not Online + Ven ikke online + + + RetroShare + RetroShare + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + Gem som... + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + Send + + + + Close + Luk + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + Ryd Chatoversigt + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + Tilføj ekstra fil + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + RetroShare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Cancel + Afbryd + + + OK + O.k. + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + Udskriv + + + + &Print... + &Udskriv... + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + Profil + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + Hent alle + + + + RetroShare + RetroShare + + + + Error : cannot get peer details. + + + + + + Name + Navn + + + + Peer ID + + + + + Size + Størrelse + + + + Profile View + Profil Vis + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + Rediger Personlig hilsen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Offentlig Information</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Offentlig Information</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Navn:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Beliggenhed:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Andre oplysninger</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Antal Venner:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Min Adresse</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Lokal Adresse:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Eksterne Adresse:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + Addresses list + Adresser liste + + + + QObject + + Name + Navn + + + Date + Dato + + + Size + Størrelse + + + Popularity + Popularitet + + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + Log ind Manglende + + + + Maybe password is wrong + Måske password er forkert + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + Afvis ven + + + + Make friend + Gør ven + + + + Peer details + Peer Detaljer + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + Quick Start Guiden + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + Næste > + + + + + + + Exit + Afslut + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + For den bedste ydeevne, skal RetroShare at vide lidt om din forbindelse til internettet. + + + + Choose your upload speed limit: + Vælg din upload hastighed grænse: + + + + + KB/s + + + + + Choose your download speed limit: + Vælg din download hastighed grænse: + + + + Connection : + Tilslutning : + + + + Automatic (UPnP) + Automatisk (UPnP) + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + < Tilbage + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + Mapper + + + + Network Wide + Netværk Wide + + + + Browseable + + + + + Add + Tilføj + + + + Remove + Fjerne + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Nyd bruger RetroShare!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + Start Minimeret + + + + Start RetroShare when my System Starts. + Start RetroShare når min System Starter. + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + Vælg en mappe Share + + + + Shared Directory Added! + Delt Directory tilføjet! + + + + Do you really want to stop sharing this directory ? + Vil du virkelig ønsker at holde op med at dele denne mappe? + + + + Warning! + + + + + RSettingsWin + + + General + Generelt + + + + Directories + Mapper + + + + Server + + + + + Transfer + Overførsel + + + + Notify + Advisér + + + + Security + Sikkerhed + + + + Message + + + + + Forum + + + + + Chat + Samtale + + + + Appearance + Udseende + + + File Associations + Filassociationer + + + + Sound + Lyd + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Fejl Lagring Configuration + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>Ned:</strong> 0.00 (kB/s) | <strong>Op:</strong> 0.00 (kB/s) + + + + <strong>Down:</strong> + <strong>Ned:</strong> + + + + <strong>Up:</strong> + <strong>Op:</strong> + + + Down: + Ned: + + + Up: + Op: + + + + RemoteDirModel + + Friends Directories + Venner mapper + + + My Directories + Min mapper + + + Size + Størrelse + + + Share Type + Del Type + + + Rank + Placering + + + Age + Alder + + + Anonymous + Anonym + + + Files + Filer + + + + RetroshareDirModel + + + Anonymous + Anonym + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + + + + + Invalid GUI style specified: + + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + + Download + + + + Recommend to Friends + Anbefal til venner + + + + Remove + Fjerne + + + + Remove All + Fjern alle + + + + Download Notice + Download meddelelse + + + + Enter a keyword here (at least 3 char long) + + + + Copy retroshare Link + Kopier retroshare Link + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + + Folder + Mappe + + + + New RetroShare Link(s) + + + + + Size + Størrelse + + + + Type + Type + + + + Any + Enhver + + + + Archive + Arkiv + + + + Audio + + + + + CD-Image + + + + + Document + Dokument + + + + Picture + Billede + + + + Program + + + + + Video + + + + + Directory + Mapper + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + Filnavn + + + + File Size + + + + + Close all Search Resullts + + + + + Download Selected + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enter a Keyword here</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Indtast et søgeord her</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Close all Search Resullts</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Close all Search Resullts</span></p></body></html> + + + + Close All Search Results + + + + Clear all Search Results + Ryd alle Søgeresultater + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Download Selected</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Download udvalgte</span></p></body></html> + + + + Include files from your own file list in the search result + Inkluder filer fra din egen fil listen i søgeresultatet + + + + Include own files + Omfatter egne filer + + + + Search inside "browsable" files of your friends + Søg Til indenfor "søgbar" filer AF spise Venner + + + + Search in friends lists + Søg i vennelister + + + + Multi-hop search at distance 6 in the network +(always reports available files) + Multi-hop søgning på afstand 6 i nettet +(Altid rapporter tilgængelige filer)s) + + + + F2F search + F2F søgning + + + + Limit number of results to : + Begræns antallet af resultater til: + + + + Filename + Filnavn + + + + Start Search + Start søgning + + + + Search + Søg + + + + Reset + + + + + Enter a Keyword here + + + + + Advanced Search + Avanceret søgning + + + + Advanced + Avanceret + + + + Sources + Kilder + + + + Age + Alder + + + + Hash + + + + + KeyWords + Nøgleords + + + + Results + Resultater + + + + Search Id + + + + + SendLinkDialog + + Send + Send + + + + ServerDialog + + Port: + Port: + + + + ServerPage + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + Should be disabled if you don't want to share connection information between peers. + Skal deaktiveres, hvis du ikke vil dele forbindelsen oplysninger mellem ligemænd. + + + Discovery Enabled + Discovery aktiveret + + + Discovery Disabled + Discovery handicappede + + + + Transfer Rates + Overførsel Hastighed + + + + Download (KB/s) + + + + + + kB/s + + + + + Upload (KB/s) + + + + + + Network Configuration + Netværkskonfiguration + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + Hvis du unckeck dette, vil RetroShare ikke bruge tunnel-forbindelse mellem peers, der er firewalled og kan ikke forbinde direkte. Dette er uafhængig af F2F routing (skildpadde router). + + + + Allow Tunnel Connection + Tillad Tunnel forbindelse + + + + Local Address + Lokale Adresse + + + + External Address + Eksterne Adresse + + + + Dynamic DNS + + + + + + Port: + Port: + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + Hvis du unckeck dette, kan RetroShare kun bestemme din IP +når du opretter forbindelse til nogen. Overlades denne kontrol hjælper +tilslutning, når du har få venner. Det hjælper også, hvis du er +bag en firewall eller en VPN. + + + + Allow RetroShare to ask my ip to these websites: + Tillad RetroShare at bede min ip til disse hjemmesider: + + + Forwarded External Port + Vidresendte ekstern port + + + + Settings + + + Options + Indstillinger + + + + General + Generelt + + + + Server + + + + + Transfer + Overførsel + + + + Directories + Mapper + + + + Notify + Advisér + + + + Security + Sikkerhed + + + + Message + + + + + Forum + + + + + Chat + Samtale + + + + Appearance + Udseende + + + + Sound + Lyd + + + + Cancel + Annuller + + + Apply + Anvend + + + + OK + O.k. + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + Gennemse + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + Eksempelprocent + + + + Anonymous shared Network Wide + + + + + Network Wide + Netværk Wide + + + Anonymous + Anonym + + + + Browseable by Friends + + + + Friends + Venner + + + + OK + + + + + Cancel + + + + + Select A Folder To Share + Vælg en mappe Share + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + RetroShare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + Tilføj en Del Directory + + + + Stop sharing selected Directory + Stop deling udvalgte Directory + + + Select A Folder To Share + Vælg en mappe Share + + + Do you really want to stop sharing this directory ? + Vil du virkelig ønsker at holde op med at dele denne mappe? + + + + + Remove + Fjerne + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + Shared Directory Added! + Delt Directory tilføjet! + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + Shared Folder Manager + Delt Mappeadministration + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + Mapper + + + + Virtual Folder + + + + + Network Wide + Netværk Wide + + + + Browsable + Eksempelprocent + + + + Add + Tilføj + + + + Close + Luk + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + + + + + Checking... + Kontrol ... + + + + Check files + Check-filer + + + + Copy retroshare Link + Kopier retroshare Link + + + + Send retroshare Link + + + + Recommend (Automated message) To + Anbefal (Automated besked) At + + + Recommend in a message to + Anbefal en besked til + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + Åben fil + + + + Open Folder + Åben mappe + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + Sæt kommando for åbning af denne fil + + + + <strong>My Shared Files</strong> + <strong>Min Delte filer</strong> + + + + <strong>Friends Files</strong> + <strong>Venner Filer</strong> + + + + <strong>Files</strong> + <strong>Filer</strong> + + + + Splitted View + Opsplittes View + + + + Friends Folders + Venner mapper + + + + My Folders + Mine mapper + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Filer</span></p></body></html> + + + + All + Alle + + + + One day old + En dag gammel + + + + One Week old + En uge gammel + + + + One month old + En måned gammel + + + + Search files + + + + + Start Search + Start søgning + + + + Reset + + + + + Tree view + + + + + Flat view + + + + + Download selected + Download udvalgte + + + + check files + Check-filer + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + Gennemse + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + RetroShare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Log ind</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + Log ind + + + + Remember Password + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Create new Profile...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Opret ny profil ...</span></a></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + Name (GPG Id) - location: + Navn (GPG Id) - placering: + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + Log ind Manglende + + + + Maybe password is wrong + Måske password er forkert + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + Create a New Profil + Opret en ny Profil + + + This will generate a new Profile + Are you sure you want to continue + Dette vil generere en ny profil + Er du sikker på du vil fortsætte + + + + StatisticDialog + + + + Show Settings + + + + + Cancel + Afbryd + + + + Hide Settings + + + + + %1 days + + + + + Statistics + + + + + Now + + + + + Transfer + Overførsel + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Download + + + + + Session: + + + + + + Downloaded: + + + + + + Count of Downloads: + + + + + + + Overall + + + + + Upload + + + + + + + Session + + + + + Uploaded: + + + + + + Count of Uploads: + + + + + Uploaded + + + + + + + + Connections: + + + + + + + Peers: + + + + + Time Statistics + + + + + + Uptime + + + + + Since: + + + + + Cumulative + + + + + Records + + + + + Uploadspeed: + + + + + Downloadspeed: + + + + + Uptime: + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always On Top + + + + + 100 + + + + + % Opaque + + + + + Changes the transparency of the Bandwidth Graph + + + + + Save + Gemme + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + Personlig besked + + + + Status message + Status besked + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personlig besked</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Indtast din status besked</span></p></body></html> + + + + OK + OK + + + + Cancel + Annuller + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Type + + + + Delete FeedItem + + + + + SubFileItem + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + File Name + Filnavn + + + + Download + + + + + Play + Lege + + + + %p Kb + + + + Expand + udvide + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + Brug tekst repræsentation af PGP certifikater. + + + + The text below is your PGP certificate. You have to provide it to your friend + Teksten nedenfor er din PGP-certifikat. Du er nødt til at give den til din ven + + + + Please, paste your friends PGP certificate into the box below + Please, indsæt dine venner PGP certifikat i boksen nedenfor + + + Your Cert is copied to Clipboard, paste and send it to yourfriend via email or some other way + Din Cert er kopieret til klippebordet, indsætte og sende det til din ven via email eller på anden måde + + + + You can copy this text and send it to your friend via email or some other way + Du kan kopiere denne tekst og send den til din ven via email eller på anden måde + + + + RetroShare + RetroShare + + + + Text certificate + Tekst certifikat + + + + Copy your Cert to Clipboard + Kopier Cert til klippebordet + + + + Save your Cert into a File + Gem Cert i en fil + + + + Run Email program + Kør E-mail-program + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + Connect Ven Hjælp + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + Gem som... + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare Certificate (*.rsc); Alle filer (*) + + + + Certificate Load Failed + Certifikat indlæsning fejlede + + + + TransferPage + + + Transfer options + Transfer Indstillinger + + + + Queue Size: + Kø Størrelse: + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Annuller + + + + Clear Completed + Fjern faerdige + + + + + Status + + + + + Completed + Faerdiggjort + + + + + Name + i.e: file name + Navn + + + + + Size + i.e: file size + Størrelse + + + + Speed + i.e: Download speed + Hastighed + + + + Progress / Availability + i.e: % downloaded + Fremgang + + + + Sources + i.e: Sources + Kilder + + + + Core-ID + + + + + Peer + i.e: user name + + + + + Progress + i.e: % uploaded + Fremgang + + + + Speed + i.e: upload speed + Hastighed + + + + Transferred + Overført + + + + Hash + + + + + Router Statistics + + + + + Router Requests + + + + + Force Check + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + Play + Lege + + + + Pause + + + + + Resume + Fortsæt + + + + Open Folder + Åben mappe + + + + Open File + Åben fil + + + + Preview File + Preview fil + + + + Details... + Detaljer + + + Copy retroshare Link + Kopier retroshare Link + + + + + Slower + Langsommere + + + + + + Average + Gennemsnit + + + + + Faster + Hurtigere + + + + Remaining + Tilbage + + + + Download time + i.e: Estimated Time of Arrival / Time left + Download tid + + + + Move in Queue... + Bevæger sig i kø ... + + + + Streaming + + + + + Random + + + + + Chunk strategy + Chunk strategi + + + + version: + + + + + Queued + + + + + Speed / Queue position + Speed / Kø position + + + + Down + Ned + + + + Up + Op + + + + Top + + + + + Bottom + Bund + + + + Priority (Speed)... + Priority (Hastighed)... + + + + Paused + Standset + + + + Transferring + Overførsel + + + + Checking... + Kontrol ... + + + + RetroShare + RetroShare + + + + Details: + Detaljer: + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + Er du sikker på at du vil annullere og slette disse filer? + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + Show cache transfers + Vis cache overførsler + + + + Uploads + + + + + Selected transfer + Udvalgte overførsel + + + + Done + Færdig + + + + Active + Aktiv + + + + Outstanding + Udestående + + + + + + Failed + Mislykket + + + + + + Okay + OK + + + + + Waiting + Venter + + + + Downloading + + + + + + + + Complete + Komplet + + + + Unknown + Ukendt + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + Filer + + + + File + + + + + + DIR + + + + + Friends Directories + Venner mapper + + + + My Directories + Min mapper + + + + Size + Størrelse + + + + Age + Alder + + + + Friend + + + + + Share Type + Del Type + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + Trust + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + Type + Type + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Size + Størrelse + + + Type + Type + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + O.k. + + + + Cancel + Afbryd + + + + Yes + + + + + No + + + + + Help + Hjælp + + + + Retry + + + + + Show Log + + + + + Show Settings + + + + + Continue + + + + + Quit + Afslut + + + + Browse + Gennemse + + + + misc + + + Unknown + Unknown (size) + Ukendt + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + Ukendt + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Name + Navn + + + diff --git a/retroshare-gui/src/lang/retroshare_de.qm b/retroshare-gui/src/lang/retroshare_de.qm new file mode 100644 index 000000000..93c3cdd2c Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_de.qm differ diff --git a/retroshare-gui/src/lang/retroshare_de.ts b/retroshare-gui/src/lang/retroshare_de.ts new file mode 100644 index 000000000..979a088ee --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_de.ts @@ -0,0 +1,13099 @@ + + + + + AboutDialog + + + About RetroShare + Über + + + + About + Über + + + + close + Schliessen + + + + + About RetroShare %1 + Über RestroShare %1 + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + Viel Spaß ;-) + + + + AddFileAssociationDialog + + + File type(extension): + Datei Typ (Erweiterung): + + + + Use default command + Nutze Standard Befehl + + + + Command + Befehl + + + + RetroShare + + + + + Sorry, can't determine system default command for this file + + Entschuldigung. Konnte kein Standard Programm zum Öffnen finden + + + + + AddLinksDialog + + + + Add Link + Link hinzufügen + + + + Add a new Link + Neuen Link hinzufügen + + + + Title: + Titel: + + + + Url: + URL: + + + + +2 Great! + +2 Super! + + + + +1 Good + +1 Gut + + + + 0 Okay + 0 In Ordnung + + + + -1 Sux + -1 Schrott + + + + -2 Bad Link + -2 Pfui + + + + Add Anonymous Link + Anonyme Verknüpfung hinzufügen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Link zur Verknüpfungs-Wolke hinzufügen</span></p></body></html> + + + + Cancel + Abbrechen + + + + Add Link Failure + Fehle beim Hinzufügen des Links + + + + Missing Link and/or Title + Fehlernder Link oder Titel + + + + AdvancedSearchDialog + + + Add a further search criterion. + Ein weiteres Such-Kriterium hinzufügen. + + + + Cancels the search. + Bricht die Suche ab. + + + + Cancel + Abbrechen + + + + Perform the advanced search. + Die erweiterte Suche durchführen. + + + + Search + Suchen + + + + Search Criteria + Suchkriterien + + + + RetroShare: Advanced Search + Retroshare: Erweiterte Suche + + + + Reset the search criteria. + Suchkriterien zurücksetzen. + + + + AppearancePage + + + Language + Sprache + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wähle die Sprache für RetroShare aus</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Änderungen in der Sprachwahl wirken sich erst nach einem Neustart von Retroshare aus!</p></body></html> + + + + Style + Stil + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wähle die Oberfläche für RetroShare aus</p></body></html> + + + + Style Sheet + + + + + ApplicationWindow + + + + RetroShare + + + + + Statistics + Statistiken + + + + Photo View + Photo-Ansicht + + + + Games Launcher + Spielestarter + + + + Shared Calendars + Verteilter Kalender + + + + Hide + Verbergen + + + + Show + Zeigen + + + + AttachFileItem + + + Form + Formular + + + + %p Kb + %p Kb + + + + Cancel Download + Download abbrechen + + + + BandwidthGraph + + + Since: + Seit: + + + + Hide Settings + Einstellungen verbergen + + + + + Show Settings + Einstellungen anzeigen + + + + RetroShare Bandwidth Usage + Retroshare Bandbreiten Nutzung + + + + Reset + Zurücksetzen + + + + Receive Rate + Empfangsrate + + + + Send Rate + Senderate + + + + Always on Top + Immer im Vordergrund + + + + Style + Stil + + + + Changes the transparency of the Bandwidth Graph + Ändert die Transparenz des Bandbreiten-Graphen + + + + 100 + 100 + + + + % Opaque + % Transparent + + + + Save + Speichern + + + + Cancel + Abbrechen + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + Beliebtheit + + + + Last Post + Letzter Beitrag + + + + Blog ID + + + + + Blog Description + Blog Beschreibung + + + + Cancel + Abbrechen + + + + OK + OK + + + + Close + Schliessen + + + + BlogMsgItem + + + Form + Formular + + + + Remove Item + Eintrag entfernen + + + + Expand + Erweitern + + + + Subject + Betreff + + + + Play Media + Medium abspielen + + + + BlogNewItem + + + Remove Item + Eintrag entfernen + + + + Subscribe to Blog + Blog abonnieren + + + + Expand + Erweitern + + + + Blog Decscription + Blog Beschreibung + + + + BlogsDialog + + + Form + Formular + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + Hinzufügen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + Abbestellen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + Abonnieren + + + + + Create New Blog + Neuen Blog erstellen + + + + Name + Name + + + + ID + ID + + + + Own Blogs + Eigene Blogs + + + + Subscribed Blogs + Abonnierte Blogs + + + + Popular Blogs + Beliebte Blogs + + + + Other Blogs + Andere Blogs + + + + Post to Blog + Blogbeitrag erstellen + + + + Subscribe to Blog + Blog abonnieren + + + + Unsubscribe to Blog + Blog abbestellen + + + + Show Blog Details + Zeige Blog Details + + + + Create a new Blog + Erstelle neuen Blog + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + Popularität: %1 +Abgeholt: %2 +Verfügbar: %3 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + BlogsMsgItem + + + Form + Formular + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + Kanal abbestellen + + + + Comment + Kommentar + + + + Remove Item + Beitrag löschen + + + + + Expand + Erweitern + + + + Comments here + Kommentare hier + + + + Hide + Verbergen + + + + CalDialog + + + Form + Formular + + + + Local Calendars + Lokale Kalender + + + + Shared Calendar List + Liste der gemeinsamen Kalender + + + + Name: + Name: + + + + Location: + Ort: + + + + ... + ... + + + + Status: + Status: + + + + Private + Privat + + + + Public + Öffentlich + + + + Allow List: + Liste "erlaubt": + + + + <Disabled> + <abgeschaltet> + + + + Add + Hinzufügen + + + + Remove + Entfernen + + + + Peer Calendars + Nachbarn-Kalender + + + + Share Details + Verteile Details + + + + CertificatePage + + + Certificate files + Zertifikat-Dateien + + + + Use PGP certificates saved in files. + Nutze in Dateien gespeicherte PGP Zertifikate. + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + Du musst eine Datei mit deinem Zertifikat erstellen und deinem Freund zukommen lassen. Alternativ kannst Du auch eine Datei verwenden, die Du zuvor erstellt hast. + + + + Export my certificate... + Exportiere mein Zertifikat... + + + + Browse + Durchsuchen + + + + Select Certificate + Zertifikat auswählen + + + + Please choose a filename + Bitte wähle einen Dateinamen + + + + + + + RetroShare + + + + + Certificate file successfully created + Zertifikat-Datei erfolgreich erstellt + + + + + Sorry, certificate file creation failed + Zertifikat-Datei konnte nicht erstellt werden + + + + Certificate Load Failed:something is wrong with %1 + Fehler beim Laden des Zertifikats : Etwas stimmt nicht mit %1 + + + + Certificate Load Failed:file %1 not found + Fehler beim Laden des Zertifikats: Datei %1 nicht gefunden + + + + Import friend's certificate... + Importiere Zertifikat eines Freundes... + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + Gib die Datei mit dem Zertifikat ein oder ziehe sie per Drag'n'Drop in das Fenster ziehen + + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare Zertifikat (*.rsc );;Alle Dateien (*) + + + + Sorry, create certificate failed + Zertifikat-Datei konnte nicht erstellt werden + + + + Certificate Load Failed:can't read from file %1 + Fehler beim Laden des Zertifikats: Datei %1 konnte nicht gelesen werden + + + + ChanMsgItem + + + Remove Item + Eintrag entfernen + + + + + Expand + Erweitern + + + + Download + Herunterladen + + + + Toggle Message Read Status + Setze Gelesen-Status des Beitrages + + + + Play + Abspielen + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Toggle Message Read Status</p></body></html> + Gelesen Status umschalten + + + + New + Neu + + + + Unsubscribe From Channel + Kanal abbestellen + + + Go to Channel Message + Gehe zum Kanalbeitrag + + + + Copy RetroShare Link + Kopiere RetroShare Link + + + + Channel Feed + Kanal + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Verbergen + + + + ChanNewItem + + + Remove Item + Eintrag entfernen + + + + Subscribe to Channel + Kanal abonnieren + + + Go to Channel + Gehe zum Kanal + + + + Unknown Channel + Unbekannter Kanal + + + + New Channel + Neuer Kanal + + + + Updated Channel + Geänderter Kanal + + + + Expand + Erweitern + + + + Channel Decscription + Kanalbeschreibung + + + + ChannelDetails + + + + Channel Details + Kanal-Details + + + + Channel Info + Kanal Info + + + + Popularity + Beliebtheit + + + + Last Post + Letzter Post + + + + Channel Description + Kanal Beschreibung + + + + Type + Typ + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Beschränkt - Jeder kann lesen, aber nicht jeder schreiben (Privater Veröffentlichungs-Schlüssel) + + + + Private - (Private Publish Key required to view Messages) + Privat - (Privater Veröffentlichungsschlüssel erforderlich, um Nachrichten zu lesen) + + + + Cancel + Abbrechen + + + + OK + OK + + + + Close + Schliessen + + + + Channel Name + Kanal-Name + + + + Channel ID + Kanal ID + + + + ChannelFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Kanäle</span></p></body></html> + + + Add + Hinzufügen + + + + Display + Anzeige + + + + Set all to read + Alle als gelesen markieren + + + + Enable Auto-download + Aktiviere Auto-Download + + + + Create Channel + Kanal erstellen + + + + Unsubscribe + Abbestellen + + + + Subscribe To Channel + Kanal abonnieren + + + + Subscribe + Abonnieren + + + + Unsubcribe To Channel + Kanal abbestellen + + + + Own Channels + Meine Kanäle + + + + Subscribed Channels + Abonnierte Kanäle + + + + Popular Channels + Beliebte Kanäle + + + + Other Channels + Andere Kanäle + + + + + Post to Channel + Kanalbeitrag erstellen + + + + Subscribe to Channel + Kanal abonnieren + + + + Unsubscribe to Channel + Kanal abbestellen + + + + Show Channel Details + Zeige Kanal-Details + + + + Restore Publish Rights for Channel + + + + + Share Channel + Verteile Kanal + + + + Copy RetroShare Link + Kopiere RetroShare Link + + + + No Channel Selected + Keinen Kanal gewählt + + + + Disable Auto-Download + Deaktiviere Auto-Download + + + + Enable Auto-Download + Aktiviere Auto-Download + + + + Edit Channel Details + Kanal-Details bearbeiten + + + + ChatMsgItem + + + Remove Item + Eintrag entfernen + + + + Send Mail + Nachricht senden + + + + Write Message + Nachricht schreiben + + + + + Start Chat + Chat starten + + + + Write a quick Message + Schnelle Nachricht schreiben + + + + Send + Senden + + + + Cancel + Abbrechen + + + + Quick Message + Schnelle Nachrricht + + + + ChatPage + + + Chat Settings + Chat Einstellungen + + + + Enable Emoticons Privat Chat + Emoticons für privaten Chat + + + + Chat Font + Chat Schriftart + + + + Change Chat Font + Wähle Chat Schriftart + + + + Chat Font: + Chat Schriftart: + + + + Enable Emoticons Group Chat + Emoticons für Gruppenchat + + + + Chat History + Chat History + + + + Load number of messages (0 = off) + Lade Anzahl von Nachrichten (0 = aus) + + + + Group Chat + Gruppenchat + + + + Private Chat + Privater Chat + + + + Group chat + Gruppenchat + + + + Private chat + Privater Chat + + + + General + Allgemein + + + + Enable Group Chat History + Chat Verlauf für Gruppenchat + + + + Send message with Ctrl+Return + Sende Nachricht mit Strg+Enter + + + + Enable Private Chat History + Chat Verlauf für privaten Chat + + + + Style + Stil + + + + + + Variant + Variante + + + + + + Author: + Autor: + + + + + + Description: + Beschreibung: + + + + History + Verlauf + + + + Incoming message in history + Eingehehende Nachricht aus dem Verlauf + + + + Outgoing message in history + Ausgehende Nachricht aus dem Verlauf + + + + Incoming message + Eingehehende Nachricht + + + + Outgoing message + Ausgehehende Nachricht + + + + Outgoing offline message + Ausgehehende offline Nachricht + + + + ChatStyle + + + Standard style for group chat + Standard Stil für den Gruppenchat + + + + Standard style for private chat + Standard Stil für den privaten Chat + + + + Standard style for history + Standard Stil für den Verlauf + + + + ConclusionPage + + + Make Friend + Als Freund wählen + + + + Details about your friend : + Details zu Ihrem Freund: + + + + Key validity: + Schlüssel Echtheit: + + + + Email: + Email: + + + + Options + Optionen + + + + Add friend to group: + Freund zur Gruppe hinzufügen: + + + + Authenticate friend (Sign GPG Key) + Authentifiziere Freund (GPG Schlüssel unterzeichnen) + + + + Add as friend to connect with + Füge als Freund hinzu, zu dem verbunden wird + + + + It seems your friend is already registered. Adding it might just set it's ip address. + Ihr Freund ist bereits registriert. Das nochmalige Hinzufügen ändert nur seine IP. + + + + Peer details + Nachbar Details + + + + Name: + Name: + + + + Loc: + Ort: + + + + Signers + Unterzeichner + + + + ConfCertDialog + + + Cancel + Abbrechen + + + + OK + OK + + + + Peer Info + Nachbar Info + + + + Details + Details + + + + Name + Name + + + + Peer ID + Peer ID + + + + Peer Address + Adresse des Nachbarn + + + + Deny Friend + Blockiere Freund + + + + Make Friend + Als Freund wählen + + + + + Sign GPG key + Unterzeichne GPG Schlüssel + + + + Your trust in this peer is: + Dein Vertrauen zu diesem Nachbar ist: + + + + GPG Key + GPG Schlüssel + + + + Peer has signed my GPG key + Nachbar hat meinen GPG Schlüssel unterzeichnet + + + + Peer key is signed by : + Nachbar Schlüssel ist unterzeichnet von: + + + + Last Contact + Letzter Kontakt + + + + Friend Details + Freund-Details + + + + Version + + + + + Loc + Ort + + + + Status + Status + + + + Local Address + Lokale Adresse + + + + External Address + Externe Adresse + + + + + Port + + + + + Addresses list + Adressenliste + + + + None + Nicht + + + + Marginal + Geringfügig + + + + Full + Voll + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Apply and Close + Übernehmen und Schliessen + + + + + RetroShare + + + + + + Error : cannot get peer details. + Fehler: Kann Peer Details nicht ermitteln. + + + + Your key is signed by : + Ihr Schlüssel ist unterzeichnet von: + + + + Peer key is signed by : + Nachbar Schlüssel ist unterzeichnet von: + + + + Your trust in this peer is ultimate, it's probably a key you own. + Du hast das höchste Vertrauen in diesen Nachbarn. Es ist wahrscheinlich ein Schlüssel von Dir. + + + + Your trust in this peer is full. + Du vertraust diesem Nachbarn voll. + + + + Your trust in this peer is marginal. + Du vertraust diesem Nachbarn geringfügig. + + + + Your trust in this peer is none. + Du vertraust diesem Nachbarn nicht. + + + + Your trust in this peer is not set. + Dein Vertrauen in diesen Nachbarn ist nicht festgelegt. + + + + Peer has authenticated me as a friend and did sign my GPG key + Nachbar hat mich als Freund authentifiziert +und meinen GPG Schlüssel unterzeichnet + + + + Peer has not authenticated me as a friend and did not sign my GPG key + Nachbar hat mich nicht als Freund authentifiziert +und meinen GPG Schlüssel nicht unterzeichnet + + + + Signature Failure + Signatur Fehler + + + + Maybe password is wrong + Vielleicht ist das Passwort falsch + + + + Trust + Vertrauen + + + + Dynamic DNS + Dynamisches DNS + + + + Show Help for Trust Settings and Signing + Zeige Hilfe + + + + RetroShare ID + + + + Copy Peer + Kopiere Nachbar + + + + Certificate + Zertifikat + + + + ConnectFriendWizard + + + Connect Friend Wizard + Assistent um sich zu einem Freund zu verbinden + + + + CreateBlog + + + Create new Blog + Neuen Blog erstellen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + Name + + + + Description + Beschreibung + + + + Type: + Typ: + + + + Public - Anyone can read and publish (Shared Publish Key) + Öffentlich - Jeder kann lesen und schreiben (gemeinsamer Veröffentlichungs-Schlüssel) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Beschränkt - Jeder kann lesen, aber nicht jeder schreiben (Privater Veröffentlichungs-Schlüssel) + + + + Private - (Private Publish Key required to view Messages) + Privat - (Privater Veröffentlichungsschlüssel erforderlich, um Nachrichten zu lesen) + + + + Allowed Messages + Erlaubte Nachrichten + + + + Anonymous Messages + Anonyme Nachrichten + + + + Cancel + Abbrechen + + + + Create + Erstellen + + + + RetroShare + + + + + Please add a Name + Bitte Name hinzufügen + + + + Load File + Lade Datei + + + + Pictures (*.png *.xpm *.jpg) + Bilder (*.png *.xpm *.jpg) + + + + Authemticated Messages + Authentifizierte Nachrichten + + + + Blog Logo + + + + + Add Blog Logo + + + + + CreateBlogMsg + + + New Blog Post + Neuer Blogbeitrag + + + + Blog Post + Blogbeitrag + + + + Blog Post to: + Blogbeitrag an: + + + + Visual Editor + Visueller Editor + + + + Blog Message + Blognachricht + + + + Subject : + Betreff: + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + Vergrößere Schrift + + + + Decrease font size + Verkleinere Schrift + + + + Bold + Fett + + + + Underline + Unterstrichen + + + + Italic + Kursiv + + + + Publish + Veröffentlichen + + + + New + Neu + + + + Code + Code + + + + splitPost + teile Beitrag + + + + Ordered List + Geordnete Liste + + + + Unordered List + Ungeordnete Liste + + + + Clipboard + Zwischenablage + + + + Undo + Rückgängig + + + + RetroShare + + + + + Please add a Subject + Bitte den Betreff nicht vergessen + + + + &File + &Datei + + + + &New + &Neu + + + + &Open... + O&ffnen... + + + + &Save + S&peichern + + + + Save &As... + Speichern &als... + + + + &Print... + &Drucken... + + + + Print Preview... + Druckvorschau... + + + + &Export PDF... + PDF &exportieren... + + + + &Quit + &Schliessen + + + + &Edit + &Bearbeiten + + + + &Undo + Rü&ckgängig + + + + &Redo + &Wiederholen + + + + Cu&t + Auss&chneiden + + + + &Copy + Ko&pieren + + + + &Paste + Einfü&gen + + + + &View + Anse&hen + + + + &Insert + Ein&fügen + + + + &Image + &Bild + + + + F&ormat + F&ormat + + + + &Bold + &Fett + + + + &Italic + &Kursiv + + + + &Underline + &Unterstrichen + + + + + &Left + &Links + + + + + C&enter + &Zentriert + + + + + &Right + &Rechts + + + + &Justify + &Blocksatz + + + + &Text Color... + &Textfarbe... + + + + Application + Anwendung + + + + The document has been modified. +Do you want to save your changes? + Das Dokument wurde verändert. +Möchten Sie die Änderungen speichern? + + + + Open File... + Datei öffnen... + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-Dateien (*.htm *.html);;Alle Dateien (*) + + + + Save as... + Speichern unter... + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + Dokument drucken + + + + Export PDF + PDF exportieren + + + + Choose Image + Bild wählen + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Unterstützte Bilddateien (*.png *.jpeg *.jpg *.gif) + + + + CreateChannel + + + Create a new Channel + Erstelle einen neuen Kanal + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + <span style="font-size:24pt; font-weight:500;color:#32CD32;">Neuer Kanal</span> + + + + Name + Name + + + + check peers you would like to share private publish key with + Wähle die Nachbarn, an die du den privaten Schlüssel verteilen möchtest + + + + Share Key With + Schlüssel verteilen an + + + + Contacts: + Kontakte: + + + + Description + Beschreibung + + + + Type: + Typ: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Beschränkt - Jeder kann lesen, aber nicht jeder schreiben (Privater Veröffentlichungs-Schlüssel) + + + + Private - (Private Publish Key required to view Messages) + Privat - (Privater Veröffentlichungsschlüssel erforderlich, um Nachrichten zu lesen) + + + + Allowed Messages + Erlaubte Nachrichten + + + + Anonymous Messages + Anonyme Nachrichten + + + + Authenticated Messages + Authentifizierte Nachrichten + + + + Key Sharing + Schlüsselverteilung + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + Verteile privaten Schlüssel + + + + Channel Logo + Kanal Logo + + + + Add Channel Logo + Kanal Logo hinzufügen + + + + Cancel + Abbrechen + + + + Create + Erstellen + + + + RetroShare + + + + + Please add a Name + Bitte einen Name hinzufügen + + + + Load File + Lade Datei + + + + Pictures (*.png *.xpm *.jpg) + Bilder (*.png *.xpm *.jpg) + + + + CreateChannelMsg + + + New Channel Post + Neuer Kanalbeitrag + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">Neuer Kanalbeitrag</span></p></body></html> + + + + Channel Post + Kanalbeitrag + + + + Channel Post to: + Kanal: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Du kannst dein Miniaturbild für deinen Kanalbeitrag setzen.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Du kannst Dateien mit Drag'n'Drop einfügen.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Schreibe deinen Betreff und die Beschreibung deines Beitrages.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Du kannst die angehängten Dateien in Reiter Anhang anschauen.</span></p></body></html> + + + + Add File to Attach + Datei hinzufügen + + + + Add Channel Thumbnail + Miniaturbild hinzufügen + + + + Message + Beitrag + + + + Subject : + Betreff : + + + + + Attachments + Anhänge + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + Drag'n'Drop Dateien aus den Suchergebnissen + + + + + Drop file error. + Dateifehler bei Drag'n'Drop. + + + + Directory can't be dropped, only files are accepted. + Ordner können nicht für Drag'n'Drop genutzt werden. Nur Dateien werden akzeptiert. + + + + File not found or file name not accepted. + Datei nicht gefunden oder Dateiname nicht akzeptiert. + + + + Add Extra File + Zusätzlich eine Datei hinzufügen + + + + + RetroShare + + + + + File already Added and Hashed + Datei wurde schon hinzugefügt und gehasht + + + + Please add a Subject + Bitte Subjekt nicht vergessen + + + + Load File + Lade Datei + + + + Pictures (*.png *.xpm *.jpg) + Bilder (*.png *.xpm *.jpg) + + + + CreateForum + + + Create new Forum + Erstelle neues Forum + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Neues Forum</span></p></body></html> + + + + Name + Name + + + + Description + Beschreibung + + + + Type: + Typ: + + + + Public - Anyone can read and publish (Shared Publish Key) + Öffentlich - Jeder kann lesen und schreiben (gemeinsamer Veröffentlichungs-Schlüssel) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Beschränkt - Jeder kann lesen, aber nicht jeder schreiben (Privater Veröffentlichungs-Schlüssel) + + + + Private - (Private Publish Key required to view Messages) + Privat - (Privater Veröffentlichungsschlüssel erforderlich, um Nachrichten zu lesen) + + + + Allowed Messages + Erlaubte Nachrichten + + + + Authenticated Messages + Authentifizierte Nachrichten + + + + Anonymous Messages + Anonyme Nachrichten + + + + Cancel + Abbrechen + + + + Create + Erstellen + + + + Please add a Name + Bitte Name hinzüfügen + + + + CreateForumMsg + + + Post Forum Msg + Forumbeitrag schreiben + + + + Forum + Forum + + + + Forum Post + Beitrag + + + + Sign Message + Beitrag unterschreiben + + + + Subject + Betreff + + + + Close + Schliessen + + + + Post Forum Message + Erstelle Forumbeitrag + + + + + Paste RetroShare Link + RetroShare Link einfügen + + + + Paste full RetroShare Link + Vollen RetroShare Link einfügen + + + + In Reply to + Als Antwort auf + + + + RetroShare + + + + + Please set a Forum Subject and Forum Message + Bitte einen Betreff und eine Beitrag eingeben + + + + Add Extra File + Zusätzliche Datei hinzufügen + + + + Attach File + Datei anhängen + + + + Attach files via drag and drop + Hänge Dateien mit Drag'n'Drop an + + + + You can attach files via drag and drop here in this window + Du kannst Dateien mit Drag'n'Drop anhängen + + + + + Drop file error. + Dateifehler bei Drag'n'Drop. + + + + File not found or file name not accepted. + Datei nicht gefunden oder Dateiname nicht akzeptiert. + + + + Directory can't be dropped, only files are accepted. + Ordner können nicht für Drag'n'Drop genutzt werden. Nur Dateien werden akzeptiert. + + + + CreateGroup + + + Create a Group + Gruppe erstellen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + ruppe erstellen + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Gruppe erstellen</span></p></body></html> + + + + Group Name + Name + + + + Enter a name for your group + Gib einen Namen für Deine Gruppe ein + + + + Edit Group + Gruppe ändern + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Gruppe ändern</span></p></body></html> + + + + CryptoPage + + + RetroShare + + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + Dein öffentlicher Schlüssel ist in die Zwischenablage kopiert worden + + + + Save as... + Speichern unter... + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + Öffentlicher Schlüssel + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Kopiere mein Schlüssel in die Zwischenablage</p></body></html> + + + + Copy Key + Kopiere Schlüssel + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Speicher Schlüssel in eine Datei</p></body></html> + + + + Save Key + Schlüssel speichern + + + + DHTStatus + + + DHT + DHT + + + + DHT On + DHT An + + + + DHT Off + DHT aus + + + + RetroShare users in DHT (Total DHT users) + RetroShare Nutzer in DHT (Totale DHT Nutzer) + + + + DLListDelegate + + + B + B + + + + KB + KB + + + + MB + MB + + + + GB + GB + + + + DetailsDialog + + + Details + Details + + + + + General + Allgemein + + + + File Name: + Dateiname: + + + + Hash: + Prüfsumme: + + + + Size: + Größe: + + + + Status: + + + + + Priority: + Priorität: + + + + Type: + Typ: + + + + Transfer + Transfer + + + + Sources: + Quellen: + + + + Datarate: + Datenrate: + + + + Completed: + Komplett: + + + + Chunk size: + Block Größe: + + + + + Number of Chunks + Anzahl der Blöcke + + + + Chunks: + Blöcke: + + + + Remaining: + Verbleibend: + + + + Date + Datum + + + + Download time: + Download Zeit: + + + + + Comments + Kommentare + + + + + retroshare link(s) + RetroShare Link(s) + + + + Copy + Kopieren + + + + OK + OK + + + + Cancel + Abbrechen + + + + Rating + Bewertung + + + + File Name + Dateiname + + + + Not Rated + Nicht bewertet + + + + No Comments + Keine Kommentare + + + + DirectoriesPage + + + Shared Directories + Freigegebene Ordner + + + + + Browse + Durchsuchen + + + + Set Incoming Directory + Ordner für eingehende Dateien + + + + Set Partials Directory + Ordner für temporäre Dateien + + + + Incoming Directory + Eingehende Dateien + + + + Edit Share + Freigaben bearbeiten + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + Merke Hashs von Dateien auch wenn sie nicht mehr freigegeben sind. +Das ist nützlich, wenn Du eine externe Festplatte freigibst und die Datei nicht neu eingelesen werden sollen, wenn Du sie ansteckst. + + + + Remember hashed files for + Merke gehashte Dateien für + + + + days + Tage + + + + Forget any hashed file that is not anymore shared. + Vergesse gehashte Dateien, die nicht mehr freigegeben sind. + + + + Clean Hash Cache + Bereinige Hash Cache + + + + Auto-check shared directories every + Automatische Überprüfung der Freigaben alle + + + + minute(s) + Minute(n) + + + + Partials Directory + Temporäre Dateien + + + + Automatically share incoming directory (Recommended) + Eingehende Ordner automatisch freigeben (Empfohlen) + + + + DiscStatus + + + Waiting outgoing discovery operations + Wartende ausgehene Discovery-Operationen + + + + Waiting incoming discovery operations + Wartende eingehende Discovery-Operationen + + + + DownloadToaster + + + Start file + Starte Datei + + + + <b>Download completed</b> + <b>Download fertig</b> + + + + Close + Schliessen + + + + EditChanDetails + + + Channel Details + Kanal-Details + + + + Cancel + Abbrechen + + + + OK + OK + + + + Edit Channel Details + Kanal-Details bearbeiten + + + + Channel Info + Kanal Info + + + + Channel Name + Kanal-Name + + + + Channel Description + Kanal Beschreibung + + + + Add Channel Logo + Kanal Logo hinzufügen + + + + Load File + Lade Datei + + + + Pictures (*.png *.xpm *.jpg) + Bilder (*.png *.xpm *.jpg) + + + + EditForumDetails + + + Forum Details + Forum-Details + + + + Cancel + Abbrechen + + + + OK + OK + + + + Edit Forum Details + Forum-Details bearbeiten + + + + Forum Info + Forum Info + + + + Forum Name + Forum Name + + + + Forum Description + Forum Beschreibung + + + + EmailPage + + + Invite Friends by Email + Lade Freunde per Email ein + + + + Enter your friends' email addresses (seperate each on with a semicolon) + Gib die Email Adressen Deined Freundes an (mehrere Adressen müssen mit Semikolon getrennt werden) + + + + Your friends' email addresses: + Email Adresse Deines Freundes: + + + + Enter Friends Email addresses + Gib die Email Adresse Deines Freundes ein + + + + Subject: + Betreff: + + + + Friend invites you to check out RetroShare + Ein Freund lädt Dich zu RetroShare ein + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + Ein Freund verwendet RetroShare zur sicheren Kommunikation. Er lädt Dich zum Tauschen von Dateien ein. +RetroShare ist frei und die Benutzung ist sicher: Es enthält keine Viren, keine Spyware, keine Adware und es kann leicht wieder entfernt werden. +Erfahre mehr auf unsere Webseite http://retroshare.sourceforge.net/ oder lade die Software dort herunter http://retroshare.sourceforge.net/downloads.html. +Bis bald in RetroShare! + + + + ErrorMessagePage + + + Sorry, some error appeared + Entschuldigung, es trat ein Fehler auf + + + + Here is the error message: + Dies ist die Fehlermeldung: + + + + ExampleDialog + + + Vote Up + Daumen hoch + + + + Vote Down + Daumen runter + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Freunde</span></p></body></html> + + + + # + # + + + + Status + Status + + + + Person + Person + + + + Auto Connect + Automatisch verbinden + + + + Trust Level + Höhe des Vertrauens + + + + Peer Address + Adresse des Peers + + + + Last Contact + Letzter Kontakt + + + + Organisation + Organisation + + + + Location + Ort + + + + Country + Land + + + + Person Id + Persönliche ID + + + + Auth Code + + + + + ExprParamElement + + + + + to + bis + + + + ignore case + groß/klein ignorieren + + + + + dd.MM.yyyy + dd.MM.yyyy + + + + + KB + KB + + + + + MB + MB + + + + + GB + GB + + + + ExpressionWidget + + + Expression Widget + Ausdruck Oberfläche + + + + Delete this expression + Den Ausdruck löschen + + + + FileAssociationsPage + + + &New + &Neu + + + + Add new Association + Neue Verknüpfung hinzufügen + + + + &Edit + &Bearbeiten + + + + Edit this Association + Diese Verknüpfung bearbeiten + + + + &Remove + &Entfernen + + + + Remove this Association + Entferne diese Verknüpfung + + + + File type + Dateityp + + + + Friend Help + + + + + You this + + + + + FileTransferInfoWidget + + + Chunk map + Block map + + + + Active chunks + Aktive Blöcke + + + + Availability map (%1 active sources) + Verfügbarkeitsmappe (%1 aktive Quellen) + + + + Availability map (%1 active source) + Verfügbarkeitsmappe (%1 aktive Quelle) + + + + File info + Datei Info + + + + File hash + Datei Prüfsumme + + + + File size + Datei Größe + + + + + + + bytes + + + + + Chunk size + Block Größe + + + + Number of chunks + Anzahl der Blöcke + + + + Transfered + Übertragen + + + + Remaining + Verbleibend + + + + Number of sources + Anzahl der Quellen + + + + Chunk strategy + Block Strategie + + + + Transfer type + Transfer Typ + + + + Anonymous F2F + Anonym F2F + + + + Direct friend transfer / Availability assumed + Direkte Freund-Übertragung / Verfügbarkeit angenommen + + + + FlatStyle_RDM + + + Friends Directories + Dateien von Freunden + + + + My Directories + Meine Ordner + + + + Size + Grösse + + + + Age + Alter + + + + Friend + Freund + + + + Share Type + Freigabe Typ + + + + Directory + Ordner + + + + FofPage + + + Friends of friends + Freunde von Freunden + + + + Select now who you want to make friends with. + Wählen Sie nun aus, wen Sie zu Ihren Freundne hinzufügen möchten. + + + + Show me: + Zeige mir: + + + + Any peer I've not signed + Jeden Peer, den ich nicht unterzeichnet habe + + + + Friends of my friends who already trust me + Freunde meiner Freunde, welche mir schon vertrauen + + + + Signed peers showing as denied + Unterzeichnete Peers, die geblockt sind + + + + Peer name + Peer Name + + + + Also signed by + Auch unterzeichnet von + + + + Peer id + + + + + Make friend with these peers + Füge diese Peers zu deinen Freunden hinzu + + + + *** None *** + *** Keine *** + + + + ForumDetails + + + + Forum Details + Forum Details + + + + Forum Info + Forum Info + + + + Forum Name + Forum Name + + + + Popularity + Beliebtheit + + + + Last Post + Letzter Post + + + + Forum ID + + + + + Forum Description + Forum Beschreibung + + + + Security + Sicherheit + + + + Allowed Messages + Erlaubte Nachrichten + + + + Anonymous Messages + Anonyme Nachrichten + + + + Cancel + Abbrechen + + + + OK + OK + + + + Apply and Close + Annehmen und Schliessen + + + + Authemticated Messages + Authentifizierte Nachrichten + + + + ForumMsgItem + + + Remove Item + Eintrag entfernen + + + + Expand + Erweitern + + + + + + Subject: + Betreff: + + + Go to Forum Message + Gehe zum Forumbeitrag + + + + Unsubscribe To Forum + Forum abbestellen + + + + Reply + Antwort + + + + Send + Senden + + + + Signed + Unterzeichnen + + + + Forum Post + Beitrag + + + + Unknown Forum Post + Unbekannter Forumbeitrag + + + + + + Anonymous + Anonym + + + + In Reply to + Als Antwort auf + + + + Please give a Text Message + Bitte Nachricht eingeben + + + + ForumNewItem + + + Form + Formular + + + + Remove Item + Eintrag entfernen + + + + Subscribe to Forum + Forum abonnieren + + + Go to Forum + Gehe zum Forum + + + + Expand + Erweitern + + + + Forum Description + Forenbeschreibung + + + + ForumPage + + + Misc + Verschiedenes + + + + Set message to read on activate + Setze Beitrag beim Aktivieren als gelesen + + + + Expand new messages + Neue Beiträge erweitern + + + + ForumsDialog + + + Subscribe to Forum + Forum abonnieren + + + + Unsubscribe to Forum + Forum abbestellen + + + + New Forum + Neues Forum + + + + Show Forum Details + Zeige Foren-Details + + + + Edit Forum Details + Forum-Details bearbeiten + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + Kopiere RetroShare Link + + + + Mark all as read + Alle als gelesen markieren + + + + Mark all as unread + Alle als ungelesen markieren + + + + Reply + Antwort + + + + Reply to Author + Dem Autor antworten + + + + Expand all + Alle erweitern + + + + Collapse all + Alle reduzieren + + + + Hide + Verbergen + + + + Expand + Erweitern + + + + AUTHD + + + + + + Anonymous + Anonym + + + + + signed + unterzeichnet + + + + + none + keine + + + + + RetroShare + + + + + No Forum Selected! + Kein Forum ausgewählt! + + + + You cant reply a Anonymous Author + Du kannst einem anonymen Autor nicht antworten + + + + Your Forums + Deine Foren + + + + Subscribed Forums + Abonnierte Foren + + + + Popular Forums + Populäre Foren + + + + Other Forums + Andere Foren + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Foren</span></p></body></html> + + + Add + Hinzufügen + + + + Start new Thread for Selected Forum + Starte ein neues Thema im ausgewählten Forum + + + + Display + Anzeige + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + Last Post + Letzter Beitrag + + + + Threaded View + Hierarchische Ansicht + + + + Flat View + Ebene Ansicht + + + + + Date + Datum + + + + + Title + Titel + + + + + Author + Autor + + + + Signed + Unterzeichnet + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thema:</span></p></body></html> + + + + Previous Thread + Vorheriger Beitrag + + + + Next Thread + Nächster Beitrag + + + + Download all files + Alle Dateien runterladen + + + + Reply Message + Auf Beitrag antworten + + + + Create Forum + Forum erstellen + + + + Print + Drucken + + + + PrintPreview + Druckvorschau + + + + + Start New Thread + Erstelle neues Thema + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Suche Foren</span></p></body></html> + + + + Reset + Zurücksetzen + + + + Content + Inhalt + + + + + Mark as read + Als gelesen markieren + + + + + Mark as unread + Als ungelesen markieren + + + + + with children + mit Kindern + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Freunde</span></p></body></html> + + + + Add + Hinzufügen + + + + Display + Anzeige + + + + Friends + Freunde + + + + Status + Status + + + + Add or Change your Avatar + Wähle oder ändere dein Avatar Bild + + + + Edit Personal message + Statusnachricht ändern + + + + Group Chat + Gruppenchat + + + + Messages entered here are sent to all collected friends + Nachrichten, die Du hier eingibst, werden an alle verbundenen Freunde versendet + + + + Bold + Fett + + + + Underline + Unterstrichen + + + + Italic + Kursiv + + + + Font + Schriftart + + + + Text Color + Textfarbe + + + + Attach File + Datei anhängen + + + + Send + Senden + + + + Clear Chat History + Nachrichtenverlauf leeren + + + + + Add Friend + Freund hinzufügen + + + + Create new Profile + Erstelle neues Profil + + + + + Create new Forum + Erstelle neues Forum + + + + F + + + + + + Create new Channel + Erstelle neuen Kanal + + + + C + + + + + Add your Avatar Picture + Wähle dein Avatar Bild + + + + A + + + + + Set your Personal Message + Statusnachricht ändern + + + + Edit your status Message + Statusnachricht ändern + + + + Browse Message History + Nachrichtenverlauf anzeigen + + + + Browse History + Nachrichtenverlauf + + + + + Save Chat History + Nachrichtenverlauf speichern + + + + Hide Offline Friends + Verstecke offline Freunde + + + + Hide Status Column + Status Spalte ausblenden + + + + + Sort by State + Sortiere nach Status + + + + Hide State + Status ausblenden + + + + + Add a new Group + Neue Gruppe hinzufügen + + + + + Sort Descending Order + Absteigend sortieren + + + + + Sort Ascending Order + Aufsteigend sortieren + + + + Delete Chat History + Nachrichtenverlauf löschen + + + + Deletes all stored and displayed chat history + Löscht den gespeicherten und angezeigten Chat Verlauf + + + + Profile + Profil + + + + News Feed + Neuigkeiten + + + + Welcome to RetroShare's group chat. + Willkommen bei RetroShare's Gruppenchat. + + + + me + ich + + + + Paste RetroShare Link + RetroShare Link einfügen + + + + Group + Gruppe + + + + Friend + Freund + + + + Location + Standort + + + + Message Group + Gruppe anschreiben + + + + Edit Group + Gruppe ändern + + + + Remove Group + Gruppe entfernen + + + + Chat + Chat + + + + Message Friend + Freund anschreiben + + + + Friend Details + Freund-Details + + + + Recommend this Friend to... + Freund weiterempfehlen... + + + + Connect To Friend + Zum Freund verbinden + + + + Copy RetroShare Link + Kopiere RetroShare Link + + + + + Paste Friend Link + RetroShare Link einfügen + + + + Deny Friend + Blockiere Freund + + + + Remove Friend Location + Freund entfernen + + + + Add to group + Hinzufügen zur Gruppe + + + + Move to group + Verschiebe in Gruppe + + + + Groups + Gruppen + + + + Remove from group + Aus Gruppe entfernen + + + + Remove from all groups + Aus allen Gruppen entfernen + + + + Expand all + Alle erweitern + + + + Collapse all + Alle reduzieren + + + + location + Standort + + + + + Available + Verfügbar + + + + Save Certificate + Zertifikat speichern + + + + Certificates (*.pqi) + Zertifikate (*.pqi) + + + + Do you want to remove this Friend? + Willst du diesen Freund entfernen? + + + + is typing... + tippt... + + + + + New group chat + Neuer Gruppenchat + + + + Do you really want to physically delete the history? + Willst Du wirklich den Nachrichtenverlauf physisch löschen? + + + + Load File + Lade Datei + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Bilder (*.png *.xpm *.jpg *.tiff *.gif) + + + + Add Extra File + Zusätzliche Datei hinzufügen + + + + + Drop file error. + Dateifehler bei Drag'n'Drop. + + + + Directory can't be dropped, only files are accepted. + Ordner können nicht für Drag'n'Drop genutzt werden. Nur Dateien werden akzeptiert. + + + + File not found or file name not accepted. + Datei nicht gefunden oder Dateiname nicht akzeptiert. + + + + Save as... + Speichern unter... + + + + Text File (*.txt );;All Files (*) + Text Datei (*.txt );;Alle Dateien (*) + + + + GamesDialog + + + Cancel Game + Spiel abbrechen + + + + Add to Invite List + Zur Einladungsliste zufügen + + + + Remove from Invite List + Von Einladungsliste entfernen + + + + + Interested in Playing + An Spielen interessiert + + + + Not Interested in Game + Nicht an Spielen interessiert + + + + + Not Interested + Nicht interessiert + + + + Confirm Peer in Game + Nachbar im Spiel bestätigen + + + + Remove Peer from Game + Nachbar vom Spiel entfernen + + + + Interested in Game + An Spiel interessiert + + + + Quit Game + Spiel verlassen + + + + Form + Formular + + + + Game: + Spiel: + + + + GameType: 0. Want to Add your Game here? + Spieltyp: 0. Wollen Sie Ihr Spiel hier einfügen? + + + + GameType: 1. Get In Touch with the developers + Spieltyp: 1. Kontaktieren Sie die Entwickler + + + + GameType: 2. + Spieltyp: 2. + + + + Title / Comment + Titel / Kommentar + + + + Create New Game + Neues Spiel anlegen + + + + Invite All Friends + Alle Freunde einladen + + + + Game Type + Spieltyp + + + + Server + Server + + + + Status + Status + + + + Comment + Kommentar + + + + GameID + Spiel-ID + + + + Player + Spieler + + + + + Invite + Einladen + + + + Interested + Interessiert + + + + Accept + Bestätigen + + + + Delete + Löschen + + + + + Move Player + Spieler bewegen + + + + Play Game + Spielen + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + GenCertDialog + + + + Generate GPG key Failure + Fehler beim Generieren des GPG Schlüssels + + + + Location field is required with a minimum of 3 characters + Das Feld Ort ist mit min. 3 Zeichen zu versehen + + + + All fields are required with a minimum of 3 characters + Alle Felder sind mit min. 3 Zeichen zu versehen + + + + Select Trusted Friend + Wähle vertrauten Freund + + + + Certificates (*.pqi *.pem) + Zertifikate (*.pqi *.pem) + + + + Name + Name + + + + Email + + + + + + Your profile is associated to a GPG key + Dein Profil ist mit einem GPG Schlüssel verbunden + + + + Generate New Profile + Generiere neues Profil + + + + Info + + + + + Password + Passwort + + + + + + Create new Profile + Erstelle neues Profil + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + Es sieht so aus, als ob Du kein Profile (GPG Schlüssel) besitzt. Bitte fülle die Felder aus und generiere dir ein GPG Schlüssel oder nutze deinen favoritisierten GPG Schlüssel Manager. + + + + Generate a new Profile + Erstelle ein neus Profil + + + + Use Profile + Nutze Profil + + + + Enter here your nickname + Gib deinen Spitznamen ein + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + Sei vorsichtig: Diese E-Mail ist für deine Freunde und und dessen Freunde sichtbar. +Diese Information ist für GPG erforderlich, aber du kannst durch Eingabe einer Fake E-Mail anonym bleiben. + + + + This Password is for GPG + Dieses Passwort ist für GPG + + + + Put a strong password here. This password protects your GPG key. + Gib ein schwieriges Passwort ein. Dieses Passwort schützt deinen GPG Schlüssel. + + + + Location + Ort + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + Nutze einen aussagekräftigen Ort (z.B. home, laptop). Dieses Feld wird genutzt um verschiedene Installationen mit dem selben Schlüssel auseinanderzuhalten. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Neues Profil erstellen</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare benutzt GPG Schlüssel für die Identität. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Du kannst ein vorhandenes Profil (GPG Schlüssel) benutzen oder ein neues Profil erstellen.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Du kannst RetroShare an mehreren Standorten installieren und das selbe Profil (GPG Schlüssel) verwenden.</span></p></body></html> + + + + + Create new Location + Erstelle neuen Ort + + + + + Generate new Location + Erstelle neues Ort + + + + + Create a new Location + Erstelle einen neuen Ort + + + + + Generate new Profile + Generiere neues Profil + + + + + Create a new Profile + Erstelle neues Profil + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + Erstelle einen neuen GPG Schlüssel, bitte habe etwas Gedult. Dieser Prozess generiert große Primzahlen und kann einige Minuten auf langsamen Rechnern dauern. + +Gib Dein GPG Passwort wenn Du gefragt wirst ein, um Deinen neuen Schlüssel zu unterzeichnen. + + + + + Multiple instances + Mehrere Instanzen + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Ein laufendes RetroShare benutzt das gleiche Profil. Bitte schliesse diese Instanz + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Ein unerwartete Fehler während des "Single instance lock" ist aufgetreten + + + + Generate ID Failure + Fehler beim Generieren der ID + + + + Failed to Load your new Certificate! + Fehler beim Laden Deines neuen Zertifikates! + + + + GeneralPage + + + Auto Login + Automatische Anmeldung + + + + Startup + Programmstart + + + + Start minimized on system start + Minimieren beim Starten mit dem System + + + + Misc + Verschiedenes + + + + Do not show the Quit RetroShare MessageBox + MessageBox beim Schliessen nicht anzeigen + + + + Do not Minimize to Tray Icon + Nicht in den Systemabschnitt minimieren + + + + seconds + Sekunden + + + + Start minimized + Minimiert starten + + + + Start RetroShare when my system starts + Starte RetroShare mit dem System + + + + Register retroshare:// as url protocol (Restart required) + Registriere retroshare:// als Protokoll (Neustart erforderlich) + + + + Idle + Untätig + + + + Idle Time + Zeit bis zur Untätigkeit + + + + GraphFrame + + + Recv: + Recv: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + gesendet: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Freunde + + + + Family + Familie + + + + Co-Workers + Mitarbeiter + + + + Other Contacts + Andere Kontakte + + + + Favorites + Favoriten + + + + GroupTreeWidget + + + Enter a Keyword here + Gib einen Suchbegriff ein + + + + Title + Titel + + + + Description + Beschreibung + + + + Reset + Zurücksetzen + + + + Sort by Name + Sortiere nach Name + + + + Sort by Popularity + Sortiere nach Popularität + + + + Sort by Last Post + Sortiere nach letztem Beitrag + + + + Private Key Available + Privater Schlüssel verfügbar + + + + GuiExprElement + + + and + und + + + + and / or + und / oder + + + + or + oder + + + + Name + Name + + + + Path + Pfad + + + + Extension + Erweiterung + + + + Hash + Prüfsumme + + + + Date + Datum + + + + Size + Grösse + + + + Popularity + Beliebtheit + + + + contains + enthält + + + + contains all + enthält alles + + + + is + ist + + + + less than + kleiner als + + + + less than or equal + kleiner als oder gleich + + + + equals + gleich + + + + greater than or equal + grösser als oder gleich + + + + greater than + grösser als + + + + is in range + im Bereich + + + + HelpBrowser + + + + Error Loading Help Contents: + Fehler beim Laden des Hilfe-Inhalts: + + + + Supplied XML file is not a valid Contents document. + Diese XML-Datei ist kein gültiges Inhaltsdokument. + + + + Search reached end of document + Suche am Ende des Dokuments angekommen + + + + Search reached start of document + Suche am Anfang des Dokuments angekommen + + + + Text not found in document + Text im Dokument nicht gefunden + + + + Found %1 results + %1 Ergebnis(se) gefunden + + + + + RetroShare Help + RetroShare Hilfe + + + + Find: + Suche: + + + + Find Previous + Suche vorheriges + + + + Find Next + Suche nächstes + + + + Case sensitive + unterscheide Groß/Klein + + + + Whole words only + Nur ganze Wörter + + + + Contents + Inhalt + + + + Help Topics + Hilfe-Kapitel + + + + + Search + Suchen + + + + Searching for: + Suche nach: + + + + Found Documents + gefundene Dokumente + + + + Back + Zurück + + + + Move to previous page (Backspace) + zur vorherigen Seite zurück (Rückschritt) + + + + Backspace + Rückschritt + + + + Forward + Vorwärts + + + + Move to next page (Shift+Backspace) + Zur nächsten Seite (Umschalt-Rückschritt) + + + + Shift+Backspace + Umschalt-Rückschritt + + + + Home + Home + + + + Move to the Home page (Ctrl+H) + Zur Startseite (Strg-H) + + + + Ctrl+H + Strg-H + + + + + + Find + Suche + + + + Search for a word or phrase on current page (Ctrl+F) + Suche nach einem Begriff auf der aktuellen Seite (Strg-F) + + + + Ctrl+F + Strg-F + + + + Close + Schliessen + + + + Close Vidalia Help + Schliesse Vidalia-Hilfe + + + + Esc + Esc + + + + HelpDialog + + + About + Über + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + Authoren + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + Thanks to + Dank an + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Translation + Übersetzung + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + License Agreement + Lizenzvereinbarung + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Über RetroShare</span></p></body></html> + + + + HelpTextBrowser + + + Error opening help file: + Fehler beim Öffnen der Hilfedatei: + + + + Opening External Link + Öffne externe Verknüpfung + + + + Unable to Open Link + Die Verknüpfung konnte nicht geöffnet werden + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + Retroshare kann den Link in ihrem Browser öffnen. Falls dieser nicht z.B. mit TOR konfiguriert ist, wird der Aufruf der Seite nicht anonym sein. + + + + Do you want Retroshare to open the link in your Web browser? + Soll RetroShare den Link im Browser öffnen? + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + RetroShare konnte den Link nicht mit Deinem Browser öffnen. Du kanns ihn aber kopieren und im Browser per Hand einfügen. + + + + ImHistoryBrowser + + + Message History + Nachrichtenverlauf + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Nachrichtenverlauf</span></p></body></html> + + + + Reset + Zurücksetzen + + + + + Copy + Kopieren + + + + Remove + Entfernen + + + + Mark all + Alle markieren + + + + Delete + Löschen + + + + Clear history + Verlauf löschen + + + + Send + Senden + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare benutzt GPG Schlüssel, das ist für die Erstellung eines RetroShare Profiles erforderlich.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Du muß deinen GPG Schlüssel mit deinen Freunden über E-Mail oder andere Wege tauschen.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Wenn du einen GPG Schlüssel von einem Freund erhälst, kannst du ihn mit dem Assistenten hinzufügen.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. Unter Linux mußt du GPA installieren:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. Unter Windows mußt du gpg4win für die Erstellung der GPG Schlüssel installieren:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. Wenn du möchstest, kannst du deinen GPG Schlüssel mit GPA oder mit WinPT erstellen:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + IntroPage + + + &Make friend with selected friends of my friends + &Füge ausgewählte Freunde Deiner Freunde hinzu + + + + Add a new Friend + Fügen einen neuen Freund hinzu + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + Dieser Assistent hilft Dir, Dich mit einem Freund im RetroShare-Netzwerk zu verbinden. +Die folgenden Wege sind möglich: + + + + &Enter the certificate manually + Gib das Zertifikat &manuell ein + + + + &You get a certificate file from your friend + &Du hast eine Datei mit einem Zertifikat deines Freund bekommen + + + + &Enter RetroShare ID manually + Gib die RetroShare &ID manuell ein + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + &Sende eine Einladung per Email +(Er/Sie erhält eine Email mit der Anleitung zum Herunterladen von RetroShare) + + + + LinksDialog + + + Share Link Anonymously + Verknüpfung anonym teilen + + + + Vote on Link + Über diese Verknüpfung abstimmen + + + + Download + Herunterladen + + + + Expand + Erweitern + + + + Hide + Verbergen + + + + File Request Confirmation + Bestätigung der Dateianforderung + + + + The file has been added to your download list. + Die Datei wurde zur Downloadliste hinzugefügt. + + + + File Request canceled + Dateianforderung abgebrochen + + + + The file has not been added to your download list, because you already have it. + Die Datei wurde nicht zur Downloadliste hinzugefügt, da Sie sie schon haben. + + + + File Request Error + Fehler bei der Dateianforderung + + + + The file link is malformed. + Link ist fehlerhaft. + + + + Title / Comment + Titel / Kommentar + + + + Score + Punkte + + + + Peer / Link + Nachbar / Verknüpfung + + + + Sort by + Sortieren nach + + + + Time + Zeit + + + + Ranking + Rangfolge + + + + In last + Seit letztem + + + + Month + Monat + + + + Week + Woche + + + + Day + Tag + + + + From + Von + + + + All Peers + Alle Nachbarn + + + + Own Links + Eigene Verknüpfungen + + + + Show + Zeigen + + + + Top 100 + Top 100 + + + + 101-200 + 101-200 + + + + 201-300 + 201-300 + + + + 301-400 + 301-400 + + + + 401-500 + 401-500 + + + + Bottom 100 + Letzte 100 + + + + Link: + Verknüpfung: + + + + Add Anonymous Link + Anonyme Verknüpfung hinzufügen + + + + Add Link/Comment + Verknüpfung/Kommentar hinzufügen + + + + Title: + Titel: + + + + Score: + Punkte: + + + + +2 Great! + +2 Super! + + + + +1 Good + +1 Gut + + + + 0 Okay + 0 Okay + + + + -1 Sux + -1 Schrott + + + + -2 Bad Link + -2 Pfui + + + + Url: + URL: + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Verknüpfungs-Wolke</span></p></body></html> + + + + Add new link + Neuen Link hinzufügen + + + + Combo + Kombiniert + + + + MainWindow + + + Network + Netzwerk + + + + Friends + Freunde + + + + + Transfers + Übertragungen + + + + + Messages + Nachrichten + + + + + Channels + Kanäle + + + + Blogs + Blogs + + + + Chat + Chat + + + + + + + %1 new messages + %1 neue Nachrichten + + + + + + + %1 new message + %1 neue Nachricht + + + + You have %1 completed downloads + Du hast %1 fertige Downloads + + + + You have %1 completed download + Du hast %1 fertigen Download + + + + %1 completed downloads + %1 fertige Downloads + + + + %1 completed download + %1 fertigen Download + + + + Down: %1 (kB/s) + Runter: %1 (kB/s) + + + + Up: %1 (kB/s) + Hoch: %1 (kB/s) + + + + %1 friends connected + %1 Freunde verbunden + + + + It seems to be an old RetroShare link. Please use copy instead. + Es scheint ein alter RetroShare Link zu sein. Bitte kopiere den Link stattdessen. + + + + The file link is malformed. + Link ist fehlerhaft. + + + + %1 friend connected + %1 Freund verbunden + + + + Internal Error + Interener Fehler + + + + + Options + Optionen + + + + Hide + Verbergen + + + + Show + Zeigen + + + + RetroShare + + + + + MainWindow + Hauptfenster + + + + Add Friend + Freund hinzufügen + + + + Add a Friend Wizard + Assistent zum Hinzufügen von Freunden + + + + Add Share + Dateien freigeben + + + + + Quick Start Wizard + Schnellstart Assistent + + + + Search + Suchen + + + + Files + Dateien + + + + Messenger + Messenger + + + + Show/Hide + Anzeigen/Verbergen + + + + &Quit + &Schliessen + + + + + + + You have %1 new messages + Du hast %1 neue Nachrichten + + + + + + + You have %1 new message + Du hast %1 neue Nachricht + + + + Bandwidth Graph + Bandbreiten-Graph + + + + Open Messenger + Öffne Messenger + + + + Quit + Schliessen + + + + Minimize + Minimieren + + + + Maximize + Maximieren + + + + Links Cloud + Verknüpfungs-Wolke + + + + Unfinished + unfertig + + + + SMPlayer + + + + + Help + Hilfe + + + + About + Über + + + + + Forums + Foren + + + + RetroShare %1 a secure decentralised communication platform + RetroShare %1 eine sichere und dezentralisierte Kommunikationsplattform + + + + Open Messages + Öffne Nachrichten + + + + Applications + Anwendungen + + + + Plugins + + + + + Do you really want to exit RetroShare ? + Willst Du RetroShare wirklich beenden? + + + + Really quit ? + Wirklich beenden? + + + + Low disk space warning + Wenig Festplatenspeicher + + + + The disk space in your + Der Festplattenspeicher in + + + + directory is running low (current limit is + Verzeichnis ist sehr gering (Die aktuelle Grenze ist + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + MB). + +Normalerweise hält RetroShare jetzt sicher alle Festplattenzugriffe auf das Verzeichnis an. + +Bitte gib etwas Speicher frei und drücke OK. + + + + Status + Status + + + + MessageComposer + + + + Compose + Verfassen + + + + + Contacts + Kontakte + + + + Search for Name: + Suche Name: + + + + Reset + Zurücksetzen + + + + Send To: + Senden an: + + + + >> To + >> An + + + + >> Cc + >> Cc + + + + >> Bcc + >> Bcc + + + + Subject: + Betreff: + + + + Paragraph + Absatz + + + + Search Friends + Suche Freunde + + + + >> Recommend + >> Empfehlen + + + + Heading 1 + Überschrift 1 + + + + + Heading 2 + Überschrift 2 + + + + Heading 3 + Überschrift 3 + + + + Heading 4 + Überschrift 4 + + + + Heading 5 + Überschrift 5 + + + + Heading 6 + Überschrift 6 + + + + Font size + Schriftgröße + + + + Increase font size + Schrift vergrößern + + + + Decrease font size + Schrift verkleinern + + + + Bold + Fett + + + + Underline + Unterstrichen + + + + Tags: + Schlagwörter: + + + + + Tags + Schlagwörter + + + + Italic + Kursiv + + + + Select Color + Text-Farbe auswählen + + + + Alignment + Ausrichtung + + + + Add a Image + Ein Bild hinzufügen + + + + Sets text font to code style + Setzt Schriftart auf Codestil + + + + To + An + + + + Cc + Cc + + + + Bcc + Bcc + + + + Recommended Files + Empfohlene Dateien + + + + File Name + Dateiname + + + + Size + Grösse + + + + Hash + Prüfsumme + + + + Send + Senden + + + + Send this message now + Diese Nachricht jetzt senden + + + + Reply + Antwort + + + + Toggle Contacts View + Kontakt-Ansicht umschalten + + + + Save + Speichern + + + + Save this message + Diese Nachricht speichern + + + + Attach + Anhängen + + + + Attach File + Datei anhängen + + + + Quote + Blockquote + + + + Add Blockquote + Blockquote hinzufügen + + + + &Left + &Links + + + + C&enter + &Zentriert + + + + &Right + &Rechts + + + + &Justify + &Blocksatz + + + + + Save Message + Nachricht speichern + + + + Message has not been Sent. +Do you want to save message to draft box? + Nachricht wurde noch nicht gesendet. +Möchtest Du die Nachricht in den Entwürfen speichern? + + + + + Paste RetroShare Link + RetroShare Link einfügen + + + + Add to "To" + Zu "An" hinzufügen + + + + Add to "CC" + Zu "Cc" hinzufügen + + + + Add to "BCC" + Zu "Bcc" hinzufügen + + + + Add as Recommend + Als empfohlen hinzufügen + + + + Friend Details + Freund-Details + + + + Re: + Re: + + + + Fwd: + Fwd: + + + + + RetroShare + + + + + Do you want to send the message without a subject ? + Möchtest Du die Nachricht ohne Betreff senden ? + + + + Please insert at least one recipient. + Bitte geben sie mindestens einen Empfänger ein. + + + + Unknown + Unbekannt + + + + Unknown friend + Unbekannter Freund + + + + &File + &Datei + + + + &New + &Neu + + + + &Open... + Ö&ffnen... + + + + &Save + S&peichern + + + + Save &As File + Speichern &unter + + + + Save &As Draft + Als &Entwurf speichern + + + + &Print... + &Drucken... + + + + &Export PDF... + PDF &exportieren... + + + + &Quit + &Schliessen + + + + &Edit + &Bearbeiten + + + + &Undo + Rü&ckgängig + + + + &Redo + &Wiederholen + + + + Cu&t + Auss&chneiden + + + + &Copy + Ko&pieren + + + + &Paste + Einfü&gen + + + + &View + &Ansicht + + + + &Contacts Sidebar + &Kontakt-Sidebar + + + + &Insert + Ein&fügen + + + + &Image + &Bild + + + + &Horizontal Line + &Horizontale Linie + + + + &Format + &Format + + + + Open File... + Datei öffnen... + + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-Dateien (*.htm *.html);;Alle Dateien (*) + + + + Save as... + Speichern unter... + + + + Print Document + Dokument drucken + + + + Export PDF + PDF exportieren + + + + Message has not been Sent. +Do you want to save message ? + Nachricht noch nicht versandt. +Willst Du die Nachricht speichern ? + + + + Choose Image + Bild wählen + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Unterstützte Bilddateien (*.png *.jpeg *.jpg *.gif) + + + + Add Extra File + Zusätzliche Datei hinzufügen + + + + + Drop file error. + Dateifehler bei Drag'n'Drop. + + + + Directory can't be dropped, only files are accepted. + Ordner können nicht für Drag'n'Drop genutzt werden. Nur Dateien werden akzeptiert. + + + + File not found or file name not accepted. + Datei nicht gefunden oder Dateiname nicht akzeptiert. + + + + Friend Recommendation(s) + Freundempfehlung(en) + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + Ich empfehle Dir einen guten Freund von mir. Du kannst ihm vertrauen, wenn Du mir vertraust. <br> Kopiere den Link und füge ihn in der Freundesliste ein + + + + MessagePage + + Misc + Verschiedenes + + + + Reading + Lesen + + + + Set message to read on activate + Setze Nachricht beim Aktivieren als gelesen + + + + Open messages in + Nachricht durch Doppelklick öffnen in + + + + Tags + Schlagwörter + + + + Tags can be used to categorize and prioritize your messages + Schlagwörter können beim Sortieren und Erkennen von Nachrichten helfen + + + + Add + Hinzufügen + + + + Edit + Bearbeiten + + + + Delete + Löschen + + + + Default + Standard + + + + A new tab + Neuem Tab + + + + A new window + Neuem Fenster + + + + Edit Tag + Schlagwort bearbeiten + + + + MessageToaster + + + <b>1 new Message from</b> + <b>1 neue Nachricht von</b> + + + + Close + Schliessen + + + + Subject + Betreff + + + + Sub: + Betreff: + + + + MessageWidget + + MainWindow + Hauptfenster + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Empfohlene Dateien</span></p></body></html> + + + + Download all Recommended Files + Alle Dateien runterladen + + + + Subject: + Betreff: + + + + From: + Von: + + + + To: + An: + + + + Cc: + Cc: + + + + Bcc: + Bcc: + + + + Tags: + Schlagwörter: + + + + File Name + Dateiname + + + + Size + Grösse + + + + Hash + Prüfsumme + + + + Print + Drucken + + + + Print Preview + Druckvorschau + + + + No subject + Kein Betreff + + + + Download + Herunterladen + + + + Download all + Alle herunterladen + + + + Hide + Verbergen + + + + Expand + Erweitern + + + + File + Datei + + + + Files + Dateien + + + + Print Document + Dokument drucken + + + + Save as... + Speichern unter... + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-Dateien (*.htm *.html);;Alle Dateien (*) + + + + MessageWindow + + MainWindow + Hauptfenster + + + + New Message + Neue Nachricht + + + + Compose + Verfassen + + + + Reply to selected message + Auf gewählte Nachricht antworten + + + + Reply + Antwort + + + + Reply all to selected message + Auf gewählte Nachricht an alle Empfänger antworten + + + + Reply all + Allen antworten + + + + Forward selected message + Gewählte Nachricht weiterleiten + + + + Foward + Weiterleiten + + + + Remove selected message + Gewählte Nachricht entfernen + + + + Delete + Löschen + + + + Print selected message + Gewählte Nachricht drucken + + + + + Print + Drucken + + + + Display + Anzeige + + + + + + Tags + Schlagwörter + + + + Print Preview + Druckvorschau + + + + + Buttons Icon Only + Buttons nur mit Icon + + + + Buttons Text Beside Icon + Button Text neben Icon + + + + Buttons with Text + Buttons mit Text + + + + Buttons Text Under Icon + Buttons Text unter dem Icon + + + + Set Text Under Icon + Text unter dem Icon + + + + &File + &Datei + + + + Save &As File + Speichern &unter + + + + &Print... + &Drucken... + + + + Print Preview... + Druckvorschau... + + + + &Quit + &Schliessen + + + + MessagesDialog + + + + New Message + Neue Nachricht + + + + Reply to Message + Antworten nur an Absender + + + + Open in a new window + In neuem Fenster öffnen + + + + Open in a new tab + In neuem Tab öffnen + + + + Remove Message + Nachricht entfernen + + + + + Date + Datum + + + + + + From + Von + + + Size + Grösse + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Empfohlene Dateien</span></p></body></html> + + + + Reply + Antworten + + + + Reply all + Allen antworten + + + + Foward + Weiterleiten + + + + Delete + Löschen + + + + Compose + Verfassen + + + + Reply to selected message + Auf gewählte Nachricht antworten + + + + Reply all to selected message + Auf gewählte Nachricht an alle Empfänger antworten + + + + Forward selected message + Gewählte Nachricht weiterleiten + + + + Remove selected message + Gewählte Nachricht entfernen + + + + Print selected message + Gewählte Nachricht drucken + + + + Display + Anzeige + + + + Reset + Zurücksetzen + + + + Attachments + Anhänge + + + + + + + Inbox + Posteingang + + + + + + + Outbox + Postausgang + + + + Draft + Entwürfe + + + + + Sent + Gesendet + + + + Quick View + Schnellansicht + + + Download all Recommended Files + Alle Dateien runterladen + + + Cc: + Cc: + + + Bcc: + Bcc: + + + Tags: + Schlagwörter: + + + + + Print... + Drucken... + + + + Print Preview + Druckvorschau + + + + + Buttons Icon Only + Buttons nur mit Icon + + + + Buttons Text Beside Icon + Button Text neben Icon + + + + Buttons with Text + Buttons mit Text + + + + Buttons Text Under Icon + Buttons Text unter dem Icon + + + + Set Text Under Icon + Text unter dem Icon + + + + Save As... + Speichern unter... + + + Print Document + Dokument drucken + + + + + Subject + Betreff + + + Subject: + Betreff: + + + From: + Von: + + + To: + An: + + + File Name + Dateiname + + + Hash + Prüfsumme + + + + Print + Drucken + + + + Forward selected Message + Gewählte Nachricht weiterleiten + + + + Starred + Gekennzeichnet + + + + Edit + Bearbeiten + + + + Edit as new + Als neu bearbeiten + + + + Remove Messages + Nachrichten entfernen + + + + Forward Message + Weiterleiten + + + + Click to sort by attachments + Klicken, um nach Anhang zu sortieren + + + + Click to sort by subject + Klicken, um nach Betreff zu sortieren + + + + Click to sort by read + Klicken, um nach Gelesen / Ungelesen zu sortieren + + + + + Click to sort by from + Klicken, um nach Von zu sortieren + + + + Click to sort by date + Klicken, um nach Datum zu sortieren + + + + Click to sort by tags + Klicken, um nach Schlagwörter zu sortieren + + + Click to sort by mark + Klicken, um nach Kennzeichnung zu sortieren + + + Download + Herunterladen + + + Hide + Empfohlene Dateien ausblenden + + + Expand + Empfohlene Dateien einblenden + + + + Click to sort by to + Klicken, um nach Empfänger zu sortieren + + + File + Datei + + + Files + Dateien + + + Save as... + Speichern unter... + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-Dateien (*.htm *.html);;Alle Dateien (*) + + + + + Reply to All + Allen antworten + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Alle Dateien runterladen</p></body></html> + + + + Total Inbox: + Posteingang gesamt: + + + + + Content + Inhalt + + + + + + + + Tags + Schlagwörter + + + Tag + Schlagwort + + + + + + + Trash + Papierkorb + + + Favorite Tags + Schlagwörter + + + + Folders + Ordner + + + Remove All Tags + Alle Schlagwörter entfernen + + + New tag ... + Neues Schlagwort... + + + + Mark as read + Als gelesen markieren + + + + Mark as unread + Als ungelesen markieren + + + + Add Star + Kennzeichnung + + + + Undelete + Wiederherstellen + + + + Empty trash + Papierkorb leeren + + + + + + Drafts + Entwürfe + + + + To + An + + + Edit... + Editieren... + + + + Click to sort by star + Klicken, um nach Kennzeichnung zu sortieren + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + Es sind keine gekennzeichneten Nachrichten vorhanden. Durch die Kennzeichnung kannst du Nachrichten mit einem speziellen Status versehen, sodass sie leichter zu finden sind. Klicke zum Kennzeichnen einer Nachricht auf den hellgrauen Stern neben der jeweiligen Nachricht. + + + + + + + + Total: + Gesamt: + + + + MessengerWindow + + + Expand all + Alle erweitern + + + + Collapse all + Alle reduzieren + + + + Chat + Unterhaltung + + + + Message Friend + Freund anschreiben + + + + Connect To Friend + Zum Freund verbinden + + + + Peer Details + Peer-Details + + + + Paste RetroShare Link + RetroShare Link einfügen + + + + Export Friend + Zertifikat des Freundes exportieren + + + + Deny Friend + Blockiere Freund + + + + Remove Friend Location + Freund entfernen + + + + <strong>GPG Key</strong> + <strong>GPG Schlüssel</strong> + + + + <strong>RetroShare instance</strong> + <strong>RetroShare Instanz</strong> + + + + Save Certificate + Zertifikat speichern + + + + Certificates (*.pqi) + Zertifikate (*.pqi) + + + + Click to Change your Avatar + Klick zum Ändern deines Avatars + + + + Add a Friend + Einen Freund hinzufügen + + + + Share Files for your Friends + Ordner für deine Freunde freigeben + + + + Search Friends + Suche Freunde + + + + + Sort Descending Order + Absteigend sortieren + + + + + Sort Ascending Order + Aufsteigend sortieren + + + + Set root is Decorated + Zeige Baumstruktur + + + + Set Root Decorated + Zeige Baumstruktur + + + + Hide Offline Friends + Verstecke offline Freunde + + + + Reset + Zurücksetzen + + + + Sort by State + Sortiere nach Status + + + + Recomend this Friend to... + Freund weiterempfehlen... + + + + RetroShare Messenger + + + + + + + + location + Standort + + + + MsgItem + + + Remove Item + Entferne Element + + + + + Expand + Erweitern + + + + Reply to Message + Auf die Nachricht antworten + + + + Delete Message + Nachricht löschen + + + + Play Media + Medium abspielen + + + + Reply Message + Auf Nachricht antworten + + + + Message From + Nachricht von + + + + Sent Msg + Gesendet + + + + Draft Msg + Entwurf + + + + Pending Msg + Wartend + + + + Hide + Verbergen + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + Internetverbindung + + + + No internet connection + Keine Internetverbindung + + + + No local network + Kein lokales Netwerk + + + + OK | RetroShare Server + + + + + NetworkDialog + + + Personal signature + Persönliche Unterschrift + + + + GPG key signed by you + GPG Schlüssel von dir unterzeichnet + + + + Marginally trusted peer + Geringfügig vertrauter Nachbar + + + + Fully trusted peer + Voll vertrauter Nachbar + + + + Untrusted peer + Nicht vertrauter Nachbar + + + + Has authenticated me + Hat mich authentifiziert + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + hat mich authentifiziert. +Rechtsklick und als Freund hinzufügen um zu verbinden. + + + + + + Name + Name + + + + + Did I authenticated peer + Habe ich den Peer authentifiziert + + + + Did I sign his gpg key + Habe ich seinen GPG Schlüssel unterzeichnet + + + + + Cert Id + ID des Zertifikates + + + + Search Network + Netzwerksuche + + + + Clear Filter + Filter leeren + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anzeige</span></p></body></html> + + + + Local network + Lokales Netzwerk + + + + UPnP + + + + + External ip address finder + Externer IP Adressen Finder + + + + Add Friend + Freund hinzufügen + + + + Copy My Key to Clipboard + Kopiere mein Zertifikat in die Zwischenablage + + + + Export My Key + Exportiere mein Zertifikat + + + + Create New Profile + Erstelle neues Profil + + + + Create a new Profile + Erstelle ein neues Profil + + + + Network + Netzwerk + + + + + Did peer authenticated me + Hat mich der Peer authentifiziert + + + + Show keys that are not validated by the GPG web of trust + Zeige Schlüssel, die nicht vom web of trust bestätigt sind + + + + Clear + Leeren + + + + Deny friend + Blockiere Freund + + + + Make friend + Freund hinzufügen + + + + Delete certificate + Zertifikat löschen + + + + Export my Cert + Exportiere mein Zertifikat + + + + Peer details... + Nachbar-Details... + + + + Copy RetroShare Link + Kopiere RetroShare Link + + + + Unknown + Unbekannt + + + + Authentication matrix + Authentifizierungsmatrix + + + + Network View + Netzwerk Ansicht + + + + yourself + selbst + + + + Network Status + Netzwerk-Status + + + + Set Tabs Right + Setze Tabs nach Rechts + + + + Set Tabs North + Setze Tabs nach Oben + + + + Set Tabs South + Setze Tabs nach Unten + + + + Set Tabs Left + Setze Tabs nach Links + + + + Set Tabs Rounded + Setze Tabs Form Rund + + + + Set Tabs Triangular + Setze Tabs Form Dreieck + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Netzwerk</span></p></body></html> + + + + Peer ID + Peer ID + + + + NetworkView + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + Neu zeichnen + + + + Friendship level: + Freundshaftslevel: + + + + Edge length: + Kantenlänge: + + + + NewTag + + + New Tag + Neues Schlagwort + + + + Name: + Name: + + + + Choose color + Farbe wählen + + + + OK + OK + + + + Cancel + Abbrechen + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Neuigkeiten</span></p></body></html> + + + + Remove All + Alle entfernen + + + + Options + Optionen + + + + NotifyPage + + + News Feed + News Feed + + + + Peers + Nachbarn + + + + Channels + Kanäle + + + + Forums + Foren + + + + Chat + + + + + Blogs + Blogs + + + + Messages + Nachrichten + + + + Systray Icon + Systray Icon + + + + Private Message + Private Nachricht + + + + Message + Nachricht + + + + Channel Post + Kanalbeitrag + + + + Forum Post + Forumbeitrag + + + + + Download completed + Download fertig + + + + Combined icon + Kombiniertes Icon + + + + Toasters + + + + + Friend Connect + Verbinde zu Freund + + + + New Message + Neue Nachricht + + + + Position + Position + + + + X Margin + Abstand X + + + + Y Margin + Abstand Y + + + + Private Chat + Privater Chat + + + + Open Window for new chat + Öffne Fenster für neuen Chat + + + + Grab Focus when chat arrives + Fokus auf neues Chatfenster legen + + + + Use a single tabbed window + Ein Fenster mit Tabs verwenden + + + + Group chat + Gruppenchat + + + + Display systray message + Zeige Systemabschnitts-Nachricht an + + + + Add feeds at end + Feeds am Ende anfügen + + + + Top Left + Oben Links + + + + Top Right + Oben Rechts + + + + Bottom Left + Unten Links + + + + Bottom Right + Unten Rechts + + + + NotifyQt + + + GPG key passphrase + GPG Schlüssel Passwort + + + + Wrong password ! + Falsches Passwort ! + + + + Please enter the password to unlock the following GPG key: + Bitte geben Sie das Passwort ein um folgenden GPG Schlüssel freizuschalten: + + + + Examining shared files... + Prüfe freigegebene Dateien... + + + + Hashing file + Erstelle Prüfsumme + + + + Saving file index... + Speichere Dateiindex... + + + + OnlineToaster + + + Friend Online + Freund Online + + + + PeerDefs + + + + Unknown + Unbekannt + + + + PeerItem + + + Remove Item + Entferne Element + + + + + Expand + Erweitern + + + + Status: + Status: + + + + Trust: + Vertrauen: + + + + Chat + Chat + + + + Name: + Name: + + + + Peer ID: + Peer ID: + + + + Location + Ort + + + + IP Address + IP-Adresse + + + + Connection Method + Verbindungsmethode + + + + Write Message + Nachricht schreiben + + + + Start Chat + Chat starten + + + + Write a quick Message + Schnelle Nachricht schreiben + + + + Send + Senden + + + + Cancel + Abbrechen + + + + Friend Connected + Freund verbunden + + + + Friend + Freund + + + + Connect Attempt + Verbindungsversuch + + + + Friend of Friend + Freunde eines Freundes + + + + Peer + Nachbar + + + + + + + + + + + + Unknown Peer + Unbekannter Nachbar + + + + Hide + Verbergen + + + + Quick Message + Schnelle Nachrricht + + + + PeerStatus + + + Friends: 0/0 + Freunde: 0/0 + + + + Online Friends/Total Friends + Freunde online / Freunde total + + + + Friends + Freunde + + + + PeersDialog + + Chat + Chat + + + Save Certificate + Zertifikat speichern + + + Certificates (*.pqi) + Zertifikate (*.pqi) + + + Status + Status + + + Connect To Friend + Verbinde zum Freund + + + Profile + Profil + + + Welcome to RetroShare's group chat. + Willkommen bei RetroShare's Gruppenchat. + + + me + ich + + + Group + Gruppe + + + Friend + Freund + + + Location + Standort + + + Friend Details + Freund-Details + + + Expand all + Alle erweitern + + + Collapse all + Alle reduzieren + + + Message Friend + Freund anschreiben + + + News Feed + Neuigkeiten + + + Paste RetroShare Link + RetroShare Link einfügen + + + Recommend this Friend to... + Freund weiterempfehlen... + + + Copy RetroShare Link + Kopiere RetroShare Link + + + Deny Friend + Blockiere Freund + + + Remove Friend Location + Freund entfernen + + + Add to group + Hinzufügen zur Gruppe + + + Move to group + Verschiebe in Gruppe + + + Groups + Gruppen + + + Remove from group + Aus Gruppe entfernen + + + Remove from all groups + Aus allen Gruppen entfernen + + + Available + Verfügbar + + + New group chat + Neuer Gruppenchat + + + Do you really want to physically delete the history? + Willst Du wirklich den Nachrichtenverlauf physisch löschen? + + + Load File + Lade Datei + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Bilder (*.png *.xpm *.jpg *.tiff *.gif) + + + Add Extra File + Zusätzliche Datei hinzufügen + + + Drop file error. + Dateifehler bei Drag'n'Drop. + + + File not found or file name not accepted. + Datei nicht gefunden oder Dateiname nicht akzeptiert. + + + Directory can't be dropped, only files are accepted. + Ordner können nicht für Drag'n'Drop genutzt werden. Nur Dateien werden akzeptiert. + + + Italic + Kursiv + + + Underline + Unterstrichen + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Freunde</span></p></body></html> + + + Add + Hinzufügen + + + Display + Anzeige + + + Add or Change your Avatar + Wähle oder ändere dein Avatar Bild + + + Edit Personal message + Statusnachricht ändern + + + Messages entered here are sent to all collected friends + Nachrichten, die Du hier eingibst, werden an alle verbundenen Freunde versendet + + + Bold + Fett + + + Text Color + Textfarbe + + + Create new Forum + Erstelle neues Forum + + + Create new Channel + Erstelle neuen Kanal + + + Add your Avatar Picture + Wähle dein Avatar Bild + + + Set your Personal Message + Statusnachricht ändern + + + Edit your status Message + Statusnachricht ändern + + + Sort by State + Sortiere nach Status + + + Hide State + Status ausblenden + + + Add a new Group + Neue Gruppe hinzufügen + + + Sort Descending Order + Absteigend sortieren + + + Sort Ascending Order + Aufsteigend sortieren + + + Delete Chat History + Nachrichtenverlauf löschen + + + Deletes all stored and displayed chat history + Löscht den gespeicherten und angezeigten Chat Verlauf + + + Add Friend + Freund hinzufügen + + + Create new Profile + Erstelle neues Profil + + + Font + Schriftart + + + Group Chat + Gruppenchat + + + Attach File + Datei anhängen + + + Send + Senden + + + Clear Chat History + Nachrichtenverlauf leeren + + + Save Chat History + Nachrichtenverlauf speichern + + + Message Group + Gruppe anschreiben + + + Edit Group + Gruppe ändern + + + Remove Group + Gruppe entfernen + + + Do you want to remove this Friend? + Willst du diesen Freund entfernen? + + + Save as... + Speichern unter... + + + Text File (*.txt );;All Files (*) + Text Datei (*.txt );;Alle Dateien (*) + + + Hide Offline Friends + Verstecke offline Freunde + + + Hide Status Column + Status Spalte ausblenden + + + is typing... + tippt... + + + Browse Message History + Nachrichtenverlauf anzeigen + + + Browse History + Nachrichtenverlauf + + + Friends + Freunde + + + Paste Friend Link + RetroShare Link einfügen + + + location + Standort + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + Öffnen + + + + Remove + Entfernen + + + + Excellent + Exzellent + + + + Good + Gut + + + + Average + Durchschnittlich + + + + Below avarage + Unter Durchschnitt + + + + Bad + Schlecht + + + + Unrated + Unbewertet + + + + Rating + Bewertung + + + + Peer + Nachbar + + + + Slideshow + Slideshow + + + + Photo + Foto + + + + Thumb Image + Vorschaubild + + + + Image Name + Bild-Name + + + + + Comment + Kommentar + + + + + Date + Datum + + + + + Location + Ort + + + + Size + Grösse + + + + PeerId + PeerId + + + + PhotoId + PhotoId + + + + + Add Photo(s) + Foto(s) hinzufügen + + + + Add Photo SlideShow + Foto-Slideshow hinzufügen + + + + Update Details + Details aktualisieren + + + + Photo + Foto + + + + Description + Beschreibung + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + PhotoShow + + + Date: + Datum: + + + + Location: + Ort: + + + + Comment: + Kommentar: + + + + Display Size: + Anzeige-Grösse: + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + Volle Grösse + + + + Play Rate: + Abspielrate: + + + + 1 Sec + 1 Sek + + + + 2 Sec + 2 Sek + + + + 5 Sec + 5 Sek + + + + 10 Sec + 10 Sek + + + + 20 Sec + 20 Sek + + + + 1 Min + 1 Min + + + + Edit Photo Details + Foto-Details bearbeiten + + + + Save Photo + Foto speichern + + + + No Photo Selected + Kein Foto ausgewählt + + + + Start + Start + + + + Back + Zurück + + + + Photo Show + + + + + Play + Abspielen + + + + Pause + Pause + + + + Forward + Vorwärts + + + + PluginFrame + + + Remove + Entfernen + + + + PluginManagerWidget + + + Install New Plugin... + Neues Plugin installieren... + + + + Open Plugin to install + Öffne Plugin zum Installieren + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + Beliebtheit + + + + PopupChatDialog + + + Hide Avatar + Avatar verstecken + + + + Show Avatar + Avatar zeigen + + + + Do you really want to physically delete the history? + Willst Du wirklich den Nachrichtenverlauf physisch löschen? + + + + Load Picture File + Lade Bilddatei + + + + File not found or file name not accepted. + Datei nicht gefunden oder Dateiname nicht akzeptiert. + + + + Messages you send will be delivered after Friend is again Online + Nachrichten, die Du versendest gehen bei diesem Freund erst wieder ein wenn er Online ist + + + + + Bold + Fett + + + + + Underline + Unterstrichen + + + + + Italic + Kursiv + + + + Text Color + Textfarbe + + + + Clear offline messages + Entferne offline Nachrichten + + + + Browse Message History + Nachrichtenverlauf anzeigen + + + + Browse History + Nachrichtenverlauf + + + + Clear Chat History + Nachrichtenverlauf leeren + + + + Font + Schriftart + + + + Delete Chat History + Nachrichtenverlauf löschen + + + + Deletes all stored and displayed chat history + Löscht den gespeicherten und angezeigten Chat Verlauf + + + + Send + Senden + + + + Disable Emoticons + Deaktiviere Emoticons + + + + Strike + Durchgestrichen + + + + Add Extra File + Zusätzlich eine Datei hinzufügen + + + + + Drop file error. + Dateifehler bei Drag'n'Drop. + + + + Directory can't be dropped, only files are accepted. + Ordner können nicht für Drag'n'Drop genutzt werden. Nur Dateien werden akzeptiert. + + + + Add a File for your Friend + Füge eine Datei für deinen Freund hinzu + + + + + Save Chat History + Nachrichtenverlauf speichern + + + + Save as... + Speichern unter... + + + + Text File (*.txt );;All Files (*) + Text Datei (*.txt );;Alle Dateien (*) + + + + Your Friend is offline +Do you want to send them a Message instead + Dein Freund ist Offline willst du ihm stattdessen eine Nachricht senden + + + + Attach a Picture + Bild anhängen + + + + is Idle and may not reply + antwortet möglicherweise nicht, da der Status auf "Untätig" gesetzt wurde + + + + is Away and may not reply + antwortet möglicherweise nicht, da der Status auf "Abwesend" gesetzt wurde + + + + is Busy and may not reply + antwortet möglicherweise nicht, da der Status auf "Beschäftigt" gesetzt wurde + + + + apears to be Offline. + ist Offline. + + + + Paste RetroShare Link + RetroShare Link einfügen + + + + is typing... + tippt... + + + + Close + Schliessen + + + + Friend not Online + Freund ist nicht online + + + + PopupChatWindow + + + Avatar + Avatar + + + + Set your Avatar Picture + Wähle dein Avatar Bild + + + + + Dock tab + Tab andocken + + + + + Undock tab + Tab abdocken + + + + + Set Chat Window Color + Setze Farbe des Chat Fensters + + + + RetroShare + RetroShare + + + + Load File + Lade Datei + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Bilder (*.png *.xpm *.jpg *.tiff *.gif) + + + + PrintPreview + + + RetroShare Message - Print Preview + RetroShare Nachricht - Druckvorschau + + + + Print + Drucken + + + + &Print... + &Drucken... + + + + Page Setup... + Seiteneinstellung... + + + + Zoom In + Hereinzoomen + + + + Zoom Out + Herauszoomen + + + + &Close + S&cliessen + + + + ProfileEdit + + + Remove Profile Entry + Profil-Eintrag entfernen + + + + Move Profile Entry Up + Profil-Eintrag nach oben + + + + Move Profile Entry Down + Profil-Eintrag nach unten + + + + Profile + Profil + + + + Category + Kategorie + + + + Thoughts + Gedanken + + + + Edit Profile Category + Profil-Kategorie bearbeiten + + + + Birthday + Geburtstag + + + + School + Schule + + + + University + Universität + + + + Phone Number + Telefonnummer + + + + Favourite Books + Lieblings-Bücher + + + + Favourite Music + Lieblings-Musik + + + + Favourite Films + Lieblings-Filme + + + + or Custom Entry + oder eigener Eintrag + + + + Add Entry + Eintrag hinzufügen + + + + + Move + Bewegen + + + + Close Editor + Editor schliessen + + + + Profile Edit + Profil editieren + + + + ProfileView + + + Clear Photo + Photo entfernen + + + + Change Photo + Photo ändern + + + + + Edit Profile + Profil bearbeiten + + + + Remove Favourite + Favoriten entfernen + + + + Clear Favourites + Alle Favoriten löschen + + + + Download File + Datei herunterladen + + + + Download All + Alle herunterladen + + + + + Name + Name + + + + Last Post: + letztes Posting: + + + + Category + Kategorie + + + + Thoughts + Gedanken + + + + Favourite Files + Lieblings-Dateien + + + + Size + Grösse + + + + Hash + Prüfsumme + + + + Close Profile + Profil schliessen + + + + Profile View + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Peer ID + Peer ID + + + + RetroShare + + + + + Error : cannot get peer details. + Fehler: Kann Peer Details nicht bekommen. + + + + ProfileWidget + + + + Edit Personal message + Statusnachricht ändern + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Informationen</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Öffentliche Informationen</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Standort:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online seit:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamisches DNS:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Andere Informationen</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Anzahl Freunde:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Meine Adresse</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Lokale Adresse:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Externe Adresse:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Adressliste</span></p></body></html> + + + + QObject + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + Initialisierung fehlgeschlagen. GPG fehlt oder es ist eine falsche Version installiert. + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + Ein unerwarteter Fehler ist aufgetreten. Bitte melde 'RsInit::InitRetroShare unexpected return code %1'. + + + + + Multiple instances + Mehrere Instanzen + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + Ein laufendes RetroShare benutzt das gleiche Profil. Bitte schliesse diese Instanz +Lockdatei: + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + Ein unerwartete Fehler während des "Single instance lock" ist aufgetreten +Lockdatei: + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Ein laufendes RetroShare benutzt das gleiche Profil. Bitte schliesse diese Instanz + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Ein unerwartete Fehler während des "Single instance lock" ist aufgetreten + + + + Login Failure + Loginfehler + + + + Maybe password is wrong + Vielleicht ist das Passwort falsch + + + + File Request Confirmation + Bestätigung der Dateianforderung + + + + The file has been added to your download list. + Die Datei wurde zur Downloadliste hinzugefügt. + + + + + File Request canceled + Dateianforderung abgebrochen + + + + The following has not been added to your download list, because you already have it: + + Die folgende Datei wurde nicht zur Downloadliste hinzugefügt, da Du diese schon hast: + + + + + The file has not been added to your download list, because you already have it. + Die Datei wurde nicht zur Downloadliste hinzugefügt, da Du sie schon hast. + + + + + Friend Request Confirmation + Freundanfrage bestätigen + + + + The friend is already in your list. + Der Freund ist schon in Deiner Liste. + + + + The friend has been added to your list. + Der Freund wurde zu Deiner Liste hinzugefügt. + + + + + Friend Request canceled + Freundanfrage abgebrochen + + + + The friend could not be added to your list. + Der Freund konnte nicht zu Deiner Liste hinzugefügt werden. + + + + The friend could not be found. + Der Freund konnte nicht gefunden werden. + + + + + Forum Request canceled + Forumanfrage abgebrochen + + + + The forum "%1" could not be found. + Das Forum "%1" konnte nicht gefunden werden. + + + + The forum message in forum "%1" could not be found. + Der Forumbeitrag im Forum "%1" konnte nicht gefunden werden. + + + + The channel message in channel "%1" could not be found. + Der Kanalbeitrag im Kanal "%1" konnte nicht gefunden werden. + + + + The receipient of the message is unknown. + Der Empfänger der Nachricht ist unbekannt. + + + + %1 of %2 RetroShare links processed. + %1 von %2 RetroShare Links verarbeitet. + + + %1 of %2 RetroShare links processed + %1 von %2 RetroShare Links verarbeitet. + + + + Request Confirmation + Anfrage bestätigen + + + The forum message could not be found. + Der Forumbeitrag "%1" konnte nicht gefunden werden. + + + + + Channel Request canceled + Kanalanfrage abgebrochen + + + + The channel "%1" could not be found. + Der Kanal "%1" konnte nicht gefunden werden. + + + + Cannot send a message to a not accepted receipient "%1". + Nachricht kann nicht an den nicht akzeptierten Empfänger "%1" senden. + + + + + Message Request canceled + Nachrichtenanfrage abgebrochen + + + The receipient of the message "%1" is unknown. + Der Empfänger der Nachricht "%1" ist unbekannt. + + + + File Request Error + Fehler bei der Dateianforderung + + + + The file link is malformed. + Link ist fehlerhaft. + + + + Deny friend + Blockiere Freund + + + + Make friend + Freund hinzufügen + + + + Peer details + Nachbar Details + + + No running instance of RetroShare found. + Kein laufendes RetroShare gefunden. + + + + Start with a RetroShare link is only supported for Windows. + Der Start mit einem RetroShare Link wird nur unter Windows unterstützt. + + + + (Age in seconds) + + + + + (Depth) + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + Schnellstart Assistent + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + + Next > + Weiter > + + + + + + + Exit + Beenden + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + Für die beste Leistung muß RetroShare ein wenig über Deine Internetverbindung wissen. + + + + Choose your upload speed limit: + Wählen Sie Ihre maximale Uploadgeschwindigkeit: + + + + + KB/s + + + + + Choose your download speed limit: + Wählen Sie Ihre maximale Downloadgeschwindigkeit: + + + + Connection : + Verbindung : + + + + Automatic (UPnP) + Automatisch (UPnP) + + + + Firewalled + Firewall + + + + Manually forwarded port + Manuell weitergeleiteter Port + + + + Discovery : + Entdeckung : + + + + + + < Back + < Zurück + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Das ist die Liste der freigegebenen Ordner. Mit den unteren Knöpfen kannst Du neue Ordner hinzufügen oder vorhandene Ordner entfernen.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Wenn Du einen neuen Ordner hinzufügst, werden alle Dateien aus dem Ordner und Unterordnern freigegeben.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Du kannst für jeden freigegebenen Ordner die Art der Freigabe einstellen:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Durchsuchbar</span><span style=" font-family:'Sans'; font-size:8pt;">: Dateien sind von Deinen direkten Freunden durchsuchbar.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Netzwerkweit</span><span style=" font-family:'Sans'; font-size:8pt;">: Dateien können von jedem über anoynme Tunnel heruntergeladen werden.</span></p></body></html> + + + + Directory + Ordner + + + + Network Wide + Netzwerkweit + + + + Browseable + Durchsuchbar + + + + Add + Hinzufügen + + + + Remove + Entfernen + + + + Automatically share incoming directory (Recommended) + Eingehende Ordner automatisch freigeben (Empfohlen) + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Viel Spaß beim Benutzen von RetroShare!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Nur noch einen Schritt! Du hast es fast geschafft.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Diese Einstellungen konfigurieren den Start von RetroShare.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Do not show a message when Closing RetroShare + Keine Nachricht beim Beenden von RetroShare anzeigen + + + + Start Minimized + Starte minimiert + + + + Start RetroShare when my System Starts. + Starte RetroShare mit dem System. + + + + Start minimized on system start + Minimieren beim Starten mit dem System + + + + Finish + Fertigstellen + + + + Select A Folder To Share + Wählen Sie ein Ordner zum Freigeben + + + + Shared Directory Added! + Ordner wurde hinzugefügt! + + + + Do you really want to stop sharing this directory ? + Möchtes Du die Freigabe dieses Ordners wirklich aufheben ? + + + + Warning! + Warnung! + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Willkommen bei RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Dieser Schnellstart Assistent hilft dir RetroShare in ein paar Schritten zu konfigurieren.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Wenn du ein erfahrener Benutzer bist, kannst du die kompletten Einstellungen über Optionen im Toolbar erreichen. Du kannst den Assistent jederzeit beenden.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Diese Assistent hilft dir bei:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> der Einrichtung der Internetverbindung.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> der Freigabe von Verzeichnissen.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> beim Start von RetroShare.</span></p></body></html> + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + Dynamisches DNS: + + + + RSettingsWin + + + General + Allgemein + + + + Directories + Ordner + + + + Server + Server + + + + Transfer + Übertragung + + + + Notify + Meldungen + + + + Security + Sicherheit + + + + Appearance + Aussehen + + + + Sound + Sound + + + + UnknownPage + Unbekannte Seite + + + + Error Saving Configuration on page + Fehler beim Speichern der Konfiguration auf der Seite + + + + Message + Nachricht + + + + Chat + Chat + + + + Forum + Forum + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + <strong>Runter:</strong> + + + + <strong>Up:</strong> + <strong>Hoch:</strong> + + + + RemoteDirModel + + Friends Directories + Dateien von Freunden + + + My Directories + Meine Ordner + + + Size + Grösse + + + Share Type + Freigabe Typ + + + What's new + Was ist neu + + + Age + Alter + + + Anonymous + Anonym + + + Anonymous and browsable by friends + Anonym und Durchsuchbar von Freunden + + + Only browsable by friends + Nur Durchsuchbar von Freunden + + + NEW + NEU + + + FILE + DATEI + + + Files + Dateien + + + File + Datei + + + DIR + ORDNER + + + + RetroshareDirModel + + + Anonymous + Anonym + + + + Anonymous and browsable by friends + Anonym und Durchsuchbar von Freunden + + + + Only browsable by friends + Nur Durchsuchbar von Freunden + + + + NEW + NEU + + + + Rshare + + + Invalid language code specified: + Ungültige Sprach-Codierung ausgewählt: + + + + Invalid GUI style specified: + Ungültigen Stil der Benutzeroberfläche ausgewählt: + + + + Resets ALL stored RetroShare settings. + Setzt alle RetroShare Einstellungen zurück. + + + + Sets the directory RetroShare uses for data files. + Setzt das Verzeichnis, welches RetroShare für Daten benutzt. + + + + Sets the name and location of RetroShare's logfile. + Setzt den Ort und Namen der Logdatei. + + + + Sets the verbosity of RetroShare's logging. + Setzt die Ausgaben der RetroShare Logdatei. + + + + Sets RetroShare's interface style. + Setzt den RetroShare Interface Stil. + + + + Sets RetroShare's interface stylesheets. + Setzt den RetroShare stylesheet. + + + + Sets RetroShare's language. + Setzt die Sprache. + + + + RetroShare Usage Information + RetroShare Informationen zur Benutzung + + + + Invalid log level specified: + Ungültiges Log Level spezifiziert: + + + + Unable to open log file '%1': %2 + Kann Logdatei nicht öffnen '%1': %2 + + + + RsidPage + + + RetroShare ID + RetroShare ID + + + + Use RetroShare ID for adding a Friend which is available in your network. + Benutze die RetroShare ID um Freunde aus deinem Netzwerk hinzuzufügen. + + + + Add Friends RetroShare ID... + Füge die RetroShare ID des Freundes ein... + + + + Paste Friends RetroShare ID in the box below + Füge die RetroShare ID eines Freunde in das Feld ein + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + Füge die RetroShare ID eines Freundes ein, Beispiel Peer@BDE8D16A46D938CF + + + + This Peer %1 is not available in your Network + Der Nutzer %1 ist nicht in deinem Netzwerk verfügbar + + + + SFListDelegate + + + B + B + + + + KB + KB + + + + MB + MB + + + + GB + GB + + + + SearchDialog + + + Sources + Quellen + + + + Results + Ergebnisse + + + + + Download + Herunterladen + + + + Enter a keyword here (at least 3 char long) + Gib einen Suchbegriff ein (min. 3 Zeichen) + + + Copy retroshare Link + Kopiere RetroShare Link + + + Send retroshare Link + Sende RetroShare Link + + + Broadcast on Channel + Im Kanal bekanntgeben + + + Recommend to Friends + Freunden empfehlen + + + + + Copy RetroShare Link + Kopiere RetroShare Link + + + + Send RetroShare Link + Sende RetroShare Link + + + + Remove + Entfernen + + + + Remove All + Alle entfernen + + + + + Folder + Ordner + + + + New RetroShare Link(s) + Neu(e) RetroShare Link(s) + + + + Any + Alle + + + + Audio + Audio + + + + Video + Video + + + + Enter a Keyword here + Gib einen Suchbegriff ein + + + + Filter Search Result + Filter Suchergebnis + + + + Filename + Dateiname + + + + Age + Alter + + + + Hash + Prüfsumme + + + + KeyWords + Schlüsselwörter + + + + Search Id + Such ID + + + + Download Notice + Download + + + + Skipping Local Files + Überspringe lokale Dateien + + + + + Sorry + Entschuldigung + + + + + This function is not yet implemented. + Diese Funktion ist noch nicht eingebaut. + + + + Size + Grösse + + + + Type + Typ + + + + Archive + Archiv + + + + CD-Image + CD-Abbild + + + + Document + Dokument + + + + Picture + Bilder + + + + Program + Programme + + + + Directory + Ordner + + + + Start Search + Starte Suche + + + + Search + Suchen + + + + Clear Filter + Filter leeren + + + + File Name + Dateiname + + + + File Size + Dateigröße + + + + Close all Search Resullts + Schließe alle Suchergebnisse + + + + Download Selected + Ausgewählte herunterladen + + + + Include files from your own file list in the search result + Schließe Dateien von dir in die Suchresultate ein + + + + Include own files + Schließe eigene Dateien ein + + + + Search inside "browsable" files of your friends + Suche in den "durchsuchbaren" Dateien von Freunden + + + + Search in friends lists + Suche in der Liste von Freunden + + + + Multi-hop search at distance 6 in the network +(always reports available files) + Multi-hop Suche mit einer Distanz von 6, +(gibt immer verfügbare Dateien an) + + + + F2F search + F2F Suche + + + + Limit number of results to : + Begrenze Anzahl der Resultate auf : + + + + Reset + Zurücksetzen + + + + Advanced Search + Erweiterte Suche + + + + Advanced + Erweitert + + + + Close All Search Results + Schließe alle Suchergebnisse + + + + ServerPage + + + + Port: + Port: + + + + Local Address + Lokale Adresse + + + + External Address + Externe Adresse + + + + Transfer Rates + Übertragungsgeschwindigkeiten + + + + Automatic (Upnp) + Automatisch (UPnP) + + + + Firewalled + Mit Firewall + + + + Manual Forwarded Port + Portweiterleitung von Hand + + + + Download (KB/s) + + + + + + kB/s + + + + + Upload (KB/s) + + + + + Show Discovery information in statusbar + Zeige Discovery-Informationen in der Statuszeile + + + + + Network Configuration + Netzwerkkonfiguration + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + Wenn Sie dies abwählen, wird RetroShare keinen Tunnel zwischen Peers aufbauen, die durch eine Firewall nicht direkt zueinander verbinden Können. Dies ist unabhängig vom "Turtle router" F2F-Routen Prinzip. + + + + Allow Tunnel Connection + Erlaube Tunnelverbindungen + + + + IP Service + IP Dienst + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + Wenn Sie dies abwählen, kann RetroShare nur ihre IP herausfinden, +wenn Sie mit jemandem verbunden sind. Wenn sie dies anwählen, +wird es helfen Verbindungen aufzubauen, trotz geringer Anzahl von Freunden. +Es hilft auch, wenn Sie sich hinter einer Firewall/VPN befinden. + + + + Allow RetroShare to ask my ip to these websites: + Erlaube RetroShare folgende Webseiten nach Ihrer IP zu fragen: + + + + Dynamic DNS + Dynamisches DNS + + + + Settings + + + Options + Optionen + + + + Transfer + Übertragung + + + + Notify + Meldungen + + + + Security + Sicherheit + + + + Appearance + Aussehen + + + + Cancel + Abbrechen + + + + OK + OK + + + + General + Allgemein + + + + Server + Server + + + + Directories + Ordner + + + + Message + Nachricht + + + + Chat + Chat + + + + Sound + Sound + + + + Forum + Forum + + + + ShareDialog + + + RetroShare Share Folder + RetroShare Ordner freigeben + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Ordner freigeben</span></p></body></html> + + + + Share Folder + Ordner + + + + Local Path + Lokaler Pfad + + + + Browse + Durchsuchen + + + + Virtual Folder + Virtueller Ordner + + + + Share Flags + Freigabe + + + + Anonymous shared Network Wide + Anonym im ganzen Netzwerk freigeben + + + + Network Wide + Netzwerkweit + + + + Browseable by Friends + Durchsuchbar von Freunden + + + + Browsable + Durchsuchbar + + + + OK + OK + + + + Cancel + Abbrechen + + + + Select A Folder To Share + Wähle einen Ordner zum Freigeben aus + + + + ShareKey + + + check peers you would like to share private publish key with + Wähle die Nachbarn, an die du den privaten Schlüssel verteilen möchtest + + + + Share Channel + Verteile Kanal + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Verteile Kanal</span></p></body></html> + + + + Share for Friend + Verteile für Freund + + + + Contacts: + Kontakte: + + + + Share + Verteilen + + + + Cancel + Abbrechen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Wähle die Freunde aus, mit denen Du den Kanal teilen möchtest.</span></p></body></html> + + + + RetroShare + + + + + Please select at least one peer + Bitte wähle mindestens einen Nachbarn + + + + ShareManager + + + Add a Share Directory + Freigabe hinzufügen + + + + Stop sharing selected Directory + Freigabe entfernen + + + + If checked, the share is anonymously shared to anybody. + Wenn aktiviert, dann ist dieser Ordner anonym feigegeben. + + + + If checked, the share is browsable by your friends. + Wenn aktiviert, dann ist dieser Ordner von Deinen Freunden durchsuchbar. + + + + Do you really want to stop sharing this directory ? + Möchtes Du die Freigabe dieses Ordners wirklich aufheben ? + + + + + Drop file error. + Dateifehler bei Drag'n'Drop. + + + + File can't be dropped, only directories are accepted. + Dateien können nicht für Drag'n'Drop genutzt werden. Nur Ordner werden akzeptiert. + + + + Directory not found or directory name not accepted. + Ordner nicht gefunden oder Ordnername nicht akzeptiert. + + + + + Remove + Entfernen + + + + Warning! + Warnung! + + + + RetroShare Share Manager + RetroShare Freigabe Manager + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Freigabe Manager</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Das ist die Liste der freigegebenen Ordner. Mit den unteren Knöpfen kannst Du neue Ordner hinzufügen oder vorhandene Ordner entfernen.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Wenn Du einen neuen Ordner hinzufügst, werden alle Dateien aus dem Ordner und Unterordnern freigegeben.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Du kannst für jeden freigegebenen Ordner die Art der Freigabe einstellen:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Durchsuchbar</span><span style=" font-family:'Sans'; font-size:8pt;">: Dateien sind von Deinen direkten Freunden durchsuchbar.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Netzwerkweit</span><span style=" font-family:'Sans'; font-size:8pt;">: Dateien können von jedem über anoynme Tunnel heruntergeladen werden.</span></p></body></html> + + + + Directory + Ordner + + + + Virtual Folder + Virtueller Ordner + + + + Network Wide + Netzwerkweit + + + + Browsable + Durchsuchbar + + + + Close + Schliessen + + + + Edit selected Shared Directory + Freigabe bearbeiten + + + + + Edit + Bearbeiten + + + + Add + Hinzufügen + + + + Shared Folder Manager + Freigabe Manager + + + + SharedFilesDialog + + + + Download + Herunterladen + + + + Splitted View + Geteiltes Fenster + + + + Friends Folders + Ordner der Freunde + + + + My Folders + Meine Ordner + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Dateien</span></p></body></html> + + + + All + Alle + + + + One day old + Einen Tag alt + + + + One Week old + Eine Woche alt + + + + One month old + Einen Monat alt + + + + Search files + Suche Dateien + + + + Start Search + Starte Suche + + + + Reset + Zurücksetzen + + + + Tree view + Baumansicht + + + + Flat view + Listenansicht + + + + check files + Prüfe Dateien + + + + + Open File + Datei öffnen + + + + Open Folder + Ordner öffnen + + + + Set command for opening this file + Setze eine Regel zum Öffnen dieser Datei + + + + Copy retroshare Link + Kopiere RetroShare Link + + + + Checking... + Überprüfe... + + + + Check files + Überprüfe Dateien + + + + Send retroshare Link + Sende RetroShare Link + + + + Copy retroshare Links to Clipboard + Kopiere RetroShare Links in die Zwischenablage + + + + Copy retroshare Links to Clipboard (HTML) + Kopiere RetroShare Links in die Zwischenablage (HTML) + + + + Send retroshare Links + Sende RetroShare Links + + + + Send retroshare Links (HTML) + Sende RetroShare Links (HTML) + + + + Send retroshare Links to Cloud + Sende RetroShare Links an die Verknüpfungs-Wolke + + + + Add Links to Cloud + Füge die Links zur Verknüpfungs-Wolke hinzu + + + + + Recommend in a message to + Empfehle in einer Nachricht an + + + + + + RetroShare Link + RetroShare Link + + + + + + + Recommendation(s) + Empfehlung(en) + + + + <strong>My Shared Files</strong> + <strong>Meine Dateien</strong> + + + + <strong>Friends Files</strong> + <strong>Dateien von Freunden</strong> + + + + <strong>Files</strong> + <strong>Dateien</strong> + + + + Download selected + Ausgewählte herunterladen + + + + SoundPage + + + Sound Events + Soundereignisse + + + + go Online + Online + + + + FileSend + Dateitransfer + + + + + Finished + Beendet + + + + FileRecive + Dateitransfer ankommend + + + + Incoming + Eingehend + + + + Chatmessage + Chatnachricht + + + + Friend + Freund + + + + + + + + Browse + Durchsuchen + + + + New Msg + Neue Nachricht + + + + SplashScreen + + + Load profile + Lade Profil + + + + Load configuration + Lade Konfiguration + + + + Create interface + Erstelle Oberfläche + + + + StartDialog + + + RetroShare + + + + + Log In + Anmelden + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + Öffnet ein Fenster zum Erstellen eines neuen Profiles oder +zum Hinzufügen von Standorten zu Deinem vorhandenen Profil. +Die aktuellen Identitäten/Standorte werden nicht geändert. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Verwalte Profile und Standorte...</span></a></p></body></html> + + + + Name (GPG Id) - location: + Name (GPG Id) - Ort: + + + + Remember Password + Passwort speichern + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"><p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Anmeldung</span></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + Login Failure + Anmeldefehler + + + + Maybe password is wrong + Vielleicht ist das Passwort falsch + + + + + Multiple instances + Mehrere Instanzen + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile + Ein laufendes RetroShare benutzt das gleiche Profil. Bitte schliesse diese Instanz oder benutze ein anderes Profil + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Ein unerwartete Fehler während des "Single instance lock" ist aufgetreten + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + + Warning + Warnung + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + Das Passwort deines SSL Zertifikates (deines Standortes) wird verschlüsselt in deinem Gnome Keyring gespeichert. + +Dein PGP wird nicht gespeichert. + +Du kannst die Auswahl in den Optionen zurücksetzen. + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + Das Passwort deines SSL Zertifikates (deines Standortes) wird verschlüsselt in der Datei keys/help.dta gespeichert- Das ist nicht sicher. + +Dein PGP wird nicht gespeichert. + +Du kannst die Auswahl in den Optionen zurücksetzen. + + + + StatisticDialog + + + Statistics + Statistiken + + + + Download + Herunterladen + + + + Session: + Sitzung: + + + + + Downloaded: + Heruntergeladen: + + + + + Count of Downloads: + Anzahl an heruntergeladenen Dateien: + + + + + + Overall + Insgesamt + + + + Upload + Hochladen + + + + + + Session + Sitzung + + + + Uploaded: + Hochgeladen: + + + + + Count of Uploads: + Anzahl an hochgeladenen Dateien: + + + + Uploaded + Hochgeladen + + + + + + + Connections: + Verbindungen: + + + + + + Peers: + Nachbarn: + + + + Uptime: + Laufzeit: + + + + + Uptime + Laufzeit + + + + Records + Rekorde + + + + Uploadspeed: + Geschwindigkeit beim Hochladen: + + + + Downloadspeed: + Geschwindigkeit beim Herunterladen: + + + + + Show Settings + Einstellungen anzeigen + + + + Reset + Zurücksetzen + + + + Receive Rate + Eingehend + + + + Send Rate + Ausgehend + + + + Always On Top + Immer obenauf + + + + 100 + 100 + + + + % Opaque + % Transparent + + + + Changes the transparency of the Bandwidth Graph + Verändert die Transparentz des Bandbreiten-Graph + + + + Save + Speichern + + + + Cancel + Abbrechen + + + + Hide Settings + Einstellungen verbergen + + + + %1 days + %1 Tage + + + + Since: + Seit: + + + + Now + Jetzt + + + + Transfer + Übertragung + + + + Session UL:DL Ratio: + Sitzung UL:DL Verhältnis: + + + + Cumulative UL:DL Ratio + Gesamt UL:DL Verhältnis + + + + Time Statistics + Zeit Statistiken + + + + Cumulative + Gesamt + + + + StatusDefs + + + + Offline + + + + + Away + Abwesend + + + + Busy + Beschäftigt + + + + Online + + + + + Idle + Untätig + + + + Friend is offline + Freund ist offline + + + + Friend is away + Freund ist abwesend + + + + Friend is busy + Freund ist beschäftigt + + + + Friend is online + Freund ist online + + + + Friend is idle + Freund ist untätig + + + + Connected + Verbunden + + + + Unreachable + Unerreichbar + + + + Available + Verfügbar + + + + Neighbour + Nachbar + + + + Trying tunnel connection + Versuche Tunnelverbindung + + + + Trying TCP + Versuche TCP + + + + Trying UDP + Versuche UDP + + + + Connected: TCP + Verbunden: TCP + + + + Connected: UDP + Verbunden: UDP + + + + Connected: Tunnel + Verbunden: Tunnel + + + + Connected: Unknown + Verbunden: Unbekannt + + + + DHT: Contact + DHT: Kontakt + + + + StatusMessage + + + Personal message + Status Nachricht + + + + Status message + Statusnachricht + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Statusnachricht </span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Bitte geben sie ihre Statusnachricht ein</span></p></body></html> + + + + OK + OK + + + + Cancel + Abbrechen + + + Paste RetroShare Link + RetroShare Link einfügen + + + + StyleDialog + + + Define Style + Definiere Farben + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Definiere Farben</span></p></body></html> + + + + + Choose color + Farbe wählen + + + + Color 2 + Farbe 2 + + + + Color 1 + Farbe 1 + + + + Style + Stil + + + + None + Kein + + + + Solid + Farbe + + + + Gradient + Farbverlauf + + + + SubDestItem + + + Delete FeedItem + Nachricht löschen + + + + SubFileItem + + + %p Kb + %p Kb + + + + Save File + Datei speichern + + + + Cancel Download + Download abbrechen + + + + Download File + Datei herunterladen + + + + + + Play File + Datei abspielen + + + + Save Channel File + Channel Datei speichern + + + + Download + Herunterladen + + + + Play + Abspielen + + + + + ERROR + FEHLER + + + + EXTRA + EXTRA + + + + REMOTE + ENTFERNT + + + + DOWNLOAD + DOWNLOAD + + + + LOCAL + LOKAL + + + + UPLOAD + UPLOAD + + + + File %1 does not exist at location. + Datei %1 existiert nicht. + + + + File %1 is not completed. + Datei %1 ist nicht komplett. + + + + TBoard + + + Pause + Pause + + + + TagDefs + + + Important + Wichtig + + + + Work + Dienstlich + + + + Personal + Persönlich + + + + Todo + Zu erledigen + + + + Later + Später + + + + TagsMenu + + + Remove All Tags + Alle Schlagwörter entfernen + + + + New tag ... + Neues Schlagwort... + + + + TextPage + + + Use text representation of the PGP certificates. + Verwende diesen Text als PGP Zertifikat. + + + + The text below is your PGP certificate. You have to provide it to your friend + Der folgende Text ist Ihr PGP Zertifikat. Sie können es zu Ihrem Freund geben + + + + Save your Cert into a File + Zertifikat als Datei speichern + + + + Please, paste your friends PGP certificate into the box below + Bitte füge das PGP-Zertifikat von Ihre Freunde in das Feld unten ein + + + + Clean certificate + Bereinige Zertifikat + + + + Save as... + Speichern unter... + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare Zertifikat (*.rsc );;Alle Dateien (*) + + + + You can copy this text and send it to your friend via email or some other way + Du kannst diesen Text kopieren und an deinen Freund per Email senden oder über einen anderen Weg zukommen lassen + + + + RetroShare + + + + + Text certificate + Text-Zertifikat + + + + Copy your Cert to Clipboard + Kopiere dein Zertifikat in die Zwischenablage + + + + Run Email program + Starte das Standard-Emailprogramm + + + + Connect Friend Help + Verbindungshilfe + + + + Certificate Load Failed + Das Zertifikat konnte nicht geladen werden + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + Dein Zertiifkat ist in in die Zwischenablage kopiert worden + + + + RetroShare Invite + RetroShare Einladung + + + + TransferPage + + + Transfer options + Übertragungsoptionen + + + + Queue Size: + Warteschlangengröße: + + + + Default chunk strategy: + Standard Block Strategie: + + + + Streaming + Streaming + + + + Random + Zufall + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + Safety disk space limit : + Sicherheitsgrenze Festplattenspeicher: + + + + MB + + + + + TransfersDialog + + + Cancel + Abbrechen + + + + Clear Completed + Fertige ausblenden + + + + + Status + Status + + + + Completed + Fertiggestellt + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + Show cache transfers + Zeige Cache Übertragungen + + + + Uploads + + + + + Selected transfer + Transfer + + + + Done + Fertig + + + + Active + Aktiv + + + + Outstanding + Ausstehend + + + + + Name + i.e: file name + Name + + + + + Size + i.e: file size + Grösse + + + + Speed + i.e: Download speed + Geschwindigkeit + + + + Progress / Availability + i.e: % downloaded + Fortschritt / Verfügbarkeit + + + + Sources + i.e: Sources + Quellen + + + + Core-ID + Kern-ID + + + + Progress + i.e: % uploaded + Fortschritt + + + + Speed + i.e: upload speed + Geschwindigkeit + + + + Transferred + Übertragen + + + + Play + Abspielen + + + + Pause + Pause + + + + Resume + Fortsetzen + + + + Open Folder + Ordner öffnen + + + + Open File + Datei öffnen + + + + Preview File + Vorschau + + + + Details... + Details... + + + + Down + Runter + + + + Up + Hoch + + + + Top + Anfang + + + + Bottom + Ende + + + + Priority (Speed)... + Prioritä t(Geschwindigkeit)... + + + + Streaming + Streaming + + + + Random + Zufall + + + + Chunk strategy + Blockstrategie + + + + Queued + In Warteschleife + + + + Paused + Pausiert + + + + Transferring + Übertrage + + + + RetroShare + + + + + Details: + Details: + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + Öffne Übertragung + + + + File %1 is not completed. If it is a media file, try to preview it. + Datei %1 ist nicht komplett. Wenn es eine Media Datei ist dann versuche "Vorschau". + + + + Are you sure that you want to cancel and delete these files? + Soll dieser Download wirklich abgebrochen und gelöscht werden? + + + + Speed / Queue position + Geschwindigkeits- / Warteschlangenposition + + + + Remaining + Verbleibend + + + + Download time + i.e: Estimated Time of Arrival / Time left + Download Zeit + + + + Peer + i.e: user name + Nachbar + + + + Hash + Prüfsumme + + + + Router Statistics + Router Statistiken + + + + Router Requests + + + + + Copy RetroShare Link + Kopiere RetroShare Link + + + + Paste RetroShare Link + RetroShare Link einfügen + + + + + Slower + Langsamer + + + + + + Average + Durchschnitt + + + + + Faster + Schneller + + + + Move in Queue... + Verschiebe in Warteschlange... + + + + + + Failed + Gescheitert + + + + + + Okay + OK + + + + + Waiting + Warte + + + + Downloading + Ladend + + + + + + + Complete + Vollständig + + + + Unknown + Unbekannt + + + + version: + Version: + + + + Uploading + Hochladend + + + + Checking... + Überprüfe... + + + + Force Check + Erzwinge Überprüfung + + + + TreeStyle_RDM + + + + FILE + DATEI + + + + Files + Dateien + + + + File + Datei + + + + + DIR + ORDNER + + + + Friends Directories + Dateien von Freunden + + + + My Directories + Meine Ordner + + + + Size + Grösse + + + + Age + Alter + + + + Friend + Freund + + + + Share Type + Freigabe Typ + + + + What's new + Was ist neu + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + Anzeige: Ganzes Netzwerk + + + + This table normaly auto-updates every 10 seconds. + Diese Tabelle wird normalerweise alle 10 Sekunden neu geladen. + + + + Self + Selbst + + + + Trust + Vertrauen + + + + is authenticated (one way) by + ist authentifiziert (ein Weg) von + + + + Half + Halb + + + + authenticated himself + authentifizierte sich selbst + + + + authenticated each other + authentifizierten sich einander + + + + Full + Voll + + + + + peers, including him(her)self. + Nachbarn, dich selber eingeschlossen. + + + + is authenticated by + ist authentifiziert von + + + + authenticated + authentifiziert + + + + Showing: peers connected to + Anzeige: Nachbarn verbunden zu + + + + TurtleRouterDialog + + + + Search requests + Suchanfragen + + + + + Tunnel requests + Tunnelanfragen + + + + TurtleRouterDialogForm + + + Router Statistics + Router Statistiken + + + + F2F router information + F2F Routerinformationen + + + + TurtleRouterStatistics + + + Router Statistics + Router Statistiken + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + ULListDelegate + + + B + B + + + + KB + kB + + + + MB + MB + + + + GB + GB + + + + VMessageBox + + + OK + OK + + + + Cancel + Abbrechen + + + + Yes + Ja + + + + No + Nein + + + + Help + Hilfe + + + + Retry + Erneut versuchen + + + + Show Log + Log anzeigen + + + + Show Settings + Einstellungen anzeigen + + + + Continue + Fortsetzen + + + + Quit + Schliessen + + + + Browse + Durchsuchen + + + + misc + + + Unknown + Unknown (size) + Unbekannt + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + Unbekannt + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + %1 Minuten + + + + %1h %2m + e.g: 3hours 5minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + k + + + + M + e.g: 3.1 M + M + + + + G + e.g: 3.1 G + G + + + + T + e.g: 3.1 T + T + + + diff --git a/retroshare-gui/src/lang/retroshare_en.qm b/retroshare-gui/src/lang/retroshare_en.qm new file mode 100644 index 000000000..be651eede --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_en.qm @@ -0,0 +1 @@ + + + + + AboutDialog + + + About RetroShare + + + + + About + + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + + + + + Sorry, can't determine system default command for this file + + + + + + AddLinksDialog + + + + Add Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + Add Anonymous Link + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Search Criteria + + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + Cancels the search. + + + + + Cancel + + + + + Perform the advanced search. + + + + + Search + + + + + AppearancePage + + + Language + + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + + + Style + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + + + Style Sheet + + + + + ApplicationWindow + + + + RetroShare + + + + + Statistics + + + + + Photo View + + + + + Games Launcher + + + + + Shared Calendars + + + + + Hide + + + + + Show + + + + + AttachFileItem + + + Form + + + + + %p Kb + + + + + Cancel Download + + + + + BandwidthGraph + + + RetroShare Bandwidth Usage + + + + + + Show Settings + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always on Top + + + + + Style + + + + + Changes the transparency of the Bandwidth Graph + + + + + 100 + + + + + % Opaque + + + + + Save + + + + + Cancel + + + + + Since: + + + + + Hide Settings + + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + + + + + Close + + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + + Expand + + + + + Remove Item + + + + + Unsubscribe From Channel + + + + + Comments here + + + + + Comment + + + + + Hide + + + + + CalDialog + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Remove + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + Browse + + + + + Select Certificate + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + + + + RetroShare + + + + + Sorry, create certificate failed + + + + + Please choose a filename + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + + + + + Play + + + + + Unsubscribe From Channel + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + + + + + ChanNewItem + + + Subscribe to Channel + + + + + Expand + + + + + Remove Item + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Popularity + + + + + Last Post + + + + + Channel ID + + + + + Channel Description + + + + + Type + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + + + + + OK + + + + + Close + + + + + ChannelFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Create Channel + + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe To Channel + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + + + Post to Channel + + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + + Start Chat + + + + + Send + + + + + Cancel + + + + + Quick Message + + + + + ChatPage + + + General + + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Emoticons Group Chat + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + + + + + Details about your friend : + + + + + Peer details + + + + + Key validity: + + + + + Name: + + + + + Email: + + + + + Loc: + + + + + Signers + + + + + Options + + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + ConfCertDialog + + + Friend Details + + + + + Details + + + + + Peer Info + + + + + Name + + + + + Peer ID + + + + + Last Contact + + + + + Version + + + + + Loc + + + + + RetroShare ID + + + + + Status + + + + + Peer Address + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port + + + + + Addresses list + + + + + Trust + + + + + Your trust in this peer is: + + + + + None + + + + + Marginal + + + + + Full + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + + Sign GPG key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Deny Friend + + + + + Make Friend + + + + + Certificate + + + + + Apply and Close + + + + + OK + + + + + Cancel + + + + + + RetroShare + + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + + + + + Description + + + + + Type: + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Name + + + + + Description + + + + + Type: + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authenticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + Create + + + + + Please add a Name + + + + + CreateForumMsg + + + Post Forum Message + + + + + Forum + + + + + Subject + + + + + Attach File + + + + + Sign Message + + + + + + Paste RetroShare Link + + + + + Forum Post + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Close + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + RetroShare + + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + + + + + + General + + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + + + + + Cancel + + + + + Rating + + + + + File Name + + + + + Not Rated + + + + + No Comments + + + + + DirectoriesPage + + + Incoming Directory + + + + + + Browse + + + + + Partials Directory + + + + + Shared Directories + + + + + Automatically share incoming directory (Recommended) + + + + + Edit Share + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + + + # + + + + + Status + + + + + Person + + + + + Auto Connect + + + + + Trust Level + + + + + Peer Address + + + + + Last Contact + + + + + Organisation + + + + + Location + + + + + Country + + + + + Person Id + + + + + Auth Code + + + + + Vote Up + + + + + Vote Down + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + File size + + + + + + + + bytes + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + OK + + + + + Apply and Close + + + + + ForumMsgItem + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Expand + + + + + Remove Item + + + + + Send + + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Subscribe to Forum + + + + + Expand + + + + + Remove Item + + + + + Forum Description + + + + + ForumPage + + + Misc + + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Display + + + + + Create Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Title + + + + + + Date + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Previous Thread + + + + + Next Thread + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + + + + + Content + + + + + Reply Message + + + + + Start new Thread for Selected Forum + + + + + Print + + + + + PrintPreview + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Mark all as read + + + + + Mark all as unread + + + + + Reply + + + + + + Start New Thread + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + + Mark as read + + + + + + with children + + + + + + Mark as unread + + + + + Hide + + + + + Expand + + + + + AUTHD + + + + + + RetroShare + + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + + + + + Status + + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + + + + + Clear Chat History + + + + + + Add Friend + + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + + + + + Certificates (*.pqi) + + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GamesDialog + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + + + + + Status + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Accept + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + GenCertDialog + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + + Your profile is associated to a GPG key + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + Generate New Profile + + + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + + + + + Certificates (*.pqi *.pem) + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + GeneralPage + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + + + + + + + %1 KB/s + + + + + Sent: + + + + + %1 KB + + + + + %1 MB + + + + + %1 GB + + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + + + + + Description + + + + + Reset + + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + + + + + Size + + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + + Search + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Home + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close + + + + + Close Vidalia Help + + + + + Esc + + + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + HelpDialog + + + About + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + Thanks to + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + Unable to Open Link + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + + + + + + Copy + + + + + Remove + + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Make friend with selected friends of my friends + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + LinksDialog + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + From + + + + + All Peers + + + + + Own Links + + + + + Show + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Add new link + + + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + + + + + Expand + + + + + Hide + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + MainWindow + + + MainWindow + + + + + Add Friend + + + + + Add a Friend Wizard + + + + + Add Share + + + + + + Options + + + + + Messenger + + + + + About + + + + + SMPlayer + + + + + Quit + + + + + + Quick Start Wizard + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Network + + + + + Friends + + + + + Search + + + + + + Transfers + + + + + Files + + + + + + Messages + + + + + + Channels + + + + + Blogs + + + + + + Forums + + + + + Links Cloud + + + + + Plugins + + + + + Unfinished + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Show/Hide + + + + + Status + + + + + Open Messenger + + + + + Open Messages + + + + + Bandwidth Graph + + + + + Applications + + + + + Help + + + + + Minimize + + + + + Maximize + + + + + &Quit + + + + + RetroShare + + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + You have %1 new message + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Do you really want to exit RetroShare ? + + + + + Really quit ? + + + + + Internal Error + + + + + Hide + + + + + Show + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + + MessageComposer + + + + Compose + + + + + + Contacts + + + + + Search for Name: + + + + + Search Friends + + + + + Reset + + + + + Send To: + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Paragraph + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Underline + + + + + Subject: + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + + + + + File Name + + + + + Size + + + + + Hash + + + + + Send + + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + Friend Recommendation(s) + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + + <b>1 new Message from</b> + + + + + Close + + + + + Subject + + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + + + + + Size + + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + + + + + Download all + + + + + Hide + + + + + Expand + + + + + File + + + + + Files + + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + + + + + Compose + + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + + + + + Compose + + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + Print + + + + + Display + + + + + Reset + + + + + Attachments + + + + + + Subject + + + + + + + From + + + + + + Date + + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + + + + + + + + Outbox + + + + + Draft + + + + + + Sent + + + + + + + + Trash + + + + + Quick View + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + + Reply to Message + + + + + + Reply to All + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Mark as read + + + + + Mark as unread + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Remove Message + + + + + Undelete + + + + + Empty trash + + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + + + + + + Total: + + + + + MessengerWindow + + + RetroShare Messenger + + + + + Click to Change your Avatar + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + Search Friends + + + + + Reset + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Hide Offline Friends + + + + + Sort by State + + + + + Expand all + + + + + Collapse all + + + + + Chat + + + + + Message Friend + + + + + Connect To Friend + + + + + Peer Details + + + + + Recomend this Friend to... + + + + + Paste RetroShare Link + + + + + Export Friend + + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>RetroShare instance</strong> + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + Save Certificate + + + + + Certificates (*.pqi) + + + + + MsgItem + + + + Expand + + + + + Remove Item + + + + + Reply to Message + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + + + + + NATStatus + + + <strong>NAT:</strong> + + + + + OK | RetroShare Server + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + NetworkDialog + + + Network + + + + + + + Name + + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + + Did peer authenticated me + + + + + + Cert Id + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Search Network + + + + + Clear Filter + + + + + Peer ID + + + + + Show keys that are not validated by the GPG web of trust + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Unknown + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + + yourself + + + + + NetworkView + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + + + + + Options + + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + + + + + Forums + + + + + Blogs + + + + + Messages + + + + + Chat + + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + + + Expand + + + + + Remove Item + + + + + Write a quick Message + + + + + Chat + + + + + Start Chat + + + + + Cancel + + + + + Send + + + + + Name: + + + + + Peer ID: + + + + + Trust: + + + + + Location + + + + + IP Address + + + + + Connection Method + + + + + Status: + + + + + Write Message + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + + + + + PhotoDialog + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + + Date + + + + + + Location + + + + + Size + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + Insert Show Lists + + + + + Open + + + + + Remove + + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + PhotoShow + + + Photo Show + + + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Back + + + + + Start + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + + Close + + + + + Attach a Picture + + + + + Add a File for your Friend + + + + + Send + + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Strike + + + + + Clear Chat History + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Friend not Online + + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Paste RetroShare Link + + + + + is typing... + + + + + Hide Avatar + + + + + Show Avatar + + + + + Do you really want to physically delete the history? + + + + + Add Extra File + + + + + Load Picture File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + Messages you send will be delivered after Friend is again Online + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + ProfileView + + + Profile View + + + + + + Name + + + + + Peer ID + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + + Edit Profile + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Size + + + + + Hash + + + + + Close Profile + + + + + Clear Photo + + + + + Change Photo + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + + + + + RetroShare + + + + + Error : cannot get peer details. + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + The following has not been added to your download list, because you already have it: + + + + + + + RetroShare + + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + Start with a RetroShare link is only supported for Windows. + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your download speed limit: + + + + + + KB/s + + + + + Choose your upload speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + + + + + Directories + + + + + Server + + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid language code specified: + + + + + Invalid GUI style specified: + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Any + + + + + Archive + + + + + Audio + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Video + + + + + Directory + + + + + Enter a Keyword here + + + + + Reset + + + + + Start Search + + + + + Search + + + + + Advanced Search + + + + + Advanced + + + + + KeyWords + + + + + Results + + + + + Search Id + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + + + + + File Size + + + + + Filename + + + + + Size + + + + + Sources + + + + + Type + + + + + Age + + + + + Hash + + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Enter a keyword here (at least 3 char long) + + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Remove + + + + + Remove All + + + + + + Folder + + + + + New RetroShare Link(s) + + + + + ServerPage + + + + Network Configuration + + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Transfer Rates + + + + + Download (KB/s) + + + + + + kB/s + + + + + Upload (KB/s) + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + + Settings + + + Options + + + + + General + + + + + Server + + + + + Transfer + + + + + Directories + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + Cancel + + + + + OK + + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browseable by Friends + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + OK + + + + + Cancel + + + + + Select A Folder To Share + + + + + ShareKey + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + check peers you would like to share private publish key with + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + + + + + Please select at least one peer + + + + + ShareManager + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add a Share Directory + + + + + Add + + + + + Stop sharing selected Directory + + + + + + Remove + + + + + Close + + + + + Edit selected Shared Directory + + + + + + Edit + + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + SharedFilesDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + + Download + + + + + check files + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + SoundPage + + + Sound Events + + + + + Friend + + + + + go Online + + + + + + + + + Browse + + + + + Chatmessage + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Name (GPG Id) - location: + + + + + Remember Password + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Download + + + + + Session: + + + + + + Downloaded: + + + + + + Count of Downloads: + + + + + + + Overall + + + + + Upload + + + + + + + Session + + + + + Uploaded: + + + + + + Count of Uploads: + + + + + Uploaded + + + + + + + + Connections: + + + + + + + Peers: + + + + + Time Statistics + + + + + + Uptime + + + + + Since: + + + + + Cumulative + + + + + Records + + + + + Uploadspeed: + + + + + Downloadspeed: + + + + + Uptime: + + + + + + Show Settings + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always On Top + + + + + 100 + + + + + % Opaque + + + + + Changes the transparency of the Bandwidth Graph + + + + + Save + + + + + Cancel + + + + + %1 days + + + + + Hide Settings + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + + + + + Cancel + + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + + Delete FeedItem + + + + + SubFileItem + + + %p Kb + + + + + Cancel Download + + + + + Download File + + + + + Download + + + + + + + Play File + + + + + Play + + + + + Save File + + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Text certificate + + + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Please, paste your friends PGP certificate into the box below + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + + + + + Active + + + + + Outstanding + + + + + + Name + i.e: file name + + + + + + Size + i.e: file size + + + + + Completed + + + + + Speed + i.e: Download speed + + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + + + + + + Status + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Core-ID + + + + + Peer + i.e: user name + + + + + Progress + i.e: % uploaded + + + + + Speed + i.e: upload speed + + + + + Transferred + + + + + Hash + + + + + Router Statistics + + + + + Router Requests + + + + + Pause + + + + + Resume + + + + + Force Check + + + + + Cancel + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Clear Completed + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Streaming + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Random + + + + + Play + + + + + Move in Queue... + + + + + Priority (Speed)... + + + + + Chunk strategy + + + + + + + Failed + + + + + + + Okay + + + + + Transferring + + + + + + + + Complete + + + + + + Waiting + + + + + Downloading + + + + + Queued + + + + + Paused + + + + + Checking... + + + + + Unknown + + + + + version: + + + + + Uploading + + + + + Are you sure that you want to cancel and delete these files? + + + + + RetroShare + + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + is authenticated by + + + + + + peers, including him(her)self. + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + + + + + Cancel + + + + + Yes + + + + + No + + + + + Help + + + + + Retry + + + + + Show Log + + + + + Show Settings + + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + diff --git a/retroshare-gui/src/lang/retroshare_es.qm b/retroshare-gui/src/lang/retroshare_es.qm new file mode 100644 index 000000000..cd19301d5 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_es.qm differ diff --git a/retroshare-gui/src/lang/retroshare_es.ts b/retroshare-gui/src/lang/retroshare_es.ts new file mode 100644 index 000000000..f54daec66 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_es.ts @@ -0,0 +1,12613 @@ + + + + + AboutDialog + + + About RetroShare + Acerca de RetroShare + + + + About + Acerca de + + + + close + Cerrar + + + + + About RetroShare %1 + Acerca de RetroShare %1 + + + + Max score: %1 + Máxima puntuación: %1 + + + + Score: %1 + Puntuación: %1 + + + + Level: %1 + Nivel: %1 + + + + Have fun ;-) + Diviértete ;-) + + + + AddFileAssociationDialog + + + File type(extension): + Tipo de archivo (extención): + + + + Use default command + Usar comando por defecto + + + + Command + Comando + + + + RetroShare + RetroShare + + + + Sorry, can't determine system default command for this file + + Perdona, no se ha encontrado el comando por defecto del sistema para este archivo + + + + + AddLinksDialog + + + + Add Link + Añadir enlace + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Añadir enlace a la nube</span></p></body></html> + + + + Cancel + Cancelar + + + + Add a new Link + Añadir nuevo enlace + + + + Title: + Título: + + + + Url: + URL: + + + + Add Anonymous Link + Añadir enlace anónimo + + + + +2 Great! + +2 Excelente! + + + + +1 Good + +1 Bueno + + + + 0 Okay + 0 Regular + + + + -1 Sux + -1 Mal + + + + -2 Bad Link + -2 Muy mal + + + + Add Link Failure + Error añadiendo enlace + + + + Missing Link and/or Title + Enlace y/o título ausente + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + RetroShare: Búsqueda avanzada + + + + Search Criteria + Criterios de búsqueda + + + + Add a further search criterion. + Añadir otro criterio de búsqueda. + + + + Reset the search criteria. + Reiniciar los critérios de búsqueda. + + + + Cancels the search. + Cancela la búsqueda. + + + + Cancel + Cancelar + + + + Perform the advanced search. + Ejacuta la búsqueda avanzada. + + + + Search + Buscar + + + + AppearancePage + + + Language + Idioma + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">¡Los cambios de idioma tomarán efecto después de reiniciar Retroshare!</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Elegir el idioma usado en Retroshare</p></body></html> + + + + Style + Estilo + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Elegir el estilo del interfaz de Retroshare</p></body></html> + + + + Style Sheet + Hoja del estilo + + + + ApplicationWindow + + + + RetroShare + RetroShare + + + + Statistics + Estadística + + + + Photo View + Visor de imágenes + + + + Games Launcher + Lanzador de juegos + + + + Shared Calendars + Calendarios compartidos + + + + Hide + Esconder + + + + Show + Mostrar + + + + AttachFileItem + + + Form + Formulario + + + + %p Kb + %p Kb + + + + Cancel Download + Cancelar descarga + + + + BandwidthGraph + + + RetroShare Bandwidth Usage + RetroShare uso de la red + + + + + Show Settings + Demostrar ajustes + + + + Reset + Reiniciar + + + + Receive Rate + Recibiendo + + + + Send Rate + Enviando + + + + Always on Top + Siempre encima + + + + Style + Estilo + + + + Changes the transparency of the Bandwidth Graph + Cambia la transparencia del gráfico de tráfico de la red + + + + 100 + 100 + + + + % Opaque + % transparente + + + + Save + Guardar + + + + Cancel + Cancelar + + + + Since: + Desde: + + + + Hide Settings + Esconder ajustes + + + + BlogDetails + + + + Blog Details + Detalles del blog + + + + Blog Info + Información sobre el blog + + + + Blog Name + Nombre de blog + + + + Popularity + Popularidad + + + + Last Post + Última entrada + + + + Blog ID + Blog ID + + + + Blog Description + Descripción del blog + + + + Cancel + Cancelar + + + + OK + OK + + + + Close + Cerrar + + + + BlogMsgItem + + + Form + Formulario + + + + Remove Item + Quitar objeto + + + + Expand + Abrir + + + + Subject + Asunto + + + + Play Media + Reproducir medio + + + + BlogNewItem + + + Remove Item + Quitar objeto + + + + Subscribe to Blog + Suscribir blog + + + + Expand + Abrir + + + + Blog Decscription + Descripción del blog + + + + BlogsDialog + + + Form + Formulario + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + Add + Añadir + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Añadir entrada al Blog</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Nombre del Blog</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Anular suscripción del blog</span></p></body></html> + + + + Unsubscribe + Anular suscripción + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Suscribir al Blog</span></p></body></html> + + + + Subscribe + Suscribir + + + + + Create New Blog + Crear nuevo blog + + + + Name + Nombre + + + + ID + ID + + + + Own Blogs + Blogs propios + + + + Subscribed Blogs + Blogs suscritos + + + + Popular Blogs + Blogs populares + + + + Other Blogs + Otros Blogs + + + + Post to Blog + Crear entrada + + + + Subscribe to Blog + Suscribir blog + + + + Unsubscribe to Blog + Anular suscripción del blog + + + + Show Blog Details + Mostrar detalles del blog + + + + Create a new Blog + Crear nuevo blog + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + Popularidad: %1 Descargado: %2 Disponible: %3 + + + + BlogsMsgItem + + + Form + Formulario + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Tema del blog</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Fecha</span></p></body></html> + + + + + Expand + Abrir + + + + Remove Item + Quitar objeto + + + + Unsubscribe From Channel + Anular suscripción del canal + + + + Comments here + Comentarios aquí + + + + Comment + Comentario + + + + Hide + Esconder + + + + CalDialog + + + Form + Formulario + + + + Local Calendars + Calendarios locales + + + + Shared Calendar List + Lista de calendarios compartidos + + + + Share Details + Compartir detalles + + + + Name: + Nombre: + + + + Location: + Lugar: + + + + ... + ... + + + + Status: + Estado: + + + + Private + Privado + + + + Public + Público + + + + Allow List: + Lista "permitido": + + + + <Disabled> + <Desactivado> + + + + Add + Añadir + + + + Remove + Quitar + + + + Peer Calendars + Calendarios de vecinos + + + + CertificatePage + + + Certificate files + Archivos de certificados GPG + + + + Use PGP certificates saved in files. + Usar certificados GPG guardados en archivos. + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + Tienes que generar un archivo de tu certificado GPG y mandaselo a tu amigo. Tambien puedes usar un archivo generado antes. + + + + Export my certificate... + Exportar mi certificado GPG... + + + + Import friend's certificate... + Importar certificado GPG de un amigo... + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + Arrastra el certificado GPG de un amigo a esta ventana o localizalo en campo abajo + + + + Browse + Navegar + + + + Select Certificate + Seleccionar certificado + + + + + RetroShare Certificate (*.rsc );;All Files (*) + Certificados GPG de RetroShare (*.rsc );;Todos los archivos (*) + + + + + + + RetroShare + RetroShare + + + + Sorry, create certificate failed + Lo siento, creación de certificado GPG ha fallado + + + + Please choose a filename + Por favor elige un nombre para el archivo + + + + Certificate file successfully created + Certificado GPG creado con exito + + + + + Sorry, certificate file creation failed + Lo siento, creación del archico de certificados GPG ha fallado + + + + Certificate Load Failed:something is wrong with %1 + Abrir certificado GPG ha fallado: algo va mal con %1 + + + + Certificate Load Failed:can't read from file %1 + Abrir certificado GPG ha fallado: no puedo leer el archivo %1 + + + + Certificate Load Failed:file %1 not found + Abrir certificado GPG ha fallado: archivo %1 no encontrado + + + + ChanMsgItem + + + Toggle Message Read Status + Cambiar estado del mensaje + + + + New + Nuevo + + + + Download + Descargar + + + + Play + Reproducir + + + + Unsubscribe From Channel + Anular suscripción del canal + + + + Remove Item + Quitar objeto + + + + + Expand + Abrir + + + + Copy RetroShare Link + Copiar enlace RetroShare + + + + Channel Feed + Canal + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + Aviso! Tienes menos de %1 horas y %2 minutos para que se borre este archivo. Considera guardarlo. + + + + Hide + Esconder + + + + ChanNewItem + + + Subscribe to Channel + Suscribir canal + + + + Expand + Abrir + + + + Remove Item + Quitar objeto + + + + Channel Decscription + Descripción del canal + + + + Unknown Channel + Canal desconocido + + + + New Channel + Canal nuevo + + + + Updated Channel + Canal actualizado + + + + ChannelDetails + + + + Channel Details + Detalles del canal + + + + Channel Info + Información sobre el canal + + + + Channel Name + Nombre del canal + + + + Popularity + Popularidad + + + + Last Post + Última entrada + + + + Channel ID + Canal ID + + + + Channel Description + Descripción del canal + + + + Type + Tipo + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Restringido - Cualquiera puede leer, publicación limitada (Llave de publicación privada) + + + + Private - (Private Publish Key required to view Messages) + Privado - (Llave de publicación privada necesaria para leer mensajes) + + + + Cancel + Cancelar + + + + OK + OK + + + + Close + Cerrar + + + + ChannelFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Canales</span></p></body></html> + + + + Display + Mostrar + + + + Create Channel + Crear canal + + + + Unsubcribe To Channel + Anular suscripción + + + + Unsubscribe + Anular suscripción + + + + Subscribe To Channel + Suscribir canal + + + + Subscribe + Suscribir + + + + Set all to read + Marcar todos como leido + + + + Enable Auto-download + Activar descarga automatica + + + + + Post to Channel + Crear entrada + + + + Own Channels + Canales propios + + + + Subscribed Channels + Canales suscritos + + + + Popular Channels + Canales populares + + + + Other Channels + Otros canales + + + + Subscribe to Channel + Suscribir canal + + + + Unsubscribe to Channel + Anular suscripción del canal + + + + Show Channel Details + Mostrar detalles del canal + + + + Restore Publish Rights for Channel + Restituir derechos de publicación para el canal + + + + Edit Channel Details + Cambiar detalles del canal + + + + Share Channel + Compartir llave de publicación privada del canal + + + + Copy RetroShare Link + Copiar enlace RetroShare + + + + No Channel Selected + Ningún canal seleccionado + + + + Disable Auto-Download + Desactivar descarga automatica + + + + Enable Auto-Download + Activar descarga automatica + + + + ChatMsgItem + + + Remove Item + Quitar objeto + + + + Write a quick Message + Escribir un mensaje instantaneo + + + + Send Mail + Enviar correo + + + + Write Message + Escribir mensaje + + + + + Start Chat + Iniciar chat + + + + Send + Enviar + + + + Cancel + Cancelar + + + + Quick Message + Mensaje instantaneo + + + + ChatPage + + + General + General + + + + Chat Settings + Ajustes del chat + + + + Enable Emoticons Privat Chat + Activar emoticónes para el chat privado + + + + Chat Font + Tipo de letra del chat + + + + Change Chat Font + Cambiar el tipo de letra del chat + + + + Chat Font: + Tipo de letra del chat: + + + + Enable Emoticons Group Chat + Activar emoticónes para el chat público + + + + Enable Private Chat History + Activar historia del chat privado + + + + Enable Group Chat History + Activar historia del chat público + + + + Send message with Ctrl+Return + Enviar mensajes con Ctrl+Intro + + + + Chat History + Historia del chat + + + + Load number of messages (0 = off) + Cargar numero de mensajes (0 = desactivado) + + + + Group Chat + Chat de grupo + + + + Private Chat + Chat privado + + + + Style + Estilo + + + + Group chat + Chat de grupo + + + + + + Variant + Estilo + + + + + + Author: + Autor: + + + + + + Description: + Descripción: + + + + Private chat + Chat privado + + + + History + Historia + + + + Incoming message in history + Mensajes recibidos en historia + + + + Outgoing message in history + Mensajes enviados en historia + + + + Incoming message + Mensaje recibido + + + + Outgoing message + Mensaje enviado + + + + Outgoing offline message + Mensaje enviado sin conexión + + + + ChatStyle + + + Standard style for group chat + Estilo estándar del chat público + + + + Standard style for private chat + Estilo estándar del chat privado + + + + Standard style for history + Estilo estándar de la historia + + + + ConclusionPage + + + Make Friend + Hacer amigo + + + + Details about your friend : + Detalles de tu amigo: + + + + Peer details + Detalles del vecino + + + + Key validity: + Validez de la llave: + + + + Name: + Nombre: + + + + Email: + Email: + + + + Loc: + Lugar: + + + + Signers + Firmantes + + + + Options + Opciones + + + + Add friend to group: + Añadir amigo a grupo: + + + + Authenticate friend (Sign GPG Key) + Autentificar amigo (firmar llave GPG) + + + + Add as friend to connect with + Añadir como amigo a quién connectar + + + + It seems your friend is already registered. Adding it might just set it's ip address. + Parece que tu amigo ya está registrado. Volver a añadirle solamente cambiaría su dirección IP. + + + + ConfCertDialog + + + Friend Details + Detalles del amigo + + + + Details + Detalles + + + + Peer Info + Información sobre el vecino + + + + Name + Nombre + + + + Peer ID + ID del vecino + + + + Last Contact + Último contacto + + + + Version + Versión + + + + Loc + Lugar + + + + RetroShare ID + ID de RetroShare + + + + Status + Estado + + + + Peer Address + Dirección del vecino + + + + Local Address + Dirección local + + + + External Address + Dirección externa + + + + Dynamic DNS + DNS dinámico + + + + + Port + Puerto + + + + Addresses list + Lista de direcciones + + + + Trust + Confianza + + + + Your trust in this peer is: + Tu confianza en ese vecino es: + + + + None + Ningún + + + + Marginal + Marginal + + + + Full + Lleno + + + + GPG Key + Llave GPG + + + + Peer has signed my GPG key + Vecino ha firmado mi llave GPG + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + La llave GPG del vecino está firmado por: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Firmar la llave GPG de un amigo es expresar tu confianza en el a otros amigos. Aparte de eso, solo amigos con llaves GPG firmados por ti recibirán información sobre tus otros amigos.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Firmar una llave GPG no se puede deshacer, así que firma concienzudamente.</p></body></html> + + + + + Sign GPG key + Firmar llave GPG + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Firmar la llave GPG de un amigo es expresar tu confianza en el a otros amigos. Aparte de eso, solo amigos con llaves GPG firmados por ti recibirán información sobre tus otros amigos.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Firmar una llave GPG no se puede deshacer, así que firma concienzudamente.</p></body></html> + + + + Deny Friend + Bloquear amigo + + + + Make Friend + Hacer amigo + + + + Certificate + Certificado + + + + Apply and Close + Aplicar y cerrar + + + + OK + OK + + + + Cancel + Cancelar + + + + + RetroShare + RetroShare + + + + + Error : cannot get peer details. + Error: No se pueden obtener los detalles del vecino. + + + + Your key is signed by : + Tu llave GPG está firmado por: + + + + Peer key is signed by : + La llave GPG del vecino está firmado por: + + + + Your trust in this peer is ultimate, it's probably a key you own. + Tu confianza en este vecino es máximo, probablemente una llave GPG que te pertenece. + + + + Your trust in this peer is full. + Tienes plena confianza en este vecino. + + + + Your trust in this peer is marginal. + Tienes confianza en este vecino. + + + + Your trust in this peer is none. + No tienes confianaz en este vecino. + + + + Your trust in this peer is not set. + No has determinado el nivel de confianza en este vecino. + + + + Peer has authenticated me as a friend and did sign my GPG key + Este vecino te ha authentificado como amigo y firmado tu llave GPG + + + + Peer has not authenticated me as a friend and did not sign my GPG key + Este vecino no te ha authentificado como amigo y tampoco ha firmado tu llave GPG + + + + Signature Failure + Error de firma + + + + Maybe password is wrong + Probablemente la contraseña es erronea + + + + ConnectFriendWizard + + + Connect Friend Wizard + Assistente para connectarte con amigos + + + + CreateBlog + + + Create new Blog + Crear nuevo blog + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Nuevo Blog</span></p></body></html> + + + + Name + Nombre + + + + Description + Descripción + + + + Type: + Tipo: + + + + Public - Anyone can read and publish (Shared Publish Key) + Público - Cualquiera puede leer y escribir (Llave de publicación compartida) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Restringido - Cualquiera puede leer, publicación limitada (Llave de publicación privada) + + + + Private - (Private Publish Key required to view Messages) + Privado - (Llave de publicación privada necesaria para leer mensajes) + + + + Allowed Messages + Mensajes permitidos + + + + Authemticated Messages + Mensajes autentificados + + + + Anonymous Messages + Mensajes anónimos + + + + Blog Logo + Logotipo de blog + + + + Add Blog Logo + Añadir logotipo para el blog + + + + Cancel + Cancelar + + + + Create + Crear + + + + RetroShare + RetroShare + + + + Please add a Name + Por favor, añade un nombre + + + + Load File + Cargar archivo + + + + Pictures (*.png *.xpm *.jpg) + Imágenes (*.png *.xpm *.jpg) + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + Editor visual + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + Disminuir tamaño de letra + + + + Bold + Negrita + + + + Underline + Subrayado + + + + Italic + Cursiva + + + + Publish + Publicar + + + + New + Nuevo + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + Deshacer + + + + RetroShare + RetroShare + + + + Please add a Subject + Por favor, añade un asunto + + + + &File + &Archivo + + + + &New + &Nuevo + + + + &Open... + &Abrir + + + + &Save + &Guardar + + + + Save &As... + + + + + &Print... + &Imprimir... + + + + Print Preview... + Vista preliminar + + + + &Export PDF... + Exportar P&DF... + + + + &Quit + &Cerrar + + + + &Edit + &Editar + + + + &Undo + De&shacer + + + + &Redo + Re&hacer + + + + Cu&t + Cor&tar + + + + &Copy + C&opiar + + + + &Paste + &Pegar + + + + &View + &Mostrar + + + + &Insert + &Insertar + + + + &Image + &Imágen + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + &Izquierda + + + + + C&enter + C&entrado + + + + + &Right + &Derecha + + + + &Justify + &Composición en bloque + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + &Abrir archivo... + + + + HTML-Files (*.htm *.html);;All Files (*) + Archivos HTML (*.htm *.html);;Todos los archivos(*) + + + + Save as... + Guardar como... + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + Imprimir documento + + + + Export PDF + Exportar PDF + + + + Choose Image + Elegir imágen + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Formatos de imágenes compatibles (*.png *.jpeg *.jpg *.gif) + + + + CreateChannel + + + Create a new Channel + Crear canal nuevo + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + <span style="font-size:24pt; font-weight:500;color:#32CD32;">Nuevo canal</span> + + + + Name + Nombre + + + + check peers you would like to share private publish key with + Selecciona a los vecinos quienes quieres enviar la llave de publicación privada + + + + Share Key With + Compartir llave de publicación privada con + + + + Contacts: + Contactos: + + + + Description + Descripción + + + + Type: + Tipo: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Restringido - Cualquiera puede leer, publicación limitada (Llave de publicación privada) + + + + Private - (Private Publish Key required to view Messages) + Privado - (Llave de publicación privada necesaria para leer mensajes) + + + + Allowed Messages + Mensajes permitidos + + + + Anonymous Messages + Mensajes anónimos + + + + Authenticated Messages + Mensajes autentificado + + + + Key Sharing + Compartit llaves de publicación + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + A los recipientes de la llave de publicación privada se les permite publicar en canales restringidos y leer y publicar en canales privados + + + + Share Private Publish Key + Compartir llave de publicación privada + + + + Channel Logo + Logotipo del canal + + + + Add Channel Logo + Añadir logotipo para el canal + + + + Cancel + Cancelar + + + + Create + Crear + + + + RetroShare + RetroShare + + + + Please add a Name + Por favor, añade un nombre + + + + Load File + Cargar archivo + + + + Pictures (*.png *.xpm *.jpg) + Imágenes (*.png *.xpm *.jpg) + + + + CreateChannelMsg + + + New Channel Post + Crear entrada nueva + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">Nuevo mensaje de canal</span></p></body></html> + + + + Channel Post + Mensaje de canal + + + + Channel Post to: + Mensaje de canal a: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;">Puedes poner una imagen para tu entrada.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;">Puedes arrastrar archivos para adjuntarlos.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;">Pon un tema y una descripción para tu entrada.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Puedes mirar los archivos adjuntos en la pestaña de los anexos.</span></p></body></html> + + + + Add File to Attach + Adjuntar archivo + + + + Add Channel Thumbnail + Añadir imágen + + + + Message + Mensaje + + + + Subject : + Asunto: + + + + + Attachments + Anexos + + + + allow channels to get frame for message thumbnail from movie media attachments or not + Permitir canales generar imagenes de videos adjuntos o no + + + + Auto Thumbnail + Generación automatica de imágenes + + + + Drag and Drop Files from Search Results + Arrastar archivos de los resultados de la búsqueda + + + + + Drop file error. + Error al arrastrar. + + + + Directory can't be dropped, only files are accepted. + Carpetas no se pueden añadir arrastrando, solamente ficheros. + + + + File not found or file name not accepted. + Archivo no encontrado o nombre del archivo no aceptado. + + + + Add Extra File + Añadir otro archivo + + + + + RetroShare + RetroShare + + + + File already Added and Hashed + Archivo ya añadido y hash generado + + + + Please add a Subject + Por favor, añade un asunto + + + + Load File + Cargar archivo + + + + Pictures (*.png *.xpm *.jpg) + Imágenes (*.png *.xpm *.jpg) + + + + CreateForum + + + Create new Forum + Crear nuevo foro + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Nuevo foro</span></p></body></html> + + + + Name + Nombre + + + + Description + Descripción + + + + Type: + Tipo: + + + + Public - Anyone can read and publish (Shared Publish Key) + Público - Cualquiera puede leer y escribir (Llave de publicación compartida) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Restringido - Cualquiera puede leer, publicación limitada (Llave de publicación privada) + + + + Private - (Private Publish Key required to view Messages) + Privado - (Llave de publicación privada necesaria para leer mensajes) + + + + Allowed Messages + Mensajes permitidos + + + + Authenticated Messages + Mensajes autentificado + + + + Anonymous Messages + Mensajes anónimos + + + + Cancel + Cancelar + + + + Create + Crear + + + + Please add a Name + Por favor, añade un nombre + + + + CreateForumMsg + + + Post Forum Message + Escribir mensaje de foro + + + + Forum + Foro + + + + Subject + Asunto + + + + Attach File + Adjuntar archivo + + + + Sign Message + Firmar mensaje + + + + + Paste RetroShare Link + Pegar enlace RetroShare + + + + Forum Post + Mensaje de foro + + + + Attach files via drag and drop + Añdadir archivos arrastrandolos + + + + You can attach files via drag and drop here in this window + Puedes adjuntar archivos arrastrandolos a esta ventana + + + + Post Forum Msg + Escribir mensaje de foro + + + + Close + Cerrar + + + + Paste full RetroShare Link + Pegar enlace RetroShare entero + + + + In Reply to + Como respuesta a + + + + RetroShare + RetroShare + + + + Please set a Forum Subject and Forum Message + Por favor, pon un tema y escribe un mensaje + + + + Add Extra File + Añadir otro archivo + + + + + Drop file error. + Error al arrastrar. + + + + Directory can't be dropped, only files are accepted. + Carpetas no se pueden añadir arrastrando, solamente ficheros. + + + + File not found or file name not accepted. + Archivo no encontrado o nombre del archivo no aceptado. + + + + CreateGroup + + + Create a Group + Crear un grupo + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Crear un grupo</span></p></body></html> + + + + Group Name + Nombre del grupo + + + + Enter a name for your group + Introduce un nombre para el grupo + + + + Edit Group + Cambiar grupo + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Cambiar grupo</span></p></body></html> + + + + CryptoPage + + + Public Key + Llave GPG pública + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copiar mi llave GPG al portapapeles </p></body></html + + + + Copy Key + Copiar llave GPG + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Guardar llave GPG en un archivo</p></body></html> + + + + Save Key + Guardar llave GPG + + + + RetroShare + RetroShare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + Tu llave GPG privada ha sido copiado al portapapeles, pega y mandaselo a tu amigos por email u otro medio + + + + Save as... + Guardar como... + + + + RetroShare Certificate (*.rsc );;All Files (*) + Certificados GPG de RetroShare (*.rsc );;Todos los archivos (*) + + + + DHTStatus + + + DHT + DHT + + + + DHT On + DHT Activo + + + + RetroShare users in DHT (Total DHT users) + Usuarios de RetroShare en DHT (Usuarios total de DHT) + + + + DHT Off + DHT Inactivo + + + + DLListDelegate + + + B + B + + + + KB + KB + + + + MB + MB + + + + GB + GB + + + + DetailsDialog + + + Details + Detalles + + + + + General + General + + + + File Name: + Nombre del archivo: + + + + Hash: + Hash: + + + + Size: + Tamaño: + + + + Status: + Estado: + + + + Priority: + Prioridad: + + + + Type: + Tipo: + + + + Transfer + Transferencia + + + + Sources: + Fuentes: + + + + Datarate: + Tasa de datos: + + + + Completed: + Completo: + + + + Chunk size: + Tamaño de bloques: + + + + + Number of Chunks + Numero de bloques + + + + Chunks: + Bloques: + + + + Remaining: + Pendiente: + + + + Date + Fecha + + + + Download time: + Tiempo estimado para completar: + + + + + Comments + Comentarios + + + + + retroshare link(s) + Enlace(s) RetroShare + + + + Copy + Copiar + + + + OK + OK + + + + Cancel + Cancelar + + + + Rating + Evaluación + + + + File Name + Nombre del archivo + + + + Not Rated + Sin evaluación + + + + No Comments + Sin comentarios + + + + DirectoriesPage + + + Incoming Directory + Carpeta de descargas completas + + + + + Browse + Navegar + + + + Partials Directory + Carpeta de descargas incompletas + + + + Shared Directories + Carpetas compartidas + + + + Automatically share incoming directory (Recommended) + Compartir carpeta de descargas incompletas automaticamente (recommendado) + + + + Edit Share + Cambiar carpetas compartidas + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + Mantener hashes de archivos aunque no estén compartidos. +Puede ser ventajoso si compartes carpetas de discos duros externos, + para no tener que recalcular los hashes al conectarlo. + + + + Remember hashed files for + Mantener hashes de archivo durante + + + + days + días + + + + Forget any hashed file that is not anymore shared. + Olvidar de hashes de archivos que ya no están compartidos. + + + + Clean Hash Cache + Limiar memoria de hashes + + + + Auto-check shared directories every + Prueba automática de carpetas compartidas cada + + + + minute(s) + minuto(s) + + + + Set Incoming Directory + Determinar carpeta de descargas completas + + + + Set Partials Directory + Determinar carpeta de descargas incompletas + + + + DiscStatus + + + Waiting outgoing discovery operations + Esperando operaciones de decubrimiento salientes + + + + Waiting incoming discovery operations + Esperando operaciones de decubrimiento entrantes + + + + DownloadToaster + + + Start file + Abrir archivo + + + + <b>Download completed</b> + <b>Decarga completa</b> + + + + Close + Cerrar + + + + EditChanDetails + + + Channel Details + Detalles del canal + + + + Cancel + Cancelar + + + + OK + OK + + + + Edit Channel Details + Cambiar detalles del canal + + + + Channel Info + Información sobre el canal + + + + Channel Name + Nombre del canal + + + + Channel Description + Descripción del canal + + + + Add Channel Logo + Añadir logotipo para el canal + + + + Load File + Cargar archivo + + + + Pictures (*.png *.xpm *.jpg) + Imágenes (*.png *.xpm *.jpg) + + + + EditForumDetails + + + Forum Details + Detalles del foro + + + + Cancel + Cancelar + + + + OK + OK + + + + Edit Forum Details + Cambiar detalles del foro + + + + Forum Info + Información sobre el foro + + + + Forum Name + Nombre del foro + + + + Forum Description + Descripción del foro + + + + EmailPage + + + Invite Friends by Email + Invitar a amigos por correo electrónico + + + + Enter your friends' email addresses (seperate each on with a semicolon) + Introduce las direcciones de correo de tus amigos (múltiples direcciones separados por punto y coma) + + + + Your friends' email addresses: + Direcciones de correo de tus amigos: + + + + Enter Friends Email addresses + Introduce la dirección de correo de tu amigo + + + + Subject: + Asunto: + + + + Friend invites you to check out RetroShare + Un amigo te invita a probar RetroShare + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + Un amigo utiliza RetroShare para la comunicación segura. Te invita a cambiar archivos de forma segura. +RetroShare es software libre y gratuita y su uso es seguro: No contiene ni virus, ni "spyware", ni tampoco publicidad y se puede desinstalar fácilmente. +Infórmate en la página web oficial (http://retroshare.sourceforge.net) o descarga de allí directamente la versión más reciente (http://retroshare.sourceforge.net/downloads.html) +Hasta pronto en RetroShare! + + + + ErrorMessagePage + + + Sorry, some error appeared + Perdona, un error ha ocurrido + + + + Here is the error message: + Esta es el mensaje de error: + + + + ExampleDialog + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Amigos</span></p></body></html> + + + + # + # + + + + Status + Estado + + + + Person + Persona + + + + Auto Connect + Conectar automaticamente + + + + Trust Level + Nivel de la confianza + + + + Peer Address + Dirección del vecino + + + + Last Contact + Último contacto + + + + Organisation + Organización + + + + Location + Lugar + + + + Country + País + + + + Person Id + ID personal + + + + Auth Code + Auth Code + + + + Vote Up + Voto positivo + + + + Vote Down + Voto negativo + + + + ExprParamElement + + + + + to + a + + + + ignore case + ignorar empleo de minúsculas/mayúsculas + + + + + dd.MM.yyyy + dd.MM.yyyy + + + + + KB + KB + + + + + MB + MB + + + + + GB + GB + + + + ExpressionWidget + + + Expression Widget + Widget de expressiones + + + + Delete this expression + Borrar esa expressión + + + + FileAssociationsPage + + + &New + &Nuevo + + + + Add new Association + Añadir nueva asociación + + + + &Edit + &Editar + + + + Edit this Association + Cambiar esa asociación + + + + &Remove + &Borrar + + + + Remove this Association + Borrar esa asociación + + + + File type + Tipo de archivo + + + + Friend Help + Amigo ayuda + + + + You this + Tú esto + + + + FileTransferInfoWidget + + + Chunk map + Mapa de bloques + + + + Active chunks + Bloques activos + + + + Availability map (%1 active source) + Bloques disponibles (%1 fuente activo) + + + + Availability map (%1 active sources) + Bloques disponibles (%1 fuentes activos) + + + + File info + Información sobre el archivo + + + + File hash + Hash del archivo + + + + File size + Tamaño del archivo + + + + + + + bytes + bytes + + + + Chunk size + Tamaño de bloques + + + + Number of chunks + Numero de bloques + + + + Transfered + Completos + + + + Remaining + Pendiente + + + + Number of sources + Numero de fuentes + + + + Chunk strategy + Estrategia de bloques + + + + Transfer type + Tipo de transferencia + + + + Anonymous F2F + F2F anónimo + + + + Direct friend transfer / Availability assumed + Transferencia directa / disponibilidad asumido + + + + FlatStyle_RDM + + + Friends Directories + Carpetas de amigos + + + + My Directories + Mis carpetas + + + + Size + Tamaño + + + + Age + Edad + + + + Friend + Amigo + + + + Share Type + Tipo de compartición + + + + Directory + Carpeta + + + + FofPage + + + Friends of friends + Amigos de amigos + + + + Select now who you want to make friends with. + Elige ahora quienes quieres hacer tus amigos. + + + + Show me: + Muesta me: + + + + Any peer I've not signed + Vecinos a quienes no he firmado las llaves GPG + + + + Friends of my friends who already trust me + Amigos de amigos que me han firmado la llave GPG + + + + Signed peers showing as denied + Vecinos bloqueados a quienes he firmado la llave GPG + + + + Peer name + Nombre del vecino + + + + Also signed by + Tambien firmado por + + + + Peer id + ID del vecino + + + + Make friend with these peers + Hacer amigos estos vecinos + + + + *** None *** + *** Ningún *** + + + + ForumDetails + + + + Forum Details + Detalles del foro + + + + Forum Info + Información sobre el foro + + + + Forum Name + Nombre del foro + + + + Popularity + Popularidad + + + + Last Post + Última entrada + + + + Forum ID + ID del foro + + + + Forum Description + Descripción del foro + + + + Security + Seguridad + + + + Allowed Messages + Mensajes permitidos + + + + Authemticated Messages + Mensajes autentificados + + + + Anonymous Messages + Mensajes anónimos + + + + Cancel + Cancelar + + + + OK + OK + + + + Apply and Close + Aplicar y cerrar + + + + ForumMsgItem + + + + + Subject: + Tema: + + + + Unsubscribe To Forum + Anular suscripción del foro + + + + Reply + Responder + + + + Expand + Abrir + + + + Remove Item + Quitar objeto + + + + Send + Enviar + + + + Signed + Firmado + + + + Forum Post + Mensaje de foro + + + + Unknown Forum Post + Entrada de foro desconocido + + + + + + Anonymous + Anónimo + + + + In Reply to + Como respuesta a + + + + Please give a Text Message + Por favor, introduce un mensaje + + + + ForumNewItem + + + Form + Formulario + + + + Subscribe to Forum + Suscribir foro + + + + Expand + Abrir + + + + Remove Item + Quitar objeto + + + + Forum Description + Descripción del foro + + + + ForumPage + + + Misc + Variado + + + + Set message to read on activate + Marcar mensaje como leido al activarlo + + + + Expand new messages + Abrir mensajes nuevos + + + + ForumsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Foros</span></p></body></html> + + + + Display + Mostrar + + + + Create Forum + Crear foro + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Foro:</p></body></html> + + + + Last Post + Última entrada + + + + Threaded View + Vista hierárquica + + + + Flat View + Vista llana + + + + + Title + Título + + + + + Date + Fecha + + + + + Author + Autor + + + + Signed + Firmado + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + Previous Thread + Tema anterior + + + + Next Thread + Tema siguiente + + + + Download all files + Descargar todo + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Buscar foros</span></p></body></html> + + + + Reset + Reiniciar + + + + Content + Contenido + + + + Reply Message + Responder a mensaje + + + + Start new Thread for Selected Forum + Empieza un tema nuevo en el foro seleccionado + + + + Print + Imprimir + + + + PrintPreview + Vista preliminar + + + + Your Forums + Tus foros + + + + Subscribed Forums + Foros suscritos + + + + Popular Forums + Foros populares + + + + Other Forums + Otros foros + + + + Subscribe to Forum + Suscribir foro + + + + Unsubscribe to Forum + Anular suscripción del foro + + + + New Forum + Nuevo foro + + + + Show Forum Details + Mostrar detalles del foro + + + + Edit Forum Details + Cambiar detalles del foro + + + + Restore Publish Rights for Forum + Restituir derechos de publicación para el foro + + + + + Copy RetroShare Link + Copiar enlace RetroShare + + + + Mark all as read + Marcar todos como leido + + + + Mark all as unread + Marcar todos como no leido + + + + Reply + Responder + + + + + Start New Thread + Empezar nuevo tema + + + + Reply to Author + Responder al autor + + + + Expand all + Abrir todos + + + + Collapse all + Cerrar todos + + + + + Mark as read + Marcar como leido + + + + + with children + con descendientes + + + + + Mark as unread + Marcar como no leido + + + + Hide + Esconder + + + + Expand + Abrir + + + + AUTHD + autentificado + + + + + RetroShare + RetroShare + + + + No Forum Selected! + Ningún foro seleccionado! + + + + You cant reply a Anonymous Author + No puedes contestar a un autor anónimo + + + + ForumsFillThread + + + + Anonymous + Anónimo + + + + + signed + firmado + + + + + none + ningún + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Amigos</span></p></body></html> + + + + Add + Añadir + + + + Display + Mostrar + + + + Friends + Amigos + + + + Status + Estado + + + + Add or Change your Avatar + Seleccionar o cambiar tu avatar + + + + Edit Personal message + Cambiar tu mensaje personal + + + + Group Chat + Chat de grupo + + + + Messages entered here are sent to all collected friends + Mensajes enviados aquí se mandarán a todos amigos conectados + + + + Bold + Negrita + + + + Underline + Subrayado + + + + Italic + Cursiva + + + + Font + Letra + + + + Text Color + Color de letra + + + + Attach File + Adjuntar archivo + + + + Send + Enviar + + + + Clear Chat History + Vaciar historia del chat + + + + + Add Friend + Agregar a amigo + + + + Create new Profile + Crear nuevo perfil + + + + + Create new Forum + Crear nuevo foro + + + + F + F + + + + + Create new Channel + Crear nuevo canal + + + + C + C + + + + Add your Avatar Picture + Añadir tu imagen del avatar + + + + A + A + + + + Set your Personal Message + Pon tu mensaje personal + + + + Edit your status Message + Cambiar tu mensaje de estado + + + + Browse Message History + Navegar historia de mensajes + + + + Browse History + Navegar historia + + + + + Save Chat History + Guardar historia del chat + + + + Hide Offline Friends + Esconder amigos desconectados + + + + Hide Status Column + Esconder columna de estado + + + + + Sort by State + Ordenar por estado + + + + Hide State + Esconder estado + + + + + Add a new Group + Añadir nuevo grupo + + + + + Sort Descending Order + Ordenar desciendiendo + + + + + Sort Ascending Order + Ordenar ascendiendo + + + + Delete Chat History + Borrar historia del chat + + + + Deletes all stored and displayed chat history + Borra toda la historia guardada y mostrada del chat + + + + Profile + Perfil + + + + News Feed + Novedades + + + + Welcome to RetroShare's group chat. + Bienvenido al chat de grupo de Retroshare. + + + + me + yo + + + + Paste RetroShare Link + Pegar enlace RetroShare + + + + Group + Grupo + + + + Friend + Amigo + + + + Location + Lugar + + + + Message Group + Escribir mensaje al grupo + + + + Edit Group + Cambiar grupo + + + + Remove Group + Quitar grupo + + + + Chat + Chat + + + + Message Friend + Escribir mensaje + + + + Friend Details + Detalles del amigo + + + + Recommend this Friend to... + Recomendar este amigo a... + + + + Connect To Friend + Conectar con amigo + + + + Copy RetroShare Link + Copiar enlace RetroShare + + + + + Paste Friend Link + Pegar enlace RetroShare + + + + Deny Friend + Bloquear amigo + + + + Remove Friend Location + Borrar lugar del amigo + + + + Add to group + Agregar a grupo + + + + Move to group + Mover a grupo + + + + Groups + Grupos + + + + Remove from group + Quitar de grupo + + + + Remove from all groups + Quitar de todos grupos + + + + Expand all + Abrir todos + + + + Collapse all + Cerrar todos + + + + location + lugar + + + + + Available + Disponible + + + + Save Certificate + Guardar certificado + + + + Certificates (*.pqi) + Certificados (*.pqi) + + + + Do you want to remove this Friend? + Quieres quitar este amigo? + + + + is typing... + está escribiendo... + + + + + New group chat + Nuevo chat de grupo + + + + Do you really want to physically delete the history? + Quieres borrar la historia de verdad? + + + + Load File + Cargar archivo + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Imágenes (*.png *.xpm *.jpg *.tiff *.gif) + + + + Add Extra File + Añadir otro archivo + + + + + Drop file error. + Error al arrastrar. + + + + Directory can't be dropped, only files are accepted. + Carpetas no se pueden añadir arrastrando, solamente ficheros. + + + + File not found or file name not accepted. + Archivo no encontrado o nombre del archivo no aceptado. + + + + Save as... + Guardar como... + + + + Text File (*.txt );;All Files (*) + Archivos texto (*.txt );;Todos los archivos (*) + + + + GamesDialog + + + Form + Formulario + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + Título / Comentario + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + Servidor + + + + Status + Estado + + + + Comment + Comentario + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Accept + Aceptar + + + + Delete + Borrar + + + + + Move Player + + + + + Play Game + + + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + GenCertDialog + + + + + Create new Profile + Crear nuevo perfil + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + + Your profile is associated to a GPG key + Tu perfil está vinculado con uns llave GPG + + + + Generate a new Profile + Generar nuevo perfil + + + + Use Profile + Usar perfil + + + + Name + Nombre + + + + Enter here your nickname + Introduce aquí tu apodo + + + + Email + Email + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + Ten cuidado. Esta direción email estará visible a tus amigos y sus amigos. +Esta información es necesaria para GPG, pero puedes poner una direción inventada. + + + + This Password is for GPG + Esta contraseña es para GPG + + + + Password + Contraseña + + + + Put a strong password here. This password protects your GPG key. + Piensate una contraseña fuerte. Protectará tu llave GPG. + + + + Location + Lugar + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + Introduce un lugar expresivo. P.e.: casa, laptop, etc.. Este campo se utilizará para distinguir instalaciones con el mismo perfil (la misma llave GPG). + + + + Generate New Profile + Generar nuevo perfil + + + + Info + Información + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Crear nuevo perfil</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare emplea llaves GPG para la autentificación.. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Puedes utilizar un perfil (llave PGP) existente o crear uno nuevo.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Puedes instalar RetroShare en lugares diferentes con el mismo perfil (la misma llave GPG).</span></p></body></html> + + + + + Create new Location + Crear nuevo lugar + + + + + Generate new Location + Generar nuevo lugar + + + + + Create a new Location + Generar un nuevo lugar + + + + + Generate new Profile + Generar nuevo perfil + + + + + Create a new Profile + Crear un nuevo perfil + + + + + Generate GPG key Failure + Error al generar la llave GPG + + + + Location field is required with a minimum of 3 characters + El campo lugar requiere como mínimo 3 letras + + + + All fields are required with a minimum of 3 characters + Todos los campos requieren como mínimo 3 letras + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + Generando una llave GPG, por favor ten paciencia: este proceso necesita generar números primos grandes y puede tardar un poco en equipos lentos. + +Introduce tu contraseña cuando se te pregunte para firmar tu nueva llave GPG. + + + + Select Trusted Friend + Seleccionar a amigo de confianza + + + + Certificates (*.pqi *.pem) + Certificados (*.pqi *.pem) + + + + + Multiple instances + Instancias múltiples + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Una instancia de RetroShare está utilizando el mísmo perfil. Por favor cierra esa instacia + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Un error inesperado ha ocurrido cuando ReroShare intentaba adquirir acceso unico + + + + Generate ID Failure + Error al generar ID + + + + Failed to Load your new Certificate! + Error al cargar tu nuevo certificado! + + + + GeneralPage + + + Startup + Inicio + + + + Start RetroShare when my system starts + Inicar ReroShare junto con el sistema + + + + Start minimized + Inicar minimizado + + + + Start minimized on system start + Inicar minimizado junto con el sistema + + + + Misc + Variado + + + + Do not show the Quit RetroShare MessageBox + No preguntar antes de cerrar RetroShare + + + + Do not Minimize to Tray Icon + No minimizar al "tray" + + + + Auto Login + Registrar automáticamente + + + + Register retroshare:// as url protocol (Restart required) + Registrar retroshare:// como protocolo (Reinicio necesario) + + + + Idle + Inactivo + + + + Idle Time + Tiempo inactivo + + + + seconds + segundos + + + + GraphFrame + + + Recv: + Recibido: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Enviado: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + Arrastra los nodos, acerca con la ruade del ratón o las teclas '+' o '-' + + + + GroupDefs + + + Friends + Amigos + + + + Family + Familia + + + + Co-Workers + Compañeros + + + + Other Contacts + Otros contactos + + + + Favorites + Favoritos + + + + GroupTreeWidget + + + Enter a Keyword here + Introduce una palabra clave aquí + + + + Title + Título + + + + Description + Descripción + + + + Reset + Reiniciar + + + + Sort by Name + Ordenar por nombre + + + + Sort by Popularity + Ordenar por popularidad + + + + Sort by Last Post + Ordenar por última entrada + + + + Private Key Available + Llave GPG privada disponible + + + + GuiExprElement + + + and + y + + + + and / or + y / o + + + + or + o + + + + Name + Nombre + + + + Path + Ruta + + + + Extension + Extensión + + + + Hash + Hash + + + + Date + Fecha + + + + Size + Tamaño + + + + Popularity + Popularidad + + + + contains + contiene + + + + contains all + contiene todo + + + + is + es + + + + less than + menor que + + + + less than or equal + menor o igual que + + + + equals + igual a + + + + greater than or equal + mayor o igual que + + + + greater than + mayor que + + + + is in range + es en el rango + + + + HelpBrowser + + + + RetroShare Help + Ayuda de RetroShare + + + + Find: + Buscar: + + + + Find Previous + Buscar anterior + + + + Find Next + Buscar siguiente + + + + Case sensitive + Distinguir minúsculas/mayúsculas + + + + Whole words only + Solamente palabras completas + + + + Contents + Contenido + + + + Help Topics + Temas de ayuda + + + + + Search + Buscar + + + + Searching for: + Buscando: + + + + Found Documents + Documentos encontrados + + + + Back + Atrás + + + + Move to previous page (Backspace) + Página anterior + + + + Backspace + Retroceso + + + + Forward + Adelante + + + + Move to next page (Shift+Backspace) + Página siguiente + + + + Shift+Backspace + Shift+Retroceso + + + + Home + Home + + + + Move to the Home page (Ctrl+H) + Página principal (Ctrl+H) + + + + Ctrl+H + Ctrl+H + + + + + + Find + Buscar + + + + Search for a word or phrase on current page (Ctrl+F) + Buscar una palabra o frase en esta página (Ctrl+F) + + + + Ctrl+F + Ctrl+F + + + + Close + Cerrar + + + + Close Vidalia Help + Cerrar ayuda Vidalia + + + + Esc + Esc + + + + + Error Loading Help Contents: + Error al cargar los contenidos de la ayuda: + + + + Supplied XML file is not a valid Contents document. + Este archivo XML no tiene contenido válido. + + + + Search reached end of document + Búsqueda ha llegado al final del documento + + + + Search reached start of document + Búsqueda ha llegado al principio del documento + + + + Text not found in document + Texto no fue encontrado en este documento + + + + Found %1 results + Encontrado %1 resultados + + + + HelpDialog + + + About + Acerca de + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare es una plataforma de comunicación multiplataforma, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">privado, seguro y decentralizado. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Te permite compartir de forma segura con tus amigos, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">empleando una red de confianza para autentificar y OpenSSL para cifrar toda la comunicación. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare proporciona carpetas compartidas, chat, mensajes y canales</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Enlaces externos útiles para más información:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">RetroShare página web</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">RetroShare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare Foros</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">RetroShare página web de projecto</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt página web.</span></a></li></ul></body></html> + + + + Authors + Autores + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + Thanks to + Gracias a + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Translation + Traducción + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare traductores:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Español: </span><span style=" font-size:8pt;"> Marc René Schädler &lt;suaefar@googlemail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Francés:</span><span style=" font-size:8pt;">Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polaco: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbio: </span><span style=" font-size:8pt;"> Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Sueco: </span><span style=" font-size:8pt;">dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare traductores de la página web:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Alemán: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polaco: </span>Maciej Mrug</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Sueco: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +</body></html> + + + + License Agreement + Acuerdo de licencia + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Acerca de RetroShare</span></p></body></html> + + + + HelpTextBrowser + + + Error opening help file: + Error al cargar archivo de ayuda: + + + + Opening External Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + RetroShare puede abrir el enlace con su navegador. Si no está configurado especialmente, esta acción so será anónima. + + + + Do you want Retroshare to open the link in your Web browser? + Quieres que RetroShare abra el enlace con tu navegador? + + + + Unable to Open Link + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + RetroShare no puede abrir el enlace con tu navegador, pero puedes copiar y abrirlo manualmente. + + + + ImHistoryBrowser + + + Message History + Historia de mensajes + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Historia de mensajes</span></p></body></html> + + + + + Reset + Reiniciar + + + + + Copy + Copiar + + + + Remove + Quitar + + + + Mark all + Marcar todo + + + + Delete + Borrar + + + + Clear history + Borrar historia + + + + Send + Enviar + + + + InfoDialog + + + Info + Información + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare emplea llaves GPG, esto es necesario para crear un perfil de RetroShare.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Tendrás que intercambiar las llaves GPG con tus amigos por email o cualquier medio que te parezca adequado.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Cuando recibes una llave GPG de un amigo añadelo con el assistente de añadir amiogs de RetroShare.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. Con Linux tienes que instalar GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. Con Windows tienes que instalar gpg4win para generar la llave GPG:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. Si no puedes generar una llave GPG con GPA intenta hacerlo con WinPT:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + IntroPage + + + Add a new Friend + Agregar a un amigo nuevo + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + Este asistente de ayudará a conectarte con un amigo el la red de RetroShare. +Tienes las siguientes posibilidades: + + + + &Enter the certificate manually + Introducir certificados &manualmente + + + + &You get a certificate file from your friend + Intercambiar certificados &guardados en archivos + + + + &Make friend with selected friends of my friends + &Hacer amigos algunos amigos de mis amigos + + + + &Enter RetroShare ID manually + &Introducir ID de RetroShare manualmente + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + &Enviar una invitación por email +(El/ella recibirá un email con instrucciones para descargar RetroShare) + + + + LinksDialog + + + Title / Comment + Título / Comentario + + + + Score + Puntuación + + + + Peer / Link + Vecino / Enlace + + + + Sort by + Ordenar por + + + + Combo + Combinado + + + + Time + Fecha + + + + Ranking + Clasificación + + + + In last + En últimos + + + + Month + Mes + + + + Week + Semana + + + + Day + Día + + + + From + De + + + + All Peers + Todos vecinos + + + + Own Links + Enlaces propios + + + + Show + Mostrar + + + + Top 100 + Primeros 100 + + + + 101-200 + 401-500 + + + + 201-300 + 401-500 + + + + 301-400 + 401-500 + + + + 401-500 + 401-500 + + + + Bottom 100 + Últimos 100 + + + + Link: + Enlace: + + + + Add Anonymous Link + Añadir enlace anónimo + + + + Add Link/Comment + Añadir enlace/comentario + + + + Title: + Título: + + + + Score: + Puntuación: + + + + +2 Great! + +2 Excelente! + + + + +1 Good + +1 Bueno + + + + 0 Okay + 0 Regular + + + + -1 Sux + -1 Mal + + + + -2 Bad Link + -2 Muy mal + + + + Url: + URL: + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Nube de enlaces</span></p></body></html> + + + + Add new link + Añadir nuevo enlace + + + + Share Link Anonymously + Compartir enlace anónimamente + + + + Vote on Link + Votar por ese enlace + + + + Download + Descargar + + + + Expand + Abrir + + + + Hide + Esconder + + + + File Request Confirmation + Solicitud del archivo afirmado + + + + The file has been added to your download list. + El archvio se ha añadido a la lista de descargas. + + + + File Request canceled + Solicitud del archivo cancelado + + + + The file has not been added to your download list, because you already have it. + El archvio no se ha añadido a la lista de descargas porque ya lo tienes. + + + + File Request Error + Error al solicitar un archivo + + + + The file link is malformed. + Enlace erroneo. + + + + MainWindow + + + MainWindow + Ventana principal + + + + Add Friend + Agregar a amigo + + + + Add a Friend Wizard + Assistente para añadir a amigos + + + + Add Share + Compartir archivos + + + + + Options + Opciones + + + + Messenger + Mensajería instantanea + + + + About + Acerca de + + + + SMPlayer + SMPlayer + + + + Quit + Cerrar + + + + + Quick Start Wizard + Asistente para el inicio rápido + + + + RetroShare %1 a secure decentralised communication platform + RetroShare %1 una plataforma segura y decentralizada de comunicación + + + + Network + Red + + + + Friends + Amigos + + + + Search + Buscar + + + + + Transfers + Transferencias + + + + Files + Archivos + + + + + Messages + Mensajes + + + + + Channels + Canales + + + + Blogs + Blogs + + + + + Forums + Foros + + + + Links Cloud + Nube de enlaces + + + + Plugins + Plug-ins + + + + Unfinished + Incompleto + + + + Low disk space warning + Aviso de poco espacio de memoria + + + + The disk space in your + El espacio de memoria en la + + + + directory is running low (current limit is + carpeta es escaso (El límite actual es + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + MB). + + RetroShare suspenderá todo el acceso a esa carpeta de forma segura. + + Por favor libera un poco espacio y pulsa OK. + + + + Show/Hide + Mostrar/esconder + + + + Status + Estado + + + + Open Messenger + Abrir mensajería instantanea + + + + Open Messages + Abrir mensajes + + + + Bandwidth Graph + Gráfico del uso de la red + + + + Applications + Aplicaciones + + + + Help + Ayuda + + + + Minimize + Minimizar + + + + Maximize + Maximizar + + + + &Quit + &Cerrar + + + + RetroShare + RetroShare + + + + Chat + Chat + + + + + + + You have %1 new messages + Tienes %1 nuevos mensajes + + + + + + + You have %1 new message + Tienes %1 nuevo mensaje + + + + + + + %1 new messages + %1 nuevos mensajes + + + + + + + %1 new message + %1 nuevo mensaje + + + + You have %1 completed downloads + Tienes %1 descargas completas + + + + You have %1 completed download + Tienes %1 descarga completa + + + + %1 completed downloads + %1 descargas completas + + + + %1 completed download + %1 descarga completa + + + + Down: %1 (kB/s) + Recibiendo: %1 (kB/s) + + + + Up: %1 (kB/s) + Enviando: %1 (kB/s) + + + + %1 friend connected + %1 amigo conectado + + + + %1 friends connected + %1 amigos conectados + + + + Do you really want to exit RetroShare ? + Quieres cerrar RetroShare de verdad? + + + + Really quit ? + Cerrar de verdad? + + + + Internal Error + Error interno + + + + Hide + Esconder + + + + Show + Mostrar + + + + It seems to be an old RetroShare link. Please use copy instead. + Esto parece ser un enlace RetroShare antiguo. Por favor intenta copiarlo. + + + + The file link is malformed. + Enlace erroneo. + + + + MessageComposer + + + + Compose + Componer + + + + + Contacts + Contactos + + + + Search for Name: + Buscar por nombre: + + + + Search Friends + Buscar a amigos + + + + Reset + Reiniciar + + + + Send To: + Enviar a: + + + + >> To + >> A + + + + >> Cc + >> Cc + + + + >> Bcc + >> Bcc + + + + >> Recommend + >> Recomendar + + + + Paragraph + Párrafo + + + + Heading 1 + Encabezamiento 1 + + + + + Heading 2 + Encabezamiento 2 + + + + Heading 3 + Encabezamiento 3 + + + + Heading 4 + Encabezamiento 4 + + + + Heading 5 + Encabezamiento 5 + + + + Heading 6 + Encabezamiento 6 + + + + Font size + Tamaño de letra + + + + Increase font size + Aumentar tamaño de letra + + + + Decrease font size + Disminuir tamaño de letra + + + + Bold + Negrita + + + + Italic + Cursiva + + + + Select Color + Elegir color + + + + Alignment + Alineación + + + + Add a Image + Añadir un imágen + + + + Sets text font to code style + Cambia el estilo de letra a tipo codigo + + + + Underline + Subrayado + + + + Subject: + Asunto: + + + + Tags: + Etiquetas: + + + + + Tags + Etiquetas + + + + Recommended Files + Archivos recomendados + + + + File Name + Nombre del archivo + + + + Size + Tamaño + + + + Hash + Hash + + + + Send + Enviar + + + + Send this message now + Enviar este mensaje ahora + + + + Reply + Responder + + + + Toggle Contacts View + Cambiar vista de contactos + + + + Save + Guardar + + + + Save this message + Guardar este mensaje + + + + Attach + Adjuntar + + + + Attach File + Adjuntar archivo + + + + Quote + Citar + + + + Add Blockquote + Añadir cita + + + + &Left + &Izquierda + + + + C&enter + C&entrado + + + + &Right + &Derecha + + + + &Justify + &Composición en bloque + + + + Friend Recommendation(s) + Amigos recomendados + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + Te recomiendo un amigo mío, puedes confiar en el si confias en mi. <br> Copia el enlace del amigo y pegalo en la lista de amigos + + + + + Save Message + Guardar mensaje + + + + Message has not been Sent. +Do you want to save message to draft box? + El mensaje no se ha enviado. +Lo quieres guardar en el borrador? + + + + + Paste RetroShare Link + Pegar enlace RetroShare + + + + Add to "To" + Añadir a "A" + + + + Add to "CC" + Añadir a "CC" + + + + Add to "BCC" + Añadir a "BCC" + + + + Add as Recommend + Añadir como recomendado + + + + Friend Details + Detalles del amigo + + + + Re: + Re: + + + + Fwd: + Fwd: + + + + + RetroShare + RetroShare + + + + Do you want to send the message without a subject ? + Quieres enviar este mensaje sin asunto? + + + + Please insert at least one recipient. + Por favor, introduce por lo menos un destinatario. + + + + To + A + + + + Cc + Cc + + + + Bcc + Bcc + + + + Unknown + Desconocido + + + + Unknown friend + Amigo desconocido + + + + &File + &Archivo + + + + &New + &Nuevo + + + + &Open... + &Abrir... + + + + &Save + &Guardar + + + + Save &As File + Guardar co&mo + + + + Save &As Draft + Guardar en &borrador + + + + &Print... + &Imprimir... + + + + &Export PDF... + Exportar P&DF... + + + + &Quit + &Cerrar + + + + &Edit + &Editar + + + + &Undo + De&shacer + + + + &Redo + Re&hacer + + + + Cu&t + Cor&tar + + + + &Copy + C&opiar + + + + &Paste + &Pegar + + + + &View + &Mostrar + + + + &Contacts Sidebar + &Barra lateral de contactos + + + + &Insert + &Insertar + + + + &Image + &Imágen + + + + &Horizontal Line + &Linea horizontal + + + + &Format + &Formato + + + + Open File... + Abrir archivo... + + + + + HTML-Files (*.htm *.html);;All Files (*) + Archivos HTML (*.htm *.html);;Todos los archivos(*) + + + + Save as... + Guardar como... + + + + Print Document + Imprimir documento + + + + Export PDF + Exportar PDF + + + + Message has not been Sent. +Do you want to save message ? + Mensaje no enviado. Lo quieres guardar? + + + + Choose Image + Elegir imágen + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Formatos de imágenes compatibles (*.png *.jpeg *.jpg *.gif) + + + + Add Extra File + Añadir otro archivo + + + + + Drop file error. + Error al arrastrar. + + + + Directory can't be dropped, only files are accepted. + Carpetas no se pueden añadir arrastrando, solamente ficheros. + + + + File not found or file name not accepted. + Archivo no encontrado o nombre del archivo no aceptado. + + + + MessagePage + + + Reading + Leyendo + + + + Set message to read on activate + Marcar mensaje como leido al activarlo + + + + Open messages in + Abrir mensajes en + + + + Tags + Etiquetas + + + + Tags can be used to categorize and prioritize your messages + Etiquetas se pueden utilizar para categorizar y priorizar tus mensajes + + + + Add + Añadir + + + + Edit + Editar + + + + Delete + Borrar + + + + Default + Por defecto + + + + A new tab + Una pestaña nueva + + + + A new window + Una ventana nueva + + + + Edit Tag + Cambiar etiqueta + + + + MessageToaster + + + <b>1 new Message from</b> + <b>1 nuevo mensaje de</b> + + + + Close + Cerrar + + + + Subject + Asunto + + + + Sub: + Asunto: + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Archivos recomendados</span></p></body></html> + + + + Download all Recommended Files + Descargar todos los archivos recomendados + + + + Subject: + Asunto: + + + + From: + De: + + + + To: + A: + + + + Cc: + Cc: + + + + Bcc: + Bcc: + + + + Tags: + Etiquetas: + + + + File Name + Nombre del archivo + + + + Size + Tamaño + + + + Hash + Hash + + + + Print + Imprimir + + + + Print Preview + Vista preliminar + + + + No subject + Sin asunto + + + + Download + Descargar + + + + Download all + Dercargar todo + + + + Hide + Esconder + + + + Expand + Abrir + + + + File + Archivo + + + + Files + Archivos + + + + Print Document + Imprimir documento + + + + Save as... + Guardar como... + + + + HTML-Files (*.htm *.html);;All Files (*) + Archivos HTML (*.htm *.html);;Todos los archivos(*) + + + + MessageWindow + + + New Message + Nuevo mensaje + + + + Compose + Componer + + + + Reply to selected message + Responder a mensaje seleccionado + + + + Reply + Responder + + + + Reply all to selected message + Responder a todos del mensaje seleccionado + + + + Reply all + Responder a todos + + + + Forward selected message + Reenviar mensaje seleccionado + + + + Foward + Reenviar + + + + Remove selected message + Quitar mensaje seleccionado + + + + Delete + Borrar + + + + Print selected message + Imprimir mensaje seleccionado + + + + + Print + Imprimir + + + + Display + Mostrar + + + + + + Tags + Etiquetas + + + + Print Preview + Vista preliminar + + + + + Buttons Icon Only + Bótones solo con icono + + + + Buttons Text Beside Icon + Bótones con texto al lado del icono + + + + Buttons with Text + Botónes con texto + + + + Buttons Text Under Icon + Botónes con texto debajo del icono + + + + Set Text Under Icon + Pon texto debajo de los iconos + + + + &File + &Archivo + + + + Save &As File + Guardar co&mo + + + + &Print... + &Imprimir... + + + + Print Preview... + Vista preliminar... + + + + &Quit + &Cerrar + + + + MessagesDialog + + + + New Message + Nuevo mensaje + + + + Compose + Componer + + + + Reply to selected message + Responder a mensaje seleccionado + + + + Reply + Responder + + + + Reply all to selected message + Responder a todos del mensaje seleccionado + + + + Reply all + Responder a todos + + + + Forward selected message + Reenviar mensaje seleccionado + + + + Foward + Reenviar + + + + Remove selected message + Quitar mensaje seleccionado + + + + Delete + Borrar + + + + Print selected message + Imprimir mensaje seleccionado + + + + Print + Imprimir + + + + Display + Mostrar + + + + Reset + Reiniciar + + + + Attachments + Anexos + + + + + Subject + Asunto + + + + + + From + De + + + + + Date + Fecha + + + + + Content + Contenido + + + + + + + + Tags + Etiquetas + + + + + + + Inbox + Bandeja de entrada + + + + + + + Outbox + Bandeja de salida + + + + Draft + Borradores + + + + + Sent + Enviados + + + + + + + Trash + Papelera + + + + Quick View + Vistas rápidas + + + + Total Inbox: + Buzón de entrada total: + + + + Folders + Carpetas + + + + + Print... + Imprimir... + + + + Print Preview + Vista preliminar + + + + + Buttons Icon Only + Bótones solo con icono + + + + Buttons Text Beside Icon + Bótones con texto al lado del icono + + + + Buttons with Text + Botónes con texto + + + + Buttons Text Under Icon + Botónes con texto debajo del icono + + + + Set Text Under Icon + Pon texto debajo de los iconos + + + + Save As... + Guardar como... + + + + Reply to Message + Responder a mensaje + + + + + Reply to All + Responder a todos + + + + Forward Message + Reenviar mensaje + + + + Click to sort by attachments + Cliquear para ordenar por anexos + + + + Click to sort by subject + Cliquear para ordenar por asunto + + + + Click to sort by read + Cliquear para ordenar por leido + + + + + Click to sort by from + Cliquear para ordenar por remitente + + + + Click to sort by date + Cliquear para ordenar por fecha + + + + Click to sort by tags + Cliquear para ordenar por etiqueta + + + + Click to sort by star + Cliquear para ordenar por estrella + + + + Forward selected Message + Reenviar mensaje seleccionado + + + + Starred + Con estrella + + + + Open in a new window + Abrir en ventana nueva + + + + Open in a new tab + Abrir en pestaña nueva + + + + Mark as read + Marcar como leido + + + + Mark as unread + Marcar como no leido + + + + Add Star + Añadir estrella + + + + Edit + Editar + + + + Edit as new + Editar como nuevo + + + + Remove Messages + Quitar mensajes + + + + Remove Message + Quitar mensaje + + + + Undelete + Restaurar + + + + Empty trash + Vaciar papelera + + + + + + Drafts + Borradores + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + No hay mensajes con estrella disponibles. Estrellas te permiten marcar mensajes para encontrarlos fácilmente. Para ãnadir una estrella a un mensaje cliquea la estrella gris al lado de cualquier mensaje. + + + + To + A + + + + Click to sort by to + Cliquear para ordenar por destinatario + + + + + + + + Total: + Total: + + + + MessengerWindow + + + RetroShare Messenger + Mensajería instantanea RetroShare + + + + Click to Change your Avatar + Cliquear para cambiar avatar + + + + Add a Friend + Agregar a amigo + + + + Share Files for your Friends + Compartir archivos con tus amigos + + + + Search Friends + Buscar a amigos + + + + Reset + Reiniciar + + + + + Sort Descending Order + Ordenar desciendiendo + + + + + Sort Ascending Order + Ordenar ascendiendo + + + + Set root is Decorated + Mostrar lugares + + + + Set Root Decorated + Mostrar lugares + + + + Hide Offline Friends + Esconder amigos desconectados + + + + Sort by State + Ordenar por estado + + + + Expand all + Abrir todos + + + + Collapse all + Cerrar todos + + + + Chat + Chat + + + + Message Friend + Escribir mensaje + + + + Connect To Friend + Conectar con amigo + + + + Peer Details + Detalles del vecino + + + + Recomend this Friend to... + Recomendar este amigo a... + + + + Paste RetroShare Link + Pegar enlace RetroShare + + + + Export Friend + Exportar amigo + + + + Deny Friend + Bloquear amigo + + + + Remove Friend Location + Borrar lugar del amigo + + + + <strong>RetroShare instance</strong> + <strong>Instancia de RetroShare</strong> + + + + <strong>GPG Key</strong> + <strong>Llave GPG</strong> + + + + + + + location + lugar + + + + Save Certificate + Guardar certificado + + + + Certificates (*.pqi) + Certificados (*.pqi) + + + + MsgItem + + + + Expand + Abrir + + + + Remove Item + Quitar objeto + + + + Reply to Message + Responder a mensaje + + + + Reply Message + Responder a mensaje + + + + Delete Message + Borrar mensaje + + + + Play Media + Reproducir medio + + + + Message From + Mensaje de + + + + Sent Msg + Mensajes enviados + + + + Draft Msg + Mensajes en borrador + + + + Pending Msg + Mensajes pendientes + + + + Hide + Esconder + + + + NATStatus + + + <strong>NAT:</strong> + <strong>NAT:</strong> + + + + OK | RetroShare Server + OK | RetroShare Server + + + + Internet connection + Conexión a internet + + + + No internet connection + No conexión a internet + + + + No local network + Ninguna red local + + + + NetworkDialog + + + Network + Red + + + + + + Name + Nombre + + + + + Did I authenticated peer + Le he autentificado al vecino + + + + Did I sign his gpg key + Le he firmado su llave GPG al vecino + + + + + Did peer authenticated me + El vecino me ha autentificado + + + + + Cert Id + ID del certificado GPG + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Red</span></p></body></html> + + + + + Search Network + Buscar en la red + + + + Clear Filter + Reiniciar filtros + + + + Peer ID + ID del vecino + + + + Show keys that are not validated by the GPG web of trust + Mostrar llaves GPG que no están validados por la red de confianza + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Pantalla</span></p></body></html> + + + + Network Status + Estado de la red + + + + Local network + Red local + + + + UPnP + UPnP + + + + External ip address finder + Buscador de direcciónes IP externo + + + + Clear + Vaciar + + + + Set Tabs Right + Pon pestañas a la derecha + + + + Set Tabs North + Pon pestañas arriba + + + + Set Tabs South + Pon pestañas abajo + + + + Set Tabs Left + Pon pestañas a la izquierda + + + + Set Tabs Rounded + Pon pestañas redondas + + + + Set Tabs Triangular + Pon pestañas triangulares + + + + Add Friend + Agregar a amigo + + + + Copy My Key to Clipboard + Copiar mi certificado GPG al portapapeles + + + + Export My Key + Exportar mi llave GPG + + + + Create New Profile + Crear nuevo perfil + + + + Create a new Profile + Crear un nuevo perfil + + + + Authentication matrix + Matrix de autentificación + + + + Network View + Vista de la red + + + + Deny friend + Bloquear amigo + + + + Make friend + Hacer amigo + + + + Delete certificate + Borrar certificado + + + + Export my Cert + Export mi certificado GPG + + + + Peer details... + Detalles del vecino... + + + + Copy RetroShare Link + Copiar enlace RetroShare + + + + Personal signature + Firma personal + + + + GPG key signed by you + Llave GPG firmado por ti + + + + Marginally trusted peer + Vecino de confianza marginal + + + + Fully trusted peer + Vecino de plena confiaza + + + + Untrusted peer + Vecino sin confianza + + + + Unknown + Desconocido + + + + Has authenticated me + Me ha autentificado + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + me ha autentificado. +Cliquear con el botón derecho y hacer amigo para conectar. + + + + yourself + tu mismo + + + + NetworkView + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + Repintar + + + + Friendship level: + + + + + Edge length: + + + + + NewTag + + + New Tag + Nueva Etiqueta + + + + Name: + Nombre: + + + + Choose color + Elegir color + + + + OK + OK + + + + Cancel + Cancelar + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Novedades</span></p></body></html> + + + + Remove All + Quitar todo + + + + Options + Opciones + + + + NotifyPage + + + News Feed + Novedades + + + + Peers + Vecinos + + + + Channels + Canales + + + + Forums + Foros + + + + Blogs + Blogs + + + + Messages + Mensajes + + + + Chat + Chat + + + + Add feeds at end + Añadir "Feeds" al final + + + + Systray Icon + Icono en el "systray" + + + + Private Message + Mensaje privado + + + + Message + Mensaje + + + + Channel Post + Mensaje de canal + + + + Forum Post + Mensaje de foro + + + + + Download completed + Descarga completa + + + + Combined icon + Icono combinado + + + + Toasters + Notificaciones + + + + Friend Connect + Conectar con amigo + + + + New Message + Nuevo mensaje + + + + Position + Posición + + + + X Margin + Distancia horizontal + + + + Y Margin + Distancia vertical + + + + Private Chat + Chat privado + + + + Open Window for new chat + Abrir ventana para chat nuevo + + + + Grab Focus when chat arrives + Enfocar ventana cuando llege chat + + + + Use a single tabbed window + Solo una ventana con pestañas + + + + Group chat + Chat de grupo + + + + Display systray message + Mostrar mensaje en el "systray" + + + + Top Left + Parte superior izquierda + + + + Top Right + Parte superior derecha + + + + Bottom Left + Parte inferior izquierda + + + + Bottom Right + Parte inferior derecha + + + + NotifyQt + + + GPG key passphrase + Contraseña de la llave GPG + + + + Wrong password ! + Contraseña erronea! + + + + Please enter the password to unlock the following GPG key: + Por favor, introduce la contraseña para abrir la llave GPG siguiente: + + + + Examining shared files... + Examinando archivos compartidos... + + + + Hashing file + Calculando hash del archivo + + + + Saving file index... + Guardando indice del archivo... + + + + OnlineToaster + + + Friend Online + Amigo conectado + + + + PeerDefs + + + + Unknown + Desconocido + + + + PeerItem + + + + Expand + Abrir + + + + Remove Item + Quitar objeto + + + + Write a quick Message + Escribir un mensaje instantaneo + + + + Chat + Chat + + + + Start Chat + Iniciar chat + + + + Cancel + Cancelar + + + + Send + Enviar + + + + Name: + Nombre: + + + + Peer ID: + ID del vecino: + + + + Trust: + Confianza: + + + + Location + Lugar + + + + IP Address + Dirección IP + + + + Connection Method + Método de conectar + + + + Status: + Estado: + + + + Write Message + Escribir mensaje + + + + Friend + Amigo + + + + Friend Connected + Amigo conectado + + + + Connect Attempt + Intentando conectar + + + + Friend of Friend + Amigo de un amigo + + + + Peer + Vecino + + + + + + + + + + + + Unknown Peer + Vecino desconocido + + + + Hide + Esconder + + + + Quick Message + Mensaje instantaneo + + + + PeerStatus + + + Friends: 0/0 + Amigos: 0/0 + + + + Online Friends/Total Friends + Amigos conectados/ total + + + + Friends + Amigos + + + + PhotoDialog + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + Vecino + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + Comentario + + + + + Date + Fecha + + + + + Location + Lugar + + + + Size + Tamaño + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + Actualizar detalles + + + + Photo + + + + + Description + Descripción + + + + Insert Show Lists + + + + + Open + + + + + Remove + Quitar + + + + Excellent + + + + + Good + + + + + Average + Normal + + + + Below avarage + + + + + Bad + + + + + Unrated + Sin evaluación + + + + Rating + Evaluación + + + + PhotoShow + + + Photo Show + + + + + Date: + + + + + Location: + Lugar: + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Back + Atrás + + + + Start + + + + + Play + + + + + Pause + Pausar + + + + Forward + Adelante + + + + PluginFrame + + + Remove + Quitar + + + + PluginManagerWidget + + + Install New Plugin... + Instalar nuevo plug-in... + + + + Open Plugin to install + Abrir plug-in para instalar + + + + Plugins (*.so *.dll) + Plug-ins (*.so *.dll) + + + + PopularityDefs + + + Popularity + Popularidad + + + + PopupChatDialog + + + Close + Cerrar + + + + Attach a Picture + Adjuntar una imagen + + + + Add a File for your Friend + Añadir un archivo para tu amigo + + + + Send + Enviar + + + + + Bold + Negrita + + + + + Underline + Subrayado + + + + + Italic + Cursiva + + + + Font + Letra + + + + Text Color + Color de letra + + + + Strike + Tachado + + + + Clear Chat History + Vaciar historia del chat + + + + Disable Emoticons + Desactivar emoticónes + + + + + Save Chat History + Guardar historia del chat + + + + Clear offline messages + Limpiar mensajes mandados sin conexión + + + + Browse Message History + Navegar historia de mensajes + + + + Browse History + Navegar historia + + + + Delete Chat History + Borrar historia del chat + + + + Deletes all stored and displayed chat history + Borra toda la historia guardada y mostrada del chat + + + + Friend not Online + Amigo desconectado + + + + Your Friend is offline +Do you want to send them a Message instead + Tu amigo no está conectado. +Quieres mandarle un mensaje email en lugar de un mensaje instantaneo? + + + + Paste RetroShare Link + Pegar enlace RetroShare + + + + is typing... + está escribiendo... + + + + Hide Avatar + Esconder avatar + + + + Show Avatar + Mostrar avatar + + + + Do you really want to physically delete the history? + Quieres borrar la historia de verdad? + + + + Add Extra File + Añadir otro archivo + + + + Load Picture File + Cargar archivo de imagen + + + + + Drop file error. + Error al arrastrar. + + + + Directory can't be dropped, only files are accepted. + Carpetas no se pueden añadir arrastrando, solamente ficheros. + + + + File not found or file name not accepted. + Archivo no encontrado o nombre del archivo no aceptado. + + + + Save as... + Guardar como... + + + + Text File (*.txt );;All Files (*) + Archivos texto (*.txt );;Todos los archivos (*) + + + + apears to be Offline. + parece deconectado. + + + + Messages you send will be delivered after Friend is again Online + Mensajes mandados se entregan cuando tu amigo vuelva a conectarse + + + + is Idle and may not reply + está inactivo e igual no contesta + + + + is Away and may not reply + no está e igual no contesta + + + + is Busy and may not reply + está ocupado e igual no contesta + + + + PopupChatWindow + + + Avatar + Avatar + + + + Set your Avatar Picture + Eligir tu imagen del avatar + + + + + Dock tab + Incorporar pestaña + + + + + Undock tab + Soltar pestaña + + + + + Set Chat Window Color + Elegir color de la ventana del chat + + + + RetroShare + RetroShare + + + + Load File + Cargar archivo + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Imágenes (*.png *.xpm *.jpg *.tiff *.gif) + + + + PrintPreview + + + RetroShare Message - Print Preview + Mensaje RetroShare - Vista previa + + + + Print + Imprimir + + + + &Print... + &Imprimir... + + + + Page Setup... + Ajustar la pagina... + + + + Zoom In + Acercar + + + + Zoom Out + Alejar + + + + &Close + &Cerrar + + + + ProfileEdit + + + Profile Edit + Cambiar perfil + + + + Profile + Perfil + + + + Category + Categoría + + + + Thoughts + Pensamientos + + + + Edit Profile Category + Cambiar categoría de perfil + + + + Birthday + Día de cumpleaños + + + + School + Escuela + + + + University + Universidad + + + + Phone Number + Numero de teléfono + + + + Favourite Books + Libros favoritos + + + + Favourite Music + Musica favorita + + + + Favourite Films + Películas favoritas + + + + or Custom Entry + o otra entrada + + + + Add Entry + Añadir entrada + + + + + Move + Mover + + + + Close Editor + Cerrar editor + + + + Remove Profile Entry + Quitar entrada de perfil + + + + Move Profile Entry Up + Subir entrada de perfil + + + + Move Profile Entry Down + Bajar entrada de perfil + + + + ProfileView + + + Profile View + + + + + + Name + Nombre + + + + Peer ID + ID del vecino + + + + Last Post: + Última entrada: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Perfil</span></p></body></html> + + + + + Edit Profile + Cambiar perfil + + + + Category + Categoría + + + + Thoughts + Pensamientos + + + + Favourite Files + Archivos favoritos + + + + Size + Tamaño + + + + Hash + Hash + + + + Close Profile + Cerrar perfil + + + + Clear Photo + Quitar foto + + + + Change Photo + Cambiar foto + + + + Remove Favourite + Quitar favoritos + + + + Clear Favourites + Quitar favoritos + + + + Download File + Descargar archivo + + + + Download All + Dercargar todo + + + + RetroShare + RetroShare + + + + Error : cannot get peer details. + Error: No se pueden obtener los detalles del vecino. + + + + ProfileWidget + + + + Edit Personal message + Cambiar tu mensaje personal + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Información pública</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Información pública</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Nombre:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Lugar:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">ID del vecino:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Otra información</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Numero de amigos:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Versión:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Conectado desde:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Mi dirección</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Dirección IP local:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dirección IP externa:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">DNS dinamico:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Lista de direcciones</span></p></body></html> + + + + QObject + + + File Request Confirmation + Solicitud del archivo afirmado + + + + The file has been added to your download list. + El archvio se ha añadido a la lista de descargas. + + + + + File Request canceled + Solicitud del archivo cancelado + + + + The file has not been added to your download list, because you already have it. + El archvio no se ha añadido a la lista de descargas porque ya lo tienes. + + + + + Friend Request Confirmation + Solicitud de hacer amigos confirmada + + + + The friend is already in your list. + Este amigo ya está en tu lista. + + + + The friend has been added to your list. + El amigo se ha agredado a tu lista. + + + + + Friend Request canceled + Solicitud de hacer amigos cancelado + + + + The friend could not be added to your list. + El amigo no se ha podido agregar a tu lista. + + + + The friend could not be found. + El amigo no ha sido encontrado. + + + + + Forum Request canceled + Solicitud de foro cancelado + + + + The forum "%1" could not be found. + El foro "%1" no se ha encontrado. + + + + The forum message in forum "%1" could not be found. + El mensaje de foro "%1" no se ha encontrado. + + + + + Channel Request canceled + Solicitud de canal cancelado + + + + The channel "%1" could not be found. + El canal "%1" no se ha encontrado. + + + + The channel message in channel "%1" could not be found. + El mensaje de canal en canal "%1" no se ha encontrado. + + + + + Message Request canceled + Solicitud de mensaje cancelado + + + + Cannot send a message to a not accepted receipient "%1". + No se puede enviar un mensaje al destinatario "%1" no aceptado. + + + + The receipient of the message is unknown. + El destinatario de este menjase está desconocido. + + + + File Request Error + Error al solicitar un archivo + + + + The file link is malformed. + Enlace erroneo. + + + + %1 of %2 RetroShare links processed. + %1 de %2 enlaces RetroShare procesado. + + + + Request Confirmation + Solicitar conformación + + + + (Age in seconds) + (Edad en segundos) + + + + (Depth) + (Profundidad) + + + + total + total + + + + Search requests repartition: + Repartición de peticiones de búsqueda: + + + + Tunnel requests repartition: + Repartición de peticiones de túneles: + + + + Deny friend + Bloquear amigo + + + + Make friend + Hacer amigo + + + + Peer details + Detalles del vecino + + + + The following has not been added to your download list, because you already have it: + + Los siguientes archivo no se han añadido a la lista de descarga, porque ya los tienes: + + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + Inicalización ha fallado. Instalación de GPG erronea. + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + Un error inesperado ha ocurrido. Error: 'RsInit::InitRetroShare unexpected return code %1'. + + + + + Multiple instances + Instancias múltiples + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + Una instancia de RetroShare está utilizando el mísmo perfil. Por favor cierra esa instacia o usa otro perfil +archivo de bloqueo: + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + Un error inesperado ha ocurrido cuando ReroShare intentaba adquirir acceso unico +archivo de bloqueo: + + + + Login Failure + Error al iniciar sesión + + + + Maybe password is wrong + Probablemente la contraseña es erronea + + + + Start with a RetroShare link is only supported for Windows. + Inicio con un enlace RetroShare solamente es compatible con Windows. + + + + QuickStartWizard + + + Quick Start Wizard + Asistente para el inicio rápido + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Bienvenido a RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Este asistente de comienzo rápido te puede ayudar a configurar RetroShare en un par de pasos simples.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Si estás un usuario con experiencia puedes configurar todos los ajustes de RetroShare en el diálogo de los opciones. Puedes cerrar el asistente cuando quieras.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Es aststente de ayudará a:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Configurar la conexión a internet.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Compartir carpetas.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Empezar a utilizar RetroShare.</span></p></body></html> + + + + + + Next > + Siguiente > + + + + + + + Exit + Cerrar + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + Para el mejor rendimiento, RetroShare tiene que saber algunos datos de la conexion a internet. + + + + Choose your download speed limit: + Elige el limite de velocidad de descargar: + + + + + KB/s + kB/s + + + + Choose your upload speed limit: + Elige el limite de velocidad de subir: + + + + Connection : + Conexión: + + + + Automatic (UPnP) + Automatico (UPnP) + + + + Firewalled + Con cortafuegos + + + + Manually forwarded port + Pueto promovido manualmente + + + + Discovery : + Descubrimiento: + + + + Public: DHT & Discovery + Público: DHT & decubrimiento + + + + Private: Discovery Only + Privado: solo decubrimiento + + + + Inverted: DHT Only + Invertido: solo DHT + + + + Dark Net: None + Red oscura: Nigún + + + + Dynamic DNS: + DNS dinámico: + + + + + + < Back + < Atrás + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Esta es una lista de carpetas compartidas. Puedes añadir carpetas utilizando los botónes a la izquierda.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Si compartes una carpeta inicialmente todos los archivos contenidos se comparten.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Puedes determinar el tipo de la compartición de cada carpeta por separado:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Navegable</span><span style=" font-family:'Sans'; font-size:8pt;">: archivos están navegables por tus amigos.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">En toda la red</span><span style=" font-family:'Sans'; font-size:8pt;">: todos pueden descargar los archivos anónimamente por túneles entre amigos.</span></p></body></html> + + + + Directory + Carpeta + + + + Network Wide + En toda la red + + + + Browseable + Navegable + + + + Add + Añadir + + + + Remove + Quitar + + + + Automatically share incoming directory (Recommended) + Compartir carpeta de descargas incompletas automaticamente (recommendado) + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Disfruta RetroShare!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Falta solo un paso! Casi tienes configurado RetroShare.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Estos ajustes determinan como y cuando se inicia RetroShare.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Do not show a message when Closing RetroShare + No preguntar antes de cerrar RetroShare + + + + Start Minimized + Inicar minimizado + + + + Start RetroShare when my System Starts. + Inicar ReroShare junto con el sistema. + + + + Start minimized on system start + Inicar minimizado junto con el sistema + + + + Finish + Terminar + + + + Select A Folder To Share + Seleciona una carpeta para compartir + + + + Shared Directory Added! + Carpeta compartida añadido! + + + + Do you really want to stop sharing this directory ? + Quieres dejar de compartir esta carpeda de verdad? + + + + Warning! + Aviso! + + + + RSettingsWin + + + General + General + + + + Directories + Carpetas + + + + Server + Servidor + + + + Transfer + Transferencia + + + + Notify + Notificación + + + + Security + Seguridad + + + + Message + Mensaje + + + + Forum + Foro + + + + Chat + Chat + + + + Appearance + Aspecto + + + + Sound + Sonido + + + + UnknownPage + Página desconocida + + + + Error Saving Configuration on page + Error al guardar configuración en página + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>Recibiendo:</strong> 0.00 (kB/s) | <strong>Enviando:</strong> 0.00 (kB/s) + + + + <strong>Down:</strong> + <strong>Recibiendo:</strong> + + + + <strong>Up:</strong> + <strong>Enviando:</strong> + + + + RetroshareDirModel + + + Anonymous + Anónimo + + + + Anonymous and browsable by friends + Anónimo y navegable por amigos + + + + Only browsable by friends + Navegable solamente por amigos + + + + NEW + NUEVO + + + + Rshare + + + Resets ALL stored RetroShare settings. + Reinicia todos los ajustes de RetroShare. + + + + Sets the directory RetroShare uses for data files. + Determina la carpeta que utiliza RetroShare para datos. + + + + Sets the name and location of RetroShare's logfile. + Determina el nombre y el lugar del archivo de registro de RetroShare. + + + + Sets the verbosity of RetroShare's logging. + Determina la verbosidad de RetroShare. + + + + Sets RetroShare's interface style. + Determina el estilo del interfaz para RetroShare. + + + + Sets RetroShare's interface stylesheets. + Determina las hojas de estilo del interfaz para RetroShare. + + + + Sets RetroShare's language. + Determina el idioma de retroShare. + + + + RetroShare Usage Information + Información sobre el uso de RetroShare + + + + Invalid language code specified: + Idioma especificada es inválida: + + + + Invalid GUI style specified: + GUI especificado es inválido: + + + + Invalid log level specified: + Nivel de registro especificado es inválido: + + + + Unable to open log file '%1': %2 + No se puede abrir el archivo de la historia '%1': %2 + + + + RsidPage + + + RetroShare ID + ID de RetroShare + + + + Use RetroShare ID for adding a Friend which is available in your network. + Utiliza la ID RetroShare para agregar a amigos que están disponibles en tu red. + + + + Add Friends RetroShare ID... + Añadir ID RetroShare del amigo... + + + + Paste Friends RetroShare ID in the box below + Pega la ID RetroShare de tu amigo en el campo abajo + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + Introduce la ID RetroShare de tu amigo, p.Ej. Peer@BDE8D16A46D938CF + + + + This Peer %1 is not available in your Network + Este vecino %1 no está disponible en tu red + + + + SFListDelegate + + + B + B + + + + KB + KB + + + + MB + MB + + + + GB + GB + + + + SearchDialog + + + Any + Cualquier + + + + Archive + Archivo + + + + Audio + Audio + + + + CD-Image + Imagen de CD + + + + Document + Documento + + + + Picture + Imagen + + + + Program + Programa + + + + Video + Video + + + + Directory + Carpeta + + + + Enter a Keyword here + Introduce una palabra clave aquí + + + + Reset + Reiniciar + + + + Start Search + Comenzar búsqueda + + + + Search + Buscar + + + + Advanced Search + Búsqueda avanzada + + + + Advanced + Avanzado + + + + KeyWords + Palabras clave + + + + Results + Resultados + + + + Search Id + ID de búsqueda + + + + Filter Search Result + Filtrar resultados de búsqueda + + + + Clear Filter + Reiniciar filtros + + + + File Name + Nombre del archivo + + + + File Size + Tamaño de archivo + + + + Filename + Nombre del archivo + + + + Size + Tamaño + + + + Sources + Fuentes + + + + Type + Tipo + + + + Age + Edad + + + + Hash + Hash + + + + Close all Search Resullts + Cerrar todos los resultados de búsqueda + + + + Close All Search Results + Cerrar todos los resultados de búsqueda + + + + Download Selected + Descarga seleccionada + + + + + Download + Descargar + + + + Include files from your own file list in the search result + Incluir archivos de tu lista de archivos de los resultados de búqueda + + + + Include own files + Incluir archivos propios + + + + Search inside "browsable" files of your friends + Buscar en carpetas navegables de tus amigos + + + + Search in friends lists + Buscar en lista de amigos + + + + Multi-hop search at distance 6 in the network +(always reports available files) + Búsqueda hasta 6 nodos de distancia en la red (siempre de archivos disponibles) + + + + F2F search + Búsqueda F2F + + + + Limit number of results to : + Limitar numero de resultados a: + + + + Enter a keyword here (at least 3 char long) + Introduce una palabra clave aquí (como mínimo 3 letras) + + + + + Copy RetroShare Link + Copiar enlace RetroShare + + + + Send RetroShare Link + Enviar enlace RetroShare + + + + Download Notice + Notificación de descarga + + + + Skipping Local Files + Omitir archivos locales + + + + + Sorry + Perdona + + + + + This function is not yet implemented. + Esta función todavia no está implementada. + + + + Remove + Quitar + + + + Remove All + Quitar todo + + + + + Folder + Carpeta + + + + New RetroShare Link(s) + Nuevo(s) enlace(s) RetroShare + + + + ServerPage + + + + Network Configuration + Configuración de la red + + + + Automatic (Upnp) + Automatico (UPnP) + + + + Firewalled + Con cortafuegos + + + + Manual Forwarded Port + Pueto promovido manualmente + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + El DHT te permite conectar con tus amigos si han cambiado de la dirección IP +mientras tu estabas deconectado. Esto puede pasar en redes pequeñas. +En general mejora la conectividad. + +El servicio de descubrimiento envia lugares y identidades GPG +de tus amigos a vecinos para ayudarles a elegir nuevos amigos. +Sin embargo los vecinos tienen que confiarse mútuamente para +poder conectarse uno con el otro. + + + + Public: DHT & Discovery + Público: DHT & decubrimiento + + + + Private: Discovery Only + Privado: solo decubrimiento + + + + Inverted: DHT Only + Invertido: solo DHT + + + + Dark Net: None + Red oscura: Nigún + + + + Transfer Rates + Velocidades de transferencia + + + + Download (KB/s) + Descargando (KB/s) + + + + + kB/s + kB/s + + + + Upload (KB/s) + Enviando (KB/s) + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + Si desactivas esta opción, RetroShare no ayudará a vecinos que no se pueden conectar directamente a crear un túnel. Esto es independiente del pricipio F2F "Turtle router". + + + + Allow Tunnel Connection + Permitir conexiones por túnel + + + + Local Address + Dirección local + + + + External Address + Dirección externa + + + + Dynamic DNS + DNS dinámico + + + + + Port: + Puerto: + + + + Show Discovery information in statusbar + Mostar información de descubrimiento en el parte inferior + + + + IP Service + Servicio IP + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + Si desactivas esta opción, RetroShare solo puede determinar tu dirección IP + si estás conectado con alguien. Si la activas +ayuda a conectar si soís pocos amigos en la red. +Tambien ayuda si te encuentras detrás de un encaminador/VPN. + + + + Allow RetroShare to ask my ip to these websites: + Permitir RetroShare a perguntar estas paginas web por tu dirección IP: + + + + Settings + + + Options + Opciones + + + + General + General + + + + Server + Servidor + + + + Transfer + Transferencia + + + + Directories + Carpetas + + + + Notify + Notificación + + + + Security + Seguridad + + + + Message + Mensaje + + + + Forum + Foro + + + + Chat + Chat + + + + Appearance + Aspecto + + + + Sound + Sonido + + + + Cancel + Cancelar + + + + OK + OK + + + + ShareDialog + + + RetroShare Share Folder + RetroShare compartir carpeta + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Compartir carpeta</span></p></body></html> + + + + Share Folder + Compartir carpeta + + + + Local Path + Ruta local + + + + Browse + Navegar + + + + Virtual Folder + Carpeta virtual + + + + Share Flags + Compartición + + + + Browseable by Friends + Navegable por amigos + + + + Browsable + Navegable + + + + Anonymous shared Network Wide + + + + + Network Wide + En toda la red + + + + OK + OK + + + + Cancel + Cancelar + + + + Select A Folder To Share + Seleciona una carpeta para compartir + + + + ShareKey + + + Share Channel + Compartir llave de publicación privada del canal + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Compartir canal</span></p></body></html> + + + + check peers you would like to share private publish key with + Selecciona a los vecinos quienes quieres enviar la llave de publicación privada + + + + Share for Friend + Compartir con amigo + + + + Contacts: + Contactos: + + + + Share + Compartir + + + + Cancel + Cancelar + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Selecciona a los amigos con quienes quieres compartin el canal.</span></p></body></html> + + + + RetroShare + RetroShare + + + + Please select at least one peer + Por favor, selecciona por lo menos un vecino + + + + ShareManager + + + RetroShare Share Manager + Gestionador de comparticiones de RetroShare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Gestionador de carpetas compartidas</span></p></body></html> + + + + Shared Folder Manager + Gestionador de carpetas compartidas + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Esta es una lista de carpetas compartidas. Puedes añadir carpetas utilizando los botónes abajo.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Si compartes una carpeta inicialmente todos los archivos contenidos se comparten.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Puedes determinar el tipo de la compartición de cada carpeta por separado:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Navegable</span><span style=" font-family:'Sans'; font-size:8pt;">: archivos están navegables por tus amigos.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">En toda la red</span><span style=" font-family:'Sans'; font-size:8pt;">: todos pueden descargar los archivos anónimamente por túneles entre amigos.</span></p></body></html> + + + + Directory + Carpeta + + + + Virtual Folder + Carpeta virtual + + + + Network Wide + En toda la red + + + + Browsable + Navegable + + + + Add a Share Directory + Compartir una carpeta + + + + Add + Añadir + + + + Stop sharing selected Directory + Dejar de compartir carpeta selecionada + + + + + Remove + Quitar + + + + Close + Cerrar + + + + Edit selected Shared Directory + Cambiar carpeta compartida selecionada + + + + + Edit + Editar + + + + If checked, the share is anonymously shared to anybody. + Si marcado, esta carpeta se comparte anónimamente con toda la red. + + + + If checked, the share is browsable by your friends. + Si marcado, esta carpeta está navegable por tus amigos. + + + + Warning! + Aviso! + + + + Do you really want to stop sharing this directory ? + Quieres dejar de compartir esta carpeda de verdad? + + + + + Drop file error. + Error al arrastrar. + + + + File can't be dropped, only directories are accepted. + Archivos no se pueden añadir arrastrando, solamente carpetas. + + + + Directory not found or directory name not accepted. + Archivo no encontrado o nombre del archivo no aceptado. + + + + SharedFilesDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Archivos</span></p></body></html> + + + + Splitted View + Paneles separados + + + + Friends Folders + Carpetas de amigos + + + + My Folders + Mis carpetas + + + + All + Todo + + + + One day old + Tiene menos de un día + + + + One Week old + Tiene menos de una semana + + + + One month old + Tiene menos de un mes + + + + Search files + Buscar archivos + + + + Start Search + Comenzar búsqueda + + + + Reset + Reiniciar + + + + Tree view + Vista hierárquica + + + + Flat view + Vista llana + + + + Download selected + Descarga seleccionada + + + + + Download + Descargar + + + + check files + Comprobar archivos + + + + Copy retroshare Links to Clipboard + Copiar enlace RetroShare al portapapeles + + + + Copy retroshare Links to Clipboard (HTML) + Copiar enlace RetroShare al portapapeles (HTML) + + + + Send retroshare Links + Enviar enlaces RetroShare + + + + Send retroshare Links (HTML) + Enviar enlace RetroShare (HTML) + + + + Send retroshare Links to Cloud + Enviar enlace RetroShare a la nube + + + + Add Links to Cloud + Añadir enlaces a la nube + + + + + Open File + Abrir archivo + + + + Open Folder + Abrir carpeta + + + + Checking... + Comprobando... + + + + Check files + Comprobar archivos + + + + Copy retroshare Link + Copiar enlace RetroShare + + + + Send retroshare Link + Enviar enlace RetroShare + + + + + Recommend in a message to + Recomendar en un mensaje a + + + + + + RetroShare Link + Enlace RetroShare + + + + + + + Recommendation(s) + Recomendaciones + + + + Set command for opening this file + Determina el programa con que abrir este archivo + + + + <strong>My Shared Files</strong> + <strong>Mis archivos compartidos</strong> + + + + <strong>Friends Files</strong> + <strong>Archivos compartidos de amigos</strong> + + + + <strong>Files</strong> + <strong>Archivos</strong> + + + + SoundPage + + + Sound Events + Eventos de sonido + + + + Friend + Amigo + + + + go Online + Conectar + + + + + + + + Browse + Navegar + + + + Chatmessage + Mensaje instantaneo + + + + New Msg + Nuevo mensaje + + + + FileSend + Enviar archivo + + + + + Finished + Terminado + + + + FileRecive + Recibir archivo + + + + Incoming + Recibiendo + + + + SplashScreen + + + Load profile + Cargar perfil + + + + Load configuration + Cargar configuración + + + + Create interface + Crear interfaz + + + + StartDialog + + + RetroShare + RetroShare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"><p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Iniciar sesión</span></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Información...</span></a></p></body></html> + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + Abre un dialogo para cear un perfil nuevo o +añadir lugares a un perfil existente. +Los identidades/lugares actuales no se modificarán. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Gestionar perfiles y lugares...</span></a></p></body></html> + + + + Log In + Iniciar sesión + + + + Name (GPG Id) - location: + Nombre (ID GPG) - lugar: + + + + Remember Password + Recordar contraseña + + + + + Multiple instances + Instancias múltiples + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + Una instancia de RetroShare está utilizando el mísmo perfil. Por favor cierra esa instacia o usa otro perfil +archivo de bloqueo: + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + Un error inesperado ha ocurrido cuando ReroShare intentaba adquirir acceso unico +archivo de bloqueo: + + + + Login Failure + Error al iniciar sesión + + + + Maybe password is wrong + Probablemente la contraseña es erronea + + + + + Warning + Aviso + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + La contraseña de tu certificado SSL (tu lugar) se guardará cifrado en el llavero de Gnome. + +Tu contraseña de la llave GPG no se guardará. + +Puedes reiniciar esta opción en los ajustes. + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + La contraseña de tu certificado SSL (tu lugar) se guardará cifrado en el archivo keys/help.dta. Esto NO es muy seguro. + +Tu contraseña de la llave GPG no se guardará. + +Puedes reiniciar esta opción en los ajustes. + + + + StatisticDialog + + + Statistics + Estadística + + + + Now + Ahora + + + + Transfer + Transferencia + + + + Session UL:DL Ratio: + Sesión: proporción SU:DE: + + + + Cumulative UL:DL Ratio + Proporción SU:DE cumulativa + + + + Download + Descargar + + + + Session: + Sesión: + + + + + Downloaded: + Recibido: + + + + + Count of Downloads: + Número de descargas: + + + + + + Overall + Total + + + + Upload + Enviando + + + + + + Session + Sesión + + + + Uploaded: + Enviado: + + + + + Count of Uploads: + Número de subidas: + + + + Uploaded + Enviado + + + + + + + Connections: + Conexiones: + + + + + + Peers: + Vecinos: + + + + Time Statistics + Estadistica de tiempo + + + + + Uptime + Tiempo activo + + + + Since: + Desde: + + + + Cumulative + Cumulativo + + + + Records + Récordes + + + + Uploadspeed: + Velocidad de subida: + + + + Downloadspeed: + Velocidad de descarga: + + + + Uptime: + Tiempo activo: + + + + + Show Settings + Demostrar ajustes + + + + Reset + Reiniciar + + + + Receive Rate + Recibiendo + + + + Send Rate + Enviando + + + + Always On Top + Siempre encima + + + + 100 + 100 + + + + % Opaque + % transparente + + + + Changes the transparency of the Bandwidth Graph + Cambia la transparencia del gráfico de tráfico de la red + + + + Save + Guardar + + + + Cancel + Cancelar + + + + %1 days + %1 días + + + + Hide Settings + Esconder ajustes + + + + StatusDefs + + + + Offline + Desconectado + + + + Away + Indisponible + + + + Busy + Ocupado + + + + Online + Conectado + + + + Idle + Inactivo + + + + Friend is offline + Amigo está desconectado + + + + Friend is away + Amigo no está + + + + Friend is busy + Amigo está ocupado + + + + Friend is online + Amigo está conectado + + + + Friend is idle + Amigo está inactivo + + + + Connected + Conectado + + + + Unreachable + Inaccesible + + + + Available + Disponible + + + + Neighbour + Vecino + + + + Trying tunnel connection + Intentando conectar por túnel + + + + Trying TCP + Intentando TCP + + + + Trying UDP + Intentando UDP + + + + Connected: TCP + Conectado: TCP + + + + Connected: UDP + Conectado: UDP + + + + Connected: Tunnel + Conectado: túnel + + + + Connected: Unknown + Conectado: deconocido + + + + DHT: Contact + Contacto por DHT + + + + StatusMessage + + + Personal message + Mensaje personal + + + + Status message + Mensaje de estado + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Mensaje de estado </span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Introduce tu mensaje de estado</span></p></body></html> + + + + OK + OK + + + + Cancel + Cancelar + + + + Paste RetroShare Link + Pegar enlace RetroShare + + + + StyleDialog + + + Define Style + Definir estilo + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Definir estilo</span></p></body></html> + + + + + Choose color + Elegir color + + + + Color 2 + Color 2 + + + + Color 1 + Color 1 + + + + Style + Estilo + + + + None + Ningún + + + + Solid + Color + + + + Gradient + Color degradado + + + + SubDestItem + + + Delete FeedItem + Borrar objeto + + + + SubFileItem + + + %p Kb + %p Kb + + + + Cancel Download + Cancelar descarga + + + + Download File + Descargar archivo + + + + Download + Descargar + + + + + + Play File + Abrir archivo + + + + Play + Reproducir + + + + Save File + Guardar archivo + + + + + ERROR + ERROR + + + + EXTRA + EXTRA + + + + REMOTE + REMOTO + + + + DOWNLOAD + RECIBIENDO + + + + LOCAL + LOCAL + + + + UPLOAD + ENVIANDO + + + + File %1 does not exist at location. + Archivo %1 no está en ese lugar. + + + + File %1 is not completed. + Archiv %1 no está completo. + + + + Save Channel File + Guardar archivo de canal + + + + TBoard + + + Pause + Pausar + + + + TagDefs + + + Important + Importante + + + + Work + Trabajo + + + + Personal + Personal + + + + Todo + Por hacer + + + + Later + Más tarde + + + + TagsMenu + + + Remove All Tags + Quitar todas las etiquetas + + + + New tag ... + Nueva Etiqueta... + + + + TextPage + + + Text certificate + Certificado de texto + + + + Use text representation of the PGP certificates. + Usar certificados GPG de texto. + + + + The text below is your PGP certificate. You have to provide it to your friend + El texto abajo es tu certificado GPG. Lo puedes mandar a tus amigos + + + + Copy your Cert to Clipboard + Copia tu certificado al portapapeles + + + + Save your Cert into a File + Guardar certificado en un archivo + + + + Run Email program + Abrir programa de email + + + + Please, paste your friends PGP certificate into the box below + Por favor, pega el certificado GPG en el campo abajo + + + + Clean certificate + Limpiar certificado GPG + + + + RetroShare Invite + Invitar a RetroShare + + + + Connect Friend Help + Ayuda para conectar con amigos + + + + You can copy this text and send it to your friend via email or some other way + Puedes copiar este texto y mandarselo a un amigo por email u otro medio + + + + RetroShare + RetroShare + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + Tu certificado se ha copiado al portapapeles. Pegalo y mandaselo a un amigo por email u otro medio + + + + Save as... + Guardar como... + + + + RetroShare Certificate (*.rsc );;All Files (*) + Certificados GPG de RetroShare (*.rsc );;Todos los archivos (*) + + + + Certificate Load Failed + Cargar certificado ha fallado + + + + TransferPage + + + Transfer options + Opciones de transferecias + + + + Queue Size: + Tamaño de cola: + + + + Default chunk strategy: + Estrategia de bloques por defecto: + + + + Safety disk space limit : + Limite de espacio de memoria de seguridad: + + + + Streaming + Streaming + + + + Random + Aleatorio + + + + MB + MB + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;">es capaz de transferir datos o peticiones de búsqueda entre vecinos que no son amigos. Sin embargo este tráfico pasa por una lista de amigos comunicados y es anónimo.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Puedes determinar los señalizadores de compartir en la ventana de las carpetas compartidas.</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Navegable por amigos</span>: archivos visibles a tus amigos.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Compartido anónimamente</span>: archivos están accesibles anónimamente por túneles F2F.</li></ul></body></html> + + + + TransfersDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Descargas:</span></p></body></html> + + + + Show cache transfers + Mostrar transferencias de cache + + + + Uploads + Enviando + + + + Selected transfer + Transferencia + + + + Done + Hecho + + + + Active + Activo + + + + Outstanding + Pendiente + + + + + Name + i.e: file name + Nombre + + + + + Size + i.e: file size + Tamaño + + + + Completed + Completo + + + + Speed + i.e: Download speed + Velocidad + + + + Progress / Availability + i.e: % downloaded + Progreso / Disponibilidad + + + + Sources + i.e: Sources + Fuentes + + + + + Status + Estado + + + + Speed / Queue position + Velocidad / Posición + + + + Remaining + Pendiente + + + + Download time + i.e: Estimated Time of Arrival / Time left + Tiempo estimado para completar + + + + Core-ID + ID nucleo + + + + Peer + i.e: user name + Vecino + + + + Progress + i.e: % uploaded + Progreso + + + + Speed + i.e: upload speed + Velocidad + + + + Transferred + Transferido + + + + Hash + Hash + + + + Router Statistics + Estadística de encaminador + + + + Router Requests + Solicitudes de encaminador + + + + Pause + Pausar + + + + Resume + Continuar + + + + Force Check + Forzar control + + + + Cancel + Cancelar + + + + Open Folder + Abrir carpeta + + + + Open File + Abrir archivo + + + + Preview File + Vista previa + + + + Details... + Detalles... + + + + Clear Completed + Quitar completos + + + + Copy RetroShare Link + Copiar enlace RetroShare + + + + Paste RetroShare Link + Pegar enlace RetroShare + + + + Down + Abajo + + + + Up + Arriba + + + + Top + Más alto + + + + Bottom + Más bajo + + + + Streaming + Streaming + + + + + Slower + Más lento + + + + + + Average + Normal + + + + + Faster + Más rápido + + + + Random + Aleatorio + + + + Play + Reproducir + + + + Move in Queue... + Mover en lista de espera... + + + + Priority (Speed)... + Prioridad (velocidad)... + + + + Chunk strategy + Estrategia de bloques + + + + + + Failed + Fallado + + + + + + Okay + OK + + + + Transferring + Transfiriendo + + + + + + + Complete + Completo + + + + + Waiting + Esperando + + + + Downloading + Descargando + + + + Queued + Esperando + + + + Paused + Pausado + + + + Checking... + Comprobando... + + + + Unknown + Desconocido + + + + version: + versión: + + + + Uploading + Enviando + + + + Are you sure that you want to cancel and delete these files? + Estás seguro que quieres cancelar y borrar estos archivos? + + + + RetroShare + RetroShare + + + + Details: + Detalles: + + + + File preview + Vista previa + + + + File %1 preview failed. + Vista previa de archivp %1 ha fallado. + + + + Open Transfer + Abrir Transferencia + + + + File %1 is not completed. If it is a media file, try to preview it. + Archivo %1 no está completo todavia. Si es un archivo de media, intenta preverlo. + + + + TreeStyle_RDM + + + + FILE + ARCHIVO + + + + Files + Archivos + + + + File + Archivo + + + + + DIR + DIR + + + + Friends Directories + Carpetas de amigos + + + + My Directories + Mis carpetas + + + + Size + Tamaño + + + + Age + Edad + + + + Friend + Amigo + + + + Share Type + Tipo de compartición + + + + What's new + Que pasa + + + + TrustView + + + Zoom : + Zoom: + + + + Update + Actualizar + + + + + Showing: whole network + Mostrando: red entera + + + + This table normaly auto-updates every 10 seconds. + Esta tabla se actualiza automáticamente cada 10 segundos. + + + + Self + uno mismo + + + + Trust + Confianza + + + + is authenticated (one way) by + está autentificado (una dirección) por + + + + Half + A medias + + + + authenticated himself + autentifica si mismo + + + + authenticated each other + se autentifican mútuamente + + + + Full + Completo + + + + is authenticated by + está autentificado por + + + + + peers, including him(her)self. + vecinos, él/ella mism@ incluido. + + + + authenticated + autentificado + + + + Showing: peers connected to + Mostrando: vecinos conectados + + + + TurtleRouterDialog + + + + Search requests + Peticiones de búsqueda + + + + + Tunnel requests + Peticiones de túneles + + + + TurtleRouterDialogForm + + + Router Statistics + Estadística de encaminador + + + + F2F router information + Información sobre encaminamiento F2F + + + + TurtleRouterStatistics + + + Router Statistics + Estadística de encaminador + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + Tráfico del encaminador Turtle: + + + + Tunnel requests Up + Peticiones de túnel subiendo + + + + Tunnel requests Dn + Peticiones de túnel bajando + + + + Incoming file data + Datos de archivos recibios + + + + Outgoing file data + Datos de archivos enviados + + + + Forwarded data + Datos reenviados + + + + ULListDelegate + + + B + B + + + + KB + KB + + + + MB + MB + + + + GB + GB + + + + VMessageBox + + + OK + OK + + + + Cancel + Cancelar + + + + Yes + + + + + No + No + + + + Help + Ayuda + + + + Retry + Reintentar + + + + Show Log + Demostrar historia + + + + Show Settings + Demostrar ajustes + + + + Continue + Continuar + + + + Quit + Cerrar + + + + Browse + Navegar + + + + misc + + + Unknown + Unknown (size) + Desconocido + + + + B + bytes + B + + + + KiB + kibibytes (1024 bytes) + KiB + + + + MiB + mebibytes (1024 kibibytes) + MiB + + + + GiB + gibibytes (1024 mibibytes) + GiB + + + + TiB + tebibytes (1024 gibibytes) + TiB + + + + Unknown + Desconocido + + + + < 1m + < 1 minute + < 1 min + + + + %1 minutes + e.g: 10minutes + %1 minutos + + + + %1h %2m + e.g: 3hours 5minutes + %1h %2min + + + + %1d %2h + e.g: 2days 10hours + %1d %2h + + + + %1y %2d + e.g: 2 years 2days + %1y %2d + + + + k + e.g: 3.1 k + k + + + + M + e.g: 3.1 M + M + + + + G + e.g: 3.1 G + G + + + + T + e.g: 3.1 T + T + + + diff --git a/retroshare-gui/src/lang/retroshare_fi.qm b/retroshare-gui/src/lang/retroshare_fi.qm new file mode 100644 index 000000000..26b0fdcdb Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_fi.qm differ diff --git a/retroshare-gui/src/lang/retroshare_fi.ts b/retroshare-gui/src/lang/retroshare_fi.ts new file mode 100644 index 000000000..52af5e629 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_fi.ts @@ -0,0 +1,15310 @@ + + + + + + + Arial + Arial + + + + @default + + Arial + Arial + + + + AboutDialog + + + About RetroShare + Tietoja RetroSharesta + + + + About + Tietoja + + + + close + sulje + + + + + About RetroShare %1 + Tietoja RetroSharesta %1 + + + + Max score: %1 + Max. pisteet: %1 + + + + Score: %1 + Pisteet: %1 + + + + Level: %1 + Taso: %1 + + + + Have fun ;-) + Pidä hauskaa ;-) + + + + AddFileAssociationDialog + + + File type(extension): + Tiedostotyyppi (pääte): + + + + Use default command + Käytä oletuskomentoa + + + + Command + Komento + + + + RetroShare + RetroShare + + + + Sorry, can't determine system default command for this file + + Järjestelmän oletuskomentoa tälle tiedostolle ei voitu selvittää + + + + AddFileAssotiationDialog + + RetroShare + RetroShare + + + + AddFriendDialog + + Cancel + Peru + + + Done + Valmis + + + Load From File + Lataa tiedostosta + + + RetroShare + RetroShare + + + Certificate Load Failed + Varmenteen lataus epäonnistui + + + + AddFriendWizard + + Cancel + Peru + + + RetroShare + RetroShare + + + Certificate Load Failed + Varmenteen lataus epäonnistui + + + + AddLinksDialog + + + + Add Link + Lisää linkki + + + + Add a new Link + Lisää uusi linkki + + + + Title: + Otsikko: + + + + Url: + Url-osoite: + + + + +2 Great! + +2 Loistava! + + + + +1 Good + +1 Hyvä + + + + 0 Okay + 0 Ok + + + + -1 Sux + -1 Huono + + + + -2 Bad Link + -2 Linkki rikki + + + + Add Anonymous Link + Lisää nimetön linkki + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Lisää linkki pilveen</span></p></body></html> + + + + Cancel + Peru + + + + Add Link Failure + Lisää linkkiongelma + + + + Missing Link and/or Title + Puuttuva linkki ja/tai otsikko + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + Retroshare: tarkennettu haku + + + + Cancel + Peru + + + + Search + Etsi + + + + Add a further search criterion. + Lisää hakuehto. + + + + Reset the search criteria. + Tyhjennä hakuehdot. + + + + Cancels the search. + Peruu haun. + + + + Perform the advanced search. + Suorita tarkennettu haku. + + + + Search Criteria + Hakuehdot + + + + AppearanceDialog + + Language + Kieli + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Valitse RetroSharessa käytetty kieli</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Muutokset kieleen tulevat voimaan vasta RetroSharen uudelleenkäynnistyksen jälkeen.</p></body></html> + + + Style + Tyyli + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Valitse RetroSharen käyttöliittymän tyyli</p></body></html> + + + Style Sheet + Tyylitiedosto + + + + AppearancePage + + + Language + Kieli + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Valitse RetroSharessa käytetty kieli</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Muutokset kieleen tulevat voimaan vasta RetroSharen uudelleenkäynnistyksen jälkeen.</p></body></html> + + + + Style + Tyyli + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Valitse RetroSharen käyttöliittymän tyyli</p></body></html> + + + + Style Sheet + Tyylitiedosto + + + + ApplicationWindow + + + Hide + Piilota + + + + Show + Näytä + + + + + RetroShare + RetroShare + + + Transfers + Siirrot + + + Messages + Viestit + + + + Games Launcher + Pelit + + + + Photo View + Valokuvat + + + + Shared Calendars + Jaetut kalenterit + + + + Statistics + Tilastot + + + + AttachFileItem + + + Form + Lomake + + + File Name + Tiedoston nimi + + + + %p Kb + %p Kb + + + + Cancel Download + Peru lataus + + + + AuthorizationDialog + + Authenticate + Varmenna + + + Authenticate Friend By Entering Their Code + Varmenna ystävä syöttämällä koodi + + + OK + OK + + + Cancel + Peru + + + + BandwidthGraph + + + + Show Settings + Näytä asetukset + + + + Reset + Palauta asetukset + + + + Receive Rate + Vastaanottonopeus + + + + Send Rate + Lähetysnopeus + + + + Style + Tyyli + + + + Changes the transparency of the Bandwidth Graph + Muuttaa siirtonopeuskuvaajan läpinäkyvyyttä + + + + 100 + 100 + + + + % Opaque + % näkyvä + + + + Save + Tallenna + + + + Cancel + Peru + + + + Since: + Alkaen: + + + + Hide Settings + Piilota asetukset + + + + RetroShare Bandwidth Usage + RetroSharen kaistanleveyden käyttö + + + + Always on Top + Aina päällimmäisenä + + + + BgWindow + + Options + Valinnat + + + About + Tietoja + + + + BlogDetails + + + + Blog Details + Blogin yksityiskohdat + + + + Blog Info + Tietoja blogista + + + + Blog Name + Blogin nimi + + + + Popularity + Suosio + + + + Last Post + Viimeisin teksti + + + + Blog ID + Blogin tunniste + + + + Blog Description + Blogin kuvaus + + + + Cancel + Peru + + + + OK + OK + + + + Close + Sulje + + + + BlogMsgItem + + + Form + Lomake + + + + Remove Item + Poista kohde + + + + Expand + Laajenna + + + + Subject + Aihe + + + + Play Media + Toista media + + + + BlogNewItem + + + Remove Item + Poista kohde + + + + Subscribe to Blog + Tilaa blogi + + + + Expand + Laajenna + + + + Blog Decscription + Blogin kuvaus + + + + BlogsDialog + + + Form + Lomake + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogit</span></p></body></html> + + + + Add + Lisää + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Kirjoita blogiin</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blogin nimi</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Lopeta blogin tilaus</span></p></body></html> + + + + Unsubscribe + Lopeta tilaus + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Tilaa blogi</span></p></body></html> + + + + Subscribe + Aloita tilaus + + + + + Create New Blog + Luo uusi blogi + + + + Name + Nimi + + + + ID + Tunniste + + + + Own Blogs + Omat blogit + + + + Subscribed Blogs + Tilatut blogit + + + + Popular Blogs + Suositut blogit + + + + Other Blogs + Muut blogit + + + + Post to Blog + Kirjoita blogiin + + + + Subscribe to Blog + Tilaa blogi + + + + Unsubscribe to Blog + Lopeta blogin tilaus + + + + Show Blog Details + Näytä blogin yksityiskohdat + + + + Create a new Blog + Luo uusi blogi + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + Suosio: %1 +Hakukerrat: %2 +Saatavilla: %3 + + + + BlogsMsgItem + + + Form + Lomake + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blogin aihe</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Päiväys ja aika</span></p></body></html> + + + + Unsubscribe From Channel + Lopeta kanavan tilaus + + + + Comment + Kommentti + + + + Remove Item + Poista kohde + + + + + Expand + Laajenna + + + + Comments here + Kommentit tähän + + + + Hide + Piilota + + + + CalDialog + + + Remove + Poista + + + + Form + Lomake + + + + Local Calendars + Paikalliset kalenterit + + + + Shared Calendar List + Luettelo jaetuista kalenterista + + + + Share Details + Jakamisen yksityiskohdat + + + + Name: + Nimi: + + + + Location: + Sijainti: + + + + ... + ... + + + + Status: + Tila: + + + + Private + Yksityinen + + + + Public + Julkinen + + + + Allow List: + Sallittujen luettelo: + + + + <Disabled> + <Ei käytössä> + + + + Add + Lisää + + + + Peer Calendars + Vertaiskalenterit + + + + CallToaster + + Message + Viesti + + + + CertificatePage + + + Certificate files + Varmennetiedostot + + + + Use PGP certificates saved in files. + Käytä tiedostoihin tallennettuja PGP-varmenteita. + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + Sinun tulee generoida tiedosto, joka sisältää varmenteesi ja antaa se ystävällesi. Voit myös käyttää aiemmin generoitua tiedostoa. + + + + Export my certificate... + Vie varmenteeni... + + + + Browse + Selaa + + + + Select Certificate + Valitse varmenne + + + Certificates (*.pqi *.pem) + Varmenteet (*.pqi *.pem) + + + + Please choose a filename + Ole hyvä ja valitse tiedostonimi + + + + + + + RetroShare + RetroShare + + + + Import friend's certificate... + Tuo ystävän varmenne... + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + Vedä ja pudota ystäviesi varmenteita tähän ikkunaan tai määritä polku allaolevaan laatikkoon + + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroSharen varmenne (*.rsc );;Kaikki tiedostot (*) + + + + Sorry, create certificate failed + Varmenteen luominen epäonnistui + + + + Certificate file successfully created + Varmennetiedosto luotiin + + + + + Sorry, certificate file creation failed + Varmennetiedoston luominen epäonnistui + + + + Certificate Load Failed:something is wrong with %1 + Varmenteen avaaminen epäonnistui: jotakin on vialla %1 + + + + Certificate Load Failed:can't read from file %1 + Varmenteen avaaminen epäonnistui: ei voitu lukea tiedostosta %1 + + + + Certificate Load Failed:file %1 not found + Varmenteen avaaminen epäonnistui: tiedostoa %1 ei löydy + + + + ChanCreateDialog + + Create a new Broadcast Channel + Luo (sp)(sp) uusi yleislähetyskanava + + + Create A New Broadcast Channel + Luo uusi yleislähetyskanava + + + Channel Name: + Kanavan nimi: + + + Type: + Tyyppi: + + + Public Channel (Signed) + Julkinen kanava(sp)(sp)(allekirjoitettu) + + + Private Channel (Encrypted) + Yksityiskanava (salattu) + + + Cancel Channel + Peru kanava + + + Create Channel + Luo kanava + + + + ChanMsgDialog + + Compose + Muodosta + + + Recommended Files + Suositellut tiedostot + + + Send To: + Lähetä: + + + Send + Lähetä + + + Delete Channel + Poista kanava + + + Create Channel MSG + Luo kanavaviesti + + + File Name + Tiedoston nimi + + + Size + Koko + + + Sources + Lähteet + + + Save + Tallenna + + + + ChanMsgItem + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Toggle Message Read Status</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vaihda viestin lukemistilaa</p></body></html> + + + + Toggle Message Read Status + + + + + New + Uusi + + + + Download + Lataa + + + + Play + Toista + + + + Remove Item + Poista kohde + + + + + Expand + Laajenna + + + + Copy RetroShare Link + Kopioi RetroShare-linkki + + + + Unsubscribe From Channel + Lopeta kanavan tilaus + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + Varoitus! Sinulla on vähemmän kuin %1 tuntia ja %2 minuuttia ennen kuin tämä tiedosto tuhotaan. Harkitse sen tallentamista. + + + + Hide + Piilota + + + + ChanNewItem + + + Remove Item + Poista kohde + + + + Subscribe to Channel + Tilaa kanava + + + + Expand + Laajenna + + + + Channel Decscription + Kanavan kuvaus + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + Kanavat + + + Video + Video + + + 1 + 1 + + + + ChannelDetails + + + + Channel Details + Kanavan yksityiskohdat + + + + Channel Info + Kanavan tiedot + + + + Popularity + Suosio + + + + Last Post + Viimeisin teksti + + + + Channel Name + Kanavan nimi + + + + Channel ID + Kanavan tunniste + + + + Channel Description + Kanavan kuvaus + + + + Type + Tyyppi + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Rajoitettu - kaikki voivat lukea, julkaisu rajoitettu (yksityinen julkaisuavain) + + + + Private - (Private Publish Key required to view Messages) + Yksityinen - (Viestien lukemiseen tarvitaan yksityinen julkaisuavain) + + + + Cancel + Peru + + + + OK + OK + + + + Close + Sulje + + + + ChannelFeed + + + Create Channel + Luo kanava + + + + Subscribe To Channel + Tilaa kanava + + + Enter a Keyword here + Kirjoita hakusana tähän + + + Title + Otsikko + + + Description + Kuvaus + + + Reset + Palauta asetukset + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Kanavat</span></p></body></html> + + + Add + Lisää + + + + Display + Näytä + + + + Unsubcribe To Channel + Lopeta kanavan tilaus + + + + Unsubscribe + Lopeta tilaus + + + + Subscribe + Tilaa + + + + Set all to read + Merkitse kaikki luetuiksi + + + + Enable Auto-download + + + + Name + Nimi + + + Popularity + Suosio + + + + Own Channels + Omat kanavat + + + + Subscribed Channels + Tilatut kanavat + + + + Popular Channels + Suositut kanavat + + + + Other Channels + Muut kanavat + + + + Share Channel + Jaa kanava + + + + Copy RetroShare Link + Kopioi RetroShare-linkki + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + Popularity: %1 + Suosio: %1 + + + + No Channel Selected + Ei kanavaa valittuna + + + + + Post to Channel + Lähetä viesti kanavaan + + + + Subscribe to Channel + Tilaa kanava + + + + Unsubscribe to Channel + Lopeta kanavan tilaus + + + + Show Channel Details + Näytä kanavan yksityiskohdat + + + + Restore Publish Rights for Channel + Palauta kanavan julkaisuoikeudet + + + + Edit Channel Details + Muokkaa kanavan yksityiskohtia + + + + ChannelStatsDialog + + 1 + 1 + + + + ChatDialog + + Chat + Keskustelu + + + 1 + 1 + + + Send + Lähetä + + + + ChatMsgItem + + + Remove Item + Poista kohde + + + + Write a quick Message + Pikainen viestinkirjoitus + + + + Send Mail + Lähetä postia + + + + Write Message + Kirjoita viesti + + + + Send + Lähetä + + + + Cancel + Peru + + + Chat + Keskustelu + + + + + Start Chat + Aloita keskustelu + + + + Quick Message + Pikainen viesti + + + + ChatPage + + + General + Yleiset + + + + Chat Settings + Keskusteluasetukset + + + + Enable Emoticons Privat Chat + Aktivoi hymiöt yksityiskeskustelussa + + + + Chat Font + Keskustelun fontti + + + + Change Chat Font + Vaihda keskustelun fonttia + + + + Chat Font: + Keskustelun fontti: + + + + Enable Private Chat History + Aktivoi yksityisten keskustelujen historia + + + + Enable Group Chat History + Aktivoi ryhmäkeskustelujen historia + + + + Send message with Ctrl+Return + Lähetä viesti painamalla Ctrl ja Enter + + + + Chat History + Keskusteluhistoria + + + + Load number of messages (0 = off) + Avaa viestien määrä (0 = pois) + + + + Group Chat + Ryhmäkeskustelu + + + + Private Chat + Yksityinen keskustelu + + + + Style + Tyyli + + + + Group chat + Ryhmäkeskustelu + + + + + + Variant + Muunnelma + + + + + + Author: + Kirjoittaja: + + + + + + Description: + Kuvaus: + + + + Private chat + Yksityinen keskustelu + + + + History + Historia + + + + Enable Emoticons Group Chat + Aktivoi hymiöt ryhmäkeskustelussa + + + + Incoming message in history + Tuleva viesti historiassa + + + + Outgoing message in history + Lähtevä viesti historiassa + + + + Incoming message + Tuleva viesti + + + + Outgoing message + Lähtevä viesti + + + + Outgoing offline message + Lähtevä viesti ei-kytketyssä tilassa + + + + ChatStyle + + + Standard style for group chat + Vakiotyyli ryhmäkeskustelulle + + + + Standard style for private chat + Vakiotyyli yksityiselle keskustelulle + + + + Standard style for history + Vakiotyyli historialle + + + + ConclusionPage + + + Make Friend + Tee ystäväksi + + + + Details about your friend : + Tietoja ystävästä: + + + + Key validity: + Avaimen kelpoisuus: + + + + Email: + Sähköposti: + + + + Options + Valinnat + + + + Add friend to group: + Lisää ystävä ryhmään: + + + + Authenticate friend (Sign GPG Key) + Varmenna ystävä (GPG-allekirjoitus) + + + + Add as friend to connect with + Lisää ystäväksi, johon ottaa yhteys + + + + It seems your friend is already registered. Adding it might just set it's ip address. + Ystäväsi näyttää olevan jo rekisteröitynyt. Hänen lisäämisensä saattaa ainoastaan määrittää IP-osoitteen. + + + + Peer details + Vertaisen yksityiskohdat + + + + Name: + Nimi: + + + + Loc: + Sijainti: + + + + Signers + Allekirjoittajat + + + + ConfCertDialog + + + Cancel + Peru + + + Port: + Portti: + + + Trust Settings + Luottamusasetukset + + + Trust Level + Luottamustaso + + + Trust Their Signature + Luota allekirjoituksiin + + + Sign The Certificate + Allekirjoita varmenne + + + + OK + OK + + + + Details + Yksityiskohdat + + + + Name + Nimi + + + + Loc + Sijainti + + + + Peer Address + Vertaisen osoite + + + + Last Contact + Viimeisin kontakti + + + Peer Details + Vertaisen yksityiskohdat + + + + Peer Info + Vertaisen tiedot + + + + Peer ID + Vertaisen tunniste + + + + Version + Versio + + + + RetroShare ID + RetroSharen tunniste + + + + Status + Tila + + + + Dynamic DNS + Dynaaminen nimipalvelujärjestelmä + + + + Addresses list + Osoiteluettelo + + + + None + Nolla + + + + Marginal + Rajallinen + + + + Full + Täysi + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Deny Friend + Torju ystävä + + + + Make Friend + Tee ystäväksi + + + + Certificate + Varmenne + + + + + Sign GPG key + Allekirjoita GPG-avain + + + + Friend Details + Ystävän yksityiskohdat + + + + Local Address + Paikallinen osoite + + + + External Address + Ulkoinen osoite + + + + + Port + Portti + + + + Your trust in this peer is: + Luottamuksesi vertaiseen on: + + + + GPG Key + GPG-avain + + + + Peer has signed my GPG key + Vertainen on allekirjoittanut GPG-avaimeni + + + + Show Help for Trust Settings and Signing + Näytä ohje luottamusasetuksille ja allekirjoittamiselle + + + + Peer key is signed by : + Vertaisen avaimen on allekirjoittanut: + + + + Apply and Close + Käytä ja sulje + + + + + RetroShare + RetroShare + + + + + Error : cannot get peer details. + Virhe: vertaisen yksityiskohtia ei saatu. + + + + Your key is signed by : + Avaimesi on allekirjoittanut: + + + + Peer key is signed by : + Vertaisen avaimen on allekirjoittanut: + + + + Your trust in this peer is ultimate, it's probably a key you own. + Luottamuksesi tähän vertaiseen on äärimmäinen, se on luultavasti oma avaimesi. + + + + Your trust in this peer is full. + Luottamuksesi tähän vertaiseen on täysi. + + + + Your trust in this peer is marginal. + Luottamuksesi tähän vertaiseen on rajallinen. + + + + Your trust in this peer is none. + Luottamuksesi tähän vertaiseen on nolla. + + + + Your trust in this peer is not set. + Luottamustasi tähän vertaiseen ei ole asetettu. + + + + Peer has authenticated me as a friend and did sign my GPG key + Vertainen on varmentanut minut ystäväkseen ja allekirjoittanut GPG-avaimeni + + + + Peer has not authenticated me as a friend and did not sign my GPG key + Vertainen ei ole varmentanut minua ystäväkseen, eikä allekirjoittanut GPG-avaintani + + + + Signature Failure + Virhe allekirjoitettaessa + + + + Maybe password is wrong + Salasana saattaa olla väärä + + + Copy Peer + Kopioi vertainen + + + + Trust + Luottamus + + + + ConnectDialog + + Peer Details + Vertaisen yksityiskohdat + + + Make Friend + Tee ystäväksi + + + Cancel + Peru + + + + ConnectFriendWizard + + + Connect Friend Wizard + Ohjattu toiminto ystävän yhdistämiseksi + + + + CreateBlog + + + Create new Blog + Luo uusi blogi + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Uusi blogi</span></p></body></html> + + + + Name + Nimi + + + + Description + Kuvaus + + + + Type: + Tyyppi: + + + + Public - Anyone can read and publish (Shared Publish Key) + Julkinen - kaikki voivat lukea ja julkaista (jaettu julkaisuavain) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Rajoitettu - kaikki voivat lukea, julkaisu rajoitettu (yksityinen julkaisuavain) + + + + Private - (Private Publish Key required to view Messages) + Yksityinen - (Viestien lukemiseen tarvitaan yksityinen julkaisuavain) + + + + Allowed Messages + Sallitut viestit + + + + Authemticated Messages + Varmennetut viestit + + + + Anonymous Messages + Nimettömät viestit + + + + Blog Logo + Blogin logo + + + + Add Blog Logo + Lisää logo blogille + + + + Cancel + Peru + + + + Create + Luo + + + + RetroShare + RetroShare + + + + Please add a Name + Ole hyvä ja lisää nimi + + + + Load File + Avaa tiedosto + + + + Pictures (*.png *.xpm *.jpg) + Kuvat (*.png *.xpm *.jpg) + + + + CreateBlogMsg + + + New Blog Post + Uusi blogiteksti + + + + Blog Post + Blogiteksti + + + + Blog Post to: + Blogiteksti vastaanottajalle: + + + + Visual Editor + Visuaalinen muokkaustyökalu + + + + Blog Message + Blogiviesti + + + + Subject : + Aihe: + + + + Html Editor + Html-editori + + + + toolBar + Työkalupalkki + + + + toolBar_2 + Työkalupalkki_2 + + + + blockquoute + Lainauslohko (blockquote) + + + + Increase font Size + Suurenna fonttikokoa + + + + Decrease font size + Pienennä fonttikokoa + + + + Bold + Lihavoitu + + + + Underline + Alleviivattu + + + + Italic + Kursivoitu + + + + Publish + Julkaise + + + + New + Uusi + + + + Code + Koodi + + + + splitPost + Jaa teksti + + + + Ordered List + Järjestetty lista (ol) + + + + Unordered List + Järjestämätön lista (ul) + + + + Clipboard + Leikepöytä + + + + Undo + Kumoa + + + + RetroShare + RetroShare + + + + Please add a Subject + Ole hyvä ja lisää aihe + + + + &File + &Tiedosto + + + + &New + &Uusi + + + + &Open... + &Avaa... + + + + &Save + &Tallenna + + + + Save &As... + Tallenna ni&mellä... + + + + &Print... + Tu&losta... + + + + Print Preview... + Tulostuksen esikatselu... + + + + &Export PDF... + &Vie PDF... + + + + &Quit + Lo&peta + + + + &Edit + &Muokkaa + + + + &Undo + K&umoa + + + + &Redo + To&ista + + + + Cu&t + &Leikkaa + + + + &Copy + K&opioi + + + + &Paste + Lii&tä + + + + &View + &Näytä + + + + &Insert + Lis&ää + + + + &Image + &Kuva + + + + F&ormat + Muotoil&e + + + + &Bold + Liha&voitu + + + + &Italic + Kur&sivoitu + + + + &Underline + Allev&iivattu + + + + + &Left + Tas&aa vasemmalle + + + + + C&enter + &Keskitä + + + + + &Right + Tasaa &oikealle + + + + &Justify + Tasaa &molemmat reunat + + + + &Text Color... + &Tekstin väri... + + + + Application + Sovellus + + + + The document has been modified. +Do you want to save your changes? + Asiakirjaa on muokattu. +Haluatko tallentaa sen? + + + + Open File... + Avaa tiedosto... + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-tiedostot (*.htm *.html);;Kaikki tiedostot (*) + + + + Save as... + Tallenna nimellä... + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + ODF-tiedostot HTML-tiedostot (*.htm *.html);;Kaikki tiedostot (*) + + + + Print Document + Tulosta asiakirja + + + + Export PDF + + + + + Choose Image + Valitse kuva + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Tuetut kuvatiedostot (*.png *.jpeg *.jpg *.gif) + + + + CreateChannel + + + Create a new Channel + Luo uusi kanava + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + <span style="font-size:24pt; font-weight:500;color:#32CD32;">Uusi kanaval</span> + + + + Name + Nimi + + + + check peers you would like to share private publish key with + Tarkista vertaiset, joiden kanssa haluat jakaa yksityisen julkaisuavaimesi + + + + Share Key With + Jaa avain + + + + Contacts: + Kontaktit: + + + + Description + Kuvaus + + + + Type: + Tyyppi: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Rajoitettu - kaikki voivat lukea, julkaisu rajoitettu (yksityinen julkaisuavain) + + + + Private - (Private Publish Key required to view Messages) + Yksityinen - (Viestien lukemiseen tarvitaan yksityinen julkaisuavain) + + + + Allowed Messages + Sallitut viestit + + + + Anonymous Messages + Nimettömät viestit + + + + Authenticated Messages + Varmennetut viestit + + + + Key Sharing + Avaimen jakaminen + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + Avaimen vastaanottajat voivat julkaista kanaville, jotka ovat rajoitettuja ja lukea ja julkaista kanaville, jotka ovat yksityisiä + + + + Share Private Publish Key + Jaa yksityinen julkaisuavain + + + + Channel Logo + Kanavan logo + + + + Add Channel Logo + Lisää logo kanavalle + + + + Cancel + Peru + + + + Create + Luo + + + + RetroShare + RetroShare + + + + Please add a Name + Ole hyvä ja lisää nimi + + + + Load File + Avaa tiedosto + + + + Pictures (*.png *.xpm *.jpg) + Kuvat (*.png *.xpm *.jpg) + + + + CreateChannelMsg + + + New Channel Post + Uusi kirjoitus kanavalle + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">Uusi kirjoitus kanavalle</span></p></body></html> + + + + Channel Post + Kirjoitus kanavalle + + + + Channel Post to: + Kirjoitus kanavalle: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Voit määrittää kanavakirjoituksellesi näyteekuvan.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Voit liittää tiedostoja vetämällä ja pudottamalla.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Anna kanavakirjoituksellesi aihe ja kuvaus.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Voit nähdä liitetiedostosi liitevälilehdeltä.</span></p></body></html> + + + + Add File to Attach + Lisää liitettävä tiedosto + + + + Add Channel Thumbnail + Lisää kanavan näytekuva + + + + Message + Viesti + + + + Subject : + Aihe: + + + + + Attachments + Liitteet + + + + allow channels to get frame for message thumbnail from movie media attachments or not + Salli kanavien poimia viestin näytekuva liitetyistä videotiedostoista tai älä salli + + + + Auto Thumbnail + Automaattinen näytekuva + + + + Drag and Drop Files from Search Results + Vedä ja pudota tiedostoja hakutuloksista + + + + + Drop file error. + Virhe pudotettaessa tiedostoa. + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + Tiedostoa ei löytynyt tai tiedoston nimeä ei hyväksytty. + + + + Add Extra File + Lisää ylimääräinen tiedosto + + + + + RetroShare + RetroShare + + + + File already Added and Hashed + Tiedosto on jo lisätty ja tiivistetty (hash) + + + + Please add a Subject + Ole hyvä ja lisää aihe + + + + Load File + Avaa tiedosto + + + + Pictures (*.png *.xpm *.jpg) + Kuvat (*.png *.xpm *.jpg) + + + + CreateForum + + + Name + Nimi + + + + Type: + Tyyppi: + + + + Authenticated Messages + Varmennetut viestit + + + + Cancel + Peru + + + RetroShare + RetroShare + + + + Please add a Name + Ole hyvä ja lisää nimi + + + + Create new Forum + Luo uusi foorumi + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Uusi foorumi</span></p></body></html> + + + + Description + Kuvaus + + + + Public - Anyone can read and publish (Shared Publish Key) + Julkinen - kaikki voivat lukea ja julkaista (jaettu julkaisuavain) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Rajoitettu - kaikki voivat lukea, julkaisu rajoitettu (yksityinen julkaisuavain) + + + + Private - (Private Publish Key required to view Messages) + Yksityinen - (Viestien lukemiseen tarvitaan yksityinen julkaisuavain) + + + + Allowed Messages + Sallitut viestit + + + + Anonymous Messages + Nimettömät viestit + + + + Create + Luo + + + + CreateForumMsg + + + Close + Sulje + + + + Post Forum Message + Lähetä viesti foorumiin + + + + Forum + Foorumi + + + + Attach File + Liitä tiedosto + + + + Forum Post + Foorumikirjoitus + + + + Sign Message + Allekirjoita viesti + + + + Subject + Aihe + + + + + Paste RetroShare Link + Liitä RetroShare-linkki + + + + Attach files via drag and drop + Liitä tiedostoja vetämällä ja pudottamalla + + + + You can attach files via drag and drop here in this window + Voit liittää tiedostoja vetämällä ja pudottamalla niitä tähän ikkunaan + + + + Post Forum Msg + Lähetä viesti foorumiin + + + + Paste full RetroShare Link + Liitä kokonainen RetroShare-linkki + + + + In Reply to + Vastauksena + + + + RetroShare + RetroShare + + + + Please set a Forum Subject and Forum Message + Ole hyvä ja aseta foorumin aihe ja foorumiviesti + + + + Add Extra File + Lisää ylimääräinen tiedosto + + + + + Drop file error. + Virhe pudotettaessa tiedostoa. + + + + File not found or file name not accepted. + Tiedostoa ei löytynyt tai tiedoston nimeä ei hyväksytty. + + + + Directory can't be dropped, only files are accepted. + Hakemistoa ei voi pudottaa, ainoastaan tiedostot ovat hyväksyttyjä. + + + + CreateGroup + + + Create a Group + Luo ryhmä + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Luo ryhmä</span></p></body></html> + + + + Group Name + Ryhmän nimi + + + + Enter a name for your group + Anna ryhmälle nimi + + + + Edit Group + Muokkaa ryhmää + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Muokkaa ryhmää</span></p></body></html> + + + + CryptoPage + + + RetroShare + RetroShare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + Julkinen avaimesi kopioitiin leikepöydälle, liitä ja lähetä se ystävällesi sähköpostilla tai muulla tavoin + + + + Save as... + Tallenna nimellä... + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroSharen varmenne (*.rsc );;Kaikki tiedostot (*) + + + + Public Key + Julkinen avain + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Kopioi avaimeni leikepöydälle</p></body></html> + + + + Copy Key + Kopioi avain + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Tallenna avain tiedostoon</p></body></html> + + + + Save Key + Tallenna avain + + + + CryptographyDialog + + RSA Key Size + RSA-avainkoko + + + Rijndael Block size + Rijndael-lohkokoko + + + 128 Bits + 128 bittiä + + + 192 Bits + 192 bittiä + + + 256 Bits + 256 bittiä + + + Rijndael Key Size + Rijndael-avaimen koko + + + Rijndael Mode + Rijndael-tila + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + Rijndael Padding + Rijndael-täyte + + + PKCS7 + PKCS7 + + + Zeros + Zeros + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Rijndael-palautteen koko + + + Key Size: + Avaimen koko: + + + Block Size: + Lohkon koko: + + + Feedback Size: + Palautteen koko: + + + Mode: + Tila: + + + Padding: + Täyte: + + + RetroShare + RetroShare + + + + DHTStatus + + + DHT + DHT + + + + DHT On + DHT päällä + + + + RetroShare users in DHT (Total DHT users) + RetroSharen käyttäjiä DHT:ssä (Kaikki DHT:n käyttäjät) + + + + DHT Off + DHT Pois päältä + + + + DLListDelegate + + + B + t + + + + KB + Kt + + + + MB + Mt + + + + GB + Gt + + + + DetailsDialog + + + Details + Yksityiskohdat + + + + + General + Yleiset + + + + File Name: + Tiedoston nimi: + + + + Hash: + Tiiviste (hash): + + + + Size: + Koko: + + + + Status: + Tila: + + + + Priority: + Tärkeysjärjestys: + + + + Type: + Tyyppi: + + + + Transfer + Siirto + + + + Sources: + Lähteet: + + + + Datarate: + Siirtonopeus: + + + + Completed: + Valmiina: + + + + Chunk size: + Palasten koko: + + + + + Number of Chunks + Palasten lukumäärä + + + + Chunks: + Palaset: + + + + Remaining: + Jäljellä: + + + + Date + Päiväys + + + + Download time: + Latauksen kesto: + + + + + Comments + Kommentit + + + + + retroshare link(s) + RetroSharen linkki/linkit + + + + Copy + Kopioi + + + + OK + OK + + + + Cancel + Peru + + + + Rating + Arvostelu + + + + File Name + Tiedoston nimi + + + + Not Rated + Ei arvosteltu + + + + No Comments + Ei kommentteja + + + + DirectoriesDialog + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Sisääntulevat tiedostot</span></p></body></html> + + + Add Shared Directory + Lisää jaettu hakemisto + + + Shared Directories + Jaetut hakemistot + + + + DirectoriesPage + + + Incoming Directory + Sisääntulevien hakemisto + + + + Partials Directory + Keskeneräisten hakemisto + + + + Automatically share incoming directory (Recommended) + Jaa sisääntulevien hakemisto automaattisesti (suositeltavaa) + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + Muista tiedostojen tiivisteet (hash), vaikka ne eivät +olisi jaossa. Tämä voi olla hyödyllistä, jos jaat ulkoiselta +kiintolevyltä, jolloin voit välttyä tekemästä tiivisteitä +tiedostoille uudelleen, kun kytket sen kiiinni. + + + + Remember hashed files for + Muista tiivistetyt (hashed) tiedostot + + + + days + päivää + + + + Forget any hashed file that is not anymore shared. + Unohda kaikki tiivistetyt (hashed) tiedostot, jotka eivät ole enää jaossa. + + + + Clean Hash Cache + Tyhjennä tiivisteiden (hash) välimuisti + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + Jaetut hakemistot + + + + Edit Share + Muokkaa jakoa + + + Incoming files + Sisääntulevat tiedostot + + + Add a Share Directory + Lisää jaettu hakemisto + + + Remove Shared Directory + Poista jaettu hakemisto + + + + + Browse + Selaa + + + Add Shared Directory + Lisää jaettu hakemisto + + + + Set Incoming Directory + Määritä sisääntulevien hakemisto + + + + Set Partials Directory + Määritä keskeneräisten hakemisto + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + Aloita tiedosto + + + + <b>Download completed</b> + <b>Lataus suoritettu</b> + + + + Close + Sulje + + + File %1 does not exist at location. + Tiedostoa %1 ei pystytä paikantamaan. + + + + EditChanDetails + + + Channel Details + Kanavan yksityiskohdat + + + + Cancel + Peru + + + + OK + OK + + + + Edit Channel Details + Muokkaa kanavan yksityiskohtia + + + + Channel Info + Kanavan tiedot + + + + Channel Name + Kanavan nimi + + + + Channel Description + Kanavan kuvaus + + + + Add Channel Logo + Lisää kanavalle logo + + + + Load File + Avaa tiedosto + + + + Pictures (*.png *.xpm *.jpg) + Kuvat (*.png *.xpm *.jpg) + + + + EditForumDetails + + + Forum Details + Foorumin yksityiskohdat + + + + Cancel + Peru + + + + OK + OK + + + + Edit Forum Details + Muokkaa foorumin yksityiskohtia + + + + Forum Info + Foorumin tiedot + + + + Forum Name + Foorumin nimi + + + + Forum Description + Foorumin kuvaus + + + + EmailPage + + + Invite Friends by Email + Kutsu ystäviä sähköpostilla + + + + Enter your friends' email addresses (seperate each on with a semicolon) + Kirjoita ystäviesi sähköpostiosoitteet (erottele osoitteet puolipisteellä) + + + + Your friends' email addresses: + Ystäviesi sähköpostiosoitteet: + + + + Enter Friends Email addresses + Kirjoita ystäviesi sähköpostiosoitteet + + + + Subject: + Aihe: + + + + Friend invites you to check out RetroShare + Ystäväsi kutsuu sinut kokeilemaan RetroSharea + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + Ystäväsi käyttää RetroSharea kommunikoidakseen turvallisesti ja kutsuu sinut jakamaan kanssaan tiedostoja. <br>RetroShare on ilmainen ja sen käyttäminen on turvallista: se ei sisällä viruksia, vakoiluohjelmia, eikä mainoksia ja sen asennus voidaan poistaa vaivattomasti. <br>Lisätietoja saat verkkosivuiltamme http://retroshare.sourceforge.net tai voit ladata ohjelman täältä: http://retroshare.sourceforge.net/downloads.html <br>Pikaisiin näkemisiin RetroSharessa! + + + + ErrorMessagePage + + + Sorry, some error appeared + Valitettavasti on tapahtunut jokin virhe + + + + Here is the error message: + Tässä on virheen viesti: + + + + ExampleDialog + + + Vote Up + Äänestä ylös + + + + Vote Down + Äänestä alas + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Ystävät</span></p></body></html> + + + + Status + Tila + + + + Person + Henkilö + + + + Auto Connect + Yhdistä automaattisesti + + + + Trust Level + Luottamustaso + + + + Peer Address + Vertaisen osoite + + + + Last Contact + Viimeisin kontakti + + + + Organisation + Organisaatio + + + + Location + Sijainti + + + + Country + Maa + + + + Person Id + Henkilön tunniste + + + + Auth Code + Varmennekoodi + + + + # + # + + + + ExprParamElement + + + + + to + vastaanottajalle + + + + ignore case + sivuuta kirjainkoko + + + + + dd.MM.yyyy + pp.KK.vvvv + + + + + KB + Kt + + + + + MB + Mt + + + + + GB + Gt + + + + ExpressionWidget + + + Expression Widget + Katso widget http://www.tsk.fi/tsk/termitalkoot/ + Lausekepienohjelma + + + + Delete this expression + Poista tämä lauseke + + + + FileAssociationsPage + + + &New + &Uusi + + + + Add new Association + Katso http://www.tsk.fi/tsk/termitalkoot/ + Lisää uusi sidos + + + + &Edit + &Muokkaa + + + + Edit this Association + Muokkaa tätä sidosta + + + + &Remove + &Poista + + + + Remove this Association + Poista tämä sidos + + + + File type + Tiedostotyyppi + + + + Friend Help + Ystäväohje + + + + You this + Sinä tämä + + + + FileTransferInfoWidget + + Chunk map: + Palasten kartta: + + + Active chunks: + Aktiiviset palaset: + + + Availability map ( + Saatavuuskartta ( + + + active sources + aktiivisia lähteitä + + + File info: + Tiedoston tiedot: + + + File hash: + Tiedoston tiiviste (hash): + + + File size: + Tiedoston koko: + + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + tavua + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + Jäljellä + + + + Number of sources + + + + + Chunk strategy + Palasten strategia + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + Chunk size: + Palasten koko: + + + Number of chunks: + Palasten lukumäärä: + + + Transfered: + Siirretty: + + + Remaining: + Jäljellä: + + + Number of sources: + Lähteiden lukumäärä: + + + Chunk strategy: + Palasten strategia: + + + Transfer type: + Siirtotyyppi: + + + + FindWindow + + %1 KB + %1 kB + + + File Name + Tiedoston nimi + + + Size + Koko + + + + FlatStyle_RDM + + + Friends Directories + Ystävien hakemistot + + + + My Directories + Omat hakemistot + + + + Size + Koko + + + + Age + Ikä + + + + Friend + Ystävä + + + + Share Type + Jakamisen tyyppi + + + + Directory + Hakemisto + + + + FofPage + + + Friends of friends + Ystävien ystävät + + + + Select now who you want to make friends with. + Valitse nyt, kenen kanssa haluat ystävystyä. + + + + Show me: + Näytä minulle: + + + + Any peer I've not signed + Kaikki vertaiset, joita en ole allekirjoittanut + + + + Friends of my friends who already trust me + Ystävieni ystävät, jotka jo luottavat minuun + + + + Signed peers showing as denied + Allekirjoitetut vertaiset, jotka näkyvät torjuttuina + + + + Peer name + Vertaisen nimi + + + + Also signed by + Muita allekirjoittaneita + + + + Peer id + Vertaisen tunniste + + + + Make friend with these peers + Ystävysty näiden vertaisten kanssa + + + + *** None *** + ***Ei mitään*** + + + + ForumDetails + + + + Forum Details + Foorumin yksityiskohdat + + + + Forum Info + Foorumin tiedot + + + + Forum Name + Foorumin nimi + + + + Popularity + Suosio + + + + Last Post + Viimeisin viesti + + + + Forum ID + Foorumin tunniste + + + + Forum Description + Foorumin kuvaus + + + + Security + Turvallisuus + + + + Allowed Messages + Sallitut viestit + + + + Authemticated Messages + Varmennetut viestit + + + + Anonymous Messages + Nimettömät viestit + + + + Cancel + Peru + + + + OK + OK + + + + Apply and Close + Käytä ja sulje + + + + ForumMsgItem + + + Remove Item + Poista kohde + + + + Expand + Laajenna + + + + + + Subject: + Aihe: + + + + Unsubscribe To Forum + Lopeta foorumin tilaus + + + + Reply + Vastaa + + + + Send + Lähetä + + + + Signed + Allekirjoitettu + + + + Forum Post + Foorumikirjoitus + + + + Unknown Forum Post + + + + + + + Anonymous + Nimetön + + + + In Reply to + Vastauksena viestiin + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + Lomake + + + + Remove Item + Poista kohde + + + + Subscribe to Forum + Tilaa foorumi + + + + Expand + Laajenna + + + + Forum Description + Foorumin kuvaus + + + + ForumPage + + + Misc + Sekalaiset + + + + Set message to read on activate + Merkitse viesti luetuksi aktivoitaessa + + + + Expand new messages + Laajenna uudet viestit + + + + ForumsDialog + + + Subscribe to Forum + Subscribe to Forum + + + + Unsubscribe to Forum + Lopeta foorumin tilaus + + + + New Forum + Uusi foorumi + + + + Show Forum Details + Näytä foorumin yksityiskohdat + + + + Edit Forum Details + Muokkaa foorumin yksityiskohtia + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + Kopioi RetroShare-linkki + + + + Reply + Vastaa + + + + Reply to Author + Vastaa kirjoittajalle + + + + Expand all + Laajenna kaikki + + + + Collapse all + Kutista kaikki + + + + AUTHD + + + + + Your Forums + Foorumisi + + + + Subscribed Forums + Tilatut foorumit + + + + Popular Forums + Suositut foorumit + + + + Other Forums + Muut foorumit + + + + + Mark as read + Merkitse luetuksi + + + + + Mark as unread + Merkitse lukemattomaksi + + + + + with children + jälkeläisten kanssa + + + + Mark all as read + Merkitse kaikki luetuiksi + + + + Mark all as unread + Merkitse kaikki lukemattomiksi + + + + Hide + Piilota + + + + Expand + Laajenna + + + Popularity: + Suosio: + + + Anonymous + Nimetön + + + signed + allekirjoitettu + + + none + ei mitään + + + + + RetroShare + RetroShare + + + + No Forum Selected! + Ei valittua foorumia! + + + + You cant reply a Anonymous Author + Et voi vastata nimettömälle kirjoittajalle + + + + + Date + Päiväys + + + + + Title + Otsikko + + + + + Start New Thread + Aloita uusi viestiketju + + + New Message + Uusi viesti + + + Add + Lisää + + + RetroShare Forums + RetroSharen foorumit + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Foorumi:</p></body></html> + + + + Last Post + Viimeisin viesti + + + + Threaded View + Ketjunäkymä + + + + Flat View + Tasanäkymä + + + + + Author + Kirjoittaja + + + + Signed + Allekirjoitettu + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Viestiketju:</span></p></body></html> + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Hae foorumeista</span></p></body></html> + + + + Reset + Palauta asetukset + + + + Content + Sisältö + + + + Create Forum + Luo foorumi + + + + Print + Tulosta + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Foorumit</span></p></body></html> + + + + Start new Thread for Selected Forum + Aloita uusi viestiketju valitussa foorumissa + + + + Display + Näytä + + + + Previous Thread + Edellinen viestiketju + + + + Next Thread + Seuraava viestiketju + + + + Reply Message + Vastaa viestiin + + + + PrintPreview + Tulostuksen esikatselu + + + + ForumsFillThread + + + + Anonymous + Nimetön + + + + + signed + allekirjoitettu + + + + + none + ei mitään + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ystävät</span></p></body></html> + + + + Add + Lisää + + + + Display + Näytä + + + + Friends + Ystävät + + + + Status + Tila + + + + Add or Change your Avatar + Lisää tai vaihda avatar + + + + Edit Personal message + Muokkaa henkilökohtaista viestiä + + + + Group Chat + Ryhmäkeskustelu + + + + Messages entered here are sent to all collected friends + + + + + Bold + Lihavoitu + + + + Underline + Alleviivattu + + + + Italic + Kursivoitu + + + + Font + Fontti + + + + Text Color + Tekstin väri + + + + Attach File + Liitä tiedosto + + + + Send + Lähetä + + + + Clear Chat History + Tyhjennä keskusteluhistoria + + + + + Add Friend + Lisää ystävä + + + + Create new Profile + Luo uusi profiili + + + + + Create new Forum + Luo uusi foorumi + + + + F + F + + + + + Create new Channel + Luo uusi kanava + + + + C + C + + + + Add your Avatar Picture + Lisää avatarkuva + + + + A + A + + + + Set your Personal Message + Aseta henkilökohtainen viesti + + + + Edit your status Message + Muokkaa tilaviestiäsi + + + + Browse Message History + Selaa viestihistoriaa + + + + Browse History + Selaa historiaa + + + + + Save Chat History + Tallenna keskusteluhistoria + + + + Hide Offline Friends + Piilota offline-ystävät + + + + Hide Status Column + Piilota tilasarake + + + + + Sort by State + Järjestä tilan mukaan + + + + Hide State + + + + + + Add a new Group + Lisää uusi ryhmä + + + + + Sort Descending Order + Laskeva järjestys + + + + + Sort Ascending Order + Nouseva järjestys + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + Profiili + + + + News Feed + Uutissyöte + + + + Welcome to RetroShare's group chat. + Tervetuloa RetroSharen ryhmäkeskusteluun. + + + + me + minä + + + + Paste RetroShare Link + Liitä RetroShare-linkki + + + + Group + Ryhmä + + + + Friend + Ystävä + + + + Location + Sijainti + + + + Message Group + Viestiryhmä + + + + Edit Group + Muokkaa ryhmää + + + + Remove Group + Poista ryhmä + + + + Chat + Keskustelu + + + + Message Friend + Lähetä viesti ystävälle + + + + Friend Details + Ystävän yksityiskohdat + + + + Recommend this Friend to... + Suosittele tätä ystävää... + + + + Connect To Friend + Yhdistä ystävään + + + + Copy RetroShare Link + Kopioi RetroShare-linkki + + + + + Paste Friend Link + Liitä ystävälinkki + + + + Deny Friend + Torju ystävä + + + + Remove Friend Location + Poista ystävän sijainti + + + + Add to group + Lisää ryhmään + + + + Move to group + Siirrä ryhmään + + + + Groups + Ryhmät + + + + Remove from group + Poista ryhmästä + + + + Remove from all groups + Poista kaikista ryhmistä + + + + Expand all + Laajenna kaikki + + + + Collapse all + Kutista kaikki + + + + location + sijainti + + + + + Available + Saatavilla + + + + Save Certificate + Tallenna varmenne + + + + Certificates (*.pqi) + Varmeneet (*.pqi) + + + + Do you want to remove this Friend? + Haluatko poistaa tämän ystävän? + + + + is typing... + kirjoittaa... + + + + + New group chat + Uusi ryhmäkeskustelu + + + + Do you really want to physically delete the history? + + + + + Load File + Avaa tiedosto + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + Lisää ylimääräinen tiedosto + + + + + Drop file error. + Virhe pudotettaessa tiedostoa. + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + Tiedostoa ei löytynyt tai tiedoston nimeä ei hyväksytty. + + + + Save as... + Tallenna nimellä... + + + + Text File (*.txt );;All Files (*) + Tekstitiedosto (*.txt );;Kaikki tiedostot (*) + + + + GSettingsWin + + General + Yleiset + + + Network + Verkko + + + Directories + Hakemistot + + + Server + Palvelin + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + Peru peli + + + + Add to Invite List + Lisää kutsuluetteloon + + + + Remove from Invite List + Poista kutsuluettelosta + + + + + Interested in Playing + Kiinnostunut pelaamaan + + + + Not Interested in Game + Ei kiinnostunut pelaamaan + + + + + Not Interested + Ei kiinnostunut + + + + Confirm Peer in Game + Vahvista vertainen peliin + + + + Remove Peer from Game + Poista vertainen pelistä + + + + Interested in Game + Kiinnostunut pelaamaan + + + + Quit Game + Poistu pelistä + + + + Server + Palvelin + + + + Status + Tila + + + + Accept + Hyväksy + + + + Form + Lomake + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Pelien käynnistys</span></p></body></html> + + + + Game: + Peli: + + + + GameType: 0. Want to Add your Game here? + Pelityyppi: 0. Haluatko lisätä pelisi tähän? + + + + GameType: 1. Get In Touch with the developers + Pelityyppi: 1. Ota yhteyttä kehittäjiin + + + + GameType: 2. + Pelityyppi: 2. + + + + Title / Comment + Otsikko / Kommentti + + + + Create New Game + Luo uusi peli + + + + Invite All Friends + Kutsu kaikki ystävät + + + + Game Type + Pelityyppi + + + + Comment + Kommentti + + + + GameID + Pelitunniste + + + + Player + Pelaaja + + + + + Invite + Kutsu + + + + Interested + Kiinnostunut + + + + Delete + Tuhoa + + + + + Move Player + Siirrä pelaaja + + + + Play Game + Pelaa + + + + GenCertDialog + + RetroShare setup + RetroShare-asetukset + + + Load Trusted Certificate (Optional) + Lataa luotettu varmenne (valinnainen) + + + + + + Create new Profile + Luo uusi profiili + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + Näyttää siltä, että sinulla ei ole yhtään profiilia (GPG-avaimia). Ole hyvä ja täytä oheinen lomake generoidaksesi profiilin tai käytä omavalintaista gnupg-avainten hallintaohjelmaa. + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier';">Your profile is associated to a GPG key</span></pre></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier';">Profiilisi on sidoksissa GPG-avaimeen</span></pre></body></html> + + + + Generate a new Profile + Generoi uusi profiili + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier'; font-size:8pt;">Your profile is associated to a GPG key</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier'; font-size:8pt;">Profiilisi on sidoksissa GPG-avaimeen</span></p></body></html> + + + + Use Profile + Käytä profiilia + + + + Name + Nimi + + + + Enter here your nickname + Kirjoita nimimerkkisi + + + + Email + Sähköposti + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + Ole varovainen: tämä sähköposti näkyy ystävillesi ja ystäviesi +ystäville. GPG tarvitsee tämän tiedon, mutta pysyäksesi +nimettömänä voit käyttää keksittyä osoitetta. + + + + This Password is for GPG + Tämä salasana on GPG:tä varten + + + + Password + Salasana + + + + Put a strong password here. This password protects your GPG key. + Laita tähän vahva salasana. Tämä salasana suojelee GPG-avaintasi. + + + + Location + Sijainti + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + Laita tähän sijainti, jolla on merkitys, esim.: koti, kannettava, jne. Tätä kenttää käytetään erottamaan toisistaan saman profiilin (GPG-avain) eri paikoissa sijaitsevat asennukset. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Luo uusi profiili</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare käyttää GPG-avaimia identiteetin hallintaan. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Voit käyttää olemassaolevaa profiilia (GPG-avain) tai luoda uuden tällä lomakkeella.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Voit asentaa RetroSharen eri paikkoihin ja käyttää silti samaa profiilia (GPG-avain).</span></p></body></html> + + + + Generate New Profile + Generoi uusi profiili + + + + + Your profile is associated to a GPG key + + + + + Info + Tiedot + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ystävä</span></p></body></html> + + + Select File + Valitse tiedosto + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nimi:</p></body></html> + + + Generate New Certificate + Luo uusi varmenne + + + + + Create new Location + Luo uusi sijainti + + + + + Generate new Location + Generoi uusi sijainti + + + + + Create a new Location + Luo uusi sijainti + + + + + Generate new Profile + Generoi uusi profiili + + + + + Create a new Profile + Luo uusi profiili + + + + + Generate GPG key Failure + Virhe generoitaessa GPG-avainta + + + + Location field is required with a minimum of 3 characters + Sijaintikenttä on pakollinen ja minimissään kolme merkkiä + + + + All fields are required with a minimum of 3 characters + Kaikki kentät ovat pakollisia ja minimissään kolme merkkiä + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + Generoidaan uutta GPG-avainta, ole hyvä ja odota: tämä prosessi vaatii suurten alkulukujen generointia ja voi kestää joitakin minuutteja hitailla tietokoneilla. + +Kirjoita GPG-salasanasi pyydettäessä allekirjoittaaksesi uuden avaimesi. + + + + Select Trusted Friend + Valitse luotettu ystävä + + + + Certificates (*.pqi *.pem) + Varmenteet (*.pqi *.pem) + + + + + Multiple instances + Useita instansseja + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Toinen RetroShare, joka käyttää samaa profiilia on jo käynnissä järjestelmässäsi. Ole hyvä ja sulje se ensin + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Odottamaton virhe haettaessa yhden instanssin lukitusta + + + + Generate ID Failure + Virhe generoitaessa tunnistetta + + + + Failed to Load your new Certificate! + Uuden varmenteesi avaaminen epäonnistui! + + + Location: + Sijainti: + + + + GeneralDialog + + Style + Tyyli + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Valitse RetroSharen käyttöliittymän tyyli</p></body></html> + + + Language + Kieli + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Valitse RetroSharessa käytetty kieli</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Muutokset kieleen tulevat voimaan vasta RetroSharen uudelleenkäynnistyksen jälkeen.</p></body></html> + + + Style Sheet + Tyylitiedosto + + + Login + Kirjautuminen + + + Misc + Sekalaiset + + + + GeneralPage + + Keys manager + Avainten hallinta + + + Style + Tyyli + + + Choose RetroShare's interface style + Valitse RetroSharen käyttöliittymän tyyli + + + Language + Kieli + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Muutokset kieleen tulevat voimaan vasta RetroSharen uudelleenkäynnistyksen jälkeen.</p></body></html> + + + Choose the language used in RetroShare + Valitse RetroSharessa käytettävä kieli + + + Login + Kirjautuminen + + + + Startup + Käynnistys + + + + Start RetroShare when my system starts + Käynnistä RetroShare yhtäaikaa järjestelmän kanssa + + + + Start minimized + Käynnistä pienennettynä + + + + Start minimized on system start + + + + + Misc + Sekalaiset + + + + Do not show the Quit RetroShare MessageBox + Älä näytä viestilaatikkoa RetroSharea suljettaessa + + + + Do not Minimize to Tray Icon + Älä pienennä ilmaisinalueelle + + + + Auto Login + Automaattinen kirjautuminen + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + Jouten + + + + Idle Time + Joutenoloaika + + + + seconds + sekuntia + + + + GraphFrame + + + Recv: + Vast: + + + + + + %1 KB/s + %1 Kt/s + + + + Sent: + Läh: + + + + %1 KB + %1 Kt + + + + %1 MB + %1 Mt + + + + %1 GB + %1 Gt + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + Napauta ja vedä solmuja paikasta toiseen ja suurenna hiiren rullalla tai '+' ja '-' -näppäimillä + + + + GroupDefs + + + Friends + Ystävät + + + + Family + Perhe + + + + Co-Workers + Työtoverit + + + + Other Contacts + Muut kontaktit + + + + Favorites + Suosikit + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + Otsikko + + + + Description + Kuvaus + + + + Reset + Palauta asetukset + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + ja + + + + and / or + ja / tai + + + + or + tai + + + + Name + Nimi + + + + Path + Polku + + + + Extension + Pääte + + + + Hash + Tiiviste (hash) + + + + Date + Päiväys + + + + Size + Koko + + + + Popularity + Suosio + + + + contains + sisältää + + + + contains all + sisältää kaikki + + + + is + on + + + + less than + pienempi kuin + + + + less than or equal + pienempi tai sama kuin + + + + equals + yhtä kuin + + + + greater than or equal + suurempi tai sama kuin + + + + greater than + suurempi kuin + + + + is in range + on välillä + + + + HelpBrowser + + + + Error Loading Help Contents: + Virhe ladattaessa ohjeen sisältöä: + + + + Supplied XML file is not a valid Contents document. + Tarjottu XML-tiedosto ei ole toimiva sisältöasiakirja. + + + + Search reached end of document + Haku päättyi asiakirjan loppuun + + + + Search reached start of document + Haku päättyi asiakirjan alkuun + + + + Text not found in document + Tekstiä ei löydetty asiakirjasta + + + + Found %1 results + Löydettiin %1 tulosta + + + + + Search + Etsi + + + + Home + Koti + + + + Close + Sulje + + + + + RetroShare Help + RetroSharen ohje + + + + Find: + Etsi: + + + + Find Previous + Etsi edellinen + + + + Find Next + Etsi seuraava + + + + Case sensitive + Merkkikokoriippuvainen + + + + Whole words only + Vain kokonaisia sanoja + + + + Contents + Sisältö + + + + Help Topics + Ohjeen aiheet + + + + Searching for: + Haetaan: + + + + Found Documents + Löydetyt asiakirjat + + + + Back + Takaisin + + + + Move to previous page (Backspace) + Siirry edelliselle sivulle (askelpalautin) + + + + Backspace + Askelpalautin + + + + Forward + Eteenpäin + + + + Move to next page (Shift+Backspace) + Siirry seuraavalle sivulle (Shift+askelpalautin) + + + + Shift+Backspace + Shift+askelpalautin + + + + Move to the Home page (Ctrl+H) + Siirry kotisivulle (Ctrl+H) + + + + Ctrl+H + Ctrl+H + + + + + + Find + Etsi + + + + Search for a word or phrase on current page (Ctrl+F) + Etsi sanaa tai lausetta tältä sivulta (Ctrl+F) + + + + Ctrl+F + Ctrl+F + + + + Close Vidalia Help + Sulje Vidalia-ohje + + + + Esc + Esc + + + + HelpDialog + + + About + Tietoja + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare on avoimen lähdekoodin alustariippumaton </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">yksityinen ja turvallinen hajautettu kommunikaatioalusta. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Se antaa sinulle mahdollisuuden jakaa turvallisesti ystäviesi kanssa </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">käyttäen luottamuksen verkkoa vertaisten varmentamiseen ja OpenSSL-tekniikkaa kaiken kommunikaation salaamiseen. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare tarjoaa tiedostojenjaon, keskustelut, viestit ja kanavat</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Hyödyllisiä linkkejä lisätietoihin:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">RetroSharen verkkosivut</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">RetroSharen Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroSharen foorumi</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">RetroSharen projektisivu</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamuttin kotisivut.</span></a></li></ul></body></html> + + + + Authors + Tekijät + + + + Thanks to + Kiitokset + + + + Translation + Käännös + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroSharen kääntäjät:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Ranska</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Puola: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbia</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Ruotsi:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroSharen verkkosivujen kääntäjät:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Ruotsi: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Saksa: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Puola: </span>Maciej Mrug</p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + License Agreement + Lisenssisopimus + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Tietoja RetroSharesta</span></p></body></html> + + + + HelpTextBrowser + + + Error opening help file: + Virhe avattaessa ohjetiedostoa: + + + + Opening External Link + Avataan ulkoista linkkiä + + + + Unable to Open Link + Linkin avaaminen epäonnistui + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + RetroShare voi avata valitsemasi linkin verkkoselaimessasi. Jos selaimesi ei ole säädetty käyttämään Tor-verkkoa, linkin avaaminen ei tapahdu nimettömänä. + + + + Do you want Retroshare to open the link in your Web browser? + Haluatko, että RetroShare avaa linkin verkkoselaimessasi? + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + RetroShare ei onnistunut avaamaan valitsemaasi linkkiä verkkoselaimessasi. Voit silti kopioda linkin osoitteen ja liittää sen selaimeesi. + + + + ImHistoryBrowser + + + Message History + Viestihistoria + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Viestihistoria</span></p></body></html> + + + + Reset + Palauta asetukset + + + + + Copy + Kopioi + + + + Remove + Poista + + + + Mark all + Merkitse kaikki + + + + Delete + Tuhoa + + + + Clear history + Tyhjennä historia + + + + Send + Lähetä + + + + InfoDialog + + + Info + Tietoja + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare käyttää GPG-avaimia ja tämä on vaatimus profiilin luomiseksi RetroShareen.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Sinun tulee vaihtaa GPG-avaimia ystäviesi kanssa, joko sähköpostitse tai miten ikinä haluatkaan.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Kun saat ystäväsi GPG-avaimen, lisää se RetroShareen ohjatulla ystävänlisäämistoiminnolla.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. Linuxissa sinun tulee asentaa GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. Windowsissa sinun tulee asentaa gpg4win-paketti GPG-avainten luomista varten:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. Kun haluat luoda oman GPG-avaimen GPA:lla, etkä onnistu, voit käyttää sen sijaan WinPT:tä:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + IntroPage + + + &Make friend with selected friends of my friends + &Ystävysty valitsemieni ystävien ystävien kanssa + + + + Add a new Friend + Lisää uusi ystävä + + + This wizard will help you to connect to your friend(s) to RetroShare network. There are five possible ways to do this: + Tämä ohjattu toiminto auttaa sinua yhteyden saamisessa ystäviisi RetroShare-verkossa. Tämän aikaansaamiseksi on viisi tapaa: + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + &Anna varmenne manuaalisesti + + + + &You get a certificate file from your friend + &Saat varmenteen ystävältäsi + + + + &Enter RetroShare ID manually + A&nna RetroSharen tunniste manuaalisesti + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + &Lähetä kutsu sähköpostilla +(Hän saa sähköpostin, jossa on ohjeet RetroSharen lataamiseksi) + + + + InviteDialog + + Done + Valmis + + + Cancel + Peru + + + Launch Email + Käynnistä sähköposti + + + + LinksDialog + + + Share Link Anonymously + Jaa linkki nimettömänä + + + + Vote on Link + Äänestä linkkiä + + + + Download + Lataa + + + + Expand + Laajenna + + + + Hide + Piilota + + + + File Request Confirmation + Tiedostopyynnön vahvistaminen + + + + The file has been added to your download list. + Tiedosto on lisätty latausluetteloosi. + + + + File Request canceled + Tiedostopyyntö peruttu + + + + The file has not been added to your download list, because you already have it. + Tiedostoa ei lisätty latausluetteloosi, koska sinulla on se jo. + + + + File Request Error + Virhe pyydettäessä tiedostoa + + + + The file link is malformed. + Tiedostolinkki on virheellinen. + + + + From + Lähettäjä + + + + Show + Näytä + + + + 101-200 + 101-200 + + + + 201-300 + 201-300 + + + + 301-400 + 301-400 + + + + 401-500 + 401-500 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Linkkipilvi</span></p></body></html> + + + + Title / Comment + Otsikko / Kommentti + + + + Score + Pisteytys + + + + Peer / Link + Vertainen / Linkki + + + + Sort by + Lajittelu + + + + Combo + Yhdistelmä + + + + Time + Aika + + + + Ranking + Sijoitus + + + + In last + Viimeisimpänä + + + + Month + Kuukausi + + + + Week + Viikko + + + + Day + Päivä + + + + All Peers + Kaikki vertaiset + + + + Own Links + Omat linkit + + + + Top 100 + Ylimmät 100 + + + + Bottom 100 + Alimmat 100 + + + + Link: + Linkki: + + + + Add Anonymous Link + Lisää nimetön linkki + + + + Add Link/Comment + Lisää linkki/kommentti + + + + Title: + Otsikko: + + + + Score: + Pisteytys: + + + + +2 Great! + +2 Loistava! + + + + +1 Good + +1 Hyvä + + + + 0 Okay + 0 OK + + + + -1 Sux + -1 Huono + + + + -2 Bad Link + -2 Linkki rikki + + + + Url: + Url-osoite: + + + + Add new link + Lisää uusi linkki + + + + LogDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> + +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +</body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> + +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Tietoja RetroSharesta </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Pikalinkit: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">Tietoja</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Alkuunpääsy</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Käyttöliittymän perusteet</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">UKK</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare on yksityisiin vertaisverkkoihin tarkoitettu viestintäalusta, jonka on luonut "Dr. Bob". Tämä ohjelma mahdollistaa tiedostojen jakamisen ja keskustelun turvallisesti ystäviesi kanssa (eikä kenenkään muun!).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lisätietoja ja uusimman julkaisun löydät osoitteesta http://www.lunamutt.com.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +</body></html> + + + + MainWindow + + + Network + Verkko + + + + Friends + Ystävät + + + + + Transfers + Siirrot + + + + + Messages + Viestit + + + + + Channels + Kanavat + + + + Blogs + Blogit + + + + Low disk space warning + Varoitus: levytila vähissä + + + + The disk space in your + Levytila + + + + directory is running low (current limit is + -hakemistossasi käy vähiin (tämänhetkinen raja on + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + Mt). + + RetroShare pysäyttää nyt turvallisesti kaiken tähän hakemistoon tulevan dataliikenteen. + + Ole hyvä ja vapauta tilaa ja paina Ok. + + + + Status + Tila + + + + Chat + Keskustelu + + + + + + + You have %1 new messages + Sinulle on uusia viestejä %1 kpl + + + + + + + %1 new messages + %1 kappalettal uusia viestejä + + + + + + + %1 new message + %1 uusi viesti + + + + You have %1 completed downloads + Sinulla on %1 valmista latausta + + + + You have %1 completed download + Sinulla on %1 valmis lataus + + + + %1 completed downloads + %1 valmiita latauksia + + + + %1 completed download + %1 valmis lataus + + + + Down: %1 (kB/s) + Lataus: %1 (kB/s) + + + + Up: %1 (kB/s) + Lähetys: %1 (kB/s) + + + + %1 friend connected + %1 ystävä yhdistettynä + + + + %1 friends connected + %1 ystävää yhdistettynä + + + + Internal Error + Sisäinen virhe + + + + It seems to be an old RetroShare link. Please use copy instead. + Tämä näyttäisi olevan vanha RetroShare-linkki. Käytä mielummin kopiointia. + + + + The file link is malformed. + Linkki on virheellinen. + + + + + Options + Valinnat + + + + Hide + Piilota + + + + Show + Näytä + + + + RetroShare + RetroShare + + + Invite Friend + Kutsu ystävä + + + + MainWindow + Pääikkuna + + + + Add Friend + Lisää ystävä + + + + Add a Friend Wizard + Ohjattu toiminto ystävän lisäämiseksi + + + + Add Share + Lisää jako + + + + + Quick Start Wizard + Ohjattu nopea käynnistys + + + + Search + Etsi + + + + Files + Tiedostot + + + Add Shared Directory + Lisää jaettu hakemisto + + + + Show/Hide + Piilota/Näytä + + + + &Quit + Lo&peta + + + + + + + You have %1 new message + Sinulle on %1 uusi viesti + + + + Bandwidth Graph + Siirtonopeuskuvaaja + + + + Open Messenger + Avaa pikaviestin + + + + Minimize + Pienennä + + + + Maximize + Suurenna + + + + Links Cloud + Linkkipilvi + + + + RetroShare %1 a secure decentralised communication platform + RetroShare %1 turvallinen hajautettu kommunikaatioalusta + + + + Unfinished + Kesken + + + + Help + Ohje + + + + About + Tietoja + + + + + Forums + Foorumit + + + + Open Messages + Avaa viestit + + + + Applications + Ohjelmat + + + Settings + Asetukset + + + + Plugins + Lisäosat + + + + Really quit ? + Lopeta? + + + + Do you really want to exit RetroShare ? + Haluatko todella poistua RetroSharesta? + + + + Quit + Lopeta + + + + SMPlayer + SMPlayer + + + + Messenger + Pikaviestin + + + + MessageComposer + + + + Compose + Kirjoita viesti + + + + + Contacts + Kontaktit + + + + Search for Name: + Etsi nimellä: + + + + Reset + Palauta asetukset + + + + Send To: + Lähetä: + + + + Subject: + Aihe: + + + + Paragraph + Kappale + + + + Search Friends + Etsi ystäviä + + + + >> To + >> Vastaanottaja + + + + >> Cc + >> Kopio + + + + >> Bcc + >> Piilokopio + + + + >> Recommend + >> Suosittele + + + + Heading 1 + Otsikko 1 + + + + + Heading 2 + Otsikko 2 + + + + Heading 3 + Otsikko 3 + + + + Heading 4 + Otsikko 4 + + + + Heading 5 + Otsikko 5 + + + + Heading 6 + Otsikko 6 + + + + Font size + Fonttikoko + + + + Increase font size + Suurenna fonttikokoa + + + + Decrease font size + Pienennä fonttikokoa + + + + Bold + Lihavoitu + + + + Underline + Alleviivattu + + + + Italic + Kursivoitu + + + + Select Color + Valitse väri + + + + Alignment + Asettelu + + + + Add a Image + Lisää kuva + + + + Sets text font to code style + Asettaa tekstin fontin koodityyliin + + + + Tags: + Merkkaukset: + + + + + Tags + Merkkaukset + + + + Recommended Files + Suositellut tiedostot + + + + File Name + Tiedoston nimi + + + + Size + Koko + + + Sources + Lähteet + + + + Hash + Tiiviste (hash) + + + + Send + Lähetä + + + + Send this message now + Lähetä tämä viesti nyt + + + + Reply + Vastaa + + + + Toggle Contacts View + Kontaktinäkymän vaihto + + + + Save + Tallenna + + + + Save this message + Tallenna tämä viesti + + + + Attach + Liitä + + + + Attach File + Liitä tiedosto + + + + Quote + Lainaa + + + + Add Blockquote + Lisää lainauslohko (blockquote) + + + + &Left + Tas&aa vasemmalle + + + + C&enter + &Keskitä + + + + &Right + Tasaa &oikealle + + + + &Justify + Tasaa &molemmat reunat + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + Suosittelen hyvää ystävääni, voit luottaa häneen, kun luotat minuun. <br> Kopioi ystävälinkki ja liitä se ystävälistaan + + + + + Save Message + Tallenna viesti + + + + Message has not been Sent. +Do you want to save message to draft box? + Viestiä ei ole lähetetty. +Haluatko tallentaa viestin luonnoslaatikkoon? + + + + Friend Recommendation(s) + Ystäväsuositukset + + + + + Paste RetroShare Link + Liitä RetroShare-linkki + + + No Title + Ei otsikkoa + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + Ystävän yksityiskohdat + + + + Re: + Vs: + + + + Fwd: + Fwd: + + + + + RetroShare + RetroShare + + + + Do you want to send the message without a subject ? + Haluatko lähettää viestin ilman otsikkoa? + + + + Please insert at least one recipient. + Ole hyvä ja lisää ainakin yksi vastaanottaja. + + + + To + Vastaanottaja + + + + Cc + Kopio + + + + Bcc + Piilokopio + + + + Unknown + Tuntematon + + + + Unknown friend + Tuntematon ystävä + + + + &File + &Tiedosto + + + + &New + &Uusi + + + + &Open... + &Avaa... + + + + &Save + &Tallenna + + + + Save &As File + Tallenna t&iedostona + + + + Save &As Draft + Tallenna &luonnoksena + + + + &Print... + Tu&losta... + + + + &Export PDF... + &Vie PDF... + + + + &Quit + Lo&peta + + + + &Edit + &Muokkaa + + + + &Undo + K&umoa + + + + &Redo + To&ista + + + + Cu&t + &Leikkaa + + + + &Copy + K&opioi + + + + &Paste + Lii&tä + + + + &View + &Näytä + + + + &Contacts Sidebar + &Kontaktit sivupalkissa + + + + &Insert + Lis&ää + + + + &Image + Ku&va + + + + &Horizontal Line + V&aakaviiva + + + + &Format + Muotoil&e + + + + Open File... + Avaa tiedosto... + + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-tiedostot (*.htm *.html);;Kaikki tiedostot (*) + + + + Save as... + Tallenna nimellä... + + + + Print Document + Tulosta asiakirja + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + Viestiä ei ole lähetetty. +Haluatko tallentaa viestin? + + + + Choose Image + Valitse kuva + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Tuetut kuvatiedostot (*.png *.jpeg *.jpg *.gif) + + + + Add Extra File + Lisää ylimääräinen tiedosto + + + + + Drop file error. + Virhe pudotettaessa tiedostoa. + + + + Directory can't be dropped, only files are accepted. + Hakemistoa ei voi pudottaa, ainoastaan tiedostoja. + + + + File not found or file name not accepted. + Tiedostoa ei löytynyt tai tiedoston nimeä ei hyväksytty. + + + + MessagePage + + Misc + Sekalaiset + + + + Reading + + + + + Set message to read on activate + Aseta viesti luetuksi aktivoitaessa + + + + Open messages in + + + + + Tags + Merkkaukset + + + + Tags can be used to categorize and prioritize your messages + Merkkauksilla voit luokitella viestejä ja järjestää niitä tärkeyden mukaan + + + + Add + Lisää + + + + Edit + Muokkaa + + + + Delete + Tuhoa + + + + Default + Oletus + + + + A new tab + + + + + A new window + + + + + Edit Tag + Muokka merkkausta + + + + MessageToaster + + message + viesti + + + New Message + Uusi viesti + + + + Subject + Aihe + + + Play video + Toista video + + + Play button + Toistopainike + + + Play the downloaded video + Toista ladattu video + + + + <b>1 new Message from</b> + <b>1 uusi viesti lähettäjältä</b> + + + + Close + Sulje + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Suositellut tiedostot</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + Aihe: + + + + From: + Lähettäjä: + + + + To: + Vastaanottaja: + + + + Cc: + Kopio: + + + + Bcc: + Piilokopio: + + + + Tags: + Merkkaukset: + + + + File Name + Tiedoston nimi + + + + Size + Koko + + + + Hash + Tiiviste (hash) + + + + Print + Tulosta + + + + Print Preview + Tulostuksen esikatselu + + + + No subject + + + + + Download + Lataa + + + + Download all + + + + + Hide + Piilota + + + + Expand + Laajenna + + + + File + Tiedosto + + + + Files + Tiedostot + + + + Print Document + Tulosta asiakirja + + + + Save as... + Tallenna nimellä... + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-tiedostot (*.htm *.html);;Kaikki tiedostot (*) + + + + MessageWindow + + + New Message + Uusi viesti + + + + Compose + + + + + Reply to selected message + Vastaa valittuun viestiin + + + + Reply + Vastaa + + + + Reply all to selected message + Vastaa kaikkiin valittuihin viesteihin + + + + Reply all + Vastaa kaikille + + + + Forward selected message + Välitä valittu viesti + + + + Foward + Välitä + + + + Remove selected message + Poista valittu viesti + + + + Delete + Tuhoa + + + + Print selected message + Tulosta valittu viesti + + + + + Print + Tulosta + + + + Display + Näytä + + + + + + Tags + Merkkaukset + + + + Print Preview + Tulostuksen esikatselu + + + + + Buttons Icon Only + Painikkeet vain kuvakkeella + + + + Buttons Text Beside Icon + Painikkeet tekstillä kuvakkeen vieressä + + + + Buttons with Text + Painikkeet tekstillä + + + + Buttons Text Under Icon + Painikkeet tekstillä kuvakkeen alla + + + + Set Text Under Icon + Aseta teksti kuvakkeen alle + + + + &File + &Tiedosto + + + + Save &As File + Tallenna t&iedostona + + + + &Print... + Tu&losta... + + + + Print Preview... + Tulostuksen esikatselu... + + + + &Quit + Lo&peta + + + + MessagesDialog + + + + New Message + Uusi viesti + + + + Quick View + + + + + Reply to Message + Vastaa viestiin + + + + Remove Message + Poista viesti + + + + + Date + Päiväys + + + + + + From + Lähettäjä + + + Size + Koko + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Suositellut tiedostot</span></p></body></html> + + + + Reply + Vastaa + + + + Reply all + Vastaa kaikille + + + + Foward + Välitä + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + poista valittu viesti + + + + Delete + Tuhoa + + + + Compose + Kirjoita viesti + + + + Reply to selected message + Vastaa valittuun viestiin + + + + Reply all to selected message + Vastaa kaikkiin valittuihin viesteihin + + + + Forward selected message + Välitä valittu viesti + + + + Remove selected message + Poista valittu viesti + + + + Print selected message + Tulosta valittu viesti + + + + Display + Näytä + + + + Reset + Palauta asetukset + + + + Attachments + Liitteet + + + + + Content + Sisältö + + + + + + + + Tags + Merkkaukset + + + Tag + Merkkaus + + + + + + + Inbox + Saapuneet + + + + + + + Outbox + Lähtevät + + + + Draft + Luonnokset + + + + + Sent + Lähetetyt + + + + + + + Trash + Roskat + + + Favorite Tags + Suosikkimerkkaukset + + + + Total Inbox: + Saapuneet yhteensä: + + + + Folders + Hakemistot + + + Cc: + Kopio: + + + Bcc: + Piilokopio: + + + Tags: + Merkkaukset: + + + + + Print... + Tulosta... + + + + Print Preview + Tulostuksen esikatselu + + + + + Buttons Icon Only + Painikkeet vain kuvakkeella + + + + Buttons Text Beside Icon + Painikkeet tekstillä kuvakkeen vieressä + + + + Buttons with Text + Painikkeet tekstillä + + + + Buttons Text Under Icon + Painikkeet tekstillä kuvakkeen alla + + + + Set Text Under Icon + Aseta teksti kuvakkeen alle + + + + Save As... + Tallenna nimellä... + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">vastaa valittuun viestiin</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Uusi viesti</p></body></html> + + + Download All + Lataa kaikki + + + Print Document + Tulosta asiakirja + + + File Name + Tiedoston nimi + + + Sources + Lähteet + + + + Forward selected Message + Välitä valittu viesti + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + Muokkaa + + + + Edit as new + + + + + Remove Messages + Poista viestit + + + + Forward Message + Välitä viesti + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + Remove All Tags + Poista kaikki merkkaukset + + + New tag ... + Uusi merkkaus... + + + Edit... + Muokkaa... + + + + Mark as read + Merkitse luetuksi + + + + Mark as unread + Merkitse lukemattomaksi + + + + Undelete + Kumoa tuhoaminen + + + Download + Lataa + + + + Empty trash + Tyhjennä roskat + + + Hide + Piilota + + + Expand + Laajenna + + + + + + Drafts + Luonnokset + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + Vastaanottaja + + + + Click to sort by to + + + + File + Tiedosto + + + Files + Tiedostot + + + Save as... + Tallenna nimellä... + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-tiedostot (*.htm *.html);;Kaikki tiedostot (*) + + + + + + + + Total: + Yhteensä: + + + + + Reply to All + Vastaa kaikille + + + + + Subject + Aihe + + + Subject: + Aihe: + + + From: + Lähettäjä: + + + To: + Vastaanottaja: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lataa kaikki suositellut tiedostot</p></body></html> + + + Hash + Tiiviste (hash) + + + + Print + Tulosta + + + + MessagesPopupDialog + + New Message + Uusi viesti + + + Reply to Message + Vastaa viestiin + + + Remove Message + Poista viesti + + + Download All + Lataa kaikki + + + Messages + Viestit + + + Inbox + Saapuneet + + + Outbox + Lähtevät + + + Draft + Luonnokset + + + Sent + Lähetetyt + + + From + Lähettäjä + + + Date + Päiväys + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Suositellut tiedostot</span></p></body></html> + + + File Name + Tiedoston nimi + + + Size + Koko + + + Sources + Lähteet + + + Compose + Muodosta + + + Remove + Poista + + + + MessengerDirModel + + Size + Koko + + + Rank + Sijaluku + + + + MessengerSharedFiles + + Download + Lataa + + + + MessengerWindow + + + Expand all + Laajenna kaikki + + + + Collapse all + Kutista kaikki + + + + Chat + Keskustelu + + + + Message Friend + Lähetä viesti ystävälle + + + + Connect To Friend + Yhdistä ystävään + + + + Peer Details + Vertaisen yksityiskohdat + + + + Recomend this Friend to... + Suosittele tätä ystävää... + + + + Export Friend + Vie ystävä + + + + Deny Friend + Torju ystävä + + + + Remove Friend Location + Poista ystävän sijainti + + + + <strong>GPG Key</strong> + <strong>GPG-avain</strong> + + + + + + + location + sijainti + + + + <strong>RetroShare instance</strong> + <strong>RetroShare-instanssi</strong> + + + + Paste RetroShare Link + Liitä RetroShare-linkki + + + + Save Certificate + Tallenna varmenne + + + + Certificates (*.pqi) + Varmeneet (*.pqi) + + + Remove Friend + Poista ystävä + + + + Click to Change your Avatar + Napauta vaihtaaksesi avatariasi + + + + Search Friends + Etsi ystäviä + + + + Reset + Palauta asetukset + + + + + Sort Descending Order + Laskeva järjestys + + + + + Sort Ascending Order + Nouseva järjestys + + + + Set root is Decorated + Asetettu juuri on koristeltu + + + + Set Root Decorated + Aseta juuri koristelluksi + + + + Sort by State + Järjestä tilan mukaan + + + + Hide Offline Friends + Piilota offline-ystävät + + + + RetroShare Messenger + RetroSharen pikaviestin + + + + Add a Friend + Lisää ystävä + + + + Share Files for your Friends + Jaa tiedostoja ystävillesi + + + + MsgFeed + + Inbox + Saapuneet + + + Outbox + Lähtevät + + + Sent + Lähetetyt + + + Date + Päiväys + + + + MsgItem + + + Reply to Message + Vastaa viestiin + + + + Remove Item + Poista kohde + + + + + Expand + Laajenna + + + + Reply Message + Vastaa viestiin + + + + Delete Message + Tuhoa viesti + + + + Play Media + Toista media + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Piilota + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Viestit</span></p></body></html> + + + Date + Päiväys + + + Rank + Sijaluku + + + From + Lähettäjä + + + Title + Otsikko + + + Msg + Viesti + + + Count + Lukumäärä + + + Size + Koko + + + Type + Tyyppi + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Viestin teksti</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Suositellut tiedostot</span></p></body></html> + + + Delete Channel + Poista kanava + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Viestit</span></p></body></html> + + + Date + Päiväys + + + Rank + Sijaluku + + + From + Lähettäjä + + + Title + Otsikko + + + Msg + Viesti + + + Count + Lukumäärä + + + Size + Koko + + + Type + Tyyppi + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Viestin teksti</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Suositellut tiedostot</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + <strong>NAT:</strong> + + + + Internet connection + Internetyhteys + + + + No internet connection + Ei internetyhteyttä + + + + No local network + Ei paikallista verkkoa + + + + OK | RetroShare Server + OK | RetroSharen palvelin + + + + NetworkDialog + + Load Certificate + Lataa varmenne + + + Select a pem/pqi File + Valitse pem/pqi-tiedosto + + + File Not Found + Tiedostoa ei löytynyt + + + %1 does not exist. Would you like to create it? + %1 ei ole olemassa. Luodaanko se? + + + Failed to Create File + Tiedostoa ei voitu luoda + + + Unable to create %1 [%2] + Ei voitu luoda kohdetta %1 [%2] + + + + Personal signature + Henkilökohtainen allekirjoitus + + + + GPG key signed by you + Allekirjoittamasi GPG-avain + + + + Marginally trusted peer + Rajallisesti luotettu vertainen + + + + Fully trusted peer + Täysin luotettu vertainen + + + + Untrusted peer + Ei-luotettu vertainen + + + + Has authenticated me + On varmentanut minut + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + on varmentanut sinut. +Paina hiiren oikeaa nappia ja valitse "ystävysty" saadaksesi yhteyden. + + + Select Certificate + Valitse varmenne + + + Certificates (*.pqi *.pem) + Varmenteet (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Verkko:</span></p></body></html> + + + Accept + Hyväksy + + + Trust + Luottamus + + + Last Contact + Viimeisin kontakti + + + + + + Name + Nimi + + + Peer Address + Vertaisen osoite + + + Organisation + Organisaatio + + + Location + Sijainti + + + Country + Maa + + + + + Cert Id + Varmennetunniste + + + + Network + Verkko + + + Peer Details + Vertaisen yksityiskohdat + + + + Authentication matrix + Varmennusmatriisi + + + + Network View + Verkkonäkymä + + + + Deny friend + Torju ystävä + + + + Make friend + Ystävysty + + + + Delete certificate + Tuhoa varmenne + + + + Export my Cert + Vie varmenteeni + + + + Peer details... + Vertaisen yksityiskohdat... + + + + Copy RetroShare Link + Kopioi RetroShare-linkki + + + + Unknown + Tuntematon + + + + yourself + sinä itse + + + RetroShare + RetroShare + + + Sorry, create certificate failed + Varmenteen luominen epäonnistui + + + Please choose a filename + Ole hyvä ja valitse tiedostonimi + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroSharen varmenne (*.rsc );;Kaikki tiedostot (*) + + + Certificate file successfully created + Varmennetiedosto luotu onnistuneesti + + + Sorry, certificate file creation failed + Valitettavasti varmennetiedoston luominen epäonnistui + + + + + Did I authenticated peer + Varmensinko vertaisen + + + + Did I sign his gpg key + Allekirjoitinko hänen GPG-avaimensa + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Verkko</span></p></body></html> + + + + Peer ID + Vertaisen tunniste + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Näkymä</span></p></body></html> + + + + Network Status + Verkon tila + + + + Local network + Paikallinen verkko + + + + UPnP + UPnP + + + + + Did peer authenticated me + Varmensiko vertainen minut + + + + Search Network + Etsi verkosta + + + + Clear Filter + Tyhjennä suodatin + + + + Show keys that are not validated by the GPG web of trust + Näytä avaimet, jotka eivät ole GPG:n luottamuksen verkon varmentamia + + + + External ip address finder + Ulkoisen IP-osoitteen paikallistaminen + + + + Clear + Tyhjennä + + + + Set Tabs Right + Aseta välilehdet oikealle + + + + Set Tabs North + Aseta välilehdet pohjoiseen + + + + Set Tabs South + Aseta välilehdet etelään + + + + Set Tabs Left + Aseta välilehdet vasemmalle + + + + Set Tabs Rounded + Aseta välilehdet pyöristetyiksi + + + + Set Tabs Triangular + Aseta välilehdet kolmikulmaisiksi + + + + Add Friend + Lisää ystävä + + + + Copy My Key to Clipboard + Kopioi avaimeni leikepöydälle + + + + Export My Key + Vie avaimeni + + + + Create New Profile + Luo uusi profiili + + + + Create a new Profile + Luo uusi profiili + + + + NetworkPage + + Rate Options + Siirtonopeusvalinnat + + + Max Total Data Rate (KB/S): + Suurin kokonaissiirtonopeus (kB/s): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Siirtonopeus henkilöä kohden (kB/s):</p></body></html> + + + + NetworkView + + Hide Settings + Piilota asetukset + + + Show Settings + Näytä asetukset + + + Settings + Asetukset + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray) + + + + Redraw + Uudista näkymä + + + + Friendship level: + Ystävyystaso: + + + Friends + Ystävät + + + + Edge length: + Reunan pituus: + + + + NewTag + + + New Tag + Uusi merkkaus + + + + Name: + Nimi: + + + + Choose color + Valitse väri + + + + OK + OK + + + + Cancel + Peru + + + + NewsFeed + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends Storm</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Ystävämyrsky</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Poista kaikki + + + + Options + Valinnat + + + + NotifyDialog + + Channels + Kanavat + + + Chat + Keskustelu + + + Messages + Viestit + + + New Message + Uusi viesti + + + + NotifyPage + + + News Feed + Uutissyöte + + + + Peers + Vertaiset + + + + Channels + Kanavat + + + + Forums + Foorumit + + + + Chat + Keskustelu + + + + Blogs + Blogit + + + + Messages + Viestit + + + + Add feeds at end + Lisää syötteet loppuun + + + + Systray Icon + Ilmaisinalueen kuvake + + + + Private Message + Yksityinen viesti + + + + Message + Viesti + + + + Channel Post + Kanavakirjoitus + + + + Forum Post + Foorumikirjoitus + + + + + Download completed + Lataus suoritettu + + + + Combined icon + Yhdistetty kuvake + + + + Toasters + Paahtimet + + + + Friend Connect + Yhteys ystävään + + + + New Message + Uusi viesti + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + Yksityinen keskustelu + + + + Open Window for new chat + Avaa ikkuna uutta keskustelua varten + + + + Grab Focus when chat arrives + Kohdista keskusteluun, kun se alkaa + + + + Use a single tabbed window + Käytä yhtä ainutta välilehtiä käyttävää ikkunaa + + + + Group chat + Ryhmäkeskustelu + + + + Display systray message + Näytä ilmaisinalueen viesti + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + GPG-avaimen salalauseke + + + + Wrong password ! + Väärä salasana! + + + + Please enter the password to unlock the following GPG key: + Ole hyvä ja anna salasana avataksesi seuraavan GPG-avaimen lukituksen: + + + + Examining shared files... + Tarkastellaan jaettuja tiedostoja... + + + + Hashing file + Luodaan tiivistettä (hash) tiedostolle + + + + Saving file index... + Tallennetaan tiedostoluetteloa... + + + + OnlineToaster + + + Friend Online + Ystävä linjoilla + + + + OptionsDlg + + Cancel + Peru + + + + PeerDefs + + Anonymous + Nimetön + + + + + Unknown + Tuntematon + + + + PeerItem + + Make Friend + Tee ystäväksi + + + Remove Friend + Poista ystävä + + + + Chat + Keskustelu + + + + Start Chat + Aloita keskustelu + + + Organisation + Organisaatio + + + + Location + Sijainti + + + Country + Maa + + + + Remove Item + Poista kohde + + + + + Expand + Laajenna + + + + Write a quick Message + Kirjoita viesti pikaisesti + + + + Send + Lähetä + + + + Cancel + Peru + + + + Peer ID: + Vertaisen tunniste: + + + + Write Message + Kirjoita viesti + + + + Status: + Tila: + + + + Trust: + Luottamus: + + + + Name: + Nimi: + + + + IP Address + IP-osoite + + + + Connection Method + Yhteysmenetelmä + + + + Friend + Ystävä + + + + Friend Connected + Ystävä yhdistyneenä + + + + Connect Attempt + Yhteydenottoyritys + + + + Friend of Friend + Ystävän ystävä + + + + Peer + Vertainen + + + + + + + + + + + + Unknown Peer + Tuntematon vertainen + + + + Hide + Piilota + + + + Quick Message + Pikainen viesti + + + + PeerStatus + + + Friends: 0/0 + Ystävät: 0/0 + + + + Online Friends/Total Friends + Ystäviä linjoilla / Ystäviä yhteensä + + + + Friends + Ystävät + + + + PeersDialog + + Chat + Keskustelu + + + Export Friend + Vie ystävä + + + Remove Friend + Poista ystävä + + + Save Certificate + Tallenna varmenne + + + Certificates (*.pqi) + Varmeneet (*.pqi) + + + Status + Tila + + + Person + Henkilö + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Ystävät</span></p></body></html> + + + Connect To Friend + Yhdistä ystävään + + + Welcome to RetroShare's group chat. + Tervetuloa RetroSharen ryhmäkeskusteluun. + + + Profile + Profiili + + + Friends Storm + Ystävämyrsky + + + me + minä + + + Paste RetroShare Link + Liitä RetroShare-linkki + + + Group + Ryhmä + + + Friend + Ystävä + + + Location + Sijainti + + + Message Group + Viestiryhmä + + + Edit Group + Muokkaa ryhmää + + + Remove Group + Poista ryhmä + + + Expand all + Laajenna kaikki + + + Collapse all + Kutista kaikki + + + Message Friend + Lähetä viesti ystävälle + + + Peer Details + Vertaisen yksityiskohdat + + + Deny Friend + Torju ystävä + + + Remove Friend Location + Poista ystävän sijainti + + + Friend Details + Ystävän yksityiskohdat + + + Recommend this Friend to... + Suosittele tätä ystävää... + + + Add to group + Lisää ryhmään + + + Move to group + Siirrä ryhmään + + + Groups + Ryhmät + + + Remove from group + Poista ryhmästä + + + Remove from all groups + Poista kaikista ryhmistä + + + Available + Saatavilla + + + RetroShare + RetroShare + + + News Feed + Uutissyöte + + + Do you want to remove this Friend? + Haluatko poistaa tämän ystävän? + + + is typing... + kirjoittaa... + + + New group chat + Uusi ryhmäkeskustelu + + + Load File + Avaa tiedosto + + + Add Extra File + Lisää ylimääräinen tiedosto + + + Drop file error. + Virhe pudotettaessa tiedostoa. + + + File not found or file name not accepted. + Tiedostoa ei löytynyt tai tiedoston nimeä ei hyväksytty. + + + Directory can't be dropped, only files are accepted. + Hakemistoa ei voi pudottaa, ainoastaan tiedostot ovat hyväksyttyjä. + + + Paste Friend Link + Liitä ystävälinkki + + + location + sijainti + + + Save as... + Tallenna nimellä... + + + Text File (*.txt );;All Files (*) + Tekstitiedosto (*.txt );;Kaikki tiedostot (*) + + + Send + Lähetä + + + Italic + Kursivoitu + + + Underline + Alleviivattu + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ystävät</span></p></body></html> + + + Add + Lisää + + + Display + Näytä + + + Add or Change your Avatar + Lisää tai vaihda avatar + + + Edit Personal message + Muokkaa henkilökohtaista viestiä + + + Bold + Lihavoitu + + + Text Color + Tekstin väri + + + Create new Forum + Luo uusi foorumi + + + F + F + + + Create new Channel + Luo uusi kanava + + + C + C + + + Add your Avatar Picture + Lisää avatarkuva + + + A + A + + + Set your Personal Message + Aseta henkilökohtainen viesti + + + Edit your status Message + Muokkaa tilaviestiäsi + + + Browse Message History + Selaa viestihistoriaa + + + Browse History + Selaa historiaa + + + Save Chat History + Tallenna keskusteluhistoria + + + Hide Offline Friends + Piilota offline-ystävät + + + Hide Status Column + Piilota tilasarake + + + Sort by State + Järjestä tilan mukaan + + + Add a new Group + Lisää uusi ryhmä + + + Sort Descending Order + Laskeva järjestys + + + Sort Ascending Order + Nouseva järjestys + + + Add Friend + Lisää ystävä + + + Create new Profile + Luo uusi profiili + + + Font + Fontti + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Näkymä</span></p></body></html> + + + Friends + Ystävät + + + Group Chat + Ryhmäkeskustelu + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">set Text Color</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Aseta tekstin väri</span></p></body></html> + + + Attach File + Liitä tiedosto + + + Clear Chat History + Tyhjennä keskusteluhistoria + + + + PeersFeed + + Save Certificate + Tallenna varmenne + + + Certificates (*.pqi) + Varmeneet (*.pqi) + + + Friends + Ystävät + + + + PhotoDialog + + + Insert Show Lists + Lisää esittelylistoja + + + + Open + Avaa + + + + Remove + Poista + + + + Excellent + Loistava + + + + Good + Hyvä + + + + Average + Keskiverto + + + + Below avarage + Keskiverron alapuolella + + + + Bad + Huono + + + + Unrated + Ei arvosteltu + + + + Rating + Arvostelu + + + + + Date + Päiväys + + + + + Location + Sijainti + + + + Size + Koko + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Valokuvanäkymä</span></p></body></html> + + + + Peer + Vertainen + + + + Slideshow + Diaesitys + + + + Photo + Valokuva + + + + Thumb Image + Pikkukuva + + + + Image Name + Kuvan nimi + + + + + Comment + Kommentti + + + + PeerId + Vertaistunniste + + + + PhotoId + Valokuvatunniste + + + + + Add Photo(s) + Lisää kuv(i)a + + + + Add Photo SlideShow + Lisää diaesitys + + + + Update Details + Päivitä yksityiskohdat + + + + Photo + Valokuva + + + + Description + Kuvaus + + + + PhotoShow + + + Date: + Päiväys: + + + + Location: + Sijainti: + + + + Comment: + Kommentti: + + + + Display Size: + Näkymän koko: + + + + 320 x 320 + 320 x 320 + + + + 640 x 640 + 640 x 640 + + + + Full Size + Täysi koko + + + + Play Rate: + Toistonopeus: + + + + 1 Sec + 1 sek + + + + 2 Sec + 2 sek + + + + 5 Sec + 5 sek + + + + 10 Sec + 10 sek + + + + 20 Sec + 20 sek + + + + 1 Min + 1 min + + + + Edit Photo Details + Muokkaa valokuvan yksityiskohtia + + + + Save Photo + Tallenna valokuva + + + + No Photo Selected + Ei kuvaa valittuna + + + + Start + Aloita + + + + Back + Takaisin + + + + Photo Show + Näytä valokuva + + + + Play + Toista + + + + Pause + Tauko + + + + Forward + Eteenpäin + + + + PluginFrame + + + Remove + Poista + + + + PluginManagerWidget + + + Install New Plugin... + Asenna uusi lisäosa... + + + + Open Plugin to install + Avaa asennettava lisäosa + + + + Plugins (*.so *.dll) + Lisäosat (*.so *.dll) + + + + PopularityDefs + + + Popularity + Suosio + + + + PopupChatDialog + + RetroShare + RetroShare + + + + Your Friend is offline +Do you want to send them a Message instead + Ystäväsi ei ole kytkeytyneenä +Haluatko sen sijaan lähettää hänelle viestin + + + + Friend not Online + Ystävä ei ole linjoilla + + + + is typing... + kirjoittaa... + + + + Hide Avatar + Piilota avatar + + + + Messages you send will be delivered after Friend is again Online + Lähettämäsi viestit toimitetaan kunhan ystäväsi palaa jälleen linjoille + + + + Show Avatar + Näytä avatar + + + + Paste RetroShare Link + Liitä RetroShare-linkki + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + Tallenna nimellä... + + + + Text File (*.txt );;All Files (*) + Tekstitiedosto (*.txt );;Kaikki tiedostot (*) + + + + apears to be Offline. + näyttää olevan poissa linjoilta. + + + + is Idle and may not reply + on jouten, eikä välttämättä vastaa + + + + is Away and may not reply + on poissa, eikä välttämättä vastaa + + + + is Busy and may not reply + on kiireinen, eikä välttämättä vastaa + + + + Send + Lähetä + + + + Close + Sulje + + + + + Bold + Lihavoitu + + + + + Underline + Alleviivattu + + + + + Italic + Kursivoitu + + + Set Font + Aseta fontti + + + + Text Color + Tekstin väri + + + + Clear Chat History + Tyhjennä keskusteluhistoria + + + + Browse Message History + Selaa viestihistoriaa + + + + Browse History + Selaa historiaa + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + Liitä kuva + + + + Font + Fontti + + + + Strike + Yliviivaus + + + Clear Chat + Tyhjennä keskustelu + + + + Disable Emoticons + Kytke hymiöt pois + + + + + Save Chat History + Tallenna keskusteluhistoria + + + + Clear offline messages + Tyhjennä offline-viestit + + + + Add Extra File + Lisää ylimääräinen tiedosto + + + + + Drop file error. + Virhe pudotettaessa tiedostoa. + + + + File not found or file name not accepted. + Tiedostoa ei löytynyt tai tiedoston nimeä ei hyväksytty. + + + + Directory can't be dropped, only files are accepted. + Hakemistoa ei voi pudottaa, ainoastaan tiedostot ovat hyväksyttyjä. + + + + Add a File for your Friend + Lisää tiedosto ystävällesi + + + + PopupChatWindow + + + Avatar + Avatar + + + + Set your Avatar Picture + Aseta avatarkuvasi + + + + + Dock tab + Telakoi välilehti + + + + + Undock tab + Irrota välilehti + + + + + Set Chat Window Color + + + + + RetroShare + RetroShare + + + + Load File + Avaa tiedosto + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Directories + Hakemistot + + + Error Saving Configuration + Virhe tallennettaessa asetuksia + + + General + Yleiset + + + Server + Palvelin + + + Options + Valinnat + + + Cancel + Peru + + + OK + OK + + + Help + Ohje + + + + PrintPreview + + + RetroShare Message - Print Preview + RetroShare-viesti - Tulostuksen esikatselu + + + + Print + Tulosta + + + + &Print... + Tu&losta... + + + + Page Setup... + Sivun asetukset... + + + + Zoom In + Suurenna + + + + Zoom Out + Pienennä + + + + &Close + &Sulje + + + + ProfileEdit + + + Remove Profile Entry + Poista profiilimerkintä + + + + Move Profile Entry Up + Siirrä profiilimerkintää ylös + + + + Move Profile Entry Down + Siirrä profiilimerkintää alas + + + + Profile Edit + Profiilin muokkaus + + + + Profile + Profiili + + + + Category + Luokitus + + + + Thoughts + Ajatuksia + + + + Edit Profile Category + Muokkaa profiililuokitusta + + + + Birthday + Syntymäpäivä + + + + School + Koulu + + + + University + Yliopisto + + + + Phone Number + Puhelinnumero + + + + Favourite Books + Lempikirjat + + + + Favourite Music + Lempimusiikki + + + + Favourite Films + Lempielokuvat + + + + or Custom Entry + tai räätälöity merkintä + + + + Add Entry + Lisää merkintä + + + + + Move + Siirrä + + + + Close Editor + Sulje muokkaaja + + + + ProfileView + + + Clear Photo + Tyhjennä valokuva + + + + Change Photo + Vaihda valokuva + + + + + Edit Profile + Muokkaa profiilia + + + + Remove Favourite + Poista suosikki + + + + Clear Favourites + Tyhjennä suosikit + + + + Download File + Lataa tiedosto + + + + Download All + Lataa kaikki + + + + RetroShare + RetroShare + + + + Error : cannot get peer details. + Virhe haettaessa vertaisen yksityiskohtia. + + + + + Name + Nimi + + + + Peer ID + Vertaisen tunniste + + + + Size + Koko + + + + Profile View + Profiilinäkymä + + + + Last Post: + Viimeisin viesti: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profiili</span></p></body></html> + + + + Category + Luokitus + + + + Thoughts + Ajatuksia + + + + Favourite Files + Suosikkitiedostot + + + + Hash + Tiiviste (hash) + + + + Close Profile + Sulje profiili + + + + ProfileWidget + + + + Edit Personal message + Muokkaa henkilökohtaista viestiä + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Julkiset tiedot</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Julkiset tiedot</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Nimi:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Sijainti:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Muut tiedot</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Ystävien lukumäärä:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynaaminen nimipalvelujärjestelmä:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Vertaisen tunniste:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Versio:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Linjoilla alkaen:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Osoitteeni</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Paikallinen osoite:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Ulkoinen osoite:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Osoiteluettelo</span></p></body></html> + + + + QObject + + Name + Nimi + + + Date + Päiväys + + + Size + Koko + + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + Käynnistys epäonnistui. Väärä tai puuttuva GPG:n asennust. + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + Odottamaton virhe. Ole hyvä ja raportoi 'RsInit::InitRetroShare unexpected return code %1'. + + + + + Multiple instances + Useita instansseja + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Toinen RetroShare, joka käyttää samaa profiilia on jo käynnissä järjestelmässäsi. Ole hyvä ja sulje se ensin + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Odottamaton virhe haettaessa yhden instanssin lukitusta + + + + Login Failure + Kirjautuminen epäonnistui + + + + Maybe password is wrong + Ehkä salasana on väärä + + + + File Request Confirmation + Tiedostopyynnön vahvistus + + + + The file has been added to your download list. + Tiedosto on lisätty latauslistaasi. + + + + + File Request canceled + Tiedostopyyntö peruttu + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + Tiedostoa ei lisätty latausluetteloosi, koska sinulla on se jo. + + + + + Friend Request Confirmation + Ystäväpyynnön vahvistus + + + + The friend is already in your list. + Ystävä on jo luettelossasi. + + + + The friend has been added to your list. + Ystävä lisättiin luetteloosi. + + + + + Friend Request canceled + Ystäväpyyntö peruttu + + + + The friend could not be added to your list. + Ystävää ei voitu lisätä luetteloosi. + + + + The friend could not be found. + Ystävää ei lödetty. + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + Virhe tiedostopyynnössä + + + + The file link is malformed. + Tiedoston linkki on virheellinen. + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + Torju ystävä + + + + Make friend + Ystävysty + + + + Peer details + Vertaisen yksityiskohdat + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + Ohjattu pika-aloitus + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Tervetuloa RetroShareen!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Tämä ohjattu pika-aloitus auttaa sinua määrittämään RetroSharen asetukset muutamalla yksinkertaisella askeleella.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Jos olet edistyneempi käyttäjä, voit päästä käsiksi RetroSharen täysimittaisiin asetuksiin Työkalupalkin kautta. Paina Lopeta sulkeaksesi ohjatun toiminnon milloin tahansa.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Tämä ohjattu toiminto auttaa sinua:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Kertomaan RetroSharelle internetyhteydestäsi.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Valitsemaan, mitä tiedostoja haluat jakaa.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Pääsemään alkuun RetroSharen käyttämisessä.</span></p></body></html> + + + + + + Next > + Seuraava > + + + + + + + Exit + Lopeta + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + Varmistaakseen tehokkaan toimivuuden, RetroSharen tulee tietää hieman internetyhteydestäsi. + + + + Choose your upload speed limit: + Valitse lähetysnopeutesi yläraja: + + + + + KB/s + Kt/s + + + + Choose your download speed limit: + Valitse latausnopeutesi yläraja: + + + + Connection : + Yhteys: + + + + Automatic (UPnP) + Automaattinen (UPnP) + + + + Firewalled + Palomuuri + + + + Manually forwarded port + Portti avattu käsin + + + + Discovery : + Etsintä: + + + + Public: DHT & Discovery + Julkinen: DHT & etsintä + + + + Private: Discovery Only + Yksityinen: Vain etsintä + + + + Inverted: DHT Only + Käänteinen: Vain DHT + + + + Dark Net: None + Darknet: ei mitään + + + + Dynamic DNS: + Dynaaminen nimipalvelujärjestelmä: + + + + + + < Back + < Takaisin + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Tämä on luettelo jaetuista tiedostoista. Voit lisätä ja poistaa hakemistoja käyttämällä vasemmalla sijaitsevaa painiketta. Lisätessäsi uusia hakemistoja kaikki tiedostot tulevat alussa jaetuksi .</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Voit määrittää erikseen jakoilmaisimia jokaiselle jaetulle hakemistolle:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Ystävien selattavissa</span><span style=" font-family:'Sans'; font-size:8pt;">: suorat ystäväsi voivat selata tiedostoja.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Nimettömästi jaetut</span><span style=" font-family:'Sans'; font-size:8pt;">: ketkä tahansa voivat ladata tiedostoja nimettömien tunneleiden kautta.</span></p></body></html> + + + + Directory + Hakemisto + + + + Network Wide + Verkon laajuinen + + + + Browseable + Selattavissa + + + + Add + Lisää + + + + Remove + Poista + + + + Automatically share incoming directory (Recommended) + Jaa sisääntulevien hakemisto automaattisesti (suositeltavaa) + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Toivomme, että nautit RetroSharen käytöstä!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Vielä yksi askel! Olet lähes säätänyt RetroSharen toimimaan koneellasi.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Nämä asetukset määrittävät milloin ja miten RetroShare käynnistyy.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Do not show a message when Closing RetroShare + Älä näytä viestiä RetroSharea suljettaessa + + + + Start Minimized + Käynnistä pienennettynä + + + + Start RetroShare when my System Starts. + Käynnistä RetroShare järjestelmän käynnistyessä. + + + + Start minimized on system start + + + + + Finish + Valmis + + + + Select A Folder To Share + Valitse hakemisto jaettavaksi + + + + Shared Directory Added! + Jaettu hakemisto lisätty! + + + + Do you really want to stop sharing this directory ? + Haluatko todella lopettaa tämän hakemiston jakamisen? + + + + Warning! + Varoitus! + + + + RSettingsWin + + + General + Yleiset + + + + Directories + Hakemistot + + + + Server + Palvelin + + + + Transfer + Siirto + + + + Notify + Huomauta + + + + Security + Turvallisuus + + + + Message + Viesti + + + + Forum + Foorumi + + + + Chat + Keskustelu + + + + Appearance + Ulkoasu + + + + Sound + Ääni + + + + UnknownPage + Tuntematon sivu + + + + Error Saving Configuration on page + Virhe tallennettaessa asetuksia sivulle + + + Error Saving Configuration + Virhe tallennettaessa asetuksia + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>Lataus:</strong> 0.00 (kB/s) | <strong>Lähetys:</strong> 0.00 (kB/s) + + + + <strong>Down:</strong> + <strong>Lataus:</strong> + + + + <strong>Up:</strong> + <strong>Lähetys:</strong> + + + + RemoteDirModel + + Friends Directories + Ystävien hakemistot + + + My Directories + Omat hakemistot + + + Size + Koko + + + Share Type + Jakamisen tyyppi + + + What's new + Uusia + + + Rank + Sijaluku + + + Age + Ikä + + + FILE + TIEDOSTO + + + Anonymous + Nimetön + + + Anonymous and browsable by friends + Nimetön ja ystävien selattavissa + + + Only browsable by friends + Vain ystävien selattavissa + + + NEW + UUSI + + + Files + Tiedostot + + + File + Tiedosto + + + DIR + HAK + + + + RetroshareDirModel + + + Anonymous + Nimetön + + + + Anonymous and browsable by friends + Nimetön ja ystävien selattavissa + + + + Only browsable by friends + Vain ystävien selattavissa + + + + NEW + UUSI + + + + Rshare + + + Invalid language code specified: + Määritelty kielikoodi on virheellinen: + + + + Invalid GUI style specified: + Määritelty käyttöliittymän tyyli on virheellinen: + + + + Resets ALL stored RetroShare settings. + Palauttaa KAIKKI tallennetut RetroSharen asetukset. + + + + Sets the directory RetroShare uses for data files. + Asettaa hakemiston, jota RetroShare käyttää datatiedostoille. + + + + Sets the name and location of RetroShare's logfile. + Asettaa RetroSharen lokitiedoston nimen ja sijainnin. + + + + Sets the verbosity of RetroShare's logging. + Asettaa RetroSharen lokin runsassanaisuuden. + + + + Sets RetroShare's interface style. + Asettaa RetroSharen käyttöliittymän tyylin. + + + + Sets RetroShare's interface stylesheets. + Asettaa RetroSharen käyttöliittymän tyylitiedostot. + + + + Sets RetroShare's language. + Asettaa RetroSharen kielen. + + + + RetroShare Usage Information + RetroSharen käyttötiedot + + + + Invalid log level specified: + Virheellinen lokitaso määritelty: + + + + Unable to open log file '%1': %2 + Lokitiedoston '%1': %2 avaaminen epäonnistui + + + + RsidPage + + + RetroShare ID + RetroShare-tunniste + + + + Use RetroShare ID for adding a Friend which is available in your network. + Käytä RetroShare-tunnistetta verkossasi olevan ystävän lisäämiseen. + + + + Add Friends RetroShare ID... + Lisää ystävän RetroShare-tunniste... + + + + Paste Friends RetroShare ID in the box below + Liitä ystävän RetroShare-tunniste allaolevaan laatikkoon + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + Kirjoita ystäväsi RetroShare-tunniste, esim. Peer@BDE8D16A46D938CF + + + + This Peer %1 is not available in your Network + Tämä vertainen %1 ei ole verkossasi + + + + SFListDelegate + + + B + t + + + + KB + Kt + + + + MB + Mt + + + + GB + Gt + + + + SearchDialog + + + Sources + Lähteet + + + + Results + Tulokset + + + + Close all Search Resullts + Sulje kaikki hakutulokset + + + + Close All Search Results + Sulje kaikki hakutulokset + + + + Download Selected + Lataa valitut + + + + + Download + Lataa + + + + Enter a keyword here (at least 3 char long) + Anna hakusana (vähintään 3 merkkiä) + + + Copy retroshare Link + Kopioi RetroShare-linkki + + + Send retroshare Link + Lähetä RetroShare-linkki + + + Broadcast on Channel + Yleislähetä kanavalla + + + Recommend to Friends + Suosittele kavereille + + + + + Copy RetroShare Link + Kopioi RetroShare-linkki + + + + Send RetroShare Link + + + + + Remove + Poista + + + + Remove All + Poista kaikki + + + + + Folder + Kansio + + + + New RetroShare Link(s) + Uusi RetroShare-linkki tai -linkit + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Muoto</p></body></html> + + + + Any + Mikä tahansa + + + + Audio + Ääni + + + + Video + Video + + + Images + Kuvat + + + Programs + Ohjelmat + + + Archives + Pakatut tiedostot + + + Documents + Asiakirjat + + + + Download Notice + Lataushuomautus + + + + Skipping Local Files + Paikallisten tiedostojen ohittaminen + + + + + Sorry + Anteeksi + + + + + This function is not yet implemented. + Tätä toimintoa ei ole vielä otettu käyttöön. + + + + Size + Koko + + + + Type + Tyyppi + + + + Archive + Pakattu tiedosto + + + + CD-Image + CD-levykuva + + + + Document + Dokumentti + + + + Picture + Kuva + + + + Program + Ohjelma + + + + Directory + Hakemisto + + + + Filter Search Result + + + + + Clear Filter + Tyhjennä suodatin + + + + File Name + Tiedoston nimi + + + + File Size + + + + + Include files from your own file list in the search result + Sisällytä hakutuloksiin oman tiedostoluettelosi tiedostot + + + + Include own files + Sisällytä omat tiedostot + + + + Search inside "browsable" files of your friends + Etsi ystäviesi "selattavien" tiedostojen joukosta + + + + Search in friends lists + Etsi ystäväluettelosta + + + + Multi-hop search at distance 6 in the network +(always reports available files) + Usean hypyn haku verkossa etäisyydellä 6 +(näyttää aina saatavilla olevat tiedostot) + + + + F2F search + F2F-haku + + + + Limit number of results to : + Rajoita tulosten lukumäärä: + + + + Filename + Tiedostonimi + + + + Start Search + Aloita haku + + + + Search + Etsi + + + + Reset + Palauta asetukset + + + + Enter a Keyword here + Anna hakusana tähän + + + + Advanced Search + Tarkennettu haku + + + + Advanced + Tarkennettu + + + + Age + Ikä + + + + Hash + Tiiviste (hash) + + + + KeyWords + Hakusanat + + + + Search Id + Hakutunniste + + + + SendLinkDialog + + Send + Lähetä + + + + ServerDialog + + Transfer Rates + Siirtonopeudet + + + Port: + Portti: + + + + ServerPage + + Change + Restart Server + Vaihda ja uudelleenkäynnistä palvelin + + + Server Settings + Palvelinasetukset + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ulkoinen osoite:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Paikallinen osoite:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Portti:</p></body></html> + + + + Automatic (Upnp) + Automaattinen (UPnP) + + + + Firewalled + Palomuuri + + + + Manual Forwarded Port + Portti avattu käsin + + + Should be disabled if you don't want to share connection information between peers. + Tulisi olla poissa päältä, jos et halua jakaa yhteysinformaatiota vertaisten kesken. + + + + Download (KB/s) + Lataus (Kt/s) + + + + Upload (KB/s) + Lähetys (Kt/s) + + + + + Network Configuration + Verkon asetukset + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + Julkinen: DHT & etsintä + + + + Private: Discovery Only + Yksityinen: Vain etsintä + + + + Inverted: DHT Only + Käänteinen: Vain DHT + + + + Dark Net: None + Darknet: ei mitään + + + + + kB/s + kB/s + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + Jos poistat tästä rastin, RetroShare ei käytä tunneliyhteyttä palomuuria käyttävien vertaisten välillä eikä voi ottaa suoraa yhteyttä. Tämä on riippumaton F2F-reitittämisestä (kilpikonnareititin). + + + + Allow Tunnel Connection + Salli tunneliyhteys + + + + Local Address + Paikallinen osoite + + + + External Address + Ulkoinen osoite + + + + Dynamic DNS + Dynaaminen nimipalvelujärjestelmä + + + + + Port: + Portti: + + + + Show Discovery information in statusbar + + + + + IP Service + IP-palvelu + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + Jos poistat tästä rastin, RetroShare voi ainoastaan määritellä +IP-osoitteesi, jos olet yhteydessä johonkuhun. Tämän +jättäminen päälle helpottaa yhteydenottoa, kun sinulla on +vähän ystäviä. Se auttaa myös, jos olet palomuurin tai VPN:n takana. + + + + Allow RetroShare to ask my ip to these websites: + Salli RetroSharen kysyä IP:täni näiltä verkkosivuilta: + + + Misc + Sekalaiset + + + behinde Firewall + Palomuurin takana + + + Forwarded External Port + Edelleenvälitetty ulkoinen portti + + + + Transfer Rates + Siirtonopeudet + + + + Settings + + Settings + Asetukset + + + + Options + Valinnat + + + + Transfer + Siirto + + + + Notify + Huomauta + + + + Security + Turvallisuus + + + + Message + Viesti + + + + Forum + Foorumi + + + + Chat + Keskustelu + + + + Appearance + Ulkoasu + + + + Sound + Ääni + + + + Cancel + Peru + + + Apply + Toteuta + + + + OK + OK + + + + General + Yleiset + + + Network + Verkko + + + + Server + Palvelin + + + + Directories + Hakemistot + + + + ShareDialog + + + RetroShare Share Folder + RetroSharen jaettu kansio + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Jaettu kansio</span></p></body></html> + + + + Share Folder + Jaettu kansio + + + + Local Path + Paikallinen polku + + + + Browse + Selaa + + + + Virtual Folder + Virtuaalinen kansio + + + + Share Flags + Jakoilmaisimet + + + + Browsable + Selattavissa + + + + Anonymous shared Network Wide + Nimettömästi jaettu verkon laajuisesti + + + + Network Wide + Verkon laajuinen + + + + Browseable by Friends + Ystävien selattavissa + + + Friends + Ystävät + + + + OK + OK + + + + Cancel + Peru + + + + Select A Folder To Share + Valitse kansio jaettavaksi + + + + ShareKey + + + check peers you would like to share private publish key with + merkitse vertaiset, joiden kanssa haluat jakaa yksityisen julkaisuavaimesi + + + + Share Channel + Jakokanava + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Jakokanava</span></p></body></html> + + + + Share for Friend + Jaa ystävälle + + + + Contacts: + Kontaktit: + + + + Share + Jaa + + + + Cancel + Peru + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Valitse ystävät, joiden kanssa haluat jakaa kanavasi.</span></p></body></html> + + + + RetroShare + RetroShare + + + + Please select at least one peer + Valitse ainakin yksi vertainen + + + + ShareManager + + + Add a Share Directory + Lisää jaettava hakemisto + + + + Stop sharing selected Directory + Lopeta valitun hakemiston jakaminen + + + + + Remove + Poista + + + Add Shared Directory + Lisää jaettu hakemisto + + + + If checked, the share is anonymously shared to anybody. + Jos rastitat tämän, kyseinen jako on nimettömästi kaikkien saatavissa. + + + + If checked, the share is browsable by your friends. + Jos rastitat tämän, kyseinen jako on ystäviesi selattavissa. + + + + Warning! + Varoitus! + + + + Do you really want to stop sharing this directory ? + Haluatko todella lopettaa tämän hakemiston jakamisen? + + + + + Drop file error. + Virhe pudotettaessa tiedostoa. + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + RetroSharen jakamisten hallinta + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Jakamisten hallinta</span></p></body></html> + + + + Shared Folder Manager + Jaettujen kansioiden hallinta + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Tämä on luettelo jaetuista kansioista. Voit lisätä ja poistaa kansioita käyttämällä alaosan painikkeita.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Kun lisäät uuden kansion, alussa kaikki sen tiedostot tulevat jaetuiksi.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Voit määrittää erikseen jakoilmaisimia jokaiselle jaetulle hakemistolle:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Selattavissa</span><span style=" font-family:'Sans'; font-size:8pt;">: suorat ystäväsi voivat selata tiedostoja.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Verkon laajuinen</span><span style=" font-family:'Sans'; font-size:8pt;">: ketkä tahansa voivat ladata tiedostoja nimettömien tunneleiden kautta.</span></p></body></html> + + + + Directory + Hakemisto + + + + Virtual Folder + Virtuaalinen kansio + + + + Network Wide + Verkon laajuinen + + + + Browsable + Selattavissa + + + + Add + Lisää + + + + Close + Sulje + + + + Edit selected Shared Directory + Muokkaa valittua jaettua hakemistoa + + + + + Edit + Muokkaa + + + + SharedFilesDialog + + + + Download + Lataa + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Tiedostot</span></p></body></html> + + + + Checking... + Tarkistaa... + + + + Check files + Tarkista tiedostot + + + + Copy retroshare Link + Kopioi RetroShare-linkki + + + + Send retroshare Link + Lähetä RetroShare-linkki + + + + Copy retroshare Links to Clipboard + Kopioi RetroShare-linkkejä leikepöydälle + + + + Copy retroshare Links to Clipboard (HTML) + Kopioi RetroShare-linkkejä leikepöydälle (HTML) + + + + Send retroshare Links + Lähetä RetroShare-linkkejä + + + + Send retroshare Links (HTML) + Lähetä RetroShare-linkkejä (HTML) + + + + Send retroshare Links to Cloud + Lähetä RetroShare-linkkejä pilveen + + + + Add Links to Cloud + Lisää linkkejä pilveen + + + + + Open File + Avaa tiedosto + + + + Open Folder + Avaa kansio + + + + + Recommend in a message to + Suosittele viestissä vastaanottajalle + + + + + + RetroShare Link + RetroShare-linkki + + + + + + + Recommendation(s) + Suositukset + + + + Set command for opening this file + Aseta komento tämän tiedoston avaamiseksi + + + + <strong>My Shared Files</strong> + <strong>Omat jaetut tiedostot</strong> + + + + <strong>Friends Files</strong> + <strong>Ystävien tiedostot</strong> + + + + <strong>Files</strong> + <strong>Tiedostot</strong> + + + + Splitted View + Jaettu näkymä + + + + Friends Folders + Ystävien kansiot + + + + My Folders + Omat kansioni + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Tiedostot</span></p></body></html> + + + + All + Kaikki + + + + One day old + Päivän vanhat + + + + One Week old + Viikon vanhat + + + + One month old + Kuukauden vanhat + + + + Search files + Etsi tiedostoja + + + + Start Search + Aloita haku + + + + Reset + Palauta asetukset + + + + Tree view + + + + + Flat view + + + + + Download selected + Lataa valitut + + + + check files + tarkista tiedostot + + + + SoundPage + + + Sound Events + Tapahtumaäänet + + + + go Online + mene online + + + + Friend + Ystävä + + + + + + + + Browse + Selaa + + + + New Msg + Uusi viesti + + + + FileSend + Tiedoston lähetys + + + + + Finished + Valmis + + + + FileRecive + Tiedoston vastaanottaminen + + + + Incoming + Sisääntuleva + + + + Chatmessage + Keskusteluviesti + + + + SplashScreen + + + Load profile + Avaa profiili + + + + Load configuration + Avaa asetukset + + + + Create interface + Luo käyttöliittymä + + + + StartDialog + + + RetroShare + RetroShare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Kirjaudu</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + Kirjaudu sisään + + + + Remember Password + Tallenna salasana + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Create new Profile...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Luo uusi profiili...</span></a></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Tiedot...</span></a></p></body></html> + + + + Name (GPG Id) - location: + Nimi (GPG-tunniste) - sijainti: + + + + + Multiple instances + Useita instansseja + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile + Toinen RetroShare, joka käyttää samaa profiilia on jo käynnissä järjestelmässäsi. Ole hyvä ja sulje se ensin + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Odottamaton virhe haettaessa yhden instanssin lukitusta + + + + Login Failure + Kirjautuminen epäonnistui + + + + Maybe password is wrong + Ehkä salasana on väärin + + + Create a New Profile + Luo uusi profiili + + + This will generate a new Profile + Are you sure you want to continue? + Tämä generoi uuden profiilin +Oletko varma, että haluat jatkaa? + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + Insecure + Turvaton + + + Auto Login is not so much secure: + - Your SSL certificate will be stored unprotected. + - Your PGP key will however not be stored. +This choice be reverted in settings. + Automaattinen kirjautuminen ei ole kovin turvallinen: + - SSL-varmenteesi tallennetaan suojaamattomana. + - PGP-avaintasi ei sen sijaan tallenneta. +Tämän valinnan voi muuttaa asetuksista. + + + + StatisticDialog + + + Session: + Istunto: + + + + + Downloaded: + Ladattu: + + + Average Downloadspeed: + Keskimääräinen latausnopeus: + + + + + Count of Downloads: + Latausten määrä: + + + + + + Overall + Yhteensä + + + + Upload + Lähetys + + + + + + Session + Istunto + + + + Uploaded: + Lähetetty: + + + Average Uploadspeed: + Keskimääräinen lähetysnopeus: + + + + + Count of Uploads: + Lähetettyjen lukumäärä: + + + + Uploaded + Lähetetty + + + + + + + Connections: + Yhteydet: + + + + + + Peers: + Vertaiset: + + + Misc + Sekalaiset + + + + Uptime: + Päällä: + + + Overall: + Yhteensä: + + + + + Uptime + Päällä + + + + Records + Tietueet + + + + Uploadspeed: + Lähetysnopeus: + + + + Downloadspeed: + Latausnopeus: + + + + + Show Settings + Näytä asetukset + + + + Reset + Palauta asetukset + + + + Receive Rate + Vastaanottonopeus + + + + Send Rate + Lähetysnopeus + + + + Always On Top + Aina päällimmäisenä + + + + 100 + 100 + + + + % Opaque + % näkyvä + + + + Changes the transparency of the Bandwidth Graph + Muuttaa siirtonopeuskuvaajan läpinäkyvyyttä + + + + Save + Tallenna + + + + Cancel + Peru + + + + Hide Settings + Piilota asetukset + + + + %1 days + %1 päivää + + + + Statistics + Tilastot + + + + Now + Nyt + + + + Transfer + Siirto + + + + Session UL:DL Ratio: + Istunnon LAT:LÄH-suhde: + + + + Cumulative UL:DL Ratio + Kertynyt LAT:LÄH-suhde + + + + Download + Lataa + + + + Time Statistics + Aikatilastot + + + + Since: + Alkaen: + + + + Cumulative + Kertynyt + + + + StatusDefs + + + + Offline + Offline + + + + Away + Poissa + + + + Busy + Kiireinen + + + + Online + Linjoilla + + + + Idle + Jouten + + + + Friend is offline + Ystävä on offline + + + + Friend is away + Ystävä on poissa + + + + Friend is busy + Ystävä on kiireinen + + + + Friend is online + Ystävä on linjoilla + + + + Friend is idle + Ystävä on jouten + + + + Connected + + + + + Unreachable + + + + + Available + Saatavilla + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + Henkilökohtainen viesti + + + + Status message + Tilaviesti + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Henkilökohtainen viesti</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Kirjoita tilaviestisi<span style=" font-size:8pt; color:#666666;"></span></p></body></html> + + + + OK + OK + + + + Cancel + Peru + + + + Paste RetroShare Link + Liitä RetroShare-linkki + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + Valitse väri + + + + Color 2 + + + + + Color 1 + + + + + Style + Tyyli + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Tyyppi + + + + Delete FeedItem + Tuhoa syötekohde + + + + SubFileItem + + File Name + Tiedoston nimi + + + + + ERROR + VIRHE + + + + EXTRA + YLIMÄÄRÄINEN + + + + REMOTE + ETÄ + + + + DOWNLOAD + LATAUS + + + + LOCAL + PAIKALLINEN + + + + UPLOAD + LÄHETYS + + + + File %1 does not exist at location. + Tiedostoa %1 ei löydy sijainnista. + + + + File %1 is not completed. + Tiedosto %1 ei ole valmistunut. + + + + Save Channel File + Tallenna kanavatiedosto + + + + Download + Lataa + + + + Play + Toista + + + + %p Kb + %p Kb + + + + Save File + Tallenna tiedosto + + + + Cancel Download + Peru lataus + + + + Download File + Lataa tiedosto + + + + + + Play File + Toista tiedosto + + + + TBoard + + + Pause + Tauko + + + + TagDefs + + + Important + Tärkeä + + + + Work + Työ + + + + Personal + Henkilökohtainen + + + + Todo + Tehtävänä + + + + Later + Myöhemmin + + + + TagsMenu + + + Remove All Tags + Poista kaikki merkkaukset + + + + New tag ... + Uusi merkkaus... + + + + TextPage + + + Use text representation of the PGP certificates. + Näytä PGP-varmenteet tekstimuotoisina. + + + + The text below is your PGP certificate. You have to provide it to your friend + Allaoleva teksti on PGP-varmenteesi. Sinun täytyy antaa se ystävällesi + + + + Please, paste your friends PGP certificate into the box below + Ole hyvä ja liitä ystäväsi PGP-varmenne allaolevaan laatikkoon + + + + You can copy this text and send it to your friend via email or some other way + Voit kopioida tämän tekstin ja lähettää sen ystävällesi sähköpostilla tai muulla tavoin + + + + RetroShare + RetroShare + + + + Text certificate + Tekstivarmenne + + + + Copy your Cert to Clipboard + Kopioi varmenne leikepöydälle + + + + Save your Cert into a File + Tallenna varmenne tiedostoon + + + + Run Email program + Käynnistä sähköpostiohjelma + + + + Clean certificate + + + + + RetroShare Invite + RetroSharekutsu + + + + Connect Friend Help + Ohje ystävän yhdistämisestä + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + Varmenteesi on kopioitu leikepöydälle, liitä ja lähetä se ystävällesi sähköpostilla tai muulla tavoin + + + + Save as... + Tallenna nimellä... + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroSharen varmenne (*.rsc );;Kaikki tiedostot (*) + + + + Certificate Load Failed + Varmenteen lataus epäonnistui + + + + TransferPage + + + Transfer options + Siirtoasetukset + + + + Queue Size: + Jonon pituus: + + + + Default chunk strategy: + Palasten oletusstrategia: + + + + Safety disk space limit : + Kiintolevytilan turvallisuusrajoitus: + + + + Streaming + Suoratoisto + + + + Random + Satunnainen + + + + MB + Mt + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;">kykenee siirtämään dataa ja hakupyyntöjä vertaisten välillä ilman, että he ovat ystäviä keskenään. Tämä liikenne tapahtuu kuitenkin ainoastaan yhteydessä olevien ystävien välityksellä ja on nimetöntä.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Voit määrittää erikseen jakoilmaisimia jokaiselle jaetulle hakemistolle:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ystävien selattavissa</span>: ystäväsi näkevät tiedostosi.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Nimettömästi jaetut</span>: tiedostoihin päästään käsiksi nimettömästi kaukaisten F2F-tunneleiden kautta.</li></ul></body></html> + + + + TransfersDialog + + + Cancel + Peru + + + + Clear Completed + Poista valmistuneet + + + + + Status + Tila + + + + Completed + Valmis + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Lataukset:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Lataukset:</span></p></body></html> + + + + Show cache transfers + Näytä välimuistisiirrot + + + + Uploads + Lähetykset + + + + Selected transfer + Valittu siirto + + + + Done + Valmis + + + + Active + Aktiivinen + + + + Outstanding + Suorittamaton + + + Tunneling + Tunneloitu + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Lähetykset:</span></p></body></html> + + + + + Name + i.e: file name + Nimi + + + + + Size + i.e: file size + Koko + + + Progress + i.e: % downloaded + Edistyminen + + + + Speed + i.e: Download speed + Nopeus + + + + Progress / Availability + i.e: % downloaded + Edistyminen / saatu + + + + Sources + i.e: Sources + Lähteet + + + + Core-ID + Ydintunniste + + + + Progress + i.e: % uploaded + Edistyminen + + + + Speed + i.e: upload speed + Nopeus + + + + Transferred + Siirretty + + + + Hash + Tiiviste (hash) + + + + Play + Toista + + + + Pause + Tauko + + + + Resume + Jatka + + + + Force Check + Pakota tarkistus + + + + Open Folder + Avaa kansio + + + + Open File + Avaa tiedosto + + + + Preview File + Esikatsele tiedostoa + + + + Details... + Yksityiskohdat... + + + + Down + Alas + + + + Up + Ylös + + + + Top + Ylimmäiseksi + + + + Bottom + Alimmaiseksi + + + + Priority (Speed)... + Tärkeysjärjestys (nopeus)... + + + + Streaming + Suoratoisto + + + + Random + Satunnainen + + + + Chunk strategy + Palasten strategia + + + + Queued + Jonossa + + + + Paused + Tauolla + + + + Transferring + Siirtää + + + + Checking... + Tarkistaa... + + + + RetroShare + RetroShare + + + + Details: + Yksityiskohdat: + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + Avaa siirto + + + + File %1 is not completed. If it is a media file, try to preview it. + Tiedosto %1 ei ole valmis. Jos se on mediatiedosto, voit yrittää esikatsella sitä. + + + + Are you sure that you want to cancel and delete these files? + Oletko varma, että haluat perua ja tuhota nämä tiedostot? + + + + Speed / Queue position + Nopeus / paikka jonossa + + + + Remaining + Jäljellä + + + + Download time + i.e: Estimated Time of Arrival / Time left + Latausaika + + + + Peer + i.e: user name + Vertainen + + + + Router Statistics + Reitittimen tilastot + + + + Router Requests + + + + + Copy RetroShare Link + Kopioi RetroShare-linkki + + + + Paste RetroShare Link + Liitä RetroShare-linkki + + + + + Slower + Hitaammin + + + + + + Average + Keskinkertaisella nopeudella + + + + + Faster + Nopeammin + + + + Move in Queue... + Siirrä jonossa... + + + + + + Failed + Epäonnistunut + + + + + + Okay + OK + + + + + Waiting + Odottaa + + + + Downloading + Lataa + + + + + + + Complete + Valmis + + + + Unknown + Tuntematon + + + + version: + versio: + + + + Uploading + Lähettää + + + + TreeStyle_RDM + + + + FILE + TIEDOSTO + + + + Files + Tiedostot + + + + File + Tiedosto + + + + + DIR + HAK + + + + Friends Directories + Ystävien hakemistot + + + + My Directories + Omat hakemistot + + + + Size + Koko + + + + Age + Ikä + + + + Friend + Ystävä + + + + Share Type + Jakamisen tyyppi + + + + What's new + Uusia + + + + TrustView + + + Zoom : + Koko: + + + + Update + Päivitä + + + + + Showing: whole network + Näyttää: koko verkon + + + + This table normaly auto-updates every 10 seconds. + Tämä taulukko päivittää itsensä normaalisti joka kymmenes sekunti. + + + + Self + Itse + + + + Trust + Luottamus + + + is athenticated (one way) by + on varmennettu (yhdellä tavalla) + + + athenticated himself + varmentajan itsensä toimesta + + + athenticated each others + varmennettujen osapuolten toimesta + + + is athenticated by + on varmennettu + + + athenticated + varmennettu + + + + is authenticated (one way) by + + + + + Half + Puolet + + + + authenticated himself + + + + + authenticated each other + + + + + Full + Täysi + + + + + peers, including him(her)self. + vertaiset, mukaanlukien hän itse. + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + Näyttää: vertaiset yhteydessä + + + + TurtleRouterDialog + + + + Search requests + Hakupyynnöt + + + + + Tunnel requests + Tunnelointipyynnöt + + + + TurtleRouterDialogForm + + + Router Statistics + Reitittimen tilastot + + + + F2F router information + F2F-reitittimen tiedot + + + File Name + Tiedoston nimi + + + Type + Tyyppi + + + + TurtleRouterStatistics + + + Router Statistics + Reitittimen tilastot + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Download + Lataa + + + Broadcast on Channel + Yleislähetä kanavalla + + + Recommend to Friends + Suosittele kavereille + + + Remove + Poista + + + Remove All + Poista kaikki + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Muoto</p></body></html> + + + Any + Mikä tahansa + + + Audio + Ääni + + + Video + Video + + + Size + Koko + + + Sources + Lähteet + + + Type + Tyyppi + + + Results + Tulokset + + + + ULListDelegate + + + B + t + + + + KB + Kt + + + + MB + Mt + + + + GB + Gt + + + + VMessageBox + + + OK + OK + + + + Cancel + Peru + + + + Yes + Kyllä + + + + No + Ei + + + + Help + Ohje + + + + Retry + Yritä uudelleen + + + + Show Log + Näytä loki + + + + Show Settings + Näytä asetukset + + + + Continue + Jatka + + + + Quit + Lopeta + + + + Browse + Selaa + + + + misc + + + Unknown + Unknown (size) + Tuntematon + + + + B + bytes + t + + + + KiB + kibibytes (1024 bytes) + kibitavu + + + + MiB + mebibytes (1024 kibibytes) + mebitavu + + + + GiB + gibibytes (1024 mibibytes) + gibitavu + + + + TiB + tebibytes (1024 gibibytes) + tebitavu + + + + Unknown + Tuntematon + + + + < 1m + < 1 minute + < 1 min + + + + %1 minutes + e.g: 10minutes + %1 minuuttia + + + + %1d %2h + e.g: 2days 10hours + %1d %2h + + + + %1y %2d + e.g: 2 years 2days + %1v %2d + + + + k + e.g: 3.1 k + k + + + + M + e.g: 3.1 M + M + + + + G + e.g: 3.1 G + G + + + + T + e.g: 3.1 T + T + + + + %1h %2m + e.g: 3hours 5minutes + %1h %2min + + + + moreinfo + + Details + Yksityiskohdat + + + OK + OK + + + Name + Nimi + + + Value + Arvo + + + diff --git a/retroshare-gui/src/lang/retroshare_fr.qm b/retroshare-gui/src/lang/retroshare_fr.qm new file mode 100644 index 000000000..1f04fc649 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_fr.qm differ diff --git a/retroshare-gui/src/lang/retroshare_fr.ts b/retroshare-gui/src/lang/retroshare_fr.ts new file mode 100644 index 000000000..21b9eada7 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_fr.ts @@ -0,0 +1,16521 @@ + + + + + AboutDialog + + + About RetroShare + A propos de RetroShare + + + + About + A propos + + + + close + Fermer + + + + + About RetroShare %1 + A propos de Retroshare %1 + + + + Max score: %1 + Meilleur score :%1 + + + + Score: %1 + Score :%1 + + + + Level: %1 + Niveau : %1 + + + + Have fun ;-) + Amusez-vous ;-) + + + + AddFileAssociationDialog + + + File type(extension): + Type de fichier (extension) : + + + + Use default command + Utiliser la commande par défaut + + + + Command + Commande + + + + RetroShare + RetroShare + + + + Sorry, can't determine system default command for this file + + Impossible de déterminerla commande système par défaut pour ce fichier + + + + + AddLinksDialog + + + + Add Link + Ajouter un lien + + + + Add a new Link + Ajouter un nouveau lien + + + + Title: + Titre : + + + + Url: + URL : + + + Score: + Points : + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400;">Title:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400;">Titre :</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400;">Url:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400;">URL :</span></p></body></html> + + + + +2 Great! + +2 Excellent ! + + + + +1 Good + +1 Bien + + + + 0 Okay + 0 Moyen + + + + -1 Sux + -1 Mauvais + + + + -2 Bad Link + -2 Très Mauvais + + + + Add Anonymous Link + Ajouter un lien anonyme + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Ajouter un lien dans le Cloud</span></p></body></html> + + + + Cancel + Annuler + + + + Add Link Failure + L'ajout du lien a échoué + + + + Missing Link and/or Title + Lien et/ou titre absent + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + RetroShare : Recherche avancée + + + + Cancel + Annuler + + + + Search + Rechercher + + + RetrosShare: Advanced Search + RetroShare : Recherche avancée + + + + Add a further search criterion. + Ajouter un critère de recherche + + + Add a selection criterion + Ajoutez un critère de sélection + + + + Reset the search criteria. + Réinitialiser les critères de recherche + + + Reset + Effacer + + + + Cancels the search. + Annuler la recherche + + + + Perform the advanced search. + Lancer la recherche + + + + Search Criteria + Critère(s) de recherche + + + + AppearancePage + + + Language + Language + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choisir le language utilisée par RetroShare</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Le changement de language de l'interface ne prendra effet qu'après le redémarrage de RetroShare !</p></body></html> + + + + Style + Habillage + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choisir le thème visuel de RetroShare</p></body></html> + + + + Style Sheet + Feuille de style + + + + ApplicationWindow + + RetroShare %1 + %1 RetroShare + + + + Hide + Cacher + + + + Show + Afficher + + + Peers + Personne + + + Transfers + Transferts + + + Messages + Messages + + + Blog Feed + Fil d'actualité du Blog + + + + Games Launcher + Lanceur de jeux + + + + Photo View + Visionneuse d'image + + + + Shared Calendars + Calendriers partagés + + + Library + Librairie + + + + Statistics + Statistiques + + + + + RetroShare + RetroShare + + + + AttachFileItem + + + Form + Formulaire + + + File Name + Nom du fichier + + + + %p Kb + %p Ko + + + + Cancel Download + Annuler le téléchargement + + + + BandwidthGraph + + + RetroShare Bandwidth Usage + Trafic réseau RetroShare + + + + + Show Settings + Options + + + + Reset + Réinitialiser + + + + Receive Rate + Vitesse de réception + + + + Send Rate + Vitesse d'émission + + + + Always on Top + Toujours visible + + + + Style + Style + + + + Changes the transparency of the Bandwidth Graph + Modifier la transparence du graphique du trafic + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Save + Mémoriser + + + + Cancel + Annuler + + + + Since: + Statistiques enregistrées depuis : + + + + Hide Settings + Masquer les options + + + + BlogDetails + + + + Blog Details + Détails du Blog + + + + Blog Info + Informations sur le Blog + + + + Blog Name + Nom du Blog + + + + Popularity + Popularité + + + + Last Post + Dernier article + + + + Blog ID + ID du Blog + + + + Blog Description + Description du Blog + + + + Cancel + Annuler + + + + OK + OK + + + + Close + Fermer + + + + BlogMsgItem + + + Form + Formulaire + + + + Remove Item + Supprimer l'article + + + Connected + Connecté + + + + Expand + Développer + + + + Subject + Objet + + + subjectLabel + Sujet + + + + Play Media + Lire l'élément multimédia + + + Long + message here + Tappez votre message içi + + + + BlogNewItem + + Form + Formulaire + + + + Remove Item + Supprimer l'article + + + + Subscribe to Blog + S'abonner aux mises à jour du Blog + + + + Expand + Développer + + + + Blog Decscription + Description du Blog + + + + BlogsDialog + + + Form + Formulaire + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + Add + Ajouter + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt;">Blog Name</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt;">Titre du Blog</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Nom du Blog</span></p></body></html> + + + Post To Channel + Poster sur le canal + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Publier sur le Blog</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Se désabonner des mises à jour du Blog</span></p></body></html> + + + + Unsubscribe + Se désabonner + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">S'abonner aux mises à jour Blog</span></p></body></html> + + + + Subscribe + S'abonner + + + + + Create New Blog + Créer un nouveau Blog + + + + Name + Nom + + + + ID + ID + + + + Own Blogs + Mes Blogs + + + + Subscribed Blogs + Blogs abonnés + + + + Popular Blogs + Blogs populaires + + + + Other Blogs + Autres Blogs + + + + Post to Blog + Poster un article sur le Blog + + + + Subscribe to Blog + S'abonner aux mises à jour du Blog + + + + Unsubscribe to Blog + Se désabonner des mises à jour du Blog + + + + Show Blog Details + Afficher les détails du Blog + + + Show Channel Details + Afficher les détails du canal + + + + Create a new Blog + Créer un nouveau Blog + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + Popularité : %1 +Récupérés : %2 +Disponible : %3 + + + + BlogsMsgItem + + + Form + Formulaire + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Objet du Blog</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Date</span></p></body></html> + + + + Comment + Commantaire + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Blog Message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Message du Blog</span></p></body></html> + + + + Unsubscribe From Channel + Se désabonner des mises à jour de la Chaîne + + + + Remove Item + Supprimer l'article + + + + + Expand + Développer + + + TextLabel + Etiquette + + + + Comments here + Tappez votre commentaire ici + + + + Hide + Cacher + + + + CalDialog + + + Name: + Nom : + + + + Location: + Machine : + + + + Remove + Supprimer + + + + Form + Formulaire + + + + Local Calendars + Calendriers locaux + + + + Shared Calendar List + Calendriers partagés + + + + Share Details + Détails des partages + + + + ... + ... + + + + Status: + Statut : + + + + Private + Privé + + + + Public + Public + + + + Allow List: + Liste autorisée : + + + + <Disabled> + <Désactivé> + + + + Add + Ajouter + + + + Peer Calendars + Calendriers d'un contact + + + + CallToaster + + Message + Message + + + + CertificatePage + + + Certificate files + Se connecter en utilisant les certificats + + + Use XPGP certificates saved in files. + Utilisez des certificats XPGP sauvés dans les fichiers. + + + + Use PGP certificates saved in files. + Utilisez les certificats PGP contenu dans un fichier. + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + Vous devez générer votre certificat sous forme de fichier et le transmettrer à vos amis. + + + + Export my certificate... + Exporter mon certificat... + + + Specify path to your friend's certificate in the box below + Spécifiez le chemin du certificat de votre ami dans la boîte ci-dessous + + + + Browse + Parcourir + + + + Select Certificate + Sélectionner le certificat + + + RetroShare Certificates (*.rsc) + Certificats RetroShare (*.rsc) + + + Not implemented + Pas encore mis en place + + + Certificates (*.pqi *.pem) + Certificats (*.pqi *.pem) + + + + Please choose a filename + Veuillez spécifier un nom de fichier + + + + + + + RetroShare + RetroShare + + + + Import friend's certificate... + Exporter ou importer un certificat + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + Importez le certificat à partir de votre disque dur + + + + + RetroShare Certificate (*.rsc );;All Files (*) + Certificat RetroShare (*.rsc );;Tous les fichiers (*) + + + + Sorry, create certificate failed + Erreur ! La génération de votre certificat a échoué + + + + Certificate file successfully created + Votre certificat a été généré avec succès + + + + + Sorry, certificate file creation failed + Erreur ! La génération de votre certificat a échoué + + + + Certificate Load Failed:something is wrong with %1 + L'importation du certificat a échoué : un problème est survenu avec %1 + + + + Certificate Load Failed:can't read from file %1 + L'importation du certificat a échoué : impossible de lire le fichier %1 + + + + Certificate Load Failed:file %1 not found + L'importation du certificat a échoué : le fichier %1 n'a pas été trouvé + + + + ChanMsgItem + + Form + Formulaire + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:normal; color:#656565;">Channel Subject</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:normal; color:#656565;">Sujet du canal</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Date</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Short Description</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Description rapide</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Toggle Message Read Status</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Marquer le message comme lu</p></body></html> + + + + Toggle Message Read Status + Afficher l'état des Messages + + + + New + Nouveau + + + + Download + Télécharger + + + + Play + Lecture + + + + Remove Item + Supprimer l'article + + + + Copy RetroShare Link + Copier le lien RetroShare + + + Connected + Connecté + + + + + Expand + Développer + + + subjectLabel + Sujet + + + + Unsubscribe From Channel + Se désabonner de la Chaîne + + + Play Media + Lire le fichier multimédia + + + TextLabel + Etiquette + + + Long + message here + Tappez votre texte içi + + + + Channel Feed + Fil d'actualité des Chaînes + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + Attention! Vous avez moins de %1 heures et %2 minutes avant que ce fichier soit supprimé. Pensez à l'enregistrer. + + + + Hide + Cacher + + + + ChanNewItem + + Form + Formulaire + + + + Remove Item + Supprimer l'article + + + Connected + Connecté + + + + Unknown Channel + Chaîne inconnue + + + + New Channel + Nouvelle Chaîne + + + + Updated Channel + Chaîne mise à jour + + + name + Nom + + + + Subscribe to Channel + S'abonner à la Chaîne + + + + Expand + Développer + + + + Channel Decscription + Description de la Chaîne + + + Description + of Forum + Description + du forum + + + + ChannelDetails + + + + Channel Details + Détails de la Chaîne + + + + Channel Info + Informations de la Chaîne + + + Forum Name + Nom du Forum + + + + Popularity + Popularité + + + + Last Post + Dernier article + + + Forum ID + ID du Forum + + + + Channel Name + Nom de la Chaîne + + + + Channel ID + ID de la Chaîne + + + + Channel Description + Description de la Chaîne + + + + Type + Type + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Restreint - N'importe qui peut lire, mais la publication est limitée (Clé de publication privée) + + + + Private - (Private Publish Key required to view Messages) + Privé - La clé de publication privée est exigée pour voir les messages + + + + Cancel + Annuler + + + + OK + OK + + + + Close + Fermer + + + + ChannelFeed + + + Create Channel + Créer une Chaîne + + + + Subscribe To Channel + S'abonner à la Chaîne + + + Form + Formulaire + + + Channel Name + Nom du canal + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Chaînes</span></p></body></html> + + + Add + Ajouter + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt;">Channel Name</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt;">Nom du canal</span></p></body></html> + + + Post To Channel + Poster sur le canal + + + Enter a Keyword here + Entrez un mot clé + + + Title + Titre + + + Description + Description + + + Reset + Réinitialiser + + + + Display + Affichage + + + + Unsubcribe To Channel + Se désabonner de la Chaîne + + + + Unsubscribe + Se désabonner + + + + Subscribe + S'abonner + + + + Set all to read + Tout marquer comme lu + + + + Enable Auto-download + Activer le téléchargement automatique + + + Auto Download On + Téléchargement automatique activé + + + Auto Download Off + Téléchargement automatique désactivé + + + Create New Channel + Créer un nouveau canal + + + Name + Nom + + + Popularity + Popularité + + + ID + ID + + + + Own Channels + Mes chaînes + + + + Subscribed Channels + Chaînes abonnées + + + + Popular Channels + Chaînes populaires + + + + Other Channels + Autres chaînes + + + + Share Channel + Partager la Chaine + + + + Copy RetroShare Link + Copier le lien RetroShare + + + + Disable Auto-Download + Désactiver le téléchargement automatique + + + + Enable Auto-Download + Activer le téléchargement automatique + + + Popularity: %1 + Popularité: %1 + + + + No Channel Selected + Aucune Chaîne sélectionnée + + + + + Post to Channel + Poster un article sur la Chaîne + + + + Subscribe to Channel + S'abonner à la Chaîne + + + + Unsubscribe to Channel + Se désabonner de la Chaîne + + + + Show Channel Details + Montrer les détails de la Chaîne + + + + Restore Publish Rights for Channel + Restaurer les droits de publication de la Chaîne + + + + Edit Channel Details + Editer les détails de la Chaîne + + + Create a new Channel + Créer un nouveau canal + + + New Channel + Nouveau canal + + + Popularity: %1 +Fetches: %2 +Available: %3 + Popularité : %1 +Amenés : %2 +Disponible : %3 + + + + ChatMsgItem + + Form + Formulaire + + + TextLabel + Etiquette + + + + Remove Item + Supprimer + + + + Write a quick Message + Envoyer un message instantané + + + + Send Mail + Envoyer un messager électronique + + + + Write Message + Envoyer un message + + + + Send + Envoyer + + + + Cancel + Annuler + + + + + Start Chat + Dialoguer + + + + Quick Message + Message instantané + + + + ChatPage + + + General + Général + + + + Chat Settings + Paramètres du Chat + + + + Enable Emoticons Privat Chat + Activer les émoticônes pour le Chat privé + + + + Chat Font + Police d'écriture + + + + Change Chat Font + Changer la police d'écriture + + + + Chat Font: + Police d'écriture : + + + + Enable Private Chat History + Activer l'historique du Chat privé + + + + Enable Group Chat History + Activer l'historique du Chat public + + + + Send message with Ctrl+Return + Envoyer les messages avec Ctrl+Entrée + + + + Chat History + Historique du Chat + + + + Load number of messages (0 = off) + Nombre de messages visibles [0 = aucun] + + + + Group Chat + Chat public + + + + Private Chat + Chat privé + + + + Style + Style + + + + Group chat + Chat public + + + + + + Variant + Variante + + + + + + Author: + Auteur : + + + + + + Description: + Description : + + + + Private chat + Chat privé + + + + History + Historique + + + + Enable Emoticons Group Chat + Activer les émoticônes pour le Chat public + + + + Incoming message in history + Message entrant pour l'historique + + + + Outgoing message in history + Message sortant pour l'historique + + + + Incoming message + Message entrant + + + + Outgoing message + Message sortant + + + + Outgoing offline message + Message sortant hors-ligne + + + + ChatStyle + + + Standard style for group chat + Préférences du Chat public + + + + Standard style for private chat + Préférences du Chat privé + + + + Standard style for history + Préférences de l'historique + + + + ChatToaster + + Message + Message + + + + ComboStatus + + Away + Absent(e) + + + Busy + Occupé(e) + + + + ConclusionPage + + + Make Friend + Devenir ami + + + + Details about your friend : + A propos de votre ami + + + + Key validity: + Validité de la clé : + + + + Email: + Mail : + + + + Options + Options supplémentaires + + + + Add friend to group: + Ajouter votre ami à un groupe : + + + + Authenticate friend (Sign GPG Key) + Authentifier cet ami (Signer la clé PGP) + + + + Add as friend to connect with + Ajouter cet ami pour communiquer avec lui + + + Add as friend and Sign GPG Key + Ajouter comme ami et signer sa clé GPG + + + Add as friend but don't sign GPG Key + Ajouter comme ami mais ne pas signer sa clé GPG + + + Peer is already a retroshare friend. Sign his GPG key. + Ce contact est déjà un ami RetroShare. Signer sa clé GPG. + + + GPG key is already signed, make it a retroshare friend. + La clé GPG a déjà été signée, ajoutez-le en tant qu'ami. + + + + It seems your friend is already registered. Adding it might just set it's ip address. + Vous avez déjà ajouté cet ami. L'ajouter se limitera à enregistrer son adresse IP. + + + Fill details about your friend here + Remplissez ici, les détails de votre ami + + + + Peer details + Informations sur ce contact + + + Trust: + Confiance : + + + + Name: + Nom : + + + + Loc: + Emplacement : + + + Country: + Pays: + + + + Signers + Ils lui font aussi confiance : + + + AUTH CODE + AUTH CODE + + + + ConfCertDialog + + + Cancel + Annuler + + + Port: + Port : + + + Trust Settings + Paramètres de confiance + + + Trust Level + Niveau de confiance + + + Trust Their Signature + Faire confiance à leur signature + + + Sign The Certificate + Signer le certificat + + + + OK + OK + + + + Peer Info + Information du contact + + + Peer Details + Détails de la personne + + + + Details + Détails + + + Name: + Nom : + + + + Last Contact + Dernière fois vu : + + + + Apply and Close + Appliquer et fermer + + + + + RetroShare + RetroShare + + + + + Error : cannot get peer details. + Erreur : impossible d'obtenir les détails de ce contact. + + + + Your key is signed by : + Votre clé PGP a été signée par : + + + + Peer key is signed by : + La clé PGP du contact a été signée par : + + + + Your trust in this peer is ultimate, it's probably a key you own. + Vous faîtes totalement confiance à ce contact, c'est probablement une de vos propre clés. + + + + Your trust in this peer is full. + Vous faîtes totalement confiance à ce contact. + + + + Your trust in this peer is marginal. + Vous faîtes moyennement confiance à ce contact. + + + + Your trust in this peer is none. + Vous ne faites pas confiance à ce contact. + + + + Your trust in this peer is not set. + Vous n'avez pas encore déterminé votre degré de confiance pour ce contact. + + + + Peer has authenticated me as a friend and did sign my GPG key + Ce contact m'a authentifié comme ami et a signé ma clé PGP + + + + Peer has not authenticated me as a friend and did not sign my GPG key + Ce contact ne m'a pas authentifié comme ami et n'a pas signé ma clé PGP + + + + Signature Failure + La signature a échoué + + + + Maybe password is wrong + Le mot de passe est incorrect + + + Copy Peer + Copier le contact + + + Org / Loc: + Org / Loc : + + + Country/State: + Pays/Région : + + + + Peer ID + ID du contact : + + + + Version + Version d RetroShare : + + + Loc: + Lieu : + + + + Peer Address + Adresses IP du contact + + + Local Address: + Adresse local : + + + External Address: + Adresse externe : + + + + Addresses list + Liste d'adresses IP connues: + + + + Trust + Confiance + + + + None + Nulle + + + + Marginal + Moyenne + + + + Full + Totale + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signer la clé d'un ami est le moyen d'accorder votre confiance envers lui pour la montrer à vos autres amis. Cepandant, seuls les amis dont vous avez signé leur clé pourront recevoir les informations à propos des autres amis à qui vous faîtes confiance.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">On ne peut pas révoquer une signature de clé, donc faîtes attention à qui vous accordez votre confiance.</p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signer la clé d'un ami est le moyen d'accorder votre confiance envers lui pour la montrer à vos autres amis. Cepandant, seuls les amis dont vous avez signé leur clé pourront recevoir les informations à propos des autres amis à qui vous faîtes confiance.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">On ne peut pas révoquer une signature de clé, donc faîtes attention à qui vous accordez votre confiance.</p></body></html> + + + + Deny Friend + Ignorer cet ami + + + + Make Friend + Devenir ami + + + + Certificate + Certificat + + + Make Friends + Devenir amis + + + + + Sign GPG key + Signer la clé PGP + + + Sign GPG Key + Signer la clé PGP + + + Your trust in this peer is : + Votre confiance envers ce contact est : + + + + Friend Details + Détails de cet ami + + + + Name + Nom : + + + + Loc + Emplacement : + + + + RetroShare ID + ID Retroshare + + + + Status + Statut : + + + + Local Address + Adresse locale : + + + + External Address + Adresse externe : + + + + Dynamic DNS + Dynamic DNS : + + + + + Port + Port : + + + + Your trust in this peer is: + Votre confiance en cette personne est : + + + None + Aucun + + + Marginal + Moyenne + + + Full + Totale + + + + GPG Key + Clé PGP + + + + Peer has signed my GPG key + Cette personne a signé ma clé PGP + + + + Show Help for Trust Settings and Signing + Afficher de l'aide pour paramètrer la confiance + + + + Peer key is signed by : + La clé de ce contact a été signée par : + + + Sign this certificate + Signer ce certificat + + + Accept connexions from this peer + Acceptez les connexions de ce pair + + + Peer has signed my certficate + Le Pair a signé mon certificat + + + Certificate signers + Signataires du certificat + + + Make friend (Sign certificate and accept) + Faire ami (signer le certificat et accepter) + + + + ConnectFriendWizard + + + Connect Friend Wizard + Assistant de connexion à un ami + + + + CreateBlog + + + Create new Blog + Publier un nouveau Blog + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Nouveau Blog</span></p></body></html> + + + + Name + Nom + + + + Description + Description + + + + Type: + Catégorie : + + + + Public - Anyone can read and publish (Shared Publish Key) + Public - Tout le monde peut lire et publier (la clé de pubication est partagée) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Restreint - Tout le monde peut lire, mais la publication est limitée (la clé de publication est privée) + + + + Private - (Private Publish Key required to view Messages) + Privé - La clé de publication privée est exigée pour voir les messages + + + + Allowed Messages + Messages autorisés + + + + Authemticated Messages + Messages signés + + + + Anonymous Messages + Messages anonymes + + + + Blog Logo + Logo du Blog + + + + Add Blog Logo + Ajouter un logo + + + + Cancel + Annuler + + + + Create + Créer + + + + RetroShare + RetroShare + + + + Please add a Name + Veuillez ajoutez un nom + + + + Load File + Ajouter un fichier + + + + Pictures (*.png *.xpm *.jpg) + Images (*.png *.xpm *.jpg) + + + + CreateBlogMsg + + + New Blog Post + Nouveau message du Blog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Blog Post</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">Nouveau message du Blog</span></p></body></html> + + + + Blog Post + Poster un message + + + + Blog Post to: + Poster un message à : + + + + Visual Editor + Editeur visuel + + + + Blog Message + Message du blog + + + + Subject : + Objet : + + + + Html Editor + Editeur Html + + + Attachments + Fichiers joints + + + + toolBar + Barre d'outils + + + + toolBar_2 + Barre d'outils_2 + + + + blockquoute + Citation + + + + Increase font Size + Accroître la taille de la police + + + + Decrease font size + Réduire la taille de la police + + + + Bold + Gras + + + + Underline + Souligné + + + + Italic + Italique + + + + Publish + Publier + + + + New + Nouveau + + + + Code + + + + + splitPost + Diviser le message + + + + Ordered List + Liste ordonnée + + + + Unordered List + Liste désordonnée + + + + Clipboard + Presse-papier + + + + Undo + Annuler + + + Drag and Drop Files from Search Results + Glisser et déposer les fichiers du résultats de recherche + + + Add Extra File + Ajouter un fichier supplémentaire + + + + RetroShare + RetroShare + + + + Please add a Subject + Veuillez ajouter un objet + + + + &File + &Fichier + + + + &New + &Nouveau + + + + &Open... + &Ouvrir... + + + + &Save + Enregi&strer + + + + Save &As... + Enregistrer sous... + + + + &Print... + Im&primer... + + + + Print Preview... + Aperçu avant l'impression + + + + &Export PDF... + Exporter en P&DF... + + + + &Quit + &Quitter + + + + &Edit + &Editer + + + + &Undo + Ann&uler + + + + &Redo + &Refaire + + + + Cu&t + Couper + + + + &Copy + &Copier + + + + &Paste + Coller + + + + &View + &Affichage + + + + &Insert + &Insérer + + + + &Image + Image + + + + F&ormat + Format + + + + &Bold + Gras + + + + &Italic + Italique + + + + &Underline + Souligné + + + + + &Left + Alligner le texte à Gauche + + + + + C&enter + Centrer le texte + + + + + &Right + Aligner le texte à Droite + + + + &Justify + Justifier le texte + + + + &Text Color... + Couleur du texte... + + + + Application + Application + + + + The document has been modified. +Do you want to save your changes? + Le document a été modifié. Voulez-vous sauvegarder les changements? + + + + Open File... + Ouvrir un fichier... + + + + HTML-Files (*.htm *.html);;All Files (*) + Fichiers HTML (*.htm *.html);;tous les fichiers (*) + + + + Save as... + Enregistrer sous... + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + Fichiers ODF (*.odt);;Fichiers HTML (*.htm *.html);;Tous les fichiers (*) + + + + Print Document + Imprimer le document + + + + Export PDF + Exporter en PDF + + + + Choose Image + Insérer une image + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Type de fichiers supportés (*.png *.jpeg *.jpg *.gif) + + + + CreateChannel + + + Create a new Channel + Créer un nouveau canal + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + <span style="font-size:24pt; font-weight:500;color:#32CD32;">Nouveau canal</span> + + + + Name + Nom + + + + check peers you would like to share private publish key with + "Visualiser les personnes avec qui vous partagez votre clé de publication privée + + + + Share Key With + Clé partagée avec + + + + Contacts: + Contacts: + + + + Description + Description + + + + Type: + Type : + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Limité - N'importe qui peut lire, mais la publication est limitée (la clé de publication est privée) + + + + Private - (Private Publish Key required to view Messages) + Privé - (La clé de publication privée est exigée pour voir les messages) + + + + Allowed Messages + Messages autorisés + + + + Anonymous Messages + Messages anonymes + + + + Authenticated Messages + Messages authentifiés + + + Authemticated Messages + Messages authentifiés + + + + Key Sharing + Partage de la clé + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + Ceux avec qui je partage ma clé peuvent publier sur les cannaux à accès limité , peuvent voir et publier sur les canaux à accès privé + + + + Share Private Publish Key + Partager la clé de publication privée + + + + Channel Logo + Logo du canal + + + + Add Channel Logo + Ajouter un logo au canal + + + + Cancel + Annuler + + + + Create + Créer + + + + RetroShare + RetroShare + + + + Please add a Name + Veuillez ajouter un nom + + + + Load File + Ajouter un fichier + + + + Pictures (*.png *.xpm *.jpg) + Images (*.png *.xpm *.jpg) + + + + CreateChannelMsg + + + New Channel Post + Poster un nouveau message + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">Poster un nouveau message</span></p></body></html> + + + + Channel Post + Message + + + + Channel Post to: + Posté sur la Chaîne : + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Vous pouvez incorporer une miniature à votre message</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Vous pouvez utiliser le "glisser/déposer" pour joindre des fichiers</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Renseignez l'intitulé de votre objet ainsi qu'une description</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Vous pouvez vérifier les fichiers joints dans l'onglet "fichiers joints".</span></p></body></html> + + + + Add File to Attach + Joindre un fichier + + + + Add Channel Thumbnail + Incorporer une miniature + + + + Message + Message + + + + Subject : + Objet : + + + + + Attachments + Fichiers joints + + + + allow channels to get frame for message thumbnail from movie media attachments or not + permet ou non d'extraire une miniature à partir du fichier joint + + + + Auto Thumbnail + Miniature automatique + + + + Drag and Drop Files from Search Results + Glisser/déposer les fichiers à partir des résultats de recherche + + + + + Drop file error. + Erreur lors de l'ajout du fichier. + + + + Directory can't be dropped, only files are accepted. + On ne peut pas déposer un répertoire, seuls les fichiers sont acceptés. + + + + File not found or file name not accepted. + Le fichier n'a pas été trouvé ou le nom du fichier n'est pas accepté. + + + + Add Extra File + Ajouter un fichier supplémentaire + + + + + RetroShare + RetroShare + + + + File already Added and Hashed + Fichier déjà ajouté + + + + Please add a Subject + Veuillez ajouter un objet à votre message + + + + Load File + Joindre un fichier + + + + Pictures (*.png *.xpm *.jpg) + Images (*.png *.xpm *.jpg) + + + + CreateForum + + + Name + Nom + + + + Type: + Type : + + + + Authenticated Messages + Messages authentifiés + + + + Cancel + Annuler + + + RetroShare + RetroShare + + + + Please add a Name + Veuillez ajouter un nom + + + Create a Forum + Créer un forum + + + + Create new Forum + Créer un nouveau Forum + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Créer un nouveau Forum</span></p></body></html> + + + + Description + Description + + + + Public - Anyone can read and publish (Shared Publish Key) + Public - Tout le monde peut lire et publier (la clé de pubication est partagée) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Restreint - Tout le monde peut lire, mais la publication est limitée (la clé de publication est privée) + + + + Private - (Private Publish Key required to view Messages) + Privé - La clé de publication privée est exigée pour voir les messages + + + + Allowed Messages + Messages autorisés + + + Authemticated Messages + Messages authentifiés + + + + Anonymous Messages + Messages anonymes + + + Channel Logo + Logo du canal + + + Add Channel Logo + Ajouter un logo au canal + + + + Create + Créer + + + + CreateForumMsg + + + Close + Fermer + + + + Post Forum Message + Poster un message sur le Forum + + + + Forum + Forum + + + Forum Post Subject + Sujet du message du forum + + + + Attach File + Joindre un fichier + + + Paste retroshare link + Coller le lien Retroshare + + + + Forum Post + Message + + + + Sign Message + Signer le message + + + + Subject + Objet + + + + + Paste RetroShare Link + Coller le lien RetroShare + + + + Attach files via drag and drop + Joindre un fichier par glisser/déposer + + + + You can attach files via drag and drop here in this window + Vous pouvez joindre des fichiers par glisser/déposer + + + toolBar + Barre d'outils + + + + Post Forum Msg + Poster + + + Paste retroshare Link + Coller le lien RetroShare + + + Paste retroshare Link Full + Coller le lien Retroshare complet + + + + Paste full RetroShare Link + Coller le lien Retroshare entier + + + + In Reply to + En réponse à + + + + RetroShare + RetroShare + + + + Please set a Forum Subject and Forum Message + Veuillez renseigner l'objet ainsi que le message du Forum + + + + Add Extra File + Ajouter un fichier supplémentaire + + + + + Drop file error. + Erreur lors de l'ajout du fichier. + + + + File not found or file name not accepted. + Le fichier n'a pas été trouvé ou le nom du fichiern'est pas accepté. + + + + Directory can't be dropped, only files are accepted. + On ne peut pas déposer un répertoire, seuls les fichiers sont acceptés. + + + + CreateGroup + + + Create a Group + Créer un Groupe + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Créer un Groupe</span></p></body></html> + + + + Group Name + Nom du Groupe + + + + Enter a name for your group + Entrer un nom pour le Groupe que vous souhaitez créer + + + + Edit Group + Modifier le Groupe + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Modifier le Groupe</span></p></body></html> + + + + CryptoPage + + + RetroShare + RetroShare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + Votre clé publique est copiée dans le press-papiers, collez et envoyez-la à vos amis par courrier électronique ou par tout autre moyen + + + + Save as... + Enregistrer sous... + + + + RetroShare Certificate (*.rsc );;All Files (*) + Certificats RetroShare (*.rsc );;Tous les fichiers (*) + + + Certificate file successfully created + Fichier certificat créé avec succès + + + Sorry, certificate file creation failed + Désolé, la création du fichier certificat a échoué + + + + Public Key + Clé publique + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copier ma clé dans le presse-papiers</p></body></html> + + + + Copy Key + Copier la clé + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enregistrer la clé dans un fichier .rsc</p></body></html> + + + + Save Key + Enregistrer la clé + + + + DHTStatus + + + DHT + DHT + + + + DHT On + DHT On + + + + RetroShare users in DHT (Total DHT users) + Utilisateurs Retroshare trouvés sur les DHT (Utilisateurs totaux de la DHT) + + + + DHT Off + DHT Off + + + + DLListDelegate + + + B + o + + + + KB + Ko + + + + MB + Mo + + + + GB + Go + + + + DetailsDialog + + + Details + Détails + + + + + General + Général + + + + File Name: + Nom du fichier : + + + Name Label + Etiquette du nom + + + + Hash: + Hash : + + + Hash Label + Etiquette du Hash + + + + Size: + Taille : + + + Size Label + Etiquette de la taille + + + + Status: + Statut : + + + Status Label + Etiquette du statut + + + Priority + Priorité + + + Priority Label + Etiquette de la priorité + + + Type Label + Etiquette du type + + + + Type: + Type : + + + + Transfer + Transfert + + + + Sources: + Sources : + + + + Datarate: + Débit des données : + + + + Completed: + Terminés : + + + Source Label + Etiquette de la source + + + Datarate Label + Etiquette du débit de données + + + Completed Label + Etiquette terminée + + + Chunks Label + Etiquette morceaux + + + + Chunk size: + Taille des morceaux : + + + + + Number of Chunks + Nombre de paquets + + + Chunks Number Label + Etiquette nombre de morceaux + + + + Chunks: + Paquets : + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Remaining Label</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Etiquette restante</span></p></body></html> + + + + Priority: + Priorité : + + + + Remaining: + Restant : + + + + Date + Date + + + + Download time: + Durée du téléchargement : + + + + + Comments + Commentaires + + + + + retroshare link(s) + Lien(s) RetroShare + + + + Copy + Copier + + + + OK + OK + + + + Cancel + Annuler + + + + Rating + Evaluation + + + + File Name + Nom du fichier + + + + Not Rated + Non évalué + + + + No Comments + Pas de commentaires + + + + DirectoriesPage + + + Partials Directory + Dossier des fichiers incomplets + + + + Shared Directories + Dossiers partagés + + + + Automatically share incoming directory (Recommended) + Partager le dossier de réception (Recommandé) + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + Sauvegarde le hachage des fichiers, même s'il n'est pas partagé. +Cela peut être intéressant si vous partagez des fichiers +situés sur un disque dur externe afin d'éviter un nouvel +hachage des fichiers qui utilise les ressources du système. + + + + Remember hashed files for + Sauvegarder le hachage pendant + + + + days + jours + + + + Forget any hashed file that is not anymore shared. + Effacer le hachage des fichiers qui ne sont plus partagés. + + + + Clean Hash Cache + Effacer le cache de la table de hachage + + + + Auto-check shared directories every + Vérifier automatiquement les répertoires partagés toutes les + + + + minute(s) + minute(s) + + + Incoming files + Fichiers entrants + + + Add Shared Directory + Partager un répertoire + + + All Files (*) + Tous les fichiers (*) + + + Add a Share Directory + Partager un répertoire + + + Remove Shared Directory + Supprimer un répertoire partagé + + + + + Browse + Parcourir + + + + Set Incoming Directory + Fichiers terminés + + + + Set Partials Directory + Fichiers temporaires + Spécifier le dossier temporaire + + + + Incoming Directory + Dossier des fichiers terminés + + + Partials Direcrtory + Répertoire temporaires + + + Automatically share incoming directory (Recommanded) + Partager automatiquement le dossier de réception (Recommandé) + + + + Edit Share + Ajouter dossier dossier + + + + DiscStatus + + + Waiting outgoing discovery operations + En attente des opérations de découvertes sortantes + + + + Waiting incoming discovery operations + En attente des opérations de découvertes entrantes + + + + DownloadToaster + + + Start file + Ouvrir le fichier + + + + <b>Download completed</b> + <b>Téléchargement terminé</b> + + + + Close + Fermer + + + File %1 does not exist at location. + Le fichier %1 n'existe pas à cet endroit. + + + + EditChanDetails + + + Channel Details + Détails de la Chaîne + + + + Cancel + Annuler + + + + OK + OK + + + + Edit Channel Details + Modifier les détails de la Chaîne + + + + Channel Info + Détails de la Chaîne + + + + Channel Name + Nom de la Chaîne + + + + Channel Description + Description de la Chaîne + + + + Add Channel Logo + Ajouter un logo à la Chaîne + + + + Load File + Charger un fichier + + + + Pictures (*.png *.xpm *.jpg) + Images (*.png *.xpm *.jpg) + + + + EditForumDetails + + + Forum Details + Détails du Forum + + + + Cancel + Annuler + + + + OK + OK + + + + Edit Forum Details + Editer les détails du Forum + + + + Forum Info + Informations sur le Forum + + + + Forum Name + Nom du Forum + + + + Forum Description + Description du Forum + + + + EmailPage + + Invite Friend by Email + Invite un ami par e-mail + + + + Invite Friends by Email + Inviter un ami à rejoindre RetroShare par e-mail + + + + Enter your friends' email addresses (seperate each on with a semicolon) + Entrez les adresses e-mail de vos amis (séparées par un point-virgule) + + + + Your friends' email addresses: + Destinataire(s) : + + + + Enter Friends Email addresses + Entrez les adresses e-mail de vos amis + + + + Subject: + Objet : + + + + Friend invites you to check out RetroShare + Un ami vous invite à découvrir Retroshare (plateforme décentralisée de communictation et de partage de fichier) + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + Votre ami utilise RetroShare pour communiquer de manière sécurisée, et vous invite à le rejoindre pour partager des fichiers avec vous. <br>RetroShare est gratuit et son utilisation est sûre: il ne contient aucun virus, aucun spyware, aucun logiciel de publicité et peut être facilement désinstallé. <br>Pour plus d'informations, consultez notre site web : http://retroshare.sourceforge.net/downloads.html <br>A bientôt sur RetroShare ! + + + + ErrorMessagePage + + + Sorry, some error appeared + Désolé, des erreurs sont survenues + + + + Here is the error message: + Voici le message d'erreur : + + + + ExampleDialog + + + Vote Up + Voter + + + + + Vote Down + Voter - + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Amis</span></p></body></html> + + + + # + # + + + + Status + Statut + + + + Person + Personne + + + + Auto Connect + Connexion automatique + + + + Trust Level + Niveau de confiance + + + + Last Contact + Dernière fois vu + + + + Organisation + Organisation + + + + Location + Emplacement + + + + Country + Pays + + + + Person Id + ID du contact + + + + Auth Code + Code d'authentification + + + + Peer Address + Adresse du contact + + + + ExprParamElement + + + + + to + à + + + + ignore case + Ignorer la casse + + + + + dd.MM.yyyy + jj.MM.aaaa + + + + + KB + Ko + + + + + MB + Mo + + + + + GB + Go + + + + ExpressionWidget + + + Expression Widget + Zone d'expression + + + + Delete this expression + Supprimer cette expression + + + + FileAssociationsPage + + + &New + &Nouveau + + + + Add new Association + Ajouter une nouvelle association + + + + &Edit + &Editer + + + + Edit this Association + Editer cette association + + + + &Remove + Supp&rimer + + + + Remove this Association + Supprimer cette association + + + + File type + Type de fichier + + + + Friend Help + Aide + + + + You this + Moi + + + + FileTransferInfoWidget + + Chunk map: + Répartition des paquets : + + + Active chunks: + Paquets en cours de chargement : + + + Availability map ( + Disponibilité ( + + + sources + sources + + + active sources + sources actives + + + File info: + Informations sur le fichier : + + + File hash: + Hachage : + + + File size: + Taille du fichier : + + + + Chunk map + Répartition des paquets + + + + Active chunks + Paquets en cours de chargement + + + + Availability map (%1 active source) + Disponibilité des paquets(%1 de la source active) + + + + Availability map (%1 active sources) + Disponibilité des paquets (à partir de %1 sources actives) + + + + File info + Informations sur le fichier + + + + File hash + Hachage + + + + + + + bytes + octets + + + + File size + Taille du fichier + + + + Chunk size + Taille des paquets + + + + Number of chunks + Nombre de paquets + + + + Transfered + Transféré + + + + Remaining + Restant + + + + Number of sources + Nombre de sources + + + + Chunk strategy + Méthode de téléchargement + + + + Transfer type + Type de transfert + + + + Anonymous F2F + F2F Anonyme + + + + Direct friend transfer / Availability assumed + Transfert direct / Disponibilité supposée + + + Chunk size: + Taille des paquets : + + + Number of chunks: + Nombre de paquets : + + + Transfered: + Transféré : + + + Remaining: + Restant : + + + Number of sources: + Nombre de sources : + + + Chunk strategy: + Méthode de chargement : + + + Transfer type: + Type de transfert : + + + + FlatStyle_RDM + + + Friends Directories + Dossiers partagés de mes amis + + + + My Directories + Mes partages + + + + Size + Taille + + + + Age + Ancienneté + + + + Friend + Ami + + + + Share Type + Méthode de partage + + + + Directory + Répertoire + + + + FofPage + + + Friends of friends + Amis de mes amis + + + + Select now who you want to make friends with. + Veuillez selectionner avec qui vous souhaitez devenir ami. + + + + Show me: + Afficher : + + + + Any peer I've not signed + Toutes les personnes dont je n'ai pas signé leur certificat + + + + Friends of my friends who already trust me + Amis de mes amis qui m'ont déjà accordé leur confiance + + + + Signed peers showing as denied + Contacts signées montrés comme refusés + + + + Peer name + Nom du contact + + + + Also signed by + Également signé par + + + + Peer id + ID du contact + + + + Make friend with these peers + Devenir ami avec ces contacts + + + + *** None *** + *** Aucune *** + + + + ForumDetails + + + + Forum Details + Détails du Forum + + + + Forum Info + Informations sur le Forum + + + + Forum Name + Nom du Forum + + + + Popularity + Popularité + + + + Last Post + Dernier message + + + + Forum ID + ID du forum + + + + Forum Description + Description du Forum + + + + Security + Sécurité + + + + Allowed Messages + Messages autorisés + + + + Authemticated Messages + Messages signés + + + + Anonymous Messages + Messages anonymes + + + + Cancel + Annuler + + + + OK + OK + + + + Apply and Close + Appliquer et Fermer + + + + ForumMsgItem + + Form + Formulaire + + + + Remove Item + Supprimer + + + Forum Name + Nom du Forum + + + + Expand + Développer + + + + + + Subject: + Objet : + + + + Send + Envoyer + + + + Signed + Signé + + + Subject... + Sujet... + + + Persons Name + Noms des personnes + + + + Unsubscribe To Forum + Se désabonner du Forum + + + + Reply + Répondre + + + Message is about ??? + Le message est de ? ? ? + + + Previous Message... + Message pécédent... + + + Currnent Message.. + Message actuel.. + + + + Forum Post + Message du Forum + + + + Unknown Forum Post + Message inconnu + + + + + + Anonymous + Anonyme + + + + In Reply to + En réponse à + + + + Please give a Text Message + Veuillez tapper votre texte + + + + ForumNewItem + + + Form + Formulaire + + + + Remove Item + Effacer l'article + + + Connected + Connecté + + + name + nom + + + + Subscribe to Forum + S'abonner au Forum + + + + Expand + Développer + + + + Forum Description + Description du Forum + + + Description + of Forum + Description du forum + + + + ForumPage + + + Misc + Divers + + + + Set message to read on activate + Signaler les messages non lus + + + + Expand new messages + Développer les Forums contenant des nouveaux messages + + + + ForumsDialog + + + Subscribe to Forum + S'abonner au Forum + + + + Unsubscribe to Forum + Se désabonner du Forum + + + + New Forum + Nouveau Forum + + + + Show Forum Details + Voir les détails Forum + + + + Edit Forum Details + Editer les détails du Forum + + + + Restore Publish Rights for Forum + Restaurer les droits de publication du Forum + + + + + Copy RetroShare Link + Copier le lien RetroShare + + + + Mark all as read + Tout marquer comme lu + + + + Mark all as unread + Tout marquer comme non lu + + + + Reply + Répondre + + + + Reply to Author + Répondre à l'auteur + + + + Expand all + Tout déplier + + + + Collapse all + Tout replier + + + + AUTHD + Authentificaiton + + + Popularity: + Popularité : + + + + Your Forums + Vos Forums + + + + Subscribed Forums + Forums abonnés + + + + Popular Forums + Forums populaires + + + + Other Forums + Autres Forums + + + + + Mark as read + Marquer comme lu + + + + + Mark as unread + Marquer comme non lu + + + + + with children + et toute la sous-arborescence + + + + Hide + Cacher + + + + Expand + Déplier + + + Popularity: + Popularité: + + + Anonymous + Anonyme + + + signed + Signé + + + none + Aucun + + + + + RetroShare + RetroShare + + + + No Forum Selected! + Aucun forum selectionné ! + + + Re: + Re: + + + + You cant reply a Anonymous Author + Vous ne pouvez pas répondre à un auteur anonyme + + + File Request Confirmation + Confirmation de demande de fichier + + + The file has been added to your download list. + Ce fichier a été ajouté à votre liste de téléchargements. + + + File Request canceled + Demande de fichier annulée + + + The file has not been added to your download list, because you already have it. + Ce fichier n'a pas été ajouté à votre liste de téléchargement car vous le possédez déjà. + + + File Request Error + Erreur de demande de fichiers + + + The file link is malformed. + Le lien du fichier est mauvais. + + + + + Date + Date + + + + + Title + Titre + + + + + Start New Thread + Nouveau sujet + + + New Message + Nouveau message + + + Forum Name + Nom du Forum + + + Popularity + Popularité + + + Posts + Publier + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + Add + Ajouter + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start new Thread for Selected Forum</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Démarrer un nouveau sujer dans le Forum selectionné</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reply Message</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Répondre au message</p></body></html> + + + + Start new Thread for Selected Forum + Créer un nouveau sujet dans les Forum sélectionné + + + RetroShare Forums + Forums RetroShare + + + + Display + Affichage + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum :</p></body></html> + + + + Last Post + Dernier message + + + + Threaded View + Affichage en arborescence + + + + Flat View + Affichage sans arborescence + + + + + Author + Auteur + + + + Signed + Signé + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Fil :</span></p></body></html> + + + + Previous Thread + Fil précédent + + + + Next Thread + Fil suivant + + + + Download all files + Télécharger tous les fichiers + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Chercher un Forum</span></p></body></html> + + + + Reset + Réinitialiser + + + + Content + Contenu + + + + Reply Message + Répondre au message + + + + Create Forum + Créer un Forum + + + Prev + Précédent + + + Next + Suivant + + + + Print + Imprimer + + + + PrintPreview + Aperçu avant impression + + + + ForumsFillThread + + + + Anonymous + Anonyme + + + + + signed + Signé + + + + + none + Aucun + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Amis</span></p></body></html> + + + + Add + Ajouter + + + + Display + Affichage + + + + Friends + Amis + + + + Status + Statut + + + + Add or Change your Avatar + Ajouter ou modifier votre image perso + + + + Edit Personal message + Editer mon message perso + + + + Group Chat + Chat public + + + + Messages entered here are sent to all collected friends + Les Messages inscrits ici sont envoyés à tous les amis sélectionnés + + + + Bold + Gras + + + + Underline + Souligner + + + + Italic + Italique + + + + Font + Police + + + + Text Color + Couleur du texte + + + + Attach File + Joindre un fichier + + + + Send + Envoyer + + + + Clear Chat History + Effacer l'historique du chat + + + + + Add Friend + Ajouter un ami + + + + Create new Profile + Créer un nouveau profil + + + + + Create new Forum + Créer un nouveau Forum + + + + F + F + + + + + Create new Channel + Créer une nouvelle Chaîne + + + + C + C + + + + Add your Avatar Picture + Ajouter votre image perso + + + + A + A + + + + Set your Personal Message + Définir votre message perso + + + + Edit your status Message + Editer votre message perso + + + + Browse Message History + Parcourir l'historique des messages + + + + Browse History + Parcourir l'historique + + + + + Save Chat History + Sauvegarder l'historique du Chat + + + + Hide Offline Friends + Cacher mes amis hors-ligne + + + + Hide Status Column + Cacher la colonne des statuts + + + + + Sort by State + Trier par statut + + + + Hide State + Cacher le statut + + + + + Add a new Group + Ajouter un nouveau groupe + + + + + Sort Descending Order + Trier par ordre décroissant + + + + + Sort Ascending Order + Trier par ordre croissant + + + + Delete Chat History + Supprimer l'historique du Chat + + + + Deletes all stored and displayed chat history + Supprimer tous les historiques de Chat affichés et enregistrés + + + + Profile + Profil + + + + News Feed + Fil d'actualité + + + + Welcome to RetroShare's group chat. + Bienvenue dans le chat public de RetroShare. + + + + me + Moi + + + + Paste RetroShare Link + Coller le lien RetroShare + + + + Group + Groupe + + + + Friend + Ami + + + + Location + Emplacement + + + + Message Group + Message à ce groupe + + + + Edit Group + Editer le groupe + + + + Remove Group + Supprimer le groupe + + + + Chat + Chat + + + + Message Friend + Envoyer un Message + + + + Friend Details + Détails de cet ami + + + + Recommend this Friend to... + Recommander cet ami à... + + + + Connect To Friend + Se connecter à cet ami + + + + Copy RetroShare Link + Copier le lien RetroShare + + + + + Paste Friend Link + Coller le lien d'ajout d'ami + + + + Deny Friend + Ignorer cet ami + + + + Remove Friend Location + Supprimer l'emplacement de cet ami + + + + Add to group + Ajouter à un groupe + + + + Move to group + Déplacer dans le groupe + + + + Groups + Groupes + + + + Remove from group + Supprimer du groupe + + + + Remove from all groups + Supprimer de tous les groupes + + + + Expand all + Tout développer + + + + Collapse all + Tout réduire + + + + location + Emplacement + + + + + Available + Disponible + + + + Save Certificate + Enregistrer le certificat + + + + Certificates (*.pqi) + Certificats (*.pqi) + + + + Do you want to remove this Friend? + Désirez-vous supprimer cet ami ? + + + + is typing... + est en train d'écrire... + + + + + New group chat + Nouveau Message à ce groupe + + + + Do you really want to physically delete the history? + Etes-vous vraiment sûr de vouloir supprimer définitivement l'historique ? + + + + Load File + Charger un fichier + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Images (*.png *.xpm *.jpg *.tiff *.gif) + + + + Add Extra File + Ajouter un fichier supplémentaire + + + + + Drop file error. + Erreur lors de l'ajout du fichier. + + + + Directory can't be dropped, only files are accepted. + On ne peut pas déposer un répertoire, seuls les fichiers sont acceptés. + + + + File not found or file name not accepted. + Le fichier n'a pas été trouvé ou le nom du fichier n'est pas accepté. + + + + Save as... + Enregistrer sous... + + + + Text File (*.txt );;All Files (*) + + + + + GamesDialog + + + Cancel Game + Abandonner le Jeu + + + + Add to Invite List + Ajouter à la liste des invités + + + + Remove from Invite List + Effacer de la liste des invités + + + + + Interested in Playing + Intéressé pour jouer + + + + Not Interested in Game + Non intéressé par le Jeu + + + + + Not Interested + Non intéressé + + + + Confirm Peer in Game + Confirmer la personne dans le Jeu + + + + Remove Peer from Game + Supprimer la personne de la partie + + + + Interested in Game + Intéressé par le Jeu + + + + Quit Game + Quitter le Jeu + + + + Server + Connexion + + + + Status + Statut + + + + Accept + Accepter + + + + Form + Formulaire + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Lanceur de Jeux</span></p></body></html> + + + + Game: + Jeu : + + + + GameType: 0. Want to Add your Game here? + Type de jeu : 0. Voulez-vous ajouter votre jeu ? + + + + GameType: 1. Get In Touch with the developers + Type de jeu : 1. Contactez les réalisateurs + + + + GameType: 2. + Type de jeu : 2. + + + + Title / Comment + Titre / Commentaire + + + + Create New Game + Créer un nouveau Jeu + + + + Invite All Friends + Inviter tous les Amis + + + + Game Type + Type de Jeu + + + + Comment + Commantaire + + + + GameID + ID du Jeu + + + + Player + Joueur + + + + + Invite + Inviter + + + + Interested + Intéressé + + + + Delete + Effacer + + + + + Move Player + Déplacer le joueur + + + + Play Game + Jouer au Jeu + + + + GenCertDialog + + RetroShare setup + Installation de RetroShare + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Generate a new profile</span><br /><br />Please fill in the information which will<br />allow your RetroShare to connect to</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Friends.</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Créez un nouveau profil</span><br /><br />Remplissez svp les informations qui<br />permettront à RetroShare de se connecter aux</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">amis.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Organisation:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Organisation:</p></body></html> + + + Password (Again) + Mot de passe (encore) + + + It looks like you don't own any GPG keys. Please fill in the form below to generate one, or use your favorite gnupg key manager. + Il semblerai que vous ne possédiez pas de clé GPG. Veuillez remplir ce formulaire pour en générer un, ou utilisez votre gestionnaire de clé GNUPG préféré. + + + Use GPG key + Utiliser une clé GPG + + + + + + Create new Profile + Créer un nouveau profil + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + Il semblerait que vous ne possédiez pas de clé PGP. Veuillez remplir ce formulaire pour en générer une, ou utilisez votre gestionnaire de clé GNUPG préféré. + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier';">Your profile is associated to a GPG key</span></pre></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<pre style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier';">Votre profil est associé à une clé PGP</span></pre></body></html> + + + + Generate a new Profile + Générer un nouveau profil + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier'; font-size:8pt;">Your profile is associated to a GPG key</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier'; font-size:8pt;">Votre profile est associé à une clé PGP</span></p></body></html> + + + + + Your profile is associated to a GPG key + Votre profil est associé à votre clé PGP + + + + Use Profile + Utiliser un profile existant + + + + Name + Pseudo + + + + Enter here your nickname + Entrez votre pseudo + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + Attention: votre courrier électronique sera visible par vos amis ainsi que les amis +de vos amis. Cette information est requise pour la génération de votre clé PGP, +mais pour rester anonyme, vous pouvez utiliser un faux courrier électronique. + + + + This Password is for GPG + Mot de passe PGP + + + + Put a strong password here. This password protects your GPG key. + Entrez un mot de passe robuste, il protègera votre clé PGP. + + + + Location + Emplacement + + + Location: + Emplacement : + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + Indiquez un emplacement à cette installation de RetroShare qui permettra de différencier parmis vos autres installations. Ex: PC Portable, PC de Bureau, PC de Travail. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Générer un nouveau profil</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare utilise le système de clés PGP pour l'identification. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Utilisez un profil existant (clé PGP) ou créez-en un nouveau avec ce formulaire.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Vous pouvez installer RestroShare sur différents ordinateurs en utilisant le même profil (clé GPG).</span></p></body></html> + + + + Email + Courrier électronique + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new RetroShare profile</span><span style=" font-family:'Arial'; font-size:8pt;"><br /><br /></span><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Retroshare uses gpg keys for identity management. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing gpg key, or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Please fill in the location field (example : "home", "laptop", etc). </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">It will be permanently attached to this retroshare installation, and visible to</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">your peers.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same gpg key.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Créer un nouveau profil RetroShare</span><span style=" font-family:'Arial'; font-size:8pt;"><br /><br /></span><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare utilise les clés GPG comme gestionnaire d'identité. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Vous pouvez utiliser un clé GPG existante, ou en créer une nouvelle à l'aide de ce formulaire.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Veuillez renseigner le champ "Lieu" (ex. "Maison", "Travail", etc.)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Ce lieu sera attaché de manière permanante à cette installation RetroShare, et visible par</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">vos contacts.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Vous pouvez installer RetroShare à plusieurs endroits différents en utilisant la même clé GPG</span></p></body></html> + + + GPG Password + Mot de passe GPG + + + + Generate New Profile + Générer un nouveau profil + + + Load Trusted Certificate (Optional) + Charger les certificats sûrs (facultatif) + + + RetroShare : Create new user Profile + RetroShare : Créer un nouveau profil utilisateur + + + Generate a new gpg key + Générer un nouvelle clé GPG + + + + Info + Aide + + + + Password + Mot de passe + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ami</span></p></body></html> + + + Select File + Choisir un fichier + + + Country: + Pays: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nom:</p></body></html> + + + Generate New Certificate + Créer un nouveau certificat + + + + + Create new Location + Créer un nouvel emplacement + + + + + Generate new Location + Générer un nouvel emplacement + + + + + Create a new Location + Créer un nouvel emplacement + + + + + Generate new Profile + Générer un nouveau profil + + + + + Create a new Profile + Créer un nouveau profil + + + + + Generate GPG key Failure + La création de la clé PGP a échoué + + + + Location field is required with a minimum of 3 characters + Le champ "Emplacement" est requis avec un minimum de 3 caractères + + + + All fields are required with a minimum of 3 characters + Tous les champs sont requis avec un minimum de 3 caractères + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + Création d'une clef PGP en cours, veuillez patienter: ce processus doit générer une grande quantité de nombres premiers et peut prendre quelques minutes sur les ordinateurs peu puissants. + +Introduisez votre mot de passe PGP lorsqu'il vous sera demandé afin de signer votre nouvelle clé. + + + + + Multiple instances + Multiples instances + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Une autre instance de RetroShare utilise actuellement le même profil sur votre système. Veuillez dans un premier temps fermer ce profil puis réessayez de l'ouvrir + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Une erreur inattendue s'est produite lorsque RetroShare a essayé d'acquérir le verrou d'instance unique + + + + Generate ID Failure + La création de l'ID a échoué + + + + Failed to Load your new Certificate! + Le chargement de votre nouveau certificat a échoué ! + + + Generating new GPG key, please be patient. Fill in your GPG password when asked. + Génération d'une nouvelle clé GPG, veuillez patienter. Confirmez votre mot de passe GPG quand il vous le sera demandé. + + + + Select Trusted Friend + Définir la confiance de vos amis + + + + Certificates (*.pqi *.pem) + Certificats (*.pqi *.pem) + + + Name: + Nom: + + + Organisation: + Organisation : + + + Friend + Ami + + + + GeneralPage + + Keys manager + Gestionnaire de clés + + + Style + Style + + + Choose RetroShare's interface style + Choisir le style de l'interface de RetroShare + + + Language + Langue + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Les changements de langue entreront en vigueur seulement après un redémarrage de RetroShare!</p></body></html> + + + Choose the language used in RetroShare + Choisir la langue utilisée dans Retroshare + + + Login + Login + + + + Startup + Démarrage + + + + Start minimized on system start + Minimiser RetroShare lorsque le système démarre + + + + Misc + Divers + + + + Do not show the Quit RetroShare MessageBox + Ne pas afficher le message d'avertissement à la fermeture de RetroShare + + + + Do not Minimize to Tray Icon + Ne pas réduire RetroShare dans la zone de notification + + + + Auto Login + Connexion automatique + + + + Register retroshare:// as url protocol (Restart required) + Enregistrer retroshare:// en tant que protocole (Redémarrage requis) + + + + Idle + Inactivité + + + + Idle Time + Inactif après + + + + seconds + secondes + + + seconds + secondes + + + Show MainWindow at Startup + Afficher la fenêtre principale au démarrage + + + + Start minimized + Démarrer RetroShare dans la zone de notification + + + + Start RetroShare when my system starts + Lancer RetroShare au démarrage du système + + + + GraphFrame + + + Recv: + Reçu : + + + + + + %1 KB/s + %1 Ko/s + + + + Sent: + Envoyé : + + + + %1 KB + %1 Ko + + + + %1 MB + %1 Mo + + + + %1 GB + %1 Go + + + + GraphWidget + + Elastic Nodes + Noeuds élastiques + + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + Cliquez et glissez les noeuds, zoomez avec la roulette de la souris ou les touches '+' et '-' + + + + GroupDefs + + + Friends + Amis + + + + Family + Famille + + + + Co-Workers + Collègues + + + + Other Contacts + Autres contacts + + + + Favorites + Favoris + + + + GroupTreeWidget + + + Enter a Keyword here + Entrez un mot clé + + + + Title + Titre + + + + Description + Description + + + + Reset + Effacer + + + + Sort by Name + Trier par nom + + + + Sort by Popularity + Trier par popularité + + + + Sort by Last Post + Trier par date + + + + Private Key Available + Clé privée disponible + + + + GuiExprElement + + + and + et + + + + and / or + et / ou + + + + or + ou + + + + Name + Nom + + + + Path + Chemin + + + + Extension + Extension + + + + Hash + Hash + + + + Date + Date + + + + Size + Taille + + + + Popularity + Popularité + + + + contains + contient un des mots suivants + + + + contains all + contient tous les mots + + + + is + expression exacte + + + + less than + inférieur + + + + less than or equal + inférieur ou égal + + + + equals + égaux + + + + greater than or equal + supérieur ou égal + + + + greater than + supérieur à + + + + is in range + dans l'intervalle + + + + HelpBrowser + + + + Error Loading Help Contents: + Erreur lors du chargement de l'aide : + + + + Supplied XML file is not a valid Contents document. + Le fichier XML fourni n'est pas un document valide. + + + + Search reached end of document + La recherche a atteint la fin du document + + + + Search reached start of document + La recherche a atteint le début du document + + + + Text not found in document + Le texte n'a pas été trouvé dans le document + + + + Found %1 results + %1 résultats trouvés + + + + + Search + Recherche + + + + Home + Accueil + + + + Close + Fermer + + + + + RetroShare Help + Aide RetroShare + + + + Find: + Trouver : + + + + Find Previous + Précédent + + + + Find Next + Suivant + + + + Case sensitive + Respecter la casse + + + + Whole words only + Mots entiers seulement + + + + Contents + Contenus + + + + Help Topics + Rubriques d'aide + + + + Searching for: + Chercher : + + + + Found Documents + Documents trouvés + + + + Back + Retour + + + + Move to previous page (Backspace) + Retourner à la page précédente (Retour arrière) + + + + Backspace + Retour arrière + + + + Forward + Suivant + + + + Move to next page (Shift+Backspace) + Avancer à la page suivante (Maj+Retour arrière) + + + + Shift+Backspace + Maj+Retour arrière + + + + Move to the Home page (Ctrl+H) + Aller à la page d'accueil (Ctrl+H) + + + + Ctrl+H + Ctrl+H + + + + + + Find + Trouver + + + + Search for a word or phrase on current page (Ctrl+F) + Chercher un mot ou une expression dans la page courante (Ctrl+F) + + + + Ctrl+F + Ctrl+F + + + + Close Vidalia Help + Fermer l'aide Vidalia + + + + Esc + Echap + + + + HelpDialog + + + About + À propos + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare est un logiciel de communication décentralisé et sécurisé, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;"> disponible sur Windows et Linux qui vous permet de communiquer en toute</span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">sécurité avec vos amis, collègues ou famille. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare utilise un système de réseau de confiance pour authentifier les contacts et utilise le protocole OpenSSL pour crypter toutes les communications.</span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare intègre plusieurs fonctionalités dont le partage de fichiers, un chat (privé ou public), une messagerie, un système de blogs et bien d'autres fonctionnalités. </span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;"></span>Liens utiles pour plus d'informations :</p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Site officiel de RetroShare</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Wiki RetroShare</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">Forums RetroShare</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Page du projet RetroShare</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Page d'accueil Lunamutt</span></a></li></ul></body></html> + + + + Authors + Auteurs + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + Thanks to + Remerciements + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Translation + Traduction + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Traducteurs de RetroShare :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Français : </span><span style=" font-size:8pt;">Temet, Romano64</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polonais : </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbe : </span><span style=" font-size:8pt;">Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Suédois : </span><span style=" font-size:8pt;">Dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Traducteurs du site web retroShare :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Suédois : </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Allemand : </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polonais : </span><span style=" font-size:8pt;"> Maciej Mrug</span></p></body></html> + + + + License Agreement + Accord de licence + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">A propos de RetroShare</span></p></body></html> + + + + HelpTextBrowser + + + Error opening help file: + Erreur lors de l'ouverture du fichier d'aide : + + + + Opening External Link + Ouverture d'un lien externe + + + + Unable to Open Link + Impossible d'ouvrir le lien + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + RetroShare peut ouvrir le lien que vous avez sélectionné dans votre navigateur web par défaut. Si votre navigateur n'est pas configuré pour utiliser Tor alors la demande ne sera pas anonyme. + + + + Do you want Retroshare to open the link in your Web browser? + Voulez-vous que Retroshare ouvre le lien dans votre navigateur web ? + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + RetroShare n'a pas été capable d'ouvrir le lien choisi dans votre navigateur web. Vous pouvez toujours copier l'URL et le coller directement dans la barre d'adresse de votre navigateur. + + + + ImHistoryBrowser + + + Message History + Historique des messages + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Historique des messages</span></p></body></html> + + + + Reset + Réinitialiser + + + + + Copy + Copier + + + + Remove + Supprimer + + + + Mark all + Tout marquer + + + + Delete + Effacer + + + + Clear history + Nettoyer l'historique + + + + Send + Envoyer + + + + InfoDialog + + + Info + Informations + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare utilise les clés PGP, elles sont requises lors de la création d'un profil RetroShare.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Vous devez échanger votre clé PGP avec vos amis, par courrier électronique ou tout autre moyen.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Si vous recevez une clé PGP d'un ami, utilisez l'assistant d'ajout d'ami intégré dans RetroShare.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. Sous Linux, vous devez installer GPA (GNU Privacy Assistant) :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">Ouvrez un terminal puis avec les droits root tappez : sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. Sous Windows vous devez installer gpg4win pour la création d'un clé PGP :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. Si vous utilisez GPA pour créer une clé PGP et que celle-ci ne fonctionne pas, utilisez plutôt WinPT pour la création de la clé :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + IntroPage + + This wizard will help you to connect to your friend(s) to RetroShare network. There are three possible ways to do this: + Cet assistant vous aidera à connecter votre (vos) ami(s) à votre réseau. Il y a trois moyens possibles: + + + This wizard will help you to connect to your friend(s) to RetroShare network. There are five possible ways to do this: + Cet assistant vous aidera à connecter votre (vos) ami(s) à votre réseau. Il existe trois possibilités: + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + Cet assistant vous aidera à vous connecter à vos amis à l'aide de RetroShare. Il y a pour cela deux possibilités : + + + + &You get a certificate file from your friend + Vous possédez le certificat de votre ami dans un &Fichier + + + + &Enter RetroShare ID manually + &Entrer l'ID RetroShare manuellement + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + Envoyez une invitation par e-mail à un ami +(Elle/il recevra un courrier électronique pour télécharger RetroShare) + + + &Use *.rsc files with certificates + &Utiliser un certificat RetroShare (*.rsc) + + + + &Make friend with selected friends of my friends + Devenir a&mi avec les amis de vos amis sélectionnés + + + + Add a new Friend + Ajouter un nouvel ami + + + This wizard will help you to connect your friend to RetroShare network. There are two possible ways to do this: + Cet assistant vous aidera à connecter votre ami au réseau RetroShare. Il y a pour cela deux possibilités : + + + + &Enter the certificate manually + &Entrez manuellement le certificat + + + &Use *.pqi files with certificates + &Utiliser les fichiers avec certificats *.pqi + + + + LinksDialog + + + Share Link Anonymously + Partager le lien anonymement + + + + Vote on Link + Voter pour le lien + + + + Download + Télécharger + + + + Expand + Développer + + + + Hide + Cacher + + + + File Request Confirmation + Demande de fichier confirmée + + + + The file has been added to your download list. + Le fichier a été ajouté à votre liste de téléchargement. + + + + File Request canceled + Demande de fichier annulée + + + + The file has not been added to your download list, because you already have it. + Le fichier n'a pas été ajouté à votre liste de téléchargement, car vous l'avez déjà. + + + + File Request Error + Erreur de demande de fichier + + + + The file link is malformed. + Le lien du fichier est corrompu. + + + + From + De + + + + Show + Montrer + + + + 101-200 + 101-200 + + + + 201-300 + 201-300 + + + + 301-400 + 301-400 + + + + 401-500 + 401-500 + + + Form + Formulaire + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Nuage de liens</span></p></body></html> + + + + Title / Comment + Titre / Commentaire + + + + Score + Points + + + + Peer / Link + Contact / Lien + + + + Sort by + Trier par + + + + Combo + Combinaison + + + + Time + Heure + + + + Ranking + Classement + + + + In last + En dernier + + + + Month + Mois + + + + Week + Semaine + + + + Day + Jour + + + + All Peers + Tout les contacts + + + + Own Links + Vos liens + + + + Top 100 + 100 meilleurs + + + + Bottom 100 + 100 plus mauvais + + + + Link: + Lien : + + + + Add Anonymous Link + Ajouter un lien anonyme + + + + Add Link/Comment + Ajouter un lien / commentaire + + + + Title: + Titre : + + + + Score: + Score : + + + + +2 Great! + +2 Excellent ! + + + + +1 Good + +1 Bien + + + + 0 Okay + 0 Moyen + + + + -1 Sux + +- Mauvais + + + + -2 Bad Link + -2 Très Mauvais + + + + Url: + URL : + + + + Add new link + Ajouter un nouveau lien + + + + MainWindow + + + Network + Réseau + + + + Friends + Amis + + + + + Transfers + Transferts + + + + + Messages + Messages + + + + + Channels + Chaînes + + + + Blogs + Blogs + + + + Low disk space warning + Alerte : Espace disque faible + + + + The disk space in your + L'espace disque dans votre + + + + directory is running low (current limit is + dossier diminue (l'espace restant est de + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + Mo). + +RetroShare va suspendre tout accès à ce dossier en toute sécurité . + +Veuillez libérer de l'espace disque et cliquer sur Ok. + + + + Status + Statut + + + + Chat + Chat + + + + + + + You have %1 new messages + Vous avez %1 nouveau(x) message(s) + + + + + + + %1 new messages + %1 nouveaux messages + + + + + + + %1 new message + %1 nouveau message + + + + You have %1 completed downloads + Vous avez %1 téléchargements terminés + + + + You have %1 completed download + Vous avez %1 téléchargement terminé + + + + %1 completed downloads + %1 téléchargements terminés + + + + %1 completed download + %1 téléchargement terminé + + + + Down: %1 (kB/s) + Réception : %1 (Ko/s) + + + + Up: %1 (kB/s) + Envoi : %1 (Ko/s) + + + + %1 friend connected + %1 ami connecté + + + + %1 friends connected + %1 amis connectés + + + + Internal Error + Erreur interne + + + + It seems to be an old RetroShare link. Please use copy instead. + Il s'agit d'un ancien lien RetroShare. Veuillez copier/coller le lien. + + + + The file link is malformed. + Le lien du fichier est corrompu. + + + Busy + Occupé(e) + + + Away + Absent(e) + + + + + Options + Options + + + + Hide + Cacher + + + + Show + Afficher + + + + RetroShare + RetroShare + + + Invite Friend + Inviter un ami + + + + MainWindow + Fenêtre principale + + + toolBar + Barre d'outils + + + + Add Friend + Ajouter un ami + + + + Add a Friend Wizard + Assistant "Ajouter un ami" + + + + Add Share + Ajouter un partage + + + + + Quick Start Wizard + Assistant de configuration rapide + + + + Search + Recherche + + + + Files + Fichiers + + + Add Shared Directory + Ajouter un dossier partagé + + + + Messenger + Messenger + + + + Show/Hide + Montrer/Cacher + + + + &Quit + &Quitter + + + + + + + You have %1 new message + Vous avez %1 nouveau message + + + + Bandwidth Graph + Traffic + + + + Open Messenger + Messenger + + + + Minimize + Réduire + + + + Maximize + Agrandir + + + + Links Cloud + Nuage de Liens + + + + RetroShare %1 a secure decentralised communication platform + RetroShare %1 - Logiciel de communication sécurisé et décentralisé + + + + Unfinished + Inachevé + + + + Help + Aide + + + + About + A propos + + + News Feed + Fil d'actualité + + + + + Forums + Forums + + + + Open Messages + Messagerie + + + + Applications + Applications + + + Settings + Paramètres + + + RetroShare %1 a secure decentralised commmunication platform + RetroShare %1 - Logiciel sécurisé et décentralisé + + + + Plugins + Plugins + + + + Really quit ? + Voulez-vous vraiment quitter ? + + + + Do you really want to exit RetroShare ? + Etes-vous sûr de vouloir quitter RetroShare ? + + + toolBar_2 + Barre d'outils_2 + + + + Quit + Quitter + + + Color + Couleur + + + + SMPlayer + SMPlayer + + + + MessageComposer + + + + Compose + Nouveau + + + + + Contacts + Contacts + + + + Search for Name: + Filtrer : + + + + Reset + Réinitialiser + + + + Send To: + Envoyer à : + + + + Subject: + Objet : + + + + Paragraph + Paragraphe + + + + Search Friends + Rechercher d'amis + + + + >> To + >> À... + + + + >> Cc + >> Cc... + + + + >> Bcc + >> Cci... + + + + >> Recommend + >> Recommander + + + + Heading 1 + Titre 1 + + + + + Heading 2 + Titre 2 + + + + Heading 3 + Titre 3 + + + + Heading 4 + Titre 4 + + + + Heading 5 + Titre 5 + + + + Heading 6 + Titre 6 + + + + Font size + Taille de police + + + + Increase font size + Agrandir la police + + + + Decrease font size + Réduire la police + + + + Bold + Gras + + + + Underline + Souligner + + + + Italic + Italique + + + + Select Color + Couleur de police + + + + Alignment + Alignement + + + + Add a Image + Insérer une image + + + + Sets text font to code style + Paramètrer la police de texte dans le code + + + + Tags: + Tags : + + + + + Tags + Tags + + + + Recommended Files + Fichiers recommandés + + + + File Name + Nom du fichier + + + + Size + Taille + + + Sources + Sources + + + + Hash + Hash + + + + Send + Envoyer + + + + Send this message now + Envoyer le message maintenant + + + + Reply + Répondre + + + + Toggle Contacts View + Afficher la liste des contacts + + + + Save + Enregistrer + + + + Save this message + Enregistrer le message + + + + Attach + Joindre + + + + Attach File + Joindre un fichier + + + + Quote + Citer + + + + Add Blockquote + Citer le texte + + + + &Left + Alligner le texte à Gauche + + + + C&enter + Centrer le texte + + + + &Right + Aligner le texte à Droite + + + + &Justify + Justifier le texte + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + Je vous recommande un de mes amis, vous pouvez lui faire confiance autant qu'à moi <br> Cliquez sur le lien suivant afin de le rajouter à votre liste d'amis. + + + + + Save Message + Enregistrer le message + + + + Message has not been Sent. +Do you want to save message to draft box? + Le message n'a pas été envoyé +Désirez-vous enregistrer le message dans les brouillons? + + + + Friend Recommendation(s) + Recommendation d'ami(s) + + + + + Paste RetroShare Link + Coller le lien RetroShare + + + No Title + Pas de titre + + + + Add to "To" + Ajouter à "A" + + + + Add to "CC" + Ajouter à "Cc" + + + + Add to "BCC" + Ajouter à "Cci" + + + + Add as Recommend + Ajouter comme fichier recommandé + + + + Friend Details + Détails de cet ami + + + + Re: + Re: + + + + Fwd: + Tr: + + + + + RetroShare + RetroShare + + + + Do you want to send the message without a subject ? + Souhaitez-vous envoyer ce message sans objet ? + + + + Please insert at least one recipient. + Veuillez inscrire au moins un destinataire. + + + + To + À... + + + + Cc + Cc... + + + + Bcc + Cci... + + + + Unknown + Inconnu + + + + Unknown friend + Ami inconnu + + + + &File + &Fichier + + + + &New + &Nouveau + + + + &Open... + &Ouvrir... + + + + &Save + Enregi&strer + + + + Save &As File + Enregistrer sous... + + + + Save &As Draft + Enregistrer comme brouillon + + + + &Print... + Im&primer + + + + &Export PDF... + Exporter en P&DF + + + + &Quit + &Quitter + + + + &Edit + &Editer + + + + &Undo + Ann&uler + + + + &Redo + &Rétablir + + + + Cu&t + Couper + + + + &Copy + &Copier + + + + &Paste + Coller + + + + &View + &Affichage + + + + &Contacts Sidebar + Barre latérale des &Contacts + + + + &Insert + &Insérer + + + + &Image + &Image + + + + &Horizontal Line + Ligne &horizontale + + + + &Format + &Format + + + + Open File... + Ouvrir un fichier... + + + + + HTML-Files (*.htm *.html);;All Files (*) + Fichiers HTML (*.htm *.html);;tous les fichiers (*) + + + + Save as... + Enregistrer sous... + + + + Print Document + Imprimer le message + + + + Export PDF + Exporter en PDF + + + + Message has not been Sent. +Do you want to save message ? + Le message n'a pas été envoyé. +Voulez-vous enregistrer votre message ? + + + + Choose Image + Insérer une image + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Type de fichiers supportés (*.png *.jpeg *.jpg *.gif) + + + + Add Extra File + Ajouter un fichier supplémentaire + + + + + Drop file error. + Erreur lors de l'ajout du fichier. + + + + Directory can't be dropped, only files are accepted. + On ne peut pas déposer un répertoire, seuls les fichiers sont acceptés. + + + + File not found or file name not accepted. + Le fichier n'a pas été trouvé ou le nom du fichiern'est pas accepté. + + + + MessagePage + + Misc + Divers + + + + Reading + Lecture + + + + Set message to read on activate + Signaler les messages non lus + + + + Open messages in + Ouvrir le Message dans + + + + Tags + Tags + + + + Tags can be used to categorize and prioritize your messages + Les tags sont utilisés pour classer et donner des priorités à vos messages + + + + Add + Ajouter + + + + Edit + Modifier + + + + Delete + Supprimer + + + + Default + Par défaut + + + + A new tab + Un nouvel onglet + + + + A new window + Une nouvelle fenêtre + + + + Edit Tag + Modifier le tag + + + + MessageToaster + + message + message + + + New Message + Nouveau message + + + + Subject + Objet + + + Play video + Lire la vidéo + + + Play button + Bouton de lecture + + + Play the downloaded video + Lire la vidéo téléchargée + + + + <b>1 new Message from</b> + <b>1 Nouveau Message de</b> + + + + Close + Fermer + + + Close button + Bouton Fermer + + + Close the information dialog + Fermer l'avertissement + + + + Sub: + Sous : + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Fichiers recommandés</span></p></body></html> + + + + Download all Recommended Files + Télécharger tous les fichiers recommandés + + + + Subject: + Objet : + + + + From: + De : + + + + To: + A : + + + + Cc: + Cc : + + + + Bcc: + Cci : + + + + Tags: + Tags : + + + + File Name + Nom du fichier + + + + Size + Taille + + + + Hash + Hash + + + + Print + Imprimer + + + + Print Preview + Aperçu avant impression + + + + No subject + Pas d'objet + + + + Download + Télécharger + + + + Download all + Tout télécharger + + + + Hide + Cacher + + + + Expand + Développer + + + + File + Fichier + + + + Files + Fichiers + + + + Print Document + Imprimer le document + + + + Save as... + Enregistrer sous... + + + + HTML-Files (*.htm *.html);;All Files (*) + Fichiers HTML (*.htm *.html);;tous les fichiers (*) + + + + MessageWindow + + + New Message + Nouveau Message + + + + Compose + Nouveau + + + + Reply to selected message + Répondre au(x) Message(s) sélectionné(s) + + + + Reply + Répondre + + + + Reply all to selected message + Répondre à tous les destinataires du(des) Message(s) sélectionné(s) + + + + Reply all + Répondre à tous + + + + Forward selected message + Transférer le(s) Message(s) sélectionné(s) + + + + Foward + Transférer + + + + Remove selected message + Supprimer le(s) Message(s) sélectionné(s) + + + + Delete + Supprimer + + + + Print selected message + Imprimer le(s) Message(s) sélectionné(s) + + + + + Print + Imprimer + + + + Display + Affichage + + + + + + Tags + Tags + + + + Print Preview + Aperçu avant impression + + + + + Buttons Icon Only + Icônes seulement + + + + Buttons Text Beside Icon + Texte à côté des icônes + + + + Buttons with Text + Icônes avec texte + + + + Buttons Text Under Icon + Texte en dessous des l'icônes + + + + Set Text Under Icon + Définir le texte sous les icônes + + + + &File + &Fichier + + + + Save &As File + Enregistrer sous... + + + + &Print... + Im&primer... + + + + Print Preview... + Aperçu avant impression... + + + + &Quit + &Quitter + + + + MessagesDialog + + + + New Message + Nouveau Message + + + + Quick View + Vue rapide + + + + Reply to Message + Répondre au Message + + + + Remove Message + Supprimer le Message + + + + + Date + Date + + + + + + From + De + + + Size + Taille + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Fichiers recommandés</span></p></body></html> + + + + Reply + Répondre + + + + Reply all + Répondre à tous + + + + Foward + Transférer + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Supprimer le message sélectionné</p></body></html> + + + + Delete + Supprimer + + + + Compose + Nouveau + + + + Reply to selected message + Répondre au(x) Message(s) sélectionné(s) + + + + Reply all to selected message + Répondre à tous les destinataires du(des) Message(s) sélectionné(s) + + + + Forward selected message + Transférer le(s) Message(s) sélectionné(s) + + + + Remove selected message + Supprimer le(s) Message(s) sélectionné(s) + + + + Print selected message + Imprimer le(s) Message(s) sélectionné(s) + + + + Display + Affichage + + + + Reset + Réinitialiser + + + + Attachments + Fichiers joints + + + + + Content + Contenu + + + + + + + + Tags + Tags + + + Tag + Tag + + + + + + + Inbox + Boîte de réception + + + + + + + Outbox + Boîte d'envoi + + + + Draft + Brouillons + + + + + Sent + Eléments envoyés + + + + + + + Trash + Eléments supprimés + + + Favorite Tags + Tags favoris + + + + Total Inbox: + Tous les messages : + + + + Folders + Dossiers courrier + + + Cc: + Cc : + + + Bcc: + Cci : + + + Tags: + Tags : + + + + + Print... + Imprimer... + + + + Print Preview + Aperçu avant impression + + + + + Buttons Icon Only + Icônes seulement + + + + Buttons Text Beside Icon + Texte à côté des l'icônes + + + + Buttons with Text + Icônes avec texte + + + + Buttons Text Under Icon + Texte en dessous des l'icônes + + + + Set Text Under Icon + Définir le texte sous les icônes + + + + Save As... + Enregistrer sous... + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Répondre au message</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nouveau message</p></body></html> + + + Download All + Tout télécharger + + + Print Document + Imprimer le Message + + + File Name + Nom du fichier + + + Sources + Sources + + + # + # + + + SRCID + SRCID + + + MSGID + MSGID + + + + Forward selected Message + Transférer le(s) Message(s) sélectionné(s) + + + + Starred + Suivi + + + + Open in a new window + Ouvrir dans une nouvelle fenêtre + + + + Open in a new tab + Ouvrir dans un nouvel onglet + + + + Add Star + Suivre + + + + Edit + Editer + + + + Edit as new + Editer en tant que nouveau + + + + Remove Messages + Supprimer le(s) Message(s) + + + + Forward Message + Faire suivre le(s) Message(s) + + + + Click to sort by attachments + Cliquer pour trier par fichiers attachés + + + + Click to sort by subject + Cliquer pour trier par objet + + + + Click to sort by read + Cliquer pour trier par lu + + + + + Click to sort by from + Cliquer pour trier par expéditeur + + + + Click to sort by date + Cliquer pour trier par date + + + + Click to sort by tags + Cliquer pour trier par tags + + + + Click to sort by star + Cliquer pour trier par suivi + + + Remove All Tags + Supprimer tous les tags + + + New tag ... + Nouveau tag ... + + + Edit... + Editer... + + + + Mark as read + Marquer comme lu + + + + Mark as unread + Marquer comme non lu + + + + Undelete + Annuler la suppression + + + Download + Télécharger + + + + Empty trash + Vider la corbeille + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + Il n'y a pas de messages suivis. Suivre un message vous permettra de le retrouver plus facilement ultérieurement. Pour suivre un Message, cliquez sur l'étoile grise devant le Message que vous souhaitez suivre. + + + + Click to sort by to + Cliquer pour trier par destinataire + + + File + Fichier + + + Files + Fichiers + + + Re: + Re: + + + Compose: + Nouveau : + + + Fwd: + Fwd: + + + Hide + Cacher + + + Expand + Développer + + + + + + Drafts + Brouillons + + + + To + À + + + Anonymous + Anonymes + + + File Request Confirmation + Confirmer la demande de fichier + + + The file has been added to your download list. + Le fichier a été ajouté à votre liste de téléchargement. + + + File Request canceled + Annuler la demande de fichier + + + The file has not been added to your download list, because you already have it. + Le fichier n'a pas été ajouté à votre liste de téléchargement, car vous l'avez déjà. + + + File Request Error + Erreur de demande de fichier + + + The file link is malformed. + Le lien du fichier est corrompu. + + + Save as... + Enregistrer sous... + + + HTML-Files (*.htm *.html);;All Files (*) + Fichiers HTML (*.htm *.html);;tous les fichiers (*) + + + + + + + + Total: + Total : + + + Replay to All + Répondre à tous + + + + + Reply to All + Répondre à tous + + + + + Subject + Objet + + + Subject: + Objet : + + + From: + De : + + + Date: + Date : + + + To: + A : + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;" +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Téléchargez tous les fichiers recommandés</p></body></html> + + + Hash + Hash + + + + Print + Imprimer + + + PrintPreview + Apperçu d'impression + + + + MessengerWindow + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click to change your avatar</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Cliquez pour changer votre avatar</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Change your Status and your display</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">picture here.</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changez votre message perso et votre</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">image perso.</p></body></html> + + + Online + En ligne + + + Busy + Occupé(e) + + + Be right Back + De retour dans un instant + + + Away + Absent(e) + + + In a Call + Au téléphone + + + Out of lunch + Parti(e) manger + + + Apear Offline + Hors-ligne + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Share a personal message with your contacts</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Partager un message personnel avec vos contacts</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Add a Friend</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ajouter un ami</p></body></html> + + + + Expand all + Tout développer + + + + Collapse all + Tout réduire + + + + Chat + Chat + + + + Message Friend + Envoyer un Message + + + + Connect To Friend + Reconnecter + + + + Peer Details + Informations + + + + Recomend this Friend to... + Recommander cet ami à... + + + + Paste RetroShare Link + Coller le lien RetroShare + + + Paste retroshare Link + Coller le lien RetroShare + + + + Export Friend + Exporter + + + + Deny Friend + Ignorer + + + + Remove Friend Location + Supprimer l'emplacement + + + + <strong>GPG Key</strong> + <strong>Clé GPG</strong> + + + + + + + location + Emplacement + + + + <strong>RetroShare instance</strong> + <strong>Instance RetroShare</strong> + + + - + - + + + location : + Lieu : + + + + + + + + + Peer Online + Personne en ligne + + + Available + Disponible + + + Offline + Hors-ligne + + + + Save Certificate + Enregistrer le certificat + + + + Certificates (*.pqi) + Certificats (*.pqi) + + + Friend Not Online + Ami Hors-ligne + + + Your Friend is offline +Do you want to send them a Message instead + Votre ami est Hors-ligne +Voulez-vous lui envoyer un message à la place ? + + + View + Affichage + + + Send Message + Envoyer + + + Remove Friend + Supprimer + + + RetroShare Messenger + RetroShare Messenger + + + + Click to Change your Avatar + Cliquez ici pour modifier votre Avatar + + + TextLabel + Etiquette + + + + Share Files for your Friends + Partagez des fichiers avec vos amis + + + ... + ... + + + + RetroShare Messenger + RetroShare Messenger + + + + Add a Friend + Ajouter un ami + + + + Search Friends + Chercher des amis + + + + Reset + Réinitialiser + + + + + Sort Descending Order + Trier par ordre décroissant + + + + + Sort Ascending Order + Trier par ordre croissant + + + + Set root is Decorated + Afficher l'arborescence + + + + Set Root Decorated + Afficher l'arborescence + + + + Sort by State + Trier par statut + + + + Hide Offline Friends + Cacher mes amis hors-ligne + + + + MsgItem + + + Reply to Message + Répondre au Message + + + Form + Formulaire + + + + Remove Item + Effacer l'article + + + Connected + Connecté + + + + + Expand + Développer + + + subjectLabel + Sujet + + + + Reply Message + Répondre au Message + + + + Delete Message + Supprimer le Message + + + + Play Media + Lecture + + + Long + message here + Tappez votre message ici + + + + Message From + Message de + + + + Sent Msg + Message(s) envoyé(s) + + + + Draft Msg + Brouillon(s) + + + + Pending Msg + Message(s) en attente + + + + Hide + Cacher + + + + NATStatus + + + <strong>NAT:</strong> + <strong>NAT :</strong> + + + + Internet connection + Connexion Internet + + + + No internet connection + Pas de connexion Internet + + + + No local network + Pas de réseau local + + + UPNP is active. + UPnP est actif. + + + UPNP NOT FOUND. + UPNP non trouvé. + + + Stable External IP Address + Adresse IP Externe Stable + + + Not Found External Address + Aucune adresse externe trouvée + + + UDP Port is reachable + Le port UDP est accessible + + + UDP Port is not reachable + Le port UDP n'est pas accessible + + + TCP Port is reachable + Le port TCP est accessible + + + TCP Port is not reachable + Le port TCP n'est pas accessible + + + + OK | RetroShare Server + OK | Serveur RetroShare + + + RetroShare Server + Serveur RetroShare + + + UDP Server + Serveur UDP + + + Net Limited + Réseau Limité + + + No Conectivity + Aucune connectivité + + + + NetworkDialog + + Load Certificate + Charger le certificat + + + Select a pem/pqi File + Choisir un fichier pem/pqi + + + File Not Found + Fichier non trouvé + + + %1 does not exist. Would you like to create it? + %1 n'existe pas. Voulez-vous le créer ? + + + Failed to Create File + La création du fichier a échoué + + + Unable to create %1 [%2] + Impossible de créer %1 [%2] + + + Marginnal + Moyenne + + + Full + Totale + + + Ultimate + Ultime + + + None + Aucune + + + + Has authenticated me + M'a authentifié + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + vous a authentifié. +Clic droit et sélectionnez 'Devenir ami' pour vous connecter. + + + Select Certificate + Choisir le certificat + + + Certificates (*.pqi *.pem) + Certificats (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Réseau:</span></p></body></html> + + + # + # + + + Accept + Accepter + + + Trust + Confiance + + + Last Contact + Dernier contact + + + + + + Name + Nom + + + Organisation + Organisation + + + Location + Lieu + + + Country + Pays + + + + + Cert Id + ID du certificat + + + RetroShare %1 started. + e.g: RetroShare v0.x started. + RetroShare %1 a commencé. + + + Welcome to RetroShare. + Bienvenue dans RetroShare. + + + + Network + Réseau + + + Peer Details + Détails du peer + + + Trust matrix + Matrice de confiance + + + View + Affichage + + + RetroShare %1 started. + RetroShare %1 a démarré. + + + Menu + Menu + + + + Deny friend + Ignorer cet ami + + + Accept friend + Accepter ami + + + + Make friend + Devenir ami + + + + Delete certificate + Supprimer le certificat + + + + Export my Cert + Exporter mon certificat + + + + Peer details... + Détails de la contact... + + + Denied + Rejetée + + + Is trusting me + Est-moi confiance + + + + Unknown + Inconnu + + + Never seen + Jamais vu + + + + Authentication matrix + Matrice d'authentification + + + Authenticated + Authentifié + + + GPG key signed + Clé GPG signée + + + Not Authenticated + Non authentifié + + + GPG key not signed + Clé GPG non signée + + + + Copy RetroShare Link + Copier le lien RetroShare + + + + Personal signature + Signature personnelle + + + + GPG key signed by you + Clé PGP que vous avez signée + + + + Marginally trusted peer + Confiance moyenne + + + + Fully trusted peer + Entière confiance + + + + Untrusted peer + Non fiable + + + + yourself + Moi + + + RetroShare + RetroShare + + + Sorry, create certificate failed + Désolé, la création du certificat a échoué + + + Please choose a filename + Veuillez spécifier un nom de fichier + + + RetroShare Certificate (*.rsc );;All Files (*) + Certificats RetroShare (*.rsc );;Tous les fichiers (*) + + + Certificate file successfully created + Fichier certificat créé avec succès + + + Sorry, certificate file creation failed + Désolé, la création du fichier certificat a échoué + + + UPNP is active. + UPNP actif. + + + UPNP not found or not enabled. + UPNP non trouvé ou non activé + + + DHT is running. + DHT fonctionne + + + DHT is off. + DHT arrêté + + + UPNP NOT FOUND. + UPNP non trouvé. + + + Stun external address detection is working. + Découverte de l'adresse IP externe + + + Stun is not working. + Détection ne fonctionne pas. + + + Local network detected + Réseau local détecté + + + No local network detected + Aucun réseau local détecté + + + ip found via external address finder + Ip trouvée par la découverte d'adresse externe + + + external address finder didn't found anything + La découverte d'adresse externe n'a rien trouvé + + + DHT OK + DHT Ok + + + DHT is not working (down). + DHT ne fonctionne pas (faible). + + + Stable External IP Address + Adresse IP Externe Stable + + + Not Found External Address + Aucune adresse externe trouvée + + + UDP Port is reachable + Le port UDP est accessible + + + UDP Port is not reachable + Le port UDP n'est pas accessible + + + TCP Port is reachable + Le port TCP est accessible + + + TCP Port is not reachable + Le port TCP n'est pas accessible + + + RetroShare Server + Serveur RetroShare + + + UDP Server + Serveur UDP + + + Net Limited + Réseau Limité + + + No Conectivity + Aucune connectivité + + + + Network View + Afficher le réseau + + + Form + Formulaire + + + Your trust + Votre confiance + + + Peer's trust + Confiance des Pairs + + + Peer Address + Adresse de pair + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Réseau</span></p></body></html> + + + + Search Network + Chercher dans le réseau + + + + Clear Filter + Supprimer le filtre + + + + Peer ID + ID du contact + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Affichage</span></p></body></html> + + + Log + Journal + + + + Network Status + Etat du réseau + + + + Local network + Réseau local + + + + UPnP + UPnP + + + + External ip address finder + Découverte de l'adresse IP externe + + + + Create New Profile + Créer un nouveau profil + + + + Create a new Profile + Créer un nouveau profil + + + Limited + Limité + + + + Add Friend + Ajouter un ami + + + + Copy My Key to Clipboard + Copier ma clé dans le presse-papiers + + + + Export My Key + Exporter ma clé + + + Udp + Udp + + + Retroshare Server + Serveur RetroShare + + + UDP Connections + Connexions Udp + + + Stable External IP Addrress + Adresse IP Externe Stable + + + DHT Okay + DHT Ok + + + UPnP Active + UPnP actif + + + TCP server + Serveur TCP + + + GPG key validity + Validité de la clé GPG + + + + + Did I authenticated peer + J'ai authentifié le contact + + + + Did I sign his gpg key + J'ai signé sa clé PGP + + + + + Did peer authenticated me + Le contact m'a authentifié + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Réseau :</span></p></body></html> + + + + Show keys that are not validated by the GPG web of trust + Afficher toutes les clés du trousseau PGP + + + + Clear + Effacer + + + + Set Tabs Right + Définir les onglets à droite + + + + Set Tabs North + Définir les onglets en haut + + + + Set Tabs South + Définir les onglets en bas + + + + Set Tabs Left + Définir les onglets à gauche + + + + Set Tabs Rounded + Onglets arrondis + + + + Set Tabs Triangular + Onglets triangulaires + + + + NetworkPage + + Rate Options + Options de vitesse + + + Max Total Data Rate (KB/S): + Vitesse max totale de téléchargement (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vitesse par personne (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Cacher les paramètres + + + Show Settings + Affichez les paramètres + + + Settings + Paramètres + + + Form + Formulaire + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + Couleur de l'arrière plan: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 gris clair, stop:1 gris foncé); + + + + Redraw + Rafraîchir + + + + Friendship level: + Niveau d'affichage : + + + Basic + Basique + + + Friends + Amis + + + Extended + Étendu + + + Display mode: + Mode d'affichage : + + + Friends level: + Niveau d' amis: + + + + Edge length: + Longueur des liaisons : + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); + + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); + + + + + + Refresh + Actualiser + + + Show Friends of Friends + Afficher les amis de mes amis + + + Connect Signature + Signature de connection + + + Draw Friend Connections + Tracez les connexions amicales + + + + NewTag + + + New Tag + Nouveau tag + + + + Name: + Nom : + + + + Choose color + Choix de la couleur + + + + OK + OK + + + + Cancel + Annuler + + + + NewsFeed + + Form + Formulaire + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/konqsidebar_news16.png" /></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/konqsidebar_news16.png" /></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends Storm</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Actualité des amis</span></p></body></html> + + + + Remove All + Tout effacer + + + + Options + Options + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Fil d'actualité</span></p></body></html> + + + + NotifyPage + + + News Feed + Fil d'actualité + + + + Peers + Contacts + + + + Channels + Chaînes + + + + Forums + Forums + + + + Chat + Chat + + + + Blogs + Blogs + + + + Messages + Messages + + + Downloads + Téléchargements + + + + Add feeds at end + Nouveautés au bas du fil + + + + Systray Icon + Icônes de notification + + + + Private Message + Message privé + + + + Message + Message + + + + Channel Post + Post des Chaînes + + + + Forum Post + Post des Forums + + + + + Download completed + Téléchargement terminé + + + + Combined icon + Icônes unifiées + + + + Toasters + Notifications + + + + Friend Connect + Connexion d'un ami + + + Peer Connect + Connetion d'un ami + + + + New Message + Nouveau Message + + + + Position + Position + + + + X Margin + Axe Horizontal + + + + Y Margin + Axe Vertical + + + + Private Chat + RetroShare Messenger + + + + Open Window for new chat + Ouvrir une fenêtre lors d'un nouveau Message privé + + + Open Window for new Peer Chat + Ouvrir le Chat dans une nouvelle fenêtre + + + Reopen if closed by user: + Rouvrir si fermé par l'utilisateur : + + + + Grab Focus when chat arrives + Message privé au premier plan + + + + Use a single tabbed window + Utiliser un onglet par conversation + + + + Group chat + Chat public + + + + Display systray message + Afficher le message dans la zone de notification + + + + Top Left + En haut à gauche + + + + Top Right + En haut à droite + + + + Bottom Left + En bas à gauche + + + + Bottom Right + En bas à droite + + + + NotifyQt + + + GPG key passphrase + Mot de passe de la clé PGP + + + + Wrong password ! + Mauvais mot de passe ! + + + + Please enter the password to unlock the following GPG key: + Veuillez entrer votre mot de passe pour dévérouiller la clé PGP suivante : + + + + + Examining shared files... + Analyse des fichiers partagés... + + + + Hashing file + Hash des fichiers + + + + Saving file index... + Enregistrement de l'index des fichiers... + + + Please enter the password to unlock the following GPG key: + + Veuillez entrer votre mot de passe pour dévérouiller la clé GPG suivante : + + + + + OnlineToaster + + Peer Online + Personne en ligne + + + + Friend Online + En ligne + + + + PeerDefs + + Anonymous + Anonymes + + + + + Unknown + Inconnu + + + + PeerItem + + Make Friend + Devenir ami + + + Remove Friend + Enlever un ami + + + + Name: + Nom : + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Peer Id:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ID de la personne :</span></p></body></html> + + + Organisation + Organisation + + + + Location + Emplacement + + + Country + Pays + + + Form + Formulaire + + + + Remove Item + Effacer l'article + + + Connected + Connecté + + + + + Expand + Développer + + + + Write a quick Message + Envoyer un message instantané + + + + Send + Envoyer + + + + Cancel + Annuler + + + + Peer ID: + ID du contact : + + + + Write Message + Ecrire un message + + + + Start Chat + Dialoguer + + + + Status: + Statut : + + + + Trust: + Confiance : + + + Good + Bonne + + + Send Mail + Envoyer un courrier électronique + + + + Chat + Chat + + + TextLabel + Etiquette + + + + IP Address + Adresse IP + + + + Connection Method + Méthode de connexion + + + Last Contact: + Dernier contact : + + + + Friend + Ami + + + + Friend Connected + Ami connecté + + + + Connect Attempt + Tentative de connection + + + + Friend of Friend + Ami d'ami + + + + Peer + Contact + + + + + + + + + + + + Unknown Peer + Contact inconnu + + + + Hide + Cacher + + + + Quick Message + Message instantané + + + + PeerStatus + + Online: 0 | Friends: 0 | Network: 0 + En-ligne : 0 | Amis : 0 | Réseau : 0 + + + + Friends: 0/0 + Amis : 0/0 + + + + Online Friends/Total Friends + Amis en ligne/Nombre total d'amis + + + + Friends + Amis + + + Online + En ligne + + + <span style="color:#000000"><strong>Friends:</strong></span> + <span style="color:#000000"><strong>Amis :</strong></span> + + + <span style="color:#0000FF"><strong>Online:</strong></span> + <span style="color:#0000FF"><strong>En-ligne :</strong></span> + + + Online: + En-ligne : + + + Friends: + Amis : + + + Network: + Réseau : + + + + PeersDialog + + Chat + Chat + + + Export Friend + Exporter un ami + + + Remove Friend + Enlever un ami + + + Save Certificate + Enregistrer le certificat + + + Certificates (*.pqi) + Certificats (*.pqi) + + + Status + Statut + + + Person + Personne + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Amis</span></p></body></html> + + + Connect To Friend + Se connecter à cet ami + + + # + # + + + Profile + Profil + + + Friends Storm + Actualité des amis + + + Paste retroshare Link + Coller le lien RetroShare + + + Welcome to RetroShare's group chat. + Bienvenue dans le chat public de RetroShare. + + + Friend Details + Détails de cet ami + + + Recommend this Friend to... + Recommander cet ami à... + + + Add to group + Ajouter à un groupe + + + Move to group + Déplacer dans le groupe + + + Groups + Groupes + + + Remove from group + Supprimer du groupe + + + Remove from all groups + Supprimer de tous les groupes + + + Expand all + Développer tout + + + Collapse all + Réduire tout + + + Message Friend + Envoyer un Message + + + Peer Details + Détails + + + Deny Friend + Ignorer cet ami + + + Remove Friend Location + Supprimer l'emplacement de cet ami + + + <strong>GPG Key</strong> + <strong>Clé GPG</strong> + + + <strong>RetroShare instance</strong> + <strong>Instance RetroShare</strong> + + + location : + Lieu : + + + Online + En-ligne + + + Peer Online + Personne en ligne + + + Away + Absent(e) + + + Busy + Occupé(e) + + + Available + Disponible + + + Offline + Hors-ligne + + + Friend Not Online + Ami hors-ligne + + + Your Friend is offline +Do you want to send them a Message instead + Votre ami est hors-ligne +Voulez-vous lui envoyer un message à la place ? + + + RetroShare + RetroShare + + + Do you want to remove this Friend? + Désirez-vous supprimer cet ami ? + + + is typing... + est en train d'écrire... + + + Create a new Channel + Créer un nouveau canal + + + New Channel + Nouveau canal + + + Add Extra File + Joindre un fichier + + + File Request Confirmation + Confirmation de demande de fichier + + + The file has been added to your download list. + Ce fichier a été ajouté à votre liste de téléchargement. + + + File Request canceled + Annulation de la demande de fichier + + + The file has not been added to your download list, because you already have it. + Ce fichier n'a pas été ajouté à votre liste de téléchargement, car vous le possédez déjà. + + + File Request Error + Erreur de demande de fichier + + + The file link is malformed. + Le lien du fichier est corrompu. + + + Drop file error. + Erreur lors du dépôt de fichier. + + + File not found or file name not accepted. + Le fichier n'a pas été trouvé ou le nom du fichier n'est pas accepté. + + + Directory can't be dropped, only files are accepted. + On ne peut pas déposer un répertoire, seuls les fichiers sont acceptés. + + + News Feed + Fil d'actualité + + + Paste RetroShare Link + Coller le lien RetroShare + + + Group + Groupe + + + Friend + Ami + + + Location + Emplacement + + + Message Group + Message à ce groupe + + + Edit Group + Modifier le groupe + + + Remove Group + Supprimer le groupe + + + Paste Friend Link + Coller le lien d'ajout d'ami + + + location + Emplacement + + + New group chat + Nouveau Message à ce groupe + + + Load File + Charger un fichier + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Images (*.png *.xpm *.jpg) + + + Save as... + Enregistrer sous... + + + Text File (*.txt );;All Files (*) + Fichier Texte (*.txt);;Tous les fichiers (*) + + + me + Moi + + + - + - + + + Send + Envoyer + + + Profile View + Affichage du profil + + + Live Group Chat: + Groupe de discution live: + + + Italic + Italique + + + Underline + Souligner + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Amis</span></p></body></html> + + + Add + Ajouter + + + hide unconnected + Cacher les amis déconnectés + + + Add or Change your Avatar + Ajouter ou modifier votre image perso + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; color:#00aa00;">nickname (me)</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; color:#00aa00;">Pseudonyme (Moi)</span></p></body></html> + + + Edit Personal message + Editer mon message perso + + + Live Chat + Chat Live + + + Bold + Gras + + + Create New Forum + Créer un nouveau Forum + + + Create new Forum + Créer un nouveau Forum + + + F + F + + + Create New Channel + Créer un nouveau canal + + + Display + Affichage + + + Messages entered here are sent to all collected friends + Les Messages inscrits ici sont envoyés à tous les amis sélectionnés + + + Create new Channel + Créer une nouvelle Chaîne + + + C + C + + + Add your Avatar Picture + Ajouter votre image perso + + + A + A + + + Set your Personal Message + Définir votre message perso + + + Edit your status Message + Editer votre message perso + + + Browse Message History + Parcourir l'historique des messages + + + Browse History + Parcourir l'historique + + + Sort by State + Trier par statut + + + Hide State + Cacher le statut + + + Add a new Group + Ajouter un nouveau groupe + + + Sort Descending Order + Trier par ordre décroissant + + + Sort Ascending Order + Trier par ordre croissant + + + Delete Chat History + Supprimer l'historique du Chat + + + Deletes all stored and displayed chat history + Supprimer tous les historiques de Chat affichés et enregistrés + + + Disable Emoticons + Désactiver les émoticônes + + + Save Chat History + Sauvegarder l'historique du Chat + + + Hide Offline Friends + Cacher mes amis hors-ligne + + + Hide Status Column + Cacher la colonne des statuts + + + Text Color + Couleur du texte + + + Add Friend + Ajouter un ami + + + Create new Profile + Créer un nouveau profil + + + Font + Police + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Affichage</span></p></body></html> + + + Friends + Amis + + + Group Chat + Chat public + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">set Text Color</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Définir la couleur du texte</span></p></body></html> + + + Attach File + Joindre un fichier + + + Clear Chat History + Effacer l'historique du chat + + + + PhotoDialog + + + Insert Show Lists + Insertion de listes d'affichages + + + + Open + Ouvrir + + + + Remove + Supprimer + + + + Excellent + Excellent + + + + Good + Bonne + + + + Average + Moyen + + + + Below avarage + Sous la moyenne + + + + Bad + Mauvaise + + + + Unrated + Non évaluée + + + + Rating + Evaluation + + + + + Date + Date + + + + + Location + Emplacement + + + + Size + Taille + + + Form + Formulaire + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Visionneuse de photo</span></p></body></html> + + + + Peer + Contact + + + + Slideshow + Diaporama + + + + Photo + Photo + + + + Thumb Image + Miniature + + + + Image Name + Nom de l'image + + + + + Comment + Commantaire + + + + PeerId + ID du contact + + + + PhotoId + ID de la photo + + + + + Add Photo(s) + Ajouter photo(s) + + + + Add Photo SlideShow + Ajouter un diaporama + + + + Update Details + Mise à jour des informations + + + + Photo + Photo + + + + Description + Description + + + + PhotoShow + + + Location: + Emplacement : + + + Form + Formulaire + + + + Date: + Date : + + + + Comment: + Commantaire : + + + + Display Size: + Taille d'affichage : + + + + 320 x 320 + 320 x 320 + + + + 640 x 640 + 640 x 640 + + + + Full Size + Taille réelle + + + + Play Rate: + Vitesse de lecture : + + + + 1 Sec + 1 Sec + + + + 2 Sec + 2 Sec + + + + 5 Sec + 5 Sec + + + + 10 Sec + 10 Sec + + + + 20 Sec + 20 Sec + + + + 1 Min + 1 Min + + + + Edit Photo Details + Editez les détails de l'image + + + + Save Photo + Enregistrer l'image + + + + No Photo Selected + Aucune image sélectionnée + + + + Start + Démarrer + + + + Back + Précédente + + + + Photo Show + Diaporama + + + + Play + Lecture + + + + Pause + Pause + + + + Forward + Suivante + + + + PluginFrame + + + Remove + Supprimer + + + + PluginManagerWidget + + + Install New Plugin... + Installation d'un nouveau plugin... + + + + Open Plugin to install + Ouvrir un plugin à installer + + + + Plugins (*.so *.dll) + Plugins (*.so *.dll) + + + + PopularityDefs + + + Popularity + Popularité + + + + PopupChatDialog + + Paste retroshare Link + Coller le lien RetroShare + + + + Your Friend is offline +Do you want to send them a Message instead + Votre ami est hors-ligne +Voulez-vous lui envoyer un Message à la place ? + + + Chatting with + Discussion avec + + + + is typing... + est en train d'écrire... + + + + Hide Avatar + Cacher l'image perso + + + :images/hide_toolbox_frame.png + :images/hide_toolbox_frame.png + + + + Show Avatar + Montrer l'image perso + + + :images/show_toolbox_frame.png + :images/show_toolbox_frame.png + + + Open Style + Ouvrir les thèmes visuels + + + Styles (*.htm) + Thèmes visuels (*.htm) + + + RetroShare + RetroShare + + + + Friend not Online + Ami Hors-ligne + + + + Paste RetroShare Link + Coller le lien RetroShare + + + + Do you really want to physically delete the history? + Etes-vous vraiment sûr de vouloir supprimer définitivement l'historique ? + + + + Add Extra File + Joindre un fichier + + + + Load Picture File + Joindre une image + + + + Save as... + Enregistrer sous... + + + + Text File (*.txt );;All Files (*) + Fichier texte (*.txt );;Tous les fichiers (*) + + + + apears to be Offline. + semble être hors-ligne. + + + + Messages you send will be delivered after Friend is again Online + Les messages que vous enverrez seront délivrés lorsque votre ami sera en ligne + + + + is Idle and may not reply + est inactif et peut ne pas répondre + + + + is Away and may not reply + est absent et peut ne pas répondre + + + + is Busy and may not reply + est occupé et peut ne pas répondre + + + File Request Confirmation + Confirmation de demande de fichier + + + The file has been added to your download list. + Ce fichier a été ajouté à votre liste de téléchargements. + + + File Request canceled + Demande de fichier annulée + + + The file has not been added to your download list, because you already have it, or you're already downloading it. + Ce fichier n'a pas été ajouté à votre liste de téléchargement car vous le possédez déjà. + + + File Request Error + Erreur de demande de fichiers + + + The file link is malformed. + Le lien du fichier est corrompu. + + + + + Drop file error. + Erreur lors de l'ajout du fichier. + + + + File not found or file name not accepted. + Le fichier n'a pas été trouvé ou le nom du fichier n'est pas accepté. + + + + Directory can't be dropped, only files are accepted. + On ne peut pas déposer un répertoire, seuls les fichiers sont acceptés. + + + + Send + Envoyer + + + RetroShare - Encrypted Chat + RetroShare - Chat crypté + + + MainWindow + Fenêtre principale + + + QLabel{ +border-image: url(:/images/mystatus_bg.png); + +} + QLabel{ +border-image: url(:/images/mystatus_bg.png); + +} + + + TextLabel + Etiquette + + + + Close + Fermer + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Set Chat Window Style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Définir le style visuel de la fenêtre Chat</p></body></html> + + + + + Bold + Gras + + + + + Underline + Souligner + + + + + Italic + Italique + + + Set Font + Définir la police + + + + Font + Police + + + + Text Color + Couleur du texte + + + + Clear Chat History + Effacer l'historique du chat + + + + Browse Message History + Parcourir l'historique des messages + + + + Browse History + Parcourir l'historique + + + + Delete Chat History + Supprimer l'historique du chat + + + + Deletes all stored and displayed chat history + Cela supprime tous les historiques de chat affichés et enregistrés + + + + Attach a Picture + Joindre une image + + + + Add a File for your Friend + Joindre un fichier + + + toolBar + Barre d'outils + + + + Strike + Découverte + + + Avatar + Image perso + + + Set your Avatar Picture + Définir votre image perso + + + Clear Chat + Effacer l'historique + + + + Disable Emoticons + Désactiver les émoticônes + + + + + Save Chat History + Sauvegarder l'historique du chat + + + + Clear offline messages + Effacer les messages hors-ligne + + + + PopupChatWindow + + + Avatar + Image perso + + + + Set your Avatar Picture + Définir votre image perso + + + + + Dock tab + Activer les onglets + + + + + Undock tab + Désactiver les onglets + + + + + Set Chat Window Color + Définir la couleur de la fenêtre du Chat + + + + RetroShare + RetroShare + + + + Load File + Charger une image + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Images (*.png *.xpm *.jpg) + + + + PrintPreview + + + RetroShare Message - Print Preview + Message RetroShare - Aperçu avant impression + + + + Print + Imprimer + + + + &Print... + Im&primer... + + + + Page Setup... + Mise en page... + + + + Zoom In + Zoom + + + + + Zoom Out + Zoom - + + + + &Close + &Fermer + + + + ProfileEdit + + + Remove Profile Entry + Supprimer l'entrée du profil + + + + Move Profile Entry Up + Monter l'entrée du profil + + + + Move Profile Entry Down + Descendre l'entrée du profil + + + + Profile Edit + Editer le profil + + + + Profile + Profil + + + + Category + Catégorie + + + + Thoughts + Pensées + + + + Edit Profile Category + Editer le profil + + + + Birthday + Anniversaire + + + + School + Ecole + + + + University + Université + + + + Phone Number + Numéro de téléphone + + + + Favourite Books + Livres préférés + + + + Favourite Music + Musiques préférées + + + + Favourite Films + Films préférés + + + + or Custom Entry + ou entrée personnalisée + + + + Add Entry + Ajouter une entrée + + + + + Move + Déplacer + + + + Close Editor + Fermer l'éditeur + + + + ProfileView + + + Clear Photo + Effacer la photo + + + + Change Photo + Modifier la photo + + + + + Edit Profile + Editez le profil + + + + Remove Favourite + Supprimer le favori + + + + Clear Favourites + Effacer les favoris + + + + Download File + Télécharger le fichier + + + + Download All + Tout télécharger + + + + RetroShare + RetroShare + + + + Error : cannot get peer details. + Erreur : impossible d'obtenir les détails de ce contact. + + + + + Name + Nom + + + + Peer ID + ID du contact + + + + Size + Taille + + + + Profile View + Voir le profil + + + Rs ID + Rs ID + + + + Last Post: + Dernier post : + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profil</span></p></body></html> + + + + Category + Catégorie + + + + Thoughts + Pensées + + + + Favourite Files + Fichiers favoris + + + + Hash + Hash + + + + Close Profile + Fermer le profil + + + + ProfileWidget + + Form + Formulaire + + + + + Edit Personal message + Editer le message personnel + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Information publique</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Informations publiques</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Nom :</span></p></body></html> + + + TextLabel + Etiquette + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Emplacement :</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">ID de la personne</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Autres informations</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Nombre d'amis :</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">ID du contact :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">En ligne depuis :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Mes adresses IP :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Adresse IP privée :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Adresse IP publique :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Historique des adresses IP :</span></p></body></html> + + + Addresses list + Liste d'adresses + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Local Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Adresse locale :</span></p></body></html> + + + + QObject + + and + et + + + and / or + et / ou + + + or + ou + + + Name + Nom + + + Path + Chemin + + + Extension + Extension + + + Date + Date + + + Size + Taille + + + Popularity + Popularité + + + contains + contient + + + contains all + les contient tous + + + is + est + + + less than + inférieur + + + less than or equal + inférieur ou égal + + + equals + égaux + + + greater than or equal + supérieur ou égal + + + greater than + supérieur + + + is in range + dans l'intervalle + + + Hash + Hash + + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + L'initialisation a échoué. Installation de PGP corrompue ou manquante. + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + Une erreur inattendue s'est produite. Vous pouvez la reporter 'RsInit::InitRetroShare unexpected return code %1'. + + + + + Multiple instances + Multiples instances + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + Une autre instance de RetroShare utilise actuellement le même profil sur votre système. Veuillez dans un premier temps fermer ce profil puis réessayez de l'ouvrir. + Fichier vérrouillé : + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + Une erreur inattendue s'est produite lorsque RetroShare a essayé d'acquérir le verrou d'instance unique + Fichier vérrouillé : + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Une autre instance de Retroshare utilise actuellement le même profil sur votre système. Veuillez fermer d'abord cette instance + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Une erreur inattendue s'est produite lorsque Retroshare a essayé d'acquérir le verrou d'instance unique + + + + Login Failure + La connexion échouée + + + + Maybe password is wrong + Veuillez vérifier votre mot de passe + + + + File Request Confirmation + Confirmation de demande de fichier + + + + The file has been added to your download list. + Ce fichier a été ajouté à votre liste de téléchargements. + + + + + File Request canceled + Demande de fichier annulée + + + + The following has not been added to your download list, because you already have it: + + Le fichier n'a pas été ajouté à votre liste de téléchargement, parce que vous l'avez déjà : + + + + + The file has not been added to your download list, because you already have it. + Ce fichier n'a pas été ajouté à votre liste de téléchargement car vous le possédez déjà. + + + + + Friend Request Confirmation + Confirmation de demande d'ami + + + + The friend is already in your list. + Cet ami est déjà dans votre liste. + + + + The friend has been added to your list. + Cet ami a été ajouté à votre liste. + + + + + Friend Request canceled + Demande d'ami annulée + + + + The friend could not be added to your list. + Cet ami n'a pas pu être ajouté à votre liste. + + + + The friend could not be found. + Cet ami n'a pas pu être trouvé. + + + + + Forum Request canceled + Demande de Forum annulée + + + + The forum "%1" could not be found. + Le Forum "%1" n'a pas pu être trouvé. + + + + The forum message in forum "%1" could not be found. + Le message du Forum "%1" n'as pas pu être trouvé. + + + + + Channel Request canceled + Demande de Chaîne annulée + + + + The channel "%1" could not be found. + La Chaîne "%1" n'a pas pu être trouvé. + + + + The channel message in channel "%1" could not be found. + Le message de la Chaîne "%1" n'a pas pu être trouvé. + + + + + Message Request canceled + Demande de Message annulée + + + + Cannot send a message to a not accepted receipient "%1". + Impossible d'envoyer un message à un destinataire non reconnu "%1". + + + + The receipient of the message is unknown. + Le destinataire du Message est inconnu. + + + + File Request Error + Erreur de demande de fichier + + + + The file link is malformed. + Le lien du fichier est corrompu. + + + + %1 of %2 RetroShare links processed. + %1 des %2 liens RetroShare traités. + + + + Request Confirmation + Demande de confirmation + + + File Request + Demande de fichier + + + Process of RetroShare links is not implemented. Please use copy instead. + Le processus des liens RetroShare n'est pas implenté. Veuillez utiliser le copier-coller. + + + + Deny friend + Ignorer cet ami + + + + Make friend + Devenir ami + + + + Peer details + Détails du contact + + + + Start with a RetroShare link is only supported for Windows. + Démarrer avec un lien RetroShare est seulement possible sous Windows. + + + + (Age in seconds) + (Ancienneté en secondes) + + + + (Depth) + (Profondeur) + + + + total + total + + + + Search requests repartition: + Répartition des requêtes de recherche : + + + + Tunnel requests repartition: + Répartition des requêtes de tunnel : + + + + QuickStartWizard + + + Quick Start Wizard + Assistant de configuration + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare !</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Choos which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Bienvenue dans RetroShare !</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Cet assistant de configuration va vous permettre de paramêtrer rapidement et simplement RetroShare !</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Utilisateurs avancés, vous pouvez accéder à la totalité des options via la barre latérale de gauche. A tout moment vous pouvez quitter cet assistant.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Cet assistant vous permettra de :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Configurer les paramètres de connexion.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Choisir les dossiers à partager.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Configurer le lancement de RetroShare.</span></p></body></html> + + + + + + Next > + Suivant > + + + + + + + Exit + Fin + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + Pour obtenir de meilleures performances, RetroShare a besoin d'informations au sujet de votre connexion internet. + + + + Choose your upload speed limit: + Vitesse d'envoi maximale : + + + + + KB/s + Ko/s + + + + Choose your download speed limit: + Vitesse de réception maximale : + + + + Connection : + Connexion : + + + + Automatic (UPnP) + Automatique (UPnP) + + + + Firewalled + Pare-feu + + + + Manually forwarded port + Redirection de port + + + Dicovery : + Découverte : + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Bienvenue dans RetroShare !</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Cet assistant de démarrage vous permet de configurer RetroShare en quelques étapes.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Si vous êtes un utilisateur avancé,vous pouvez accéder aux options complètes de RetroShare via le menu options. Vous pouvez quitter cet assistant à tout moment en cliquant sur quitter.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Cet assistant vous permettra : </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> De paramêtrer vos informations de connexion</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> De choisir les fichiers à partager</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Commencer à utiliser RetroShare</span></p></body></html> + + + + Discovery : + Découverte : + + + Share Ip and information with your friend (Disc On) + Partager mon IP et mes informations avec mes amis (Découverte activée) + + + Don't share any information (Disc Off) + Ne partager aucune informations (Découverte désactivée) + + + + Dynamic DNS: + Dynamic DNS : + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Public: DHT & Discovery + Publique : DHT & Découverte + + + + Private: Discovery Only + Privée : Découverte seulement + + + + Inverted: DHT Only + Inversé : DHT seulement + + + + Dark Net: None + Dark Net : Aucun + + + + + + < Back + < Précédent + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Voici la liste des dossiers partagés. Vous pouvez ajouter ou supprimer de nouveaux dossiers en utilisant les boutons "Ajouter" et "Supprimer" Quand vous ajoutez un nouveau dossier, tous les fichiers présents dans ce dossier sont partagés.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Vous pouvez paramétrer séparément la méthode de partage pour chacun des dossiers :</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Partage public </span><span style=" font-family:'Sans'; font-size:8pt;">: votre liste de fichiers est visible par vos amis.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Partage anonyme </span><span style=" font-family:'Sans'; font-size:8pt;">: vos fichiers seront accessibles par n'importe qui par l'intermédiaire d'un tunnel anonyme.</span></p></body></html> + + + + Directory + Répertoire + + + + Network Wide + Anonyme + + + + Browseable + Public + + + + Add + Ajouter + + + + Remove + Supprimer + + + + Automatically share incoming directory (Recommended) + Partager le dossier de réception (Recommandé) + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Amusez-vous bien avec RetroShare !</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Vous avez quasiement terminé la configuration de RetroShare ! </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Ces paramètres détermineront la façon dont RetroShare va démarrer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Do not show a message when Closing RetroShare + Ne pas afficher d'avertissement à la fermeture de RetroShare + + + + Start Minimized + Démarrer en mode réduit + + + + Start RetroShare when my System Starts. + Démarrer RetroShare au lancement du système + + + + Start minimized on system start + Minimiser au démarrage du système + + + + Finish + Fin de la configuration + + + + Select A Folder To Share + Choisir un dossier à partager + + + + Shared Directory Added! + Le dossier a été ajouté ! + + + + Do you really want to stop sharing this directory ? + Etes-vous sûr de ne plus vouloir partager ce dossier ? + + + + Warning! + Attention ! + + + + RSettingsWin + + + General + Général + + + + Directories + Répertoires + + + + Server + Connexion + + + + Transfer + Transferts + + + + Notify + Notifications + + + + Security + Sécurité + + + + Message + Messages + + + + Forum + Forums + + + + Chat + Chat + + + + Appearance + Apparence + + + File Associations + Association de fichiers + + + + Sound + Sons + + + + UnknownPage + Page inconnue + + + + Error Saving Configuration on page + Une erreur est survenue lors de l'enregistrement de la configuration + + + Error Saving Configuration + Une erreur est survenue lors de l'enregistrement de la configuration + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>Réception:</strong> 0.00 (Ko/s) | <strong>Emission:</strong> 0.00 (Ko/s) + + + + <strong>Down:</strong> + <strong>Réception : </strong> + + + + <strong>Up:</strong> + <strong>Emission : </strong> + + + Down: + Réception : + + + Up: + Emission : + + + + RemoteDirModel + + Friends Directories + Dossiers partagés de mes amis + + + My Directories + Mes partages + + + Size + Taille + + + Share Type + Méthode de partage + + + What's new + Quoi de neuf ? + + + Rank + Classement + + + Age + Ancienneté + + + FILE + Fichier + + + Anonymous + Anonyme + + + Anonymous and browsable by friends + Anonyme et visible par mes amis + + + Only browsable by friends + Visible seulement par mes amis + + + NEW + Nouveau + + + Files + Fichiers + + + File + Fichier + + + DIR + Répertoire + + + + RetroshareDirModel + + + Anonymous + Anonyme + + + + Anonymous and browsable by friends + Anonyme et visible par mes amis + + + + Only browsable by friends + Visible seulement par mes amis + + + + NEW + NOUVEAU + + + + Rshare + + + Invalid language code specified: + Le code de langue indiqué n'est pas valide : + + + + Invalid GUI style specified: + Le style visuel de l'interface indiqué n'est pas valide : + + + + Resets ALL stored RetroShare settings. + Réinitialisation de tous les paramètres de RetroShare. + + + + Sets the directory RetroShare uses for data files. + Définit le dossier utilisé par RetroShare pour stocker le profil utilisateur. + + + + Sets the name and location of RetroShare's logfile. + Définit le nom et l'emplacement des fichiers log de RetroShare. + + + Sets the verbosity of Vidalia's logging. + Définir la verbosité du log de Vidalia. + + + + Sets the verbosity of RetroShare's logging. + Définit la verbosité du log de RetroShare. + + + + Sets RetroShare's interface style. + Définit le style visuel de RetroShare. + + + + Sets RetroShare's interface stylesheets. + Définit la feuille de style de l'interface de RetroShare. + + + + Sets RetroShare's language. + Définit le language de RetroShare. + + + + RetroShare Usage Information + Information sur l'utilisation de RetroShare + + + + Invalid log level specified: + Niveau du journal spécifié invalide : + + + + Unable to open log file '%1': %2 + Impossible d'ouvrir le journal '%1': %2 + + + + RsidPage + + + RetroShare ID + ID Retroshare + + + + Use RetroShare ID for adding a Friend which is available in your network. + Utilisez l'ID RetroShare pour ajouter un ami qui est disponible sur le réseau. + + + + Add Friends RetroShare ID... + Ajouter l'ID d'un ami RetroShare... + + + + Paste Friends RetroShare ID in the box below + Coller l'ID RetroShare ci-dessous + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + Entrez l'ID RetroShare de votre ami, ex. Contact@BDE8D16A46D938CF + + + + This Peer %1 is not available in your Network + Ce contact %1 n'est pas disponible dans votre réseau + + + + SFListDelegate + + + B + O + + + + KB + Ko + + + + MB + Mo + + + + GB + Go + + + + SearchDialog + + + Sources + Sources + + + + Results + Résultats + + + Clear all Search Results + Supprimer toutes les recherches + + + + + Download + Télécharger + + + + Enter a keyword here (at least 3 char long) + Tappez votre recherche (minimum 3 caractères) + + + Copy retroshare Link + Copier le lien RetroShare + + + Send retroshare Link + Evoyer le lien RetroShare + + + Broadcast on Channel + Émettre sur la Chaîne + + + Recommend to Friends + Recommander aux amis + + + + New RetroShare Link(s) + Nouveau(x) lien(s) RetroShare + + + / + / + + + + Remove + Supprimer + + + + Remove All + Tout supprimer + + + + + Folder + Dossier + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + + Any + Tout + + + + Audio + Audio + + + + Video + Vidéo + + + Images + Images + + + Programs + Programmes + + + Archives + Archives + + + Documents + Documents + + + + + Copy RetroShare Link + Copier le lien RetroShare + + + + Send RetroShare Link + Envoyer le lien RetroShare + + + + Download Notice + Télécharger la notice + + + + Skipping Local Files + Les fichiers que vous possédez déjà seront ignorés + + + + + Sorry + Désolé + + + + + This function is not yet implemented. + Cette fonction n'est pas encore activée. + + + + Size + Taille + + + + Type + Type + + + Toggle advanced searching on and off. + Commande de recherche avancée marche et arrêt. + + + <h3>Simple Search:</h3> + <h3>Recherche simple : </h3> + + + Keywords + Mots-clés + + + + Archive + Archive + + + + CD-Image + Image Disque + + + + Document + Document + + + + Picture + Image + + + + Program + Programme + + + + Directory + Répertoire + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enter a Keyword here</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Tappez votre recherche ici</p></body></html> + + + + Start Search + Démarrer la recherche + + + + Search + Rechercher + + + + Filter Search Result + Résultats filtrés + + + + Clear Filter + Supprimer le filtre + + + + File Name + Nom du fichier + + + + File Size + Taille du fichier + + + + Close all Search Resullts + Fermer tous les résultats de recherche + + + + Download Selected + Télécharger la sélection + + + + Include files from your own file list in the search result + Afficher vos fichiers dans les résultats de recherche + + + + Include own files + Afficher mes fichiers + + + + Search inside "browsable" files of your friends + Chercher dans les dossiers de vos amis + + + + Search in friends lists + Chercher dans la liste de fichier de mes amis + + + + Multi-hop search at distance 6 in the network +(always reports available files) + Recherche jusqu'à 6 niveaux de contacts dans le réseau +(Toujours proposer des fichiers disponibles) + + + + F2F search + Recherche F2F + + + + Limit number of results to : + Nombre de résultats limités à : + + + + Reset + Réinitialiser + + + + Enter a Keyword here + Entrez un mot clé + + + + Advanced Search + Recherche avancée + + + + Advanced + Avancé + + + Perform simple search + Lancer la recherche + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Close all Search Resullts</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Supprimer toutes les recherches</span></p></body></html> + + + + Close All Search Results + Supprimer toutes les recherches + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Download Selected</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Télécharger les éléments selectionnés</span></p></body></html> + + + <h3>Advanced Search:</h3> + <h3>Recherche avancée : </h3> + + + Show Advanced Search Tool + Outil de Recherche Avancée + + + + Filename + Nom du fichier + + + + Age + Ancienneté + + + + Hash + Hash + + + + KeyWords + Mots-clés + + + + Search Id + ID de recherche + + + + SendLinkDialog + + Send RetroShare link + Envoyer le lien RetroShare + + + Send + Envoyer + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:22pt; color:#ffffff;">Send RetroShare Link</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:22pt; color:#ffffff;">Envoyer le lien RetroShare</span></p></body></html> + + + + ServerPage + + Change + Restart Server + Appliquer + redémarrer le serveur + + + Server Settings + Options du serveur + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Adresse externe:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Adresse locale:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + + + + + Port: + Port : + + + Misc + Misc + + + behinde Firewall + derrière un pare-feu + + + Forwarded External Port + Port externe transmis + + + + Transfer Rates + Vitesses de transfert + + + Network Configuration (takes effect after restart) + Configuration réseau (prend effet après un redémarrage) + + + Automatic + Automatique + + + + Firewalled + Pare-feu + + + Forwarded Port + Port redirigé + + + DHT Enabled + DHT activé + + + DHT Disabled + DHT désactivé + + + + Automatic (Upnp) + Automatique (UPnP) + + + + Manual Forwarded Port + Redirection de port manuelle + + + Should be disabled if you don't want to share connection information between peers. + Devrait être désactié si vous ne souhaitez pas partager les informations de connexion entre les personnes. + + + Discovery Enabled + Découverte activée + + + Discovery Disabled + Découverte désactivée + + + + Download (KB/s) + Téléchargement (KB/s) + + + + Upload (KB/s) + Envoi (KB/s) + + + + + Network Configuration + Configuration du réseau + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + La DHT vous permet de répondre à la demande +de connection de vos amis en utilisant DHT BitTorrent. +Il améliore considérablement la connectivité. + +Le service de découverte envoie le nom de la machine et la clé GPG + de vos contacts de confiance aux autres pairs connectés +pour les aider à choisir de nouveaux amis. +L'amitié n'est jamais automatique, il faut que +les pairs se fassent mutuellement confiance pour permettre la connexion. + + + + Public: DHT & Discovery + Publique : DHT & Découverte + + + + Private: Discovery Only + Privé : Découverte only + + + + Inverted: DHT Only + Inversé : DHT seulement + + + + Dark Net: None + Dark Net : Aucun + + + + + kB/s + Ko/s + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + Si vous décochez cette case, RetroShare n'utilisera pas de tunnel de connexion entre les personnes se trouvant derrière un pare-feu et ne pourra donc pas se connecter correctement. Ceci est indépendant du routage F2F (Turtle Routing). + + + + Allow Tunnel Connection + Autoriser les tunnels de connexion + + + + Local Address + Adresse locale + + + + External Address + Adresse externe + + + + Dynamic DNS + Dynamic DNS + + + + Show Discovery information in statusbar + Montrer les informations de découverte dans la bar de statut + + + + IP Service + Service IP + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + Si vous décochez cette case, RetroShare ne pourra déterminer votre adresse IP +que si vous vous connectez à quelqu'un. Laisser cette case cochée vous aidera +à vous connecter si vous avez peu d'amis. Cela vous aidera aussi si vous êtes +derrière un pare-feu ou un VPN (Virtual Private Network). + + + + Allow RetroShare to ask my ip to these websites: + Autoriser RetroShare à récupérer mon adresse IP à partir de ces sites : + + + Network Status + Statut du réseau + + + No Conectivity + Aucune connectivité + + + Limited + Limité + + + Udp + Udp + + + Retroshare Server + Serveur RetroShare + + + UDP Connections + Connexions Udp + + + Stable External IP Addrress + Adresse IP Externe Stable + + + DHT Okay + DHT Ok + + + UPnP Active + UPnP actif + + + TCP server + Serveur TCP + + + Total Rate (KB/s) + Taux total (KB/s) + + + Per Person + Par personne + + + + Settings + + Settings + Paramètres + + + + Options + Options + + + + Transfer + Transferts + + + + Notify + Notifications + + + + Security + Sécurité + + + + Message + Messages + + + + Forum + Forums + + + + Chat + Chat + + + + Appearance + Apparence + + + + Sound + Sons + + + + Cancel + Annuler + + + Apply + Appliquer + + + + OK + OK + + + + General + Général + + + Network + Réseau + + + + Server + Serveur + + + + Directories + Repertoires + + + + ShareDialog + + + RetroShare Share Folder + RetroShare Dossier de partage + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Partage de dossier</span></p></body></html> + + + + Share Folder + Dossier partagé + + + + Local Path + Chemin d'accès local + + + + Browse + Parcourir + + + + Virtual Folder + Dossier virtuel + + + + Share Flags + Type de partage + + + + Browsable + Visibles + + + + Anonymous shared Network Wide + Partage anonyme + + + + Network Wide + Anonyme + + + Anonymous + Anonymes + + + + Browseable by Friends + Visible par mes amis + + + Friends + Amis + + + + OK + OK + + + + Cancel + Annuler + + + + Select A Folder To Share + Selectionnez un dossier à partager + + + + ShareKey + + + check peers you would like to share private publish key with + Visualiser les contacts avec qui vous partagez votre clé de publication privée + + + + Share Channel + Partager la Chaîne + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Partager la Chaîne</span></p></body></html> + + + + Share for Friend + Partager avec mes amis + + + + Contacts: + Contacts : + + + + Share + Partager + + + + Cancel + Annuler + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Sélectionnez les amis avec qui vous désirez partager votre Chaîne.</span></p></body></html> + + + + RetroShare + RetroShare + + + + Please select at least one peer + Veuillez sélectionner au moins un contact + + + + ShareManager + + + Add a Share Directory + Ajouter un dossier à partager + + + + Stop sharing selected Directory + Arrêter de partager le dossier selectionné + + + Select A Folder To Share + Selectionnez un dossier à partager + + + Do you really want to stop sharing this directory ? + Etes-vous vraiment certains de ne plus vouloir partager ce dossier ? + + + Remove selected Shared Directory + Supprimer la sélection du répertoire partagé + + + + + Remove + Supprimer + + + Add Shared Directory + Ajouter un dossier partagé + + + + If checked, the share is anonymously shared to anybody. + Si coché, le partage est anonyme avec tout le monde. + + + + If checked, the share is browsable by your friends. + Si coché, le partage est visible par vos amis. + + + + Warning! + Attention ! + + + + Do you really want to stop sharing this directory ? + Etes-vous certains de ne plus vouloir partager ce dossier ? + + + + + Drop file error. + Erreur lors de l'ajout du fichier. + + + + File can't be dropped, only directories are accepted. + On ne peut pas déposer un fichier, seuls les répertoires sont acceptés. + + + + Directory not found or directory name not accepted. + Le répertoire n'a pas été trouvé ou le nom du répertoire n'est pas accepté. + + + Shared Directory Added! + Dossier ajouté avec succès ! + + + Do You Want to Remove ? + Voulez-vous supprimer? + + + + RetroShare Share Manager + Gestionnaire de partages RetroShare + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#32cd32;">Share Manager</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"><span style=" font-size:10pt;">Add a new Folder to Share with your Friends or remove a Shared Folder.</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#32cd32;">Gestionnaire de partage</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"><span style=" font-size:10pt;">Ajoutez un nouveau Dossier à Partager avec vos Amis ou enlever un Dossier Partagé.</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Gestionnaire de partages</span></p></body></html> + + + + Shared Folder Manager + Gestionnaire de partages + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable </span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Voici votre liste de dossiers partagés. Vous pouvez ajouter ou supprimer de nouveaux dossiers en utilisant les boutons "Ajouter" et "Supprimer".</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Quand vous ajoutez un nouveau dossier, tous les fichiers présents dans ce dossier sont automatiquement partagés.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Vous pouvez paramétrer séparément la méthode de partage pour chaque dossier :</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Partages visibles </span><span style=" font-family:'Sans'; font-size:8pt;">: vos fichiers sont visibles par vos amis.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Partages anonymes </span><span style=" font-family:'Sans'; font-size:8pt;">: vos fichiers seront accessibles par n'importe qui par l'intermédiaire d'un Tunnel anaonyme.</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Voici la liste des dossiers partagés. Vous pouvez ajouter ou supprimer de nouveaux dossiers en utilisant les boutons "Ajouter" et "Supprimer".</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Quand vous ajoutez un nouveau dossier, tous les fichiers présents dans ce dossier sont partagés.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Vous pouvez paramétrer séparément la méthode de partage pour chacun des dossiers :</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Partage public</span><span style=" font-family:'Sans'; font-size:8pt;">: votre liste de fichiers est visible par vos amis.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Partage anonyme </span><span style=" font-family:'Sans'; font-size:8pt;">: vos fichiers seront accessibles par n'importe qui par l'intermédiaire d'un tunnel anonyme.</span></p></body></html> + + + + Directory + Répertoire + + + + Virtual Folder + Dossier virtuel + + + + Network Wide + Anonymes + + + + Browsable + Visibles + + + + Add + Ajouter + + + + Close + Fermer + + + + Edit selected Shared Directory + Modifier les dossiers partagés + + + + + Edit + Modifier + + + + SharedFilesDialog + + + + Download + Télécharger + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Fichiers</span></p></body></html> + + + Add to Recommend List + Ajouter à la liste des recommandations + + + Recommend To + Recommander à + + + Message Friend + Message ami + + + + + Open File + Ouvrir le fichier + + + + Open Folder + Ouvrir le dossier + + + + + Recommend in a message to + Recommender dans un message à + + + + + + RetroShare Link + Lien RetroShare + + + + + + + Recommendation(s) + Recommandation(s) + + + + Set command for opening this file + Définir une commande d'ouverture pour ce fichier + + + + Copy retroshare Link + Copier le lien RetroShare + + + + Checking... + Vérification en cours... + + + + Check files + Vérifier les fichiers + + + + Send retroshare Link + Evoyer un lien RetroShare + + + Recommend (Automated message) To + Recommender (Message automatique) à + + + Recommend in a message to + Recommender dans un message à + + + + Copy retroshare Links to Clipboard + Copier le lien RetroShare + + + + Copy retroshare Links to Clipboard (HTML) + Copier le lien RetroShare (HTML) + + + + Send retroshare Links + Evoyer le lien RetroShare + + + + Send retroshare Links (HTML) + Evoyer le lien RetroShare (HTML) + + + Send retroshare Links to Chat + Envoyer le lien RetroShare dans le Chat public + + + + Send retroshare Links to Cloud + Envoyer les liens RetroShare dans le nuage de liens + + + + Add Links to Cloud + Ajouter les liens RetroShare dans le nuage de liens + + + Send retroshare Link (html) + Envoyer le lien RetroShare (html) + + + Send retroshare Link to Chat + Envoyer le lien RetroShare dans le Chat public + + + Send retroshare Link to Cloud + Envoyer le lien RetroShare dans le nuage de liens + + + Add Link to Cloud + Ajouter le lien dans le nuage de liens + + + + <strong>My Shared Files</strong> + <strong>Mes fichiers partagés</strong> + + + + <strong>Friends Files</strong> + <strong>Les fichiers de mes amis</strong> + + + + <strong>Files</strong> + <strong>Fichiers</strong> + + + Friends Share + Partage des amis + + + My Shared Files + Mes fichiers partagés + + + + Splitted View + Vue partagée + + + + Friends Folders + Dossiers de mes amis + + + + My Folders + Mes dossiers + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Fichiers</span></p></body></html> + + + + All + Tout + + + + One day old + Agé d'un jour + + + + One Week old + Agé d'une semaine + + + + One month old + Agé d'un mois + + + + Search files + Rechercher des fichiers + + + + Start Search + Lancer la recherche + + + + Reset + Réinitialiser + + + + Tree view + Affichage en arborescence + + + + Flat view + Affichage à plat + + + + Download selected + Télécharger la sélection + + + + check files + Vérifier les fichiers + + + + SoundPage + + + Sound Events + Alerte sonore des événements + + + User + Utilisateur + + + + go Online + En-ligne + + + go Offline + Hors-ligne + + + ... + ... + + + + Friend + Ami + + + + + + + + Browse + Parcourir + + + + New Msg + Nouveau Message + + + + FileSend + Envoi d'un fichier + + + + + Finished + Terminé + + + + FileRecive + Réception d'un fichier + + + + Incoming + Entrant + + + + Chatmessage + Réception d'un Message + + + New + Nouveau + + + + SplashScreen + + + Load profile + Chargement du profil + + + + Load configuration + Chargement de la configuration + + + + Create interface + Création de l' interface + + + + StartDialog + + + RetroShare + RetroShare + + + Auto-login + Auto-login + + + Name: + Nom: + + + + Log In + Se connecter + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Create new Profile...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Créer un nouveau profil ou lieu...</span></a></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Information...</span></a></p></body></html> + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + Ouvre une boite de dialogue permettant de créer un nouveau profil ou +l'ajout d'un nouvel emplacements à un profil existant. +Les identités actuelles/emplacements seront sauvegardés. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Gestion des profils et des emplacements...</span></a></p></body></html> + + + + Name (GPG Id) - location: + Nom (ID PGP) - Emplacement : + + + + Remember Password + Se rappeler du mot de passe + + + Name - location: + Nom - Lieu : + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Connexion</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:10pt;">You can login with your Default</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">RetroShare profile.</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">You have a Profile?</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:10pt;">Vous pouvez vous connecter avec votre Default</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">RetroShare profil.</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">Vous avez un profil??</p></body></html> + + + Generate now a Profile + Générer un profil maintenant + + + generate now a profile + générer un profil maintenant + + + Password: + Mot de passe : + + + + + Multiple instances + Multiples instances + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile + Une autre instance de RetroShare utilise actuellement le même profil sur votre ordinateur. Veuillez tout d'abord fermer cette instance + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Une erreur inattendue s'est produite lorsque RetroShare a essayé d'acquérir le verrou d'instance unique + + + + Login Failure + La connexion a échoué + + + + Maybe password is wrong + Peut-être que le mot de passe est incorrect + + + Create a New Profile + Créer un nouveau profil + + + This will generate a new Profile + Are you sure you want to continue? + Ceci génèrera un nouveau profil. +Êtes-vous certain de vouloir continuer ? + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + Une autre instance de RetroShare utilise actuellement le même profil sur votre ordinateur. Veuillez tout d'abord fermer cette instance. +Fichier vérouillé : + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + Une erreur inattendue s'est produite lorsque RetroShare a essayé d'acquérir le verrou d'instance unique. + Fichier vérrouillé : + + + + + + Warning + Attention + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + Le mot de passe de votre certificat SSL (votre emplacement) sera crypté et stocké dans votre trousseau de clés GNOME. + + Votre mot de passe PGP ne sera pas conservé. + +Ce choix peut être modifié dans les paramètres de RetroShare. + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + Le mot de passe de votre certificat SSL (votre emplacement) sera crypté et stocké dans le fichier de clés /aide.dta. Ce n'est pas sécurisé. + + Votre mot de passe PGP ne sera pas conservé. + +Ce choix peut être modifié dans les paramètres. + + + Insecure + peu sûr + + + Auto Login is not so much secure: + - Your SSL certificate will be stored unprotected. + - Your PGP key will however not be stored. +This choice be reverted in settings. + La connection automatique est moins sûr : +....- Votre certificat SSL stocké est non protogé. +....- Cependant votre clé GPG n'est pas enregistrée. +Ce choix peut être modifié dans les préférences. + + + Create a New Profil + Créer un nouveau profil + + + This will generate a new Profile + Are you sure you want to continue + Ceci generera un nouveau profil. +Etes-vous certains de vouloir continuer ? + + + + StatisticDialog + + + Statistics + Statistiques + + + + Download + Téléchargement + + + + Session: + Session : + + + + + Downloaded: + Téléchargé : + + + Average Downloadspeed: + Vitesse moyenne de téléchargement: + + + + + Count of Downloads: + Nombre de téléchargements : + + + + + + Overall + Global + + + + Upload + Émission + + + + + + Session + Session + + + + Uploaded: + Emis : + + + Average Uploadspeed: + Vitesse moyenne d'émission: + + + + + Count of Uploads: + Nombre d'émission : + + + + Uploaded + Emis + + + + + + + Connections: + Connexions : + + + + + + Peers: + Contacts : + + + Misc + Misc + + + + Uptime: + Temps de travail : + + + Overall: + Overall: + + + + + Uptime + Temps de travail + + + + Records + Enregistrements + + + + Uploadspeed: + Vitesse d'émission : + + + + Downloadspeed: + Vitesse de téléchargement : + + + + + Show Settings + Affichez les paramètres + + + + Reset + Réinitialisation + + + + Receive Rate + Vitesse de réception + + + + Send Rate + Vitesse d'émission + + + + Always On Top + Toujours visible + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Changes the transparency of the Bandwidth Graph + Change la transparence du graphique de bande passante + + + + Save + Sauvegarder + + + + Cancel + Annuler + + + + Hide Settings + Cacher les paramètres + + + + %1 days + %1 jours + + + + Since: + Depuis : + + + + Now + Maintenant + + + + Transfer + Transfert + + + + Session UL:DL Ratio: + Ratio de la session (UL:DL) : + + + + Cumulative UL:DL Ratio + Ratio total (UL:DL) + + + + Time Statistics + Statistiques de temps + + + + Cumulative + Cumulatif + + + + StatusDefs + + + + Offline + Hors-ligne + + + + Away + Absent(e) + + + + Busy + Occupé(e) + + + + Online + En-ligne + + + + Idle + Inactif + + + + Friend is offline + Ami hors-ligne + + + + Friend is away + Ami absent + + + + Friend is busy + Ami occupé + + + + Friend is online + Ami en-ligne + + + + Friend is idle + Ami inactif + + + + Connected + Connecté + + + + Unreachable + Indisponible + + + + Available + Disponible + + + + Neighbour + Voisinage + + + + Trying tunnel connection + Tentative de connection tunnel + + + + Trying TCP + Tentative TCP + + + + Trying UDP + Tentative UDP + + + + Connected: TCP + Connecté : TCP + + + + Connected: UDP + Connecté : UDP + + + + Connected: Tunnel + Connecté : Tunnel + + + + Connected: Unknown + Connecté : Inconnu + + + + DHT: Contact + DHT : Connectée + + + + StatusMessage + + + Personal message + Message perso + + + + Status message + Message d'état + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Message perso</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Entrez votre message perso</span></p></body></html> + + + + OK + OK + + + + Cancel + Annuler + + + + Paste RetroShare Link + Coller le lien RetroShare + + + + StyleDialog + + + Define Style + Définir le style + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Définir le Style</span></p></body></html> + + + + + Choose color + Choix de la couleur + + + + Color 2 + Couleur 2 + + + + Color 1 + Couleur 1 + + + + Style + Style + + + + None + Aucune + + + + Solid + Solide + + + + Gradient + Dégradé + + + + SubDestItem + + Type + Type + + + Form + Formulaire + + + Person/Channel Name + Personne / Nom du canal + + + + Delete FeedItem + Supprimer le fil d'actualité + + + + SubFileItem + + File Name + Nom du fichier + + + + + ERROR + ERREUR + + + + EXTRA + EXTRA + + + + REMOTE + LOINTAIN + + + + DOWNLOAD + TELECHARGE + + + + LOCAL + LOCAL + + + + UPLOAD + ENVOI + + + + File %1 does not exist at location. + Le fichier %1 n'existe pas à cet endroit. + + + + File %1 is not completed. + Le fichier %1 est incomplet. + + + + Save Channel File + Enregistrer le fichier de la Chaîne + + + Form + Formulaire + + + + Download + Télécharger + + + + Play + Lire + + + + %p Kb + %p Ko + + + Expand + Développer + + + + Save File + Enregistrer le fichier + + + + Cancel Download + Annuler le téléchargement + + + + Download File + Télécharger le fichier + + + + + + Play File + Lecture + + + + TBoard + + + Pause + En pause + + + + TagDefs + + + Important + Important + + + + Work + Professionnel + + + + Personal + Personnel + + + + Todo + À faire + + + + Later + Plus tard + + + + TagsMenu + + + Remove All Tags + Supprimer tout les tags + + + + New tag ... + Nouveau tag... + + + + TextPage + + + Use text representation of the PGP certificates. + Utiliser la version texte du certificat PGP. + + + + The text below is your PGP certificate. You have to provide it to your friend + Le texte suivant est votre certificat PGP. Vous devez le fournir à vos amis + + + + Save your Cert into a File + Enregistrer votre certificat dans un fichier + + + + Please, paste your friends PGP certificate into the box below + Veuillez coller le certificat PGP de votre ami dans la case ci-dessous + + + + Clean certificate + Nettoyer le certificat + + + + RetroShare Invite + Invitation RetroShare + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + Votre certificat a été copié dans le presse-papiers, collez-le et envoyez-le par courrier electronique ou par tout autre moyen + + + Your Cert is copied to Clipboard, paste and send it to yourfriend via email or some other way + Votre certificat a été copié dans le presse-papiers, collez-le et envoyez-le par courrier electronique ou par tout autre moyen + + + + Save as... + Enregistrer sous... + + + + RetroShare Certificate (*.rsc );;All Files (*) + Certificat RetroShare (*.rsc);; Tous les fichiers (*) + + + + Copy your Cert to Clipboard + Copier le certificat dans le presse-papiers + + + + You can copy this text and send it to your friend via email or some other way + Vous pouvez copier votre certificat et l'envoyer à vos amis par courrier électronique ou par tout autre moyen + + + + RetroShare + RetroShare + + + + Text certificate + Certificat version texte + + + Use text representation of the XPGP certificates. + Utiliser la représentation de la XPGP certificats. + + + The text below is your XPGP certificate. You have to provide it to your friend + Le texte ci-dessous est votre XPGP certificat. Vous devez fournir à votre ami + + + + Run Email program + Envoyer par courrier électronique + + + Please, paste your friends XPGP certificate into the box below + S'il vous plaît, amis XPGP coller votre certificat dans la case ci-dessous + + + + Connect Friend Help + Aide pour l'envoi du certificat + + + You can copy this text and send it to your friend via email, ICQ or some other way + Vous pouvez copier ce texte et l'envoyer à votre ami par e-mail, ICQ ou d'une autre manière + + + + Certificate Load Failed + Le certificat n'a pas été chargé + + + + TransferPage + + Form + Formulaire + + + Transfer + Transfert + + + + Transfer options + Options du transfert + + + + Queue Size: + Taille de la file d'attente : + + + Maximum Download speed per file: + Vitesse de téléchargement par fichier : + + + kB/s + kB/s + + + + Default chunk strategy: + Mode de téléchargement : + + + + Safety disk space limit : + Limitation de l'espace disque de sécurité : + + + + Streaming + Streaming + + + + Random + Aléatoire + + + + MB + Mo + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> est capable de transférer des fichiers et effectuer des recherches entre personnes qui ne sont pas amies. Cependant, ce traffic se fait à travers une liste de contacts anonymes.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Vous pouvez paramétrer le type de partage dans la fenêtre de partage de dossier :</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Visible par mes amis</span>: les fichiers sont visibles par mes amis.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Partage anonyme</span>: les fichiers sont accessibles anonymement par des tunnels F2F.</li></ul></body></html> + + + Show Cache Transfers + Afficher le cache des transferts + + + F2F Routing + Routage F2F + + + Show router statistics + Afficher les statistiques de routage + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> est capable de transférer des données et des recherches entre contacts qui ne sont pas nécessairement amis. Toutefois, ces données ne font que transiter qu'à travers une liste d'amis connectés et est anonyme.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Vous pouvez spécifier des règles de partage séparément pour chaque dossier que vous partagez :</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Explorable par vos amis </span>: vos amis pourront voir vos fichiers partagés.</li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + TransfersDialog + + + Cancel + Annuler + + + + Clear Completed + Effacer les fichiers terminés de la liste + + + + + Status + Statut + + + + Completed + Terminé + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Réceptions:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Téléchargements :</span></p></body></html> + + + + Show cache transfers + Afficher le cache des transferts + + + + Uploads + Envois + + + + Selected transfer + Transfert sélectionné + + + + Done + Terminé + + + + Active + En cours + + + + Outstanding + En attente + + + Tunneling + Tunneling + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Émissions:</span></p></body></html> + + + + + Name + i.e: file name + Nom + + + + + Size + i.e: file size + Taille + + + Progress + i.e: % downloaded + Progression + + + + Speed + i.e: Download speed + Vitesse + + + + Progress / Availability + i.e: % downloaded + Progression/Disponibilité + + + + Sources + i.e: Sources + Sources + + + Remaining + i.e: Estimated Time of Arrival / Time left + Restant + + + + Core-ID + Core-ID + + + User Name + i.e: user name + Nom d'utilisateur + + + Speed / Queue priority + Vitesse / Priorité + + + + Remaining + Taille restante + + + + Download time + i.e: Estimated Time of Arrival / Time left + Temps restant estimé + + + + Peer + i.e: user name + Personne + + + + Progress + i.e: % uploaded + Progression + + + + Speed + i.e: upload speed + Vitesse + + + + Transferred + Transféré + + + + Play + Lecture + + + + Pause + Mettre en pause + + + + Resume + Reprendre + + + + Force Check + Forcer la vérification + + + + Open Folder + Ouvrir le répertoire de sortie + + + + Open File + Ouvrir le fichier + + + + Preview File + Prévisualiser + + + + Details... + Détails... + + + Copy retroshare Link + Copier le lien RetroShare + + + Paste retroshare Link + Coller le lien RetroShare + + + View + Affichage + + + + Move in Queue... + Mettre en file d'attente... + + + Remove all queued + Purger la file d'attente + + + + + Slower + Basse + + + + + + Average + Normale + + + + + Faster + Rapide + + + Priority (Queue) + Priorité (File d'attente) + + + Priority (Speed) + Priorité (Vitesse) + + + Low + Basse + + + + Hash + Hash + + + Normal + Normale + + + High + Haute + + + Auto + Automatique + + + + Streaming + Streaming + + + + Random + Aléatoire + + + + Chunk strategy + Méthode de téléchargement + + + + + + Failed + Echoué + + + + + + Okay + OK + + + + + Waiting + En attente + + + + Downloading + En cours de téléchargement + + + + + + + Complete + Terminé + + + + Unknown + Inconnu + + + + version: + Version : + + + + Queued + En file d'attente + + + + Speed / Queue position + Vitesse / Priorité + + + + Router Statistics + Statistiques de routage + + + + Router Requests + Requêtes de routage + + + + Copy RetroShare Link + Copier le lien RetroShare + + + + Paste RetroShare Link + Coller le lien RetroShare + + + + Down + Descendre + + + + Up + Remonter + + + + Top + En haut + + + + Bottom + En bas + + + + Priority (Speed)... + Priorité (Vitesse)... + + + + Paused + En pause + + + + Transferring + En cours de transfert + + + + Checking... + Vérification en cours... + + + + Uploading + En cours d'envoi + + + + RetroShare + RetroShare + + + + Details: + Détails : + + + + File preview + Prévisualiser + + + + File %1 preview failed. + La prévisualisation du fichier %1 a échoué. + + + + Open Transfer + Ouvrir le transfert + + + + File %1 is not completed. If it is a media file, try to preview it. + Le fichier %1 n'est pas terminé. Si c'est un fichier multimédia, essayez de le prévisualiser. + + + + Are you sure that you want to cancel and delete these files? + Etes-vous sûr de vouloir annuler et supprimer ces fichiers ? + + + + TreeStyle_RDM + + + + FILE + FICHIER + + + + Files + Fichiers + + + + File + Fichier + + + + + DIR + REP + + + + Friends Directories + Dossiers partagés de mes amis + + + + My Directories + Mes partages + + + + Size + Taille + + + + Age + Ancienneté + + + + Friend + Ami + + + + Share Type + Méthode de partage + + + + What's new + Quoi de neuf + + + + TrustView + + Form + Formulaire + + + + Zoom : + Zoom :. + + + + Update + Mise à jour + + + + + Showing: whole network + Affiché : réseau entier + + + + This table normaly auto-updates every 10 seconds. + La table se met automatiquement à jour toutes les 10 secondes. + + + + Self + Moi + + + + Trust + Confiance + + + is athenticated (one way) by + est authentifié ( un sens) par + + + athenticated himself + est authentifié par lui-même + + + athenticated each others + sont authentifiés mutuellement + + + is athenticated by + est authentifié par + + + athenticated + Authentifié + + + + is authenticated (one way) by + est authentifié(e) par + + + + Half + Moyenne + + + + authenticated himself + s'est authentifié(e) + + + + authenticated each other + sont authentifiés mutuellement + + + + Full + Totale + + + + + peers, including him(her)self. + personnes, dont lui(elle)-même. + + + + is authenticated by + est authentifié par + + + + authenticated + authentifié + + + + Showing: peers connected to + Affiché : personnes connectées à + + + + TurtleRouterDialog + + As a helper, you can manually remove hashes +from there. Warning: doing so on currently +active transfers will block the transfer process. + Pour vous aider, vous pouvez supprimer manuellement les hash +à partir d'ici. Attention : le faire durant un transfert actif +bloquera ce dernier. + + + Stop handling this hash + Arrêter le hash manuel + + + + + Search requests + Requêtes de recherche + + + + + Tunnel requests + Requpetes de tunnel + + + + TurtleRouterDialogForm + + + Router Statistics + Statistiques de routage + + + + F2F router information + Information de routage F2F + + + Hashes and Tunnels + Hashes et Tunnels + + + Handled file hashes + Fichiers hashés manuellement + + + File hash + Hachage de fichiers + + + File Name + Nom du fichier + + + Active tunnels + Tunnels actifs + + + Last tunnel request + Dernière requète de tunnel + + + Current tunnels + Tunnels actuels + + + Tunnel id + ID du tunnel + + + Handled file hash + Hash manuel du fichier + + + Current Tunnel id + ID du tunnel actif + + + Source + Source + + + Destination + Destination + + + Hash + Hash + + + Last transfer + Dernier transfert + + + Type + Type + + + Tunnels / Search Requests + Demande de Tunnels / Recherche + + + Tunnel Requests + Demande de Tunnel + + + Request id + Demande d'ID + + + Origin + Origine + + + Age + Age + + + Search Requests + Demande de recherches + + + + TurtleRouterStatistics + + + Router Statistics + Statistiques de routage + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + Traffic de Routage Turtle : + + + + Tunnel requests Up + Requêtes de Tunnel (Envoi) + + + + Tunnel requests Dn + Requêtes de Tunnel (Réception) + + + + Incoming file data + Données entrantes + + + + Outgoing file data + Données sortantes + + + + Forwarded data + Données transmises + + + + ULListDelegate + + + B + 1 Byte (B) = 1 Octet (o) + octet + + + + KB + Ko + + + + MB + Mo + + + + GB + Go + + + + VMessageBox + + + OK + OK + + + + Cancel + Annuler + + + + Yes + Oui + + + + No + Non + + + + Help + Aide + + + + Retry + Réessayer + + + + Show Log + Afficher le log + + + + Show Settings + Affichez les paramètres + + + + Continue + Continuer + + + + Quit + Quitter + + + + Browse + Parcourir + + + + misc + + + Unknown + Unknown (size) + Inconnue + + + + B + bytes + O + + + + KiB + kibibytes (1024 bytes) + Kio + + + + MiB + mebibytes (1024 kibibytes) + Mio + + + + GiB + gibibytes (1024 mibibytes) + Gio + + + + TiB + tebibytes (1024 gibibytes) + Tio + + + + Unknown + Inconnu + + + + < 1m + < 1 minute + < 1m + + + + %1 minutes + e.g: 10minutes + %1 minutes + + + + %1d %2h + e.g: 2days 10hours + %1d %2h + + + + %1y %2d + e.g: 2 years 2days + %1a %2j + + + + k + e.g: 3.1 k + k + + + + M + e.g: 3.1 M + M + + + + G + e.g: 3.1 G + G + + + + T + e.g: 3.1 T + T + + + %1y %1d %2h %3m + e.g: 2 years 2days 10hours 2minutes + %1A %1J %2h %3m + + + + %1h %2m + e.g: 3hours 5minutes + %1h %2m + + + %1d %2h %3m + e.g: 2days 10hours 2minutes + %1J %2h %3m + + + diff --git a/retroshare-gui/src/lang/retroshare_gr.qm b/retroshare-gui/src/lang/retroshare_gr.qm new file mode 100644 index 000000000..15fd0970f Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_gr.qm differ diff --git a/retroshare-gui/src/lang/retroshare_gr.ts b/retroshare-gui/src/lang/retroshare_gr.ts new file mode 100644 index 000000000..366278d54 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_gr.ts @@ -0,0 +1,13817 @@ + + + + + + + Arial + Arial + + + + @default + + Arial + Arial + + + + AboutDialog + + + About RetroShare + + + + + About + About + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + Retroshare + + + + Sorry, can't determine system default command for this file + + + + + + AddFileAssotiationDialog + + RetroShare + Retroshare + + + + AddFriendDialog + + Cancel + ακυρώνω + + + Done + καμωμένος + + + Load From File + γεμίζω από λίμα + + + RetroShare + Retroshare + + + Certificate Load Failed + πτυχίο γεμίζω αποτυχημένος + + + + AddFriendWizard + + Cancel + ακυρώνω + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Cancel + ακυρώνω + + + + Search + ερευνώ + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search Criteria + + + + + AppearanceDialog + + Language + Language + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + Style + Style + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + Style Sheet + Style Sheet + + + + AppearancePage + + + Language + Language + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + + Style + Style + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + + Style Sheet + Style Sheet + + + + ApplicationWindow + + + Hide + Hide + + + + Show + Show + + + + + RetroShare + Retroshare + + + Transfers + έμβασμα + + + Messages + μήνυμα + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + Statistics + + + + AttachFileItem + + + Form + + + + File Name + File Name + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + πιστοποιώ την αυθεντικότητα + + + Authenticate Friend By Entering Their Code + πιστοποιώ την αυθεντικότητα φίλος συν εισέρχομαι ο κρυπτογράφημα + + + OK + εγκρίνω OK + + + Cancel + ακυρώνω + + + + BandwidthGraph + + + + Show Settings + Show Settings + + + + Reset + Reset + + + + Receive Rate + Receive Rate + + + + Send Rate + Send Rate + + + + Style + Style + + + + Changes the transparency of the Bandwidth Graph + Changes the transparency of the Bandwidth Graph + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Save + Save + + + + Cancel + ακυρώνω + + + + Since: + + + + + Hide Settings + Hide Settings + + + + RetroShare Bandwidth Usage + + + + + Always on Top + + + + + BgWindow + + About + About + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + + + + + Close + λήξη + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + Name + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + Hide + + + + CalDialog + + + Remove + Remove + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + Select Certificate + + + Certificates (*.pqi *.pem) + Certificates (*.pqi *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + Retroshare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + Create a new Broadcast Channel + δημιουργώ καινούργιος αναμετάδοση κανάλι + + + Create A New Broadcast Channel + δημιουργώ καινούργιος αναμετάδοση κανάλι + + + Channel Name: + κανάλι όνομα: + + + Type: + τύπος: + + + Public Channel (Signed) + δημόσιος κανάλι (υπογράφω) + + + Private Channel (Encrypted) + απλός στρατιώτης κανάλι (κρύπτη) + + + Cancel Channel + ακυρώνω κανάλι + + + Create Channel + δημιουργώ κανάλι + + + + ChanMsgDialog + + Compose + συνθέτω + + + Recommended Files + συνιστώ λίμα + + + Send To: + στέλλω εις: + + + Send + στέλλω + + + Delete Channel + αφαιρώ κανάλι + + + Create Channel MSG + δημιουργώ κανάλι μήνυμα + + + File Name + File Name + + + Size + Size + + + Sources + Sources + + + Save + Save + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + Download + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Hide + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + κανάλι + + + Video + Video + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + τύπος + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + + + + + OK + + + + + Close + λήξη + + + + ChannelFeed + + + Create Channel + δημιουργώ κανάλι + + + + Subscribe To Channel + Subscribe To κανάλι + + + Title + τίτλος εφημερίδας + + + Reset + Reset + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + Name + Name + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChatDialog + + Chat + φιλική συζήτηση + + + Send + στέλλω + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + στέλλω + + + + Cancel + + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + Style + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + κατασκευή φίλος + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Cancel + ακυρώνω + + + Port: + Port: + + + Trust Settings + εμπιστοσύνη τοποθέτηση + + + Trust Level + εμπιστοσύνη αλφάδι + + + Trust Their Signature + εμπιστοσύνη από υπογραφή + + + Sign The Certificate + υπογράφω πτυχίο + + + + Details + Details + + + + Name + Name + + + + Loc + + + + + Peer Address + Peer Address + + + + Last Contact + Last Contact + + + Peer Details + Peer καθέκαστα + + + + Peer Info + + + + + Peer ID + + + + + Version + + + + + Addresses list + + + + + Apply and Close + + + + + + RetroShare + Retroshare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + None + + + + + Marginal + + + + + Full + + + + + Deny Friend + + + + + + Sign GPG key + + + + + Friend Details + + + + + RetroShare ID + + + + + Status + Status + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port + + + + + Your trust in this peer is: + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Make Friend + κατασκευή φίλος + + + + Certificate + + + + + OK + + + + + ConnectDialog + + Peer Details + Peer καθέκαστα + + + Make Friend + κατασκευή φίλος + + + Cancel + ακυρώνω + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + Name + + + + Description + + + + + Type: + τύπος: + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + Retroshare + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + Name + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + τύπος: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + Retroshare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Name + + + + Type: + τύπος: + + + + Authenticated Messages + + + + + Cancel + ακυρώνω + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Description + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Create + + + + + CreateForumMsg + + + Close + λήξη + + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + Retroshare + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + Retroshare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + CryptographyDialog + + RSA Key Size + RSA Key Size + + + Rijndael Block size + Rijndael Block size + + + 128 Bits + 128 Bits + + + 192 Bits + 192 Bits + + + 256 Bits + 256 Bits + + + Rijndael Key Size + Rijndael Key Size + + + Rijndael Mode + Rijndael Mode + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + Rijndael Padding + Rijndael Padding + + + PKCS7 + PKCS7 + + + Zeros + Zeros + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Rijndael Feedback Size + + + Key Size: + Key Size: + + + Block Size: + Block Size: + + + Feedback Size: + Feedback Size: + + + Mode: + Mode: + + + Padding: + Padding: + + + RetroShare + Retroshare + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Details + + + + + General + + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + τύπος: + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + + + + + Cancel + + + + + Rating + + + + + File Name + File Name + + + + Not Rated + + + + + No Comments + + + + + DirectoriesDialog + + Shared Directories + Shared Directories + + + Other Directories + Other Directories + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + + + Add Shared Directory + Add Shared Directory + + + + DirectoriesPage + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + Shared Directories + + + + Edit Share + + + + Incoming files + Incoming files + + + + + Browse + + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + λήξη + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + + Status + Status + + + + Person + Person + + + + Auto Connect + Auto Connect + + + + Trust Level + Trust Level + + + + Peer Address + Peer Address + + + + Last Contact + Last Contact + + + + Organisation + Organisation + + + + Location + Location + + + + Country + Country + + + + Person Id + Person ID + + + + Auth Code + αυθεντικότητα κρυπτογράφημα: + + + + # + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileHashDialog + + Download + Download + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + %1 KB + %1 KB + + + File Name + File Name + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + OK + + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + στέλλω + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + Misc + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + Hide + + + + Expand + + + + + + RetroShare + Retroshare + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + + Date + Date + + + + + Title + τίτλος εφημερίδας + + + + + Start New Thread + + + + New Message + καινούργιος μήνυμα + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + Reset + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + φιλική συζήτηση συν φίλος + + + + Status + Status + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + στέλλω + + + + Clear Chat History + + + + + + Add Friend + προσθέτω φίλος + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + Location + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + Connect To φίλος + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + Save Certificate + + + + Certificates (*.pqi) + Certificates (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + General + + + Network + Network + + + Directories + Directories + + + Server + Peer Settings + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Server + Peer Settings + + + + Status + Status + + + + Accept + Accept + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Retroshare setup + + + Load Trusted Certificate (Optional) + Load Trusted Certificate (Optional) + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + Name + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + Location + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + + + Select File + Select File + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + + + Generate New Certificate + Generate New Certificate + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + εκλεκτός έμπιστος φίλος + + + + Certificates (*.pqi *.pem) + Certificates (*.pqi *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + GeneralDialog + + Style + Style + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + Language + Language + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + Style Sheet + Style Sheet + + + Login + Login + + + Misc + Misc + + + + GeneralPage + + Keys manager + Keys manager + + + Style + Style + + + Choose RetroShare's interface style + Choose RetroShare's interface style + + + Language + Language + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + Choose the language used in RetroShare + Choose the language used in RetroShare + + + Login + Login + + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + Misc + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Recv: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Sent: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + φιλική συζήτηση συν φίλος + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + τίτλος εφημερίδας + + + + Description + + + + + Reset + Reset + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + Name + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + + + + + Size + + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + Search + ερευνώ + + + + Home + Home + + + + Close + λήξη + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + About + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + Reset + + + + + Copy + + + + + Remove + Remove + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + στέλλω + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + InviteDialog + + Done + καμωμένος + + + Cancel + ακυρώνω + + + Launch Email + εκτοξεύω Email + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + Download + + + + Expand + + + + + Hide + Hide + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + από + + + + Show + Show + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + LogDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> + +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +</body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table></body></html> + + + + MainWindow + + + Network + δικτυωτό + + + + Friends + φιλική συζήτηση συν φίλος + + + + + Transfers + έμβασμα + + + + + Messages + μήνυμα + + + + + Channels + κανάλι + + + + Blogs + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + Status + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + + + Options + δικαίωμα εκλογής + + + + Hide + Hide + + + + Show + Show + + + + RetroShare + Retroshare + + + Invite Friend + προσκαλώ φίλος + + + + MainWindow + + + + + Add Friend + προσθέτω φίλος + + + + Add a Friend Wizard + + + + + Add Share + προσθέτω μερίδα + + + + + Quick Start Wizard + + + + + Search + ερευνώ + + + + Files + λίμα + + + Add Shared Directory + προσθέτω μερίδα διευθηντήριο + + + + Show/Hide + + + + + &Quit + + + + + + + + You have %1 new message + + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Minimize + + + + + Maximize + + + + + Links Cloud + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Unfinished + + + + + Help + Help + + + + About + About + + + + + Forums + + + + + Open Messages + + + + + Applications + + + + Settings + Settings + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + Quit + + + + + SMPlayer + + + + + Messenger + + + + + MessageComposer + + + + Compose + συνθέτω + + + + + Contacts + + + + + Search for Name: + + + + + Reset + Reset + + + + Send To: + στέλλω εις: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + συνιστώ λίμα + + + + File Name + File Name + + + + Size + + + + Sources + Sources + + + + Hash + + + + + Send + στέλλω + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + Save + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + Retroshare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + Misc + Misc + + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + μήνυμα + + + New Message + καινούργιος μήνυμα + + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + λήξη + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">συνιστώ λίμα</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + File Name + + + + Size + + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + Download + + + + Download all + + + + + Hide + Hide + + + + Expand + + + + + File + + + + + Files + λίμα + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + καινούργιος μήνυμα + + + + Compose + συνθέτω + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + καινούργιος μήνυμα + + + + Quick View + + + + + Reply to Message + απαντώ εις μήνυμα + + + + Remove Message + μετακινώ μήνυμα + + + + + Date + χρονολογώ + + + + + + From + από + + + Size + μέγεθος + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">συνιστώ λίμα</span></p></body></html> + + + + Reply + + + + + Reply all + + + + + Foward + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + + + + Delete + + + + + Compose + συνθέτω + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + Reset + Reset + + + + Attachments + + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + Email-Inbox + + + + + + + Outbox + Email-Outbox + + + + Draft + νομοσχέδιο + + + + + Sent + Email-Sent + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">καινούργιος Email μήνυμα</p></body></html> + + + Download All + Download All + + + File Name + File Name + + + Sources + Sources + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + Download + + + + Empty trash + + + + Hide + Hide + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + Files + λίμα + + + + + + + + Total: + + + + + + Reply to All + + + + + + Subject + + + + + Print + + + + + MessagesPopupDialog + + New Message + καινούργιος μήνυμα + + + Reply to Message + απαντώ εις μήνυμα + + + Remove Message + μετακινώ μήνυμα + + + Messages + μήνυμα + + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Draft + νομοσχέδιο + + + Sent + Email-Sent + + + From + από + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">συνιστώ λίμα</span></p></body></html> + + + File Name + File Name + + + Sources + Sources + + + Compose + συνθέτω + + + Remove + Remove + + + + MessengerDirModel + + Rank + Rank + + + + MessengerSharedFiles + + Download + Download + + + + MessengerWindow + + + Expand all + + + + + Collapse all + + + + + Chat + ομάδα φιλική συζήτηση + + + + Message Friend + + + + + Connect To Friend + Connect To φίλος + + + + Peer Details + Peer καθέκαστα + + + + Recomend this Friend to... + + + + + Export Friend + Export φίλος + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + Save Certificate + + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Remove Friend + Remove φίλος + + + + Click to Change your Avatar + + + + + Search Friends + + + + + Reset + Reset + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Sent + Email-Sent + + + Date + Date + + + + MsgItem + + + Reply to Message + απαντώ εις μήνυμα + + + + Remove Item + + + + + + Expand + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Hide + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">μήνυμα</span></p></body></html> + + + Date + Date + + + Rank + Rank + + + From + από + + + Title + τίτλος εφημερίδας + + + Size + Size + + + Type + τύπος + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;"> μήνυμα κείμενο</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">συνιστώ λίμα</span></p></body></html> + + + Delete Channel + αφαιρώ κανάλι + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">μήνυμα</span></p></body></html> + + + Date + Date + + + Rank + Rank + + + From + από + + + Title + τίτλος εφημερίδας + + + Size + Size + + + Type + τύπος + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;"> μήνυμα κείμενο</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">συνιστώ λίμα</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + γεμίζω πτυχίο + + + Select a pem/pqi File + Select a pem/pqi File + + + File Not Found + File Not Found + + + %1 does not exist. Would you like to create it? + %1 does not exist. Would you like to create it? + + + Failed to Create File + Failed to Create File + + + Unable to create %1 [%2] + Unable to create %1 [%2] + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + Select Certificate + Select Certificate + + + Certificates (*.pqi *.pem) + Certificates (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + + + Accept + Accept + + + Trust + εμπιστοσύνη + + + Last Contact + Last Contact + + + + + + Name + Name + + + Peer Address + Peer Address + + + Organisation + Organisation + + + Location + Location + + + Country + Country + + + + + Cert Id + Cert Id + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Unknown + + + + + yourself + + + + RetroShare + Retroshare + + + + Network + + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + προσθέτω φίλος + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + Rate Options + + + Max Total Data Rate (KB/S): + Your maximum upload speed (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Hide Settings + + + Show Settings + Show Settings + + + Settings + Settings + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + φιλική συζήτηση συν φίλος + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Remove All + + + + Options + + + + + NotifyDialog + + Channels + κανάλι + + + Messages + μήνυμα + + + New Message + καινούργιος μήνυμα + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + κανάλι + + + + Forums + + + + + Chat + + + + + Blogs + + + + + Messages + μήνυμα + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + καινούργιος μήνυμα + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + OptionsDlg + + Cancel + ακυρώνω + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + Make Friend + κατασκευή φίλος + + + Remove Friend + Remove φίλος + + + + Chat + ομάδα φιλική συζήτηση + + + + Start Chat + + + + Organisation + Organisation + + + + Location + Location + + + Country + Country + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Send + στέλλω + + + + Cancel + + + + + Peer ID: + + + + + Write Message + + + + + Status: + + + + + Trust: + + + + + Name: + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + Hide + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + φιλική συζήτηση συν φίλος + + + + PeersDialog + + Chat + φιλική συζήτηση + + + Export Friend + Export φίλος + + + Remove Friend + Remove φίλος + + + Save Certificate + Save Certificate + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Status + Status + + + Person + Person + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + Connect To Friend + Connect To φίλος + + + Location + Location + + + Peer Details + Peer καθέκαστα + + + RetroShare + Retroshare + + + Send + στέλλω + + + Add Friend + προσθέτω φίλος + + + Friends + φιλική συζήτηση συν φίλος + + + + PeersFeed + + Save Certificate + Save Certificate + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Friends + φιλική συζήτηση συν φίλος + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Remove + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + + Date + Date + + + + + Location + Location + + + + Size + Size + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + Remove + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + RetroShare + Retroshare + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + στέλλω + + + + Close + λήξη + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + Retroshare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Directories + Directories + + + Error Saving Configuration + Error Saving Configuration + + + General + About + + + Server + Peer Settings + + + Options + Options + + + Cancel + Cancel + + + OK + OK + + + Help + Help + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + Download όλως + + + + RetroShare + Retroshare + + + + Error : cannot get peer details. + + + + + + Name + Name + + + + Peer ID + + + + + Size + Size + + + + Profile View + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + Name + Name + + + Date + Date + + + Size + Size + + + + + RetroShare + Retroshare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + Remove + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + + + + + Directories + Directories + + + + Server + Peer Settings + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Error Saving Configuration + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RemoteDirModel + + Rank + Rank + + + Files + λίμα + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Invalid language code specified: + + + + Invalid GUI style specified: + Invalid GUI style specified: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + Sources + + + + Results + Results + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + Download + + + + Enter a keyword here (at least 3 char long) + + + + Broadcast on Channel + Broadcast on Channel + + + Recommend to Friends + Recommend to Friends + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + Remove + + + + Remove All + Remove All + + + + + Folder + + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + + Any + Any + + + + Audio + Audio + + + + Video + Video + + + Images + Images + + + Programs + Programs + + + Archives + Archives + + + Documents + Documents + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Size + Size + + + + Type + τύπος + + + + Archive + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + File Name + + + + File Size + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + ερευνώ + + + + Reset + Reset + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Search Id + + + + + SendLinkDialog + + Send + στέλλω + + + + ServerDialog + + Transfer Rates + Transfer Rates + + + Port: + Port: + + + + ServerPage + + Change + Restart Server + Change + Restart + + + Server Settings + Peer Settings + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Download (KB/s) + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + Port: + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + Misc + Misc + + + behinde Firewall + Behind a Firewall + + + Forwarded External Port + Forwarded External Port (Router) + + + + Transfer Rates + Transfer Rates + + + + Settings + + Settings + Settings + + + + Options + + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + Cancel + Cancel + + + Apply + Apply + + + + OK + OK + + + + General + General + + + Network + Network + + + + Server + Peer Settings + + + + Directories + Directories + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + Friends + φιλική συζήτηση συν φίλος + + + + OK + + + + + Cancel + + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + Retroshare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + Remove + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + λήξη + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Download + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + Reset + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + Retroshare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + Statistics + + + + Download + Download + + + + Session: + Session: + + + + + Downloaded: + Downloaded: + + + Average Downloadspeed: + Average Downloadspeed: + + + + + Count of Downloads: + Count of Downloads: + + + + + + Overall + Overall + + + + Upload + Upload + + + + + + Session + Session + + + + Uploaded: + Uploaded: + + + Average Uploadspeed: + Average Uploadspeed: + + + + + Count of Uploads: + Count of Uploads: + + + + Uploaded + Uploaded + + + + + + + Connections: + Connections: + + + + + + Peers: + Peers: + + + Misc + Misc + + + + Uptime: + Uptime: + + + Overall: + Overall: + + + + + Uptime + Uptime + + + + Records + Records + + + + Uploadspeed: + Uploadspeed: + + + + Downloadspeed: + Downloadspeed: + + + + + Show Settings + Show Settings + + + + Reset + Reset + + + + Receive Rate + Receive Rate + + + + Send Rate + Send Rate + + + + Always On Top + Always On Top + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Changes the transparency of the Bandwidth Graph + Changes the transparency of the Bandwidth Graph + + + + Save + Save + + + + Cancel + Cancel + + + + Hide Settings + Hide Settings + + + + %1 days + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Since: + + + + + Cumulative + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + + + + + Cancel + + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + Style + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + τύπος + + + + Delete FeedItem + + + + + SubFileItem + + File Name + File Name + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + Download + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + Retroshare + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + πτυχίο γεμίζω αποτυχημένος + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Cancel + + + + Clear Completed + Clear Completed + + + + + Status + Status + + + + Completed + Completed + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + καμωμένος + + + + Active + + + + + Outstanding + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + + + + + Name + i.e: file name + Name + + + + + Size + i.e: file size + Size + + + Progress + i.e: % downloaded + Progress + + + + Speed + i.e: Download speed + Speed + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + Sources + + + + Core-ID + + + + + Progress + i.e: % uploaded + Progress + + + + Speed + i.e: upload speed + Speed + + + + Transferred + + + + + Hash + + + + + Play + + + + + Pause + + + + + Resume + + + + + Force Check + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Priority (Speed)... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + Queued + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + Retroshare + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Peer + i.e: user name + + + + + Router Statistics + + + + + Router Requests + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Move in Queue... + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + version: + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + λίμα + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + εμπιστοσύνη + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + File Name + File Name + + + Type + τύπος + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Download + Download + + + Broadcast on Channel + Broadcast on Channel + + + Recommend to Friends + Recommend to Friends + + + Remove + Remove + + + Remove All + Remove All + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + Any + Any + + + Audio + Audio + + + Video + Video + + + Sources + Sources + + + Type + τύπος + + + Results + Results + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + OK + + + + Cancel + Cancel + + + + Yes + Yes + + + + No + No + + + + Help + Help + + + + Retry + Retry + + + + Show Log + Show Log + + + + Show Settings + Show Settings + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Details + Details + + + OK + OK + + + Name + Name + + + Value + Value + + + diff --git a/retroshare-gui/src/lang/retroshare_it.qm b/retroshare-gui/src/lang/retroshare_it.qm new file mode 100644 index 000000000..6a8b209d5 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_it.qm differ diff --git a/retroshare-gui/src/lang/retroshare_it.ts b/retroshare-gui/src/lang/retroshare_it.ts new file mode 100644 index 000000000..70f0b21f7 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_it.ts @@ -0,0 +1,13607 @@ + + + + + + + Arial + Arial + + + + @default + + Arial + Arial + + + + AboutDialog + + + About RetroShare + + + + + About + About + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + Retroshare + + + + Sorry, can't determine system default command for this file + + + + + + AddFileAssotiationDialog + + RetroShare + Retroshare + + + + AddFriendDialog + + Cancel + Annullamento + + + Done + Fatto + + + Load From File + Carico dalla lima + + + RetroShare + Retroshare + + + Certificate Load Failed + Il carico del certificato è venuto a mancare + + + + AddFriendWizard + + Cancel + Annullamento + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Cancel + Annullamento + + + + Search + Ricerca + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search Criteria + + + + + AppearanceDialog + + Language + Lingua + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Scegliere la lingua usata in Retroshare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I cambiamenti alla lingua entreranno in vigore soltanto dopo il nuovo inizio del Retroshare!</p></body></html> + + + Style + Stile + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose Retroshare's interface style</p></body></html> + + + Style Sheet + Foglio di stile + + + + AppearancePage + + + Language + Lingua + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Scegliere la lingua usata in Retroshare</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I cambiamenti alla lingua entreranno in vigore soltanto dopo il nuovo inizio del Retroshare!</p></body></html> + + + + Style + Stile + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose Retroshare's interface style</p></body></html> + + + + Style Sheet + Foglio di stile + + + + ApplicationWindow + + + Hide + Pellame + + + + Show + Esposizione + + + + + RetroShare + Retroshare + + + Transfers + Trasferimenti + + + Messages + Email + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + Statistiche + + + + AttachFileItem + + + Form + + + + File Name + Nome di lima + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + Autenticare + + + Authenticate Friend By Entering Their Code + Autenticare l'amico impostando il codice + + + OK + OK + + + Cancel + Annullamento + + + + BandwidthGraph + + + + Show Settings + + + + + Reset + Risistemazione + + + + Receive Rate + Receive Rate + + + + Send Rate + Send Rate + + + + Style + Stile + + + + Changes the transparency of the Bandwidth Graph + Cambia l'acetato del grafico di larghezza di banda + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Save + Risparmi + + + + Cancel + Annullamento + + + + Since: + + + + + Hide Settings + Regolazioni del pellame + + + + RetroShare Bandwidth Usage + + + + + Always on Top + + + + + BgWindow + + Options + Opzioni + + + About + About + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + OK + + + + Close + Fine + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + Nome + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + Pellame + + + + CalDialog + + + Remove + Rimuovere + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + Selezionare il certificato + + + Certificates (*.pqi *.pem) + Certificati (*.pqi *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + Retroshare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + Create a new Broadcast Channel + Generare una nuova Manica di radiodiffusione + + + Create A New Broadcast Channel + Generare una nuova Manica di radiodiffusione + + + Channel Name: + Nome della Manica: + + + Type: + Tipo: + + + Public Channel (Signed) + Manica pubblica (firmata) + + + Private Channel (Encrypted) + Manica riservata (cifrata) + + + Cancel Channel + Annullare la Manica + + + Create Channel + Generare la Manica + + + + ChanMsgDialog + + Compose + Comporre + + + Recommended Files + Lime suggerite + + + Send To: + Trasmettere a: + + + Send + Trasmettere + + + Delete Channel + Manica di cancellazione + + + Create Channel MSG + Generare il messaggio della Manica + + + File Name + Nome di lima + + + Size + Formato + + + Sources + Fonti + + + Save + Risparmi + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Pellame + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + Scanalature + + + Video + Video + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + Tipo + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + + + + + OK + OK + + + + Close + Fine + + + + ChannelFeed + + + Create Channel + Generare la Manica + + + + Subscribe To Channel + Abbonar alla Manica + + + Reset + Risistemazione + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + Name + Nome + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChatDialog + + Chat + Chiacchierata + + + Send + Trasmettere + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + Trasmettere + + + + Cancel + + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + Generalità + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + Stile + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + Fare l'amico + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + Opzioni + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Cancel + Annullamento + + + Port: + Orificio: + + + Trust Settings + Regolazioni di fiducia + + + Trust Level + Livello di fiducia + + + Trust Their Signature + Fidar della firma + + + Sign The Certificate + Firmare il certificato + + + + OK + OK + + + + Details + Particolari + + + + Name + Nome + + + + Loc + + + + + Peer Address + Indirizzo del pari + + + + Last Contact + Ultimo contatto + + + Peer Details + Particolari del pari + + + + Peer Info + + + + + Peer ID + + + + + Version + + + + + RetroShare ID + + + + + Status + Condizione + + + + Dynamic DNS + + + + + Addresses list + + + + + None + + + + + Marginal + + + + + Full + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Deny Friend + + + + + Make Friend + Fare l'amico + + + + Certificate + + + + + + Sign GPG key + + + + + Friend Details + + + + + Local Address + + + + + External Address + + + + + + Port + + + + + Your trust in this peer is: + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + Apply and Close + + + + + + RetroShare + Retroshare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + ConnectDialog + + Peer Details + Particolari del pari + + + Make Friend + Fare l'amico + + + Cancel + Annullamento + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + Nome + + + + Description + + + + + Type: + Tipo: + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + Retroshare + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + Nome + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + Tipo: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + Retroshare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Nome + + + + Type: + Tipo: + + + + Authenticated Messages + + + + + Cancel + Annullamento + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Description + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Create + + + + + CreateForumMsg + + + Close + Fine + + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + Retroshare + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + Retroshare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + CryptographyDialog + + RSA Key Size + RSA Key Size + + + Rijndael Block size + Rijndael Block size + + + 128 Bits + 128 Bits + + + 192 Bits + 192 Bits + + + 256 Bits + 256 Bits + + + Rijndael Key Size + Rijndael Key Size + + + Rijndael Mode + Rijndael Mode + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + Rijndael Padding + Rijndael Padding + + + PKCS7 + PKCS7 + + + Zeros + Zeros + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Rijndael Feedback Size + + + Key Size: + Formato chiave: + + + Block Size: + Formato di blocco: + + + Feedback Size: + Formato di risposte: + + + Mode: + Modo: + + + Padding: + Padding: + + + RetroShare + Retroshare + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Particolari + + + + + General + Generalità + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + Tipo: + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + Data + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + OK + + + + Cancel + + + + + Rating + + + + + File Name + Nome di lima + + + + Not Rated + + + + + No Comments + + + + + DirectoriesDialog + + Shared Directories + Indici comuni + + + Other Directories + Altri indici + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Lime ricevute</span></p></body></html> + + + Add Shared Directory + Aggiungere l'indice comune + + + + DirectoriesPage + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + Indici comuni + + + + Edit Share + + + + Incoming files + Lime ricevute + + + + + Browse + + + + Add Shared Directory + Aggiungere l'indice comune + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + Fine + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + OK + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + + + + + OK + OK + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Amici</span></p></body></html> + + + + Status + Condizione + + + + Person + Persona + + + + Auto Connect + Collegare automaticamente + + + + Trust Level + Livello di fiducia + + + + Peer Address + Indirizzo del pari + + + + Last Contact + Ultimo contatto + + + + Organisation + Organizzazione + + + + Location + Posizione + + + + Country + Paese + + + + Person Id + ID di persona + + + + Auth Code + Codice di aut + + + + # + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileHashDialog + + Download + Download Trasferimento + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + %1 KB + %1 KB + + + File Name + Nome di lima + + + Size + Formato + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + Formato + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + OK + OK + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + Trasmettere + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + Misc + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + Pellame + + + + Expand + + + + + + RetroShare + Retroshare + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + + Date + Data + + + + + Start New Thread + + + + New Message + Nuovo messaggio + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Title + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + Risistemazione + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + Messaggio un amico + + + + Status + Condizione + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + Trasmettere + + + + Clear Chat History + + + + + + Add Friend + Aggiungere l'amico + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + Posizione + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + Collegare all'amico + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + Risparmi il certificato + + + + Certificates (*.pqi) + Certificati (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + Generalità + + + Network + Rete + + + Directories + Indici + + + Server + Peer Regolazioni + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Status + Condizione + + + + Accept + Accettare + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Messa a punto di Retroshare + + + Load Trusted Certificate (Optional) + Il carico si è fidato del certificato (facoltativo) + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + Nome + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + Posizione + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Amico</span></p></body></html> + + + Select File + Selezionare la lima + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nome:</p></body></html> + + + Generate New Certificate + Generare il nuovo certificato + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + Selezionare l'amico di fiducia + + + + Certificates (*.pqi *.pem) + Certificati (*.pqi *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + GeneralDialog + + Style + Stile + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose Retroshare's interface style</p></body></html> + + + Language + Lingua + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Scegliere la lingua usata in Retroshare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I cambiamenti alla lingua entreranno in vigore soltanto dopo il nuovo inizio del Retroshare!</p></body></html> + + + Style Sheet + Foglio di stile + + + Login + Inizio attività (Login) + + + Misc + Misc + + + + GeneralPage + + Keys manager + Chiude a chiave il responsabile + + + Style + Stile + + + Choose RetroShare's interface style + Scegliere lo stile dell'interfaccia del Retroshare + + + Language + Lingua + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">I cambiamenti alla lingua entreranno in vigore soltanto dopo il nuovo inizio del Retroshare!</p></body></html> + + + Choose the language used in RetroShare + Scegliere la lingua usata in Retroshare + + + Login + Inizio attività (Login) + + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + Misc + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Recv: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Sent: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Messaggio un amico + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + + + + + Description + + + + + Reset + Risistemazione + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + Nome + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + Data + + + + Size + Formato + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + Search + Ricerca + + + + Home + Domestico + + + + Close + Fine + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + About + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + Risistemazione + + + + + Copy + + + + + Remove + Rimuovere + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + Trasmettere + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + InviteDialog + + Done + Fatto + + + Cancel + Annullamento + + + Launch Email + Email convenzionale del lancio + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + + + + + Expand + + + + + Hide + Pellame + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + Da + + + + Show + Esposizione + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + MainWindow + + + Network + Regolazioni della rete + + + + Friends + Messaggio un amico + + + + + Transfers + Trasferimenti + + + + + Messages + Email + + + + + Channels + Scanalature + + + + Blogs + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + Condizione + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + + + Options + Opzioni + + + + Hide + Pellame + + + + Show + Esposizione + + + + RetroShare + Retroshare + + + Invite Friend + Invitare l'amico + + + + MainWindow + + + + + Add Friend + Aggiungere l'amico + + + + Add a Friend Wizard + + + + + Add Share + Aggiungere la parte + + + + + Quick Start Wizard + + + + + Search + Ricerca + + + + Files + Lime + + + Add Shared Directory + Aggiungere l'indice comune + + + + Show/Hide + + + + + &Quit + + + + + + + + You have %1 new message + + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Minimize + + + + + Maximize + + + + + Links Cloud + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Unfinished + + + + + Help + Aiuto + + + + About + About + + + + + Forums + + + + + Open Messages + + + + + Applications + + + + Settings + Regolazioni + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + Quit + + + + + SMPlayer + + + + + Messenger + + + + + MessageComposer + + + + Compose + Comporre + + + + + Contacts + + + + + Search for Name: + + + + + Reset + Risistemazione + + + + Send To: + Trasmettere a: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + Lime suggerite + + + + File Name + Nome di lima + + + + Size + Formato + + + Sources + Fonti + + + + Hash + + + + + Send + Trasmettere + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + Risparmi + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + Retroshare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + Misc + Misc + + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + messaggio + + + New Message + Nuovo messaggio + + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + Fine + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Lime suggerite</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + Nome di lima + + + + Size + Formato + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + + + + + Download all + + + + + Hide + Pellame + + + + Expand + + + + + File + + + + + Files + Lime + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + Nuovo messaggio + + + + Compose + Comporre + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + Nuovo messaggio + + + + Quick View + + + + + Reply to Message + Risposta al messaggio + + + + Remove Message + Rimuovere il messaggio + + + + + Date + Data + + + + + + From + Da + + + Size + Formato + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Lime suggerite</span></p></body></html> + + + + Reply + + + + + Reply all + + + + + Foward + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">rimuovere il messaggio selezionato</p></body></html> + + + + Delete + + + + + Compose + Comporre + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + Reset + Risistemazione + + + + Attachments + + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + Email-Inbox + + + + + + + Outbox + Email-Outbox + + + + Draft + Brutta copia + + + + + Sent + Email-Sent + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">risposta al messaggio selezionato</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nuovo messaggio</p></body></html> + + + Download All + Download All: Trasferire tutti dal sistema centrale verso i satelliti + + + File Name + Nome di lima + + + Sources + Fonti + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + + Empty trash + + + + Hide + Pellame + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + Files + Lime + + + + + + + + Total: + + + + + + Reply to All + + + + + + Subject + + + + + Print + + + + + MessagesPopupDialog + + New Message + Nuovo messaggio + + + Reply to Message + Risposta al messaggio + + + Remove Message + Rimuovere il messaggio + + + Messages + Email + + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Draft + Brutta copia + + + Sent + Email-Sent + + + From + Da + + + Date + Data + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Lime suggerite</span></p></body></html> + + + File Name + Nome di lima + + + Size + Formato + + + Sources + Fonti + + + Compose + Comporre + + + Remove + Rimuovere + + + + MessengerDirModel + + Size + Formato + + + Rank + Rank + + + + MessengerWindow + + + Expand all + + + + + Collapse all + + + + + Chat + Chiacchierata del gruppo + + + + Message Friend + + + + + Connect To Friend + Collegare all'amico + + + + Peer Details + Particolari del pari + + + + Recomend this Friend to... + + + + + Export Friend + Amico dell'esportazione + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + Risparmi il certificato + + + + Certificates (*.pqi) + Certificati (*.pqi) + + + Remove Friend + Rimuovere l'amico + + + + Click to Change your Avatar + + + + + Search Friends + + + + + Reset + Risistemazione + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Sent + Email-Sent + + + Date + Data + + + + MsgItem + + + Reply to Message + Risposta al messaggio + + + + Remove Item + + + + + + Expand + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Pellame + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messaggi</span></p></body></html> + + + Date + Data + + + Rank + Rank + + + From + Da + + + Msg + Messaggio + + + Size + Formato + + + Type + Tipo + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Testo del messaggio</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Lime suggerite</span></p></body></html> + + + Delete Channel + Manica di cancellazione + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messaggi</span></p></body></html> + + + Date + Data + + + Rank + Rank + + + From + Da + + + Msg + Messaggio + + + Size + Formato + + + Type + Tipo + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Testo del messaggio</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Lime suggerite</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + Certificato del carico + + + Select a pem/pqi File + Selezionare una lima PEM/PQI + + + File Not Found + Lima non trovata + + + %1 does not exist. Would you like to create it? + %1 non esistono. gradite generarli? + + + Failed to Create File + Non è riuscito a generare la lima. + + + Unable to create %1 [%2] + Incapace generare %1 [%2] + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + Select Certificate + Selezionare il certificato + + + Certificates (*.pqi *.pem) + Certificati (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Rete:</span></p></body></html> + + + Accept + Accettare + + + Trust + Fiducia + + + Last Contact + Ultimo contatto + + + + + + Name + Nome + + + Peer Address + Indirizzo del pari + + + Organisation + Organizzazione + + + Location + Posizione + + + Country + Paese + + + + + Cert Id + ID di cert + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Unknown + + + + + yourself + + + + RetroShare + Retroshare + + + + Network + + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + Aggiungere l'amico + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + opzioni di velocità + + + Max Total Data Rate (KB/S): + La vostra velocità massima di upload (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Velocità a persona (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Regolazioni del pellame + + + Settings + Regolazioni + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Messaggio un amico + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + OK + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Rimuovere tutti + + + + Options + Opzioni + + + + NotifyDialog + + Channels + Scanalature + + + Messages + Email + + + New Message + Nuovo messaggio + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + Scanalature + + + + Forums + + + + + Chat + + + + + Blogs + + + + + Messages + Email + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + Nuovo messaggio + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + OptionsDlg + + Cancel + Annullamento + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + Make Friend + Fare l'amico + + + Remove Friend + Rimuovere l'amico + + + + Chat + Chiacchierata del gruppo + + + + Start Chat + + + + Organisation + Organizzazione + + + + Location + Posizione + + + Country + Paese + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Send + Trasmettere + + + + Cancel + + + + + Peer ID: + + + + + Write Message + + + + + Status: + + + + + Trust: + + + + + Name: + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + Pellame + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Messaggio un amico + + + + PeersDialog + + Chat + Chiacchierata + + + Export Friend + Amico dell'esportazione + + + Remove Friend + Rimuovere l'amico + + + Save Certificate + Risparmi il certificato + + + Certificates (*.pqi) + Certificati (*.pqi) + + + Status + Condizione + + + Person + Persona + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Amici</span></p></body></html> + + + Connect To Friend + Collegare all'amico + + + Location + Posizione + + + Peer Details + Particolari del pari + + + RetroShare + Retroshare + + + Send + Trasmettere + + + Add Friend + Aggiungere l'amico + + + Friends + Messaggio un amico + + + + PeersFeed + + Save Certificate + Risparmi il certificato + + + Certificates (*.pqi) + Certificati (*.pqi) + + + Friends + Messaggio un amico + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Rimuovere + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + + Date + Data + + + + + Location + Posizione + + + + Size + Formato + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + Rimuovere + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + RetroShare + Retroshare + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + Trasmettere + + + + Close + Fine + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + Retroshare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Directories + Indici + + + Error Saving Configuration + Configurazione di Saving di errore + + + General + Generalità + + + Server + Regolazioni del Peer + + + Options + Opzioni + + + Cancel + Annullamento + + + OK + OK + + + Help + Aiuto + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + Trasferire tutti dal sistema centrale verso i satelliti + + + + RetroShare + Retroshare + + + + Error : cannot get peer details. + + + + + + Name + Nome + + + + Peer ID + + + + + Size + Formato + + + + Profile View + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + Name + Nome + + + Date + Data + + + Size + Formato + + + + + RetroShare + Retroshare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + Rimuovere + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + Generalità + + + + Directories + Indici + + + + Server + + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Configurazione di Saving di errore + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RemoteDirModel + + Size + Formato + + + Rank + Rank + + + Files + Lime + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Codice non valido di lingua specificato: + + + + Invalid GUI style specified: + Lo stile non valido del GUI ha specificato: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + Fonti + + + + Results + Risultati + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + Download Trasferimento + + + + Enter a keyword here (at least 3 char long) + + + + Broadcast on Channel + Radiodiffusione sulla Manica + + + Recommend to Friends + Suggerire agli amici + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + Rimuovere + + + + Remove All + Rimuovere tutti + + + + + Folder + + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Disposizione</p></body></html> + + + + Any + C'è ne + + + + Audio + Audio + + + + Video + Video + + + Images + Immagini + + + Programs + Programmi + + + Archives + Archivi + + + Documents + Documenti + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Size + Formato + + + + Type + Tipo + + + + Archive + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + Nome di lima + + + + File Size + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + Ricerca + + + + Reset + Risistemazione + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Search Id + + + + + SendLinkDialog + + Send + Trasmettere + + + + ServerDialog + + Transfer Rates + Transfer Rates + + + Port: + Orificio: + + + + ServerPage + + Change + Restart Server + Cambiamento + riavviamento + + + Server Settings + Regolazioni del Peer + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Indirizzo esterno:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Adress locale:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Orificio:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Download (KB/s) + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + Orificio: + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + Misc + Misc + + + behinde Firewall + Dietro una parete refrattaria (Firewall) + + + Forwarded External Port + Orificio esterno spedito (Router) + + + + Transfer Rates + Transfer Rates + + + + Settings + + Settings + Regolazioni + + + + Options + Opzioni + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + Cancel + Annullamento + + + Apply + Applicar + + + + OK + OK + + + + General + Generalità + + + Network + Rete + + + + Server + Peer + + + + Directories + Indici + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + Friends + Messaggio un amico + + + + OK + OK + + + + Cancel + + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + Retroshare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + Rimuovere + + + Add Shared Directory + Aggiungere l'indice comune + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + Fine + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Download + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + Risistemazione + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + Retroshare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + Statistiche + + + + Download + Download + + + + Session: + Session: + + + + + Downloaded: + Downloaded: + + + Average Downloadspeed: + Average Downloadspeed: + + + + + Count of Downloads: + Count of Downloads: + + + + + + Overall + Overall + + + + Upload + Upload + + + + + + Session + Session + + + + Uploaded: + Uploaded: + + + Average Uploadspeed: + Average Uploadspeed: + + + + + Count of Uploads: + Count of Uploads: + + + + Uploaded + Uploaded + + + + + + + Connections: + Connections: + + + + + + Peers: + Peers: + + + Misc + Misc + + + + Uptime: + Uptime: + + + Overall: + Overall: + + + + + Uptime + Uptime + + + + Records + Records + + + + Uploadspeed: + Uploadspeed: + + + + Downloadspeed: + Downloadspeed: + + + + + Show Settings + Show Settings + + + + Reset + Risistemazione + + + + Receive Rate + Receive Rate + + + + Send Rate + Send Rate + + + + Always On Top + Always On Top + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Changes the transparency of the Bandwidth Graph + Cambia l'acetato del grafico di larghezza di banda + + + + Save + Risparmi + + + + Cancel + Annullamento + + + + Hide Settings + Regolazioni del pellame + + + + %1 days + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Since: + + + + + Cumulative + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + OK + + + + Cancel + + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + Stile + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Tipo + + + + Delete FeedItem + + + + + SubFileItem + + File Name + Nome di lima + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + Retroshare + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + Il carico del certificato è venuto a mancare + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Annullamento + + + + Clear Completed + La radura ha completato + + + + + Status + Condizione + + + + Completed + Completato + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads / Trasferimenti dal sistema centrale verso i satelliti:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + + + + + Active + + + + + Outstanding + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads / Trasferimenti i satelliti verso dal sistema centrale:</span></p></body></html> + + + + + Name + i.e: file name + Nome + + + + + Size + i.e: file size + Formato + + + Progress + i.e: % downloaded + Progresso + + + + Speed + i.e: Download speed + Velocità + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + Fonti + + + + Core-ID + + + + + Progress + i.e: % uploaded + Progresso + + + + Speed + i.e: upload speed + Velocità + + + + Transferred + + + + + Hash + + + + + Play + + + + + Pause + + + + + Resume + + + + + Force Check + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Priority (Speed)... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + Queued + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + Retroshare + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Peer + i.e: user name + + + + + Router Statistics + + + + + Router Requests + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Move in Queue... + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + version: + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + Lime + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + Formato + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + Fiducia + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + File Name + Nome di lima + + + Type + Tipo + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Broadcast on Channel + Radiodiffusione sulla Manica + + + Recommend to Friends + Suggerire agli amici + + + Remove + Rimuovere + + + Remove All + Rimuovere tutti + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Disposizione</p></body></html> + + + Any + C'è ne + + + Audio + Audio + + + Video + Video + + + Size + Formato + + + Sources + Fonti + + + Type + Tipo + + + Results + Risultati + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + OK + + + + Cancel + Annullamento + + + + Yes + + + + + No + No + + + + Help + Aiuto + + + + Retry + Altra prova + + + + Show Log + Mostrare la storia + + + + Show Settings + Mostrare le regolazioni + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Details + Particolari + + + OK + OK + + + Name + Nome + + + Value + Valore + + + diff --git a/retroshare-gui/src/lang/retroshare_ja_JP.qm b/retroshare-gui/src/lang/retroshare_ja_JP.qm new file mode 100644 index 000000000..442906679 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_ja_JP.qm differ diff --git a/retroshare-gui/src/lang/retroshare_ja_JP.ts b/retroshare-gui/src/lang/retroshare_ja_JP.ts new file mode 100644 index 000000000..4d71f85d2 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_ja_JP.ts @@ -0,0 +1,15544 @@ + + + + + AboutDialog + + + About RetroShare + RetroShare について + + + + About + バージョン情報 + + + + close + 閉じる + + + + + About RetroShare %1 + + + + + Max score: %1 + Max score: %1 + + + + Score: %1 + Score: %1 + + + + Level: %1 + Level: %1 + + + + Have fun ;-) + Have fun ;-) + + + + AddFileAssociationDialog + + + File type(extension): + ファイルの種類 (拡張子): + + + + Use default command + デフォルトのコマンドを使用 + + + + Command + コマンド + + + + RetroShare + RetroShare + + + + Sorry, can't determine system default command for this file + + このファイルはシステムのデフォルトのコマンドを決定できません + + + + + AddLinksDialog + + + + Add Link + リンクを追加 + + + + Add a new Link + 新規リンクを追加 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400;">Title:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400;">タイトル:</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400;">Url:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400;">URL::</span></p></body></html> + + + + Title: + タイトル: + + + + Url: + URL:: + + + + +2 Great! + +2 優良! + + + + +1 Good + +1 良好 + + + + 0 Okay + 0 普通 + + + + -1 Sux + -1 不良 + + + + -2 Bad Link + -2 リンク切れ + + + + Add Anonymous Link + 匿名リンクを追加 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">クラウドにリンクを追加</span></p></body></html> + + + + Cancel + キャンセル + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + RetroShare: 高度な検索 + + + + Cancel + キャンセル + + + + Search + 検索 + + + + Add a further search criterion. + さらに検索基準を追加. + + + + Reset the search criteria. + 検索基準をリセット. + + + + Cancels the search. + 検索をキャンセル. + + + + Perform the advanced search. + 高度な検索を実行. + + + + Search Criteria + 検索基準 + + + + AppearancePage + + + Language + 言語 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">使用する言語を選択</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">言語の変更はRetroShareの再起動後に有効になります!</p></body></html> + + + + Style + スタイル + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShareのインターフェイスのスタイルを選択</p></body></html> + + + + Style Sheet + スタイルシート + + + + ApplicationWindow + + + Hide + 非表示 + + + + Show + 表示 + + + Peers + ピア + + + Transfers + 送受信 + + + Messages + メッセージ + + + Blog Feed + ブログ フィード + + + + Games Launcher + ゲーム ランチャ + + + + Photo View + フォト ビュー + + + + Shared Calendars + 共有カレンダー + + + + Statistics + 統計 + + + + + RetroShare + RetroShare + + + + AttachFileItem + + + Form + フォーム + + + File Name + ファイル名 + + + + %p Kb + %p KB + + + + Cancel Download + ダウンロードをキャンセル + + + + BandwidthGraph + + + + Show Settings + 設定を表示 + + + + Reset + リセット + + + + Receive Rate + 受信速度 + + + + Send Rate + 送信速度 + + + + Style + スタイル + + + + Changes the transparency of the Bandwidth Graph + 帯域グラフの透明度を変更 + + + + 100 + 100 + + + + % Opaque + % 不透明 + + + + Save + 保存 + + + + Cancel + キャンセル + + + + Since: + 開始: + + + + Hide Settings + 設定を非表示 + + + + RetroShare Bandwidth Usage + RetroShare 帯域の使用量 + + + + Always on Top + 常に前面に + + + + BlogDetails + + + + Blog Details + ブログの詳細 + + + Blogl Details + typo? + ブログの詳細 + + + + Blog Info + ブログ情報 + + + + Blog Name + ブログ名 + + + + Popularity + 人気度 + + + + Last Post + 最新の投稿 + + + + Blog ID + ブログ ID + + + + Blog Description + ブログの説明 + + + + Cancel + キャンセル + + + + OK + OK + + + + Close + 閉じる + + + + BlogDialog + + Form + フォーム + + + Blogs + ブログ + + + Last Month + 先月 + + + Last Week + 先週 + + + Last Day + 前日 + + + All Users + 全ユーザー + + + Jimmy + Jimmy + + + John + John + + + Jacki + Jacki + + + No Feeds + フィードなし + + + Post Blog + ブログに投稿 + + + + BlogMsgItem + + + Form + フォーム + + + + Remove Item + アイテムを削除 + + + Connected + 接続中 + + + + Expand + 展開 + + + + Subject + 件名 + + + + Play Media + メディアを再生 + + + + BlogNewItem + + Form + フォーム + + + + Remove Item + アイテムを削除 + + + name + 名前 + + + + Subscribe to Blog + ブログを購読 + + + + Expand + 展開 + + + + Blog Decscription + + + + + BlogsDialog + + + Form + フォーム + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">ブログ</span></p></body></html> + + + + Add + 追加 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">ブログ名</span></p></body></html> + + + Post To Channel + チャネルに投稿 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">ブログの購読を中止</span></p></body></html> + + + + Unsubscribe + 購読中止 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">ブログを購読</span></p></body></html> + + + + Subscribe + 購読 + + + + + Create New Blog + ブログを新規作成 + + + + Name + 名前 + + + + ID + ID + + + + Own Blogs + 自分のブログ + + + + Subscribed Blogs + 購読中のブログ + + + + Popular Blogs + 人気のブログ + + + + Other Blogs + その他のブログ + + + + Post to Blog + ブログに投稿 + + + + Subscribe to Blog + ブログを購読 + + + + Unsubscribe to Blog + ブログの購読を中止 + + + + Show Blog Details + ブログの詳細を表示 + + + + Create a new Blog + ブログを新規作成 + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + 人気度: %1 +取得数: %2 +評価: %3 + + + + BlogsMsgItem + + + Form + フォーム + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">ブログの件名</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">日付時刻</span></p></body></html> + + + + Unsubscribe From Channel + チャネルの購読を中止 + + + + Comment + コメント + + + + Remove Item + アイテムを削除 + + + + + Expand + 展開 + + + + Comments here + ここにコメント + + + + Hide + 非表示 + + + + CalDialog + + + Remove + 削除 + + + + Form + フォーム + + + + Local Calendars + ローカル カレンダー + + + + Shared Calendar List + 共有カレンダーリスト + + + + Share Details + 共有の詳細 + + + + Name: + 名前: + + + + Location: + 場所: + + + + ... + ... + + + + Status: + 状態: + + + + Private + プライベート + + + + Public + パブリック + + + + Allow List: + 許可リスト: + + + + <Disabled> + <無効> + + + + Add + 追加 + + + + Peer Calendars + ピア カレンダー + + + + CallToaster + + Message + メッセージ + + + + CertificatePage + + + Certificate files + 証明書ファイル + + + + Use PGP certificates saved in files. + ファイルに保存された PGP 証明書を使用. + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + あなたの証明書でファイルを生成する必要があり、そのファイルをあなたの友達に渡してください また、以前に生成したファイルも使用できます. + + + + Export my certificate... + あなたの証明書をエクスポート... + + + Specify path to your friend's certificate in the box below + 下のボックスにあなたの友達の証明書のパスを指定してください + + + + Browse + ブラウズ + + + + Select Certificate + 証明書を選択 + + + RetroShare Certificates (*.rsc) + RetroShare 証明書 (*.rsc) + + + Not implemented + 未実装 + + + Certificates (*.pqi *.pem) + 証明書 (*.pqi *.pem) + + + + Please choose a filename + ファイル名を選択してください + + + + + + + RetroShare + RetroShare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare 証明書 (*.rsc); すべてのファイル (*) + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + 証明書ファイルの作成に成功しました + + + + + Sorry, certificate file creation failed + 証明書ファイルの作成に失敗しました + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + 証明書の読み込みに失敗: ファイル %1 が見つかりません + + + + ChanMsgDialog + + Compose + 作成 + + + Select Color + 色の選択 + + + Recommended Files + おすすめのファイル + + + Send To: + 宛先: + + + Send + 送信 + + + Delete Channel + 削除チャネル + + + Create Channel MSG + チャネルメッセージを作成しなさい + + + &Left + 左寄せ(&L) + + + C&enter + 中央揃え(&E) + + + &Right + 右寄せ(&R) + + + &Justify + 均等揃え(&J) + + + Send this message now + メッセージをすぐに送信 + + + Toggle Contacts View + コンタクトの表示の切り替え + + + Save this message + このメッセージを保存 + + + Compose: + 作成: + + + &File + ファイル(&F) + + + &New + 新規(&N) + + + &Open... + 開く(&O)... + + + &Save + 保存(&S) + + + Save &As... + 名前をつけて保存(&A)... + + + &Print... + 印刷(&P)... + + + &Export PDF... + PDFにエクスポート(&E)... + + + &Quit + 終了(&Q) + + + &Edit + 編集(&E) + + + &Undo + 元に戻す(&U) + + + &Redo + やり直す(&R) + + + Cu&t + 切り取り(&T) + + + &Copy + コピー(&C) + + + &Paste + 貼り付け(&P) + + + &View + 表示(&V) + + + &Contacts Sidebar + コンタクト サイドバー(&C) + + + &Insert + 挿入(&I) + + + &Image + イメージ(&I) + + + Open File... + ファイルを開く... + + + HTML-Files (*.htm *.html);;All Files (*) + HTML ファイル (*.htm *.html);;すべてのファイル (*) + + + Save as... + 名前をつけて保存... + + + Print Document + ドキュメントを印刷 + + + Save Message + メッセージを保存 + + + Message has not been Sent. +Do you want to save message ? + メッセージは送信されていません. +メッセージを保存しますか ? + + + Choose Image + イメージを選択 + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + サポートされているイメージ ファイル (*.png *.jpeg *.jpg *.gif) + + + Add Extra File + さらにファイルを追加 + + + File Name + ファイル名 + + + Size + サイズ + + + Sources + ソース + + + Save + 保存 + + + Contacts + コンタクト + + + Subject: + 件名: + + + Font size + フォント サイズ + + + Blockquote + 引用 + + + Increase font size + フォントを拡大 + + + Decrease font size + フォントを縮小 + + + Bold + 太字 + + + Underline + 下線 + + + Italic + 斜体 + + + Attach + 添付 + + + Attach File + ファイルを添付 + + + Quote + 引用 + + + Add Blockquote + 引用を追加 + + + Alignment + 文字揃え + + + Add a Image + イメージを追加 + + + Sets text font to code style + フォントをコード スタイルに設定 + + + Split text + テキストを分割 + + + Hash + ハッシュ + + + Reply + 返信 + + + + ChanMsgItem + + Form + フォーム + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:normal; color:#656565;">Channel Subject</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:normal; color:#656565;">チャネルの件名</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">日付時刻</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Short Description</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">簡単な説明</span></p></body></html> + + + + Toggle Message Read Status + + + + + New + 新規 + + + + Download + ダウンロード + + + + Play + 再生 + + + + Remove Item + アイテムを削除 + + + + + Expand + 展開 + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + チャネルの購読を中止 + + + Play Media + メディアを再生 + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + 非表示 + + + + ChanNewItem + + Form + フォーム + + + + Remove Item + アイテムを削除 + + + Connected + 接続中 + + + + Unknown Channel + + + + + New Channel + 新規チャネル + + + + Updated Channel + + + + name + 名前 + + + + Subscribe to Channel + チャネルを購読 + + + + Expand + 展開 + + + + Channel Decscription + チャネルの説明 + + + Description + of Forum + フォーラムの説明 + + + + ChannelDetails + + + + Channel Details + チャネルの詳細 + + + + Channel Info + チャネル情報 + + + Forum Name + フォーラム名 + + + + Popularity + 人気度 + + + + Last Post + 最新の投稿 + + + Forum ID + フォーラム ID + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + チャネルの説明 + + + + Type + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 制限付き - 誰でも読むことは可能. 公開は限定 (プライベート公開キー) + + + + Private - (Private Publish Key required to view Messages) + プライベート - (メッセージの表示にプライベート公開キーが必要) + + + + Cancel + キャンセル + + + + OK + OK + + + + Close + 閉じる + + + + ChannelFeed + + + Create Channel + チャネルを作成 + + + + Subscribe To Channel + チャネルを購読 + + + Form + フォーム + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">チャネル</span></p></body></html> + + + Add + 追加 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt;">Channel Name</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt;">チャネル名</span></p></body></html> + + + Post To Channel + チャネルに投稿 + + + Title + タイトル + + + Description + 説明 + + + Reset + リセット + + + + Display + 表示 + + + + Unsubcribe To Channel + チャネルの購読を中止 + + + + Unsubscribe + 購読中止 + + + + Subscribe + 購読 + + + + Set all to read + + + + + Enable Auto-download + + + + Auto Download On + 自動ダウンロード オン + + + Auto Download Off + 自動ダウンロード オフ + + + Name + 名前 + + + Popularity + 人気度 + + + ID + ID + + + + Own Channels + 自分のチャネル + + + + Subscribed Channels + 購読済みのチャネル + + + + Popular Channels + 人気のチャネル + + + + Other Channels + その他のチャネル + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + チャネルに投稿 + + + + Subscribe to Channel + チャネルを購読 + + + + Unsubscribe to Channel + チャネルの購読を中止 + + + + Show Channel Details + チャネルの詳細を表示 + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + Create a new Channel + チャネルを新規作成 + + + New Channel + 新規チャネル + + + Popularity: %1 +Fetches: %2 +Available: %3 + 人気度: %1 +取得数: %2 +評価: %3 + + + + ChatMsgItem + + Form + フォーム + + + + Remove Item + アイテムを削除 + + + + Write a quick Message + + + + + Send Mail + メールを送信 + + + + Write Message + + + + + Send + 送信 + + + + Cancel + + + + Chat + チャット + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + 一般 + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + プライベート チャット + + + + Style + + + + + Group chat + グループ チャット + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ChatToaster + + Message + メッセージ + + + + ComboStatus + + Online + オンライン + + + Away + 退席中 + + + Busy + 取り込み中 + + + + ConclusionPage + + + Make Friend + 友達になる + + + + Details about your friend : + 友達についての詳細: + + + + Key validity: + キーの有効性: + + + + Email: + Eメール: + + + + Options + オプション + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + 友達を認証する (GPG キーに署名) + + + + Add as friend to connect with + 接続する友達として追加 + + + + It seems your friend is already registered. Adding it might just set it's ip address. + この友達はすでに登録されているようです. 追加しても IP アドレスを変更するだけかもしれません. + + + + Peer details + ピア詳細 + + + + Name: + 名前: + + + + Loc: + 場所: + + + + Signers + 署名者 + + + + ConfCertDialog + + + Cancel + キャンセル + + + Port: + 港: + + + Trust Settings + 信頼の設定 + + + Trust Level + 信頼レベル + + + Trust Their Signature + 署名を信頼しなさい + + + Sign The Certificate + 証明書に署名しなさい + + + + OK + OK + + + + Details + 詳細 + + + + Name + 名前 + + + + Loc + 場所 + + + + Peer Address + ピア アドレス + + + + Last Contact + 最新のコンタクト + + + Peer Details + ピア詳細 + + + + Peer Info + ピア情報 + + + + Peer ID + ピア ID + + + + Version + バージョン + + + + RetroShare ID + + + + + Status + + + + + Dynamic DNS + + + + + Addresses list + アドレス リスト + + + + None + なし + + + + Marginal + 最低限 + + + + Full + 完全 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Certificate + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The trust settings refers to the gnupg web of trust mecanism. This trust means how you trust your friends when he is signing other gpg keys. If you set your trust to "full", it means that when your friend sign a key, this key will be shown as validated by the web of trust in the network view.</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">信頼の設定は GNUPG の WOT (Web of Trust) メカニズムを参照しています. この信頼はあなたの友達が他の GPG キーに署名したとき, あなたの友達をどのように信頼するかを意味します. 信頼を「完全」に設定した場合, あなたの友達があるキーに署名したときに, このキーが WOT によって認証されたものとしてネットワーク ビューに表示されます。 </p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should sign a key when you are sure that the person who claims ownership on this key is the real owner of the key. When you are sure that the name of the key owner is the real name of the emmitter of this key, you may sign it to confirm it. Signing the key will be public unless public discovery is not setted. This means you friends can check if you did sign someone's key.</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">このキーの所有権を主張する人物が本当にこのキーの所有者であるとあなたが確信できる場合に, このキーに署名するべきです. このキーの所有者の名前がこのキーの発行者の本当の名前であるとあなたが確信できる場合, 確認のため署名してもかまいません. 開示の設定がオフでない限り, キーへの署名は公開されます. このことは, あなたが誰かのキーに署名したかどうかを, あなたの友達がチェックできることを意味します.</p></body></html> + + + SignGPG Key + GPG キーに署名 + + + + Deny Friend + 友達を拒否 + + + + Make Friend + 友達になる + + + + + Sign GPG key + GPG キーに署名 + + + + Friend Details + + + + + Local Address + ローカル アドレス + + + + External Address + 外部アドレス + + + + + Port + ポート + + + + Your trust in this peer is: + このピアへの信頼: + + + None + 無し + + + Marginal + 最低限 + + + Full + 完全 + + + + GPG Key + GPG キー + + + + Peer has signed my GPG key + ピアはあなたの GPG キーで署名されまています + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + ピアのキーは以下によって署名されています: + + + + Apply and Close + 適用して閉じる + + + + + RetroShare + RetroShare + + + + + Error : cannot get peer details. + エラー: ピア詳細を取得できません. + + + + Your key is signed by : + あなたのキーは次によって署名されています : + + + + Peer key is signed by : + ピアのキーは次によって署名されています : + + + + Your trust in this peer is ultimate, it's probably a key you own. + このピアへのあなたの信頼は最大限です. おそらくあなた自身のキーです. + + + + Your trust in this peer is full. + このピアへのあなたの信頼は完全です. + + + + Your trust in this peer is marginal. + このピアへのあなたの信頼は最低限です. + + + + Your trust in this peer is none. + このピアへのあなたの信頼はなしです. + + + + Your trust in this peer is not set. + このピアへのあなたの信頼は設定されていません. + + + + Peer has authenticated me as a friend and did sign my GPG key + ピアはあなたを友達として認証し、あなたの GPG キーに署名しました + + + + Peer has not authenticated me as a friend and did not sign my GPG key + ピアはあなたを友達として認証しておらず、あなたの GPG キーに署名していません + + + + Signature Failure + 署名失敗 + + + + Maybe password is wrong + おそらくパスワードが間違っています + + + + Trust + 信頼 + + + + ConnectDialog + + Peer Details + ピア詳細 + + + Make Friend + 友達になる + + + Cancel + キャンセル + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#000000;"> Make Friend</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#000000;"> 友達になる</span></p></body></html> + + + Trust: + 信頼: + + + Name: + 名前: + + + Org: + 組織: + + + Loc: + 場所: + + + Country: + 国: + + + signers: + 署名者: + + + AUTH CODE: + 認証コード: + + + + ConnectFriendWizard + + + Connect Friend Wizard + 友達と接続ウィザード + + + + CreateBlog + + + Create new Blog + ブログを新規作成 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">新規ブログ</span></p></body></html> + + + + Name + 名前 + + + + Description + 説明 + + + + Type: + 種類: + + + + Public - Anyone can read and publish (Shared Publish Key) + パブリック - 誰でも読み書き可能 (共有公開キー) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 制限付き - 誰でも読むことは可能. 公開は限定 (プライベート公開キー) + + + + Private - (Private Publish Key required to view Messages) + プライベート - (メッセージの表示にプライベート公開キーが必要) + + + + Allowed Messages + 許可されるメッセージ + + + + Authemticated Messages + 認証されたメッセージ + + + + Anonymous Messages + 匿名のメッセージ + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + キャンセル + + + + Create + 作成 + + + + RetroShare + RetroShare + + + + Please add a Name + 名前を追加してください + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + 新規ブログ投稿 + + + + Blog Post + ブログ投稿 + + + + Blog Post to: + 投稿するブログ: + + + + Visual Editor + ビジュアル エディタ + + + + Blog Message + ブログ メッセージ + + + + Subject : + 件名: + + + + Html Editor + HTML エディタ + + + Attachments + 添付 + + + + toolBar + ツールバー + + + + toolBar_2 + ツールバー_2 + + + + blockquoute + 引用 + + + + Increase font Size + フォントを拡大 + + + + Decrease font size + フォントを縮小 + + + + Bold + 太字 + + + + Underline + 下線 + + + + Italic + 斜体 + + + + Publish + 公開 + + + + New + 新規 + + + + Code + コード + + + + splitPost + 投稿を分割 + + + + Ordered List + 順序付きリスト + + + + Unordered List + 順序なしリスト + + + + Clipboard + クリップボード + + + + Undo + 元に戻す + + + Add Extra File + さらにファイルを追加 + + + + RetroShare + RetroShare + + + + Please add a Subject + 件名を追加してください + + + + &File + ファイル(&F) + + + + &New + 新規(&N) + + + + &Open... + 開く(&O)... + + + + &Save + 保存(&S) + + + + Save &As... + 名前をつけて保存(&A)... + + + + &Print... + 印刷(&P)... + + + + Print Preview... + 印刷プレビュー... + + + + &Export PDF... + PDFにエクスポート(&E)... + + + + &Quit + 終了(&Q) + + + + &Edit + 編集(&E) + + + + &Undo + 元に戻す(&U) + + + + &Redo + やり直す(&R) + + + + Cu&t + 切り取り(&T) + + + + &Copy + コピー(&C) + + + + &Paste + 貼り付け(&P) + + + + &View + 表示(&V) + + + + &Insert + 挿入(&I) + + + + &Image + イメージ(&I) + + + + F&ormat + フォーマット(&F) + + + + &Bold + 太字(&B) + + + + &Italic + 斜体(&I) + + + + &Underline + 下線(&U) + + + + + &Left + 左寄せ(&L) + + + + + C&enter + 中央揃え(&E) + + + + + &Right + 右寄せ(&R) + + + + &Justify + 均等揃え(&J) + + + + &Text Color... + 文字色(&T)... + + + + Application + アプリケーション + + + + The document has been modified. +Do you want to save your changes? + ドキュメントが変更されています. +変更を保存しますか? + + + + Open File... + ファイルを開く... + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML ファイル (*.htm *.html);;すべてのファイル (*) + + + + Save as... + 名前をつけて保存... + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + ODF ファイル(*.odt); HTML ファイル (*.htm *.html); すべてのファイル (*) + + + + Print Document + ドキュメントを印刷 + + + + Export PDF + + + + + Choose Image + イメージを選択 + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + サポートされているイメージ ファイル (*.png *.jpeg *.jpg *.gif) + + + + CreateChannel + + + Create a new Channel + チャネルを新規作成 + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + 説明 + + + + Type: + 種類: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 制限付き - 誰でも読むことは可能. 公開は限定 (プライベート公開キー) + + + + Private - (Private Publish Key required to view Messages) + プライベート - (メッセージの表示にプライベート公開キーが必要) + + + + Allowed Messages + 許可されるメッセージ + + + + Anonymous Messages + 匿名のメッセージ + + + + Authenticated Messages + + + + Authemticated Messages + 認証されたメッセージ + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + チャネル ロゴ + + + + Add Channel Logo + チャネル ロゴを追加 + + + + Cancel + + + + + Create + 作成 + + + + RetroShare + RetroShare + + + + Please add a Name + 名前を追加してください + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + 新規チャネル投稿 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">新規チャネル投稿</span></p></body></html> + + + + Channel Post + チャネル投稿 + + + + Channel Post to: + 投稿するチャネル: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> チャネル投稿にサムネイル画像を設定できます. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> ドラッグ&ドロップでファイルを添付できます. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> チャネル投稿には件名と説明を設定してください. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> 添付したファイルは添付タブに表示されます. </span></p></body></html> + + + + Add File to Attach + 添付するファイルを追加 + + + + Add Channel Thumbnail + チャネル サムネイルを追加 + + + + Message + メッセージ + + + + Subject : + 件名: + + + + + Attachments + 添付 + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + 検索結果からファイルをドラッグ & ドロップ + + + + + Drop file error. + ファイルのドロップ エラー. + + + + Directory can't be dropped, only files are accepted. + フォルダーはドロップできません. ファイルのみ可能です. + + + + File not found or file name not accepted. + ファイルが見つからないかファイル名が受け入れられません. + + + + Add Extra File + さらにファイルを追加 + + + + + RetroShare + RetroShare + + + + File already Added and Hashed + + + + + Please add a Subject + 件名を追加してください + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + 名前 + + + + Type: + 種類: + + + + Authenticated Messages + + + + + Cancel + キャンセル + + + RetroShare + RetroShare + + + + Please add a Name + 名前を追加してください + + + + Create new Forum + フォーラムを新規作成 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">新規フォーラム</span></p></body></html> + + + + Description + 説明 + + + + Public - Anyone can read and publish (Shared Publish Key) + パブリック - 誰でも読み書き可能 (共有公開キー) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 制限付き - 誰でも読むことは可能. 公開は限定 (プライベート公開キー) + + + + Private - (Private Publish Key required to view Messages) + プライベート - (メッセージの表示にプライベート公開キーが必要) + + + + Allowed Messages + 許可されるメッセージ + + + Authemticated Messages + 認証されたメッセージ + + + + Anonymous Messages + 匿名のメッセージ + + + Channel Logo + チャネル ロゴ + + + Add Channel Logo + チャネル ロゴを追加 + + + + Create + 作成 + + + + CreateForumMsg + + + Close + 閉じる + + + + Post Forum Message + フォーラム メッセージを投稿 + + + + Forum + フォーラム + + + Forum Post Subject + フォーラム投稿の件名 + + + + Attach File + ファイルを添付 + + + Paste retroshare link + Retoroshare リンクを貼り付け + + + + Forum Post + フォーラム投稿 + + + + Sign Message + メッセージに署名 + + + + Subject + 件名 + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + toolBar + ツールバー + + + + Post Forum Msg + フォーラム メッセージを投稿 + + + Paste retroshare Link + RetroShare リンクを貼り付け + + + Paste retroshare Link Full + RetroShare リンクをすべて貼り付けてください + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + RetroShare + + + + Please set a Forum Subject and Forum Message + フォーラムの件名とフォーラムのメッセージを設定してください + + + + Add Extra File + さらにファイルを追加 + + + + + Drop file error. + ファイルのドロップ エラー. + + + + File not found or file name not accepted. + ファイルが見つからないかファイル名が受け入れられません. + + + + Directory can't be dropped, only files are accepted. + フォルダーはドロップできません. ファイルのみ可能です. + + + Clipboard does not contains RetroShare link('s) + クリップボードにRetroShare リンクがありません + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + RetroShare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + あなたの公開キーがクリップボードにコピーされました. Eメール(またはその他の方法)に貼り付けてあなたの友達に送ってください + + + + Save as... + 名前をつけて保存... + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare 証明書 (*.rsc); すべてのファイル (*) + + + + Public Key + パブリック キー + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">あなたのキーをクリップボードにコピー</p></body></html> + + + + Copy Key + キーをコピー + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">キーをファイルに保存</p></body></html> + + + + Save Key + キーを保存 + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + B + + + + KB + KB + + + + MB + MB + + + + GB + GB + + + + DetailsDialog + + + Details + 詳細 + + + + + General + 一般 + + + + File Name: + ファイル名: + + + + Hash: + ハッシュ: + + + + Size: + サイズ: + + + + Status: + 状態: + + + Priority + 優先度 + + + + Priority: + + + + + Type: + 種類: + + + + Transfer + 転送 + + + + Sources: + ソース: + + + + Datarate: + 転送速度: + + + + Completed: + 完了: + + + + Chunk size: + チャンク サイズ: + + + + + Number of Chunks + チャンクの数 + + + + Chunks: + チャンク: + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Remaining Label</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Remaining Label</span></p></body></html> + + + + Remaining: + 残り: + + + + Date + 日付 + + + + Download time: + ダウンロードした日時: + + + + + Comments + コメント + + + + + retroshare link(s) + RetroShare リンク + + + + Copy + コピー + + + + OK + OK + + + + Cancel + キャンセル + + + + Rating + 評価 + + + + File Name + ファイル名 + + + + Not Rated + 未評価 + + + + No Comments + コメントなし + + + + DirectoriesPage + + + Incoming Directory + ダウンロード フォルダ + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + Partials Direcrtory + 未完了ファイルのフォルダ + + + + Shared Directories + 共有フォルダ + + + Automatically share incoming directory (Recommanded) + ダウンロード フォルダを自動的に共有 (推奨) + + + + Edit Share + 共有を編集 + + + Incoming files + 入って来るファイル + + + Add a Share Directory + 共有フォルダを追加 + + + Remove Shared Directory + 共有フォルダを削除 + + + + + Browse + ブラウズ + + + Add Shared Directory + 共有フォルダを追加 + + + + Set Incoming Directory + ダウンロード フォルダを設定 + + + + Set Partials Directory + 不完全ファイルのフォルダを設定 + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + 閉じる + + + + EditChanDetails + + + Channel Details + チャネルの詳細 + + + + Cancel + + + + + OK + OK + + + + Edit Channel Details + + + + + Channel Info + チャネル情報 + + + + Channel Name + + + + + Channel Description + チャネルの説明 + + + + Add Channel Logo + チャネル ロゴを追加 + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + フォーラムの詳細 + + + + Cancel + + + + + OK + OK + + + + Edit Forum Details + + + + + Forum Info + フォーラム情報 + + + + Forum Name + フォーラム名 + + + + Forum Description + フォーラムの説明 + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + 件名: + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + エラーが発生しました + + + + Here is the error message: + エラーメッセージ: + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">友達</span></p></body></html> + + + + Status + 状態 + + + + Person + パーソン + + + + Auto Connect + 自動接続 + + + + Trust Level + 信頼レベル + + + + Peer Address + ピア アドレス + + + + Last Contact + 最新のコンタクト + + + + Organisation + 組織 + + + + Location + 場所 + + + + Country + + + + + Person Id + パーソン ID + + + + Auth Code + 認証コード + + + + # + + + + + ExprParamElement + + + + + to + + + + + ignore case + 大文字小文字を無視 + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + 言い回しウィジット + + + + Delete this expression + この言い回しを削除 + + + + FileAssociationsPage + + + &New + 新規(&N) + + + + Add new Association + 関連付けを新規追加 + + + + &Edit + 編集(&E) + + + + Edit this Association + この関連付けを編集 + + + + &Remove + 削除(&R) + + + + Remove this Association + この関連付けを削除 + + + + File type + ファイルの種類 + + + + Friend Help + 友達 ヘルプ + + + + You this + + + + + FileTransferInfoWidget + + Chunk map: + チャンク マップ: + + + Active chunks: + アクティブなチャンク: + + + Availability map ( + 可用性マップ ( + + + sources + ソース + + + active sources + 個のアクティブな ソース + + + File info: + ファイル情報: + + + File hash: + ファイル ハッシュ: + + + File size: + ファイル サイズ: + + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + 残り + + + + Number of sources + + + + + Chunk strategy + チャンクの方針 + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + Chunk size: + チャンク サイズ: + + + Number of chunks: + チャンクの数: + + + Transfered: + 転送済: + + + Number of sources: + ソースの数: + + + Chunk strategy: + チャンクの方針: + + + Transfer type: + 転送の種類: + + + + FlatStyle_RDM + + + Friends Directories + 友達のフォルダ + + + + My Directories + 自分のフォルダ + + + + Size + + + + + Age + 経過時間 + + + + Friend + 友達 + + + + Share Type + 共有の種類 + + + + Directory + フォルダ + + + + FofPage + + + Friends of friends + 友達の友達 + + + + Select now who you want to make friends with. + 友達にしたい人を選択してください. + + + + Show me: + 以下を表示: + + + + Any peer I've not signed + 署名していないすべてのピア + + + + Friends of my friends who already trust me + あなたの友達の友達で、すでにあなたを信頼している人 + + + + Signed peers showing as denied + 署名済のピアで拒否と表示されているもの + + + + Peer name + ピアの名前 + + + + Also signed by + 署名されている + + + + Peer id + ピア ID + + + + Make friend with these peers + これらのピアと友達になる + + + + *** None *** + *** なし *** + + + + ForumDetails + + + + Forum Details + フォーラムの詳細 + + + + Forum Info + フォーラム情報 + + + + Forum Name + フォーラム名 + + + + Popularity + 人気度 + + + + Last Post + 最新の投稿 + + + + Forum ID + フォーラム ID + + + + Forum Description + フォーラムの説明 + + + + Security + セキュリティ + + + + Allowed Messages + 許可されるメッセージ + + + + Authemticated Messages + 認証されたメッセージ + + + + Anonymous Messages + 匿名のメッセージ + + + + Cancel + キャンセル + + + + OK + OK + + + + Apply and Close + 適用して閉じる + + + + ForumMsgItem + + Form + フォーム + + + + Remove Item + アイテムを削除 + + + Forum Name + フォーラム名 + + + + Expand + 展開 + + + + + + Subject: + 件名: + + + + Send + 送信 + + + + Signed + 署名済 + + + Subject... + 件名... + + + Persons Name + 人物名 + + + + Unsubscribe To Forum + フォーラムの購読を中止 + + + + Reply + 返信 + + + Previous Message... + 前のメッセージ... + + + Currnent Message.. + 現在のメッセージ.. + + + + Forum Post + フォーラム投稿 + + + + Unknown Forum Post + + + + + + + Anonymous + 匿名 + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + フォーム + + + + Remove Item + アイテムを削除 + + + Connected + 接続中 + + + name + 名前 + + + + Subscribe to Forum + フォーラムを購読 + + + + Expand + 展開 + + + + Forum Description + フォーラムの説明 + + + + ForumPage + + + Misc + + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + フォーラムを購読 + + + + Unsubscribe to Forum + フォーラムの購読を中止 + + + + New Forum + 新規フォーラム + + + + Show Forum Details + フォーラムの詳細を表示 + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + 返信 + + + + Reply to Author + スレ主に返信 + + + + Expand all + すべて展開 + + + + Collapse all + すべて折りたたみ + + + + AUTHD + + + + Popularity: + 人気度: + + + + Your Forums + あなたのフォーラム + + + + Subscribed Forums + 購読済のフォーラム + + + + Popular Forums + 人気のフォーラム + + + + Other Forums + その他のフォーラム + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + 非表示 + + + + Expand + 展開 + + + Anonymous + 匿名 + + + signed + 署名済 + + + none + なし + + + + + RetroShare + RetroShare + + + + No Forum Selected! + フォーラムが選択されていません! + + + + You cant reply a Anonymous Author + 匿名のスレ主には返信できません + + + File Request Confirmation + ファイル リクエストの確認 + + + The file has been added to your download list. + ファイルはすでにダウンロードリストに追加されています. + + + File Request canceled + ファイル リクエストがキャンセルされました + + + The file has not been added to your download list, because you already have it. + そのファイルはすでに持っているためダウンロードリストには追加されません. + + + File Request Error + ファイル リクエスト エラー + + + The file link is malformed. + ファイルのリンクが不正です. + + + + + Date + 日付 + + + + + Start New Thread + スレッドを新規作成 + + + New Message + 新しいメッセージ + + + Add + 追加 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start new Thread for Selected Forum</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">選択されたフォーラムでスレッドを新規作成</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reply Message</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">メッセージに返信</p></body></html> + + + RetroShare Forums + RetroShare フォーラム + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">フォーラム:</p></body></html> + + + + Last Post + 最新の投稿 + + + + Threaded View + スレッド表示 + + + + Flat View + フラット表示 + + + + + Title + タイトル + + + + + Author + スレ主 + + + + Signed + 署名済 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">スレッド:</span></p></body></html> + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + リセット + + + + Content + + + + + Create Forum + フォーラムを作成 + + + + Print + 印刷 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">フォーラム</span></p></body></html> + + + + Start new Thread for Selected Forum + + + + + Display + 表示 + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + 印刷プレビュー + + + + ForumsFillThread + + + + Anonymous + 匿名 + + + + + signed + 署名済 + + + + + none + なし + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">友達</span></p></body></html> + + + + Add + 追加 + + + + Display + 表示 + + + + Friends + 友達 + + + + Status + + + + + Add or Change your Avatar + アバターの追加または変更 + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + 太字 + + + + Underline + 下線 + + + + Italic + 斜体 + + + + Font + フォント + + + + Text Color + 文字色 + + + + Attach File + ファイルを添付 + + + + Send + 送信 + + + + Clear Chat History + チャットの履歴をクリア + + + + + Add Friend + 友達を追加 + + + + Create new Profile + プロファイルを新規作成 + + + + + Create new Forum + フォーラムを新規作成 + + + + F + + + + + + Create new Channel + チャネルを新規作成 + + + + C + + + + + Add your Avatar Picture + アバターの画像を追加 + + + + A + + + + + Set your Personal Message + パーソナルメッセージを設定 + + + + Edit your status Message + 状態メッセージを編集 + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + オフラインの友達を隠す + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + 降順に並べ替え + + + + + Sort Ascending Order + 昇順に並べ替え + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + プロファイル + + + + News Feed + ニュース フィード + + + + Welcome to RetroShare's group chat. + Retoroshare のグループチャットにようこそ. + + + + me + 自分 + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + 友達 + + + + Location + + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + チャット + + + + Message Friend + 友達にメッセージを送る + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + 友達に接続 + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + 友達を拒否 + + + + Remove Friend Location + 友達の場所を削除 + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + すべて展開 + + + + Collapse all + すべて折りたたみ + + + + location + + + + + + Available + 利用可能 + + + + Save Certificate + 証明書を保存 + + + + Certificates (*.pqi) + 証明書(*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + さらにファイルを追加 + + + + + Drop file error. + ファイルのドロップ エラー. + + + + Directory can't be dropped, only files are accepted. + フォルダーはドロップできません. ファイルのみ可能です. + + + + File not found or file name not accepted. + ファイルが見つからないかファイル名が受け入れられません. + + + + Save as... + 名前をつけて保存... + + + + Text File (*.txt );;All Files (*) + + + + + GamesDialog + + + Cancel Game + ゲームをキャンセル + + + + Add to Invite List + 招待リストに追加 + + + + Remove from Invite List + 招待リストから削除 + + + + + Interested in Playing + ゲームに興味あり + + + + Not Interested in Game + ゲームに興味なし + + + + + Not Interested + 興味なし + + + + Confirm Peer in Game + ゲーム中のピアを承認 + + + + Remove Peer from Game + ゲームからピアを削除 + + + + Interested in Game + ゲームに興味あり + + + + Quit Game + ゲームを終了 + + + + Status + 状態 + + + + Accept + 承認 + + + + Form + フォーム + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">ゲーム ランチャ</span></p></body></html> + + + + Game: + ゲーム: + + + + GameType: 0. Want to Add your Game here? + ゲームの種類: 0. ゲームをここに追加しますか? + + + + GameType: 1. Get In Touch with the developers + ゲームの種類: 1. 開発者に連絡 + + + + GameType: 2. + ゲームの種類:: 2. + + + + Title / Comment + タイトル/コメント + + + + Create New Game + ゲームを新規作成 + + + + Invite All Friends + 友達をすべて招待 + + + + Game Type + ゲームの種類 + + + + Server + サーバ + + + + Comment + コメント + + + + GameID + ゲーム ID + + + + Player + プレイヤ + + + + + Invite + 招待 + + + + Interested + 興味あり + + + + Delete + 消去 + + + + + Move Player + プレイヤを移動 + + + + Play Game + ゲームをプレイ + + + + GenCertDialog + + RetroShare setup + Retroshareの組み立て + + + Load Trusted Certificate (Optional) + 負荷信託証券(任意) + + + RetroShare : Create new user Profile + RetroShare: ユーザ プロファイルを新規作成 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new RetroShare profile</span><span style=" font-family:'Arial'; font-size:8pt;"><br /><br /></span><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Retroshare uses gpg keys for identity management. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing gpg key, or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">Please fill in the location field (example : "home", "laptop", etc). </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">It will be permanently attached to this retroshare installation, and visible to</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">your peers.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same gpg key.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">新規 RetroShare プロファイルを作成</span><span style=" font-family:'Arial'; font-size:8pt;"><br /><br /></span><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShar は GPG キーをアイデンティティ管理のために使用します.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">既存の GPG キーやプロファイルを使用することも, このフォームで新規に作成することもできます.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">場所フィールドは (例 : "home", "laptop", など) のように入力してください.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">プロファイルはこの RetroShare に永続的に紐付けられ、他のピアに</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">表示されます.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">同じ GPG キーを使って異なる場所に RetroShare をインストールすることもできます.</span></p></body></html> + + + It looks like you don't own any GPG keys. Please fill in the form below to generate one, or use your favorite gnupg key manager. + あなたは GPG キーを所有していないようです. 下のフォームに入力してキーを生成するか, ご利用の GPG キー マネージャを使用してください. + + + Use GPG key + GPG キーを使用 + + + + + + Create new Profile + プロファイルを新規作成 + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + + Your profile is associated to a GPG key + + + + + Use Profile + + + + + Name + 名前 + + + + Enter here your nickname + + + + + Email + Eメール + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + GPG Password + GPG パスワード + + + Put a meaningfull location. ex : home, laptop, etc. + 有意な場所を入力. 例: home, laptop, など. + + + Generate a new gpg key + 新規 GPG キーを生成 + + + + Generate New Profile + 新規プロファイルを生成 + + + + Info + 情報 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">友人</span></p></body></html> + + + Select File + ファイルを選びなさい + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">名前: </p></body></html> + + + Generate New Certificate + 新しい証明書を発生させなさい + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + プロファイルを新規作成 + + + + + Generate GPG key Failure + GPG キーの生成に失敗 + + + + Location field is required with a minimum of 3 characters + 場所フィールドは最低3文字以上必要です + + + + All fields are required with a minimum of 3 characters + すべてのフィールドは最低3文字以上必要です + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + Generating new GPG key, please be patient. Fill in your GPG password when asked. + 新規 GPG キーを生成中. しばらくお待ちください. GPG パスワードをたずねられたら入力してください. + + + + Select Trusted Friend + 信頼している友達を選択 + + + + Certificates (*.pqi *.pem) + 証明書 (*.pqi *.pem) + + + Location: + 場所: + + + + GeneralMsgDialog + + General Message + 一般メッセージ + + + Channel + チャンネル + + + Forum + フォーラム + + + Blog + ブログ + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600; color:#ffffff;">General Message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600; color:#ffffff;">一般メッセージ</span></p></body></html> + + + Message + メッセージ + + + Add Extra File + さらにファイルを追加 + + + Friend + 友達 + + + Add Message Destination + メッセージの宛先を追加 + + + Message Destination + メッセージの宛先 + + + Attachments + 添付 + + + Subject : + 件名: + + + + GeneralPage + + Keys manager + キーのマネージャー + + + Style + 様式 + + + Choose RetroShare's interface style + インターフェイス様式を選びなさい + + + Language + 言語 (Language) + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">言語への変更は適用を再始動した後だけ実施される!</p></body></html> + + + Choose the language used in RetroShare + Retroshareで使用される言語を選びなさい + + + Login + ログイン (Login) + + + + Startup + スタートアップ + + + + Start RetroShare when my system starts + システム起動時に Retoroshare を起動 + + + + Start minimized + 最小化して起動 + + + + Start minimized on system start + + + + + Misc + その他 + + + + Do not show the Quit RetroShare MessageBox + 終了時にメッセージボックスを表示しない + + + + Do not Minimize to Tray Icon + トレイ アイコンに最小化しない + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + 受信: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + 送信: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + Elastic Nodes + 活動中ノード + + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + 友達 + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + タイトル + + + + Description + 説明 + + + + Reset + リセット + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + そして + + + + and / or + そして / または + + + + or + または + + + + Name + + + + + Path + パス + + + + Extension + 拡張子 + + + + Hash + ハッシュ + + + + Date + + + + + Size + + + + + Popularity + 人気度 + + + + contains + 含む + + + + contains all + すべて含む + + + + is + です + + + + less than + 未満 + + + + less than or equal + 以下 + + + + equals + 等しい + + + + greater than or equal + 以上 + + + + greater than + より多い + + + + is in range + 範囲内 + + + + HelpBrowser + + + + Error Loading Help Contents: + ヘルプ コンテンツの読み込みエラー: + + + + Supplied XML file is not a valid Contents document. + 提供された XML ファイルは有効なコンテンツ ドキュメントではありません. + + + + Search reached end of document + ドキュメントの最後まで検索しました + + + + Search reached start of document + ドキュメントの最初まで検索しました + + + + Text not found in document + ドキュメント中にテキストが見つかりません + + + + Found %1 results + %1個の検索結果が見つかりました + + + + + Search + 検索 + + + + Home + ホーム + + + + Close + 閉じる + + + + + RetroShare Help + Retoroshare ヘルプ + + + + Find: + 検索: + + + + Find Previous + 前を検索 + + + + Find Next + 次を検索 + + + + Case sensitive + 大文字・小文字を区別 + + + + Whole words only + フレーズで検索 + + + + Contents + コンテンツ + + + + Help Topics + ヘルプ トピックス + + + + Searching for: + 検索中: + + + + Found Documents + ドキュメントを見つけました + + + + Back + 戻る + + + + Move to previous page (Backspace) + 前のページに移動 (Backspace) + + + + Backspace + + + + + Forward + 進む + + + + Move to next page (Shift+Backspace) + 次のページへ移動 (Shift+Backspace) + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + ホームへ移動 (Ctrl+H) + + + + Ctrl+H + + + + + + + Find + 検索 + + + + Search for a word or phrase on current page (Ctrl+F) + このページ内で検索 (Ctrl+F) + + + + Ctrl+F + + + + + Close Vidalia Help + what is vidalia? + Vidalia ヘルプを閉じる + + + + Esc + + + + + HelpDialog + + + About + バージョン情報 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShareは, オープンソース, クロスプラットフォーム, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">非公開, セキュア, 分散型のコミュニケーション プラットフォームです. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ピアの信頼性を認証するために WOT (Web of Trust) を使い, すべてのコミュニケーションを暗号化するために OpenSSL を使うため, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">あなたの友達と安全に共有することができます. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare は, ファイル共有, チャット, メッセージ, チャネルを提供します. </span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">以下の外部リンクから有益な詳細情報が得られます:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">RetroShare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">RetroShare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">RetroShare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + Authors + 作者 + + + + Thanks to + 謝辞 + + + + Translation + 翻訳 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + ライセンス許諾 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare について</span></p></body></html> + + + + HelpTextBrowser + + + Error opening help file: + ヘルプ ファイルのオープン エラー: + + + + Opening External Link + 外部リンクを開く + + + + Unable to Open Link + リンクを開けません + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + Retoroshare はデフォルトのウェブ ブラウザで選択されたリンクを開きます. ブラウザが TOR を使用するように設定されていなければ, リクエストは匿名ではありません. + + + + Do you want Retroshare to open the link in your Web browser? + ウェブ ブラウザでリンクを開きますか? + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + ウェブ ブラウザで選択されたリンクを開けません. URLをコピーしてブラウザに貼り付ることもできます. + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + リセット + + + + + Copy + コピー + + + + Remove + 削除 + + + + Mark all + + + + + Delete + 消去 + + + + Clear history + + + + + Send + 送信 + + + + InfoDialog + + + Info + 情報 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare は GPG キーを使用します. これは RetroShare のプロファイルを作成するために必要です. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">あなたはあなたの友達とEメールやその他の方法で GPG キーを交換する必要があります. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">友達の GPG キーを受け取ったら, RetroShare の「友達追加ウィザード」でそのキーを追加してください. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. Linux では GPA をインストールする必要があります :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. Windows では GPG キーを作成するために, gpg4win をインストールする必要があります :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. GPA で GPG キーを作成しようとして, それがうまく動作しない場合は, GPG キーの作成に WinPT を使用してください :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + IntroPage + + This wizard will help you to connect to your friend(s) to RetroShare network. There are three possible ways to do this: + このウィザードはあなたと友達が Retoroshare ネットワークに接続するお手伝いをします. 接続するには次の3通りの方法があります: + + + &Use *.rsc files with certificates + 認証に *.rsc ファイルを使用する (&U) + + + + &Make friend with selected friends of my friends + 選択されたあなたの友達の友達と, 友達になる (&M) + + + + Add a new Friend + 友達を新規追加 + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + 証明書を手動で入力 (&E) + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + LinksDialog + + + Share Link Anonymously + リンクを匿名で共有 + + + + Vote on Link + リンクに投票 + + + + Download + ダウンロード + + + + Expand + 展開 + + + + Hide + 非表示 + + + + File Request Confirmation + ファイルリクエストの確認 + + + + The file has been added to your download list. + ファイルはすでにダウンロードリストに追加されています. + + + + File Request canceled + ファイル リクエストがキャンセルされました + + + + The file has not been added to your download list, because you already have it. + そのファイルはすでに持っているためダウンロードリストには追加されません. + + + + File Request Error + ファイル リクエスト エラー + + + + The file link is malformed. + ファイルのリンクが不正です. + + + + From + 範囲 + + + + Show + 表示 + + + Form + フォーム + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">リンク クラウド</span></p></body></html> + + + + Title / Comment + タイトル/コメント + + + + Score + 得点 + + + + Peer / Link + ピア/リンク + + + + Sort by + 並び替え + + + + Combo + コンボ + + + + Time + 時間 + + + + Ranking + ランキング + + + + In last + 最新の + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + すべてのピア + + + + Own Links + 自分のリンク + + + + Top 100 + トップ100 + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + ワースト100 + + + + Link: + リンク: + + + + Add Anonymous Link + 匿名リンクを追加 + + + + Add Link/Comment + リンク/コメントを追加 + + + + Title: + タイトル: + + + + Score: + 得点: + + + + +2 Great! + +2 優良! + + + + +1 Good + +1 良好 + + + + 0 Okay + 0 普通 + + + + -1 Sux + -1 不良 + + + + -2 Bad Link + -2 リンク切れ + + + + Url: + URL:: + + + + Add new link + + + + + MainWindow + + + Network + ネットワーク + + + + Friends + 友達 + + + + + Transfers + 転送 + + + + + Messages + メッセージ + + + + + Channels + チャネル + + + + Blogs + ブログ + + + You has a new message + 新しいメッセージがあります + + + + Internal Error + 内部エラー + + + + + Options + オプション + + + + Hide + 非表示 + + + + Show + 表示 + + + + RetroShare + RetroShare + + + Invite Friend + 友人を誘いなさい + + + + MainWindow + メイン ウィンドウ + + + toolBar + ツールバー + + + + Add Friend + 友達を追加 + + + + Add a Friend Wizard + 友達追加ウィザード + + + + Add Share + 共有の追加 + + + + + Quick Start Wizard + クィック スタート ウィザード + + + + Search + 検索 + + + + Files + ファイル + + + Add Shared Directory + 共用登録簿を加えなさい + + + + Show/Hide + 表示/非表示 + + + + &Quit + 終了 (&Q) + + + + + + + You have %1 new message + + + + + Bandwidth Graph + 帯域グラフ + + + + Open Messenger + メッセンジャーを開く + + + + Minimize + 最小化 + + + + Maximize + 最大化 + + + + Links Cloud + リンク クラウド + + + + RetroShare %1 a secure decentralised communication platform + RetroShare %1 セキュアで分散型のコミュニケーション プラットフォーム + + + + Unfinished + 未完了 + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + + + + + Chat + チャット + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Help + ヘルプ + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + ファイルのリンクが不正です. + + + Online + オンライン + + + Busy + 取り込み中 + + + Away + 退席中 + + + + About + バージョン情報 + + + News Feed + ニュース フィード + + + + + Forums + フォーラム + + + + Open Messages + メッセンジャーを開く + + + + Applications + アプリケーション + + + Settings +  設定 + + + + Plugins + プラグイン + + + + Really quit ? + 本当に終了しますか? + + + + Do you really want to exit RetroShare ? + 本当に Retoroshare を終了しますか? + + + toolBar_2 + ツールバー_2 + + + + Quit + 終了 + + + + SMPlayer + + + + + Messenger + メッセンジャー + + + + MessageComposer + + + + Compose + 作成 + + + + + Contacts + コンタクト + + + + Search for Name: + + + + + Reset + リセット + + + + Send To: + 宛先: + + + + Subject: + 件名: + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + フォント サイズ + + + + Increase font size + フォントを拡大 + + + + Decrease font size + フォントを縮小 + + + + Bold + 太字 + + + + Underline + 下線 + + + + Italic + 斜体 + + + + Select Color + 色の選択 + + + + Alignment + 文字揃え + + + + Add a Image + イメージを追加 + + + + Sets text font to code style + フォントをコード スタイルに設定 + + + + Tags: + + + + + + Tags + + + + + Recommended Files + おすすめのファイル + + + + File Name + + + + + Size + + + + + Hash + ハッシュ + + + + Send + 送信 + + + + Send this message now + メッセージをすぐに送信 + + + + Reply + 返信 + + + + Toggle Contacts View + コンタクトの表示の切り替え + + + + Save + 保存 + + + + Save this message + このメッセージを保存 + + + + Attach + 添付 + + + + Attach File + ファイルを添付 + + + + Quote + 引用 + + + + Add Blockquote + 引用を追加 + + + + &Left + 左寄せ(&L) + + + + C&enter + 中央揃え(&E) + + + + &Right + 右寄せ(&R) + + + + &Justify + 均等揃え(&J) + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + メッセージを保存 + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + Compose: + 作成: + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + RetroShare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + 不明 + + + + Unknown friend + + + + + &File + ファイル(&F) + + + + &New + 新規(&N) + + + + &Open... + 開く(&O)... + + + + &Save + 保存(&S) + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + 印刷(&P)... + + + + &Export PDF... + PDFにエクスポート(&E)... + + + + &Quit + + + + + &Edit + 編集(&E) + + + + &Undo + 元に戻す(&U) + + + + &Redo + やり直す(&R) + + + + Cu&t + 切り取り(&T) + + + + &Copy + コピー(&C) + + + + &Paste + 貼り付け(&P) + + + + &View + 表示(&V) + + + + &Contacts Sidebar + コンタクト サイドバー(&C) + + + + &Insert + 挿入(&I) + + + + &Image + イメージ(&I) + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + ファイルを開く... + + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML ファイル (*.htm *.html);;すべてのファイル (*) + + + + Save as... + 名前をつけて保存... + + + + Print Document + ドキュメントを印刷 + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + メッセージは送信されていません. +メッセージを保存しますか ? + + + + Choose Image + イメージを選択 + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + サポートされているイメージ ファイル (*.png *.jpeg *.jpg *.gif) + + + + Add Extra File + さらにファイルを追加 + + + + + Drop file error. + ファイルのドロップ エラー. + + + + Directory can't be dropped, only files are accepted. + フォルダーはドロップできません. ファイルのみ可能です. + + + + File not found or file name not accepted. + ファイルが見つからないかファイル名が受け入れられません. + + + + MessagePage + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + 追加 + + + + Edit + + + + + Delete + 消去 + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + メッセージ + + + New Message + 新しいメッセージ + + + + Subject + 件名 + + + Play video + ビデオを再生 + + + Play button + 再生ボタン + + + Play the downloaded video + ダウンロードしたビデオを再生 + + + + <b>1 new Message from</b> + <b>新規メッセージ1件あります</b> + + + + Close + 閉じる + + + Close button + 閉じるボタン + + + Close the information dialog + 情報ダイアログを閉じる + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + + + + + Download all Recommended Files + + + + + Subject: + 件名: + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + + + + + Size + + + + + Hash + ハッシュ + + + + Print + 印刷 + + + + Print Preview + 印刷プレビュー + + + + No subject + + + + + Download + ダウンロード + + + + Download all + + + + + Hide + 非表示 + + + + Expand + 展開 + + + + File + ファイル + + + + Files + ファイル + + + + Print Document + ドキュメントを印刷 + + + + Save as... + 名前をつけて保存... + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML ファイル (*.htm *.html);;すべてのファイル (*) + + + + MessageWindow + + + New Message + + + + + Compose + 作成 + + + + Reply to selected message + + + + + Reply + 返信 + + + + Reply all to selected message + + + + + Reply all + 全員に返信 + + + + Forward selected message + + + + + Foward + 転送 + + + + Remove selected message + + + + + Delete + 消去 + + + + Print selected message + + + + + + Print + 印刷 + + + + Display + 表示 + + + + + + Tags + + + + + Print Preview + 印刷プレビュー + + + + + Buttons Icon Only + アイコンのみ + + + + Buttons Text Beside Icon + アイコンの横にテキスト + + + + Buttons with Text + テキスト + + + + Buttons Text Under Icon + アイコンの下にテキスト + + + + Set Text Under Icon + アイコンの下にテキストを設定 + + + + &File + ファイル(&F) + + + + Save &As File + + + + + &Print... + 印刷(&P)... + + + + Print Preview... + 印刷プレビュー... + + + + &Quit + + + + + MessagesDialog + + + + New Message + 新規メッセージ + + + + Quick View + + + + + Reply to Message + メッセージに返信 + + + + Remove Message + メッセージを削除 + + + + + Date + 日付 + + + + + + From + + + + Size + サイズ + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">おすすめのファイル </span></p></body></html> + + + + Reply + 返信 + + + + Reply all + 全員に返信 + + + + Foward + 転送 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">選択したメッセージを削除</p></body></html> + + + + Delete + 消去 + + + + Compose + 作成 + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + 表示 + + + + Reset + リセット + + + + Attachments + 添付 + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + 受信箱 + + + + + + + Outbox + 送信箱 + + + + Draft + 下書き + + + + + Sent + 送信済 + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + 印刷... + + + + Print Preview + 印刷プレビュー + + + + + Buttons Icon Only + アイコンのみ + + + + Buttons Text Beside Icon + アイコンの横にテキスト + + + + Buttons with Text + テキスト + + + + Buttons Text Under Icon + アイコンの下にテキスト + + + + Set Text Under Icon + アイコンの下にテキストを設定 + + + + Save As... + 名前をつけて保存... + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">選択したメッセージに返信</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">新規メッセージ</p></body></html> + + + Download All + すべてをダウンロードしなさい + + + Print Document + ドキュメントを印刷 + + + File Name + ファイル名 + + + Sources + ソース + + + + Forward selected Message + 選択したメッセージを転送 + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + メッセージを削除 + + + + Forward Message + メッセージを転送 + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + ダウンロード + + + + Empty trash + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + Click to sort by to + + + + File + ファイル + + + Files + ファイル + + + Compose: + 作成: + + + Hide + 非表示 + + + Expand + 展開 + + + + + + Drafts + 下書き + + + + To + + + + Anonymous + 匿名 + + + File Request Confirmation + ファイル リクエストの確認 + + + The file has been added to your download list. + ファイルはすでにダウンロードリストに追加されています. + + + File Request canceled + ファイル リクエストがキャンセルされました + + + The file has not been added to your download list, because you already have it. + そのファイルはすでに持っているためダウンロードリストには追加されません. + + + File Request Error + ファイル リクエスト エラー + + + The file link is malformed. + ファイルのリンクが不正です. + + + Save as... + 名前をつけて保存... + + + HTML-Files (*.htm *.html);;All Files (*) + HTML ファイル (*.htm *.html);;すべてのファイル (*) + + + + + + + + Total: + + + + + + Reply to All + 全員に返信 + + + + + Subject + 件名 + + + Subject: + 件名: + + + Date: + 日付: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">おすすめのファイルをすべてダウンロード</p></body></html> + + + Hash + ハッシュ + + + + Print + 印刷 + + + + MessagesPopupDialog + + New Message + 新しいメッセージ + + + Reply to Message + メッセージへの応答 + + + Remove Message + メッセージを取除きなさい + + + Download All + すべてをダウンロードしなさい + + + Messages + メッセージ + + + Inbox + 入って来る電子メール + + + Outbox + 出て行くのための電子メール + + + Draft + 草案 + + + Sent + 送られた電子メール + + + From + から + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">推薦されたファイル </span></p></body></html> + + + File Name + ファイル名前 + + + Size + サイズ + + + Sources + + + + Compose + 作成 + + + Remove + 削除 + + + Reply + 返信 + + + Forward + 転送 + + + Print + 印刷 + + + PrintPreview + 印刷プレビュー + + + + MessengerWindow + + + Expand all + すべて展開 + + + + Collapse all + すべて折りたたみ + + + + Chat + チャット + + + + Message Friend + 友達にメッセージを送る + + + + Connect To Friend + 友達に接続 + + + + Peer Details + ピア詳細 + + + + Recomend this Friend to... + + + + + Paste RetroShare Link + + + + + Export Friend + 友達をエクスポート + + + + Deny Friend + 友達を拒否 + + + + Remove Friend Location + 友達の場所を削除 + + + + <strong>GPG Key</strong> + <strong>GPG キー</strong> + + + + + + + location + + + + + <strong>RetroShare instance</strong> + <strong>RetroShare インスタンス</strong> + + + location : + 場所: + + + Peer Online + ピアがオンライン + + + Available + 利用可能 + + + Offline + オフライン + + + + Save Certificate + 証明書を保存 + + + + Certificates (*.pqi) + 証明書(*.pqi) + + + Friend Not Online + 友達はオンラインではありません + + + Your Friend is offline +Do you want to send them a Message instead + あなたの友達はオフラインです. +代わりにメッセージを送りますか + + + View + 表示 + + + Remove Friend + 友人を取除きなさい + + + RetroShare Messenger + Retoroshare メッセンジャー + + + + Click to Change your Avatar + クリックししてアバターを変更 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Change your Status and your display</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">picture here.</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">状態と表示の変更</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">画像はこちら.</p></body></html> + + + Online + オンライン + + + Busy + 取り込み中 + + + Change your Personal Status here... + ここで個人的な状態を変更... + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Search Friends + + + + + Reset + リセット + + + + + Sort Descending Order + 降順に並べ替え + + + + + Sort Ascending Order + 昇順に並べ替え + + + + Set root is Decorated + ルートを装飾する + + + + Set Root Decorated + ルートを装飾 + + + + Sort by State + + + + Set Root is not Decorated + ルートを装飾しない + + + + Hide Offline Friends + オフラインの友達を隠す + + + Away + 退席中 + + + Apear Offline + オフラインにする + + + + Share Files for your Friends + 友達ににファイルを共有 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Add a Friend</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">友達を追加</p></body></html> + + + + MsgFeed + + Inbox + 受信箱 + + + Outbox + 送信箱 + + + Sent + 送信済 + + + Date + 日付 + + + Form + フォーム + + + Msgs In: + メッセージ: + + + Drafts + 下書き + + + All + すべて + + + Sort By: + 並び替え: + + + Subject + 件名 + + + Received + 受信順 + + + New Msg + 新しいメッセージ + + + + MsgItem + + + Reply to Message + メッセージに返信 + + + Form + フォーム + + + + Remove Item + アイテムを削除 + + + Connected + 接続中 + + + + + Expand + 展開 + + + + Reply Message + + + + + Delete Message + メッセージを削除 + + + + Play Media + メディアを再生 + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + 非表示 + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + インターネット接続 + + + + No internet connection + インターネット接続なし + + + + No local network + ローカル ネットワークなし + + + + OK | RetroShare Server + OK | Retoroshare サーバ + + + + NetworkDialog + + Load Certificate + 負荷証明書 + + + Select a pem/pqi File + PEM/PQI ファイルを選択してください + + + File Not Found + ファイルが見つかりません + + + %1 does not exist. Would you like to create it? + %1 がありません. 作成しますか? + + + Failed to Create File + ファイルの作成に失敗 + + + Unable to create %1 [%2] + %1 を作成できません [%2] + + + + Copy RetroShare Link + + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + 認証済 + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + はあなたを認証しています. +接続できるようにするためには, 右クリックして ’友達になる’ を選択してください. + + + Select Certificate + 証明書を選択 + + + Certificates (*.pqi *.pem) + 証明書 (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">ネットワーク:</span></p></body></html> + + + Accept + 受容 + + + Trust + 信頼 + + + Last Contact + 最後の接触 + + + + + + Name + 名前 + + + Peer Address + 同等者の住所 + + + Organisation + 構成 + + + Location + 位置 + + + Country + + + + + + Cert Id + 証明書 ID + + + Welcome to RetroShare. + Retoroshare へようこそ. + + + Menu + メニュー + + + Trust matrix + 信頼マトリックス + + + + Authentication matrix + 認証 マトリックス + + + + Network View + + + + RetroShare %1 started. + Retoroshare %1 が起動しました. + + + + Deny friend + 友達を拒否 + + + + Make friend + 友達になる + + + + Delete certificate + 証明書を削除 + + + + Export my Cert + あなたの証明書をエクスポート + + + + Peer details... + ピア詳細... + + + Authenticated + 認証済 + + + GPG key signed + GPG キーが署名済 + + + Not Authenticated + 未認証 + + + GPG key not signed + GPG キーが未署名 + + + + Unknown + 不明 + + + + yourself + + + + RetroShare + RetroShare + + + Please choose a filename + ファイル名を選択してください + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare 証明書 (*.rsc); すべてのファイル (*) + + + Certificate file successfully created + 証明書ファイルは正常に作成されました + + + Sorry, certificate file creation failed + 署名書ファイルの作成に失敗しました + + + UPNP is active. + UPNPが有効. + + + UPNP NOT FOUND. + UPNPが見つかりません. + + + Stun external address detection is working. + STUN 外部アドレス検出が動作中. + + + Stun is not working. + STUN が動作していません. + + + Local network detected + ローカルネットワークが検出されました + + + No local network detected + ローカルネットワークが検出されませんでした + + + ip found via external address finder + 外部ネットワーク ファインダーでIPが検出されました + + + external address finder didn't found anything + 外部ネットワーク ファインダーは何も検出しませんでした + + + DHT is not working (down). + DHTは動作していません (ダウン). + + + Form + フォーム + + + + Network + ネットワーク + + + + + Did I authenticated peer + ピアへの認証 + + + + Did I sign his gpg key + ピアのGPG キーへの署名 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + ピア ID + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">表示</span></p></body></html> + + + Log + ログ + + + + Network Status + ネットワーク状態 + + + + Local network + ローカル ネットワーク + + + + UPnP + UPnP + + + + + Did peer authenticated me + ピアによる認証 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ネットワーク:</span></p></body></html> + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + GPG WOT (Web of Trust) によって認証されていないキーを表示 + + + + External ip address finder + 外部 IP アドレス ファインダー + + + + Clear + クリア + + + + Set Tabs Right + タブを右側に設定 + + + + Set Tabs North + タブを上側に設定 + + + + Set Tabs South + タブを下側に設定 + + + + Set Tabs Left + タブを左側に設定 + + + + Set Tabs Rounded + タブを丸める + + + + Set Tabs Triangular + タブを三角にする + + + + Add Friend + 友達を追加 + + + + Copy My Key to Clipboard + キーをクリップボードにコピー + + + + Export My Key + キーをエクスポート + + + + Create New Profile + プロファイルを新規作成 + + + + Create a new Profile + プロファイルを新規作成 + + + + NetworkPage + + Rate Options + 速度の選択 + + + Max Total Data Rate (KB/S): + あなたの最高のアップロードの速度 (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">一人につき速度 (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + 設定を非表示 + + + Show Settings + 設定を表示 + + + Settings + 設定 + + + Form + フォーム + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + 友達 + + + + Edge length: + + + + Refresh + 更新 + + + Show Friends of Friends + 友達の友達を表示 + + + Connect Signature + 署名に接続 + + + Draw Friend Connections + 友達の接続を表示 + + + + NewTag + + + New Tag + + + + + Name: + 名前: + + + + Choose color + + + + + OK + OK + + + + Cancel + + + + + NewsFeed + + Form + フォーム + + + + Remove All + すべてを削除 + + + + Options + オプション + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">ニュース フィード</span></p></body></html> + + + + NotifyPage + + + News Feed + ニュース フィード + + + + Peers + ピア + + + + Channels + チャネル + + + + Forums + フォーラム + + + + Chat + チャット + + + + Blogs + ブログ + + + + Messages + メッセージ + + + Downloads + ダウンロード + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + メッセージ + + + + Channel Post + チャネル投稿 + + + + Forum Post + フォーラム投稿 + + + + + Download completed + + + + + Combined icon + + + + + Toasters + トースタ + + + + Friend Connect + + + + Peer Connect + ピア接続 + + + + New Message + 新しいメッセージ + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + プライベート チャット + + + + Open Window for new chat + + + + Open Window for new Peer Chat + 新しいピア チャットでウィンドウを開く + + + Reopen if closed by user: + ユーザーが閉じた場合再度開く: + + + + Grab Focus when chat arrives + チャットが届いた時フォーカスを取得 + + + + Use a single tabbed window + + + + + Group chat + グループ チャット + + + + Display systray message + システムトレイにメッセージを表示 + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + GPG キー パスワード + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + Please enter the password to unlock the following GPG key: + + 次の GPG キーをアンロックするためにパスワードを入力してください: + + + + + OnlineToaster + + Peer Online + ピアがオンライン + + + + Friend Online + + + + + PeerDefs + + Anonymous + 匿名 + + + + + Unknown + 不明 + + + + PeerItem + + Make Friend + 友達になる + + + Remove Friend + 友達から削除 + + + + Chat + チャット + + + + Start Chat + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Peer Id:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ピア ID</span></p></body></html> + + + Organisation + 組織 + + + + Location + 場所 + + + Country + + + + Form + フォーム + + + + Remove Item + アイテムを削除 + + + Connected + 接続中 + + + + + Expand + 展開 + + + + Write a quick Message + + + + + Send + 送信 + + + + Cancel + + + + + Peer ID: + + + + + Write Message + + + + + Status: + 状態: + + + + Trust: + 信頼: + + + Good + 良好 + + + Send Mail + メールを送信 + + + + Name: + 名前: + + + + IP Address + IP アドレス + + + + Connection Method + 接続方法 + + + Last Contact: + 最新のコンタクト: + + + + Friend + 友達 + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + ピア + + + + + + + + + + + + Unknown Peer + + + + + Hide + 非表示 + + + + Quick Message + + + + + PeerStatus + + Online: 0 | Friends: 0 | Network: 0 + オンライン: 0 | 友達: 0 | ネットワーク: 0 + + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + 友達 + + + Online + オンライン + + + <span style="color:#000000"><strong>Friends:</strong></span> + <span style="color:#000000"><strong>友達:</strong></span> + + + <span style="color:#0000FF"><strong>Online:</strong></span> + <span style="color:#0000FF"><strong>オンライン:</strong></span> + + + Online: + オンライン: + + + Friends: + 友達: + + + Network: + ネットワーク: + + + + PeersDialog + + Chat + チャット + + + Export Friend + 友達をエクスポート + + + Remove Friend + 友人を取除きなさい + + + Save Certificate + 証明書を保存 + + + Certificates (*.pqi) + 証明書(*.pqi) + + + Status + 状態 + + + Person + パーソン + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">友人</span></p></body></html> + + + Connect To Friend + 友達に接続 + + + Welcome to RetroShare's group chat. + Retoroshare のグループチャットにようこそ. + + + Profile + プロファイル + + + Expand all + すべて展開 + + + Collapse all + すべて折りたたみ + + + Message Friend + 友達にメッセージを送る + + + Peer Details + ピア詳細 + + + Deny Friend + 友達を拒否 + + + Remove Friend Location + 友達の場所を削除 + + + <strong>GPG Key</strong> + <strong>GPG キー</strong> + + + <strong>RetroShare instance</strong> + <strong>RetroShare インスタンス</strong> + + + location : + 場所: + + + Online + オンライン + + + Peer Online + ピアがオンライン + + + Away + 退席中 + + + Busy + 取り込み中 + + + Available + 利用可能 + + + Offline + オフライン + + + Friend Not Online + 友達はオンラインではありません + + + Your Friend is offline +Do you want to send them a Message instead + あなたの友達はオフラインです. +代わりにメッセージを送りますか + + + RetroShare + RetroShare + + + Create a new Channel + チャネルを新規作成 + + + New Channel + 新規チャネル + + + Add Extra File + さらにファイルを追加 + + + File Request Confirmation + ファイル リクエストの確認 + + + The file has been added to your download list. + ファイルはすでにダウンロードリストに追加されています. + + + File Request canceled + ファイル リクエストがキャンセルされました + + + The file has not been added to your download list, because you already have it. + そのファイルはすでに持っているためダウンロードリストには追加されません. + + + File Request Error + ファイル リクエスト エラー + + + The file link is malformed. + ファイルのリンクが不正です. + + + Drop file error. + ファイルのドロップ エラー. + + + File not found or file name not accepted. + ファイルが見つからないかファイル名が受け入れられません. + + + Directory can't be dropped, only files are accepted. + フォルダーはドロップできません. ファイルのみ可能です. + + + News Feed + ニュース フィード + + + Friend + 友達 + + + Save as... + 名前をつけて保存... + + + me + 自分 + + + Send + 送信 + + + Profile View + プロファイル表示 + + + Italic + 斜体 + + + Underline + 下線 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">友達</span></p></body></html> + + + Add + 追加 + + + hide unconnected + 未接続を非表示 + + + Add or Change your Avatar + アバターの追加または変更 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; color:#00aa00;">nickname (me)</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; color:#00aa00;">ニックネーム (自分)</span></p></body></html> + + + Edit Personal message + パーソナル メッセージを編集 + + + Live Chat + ライブ チャット + + + Bold + 太字 + + + Create New Forum + フォーラムを新規作成 + + + Create new Forum + フォーラムを新規作成 + + + Create New Channel + チャネルを新規作成 + + + Create new Channel + チャネルを新規作成 + + + Add your Avatar Picture + アバターの画像を追加 + + + Set your Personal Message + パーソナルメッセージを設定 + + + Edit your status Message + 状態メッセージを編集 + + + Sort Descending Order + 降順に並べ替え + + + Sort Ascending Order + 昇順に並べ替え + + + Disable Emoticons + 気分を無効化 + + + Hide Offline Friends + オフラインの友達を隠す + + + Add Friend + 友達を追加 + + + Display + 表示 + + + Text Color + 文字色 + + + Create new Profile + プロファイルを新規作成 + + + Font + フォント + + + Friends + 友達 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">set Text Color</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">文字色を設定</span></p></body></html> + + + Attach File + ファイルを添付 + + + Clear Chat History + チャットの履歴をクリア + + + + PeersFeed + + Save Certificate + 証明書を保存 + + + Certificates (*.pqi) + 証明書(*.pqi) + + + Friends + 友達 + + + Form + フォーム + + + Show: + 表示: + + + Online Friends + オンラインの友達 + + + Friends of Friends. + 友達の友達. + + + All Peers + すべてのピア + + + + PhotoDialog + + + Insert Show Lists + 表示リストを挿入 + + + + Open + 開く + + + + Remove + 削除 + + + + Excellent + 優秀 + + + + Good + 良好 + + + + Average + 平均的 + + + + Below avarage + 平均以下 + + + + Bad + 不良 + + + + Unrated + 未評価 + + + + Rating + 評価 + + + + + Date + 日付 + + + + + Location + 場所 + + + + Size + サイズ + + + Form + フォーム + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">フォト ビュー</span></p></body></html> + + + + Peer + ピア + + + + Slideshow + スライドショー + + + + Photo + フォト + + + + Thumb Image + サムネイル イメージ + + + + Image Name + イメージ名 + + + + + Comment + コメント + + + + PeerId + ピア ID + + + + PhotoId + フォト ID + + + + + Add Photo(s) + フォトを追加 + + + + Add Photo SlideShow + フォトをスライドショーに追加 + + + + Update Details + 詳細をアップデート + + + + Photo + フォト + + + + Description + 説明 + + + + PhotoShow + + Form + フォーム + + + + Date: + 日付: + + + + Location: + 場所: + + + + Comment: + コメント: + + + + Display Size: + 表示サイズ: + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + フルサイズ + + + + Play Rate: + 表示速度: + + + + 1 Sec + 1秒 + + + + 2 Sec + 2秒 + + + + 5 Sec + 5秒 + + + + 10 Sec + 10秒 + + + + 20 Sec + 20秒 + + + + 1 Min + 1分 + + + + Edit Photo Details + フォト詳細を編集 + + + + Save Photo + フォトを保存 + + + + No Photo Selected + フォトが選択されていません + + + + Start + 最初から + + + + Back + 巻き戻し + + + + Photo Show + フォト ショー + + + + Play + 再生 + + + + Pause + ポーズ + + + + Forward + 早送り + + + + PluginFrame + + + Remove + 削除 + + + + PluginManagerWidget + + + Install New Plugin... + 新しいプラグインをインストール... + + + + Open Plugin to install + インストールするプラグインを開く + + + + Plugins (*.so *.dll) + プラグイン (*.so *.dll) + + + + PopularityDefs + + + Popularity + 人気度 + + + + PopupChatDialog + + Paste retroshare Link + Retoroshare リンクを貼り付け + + + Friend Not Online + 友達はオンラインではありません + + + RetroShare + RetroShare + + + + Your Friend is offline +Do you want to send them a Message instead + あなたの友達はオフラインです. +代わりにメッセージを送りますか + + + + Friend not Online + + + + + Paste RetroShare Link + + + + + is typing... + + + + + Hide Avatar + アバターを非表示 + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + アバターを表示 + + + Open Style + スタイルを開く + + + Styles (*.htm) + スタイル (*.htm) + + + + Save as... + 名前をつけて保存... + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + 送信 + + + RetroShare - Encrypted Chat + RetroShare - 暗号化チャット + + + MainWindow + メイン ウィンドウ + + + + Close + 閉じる + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Set Chat Window Style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">チャット ウィンドウのスタイルを設定</p></body></html> + + + + + Bold + 太字 + + + + + Underline + 下線 + + + + + Italic + 斜体 + + + Set Font + フォント設定 + + + + Font + フォント + + + + Text Color + 文字色 + + + + Clear Chat History + チャットの履歴をクリア + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + toolBar + ツールバー + + + + Strike + + + + Avatar + アバター + + + Set your Avatar Picture + アバターの画像を設定 + + + Clear Chat + チャットをクリア + + + + Disable Emoticons + 気分を無効化 + + + + + Save Chat History + + + + + Clear offline messages + + + + Chatting with + チャットする + + + + Add Extra File + さらにファイルを追加 + + + File Request Confirmation + ファイル リクエストの確認 + + + The file has been added to your download list. + ファイルはすでにダウンロードリストに追加されています. + + + File Request canceled + ファイル リクエストがキャンセルされました + + + The file has not been added to your download list, because you already have it, or you're already downloading it. + そのファイルはすでに持っているためダウンロードリストには追加されません. + + + File Request Error + ファイル リクエスト エラー + + + The file link is malformed. + ファイルのリンクが不正です. + + + + + Drop file error. + ファイルのドロップ エラー. + + + + File not found or file name not accepted. + ファイルが見つからないかファイル名が受け入れられません. + + + + Directory can't be dropped, only files are accepted. + フォルダーはドロップできません. ファイルのみ可能です. + + + + Add a File for your Friend + 友達宛のファイルを追加 + + + + PopupChatWindow + + + Avatar + アバター + + + + Set your Avatar Picture + アバターの画像を設定 + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + RetroShare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PrintPreview + + + RetroShare Message - Print Preview + RetoroShare メッセージ - 印刷プレビュー + + + + Print + 印刷 + + + + &Print... + 印刷(&P)... + + + + Page Setup... + ページ設定... + + + + Zoom In + ズームイン + + + + Zoom Out + ズームアウト + + + + &Close + 閉じる (&C) + + + + ProfileEdit + + + Remove Profile Entry + プロファイルのエントリーを削除 + + + + Move Profile Entry Up + プロファイルのエントリーを上に移動 + + + + Move Profile Entry Down + プロファイルのエントリーを下に移動 + + + + Profile Edit + プロファイル編集 + + + + Profile + プロファイル + + + + Category + カテゴリ + + + + Thoughts + 目的 + + + + Edit Profile Category + プロファイルのカテゴリを編集 + + + + Birthday + 誕生日 + + + + School + 学校 + + + + University + 大学 + + + + Phone Number + 電話番号 + + + + Favourite Books + お気に入りの本 + + + + Favourite Music + お気に入りの音楽 + + + + Favourite Films + お気に入りの映画 + + + + or Custom Entry + カスタム エントリー + + + + Add Entry + エントリーを追加 + + + + + Move + 移動 + + + + Close Editor + エディタを閉じる + + + + ProfileView + + + Clear Photo + フォトをクリア + + + + Change Photo + フォトを変更 + + + + + Edit Profile + プロファイルを編集 + + + + Remove Favourite + お気に入りを削除 + + + + Clear Favourites + お気に入りをクリア + + + + Download File + ファイルをダウンロード + + + + Download All + すべてダウンロード + + + + RetroShare + RetroShare + + + + Error : cannot get peer details. + エラー: ピア詳細を取得できません. + + + + + Name + 名前 + + + + Peer ID + ピア ID + + + + Size + サイズ + + + + Profile View + プロファイル表示 + + + Rs ID + RS ID + + + + Last Post: + 最新の投稿: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">プロファイル</span></p></body></html> + + + + Category + カテゴリ + + + + Thoughts + 目的 + + + + Favourite Files + お気に入りのファイル + + + + Hash + ハッシュ + + + + Close Profile + プロファイルを閉じる + + + + ProfileWidget + + Form + フォーム + + + + + Edit Personal message + パーソナル メッセージの編集 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">パブリック情報</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">パブリック情報</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">名前:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">場所:</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">ピア ID</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">その他の情報</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">友達の数</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">バージョン</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">アドレス</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">ローカル アドレス:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">外部アドレス:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + Addresses list + アドレス リスト + + + + QObject + + Name + 名前 + + + Path + パス + + + Extension + 拡張子 + + + Date + 日付 + + + Size + サイズ + + + Popularity + 人気度 + + + contains + 含む + + + contains all + すべて含む + + + is + です + + + less than + 未満 + + + less than or equal + 以下 + + + greater than or equal + 以上 + + + greater than + より多い + + + is in range + 範囲内 + + + and + そして + + + and / or + そして / または + + + or + または + + + equals + 等しい + + + Hash + ハッシュ + + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + ログインに失敗 + + + + Maybe password is wrong + おそらくパスワードが間違っています + + + + File Request Confirmation + + + + + The file has been added to your download list. + ファイルはすでにダウンロードリストに追加されています. + + + + + File Request canceled + ファイル リクエストがキャンセルされました + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + そのファイルはすでに持っているためダウンロードリストには追加されません. + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + ファイル リクエスト エラー + + + + The file link is malformed. + ファイルのリンクが不正です. + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + 友達を拒否 + + + + Make friend + 友達になる + + + + Peer details + ピア詳細 + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + クィック スタート ウィザード + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Choos which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">RetroShare へようこそ!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">このクィック スタート ウィザードは, ほんの数ステップでRetoroshareを設定するお手伝いをします.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">もしあなたが上級ユーザーならば, ツールバーからRetoroshareのすべての設定を行うことができます. 終了をクリックすれば, いつでもウィザードを終了できます.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">このウィザードは以下のようなアシストをします.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> インターネット接続についてRetoroshareに教える.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> どのファイルを共有するか選択する.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> RetroShare を使い始める.</span></p></body></html> + + + + + + Next > + 次へ > + + + + + + + Exit + 終了 + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + よりよいパフォーマンスのために, Retoroshareはあなたのインターネット接続について少し知る必要があります. + + + + Choose your upload speed limit: + アップロード速度の制限を選択してください: + + + + + KB/s + + + + + Choose your download speed limit: + ダウンロードスピードの制限を選択してください: + + + + Connection : + 接続: + + + + Automatic (UPnP) + 自動 (UPnP) + + + + Firewalled + ファイアーウォール内 + + + + Manually forwarded port + 手動でポート フォーワーディング + + + Dicovery : + 開示: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + Discovery : + 開示: + + + Share Ip and information with your friend (Disc On) + あなたの友達と IP その他の情報を共有する (開示オン) + + + Don't share any information (Disc Off) + 情報を何も共有しない (開示 オフ) + + + + Dynamic DNS: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + + < Back + < 戻る + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">これは共有フォルダのリストです. 左側のボタンを使ってフォルダを追加または削除できます. 新しくフォルダを追加した場合, そのフォルダ内のすべてのファイルは最初に共有されます.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">それぞれの共有フォルダに対して,個別に共有フラグを設定できます:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">ブラウズ可能 </span><span style=" font-family:'Sans'; font-size:8pt;">: 直接の友達がファイルをブラウズ可能.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">ネットワーク全体</span><span style=" font-family:'Sans'; font-size:8pt;">: 匿名トンネルを経由して誰でもファイルをダウンロード可能.</span></p></body></html> + + + + Directory + フォルダ + + + + Network Wide + ネットワーク全体 + + + + Browseable + ブラウズ可能 + + + + Add + 追加 + + + + Remove + 削除 + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Retoroshareをお楽しみください!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">これが最後のステップです! Retoroshareがあなたのコンピューターで動作するための設定はほとんど終わりました. .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ここでは Retoroshare がいつ,どのように起動するかを設定します.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Do not show a message when Closing RetroShare + Retoroshare が閉じるときメッセージを表示しない + + + + Start Minimized + 最小化して起動 + + + + Start RetroShare when my System Starts. + システム起動時に Retoroshare を起動. + + + + Start minimized on system start + + + + + Finish + 完了 + + + + Select A Folder To Share + 共有するフォルダを選択 + + + + Shared Directory Added! + 共有フォルダが追加されました! + + + + Do you really want to stop sharing this directory ? + 本当にこのフォルダの共有を中止しますか? + + + + Warning! + 警告! + + + + RSettingsWin + + + General + 一般 + + + + Directories + フォルダ + + + + Server + サーバ + + + + Transfer + 転送 + + + + Notify + 通知 + + + + Security + セキュリティ + + + + Message + メッセージ + + + + Forum + フォーラム + + + + Chat + チャット + + + + Appearance + 外観 + + + File Associations + ファイルの関連付け + + + + Sound + サウンド + + + + UnknownPage + 不明なページ + + + + Error Saving Configuration on page + + + + Error Saving Configuration + 設定の保存エラー + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>下り:</strong> 0.00 (kB/s) | <strong>上り:</strong> 0.00 (kB/s) + + + + <strong>Down:</strong> + <strong>下り::</strong> + + + + <strong>Up:</strong> + <strong>上り:</strong> + + + Down: + 下り: + + + Up: + 上り: + + + + RemoteDirModel + + Friends Directories + 友達のフォルダ + + + My Directories + 自分のフォルダ + + + Size + サイズ + + + Share Type + 共有の種類 + + + What's new + 最新情報 + + + Rank + ランク + + + Age + 経過時間 + + + FILE + ファイル + + + Anonymous + 匿名 + + + Files + ファイル + + + File + ファイル + + + DIR + フォルダ + + + + RetroshareDirModel + + + Anonymous + 匿名 + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + 無効な文字コードが指定されました: + + + + Invalid GUI style specified: + 無効なGUIスタイルが指定されました: + + + + Resets ALL stored RetroShare settings. + 保存された Retoroshare の設定をすべてリセット. + + + + Sets the directory RetroShare uses for data files. + RetroShare がデータファイルとして使用するフォルダを設定. + + + + Sets the name and location of RetroShare's logfile. + Retoroshare のログファイルの名前と場所を設定. + + + Sets the verbosity of Vidalia's logging. + Vidaliaのログ出力の詳細さを設定. + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + Retoroshare のインターフェイス スタイルを設定. + + + + Sets RetroShare's interface stylesheets. + Retoroshare のインターフェイス スタイルシートを設定. + + + + Sets RetroShare's language. + Retoroshare の言語を設定. + + + + RetroShare Usage Information + Retoroshare の使用方法 + + + + Invalid log level specified: + 無効なログ レベルが指定されました: + + + + Unable to open log file '%1': %2 + ログファイル '%1" が開けません: %2 + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + ソース + + + + Results + 結果 + + + + Close all Search Resullts + + + + + Close All Search Results + 検索結果をすべてクリア + + + + Download Selected + + + + + + Download + ダウンロード + + + + Enter a keyword here (at least 3 char long) + キーワードをここに入力 (最低3文字以上) + + + Copy retroshare Link + Retoroshare リンクをコピー + + + Send retroshare Link + Retoroshare リンクを送信 + + + Broadcast on Channel + チャネルにブロードキャスト + + + Recommend to Friends + 友達におすすめ + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + 削除 + + + + Remove All + すべてを削除 + + + + + Folder + フォルダ + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">フォーマット</p></body></html> + + + + Any + すべて + + + + Audio + オーディオ + + + + Video + ビデオ + + + Images + イメージ + + + Programs + プログラム + + + Archives + アーカイブ + + + Documents + 文書 + + + + Download Notice + ダウンロード通知 + + + + Skipping Local Files + ローカル ファイルをスキップ + + + + + Sorry + + + + + + This function is not yet implemented. + この機能はまだ実装されていません. + + + + Size + サイズ + + + + Type + 種類 + + + + Archive + アーカイブ + + + + CD-Image + CD イメージ + + + + Document + ドキュメント + + + + Picture + 画像 + + + + Program + プログラム + + + + Directory + フォルダ + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enter a Keyword here</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ここにキーワードを入力</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Close all Search Resullts</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">検索結果をすべて閉じる</span></p></body></html> + + + Clear all Search Results + 検索結果をすべてクリア + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Download Selected</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">選択されたものをダウンロード</span></p></body></html> + + + + Include files from your own file list in the search result + 検索結果に自分のファイルリストのファイルを含める + + + + Include own files + 自分のファイルを含める + + + + Search inside "browsable" files of your friends + 友達の”ブラウズ可能”なファイルを検索 + + + + Search in friends lists + 友達のリストを検索 + + + + Multi-hop search at distance 6 in the network +(always reports available files) + ネット-ワーク上で6ホップまでマルチ・ホップ検索 +(利用可能なファイルを常に報告) + + + + F2F search + F2F検索 + + + + Limit number of results to : + 検索結果数を制限: + + + + Filename + ファイル名 + + + + Start Search + 検索開始 + + + + Search + 検索 + + + + Reset + リセット + + + + Enter a Keyword here + + + + + Advanced Search + 高度な検索 + + + + Advanced + 高度 + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + + + + + File Size + + + + + Age + 経過時間 + + + + Hash + ハッシュ + + + + KeyWords + キーワード + + + + Search Id + 検索 ID + + + + SendLinkDialog + + Send RetroShare link + Retoroshare リンクを送信 + + + Send + 送信 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:22pt; color:#ffffff;">Send RetroShare Link</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:22pt; color:#ffffff;">Retoroshare リンクを送信</span></p></body></html> + + + + ServerPage + + Change + Restart Server + 変更+再始動 + + + Server Settings + 同等者の設定 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">外的な住所:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">現住所: </p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + + + + Automatic (Upnp) + 自動 (UPnP) + + + + Firewalled + ファイアーウォール内 + + + + Manual Forwarded Port + 手動でポート フォーワーディング + + + Should be disabled if you don't want to share connection information between peers. + ピア間で接続情報を共有したくない場合は無効にしてください. + + + Discovery Enabled + 開示を有効化 + + + Discovery Disabled + 開示を無効化 + + + + Download (KB/s) + ダウンロード (KB/s) + + + + Upload (KB/s) + アップロード (KB/s) + + + + + Network Configuration + ネットワークの設定 + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + ここをチェックしない場合, Retoroshareはファイアウォール内の直接接続できないピア同士でトンネル接続を行いません. この設定はF2Fルーティング (タートル ルータ) とは独立しています. + + + + Allow Tunnel Connection + トンネル接続を許可 + + + + Local Address + ローカル アドレス + + + + External Address + 外部アドレス + + + + Dynamic DNS + + + + + + Port: + ポート: + + + + Show Discovery information in statusbar + + + + + IP Service + IP サービス + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + ここをチェックしない場合, Retoroshareは誰かと接続した場合のみ +あなたのIPを決定できます. チェックすると友達がほとんどいない場合 +にも接続可能です. またファイアーウォールやVPN内にいる場合も +同様です. + + + + Allow RetroShare to ask my ip to these websites: + RetroShareが以下のウェブサイトにあなたのIPアドレスを問い合わせるのを許可: + + + Misc + 雑多 + + + behinde Firewall + 防火壁の後ろ + + + Forwarded External Port + 進められた外的な港(ルーター) + + + + Transfer Rates + 転送速度 + + + + Settings + + Settings +  設定 + + + + Options + オプション + + + + Transfer + 転送 + + + + Notify + 通知 + + + + Security + セキュリティ + + + + Message + メッセージ + + + + Forum + フォーラム + + + + Chat + チャット + + + + Appearance + 外観 + + + + Sound + サウンド + + + + Cancel + キャンセル + + + Apply + 適用 + + + + OK + OK + + + + General + 一般 + + + Network + ネットワーク + + + + Server + サーバ + + + + Directories + フォルダ + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + ブラウズ + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + ブラウズ可能 + + + + Anonymous shared Network Wide + + + + + Network Wide + ネットワーク全体 + + + Anonymous + 匿名 + + + + Browseable by Friends + + + + Friends + 友達 + + + + OK + OK + + + + Cancel + + + + + Select A Folder To Share + 共有するフォルダを選択 + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + RetroShare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + 共有フォルダを追加 + + + + Stop sharing selected Directory + 選択したフォルダの共有を中止 + + + Select A Folder To Share + 共有するフォルダを選択 + + + Do you really want to stop sharing this directory ? + 本当にこのフォルダの共有を中止しますか? + + + + + Remove + 削除 + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + 警告! + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + ファイルのドロップ エラー. + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + Shared Directory Added! + 共有フォルダが追加されました! + + + + RetroShare Share Manager + Retoroshare 共有マネージャ + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">共有マネージャ</span></p></body></html> + + + + Shared Folder Manager + 共有フォルダ マネージャ + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable </span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + 'intially' is typo of 'initially'? + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">これは共有フォルダのリストです. 左側のボタンを使ってフォルダを追加または削除できます. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">新しくフォルダを追加した場合, そのフォルダ内のすべてのファイルは最初に共有されます.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">それぞれの共有フォルダに対して,個別に共有フラグを設定できます:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">ブラウズ可能 </span><span style=" font-family:'Sans'; font-size:8pt;">: 直接の友達がファイルをブラウズ可能.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">ネットワーク全体 </span><span style=" font-family:'Sans'; font-size:8pt;">: 匿名トンネルを経由して誰でもファイルをダウンロード可能.</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + フォルダ + + + + Virtual Folder + + + + + Network Wide + ネットワーク全体 + + + + Browsable + ブラウズ可能 + + + + Add + 追加 + + + + Close + 閉じる + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + ダウンロード + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">ファイル</span></p></body></html> + + + + Checking... + 確認中... + + + + Check files + ファイルを確認 + + + + Copy retroshare Link + Retoroshare リンクをコピー + + + + Send retroshare Link + Retoroshare リンクを送信 + + + Recommend (Automated message) To + おすすめする (自動メッセージ) + + + Recommend in a message to + メッセージでおすすめする + + + + Copy retroshare Links to Clipboard + クリップボードにRetoroshare リンクをコピー + + + + Copy retroshare Links to Clipboard (HTML) + クリップボードにRetoroshare リンクをコピー (HTML) + + + + Send retroshare Links + Retoroshare リンクを送信 + + + + Send retroshare Links (HTML) + Retoroshare リンクを送信 (HTML) + + + Send retroshare Links to Chat + チャットでRetoroshare リンクを送信 + + + + Send retroshare Links to Cloud + クラウドに Retoroshare リンクを送信 + + + + Add Links to Cloud + リンクをクラウドに追加 + + + + + Open File + ファイルを開く + + + + Open Folder + フォルダを開く + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + このファイルを開くためのコマンドを設定 + + + + <strong>My Shared Files</strong> + <strong>自分の共有ファイル</strong> + + + + <strong>Friends Files</strong> + <strong>友達のファイル</strong> + + + + <strong>Files</strong> + <strong>ファイル</strong> + + + + Splitted View + 分割されたビュー + + + + Friends Folders + 友達のフォルダ + + + + My Folders + 自分のフォルダ + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">ファイル</span></p></body></html> + + + + All + すべて + + + + One day old + 1日経過 + + + + One Week old + 1週間経過 + + + + One month old + 1ヶ月経過 + + + + Search files + + + + + Start Search + 検索開始 + + + + Reset + リセット + + + + Tree view + + + + + Flat view + + + + + Download selected + 選択したものをダウンロード + + + + check files + ファイルを確認 + + + + SoundPage + + + Sound Events + サウンド イベント + + + User + ユーザ + + + + go Online + オンライン + + + go Offline + オフライン + + + + Friend + 友達 + + + + + + + + Browse + ブラウズ + + + + New Msg + 新しいメッセージ + + + + FileSend + ファイル送信 + + + + + Finished + 完了 + + + + FileRecive + ファイル受信 + + + + Incoming + ダウンロード + + + + Chatmessage + チャット メッセージ + + + New + 新規 + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + RetroShare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">ログイン</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + ログイン + + + + Remember Password + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Create new Profile...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">新規プロファイルを作成...</span></a></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">情報...</span></a></p></body></html> + + + + Name (GPG Id) - location: + 名前 (GPG ID) - 場所: + + + Name - location: + 名前 - 場所: + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + ログインに失敗 + + + + Maybe password is wrong + おそらくパスワードが間違っています + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + Create a New Profil + プロファイルを新規作成 + + + This will generate a new Profile + Are you sure you want to continue + 新規プロファイルが作成されます + 続行しますか + + + + StatisticDialog + + + Statistics + 統計 + + + + Download + ダウンロード + + + + Session: + セッション: + + + + + Downloaded: + ダウンロード済: + + + Average Downloadspeed: + Average Downloadspeed: + + + + + Count of Downloads: + ダウンロード数: + + + + + + Overall + 全体 + + + + Upload + アップロード + + + + + + Session + セッション + + + + Uploaded: + アップロード済: + + + Average Uploadspeed: + Average Uploadspeed: + + + + + Count of Uploads: + アップロード数: + + + + Uploaded + アップロード済 + + + + + + + Connections: + 接続: + + + + + + Peers: + ピア: + + + Misc + Misc + + + + Uptime: + 経過時間: + + + Overall: + Overall: + + + + + Uptime + 経過時間 + + + + Records + 記録 + + + + Uploadspeed: + アップロード速度: + + + + Downloadspeed: + ダウンロード速度: + + + + + Show Settings + 設定を表示 + + + + Reset + リセット + + + + Receive Rate + 受信速度 + + + + Send Rate + 送信速度 + + + + Always On Top + 常に最前面に表示 + + + + 100 + 100 + + + + % Opaque + % 不透明 + + + + Changes the transparency of the Bandwidth Graph + 帯域グラフの透明度を変更 + + + + Save + 保存 + + + + Cancel + キャンセル + + + + Hide Settings + 設定を非表示 + + + %1 KIB + %1 KB + + + %1 MIB + %1 MB + + + %1 GIB + %1 GB + + + + %1 days + %1 日 + + + + Now + 現在 + + + + Transfer + 転送 + + + + Session UL:DL Ratio: + セッションの UL:DL 比: + + + + Cumulative UL:DL Ratio + 累積 UL: DL 比 + + + + Time Statistics + 時間統計 + + + + Since: + 開始: + + + + Cumulative + 累積 + + + + StatusDefs + + + + Offline + オフライン + + + + Away + 退席中 + + + + Busy + 取り込み中 + + + + Online + オンライン + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + 接続中 + + + + Unreachable + + + + + Available + 利用可能 + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + パーソナル メッセージ + + + + Status message + 状態メッセージ + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">パーソナルメッセージ</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">状態メッセージを入力</span></p></body></html> + + + + OK + OK + + + + Cancel + キャンセル + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + 種類 + + + Form + フォーム + + + Person/Channel Name + パーソン/チャネル名 + + + + Delete FeedItem + フィード アイテムを削除 + + + + SubFileItem + + File Name + ファイル名 + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + チャネル ファイルを保存 + + + Form + フォーム + + + + Download + ダウンロード + + + + Play + 再生 + + + + %p Kb + + + + Expand + 展開 + + + + Save File + ファイルを保存 + + + + Cancel Download + ダウンロードをキャンセル + + + + Download File + ファイルをダウンロード + + + + + + Play File + ファイルを再生 + + + + TBoard + + + Pause + ポーズ + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + テキスト形式で PGP 証明書を使用. + + + + The text below is your PGP certificate. You have to provide it to your friend + 下記テキストはあなたのPGP証明書です. あなたの友達に渡してください + + + + Please, paste your friends PGP certificate into the box below + あなたの友達の PGP 証明書を下のボックスに貼り付けてください + + + Your Cert is copied to Clipboard, paste and send it to yourfriend via email or some other way + あなたの証明書はクリップボードにコピーされました. Eメールに貼り付けるかその他の方法であなたの友達に送ってください + + + + You can copy this text and send it to your friend via email or some other way + このテキストをコピーしてEメールやその他の方法であなたの友達に送ることができます + + + + RetroShare + RetroShare + + + + Text certificate + テキスト証明書 + + + + Copy your Cert to Clipboard + 証明書をクリップボードにコピー + + + + Save your Cert into a File + 証明書をファイルに保存 + + + + Run Email program + Eメール プログラムを起動 + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + 友達と接続ヘルプ + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + 名前をつけて保存... + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare 証明書 (*.rsc); すべてのファイル (*) + + + + Certificate Load Failed + 証明書の読み込みに失敗 + + + + TransferFeed + + Form + フォーム + + + Sort: + 並び替え: + + + None + なし + + + + TransferPage + + Form + フォーム + + + Transfer + 転送 + + + + Transfer options + 転送オプション + + + + Queue Size: + キューサイズ: + + + Maximum Download speed per file: + ファイルごとの最大ダウンロード速度: + + + kB/s + KB/s + + + + Default chunk strategy: + デフォルトのチャンクの方針: + + + + Safety disk space limit : + + + + + Streaming + ストリーミング + + + + Random + ランダム + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + Show Cache Transfers + キャッシュの転送を表示 + + + F2F Routing + F2Fルーティング + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">共有ファイルダイアログで指定した, それぞれの共有フォルダに個別の共有フラグを設定できます.:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">友達がファイルをブラウズ可能</span>: あなたの友達は参照できます</li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">匿名で共有</span>: ファイルはF2Fトンネル経由で匿名で到達可能</li></ul></body></html> + + + + TransfersDialog + + + Cancel + キャンセル + + + + Clear Completed + 完了したものをクリア + + + + + Status + 状態 + + + + Completed + 完了 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">ダウンロード (Downloads):</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ダウンロード:</span></p></body></html> + + + + Show cache transfers + + + + + Uploads + アップロード + + + + Selected transfer + 選択した転送 + + + + Done + 完了 + + + + Active + アクティブ + + + + Outstanding + 未処理 + + + Tunneling + トネリング + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">アップロード(Uploads):</span></p></body></html> + + + + + Name + i.e: file name + 名前 + + + + + Size + i.e: file size + サイズ + + + Progress + i.e: % downloaded + 進歩 + + + + Speed + i.e: Download speed + 速度 + + + + Progress / Availability + i.e: % downloaded + 進捗/可用性 + + + + Sources + i.e: Sources + ソース + + + + Core-ID + コア ID + + + + Progress + i.e: % uploaded + 進捗 + + + + Speed + i.e: upload speed + 速度 + + + + Transferred + 転送済 + + + + Hash + ハッシュ + + + + Play + 再生 + + + + Pause + ポーズ + + + + Resume + 再開 + + + + Open Folder + フォルダを開く + + + + Open File + ファイルを開く + + + + Preview File + ファイルをプレビュー + + + + Details... + 詳細... + + + Copy retroshare Link + Retoroshare リンクをコピー + + + Paste retroshare Link + Retoroshare リンクを貼り付け + + + View + 表示 + + + + Down + 下へ + + + + Up + 上へ + + + + Top + 先頭 + + + + Bottom + 末尾 + + + Move in queue... + キューで移動... + + + + Priority (Speed)... + 優先度 (速度)... + + + + Streaming + ストリーミング + + + + Random + ランダム + + + + Chunk strategy + チャンクの方針 + + + + Queued + キュー済 + + + + Checking... + 確認中... + + + + RetroShare + RetroShare + + + + Details: + 詳細: + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + 転送を開く + + + + File %1 is not completed. If it is a media file, try to preview it. + ファイル %1 は完了していません. もしそれがメディア ファイルならプレビューを試みてください. + + + + Are you sure that you want to cancel and delete these files? + 本当にこれらのファイルをキャンセルして削除しますか? + + + + Speed / Queue position + 速度/キュー順 + + + + Remaining + 残り + + + + Download time + i.e: Estimated Time of Arrival / Time left + ダウンロード時間 + + + + Peer + i.e: user name + ピア + + + + Router Statistics + ルータ統計 + + + + Router Requests + + + + + Force Check + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + 遅く + + + + + + Average + 平均 + + + + + Faster + 速く + + + + Move in Queue... + キュー内で移動... + + + + + + Failed + 失敗 + + + + + + Okay + OK + + + + + Waiting + 待機中 + + + + Downloading + ダウンロード中 + + + + + + + Complete + 完了 + + + + Paused + ポーズ + + + + Unknown + 不明 + + + + version: + バージョン: + + + + Transferring + + + + + Uploading + アップロード中 + + + + TreeStyle_RDM + + + + FILE + ファイル + + + + Files + ファイル + + + + File + ファイル + + + + + DIR + フォルダ + + + + Friends Directories + 友達のフォルダ + + + + My Directories + 自分のフォルダ + + + + Size + + + + + Age + 経過時間 + + + + Friend + 友達 + + + + Share Type + 共有の種類 + + + + What's new + 最新情報 + + + + TrustView + + Form + フォーム + + + + Zoom : + ズーム : + + + + Update + 更新 + + + + + Showing: whole network + 表示中: ネットワーク全体 + + + + This table normaly auto-updates every 10 seconds. + この表は通常10秒ごとに自動更新されます. + + + + Self + + + + + Trust + 信頼 + + + is athenticated (one way) by + は (一方向に) 認証されています + + + athenticated himself + は自分自身を認証しています + + + athenticated each others + はお互いに認証されています + + + is athenticated by + は認証されています + + + athenticated + は認証しています + + + + is authenticated (one way) by + + + + + Half + ハーフ + + + + authenticated himself + + + + + authenticated each other + + + + + Full + 完全 + + + + + peers, including him(her)self. + 個のピア (自分自身を含む). + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + 表示中: 接続しているピア + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + ルータ統計 + + + + F2F router information + F2F ルータ情報 + + + File Name + ファイル名前 + + + Type + タイプ + + + + TurtleRouterStatistics + + + Router Statistics + ルータ統計 + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + OK + + + + Cancel + キャンセル + + + + Yes + はい + + + + No + いいえ + + + + Help + ヘルプ + + + + Retry + 再試行 + + + + Show Log + ログを表示 + + + + Show Settings + 設定を表示 + + + + Continue + 続行 + + + + Quit + 終了 + + + + Browse + ブラウズ + + + + misc + + + Unknown + Unknown (size) + 不明 + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + KB/s + + + + MiB + mebibytes (1024 kibibytes) + MB + + + + GiB + gibibytes (1024 mibibytes) + GB + + + + TiB + tebibytes (1024 gibibytes) + TB + + + + Unknown + 不明 + + + + < 1m + < 1 minute + < 1分 + + + + %1 minutes + e.g: 10minutes + %1分 + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + %1y %2d %3h %4m + e.g: 2 years 2days 10hours 2minutes + %1年%2日%3時間%4分 + + + %1y %1d %2h %3m + e.g: 2 years 2days 10hours 2minutes + is this correct? %1 is duplicated at y and d + %1年%1日%2時間%3分 + + + + %1h %2m + e.g: 3hours 5minutes + %1時間 %2分 + + + %1d %2h %3m + e.g: 2days 10hours 2minutes + %1日%2時間%3分 + + + diff --git a/retroshare-gui/src/lang/retroshare_ko.qm b/retroshare-gui/src/lang/retroshare_ko.qm new file mode 100644 index 000000000..8ec3fec1c Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_ko.qm differ diff --git a/retroshare-gui/src/lang/retroshare_ko.ts b/retroshare-gui/src/lang/retroshare_ko.ts new file mode 100644 index 000000000..989da8aa0 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_ko.ts @@ -0,0 +1,13953 @@ + + + + + AboutDialog + + + About RetroShare + + + + + About + 에 관하여 + + + + close + 닫기 + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + Retroshare (뒤에몫) + + + + Sorry, can't determine system default command for this file + + + + + + AddFileAssotiationDialog + + RetroShare + Retroshare (뒤에몫) + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + RetroShare : 고급 검색 + + + + Cancel + 취소 + + + + Search + 수색 + + + + Add a further search criterion. + 검색 조건을 추가합니다. + + + + Reset the search criteria. + 검색 기준을 재설정합니다. + + + + Cancels the search. + 검색을 취소합니다. + + + + Perform the advanced search. + 시작 + + + + Search Criteria + 검색 조건 + + + + AppearancePage + + + Language + 언어 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">이 신청에서 사용된 언어를 선택하십시오</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">언어 변경에만 RetroShare를 다시 시작한 후에 적용됩니다!</p></body></html> + + + + Style + 스타일 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">이 신청의 공용영역 작풍을 선택하십시오</p></body></html> + + + + Style Sheet + 문서 양식 + + + + ApplicationWindow + + + Hide + 은신처 + + + + Show + + + + + + RetroShare + Retroshare (뒤에몫) + + + Transfers + 파일-전송 + + + Messages + 전자 우편 메시지 + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + 통계 + + + + AttachFileItem + + + Form + + + + File Name + 파일명 + + + + %p Kb + + + + + Cancel Download + + + + + BandwidthGraph + + + + Show Settings + + + + + Reset + 리셋 + + + + Receive Rate + 비율을 받으십시오 + + + + Send Rate + 비율을 보내십시오 + + + + Style + 작풍 + + + + Changes the transparency of the Bandwidth Graph + 대역폭 도표의 투명도를 바꾼다 + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Save + 저장하십시오 + + + + Cancel + 취소 + + + + Since: + + + + + Hide Settings + 은신처 조정 + + + + RetroShare Bandwidth Usage + + + + + Always on Top + + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + 인기도 + + + + Last Post + 마지막 게시물 + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + + + + + Close + 마지막 + + + + BlogDialog + + Blogs + 블로그 + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + 주제 + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + 추가 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + 이름 + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + 은신처 + + + + CalDialog + + + Remove + 제거하십시오 + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + 이름: + + + + Location: + 위치 : + + + + ... + + + + + Status: + 상태: + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + 추가 + + + + Peer Calendars + + + + + CallToaster + + Message + 메시지 + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + 증명서를 선정하십시오 + + + Certificates (*.pqi *.pem) + 증명서 (*.pqi *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + Retroshare (뒤에몫) + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare 인증서 (*.의 RSC);; 모든 파일 (*) + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanMsgDialog + + Compose + 구성하십시오 + + + Recommended Files + 추천된 파일 + + + Send To: + 에 보내십시오: + + + Send + 보내십시오 + + + Delete Channel + 감소 채널 + + + Create Channel MSG + 채널 메시지를 창조하십시오 + + + Compose: + 구성하십시오 + + + &Save + 저장하십시오 + + + Save &As... + 다른 이름으로 저장 + + + &Print... + 인쇄 + + + &Quit + 종료 + + + Open File... + 파일 열기 + + + Save as... + 다른 이름으로 저장 + + + Add Extra File + 추가 파일 추가 + + + Size + 크기 + + + Sources + 근원 + + + Save + 저장하십시오 + + + Contacts + 연락처 + + + Subject: + 주제: + + + Underline + 밑줄 + + + Italic + 기울임꼴 + + + File Name + 파일명 + + + Hash + 해쉬 + + + Reply + 대답 + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + + + + + Play + 놀이 + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + 은신처 + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + Forum Name + 포럼 이름 + + + + Popularity + 인기도 + + + + Last Post + 마지막 게시물 + + + Forum ID + 포럼 자료 ID + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + 유형 + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 제한됨 - 누구나 제한 게시 (사립 게시 키)를 읽을 수있습니다 + + + + Private - (Private Publish Key required to view Messages) + 개인 - (사립 게시 키 메시지를 볼 필요) + + + + Cancel + + + + + OK + + + + + Close + 마지막 + + + + ChannelFeed + + + Create Channel + 채널을 창조하십시오 + + + + Subscribe To Channel + 채널을 구독하십시오 + + + Title + 제목 + + + Description + 설명 + + + Reset + 리셋 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + Add + 추가 + + + + Display + 표시 + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + Name + 이름 + + + Popularity + 인기도 + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + 보내십시오 + + + + Cancel + + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + 일반 + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ChatToaster + + Message + 메시지 + + + + ComboStatus + + Online + 온라인 + + + + ConclusionPage + + + Make Friend + 친구를 사귀십시오 + + + + Details about your friend : + 당신의 친구에 대한 세부 정보 : + + + + Key validity: + 키 유효 기간 : + + + + Email: + 이메일: + + + + Options + 선택권 + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + 친구 인증 (로그인 GPG 키를) + + + + Add as friend to connect with + 친구와 연결에 담기 + + + + It seems your friend is already registered. Adding it might just set it's ip address. + 그것은 당신의 친구가 이미 등록되어있는 것으로 보인다. 그냥 그것의 IP 주소를 설정할 수있습니다 추가. + + + + Peer details + 피어 세부 사항 + + + + Name: + 이름: + + + + Loc: + 위치: + + + + Signers + 서명자 + + + + ConfCertDialog + + + Cancel + 취소 + + + Port: + 항구: + + + Trust Settings + 신망 조정 + + + Trust Level + 신망 수준 + + + Trust Their Signature + 그들의 서명을 신뢰하십시오 + + + Sign The Certificate + 증명서를 서명하십시오 + + + + Details + 세부사항 + + + + Name + 이름 + + + + Loc + + + + + Peer Address + 동료 주소 + + + + Last Contact + 마지막 문의 + + + Peer Details + 동료 세부사항 + + + + Peer Info + 피어 정보 + + + + Peer ID + + + + + Version + + + + + RetroShare ID + + + + + Status + 상태 + + + + Dynamic DNS + + + + + Addresses list + 주소 목록 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Apply and Close + 닫기 + + + + + RetroShare + Retroshare (뒤에몫) + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + 아마 비밀 번호가 잘못입니다 + + + + Trust + + + + + None + + + + + Marginal + + + + + Full + + + + + Deny Friend + 친구 거부 + + + + + Sign GPG key + + + + + Friend Details + + + + + Local Address + 로컬 주소 + + + + External Address + 외부 주소 + + + + + Port + 항구 + + + + Your trust in this peer is: + + + + Marginal + 한계 + + + Full + 전체 + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + Make Friend + 친구를 사귀십시오 + + + + Certificate + + + + + OK + 확인 + + + + ConnectDialog + + Peer Details + 동료 세부사항 + + + Make Friend + 친구를 사귀십시오 + + + Cancel + 취소 + + + Name: + 이름: + + + Loc: + 위치: + + + + ConnectFriendWizard + + + Connect Friend Wizard + 친구 연결 마법사 + + + + CreateBlog + + + Create new Blog + 새 블로그 만들기 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">새 블로그</span></p></body></html> + + + + Name + 이름 + + + + Description + 설명 + + + + Type: + 유형: + + + + Public - Anyone can read and publish (Shared Publish Key) + 공개 - 누구나 읽을 수 있고 (공유 게시 키) 게시 + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 제한됨 - 누구나 제한 게시 (사립 게시 키)를 읽을 수있습니다 + + + + Private - (Private Publish Key required to view Messages) + 개인 - (사립 게시 키 메시지를 볼 필요) + + + + Allowed Messages + 허용 메시지 + + + + Authemticated Messages + 인증된 메시지 + + + + Anonymous Messages + 익명 메시지 + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + 취소 + + + + Create + 만들기 + + + + RetroShare + Retroshare (뒤에몫) + + + + Please add a Name + 제발 이름을 추가합니다 + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + Attachments + 첨부 파일 + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + 밑줄 + + + + Italic + 기울임꼴 + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + Add Extra File + 추가 파일 추가 + + + + RetroShare + Retroshare (뒤에몫) + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + 저장하십시오 + + + + Save &As... + 다른 이름으로 저장 + + + + &Print... + 인쇄 + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + 종료 + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + 파일 열기 + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + 다른 이름으로 저장 + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + 이름 + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + 설명 + + + + Type: + 유형: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 제한됨 - 누구나 제한 게시 (사립 게시 키)를 읽을 수있습니다 + + + + Private - (Private Publish Key required to view Messages) + 개인 - (사립 게시 키 메시지를 볼 필요) + + + + Allowed Messages + 허용 메시지 + + + + Anonymous Messages + 익명 메시지 + + + + Authenticated Messages + + + + Authemticated Messages + 인증된 메시지 + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + 채널 로고 + + + + Add Channel Logo + 채널 로고 추가 + + + + Cancel + + + + + Create + 만들기 + + + + RetroShare + Retroshare (뒤에몫) + + + + Please add a Name + 제발 이름을 추가합니다 + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + 메시지 + + + + Subject : + + + + + + Attachments + 첨부 파일 + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + 추가 파일 추가 + + + + + RetroShare + Retroshare (뒤에몫) + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + 이름 + + + + Type: + 유형: + + + + Authenticated Messages + + + + + Cancel + 취소 + + + RetroShare + Retroshare (뒤에몫) + + + + Please add a Name + 제발 이름을 추가합니다 + + + + Create new Forum + 새 포럼 만들기 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">새 포럼</span></p></body></html> + + + + Description + 설명 + + + + Public - Anyone can read and publish (Shared Publish Key) + 공개 - 누구나 읽을 수 있고 (공유 게시 키) 게시 + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 제한됨 - 누구나 제한 게시 (사립 게시 키)를 읽을 수있습니다 + + + + Private - (Private Publish Key required to view Messages) + 개인 - (사립 게시 키 메시지를 볼 필요) + + + + Allowed Messages + 허용 메시지 + + + Authemticated Messages + 인증된 메시지 + + + + Anonymous Messages + 익명 메시지 + + + Channel Logo + 채널 로고 + + + Add Channel Logo + 채널 로고 추가 + + + + Create + 만들기 + + + + CreateForumMsg + + + Close + 마지막 + + + + Post Forum Message + 포스트 포럼 메시지 + + + + Forum + 포럼 + + + Forum Post Subject + 포럼 게시물 제목 + + + + Attach File + + + + Paste retroshare link + 붙여넣기 retroshare 링크 + + + + Forum Post + 포럼 게시물 + + + + Sign Message + 로그인 메시지 + + + + Subject + 주제 + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + 포스트 포럼 메시지 + + + Paste retroshare Link + 붙여넣기 retroshare 링크 + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + Retroshare (뒤에몫) + + + + Please set a Forum Subject and Forum Message + 제발 메시지 포럼 제목 및 포럼 설정 + + + + Add Extra File + 추가 파일 추가 + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + Clipboard does not contains RetroShare link('s) + 클립 보드로하지 않습니다 RetroShare 링크가 포함되어있습니다 + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + Retroshare (뒤에몫) + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + 다른 이름으로 저장 + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare 인증서 (*.의 RSC);; 모든 파일 (*) + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + 세부사항 + + + + + General + 일반 + + + + File Name: + 파일명: + + + + Hash: + 해시: + + + + Size: + 크기: + + + + Status: + 상태: + + + Priority + 우선순위 + + + + Priority: + + + + + Type: + 유형: + + + + Transfer + 전송 + + + + Sources: + 근원: + + + + Datarate: + 속도 + + + + Completed: + 완료하는: + + + + Chunk size: + 청크 크기 : + + + + + Number of Chunks + 조각수 + + + + Chunks: + 청크 : + + + + Remaining: + 남은 시간: + + + + Date + 날짜 + + + + Download time: + 다운로드 시간 : + + + + + Comments + 댓글 + + + + + retroshare link(s) + retroshare 링크 + + + + Copy + 복사 + + + + OK + + + + + Cancel + 취소 + + + + Rating + 평가 + + + + File Name + 파일명 + + + + Not Rated + 아니 등급 + + + + No Comments + 코멘트 없음 + + + + DirectoriesPage + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + 공유 디렉토리 + + + + Edit Share + + + + Incoming files + 공유디렉토리 + + + Add a Share Directory + 공유 디렉토리를 추가하십시오 + + + + + Browse + + + + Add Shared Directory + 공유 디렉토리를 추가하십시오 + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + 채널 로고 추가 + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + 포럼 내용 + + + + Cancel + + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + 포럼 소개 + + + + Forum Name + 포럼 이름 + + + + Forum Description + 포럼에 대한 설명 + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + 주제: + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">친구 </span></p></body></html> + + + + Person + 사람 + + + + Auto Connect + 자동으로 연결하십시오 + + + + Trust Level + 신망 수준 + + + + Peer Address + 동료 주소 + + + + Last Contact + Last Contact + + + + Organisation + 조직 + + + + Location + 위치 + + + + Country + 국가 + + + + Person Id + 사람 ID + + + + Auth Code + 입증 부호 + + + + # + + + + + Status + 상태 + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileTransferInfoWidget + + Chunk map: + 청크지도 : + + + Active chunks: + Active chunks: + + + Availability map ( + 상태지도 + + + sources + 근원 + + + File info: + 파일 정보 : + + + File hash: + 파일 해쉬 : + + + File size: + 파일 크기 : + + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + 바이트 + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + 남은 시간 + + + + Number of sources + + + + + Chunk strategy + 청크 전략 + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + Chunk size: + 청크 크기 : + + + Number of chunks: + 청크의 개수 : + + + Transfered: + 전송 : + + + Number of sources: + 소스의 개수 : + + + Chunk strategy: + 청크 전략: + + + Transfer type: + 전송 유형 : + + + + FlatStyle_RDM + + + Friends Directories + 친구 디렉터리 + + + + My Directories + 내 디렉토리 + + + + Size + 크기 + + + + Age + 나이 + + + + Friend + + + + + Share Type + 공유 유형 + + + + Directory + 디렉토리 + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + 포럼 내용 + + + + Forum Info + 포럼 소개 + + + + Forum Name + 포럼 이름 + + + + Popularity + 인기도 + + + + Last Post + 마지막 게시물 + + + + Forum ID + 포럼 자료 ID + + + + Forum Description + 포럼에 대한 설명 + + + + Security + 보안 + + + + Allowed Messages + 허용 메시지 + + + + Authemticated Messages + 인증된 메시지 + + + + Anonymous Messages + 익명 메시지 + + + + Cancel + 취소 + + + + OK + 좋습니다 + + + + Apply and Close + 닫기 + + + + ForumMsgItem + + + Remove Item + + + + Forum Name + 포럼 이름 + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + 대답 + + + + Send + 보내십시오 + + + + Signed + 서명 + + + + Forum Post + 포럼 게시물 + + + + Unknown Forum Post + + + + + + + Anonymous + 익명 + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + 구독 포럼 + + + + Expand + + + + + Forum Description + 포럼에 대한 설명 + + + + ForumPage + + + Misc + + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + 구독 포럼 + + + + Unsubscribe to Forum + 취소 포럼 + + + + New Forum + 새 포럼 + + + + Show Forum Details + 포럼 내용보기 + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + 대답 + + + + Reply to Author + 작성자에게 회신 + + + + Expand all + 모두 확장 + + + + Collapse all + 모두 축소 + + + + AUTHD + + + + Popularity: + 인기도 : + + + + Your Forums + 귀하 포럼 + + + + Subscribed Forums + 포럼 가입 + + + + Popular Forums + 인기 포럼 + + + + Other Forums + 기타 포럼 + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + + + + + Expand + + + + Anonymous + 익명 + + + signed + 서명 + + + none + 없음 + + + + + RetroShare + Retroshare (뒤에몫) + + + + No Forum Selected! + 아니 포럼 선정! + + + + You cant reply a Anonymous Author + + + + + + Date + 날짜 + + + + + Title + 제목 + + + + + Start New Thread + 새 스레드를 시작합니다 + + + New Message + 새로운 메시지 + + + Add + 추가 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start new Thread for Selected Forum</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">선택된 포럼 새 스레드를 시작합니다</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reply Message</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">회신 메시지</p></body></html> + + + RetroShare Forums + RetroShare 포럼 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">포럼:</p></body></html> + + + + Last Post + 마지막 게시물 + + + + Threaded View + + + + + Flat View + + + + + + Author + 저자 + + + + Signed + 서명 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">실:</span></p></body></html> + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + 리셋 + + + + Content + + + + + Create Forum + 포럼 만들기 + + + + Print + 인쇄 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">포럼</span></p></body></html> + + + + Start new Thread for Selected Forum + + + + + Display + 표시 + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + 인쇄 미리보기 + + + + ForumsFillThread + + + + Anonymous + 익명 + + + + + signed + 서명 + + + + + none + 없음 + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">친구들</span></p></body></html> + + + + Add + 추가 + + + + Display + 표시 + + + + Friends + + + + + Status + 상태 + + + + Add or Change your Avatar + + + + + Edit Personal message + 편집 상태 메시지 + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + 밑줄 + + + + Italic + 기울임꼴 + + + + Font + 글꼴 + + + + Text Color + + + + + Attach File + + + + + Send + 보내십시오 + + + + Clear Chat History + 지우기 채팅 내역 + + + + + Add Friend + + + + + Create new Profile + + + + + + Create new Forum + 새 포럼 만들기 + + + + F + + + + + + Create new Channel + 새 채널 만들기 + + + + C + + + + + Add your Avatar Picture + 귀하의 아바타 이미지 추가 + + + + A + + + + + Set your Personal Message + 개인 메시지를 설정하십시오 + + + + Edit your status Message + 편집 상태 메시지 + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + 개요 + + + + News Feed + 뉴스 피드 + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + 위치 + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + 메시지를 친구에게 보내기 + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + 친구 거부 + + + + Remove Friend Location + 제거 친구 위치 + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + 모두 확장 + + + + Collapse all + 모두 축소 + + + + location + + + + + + Available + 사용 가능 + + + + Save Certificate + 증명서를 저장하십시오 + + + + Certificates (*.pqi) + 증명서 (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + 추가 파일 추가 + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + 다른 이름으로 저장 + + + + Text File (*.txt );;All Files (*) + + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Server + 동료 조정 + + + + Accept + 수락 + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Status + 상태 + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + 삭제 + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Retroshare (뒤에몫) 체제 + + + Load Trusted Certificate (Optional) + (선택) 짐 트러스트 인증서 + + + RetroShare : Create new user Profile + RetroShare : 새 사용자 프로필 만들기 + + + It looks like you don't own any GPG keys. Please fill in the form below to generate one, or use your favorite gnupg key manager. + 당신은 전혀의 GPG 키를 소유하고 있지 않은 것 같습니다. 아래 양식에 하나, 또는 좋아하는 GPG는 키 관리자를 사용하여 생성할 수를 입력합니다. + + + Use GPG key + GPG 키를 사용하여 + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + + Your profile is associated to a GPG key + + + + + Use Profile + + + + + Name + 이름 + + + + Enter here your nickname + + + + + Email + 이메일 + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + 위치 + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + GPG Password + 의 GPG 비밀 번호 + + + Put a meaningfull location. ex : home, laptop, etc. + 의미있는 위치를 내려놔. 예 : 집, 노트북 등 + + + Generate a new gpg key + 생성의 새로운 GPG 키를 + + + + Generate New Profile + 새 프로필 생성 + + + + Info + 정보 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">친구</span></p></body></html> + + + Select File + 파일을 선정하십시오 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">이름: </p></body></html> + + + Generate New Certificate + 새로운 증명서를 생성하십시오 + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + GPG 키를 생성 실패 + + + + Location field is required with a minimum of 3 characters + 위치 필드 3 문자의 최소 필요합니다 + + + + All fields are required with a minimum of 3 characters + 모든 분야의 3 문자의 최소 필요합니다 + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + Generating new GPG key, please be patient. Fill in your GPG password when asked. + 새로운 GPG 키를 생성, 기다려 주시기 바랍니다. 여러분의 GPG 때 비밀 번호를 기입 물었다. + + + + Select Trusted Friend + 신뢰한 친구를 선정하십시오 + + + + Certificates (*.pqi *.pem) + 증명서 (*.pqi *.pem) + + + Location: + 위치 : + + + + GeneralMsgDialog + + Forum + 포럼 + + + Message + 메시지 + + + Add Extra File + 추가 파일 추가 + + + Attachments + 첨부 파일 + + + + GeneralPage + + Keys manager + 열쇠 매니저 + + + Style + 작풍 + + + Choose RetroShare's interface style + 공용영역 작풍을 선택하십시오 + + + Language + 언어 (Language) + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">언어에 변화는 신청을 재출발한 후에서만 효력을 나타낼 것이다!</p></body></html> + + + Choose the language used in RetroShare + 이 즉시 메신저에서 사용된 언어를 선택하십시오 + + + Login + 로그인 (Login) + + + + Startup + 시작 + + + + Start RetroShare when my system starts + 시작 RetroShare 내 시스템을 시작 할 때 + + + + Start minimized + 시작을 최소화 + + + + Start minimized on system start + + + + + Misc + 잡다한 + + + + Do not show the Quit RetroShare MessageBox + 종료 RetroShare MessageBox를 표시하지 않음 + + + + Do not Minimize to Tray Icon + 트레이 아이콘을 최소화하지 마십시오 + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Recv: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Sent: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + 제목 + + + + Description + 설명 + + + + Reset + 리셋 + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + 이름 + + + + Path + + + + + Extension + + + + + Hash + 해쉬 + + + + Date + 날짜 + + + + Size + 크기 + + + + Popularity + 인기도 + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + Search + 수색 + + + + Home + 가정 + + + + Close + 마지막 + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + 에 관하여 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + 리셋 + + + + + Copy + 복사 + + + + Remove + 제거하십시오 + + + + Mark all + + + + + Delete + 삭제 + + + + Clear history + + + + + Send + 보내십시오 + + + + InfoDialog + + + Info + 정보 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + + + + + Expand + + + + + Hide + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + 에서 + + + + Show + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + MainWindow + + + Network + 네트워크 + + + + Friends + 친구들 + + + + + Transfers + 파일-전송 + + + + + Messages + 전자 우편 메시지 + + + + + Channels + 수로 + + + + Blogs + 블로그 + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + 상태 + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + Online + 온라인 + + + + + Options + 선택권 + + + + Hide + 은신처 + + + + Show + + + + + RetroShare + Retroshare (뒤에몫) + + + Invite Friend + 친구를 초대하십시오 + + + + MainWindow + + + + + Add Friend + 친구를 추가하십시오 + + + + Add a Friend Wizard + 친구로 추가 마법사 + + + + Add Share + 몫을 추가하십시오 + + + + + Quick Start Wizard + 빠른 시작 마법사 + + + + Search + 수색 + + + + Files + 파일 + + + Add Shared Directory + 공유 디렉토리를 추가하십시오 + + + + Show/Hide + 표시 / 숨기기 + + + + &Quit + 종료 + + + + + + + You have %1 new message + + + + + Bandwidth Graph + 대역폭 그래프 + + + + Open Messenger + 열기 메신저 + + + + Minimize + 최소화 + + + + Maximize + 최대화 + + + + Links Cloud + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Unfinished + + + + + Help + 도움 + + + + About + 에 관하여 + + + News Feed + 뉴스 피드 + + + + + Forums + 포럼 + + + + Open Messages + 메시지를 열 + + + + Applications + 응용 프로그램 + + + Settings + 조정 + + + RetroShare %1 a secure decentralised commmunication platform + RetroShare %1 보안 분산 커뮤니케이션 플랫폼 + + + + Plugins + 플러그인 + + + + Really quit ? + 정말 그만? + + + + Do you really want to exit RetroShare ? + 정말 RetroShare 종료 하시겠습니까? + + + + Quit + 종료 + + + + SMPlayer + + + + + Messenger + 메신저 + + + + MessageComposer + + + + Compose + 구성하십시오 + + + + + Contacts + 연락처 + + + + Search for Name: + + + + + Reset + 리셋 + + + + Send To: + 에 보내십시오: + + + + Subject: + 주제: + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + 밑줄 + + + + Italic + 기울임꼴 + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + 추천된 파일 + + + + File Name + 파일명 + + + + Size + 크기 + + + Sources + 근원 + + + + Hash + 해쉬 + + + + Send + 보내십시오 + + + + Send this message now + + + + + Reply + 대답 + + + + Toggle Contacts View + + + + + Save + 저장하십시오 + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + Compose: + 구성하십시오 + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + Retroshare (뒤에몫) + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + 알 수없는 + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + 저장하십시오 + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + 인쇄 + + + + &Export PDF... + + + + + &Quit + 종료 + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + 파일 열기 + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + 다른 이름으로 저장 + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + 추가 파일 추가 + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + 추가 + + + + Edit + + + + + Delete + 삭제 + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + 메시지 + + + New Message + 새로운 메시지 + + + + Subject + 주제 + + + + <b>1 new Message from</b> + + + + + Close + 마지막 + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">추천된 파일</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + 주제: + + + + From: + 에서: + + + + To: + 으로: + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + 파일명 + + + + Size + 크기 + + + + Hash + 해쉬 + + + + Print + 인쇄 + + + + Print Preview + 인쇄 미리보기 + + + + No subject + + + + + Download + + + + + Download all + + + + + Hide + + + + + Expand + + + + + File + + + + + Files + 파일 + + + + Print Document + + + + + Save as... + 다른 이름으로 저장 + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + + + + + Compose + 구성하십시오 + + + + Reply to selected message + + + + + Reply + 대답 + + + + Reply all to selected message + + + + + Reply all + 전체 답장 + + + + Forward selected message + + + + + Foward + 앞으로 + + + + Remove selected message + + + + + Delete + 삭제 + + + + Print selected message + + + + + + Print + 인쇄 + + + + Display + 표시 + + + + + + Tags + + + + + Print Preview + 인쇄 미리보기 + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + 인쇄 + + + + Print Preview... + + + + + &Quit + 종료 + + + + MessagesDialog + + + + New Message + 새로운 메시지 + + + + Quick View + + + + + Reply to Message + 메시지에 대답 + + + + Remove Message + 메시지를 제거하십시오 + + + + + Date + 날짜 + + + + + + From + 에서 + + + Size + 크기 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">추천된 파일</span></p></body></html> + + + + Reply + 대답 + + + + Reply all + 전체 답장 + + + + Foward + 앞으로 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">선정한 메시지를 제거하십시오 </p></body></html> + + + + Delete + 삭제 + + + + Compose + 구성하십시오 + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + 표시 + + + + Reset + 리셋 + + + + Attachments + 첨부 파일 + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + 들어오는 전자 우편 + + + + + + + Outbox + 나가는 전자 우편 + + + + Draft + 초안 + + + + + Sent + 보내진 전자 우편 + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + 인쇄 + + + + Print Preview + 인쇄 미리보기 + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + 다른 이름으로 저장 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">선정된 메시지에 대답</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">새로운 메시지</p></body></html> + + + Download All + 모두를 다운로드하십시오 + + + Sources + 근원 + + + + Forward selected Message + 전달 메시지 선택 + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + 메시지를 제거하십시오 + + + + Forward Message + 전달 메시지 + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + 다운로드 + + + + Empty trash + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + Click to sort by to + + + + Files + 파일 + + + Compose: + 구성하십시오 + + + + + + Drafts + + + + + To + + + + Anonymous + 익명 + + + Save as... + 다른 이름으로 저장 + + + + + + + + Total: + + + + + + Reply to All + 전체 답장 + + + + + Subject + 주제 + + + Subject: + 주제: + + + From: + 에서: + + + Date: + 날짜: + + + To: + 으로: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">추천 파일 모두 다운로드</p></body></html> + + + File Name + 파일명 + + + Hash + 해쉬 + + + + Print + 인쇄 + + + + MessagesPopupDialog + + New Message + 새로운 메시지 + + + Reply to Message + 메시지에 대답 + + + Remove Message + 메시지를 제거하십시오 + + + Messages + 전자 우편 메시지 + + + Inbox + 들어오는 전자 우편 + + + Outbox + 나가는 전자 우편 + + + Draft + 초안 + + + Sent + 보내진 전자 우편 + + + Date + 날짜 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">추천된 파일</span></p></body></html> + + + Sources + 근원 + + + Compose + 구성하십시오 + + + Remove + 제거하십시오 + + + Reply + 대답 + + + Print + 인쇄 + + + PrintPreview + 인쇄 미리보기 + + + + MessengerWindow + + + Expand all + 모두 확장 + + + + Collapse all + 모두 축소 + + + + Chat + 그룹 잡담 + + + + Message Friend + 메시지를 친구에게 보내기 + + + + Connect To Friend + 친구에 연결하십시오 + + + + Peer Details + 동료 세부사항 + + + + Recomend this Friend to... + + + + + Paste RetroShare Link + + + + Paste retroshare Link + 붙여넣기 retroshare 링크 + + + + Export Friend + 수출 친구 + + + + Deny Friend + 친구 거부 + + + + Remove Friend Location + 제거 친구 위치 + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + <strong>RetroShare 예를 들어</strong> + + + location : + 위치 : + + + Available + 사용 가능 + + + Offline + 오프라인 + + + + Save Certificate + 증명서를 저장하십시오 + + + + Certificates (*.pqi) + 증명서 (*.pqi) + + + Friend Not Online + 친구가 아니 온라인 + + + View + 보기 + + + Remove Friend + 친구를 제거하십시오 + + + + Click to Change your Avatar + + + + Online + 온라인 + + + + Search Friends + + + + + Reset + 리셋 + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + 들어오는 전자 우편 + + + Outbox + 나가는 전자 우편 + + + Sent + 보내진 전자 우편 + + + Date + 날짜 + + + All + 모두 + + + Subject + 주제 + + + + MsgItem + + + Reply to Message + 메시지에 대답 + + + + Remove Item + + + + + + Expand + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + 짐 증명서 + + + Select a pem/pqi File + 파일을 선정하십시오 PEM/PQI + + + File Not Found + 찾아내지 않는 파일 + + + %1 does not exist. Would you like to create it? + %1 존재하지 않는다.당신은 그것을 창조하고 싶은가 하고자 했는가? + + + Failed to Create File + 파일을 창조하지 못하는. + + + Unable to create %1 [%2] + 창조할 수 없습니다 %1 [%2] + + + + Copy RetroShare Link + + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + 이 내게 인증 + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + Select Certificate + 증명서를 선정하십시오 + + + Certificates (*.pqi *.pem) + 증명서 (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">네트워크:</span></p></body></html> + + + Accept + 수락 + + + Trust + 신망 + + + Last Contact + Last Contact + + + + + + Name + 이름 + + + Peer Address + 동료 주소 + + + Organisation + 조직 + + + Location + 위치 + + + Country + 국가 + + + + + Cert Id + 증명서 ID + + + + Network + 네트워크 + + + Trust matrix + 트러스트 매트릭스 + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + 친구 부인 + + + + Make friend + 친구 만들기 + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + 피어 세부 사항 + + + GPG key not signed + GPG 키를 서명하지 + + + + Unknown + 알 수없는 + + + + yourself + + + + RetroShare + Retroshare (뒤에몫) + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare 인증서 (*.의 RSC);; 모든 파일 (*) + + + + + Did I authenticated peer + 난 피어 인증나요 + + + + Did I sign his gpg key + 나는 그의 GPG 키를 서명 했나 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">표시</span></p></body></html> + + + + Network Status + 네트워크 상태 + + + + Local network + 로컬 네트워크 + + + + UPnP + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + 친구를 추가하십시오 + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + 속도 선택권 + + + Max Total Data Rate (KB/S): + 당신의 최대 올려주기 속도 (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">사람마다 속도 (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + 은신처 조정 + + + Settings + 조정 + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + 이름: + + + + Choose color + + + + + OK + + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + 모두를 제거하십시오 + + + + Options + 선택권 + + + + NotifyPage + + + News Feed + 뉴스 피드 + + + + Peers + + + + + Channels + 수로 + + + + Forums + 포럼 + + + + Chat + + + + + Blogs + 블로그 + + + + Messages + 전자 우편 메시지 + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + 메시지 + + + + Channel Post + + + + + Forum Post + 포럼 게시물 + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + 새로운 메시지 + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + PeerDefs + + Anonymous + 익명 + + + + + Unknown + 알 수없는 + + + + PeerItem + + Make Friend + 친구를 사귀십시오 + + + Remove Friend + 친구를 제거하십시오 + + + + Chat + 그룹 잡담 + + + + Start Chat + + + + Organisation + 조직 + + + + Location + 위치 + + + Country + 국가 + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Send + 보내십시오 + + + + Cancel + + + + + Peer ID: + + + + + Write Message + + + + + Status: + 상태: + + + + Trust: + + + + + Name: + 이름: + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + 피어 + + + + + + + + + + + + Unknown Peer + + + + + Hide + + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + + + + Online + 온라인 + + + <span style="color:#000000"><strong>Friends:</strong></span> + <span style="color:#000000"><strong>친구:</strong></span> + + + <span style="color:#0000FF"><strong>Online:</strong></span> + <span style="color:#0000FF"><strong>온라인:</strong></span> + + + Online: + 온라인: + + + Friends: + 친구: + + + Network: + 네트워크: + + + + PeersDialog + + Chat + 잡담 + + + Export Friend + 수출 친구 + + + Remove Friend + 친구를 제거하십시오 + + + Save Certificate + 증명서를 저장하십시오 + + + Certificates (*.pqi) + 증명서 (*.pqi) + + + Status + 상태 + + + Person + 사람 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">친구 </span></p></body></html> + + + Connect To Friend + 친구에 연결하십시오 + + + Profile + 개요 + + + Paste retroshare Link + 붙여넣기 retroshare 링크 + + + Expand all + 모두 확장 + + + Collapse all + 모두 축소 + + + Message Friend + 메시지를 친구에게 보내기 + + + Peer Details + 동료 세부사항 + + + Deny Friend + 친구 거부 + + + Remove Friend Location + 제거 친구 위치 + + + <strong>RetroShare instance</strong> + <strong>RetroShare 예를 들어</strong> + + + location : + 위치 : + + + Online + 온라인 + + + Available + 사용 가능 + + + Offline + 오프라인 + + + Friend Not Online + 친구가 아니 온라인 + + + RetroShare + Retroshare (뒤에몫) + + + Location + 위치 + + + Add Extra File + 추가 파일 추가 + + + News Feed + 뉴스 피드 + + + Save as... + 다른 이름으로 저장 + + + Send + 보내십시오 + + + Italic + 기울임꼴 + + + Underline + 밑줄 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">친구들</span></p></body></html> + + + Add + 추가 + + + Display + 표시 + + + Edit Personal message + 편집 상태 메시지 + + + Live Chat + 라이브 채팅 + + + Create New Forum + 새 포럼 만들기 + + + Create new Forum + 새 포럼 만들기 + + + Create New Channel + 새 채널 만들기 + + + Create new Channel + 새 채널 만들기 + + + Add your Avatar Picture + 귀하의 아바타 이미지 추가 + + + Set your Personal Message + 개인 메시지를 설정하십시오 + + + Edit your status Message + 편집 상태 메시지 + + + Disable Emoticons + 이모티콘 사용 안 함 + + + Add Friend + 친구를 추가하십시오 + + + Font + 글꼴 + + + Clear Chat History + 지우기 채팅 내역 + + + + PeersFeed + + Save Certificate + 증명서를 저장하십시오 + + + Certificates (*.pqi) + 증명서 (*.pqi) + + + Friends + 메시지 당신의 친구 + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + 제거하십시오 + + + + Excellent + + + + + Good + + + + + Average + 평균 + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + 평가 + + + + + Date + 날짜 + + + + + Location + 위치 + + + + Size + 크기 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + 피어 + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + 설명 + + + + PhotoShow + + + Date: + 날짜: + + + + Location: + 위치 : + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + 일시 중지 + + + + Forward + + + + + PluginFrame + + + Remove + 제거하십시오 + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + 인기도 + + + + PopupChatDialog + + Paste retroshare Link + 붙여넣기 retroshare 링크 + + + Friend Not Online + 친구가 아니 온라인 + + + RetroShare + Retroshare (뒤에몫) + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + 아바타보기 + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + 다른 이름으로 저장 + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + 보내십시오 + + + + Close + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Bold + + + + + + Underline + 밑줄 + + + + + Italic + 기울임꼴 + + + + Text Color + + + + + Clear Chat History + 지우기 채팅 내역 + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + 글꼴 + + + + Strike + + + + Avatar + 아바타 + + + Set your Avatar Picture + 설정 귀하의 아바타 이미지 + + + Clear Chat + 취소 채팅 + + + + Disable Emoticons + 이모티콘 사용 안 함 + + + + + Save Chat History + + + + + Clear offline messages + + + + Chatting with + 채팅 + + + + Add Extra File + 추가 파일 추가 + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + 아바타 + + + + Set your Avatar Picture + 설정 귀하의 아바타 이미지 + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + Retroshare (뒤에몫) + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + 인쇄 + + + + &Print... + 인쇄 + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + 개요 + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + 모두를 다운로드하십시오 + + + + RetroShare + Retroshare (뒤에몫) + + + + Error : cannot get peer details. + + + + + + Name + 이름 + + + + Peer ID + + + + + Size + 크기 + + + + Profile View + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + 해쉬 + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + 편집 상태 메시지 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">공공 정보</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">공공 정보</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">이름:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">위치:</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">기타 정보</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">친구의 번호 :</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">버전</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">내 주소</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">로컬 주소 :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">외부 주소 :</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + Addresses list + 주소 목록 + + + + QObject + + Name + 이름 + + + Date + 날짜 + + + Size + 크기 + + + Popularity + 인기도 + + + Hash + 해쉬 + + + + + RetroShare + Retroshare (뒤에몫) + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + 로그인 실패 + + + + Maybe password is wrong + 아마 비밀 번호가 잘못입니다 + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + 친구 부인 + + + + Make friend + 친구 만들기 + + + + Peer details + 피어 세부 사항 + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + 빠른 시작 마법사 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + + Next > + 다음 > + + + + + + + Exit + 종료 + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + 최상의 성능을 위해, RetroShare 조금 알 필요는 인터넷 연결에 대해. + + + + Choose your upload speed limit: + 업로드 속도 제한을 선택하십시오 : + + + + + KB/s + + + + + Choose your download speed limit: + 다운로드 속도 제한을 선택하십시오 : + + + + Connection : + 연결 : + + + + Automatic (UPnP) + 자동 (UPnP)를 + + + + Firewalled + 방화벽 + + + + Manually forwarded port + 앞으로 수동 포트 + + + Dicovery : + 디스커버리 : + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + Discovery : + + + + Share Ip and information with your friend (Disc On) + 공유 IP 및 당신의 친구 (디스크) 정보를 + + + Don't share any information (Disc Off) + (디스크 끄기) 모든 정보를 공유하지 마십시오 + + + + Dynamic DNS: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + + < Back + < 뒤로 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">이 공유 폴더의 목록입니다. 추가할 수 있으며 제거할 폴더 왼쪽에있는 버튼을 사용합니다. 하면 해당 폴더의 모든 파일의 처음에 새 폴더를 추가 공유됩니다.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">각각의 공유 디렉토리를 별도로 설치하실 수있습니다 공유 플래그:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">본문 친구</span><span style=" font-family:'Sans'; font-size:8pt;">:파일을 직접 검색할 수있습니다 친구.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">익명 공유</span><span style=" font-family:'Sans'; font-size:8pt;">: 파일을 다른 사람에 의해 익명의 터널을 통해 다운로드하실 수있습니다.</span></p></body></html> + + + + Directory + 디렉토리 + + + + Network Wide + 네트워크 와이드 + + + + Browseable + 본문 + + + + Add + 추가 + + + + Remove + 제거하십시오 + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">RetroShare를 사용하여 즐거운 시간 되십시오!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">그냥 한 걸음! 당신은 거의 컴퓨터와 함께 작동하도록 구성 RetroShare 끝났어요.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">이러한 설정을 구성하는 방법과 시기를 RetroShare가 시작됩니다.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Do not show a message when Closing RetroShare + 메시지를 표시하지 마십시오 닫을 때 RetroShare + + + + Start Minimized + 시작을 최소화 + + + + Start RetroShare when my System Starts. + 내 시스템을 시작 할 때 RetroShare를 시작합니다. + + + + Start minimized on system start + + + + + Finish + 마침 + + + + Select A Folder To Share + 를 선택하려면 폴더 공유 + + + + Shared Directory Added! + 공유 디렉토리 추가! + + + + Do you really want to stop sharing this directory ? + 정말이 디렉토리의 공유를 중지하시겠습니까? + + + + Warning! + 경고! + + + + RSettingsWin + + + General + 일반 + + + + Directories + 전화번호부 + + + + Server + 동료 조정 + + + + Transfer + 전송 + + + + Notify + 알림 + + + + Security + 보안 + + + + Message + 메시지 + + + + Forum + 포럼 + + + + Chat + + + + + Appearance + 외관 + + + File Associations + 파일 협회 + + + + Sound + 사운드 + + + + UnknownPage + 알 수없는 페이지 + + + + Error Saving Configuration on page + + + + Error Saving Configuration + 과실 저축 윤곽 + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>다운 :</strong> 0.00 (kB/s) | <strong>최대 :</strong> 0.00 (kB/s) + + + + <strong>Down:</strong> + <strong>다운 :</strong> + + + + <strong>Up:</strong> + <strong>최대 :</strong> + + + Down: + 다운 : + + + Up: + 최대 : + + + + RemoteDirModel + + Friends Directories + 친구 디렉터리 + + + My Directories + 내 디렉토리 + + + Size + 크기 + + + Share Type + 공유 유형 + + + What's new + 어떤 새로운이야 + + + Rank + 계급 + + + Age + 나이 + + + FILE + 파일 + + + Anonymous + 익명 + + + Files + 파일 + + + DIR + 디렉토리 + + + + RetroshareDirModel + + + Anonymous + 익명 + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + 지정되는 부당한 언어 부호: + + + + Invalid GUI style specified: + 지정되는 부당한 도표 사용자 인터페이스 작풍: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + 근원 + + + + Results + 결과 + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + 다운로드 + + + + Enter a keyword here (at least 3 char long) + 여기에 키워드를 입력 (최소 3 길이) 숯불 + + + Copy retroshare Link + retroshare 링크 복사 + + + Send retroshare Link + retroshare 링크 보내기 + + + Broadcast on Channel + 채널에 방송 + + + Recommend to Friends + 친구에게 추천하십시오 + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + 제거하십시오 + + + + Remove All + 모두를 제거하십시오 + + + + + Folder + 폴더 + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">체재 </p></body></html> + + + + Any + 무엇이든 + + + + Audio + 오디오 + + + + Video + 영상 + + + Images + 심상 + + + Programs + 프로그램 + + + Archives + 기록 보관소 + + + Documents + 문서 + + + + Download Notice + 다운로드 공지 사항 + + + + Skipping Local Files + 로컬 파일을 건너 뜁니다 + + + + + Sorry + 죄송합니다 + + + + + This function is not yet implemented. + + + + + Size + 크기 + + + + Type + 유형 + + + + Archive + 아카이브 + + + + CD-Image + CD를 - 이미지 + + + + Document + 문서 + + + + Picture + 그림 + + + + Program + 프로그램 + + + + Directory + 디렉토리 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enter a Keyword here</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">여기에 키워드를 입력하십시오</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Close all Search Resullts</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">모든 검색 결과 삭제</span></p></body></html> + + + Clear all Search Results + 모든 검색 결과 삭제 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Download Selected</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">선택한 다운로드</span></p></body></html> + + + + Include files from your own file list in the search result + 검색 결과에 자신의 파일 목록에서 포함 파일을 + + + + Include own files + 자신의 파일을 포함 + + + + Search inside "browsable" files of your friends + 검색 안으로 "당신 친구의 일람"파일을 + + + + Search in friends lists + 친구 검색 목록 + + + + Multi-hop search at distance 6 in the network +(always reports available files) + 다중 네트워크에서 거리를 6 홉 검색 +(항상) 해당 파일을보고 + + + + F2F search + F2F 검색 + + + + Limit number of results to : + 결과의 한계 번호 : + + + + Filename + 파일명 + + + + Start Search + 검색 시작 + + + + Search + 수색 + + + + Reset + 리셋 + + + + Enter a Keyword here + + + + + Advanced Search + 고급 검색 + + + + Advanced + 고급 + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + 파일명 + + + + File Size + + + + + Age + 나이 + + + + Hash + 해쉬 + + + + KeyWords + 키워드 + + + + Search Id + + + + + SendLinkDialog + + Send + 보내십시오 + + + + ServerPage + + Change + Restart Server + 변화 + 재착수 + + + Server Settings + 동료 조정 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">외부 주소:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">로컬 주소:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + 방화벽 + + + + Manual Forwarded Port + + + + + Download (KB/s) + 다운로드 (KB/s) + + + + Upload (KB/s) + 업로드 (KB/s) + + + + + Network Configuration + 네트워크 구성 + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + 터널 연결 허용 + + + + Local Address + 로컬 주소 + + + + External Address + 외부 주소 + + + + Dynamic DNS + + + + + + Port: + 항구: + + + + Show Discovery information in statusbar + + + + + IP Service + IP 서비스 + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + Misc + 잡다한 + + + behinde Firewall + 방호벽의 뒤에 + + + Forwarded External Port + 발송된 외부 항구 (대패) + + + + Transfer Rates + 이동 속도 + + + + Settings + + Settings + 조정 + + + + Options + 선택권 + + + + Transfer + 전송 + + + + Notify + 알림 + + + + Security + 보안 + + + + Message + 메시지 + + + + Forum + 포럼 + + + + Chat + + + + + Appearance + 외관 + + + + Sound + 사운드 + + + + Cancel + 취소 + + + Apply + 적용하십시오 + + + + OK + 좋습니다 + + + + General + 일반 + + + Network + 네트워크 + + + + Server + 동료 조정 + + + + Directories + 전화번호부 + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + 본문 + + + + Anonymous shared Network Wide + + + + + Network Wide + 네트워크 와이드 + + + Anonymous + 익명 + + + + Browseable by Friends + + + + + OK + + + + + Cancel + + + + + Select A Folder To Share + 를 선택하려면 폴더 공유 + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + Retroshare (뒤에몫) + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + 공유 디렉토리를 추가하십시오 + + + + Stop sharing selected Directory + 그만 공유 디렉토리를 선택 + + + Select A Folder To Share + 를 선택하려면 폴더 공유 + + + Do you really want to stop sharing this directory ? + 정말이 디렉토리의 공유를 중지하시겠습니까? + + + + + Remove + 제거하십시오 + + + Add Shared Directory + 공유 디렉토리를 추가하십시오 + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + 경고! + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + Shared Directory Added! + 공유 디렉토리 추가! + + + + RetroShare Share Manager + RetroShare 공유 관리자 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">공유 관리자</span></p></body></html> + + + + Shared Folder Manager + 공유 폴더 관리자 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + 디렉토리 + + + + Virtual Folder + + + + + Network Wide + 네트워크 와이드 + + + + Browsable + 본문 + + + + Add + 추가 + + + + Close + 닫기 + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + 다운로드 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">파일 </span></p></body></html> + + + + Checking... + 확인중 ... + + + + Check files + 확인 파일 + + + + Copy retroshare Link + retroshare 링크 복사 + + + + Send retroshare Link + retroshare 링크 보내기 + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + 파일 열기 + + + + Open Folder + 폴더 열기 + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + <strong>내 공유 파일</strong> + + + + <strong>Friends Files</strong> + <strong>친구 파일</strong> + + + + <strong>Files</strong> + <strong>파일</strong> + + + + Splitted View + + + + + Friends Folders + 친구 폴더 + + + + My Folders + 나의 폴더 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">파일</span></p></body></html> + + + + All + 모두 + + + + One day old + 어느날 세 + + + + One Week old + 한 주 세 + + + + One month old + 1 개월 + + + + Search files + + + + + Start Search + 검색 시작 + + + + Reset + 리셋 + + + + Tree view + + + + + Flat view + + + + + Download selected + 다운로드 + + + + check files + 확인 파일 + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + Retroshare (뒤에몫) + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">로그인</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + 로그인 + + + + Remember Password + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Create new Profile...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">새 프로필 만들기...</span></a></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">정보...</span></a></p></body></html> + + + + Name (GPG Id) - location: + + + + Name - location: + 이름 - 위치 : + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + 로그인 실패 + + + + Maybe password is wrong + 아마 비밀 번호가 잘못입니다 + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + Create a New Profil + 새 프로필 만들기 + + + This will generate a new Profile + Are you sure you want to continue + 이것은 새 프로필을 생성합니다 + 당신이 계속하겠습니까 + + + + StatisticDialog + + + Statistics + 통계 + + + + Download + 다운로드 + + + + Session: + 회의: + + + + + Downloaded: + 다운로드하는: + + + Average Downloadspeed: + 평균 다운로드 속도: + + + + + Count of Downloads: + 다운로드의 조사: + + + + + + Overall + 전반적인 + + + + Upload + 올려주기 + + + + + + Session + Session: + + + + Uploaded: + 올려주기하는: + + + Average Uploadspeed: + 평균 올려주기 속도: + + + + + Count of Uploads: + 올려주기의 조사: + + + + Uploaded + 올려주기하는 + + + + + + + Connections: + Connections: + + + + + + Peers: + Peers: + + + Misc + 잡다한 + + + + Uptime: + 가동 시간: + + + Overall: + 전반적인: + + + + + Uptime + 가동 시간 + + + + Records + 기록 + + + + Uploadspeed: + 올려주기 속도: + + + + Downloadspeed: + 다운로드 속도: + + + + + Show Settings + 쇼 조정 + + + + Reset + 리셋 + + + + Receive Rate + 비율을 받으십시오 + + + + Send Rate + 비율을 보내십시오 + + + + Always On Top + Always On Top + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Changes the transparency of the Bandwidth Graph + 대역폭 도표의 투명도를 바꾼다 + + + + Save + 저장하십시오 + + + + Cancel + 취소 + + + + Hide Settings + 은신처 조정 + + + + %1 days + + + + + Now + + + + + Transfer + 전송 + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Since: + + + + + Cumulative + + + + + StatusDefs + + + + Offline + 오프라인 + + + + Away + + + + + Busy + + + + + Online + 온라인 + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + 사용 가능 + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + 개인 메시지 + + + + Status message + 상태 메시지 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">개인 메시지</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">귀하의 상태 메시지를 입력하세요</span></p></body></html> + + + + OK + 좋습니다 + + + + Cancel + 취소 + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + 유형 + + + + Delete FeedItem + + + + + SubFileItem + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + File Name + 파일명 + + + + Download + + + + + Play + 놀이 + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + 일시 중지 + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + 등록된 PGP 공개키 인증서를 사용하여 텍스트를 표현. + + + + The text below is your PGP certificate. You have to provide it to your friend + 아래의 텍스트를 귀하의 PGP는 인증서입니다. 당신은 친구에게 그것을 제공해야 + + + + Please, paste your friends PGP certificate into the box below + 제발, 상자 아래에 등록된 PGP 공개키 인증서를 귀하의 친구에 붙여넣기하세요 + + + Your Cert is copied to Clipboard, paste and send it to yourfriend via email or some other way + 귀하의 쿠폰 클립 보드에 복사 붙여넣기하고 너의 친구이기도 이메일 또는 기타 방법을 통해 보내세요 + + + + You can copy this text and send it to your friend via email or some other way + 이 텍스트를 복사하여 친구에게 이메일을 통해 보내세요 + + + + RetroShare + Retroshare (뒤에몫) + + + + Text certificate + 텍스트 증명서 + + + + Copy your Cert to Clipboard + 클립 보드로 복사하여 쿠폰 + + + + Save your Cert into a File + 파일에 사용자 쿠폰 할인 + + + + Run Email program + 이메일 프로그램을 실행 + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + 친구 연결 도움말 + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + 다른 이름으로 저장 + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare 인증서 (*.의 RSC);; 모든 파일 (*) + + + + Certificate Load Failed + 증명서 짐은 실패했다 + + + + TransferPage + + Transfer + 전송 + + + + Transfer options + 전송 옵션 + + + + Queue Size: + 대기열 크기: + + + Maximum Download speed per file: + 파일 당 최대 다운로드 속도: + + + + Default chunk strategy: + 기본 청크 전략 : + + + + Safety disk space limit : + + + + + Streaming + 스트리밍 + + + + Random + 랜덤 + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + Show Cache Transfers + 보기 캐시 전송 + + + F2F Routing + F2F 라우팅 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + TransfersDialog + + + Cancel + 취소 + + + + Clear Completed + 공간은 완료했다 + + + + + Status + 상태 + + + + Completed + 완료하는 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">다운로드 (Downloads):</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">다운로드</span></p></body></html> + + + + Show cache transfers + + + + + Uploads + 업로드 + + + + Selected transfer + 선택한 전송 + + + + Done + 하는 + + + + Active + 액티브 + + + + Outstanding + 우수 + + + Tunneling + 터널링 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">올려주기 (Uploads):</span></p></body></html> + + + + + Name + i.e: file name + 이름 + + + + + Size + i.e: file size + 크기 + + + Progress + i.e: % downloaded + 진도 + + + + Speed + i.e: Download speed + 속도 + + + + Progress / Availability + i.e: % downloaded + 진행 + + + + Sources + i.e: Sources + 근원 + + + + Core-ID + + + + + Progress + i.e: % uploaded + 진도 + + + + Speed + i.e: upload speed + 속도 + + + + Transferred + 전송 + + + + Hash + 해쉬 + + + + Play + 놀이 + + + + Pause + 일시 중지 + + + + Resume + 이력서 + + + + Open Folder + 폴더 열기 + + + + Open File + 파일 열기 + + + + Preview File + 미리보기 파일 + + + + Details... + 세부 정보 + + + Copy retroshare Link + retroshare 링크 복사 + + + Paste retroshare Link + 붙여넣기 retroshare 링크 + + + View + 보기 + + + + Down + 아래로 + + + + Up + 위로 + + + + Top + 위쪽 + + + + Bottom + 아래쪽 + + + Move in queue... + 대기열로 이동 ... + + + + Priority (Speed)... + 우선순위 (고속) ... + + + + Streaming + 스트리밍 + + + + Random + 랜덤 + + + + Chunk strategy + 청크 전략 + + + + Queued + 대기 + + + + Checking... + 확인중 ... + + + + RetroShare + Retroshare (뒤에몫) + + + + Details: + 세부 사항 : + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + 열기 전송 + + + + File %1 is not completed. If it is a media file, try to preview it. + %1 파일이 완료되지 않습니다. 만약 미디어 미리보기하려고하는 파일입니다. + + + + Are you sure that you want to cancel and delete these files? + 당신을 취소하고 해당 파일을 삭제하겠습니까? + + + + Speed / Queue position + 고속 / 대기열에 위치 + + + + Remaining + 남은 시간 + + + + Download time + i.e: Estimated Time of Arrival / Time left + 다운로드 시간 + + + + Peer + i.e: user name + 피어 + + + + Router Statistics + 라우터 통계 + + + + Router Requests + + + + + Force Check + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + 천천히 + + + + + + Average + 평균 + + + + + Faster + 빨리 + + + + Move in Queue... + 대기열에있는 이동 ... + + + + + + Failed + 실패 + + + + + + Okay + 좋아요 + + + + + Waiting + 대기 + + + + Downloading + 다운로드 + + + + + + + Complete + 완료 + + + + Paused + 일시 중지됨 + + + + Unknown + 알 수없는 + + + + version: + 버전: + + + + Transferring + 전송 + + + + Uploading + 업로드 + + + + TreeStyle_RDM + + + + FILE + 파일 + + + + Files + 파일 + + + + File + + + + + + DIR + 디렉토리 + + + + Friends Directories + 친구 디렉터리 + + + + My Directories + 내 디렉토리 + + + + Size + 크기 + + + + Age + 나이 + + + + Friend + + + + + Share Type + 공유 유형 + + + + What's new + 어떤 새로운이야 + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + 신망 + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + 전체 + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + 라우터 통계 + + + + F2F router information + F2F 라우터 정보 + + + Type + 유형 + + + + TurtleRouterStatistics + + + Router Statistics + 라우터 통계 + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + 좋습니다 + + + + Cancel + 취소 + + + + Yes + 그렇습니다 + + + + No + 아니다 + + + + Help + 도움 + + + + Retry + 재시도 + + + + Show Log + 쇼 역사 + + + + Show Settings + 쇼 조정 + + + + Continue + + + + + Quit + 종료 + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + 알 수없는 + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + 알 수없는 + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + diff --git a/retroshare-gui/src/lang/retroshare_nl.ts b/retroshare-gui/src/lang/retroshare_nl.ts new file mode 100644 index 000000000..56f136ef8 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_nl.ts @@ -0,0 +1,12214 @@ + + + + + AboutDialog + + + About RetroShare + + + + + About + + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + + + + + Sorry, can't determine system default command for this file + + + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + RetroShare: Advanced Search + + + + + Cancels the search. + + + + + Cancel + + + + + Perform the advanced search. + + + + + Search + + + + + Search Criteria + + + + + AppearancePage + + + Language + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + + + Style + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + + + Style Sheet + + + + + ApplicationWindow + + + Hide + + + + + Show + + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + + + + + + RetroShare + + + + + AttachFileItem + + + Form + + + + + %p Kb + + + + + Cancel Download + + + + + BandwidthGraph + + + + Show Settings + + + + + Since: + + + + + Hide Settings + + + + + RetroShare Bandwidth Usage + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always on Top + + + + + Style + + + + + Changes the transparency of the Bandwidth Graph + + + + + 100 + + + + + % Opaque + + + + + Save + + + + + Cancel + + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + + + + + Close + + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + + + + + CalDialog + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Remove + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + + + + + Please choose a filename + + + + + + + + RetroShare + + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + + + + + OK + + + + + Close + + + + + ChannelFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubscribe + + + + + Subscribe To Channel + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + + Create Channel + + + + + Unsubcribe To Channel + + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + + + + + Cancel + + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Details + + + + + Peer Info + + + + + Name + + + + + Peer ID + + + + + Last Contact + + + + + Version + + + + + Loc + + + + + RetroShare ID + + + + + Status + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port + + + + + Peer Address + + + + + Friend Details + + + + + Addresses list + + + + + Your trust in this peer is: + + + + + None + + + + + Marginal + + + + + Full + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Make Friend + + + + + Certificate + + + + + Cancel + + + + + Apply and Close + + + + + + RetroShare + + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + Deny Friend + + + + + + Sign GPG key + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + OK + + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + + + + + Description + + + + + Type: + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Name + + + + + Description + + + + + Type: + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authenticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + Create + + + + + CreateForumMsg + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Close + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + + + + + + General + + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + + + + + Cancel + + + + + Rating + + + + + File Name + + + + + Not Rated + + + + + No Comments + + + + + DirectoriesPage + + + + Browse + + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + + + + + Edit Share + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + + + # + + + + + Status + + + + + Person + + + + + Auto Connect + + + + + Trust Level + + + + + Peer Address + + + + + Last Contact + + + + + Organisation + + + + + Location + + + + + Country + + + + + Person Id + + + + + Auth Code + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + OK + + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + + + + + Expand + + + + + + RetroShare + + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + + Start New Thread + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Date + + + + + + Title + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + + + + + Status + + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + + + + + Clear Chat History + + + + + + Add Friend + + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + + + + + Certificates (*.pqi) + + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + + + + + Status + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Accept + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + + + + + Certificates (*.pqi *.pem) + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + + GeneralPage + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + + + + + + + %1 KB/s + + + + + Sent: + + + + + %1 KB + + + + + %1 MB + + + + + %1 GB + + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + + + + + Description + + + + + Reset + + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + + + + + Size + + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + + Search + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Home + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + + + + + + Copy + + + + + Remove + + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + + + + + Expand + + + + + Hide + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + From + + + + + All Peers + + + + + Own Links + + + + + Show + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + MainWindow + + + Network + + + + + Friends + + + + + + Transfers + + + + + + Messages + + + + + + Channels + + + + + + Options + + + + + Hide + + + + + Show + + + + + RetroShare + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Search + + + + + Files + + + + + Blogs + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Show/Hide + + + + + Status + + + + + &Quit + + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + + Minimize + + + + + Maximize + + + + + Links Cloud + + + + + Unfinished + + + + + Help + + + + + + Forums + + + + + + + + You have %1 new message + + + + + Open Messages + + + + + Applications + + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + Add Friend + + + + + Add a Friend Wizard + + + + + Add Share + + + + + Quit + + + + + + Quick Start Wizard + + + + + SMPlayer + + + + + Messenger + + + + + MainWindow + + + + + About + + + + + MessageComposer + + + + Compose + + + + + + Contacts + + + + + Search for Name: + + + + + Reset + + + + + Send To: + + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + + + + + File Name + + + + + Size + + + + + Hash + + + + + Send + + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + + + + + Size + + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + + + + + Download all + + + + + Hide + + + + + Expand + + + + + File + + + + + Files + + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + + + + + Compose + + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + + + + + Quick View + + + + + Reply to Message + + + + + Remove Message + + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + + Empty trash + + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + + + + + + Total: + + + + + + Reply to All + + + + + + + + Inbox + + + + + + + + Outbox + + + + + Draft + + + + + + Sent + + + + + + + From + + + + + + Subject + + + + + Reply + + + + + Reply all + + + + + Foward + + + + + Delete + + + + + Compose + + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + Reset + + + + + Attachments + + + + + + Date + + + + + + Content + + + + + + + + + Tags + + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + + Print + + + + + MessengerWindow + + + Expand all + + + + + Collapse all + + + + + Chat + + + + + Message Friend + + + + + Connect To Friend + + + + + Peer Details + + + + + Recomend this Friend to... + + + + + Export Friend + + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + + + + + Certificates (*.pqi) + + + + + Click to Change your Avatar + + + + + Search Friends + + + + + Reset + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgItem + + + Remove Item + + + + + + Expand + + + + + Reply to Message + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Unknown + + + + + yourself + + + + + Network + + + + + + + Name + + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + + Cert Id + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + External ip address finder + + + + + Create New Profile + + + + + Create a new Profile + + + + + Clear + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + NetworkView + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + + + + + Options + + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + + + + + Forums + + + + + Chat + + + + + Blogs + + + + + Messages + + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + + Remove Item + + + + + + Expand + + + + + Peer ID: + + + + + Status: + + + + + Trust: + + + + + Write Message + + + + + Chat + + + + + Write a quick Message + + + + + Start Chat + + + + + Send + + + + + Cancel + + + + + Name: + + + + + Location + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + + Date + + + + + + Location + + + + + Size + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Close + + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Send + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + + + + + RetroShare + + + + + Error : cannot get peer details. + + + + + Profile View + + + + + + Name + + + + + Peer ID + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Size + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + + + RetroShare + + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + + + + + Directories + + + + + Server + + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + + + + + Invalid GUI style specified: + + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + + Download + + + + + Remove + + + + + Remove All + + + + + Download Notice + + + + + Enter a keyword here (at least 3 char long) + + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + + Folder + + + + + New RetroShare Link(s) + + + + + Any + + + + + Archive + + + + + Audio + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Video + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + + + + + File Size + + + + + Close all Search Resullts + + + + + Download Selected + + + + + Close All Search Results + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + + + + + Reset + + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Size + + + + + Sources + + + + + Type + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Results + + + + + Search Id + + + + + ServerPage + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Transfer Rates + + + + + Download (KB/s) + + + + + + kB/s + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + + Settings + + + Options + + + + + General + + + + + Server + + + + + Transfer + + + + + Directories + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + Cancel + + + + + OK + + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + + OK + + + + + Cancel + + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + + Show Settings + + + + + Hide Settings + + + + + %1 days + + + + + Statistics + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Download + + + + + Session: + + + + + + Downloaded: + + + + + + Count of Downloads: + + + + + + + Overall + + + + + Upload + + + + + + + Session + + + + + Uploaded: + + + + + + Count of Uploads: + + + + + Uploaded + + + + + + + + Connections: + + + + + + + Peers: + + + + + Time Statistics + + + + + + Uptime + + + + + Since: + + + + + Cumulative + + + + + Records + + + + + Uploadspeed: + + + + + Downloadspeed: + + + + + Uptime: + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always On Top + + + + + 100 + + + + + % Opaque + + + + + Changes the transparency of the Bandwidth Graph + + + + + Save + + + + + Cancel + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + + + + + Cancel + + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + + Delete FeedItem + + + + + SubFileItem + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + + + + + Clear Completed + + + + + + Status + + + + + Completed + + + + + + Name + i.e: file name + + + + + + Size + i.e: file size + + + + + Speed + i.e: Download speed + + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + + + + + Core-ID + + + + + Peer + i.e: user name + + + + + Progress + i.e: % uploaded + + + + + Speed + i.e: upload speed + + + + + Transferred + + + + + Hash + + + + + Router Statistics + + + + + Router Requests + + + + + Force Check + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + Play + + + + + Pause + + + + + Resume + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + version: + + + + + Queued + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Move in Queue... + + + + + Priority (Speed)... + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + + + + + Active + + + + + Outstanding + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + + + + + is authenticated (one way) by + + + + + authenticated himself + + + + + authenticated each other + + + + + is authenticated by + + + + + authenticated + + + + + Half + + + + + Full + + + + + + peers, including him(her)self. + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + + + + + Cancel + + + + + Yes + + + + + No + + + + + Help + + + + + Retry + + + + + Show Log + + + + + Show Settings + + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + diff --git a/retroshare-gui/src/lang/retroshare_pl.qm b/retroshare-gui/src/lang/retroshare_pl.qm new file mode 100644 index 000000000..3469e625a Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_pl.qm differ diff --git a/retroshare-gui/src/lang/retroshare_pl.ts b/retroshare-gui/src/lang/retroshare_pl.ts new file mode 100644 index 000000000..ee78cf637 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_pl.ts @@ -0,0 +1,13998 @@ + + + + + + + Arial + Arial + + + + @default + + Arial + Arial + + + + AboutDialog + + + About RetroShare + + + + + About + O + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + + + + + Sorry, can't determine system default command for this file + + + + + + AddFriendDialog + + Cancel + Anuluj + + + Done + Wykonano + + + Load From File + Wczytaj z pliku + + + RetroShare + RetroShare + + + Certificate Load Failed + Błąd wczytania certyfikatu + + + Add a Friend + Dodaj znajomego + + + + AddFriendWizard + + Add Friend to my netowork Wizard + Dodaj znajomego do kreatora sieci + + + < Back + <Do tyłu + + + Next > + Następny> + + + Cancel + Anuluj + + + I have a .pqi/.pem file received from a Friend + Mam plik .pqi/.pem przyjęty od znajomego + + + I have Key received from a Friend + Mam klucz przyjęty od znajomego + + + I want to invite a friend to my RetroShare network + Chcę zaprosić znajomego do mojej sieci RetroShare + + + Browse + Przeglądaj + + + Certificate Load Failed + Błąd wczytania certyfikatu + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + Anuluj + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Cancel + Anuluj + + + + Search + Szukaj + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search Criteria + + + + + AppearanceDialog + + Language + Język + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wybierz język używany przez RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Zmiana języka przyniesie efekt po ponownym uruchomieniu RetroShare!</p></body></html> + + + Style + Styl + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wybierz styl interfejsu RetroShare</p></body></html> + + + Style Sheet + Lista stylów + + + + AppearancePage + + + Language + Język + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wybierz język używany przez RetroShare</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Zmiana języka przyniesie efekt po ponownym uruchomieniu RetroShare!</p></body></html> + + + + Style + Styl + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wybierz styl interfejsu RetroShare</p></body></html> + + + + Style Sheet + Lista stylów + + + + ApplicationWindow + + + Hide + Ukryj + + + + Show + Pokaż + + + Transfers + Transfery + + + Messages + Wiadomości + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + Statystyki + + + + + RetroShare + + + + + AttachFileItem + + + Form + + + + File Name + Nazwa pliku + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + Autentykacja + + + Authenticate Friend By Entering Their Code + Autentykacja znajomego przez wpisanie jego kodu + + + OK + OK + + + Cancel + Anuluj + + + + BandwidthGraph + + + RetroShare Bandwidth Usage + Przepustowość łącza używana przez RetroShare + + + + + Show Settings + Pokaż ustawienia + + + + Reset + Reset + + + + Receive Rate + Pokaż ściąganie + + + + Send Rate + Pokaż wysyłanie + + + + Always on Top + Zawsze na wierzchu + + + + Style + Styl + + + + Changes the transparency of the Bandwidth Graph + Zmień przezroczystość wykresu przepustowości łącza + + + + 100 + 100 + + + + % Opaque + % nieprzezroczysty + + + + Save + Zapisz + + + + Cancel + Anuluj + + + + Since: + Od czasu kiedy: + + + + Hide Settings + Ukryj ustawienia + + + + BgWindow + + Options + Opcje + + + About + O + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + Anuluj + + + + OK + + + + + Close + Zamknij + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + Nazwa + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + Ukryj + + + + CalDialog + + + Name: + Nazwa: + + + + Location: + Lokalizacja: + + + + Remove + Usuń + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Peer Calendars + + + + + CallToaster + + Message + Wiadomość + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + Przeglądaj + + + + Select Certificate + Wybierz certyfikat + + + Certificates (*.pqi *.pem) + Certyfikaty (*.pqi *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + Create a new Broadcast Channel + Stwórz nowy kanał transmisji + + + Create A New Broadcast Channel + Stwórz nowy kanał transmisji + + + Channel Name: + Nazwa kanału: + + + Type: + Typ: + + + Public Channel (Signed) + Kanał publiczny (Podpisany) + + + Private Channel (Encrypted) + Prywatny kanał (Zaszyfrowany) + + + Cancel Channel + Anuluj kanał + + + Create Channel + Stwórz kanał + + + + ChanMsgDialog + + Compose + Składać + + + Recommended Files + Rekomendowany Plik + + + Send To: + Wyślij do: + + + Send + Wyślij + + + Delete Channel + Skasuj kanał + + + Create Channel MSG + Stwórz kanał MSG + + + &Quit + &Zamknij + + + File Name + Nazwa pliku + + + Size + Rozmiar + + + Sources + Źródła + + + Save + Zapisz + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + Pobieranie + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Ukryj + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + Kanały + + + Video + Wideo + + + 1 + 1 + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + Typ + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + Anuluj + + + + OK + + + + + Close + Zamknij + + + + ChannelFeed + + + Create Channel + Stwórz kanał + + + + Subscribe To Channel + Subskrybuj kanał + + + Title + Tytuł + + + Reset + Reset + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + Name + Nazwa + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChannelStatsDialog + + 1 + 1 + + + + ChatDialog + + Chat + Chat + + + 1 + 1 + + + Send + Wyślij + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + Wyślij + + + + Cancel + Anuluj + + + Chat + Chat + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + Główne + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + Styl + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ChatToaster + + Message + Wiadomość + + + + ComboStatus + + Online + Dostępny + + + Away + Nieobecny + + + Busy + Zajęty + + + + ConclusionPage + + + Make Friend + Twórz znajomego + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + Opcje + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + Nazwa: + + + + Loc: + + + + Country: + Kraj: + + + + Signers + + + + + ConfCertDialog + + + Cancel + Anuluj + + + Port: + Port: + + + Trust Settings + Zaufane ustawienia + + + Trust Level + Zaufany poziom + + + Trust Their Signature + Zaufaj tej sygnaturze + + + Sign The Certificate + Znak certyfikatu + + + + OK + Ok + + + + Peer Info + Info Peera + + + Peer Details + Detale Peera + + + + Details + Detale + + + + Name + Nazwa + + + + Loc + + + + + Peer Address + Adres Peera + + + Name: + Nazwa: + + + + Last Contact + Ostatni kontakt + + + + Peer ID + + + + + Version + + + + + Addresses list + + + + + None + + + + + Marginal + + + + + Full + + + + + Deny Friend + + + + + + Sign GPG key + + + + + Friend Details + + + + + RetroShare ID + + + + + Status + Status + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port + + + + + Your trust in this peer is: + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Make Friend + Twórz znajomego + + + + Certificate + + + + + Apply and Close + + + + + + RetroShare + + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + ConnectDialog + + Peer Details + Detale Peera + + + Make Friend + Twórz znajomego + + + Cancel + Anuluj + + + Name: + Nazwa: + + + Country: + Kraj: + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + Nazwa + + + + Description + + + + + Type: + Typ: + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + Anuluj + + + + Create + + + + + RetroShare + + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + &Zamknij + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + Nazwa + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + Typ: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + Anuluj + + + + Create + + + + + RetroShare + + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + Wiadomość + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Nazwa + + + + Type: + Typ: + + + + Authenticated Messages + + + + + Cancel + Anuluj + + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Description + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Create + + + + + CreateForumMsg + + + Close + Zamknij + + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + CryptographyDialog + + RSA Key Size + Rozmiar klucza RSA + + + Rijndael Block size + Rozmiar bloku Rijndael + + + 128 Bits + 128 Bits + + + 192 Bits + 192 Bits + + + 256 Bits + 256 Bits + + + Rijndael Key Size + Rozmiar klucza Rijndael + + + Rijndael Mode + Tryb Rijndael + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + Rijndael Padding + Wypełnianie Rijndael + + + PKCS7 + PKCS7 + + + Zeros + Zera + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Rozmiar odpowiedzi Rijndael + + + Key Size: + Rozmiar klucza: + + + Block Size: + Rozmiar bloku: + + + Feedback Size: + Rozmiar odpowiedzi: + + + Mode: + Tryb: + + + Padding: + Wypełnienie: + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Detale + + + + + General + Główne + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + Typ: + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + Data + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + + + + + Cancel + Anuluj + + + + Rating + + + + + File Name + Nazwa pliku + + + + Not Rated + + + + + No Comments + + + + + DirectoriesDialog + + Shared Directories + Współdzielone katalogi + + + Other Directories + Inne katalogi + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Przychodzące pliki</span></p></body></html> + + + Add Shared Directory + Dodaj współdzielone katalogi + + + Browse + Przeglądaj + + + + DirectoriesPage + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + Współdzielone katalogi + + + + Edit Share + + + + Incoming files + Przychodzące pliki + + + + + Browse + Przeglądaj + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + Zamknij + + + + EditChanDetails + + + Channel Details + + + + + Cancel + Anuluj + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + Anuluj + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Znajomi</span></p></body></html> + + + + # + # + + + + Status + Status + + + + Person + Osoba + + + + Auto Connect + Autopołączenie + + + + Trust Level + Zaufany poziom + + + + Peer Address + Adres Peera + + + + Last Contact + Ostatni kontakt + + + + Organisation + Organizacja + + + + Location + Lokalizacja + + + + Country + Kraj + + + + Person Id + ID osoby + + + + Auth Code + Kod autentykacji + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileHashDialog + + Download + Pobieranie + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + %1 KB + %1 KB + + + File Name + Nazwa pliku + + + Size + Rozmiar + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + Rozmiar + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + Anuluj + + + + OK + + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + Wyślij + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + Misc + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + Ukryj + + + + Expand + + + + + + RetroShare + + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + + Date + Data + + + + + Title + Tytuł + + + + + Start New Thread + + + + New Message + Nowa Wiadomość + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + Reset + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + Znajomi + + + + Status + Status + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + Wyślij + + + + Clear Chat History + + + + + + Add Friend + Dodaj znajomego + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + Lokalizacja + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + Chat + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + Zapisz certyfikat + + + + Certificates (*.pqi) + Certyfikaty (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + Główne + + + Network + Sieć + + + Directories + Katalogi + + + Server + Serwer + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Server + Serwer + + + + Status + Status + + + + Accept + Akceptuj + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Konfiguracja RetroShare + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Generate a new profile</span><br /><br />Please fill in the information which will<br />allow your RetroShare to connect to</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Friends.</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Generuj nowy profil</span><br /><br />Please fill in the information which will<br />allow your RetroShare to connect to</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Znajomi.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Organisation:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Organizacja:</p></body></html> + + + Password (Again) + Hasło (Ponownie) + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + Nazwa + + + + Enter here your nickname + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Put a strong password here. This password protects your GPG key. + + + + Location: + Lokalizacja: + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Email + + + + + + Your profile is associated to a GPG key + + + + + Location + Lokalizacja + + + + Generate New Profile + + + + Load Trusted Certificate (Optional) + Wczytaj zaufany certyfikat (Opcjonalnie) + + + + Info + + + + + Password + Hasło + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Znajomy</span></p></body></html> + + + Select File + Wybierz plik + + + Country: + Kraj: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nazwa:</p></body></html> + + + Generate New Certificate + Wygeneruj nowy certyfikat + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + Wybierz zaufanego znajomego + + + + Certificates (*.pqi *.pem) + Certyfikaty (*.pqi *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + Name: + Nazwa: + + + + GeneralDialog + + Style + Styl + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wybierz styl interfejsu RetroShare</p></body></html> + + + Language + Język + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wybierz język używany przez RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Zmiana języka przyniesie efekt po ponownym uruchomieniu RetroShare!</p></body></html> + + + Style Sheet + Lista stylów + + + Login + Login + + + Misc + Misc + + + + GeneralMsgDialog + + Message + Wiadomość + + + + GeneralPage + + Keys manager + Menadżer kluczy + + + Style + Styl + + + Choose RetroShare's interface style + Wybierz styl interfejsu RetroShare's + + + Language + Język + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Zmiana języka przyniesie efekt po ponownym uruchomieniu RetroShare!</p></body></html> + + + Choose the language used in RetroShare + Wybierz język używany w RetroShare + + + Login + Login + + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + Misc + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Recv: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Wysłany: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Znajomi + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + Tytuł + + + + Description + + + + + Reset + Reset + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + Nazwa + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + Data + + + + Size + Rozmiar + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + Search + Szukaj + + + + Home + Home + + + + Close + Zamknij + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + O + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + Autorzy + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + Thanks to + Podziękowania dla + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Translation + Tłumaczenie + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + License Agreement + Umowa licencyjna + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + Reset + + + + + Copy + + + + + Remove + Usuń + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + Wyślij + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + InviteDialog + + Done + Wykonano + + + Cancel + Anuluj + + + Launch Email + Uruchom klienta Email + + + Invite a Friend + Zaproś znajomego + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + Pobieranie + + + + Expand + + + + + Hide + Ukryj + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + Z + + + + Show + Pokaż + + + + 101-200 + 101-200 + + + + 201-300 + 201-300 + + + + 301-400 + 301-400 + + + + 401-500 + 401-500 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + MainWindow + + + Network + Sieć + + + + Friends + Znajomi + + + + + Transfers + Transfery + + + + + Messages + Wiadomości + + + + + Channels + Kanały + + + + Blogs + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + Status + + + + Chat + Chat + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + Online + Dostępny + + + Busy + Zajęty + + + Away + Nieobecny + + + + + Options + Opcje + + + + Hide + Ukryj + + + + Show + Pokaż + + + + RetroShare + Retroshare + + + Invite Friend + Zaproś znajomego + + + + MainWindow + + + + + Add Friend + Dodaj znajomego + + + + Add a Friend Wizard + + + + + Add Share + Dodaj udostępniany + + + + + Quick Start Wizard + + + + + Search + Szukaj + + + + Files + Pliki + + + Add Shared Directory + Dodaj udostępniane katalogi + + + + Messenger + Messenger + + + + Show/Hide + Pokaż/Ukryj + + + + &Quit + &Zamknij + + + + + + + You have %1 new message + + + + + Bandwidth Graph + Wykres przepustowości łącza + + + + Open Messenger + Otwórz Messenger + + + + Minimize + + + + + Maximize + + + + + Links Cloud + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Unfinished + + + + + Help + Pomoc + + + + About + O + + + + + Forums + + + + + Open Messages + + + + + Applications + + + + Settings + Ustawienia + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + Quit + + + + + SMPlayer + + + + + MessageComposer + + + + Compose + Składać + + + + + Contacts + + + + + Search for Name: + + + + + Reset + Reset + + + + Send To: + Wyślij do: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + Rekomendowany Plik + + + + File Name + Nazwa pliku + + + + Size + Rozmiar + + + Sources + Źródła + + + + Hash + + + + + Send + Wyślij + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + Zapisz + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + &Zamknij + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + Misc + Misc + + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + Wiadomość + + + New Message + Nowa Wiadomość + + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + Zamknij + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekomendowane pliki</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + Nazwa pliku + + + + Size + Rozmiar + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + Pobieranie + + + + Download all + + + + + Hide + Ukryj + + + + Expand + + + + + File + + + + + Files + Pliki + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + Nowa Wiadomość + + + + Compose + Składać + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + &Zamknij + + + + MessagesDialog + + + + New Message + Nowa Wiadomość + + + + Quick View + + + + + Reply to Message + Odpowiedz na wiadomość + + + + Remove Message + Usuń wiadomość + + + + + Date + Data + + + + + + From + Z + + + Size + Rozmiar + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekomendowane pliki</span></p></body></html> + + + + Reply + + + + + Reply all + + + + + Foward + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">usuń wybrane wiadomości</p></body></html> + + + + Delete + + + + + Compose + Składać + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + Reset + Reset + + + + Attachments + + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + Pobrane email + + + + + + + Outbox + Outbox email + + + + Draft + Załącznik + + + + + Sent + Wysłane email + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">odpowiedz na wybraną wiadomość</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nowa wiadomość</p></body></html> + + + Download All + Pobierz wszystko + + + File Name + Nazwa pliku + + + Sources + Źródła + + + # + # + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + Pobieranie + + + + Empty trash + + + + Hide + Ukryj + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + Files + Pliki + + + + + + + + Total: + + + + + + Reply to All + + + + + + Subject + + + + + Print + + + + + MessagesPopupDialog + + New Message + Nowa Wiadomość + + + Reply to Message + Odpowiedz na wiadomość + + + Remove Message + Usuń wiadomość + + + Download All + Pobierz wszystko + + + Messages + Wiadomości + + + Inbox + Pobrane email + + + Outbox + Outbox email + + + Draft + Załącznik + + + Sent + Wysłane email + + + From + Z + + + Date + Data + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekomendowane pliki</span></p></body></html> + + + File Name + Nazwa pliku + + + Size + Rozmiar + + + Sources + Źródła + + + Compose + Składać + + + Remove + Usuń + + + + MessengerDirModel + + Size + Rozmiar + + + Rank + Rząd + + + + MessengerSharedFiles + + Download + Pobieranie + + + + MessengerWindow + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click to change your avatar</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Kliknij aby zmienić swój avatar</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Change your Status and your display</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">picture here.</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Zmień swój status i swoje wyświetlanie</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">obrazek tutaj.</p></body></html> + + + Online + Dostępny + + + Busy + Zajęty + + + + RetroShare Messenger + + + + + Add a Friend + Dodaj znajomego + + + + Search Friends + + + + + Reset + Reset + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + Be right Back + Zaraz wracam + + + Away + Nieobecny + + + Apear Offline + Niedostępny + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Share a personal message with your contacts</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Podziel aię prywatną wiadomością z twoimi kontaktami</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Add a Friend</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dodaj znajomego</p></body></html> + + + + Expand all + + + + + Collapse all + + + + + Chat + Chat + + + + Message Friend + + + + + Connect To Friend + Połącz z znajomym + + + + Peer Details + Detale Peera + + + + Recomend this Friend to... + + + + + Export Friend + Eksportuj znajomego + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + Zapisz certyfikat + + + + Certificates (*.pqi) + Certyfikaty (*.pqi) + + + Remove Friend + Usuń znajomego + + + + Click to Change your Avatar + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + Pobrane email + + + Outbox + Outbox email + + + Sent + Wysłane email + + + Date + Data + + + + MsgItem + + + Reply to Message + Odpowiedz na wiadomość + + + + Remove Item + + + + + + Expand + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Ukryj + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Wiadomości</span></p></body></html> + + + Date + Data + + + Rank + Rząd + + + From + Z + + + Title + Tytuł + + + Msg + Wiadomość + + + Count + Numer + + + Size + Rozmiar + + + Type + Typ + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tekst wiadomości</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekomendowane pliki</span></p></body></html> + + + Delete Channel + Skasuj kanał + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Wiadomości</span></p></body></html> + + + Date + Data + + + Rank + Rząd + + + From + Z + + + Title + Tytuł + + + Msg + Wiadomość + + + Count + Numer + + + Size + Rozmiar + + + Type + Typ + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tekst wiadomości</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekomendowane pliki</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + Wczytaj certyfikat + + + Select a pem/pqi File + Wybierz plik pem/pqi + + + File Not Found + Nie znaleziono pliku + + + %1 does not exist. Would you like to create it? + %1 nie istnieje. Czy chciałbyś go utworzyć? + + + Failed to Create File + Błąd tworzenia pliku + + + Unable to create %1 [%2] + Nie można stworzyć %1 [%2] + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + Select Certificate + Wybierz certyfikat + + + Certificates (*.pqi *.pem) + Certyfikaty (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Sieć:</span></p></body></html> + + + # + # + + + Accept + Akceptuj + + + Trust + Zaufaj + + + Last Contact + Ostatni kontakt + + + + + + Name + Nazwa + + + Peer Address + Adres Peera + + + Organisation + Organizacja + + + Location + Lokalizacja + + + Country + Kraj + + + + + Cert Id + Cert Id + + + + Network + Sieć + + + Peer Details + Detale Peera + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Unknown + + + + + yourself + + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + Dodaj znajomego + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + Opcje przesyłania + + + Max Total Data Rate (KB/S): + Maksymalna prędkość wysyłania (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Przesyłanie na osobę (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Ukryj ustawienia + + + Show Settings + Pokaż ustawienia + + + Settings + Ustawienia + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Znajomi + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + Nazwa: + + + + Choose color + + + + + OK + + + + + Cancel + Anuluj + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Usuń wszystko + + + + Options + Opcje + + + + NotifyDialog + + Channels + Kanały + + + Chat + Chat + + + Messages + Wiadomości + + + New Message + Nowa Wiadomość + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + Kanały + + + + Forums + + + + + Chat + Chat + + + + Blogs + + + + + Messages + Wiadomości + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + Wiadomość + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + Nowa Wiadomość + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + OptionsDlg + + Cancel + Anuluj + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + Make Friend + Twórz znajomego + + + Remove Friend + Usuń znajomego + + + + Chat + Chat + + + + Start Chat + + + + + Send + Wyślij + + + + Cancel + Anuluj + + + + Name: + Nazwa: + + + Organisation + Organizacja + + + + Location + Lokalizacja + + + Country + Kraj + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Peer ID: + + + + + Write Message + + + + + Status: + + + + + Trust: + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + Ukryj + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Znajomi + + + Online + Dostępny + + + + PeersDialog + + Chat + Chat + + + Export Friend + Eksportuj znajomego + + + Remove Friend + Usuń znajomego + + + Save Certificate + Zapisz certyfikat + + + Certificates (*.pqi) + Certyfikaty (*.pqi) + + + Status + Status + + + Person + Osoba + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Znajomi</span></p></body></html> + + + Connect To Friend + Połącz z znajomym + + + # + # + + + Peer Details + Detale Peera + + + Online + Dostępny + + + Away + Nieobecny + + + Busy + Zajęty + + + Location + Lokalizacja + + + Send + Wyślij + + + Add Friend + Dodaj znajomego + + + Friends + Znajomi + + + + PeersFeed + + Save Certificate + Zapisz certyfikat + + + Certificates (*.pqi) + Certyfikaty (*.pqi) + + + Friends + Znajomi + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Usuń + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + + Date + Data + + + + + Location + Lokalizacja + + + + Size + Rozmiar + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Location: + Lokalizacja: + + + + Date: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + Usuń + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + Wyślij + + + + Close + Zamknij + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Directories + Katalogi + + + Error Saving Configuration + Błąd zapisu konfiguracji + + + General + Główne + + + Server + Serwer + + + Options + Opcje + + + Cancel + Anuluj + + + OK + Ok + + + Help + Pomoc + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + Pobierz wszystko + + + + RetroShare + + + + + Error : cannot get peer details. + + + + + + Name + Nazwa + + + + Peer ID + + + + + Size + Rozmiar + + + + Profile View + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + Name + Nazwa + + + Date + Data + + + Size + Rozmiar + + + + + RetroShare + + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + Następny> + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + <Do tyłu + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + Usuń + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + Główne + + + + Directories + Katalogi + + + + Server + Serwer + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + Wiadomość + + + + Forum + + + + + Chat + Chat + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Błąd zapisu konfiguracji + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RemoteDirModel + + Size + Rozmiar + + + Rank + Rząd + + + Files + Pliki + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Błędny kod języka: + + + + Invalid GUI style specified: + Błędny styl GUI: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + Źródła + + + + Results + Rezultat + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + Pobieranie + + + + Enter a keyword here (at least 3 char long) + + + + Broadcast on Channel + Kanał rozsiewczy + + + Recommend to Friends + Zarekomenduj znajomemu + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + Usuń + + + + Remove All + Usuń wszystko + + + + + Folder + + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + + Any + Dowolny + + + + Audio + Audio + + + + Video + Wideo + + + Images + Obrazy + + + Programs + Programy + + + Archives + Archiwa + + + Documents + Dokumenty + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Size + Rozmiar + + + + Type + Typ + + + + Archive + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + Nazwa pliku + + + + File Size + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + Szukaj + + + + Reset + Reset + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Search Id + + + + + SendLinkDialog + + Send + Wyślij + + + + ServerDialog + + Transfer Rates + Szybkość przesyłania + + + Port: + Port: + + + + ServerPage + + Change + Restart Server + Zmień + Restartuj serwer + + + Server Settings + Ustawienia serwera + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Zewnętrzny Adres:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokalny Adres:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Download (KB/s) + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + Port: + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + Misc + Misc + + + behinde Firewall + Za firewallem + + + Forwarded External Port + Następny zewnętrzny Port (Router) + + + + Transfer Rates + Szybkość przesyłania + + + + Settings + + Settings + Ustawienia + + + + Options + Opcje + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + Wiadomość + + + + Forum + + + + + Chat + Chat + + + + Appearance + + + + + Sound + + + + + Cancel + Anuluj + + + Apply + Zatwierdź + + + + OK + Ok + + + + General + Główne + + + Network + Sieć + + + + Server + Serwer + + + + Directories + Katalogi + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + Przeglądaj + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + Friends + Znajomi + + + + OK + + + + + Cancel + Anuluj + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + Anuluj + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + Usuń + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + Zamknij + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Pobieranie + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Pliki</span></p></body></html> + + + Add to Recommend List + Dodaj do listy rekomendowanych + + + Recommend To + Rekomenduj do + + + Message Friend + Wiadomość od znajomego + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + Reset + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + Przeglądaj + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + RetroShare + + + Auto-login + Auto-login + + + Name: + Nazwa: + + + + Log In + Zaloguj + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + Statystyki + + + + Download + Pobieranie + + + + Session: + Sesja: + + + + + Downloaded: + Pobierane: + + + Average Downloadspeed: + Średnia prędkość pobierania: + + + + + Count of Downloads: + Numer pobierania: + + + + + + Overall + Ogólnie + + + + Upload + Wysyłanie + + + + + + Session + Sesja + + + + Uploaded: + Wysyłane: + + + Average Uploadspeed: + Średnia prędkość wysyłania: + + + + + Count of Uploads: + Numer wysyłania: + + + + Uploaded + Wysyłane + + + + + + + Connections: + Połączenia: + + + + + + Peers: + Peers: + + + Misc + Misc + + + + Uptime: + Czas nieprzerwanej pracy: + + + Overall: + Ogólnie: + + + + + Uptime + Czas nieprzerwanej pracy + + + + Records + Archiwa + + + + Uploadspeed: + Prędkość wysyłania: + + + + Downloadspeed: + Prędkość pobierania: + + + + + Show Settings + Pokaż ustawienia + + + + Reset + Reset + + + + Receive Rate + Pokaż ściąganie + + + + Send Rate + Pokaż wysyłanie + + + + Always On Top + Zawsze na wierzchu + + + + 100 + 100 + + + + % Opaque + % nieprzezroczysty + + + + Changes the transparency of the Bandwidth Graph + Zmień przezroczystość wykresu przepustowości łącza + + + + Save + Zapisz + + + + Cancel + Anuluj + + + + Hide Settings + Ukryj ustawienia + + + + %1 days + + + + + Since: + Od czasu kiedy: + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Cumulative + + + + + StatusDefs + + + + Offline + + + + + Away + Nieobecny + + + + Busy + Zajęty + + + + Online + Dostępny + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + + + + + Cancel + Anuluj + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + Styl + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Typ + + + + Delete FeedItem + + + + + SubFileItem + + File Name + Nazwa pliku + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + Pobieranie + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + Błąd wczytania certyfikatu + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Anuluj + + + + Clear Completed + Wyczyść ukończone + + + + + Status + Status + + + + Completed + Ukończone + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Pobierania:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + Wykonano + + + + Active + + + + + Outstanding + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Wysyłania:</span></p></body></html> + + + + + Name + i.e: file name + Nazwa + + + + + Size + i.e: file size + Rozmiar + + + Progress + i.e: % downloaded + Postęp + + + + Speed + i.e: Download speed + Prędkość + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + Źródła + + + + Core-ID + + + + + Progress + i.e: % uploaded + Postęp + + + + Speed + i.e: upload speed + Prędkość + + + + Transferred + + + + + Hash + + + + + Play + + + + + Pause + + + + + Resume + + + + + Force Check + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Priority (Speed)... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + Queued + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Peer + i.e: user name + + + + + Router Statistics + + + + + Router Requests + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Move in Queue... + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + version: + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + Pliki + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + Rozmiar + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + Zaufaj + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + File Name + Nazwa pliku + + + Type + Typ + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Download + Pobieranie + + + Broadcast on Channel + Kanał rozsiewczy + + + Recommend to Friends + Zarekomenduj znajomemu + + + Remove + Usuń + + + Remove All + Usuń wszystko + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + Any + Dowolny + + + Audio + Audio + + + Video + Wideo + + + Size + Rozmiar + + + Sources + Źródła + + + Type + Typ + + + Results + Rezultat + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + Ok + + + + Cancel + Anuluj + + + + Yes + Tak + + + + No + Nie + + + + Help + Pomoc + + + + Retry + Ponów + + + + Show Log + Pokaż Log + + + + Show Settings + Pokaż ustawienia + + + + Continue + + + + + Quit + + + + + Browse + Przeglądaj + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Details + Detale + + + OK + Ok + + + Name + Nazwa + + + Value + Wartość + + + diff --git a/retroshare-gui/src/lang/retroshare_pt.qm b/retroshare-gui/src/lang/retroshare_pt.qm new file mode 100644 index 000000000..f905b8a62 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_pt.qm differ diff --git a/retroshare-gui/src/lang/retroshare_pt.ts b/retroshare-gui/src/lang/retroshare_pt.ts new file mode 100644 index 000000000..4aa46fdfa --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_pt.ts @@ -0,0 +1,13789 @@ + + + + + + + Arial + Arial + + + + @default + + Arial + Arial + + + + AboutDialog + + + About RetroShare + + + + + About + Sobre + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + Retroshare + + + + Sorry, can't determine system default command for this file + + + + + + AddFileAssotiationDialog + + RetroShare + Retroshare + + + + AddFriendDialog + + Cancel + Cancelamento + + + Done + Feito + + + Load From File + Carga da lima + + + RetroShare + Retroshare + + + Certificate Load Failed + A carga do certificado falhou + + + + AddFriendWizard + + Cancel + Cancelamento + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Cancel + Cancelamento + + + + Search + Busca + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search Criteria + + + + + AppearanceDialog + + Language + Língua + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Escolher a língua usada em Retroshare </p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Escolher o estilo da relação de Retroshare</p></body></html> + + + Style Sheet + Folha do estilo + + + + AppearancePage + + + Language + Língua + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Escolher a língua usada em Retroshare </p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + + + Style + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Escolher o estilo da relação de Retroshare</p></body></html> + + + + Style Sheet + Folha do estilo + + + + ApplicationWindow + + + Hide + não mostrar + + + + Show + Mostra + + + + + RetroShare + Retroshare + + + Transfers + Transferências + + + Messages + Email-Mensagens + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + Statistics + + + + AttachFileItem + + + Form + + + + File Name + Lima - nome + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + Authenticate + + + Authenticate Friend By Entering Their Code + Authenticate o amigo dando entrada ao código + + + OK + APROVAÇÃO (OK) + + + Cancel + Cancelamento + + + + BandwidthGraph + + + + Show Settings + + + + + Reset + Restauração + + + + Receive Rate + Receive Rate + + + + Send Rate + Send Rate + + + + Style + Língua + + + + Changes the transparency of the Bandwidth Graph + Muda a transparência do gráfico da largura de faixa + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Save + Excepto + + + + Cancel + Cancelamento + + + + Since: + + + + + Hide Settings + Não mostrar ajustes + + + + RetroShare Bandwidth Usage + + + + + Always on Top + + + + + BgWindow + + Options + Opções + + + About + Sobre + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + APROVAÇÃO (OK) + + + + Close + Fim + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + não mostrar + + + + CalDialog + + + Remove + Remover + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + Selecionar o certificado + + + Certificates (*.pqi *.pem) + Certificados (*.pqi *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + Retroshare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + Create a new Broadcast Channel + Criar uma canaleta nova da transmissão + + + Create A New Broadcast Channel + Criar uma canaleta nova da transmissão + + + Channel Name: + Nome da canaleta: + + + Type: + Tipo: + + + Public Channel (Signed) + Canaleta pública (assinada) + + + Private Channel (Encrypted) + Canaleta confidencial (cifrada) + + + Cancel Channel + Cancelar a canaleta + + + Create Channel + Create Channel + + + + ChanMsgDialog + + Compose + Compôr + + + Recommended Files + Limas recomendadas + + + Send To: + Emitir a: + + + Send + Emitir + + + Delete Channel + Canaleta da supressão + + + Create Channel MSG + Criar a mensagem da canaleta + + + File Name + Lima - nome + + + Size + Tamanho + + + Sources + Fontes + + + Save + Excepto + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + Download + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + não mostrar + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + Canaletas + + + Video + Vídeo + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + Tipo + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + + + + + OK + APROVAÇÃO (OK) + + + + Close + Fim + + + + ChannelFeed + + + Create Channel + Create Channel + + + + Subscribe To Channel + Subscrever à canaleta + + + Reset + Restauração + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChatDialog + + Chat + Bate-papo + + + Send + Emitir + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + Emitir + + + + Cancel + + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + Fazer o amigo + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + Opções + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Cancel + Cancelamento + + + Port: + Porto: + + + Trust Settings + Ajustes da confiança + + + Trust Level + Nível da confiança + + + Trust Their Signature + Confiar em sua assinatura + + + Sign The Certificate + Assinar o certificado + + + + OK + APROVAÇÃO (OK) + + + + Details + Detalhes + + + + Name + + + + + Loc + + + + + Peer Address + Endereço do par + + + + Last Contact + Último contato + + + Peer Details + Detalhes do Peer + + + + Peer Info + + + + + Peer ID + + + + + Version + + + + + RetroShare ID + + + + + Status + + + + + Dynamic DNS + + + + + Addresses list + + + + + None + + + + + Marginal + + + + + Full + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Deny Friend + + + + + Make Friend + Fazer o amigo + + + + Certificate + + + + + + Sign GPG key + + + + + Friend Details + + + + + Local Address + + + + + External Address + + + + + + Port + + + + + Your trust in this peer is: + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + Apply and Close + + + + + + RetroShare + Retroshare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + ConnectDialog + + Peer Details + Detalhes do Peer + + + Make Friend + Fazer o amigo + + + Cancel + Cancelamento + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + + + + + Description + + + + + Type: + Tipo: + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + Retroshare + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + Tipo: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + Retroshare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Nome + + + + Type: + Tipo: + + + + Authenticated Messages + + + + + Cancel + Cancelamento + + + RetroShare + Retroshare + + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Description + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Create + + + + + CreateForumMsg + + + Close + Fim + + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + Retroshare + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + Retroshare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + CryptographyDialog + + RSA Key Size + RSA Key Size + + + Rijndael Block size + Rijndael Block size + + + 128 Bits + 128 Bits + + + 192 Bits + 192 Bits + + + 256 Bits + 256 Bits + + + Rijndael Key Size + Rijndael Key Size + + + Rijndael Mode + Rijndael Mode + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + Rijndael Padding + Rijndael Padding + + + PKCS7 + PKCS7 + + + Zeros + Zeros + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Rijndael Feedback Size + + + Key Size: + Key Size: + + + Block Size: + Block Size: + + + Feedback Size: + Feedback Size: + + + Mode: + Mode: + + + Padding: + Padding: + + + RetroShare + Retroshare + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Detalhes + + + + + General + + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + Tipo: + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + APROVAÇÃO (OK) + + + + Cancel + + + + + Rating + + + + + File Name + Lima - nome + + + + Not Rated + + + + + No Comments + + + + + DirectoriesDialog + + Shared Directories + Diretórios compartilhados + + + Other Directories + Outros diretórios + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Limas entrantes </span></p></body></html> + + + Add Shared Directory +  Adicionar o diretório compartilhado + + + + DirectoriesPage + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + Shared Directories + + + + Edit Share + + + + Incoming files + Limas entrantes + + + + + Browse + + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + Fim + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + APROVAÇÃO (OK) + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + + + + + OK + APROVAÇÃO (OK) + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Amigos</span></p></body></html> + + + + Person + Pessoa + + + + Auto Connect + O automóvel conecta + + + + Trust Level + Nível da confiança + + + + Peer Address + Endereço do par + + + + Last Contact + Último contato + + + + Organisation + Organização + + + + Location + Posição + + + + Country + País + + + + Person Id + ID de pessoa + + + + Auth Code + AUTHenticate o código + + + + # + + + + + Status + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileHashDialog + + Download + Download + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + %1 KB + %1 KB + + + File Name + Lima - nome + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + OK + APROVAÇÃO (OK) + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + Emitir + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + Misc + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + não mostrar + + + + Expand + + + + + + RetroShare + Retroshare + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + + Date + Data + + + + + Start New Thread + + + + New Message + Mensagem nova + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Title + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + Restauração + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + Bate-papo aos amigos + + + + Status + + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + Emitir + + + + Clear Chat History + + + + + + Add Friend + Amigo de Convidar o + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + Posição + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + Conectar ao amigo + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + Excepto o certificado + + + + Certificates (*.pqi) + Certificados (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + Geral + + + Network + Rede + + + Directories + Diretórios + + + Server + Peer + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Server + Peer + + + + Accept + Accept + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Status + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Instalação de Retroshare + + + Load Trusted Certificate (Optional) + A carga confiou no certificado (opcional) + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + Posição + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + + + Select File + Selecionar a lima + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nome:</p></body></html> + + + Generate New Certificate + Gerar o certificado novo + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + Selecionar o amigo confiado + + + + Certificates (*.pqi *.pem) + Certificados (*.pqi *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + GeneralDialog + + Style + Língua + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Escolher o estilo da relação de Retroshare</p></body></html> + + + Language + Língua + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Escolher a língua usada em Retroshare </p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">As mudanças à língua farão exame somente do efeito após ter reiniciado Retroshare!</p></body></html> + + + Style Sheet + Folha do estilo + + + Login + Início de uma sessão (Login) + + + Misc + Misc + + + + GeneralPage + + Keys manager + Fecha à chave o gerente + + + Style + Gerente do chave o do à de Fecha + + + Choose RetroShare's interface style + Escolher o estilo da relação de Retroshare + + + Language + Língua + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">As mudanças à língua farão exame somente do efeito após ter reiniciado RetroShare!</p></body></html> + + + Choose the language used in RetroShare + Escolher a língua usada em Retroshare + + + Login + Início de uma sessão (Login) + + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + Misc + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Recieve: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Emitido: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Bate-papo aos amigos + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + + + + + Description + + + + + Reset + Restauração + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + + + + + Size + + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + Search + Busca + + + + Home + Home + + + + Close + Fim + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + Sobre + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + Restauração + + + + + Copy + + + + + Remove + Remover + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + Emitir + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + InviteDialog + + Done + Feito + + + Cancel + Cancelamento + + + Launch Email + Email convencional do lançamento + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + Download + + + + Expand + + + + + Hide + não mostrar + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + De + + + + Show + Mostra + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + LogDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> + +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +</body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p><ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#cccccc"><p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p><table border="0" width="100%" cellspacing="2" cellpadding="2"><tr><td bgcolor="#aaaaaa"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td><td bgcolor="#cccccc"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table></body></html> + + + + MainWindow + + + Network + Rede + + + + Friends + Bate-papo aos amigos + + + + + Transfers + Transferências + + + + + Messages + Email-Mensagens + + + + + Channels + Canaletas + + + + Blogs + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + + + Options + Opções + + + + Hide + não mostrar + + + + Show + Mostra + + + + RetroShare + Retroshare + + + Invite Friend + Convidar o amigo + + + + MainWindow + + + + + Add Friend + Amigo de Convidar o + + + + Add a Friend Wizard + + + + + Add Share + Adicionar a parte + + + + + Quick Start Wizard + + + + + Search + Busca + + + + Files + Limas + + + Add Shared Directory + Adicionar o diretório compartilhado + + + + Show/Hide + + + + + &Quit + + + + + + + + You have %1 new message + + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Minimize + + + + + Maximize + + + + + Links Cloud + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Unfinished + + + + + Help + Ajuda + + + + About + Sobre + + + + + Forums + + + + + Open Messages + + + + + Applications + + + + Settings + Ajustes + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + Quit + + + + + SMPlayer + + + + + Messenger + + + + + MessageComposer + + + + Compose + Compôr + + + + + Contacts + + + + + Search for Name: + + + + + Reset + Restauração + + + + Send To: + Emitir a: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + Limas recomendadas + + + + File Name + Lima - nome + + + + Size + + + + + Hash + + + + + Send + Emitir + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + Excepto + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + Retroshare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + Misc + Misc + + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + mensagem + + + New Message + Mensagem nova + + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + Fim + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Limas recomendadas</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + Lima - nome + + + + Size + + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + Download + + + + Download all + + + + + Hide + não mostrar + + + + Expand + + + + + File + + + + + Files + Limas + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + Mensagem nova + + + + Compose + Compôr + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + Mensagem nova + + + + Quick View + + + + + Reply to Message + + + + + Remove Message + Remover a mensagem + + + + + Date + Data + + + + + + From + De + + + Size + Tamanho + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Limas recomendadas</span></p></body></html> + + + + Reply + + + + + Reply all + + + + + Foward + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remover a mensagem selecionada </p></body></html> + + + + Delete + + + + + Compose + Compôr + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + Reset + Restauração + + + + Attachments + + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + Email-Inbox + + + + + + + Outbox + Email-Outbox + + + + Draft + Esboço + + + + + Sent + Email-Emitido + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">resposta à mensagem selecionada </p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Mensagem nova</p></body></html> + + + Download All + Download tudo + + + File Name + Lima - nome + + + Sources + Fontes + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + Download + + + + Empty trash + + + + Hide + não mostrar + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + Files + Limas + + + + + + + + Total: + + + + + + Reply to All + + + + + + Subject + + + + + Print + + + + + MessagesPopupDialog + + New Message + Mensagem nova + + + Remove Message + Remover a mensagem + + + Messages + Email-Mensagens + + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Draft + Esboço + + + Sent + Email-Emitido + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Limas recomendadas</span></p></body></html> + + + File Name + Lima - nome + + + Compose + Compôr + + + Remove + Remover + + + + MessengerDirModel + + Rank + Rank + + + + MessengerSharedFiles + + Download + Download + + + + MessengerWindow + + + Expand all + + + + + Collapse all + + + + + Chat + Bate-papo do grupo + + + + Message Friend + + + + + Connect To Friend + Conectar ao amigo + + + + Peer Details + Detalhes do Peer + + + + Recomend this Friend to... + + + + + Export Friend + Export Friend + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + Excepto o certificado + + + + Certificates (*.pqi) + Certificados (*.pqi) + + + Remove Friend + Remover o amigo + + + + Click to Change your Avatar + + + + + Search Friends + + + + + Reset + Restauração + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Sent + Email-Emitido + + + Date + Data + + + + MsgItem + + + Remove Item + + + + + + Expand + + + + + Reply to Message + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + não mostrar + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Mensagens</span></p></body></html> + + + Date + Data + + + Rank + Rank + + + From + De + + + Msg + Mensagem + + + Count + Contagem + + + Size + Tamanho + + + Type + Tipo + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IDSize + + + RsMsgId + RsMsgID + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Texto da mensagem</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Limas recomendadas</span></p></body></html> + + + Delete Channel + Canaleta da supressão + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Mensagens</span></p></body></html> + + + Date + Data + + + Rank + Rank + + + From + De + + + Msg + Mensagem + + + Count + Contagem + + + Size + Tamanho + + + Type + Tipo + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IDSize + + + RsMsgId + RsMsgID + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Texto da mensagem</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Limas recomendadas</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + Certificado da carga + + + Select a pem/pqi File + Selecionar uma lima do PEM/PQI + + + File Not Found + File Not Found + + + %1 does not exist. Would you like to create it? + %1 não existe. Você gosta de criá-lo? + + + Failed to Create File + Não criou a lima + + + Unable to create %1 [%2] + Incapaz de criar %1 [%2] + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + Select Certificate + Selecionar o certificado + + + Certificates (*.pqi *.pem) + Certificados (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Rede:</span></p></body></html> + + + Accept + Accept + + + Trust + Confiança + + + Last Contact + Último contato + + + + + + Name + Nome + + + Peer Address + Endereço do par + + + Organisation + Organização + + + Location + Posição + + + Country + País + + + + + Cert Id + ID do certificado + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Unknown + + + + + yourself + + + + RetroShare + Retroshare + + + + Network + + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + Amigo de Convidar o + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + Opções da velocidade + + + Max Total Data Rate (KB/S): + Sua velocidade máxima do upload (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Velocidade por a pessoa (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Não mostrar ajustes + + + Settings + Ajustes + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Bate-papo aos amigos + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + APROVAÇÃO (OK) + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Remover tudo + + + + Options + Opções + + + + NotifyDialog + + Channels + Canaletas + + + Messages + Email-Mensagens + + + New Message + Mensagem nova + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + Canaletas + + + + Forums + + + + + Chat + + + + + Blogs + + + + + Messages + Email-Mensagens + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + Mensagem nova + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + OptionsDlg + + Cancel + Cancelamento + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + Make Friend + Fazer o amigo + + + Remove Friend + Remover o amigo + + + + Chat + Bate-papo do grupo + + + + Start Chat + + + + Organisation + Organização + + + + Location + Posição + + + Country + País + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Send + Emitir + + + + Cancel + + + + + Peer ID: + + + + + Write Message + + + + + Status: + + + + + Trust: + + + + + Name: + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + não mostrar + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Bate-papo aos amigos + + + + PeersDialog + + Chat + bate-papo + + + Export Friend + Export Friend + + + Remove Friend + Remover o amigo + + + Save Certificate + Excepto o certificado + + + Certificates (*.pqi) + Certificados (*.pqi) + + + Status + Status + + + Person + Pessoa + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Amigos</span></p></body></html> + + + Connect To Friend + Conectar ao amigo + + + Location + Posição + + + Peer Details + Detalhes do Peer + + + RetroShare + Retroshare + + + Send + Emitir + + + Add Friend + Amigo de Convidar o + + + Friends + Bate-papo aos amigos + + + + PeersFeed + + Save Certificate + Excepto o certificado + + + Certificates (*.pqi) + Certificados (*.pqi) + + + Friends + Bate-papo aos amigos + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Remover + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + + Date + Data + + + + + Location + Posição + + + + Size + Tamanho + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + Remover + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + RetroShare + Retroshare + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + Emitir + + + + Close + Fim + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + Retroshare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Directories + Diretórios + + + Error Saving Configuration + Configuração do Saving do erro + + + General + Geral + + + Server + Peer + + + Options + Opções + + + Cancel + Cancelamento + + + OK + APROVAÇÃO (OK) + + + Help + Ajuda + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + Download tudo + + + + RetroShare + Retroshare + + + + Error : cannot get peer details. + + + + + + Name + Nome + + + + Peer ID + + + + + Size + Tamanho + + + + Profile View + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + Name + Nome + + + Date + Data + + + Size + Tamanho + + + + + RetroShare + Retroshare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + Remover + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + + + + + Directories + Diretórios + + + + Server + Peer + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Configuração do Saving do erro + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RemoteDirModel + + Rank + Rank + + + Files + Limas + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Código inválido da língua especificado: + + + + Invalid GUI style specified: + Estilo inválido do GUI especificado: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + Fontes + + + + Results + Resultados + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + Download + + + + Enter a keyword here (at least 3 char long) + + + + Broadcast on Channel + Transmissão na canaleta + + + Recommend to Friends + Recomendar aos amigos + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + Remover + + + + Remove All + Remover tudo + + + + + Folder + + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Formato</p></body></html> + + + + Any + Alguns + + + + Audio + Audio + + + + Video + Vídeo + + + Images + Imagens + + + Programs + Programs + + + Archives + Arquivos + + + Documents + Originais + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Size + Tamanho + + + + Type + Tipo + + + + Archive + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + Lima - nome + + + + File Size + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + Busca + + + + Reset + Restauração + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Search Id + + + + + SendLinkDialog + + Send + Emitir + + + + ServerDialog + + Transfer Rates + Velocidade de transferência + + + Port: + Porto: + + + + ServerPage + + Change + Restart Server + Mudança + Reinício + + + Server Settings + Ajustes do Peer + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Endereço externo:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Endereço local:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Porto:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Download (KB/s) + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + Porto: + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + Misc + Misc + + + behinde Firewall + rás de um guarda-fogo (Firewall) + + + Forwarded External Port + Porto externo enviado (Router) + + + + Transfer Rates + Velocidade de transferência + + + + Settings + + Settings + Ajustes + + + + Options + Opções + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + Cancel + Cancelamento + + + Apply + Aplicar + + + + OK + APROVAÇÃO (OK) + + + + General + Geral + + + Network + Rede + + + + Server + Peer + + + + Directories + Diretórios + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + Friends + Bate-papo aos amigos + + + + OK + APROVAÇÃO (OK) + + + + Cancel + + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + Retroshare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + Remover + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + Fim + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Download + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Limas</span></p></body></html> + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + Restauração + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + Retroshare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + Statistics + + + + Session: + Session: + + + + + Downloaded: + Downloaded: + + + Average Downloadspeed: + Average Downloadspeed: + + + + + Count of Downloads: + Count of Downloads: + + + + + + Overall + Overall + + + + Upload + Upload + + + + + + Session + Session + + + + Uploaded: + Uploaded: + + + Average Uploadspeed: + Average Uploadspeed: + + + + + Count of Uploads: + Count of Uploads: + + + + Uploaded + Uploaded + + + + + + + Connections: + Connections: + + + + + + Peers: + Peers: + + + Misc + Misc + + + + Uptime: + Uptime: + + + Overall: + Overall: + + + + + Uptime + Uptime + + + + Records + Records + + + + Uploadspeed: + Uploadspeed: + + + + Downloadspeed: + Downloadspeed: + + + + + Show Settings + Show Settings + + + + Reset + Restauração + + + + Receive Rate + Receive Rate + + + + Send Rate + Send Rate + + + + Always On Top + Sempre no alto + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Changes the transparency of the Bandwidth Graph + Muda a transparência do gráfico da largura de faixa + + + + Save + Excepto + + + + Cancel + Cancelamento + + + + Hide Settings + Não mostrar ajustes + + + + %1 days + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Download + Download + + + + Time Statistics + + + + + Since: + + + + + Cumulative + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + APROVAÇÃO (OK) + + + + Cancel + + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Tipo + + + + Delete FeedItem + + + + + SubFileItem + + File Name + Lima - nome + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + Download + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + Retroshare + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + A carga do certificado falhou + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Cancelamento + + + + Clear Completed + O espaço livre terminou + + + + + Status + Status + + + + Completed + Terminado + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + Feito + + + + Active + + + + + Outstanding + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + + + + + Name + i.e: file name + Nome + + + + + Size + i.e: file size + Tamanho + + + Progress + i.e: % downloaded + Progresso + + + + Speed + i.e: Download speed + Velocidade + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + Fontes + + + + Core-ID + + + + + Progress + i.e: % uploaded + Progresso + + + + Speed + i.e: upload speed + Velocidade + + + + Transferred + + + + + Hash + + + + + Play + + + + + Pause + + + + + Resume + + + + + Force Check + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Priority (Speed)... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + Queued + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + Retroshare + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Peer + i.e: user name + + + + + Router Statistics + + + + + Router Requests + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Move in Queue... + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + version: + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + Limas + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + Confiança + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + File Name + Lima - nome + + + Type + Tipo + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Download + Download + + + Broadcast on Channel + Transmissão na canaleta + + + Recommend to Friends + Recomendar aos amigos + + + Remove + Remover + + + Remove All + Remover tudo + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Formato</p></body></html> + + + Any + Alguns + + + Audio + Audio + + + Video + Vídeo + + + Type + Tipo + + + Results + Resultados + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + APROVAÇÃO (OK) + + + + Cancel + Cancelamento + + + + Yes + Sim + + + + No + Não + + + + Help + Ajuda + + + + Retry + Nova tentativa + + + + Show Log + Mostrar a história + + + + Show Settings + Mostrar ajustes + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Details + Detalhes + + + OK + APROVAÇÃO (OK) + + + Name + Nome + + + Value + Valor + + + diff --git a/retroshare-gui/src/lang/retroshare_ru.qm b/retroshare-gui/src/lang/retroshare_ru.qm new file mode 100644 index 000000000..d883b314e Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_ru.qm differ diff --git a/retroshare-gui/src/lang/retroshare_ru.ts b/retroshare-gui/src/lang/retroshare_ru.ts new file mode 100644 index 000000000..89156057e --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_ru.ts @@ -0,0 +1,15217 @@ + + + + + + + Arial + Arial + + + + @default + + Arial + Arial + + + + AboutDialog + + + About RetroShare + + + + + About + О программе + + + + close + закрыть + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + + + + + Sorry, can't determine system default command for this file + + + + + + AddFriendDialog + + Cancel + Отмена + + + Done + Готово + + + Load From File + Загрузка из файла + + + RetroShare + Retroshare + + + Certificate Load Failed + Сертификат не загружен + + + Add a new Friend +To add a new Friend, cut and paste their email +invitation into the box below, and click done. + + Добавить новый контакт +Чтобы добавить новый контакт, скопируйте приглашение +в буфер обмена и вставьте сюда. + + + + + AddFriendWizard + + < Back + < Назад + + + Next > + Вперед > + + + Cancel + Отмена + + + I have a .pqi/.pem file received from a Friend + У меня есть файл с расширением .pqi/.pem, полученный от друга + + + I have Key received from a Friend + У меня есть ключ, полученный от друга + + + I want to invite a friend to my RetroShare network + Я хочу пригласить друга в мою сеть RetroShare + + + Browse + Выбор файла + + + Add Friend to my netowork Wizard + Мастер добавления контакта в мою сеть + + + Certificate Load Failed + Ошибка при загрузке сертификата + + + This Wizard helps to Connect to your Friends + Этот мастер помогает Вам подключиться к друзьям + + + Cut and paste the text below into an email. and send it to all your friends! When you press next, RetroShare will attempt to launch a Email client + Скопируйте текст внизу в e-mail, и пошлите его Вашим друзьям. Когда Вы нажмете Далее, RetroShare попробует открыть программу e-mail + + + Invite your Friends to join with RetroShare + Пригласить Ваших друзей соединиться с RetroShare + + + Enter the Key code you got from your friend: + Введите код, полученный от друга: + + + When you press next RetroShare will attempt to connect using the key. + Когда Вы нажмете Далее, RetroShare попытается соединиться с помощью этого ключа. + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + RetroShare: Расширенный поиск + + + + Cancel + Отмена + + + + Search + Поиск + + + + Add a further search criterion. + Добавить дополнительный критерий поиска. + + + + Reset the search criteria. + Сбросить критерии поиска. + + + + Cancels the search. + Отмена поиска. + + + + Perform the advanced search. + Выполните расширенный поиск. + + + + Search Criteria + Критерии + + + + AppearanceDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + Выберите язык, используемый в Retroshare + + + Style + Style + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Выберите стиль интерфейса Retroshare </p></body></html> + + + Style Sheet + Стиль Спецификация + + + + AppearancePage + + + Language + языка + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + Выберите язык, используемый в Retroshare + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Изменения языка вступят в силу только после перезапуска RetroShare!</p></body></html> + + + + Style + Стиль + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Выберите стиль интерфейса Retroshare </p></body></html> + + + + Style Sheet + Стиль Спецификация + + + + ApplicationWindow + + + Hide + Скрыт + + + + Show + Показать + + + Transfers + Передача файлов + + + Messages + E-Mail-Сообщения + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + Statistics (статистика) + + + + + RetroShare + + + + + AttachFileItem + + + Form + + + + File Name + Имя файла + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + Авторизовать / аутентификации + + + Authenticate Friend By Entering Their Code + Авторизовать/ аутентификации друг, введя код + + + OK + OK (нууу) + + + Cancel + Вернуться/Отмена + + + + BandwidthGraph + + + + Show Settings + Показать параметры + + + + Reset + Сбросить + + + + Receive Rate + Получите Оценить + + + + Send Rate + Отправить Оценить + + + + Style + Стиль + + + + Changes the transparency of the Bandwidth Graph + Изменения прозрачности Bandwidth Graph + + + + 100 + 100 + + + + % Opaque + % Непрозрачные + + + + Save + Сохранить + + + + Cancel + Отмена + + + + Since: + С тех пор, как: + + + + Hide Settings + Скрыть настройки + + + + RetroShare Bandwidth Usage + RetroShare использования пропускной способности + + + + Always on Top + Всегда поверх других окон + + + + BgWindow + + Quit + Выход + + + About + О программе + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + Последнее сообщение + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + + + + + Close + закрыть + + + + BlogDialog + + Blogs + Блоги + + + + BlogMsgItem + + + Form + + + + + Remove Item + Удалить элемент + + + Connected + связано + + + + Expand + Развернуть + + + + Subject + Тема + + + + Play Media + + + + + BlogNewItem + + + Remove Item + Удалить элемент + + + + Subscribe to Blog + + + + + Expand + Развернуть + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + Добавить + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + Удалить элемент + + + + + Expand + Развернуть + + + + Comments here + + + + + Hide + Скрыт + + + + CalDialog + + + Name: + Имя: + + + + Remove + Удалить + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Location: + + + + + ... + + + + + Status: + Состояние: + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + Добавить + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + Выбор файла + + + + Select Certificate + Выберите сертификат + + + Certificates (*.pqi *.pem) + Сертификаты (*.pqi /*.pem) + + + + Please choose a filename + + + + + + + + RetroShare + + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + Create a new Broadcast Channel + Создайте новый канал вещания + + + Create A New Broadcast Channel + Создать новый канал вещания + + + Channel Name: + Имя канала: + + + Type: + Тип: + + + Public Channel (Signed) + Общественной Channel (Подпись) + + + Private Channel (Encrypted) + Частные Channel (Шифрование) + + + Cancel Channel + Отмена Channel + + + Create Channel + Создать Channel + + + + ChanMsgDialog + + Compose + Написать + + + Recommended Files + Рекомендуемые Файлы + + + Send To: + Отправить: + + + Send + Отправить + + + Delete Channel + Удалить канал + + + Create Channel MSG + Создать канал сообщение + + + Compose: + Написать: + + + &Quit + Выход + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-файлы (*. HTM *. HTML), все файлы (*) + + + Save as... + Сохранить как ... + + + Print Document + Распечатать документ + + + Add Extra File + Дополнительные файлы + + + Bold + Жирным + + + Underline + Подчеркнуть + + + Italic + Курсив + + + Size + Size + + + Sources + Источники + + + Save + Сохранить + + + Subject: + Тема: + + + File Name + Имя файла + + + Hash + Хэш + + + Reply + Ответ + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + + + + + Play + Играть + + + + Remove Item + Удалить элемент + + + + + Expand + Развернуть + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Скрыт + + + + ChanNewItem + + + Remove Item + Удалить элемент + + + Connected + связано + + + + Unknown Channel + + + + + New Channel + Новый Канал + + + + Updated Channel + + + + + Subscribe to Channel + + + + + Expand + Развернуть + + + + Channel Decscription + + + + + ChannelBrowserDialog + + Channels + Каналы + + + Video + Video + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + Последнее сообщение + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + + + + + OK + + + + + Close + закрыть + + + + ChannelFeed + + + Create Channel + Создать Channel + + + + Subscribe To Channel + Подписка на канал + + + Title + Название + + + Description + Описание + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + Add + Добавить + + + + Display + Отображать + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + Create a new Channel + Создать новый канал + + + New Channel + Новый Канал + + + + ChatDialog + + Chat + Чат + + + Welcome to RetroShare's group chat. + Добро пожаловать в групповой чат RetroShare + + + Live Group Chat: + Чат в группе: + + + Underline + Подчеркнуть + + + Italic + Курсив + + + Bold + Жирным + + + Text Color + Цвет текста + + + Font + Шрифт + + + Send + Отправить + + + Clear Chat History + Очистить историю + + + + ChatMsgItem + + + Remove Item + Удалить элемент + + + + Write a quick Message + + + + + Send Mail + Написать письмо + + + + Write Message + + + + + Send + Отправить + + + + Cancel + + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + Частные чат + + + + Style + + + + + Group chat + Групповой чат + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ComboStatus + + Online + Онлайн + + + Away + Далеко + + + Busy + Занятый + + + + ConclusionPage + + + Make Friend + Объявить другом + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + Trust: + Доверие: + + + + Name: + Имя: + + + Org: + Огр.: + + + + Loc: + Место: + + + Country: + Страна: + + + + Signers + + + + + ConfCertDialog + + + Cancel + Отмена + + + Port: + Порт: + + + Trust Settings + Целевой Настройки + + + Trust Level + Целевой уровень + + + Trust Their Signature + Целевой подпись + + + Sign The Certificate + Знак сертификата + + + + Details + Подробности + + + + Loc + + + + + Peer Address + Адрес узла + + + Name: + Имя: + + + Peer Details + Настройки контакта + + + + Peer Info + Peer информация + + + + Name + Имя + + + + Peer ID + + + + + Last Contact + Посл. контакт + + + + Version + Версия + + + Loc: + Место: + + + + Addresses list + Список адресов + + + + Apply and Close + Применить и закрыть + + + + + RetroShare + + + + + + Error : cannot get peer details. + Ошибка: не могу получить совокупность деталей. + + + + Your key is signed by : + Ваш ключ подписан: + + + + Peer key is signed by : + Peer ключа подписали: + + + + Your trust in this peer is ultimate, it's probably a key you own. + Ваше доверие к этой конечной совокупности, вероятно, это ключевой Вы владеете. + + + + Your trust in this peer is full. + Ваше доверие к этой совокупности является полным. + + + + Your trust in this peer is marginal. + Ваше доверие к этой совокупности является маргинальной. + + + + Your trust in this peer is none. + Ваше доверие к этой совокупности нет. + + + + Your trust in this peer is not set. + Ваше доверие в эту совокупность не установлена. + + + + Peer has authenticated me as a friend and did sign my GPG key + Peer аутентифицирован мне как к другу и сделал знак моего ключа GPG + + + + Peer has not authenticated me as a friend and did not sign my GPG key + Peer не аутентифицированных мне как к другу и не подписал мое ключа GPG + + + + Signature Failure + Ошибка в подписи + + + + Maybe password is wrong + Может быть, неправильный пароль + + + + Trust + Доверие + + + + None + + + + + Marginal + + + + + Full + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Deny Friend + Запретить другу + + + + + Sign GPG key + Войти ключа GPG + + + + Friend Details + + + + + RetroShare ID + + + + + Status + + + + + Local Address + Локальный адрес + + + + External Address + Внешний адрес + + + + Dynamic DNS + + + + + + Port + Порт + + + + Your trust in this peer is: + Ваше доверие к этой совокупности является: + + + None + никакой + + + Marginal + Маргинальные + + + Full + Полный + + + + GPG Key + Ключа GPG + + + + Peer has signed my GPG key + Peer подписал мой ключа GPG + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + Peer ключевые подписан : + + + SignGPG Key + Войти ключа GPG + + + + Make Friend + Подружиться + + + + Certificate + + + + + OK + + + + + ConfirmQuitDialog + + Exit RetroShare + Завершение RetroShare + + + You are about to exit the RetroShare application and therefore stop all transfers. <br><br>Are you sure you want to stop and exit RetroShare? + Вы хотите завершить RetroShare. Все передачи файлов будут остановлены. <br><br>Действительно завершить ? + + + Do not show this message again. + Больше не показывать это сообщение + + + + ConnectDialog + + Peer Details + Свойства узла + + + Make Friend + Объявить другом + + + Cancel + Отмена + + + Trust: + Доверие: + + + Name: + Имя: + + + Org: + Огр.: + + + Loc: + Место: + + + Country: + Страна: + + + signers: + подписи: + + + AUTH CODE: + Код доступа: + + + + ConnectFriendWizard + + + Connect Friend Wizard + Подключите другой мастер + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + + + + + Description + Описание + + + + Type: + Тип: + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + Номер сообщения + + + + Authemticated Messages + Прошедшие проверку сообщений + + + + Anonymous Messages + Анонимные сообщения + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + + + + + Create + Создать + + + + RetroShare + + + + + Please add a Name + Просьба добавить имя + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + Attachments + Вложения + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + Жирным + + + + Underline + Подчеркнуть + + + + Italic + Курсив + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + Add Extra File + Дополнительные файлы + + + + RetroShare + + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + Выход + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-файлы (*. HTM *. HTML), все файлы (*) + + + + Save as... + Сохранить как ... + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + Распечатать документ + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + Создать новый канал + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + Описание + + + + Type: + Тип: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + Номер сообщения + + + + Anonymous Messages + Анонимные сообщения + + + + Authenticated Messages + + + + Authemticated Messages + Прошедшие проверку сообщений + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + Логотип канала + + + + Add Channel Logo + Добавить логотип канала + + + + Cancel + + + + + Create + Создать + + + + RetroShare + + + + + Please add a Name + Просьба добавить имя + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + Вложения + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + Оставьте файл ошибок. + + + + Directory can't be dropped, only files are accepted. + Каталог не может быть удален, принимаются только файлы. + + + + File not found or file name not accepted. + Файл не найден или имя файла, не принимаются. + + + + Add Extra File + Дополнительные файлы + + + + + RetroShare + + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Название форума + + + + Type: + Тип: + + + + Authenticated Messages + + + + + Cancel + Отмена + + + + Please add a Name + Просьба добавить имя + + + + Create new Forum + Создать форум + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Новый форум</span></p></body></html> + + + + Description + Описание + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + Номер сообщения + + + Authemticated Messages + Прошедшие проверку сообщений + + + + Anonymous Messages + Анонимные сообщения + + + Channel Logo + Логотип канала + + + Add Channel Logo + Добавить логотип канала + + + + Create + Создать + + + + CreateForumMsg + + + Close + закрыть + + + + Post Forum Message + Почтовые сообщения форума + + + + Forum + Форум + + + Forum Post Subject + Тема форума + + + + Attach File + + + + Paste retroshare link + Вставить ссылку RetroShare + + + + Forum Post + Форум + + + + Sign Message + Вывеска + + + + Subject + Тема + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + Почтовые сообщения форума + + + Paste retroshare Link + Вставить ссылку RetroShare + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + + + + + Please set a Forum Subject and Forum Message + Пожалуйста, установите форум темы и сообщения форума + + + + Add Extra File + Дополнительные файлы + + + + + Drop file error. + Оставьте файл ошибок. + + + + File not found or file name not accepted. + Файл не найден или имя файла, не принимаются. + + + + Directory can't be dropped, only files are accepted. + Каталог не может быть удален, принимаются только файлы. + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + Ваш Cert копируется в буфер обмена, вставить и отправить его yourfriend по электронной почте или другим способом + + + + Save as... + Сохранить как ... + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare сертификата (*.rsc );; все файлы (*) + + + + Public Key + Открытых ключей + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Скопируйте мой ключ в буфер обмена</p></body></html> + + + + Copy Key + Копировать + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Сохраните ключ в файле</p></body></html> + + + + Save Key + Сохранить раздел + + + + CryptographyDialog + + RSA Key Size + RSA Key Size + + + Rijndael Block size + Rijndael Block size + + + 128 Bits + 128 Bits + + + 192 Bits + 192 Bits + + + 256 Bits + 256 Bits + + + Rijndael Key Size + Rijndael Key Size + + + Rijndael Mode + Rijndael Mode + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + Rijndael Padding + Rijndael Padding + + + PKCS7 + PKCS7 + + + Zeros + Zeros + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Rijndael Feedback Size + + + Key Size: + Key Size: + + + Block Size: + Block Size: + + + Feedback Size: + Feedback Size: + + + Mode: + Mode: + + + Padding: + Padding: + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Подробности + + + + + General + Общий + + + + File Name: + Имя файла: + + + + Hash: + Хэш: + + + + Size: + Размер: + + + + Status: + Состояние: + + + Priority + Приоритет + + + + Priority: + + + + + Type: + Тип: + + + + Transfer + Передача + + + + Sources: + Источники: + + + + Datarate: + Скорость + + + + Completed: + Завершено: + + + + Chunk size: + Размер куска: + + + + + Number of Chunks + Номер кусков + + + + Chunks: + блоки: + + + + Remaining: + Осталось: + + + + Date + часы + + + + Download time: + Время загрузки + + + + + Comments + Комментариев + + + + + retroshare link(s) + RetroShare ссылками + + + + Copy + Копировать + + + + OK + + + + + Cancel + Отмена + + + + Rating + Рейтинг + + + + File Name + Имя файла + + + + Not Rated + Нет оценки + + + + No Comments + Нет комментариев + + + + DirectoriesDialog + + Shared Directories + Разделяемые папки + + + Other Directories + Другие папки + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Входящие файлы</span></p></body></html> + + + Add Shared Directory + Добавить разделяемую папку + + + Add a Share Directory + Добавить Открыть каталог + + + Browse + Выбор файла + + + + DirectoriesPage + + + Incoming Directory + Входящий каталог + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + Partials Direcrtory + частичных каталога + + + + Shared Directories + Общие справочники + + + Automatically share incoming directory (Recommanded) + Автоматическое долю входящих каталога (рекомендовано) + + + + Edit Share + Изменить Share + + + Incoming files + Входящие файлы + + + Add a Share Directory + Добавить Открыть каталог + + + Remove Shared Directory + Удалить общий каталог + + + + + Browse + Выбор файла + + + Add Shared Directory + Добавить разделяемую папку + + + + Set Incoming Directory + Задать входящий каталог + + + + Set Partials Directory + Задать частичных каталога + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + закрыть + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + Добавить логотип канала + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + Тема: + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Друзья</span></p></body></html> + + + + Person + Имя + + + + Auto Connect + Авто Подключите + + + + Trust Level + Trust Level + + + + Peer Address + Адрес узла + + + + Last Contact + Последний контакт + + + + Organisation + Организация + + + + Location + Место + + + + Country + Страна + + + + Person Id + Person ID + + + + Auth Code + Авторизовать/ аутентификации код + + + + # + + + + + Status + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileHashDialog + + Download + Скачать (Download) + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + Осталось + + + + Number of sources + + + + + Chunk strategy + кусок стратегия + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + %1 KB + %1 KB + + + + FlatStyle_RDM + + + Friends Directories + Друзья Каталоги + + + + My Directories + Моя Каталоги + + + + Size + + + + + Age + Возраст + + + + Friend + + + + + Share Type + Тип акции + + + + Directory + Каталог + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + Последнее сообщение + + + + Forum ID + + + + + Forum Description + + + + + Security + Безопасность + + + + Allowed Messages + Номер сообщения + + + + Authemticated Messages + Прошедшие проверку сообщений + + + + Anonymous Messages + Анонимные сообщения + + + + Cancel + + + + + OK + + + + + Apply and Close + Применить и закрыть + + + + ForumMsgItem + + + Remove Item + Удалить элемент + + + + Expand + Развернуть + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + Ответ + + + + Send + Отправить + + + + Signed + Подпись + + + + Forum Post + Форум + + + + Unknown Forum Post + + + + + + + Anonymous + Аноним + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + Удалить элемент + + + Connected + связано + + + + Subscribe to Forum + Подписаться на форум + + + + Expand + Развернуть + + + + Forum Description + + + + + ForumPage + + + Misc + + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + Подписаться на форум + + + + Unsubscribe to Forum + Отказ от подписки на форум + + + + New Forum + Новый форум + + + + Show Forum Details + Показать форума Подробности + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + Ответ + + + + Reply to Author + Ответить автору + + + + Expand all + Развернуть все + + + + Collapse all + Свернуть все + + + + AUTHD + + + + Popularity: + Популярность: + + + + Your Forums + Ваши форумы + + + + Subscribed Forums + Подписка Форум + + + + Popular Forums + Популярные форумы + + + + Other Forums + Другие форумы + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + Скрыт + + + + Expand + Развернуть + + + Anonymous + Аноним + + + signed + подписано + + + none + никакой + + + + + RetroShare + + + + + No Forum Selected! + Нет Форума Закладки! + + + + You cant reply a Anonymous Author + Вы наклоняю ответ анонимного автора + + + File Request Confirmation + Введите запрос файла + + + The file has been added to your download list. + Файл был добавлен в корзину. + + + File Request canceled + Запрос файла отменена + + + The file has not been added to your download list, because you already have it. + Файл не был добавлен в ваш список загрузки, потому что вы уже получили его. + + + File Request Error + Запрос файла ошибке + + + The file link is malformed. + Неверный ссылки на файл. + + + + + Date + часы + + + + + Start New Thread + Начать новое обсуждение + + + New Message + Новое сообщение + + + Add + Добавить + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start new Thread for Selected Forum</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Начать новое обсуждение в форуме Закладки</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reply Message</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ответ сообщение</p></body></html> + + + RetroShare Forums + RetroShare форумы + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Форум:</p></body></html> + + + + Last Post + Последнее сообщение + + + + Threaded View + + + + + Flat View + + + + + + Title + Название + + + + + Author + Автор + + + + Signed + Подпись + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">тема:</span></p></body></html> + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + + + + + Content + + + + + Create Forum + Создать форум + + + + Print + Распечатать + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Форум</span></p></body></html> + + + + Start new Thread for Selected Forum + + + + + Display + Отображать + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + Предварительный просмотр + + + + ForumsFillThread + + + + Anonymous + Аноним + + + + + signed + подписано + + + + + none + никакой + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Друзья</span></p></body></html> + + + + Add + Добавить + + + + Display + Отображать + + + + Friends + Друзья + + + + Status + + + + + Add or Change your Avatar + Добавить или изменить Avatar + + + + Edit Personal message + Править Личные сообщения + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + Жирным + + + + Underline + Подчеркнуть + + + + Italic + Курсив + + + + Font + Шрифт + + + + Text Color + Цвет текста + + + + Attach File + + + + + Send + Отправить + + + + Clear Chat History + Очистить историю + + + + + Add Friend + Добавить друга + + + + Create new Profile + Создание нового профиля + + + + + Create new Forum + Создать форум + + + + F + + + + + + Create new Channel + Создать новый канал + + + + C + + + + + Add your Avatar Picture + Добавить Аватар Фото + + + + A + + + + + Set your Personal Message + Задать Ваше личное сообщение + + + + Edit your status Message + Изменить свой статус + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + Скрыть знакомых + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + Сортировать убыванию + + + + + Sort Ascending Order + Сортировка по возрастанию заказа + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + Профиль + + + + News Feed + Новости кормить + + + + Welcome to RetroShare's group chat. + Добро пожаловать в групповой чат RetroShare + + + + me + меня + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + Сообщение другу + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + Подключиться к другу + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + Удалить друга Местоположение + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + Развернуть все + + + + Collapse all + Свернуть все + + + + location + + + + + + Available + Доступный + + + + Save Certificate + Сохранить сертификат + + + + Certificates (*.pqi) + Сертификаты (*. pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + Дополнительные файлы + + + + + Drop file error. + Оставьте файл ошибок. + + + + Directory can't be dropped, only files are accepted. + Каталог не может быть удален, принимаются только файлы. + + + + File not found or file name not accepted. + Файл не найден или имя файла, не принимаются. + + + + Save as... + Сохранить как ... + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + Общий + + + Network + Network + + + Directories + Справочники + + + Server + Peer + + + %1 + %1 + + + File assotiations + Файл assoziation + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Accept + Принять + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + + + + + Status + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + Удалить + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Retroshare настройки + + + Load Trusted Certificate (Optional) + Загрузка доверенный сертификат (опционально) + + + + + + Create new Profile + Создание нового профиля + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Другу</span></p></body></html> + + + Select File + выберите Файл + + + Country: + Страна: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Имя:</p></body></html> + + + Generate New Certificate + Создать новый сертификат + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + Выбор верного друга + + + + Certificates (*.pqi *.pem) + Сертификаты (*.pqi /*.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + Name: + Имя: + + + + GeneralDialog + + Style + Style + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Выберите стиль интерфейса Retroshare </p></body></html> + + + Language + языка / Language + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + Выберите язык, используемый в Retroshare + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting Retroshare!</p></body></html> + + + Style Sheet + Стиль Спецификация + + + Login + Login (логин) + + + Misc + Misc/Разное + + + + GeneralMsgDialog + + Forum + Форум + + + Add Extra File + Дополнительные файлы + + + Attachments + Вложения + + + + GeneralPage + + Keys manager + Клавиши менеджер + + + Style + Style + + + Choose RetroShare's interface style + Выберите стиль интерфейса Retroshare + + + Language + языка + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Изменения языка вступят в силу только после перезапуска Retroshare!</p></body></html> + + + Choose the language used in RetroShare + Выберите язык, используемый в Retroshare + + + Login + Login (логин) + + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + Misc/Разное + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Recv: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Отправлено: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Друзья + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + Название + + + + Description + Описание + + + + Reset + + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + + + + + Path + + + + + Extension + + + + + Hash + Хэш + + + + Date + часы + + + + Size + + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + Search + Поиск + + + + Home + Home + + + + Close + закрыть + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + О программе + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + Авторы + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + Thanks to + Благодарности + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Translation + Перевод + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + License Agreement + Лицензионное соглашение + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + + + + + + Copy + Копировать + + + + Remove + Удалить + + + + Mark all + + + + + Delete + Удалить + + + + Clear history + + + + + Send + Отправить + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &You get a certificate file from your friend + + + + + &Make friend with selected friends of my friends + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + Add a new Friend + Добавить нового друга + + + This wizard will help you to connect your friend to RetroShare network. There are two possible ways to do this: + Этот мастер поможет вам подключить друга к сети RetroShare. Есть два возможных пути для этого: + + + + &Enter the certificate manually + &Введите сертификат вручную + + + &Use *.pqi files with certificates + &используйте *.pqi файлы с сертификатами + + + + InviteDialog + + Done + Готово + + + Cancel + Отмена + + + Launch Email + Открыть email + + + Invite a Friend + Пригласить друга + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt;"><span style=" font-size:16pt;">Invite a Friend</span><br /><br /><span style=" font-size:10pt;">To Invite your friends to join you with Retroshare: </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:10pt;">Cut and paste the text below into an email.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:10pt;">and send it to all your friends!</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt;"><span style=" font-size:16pt;">Пригласить друга</span><br /><br /><span style=" font-size:10pt;">Чтобы пригласить кого-либо в Вашу сеть RetroShare: </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:10pt;">Скопируйте текст внизу в письмо электронной почты</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:10pt;">и отправьте его Вашим друзьям!</p></body></html> + + + Please Choose Directory to Save Certificate + Выберите папку для сохранения сертификата + + + Save Cert To File + Сохранить сертификат в файл + + + + LinksDialog + + + Share Link Anonymously + Отправить ссылку анонимно + + + + Vote on Link + Голосовать на ссылку + + + + Download + Скачать + + + + Expand + Развернуть + + + + Hide + Скрыт + + + + File Request Confirmation + Введите запрос файла + + + + The file has been added to your download list. + Файл был добавлен в корзину. + + + + File Request canceled + Запрос файла отменена + + + + The file has not been added to your download list, because you already have it. + Файл не был добавлен в ваш список загрузки, потому что вы уже получили его. + + + + File Request Error + Запрос файла ошибке + + + + The file link is malformed. + Неверный ссылки на файл. + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Облако ссылок</span></p></body></html> + + + + Score + Оценка + + + + Peer / Link + Кто / ссылка + + + + From + разослан + + + + Show + Показать + + + + Title / Comment + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + MainWindow + + + Network + Сеть + + + + Friends + Друзья + + + + + Transfers + Передача + + + + + Messages + Сообщения + + + + + Channels + Каналы + + + + Blogs + Блоги + + + You has a new message + Вы есть новые сообщения + + + + Internal Error + + + + + + Options + Опции + + + + Hide + Скрыт + + + + Show + Показать + + + + RetroShare + Retroshare + + + Invite Friend + Пригласить друга + + + + MainWindow + + + + + Add Friend + Добавить друга + + + + Add a Friend Wizard + Добавить друга мастера + + + + Add Share + Добавить разделяемый каталог + + + + + Quick Start Wizard + Master bystr + + + + Search + Поиск + + + + Files + Файлы + + + Add Shared Directory + Добавить разделяемую директорию + + + + Messenger + Мессенджер + + + + Show/Hide + Показать / Скрыть + + + + &Quit + &Выход + + + + + + + You have %1 new message + + + + + Bandwidth Graph + пропускная способность графа + + + + Open Messenger + Открыто Мессенджер + + + + Minimize + Минимизировать + + + + Maximize + Развернуть + + + + Links Cloud + Облако ссылок + + + + Unfinished + Еще не готово + + + Down: 0.0 | Up: 0.0 + Скачка: 0.0 | Закачка: 0.0 + + + + SMPlayer + SMPlayer + + + + Help + Помощь + + + + About + О программе + + + News Feed + Новости кормить + + + + + Forums + Форум + + + + RetroShare %1 a secure decentralised communication platform + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Open Messages + Открыто Сообщений + + + + Applications + Применения + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + Неверный ссылки на файл. + + + Online + Онлайн + + + Busy + Занятый + + + Away + Далеко + + + Settings + Настройки + + + + Plugins + Плагины + + + + Really quit ? + Не ушел? + + + + Do you really want to exit RetroShare ? + Вы действительно хотите выйти RetroShare? + + + + Quit + Выход + + + + MessageComposer + + + + Compose + Написать + + + + + Contacts + + + + + Search for Name: + + + + + Reset + + + + + Send To: + Отправить: + + + + Subject: + Тема: + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + Жирным + + + + Underline + Подчеркнуть + + + + Italic + Курсив + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + Рекомендуемые Файлы + + + + File Name + Имя файла + + + + Size + + + + Sources + Источники + + + + Hash + Хэш + + + + Send + Отправить + + + + Send this message now + + + + + Reply + Ответ + + + + Toggle Contacts View + + + + + Save + Сохранить + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + Compose: + Написать: + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + Неизвестно + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-файлы (*. HTM *. HTML), все файлы (*) + + + + Save as... + Сохранить как ... + + + + Print Document + Распечатать документ + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + Дополнительные файлы + + + + + Drop file error. + Оставьте файл ошибок. + + + + Directory can't be dropped, only files are accepted. + Каталог не может быть удален, принимаются только файлы. + + + + File not found or file name not accepted. + Файл не найден или имя файла, не принимаются. + + + + MessagePage + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + Добавить + + + + Edit + + + + + Delete + Удалить + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + новости / Текст сообщения + + + New Message + Новое сообщение + + + + Subject + Тема + + + + <b>1 new Message from</b> + + + + + Close + закрыть + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + + + + + Download all Recommended Files + + + + + Subject: + Тема: + + + + From: + от: + + + + To: + Кому: + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + Имя файла + + + + Size + + + + + Hash + Хэш + + + + Print + Распечатать + + + + Print Preview + Предварительный просмотр + + + + No subject + + + + + Download + + + + + Download all + + + + + Hide + Скрыт + + + + Expand + Развернуть + + + + File + + + + + Files + Файлы + + + + Print Document + Распечатать документ + + + + Save as... + Сохранить как ... + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-файлы (*. HTM *. HTML), все файлы (*) + + + + MessageWindow + + + New Message + Новое сообщение + + + + Compose + Написать + + + + Reply to selected message + + + + + Reply + Ответ + + + + Reply all to selected message + + + + + Reply all + Ответить всем + + + + Forward selected message + + + + + Foward + Вперед + + + + Remove selected message + + + + + Delete + Удалить + + + + Print selected message + + + + + + Print + Распечатать + + + + Display + Отображать + + + + + + Tags + + + + + Print Preview + Предварительный просмотр + + + + + Buttons Icon Only + Кнопки только значок + + + + Buttons Text Beside Icon + Кнопки Текст Кроме Icon + + + + Buttons with Text + Кнопки с текстом + + + + Buttons Text Under Icon + Кнопки текст под иконы + + + + Set Text Under Icon + Установить текст под иконы + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + Новое сообщение + + + + Quick View + + + + + Reply to Message + Ответить на сообщение + + + + Remove Message + Удалить сообщение + + + + + Date + часы + + + + + + From + разослан + + + Size + Size + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Рекомендуем Файлы</span></p></body></html> + + + + Reply + Ответ + + + + Reply all + Ответить всем + + + + Foward + Вперед + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">удалить выбранные сообщения</p></body></html> + + + + Delete + Удалить + + + + Compose + Написать + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + Отображать + + + + Reset + Сбросить + + + + Attachments + Вложения + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + Входящие + + + + + + + Outbox + Исходящие + + + + Draft + Дизайн неотправленных (draft) + + + + + Sent + Отправлено + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + Печать ... + + + + Print Preview + Предварительный просмотр + + + + + Buttons Icon Only + Кнопки только значок + + + + Buttons Text Beside Icon + Кнопки Текст Кроме Icon + + + + Buttons with Text + Кнопки с текстом + + + + Buttons Text Under Icon + Кнопки текст под иконы + + + + Set Text Under Icon + Установить текст под иконы + + + + Save As... + Сохранить как ... + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Отвечая на выбранные сообщения</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Новое сообщение</p></body></html> + + + Download All + Скачать Все + + + Print Document + Распечатать документ + + + Sources + Источники + + + + Forward selected Message + Переслать выбранное сообщение + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + Удалить сообщение + + + + Forward Message + Переслать сообщение + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + Скачать + + + + Empty trash + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + Click to sort by to + + + + Files + Файлы + + + Compose: + Написать: + + + Hide + Скрыт + + + Expand + Развернуть + + + + + + Drafts + + + + + To + + + + Anonymous + Аноним + + + File Request Confirmation + Введите запрос файла + + + The file has been added to your download list. + Файл был добавлен в корзину. + + + File Request canceled + Запрос файла отменена + + + The file has not been added to your download list, because you already have it. + Файл не был добавлен в ваш список загрузки, потому что вы уже получили его. + + + File Request Error + Запрос файла ошибке + + + The file link is malformed. + Неверный ссылки на файл. + + + Save as... + Сохранить как ... + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-файлы (*. HTM *. HTML), все файлы (*) + + + + + + + + Total: + + + + + + Reply to All + Ответить всем + + + + + Subject + Тема + + + Subject: + Тема: + + + From: + от: + + + Date: + Свидание: + + + To: + Кому: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Скачать все рекомендованные Файлы</p></body></html> + + + File Name + Имя файла + + + Hash + Хэш + + + + Print + Распечатать + + + + MessagesPopupDialog + + New Message + Новое сообщение + + + Reply to Message + Ответить на сообщение + + + Remove Message + Удалить сообщение + + + Messages + E-Mail-Сообщения + + + Inbox + Email-Входящие + + + Outbox + Email-Исходящие + + + Draft + Дизайн неотправленных (draft) + + + Sent + Email-Отправлено + + + From + разослан + + + Date + часы + + + Sources + Источники + + + Compose + Написать + + + Remove + Удалить + + + Hash + Хэш + + + Reply + Ответ + + + Print + Распечатать + + + PrintPreview + Предварительный просмотр + + + + MessengerDirModel + + FILE + ФАЙЛОВ + + + Friends Directories + Друзья Каталоги + + + My Directories + Моя Каталоги + + + Rank + Ранг + + + Age + Возраст + + + + MessengerWindow + + + Expand all + Развернуть все + + + + Collapse all + Свернуть все + + + + Chat + Группы Чат + + + + Message Friend + Сообщение другу + + + + Connect To Friend + Подключиться к другу + + + + Peer Details + Настройки контакта + + + + Recomend this Friend to... + + + + + Paste RetroShare Link + + + + Paste retroshare Link + Вставить ссылку RetroShare + + + + Export Friend + Экспорт контакта + + + + Deny Friend + Запретить другу + + + + Remove Friend Location + Удалить друга Местоположение + + + + <strong>GPG Key</strong> + <strong>GPG Ключ</strong> + + + + + + + location + + + + + <strong>RetroShare instance</strong> + <strong>RetroShare Например</strong> + + + location : + Место: + + + Peer Online + Peer Интернет + + + Available + Доступный + + + Offline + Оффлайн + + + + Save Certificate + Сохранить сертификат + + + + Certificates (*.pqi) + Сертификаты (*. pqi) + + + Friend Not Online + Друг не Онлайн + + + Your Friend is offline +Do you want to send them a Message instead + Ваш друг форума +Вы хотите, чтобы отправить им сообщение, а не + + + View + Просмотр + + + Remove Friend + Удалить контакт + + + + Click to Change your Avatar + Нажмите кнопку изменить Avatar + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Change your Status and your display</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">picture here.</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Изменить статус и ваш дисплей</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">фотографии здесь.</p></body></html> + + + Online + Онлайн + + + Busy + Занятый + + + Change your Personal Status here... + Изменить личную статус здесь ... + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Search Friends + + + + + Reset + + + + + + Sort Descending Order + Сортировать убыванию + + + + + Sort Ascending Order + Сортировка по возрастанию заказа + + + + Set root is Decorated + Оформлен Задать корневую + + + + Set Root Decorated + Установить корневой Награжден + + + + Sort by State + + + + Set Root is not Decorated + Установить корневой не украшено + + + + Hide Offline Friends + Скрыть знакомых + + + Away + Далеко + + + Apear Offline + Появляться, Оффлайн + + + + Share Files for your Friends + Общие файлы для Ваших друзей + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Add a Friend</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Добавить друга</p></body></html> + + + + MsgFeed + + Inbox + Email-Входящие + + + Outbox + Email-Исходящие + + + Sent + Email-Отправлено + + + Date + часы + + + All + Все + + + Subject + Тема + + + + MsgItem + + + Reply to Message + Ответить на сообщение + + + + Remove Item + Удалить элемент + + + Connected + связано + + + + + Expand + Развернуть + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Скрыт + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Сообщения</span></p></body></html> + + + Date + часы + + + Rank + Ранг + + + From + разослан + + + Size + Size + + + Type + Type + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgID/ новости-Идентификация + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Текст сообщения</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Рекомендуемые Файлы</span></p></body></html> + + + Delete Channel + Удалить канал + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Сообщения</span></p></body></html> + + + Date + часы + + + Rank + Ранг + + + From + разослан + + + Size + Size + + + Type + Type + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgID/ новости-Идентификация + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Текст сообщения</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Рекомендуемые Файлы</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + Подключение к Интернету + + + + No internet connection + Отсутствует соединение с интернетом + + + + No local network + Нет локальной сети + + + + OK | RetroShare Server + ОК | RetroShare Server + + + + NetworkDialog + + Load Certificate + Загрузить сертификат + + + Select a pem/pqi File + Выберите PEM / PQI Файл + + + File Not Found + Файл не найден + + + %1 does not exist. Would you like to create it? + %1 нет. Хотите создать его? + + + Failed to Create File + Не удалось создать файл + + + Unable to create %1 [%2] + Не удается создать %1 [%2] + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + Аутентифицирован мне + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + аутентифицирован вас. +Щелкните правой кнопкой мыши и выберите "Сделать другом" чтобы иметь возможность подключиться. + + + Select Certificate + Выберите сертификат + + + Certificates (*.pqi *.pem) + Сертификаты (*.pqi /*.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + + + Accept + Доступ + + + Trust + Доверие + + + Last Contact + Посл. контакт + + + + + + Name + Имя + + + Peer Address + Адрес узла + + + Organisation + Организация + + + Location + Место + + + Country + Страна + + + + + Cert Id + Серт ID + + + RetroShare %1 started. + e.g: RetroShare v0.x started. + RetroShare %1 запущен. + + + Welcome to RetroShare. + Добро пожаловать в RetroShare + + + Make Friend / Peer Details + Объявить другом / настройки контакта + + + Deny + Запрещен + + + + Network + Сеть + + + + + Did peer authenticated me + Разве совокупность Authenticated мне + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + Show keys that are not validated by the GPG web of trust + Показать ключей, которые не проверяются на веб GPG доверия + + + Log + Протокол + + + + Network View + Карта сети + + + + Clear + Очистить + + + Trust matrix + Целевые матрица + + + View + Просмотр + + + RetroShare %1 started. + RetroShare %1 запущен. + + + Menu + Меню + + + + Deny friend + Запретить другу + + + Accept friend + Согласен другу + + + + Make friend + Сделать другом + + + + Delete certificate + Удалить сертификат + + + + Export my Cert + + + + + Peer details... + Экспертный подробнее ... + + + Trusted + Доверенные + + + Denied + Отвергнутые + + + Is trusting me + Является ли доверять мне + + + + Unknown + Неизвестно + + + Never seen + Никогда не видел + + + + Authentication matrix + + + + + Copy RetroShare Link + + + + + yourself + + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + Search Network + + + + + Clear Filter + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + External ip address finder + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + Добавить друга + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + Скорость Опции + + + Max Total Data Rate (KB/S): + Максимальная скорость загрузки (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Скорость на личности (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Скрыть настройки + + + Show Settings + Показать параметры + + + Settings + Настройки + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Друзья + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + Имя: + + + + Choose color + + + + + OK + + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + + + + + Options + + + + + NotifyDialog + + Channels + Каналы + + + Messages + E-Mail-Сообщения + + + New Message + Новое сообщение + + + + NotifyPage + + + News Feed + Новости кормить + + + + Peers + + + + + Channels + Каналы + + + + Forums + Форум + + + + Chat + Чат + + + + Blogs + Блоги + + + + Messages + E-Mail-Сообщения + + + Downloads + Загрузки + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + Форум + + + + + Download completed + + + + + Combined icon + + + + + Toasters + Тостеры + + + + Friend Connect + + + + + New Message + Новое сообщение + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + Частные чат + + + + Open Window for new chat + + + + Open Window for new Peer Chat + Открыто новое окно для чата Peer + + + Reopen if closed by user: + Reopen если она закрыта пользователем: + + + + Grab Focus when chat arrives + Grab фокус, когда приходит чате + + + + Use a single tabbed window + + + + + Group chat + Групповой чат + + + + Display systray message + Дисплей Systray сообщения + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + GPG ключевую фразу + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + Please enter the password to unlock the following GPG key: + + Пожалуйста, введите пароль для разблокировки следующие ключевые GPG: + + + + OnlineToaster + + Peer Online + Peer Интернет + + + + Friend Online + + + + + OptionsDlg + + Cancel + Вернуться/Отмена + + + + PeerDefs + + Anonymous + Аноним + + + + + Unknown + Неизвестно + + + + PeerItem + + Make Friend + Объявить другом + + + Remove Friend + Удалить контакт + + + + Chat + Чат + + + + Start Chat + + + + + Send + Отправить + + + + Cancel + + + + + Name: + Имя: + + + Organisation + Организация + + + + Location + Местонахождение + + + Country + Страна + + + + Remove Item + Удалить элемент + + + Connected + связано + + + + + Expand + Развернуть + + + + Write a quick Message + + + + + Peer ID: + + + + + Write Message + + + + + Status: + Состояние: + + + + Trust: + Доверие: + + + Good + хороший: + + + Send Mail + Написать письмо + + + + IP Address + IP-адрес + + + + Connection Method + Метод подключения + + + Last Contact: + Последний контакт: + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + совокупность + + + + + + + + + + + + Unknown Peer + + + + + Hide + Скрыт + + + + Quick Message + + + + + PeerStatus + + Online: 0 |Friends: 0|Network: 0 + Oнлайн: 0 |Друзей: 0|Сетей: 0 + + + Online: 0 | Friends: 0 | Network: 0 + Oнлайн: 0 | Друзей: 0 | Сетей: 0 + + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Друзья + + + Online + Онлайн + + + <span style="color:#000000"><strong>Friends:</strong></span> + <span style="color:#000000"><strong>Друзей:</strong></span> + + + <span style="color:#0000FF"><strong>Online:</strong></span> + <span style="color:#0000FF"><strong>Oнлайн:</strong></span> + + + Online: + Oнлайн: + + + Friends: + Друзей: + + + Network: + Сетей: + + + + PeersDialog + + Chat + Чат + + + Export Friend + Экспорт контакта + + + Remove Friend + Удалить контакт + + + Save Certificate + Сохранить сертификат + + + Certificates (*.pqi) + Сертификаты (*. pqi) + + + Status + Состояние + + + Person + Имя + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Друзья</span></p></body></html> + + + Connect To Friend + Подключиться к другу + + + Welcome to RetroShare's group chat. + Добро пожаловать в групповой чат RetroShare + + + Profile + Профиль + + + Paste retroshare Link + Вставить ссылку RetroShare + + + Expand all + Развернуть все + + + Collapse all + Свернуть все + + + Message Friend + Сообщение другу + + + Peer Details + Настройки контакта + + + Deny Friend + Запрет другу + + + Remove Friend Location + Удалить друга Местоположение + + + <strong>GPG Key</strong> + <strong>GPG Ключ</strong> + + + <strong>RetroShare instance</strong> + <strong>RetroShare Например</strong> + + + location : + Место: + + + Online + Онлайн + + + Peer Online + Peer Интернет + + + Away + Далеко + + + Busy + Занятый + + + Available + Доступный + + + Offline + Оффлайн + + + Friend Not Online + Друг не Онлайн + + + Your Friend is offline +Do you want to send them a Message instead + Ваш друг форума +Вы хотите, чтобы отправить им сообщение, а не + + + Create a new Channel + Создать новый канал + + + New Channel + Новый Канал + + + Add Extra File + Дополнительные файлы + + + File Request Confirmation + Введите запрос файла + + + The file has been added to your download list. + Файл был добавлен в корзину. + + + File Request canceled + Запрос файла отменена + + + The file has not been added to your download list, because you already have it. + Файл не был добавлен в ваш список загрузки, потому что вы уже получили его. + + + File Request Error + Запрос файла ошибке + + + The file link is malformed. + Неверный ссылки на файл. + + + Drop file error. + Оставьте файл ошибок. + + + File not found or file name not accepted. + Файл не найден или имя файла, не принимаются. + + + Directory can't be dropped, only files are accepted. + Каталог не может быть удален, принимаются только файлы. + + + News Feed + Новости кормить + + + Save as... + Сохранить как ... + + + me + меня + + + Live Group Chat: + Чат в группе: + + + Italic + Курсив + + + Underline + Подчеркнуть + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Друзья</span></p></body></html> + + + Add + Добавить + + + hide unconnected + прятать связанным + + + Add or Change your Avatar + Добавить или изменить Avatar + + + Edit Personal message + Править Личные сообщения + + + Live Chat + Live чат + + + Bold + Жирным + + + Create New Forum + Создать форум + + + Create new Forum + Создать форум + + + Create New Channel + Создать новый канал + + + Display + Отображать + + + Create new Channel + Создать новый канал + + + Add your Avatar Picture + Добавить Аватар Фото + + + Set your Personal Message + Задать Ваше личное сообщение + + + Edit your status Message + Изменить свой статус + + + Sort Descending Order + Сортировать убыванию + + + Sort Ascending Order + Сортировка по возрастанию заказа + + + Disable Emoticons + Отключить смайлики + + + Hide Offline Friends + Скрыть знакомых + + + Text Color + Цвет текста + + + Add Friend + Добавить друга + + + Create new Profile + Создание нового профиля + + + Font + Шрифт + + + Friends + Друзья + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">set Text Color</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">установить цвет текста</span></p></body></html> + + + Send + Отправить + + + Clear Chat History + Очистить историю + + + Profile View + Посмотреть профиль + + + + PeersFeed + + Save Certificate + Сохранить сертификат + + + Certificates (*.pqi) + Сертификаты (*. pqi) + + + Friends + Друзья + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Удалить + + + + Excellent + + + + + Good + хороший: + + + + Average + Среднее + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + Рейтинг + + + + + Date + часы + + + + + Location + Местонахождение + + + + Size + Size + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + совокупность + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + Описание + + + + PhotoShow + + + Date: + Свидание: + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + Пауза + + + + Forward + + + + + PluginFrame + + + Remove + Удалить + + + + PluginManagerWidget + + + Install New Plugin... + Установить новый плагин ... + + + + Open Plugin to install + Открыть плагин для установки + + + + Plugins (*.so *.dll) + Плагины (*. so *. dll) + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + Paste retroshare Link + Вставить ссылку RetroShare + + + Friend Not Online + Друг не Онлайн + + + + Your Friend is offline +Do you want to send them a Message instead + Ваш друг форума +Вы хотите, чтобы отправить им сообщение, а не + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + Скрыть Аватара + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + Показать Аватара + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + Сохранить как ... + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + + Bold + Жирным + + + + + Underline + Подчеркнуть + + + + + Italic + Курсив + + + + Font + Шрифт + + + + Text Color + Цвет текста + + + + Clear Chat History + Очистить историю + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Send + Отправить + + + RetroShare - Encrypted Chat + RetroShare - Кодированные Чат + + + + Close + закрыть + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Attach a Picture + + + + + Strike + + + + + Disable Emoticons + Отключить смайлики + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + Дополнительные файлы + + + File Request Confirmation + Введите запрос файла + + + The file has been added to your download list. + Файл был добавлен в корзину. + + + File Request canceled + Запрос файла отменена + + + File Request Error + Запрос файла ошибке + + + The file link is malformed. + Неверный ссылки на файл. + + + + + Drop file error. + Оставьте файл ошибок. + + + + File not found or file name not accepted. + Файл не найден или имя файла, не принимаются. + + + + Directory can't be dropped, only files are accepted. + Каталог не может быть удален, принимаются только файлы. + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Directories + Папки + + + Error Saving Configuration + Ошибка при сохранении конфигурации + + + General + Общие настройки + + + Server + Настройки сервера + + + Options + Опции + + + Cancel + Отмена + + + OK + Готово + + + Appearance + Внешний вид + + + Notify + Уведомить + + + Help + Помощь + + + File assotiations + Файл assoziation + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + Распечатать + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + Профиль + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + Загрузить все (Download All) + + + + RetroShare + + + + + Error : cannot get peer details. + Ошибка: не могу получить совокупность деталей. + + + + + Name + Name/сетевой карты + + + + Peer ID + + + + + Size + Size + + + + Profile View + Посмотреть профиль + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + Хэш + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + Править Личные сообщения + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Общественной информации</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Общественной информации</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Имя:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Местонахождение:</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Другая информация</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Количество друзей:</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Версии</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Мой адрес</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Местный адрес:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Внешний адрес:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + Addresses list + Список адресов + + + + QObject + + Name + Name/сетевой карты + + + Date + часы + + + Size + Size + + + Hash + Хэш + + + + + RetroShare + + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + Войти провал + + + + Maybe password is wrong + Может быть, неправильный пароль + + + + File Request Confirmation + Введите запрос файла + + + + The file has been added to your download list. + Файл был добавлен в корзину. + + + + + File Request canceled + Запрос файла отменена + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + Файл не был добавлен в ваш список загрузки, потому что вы уже получили его. + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + Запрос файла ошибке + + + + The file link is malformed. + Неверный ссылки на файл. + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + Запретить другу + + + + Make friend + Сделать другом + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + Мастер быстрого запуска + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Choos which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Добро пожаловать на RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Это быстрого запуска мастера могут помочь вам настроить ваши RetorShare в несколько простых шагов.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Если вы более продвинутый пользователь, вы можете получить полный спектр возможностей RetroShare's через панель инструментов. Нажмите кнопку Выход, чтобы закрыть мастер в любое время.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Этот мастер поможет Вам:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> RetroShare Расскажите о вашем интернет-соединения.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Выберите, какие файлы вы разделяете..</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> Начать использование RetroShare.</span></p></body></html + + + + + + Next > + Вперед > + + + + + + + Exit + Выйти + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + Для наилучшей производительности RetroShare необходимо знать немного о Вашем подключении к Интернету. + + + + Choose your upload speed limit: + Выберите Добавить предел скорости: + + + + + KB/s + + + + + Choose your download speed limit: + Выбери скачать предел скорости: + + + + Connection : + Соединение: + + + + Automatic (UPnP) + Автоматический (UPnP) + + + + Firewalled + Файрвол + + + + Manually forwarded port + Переадресованные руководство порта + + + Dicovery : + открытие: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + Discovery : + + + + Share Ip and information with your friend (Disc On) + Доля Ип и информацию с вашего друга (диска) + + + Don't share any information (Disc Off) + Не сообщайте любую информацию (Disc Off) + + + + Dynamic DNS: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + + < Back + < Назад + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Это список общих папок. Вы можете добавить или удалить папки с помощью кнопки на левой. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Когда вы добавляете новую папку, являются общими первоначально все файлы в этой папке.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Вы можете отдельно долю установка флагов для каждого разделяемого каталога:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Просматриваться </span><span style=" font-family:'Sans'; font-size:8pt;">: просмотр файлов с вашего прямого друзей.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">широкая сеть</span><span style=" font-family:'Sans'; font-size:8pt;">: файлы могут быть загружены любым путем анонимных tunnels.</span></p></body></html> + + + + Directory + Каталог + + + + Network Wide + широкая сеть + + + + Browseable + Просматриваться + + + + Add + Добавить + + + + Remove + Удалить + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Наслаждайтесь помощью RetroShare!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Еще один шаг! Ты почти готов RetroShare настройки для работы с компьютером.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Эти настройки параметров, как и когда RetroShare начинается.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Do not show a message when Closing RetroShare + Не показывать сообщения при закрытии RetroShare + + + + Start Minimized + Начало свернутое + + + + Start RetroShare when my System Starts. + Начало RetroShare когда моя запуске системы. + + + + Start minimized on system start + + + + + Finish + Готово + + + + Select A Folder To Share + Выберите папку для доли + + + + Shared Directory Added! + Общий каталог добавлено! + + + + Do you really want to stop sharing this directory ? + Вы действительно хотите отменить совместный доступ к этой папке? + + + + Warning! + Внимание! + + + + RSettingsWin + + + General + Общий + + + + Directories + Справочники + + + + Server + Сервер + + + + Transfer + Передача + + + + Notify + Уведомить + + + + Security + Безопасность + + + + Message + + + + + Forum + Форум + + + + Chat + + + + + Appearance + Внешний вид + + + + Sound + звук + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Ошибка при сохранении конфигурации + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>Приём::</strong> 0.00 (kB/s) | <strong>Отдача:</strong> 0.00 (kB/s) + + + + <strong>Down:</strong> + <strong>Приём:</strong> + + + + <strong>Up:</strong> + <strong>Отдача:</strong> + + + Down: + Приём: + + + Up: + Отдача: + + + + RemoteDirModel + + Friends Directories + Друзья Каталоги + + + My Directories + Моя Каталоги + + + Size + размер + + + Share Type + Тип акции + + + What's new + Что нового + + + Rank + Ранг + + + Age + Возраст + + + FILE + ФАЙЛОВ + + + Anonymous + Аноним + + + Files + Файлы + + + DIR + Папка + + + Hash + Хэш + + + + RetroshareDirModel + + + Anonymous + Аноним + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Неправильный код языка указывается: + + + + Invalid GUI style specified: + Неправильный стиль GUI указывается: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + Источники + + + + Results + Результаты + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + Скачки + + + + Enter a keyword here (at least 3 char long) + Введите ключевое слово здесь (по крайней мере 3-значным) + + + Copy retroshare Link + Скопировать ссылку RetroShare + + + Send retroshare Link + Отправить ссылку RetroShare + + + Broadcast on Channel + Вещания на канале + + + Recommend to Friends + Рекомендовать Друзья + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + Удалить + + + + Remove All + Remove All + + + + + Folder + Папка + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Формат</p></body></html> + + + + Any + Любой + + + + Audio + Аудио + + + + Video + Видео + + + Images + Фотогалерея + + + Programs + Программы + + + Archives + Archives + + + Documents + Документы + + + + Download Notice + Скачать Уведомление + + + + Skipping Local Files + Пропуск локальные файлы + + + + + Sorry + Извините + + + + + This function is not yet implemented. + Эта функция еще не реализована. + + + + Size + Размер + + + + Type + Тип + + + Toggle advanced searching on and off. + Toggle поиск и выключается. + + + <h3>Simple Search:</h3> + <h3>Простой поиск:</ h3> + + + Keywords + Ключевые слова + + + + Archive + Архив + + + + CD-Image + образ CD + + + + Document + документ + + + + Picture + Изображение + + + + Program + Программа + + + + Directory + Каталог + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enter a Keyword here</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Введите ключевое слово здесь</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Close all Search Resullts</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Закрыть все Результаты поиска</span></p></body></html> + + + Clear all Search Results + Закрыть все Результаты поиска + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Download Selected</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Загрузить выбранные</span></p></body></html> + + + + Include files from your own file list in the search result + Включать файлы из собственного списка файлов в результатах поиска + + + + Include own files + Включите собственные файлы + + + + Search inside "browsable" files of your friends + Поиск внутри "просмотр" файлы из ваших друзей + + + + Search in friends lists + Поиск в списки друзей + + + + Multi-hop search at distance 6 in the network +(always reports available files) + Multi-хоп поиск на расстоянии 6 в сети +(всегда докладов доступны файлы) + + + + F2F search + F2F поиск + + + + Limit number of results to : + Ограничить число результатов: + + + + Filename + Имя файла + + + + Start Search + Начать поиск + + + + Search + Поиск + + + + Reset + Сбросить + + + + Enter a Keyword here + + + + + Advanced Search + Расширенный поиск + + + + Advanced + Расширенный + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + Имя файла + + + + File Size + + + + + Age + Возраст + + + + Hash + Хэш + + + + KeyWords + Ключевые слова + + + + Search Id + Поиск ID + + + + SendLinkDialog + + Send RetroShare link + Отправить ссылку RetroShare + + + Send + Отправить + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:22pt; color:#ffffff;">Send RetroShare Link</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:22pt; color:#ffffff;">Отправить ссылку RetroShare</span></p></body></html> + + + + ServerDialog + + Transfer Rates + Скорость передачи + + + Port: + Порт: + + + + ServerPage + + Change + Restart Server + Изменить + Перезагрузить + + + Server Settings + Экспертный Настройки Peer + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Внешние Адрес:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Локал Адрес :</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Порт:</p></body></html> + + + + Automatic (Upnp) + Автоматический (UPnP) + + + + Firewalled + Файрвол + + + + Manual Forwarded Port + Переадресованные руководство порта + + + Should be disabled if you don't want to share connection information between peers. + Должна быть отключена, если вы не хотите поделиться связи информацией между сверстниками. + + + Discovery Enabled + Включено открытия + + + Discovery Disabled + открытая для инвалидов + + + + Download (KB/s) + Скачать (KB/s) + + + + Upload (KB/s) + Закачать (KB/s) + + + + + Network Configuration + Настройка сети + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + Если вы unckeck этом RetroShare не будет использовать туннель связи между сверстниками, которые файрволом и не может напрямую подключаться. Это не зависит от F2F маршрутизации (черепахи маршрутизатора). + + + + Allow Tunnel Connection + Разрешить подключение тоннеля + + + + Local Address + Локальный адрес + + + + External Address + Внешний адрес + + + + Dynamic DNS + + + + + + Port: + Порт: + + + + Show Discovery information in statusbar + + + + + IP Service + Служба IP + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + Если вы unckeck этом RetroShare может лишь определить Ваш IP +При подключении по почте. Оставляя это проверил помогает +подключении, когда у вас есть несколько друзей. Она также помогает, если вы +брандмауэр или VPN. + + + + Allow RetroShare to ask my ip to these websites: + Позвольте спросить RetroShare мой IP на этих сайтах: + + + Misc + Misc/Разное + + + behinde Firewall + За брандмауэр (Firewall) + + + Forwarded External Port + Разрешены внешний порт + + + + Transfer Rates + Скорость передачи + + + + Settings + + Settings + Настройки + + + + Options + Опции + + + + Transfer + Передача + + + + Notify + Уведомить + + + + Security + Безопасность + + + + Message + + + + + Forum + Форум + + + + Chat + + + + + Appearance + Внешний вид + + + + Sound + звук + + + + Cancel + Отмена + + + Apply + подтвердить + + + + OK + OK (Хорошо) + + + + General + Общее + + + Network + Network + + + + Server + Сервер + + + + Directories + Справочники + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + Выбор файла + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + Просматриваться + + + + Anonymous shared Network Wide + + + + + Network Wide + широкая сеть + + + Anonymous + Аноним + + + + Browseable by Friends + + + + Friends + Друзья + + + + OK + + + + + Cancel + + + + + Select A Folder To Share + Выберите папку для доли + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + Добавить Открыть каталог + + + + Stop sharing selected Directory + Остановка обмена выбранной директории + + + Select A Folder To Share + Выберите папку для доли + + + Do you really want to stop sharing this directory ? + Вы действительно хотите отменить совместный доступ к этой папке? + + + Remove selected Shared Directory + Удалить выбранный каталог Общие + + + + + Remove + Удалить + + + Add Shared Directory + Добавить общий каталог + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + Внимание! + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + Оставьте файл ошибок. + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + Shared Directory Added! + Общий каталог добавлено! + + + Do You Want to Remove ? + Вы хотите удалить? + + + + RetroShare Share Manager + RetroShare Доля менеджера + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Доля менеджера</span></p></body></html> + + + + Shared Folder Manager + Общие менеджер папок + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable </span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Это список общих папок. Вы можете добавить или удалить папки с помощью кнопки на левой. </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Когда вы добавляете новую папку, являются общими первоначально все файлы в этой папке.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">Вы можете отдельно долю установка флагов для каждого разделяемого каталога:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Просматриваться </span><span style=" font-family:'Sans'; font-size:8pt;">: просмотр файлов с вашего прямого друзей.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">широкая сеть</span><span style=" font-family:'Sans'; font-size:8pt;">: файлы могут быть загружены любым путем анонимных tunnels.</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + Каталог + + + + Virtual Folder + + + + + Network Wide + широкая сеть + + + + Browsable + Просматриваться + + + + Add + Добавить + + + + Close + закрыть + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Скачать (Download) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + + + + Checking... + Проверка ... + + + + Check files + Проверять файлы + + + + Copy retroshare Link + Скопировать ссылку RetroShare + + + + Send retroshare Link + Отправить ссылку RetroShare + + + Recommend (Automated message) To + Рекомендовать (автоматическое сообщение) до + + + Recommend in a message to + Рекомендовать в послании + + + + Copy retroshare Links to Clipboard + RetroShare Скопировать ссылку в буфер обмена + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + Отправить ссылку RetroShare + + + + Send retroshare Links (HTML) + + + + Send retroshare Links to Chat + Отправить RetroShare ссылки на чат + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + Открыть файл + + + + Open Folder + Открыть папку + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + <strong>Моя Общие файлы</strong> + + + + <strong>Friends Files</strong> + <strong>друзей файлы</strong> + + + + <strong>Files</strong> + <strong>Файлы</strong> + + + + Splitted View + Открыть разделилась + + + + Friends Folders + Файлы друзей + + + + My Folders + Мои Папки + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Файлы</span></p></body></html> + + + + All + Все + + + + One day old + Один день + + + + One Week old + Одна неделя + + + + One month old + Один месяц + + + + Search files + + + + + Start Search + Начать поиск + + + + Reset + + + + + Tree view + + + + + Flat view + + + + + Download selected + Скачать выбранные + + + + check files + проверку файлов + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + Выбор файла + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + Name: + Имя: + + + + RetroShare + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Войти</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + Войти + + + + Remember Password + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Create new Profile...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Создать новый профиль ...</span></a></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Информация...</span></a></p></body></html> + + + + Name (GPG Id) - location: + + + + Name - location: + Имя - Место проведения: + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + Войти провал + + + + Maybe password is wrong + Может быть, неправильный пароль + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + Create a New Profil + Создание нового профиля + + + This will generate a new Profile + Are you sure you want to continue + Это позволит создать новый профиль + Вы уверены, что хотите продолжать + + + + StatisticDialog + + + Statistics + Statistics (статистика) + + + + Download + Download + + + + Session: + Session: + + + + + Downloaded: + Downloaded: + + + Average Downloadspeed: + Average Downloadspeed: + + + + + Count of Downloads: + Count of Downloads: + + + + + + Overall + Overall + + + + Upload + Upload + + + + + + Session + Session + + + + Uploaded: + Uploaded: + + + Average Uploadspeed: + Average Uploadspeed: + + + + + Count of Uploads: + Count of Uploads: + + + + Uploaded + Uploaded + + + + + + + Connections: + Connections: + + + + + + Peers: + Peers: + + + Misc + Misc + + + + Uptime: + Uptime: + + + Overall: + Overall: + + + + + Uptime + Uptime + + + + Records + Records + + + + Uploadspeed: + Uploadspeed: + + + + Downloadspeed: + Downloadspeed: + + + + + Show Settings + Показать параметры + + + + Reset + Reset + + + + Receive Rate + Receive Rate + + + + Send Rate + Send Rate + + + + Always On Top + Always On Top + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Changes the transparency of the Bandwidth Graph + Изменения прозрачности Bandwidth Graph + + + + Save + Сохранить + + + + Cancel + Вернуться/Отмена + + + + Hide Settings + Скрыть настройки + + + + %1 days + + + + + Now + + + + + Transfer + Передача + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Since: + С тех пор, как: + + + + Cumulative + + + + + StatusDefs + + + + Offline + Оффлайн + + + + Away + Далеко + + + + Busy + Занятый + + + + Online + Онлайн + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + связано + + + + Unreachable + + + + + Available + Доступный + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + Личные сообщения + + + + Status message + Статус сообщения + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Личные сообщения</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Введите свой статус</span></p></body></html> + + + + OK + + + + + Cancel + Отмена + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + никакой + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Type + + + + Delete FeedItem + + + + + SubFileItem + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + Сохранить канал Файл + + + File Name + Имя файла + + + + Download + + + + + Play + Играть + + + + %p Kb + + + + Expand + Развернуть + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + Пауза + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + Использовать текст представления сертификатов PGP. + + + + The text below is your PGP certificate. You have to provide it to your friend + Приводимый ниже текст PGP вашем сертификате. Вы должны предоставить его в другом + + + + Save your Cert into a File + Cert Сохранить в файл + + + + Please, paste your friends PGP certificate into the box below + Пожалуйста, вставьте друзья PGP сертификата в окне, расположенном ниже + + + + Clean certificate + + + + + RetroShare Invite + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + Your Cert is copied to Clipboard, paste and send it to yourfriend via email or some other way + Ваш Cert копируется в буфер обмена, вставить и отправить его yourfriend по электронной почте или другим способом + + + + Save as... + Сохранить как ... + + + + RetroShare Certificate (*.rsc );;All Files (*) + RetroShare сертификата (*. rsc), все файлы (*) + + + + You can copy this text and send it to your friend via email or some other way + Вы можете скопировать этот текст и отправить его другу по электронной почте или другим способом + + + + RetroShare + + + + + Text certificate + Текст сертификата + + + Use text representation of the XPGP certificates. + Использование текстовых представление о XPGP сертификатов. + + + The text below is your XPGP certificate. You have to provide it to your friend + В тексте ниже вы XPGP сертификат. Вы должны представить вашему другу + + + + Copy your Cert to Clipboard + Скопируйте в буфер обмена Cert + + + + Run Email program + Запустите почтовую программу + + + Please, paste your friends XPGP certificate into the box below + Пожалуйста, вставьте друзья XPGP сертификата в поле ниже + + + + Connect Friend Help + Связь Помощь другу + + + You can copy this text and send it to your friend via email, ICQ or some other way + Вы можете скопировать этот текст и отправить его к своему другу по электронной почте, ICQ или каким-либо другим способо + + + + Certificate Load Failed + Нагрузка Ошибка сертификата + + + + TransferFeed + + None + никакой + + + + TransferPage + + Transfer + Передача + + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + потоковое + + + + Random + Случайные + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Вернуться/Отмена + + + + Clear Completed + Очистка завершена + + + + + Status + Status + + + + Completed + Завершено + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Скачивается:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Приём:</span></p></body></html> + + + + Show cache transfers + + + + + Uploads + Отдача + + + + Selected transfer + Выбранный transfe + + + + Done + Готово + + + + Active + Активная + + + + Outstanding + Шт + + + Tunneling + Туннельный + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Закачивается:</span></p></body></html> + + + + + Name + i.e: file name + Имя файла + + + + + Size + i.e: file size + Размер + + + Progress + i.e: % downloaded + Передано % + + + + Speed + i.e: Download speed + Скорость + + + + Progress / Availability + i.e: % downloaded + Прогресс + + + + Sources + i.e: Sources + Источники + + + Remaining + i.e: Estimated Time of Arrival / Time left + Осталось + + + + Core-ID + + + + User Name + i.e: user name + Имя пользователя + + + + Progress + i.e: % uploaded + Progress + + + + Speed + i.e: upload speed + Скорость + + + + Transferred + Передано + + + + Play + Играть + + + + Pause + Пауза + + + + Resume + Продолжить + + + + Open Folder + Открыть папку + + + + Open File + Открыть файл + + + + Preview File + Предварительный просмотр файла + + + + Details... + Подробности ... + + + Copy retroshare Link + Скопировать ссылку RetroShare + + + Paste retroshare Link + Вставить ссылку RetroShare + + + View + Просмотр + + + + Down + Вниз + + + + Up + Вверх + + + + Top + Верх + + + + Bottom + Дно + + + + Priority (Speed)... + Приоритета (скорость) ... + + + + Streaming + потоковое + + + + Random + Случайные + + + + Chunk strategy + кусок стратегия + + + + Queued + В очереди + + + + Paused + Приостановлена + + + + Transferring + Перенос + + + + Checking... + Проверка ... + + + + RetroShare + + + + + Details: + Подробности: + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + Открытой передачи + + + + File %1 is not completed. If it is a media file, try to preview it. + Файл %1 не завершена. Если это мультимедийный файл, попробуйте просмотреть его. + + + + Are you sure that you want to cancel and delete these files? + Вы уверены, что вы хотите отменить, и удалить эти файлы? + + + + Speed / Queue position + Скорость / Очередь позиции + + + + Remaining + Осталось + + + + Download time + i.e: Estimated Time of Arrival / Time left + Время загрузки + + + + Peer + i.e: user name + совокупность + + + + Hash + Хэш + + + + Router Statistics + + + + + Router Requests + + + + + Force Check + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + Медленнее + + + + + + Average + Среднее + + + + + Faster + Быстрее + + + + Move in Queue... + Переместить в очереди ... + + + + + + Failed + Ошибка + + + + + + Okay + Хорошо + + + + + Waiting + ожидание + + + + Downloading + Загрузка + + + + + + + Complete + Полная + + + + Unknown + Неизвестно + + + + version: + Версия: + + + + Uploading + Загружаю + + + + TreeStyle_RDM + + + + FILE + ФАЙЛОВ + + + + Files + Файлы + + + + File + + + + + + DIR + Папка + + + + Friends Directories + Друзья Каталоги + + + + My Directories + Моя Каталоги + + + + Size + + + + + Age + Возраст + + + + Friend + + + + + Share Type + Тип акции + + + + What's new + Что нового + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + Доверие + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + Полный + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + Hash + Хэш + + + Type + Type + + + Age + Возраст + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Download + Скачать (Download) + + + Broadcast on Channel + Вещания на канале + + + Recommend to Friends + Рекомендовать Друзья + + + Remove + Удалить + + + Remove All + Удалить все + + + Toggle advanced searching on and off. + Toggle поиск и выключается. + + + <h3>Simple Search:</h3> + <h3>Простой поиск:</ h3> + + + Keywords + Ключевые слова + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Формат</p></body></html> + + + Any + Любой + + + Audio + Аудио + + + Video + Video + + + Filename + Имя файла + + + Size + размер + + + Sources + Источники + + + Type + Type + + + Hash + Хэш + + + KeyWords + Ключевые слова + + + Results + Результаты + + + Search Id + Поиск ID + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + OK (Хорошо) + + + + Cancel + Вернуться/Отмена + + + + Yes + Да + + + + No + Нет + + + + Help + Help + + + + Retry + Повторить + + + + Show Log + Показать История + + + + Show Settings + Показать параметры + + + + Continue + Продолжить + + + + Quit + Выход + + + + Browse + Выбор файла + + + + misc + + + Unknown + Unknown (size) + Неизвестно + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + Неизвестно + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Details + Details + + + OK + OK (Хорошо) + + + Name + Name/сетевой карты + + + Value + Value + + + diff --git a/retroshare-gui/src/lang/retroshare_sl.qm b/retroshare-gui/src/lang/retroshare_sl.qm new file mode 100644 index 000000000..b6a9406aa Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_sl.qm differ diff --git a/retroshare-gui/src/lang/retroshare_sl.ts b/retroshare-gui/src/lang/retroshare_sl.ts new file mode 100644 index 000000000..ae3b512b1 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_sl.ts @@ -0,0 +1,14190 @@ + + + + + + + Arial + Arial + + + + @default + + Arial + Arial + + + + AboutDialog + + + About RetroShare + + + + + About + O programu + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + RetroShare + + + + Sorry, can't determine system default command for this file + + + + + + AddFileAssotiationDialog + + RetroShare + RetroShare + + + + AddFriendDialog + + Cancel + Prekliči + + + Done + Opravljeno + + + Load From File + Naloži iz datoteke + + + RetroShare + RetroShare + + + Certificate Load Failed + Nalaganje potrdila ni uspelo + + + + AddFriendWizard + + Cancel + Prekliči + + + RetroShare + RetroShare + + + Certificate Load Failed + Nalaganje potrdila ni uspelo + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + Prekliči + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Cancel + Prekliči + + + + Search + Najdi + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search Criteria + + + + + AppearanceDialog + + Language + Jezik + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Izberite jezik vmesnika za RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sprememba jezika bo veljala šele po ponovnem zagonu aplikacije RetroShare!</p></body></html> + + + Style + Slog + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Izberite slog vmesnika za RetroShare</p></body></html> + + + Style Sheet + Slogovna predloga + + + + AppearancePage + + + Language + Jezik + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Izberite jezik vmesnika za RetroShare</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sprememba jezika bo veljala šele po ponovnem zagonu aplikacije RetroShare!</p></body></html> + + + + Style + Slog + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Izberite slog vmesnika za RetroShare</p></body></html> + + + + Style Sheet + Slogovna predloga + + + + ApplicationWindow + + + Hide + Skrij + + + + Show + Pokaži + + + + + RetroShare + RetroShare + + + Transfers + Prenosi + + + Messages + Sporočila + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Statistics + Statistika + + + + AttachFileItem + + + Form + + + + File Name + Ime datoteke + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + Preveri istovetnost + + + Authenticate Friend By Entering Their Code + Preveri istovetnost prijatelja, tako da vnesete njegovo kodo + + + OK + V redu + + + Cancel + Prekliči + + + + BandwidthGraph + + + + Show Settings + Pokaži nastavitve + + + + Reset + Ponastavi + + + + Receive Rate + Razmerje prejemanja + + + + Send Rate + Razmerje pošiljanja + + + + Style + Slog + + + + Changes the transparency of the Bandwidth Graph + Spremeni prosojnost grafa pretočnosti + + + + 100 + 100 + + + + % Opaque + % prekrivno + + + + Save + Shrani + + + + Cancel + Prekliči + + + + Since: + + + + + Hide Settings + Skrij nastavitve + + + + RetroShare Bandwidth Usage + + + + + Always on Top + + + + + BgWindow + + Options + Možnosti + + + About + O programu + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + Prekliči + + + + OK + V redu + + + + Close + Zapri + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + Ime + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + Skrij + + + + CalDialog + + + Remove + Odstrani + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + Izberi digitalno potrdilo + + + Certificates (*.pqi *.pem) + Digitalna potrdila (*.pqi, *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + RetroShare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanCreateDialog + + Create a new Broadcast Channel + Ustvari nov oddajni kanal + + + Create A New Broadcast Channel + Ustvari novi oddajni kanal + + + Channel Name: + Ime kanala: + + + Type: + Vrsta: + + + Public Channel (Signed) + Javni kanal (podpisano) + + + Private Channel (Encrypted) + Zasebni kanal (šifrirano) + + + Cancel Channel + Prekliči kanal + + + Create Channel + Ustvari kanal + + + + ChanMsgDialog + + Compose + Sestavi + + + Recommended Files + Priporočene datoteke + + + Send To: + Prejemnik: + + + Send + Pošlji + + + Delete Channel + Izbriši kanal + + + Create Channel MSG + Ustvari sporočilo za kanal + + + File Name + Ime datoteke + + + Size + Velikost + + + Sources + Viri + + + Save + Shrani + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Skrij + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + Kanali + + + Video + Video + + + 1 + 1 + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + Vrsta + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + Prekliči + + + + OK + V redu + + + + Close + Zapri + + + + ChannelFeed + + + Create Channel + Ustvari kanal + + + + Subscribe To Channel + Naroči se na kanal + + + Reset + Ponastavi + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubcribe To Channel + + + + + Unsubscribe + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + Name + Ime + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChannelStatsDialog + + 1 + 1 + + + + ChatDialog + + Chat + Klepet + + + 1 + 1 + + + Send + Pošlji + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + Pošlji + + + + Cancel + Prekliči + + + Chat + Klepet + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + Splošno + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + Slog + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + Ustvari prijatelja + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + Možnosti + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Cancel + Prekliči + + + Port: + Vrata: + + + Trust Settings + Nastavitve zaupanja + + + Trust Level + Raven zaupanja + + + Trust Their Signature + Zaupaj podpisu + + + Sign The Certificate + Podpiši digitalno potrdilo + + + + OK + V redu + + + + Details + Podrobnosti + + + + Name + Ime + + + + Loc + + + + + Peer Address + Naslov vrstnika + + + + Last Contact + Zadnji stik + + + Peer Details + Podrobnosti o vrstniku + + + + Peer Info + + + + + Peer ID + + + + + Version + + + + + RetroShare ID + + + + + Status + Stanje + + + + Dynamic DNS + + + + + Addresses list + + + + + None + + + + + Marginal + + + + + Full + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Deny Friend + + + + + Make Friend + Ustvari prijatelja + + + + Certificate + + + + + + Sign GPG key + + + + + Friend Details + + + + + Local Address + + + + + External Address + + + + + + Port + + + + + Your trust in this peer is: + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + Apply and Close + + + + + + RetroShare + RetroShare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + ConnectDialog + + Peer Details + Podrobnosti o vrstniku + + + Make Friend + Ustvari prijatelja + + + Cancel + Prekliči + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + Ime + + + + Description + + + + + Type: + Vrsta: + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + Prekliči + + + + Create + + + + + RetroShare + RetroShare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + RetroShare + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + Ime + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + Vrsta: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + Prekliči + + + + Create + + + + + RetroShare + RetroShare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + RetroShare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Ime + + + + Type: + Vrsta: + + + + Authenticated Messages + + + + + Cancel + Prekliči + + + RetroShare + RetroShare + + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Description + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Create + + + + + CreateForumMsg + + + Close + Zapri + + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + RetroShare + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + RetroShare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + CryptographyDialog + + RSA Key Size + Velikost ključa RSA + + + Rijndael Block size + Velikost bloka Rijndael + + + 128 Bits + 128-bitni + + + 192 Bits + 192-bitni + + + 256 Bits + 256-bitni + + + Rijndael Key Size + Velikost ključa Rijndael + + + Rijndael Mode + Način Rijndael + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + Rijndael Padding + Bitno zapolnjevanje Rijndael + + + PKCS7 + PKCS7 + + + Zeros + Ničle + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Velikost odziva Rijndael + + + Key Size: + Velikost ključa: + + + Block Size: + Velikost bloka: + + + Feedback Size: + Velikost odziva: + + + Mode: + Način: + + + Padding: + Bitno zapolnjevanje: + + + RetroShare + RetroShare + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Podrobnosti + + + + + General + Splošno + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + Vrsta: + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + Datum + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + V redu + + + + Cancel + Prekliči + + + + Rating + + + + + File Name + Ime datoteke + + + + Not Rated + + + + + No Comments + + + + + DirectoriesDialog + + Shared Directories + Mape v skupni rabi + + + Other Directories + Druge mape + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Dohodne datoteke</span></p></body></html> + + + Add Shared Directory + Dodaj mapo v skupni rabi + + + + DirectoriesPage + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + Mape v skupni rabi + + + + Edit Share + + + + Incoming files + Dohodne datoteke + + + + + Browse + + + + Add Shared Directory + Dodaj mapo v skupni rabi + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + Zapri + + + + EditChanDetails + + + Channel Details + + + + + Cancel + Prekliči + + + + OK + V redu + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + Prekliči + + + + OK + V redu + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Prijatelji</span></p></body></html> + + + + Status + Stanje + + + + Person + Oseba + + + + Auto Connect + Samodejno poveži + + + + Trust Level + Raven zaupanja + + + + Peer Address + Naslov vrstnika + + + + Last Contact + Zadnji stik + + + + Organisation + Organizacija + + + + Location + Kraj + + + + Country + Država + + + + Person Id + Id osebe + + + + Auth Code + Avtorizacijska koda + + + + # + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileHashDialog + + Download + Prenesi + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + %1 KB + %1 kB + + + File Name + Ime datoteke + + + Size + Velikost + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + Velikost + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + Prekliči + + + + OK + V redu + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + Pošlji + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + Razno + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + Skrij + + + + Expand + + + + + + RetroShare + RetroShare + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + + Date + Datum + + + + + Start New Thread + + + + New Message + Novo sporočilo + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Title + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + Ponastavi + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + Prijatelji + + + + Status + Stanje + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + Pošlji + + + + Clear Chat History + + + + + + Add Friend + Dodaj prijatelja + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + Kraj + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + Klepet + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + Poveži se s prijateljem + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + Shrani digitalno potrdilo + + + + Certificates (*.pqi) + Digitalna potrdila (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + Splošno + + + Network + Omrežje + + + Directories + Mape + + + Server + Strežnik + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Server + Strežnik + + + + Status + Stanje + + + + Accept + Sprejmi + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Namestitev RetroShare + + + Load Trusted Certificate (Optional) + Naloži zaupanja vredna digitalna potrdila (dodatno) + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + Ime + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + Kraj + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Prijatelj</span></p></body></html> + + + Select File + Izberite datoteko + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ime:</p></body></html> + + + Generate New Certificate + Ustvari novo digitalno potrdilo + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + Izberite zaupanja vrednega prijatelja + + + + Certificates (*.pqi *.pem) + Digitalna potrdila (*.pqi, *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + GeneralDialog + + Style + Slog + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Izberite slog vmesnika za RetroShare</p></body></html> + + + Language + Jezik + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Izberite jezik vmesnika za RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sprememba jezika bo veljala šele po ponovnem zagonu aplikacije RetroShare!</p></body></html> + + + Style Sheet + Slogovna predloga + + + Login + Prijava + + + Misc + Razno + + + + GeneralPage + + Keys manager + Upravitelj ključev + + + Style + Slog + + + Choose RetroShare's interface style + Izberite slog vmesnika za RetroShare + + + Language + Jezik + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sprememba jezika bo veljala šele po ponovnem zagonu aplikacije RetroShare!</p></body></html> + + + Choose the language used in RetroShare + Izberite jezik, ki ga bo uporabljal RetroShare + + + Login + Prijava + + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + Razno + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Prejeto: + + + + + + %1 KB/s + %1 kB/s + + + + Sent: + Poslano: + + + + %1 KB + %1 kB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Prijatelji + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + + + + + Description + + + + + Reset + Ponastavi + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + Ime + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + Datum + + + + Size + Velikost + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + Search + Najdi + + + + Home + Domov + + + + Close + Zapri + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + O programu + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + Ponastavi + + + + + Copy + + + + + Remove + Odstrani + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + Pošlji + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + InviteDialog + + Done + Opravljeno + + + Cancel + Prekliči + + + Launch Email + Zaženi program za pošto + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + + + + + Expand + + + + + Hide + Skrij + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + Od + + + + Show + Pokaži + + + + 101-200 + 101-200 + + + + 201-300 + 201-300 + + + + 301-400 + 301-400 + + + + 401-500 + 401-500 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + LogDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> + +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +</body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> + +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">O programu RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Hitre povezave: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">O programu</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Prvi koraki</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Osnove uporabniškega vmesnika</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Pogosto zastavljena vprašanja (FAQ)</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Hitre povezave: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table><table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Pogosto zastavljena vprašanja </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Hitre povezave: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">O programu</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Prvi koraki</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Osnove uporabniškega vmesnika</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Pogosto zastavljena vprašanja (FAQ)</span></a></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> +</span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">Z</span><span style=" font-size:small;">akaj se noče povezati?</span><span style=" font-size:small;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. +RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Hitre povezave: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">O programu</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Prvi koraki</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Osnove uporabniškega vmesnika</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Pogosto zastavljena vprašanja (FAQ)</span></a></p></td></tr></table> +</body></html> + + + + MainWindow + + + Network + Omrežje + + + + Friends + Prijatelji + + + + + Transfers + Prenosi + + + + + Messages + Sporočila + + + + + Channels + Kanali + + + + Blogs + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + Stanje + + + + Chat + Klepet + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + + + Options + Možnosti + + + + Hide + Skrij + + + + Show + Pokaži + + + + RetroShare + RetroShare + + + Invite Friend + Povabi prijatelja + + + + MainWindow + + + + + Add Friend + Dodaj prijatelja + + + + Add a Friend Wizard + + + + + Add Share + Dodaj skupno rabo + + + + + Quick Start Wizard + + + + + Search + Najdi + + + + Files + Datoteke + + + Add Shared Directory + Dodaj mapo v skupni rabi + + + + Show/Hide + + + + + &Quit + + + + + + + + You have %1 new message + + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Minimize + + + + + Maximize + + + + + Links Cloud + + + + + RetroShare %1 a secure decentralised communication platform + + + + + Unfinished + + + + + Help + Pomoč + + + + About + O programu + + + + + Forums + + + + + Open Messages + + + + + Applications + + + + Settings + Nastavitve + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + Quit + + + + + SMPlayer + + + + + Messenger + + + + + MessageComposer + + + + Compose + Sestavi + + + + + Contacts + + + + + Search for Name: + + + + + Reset + Ponastavi + + + + Send To: + Prejemnik: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + Priporočene datoteke + + + + File Name + Ime datoteke + + + + Size + Velikost + + + Sources + Viri + + + + Hash + + + + + Send + Pošlji + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + Shrani + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + RetroShare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + Misc + Razno + + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + sporočilo + + + New Message + Novo sporočilo + + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + Zapri + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Priporočene datoteke</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + Ime datoteke + + + + Size + Velikost + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + + + + + Download all + + + + + Hide + Skrij + + + + Expand + + + + + File + + + + + Files + Datoteke + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + Novo sporočilo + + + + Compose + Sestavi + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + Novo sporočilo + + + + Quick View + + + + + Reply to Message + Odgovori + + + + Remove Message + Odstrani sporočilo + + + + + Date + Datum + + + + + + From + Od + + + Size + Velikost + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Priporočene datoteke</span></p></body></html> + + + + Reply + + + + + Reply all + + + + + Foward + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Odstrani izbrano sporočilo</p></body></html> + + + + Delete + + + + + Compose + Sestavi + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + Reset + Ponastavi + + + + Attachments + + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + Prejeto + + + + + + + Outbox + Odhodna pošta + + + + Draft + Osnutki + + + + + Sent + Poslano + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Odgovori izbranemu sporočilu</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Novo sporočilo</p></body></html> + + + Download All + Prenesi vse + + + File Name + Ime datoteke + + + Sources + Viri + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + + Empty trash + + + + Hide + Skrij + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + Files + Datoteke + + + + + + + + Total: + + + + + + Reply to All + + + + + + Subject + + + + + Print + + + + + MessagesPopupDialog + + New Message + Novo sporočilo + + + Reply to Message + Odgovori + + + Remove Message + Odstrani sporočilo + + + Download All + Prenesi vse + + + Messages + Sporočila + + + Inbox + Prejeto + + + Outbox + Odhodna pošta + + + Draft + Osnutki + + + Sent + Poslano + + + From + Od + + + Date + Datum + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Priporočene datoteke</span></p></body></html> + + + File Name + Ime datoteke + + + Size + Velikost + + + Sources + Viri + + + Compose + Sestavi + + + Remove + Odstrani + + + + MessengerDirModel + + Size + Velikost + + + Rank + Uvrstitev + + + + MessengerWindow + + + Expand all + + + + + Collapse all + + + + + Chat + Klepet + + + + Message Friend + + + + + Connect To Friend + Poveži se s prijateljem + + + + Peer Details + Podrobnosti o vrstniku + + + + Recomend this Friend to... + + + + + Export Friend + Izvozi prijatelja + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + Shrani digitalno potrdilo + + + + Certificates (*.pqi) + Digitalna potrdila (*.pqi) + + + Remove Friend + Odstrani prijatelja + + + + Click to Change your Avatar + + + + + Search Friends + + + + + Reset + Ponastavi + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + Prejeto + + + Outbox + Odhodna pošta + + + Sent + Poslano + + + Date + Datum + + + + MsgItem + + + Reply to Message + Odgovori + + + + Remove Item + + + + + + Expand + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Skrij + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Sporočila</span></p></body></html> + + + Date + Datum + + + Rank + Uvrstitev + + + From + Od + + + Msg + Sporočilo + + + Count + Število + + + Size + Velikost + + + Type + Vrsta + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Besedilo sporočila</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Priporočene datoteke</span></p></body></html> + + + Delete Channel + Izbriši kanal + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Sporočila</span></p></body></html> + + + Date + Datum + + + Rank + Uvrstitev + + + From + Od + + + Msg + Sporočilo + + + Count + Število + + + Size + Velikost + + + Type + Vrsta + + + Rs[Cert/Chan]IdSize + Rs[Cert/Chan]IdSize + + + RsMsgId + RsMsgId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Besedilo sporočila</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Priporočene datoteke</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + Naloži digitalno potrdilo + + + Select a pem/pqi File + Izberite datoteko pem/pqi + + + File Not Found + Datoteke ni mogoče najti + + + %1 does not exist. Would you like to create it? + %1 ne obstaja. Jo želite ustvariti? + + + Failed to Create File + Datoteke ni mogoče ustvariti + + + Unable to create %1 [%2] + Ni mogoče ustvariti %1 [%2] + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + Select Certificate + Izberi digitalno potrdilo + + + Certificates (*.pqi *.pem) + Digitalna potrdila (*.pqi, *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Omrežje:</span></p></body></html> + + + Accept + Sprejmi + + + Trust + Zaupaj + + + Last Contact + Zadnji stik + + + + + + Name + Ime + + + Peer Address + Naslov vrstnika + + + Organisation + Organizacija + + + Location + Kraj + + + Country + Država + + + + + Cert Id + Id potrdila + + + + Network + Omrežje + + + Peer Details + Podrobnosti o vrstniku + + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Unknown + + + + + yourself + + + + RetroShare + RetroShare + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + Dodaj prijatelja + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + Možnosti prepustnosti + + + Max Total Data Rate (KB/S): + Največji prenos podatkov (kB/s): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Hitrost na osebo (kB/s):</p></body></html> + + + + NetworkView + + Hide Settings + Skrij nastavitve + + + Show Settings + Pokaži nastavitve + + + Settings + Nastavitve + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Prijatelji + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + V redu + + + + Cancel + Prekliči + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Odstrani vse + + + + Options + Možnosti + + + + NotifyDialog + + Channels + Kanali + + + Chat + Klepet + + + Messages + Sporočila + + + New Message + Novo sporočilo + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + Kanali + + + + Forums + + + + + Chat + Klepet + + + + Blogs + + + + + Messages + Sporočila + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + Novo sporočilo + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + OptionsDlg + + Cancel + Prekliči + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + Make Friend + Ustvari prijatelja + + + Remove Friend + Odstrani prijatelja + + + + Chat + Klepet + + + + Start Chat + + + + Organisation + Organizacija + + + + Location + Kraj + + + Country + Država + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Send + Pošlji + + + + Cancel + Prekliči + + + + Peer ID: + + + + + Write Message + + + + + Status: + + + + + Trust: + + + + + Name: + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + Skrij + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Prijatelji + + + + PeersDialog + + Chat + Klepet + + + Export Friend + Izvozi prijatelja + + + Remove Friend + Odstrani prijatelja + + + Save Certificate + Shrani digitalno potrdilo + + + Certificates (*.pqi) + Digitalna potrdila (*.pqi) + + + Status + Stanje + + + Person + Oseba + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Prijatelji</span></p></body></html> + + + Connect To Friend + Poveži se s prijateljem + + + Location + Kraj + + + Peer Details + Podrobnosti o vrstniku + + + RetroShare + RetroShare + + + Send + Pošlji + + + Add Friend + Dodaj prijatelja + + + Friends + Prijatelji + + + + PeersFeed + + Save Certificate + Shrani digitalno potrdilo + + + Certificates (*.pqi) + Digitalna potrdila (*.pqi) + + + Friends + Prijatelji + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Odstrani + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + + Date + Datum + + + + + Location + Kraj + + + + Size + Velikost + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + Odstrani + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + RetroShare + RetroShare + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + Pošlji + + + + Close + Zapri + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + RetroShare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + Directories + Mape + + + Error Saving Configuration + Napaka pri shranjevanju nastavitev + + + General + Splošno + + + Server + Strežnik + + + Options + Možnosti + + + Cancel + Prekliči + + + OK + V redu + + + Help + Pomoč + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + Prenesi vse + + + + RetroShare + RetroShare + + + + Error : cannot get peer details. + + + + + + Name + Ime + + + + Peer ID + + + + + Size + Velikost + + + + Profile View + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + Name + Ime + + + Date + Datum + + + Size + Velikost + + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + Odstrani + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + Splošno + + + + Directories + Mape + + + + Server + Strežnik + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + Klepet + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Napaka pri shranjevanju nastavitev + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RemoteDirModel + + Size + Velikost + + + Rank + Uvrstitev + + + Files + Datoteke + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Navedena neveljavna koda jezika: + + + + Invalid GUI style specified: + Naveden neveljaven slog vmesnika: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + Viri + + + + Results + Rezultati + + + + Close all Search Resullts + + + + + Close All Search Results + + + + + Download Selected + + + + + + Download + Prenesi + + + + Enter a keyword here (at least 3 char long) + + + + Broadcast on Channel + Oddajaj na kanalu + + + Recommend to Friends + Priporoči prijateljem + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + Odstrani + + + + Remove All + Odstrani vse + + + + + Folder + + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vrsta</p></body></html> + + + + Any + Karkoli + + + + Audio + Zvok + + + + Video + Video + + + Images + Slike + + + Programs + Programi + + + Archives + Arhivi + + + Documents + Dokumenti + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Size + Velikost + + + + Type + Vrsta + + + + Archive + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + Ime datoteke + + + + File Size + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + Najdi + + + + Reset + Ponastavi + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Search Id + + + + + SendLinkDialog + + Send + Pošlji + + + + ServerDialog + + Transfer Rates + Hitrost prenosov + + + Port: + Vrata: + + + + ServerPage + + Change + Restart Server + Spremeni in ponovno zaženi strežnik + + + Server Settings + Nastavitve strežnika + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Zunanji naslov:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Krajevni naslov:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vrata:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Download (KB/s) + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + Vrata: + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + Misc + Razno + + + behinde Firewall + za požarnim zidom + + + Forwarded External Port + Posredovana zunanja vrata + + + + Transfer Rates + Hitrost prenosov + + + + Settings + + Settings + Nastavitve + + + + Options + Možnosti + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + Klepet + + + + Appearance + + + + + Sound + + + + + Cancel + Prekliči + + + Apply + Uporabi + + + + OK + V redu + + + + General + Splošno + + + Network + Omrežje + + + + Server + Strežnik + + + + Directories + Mape + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + Friends + Prijatelji + + + + OK + V redu + + + + Cancel + Prekliči + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + Prekliči + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + RetroShare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + Odstrani + + + Add Shared Directory + Dodaj mapo v skupni rabi + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + Zapri + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Prenesi + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Datoteke</span></p></body></html> + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + Ponastavi + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + RetroShare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + Statistika + + + + Download + Prenosi na računalnik + + + + Session: + Seja: + + + + + Downloaded: + Preneseno: + + + Average Downloadspeed: + Povprečna hitrost prenosov: + + + + + Count of Downloads: + Število prenosov: + + + + + + Overall + Skupaj + + + + Upload + Prenosi z računalnika + + + + + + Session + Seja + + + + Uploaded: + Preneseno: + + + Average Uploadspeed: + Povprečna hitrost prenosov: + + + + + Count of Uploads: + Število prenosov: + + + + Uploaded + Preneseno + + + + + + + Connections: + Povezave: + + + + + + Peers: + Vrstniki: + + + Misc + Razno + + + + Uptime: + Čas povezave: + + + Overall: + Skupno: + + + + + Uptime + Čas povezave + + + + Records + Zapisi + + + + Uploadspeed: + Hitrost prenosov z računalnika: + + + + Downloadspeed: + Hitrost prenosov na računalnik: + + + + + Show Settings + Pokaži nastavitve + + + + Reset + Ponastavi + + + + Receive Rate + Razmerje prejemanja + + + + Send Rate + Razmerje pošiljanja + + + + Always On Top + Vedno na vrhu + + + + 100 + 100 + + + + % Opaque + % prekrivno + + + + Changes the transparency of the Bandwidth Graph + Spremeni prosojnost grafa pretočnosti + + + + Save + Shrani + + + + Cancel + Prekliči + + + + Hide Settings + Skrij nastavitve + + + + %1 days + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Since: + + + + + Cumulative + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + V redu + + + + Cancel + Prekliči + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + Slog + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Vrsta + + + + Delete FeedItem + + + + + SubFileItem + + File Name + Ime datoteke + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + RetroShare + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + Nalaganje potrdila ni uspelo + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Prekliči + + + + Clear Completed + Počisti zaključene + + + + + Status + Stanje + + + + Completed + Dokončano + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Prenosi na računalnik:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + Opravljeno + + + + Active + + + + + Outstanding + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Prenosi z računalnika:</span></p></body></html> + + + + + Name + i.e: file name + Ime + + + + + Size + i.e: file size + Velikost + + + Progress + i.e: % downloaded + Napredek + + + + Speed + i.e: Download speed + Hitrost + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + Viri + + + + Core-ID + + + + + Progress + i.e: % uploaded + Napredek + + + + Speed + i.e: upload speed + Hitrost + + + + Transferred + + + + + Hash + + + + + Play + + + + + Pause + + + + + Resume + + + + + Force Check + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Priority (Speed)... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + Queued + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + RetroShare + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Peer + i.e: user name + + + + + Router Statistics + + + + + Router Requests + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Move in Queue... + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + version: + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + Datoteke + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + Velikost + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + Zaupaj + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + File Name + Ime datoteke + + + Type + Vrsta + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Broadcast on Channel + Oddajaj na kanalu + + + Recommend to Friends + Priporoči prijateljem + + + Remove + Odstrani + + + Remove All + Odstrani vse + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vrsta</p></body></html> + + + Any + Karkoli + + + Audio + Zvok + + + Video + Video + + + Size + Velikost + + + Sources + Viri + + + Type + Vrsta + + + Results + Rezultati + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + V redu + + + + Cancel + Prekliči + + + + Yes + Da + + + + No + Ne + + + + Help + Pomoč + + + + Retry + Poskusi ponovno + + + + Show Log + Pokaži dnevnik + + + + Show Settings + Pokaži nastavitve + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Details + Podrobnosti + + + OK + V redu + + + Name + Ime + + + Value + Vrednost + + + diff --git a/retroshare-gui/src/lang/retroshare_sr.qm b/retroshare-gui/src/lang/retroshare_sr.qm new file mode 100644 index 000000000..0cc60e508 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_sr.qm differ diff --git a/retroshare-gui/src/lang/retroshare_sr.ts b/retroshare-gui/src/lang/retroshare_sr.ts new file mode 100644 index 000000000..b380e31e6 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_sr.ts @@ -0,0 +1,13813 @@ + + + + + + + Arial + Ариал + + + + @default + + Arial + Ариал + + + + AboutDialog + + + About RetroShare + + + + + About + + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + RetroShare + + + + Sorry, can't determine system default command for this file + + + + + + AddFileAssotiationDialog + + RetroShare + RetroShare + + + + AddFriendDialog + + RetroShare + RetroShare + + + Cancel + Поништи + + + + AddFriendWizard + + RetroShare + RetroShare + + + Cancel + Поништи + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + Поништи + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + Cancel + Поништи + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + RetroShare: Advanced Search + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search + + + + + Search Criteria + + + + + AppearanceDialog + + Language + Језик + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">При промени језика морате рестартовати RetroShare! </p></body></html> + + + Style + Стил + + + Style Sheet + Стил Странице + + + + AppearancePage + + + Language + Језик + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">При промени језика морате рестартовати RetroShare! </p></body></html> + + + + Style + Стил + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + + + Style Sheet + Стил Странице + + + + ApplicationWindow + + Transfers + Трансфер + + + Messages + Поруке + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Hide + Сакри + + + + Show + Прикажи + + + + + RetroShare + RetroShare + + + + Statistics + Статистике + + + + AttachFileItem + + + Form + + + + File Name + Име Фајла + + + + %p Kb + + + + + Cancel Download + + + + + AuthorizationDialog + + Authenticate + Аутентификуј + + + Authenticate Friend By Entering Their Code + Аутентификуј Пријатеља Уношењем Његовог Кода + + + OK + У Реду + + + Cancel + Поништи + + + + BandwidthGraph + + + Since: + + + + + Hide Settings + Сакри Подешавања + + + + + Show Settings + Прикажи Подешавања + + + + Reset + Ресет + + + + Receive Rate + Брзина Примања + + + + Send Rate + Брзина Слања + + + + Style + Стил + + + + Changes the transparency of the Bandwidth Graph + Промени Провидност Графика Протока + + + + 100 + 100 + + + + % Opaque + % Непровидан + + + + Save + Сачувај + + + + Cancel + Поништи + + + + RetroShare Bandwidth Usage + + + + + Always on Top + + + + + BgWindow + + Options + Опције + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + Поништи + + + + OK + У Реду + + + + Close + + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + Име + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + Сакри + + + + CalDialog + + + Remove + Уклони + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + Изабери Сертификат + + + + Please choose a filename + + + + + + + + RetroShare + RetroShare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanMsgDialog + + Delete Channel + Обриши Канал + + + Create Channel MSG + Направи Поруку Канала + + + Send To: + Пошаљи: + + + Recommended Files + Препоручени Фајлови + + + File Name + Име Фајла + + + Size + Величина + + + Sources + Изворишта + + + Send + Пошаљи + + + Save + Сачувај + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + Преузимање + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Сакри + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + Канали + + + 1 + 1 + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + Поништи + + + + OK + У Реду + + + + Close + + + + + ChannelFeed + + Title + Назив + + + Reset + Ресет + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubscribe + + + + + Subscribe To Channel + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + + Create Channel + + + + + Unsubcribe To Channel + + + + Name + Име + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChannelStatsDialog + + 1 + 1 + + + + ChatDialog + + Send + Пошаљи + + + Chat + Чет + + + 1 + 1 + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + Пошаљи + + + + Cancel + Поништи + + + Chat + Чет + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + Опште + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + Стил + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + Опције + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Details + Детаљи + + + + Name + Име + + + + Loc + + + + + Peer Address + Адреса Мреже + + + Port: + Порт: + + + Trust Level + Ниво Поверења + + + + Cancel + Поништи + + + + OK + У Реду + + + + Peer Info + + + + Peer Details + Подаци Мреже + + + + Peer ID + + + + + Last Contact + + + + + Version + + + + + RetroShare ID + + + + + Status + Статус + + + + Dynamic DNS + + + + + Addresses list + + + + + None + + + + + Marginal + + + + + Full + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Deny Friend + + + + + Make Friend + + + + + Certificate + + + + + + Sign GPG key + + + + + Friend Details + + + + + Local Address + + + + + External Address + + + + + + Port + + + + + Your trust in this peer is: + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + Apply and Close + + + + + + RetroShare + RetroShare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + ConnectDialog + + Peer Details + Подаци Мреже + + + Cancel + Поништи + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + Име + + + + Description + + + + + Type: + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + Поништи + + + + Create + + + + + RetroShare + RetroShare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + RetroShare + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + Име + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + Поништи + + + + Create + + + + + RetroShare + RetroShare + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + RetroShare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Име + + + + Authenticated Messages + + + + + Cancel + Поништи + + + RetroShare + RetroShare + + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Description + + + + + Type: + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Create + + + + + CreateForumMsg + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Close + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + RetroShare + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + RetroShare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + CryptographyDialog + + RSA Key Size + RSA Величина Кључа + + + Rijndael Block size + Rijndael Величина Блока + + + 128 Bits + 128 Бита + + + 192 Bits + 192 Бита + + + 256 Bits + 256 Бита + + + Rijndael Key Size + Rijndael Величина Кључа + + + Rijndael Mode + Rijndael Мод + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + Rijndael Padding + Rijndael Пуњење + + + PKCS7 + PKCS7 + + + Zeros + Zeros + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Rijndael Feedback Size + Rijndael Величина Повратне Спреге + + + Key Size: + Величина Кључа: + + + Block Size: + Величина Блока: + + + Feedback Size: + Величина Повратне Спреге: + + + Mode: + Мод: + + + Padding: + Пуњење: + + + RetroShare + RetroShare + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + Детаљи + + + + + General + Опште + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + Датум + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + У Реду + + + + Cancel + Поништи + + + + Rating + + + + + File Name + Име Фајла + + + + Not Rated + + + + + No Comments + + + + + DirectoriesDialog + + Shared Directories + Дељени Директоријуми + + + Other Directories + Остали Директоријуми + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Долазећи Фајлови</span></p></body></html> + + + Add Shared Directory + Додај Дељени Директоријум + + + + DirectoriesPage + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + Дељени Директоријуми + + + + Edit Share + + + + Incoming files + Долазећи Фајлови + + + + + Browse + + + + Add Shared Directory + Додај Дељени Директоријум + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + + + + + EditChanDetails + + + Channel Details + + + + + Cancel + Поништи + + + + OK + У Реду + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + Поништи + + + + OK + У Реду + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + Status + Статус + + + + Person + Особа + + + + Auto Connect + Аутоматско Конектовање + + + + Trust Level + Ниво Поверења + + + + Peer Address + Адреса Мреже + + + + Organisation + Организација + + + + Location + Локација + + + + Country + Земља + + + + Person Id + ID Особе + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + + + # + + + + + Last Contact + + + + + Auth Code + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + %1 KB + %1 KB + + + File Name + Име Фајла + + + Size + Величина + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + Величина + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + Поништи + + + + OK + У Реду + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + Пошаљи + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + Разно + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + Сакри + + + + Expand + + + + + + RetroShare + RetroShare + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + + Date + Датум + + + + + Title + Назив + + + + + Start New Thread + + + + New Message + Нова Порука + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + Ресет + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + Пријатељи + + + + Status + Статус + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + Пошаљи + + + + Clear Chat History + + + + + + Add Friend + + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + Локација + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + Чет + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + Сачувај Сертификат + + + + Certificates (*.pqi) + Сертификати (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + Опште + + + Network + Мрежа + + + Directories + Директоријуми + + + Server + Сервер + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Server + Сервер + + + + Status + Статус + + + + Accept + Прихвати + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + Изабери Пријатеља Од Поверења + + + + Certificates (*.pqi *.pem) + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + Load Trusted Certificate (Optional) + Учитај Сертификат Од Поверења (Опционо) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Пријатељ</span></p></body></html> + + + Select File + Изабери Фајл + + + Generate New Certificate + Генериши Нови Сертификат + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + Име + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + Локација + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + + GeneralDialog + + Style + Стил + + + Language + Језик + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">При промени језика морате рестартовати RetroShare! </p></body></html> + + + Style Sheet + Стил Странице + + + Misc + Разно + + + + GeneralPage + + Keys manager + Менаџер Кључева + + + Style + Стил + + + Choose RetroShare's interface style + Изабери Стил Интерфејса RetroShare-a + + + Language + Језик + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">При промени језика морате рестартовати RetroShare! </p></body></html> + + + Choose the language used in RetroShare + Изабери Језик За RetroShare + + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + Разно + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Прим: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Послато: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Пријатељи + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + Назив + + + + Description + + + + + Reset + Ресет + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + Име + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + Датум + + + + Size + Величина + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + + Search + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Home + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + Unable to Open Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + Ресет + + + + + Copy + + + + + Remove + Уклони + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + Пошаљи + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + InviteDialog + + Cancel + Поништи + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + Преузимање + + + + Expand + + + + + Hide + Сакри + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + Од + + + + Show + Прикажи + + + + 101-200 + 101-200 + + + + 201-300 + 201-300 + + + + 301-400 + 301-400 + + + + 401-500 + 401-500 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + LogDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> + +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +</body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="ABOUT"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">About RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare is a private peer to peer communication platform created by Dr. Bob.This program enables you to securely share files and chat with your friends (and no-one else!).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">For more information, and the latest release go to http://www.lunamutt.com.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="START"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Quick Start Guide to RetroShare </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If this is your first time using Retroshare, it is recommended that you readthis guide for instructions on how to get started. The first step is:<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Connecting to Your Friends</span></a>. Once you have managed this you can <a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">Download Files</span></a> and<a href="#START-SHARE"><span style=" text-decoration: underline; color:#0000ff;">Share with Others</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Some of the key concepts related to ensuring your sharing remains private aredescribed in the <a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">Frequently Asked Questions</span></a>. Some Key security questions are:<a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">What is a Web of Trust?</span></a>, <a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">Should I Sign this Certificate?</span></a>, and finally<a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">What does "Trust" Mean?</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It is also worthwhile reading the <a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">GUI Overview</span></a>which describes the featureson available through the User Interface.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Connecting to your Friends </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">There are four steps to connecting to a Friend:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Get Friend's Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Load Certificate </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Sign Certificate </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect to Friend.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The instructions might initially appear long and daunting, however thesesteps are required to ensure that your sharing is private and secure.These steps are only required a couple of times, to add new friends, and become quite straight forward after the first time.</p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (1) EXCHANGE CERTIFICATES </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Before you can connect, you need send your certificate to your friend, and get your friends certificate. Follow these steps to get your certificate:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on Your Certificate to Select it. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click on the "Export Friend" Button to bring up a file save dialog. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select directory to save the certificate to. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Enter desired filename. (with a file type of .pqi), and Click OK. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Email this File to your Friend. (It is recommended you put the certificate in a zip file before sending, as some email programs don't transmit the file correctly). </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Ask your friend to do the same. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Once you have received your friend's certificate, removed it from the zip file and saved it to disk, you can proceed to step (2).</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: This exchange of certificates is only necessary to get you started.Once you are connected to some friends the exchange of certificates becomeautomated by the autoDiscovery system. See<a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">GUI: Connecting</span></a> for more information.------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (2) LOAD YOUR FRIEND'S CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Go to the "Connect" Tab </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Import Friend" </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select your friends certificate file, then click "Okay". Their certificate should appear in the top window of the "Connect" Tab.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">------------------------------------------------------------------------<br /><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (3) SIGN CERTIFICATE </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Select their Certificate by clicking on their name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click "Configure Friend" Button. This will bring up a configuration window. which allows you to look at the details of the certificate. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click the "Sign Certificate" button near the bottom of the "Certificate Configuration" Window. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Now close the window by clicking on the "Done" button. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Your Friends certificate should now say "Trusted (S)", indicating it is ready for connections.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can only share with "Trusted" Peers. You must sign your Friend'scertificate to prove that you know the certificate belongs to your Friend. Do not sign any/all certificates - only the people youtrust. For more information see: <br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br />------------------------------------------------------------------------<br /><br /> <br /></p> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600;"><span style=" font-size:small;"> (4) AUTOCONNECT TO PEER </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Finally You need to activate the connection: </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Click in the Box, next to your friends Name. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A Tick should appear in the box, a connection will be started. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The "Offline" will change to "Online" when you have successfully connected.</li></ul> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remember: Your initial connection attempts will fail, until your friend has signed your certificate and ticked the Auto-Connect Box.This ensures that both peers trust each other, and stops random peopleaccessing your files.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>. <br />------------------------------------------------------------------------<br /><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-DOWNLOAD"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Downloading Files </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have connected to friends, you can download their shared files.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can search for the files you want using either:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) File Listing Tab: This gives you a directory view of the files being shared by your peers. Double clickon the directory name (not the arrow) to diplay its subdirectories and files.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 1: This can take up to 5 seconds to fetch the information for your peer.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 2: If the directory is empty, or the person is offline, then the request will silently fail.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Search Tab: Retroshare also allows you to search your peers computers for filenames. Enter yourterm(s) in the search box at the top of the TAB and click the "Search" button. This willsearch all of the peers that you are currently connected to.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 3: If any matching files are found they will be displayed within 5 - 10 seconds.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Once you have found the files you want, Select the file(s), and click "Download" to begin the download process.If you click over the "File Transfer" TAB, the status of the files will appear.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NOTE 4: The files can take up to 10 seconds to appear in the transfer window.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="START-SHARING"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Sharing Files </span><span style=" font-size:small;"> </span></p></td></tr></table><p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can specify which files you want to share in the "Config" Tab.In the "Share Directories" section, click the "Add Directory" Button, and select the directory you want to share.The files and subdirectories will become available for you peers.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can remove a directory from the Shared Directories List by clicking onthe directory name in the list, and then clicking "Remove Directory".</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="GUI"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Gui Overview (Tab Description) </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The GUI is divided up into several sections which can be accessed by clicking on the Tabs along the top of the main window. </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><br /></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:1; text-indent:1px;"> </p> +<ul style="-qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Connect: Manage Connections and Friends. (<a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">getting started</span></a> and <a href="#GUI-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Listing: A directory view of available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Search: Search for available files. (<a href="#START-DOWNLOAD"><span style=" text-decoration: underline; color:#0000ff;">downloading</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Messages: For Sending/Recving Message. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Channels: A broadcast/subscription system. (Coming Soon) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> File Transfer: Listing of Current and completed Transfers. </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Config: Specify of share diectories and IP Addresses. (<a href="#GUI-CONFIG"><span style=" text-decoration: underline; color:#0000ff;">more info</span></a>) </li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> About: Help and other Information. </li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Chat: Accessed by the clicking on the "Chat" button.</li></ul> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONNECT"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Connect Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Connect TAB consists of two windows. The upper windowshows a list of your friends. This window indicates each friendscurrent trust level, as well as their connection state.The "Trust_Lvl" Column indicates if the certificate has beenAuthenticated using the web of trust. You can only connect to "Trusted" certificates. Tick the "Auto_Connect" box to connect to your trusted friends.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The lower window provides a list of the friends of your friends.This window shows the neighbour's name and how long ago they attempted to connect to you. This window is automatically populatedby the autoDiscovery system, and should be used to expand yourretroShare network. A word of warning: Do not automatically trust (or sign) anyonethat appears in this window. First verify by some other means (email/phone)that certificate belongs to the person you think it does.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Use the "Neighbour List" window to expand your friend list. Select the desired entry in the lower window by clicking on it, then click the "Add to Friends" Button to move it to the upper window.Likewise the "Remove from Friends" button moved a person from the upper window to the lower window.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The "Configure Friend" Button opens a Certificate Configuration window.This window can be used to examine the certificate details, sign the certificate or manually change the peer's IP Address.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">See Also:<br /><a href="#START-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">Getting Started: Connecting to your friends</span></a>.<br /><a href="#FAQ-CONNECT"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Why won't it Connect?</span></a>.<br /><a href="#FAQ-SIGN"><span style=" text-decoration: underline; color:#0000ff;">FAQ: Should I Sign this Certificate?</span></a>.<br /><a href="#FAQ-TRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What does "Trust" Mean?</span></a>.<br /><a href="#FAQ-WEBOFTRUST"><span style=" text-decoration: underline; color:#0000ff;">FAQ: What is a Web of Trust?</span></a>. <br /></p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="GUI-CONFIG"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">The Config Tab </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Configuration Tab allows you to select the share directories, as well as the directory that downloaded files are saved to.<br />See <a href="#STARTUP-SHARING"><span style=" text-decoration: underline; color:#0000ff;">Sharing you Files</span></a> for details. </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The Config Tab also allows you to control the IP Address and Portused by RetroShare. Under most cirumstances you do not need to changethese setting. If you are behind a firewall and can setup a forwarded port, the selected IP Address and Port should be specified here.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:medium; font-weight:600; background-color:#aaaaaa;"><a name="FAQ"></a><span style=" font-size:medium;"> </span><span style=" font-size:medium;">Frequently Asked Questions </span><span style=" font-size:medium;"> </span></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">How does the security/privacy work? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShares uses a Web of Trust Authentication system to ensurethat your "friends" are your friends, and uses SSL to encryptthe communcications between peers. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-WEBOFTRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What is a Web of Trust? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A Web of Trust relies on a collection of peers to identify eachother. Look it up on the Web!</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-TRUST"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">What does "Trust" Mean in RetroShare?</span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anyone can generate a certificate, with any name on it. So howdo you know that the certificate that claims to be from "Joe Bloggs"is really from your mate Joe. This is the "AuthenticationProblem". RetroShare uses a Web of Trust to Authenticate your peers.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><a name="FAQ-SIGN"></a><span style=" font-size:small;"> </span><span style=" font-size:small;">Should I Sign this Certificate? </span><span style=" font-size:small;"> </span></p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You should only sign a certificate if you are completely surethat it comes from the "right" person. If you sign a certificateyou are "Authenticating" the person to yourself and others.If you sign certificates that you haven't checked, then you aredestroying your own privacy and security.</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">How do you verify a certificate? Use an alternative method ofcommunication to send the certificate: E.g. email or USB stick. This will improve you confidence that the certificate belongsto the correct person. </p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#cccccc"> +<p style=" margin-top:12px; margin-bottom:4px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:small; font-weight:600; background-color:#cccccc;"><span style=" font-size:small;"> </span><a name="FAQ-CONNECT"></a><span style=" font-size:small;">W</span><span style=" font-size:small;">hy won't it Connect?</span><span style=" font-size:small;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td></tr></table> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A connection can fail for a number of reasons:</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(1) Failed Authentication. Have both peers signed each otherscertificates? </p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(2) Firewalls. If both peers are behind firewalls then they cannotconnect directly. RetroShare has a built in proxy system to circumventfirewalls - However this can only function if both peers can connect to a common third party that is not behind a firewall. Thisis the most likely reason for initial connections to fail. The only solution to find a common friend that isn't firewalled (know anyone with Broadband?)</p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(3) IP Addresses are wrong. You can manually examine and change these using the Certificate configuration.</p> +<table border="0" width="100%" cellspacing="2" cellpadding="2"> +<tr> +<td bgcolor="#aaaaaa"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#aaaaaa;">Quick Links: </p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#ABOUT"><span style=" text-decoration: underline; color:#0000ff;">About</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#START"><span style=" text-decoration: underline; color:#0000ff;">Getting Started</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#GUI"><span style=" text-decoration: underline; color:#0000ff;">Gui Basics</span></a></p></td> +<td bgcolor="#cccccc"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#cccccc;"><a href="#FAQ"><span style=" text-decoration: underline; color:#0000ff;">FAQ</span></a></p></td></tr></table> +</body></html> + + + + MainWindow + + + Network + Мрежа + + + + Friends + Пријатељи + + + + + Transfers + Трансфер + + + + + Messages + Поруке + + + + + Channels + Канали + + + + + Options + Опције + + + + Hide + Сакри + + + + Show + Прикажи + + + + RetroShare + RetroShare + + + + RetroShare %1 a secure decentralised communication platform + + + + + Search + + + + + Files + + + + + Blogs + + + + + Links Cloud + + + + + Unfinished + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Show/Hide + + + + + Status + Статус + + + + Minimize + + + + + Maximize + + + + + &Quit + + + + + Chat + Чет + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + Add Shared Directory + Додај Дељени Директоријум + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Help + Помоћ + + + + + Forums + + + + + + + + You have %1 new message + + + + + Open Messages + + + + + Applications + + + + Settings + Подешавања + + + + Plugins + + + + + Really quit ? + + + + + Do you really want to exit RetroShare ? + + + + + Add Friend + + + + + Add a Friend Wizard + + + + + Add Share + + + + + Quit + + + + + + Quick Start Wizard + + + + + SMPlayer + + + + + Messenger + + + + + MainWindow + + + + + About + + + + + MessageComposer + + + + Compose + + + + + + Contacts + + + + + Search for Name: + + + + + Reset + Ресет + + + + Send To: + Пошаљи: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + Препоручени Фајлови + + + + File Name + Име Фајла + + + + Size + Величина + + + Sources + Изворишта + + + + Hash + + + + + Send + Пошаљи + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + Сачувај + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + RetroShare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + Misc + Разно + + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + New Message + Нова Порука + + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоручени Фајлови</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + Име Фајла + + + + Size + Величина + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + Преузимање + + + + Download all + + + + + Hide + Сакри + + + + Expand + + + + + File + + + + + Files + + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + Нова Порука + + + + Compose + + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + + New Message + Нова Порука + + + + Quick View + + + + + Reply to Message + Одговори На Поруку + + + + Remove Message + Уклони Поруку + + + + + Date + Датум + + + + + + From + Од + + + Size + Величина + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоручени Фајлови</span></p></body></html> + + + File Name + Име Фајла + + + Sources + Изворишта + + + + Forward selected Message + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + + + + + Forward Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + Преузимање + + + + Empty trash + + + + Hide + Сакри + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + + + + + + Total: + + + + + + Reply to All + + + + + Reply + + + + + Reply all + + + + + Foward + + + + + Delete + + + + + Compose + + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + + + + Inbox + + + + + + + + Outbox + + + + + Draft + + + + + + Sent + + + + + + Subject + + + + + Reset + Ресет + + + + Attachments + + + + + + Content + + + + + + + + + Tags + + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + + Print + + + + + MessagesPopupDialog + + New Message + Нова Порука + + + Reply to Message + Одговори На Поруку + + + Remove Message + Уклони Поруку + + + Messages + Поруке + + + From + Од + + + Date + Датум + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоручени Фајлови</span></p></body></html> + + + File Name + Име Фајла + + + Size + Величина + + + Sources + Изворишта + + + Remove + Уклони + + + + MessengerDirModel + + Size + Величина + + + Rank + Категорија + + + + MessengerSharedFiles + + Download + Преузимање + + + + MessengerWindow + + + Expand all + + + + + Collapse all + + + + + Chat + Чет + + + + Message Friend + + + + + Peer Details + Подаци Мреже + + + + Recomend this Friend to... + + + + + Export Friend + Извези Пријатеља + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + Сачувај Сертификат + + + + Certificates (*.pqi) + Сертификати (*.pqi) + + + + Connect To Friend + + + + Remove Friend + Уклони Пријатеља + + + + Click to Change your Avatar + + + + + Search Friends + + + + + Reset + Ресет + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Date + Датум + + + + MsgItem + + + Reply to Message + Одговори На Поруку + + + + Remove Item + + + + + + Expand + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Сакри + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Порука</span></p></body></html> + + + Date + Датум + + + Rank + Категорија + + + From + Од + + + Title + Назив + + + Msg + Пор + + + Count + Бројање + + + Size + Величина + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Текст Поруке</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоручени Фајлови</span></p></body></html> + + + Delete Channel + Обриши Канал + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Порука</span></p></body></html> + + + Date + Датум + + + Rank + Категорија + + + From + Од + + + Title + Назив + + + Msg + Пор + + + Count + Бројање + + + Size + Величина + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Текст Поруке</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Препоручени Фајлови</span></p></body></html> + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + Load Certificate + Учитај Сертификат + + + Select a pem/pqi File + Изабери pem/pqi Фајл + + + File Not Found + Фајл Није Нађен + + + %1 does not exist. Would you like to create it? + %1 не постоји. Да ли желите да га направите? + + + Failed to Create File + Неуспешно Прављење Фајла + + + Unable to create %1 [%2] + Није Могуће Направити %1 [%2] + + + Accept + Прихвати + + + Select Certificate + Изабери Сертификат + + + + Network + Мрежа + + + Trust + Поверење + + + + + + Name + Име + + + Peer Address + Адреса Мреже + + + Organisation + Организација + + + Location + Локација + + + Country + Земља + + + + + Cert Id + Серт ID + + + Peer Details + Подаци Мреже + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Unknown + + + + + Has authenticated me + + + + + Authentication matrix + + + + + Network View + + + + + Copy RetroShare Link + + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + + yourself + + + + RetroShare + RetroShare + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Show keys that are not validated by the GPG web of trust + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + External ip address finder + + + + + Clear + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + Опције Брзине + + + Max Total Data Rate (KB/S): + Макс Тотална Брзина (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Брзина По Особи (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Сакри Подешавања + + + Show Settings + Прикажи Подешавања + + + Settings + Подешавања + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Пријатељи + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + У Реду + + + + Cancel + Поништи + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + Уклони Све + + + + Options + Опције + + + + NotifyDialog + + Channels + Канали + + + Chat + Чет + + + Messages + Поруке + + + New Message + Нова Порука + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + Канали + + + + Forums + + + + + Chat + Чет + + + + Blogs + + + + + Messages + Поруке + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + Нова Порука + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + OptionsDlg + + Cancel + Поништи + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + Remove Friend + Уклони Пријатеља + + + + Chat + Чет + + + + Start Chat + + + + Organisation + Организација + + + + Location + Локација + + + Country + Земља + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Send + Пошаљи + + + + Cancel + Поништи + + + + Peer ID: + + + + + Write Message + + + + + Status: + + + + + Trust: + + + + + Name: + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + Сакри + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Пријатељи + + + + PeersDialog + + Chat + Чет + + + Export Friend + Извези Пријатеља + + + Remove Friend + Уклони Пријатеља + + + Save Certificate + Сачувај Сертификат + + + Certificates (*.pqi) + Сертификати (*.pqi) + + + Status + Статус + + + Person + Особа + + + Location + Локација + + + Peer Details + Подаци Мреже + + + RetroShare + RetroShare + + + Send + Пошаљи + + + Friends + Пријатељи + + + + PeersFeed + + Save Certificate + Сачувај Сертификат + + + Certificates (*.pqi) + Сертификати (*.pqi) + + + Friends + Пријатељи + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + Уклони + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + + Date + Датум + + + + + Location + Локација + + + + Size + Величина + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + Уклони + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + RetroShare + RetroShare + + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + Пошаљи + + + + Close + + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + RetroShare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PreferencesWindow + + General + Опште + + + Server + Сервер + + + Options + Опције + + + Cancel + Поништи + + + OK + У Реду + + + Help + Помоћ + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + + + + + RetroShare + RetroShare + + + + Error : cannot get peer details. + + + + + + Name + Име + + + + Peer ID + + + + + Size + Величина + + + + Profile View + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + Name + Име + + + Date + Датум + + + Size + Величина + + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + Уклони + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + Опште + + + + Directories + Директоријуми + + + + Server + Сервер + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + Чет + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RemoteDirModel + + Size + Величина + + + Rank + Категорија + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Изабран Је Погрешан Код Језика: + + + + Invalid GUI style specified: + Погрешан GUI Стил Је Изабран: + + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + + Download + Преузимање + + + Broadcast on Channel + Бродкест На Каналу + + + Recommend to Friends + Препоручено Пријатељима + + + + Remove + Уклони + + + + Remove All + Уклони Све + + + + Download Notice + + + + + Enter a keyword here (at least 3 char long) + + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + + Folder + + + + + New RetroShare Link(s) + + + + + Size + Величина + + + + Any + + + + + Archive + + + + + Audio + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Video + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + Име Фајла + + + + File Size + + + + + Close all Search Resullts + + + + + Download Selected + + + + + Close All Search Results + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + + + + + Reset + Ресет + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Sources + Изворишта + + + + Type + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Results + + + + + Search Id + + + + + SendLinkDialog + + Send + Пошаљи + + + + ServerDialog + + Transfer Rates + Брзина Трансфера + + + Port: + Порт: + + + + ServerPage + + Change + Restart Server + Промени + Рестартује Сервер + + + Server Settings + Подешавање Сервера + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Спољашња Адреса:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Локална Адреса:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Порт:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Download (KB/s) + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + + kB/s + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + Порт: + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + Misc + Разно + + + behinde Firewall + иза Фајервола + + + Forwarded External Port + Пролсеђени Спољашњи Порт + + + + Transfer Rates + Брзина Трансфера + + + + Settings + + Settings + Подешавања + + + + Options + Опције + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + Чет + + + + Appearance + + + + + Sound + + + + + Cancel + Поништи + + + Apply + Задај + + + + OK + У Реду + + + + General + Опште + + + Network + Мрежа + + + + Server + Сервер + + + + Directories + Директоријуми + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + Friends + Пријатељи + + + + OK + У Реду + + + + Cancel + Поништи + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + Поништи + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + RetroShare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + Уклони + + + Add Shared Directory + Додај Дељени Директоријум + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Преузимање + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + Ресет + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + RetroShare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + Статистике + + + + Download + Преузимање + + + + Session: + Сесија: + + + + + Downloaded: + Преузето: + + + Average Downloadspeed: + Просечна Брзина Преузимања: + + + + + Count of Downloads: + Број Преузимања: + + + + + + Overall + Укупно + + + + Upload + Слање + + + + + + Session + Сесиа + + + + Uploaded: + Послато: + + + Average Uploadspeed: + Просечна Брзина Слања: + + + + + Count of Uploads: + Прој Слања: + + + + Uploaded + Послато + + + + + + + Connections: + Конекције: + + + + + + Peers: + Мреже(пирови): + + + Misc + Разно + + + + Uptime: + Време рада: + + + Overall: + Укупно: + + + + + Uptime + Време рада + + + + Records + Забелешке + + + + Uploadspeed: + Брзина Слања: + + + + Downloadspeed: + Брзина Преузимања: + + + + + Show Settings + Прикажи Подешавања + + + + Reset + Ресет + + + + Receive Rate + Брзина Примања + + + + Send Rate + Брзина Слања + + + + Always On Top + Увек На Врху + + + + 100 + 100 + + + + % Opaque + % Непровидан + + + + Changes the transparency of the Bandwidth Graph + Промени Провидност Графика Протока + + + + Save + Сачувај + + + + Cancel + Поништи + + + + Hide Settings + Сакри Подешавања + + + + %1 days + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Since: + + + + + Cumulative + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + У Реду + + + + Cancel + Поништи + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + Стил + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + + Delete FeedItem + + + + + SubFileItem + + File Name + Име Фајла + + + + + + Play File + Пусти Фајл + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + Преузимање + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + RetroShare + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + Поништи + + + + Clear Completed + Очисти Завршено + + + + + Status + Статус + + + + Completed + Завршено + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Преузимање:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + + + + + Active + + + + + Outstanding + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Слање:</span></p></body></html> + + + + + Name + i.e: file name + Име + + + + + Size + i.e: file size + Величина + + + + Speed + i.e: Download speed + Брзина + + + Progress + i.e: % downloaded + Прогрес + + + + Progress / Availability + i.e: % downloaded + + + + + Sources + i.e: Sources + Изворишта + + + + Core-ID + + + + + Progress + i.e: % uploaded + Прогрес + + + + Speed + i.e: upload speed + Брзина + + + + Transferred + + + + + Hash + + + + + Play + + + + + Pause + + + + + Resume + + + + + Force Check + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Priority (Speed)... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + Queued + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + RetroShare + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + Speed / Queue position + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Peer + i.e: user name + + + + + Router Statistics + + + + + Router Requests + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Move in Queue... + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + version: + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + Величина + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + Поверење + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + File Name + Име Фајла + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Download + Преузимање + + + Broadcast on Channel + Бродкест На Каналу + + + Recommend to Friends + Препоручено Пријатељима + + + Remove + Уклони + + + Remove All + Уклони Све + + + Size + Величина + + + Sources + Изворишта + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + У Реду + + + + Cancel + Поништи + + + + Yes + Да + + + + No + Не + + + + Help + Помоћ + + + + Retry + Покушај Поново + + + + Show Log + Прикажи Лог + + + + Show Settings + Прикажи Подешавања + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + + moreinfo + + Details + Детаљи + + + OK + У Реду + + + Name + Име + + + Value + Вредност + + + diff --git a/retroshare-gui/src/lang/retroshare_sv.qm b/retroshare-gui/src/lang/retroshare_sv.qm new file mode 100644 index 000000000..466e28e18 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_sv.qm differ diff --git a/retroshare-gui/src/lang/retroshare_sv.ts b/retroshare-gui/src/lang/retroshare_sv.ts new file mode 100644 index 000000000..d4a9ed208 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_sv.ts @@ -0,0 +1,17033 @@ + + + + + + + Arial + Arial + + + + @default + + Arial + Arial + + + + AboutDialog + + + About RetroShare + + + + + About + Om + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + Filtyp (ändelse): + + + + Use default command + Använd standardkommando + + + + Command + Kommando + + + + RetroShare + RetroShare + + + + Sorry, can't determine system default command for this file + + Ursäkta, kan inte avgöra systemets standardkommando för denna fil + + + + AddFileAssotiationDialog + + File type(extension): + Filtyp (ändelse): + + + Use default command + Använd standardkommando + + + Command + Kommando + + + RetroShare + RetroShare + + + Sorry, can't determine system default command for this file + + Ursäkta, kan inte avgöra systemets standardkommando för denna fil + + + + AddFriendDialog + + Cancel + Avbryt + + + Done + Färdig + + + Load From File + Läs in från fil + + + RetroShare + RetroShare + + + Certificate Load Failed + Inläsning av certifikat misslyckades + + + Add a Friend + Lägg till en vän + + + + AddFriendWizard + + Add Friend to my netowork Wizard + Lägg till vän till min nätverksguide + + + < Back + < Tillbaka + + + Next > + Nästa > + + + Cancel + Avbryt + + + I have a .pqi/.pem file received from a Friend + Jag har en .pqi/.pem-fil som jag tagit emot från en vän + + + I have Key received from a Friend + Jag har en nyckel som jag tagit emot från en vän + + + I want to invite a friend to my RetroShare network + Jag vill bjuda in en vän till mitt RetroShare-nätverk + + + Browse + Bläddra + + + RetroShare + RetroShare + + + Certificate Load Failed + Inläsning av certifikat misslyckades + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + Titel: + + + + Url: + Url: + + + Score: + Poäng: + + + + +2 Great! + +2 Jättebra! + + + + +1 Good + +1 Bra + + + + 0 Okay + 0 Okej + + + + -1 Sux + -1 Dåligt + + + + -2 Bad Link + -2 Trasig länk + + + + Add Anonymous Link + Lägg till anonym länk + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + Avbryt + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Cancel + Avbryt + + + + Search + Sök + + + RetrosShare: Advanced Search + RetrosShare: Avancerad sök + + + + Add a further search criterion. + Lägg till ytterligare sökkriterium + + + Add a selection criterion + Lägg till sökkriterium + + + + Reset the search criteria. + Återställ sökkriterium + + + Reset + Återställ + + + + Cancels the search. + Avbryter sökningen + + + + Perform the advanced search. + Utför avancerad sökning + + + + Search Criteria + Sökkriterium + + + + AppearanceDialog + + Language + Språk + + + Style + Stil + + + Style Sheet + Stilmall + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + This is what I think the translation should be.... + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Välj språket som används i RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ändringar av språk kommer utföras vid omstart av RetroShare!</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Välj RetroShares gränssnittsstil</p></body></html> + + + + AppearancePage + + + Language + Språk + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Välj språket som används i RetroShare</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ändringar av språk kommer utföras vid omstart av RetroShare!</p></body></html> + + + + Style + Stil + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Välj RetroShares gränssnittsstil</p></body></html> + + + + Style Sheet + Stilmall + + + + ApplicationWindow + + RetroShare %1 + RetroShare %1 + + + Peers + Klienter + + + Transfers + Överföringar + + + Messages + Meddelanden + + + Blog Feed + Bloggflöde + + + + Games Launcher + Spelstartare + + + + Photo View + Fotovisare + + + + Shared Calendars + Delade kalendrar + + + + Hide + Dölj + + + + Show + Visa + + + + + RetroShare + RetroShare + + + Library + Bibliotek + + + + Statistics + Statistik + + + + AttachFileItem + + + Form + Formulär + + + File Name + Filnamn + + + + %p Kb + %p Kb + + + + Cancel Download + Avbryt nedladdning + + + + AuthorizationDialog + + Authenticate + Autentisera + + + OK + OK + + + Cancel + Avbryt + + + + BandwidthGraph + + + + Show Settings + Visa inställningar + + + + Reset + Nollställ + + + + Always on Top + Alltid överst + + + + Style + Stil + + + + 100 + 100 + + + + Save + Spara + + + + Cancel + Avbryt + + + + Since: + Sedan: + + + + Hide Settings + Dölj inställningar + + + + RetroShare Bandwidth Usage + RetroShar Bandbreddsanvändning + + + + Receive Rate + Mottagningshastighet + + + + Send Rate + Sändningshastighet + + + + Changes the transparency of the Bandwidth Graph + Ändrar transparensen av bandbreddsgrafen + + + + % Opaque + % Ogenomskinlig + + + + BgBoard + + QBackgammon + QBackgammon + + + + BgWidget + + Player + Spelare + + + QBackgammon + QBackgammon + + + wins! + vinner! + + + + BgWindow + + Ready + Redo + + + QBackgammon + QBackgammon + + + &New Game + &Nytt spel + + + Ctrl+O + Ctrl+O + + + &Undo + &Ångra + + + Ctrl+Z + Ctrl+Z + + + Resign + Ge upp + + + Options + Alternativ + + + Hint + Tips + + + Quit + Avsluta + + + About + Om + + + &File + &Fil + + + Are you sure you want to start a new game? +The current one will be lost. + Är du säker att du vill starta ett nytt spel? +Aktuellt spel kommer att gå förlorat. + + + Are you sure you want to resign? + Är du säker att du vill ge upp? + + + Are you sure you want to quit? + Är du säker att du vill avsluta? + + + QBackgammon +(C) Daren Sawkey 2006 +daren@sawkey.net +Released under GPL + QBackgammon +(C) Daren Sawkey 2006 +daren@sawkey.net +Släppt under GPL + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + Popularitet + + + + Last Post + Senaste inlägg + + + + Blog ID + + + + + Blog Description + + + + + Cancel + Avbryt + + + + OK + OK + + + + Close + Stäng + + + + BlogDialog + + Form + Formulär + + + Blogs + Bloggar + + + Last Month + Senaste månaden + + + Last Week + Senaste veckan + + + Last Day + Idag + + + All Users + Alla användare + + + Jimmy + Jimmy + + + John + John + + + Jacki + Jacki + + + No Feeds + Inga flöden + + + Post Blog + Posta blogg + + + + BlogMsgItem + + + Form + Formulär + + + + Remove Item + Radera objekt + + + Connected + Ansluten + + + + Expand + Utöka + + + + Subject + Ämne + + + subjectLabel + ämnesEtikett + + + + Play Media + Spela media + + + Long + message here + Långt + meddelande här + + + + BlogNewItem + + Form + Formulär + + + + Remove Item + Radera objekt + + + name + namn + + + + Subscribe to Blog + + + + + Expand + Utöka + + + + Blog Decscription + + + + + BlogsDialog + + + Form + Formulär + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + Lägg till + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + Post To Channel + Posta till kanal + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + Avsluta prenumereration + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + Prenumerera + + + + + Create New Blog + + + + + Name + + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + Formulär + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + Ta bort prenumeration från kanal + + + + Comment + Kommentar + + + + Remove Item + Radera objekt + + + + + Expand + Utöka + + + TextLabel + TextEtikett + + + + Comments here + + + + + Hide + Dölj + + + + CalDialog + + + Name: + Namn: + + + + Location: + Plats: + + + + Remove + Ta bort + + + + Form + Formulär + + + + Local Calendars + Lokala kalendrar + + + + Shared Calendar List + Lista delade kalendrar + + + + Share Details + Dela detaljer + + + + ... + ... + + + + Status: + Status + + + + Private + Privat + + + + Public + Publik + + + + Allow List: + Tillåten-lista: + + + + <Disabled> + <Avaktiverad> + + + + Add + Lägg till + + + + Peer Calendars + Klienters kalendrar + + + + CallToaster + + Message + Meddelande + + + + CertificatePage + + + Certificate files + Certifikatfiler + + + Use XPGP certificates saved in files. + Använd XPGP-certifikat sparade i filer + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + Du måste skapa en fil med ditt certifikat och ge det till din vän. Alternativt kan du använda en tidigare skapad fil. + + + + Export my certificate... + + + + Specify path to your friend's certificate in the box below + Ange sökväg till din väns certifikat i rutan nedan + + + + Browse + Bläddra + + + + Select Certificate + Välj certifikat + + + Certificates (*.pqi *.pem) + Certifikat (*.pqi *.pem) + + + + Please choose a filename + + + + + + + + RetroShare + RetroShare + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + Certifikatsfil skapad utan fel + + + + + Sorry, certificate file creation failed + Tyvärr, fel uppstod vid skapande av certifikatsfilen + + + + Certificate Load Failed:something is wrong with %1 + Laddning av certifikat felaktigt: något är fel med %1 + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + Laddning av certifikat felaktigt %1 hittades inte + + + + Use PGP certificates saved in files. + + + + + ChanCreateDialog + + Channel Name: + Kanalnamn: + + + Type: + Typ: + + + Public Channel (Signed) + Publik kanal (signerad) + + + Private Channel (Encrypted) + Privat kanal (krypterad) + + + Cancel Channel + Avbryt kanal + + + Create Channel + Skapa kanal + + + Create a new Broadcast Channel + Skapa en ny utsändningskanal + + + Create A New Broadcast Channel + Skapa en ny utsändningskanal + + + + ChanGroupItem + + Form + Formulär + + + Expand + Utöka + + + Channel Group + Kanalgrupp + + + + ChanMenuItem + + Form + Formulär + + + Expand + Utöka + + + Connected + Ansluten + + + Popularity: + Popularitet: + + + Fetches: + Hämtningar: + + + Available: + Tillgänglig: + + + Description + of Forum + Beskrivning +av forum + + + + ChanMsgDialog + + Recommended Files + Rekommenderade filer + + + Send To: + Skicka till: + + + Send + Skicka + + + Delete Channel + Ta bort kanal + + + Create Channel MSG + Skapa kanalmeddelande + + + &Left + &Vänster + + + C&enter + &Centrerad + + + &Right + &Höger + + + &Justify + &Justerad + + + Send this message now + Skicka detta meddelande nu + + + Toggle Contacts View + Visa/dölj kontakter + + + Save this message + Spara detta meddelande + + + Compose: + Skapa: + + + &File + &Fil + + + &New + &Ny + + + &Open... + &Öppna + + + &Save + &Spara + + + Save &As... + Spara S&om + + + &Print... + Skriv &ut.... + + + &Export PDF... + &Exportera till PDF + + + &Quit + &Avsluta + + + &Edit + &Redigera + + + &Undo + &Ångra + + + &Redo + &Gör om + + + Cu&t + &Klipp ut + + + &Copy + K&opiera + + + &Paste + K&listra in + + + &View + &Visa + + + &Contacts Sidebar + &Kontakter i sidofältet + + + &Insert + &Infoga + + + &Image + &Bild + + + Open File... + Öppna fil... + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-filer (*.htm *.html);;Alla filer (*) + + + Save as... + Spara som... + + + Print Document + Skriv ut dokument + + + Save Message + Spara meddelande + + + Message has not been Sent. +Do you want to save message ? + Meddelandet har inte skickats. +Vill du spara meddelandet ? + + + Choose Image + Välj bild + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Bildfiler som stöds (*.png *.jpeg *.jpg *.gif) + + + Add Extra File + Lägg till extra fil + + + File Name + Filnamn + + + Size + Storlek + + + Sources + Källor + + + Save + Spara + + + Compose + Skapa + + + Contacts + Kontakter + + + Subject: + Ämne: + + + Font size + Teckensnittsstorlek + + + Bold + Fet + + + Underline + Understruken + + + Italic + Kursiv + + + Attach File + Bifoga fil + + + Color + Färg + + + Alignment + Justering + + + Add a Image + Lägg till bild + + + Hash + Hash + + + Reply + Svara + + + + ChanMsgItem + + Form + Formulär + + + + Toggle Message Read Status + + + + + New + + + + + Download + Hämta + + + + Play + Spela + + + + Remove Item + Radera objekt + + + + Copy RetroShare Link + + + + Connected + Ansluten + + + + + Expand + Utöka + + + subjectLabel + ämnesEtikett + + + + Unsubscribe From Channel + Ta bort prenumeration från kanal + + + Play Media + Spela media + + + TextLabel + TextEtikett + + + Long + message here + Långt + meddelande här + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + Dölj + + + + ChanNewItem + + Form + Formulär + + + + Remove Item + Radera objekt + + + Connected + Ansluten + + + name + namn + + + + Subscribe to Channel + Prenumerera på kanal + + + + Expand + Utöka + + + + Channel Decscription + + + + Description + of Forum + Beskrivning +av forum + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelBrowserDialog + + Channels + Kanaler + + + Video + Video + + + 1 + 1 + + + Subscribe + Prenumerera + + + Remove Subscription + Ta bort prenumeration + + + Manage Subscription + Ändra prenumeration + + + Manage Channel + Ändra kanal + + + Quick Delete + Snabbradering + + + Channel Browser + Kanalbläddrare + + + Indie + Indie + + + Zoogie on Drums + Zoogie på trummor + + + Darkman Records + Darkman Records + + + Interviews with a Coder + Intervjuer med en programmerare + + + Miscellaneous + Blandat + + + Test Channel 1 + Testa kanal 1 + + + The Open Source Channel + Öppen källkodskanalen + + + Retroshare + Retroshare + + + Retroshare's Demo Channel + Retroshares demokanal + + + Channel Details + Kanaldetaljer + + + Popularity: + Popularitet: + + + Name of Selected Channel + Namn för vald kanal + + + Last update: + Senast uppdaterad: + + + 12.12.2007 10:48 UTC + 12.12.2007-10:48:UTC + + + Subscribers: + Prenumeranter: + + + Once a channel is selected in the tree (left), it's description, data, title and icon will appear here in this right hand side panel.<br><br>The user can subscribe / remove subscriptions or change to the relevant page to manage their channels as required via the context menu. + När en kanal är markerad i katalogträder (till vänster) kommer dess beskrivning; data, titel och ikon visas i panelen till höger.<br><br>Användaren kan prenumerera / avsluta prenumeration eller ändra sina kanaler som önskat via menyn. + + + + ChannelDetails + + + + Channel Details + Kanaldetaljer + + + + Channel Info + + + + + Popularity + Popularitet + + + + Last Post + Senaste inlägg + + + + Channel Name + Kanalnamn: + + + + Channel ID + + + + + Channel Description + + + + + Type + Typ + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Begränsad - Alla kan läsa, begränsad publicering (Privat publiceringsnyckel) + + + + Private - (Private Publish Key required to view Messages) + Privat . (Privat publiceringsnyckel krävs för att visa meddelanden) + + + + Cancel + Avbryt + + + + OK + OK + + + + Close + Stäng + + + + ChannelFeed + + + Create Channel + Skapa kanal + + + + Subscribe To Channel + Prenumerera på kanal + + + Form + Formulär + + + Channel Name + Kanalnamn: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + Add + Lägg till + + + Post To Channel + Posta till kanal + + + Title + Titel + + + Description + Beskrivning + + + Reset + Nollställ + + + + Display + Visa + + + + Unsubcribe To Channel + Ta bort prenumeration från kanal + + + + Unsubscribe + Avsluta prenumereration + + + + Subscribe + Prenumerera + + + + Set all to read + + + + + Enable Auto-download + + + + Create New Channel + Skapa ny kanal + + + Popularity + Popularitet + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + Prenumerera på kanal + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChannelStatsDialog + + 1 + 1 + + + Channel Statistics + Kanalstatistik + + + Subscribe to this channel to get news on the latest groovy happenings on Retroshare. + Prenumerera på denna kanal för att få nyheter om de senaste coola händelserna på Retroshare. + + + Last update: + Senast uppdaterad: + + + 12.12.2007 10:48 UTC + 12.12.2007-10:48:UTC + + + Popularity: + Popularitet: + + + Subscribers: + Prenumeranter: + + + + ChannelsDialog + + Browse Channels + Bläddra bland kanaler + + + My Subscriptions + Mina prenumerationer + + + My Channels + Mina kanaler + + + Channel Module + Kanalmodul + + + + ChatDialog + + Chat + Chatta + + + 1 + 1 + + + Send + Skicka + + + + ChatMsgItem + + Form + Formulär + + + TextLabel + TextEtikett + + + + Remove Item + Radera objekt + + + + Write a quick Message + + + + + Send Mail + Skicka mail + + + + Write Message + + + + + Send + Skicka + + + + Cancel + Avbryt + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + Allmänt + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + Stil + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ChatToaster + + Message + Meddelande + + + + ComboStatus + + Online + Ansluten + + + Away + Frånvarande + + + Busy + Upptagen + + + + ConclusionPage + + + Make Friend + Skapa vän + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + Alternativ + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + Fill details about your friend here + Fyll i detaljerna om din vän här + + + + Peer details + Klientdetaljer + + + Trust: + Pålitlig: + + + + Name: + Namn: + + + Org: + Org: + + + + Loc: + Plac: + + + Country: + Land: + + + + Signers + Signerare + + + AUTH CODE + AUTH-COD + + + + ConfCertDialog + + + Cancel + Avbryt + + + Port: + Port: + + + Sign The Certificate + Signera certifikatet + + + + OK + OK + + + + Details + Detaljer + + + Peer Details + Klientdetaljer + + + Name: + Namn: + + + + Peer Info + Klientinfo + + + Org / Loc: + Org / Plats: + + + Country/State: + Land: + + + + Peer ID + Klient-ID + + + + Last Contact + Senaste kontakt + + + + Version + + + + + Peer Address + Klientadress + + + Local Address: + Lokal adress: + + + External Address: + Extern adress: + + + + Addresses list + + + + + None + + + + + Marginal + + + + + Full + + + + + Deny Friend + Neka vän + + + + Make Friend + Skapa vän + + + + + Sign GPG key + + + + + Friend Details + + + + + Name + + + + + Loc + + + + + RetroShare ID + + + + + Status + Status + + + + Local Address + Lokal adress + + + + External Address + Extern adress + + + + Dynamic DNS + + + + + + Port + + + + + Your trust in this peer is: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Certificate + + + + None + Ingen + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + Trust Settings + Pålitlighetsinställningar + + + Sign this certificate + Signera detta certifikat + + + Accept connexions from this peer + Acceptera anslutningar från denna klient + + + Peer has signed my certficate + Klient som signerat mitt certifikat + + + Certificate signers + Certifikatsignerare + + + Make friend (Sign certificate and accept) + Skapa vän (signera certifikat och acceptera) + + + + Apply and Close + Verkställ och stäng + + + + + RetroShare + RetroShare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + Lita på + + + + ConfirmQuitDialog + + Exit RetroShare + Avsluta RetroShare + + + You are about to exit the RetroShare application and therefore stop all transfers. <br><br>Are you sure you want to stop and exit RetroShare? + Du håller på att avsluta RetroShare och därför stoppa alla överföringar. <br><br>Är du säker att du vill stoppa och avsluta RetroShare? + + + Do not show this message again. + Visa inte detta meddelande igen. + + + + ConnectDialog + + Cancel + Avbryt + + + Name: + Namn: + + + Country: + Land: + + + Make Friend + Skapa vän + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#000000;"> Make Friend</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#000000;"> Skapa vän</span></p></body></html> + + + Peer Details + Klientdetaljer + + + Trust: + Pålitlig: + + + Org: + Org: + + + Loc: + Plats: + + + signers: + Signerare: + + + AUTH CODE: + AUTH-KOD: + + + + ConnectFriendWizard + + + Connect Friend Wizard + Anslut till vän (assisterad) + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + + + + + Description + Beskrivning + + + + Type: + Typ: + + + + Public - Anyone can read and publish (Shared Publish Key) + Publik - Alla kan läsa och publivera (Delad publiceringsnyckel) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Begränsad - Alla kan läsa, begränsad publicering (Privat publiceringsnyckel) + + + + Private - (Private Publish Key required to view Messages) + Privat . (Privat publiceringsnyckel krävs för att visa meddelanden) + + + + Allowed Messages + Tillåtna meddelanden + + + + Authemticated Messages + Verifierade meddelanden + + + + Anonymous Messages + Anonyma meddelanden + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + Avbryt + + + + Create + Skapa + + + + RetroShare + RetroShare + + + + Please add a Name + Lägg till ett namn + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + Ämne: + + + + Html Editor + + + + Attachments + Bilagor + + + + toolBar + Verkygsfält + + + + toolBar_2 + Verktygsfält_2 + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + Fet + + + + Underline + Understruken + + + + Italic + Kursiv + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + Drag and Drop Files from Search Results + Dra och släpp filer från sökresultat + + + Add Extra File + Lägg till extra fil + + + + RetroShare + RetroShare + + + + Please add a Subject + + + + + &File + &Fil + + + + &New + &Ny + + + + &Open... + &Öppna + + + + &Save + &Spara + + + + Save &As... + Spara S&om + + + + &Print... + Skriv &ut.... + + + + Print Preview... + + + + + &Export PDF... + &Exportera till PDF + + + + &Quit + &Avsluta + + + + &Edit + &Redigera + + + + &Undo + &Ångra + + + + &Redo + &Gör om + + + + Cu&t + &Klipp ut + + + + &Copy + K&opiera + + + + &Paste + K&listra in + + + + &View + &Visa + + + + &Insert + &Infoga + + + + &Image + &Bild + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + &Vänster + + + + + C&enter + &Centrerad + + + + + &Right + &Höger + + + + &Justify + &Justerad + + + + &Text Color... + + + + + Application + Applikation + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + Öppna fil... + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-filer (*.htm *.html);;Alla filer (*) + + + + Save as... + Spara som... + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + Skriv ut dokument + + + + Export PDF + + + + + Choose Image + Välj bild + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Bildfiler som stöds (*.png *.jpeg *.jpg *.gif) + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + Beskrivning + + + + Type: + Typ: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Begränsad - Alla kan läsa, begränsad publicering (Privat publiceringsnyckel) + + + + Private - (Private Publish Key required to view Messages) + Privat . (Privat publiceringsnyckel krävs för att visa meddelanden) + + + + Allowed Messages + Tillåtna meddelanden + + + + Anonymous Messages + Anonyma meddelanden + + + + Authenticated Messages + + + + Authemticated Messages + Verifierade meddelanden + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + Avbryt + + + + Create + Skapa + + + + RetroShare + RetroShare + + + + Please add a Name + Lägg till ett namn + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + Meddelande + + + + Subject : + Ämne: + + + + + Attachments + Bilagor + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + Dra och släpp filer från sökresultat + + + + + Drop file error. + Filsläppningsfel. + + + + Directory can't be dropped, only files are accepted. + Kataloger kan inte dra och släppas, endast filer. + + + + File not found or file name not accepted. + Filen hittades inte eller filnamn ogiltigt. + + + + Add Extra File + Lägg till extra fil + + + + + RetroShare + RetroShare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + Namn + + + + Type: + Typ: + + + + Authenticated Messages + + + + + Cancel + Avbryt + + + RetroShare + RetroShare + + + + Please add a Name + Lägg till ett namn + + + Create a Forum + Skapa ett forum + + + + Create new Forum + Skapa ett forum + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Description + Beskrivning + + + + Public - Anyone can read and publish (Shared Publish Key) + Publik - Alla kan läsa och publivera (Delad publiceringsnyckel) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + Begränsad - Alla kan läsa, begränsad publicering (Privat publiceringsnyckel) + + + + Private - (Private Publish Key required to view Messages) + Privat . (Privat publiceringsnyckel krävs för att visa meddelanden) + + + + Allowed Messages + Tillåtna meddelanden + + + Authemticated Messages + Verifierade meddelanden + + + + Anonymous Messages + Anonyma meddelanden + + + + Create + Skapa + + + + CreateForumMsg + + + Close + Stäng + + + + Post Forum Message + Posta forummeddelande + + + + Forum + Forum + + + Forum Post Subject + Forum Posta ämne + + + + Attach File + Bifoga fil + + + + Forum Post + Forum Posta + + + + Sign Message + Signera meddelande + + + + Subject + Ämne + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + toolBar + Verkygsfält + + + + Post Forum Msg + Posta forummeddelande + + + Paste retroshare Link + Klistra in retrosharelänk + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + RetroShare + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + Lägg till extra fil + + + + + Drop file error. + Filsläppningsfel. + + + + File not found or file name not accepted. + Filen hittades inte eller filnamn ogiltigt. + + + + Directory can't be dropped, only files are accepted. + Kataloger kan inte dra och släppas, endast filer. + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + RetroShare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + Spara som... + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + Certificate file successfully created + Certifikatsfil skapad utan fel + + + Sorry, certificate file creation failed + Tyvärr, fel uppstod vid skapande av certifikatsfilen + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + CryptographyDialog + + 128 Bits + 128 bitar + + + 192 Bits + 192 bitar + + + 256 Bits + 256 bitar + + + CBC + CBC + + + ECB + ECB + + + CFB + CFB + + + PKCS7 + PKCS7 + + + ANSIX923 + ANSIX923 + + + ISO10126 + ISO10126 + + + Key Size: + Nyckelstorlek: + + + Block Size: + Blockstorlek: + + + Mode: + Läge: + + + RSA Key Size + Storlek RSA-nyckel + + + Rijndael Mode + Rijndael-läge + + + Rijndael Padding + Rijndael-utfyllnad + + + Zeros + If this is some type of encryption method I don't know of, the translation should be left Zeros, but if this is the digit zero [0] than the translation is correct. + Nollor + + + Padding: + Utfyllnad: + + + Rijndael Feedback Size + Rijndael Återkopplingsstorlek + + + Feedback Size: + Återkopplingsstorlek: + + + Rijndael Block size + Rijndael blockstorlek + + + Rijndael Key Size + Rijndael nyckelstorlek + + + + DHTStatus + + <strong>DHT:</strong> + <strong>DHT:</strong> + + + DHT OK + DHT OK + + + DHT DOWN + DHT NER + + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + B + + + + KB + KB + + + + MB + MB + + + + GB + GB + + + + DetailsDialog + + + Details + Detaljer + + + + + General + Allmänt + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + Typ: + + + + Transfer + Överföring + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + Datum + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + Kopiera + + + + OK + OK + + + + Cancel + Avbryt + + + + Rating + + + + + File Name + Filnamn + + + + Not Rated + + + + + No Comments + + + + + DirectoriesDialog + + Shared Directories + Utdelade kataloger + + + Other Directories + Övriga kataloger + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Incoming Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Inkommande filer</span></p></body></html> + + + Add Shared Directory + Lägg till delad katalog + + + Add a Share Directory + Lägg till delad katalog + + + Remove Shared Directory + Ta bort delad katalog + + + Browse + Bläddra + + + Set Incoming Directory + Ange inkommande katalog + + + Set Partials Directory + Ange delkatalog + + + Incoming Directory + Inkommande katalog + + + Partials Direcrtory + Delkatalog + + + + DirectoriesPage + + + Incoming Directory + Inkommande katalog + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + Partials Direcrtory + Delkatalog + + + + Shared Directories + Delade kataloger + + + + Edit Share + + + + Incoming files + Inkommande filer + + + Add a Share Directory + Lägg till delad katalog + + + Remove Shared Directory + Ta bort delad katalog + + + + + Browse + Bläddra + + + Add Shared Directory + Lägg till delad katalog + + + + Set Incoming Directory + Ange inkommande katalog + + + + Set Partials Directory + Ange delkatalog + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + Stäng + + + + EditChanDetails + + + Channel Details + Kanaldetaljer + + + + Cancel + Avbryt + + + + OK + OK + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + Kanalnamn: + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + Avbryt + + + + OK + OK + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + Ursäkta, ett fel uppstod + + + + Here is the error message: + Här är felmeddelandet: + + + + ExampleDialog + + + Vote Up + Rösta Upp + + + + Vote Down + Rösta Ned + + + + # + # + + + + Status + Status + + + + Person + Person + + + + Organisation + Organisation + + + + Location + Plats + + + + Country + Land + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Vänner</span></p></body></html> + + + + Auto Connect + Anslut automatiskt + + + + Trust Level + Pålitlighetsnivå + + + + Peer Address + Klientadress + + + + Last Contact + Senaste kontakt + + + + Person Id + Person Id + + + + Auth Code + AUTH-KOD + + + + ExprParamElement + + + + + to + till + + + + ignore case + ignorera skiftläge + + + + + dd.MM.yyyy + dd.MM.yyyy + + + + + KB + KB + + + + + MB + MB + + + + + GB + GB + + + + ExpressionWidget + + + Expression Widget + Utryckssymbol + + + + Delete this expression + Ta bort denna uttryckssymbol + + + + FileAssociationsPage + + + &New + &Ny + + + + Add new Association + + + + + &Edit + &Redigera + + + + Edit this Association + + + + + &Remove + &Radera + + + + Remove this Association + + + + + File type + Filtyp + + + + Friend Help + Vän hjälp + + + + You this + Du denna + + + + FileAssotiationsDialog + + &New + &Ny + + + Add new assotiation + Lägg till ny associasion + + + &Edit + &Redigera + + + Edit this assotiation + Redigera denna associasion + + + &Remove + &Radera + + + Remove this assotiation + Ta bort denna associasion + + + File type + Filtyp + + + Friend Help + Vän hjälp + + + You this + Du denna + + + + FileHashDialog + + Download + Hämta + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + Återstår + + + + Number of sources + + + + + Chunk strategy + Chunk strategi + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FindWindow + + &Browse... + &Bläddra + + + &Find + &Hitta + + + Named: + Filnamn: + + + Containing text: + Innehåller text: + + + In directory: + I katalog: + + + Find Files + Hitta filer + + + %1 KB + %1 KB + + + %1 file(s) found + %1 fil(er) hittade + + + File Name + Filnamn + + + Size + Storlek + + + + FlatStyle_RDM + + + Friends Directories + Vänners kataloger + + + + My Directories + Mina kataloger + + + + Size + Storlek + + + + Age + Ålder + + + + Friend + Vän + + + + Share Type + + + + + Directory + Kataloger + + + + FofPage + + + Friends of friends + Vänner till vänner + + + + Select now who you want to make friends with. + Välj nu vem du vill bli vän med. + + + + Show me: + Visa mig: + + + + Any peer I've not signed + Osignerade klienter + + + + Friends of my friends who already trust me + Vänner till mina vänner som redan litar på mig + + + + Signed peers showing as denied + Signerade XXX som visas som nekade + + + + Peer name + Klientnamn + + + + Also signed by + Även signerad av + + + + Peer id + Klient-ID + + + + Make friend with these peers + Bli vän med dessa XXX + + + + *** None *** + *** Ingen *** + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + Popularitet + + + + Last Post + Senaste inlägg + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + Tillåtna meddelanden + + + + Authemticated Messages + Verifierade meddelanden + + + + Anonymous Messages + Anonyma meddelanden + + + + Cancel + Avbryt + + + + OK + OK + + + + Apply and Close + Verkställ och stäng + + + + ForumMsgItem + + Form + Formulär + + + + Remove Item + Radera objekt + + + Forum Name + Forum namn + + + + Expand + Utöka + + + + + + Subject: + Ämne: + + + + Send + Skicka + + + + Signed + Signerad + + + Subject... + Ämne... + + + Persons Name + Personens namn + + + + Unsubscribe To Forum + Ta bort prenumeration från forum + + + + Reply + Svara + + + Message is about ??? + Meddelandet handlar om ??? + + + Previous Message... + Föregående meddelande... + + + Currnent Message.. + Aktuellt meddelande.. + + + + Forum Post + Forum Posta + + + + Unknown Forum Post + + + + + + + Anonymous + Anonym + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + Formulär + + + + Remove Item + Radera objekt + + + Connected + Ansluten + + + name + namn + + + + Subscribe to Forum + Prenumerera på forum + + + + Expand + Utöka + + + + Forum Description + + + + Description + of Forum + Beskrivning +av forum + + + + ForumPage + + + Misc + Diverse + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + Prenumerera på forum + + + + Unsubscribe to Forum + Ta bort prenumeration från forum + + + + New Forum + Nytt forum + + + + Show Forum Details + Visa forumdetaljer + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Mark all as read + + + + + Mark all as unread + + + + + Reply + Svara + + + + Reply to Author + Svara författaren + + + + Expand all + Expandera alla + + + + Collapse all + Komprimera alla + + + + AUTHD + + + + Popularity: + Popularitet: + + + + Your Forums + Dina forum + + + + Subscribed Forums + Bevakade forum + + + + Popular Forums + Populära forum + + + + Other Forums + Andra forum + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Hide + Dölj + + + + Expand + Utöka + + + Popularity: + Popularitet: + + + Anonymous + Anonym + + + signed + Signerad + + + none + Ingen + + + + + RetroShare + RetroShare + + + + No Forum Selected! + Nej Forum vald! + + + Re: + Re: + + + + You cant reply a Anonymous Author + You cant svar en Anonym Författare + + + File Request Confirmation + Bekräfta filförfrågan + + + The file has been added to your download list. + Filen har lagts till i din nedladdningslista. + + + File Request canceled + File begäran avbryts + + + The file has not been added to your download list, because you already have it. + Filen har inte lagts till i din nedladdning listan, eftersom du redan har det. + + + + File Request Error + Filförfrågningsfel + + + The file link is malformed. + Fillänken är missbildad. + + + + + Date + Datum + + + + + Title + Titel + + + + + Start New Thread + Starta ny tråd + + + New Message + Nytt meddelande + + + Forum Name + Forumnamn + + + Popularity + Popularitet + + + Posts + Inlägg + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + Add + Lägg till + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start new Thread for Selected Forum</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Starta ny tråd för utvalda Forum</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reply Message</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Svarsmeddelandet +</p></body></html> + + + + Start new Thread for Selected Forum + + + + + Display + Visa + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + Last Post + Senaste inlägg + + + + Threaded View + Trådvy + + + + Flat View + Platt vy + + + + + Author + Författare + + + + Signed + Signerad + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tråd:</span></p></body></html> + + + + Previous Thread + + + + + Next Thread + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + Nollställ + + + + Content + + + + + Reply Message + + + + + Create Forum + Skapa ett forum + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Forum Post</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Foruminlägg</span></p></body></html> + + + Prev + Föregående + + + Next + Nästa + + + + Print + Skriv ut + + + + PrintPreview + Förhandsgranska + + + + ForumsFillThread + + + + Anonymous + Anonym + + + + + signed + Signerad + + + + + none + Ingen + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Vänner</span></p></body></html> + + + + Add + Lägg till + + + + Display + Visa + + + + Friends + Vänner + + + + Status + Status + + + + Add or Change your Avatar + Lägga till eller ändra din avatar + + + + Edit Personal message + Redigera Personligt meddelande + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + Fet + + + + Underline + Understruken + + + + Italic + Kursiv + + + + Font + Typsnitt + + + + Text Color + Textfärg + + + + Attach File + Bifoga fil + + + + Send + Skicka + + + + Clear Chat History + Rensa chatthistorik + + + + + Add Friend + Lägg till en vän + + + + Create new Profile + + + + + + Create new Forum + Skapa ett forum + + + + F + + + + + + Create new Channel + Skapa ny kanal + + + + C + + + + + Add your Avatar Picture + Lägg till din avatar bild + + + + A + + + + + Set your Personal Message + Ställ din personliga meddelande + + + + Edit your status Message + Edit your status message + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + Profil + + + + News Feed + Nyhetsflöde + + + + Welcome to RetroShare's group chat. + Välkommen till RetroShares gruppchatt. + + + + me + jag + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + Vän + + + + Location + Plats + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + Meddelandevän + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + Anslut till vän + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + Neka vän + + + + Remove Friend Location + Ta bort kompis location + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + Expandera alla + + + + Collapse all + Komprimera alla + + + + location + + + + + + Available + Tillgänglig + + + + Save Certificate + Spara certifikat + + + + Certificates (*.pqi) + Certifikat (*.pqi) + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + Lägg till extra fil + + + + + Drop file error. + Filsläppningsfel. + + + + Directory can't be dropped, only files are accepted. + Kataloger kan inte dra och släppas, endast filer. + + + + File not found or file name not accepted. + Filen hittades inte eller filnamn ogiltigt. + + + + Save as... + Spara som... + + + + Text File (*.txt );;All Files (*) + + + + + GSettingsWin + + General + Allmänt + + + Network + Nätverk + + + Directories + Kataloger + + + Server + Server + + + %1 + %1 + + + + GamesDialog + + + Cancel Game + Avbryt spel + + + + Add to Invite List + Lägg till i inbjudningslistan + + + + Remove from Invite List + Ta bort från inbjudningslistan + + + + + Interested in Playing + Intresserad av att spela + + + + Not Interested in Game + Inte intresserad av spel + + + + + Not Interested + Inte intresserad + + + + Confirm Peer in Game + Bekräfta klient i spel + + + + Remove Peer from Game + Ta bort klient från spel + + + + Interested in Game + Intresserad av spel + + + + Quit Game + Avsluta spel + + + + Server + Server + + + + Status + Status + + + + Accept + Godkänn + + + + Form + Formulär + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Spelstartare</span></p></body></html> + + + + Game: + Spel: + + + + GameType: 0. Want to Add your Game here? + Speltyp: 0 Vill du lägga till ditt spel här? + + + + GameType: 1. Get In Touch with the developers + Speltyp: 1 Kontakta utvecklarna + + + + GameType: 2. + Speltyp: 2. + + + + Title / Comment + Titel / kommentar + + + + Create New Game + Skapa nytt spel + + + + Invite All Friends + Bjud in alla vänner + + + + Game Type + Speltyp + + + + Comment + Kommentar + + + + GameID + Spel-ID + + + + Player + Spelare + + + + + Invite + Bjud in + + + + Interested + Intresserad + + + + Delete + Ta bort + + + + + Move Player + Flytta spelare + + + + Play Game + Spela spel + + + + GenCertDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Generate a new profile</span><br /><br />Please fill in the information which will<br />allow your RetroShare to connect to</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Friends.</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Generera en ny profil</span><br /><br />Fyll i informationen som gör att<br />ditt RetroShare kan ansluta till</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">dina vänner.</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Organisation:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Organisation:</p></body></html> + + + Password (Again) + Lösenord (igen) + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + + + + + Enter here your nickname + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Put a strong password here. This password protects your GPG key. + + + + Location: + Plats: + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Email + + + + + + Your profile is associated to a GPG key + + + + + Location + Plats + + + + Generate New Profile + + + + Load Trusted Certificate (Optional) + Läs in pålitligt certifikat (valfritt) + + + + Password + Lösenord + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Vän</span></p></body></html> + + + Select File + Välj fil + + + Country: + Land: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Namn:</p></body></html> + + + Generate New Certificate + Generera nytt certifikat + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + Välj pålitlig vän + + + + Certificates (*.pqi *.pem) + Certifikat (*.pqi *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + Name: + Namn: + + + RetroShare setup + RetroShare setup + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Generate a new profile</span><br /><br /><span style=" font-size:9pt;">Please fill in the information which will<br />allow your RetroShare to connect to</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;">Friends.</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt;">Skapa en ny profil</span><br /><br /><span style=" font-size:9pt;">Fyll i informationen som kommer<br />tillåta din RetroShare att ansluta till dina</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;">vänner.</p></body></html> + + + Organisation: + Organisation: + + + Friend + Vän + + + OpenPGP User + OpenPGP-användare + + + PGP Password + PGP-lösenord + + + + Info + + + + + GeneralDialog + + Style + Stil + + + Language + Språk + + + Style Sheet + Stilmall + + + Misc + Diverse + + + Login + Inloggning + + + Auto Login + Autoinloggning + + + Start minimized + Starta minimerad + + + Start RetroShare when my system starts + Starta RetroShare vid systemstart + + + Startup + Uppstart + + + + GeneralMsgDialog + + Channel + Kanal + + + Forum + Forum + + + Blog + Blogg + + + Message + Meddelande + + + Add Extra File + Lägg till extra fil + + + Dialog + Dialog + + + Friend + Vän + + + Add Message Destination + Lägg till destination för meddelande + + + Message Destination + Destination för meddelande + + + Drag and Drop Files from Search Results + Dra och släpp filer från sökresultat + + + Attachments + Bilagor + + + Subject : + Ämne: + + + + GeneralPage + + Keys manager + Nyckelhanterare + + + Style + Stil + + + Language + Språk + + + Choose the language used in RetroShare + Välj språket som ska användas i RetroShare + + + + Startup + Uppstart + + + + Start RetroShare when my system starts + Starta RetroShare vid systemstart + + + + Start minimized + Starta minimerad + + + + Start minimized on system start + + + + + Misc + Diverse + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + Autoinloggning + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + Mottaget: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + Skickat: + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + Elastic Nodes + Elastiska noder + + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + Vänner + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + Titel + + + + Description + Beskrivning + + + + Reset + Nollställ + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + och + + + + and / or + och / eller + + + + or + eller + + + + Name + + + + + Path + Sökväg + + + + Extension + Filändelse + + + + Hash + Hash + + + + Date + Datum + + + + Size + Storlek + + + + Popularity + Popularitet + + + + contains + innehåller + + + + contains all + innehåller alla + + + + is + är + + + + less than + mindre än + + + + less than or equal + mindre än eller lika med + + + + equals + lika med + + + + greater than or equal + större än eller lika med + + + + greater than + större än + + + + is in range + är inom omfång + + + + HelpBrowser + + + + Error Loading Help Contents: + Fel vid laddning av innehållsförteckning för hjälp: + + + + Supplied XML file is not a valid Contents document. + Aktuell XML-fil är inte ett giltigt innehållsdokument. + + + + Search reached end of document + Sökningen har kommit till slutet av dokumentet + + + + Search reached start of document + Sökningen har kommit till början av dokumentet + + + + Text not found in document + Text hittades inte i dokumentet + + + + Found %1 results + Hittade %1 resultat + + + + + Search + Sök + + + + Home + Hem + + + + Close + Stäng + + + + + RetroShare Help + RetroShare Hjälp + + + + Find: + Hitta: + + + + Find Previous + Hitta föregående + + + + Find Next + Hitta nästa + + + + Case sensitive + Skiftlägeskänslig + + + + Whole words only + Endast hela ord + + + + Contents + Innehåll + + + + Help Topics + Hjälpämnen + + + + Searching for: + Söker efter: + + + + Found Documents + Hittade dokument + + + + Back + Tillbaka + + + + Move to previous page (Backspace) + Gå till föregående sida (Backspace) + + + + Backspace + Backspace + + + + Forward + Framåt + + + + Move to next page (Shift+Backspace) + Gå till nästa sida (Shift+Backspace) + + + + Shift+Backspace + Shift+Backspace + + + + Move to the Home page (Ctrl+H) + Gå till startsidan (Ctrl+H) + + + + Ctrl+H + Ctrl+H + + + + + + Find + Hitta + + + + Search for a word or phrase on current page (Ctrl+F) + Sök efter ett ord eller en fras på aktuell sida (Ctrl+F) + + + + Ctrl+F + Ctrl+F + + + + Close Vidalia Help + Stäng Vidalia Hjälp + + + + Esc + Esc + + + + HelpDialog + + + About + Om + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + Upphovsmän + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + Thanks to + Tack till + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Translation + Översättning + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + License Agreement + Licensavtal + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;">RetroShare is a Open Source cross-platform, private and secure decentralised commmunication platform. </p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;">It lets you share securely your friends, using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;">RetroShare provides filesharing, chat, messages and channels</p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;"><img src=":/images/retrosharelogo2.png" /></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;">Usefull External Links to more information:</p> +<ul style="-qt-list-indent: 1;"><li align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;">RetroShare är en privat och säker kommunikationsplattform, baserad på öppen källkod och plattformsoberoende. </p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;">Den låter dig säkert chatta och dela filer med dina vänner och din familj genom att använda web-of-trust för att autentisiera källor och OpenSSL för att kryptera all kommunikation. </p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;">RetroShare erbjuder fildelning, chat, meddelanden, forum och kanaler</p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;"></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; font-weight:600;"><img src=":/images/retrosharelogo2.png" /></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;">Användbara externa länkar till mer information:</p> +<ul style="-qt-list-indent: 1;"><li align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webbsida</span></a></li> +<li align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShares Forum</a></li> +<li align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshares Projektsida</span></a></li> +<li align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Hemsida.</span></a></li></ul></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><span style=" font-size:19pt; font-weight:600; color:#0000ff;">The RetroShare Team:</span><br /> <br /><span style=" font-size:9pt; color:#0000ff;">defnax</span>: Lead GUI developer <br /><span style=" font-size:9pt; color:#0000ff;">drbob7</span>: Lead Core developer. <br /> <br /><span style=" font-size:9pt; color:#0000ff;">bmeck</span> : Our new web-developer. Joined retroshare a couple <br />of weeks ago, and already starting on an exciting new <br />design for the web-page. <br /> <br /><span style=" font-size:9pt; color:#0000ff;">noragen</span> : Developer from the SIM-IM project. Working on a retroshare plugin to SIM-IM. <br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#0000ff;">kernelpanix</span> : Gui and skin developer</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#0000ff;">libris</span><span style=" font-size:9pt;">:</span> core developer</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><span style=" font-size:9pt; color:#0000ff;">kashif: </span><span style=" color:#000000;">core developer</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; color:#000000;"><span style=" font-size:8pt;"><br /></span><span style=" color:#0000ff;">agent725</span><span style=" font-size:8pt;">: Manages the 'local' Retroshare release, <br />and beta-testing retroshare on a large scale. <br /> <br /></span><span style=" color:#0000ff;">the_mgt</span><span style=" font-size:8pt;">: Maintains the Gentoo and generic linux <br />installation/compilation scripts. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#0000ff;">notdefine:</span> Maintains the .rpm, .deb installation/compilation scripts.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#0000ff;">zhouk</span>: developer</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><span style=" font-size:19pt; font-weight:600; color:#0000ff;">RetroShare Teamet:</span><br /> <br /><span style=" font-size:9pt; color:#0000ff;">defnax</span>: Förste GUI-utvecklare <br /><span style=" font-size:9pt; color:#0000ff;">drbob7</span>: Förste kärnutvecklare. <br /> <br /><span style=" font-size:9pt; color:#0000ff;">bmeck</span> : Vår nye webbutvecklare. Anslöt till retroshare för ett par <br />veckor sedan och har redan börjat arbetet med en ny spännande <br />design för webbsidan. <br /> <br /><span style=" font-size:9pt; color:#0000ff;">noragen</span> : Utvecklare från SIM-IM-projektet. Arbetar med ett retroshare-plugin för SIM-IM. <br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#0000ff;">kernelpanix</span> : GUI- och skalutvecklare.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#0000ff;">libris</span><span style=" font-size:9pt;">:</span> kärnutvecklare</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /><span style=" font-size:9pt; color:#0000ff;">kashif: </span><span style=" color:#000000;">kärnutvecklare</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt; color:#000000;"><span style=" font-size:8pt;"><br /></span><span style=" color:#0000ff;">agent725</span><span style=" font-size:8pt;">: Hanterar de 'lokala' Retroshare releaserna, <br />och betatestar retroshare i stor skala. <br /> <br /></span><span style=" color:#0000ff;">the_mgt</span><span style=" font-size:8pt;">: Underhåller Gentoo och generiska linux <br />installations/kompileringsscripten. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#0000ff;">notdefine:</span> Underhåller .rpm, .deb installation/kompileringsscripten.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; color:#0000ff;">zhouk</span>: utvecklare</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">French</span>:Temet</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Jarek</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Serbian</span>: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Swedish:</span> dnylander</p></body></html> + added myself as swedish translator ;-) + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Översättare:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Franska</span>:Temet</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polska: </span>Jarek</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Serbiska</span>: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Svenska:</span> dub_u</p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Om RetroShare</span></p></body></html> + + + + HelpTextBrowser + + + Error opening help file: + Fel vid öppning av hjälpfil: + + + + Opening External Link + Öppnar extern länk + + + + Unable to Open Link + Kan ej öppna länk + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + RetroShare kan öppna länken du valt i din standardwebbläsare. Om din webbläsare inte är konfigurerad att använda Tor, kommer inte förfrågan att vara anonym. + + + + Do you want Retroshare to open the link in your Web browser? + Vill du att RetroShare öppnar länken i din webbläsare? + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + RetroShare kunde inte öppna vald länk i din webbläsare. Du kan fortfarande kopiera länkadressen och klistra in i din webbläsare. + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + Nollställ + + + + + Copy + Kopiera + + + + Remove + Ta bort + + + + Mark all + + + + + Delete + Ta bort + + + + Clear history + + + + + Send + Skicka + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + This wizard will help you to connect to your friend(s) to RetroShare network. There are three possible ways to do this: + Denna guide kommer att hjälpa dig att ansluta din(a) vän(ner) till RetroShare nätverk. Det finns tre möjliga sätt att göra detta: + + + + &Make friend with selected friends of my friends + &Bli vän med markerade vänner till mina vänner + + + + Add a new Friend + Lägg till en ny vän + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + &Skriv in certifikatet manuellt + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + &Use *.pqi files with certificates + &Använd *pqi-filer med certifikat + + + + InviteDialog + + Done + Färdig + + + Cancel + Avbryt + + + Invite a Friend + Bjud in en vän + + + + LibraryDialog + + Play + Spela + + + Copy + Kopiera + + + Delete + Ta bort + + + Rename + Byt namn + + + Open File... + Öppna fil... + + + Media-Files (*.avi *.mp3 *.wmv *.wav *.dat *.mov *.mpeg);;All Files (*) + Mediafiler (*.avi *.mp3 *.wmv *.wav *.dat *.mov *.mpeg);;Alla filer (*) + + + Library + Bibliotek + + + Folder + Katalog + + + All File Types + Alla filtyper + + + Application + Applikation + + + Archive + Arkiv + + + Organizer + Kalender + + + Share Files.. + Dela filer.. + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/folder_blueshared.png" /> Exploring My RetroShare Library</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/folder_blueshared.png" /> Utforskar mitt RetroShare-bibliotek</p></body></html> + + + Tile view + Överlappad vy + + + Show Details + Visa detaljer + + + Create Album + Skapa album + + + Delete Album + Ta bort album + + + Find + Hitta + + + + LinksDialog + + + Share Link Anonymously + Dela länk anonymt + + + + Vote on Link + Rösta på länk + + + + Download + Hämta + + + + Expand + Utöka + + + + Hide + Dölj + + + + File Request Confirmation + Bekräfta filförfrågan + + + + The file has been added to your download list. + Filen har lagts till i din nedladdningslista. + + + + File Request canceled + File begäran avbryts + + + + The file has not been added to your download list, because you already have it. + Filen har inte lagts till i din nedladdning listan, eftersom du redan har det. + + + + + File Request Error + Filförfrågningsfel + + + + The file link is malformed. + Fillänken är missbildad. + + + + From + Från + + + + Show + Visa + + + + 101-200 + 101-200 + + + + 201-300 + 201-300 + + + + 301-400 + 301-400 + + + + 401-500 + 401-500 + + + Form + Formulär + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Länkmoln</span></p></body></html> + + + + Title / Comment + Titel / kommentar + + + + Score + Poäng + + + + Peer / Link + Klient / Länk + + + + Sort by + Sortera på + + + + Combo + Kombination + + + + Time + Tid + + + + Ranking + Ranking + + + + In last + Senaste + + + + Month + Månaden + + + + Week + Veckan + + + + Day + Dagen + + + + All Peers + Alla klienter + + + + Own Links + Egna länkar + + + + Top 100 + 100 Högsta + + + + Bottom 100 + 100 Lägsta + + + + Link: + + + + + Add Anonymous Link + Lägg till anonym länk + + + + Add Link/Comment + Lägg till länk/kommentar + + + + Title: + Titel: + + + + Score: + Poäng: + + + + +2 Great! + +2 Jättebra! + + + + +1 Good + +1 Bra + + + + 0 Okay + 0 Okej + + + + -1 Sux + -1 Dåligt + + + + -2 Bad Link + -2 Trasig länk + + + + Url: + Url: + + + + Add new link + + + + + MainWindow + + + Network + Nätverk + + + + Friends + Vänner + + + + + Transfers + Överföringar + + + + + Messages + Meddelanden + + + + + Channels + Kanaler + + + + Blogs + Bloggar + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + Status + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + Fillänken är missbildad. + + + Online + Ansluten + + + Busy + Upptagen + + + Away + Frånvarande + + + + + Options + Alternativ + + + + Hide + Dölj + + + + Show + Visa + + + + RetroShare + RetroShare + + + Invite Friend + Bjud in vän + + + + MainWindow + Huvudfönster + + + toolBar + Verkygsfält + + + + Add Friend + Lägg till en vän + + + + Add a Friend Wizard + + + + + Add Share + Lägg till utdelning + + + + + Quick Start Wizard + + + + + Search + Sök + + + + Files + Filer + + + Add Shared Directory + Lägg till delad katalog + + + + Show/Hide + Visa/Dölj + + + + &Quit + &Avsluta + + + + Bandwidth Graph + Bandbreddsdiagram + + + + Open Messenger + Öppna meddelandeklient + + + + Links Cloud + Länkmoln + + + + RetroShare %1 a secure decentralised communication platform + + + + + Unfinished + Ej slutförda + + + + Minimize + Minimera + + + + Maximize + Maximera + + + + + + + You have %1 new message + + + + + Help + Hjälp + + + + About + Om + + + News Feed + Nyhetsflöde + + + + + Forums + Forum + + + + Open Messages + Öppna meddelanden + + + + Applications + Applikationer + + + Settings + Inställningar + + + RetroShare %1 a secure decentralised commmunication platform + RetroShare %1 en säker och decentraliserad kommunikationsplattform + + + Turtle + Turtle + + + + Plugins + Plugin + + + + Really quit ? + Verkligen avsluta? + + + + Do you really want to exit RetroShare ? + Vill du verkligen avsluta RetroShare? + + + toolBar_2 + Verktygsfält_2 + + + + Quit + Avsluta + + + Color + Färg + + + + SMPlayer + SMPlayer + + + + Messenger + Meddelandeklient + + + + MessageComposer + + + + Compose + Skapa + + + + + Contacts + Kontakter + + + + Search for Name: + + + + + Reset + Nollställ + + + + Send To: + Skicka till: + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + Teckensnittsstorlek + + + + Increase font size + + + + + Decrease font size + + + + + Bold + Fet + + + + Underline + Understruken + + + + Italic + Kursiv + + + + Select Color + + + + + Alignment + Justering + + + + Add a Image + Lägg till bild + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + Rekommenderade filer + + + + File Name + Filnamn + + + + Size + Storlek + + + Sources + Källor + + + + Hash + Hash + + + + Send + Skicka + + + + Send this message now + Skicka detta meddelande nu + + + + Reply + Svara + + + + Toggle Contacts View + Visa/dölj kontakter + + + + Save + Spara + + + + Save this message + Spara detta meddelande + + + + Attach + + + + + Attach File + Bifoga fil + + + + Quote + + + + + Add Blockquote + + + + + &Left + &Vänster + + + + C&enter + &Centrerad + + + + &Right + &Höger + + + + &Justify + &Justerad + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + Spara meddelande + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + Compose: + Skapa: + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + RetroShare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + Okänd + + + + Unknown friend + + + + + &File + &Fil + + + + &New + &Ny + + + + &Open... + &Öppna + + + + &Save + &Spara + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + Skriv &ut.... + + + + &Export PDF... + &Exportera till PDF + + + + &Quit + &Avsluta + + + + &Edit + &Redigera + + + + &Undo + &Ångra + + + + &Redo + &Gör om + + + + Cu&t + &Klipp ut + + + + &Copy + K&opiera + + + + &Paste + K&listra in + + + + &View + &Visa + + + + &Contacts Sidebar + &Kontakter i sidofältet + + + + &Insert + &Infoga + + + + &Image + &Bild + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + Öppna fil... + + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-filer (*.htm *.html);;Alla filer (*) + + + + Save as... + Spara som... + + + + Print Document + Skriv ut dokument + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + Meddelandet har inte skickats. +Vill du spara meddelandet ? + + + + Choose Image + Välj bild + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + Bildfiler som stöds (*.png *.jpeg *.jpg *.gif) + + + + Add Extra File + Lägg till extra fil + + + + + Drop file error. + Filsläppningsfel. + + + + Directory can't be dropped, only files are accepted. + Kataloger kan inte dra och släppas, endast filer. + + + + File not found or file name not accepted. + Filen hittades inte eller filnamn ogiltigt. + + + + MessagePage + + Misc + Diverse + + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + Lägg till + + + + Edit + + + + + Delete + Ta bort + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + meddelande + + + New Message + Nytt meddelande + + + + Subject + Ämne + + + + <b>1 new Message from</b> + + + + + Close + Stäng + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekommenderade filer</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + Från: + + + + To: + Till: + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + Filnamn + + + + Size + Storlek + + + + Hash + Hash + + + + Print + Skriv ut + + + + Print Preview + Förhandsgranska + + + + No subject + + + + + Download + Hämta + + + + Download all + + + + + Hide + Dölj + + + + Expand + Utöka + + + + File + + + + + Files + Filer + + + + Print Document + Skriv ut dokument + + + + Save as... + Spara som... + + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-filer (*.htm *.html);;Alla filer (*) + + + + MessageWindow + + + New Message + Nytt meddelande + + + + Compose + Skapa + + + + Reply to selected message + + + + + Reply + Svara + + + + Reply all to selected message + + + + + Reply all + Svara alla + + + + Forward selected message + + + + + Foward + Framåt + + + + Remove selected message + + + + + Delete + Ta bort + + + + Print selected message + + + + + + Print + Skriv ut + + + + Display + Visa + + + + + + Tags + + + + + Print Preview + Förhandsgranska + + + + + Buttons Icon Only + Knappar endast ikon + + + + Buttons Text Beside Icon + Knappar text bredvid Icon + + + + Buttons with Text + Knappar med text + + + + Buttons Text Under Icon + Knappar texten under Icon + + + + Set Text Under Icon + Ange texten under Icon + + + + &File + &Fil + + + + Save &As File + + + + + &Print... + Skriv &ut.... + + + + Print Preview... + + + + + &Quit + &Avsluta + + + + MessagesDialog + + + + New Message + Nytt meddelande + + + + Quick View + + + + + Reply to Message + Svara på meddelande + + + + Remove Message + Ta bort meddelande + + + + + Date + Datum + + + + + + From + Från + + + Size + Storlek + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekommenderade filer</span></p></body></html> + + + + Reply + Svara + + + + Reply all + Svara alla + + + + Foward + Framåt + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ta bort markerat meddelande</p></body></html> + + + + Delete + Ta bort + + + + Compose + Skapa + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + Visa + + + + Reset + Nollställ + + + + Attachments + Bilagor + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + Inkorg + + + + + + + Outbox + Utkorg + + + + Draft + Utkast + + + + + Sent + Skickat + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + Skriv ut... + + + + Print Preview + Förhandsgranska + + + + + Buttons Icon Only + Knappar endast ikon + + + + Buttons Text Beside Icon + Knappar text bredvid Icon + + + + Buttons with Text + Knappar med text + + + + Buttons Text Under Icon + Knappar texten under Icon + + + + Set Text Under Icon + Ange texten under Icon + + + + Save As... + Spara som... + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">svara på markerat meddelande</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nytt meddelande</p></body></html> + + + Download All + Hämta alla + + + Print Document + Skriv ut dokument + + + File Name + Filnamn + + + Sources + Källor + + + # + # + + + + Forward selected Message + Vidarebefodra markerat meddelande + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + Ta bort meddelanden + + + + Forward Message + Vidarebefodra meddelande + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + Hämta + + + + Empty trash + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + Click to sort by to + + + + Files + Filer + + + Re: + Re: + + + Compose: + Skapa: + + + Fwd: + Fwd: + + + Hide + Dölj + + + Expand + Utöka + + + + + + Drafts + Utkast + + + + To + + + + Anonymous + Anonym + + + File Request Confirmation + Bekräfta filförfrågan + + + The file has been added to your download list. + Filen har lagts till i din nedladdningslista. + + + File Request canceled + File begäran avbryts + + + The file has not been added to your download list, because you already have it. + Filen har inte lagts till i din nedladdning listan, eftersom du redan har det. + + + + File Request Error + Filförfrågningsfel + + + The file link is malformed. + Fillänken är missbildad. + + + Save as... + Spara som... + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-filer (*.htm *.html);;Alla filer (*) + + + + + + + + Total: + + + + Replay to All + Svara alla + + + + + Reply to All + Svara alla + + + + + Subject + Ämne + + + Subject: + Ämnde: + + + From: + Från: + + + Date: + Datum: + + + To: + Till: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ladda ned alla rekommenderade filer</p></body></html> + + + Hash + Hash + + + + Print + Skriv ut + + + PrintPreview + Förhandsgranskning + + + + MessagesPopupDialog + + New Message + Nytt meddelande + + + Remove Messages + Ta bort meddelanden + + + Reply to Message + Svara på meddelande + + + Forward Message + Vidarebefodra meddelande + + + Remove Message + Ta bort meddelande + + + Download All + Hämta alla + + + Re: + Re: + + + Fwd: + Fwd: + + + Print Document + Skriv ut dokument + + + Messages + Meddelanden + + + Inbox + Inkorg + + + Outbox + Utkorg + + + Draft + Utkast + + + Sent + Skickat + + + From + Från + + + Date + Datum + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekommenderade filer</span></p></body></html> + + + File Name + Filnamn + + + Size + Storlek + + + Sources + Källor + + + Remove + Ta bort + + + Subject + Ämne + + + Subject: + Ämne: + + + From: + Från: + + + Date: + Datum: + + + To: + Till: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ladda ned alla rekommenderade filer</p></body></html> + + + Hash + Hash + + + toolBar + Verkygsfält + + + Compose + Skapa + + + Reply + Svara + + + Forward + Vidarebefodra + + + Print + Skriv ut + + + PrintPreview + Förhandsgranska + + + + MessengerWindow + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Click to change your avatar</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Klicka för att byta din avatar</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Change your Status and your display</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">picture here.</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ändra din status och din</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">visningsbild här.</p></body></html> + + + Online + Ansluten + + + Busy + Upptagen + + + Be right Back + Strax tillbaka + + + Away + Frånvarande + + + In a Call + Sitter i telefon + + + Out of lunch + Ute på lunch + + + Apear Offline + Visa som frånkopplad + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Share a personal message with your contacts</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dela ett personligt meddelande med dina kontakter</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Add a Friend</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lägg till en vän</p></body></html> + + + + Expand all + Expandera alla + + + + Collapse all + Komprimera alla + + + + Chat + Chatt + + + + Message Friend + Meddelandevän + + + + Connect To Friend + Anslut till vän + + + + Peer Details + Klientdetaljer + + + + Recomend this Friend to... + + + + + Paste RetroShare Link + + + + Paste retroshare Link + Klistra in retrosharelänk + + + + Export Friend + Exportera vän + + + + Deny Friend + Neka vän + + + + Remove Friend Location + Ta bort kompis location + + + + <strong>GPG Key</strong> + <strong>GPG Nyckel</strong> + + + + + + + location + + + + + <strong>RetroShare instance</strong> + <strong>RetroShare instance</strong> + + + location : + Ort: + + + Peer Online + Klient online + + + Available + Tillgänglig + + + + Save Certificate + Spara certifikat + + + + Certificates (*.pqi) + Certifikat (*.pqi) + + + Your Friend is offline +Do you want to send them a Message instead + Din vän är offline +Vill du skicka ett meddelande i stället + + + Send Message + Skicka meddelande + + + Remove Friend + Ta bort vän + + + RetroShare Messenger + RetroShare Meddelandeklient + + + + Click to Change your Avatar + Klicka för att ändra din avatar + + + TextLabel + TextEtikett + + + + Share Files for your Friends + Dela filer med dina vänner + + + ... + ... + + + + RetroShare Messenger + + + + + Add a Friend + Lägg till en vän + + + + Search Friends + + + + + Reset + Nollställ + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + Set Root is not Decorated + Ange rot är inte dekorerad + + + + Hide Offline Friends + + + + + MsgFeed + + Inbox + Inkorg + + + Outbox + Utkorg + + + Sent + Skickat + + + Date + Datum + + + Form + Formulär + + + Msgs In: + Meddelanden In: + + + Drafts + Utkast + + + From: + Från: + + + All + Alla + + + Sort By: + Sortera på + + + Subject + Ämne + + + Received + Mottagna + + + New Msg + Nytt meddelande + + + + MsgItem + + + Reply to Message + Svara på meddelande + + + Form + Formulär + + + + Remove Item + Radera objekt + + + Connected + Ansluten + + + + + Expand + Utöka + + + subjectLabel + ämnesEtikett + + + + Reply Message + + + + + Delete Message + Ta bort meddelande + + + + Play Media + Spela media + + + Long + message here + Långt + meddelande här + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + Dölj + + + Re: + Re: + + + + MyChannelsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Meddelanden</span></p></body></html> + + + Date + Datum + + + From + Från + + + Title + Titel + + + Msg + Meddelande + + + Count + Antal + + + Size + Storlek + + + Type + Typ + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekommenderade filer</span></p></body></html> + + + Delete Channel + Ta bort kanal + + + My Channels + Mina kanaler + + + Retroshare Demo Channel + Retroshares demokanal + + + Test channel 1 + Testa kanal 1 + + + Create New Channel + Skapa ny kanal + + + Channel Details + Kanaldetaljer + + + Rank + Ranking + + + Rs[Cert/Chan]IdSize + Rs[Cert/Kan]IdStorl + + + RsMsgId + RsMeddId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Meddelandetext</span></p></body></html> + + + Save changes + Spara ändringar + + + + MySubscriptionsDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Messages</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Meddelanden</span></p></body></html> + + + Date + Datum + + + From + Från + + + Title + Titel + + + Msg + Meddelande + + + Count + Antal + + + Size + Storlek + + + Type + Typ + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Rekommenderade filer</span></p></body></html> + + + My Subscriptions + Mina prenumerationer + + + Channel Details + Kanaldetaljer + + + Rank + Ranking + + + Rs[Cert/Chan]IdSize + Rs[Cert/Kan]IdStorl + + + RsMsgId + RsMeddId + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Message Text</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Meddelandetext</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Subscription:</span> </p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Prenumeration:</span> </p></body></html> + + + Retroshare Demo Channel + Retroshares demokanal + + + The Open Source Channel + Öppen källkodskanalen + + + Unsubscribe + Avsluta prenumereration + + + + NATStatus + + + <strong>NAT:</strong> + <strong>NAT:</strong> + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + UPNP is active. + UPNP är aktivt. + + + UPNP NOT FOUND. + UPNP HITTADES EJ. + + + Stable External IP Address + Stabil extern IP-adress + + + Not Found External Address + Hittade inte extern adress + + + UDP Port is reachable + UDP-port är anslutningsbar + + + UDP Port is not reachable + UDP-port är inte anslutningsbar + + + TCP Port is reachable + TCP-port är anslutningsbar + + + TCP Port is not reachable + TCP-port är inte anslutningsbar + + + Net Limited + Begränsad nätåtkomst + + + No Conectivity + Ingen anslutning + + + + OK | RetroShare Server + OK | RetroShare Server + + + OK | UDP Server + OK | UDP Server + + + + NetworkDialog + + RetroShare %1 started. + e.g: RetroShare v0.x started. + RetroShare %1 startad. + + + Welcome to RetroShare. + Välkommen till RetroShare. + + + Load Certificate + Läs in certifikat + + + Select a pem/pqi File + Välj en pem/pqi-fil + + + File Not Found + Filen hittades inte + + + %1 does not exist. Would you like to create it? + %1 finns inte. Vill du skapa den? + + + Failed to Create File + Misslyckades med att skapa fil + + + Unable to create %1 [%2] + Kunde inte skapa %1 [%2] + + + Accept + Godkänn + + + Select Certificate + Välj certifikat + + + Certificates (*.pqi *.pem) + Certifikat (*.pqi *.pem) + + + + Network + Nätverk + + + # + # + + + + + + Name + Namn + + + Organisation + Organisation + + + Location + Plats + + + Country + Land + + + is trusting you. +Right-click and select 'make friend' to be able to connect. + litar på dig. +Högerklicka och välj 'bli vän med' för att kunna ansluta. + + + Trust matrix + Pålitlighetsmatris + + + View + Vy + + + RetroShare %1 started. + RetroShare %1 startad. + + + + Deny friend + Neka vän + + + Accept friend + Acceptera vän + + + + Make friend + Skapa vän + + + + Delete certificate + Neka certifikat + + + + Export my Cert + + + + + Peer details... + Klientdetaljer... + + + Trusted + Pålitliga + + + Denied + Nekade + + + Is trusting me + Litar på mig + + + + Unknown + Okänd + + + Never seen + Har aldrig sett + + + None + Ingen + + + + Authentication matrix + + + + + Copy RetroShare Link + + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + + yourself + + + + RetroShare + RetroShare + + + Certificate file successfully created + Certifikatsfil skapad utan fel + + + Sorry, certificate file creation failed + Tyvärr, fel uppstod vid skapande av certifikatsfilen + + + UPNP is active. + UPNP är aktivt. + + + UPNP NOT FOUND. + UPNP HITTADES EJ. + + + DHT OK + DHT OK + + + DHT is not working (down). + DHT fungerar inte (nere). + + + Stable External IP Address + Stabil extern IP-adress + + + Not Found External Address + Hittade inte extern adress + + + RetroShare Server + RetroShare Server + + + UDP Server + UDP-server + + + Net Limited + Begränsad nätåtkomst + + + No Conectivity + Ingen anslutning + + + + Network View + Nätverksvy + + + Form + Formulär + + + + + Did peer authenticated me + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Nätverk:</span></p></body></html> + + + Your trust + Din pålitlighet + + + Peer's trust + Klientens pålitlighet + + + Last Contact + Senaste kontakt + + + Peer Address + Klientadress + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + + Cert Id + Cert-Id + + + + Search Network + + + + + Clear Filter + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Show keys that are not validated by the GPG web of trust + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + Klient-ID + + + Log + Logg + + + + Network Status + Nätverksstatus + + + + Local network + + + + + UPnP + + + + + External ip address finder + + + + + Add Friend + Lägg till en vän + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + Limited + Begränsad + + + UDP Connections + UDP-anslutningar + + + UPnP Active + UPnP Aktivt + + + + Clear + Rensa + + + + Set Tabs Right + Sätt tabbar höger + + + + Set Tabs North + Sätt tabbar norr + + + + Set Tabs South + Sätt tabbar söder + + + + Set Tabs Left + Sätt tabbar vänster + + + + Set Tabs Rounded + Sätt tabbar rundade + + + + Set Tabs Triangular + Sätt tabbar triangulär + + + UDP Port is active (UDP Connections) + UDP-port är aktiv (UDP-anslutningar) + + + UDP Port is not active + UDP-port är inte aktiv + + + TCP Port is active (TCP Server) + TCP-port är aktiv (TCP-server) + + + TCP Port is not active + TCP-port är inte aktiv + + + UPnP active + UPnP aktivt + + + UPnP inactive + UPnP inaktivt + + + DHT active + DHT aktivt + + + DHT inactive + DHT inaktivt + + + Stabile External IP Address + Stabil extern IP-adress + + + Not Found External IP Address + Hittade inte extern IP-adress + + + UDP Port is active ( UDP Connections ) + UDP-port är aktiv ( UDP-anslutningar ) + + + No Connectivity + Ingen anslutning + + + UDP + UDP + + + TCP Server + TCP-server + + + + NetworkView + + Hide Settings + Dölj inställningar + + + Show Settings + Visa inställningar + + + Settings + Inställningar + + + Form + Formulär + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + Friends + Vänner + + + + Edge length: + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); + + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); + + + + + + + Refresh + Uppdatera + + + Show Friends of Friends + Visa Vänner till vänner + + + Connect Signature + Anslutningssignatur + + + Draw Friend Connections + Rita vänanknytningar + + + + NewTag + + + New Tag + + + + + Name: + Namn: + + + + Choose color + + + + + OK + OK + + + + Cancel + Avbryt + + + + NewsFeed + + Form + Formulär + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/konqsidebar_news16.png" /></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/konqsidebar_news16.png" /></p></body></html> + + + + Remove All + Ta bort alla + + + + Options + Alternativ + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Nyhetsflöde</span></p></body></html> + + + + NotifyDialog + + Channels + Kanaler + + + Messages + Meddelanden + + + New Message + Nytt meddelande + + + News Feed + Nyhetsflöde + + + Peers + Klienter + + + Forums + Forum + + + Chat + Chatt + + + Blogs + Bloggar + + + Downloads + Nedladdningar + + + Popups + Popupfönster + + + Peer Connect + Klientanslutning + + + New Chat + Ny chatt + + + Private Chat Behaviour + Privat chatbeteende + + + Open Window for new Peer Chat + Öppna fönster för ny klientchatt + + + Reopen if closed by user: + Återöppna om stängd av användare: + + + Grab Focus when chat arrives + Fokusera när chatt ankommer + + + + NotifyPage + + + News Feed + Nyhetsflöde + + + + Peers + Klienter + + + + Channels + Kanaler + + + + Forums + Forum + + + + Chat + + + + + Blogs + Bloggar + + + + Messages + Meddelanden + + + Downloads + Nedladdningar + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + Meddelande + + + + Channel Post + + + + + Forum Post + Forum Posta + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + Peer Connect + Klientanslutning + + + + New Message + Nytt meddelande + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + Open Window for new Peer Chat + Öppna fönster för ny klientchatt + + + Reopen if closed by user: + Återöppna om stängd av användare: + + + + Grab Focus when chat arrives + Fokusera när chatt ankommer + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + Peer Online + Klient online + + + + Friend Online + + + + + OptionsDlg + + Color + Färg + + + Human + Människa + + + Computer + Dator + + + auto roll + rulla automatiskt + + + Colors + Färger + + + Colors: + Färger: + + + Points (1) + Poäng (1) + + + Points (2) + Poäng (2) + + + Board + Bräde + + + Case + Fodral + + + Ok + Ok + + + Cancel + Avbryt + + + + PeerDefs + + Anonymous + Anonym + + + + + Unknown + Okänd + + + + PeerItem + + Remove Friend + Ta bort vän + + + + Name: + Namn: + + + Organisation + Organisation + + + + Location + Plats + + + Country + Land + + + Form + Formulär + + + + Remove Item + Radera objekt + + + Connected + Ansluten + + + + + Expand + Utöka + + + + Write a quick Message + + + + + Send + Skicka + + + + Cancel + Avbryt + + + + Peer ID: + + + + + Write Message + + + + + Start Chat + + + + + Status: + Status: + + + + Trust: + Pålitlig: + + + Good + Bra + + + Make Friend + Skapa vän + + + Send Mail + Skicka mail + + + + Chat + Chatta + + + RsId: + RsId: + + + TextLabel + TextEtikett + + + + IP Address + Ip-adress + + + + Connection Method + Anslutningsmetod + + + Last Contact: + Senaste kontakt: + + + + Friend + Vän + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + Klient + + + + + + + + + + + + Unknown Peer + + + + + Hide + Dölj + + + + Quick Message + + + + + PeerStatus + + Online: 0 | Friends: 0 | Network: 0 + Online: 0 | Vänner: 0 | Nätverk: 0 + + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + Vänner + + + Online + Ansluten + + + <span style="color:#000000"><strong>Friends:</strong></span> + <span style="color:#000000"><strong>Vänner:</strong></span> + + + <span style="color:#0000FF"><strong>Online:</strong></span> + <span style="color:#0000FF"><strong>Online:</strong></span> + + + Online: + Online: + + + Friends: + Vänner: + + + Network: + Nätverk: + + + + PeersDialog + + Chat + Chatta + + + Export Friend + Exportera vän + + + Remove Friend + Ta bort vän + + + Save Certificate + Spara certifikat + + + Certificates (*.pqi) + Certifikat (*.pqi) + + + Status + Status + + + Person + Person + + + Connect To Friend + Anslut till vän + + + # + # + + + Profile + Profil + + + Paste retroshare Link + Klistra in retrosharelänk + + + Welcome to RetroShare's group chat. + Välkommen till RetroShares gruppchatt. + + + Expand all + Expandera alla + + + Collapse all + Komprimera alla + + + Message Friend + Meddelandevän + + + Peer Details + Klientdetaljer + + + Deny Friend + Neka vän + + + Remove Friend Location + Ta bort kompis location + + + <strong>GPG Key</strong> + <strong>GPG Nyckel</strong> + + + <strong>RetroShare instance</strong> + <strong>RetroShare instance</strong> + + + location : + Ort: + + + Online + Ansluten + + + Peer Online + Klient online + + + Away + Frånvarande + + + Busy + Upptagen + + + Available + Tillgänglig + + + Your Friend is offline +Do you want to send them a Message instead + Din vän är offline +Vill du skicka ett meddelande i stället + + + RetroShare + RetroShare + + + Add Extra File + Lägg till extra fil + + + File Request Confirmation + Bekräfta filförfrågan + + + The file has been added to your download list. + Filen har lagts till i din nedladdningslista. + + + File Request canceled + File begäran avbryts + + + The file has not been added to your download list, because you already have it. + Filen har inte lagts till i din nedladdning listan, eftersom du redan har det. + + + + File Request Error + Filförfrågningsfel + + + The file link is malformed. + Fillänken är missbildad. + + + Drop file error. + Filsläppningsfel. + + + File not found or file name not accepted. + Filen hittades inte eller filnamn ogiltigt. + + + Directory can't be dropped, only files are accepted. + Kataloger kan inte dra och släppas, endast filer. + + + News Feed + Nyhetsflöde + + + Friend + Vän + + + Location + Plats + + + Save as... + Spara som... + + + me + jag + + + Send + Skicka + + + Profile View + Profilvy + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Vänner</span></p></body></html> + + + Live Group Chat: + Live Gruppchatt: + + + Italic + Kursiv + + + Underline + Understruken + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Vänner</span></p></body></html> + + + Add + Lägg till + + + hide unconnected + Hide osammanhängande + + + Add or Change your Avatar + Lägga till eller ändra din avatar + + + Edit Personal message + Redigera Personligt meddelande + + + Bold + Fet + + + Create New Forum + Skapa ett forum + + + Create new Forum + Skapa ett forum + + + Create New Channel + Skapa ny kanal + + + Display + Visa + + + Create new Channel + Skapa ny kanal + + + Add your Avatar Picture + Lägg till din avatar bild + + + Set your Personal Message + Ställ din personliga meddelande + + + Edit your status Message + Edit your status message + + + Disable Emoticons + Inaktivera Emoticons + + + Text Color + Textfärg + + + Add Friend + Lägg till en vän + + + Font + Typsnitt + + + Friends + Vänner + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">set Text Color</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ställa Textfärg</span></p></body></html> + + + Attach File + Bifoga fil + + + Clear Chat History + Rensa chatthistorik + + + + PeersFeed + + Save Certificate + Spara certifikat + + + Certificates (*.pqi) + Certifikat (*.pqi) + + + Friends + Vänner + + + Form + Formulär + + + Show: + Visa: + + + Online Friends + Vänner online + + + Friends of Friends. + Vänner till vänner. + + + All Peers + Alla klienter + + + + PhotoDialog + + + Insert Show Lists + Infoga visningslistor + + + + Open + + + + + Remove + Ta bort + + + + Excellent + + + + + Good + Bra + + + + Average + Medel + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + + Date + Datum + + + + + Location + Plats + + + + Size + Storlek + + + Form + Formulär + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Fotovy</span></p></body></html> + + + + Peer + Klient + + + + Slideshow + Bildspel + + + + Photo + Foto + + + + Thumb Image + Miniatyrbild + + + + Image Name + Bildnamn + + + + + Comment + Kommentar + + + + PeerId + Klient-ID + + + + PhotoId + Foto-ID + + + + + Add Photo(s) + Lägg till foto(n) + + + + Add Photo SlideShow + Lägg till foto till bildspel + + + + Update Details + Uppdatera detaljer + + + + Photo + Foto + + + + Description + Beskrivning + + + + PhotoShow + + + Location: + Plats: + + + Form + Formulär + + + + Date: + Datum: + + + + Comment: + Kommentar: + + + + Display Size: + Visningsstorlek: + + + + 320 x 320 + 320 x 320 + + + + 640 x 640 + 640 x 640 + + + + Full Size + Fullstorlek + + + + Play Rate: + Bläddringshastighet: + + + + 1 Sec + 1 sek + + + + 2 Sec + 2 sek + + + + 5 Sec + 5 sek + + + + 10 Sec + 10 sek + + + + 20 Sec + 20 sek + + + + 1 Min + 1 min + + + + Edit Photo Details + Redigera fotodetaljer + + + + Save Photo + Spara foto + + + + No Photo Selected + Inget foto markerat + + + + Start + Starta + + + + Back + Tillbaka + + + + Photo Show + + + + + Play + Spela + + + + Pause + Paus + + + + Forward + Framåt + + + + PluginFrame + + + Remove + Ta bort + + + + PluginManagerWidget + + + Install New Plugin... + Installera nytt plugin... + + + + Open Plugin to install + Öppna plugin att installera + + + + Plugins (*.so *.dll) + Plugin (*.so *.dll) + + + + PopularityDefs + + + Popularity + Popularitet + + + + PopupChatDialog + + Paste retroshare Link + Klistra in retrosharelänk + + + RetroShare + RetroShare + + + + Your Friend is offline +Do you want to send them a Message instead + Din vän är offline +Vill du skicka ett meddelande i stället + + + + Friend not Online + + + + + Paste RetroShare Link + + + + + is typing... + + + + + Hide Avatar + Göm avatar + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Messages you send will be delivered after Friend is again Online + + + + :images/hide_toolbox_frame.png + :images/hide_toolbox_frame.png + + + + Show Avatar + Visa avatar + + + :images/show_toolbox_frame.png + :images/show_toolbox_frame.png + + + Open Style + Öppna stil + + + Styles (*.htm) + Stilar (*.htm) + + + + Save as... + Spara som... + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + Send + Skicka + + + RetroShare - Encrypted Chat + RetroShare - Krypterad chatt + + + MainWindow + Huvudfönster + + + QLabel{ +border-image: url(:/images/mystatus_bg.png); + +} + QLabel{ +border-image: url(:/images/mystatus_bg.png); + +} + + + TextLabel + TextEtikett + + + + Close + Stäng + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Set Chat Window Style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ange chattfönsterstil</p></body></html> + + + + + Bold + Fet + + + + + Underline + Understruken + + + + + Italic + Kursiv + + + Set Font + Ange typsnitt + + + + Font + Typsnitt + + + + Text Color + Textfärg + + + + Clear Chat History + Rensa chatthistorik + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + toolBar + Verkygsfält + + + + Strike + Strike + + + Avatar + Avatar + + + Set your Avatar Picture + Ange din avatarbild + + + + Disable Emoticons + Inaktivera Emoticons + + + + + Save Chat History + + + + + Clear offline messages + + + + Chatting with + Chattar med + + + + Add Extra File + Lägg till extra fil + + + File Request Confirmation + Bekräfta filförfrågan + + + The file has been added to your download list. + Filen har lagts till i din nedladdningslista. + + + File Request canceled + File begäran avbryts + + + File Request Error + Filförfrågningsfel + + + The file link is malformed. + Fillänken är missbildad. + + + + + Drop file error. + Filsläppningsfel. + + + + File not found or file name not accepted. + Filen hittades inte eller filnamn ogiltigt. + + + + Directory can't be dropped, only files are accepted. + Kataloger kan inte dra och släppas, endast filer. + + + + Add a File for your Friend + Lägg till en fil till din vän + + + + PopupChatWindow + + + Avatar + Avatar + + + + Set your Avatar Picture + Ange din avatarbild + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + RetroShare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PopupWindowClass + + PopupWindow + Popupfönster + + + + PreferencesWindow + + Directories + Kataloger + + + Error Saving Configuration + Fel vid sparande av konfiguration + + + General + Allmänt + + + Server + Server + + + Options + Alternativ + + + Cancel + Avbryt + + + OK + OK + + + Appearance + Utseende + + + Notify + Meddela + + + Help + Hjälp + + + File assotiations + Filassociationer + + + + PrintPreview + + + RetroShare Message - Print Preview + RetroShare-meddelande - Förhandsgranskning + + + + Print + Skriv ut + + + + &Print... + Skriv &ut.... + + + + Page Setup... + Utskriftsformat... + + + + Zoom In + Zooma in + + + + Zoom Out + Zooma ut + + + + &Close + Stäng + + + + ProfileEdit + + + Remove Profile Entry + Ta bort profilinlägg + + + + Move Profile Entry Up + Flytta upp profilinlägg + + + + Move Profile Entry Down + Flytta ned profilinlägg + + + + Profile Edit + Redigera profil + + + + Profile + Profil + + + + Category + Kategori + + + + Thoughts + Tankar + + + + Edit Profile Category + Redigera profilkategori + + + + Birthday + Födelsedag + + + + School + Skola + + + + University + Universitet + + + + Phone Number + Telefonnummer + + + + Favourite Books + Favoritböcker + + + + Favourite Music + Favoritmusik + + + + Favourite Films + Favoritfilmer + + + + or Custom Entry + eller Valfritt inlägg + + + + Add Entry + Lägg till inlägg + + + + + Move + Flytta + + + + Close Editor + Stäng redigerare + + + + ProfileView + + + Clear Photo + Rensa foto + + + + Change Photo + Ändra foto + + + + + Edit Profile + Redigera profil + + + + Remove Favourite + Ta bort favorit + + + + Clear Favourites + Rensa favoriter + + + + Download File + Ladda ned fil + + + + Download All + Hämta alla + + + + RetroShare + RetroShare + + + + Error : cannot get peer details. + + + + + + Name + Namn + + + + Peer ID + Klient-ID + + + + Size + Storlek + + + + Profile View + Profilvy + + + Rs ID + Rs ID + + + + Last Post: + Senaste inlägg: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profil</span></p></body></html> + + + + Category + Kategori + + + + Thoughts + Tankar + + + + Favourite Files + Favoritfiler + + + + Hash + Hash + + + + Close Profile + Stäng profil + + + + ProfileWidget + + Form + Formulär + + + + + Edit Personal message + Redigera Personligt meddelande + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + TextLabel + TextEtikett + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + and + och + + + and / or + och / eller + + + or + eller + + + Name + Namn + + + Path + Sökväg + + + Extension + Filändelse + + + Hash + Hash + + + Date + Datum + + + Size + Storlek + + + Popularity + Popularitet + + + contains + innehåller + + + contains all + innehåller alla + + + is + är + + + less than + mindre än + + + less than or equal + mindre än eller lika med + + + equals + lika med + + + greater than or equal + större än eller lika med + + + greater than + större än + + + is in range + är inom omfång + + + + + RetroShare + RetroShare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + Bekräfta filförfrågan + + + + The file has been added to your download list. + Filen har lagts till i din nedladdningslista. + + + + + File Request canceled + File begäran avbryts + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + Filen har inte lagts till i din nedladdning listan, eftersom du redan har det. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + Filförfrågningsfel + + + + The file link is malformed. + Fillänken är missbildad. + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + Neka vän + + + + Make friend + Skapa vän + + + + Peer details + Klientdetaljer + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + Nästa > + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + Brandväggsskyddad + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + < Tillbaka + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + Kataloger + + + + Network Wide + + + + + Browseable + + + + + Add + Lägg till + + + + Remove + Ta bort + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + Delad katalog tillagd! + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + Varning! + + + + RSettingsWin + + + General + Allmänt + + + + Directories + Kataloger + + + + Server + Server + + + + Transfer + Överföring + + + + Notify + Meddela + + + + Security + + + + + Message + Meddelande + + + + Forum + Forum + + + + Chat + + + + + Appearance + Utseende + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + Error Saving Configuration + Fel vid sparande av konfiguration + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>Ner:</strong> 0.00 (kB/s) | <strong>Upp:</strong> 0.00 (kB/s) + + + + <strong>Down:</strong> + <strong>Ner:</strong> + + + + <strong>Up:</strong> + <strong>Upp:</strong> + + + Down: + Ner: + + + Up: + Upp: + + + + RemoteDirModel + + Friends Directories + Vänners kataloger + + + My Directories + Mina kataloger + + + Size + Storlek + + + Rank + Ranking + + + Age + Ålder + + + FILE + FIL + + + Anonymous + Anonym + + + Files + Filer + + + DIR + KAT + + + + RetroshareDirModel + + + Anonymous + Anonym + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + Ogiltig språkkod angiven: + + + + Invalid GUI style specified: + Ogiltigt användargränssnitt valt: + + + + Resets ALL stored RetroShare settings. + Återställer ALLA sparade RetroShare-inställningar. + + + + Sets the directory RetroShare uses for data files. + Anger katalog som RetroShare använder för datafiler. + + + + Sets the name and location of RetroShare's logfile. + Anger namn och plats för RetroShares loggfil. + + + Sets the verbosity of Vidalia's logging. + Anger ordrikedom för Vidalias loggning. + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + Anger RetroShares gränssnittsstil. + + + + Sets RetroShare's interface stylesheets. + Anger RetroShares gränssnittsstilmallar. + + + + Sets RetroShare's language. + Anger RetroShares språk. + + + + RetroShare Usage Information + Information om RetroShareanvändning + + + + Invalid log level specified: + Ogiltig loggningsnivå angiven: + + + + Unable to open log file '%1': %2 + Kan inte öppna loggfil '%1': %2 + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + B + + + + KB + KB + + + + MB + MB + + + + GB + GB + + + + SearchDialog + + + Sources + Källor + + + + Results + Resultat + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + Filnamn + + + + File Size + + + + + Close all Search Resullts + + + + + Download Selected + + + + + + Download + Hämta + + + + Enter a keyword here (at least 3 char long) + + + + Copy retroshare Link + Kopiera retrosharelänk + + + Send retroshare Link + Skicka retrosharelänk + + + Broadcast on Channel + Sänd på kanal + + + Recommend to Friends + Rekommendera till vänner + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + Ta bort + + + + Remove All + Ta bort alla + + + + + Folder + Katalog + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + + Any + Alla + + + + Audio + Ljud + + + + Video + Video + + + Images + Bilder + + + Programs + Program + + + Archives + Arkiv + + + Documents + Dokument + + + + Download Notice + Nedladdningsnotering + + + + Skipping Local Files + Hoppa över lokala filer + + + + + Sorry + Ledsen + + + + + This function is not yet implemented. + Denna funktion är inte implemeterad än. + + + + Size + Storlek + + + + Type + Typ + + + Toggle advanced searching on and off. + Avancerad sökning av eller på. + + + <h3>Simple Search:</h3> + <h3>Enkel sökning:</h3> + + + Keywords + Nyckelord + + + + Archive + Arkiv + + + + CD-Image + CD-avbild + + + + Document + Dokument + + + + Picture + Bild + + + + Program + Program + + + Perform simple search + Utför enkel sökning + + + <h3>Advanced Search:</h3> + <h3>Avancerad sökning:</h3> + + + Show Advanced Search Tool + Visa avancerade sökverktyg + + + + Filename + Filnamn + + + + Age + Ålder + + + + Hash + Hash + + + + KeyWords + Nyckelord + + + + Directory + Kataloger + + + + Start Search + Starta sökningen + + + + Search + Sök + + + + Reset + Nollställ + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Search Id + Sök-Id + + + Clear all Search Results + Stäng all sökningar + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reset Search Keyword and File Type</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Återställ nyckelord och filtyp för sökning</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download Select</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Val av nedladdning</p></body></html> + + + + Close All Search Results + Stäng alla sökresultat + + + + SendLinkDialog + + Send + Skicka + + + + ServerDialog + + Port: + Port: + + + Network Configuration (takes effect after restart) + Nätverkskonfiguration (får effekt efter omstart) + + + Automatic + Automatisk + + + Firewalled + Brandväggsskyddad + + + Forwarded Port + Vidarebefodrad port + + + DHT Enabled + DHT aktiverat + + + DHT Disabled + DHT inaktiverat + + + Discovery Enabled + Upptäckt aktiverat + + + Discovery Disabled + Upptäckt inaktiverat + + + Network Configuration + Nätverkskonfiguration + + + Local Address + Lokal adress + + + External Address + Extern adress + + + IP Service + IP-service + + + IP check service + IP-kontrollservice + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + Om du avmarkerar detta, kan RetroShare endast avgöra ditt IP +när du ansluter till någon. Genom att behålla denna markerad +hjälper det till att ansluta om du har få vänner. Det hjälper också +om du sitter bakom en brandvägg eller VPN. + + + Allow RetroShare to ask my ip to these websites: + Tillåt RetroShare att fråga efter mitt ip till dessa webbsidor: + + + Transfer Rates + Överföringshastighet + + + Download (KB/s) + Nedladdning (KB/s) + + + Upload (KB/s) + Uppladdning (KB/s) + + + + ServerPage + + Server Settings + Serverinställningar + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Extern adress:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal adress:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + + + + Automatic (Upnp) + + + + + Firewalled + Brandväggsskyddad + + + + Manual Forwarded Port + + + + Discovery Enabled + Upptäckt aktiverat + + + Discovery Disabled + Upptäckt inaktiverat + + + + Transfer Rates + Överföringshastighet + + + + Download (KB/s) + Nedladdning (KB/s) + + + + + kB/s + + + + + Upload (KB/s) + Uppladdning (KB/s) + + + + + Network Configuration + Nätverkskonfiguration + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + Lokal adress + + + + External Address + Extern adress + + + + Dynamic DNS + + + + + + Port: + Port: + + + + Show Discovery information in statusbar + + + + + IP Service + IP-service + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + Om du avmarkerar detta, kan RetroShare endast avgöra ditt IP +när du ansluter till någon. Genom att behålla denna markerad +hjälper det till att ansluta om du har få vänner. Det hjälper också +om du sitter bakom en brandvägg eller VPN. + + + + Allow RetroShare to ask my ip to these websites: + Tillåt RetroShare att fråga efter mitt ip till dessa webbsidor: + + + Misc + Diverse + + + + Settings + + Settings + Inställningar + + + + Options + Alternativ + + + + Transfer + Överföring + + + + Notify + Meddela + + + + Security + + + + + Message + Meddelande + + + + Forum + Forum + + + + Chat + + + + + Appearance + Utseende + + + + Sound + + + + + Cancel + Avbryt + + + Apply + Verkställ + + + + OK + OK + + + + General + Allmänt + + + Network + Nätverk + + + + Server + Server + + + + Directories + Kataloger + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + Bläddra + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + Anonymous + Anonym + + + + Browseable by Friends + + + + Friends + Vänner + + + + OK + OK + + + + Cancel + Avbryt + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + Avbryt + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + RetroShare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + Lägg till delad katalog + + + + Stop sharing selected Directory + + + + Remove selected Shared Directory + Ta bort markerad delad katalog + + + + + Remove + Ta bort + + + Add Shared Directory + Lägg till delad katalog + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + Varning! + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + Filsläppningsfel. + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + Shared Directory Added! + Delad katalog tillagd! + + + Do You Want to Remove ? + Vill du ta bort? + + + + RetroShare Share Manager + RetroShare delningshanterare + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#32cd32;">Share Manager</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"><span style=" font-size:10pt;">Add a new Folder to Share with your Friends or remove a Shared Folder.</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#32cd32;">Delningshanterare</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"><span style=" font-size:10pt;">Lägg till en ny katalog att dela med dina vänner eller ta bort en delad katalog.</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + Folderdelningshanterare + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + Kataloger + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + Lägg till + + + + Close + Stäng + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + Hämta + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Filer</span></p></body></html> + + + Add to Recommend List + Lägg till i rekommendationer + + + Recommend To + Rekommendera till + + + + Checking... + Kontrollerar... + + + + Check files + Kontrollera filer + + + + Copy retroshare Link + Kopiera retrosharelänk + + + + Send retroshare Link + Skicka retrosharelänk + + + Recommend (Automated message) To + Rekommendera (automatiserat meddelande) till + + + Recommend in a message to + Rekommendera i ett meddelande till + + + + Copy retroshare Links to Clipboard + Kopiera retroshare Länkar till Urklipp + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + Skicka retroshare Länkar + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + Öppna fil + + + + Open Folder + Öppna katalog + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + Ange kommando för öppning av denna fil + + + + <strong>My Shared Files</strong> + <strong>Mina Filer</strong> + + + + <strong>Friends Files</strong> + <strong>Vänner filer</strong> + + + + <strong>Files</strong> + <strong>Filer</strong> + + + Friends Share + Delning mellan vänner + + + My Shared Files + Mina delade filer + + + + Splitted View + + + + + Friends Folders + Vänner filer + + + + My Folders + Mina Filer + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Filer</span></p></body></html> + + + + All + Alla + + + + One day old + En dag gammal + + + + One Week old + En vecka gamla + + + + One month old + En månad gammal + + + + Search files + + + + + Start Search + Starta sökningen + + + + Reset + Nollställ + + + + Tree view + + + + + Flat view + + + + + Download selected + Ladda ned markerade + + + + check files + kontrollera filer + + + + SoundPage + + + Sound Events + + + + + go Online + + + + ... + ... + + + + Friend + Vän + + + + + + + + Browse + Bläddra + + + + New Msg + Nytt meddelande + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + RetroShare + + + generate new a profile + generera en ny profil + + + Auto-login + Automatisk inloggning + + + Name: + Namn: + + + PGP Password + PGP-lösenord + + + + Log In + Logga in + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Logga in</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:10pt;">You can login with your Default</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">RetroShare profile.</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">You have a Profile?</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:10pt;">Du kan logga in med din standard</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">RetroShare-profil.</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">Har du en profil?</p></body></html> + + + Generate now a Profile + Generera en profil nu + + + Password: + Lösenord: + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + Statistics + Statistik + + + + Download + Hämta + + + + Session: + Session: + + + + + Downloaded: + Hämtat: + + + + + + Session + Session + + + + + + + Connections: + Anslutningar: + + + Misc + Diverse + + + + + Show Settings + Visa inställningar + + + + Reset + Nollställ + + + + Always On Top + Alltid överst + + + + 100 + 100 + + + + Save + Spara + + + + Cancel + Avbryt + + + + Hide Settings + Dölj inställningar + + + + %1 days + %1 dagar + + + + Since: + Sedan: + + + + Now + Nu + + + + Transfer + Överföring + + + + Session UL:DL Ratio: + Session Upp/Ned-förhållande: + + + + Cumulative UL:DL Ratio + Ackumulerad Upp/Ned-förhållande + + + + + Count of Downloads: + Nedladdningsräknare: + + + + + + Overall + Totalt + + + + Upload + Uppladning + + + + Uploaded: + Uppladdat: + + + + + Count of Uploads: + Uppladdningsräknare: + + + + Uploaded + Uppladdat + + + + + + Peers: + Klienter: + + + + Time Statistics + Tidsstatistik + + + + + Uptime + Upptid + + + + Cumulative + Ackumulerat + + + + Records + Anteckingar + + + + Uploadspeed: + Uppladdningshastighet: + + + + Downloadspeed: + Nedladdningshastighet: + + + + Uptime: + Upptid: + + + + Receive Rate + Mottagningshastighet + + + + Send Rate + Sändningshastighet + + + + % Opaque + % Ogenomskinlig + + + + Changes the transparency of the Bandwidth Graph + Ändrar transparensen av bandbreddsgrafen + + + + StatusDefs + + + + Offline + + + + + Away + Frånvarande + + + + Busy + Upptagen + + + + Online + Ansluten + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + Ansluten + + + + Unreachable + + + + + Available + Tillgänglig + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + Personligt meddelande + + + + Status message + Statusmeddelande + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personligt meddelande</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Ange ditt statusmeddelande</span></p></body></html> + + + + OK + OK + + + + Cancel + Avbryt + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + Stil + + + + None + Ingen + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + Typ + + + Form + Formulär + + + Person/Channel Name + Person/Kanalnamn + + + + Delete FeedItem + Ta bort flödesobjekt + + + + SubFileItem + + File Name + Filnamn + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + Spara kanalfil + + + Form + Formulär + + + + Download + Hämta + + + + Play + Spela + + + + %p Kb + %p Kb + + + Expand + Utöka + + + + Save File + Spara fil + + + + Cancel Download + Avbryt nedladdning + + + + Download File + Ladda ned fil + + + + + + Play File + Spela fil + + + + TBoard + + + Pause + Paus + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Please, paste your friends PGP certificate into the box below + + + + + Clean certificate + + + + + RetroShare Invite + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + RetroShare + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + Spara som... + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Text certificate + Textcertifikat + + + Use text representation of the XPGP certificates. + Använd textrepresentation av XPGP-certifikat. + + + The text below is your XPGP certificate. You have to provide it to your friend + Texten nedan är ditt XPGP-certifikat. Du måste ge detta till din vän + + + + Run Email program + Kör epostklient + + + Please, paste your friends XPGP certificate into the box below + Klistra in dina vänners XPGP-certifikat i rutan nedan + + + + Connect Friend Help + Anslut vän-hjälp + + + You can copy this text and send it to your friend via email, ICQ or some other way + Du kan kopiera denna text och skicka till dina vänner via epost, ICQ eller annat sätt + + + + Certificate Load Failed + Inläsning av certifikat misslyckades + + + + TransferFeed + + Form + Formulär + + + Sort: + Sortera: + + + None + Ingen + + + + TransferPage + + Form + Formulär + + + Transfer + Överföring + + + + Transfer options + Överföringsalternativen + + + + Queue Size: + Kö Storlek: + + + Maximum Download speed per file: + Maximal nedladdningshastighet per ärende: + + + + Default chunk strategy: + Standard chunk strategi: + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + Show Cache Transfers + Visa Cache Överföringar + + + + TransfersDialog + + + Cancel + Avbryt + + + + Clear Completed + Töm färdiga + + + + + Status + Status + + + + Completed + Färdig + + + + + Name + i.e: file name + Filnamn + + + + + Size + i.e: file size + Storlek + + + + Speed + i.e: Download speed + Hastighet + + + Progress + i.e: % downloaded + Förlopp + + + + Sources + i.e: Sources + Källor + + + Remaining + i.e: Estimated Time of Arrival / Time left + Återstår + + + + Core-ID + Kärn-ID + + + User Name + i.e: user name + Användarnamn + + + + Progress / Availability + i.e: % downloaded + + + + + Remaining + Återstår + + + + Download time + i.e: Estimated Time of Arrival / Time left + Hämtningstid + + + + Peer + i.e: user name + Klient + + + + Progress + i.e: % uploaded + Förlopp + + + + Speed + i.e: upload speed + Hastighet + + + + Transferred + Överfört + + + + Hash + Hash + + + + Router Statistics + + + + + Router Requests + + + + + Force Check + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + Play + Spela + + + + Pause + Paus + + + + Resume + Återuppta + + + + Open Folder + Öppna katalog + + + + Open File + Öppna fil + + + + Preview File + Förhandsgranska fil + + + + Details... + Detaljer... + + + Copy retroshare Link + Kopiera retrosharelänk + + + Paste retroshare Link + Klistra in retrosharelänk + + + Set Root is not Decorated + This is obviously an incorrect translation, but I'm not quite sure how to translate it... + Ange rot är inte dekorerad + + + Set Root is Decorated + This is obviously an incorrect translation, but I'm not quite sure how to translate it... + Ange rot är dekorerad + + + View + Visa + + + + + Slower + Långsammare + + + + + + Average + Medel + + + + + Faster + Snabbare + + + + Move in Queue... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + Chunk strategi + + + + version: + + + + + Queued + + + + + Speed / Queue position + Hastighet / kö position + + + + Down + Nere + + + + + Up + Upp + + + + Top + Topp + + + + Bottom + Botten + + + + Priority (Speed)... + Prioritet (Hastighet) ... + + + + Paused + Pausad + + + + Transferring + Överföra + + + + Checking... + Kontrollerar... + + + + RetroShare + RetroShare + + + + Details: + Detaljer: + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + Öppna överföring + + + + File %1 is not completed. If it is a media file, try to preview it. + Fil %1 är inte komplett. Om det är en mediafil, försök att förhandsgranska den. + + + + Are you sure that you want to cancel and delete these files? + Är du säker att du vill avbryta och ta bort dessa filer? + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Nedladdningar:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Nedladdningar:</span></p></body></html> + + + + Show cache transfers + + + + + Uploads + Uppladdningar + + + + Selected transfer + Valda överföring + + + + Done + Färdig + + + + Active + Aktiva + + + + Outstanding + Utestående + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uppladdningar:</span></p></body></html> + + + + + + Failed + Misslyckades + + + + + + Okay + Okej + + + + + Waiting + Väntar + + + + Downloading + Hämtar + + + + + + + Complete + Fullständig + + + + Unknown + Okänd + + + + Uploading + Laddar upp + + + + TreeStyle_RDM + + + + FILE + FIL + + + + Files + Filer + + + + File + + + + + + DIR + KAT + + + + Friends Directories + Vänners kataloger + + + + My Directories + Mina kataloger + + + + Size + Storlek + + + + Age + Ålder + + + + Friend + Vän + + + + Share Type + + + + + What's new + + + + + TrustView + + Form + Formulär + + + + Zoom : + Zooma : + + + + Update + Uppdatera + + + + + Showing: whole network + Visar: hela nätverket + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + File Name + Filnamn + + + Hash + Hash + + + Type + Typ + + + Age + Ålder + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + TurtleSearchDialog + + Download + Hämta + + + Broadcast on Channel + Sänd på kanal + + + Recommend to Friends + Rekommendera till vänner + + + Download Notice + Nedladdningsnotering + + + Skipping Local Files + Hoppa över lokala filer + + + Sorry + Ledsen + + + This function is not yet implemented. + Denna funktion är inte implemeterad än. + + + Remove + Ta bort + + + Remove All + Ta bort alla + + + Toggle advanced searching on and off. + Avancerad sökning av eller på. + + + <h3>Simple Search:</h3> + <h3>Enkel sökning:</h3> + + + Keywords + Nyckelord + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + Any + Alla + + + Archive + Arkiv + + + Audio + Ljud + + + CD-Image + CD-avbild + + + Document + Dokument + + + Picture + Bild + + + Program + Program + + + Video + Video + + + Perform simple search + Utför enkel sökning + + + <h3>Advanced Search:</h3> + <h3>Avancerad sökning:</h3> + + + Show Advanced Search Tool + Visa avancerade sökverktyg + + + Filename + Filnamn + + + Size + Storlek + + + Sources + Källor + + + Type + Typ + + + Hash + Hash + + + KeyWords + Nyckelord + + + Results + Resultat + + + Search Id + Sök-Id + + + + ULListDelegate + + + B + B + + + + KB + KB + + + + MB + MB + + + + GB + GB + + + + VMessageBox + + + OK + OK + + + + Cancel + Avbryt + + + + Yes + Ja + + + + No + Nej + + + + Help + Hjälp + + + + Retry + Försök igen + + + + Show Log + Visa logg + + + + Show Settings + Visa inställningar + + + + Continue + Fortsätt + + + + Quit + Avsluta + + + + Browse + Bläddra + + + + misc + + + Unknown + Unknown (size) + Okänd + + + + B + bytes + B + + + + KiB + kibibytes (1024 bytes) + KiB + + + + MiB + mebibytes (1024 kibibytes) + MiB + + + + GiB + gibibytes (1024 mibibytes) + GiB + + + + TiB + tebibytes (1024 gibibytes) + TiB + + + + Unknown + Okänd + + + + < 1m + < 1 minute + < 1 minut + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + %1m + e.g: 10minutes + %1 minuter + + + + %1h %2m + e.g: 3hours 5minutes + %1 timme och %2 minuter + + + %1d %2h %3m + e.g: 2days 10hours 2minutes + %1 dag %2 timmar %3 minuter + + + + moreinfo + + Details + Detaljer + + + OK + OK + + + Name + Namn + + + Value + Värde + + + diff --git a/retroshare-gui/src/lang/retroshare_tr.qm b/retroshare-gui/src/lang/retroshare_tr.qm new file mode 100644 index 000000000..14846f711 Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_tr.qm differ diff --git a/retroshare-gui/src/lang/retroshare_tr.ts b/retroshare-gui/src/lang/retroshare_tr.ts new file mode 100644 index 000000000..919928d91 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_tr.ts @@ -0,0 +1,11544 @@ + + + + + AboutDialog + + About + About + + + About RetroShare + + + + close + + + + About RetroShare %1 + + + + Max score: %1 + + + + Score: %1 + + + + Level: %1 + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + RetroShare + Retroshare + + + File type(extension): + + + + Use default command + + + + Command + + + + Sorry, can't determine system default command for this file + + + + + + AddLinksDialog + + Add Link + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + Cancel + + + + Add a new Link + + + + Title: + + + + Url: + + + + Add Anonymous Link + + + + +2 Great! + + + + +1 Good + + + + 0 Okay + + + + -1 Sux + + + + -2 Bad Link + + + + Add Link Failure + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + Cancel + geçersiz kılmak + + + Search + araştırmak + + + RetroShare: Advanced Search + + + + Search Criteria + + + + Add a further search criterion. + + + + Reset the search criteria. + + + + Cancels the search. + + + + Perform the advanced search. + + + + + AppearancePage + + Language + Dil + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + Style + Style + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + Style Sheet + Style Sheet + + + + ApplicationWindow + + Hide + Hide + + + Show + Show + + + RetroShare + Retroshare + + + Transfers + Transfers + + + Messages + Email + + + Statistics + Statistics + + + Photo View + + + + Games Launcher + + + + Shared Calendars + + + + + AttachFileItem + + File Name + Dosya Ad + + + Cancel Download + Iptal + + + Form + + + + %p Kb + + + + + BandwidthGraph + + Show Settings + Show Settings + + + Reset + Reset + + + Receive Rate + Receive Rate + + + Send Rate + Send Rate + + + Style + Style + + + Changes the transparency of the Bandwidth Graph + Changes the transparency of the Bandwidth Graph + + + 100 + 100 + + + % Opaque + % Opaque + + + Save + Save + + + Cancel + geçersiz kılmak + + + Hide Settings + Hide Settings + + + RetroShare Bandwidth Usage + + + + Always on Top + + + + Since: + + + + + BlogDetails + + Popularity + Popülerlik: + + + Last Post + Son Mesaj + + + Close + bağlantılı + + + Blog Details + + + + Blog Info + + + + Blog Name + + + + Blog ID + + + + Blog Description + + + + Cancel + + + + OK + + + + + BlogDialog + + Blogs + Bloglar + + + + BlogMsgItem + + Expand + Genişlet + + + Subject + Konu + + + Form + + + + Remove Item + + + + Play Media + + + + + BlogNewItem + + Expand + Genişlet + + + Remove Item + + + + Subscribe to Blog + + + + Blog Decscription + + + + + BlogsDialog + + Add + Ekle + + + Unsubscribe + Iptal + + + Subscribe + Abone Ol + + + Name + Name + + + Form + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + Create New Blog + + + + ID + + + + Own Blogs + + + + Subscribed Blogs + + + + Popular Blogs + + + + Other Blogs + + + + Post to Blog + + + + Subscribe to Blog + + + + Unsubscribe to Blog + + + + Show Blog Details + + + + Create a new Blog + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + Expand + Genişlet + + + Hide + Hide + + + Form + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + Remove Item + + + + Unsubscribe From Channel + + + + Comments here + + + + Comment + + + + + CalDialog + + Remove + Remove + + + Status: + Durum: + + + Add + Ekle + + + Form + + + + Local Calendars + + + + Shared Calendar List + + + + Share Details + + + + Name: + + + + Location: + + + + ... + + + + Private + + + + Public + + + + Allow List: + + + + <Disabled> + + + + Peer Calendars + + + + + CallToaster + + Message + Mesaj + + + + CertificatePage + + Browse + Gözalt + + + Select Certificate + Select Certificate + + + Certificates (*.pqi *.pem) + Certificates (*.pqi *.pem) + + + RetroShare + Retroshare + + + Certificate file successfully created + Sertifika dosyası başarıyla oluşturuldu + + + Certificate files + + + + Use PGP certificates saved in files. + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + Export my certificate... + + + + Import friend's certificate... + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + Sorry, create certificate failed + + + + Please choose a filename + + + + Sorry, certificate file creation failed + + + + Certificate Load Failed:something is wrong with %1 + + + + Certificate Load Failed:can't read from file %1 + + + + Certificate Load Failed:file %1 not found + + + + + ChanMsgDialog + + Compose + Yeni ileti yaz + + + Recommended Files + Tavsiye edilen dosya + + + Send To: + Gönde Kime: + + + Send + Gönder + + + Delete Channel + Silmek kanal + + + Create Channel MSG + yaratmak kanal mesaj + + + Compose: + Yeni posta: + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-Dosya (*.htm *.html);;Tüm Dosyalar (*) + + + Save as... + Farklı kaydet... + + + Print Document + Belge yazdır + + + Add Extra File + Ekstra Dosya Ekle + + + File Name + Dosya Adı + + + Size + Boyut + + + Sources + Kaynak + + + Save + Kaydet + + + Contacts + Rehber + + + Subject: + Konu: + + + Italic + Italik + + + Attach + Ekle + + + Attach File + Dosya ekle + + + Reply + Yanıtla + + + + ChanMsgItem + + Download + Download + + + Play + Başlat + + + Expand + Genişlet + + + Hide + Hide + + + Toggle Message Read Status + + + + New + + + + Unsubscribe From Channel + + + + Remove Item + + + + Copy RetroShare Link + Kopyala retroshare Link + + + Channel Feed + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + ChanNewItem + + New Channel + Yeni Kanal + + + Subscribe to Channel + Kanala Abone Ol + + + Expand + Genişlet + + + Remove Item + + + + Channel Decscription + + + + Unknown Channel + + + + Updated Channel + + + + + ChannelDetails + + Forum Name + Forum İsmi + + + Popularity + Popülerlik: + + + Last Post + Son Mesaj + + + Close + bağlantılı + + + Channel Details + + + + Channel Info + + + + Channel Name + + + + Channel ID + + + + Channel Description + + + + Type + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + Private - (Private Publish Key required to view Messages) + + + + Cancel + + + + OK + + + + + ChannelFeed + + Create Channel + Kanal oluştur + + + Subscribe To Channel + Kanala Abone Ol + + + Title + Başlık + + + Description + Açıklamalar + + + Reset + Iptal + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Kanallar</span></p></body></html> + + + Add + Ekle + + + Display + Görüntü + + + Unsubcribe To Channel + Kanaldan Iptal Ol + + + Unsubscribe + Iptal + + + Subscribe + Abone Ol + + + Set all to read + Hepsini Işaretle Okunmuş olarak + + + Name + Name + + + Popularity + Popülerlik + + + Own Channels + Senin Kanallar + + + Subscribed Channels + Abone Kanallar + + + Popular Channels + Popüler Kanallar + + + Other Channels + Diğer Kanallar + + + Share Channel + Paylaş Kanalı + + + Popularity: %1 + Popülerlik: %1 + + + No Channel Selected + Kanal seçmediniz! + + + Post to Channel + Kanala yaz + + + Subscribe to Channel + Kanala Abone Ol + + + Unsubscribe to Channel + Kanaldan Iptal Ol + + + Show Channel Details + Kanal Detaylari göster + + + Edit Channel Details + Kanal Detayları düzenle + + + Create a new Channel + Yeni bir kanal oluştur + + + New Channel + Yeni Kanal + + + Enable Auto-download + + + + Restore Publish Rights for Channel + + + + Copy RetroShare Link + Kopyala retroshare Link + + + Disable Auto-Download + + + + Enable Auto-Download + + + + + ChatMsgItem + + Remove Item + + + + Write a quick Message + + + + Send Mail + + + + Write Message + + + + Start Chat + + + + Send + + + + Cancel + + + + Quick Message + + + + + ChatPage + + General + Genel + + + Group Chat + Canli Sohbet + + + Private Chat + Özel Sohbet + + + Style + Style + + + Chat Settings + + + + Enable Emoticons Privat Chat + + + + Chat Font + + + + Change Chat Font + + + + Chat Font: + + + + Enable Emoticons Group Chat + + + + Enable Private Chat History + + + + Enable Group Chat History + + + + Send message with Ctrl+Return + + + + Chat History + + + + Load number of messages (0 = off) + + + + Group chat + + + + Variant + + + + Author: + + + + Description: + + + + Private chat + + + + History + + + + Incoming message in history + + + + Outgoing message in history + + + + Incoming message + + + + Outgoing message + + + + Outgoing offline message + + + + + ChatStyle + + Standard style for group chat + + + + Standard style for private chat + + + + Standard style for history + + + + + ConclusionPage + + Make Friend + Yapı Arkadaş + + + Options + Seçenekler + + + Details about your friend : + + + + Peer details + + + + Key validity: + + + + Name: + + + + Email: + + + + Loc: + + + + Signers + + + + Add friend to group: + + + + Authenticate friend (Sign GPG Key) + + + + Add as friend to connect with + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + ConfCertDialog + + Cancel + Iptal + + + Port: + Port: + + + Trust Settings + Güven Düzenleme + + + Trust Level + Güven Düzlük + + + Trust Their Signature + Güven den imza + + + Sign The Certificate + imzalamak sertifika + + + Details + Ayrıntılar + + + Name + Isim + + + Loc + Yer + + + Peer Address + Adres + + + Last Contact + Son İletişim + + + Peer Details + Peer ayrıntılar + + + Peer Info + Peer Bilgileri + + + Peer ID + + + + Version + + + + Addresses list + Adres listesi + + + Apply and Close + Kapat + + + RetroShare + Retroshare + + + Error : cannot get peer details. + + + + Your key is signed by : + Anahtar imzalanmış: + + + Peer key is signed by : + Peer anahtar tarafından imzalanmış: + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + Your trust in this peer is full. + + + + Your trust in this peer is marginal. + + + + Your trust in this peer is none. + + + + Your trust in this peer is not set. + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + Signature Failure + + + + Maybe password is wrong + Belki şifre yanlış + + + Trust + Güven + + + None + + + + Marginal + + + + Full + + + + Deny Friend + Arkadaş reddet + + + Sign GPG key + + + + Friend Details + Arkadaş Detayları + + + RetroShare ID + + + + Status + + + + Local Address + + + + External Address + + + + Dynamic DNS + + + + Port + + + + Your trust in this peer is: + + + + GPG Key + + + + Peer has signed my GPG key + + + + Show Help for Trust Settings and Signing + + + + Peer key is signed by : + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + Make Friend + Arkadaş yap + + + Certificate + + + + OK + + + + + ConnectDialog + + Peer Details + Peer ayrıntılar + + + Make Friend + Yapı Arkadaş + + + Cancel + geçersiz kılmak + + + + ConnectFriendWizard + + Connect Friend Wizard + + + + + CreateBlog + + Name + Name + + + Description + Açıklamalar + + + Type: + Tip: + + + Allowed Messages + Izin Mesajlar + + + Authemticated Messages + Doğrulanmış Mesajlar + + + Anonymous Messages + Anonim Mesajlar + + + Create + Oluştur + + + RetroShare + Retroshare + + + Create new Blog + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + Private - (Private Publish Key required to view Messages) + + + + Blog Logo + + + + Add Blog Logo + + + + Cancel + + + + Please add a Name + + + + Load File + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + Attachments + Ek + + + Italic + Italik + + + Add Extra File + Ekstra Dosya Ekle + + + RetroShare + Retroshare + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-Dosya (*.htm *.html);;Tüm Dosyalar (*) + + + Save as... + Farklı kaydet... + + + Print Document + Belge yazdır + + + New Blog Post + + + + Blog Post + + + + Blog Post to: + + + + Visual Editor + + + + Blog Message + + + + Subject : + + + + Html Editor + + + + toolBar + + + + toolBar_2 + + + + blockquoute + + + + Increase font Size + + + + Decrease font size + + + + Bold + + + + Underline + + + + Publish + + + + New + + + + Code + + + + splitPost + + + + Ordered List + + + + Unordered List + + + + Clipboard + + + + Undo + + + + Please add a Subject + + + + &File + &Dosya + + + &New + + + + &Open... + + + + &Save + + + + Save &As... + + + + &Print... + &Yazdır... + + + Print Preview... + &Yazdırma önizleme + + + &Export PDF... + + + + &Quit + &Çıkış + + + &Edit + + + + &Undo + + + + &Redo + + + + Cu&t + + + + &Copy + + + + &Paste + + + + &View + + + + &Insert + + + + &Image + + + + F&ormat + + + + &Bold + + + + &Italic + + + + &Underline + + + + &Left + + + + C&enter + + + + &Right + + + + &Justify + + + + &Text Color... + + + + Application + + + + The document has been modified. +Do you want to save your changes? + + + + Open File... + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + Export PDF + + + + Choose Image + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + Create a new Channel + Yeni bir kanal oluştur + + + Description + Açıklamalar + + + Type: + Tip: + + + Allowed Messages + Izin Mesajlar + + + Anonymous Messages + Anonim Mesajlar + + + Authemticated Messages + Doğrulanmış Mesajlar + + + Create + Oluştur + + + RetroShare + Retroshare + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + Name + + + + check peers you would like to share private publish key with + + + + Share Key With + + + + Contacts: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + Private - (Private Publish Key required to view Messages) + + + + Authenticated Messages + + + + Key Sharing + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + Share Private Publish Key + + + + Channel Logo + + + + Add Channel Logo + + + + Cancel + + + + Please add a Name + + + + Load File + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + Message + Mesaj + + + Attachments + Ek + + + File not found or file name not accepted. + Dosya bulunamadı veya isim kabul edilmedi . + + + Add Extra File + Ekstra Dosya Ekle + + + RetroShare + Retroshare + + + New Channel Post + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + Channel Post + + + + Channel Post to: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + Add File to Attach + + + + Add Channel Thumbnail + + + + Subject : + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + Auto Thumbnail + + + + Drag and Drop Files from Search Results + + + + Drop file error. + + + + Directory can't be dropped, only files are accepted. + + + + File already Added and Hashed + + + + Please add a Subject + + + + Load File + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + Name + Isim + + + Type: + Tip: + + + Cancel + Iptal + + + RetroShare + Retroshare + + + Create new Forum + Yeni Forum yarat + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">Yeni Forum</span></p></body></html> + + + Description + Açıklamalar + + + Allowed Messages + Izin Mesajlar + + + Authemticated Messages + Doğrulanmış Mesajlar + + + Anonymous Messages + Anonim Mesajlar + + + Create + Oluştur + + + Public - Anyone can read and publish (Shared Publish Key) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + Private - (Private Publish Key required to view Messages) + + + + Authenticated Messages + + + + Please add a Name + + + + + CreateForumMsg + + Close + Kapat + + + Forum Post Subject + Başlık + + + Attach File + Dosya ekle + + + Paste retroshare link + Yapıştır retroshare Link + + + Subject + Konu + + + Paste retroshare Link + Yapıştır retroshare Link + + + RetroShare + Retroshare + + + Add Extra File + Ekstra Dosya Ekle + + + File not found or file name not accepted. + Dosya bulunamadı veya isim kabul edilmedi . + + + Post Forum Message + + + + Forum + + + + Sign Message + + + + Paste RetroShare Link + + + + Forum Post + + + + Attach files via drag and drop + + + + You can attach files via drag and drop here in this window + + + + Post Forum Msg + + + + Paste full RetroShare Link + + + + In Reply to + + + + Please set a Forum Subject and Forum Message + + + + Drop file error. + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + Edit Group + Grubu düzenle + + + Create a Group + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + Group Name + + + + Enter a name for your group + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + RetroShare + Retroshare + + + Save as... + Farklı kaydet... + + + Public Key + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + Copy Key + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + Save Key + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + DHTStatus + + DHT + + + + DHT On + + + + RetroShare users in DHT (Total DHT users) + + + + DHT Off + + + + + DLListDelegate + + B + + + + KB + + + + MB + + + + GB + + + + + DetailsDialog + + Details + Ayrıntılar + + + General + Genel + + + File Name: + Dosya Adı: + + + Size: + Boyut: + + + Status: + Durum: + + + Priority + Öncelik + + + Type: + Tip: + + + Transfer + Aktarım + + + Sources: + Kaynak: + + + Datarate: + Hız + + + Completed: + Tamanlandı: + + + Chunk size: + Chunk boyutu: + + + Remaining: + Kalan: + + + Date + Tarih + + + Download time: + Indirme zamani + + + Comments + Yorum + + + Copy + Kopyala + + + OK + Tamam + + + Cancel + Iptal + + + Rating + Oran + + + File Name + Dosya Adı + + + Hash: + + + + Priority: + + + + Number of Chunks + + + + Chunks: + + + + retroshare link(s) + + + + Not Rated + + + + No Comments + + + + + DirectoriesPage + + Incoming Directory + Gelen Dizin + + + Partials Direcrtory + Geçici Dizin + + + Shared Directories + Paylaşılan Dizinler + + + Automatically share incoming directory (Recommanded) + Otomatik olarak paylaş gelen dizini (önerilir) + + + Edit Share + Değiştir Paylaş + + + Incoming files + Incoming files + + + Add a Share Directory + Paylaşım Dizin Ekle + + + Remove Shared Directory + Kaldır Paylaşılan Dizin + + + Browse + Gözalt + + + Add Shared Directory + eklemek paylaşmak rehber kitap + + + Set Incoming Directory + Gelen Dizin + + + Set Partials Directory + Geçici Dizin + + + Partials Directory + + + + Automatically share incoming directory (Recommended) + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + Remember hashed files for + + + + days + + + + Forget any hashed file that is not anymore shared. + + + + Clean Hash Cache + + + + Auto-check shared directories every + + + + minute(s) + + + + + DiscStatus + + Waiting outgoing discovery operations + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + Start file + + + + <b>Download completed</b> + + + + Close + + + + + EditChanDetails + + Edit Channel Details + Kanal Detayları düzenle + + + Channel Details + + + + Cancel + + + + OK + + + + Channel Info + + + + Channel Name + + + + Channel Description + + + + Add Channel Logo + + + + Load File + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + Forum Details + Forum Detayları + + + Edit Forum Details + Forum Detayları düzenle + + + Forum Info + Forum Bilgileri + + + Forum Name + Forum İsmi + + + Forum Description + Forum Açıklama + + + Cancel + + + + OK + + + + + EmailPage + + Subject: + Konu: + + + Invite Friends by Email + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + Your friends' email addresses: + + + + Enter Friends Email addresses + + + + Friend invites you to check out RetroShare + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + Sorry, some error appeared + + + + Here is the error message: + + + + + ExampleDialog + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Arkadaş</span></p></body></html> + + + Status + Status + + + Person + Person + + + Auto Connect + Auto Connect + + + Trust Level + Trust Level + + + Peer Address + Peer Address + + + Last Contact + Last Contact + + + Organisation + Organisation + + + Location + Location + + + Country + Country + + + Person Id + Person ID + + + Auth Code + belgelemek kodlamak: + + + # + + + + Vote Up + + + + Vote Down + + + + + ExprParamElement + + to + + + + ignore case + + + + dd.MM.yyyy + + + + KB + + + + MB + + + + GB + + + + + ExpressionWidget + + Expression Widget + + + + Delete this expression + + + + + FileAssociationsPage + + &New + + + + Add new Association + + + + &Edit + + + + Edit this Association + + + + &Remove + + + + Remove this Association + + + + File type + + + + Friend Help + + + + You this + + + + + FileTransferInfoWidget + + Active chunks: + Aktiv chunks: + + + Availability map ( + Mevcut map + + + sources + Kaynak + + + File info: + Dosya bilgi + + + File size: + Dosa Boyut: + + + Remaining + Kalan + + + Chunk strategy + Chunk stratejisi + + + Chunk size: + Chunk boyut: + + + Transfered: + Aktarıldı + + + Number of sources: + Kaynak: + + + Chunk strategy: + Chunk stratejisi + + + Transfer type: + Aktarım tip: + + + Chunk map + + + + Active chunks + + + + Availability map (%1 active source) + + + + Availability map (%1 active sources) + + + + File info + + + + File hash + + + + File size + + + + bytes + + + + Chunk size + + + + Number of chunks + + + + Transfered + + + + Number of sources + + + + Transfer type + + + + Anonymous F2F + + + + Direct friend transfer / Availability assumed + + + + + FlatStyle_RDM + + Friends Directories + Arkadaş Dizinleri + + + My Directories + Dosyalarım + + + Age + Yaş + + + Friend + Arkadaş + + + Share Type + Paylaş Tipi + + + Directory + Klasör + + + Size + + + + + FofPage + + Friends of friends + + + + Select now who you want to make friends with. + + + + Show me: + + + + Any peer I've not signed + + + + Friends of my friends who already trust me + + + + Signed peers showing as denied + + + + Peer name + + + + Also signed by + + + + Peer id + + + + Make friend with these peers + + + + *** None *** + + + + + ForumDetails + + Forum Details + Forum Detayları + + + Forum Info + Forum Bilgileri + + + Forum Name + Forum İsmi + + + Popularity + Popülerlik: + + + Last Post + Son Mesaj + + + Forum Description + Forum Açıklama + + + Security + Güvenlik + + + Allowed Messages + Izin Mesajlar + + + Authemticated Messages + Doğrulanmış Mesajlar + + + Anonymous Messages + Anonim Mesajlar + + + Cancel + Iptal + + + OK + Tamam + + + Apply and Close + Kapat + + + Forum ID + + + + + ForumMsgItem + + Forum Name + Forum İsmi + + + Expand + Genişlet + + + Reply + Yanıtla + + + Signed + imzalı + + + + Anonymous + Anonim + + + Subject: + + + + Unsubscribe To Forum + + + + Remove Item + + + + Send + + + + Forum Post + + + + Unknown Forum Post + + + + In Reply to + + + + Please give a Text Message + + + + + ForumNewItem + + Subscribe to Forum + Foruma abone ol + + + Expand + Genişlet + + + Forum Description + Forum Açıklama + + + Form + + + + Remove Item + + + + + ForumPage + + Misc + Misc + + + Set message to read on activate + + + + Expand new messages + + + + + ForumsDialog + + Subscribe to Forum + Foruma abone ol + + + Unsubscribe to Forum + Foruma iptal ol + + + New Forum + Yeni Forum + + + Show Forum Details + Forum bilgilerini göster + + + Edit Forum Details + Forum Detayları düzenle + + + Reply + Yanıtla + + + Reply to Author + Yazarı yanıtla + + + Expand all + Tüm genişletin + + + Collapse all + Tümünü daralt + + + Popularity: + Popülerlik: + + + Your Forums + Senin Forumlar + + + Subscribed Forums + Abone Forumlar + + + Popular Forums + Popüler Forumlar + + + Other Forums + Diğer Forumlar + + + Mark as read + Işaretle Okunmuş olarak + + + Mark as unread + Işaretle Okunmamuş olarak + + + Mark all as read + Hepsini Işaretle Okunmuş olarak + + + Mark all as unread + Hepsini Işaretle Okunmamuş olarak + + + Hide + Gizle + + + Expand + Genişlet + + + Popularity: + Popülerlik: + + + Anonymous + Anonim + + + signed + Imzalı + + + none + yok + + + RetroShare + Retroshare + + + No Forum Selected! + Forum seçmediniz! + + + You cant reply a Anonymous Author + Bir Anonim Yazara yanıt veremiyoruz + + + Date + Tarih + + + Title + Başlık + + + Start New Thread + Yeni konu başlat + + + New Message + Yeni Mesaj + + + Add + Ekle + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start new Thread for Selected Forum</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Seçilen Forum için Yeni konu Başlat</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reply Message</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Mesaj cevap</p></body></html> + + + RetroShare Forums + RetroShare Forumlar + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + Last Post + Son Mesaj + + + Author + Yazar + + + Signed + imzalı + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Konu:</span></p></body></html> + + + Create Forum + Forum yarat + + + Print + Yazdır + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forumlar</span></p></body></html> + + + Display + Görüntü + + + PrintPreview + Baskı Önizleme + + + Threaded View + + + + Flat View + + + + Previous Thread + + + + Next Thread + + + + Download all files + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + Reset + + + + Content + Içindekiler + + + Reply Message + + + + Start new Thread for Selected Forum + + + + Restore Publish Rights for Forum + + + + Copy RetroShare Link + Kopyala retroshare Link + + + with children + + + + AUTHD + + + + + ForumsFillThread + + Anonymous + Anonim + + + signed + Imzalı + + + none + yok + + + + FriendsDialog + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Arkadaşlar</span></p></body></html> + + + Add + Ekle + + + Display + Görüntü + + + Friends + Arkadaşlar + + + Status + Durum + + + Add or Change your Avatar + Ekle veya Avatar Değiştir + + + Edit Personal message + Değiştir Kişisel mesaj + + + Group Chat + Canli Sohbet + + + Italic + Italik + + + Attach File + Dosya ekle + + + Clear Chat History + Chat Sohbeti temizle + + + Add Friend + Arkadaş ekle + + + Create new Profile + Yeni profil oluştur + + + Create new Forum + Yeni Forum yarat + + + Create new Channel + Yeni bir kanal oluştur + + + Add your Avatar Picture + Ekle veya Avatar Değiştir + + + Set your Personal Message + Kişisel Mesaj aya + + + Edit your status Message + Değiştir Kişisel mesaj + + + Add a new Group + Yeni Grup ekle + + + Profile + Profil + + + News Feed + Haber Kaynağı + + + Welcome to RetroShare's group chat. + Hoşgeldiniz RetroShare grub sohbetine. + + + me + ben + + + Group + Grub + + + Friend + Arkadaş + + + Location + Yer + + + Message Group + Gruba Mesaj yaz + + + Edit Group + Grubu düzenle + + + Remove Group + Grubu Kaldır + + + Chat + Sohbet + + + Message Friend + Arkadaş'a Mesaj yaz + + + Friend Details + Arkadaş Detayları + + + Recommend this Friend to... + Bu Arkadaşı Tavsiye Et ... + + + Copy RetroShare Link + Kopyala retroshare Link + + + Paste Friend Link + Yapıştır Arkadaş Link + + + Deny Friend + Arkadaş reddet + + + Remove Friend Location + Kaldır Arkadaş Yeri + + + Add to group + Gruba ekle + + + Move to group + Gruba taşı + + + Groups + Grublar + + + Remove from group + Grubtan kaldır + + + Remove from all groups + Tüm grublardan Kaldır + + + Expand all + Tüm genişletin + + + Collapse all + Tümünü daralt + + + location + Yer + + + Available + Mevcut + + + Save Certificate + Belgeyi kaydet + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Do you want to remove this Friend? + Bu Arkadaşı kaldırmak istiyor musunuz? + + + is typing... + yazıyor ... + + + New group chat + Canli Sohbet + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Resimler (*.png *.xpm *.jpg *.tiff *.gif) + + + Add Extra File + Ekstra Dosya Ekle + + + File not found or file name not accepted. + Dosya bulunamadı veya isim kabul edilmedi . + + + Save as... + Farklı kaydet... + + + Messages entered here are sent to all collected friends + + + + Bold + + + + Underline + + + + Font + + + + Text Color + + + + Send + + + + F + + + + C + + + + A + + + + Browse Message History + + + + Browse History + + + + Save Chat History + + + + Hide Offline Friends + + + + Hide Status Column + + + + Sort by State + + + + Hide State + + + + Sort Descending Order + + + + Sort Ascending Order + + + + Delete Chat History + + + + Deletes all stored and displayed chat history + + + + Paste RetroShare Link + + + + Connect To Friend + + + + Do you really want to physically delete the history? + + + + Load File + + + + Drop file error. + + + + Directory can't be dropped, only files are accepted. + + + + Text File (*.txt );;All Files (*) + + + + + GamesDialog + + Server + Peer Settings + + + Status + Status + + + Accept + Accept + + + Delete + Sil + + + Form + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + Game: + + + + GameType: 0. Want to Add your Game here? + + + + GameType: 1. Get In Touch with the developers + + + + GameType: 2. + + + + Title / Comment + + + + Create New Game + + + + Invite All Friends + + + + Game Type + + + + Comment + + + + GameID + + + + Player + + + + Invite + + + + Interested + + + + Move Player + + + + Play Game + + + + Cancel Game + + + + Add to Invite List + + + + Remove from Invite List + + + + Interested in Playing + + + + Not Interested in Game + + + + Not Interested + + + + Confirm Peer in Game + + + + Remove Peer from Game + + + + Interested in Game + + + + Quit Game + + + + + GenCertDialog + + RetroShare setup + Retroshare setup + + + Load Trusted Certificate (Optional) + Load Trusted Certificate (Optional) + + + RetroShare : Create new user Profile + Retroshare: Yeni kullanıcı oluştur + + + It looks like you don't own any GPG keys. Please fill in the form below to generate one, or use your favorite gnupg key manager. + Herhalde GPG anahtarı yok gibi görünüyor. Lütfen aşağıdaki formu bir veya en sevdiğiniz gnupg anahtar yöneticisi kullanız oluşturmak için doldurunuz. + + + Use GPG key + Kullan GPG anahtarı + + + Create new Profile + Yeni profil oluştur + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + Generate a new Profile + + + + Your profile is associated to a GPG key + + + + Use Profile + + + + Name + Name + + + Enter here your nickname + + + + Email + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + This Password is for GPG + + + + Password + + + + Put a strong password here. This password protects your GPG key. + + + + Location + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + GPG Password + GPG Şifre + + + Put a meaningfull location. ex : home, laptop, etc. + Anlamlı bir yer koyun. örnek: ev, laptop... + + + Generate a new gpg key + Yeni bir gpg anahtarı Üüret + + + Generate New Profile + Yeni Profil Oluştur + + + Info + Bilgi + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + + + Select File + Select File + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + + + Generate New Certificate + Generate New Certificate + + + Create new Location + + + + Generate new Location + + + + Create a new Location + + + + Generate new Profile + + + + Create a new Profile + Yeni profil oluştur + + + Generate GPG key Failure + + + + Location field is required with a minimum of 3 characters + + + + All fields are required with a minimum of 3 characters + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + Select Trusted Friend + Select Trusted Friend + + + Certificates (*.pqi *.pem) + Certificates (*.pqi *.pem) + + + Multiple instances + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + Generate ID Failure + + + + Failed to Load your new Certificate! + + + + + GeneralDialog + + Style + Style + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + Language + Language + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + Style Sheet + Style Sheet + + + Login + Login + + + Misc + Misc + + + + GeneralMsgDialog + + Add Extra File + Ekstra Dosya Ekle + + + Attachments + Ek + + + + GeneralPage + + Keys manager + Keys manager + + + Style + Style + + + Choose RetroShare's interface style + Choose Retroshare's interface style + + + Language + Language + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + Choose the language used in RetroShare + Choose the language used in RetroShare + + + Login + Login + + + Misc + Misc + + + Idle + Boşta + + + Startup + + + + Start RetroShare when my system starts + + + + Start minimized + + + + Start minimized on system start + + + + Do not show the Quit RetroShare MessageBox + + + + Do not Minimize to Tray Icon + + + + Auto Login + + + + Register retroshare:// as url protocol (Restart required) + + + + Idle Time + + + + seconds + + + + + GraphFrame + + Recv: + Recv: + + + %1 KB/s + %1 KB/s + + + Sent: + Sent: + + + %1 KB + %1 KB + + + %1 MB + %1 MB + + + %1 GB + %1 GB + + + + GraphWidget + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + Friends + Arkadaşlar + + + Family + Aile + + + Co-Workers + Personel + + + Other Contacts + Diğer Kişiler + + + Favorites + Favori + + + + GroupTreeWidget + + Title + Başlık + + + Description + Açıklamalar + + + Enter a Keyword here + + + + Reset + + + + Sort by Name + + + + Sort by Popularity + + + + Sort by Last Post + + + + Private Key Available + + + + + GuiExprElement + + Popularity + Popülerlik: + + + and + + + + and / or + + + + or + + + + Name + + + + Path + + + + Extension + + + + Hash + + + + Date + + + + Size + + + + contains + + + + contains all + + + + is + + + + less than + + + + less than or equal + + + + equals + + + + greater than or equal + + + + greater than + + + + is in range + + + + + HelpBrowser + + Error Loading Help Contents: + + + + Supplied XML file is not a valid Contents document. + + + + Search reached end of document + + + + Search reached start of document + + + + Text not found in document + + + + Found %1 results + + + + Search + araştırmak + + + Home + Home + + + Close + bağlantılı + + + RetroShare Help + + + + Find: + + + + Find Previous + + + + Find Next + + + + Case sensitive + + + + Whole words only + + + + Contents + + + + Help Topics + + + + Searching for: + + + + Found Documents + + + + Back + + + + Move to previous page (Backspace) + + + + Backspace + + + + Forward + + + + Move to next page (Shift+Backspace) + + + + Shift+Backspace + + + + Move to the Home page (Ctrl+H) + + + + Ctrl+H + + + + Find + + + + Search for a word or phrase on current page (Ctrl+F) + + + + Ctrl+F + + + + Close Vidalia Help + + + + Esc + + + + + HelpDialog + + About + About + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + Authors + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + Thanks to + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Translation + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + License Agreement + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + Error opening help file: + + + + Opening External Link + + + + Unable to Open Link + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + Do you want Retroshare to open the link in your Web browser? + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + Copy + Kopyala + + + Delete + Sil + + + Message History + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + Reset + + + + Remove + + + + Mark all + + + + Clear history + + + + Send + + + + + InfoDialog + + Info + Bilgi + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + Add a new Friend + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + &Enter the certificate manually + + + + &You get a certificate file from your friend + + + + &Make friend with selected friends of my friends + + + + &Enter RetroShare ID manually + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + LinksDialog + + Download + Download + + + Expand + Genişlet + + + From + den + + + Show + Show + + + Title / Comment + + + + Score + + + + Peer / Link + + + + Sort by + + + + Combo + + + + Time + + + + Ranking + + + + In last + + + + Month + + + + Week + + + + Day + + + + All Peers + + + + Own Links + + + + Top 100 + + + + 101-200 + + + + 201-300 + + + + 301-400 + + + + 401-500 + + + + Bottom 100 + + + + Link: + + + + Add Anonymous Link + + + + Add Link/Comment + + + + Title: + + + + Score: + + + + +2 Great! + + + + +1 Good + + + + 0 Okay + + + + -1 Sux + + + + -2 Bad Link + + + + Url: + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + Add new link + + + + Share Link Anonymously + + + + Vote on Link + + + + Hide + + + + File Request Confirmation + + + + The file has been added to your download list. + + + + File Request canceled + + + + The file has not been added to your download list, because you already have it. + + + + File Request Error + + + + The file link is malformed. + + + + + MainWindow + + Network + + + + Friends + Arkadaşlar + + + Transfers + Aktarımlar + + + Messages + Mesajlar + + + Channels + Kanallar + + + Blogs + Bloglar + + + Status + Durum + + + You have %1 new messages + %1 yeni mesaj var + + + Down: %1 (kB/s) + Indirme: %1 (kB/s) + + + Up: %1 (kB/s) + Gönderme: %1 (kB/s) + + + %1 friend connected + %1 Arkadaş Bağlandı + + + %1 friends connected + %1 Arkadaşlar Bağlandı + + + Options + Seçenekler + + + Hide + Gizle + + + Show + Göster + + + RetroShare + Retroshare + + + Invite Friend + davet etmek Arkadaş + + + Add Friend + Arkadaş ekle + + + Add a Friend Wizard + Arkadaş Ekleme Sihirbazı + + + Add Share + Paylaş ekle + + + Quick Start Wizard + Hızlı Başlangıç Sihirbazı + + + Search + Ara + + + Files + Dosya + + + Add Shared Directory + eklemek paylaşmak rehber kitap + + + Show/Hide + Göster/Gizle + + + You have %1 new message + %1 yeni mesaj var + + + Bandwidth Graph + Bant genişliği Grafik + + + Open Messenger + Aç Messenger + + + Help + Yardım + + + About + Ile ilgili + + + Forums + Forumlar + + + Open Messages + Aç Mesajlar + + + Settings + Settings + + + RetroShare %1 a secure decentralised commmunication platform + RetroShare %1 güvenli bir merkezden uzak iletişim platformu + + + Really quit ? + Gerçekten çıkmak istiyorsunuz? + + + Do you really want to exit RetroShare ? + RetroShare'dan çıkmak istiyor musunuz? + + + Quit + Çıkış + + + MainWindow + + + + Messenger + + + + SMPlayer + + + + RetroShare %1 a secure decentralised communication platform + + + + Links Cloud + + + + Plugins + + + + Unfinished + + + + Low disk space warning + + + + The disk space in your + + + + directory is running low (current limit is + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + Applications + + + + Minimize + + + + Maximize + + + + &Quit + &Çıkış + + + Chat + + + + %1 new messages + + + + %1 new message + + + + You have %1 completed downloads + + + + You have %1 completed download + + + + %1 completed downloads + + + + %1 completed download + + + + Internal Error + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + The file link is malformed. + + + + + MessageComposer + + Compose + Yeni ileti + + + Contacts + Rehber + + + Send To: + Gönde Kime: + + + Subject: + Konu: + + + >> To + Kime: bölümüne ekle + + + >> Cc + Ilgili adrese ekle + + + >> Bcc + Gizli adrese ekle + + + >> Recommend + Tavsiye + + + Italic + Italik + + + Tags + Etiket + + + Recommended Files + Tavsiye edilen dosya + + + File Name + Dosya Adı + + + Size + Boyut + + + Send + Gönder + + + Reply + Yanıtla + + + Save + Kaydet + + + Attach + Ekle + + + Attach File + Dosya ekle + + + Compose: + Yeni posta: + + + Friend Recommendation(s) + Arkadaş tavsiyesi + + + Add to "To" + Kime: bölümüne ekle + + + Add to "CC" + Ilgili adrese ekle + + + Add to "BCC" + Gizli adrese ekle + + + Add as Recommend + Tavsiye + + + Friend Details + Arkadaş Detayları + + + RetroShare + Retroshare + + + To + Kime + + + Cc + Ilgili kopyasi + + + Bcc + Gizli kopya + + + Unknown + Bilinmeyen + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-Dosya (*.htm *.html);;Tüm Dosyalar (*) + + + Save as... + Farklı kaydet... + + + Print Document + Belge yazdır + + + Add Extra File + Ekstra Dosya Ekle + + + File not found or file name not accepted. + Dosya bulunamadı veya isim kabul edilmedi . + + + Search for Name: + + + + Search Friends + + + + Reset + + + + Paragraph + + + + Heading 1 + + + + Heading 2 + + + + Heading 3 + + + + Heading 4 + + + + Heading 5 + + + + Heading 6 + + + + Font size + + + + Increase font size + + + + Decrease font size + + + + Bold + + + + Select Color + + + + Alignment + + + + Add a Image + + + + Sets text font to code style + + + + Underline + + + + Tags: + + + + Hash + + + + Send this message now + + + + Toggle Contacts View + + + + Save this message + + + + Quote + + + + Add Blockquote + + + + &Left + + + + C&enter + + + + &Right + + + + &Justify + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + Save Message + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + Paste RetroShare Link + + + + Re: + + + + Fwd: + + + + Do you want to send the message without a subject ? + + + + Please insert at least one recipient. + + + + Unknown friend + + + + &File + &Dosya + + + &New + + + + &Open... + + + + &Save + + + + Save &As File + Farklı kaydet + + + Save &As Draft + + + + &Print... + &Yazdır... + + + &Export PDF... + + + + &Quit + &Çıkış + + + &Edit + + + + &Undo + + + + &Redo + + + + Cu&t + + + + &Copy + + + + &Paste + + + + &View + + + + &Contacts Sidebar + + + + &Insert + + + + &Image + + + + &Horizontal Line + + + + &Format + + + + Open File... + + + + Export PDF + + + + Message has not been Sent. +Do you want to save message ? + + + + Choose Image + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + Drop file error. + + + + Directory can't be dropped, only files are accepted. + + + + + MessagePage + + Misc + Misc + + + Tags + Etiket + + + Tags can be used to categorize and prioritize your messages + Etiketler, iletilerde kategori oluşturmaya veya önemlilik derecesine göre sıralamanıza yarar. + + + Add + Ekle + + + Edit + Düzenle + + + Delete + Sil + + + Default + Varsayılan + + + Edit Tag + Düzenle Etiketi + + + Reading + + + + Set message to read on activate + + + + Open messages in + + + + A new tab + + + + A new window + + + + + MessageToaster + + message + Mesaj + + + New Message + Yeni Mesaj + + + Subject + Konu + + + Close + bağlantılı + + + <b>1 new Message from</b> + + + + Sub: + + + + + MessageWidget + + Subject: + Konu: + + + From: + Kimden: + + + To: + Kime: + + + Print + Yazdır + + + Print Preview + Yazdırma önizleme + + + Expand + Genişlet + + + Files + Dosya + + + Print Document + Belge yazdır + + + Save as... + Farklı kaydet... + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-Dosya (*.htm *.html);;Tüm Dosyalar (*) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + + + + Download all Recommended Files + + + + Cc: + + + + Bcc: + + + + Tags: + + + + File Name + + + + Size + + + + Hash + + + + No subject + + + + Download + + + + Download all + + + + Hide + + + + File + + + + + MessageWindow + + New Message + Yeni ileti + + + Compose + Yeni ileti + + + Reply to selected message + Iletiyi yanıtla + + + Reply + Yanıtla + + + Reply all to selected message + Tüm alicilara yanıtla + + + Reply all + Hepsini yanıtla + + + Forward selected message + Seçilmiş postaları ilet + + + Foward + Ilet + + + Remove selected message + Iletiyi sil + + + Delete + Sil + + + Print selected message + Iletiyi yazdıır + + + Print + Yazdır + + + Display + Görüntü + + + Tags + Etiket + + + Print Preview + Yazdırma önizleme + + + &File + &Dosya + + + Save &As File + Farklı kaydet + + + &Print... + &Yazdır... + + + Print Preview... + &Yazdırma önizleme + + + &Quit + &Çıkış + + + Buttons Icon Only + + + + Buttons Text Beside Icon + + + + Buttons with Text + + + + Buttons Text Under Icon + + + + Set Text Under Icon + + + + + MessagesDialog + + New Message + Yeni Posta + + + Reply to Message + Yanıtla + + + Remove Message + Sil + + + Date + Tarih + + + From + Kimden + + + Size + Boyut + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tavsiye edilen dosyalar</span></p></body></html> + + + Reply + Yanıtla + + + Reply all + Hepsini yanıtla + + + Foward + Ilet + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Iletiyi Sil</p></body></html> + + + Delete + Sil + + + Compose + Yeni ileti + + + Reply to selected message + Iletiyi yanıtla + + + Reply all to selected message + Tüm alicilara yanıtla + + + Forward selected message + Seçilmiş postaları ilet + + + Remove selected message + Iletiyi sil + + + Print selected message + Iletiyi yazdıır + + + Display + Görüntü + + + Reset + Iptal + + + Attachments + Ek + + + Content + Içindekiler + + + Tags + Etiket + + + Quick View + Hızlı görünümler + + + Tag + Etiket + + + Inbox + Gelen + + + Outbox + Giden + + + Draft + Taslak + + + Sent + Gönderildi + + + Trash + Çöp + + + Favorite Tags + Favori Etiket + + + Folders + Dosyalar + + + Print... + Yazdır... + + + Print Preview + Yazdırma önizleme + + + Save As... + Farklı kaydet... + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sadece göndereni yanıtla</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Yeni Mesaj</p></body></html> + + + Download All + Download All + + + Print Document + Belge yazdır + + + File Name + Dosya Adı + + + Sources + Kaynak + + + Forward selected Message + Ilet + + + Starred + Yildizli + + + Open in a new window + Yeni pencerede aç + + + Open in a new tab + İletiyi yeni sekmede aç + + + Add Star + Yıldız ekle + + + Edit + Düzenle + + + Edit as new + Yeni olarak düzenle... + + + Remove Messages + Iletiyi sil + + + Forward Message + Ilet + + + Click to sort by attachments + Eklere göre siralamak için tiklayin + + + Click to sort by subject + Konuya göre siralamak için tiklayin + + + Click to sort by read + Okunanlara göre siralamak için tiklayin + + + Click to sort by from + Gönderene göre siralamak için tiklayin + + + Click to sort by date + Tarihe göre siralamak için tiklayin + + + Click to sort by tags + Etikete göre siralamak için tiklayin + + + Click to sort by star + Yıldızlara göre siralamak için tiklayin + + + Remove All Tags + Tüm etiketleri sil + + + New tag ... + Yeni etiket... + + + Edit... + Düzenle... + + + Mark as read + Işaretle Okunmuş olarak + + + Mark as unread + Işaretle Okunmamuş olarak + + + Download + Indir + + + Empty trash + Çöpi Boşalt + + + Click to sort by to + Alıcıya göre siralamak için tiklayin + + + Files + Dosya + + + Compose: + Yeni posta: + + + Hide + Gizle + + + Expand + Genişlet + + + Drafts + Taslak + + + To + Kime + + + Anonymous + Anonim + + + Save as... + Farklı kaydet... + + + HTML-Files (*.htm *.html);;All Files (*) + HTML-Dosya (*.htm *.html);;Tüm Dosyalar (*) + + + Total: + Toplam: + + + Reply to All + Hepsini yanıtla + + + Subject + Konu + + + Subject: + Konu: + + + From: + Kimden: + + + Date: + Tarih: + + + To: + Kime: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Tüm Önerilen Dosyalar indir</p></body></html> + + + Print + Yazdır + + + Total Inbox: + + + + Buttons Icon Only + + + + Buttons Text Beside Icon + + + + Buttons with Text + + + + Buttons Text Under Icon + + + + Set Text Under Icon + + + + Undelete + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + Yildizli posta yok. Yildiz eklediginiz e-postalari daha kolay bulabilirsiniz. Bir postaya yildiz eklemek için yanindaki açik mavi yildizi tiklayabilirsiniz. + + + + MessagesPopupDialog + + New Message + Yeni Mesaj + + + Reply to Message + Reply to Mesaj + + + Remove Message + Remove Mesaj + + + Messages + Mesaj + + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Draft + Müsvedde + + + Sent + Email-Sent + + + Date + Date + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">tavsiye etmek dosya</span></p></body></html> + + + File Name + File Name + + + Size + Size + + + Sources + Sources + + + Compose + oluşturmak + + + Remove + Remove + + + Reply + Yanıtla + + + Print + Yazdır + + + PrintPreview + Baskı Önizleme + + + + MessengerWindow + + Expand all + Tüm genişletin + + + Collapse all + Tümünü daralt + + + Chat + GrupSohbet + + + Message Friend + Arkadaş'a Mesaj yaz + + + Connect To Friend + Connect To Arkadaş + + + Peer Details + Peer ayrıntılar + + + Recomend this Friend to... + + + + Paste RetroShare Link + + + + Paste retroshare Link + Yapıştır retroshare Link + + + Export Friend + Export Arkadaş + + + Deny Friend + Arkadaş reddet + + + Remove Friend Location + Kaldır Arkadaş Yeri + + + <strong>GPG Key</strong> + <strong>GPG Anahtar</strong> + + + location + Yer + + + <strong>RetroShare instance</strong> + <strong>RetroShare instance</strong> + + + location : + Yer: + + + Available + Mevcut + + + Save Certificate + Save Certificate + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Friend Not Online + Arkadaşım Online değil + + + Your Friend is offline +Do you want to send them a Message instead + Arkadaşınızın offline +Bunun yerine Mesaj göndermek istiyor musunuz? + + + View + Görüntü + + + Remove Friend + Remove Arkadaş + + + Click to Change your Avatar + + + + Search Friends + + + + Reset + + + + Sort Descending Order + + + + Sort Ascending Order + + + + Set root is Decorated + + + + Set Root Decorated + + + + Sort by State + + + + Hide Offline Friends + + + + RetroShare Messenger + + + + Add a Friend + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + Email-Inbox + + + Outbox + Email-Outbox + + + Sent + Email-Sent + + + Date + Date + + + All + Hepsi + + + Subject + Konu + + + + MsgItem + + Reply to Message + Reply to Mesaj + + + Expand + Genişlet + + + Remove Item + + + + Reply Message + + + + Delete Message + + + + Play Media + + + + Message From + + + + Sent Msg + + + + Draft Msg + + + + Pending Msg + + + + Hide + + + + + NATStatus + + <strong>NAT:</strong> + + + + OK | RetroShare Server + + + + Internet connection + + + + No internet connection + + + + No local network + + + + + NetworkDialog + + Load Certificate + Yüklemek Sertifika + + + Select a pem/pqi File + Select a pem/pqi File + + + File Not Found + File Not Found + + + %1 does not exist. Would you like to create it? + %1 does not exist. Would you like to create it? + + + Failed to Create File + Failed to Create File + + + Unable to create %1 [%2] + Unable to create %1 [%2] + + + Select Certificate + Select Certificate + + + Certificates (*.pqi *.pem) + Certificates (*.pqi *.pem) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + + + Accept + Accept + + + Trust + Güven + + + Last Contact + Last Contact + + + Name + Isim + + + Peer Address + Peer Address + + + Organisation + Organisation + + + Location + Location + + + Country + Country + + + Cert Id + Cert Id + + + Trust matrix + Güven matris + + + Deny friend + Arkadaş reddet + + + Make friend + Arkadaş yap + + + Delete certificate + Sil sertifika + + + Authenticated + Doğrulanmış + + + GPG key signed + GPG anahtar imzaladı + + + Not Authenticated + Doğrulanmamış + + + GPG key not signed + GPG anahtar imzalanmamış + + + Unknown + Bilinmeyen + + + RetroShare + Retroshare + + + Certificate file successfully created + Sertifika dosyası başarıyla oluşturuldu + + + Network + + + + Did I authenticated peer + Doğrulanmış Peer + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Görüntü</span></p></body></html> + + + Network Status + Ağ Durumu + + + Local network + Yerel ağ + + + Did peer authenticated me + Akran Beni doğrulanmış mı + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Ağ: +</span></p></body></html> + + + Show keys that are not validated by the GPG web of trust + Güven GPG web tarafından onaylanmamışları göster + + + External ip address finder + Dış IP adres bulucu + + + Clear + Temizle + + + Add Friend + Arkadaş ekle + + + Create New Profile + Yeni profil oluştur + + + Create a new Profile + Yeni profil oluştur + + + Did I sign his gpg key + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + Search Network + + + + Clear Filter + + + + Peer ID + + + + UPnP + + + + Set Tabs Right + + + + Set Tabs North + + + + Set Tabs South + + + + Set Tabs Left + + + + Set Tabs Rounded + + + + Set Tabs Triangular + + + + Copy My Key to Clipboard + + + + Export My Key + + + + Authentication matrix + + + + Network View + + + + Export my Cert + + + + Peer details... + + + + Copy RetroShare Link + Kopyala retroshare Link + + + Personal signature + + + + GPG key signed by you + + + + Marginally trusted peer + + + + Fully trusted peer + + + + Untrusted peer + + + + Has authenticated me + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + yourself + + + + + NetworkPage + + Rate Options + Rate Options + + + Max Total Data Rate (KB/S): + You maximum Upload Speed (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + Hide Settings + + + Show Settings + Show Settings + + + Settings + Settings + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + Redraw + + + + Friendship level: + + + + Edge length: + + + + + NewTag + + New Tag + + + + Name: + + + + Choose color + + + + OK + + + + Cancel + + + + + NewsFeed + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Haber Kaynağı</span></p></body></html> + + + Remove All + Hepsini Kaldır + + + Options + Seçenekler + + + + NotifyPage + + News Feed + Haber Kaynağı + + + Channels + Kanallar + + + Forums + Forumlar + + + Blogs + Bloglar + + + Messages + Mesajlar + + + Downloads + Indir + + + Message + Mesaj + + + Peer Connect + Peer Bağlantı + + + New Message + Yeni Mesaj + + + Private Chat + Özel Sohbet + + + Open Window for new Peer Chat + Pencere aç yeni Sohbet için + + + Reopen if closed by user: + Eğer kullanıcı tarafından kapalıys Yeniden aç: + + + Display systray message + Systray mesaj göster + + + Peers + + + + Chat + + + + Add feeds at end + + + + Systray Icon + + + + Private Message + + + + Channel Post + + + + Forum Post + + + + Download completed + + + + Combined icon + + + + Toasters + + + + Friend Connect + + + + Position + + + + X Margin + + + + Y Margin + + + + Open Window for new chat + + + + Grab Focus when chat arrives + + + + Use a single tabbed window + + + + Group chat + + + + Top Left + + + + Top Right + + + + Bottom Left + + + + Bottom Right + + + + + NotifyQt + + GPG key passphrase + + + + Wrong password ! + + + + Please enter the password to unlock the following GPG key: + + + + Examining shared files... + + + + Hashing file + + + + Saving file index... + + + + + OnlineToaster + + Friend Online + + + + + PeerDefs + + Anonymous + Anonim + + + Unknown + Bilinmeyen + + + + PeerItem + + Make Friend + Yapı Arkadaş + + + Remove Friend + Remove Arkadaş + + + Chat + GrupSohbet + + + Organisation + Organisation + + + Location + Location + + + Country + Country + + + Expand + Genişlet + + + Status: + Durum: + + + Friend + Arkadaş + + + Remove Item + + + + Write a quick Message + + + + Start Chat + + + + Cancel + + + + Send + + + + Name: + + + + Peer ID: + + + + Trust: + + + + IP Address + + + + Connection Method + + + + Write Message + + + + Friend Connected + + + + Connect Attempt + + + + Friend of Friend + + + + Peer + + + + Unknown Peer + + + + Hide + + + + Quick Message + + + + + PeerStatus + + Friends + Arkadaşlar + + + Online + Çevrimiçi + + + <span style="color:#000000"><strong>Friends:</strong></span> + <span style="color:#000000"><strong>Arkadaşlar:</strong></span> + + + <span style="color:#0000FF"><strong>Online:</strong></span> + <span style="color:#0000FF"><strong>Online:</strong></span> + + + Friends: + Arkadaşlar: + + + Friends: 0/0 + + + + Online Friends/Total Friends + + + + + PeersDialog + + Chat + Sohbet + + + Export Friend + Export Arkadaş + + + Remove Friend + Remove Arkadaş + + + Save Certificate + Belgeyi kaydet + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Status + Durum + + + Person + Kişi + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Arkadaş</span></p></body></html> + + + Connect To Friend + Arkadaş'a Bağlan + + + Welcome to RetroShare's group chat. + Hoşgeldiniz RetroShare grub sohbetine. + + + Profile + Profil + + + Friends Storm + Aktiviteler + + + Paste retroshare Link + Yapıştır retroshare Link + + + me + ben + + + <strong>Group</strong> + <strong>Grup</strong> + + + <strong>Friend</strong> + <strong>Arkadaş</strong> + + + Message group + Grup Mesaj + + + Edit group + Grubu düzenle + + + Remove group + Grubu Kaldır + + + Friend Details + Arkadaş Detayları + + + Recommend this Friend to... + Bu Arkadaşı Tavsiye Et ... + + + Add to group + Gruba ekle + + + Move to group + Gruba taşı + + + Groups + Grublar + + + Remove from group + Grubtan kaldır + + + Remove from all groups + Tüm grublardan Kaldır + + + Expand all + Tüm genişletin + + + Collapse all + Tümünü daralt + + + Message Friend + Arkadaş'a Mesaj yaz + + + Peer Details + Peer ayrıntılar + + + Deny Friend + Arkadaş reddet + + + Remove Friend Location + Kaldır Arkadaş Yeri + + + <strong>GPG Key</strong> + <strong>GPG Anahtar</strong> + + + <strong>RetroShare instance</strong> + <strong>RetroShare instance</strong> + + + location : + Yer: + + + Available + Mevcut + + + Friend Not Online + Arkadaşım Online değil + + + Your Friend is offline +Do you want to send them a Message instead + Arkadaşınızın offline +Bunun yerine Mesaj göndermek istiyor musunuz? + + + RetroShare + Retroshare + + + Do you want to remove this Friend? + Bu Arkadaşı kaldırmak istiyor musunuz? + + + is typing... + yazıyor ... + + + Create a new Channel + Yeni bir kanal oluştur + + + New Channel + Yeni Kanal + + + Add Extra File + Ekstra Dosya Ekle + + + File not found or file name not accepted. + Dosya bulunamadı veya isim kabul edilmedi . + + + News Feed + Haber Kaynağı + + + Group + Grub + + + Friend + Arkadaş + + + Location + Yer + + + Message Group + Gruba Mesaj yaz + + + Edit Group + Grubu düzenle + + + Remove Group + Grubu Kaldır + + + Paste Friend Link + Yapıştır Arkadaş Link + + + location + Yer + + + Save as... + Farklı kaydet... + + + Send + Gönder + + + Italic + Italik + + + Display + Görüntü + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Arkadaşlar</span></p></body></html> + + + Add + Ekle + + + hide unconnected + sakla offline Arkadaşlar + + + Add or Change your Avatar + Ekle veya Avatar Değiştir + + + Edit Personal message + Değiştir Kişisel mesaj + + + Live Chat + Canli Sohbet + + + Create New Forum + Yeni Forum yarat + + + Create new Forum + Yeni Forum yarat + + + Create New Channel + Yeni bir kanal oluştur + + + Create new Channel + Yeni bir kanal oluştur + + + Add your Avatar Picture + Ekle veya Avatar Değiştir + + + Set your Personal Message + Kişisel Mesaj aya + + + Edit your status Message + Değiştir Kişisel mesaj + + + Add a new Group + Yeni Grup ekle + + + Add Friend + Arkadaş ekle + + + Create new Profile + Yeni profil oluştur + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Görüntu</span></p></body></html> + + + Friends + Arkadaşlar + + + Group Chat + Canli Sohbet + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">set Text Color</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Metin Rengi</span></p></body></html> + + + Attach File + Dosya ekle + + + Clear Chat History + Chat Sohbeti temizle + + + + PeersFeed + + Save Certificate + Save Certificate + + + Certificates (*.pqi) + Certificates (*.pqi) + + + Friends + Sohbet ile Arkadaş + + + + PhotoDialog + + Remove + Remove + + + Average + Ortalama + + + Rating + Oran + + + Date + Date + + + Location + Location + + + Size + Size + + + Description + Açıklamalar + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + Peer + + + + Slideshow + + + + Photo + + + + Thumb Image + + + + Image Name + + + + Comment + + + + PeerId + + + + PhotoId + + + + Add Photo(s) + + + + Add Photo SlideShow + + + + Update Details + + + + Photo + + + + Insert Show Lists + + + + Open + + + + Excellent + + + + Good + + + + Below avarage + + + + Bad + + + + Unrated + + + + + PhotoShow + + Date: + Tarih: + + + Pause + Duraklat + + + Photo Show + + + + Location: + + + + Comment: + + + + Display Size: + + + + 320 x 320 + + + + 640 x 640 + + + + Full Size + + + + Play Rate: + + + + 1 Sec + + + + 2 Sec + + + + 5 Sec + + + + 10 Sec + + + + 20 Sec + + + + 1 Min + + + + Edit Photo Details + + + + Save Photo + + + + No Photo Selected + + + + Back + + + + Start + + + + Play + + + + Forward + + + + + PluginFrame + + Remove + Remove + + + + PluginManagerWidget + + Install New Plugin... + + + + Open Plugin to install + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + Popularity + + + + + PopupChatDialog + + Paste retroshare Link + Yapıştır retroshare Link + + + Friend Not Online + Arkadaşım Online değil + + + RetroShare + Retroshare + + + Your Friend is offline +Do you want to send them a Message instead + Arkadaşınızın offline +Bunun yerine Mesaj göndermek istiyor musunuz? + + + is typing... + yazıyor ... + + + Save as... + Farklı kaydet... + + + Send + Göndermek + + + Italic + Italik + + + Clear Chat History + Chat Sohbeti temizle + + + Add Extra File + Ekstra Dosya Ekle + + + File not found or file name not accepted. + Dosya bulunamadı veya isim kabul edilmedi . + + + Close + + + + Attach a Picture + + + + Add a File for your Friend + + + + Bold + + + + Underline + + + + Font + + + + Text Color + + + + Strike + + + + Disable Emoticons + + + + Save Chat History + + + + Clear offline messages + + + + Browse Message History + + + + Browse History + + + + Delete Chat History + + + + Deletes all stored and displayed chat history + + + + Friend not Online + + + + Paste RetroShare Link + + + + Hide Avatar + + + + Show Avatar + + + + Do you really want to physically delete the history? + + + + Load Picture File + + + + Drop file error. + + + + Directory can't be dropped, only files are accepted. + + + + Text File (*.txt );;All Files (*) + + + + apears to be Offline. + + + + Messages you send will be delivered after Friend is again Online + + + + is Idle and may not reply + + + + is Away and may not reply + + + + is Busy and may not reply + + + + + PopupChatWindow + + RetroShare + Retroshare + + + Avatar + + + + Set your Avatar Picture + + + + Dock tab + + + + Undock tab + + + + Set Chat Window Color + + + + Load File + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + Resimler (*.png *.xpm *.jpg *.tiff *.gif) + + + + PrintPreview + + Print + Yazdır + + + RetroShare Message - Print Preview + + + + &Print... + &Yazdır... + + + Page Setup... + + + + Zoom In + + + + Zoom Out + + + + &Close + + + + + ProfileEdit + + Profile + Profil + + + Profile Edit + + + + Category + + + + Thoughts + + + + Edit Profile Category + + + + Birthday + + + + School + + + + University + + + + Phone Number + + + + Favourite Books + + + + Favourite Music + + + + Favourite Films + + + + or Custom Entry + + + + Add Entry + + + + Move + + + + Close Editor + + + + Remove Profile Entry + + + + Move Profile Entry Up + + + + Move Profile Entry Down + + + + + ProfileView + + Download All + Download alayı + + + RetroShare + Retroshare + + + Name + Name + + + Size + Size + + + Profile View + + + + Peer ID + + + + Last Post: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + Edit Profile + + + + Category + + + + Thoughts + + + + Favourite Files + + + + Hash + + + + Close Profile + + + + Clear Photo + + + + Change Photo + + + + Remove Favourite + + + + Clear Favourites + + + + Download File + + + + Error : cannot get peer details. + + + + + ProfileWidget + + Edit Personal message + Değiştir Kişisel mesaj + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Yer:</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Diğer Bilgiler</span></p></body></html> + + + Addresses list + Ads listesi + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + Name + Name + + + Date + Date + + + Size + Size + + + Popularity + Popülerlik: + + + RetroShare + Retroshare + + + Inititialize failed. Wrong or missing installation of gpg. + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + Multiple instances + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + Login Failure + Giriş Hatası + + + Maybe password is wrong + Belki şifre yanlış + + + Deny friend + Arkadaş reddet + + + Make friend + Arkadaş yap + + + File Request Confirmation + + + + The file has been added to your download list. + + + + File Request canceled + + + + The file has not been added to your download list, because you already have it. + + + + Friend Request Confirmation + + + + The friend is already in your list. + + + + The friend has been added to your list. + + + + Friend Request canceled + + + + The friend could not be added to your list. + + + + The friend could not be found. + + + + Forum Request canceled + + + + The forum "%1" could not be found. + + + + The forum message in forum "%1" could not be found. + + + + Channel Request canceled + + + + The channel "%1" could not be found. + + + + The channel message in channel "%1" could not be found. + + + + Message Request canceled + + + + Cannot send a message to a not accepted receipient "%1". + + + + The receipient of the message is unknown. + + + + File Request Error + + + + The file link is malformed. + + + + %1 of %2 RetroShare links processed. + + + + Request Confirmation + + + + (Age in seconds) + + + + (Depth) + + + + total + + + + Search requests repartition: + + + + Tunnel requests repartition: + + + + Peer details + + + + The following has not been added to your download list, because you already have it: + + + + + Start with a RetroShare link is only supported for Windows. + + + + + QuickStartWizard + + Quick Start Wizard + Hızlı Başlangıç Sihirbazı + + + Next > + Sonraki > + + + Exit + Çıkış + + + For best performance, RetroShare needs to know a little about your connection to the internet. + En iyi performans için, Retroshare biraz İnternet bağlantınız hakkında bilmelidir + + + Choose your upload speed limit: + gönderme hız sınırı seç: + + + Choose your download speed limit: + indirme hız sınırı seç: + + + Connection : + Bağlantı + + + Firewalled + Güvenlik duvarı + + + Manually forwarded port + Port yönlendirme + + + Dicovery : + Keşif: + + + Share Ip and information with your friend (Disc On) + Ip ve bilgi paylaş arkadaşınız ile + + + Don't share any information (Disc Off) + (Disk Kapalı) herhangi bir bilgi paylaşmayın + + + < Back + < Geri + + + Directory + Klasör + + + Network Wide + Geniş ağı + + + Browseable + Taranabilir + + + Add + Ekle + + + Remove + Kaldır + + + Do not show a message when Closing RetroShare + Çıkarken sorma + + + Start Minimized + Küçültülmüş başlat + + + Start RetroShare when my System Starts. + Windows ile başlat + + + Finish + Bitir + + + Select A Folder To Share + Bir klasör seçin Paylaşım için + + + Shared Directory Added! + Paylaşılan Dizin Eklendi! + + + Do you really want to stop sharing this directory ? + Gerçekten bu dizinin paylaşımını durdurmak istiyor musunuz? + + + Warning! + Uyarı! + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + KB/s + + + + Automatic (UPnP) + + + + Discovery : + + + + Public: DHT & Discovery + + + + Private: Discovery Only + + + + Inverted: DHT Only + + + + Dark Net: None + + + + Dynamic DNS: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + Automatically share incoming directory (Recommended) + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Start minimized on system start + + + + + RSettingsWin + + General + Genel + + + Directories + Dizinler + + + Server + Bağlantı + + + Transfer + Aktarım + + + Notify + Bildirimler + + + Security + Güvenlik + + + Message + Mesaj + + + Appearance + Görünüm + + + Sound + Ses + + + Error Saving Configuration + Error Saving Configuration + + + Forum + + + + Chat + + + + UnknownPage + + + + Error Saving Configuration on page + + + + + RatesStatus + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>Indirme:</strong> 0.00 (kB/s) | <strong>Gönderme:</strong> 0.00 (kB/s) + + + <strong>Down:</strong> + <strong>Indirme:</strong> + + + <strong>Up:</strong> + <strong>Gönderme:</strong> + + + Down: + Indirme: + + + Up: + Gönderme: + + + + RemoteDirModel + + Friends Directories + Arkadaş Dizinleri + + + My Directories + Dosyalarım + + + Size + Boyut + + + Share Type + Paylaş Tipi + + + Rank + Rank + + + Age + Yaş + + + FILE + Dosya + + + Anonymous + Anonim + + + Files + Dosya + + + DIR + Klasör + + + + RetroshareDirModel + + Anonymous + Anonim + + + Anonymous and browsable by friends + + + + Only browsable by friends + + + + NEW + + + + + Rshare + + Invalid language code specified: + Invalid language code specified: + + + Invalid GUI style specified: + Invalid GUI style specified: + + + Resets ALL stored RetroShare settings. + + + + Sets the directory RetroShare uses for data files. + + + + Sets the name and location of RetroShare's logfile. + + + + Sets the verbosity of RetroShare's logging. + + + + Sets RetroShare's interface style. + + + + Sets RetroShare's interface stylesheets. + + + + Sets RetroShare's language. + + + + RetroShare Usage Information + + + + Invalid log level specified: + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + RetroShare ID + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + Add Friends RetroShare ID... + + + + Paste Friends RetroShare ID in the box below + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + B + + + + KB + + + + MB + + + + GB + + + + + SearchDialog + + Sources + Kaynak + + + Results + Sonuç + + + Close all Search Resullts + Tümünü Kapat + + + Close All Search Results + Tümünü Kapat + + + Download Selected + Indir + + + Download + Indir + + + Enter a keyword here (at least 3 char long) + Burada anahtar kelime girin (en az 3 uzun) char + + + Copy retroshare Link + Kopyala retroshare Link + + + Send retroshare Link + Gönder retroshare Link Mesajla + + + Broadcast on Channel + Broadcast on Channel + + + Recommend to Friends + Recommend to Arkadaş + + + Remove + Kaldır + + + Remove All + Hepsini Kaldır + + + Folder + Klasör + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + Any + Herhangi + + + Audio + Ses + + + Video + Görüntü + + + Images + Images + + + Programs + Programs + + + Archives + Archives + + + Documents + Documents + + + Download Notice + Indirme haberi + + + Size + Boyut + + + Type + Türü + + + Archive + Arşiv + + + CD-Image + CD-imajı + + + Document + Belge + + + Picture + Resim + + + Directory + Klasör + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Close all Search Resullts</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Tümünp Kapat</span></p></body></html> + + + Clear all Search Results + Tümünü Kapat + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Download Selected</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Indir</span></p></body></html> + + + Include files from your own file list in the search result + Arama sonucu kendi dosyalarini listeden Dahil et + + + Include own files + kendi dosyalarini göster + + + Search inside "browsable" files of your friends + Arama için "arkadaşlarınızın göz atılabilir" dosyaları + + + Search in friends lists + Arkadaşlari ara + + + Multi-hop search at distance 6 in the network +(always reports available files) + Çok ağ mesafe 6 hop arama +(her zaman) dosyaları mevcuttur raporları + + + F2F search + F2F ara + + + Limit number of results to : + Sonuç için sınır sayısı: + + + Filename + Dosya Adı + + + Start Search + Başlat + + + Search + Başlat + + + Reset + Iptal + + + Advanced Search + Gelişmiş Arama + + + Advanced + Ilerlemiş + + + Age + Yaş + + + KeyWords + Kelimeler + + + Program + + + + Enter a Keyword here + + + + Search Id + + + + Filter Search Result + + + + Clear Filter + + + + File Name + + + + File Size + + + + Hash + + + + Copy RetroShare Link + Kopyala retroshare Link + + + Send RetroShare Link + + + + Skipping Local Files + + + + Sorry + + + + This function is not yet implemented. + + + + New RetroShare Link(s) + + + + + SendLinkDialog + + Send + Göndermek + + + + ServerPage + + Change + Restart Server + Change + Restart + + + Server Settings + Peer Settings + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + + + Firewalled + Güvenlik duvarı + + + Port: + Port: + + + Misc + Misc + + + behinde Firewall + Behind a Firewall + + + Forwarded External Port + Forwarded External Port (Router) + + + Transfer Rates + Transfer Rates + + + Network Configuration + + + + Automatic (Upnp) + + + + Manual Forwarded Port + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + Public: DHT & Discovery + + + + Private: Discovery Only + + + + Inverted: DHT Only + + + + Dark Net: None + + + + Download (KB/s) + + + + kB/s + + + + Upload (KB/s) + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + Allow Tunnel Connection + + + + Local Address + + + + External Address + + + + Dynamic DNS + + + + Show Discovery information in statusbar + + + + IP Service + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + Allow RetroShare to ask my ip to these websites: + + + + + Settings + + Settings + Settings + + + Options + Seçenekler + + + Transfer + Aktarım + + + Notify + Bildirimler + + + Security + Güvenlik + + + Message + Mesaj + + + Appearance + Görünüm + + + Sound + Ses + + + Cancel + Iptal + + + Apply + Apply + + + OK + OK + + + General + Genel + + + Network + Network + + + Server + Bağlantı + + + Directories + Dizinler + + + Forum + + + + Chat + + + + + ShareDialog + + Browse + Gözalt + + + Virtual Folder + Sanal Klasör + + + Browsable + Taranabilir + + + Network Wide + Geniş ağı + + + Anonymous + Anonim + + + Select A Folder To Share + Bir klasör seçin Paylaşım için + + + RetroShare Share Folder + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + Share Folder + + + + Local Path + + + + Share Flags + + + + Browseable by Friends + + + + Anonymous shared Network Wide + + + + OK + + + + Cancel + + + + + ShareKey + + Share Channel + Paylaş Kanalı + + + RetroShare + Retroshare + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + check peers you would like to share private publish key with + + + + Share for Friend + + + + Contacts: + + + + Share + + + + Cancel + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + Please select at least one peer + + + + + ShareManager + + Add a Share Directory + Paylaşım Dizin Ekle + + + Stop sharing selected Directory + Seçilen paylaşımı durdur + + + Select A Folder To Share + Bir klasör seçin Paylaşım için + + + Do you really want to stop sharing this directory ? + Gerçekten bu dizinin paylaşımını durdurmak istiyor musunuz? + + + Remove + Kaldır + + + Warning! + Uyarı! + + + Shared Directory Added! + Paylaşılan Dizin Eklendi! + + + RetroShare Share Manager + Retroshare Paylaş Yöneticisi + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Paylaş Yöneticisi</span></p></body></html> + + + Shared Folder Manager + Paylaşılan Klasör Yöneticisi + + + Directory + Klasör + + + Virtual Folder + Sanal Klasör + + + Network Wide + Geniş ağı + + + Browsable + Taranabilir + + + Add + Ekle + + + Close + Kapat + + + Edit + Değiştir + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + Edit selected Shared Directory + + + + If checked, the share is anonymously shared to anybody. + + + + If checked, the share is browsable by your friends. + + + + Do you really want to stop sharing this directory ? + + + + Drop file error. + + + + File can't be dropped, only directories are accepted. + + + + Directory not found or directory name not accepted. + + + + + SharedFilesDialog + + Download + Indir + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + + + Checking... + Kontrol ediliyor ... + + + Check files + Onay dosyaları + + + Copy retroshare Link + Kopyala retroshare Link + + + Send retroshare Link + Gönder retroshare Link Mesajla + + + Copy retroshare Links to Clipboard + retroshare Link Panoya Kopyala + + + Copy retroshare Links to Clipboard (HTML) + reroshare Link Panoya Kopyala (HTML) + + + Send retroshare Links + Gönder retroshare link Mesajla + + + Send retroshare Links (HTML) + Gönder retroshare link Mesajla (HTML) + + + Send retroshare Links to Chat + Gönder retroshare link Chat + + + Open File + Dosyayı Aç + + + Open Folder + Klasör Aç + + + <strong>My Shared Files</strong> + <strong>Paylaşılan Dosyalar</strong> + + + <strong>Friends Files</strong> + <strong>Arkadaşların Dosyaları</strong> + + + <strong>Files</strong> + <strong>Dosyalar</strong> + + + Splitted View + Pencereyi Böl + + + Friends Folders + Arkadaşların Dosyaları + + + My Folders + Klasörlerim + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Dosyalar</span></p></body></html> + + + All + Hepsi + + + One day old + Bir gün olan + + + One Week old + Bir Haft + + + One month old + Bir ay + + + Start Search + Başlat + + + Download selected + Indir + + + check files + Onay dosyaları + + + Search files + + + + Reset + + + + Tree view + + + + Flat view + + + + Send retroshare Links to Cloud + + + + Add Links to Cloud + + + + Recommend in a message to + + + + RetroShare Link + + + + Recommendation(s) + + + + Set command for opening this file + + + + + SoundPage + + Friend + Arkadaş + + + Browse + Gözalt + + + Sound Events + + + + go Online + + + + Chatmessage + + + + New Msg + + + + FileSend + + + + Finished + + + + FileRecive + + + + Incoming + + + + + SplashScreen + + Load profile + + + + Load configuration + + + + Create interface + + + + + StartDialog + + RetroShare + Retroshare + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Giriş</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + Log In + Giriş + + + Remember Password + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Create new Profile...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Yeni profil oluştur...</span></a></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Bilgi...</span></a></p></body></html> + + + Name (GPG Id) - location: + + + + Name - location: + Adı - yeri: + + + Multiple instances + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + Login Failure + Giriş Hatası + + + Maybe password is wrong + Belki şifre yanlış + + + Warning + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + Create a New Profil + Yeni profil oluştur + + + This will generate a new Profile + Are you sure you want to continue + Bu yeni bir profil oluşturur + Devam etmek istediğinizden emin misiniz + + + + StatisticDialog + + Statistics + Statistics + + + Download + Download + + + Session: + Session: + + + Downloaded: + Downloaded: + + + Average Downloadspeed: + Average Downloadspeed: + + + Count of Downloads: + Count of Downloads: + + + Overall + Overall + + + Upload + Upload + + + Session + Session + + + Uploaded: + Uploaded: + + + Average Uploadspeed: + Average Uploadspeed: + + + Count of Uploads: + Count of Uploads: + + + Uploaded + Uploaded + + + Connections: + Connections: + + + Peers: + Peers: + + + Misc + Misc + + + Uptime: + Uptime: + + + Overall: + Overall: + + + Uptime + Uptime + + + Records + Records + + + Uploadspeed: + Uploadspeed: + + + Downloadspeed: + Downloadspeed: + + + Show Settings + Show Settings + + + Reset + Reset + + + Receive Rate + Receive Rate + + + Send Rate + Send Rate + + + Always On Top + Always On Top + + + 100 + 100 + + + % Opaque + % Opaque + + + Changes the transparency of the Bandwidth Graph + Changes the transparency of the Bandwidth Graph + + + Save + Save + + + Cancel + Cancel + + + Hide Settings + Hide Settings + + + Transfer + Aktarım + + + Now + + + + Session UL:DL Ratio: + + + + Cumulative UL:DL Ratio + + + + Time Statistics + + + + Since: + + + + Cumulative + + + + %1 days + + + + + StatusDefs + + Offline + Çevrimdışı + + + Away + Dışarıda + + + Busy + Meşgul + + + Online + Çevrimiçi + + + Idle + Boşta + + + Friend is offline + + + + Friend is away + + + + Friend is busy + + + + Friend is online + + + + Friend is idle + + + + Connected + + + + Unreachable + + + + Available + Mevcut + + + Neighbour + + + + Trying tunnel connection + + + + Trying TCP + + + + Trying UDP + + + + Connected: TCP + + + + Connected: UDP + + + + Connected: Tunnel + + + + Connected: Unknown + + + + DHT: Contact + + + + + StatusMessage + + Personal message + Kişisel ileti + + + Status message + Durum mesajı + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Kişisel ileti</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Durum mesajı</span></p></body></html> + + + OK + Tamam + + + Cancel + Iptal + + + Paste RetroShare Link + + + + + StyleDialog + + Style + Style + + + Define Style + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + Choose color + + + + Color 2 + + + + Color 1 + + + + None + + + + Solid + + + + Gradient + + + + + SubDestItem + + Type + Type + + + Delete FeedItem + + + + + SubFileItem + + File Name + File Name + + + Play + Başlat + + + Expand + Genişlet + + + Cancel Download + Iptal + + + %p Kb + + + + Download File + + + + Download + + + + Play File + + + + Save File + + + + ERROR + + + + EXTRA + + + + REMOTE + + + + DOWNLOAD + + + + LOCAL + + + + UPLOAD + + + + File %1 does not exist at location. + + + + File %1 is not completed. + + + + Save Channel File + + + + + TBoard + + Pause + Duraklat + + + + TagDefs + + Important + Önemli + + + Work + + + + Personal + Kişisel + + + Todo + Yapılacak + + + Later + Sonra + + + + TagsMenu + + Remove All Tags + Tüm etiketleri sil + + + New tag ... + Yeni etiket... + + + + TextPage + + Use text representation of the PGP certificates. + PGP sertifikaların Metin temsili. + + + The text below is your PGP certificate. You have to provide it to your friend + Metni aşağıda PGP belgedir. Arkadaşınızın bunu sağlamak zorunda + + + RetroShare + Retroshare + + + Save as... + Farklı kaydet... + + + Certificate Load Failed + sertifika yüklemek başaramamak + + + Text certificate + + + + Copy your Cert to Clipboard + + + + Save your Cert into a File + + + + Run Email program + + + + Please, paste your friends PGP certificate into the box below + + + + Clean certificate + + + + RetroShare Invite + + + + Connect Friend Help + + + + You can copy this text and send it to your friend via email or some other way + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + TransferPage + + Transfer + Aktarım + + + Transfer options + Aktarım seçenekleri + + + Queue Size: + kuyruk Boyut: + + + Maximum Download speed per file: + Dosya başına maksimum yükleme hızı: + + + Default chunk strategy: + Varsayılan chunk stratejisi: + + + Random + Rasgele + + + Show Cache Transfers + göster Önbellek Transferleri + + + F2F Routing + F2F Yönlendirme + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + Safety disk space limit : + + + + Streaming + + + + MB + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + Cancel + Iptal + + + Clear Completed + Tamanları Temizle + + + Status + Durum + + + Completed + Tamanlandı + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Indirenler:</span></p></body></html> + + + Uploads + Gönderiliyor + + + Selected transfer + Dosya + + + Done + olmuş + + + Active + Aktif + + + Outstanding + Tamamlanmamış + + + Tunneling + Tünel + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + + + Name + i.e: file name + Dosya Adı + + + Size + i.e: file size + Boyut + + + Progress + i.e: % downloaded + Progress + + + Speed + i.e: Download speed + Hız + + + Progress / Availability + i.e: % downloaded + Ilerleme + + + Sources + i.e: Sources + Kaynak + + + Progress + i.e: % uploaded + Ilerleme + + + Speed + i.e: upload speed + Hız + + + Transferred + Aktarıldı + + + Play + Başlat + + + Pause + Duraklat + + + Resume + Devam + + + Open Folder + Klasör Aç + + + Open File + Dosyayı Aç + + + Preview File + Önizleme + + + Details... + Ayrıntılar + + + Copy retroshare Link + Kopyala retroshare Link + + + Paste retroshare Link + Yapıştır retroshare Link + + + View + Görüntü + + + Down + Aşağı + + + Up + Yukarı + + + Top + Üst + + + Bottom + Alt + + + Move in queue... + Kuyrukta Taşı ... + + + Priority (Speed)... + Öncelikl (Hız) + + + Low + Düşuk + + + Normal + Normal + + + High + Yüksek + + + Auto + Otomatik + + + Random + Rasgele + + + Chunk strategy + Chunk stratejisi + + + Queued + Sırada + + + Checking... + Kontrol ediliyor ... + + + RetroShare + Retroshare + + + Details: + Ayrıntılar + + + File %1 is not completed. If it is a media file, try to preview it. + %1 Dosya Tamamlanmamış. Eğer bir medya sa, önizleme deneyin . + + + Are you sure that you want to cancel and delete these files? + Bu dosyaları iptal et ve silmek istediğinizden emin misiniz? + + + Speed / Queue position + Hızı / Kuyruk konumu + + + Remaining + Kalan + + + Download time + i.e: Estimated Time of Arrival / Time left + Indirme zamani + + + Slower + Yavaş + + + Average + Ortalama + + + Faster + Daha hızlı + + + Failed + Başarısız + + + Okay + Tamam + + + Waiting + Bekliyor + + + Downloading + Indiriliyor + + + Complete + Bitmış + + + Paused + Durdurulmuş + + + Unknown + Bilinmeyen + + + Transferring + Aktarılıyor + + + Uploading + Gönderiliyor + + + Show cache transfers + + + + Core-ID + + + + Peer + i.e: user name + + + + Hash + + + + Router Statistics + Yönlendirici İstatistikleri + + + Router Requests + Rota İstek + + + Force Check + + + + Copy RetroShare Link + Kopyala retroshare Link + + + Paste RetroShare Link + Yapıştır retroshare Link + + + Streaming + + + + Move in Queue... + + + + version: + + + + File preview + + + + File %1 preview failed. + + + + Open Transfer + + + + + TreeStyle_RDM + + FILE + Dosya + + + Files + Dosya + + + DIR + Klasör + + + Friends Directories + Arkadaş Dizinleri + + + My Directories + Dosyalarım + + + Age + Yaş + + + Friend + Arkadaş + + + Share Type + Paylaş Tipi + + + File + + + + Size + + + + What's new + + + + + TrustView + + Trust + Güven + + + Zoom : + + + + Update + + + + Showing: whole network + + + + This table normaly auto-updates every 10 seconds. + + + + Self + + + + is authenticated (one way) by + + + + Half + + + + authenticated himself + + + + authenticated each other + + + + Full + + + + is authenticated by + + + + peers, including him(her)self. + + + + authenticated + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + Search requests + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + File Name + File Name + + + Type + Type + + + Router Statistics + + + + F2F router information + + + + + TurtleRouterStatistics + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + Turtle router traffic: + + + + Tunnel requests Up + + + + Tunnel requests Dn + + + + Incoming file data + + + + Outgoing file data + + + + Forwarded data + + + + + ULListDelegate + + B + + + + KB + + + + MB + + + + GB + + + + + VMessageBox + + OK + OK + + + Cancel + Cancel + + + Yes + Yes + + + No + No + + + Help + Help + + + Retry + Retry + + + Show Log + Show Log + + + Show Settings + Show Settings + + + Continue + + + + Quit + Çıkış + + + Browse + Gözalt + + + + misc + + Unknown + Unknown (size) + Bilinmeyen + + + Unknown + Bilinmeyen + + + B + bytes + + + + KiB + kibibytes (1024 bytes) + + + + MiB + mebibytes (1024 kibibytes) + + + + GiB + gibibytes (1024 mibibytes) + + + + TiB + tebibytes (1024 gibibytes) + + + + < 1m + < 1 minute + + + + %1 minutes + e.g: 10minutes + + + + %1h %2m + e.g: 3hours 5minutes + + + + %1d %2h + e.g: 2days 10hours + + + + %1y %2d + e.g: 2 years 2days + + + + k + e.g: 3.1 k + + + + M + e.g: 3.1 M + + + + G + e.g: 3.1 G + + + + T + e.g: 3.1 T + + + + diff --git a/retroshare-gui/src/lang/retroshare_zh_CN.qm b/retroshare-gui/src/lang/retroshare_zh_CN.qm new file mode 100644 index 000000000..bd350a14d Binary files /dev/null and b/retroshare-gui/src/lang/retroshare_zh_CN.qm differ diff --git a/retroshare-gui/src/lang/retroshare_zh_CN.ts b/retroshare-gui/src/lang/retroshare_zh_CN.ts new file mode 100644 index 000000000..0443aeda4 --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_zh_CN.ts @@ -0,0 +1,14673 @@ + + + + + AboutDialog + + + About RetroShare + + + + + About + + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + 文件类型(扩展名): + + + + Use default command + 使用缺省命令 + + + + Command + 命令 + + + + RetroShare + + + + + Sorry, can't determine system default command for this file + + 抱歉,不能确定文件的缺省命令。 + + + + AddLinksDialog + + + + Add Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + Add Anonymous Link + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + RetroShare: Advanced Search + + + + + Cancel + 取消 + + + + Search + 搜索 + + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + Cancels the search. + + + + + Perform the advanced search. + + + + + Search Criteria + + + + + AppearancePage + + + Language + 语言 (Language) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare에서 사용되는 언어를 선택하십시오</p></body></html> + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">改变语言才生效后重啟Retroshare!</p></body></html> + + + + Style + 风格 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RetroShare의 인터페이스 스타일을 선택하십시오</p></body></html> + + + + Style Sheet + + + + + ApplicationWindow + + RetroShare %1 + RetroShare %1 + + + + Hide + 隐藏 + + + + Show + 显示 + + + Peers + 节点 + + + Transfers + 文件 + + + Messages + 电子邮件 + + + Blog Feed + 博客日志 + + + + Games Launcher + 加载游戏 + + + + Photo View + 照片查看 + + + + Shared Calendars + 分享日程表 + + + Library + + + + + Statistics + 统计 (Statistics) + + + + + RetroShare + + + + + AttachFileItem + + + Form + + + + + %p Kb + + + + + Cancel Download + + + + + BandwidthGraph + + + + Show Settings + 显示设置 + + + + Reset + 重新设置 + + + + Receive Rate + 接收速率 + + + + Send Rate + 发送速率 + + + + Style + 风格 + + + + Changes the transparency of the Bandwidth Graph + Changes the transparency of the Bandwidth Graph / 改变透明度的频宽图 + + + + 100 + 100 + + + + % Opaque + % Opaque + + + + Save + 保存 + + + + Cancel + 取消 + + + + Since: + 自从: + + + + Hide Settings + 隐藏设置 + + + + RetroShare Bandwidth Usage + + + + + Always on Top + + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + 流行度 + + + + Last Post + 最后发表 + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + 确定 + + + + Close + 关闭 + + + + BlogDialog + + Blogs + 博客 + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + 题目 + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + 添加 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + 订阅 + + + + + Create New Blog + + + + + Name + 姓名 + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + Comments here + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + + Expand + + + + + Remove Item + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Hide + 隐藏 + + + + CalDialog + + + Remove + 移除 + + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + 名字 + + + + Location: + + + + + ... + + + + + Status: + 状态: + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + 添加 + + + + Peer Calendars + + + + + CallToaster + + Message + 信息 + + + + CertificatePage + + + Certificate files + 证书 + + + Use XPGP certificates saved in files. + 导入文件中的XPGP证书。 + + + + Use PGP certificates saved in files. + 导入文件中的PGP证书。 + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + 你可把生成的证书文件分享给你的好友。同样的,你也可以使用以前生成的证书文件。 + + + + Export my certificate... + 出口我的证书... + + + Specify path to your friend's certificate in the box below + 选择在下表中给你好友的证书 + + + + Browse + 浏览 + + + + Select Certificate + 选择证书 + + + + Please choose a filename + 请选择一个文件名 + + + Certificates (*.pqi *.pem) + 证书 (*.pqi *.pem) + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + + + + RetroShare + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + 证书创建成功 + + + + + Sorry, certificate file creation failed + 抱歉,证书创建失败 + + + + Certificate Load Failed:something is wrong with %1 + 证书加载失败:%1出错。 + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + 证书加载失败:文件%1不存在。 + + + + ChanMsgDialog + + Compose + 谱写了信息渠道 + + + Recommended Files + 推荐档案 + + + Send To: + 发送给: + + + Send + 发送 + + + Delete Channel + 删除频道 + + + Create Channel MSG + 建立MSG频道 + + + &Left + (&L)左 + + + C&enter + (&E)中心 + + + &Right + (&R)右 + + + &Justify + (&J)两端对齐 + + + Send this message now + 立刻发送信息 + + + Toggle Contacts View + 切换联系人视图 + + + Save this message + 保存信息 + + + Compose: + 谱写了信息渠道 + + + &File + (&F)文件 + + + &New + (&N)新建 + + + &Open... + (&O)打开 + + + &Save + (&S)保存 + + + Save &As... + (&A)另存为 + + + &Print... + (&P)打印 + + + &Export PDF... + (&E)导出PDF + + + &Quit + (&Q)退出 + + + &Edit + (&E)编辑 + + + &Undo + (&U)撤销 + + + &Redo + (&R)重做 + + + Cu&t + (&T)剪切 + + + &Copy + (&C)复制 + + + &Paste + (&P)粘贴 + + + &View + (&V)查看 + + + &Contacts Sidebar + (&C)联系人栏 + + + &Insert + (&I)插入 + + + &Image + (&I)图片 + + + Open File... + 打开文件 + + + HTML-Files (*.htm *.html);;All Files (*) + 网页 (*.htm *.html);;所有文件 (*) + + + Save as... + 另存为 + + + Print Document + 打印文档 + + + Save Message + 保存信息 + + + Message has not been Sent. +Do you want to save message ? + 信息还没有发送。你要保存吗? + + + Choose Image + 选择图片 + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + 支持的图片格式(*.png *.jpeg *jpg *gif) + + + Add Extra File + 添加附件 + + + File Name + 文件名称 + + + Size + 大小 + + + Sources + 来源 + + + Save + 保存 + + + Subject: + 题目: + + + Attach File + 附加文件 + + + Color + 颜色 + + + Reply + 回复 + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + + + + + Play + 播放 + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + 隐藏 + + + + ChanNewItem + + + Remove Item + + + + + Unknown Channel + + + + + New Channel + 新频道 + + + + Updated Channel + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + Forum Name + 论坛名称 + + + + Popularity + 流行度 + + + + Last Post + 最后发表 + + + Forum ID + 论坛身份证 + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + 类型 + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 限制 - 任何人都可以阅读,有限的出版(私人发布键) + + + + Private - (Private Publish Key required to view Messages) + 私人 - (私人发布的关键要求,以查看消息) + + + + Cancel + + + + + OK + 确定 + + + + Close + 关闭 + + + + ChannelFeed + + + Create Channel + 创建频道 + + + + Subscribe To Channel + 订閲频道 (Subscribe) + + + Title + 标题 + + + Description + 描述 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + Add + 添加 + + + + Display + 显示 + + + + Unsubscribe + + + + + Subscribe + 订阅 + + + + Set all to read + + + + + Enable Auto-download + + + + + Unsubcribe To Channel + + + + Name + 姓名 + + + Popularity + 流行度 + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + Create a new Channel + 创建一个新频道 + + + New Channel + 新频道 + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + 发送 + + + + Cancel + + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + 一般 + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ChatToaster + + Message + 信息 + + + + ComboStatus + + Online + 在线 + + + + ConclusionPage + + + Make Friend + 成为好友 + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + 选项 + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + Fill details about your friend here + 填写你好友的详细信息 + + + + Peer details + 节点详细信息 + + + Trust: + 信任 + + + + Name: + 名字 + + + + Loc: + + + + Country: + 国家 + + + + Signers + 签名 + + + AUTH CODE + 认证码 + + + + ConfCertDialog + + + Cancel + 取消 + + + Port: + ip端口 + + + Trust Settings + 信託设定 + + + Trust Level + 信任水平 + + + Trust Their Signature + 信託签名 + + + Sign The Certificate + 签署证书 + + + + Details + 详情 + + + + Loc + + + + + Peer Address + 结点地址 + + + + Last Contact + 最后一次联系 + + + + Apply and Close + 应用并关闭 + + + + + RetroShare + Retroshare + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + 密码错误 + + + + Peer Info + + + + Name: + 名字 + + + Peer Details + 结点详细信息 + + + + Name + 姓名 + + + + Peer ID + + + + + Version + + + + + RetroShare ID + + + + + Status + 状态 + + + + Dynamic DNS + + + + + Addresses list + 地址列表 + + + + Trust + + + + + Local Address + 本地地址 + + + + Friend Details + 节点详细信息 + + + + External Address + 외부 주소 + + + + + Port + 포트 + + + + Your trust in this peer is: + 이 피어에 대한 여러분의 신뢰입니다 : + + + None + 毫无 + + + Marginal + 한계 + + + Full + 전체 + + + + None + + + + + Marginal + + + + + Full + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + + Sign GPG key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Deny Friend + 拒绝好友 + + + + Make Friend + 成为好友 + + + + Certificate + + + + + OK + 确定 + + + + ConnectDialog + + Peer Details + 结点详细信息 + + + Make Friend + 成爲好友 + + + Cancel + 取消 + + + Trust: + 信任 + + + Name: + 名字 + + + Country: + 国家 + + + + ConnectFriendWizard + + + Connect Friend Wizard + 连接好友向导 + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + 姓名 + + + + Description + 描述 + + + + Type: + 类型: + + + + Public - Anyone can read and publish (Shared Publish Key) + 公共 - 任何人都可以阅读和发布(发布共享密钥) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 限制 - 任何人都可以阅读,有限的出版(私人发布键) + + + + Private - (Private Publish Key required to view Messages) + 私人 - (私人发布的关键要求,以查看消息) + + + + Allowed Messages + 允许邮件 + + + + Authemticated Messages + + + + + Anonymous Messages + 匿名邮件 + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + + + + + Create + 创建 + + + + RetroShare + Retroshare + + + + Please add a Name + 请添加一个名字 + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + Attachments + 附件 + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + 大胆 + + + + Underline + 强调 + + + + Italic + 斜体 + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + Add Extra File + 添加附件 + + + + RetroShare + Retroshare + + + + Please add a Subject + + + + + &File + (&F)文件 + + + + &New + (&N)新建 + + + + &Open... + (&O)打开 + + + + &Save + (&S)保存 + + + + Save &As... + (&A)另存为 + + + + &Print... + (&P)打印 + + + + Print Preview... + + + + + &Export PDF... + (&E)导出PDF + + + + &Quit + (&Q)退出 + + + + &Edit + (&E)编辑 + + + + &Undo + (&U)撤销 + + + + &Redo + (&R)重做 + + + + Cu&t + (&T)剪切 + + + + &Copy + (&C)复制 + + + + &Paste + (&P)粘贴 + + + + &View + (&V)查看 + + + + &Insert + (&I)插入 + + + + &Image + (&I)图片 + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + (&L)左 + + + + + C&enter + (&E)中心 + + + + + &Right + (&R)右 + + + + &Justify + (&J)两端对齐 + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + 打开文件 + + + + HTML-Files (*.htm *.html);;All Files (*) + 网页 (*.htm *.html);;所有文件 (*) + + + + Save as... + 另存为 + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + 打印文档 + + + + Export PDF + + + + + Choose Image + 选择图片 + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + 支持的图片格式(*.png *.jpeg *jpg *gif) + + + + CreateChannel + + + Create a new Channel + 创建一个新频道 + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + 姓名 + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + 描述 + + + + Type: + 类型: + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 限制 - 任何人都可以阅读,有限的出版(私人发布键) + + + + Private - (Private Publish Key required to view Messages) + 私人 - (私人发布的关键要求,以查看消息) + + + + Allowed Messages + 允许邮件 + + + + Anonymous Messages + 匿名邮件 + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + 通道标识 + + + + Add Channel Logo + 添加频道标志 + + + + Cancel + + + + + Create + 创建 + + + + RetroShare + Retroshare + + + + Please add a Name + 请添加一个名字 + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + 信息 + + + + Subject : + + + + + + Attachments + 附件 + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + 添加附件 + + + + + RetroShare + Retroshare + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Name + 姓名 + + + + Type: + 类型: + + + + Authenticated Messages + + + + + Cancel + 取消 + + + + Please add a Name + 请添加一个名字 + + + + Create new Forum + 创建新论坛 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">新论坛</span></p></body></html> + + + + Description + 描述 + + + + Public - Anyone can read and publish (Shared Publish Key) + 公共 - 任何人都可以阅读和发布(发布共享密钥) + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + 限制 - 任何人都可以阅读,有限的出版(私人发布键) + + + + Private - (Private Publish Key required to view Messages) + 私人 - (私人发布的关键要求,以查看消息) + + + + Allowed Messages + 允许邮件 + + + Authemticated Messages + Authenticated Messages + + + + Anonymous Messages + 匿名邮件 + + + Channel Logo + 通道标识 + + + Add Channel Logo + 添加频道标志 + + + + Create + 创建 + + + + CreateForumMsg + + + Close + 关闭 + + + + Post Forum Message + 邮政论坛留言 + + + + Forum + 论坛 + + + Forum Post Subject + 论坛发布主题 + + + + Attach File + 附加文件 + + + Paste retroshare link + 粘贴retroshare链接 + + + + Forum Post + 论坛发表 + + + + Sign Message + 签写留言 + + + + Subject + 题目 + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + 邮政论坛留言 + + + Paste retroshare Link + 粘贴retroshare链接 + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + Retroshare + + + + Please set a Forum Subject and Forum Message + 请设定一个论坛主题和论坛留言 + + + + Add Extra File + 添加附件 + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + 复制项 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + 保存项 + + + + RetroShare + Retroshare + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + 另存为 + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + 详情 + + + + + General + 一般 + + + + File Name: + 文件名称: + + + + Hash: + + + + + Size: + 大小: + + + + Status: + 状态: + + + Priority + 优先: + + + + Priority: + + + + + Type: + 类型: + + + + Transfer + 文件 + + + + Sources: + 来源: + + + + Datarate: + 速度: + + + + Completed: + 完成: + + + + Chunk size: + 块的大小: + + + + + Number of Chunks + 数块 + + + + Chunks: + 块: + + + + Remaining: + 剩余时间: + + + + Date + 日期 + + + + Download time: + 下载时间: + + + + + Comments + 评论 + + + + + retroshare link(s) + retroshare链接 + + + + Copy + 复制 + + + + OK + 确定 + + + + Cancel + 取消 + + + + Rating + 评级 + + + + File Name + 文件名称 + + + + Not Rated + 未分级 + + + + No Comments + 没有评论 + + + + DirectoriesPage + + + Partials Directory + + + + + Shared Directories + 共享目录 + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + Incoming files + 接收的文件 + + + Add Shared Directory + 添加共享目录 + + + All Files (*) + 所有文件 (*) + + + Add a Share Directory + 添加分享目录 + + + Remove Shared Directory + 移除共享目录 + + + + + Browse + 浏览 + + + + Set Incoming Directory + 设置上传目录 + + + + Set Partials Directory + 设置部分目录 + + + + Incoming Directory + + + + Automatically share incoming directory (Recommanded) + Automatically share incoming directory (Recommanded) + + + + Edit Share + 编辑分享 + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + 关闭 + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + 确定 + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + 添加频道标志 + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + 论坛详情 + + + + Cancel + + + + + OK + 确定 + + + + Edit Forum Details + + + + + Forum Info + 论坛信息 + + + + Forum Name + 论坛名称 + + + + Forum Description + 论坛简介 + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + 题目: + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + 抱歉,有错误产生 + + + + Here is the error message: + 错误信息: + + + + ExampleDialog + + + Vote Up + 投票 + + + + Vote Down + 否决 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">好友</span></p></body></html> + + + + Status + 状态 + + + + Person + + + + + Auto Connect + 自动连接 + + + + Trust Level + 信任水平 + + + + Peer Address + 结点地址 + + + + Last Contact + 最后一次联系 + + + + Organisation + 组织 + + + + Location + 位置 + + + + Country + 国别 + + + + Person Id + 个人识别号码 + + + + Auth Code + 认证码(Authenticate Code 认证) + + + + # + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + (&N)新建 + + + + Add new Association + + + + + &Edit + (&E)编辑 + + + + Edit this Association + + + + + &Remove + (&R)移除 + + + + Remove this Association + + + + + File type + 文件类型 + + + + Friend Help + 好友帮助 + + + + You this + + + + + FileAssotiationsDialog + + &New + (&N)新建 + + + &Edit + (&E)编辑 + + + &Remove + (&R)移除 + + + File type + 文件类型 + + + Friend Help + 好友帮助 + + + + FileTransferInfoWidget + + Chunk map: + 块图: + + + Active chunks: + 主动块: + + + Availability map ( + 可用性地图 + + + sources + 来源 + + + File info: + 文件信息: + + + File hash: + 文件 hash: + + + File size: + 文件大小: + + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + 剩余时间 + + + + Number of sources + + + + + Chunk strategy + 块策略 + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + Chunk size: + 块的大小: + + + Number of chunks: + 数块: + + + Transfered: + 转让: + + + Number of sources: + 数来源: + + + Chunk strategy: + 块策略: + + + Transfer type: + 传输类型: + + + + FlatStyle_RDM + + + Friends Directories + 好友目录 + + + + My Directories + 我的目录 + + + + Size + + + + + Age + 年龄 + + + + Friend + + + + + Share Type + 共享型 + + + + Directory + 目录 + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + 论坛详情 + + + + Forum Info + 论坛信息 + + + + Forum Name + 论坛名称 + + + + Popularity + 流行度 + + + + Last Post + 最后发表 + + + + Forum ID + 论坛身份证 + + + + Forum Description + 论坛简介 + + + + Security + 安全 + + + + Allowed Messages + 允许邮件 + + + + Authemticated Messages + 经过身份验证的邮件 + + + + Anonymous Messages + 匿名邮件 + + + + Cancel + 取消 + + + + OK + 确定 + + + + Apply and Close + 申请并关闭 + + + + ForumMsgItem + + + Remove Item + + + + Forum Name + 论坛名称 + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + 回复 + + + + Send + 发送 + + + + Signed + 签署 + + + + Forum Post + 论坛发表 + + + + Unknown Forum Post + + + + + + + Anonymous + 匿名 + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + 订阅论坛 + + + + Expand + + + + + Forum Description + 论坛简介 + + + + ForumPage + + + Misc + + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + 订阅论坛 + + + + Unsubscribe to Forum + 取消订阅论坛 + + + + New Forum + 新论坛 + + + + Show Forum Details + 显示论坛详细内容 + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Reply + 回复 + + + + Reply to Author + 回覆作者 + + + + Expand all + 全部展开 + + + + Collapse all + 折叠全部 + + + + AUTHD + + + + Popularity: + 流行度: + + + + Your Forums + 你的论坛 + + + + Subscribed Forums + 已订阅论坛 + + + + Popular Forums + 热门论坛 + + + + Other Forums + 其它论坛 + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Mark all as read + + + + + Mark all as unread + + + + + Hide + 隐藏 + + + + Expand + + + + Anonymous + 匿名 + + + signed + 签署 + + + none + 毫无 + + + + + RetroShare + + + + + No Forum Selected! + 没有论坛选择! + + + + You cant reply a Anonymous Author + 你不能回答一匿名作者 + + + + + Date + 日期 + + + + + Start New Thread + 开始新主题 + + + New Message + 新讯息 + + + Popularity + 流行度 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">论坛 </span></p></body></html> + + + Add + 添加 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Start new Thread for Selected Forum</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">启动新的Thread论坛的选择</p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reply Message</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">回复</p></body></html> + + + RetroShare Forums + RetroShare论坛 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">论坛:</p></body></html> + + + + Last Post + 最后发表 + + + + Threaded View + 螺纹查看 + + + + Flat View + 平的看法 + + + + + Title + 标题 + + + + + Author + 作者 + + + + Signed + 签署 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">话题:</span></p></body></html> + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + + + + + Content + + + + + Create Forum + 创建论坛 + + + + Print + 打印 + + + + Start new Thread for Selected Forum + + + + + Display + 显示 + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + 打印预览 + + + + ForumsFillThread + + + + Anonymous + 匿名 + + + + + signed + 签署 + + + + + none + 毫无 + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">朋友们</span></p></body></html> + + + + Add + 添加 + + + + Display + 显示 + + + + Friends + + + + + Status + 状态 + + + + Add or Change your Avatar + 添加或更改您的头像 + + + + Edit Personal message + 修改个人信息 + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + 大胆 + + + + Underline + 强调 + + + + Italic + 斜体 + + + + Font + 字体 + + + + Text Color + + + + + Attach File + 附加文件 + + + + Send + 发送 + + + + Clear Chat History + 清除聊天记录 + + + + + Add Friend + 添加好友 + + + + Create new Profile + 创建新用户资料 + + + + + Create new Forum + 创建新论坛 + + + + F + + + + + + Create new Channel + 创建一个新频道 + + + + C + + + + + Add your Avatar Picture + 添加您的头像照片 + + + + A + + + + + Set your Personal Message + 设置您的个人信息 + + + + Edit your status Message + 编辑您的状态讯息 + + + + Browse Message History + 浏览消息历史记录 + + + + Browse History + 浏览历史 + + + + + Save Chat History + 保存聊天记录 + + + + Hide Offline Friends + 隐藏离线好友 + + + + Hide Status Column + 隐藏状态栏 + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + 添加一个新的组 + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + 外形 + + + + News Feed + 新闻提供 + + + + Welcome to RetroShare's group chat. + 欢迎来到RetroShare组聊天。 + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + 位置 + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + 讯息好友 + + + + Friend Details + 节点详细信息 + + + + Recommend this Friend to... + 这位朋友推荐给... + + + + Connect To Friend + 连接到好友 + + + + Copy RetroShare Link + + + + + + Paste Friend Link + 粘贴友情链接 + + + + Deny Friend + 拒绝好友 + + + + Remove Friend Location + 删除好友位置 + + + + Add to group + 添加到组 + + + + Move to group + 移动到组 + + + + Groups + 团体 + + + + Remove from group + 从组中删除 + + + + Remove from all groups + 从所有组中删除 + + + + Expand all + 全部展开 + + + + Collapse all + 折叠全部 + + + + location + + + + + + Available + 选择不同 + + + + Save Certificate + 保存证书 + + + + Certificates (*.pqi) + 证书 (*.pqi) + + + + Do you want to remove this Friend? + 你要删除这个朋友? + + + + is typing... + 正在输入... + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + 添加附件 + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GamesDialog + + + Cancel Game + 取消游戏 + + + + Add to Invite List + 添加邀请名单 + + + + Remove from Invite List + 移除邀请名单 + + + + + Interested in Playing + 感兴趣的游戏 + + + + Not Interested in Game + 不感兴趣的游戏 + + + + + Not Interested + 不感兴趣 + + + + Confirm Peer in Game + 确认在游戏中的节点 + + + + Remove Peer from Game + 从游戏中移除节点 + + + + Interested in Game + 感兴趣的游戏 + + + + Quit Game + 退出游戏 + + + + Status + 状态 + + + + Accept + 接受 + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + 服务器 + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Delete + 删除 + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + RetroShare setup + Retroshare 设置 + + + Load Trusted Certificate (Optional) + 加载可信任证书(可选) + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friend</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">好友</span></p></body></html> + + + Select File + 选择文案 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Name:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">姓名:</p></body></html> + + + Generate New Certificate + 生成新的证书 + + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + 选择信赖的好友 + + + + Certificates (*.pqi *.pem) + 证书 (*.pqi *.pem) + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + + + Create new Profile + 创建新用户资料 + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + + Your profile is associated to a GPG key + + + + + Use Profile + + + + + Name + 姓名 + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + 位置 + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + Info + 信息 + + + Country: + 国家 + + + Name: + 名字 + + + + GeneralMsgDialog + + Channel + 频道 + + + Forum + 论坛 + + + Blog + 博客 + + + Message + 信息 + + + Add Extra File + 添加附件 + + + Attachments + 附件 + + + + GeneralPage + + Keys manager + key管理器 + + + Style + 风格 + + + Choose RetroShare's interface style + 选择界面风格 + + + Language + 语言 (Language) + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">改变语言才生效后重啟Retroshare!</p></body></html> + + + Choose the language used in RetroShare + 选择语言Retroshare + + + Login + Login 登陆 + + + + Startup + 启动 + + + + Start minimized on system start + + + + + Misc + Misc + + + + Do not show the Quit RetroShare MessageBox + 不显示消息时关闭RetroShare + + + + Do not Minimize to Tray Icon + 不要最小化到托盘图标 + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + Start minimized + 最小化启动 + + + + Start RetroShare when my system starts + 当我开始RetroShare系统启动。 + + + + GraphFrame + + + Recv: + 接收 / Recv: + + + + + + %1 KB/s + %1 KB/s + + + + Sent: + 发送 (Sent): + + + + %1 KB + %1 KB + + + + %1 MB + %1 MB + + + + %1 GB + %1 GB + + + + GraphWidget + + Elastic Nodes + 弹性节点 + + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + 聊天好友 + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + 标题 + + + + Description + 描述 + + + + Reset + + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + 与 / 或 + + + + or + + + + + Name + 姓名 + + + + Path + 路径 + + + + Extension + 扩展名 + + + + Hash + + + + + Date + 日期 + + + + Size + + + + + Popularity + 流行度 + + + + contains + 包含 + + + + contains all + 包含所有 + + + + is + + + + + less than + 小于 + + + + less than or equal + 小于或等于 + + + + equals + 等于 + + + + greater than or equal + 大于或等于 + + + + greater than + 大于 + + + + is in range + 在范围内 + + + + HelpBrowser + + + + Error Loading Help Contents: + 载入帮助内容时发生错误: + + + + Supplied XML file is not a valid Contents document. + XML文件不是有效的文件。 + + + + Search reached end of document + 搜索已到达文件结尾 + + + + Search reached start of document + 搜索已到达文件开头 + + + + Text not found in document + 搜索内容未找到 + + + + Found %1 results + 搜索到%1个结果 + + + + + Search + 搜索 + + + + Home + 主页 + + + + Close + 关闭 + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + 关於 + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + 打开帮助文件出错 + + + + Opening External Link + 打开外部链接 + + + + Unable to Open Link + 不能打开链接 + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + RetroShare不能用缺省浏览器打开链接。如果你的浏览器没有配置为使用Tor,你的请求将无法使用匿名模式。 + + + + Do you want Retroshare to open the link in your Web browser? + 你想让Retroshare用默认浏览器打开链接吗? + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + RetroShare不能用缺省浏览器打开链接。你可以复制网址到你的浏览器中去。 + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + + + + + + Copy + 复制 + + + + Remove + 移除 + + + + Mark all + + + + + Delete + 删除 + + + + Clear history + + + + + Send + 发送 + + + + InfoDialog + + + Info + 信息 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + Add a new Friend + 添加一个新好友 + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &You get a certificate file from your friend + + + + + &Make friend with selected friends of my friends + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + This wizard will help you to connect your friend to RetroShare network. There are two possible ways to do this: + 本向导将帮你与你的好友使用RetroShare网络。按照以下两个方法来做。 + + + + &Enter the certificate manually + (&E)手工输入证书 + + + &Use *.pqi files with certificates + (&U)使用 *.pqi 证书文件 + + + + LinksDialog + + + Share Link Anonymously + 匿名分享链接 + + + + Vote on Link + 投票链接 + + + + Download + + + + + Expand + + + + + Hide + 隐藏 + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + From + 发送方 + + + + Show + 显示 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + All Peers + + + + + Own Links + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + MainWindow + + + Network + 网络 + + + + Friends + 聊天好友 + + + + + Transfers + 文件 + + + + + Messages + 电子邮件 + + + + + Channels + 频道 + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Status + 状态 + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + You have %1 new message + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + Internal Error + 内部错误 + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + Online + 在线 + + + + + Options + 选项 + + + + Hide + 隐藏 + + + + Show + 显示 + + + + RetroShare + Retroshare + + + Invite Friend + 邀请好友 + + + + MainWindow + + + + + Add Friend + 添加好友 + + + + Add a Friend Wizard + 连接好友向导 + + + + Add Share + 添加共享 + + + + + Quick Start Wizard + 快速启动向导 + + + + Search + 搜索 + + + + Files + 文案 + + + Add Shared Directory + 添加共享目录 + + + + Show/Hide + 显示/隐藏 + + + + &Quit + (&Q)退出 + + + You has a new message + 你有新邮件 + + + + Bandwidth Graph + 带宽图 + + + + Open Messenger + 打开信使 + + + + Minimize + 最小化 + + + + Maximize + 最大化 + + + + Links Cloud + 链接 + + + + RetroShare %1 a secure decentralised communication platform + + + + + Blogs + 博客 + + + + Unfinished + 未完成 + + + + Help + 幇助 + + + + About + 关於 + + + News Feed + 新闻提供 + + + + + Forums + 论坛 + + + + Open Messages + 打开信使 + + + + Applications + 程序 + + + Settings + 设置 + + + RetroShare %1 a secure decentralised commmunication platform + RetroShare %1 一个安全分散的通信平台 + + + + Plugins + 插件 + + + + Really quit ? + 真要退出吗? + + + + Do you really want to exit RetroShare ? + 你真的要退出RetroShare? + + + + Quit + 退出 + + + Color + 颜色 + + + + SMPlayer + + + + + Messenger + 信使 + + + + MessageComposer + + + + Compose + 谱写了信息渠道 + + + + + Contacts + + + + + Search for Name: + + + + + Reset + + + + + Send To: + 发送给: + + + + Subject: + 题目: + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + 大胆 + + + + Underline + 强调 + + + + Italic + 斜体 + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + 推荐档案 + + + + File Name + + + + + Size + + + + Sources + 来源 + + + + Hash + + + + + Send + 发送 + + + + Send this message now + 立刻发送信息 + + + + Reply + 回复 + + + + Toggle Contacts View + 切换联系人视图 + + + + Save + + + + + Save this message + 保存信息 + + + + Attach + + + + + Attach File + 附加文件 + + + + Quote + + + + + Add Blockquote + + + + + &Left + (&L)左 + + + + C&enter + (&E)中心 + + + + &Right + (&R)右 + + + + &Justify + (&J)两端对齐 + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + 保存信息 + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + Compose: + 谱写了信息渠道 + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + 节点详细信息 + + + + Re: + + + + + Fwd: + + + + + + RetroShare + Retroshare + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + 未知 + + + + Unknown friend + + + + + &File + (&F)文件 + + + + &New + (&N)新建 + + + + &Open... + (&O)打开 + + + + &Save + (&S)保存 + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + (&P)打印 + + + + &Export PDF... + (&E)导出PDF + + + + &Quit + (&Q)退出 + + + + &Edit + (&E)编辑 + + + + &Undo + (&U)撤销 + + + + &Redo + (&R)重做 + + + + Cu&t + (&T)剪切 + + + + &Copy + (&C)复制 + + + + &Paste + (&P)粘贴 + + + + &View + (&V)查看 + + + + &Contacts Sidebar + (&C)联系人栏 + + + + &Insert + (&I)插入 + + + + &Image + (&I)图片 + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + 打开文件 + + + + + HTML-Files (*.htm *.html);;All Files (*) + 网页 (*.htm *.html);;所有文件 (*) + + + + Save as... + 另存为 + + + + Print Document + 打印文档 + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + 信息还没有发送。你要保存吗? + + + + Choose Image + 选择图片 + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + 支持的图片格式(*.png *.jpeg *jpg *gif) + + + + Add Extra File + 添加附件 + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + 添加 + + + + Edit + + + + + Delete + 删除 + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + message + 电文 + + + New Message + 新讯息 + + + + Subject + 题目 + + + + <b>1 new Message from</b> + + + + + Close + 关闭 + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">推荐档案</span></p></body></html> + + + + Download all Recommended Files + + + + + Subject: + 题目: + + + + From: + 发送方: + + + + To: + 至: + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + + + + + Size + + + + + Hash + + + + + Print + 打印 + + + + Print Preview + 打印预览 + + + + No subject + + + + + Download + + + + + Download all + + + + + Hide + 隐藏 + + + + Expand + + + + + File + + + + + Files + 文案 + + + + Print Document + 打印文档 + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + 网页 (*.htm *.html);;所有文件 (*) + + + + MessageWindow + + + New Message + 新讯息 + + + + Compose + 谱写了信息渠道 + + + + Reply to selected message + + + + + Reply + 回复 + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + 转寄 + + + + Remove selected message + + + + + Delete + 删除 + + + + Print selected message + + + + + + Print + 打印 + + + + Display + 显示 + + + + + + Tags + + + + + Print Preview + 打印预览 + + + + + Buttons Icon Only + 按钮图标只 + + + + Buttons Text Beside Icon + 按钮的文本旁边图标 + + + + Buttons with Text + 按钮与文本 + + + + Buttons Text Under Icon + 按钮的文字在图标 + + + + Set Text Under Icon + 设置下的文本,图标 + + + + &File + (&F)文件 + + + + Save &As File + + + + + &Print... + (&P)打印 + + + + Print Preview... + + + + + &Quit + (&Q)退出 + + + + MessagesDialog + + + + New Message + 新讯息 + + + + Quick View + + + + + Reply to Message + 回覆讯息 + + + + Remove Message + 清除讯息 + + + + + Date + 日期 + + + + + + From + + + + + Remove selected message + + + + Size + 大小 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">推荐档案</span></p></body></html> + + + + Compose + 谱写了信息渠道 + + + + Reply to selected message + + + + + Reply + 回复 + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + 转寄 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">remove selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">删除选中邮件</p></body></html> + + + + Delete + 删除 + + + + Print selected message + + + + + Display + 显示 + + + + Reset + 重设 + + + + Attachments + 附件 + + + + + Content + + + + + + + + + Tags + + + + + + + + Inbox + 收件箱 + + + + + + + Outbox + 发件箱 + + + + Draft + 草稿 + + + + + Sent + 发送电子邮件 + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + 打印 + + + + Print Preview + 打印预览 + + + + + Buttons Icon Only + 按钮图标只 + + + + Buttons Text Beside Icon + 按钮的文本旁边图标 + + + + Buttons with Text + 按钮与文本 + + + + Buttons Text Under Icon + 按钮的文字在图标 + + + + Set Text Under Icon + 设置下的文本,图标 + + + + Save As... + 另存为 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">reply to selected message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">回覆选定消息</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">New Message</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">新邮件 </p></body></html> + + + Download All + 下载所有 + + + Print Document + 打印文档 + + + File Name + 文案名称 + + + Sources + 来源 + + + + Forward selected Message + 转发选择讯息 + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Messages + 移除讯息 + + + + Forward Message + 转发讯息 + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Mark as read + + + + + Mark as unread + + + + + Undelete + + + + Download + 下载 + + + + Empty trash + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + Click to sort by to + + + + Files + 文案 + + + Compose: + 谱写了信息渠道 + + + Hide + 隐藏 + + + + + + Drafts + + + + + To + + + + Anonymous + 匿名 + + + Save as... + 另存为 + + + HTML-Files (*.htm *.html);;All Files (*) + 网页 (*.htm *.html);;所有文件 (*) + + + + + + + + Total: + + + + Replay to All + 全部回复 + + + + + Reply to All + 全部回复 + + + + + Subject + 题目 + + + Subject: + 题目: + + + From: + 发送方: + + + Date: + 日期: + + + To: + 至: + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download all Recommended Files</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">推荐下载所有文件</p></body></html> + + + + Print + 打印 + + + + MessagesPopupDialog + + New Message + 新讯息 + + + Remove Messages + 移除讯息 + + + Reply to Message + 回覆讯息 + + + Forward Message + 转发讯息 + + + Remove Message + 清除讯息 + + + Download All + 下载所有 + + + Print Document + 打印文档 + + + Messages + 电子邮件 + + + Inbox + 收件箱 + + + Outbox + 发件箱 + + + Draft + 草稿 + + + Sent + 发送电子邮件 + + + Date + 日期 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">推荐档案</span></p></body></html> + + + File Name + 文案名称 + + + Size + 大小 + + + Compose + 谱写了信息渠道 + + + Remove + 移除 + + + Reply + 回复 + + + Print + 打印 + + + PrintPreview + 打印预览 + + + + MessengerWindow + + + Expand all + 全部展开 + + + + Collapse all + 折叠全部 + + + + Chat + 聊天 + + + + Message Friend + 讯息好友 + + + + Connect To Friend + 连接到好友 + + + + Peer Details + 结点详细信息 + + + + Recomend this Friend to... + + + + + Paste RetroShare Link + + + + Paste retroshare Link + 粘贴retroshare链接 + + + + Export Friend + 导出好友 + + + + Deny Friend + 拒绝好友 + + + + Remove Friend Location + 删除好友位置 + + + + <strong>GPG Key</strong> + <strong>GPG 钥匙</strong> + + + + + + + location + + + + + <strong>RetroShare instance</strong> + <strong>RetroShare 实例</strong> + + + location : + 位置: + + + Peer Online + 同行在線 + + + Available + 选择不同 + + + Offline + 离线 + + + + Save Certificate + 保存证书 + + + + Certificates (*.pqi) + 证书 (*.pqi) + + + Friend Not Online + 好友不在线 + + + Your Friend is offline +Do you want to send them a Message instead + 您的朋友离线 +是否要发送信息给他们,而不是 + + + View + 查看 + + + Send Message + 发送讯息 + + + Remove Friend + 删除好友 + + + + Click to Change your Avatar + + + + Online + 在线 + + + + Search Friends + + + + + Reset + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + 隐藏离线好友 + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgFeed + + Inbox + 收件箱 + + + Outbox + 发件箱 + + + Sent + 发送电子邮件 + + + Date + 日期 + + + All + 全部 + + + Subject + 题目 + + + + MsgItem + + + Reply to Message + 回覆讯息 + + + + Remove Item + + + + + + Expand + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + 隐藏 + + + + NATStatus + + + <strong>NAT:</strong> + + + + + OK | RetroShare Server + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + UPNP is active. + UPNP已经激活 + + + UPNP NOT FOUND. + UPNP没有发现 + + + Stable External IP Address + 稳定的外部IP地址 + + + Not Found External Address + 没有发现外部地址 + + + UDP Port is reachable + UDP端口可以访问 + + + UDP Port is not reachable + UDP端口不可以访问 + + + TCP Port is reachable + TCP端口可以访问 + + + TCP Port is not reachable + TCP端口不可以访问 + + + RetroShare Server + RetroShare服务器 + + + UDP Server + UDP服务器 + + + Net Limited + 网络受限 + + + No Conectivity + 没有连接 + + + + NetworkDialog + + Load Certificate + 加载证书 + + + + Authentication matrix + + + + RetroShare %1 started. + RetroShare %1已经启动 + + + + Export my Cert + + + + Select a pem/pqi File + 选择一个文件 PEM/PQI + + + File Not Found + 未找到文件 + + + %1 does not exist. Would you like to create it? + %1 不存在. 你想创建它吗? + + + Failed to Create File + 创建文件失败 + + + Unable to create %1 [%2] + 无法创建 %1 [%2] + + + Authenticated + 身份验证 + + + GPG key signed + GPG密钥签署 + + + Not Authenticated + 未通过身份验证 + + + GPG key not signed + GPG密钥没有签名 + + + + Copy RetroShare Link + + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + 我已经验证 + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + 已验证你。 +右键单击并选择'交友'能够连接。 + + + + yourself + + + + Select Certificate + 选择证书 + + + Certificates (*.pqi *.pem) + 证书 (*.pqi *.pem) + + + Please choose a filename + 请选择一个文件名 + + + Certificate file successfully created + 证书创建成功 + + + Sorry, certificate file creation failed + 抱歉,证书创建失败 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Network:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">网络:</span></p></body></html> + + + Accept + 接受 + + + Trust + 信託 + + + Last Contact + 最后一次联系 + + + + + + Name + 姓名 + + + Peer Address + 结点地址 + + + Organisation + 组织 + + + Location + 位置 + + + Country + 国别 + + + + + Cert Id + 证书编号 + + + RetroShare %1 started. + e.g: RetroShare v0.x started. + RetroShare %1已经启动 + + + Welcome to RetroShare. + 欢迎使用RetroShare。 + + + + Network + 网络 + + + is trusting you. +Right-click and select 'make friend' to be able to connect. + 信任你。点击右键选择“成为好友”,就可以联系。 + + + Trust matrix + 信任矩阵 + + + View + 查看 + + + + Deny friend + 拒绝好友 + + + Accept friend + 接受好友 + + + + Make friend + 成为好友 + + + + Delete certificate + 删除证书 + + + + Peer details... + 节点详细资料 + + + Trusted + 信任的 + + + Denied + 拒绝的 + + + Is trusting me + 信任我 + + + + Unknown + 未知 + + + Never seen + 从未见过 + + + UPNP is active. + UpNP是活动的 + + + UPNP NOT FOUND. + 没有发现UPNP + + + DHT is not working (down). + DHT没有工作。 + + + Stable External IP Address + 固定的外部IP地址 + + + Not Found External Address + 没有发现外部地址 + + + UDP Port is reachable + UDP端口可以访问 + + + UDP Port is not reachable + UDP端口不可以访问 + + + TCP Port is reachable + TCP端口可以访问 + + + TCP Port is not reachable + TCP端口不可以访问 + + + RetroShare Server + RetroShare服务器 + + + UDP Server + UDP服务器 + + + Net Limited + 网络受限 + + + No Conectivity + 没有链接 + + + + Network View + 网络查看 + + + + Network Status + 网络状态 + + + + + Did I authenticated peer + 难道我同行验证 + + + + Did I sign his gpg key + 难道我签下自己的GPG密钥 + + + + + Did peer authenticated me + 我没有同行验证 + + + + Search Network + + + + + Clear Filter + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Show keys that are not validated by the GPG web of trust + 显示密钥不被验证 GPG web of trust + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + Local network + 本地网络 + + + + UPnP + + + + + External ip address finder + 外部IP地址搜索器 + + + + Clear + 清楚的 + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + 添加好友 + + + + Copy My Key to Clipboard + 我的钥匙复制到剪贴板 + + + + Export My Key + + + + + Create New Profile + + + + + Create a new Profile + + + + + NetworkPage + + Rate Options + 速度选项 + + + Max Total Data Rate (KB/S): + 你的最大上传速度 (KB/S): + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rate per Person (KB/S):</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">速每人 (KB/S):</p></body></html> + + + + NetworkView + + Hide Settings + 隐藏设置 + + + Show Settings + 显示设置 + + + Settings + 设置 + + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + 名字 + + + + Choose color + + + + + OK + 确定 + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + 清除所有 + + + + Options + 选项 + + + + NotifyPage + + + News Feed + 新闻提供 + + + + Peers + 节点 + + + + Channels + 频道 + + + + Forums + 论坛 + + + + Chat + + + + + Blogs + 博客 + + + + Messages + 电子邮件 + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + 信息 + + + + Channel Post + + + + + Forum Post + 论坛发表 + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + 新讯息 + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + GPG密钥密码 + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + Please enter the password to unlock the following GPG key: + + 请输入密码来解锁以下GPG密钥: + + + + OnlineToaster + + Peer Online + 同行在線 + + + + Friend Online + + + + + PeerDefs + + Anonymous + 匿名 + + + + + Unknown + 未知 + + + + PeerItem + + Make Friend + 成爲好友 + + + Remove Friend + 删除好友 + + + + Chat + 聊天 + + + + Start Chat + + + + Organisation + 组织 + + + + Location + 位置 + + + Country + 国别 + + + + Remove Item + + + + + + Expand + + + + + Write a quick Message + + + + + Send + 发送 + + + + Cancel + + + + + Peer ID: + + + + + Write Message + + + + + Status: + 状态: + + + + Trust: + + + + + Name: + 名字 + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + 节点 + + + + + + + + + + + + Unknown Peer + + + + + Hide + 隐藏 + + + + Quick Message + + + + + PeerStatus + + Online: 0 | Friends: 0 | Network: 0 + 在线: ) | 好友: 0 | 网络: 0 + + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + + + + Online + 在线 + + + Online: + 在线: ) + + + Friends: + 好友: + + + Network: + 网络: + + + + PeersDialog + + Chat + 聊天 + + + Export Friend + 导出好友 + + + Remove Friend + 删除好友 + + + Save Certificate + 保存证书 + + + Certificates (*.pqi) + 证书 (*.pqi) + + + Status + 状态 + + + Person + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">好友</span></p></body></html> + + + Connect To Friend + 连接到好友 + + + Welcome to RetroShare's group chat. + 欢迎来到RetroShare组聊天。 + + + Profile + 外形 + + + Friends Storm + 活动 + + + Paste retroshare Link + 粘贴retroshare链接 + + + <strong>Group</strong> + <strong>集团</strong> + + + <strong>Friend</strong> + <strong>朋友</strong> + + + Message group + 消息组 + + + Edit group + 编辑组 + + + Remove group + 删除组 + + + Friend Details + 节点详细信息 + + + Recommend this Friend to... + 这位朋友推荐给... + + + Add to group + 添加到组 + + + Move to group + 移动到组 + + + Groups + 团体 + + + Remove from group + 从组中删除 + + + Remove from all groups + 从所有组中删除 + + + Expand all + 全部展开 + + + Collapse all + 折叠全部 + + + Message Friend + 讯息好友 + + + Peer Details + 结点详细信息 + + + Deny Friend + 拒绝好友 + + + Remove Friend Location + 删除好友位置 + + + <strong>GPG Key</strong> + <strong>GPG 钥匙</strong> + + + <strong>RetroShare instance</strong> + <strong>RetroShare 实例</strong> + + + me + + + + location : + 位置: + + + Online + 在线 + + + Peer Online + 同行在線 + + + Available + 选择不同 + + + Offline + 离线 + + + Friend Not Online + 好友不在线 + + + Your Friend is offline +Do you want to send them a Message instead + 您的朋友离线 +是否要发送信息给他们,而不是 + + + RetroShare + Retroshare + + + Do you want to remove this Friend? + 你要删除这个朋友? + + + is typing... + 正在输入... + + + Create a new Channel + 创建一个新频道 + + + New Channel + 新频道 + + + Add Extra File + 添加附件 + + + News Feed + 新闻提供 + + + Location + 位置 + + + Paste Friend Link + 粘贴友情链接 + + + Save as... + 另存为... + + + Send + 发送 + + + Profile View + 简介检视 + + + Italic + 斜体 + + + Underline + 强调 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">朋友们</span></p></body></html> + + + Add + 添加 + + + hide unconnected + 隐藏无关 + + + Add or Change your Avatar + 添加或更改您的头像 + + + Edit Personal message + 修改个人信息 + + + Live Chat + 在线聊天 + + + Bold + 大胆 + + + Add Friend + 添加好友 + + + Create new Profile + 创建新用户资料 + + + Create New Forum + 创建新论坛 + + + Create new Forum + 创建新论坛 + + + Create New Channel + 创建一个新频道 + + + Display + 显示 + + + Create new Channel + 创建一个新频道 + + + Add your Avatar Picture + 添加您的头像照片 + + + Set your Personal Message + 设置您的个人信息 + + + Edit your status Message + 编辑您的状态讯息 + + + Browse Message History + 浏览消息历史记录 + + + Browse History + 浏览历史 + + + Add a new Group + 添加一个新的组 + + + Disable Emoticons + 禁用表情 + + + Save Chat History + 保存聊天记录 + + + Hide Offline Friends + 隐藏离线好友 + + + Hide Status Column + 隐藏状态栏 + + + Font + 字体 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Display</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">显示</span></p></body></html> + + + Friends + 聊天好友 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">set Text Color</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">设置文字颜色</span></p></body></html> + + + Attach File + 附加文件 + + + Clear Chat History + 清除聊天记录 + + + + PeersFeed + + Save Certificate + 保存证书 + + + Certificates (*.pqi) + 证书 (*.pqi) + + + Friends + 聊天好友 + + + + PhotoDialog + + + Insert Show Lists + 插入查看列表 + + + + Open + + + + + Remove + 移除 + + + + Excellent + + + + + Good + + + + + Average + 平均 + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + 评级 + + + + + Date + 日期 + + + + + Location + 位置 + + + + Size + 大小 + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + 节点 + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + 描述 + + + + PhotoShow + + + Date: + 日期: + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + 暂停 + + + + Forward + + + + + PluginFrame + + + Remove + 移除 + + + + PluginManagerWidget + + + Install New Plugin... + 安装新插件 + + + + Open Plugin to install + 打开插件安装 + + + + Plugins (*.so *.dll) + 插件 (*.so *.dll) + + + + PopularityDefs + + + Popularity + 流行度 + + + + PopupChatDialog + + Paste retroshare Link + 粘贴retroshare链接 + + + Friend Not Online + 好友不在线 + + + + Your Friend is offline +Do you want to send them a Message instead + 您的朋友离线 +是否要发送信息给他们,而不是 + + + Chatting with + 聊天 + + + + is typing... + 正在输入... + + + + Hide Avatar + 隐藏头像 + + + + Show Avatar + 显示头像 + + + Open Style + 打开样式 + + + Styles (*.htm) + 样式 (*.htm) + + + RetroShare + Retroshare + + + + Friend not Online + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Add Extra File + 添加附件 + + + + Load Picture File + + + + + Save as... + 另存为 + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + Messages you send will be delivered after Friend is again Online + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + Send + 发送 + + + RetroShare - Encrypted Chat + RetroShare - 安全聊天 + + + + Close + 关闭 + + + + + Bold + 大胆 + + + + + Underline + 强调 + + + + + Italic + 斜体 + + + + Text Color + + + + + Clear Chat History + 清除聊天记录 + + + + Browse Message History + 浏览消息历史记录 + + + + Browse History + 浏览历史 + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Add a File for your Friend + 添加您的朋友一文件 + + + + Font + 字体 + + + + Strike + + + + Clear Chat + 清除聊天记录 + + + + Disable Emoticons + 禁用表情 + + + + + Save Chat History + 保存聊天记录 + + + + Clear offline messages + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + Retroshare + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PrintPreview + + + RetroShare Message - Print Preview + RetroShare 信息 - 打印预览 + + + + Print + 打印 + + + + &Print... + (&P)打印 + + + + Page Setup... + 打印设置 + + + + Zoom In + 放大 + + + + Zoom Out + 缩小 + + + + &Close + (&C)关闭 + + + + ProfileEdit + + + Remove Profile Entry + 移除简介条目 + + + + Move Profile Entry Up + 向上移动简介条目 + + + + Move Profile Entry Down + 向下移动简介条目 + + + + Profile Edit + 资料编辑 + + + + Profile + 外形 + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + 清除照片 + + + + Change Photo + 更改照片 + + + + + Edit Profile + 编辑简介 + + + + Remove Favourite + 移除喜爱的 + + + + Clear Favourites + 清除喜爱的 + + + + Download File + 下载文件 + + + + Download All + 下载所有 (Download All) + + + + RetroShare + Retroshare + + + + Error : cannot get peer details. + + + + + + Name + 姓名 + + + + Peer ID + + + + + Size + 大小 + + + + Profile View + 简介检视 + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + 修改个人信息 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">公共信息</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">公共信息</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">名称:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">位置:</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">同行 ID</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">其它信息</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">朋友数:</span></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">版本</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">我的地址</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">本地地址:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">外部地址:</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + Addresses list + 地址列表 + + + + QObject + + Name + 姓名 + + + Path + 路径 + + + Extension + 扩展名 + + + Date + 日期 + + + Size + 大小 + + + Popularity + 流行度 + + + contains + 包含 + + + contains all + 包含所有 + + + less than + 小于 + + + less than or equal + 小于或等于 + + + greater than or equal + 大于或等于 + + + greater than + 大于 + + + is in range + 在范围内 + + + and + + + + and / or + 与 / 或 + + + or + + + + equals + 等于 + + + + + RetroShare + Retroshare + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + 登录失败 + + + + Maybe password is wrong + 密码错误 + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + 拒绝好友 + + + + Make friend + 成为好友 + + + + Peer details + 节点详细信息 + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + 快速启动向导 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + + + Next > + 下一个 > + + + + + + + Exit + 退出 + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + 选择你的上传速度的限制: + + + + + KB/s + + + + + Choose your download speed limit: + 选择你的下载速度的限制: + + + + Connection : + 连接: + + + + Automatic (UPnP) + 自动 (UPnP) + + + + Firewalled + 防火墙 + + + + Manually forwarded port + 手动转发端口 + + + Dicovery : + 发现: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + Discovery : + 发现: + + + Share Ip and information with your friend (Disc On) + 共享知识产权,并与您的朋友(愉在信息) + + + Don't share any information (Disc Off) + 不共享任何信息(愉关闭) + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + < 后面 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">这是一个共享文件夹列表 . 您可以添加和删除文件夹使用左方的按钮。当您添加新的文件夹,开始在该文件夹的所有文件的共享。</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">可以单独设置每个共享目录共享标志:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">可浏览朋友</span><span style=" font-family:'Sans'; font-size:8pt;">: 可浏览的文件直接从你的朋友。</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">匿名共享</span><span style=" font-family:'Sans'; font-size:8pt;">: 文件可以下载任何人通过匿名隧道。</span></p></body></html> + + + + Directory + + + + + Network Wide + 整个网络 + + + + Browseable + 可浏览 + + + + Add + 添加 + + + + Remove + 移除 + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">喜欢使用RetroShare!</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">只要再一个步骤!您快完成配置RetroShare工作与您的计算机。</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">这些设置配置如何以及何时RetroShare启动。</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + Do not show a message when Closing RetroShare + 不显示消息时关闭RetroShare + + + + Start Minimized + 最小化启动 + + + + Start RetroShare when my System Starts. + 当我开始RetroShare系统启动。 + + + + Start minimized on system start + + + + + Finish + 完成 + + + + Select A Folder To Share + 选择一个文件夹共享 + + + + Shared Directory Added! + 分享目录已经添加! + + + + Do you really want to stop sharing this directory ? + 你真的要停止共享此目录? + + + + Warning! + 注意! + + + + RSettingsWin + + + General + 一般 + + + + Directories + 目录 + + + + Server + 服务器 + + + + Transfer + 文件 + + + + Notify + 通告 + + + + Security + 安全 + + + + Message + 信息 + + + + Forum + 论坛 + + + + Chat + + + + + Appearance + 外观 + + + File Associations + 文件关联 + + + + Sound + 声音 + + + + UnknownPage + 未知页 + + + + Error Saving Configuration on page + + + + Error Saving Configuration + 保存配置出错 + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + <strong>下载:</strong> 0.00 (kB/s) | <strong>上传:</strong> 0.00 (kB/s) + + + + <strong>Down:</strong> + <strong>下载:</strong> + + + + <strong>Up:</strong> + <strong>上传:</strong> + + + Down: + 下载: + + + Up: + 上传: + + + + RemoteDirModel + + Friends Directories + 好友目录 + + + My Directories + 我的目录 + + + Size + 大小 + + + Share Type + 共享型 + + + What's new + 最新消息 + + + Rank + 排名 + + + Age + 年龄 + + + FILE + 文件 + + + Anonymous + 匿名 + + + Files + 文案 + + + DIR + 目录 + + + + RetroshareDirModel + + + Anonymous + 匿名 + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Invalid language code specified: + 无效的语言代码指定: + + + + Invalid GUI style specified: + 无效样式指定: + + + + Resets ALL stored RetroShare settings. + 重设所有保存的RetroShare设置。 + + + + Sets the directory RetroShare uses for data files. + 设置用于数据文件的目录RetroShare。 + + + + Sets the name and location of RetroShare's logfile. + 设置RetroShare日志文件的名字和保存位置。 + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + 设置RetroShare的界面样式。 + + + + Sets RetroShare's interface stylesheets. + 设置RetroShare的界面样式表。 + + + + Sets RetroShare's language. + 设置RetroShare语言 + + + + RetroShare Usage Information + RetroShare实用信息 + + + + Invalid log level specified: + 指定日志级别无效: + + + + Unable to open log file '%1': %2 + 不能打开日志文件 "%1':%2 + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + Sources + 来源 + + + + Results + 结果 + + + + Directory + 目录 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enter a Keyword here</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">在这里输入关键字</p></body></html> + + + + Reset + 重设 + + + + Start Search + 开始搜索 + + + + Search + 搜索 + + + + Advanced Search + 高级搜索 + + + + Advanced + 高级 + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + + + + + File Size + + + + + Age + 年龄 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Close all Search Resullts</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">關閉所有搜索結果</span></p></body></html> + + + Clear all Search Results + 關閉所有搜索結果 + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Download Selected</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">欢迎下载选择 </span></p></body></html> + + + + Close all Search Resullts + + + + + Download Selected + + + + + + Download + 下载 + + + + Include files from your own file list in the search result + 您在搜索结果中的文件列表包含文件 + + + + Include own files + 包括自己的文件 + + + + Search inside "browsable" files of your friends + 搜索内部“可浏览”您的朋友文件 + + + + Search in friends lists + 在朋友搜索列表 + + + + Multi-hop search at distance 6 in the network +(always reports available files) + 多跳的距离在网络中搜索6 +(总是报告中提供的文件) + + + + F2F search + F2F 搜索 + + + + Limit number of results to : + 数量限制的结果: + + + + Enter a keyword here (at least 3 char long) + 在这里输入关键字(至少3个字符长) + + + Copy retroshare Link + 复制retroshare链接 + + + Send retroshare Link + 发送retroshare链接 + + + Broadcast on Channel + 在频道内广播 + + + Recommend to Friends + 推荐给好友 + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Remove + 移除 + + + + Remove All + 清除所有 + + + + + Folder + 目录 + + + + New RetroShare Link(s) + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + + Any + 任何 + + + + Audio + 音频 + + + + Video + 视频 + + + Images + 图片 + + + Programs + 节目 + + + Archives + 文件夹 + + + Documents + 文件 + + + + Download Notice + 下载通告 + + + + Skipping Local Files + 跳过本地文件 + + + + + Sorry + 抱歉 + + + + + This function is not yet implemented. + 这个功能还没有开发实现。 + + + + Size + 大小 + + + + Type + 类型 + + + Toggle advanced searching on and off. + 切换高级搜索开关 + + + <h3>Simple Search:</h3> + <h3>简单搜索:</h3> + + + Keywords + 关键字 + + + + Archive + 存档 + + + + CD-Image + CD镜像 + + + + Document + 文档 + + + + Picture + 图片 + + + + Program + 程序 + + + Perform simple search + 执行简单搜索 + + + <h3>Advanced Search:</h3> + <h3>高级搜索:</h3> + + + Show Advanced Search Tool + 显示高级搜索工具 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reset Search Keyword and File Type</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">重置搜索關鍵字和文件類型</p></body></html> + + + + Filename + 文件名 + + + + Hash + + + + + KeyWords + 关键字 + + + + Enter a Keyword here + + + + + Search Id + 搜索 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download Select</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Download Select</p></body></html> + + + + Close All Search Results + 關閉所有搜索結果 + + + + SendLinkDialog + + Send + 发送 + + + + ServerPage + + Change + Restart Server + 改变+重綮动 + + + Server Settings + 服务器设置 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">External Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">外部地址:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lokal Adress:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">本地地址:</p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Port:</p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IP-Port (IP的端口/ 港口):</p></body></html> + + + + + Port: + IP-Port (IP的端口): + + + Misc + Misc + + + behinde Firewall + 防火墙 + + + Forwarded External Port + 转发外部端口 + + + + Transfer Rates + 传输速度 + + + + Firewalled + 防火墙 + + + + + Network Configuration + + + + + Automatic (Upnp) + + + + + Manual Forwarded Port + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Download (KB/s) + 下载(KB /s) + + + + + kB/s + + + + + Upload (KB/s) + 上传(KB /s) + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + 允许隧道连接 + + + + Local Address + 本地地址 + + + + External Address + 외부 주소 + + + + Dynamic DNS + + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + + Settings + + Settings + 设置 + + + + Options + 选项 + + + + Transfer + 文件 + + + + Notify + 通告 + + + + Security + 安全 + + + + Message + 信息 + + + + Forum + 论坛 + + + + Chat + + + + + Appearance + 外观 + + + + Sound + 声音 + + + + Cancel + 取消 + + + Apply + 应用 + + + + OK + 确定 + + + + General + 一般 + + + Network + 网络 + + + + Server + 服务器 + + + + Directories + 目录 + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + 浏览 + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + 可浏览 + + + + Anonymous shared Network Wide + + + + + Network Wide + 整个网络 + + + Anonymous + 匿名 + + + + Browseable by Friends + + + + Friends + 聊天好友 + + + + OK + 确定 + + + + Cancel + + + + + Select A Folder To Share + 选择一个文件夹共享 + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + Retroshare + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + 添加分享目录 + + + + Stop sharing selected Directory + + + + Select A Folder To Share + 选择一个文件夹共享 + + + Do you really want to stop sharing this directory ? + 你真的要停止共享此目录? + + + Remove selected Shared Directory + 移除选定的分享目录 + + + + + Remove + 移除 + + + Add Shared Directory + 添加分享目录 + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + 注意! + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + Shared Directory Added! + 分享目录已经添加! + + + Do You Want to Remove ? + 你真想移除吗? + + + + RetroShare Share Manager + RetroShare分享管理 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#32cd32;">Share Manager</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"><span style=" font-size:10pt;">Add a new Folder to Share with your Friends or remove a Shared Folder.</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600; color:#32cd32;">Share Manager</span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt;"><span style=" font-size:10pt;">添加一個新文件夾來與朋友分享或刪除共享文件夾。</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">共享管理</span></p></body></html> + + + + Shared Folder Manager + 共享文件夾管理器 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + 目录 + + + + Virtual Folder + + + + + Network Wide + 整个网络 + + + + Browsable + 可浏览 + + + + Add + 添加 + + + + Close + 关闭 + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + 下载 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Files</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">档案</span></p></body></html> + + + Add to Recommend List + 添加到推荐列表 + + + Recommend To + 推荐给 + + + Message Friend + 讯息好友 + + + + + Open File + 打开文件 + + + + Open Folder + 打开文件夹 + + + + Set command for opening this file + 设置打开这个文件时使用的命令 + + + + Copy retroshare Link + 复制retroshare链接 + + + + Checking... + 检查... + + + + Check files + 刷新 + + + + Send retroshare Link + 发送retroshare链接 + + + Recommend (Automated message) To + 推荐(自动消息) + + + Recommend in a message to + 推荐的信息 + + + + Copy retroshare Links to Clipboard + 复制retroshare链接到剪贴板 + + + + Copy retroshare Links to Clipboard (HTML) + retroshare链接复制到剪贴板(HTML) + + + + Send retroshare Links + 发送retroshare链接 + + + + Send retroshare Links (HTML) + 发送retroshare链接(HTML) + + + Send retroshare Links to Chat + 发送retroshare链接聊天 + + + + Send retroshare Links to Cloud + 发送retroshare链接云 + + + + Add Links to Cloud + 添加链接云 + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + <strong>My Shared Files</strong> + <strong>我的共享文件</strong> + + + + <strong>Friends Files</strong> + <strong>朋友文件</strong> + + + + <strong>Files</strong> + <strong>文件</strong> + + + Friends Share + 好友分享 + + + My Shared Files + 共享文件 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">文件</span></p></body></html> + + + + Splitted View + 劈裂查看 + + + + Friends Folders + 朋友文件夹 + + + + My Folders + 我的文件夹 + + + + All + 全部 + + + + One day old + 有一天,老 + + + + One Week old + 一周岁 + + + + One month old + 满月 + + + + Search files + + + + + Start Search + 开始搜索 + + + + Reset + + + + + Tree view + + + + + Flat view + + + + + Download selected + 下載選擇 + + + + check files + 刷新 + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + 浏览 + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"><p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">註冊</span></p><p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">Create new Profile...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" text-decoration: underline; color:#0000ff;">创建新文件...</span></a></p></body></html> + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">信息...</span></a></p></body></html> + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + Name - location: + 名称 - 位置: + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:10pt;">You can login with your Default</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">RetroShare profile.</p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">You have a Profile?</p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:10pt;">您可以登錄與您的默認</span></p><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">RetroShare簡介.</p><p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;">您已設定檔?</p></body></html> + + + Generate now a Profile + 現在生成一個配置文件 + + + generate now a profile + 現在生成的配置文件 + + + Name: + 名字 + + + Password: + 密碼: + + + Auto-login + 自動登錄 + + + + Log In + 登錄 + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + 登录失败 + + + + Maybe password is wrong + 密码错误 + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + Create a New Profil + 创建新用户资料 + + + This will generate a new Profile + Are you sure you want to continue + 这将会产生一个新的配置文件 + 您确定要继续 + + + + StatisticDialog + + + Statistics + 统计 (Statistics) + + + + Download + 下载中 + + + + Session: + Session: + + + + + Downloaded: + 下载完成: + + + Average Downloadspeed: + Average Downloadspeed: + + + + + Count of Downloads: + 下载统计: + + + + + + Overall + Overall + + + + Upload + Upload + + + + + + Session + Session + + + + Uploaded: + Uploaded: + + + Average Uploadspeed: + Average Uploadspeed: + + + + + Count of Uploads: + 上载统计: + + + + Uploaded + Uploaded + + + + + + + Connections: + 连接: + + + + + + Peers: + 节点: + + + Misc + Misc + + + + Uptime: + Uptime: + + + Overall: + Overall: + + + + + Uptime + Uptime + + + + Records + Records + + + + Uploadspeed: + 上传速度: + + + + Downloadspeed: + 下载速度: + + + + + Show Settings + 显示设置 + + + + Reset + 重设 + + + + Receive Rate + 接收速度 + + + + Send Rate + 发送速度 + + + + Always On Top + 总在最顶部 + + + + 100 + 100 + + + + % Opaque + % 不透明 + + + + Changes the transparency of the Bandwidth Graph + Changes the transparency of the Bandwidth Graph / 改变透明度的频宽图 + + + + Save + 保存 + + + + Cancel + 取消 + + + + Hide Settings + 隐藏设置 + + + + %1 days + %1天 + + + + Now + + + + + Transfer + 文件 + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Time Statistics + + + + + Since: + 自从: + + + + Cumulative + + + + + StatusDefs + + + + Offline + 离线 + + + + Away + + + + + Busy + + + + + Online + 在线 + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + 选择不同 + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + 状态消息 + + + + Status message + 状态消息 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">个人信息</span></p></body></html> + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">输入您的状态消息</span></p></body></html> + + + + OK + 确定 + + + + Cancel + + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + 毫无 + + + + Solid + + + + + Gradient + + + + + SubDestItem + + Type + 类型 + + + + Delete FeedItem + + + + + SubFileItem + + File Name + 文案名称 + + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + 保存频道文件 + + + + Download + + + + + Play + 播放 + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + 下载文件 + + + + + + Play File + + + + + TBoard + + + Pause + 暂停 + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Text certificate + 文本证书 + + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Please, paste your friends PGP certificate into the box below + + + + + Clean certificate + + + + + RetroShare Invite + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + Retroshare + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + 另存为 + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + Use text representation of the XPGP certificates. + 使用文字描述XPGP证书。 + + + The text below is your XPGP certificate. You have to provide it to your friend + 你需要把你XPGP证书下面的文字提供给你的好友。 + + + + Run Email program + 运行邮件程序 + + + Please, paste your friends XPGP certificate into the box below + 请粘贴你好友的XPGP证书到下面的框中 + + + + Connect Friend Help + 连接好友帮助 + + + You can copy this text and send it to your friend via email, ICQ or some other way + 你可以复制这段文字通过电子邮件、ICQ或其它渠道发送给你的好友。 + + + + Certificate Load Failed + 证书加载失败 + + + + TransferFeed + + None + 毫无 + + + + TransferPage + + Transfer + 文件 + + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + 随机 + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + Cancel + 取消 + + + + Clear Completed + 明确完成 + + + + + Status + 状态 + + + + Completed + 完成 + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Downloads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">下载 (Downloads):</span></p></body></html> + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Uploads:</span></p></body></html> + <html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">上传 (Uploads):</span></p></body></html> + + + + + Name + i.e: file name + 姓名 + + + + + Size + i.e: file size + 大小 + + + Progress + i.e: % downloaded + 进度 + + + + Speed + i.e: Download speed + 速度 + + + + Sources + i.e: Sources + 来源 + + + Remaining + i.e: Estimated Time of Arrival / Time left + 剩余时间 + + + + Core-ID + + + + User Name + i.e: user name + 用户姓名 + + + + Progress + i.e: % uploaded + 进度 + + + + Speed + i.e: upload speed + 速度 + + + + Transferred + 已下载 + + + + Play + 播放 + + + + Move in Queue... + 移动在队列... + + + + Checking... + 检查... + + + + RetroShare + + + + + + + Failed + 失败 + + + + Progress / Availability + i.e: % downloaded + 进度 + + + Speed / Queue priority + 速度/队列优先 + + + + Remaining + 剩余时间 + + + + Download time + i.e: Estimated Time of Arrival / Time left + 下载时间 + + + + Peer + i.e: user name + 节点 + + + + Hash + + + + + Router Statistics + + + + + Router Requests + + + + + Pause + 暂停 + + + + Resume + 简历 + + + + Force Check + + + + + Open Folder + 打开文件夹 + + + + Open File + 打开文件 + + + + Preview File + 预览文件 + + + + Details... + 详情 + + + Copy retroshare Link + 复制retroshare链接 + + + Paste retroshare Link + 粘贴retroshare链接 + + + View + 查看 + + + Remove all queued + 删除所有排队 + + + Low + + + + Normal + 普通 + + + High + + + + Auto + 汽车 + + + + + Slower + + + + + + + Average + 平均 + + + + + Faster + 更快 + + + Priority (Queue) + 优先(队列) + + + Priority (Speed) + 优先级(速度) + + + + Streaming + + + + + Random + 随机 + + + + Chunk strategy + 块策略 + + + + + + Okay + 确定 + + + + + Waiting + 轮候 + + + + Downloading + 下载 + + + + + + + Complete + 完成 + + + + Unknown + 未知 + + + + version: + 版本: + + + + Queued + 排队 + + + + Speed / Queue position + 速度/队列位置 + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + Down + 向下 + + + + Up + 向上 + + + + Top + 顶部 + + + + Bottom + 底部 + + + + Priority (Speed)... + 优先级(速度)... + + + + Paused + 已暂停 + + + + Transferring + 转移 + + + + Uploading + 上传 + + + + Are you sure that you want to cancel and delete these files? + 您确定要取消,并删除这些文件? + + + + Details: + 详情: + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + 开放式传输 + + + + File %1 is not completed. If it is a media file, try to preview it. + 文件 %1 没有完成。如果它是一个媒体文件,尝试预览。 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">下载:</span></p></body></html> + + + + Show cache transfers + + + + + Uploads + 上传 + + + + Selected transfer + 选择转移 + + + + Done + 完成 + + + + Active + 主动 + + + + Outstanding + 杰出 + + + Tunneling + 隧道 + + + + TreeStyle_RDM + + + + FILE + 文件 + + + + Files + 文案 + + + + File + + + + + + DIR + 目录 + + + + Friends Directories + 好友目录 + + + + My Directories + 我的目录 + + + + Size + + + + + Age + 年龄 + + + + Friend + + + + + Share Type + 共享型 + + + + What's new + 最新消息 + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + 信託 + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + 전체 + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + 确定 + + + + Cancel + 取消 + + + + Yes + + + + + No + + + + + Help + 幇助 + + + + Retry + 再试 + + + + Show Log + 显示记录 + + + + Show Settings + 显示设置 + + + + Continue + 继续 + + + + Quit + 退出 + + + + Browse + 浏览 + + + + misc + + + Unknown + Unknown (size) + 未知 + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + 未知 + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + diff --git a/retroshare-gui/src/lang/retroshare_zh_TW.qm b/retroshare-gui/src/lang/retroshare_zh_TW.qm new file mode 100644 index 000000000..be651eede --- /dev/null +++ b/retroshare-gui/src/lang/retroshare_zh_TW.qm @@ -0,0 +1 @@ + + + + + AboutDialog + + + About RetroShare + + + + + About + + + + + close + + + + + + About RetroShare %1 + + + + + Max score: %1 + + + + + Score: %1 + + + + + Level: %1 + + + + + Have fun ;-) + + + + + AddFileAssociationDialog + + + File type(extension): + + + + + Use default command + + + + + Command + + + + + RetroShare + + + + + Sorry, can't determine system default command for this file + + + + + + AddLinksDialog + + + + Add Link + + + + + Add a new Link + + + + + Title: + + + + + Url: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Add Anonymous Link + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:18pt; font-weight:600; color:#ffffff;">Add Link to Cloud</span></p></body></html> + + + + + Cancel + + + + + Add Link Failure + + + + + Missing Link and/or Title + + + + + AdvancedSearchDialog + + + Add a further search criterion. + + + + + Reset the search criteria. + + + + + RetroShare: Advanced Search + + + + + Cancels the search. + + + + + Cancel + + + + + Perform the advanced search. + + + + + Search + + + + + Search Criteria + + + + + AppearancePage + + + Language + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose the language used in RetroShare</p></body></html> + + + + + <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Arial; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Changes to language will only take effect after restarting RetroShare!</p></body></html> + + + + + Style + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choose RetroShare's interface style</p></body></html> + + + + + Style Sheet + + + + + ApplicationWindow + + + Statistics + + + + + Games Launcher + + + + + Photo View + + + + + Shared Calendars + + + + + Hide + + + + + Show + + + + + + RetroShare + + + + + AttachFileItem + + + Form + + + + + %p Kb + + + + + Cancel Download + + + + + BandwidthGraph + + + Since: + + + + + Hide Settings + + + + + + Show Settings + + + + + RetroShare Bandwidth Usage + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always on Top + + + + + Style + + + + + Changes the transparency of the Bandwidth Graph + + + + + 100 + + + + + % Opaque + + + + + Save + + + + + Cancel + + + + + BlogDetails + + + + Blog Details + + + + + Blog Info + + + + + Blog Name + + + + + Popularity + + + + + Last Post + + + + + Blog ID + + + + + Blog Description + + + + + Cancel + + + + + OK + + + + + Close + + + + + BlogMsgItem + + + Form + + + + + Remove Item + + + + + Expand + + + + + Subject + + + + + Play Media + + + + + BlogNewItem + + + Remove Item + + + + + Subscribe to Blog + + + + + Expand + + + + + Blog Decscription + + + + + BlogsDialog + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Blogs</span></p></body></html> + + + + + Add + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Post To Blog</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'DejaVu Sans'; font-size:14pt; color:#ffffff;">Blog Name</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Unsubcribe To Blog</span></p></body></html> + + + + + Unsubscribe + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Subscribe To Blog</span></p></body></html> + + + + + Subscribe + + + + + + Create New Blog + + + + + Name + + + + + ID + + + + + Own Blogs + + + + + Subscribed Blogs + + + + + Popular Blogs + + + + + Other Blogs + + + + + Post to Blog + + + + + Subscribe to Blog + + + + + Unsubscribe to Blog + + + + + Show Blog Details + + + + + Create a new Blog + + + + + + + + Popularity: %1 +Fetches: %2 +Available: %3 + + + + + BlogsMsgItem + + + Form + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:11pt; font-weight:600; font-style:italic;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#656565;">Blog Subject</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">DateTime</span></p></body></html> + + + + + Unsubscribe From Channel + + + + + Comment + + + + + Remove Item + + + + + + Expand + + + + + Comments here + + + + + Hide + + + + + CalDialog + + + Form + + + + + Local Calendars + + + + + Shared Calendar List + + + + + Share Details + + + + + Name: + + + + + Location: + + + + + ... + + + + + Status: + + + + + Private + + + + + Public + + + + + Allow List: + + + + + <Disabled> + + + + + Add + + + + + Remove + + + + + Peer Calendars + + + + + CertificatePage + + + Certificate files + + + + + Use PGP certificates saved in files. + + + + + You have to generate a file with your certificate and give it to your friend. Also, you can use a file generated before. + + + + + Export my certificate... + + + + + Browse + + + + + Select Certificate + + + + + Please choose a filename + + + + + + + + RetroShare + + + + + Import friend's certificate... + + + + + Drag and Drop your friends's certificate in this Window or specify path in the box below + + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Sorry, create certificate failed + + + + + Certificate file successfully created + + + + + + Sorry, certificate file creation failed + + + + + Certificate Load Failed:something is wrong with %1 + + + + + Certificate Load Failed:can't read from file %1 + + + + + Certificate Load Failed:file %1 not found + + + + + ChanMsgItem + + + Toggle Message Read Status + + + + + New + + + + + Download + + + + + Play + + + + + Remove Item + + + + + + Expand + + + + + Copy RetroShare Link + + + + + Unsubscribe From Channel + + + + + Channel Feed + + + + + Warning! You have less than %1 hours and %2 minute before this file is delted Consider saving it. + + + + + Hide + + + + + ChanNewItem + + + Remove Item + + + + + Subscribe to Channel + + + + + Expand + + + + + Channel Decscription + + + + + Unknown Channel + + + + + New Channel + + + + + Updated Channel + + + + + ChannelDetails + + + + Channel Details + + + + + Channel Info + + + + + Popularity + + + + + Last Post + + + + + Channel Name + + + + + Channel ID + + + + + Channel Description + + + + + Type + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Cancel + + + + + OK + + + + + Close + + + + + ChannelFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:10pt; font-weight:600;">Channels</span></p></body></html> + + + + + Display + + + + + Unsubscribe + + + + + Subscribe To Channel + + + + + Subscribe + + + + + Set all to read + + + + + Enable Auto-download + + + + + Create Channel + + + + + Unsubcribe To Channel + + + + + Own Channels + + + + + Subscribed Channels + + + + + Popular Channels + + + + + Other Channels + + + + + Share Channel + + + + + Copy RetroShare Link + + + + + No Channel Selected + + + + + Disable Auto-Download + + + + + Enable Auto-Download + + + + + + Post to Channel + + + + + Subscribe to Channel + + + + + Unsubscribe to Channel + + + + + Show Channel Details + + + + + Restore Publish Rights for Channel + + + + + Edit Channel Details + + + + + ChatMsgItem + + + Remove Item + + + + + Write a quick Message + + + + + Send Mail + + + + + Write Message + + + + + Send + + + + + Cancel + + + + + + Start Chat + + + + + Quick Message + + + + + ChatPage + + + General + + + + + Chat Settings + + + + + Enable Emoticons Privat Chat + + + + + Chat Font + + + + + Change Chat Font + + + + + Chat Font: + + + + + Enable Private Chat History + + + + + Enable Group Chat History + + + + + Send message with Ctrl+Return + + + + + Chat History + + + + + Load number of messages (0 = off) + + + + + Group Chat + + + + + Private Chat + + + + + Style + + + + + Group chat + + + + + + + Variant + + + + + + + Author: + + + + + + + Description: + + + + + Private chat + + + + + History + + + + + Enable Emoticons Group Chat + + + + + Incoming message in history + + + + + Outgoing message in history + + + + + Incoming message + + + + + Outgoing message + + + + + Outgoing offline message + + + + + ChatStyle + + + Standard style for group chat + + + + + Standard style for private chat + + + + + Standard style for history + + + + + ConclusionPage + + + Make Friend + + + + + Details about your friend : + + + + + Key validity: + + + + + Email: + + + + + Options + + + + + Add friend to group: + + + + + Authenticate friend (Sign GPG Key) + + + + + Add as friend to connect with + + + + + It seems your friend is already registered. Adding it might just set it's ip address. + + + + + Peer details + + + + + Name: + + + + + Loc: + + + + + Signers + + + + + ConfCertDialog + + + Details + + + + + Peer Info + + + + + Name + + + + + Peer ID + + + + + Last Contact + + + + + Version + + + + + Peer Address + + + + + Addresses list + + + + + None + + + + + Marginal + + + + + Full + + + + + Make Friend + + + + + Cancel + + + + + Apply and Close + + + + + + RetroShare + + + + + + Error : cannot get peer details. + + + + + Your key is signed by : + + + + + Peer key is signed by : + + + + + Your trust in this peer is ultimate, it's probably a key you own. + + + + + Your trust in this peer is full. + + + + + Your trust in this peer is marginal. + + + + + Your trust in this peer is none. + + + + + Your trust in this peer is not set. + + + + + Peer has authenticated me as a friend and did sign my GPG key + + + + + Peer has not authenticated me as a friend and did not sign my GPG key + + + + + Signature Failure + + + + + Maybe password is wrong + + + + + Trust + + + + + Deny Friend + + + + + + Sign GPG key + + + + + Friend Details + + + + + Loc + + + + + RetroShare ID + + + + + Status + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port + + + + + Your trust in this peer is: + + + + + GPG Key + + + + + Peer has signed my GPG key + + + + + Show Help for Trust Settings and Signing + + + + + Peer key is signed by : + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a friend's key is a way to express your trust into this friend, to your other friends. Besides, only signed peers will receive information about your other trusted friends.</p> +<p align="justify" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signing a key cannot be undone, so do it wisely.</p></body></html> + + + + + Certificate + + + + + OK + + + + + ConnectFriendWizard + + + Connect Friend Wizard + + + + + CreateBlog + + + Create new Blog + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Blog</span></p></body></html> + + + + + Name + + + + + Description + + + + + Type: + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Blog Logo + + + + + Add Blog Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateBlogMsg + + + New Blog Post + + + + + Blog Post + + + + + Blog Post to: + + + + + Visual Editor + + + + + Blog Message + + + + + Subject : + + + + + Html Editor + + + + + toolBar + + + + + toolBar_2 + + + + + blockquoute + + + + + Increase font Size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Publish + + + + + New + + + + + Code + + + + + splitPost + + + + + Ordered List + + + + + Unordered List + + + + + Clipboard + + + + + Undo + + + + + RetroShare + + + + + Please add a Subject + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As... + + + + + &Print... + + + + + Print Preview... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Insert + + + + + &Image + + + + + F&ormat + + + + + &Bold + + + + + &Italic + + + + + &Underline + + + + + + &Left + + + + + + C&enter + + + + + + &Right + + + + + &Justify + + + + + &Text Color... + + + + + Application + + + + + The document has been modified. +Do you want to save your changes? + + + + + Open File... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + ODF files (*.odt);;HTML-Files (*.htm *.html);;All Files (*) + + + + + Print Document + + + + + Export PDF + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + CreateChannel + + + Create a new Channel + + + + + <span style="font-size:24pt; font-weight:500;color:#32CD32;">New Channel</span> + + + + + Name + + + + + check peers you would like to share private publish key with + + + + + Share Key With + + + + + Contacts: + + + + + Description + + + + + Type: + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Anonymous Messages + + + + + Authenticated Messages + + + + + Key Sharing + + + + + Key recipients can publish to restricted-type channels, and can view and publish for private-type channels + + + + + Share Private Publish Key + + + + + Channel Logo + + + + + Add Channel Logo + + + + + Cancel + + + + + Create + + + + + RetroShare + + + + + Please add a Name + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateChannelMsg + + + New Channel Post + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt; color:#ffffff;">New Channel Post</span></p></body></html> + + + + + Channel Post + + + + + Channel Post to: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can set your Thumbnail Image for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can use Drap and Drop to Attach Files.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> Set your Subject and Description for your Channel Post.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/feedback_arrow.png" /><span style=" font-size:8pt;"> You can View your Attached Files on Attachments Tab.</span></p></body></html> + + + + + Add File to Attach + + + + + Add Channel Thumbnail + + + + + Message + + + + + Subject : + + + + + + Attachments + + + + + allow channels to get frame for message thumbnail from movie media attachments or not + + + + + Auto Thumbnail + + + + + Drag and Drop Files from Search Results + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Add Extra File + + + + + + RetroShare + + + + + File already Added and Hashed + + + + + Please add a Subject + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + CreateForum + + + Please add a Name + + + + + Create new Forum + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:24pt; font-weight:600; color:#ffffff;">New Forum</span></p></body></html> + + + + + Name + + + + + Description + + + + + Type: + + + + + Public - Anyone can read and publish (Shared Publish Key) + + + + + Restricted - Anyone can read, limited publishing (Private Publish Key) + + + + + Private - (Private Publish Key required to view Messages) + + + + + Allowed Messages + + + + + Authenticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + Create + + + + + CreateForumMsg + + + Post Forum Message + + + + + Forum + + + + + Attach File + + + + + Forum Post + + + + + Sign Message + + + + + Subject + + + + + + Paste RetroShare Link + + + + + Attach files via drag and drop + + + + + You can attach files via drag and drop here in this window + + + + + Post Forum Msg + + + + + Close + + + + + Paste full RetroShare Link + + + + + In Reply to + + + + + RetroShare + + + + + Please set a Forum Subject and Forum Message + + + + + Add Extra File + + + + + + Drop file error. + + + + + File not found or file name not accepted. + + + + + Directory can't be dropped, only files are accepted. + + + + + CreateGroup + + + Create a Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Create a Group</span></p></body></html> + + + + + Group Name + + + + + Enter a name for your group + + + + + Edit Group + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Edit Group</span></p></body></html> + + + + + CryptoPage + + + RetroShare + + + + + Your Public Key is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Public Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copy my Key to Clipboard</p></body></html> + + + + + Copy Key + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save Key into a file</p></body></html> + + + + + Save Key + + + + + DHTStatus + + + DHT + + + + + DHT On + + + + + RetroShare users in DHT (Total DHT users) + + + + + DHT Off + + + + + DLListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + DetailsDialog + + + Details + + + + + + General + + + + + File Name: + + + + + Hash: + + + + + Size: + + + + + Status: + + + + + Priority: + + + + + Type: + + + + + Transfer + + + + + Sources: + + + + + Datarate: + + + + + Completed: + + + + + Chunk size: + + + + + + Number of Chunks + + + + + Chunks: + + + + + Remaining: + + + + + Date + + + + + Download time: + + + + + + Comments + + + + + + retroshare link(s) + + + + + Copy + + + + + OK + + + + + Cancel + + + + + Rating + + + + + File Name + + + + + Not Rated + + + + + No Comments + + + + + DirectoriesPage + + + + Browse + + + + + Set Incoming Directory + + + + + Set Partials Directory + + + + + Incoming Directory + + + + + Partials Directory + + + + + Automatically share incoming directory (Recommended) + + + + + Remember file hashes even if not shared. +This might be useful if you're sharing an +external HD, to avoid re-hashing files when +you plug it in. + + + + + Remember hashed files for + + + + + days + + + + + Forget any hashed file that is not anymore shared. + + + + + Clean Hash Cache + + + + + Auto-check shared directories every + + + + + minute(s) + + + + + Shared Directories + + + + + Edit Share + + + + + DiscStatus + + + Waiting outgoing discovery operations + + + + + Waiting incoming discovery operations + + + + + DownloadToaster + + + Start file + + + + + <b>Download completed</b> + + + + + Close + + + + + EditChanDetails + + + Channel Details + + + + + Cancel + + + + + OK + + + + + Edit Channel Details + + + + + Channel Info + + + + + Channel Name + + + + + Channel Description + + + + + Add Channel Logo + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg) + + + + + EditForumDetails + + + Forum Details + + + + + Cancel + + + + + OK + + + + + Edit Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Forum Description + + + + + EmailPage + + + Invite Friends by Email + + + + + Enter your friends' email addresses (seperate each on with a semicolon) + + + + + Your friends' email addresses: + + + + + Enter Friends Email addresses + + + + + Subject: + + + + + Friend invites you to check out RetroShare + + + + + Friend uses RetroShare to communicate securely, and invites you to join him to share files together. <br>RetroShare is free and using it is safe: it contains no viruses, no spyware, no adware and it can easily be uninstalled. <br>For more information, see our website http://retroshare.sourceforge.net/ or download the software here http://retroshare.sourceforge.net/downloads.html. <br>See you soon on RetroShare! + + + + + ErrorMessagePage + + + Sorry, some error appeared + + + + + Here is the error message: + + + + + ExampleDialog + + + Vote Up + + + + + Vote Down + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">Friends</span></p></body></html> + + + + + # + + + + + Status + + + + + Person + + + + + Auto Connect + + + + + Trust Level + + + + + Peer Address + + + + + Last Contact + + + + + Organisation + + + + + Location + + + + + Country + + + + + Person Id + + + + + Auth Code + + + + + ExprParamElement + + + + + to + + + + + ignore case + + + + + + dd.MM.yyyy + + + + + + KB + + + + + + MB + + + + + + GB + + + + + ExpressionWidget + + + Expression Widget + + + + + Delete this expression + + + + + FileAssociationsPage + + + &New + + + + + Add new Association + + + + + &Edit + + + + + Edit this Association + + + + + &Remove + + + + + Remove this Association + + + + + File type + + + + + Friend Help + + + + + You this + + + + + FileTransferInfoWidget + + + Chunk map + + + + + Active chunks + + + + + Availability map (%1 active source) + + + + + Availability map (%1 active sources) + + + + + File info + + + + + File hash + + + + + + + + bytes + + + + + File size + + + + + Chunk size + + + + + Number of chunks + + + + + Transfered + + + + + Remaining + + + + + Number of sources + + + + + Chunk strategy + + + + + Transfer type + + + + + Anonymous F2F + + + + + Direct friend transfer / Availability assumed + + + + + FlatStyle_RDM + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + Directory + + + + + FofPage + + + Friends of friends + + + + + Select now who you want to make friends with. + + + + + Show me: + + + + + Any peer I've not signed + + + + + Friends of my friends who already trust me + + + + + Signed peers showing as denied + + + + + Peer name + + + + + Also signed by + + + + + Peer id + + + + + Make friend with these peers + + + + + *** None *** + + + + + ForumDetails + + + + Forum Details + + + + + Forum Info + + + + + Forum Name + + + + + Popularity + + + + + Last Post + + + + + Forum ID + + + + + Forum Description + + + + + Security + + + + + Allowed Messages + + + + + Authemticated Messages + + + + + Anonymous Messages + + + + + Cancel + + + + + OK + + + + + Apply and Close + + + + + ForumMsgItem + + + Remove Item + + + + + Expand + + + + + + + Subject: + + + + + Unsubscribe To Forum + + + + + Reply + + + + + Send + + + + + Signed + + + + + Forum Post + + + + + Unknown Forum Post + + + + + + + Anonymous + + + + + In Reply to + + + + + Please give a Text Message + + + + + ForumNewItem + + + Form + + + + + Remove Item + + + + + Subscribe to Forum + + + + + Expand + + + + + Forum Description + + + + + ForumPage + + + Misc + + + + + Set message to read on activate + + + + + Expand new messages + + + + + ForumsDialog + + + Subscribe to Forum + + + + + Unsubscribe to Forum + + + + + New Forum + + + + + Show Forum Details + + + + + Edit Forum Details + + + + + Restore Publish Rights for Forum + + + + + + Copy RetroShare Link + + + + + Mark all as read + + + + + Mark all as unread + + + + + Reply + + + + + + Start New Thread + + + + + Reply to Author + + + + + Expand all + + + + + Collapse all + + + + + AUTHD + + + + + Your Forums + + + + + Subscribed Forums + + + + + Popular Forums + + + + + Other Forums + + + + + + Mark as read + + + + + + Mark as unread + + + + + + with children + + + + + Hide + + + + + Expand + + + + + + RetroShare + + + + + No Forum Selected! + + + + + You cant reply a Anonymous Author + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Forum:</p></body></html> + + + + + Last Post + + + + + Threaded View + + + + + Flat View + + + + + + Date + + + + + + Title + + + + + Start new Thread for Selected Forum + + + + + Display + + + + + + Author + + + + + Signed + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Thread:</span></p></body></html> + + + + + Download all files + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Search forums</span></p></body></html> + + + + + Reset + + + + + Content + + + + + Create Forum + + + + + Print + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-weight:600;">Forums</span></p></body></html> + + + + + Previous Thread + + + + + Next Thread + + + + + Reply Message + + + + + PrintPreview + + + + + ForumsFillThread + + + + Anonymous + + + + + + signed + + + + + + none + + + + + FriendsDialog + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Friends</span></p></body></html> + + + + + Add + + + + + Display + + + + + Friends + + + + + Status + + + + + Add or Change your Avatar + + + + + Edit Personal message + + + + + Group Chat + + + + + Messages entered here are sent to all collected friends + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Font + + + + + Text Color + + + + + Attach File + + + + + Send + + + + + Clear Chat History + + + + + + Add Friend + + + + + Create new Profile + + + + + + Create new Forum + + + + + F + + + + + + Create new Channel + + + + + C + + + + + Add your Avatar Picture + + + + + A + + + + + Set your Personal Message + + + + + Edit your status Message + + + + + Browse Message History + + + + + Browse History + + + + + + Save Chat History + + + + + Hide Offline Friends + + + + + Hide Status Column + + + + + + Sort by State + + + + + Hide State + + + + + + Add a new Group + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Profile + + + + + News Feed + + + + + Welcome to RetroShare's group chat. + + + + + me + + + + + Paste RetroShare Link + + + + + Group + + + + + Friend + + + + + Location + + + + + Message Group + + + + + Edit Group + + + + + Remove Group + + + + + Chat + + + + + Message Friend + + + + + Friend Details + + + + + Recommend this Friend to... + + + + + Connect To Friend + + + + + Copy RetroShare Link + + + + + + Paste Friend Link + + + + + Deny Friend + + + + + Remove Friend Location + + + + + Add to group + + + + + Move to group + + + + + Groups + + + + + Remove from group + + + + + Remove from all groups + + + + + Expand all + + + + + Collapse all + + + + + location + + + + + + Available + + + + + Save Certificate + + + + + Certificates (*.pqi) + + + + + Do you want to remove this Friend? + + + + + is typing... + + + + + + New group chat + + + + + Do you really want to physically delete the history? + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + GamesDialog + + + Cancel Game + + + + + Add to Invite List + + + + + Remove from Invite List + + + + + + Interested in Playing + + + + + Not Interested in Game + + + + + + Not Interested + + + + + Confirm Peer in Game + + + + + Remove Peer from Game + + + + + Interested in Game + + + + + Quit Game + + + + + Form + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Games Launcher</span></p></body></html> + + + + + Game: + + + + + GameType: 0. Want to Add your Game here? + + + + + GameType: 1. Get In Touch with the developers + + + + + GameType: 2. + + + + + Title / Comment + + + + + Create New Game + + + + + Invite All Friends + + + + + Game Type + + + + + Server + + + + + Status + + + + + Comment + + + + + GameID + + + + + Player + + + + + + Invite + + + + + Interested + + + + + Accept + + + + + Delete + + + + + + Move Player + + + + + Play Game + + + + + GenCertDialog + + + + Create new Location + + + + + + Generate new Location + + + + + + Create a new Location + + + + + + Generate new Profile + + + + + + Create a new Profile + + + + + + Generate GPG key Failure + + + + + Location field is required with a minimum of 3 characters + + + + + All fields are required with a minimum of 3 characters + + + + + Generating new GPG key, please be patient: this process needs generating large prime numbers, and can take some minutes on slow computers. + +Fill in your GPG password when asked, to sign your new key. + + + + + Select Trusted Friend + + + + + Certificates (*.pqi *.pem) + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + + + + + Generate ID Failure + + + + + Failed to Load your new Certificate! + + + + + + + Create new Profile + + + + + It looks like you don't own any Profile (GPG keys). Please fill in the form below to generate one, or use your favorite gnupg key manager. + + + + + Generate a new Profile + + + + + Use Profile + + + + + Name + + + + + Enter here your nickname + + + + + Email + + + + + Be careful: this email will be visible to your friends and friends +of your friends. This information is required by GPG, but to stay +anonymous, you can use a fake email. + + + + + This Password is for GPG + + + + + Password + + + + + Put a strong password here. This password protects your GPG key. + + + + + Location + + + + + Put a meaningfull location. ex : home, laptop, etc. This field will be used to differentiate different installations with the same profile (gpg key). + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:16pt; color:#ffffff;">Create a new Profile</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">RetroShare uses gpg keys for identity management. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Arial'; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can use an existing profile (gpg key), or create a new one with this form.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:8pt; font-weight:600;">You can install retroshare on different locations using the same profile (gpg key).</span></p></body></html> + + + + + Generate New Profile + + + + + + Your profile is associated to a GPG key + + + + + Info + + + + + GeneralPage + + + Startup + + + + + Start RetroShare when my system starts + + + + + Start minimized + + + + + Start minimized on system start + + + + + Misc + + + + + Do not show the Quit RetroShare MessageBox + + + + + Do not Minimize to Tray Icon + + + + + Auto Login + + + + + Register retroshare:// as url protocol (Restart required) + + + + + Idle + + + + + Idle Time + + + + + seconds + + + + + GraphFrame + + + Recv: + + + + + + + %1 KB/s + + + + + Sent: + + + + + %1 KB + + + + + %1 MB + + + + + %1 GB + + + + + GraphWidget + + + Click and drag the nodes around, and zoom with the mouse wheel or the '+' and '-' keys + + + + + GroupDefs + + + Friends + + + + + Family + + + + + Co-Workers + + + + + Other Contacts + + + + + Favorites + + + + + GroupTreeWidget + + + Enter a Keyword here + + + + + Title + + + + + Description + + + + + Reset + + + + + Sort by Name + + + + + Sort by Popularity + + + + + Sort by Last Post + + + + + Private Key Available + + + + + GuiExprElement + + + and + + + + + and / or + + + + + or + + + + + Name + + + + + Path + + + + + Extension + + + + + Hash + + + + + Date + + + + + Size + + + + + Popularity + + + + + contains + + + + + contains all + + + + + is + + + + + less than + + + + + less than or equal + + + + + equals + + + + + greater than or equal + + + + + greater than + + + + + is in range + + + + + HelpBrowser + + + + Error Loading Help Contents: + + + + + Supplied XML file is not a valid Contents document. + + + + + Search reached end of document + + + + + Search reached start of document + + + + + Text not found in document + + + + + Found %1 results + + + + + + RetroShare Help + + + + + Find: + + + + + Find Previous + + + + + Find Next + + + + + Case sensitive + + + + + Whole words only + + + + + Contents + + + + + Help Topics + + + + + + Search + + + + + Searching for: + + + + + Found Documents + + + + + Back + + + + + Move to previous page (Backspace) + + + + + Backspace + + + + + Forward + + + + + Move to next page (Shift+Backspace) + + + + + Shift+Backspace + + + + + Home + + + + + Move to the Home page (Ctrl+H) + + + + + Ctrl+H + + + + + + + Find + + + + + Search for a word or phrase on current page (Ctrl+F) + + + + + Ctrl+F + + + + + Close + + + + + Close Vidalia Help + + + + + Esc + + + + + HelpDialog + + + About + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare is a Open Source cross-platform, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">private and secure decentralised commmunication platform. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">It lets you share securely your friends, </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">using a web-of-trust to authenticate peers and OpenSSL to encrypt all communication. </span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">RetroShare provides filesharing, chat, messages and channels</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Usefull External Links to more information:</span></p> +<ul style="-qt-list-indent: 1;"><li style=" font-size:8pt;" align="justify" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Webpage</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/wiki/index.php/Main_Page"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Wiki</span></a></li> +<li style=" font-size:8pt; text-decoration: underline; color:#0000ff;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://retroshare.sourceforge.net/forum/">RetroShare's Forum</a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://sourceforge.net/projects/retroshare/"><span style=" text-decoration: underline; color:#0000ff;">Retroshare Project Page</span></a></li> +<li style=" font-size:8pt;" align="justify" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.lunamutt.com"><span style=" text-decoration: underline; color:#0000ff;">Lunamutt Homepage.</span></a></li></ul></body></html> + + + + + Authors + + + + + Thanks to + + + + + Translation + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">French</span><span style=" font-size:8pt;">:Temet</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Polish: </span><span style=" font-size:8pt;">Jarek</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Serbian</span><span style=" font-size:8pt;">: Kunalagon Umuhanik &lt;kunalagon@gmail.com&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish:</span><span style=" font-size:8pt;"> dnylander</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">RetroShare Website Translators:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Swedish: </span><span style=" font-size:8pt;"> Daniel Wester</span><span style=" font-size:8pt; font-weight:600;"> &lt;</span><span style=" font-size:8pt;">wester@speedmail.se</span><span style=" font-size:8pt; font-weight:600;">&gt;</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">German: </span><span style=" font-size:8pt;">Jan</span><span style=" font-size:8pt; font-weight:600;"> </span><span style=" font-size:8pt;">Keller</span> &lt;<span style=" font-size:8pt;">trilarion@users.sourceforge.net</span>&gt;</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Polish: </span>Maciej Mrug</p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + License Agreement + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">About RetroShare</span></p></body></html> + + + + + HelpTextBrowser + + + Error opening help file: + + + + + Opening External Link + + + + + RetroShare can open the link you selected in your default Web browser. If your browser is not currently configured to use Tor then the request will not be anonymous. + + + + + Do you want Retroshare to open the link in your Web browser? + + + + + Unable to Open Link + + + + + RetroShare was unable to open the selected link in your Web browser. You can still copy the URL and paste it into your browser. + + + + + ImHistoryBrowser + + + Message History + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; color:#ffffff;">Message History</span></p></body></html> + + + + + Reset + + + + + + Copy + + + + + Remove + + + + + Mark all + + + + + Delete + + + + + Clear history + + + + + Send + + + + + InfoDialog + + + Info + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">RetroShare uses GPG keys, this is required for creating a RetroShare Profile.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">You must exchange your gpg keys with you friends, by emailing it or any way you want.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">When you recieve a friend's gpg key, add it within RS on the add friend wizard.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">1. On Linux you must install GPA :</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#0000ff;">sudo apt-get install gpa</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">2. On Windows you must install gpg4win package for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; font-weight:600;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://ftp.gpg4win.org/gpg4win-1.1.4.exe"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://ftp.gpg4win.org/gpg4win-1.1.4.exe</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#000000;">3. When want create your GPG key with GPA when it doesnt works then use WinPT for GPG Key creation:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; color:#0000ff;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://winpt.gnupt.de/winpt.zip"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://winpt.gnupt.de/winpt.zip</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt; text-decoration: underline; color:#0000ff;"></p></body></html> + + + + + IntroPage + + + &Make friend with selected friends of my friends + + + + + Add a new Friend + + + + + This wizard will help you to connect to your friend(s) to RetroShare network. +These ways are possible to do this: + + + + + &Enter the certificate manually + + + + + &You get a certificate file from your friend + + + + + &Enter RetroShare ID manually + + + + + &Send a Invitation by Email + (She/He receives a email with instructions howto to download RetroShare) + + + + + LinksDialog + + + Share Link Anonymously + + + + + Vote on Link + + + + + Download + + + + + Expand + + + + + Hide + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + File Request canceled + + + + + The file has not been added to your download list, because you already have it. + + + + + File Request Error + + + + + The file link is malformed. + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-weight:600;">Links Cloud</span></p></body></html> + + + + + Title / Comment + + + + + Score + + + + + Peer / Link + + + + + Sort by + + + + + Combo + + + + + Time + + + + + Ranking + + + + + In last + + + + + Month + + + + + Week + + + + + Day + + + + + From + + + + + All Peers + + + + + Own Links + + + + + Show + + + + + Top 100 + + + + + 101-200 + + + + + 201-300 + + + + + 301-400 + + + + + 401-500 + + + + + Bottom 100 + + + + + Link: + + + + + Add Anonymous Link + + + + + Add Link/Comment + + + + + Title: + + + + + Score: + + + + + +2 Great! + + + + + +1 Good + + + + + 0 Okay + + + + + -1 Sux + + + + + -2 Bad Link + + + + + Url: + + + + + Add new link + + + + + MainWindow + + + Network + + + + + Friends + + + + + Search + + + + + + Transfers + + + + + Files + + + + + + Messages + + + + + Links Cloud + + + + + + Forums + + + + + RetroShare %1 a secure decentralised communication platform + + + + + + Channels + + + + + Blogs + + + + + Plugins + + + + + Unfinished + + + + + Low disk space warning + + + + + The disk space in your + + + + + directory is running low (current limit is + + + + + MB). + + RetroShare will now safely suspend any disk access to this directory. + + Please make some free space and click Ok. + + + + + Show/Hide + + + + + Status + + + + + Minimize + + + + + Maximize + + + + + &Quit + + + + + RetroShare + + + + + Chat + + + + + + + + You have %1 new messages + + + + + + + + You have %1 new message + + + + + + + + %1 new messages + + + + + + + + %1 new message + + + + + You have %1 completed downloads + + + + + You have %1 completed download + + + + + %1 completed downloads + + + + + %1 completed download + + + + + Down: %1 (kB/s) + + + + + Up: %1 (kB/s) + + + + + %1 friend connected + + + + + %1 friends connected + + + + + It seems to be an old RetroShare link. Please use copy instead. + + + + + The file link is malformed. + + + + + + Options + + + + + Bandwidth Graph + + + + + Open Messenger + + + + + Open Messages + + + + + Applications + + + + + Help + + + + + Really quit ? + + + + + Internal Error + + + + + Hide + + + + + Show + + + + + Do you really want to exit RetroShare ? + + + + + Add Friend + + + + + Add a Friend Wizard + + + + + Add Share + + + + + Quit + + + + + + Quick Start Wizard + + + + + SMPlayer + + + + + Messenger + + + + + MainWindow + + + + + About + + + + + MessageComposer + + + + Compose + + + + + + Contacts + + + + + Search for Name: + + + + + Reset + + + + + Send To: + + + + + Subject: + + + + + Paragraph + + + + + Search Friends + + + + + >> To + + + + + >> Cc + + + + + >> Bcc + + + + + >> Recommend + + + + + Heading 1 + + + + + + Heading 2 + + + + + Heading 3 + + + + + Heading 4 + + + + + Heading 5 + + + + + Heading 6 + + + + + Font size + + + + + Increase font size + + + + + Decrease font size + + + + + Bold + + + + + Underline + + + + + Italic + + + + + Select Color + + + + + Alignment + + + + + Add a Image + + + + + Sets text font to code style + + + + + Tags: + + + + + + Tags + + + + + Recommended Files + + + + + File Name + + + + + Size + + + + + Hash + + + + + Send + + + + + Send this message now + + + + + Reply + + + + + Toggle Contacts View + + + + + Save + + + + + Save this message + + + + + Attach + + + + + Attach File + + + + + Quote + + + + + Add Blockquote + + + + + &Left + + + + + C&enter + + + + + &Right + + + + + &Justify + + + + + I recommend a good friend of me, you can trust him too when you trust me. <br> Copy friend link and paste to Friends list + + + + + + Save Message + + + + + Message has not been Sent. +Do you want to save message to draft box? + + + + + Friend Recommendation(s) + + + + + + Paste RetroShare Link + + + + + Add to "To" + + + + + Add to "CC" + + + + + Add to "BCC" + + + + + Add as Recommend + + + + + Friend Details + + + + + Re: + + + + + Fwd: + + + + + + RetroShare + + + + + Do you want to send the message without a subject ? + + + + + Please insert at least one recipient. + + + + + To + + + + + Cc + + + + + Bcc + + + + + Unknown + + + + + Unknown friend + + + + + &File + + + + + &New + + + + + &Open... + + + + + &Save + + + + + Save &As File + + + + + Save &As Draft + + + + + &Print... + + + + + &Export PDF... + + + + + &Quit + + + + + &Edit + + + + + &Undo + + + + + &Redo + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + &View + + + + + &Contacts Sidebar + + + + + &Insert + + + + + &Image + + + + + &Horizontal Line + + + + + &Format + + + + + Open File... + + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + Save as... + + + + + Print Document + + + + + Export PDF + + + + + Message has not been Sent. +Do you want to save message ? + + + + + Choose Image + + + + + Image Files supported (*.png *.jpeg *.jpg *.gif) + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + File not found or file name not accepted. + + + + + MessagePage + + + Reading + + + + + Set message to read on activate + + + + + Open messages in + + + + + Tags + + + + + Tags can be used to categorize and prioritize your messages + + + + + Add + + + + + Edit + + + + + Delete + + + + + Default + + + + + A new tab + + + + + A new window + + + + + Edit Tag + + + + + MessageToaster + + + Subject + + + + + <b>1 new Message from</b> + + + + + Close + + + + + Sub: + + + + + MessageWidget + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Recommended Files</span></p></body></html> + + + + + Download all Recommended Files + + + + + Subject: + + + + + From: + + + + + To: + + + + + Cc: + + + + + Bcc: + + + + + Tags: + + + + + File Name + + + + + Size + + + + + Hash + + + + + Print + + + + + Print Preview + + + + + No subject + + + + + Download + + + + + Download all + + + + + Hide + + + + + Expand + + + + + File + + + + + Files + + + + + Print Document + + + + + Save as... + + + + + HTML-Files (*.htm *.html);;All Files (*) + + + + + MessageWindow + + + New Message + + + + + Compose + + + + + Reply to selected message + + + + + Reply + + + + + Reply all to selected message + + + + + Reply all + + + + + Forward selected message + + + + + Foward + + + + + Remove selected message + + + + + Delete + + + + + Print selected message + + + + + + Print + + + + + Display + + + + + + + Tags + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + &File + + + + + Save &As File + + + + + &Print... + + + + + Print Preview... + + + + + &Quit + + + + + MessagesDialog + + + Forward selected Message + + + + + + New Message + + + + + Remove Messages + + + + + Reply to Message + + + + + Click to sort by attachments + + + + + Click to sort by subject + + + + + Click to sort by read + + + + + + Click to sort by from + + + + + Click to sort by date + + + + + Click to sort by tags + + + + + Click to sort by star + + + + + Starred + + + + + Open in a new window + + + + + Open in a new tab + + + + + + Reply to All + + + + + Forward Message + + + + + Mark as read + + + + + Mark as unread + + + + + Add Star + + + + + Edit + + + + + Edit as new + + + + + Remove Message + + + + + Undelete + + + + + Empty trash + + + + + + + Drafts + + + + + No starred messages available. Stars let you give messages a special status to make them easier to find. To star a message, click on the light grey star beside any message. + + + + + To + + + + + Click to sort by to + + + + + + + + + Total: + + + + + + + + Inbox + + + + + + + + Outbox + + + + + Draft + + + + + + Sent + + + + + + + From + + + + + + Subject + + + + + Reply + + + + + Reply all + + + + + Foward + + + + + Delete + + + + + Compose + + + + + Reply to selected message + + + + + Reply all to selected message + + + + + Forward selected message + + + + + Remove selected message + + + + + Print selected message + + + + + Display + + + + + Reset + + + + + Attachments + + + + + + Date + + + + + Quick View + + + + + + Content + + + + + + + + + Tags + + + + + + + + Trash + + + + + Total Inbox: + + + + + Folders + + + + + + Print... + + + + + Print Preview + + + + + + Buttons Icon Only + + + + + Buttons Text Beside Icon + + + + + Buttons with Text + + + + + Buttons Text Under Icon + + + + + Set Text Under Icon + + + + + Save As... + + + + + Print + + + + + MessengerWindow + + + Expand all + + + + + Collapse all + + + + + Chat + + + + + Message Friend + + + + + Peer Details + + + + + Recomend this Friend to... + + + + + Export Friend + + + + + Deny Friend + + + + + Remove Friend Location + + + + + <strong>GPG Key</strong> + + + + + + + + location + + + + + <strong>RetroShare instance</strong> + + + + + Paste RetroShare Link + + + + + Save Certificate + + + + + Certificates (*.pqi) + + + + + Connect To Friend + + + + + Click to Change your Avatar + + + + + Search Friends + + + + + Reset + + + + + + Sort Descending Order + + + + + + Sort Ascending Order + + + + + Set root is Decorated + + + + + Set Root Decorated + + + + + Sort by State + + + + + Hide Offline Friends + + + + + RetroShare Messenger + + + + + Add a Friend + + + + + Share Files for your Friends + + + + + MsgItem + + + Remove Item + + + + + + Expand + + + + + Reply to Message + + + + + Reply Message + + + + + Delete Message + + + + + Play Media + + + + + Message From + + + + + Sent Msg + + + + + Draft Msg + + + + + Pending Msg + + + + + Hide + + + + + NATStatus + + + <strong>NAT:</strong> + + + + + Internet connection + + + + + No internet connection + + + + + No local network + + + + + OK | RetroShare Server + + + + + NetworkDialog + + + Authentication matrix + + + + + Network View + + + + + Deny friend + + + + + Make friend + + + + + Delete certificate + + + + + Export my Cert + + + + + Peer details... + + + + + Copy RetroShare Link + + + + + Personal signature + + + + + GPG key signed by you + + + + + Marginally trusted peer + + + + + Fully trusted peer + + + + + Untrusted peer + + + + + Has authenticated me + + + + + has authenticated you. +Right-click and select 'make friend' to be able to connect. + + + + + yourself + + + + + Unknown + + + + + Network + + + + + + + Name + + + + + + Did I authenticated peer + + + + + Did I sign his gpg key + + + + + + Cert Id + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Network</span></p></body></html> + + + + + Peer ID + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Display</span></p></body></html> + + + + + Network Status + + + + + Local network + + + + + UPnP + + + + + External ip address finder + + + + + Create New Profile + + + + + Create a new Profile + + + + + Clear + + + + + + Did peer authenticated me + + + + + Search Network + + + + + Clear Filter + + + + + Show keys that are not validated by the GPG web of trust + + + + + Set Tabs Right + + + + + Set Tabs North + + + + + Set Tabs South + + + + + Set Tabs Left + + + + + Set Tabs Rounded + + + + + Set Tabs Triangular + + + + + Add Friend + + + + + Copy My Key to Clipboard + + + + + Export My Key + + + + + NetworkView + + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray); + + + + + Redraw + + + + + Friendship level: + + + + + Edge length: + + + + + NewTag + + + New Tag + + + + + Name: + + + + + Choose color + + + + + OK + + + + + Cancel + + + + + NewsFeed + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt; font-weight:600;">News Feed</span></p></body></html> + + + + + Remove All + + + + + Options + + + + + NotifyPage + + + News Feed + + + + + Peers + + + + + Channels + + + + + Forums + + + + + Chat + + + + + Blogs + + + + + Messages + + + + + Add feeds at end + + + + + Systray Icon + + + + + Private Message + + + + + Message + + + + + Channel Post + + + + + Forum Post + + + + + + Download completed + + + + + Combined icon + + + + + Toasters + + + + + Friend Connect + + + + + New Message + + + + + Position + + + + + X Margin + + + + + Y Margin + + + + + Private Chat + + + + + Open Window for new chat + + + + + Grab Focus when chat arrives + + + + + Use a single tabbed window + + + + + Group chat + + + + + Display systray message + + + + + Top Left + + + + + Top Right + + + + + Bottom Left + + + + + Bottom Right + + + + + NotifyQt + + + GPG key passphrase + + + + + Wrong password ! + + + + + Please enter the password to unlock the following GPG key: + + + + + Examining shared files... + + + + + Hashing file + + + + + Saving file index... + + + + + OnlineToaster + + + Friend Online + + + + + PeerDefs + + + + Unknown + + + + + PeerItem + + + Remove Item + + + + + + Expand + + + + + Peer ID: + + + + + Status: + + + + + Trust: + + + + + Write Message + + + + + Chat + + + + + Write a quick Message + + + + + Start Chat + + + + + Send + + + + + Cancel + + + + + Name: + + + + + Location + + + + + IP Address + + + + + Connection Method + + + + + Friend + + + + + Friend Connected + + + + + Connect Attempt + + + + + Friend of Friend + + + + + Peer + + + + + + + + + + + + + Unknown Peer + + + + + Hide + + + + + Quick Message + + + + + PeerStatus + + + Friends: 0/0 + + + + + Online Friends/Total Friends + + + + + Friends + + + + + PhotoDialog + + + Insert Show Lists + + + + + Open + + + + + Remove + + + + + Excellent + + + + + Good + + + + + Average + + + + + Below avarage + + + + + Bad + + + + + Unrated + + + + + Rating + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Photo View</span></p></body></html> + + + + + Peer + + + + + Slideshow + + + + + Photo + + + + + Thumb Image + + + + + Image Name + + + + + + Comment + + + + + + Date + + + + + + Location + + + + + Size + + + + + PeerId + + + + + PhotoId + + + + + + Add Photo(s) + + + + + Add Photo SlideShow + + + + + Update Details + + + + + Photo + + + + + Description + + + + + PhotoShow + + + Date: + + + + + Location: + + + + + Comment: + + + + + Display Size: + + + + + 320 x 320 + + + + + 640 x 640 + + + + + Full Size + + + + + Play Rate: + + + + + 1 Sec + + + + + 2 Sec + + + + + 5 Sec + + + + + 10 Sec + + + + + 20 Sec + + + + + 1 Min + + + + + Edit Photo Details + + + + + Save Photo + + + + + No Photo Selected + + + + + Start + + + + + Back + + + + + Photo Show + + + + + Play + + + + + Pause + + + + + Forward + + + + + PluginFrame + + + Remove + + + + + PluginManagerWidget + + + Install New Plugin... + + + + + Open Plugin to install + + + + + Plugins (*.so *.dll) + + + + + PopularityDefs + + + Popularity + + + + + PopupChatDialog + + + Your Friend is offline +Do you want to send them a Message instead + + + + + Friend not Online + + + + + is typing... + + + + + Hide Avatar + + + + + Messages you send will be delivered after Friend is again Online + + + + + Show Avatar + + + + + Paste RetroShare Link + + + + + Do you really want to physically delete the history? + + + + + Load Picture File + + + + + Save as... + + + + + Text File (*.txt );;All Files (*) + + + + + apears to be Offline. + + + + + is Idle and may not reply + + + + + is Away and may not reply + + + + + is Busy and may not reply + + + + + File not found or file name not accepted. + + + + + Close + + + + + + Bold + + + + + + Underline + + + + + + Italic + + + + + Text Color + + + + + Clear Chat History + + + + + Browse Message History + + + + + Browse History + + + + + Delete Chat History + + + + + Deletes all stored and displayed chat history + + + + + Attach a Picture + + + + + Send + + + + + Font + + + + + Strike + + + + + Disable Emoticons + + + + + + Save Chat History + + + + + Clear offline messages + + + + + Add Extra File + + + + + + Drop file error. + + + + + Directory can't be dropped, only files are accepted. + + + + + Add a File for your Friend + + + + + PopupChatWindow + + + Avatar + + + + + Set your Avatar Picture + + + + + + Dock tab + + + + + + Undock tab + + + + + + Set Chat Window Color + + + + + RetroShare + + + + + Load File + + + + + Pictures (*.png *.xpm *.jpg *.tiff *.gif) + + + + + PrintPreview + + + RetroShare Message - Print Preview + + + + + Print + + + + + &Print... + + + + + Page Setup... + + + + + Zoom In + + + + + Zoom Out + + + + + &Close + + + + + ProfileEdit + + + Remove Profile Entry + + + + + Move Profile Entry Up + + + + + Move Profile Entry Down + + + + + Profile Edit + + + + + Profile + + + + + Category + + + + + Thoughts + + + + + Edit Profile Category + + + + + Birthday + + + + + School + + + + + University + + + + + Phone Number + + + + + Favourite Books + + + + + Favourite Music + + + + + Favourite Films + + + + + or Custom Entry + + + + + Add Entry + + + + + + Move + + + + + Close Editor + + + + + ProfileView + + + Clear Photo + + + + + Change Photo + + + + + + Edit Profile + + + + + Remove Favourite + + + + + Clear Favourites + + + + + Download File + + + + + Download All + + + + + RetroShare + + + + + Error : cannot get peer details. + + + + + Profile View + + + + + + Name + + + + + Peer ID + + + + + Last Post: + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; vertical-align:sub;">Profile</span></p></body></html> + + + + + Category + + + + + Thoughts + + + + + Favourite Files + + + + + Size + + + + + Hash + + + + + Close Profile + + + + + ProfileWidget + + + + Edit Personal message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/images/info16.png" /><span style=" font-size:8pt;"> </span><span style=" font-size:12pt;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Public Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Name:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Location:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">Other Information</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Number of Friends:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Dynamic DNS:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Peer ID:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Version:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Online since:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600; color:#808080;">My Address</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; color:#76746c;">Local Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">External Address:</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#76746c;">Addresses list</span></p></body></html> + + + + + QObject + + + + RetroShare + + + + + Inititialize failed. Wrong or missing installation of gpg. + + + + + + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first + Lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock + Lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + File Request Confirmation + + + + + The file has been added to your download list. + + + + + + File Request canceled + + + + + The following has not been added to your download list, because you already have it: + + + + + + The file has not been added to your download list, because you already have it. + + + + + + Friend Request Confirmation + + + + + The friend is already in your list. + + + + + The friend has been added to your list. + + + + + + Friend Request canceled + + + + + The friend could not be added to your list. + + + + + The friend could not be found. + + + + + + Forum Request canceled + + + + + The forum "%1" could not be found. + + + + + The forum message in forum "%1" could not be found. + + + + + + Channel Request canceled + + + + + The channel "%1" could not be found. + + + + + The channel message in channel "%1" could not be found. + + + + + + Message Request canceled + + + + + Cannot send a message to a not accepted receipient "%1". + + + + + The receipient of the message is unknown. + + + + + File Request Error + + + + + The file link is malformed. + + + + + %1 of %2 RetroShare links processed. + + + + + Request Confirmation + + + + + Deny friend + + + + + Make friend + + + + + Peer details + + + + + Start with a RetroShare link is only supported for Windows. + + + + + (Age in seconds) + + + + + (Depth) + + + + + total + + + + + Search requests repartition: + + + + + Tunnel requests repartition: + + + + + QuickStartWizard + + + Quick Start Wizard + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:26pt;">RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Welcome to RetroShare!</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This QuickStart wizard can help you configure your RetorShare in a few simple steps.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you're a more advanced user, you can access the full range of RetroShare's options via the ToolBar. Click Exit to close the wizard at any time.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This wizard will assist you to:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Tell RetroShare about your internet connection.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Choose which files you share.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><img src=":/images/list_bullet_arrow.png" /><span style=" font-size:8pt;"> Get started using RetroShare.</span></p></body></html> + + + + + + + Next > + + + + + + + + Exit + + + + + For best performance, RetroShare needs to know a little about your connection to the internet. + + + + + Choose your upload speed limit: + + + + + + KB/s + + + + + Choose your download speed limit: + + + + + Connection : + + + + + Automatic (UPnP) + + + + + Firewalled + + + + + Manually forwarded port + + + + + Discovery : + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + Dynamic DNS: + + + + + + + < Back + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders . You can add and remove folders using the button on the left. When you add a new folder, intially all file in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable by friends</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Anonymously shared</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Network Wide + + + + + Browseable + + + + + Add + + + + + Remove + + + + + Automatically share incoming directory (Recommended) + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Enjoy using RetroShare!</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Just one more step! You're almost done configuring RetroShare to work with your computer.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">These settings configure how and when RetroShare starts .</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + + + Do not show a message when Closing RetroShare + + + + + Start Minimized + + + + + Start RetroShare when my System Starts. + + + + + Start minimized on system start + + + + + Finish + + + + + Select A Folder To Share + + + + + Shared Directory Added! + + + + + Do you really want to stop sharing this directory ? + + + + + Warning! + + + + + RSettingsWin + + + General + + + + + Directories + + + + + Server + + + + + Transfer + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + UnknownPage + + + + + Error Saving Configuration on page + + + + + RatesStatus + + + <strong>Down:</strong> 0.00 (kB/s) | <strong>Up:</strong> 0.00 (kB/s) + + + + + <strong>Down:</strong> + + + + + <strong>Up:</strong> + + + + + RetroshareDirModel + + + Anonymous + + + + + Anonymous and browsable by friends + + + + + Only browsable by friends + + + + + NEW + + + + + Rshare + + + Resets ALL stored RetroShare settings. + + + + + Sets the directory RetroShare uses for data files. + + + + + Sets the name and location of RetroShare's logfile. + + + + + Sets the verbosity of RetroShare's logging. + + + + + Sets RetroShare's interface style. + + + + + Sets RetroShare's interface stylesheets. + + + + + Sets RetroShare's language. + + + + + RetroShare Usage Information + + + + + Invalid language code specified: + + + + + Invalid GUI style specified: + + + + + Invalid log level specified: + + + + + Unable to open log file '%1': %2 + + + + + RsidPage + + + RetroShare ID + + + + + Use RetroShare ID for adding a Friend which is available in your network. + + + + + Add Friends RetroShare ID... + + + + + Paste Friends RetroShare ID in the box below + + + + + Enter the RetroShare ID of your Friend, e.g. Peer@BDE8D16A46D938CF + + + + + This Peer %1 is not available in your Network + + + + + SFListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + SearchDialog + + + + Download + + + + + Enter a keyword here (at least 3 char long) + + + + + + Copy RetroShare Link + + + + + Send RetroShare Link + + + + + Download Notice + + + + + Skipping Local Files + + + + + + Sorry + + + + + + This function is not yet implemented. + + + + + Remove + + + + + Remove All + + + + + + Folder + + + + + New RetroShare Link(s) + + + + + Any + + + + + Archive + + + + + Audio + + + + + CD-Image + + + + + Document + + + + + Picture + + + + + Program + + + + + Video + + + + + Directory + + + + + Filter Search Result + + + + + Clear Filter + + + + + File Name + + + + + File Size + + + + + Close all Search Resullts + + + + + Download Selected + + + + + Close All Search Results + + + + + Include files from your own file list in the search result + + + + + Include own files + + + + + Search inside "browsable" files of your friends + + + + + Search in friends lists + + + + + Multi-hop search at distance 6 in the network +(always reports available files) + + + + + F2F search + + + + + Limit number of results to : + + + + + Filename + + + + + Start Search + + + + + Search + + + + + Reset + + + + + Enter a Keyword here + + + + + Advanced Search + + + + + Advanced + + + + + Size + + + + + Sources + + + + + Type + + + + + Age + + + + + Hash + + + + + KeyWords + + + + + Results + + + + + Search Id + + + + + ServerPage + + + Automatic (Upnp) + + + + + Firewalled + + + + + Manual Forwarded Port + + + + + Transfer Rates + + + + + Download (KB/s) + + + + + + kB/s + + + + + Upload (KB/s) + + + + + + Network Configuration + + + + + The DHT allows you to answer connection +requests from your friends using BitTorrent's DHT. +It greatly improves the connectivity. + +The Discovery service sends locations and GPG +identities of your trusted contacts to connected +peers, to help them choose new friends. +The friendship is never automatic however, and both +peers still need to trust each other to allow connection. + + + + + Public: DHT & Discovery + + + + + Private: Discovery Only + + + + + Inverted: DHT Only + + + + + Dark Net: None + + + + + If you unckeck this, RetroShare will not use tunnel connection between peers that are firewalled and cannot connect directly. This is independant from F2F routing (turtle router). + + + + + Allow Tunnel Connection + + + + + Local Address + + + + + External Address + + + + + Dynamic DNS + + + + + + Port: + + + + + Show Discovery information in statusbar + + + + + IP Service + + + + + If you unckeck this, RetroShare can only determine your IP +when you connect to somebody. Leaving this checked helps +connecting when you have few friends. It also helps if you're +behind a firewall or a VPN. + + + + + Allow RetroShare to ask my ip to these websites: + + + + + Settings + + + Options + + + + + General + + + + + Server + + + + + Transfer + + + + + Directories + + + + + Notify + + + + + Security + + + + + Message + + + + + Forum + + + + + Chat + + + + + Appearance + + + + + Sound + + + + + Cancel + + + + + OK + + + + + ShareDialog + + + RetroShare Share Folder + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Folder</span></p></body></html> + + + + + Share Folder + + + + + Local Path + + + + + Browse + + + + + Virtual Folder + + + + + Share Flags + + + + + Browsable + + + + + Anonymous shared Network Wide + + + + + Network Wide + + + + + Browseable by Friends + + + + + OK + + + + + Cancel + + + + + Select A Folder To Share + + + + + ShareKey + + + check peers you would like to share private publish key with + + + + + Share Channel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial'; font-size:18pt; font-weight:600; color:#ffffff;">Share Channel</span></p></body></html> + + + + + Share for Friend + + + + + Contacts: + + + + + Share + + + + + Cancel + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the Friends with which you want to Share your Channel.</span></p></body></html> + + + + + RetroShare + + + + + Please select at least one peer + + + + + ShareManager + + + Add a Share Directory + + + + + Stop sharing selected Directory + + + + + + Remove + + + + + If checked, the share is anonymously shared to anybody. + + + + + If checked, the share is browsable by your friends. + + + + + Warning! + + + + + Do you really want to stop sharing this directory ? + + + + + + Drop file error. + + + + + File can't be dropped, only directories are accepted. + + + + + Directory not found or directory name not accepted. + + + + + RetroShare Share Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:26pt; font-weight:600; color:#ffffff;">Share Manager</span></p></body></html> + + + + + Shared Folder Manager + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of shared folders. You can add and remove folders using the buttons at the bottom.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">When you add a new folder, intially all files in that folder are shared.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Browsable</span><span style=" font-family:'Sans'; font-size:8pt;">: files are browsable from your direct friends.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">Network Wide</span><span style=" font-family:'Sans'; font-size:8pt;">: files can be downloaded by anybody through anonymous tunnels.</span></p></body></html> + + + + + Directory + + + + + Virtual Folder + + + + + Network Wide + + + + + Browsable + + + + + Add + + + + + Close + + + + + Edit selected Shared Directory + + + + + + Edit + + + + + SharedFilesDialog + + + + Download + + + + + Checking... + + + + + Check files + + + + + Copy retroshare Link + + + + + Send retroshare Link + + + + + Copy retroshare Links to Clipboard + + + + + Copy retroshare Links to Clipboard (HTML) + + + + + Send retroshare Links + + + + + Send retroshare Links (HTML) + + + + + Send retroshare Links to Cloud + + + + + Add Links to Cloud + + + + + + Open File + + + + + Open Folder + + + + + + Recommend in a message to + + + + + + + RetroShare Link + + + + + + + + Recommendation(s) + + + + + Set command for opening this file + + + + + <strong>My Shared Files</strong> + + + + + <strong>Friends Files</strong> + + + + + <strong>Files</strong> + + + + + Splitted View + + + + + Friends Folders + + + + + My Folders + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-weight:600;">Files</span></p></body></html> + + + + + All + + + + + One day old + + + + + One Week old + + + + + One month old + + + + + Search files + + + + + Start Search + + + + + Reset + + + + + Tree view + + + + + Flat view + + + + + Download selected + + + + + check files + + + + + SoundPage + + + Sound Events + + + + + go Online + + + + + Friend + + + + + + + + + Browse + + + + + New Msg + + + + + FileSend + + + + + + Finished + + + + + FileRecive + + + + + Incoming + + + + + Chatmessage + + + + + SplashScreen + + + Load profile + + + + + Load configuration + + + + + Create interface + + + + + StartDialog + + + RetroShare + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><span style=" font-size:18pt; color:#55aaff;">Login</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; color:#55aaff;"></p></body></html> + + + + + Opens a dialog for creating a new profile or +adding locations to an existing profile. +The current identities/locations will not be affected. + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Create new Profile..."><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;">Manage profiles and locations...</span></a></p></body></html> + + + + + Log In + + + + + Remember Password + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="Info"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Info...</span></a></p></body></html> + + + + + Name (GPG Id) - location: + + + + + + Multiple instances + + + + + Another RetroShare using the same profile is already running on your system. Please close that instance first, or choose another profile +lock file: + + + + + + An unexpected error occurred when Retrosharetried to acquire the single instance lock +lock file: + + + + + + Login Failure + + + + + Maybe password is wrong + + + + + + Warning + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in your Gnome Keyring. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + The passwd to your SSL certificate (your location) will be stored encrypted in the keys/help.dta file. This is not secure. + + Your PGP passwd will not be stored. + +This choice can be reverted in settings. + + + + + StatisticDialog + + + %1 days + + + + + Hide Settings + + + + + + Show Settings + + + + + Statistics + + + + + Now + + + + + Transfer + + + + + Session UL:DL Ratio: + + + + + Cumulative UL:DL Ratio + + + + + Download + + + + + Session: + + + + + + Downloaded: + + + + + + Count of Downloads: + + + + + + + Overall + + + + + Upload + + + + + + + Session + + + + + Uploaded: + + + + + + Count of Uploads: + + + + + Uploaded + + + + + + + + Connections: + + + + + + + Peers: + + + + + Time Statistics + + + + + + Uptime + + + + + Since: + + + + + Cumulative + + + + + Records + + + + + Uploadspeed: + + + + + Downloadspeed: + + + + + Uptime: + + + + + Reset + + + + + Receive Rate + + + + + Send Rate + + + + + Always On Top + + + + + 100 + + + + + % Opaque + + + + + Changes the transparency of the Bandwidth Graph + + + + + Save + + + + + Cancel + + + + + StatusDefs + + + + Offline + + + + + Away + + + + + Busy + + + + + Online + + + + + Idle + + + + + Friend is offline + + + + + Friend is away + + + + + Friend is busy + + + + + Friend is online + + + + + Friend is idle + + + + + Connected + + + + + Unreachable + + + + + Available + + + + + Neighbour + + + + + Trying tunnel connection + + + + + Trying TCP + + + + + Trying UDP + + + + + Connected: TCP + + + + + Connected: UDP + + + + + Connected: Tunnel + + + + + Connected: Unknown + + + + + DHT: Contact + + + + + StatusMessage + + + Personal message + + + + + Status message + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14pt; font-weight:600;">Personal message</span></p></body></html> + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; color:#666666;">Enter your Status message</span></p></body></html> + + + + + OK + + + + + Cancel + + + + + Paste RetroShare Link + + + + + StyleDialog + + + Define Style + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; color:#ffffff;">Define Style</span></p></body></html> + + + + + + Choose color + + + + + Color 2 + + + + + Color 1 + + + + + Style + + + + + None + + + + + Solid + + + + + Gradient + + + + + SubDestItem + + + Delete FeedItem + + + + + SubFileItem + + + + ERROR + + + + + EXTRA + + + + + REMOTE + + + + + DOWNLOAD + + + + + LOCAL + + + + + UPLOAD + + + + + File %1 does not exist at location. + + + + + File %1 is not completed. + + + + + Save Channel File + + + + + Download + + + + + Play + + + + + %p Kb + + + + + Save File + + + + + Cancel Download + + + + + Download File + + + + + + + Play File + + + + + TBoard + + + Pause + + + + + TagDefs + + + Important + + + + + Work + + + + + Personal + + + + + Todo + + + + + Later + + + + + TagsMenu + + + Remove All Tags + + + + + New tag ... + + + + + TextPage + + + Use text representation of the PGP certificates. + + + + + The text below is your PGP certificate. You have to provide it to your friend + + + + + Please, paste your friends PGP certificate into the box below + + + + + You can copy this text and send it to your friend via email or some other way + + + + + RetroShare + + + + + Text certificate + + + + + Copy your Cert to Clipboard + + + + + Save your Cert into a File + + + + + Run Email program + + + + + Clean certificate + + + + + RetroShare Invite + + + + + Connect Friend Help + + + + + Your Cert is copied to Clipboard, paste and send it to your friend via email or some other way + + + + + Save as... + + + + + RetroShare Certificate (*.rsc );;All Files (*) + + + + + Certificate Load Failed + + + + + TransferPage + + + Transfer options + + + + + Queue Size: + + + + + Default chunk strategy: + + + + + Safety disk space limit : + + + + + Streaming + + + + + Random + + + + + MB + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt; font-weight:600;">RetroShare</span><span style=" font-family:'Sans'; font-size:8pt;"> is capable of transfering data and search requests between peers that are not necessarily friends. This traffic however only transits through a connected list of friends and is anonymous.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans'; font-size:8pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans'; font-size:8pt;">You can separately setup share flags for each shared directory in the shared files dialog to be:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Browsable by friends</span>: files are seen by your friends.</li> +<li style=" font-family:'Sans'; font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Anonymously shared</span>: files are anonymously reachable through distant F2F tunnels.</li></ul></body></html> + + + + + TransfersDialog + + + + Name + i.e: file name + + + + + + Size + i.e: file size + + + + + Completed + + + + + Speed + i.e: Download speed + + + + + Sources + i.e: Sources + + + + + + Status + + + + + Progress / Availability + i.e: % downloaded + + + + + Core-ID + + + + + Peer + i.e: user name + + + + + Progress + i.e: % uploaded + + + + + Speed + i.e: upload speed + + + + + Transferred + + + + + Hash + + + + + Copy RetroShare Link + + + + + Paste RetroShare Link + + + + + Play + + + + + Pause + + + + + Router Statistics + + + + + Router Requests + + + + + Resume + + + + + Force Check + + + + + Cancel + + + + + Open Folder + + + + + Open File + + + + + Preview File + + + + + Details... + + + + + Clear Completed + + + + + + Slower + + + + + + + Average + + + + + + Faster + + + + + Remaining + + + + + Download time + i.e: Estimated Time of Arrival / Time left + + + + + Move in Queue... + + + + + Streaming + + + + + Random + + + + + Chunk strategy + + + + + version: + + + + + Queued + + + + + Speed / Queue position + + + + + Down + + + + + Up + + + + + Top + + + + + Bottom + + + + + Priority (Speed)... + + + + + Paused + + + + + Transferring + + + + + Checking... + + + + + RetroShare + + + + + Details: + + + + + File preview + + + + + File %1 preview failed. + + + + + Open Transfer + + + + + File %1 is not completed. If it is a media file, try to preview it. + + + + + Are you sure that you want to cancel and delete these files? + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Downloads:</span></p></body></html> + + + + + Show cache transfers + + + + + Uploads + + + + + Selected transfer + + + + + Done + + + + + Active + + + + + Outstanding + + + + + + + Failed + + + + + + + Okay + + + + + + Waiting + + + + + Downloading + + + + + + + + Complete + + + + + Unknown + + + + + Uploading + + + + + TreeStyle_RDM + + + + FILE + + + + + Files + + + + + File + + + + + + DIR + + + + + Friends Directories + + + + + My Directories + + + + + Size + + + + + Age + + + + + Friend + + + + + Share Type + + + + + What's new + + + + + TrustView + + + Zoom : + + + + + Update + + + + + + Showing: whole network + + + + + This table normaly auto-updates every 10 seconds. + + + + + Self + + + + + Trust + + + + + is authenticated (one way) by + + + + + Half + + + + + authenticated himself + + + + + authenticated each other + + + + + Full + + + + + + peers, including him(her)self. + + + + + is authenticated by + + + + + authenticated + + + + + Showing: peers connected to + + + + + TurtleRouterDialog + + + + Search requests + + + + + + Tunnel requests + + + + + TurtleRouterDialogForm + + + Router Statistics + + + + + F2F router information + + + + + TurtleRouterStatistics + + + Router Statistics + + + + + TurtleRouterStatisticsWidget + + + Turtle router traffic: + + + + + Tunnel requests Up + + + + + Tunnel requests Dn + + + + + Incoming file data + + + + + Outgoing file data + + + + + Forwarded data + + + + + ULListDelegate + + + B + + + + + KB + + + + + MB + + + + + GB + + + + + VMessageBox + + + OK + + + + + Cancel + + + + + Yes + + + + + No + + + + + Help + + + + + Retry + + + + + Show Log + + + + + Show Settings + + + + + Continue + + + + + Quit + + + + + Browse + + + + + misc + + + Unknown + Unknown (size) + + + + + B + bytes + + + + + KiB + kibibytes (1024 bytes) + + + + + MiB + mebibytes (1024 kibibytes) + + + + + GiB + gibibytes (1024 mibibytes) + + + + + TiB + tebibytes (1024 gibibytes) + + + + + Unknown + + + + + < 1m + < 1 minute + + + + + %1 minutes + e.g: 10minutes + + + + + %1d %2h + e.g: 2days 10hours + + + + + %1y %2d + e.g: 2 years 2days + + + + + k + e.g: 3.1 k + + + + + M + e.g: 3.1 M + + + + + G + e.g: 3.1 G + + + + + T + e.g: 3.1 T + + + + + %1h %2m + e.g: 3hours 5minutes + + + + diff --git a/retroshare-gui/src/license/license-FR.txt b/retroshare-gui/src/license/license-FR.txt new file mode 100644 index 000000000..b64a4d91d --- /dev/null +++ b/retroshare-gui/src/license/license-FR.txt @@ -0,0 +1,336 @@ +GPL + +Introduction +This is an unofficial translation of the GNU General Public License into French. +It was not published by the Free Software Foundation, and does not legally state +the distribution terms for software that uses the GNU GPL--only the original +English text of the GNU GPL does that. However, we hope that this translation +will help French speakers understand the GNU GPL better. + +Voici (http://www.linux-france.org/article/these/gpl.html) une adaptation non +officielle de la Licence Publique Gnrale du projet GNU. Elle n'a pas t +publie par la Free Software Foundation et son contenu n'a aucune porte lgale +car seule la version anglaise de ce document dtaille le mode de distribution +des logiciels sous GNU GPL. Nous esprons cependant qu'elle permettra aux +francophones de mieux comprendre la GPL. + +Licence Publique Gnrale GNU Version 2, Juin 1991 +Copyright Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 +tats-Unis, 1989, 1991. +La copie et la distribution de copies exactes de ce document sont autorises, +mais aucune modification n'est permise. + +Prambule +Les licences d'utilisation de la plupart des programmes sont dfinies pour +limiter ou supprimer toute libert l'utilisateur. l'inverse, la Licence +Publique Gnrale (General Public License) est destine vous garantir la +libert de partager et de modifier les logiciels libres, et de s'assurer que ces +logiciels sont effectivement accessibles tout utilisateur. + +Cette Licence Publique Gnrale s'applique la plupart des programmes de la +Free Software Foundation, comme tout autre programme dont l'auteur l'aura +dcid (d'autres logiciels de la FSF sont couverts pour leur part par la Licence +Publique Gnrale pour Bibliothques GNU (LGPL)). Vous pouvez aussi appliquer +les termes de cette Licence vos propres programmes, si vous le dsirez. + +Libert des logiciels ne signifie pas ncessairement gratuit. Notre Licence est +conue pour vous assurer la libert de distribuer des copies des programmes, +gratuitement ou non, de recevoir le code source ou de pouvoir l'obtenir, de +modifier les programmes ou d'en utiliser des lments dans de nouveaux +programmes libres, en sachant que vous y tes autoris. + +Afin de garantir ces droits, nous avons d introduire des restrictions +interdisant quiconque de vous les refuser ou de vous demander d'y renoncer. +Ces restrictions vous imposent en retour certaines obligations si vous +distribuez ou modifiez des copies de programmes protgs par la Licence. En d'autre +termes, il vous incombera en ce cas de : + +transmettre aux destinataires tous les droits que vous possdez, + +expdier aux destinataires le code source ou bien tenir celui-ci leur +disposition, + +leur remettre cette Licence afin qu'ils prennent connaissance de leurs droits. + +Nous protgeons vos droits de deux faons : d'abord par le copyright du logiciel, +ensuite par la remise de cette Licence qui vous autorise lgalement copier, +distribuer et/ou modifier le logiciel. + +En outre, pour protger chaque auteur ainsi que la FSF, nous affirmons +solennellement que le programme concern ne fait l'objet d'aucune garantie. Si +un tiers le modifie puis le redistribue, tous ceux qui en recevront une copie +doivent savoir qu'il ne s'agit pas de l'original afin qu'une copie dfectueuse n'entache +pas la rputation de l'auteur du logiciel. + +Enfin, tout programme libre est sans cesse menac par des dpts de brevets. +Nous souhaitons tout prix viter que des distributeurs puissent dposer des +brevets sur les Logiciels Libres pour leur propre compte. Pour viter cela, nous +stipulons bien que tout dpt ventuel de brevet doit accorder expressment +tout un chacun le libre usage du produit. + +Les dispositions prcises et les conditions de copie, de distribution et de +modification de nos logiciels sont les suivantes : + +Stipulations et conditions relatives la copie, la distribution et la +modification + +Article 0 +La prsente Licence s'applique tout Programme (ou autre travail) o figure une +note, place par le dtenteur des droits, stipulant que ledit Programme ou +travail peut tre distribu selon les termes de la prsente Licence. Le terme +Programme dsigne aussi bien le Programme lui-mme que tout travail qui en est +driv selon la loi, c'est--dire tout ouvrage reproduisant le Programme ou une +partie de celui-ci, l'identique ou bien modifi, et/ou traduit dans une autre +langue (la traduction est considre comme une modification). Chaque personne +concerne par la Licence Publique Gnrale sera dsigne par le terme Vous. + +Les activits autres que copie, distribution et modification ne sont pas +couvertes par la prsente Licence et sortent de son cadre. Rien ne restreint l'utilisation +du Programme et les donnes issues de celui-ci ne sont couvertes que si leur +contenu constitue un travail bas sur le logiciel (indpendemment du fait d'avoir +t ralis en lanant le Programme). Tout dpend de ce que le Programme est +cens produire. + +Article 1. +Vous pouvez copier et distribuer des copies conformes du code source du +Programme, tel que Vous l'avez reu, sur n'importe quel support, condition de +placer sur chaque copie un copyright appropri et une restriction de garantie, +de ne pas modifier ou omettre toutes les stipulations se rfrant la prsente +Licence et la limitation de garantie, et de fournir avec toute copie du +Programme un exemplaire de la Licence. + +Vous pouvez demander une rtribution financire pour la ralisation de la copie +et demeurez libre de proposer une garantie assure par vos soins, moyennant +finances. + +Article 2. +Vous pouvez modifier votre copie ou vos copies du Programme ou partie de celui-ci, +ou d'un travail bas sur ce Programme, et copier et distribuer ces modifications +selon les termes de l'article 1, condition de Vous conformer galement aux +conditions suivantes : + +a) Ajouter aux fichiers modifis l'indication trs claire des modifications +effectues, ainsi que la date de chaque changement. + +b) Distribuer sous les termes de la Licence Publique Gnrale l'ensemble de +toute ralisation contenant tout ou partie du Programme, avec ou sans +modifications. + +c) Si le Programme modifi lit des commandes de manire interactive lors de son +excution, faire en sorte qu'il affiche, lors d'une invocation ordinaire, le +copyright appropri en indiquant clairement la limitation de garantie (ou la +garantie que Vous Vous engagez fournir Vous-mme), qu'il stipule que tout +utilisateur peut librement redistribuer le Programme selon les conditions de la +Licence Publique Gnrale GNU, et qu'il montre tout utilisateur comment lire +une copie de celle-ci (exception : si le Programme original est interactif mais +n'affiche pas un tel message en temps normal, tout travail driv de ce +Programme ne sera pas non plus contraint de l'afficher). + +Toutes ces conditions s'appliquent l'ensemble des modifications. Si des +lments identifiables de ce travail ne sont pas drivs du Programme et peuvent +tre raisonnablement considrs comme indpendants, la prsente Licence ne s'applique +pas ces lments lorsque Vous les distribuez seuls. Mais, si Vous distribuez +ces mmes lments comme partie d'un ensemble cohrent dont le reste est bas +sur un Programme soumis la Licence, ils lui sont galement soumis, et la +Licence s'tend ainsi l'ensemble du produit, quel qu'en soit l'auteur. + +Cet article n'a pas pour but de s'approprier ou de contester vos droits sur un +travail entirement ralis par Vous, mais plutt d'ouvrir droit un contrle +de la libre distribution de tout travail driv ou collectif bas sur le +Programme. + +En outre, toute fusion d'un autre travail, non bas sur le Programme, avec le +Programme (ou avec un travail driv de ce dernier), effectue sur un support de +stockage ou de distribution, ne fait pas tomber cet autre travail sous le +contrle de la Licence. + +Article 3. +Vous pouvez copier et distribuer le Programme (ou tout travail driv selon les +conditions nonces dans l'article 1) sous forme de code objet ou excutable, +selon les termes des articles 0 et 1, condition de respecter les clauses +suivantes : + +a) Fournir le code source complet du Programme, sous une forme lisible par un +ordinateur et selon les termes des articles 0 et 1, sur un support +habituellement utilis pour l'change de donnes ; ou, + +b) Faire une offre crite, valable pendant au moins trois ans, prvoyant de +donner tout tiers qui en fera la demande une copie, sous forme lisible par un +ordinateur, du code source correspondant, pour un tarif n'excdant pas le cot +de la copie, selon les termes des articles 0 et 1, sur un support couramment +utilis pour l'change de donnes informatiques ; ou, + +c) Informer le destinataire de l'endroit o le code source peut tre obtenu (cette +solution n'est recevable que dans le cas d'une distribution non commerciale, et +uniquement si Vous avez reu le Programme sous forme de code objet ou excutable +avec l'offre prvue l'alina b ci-dessus). + +Le code source d'un travail dsigne la forme de cet ouvrage sous laquelle les +modifications sont les plus aises. Sont ainsi dsigns la totalit du code +source de tous les modules composant un Programme excutable, de mme que tout +fichier de dfinition associ, ainsi que les scripts utiliss pour effectuer la +compilation et l'installation du Programme excutable. Toutefois, l'environnement +standard de dveloppement du systme d'exploitation mis en oeuvre (source ou +binaire) -- compilateurs, bibliothques, noyau, etc. -- constitue une exception, +sauf si ces lments sont diffuss en mme temps que le Programme excutable. + +Si la distribution de l'excutable ou du code objet consiste offrir un accs +permettant de copier le Programme depuis un endroit particulier, l'offre d'un +accs quivalent pour se procurer le code source au mme endroit est considr +comme une distribution de ce code source, mme si l'utilisateur choisit de ne +pas profiter de cette offre. + +Article 4. +Vous ne pouvez pas copier, modifier, cder, dposer ou distribuer le Programme d'une +autre manire que l'autorise la Licence Publique Gnrale. Toute tentative de ce +type annule immdiatement vos droits d'utilisation du Programme sous cette +Licence. Toutefois, les tiers ayant reu de Vous des copies du Programme ou le +droit d'utiliser ces copies continueront bnficier de leur droit d'utilisation +tant qu'ils respecteront pleinement les conditions de la Licence. + +Article 5. +Ne l'ayant pas signe, Vous n'tes pas oblig d'accepter cette Licence. +Cependant, rien d'autre ne Vous autorise modifier ou distribuer le Programme +ou quelque travaux drivs : la loi l'interdit tant que Vous n'acceptez pas les +termes de cette Licence. En consquence, en modifiant ou en distribuant le +Programme (ou tout travail bas sur lui), Vous acceptez implicitement tous les +termes et conditions de cette Licence. + +Article 6. +La diffusion d'un Programme (ou de tout travail driv) suppose l'envoi +simultan d'une licence autorisant la copie, la distribution ou la modification +du Programme, aux termes et conditions de la Licence. Vous n'avez pas le droit d'imposer +de restrictions supplmentaires aux droits transmis au destinataire. Vous n'tes +pas responsable du respect de la Licence par un tiers. + +Article 7. +Si, la suite d'une dcision de Justice, d'une plainte en contrefaon ou pour +toute autre raison (lie ou non la contrefaon), des conditions Vous sont +imposes (que ce soit par ordonnance, accord amiable ou autre) qui se rvlent +incompatibles avec les termes de la prsente Licence, Vous n'tes pas pour +autant dgag des obligations lies celle-ci : si Vous ne pouvez concilier vos +obligations lgales ou autres avec les conditions de cette Licence, Vous ne +devez pas distribuer le Programme. + +Si une partie quelconque de cet article est invalide ou inapplicable pour +quelque raison que ce soit, le reste de l'article continue de s'appliquer et l'intgralit +de l'article s'appliquera en toute autre circonstance. + +Le prsent article n'a pas pour but de Vous pousser enfreindre des droits ou +des dispositions lgales ni en contester la validit ; son seul objectif est de +protger l'intgrit du systme de distribution du Logiciel Libre. De nombreuses +personnes ont gnreusement contribu la large gamme de Programmes distribue +de cette faon en toute confiance ; il appartient chaque auteur/donateur de +dcider de diffuser ses Programmes selon les critres de son choix. + +Article 8. +Si la distribution et/ou l'utilisation du Programme est limite dans certains +pays par des brevets ou des droits sur des interfaces, le dtenteur original des +droits qui place le Programme sous la Licence Publique Gnrale peut ajouter +explicitement une clause de limitation gographique excluant ces pays. Dans ce +cas, cette clause devient une partie intgrante de la Licence. + +Article 9. +La Free Software Foundation se rserve le droit de publier priodiquement des +mises jour ou de nouvelles versions de la Licence. Rdiges dans le mme +esprit que la prsente version, elles seront cependant susceptibles d'en +modifier certains dtails mesure que de nouveaux problmes se font jour. + +Chaque version possde un numro distinct. Si le Programme prcise un numro de +version de cette Licence et toute version ultrieure , Vous avez le choix de +suivre les termes et conditions de cette version ou de toute autre version plus +rcente publie par la Free Software Foundation. Si le Programme ne spcifie +aucun numro de version, Vous pouvez alors choisir l'une quelconque des versions +publies par la Free Software Foundation. + +Article 10. +Si Vous dsirez incorporer des lments du Programme dans d'autres Programmes +libres dont les conditions de distribution diffrent, Vous devez crire l'auteur +pour lui en demander la permission. Pour ce qui est des Programmes directement +dposs par la Free Software Foundation, crivez-nous : une exception est +toujours envisageable. Notre dcision sera base sur notre volont de prserver +la libert de notre Programme ou de ses drivs et celle de promouvoir le +partage et la rutilisation du logiciel en gnral. + +LIMITATION DE GARANTIE + +Article 11. +Parce que l'utilisation de ce Programme est libre et gratuite, aucune garantie n'est +fournie, comme le permet la loi. Sauf mention crite, les dtenteurs du +copyright et/ou les tiers fournissent le Programme en l'tat, sans aucune sorte +de garantie explicite ou implicite, y compris les garanties de commercialisation +ou d'adaptation dans un but particulier. Vous assumez tous les risques quant +la qualit et aux effets du Programme. Si le Programme est dfectueux, Vous +assumez le cot de tous les services, corrections ou rparations ncessaires. + +Article 12. +Sauf lorsqu'explicitement prvu par la Loi ou accept par crit, ni le dtenteur +des droits, ni quiconque autoris modifier et/ou redistribuer le Programme +comme il est permis ci-dessus ne pourra tre tenu pour responsable de tout +dommage direct, indirect, secondaire ou accessoire (pertes financires dues au +manque gagner, l'interruption d'activits ou la perte de donnes, etc., +dcoulant de l'utilisation du Programme ou de l'impossibilit d'utiliser celui-ci). + +FIN DES TERMES ET CONDITIONS + +Comment appliquer ces directives vos nouveaux programmes +Si vous dveloppez un nouveau programme et dsirez en faire bnficier tout un +chacun, la meilleure mthode est d'en faire un Logiciel Libre que tout le monde +pourra redistribuer et modifier selon les termes de la Licence Publique Gnrale. + +Pour cela, insrez les indications suivantes dans votre programme (il est +prfrable et plus sr de les faire figurer au dbut de chaque fichier source ; +dans tous les cas, chaque module source devra comporter au minimum la ligne de +copyright et indiquer o rsident toutes les autres indications) : + +((une ligne pour donner le nom du programme et donner une ide de sa finalit)) +Copyright (C) 19xx ((nom de l'auteur)) + +Ce programme est libre, vous pouvez le redistribuer et/ou le modifier selon les +termes de la Licence Publique Gnrale GNU publie par la Free Software +Foundation (version 2 ou bien toute autre version ultrieure choisie par vous). + +Ce programme est distribu car potentiellement utile, mais SANS AUCUNE GARANTIE, +ni explicite ni implicite, y compris les garanties de commercialisation ou d'adaptation +dans un but spcifique. Reportez-vous la Licence Publique Gnrale GNU pour +plus de dtails. + +Vous devez avoir reu une copie de la Licence Publique Gnrale GNU en mme +temps que ce programme ; si ce n'est pas le cas, crivez la Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, tats-Unis. + +Ajoutez galement votre adresse lectronique, le cas chant, ainsi que votre +adresse postale. + +Si le programme est interactif, faites-lui afficher un court avertissement du +type de celui-ci chaque invocation : + +...(nom du programme) version 69, Copyright (C) 19aa nom de l'auteur + +...(nom du programme) est fourni sans AUCUNE GARANTIE. +Pour plus de dtails, tapez `g'. + +Ce programme est libre et vous tes encourag le redistribuer sous certaines +conditions ; tapez `c' pour plus de dtails. + +Les commandes hypothtiques `g' et `c' doivent afficher les sections appropries +de la Licence Publique Gnrale GNU. Bien entendu, vous pouvez implanter ces +commandes comme bon vous semble : options dans un menu, ou bien accessibles d'un +clic de souris, etc., tout dpend de votre programme. + +Si vous officiez en tant que programmeur, n'omettez pas de demander votre +employeur, votre tablissement scolaire ou autres de signer une dcharge +stipulant leur renoncement aux droits qu'ils pourraient avoir sur le programme : + +...((employeur, cole...)) dclare par la prsente ne pas revendiquer de droits +sur le programme (nom du programme) ralis par ...((nom de l'auteur)). +((signature du responsable)), ...((date)), ...((nom et qualit du responsable)). + +La Licence Publique Gnrale ne permet pas d'inclure votre programme dans des +logiciels sous licence commerciale spcifique. Si votre programme est une +fonction de bibliothque, vous jugerez probablement plus judicieux de le faire +relever de la Licence Gnrale de Bibliothque GNU (LGPL) plutt que de la +prsente. + +Last modified: Tue Sep 29 22:41:45 MET DST 1998 \ No newline at end of file diff --git a/retroshare-gui/src/license/license-GER.txt b/retroshare-gui/src/license/license-GER.txt new file mode 100644 index 000000000..58f771516 --- /dev/null +++ b/retroshare-gui/src/license/license-GER.txt @@ -0,0 +1,88 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + +a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + +b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + +c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + +b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + +c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + +Ende der Bedingungen diff --git a/retroshare-gui/src/license/license-TR.txt b/retroshare-gui/src/license/license-TR.txt new file mode 100644 index 000000000..9c4816a4a --- /dev/null +++ b/retroshare-gui/src/license/license-TR.txt @@ -0,0 +1,354 @@ +Bu, GNU Genel Kamu Lisansnn (GPL) Trke'ye gayrresmi evirisidir. Bu eviri +Free Software Foundation tarafndan yaynlanmam olup GNU GPL kullanan +yazlmlarn datm artlarn belirleme asndan hukuki balaycl yoktur +-- Hukuki adan yalnzca GNU GPL'in ngilizce metni balaycdr. Bu eviri, +Trke kullanclarnn GNU GPL'i daha iyi anlayabilmeleri iin hazrlanmtr. + +GNU Genel Kamu Lisans (GPL) + +Srm 2, Haziran 1991 + +Telif Hakk 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite +330, Boston, MA 02111-1307, USA + +Bu lisans dkmannn birebir kopyalarn yapma ve datma izni herkese +verilmitir, fakat metinde deiiklik yapma izni yoktur. + +GR + +Yazlm lisanslarnn ou sizin yazlm paylama ve deitirme hakknzn +elinizden alnmas iin hazrlanmtr. Buna karlk, GNU Genel Kamu Lisans +sizin serbest yazlmlar deitirme ve paylama hakknzn mahfuz tutulmas ve +yazlmn btn kullanclar iin serbest olmas amac ile yazlmtr. Bu +Genel Kamu Lisans, Free Software Foundation'un ou yazlm ve bu lisans +kullanmay dstur edinen dier yazlmclarn yazlmlar iin kullanlmaktadr. +(Free Software Foundation'un baz yazlmlar GNU Kitaplk Genel Kamu Lisans -- +GNU LGPL -- altnda datlmaktadr.) Siz de bu lisans yazlmlarnza +uygulayabilirsiniz. + +Serbest yazlmdan bahsettiimiz zaman fiyattan deil, zgrlkten bahsediyoruz. +Bizim Genel Kamu Lisanslarmz, sizin serbest yazlmlarn kopyalarn datma +zgrlnz (ve isterseniz bu hizmet iin para almanz), yazlm kaynak +kodlarnn size datm esnasnda veya eer isterseniz verilmesini, yazlm +deitirebilmenizi, yazlmn paralarn yeni yazlmlar ierisinde +kullanabilmenizi ve bunlar yapabileceinizi bilmenizi salamaktadr. + +Haklarnz koruyabilmemiz iin sizin haklarnz kstlama veya sizin bu +haklarnzdan feragat etmenizi isteme yollarn yasaklayc baz kstlamalar +getirmemiz gerekmektedir. Bu kstlamalar eer serbest yazlm datyor veya +deitiriyorsanz size baz ykmllkler getirmektedir. + +rnein byle bir programn kopyalarn, bedava veya cret karl +datyorsanz alclara sizin sahip olduunuz btn haklar salamalsnz. +Onlarn da kaynak kodlarna sahip olmalarn veya ulaabilmelerini +salamalsnz. Onlara da haklarn bilebilmeleri iin bu artlar +gstermelisiniz. + +Haklarnz iki koruma iki aamada gereklemektedir: + +Yazlma telif hakk alnmaktadr. + +Yazlm lisans olarak size, hukuki olarak, yazlm kopyalama, datma ve/veya +deitirme hakk tanyan bu lisans sunulmaktadr. + +Ayrca, yazarlarn ve bizim korunmamz iin bu serbest yazlmn herhangi bir +garantisi olmadn herkesin anlamasn istiyoruz. Eer yazlm bakas +tarafndan deitirilmi ve deitirilmi hali ile tarafnza ulatrlm ise +alclarn, ellerinde olan yazlmn orjinal olmadn, dolaysyla bakalar +tarafndan eklenen problemlerin ilk yazarlarn hretlerine olumsuz etkide +bulunmamas gerektiini bilmelerini istiyoruz. + +Son olarak, btn serbest yazlmlar yazlm patentleri tarafndan srekli +tehdit altnda bulunmaktadr. Serbest bir yazlmn datclarnn bireysel +olarak patent lisans almalarn ve bu yol ile yazlm mseccel hale +getirmelerine imkan vermemek istiyoruz. Bunu engellemek iin, yazlm iin +alnacak her patentin herkesin serbest kullanmna izin vermesi veya +patentlenmemesi gerektiini ak olarak ortaya koyuyoruz. + +Kopyalama, datm ve deitirme ile ilgili kesin art ve kaytlar aada yer +almaktadr. + +KOPYALAMA, DAITIM VE DETRME LE LGL ART VE KAYITLAR + +0. Bu Lisans, telif hakk sahibi tarafndan ierisine bu Genel Kamu Lisans +altnda datldna dair ibare konmu olan herhangi bir yazlm veya baka +eseri kapsamaktadr. Aada "Yazlm", bu kapsamdaki herhangi bir yazlm veya +eser, "Yazlm baz alan rn", ise Yazlm veya telif kanunu altnda Yazlm'dan +itikak etmi, yani Yazlm'n tamamn veya bir parasn, deitirmeden veya +deiiklikler ile, veya baka bir dile tercme edilmi hali ile ieren herhangi +bir rn, manasnda kullanlmaktadr. (Bundan sonra tercme "deitirme" +kapsamnda snrsz olarak ierilecektir.) Her ruhsat sahibine "siz" olarak +hitap edilmektedir. + +Kopyalama, datm ve deitirme haricinde kalan faaliyetler bu Lisans'n +kapsam dndadrlar. Yazlm' altrma eylemi snrlandrlmamtr ve +Yazlm'n kts yalnzca ktnn ierii (Yazlm' altrmak yolu ile +elde edilmesinden bamsz olarak) Yazlm' baz alan rn kapsamna girer ise +bu Lisans kapsamndadr. Bu koulun salanp salanmad Yazlm'n ne yapt +ile ilgilidir. + +1. Yazlm'n kaynak kodlarn birebir, aldnz ekilde, herhangi bir ortamda +ve vasta ile, uygun ve grnr bir ekilde telif hakk bildirimi ve garantisiz +olduuna dair bildirim koymak, bu Lisans'dan bahseden herhangi bir bildirimi +aynen muhafaza etmek ve btn dier alclara Yazlm ile birlikte bu Lisans'n +bir kopyasn vermek art ile kopyalayabilir ve databilirsiniz. + +Kopyalamak fiili ilemi iin bir cret talep edebilir ve sizin seiminize bal +olarak cret karl garanti verebilirsiniz. + +2. Yazlm'n kopyasn veya kopyalarn veya herhangi bir parasn +deitirerek Yazlm' baz alan rn elde edebilir, bu deiiklikleri veya +rnn kendisini yukarda 1. blmdeki artlar dahilinde ve aada sralanan +artlarn yerine getirilmesi koulu ile kopyalayabilir ve databilirsiniz. + +a) Deitirilen dosyalarn grnr bir ekilde dosyalarn sizin tarafnzdan +deitirildiine dair, tarihli bir bildirim iermesini salamalsnz. + +b) Yazlm'dan veya Yazlm'n bir parasndan tamamen veya ksmen itikak etmi +ve sizin tarafnzdan datlan veya yaynlanan herhangi bir rnn btn nc +ahslara bu Lisans artlar altnda cretsiz olarak ruhsatlanmasn +salamalsnz. + +c) Eer deitirilen yazlm olaan kullanm altnda komutlar interaktif olarak +alyor ise, yazlm, en olaan kullanm iin interaktif olarak altrld +zaman uygun bir telif hakk bildirimi, garantisi olmadna (veya sizin +tarafnzdan garanti verildiine), kullanclarn bu yazlm bu artlar altnda +tekrar databileceklerine, ve kullancnn bu Lisansn bir kopyasn nasl +grebileceine dair bir bildirim yazdrmal veya gstermelidir. (stisna: Eer +Yazlm'n kendisi interaktif ise fakat byle bir bildirimi olaan kullanm +esnasnda yazdrmyor ise, sizin Yazlm' baz alan rnnz byle bir +bildirimde bulunmak zorunda deildir.) + +Bu artlar deitirilmi eserin tamamn kapsamaktadr. Eer eserin tespit +edilebilir ksmlar Yazlm'dan itikak etmemi ise ve makul surette kendi +balarna bamsz ve ayr eserler olarak kabul edilebilir ise, o zaman bu +Lisans ve artlar, bu paralar ayr eser olarak dattnz zaman balayc +deildir. Fakat, ayn paralar Yazlm' baz alan bir rn btnnn bir +paras olarak dattnz zaman btnn datm, dier ruhsat sahiplerine +verilen izinlerin btne ait olduu ve paralarna, yazarnn kim olduuna +baklmakszn btn paralarna tek tek ve mterek olarak uyguland bu Lisans +artlarna uygun olmaldr. + +Bu blmn hedefi tamamen sizin tarafnzdan yazlan bir eser zerinde hak iddia +etmek veya sizin byle bir eser zerindeki haklarnza muhalefet etmek deil, +Yazlm' baz alan, Yazlm'dan itikak etmi veya mterek olarak ortaya +karlm eserlerin datmn kontrol etme haklarn dzenlemektir. + +Buna ek olarak, Yazlm' baz almayan herhangi bir rnn Yazlm ile (veya +Yazlm' baz alan bir rn ile) bir bilgi saklama ortamnda veya bir datm +ortamnda beraber tutulmas dier eseri bu Lisans kapsamna sokmaz. + +3. Yazlm' ( veya 2. blmde tanmland hali ile onu baz alan bir rn) ara +derlenmi veya uygulama hali ile 1. ve 2. Blm'deki artlar dahilinde ve +aada sralanan yntemlerden birisine uygun olarak kopyalayabilir ve +databilirsiniz. + +a) Yaygn olarak yazlm datmnda kullanlan bir ortam zerinde, yukarda 1. +ve 2. Blm'de bulunan artlar dahilinde, bilgisayar tarafndan okunabilir +kaynak kodlarnn tamam ile birlikte datmak. + +b)Herhangi bir nc ahsa, fiziksel olarak datm gerekletirme +masrafnzdan daha fazla cret almayarak, yaygn olarak yazlm datmnda +kullanlan bir ortam zerinde, yukarda 1. ve 2. Blm'de bulunan artlar +dahilinde, bilgisayar tarafndan okunabilir kaynak kodlarnn tamamn +datacanza dair en az yl geerli olacak yazl bir taahhtname ile +birlikte datmak. + +c)Size verilmi olan ilgili kaynak kodunu datma taahhtnamesi ile birlikte +datmak. (Bu alternatif yalnzca ticari olmayan datmlar iin ve yalnzca siz +de yazlm ara derlenmi veya uygulama bieminde ve yukarda b) blmnde +anlatlan ekli ile bir taahhtname ile birlikte alm iseniz geerlidir.) + +Bir eserin kaynak kodu, esere deitirme yapmak iin en uygun yntem ve imkan +anlamnda kullanlmaktadr. Uygulama bieminde bir eser iin, kaynak kodu, +ierdii btn paralar iin ilgili kaynak kodlar, ilgili arayz tanm +dosyalar ve derleme ve ykleme ilemlerinde kullanlan btn betikler anlamnda +kullanlmaktadr. Bir istisna olarak, datlan kaynak kodu, genelde uygulamann +zerinde alaca iletim sisteminin ana paralar (derleyici, ekirdek v.b.) +ile birlikte datlan herhangi bir bileeni,eer ilgili bileen, uygulama ile +birlikte datlmyorsa, iermek zorunda deildir. + +Eer uygulama veya ara derlenmi biemde yazlmn datm belli bir yere +eriim ve oradan kopyalama imkan olarak yaplyorsa, ayn yerden, ayn koullar +altnda kaynak koduna eriim imkan salamak, nc ahslarn ara derlenmi ve +uygulama biemleri ile birlikte kaynak kodunu kopyalama zorunluluklar olmasa +bile kaynak kodunu datmak olarak kabul edilmektedir. + +4. Yazlm' bu Lisans'ta sarih olarak belirtilen artlar haricinde kopyalayamaz, +deitiremez, ruhsat hakkn veremez ve datamazsnz. Buna aykr herhangi bir +kopyalama, deitirme, ruhsat hakk verme, veya datmda bulunma hkmszdr ve +byle bir teebbs halinde bu Lisans altndaki btn haklarnz iptal edilir. +Sizden, bu Lisans kapsamnda kopya veya hak alm olan nc ahslar, Lisans +artlarna uygunluklarn devam ettirdikleri srece, ruhsat haklarn muhafaza +edeceklerdir. + +5. Bu Lisans sizin tarafnzdan imzalanmad iin bu Lisans' kabul etmek +zorunda deilsiniz. Fakat, size Yazlm' veya onu baz alan rnleri deitirmek +veya datmak iin izin veren baka bir belge yoktur. Eer bu Lisans' kabul +etmiyorsanz bu eylemler kanun tarafndan sizin iin yasaklanmtr. Dolaysyla, +Yazlm' (veya onu baz alan bir rn) deitirmeniz veya datmanz bu Lisans' +ve Lisans'n Yazlm' veya ondan itikak etmi btn eserleri kopyalamak, +deitirmek ve datmak iin getirdii art ve kaytlar kabul ettiiniz +manasna gelmektedir. + +6. Yazlm' (veya onu baz alan herhangi bir rn) yeniden dattnz her +defada alc, ilk ruhsat sahibinden otomatik olarak Yazlm' bu artlar ve +kaytlar dahilinde kopyalamak, deitirmek ve datmak iin ruhsat almaktadr. +Alcnn burada verilen haklar kullanmasna ek bir takm kstlamalar +getiremezsiniz. nc ahslar bu Lisans mucibince hareket etmee mecbur etmek +sizin sorumluluk ve ykmllnz altnda deildir. + +7. Eer bir mahkeme karar veya patent ihlal iddias veya herhangi baka bir (patent +meseleleri ile snrl olmayan) sebep sonucunda size, bu Lisans'n art ve +kaytlarna aykr olan bir takm (mahkeme karar, zel anlama veya baka bir +ekilde) kstlamalar getirilirse, bu sizi bu Lisans art ve kaytlarna uyma +mecburiyetinden serbest brakmaz. Eer ayn anda hem bu Lisans'n artlarn +yerine getiren hem de dier kstlamalara uygun olan bir ekilde Yazlm' +datamyorsanz, o zaman Yazlm' datamazsnz. rnein, eer bir patent +lisans direkt veya endirekt olarak sizden kopya alacak olan nc ahslarn +bedel demeksizin Yazlm' datmalarna hak tanmyorsa o zaman sizin hem bu +koulu hem Lisans koullarn yerine getirmenizin tek yolu Yazlm' datmamak +olacaktr. + +Eer bu blmn herhangi bir paras herhangi bir art altnda uygulanamaz veya +hatal bulunur ise o artlar dahilinde blmn geri kalan ksm, btn dier +artlar altnda da blmn tamam geerlidir. + +Bu blmn amac sizin patent haklarn, herhangi bir mlkiyet hakkn ihlal +etmenize yol amak veya bu haklarn geerliliine muhalefet etmenizi salamak +deildir; bu blmn btn amac kamu lisans uygulamalar ile oluturulan +serbest yazlm datm sisteminin btnln ve ilerliini korumaktr. Bu +sistemin tutarl uygulanmasna dayanarak pek ok kii bu sistemle datlan +geni yelpazedeki yazlmlara katkda bulunmutur; yazlmn bu veya baka bir +sistemle datmak karar yazara aittir, herhangi bir kullanc bu karar veremez. + +Bu blm Lisans'n geri kalannn dourduu sonularn ne olduunu akla +kavuturmak amacn gtmektedir. + +8. Eer Yazlm'n kullanm ve/veya datm baz lkelerde telif hakk tayan +arayzler veya patentler yznden kstlanrsa, Yazlm' bu Lisans kapsamna +ilk koyan telif hakk sahibi, Yazlm'n yalnzca bu lkeler haricinde +datlabileceine dair ak bir corafi datm kstlamas koyabilir. Byle +bir durumda bu Lisans bu kstlamay sanki Lisans'n ierisine yazlm gibi +kapsar. + +9. Free Software Foundation zaman zaman Genel Kamu Lisans'nn yeni ve/veya +deitirilmi biimlerini yaynlayabilir. Byle yeni srmler mana olarak +imdiki haline benzer olacaktr, fakat doacak yeni problemler veya kayglara +cevap verecek ekilde detayda farkllk arzedebilir. + +Her yeni biime ayrdedici bir srm numaras verilmektedir. Eer Yazlm bir +srm numaras belirtiyor ve "bu ve bundan sonraki srmler" altnda +datlyorsa, belirtilen srm veya Free Software Foundation tarafndan +yaynlanan herhangi sonraki bir srmn art ve kaytlarna uymakta serbestsiniz. +Eer Yazlm Lisans iin bir srm numaras belirtmiyor ise, Free Software +Foundation tarafndan yaynlanm olan herhangi bir srmn art ve kaytlarna +uymakta serbestsiniz. + +10. Eer bu Yazlm'n paralarn datm koullar farkl olan baka serbest +yazlmlarn ierisinde kullanmak isterseniz, yazara sorarak izin isteyin. Telif +hakk Free Software Foundation'a ait olan yazlmlar iin Free Software +Foundation'a yazn, bazen istisnalar kabul edilmektedir. Kararmz, serbest +yazlmlarmzdan itikak etmi yazlmlarn serbest statlerini korumak ve +genel olarak yazlmlarn yeniden kullanlabilirliini ve paylamn salamak +amalar dorultusunda ekillenecektir. + +GARANT YOKTUR + +11. BU YAZILIM CRETSZ OLARAK RUHSATLANDII N, YAZILIM N LGL +KANUNLARIN ZN VERD LDE HERHANG BR GARANT VERLMEMEKTEDR. AKS YAZILI +OLARAK BELRTLMED MDDETE TELF HAKKI SAHPLER VE/VEYA BAKA AHISLAR +YAZILIMI "OLDUU GB", AKAR VEYA ZIMNEN, SATILABLRL VEYA HERHANG BR +AMACA UYGUNLUU DA DAHL OLMAK ZERE HBR GARANT VERMEKSZN DAITMAKTADIRLAR. +YAZILIMIN KALTES VEYA PERFORMANSI LE LGL TM SORUNLAR SZE ATTR. +YAZILIMDA HERHANG BR BOZUKLUKTAN DOLAYI DOABLECEK OLAN BTN SERVS, TAMR +VEYA DZELTME MASRAFLARI SZE ATTR. + +12. LGL KANUNUN CBAR ETT DURUMLAR VEYA YAZILI ANLAMA HARCNDE HERHANG +BR EKLDE TELF HAKKI SAHB VEYA YUKARIDA ZN VERLD EKLDE YAZILIMI +DETREN VEYA YENDEN DAITAN HERHANG BR K, YAZILIMIN KULLANIMI VEYA +KULLANILAMAMASI (VEYA VER KAYBI OLUMASI, VERNN YANLI HALE GELMES, SZN +VEYA NC AHISLARIN ZARARA URAMASI VEYA YAZILIMIN BAKA YAZILIMLARLA BERABER +ALIAMAMASI) YZNDEN OLUAN GENEL, ZEL, DORUDAN YA DA DOLAYLI HERHANG BR +ZARARDAN, BYLE BR TAZMNAT TALEB TELF HAKKI SAHB VEYA LGL KYE +BLDRLM OLSA DAH, SORUMLU DELDR. + +ART VE KAYITLARIN SONU + +Bu artlar Yeni Yazlmlara Nasl Uygulanr + +Eer yeni bir yazlm gelitiriyor ve bunun kamuya en fazla dzeyde yarar +salamasn istiyorsanz, yazlmnz herkesin datp, deitirebilecei zgr +yazlm haline getirmenizi neriyoruz. + +Bu koullar uygulamak iin yazlma aadaki bildirimleri ekleyin. En salkl +yntem her kaynak kodu dosyasnn bana bu bildirimi ekleyerek garanti +olmadna dair bilginin verildiinden emin olmaktr; her dosya en azndan "copyright" +(telif hakk) satrn ve bildirimin tam metninin nerede bulunabileceine dair +bilgi iermelidir. + +{yazlmn adn ve ne yaptn anlatan bir satr.} + +Copyright (C) {yl} {yazarn ad} + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Size normal ve elektronik posta ile nasl ulalabileceine dair bilgi eklemeyi +unutmayn. + +Eer yazlmnz interaktif ise, interaktif kipte balatld zaman gsterilen +ksa bir bildirim koyun. + +Gnomovizyon version 69, Copyright (C) yl yazarn ad +Gnomovizyon comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This +is free software, and you are welcome to redistribute it under certain +conditions; type `show c' for details. + +Gnomovizyon srm 69, Telif hakk (C) yl yazarn ad +Gnomovizyon iin H BR GARANT verilmemektedir; detaylar iin `show w' yazn. +Bu bir serbest yazlmdr ve belli koullar altnda yeniden datlabilir; +detaylar iin `show c' yazn. + +rnekte verilen `show w' ve `show c' komutlar GNU Genel Kamu Lisans'nn ilgili +blmlerini gstermelidir. Elbette kullanlan komutlar daha farkl olabilir veya +yazlmnza uyan baka yntemlerle bu bildirim yaplabilir. + +vereninizin (eer programc olarak alyorsanz) veya, eer renci iseniz, +okulunuzun telif haklarndan feragat ettiklerine dair bir feragatname +imzalamalarn isteyebilirsiniz. Aada bir rnek yer almaktadr, isimleri +deitirin: + +Gereksizler, A.., Mehmet Herhangibiri tarafndan yazlm `AbidikGubidik' +yazlmnda (kapkolu evirmekte kullanlan bir yazlm) olabilecek btn telif +haklarndan feragat eder. + +{Yn Etici mzas}, 1 April 1990 +Yn Etici, Gereksizler Yetkilisi + +Bu Genel Kamu Lisans yazlmnzn serbest olmayan yazlmlarn ierisine dahil +edilmesine imkan tanmaz. Eer yazlmnz bir kitaplk ise, serbest olmayan +yazlmlarn kitaplnza balanmasna imkan tanmak isteyebilirsiniz. Eer +yapmak istediiniz bu ise, bu Lisans yerine GNU Kstl Genel Kamu Lisans'n +kullanabilirsiniz. + +eviren: Deniz Akku Kanca, 2001 +Translated by: Deniz Akku Kanca, 2001 + + +This is an unofficial translation of the GNU General Public License into Turkish. +It was not published by the Free Software Foundation, and does not legally state +the distribution terms for software that uses the GNU GPL--only the original +English text of the GNU GPL does that. However, we hope that this translation +will help Turkish speakers understand the GNU GPL better. + diff --git a/retroshare-gui/src/license/license.txt b/retroshare-gui/src/license/license.txt new file mode 100644 index 000000000..74ba77993 --- /dev/null +++ b/retroshare-gui/src/license/license.txt @@ -0,0 +1,88 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + +a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + +b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + +c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + +b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + +c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp new file mode 100644 index 000000000..d418b7684 --- /dev/null +++ b/retroshare-gui/src/main.cpp @@ -0,0 +1,335 @@ +/**************************************************************** + * RetroShare QT Gui is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include +#ifndef MINIMAL_RSGUI +#include "gui/MainWindow.h" +#include "gui/FriendsDialog.h" +#include "gui/SearchDialog.h" +#include "gui/TransfersDialog.h" +#include "gui/MessagesDialog.h" +#include "gui/SharedFilesDialog.h" +#include "gui/NetworkDialog.h" +#include "gui/chat/PopupChatDialog.h" +#include "gui/QuickStartWizard.h" +#endif // MINIMAL_RSGUI +#include "gui/MessengerWindow.h" +#include "gui/StartDialog.h" +#include "gui/GenCertDialog.h" +#include "gui/settings/rsharesettings.h" +#include "gui/settings/RsharePeerSettings.h" +#include "gui/connect/ConfCertDialog.h" +#include "idle/idle.h" +#include "gui/common/Emoticons.h" +#include "util/EventReceiver.h" +#include "gui/RetroShareLink.h" + +/*** WINDOWS DON'T LIKE THIS - REDEFINES VER numbers. +#include +****/ + +#include +#include +#include +#include "gui/notifyqt.h" + +int main(int argc, char *argv[]) +{ +#ifdef WINDOWS_SYS + { + /* Set the current directory to the application dir, + because the start dir with autostart from the registry run key is not the exe dir */ + QApplication app(argc, argv); + QDir::setCurrent(QCoreApplication::applicationDirPath()); + } +#endif + + QStringList args = char_array_to_stringlist(argv+1, argc-1); + + Q_INIT_RESOURCE(images); + + rsiface = NULL; + + NotifyQt *notify = NotifyQt::Create(); + createRsIface(*notify); + createRsControl(*rsiface, *notify); + + /* RetroShare Core Objects */ + RsInit::InitRsConfig(); + int initResult = RsInit::InitRetroShare(argc, argv); + + if (initResult < 0) { + /* Error occured */ + QApplication dummyApp (argc, argv); // needed for QMessageBox + QMessageBox mb(QMessageBox::Critical, QObject::tr("RetroShare"), "", QMessageBox::Ok); + mb.setWindowIcon(QIcon(":/images/rstray3.png")); + + switch (initResult) { + case RS_INIT_AUTH_FAILED: + std::cerr << "RsInit::InitRetroShare AuthGPG::InitAuth failed" << std::endl; + mb.setText(QObject::tr("Inititialize failed. Wrong or missing installation of gpg.")); + break; + default: + /* Unexpected return code */ + std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl; + mb.setText(QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult)); + break; + } + mb.exec(); + return 1; + } + + /* create global settings object + path maybe wrong, when no profile exist + in this case it can be use only for default values */ + RshareSettings::Create (); + + /* Setup The GUI Stuff */ + Rshare rshare(args, argc, argv, + QString::fromStdString(RsInit::RsConfigDirectory())); + + std::string url = RsInit::getRetroShareLink(); + if (!url.empty()) { + /* start with RetroShare link */ + EventReceiver eventReceiver; + if (eventReceiver.sendRetroShareLink(QString::fromStdString(url))) { + return 0; + } + + /* Start RetroShare */ + } + + QSplashScreen splashScreen(QPixmap(":/images/splash.png")/* , Qt::WindowStaysOnTopHint*/); + + switch (initResult) { + case RS_INIT_OK: + { + /* Login Dialog */ + /* check for existing Certificate */ + std::string userName; + + StartDialog *sd = NULL; + bool genCert = false; + std::list accountIds; + if (RsInit::getAccountIds(accountIds) && (accountIds.size() > 0)) + { + sd = new StartDialog(); + sd->show(); + + while(sd -> isVisible()) + { + rshare.processEvents(); +#ifdef WIN32 + Sleep(10); +#else // __LINUX__ + usleep(10000); +#endif + } + + /* if we're logged in */ + genCert = sd->requestedNewCert(); + delete (sd); + } + else + { + genCert = true; + } + + if (genCert) + { + GenCertDialog gd; + gd.exec (); + } + + splashScreen.show(); + } + break; + case RS_INIT_HAVE_ACCOUNT: + { + splashScreen.show(); + splashScreen.showMessage(rshare.translate("SplashScreen", "Load profile"), Qt::AlignHCenter | Qt::AlignBottom); + + std::string preferredId, gpgId, gpgName, gpgEmail, sslName; + RsInit::getPreferedAccountId(preferredId); + + if (RsInit::getAccountDetails(preferredId, gpgId, gpgName, gpgEmail, sslName)) + { + RsInit::SelectGPGAccount(gpgId); + } + + // true: note auto-login is active + std::string lockFile; + int retVal = RsInit::LockAndLoadCertificates(true, lockFile); + switch(retVal) + { + case 0: break; + case 1: QMessageBox::warning( 0, + QObject::tr("Multiple instances"), + QObject::tr("Another RetroShare using the same profile is " + "already running on your system. Please close " + "that instance first\n Lock file:\n") + + QString::fromStdString(lockFile)); + return 1; + case 2: QMessageBox::critical( 0, + QObject::tr("Multiple instances"), + QObject::tr("An unexpected error occurred when Retroshare" + "tried to acquire the single instance lock\n Lock file:\n") + + QString::fromStdString(lockFile)); + return 1; + case 3: QMessageBox::critical( 0, + QObject::tr("Login Failure"), + QObject::tr("Maybe password is wrong") ); + return 1; + default: std::cerr << "StartDialog::loadCertificates() unexpected switch value " << retVal << std::endl; + } + } + break; + default: + /* Unexpected return code */ + std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl; + QMessageBox::warning(0, QObject::tr("RetroShare"), QObject::tr("An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'.").arg(initResult)); + return 1; + } + + splashScreen.showMessage(rshare.translate("SplashScreen", "Load configuration"), Qt::AlignHCenter | Qt::AlignBottom); + + rsicontrol->StartupRetroShare(); + + splashScreen.showMessage(rshare.translate("SplashScreen", "Create interface"), Qt::AlignHCenter | Qt::AlignBottom); + + /* recreate global settings object, now with correct path */ + RshareSettings::Create (); + RsharePeerSettings::Create(); + +#ifdef MINIMAL_RSGUI + MessengerWindow::showYourself(); + + rshare.setQuitOnLastWindowClosed(true); + + splashScreen.hide(); +#else + Emoticons::load(); + + if (Settings->value(QString::fromUtf8("FirstRun"), true).toBool()) { + splashScreen.hide(); + + Settings->setValue(QString::fromUtf8("FirstRun"), false); + QuickStartWizard qstartWizard; + qstartWizard.exec(); + } + + MainWindow *w = MainWindow::Create (); + splashScreen.finish(w); + + EventReceiver *eventReceiver = NULL; + if (Settings->getRetroShareProtocol()) { + /* Create event receiver */ + eventReceiver = new EventReceiver; + if (eventReceiver->start()) { + QObject::connect(eventReceiver, SIGNAL(linkReceived(const QUrl&)), w, SLOT(linkActivated(const QUrl&))); + } + } + + if (!url.empty()) { + /* Now use link from the command line, because no RetroShare was running */ + RetroShareLink link(QString::fromStdString(url)); + if (link.valid()) { + w->linkActivated(link.toUrl()); + } + } + + // I'm using a signal to transfer the hashing info to the mainwindow, because Qt schedules signals properly to + // avoid clashes between infos from threads. + // + + qRegisterMetaType("FileDetail") ; + + std::cerr << "connecting signals and slots" << std::endl ; + QObject::connect(notify,SIGNAL(gotTurtleSearchResult(qulonglong,FileDetail)),w->searchDialog ,SLOT(updateFiles(qulonglong,FileDetail))) ; + QObject::connect(notify,SIGNAL(diskFull(int,int)) ,w ,SLOT(displayDiskSpaceWarning(int,int))) ; + QObject::connect(notify,SIGNAL(filesPreModChanged(bool)) ,w->sharedfilesDialog ,SLOT(preModDirectories(bool) )) ; + QObject::connect(notify,SIGNAL(filesPostModChanged(bool)) ,w->sharedfilesDialog ,SLOT(postModDirectories(bool) )) ; + QObject::connect(notify,SIGNAL(filesPostModChanged(bool)) ,w ,SLOT(postModDirectories(bool) )) ; + QObject::connect(notify,SIGNAL(transfersChanged()) ,w->transfersDialog ,SLOT(insertTransfers() )) ; + QObject::connect(notify,SIGNAL(friendsChanged()) ,w->friendsDialog ,SLOT(insertPeers() )) ; + QObject::connect(notify,SIGNAL(publicChatChanged(int)) ,w->friendsDialog ,SLOT(publicChatChanged(int) )); + QObject::connect(notify,SIGNAL(groupsChanged(int)) ,w->friendsDialog ,SLOT(groupsChanged(int) )); + QObject::connect(notify,SIGNAL(privateChatChanged(int, int)) ,w ,SLOT(privateChatChanged(int, int) )); + QObject::connect(notify,SIGNAL(neighborsChanged()) ,w->networkDialog ,SLOT(insertConnect() )) ; + QObject::connect(notify,SIGNAL(messagesChanged()) ,w->messagesDialog ,SLOT(insertMessages() )) ; + QObject::connect(notify,SIGNAL(messagesTagsChanged()) ,w->messagesDialog ,SLOT(messagesTagsChanged() )) ; + QObject::connect(notify,SIGNAL(messagesChanged()) ,w ,SLOT(updateMessages() )) ; + QObject::connect(notify,SIGNAL(forumsChanged()) ,w ,SLOT(updateForums() ), Qt::QueuedConnection); + QObject::connect(notify,SIGNAL(channelsChanged(int)) ,w ,SLOT(updateChannels(int) ), Qt::QueuedConnection); + QObject::connect(notify,SIGNAL(downloadCompleteCountChanged(int)) ,w ,SLOT(updateTransfers(int) )); + + QObject::connect(notify,SIGNAL(chatStatusChanged(const QString&,const QString&,bool)),w->friendsDialog,SLOT(updatePeerStatusString(const QString&,const QString&,bool))); + QObject::connect(notify,SIGNAL(peerHasNewAvatar(const QString&)),w->friendsDialog,SLOT(updatePeersAvatar(const QString&))); + QObject::connect(notify,SIGNAL(ownAvatarChanged()),w->friendsDialog,SLOT(updateAvatar())); + QObject::connect(notify,SIGNAL(ownStatusMessageChanged()),w->friendsDialog,SLOT(loadmypersonalstatus())); + + QObject::connect(notify,SIGNAL(logInfoChanged(const QString&)) ,w->networkDialog,SLOT(setLogInfo(QString))) ; + QObject::connect(notify,SIGNAL(discInfoChanged()) ,w->networkDialog,SLOT(updateNewDiscoveryInfo()),Qt::QueuedConnection) ; + QObject::connect(notify,SIGNAL(errorOccurred(int,int,const QString&)),w,SLOT(displayErrorMessage(int,int,const QString&))) ; + + QObject::connect(w->friendsDialog,SIGNAL(friendsUpdated()),w->networkDialog,SLOT(insertConnect())) ; + + w->installGroupChatNotifier(); + + /* only show window, if not startMinimized */ + if (RsInit::getStartMinimised() || Settings->getStartMinimized()) + { + splashScreen.close(); + } else { + w->show(); + } + + /* Startup a Timer to keep the gui's updated */ + QTimer *timer = new QTimer(w); + timer -> connect(timer, SIGNAL(timeout()), notify, SLOT(UpdateGUI())); + timer->start(1000); +#endif // MINIMAL_RSGUI + + /* dive into the endless loop */ + int ti = rshare.exec(); +#ifndef MINIMAL_RSGUI + delete w ; + + if (eventReceiver) { + /* Destroy event receiver */ + delete eventReceiver; + eventReceiver = NULL; + } + + /* cleanup */ + PopupChatDialog::cleanupChat(); +#endif // MINIMAL_RSGUI + + rsicontrol->rsGlobalShutDown(); + + Settings->sync(); + delete Settings; + + return ti ; +} diff --git a/retroshare-gui/src/mingw32make.bat b/retroshare-gui/src/mingw32make.bat new file mode 100644 index 000000000..fe84948db --- /dev/null +++ b/retroshare-gui/src/mingw32make.bat @@ -0,0 +1,13 @@ +set QTDIR=d:\qt\2010.01 +set MINGW=%QTDIR%\mingw + +set PATH=%QTDIR%\qt\bin;%QTDIR%\bin;%MINGW%\bin;%PATH% + +"D:\Programme\TortoiseSVN\bin\SubWCRev" . util\rsversion.in util\rsversion.h + +qmake RetroShare.pro + +mingw32-make + +pause + diff --git a/retroshare-gui/src/qss/Thumbs.db b/retroshare-gui/src/qss/Thumbs.db new file mode 100644 index 000000000..a09090af5 Binary files /dev/null and b/retroshare-gui/src/qss/Thumbs.db differ diff --git a/retroshare-gui/src/qss/blacknight.qss b/retroshare-gui/src/qss/blacknight.qss new file mode 100644 index 000000000..b2907d14a --- /dev/null +++ b/retroshare-gui/src/qss/blacknight.qss @@ -0,0 +1,297 @@ + +QWidget{ +background: black; +color: lightgray; +border-color: transparent; +} +QDialog, QMainWindow{ +background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgb(25, 25, 25), stop:0.05 rgb(0, 0, 0), stop:0.95 rgb(0, 0, 0), stop:1 rgb(25, 25, 25)); +} +QPushButton{ +padding-left: 7px; +padding-right: 7px; +} +QFrame{ +background: transparent; +} +QFrame#frame{ +background: black; +border:1px solid rgb(100,100,100); +} +QComboBox, QFontComboBox{ +padding-left: 5px; +padding-right: 5px; +} +QPushButton:hover{ +color: white; +} +QTabBar{ +background: transparent; +border:1px solid rgb(100,100,100); +} +QTabBar::tab{ +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 rgb(0, 0, 0), stop: 1 rgb(85, 85, 85)); +color: lightgray; +border: 1px solid rgb(100,100,100); +margin-bottom:1px; +margin-right: -1px; +padding-top:3px; +} +QTabBar::tab:selected{ +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 rgb(85, 85, 85), stop: 1 rgb(0, 0, 0)); +border-bottom:1px solid black; +} +QTabBar::tab:last{ +margin-right:0px; +} +QTabWidget::pane{ +border:1px solid rgb(100,100,100); +} +QMenu, QTreeView, QComboBox QAbstractItemView{ +background: black; +color: lightgray; +border:1px solid rgb(100, 100, 100); +} +QMenu::item:disabled, QComboBox QAbstractItemView::item:disabled{ +color: rgb(38,38,38); +border:4px solid transparent; +padding-left: 20px; +} +QMenu::item, QComboBox QAbstractItemView::item{ +border: 4px solid transparent; +padding-left: 20px; +padding-right: 16px; +padding-top:+3; +color: lightgray; +} +QMenu::item:selected, QComboBox QAbstractItemView::item:selected{ +color: lightgray; +background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgb(0, 0, 0), stop:0.40 rgb(100, 100, 100), stop:0.60 rgb(100, 100, 100), stop:1 rgb(0, 0, 0)); +} +QMenu::separator, QComboBox QAbstractItemView::separator{ +background: rgb(100, 100, 100); +height: 1px; +} +QTextEdit{ +background: black; +color: black; +border:1px solid rgb(100,100,100); +border-radius:5px; +} +QTreeView{ +/*color: red;*/ +alternate-background-color: rgb(10,10,10); +selection-background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgb(0,0,0), stop:0.50 rgb(100, 100, 100), stop:1 rgb(0,0,0)); +background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(15, 15, 15), stop:0.10 rgb(0, 0, 0), stop:0.90 rgb(0, 0, 0), stop:1 rgb(15, 15, 15)); +} +QComboBox::down-arrow{ +image: url(:/qss/simple/combobox/arrow.png); +width: 8px; +height: 8px; +} +QComboBox::drop-down{ +width: 20px; +border:0px; +} +QToolTip{ +opacity: 75; +border:1px solid rgb(100, 100, 100); +color: white; +background: black; +padding: 3px; +} +QToolButton{ +padding:1px; +} +QSpinBox, QListWidget, QFontComboBox{ +/*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 rgb(85, 85, 85), stop: 1 rgb(0, 0, 0));*/ +color: lightgray; +/*border-radius: 5px;*/ +border: 1px solid rgb(100,100,100); +background: black; +margin:1px; +} +QLineEdit, QPushButton, QToolButton, QComboBox, QFontComboBox{ +border: 1px solid rgb(100,100,100); +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 rgb(85, 85, 85), stop: 1 rgb(0, 0, 0)); +color: lightgray; +border-radius: 5px; +margin:1px; +} +QHeaderView::section{ +background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 rgb(85, 85, 85), stop: 1 rgb(0, 0, 0)); +color: lightgray; +padding-left: 4px; +border: 1px solid transparent; +border-bottom: 1px solid rgb(100, 100, 100); +} +QSplitter{ +background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgb(0,0,0), stop: 0.5 rgb(100, 100, 100), stop: 1 rgb(0, 0, 0)); +} +QScrollBar:vertical{ +border: 1px solid rgb(100,100,100); +background: black; +width: 15px; +margin: 16px 0 16px 0; +} +QScrollBar::handle:vertical{ +background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgb(100, 100, 100), stop: 0.6 rgb(0,0,0), stop: 1 rgb(0, 0, 0)); +min-height: 20px; +} +QScrollBar::add-line:vertical{ +border: 1px solid rgb(100,100,100); +border-bottom-color: transparent; +background: black; +height: 15px; +subcontrol-position: bottom; +subcontrol-origin: margin; +} +QScrollBar::sub-line:vertical{ +border: 1px solid rgb(100, 100, 100); +border-top-color: transparent; +background: black; +height: 15px; +subcontrol-position: top; +subcontrol-origin: margin; +} +QScrollBar::up-arrow:vertical{ +image: url(qss/blacknight/up.png); +} +QScrollBar::down-arrow:vertical{ +image: url(qss/blacknight/down.png); +} +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical{ +background: none; +} +QCheckBox, QRadioButton{ +spacing: 2px; +} +QCheckBox::!enabled, QRadioButton::!enabled{ +color : rgb(50, 50, 50); +} +QCheckBox::indicator:unchecked{ +image: url(qss/blacknight/check_unsel.png); +} +QCheckBox::indicator:unchecked:hover{ +image: url(qss/blacknight/check_unsel.png); +} +QCheckBox::indicator:unchecked:pressed{ +image: url(qss/blacknight/check_unsel.png); +} +QCheckBox::indicator:checked{ +image: url(qss/blacknight/check_sel.png); +} +QCheckBox::indicator:checked:hover{ +image: url(qss/blacknight/check_sel.png); +} +QCheckBox::indicator:checked:!enabled{ +image: url(qss/blacknight/check_sel.png); +} +QCheckBox::indicator:unchecked:!enabled{ +image: url(qss/blacknight/check_unsel.png); +} +QRadioButton::indicator::unchecked{ +image: url(qss/blacknight/radio_unsel.png); +} +QRadioButton::indicator:unchecked:hover{ +image: url(qss/blacknight/radio_unsel.png); +} +QRadioButton::indicator:unchecked:pressed{ +image: url(qss/blacknight/radio_unsel.png); +} +QRadioButton::indicator::checked{ +image: url(qss/blacknight/radio_sel.png); +} +QRadioButton::indicator:checked:hover{ +image: url(qss/blacknight/radio_sel.png); +} +QRadioButton::indicator:checked:pressed{ +image: url(qss/blacknight/radio_sel.png); +} +QTreeWidget#contactListTree{ +background: black url(qss/blacknight/clbg.png) repeat-y; +} +icqTextBrowser, icqTextEdit{ +/* +background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 rgb(0, 0, 0), stop: 0.05 transparent, stop: 0.95 transparent, stop: 1 rgb(0, 0, 0)); +border-color: transparent; +*/ +} + +QLabel#infolabel{ + color: black; +} + +QLabel#friendslabel{ + color: black; +} + +QLabel#networklabel{ + color: black; +} + +QLabel#channellabel{ + color: black; +} + +QLabel#forumslabel{ + color: black; +} + +QLabel#downloadslabel{ + color: black; +} + +QLabel#forumName{ + color: black; +} + +QLabel#threadTitle{ + color: black; +} + +QLabel#labeltext{ + color: black; +} + +QLabel#label{ + color: black; +} + +QPushButton#Folders_Button{ + color: black; +} + +QToolButton#Tags_Button{ + color: black; +} + +QTextBrowser#msgText{ + color: black; +} + +QTextEdit#lineedit{ + color: black; + background: white; + +} + +QTextEdit#chattextEdit{ + color: black; +} + +QTextEdit#lineEdit{ + color: black; + background: white; +} + +QTextBrowser#postText{ + color: white; +} + +QTreeWidget#treeWidget{ + color: white; + background: white; + +} + diff --git a/retroshare-gui/src/qss/blacknight/check_sel.png b/retroshare-gui/src/qss/blacknight/check_sel.png new file mode 100644 index 000000000..300de11ee Binary files /dev/null and b/retroshare-gui/src/qss/blacknight/check_sel.png differ diff --git a/retroshare-gui/src/qss/blacknight/check_unsel.png b/retroshare-gui/src/qss/blacknight/check_unsel.png new file mode 100644 index 000000000..50ca1d0a5 Binary files /dev/null and b/retroshare-gui/src/qss/blacknight/check_unsel.png differ diff --git a/retroshare-gui/src/qss/blacknight/clbg.png b/retroshare-gui/src/qss/blacknight/clbg.png new file mode 100644 index 000000000..45ce37337 Binary files /dev/null and b/retroshare-gui/src/qss/blacknight/clbg.png differ diff --git a/retroshare-gui/src/qss/blacknight/down.png b/retroshare-gui/src/qss/blacknight/down.png new file mode 100644 index 000000000..ce161569b Binary files /dev/null and b/retroshare-gui/src/qss/blacknight/down.png differ diff --git a/retroshare-gui/src/qss/blacknight/radio_sel.png b/retroshare-gui/src/qss/blacknight/radio_sel.png new file mode 100644 index 000000000..1239b6dc8 Binary files /dev/null and b/retroshare-gui/src/qss/blacknight/radio_sel.png differ diff --git a/retroshare-gui/src/qss/blacknight/radio_unsel.png b/retroshare-gui/src/qss/blacknight/radio_unsel.png new file mode 100644 index 000000000..4c895c9da Binary files /dev/null and b/retroshare-gui/src/qss/blacknight/radio_unsel.png differ diff --git a/retroshare-gui/src/qss/blacknight/up.png b/retroshare-gui/src/qss/blacknight/up.png new file mode 100644 index 000000000..38d747789 Binary files /dev/null and b/retroshare-gui/src/qss/blacknight/up.png differ diff --git a/retroshare-gui/src/qss/blue.qss b/retroshare-gui/src/qss/blue.qss new file mode 100644 index 000000000..b1938b221 --- /dev/null +++ b/retroshare-gui/src/qss/blue.qss @@ -0,0 +1,153 @@ +.QWidget { + background-color: #c4dafa; + border-color: transparent; +} + +QDialog{ + background-color: #c4dafa; + +} + +QWidget#chatcentralwidget{ + background-color: #c4dafa; + +} + +QToolBar#chattoolBar{ + border-image: url(qss/blue/blue.png); + + +} + + +/* Customize the toolbar. */ +QToolBar#toolBar { + border-image: url(qss/blue/blue.png); + +} + +QToolBar#toolBar_2 { + border-image: url(qss/blue/blue2.png); + +} + +QTabBar::tab { + border-image: url(qss/blue/tab1.png); + min-width: 8ex; + padding: 4px; + + +} + +QTabBar::tab:!selected { + margin-top: 2px; /* make non-selected tabs look smaller */ + +} + +QTabBar::tab:selected, QTabBar::tab:hover { + + border-image: url(qss/orangesurfer/tab_hover.png); + + +} + +QTabBar::tab:selected { + border-image: url(qss/blue/tabselected.png); +} + +QPushButton#okButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelprefButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelButton { + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + + +QPushButton#applyButton { + + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + + + +QMenu::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #E3EFFF, stop: 1 #87ADE4); +} + +QListWidget::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #E3EFFF, stop: 1 #87ADE4); +} + +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #E3EFFF, stop: 1 #87ADE4); +} + +QStatusBar{ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #E3EFFF, stop: 1 #87ADE4); +} + +QFrame#messengerframetop{ + + border-image: url(qss/blue/blue.png); + +} + +QFrame#Chatbuttonframe{ + + border-image: url(qss/blue/blue.png); + +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} +QSplitter#splitter{ + border-image: url(qss/blue/blue.png); + +} diff --git a/retroshare-gui/src/qss/blue/Thumbs.db b/retroshare-gui/src/qss/blue/Thumbs.db new file mode 100644 index 000000000..b27dfd73c Binary files /dev/null and b/retroshare-gui/src/qss/blue/Thumbs.db differ diff --git a/retroshare-gui/src/qss/blue/blue.png b/retroshare-gui/src/qss/blue/blue.png new file mode 100644 index 000000000..28a723edd Binary files /dev/null and b/retroshare-gui/src/qss/blue/blue.png differ diff --git a/retroshare-gui/src/qss/blue/blue2.png b/retroshare-gui/src/qss/blue/blue2.png new file mode 100644 index 000000000..7671a1649 Binary files /dev/null and b/retroshare-gui/src/qss/blue/blue2.png differ diff --git a/retroshare-gui/src/qss/blue/tab1.png b/retroshare-gui/src/qss/blue/tab1.png new file mode 100644 index 000000000..68d6960b4 Binary files /dev/null and b/retroshare-gui/src/qss/blue/tab1.png differ diff --git a/retroshare-gui/src/qss/blue/tabselected.png b/retroshare-gui/src/qss/blue/tabselected.png new file mode 100644 index 000000000..78a819cb8 Binary files /dev/null and b/retroshare-gui/src/qss/blue/tabselected.png differ diff --git a/retroshare-gui/src/qss/default.qss b/retroshare-gui/src/qss/default.qss new file mode 100644 index 000000000..6ef68e5d2 --- /dev/null +++ b/retroshare-gui/src/qss/default.qss @@ -0,0 +1,71 @@ + +QWidget#chatcentralwidget +{ + background-image: url(:/images/backchat.png) +} + +QToolBar#chattoolBar{ + border: none; background-image: url(:/images/backblue.png) +} +QStatusBar{ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F6FCFF, stop:1 #F6FCFF); +} + +QFrame#Chatbuttonframe{ + background-image: url(:/images/buttonframe.png); +} + +/* Customize the toolbar. */ +QToolBar { + border-image: url(qss/default/retrotoolbar.png); + +} + +QFrame#messengerframetop{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #05538B, stop:1 #E4F1E5); +} + + +QFrame#messengerframetop{ + + border-image: url(qss/default/rsdefault.png); + +} + +QFrame#Chatbuttonframe{ + + border-image: url(qss/default/rsdefault.png); + +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} diff --git a/retroshare-gui/src/qss/default/Thumbs.db b/retroshare-gui/src/qss/default/Thumbs.db new file mode 100644 index 000000000..c5a42ad8a Binary files /dev/null and b/retroshare-gui/src/qss/default/Thumbs.db differ diff --git a/retroshare-gui/src/qss/default/retrotoolbar.png b/retroshare-gui/src/qss/default/retrotoolbar.png new file mode 100644 index 000000000..4a8e6cd39 Binary files /dev/null and b/retroshare-gui/src/qss/default/retrotoolbar.png differ diff --git a/retroshare-gui/src/qss/default/rsdefault.png b/retroshare-gui/src/qss/default/rsdefault.png new file mode 100644 index 000000000..c9d57bcc0 Binary files /dev/null and b/retroshare-gui/src/qss/default/rsdefault.png differ diff --git a/retroshare-gui/src/qss/groove.qss b/retroshare-gui/src/qss/groove.qss new file mode 100644 index 000000000..295a25dd6 --- /dev/null +++ b/retroshare-gui/src/qss/groove.qss @@ -0,0 +1,55 @@ +.QWidget{ + + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #6799B3, stop: 1 #377a90); +} +QDialog{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #6799B3, stop: 1 #377a90); + +} + +QWidget#chatcentralwidget{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #6799B3, stop: 1 #377a90); + + +} + + +QToolBar#chattoolBar{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #6799B3, stop: 0.3 #377a90, + stop: 0.31 #0e5e73, stop: 1 #4b8598); + + border: 1px solid #4b8598; +} + +QFrame#Chatbuttonframe{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #6799B3, stop: 0.3 #377a90, + stop: 0.31 #0e5e73, stop: 1 #4b8598); + + border: 1px solid #4b8598; +} + +QStatusBar{ + + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #6799B3, stop: 1 #377a90); + +} + +/* Customize the toolbar. */ +QToolBar { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #6799B3, stop: 0.3 #377a90, + stop: 0.31 #0e5e73, stop: 1 #4b8598); + + border: 1px solid #4b8598; +} + +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #6799B3, stop: 0.3 #377a90, + stop: 0.31 #0e5e73, stop: 1 #4b8598); + +} + +Q diff --git a/retroshare-gui/src/qss/noskin.qss b/retroshare-gui/src/qss/noskin.qss new file mode 100644 index 000000000..b4ed2f939 --- /dev/null +++ b/retroshare-gui/src/qss/noskin.qss @@ -0,0 +1,91 @@ + +QWidget#chatcentralwidget +{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #3AAEE4, stop: 0.1 #E0EFF6, + stop: 0.31 #E4F1F7, stop: 0.7 #FCFDFE, + stop: 0.71 #F7FCFD, stop: 1 #C9E7F3,); + border: none; +} + +QToolBar#chattoolBar{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #8DD2F3, stop: 0.5 #43B5EB, + stop: 0.51 #39ABE1, stop: 1 #3CB2EA); + border: none; +} +QStatusBar#chatstatusbar{ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F6FCFF, stop:1 #F6FCFF); +} + +QFrame#Chatbuttonframe{ + background-image: url(:/images/buttonframe.png); +} + +QFrame#messengerframetop{ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #05538B, stop:1 #E4F1E5); +} + +border: 1px solid #BDD5DF;}QPushButton#okButton { + + max-height: 25px + min-height: 25px; + min-width: 77px; + /*max-width: 77px;*/ +} + +QPushButton#cancelprefButton { + + min-height: 25px; + min-width: 77px; + max-width: 77px; +} + +QPushButton#applyButton { + + min-height: 25px; + max-height: 25px; + min-width: 77px; + max-width: 77px; +} + +QPushButton#cancelButton { + + min-height: 25px; + max-height: 25px; + min-width: 77px; + max-width: 77px; +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} + diff --git a/retroshare-gui/src/qss/orangesurfer.qss b/retroshare-gui/src/qss/orangesurfer.qss new file mode 100644 index 000000000..b2117fb7e --- /dev/null +++ b/retroshare-gui/src/qss/orangesurfer.qss @@ -0,0 +1,198 @@ +.QWidget { + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07); + + +} + +QDialog, QMainWindow{ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07); +} + +QWidget#chatcentralwidget{ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07); + +} + +QToolBar#chattoolBar{ + border-image: url(qss/orangesurfer/main.png); + + +} + +/* Customize the toolbar. */ +QToolBar#toolBar { + border-image: url(qss/orangesurfer/main.png); + +} + +QToolBar#toolBar_2 { + border-image: url(qss/orangesurfer/main2.png); + +} + + +QTabBar::tab { + border-image: url(qss/orangesurfer/tab_normal.png); + border-top-left-radius: 4px; + border-top-right-radius: 4px; + min-width: 8ex; + padding: 4px; + + +} + +QTabBar::tab:!selected { + margin-top: 2px; /* make non-selected tabs look smaller */ + +} + +QTabBar::tab:selected, QTabBar::tab:hover { + + border-image: url(qss/orangesurfer/tab_hover.png); + + +} + +QTabBar::tab:selected { + border-image: url(qss/orangesurfer/tab_pressed.png); +} + + +QPushButton#okButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelprefButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelButton { + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + + +QPushButton#applyButton { + + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + + + +QStatusBar{ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #67768D, stop: 0.4 #EDEEFD); + +} + +QSizeGrip { + image: url(qss/orangesurfer/sizegrip.png); + width: 16px; + height: 16px; +} + +QMenu { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #67768D, stop: 0.4 #EDEEFD); + border: 1px solid black; +} + +QMenu::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07); +} + +QListWidget::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07); +} + + +QTreeWidget { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07); + + +} +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + + + + border-image: url(qss/gofast/border.png); + +} + +QTreeView { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07); + + +} + +QTreeView::item:selected { /* when user selects item using mouse or keyboard */ + + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07);*/ + + border-image: url(qss/orangesurfer/border.png); + +} + +QFrame#messengerframetop{ + + border-image: url(qss/orangesurfer/main.png); + + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07);*/ +} + +QFrame#Chatbuttonframe{ + + border-image: url(qss/orangesurfer/main.png); + +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} diff --git a/retroshare-gui/src/qss/orangesurfer/Thumbs.db b/retroshare-gui/src/qss/orangesurfer/Thumbs.db new file mode 100644 index 000000000..1c5d4c51e Binary files /dev/null and b/retroshare-gui/src/qss/orangesurfer/Thumbs.db differ diff --git a/retroshare-gui/src/qss/orangesurfer/border.png b/retroshare-gui/src/qss/orangesurfer/border.png new file mode 100644 index 000000000..e8bd39f07 Binary files /dev/null and b/retroshare-gui/src/qss/orangesurfer/border.png differ diff --git a/retroshare-gui/src/qss/orangesurfer/main.png b/retroshare-gui/src/qss/orangesurfer/main.png new file mode 100644 index 000000000..2605e0d4d Binary files /dev/null and b/retroshare-gui/src/qss/orangesurfer/main.png differ diff --git a/retroshare-gui/src/qss/orangesurfer/main2.png b/retroshare-gui/src/qss/orangesurfer/main2.png new file mode 100644 index 000000000..e977b4812 Binary files /dev/null and b/retroshare-gui/src/qss/orangesurfer/main2.png differ diff --git a/retroshare-gui/src/qss/orangesurfer/sizegrip.png b/retroshare-gui/src/qss/orangesurfer/sizegrip.png new file mode 100644 index 000000000..be6cd102c Binary files /dev/null and b/retroshare-gui/src/qss/orangesurfer/sizegrip.png differ diff --git a/retroshare-gui/src/qss/orangesurfer/tab_hover.png b/retroshare-gui/src/qss/orangesurfer/tab_hover.png new file mode 100644 index 000000000..1a5fc3ef4 Binary files /dev/null and b/retroshare-gui/src/qss/orangesurfer/tab_hover.png differ diff --git a/retroshare-gui/src/qss/orangesurfer/tab_normal.png b/retroshare-gui/src/qss/orangesurfer/tab_normal.png new file mode 100644 index 000000000..f3a4b4694 Binary files /dev/null and b/retroshare-gui/src/qss/orangesurfer/tab_normal.png differ diff --git a/retroshare-gui/src/qss/orangesurfer/tab_pressed.png b/retroshare-gui/src/qss/orangesurfer/tab_pressed.png new file mode 100644 index 000000000..eeae9b138 Binary files /dev/null and b/retroshare-gui/src/qss/orangesurfer/tab_pressed.png differ diff --git a/retroshare-gui/src/qss/orangesurfer/toolbar.png b/retroshare-gui/src/qss/orangesurfer/toolbar.png new file mode 100644 index 000000000..2aae1f8ff Binary files /dev/null and b/retroshare-gui/src/qss/orangesurfer/toolbar.png differ diff --git a/retroshare-gui/src/qss/qlive.qss b/retroshare-gui/src/qss/qlive.qss new file mode 100644 index 000000000..894376153 --- /dev/null +++ b/retroshare-gui/src/qss/qlive.qss @@ -0,0 +1,109 @@ +.QWidget{ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #77AEF1, stop: 0.4 #86BBF7); +} + +QDialog{ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #77AEF1, stop: 0.4 #86BBF7); +} + + +/* Customize the toolbar. */ +QToolBar#toolBar { + border-image: url(qss/qlive/qb.png); + +} + +QToolBar#toolBar_2 { + border-image: url(qss/qlive/qb2.png); + +} + +QToolBar#chattoolBar{ + border-image: url(qss/qlive/qb.png); + +} + +QMenu { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #77AEF1, stop: 0.4 #86BBF7); + + border: 1px solid black; + } + +QMenu::item:selected { /* when user selects item using mouse or keyboard */ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F6F9FA, stop: 1 #C6D3E5); +} + +QListWidget::item:selected { /* when user selects item using mouse or keyboard */ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F6F9FA, stop: 1 #C6D3E5); +} +QTreeWidget { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #77AEF1, stop: 0.4 #86BBF7); + + } + + +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F6F9FA, stop: 1 #C6D3E5); + +} + +QTreeView::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F6F9FA, stop: 1 #C6D3E5); + +} + +QFrame#messengerframetop{ + + border-image: url(qss/qlive/qb.png); + +} + +QFrame#Chatbuttonframe{ + + border-image: url(qss/qlive/qb.png); + +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} +QStatusBar{ + border-image: url(qss/qlive/qb.png); +} + diff --git a/retroshare-gui/src/qss/qlive/qb.png b/retroshare-gui/src/qss/qlive/qb.png new file mode 100644 index 000000000..cde1a8588 Binary files /dev/null and b/retroshare-gui/src/qss/qlive/qb.png differ diff --git a/retroshare-gui/src/qss/qlive/qb2.png b/retroshare-gui/src/qss/qlive/qb2.png new file mode 100644 index 000000000..abd2f0b74 Binary files /dev/null and b/retroshare-gui/src/qss/qlive/qb2.png differ diff --git a/retroshare-gui/src/qss/redscorpion.qss b/retroshare-gui/src/qss/redscorpion.qss new file mode 100644 index 000000000..15fdd024d --- /dev/null +++ b/retroshare-gui/src/qss/redscorpion.qss @@ -0,0 +1,273 @@ +.QWidget { + background-color: #3E1716; +} + +QDialog{ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 red, stop: 1 darkred); + +} + +/* Customize the toolbar. */ +QToolBar#toolBar { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F55332, stop: 0.5 #C82B18, + stop: 0.51 #B71502, stop: 1 #900907); + border: 1px solid #7A3C37; + +} + +QToolBar#toolBar_2 { + border-image: url(qss/redscorpion/red2.png); + + +} + +QToolBar#chattoolBar{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F55332, stop: 0.5 #C82B18, + stop: 0.51 #B71502, stop: 1 #900907); + border: 1px solid #7A3C37; + +} + + +/* it works only at the moment with vista Thema on XP*/ +QToolButton::hover { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #FFD200, stop: 1 #FF6400); + + +} + +QToolButton::pressed { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #FFD200, stop: 1 #FF6400); + + +} + +QPushButton { + /* background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 red, stop: 1 darkred);*/ +} + +QPushButton#okButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelprefButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelButton { + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + + +QPushButton#applyButton { + + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + +QToolButton { + color: black; +} + + QTabWidget::tab-bar { + left: 0px; /* move to the right by 5px */ + } + + /* Style the tab using the tab sub-control. Note that + it reads QTabBar _not_ QTabWidget */ + QTabBar::tab { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 red, stop: 1 darkred); + border: 2px solid #C4C4C3; + border-bottom-color: #C2C7CB; /* same as the pane color */ + border-top-left-radius: 4px; + border-top-right-radius: 4px; + min-width: 8ex; + padding: 2px; + } + + QTabBar::tab:selected, QTabBar::tab:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 darkred, stop: 1 red); + } + + QTabBar::tab:selected { + border-color: #9B9B9B; + border-bottom-color: #C2C7CB; /* same as pane color */ + } + + QTabBar::tab:!selected { + margin-top: 2px; /* make non-selected tabs look smaller */ + } + +QStatusBar{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F55332, stop: 0.5 #C82B18, + stop: 0.51 #B71502, stop: 1 #900907); + border: 1px solid #7A3C37; + +} + +QToolTip{ + background-color: darkred; +} + +QMenu { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 red, stop: 1 darkred); + border: 1px solid black; + } + +QMenu::item { + /* sets background of menu item. set this to something non-transparent + if you want menu color and menu item color to be different */ + background-color: transparent; + } + +QMenu::item:selected { /* when user selects item using mouse or keyboard */ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #FFD200, stop: 1 #FF6400); + } + +QListWidget::item:selected { /* when user selects item using mouse or keyboard */ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 red, stop: 1 darkred); +} + +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 red, stop: 1 darkred); +} + +QTreeView::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 red, stop: 1 darkred); + +} + +QFrame#messengerframetop{ + + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F55332, stop: 0.5 #C82B18, + stop: 0.51 #B71502, stop: 1 #900907); + border: 1px solid #7A3C37; +} + +QFrame#Chatbuttonframe{ + + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F55332, stop: 0.5 #C82B18, + stop: 0.51 #B71502, stop: 1 #900907); + border: 1px solid #7A3C37; + +} + +QFrame#frame_2{ + border-image: url(qss/redscorpion/red.png); + + +border: 1px solid #CCCCCC; +} + +QFrame#buttonframe{ + border-image: url(qss/redscorpion/red.png); + + +border: 1px solid #CCCCCC; +} + +QFrame#frame{ + border-image: url(qss/redscorpion/red.png); + + border: 1px solid #CCCCCC; +} + +QFrame#chheaderframe{ + border-image: url(qss/redscorpion/red.png); + + +border: 1px solid #CCCCCC; +} + + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} + +QLabel#infolabel{ + color: darkred; +} + +QLabel#friendstitlellabel{ + color: black; +} + +QLabel#networklabel{ + color: black; +} + +QLabel#labeltext{ + color: black; +} + +QRadioButton{ + color: white; +} + +QLabel{ + + color: white; +} + +QLabel#forumName{ + border: 2px solid red; + border-radius: 10px; + background: white; + color: black; +} + +QLabel#threadTitle{ + border: 2px solid red; + border-radius: 10px; + background: white; + color: black; +} diff --git a/retroshare-gui/src/qss/redscorpion/red.png b/retroshare-gui/src/qss/redscorpion/red.png new file mode 100644 index 000000000..8c2246cdb Binary files /dev/null and b/retroshare-gui/src/qss/redscorpion/red.png differ diff --git a/retroshare-gui/src/qss/redscorpion/red2.png b/retroshare-gui/src/qss/redscorpion/red2.png new file mode 100644 index 000000000..0b2a36121 Binary files /dev/null and b/retroshare-gui/src/qss/redscorpion/red2.png differ diff --git a/retroshare-gui/src/qss/silver.qss b/retroshare-gui/src/qss/silver.qss new file mode 100644 index 000000000..f6dbfd7df --- /dev/null +++ b/retroshare-gui/src/qss/silver.qss @@ -0,0 +1,120 @@ +.QWidget{ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F9F9FF, stop: 1 #9F9DB9); +} + +/* Customize the toolbar. */ +QToolBar#toolBar { + border-image: url(qss/silver/silver.png); + +} + +/* Customize the toolbar. */ +QToolBar#toolBar_2 { + border-image: url(qss/silver/silver2.png); + +} + +QToolBar#chattoolBar{ + border-image: url(qss/silver/silver.png); + +} + +QDialog{ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F9F9FF, stop: 1 #9F9DB9); +} + +QPushButton#okButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelprefButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelButton { + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + + +QPushButton#applyButton { + + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + +QMenu::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F9F9FF, stop: 1 #9F9DB9); +} + +QListWidget::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F9F9FF, stop: 1 #9F9DB9); +} + +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F9F9FF, stop: 1 #9F9DB9); +} + +QStatusBar{ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F9F9FF, stop: 1 #9F9DB9); +} + +QFrame#messengerframetop{ + + border-image: url(qss/silver/silver.png); + + + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07);*/ +} + +QFrame#Chatbuttonframe{ + + border-image: url(qss/silver/silver.png); + +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} diff --git a/retroshare-gui/src/qss/silver/silver.png b/retroshare-gui/src/qss/silver/silver.png new file mode 100644 index 000000000..2559aa8d8 Binary files /dev/null and b/retroshare-gui/src/qss/silver/silver.png differ diff --git a/retroshare-gui/src/qss/silver/silver2.png b/retroshare-gui/src/qss/silver/silver2.png new file mode 100644 index 000000000..fe875f925 Binary files /dev/null and b/retroshare-gui/src/qss/silver/silver2.png differ diff --git a/retroshare-gui/src/qss/silvergrey.qss b/retroshare-gui/src/qss/silvergrey.qss new file mode 100644 index 000000000..b4b997dc9 --- /dev/null +++ b/retroshare-gui/src/qss/silvergrey.qss @@ -0,0 +1,150 @@ +.QWidget { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); + } + +QDialog{ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); +} + +/* Customize the toolbar. */ +QToolBar { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); +} + +QStatusBar { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); +} + + +QHeaderView::section { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #616161, stop: 0.5 #505050, + stop: 0.6 #434343, stop:1 #656565); + color: white; + padding-left: 4px; + border: 1px solid #6c6c6c; + } + + + QMenuBar { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); + } + + QTabWidget::pane { /* The tab widget frame */ + border-top: 2px solid #C2C7CB; + } + + QTabWidget::tab-bar { + left: 0px; /* move to the right by 5px */ + } + + /* Style the tab using the tab sub-control. Note that + it reads QTabBar _not_ QTabWidget */ + QTabBar::tab { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, + stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); + border: 2px solid #C4C4C3; + border-bottom-color: #C2C7CB; /* same as the pane color */ + border-top-left-radius: 4px; + border-top-right-radius: 4px; + min-width: 8ex; + padding: 2px; + } + + QTabBar::tab:selected, QTabBar::tab:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #fafafa, stop: 0.4 #f4f4f4, + stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); + } + + QTabBar::tab:selected { + border-color: #9B9B9B; + border-bottom-color: #C2C7CB; /* same as pane color */ + } + + QTabBar::tab:!selected { + margin-top: 2px; /* make non-selected tabs look smaller */ + } + +QMenu { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); + border: 1px solid black; + } + +QMenu::item { + /* sets background of menu item. set this to something non-transparent + if you want menu color and menu item color to be different */ + /*background-color: transparent;*/ + } + +QMenu::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6F6F6F, stop:1 #979797); + } + +QListWidget::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6F6F6F, stop:1 #979797); +} + +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6F6F6F, stop:1 #979797); +} + +QTreeView::item:selected { /* when user selects item using mouse or keyboard */ + + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop:0 #6F6F6F, stop:1 #979797); + +} + +QFrame#messengerframetop{ + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); +} + +QFrame#Chatbuttonframe{ + + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6F6F6F, stop:1 #979797); +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} diff --git a/retroshare-gui/src/qss/uus.qss b/retroshare-gui/src/qss/uus.qss new file mode 100644 index 000000000..7f9bf4e2f --- /dev/null +++ b/retroshare-gui/src/qss/uus.qss @@ -0,0 +1,286 @@ +.QWidget { + /*background-color: black;*/ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #376D85, stop: 0.4 #185772); + +} + +QDialog{ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #376D85, stop: 0.4 #185772); +} + + +/* Customize the toolbar. */ +QToolBar#toolBar { + border-image: url(qss/uus/uus.png); + +} +QToolBar#toolBar_2 { + border-image: url(qss/uus/uus2.png); + +} + +QToolBar#chattoolBar{ + border-image: url(qss/uus/uus.png); + + +} + +QFrame#frame_2{ +background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #376D85, stop: 0.4 #185772); + border: 1px solid #CCCCCC; + +} + +QFrame#buttonframe{ +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FEFEFE, stop:1 #E8E8E8); +} + +/* it works only at the moment with vista Thema on XP*/ +QToolButton::hover { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); + + +} + +QToolButton::pressed { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); + + +} + +/* Style the tab using the tab sub-control. Note that + it reads QTabBar _not_ QTabWidget */ +QTabBar::tab { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); + border: 2px solid #BDDF7D; + border-bottom-color: #49881F; /* same as the pane color */ + border-top-left-radius: 4px; + border-top-right-radius: 4px; + min-width: 8ex; + padding: 2px; + +} + +QTabBar::tab:!selected { + margin-top: 2px; /* make non-selected tabs look smaller */ + +} + +QTabBar::tab:selected, QTabBar::tab:hover { + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F0F8CB, stop: 1 #F0F8CD); + +} + +QTabBar::tab:selected { + border-color: #9B9B9B; + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F5FFBC, stop: 1 #609C08); +} + +QHeaderView::section { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); + color: white; + padding-left: 4px; + border: 1px solid #6c6c6c; + } + +QPushButton#okButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelprefButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelButton { + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + + +QPushButton#applyButton { + + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + +QPushButton { + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); + border: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F);*/ +} + + +QPushButton::hover { + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F0F8CB, stop: 1 #F0F8CD);*/ +} + +QPushButton::pressed { + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F5FFBC, stop: 1 #609C08);*/ +} + + +QLabel +{ +color: white; +} + +QStatusBar{ + border-image: url(qss/uus/uus.png); + +} + +QMenu { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #376D85, stop: 1 #185772); + border: 1px solid black; + } + +QMenu::item:selected { /* when user selects item using mouse or keyboard */ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); +} + +QListWidget::item:selected { /* when user selects item using mouse or keyboard */ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); +} + +QTreeWidget { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #376D85, stop: 1 #185772); + + } + + +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); + +} + +QTreeView { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #376D85, stop: 1 #185772); + + } + +QTreeView::item:selected { /* when user selects item using mouse or keyboard */ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); + +} + +QToolTip{ + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07); +} + +QFrame#messengerframetop{ + + border-image: url(qss/uus/uus.png); + + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07);*/ +} + +QFrame#Chatbuttonframe{ + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); + +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} + +QLabel#friendstitlellabel{ + color: black; +} + +QLabel#friendslabel{ + color: black; +} + +QLabel#networklabel{ + color: black; +} + +QLabel#channellabel{ + color: black; +} + +QLabel#forumslabel{ + color: black; +} + +QLabel#downloadslabel{ + color: black; +} + +QLabel#forumName{ + color: black; +} + +QLabel#threadTitle{ + color: black; +} + + +QLabel#labeltext{ + color: black; +} + +QStatusBar { + + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #BDDF7D, stop: 1 #49881F); + +} \ No newline at end of file diff --git a/retroshare-gui/src/qss/uus/Thumbs.db b/retroshare-gui/src/qss/uus/Thumbs.db new file mode 100644 index 000000000..0cac47bd7 Binary files /dev/null and b/retroshare-gui/src/qss/uus/Thumbs.db differ diff --git a/retroshare-gui/src/qss/uus/uus.png b/retroshare-gui/src/qss/uus/uus.png new file mode 100644 index 000000000..1e4f98f98 Binary files /dev/null and b/retroshare-gui/src/qss/uus/uus.png differ diff --git a/retroshare-gui/src/qss/uus/uus2.png b/retroshare-gui/src/qss/uus/uus2.png new file mode 100644 index 000000000..6036684b0 Binary files /dev/null and b/retroshare-gui/src/qss/uus/uus2.png differ diff --git a/retroshare-gui/src/qss/wx.qss b/retroshare-gui/src/qss/wx.qss new file mode 100644 index 000000000..f14cd31a2 --- /dev/null +++ b/retroshare-gui/src/qss/wx.qss @@ -0,0 +1,77 @@ + +/* Customize the toolbar. */ +QToolBar { + border-image: url(qss/wx/wx.png); + +} + + +QPushButton#okButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelprefButton { + min-height: 27px; + min-width: 77px; +} + +QPushButton#cancelButton { + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + + +QPushButton#applyButton { + + min-height: 25px; + max-height: 25px; + min-width: 75px; +} + + +QFrame#messengerframetop{ + + border-image: url(qss/wx/wx.png); + + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07);*/ +} + +QFrame#Chatbuttonframe{ + + border-image: url(qss/wx/wx.png); + +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} diff --git a/retroshare-gui/src/qss/wx/Thumbs.db b/retroshare-gui/src/qss/wx/Thumbs.db new file mode 100644 index 000000000..20909753f Binary files /dev/null and b/retroshare-gui/src/qss/wx/Thumbs.db differ diff --git a/retroshare-gui/src/qss/wx/wx.png b/retroshare-gui/src/qss/wx/wx.png new file mode 100644 index 000000000..afc00a550 Binary files /dev/null and b/retroshare-gui/src/qss/wx/wx.png differ diff --git a/retroshare-gui/src/qss/yaba.qss b/retroshare-gui/src/qss/yaba.qss new file mode 100644 index 000000000..7a11672e0 --- /dev/null +++ b/retroshare-gui/src/qss/yaba.qss @@ -0,0 +1,181 @@ +.QWidget { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6F6F6F, stop:1 #979797); + } + +QDialog, QMainWindow, QStatusBar{ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6F6F6F, stop:1 #979797); +} + +QWidget#chatcentralwidget{ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6F6F6F, stop:1 #979797); +} + +/* Customize the toolbar. */ +QToolBar#toolBar { + border-image: url(qss/yaba/yaba.png); + +} + +QToolBar#toolBar_2 { + border-image: url(qss/yaba/yaba2.png); + +} + +QFrame#frame_2{ + border-image: url(qss/yaba/yaba3.png); + +} + +QFrame#buttonframe{ + border-image: url(qss/yaba/yaba3.png); + +} + +QFrame#chheaderframe{ + border-image: url(qss/yaba/yaba3.png); + +} +QFrame#frame{ + border-image: url(qss/yaba/yaba3.png); + +} + +QHeaderView::section { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #616161, stop: 0.5 #505050, + stop: 0.6 #434343, stop:1 #656565); + color: white; + padding-left: 4px; + border: 1px solid #6c6c6c; + } + + + QMenuBar { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #626262, stop:1 #989898); + } + + QTabWidget::pane { /* The tab widget frame */ + border-top: 2px solid #C2C7CB; + } + + QTabWidget::tab-bar { + left: 0px; /* move to the right by 5px */ + } + + /* Style the tab using the tab sub-control. Note that + it reads QTabBar _not_ QTabWidget */ + QTabBar::tab { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, + stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); + border: 2px solid #C4C4C3; + border-bottom-color: #C2C7CB; /* same as the pane color */ + border-top-left-radius: 4px; + border-top-right-radius: 4px; + min-width: 8ex; + padding: 2px; + } + + QTabBar::tab:selected, QTabBar::tab:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #fafafa, stop: 0.4 #f4f4f4, + stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); + } + + QTabBar::tab:selected { + border-color: #9B9B9B; + border-bottom-color: #C2C7CB; /* same as pane color */ + } + + QTabBar::tab:!selected { + margin-top: 2px; /* make non-selected tabs look smaller */ + } + +QMenu { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6F6F6F, stop:1 #979797); + border: 1px solid black; + } + + +QMenu::item { + /* sets background of menu item. set this to something non-transparent + if you want menu color and menu item color to be different */ + background-color: transparent; + } + +QMenu::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FBC957, stop:1 #D79704); + } + +QListWidget::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FBC957, stop:1 #D79704); +} + +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FBC957, stop:1 #D79704); +} + +QTreeView::item:selected { /* when user selects item using mouse or keyboard */ + + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #FBC957, stop: 1 #D79704); + +} + +QFrame#messengerframetop{ + + border-image: url(qss/yaba/yaba.png); + + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07);*/ +} + +QFrame#Chatbuttonframe{ + + border-image: url(qss/yaba/yaba.png); + +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} + +QLabel#fromText{ + font: bold ; + color: blue; + +} + +QToolBar#chattoolBar{ + border-image: url(qss/yaba/yaba.png); + +} diff --git a/retroshare-gui/src/qss/yaba/Thumbs.db b/retroshare-gui/src/qss/yaba/Thumbs.db new file mode 100644 index 000000000..bc0e38256 Binary files /dev/null and b/retroshare-gui/src/qss/yaba/Thumbs.db differ diff --git a/retroshare-gui/src/qss/yaba/yaba.png b/retroshare-gui/src/qss/yaba/yaba.png new file mode 100644 index 000000000..e8659f66d Binary files /dev/null and b/retroshare-gui/src/qss/yaba/yaba.png differ diff --git a/retroshare-gui/src/qss/yaba/yaba2.png b/retroshare-gui/src/qss/yaba/yaba2.png new file mode 100644 index 000000000..af6be6117 Binary files /dev/null and b/retroshare-gui/src/qss/yaba/yaba2.png differ diff --git a/retroshare-gui/src/qss/yaba/yaba3.png b/retroshare-gui/src/qss/yaba/yaba3.png new file mode 100644 index 000000000..5dd5a2a32 Binary files /dev/null and b/retroshare-gui/src/qss/yaba/yaba3.png differ diff --git a/retroshare-gui/src/qss/yeah.qss b/retroshare-gui/src/qss/yeah.qss new file mode 100644 index 000000000..1deb61008 --- /dev/null +++ b/retroshare-gui/src/qss/yeah.qss @@ -0,0 +1,153 @@ +.QWidget { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); +} + + +QDialog{ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); +} + + +/* Customize the toolbar. */ +QToolBar { + border-image: url(qss/yeah/yeah.png); + +} + +QStatusBar{ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); +} + + +QHeaderView::section { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #616161, stop: 0.5 #505050, + stop: 0.6 #434343, stop:1 #656565); + color: white; + padding-left: 4px; + border: 1px solid #6c6c6c; +} + + +QMenuBar { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); +} + + QTabWidget::pane { /* The tab widget frame */ + border-top: 2px solid #C2C7CB; + } + + QTabWidget::tab-bar { + left: 0px; /* move to the right by 5px */ + } + + /* Style the tab using the tab sub-control. Note that + it reads QTabBar _not_ QTabWidget */ + QTabBar::tab { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #E1E1E1, stop: 0.4 #DDDDDD, + stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3); + border: 2px solid #C4C4C3; + border-bottom-color: #C2C7CB; /* same as the pane color */ + border-top-left-radius: 4px; + border-top-right-radius: 4px; + min-width: 8ex; + padding: 2px; + } + + QTabBar::tab:selected, QTabBar::tab:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #fafafa, stop: 0.4 #f4f4f4, + stop: 0.5 #e7e7e7, stop: 1.0 #fafafa); + } + + QTabBar::tab:selected { + border-color: #9B9B9B; + border-bottom-color: #C2C7CB; /* same as pane color */ + } + + QTabBar::tab:!selected { + margin-top: 2px; /* make non-selected tabs look smaller */ + } + + QMenu { + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 lightgray, stop:1 darkgray); + border: 1px solid black; + } + +QMenu::item { + /* sets background of menu item. set this to something non-transparent + if you want menu color and menu item color to be different */ + background-color: transparent; + } + +QMenu::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FBC957, stop:1 #D79704); + } + +QListWidget::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FBC957, stop:1 #D79704); +} + +QTreeWidget::item:selected { /* when user selects item using mouse or keyboard */ + background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FBC957, stop:1 #D79704); +} + +QTreeView::item:selected { /* when user selects item using mouse or keyboard */ + + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #FBC957, stop: 1 #D79704); + +} + +QFrame#messengerframetop{ + + border-image: url(qss/yeah/yeah.png); + + /*background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #F7B552, stop: 1 #FF5E07);*/ +} + +QFrame#Chatbuttonframe{ + + border-image: url(qss/yeah/yeah.png); + +} + +QLabel#subjectText{ + font: bold 12px; + +} + +QLabel#subjectlabel{ + font: bold 12px; + +} + +QLabel#fromlabel{ + font: bold 12px; + +} + +QLabel#datelabel{ + font: bold 12px; + +} + +QLabel#tolabel{ + font: bold 12px; + +} +QLabel#fromText{ + font: bold ; + color: blue; + +} diff --git a/retroshare-gui/src/qss/yeah/Thumbs.db b/retroshare-gui/src/qss/yeah/Thumbs.db new file mode 100644 index 000000000..6bb0ea39b Binary files /dev/null and b/retroshare-gui/src/qss/yeah/Thumbs.db differ diff --git a/retroshare-gui/src/qss/yeah/yeah.png b/retroshare-gui/src/qss/yeah/yeah.png new file mode 100644 index 000000000..bd31010f7 Binary files /dev/null and b/retroshare-gui/src/qss/yeah/yeah.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/maxButton.png b/retroshare-gui/src/release/skin/Bliss/maxButton.png new file mode 100644 index 000000000..4d83bcd35 Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/maxButton.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/maxButton1.png b/retroshare-gui/src/release/skin/Bliss/maxButton1.png new file mode 100644 index 000000000..a916ba483 Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/maxButton1.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/maxButton2.png b/retroshare-gui/src/release/skin/Bliss/maxButton2.png new file mode 100644 index 000000000..aaba43674 Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/maxButton2.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/minButton.png b/retroshare-gui/src/release/skin/Bliss/minButton.png new file mode 100644 index 000000000..7f1553a6e Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/minButton.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/minButton1.png b/retroshare-gui/src/release/skin/Bliss/minButton1.png new file mode 100644 index 000000000..a3c564cdd Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/minButton1.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/minButton2.png b/retroshare-gui/src/release/skin/Bliss/minButton2.png new file mode 100644 index 000000000..01af810b0 Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/minButton2.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/quiButton.png b/retroshare-gui/src/release/skin/Bliss/quiButton.png new file mode 100644 index 000000000..6a657ae1a Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/quiButton.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/quiButton1.png b/retroshare-gui/src/release/skin/Bliss/quiButton1.png new file mode 100644 index 000000000..174c7b2ee Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/quiButton1.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/quiButton2.png b/retroshare-gui/src/release/skin/Bliss/quiButton2.png new file mode 100644 index 000000000..f379e9431 Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/quiButton2.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/sl.png b/retroshare-gui/src/release/skin/Bliss/sl.png new file mode 100644 index 000000000..851821b6a Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/sl.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/so.png b/retroshare-gui/src/release/skin/Bliss/so.png new file mode 100644 index 000000000..6497639b3 Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/so.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/sr.png b/retroshare-gui/src/release/skin/Bliss/sr.png new file mode 100644 index 000000000..6689549b3 Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/sr.png differ diff --git a/retroshare-gui/src/release/skin/Bliss/su.png b/retroshare-gui/src/release/skin/Bliss/su.png new file mode 100644 index 000000000..9862742f0 Binary files /dev/null and b/retroshare-gui/src/release/skin/Bliss/su.png differ diff --git a/retroshare-gui/src/release/skin/Glassy/Thumbs.db b/retroshare-gui/src/release/skin/Glassy/Thumbs.db new file mode 100644 index 000000000..4936258e2 Binary files /dev/null and b/retroshare-gui/src/release/skin/Glassy/Thumbs.db differ diff --git a/retroshare-gui/src/release/skin/Glassy/maxButton.png b/retroshare-gui/src/release/skin/Glassy/maxButton.png new file mode 100644 index 000000000..469d21e40 Binary files /dev/null and b/retroshare-gui/src/release/skin/Glassy/maxButton.png differ diff --git a/retroshare-gui/src/release/skin/Glassy/minButton.png b/retroshare-gui/src/release/skin/Glassy/minButton.png new file mode 100644 index 000000000..40c6ba78c Binary files /dev/null and b/retroshare-gui/src/release/skin/Glassy/minButton.png differ diff --git a/retroshare-gui/src/release/skin/Glassy/quiButton.png b/retroshare-gui/src/release/skin/Glassy/quiButton.png new file mode 100644 index 000000000..da6390211 Binary files /dev/null and b/retroshare-gui/src/release/skin/Glassy/quiButton.png differ diff --git a/retroshare-gui/src/release/skin/Glassy/sl.png b/retroshare-gui/src/release/skin/Glassy/sl.png new file mode 100644 index 000000000..f259a74c7 Binary files /dev/null and b/retroshare-gui/src/release/skin/Glassy/sl.png differ diff --git a/retroshare-gui/src/release/skin/Glassy/so.png b/retroshare-gui/src/release/skin/Glassy/so.png new file mode 100644 index 000000000..9b554663d Binary files /dev/null and b/retroshare-gui/src/release/skin/Glassy/so.png differ diff --git a/retroshare-gui/src/release/skin/Glassy/sr.png b/retroshare-gui/src/release/skin/Glassy/sr.png new file mode 100644 index 000000000..f259a74c7 Binary files /dev/null and b/retroshare-gui/src/release/skin/Glassy/sr.png differ diff --git a/retroshare-gui/src/release/skin/Glassy/su.png b/retroshare-gui/src/release/skin/Glassy/su.png new file mode 100644 index 000000000..0e96fdbed Binary files /dev/null and b/retroshare-gui/src/release/skin/Glassy/su.png differ diff --git a/retroshare-gui/src/release/skin/Green/Thumbs.db b/retroshare-gui/src/release/skin/Green/Thumbs.db new file mode 100644 index 000000000..1e5860e7c Binary files /dev/null and b/retroshare-gui/src/release/skin/Green/Thumbs.db differ diff --git a/retroshare-gui/src/release/skin/Green/maxButton.png b/retroshare-gui/src/release/skin/Green/maxButton.png new file mode 100644 index 000000000..73f1fc27d Binary files /dev/null and b/retroshare-gui/src/release/skin/Green/maxButton.png differ diff --git a/retroshare-gui/src/release/skin/Green/minButton.png b/retroshare-gui/src/release/skin/Green/minButton.png new file mode 100644 index 000000000..1c9adaa6c Binary files /dev/null and b/retroshare-gui/src/release/skin/Green/minButton.png differ diff --git a/retroshare-gui/src/release/skin/Green/quiButton.png b/retroshare-gui/src/release/skin/Green/quiButton.png new file mode 100644 index 000000000..6134015ef Binary files /dev/null and b/retroshare-gui/src/release/skin/Green/quiButton.png differ diff --git a/retroshare-gui/src/release/skin/Green/sl.png b/retroshare-gui/src/release/skin/Green/sl.png new file mode 100644 index 000000000..06af00e82 Binary files /dev/null and b/retroshare-gui/src/release/skin/Green/sl.png differ diff --git a/retroshare-gui/src/release/skin/Green/so.png b/retroshare-gui/src/release/skin/Green/so.png new file mode 100644 index 000000000..661ffd761 Binary files /dev/null and b/retroshare-gui/src/release/skin/Green/so.png differ diff --git a/retroshare-gui/src/release/skin/Green/sr.png b/retroshare-gui/src/release/skin/Green/sr.png new file mode 100644 index 000000000..7f62f1c0b Binary files /dev/null and b/retroshare-gui/src/release/skin/Green/sr.png differ diff --git a/retroshare-gui/src/release/skin/Green/su.png b/retroshare-gui/src/release/skin/Green/su.png new file mode 100644 index 000000000..8e04d5077 Binary files /dev/null and b/retroshare-gui/src/release/skin/Green/su.png differ diff --git a/retroshare-gui/src/release/skin/Night Vision/maxButton.png b/retroshare-gui/src/release/skin/Night Vision/maxButton.png new file mode 100644 index 000000000..cbb27c3cb Binary files /dev/null and b/retroshare-gui/src/release/skin/Night Vision/maxButton.png differ diff --git a/retroshare-gui/src/release/skin/Night Vision/minButton.png b/retroshare-gui/src/release/skin/Night Vision/minButton.png new file mode 100644 index 000000000..5892a982c Binary files /dev/null and b/retroshare-gui/src/release/skin/Night Vision/minButton.png differ diff --git a/retroshare-gui/src/release/skin/Night Vision/quiButton.png b/retroshare-gui/src/release/skin/Night Vision/quiButton.png new file mode 100644 index 000000000..1443caa9d Binary files /dev/null and b/retroshare-gui/src/release/skin/Night Vision/quiButton.png differ diff --git a/retroshare-gui/src/release/skin/Night Vision/sl.png b/retroshare-gui/src/release/skin/Night Vision/sl.png new file mode 100644 index 000000000..acc9db3d1 Binary files /dev/null and b/retroshare-gui/src/release/skin/Night Vision/sl.png differ diff --git a/retroshare-gui/src/release/skin/Night Vision/so.png b/retroshare-gui/src/release/skin/Night Vision/so.png new file mode 100644 index 000000000..900e051a9 Binary files /dev/null and b/retroshare-gui/src/release/skin/Night Vision/so.png differ diff --git a/retroshare-gui/src/release/skin/Night Vision/sr.png b/retroshare-gui/src/release/skin/Night Vision/sr.png new file mode 100644 index 000000000..0d0f296ec Binary files /dev/null and b/retroshare-gui/src/release/skin/Night Vision/sr.png differ diff --git a/retroshare-gui/src/release/skin/Night Vision/su.png b/retroshare-gui/src/release/skin/Night Vision/su.png new file mode 100644 index 000000000..32b195e0d Binary files /dev/null and b/retroshare-gui/src/release/skin/Night Vision/su.png differ diff --git a/retroshare-gui/src/release/skin/Vista/maxButton.png b/retroshare-gui/src/release/skin/Vista/maxButton.png new file mode 100644 index 000000000..cbb27c3cb Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/maxButton.png differ diff --git a/retroshare-gui/src/release/skin/Vista/maxButton1.png b/retroshare-gui/src/release/skin/Vista/maxButton1.png new file mode 100644 index 000000000..1bed27a49 Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/maxButton1.png differ diff --git a/retroshare-gui/src/release/skin/Vista/maxButton2.png b/retroshare-gui/src/release/skin/Vista/maxButton2.png new file mode 100644 index 000000000..a9ece6da2 Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/maxButton2.png differ diff --git a/retroshare-gui/src/release/skin/Vista/minButton.png b/retroshare-gui/src/release/skin/Vista/minButton.png new file mode 100644 index 000000000..5892a982c Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/minButton.png differ diff --git a/retroshare-gui/src/release/skin/Vista/minButton1.png b/retroshare-gui/src/release/skin/Vista/minButton1.png new file mode 100644 index 000000000..79207e5df Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/minButton1.png differ diff --git a/retroshare-gui/src/release/skin/Vista/minButton2.png b/retroshare-gui/src/release/skin/Vista/minButton2.png new file mode 100644 index 000000000..b52bdb299 Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/minButton2.png differ diff --git a/retroshare-gui/src/release/skin/Vista/quiButton.png b/retroshare-gui/src/release/skin/Vista/quiButton.png new file mode 100644 index 000000000..1443caa9d Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/quiButton.png differ diff --git a/retroshare-gui/src/release/skin/Vista/quiButton1.png b/retroshare-gui/src/release/skin/Vista/quiButton1.png new file mode 100644 index 000000000..008b25e2e Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/quiButton1.png differ diff --git a/retroshare-gui/src/release/skin/Vista/quiButton2.png b/retroshare-gui/src/release/skin/Vista/quiButton2.png new file mode 100644 index 000000000..3e79d9f08 Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/quiButton2.png differ diff --git a/retroshare-gui/src/release/skin/Vista/sl.png b/retroshare-gui/src/release/skin/Vista/sl.png new file mode 100644 index 000000000..05628496b Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/sl.png differ diff --git a/retroshare-gui/src/release/skin/Vista/so.png b/retroshare-gui/src/release/skin/Vista/so.png new file mode 100644 index 000000000..d9472686c Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/so.png differ diff --git a/retroshare-gui/src/release/skin/Vista/sr.png b/retroshare-gui/src/release/skin/Vista/sr.png new file mode 100644 index 000000000..60e8e091f Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/sr.png differ diff --git a/retroshare-gui/src/release/skin/Vista/su.png b/retroshare-gui/src/release/skin/Vista/su.png new file mode 100644 index 000000000..c62254cfb Binary files /dev/null and b/retroshare-gui/src/release/skin/Vista/su.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/bg.png b/retroshare-gui/src/release/skin/VistaAlpha/bg.png new file mode 100644 index 000000000..f7ead614a Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/bg.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/maxButton.png b/retroshare-gui/src/release/skin/VistaAlpha/maxButton.png new file mode 100644 index 000000000..bb1c53ee4 Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/maxButton.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/maxButton1.png b/retroshare-gui/src/release/skin/VistaAlpha/maxButton1.png new file mode 100644 index 000000000..1bed27a49 Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/maxButton1.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/maxButton2.png b/retroshare-gui/src/release/skin/VistaAlpha/maxButton2.png new file mode 100644 index 000000000..a9ece6da2 Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/maxButton2.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/minButton.png b/retroshare-gui/src/release/skin/VistaAlpha/minButton.png new file mode 100644 index 000000000..379bfa4cb Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/minButton.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/minButton1.png b/retroshare-gui/src/release/skin/VistaAlpha/minButton1.png new file mode 100644 index 000000000..79207e5df Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/minButton1.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/minButton2.png b/retroshare-gui/src/release/skin/VistaAlpha/minButton2.png new file mode 100644 index 000000000..b52bdb299 Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/minButton2.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/quiButton.png b/retroshare-gui/src/release/skin/VistaAlpha/quiButton.png new file mode 100644 index 000000000..e3882e9ff Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/quiButton.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/quiButton1.png b/retroshare-gui/src/release/skin/VistaAlpha/quiButton1.png new file mode 100644 index 000000000..008b25e2e Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/quiButton1.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/quiButton2.png b/retroshare-gui/src/release/skin/VistaAlpha/quiButton2.png new file mode 100644 index 000000000..3e79d9f08 Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/quiButton2.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/sl.png b/retroshare-gui/src/release/skin/VistaAlpha/sl.png new file mode 100644 index 000000000..82deb022e Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/sl.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/so.png b/retroshare-gui/src/release/skin/VistaAlpha/so.png new file mode 100644 index 000000000..677255b01 Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/so.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/sr.png b/retroshare-gui/src/release/skin/VistaAlpha/sr.png new file mode 100644 index 000000000..22f2e74fe Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/sr.png differ diff --git a/retroshare-gui/src/release/skin/VistaAlpha/su.png b/retroshare-gui/src/release/skin/VistaAlpha/su.png new file mode 100644 index 000000000..6f19cdc00 Binary files /dev/null and b/retroshare-gui/src/release/skin/VistaAlpha/su.png differ diff --git a/retroshare-gui/src/release/skin/skin.dat b/retroshare-gui/src/release/skin/skin.dat new file mode 100644 index 000000000..7a501621c --- /dev/null +++ b/retroshare-gui/src/release/skin/skin.dat @@ -0,0 +1,7 @@ +[Skin] +Blur=false +Hintergrundfarbe=@Variant(\0\0\0\x43\x1\xff\xff\xd5\xd5\xd5\xd5\xd5\xd5\0\0) +SkinOn=true +Skinpfad=skin/Vista/ +Titelfarbe=@Variant(\0\0\0\x43\x1\xff\xff\0\0\0\0\0\0\0\0) +Titelschrift=@Variant(\0\0\0@\0\0\0\x1a\0\x43\0o\0m\0i\0\x63\0 \0S\0\x61\0n\0s\0 \0M\0S@$\0\0\0\0\0\0\xff\xff\xff\xff\x5\x1\0K\x10) diff --git a/retroshare-gui/src/retroshare-portable.nsi b/retroshare-gui/src/retroshare-portable.nsi new file mode 100644 index 000000000..e12617b25 --- /dev/null +++ b/retroshare-gui/src/retroshare-portable.nsi @@ -0,0 +1,473 @@ +; Script generated with the Venis Install Wizard & modified by defnax + +; Define your application name +!define APPNAME "RetroShare" +!define VERSION "0.5.1 4069" +!define APPNAMEANDVERSION "${APPNAME} Portable ${VERSION}" +!define QTBASE "D:\qt\2010.01" + +; Main Install settings +Name "${APPNAMEANDVERSION}" +InstallDir "$PROGRAMFILES\RetroShare" +InstallDirRegKey HKLM "Software\${APPNAME}" "" +OutFile "RetroSharePortable_${VERSION}_setup.exe" +BrandingText "${APPNAMEANDVERSION}" +; Use compression +SetCompressor /SOLID LZMA + +; Modern interface settings +!include Sections.nsh +!include "UMUI.nsh" + +;Interface Settings +!define MUI_ABORTWARNING +;!define MUI_HEADERIMAGE +;!define MUI_HEADERIMAGE_BITMAP "retroshare.bmp" ; optional + +# MUI defines +!define MUI_ICON "${NSISDIR}\Contrib\Graphics\UltraModernUI\Icon.ico" +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_LICENSEPAGE_RADIOBUTTONS +!define MUI_COMPONENTSPAGE_SMALLDESC +!define MUI_FINISHPAGE_LINK "Visit the RetroShare forum for the latest news and support" +!define MUI_FINISHPAGE_LINK_LOCATION "http://retroshare.sourceforge.net/forum/" +!define MUI_FINISHPAGE_RUN "$INSTDIR\RetroShare.exe" +!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_TEXT changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\UltraModernUI\UnIcon.ico" +!define MUI_UNFINISHPAGE_NOAUTOCLOSE +!define MUI_LANGDLL_REGISTRY_ROOT HKLM +!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY} +!define UMUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage + +;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without havinf to reboot your computer. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + +;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + + +; Defines the un-/installer logo of RetroShare +!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp" +!insertmacro MUI_DEFAULT MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp" + +; Set languages (first is default language) +!insertmacro MUI_RESERVEFILE_LANGDLL +ReserveFile "${NSISDIR}\Plugins\AdvSplash.dll" + +;-------------------------------- +;Configuration + + + ;!insertmacro MUI_RESERVEFILE_SPECIALBITMAP + + LicenseLangString myLicenseData 1030 "license\license.txt" + LicenseLangString myLicenseData 1033 "license\license.txt" + LicenseLangString myLicenseData 1031 "license\license-GER.txt" + LicenseLangString myLicenseData 1036 "license\license-FR.txt" + LicenseLangString myLicenseData 1055 "license\license-TR.txt" + LicenseLangString myLicenseData 2052 "license\license.txt" + LicenseLangString myLicenseData 1045 "license\license.txt" + LicenseLangString myLicenseData 1041 "license\license.txt" + LicenseLangString myLicenseData 1042 "license\license.txt" + LicenseLangString myLicenseData 1049 "license\license.txt" + LicenseLangString myLicenseData 1053 "license\license.txt" + + LicenseData $(myLicenseData) + +# Installer pages +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +# Installer languages +!define MUI_LANGDLL_ALLLANGUAGES + +!insertmacro MUI_LANGUAGE Danish +!insertmacro MUI_LANGUAGE English +!insertmacro MUI_LANGUAGE French +!insertmacro MUI_LANGUAGE German +!insertmacro MUI_LANGUAGE Japanese +!insertmacro MUI_LANGUAGE Korean +!insertmacro MUI_LANGUAGE Polish +!insertmacro MUI_LANGUAGE Russian +!insertmacro MUI_LANGUAGE Swedish +!insertmacro MUI_LANGUAGE SimpChinese +!insertmacro MUI_LANGUAGE Turkish + + + + ;Component-selection page + ;Titles + + LangString sec_main ${LANG_ENGLISH} "Program Files" + LangString sec_data ${LANG_ENGLISH} "Program Skins" + LangString sec_shortcuts ${LANG_ENGLISH} "Shortcuts" + LangString sec_link ${LANG_ENGLISH} "File Association" + LangString sec_autostart ${LANG_ENGLISH} "Auto Startup" + LangString DESC_sec_main ${LANG_ENGLISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_ENGLISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_ENGLISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_ENGLISH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_ENGLISH} "1033" + + + LangString sec_main ${LANG_FRENCH} "RetroShare" + LangString sec_data ${LANG_FRENCH} "Programme de Skins" + LangString sec_shortcuts ${LANG_FRENCH} "Raccourcis" + LangString sec_link ${LANG_FRENCH} "RetroShare fichiers Association" + LangString sec_startmenu ${LANG_FRENCH} "Raccourcis du menu Démarrer" + LangString sec_autostart ${LANG_FRENCH} "Démarrage automatique" + LangString DESC_sec_main ${LANG_FRENCH} "Installe les fichiers du programme." + LangString DESC_sec_data ${LANG_FRENCH} "Installe RetroShare Skins" + LangString DESC_sec_startmenu ${LANG_FRENCH} "Crée les raccourcis du menu Démarrer" + LangString DESC_sec_shortcuts ${LANG_FRENCH} "Crée une icône sur le bureau." + LangString DESC_sec_link ${LANG_FRENCH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_FRENCH} "1036" + + + LangString sec_main ${LANG_GERMAN} "Programmdateien" + LangString sec_data ${LANG_GERMAN} "Skins fuer das Programm" + LangString sec_shortcuts ${LANG_GERMAN} "Shortcuts" + LangString sec_link ${LANG_GERMAN} "Dateiverknuepfungen" + LangString sec_autostart ${LANG_GERMAN} "Auto Startup" + LangString DESC_sec_main ${LANG_GERMAN} "Installiert die erforderlichen Programmdateien." + LangString DESC_sec_data ${LANG_GERMAN} "Installiert RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_GERMAN} "Erstellt eine RetroShare Verkn�pfung im Startmen�, Desktop oder im Schnellstarter." + LangString DESC_sec_link ${LANG_GERMAN} "RetroShare mit .rsc Dateien verkn�pfen" + LangString LANGUAGEID ${LANG_GERMAN} "1031" + + LangString sec_main ${LANG_TURKISH} "Program Dosyalar�" + LangString sec_data ${LANG_TURKISH} "Program Skinleri" + LangString sec_shortcuts ${LANG_TURKISH} "Shortcut'lar" + LangString sec_link ${LANG_TURKISH} ".rsc Dosya Kaydet" + LangString sec_autostart ${LANG_TURKISH} "Otomatik calistir ve baglan" + LangString DESC_sec_main ${LANG_TURKISH} "Program dosyalar�n� kurar." + LangString DESC_sec_data ${LANG_TURKISH} "RetroShare Skin'leri kurar" + LangString DESC_sec_shortcuts ${TURKISH} "Shortcut yap Start menu , Desktop veya Quicklaunchbar icin." + LangString DESC_sec_link ${LANG_TURKISH} "RetroShare .rsc almas� i�in kaydettirir" + LangString LANGUAGEID ${LANG_TURKISH} "1055" + + LangString sec_main ${LANG_SIMPCHINESE} "程序文件" + LangString sec_data ${LANG_SIMPCHINESE} "程序皮肤" + LangString sec_shortcuts ${LANG_SIMPCHINESE} "快捷方式" + LangString sec_link ${LANG_SIMPCHINESE} "RetroShare文件关联" + LangString sec_autostart ${LANG_SIMPCHINESE} "自动启动" + LangString DESC_sec_main ${LANG_SIMPCHINESE} "安装RetroShare程序" + LangString DESC_sec_data ${LANG_SIMPCHINESE} "安装RetroShare皮肤" + LangString DESC_sec_shortcuts ${LANG_SIMPCHINESE} "建RetroShare快捷方式" + LangString DESC_sec_link ${LANG_SIMPCHINESE} "关联.rsc扩" + LangString LANGUAGEID ${LANG_SIMPCHINESE} "2052" + + LangString sec_main ${LANG_POLISH} "Pliki programu" + LangString sec_data ${LANG_POLISH} "Skórki" + LangString sec_shortcuts ${LANG_POLISH} "Skróty" + LangString sec_link ${LANG_POLISH} "Skojarz pliki" + LangString sec_autostart ${LANG_POLISH} "Automatyczne uruchamianie" + LangString DESC_sec_main ${LANG_POLISH} "Instaluje pliki programu RetroShare" + LangString DESC_sec_data ${LANG_POLISH} "Instaluje skórki programu RetroShare" + LangString DESC_sec_shortcuts ${LANG_POLISH} "Utwórz ikony skrótów na pulpicie, w menu start oraz na pasku szybkiego uruchamiania." + LangString DESC_sec_link ${LANG_POLISH} "Skojarz pliki o rozszerzeniu .rsc z RetroShare" + LangString LANGUAGEID ${LANG_POLISH} "1045" + + LangString sec_main ${LANG_DANISH} "Program Files" + LangString sec_data ${LANG_DANISH} "Program Skins" + LangString sec_shortcuts ${LANG_DANISH} "Shortcuts" + LangString sec_link ${LANG_DANISH} "File Association" + LangString sec_autostart ${LANG_DANISH} "Auto Startup" + LangString DESC_sec_main ${LANG_DANISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_DANISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_DANISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_DANISH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_DANISH} "1030" + + LangString sec_main ${LANG_RUSSIAN} "Program Files" + LangString sec_data ${LANG_RUSSIAN} "Program Skins" + LangString sec_shortcuts ${LANG_RUSSIAN} "Shortcuts" + LangString sec_link ${LANG_RUSSIAN} "File Association" + LangString sec_autostart ${LANG_RUSSIAN} "Auto Startup" + LangString DESC_sec_main ${LANG_RUSSIAN} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_RUSSIAN} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_RUSSIAN} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_RUSSIAN} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_RUSSIAN} "1049" + + LangString sec_main ${LANG_SWEDISH} "Program Files" + LangString sec_data ${LANG_SWEDISH} "Program Skins" + LangString sec_shortcuts ${LANG_SWEDISH} "Shortcuts" + LangString sec_link ${LANG_SWEDISH} "File Association" + LangString sec_autostart ${LANG_SWEDISH} "Auto Startup" + LangString DESC_sec_main ${LANG_SWEDISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_SWEDISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_SWEDISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_SWEDISH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_SWEDISH} "1053" + + LangString sec_main ${LANG_JAPANESE} "Program Files" + LangString sec_data ${LANG_JAPANESE} "Program Skins" + LangString sec_shortcuts ${LANG_JAPANESE} "Shortcuts" + LangString sec_link ${LANG_JAPANESE} "File Association" + LangString sec_autostart ${LANG_JAPANESE} "Auto Startup" + LangString DESC_sec_main ${LANG_JAPANESE} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_JAPANESE} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_JAPANESE} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_JAPANESE} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_JAPANESE} "1041" + + LangString sec_main ${LANG_KOREAN} "Program Files" + LangString sec_data ${LANG_KOREAN} "Program Skins" + LangString sec_shortcuts ${LANG_KOREAN} "Shortcuts" + LangString sec_link ${LANG_KOREAN} "File Association" + LangString sec_autostart ${LANG_KOREAN} "Auto Startup" + LangString DESC_sec_main ${LANG_KOREAN} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_KOREAN} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_KOREAN} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_KOREAN} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_KOREAN} "1042" + + +!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +Section $(sec_main) sec_main + + ;Set Section required + SectionIn RO + + ; Set Section properties + SetOverwrite on + + ; Clears previous error logs + Delete "$INSTDIR\*.log" + + ; Set Section Files and Shortcuts + SetOutPath "$INSTDIR\" + File /r "release\RetroShare.exe" + File /r "..\..\retroshare-nogui\src\release\retroshare-nogui.exe" + File /r "D:\Qt\2010.01\mingw\bin\mingwm10.dll" + File /r "D:\Qt\2010.01\qt\bin\QtCore4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtGui4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtNetwork4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtXml4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtScript4.dll" + File /r "D:\Qt\2010.01\qt\bin\libgcc_s_dw2-1.dll" + File /r "D:\Qt\2010.01\qt\plugins\imageformats" + File /r "D:\Development\miniupnpc-1.3\miniupnpc.dll" + File /r ${QTBASE}\qt\qt_*.qm + File /r "release\pthreadGC2d.dll" + File /r "release\libgpg-error-0.dll" + File /r "release\libgpgme-11.dll" + File /r "release\gpg.exe" + File /r "release\gpgme-w32spawn.exe" + File /r "changelog.txt" + File /r /x Data "release\bdboot.txt" + + +SectionEnd + +Section $(sec_data) sec_data + + ; Set Section properties + SetOverwrite on + + ; Set Section Files and Shortcuts + ;SetOutPath "$APPDATA\RetroShare\" + ;File /r "data\*" + + ; Set Section Plugins + ;SetOutPath "$APPDATA\RetroShare\plugins\" + ;File /r "plugins\" + + ; Set Section qss and exclude svn + SetOutPath "$INSTDIR\qss\" + File /r /x .svn qss\*.* + + ; Set Section sounds and exclude svn + SetOutPath "$INSTDIR\sounds\" + File /r /x .svn sounds\*.* + + ; Set Section skin + ; SetOutPath "$INSTDIR\skin\" + ; File /r release\skin\*.* + + ; Add emoticons + ;SetOutPath "$INSTDIR\emoticons\" + ;File /r emoticons\*.* + + ; Add Chat Style + ;SetOutPath "$INSTDIR\style\" + ;File /r style\*.* + +SectionEnd + +Section $(sec_link) sec_link + ; Delete any existing keys + + + ; Write the file association + WriteRegStr HKCR .rsc "" retroshare + WriteRegStr HKCR retroshare "" "RSC File" + WriteRegBin HKCR retroshare EditFlags 00000100 + WriteRegStr HKCR "retroshare\shell" "" open + WriteRegStr HKCR "retroshare\shell\open\command" "" `"$INSTDIR\RetroShare.exe" "%1"` + +SectionEnd + +SectionGroup $(sec_shortcuts) sec_shortcuts +Section StartMenu SEC0001 + + SetOutPath "$INSTDIR" + CreateDirectory "$SMPROGRAMS\${APPNAME}" + CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + CreateShortCut "$SMPROGRAMS\${APPNAME}\$(^UninstallLink).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + +SectionEnd + +Section Desktop SEC0002 + + + CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd + +Section Quicklaunchbar SEC0003 + + + CreateShortCut "$QUICKLAUNCH\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd +SectionGroupEnd + +;Section $(sec_autostart) sec_autostart + +; WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" "$INSTDIR\${APPNAME}.exe -a" + +;SectionEnd + +;Section $(sec_autostart) sec_autostart + +; CreateShortCut "$SMSTARTUP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 +;SectionEnd + + +Section -FinishSection + + WriteRegStr HKLM "Software\${APPNAME}" "" "$INSTDIR" + WriteRegStr HKLM "Software\${APPNAME}" "Version" "${VERSION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe" + WriteUninstaller "$INSTDIR\uninstall.exe" + +SectionEnd + + + +;-------------------------------- +;Descriptions + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${sec_main} $(DESC_sec_main) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_data} $(DESC_sec_data) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_shortcuts} $(DESC_sec_shortcuts) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_link} $(DESC_sec_link) + ;!insertmacro MUI_DESCRIPTION_TEXT ${sec_autostart} $(DESC_sec_autostart) +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +;Uninstall section +Section "Uninstall" + + ; Remove file association registry keys + DeleteRegKey HKCR .rsc + DeleteRegKey HKCR retroshare + + ; Remove program/uninstall regsitry keys + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" + DeleteRegKey HKLM SOFTWARE\${APPNAME} + + DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" + + ; Remove files and uninstaller + Delete $INSTDIR\RetroShare.exe + Delete $INSTDIR\retroshare-nogui.exe + Delete $INSTDIR\gpg.exe + Delete $INSTDIR\gpgme-w32spawn.exe + Delete $INSTDIR\*.dll + Delete $INSTDIR\*.dat + Delete $INSTDIR\*.txt + Delete $INSTDIR\*.ini + Delete $INSTDIR\*.log + + Delete $INSTDIR\uninstall.exe + + ; Don't remove the directory, otherwise + ; we lose the XPGP keys. + ; Should make this an option though... + + ; Remove shortcuts, if any + Delete "$SMPROGRAMS\${APPNAME}\*.*" + + ; Remove desktop shortcut + Delete "$DESKTOP\${APPNAME}.lnk" + + ; Remove Quicklaunch shortcut + Delete "$QUICKLAUNCH\${APPNAME}.lnk" + + ; Remove Autostart + ;Delete "$SMSTARTUP\${APPNAME}.lnk" + + ; Remove directories used + RMDir "$SMPROGRAMS\${APPNAME}" + RMDir /r "$INSTDIR\qss" + RMDir /r "$INSTDIR\translations" + RMDir /r "$INSTDIR\imageformats" + RMDir /r "$INSTDIR\sounds" + +SectionEnd + +Function .onInit + + InitPluginsDir + Push $R1 + File /oname=$PLUGINSDIR\spltmp.bmp "gui\images\splash.bmp" + advsplash::show 1200 1000 1000 -1 $PLUGINSDIR\spltmp + Pop $R1 + Pop $R1 + !insertmacro MUI_LANGDLL_DISPLAY + + + +FunctionEnd + + +# Installer Language Strings +# TODO Update the Language Strings with the appropriate translations. + +LangString FINISHPAGELINK ${LANG_ENGLISH} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_GERMAN} "Besuche RetroShare Support Forum " +LangString FINISHPAGELINK ${LANG_TURKISH} "Destek için Retroshare foruma ziyaret" +LangString FINISHPAGELINK ${LANG_FRENCH} "Consultez le forum RetroShare pour vous tenir au courant des dernieres modifications, et obtenir de l'aide." +LangString FINISHPAGELINK ${LANG_SIMPCHINESE} "帮助论坛" +LangString FINISHPAGELINK ${LANG_POLISH} "Odwiedź forum RetroShare do najświeższych informacji i wsparcia" +LangString FINISHPAGELINK ${LANG_DANISH} "Besøg RetroShare fora for de seneste nyheder og støtte" +LangString FINISHPAGELINK ${LANG_JAPANESE} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_KOREAN} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_RUSSIAN} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_SWEDISH} "Besök RetroShare forum för de senaste nyheterna och stöd" + +LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall" +LangString ^UninstallLink ${LANG_GERMAN} "Deinstallieren" +LangString ^UninstallLink ${LANG_TURKISH} "Kald�r" +LangString ^UninstallLink ${LANG_FRENCH} "Désinstaller" +LangString ^UninstallLink ${LANG_SIMPCHINESE} "卸载" +LangString ^UninstallLink ${LANG_POLISH} "Odinstaluj" +LangString ^UninstallLink ${LANG_DANISH} "Afinstaller" +LangString ^UninstallLink ${LANG_JAPANESE} "Uninstall" +LangString ^UninstallLink ${LANG_KOREAN} "Uninstall" +LangString ^UninstallLink ${LANG_RUSSIAN} "Uninstall" +LangString ^UninstallLink ${LANG_SWEDISH} "Avinstallera" + + +; eof diff --git a/retroshare-gui/src/retroshare-process.nsi b/retroshare-gui/src/retroshare-process.nsi new file mode 100644 index 000000000..685f90214 --- /dev/null +++ b/retroshare-gui/src/retroshare-process.nsi @@ -0,0 +1,502 @@ +; Script generated with the Venis Install Wizard & modified by defnax +; This script need the http://nsis.sourceforge.net/Processes_plug-in +; This script need the http://nsis.sourceforge.net/KillProcDLL_plug-in + +; Define your application name +!define APPNAME "RetroShare" +!define VERSION "0.4.13d" +!define APPNAMEANDVERSION "${APPNAME} ${VERSION}" + + +; Main Install settings +Name "${APPNAMEANDVERSION}" +InstallDir "$PROGRAMFILES\RetroShare" +InstallDirRegKey HKLM "Software\${APPNAME}" "" +OutFile "RetroShare_${VERSION}_setup.exe" +BrandingText "${APPNAMEANDVERSION}" +; Use compression +SetCompressor LZMA + +VAR KILLEXENAME + + +; Modern interface settings +!include Sections.nsh +!include "MUI.nsh" + +;Interface Settings +!define MUI_ABORTWARNING +;!define MUI_HEADERIMAGE +;!define MUI_HEADERIMAGE_BITMAP "retroshare.bmp" ; optional + +# MUI defines +!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico" +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_LICENSEPAGE_RADIOBUTTONS +!define MUI_COMPONENTSPAGE_SMALLDESC +!define MUI_FINISHPAGE_LINK "Visit the RetroShare forum for the latest news and support" +!define MUI_FINISHPAGE_LINK_LOCATION "http://retroshare.sourceforge.net/forum/" +!define MUI_FINISHPAGE_RUN "$INSTDIR\RetroShare.exe" +!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_TEXT changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico" +!define MUI_UNFINISHPAGE_NOAUTOCLOSE +!define MUI_LANGDLL_REGISTRY_ROOT HKLM +!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY} +!define MUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage + +; !define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without havinf to reboot your computer. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + +;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + + +; Defines the un-/installer logo of RetroShare +!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp" +!insertmacro MUI_DEFAULT MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp" + +; Set languages (first is default language) +!insertmacro MUI_RESERVEFILE_LANGDLL +ReserveFile "${NSISDIR}\Plugins\AdvSplash.dll" + +;-------------------------------- +;Configuration + + + ;!insertmacro MUI_RESERVEFILE_SPECIALBITMAP + + LicenseLangString myLicenseData 1033 "license\license.txt" + LicenseLangString myLicenseData 1031 "license\license-GER.txt" + LicenseLangString myLicenseData 1036 "license\license-FR.txt" + LicenseLangString myLicenseData 1055 "license\license-TR.txt" + LicenseLangString myLicenseData 2052 "license\license.txt" + LicenseLangString myLicenseData 1045 "license\license.txt" + + LicenseData $(myLicenseData) + +# Installer pages +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +# Installer languages +!define MUI_LANGDLL_ALLLANGUAGES + +!insertmacro MUI_LANGUAGE English +!insertmacro MUI_LANGUAGE German +!insertmacro MUI_LANGUAGE French +!insertmacro MUI_LANGUAGE Turkish +!insertmacro MUI_LANGUAGE SimpChinese +!insertmacro MUI_LANGUAGE Polish + + ;Component-selection page + ;Titles + + LangString sec_main ${LANG_ENGLISH} "Program Files" + LangString sec_data ${LANG_ENGLISH} "Program Skins" + LangString sec_shortcuts ${LANG_ENGLISH} "Shortcuts" + LangString sec_link ${LANG_ENGLISH} "File Association" + LangString sec_autostart ${LANG_ENGLISH} "Auto Startup" + LangString DESC_sec_main ${LANG_ENGLISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_ENGLISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_ENGLISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_ENGLISH} "Associate RetroShare with .pqi file extension" + LangString DESC_sec_autostart ${LANG_ENGLISH} "Auto-Run and Login at Startup" + LangString LANGUAGEID ${LANG_ENGLISH} "1033" + + LangString sec_main ${LANG_FRENCH} "RetroShare" + LangString sec_data ${LANG_FRENCH} "Programme de Skins" + LangString sec_shortcuts ${LANG_FRENCH} "Raccourcis" + LangString sec_link ${LANG_FRENCH} "RetroShare fichiers Association" + LangString sec_startmenu ${LANG_FRENCH} "Raccourcis du menu Démarrer" + LangString sec_autostart ${LANG_FRENCH} "Démarrage automatique" + LangString DESC_sec_main ${LANG_FRENCH} "Installe les fichiers du programme." + LangString DESC_sec_data ${LANG_FRENCH} "Installe RetroShare Skins" + LangString DESC_sec_startmenu ${LANG_FRENCH} "Crée les raccourcis du menu Démarrer" + LangString DESC_sec_shortcuts ${LANG_FRENCH} "Crée une icône sur le bureau." + LangString DESC_sec_link ${LANG_FRENCH} "Associate RetroShare with .pqi file extension" + LangString DESC_sec_autostart ${LANG_FRENCH} "Run and Auto-connexion au démarrage" + LangString LANGUAGEID ${LANG_FRENCH} "1036" + + LangString sec_main ${LANG_GERMAN} "Programmdateien" + LangString sec_data ${LANG_GERMAN} "Skins f�r das Programm" + LangString sec_shortcuts ${LANG_GERMAN} "Shortcuts" + LangString sec_link ${LANG_GERMAN} "Dateiverkn�pfungen" + LangString sec_autostart ${LANG_GERMAN} "Auto Startup" + LangString DESC_sec_main ${LANG_GERMAN} "Installiert die erforderlichen Programmdateien." + LangString DESC_sec_data ${LANG_GERMAN} "Installiert RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_GERMAN} "Erstellt eine RetroShare Verkn�pfung im Startmen�, Desktop oder im Schnellstarter." + LangString DESC_sec_link ${LANG_GERMAN} "RetroShare mit .pqi Dateien verkn�pfen" + LangString DESC_sec_autostart ${LANG_GERMAN} "Beim Neustart automatisch RetroShare starten und sich anmelden" + LangString LANGUAGEID ${LANG_GERMAN} "1031" + + LangString sec_main ${LANG_TURKISH} "Program Dosyalar�" + LangString sec_data ${LANG_TURKISH} "Program Skinleri" + LangString sec_shortcuts ${LANG_TURKISH} "Shortcut'lar" + LangString sec_link ${LANG_TURKISH} ".pqi Dosya Kaydet" + LangString sec_autostart ${LANG_TURKISH} "Otomatik calistir ve baglan" + LangString DESC_sec_main ${LANG_TURKISH} "Program dosyalar�n� kurar." + LangString DESC_sec_data ${LANG_TURKISH} "RetroShare Skin'leri kurar" + LangString DESC_sec_shortcuts ${TURKISH} "Shortcut yap Start menu , Desktop veya Quicklaunchbar icin." + LangString DESC_sec_link ${LANG_TURKISH} "RetroShare .pqi almas� i�in kaydettirir" + LangString DESC_sec_autostart ${LANG_TURKISH} "Isletim sistemi acildiginda Otomatik olarak calistir ve baglan" + LangString LANGUAGEID ${LANG_TURKISH} "1055" + + LangString sec_main ${LANG_SIMPCHINESE} "程序文件" + LangString sec_data ${LANG_SIMPCHINESE} "程序皮肤" + LangString sec_shortcuts ${LANG_SIMPCHINESE} "快捷方式" + LangString sec_link ${LANG_SIMPCHINESE} "RetroShare文件关联" + LangString sec_autostart ${LANG_SIMPCHINESE} "自动启动" + LangString DESC_sec_main ${LANG_SIMPCHINESE} "安装RetroShare程序" + LangString DESC_sec_data ${LANG_SIMPCHINESE} "安装RetroShare皮肤" + LangString DESC_sec_shortcuts ${LANG_SIMPCHINESE} "建RetroShare快捷方式" + LangString DESC_sec_link ${LANG_SIMPCHINESE} "关联.pqi扩展名" + LangString DESC_sec_autostart ${LANG_SIMPCHINESE} "启动时自动运行和登录" + LangString LANGUAGEID ${LANG_SIMPCHINESE} "2052" + + LangString sec_main ${LANG_POLISH} "Pliki programu" + LangString sec_data ${LANG_POLISH} "Skórki" + LangString sec_shortcuts ${LANG_POLISH} "Skróty" + LangString sec_link ${LANG_POLISH} "Skojarz pliki" + LangString sec_autostart ${LANG_POLISH} "Automatyczne uruchamianie" + LangString DESC_sec_main ${LANG_POLISH} "Instaluje pliki programu RetroShare" + LangString DESC_sec_data ${LANG_POLISH} "Instaluje skórki programu RetroShare" + LangString DESC_sec_shortcuts ${LANG_POLISH} "Utwórz ikony skrótów na pulpicie, w menu start oraz na pasku szybkiego uruchamiania." + LangString DESC_sec_link ${LANG_POLISH} "Skojarz pliki o rozszerzeniu .pqi z RetroShare" + LangString DESC_sec_autostart ${LANG_POLISH} "Uruchom i zaloguj podczas startu systemu" + LangString LANGUAGEID ${LANG_POLISH} "1045" + + +!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +; CloseRetroShare: this will in a loop send the RetroShare window the WM_CLOSE +; message until it does not find a valid RetroShare window +; + +!macro CloseRetroShare UN +Function ${UN}CloseRetroShare + Push $0 + + IntFmt $R4 "%u" 0 + + goto skip + killloop: + DetailPrint "Killing RetroShare" + KillProcDLL::KillProc "RetroShare.exe" + loop: + Sleep 1000 + IntOp $R4 $R4 + 1 + IntCmp $R4 5 done + skip: + DetailPrint "Looking for running copies of RetroShare" + + ;Push "wxWindowClassNR" # the wcn + ;Push "RetroShare" # the known part of the wt + ;Call ${UN}EnhancedFindWindow + ;Pop $0 # will contain the window's handle + ;Pop $1 # will containg the full wcn + # both will containg "failed", if no matching wcn was found + + ;StrCmp $0 "failed" done + ;StrCmp $0 "0" done + ;DetailPrint "Stopping RetroShare" + ;SendMessage $0 16 0 0 # WM_CLOSE == 16 + Goto loop + done: + + IntFmt $R4 "%u" 0 + Processes::FindProcess "RetroShare.exe" + StrCmp $R0 "1" killloop reallydone + + reallydone: + Pop $0 +FunctionEnd +!macroend + + +!macro CheckForIt UN +Function ${UN}CheckForIt + + Processes::FindProcess $KILLEXENAME + StrCmp $R0 "1" foundit didntfindit + + foundit: + MessageBox MB_OKCANCEL "You must quit ${APPNAME} ($KILLEXENAME) \ + before installing this version.$\r$\nPlease quit it and press \ + OK to continue." IDOK tryagain + Abort + + tryagain: + + Sleep 2000 + Processes::FindProcess $KILLEXENAME + StrCmp $R0 "1" stillthere didntfindit + + stillthere: + MessageBox MB_OKCANCEL "There is still a copy of ${APPNAME} \ + ($KILLEXENAME) running.$\r$\nPress OK to force-quit the application, \ + or Cancel to exit." IDOK killit + Abort + + killit: + KillProcDLL::KillProc $KILLEXENAME + Sleep 1000 + + didntfindit: + +FunctionEnd +!macroend + +!macro QuitIt UN +Function ${UN}QuitIt + + # try nicely first + Call ${UN}CloseRetroShare + + # kill all the old ones + StrCpy $KILLEXENAME "RetroShare.exe" + Call ${UN}CheckForIt + StrCpy $KILLEXENAME "" +FunctionEnd +!macroend + + +; This function automatically uninstalls older versions. +; It is largely copied from: +; http://nsis.sourceforge.net/archive/viewpage.php?pageid=326 + + +Section $(sec_main) sec_main + + ;Set Section required + SectionIn RO + + ; Set Section properties + SetOverwrite on + + ; Clears previous error logs + Delete "$INSTDIR\*.log" + + ; Set Section Files and Shortcuts + SetOutPath "$INSTDIR\" + File /r "release\RetroShare.exe" + File /r "D:\Qt\2009.02\mingw\bin\mingwm10.dll" + File /r "D:\Qt\2009.02\qt\bin\QtCore4.dll" + File /r "D:\Qt\2009.02\qt\bin\QtGui4.dll" + File /r "D:\Qt\2009.02\qt\bin\QtNetwork4.dll" + File /r "D:\Qt\2009.02\qt\bin\QtXml4.dll" + File /r "D:\Qt\2009.02\qt\bin\QtScript4.dll" + File /r "pthreadGCE2.dll" + File /r "pthreadGC2d.dll" + File /r "changelog.txt" + + +SectionEnd + +Section $(sec_data) sec_data + + ; Set Section properties + SetOverwrite on + + ; Set Section Files and Shortcuts + SetOutPath "$APPDATA\RetroShare\" + ;File /r "data\*" + + ; We're not ready for external skins... + ; Set Section qss need to remove svn path + SetOutPath "$INSTDIR\qss\" + File /r qss\*.* + + ; Set Section skin + ; SetOutPath "$INSTDIR\skin\" + ; File /r release\skin\*.* + + ; Add emoticons + SetOutPath "$INSTDIR\emoticons\" + File /r emoticons\*.* + + ; Add Chat Style + SetOutPath "$INSTDIR\style\" + File /r style\*.* + +SectionEnd + +Section $(sec_link) sec_link + ; Delete any existing keys + + + ; Write the file association + WriteRegStr HKCR .pqi "" retroshare + WriteRegStr HKCR retroshare "" "PQI File" + WriteRegBin HKCR retroshare EditFlags 00000100 + WriteRegStr HKCR "retroshare\shell" "" open + WriteRegStr HKCR "retroshare\shell\open\command" "" `"$INSTDIR\RetroShare.exe" "%1"` + +SectionEnd + +SectionGroup $(sec_shortcuts) sec_shortcuts +Section StartMenu SEC0001 + + SetOutPath "$INSTDIR" + CreateDirectory "$SMPROGRAMS\${APPNAME}" + CreateShortCut "$SMPROGRAMS\${APPNAME}\$(^UninstallLink).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd + +Section Desktop SEC0002 + + + CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd + +Section Quicklaunchbar SEC0003 + + + CreateShortCut "$QUICKLAUNCH\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd +SectionGroupEnd + +;Section $(sec_autostart) sec_autostart + +; WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" "$INSTDIR\${APPNAME}.exe -a" + +;SectionEnd + +Section $(sec_autostart) sec_autostart + + CreateShortCut "$SMSTARTUP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 +SectionEnd + + +Section -FinishSection + + WriteRegStr HKLM "Software\${APPNAME}" "" "$INSTDIR" + WriteRegStr HKLM "Software\${APPNAME}" "Version" "${VERSION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe" + WriteUninstaller "$INSTDIR\uninstall.exe" + +SectionEnd + + + +;-------------------------------- +;Descriptions + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${sec_main} $(DESC_sec_main) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_data} $(DESC_sec_data) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_shortcuts} $(DESC_sec_shortcuts) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_link} $(DESC_sec_link) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_autostart} $(DESC_sec_autostart) +!insertmacro MUI_FUNCTION_DESCRIPTION_END + + +;!insertmacro EnhancedFindWindow "" +;!insertmacro EnhancedFindWindow "un." + +!insertmacro CloseRetroShare "" +!insertmacro CloseRetroShare "un." + +!insertmacro CheckForIt "" +!insertmacro CheckForIt "un." + +!insertmacro QuitIt "" +!insertmacro QuitIt "un." + +;Uninstall section +Section "Uninstall" + + Call un.QuitIt + + ; Remove file association registry keys + DeleteRegKey HKCR .pqi + DeleteRegKey HKCR retroshare + + ; Remove program/uninstall regsitry keys + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" + DeleteRegKey HKLM SOFTWARE\${APPNAME} + + DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" + + ; Remove files and uninstaller + Delete $INSTDIR\RetroShare.exe + Delete $INSTDIR\*.dll + Delete $INSTDIR\*.dat + Delete $INSTDIR\*.txt + Delete $INSTDIR\*.ini + Delete $INSTDIR\*.log + + Delete $INSTDIR\uninstall.exe + + ; Remove the kadc.ini file. + ; Don't remove the directory, otherwise + ; we lose the XPGP keys. + ; Should make this an option though... + Delete "$APPDATA\${APPNAME}\kadc.ini" + Delete "$APPDATA\${APPNAME}\*.cfg" + Delete "$APPDATA\${APPNAME}\*.conf" + Delete "$APPDATA\${APPNAME}\*.log-save" + Delete "$APPDATA\${APPNAME}\*.log" + Delete "$APPDATA\${APPNAME}\*.failed" + + RMDir /r "$APPDATA\${APPNAME}\cache" + RMDir /r "$APPDATA\${APPNAME}\Partials" + + ; Remove shortcuts, if any + Delete "$SMPROGRAMS\${APPNAME}\*.*" + + ; Remove desktop shortcut + Delete "$DESKTOP\${APPNAME}.lnk" + + ; Remove Quicklaunch shortcut + Delete "$QUICKLAUNCH\${APPNAME}.lnk" + + ; Remove Autstart + Delete "$SMSTARTUP\${APPNAME}.lnk" + + ; Remove directories used + RMDir "$SMPROGRAMS\${APPNAME}" + RMDir /r "$INSTDIR" + RMDir /r "$INSTDIR\qss" + RMDir /r "$INSTDIR\emoticons" + RMDir /r "$INSTDIR\style" + +SectionEnd + +Function .onInit + + InitPluginsDir + Push $R1 + File /oname=$PLUGINSDIR\spltmp.bmp "gui\images\splash.bmp" + advsplash::show 1200 1000 1000 -1 $PLUGINSDIR\spltmp + Pop $R1 + Pop $R1 + !insertmacro MUI_LANGDLL_DISPLAY + +FunctionEnd + + +# Installer Language Strings +# TODO Update the Language Strings with the appropriate translations. + +LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall" +LangString ^UninstallLink ${LANG_GERMAN} "Deinstallieren" +LangString ^UninstallLink ${LANG_TURKISH} "Kald�r" +LangString ^UninstallLink ${LANG_FRENCH} "Désinstaller" +LangString ^UninstallLink ${LANG_SIMPCHINESE} "卸载" +LangString ^UninstallLink ${LANG_POLISH} "Odinstaluj" + + + + + +; eof diff --git a/retroshare-gui/src/retroshare-ultramodern.nsi b/retroshare-gui/src/retroshare-ultramodern.nsi new file mode 100644 index 000000000..d224cc8f1 --- /dev/null +++ b/retroshare-gui/src/retroshare-ultramodern.nsi @@ -0,0 +1,501 @@ +; Script generated with the Venis Install Wizard & modified by defnax + +; Define your application name +!define APPNAME "RetroShare" +!define VERSION "0.5.1 4049" +!define APPNAMEANDVERSION "${APPNAME} ${VERSION}" +!define QTBASE "D:\qt\2010.01" + +; Main Install settings +Name "${APPNAMEANDVERSION}" +InstallDir "$PROGRAMFILES\RetroShare" +InstallDirRegKey HKLM "Software\${APPNAME}" "" +OutFile "RetroShare_${VERSION}_setup_ultramodern.exe" +BrandingText "${APPNAMEANDVERSION}" +; Use compression +SetCompressor /SOLID LZMA + +; Modern interface settings +!include Sections.nsh +!include "UMUI.nsh" + +;Interface Settings +!define MUI_ABORTWARNING +;!define MUI_HEADERIMAGE +;!define MUI_HEADERIMAGE_BITMAP "retroshare.bmp" ; optional + +# MUI defines +!define MUI_ICON "${NSISDIR}\Contrib\Graphics\UltraModernUI\Icon.ico" +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_LICENSEPAGE_RADIOBUTTONS +!define MUI_COMPONENTSPAGE_SMALLDESC +!define MUI_FINISHPAGE_LINK "Visit the RetroShare forum for the latest news and support" +!define MUI_FINISHPAGE_LINK_LOCATION "http://retroshare.sourceforge.net/forum/" +!define MUI_FINISHPAGE_RUN "$INSTDIR\RetroShare.exe" +!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_TEXT changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\UltraModernUI\UnIcon.ico" +!define MUI_UNFINISHPAGE_NOAUTOCLOSE +!define MUI_LANGDLL_REGISTRY_ROOT HKLM +!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY} +!define UMUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage + +;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without havinf to reboot your computer. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + +;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + + +; Defines the un-/installer logo of RetroShare +!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp" +!insertmacro MUI_DEFAULT MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp" + +; Set languages (first is default language) +!insertmacro MUI_RESERVEFILE_LANGDLL +ReserveFile "${NSISDIR}\Plugins\AdvSplash.dll" + +;-------------------------------- +;Configuration + + + ;!insertmacro MUI_RESERVEFILE_SPECIALBITMAP + + LicenseLangString myLicenseData 1030 "license\license.txt" + LicenseLangString myLicenseData 1033 "license\license.txt" + LicenseLangString myLicenseData 1031 "license\license-GER.txt" + LicenseLangString myLicenseData 1036 "license\license-FR.txt" + LicenseLangString myLicenseData 1055 "license\license-TR.txt" + LicenseLangString myLicenseData 2052 "license\license.txt" + LicenseLangString myLicenseData 1045 "license\license.txt" + LicenseLangString myLicenseData 1041 "license\license.txt" + LicenseLangString myLicenseData 1042 "license\license.txt" + LicenseLangString myLicenseData 1049 "license\license.txt" + LicenseLangString myLicenseData 1053 "license\license.txt" + + LicenseData $(myLicenseData) + +# Installer pages +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +# Installer languages +!define MUI_LANGDLL_ALLLANGUAGES + +!insertmacro MUI_LANGUAGE Danish +!insertmacro MUI_LANGUAGE English +!insertmacro MUI_LANGUAGE French +!insertmacro MUI_LANGUAGE German +!insertmacro MUI_LANGUAGE Japanese +!insertmacro MUI_LANGUAGE Korean +!insertmacro MUI_LANGUAGE Polish +!insertmacro MUI_LANGUAGE Russian +!insertmacro MUI_LANGUAGE Swedish +!insertmacro MUI_LANGUAGE SimpChinese +!insertmacro MUI_LANGUAGE Turkish + + + + ;Component-selection page + ;Titles + + LangString sec_main ${LANG_ENGLISH} "Program Files" + LangString sec_data ${LANG_ENGLISH} "Program Skins" + LangString sec_shortcuts ${LANG_ENGLISH} "Shortcuts" + LangString sec_link ${LANG_ENGLISH} "File Association" + LangString sec_autostart ${LANG_ENGLISH} "Auto Startup" + LangString DESC_sec_main ${LANG_ENGLISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_ENGLISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_ENGLISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_ENGLISH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_ENGLISH} "1033" + + + LangString sec_main ${LANG_FRENCH} "RetroShare" + LangString sec_data ${LANG_FRENCH} "Programme de Skins" + LangString sec_shortcuts ${LANG_FRENCH} "Raccourcis" + LangString sec_link ${LANG_FRENCH} "RetroShare fichiers Association" + LangString sec_startmenu ${LANG_FRENCH} "Raccourcis du menu Démarrer" + LangString sec_autostart ${LANG_FRENCH} "Démarrage automatique" + LangString DESC_sec_main ${LANG_FRENCH} "Installe les fichiers du programme." + LangString DESC_sec_data ${LANG_FRENCH} "Installe RetroShare Skins" + LangString DESC_sec_startmenu ${LANG_FRENCH} "Crée les raccourcis du menu Démarrer" + LangString DESC_sec_shortcuts ${LANG_FRENCH} "Crée une icône sur le bureau." + LangString DESC_sec_link ${LANG_FRENCH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_FRENCH} "1036" + + + LangString sec_main ${LANG_GERMAN} "Programmdateien" + LangString sec_data ${LANG_GERMAN} "Skins fuer das Programm" + LangString sec_shortcuts ${LANG_GERMAN} "Shortcuts" + LangString sec_link ${LANG_GERMAN} "Dateiverknuepfungen" + LangString sec_autostart ${LANG_GERMAN} "Auto Startup" + LangString DESC_sec_main ${LANG_GERMAN} "Installiert die erforderlichen Programmdateien." + LangString DESC_sec_data ${LANG_GERMAN} "Installiert RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_GERMAN} "Erstellt eine RetroShare Verkn�pfung im Startmen�, Desktop oder im Schnellstarter." + LangString DESC_sec_link ${LANG_GERMAN} "RetroShare mit .rsc Dateien verkn�pfen" + LangString LANGUAGEID ${LANG_GERMAN} "1031" + + LangString sec_main ${LANG_TURKISH} "Program Dosyalar�" + LangString sec_data ${LANG_TURKISH} "Program Skinleri" + LangString sec_shortcuts ${LANG_TURKISH} "Shortcut'lar" + LangString sec_link ${LANG_TURKISH} ".rsc Dosya Kaydet" + LangString sec_autostart ${LANG_TURKISH} "Otomatik calistir ve baglan" + LangString DESC_sec_main ${LANG_TURKISH} "Program dosyalar�n� kurar." + LangString DESC_sec_data ${LANG_TURKISH} "RetroShare Skin'leri kurar" + LangString DESC_sec_shortcuts ${TURKISH} "Shortcut yap Start menu , Desktop veya Quicklaunchbar icin." + LangString DESC_sec_link ${LANG_TURKISH} "RetroShare .rsc almas� i�in kaydettirir" + LangString LANGUAGEID ${LANG_TURKISH} "1055" + + LangString sec_main ${LANG_SIMPCHINESE} "程序文件" + LangString sec_data ${LANG_SIMPCHINESE} "程序皮肤" + LangString sec_shortcuts ${LANG_SIMPCHINESE} "快捷方式" + LangString sec_link ${LANG_SIMPCHINESE} "RetroShare文件关联" + LangString sec_autostart ${LANG_SIMPCHINESE} "自动启动" + LangString DESC_sec_main ${LANG_SIMPCHINESE} "安装RetroShare程序" + LangString DESC_sec_data ${LANG_SIMPCHINESE} "安装RetroShare皮肤" + LangString DESC_sec_shortcuts ${LANG_SIMPCHINESE} "建RetroShare快捷方式" + LangString DESC_sec_link ${LANG_SIMPCHINESE} "关联.rsc扩" + LangString LANGUAGEID ${LANG_SIMPCHINESE} "2052" + + LangString sec_main ${LANG_POLISH} "Pliki programu" + LangString sec_data ${LANG_POLISH} "Skórki" + LangString sec_shortcuts ${LANG_POLISH} "Skróty" + LangString sec_link ${LANG_POLISH} "Skojarz pliki" + LangString sec_autostart ${LANG_POLISH} "Automatyczne uruchamianie" + LangString DESC_sec_main ${LANG_POLISH} "Instaluje pliki programu RetroShare" + LangString DESC_sec_data ${LANG_POLISH} "Instaluje skórki programu RetroShare" + LangString DESC_sec_shortcuts ${LANG_POLISH} "Utwórz ikony skrótów na pulpicie, w menu start oraz na pasku szybkiego uruchamiania." + LangString DESC_sec_link ${LANG_POLISH} "Skojarz pliki o rozszerzeniu .rsc z RetroShare" + LangString LANGUAGEID ${LANG_POLISH} "1045" + + LangString sec_main ${LANG_DANISH} "Program Files" + LangString sec_data ${LANG_DANISH} "Program Skins" + LangString sec_shortcuts ${LANG_DANISH} "Shortcuts" + LangString sec_link ${LANG_DANISH} "File Association" + LangString sec_autostart ${LANG_DANISH} "Auto Startup" + LangString DESC_sec_main ${LANG_DANISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_DANISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_DANISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_DANISH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_DANISH} "1030" + + LangString sec_main ${LANG_RUSSIAN} "Program Files" + LangString sec_data ${LANG_RUSSIAN} "Program Skins" + LangString sec_shortcuts ${LANG_RUSSIAN} "Shortcuts" + LangString sec_link ${LANG_RUSSIAN} "File Association" + LangString sec_autostart ${LANG_RUSSIAN} "Auto Startup" + LangString DESC_sec_main ${LANG_RUSSIAN} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_RUSSIAN} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_RUSSIAN} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_RUSSIAN} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_RUSSIAN} "1049" + + LangString sec_main ${LANG_SWEDISH} "Program Files" + LangString sec_data ${LANG_SWEDISH} "Program Skins" + LangString sec_shortcuts ${LANG_SWEDISH} "Shortcuts" + LangString sec_link ${LANG_SWEDISH} "File Association" + LangString sec_autostart ${LANG_SWEDISH} "Auto Startup" + LangString DESC_sec_main ${LANG_SWEDISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_SWEDISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_SWEDISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_SWEDISH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_SWEDISH} "1053" + + LangString sec_main ${LANG_JAPANESE} "Program Files" + LangString sec_data ${LANG_JAPANESE} "Program Skins" + LangString sec_shortcuts ${LANG_JAPANESE} "Shortcuts" + LangString sec_link ${LANG_JAPANESE} "File Association" + LangString sec_autostart ${LANG_JAPANESE} "Auto Startup" + LangString DESC_sec_main ${LANG_JAPANESE} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_JAPANESE} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_JAPANESE} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_JAPANESE} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_JAPANESE} "1041" + + LangString sec_main ${LANG_KOREAN} "Program Files" + LangString sec_data ${LANG_KOREAN} "Program Skins" + LangString sec_shortcuts ${LANG_KOREAN} "Shortcuts" + LangString sec_link ${LANG_KOREAN} "File Association" + LangString sec_autostart ${LANG_KOREAN} "Auto Startup" + LangString DESC_sec_main ${LANG_KOREAN} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_KOREAN} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_KOREAN} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_KOREAN} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_KOREAN} "1042" + + +!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +Section $(sec_main) sec_main + + ;Set Section required + SectionIn RO + + ; Set Section properties + SetOverwrite on + + ; Clears previous error logs + Delete "$INSTDIR\*.log" + + ; Set Section Files and Shortcuts + SetOutPath "$INSTDIR\" + File /r "release\RetroShare.exe" + File /r "..\..\retroshare-nogui\src\release\retroshare-nogui.exe" + File /r "D:\Qt\2010.01\mingw\bin\mingwm10.dll" + File /r "D:\Qt\2010.01\qt\bin\QtCore4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtGui4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtNetwork4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtXml4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtScript4.dll" + File /r "D:\Qt\2010.01\qt\bin\libgcc_s_dw2-1.dll" + File /r "D:\Qt\2010.01\qt\plugins\imageformats" + File /r "D:\Development\miniupnpc-1.3\miniupnpc.dll" + File /r ${QTBASE}\qt\qt_*.qm + File /r "release\pthreadGC2d.dll" + File /r "release\libgpg-error-0.dll" + File /r "release\libgpgme-11.dll" + File /r "changelog.txt" + File /r /x Data "release\bdboot.txt" + + +SectionEnd + +Section $(sec_data) sec_data + + ; Set Section properties + SetOverwrite on + + ; Set Section Files and Shortcuts + SetOutPath "$APPDATA\RetroShare\" + ;File /r "data\*" + + ; Set Section Plugins + SetOutPath "$APPDATA\RetroShare\plugins\" + ;File /r "plugins\" + + ; Set Section qss and exclude svn + SetOutPath "$INSTDIR\qss\" + File /r /x .svn qss\*.* + + ; Set Section sounds and exclude svn + SetOutPath "$INSTDIR\sounds\" + File /r /x .svn sounds\*.* + + ; Set Section skin + ; SetOutPath "$INSTDIR\skin\" + ; File /r release\skin\*.* + + ; Add emoticons + ;SetOutPath "$INSTDIR\emoticons\" + ;File /r emoticons\*.* + + ; Add Chat Style + ;SetOutPath "$INSTDIR\style\" + ;File /r style\*.* + +SectionEnd + +; These are the programs that are needed by RetroShare. +Section -Prerequisites + SetOutPath $INSTDIR\Prerequisites + MessageBox MB_YESNO "$(InstallGPG4WIN)" /SD IDYES IDNO leave + File "Prerequisites\gpg4win-1.1.4.exe" + ExecWait "$INSTDIR\Prerequisites\gpg4win-1.1.4.exe" + + leave: +SectionEnd + +Section $(sec_link) sec_link + ; Delete any existing keys + + + ; Write the file association + WriteRegStr HKCR .rsc "" retroshare + WriteRegStr HKCR retroshare "" "RSC File" + WriteRegBin HKCR retroshare EditFlags 00000100 + WriteRegStr HKCR "retroshare\shell" "" open + WriteRegStr HKCR "retroshare\shell\open\command" "" `"$INSTDIR\RetroShare.exe" "%1"` + +SectionEnd + +SectionGroup $(sec_shortcuts) sec_shortcuts +Section StartMenu SEC0001 + + SetOutPath "$INSTDIR" + CreateDirectory "$SMPROGRAMS\${APPNAME}" + CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + CreateShortCut "$SMPROGRAMS\${APPNAME}\$(^UninstallLink).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + +SectionEnd + +Section Desktop SEC0002 + + + CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd + +Section Quicklaunchbar SEC0003 + + + CreateShortCut "$QUICKLAUNCH\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd +SectionGroupEnd + +;Section $(sec_autostart) sec_autostart + +; WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" "$INSTDIR\${APPNAME}.exe -a" + +;SectionEnd + +;Section $(sec_autostart) sec_autostart + +; CreateShortCut "$SMSTARTUP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 +;SectionEnd + + +Section -FinishSection + + WriteRegStr HKLM "Software\${APPNAME}" "" "$INSTDIR" + WriteRegStr HKLM "Software\${APPNAME}" "Version" "${VERSION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe" + WriteUninstaller "$INSTDIR\uninstall.exe" + +SectionEnd + + + +;-------------------------------- +;Descriptions + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${sec_main} $(DESC_sec_main) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_data} $(DESC_sec_data) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_shortcuts} $(DESC_sec_shortcuts) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_link} $(DESC_sec_link) + ;!insertmacro MUI_DESCRIPTION_TEXT ${sec_autostart} $(DESC_sec_autostart) +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +;Uninstall section +Section "Uninstall" + + ; Remove file association registry keys + DeleteRegKey HKCR .rsc + DeleteRegKey HKCR retroshare + + ; Remove program/uninstall regsitry keys + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" + DeleteRegKey HKLM SOFTWARE\${APPNAME} + + DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" + + ; Remove files and uninstaller + Delete $INSTDIR\RetroShare.exe + Delete $INSTDIR\*.dll + Delete $INSTDIR\*.dat + Delete $INSTDIR\*.txt + Delete $INSTDIR\*.ini + Delete $INSTDIR\*.log + + Delete $INSTDIR\uninstall.exe + + ; Remove the kadc.ini file. + ; Don't remove the directory, otherwise + ; we lose the XPGP keys. + ; Should make this an option though... + Delete "$APPDATA\${APPNAME}\kadc.ini" + Delete "$APPDATA\${APPNAME}\*.cfg" + Delete "$APPDATA\${APPNAME}\*.conf" + Delete "$APPDATA\${APPNAME}\*.log-save" + Delete "$APPDATA\${APPNAME}\*.log" + Delete "$APPDATA\${APPNAME}\*.failed" + + RMDir /r "$APPDATA\${APPNAME}\cache" + RMDir /r "$APPDATA\${APPNAME}\Partials" + + ; Remove shortcuts, if any + Delete "$SMPROGRAMS\${APPNAME}\*.*" + + ; Remove desktop shortcut + Delete "$DESKTOP\${APPNAME}.lnk" + + ; Remove Quicklaunch shortcut + Delete "$QUICKLAUNCH\${APPNAME}.lnk" + + ; Remove Autostart + ;Delete "$SMSTARTUP\${APPNAME}.lnk" + + ; Remove directories used + RMDir "$SMPROGRAMS\${APPNAME}" + RMDir /r "$INSTDIR" + RMDir /r "$INSTDIR\qss" + RMDir /r "$INSTDIR\emoticons" + RMDir /r "$INSTDIR\style" + RMDir /r "$INSTDIR\translations" + +SectionEnd + +Function .onInit + + InitPluginsDir + Push $R1 + File /oname=$PLUGINSDIR\spltmp.bmp "gui\images\splash.bmp" + advsplash::show 1200 1000 1000 -1 $PLUGINSDIR\spltmp + Pop $R1 + Pop $R1 + !insertmacro MUI_LANGDLL_DISPLAY + + + +FunctionEnd + + +# Installer Language Strings +# TODO Update the Language Strings with the appropriate translations. + +LangString InstallGPG4WIN ${LANG_ENGLISH} "Install Gpg4win ? Gpg4win is required for RetroShare!" +LangString InstallGPG4WIN ${LANG_GERMAN} "Installiere Gpg4win ? Gpg4win ist erforderlich fuer RetroShare!" +LangString InstallGPG4WIN ${LANG_TURKISH} "Gpg4win Yükle? Gpg4win RetroShare için gerekli!" +LangString InstallGPG4WIN ${LANG_FRENCH} "RetroShare a besoin de GPG4win pour fonctionner. Lancer l'installation de GPG4win?" +LangString InstallGPG4WIN ${LANG_SIMPCHINESE} "Install Gpg4win ? Gpg4win是需要Retroshare!" +LangString InstallGPG4WIN ${LANG_POLISH} "Install Gpg4win ? Gpg4win wymagane jest Retroshare!" +LangString InstallGPG4WIN ${LANG_DANISH} "Installer Gpg4win? Gpg4win er nødvendig for RetroShare!" +LangString InstallGPG4WIN ${LANG_JAPANESE} "Install Gpg4win ? Gpg4win is required for RetroShare!" +LangString InstallGPG4WIN ${LANG_KOREAN} "Install Gpg4win ? Gpg4win is required for RetroShare!" +LangString InstallGPG4WIN ${LANG_RUSSIAN} "Install Gpg4win ? Gpg4win is required for RetroShare!" +LangString InstallGPG4WIN ${LANG_SWEDISH} "Installera Gpg4win? Gpg4win krävs för RetroShare!" + +LangString FINISHPAGELINK ${LANG_ENGLISH} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_GERMAN} "Besuche RetroShare Support Forum " +LangString FINISHPAGELINK ${LANG_TURKISH} "Destek için Retroshare foruma ziyaret" +LangString FINISHPAGELINK ${LANG_FRENCH} "Consultez le forum RetroShare pour vous tenir au courant des dernieres modifications, et obtenir de l'aide." +LangString FINISHPAGELINK ${LANG_SIMPCHINESE} "帮助论坛" +LangString FINISHPAGELINK ${LANG_POLISH} "Odwiedź forum RetroShare do najświeższych informacji i wsparcia" +LangString FINISHPAGELINK ${LANG_DANISH} "Besøg RetroShare fora for de seneste nyheder og støtte" +LangString FINISHPAGELINK ${LANG_JAPANESE} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_KOREAN} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_RUSSIAN} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_SWEDISH} "Besök RetroShare forum för de senaste nyheterna och stöd" + +LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall" +LangString ^UninstallLink ${LANG_GERMAN} "Deinstallieren" +LangString ^UninstallLink ${LANG_TURKISH} "Kald�r" +LangString ^UninstallLink ${LANG_FRENCH} "Désinstaller" +LangString ^UninstallLink ${LANG_SIMPCHINESE} "卸载" +LangString ^UninstallLink ${LANG_POLISH} "Odinstaluj" +LangString ^UninstallLink ${LANG_DANISH} "Afinstaller" +LangString ^UninstallLink ${LANG_JAPANESE} "Uninstall" +LangString ^UninstallLink ${LANG_KOREAN} "Uninstall" +LangString ^UninstallLink ${LANG_RUSSIAN} "Uninstall" +LangString ^UninstallLink ${LANG_SWEDISH} "Avinstallera" + + +; eof diff --git a/retroshare-gui/src/retroshare.nsi b/retroshare-gui/src/retroshare.nsi new file mode 100644 index 000000000..7957f021b --- /dev/null +++ b/retroshare-gui/src/retroshare.nsi @@ -0,0 +1,501 @@ +; Script generated with the Venis Install Wizard & modified by defnax + +; Define your application name +!define APPNAME "RetroShare" +!define VERSION "0.5.1 4049" +!define APPNAMEANDVERSION "${APPNAME} ${VERSION}" +!define QTBASE "D:\qt\2010.01" + +; Main Install settings +Name "${APPNAMEANDVERSION}" +InstallDir "$PROGRAMFILES\RetroShare" +InstallDirRegKey HKLM "Software\${APPNAME}" "" +OutFile "RetroShare_${VERSION}_setup.exe" +BrandingText "${APPNAMEANDVERSION}" +; Use compression +SetCompressor /SOLID LZMA + +; Modern interface settings +!include Sections.nsh +!include "MUI.nsh" + +;Interface Settings +!define MUI_ABORTWARNING +;!define MUI_HEADERIMAGE +;!define MUI_HEADERIMAGE_BITMAP "retroshare.bmp" ; optional + +# MUI defines +!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico" +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_LICENSEPAGE_RADIOBUTTONS +!define MUI_COMPONENTSPAGE_SMALLDESC +!define MUI_FINISHPAGE_LINK "$(FINISHPAGELINK)" +!define MUI_FINISHPAGE_LINK_LOCATION "http://retroshare.sourceforge.net/forum/" +!define MUI_FINISHPAGE_RUN "$INSTDIR\RetroShare.exe" +!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_TEXT changelog.txt +!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico" +!define MUI_UNFINISHPAGE_NOAUTOCLOSE +!define MUI_LANGDLL_REGISTRY_ROOT HKLM +!define MUI_LANGDLL_REGISTRY_KEY ${REGKEY} +!define MUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage + +;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIt is recommended that you close all other applications before starting Setup. This will make it possible to update relevant system files without havinf to reboot your computer. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + +;!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of RetroShare. \r\n\r\nIMPORTANT: Ensure that RetroShare is NOT RUNNING before continuing (you can exit from the taskbar menu), otherwise the installer cannot update the executables, and the installation will fail. \r\n\r\nClick Next to continue. " + + +; Defines the un-/installer logo of RetroShare +!insertmacro MUI_DEFAULT MUI_WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange.bmp" +!insertmacro MUI_DEFAULT MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\orange-uninstall.bmp" + +; Set languages (first is default language) +!insertmacro MUI_RESERVEFILE_LANGDLL +ReserveFile "${NSISDIR}\Plugins\AdvSplash.dll" + +;-------------------------------- +;Configuration + + + ;!insertmacro MUI_RESERVEFILE_SPECIALBITMAP + + LicenseLangString myLicenseData 1030 "license\license.txt" + LicenseLangString myLicenseData 1033 "license\license.txt" + LicenseLangString myLicenseData 1031 "license\license-GER.txt" + LicenseLangString myLicenseData 1036 "license\license-FR.txt" + LicenseLangString myLicenseData 1055 "license\license-TR.txt" + LicenseLangString myLicenseData 2052 "license\license.txt" + LicenseLangString myLicenseData 1045 "license\license.txt" + LicenseLangString myLicenseData 1041 "license\license.txt" + LicenseLangString myLicenseData 1042 "license\license.txt" + LicenseLangString myLicenseData 1049 "license\license.txt" + LicenseLangString myLicenseData 1053 "license\license.txt" + + LicenseData $(myLicenseData) + +# Installer pages +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)" +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + +# Installer languages +!define MUI_LANGDLL_ALLLANGUAGES + +!insertmacro MUI_LANGUAGE Danish +!insertmacro MUI_LANGUAGE English +!insertmacro MUI_LANGUAGE French +!insertmacro MUI_LANGUAGE German +!insertmacro MUI_LANGUAGE Japanese +!insertmacro MUI_LANGUAGE Korean +!insertmacro MUI_LANGUAGE Polish +!insertmacro MUI_LANGUAGE Russian +!insertmacro MUI_LANGUAGE Swedish +!insertmacro MUI_LANGUAGE SimpChinese +!insertmacro MUI_LANGUAGE Turkish + + + + ;Component-selection page + ;Titles + + LangString sec_main ${LANG_ENGLISH} "Program Files" + LangString sec_data ${LANG_ENGLISH} "Program Skins" + LangString sec_shortcuts ${LANG_ENGLISH} "Shortcuts" + LangString sec_link ${LANG_ENGLISH} "File Association" + LangString sec_autostart ${LANG_ENGLISH} "Auto Startup" + LangString DESC_sec_main ${LANG_ENGLISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_ENGLISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_ENGLISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_ENGLISH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_ENGLISH} "1033" + + + LangString sec_main ${LANG_FRENCH} "RetroShare" + LangString sec_data ${LANG_FRENCH} "Programme de Skins" + LangString sec_shortcuts ${LANG_FRENCH} "Raccourcis" + LangString sec_link ${LANG_FRENCH} "RetroShare fichiers Association" + LangString sec_startmenu ${LANG_FRENCH} "Raccourcis du menu Démarrer" + LangString sec_autostart ${LANG_FRENCH} "Démarrage automatique" + LangString DESC_sec_main ${LANG_FRENCH} "Installe les fichiers du programme." + LangString DESC_sec_data ${LANG_FRENCH} "Installe RetroShare Skins" + LangString DESC_sec_startmenu ${LANG_FRENCH} "Crée les raccourcis du menu Démarrer" + LangString DESC_sec_shortcuts ${LANG_FRENCH} "Crée une icône sur le bureau." + LangString DESC_sec_link ${LANG_FRENCH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_FRENCH} "1036" + + + LangString sec_main ${LANG_GERMAN} "Programmdateien" + LangString sec_data ${LANG_GERMAN} "Skins fuer das Programm" + LangString sec_shortcuts ${LANG_GERMAN} "Shortcuts" + LangString sec_link ${LANG_GERMAN} "Dateiverknuepfungen" + LangString sec_autostart ${LANG_GERMAN} "Auto Startup" + LangString DESC_sec_main ${LANG_GERMAN} "Installiert die erforderlichen Programmdateien." + LangString DESC_sec_data ${LANG_GERMAN} "Installiert RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_GERMAN} "Erstellt eine RetroShare Verknuepfung im Startmen�, Desktop oder im Schnellstarter." + LangString DESC_sec_link ${LANG_GERMAN} "RetroShare mit .rsc Dateien verkn�pfen" + LangString LANGUAGEID ${LANG_GERMAN} "1031" + + LangString sec_main ${LANG_TURKISH} "Program Dosyalar�" + LangString sec_data ${LANG_TURKISH} "Program Skinleri" + LangString sec_shortcuts ${LANG_TURKISH} "Shortcut'lar" + LangString sec_link ${LANG_TURKISH} ".rsc Dosya Kaydet" + LangString sec_autostart ${LANG_TURKISH} "Otomatik calistir ve baglan" + LangString DESC_sec_main ${LANG_TURKISH} "Program dosyalar�n� kurar." + LangString DESC_sec_data ${LANG_TURKISH} "RetroShare Skin'leri kurar" + LangString DESC_sec_shortcuts ${TURKISH} "Shortcut yap Start menu , Desktop veya Quicklaunchbar icin." + LangString DESC_sec_link ${LANG_TURKISH} "RetroShare .rsc almas� i�in kaydettirir" + LangString LANGUAGEID ${LANG_TURKISH} "1055" + + LangString sec_main ${LANG_SIMPCHINESE} "程序文件" + LangString sec_data ${LANG_SIMPCHINESE} "程序皮肤" + LangString sec_shortcuts ${LANG_SIMPCHINESE} "快捷方式" + LangString sec_link ${LANG_SIMPCHINESE} "RetroShare文件关联" + LangString sec_autostart ${LANG_SIMPCHINESE} "自动启动" + LangString DESC_sec_main ${LANG_SIMPCHINESE} "安装RetroShare程序" + LangString DESC_sec_data ${LANG_SIMPCHINESE} "安装RetroShare皮肤" + LangString DESC_sec_shortcuts ${LANG_SIMPCHINESE} "建RetroShare快捷方式" + LangString DESC_sec_link ${LANG_SIMPCHINESE} "关联.rsc扩展名" + LangString LANGUAGEID ${LANG_SIMPCHINESE} "2052" + + LangString sec_main ${LANG_POLISH} "Pliki programu" + LangString sec_data ${LANG_POLISH} "Skórki" + LangString sec_shortcuts ${LANG_POLISH} "Skróty" + LangString sec_link ${LANG_POLISH} "Skojarz pliki" + LangString sec_autostart ${LANG_POLISH} "Automatyczne uruchamianie" + LangString DESC_sec_main ${LANG_POLISH} "Instaluje pliki programu RetroShare" + LangString DESC_sec_data ${LANG_POLISH} "Instaluje skórki programu RetroShare" + LangString DESC_sec_shortcuts ${LANG_POLISH} "Utwórz ikony skrótów na pulpicie, w menu start oraz na pasku szybkiego uruchamiania." + LangString DESC_sec_link ${LANG_POLISH} "Skojarz pliki o rozszerzeniu .rsc z RetroShare" + LangString LANGUAGEID ${LANG_POLISH} "1045" + + LangString sec_main ${LANG_DANISH} "Program Files" + LangString sec_data ${LANG_DANISH} "Program Skins" + LangString sec_shortcuts ${LANG_DANISH} "Shortcuts" + LangString sec_link ${LANG_DANISH} "File Association" + LangString sec_autostart ${LANG_DANISH} "Auto Startup" + LangString DESC_sec_main ${LANG_DANISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_DANISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_DANISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_DANISH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_DANISH} "1030" + + LangString sec_main ${LANG_RUSSIAN} "Program Files" + LangString sec_data ${LANG_RUSSIAN} "Program Skins" + LangString sec_shortcuts ${LANG_RUSSIAN} "Shortcuts" + LangString sec_link ${LANG_RUSSIAN} "File Association" + LangString sec_autostart ${LANG_RUSSIAN} "Auto Startup" + LangString DESC_sec_main ${LANG_RUSSIAN} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_RUSSIAN} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_RUSSIAN} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_RUSSIAN} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_RUSSIAN} "1049" + + LangString sec_main ${LANG_SWEDISH} "Program Files" + LangString sec_data ${LANG_SWEDISH} "Program Skins" + LangString sec_shortcuts ${LANG_SWEDISH} "Shortcuts" + LangString sec_link ${LANG_SWEDISH} "File Association" + LangString sec_autostart ${LANG_SWEDISH} "Auto Startup" + LangString DESC_sec_main ${LANG_SWEDISH} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_SWEDISH} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_SWEDISH} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_SWEDISH} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_SWEDISH} "1053" + + LangString sec_main ${LANG_JAPANESE} "Program Files" + LangString sec_data ${LANG_JAPANESE} "Program Skins" + LangString sec_shortcuts ${LANG_JAPANESE} "Shortcuts" + LangString sec_link ${LANG_JAPANESE} "File Association" + LangString sec_autostart ${LANG_JAPANESE} "Auto Startup" + LangString DESC_sec_main ${LANG_JAPANESE} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_JAPANESE} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_JAPANESE} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_JAPANESE} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_JAPANESE} "1041" + + LangString sec_main ${LANG_KOREAN} "Program Files" + LangString sec_data ${LANG_KOREAN} "Program Skins" + LangString sec_shortcuts ${LANG_KOREAN} "Shortcuts" + LangString sec_link ${LANG_KOREAN} "File Association" + LangString sec_autostart ${LANG_KOREAN} "Auto Startup" + LangString DESC_sec_main ${LANG_KOREAN} "Installs the RetroShare program files." + LangString DESC_sec_data ${LANG_KOREAN} "Installs RetroShare Skins" + LangString DESC_sec_shortcuts ${LANG_KOREAN} "Create RetroShare shortcut icons." + LangString DESC_sec_link ${LANG_KOREAN} "Associate RetroShare with .rsc file extension" + LangString LANGUAGEID ${LANG_KOREAN} "1042" + + +!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +Section $(sec_main) sec_main + + ;Set Section required + SectionIn RO + + ; Set Section properties + SetOverwrite on + + ; Clears previous error logs + Delete "$INSTDIR\*.log" + + ; Set Section Files and Shortcuts + SetOutPath "$INSTDIR\" + File /r "release\RetroShare.exe" + File /r "..\..\retroshare-nogui\src\release\retroshare-nogui.exe" + File /r "D:\Qt\2010.01\mingw\bin\mingwm10.dll" + File /r "D:\Qt\2010.01\qt\bin\QtCore4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtGui4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtNetwork4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtXml4.dll" + File /r "D:\Qt\2010.01\qt\bin\QtScript4.dll" + File /r "D:\Qt\2010.01\qt\bin\libgcc_s_dw2-1.dll" + File /r "D:\Qt\2010.01\qt\plugins\imageformats" + File /r "D:\Development\miniupnpc-1.3\miniupnpc.dll" + File /r ${QTBASE}\qt\qt_*.qm + File /r "release\pthreadGC2d.dll" + File /r "release\libgpg-error-0.dll" + File /r "release\libgpgme-11.dll" + File /r "changelog.txt" + File /r /x Data "release\bdboot.txt" + + +SectionEnd + +Section $(sec_data) sec_data + + ; Set Section properties + SetOverwrite on + + ; Set Section Files and Shortcuts + SetOutPath "$APPDATA\RetroShare\" + ;File /r "data\*" + + ; Set Section Plugins + SetOutPath "$APPDATA\RetroShare\plugins\" + ;File /r "plugins\" + + ; Set Section qss and exclude svn + SetOutPath "$INSTDIR\qss\" + File /r /x .svn qss\*.* + + ; Set Section sounds and exclude svn + SetOutPath "$INSTDIR\sounds\" + File /r /x .svn sounds\*.* + + ; Set Section skin + ; SetOutPath "$INSTDIR\skin\" + ; File /r release\skin\*.* + + ; Add emoticons + ;SetOutPath "$INSTDIR\emoticons\" + ;File /r emoticons\*.* + + ; Add Chat Style + ;SetOutPath "$INSTDIR\style\" + ;File /r style\*.* + +SectionEnd + +; These are the programs that are needed by RetroShare. +Section -Prerequisites + SetOutPath $INSTDIR\Prerequisites + MessageBox MB_YESNO "$(InstallGPG4WIN)" /SD IDYES IDNO leave + File "Prerequisites\gpg4win-1.1.4.exe" + ExecWait "$INSTDIR\Prerequisites\gpg4win-1.1.4.exe" + + leave: +SectionEnd + +Section $(sec_link) sec_link + ; Delete any existing keys + + + ; Write the file association + WriteRegStr HKCR .rsc "" retroshare + WriteRegStr HKCR retroshare "" "RSC File" + WriteRegBin HKCR retroshare EditFlags 00000100 + WriteRegStr HKCR "retroshare\shell" "" open + WriteRegStr HKCR "retroshare\shell\open\command" "" `"$INSTDIR\RetroShare.exe" "%1"` + +SectionEnd + +SectionGroup $(sec_shortcuts) sec_shortcuts +Section StartMenu SEC0001 + + SetOutPath "$INSTDIR" + CreateDirectory "$SMPROGRAMS\${APPNAME}" + CreateShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + CreateShortCut "$SMPROGRAMS\${APPNAME}\$(^UninstallLink).lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + +SectionEnd + +Section Desktop SEC0002 + + + CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd + +Section Quicklaunchbar SEC0003 + + + CreateShortCut "$QUICKLAUNCH\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 + +SectionEnd +SectionGroupEnd + +;Section $(sec_autostart) sec_autostart + +; WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" "$INSTDIR\${APPNAME}.exe -a" + +;SectionEnd + +;Section $(sec_autostart) sec_autostart + +; CreateShortCut "$SMSTARTUP\${APPNAME}.lnk" "$INSTDIR\RetroShare.exe" "" "$INSTDIR\RetroShare.exe" 0 +;SectionEnd + + +Section -FinishSection + + WriteRegStr HKLM "Software\${APPNAME}" "" "$INSTDIR" + WriteRegStr HKLM "Software\${APPNAME}" "Version" "${VERSION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe" + WriteUninstaller "$INSTDIR\uninstall.exe" + +SectionEnd + + + +;-------------------------------- +;Descriptions + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${sec_main} $(DESC_sec_main) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_data} $(DESC_sec_data) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_shortcuts} $(DESC_sec_shortcuts) + !insertmacro MUI_DESCRIPTION_TEXT ${sec_link} $(DESC_sec_link) + ;!insertmacro MUI_DESCRIPTION_TEXT ${sec_autostart} $(DESC_sec_autostart) +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +;Uninstall section +Section "Uninstall" + + ; Remove file association registry keys + DeleteRegKey HKCR .rsc + DeleteRegKey HKCR retroshare + + ; Remove program/uninstall regsitry keys + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" + DeleteRegKey HKLM SOFTWARE\${APPNAME} + + DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "RetroRun" + + ; Remove files and uninstaller + Delete $INSTDIR\RetroShare.exe + Delete $INSTDIR\*.dll + Delete $INSTDIR\*.dat + Delete $INSTDIR\*.txt + Delete $INSTDIR\*.ini + Delete $INSTDIR\*.log + + Delete $INSTDIR\uninstall.exe + + ; Remove the kadc.ini file. + ; Don't remove the directory, otherwise + ; we lose the XPGP keys. + ; Should make this an option though... + Delete "$APPDATA\${APPNAME}\kadc.ini" + Delete "$APPDATA\${APPNAME}\*.cfg" + Delete "$APPDATA\${APPNAME}\*.conf" + Delete "$APPDATA\${APPNAME}\*.log-save" + Delete "$APPDATA\${APPNAME}\*.log" + Delete "$APPDATA\${APPNAME}\*.failed" + + RMDir /r "$APPDATA\${APPNAME}\cache" + RMDir /r "$APPDATA\${APPNAME}\Partials" + + ; Remove shortcuts, if any + Delete "$SMPROGRAMS\${APPNAME}\*.*" + + ; Remove desktop shortcut + Delete "$DESKTOP\${APPNAME}.lnk" + + ; Remove Quicklaunch shortcut + Delete "$QUICKLAUNCH\${APPNAME}.lnk" + + ; Remove Autostart + ;Delete "$SMSTARTUP\${APPNAME}.lnk" + + ; Remove directories used + RMDir "$SMPROGRAMS\${APPNAME}" + RMDir /r "$INSTDIR" + RMDir /r "$INSTDIR\qss" + RMDir /r "$INSTDIR\emoticons" + RMDir /r "$INSTDIR\style" + RMDir /r "$INSTDIR\translations" + +SectionEnd + +Function .onInit + + InitPluginsDir + Push $R1 + File /oname=$PLUGINSDIR\spltmp.bmp "gui\images\splash.bmp" + advsplash::show 1200 1000 1000 -1 $PLUGINSDIR\spltmp + Pop $R1 + Pop $R1 + !insertmacro MUI_LANGDLL_DISPLAY + + + +FunctionEnd + + +# Installer Language Strings +# TODO Update the Language Strings with the appropriate translations. + +LangString InstallGPG4WIN ${LANG_ENGLISH} "Install Gpg4win ? Gpg4win is required for RetroShare!" +LangString InstallGPG4WIN ${LANG_GERMAN} "Installiere Gpg4win ? Gpg4win ist erforderlich fuer RetroShare!" +LangString InstallGPG4WIN ${LANG_TURKISH} "Gpg4win Yükle? Gpg4win RetroShare için gerekli!" +LangString InstallGPG4WIN ${LANG_FRENCH} "RetroShare a besoin de GPG4win pour fonctionner. Lancer l'installation de GPG4win?" +LangString InstallGPG4WIN ${LANG_SIMPCHINESE} "Install Gpg4win ? Gpg4win是需要Retroshare!" +LangString InstallGPG4WIN ${LANG_POLISH} "Install Gpg4win ? Gpg4win wymagane jest Retroshare!" +LangString InstallGPG4WIN ${LANG_DANISH} "Installer Gpg4win? Gpg4win er nødvendig for RetroShare!" +LangString InstallGPG4WIN ${LANG_JAPANESE} "Install Gpg4win ? Gpg4win is required for RetroShare!" +LangString InstallGPG4WIN ${LANG_KOREAN} "Install Gpg4win ? Gpg4win is required for RetroShare!" +LangString InstallGPG4WIN ${LANG_RUSSIAN} "Install Gpg4win ? Gpg4win is required for RetroShare!" +LangString InstallGPG4WIN ${LANG_SWEDISH} "Installera Gpg4win? Gpg4win krävs för RetroShare!" + +LangString FINISHPAGELINK ${LANG_ENGLISH} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_GERMAN} "Besuche RetroShare Support Forum " +LangString FINISHPAGELINK ${LANG_TURKISH} "Destek için Retroshare foruma ziyaret" +LangString FINISHPAGELINK ${LANG_FRENCH} "Consultez le forum RetroShare pour vous tenir au courant des dernieres modifications, et obtenir de l'aide." +LangString FINISHPAGELINK ${LANG_SIMPCHINESE} "帮助论坛" +LangString FINISHPAGELINK ${LANG_POLISH} "Odwiedź forum RetroShare do najświeższych informacji i wsparcia" +LangString FINISHPAGELINK ${LANG_DANISH} "Besøg RetroShare fora for de seneste nyheder og støtte" +LangString FINISHPAGELINK ${LANG_JAPANESE} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_KOREAN} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_RUSSIAN} "Visit the RetroShare forums for the latest news and support" +LangString FINISHPAGELINK ${LANG_SWEDISH} "Besök RetroShare forum för de senaste nyheterna och stöd" + +LangString ^UninstallLink ${LANG_ENGLISH} "Uninstall" +LangString ^UninstallLink ${LANG_GERMAN} "Deinstallieren" +LangString ^UninstallLink ${LANG_TURKISH} "Kald�r" +LangString ^UninstallLink ${LANG_FRENCH} "Désinstaller" +LangString ^UninstallLink ${LANG_SIMPCHINESE} "卸载" +LangString ^UninstallLink ${LANG_POLISH} "Odinstaluj" +LangString ^UninstallLink ${LANG_DANISH} "Afinstaller" +LangString ^UninstallLink ${LANG_JAPANESE} "Uninstall" +LangString ^UninstallLink ${LANG_KOREAN} "Uninstall" +LangString ^UninstallLink ${LANG_RUSSIAN} "Uninstall" +LangString ^UninstallLink ${LANG_SWEDISH} "Avinstallera" + + +; eof diff --git a/retroshare-gui/src/rshare.cpp b/retroshare-gui/src/rshare.cpp new file mode 100644 index 000000000..58a1c30a3 --- /dev/null +++ b/retroshare-gui/src/rshare.cpp @@ -0,0 +1,421 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "gui/settings/rsharesettings.h" + +#include "rshare.h" + +/* Available command-line arguments. */ +#define ARG_LANGUAGE "lang" /**< Argument specifying language. */ +#define ARG_GUISTYLE "style" /**< Argument specfying GUI style. */ +#define ARG_GUISTYLESHEET "stylesheet" /**< Argument specfying GUI style. */ +#define ARG_RESET "reset" /**< Reset Rshare's saved settings. */ +#define ARG_DATADIR "datadir" /**< Directory to use for data files. */ +#define ARG_LOGFILE "logfile" /**< Location of our logfile. */ +#define ARG_LOGLEVEL "loglevel" /**< Log verbosity. */ + + +/* Static member variables */ +QMap Rshare::_args; /**< List of command-line arguments. */ +QString Rshare::_style; /**< The current GUI style. */ +QString Rshare::_language; /**< The current language. */ +QString Rshare::_stylesheet; /**< The current GUI stylesheet. */ +Log Rshare::_log; +bool Rshare::useConfigDir; +QString Rshare::configDir; + +/** Catches debugging messages from Qt and sends them to RetroShare's logs. If Qt + * emits a QtFatalMsg, we will write the message to the log and then abort(). + */ +void +Rshare::qt_msg_handler(QtMsgType type, const char *s) +{ + QString msg(s); + switch (type) { + case QtDebugMsg: + rDebug("QtDebugMsg: %1").arg(msg); + break; + case QtWarningMsg: + rNotice("QtWarningMsg: %1").arg(msg); + break; + case QtCriticalMsg: + rWarn("QtCriticalMsg: %1").arg(msg); + break; + case QtFatalMsg: + rError("QtFatalMsg: %1").arg(msg); + break; + } + if (type == QtFatalMsg) { + rError("Fatal Qt error. Aborting."); + abort(); + } +} + +/** Constructor. Parses the command-line arguments, resets Rshare's + * configuration (if requested), and sets up the GUI style and language + * translation. */ +Rshare::Rshare(QStringList args, int &argc, char **argv, QString dir) +: QApplication(argc, argv) +{ + qInstallMsgHandler(qt_msg_handler); + + /* Read in all our command-line arguments. */ + parseArguments(args); + + /* Check if we're supposed to reset our config before proceeding. */ + if (_args.contains(ARG_RESET)) { + Settings->reset(); + } + + /* Handle the -loglevel and -logfile options. */ + if (_args.contains(ARG_LOGFILE)) + _log.open(_args.value(ARG_LOGFILE)); + if (_args.contains(ARG_LOGLEVEL)) { + _log.setLogLevel(Log::stringToLogLevel( + _args.value(ARG_LOGLEVEL))); + if (!_args.contains(ARG_LOGFILE)) + _log.open(stdout); + } + if (!_args.contains(ARG_LOGLEVEL) && + !_args.contains(ARG_LOGFILE)) + _log.setLogLevel(Log::Off); + + /* config directory */ + useConfigDir = false; + if (dir != "") + { + setConfigDirectory(dir); + } + + /** Initialize support for language translations. */ + //LanguageSupport::initialize(); + + /** Translate the GUI to the appropriate language. */ + setLanguage(_args.value(ARG_LANGUAGE)); + + /** Set the GUI style appropriately. */ + setStyle(_args.value(ARG_GUISTYLE)); + + /** Set the GUI stylesheet appropriately. */ + setSheet(_args.value(ARG_GUISTYLESHEET)); + + /* Switch off auto shutdown */ + setQuitOnLastWindowClosed ( false ); +} + +/** Destructor */ +Rshare::~Rshare() +{ + +} + +/** Enters the main event loop and waits until exit() is called. The signal + * running() will be emitted when the event loop has started. */ +int +Rshare::run() +{ + QTimer::singleShot(0, rApp, SLOT(onEventLoopStarted())); + return rApp->exec(); +} + +/** Called when the application's main event loop has started. This method + * will emit the running() signal to indicate that the application's event + * loop is running. */ +void +Rshare::onEventLoopStarted() +{ + emit running(); +} + +#if defined(Q_OS_WIN) +/** On Windows, we need to catch the WM_QUERYENDSESSION message + * so we know that it is time to shutdown. */ +bool +Rshare::winEventFilter(MSG *msg, long *result) +{ + if (msg->message == WM_QUERYENDSESSION) { + emit shutdown(); + } + return QApplication::winEventFilter(msg, result); +} +#endif + +/** Display usage information regarding command-line arguments. */ +/*void +Rshare::printUsage(QString errmsg) +{ + QTextStream out(stdout);*/ + + /* If there was an error message, print it out. */ + /*if (!errmsg.isEmpty()) { + out << "** " << errmsg << " **" << endl << endl; + }*/ + + /* Now print the application usage */ + //out << "Usage: " << endl; + //out << "\t" << qApp->arguments().at(0) << " [options]" << endl; + + /* And available options */ + //out << endl << "Available Options:" << endl; + //out << "\t-"ARG_RESET"\t\tResets ALL stored Rshare settings." << endl; + //out << "\t-"ARG_DATADIR"\tSets the directory Rshare uses for data files"<< endl; + //out << "\t-"ARG_GUISTYLE"\t\tSets Rshare's interface style." << endl; + //out << "\t-"ARG_GUISTYLESHEET"\t\tSets Rshare's stylesheet." << endl; + //out << "\t\t\t[" << QStyleFactory::keys().join("|") << "]" << endl; + //out << "\t-"ARG_LANGUAGE"\t\tSets Rshare's language." << endl; + //out << "\t\t\t[" << LanguageSupport::languageCodes().join("|") << "]" << endl; +//} + +/** Displays usage information for command-line args. */ +void +Rshare::showUsageMessageBox() +{ + QString usage; + QTextStream out(&usage); + + out << "Available Options:" << endl; + out << ""; + //out << trow(tcol("-"ARG_HELP) + + // tcol(tr("Displays this usage message and exits."))); + out << trow(tcol("-"ARG_RESET) + + tcol(tr("Resets ALL stored RetroShare settings."))); + out << trow(tcol("-"ARG_DATADIR" <dir>") + + tcol(tr("Sets the directory RetroShare uses for data files."))); + out << trow(tcol("-"ARG_LOGFILE" <file>") + + tcol(tr("Sets the name and location of RetroShare's logfile."))); + out << trow(tcol("-"ARG_LOGLEVEL" <level>") + + tcol(tr("Sets the verbosity of RetroShare's logging.") + + "
    [" + Log::logLevels().join("|") +"]")); + out << trow(tcol("-"ARG_GUISTYLE" <style>") + + tcol(tr("Sets RetroShare's interface style.") + + "
    [" + QStyleFactory::keys().join("|") + "]")); + out << trow(tcol("-"ARG_GUISTYLESHEET" <stylesheet>") + + tcol(tr("Sets RetroShare's interface stylesheets."))); + out << trow(tcol("-"ARG_LANGUAGE" <language>") + + tcol(tr("Sets RetroShare's language.") + + "
    [" + LanguageSupport::languageCodes().join("|") + "]")); + out << "
    "; + + VMessageBox::information(0, + tr("RetroShare Usage Information"), usage, VMessageBox::Ok); +} + +/** Returns true if the specified argument expects a value. */ +bool +Rshare::argNeedsValue(QString argName) +{ + return (argName == ARG_GUISTYLE || + argName == ARG_GUISTYLESHEET || + argName == ARG_LANGUAGE || + argName == ARG_DATADIR || + argName == ARG_LOGFILE || + argName == ARG_LOGLEVEL); + +} + +/** Parses the list of command-line arguments for their argument names and + * values. */ +void +Rshare::parseArguments(QStringList args) +{ + QString arg, value; + + /* Loop through all command-line args/values and put them in a map */ + for (int i = 0; i < args.size(); i++) { + /* Get the argument name and set a blank value */ + arg = args.at(i).toLower(); + value = ""; + + /* Check if it starts with a - or -- */ + if (arg.startsWith("-")) { + arg = arg.mid((arg.startsWith("--") ? 2 : 1)); + } + /* Check if it takes a value and there is one on the command-line */ + if (i < args.size()-1 && argNeedsValue(arg)) { + value = args.at(++i); + } + /* Place this arg/value in the map */ + _args.insert(arg, value); + } +} + +/** Verifies that all specified arguments were valid. */ +bool +Rshare::validateArguments(QString &errmsg) +{ + /* Check for a language that Retroshare recognizes. */ + if (_args.contains(ARG_LANGUAGE) && + !LanguageSupport::isValidLanguageCode(_args.value(ARG_LANGUAGE))) { + errmsg = tr("Invalid language code specified: ") + _args.value(ARG_LANGUAGE); + return false; + } + /* Check for a valid GUI style */ + if (_args.contains(ARG_GUISTYLE) && + !QStyleFactory::keys().contains(_args.value(ARG_GUISTYLE), + Qt::CaseInsensitive)) { + errmsg = tr("Invalid GUI style specified: ") + _args.value(ARG_GUISTYLE); + return false; + } + /* Check for a valid log level */ + if (_args.contains(ARG_LOGLEVEL) && + !Log::logLevels().contains(_args.value(ARG_LOGLEVEL))) { + errmsg = tr("Invalid log level specified: ") + _args.value(ARG_LOGLEVEL); + return false; + } + /* Check for a writable log file */ + if (_args.contains(ARG_LOGFILE) && !_log.isOpen()) { + errmsg = tr("Unable to open log file '%1': %2") + .arg(_args.value(ARG_LOGFILE)) + .arg(_log.errorString()); + return false; + } + return true; +} + +/** Sets the translation RetroShare will use. If one was specified on the + * command-line, we will use that. Otherwise, we'll check to see if one was + * saved previously. If not, we'll default to one appropriate for the system + * locale. */ +bool +Rshare::setLanguage(QString languageCode) +{ + /* If the language code is empty, use the previously-saved setting */ + if (languageCode.isEmpty()) { + languageCode = Settings->getLanguageCode(); + } + /* Translate into the desired langauge */ + if (LanguageSupport::translate(languageCode)) { + _language = languageCode; + return true; + } + return false; +} + +/** Sets the GUI style RetroShare will use. If one was specified on the + * command-line, we will use that. Otherwise, we'll check to see if one was + * saved previously. If not, we'll default to one appropriate for the + * operating system. */ +bool +Rshare::setStyle(QString styleKey) +{ + /* If no style was specified, use the previously-saved setting */ + if (styleKey.isEmpty()) { + styleKey = Settings->getInterfaceStyle(); + } + /* Apply the specified GUI style */ + if (QApplication::setStyle(styleKey)) { + _style = styleKey; + return true; + } + return false; +} + +bool +Rshare::setSheet(QString sheet) +{ + /* If no stylesheet was specified, use the previously-saved setting */ + if (sheet.isEmpty()) { + sheet = Settings->getSheetName(); + } + /* Apply the specified GUI stylesheet */ + _stylesheet = sheet; + return true; + +} + +/** Returns the directory RetroShare uses for its data files. */ +QString +Rshare::dataDirectory() +{ + if (useConfigDir) + { + return configDir; + } + else if (_args.contains(ARG_DATADIR)) { + return _args.value(ARG_DATADIR); + } + return defaultDataDirectory(); +} + +/** Returns the default location of RetroShare's data directory. */ +QString +Rshare::defaultDataDirectory() +{ +#if defined(Q_OS_WIN32) + return (win32_app_data_folder() + "\\RetroShare"); +#else + return (QDir::homePath() + "/.RetroShare"); +#endif +} + +/** Creates Rshare's data directory, if it doesn't already exist. */ +bool +Rshare::createDataDirectory(QString *errmsg) +{ + QDir datadir(dataDirectory()); + if (!datadir.exists()) { + QString path = datadir.absolutePath(); + if (!datadir.mkpath(path)) { + return err(errmsg, + QString("Could not create data directory: %1").arg(path)); + } + } + return true; +} + +/** Set Rshare's data directory - externally */ +bool Rshare::setConfigDirectory(QString dir) +{ + useConfigDir = true; + configDir = dir; + return true; +} + +/** Writes msg with severity level to RetroShare's log. */ +Log::LogMessage +Rshare::log(Log::LogLevel level, QString msg) +{ + return _log.log(level, msg); +} + +/** Creates and binds a shortcut such that when key is pressed in + * sender's context, receiver's slot will be called. */ +void +Rshare::createShortcut(const QKeySequence &key, QWidget *sender, + QWidget *receiver, const char *slot) +{ + QShortcut *s = new QShortcut(key, sender); + connect(s, SIGNAL(activated()), receiver, slot); +} diff --git a/retroshare-gui/src/rshare.h b/retroshare-gui/src/rshare.h new file mode 100644 index 000000000..bedf3c4be --- /dev/null +++ b/retroshare-gui/src/rshare.h @@ -0,0 +1,156 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + + +#ifndef _RSHARE_H +#define _RSHARE_H + +#if defined(Q_OS_WIN) +#include +#include +#endif + +#include +#include +#include +#include + +#include "util/log.h" + +/** Rshare's version string */ +#define RSHARE_VERSION "0.7" + +/** Pointer to this RetroShare application instance. */ +#define rApp ((Rshare *)qApp) + +#define rDebug(fmt) (rApp->log(Log::Debug, (fmt))) +#define rInfo(fmt) (rApp->log(Log::Info, (fmt))) +#define rNotice(fmt) (rApp->log(Log::Notice, (fmt))) +#define rWarn(fmt) (rApp->log(Log::Warn, (fmt))) +#define rError(fmt) (rApp->log(Log::Error, (fmt))) + + +class Rshare : public QApplication +{ + Q_OBJECT + +public: + /** Constructor. */ + Rshare(QStringList args, int &argc, char **argv, QString dir); + /** Destructor. */ + ~Rshare(); + + /** Return the map of command-line arguments and values. */ + static QMap arguments() { return _args; } + /** Validates that all arguments were well-formed. */ + bool validateArguments(QString &errmsg); + /** Prints usage information to the given text stream. */ + //void printUsage(QString errmsg = QString()); + /** Displays usage information for command-line args. */ + static void showUsageMessageBox(); + /** Returns true if the user wants to see usage information. */ + static bool showUsage(); + + /** Sets the current language. */ + static bool setLanguage(QString languageCode = QString()); + /** Sets the current GUI style. */ + static bool setStyle(QString styleKey = QString()); + /** Sets the current GUI stylesheet. */ + static bool setSheet(QString sheet = QString()); + + + /** Returns the current language. */ + static QString language() { return _language; } + /** Returns the current GUI style. */ + static QString style() { return _style; } + /** Returns the current GUI stylesheet. */ + static QString stylesheet() { return _stylesheet; } + /** Returns Rshare's application version. */ + static QString version() { return RSHARE_VERSION; } + + + /** Returns the location Rshare uses for its data files. */ + static QString dataDirectory(); + /** Returns the default location of Rshare's data directory. */ + static QString defaultDataDirectory(); + /** Creates Rshare's data directory, if it doesn't already exist. */ + static bool createDataDirectory(QString *errmsg); + + /** Writes msg with severity level to RetroShare's log. */ + static Log::LogMessage log(Log::LogLevel level, QString msg); + + /** Creates Rshare's data directory, if it doesn't already exist. */ + static bool setConfigDirectory(QString dir); + + /** Enters the main event loop and waits until exit() is called. The signal + * running() will be emitted when the event loop has started. */ + static int run(); + + /** Creates and binds a shortcut such that when key is pressed in + * sender's context, receiver's slot will be called. */ + static void createShortcut(const QKeySequence &key, QWidget *sender, + QWidget *receiver, const char *slot); + +signals: + /** Emitted when the application is running and the main event loop has + * started. */ + void running(); + /** Signals that the application needs to shutdown now. */ + void shutdown(); + +protected: +#if defined(Q_OS_WIN) + /** Filters Windows events, looking for events of interest */ + bool winEventFilter(MSG *msg, long *result); +#endif + +private slots: + /** Called when the application's main event loop has started. This method + * will emit the running() signal to indicate that the application's event + * loop is running. */ + void onEventLoopStarted(); + + +private: + /** Catches debugging messages from Qt and sends them to + * RetroShare's logs. */ + static void qt_msg_handler(QtMsgType type, const char *msg); + + /** Parse the list of command-line arguments. */ + void parseArguments(QStringList args); + /** Returns true if the specified arguments wants a value. */ + bool argNeedsValue(QString argName); + + static QMap _args; /**< List of command-line arguments. */ + static QString _style; /**< The current GUI style. */ + static QString _stylesheet; /**< The current GUI stylesheet. */ + static QString _language; /**< The current language. */ + static Log _log; /**< Logs debugging messages to file or stdout. */ + + static bool useConfigDir; + static QString configDir; + +}; + +#endif + diff --git a/retroshare-gui/src/sounds/File.wav b/retroshare-gui/src/sounds/File.wav new file mode 100644 index 000000000..1cbc55f73 Binary files /dev/null and b/retroshare-gui/src/sounds/File.wav differ diff --git a/retroshare-gui/src/sounds/Notify.wav b/retroshare-gui/src/sounds/Notify.wav new file mode 100644 index 000000000..76fd968c8 Binary files /dev/null and b/retroshare-gui/src/sounds/Notify.wav differ diff --git a/retroshare-gui/src/sounds/Startup.wav b/retroshare-gui/src/sounds/Startup.wav new file mode 100644 index 000000000..f9f45e1b4 Binary files /dev/null and b/retroshare-gui/src/sounds/Startup.wav differ diff --git a/retroshare-gui/src/sounds/alert.wav b/retroshare-gui/src/sounds/alert.wav new file mode 100644 index 000000000..e456f4ae5 Binary files /dev/null and b/retroshare-gui/src/sounds/alert.wav differ diff --git a/retroshare-gui/src/sounds/online.wav b/retroshare-gui/src/sounds/online.wav new file mode 100644 index 000000000..ec06433ef Binary files /dev/null and b/retroshare-gui/src/sounds/online.wav differ diff --git a/retroshare-gui/src/sounds/receive.wav b/retroshare-gui/src/sounds/receive.wav new file mode 100644 index 000000000..dce135e0f Binary files /dev/null and b/retroshare-gui/src/sounds/receive.wav differ diff --git a/retroshare-gui/src/sounds/send.wav b/retroshare-gui/src/sounds/send.wav new file mode 100644 index 000000000..c77beb7f8 Binary files /dev/null and b/retroshare-gui/src/sounds/send.wav differ diff --git a/retroshare-gui/src/svn_revision.bat b/retroshare-gui/src/svn_revision.bat new file mode 100644 index 000000000..d828ece90 --- /dev/null +++ b/retroshare-gui/src/svn_revision.bat @@ -0,0 +1,2 @@ +@echo off +"D:\Programme\TortoiseSVN\bin\SubWCRev" . util\rsversion.in util\rsversion.h \ No newline at end of file diff --git a/retroshare-gui/src/util/EventFilter.cpp b/retroshare-gui/src/util/EventFilter.cpp new file mode 100644 index 000000000..a1072cede --- /dev/null +++ b/retroshare-gui/src/util/EventFilter.cpp @@ -0,0 +1,37 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include + +EventFilter::EventFilter(QObject * receiver, const char * member) + : QObject() { + connect(this, SIGNAL(activate(QEvent *)), receiver, member); +} + +void EventFilter::filter(QEvent * event) { + activate(event); +} + +bool EventFilter::eventFilter(QObject * watched, QEvent * event) { + return QObject::eventFilter(watched, event); +} diff --git a/retroshare-gui/src/util/EventFilter.h b/retroshare-gui/src/util/EventFilter.h new file mode 100644 index 000000000..1ee7d8a19 --- /dev/null +++ b/retroshare-gui/src/util/EventFilter.h @@ -0,0 +1,84 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef EVENTFILTER_H +#define EVENTFILTER_H + +#include + +#include + +#include + +class QEvent; + +/** + * EventFilter for QObject. + * + * Permits to make some special actions on Qt events. + * Example: + * + * QMainWindow * widget = new QMainWindow(); + * CloseEventFilter * closeFilter = new CloseEventFilter(this, SLOT(printHelloWorld())); + * ResizeEventFilter * resizeFilter = new ResizeEventFilter(this, SLOT(printHelloWorld())); + * widget->installEventFilter(closeFilter); + * widget->installEventFilter(resizeFilter); + * + * + * + */ +class RSQTUTIL_API EventFilter : public QObject, NonCopyable { + Q_OBJECT +public: + + /** + * Filters an event. + * + * @param receiver object receiver of the filter signal + * @param member member of the object called by the filter signal + * @param watched watched object the filter is going to be applied on + */ + EventFilter(QObject * receiver, const char * member); + +protected: + + /** + * Emits the filter signal. + * + * @param event event filtered + */ + void filter(QEvent * event); + + /** + * Filters the event. + * + * @param watched watched object + * @param event event filtered of the watched object + * @return true then stops the event being handled further + */ + virtual bool eventFilter(QObject * watched, QEvent * event); + +Q_SIGNALS: + + void activate(QEvent * event); +}; + +#endif //EVENTFILTER_H diff --git a/retroshare-gui/src/util/EventReceiver.cpp b/retroshare-gui/src/util/EventReceiver.cpp new file mode 100644 index 000000000..bcc15932a --- /dev/null +++ b/retroshare-gui/src/util/EventReceiver.cpp @@ -0,0 +1,169 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include +#include +#include + +#include + +#include "EventReceiver.h" +#include "gui/RetroShareLink.h" + +#ifdef WINDOWS_SYS +#include +#define OP_RETROSHARELINK 12000 +#endif + +struct SharedMemoryInfo +{ +#ifdef WINDOWS_SYS + /* Store handle of the event window */ + WId wid; +#else + long dummy; +#endif +}; + +EventReceiver::EventReceiver() +{ +#ifdef WINDOWS_SYS + setWindowTitle("RetroShare EventReceiver"); +#endif + + /* Build unique name for the running instance */ + QString name = QString("RetroShare-%1::EventReceiver").arg(QCoreApplication::applicationDirPath()); + sharedMemory.setKey(name); +} + +EventReceiver::~EventReceiver() +{ + sharedMemory.detach(); +} + +bool EventReceiver::start() +{ + if (!sharedMemory.create(sizeof(SharedMemoryInfo))) { + std::cerr << "EventReceiver::start() Cannot create shared memory !" << sharedMemory.errorString().toStdString() << std::endl; + return false; + } + + bool result = true; + + if (sharedMemory.lock()) { + SharedMemoryInfo *info = (SharedMemoryInfo*) sharedMemory.data(); + if (info) { +#ifdef WINDOWS_SYS + info->wid = winId(); +#else + info->dummy = 0; +#endif + } else { + result = false; + std::cerr << "EventReceiver::start() Shared memory returns a NULL pointer!" << std::endl; + } + + sharedMemory.unlock(); + } else { + result = false; + std::cerr << "EventReceiver::start() Cannot lock shared memory !" << std::endl; + } + + return result; +} + +bool EventReceiver::sendRetroShareLink(const QString& link) +{ + if (!sharedMemory.attach()) { + /* No running instance found */ + return false; + } + + bool result = true; + + if (sharedMemory.lock()) { + SharedMemoryInfo *info = (SharedMemoryInfo*) sharedMemory.data(); + if (info) { +#ifdef WINDOWS_SYS + if (info->wid) { + QByteArray linkData = link.toAscii(); + + COPYDATASTRUCT send; + send.dwData = OP_RETROSHARELINK; + send.cbData = link.length() * sizeof(char); + send.lpData = (void*) linkData.constData(); + + SendMessage((HWND) info->wid, WM_COPYDATA, (WPARAM) 0, (LPARAM) (PCOPYDATASTRUCT) &send); + } else { + result = false; + } +#else + QMessageBox mb(QMessageBox::Critical, "RetroShare", QObject::tr("Start with a RetroShare link is only supported for Windows."), QMessageBox::Ok); + mb.setWindowIcon(QIcon(":/images/rstray3.png")); + mb.exec(); + + result = false; +#endif + } else { + result = false; + std::cerr << "EventReceiver::sendRetroShareLink() Cannot lock shared memory !" << std::endl; + } + + sharedMemory.unlock(); + } else { + result = false; + std::cerr << "EventReceiver::start() Cannot lock shared memory !" << std::endl; + } + + sharedMemory.detach(); + + return result; +} + +#ifdef WINDOWS_SYS +bool EventReceiver::winEvent(MSG* message, long* result) +{ + if (message->message == WM_COPYDATA ) { + /* Extract the struct from lParam */ + COPYDATASTRUCT *data = (COPYDATASTRUCT*) message->lParam; + + if (data && data->dwData == OP_RETROSHARELINK) { + received(QString::fromAscii((const char*) data->lpData, data->cbData)); + + /* Keep the event from Qt */ + *result = 0; + return true; + } + } + + /* Give the event to Qt */ + return false; +} +#endif + +void EventReceiver::received(const QString &url) +{ + RetroShareLink link(url); + if (link.valid()) { + emit linkReceived(link.toUrl()); + } +} diff --git a/retroshare-gui/src/util/EventReceiver.h b/retroshare-gui/src/util/EventReceiver.h new file mode 100644 index 000000000..adf1b5d7b --- /dev/null +++ b/retroshare-gui/src/util/EventReceiver.h @@ -0,0 +1,60 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _EVENTRECEIVER_H +#define _EVENTRECEIVER_H + +#include +#include + +class QUrl; + +class EventReceiver : public +#ifdef WINDOWS_SYS + QWidget +#else + QObject +#endif +{ + Q_OBJECT + +public: + EventReceiver(); + ~EventReceiver(); + + bool start(); + bool sendRetroShareLink(const QString& link); + +signals: + void linkReceived(const QUrl& url); + +private: + void received(const QString& url); + +#ifdef WINDOWS_SYS + /* Extend QWidget with a class that will capture the WM_COPYDATA messages */ + bool winEvent (MSG* message, long* result); +#endif // WINDOWS_SYS + + QSharedMemory sharedMemory; +}; + +#endif diff --git a/retroshare-gui/src/util/Interface.h b/retroshare-gui/src/util/Interface.h new file mode 100644 index 000000000..3734eeddd --- /dev/null +++ b/retroshare-gui/src/util/Interface.h @@ -0,0 +1,37 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef INTERFACE_H +#define INTERFACE_H + +#include + +/** + * + * + */ +class Interface : NonCopyable { +public: + + virtual ~Interface() { } +}; + +#endif //INTERFACE_H diff --git a/retroshare-gui/src/util/MouseEventFilter.cpp b/retroshare-gui/src/util/MouseEventFilter.cpp new file mode 100644 index 000000000..503e396e9 --- /dev/null +++ b/retroshare-gui/src/util/MouseEventFilter.cpp @@ -0,0 +1,106 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include +#include + +#include +#include + +MouseMoveEventFilter::MouseMoveEventFilter(QObject * receiver, const char * member) + : EventFilter(receiver, member) { +} + +bool MouseMoveEventFilter::eventFilter(QObject * watched, QEvent * event) { + if (event->type() == QEvent::MouseMove) { + filter(event); + return false; + } + return EventFilter::eventFilter(watched, event); +} + +MousePressEventFilter::MousePressEventFilter(QObject * receiver, const char * member, Qt::MouseButton button) + : EventFilter(receiver, member), + _button(button) { +} + +bool MousePressEventFilter::eventFilter(QObject * watched, QEvent * event) { + if (event->type() == QEvent::MouseButtonPress) { + try { + QMouseEvent * mouseEvent = dynamic_cast(event); + + if ((_button == Qt::NoButton) || (mouseEvent->button() == _button)) { + filter(event); + return false; + } + } catch (std::bad_cast) { + //LOG_FATAL("exception when casting a QEvent to a QMouseEvent"); + } + } + return EventFilter::eventFilter(watched, event); +} + +MouseReleaseEventFilter::MouseReleaseEventFilter(QObject * receiver, const char * member, Qt::MouseButton button) + : EventFilter(receiver, member), + _button(button) { +} + +bool MouseReleaseEventFilter::eventFilter(QObject * watched, QEvent * event) { + if (event->type() == QEvent::MouseButtonRelease) { + try { + QMouseEvent * mouseEvent = dynamic_cast(event); + + if ((_button == Qt::NoButton) || (mouseEvent->button() == _button)) { + filter(event); + return false; + } + } catch (std::bad_cast) { + //LOG_FATAL("exception when casting a QEvent to a QMouseEvent"); + } + } + return EventFilter::eventFilter(watched, event); +} + +MouseHoverEnterEventFilter::MouseHoverEnterEventFilter(QObject * receiver, const char * member) + : EventFilter(receiver, member) { +} + +bool MouseHoverEnterEventFilter::eventFilter(QObject * watched, QEvent * event) { + if (event->type() == QEvent::HoverEnter) { + filter(event); + return false; + } + return EventFilter::eventFilter(watched, event); +} + +MouseHoverLeaveEventFilter::MouseHoverLeaveEventFilter(QObject * receiver, const char * member) + : EventFilter(receiver, member) { +} + +bool MouseHoverLeaveEventFilter::eventFilter(QObject * watched, QEvent * event) { + if (event->type() == QEvent::HoverLeave) { + filter(event); + return false; + } + return EventFilter::eventFilter(watched, event); +} diff --git a/retroshare-gui/src/util/MouseEventFilter.h b/retroshare-gui/src/util/MouseEventFilter.h new file mode 100644 index 000000000..3690d7fd2 --- /dev/null +++ b/retroshare-gui/src/util/MouseEventFilter.h @@ -0,0 +1,110 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef MOUSEEVENTFILTER_H +#define MOUSEEVENTFILTER_H + +#include + +/** + * Catch MouseMove event. + * + * + */ +class RSQTUTIL_API MouseMoveEventFilter : public EventFilter { +public: + + MouseMoveEventFilter(QObject * receiver, const char * member); + +private: + + virtual bool eventFilter(QObject * watched, QEvent * event); +}; + + +/** + * Catch MouseButtonPress event. + * + * + */ +class RSQTUTIL_API MousePressEventFilter : public EventFilter { +public: + + MousePressEventFilter(QObject * receiver, const char * member, Qt::MouseButton button = Qt::NoButton); + +private: + + virtual bool eventFilter(QObject * watched, QEvent * event); + + Qt::MouseButton _button; +}; + + +/** + * Catch MouseButtonRelease event. + * + * + */ +class RSQTUTIL_API MouseReleaseEventFilter : public EventFilter { +public: + + MouseReleaseEventFilter(QObject * receiver, const char * member, Qt::MouseButton button = Qt::NoButton); + +private: + + virtual bool eventFilter(QObject * watched, QEvent * event); + + Qt::MouseButton _button; +}; + + +/** + * Catch HoverEnter event. + * + * + */ +class RSQTUTIL_API MouseHoverEnterEventFilter : public EventFilter { +public: + + MouseHoverEnterEventFilter(QObject * receiver, const char * member); + +private: + + virtual bool eventFilter(QObject * watched, QEvent * event); +}; + + +/** + * Catch HoverLeave event. + * + * + */ +class RSQTUTIL_API MouseHoverLeaveEventFilter : public EventFilter { +public: + + MouseHoverLeaveEventFilter(QObject * receiver, const char * member); + +private: + + virtual bool eventFilter(QObject * watched, QEvent * event); +}; + +#endif //MOUSEEVENTFILTER_H diff --git a/retroshare-gui/src/util/NonCopyable.cpp b/retroshare-gui/src/util/NonCopyable.cpp new file mode 100644 index 000000000..f14d0a19a --- /dev/null +++ b/retroshare-gui/src/util/NonCopyable.cpp @@ -0,0 +1,28 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +NonCopyable::NonCopyable() { +} + +NonCopyable::~NonCopyable() { +} diff --git a/retroshare-gui/src/util/NonCopyable.h b/retroshare-gui/src/util/NonCopyable.h new file mode 100644 index 000000000..c4b34729b --- /dev/null +++ b/retroshare-gui/src/util/NonCopyable.h @@ -0,0 +1,63 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef NONCOPYABLE_H +#define NONCOPYABLE_H + +#include + +/** + * Ensures derived classes have private copy constructor and copy assignment. + * + * Example: + *
    + * class MyClass : NonCopyable {
    + * public:
    + *    ...
    + * };
    + * 
    + * + * Taken from Boost library. + * + * @see boost::noncopyable + * + */ +class NonCopyable { +protected: + + RSUTIL_API NonCopyable(); + + RSUTIL_API ~NonCopyable(); + +private: + + /** + * Copy constructor is private. + */ + NonCopyable(const NonCopyable &); + + /** + * Copy assignement is private. + */ + const NonCopyable & operator=(const NonCopyable &); +}; + +#endif //NONCOPYABLE_H diff --git a/retroshare-gui/src/util/PixmapMerging.cpp b/retroshare-gui/src/util/PixmapMerging.cpp new file mode 100644 index 000000000..1b80cf1fb --- /dev/null +++ b/retroshare-gui/src/util/PixmapMerging.cpp @@ -0,0 +1,40 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include + +QPixmap PixmapMerging::merge(const std::string & foregroundPixmapData, const std::string & backgroundPixmapFilename) { + QImage foregroundImage; + foregroundImage.loadFromData((uchar *) foregroundPixmapData.c_str(), foregroundPixmapData.size()); + + QPixmap backgroundPixmap = QPixmap(QString::fromStdString(backgroundPixmapFilename)); + + if (!foregroundImage.isNull()) { + QPainter painter(&backgroundPixmap); + painter.drawImage(0, 0, + foregroundImage.scaled(backgroundPixmap.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + painter.end(); + } + + return backgroundPixmap; +} diff --git a/retroshare-gui/src/util/PixmapMerging.h b/retroshare-gui/src/util/PixmapMerging.h new file mode 100644 index 000000000..78436a9fc --- /dev/null +++ b/retroshare-gui/src/util/PixmapMerging.h @@ -0,0 +1,53 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef PIXMAPMERGING_H +#define PIXMAPMERGING_H + +#include + +#include + +#include + +class QPixmap; + +/** + * Merges 2 pixmaps together. + * + * + */ +class PixmapMerging : NonCopyable { +public: + + /** + * Merges 2 pixmaps together. + * + * Used to have a background picture (a cadre) and a picture inside it. + * Currently used to a the avatar of a contact inside a nice background. + * + * @param foregroundPixmapData an 'array' with the foreground picture data + * @param backgroundPixmapFilename background pixmap filename e.g ":/pics/avatar_background.png" + */ + RSQTUTIL_API static QPixmap merge(const std::string & foregroundPixmapData, const std::string & backgroundPixmapFilename); +}; + +#endif //PIXMAPMERGING_H diff --git a/retroshare-gui/src/util/RetroStyleLabel.cpp b/retroshare-gui/src/util/RetroStyleLabel.cpp new file mode 100644 index 000000000..f10ba0b87 --- /dev/null +++ b/retroshare-gui/src/util/RetroStyleLabel.cpp @@ -0,0 +1,215 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include + +RetroStyleLabel::RetroStyleLabel(QWidget * parent, Mode mode, Qt::AlignmentFlag hAlign) + : QLabel(parent), _mode(mode) { + + _parent = parent; + _pressed = false; + _selected = false; + _toggled = false; + + //Default background color + _backgroundColor = _parent->palette().color(QPalette::Window); + //Default text color + _textColor = _parent->palette().color(QPalette::Text); + + _alignment = Qt::AlignVCenter | hAlign; +} + +RetroStyleLabel::~RetroStyleLabel() { +} + +void RetroStyleLabel::paintEvent(QPaintEvent * event) { +/* + qDebug() << "Paint event"; + QLabel::paintEvent( event ); + return; +*/ + QRect rect = this->rect(); + + QPainter painter(this); + rect.adjust(-1, -1, 1, 1); + + //painter.fillRect(rect,QBrush(_backgroundColor)); + + if (!_pressed && !_selected) { + //Draw the left side if any + if (!_normalLeftPixmap.isNull()) { + painter.drawPixmap(0,0,_normalLeftPixmap); + } + //Fill the the label + if (!_normalFillPixmap.isNull()) { + QBrush brush(_normalFillPixmap); + + QRect fillRect = rect; + if (!_normalLeftPixmap.isNull()) { + fillRect.adjust(_normalLeftPixmap.rect().width()-1,0,0,0); + } + if (!_normalRightPixmap.isNull()) { + fillRect.adjust(0,0,0-_normalRightPixmap.rect().width(),0); + } + painter.fillRect(fillRect,brush); + } + //Draw the right side + if (!_normalRightPixmap.isNull()) { + painter.drawPixmap( (rect.width()-1) - _normalRightPixmap.rect().width(),0,_normalRightPixmap); + } + + } //if (! _pressed ) + + else { + //Draw the left side if any + if (!_pressedLeftPixmap.isNull()) { + painter.drawPixmap(0, 0, _pressedLeftPixmap); + } + //Fill the the label + if (!_pressedFillPixmap.isNull()) { + QBrush brush(_pressedFillPixmap); + + QRect fillRect = rect; + if (!_pressedLeftPixmap.isNull()) { + fillRect.adjust(_pressedLeftPixmap.rect().width() - 1, 0, 0, 0); + } + if (!_pressedRightPixmap.isNull()) { + fillRect.adjust(0, 0, 0 - _pressedRightPixmap.rect().width(), 0); + } + painter.fillRect(fillRect,brush); + } + //Draw the right side + if (!_pressedRightPixmap.isNull()) { + painter.drawPixmap((rect.width() - 1) - _pressedRightPixmap.rect().width(), 0, _pressedRightPixmap); + } + } + painter.end(); + QPainter p(this); + drawText(&p); + p.end(); +} + +void RetroStyleLabel::drawText(QPainter * painter) { + QRect rect = this->rect(); + + painter->save(); + painter->setPen(_textColor); + painter->drawText(rect, _alignment, this->text(), &rect); + painter->restore(); +} + +void RetroStyleLabel::resizeEvent ( QResizeEvent * event) { + QLabel::resizeEvent(event); +} + +void RetroStyleLabel::setPixmaps(const QPixmap & normalLeftPixmap, + const QPixmap & normalRightPixmap, + const QPixmap & normalFillPixmap, + const QPixmap & pressedLeftPixmap, + const QPixmap & pressedRightPixmap, + const QPixmap & pressedFillPixmap) { + + _normalLeftPixmap = normalLeftPixmap; + _normalRightPixmap = normalRightPixmap; + _normalFillPixmap = normalFillPixmap; + + _pressedLeftPixmap = pressedLeftPixmap; + _pressedRightPixmap = pressedRightPixmap; + _pressedFillPixmap = pressedFillPixmap; +} + +/*void RetroStyleLabel::setLeftPixmaps(const QPixmap & normalLeftPixmap, const QPixmap & pressedLeftPixmap) { + _normalLeftPixmap = normalLeftPixmap; + _pressedLeftPixmap = pressedLeftPixmap; +} + +void RetroStyleLabel::setRightPixmaps(const QPixmap & normalRightPixmap, const QPixmap & pressedRightPixmap) { + _normalRightPixmap = normalRightPixmap; + _pressedRightPixmap = pressedRightPixmap; +}*/ + +void RetroStyleLabel::setTextColor(const QColor & color) { + _textColor = color; +} + +/*void RetroStyleLabel::setBackgroundColor(const QColor & color) { + _backgroundColor = color; +}*/ + +void RetroStyleLabel::mouseMoveEvent(QMouseEvent * event) { + _pressed = false; + QPoint mousePosition = event->pos(); + const QRect rect = this->rect(); + if ((mousePosition.x() >= rect.x()) && ( mousePosition.x() <= rect.width())) { + if ((mousePosition.y() >= rect.y()) && ( mousePosition.y() <= rect.height())) { + _pressed = true; + } + } + update(); +} + +void RetroStyleLabel::mousePressEvent(QMouseEvent * event) { + if (event->button() == Qt::LeftButton) { + _pressed = true; + update(); + } +} + +void RetroStyleLabel::mouseReleaseEvent(QMouseEvent * event) { + if (!_pressed) { + return; + } + //Gets the widget rect + const QRect rect = this->rect(); + + //Gets the mouse position relative to this widget + QPoint mousePosition = event->pos(); + if ((mousePosition.x() >= rect.x()) && (mousePosition.x() <= rect.width())) { + if ((mousePosition.y() >= rect.y()) && (mousePosition.y() <= rect.height())) { + clicked(); + if (_mode == Toggled) { + _toggled = !_toggled; + if (_toggled) { + _pressed = true; + } else { + _pressed = false; + } + } else { + _pressed = false; + } + update(); + } + } +} + +void RetroStyleLabel::setText(const QString & text) { + QLabel::setText(text); + QFontMetrics fm(font()); + int textWidth = fm.width(text); + textWidth += 40; + QSize s = size(); + if (textWidth > s.width()) { + //setMaximumSize(textWidth,s.height()); + setMinimumSize(textWidth,s.height()); + } +} diff --git a/retroshare-gui/src/util/RetroStyleLabel.h b/retroshare-gui/src/util/RetroStyleLabel.h new file mode 100644 index 000000000..76282d3bf --- /dev/null +++ b/retroshare-gui/src/util/RetroStyleLabel.h @@ -0,0 +1,119 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RETROSTYLELABEL_H +#define RETROSTYLELABEL_H + +#include + +#include +#include +#include + + +class RSQTUTIL_API RetroStyleLabel : public QLabel { + Q_OBJECT +public: + + enum Mode { + Normal, + Toggled, + }; + + RetroStyleLabel(QWidget * parent, Mode = Normal, Qt::AlignmentFlag hAlign = Qt::AlignHCenter); + + ~RetroStyleLabel(); + + void setPixmaps(const QPixmap & normalLeftPixmap, + const QPixmap & normalRightPixmap, + const QPixmap & normalFillPixmap, + const QPixmap & pressedLeftPixmap, + const QPixmap & pressedRightPixmap, + const QPixmap & pressedFillPixmap); + + /*void setLeftPixmaps(const QPixmap & normalRightPixmap, const QPixmap & pressedRightPixmap); + + void setRightPixmaps(const QPixmap & normalRightPixmap, const QPixmap & pressedRightPixmap);*/ + + void setTextColor(const QColor & color); + + //void setBackgroundColor(const QColor & color); + + void setTextAlignment(int alignment) { + _alignment = alignment; + } + + void setSelected(bool value) { + _selected = value; + } + +public Q_SLOTS: + + void setText(const QString & text); + +Q_SIGNALS: + + void clicked(); + +private: + + void paintEvent(QPaintEvent * event); + + void resizeEvent(QResizeEvent * event); + + void drawText(QPainter * painter); + + void mouseMoveEvent(QMouseEvent * event); + + void mousePressEvent(QMouseEvent * event); + + void mouseReleaseEvent(QMouseEvent * event); + + QPixmap _normalFillPixmap; + + QPixmap _normalLeftPixmap; + + QPixmap _normalRightPixmap; + + QPixmap _pressedFillPixmap; + + QPixmap _pressedLeftPixmap; + + QPixmap _pressedRightPixmap; + + QColor _textColor; + + QColor _backgroundColor; + + bool _pressed; + + bool _selected; + + QWidget * _parent; + + int _alignment; + + bool _toggled; + + Mode _mode; +}; + +#endif //RETROSTYLELABEL_H diff --git a/retroshare-gui/src/util/RsAction.cpp b/retroshare-gui/src/util/RsAction.cpp new file mode 100644 index 000000000..f873cc978 --- /dev/null +++ b/retroshare-gui/src/util/RsAction.cpp @@ -0,0 +1,50 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2007 DrBob + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "util/RsAction.h" + +RsAction::RsAction(QWidget * parent, std::string rsid) + : QAction(parent), RsId(rsid) +{ + connect(this, SIGNAL( triggered( bool ) ), this, SLOT( triggerEvent( bool ) ) ); +} + + +RsAction::RsAction(const QString & text, QObject * parent, std::string rsid) + : QAction(text, parent), RsId(rsid) +{ + connect(this, SIGNAL( triggered( bool ) ), this, SLOT( triggerEvent( bool ) ) ); +} + + +RsAction::RsAction(const QIcon & icon, const QString & text, QObject * parent , std::string rsid) + : QAction(icon, text, parent), RsId(rsid) +{ + connect(this, SIGNAL( triggered( bool ) ), this, SLOT( triggerEvent( bool ) ) ); +} + + +void RsAction::triggerEvent( bool checked ) +{ + triggeredId(RsId); +} + +//void triggeredId( std::string rsid ); diff --git a/retroshare-gui/src/util/RsAction.h b/retroshare-gui/src/util/RsAction.h new file mode 100644 index 000000000..ad3dfb5ec --- /dev/null +++ b/retroshare-gui/src/util/RsAction.h @@ -0,0 +1,50 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2007 drbob + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RETRO_ACTION_H +#define RETRO_ACTION_H + + +#include + +class RsAction : public QAction { + Q_OBJECT +public: + + RsAction(QWidget * parent, std::string rsid); + RsAction(const QString & text, QObject * parent, std::string rsid); + RsAction(const QIcon & icon, const QString & text, QObject * parent , std::string rsid); + +public Q_SLOTS: + + /* attached to triggered() -> calls triggeredId() */ + void triggerEvent( bool checked ); + +Q_SIGNALS: + + void triggeredId( std::string rsid ); + +private: + + std::string RsId; +}; + +#endif //RETRO_ACTION_H diff --git a/retroshare-gui/src/util/Widget.cpp b/retroshare-gui/src/util/Widget.cpp new file mode 100644 index 000000000..dcf2aa340 --- /dev/null +++ b/retroshare-gui/src/util/Widget.cpp @@ -0,0 +1,38 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include + +QGridLayout * Widget::createLayout(QWidget * parent) { + QGridLayout * layout = new QGridLayout(parent); + layout->setSpacing(0); + layout->setMargin(0); + return layout; +} + +QDialog * Widget::transformToWindow(QWidget * widget) { + QDialog * dialog = new QDialog(widget->parentWidget()); + widget->setParent(NULL); + createLayout(dialog)->addWidget(widget); + return dialog; +} diff --git a/retroshare-gui/src/util/Widget.h b/retroshare-gui/src/util/Widget.h new file mode 100644 index 000000000..f3a17aba2 --- /dev/null +++ b/retroshare-gui/src/util/Widget.h @@ -0,0 +1,58 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RSWIDGET_H +#define RSWIDGET_H + +#include + +#include + +class QWidget; +class QGridLayout; +class QDialog; + +/** + * Helper functions for QWidget. + * + * + */ +class Widget : NonCopyable { +public: + + /** + * Creates a QGridLayout inside a widget. + * + * @param parent QWidget where to create the layout + * @return QGridLayout + */ + RSQTUTIL_API static QGridLayout * createLayout(QWidget * parent); + + /** + * Transforms a QWidget into a QDialog. + * + * @param widget QWidget to transform into a QDialog + * @return the QDialog created + */ + RSQTUTIL_API static QDialog * transformToWindow(QWidget * widget); +}; + +#endif //RSWIDGET_H diff --git a/retroshare-gui/src/util/WidgetBackgroundImage.cpp b/retroshare-gui/src/util/WidgetBackgroundImage.cpp new file mode 100644 index 000000000..e77574752 --- /dev/null +++ b/retroshare-gui/src/util/WidgetBackgroundImage.cpp @@ -0,0 +1,53 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, 2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include +#include +#include +#include +#include + +void WidgetBackgroundImage::setBackgroundImage(QWidget * widget, const char * imageFile, WidgetBackgroundImage::AdjustMode adjustMode) { + widget->setAutoFillBackground(true); + + QPixmap pixmap(imageFile); + + switch (adjustMode) { + case AdjustNone: + break; + case AdjustWidth: + widget->setMinimumWidth(pixmap.width()); + break; + case AdjustHeight: + widget->setMinimumHeight(pixmap.height()); + break; + case AdjustSize: + widget->resize(pixmap.size()); + widget->setMinimumSize(pixmap.size()); + break; + } + + QPalette palette = widget->palette(); + palette.setBrush(widget->backgroundRole(), QBrush(pixmap)); + widget->setPalette(palette); +} diff --git a/retroshare-gui/src/util/WidgetBackgroundImage.h b/retroshare-gui/src/util/WidgetBackgroundImage.h new file mode 100644 index 000000000..6d15bf96c --- /dev/null +++ b/retroshare-gui/src/util/WidgetBackgroundImage.h @@ -0,0 +1,58 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef WIDGETBACKGROUNDIMAGE_H +#define WIDGETBACKGROUNDIMAGE_H + +#include + +#include + +class QWidget; + +/** + * Replacement for QWidget::setBackgroundPixmap() that does not exist in Qt4 anymore. + * + * Draws a background image inside a QWidget. + * + * + */ +class WidgetBackgroundImage : NonCopyable { +public: + + enum AdjustMode { + AdjustNone, + AdjustWidth, + AdjustHeight, + AdjustSize + }; + /** + * Sets a background image to a QWidget. + * + * @param widget QWidget that will get the background image + * @param imageFile background image filename + * @param adjustMode whether we should adjust the image width, height or + * both + */ + RSQTUTIL_API static void setBackgroundImage(QWidget * widget, const char * imageFile, AdjustMode adjustMode); +}; + +#endif //WIDGETBACKGROUNDIMAGE_H diff --git a/retroshare-gui/src/util/dllexport.h b/retroshare-gui/src/util/dllexport.h new file mode 100644 index 000000000..3d0c2cad8 --- /dev/null +++ b/retroshare-gui/src/util/dllexport.h @@ -0,0 +1,84 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef DLLEXPORT_H +#define DLLEXPORT_H + +#include + +/** + * @file dllexport.h + * + * Header that export symbols for creating a .dll under Windows. + * Example: + *
    + * #ifdef MY_DLL
    + * 	#ifdef BUILDING_DLL
    + * 		#define API DLLEXPORT
    + * 	#else
    + * 		#define API DLLIMPORT
    + * 	#endif
    + * #else
    + * 	#define API
    + * #endif
    + *
    + * class API MyClass
    + * API int publicFunction()
    + * class EXCEPTIONAPI(API) PublicThrowableClass
    + * class DLLLOCAL MyClass
    + * 
    + * + * You should define DLL if you want to use the library as a shared one + * + when you build the library you should define BUILDING_DLL + * GCC > v4.0 support library visibility attributes. + * + * @see http://gcc.gnu.org/wiki/Visibility + * + */ +//Shared library support +#ifdef OS_WIN32 + #define DLLIMPORT __declspec(dllimport) + #define DLLEXPORT __declspec(dllexport) + #define DLLLOCAL + #define DLLPUBLIC +#else + #define DLLIMPORT + #ifdef CC_GCC4 + #define DLLEXPORT __attribute__ ((visibility("default"))) + #define DLLLOCAL __attribute__ ((visibility("hidden"))) + #define DLLPUBLIC __attribute__ ((visibility("default"))) + #else + #define DLLEXPORT + #define DLLLOCAL + #define DLLPUBLIC + #endif +#endif + +//Throwable classes must always be visible on GCC in all binaries +#ifdef OS_WIN32 + #define EXCEPTIONAPI(api) api +#elif defined(GCC_HASCLASSVISIBILITY) + #define EXCEPTIONAPI(api) DLLEXPORT +#else + #define EXCEPTIONAPI(api) +#endif + +#endif //DLLEXPORT_H diff --git a/retroshare-gui/src/util/framecatcher.cpp b/retroshare-gui/src/util/framecatcher.cpp new file mode 100644 index 000000000..c771fc49e --- /dev/null +++ b/retroshare-gui/src/util/framecatcher.cpp @@ -0,0 +1,336 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006 Raul E. + * Copyright (c) 2010 Chris Evi-Parker + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *************************************************************************/ + + +#include "framecatcher.h" + +#include + +framecatcher::framecatcher(): xine(NULL), stream(NULL), vo_port(NULL){ + + // start up drivers + std::string vo_driver = "auto"; + xine= xine_new(); + xine_init(xine); + + if((vo_port=xine_open_video_driver(xine,vo_driver.c_str(),XINE_VISUAL_TYPE_NONE, NULL))==NULL) + std::cerr << "framecatcher::framecatcher() " << "ERROR OPENING VIDEO DRIVER"; + +} + +framecatcher::~framecatcher(){ + + if(stream != NULL){ + close(); + } + + xine_close_video_driver(xine,vo_port); + +} + +std::string framecatcher::getCodec(){ + return codec; +} + +int framecatcher::getLength(){ + return length; +} + +int framecatcher::open(const std::string& fileName){ + + int errorCode = 0; + + + /* ensure resources used previous stream have been released */ + if(stream != NULL) + close(); + + + stream = xine_stream_new(xine,NULL,vo_port); + + if(stream == NULL) + return 0; + + + // open stream + if(!xine_open(stream,fileName.c_str())){ + errorCode= xine_get_error(stream); + return errorCode; + } + + // get length of video file stream is attached to + if(!xine_get_pos_length(stream,0,0,&length)){ + errorCode = xine_get_error(stream); + return errorCode; + } + + xine_play(stream,0,0); + const char* temp_codec=xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC); + + if(temp_codec == NULL) + return 0; + + codec = temp_codec; + return 1; +} + +void framecatcher::close(){ + + if(stream != NULL){ + + xine_close(stream); + xine_dispose(stream); + stream = NULL; + } + +} + + +int framecatcher::getRGBImage(int frame, unsigned char*& rgb32BitData, int& width, int& height){ + + if(stream == NULL) + return 0; + + int errCode = 0; + xine_play(stream,0,0); + xine_play(stream,0,frame); // 1 frame 2 mseconds + + uint8_t *yuv = NULL, *y = NULL, *u = NULL, *v =NULL ; + int ratio = 0, format = 0; + + if (!xine_get_current_frame(stream, &width, &height, &ratio, &format, NULL)){ + errCode= xine_get_error(stream); + return errCode; + } + + yuv = new uint8_t[((width+8) * (height+1) * 2)]; + if (yuv == NULL){ + std::cerr << "Out of Memory!"; + return 0; + } + + if (!xine_get_current_frame(stream, &width, &height, &ratio, &format, yuv)){ + errCode= xine_get_error(stream); + + if(yuv != NULL) + delete[] yuv; + + return errCode; + } + + /* + * convert to yv12 if necessary + */ + switch (format){ + case XINE_IMGFMT_YUY2: + { + uint8_t *yuy2 = yuv; + + yuv = new uint8_t[(width * height * 2)]; + if (yuv == NULL){ + std::cerr << "Not enough memory to make screenshot!" << std::endl; + return 0; + } + + y = yuv; + u = yuv + width * height; + v = yuv + width * height * 5 / 4; + + yuy2Toyv12 (y, u, v, yuy2, width, height); + + delete [] yuy2; + } + break; + case XINE_IMGFMT_YV12: + y = yuv; + u = yuv + width * height; + v = yuv + width * height * 5 / 4; + + break; + default: + { + std::cerr << "Format Not Supported" << std::endl; + + if(yuv != NULL) + delete [] yuv; + + return 0; + } + } + + rgb32BitData = yv12ToRgb (y, u, v, width, height); + delete [] yuv; + return 1; +} + + + + +void framecatcher::yuy2Toyv12 (uint8_t *y, uint8_t *u, uint8_t *v, uint8_t *input, int width, int height){ + + int i, j, w2; + + w2 = width / 2; + + for (i = 0; i < height; i += 2){ + for (j = 0; j < w2; j++){ + /* + * packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] + */ + *(y++) = *(input++); + *(u++) = *(input++); + *(y++) = *(input++); + *(v++) = *(input++); + } + + /* + * down sampling + */ + + for (j = 0; j < w2; j++){ + /* + * skip every second line for U and V + */ + *(y++) = *(input++); + input++; + *(y++) = *(input++); + input++; + } + } +} + +unsigned char * framecatcher::yv12ToRgb (uint8_t *src_y, uint8_t *src_u, uint8_t *src_v, int width, int height){ + /* + * Create rgb data from yv12 + */ + +#define clip_8_bit(val) \ +{ \ + if (val < 0) \ + val = 0; \ + else \ + if (val > 255) val = 255; \ +} + + int i, j; + + int y, u, v; + int r, g, b; + + int sub_i_uv; + int sub_j_uv; + + int uv_width, uv_height; + + unsigned char *rgb; + + uv_width = width / 2; + uv_height = height / 2; + + rgb = new unsigned char[(width * height * 4)]; //qt needs a 32bit align + if (!rgb) //qDebug ("Not enough memory!"); + return NULL; + + + for (i = 0; i < height; ++i){ + /* + * calculate u & v rows + */ + sub_i_uv = ((i * uv_height) / height); + + for (j = 0; j < width; ++j){ + /* + * calculate u & v columns + */ + sub_j_uv = ((j * uv_width) / width); + + /*************************************************** + * + * Colour conversion from + * http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30 + * + * Thanks to Billy Biggs + * for the pointer and the following conversion. + * + * R' = [ 1.1644 0 1.5960 ] ([ Y' ] [ 16 ]) + * G' = [ 1.1644 -0.3918 -0.8130 ] * ([ Cb ] - [ 128 ]) + * B' = [ 1.1644 2.0172 0 ] ([ Cr ] [ 128 ]) + * + * Where in xine the above values are represented as + * + * Y' == image->y + * Cb == image->u + * Cr == image->v + * + ***************************************************/ + + y = src_y[(i * width) + j] - 16; + u = src_u[(sub_i_uv * uv_width) + sub_j_uv] - 128; + v = src_v[(sub_i_uv * uv_width) + sub_j_uv] - 128; + + r = (int)((1.1644 * (double)y) + (1.5960 * (double)v)); + g = (int)((1.1644 * (double)y) - (0.3918 * (double)u) - (0.8130 * (double)v)); + b = (int)((1.1644 * (double)y) + (2.0172 * (double)u)); + + clip_8_bit (r); + clip_8_bit (g); + clip_8_bit (b); + + rgb[(i * width + j) * 4 + 0] = b; + rgb[(i * width + j) * 4 + 1] = g; + rgb[(i * width + j) * 4 + 2] = r; + rgb[(i * width + j) * 4 + 3] = 0; + + } + } + + return rgb; +} + +void framecatcher::getError(int errorCode, std::string& errorStr){ + + switch (errorCode){ + case XINE_ERROR_NO_INPUT_PLUGIN: + case XINE_ERROR_NO_DEMUX_PLUGIN: { + errorStr = "No plugin found to handle this resource"; + break; + } + case XINE_ERROR_DEMUX_FAILED: { + errorStr = "Resource seems to be broken"; + break; + } + case XINE_ERROR_MALFORMED_MRL: { + errorStr = "Requested resource does not exist"; + break; + } + case XINE_ERROR_INPUT_FAILED: { + errorStr = "Resource can not be opened"; + break; + } + default: { + errorStr = "Unknown error"; + break; + } + } + + return; +} diff --git a/retroshare-gui/src/util/framecatcher.h b/retroshare-gui/src/util/framecatcher.h new file mode 100644 index 000000000..92ee9a5d4 --- /dev/null +++ b/retroshare-gui/src/util/framecatcher.h @@ -0,0 +1,82 @@ +#ifndef FILEFUNCTIONS_H +#define FILEFUNCTIONS_H + +#include +#include + +#include + + +/*! + * This can be used to retrieve image frames at a specified + * time from video files using the xine library + * + * In the original implementation this class derived from, attributes were declared static, + * Possibly a good reason, as using seperate instances + * of framecatcher can cause a crash if the xine stream is not correctly closed + */ +class framecatcher{ + +public: + + /*! + * video drivers/ports are started up + */ + framecatcher(); + + /*! + * video drivers/ports closed, + * current stream is closed if open + */ + ~framecatcher(); + + std::string getCodec(); + + int getLength(); + + /*! + * + * @param frame time in msecs you want frame to be taken + * @param rgb32BitData 32 bit aligned rgb image format + * @param width of the image data returned + * @param height of the image data returned + */ + int getRGBImage(int frame, unsigned char*& rgb32BitData, int& width, int& height); + + /*! + * attaches a xine stream to the file, + * if valid user can then request image frames using RGBImage + * please ensure you close this stream before establishing a new one! + * Not doing may lead to a seg fault, even if you are using a new instance of framecatcher + * @see getRGBImage + * @see close + */ + int open(const std::string& file); + + /*! + * closes and disposes current xine stream if open + */ + void close(); + + void getError(int errCode, std::string& errStr); + +private: + + xine_t *xine; + xine_stream_t *stream; + xine_video_port_t *vo_port; + std::string vo_driver; + std::string codec; + + int length; // length of the stream + + + + void yuy2Toyv12 (uint8_t *, uint8_t *, uint8_t *, uint8_t *, int , int ); + unsigned char * yv12ToRgb (uint8_t *, uint8_t *, uint8_t *, int , int ); + + +}; + + +#endif diff --git a/retroshare-gui/src/util/global.h b/retroshare-gui/src/util/global.h new file mode 100644 index 000000000..8ff3671df --- /dev/null +++ b/retroshare-gui/src/util/global.h @@ -0,0 +1,152 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RSGLOBAL_H +#define RSGLOBAL_H + +/** + * OS and compilers detection via defines (preprocessor). + * + * Most of this defines are from Qt (Trolltech). + * In each category (OS_ and CC_) one define exludes the others. + * Warning: if you want to add a define to this file, the order is very important. + * + * Operating systems: + * - OS_WINDOWS + * - OS_WIN32 + * - OS_WIN64 + * - OS_WINCE_POCKETPC (Windows CE for PocketPC) + * - OS_WINCE_SMARTPHONE (Windows CE for smartphone) + * - OS_POSIX + * - OS_MACOSX + * - OS_LINUX + * - OS_HURD + * - OS_BSD + * - OS_FREEBSD + * - OS_NETBSD + * - OS_OPENBSD + * + * Compilers: + * - CC_MSVC (Microsoft Visual C++) + * - CC_MSVC6 (Visual C++ 6) + * - CC_MSVC7 (Visual C++ .NET) + * - CC_MSVC71 (Visual C++ 2003) + * - CC_MSVC8 (Visual C++ 2005) + * - CC_WINCE (Microsoft Visual C++ Embedded for Windows CE) + * - CC_WINCE1 (Windows CE 1.x) + * - CC_WINCE2 (Windows CE 2.x) + * - CC_WINCE3 (Windows CE 3.x) + * - CC_WINCE4 (Windows CE 4.x) + * - CC_WINCE5 (Windows CE 5.x) + * - CC_GCC + * - CC_MINGW (Native GCC under Windows) + * - CC_GCC3 (GNU GCC 3.x) + * - CC_GCC4 (GNU GCC 4.x) + * - CC_INTEL (Intel C++) + * - CC_BORLAND (Borland C++) + * + * @file global.h + * @see qglobal.h from Qt4 + * + */ + +//OS +#if defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__)) + #define OS_MACOSX +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) + #define OS_WIN32 +#elif defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + #define OS_WIN64 +#elif defined(__linux__) || defined(__linux) + #define OS_LINUX +#elif defined(__FreeBSD__) || defined(__DragonFly__) + #define OS_FREEBSD +#elif defined(__NetBSD__) + #define OS_NETBSD +#elif defined(__OpenBSD__) + #define OS_OPENBSD +#elif defined(__GNU_HURD__) + #define OS_HURD +#elif defined(WIN32_PLATFORM_PSPC) + #define OS_WINCE_POCKETPC +#elif defined(WIN32_PLATFORM_WFSP) + #define OS_WINCE_SMARTPHONE +#else + #error This OS has not been tested +#endif + +#if defined(OS_WIN32) || defined(OS_WIN64) || defined(OS_WINCE_POCKETPC) || defined(OS_WINCE_SMARTPHONE) + #define OS_WINDOWS +#endif + +#if defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) + #define OS_BSD +#endif + +#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_HURD) || defined(OS_BSD) + #define OS_POSIX +#endif + + +//Compilers +#if defined(__INTEL_COMPILER) + #define CC_INTEL +#elif defined(_MSC_VER) + #define CC_MSVC + #if _MSC_VER <= 1200 + #define CC_MSVC6 + #elif _MSC_VER <= 1300 + #define CC_MSVC7 + #elif _MSC_VER <= 1310 + #define CC_MSVC71 + #elif _MSC_VER <= 1400 + #define CC_MSVC8 + #endif +#elif defined(_WIN32_WCE) + #define CC_WINCE + #if _WIN32_WCE <= 101 + #define CC_WINCE1 + #elif _WIN32_WCE <= 211 + #define CC_WINCE2 + #elif _WIN32_WCE <= 300 + #define CC_WINCE3 + #elif _WIN32_WCE <= 400 + #define CC_WINCE4 + #elif _WIN32_WCE <= 500 + #define CC_WINCE5 + #endif +#elif defined(__GNUC__) + #define CC_GCC + #if __GNUC__ == 3 + #define CC_GCC3 + #elif _MSC_VER == 4 + #define CC_GCC4 + #endif + #if defined(__MINGW32__) + #define CC_MINGW + #endif +#elif defined(__BORLANDC__) || defined(__TURBOC__) + #define CC_BORLAND +#else + #error This compiler has not been tested +#endif + +#endif //OWGLOBAL_H diff --git a/retroshare-gui/src/util/log.cpp b/retroshare-gui/src/util/log.cpp new file mode 100644 index 000000000..295d04435 --- /dev/null +++ b/retroshare-gui/src/util/log.cpp @@ -0,0 +1,181 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, crypton + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include +#include + +#include "log.h" + +/** Open log files for appending as write-only text. */ +#define LOGFILE_MODE \ + (QIODevice::WriteOnly|QIODevice::Append|QIODevice::Text) +/** Format for log message timestamps. */ +#define TIMESTAMP_FMT "MMM dd HH:mm:ss.zzz" + + +/** Default constructor. Logs at level Notice by default. */ +Log::Log() +{ + _logLevel = Notice; +} + +/** Destructor. Closes the log file. */ +Log::~Log() +{ + close(); +} + +/** Returns a list of strings representing available log levels. */ +QStringList +Log::logLevels() +{ + return (QStringList() << "debug" << "info" << "notice" + << "warn" << "error"); +} + +/** Sets the current log level to level. If level is Off, then + * the log file will be closed as well. If level is Unknown, no change + * to the current log level is made. */ +void +Log::setLogLevel(LogLevel level) +{ + if (level >= Debug && level < Unknown) + _logLevel = level; + if (level == Off) + _logFile.close(); +} + +/** Opens file for appending, to which log messages will be written. */ +bool +Log::open(FILE *file) +{ + if (_logFile.isOpen()) + close(); + + _logFile.open(file, LOGFILE_MODE); + return isOpen(); +} + +/** Opens file for appending, to which log messages will be written. */ +bool +Log::open(QString file) +{ + if (_logFile.isOpen()) + close(); + + _logFile.setFileName(file); + _logFile.open(LOGFILE_MODE); + return isOpen(); +} + +/** Flushes any outstanding log messages and closes the log file. */ +void +Log::close() +{ + if (_logFile.isOpen()) { + _logFile.flush(); + _logFile.close(); + } +} + +/** Creates a log message with severity level and initial message + * contents message. The log message can be appended to until the + * returned LogMessage's destructor is called, at which point the complete + * message is written to the log file. */ +inline Log::LogMessage +Log::log(LogLevel level) +{ + if (level < _logLevel) + return LogMessage(level, 0); + return LogMessage(level, &_logFile); +} + +/** Creates a log message with severity level. The log message can be + * appended to until the returned LogMessage's destructor is called, at + * which point the complete message is written to the log file. */ +Log::LogMessage +Log::log(LogLevel level, QString msg) +{ + return log(level) << msg; +} + +/** Returns a string description of the given LogLevel level. */ +inline QString +Log::logLevelToString(LogLevel level) +{ + switch (level) { + case Debug: return "debug"; + case Info: return "info"; + case Notice: return "notice"; + case Warn: return "warn"; + case Error: return "error"; + case Off: return "off"; + default: return "unknown"; + } +} + +/** Returns a LogLevel for the level given by str, or Unknown if the + * given string does not represent a valid LogLevel value. */ +Log::LogLevel +Log::stringToLogLevel(QString str) +{ + str = str.toLower(); + if (str == "debug") + return Debug; + else if (str == "info") + return Info; + else if (str == "notice") + return Notice; + else if (str == "warn") + return Warn; + else if (str == "error") + return Error; + else if (str == "off") + return Off; + return Unknown; +} + +/** Returns a formatted log message, prefixed with a timestamp and the log + * message severity level. */ +inline QString +Log::LogMessage::toString() const +{ + QString msg = QDateTime::currentDateTime().toString(TIMESTAMP_FMT); + msg.append(" [" + Log::logLevelToString(stream->type) + "] "); + msg.append(stream->buf); + return msg; +} + +/** Destructor. Writes the buffered log message out to the log file specified + * in the constructor. */ +Log::LogMessage::~LogMessage() +{ + if (!--stream->ref) { + if (stream->out && !stream->buf.isEmpty()) { + QTextStream log(stream->out); + log << toString() << endl; + log.flush(); + } + delete stream; + } +} + diff --git a/retroshare-gui/src/util/log.h b/retroshare-gui/src/util/log.h new file mode 100644 index 000000000..72401e70d --- /dev/null +++ b/retroshare-gui/src/util/log.h @@ -0,0 +1,163 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef _LOG_H +#define _LOG_H + +#include +#include +#include +#include +#include + + +/** The Log class is similar to the QDebug class provided with Qt, but with + * finer-grained logging levels, slightly different output (for example, not + * everything is wrapped in double quotes), supports using .arg(), and can + * still be used even if Qt was compiled with QT_NO_DEBUG_STREAM. */ +class Log +{ +public: + /** Logging severity levels. */ + enum LogLevel { + Debug = 0, /**< Verbose debugging output. */ + Info, /**< Primarily program flow output. */ + Notice, /**< Non-failure (but important) events. */ + Warn, /**< Recoverable failure conditions. */ + Error, /**< Critical, non-recoverable errors. */ + Off, /**< No logging output. */ + Unknown /**< Unknown/invalid log level. */ + }; + class LogMessage; + + /** Default constructor. */ + Log(); + /** Destructor. */ + ~Log(); + + /** Opens a file on disk (or stdout or stderr) to which log messages will be + * written. */ + bool open(FILE *file); + /** Opens a file on disk to which log messages will be written. */ + bool open(QString file); + /** Closes the log file. */ + void close(); + /** Returns true if the log file is open and ready for writing. */ + bool isOpen() { return _logFile.isOpen() && _logFile.isWritable(); } + /** Returns a string description of the last file error encountered. */ + QString errorString() { return _logFile.errorString(); } + + /** Sets the current log level to level. */ + void setLogLevel(LogLevel level); + /** Returns a list of strings representing valid log levels. */ + static QStringList logLevels(); + /** Returns a string description of the given LogLevel level. */ + static inline QString logLevelToString(LogLevel level); + /** Returns a LogLevel for the level given by str. */ + static LogLevel stringToLogLevel(QString str); + + /** Creates a log message with severity level and initial message + * contents message. The log message can be appended to until the + * returned LogMessage's destructor is called, at which point the complete + * message is written to the log file. */ + LogMessage log(LogLevel level, QString message); + /** Creates a log message with severity level. The log message can be + * appended to until the returned LogMessage's destructor is called, at + * which point the complete message is written to the log file. */ + inline LogMessage log(LogLevel level); + +private: + LogLevel _logLevel; /**< Minimum log severity level. */ + QFile _logFile; /**< Log output destination. */ +}; + +/** This internal class represents a single message that is to be written to + * the log destination. The message is buffered until it is written to the + * log in this class's destructor. */ +class Log::LogMessage +{ +public: + struct Stream { + Stream(Log::LogLevel t, QIODevice *o) + : type(t), out(o), ref(1) {} + Log::LogLevel type; + QIODevice *out; + int ref; + QString buf; + } *stream; + + inline LogMessage(Log::LogLevel t, QIODevice *o) + : stream(new Stream(t,o)) {} + inline LogMessage(const LogMessage &o) + : stream(o.stream) { ++stream->ref; } + inline QString toString() const; + ~LogMessage(); + + /* Support both the << and .arg() methods */ + inline LogMessage &operator<<(const QString &t) + { stream->buf += t; return *this; } + inline LogMessage arg(const QString &a) + { stream->buf = stream->buf.arg(a); return *this; } + inline LogMessage &operator<<(const QStringList &a) + { stream->buf += a.join(","); return *this; } + inline LogMessage arg(const QStringList &a) + { stream->buf = stream->buf.arg(a.join(",")); return *this; } + inline LogMessage &operator<<(const QHostAddress &a) + { stream->buf += a.toString(); return *this; } + inline LogMessage arg(const QHostAddress &a) + { stream->buf = stream->buf.arg(a.toString()); return *this; } + inline LogMessage &operator<<(short a) + { stream->buf += QString::number(a); return *this; } + inline LogMessage arg(short a) + { stream->buf = stream->buf.arg(a); return *this; } + inline LogMessage &operator<<(ushort a) + { stream->buf += QString::number(a); return *this; } + inline LogMessage arg(ushort a) + { stream->buf = stream->buf.arg(a); return *this; } + inline LogMessage &operator<<(int a) + { stream->buf += QString::number(a); return *this; } + inline LogMessage arg(int a) + { stream->buf = stream->buf.arg(a); return *this; } + inline LogMessage &operator<<(uint a) + { stream->buf += QString::number(a); return *this; } + inline LogMessage arg(uint a) + { stream->buf = stream->buf.arg(a); return *this; } + inline LogMessage &operator<<(long a) + { stream->buf += QString::number(a); return *this; } + inline LogMessage arg(long a) + { stream->buf = stream->buf.arg(a); return *this; } + inline LogMessage &operator<<(ulong a) + { stream->buf += QString::number(a); return *this; } + inline LogMessage arg(ulong a) + { stream->buf = stream->buf.arg(a); return *this; } + inline LogMessage &operator<<(qlonglong a) + { stream->buf += QString::number(a); return *this; } + inline LogMessage arg(qlonglong a) + { stream->buf = stream->buf.arg(a); return *this; } + inline LogMessage &operator<<(qulonglong a) + { stream->buf += QString::number(a); return *this; } + inline LogMessage arg(qulonglong a) + { stream->buf = stream->buf.arg(a); return *this; } +}; + +#endif + diff --git a/retroshare-gui/src/util/misc.cpp b/retroshare-gui/src/util/misc.cpp new file mode 100644 index 000000000..cebdd56cb --- /dev/null +++ b/retroshare-gui/src/util/misc.cpp @@ -0,0 +1,286 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (C) 2006 Christophe Dumez + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *************************************************************************/ + +#include +#include +#include + +#include "misc.h" + +// return best userfriendly storage unit (B, KiB, MiB, GiB, TiB) +// use Binary prefix standards from IEC 60027-2 +// see http://en.wikipedia.org/wiki/Kilobyte +// value must be given in bytes +QString misc::friendlyUnit(float val) +{ + if(val < 0) { + return tr("Unknown", "Unknown (size)"); + } + const QString units[4] = {tr(" B", "bytes"), tr(" KiB", "kibibytes (1024 bytes)"), tr(" MiB", "mebibytes (1024 kibibytes)"), tr(" GiB", "gibibytes (1024 mibibytes)")}; + for(unsigned int i=0; i<5; ++i) { + if (val < 1024.) { + return QString(QByteArray::number(val, 'f', 1)) + units[i]; + } + val /= 1024.; + } + return QString(QByteArray::number(val, 'f', 1)) + tr(" TiB", "tebibytes (1024 gibibytes)"); +} + +bool misc::isPreviewable(QString extension) +{ + extension = extension.toUpper(); + if(extension == "AVI") return true; + if(extension == "MP3") return true; + if(extension == "OGG") return true; + if(extension == "OGM") return true; + if(extension == "WMV") return true; + if(extension == "WMA") return true; + if(extension == "MPEG") return true; + if(extension == "MPG") return true; + if(extension == "ASF") return true; + if(extension == "QT") return true; + if(extension == "RM") return true; + if(extension == "RMVB") return true; + if(extension == "RMV") return true; + if(extension == "SWF") return true; + if(extension == "FLV") return true; + if(extension == "WAV") return true; + if(extension == "MOV") return true; + if(extension == "VOB") return true; + if(extension == "MID") return true; + if(extension == "AC3") return true; + if(extension == "MP4") return true; + if(extension == "MP2") return true; + if(extension == "AVI") return true; + if(extension == "FLAC") return true; + if(extension == "AU") return true; + if(extension == "MPE") return true; + if(extension == "MOV") return true; + if(extension == "MKV") return true; + if(extension == "AIF") return true; + if(extension == "AIFF") return true; + if(extension == "AIFC") return true; + if(extension == "RA") return true; + if(extension == "RAM") return true; + if(extension == "M4P") return true; + if(extension == "M4A") return true; + if(extension == "3GP") return true; + if(extension == "AAC") return true; + if(extension == "SWA") return true; + if(extension == "MPC") return true; + if(extension == "MPP") return true; + return false; +} + +// return qBittorrent config path +QString misc::qBittorrentPath() +{ + QString qBtPath = QDir::homePath()+QDir::separator()+QString::fromUtf8(".qbittorrent") + QDir::separator(); + // Create dir if it does not exist + if(!QFile::exists(qBtPath)){ + QDir dir(qBtPath); + dir.mkpath(qBtPath); + } + return qBtPath; +} + +QString misc::findFileInDir(QString dir_path, QString fileName) +{ + QDir dir(dir_path); + if(dir.exists(fileName)) { + return dir.filePath(fileName); + } + QStringList subDirs = dir.entryList(QDir::Dirs); + QString subdir_name; + foreach(subdir_name, subDirs) { + QString result = findFileInDir(dir.path()+QDir::separator()+subdir_name, fileName); + if(!result.isNull()) { + return result; + } + } + return QString(); +} + +// Can't use template class for QString because >,< use unicode code for sorting +// which is not what a human would expect when sorting strings. +void misc::insertSortString(QList > &list, QPair value, Qt::SortOrder sortOrder) +{ + int i = 0; + if(sortOrder == Qt::AscendingOrder) { + while(i < list.size() and QString::localeAwareCompare(value.second, list.at(i).second) > 0) { + ++i; + } + }else{ + while(i < list.size() and QString::localeAwareCompare(value.second, list.at(i).second) < 0) { + ++i; + } + } + list.insert(i, value); +} + +float misc::getPluginVersion(QString filePath) +{ + QFile plugin(filePath); + if(!plugin.exists()){ + qDebug("%s plugin does not exist, returning 0.0", filePath.toUtf8().data()); + return 0.0; + } + if(!plugin.open(QIODevice::ReadOnly | QIODevice::Text)){ + return 0.0; + } + float version = 0.0; + while (!plugin.atEnd()){ + QByteArray line = plugin.readLine(); + if(line.startsWith("#VERSION: ")){ + line = line.split(' ').last(); + line.replace("\n", ""); + version = line.toFloat(); + qDebug("plugin %s version: %.2f", filePath.toUtf8().data(), version); + break; + } + } + return version; +} + +// Take a number of seconds and return an user-friendly +// time duration like "1d 2h 10m". +QString misc::userFriendlyDuration(qlonglong seconds) +{ + if(seconds < 0) { + return tr("Unknown"); + } + if(seconds < 60) { + return tr("< 1m", "< 1 minute"); + } + int minutes = seconds / 60; + if(minutes < 60) { + return tr("%1 minutes","e.g: 10minutes").arg(QString::QString::fromUtf8(misc::toString(minutes).c_str())); + } + int hours = minutes / 60; + minutes = minutes - hours*60; + if(hours < 24) { + return tr("%1h %2m", "e.g: 3hours 5minutes").arg(QString::fromUtf8(misc::toString(hours).c_str())).arg(QString::fromUtf8(misc::toString(minutes).c_str())); + } + int days = hours / 24; + hours = hours - days * 24; + if(days < 365) { + return tr("%1d %2h", "e.g: 2days 10hours").arg(QString::fromUtf8(misc::toString(days).c_str())).arg(QString::fromUtf8(misc::toString(hours).c_str())); + } + int years = days / 365; + days = days - years * 365; + return tr("%1y %2d", "e.g: 2 years 2days ").arg(QString::fromUtf8(misc::toString(years).c_str())).arg(QString::fromUtf8(misc::toString(days).c_str())); +} + +QString misc::userFriendlyUnit(double count, unsigned int decimal, double factor) +{ + if (count <= 0.0) { + return "0"; + } + + QString output; + + int i; + for (i = 0; i < 5; i++) { + if (count < factor) { + break; + } + + count /= factor; + } + + QString unit; + switch (i) { + case 0: + decimal = 0; // no decimal + break; + case 1: + unit = tr("k", "e.g: 3.1 k"); + break; + case 2: + unit = tr("M", "e.g: 3.1 M"); + break; + case 3: + unit = tr("G", "e.g: 3.1 G"); + break; + default: // >= 4 + unit = tr("T", "e.g: 3.1 T"); + } + + return QString("%1 %2").arg(count, 0, 'f', decimal).arg(unit); +} + +QString misc::removeNewLine(const QString &text) +{ + return QString(text).replace("\n", " "); +} + +QString misc::removeNewLine(const std::string &text) +{ + return QString::fromUtf8(text.c_str()).replace("\n", " "); +} + +QString misc::removeNewLine(const std::wstring &text) +{ + return QString::fromStdWString(text).replace("\n", " "); +} + +bool misc::getOpenFileName(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QString &file) +{ + QString lastDir = Settings->getLastDir(type); + + file = QFileDialog::getOpenFileName(parent, caption, lastDir, filter, NULL, QFileDialog::DontResolveSymlinks); + + if (file.isEmpty() == false) { + lastDir = QFileInfo(file).absoluteDir().absolutePath(); + Settings->setLastDir(type, lastDir); + } + + return !file.isEmpty(); +} + +bool misc::getOpenFileNames(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QStringList &files) +{ + QString lastDir = Settings->getLastDir(type); + + files = QFileDialog::getOpenFileNames(parent, caption, lastDir, filter, NULL, QFileDialog::DontResolveSymlinks); + + if (files.isEmpty() == false) { + lastDir = QFileInfo(*files.begin()).absoluteDir().absolutePath(); + Settings->setLastDir(type, lastDir); + } + + return !files.isEmpty(); +} + +bool misc::getSaveFileName(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QString &file) +{ + QString lastDir = Settings->getLastDir(type); + + file = QFileDialog::getSaveFileName(parent, caption, lastDir, filter); + + if (file.isEmpty() == false) { + lastDir = QFileInfo(file).absoluteDir().absolutePath(); + Settings->setLastDir(type, lastDir); + } + + return !file.isEmpty(); +} diff --git a/retroshare-gui/src/util/misc.h b/retroshare-gui/src/util/misc.h new file mode 100644 index 000000000..16707e5d6 --- /dev/null +++ b/retroshare-gui/src/util/misc.h @@ -0,0 +1,174 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, defnax + * Copyright (C) 2006 Christophe Dumez + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *************************************************************************/ + +#ifndef MISC_H +#define MISC_H + +#include +#include +#include +#include +#include + +#include "gui/settings/rsharesettings.h" + +/* Miscellaneaous functions that can be useful */ +class misc : public QObject +{ + Q_OBJECT + + public: + // Convert any type of variable to C++ String + // convert=true will convert -1 to 0 + template static std::string toString(const T& x, bool convert=false) { + std::ostringstream o; + if(!(o< static QString toQString(const T& x, bool convert=false) { + std::ostringstream o; + if(!(o< static QByteArray toQByteArray(const T& x, bool convert=false) { + std::ostringstream o; + if(!(o< static T fromString(const std::string& s) { + T x; + std::istringstream i(s); + if(!(i>>x)) { + throw std::runtime_error("::fromString()"); + } + return x; + } + +// template static T fromQString::fromUtf8(const QString& s) { +// T x; +// std::istringstream i((const char*)s.toUtf8()); +// if(!(i>>x)) { +// throw std::runtime_error("::fromString()"); +// } +// return x; +// } +// +// template static T fromQByteArray(const QByteArray& s) { +// T x; +// std::istringstream i((const char*)s); +// if(!(i>>x)) { +// throw std::runtime_error("::fromString()"); +// } +// return x; +// } + + // return best userfriendly storage unit (B, KiB, MiB, GiB, TiB) + // use Binary prefix standards from IEC 60027-2 + // see http://en.wikipedia.org/wiki/Kilobyte + // value must be given in bytes + static QString friendlyUnit(float val); + + static bool isPreviewable(QString extension); + + // return qBittorrent config path + static QString qBittorrentPath(); + + static QString findFileInDir(QString dir_path, QString fileName); + + // Insertion sort, used instead of bubble sort because it is + // approx. 5 times faster. +// template static void insertSort(QList > &list, const QPair& value, Qt::SortOrder sortOrder) { +// int i = 0; +// if(sortOrder == Qt::AscendingOrder) { +// while(i < list.size() and value.second > list.at(i).second) { +// ++i; +// } +// }else{ +// while(i < list.size() and value.second < list.at(i).second) { +// ++i; +// } +// } +// list.insert(i, value); +// } + +// template static void insertSort2(QList > &list, const QPair& value, Qt::SortOrder sortOrder) { +// int i = 0; +// if(sortOrder == Qt::AscendingOrder) { +// while(i < list.size() and value.first > list.at(i).first) { +// ++i; +// } +// }else{ +// while(i < list.size() and value.first < list.at(i).first) { +// ++i; +// } +// } +// list.insert(i, value); +// } + + // Can't use template class for QString because >,< use unicode code for sorting + // which is not what a human would expect when sorting strings. + static void insertSortString(QList > &list, QPair value, Qt::SortOrder sortOrder); + + static float getPluginVersion(QString filePath); + + // Take a number of seconds and return an user-friendly + // time duration like "1d 2h 10m". + static QString userFriendlyDuration(qlonglong seconds); + + static QString userFriendlyUnit(double count, unsigned int decimal, double factor = 1000); + + static QString removeNewLine(const QString &text); + static QString removeNewLine(const std::string &text); + static QString removeNewLine(const std::wstring &text); + + static bool getOpenFileName(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QString &file); + static bool getOpenFileNames(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QStringList &files); + + static bool getSaveFileName(QWidget *parent, RshareSettings::enumLastDir type, const QString &caption, const QString &filter, QString &file); +}; + +// Trick to get a portable sleep() function +class SleeperThread : public QThread{ + public: + static void msleep(unsigned long msecs) + { + QThread::msleep(msecs); + } +}; + +#endif diff --git a/retroshare-gui/src/util/printpreview.cpp b/retroshare-gui/src/util/printpreview.cpp new file mode 100644 index 000000000..8e920417e --- /dev/null +++ b/retroshare-gui/src/util/printpreview.cpp @@ -0,0 +1,334 @@ +/**************************************************************************** +** +** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved. +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/ +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.0, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** In addition, as a special exception, Trolltech, as the sole copyright +** holder for Qt Designer, grants users of the Qt/Eclipse Integration +** plug-in the right for the Qt/Eclipse Integration to link to +** functionality provided by Qt Designer and its related libraries. +** +** Trolltech reserves all rights not expressly granted herein. +** +** Trolltech ASA (c) 2007 +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "printpreview.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_WS_MAC +const QString rsrcPath = ":/images/mac"; +#else +const QString rsrcPath = ":/images/win"; +#endif + +static inline int inchesToPixels(float inches, QPaintDevice *device) +{ + return qRound(inches * device->logicalDpiY()); +} + +static inline qreal mmToInches(double mm) +{ + return mm*0.039370147; +} + +class PreviewView : public QAbstractScrollArea +{ + Q_OBJECT +public: + PreviewView(QTextDocument *document, PrintPreview *printPrev); + + inline void updateLayout() { resizeEvent(0); viewport()->update(); } + +public slots: + void zoomIn(); + void zoomOut(); + +protected: + virtual void paintEvent(QPaintEvent *e); + virtual void resizeEvent(QResizeEvent *); + virtual void mousePressEvent(QMouseEvent *e); + virtual void mouseMoveEvent(QMouseEvent *e); + virtual void mouseReleaseEvent(QMouseEvent *e); + +private: + void paintPage(QPainter *painter, int page); + QTextDocument *doc; + qreal scale; + int interPageSpacing; + QPoint mousePressPos; + QPoint scrollBarValuesOnMousePress; + PrintPreview *printPreview; +}; + +PreviewView::PreviewView(QTextDocument *document, PrintPreview *printPrev) + : printPreview(printPrev) +{ + verticalScrollBar()->setSingleStep(20); + horizontalScrollBar()->setSingleStep(20); + + viewport()->setBackgroundRole(QPalette::Dark); + + doc = document; + scale = 1.0; + interPageSpacing = 30; +} + +void PreviewView::zoomIn() +{ + scale += 0.2; + resizeEvent(0); + viewport()->update(); +} + +void PreviewView::zoomOut() +{ + scale -= 0.2; + resizeEvent(0); + viewport()->update(); +} + +void PreviewView::paintEvent(QPaintEvent *) +{ + QPainter p(viewport()); + + p.translate(-horizontalScrollBar()->value(), -verticalScrollBar()->value()); + p.translate(interPageSpacing, interPageSpacing); + + const int pages = doc->pageCount(); + for (int i = 0; i < pages; ++i) { + p.save(); + p.scale(scale, scale); + + paintPage(&p, i); + + p.restore(); + p.translate(0, interPageSpacing + printPreview->paperSize.height() * scale); + } +} + +void PreviewView::paintPage(QPainter *painter, int page) +{ + const QSizeF pgSize = doc->pageSize(); + + QColor col(Qt::black); + + painter->setPen(col); + painter->setBrush(Qt::white); + painter->drawRect(QRectF(QPointF(0, 0), printPreview->paperSize)); + painter->setBrush(Qt::NoBrush); + + col = col.light(); + painter->drawLine(QLineF(printPreview->paperSize.width(), 1, + printPreview->paperSize.width(), printPreview->paperSize.height() - 1)); + + col = col.light(); + painter->drawLine(QLineF(printPreview->paperSize.width(), 2, + printPreview->paperSize.width(), printPreview->paperSize.height() - 2)); + + QRectF docRect(QPointF(0, page * pgSize.height()), pgSize); + QAbstractTextDocumentLayout::PaintContext ctx; + ctx.clip = docRect; + + // don't use the system palette text as default text color, on HP/UX + // for example that's white, and white text on white paper doesn't + // look that nice + ctx.palette.setColor(QPalette::Text, Qt::black); + + painter->translate(0, - page * pgSize.height()); + + painter->translate(printPreview->pageTopLeft); + painter->setClipRect(docRect);//.translated(printPreview->pageTopLeft)); + doc->documentLayout()->draw(painter, ctx); +} + +void PreviewView::resizeEvent(QResizeEvent *) +{ + const QSize viewportSize = viewport()->size(); + + QSize docSize; + docSize.setWidth(qRound(printPreview->paperSize.width() * scale + 2 * interPageSpacing)); + const int pageCount = doc->pageCount(); + docSize.setHeight(qRound(pageCount * printPreview->paperSize.height() * scale + (pageCount + 1) * interPageSpacing)); + + horizontalScrollBar()->setRange(0, docSize.width() - viewportSize.width()); + horizontalScrollBar()->setPageStep(viewportSize.width()); + + verticalScrollBar()->setRange(0, docSize.height() - viewportSize.height()); + verticalScrollBar()->setPageStep(viewportSize.height()); +} + +void PreviewView::mousePressEvent(QMouseEvent *e) +{ + mousePressPos = e->pos(); + scrollBarValuesOnMousePress.rx() = horizontalScrollBar()->value(); + scrollBarValuesOnMousePress.ry() = verticalScrollBar()->value(); + e->accept(); +} + +void PreviewView::mouseMoveEvent(QMouseEvent *e) +{ + if (mousePressPos.isNull()) { + e->ignore(); + return; + } + + horizontalScrollBar()->setValue(scrollBarValuesOnMousePress.x() - e->pos().x() + mousePressPos.x()); + verticalScrollBar()->setValue(scrollBarValuesOnMousePress.y() - e->pos().y() + mousePressPos.y()); + horizontalScrollBar()->update(); + verticalScrollBar()->update(); + e->accept(); +} + +void PreviewView::mouseReleaseEvent(QMouseEvent *e) +{ + mousePressPos = QPoint(); + e->accept(); +} + +PrintPreview::PrintPreview(const QTextDocument *document, QWidget *parent) + : QMainWindow(parent), printer(QPrinter::HighResolution) +{ + setWindowTitle(tr("RetroShare Message - Print Preview")); + + printer.setFullPage(true); + doc = document->clone(); + + view = new PreviewView(doc, this); + setCentralWidget(view); + resize(800, 600); + + doc->setUseDesignMetrics(true); + doc->documentLayout()->setPaintDevice(view->viewport()); + + // add a nice 2 cm margin + const qreal margin = inchesToPixels(mmToInches(20), this); + QTextFrameFormat fmt = doc->rootFrame()->frameFormat(); + fmt.setMargin(margin); + doc->rootFrame()->setFrameFormat(fmt); + + setup(); + + QFont f(doc->defaultFont()); + f.setPointSize(10); + doc->setDefaultFont(f); + + QToolBar *tb = addToolBar(tr("Print")); + tb->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); + + QAction *a; + a = new QAction(QIcon(":/images/textedit/fileprint.png"), tr("&Print..."), this); + a->setShortcut(Qt::CTRL + Qt::Key_P); + connect(a, SIGNAL(triggered()), this, SLOT(print())); + tb->addAction(a); + + a = new QAction(this); + a->setText(tr("Page Setup...")); + connect(a, SIGNAL(triggered()), this, SLOT(pageSetup())); + tb->addAction(a); + + tb->addSeparator(); + + a = new QAction(QIcon(":/images/textedit/zoomin.png"), tr("Zoom In"), this); + connect(a, SIGNAL(triggered()), view, SLOT(zoomIn())); + tb->addAction(a); + + a = new QAction(QIcon(":/images/textedit/zoomout.png"), tr("Zoom Out"), this); + connect(a, SIGNAL(triggered()), view, SLOT(zoomOut())); + tb->addAction(a); + + tb->addSeparator(); + + a = new QAction(this); + a->setText(tr("&Close")); + connect(a, SIGNAL(triggered()), this, SLOT(close())); + tb->addAction(a); + + statusBar()->setSizeGripEnabled(true); +} + +void PrintPreview::setup() +{ + QSizeF page = printer.pageRect().size(); + paperSize = printer.paperRect().size(); + paperSize.rwidth() *= qreal(view->logicalDpiX()) / printer.logicalDpiX(); + paperSize.rheight() *= qreal(view->logicalDpiY()) / printer.logicalDpiY(); + + pageTopLeft = printer.pageRect().topLeft(); + pageTopLeft.rx() *= qreal(view->logicalDpiX()) / printer.logicalDpiX(); + pageTopLeft.ry() *= qreal(view->logicalDpiY()) / printer.logicalDpiY(); + + page.setWidth(page.width() * view->logicalDpiX() / printer.logicalDpiX()); + page.setHeight(page.height() * view->logicalDpiY() / printer.logicalDpiY()); + + // add a nice 2 cm margin + const qreal margin = inchesToPixels(mmToInches(20), this); + QTextFrameFormat fmt = doc->rootFrame()->frameFormat(); + fmt.setMargin(margin); + doc->rootFrame()->setFrameFormat(fmt); + + doc->setPageSize(page); +} + +PrintPreview::~PrintPreview() +{ + delete doc; +} + +void PrintPreview::print() +{ + QPrintDialog *dlg = new QPrintDialog(&printer, this); + if (dlg->exec() == QDialog::Accepted) { + doc->print(&printer); + } + delete dlg; +} + +void PrintPreview::pageSetup() +{ + QPageSetupDialog dlg(&printer, this); + if (dlg.exec() == QDialog::Accepted) { + setup(); + view->updateLayout(); + } +} + +#include "printpreview.moc" diff --git a/retroshare-gui/src/util/printpreview.h b/retroshare-gui/src/util/printpreview.h new file mode 100644 index 000000000..e8f7a769d --- /dev/null +++ b/retroshare-gui/src/util/printpreview.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved. +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of +** this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/ +** +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** In addition, as a special exception, Trolltech gives you certain +** additional rights. These rights are described in the Trolltech GPL +** Exception version 1.0, which can be found at +** http://www.trolltech.com/products/qt/gplexception/ and in the file +** GPL_EXCEPTION.txt in this package. +** +** In addition, as a special exception, Trolltech, as the sole copyright +** holder for Qt Designer, grants users of the Qt/Eclipse Integration +** plug-in the right for the Qt/Eclipse Integration to link to +** functionality provided by Qt Designer and its related libraries. +** +** Trolltech reserves all rights not expressly granted herein. +** +** Trolltech ASA (c) 2007 +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef PRINTPREVIEW_H +#define PRINTPREVIEW_H + +#include +#include +#include +#include + +class PreviewView; +class QTextDocument; + +class PrintPreview : public QMainWindow +{ + Q_OBJECT +public: + PrintPreview(const QTextDocument *document, QWidget *parent); + virtual ~PrintPreview(); + + QSizeF paperSize; + QPointF pageTopLeft; + +private slots: + void print(); + void pageSetup(); + +private: + void setup(); + + QTextDocument *doc; + PreviewView *view; + QPrinter printer; +}; + +#endif // PRINTPREVIEW_H + diff --git a/retroshare-gui/src/util/rsqtutildll.h b/retroshare-gui/src/util/rsqtutildll.h new file mode 100644 index 000000000..80410d3c7 --- /dev/null +++ b/retroshare-gui/src/util/rsqtutildll.h @@ -0,0 +1,37 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RSQTUTILDLL_H +#define RSQTUTILDLL_H + +#include + +#ifdef RSQTUTIL_DLL + #ifdef BUILD_RSQTUTIL_DLL + #define RSQTUTIL_API DLLEXPORT + #else + #define RSQTUTIL_API DLLIMPORT + #endif +#else + #define RSQTUTIL_API +#endif + +#endif //RSQTUTILDLL_H diff --git a/retroshare-gui/src/util/rsutildll.h b/retroshare-gui/src/util/rsutildll.h new file mode 100644 index 000000000..39b4703aa --- /dev/null +++ b/retroshare-gui/src/util/rsutildll.h @@ -0,0 +1,37 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifndef RSUTILDLL_H +#define RSUTILDLL_H + +#include + +#ifdef RSUTIL_DLL + #ifdef BUILD_RSUTIL_DLL + #define RSUTIL_API DLLEXPORT + #else + #define RSUTIL_API DLLIMPORT + #endif +#else + #define RSUTIL_API +#endif + +#endif //RSUTILDLL_H diff --git a/retroshare-gui/src/util/rsversion.cpp b/retroshare-gui/src/util/rsversion.cpp new file mode 100644 index 000000000..428180a24 --- /dev/null +++ b/retroshare-gui/src/util/rsversion.cpp @@ -0,0 +1,30 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include "rsversion.h" + +QString retroshareVersion() { + return QString(GUI_VERSION); +} + +QString retroshareRevision() { + return QString(GUI_REVISION); +} \ No newline at end of file diff --git a/retroshare-gui/src/util/rsversion.h b/retroshare-gui/src/util/rsversion.h new file mode 100644 index 000000000..31d980fc7 --- /dev/null +++ b/retroshare-gui/src/util/rsversion.h @@ -0,0 +1,33 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#define GUI_VERSION "0.5.1" + +#define GUI_REVISION "Revision: " + + +#include + +QString retroshareVersion(); + +QString retroshareRevision(); + diff --git a/retroshare-gui/src/util/rsversion.in b/retroshare-gui/src/util/rsversion.in new file mode 100644 index 000000000..63f2bd6f8 --- /dev/null +++ b/retroshare-gui/src/util/rsversion.in @@ -0,0 +1,34 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 2006,2007 crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#define GUI_VERSION "0.5.1" + +#define GUI_REVISION "Revision: $WCREV$" + + +#include + +QString retroshareVersion(); + +QString retroshareRevision(); + + diff --git a/retroshare-gui/src/util/stringutil.cpp b/retroshare-gui/src/util/stringutil.cpp new file mode 100644 index 000000000..fe0d9d428 --- /dev/null +++ b/retroshare-gui/src/util/stringutil.cpp @@ -0,0 +1,319 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, crypton + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +/* +** \file stringutil.cpp +** \version $Id: stringutil.cpp 2486 2008-04-05 14:43:08Z edmanm $ +** \brief Common string manipulation functions +*/ + +#include "stringutil.h" + + +/** Create a QStringList from the array of C-style strings. */ +QStringList +char_array_to_stringlist(char **arr, int len) +{ + QStringList list; + for (int i = 0; i < len; i++) { + list << QString(arr[i]); + } + return list; +} + +/** Conditionally assigns errmsg to str if str is not null and returns false. + * This is a seemingly pointless function, but it saves some messiness in + * methods whose QString *errmsg parameter is optional. */ +bool +err(QString *str, const QString &errmsg) +{ + if (str) { + *str = errmsg; + } + return false; +} + +/** Ensures all characters in str are in validChars. If a character appears + * in str but not in validChars, it will be removed and the resulting + * string returned. */ +QString +ensure_valid_chars(const QString &str, const QString &validChars) +{ + QString out = str; + for (int i = 0; i < str.length(); i++) { + QChar c = str.at(i); + if (validChars.indexOf(c) < 0) { + out.remove(c); + } + } + return out; +} + +/** Scrubs an email address by replacing "@" with " at " and "." with " dot ". */ +QString +scrub_email_addr(const QString &email) +{ + QString scrubbed = email; + scrubbed = scrubbed.replace("@", " at "); + scrubbed = scrubbed.replace(".", " dot "); + return scrubbed; +} + +/** Wraps str at width characters wide, using sep as the + * word separator (" ", for example), and placing the line ending le at + * the end of each line, except the last. */ +QString +string_wrap(const QString &str, int width, + const QString &sep, const QString &le) +{ + QString wrapped; + int pos, nextsep, wordlen, n; + int seplen = sep.length(); + + if (str.length() < width) { + return str; + } + + pos = 0; + n = width; + while (pos < str.length()) { + /* Get the length of a "word" */ + nextsep = str.indexOf(sep, pos); + if (nextsep < 0) { + nextsep = str.length(); + } + wordlen = nextsep-pos; + + /* Check if there is room for the word on this line */ + if (wordlen > n) { + /* Create a new line */ + wrapped.append(le); + n = width; + } + + /* Add the word to the current line */ + wrapped.append(str.mid(pos, wordlen+seplen)); + n = n - wordlen - seplen; + pos += wordlen + seplen; + } + return wrapped.trimmed(); +} + +/** Encodes the bytes in buf as an uppercase hexadecimal string and + * returns the result. This function is derived from base16_encode() in Tor's + * util.c. See LICENSE for details on Tor's license. */ +QString +base16_encode(const QByteArray &buf) +{ + QString hex; + for (int i = 0; i < buf.size(); i++) { + hex += "0123456789ABCDEF"[((quint8)buf[i]) >> 4]; + hex += "0123456789ABCDEF"[((quint8)buf[i]) & 0xf]; + } + return hex; +} + +/** Given a string str, this function returns a quoted string with all + * '"' and '\' characters escaped with a single '\'. */ +QString +string_escape(const QString &str) +{ + QString out; + out.append("\""); + for (int i = 0; i < str.length(); i++) { + if (str[i] == '\"' || str[i] == '\\') + out.append('\\'); + out.append(str[i]); + } + out.append("\""); + return out; +} + +/** Given a quoted string str, this function returns an unquoted, + * unescaped string. str must start and end with an unescaped quote. */ +QString +string_unescape(const QString &str, bool *ok) +{ + QString out; + + /* The string must start and end with an unescaped dquote */ + if (str.length() < 2 || !str.startsWith("\"") || !str.endsWith("\"") || + (str.endsWith("\\\"") && !str.endsWith("\\\\\""))) { + if (ok) + *ok = false; + return QString(); + } + for (int i = 1; i < str.length()-1; i++) { + if (str[i] == '\\') + i++; + out.append(str[i]); + } + if (ok) + *ok = true; + return out; +} + +/** Parses a series of space-separated key[=value|="value"] tokens from + * str and returns the mappings in a QHash. If str was unable + * to be parsed, ok is set to false. */ +QHash +string_parse_keyvals(const QString &str, bool *ok) +{ + int i, len; + bool tmp_ok; + QHash keyvals; + + i = 0; + len = str.length(); + while (i < len && str[i].isSpace()) + i++; /* Skip initial whitespace */ + while (i < len) { + QString key, val; + + while (i < len && !str[i].isSpace() && str[i] != '=') + key.append(str[i++]); + + if (i < len && str[i] == '=') { + if (++i < len && str[i] == '\"') { + /* The value is wrapped in quotes */ + val.append(str[i]); + while (++i < len) { + val.append(str[i]); + if (str[i] == '\\') { + if (++i == len) + goto error; + val.append(str[i]); + } else if (str[i] == '\"') { + i++; + break; + } + } + val = string_unescape(val, &tmp_ok); + if (!tmp_ok) + goto error; + keyvals.insert(key, val); + } else { + /* The value was not wrapped in quotes */ + while (i < len && !str[i].isSpace()) + val.append(str[i++]); + keyvals.insert(key, val); + } + } else { + /* The key had no value */ + keyvals.insert(key, QString("")); + } + while (i < len && str[i].isSpace()) + i++; + } + if (ok) + *ok = true; + return keyvals; + +error: + if (ok) + *ok = false; + return QHash(); +} + +/** Parses a series of command line arguments from str. If str + * was unable to be parsed, ok is set to false. */ +QStringList +string_parse_arguments(const QString &str, bool *ok) +{ + QStringList args; + int i, len; + bool tmp_ok; + + i = 0; + len = str.length(); + while (i < len && str[i].isSpace()) + i++; /* Skip initial whitespace */ + while (i < len) { + QString arg; + + if (str[i] == '\"') { + /* The value is wrapped in quotes */ + arg.append(str[i]); + while (++i < len) { + arg.append(str[i]); + if (str[i] == '\\') { + if (++i == len) + goto error; + arg.append(str[i]); + } else if (str[i] == '\"') { + i++; + break; + } + } + arg = string_unescape(arg, &tmp_ok); + if (!tmp_ok) + goto error; + args << arg; + } else { + /* The value was not wrapped in quotes */ + while (i < len && !str[i].isSpace()) + arg.append(str[i++]); + args << arg; + } + while (i < len && str[i].isSpace()) + i++; + } + + if (ok) + *ok = true; + return args; + +error: + if (ok) + *ok = false; + return QStringList(); +} + +/** Formats the list of command line arguments in args as a string. + * Arguments that contain ' ', '\', or '"' tokens will be escaped and + * wrapped in double quotes. */ +QString +string_format_arguments(const QStringList &args) +{ + QStringList out; + foreach (QString arg, args) { + if (arg.contains("\"") || arg.contains("\\") || arg.contains(" ")) + out << string_escape(arg); + else + out << arg; + } + return out.join(" "); +} + +/** Returns true if str is a valid hexademical string. Returns false + * otherwise. */ +bool +string_is_hex(const QString &str) +{ + for (int i = 0; i < str.length(); i++) { + char c = str[i].toUpper().toAscii(); + if ((c < 'A' || c > 'F') && (c < '0' || c > '9')) + return false; + } + return true; +} + diff --git a/retroshare-gui/src/util/stringutil.h b/retroshare-gui/src/util/stringutil.h new file mode 100644 index 000000000..eafde6b2d --- /dev/null +++ b/retroshare-gui/src/util/stringutil.h @@ -0,0 +1,88 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2008, crypton + * Copyright (c) 2008, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ +/* +** \file stringutil.h +** \version $Id: stringutil.h 2486 2008-04-05 14:43:08Z edmanm $ +** \brief Common string manipulation functions +*/ + +#ifndef _STRINGUTIL_H +#define _STRINGUTIL_H + +#include +#include + + +/** Creates a QStringList from the array of C strings. */ +QStringList char_array_to_stringlist(char **arr, int len); + +/** Ensures all characters in str are in validChars. If a character appears + * in str but not in validChars, it will be removed and the resulting + * string returned. */ +QString ensure_valid_chars(const QString &str, const QString &validChars); + +/** Scrubs an email address by replacing "@" with " at " and "." with " dot ". */ +QString scrub_email_addr(const QString &email); + +/** Conditionally assigns errmsg to string if str is not null and returns + * false. */ +bool err(QString *str, const QString &errmsg); + +/** Wraps str at width characters wide, using sep as the + * word separator (" ", for example), and placing the line ending le at + * the end of each line, except the last.*/ +QString string_wrap(const QString &str, int width, + const QString &sep, const QString &le); + +/** Encodes the bytes in buf as an uppercase hexadecimal string and + * returns the result. This function is derived from base16_encode() in Tor's + * util.c. See LICENSE for details on Tor's license. */ +QString base16_encode(const QByteArray &buf); + +/** Given a string str, this function returns a quoted string with all + * '"' and '\' characters escaped with a single '\'. */ +QString string_escape(const QString &str); + +/** Given a quoted string str, this function returns an unquoted, + * unescaped string. str must start and end with an unescaped quote. */ +QString string_unescape(const QString &str, bool *ok = 0); + +/** Parses a series of space-separated key[=value|="value"] tokens from + * str and returns the mappings in a QHash. If str was unable + * to be parsed, ok is set to false. */ +QHash string_parse_keyvals(const QString &str, bool *ok = 0); + +/** Parses a series of command line arguments from str. If str + * was unable to be parsed, ok is set to false. */ +QStringList string_parse_arguments(const QString &str, bool *ok = 0); + +/** Formats the list of command line arguments in args as a string. + * Arguments that contain ' ', '\', or '"' tokens will be escaped and wrapped + * in double quotes. */ +QString string_format_arguments(const QStringList &args); + +/** Returns true if str is a valid hexademical string. Returns false + * otherwise. */ +bool string_is_hex(const QString &str); + +#endif + diff --git a/retroshare-gui/src/util/win32.cpp b/retroshare-gui/src/util/win32.cpp new file mode 100644 index 000000000..5d2a87ac6 --- /dev/null +++ b/retroshare-gui/src/util/win32.cpp @@ -0,0 +1,169 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#ifdef WIN32 + +#define WIN32_LEAN_AND_MEAN +#include + +#endif + +#if 0 +#include +#include +#endif + +#include +#include "win32.h" + + +/** Finds the location of the "special" Windows folder using the given CSIDL + * value. If the folder cannot be found, the given default path is used. */ +QString +win32_get_folder_location(int folder, QString defaultPath) +{ +#if 0 + TCHAR path[MAX_PATH+1]; + LPITEMIDLIST idl; + IMalloc *m; + HRESULT result; + + /* Find the location of %PROGRAMFILES% */ + if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, folder, &idl))) { + /* Get the path from the IDL */ + result = SHGetPathFromIDList(idl, path); + SHGetMalloc(&m); + if (m) { + m->Release(); + } + if (SUCCEEDED(result)) { + QT_WA(return QString::fromUtf16((const ushort *)path);, + return QString::fromLocal8Bit((char *)path);) + } + } +#endif + + return defaultPath; +} + +/** Returns the value in keyName at keyLocation. + * Returns an empty QString if the keyName doesn't exist */ +QString +win32_registry_get_key_value(QString keyLocation, QString keyName) +{ +#ifdef WIN32 + HKEY key; + char data[255] = {0}; + DWORD size = sizeof(data); + + /* Open the key for reading (opens new key if it doesn't exist) */ + if (RegOpenKeyExA(HKEY_CURRENT_USER, + qPrintable(keyLocation), + 0L, KEY_READ, &key) == ERROR_SUCCESS) { + + /* Key exists, so read the value into data */ + RegQueryValueExA(key, qPrintable(keyName), + NULL, NULL, (LPBYTE)data, &size); + } + + /* Close anything that was opened */ + RegCloseKey(key); + + return QString(data); +#else + return QString(); +#endif +} + +/** Creates and/or sets the key to the specified value */ +void +win32_registry_set_key_value(QString keyLocation, QString keyName, QString keyValue) +{ +#ifdef WIN32 + HKEY key; + + /* Open the key for writing (opens new key if it doesn't exist */ + if (RegOpenKeyExA(HKEY_CURRENT_USER, + qPrintable(keyLocation), + 0, KEY_WRITE, &key) != ERROR_SUCCESS) { + + /* Key didn't exist, so write the newly opened key */ + RegCreateKeyExA(HKEY_CURRENT_USER, + qPrintable(keyLocation), + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, + &key, NULL); + } + + /* Save the value in the key */ + RegSetValueExA(key, qPrintable(keyName), 0, REG_SZ, + (BYTE *)qPrintable(keyValue), + (DWORD)keyValue.length() + 1); // include null terminator + + /* Close the key */ + RegCloseKey(key); +#endif +} + +/** Removes the key from the registry if it exists */ +void +win32_registry_remove_key(QString keyLocation, QString keyName) +{ +#ifdef WIN32 + HKEY key; + + /* Open the key for writing (opens new key if it doesn't exist */ + if (RegOpenKeyExA(HKEY_CURRENT_USER, + qPrintable(keyLocation), + 0, KEY_SET_VALUE, &key) == ERROR_SUCCESS) { + + /* Key exists so delete it */ + RegDeleteValueA(key, qPrintable(keyName)); + } + + /* Close anything that was opened */ + RegCloseKey(key); +#endif +} + +/** Gets the location of the user's %PROGRAMFILES% folder. */ +QString +win32_program_files_folder() +{ + return win32_get_folder_location( +#if 0 + CSIDL_PROGRAM_FILES, QDir::rootPath() + "\\Program Files"); +#endif + 0, QDir::rootPath() + "\\Program Files"); +} + +/** Gets the location of the user's %APPDATA% folder. */ +QString +win32_app_data_folder() +{ + return win32_get_folder_location( +#if 0 + CSIDL_APPDATA, QDir::homePath() + "\\Application Data"); +#endif + 0, QDir::homePath() + "\\Application Data"); + +} + diff --git a/retroshare-gui/src/util/win32.h b/retroshare-gui/src/util/win32.h new file mode 100644 index 000000000..5b0dcdca3 --- /dev/null +++ b/retroshare-gui/src/util/win32.h @@ -0,0 +1,46 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006-2007, crypton + * Copyright (c) 2006, Matt Edman, Justin Hipple + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#ifndef _WIN32_H +#define _WIN32_H + +#include +#include + +/** Retrieves the location of the user's %PROGRAMFILES% folder. */ +QString win32_program_files_folder(); + +/** Retrieves the location of the user's %APPDATA% folder. */ +QString win32_app_data_folder(); + +/** Returns value of keyName or empty QString if keyName doesn't exist */ +QString win32_registry_get_key_value(QString keyLocation, QString keyName); + +/** Creates and/or sets the key to the specified value */ +void win32_registry_set_key_value(QString keyLocation, QString keyName, QString keyValue); + +/** Removes the key from the registry if it exists */ +void win32_registry_remove_key(QString keyLocation, QString keyName); + +#endif + diff --git a/retroshare-gui/src/version_detail.sh b/retroshare-gui/src/version_detail.sh new file mode 100755 index 000000000..0023bb6bf --- /dev/null +++ b/retroshare-gui/src/version_detail.sh @@ -0,0 +1,53 @@ +#!/bin/bash +#check if we're on *nix system +#write the version.html file + +#don't exit even if a command fails +set +e + +if (ls &> /dev/null); then + echo "Retroshare Gui version : " > gui/help/version.html + if ( /usr/bin/git log -n 1 &> /dev/null); then + #retrieve git information + echo "Git version : $(git status | grep branch | cut -c 3-) $(git log -n 1 | grep commit)" >> gui/help/version.html + fi + if ( /usr/bin/git log -n 1 | grep svn &> /dev/null); then + #retrieve git svn information + echo "Svn version : $(git log -n 1 | grep svn | awk '{print $2}' | head -1)" >> gui/help/version.html + elif ( /usr/bin/git log -n 10 | grep svn &> /dev/null); then + #retrieve git svn information + echo "Svn closest version : $(git log -n 10 | grep svn | awk '{print $2}' | head -1)" >> gui/help/version.html + fi + + if ( /usr/bin/svn info &> /dev/null); then + echo "Svn version : $(svn info | head -n 5 | tail -1)" >> gui/help/version.html + fi + date >> gui/help/version.html + echo "" >> gui/help/version.html + echo "" >> gui/help/version.html +fi + +#write the rsversion.h file +if ( git log -n 1 &> /dev/null); then + #retrieve git information + version="git : $(git status | grep branch | cut -c 6-) $(git log -n 1 | grep commit)" +fi + +if ( git log -n 1 | grep svn &> /dev/null); then + #retrieve git svn information + version="$version svn : $(git log -n 1 | grep svn | awk '{print $2}' | head -1 | sed 's/.*@//')" +elif ( git log -n 10 | grep svn &> /dev/null); then + #retrieve git svn information + version="$version svn closest version : $(git log -n 10 | grep svn | awk '{print $2}' | head -1 | sed 's/.*@//')" +fi + +if ( svn info &> /dev/null); then + version=$(svn info | head -n 5 | tail -1) +fi +if [[ $version != '' ]]; then + version="$version date : $(date +'%T %m.%d.%y')" + echo "Writing version to util/rsversion.h : $version " + sed -i "s/GUI_REVISION .*/GUI_REVISION \"$version\"/g" util/rsversion.h +fi +echo "version_detail.sh scripts finished" +exit 0 diff --git a/retroshare-nogui/src/mingw32make.bat b/retroshare-nogui/src/mingw32make.bat new file mode 100644 index 000000000..eeb87120c --- /dev/null +++ b/retroshare-nogui/src/mingw32make.bat @@ -0,0 +1,13 @@ +set QTDIR=d:\qt\2010.01 +set MINGW=%QTDIR%\mingw + +set PATH=%QTDIR%\qt\bin;%QTDIR%\bin;%MINGW%\bin;%PATH% + +mingw32-make clean + +qmake retroshare-nogui.pro + +mingw32-make + +pause + diff --git a/retroshare-nogui/src/notifytxt.cc b/retroshare-nogui/src/notifytxt.cc new file mode 100644 index 000000000..d7f6b445a --- /dev/null +++ b/retroshare-nogui/src/notifytxt.cc @@ -0,0 +1,213 @@ +/* + * "$Id: notifytxt.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "notifytxt.h" +#include +#include + +#include +#include + +#ifdef WINDOWS_SYS +#include +#include + +#define PASS_MAX 512 + +char *getpass (const char *prompt) +{ + static char getpassbuf [PASS_MAX + 1]; + size_t i = 0; + int c; + + if (prompt) { + fputs (prompt, stderr); + fflush (stderr); + } + + for (;;) { + c = _getch (); + if (c == '\r') { + getpassbuf [i] = '\0'; + break; + } + else if (i < PASS_MAX) { + getpassbuf[i++] = c; + } + + if (i >= PASS_MAX) { + getpassbuf [i] = '\0'; + break; + } + } + + if (prompt) { + fputs ("\r\n", stderr); + fflush (stderr); + } + + return getpassbuf; +} +#endif + +void NotifyTxt::notifyErrorMsg(int list, int type, std::string msg) +{ + return; +} + +void NotifyTxt::notifyChat() +{ + return; +} + +std::string NotifyTxt::askForPassword(const std::string& key_details,bool prev_is_bad) +{ + char *password = getpass(("Please enter GPG password for key "+key_details+": ").c_str()) ; + return std::string(password); +} + + +void NotifyTxt::notifyListChange(int list, int type) +{ + std::cerr << "NotifyTxt::notifyListChange()" << std::endl; + switch(list) + { +// case NOTIFY_LIST_NEIGHBOURS: +// displayNeighbours(); +// break; + case NOTIFY_LIST_FRIENDS: + displayFriends(); + break; + case NOTIFY_LIST_DIRLIST_FRIENDS: + displayDirectories(); + break; + case NOTIFY_LIST_SEARCHLIST: + displaySearch(); + break; + case NOTIFY_LIST_MESSAGELIST: + displayMessages(); + break; + case NOTIFY_LIST_CHANNELLIST: + displayChannels(); + break; + case NOTIFY_LIST_TRANSFERLIST: + displayTransfers(); + break; + default: + break; + } + return; +} + +void NotifyTxt::displayNeighbours() +{ + std::list neighs; + std::list::iterator it; + + rsPeers->getGPGAllList(neighs); + + std::ostringstream out; + for(it = neighs.begin(); it != neighs.end(); it++) + { + RsPeerDetails detail; + rsPeers->getPeerDetails(*it, detail); + + out << "Neighbour: "; + out << detail; + out << std::endl; + } + std::cerr << out.str(); +} + +void NotifyTxt::displayFriends() +{ + std::list ids; + std::list::iterator it; + + rsPeers->getFriendList(ids); + + std::ostringstream out; + for(it = ids.begin(); it != ids.end(); it++) + { + RsPeerDetails detail; + rsPeers->getPeerDetails(*it, detail); + + out << "Neighbour: "; + out << detail; + out << std::endl; + } + std::cerr << out.str(); +} + +void NotifyTxt::displayDirectories() +{ + iface->lockData(); /* Lock Interface */ + + std::ostringstream out; + std::cerr << out.str(); + + iface->unlockData(); /* UnLock Interface */ +} + + +void NotifyTxt::displaySearch() +{ + iface->lockData(); /* Lock Interface */ + + std::ostringstream out; + std::cerr << out.str(); + + iface->unlockData(); /* UnLock Interface */ +} + + +void NotifyTxt::displayMessages() +{ + iface->lockData(); /* Lock Interface */ + iface->unlockData(); /* UnLock Interface */ +} + +void NotifyTxt::displayChannels() +{ + iface->lockData(); /* Lock Interface */ + + std::ostringstream out; + std::cerr << out.str(); + + iface->unlockData(); /* UnLock Interface */ +} + + +void NotifyTxt::displayTransfers() +{ + iface->lockData(); /* Lock Interface */ + + std::ostringstream out; + std::cerr << out.str(); + + iface->unlockData(); /* UnLock Interface */ +} + diff --git a/retroshare-nogui/src/notifytxt.h b/retroshare-nogui/src/notifytxt.h new file mode 100644 index 000000000..274b07892 --- /dev/null +++ b/retroshare-nogui/src/notifytxt.h @@ -0,0 +1,58 @@ +#ifndef RSIFACE_NOTIFY_TXT_H +#define RSIFACE_NOTIFY_TXT_H +/* + * "$Id: notifytxt.h,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include + +#include + +class NotifyTxt: public NotifyBase +{ + public: + NotifyTxt() { return; } + virtual ~NotifyTxt() { return; } + void setRsIface(RsIface *i) { iface = i; } + + virtual void notifyListChange(int list, int type); + virtual void notifyErrorMsg(int list, int sev, std::string msg); + virtual void notifyChat(); + virtual std::string askForPassword(const std::string& key_details,bool prev_is_bad) ; + + private: + + void displayNeighbours(); + void displayFriends(); + void displayDirectories(); + void displaySearch(); + void displayMessages(); + void displayChannels(); + void displayTransfers(); + + RsIface *iface; /* so we can get the data */ +}; + +#endif diff --git a/retroshare-nogui/src/resources/retroshare_win.rc b/retroshare-nogui/src/resources/retroshare_win.rc new file mode 100644 index 000000000..33584d9ad --- /dev/null +++ b/retroshare-nogui/src/resources/retroshare_win.rc @@ -0,0 +1,3 @@ +#include "retroshare_win.rc.h" + +IDI_ICON1 ICON "resources/rs.ico" diff --git a/retroshare-nogui/src/resources/retroshare_win.rc.h b/retroshare-nogui/src/resources/retroshare_win.rc.h new file mode 100644 index 000000000..c2cfcae27 --- /dev/null +++ b/retroshare-nogui/src/resources/retroshare_win.rc.h @@ -0,0 +1,24 @@ +/**************************************************************** + * RetroShare is distributed under the following license: + * + * Copyright (C) 20010, RetroShare Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + + +#define IDI_ICON1 101 + diff --git a/retroshare-nogui/src/resources/rs.ico b/retroshare-nogui/src/resources/rs.ico new file mode 100644 index 000000000..04898b69b Binary files /dev/null and b/retroshare-nogui/src/resources/rs.ico differ diff --git a/retroshare-nogui/src/retroshare-nogui.pro b/retroshare-nogui/src/retroshare-nogui.pro new file mode 100644 index 000000000..03e2227aa --- /dev/null +++ b/retroshare-nogui/src/retroshare-nogui.pro @@ -0,0 +1,103 @@ +TEMPLATE = app +TARGET = retroshare-nogui +CONFIG += bitdht + +################################# Linux ########################################## +linux-* { + #CONFIG += version_detail_bash_script + QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 + + system(which gpgme-config >/dev/null 2>&1) { + INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g") + } else { + message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include) + } + + LIBS += ../../libretroshare/src/lib/libretroshare.a + LIBS += -lssl -lgpgme -lupnp -lgnome-keyring +} + +linux-g++ { + OBJECTS_DIR = temp/linux-g++/obj +} + +linux-g++-64 { + OBJECTS_DIR = temp/linux-g++-64/obj +} + +#################### Cross compilation for windows under Linux ################### + +win32-x-g++ { + OBJECTS_DIR = temp/win32-x-g++/obj + + LIBS += ../../../../lib/win32-x-g++/libretroshare.a + LIBS += ../../../../lib/win32-x-g++/libssl.a + LIBS += ../../../../lib/win32-x-g++/libcrypto.a + LIBS += ../../../../lib/win32-x-g++/libminiupnpc.a + LIBS += ../../../../lib/win32-x-g++/libz.a + LIBS += -L${HOME}/.wine/drive_c/pthreads/lib -lpthreadGCE2 + LIBS += -lws2_32 -luuid -lole32 -liphlpapi -lcrypt32 -gdi32 + LIBS += -lole32 -lwinmm + + RC_FILE = gui/images/retroshare_win.rc + + DEFINES *= WIN32 +} + +#################################### Windows ##################################### + +win32 { + CONFIG += console release + OBJECTS_DIR = temp/obj + RCC_DIR = temp/qrc + UI_DIR = temp/ui + MOC_DIR = temp/moc + + LIBS += ../../libretroshare/src/lib/libretroshare.a + LIBS += -L"../../../../lib" -lssl -lcrypto -lpthreadGC2d -lminiupnpc -lz + LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz +# added after bitdht +# LIBS += -lws2_32 + LIBS += -luuid -lole32 -liphlpapi -lcrypt32-cygwin -lgdi32 + LIBS += -lole32 -lwinmm + + RC_FILE = resources/retroshare_win.rc + + DEFINES *= WINDOWS_SYS +} + +##################################### MacOS ###################################### + +macx { + # ENABLE THIS OPTION FOR Univeral Binary BUILD. + # CONFIG += ppc x86 + + LIBS += -Wl,-search_paths_first +} + +############################## Common stuff ###################################### + +# bitdht config +bitdht { + LIBS += ../../libbitdht/src/lib/libbitdht.a +} + +win32 { +# must be added after bitdht + LIBS += -lws2_32 +} + +DEPENDPATH += ../../libretroshare/src + +INCLUDEPATH += . ../../libretroshare/src + +# Input +HEADERS += notifytxt.h +SOURCES += notifytxt.cc \ + retroshare.cc + + + + + + diff --git a/retroshare-nogui/src/retroshare.cc b/retroshare-nogui/src/retroshare.cc new file mode 100644 index 000000000..183e28fd4 --- /dev/null +++ b/retroshare-nogui/src/retroshare.cc @@ -0,0 +1,145 @@ + +/* + * "$Id: retroshare.cc,v 1.4 2007-04-21 19:08:51 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include /* definition of iface */ +#include /* definition of iface */ + +#include "notifytxt.h" + +#include +#ifdef WINDOWS_SYS +#include +#endif + + +/* Basic instructions for running libretroshare as background thread. + * ******************************************************************* * + * This allows your program to communicate with authenticated peers. + * + * libretroshare's interfaces are defined in libretroshare/src/rsiface. + * This should be the only headers that you need to include. + * + * The startup routine's are defined in rsiface.h + */ + +int main(int argc, char **argv) +{ + /* Retroshare startup is configured using an RsInit object. + * This is an opaque class, which the user cannot directly tweak + * If you want to peek at whats happening underneath look in + * libretroshare/src/rsserver/p3face-startup.cc + * + * You create it with InitRsConfig(), and delete with CleanupRsConfig() + * InitRetroshare(argv, argc, config) parses the command line options, + * and initialises the config paths. + * + * *** There are several functions that I should add to modify + * **** the config the moment these can only be set via the commandline + * - RsConfigDirectory(...) is probably the most useful. + * - RsConfigNetAddr(...) for setting port, etc. + * - RsConfigOutput(...) for logging and debugging. + * + * Next you need to worry about loading your certificate, or making + * a new one: + * + * RsGenerateCertificate(...) To create a new key, certificate + * LoadPassword(...) set password for existing certificate. + **/ + + RsInit::InitRsConfig(); + int initResult = RsInit::InitRetroShare(argc, argv); + + if (initResult < 0) { + /* Error occured */ + switch (initResult) { + case RS_INIT_AUTH_FAILED: + std::cerr << "RsInit::InitRetroShare AuthGPG::InitAuth failed" << std::endl; + break; + default: + /* Unexpected return code */ + std::cerr << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl; + break; + } + return 1; + } + + /* load password should be called at this point: LoadPassword() + * otherwise loaded from commandline. + */ + + + /* Now setup the libretroshare interface objs + * You will need to create you own NotifyXXX class + * if you want to receive notifications of events */ + + NotifyTxt *notify = new NotifyTxt(); + RsIface *iface = createRsIface(*notify); + RsControl *rsServer = createRsControl(*iface, *notify); + rsicontrol = rsServer ; + + notify->setRsIface(iface); + + std::string preferredId, gpgId, gpgName, gpgEmail, sslName; + RsInit::getPreferedAccountId(preferredId); + + if (RsInit::getAccountDetails(preferredId, gpgId, gpgName, gpgEmail, sslName)) + { + RsInit::SelectGPGAccount(gpgId); + } + + /* Key + Certificate are loaded into libretroshare */ + + std::string error_string ; + int retVal = RsInit::LockAndLoadCertificates(false,error_string); + switch(retVal) + { + case 0: break; + case 1: std::cerr << "Error: another instance of retroshare is already using this profile" << std::endl; + return 1; + case 2: std::cerr << "An unexpected error occurred while locking the profile" << std::endl; + return 1; + case 3: std::cerr << "An error occurred while login with the profile" << std::endl; + return 1; + default: std::cerr << "Main: Unexpected switch value " << retVal << std::endl; + return 1; + } + + /* Start-up libretroshare server threads */ + rsServer -> StartupRetroShare(); + + /* pass control to the GUI */ + while(1) + { + std::cerr << "GUI Tick()" << std::endl; +#ifndef WINDOWS_SYS + sleep(1); +#else + Sleep(1000); +#endif + } + return 1; +}